vite-plugin-mock-dev-server 1.6.1 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -892
- package/dist/chunk-FND5XIG2.cjs +73 -0
- package/dist/chunk-S76FMTCD.cjs +911 -0
- package/dist/chunk-TTKDHWOT.js +911 -0
- package/dist/chunk-VMBOC7DG.js +73 -0
- package/dist/helper.cjs +10 -0
- package/dist/helper.d.cts +87 -0
- package/dist/helper.d.ts +87 -0
- package/dist/helper.js +10 -0
- package/dist/index.cjs +365 -1390
- package/dist/index.d.cts +20 -728
- package/dist/index.d.ts +20 -727
- package/dist/index.js +308 -1290
- package/dist/server.cjs +18 -0
- package/dist/server.d.cts +94 -0
- package/dist/server.d.ts +94 -0
- package/dist/server.js +18 -0
- package/dist/types-D50kW_6z.d.cts +571 -0
- package/dist/types-D50kW_6z.d.ts +571 -0
- package/package.json +34 -32
- package/README.zh-CN.md +0 -943
package/dist/index.js
CHANGED
|
@@ -1,103 +1,51 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createDefineMock,
|
|
3
|
+
defineMock,
|
|
4
|
+
defineMockData
|
|
5
|
+
} from "./chunk-VMBOC7DG.js";
|
|
6
|
+
import {
|
|
7
|
+
baseMiddleware,
|
|
8
|
+
createLogger,
|
|
9
|
+
debug,
|
|
10
|
+
doesProxyContextMatchUrl,
|
|
11
|
+
ensureProxies,
|
|
12
|
+
logLevels,
|
|
13
|
+
lookupFile,
|
|
14
|
+
mockWebSocket,
|
|
15
|
+
normalizePath,
|
|
16
|
+
recoverRequest,
|
|
17
|
+
sortByValidator,
|
|
18
|
+
transformMockData,
|
|
19
|
+
transformRawData,
|
|
20
|
+
urlParse
|
|
21
|
+
} from "./chunk-TTKDHWOT.js";
|
|
22
|
+
|
|
1
23
|
// src/plugin.ts
|
|
2
|
-
import
|
|
3
|
-
import { toArray as toArray5 } from "@pengzhanbo/utils";
|
|
24
|
+
import { toArray as toArray4 } from "@pengzhanbo/utils";
|
|
4
25
|
|
|
5
|
-
// src/build.ts
|
|
6
|
-
import
|
|
26
|
+
// src/core/build.ts
|
|
27
|
+
import fs2 from "node:fs";
|
|
7
28
|
import fsp2 from "node:fs/promises";
|
|
8
|
-
import
|
|
9
|
-
import
|
|
29
|
+
import path2 from "node:path";
|
|
30
|
+
import process2 from "node:process";
|
|
10
31
|
import { toArray } from "@pengzhanbo/utils";
|
|
11
32
|
import fg from "fast-glob";
|
|
12
33
|
import isCore from "is-core-module";
|
|
13
34
|
import { createFilter } from "@rollup/pluginutils";
|
|
14
35
|
import c from "picocolors";
|
|
15
36
|
|
|
16
|
-
// src/compiler.ts
|
|
17
|
-
import
|
|
18
|
-
import
|
|
19
|
-
import path2 from "node:path";
|
|
37
|
+
// src/core/compiler.ts
|
|
38
|
+
import fs, { promises as fsp } from "node:fs";
|
|
39
|
+
import path from "node:path";
|
|
20
40
|
import { pathToFileURL } from "node:url";
|
|
21
41
|
import process from "node:process";
|
|
22
42
|
import { build } from "esbuild";
|
|
23
43
|
import JSON5 from "json5";
|
|
24
|
-
|
|
25
|
-
// src/utils.ts
|
|
26
|
-
import fs from "node:fs";
|
|
27
|
-
import path from "node:path";
|
|
28
|
-
import { parse as queryParse } from "node:querystring";
|
|
29
|
-
import { URL as URL2, fileURLToPath } from "node:url";
|
|
30
|
-
import os from "node:os";
|
|
31
|
-
import Debug from "debug";
|
|
32
|
-
import { match } from "path-to-regexp";
|
|
33
|
-
function isStream(stream) {
|
|
34
|
-
return stream !== null && typeof stream === "object" && typeof stream.pipe === "function";
|
|
35
|
-
}
|
|
36
|
-
function isReadableStream(stream) {
|
|
37
|
-
return isStream(stream) && stream.readable !== false && typeof stream._read === "function" && typeof stream._readableState === "object";
|
|
38
|
-
}
|
|
39
|
-
function getDirname(importMetaUrl) {
|
|
40
|
-
return path.dirname(fileURLToPath(importMetaUrl));
|
|
41
|
-
}
|
|
42
|
-
var debug = Debug("vite:mock-dev-server");
|
|
43
|
-
function lookupFile(dir, formats, options) {
|
|
44
|
-
for (const format of formats) {
|
|
45
|
-
const fullPath = path.join(dir, format);
|
|
46
|
-
if (fs.existsSync(fullPath) && fs.statSync(fullPath).isFile()) {
|
|
47
|
-
const result = (options == null ? void 0 : options.pathOnly) ? fullPath : fs.readFileSync(fullPath, "utf-8");
|
|
48
|
-
if (!(options == null ? void 0 : options.predicate) || options.predicate(result))
|
|
49
|
-
return result;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
const parentDir = path.dirname(dir);
|
|
53
|
-
if (parentDir !== dir && (!(options == null ? void 0 : options.rootDir) || parentDir.startsWith(options == null ? void 0 : options.rootDir))) {
|
|
54
|
-
return lookupFile(parentDir, formats, options);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
function ensureProxies(serverProxy = {}) {
|
|
58
|
-
const httpProxies = [];
|
|
59
|
-
const wsProxies = [];
|
|
60
|
-
Object.keys(serverProxy).forEach((key) => {
|
|
61
|
-
var _a, _b;
|
|
62
|
-
const value = serverProxy[key];
|
|
63
|
-
if (typeof value === "string" || !value.ws && !((_a = value.target) == null ? void 0 : _a.toString().startsWith("ws:")) && !((_b = value.target) == null ? void 0 : _b.toString().startsWith("wss:"))) {
|
|
64
|
-
httpProxies.push(key);
|
|
65
|
-
} else {
|
|
66
|
-
wsProxies.push(key);
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
return { httpProxies, wsProxies };
|
|
70
|
-
}
|
|
71
|
-
function doesProxyContextMatchUrl(context, url) {
|
|
72
|
-
return context[0] === "^" && new RegExp(context).test(url) || url.startsWith(context);
|
|
73
|
-
}
|
|
74
|
-
function parseParams(pattern, url) {
|
|
75
|
-
const urlMatch = match(pattern, { decode: decodeURIComponent })(url) || {
|
|
76
|
-
params: {}
|
|
77
|
-
};
|
|
78
|
-
return urlMatch.params || {};
|
|
79
|
-
}
|
|
80
|
-
function urlParse(input) {
|
|
81
|
-
const url = new URL2(input, "http://example.com");
|
|
82
|
-
const pathname = decodeURIComponent(url.pathname);
|
|
83
|
-
const query = queryParse(url.search.replace(/^\?/, ""));
|
|
84
|
-
return { pathname, query };
|
|
85
|
-
}
|
|
86
|
-
var windowsSlashRE = /\\/g;
|
|
87
|
-
var isWindows = os.platform() === "win32";
|
|
88
|
-
function slash(p) {
|
|
89
|
-
return p.replace(windowsSlashRE, "/");
|
|
90
|
-
}
|
|
91
|
-
function normalizePath(id) {
|
|
92
|
-
return path.posix.normalize(isWindows ? slash(id) : id);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// src/compiler.ts
|
|
96
44
|
var externalizeDeps = {
|
|
97
45
|
name: "externalize-deps",
|
|
98
46
|
setup(build2) {
|
|
99
47
|
build2.onResolve({ filter: /.*/ }, ({ path: id }) => {
|
|
100
|
-
if (id[0] !== "." && !
|
|
48
|
+
if (id[0] !== "." && !path.isAbsolute(id))
|
|
101
49
|
return { external: true };
|
|
102
50
|
});
|
|
103
51
|
}
|
|
@@ -105,8 +53,8 @@ var externalizeDeps = {
|
|
|
105
53
|
var json5Loader = {
|
|
106
54
|
name: "json5-loader",
|
|
107
55
|
setup(build2) {
|
|
108
|
-
build2.onLoad({ filter: /\.json5$/ }, async ({ path:
|
|
109
|
-
const content = await fsp.readFile(
|
|
56
|
+
build2.onLoad({ filter: /\.json5$/ }, async ({ path: path3 }) => {
|
|
57
|
+
const content = await fsp.readFile(path3, "utf-8");
|
|
110
58
|
return {
|
|
111
59
|
contents: `export default ${JSON.stringify(JSON5.parse(content))}`,
|
|
112
60
|
loader: "js"
|
|
@@ -117,8 +65,8 @@ var json5Loader = {
|
|
|
117
65
|
var jsonLoader = {
|
|
118
66
|
name: "json-loader",
|
|
119
67
|
setup(build2) {
|
|
120
|
-
build2.onLoad({ filter: /\.json$/ }, async ({ path:
|
|
121
|
-
const content = await fsp.readFile(
|
|
68
|
+
build2.onLoad({ filter: /\.json$/ }, async ({ path: path3 }) => {
|
|
69
|
+
const content = await fsp.readFile(path3, "utf-8");
|
|
122
70
|
return {
|
|
123
71
|
contents: `export default ${content}`,
|
|
124
72
|
loader: "js"
|
|
@@ -126,6 +74,20 @@ var jsonLoader = {
|
|
|
126
74
|
});
|
|
127
75
|
}
|
|
128
76
|
};
|
|
77
|
+
var renamePlugin = {
|
|
78
|
+
name: "rename-plugin",
|
|
79
|
+
setup(build2) {
|
|
80
|
+
build2.onResolve({ filter: /.*/ }, ({ path: id }) => {
|
|
81
|
+
if (id === "vite-plugin-mock-dev-server") {
|
|
82
|
+
return {
|
|
83
|
+
path: "vite-plugin-mock-dev-server/helper",
|
|
84
|
+
external: true
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
};
|
|
129
91
|
function aliasPlugin(alias) {
|
|
130
92
|
return {
|
|
131
93
|
name: "alias-plugin",
|
|
@@ -158,215 +120,107 @@ function aliasMatches(pattern, importee) {
|
|
|
158
120
|
return importee.startsWith(`${pattern}/`);
|
|
159
121
|
}
|
|
160
122
|
async function transformWithEsbuild(entryPoint, options) {
|
|
161
|
-
var _a;
|
|
162
123
|
const { isESM = true, define, alias, cwd = process.cwd() } = options;
|
|
124
|
+
const filepath = path.resolve(cwd, entryPoint);
|
|
125
|
+
const filename = path.basename(entryPoint);
|
|
126
|
+
const dirname = path.dirname(filepath);
|
|
163
127
|
try {
|
|
164
128
|
const result = await build({
|
|
165
129
|
entryPoints: [entryPoint],
|
|
166
130
|
outfile: "out.js",
|
|
167
131
|
write: false,
|
|
168
|
-
target: ["
|
|
132
|
+
target: ["node18"],
|
|
169
133
|
platform: "node",
|
|
170
134
|
bundle: true,
|
|
171
135
|
metafile: true,
|
|
172
136
|
format: isESM ? "esm" : "cjs",
|
|
173
|
-
define
|
|
174
|
-
|
|
137
|
+
define: {
|
|
138
|
+
...define,
|
|
139
|
+
__dirname: JSON.stringify(dirname),
|
|
140
|
+
__filename: JSON.stringify(filename),
|
|
141
|
+
...isESM ? {} : { "import.meta.url": JSON.stringify(pathToFileURL(filepath)) }
|
|
142
|
+
},
|
|
143
|
+
plugins: [aliasPlugin(alias), renamePlugin, externalizeDeps, jsonLoader, json5Loader],
|
|
175
144
|
absWorkingDir: cwd
|
|
176
145
|
});
|
|
177
146
|
return {
|
|
178
147
|
code: result.outputFiles[0].text,
|
|
179
|
-
deps:
|
|
148
|
+
deps: result.metafile?.inputs || {}
|
|
180
149
|
};
|
|
181
150
|
} catch (e) {
|
|
182
151
|
console.error(e);
|
|
183
152
|
}
|
|
184
153
|
return { code: "", deps: {} };
|
|
185
154
|
}
|
|
186
|
-
var _dirname = getDirname(import.meta.url);
|
|
187
|
-
var _require = createRequire(_dirname);
|
|
188
155
|
async function loadFromCode({
|
|
189
156
|
filepath,
|
|
190
157
|
code,
|
|
191
158
|
isESM,
|
|
192
159
|
cwd
|
|
193
160
|
}) {
|
|
194
|
-
filepath =
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
161
|
+
filepath = path.resolve(cwd, filepath);
|
|
162
|
+
const ext = isESM ? ".mjs" : ".cjs";
|
|
163
|
+
const filepathTmp = `${filepath}.timestamp-${Date.now()}${ext}`;
|
|
164
|
+
const file = pathToFileURL(filepathTmp).toString();
|
|
165
|
+
await fsp.writeFile(filepathTmp, code, "utf8");
|
|
166
|
+
try {
|
|
167
|
+
const mod = await import(file);
|
|
168
|
+
return mod.default || mod;
|
|
169
|
+
} finally {
|
|
200
170
|
try {
|
|
201
|
-
|
|
202
|
-
}
|
|
203
|
-
try {
|
|
204
|
-
fs2.unlinkSync(fileNameTmp);
|
|
205
|
-
} catch {
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
} else {
|
|
209
|
-
const extension = path2.extname(filepath);
|
|
210
|
-
const realFileName = fs2.realpathSync(filepath);
|
|
211
|
-
const loaderExt = extension in _require.extensions ? extension : ".js";
|
|
212
|
-
const defaultLoader = _require.extensions[loaderExt];
|
|
213
|
-
_require.extensions[loaderExt] = (module, filename) => {
|
|
214
|
-
if (filename === realFileName) {
|
|
215
|
-
;
|
|
216
|
-
module._compile(code, filename);
|
|
217
|
-
} else {
|
|
218
|
-
defaultLoader(module, filename);
|
|
219
|
-
}
|
|
220
|
-
};
|
|
221
|
-
delete _require.cache[_require.resolve(filepath)];
|
|
222
|
-
const raw = _require(filepath);
|
|
223
|
-
_require.extensions[loaderExt] = defaultLoader;
|
|
224
|
-
return raw.__esModule ? raw : { default: raw };
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// src/define.ts
|
|
229
|
-
import process2 from "node:process";
|
|
230
|
-
function viteDefine(config) {
|
|
231
|
-
const processNodeEnv = {};
|
|
232
|
-
const nodeEnv = process2.env.NODE_ENV || config.mode;
|
|
233
|
-
Object.assign(processNodeEnv, {
|
|
234
|
-
"process.env.NODE_ENV": JSON.stringify(nodeEnv),
|
|
235
|
-
"global.process.env.NODE_ENV": JSON.stringify(nodeEnv),
|
|
236
|
-
"globalThis.process.env.NODE_ENV": JSON.stringify(nodeEnv)
|
|
237
|
-
});
|
|
238
|
-
const userDefine = {};
|
|
239
|
-
const userDefineEnv = {};
|
|
240
|
-
for (const key in config.define) {
|
|
241
|
-
const val = config.define[key];
|
|
242
|
-
const isMetaEnv = key.startsWith("import.meta.env.");
|
|
243
|
-
if (typeof val === "string") {
|
|
244
|
-
if (canJsonParse(val)) {
|
|
245
|
-
userDefine[key] = val;
|
|
246
|
-
if (isMetaEnv)
|
|
247
|
-
userDefineEnv[key.slice(16)] = val;
|
|
248
|
-
}
|
|
249
|
-
} else {
|
|
250
|
-
userDefine[key] = handleDefineValue(val);
|
|
251
|
-
if (isMetaEnv)
|
|
252
|
-
userDefineEnv[key.slice(16)] = val;
|
|
171
|
+
fs.unlinkSync(filepathTmp);
|
|
172
|
+
} catch {
|
|
253
173
|
}
|
|
254
174
|
}
|
|
255
|
-
const importMetaKeys = {};
|
|
256
|
-
const importMetaEnvKeys = {};
|
|
257
|
-
const importMetaFallbackKeys = {};
|
|
258
|
-
importMetaKeys["import.meta.hot"] = `undefined`;
|
|
259
|
-
for (const key in config.env) {
|
|
260
|
-
const val = JSON.stringify(config.env[key]);
|
|
261
|
-
importMetaKeys[`import.meta.env.${key}`] = val;
|
|
262
|
-
importMetaEnvKeys[key] = val;
|
|
263
|
-
}
|
|
264
|
-
importMetaFallbackKeys["import.meta.env"] = `undefined`;
|
|
265
|
-
const define = {
|
|
266
|
-
...processNodeEnv,
|
|
267
|
-
...importMetaKeys,
|
|
268
|
-
...userDefine,
|
|
269
|
-
...importMetaFallbackKeys
|
|
270
|
-
};
|
|
271
|
-
if ("import.meta.env" in define) {
|
|
272
|
-
define["import.meta.env"] = serializeDefine({
|
|
273
|
-
...importMetaEnvKeys,
|
|
274
|
-
...userDefineEnv
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
return define;
|
|
278
|
-
}
|
|
279
|
-
function serializeDefine(define) {
|
|
280
|
-
let res = `{`;
|
|
281
|
-
const keys = Object.keys(define);
|
|
282
|
-
for (let i = 0; i < keys.length; i++) {
|
|
283
|
-
const key = keys[i];
|
|
284
|
-
const val = define[key];
|
|
285
|
-
res += `${JSON.stringify(key)}: ${handleDefineValue(val)}`;
|
|
286
|
-
if (i !== keys.length - 1)
|
|
287
|
-
res += `, `;
|
|
288
|
-
}
|
|
289
|
-
return `${res}}`;
|
|
290
|
-
}
|
|
291
|
-
function handleDefineValue(value) {
|
|
292
|
-
if (typeof value === "undefined")
|
|
293
|
-
return "undefined";
|
|
294
|
-
if (typeof value === "string")
|
|
295
|
-
return value;
|
|
296
|
-
return JSON.stringify(value);
|
|
297
|
-
}
|
|
298
|
-
function canJsonParse(value) {
|
|
299
|
-
try {
|
|
300
|
-
JSON.parse(value);
|
|
301
|
-
return true;
|
|
302
|
-
} catch {
|
|
303
|
-
return false;
|
|
304
|
-
}
|
|
305
175
|
}
|
|
306
176
|
|
|
307
|
-
// src/build.ts
|
|
308
|
-
|
|
309
|
-
var packageVersion = true ? "1.6.1" : "latest";
|
|
310
|
-
async function generateMockServer(ctx, config, options) {
|
|
177
|
+
// src/core/build.ts
|
|
178
|
+
async function generateMockServer(ctx, options) {
|
|
311
179
|
const include = toArray(options.include);
|
|
312
180
|
const exclude = toArray(options.exclude);
|
|
313
|
-
const
|
|
314
|
-
const cwd = options.cwd || process3.cwd();
|
|
315
|
-
const { httpProxies } = ensureProxies(config.server.proxy || {});
|
|
316
|
-
httpProxies.push(...toArray(options.prefix));
|
|
317
|
-
const wsProxies = toArray(options.wsPrefix);
|
|
181
|
+
const cwd = options.cwd || process2.cwd();
|
|
318
182
|
let pkg = {};
|
|
319
183
|
try {
|
|
320
|
-
const pkgStr = lookupFile(
|
|
184
|
+
const pkgStr = lookupFile(options.context, ["package.json"]);
|
|
321
185
|
if (pkgStr)
|
|
322
186
|
pkg = JSON.parse(pkgStr);
|
|
323
187
|
} catch {
|
|
324
188
|
}
|
|
325
189
|
const outputDir = options.build.dist;
|
|
326
190
|
const content = await generateMockEntryCode(cwd, include, exclude);
|
|
327
|
-
const mockEntry =
|
|
191
|
+
const mockEntry = path2.join(cwd, `mock-data-${Date.now()}.js`);
|
|
328
192
|
await fsp2.writeFile(mockEntry, content, "utf-8");
|
|
329
|
-
const { code, deps } = await transformWithEsbuild(mockEntry,
|
|
330
|
-
|
|
331
|
-
alias: config.resolve.alias
|
|
332
|
-
});
|
|
333
|
-
const mockDeps = getMockDependencies(deps, config.resolve.alias);
|
|
193
|
+
const { code, deps } = await transformWithEsbuild(mockEntry, options);
|
|
194
|
+
const mockDeps = getMockDependencies(deps, options.alias);
|
|
334
195
|
await fsp2.unlink(mockEntry);
|
|
335
196
|
const outputList = [
|
|
336
197
|
{
|
|
337
|
-
filename:
|
|
198
|
+
filename: path2.join(outputDir, "mock-data.js"),
|
|
338
199
|
source: code
|
|
339
200
|
},
|
|
340
201
|
{
|
|
341
|
-
filename:
|
|
342
|
-
source: generatorServerEntryCode(
|
|
343
|
-
httpProxies,
|
|
344
|
-
wsProxies,
|
|
345
|
-
options.cookiesOptions,
|
|
346
|
-
options.bodyParserOptions,
|
|
347
|
-
options.priority,
|
|
348
|
-
options.build
|
|
349
|
-
)
|
|
202
|
+
filename: path2.join(outputDir, "index.js"),
|
|
203
|
+
source: generatorServerEntryCode(options)
|
|
350
204
|
},
|
|
351
205
|
{
|
|
352
|
-
filename:
|
|
206
|
+
filename: path2.join(outputDir, "package.json"),
|
|
353
207
|
source: generatePackageJson(pkg, mockDeps)
|
|
354
208
|
}
|
|
355
209
|
];
|
|
356
210
|
try {
|
|
357
|
-
if (
|
|
211
|
+
if (path2.isAbsolute(outputDir)) {
|
|
358
212
|
for (const { filename } of outputList) {
|
|
359
|
-
if (
|
|
213
|
+
if (fs2.existsSync(filename))
|
|
360
214
|
await fsp2.rm(filename);
|
|
361
215
|
}
|
|
362
|
-
|
|
216
|
+
options.logger.info(`${c.green("\u2713")} generate mock server in ${c.cyan(outputDir)}`);
|
|
363
217
|
for (const { filename, source } of outputList) {
|
|
364
|
-
|
|
218
|
+
fs2.mkdirSync(path2.dirname(filename), { recursive: true });
|
|
365
219
|
await fsp2.writeFile(filename, source, "utf-8");
|
|
366
220
|
const sourceSize = (source.length / 1024).toFixed(2);
|
|
367
|
-
const name =
|
|
221
|
+
const name = path2.relative(outputDir, filename);
|
|
368
222
|
const space = name.length < 30 ? " ".repeat(30 - name.length) : "";
|
|
369
|
-
|
|
223
|
+
options.logger.info(` ${c.green(name)}${space}${c.bold(c.dim(`${sourceSize} kB`))}`);
|
|
370
224
|
}
|
|
371
225
|
} else {
|
|
372
226
|
for (const { filename, source } of outputList) {
|
|
@@ -383,17 +237,25 @@ async function generateMockServer(ctx, config, options) {
|
|
|
383
237
|
}
|
|
384
238
|
function getMockDependencies(deps, alias) {
|
|
385
239
|
const list = /* @__PURE__ */ new Set();
|
|
386
|
-
const excludeDeps = [
|
|
240
|
+
const excludeDeps = ["vite-plugin-mock-dev-server", "connect", "cors"];
|
|
387
241
|
const isAlias = (p) => alias.find(({ find }) => aliasMatches(find, p));
|
|
388
242
|
Object.keys(deps).forEach((mPath) => {
|
|
389
243
|
const imports = deps[mPath].imports.filter((_) => _.external && !_.path.startsWith("<define:") && !isAlias(_.path)).map((_) => _.path);
|
|
390
244
|
imports.forEach((dep) => {
|
|
391
|
-
|
|
392
|
-
|
|
245
|
+
const name = normalizePackageName(dep);
|
|
246
|
+
if (!excludeDeps.includes(name) && !isCore(name))
|
|
247
|
+
list.add(name);
|
|
393
248
|
});
|
|
394
249
|
});
|
|
395
250
|
return Array.from(list);
|
|
396
251
|
}
|
|
252
|
+
function normalizePackageName(dep) {
|
|
253
|
+
const [scope, name] = dep.split("/");
|
|
254
|
+
if (scope[0] === "@") {
|
|
255
|
+
return `${scope}/${name}`;
|
|
256
|
+
}
|
|
257
|
+
return scope;
|
|
258
|
+
}
|
|
397
259
|
function generatePackageJson(pkg, mockDeps) {
|
|
398
260
|
const { dependencies = {}, devDependencies = {} } = pkg;
|
|
399
261
|
const dependents = { ...dependencies, ...devDependencies };
|
|
@@ -404,9 +266,9 @@ function generatePackageJson(pkg, mockDeps) {
|
|
|
404
266
|
start: "node index.js"
|
|
405
267
|
},
|
|
406
268
|
dependencies: {
|
|
407
|
-
|
|
408
|
-
"vite-plugin-mock-dev-server": `^${
|
|
409
|
-
|
|
269
|
+
connect: "^3.7.0",
|
|
270
|
+
["vite-plugin-mock-dev-server"]: `^${"1.7.0"}`,
|
|
271
|
+
cors: "^2.8.5"
|
|
410
272
|
},
|
|
411
273
|
pnpm: { peerDependencyRules: { ignoreMissing: ["vite"] } }
|
|
412
274
|
};
|
|
@@ -415,35 +277,37 @@ function generatePackageJson(pkg, mockDeps) {
|
|
|
415
277
|
});
|
|
416
278
|
return JSON.stringify(mockPkg, null, 2);
|
|
417
279
|
}
|
|
418
|
-
function generatorServerEntryCode(
|
|
280
|
+
function generatorServerEntryCode({
|
|
281
|
+
proxies,
|
|
282
|
+
wsProxies,
|
|
283
|
+
cookiesOptions,
|
|
284
|
+
bodyParserOptions,
|
|
285
|
+
priority,
|
|
286
|
+
build: build2
|
|
287
|
+
}) {
|
|
419
288
|
const { serverPort, log } = build2;
|
|
420
289
|
return `import { createServer } from 'node:http';
|
|
421
290
|
import connect from 'connect';
|
|
422
291
|
import corsMiddleware from 'cors';
|
|
423
|
-
import { baseMiddleware, createLogger, mockWebSocket } from 'vite-plugin-mock-dev-server';
|
|
292
|
+
import { baseMiddleware, createLogger, mockWebSocket } from 'vite-plugin-mock-dev-server/server';
|
|
424
293
|
import mockData from './mock-data.js';
|
|
425
294
|
|
|
426
295
|
const app = connect();
|
|
427
296
|
const server = createServer(app);
|
|
428
297
|
const logger = createLogger('mock-server', '${log}');
|
|
429
|
-
const
|
|
298
|
+
const proxies = ${JSON.stringify(proxies)};
|
|
430
299
|
const wsProxies = ${JSON.stringify(wsProxies)};
|
|
431
300
|
const cookiesOptions = ${JSON.stringify(cookiesOptions)};
|
|
432
301
|
const bodyParserOptions = ${JSON.stringify(bodyParserOptions)};
|
|
433
302
|
const priority = ${JSON.stringify(priority)};
|
|
303
|
+
const compiler = { mockData }
|
|
434
304
|
|
|
435
|
-
mockWebSocket({
|
|
436
|
-
loader: { mockData },
|
|
437
|
-
httpServer: server,
|
|
438
|
-
proxies: wsProxies,
|
|
439
|
-
cookiesOptions,
|
|
440
|
-
logger,
|
|
441
|
-
});
|
|
305
|
+
mockWebSocket(compiler, server, { wsProxies, cookiesOptions, logger });
|
|
442
306
|
|
|
443
307
|
app.use(corsMiddleware());
|
|
444
|
-
app.use(baseMiddleware(
|
|
308
|
+
app.use(baseMiddleware(compiler, {
|
|
445
309
|
formidableOptions: { multiples: true },
|
|
446
|
-
proxies
|
|
310
|
+
proxies,
|
|
447
311
|
priority,
|
|
448
312
|
cookiesOptions,
|
|
449
313
|
bodyParserOptions,
|
|
@@ -462,706 +326,44 @@ async function generateMockEntryCode(cwd, include, exclude) {
|
|
|
462
326
|
});
|
|
463
327
|
const mockFiles = includePaths.filter(includeFilter);
|
|
464
328
|
let importers = "";
|
|
465
|
-
|
|
329
|
+
const exporters = [];
|
|
466
330
|
mockFiles.forEach((filepath, index) => {
|
|
467
|
-
const file = normalizePath(
|
|
331
|
+
const file = normalizePath(path2.join(cwd, filepath));
|
|
468
332
|
importers += `import * as m${index} from '${file}';
|
|
469
333
|
`;
|
|
470
|
-
exporters
|
|
334
|
+
exporters.push(`[m${index}, '${filepath}']`);
|
|
471
335
|
});
|
|
472
|
-
return `import { transformMockData } from 'vite-plugin-mock-dev-server';
|
|
336
|
+
return `import { transformMockData, transformRawData } from 'vite-plugin-mock-dev-server/server';
|
|
473
337
|
${importers}
|
|
474
|
-
const exporters = [
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
mockConfig = []
|
|
481
|
-
Object.keys(raw || {}).forEach((key) => {
|
|
482
|
-
Array.isArray(raw[key])
|
|
483
|
-
? mockConfig.push(...raw[key])
|
|
484
|
-
: mockConfig.push(raw[key])
|
|
485
|
-
})
|
|
486
|
-
}
|
|
487
|
-
return mockConfig
|
|
338
|
+
const exporters = [
|
|
339
|
+
${exporters.join(",\n ")}
|
|
340
|
+
];
|
|
341
|
+
const mockList = exporters.map(([mod, filepath]) => {
|
|
342
|
+
const raw = mod.default || mod;
|
|
343
|
+
return transformRawData(raw, filepath);
|
|
488
344
|
});
|
|
489
345
|
export default transformMockData(mockList);`;
|
|
490
346
|
}
|
|
491
347
|
|
|
492
|
-
// src/mockMiddleware.ts
|
|
493
|
-
import { isBoolean as isBoolean2, toArray as toArray4, uniq as uniq2 } from "@pengzhanbo/utils";
|
|
348
|
+
// src/core/mockMiddleware.ts
|
|
494
349
|
import cors from "cors";
|
|
495
|
-
import { pathToRegexp
|
|
496
|
-
import c2 from "picocolors";
|
|
497
|
-
|
|
498
|
-
// src/baseMiddleware.ts
|
|
499
|
-
import { Buffer as Buffer2 } from "node:buffer";
|
|
500
|
-
import {
|
|
501
|
-
isArray as isArray3,
|
|
502
|
-
isEmptyObject as isEmptyObject2,
|
|
503
|
-
isFunction,
|
|
504
|
-
random,
|
|
505
|
-
sleep,
|
|
506
|
-
timestamp
|
|
507
|
-
} from "@pengzhanbo/utils";
|
|
508
|
-
import Cookies from "cookies";
|
|
509
|
-
import HTTP_STATUS from "http-status";
|
|
510
|
-
import * as mime from "mime-types";
|
|
511
|
-
import { pathToRegexp as pathToRegexp2 } from "path-to-regexp";
|
|
512
|
-
import colors from "picocolors";
|
|
350
|
+
import { pathToRegexp } from "path-to-regexp";
|
|
513
351
|
|
|
514
|
-
// src/
|
|
515
|
-
import {
|
|
516
|
-
isArray,
|
|
517
|
-
isEmptyObject,
|
|
518
|
-
isString,
|
|
519
|
-
sortBy,
|
|
520
|
-
uniq
|
|
521
|
-
} from "@pengzhanbo/utils";
|
|
522
|
-
import { parse, pathToRegexp } from "path-to-regexp";
|
|
523
|
-
var tokensCache = {};
|
|
524
|
-
function getTokens(rule) {
|
|
525
|
-
if (tokensCache[rule])
|
|
526
|
-
return tokensCache[rule];
|
|
527
|
-
const tks = parse(rule);
|
|
528
|
-
const tokens = [];
|
|
529
|
-
for (const tk of tks) {
|
|
530
|
-
if (!isString(tk)) {
|
|
531
|
-
tokens.push(tk);
|
|
532
|
-
} else {
|
|
533
|
-
const hasPrefix = tk[0] === "/";
|
|
534
|
-
const subTks = hasPrefix ? tk.slice(1).split("/") : tk.split("/");
|
|
535
|
-
tokens.push(
|
|
536
|
-
`${hasPrefix ? "/" : ""}${subTks[0]}`,
|
|
537
|
-
...subTks.slice(1).map((t) => `/${t}`)
|
|
538
|
-
);
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
tokensCache[rule] = tokens;
|
|
542
|
-
return tokens;
|
|
543
|
-
}
|
|
544
|
-
function getHighest(rules) {
|
|
545
|
-
let weights = rules.map((rule) => getTokens(rule).length);
|
|
546
|
-
weights = weights.length === 0 ? [1] : weights;
|
|
547
|
-
return Math.max(...weights) + 2;
|
|
548
|
-
}
|
|
549
|
-
function sortFn(rule) {
|
|
550
|
-
const tokens = getTokens(rule);
|
|
551
|
-
let w = 0;
|
|
552
|
-
for (let i = 0; i < tokens.length; i++) {
|
|
553
|
-
const token = tokens[i];
|
|
554
|
-
if (!isString(token))
|
|
555
|
-
w += 10 ** (i + 1);
|
|
556
|
-
w += 10 ** (i + 1);
|
|
557
|
-
}
|
|
558
|
-
return w;
|
|
559
|
-
}
|
|
560
|
-
function preSort(rules) {
|
|
561
|
-
let matched = [];
|
|
562
|
-
const preMatch = [];
|
|
563
|
-
for (const rule of rules) {
|
|
564
|
-
const tokens = getTokens(rule);
|
|
565
|
-
const len = tokens.filter((token) => typeof token !== "string").length;
|
|
566
|
-
if (!preMatch[len])
|
|
567
|
-
preMatch[len] = [];
|
|
568
|
-
preMatch[len].push(rule);
|
|
569
|
-
}
|
|
570
|
-
for (const match2 of preMatch.filter((v) => v && v.length > 0))
|
|
571
|
-
matched = [...matched, ...sortBy(match2, sortFn).reverse()];
|
|
572
|
-
return matched;
|
|
573
|
-
}
|
|
574
|
-
function defaultPriority(rules) {
|
|
575
|
-
const highest = getHighest(rules);
|
|
576
|
-
return sortBy(rules, (rule) => {
|
|
577
|
-
const tokens = getTokens(rule);
|
|
578
|
-
const dym = tokens.filter((token) => typeof token !== "string");
|
|
579
|
-
if (dym.length === 0)
|
|
580
|
-
return 0;
|
|
581
|
-
let weight = dym.length;
|
|
582
|
-
let exp = 0;
|
|
583
|
-
for (let i = 0; i < tokens.length; i++) {
|
|
584
|
-
const token = tokens[i];
|
|
585
|
-
const isDynamic = !isString(token);
|
|
586
|
-
const {
|
|
587
|
-
pattern = "",
|
|
588
|
-
modifier,
|
|
589
|
-
prefix,
|
|
590
|
-
name
|
|
591
|
-
} = isDynamic ? token : {};
|
|
592
|
-
const isGlob = pattern && pattern.includes(".*");
|
|
593
|
-
const isSlash = prefix === "/";
|
|
594
|
-
const isNamed = isString(name);
|
|
595
|
-
exp += isDynamic && isSlash ? 1 : 0;
|
|
596
|
-
if (i === tokens.length - 1 && isGlob) {
|
|
597
|
-
weight += 5 * 10 ** (tokens.length === 1 ? highest + 1 : highest);
|
|
598
|
-
} else {
|
|
599
|
-
if (isGlob) {
|
|
600
|
-
weight += 3 * 10 ** (highest - 1);
|
|
601
|
-
} else if (pattern) {
|
|
602
|
-
if (isSlash) {
|
|
603
|
-
weight += (isNamed ? 2 : 1) * 10 ** (exp + 1);
|
|
604
|
-
} else {
|
|
605
|
-
weight -= 1 * 10 ** exp;
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
if (modifier === "+")
|
|
610
|
-
weight += 1 * 10 ** (highest - 1);
|
|
611
|
-
if (modifier === "*")
|
|
612
|
-
weight += 1 * 10 ** (highest - 1) + 1;
|
|
613
|
-
if (modifier === "?")
|
|
614
|
-
weight += 1 * 10 ** (exp + (isSlash ? 1 : 0));
|
|
615
|
-
}
|
|
616
|
-
return weight;
|
|
617
|
-
});
|
|
618
|
-
}
|
|
619
|
-
function matchingWeight(rules, url, priority) {
|
|
620
|
-
let matched = defaultPriority(
|
|
621
|
-
preSort(rules.filter((rule) => pathToRegexp(rule).test(url)))
|
|
622
|
-
);
|
|
623
|
-
const { global = [], special = {} } = priority;
|
|
624
|
-
if (global.length === 0 && isEmptyObject(special) || matched.length === 0)
|
|
625
|
-
return matched;
|
|
626
|
-
const [statics, dynamics] = twoPartMatch(matched);
|
|
627
|
-
const globalMatch = global.filter((rule) => dynamics.includes(rule));
|
|
628
|
-
if (globalMatch.length > 0) {
|
|
629
|
-
matched = uniq([...statics, ...globalMatch, ...dynamics]);
|
|
630
|
-
}
|
|
631
|
-
if (isEmptyObject(special))
|
|
632
|
-
return matched;
|
|
633
|
-
const specialRule = Object.keys(special).filter(
|
|
634
|
-
(rule) => matched.includes(rule)
|
|
635
|
-
)[0];
|
|
636
|
-
if (!specialRule)
|
|
637
|
-
return matched;
|
|
638
|
-
const options = special[specialRule];
|
|
639
|
-
const { rules: lowerRules, when } = isArray(options) ? { rules: options, when: [] } : options;
|
|
640
|
-
if (lowerRules.includes(matched[0])) {
|
|
641
|
-
if (when.length === 0 || when.some((path4) => pathToRegexp(path4).test(url))) {
|
|
642
|
-
matched = uniq([specialRule, ...matched]);
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
return matched;
|
|
646
|
-
}
|
|
647
|
-
function twoPartMatch(rules) {
|
|
648
|
-
const statics = [];
|
|
649
|
-
const dynamics = [];
|
|
650
|
-
for (const rule of rules) {
|
|
651
|
-
const tokens = getTokens(rule);
|
|
652
|
-
const dym = tokens.filter((token) => typeof token !== "string");
|
|
653
|
-
if (dym.length > 0)
|
|
654
|
-
dynamics.push(rule);
|
|
655
|
-
else statics.push(rule);
|
|
656
|
-
}
|
|
657
|
-
return [statics, dynamics];
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
// src/parseReqBody.ts
|
|
661
|
-
import bodyParser from "co-body";
|
|
662
|
-
import formidable from "formidable";
|
|
663
|
-
async function parseReqBody(req, formidableOptions, bodyParserOptions = {}) {
|
|
664
|
-
var _a;
|
|
665
|
-
const method = req.method.toUpperCase();
|
|
666
|
-
if (["GET", "DELETE", "HEAD"].includes(method))
|
|
667
|
-
return void 0;
|
|
668
|
-
const type = ((_a = req.headers["content-type"]) == null ? void 0 : _a.toLocaleLowerCase()) || "";
|
|
669
|
-
const { limit, formLimit, jsonLimit, textLimit, ...rest } = bodyParserOptions;
|
|
670
|
-
try {
|
|
671
|
-
if (type.startsWith("application/json")) {
|
|
672
|
-
return await bodyParser.json(req, {
|
|
673
|
-
limit: jsonLimit || limit,
|
|
674
|
-
...rest
|
|
675
|
-
});
|
|
676
|
-
}
|
|
677
|
-
if (type.startsWith("application/x-www-form-urlencoded")) {
|
|
678
|
-
return await bodyParser.form(req, {
|
|
679
|
-
limit: formLimit || limit,
|
|
680
|
-
...rest
|
|
681
|
-
});
|
|
682
|
-
}
|
|
683
|
-
if (type.startsWith("text/plain")) {
|
|
684
|
-
return await bodyParser.text(req, {
|
|
685
|
-
limit: textLimit || limit,
|
|
686
|
-
...rest
|
|
687
|
-
});
|
|
688
|
-
}
|
|
689
|
-
if (type.startsWith("multipart/form-data"))
|
|
690
|
-
return await parseMultipart(req, formidableOptions);
|
|
691
|
-
} catch (e) {
|
|
692
|
-
console.error(e);
|
|
693
|
-
}
|
|
694
|
-
return void 0;
|
|
695
|
-
}
|
|
696
|
-
async function parseMultipart(req, options) {
|
|
697
|
-
const form = formidable(options);
|
|
698
|
-
return new Promise((resolve, reject) => {
|
|
699
|
-
form.parse(req, (error, fields, files) => {
|
|
700
|
-
if (error) {
|
|
701
|
-
reject(error);
|
|
702
|
-
return;
|
|
703
|
-
}
|
|
704
|
-
resolve({ ...fields, ...files });
|
|
705
|
-
});
|
|
706
|
-
});
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
// src/requestRecovery.ts
|
|
710
|
-
import { Buffer } from "node:buffer";
|
|
711
|
-
var cache = /* @__PURE__ */ new WeakMap();
|
|
712
|
-
function collectRequest(req) {
|
|
713
|
-
const chunks = [];
|
|
714
|
-
req.addListener("data", (chunk) => {
|
|
715
|
-
chunks.push(Buffer.from(chunk));
|
|
716
|
-
});
|
|
717
|
-
req.addListener("end", () => {
|
|
718
|
-
if (chunks.length)
|
|
719
|
-
cache.set(req, Buffer.concat(chunks));
|
|
720
|
-
});
|
|
721
|
-
}
|
|
722
|
-
function recoverRequest(config) {
|
|
723
|
-
if (!config.server)
|
|
724
|
-
return;
|
|
725
|
-
const proxies = config.server.proxy || {};
|
|
726
|
-
Object.keys(proxies).forEach((key) => {
|
|
727
|
-
const target = proxies[key];
|
|
728
|
-
const options = typeof target === "string" ? { target } : target;
|
|
729
|
-
if (options.ws)
|
|
730
|
-
return;
|
|
731
|
-
const { configure, ...rest } = options;
|
|
732
|
-
proxies[key] = {
|
|
733
|
-
...rest,
|
|
734
|
-
configure(proxy, options2) {
|
|
735
|
-
configure == null ? void 0 : configure(proxy, options2);
|
|
736
|
-
proxy.on("proxyReq", (proxyReq, req) => {
|
|
737
|
-
const buffer = cache.get(req);
|
|
738
|
-
if (buffer) {
|
|
739
|
-
cache.delete(req);
|
|
740
|
-
if (!proxyReq.headersSent)
|
|
741
|
-
proxyReq.setHeader("Content-Length", buffer.byteLength);
|
|
742
|
-
if (!proxyReq.writableEnded)
|
|
743
|
-
proxyReq.write(buffer);
|
|
744
|
-
}
|
|
745
|
-
});
|
|
746
|
-
}
|
|
747
|
-
};
|
|
748
|
-
});
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
// src/validator.ts
|
|
752
|
-
import { isArray as isArray2, isObject } from "@pengzhanbo/utils";
|
|
753
|
-
function validate(request, validator) {
|
|
754
|
-
return isObjectSubset(request.headers, validator.headers) && isObjectSubset(request.body, validator.body) && isObjectSubset(request.params, validator.params) && isObjectSubset(request.query, validator.query) && isObjectSubset(request.refererQuery, validator.refererQuery);
|
|
755
|
-
}
|
|
756
|
-
function isObjectSubset(source, target) {
|
|
757
|
-
if (!target)
|
|
758
|
-
return true;
|
|
759
|
-
for (const key in target) {
|
|
760
|
-
if (!isIncluded(source[key], target[key]))
|
|
761
|
-
return false;
|
|
762
|
-
}
|
|
763
|
-
return true;
|
|
764
|
-
}
|
|
765
|
-
function isIncluded(source, target) {
|
|
766
|
-
if (isArray2(source) && isArray2(target)) {
|
|
767
|
-
const seen = /* @__PURE__ */ new Set();
|
|
768
|
-
return target.every(
|
|
769
|
-
(ti) => source.some((si, i) => {
|
|
770
|
-
if (seen.has(i))
|
|
771
|
-
return false;
|
|
772
|
-
const included = isIncluded(si, ti);
|
|
773
|
-
if (included)
|
|
774
|
-
seen.add(i);
|
|
775
|
-
return included;
|
|
776
|
-
})
|
|
777
|
-
);
|
|
778
|
-
}
|
|
779
|
-
if (isObject(source) && isObject(target))
|
|
780
|
-
return isObjectSubset(source, target);
|
|
781
|
-
return Object.is(source, target);
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
// src/baseMiddleware.ts
|
|
785
|
-
function baseMiddleware(mockLoader, {
|
|
786
|
-
formidableOptions = {},
|
|
787
|
-
bodyParserOptions = {},
|
|
788
|
-
proxies,
|
|
789
|
-
cookiesOptions,
|
|
790
|
-
logger,
|
|
791
|
-
priority = {}
|
|
792
|
-
}) {
|
|
793
|
-
return async function(req, res, next) {
|
|
794
|
-
const startTime = timestamp();
|
|
795
|
-
const { query, pathname } = urlParse(req.url);
|
|
796
|
-
if (!pathname || proxies.length === 0 || !proxies.some((context) => doesProxyContextMatchUrl(context, req.url))) {
|
|
797
|
-
return next();
|
|
798
|
-
}
|
|
799
|
-
const mockData = mockLoader.mockData;
|
|
800
|
-
const mockUrls = matchingWeight(Object.keys(mockData), pathname, priority);
|
|
801
|
-
if (mockUrls.length === 0) {
|
|
802
|
-
return next();
|
|
803
|
-
}
|
|
804
|
-
collectRequest(req);
|
|
805
|
-
const { query: refererQuery } = urlParse(req.headers.referer || "");
|
|
806
|
-
const reqBody = await parseReqBody(req, formidableOptions, bodyParserOptions);
|
|
807
|
-
const cookies = new Cookies(req, res, cookiesOptions);
|
|
808
|
-
const getCookie = cookies.get.bind(cookies);
|
|
809
|
-
const method = req.method.toUpperCase();
|
|
810
|
-
let mock;
|
|
811
|
-
let _mockUrl;
|
|
812
|
-
for (const mockUrl of mockUrls) {
|
|
813
|
-
mock = fineMock(mockData[mockUrl], logger, {
|
|
814
|
-
pathname,
|
|
815
|
-
method,
|
|
816
|
-
request: {
|
|
817
|
-
query,
|
|
818
|
-
refererQuery,
|
|
819
|
-
body: reqBody,
|
|
820
|
-
headers: req.headers,
|
|
821
|
-
getCookie
|
|
822
|
-
}
|
|
823
|
-
});
|
|
824
|
-
if (mock) {
|
|
825
|
-
_mockUrl = mockUrl;
|
|
826
|
-
break;
|
|
827
|
-
}
|
|
828
|
-
}
|
|
829
|
-
if (!mock) {
|
|
830
|
-
const matched = mockUrls.map(
|
|
831
|
-
(m) => m === _mockUrl ? colors.underline(colors.bold(m)) : colors.dim(m)
|
|
832
|
-
).join(", ");
|
|
833
|
-
logger.warn(
|
|
834
|
-
`${colors.green(
|
|
835
|
-
pathname
|
|
836
|
-
)} matches ${matched} , but mock data is not found.`
|
|
837
|
-
);
|
|
838
|
-
return next();
|
|
839
|
-
}
|
|
840
|
-
const request = req;
|
|
841
|
-
const response = res;
|
|
842
|
-
request.body = reqBody;
|
|
843
|
-
request.query = query;
|
|
844
|
-
request.refererQuery = refererQuery;
|
|
845
|
-
request.params = parseParams(mock.url, pathname);
|
|
846
|
-
request.getCookie = getCookie;
|
|
847
|
-
response.setCookie = cookies.set.bind(cookies);
|
|
848
|
-
const {
|
|
849
|
-
body,
|
|
850
|
-
delay,
|
|
851
|
-
type = "json",
|
|
852
|
-
response: responseFn,
|
|
853
|
-
status = 200,
|
|
854
|
-
statusText,
|
|
855
|
-
log: logLevel,
|
|
856
|
-
__filepath__: filepath
|
|
857
|
-
} = mock;
|
|
858
|
-
responseStatus(response, status, statusText);
|
|
859
|
-
await provideHeaders(request, response, mock, logger);
|
|
860
|
-
await provideCookies(request, response, mock, logger);
|
|
861
|
-
logger.info(requestLog(request, filepath), logLevel);
|
|
862
|
-
logger.debug(
|
|
863
|
-
`${colors.magenta("DEBUG")} ${colors.underline(
|
|
864
|
-
pathname
|
|
865
|
-
)} matches: [ ${mockUrls.map(
|
|
866
|
-
(m) => m === _mockUrl ? colors.underline(colors.bold(m)) : colors.dim(m)
|
|
867
|
-
).join(", ")} ]
|
|
868
|
-
`
|
|
869
|
-
);
|
|
870
|
-
if (body) {
|
|
871
|
-
try {
|
|
872
|
-
const content = isFunction(body) ? await body(request) : body;
|
|
873
|
-
await realDelay(startTime, delay);
|
|
874
|
-
sendData(response, content, type);
|
|
875
|
-
} catch (e) {
|
|
876
|
-
logger.error(
|
|
877
|
-
`${colors.red(
|
|
878
|
-
`mock error at ${pathname}`
|
|
879
|
-
)}
|
|
880
|
-
${e}
|
|
881
|
-
at body (${colors.underline(filepath)})`,
|
|
882
|
-
logLevel
|
|
883
|
-
);
|
|
884
|
-
responseStatus(response, 500);
|
|
885
|
-
res.end("");
|
|
886
|
-
}
|
|
887
|
-
return;
|
|
888
|
-
}
|
|
889
|
-
if (responseFn) {
|
|
890
|
-
try {
|
|
891
|
-
await realDelay(startTime, delay);
|
|
892
|
-
await responseFn(request, response, next);
|
|
893
|
-
} catch (e) {
|
|
894
|
-
logger.error(
|
|
895
|
-
`${colors.red(
|
|
896
|
-
`mock error at ${pathname}`
|
|
897
|
-
)}
|
|
898
|
-
${e}
|
|
899
|
-
at response (${colors.underline(filepath)})`,
|
|
900
|
-
logLevel
|
|
901
|
-
);
|
|
902
|
-
responseStatus(response, 500);
|
|
903
|
-
res.end("");
|
|
904
|
-
}
|
|
905
|
-
return;
|
|
906
|
-
}
|
|
907
|
-
res.end("");
|
|
908
|
-
};
|
|
909
|
-
}
|
|
910
|
-
function fineMock(mockList, logger, {
|
|
911
|
-
pathname,
|
|
912
|
-
method,
|
|
913
|
-
request
|
|
914
|
-
}) {
|
|
915
|
-
return mockList.find((mock) => {
|
|
916
|
-
if (!pathname || !mock || !mock.url || mock.ws === true)
|
|
917
|
-
return false;
|
|
918
|
-
const methods = mock.method ? isArray3(mock.method) ? mock.method : [mock.method] : ["GET", "POST"];
|
|
919
|
-
if (!methods.includes(method))
|
|
920
|
-
return false;
|
|
921
|
-
const hasMock = pathToRegexp2(mock.url).test(pathname);
|
|
922
|
-
if (hasMock && mock.validator) {
|
|
923
|
-
const params = parseParams(mock.url, pathname);
|
|
924
|
-
if (isFunction(mock.validator)) {
|
|
925
|
-
return mock.validator({ params, ...request });
|
|
926
|
-
} else {
|
|
927
|
-
try {
|
|
928
|
-
return validate({ params, ...request }, mock.validator);
|
|
929
|
-
} catch (e) {
|
|
930
|
-
const file = mock.__filepath__;
|
|
931
|
-
logger.error(
|
|
932
|
-
`${colors.red(
|
|
933
|
-
`mock error at ${pathname}`
|
|
934
|
-
)}
|
|
935
|
-
${e}
|
|
936
|
-
at validator (${colors.underline(file)})`,
|
|
937
|
-
mock.log
|
|
938
|
-
);
|
|
939
|
-
return false;
|
|
940
|
-
}
|
|
941
|
-
}
|
|
942
|
-
}
|
|
943
|
-
return hasMock;
|
|
944
|
-
});
|
|
945
|
-
}
|
|
946
|
-
function responseStatus(response, status = 200, statusText) {
|
|
947
|
-
response.statusCode = status;
|
|
948
|
-
response.statusMessage = statusText || getHTTPStatusText(status);
|
|
949
|
-
}
|
|
950
|
-
async function provideHeaders(req, res, mock, logger) {
|
|
951
|
-
const { headers, type = "json" } = mock;
|
|
952
|
-
const filepath = mock.__filepath__;
|
|
953
|
-
const contentType2 = mime.contentType(type) || mime.contentType(mime.lookup(type) || "");
|
|
954
|
-
if (contentType2)
|
|
955
|
-
res.setHeader("Content-Type", contentType2);
|
|
956
|
-
res.setHeader("Cache-Control", "no-cache,max-age=0");
|
|
957
|
-
res.setHeader("X-Mock-Power-By", "vite-plugin-mock-dev-server");
|
|
958
|
-
if (filepath)
|
|
959
|
-
res.setHeader("X-File-Path", filepath);
|
|
960
|
-
if (!headers)
|
|
961
|
-
return;
|
|
962
|
-
try {
|
|
963
|
-
const raw = isFunction(headers) ? await headers(req) : headers;
|
|
964
|
-
Object.keys(raw).forEach((key) => {
|
|
965
|
-
res.setHeader(key, raw[key]);
|
|
966
|
-
});
|
|
967
|
-
} catch (e) {
|
|
968
|
-
logger.error(
|
|
969
|
-
`${colors.red(
|
|
970
|
-
`mock error at ${req.url.split("?")[0]}`
|
|
971
|
-
)}
|
|
972
|
-
${e}
|
|
973
|
-
at headers (${colors.underline(filepath)})`,
|
|
974
|
-
mock.log
|
|
975
|
-
);
|
|
976
|
-
}
|
|
977
|
-
}
|
|
978
|
-
async function provideCookies(req, res, mock, logger) {
|
|
979
|
-
const { cookies } = mock;
|
|
980
|
-
const filepath = mock.__filepath__;
|
|
981
|
-
if (!cookies)
|
|
982
|
-
return;
|
|
983
|
-
try {
|
|
984
|
-
const raw = isFunction(cookies) ? await cookies(req) : cookies;
|
|
985
|
-
Object.keys(raw).forEach((key) => {
|
|
986
|
-
const cookie = raw[key];
|
|
987
|
-
if (isArray3(cookie)) {
|
|
988
|
-
const [value, options] = cookie;
|
|
989
|
-
res.setCookie(key, value, options);
|
|
990
|
-
} else {
|
|
991
|
-
res.setCookie(key, cookie);
|
|
992
|
-
}
|
|
993
|
-
});
|
|
994
|
-
} catch (e) {
|
|
995
|
-
logger.error(
|
|
996
|
-
`${colors.red(
|
|
997
|
-
`mock error at ${req.url.split("?")[0]}`
|
|
998
|
-
)}
|
|
999
|
-
${e}
|
|
1000
|
-
at cookies (${colors.underline(filepath)})`,
|
|
1001
|
-
mock.log
|
|
1002
|
-
);
|
|
1003
|
-
}
|
|
1004
|
-
}
|
|
1005
|
-
function sendData(res, raw, type) {
|
|
1006
|
-
if (isReadableStream(raw)) {
|
|
1007
|
-
raw.pipe(res);
|
|
1008
|
-
} else if (Buffer2.isBuffer(raw)) {
|
|
1009
|
-
res.end(type === "text" || type === "json" ? raw.toString("utf-8") : raw);
|
|
1010
|
-
} else {
|
|
1011
|
-
const content = typeof raw === "string" ? raw : JSON.stringify(raw);
|
|
1012
|
-
res.end(type === "buffer" ? Buffer2.from(content) : content);
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1015
|
-
async function realDelay(startTime, delay) {
|
|
1016
|
-
if (!delay || typeof delay === "number" && delay <= 0 || isArray3(delay) && delay.length !== 2) {
|
|
1017
|
-
return;
|
|
1018
|
-
}
|
|
1019
|
-
let realDelay2 = 0;
|
|
1020
|
-
if (isArray3(delay)) {
|
|
1021
|
-
const [min, max] = delay;
|
|
1022
|
-
realDelay2 = random(min, max);
|
|
1023
|
-
} else {
|
|
1024
|
-
realDelay2 = delay - (timestamp() - startTime);
|
|
1025
|
-
}
|
|
1026
|
-
if (realDelay2 > 0)
|
|
1027
|
-
await sleep(realDelay2);
|
|
1028
|
-
}
|
|
1029
|
-
function getHTTPStatusText(status) {
|
|
1030
|
-
return HTTP_STATUS[status] || "Unknown";
|
|
1031
|
-
}
|
|
1032
|
-
function requestLog(request, filepath) {
|
|
1033
|
-
const { url, method, query, params, body } = request;
|
|
1034
|
-
let { pathname } = new URL(url, "http://example.com");
|
|
1035
|
-
pathname = colors.green(decodeURIComponent(pathname));
|
|
1036
|
-
const format = (prefix, data) => {
|
|
1037
|
-
return !data || isEmptyObject2(data) ? "" : ` ${colors.gray(`${prefix}:`)}${JSON.stringify(data)}`;
|
|
1038
|
-
};
|
|
1039
|
-
const ms = colors.magenta(colors.bold(method));
|
|
1040
|
-
const qs = format("query", query);
|
|
1041
|
-
const ps = format("params", params);
|
|
1042
|
-
const bs = format("body", body);
|
|
1043
|
-
const file = ` ${colors.dim(colors.underline(`(${filepath})`))}`;
|
|
1044
|
-
return `${ms} ${pathname}${qs}${ps}${bs}${file}`;
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
|
-
// src/logger.ts
|
|
1048
|
-
import { isBoolean } from "@pengzhanbo/utils";
|
|
1049
|
-
import colors2 from "picocolors";
|
|
1050
|
-
var logLevels = {
|
|
1051
|
-
silent: 0,
|
|
1052
|
-
error: 1,
|
|
1053
|
-
warn: 2,
|
|
1054
|
-
info: 3,
|
|
1055
|
-
debug: 4
|
|
1056
|
-
};
|
|
1057
|
-
function createLogger(prefix, defaultLevel = "info") {
|
|
1058
|
-
prefix = `[${prefix}]`;
|
|
1059
|
-
function output(type, msg, level) {
|
|
1060
|
-
level = isBoolean(level) ? level ? defaultLevel : "error" : level;
|
|
1061
|
-
const thresh = logLevels[level];
|
|
1062
|
-
if (thresh >= logLevels[type]) {
|
|
1063
|
-
const method = type === "info" || type === "debug" ? "log" : type;
|
|
1064
|
-
const tag = type === "debug" ? colors2.magenta(colors2.bold(prefix)) : type === "info" ? colors2.cyan(colors2.bold(prefix)) : type === "warn" ? colors2.yellow(colors2.bold(prefix)) : colors2.red(colors2.bold(prefix));
|
|
1065
|
-
const format = `${colors2.dim(
|
|
1066
|
-
(/* @__PURE__ */ new Date()).toLocaleTimeString()
|
|
1067
|
-
)} ${tag} ${msg}`;
|
|
1068
|
-
console[method](format);
|
|
1069
|
-
}
|
|
1070
|
-
}
|
|
1071
|
-
const logger = {
|
|
1072
|
-
debug(msg, level = defaultLevel) {
|
|
1073
|
-
output("debug", msg, level);
|
|
1074
|
-
},
|
|
1075
|
-
info(msg, level = defaultLevel) {
|
|
1076
|
-
output("info", msg, level);
|
|
1077
|
-
},
|
|
1078
|
-
warn(msg, level = defaultLevel) {
|
|
1079
|
-
output("warn", msg, level);
|
|
1080
|
-
},
|
|
1081
|
-
error(msg, level = defaultLevel) {
|
|
1082
|
-
output("error", msg, level);
|
|
1083
|
-
}
|
|
1084
|
-
};
|
|
1085
|
-
return logger;
|
|
1086
|
-
}
|
|
1087
|
-
|
|
1088
|
-
// src/MockLoader.ts
|
|
352
|
+
// src/core/mockCompiler.ts
|
|
1089
353
|
import EventEmitter from "node:events";
|
|
1090
|
-
import
|
|
1091
|
-
import {
|
|
354
|
+
import process3 from "node:process";
|
|
355
|
+
import { promiseParallel, toArray as toArray2 } from "@pengzhanbo/utils";
|
|
1092
356
|
import chokidar from "chokidar";
|
|
1093
357
|
import fastGlob from "fast-glob";
|
|
1094
358
|
import { createFilter as createFilter2 } from "@rollup/pluginutils";
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
import {
|
|
1098
|
-
isEmptyObject as isEmptyObject3,
|
|
1099
|
-
isFunction as isFunction2,
|
|
1100
|
-
isObject as isObject2,
|
|
1101
|
-
sortBy as sortBy2,
|
|
1102
|
-
toArray as toArray2
|
|
1103
|
-
} from "@pengzhanbo/utils";
|
|
1104
|
-
function transformMockData(mockList) {
|
|
1105
|
-
const list = [];
|
|
1106
|
-
for (const [, handle] of mockList.entries()) {
|
|
1107
|
-
if (handle)
|
|
1108
|
-
list.push(...toArray2(handle));
|
|
1109
|
-
}
|
|
1110
|
-
const mocks = {};
|
|
1111
|
-
list.filter((mock) => isObject2(mock) && mock.enabled !== false && mock.url).forEach((mock) => {
|
|
1112
|
-
const { pathname, query } = urlParse(mock.url);
|
|
1113
|
-
const list2 = mocks[pathname] ??= [];
|
|
1114
|
-
const current = { ...mock, url: pathname };
|
|
1115
|
-
if (current.ws !== true) {
|
|
1116
|
-
const validator = current.validator;
|
|
1117
|
-
if (!isEmptyObject3(query)) {
|
|
1118
|
-
if (isFunction2(validator)) {
|
|
1119
|
-
current.validator = function(request) {
|
|
1120
|
-
return isObjectSubset(request.query, query) && validator(request);
|
|
1121
|
-
};
|
|
1122
|
-
} else if (validator) {
|
|
1123
|
-
current.validator = { ...validator };
|
|
1124
|
-
current.validator.query = current.validator.query ? { ...query, ...current.validator.query } : query;
|
|
1125
|
-
} else {
|
|
1126
|
-
current.validator = { query };
|
|
1127
|
-
}
|
|
1128
|
-
}
|
|
1129
|
-
}
|
|
1130
|
-
list2.push(current);
|
|
1131
|
-
});
|
|
1132
|
-
Object.keys(mocks).forEach((key) => {
|
|
1133
|
-
mocks[key] = sortByValidator(mocks[key]);
|
|
1134
|
-
});
|
|
1135
|
-
return mocks;
|
|
1136
|
-
}
|
|
1137
|
-
function sortByValidator(mocks) {
|
|
1138
|
-
return sortBy2(mocks, (item) => {
|
|
1139
|
-
if (item.ws === true)
|
|
1140
|
-
return 0;
|
|
1141
|
-
const { validator } = item;
|
|
1142
|
-
if (!validator || isEmptyObject3(validator))
|
|
1143
|
-
return 2;
|
|
1144
|
-
if (isFunction2(validator))
|
|
1145
|
-
return 0;
|
|
1146
|
-
const count = Object.keys(validator).reduce(
|
|
1147
|
-
(prev, key) => prev + keysCount(validator[key]),
|
|
1148
|
-
0
|
|
1149
|
-
);
|
|
1150
|
-
return 1 / count;
|
|
1151
|
-
});
|
|
1152
|
-
}
|
|
1153
|
-
function keysCount(obj) {
|
|
1154
|
-
if (!obj)
|
|
1155
|
-
return 0;
|
|
1156
|
-
return Object.keys(obj).length;
|
|
359
|
+
function createMockCompiler(options) {
|
|
360
|
+
return new MockCompiler(options);
|
|
1157
361
|
}
|
|
1158
|
-
|
|
1159
|
-
// src/MockLoader.ts
|
|
1160
|
-
var MockLoader = class extends EventEmitter {
|
|
362
|
+
var MockCompiler = class extends EventEmitter {
|
|
1161
363
|
constructor(options) {
|
|
1162
364
|
super();
|
|
1163
365
|
this.options = options;
|
|
1164
|
-
this.cwd = options.cwd ||
|
|
366
|
+
this.cwd = options.cwd || process3.cwd();
|
|
1165
367
|
try {
|
|
1166
368
|
const pkg = lookupFile(this.cwd, ["package.json"]);
|
|
1167
369
|
this.moduleType = !!pkg && JSON.parse(pkg).type === "module" ? "esm" : "cjs";
|
|
@@ -1178,11 +380,9 @@ var MockLoader = class extends EventEmitter {
|
|
|
1178
380
|
get mockData() {
|
|
1179
381
|
return this._mockData;
|
|
1180
382
|
}
|
|
1181
|
-
|
|
383
|
+
run() {
|
|
1182
384
|
const { include, exclude } = this.options;
|
|
1183
|
-
const includeFilter = createFilter2(include, exclude, {
|
|
1184
|
-
resolve: false
|
|
1185
|
-
});
|
|
385
|
+
const includeFilter = createFilter2(include, exclude, { resolve: false });
|
|
1186
386
|
fastGlob(include, { cwd: this.cwd }).then(
|
|
1187
387
|
(files) => files.filter(includeFilter).map((file) => () => this.loadMock(file))
|
|
1188
388
|
).then((loadList) => promiseParallel(loadList, 10)).then(() => this.updateMockList());
|
|
@@ -1211,7 +411,7 @@ var MockLoader = class extends EventEmitter {
|
|
|
1211
411
|
}
|
|
1212
412
|
watchMockEntry() {
|
|
1213
413
|
const { include } = this.options;
|
|
1214
|
-
const [firstGlob, ...otherGlob] = include;
|
|
414
|
+
const [firstGlob, ...otherGlob] = toArray2(include);
|
|
1215
415
|
const watcher = this.mockWatcher = chokidar.watch(firstGlob, {
|
|
1216
416
|
ignoreInitial: true,
|
|
1217
417
|
cwd: this.cwd
|
|
@@ -1247,7 +447,7 @@ var MockLoader = class extends EventEmitter {
|
|
|
1247
447
|
this.depsWatcher.on("change", (filepath) => {
|
|
1248
448
|
filepath = normalizePath(filepath);
|
|
1249
449
|
const mockFiles = this.moduleDeps.get(filepath);
|
|
1250
|
-
mockFiles
|
|
450
|
+
mockFiles?.forEach((file) => {
|
|
1251
451
|
this.emit("mock:update", file);
|
|
1252
452
|
});
|
|
1253
453
|
});
|
|
@@ -1265,9 +465,8 @@ var MockLoader = class extends EventEmitter {
|
|
|
1265
465
|
});
|
|
1266
466
|
}
|
|
1267
467
|
close() {
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
(_b = this.depsWatcher) == null ? void 0 : _b.close();
|
|
468
|
+
this.mockWatcher?.close();
|
|
469
|
+
this.depsWatcher?.close();
|
|
1271
470
|
}
|
|
1272
471
|
updateMockList() {
|
|
1273
472
|
this._mockData = transformMockData(this.moduleCache);
|
|
@@ -1300,28 +499,8 @@ var MockLoader = class extends EventEmitter {
|
|
|
1300
499
|
{ isESM, define, alias, cwd: this.cwd }
|
|
1301
500
|
);
|
|
1302
501
|
try {
|
|
1303
|
-
const raw = await loadFromCode({
|
|
1304
|
-
|
|
1305
|
-
code,
|
|
1306
|
-
isESM,
|
|
1307
|
-
cwd: this.cwd
|
|
1308
|
-
}) || {};
|
|
1309
|
-
let mockConfig;
|
|
1310
|
-
if (hasOwn(raw, "default")) {
|
|
1311
|
-
mockConfig = raw.default;
|
|
1312
|
-
} else {
|
|
1313
|
-
mockConfig = [];
|
|
1314
|
-
Object.keys(raw).forEach(
|
|
1315
|
-
(key) => mockConfig.push(...toArray3(raw[key]))
|
|
1316
|
-
);
|
|
1317
|
-
}
|
|
1318
|
-
if (isArray4(mockConfig)) {
|
|
1319
|
-
mockConfig.forEach((mock) => mock.__filepath__ = filepath);
|
|
1320
|
-
} else {
|
|
1321
|
-
;
|
|
1322
|
-
mockConfig.__filepath__ = filepath;
|
|
1323
|
-
}
|
|
1324
|
-
this.moduleCache.set(filepath, mockConfig);
|
|
502
|
+
const raw = await loadFromCode({ filepath, code, isESM, cwd: this.cwd }) || {};
|
|
503
|
+
this.moduleCache.set(filepath, transformRawData(raw, filepath));
|
|
1325
504
|
this.updateModuleDeps(filepath, deps);
|
|
1326
505
|
} catch (e) {
|
|
1327
506
|
console.error(e);
|
|
@@ -1329,198 +508,16 @@ var MockLoader = class extends EventEmitter {
|
|
|
1329
508
|
}
|
|
1330
509
|
};
|
|
1331
510
|
|
|
1332
|
-
// src/
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
function mockWebSocket({
|
|
1338
|
-
loader,
|
|
1339
|
-
httpServer,
|
|
1340
|
-
proxies,
|
|
1341
|
-
cookiesOptions,
|
|
1342
|
-
logger
|
|
1343
|
-
}) {
|
|
1344
|
-
var _a;
|
|
1345
|
-
const hmrMap = /* @__PURE__ */ new Map();
|
|
1346
|
-
const poolMap = /* @__PURE__ */ new Map();
|
|
1347
|
-
const wssContextMap = /* @__PURE__ */ new WeakMap();
|
|
1348
|
-
const getWssMap = (mockUrl) => {
|
|
1349
|
-
let wssMap = poolMap.get(mockUrl);
|
|
1350
|
-
if (!wssMap)
|
|
1351
|
-
poolMap.set(mockUrl, wssMap = /* @__PURE__ */ new Map());
|
|
1352
|
-
return wssMap;
|
|
1353
|
-
};
|
|
1354
|
-
const getWss = (wssMap, pathname) => {
|
|
1355
|
-
let wss = wssMap.get(pathname);
|
|
1356
|
-
if (!wss)
|
|
1357
|
-
wssMap.set(pathname, wss = new WebSocketServer({ noServer: true }));
|
|
1358
|
-
return wss;
|
|
1359
|
-
};
|
|
1360
|
-
const addHmr = (filepath, mockUrl) => {
|
|
1361
|
-
let urlList = hmrMap.get(filepath);
|
|
1362
|
-
if (!urlList)
|
|
1363
|
-
hmrMap.set(filepath, urlList = /* @__PURE__ */ new Set());
|
|
1364
|
-
urlList.add(mockUrl);
|
|
1365
|
-
};
|
|
1366
|
-
const setupWss = (wssMap, wss, mock, context, pathname, filepath) => {
|
|
1367
|
-
var _a2;
|
|
1368
|
-
try {
|
|
1369
|
-
(_a2 = mock.setup) == null ? void 0 : _a2.call(mock, wss, context);
|
|
1370
|
-
wss.on("close", () => wssMap.delete(pathname));
|
|
1371
|
-
wss.on("error", (e) => {
|
|
1372
|
-
logger.error(
|
|
1373
|
-
`${colors3.red(
|
|
1374
|
-
`WebSocket mock error at ${wss.path}`
|
|
1375
|
-
)}
|
|
1376
|
-
${e}
|
|
1377
|
-
at setup (${filepath})`,
|
|
1378
|
-
mock.log
|
|
1379
|
-
);
|
|
1380
|
-
});
|
|
1381
|
-
} catch (e) {
|
|
1382
|
-
logger.error(
|
|
1383
|
-
`${colors3.red(
|
|
1384
|
-
`WebSocket mock error at ${wss.path}`
|
|
1385
|
-
)}
|
|
1386
|
-
${e}
|
|
1387
|
-
at setup (${filepath})`,
|
|
1388
|
-
mock.log
|
|
1389
|
-
);
|
|
1390
|
-
}
|
|
1391
|
-
};
|
|
1392
|
-
const emitConnection = (wss, ws, req, connectionList) => {
|
|
1393
|
-
wss.emit("connection", ws, req);
|
|
1394
|
-
ws.on("close", () => {
|
|
1395
|
-
const i = connectionList.findIndex((item) => item.ws === ws);
|
|
1396
|
-
if (i !== -1)
|
|
1397
|
-
connectionList.splice(i, 1);
|
|
1398
|
-
});
|
|
1399
|
-
};
|
|
1400
|
-
const restartWss = (wssMap, wss, mock, pathname, filepath) => {
|
|
1401
|
-
const { cleanupList, connectionList, context } = wssContextMap.get(wss);
|
|
1402
|
-
cleanupRunner(cleanupList);
|
|
1403
|
-
connectionList.forEach(({ ws }) => ws.removeAllListeners());
|
|
1404
|
-
wss.removeAllListeners();
|
|
1405
|
-
setupWss(wssMap, wss, mock, context, pathname, filepath);
|
|
1406
|
-
connectionList.forEach(
|
|
1407
|
-
({ ws, req }) => emitConnection(wss, ws, req, connectionList)
|
|
1408
|
-
);
|
|
1409
|
-
};
|
|
1410
|
-
(_a = loader.on) == null ? void 0 : _a.call(loader, "mock:update-end", (filepath) => {
|
|
1411
|
-
if (!hmrMap.has(filepath))
|
|
1412
|
-
return;
|
|
1413
|
-
const mockUrlList = hmrMap.get(filepath);
|
|
1414
|
-
if (!mockUrlList)
|
|
1415
|
-
return;
|
|
1416
|
-
for (const mockUrl of mockUrlList.values()) {
|
|
1417
|
-
for (const mock of loader.mockData[mockUrl]) {
|
|
1418
|
-
if (!mock.ws || mock.__filepath__ !== filepath)
|
|
1419
|
-
return;
|
|
1420
|
-
const wssMap = getWssMap(mockUrl);
|
|
1421
|
-
for (const [pathname, wss] of wssMap.entries())
|
|
1422
|
-
restartWss(wssMap, wss, mock, pathname, filepath);
|
|
1423
|
-
}
|
|
1424
|
-
}
|
|
1425
|
-
});
|
|
1426
|
-
httpServer == null ? void 0 : httpServer.on("upgrade", (req, socket, head) => {
|
|
1427
|
-
const { pathname, query } = urlParse(req.url);
|
|
1428
|
-
if (!pathname || proxies.length === 0 || !proxies.some((context) => doesProxyContextMatchUrl(context, req.url))) {
|
|
1429
|
-
return;
|
|
1430
|
-
}
|
|
1431
|
-
const mockData = loader.mockData;
|
|
1432
|
-
const mockUrl = Object.keys(mockData).find((key) => {
|
|
1433
|
-
return pathToRegexp3(key).test(pathname);
|
|
1434
|
-
});
|
|
1435
|
-
if (!mockUrl)
|
|
1436
|
-
return;
|
|
1437
|
-
const mock = mockData[mockUrl].find((mock2) => {
|
|
1438
|
-
return mock2.url && mock2.ws && pathToRegexp3(mock2.url).test(pathname);
|
|
1439
|
-
});
|
|
1440
|
-
if (!mock)
|
|
1441
|
-
return;
|
|
1442
|
-
const filepath = mock.__filepath__;
|
|
1443
|
-
addHmr(filepath, mockUrl);
|
|
1444
|
-
const wssMap = getWssMap(mockUrl);
|
|
1445
|
-
const wss = getWss(wssMap, pathname);
|
|
1446
|
-
let wssContext = wssContextMap.get(wss);
|
|
1447
|
-
if (!wssContext) {
|
|
1448
|
-
const cleanupList = [];
|
|
1449
|
-
const context = {
|
|
1450
|
-
onCleanup: (cleanup) => cleanupList.push(cleanup)
|
|
1451
|
-
};
|
|
1452
|
-
wssContext = { cleanupList, context, connectionList: [] };
|
|
1453
|
-
wssContextMap.set(wss, wssContext);
|
|
1454
|
-
setupWss(wssMap, wss, mock, context, pathname, filepath);
|
|
1455
|
-
}
|
|
1456
|
-
const request = req;
|
|
1457
|
-
const cookies = new Cookies2(req, req, cookiesOptions);
|
|
1458
|
-
const { query: refererQuery } = urlParse(req.headers.referer || "");
|
|
1459
|
-
request.query = query;
|
|
1460
|
-
request.refererQuery = refererQuery;
|
|
1461
|
-
request.params = parseParams(mockUrl, pathname);
|
|
1462
|
-
request.getCookie = cookies.get.bind(cookies);
|
|
1463
|
-
wss.handleUpgrade(request, socket, head, (ws) => {
|
|
1464
|
-
logger.info(
|
|
1465
|
-
`${colors3.magenta(colors3.bold("WebSocket"))} ${colors3.green(
|
|
1466
|
-
req.url
|
|
1467
|
-
)} connected ${colors3.dim(`(${filepath})`)}`,
|
|
1468
|
-
mock.log
|
|
1469
|
-
);
|
|
1470
|
-
wssContext.connectionList.push({ req: request, ws });
|
|
1471
|
-
emitConnection(wss, ws, request, wssContext.connectionList);
|
|
1472
|
-
});
|
|
1473
|
-
});
|
|
1474
|
-
httpServer == null ? void 0 : httpServer.on("close", () => {
|
|
1475
|
-
for (const wssMap of poolMap.values()) {
|
|
1476
|
-
for (const wss of wssMap.values()) {
|
|
1477
|
-
const wssContext = wssContextMap.get(wss);
|
|
1478
|
-
cleanupRunner(wssContext.cleanupList);
|
|
1479
|
-
wss.close();
|
|
1480
|
-
}
|
|
1481
|
-
wssMap.clear();
|
|
1482
|
-
}
|
|
1483
|
-
poolMap.clear();
|
|
1484
|
-
hmrMap.clear();
|
|
1485
|
-
});
|
|
1486
|
-
}
|
|
1487
|
-
function cleanupRunner(cleanupList) {
|
|
1488
|
-
let cleanup;
|
|
1489
|
-
while (cleanup = cleanupList.shift())
|
|
1490
|
-
cleanup == null ? void 0 : cleanup();
|
|
1491
|
-
}
|
|
1492
|
-
|
|
1493
|
-
// src/mockMiddleware.ts
|
|
1494
|
-
function mockServerMiddleware(config, options, httpServer, ws) {
|
|
1495
|
-
const logger = createLogger(
|
|
1496
|
-
"vite:mock",
|
|
1497
|
-
isBoolean2(options.log) ? options.log ? "info" : "error" : options.log
|
|
1498
|
-
);
|
|
1499
|
-
const loader = new MockLoader({
|
|
1500
|
-
cwd: options.cwd,
|
|
1501
|
-
include: toArray4(options.include),
|
|
1502
|
-
exclude: toArray4(options.exclude),
|
|
1503
|
-
define: viteDefine(config),
|
|
1504
|
-
alias: config.resolve.alias
|
|
1505
|
-
});
|
|
1506
|
-
loader.load();
|
|
1507
|
-
loader.on("mock:update-end", () => {
|
|
511
|
+
// src/core/mockMiddleware.ts
|
|
512
|
+
function mockServerMiddleware(options, server, ws) {
|
|
513
|
+
const compiler = createMockCompiler(options);
|
|
514
|
+
compiler.run();
|
|
515
|
+
compiler.on("mock:update-end", () => {
|
|
1508
516
|
if (options.reload)
|
|
1509
|
-
ws
|
|
1510
|
-
});
|
|
1511
|
-
httpServer == null ? void 0 : httpServer.on("close", () => loader.close());
|
|
1512
|
-
const { httpProxies } = ensureProxies(config.server.proxy || {});
|
|
1513
|
-
const prefix = toArray4(options.prefix);
|
|
1514
|
-
const proxies = uniq2([...prefix, ...httpProxies]);
|
|
1515
|
-
if (!proxies.length && !toArray4(options.wsPrefix).length)
|
|
1516
|
-
logger.warn(`No proxy was configured, mock server will not work. See ${c2.cyan("https://vite-plugin-mock-dev-server.netlify.app/guide/usage")}`);
|
|
1517
|
-
mockWebSocket({
|
|
1518
|
-
loader,
|
|
1519
|
-
httpServer,
|
|
1520
|
-
proxies: toArray4(options.wsPrefix),
|
|
1521
|
-
cookiesOptions: options.cookiesOptions,
|
|
1522
|
-
logger
|
|
517
|
+
ws?.send({ type: "full-reload" });
|
|
1523
518
|
});
|
|
519
|
+
server?.on("close", () => compiler.close());
|
|
520
|
+
mockWebSocket(compiler, server, options);
|
|
1524
521
|
const middlewares = [];
|
|
1525
522
|
middlewares.push(
|
|
1526
523
|
/**
|
|
@@ -1534,43 +531,20 @@ function mockServerMiddleware(config, options, httpServer, ws) {
|
|
|
1534
531
|
* 也会使用 viteConfig.server.cors 配置,并支持 用户可以对 mock 中的 cors 中间件进行配置。
|
|
1535
532
|
* 而用户的配置也仅对 mock 的接口生效。
|
|
1536
533
|
*/
|
|
1537
|
-
corsMiddleware(
|
|
1538
|
-
baseMiddleware(
|
|
1539
|
-
formidableOptions: options.formidableOptions,
|
|
1540
|
-
proxies,
|
|
1541
|
-
cookiesOptions: options.cookiesOptions,
|
|
1542
|
-
bodyParserOptions: options.bodyParserOptions,
|
|
1543
|
-
priority: options.priority,
|
|
1544
|
-
logger
|
|
1545
|
-
})
|
|
534
|
+
corsMiddleware(compiler, options),
|
|
535
|
+
baseMiddleware(compiler, options)
|
|
1546
536
|
);
|
|
1547
537
|
return middlewares.filter(Boolean);
|
|
1548
538
|
}
|
|
1549
|
-
function corsMiddleware(
|
|
1550
|
-
|
|
1551
|
-
const enabled = options.cors === false ? false : config.server.cors !== false;
|
|
1552
|
-
if (enabled && config.server.cors !== false) {
|
|
1553
|
-
corsOptions = {
|
|
1554
|
-
...corsOptions,
|
|
1555
|
-
...typeof config.server.cors === "boolean" ? {} : config.server.cors
|
|
1556
|
-
};
|
|
1557
|
-
}
|
|
1558
|
-
if (enabled && options.cors !== false) {
|
|
1559
|
-
corsOptions = {
|
|
1560
|
-
...corsOptions,
|
|
1561
|
-
...typeof options.cors === "boolean" ? {} : options.cors
|
|
1562
|
-
};
|
|
1563
|
-
}
|
|
1564
|
-
return !enabled ? void 0 : function(req, res, next) {
|
|
539
|
+
function corsMiddleware(compiler, { proxies, cors: corsOptions }) {
|
|
540
|
+
return !corsOptions ? void 0 : function(req, res, next) {
|
|
1565
541
|
const { pathname } = urlParse(req.url);
|
|
1566
|
-
if (!pathname || proxies.length === 0 || !proxies.some(
|
|
1567
|
-
(context) => doesProxyContextMatchUrl(context, req.url)
|
|
1568
|
-
)) {
|
|
542
|
+
if (!pathname || proxies.length === 0 || !proxies.some((context) => doesProxyContextMatchUrl(context, req.url))) {
|
|
1569
543
|
return next();
|
|
1570
544
|
}
|
|
1571
|
-
const mockData =
|
|
545
|
+
const mockData = compiler.mockData;
|
|
1572
546
|
const mockUrl = Object.keys(mockData).find(
|
|
1573
|
-
(key) =>
|
|
547
|
+
(key) => pathToRegexp(key).test(pathname)
|
|
1574
548
|
);
|
|
1575
549
|
if (!mockUrl)
|
|
1576
550
|
return next();
|
|
@@ -1578,11 +552,95 @@ function corsMiddleware(mockLoader, proxies, config, options) {
|
|
|
1578
552
|
};
|
|
1579
553
|
}
|
|
1580
554
|
|
|
1581
|
-
// src/
|
|
1582
|
-
|
|
555
|
+
// src/core/resolvePluginOptions.ts
|
|
556
|
+
import process5 from "node:process";
|
|
557
|
+
import { isArray, isBoolean, toArray as toArray3, uniq } from "@pengzhanbo/utils";
|
|
558
|
+
import color from "picocolors";
|
|
559
|
+
|
|
560
|
+
// src/core/define.ts
|
|
561
|
+
import process4 from "node:process";
|
|
562
|
+
function viteDefine(config) {
|
|
563
|
+
const processNodeEnv = {};
|
|
564
|
+
const nodeEnv = process4.env.NODE_ENV || config.mode;
|
|
565
|
+
Object.assign(processNodeEnv, {
|
|
566
|
+
"process.env.NODE_ENV": JSON.stringify(nodeEnv),
|
|
567
|
+
"global.process.env.NODE_ENV": JSON.stringify(nodeEnv),
|
|
568
|
+
"globalThis.process.env.NODE_ENV": JSON.stringify(nodeEnv)
|
|
569
|
+
});
|
|
570
|
+
const userDefine = {};
|
|
571
|
+
const userDefineEnv = {};
|
|
572
|
+
for (const key in config.define) {
|
|
573
|
+
const val = config.define[key];
|
|
574
|
+
const isMetaEnv = key.startsWith("import.meta.env.");
|
|
575
|
+
if (typeof val === "string") {
|
|
576
|
+
if (canJsonParse(val)) {
|
|
577
|
+
userDefine[key] = val;
|
|
578
|
+
if (isMetaEnv)
|
|
579
|
+
userDefineEnv[key.slice(16)] = val;
|
|
580
|
+
}
|
|
581
|
+
} else {
|
|
582
|
+
userDefine[key] = handleDefineValue(val);
|
|
583
|
+
if (isMetaEnv)
|
|
584
|
+
userDefineEnv[key.slice(16)] = val;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
const importMetaKeys = {};
|
|
588
|
+
const importMetaEnvKeys = {};
|
|
589
|
+
const importMetaFallbackKeys = {};
|
|
590
|
+
importMetaKeys["import.meta.hot"] = `undefined`;
|
|
591
|
+
for (const key in config.env) {
|
|
592
|
+
const val = JSON.stringify(config.env[key]);
|
|
593
|
+
importMetaKeys[`import.meta.env.${key}`] = val;
|
|
594
|
+
importMetaEnvKeys[key] = val;
|
|
595
|
+
}
|
|
596
|
+
importMetaFallbackKeys["import.meta.env"] = `undefined`;
|
|
597
|
+
const define = {
|
|
598
|
+
...processNodeEnv,
|
|
599
|
+
...importMetaKeys,
|
|
600
|
+
...userDefine,
|
|
601
|
+
...importMetaFallbackKeys
|
|
602
|
+
};
|
|
603
|
+
if ("import.meta.env" in define) {
|
|
604
|
+
define["import.meta.env"] = serializeDefine({
|
|
605
|
+
...importMetaEnvKeys,
|
|
606
|
+
...userDefineEnv
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
return define;
|
|
610
|
+
}
|
|
611
|
+
function serializeDefine(define) {
|
|
612
|
+
let res = `{`;
|
|
613
|
+
const keys = Object.keys(define);
|
|
614
|
+
for (let i = 0; i < keys.length; i++) {
|
|
615
|
+
const key = keys[i];
|
|
616
|
+
const val = define[key];
|
|
617
|
+
res += `${JSON.stringify(key)}: ${handleDefineValue(val)}`;
|
|
618
|
+
if (i !== keys.length - 1)
|
|
619
|
+
res += `, `;
|
|
620
|
+
}
|
|
621
|
+
return `${res}}`;
|
|
622
|
+
}
|
|
623
|
+
function handleDefineValue(value) {
|
|
624
|
+
if (typeof value === "undefined")
|
|
625
|
+
return "undefined";
|
|
626
|
+
if (typeof value === "string")
|
|
627
|
+
return value;
|
|
628
|
+
return JSON.stringify(value);
|
|
629
|
+
}
|
|
630
|
+
function canJsonParse(value) {
|
|
631
|
+
try {
|
|
632
|
+
JSON.parse(value);
|
|
633
|
+
return true;
|
|
634
|
+
} catch {
|
|
635
|
+
return false;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
// src/core/resolvePluginOptions.ts
|
|
640
|
+
function resolvePluginOptions({
|
|
1583
641
|
prefix = [],
|
|
1584
642
|
wsPrefix = [],
|
|
1585
|
-
cwd
|
|
643
|
+
cwd,
|
|
1586
644
|
include = ["mock/**/*.mock.{js,ts,cjs,mjs,json,json5}"],
|
|
1587
645
|
exclude = ["**/node_modules/**", "**/.vscode/**", "**/.git/**"],
|
|
1588
646
|
reload = false,
|
|
@@ -1593,15 +651,43 @@ function mockDevServerPlugin({
|
|
|
1593
651
|
cookiesOptions = {},
|
|
1594
652
|
bodyParserOptions = {},
|
|
1595
653
|
priority = {}
|
|
1596
|
-
}
|
|
1597
|
-
const
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
654
|
+
}, config) {
|
|
655
|
+
const logger = createLogger("vite:mock", isBoolean(log) ? log ? "info" : "error" : log);
|
|
656
|
+
const { httpProxies } = ensureProxies(config.server.proxy || {});
|
|
657
|
+
const proxies = uniq([...toArray3(prefix), ...httpProxies]);
|
|
658
|
+
const wsProxies = toArray3(wsPrefix);
|
|
659
|
+
if (!proxies.length && !wsProxies.length)
|
|
660
|
+
logger.warn(`No proxy was configured, mock server will not work. See ${color.cyan("https://vite-plugin-mock-dev-server.netlify.app/guide/usage")}`);
|
|
661
|
+
const enabled = cors2 === false ? false : config.server.cors !== false;
|
|
662
|
+
let corsOptions = {};
|
|
663
|
+
if (enabled && config.server.cors !== false) {
|
|
664
|
+
corsOptions = {
|
|
665
|
+
...corsOptions,
|
|
666
|
+
...typeof config.server.cors === "boolean" ? {} : config.server.cors
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
if (enabled && cors2 !== false) {
|
|
670
|
+
corsOptions = {
|
|
671
|
+
...corsOptions,
|
|
672
|
+
...typeof cors2 === "boolean" ? {} : cors2
|
|
673
|
+
};
|
|
674
|
+
}
|
|
675
|
+
const alias = [];
|
|
676
|
+
const aliasConfig = config.resolve.alias || [];
|
|
677
|
+
if (isArray(aliasConfig)) {
|
|
678
|
+
alias.push(...aliasConfig);
|
|
679
|
+
} else {
|
|
680
|
+
Object.entries(aliasConfig).forEach(([find, replacement]) => {
|
|
681
|
+
alias.push({ find, replacement });
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
return {
|
|
685
|
+
cwd: cwd || process5.cwd(),
|
|
1601
686
|
include,
|
|
1602
687
|
exclude,
|
|
688
|
+
context: config.root,
|
|
1603
689
|
reload,
|
|
1604
|
-
cors:
|
|
690
|
+
cors: enabled ? corsOptions : false,
|
|
1605
691
|
cookiesOptions,
|
|
1606
692
|
log,
|
|
1607
693
|
formidableOptions: {
|
|
@@ -1617,42 +703,50 @@ function mockDevServerPlugin({
|
|
|
1617
703
|
log: "error"
|
|
1618
704
|
},
|
|
1619
705
|
typeof build2 === "object" ? build2 : {}
|
|
1620
|
-
) : false
|
|
706
|
+
) : false,
|
|
707
|
+
proxies,
|
|
708
|
+
wsProxies,
|
|
709
|
+
logger,
|
|
710
|
+
alias,
|
|
711
|
+
define: viteDefine(config)
|
|
1621
712
|
};
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
// src/plugin.ts
|
|
716
|
+
function mockDevServerPlugin(options = {}) {
|
|
717
|
+
const plugins = [serverPlugin(options)];
|
|
718
|
+
if (options.build)
|
|
719
|
+
plugins.push(buildPlugin(options));
|
|
1625
720
|
return plugins;
|
|
1626
721
|
}
|
|
1627
|
-
function buildPlugin(
|
|
722
|
+
function buildPlugin(options) {
|
|
1628
723
|
let viteConfig = {};
|
|
724
|
+
let resolvedOptions;
|
|
1629
725
|
return {
|
|
1630
726
|
name: "vite-plugin-mock-dev-server-generator",
|
|
1631
727
|
enforce: "post",
|
|
1632
728
|
apply: "build",
|
|
1633
729
|
configResolved(config) {
|
|
1634
730
|
viteConfig = config;
|
|
731
|
+
resolvedOptions = resolvePluginOptions(options, config);
|
|
1635
732
|
config.logger.warn("");
|
|
1636
733
|
},
|
|
1637
734
|
async buildEnd(error) {
|
|
1638
|
-
if (error)
|
|
735
|
+
if (error || viteConfig.command !== "build")
|
|
1639
736
|
return;
|
|
1640
|
-
|
|
1641
|
-
return;
|
|
1642
|
-
await generateMockServer(this, viteConfig, pluginOptions);
|
|
737
|
+
await generateMockServer(this, resolvedOptions);
|
|
1643
738
|
}
|
|
1644
739
|
};
|
|
1645
740
|
}
|
|
1646
|
-
function serverPlugin(
|
|
1647
|
-
let
|
|
741
|
+
function serverPlugin(options) {
|
|
742
|
+
let resolvedOptions;
|
|
1648
743
|
return {
|
|
1649
744
|
name: "vite-plugin-mock-dev-server",
|
|
1650
745
|
enforce: "pre",
|
|
1651
746
|
apply: "serve",
|
|
1652
747
|
config(config) {
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
if (wsPrefix.length && ((_a = config.server) == null ? void 0 : _a.proxy)) {
|
|
748
|
+
const wsPrefix = toArray4(options.wsPrefix);
|
|
749
|
+
if (wsPrefix.length && config.server?.proxy) {
|
|
1656
750
|
const proxy = {};
|
|
1657
751
|
Object.keys(config.server.proxy).forEach((key) => {
|
|
1658
752
|
if (!wsPrefix.includes(key))
|
|
@@ -1663,97 +757,20 @@ function serverPlugin(pluginOptions) {
|
|
|
1663
757
|
recoverRequest(config);
|
|
1664
758
|
},
|
|
1665
759
|
configResolved(config) {
|
|
1666
|
-
|
|
760
|
+
resolvedOptions = resolvePluginOptions(options, config);
|
|
1667
761
|
config.logger.warn("");
|
|
1668
762
|
},
|
|
1669
|
-
configureServer({ middlewares,
|
|
1670
|
-
const middlewareList = mockServerMiddleware(
|
|
1671
|
-
config,
|
|
1672
|
-
pluginOptions,
|
|
1673
|
-
httpServer,
|
|
1674
|
-
ws
|
|
1675
|
-
);
|
|
763
|
+
configureServer({ middlewares, httpServer, ws }) {
|
|
764
|
+
const middlewareList = mockServerMiddleware(resolvedOptions, httpServer, ws);
|
|
1676
765
|
middlewareList.forEach((middleware) => middlewares.use(middleware));
|
|
1677
766
|
},
|
|
1678
767
|
configurePreviewServer({ middlewares, httpServer }) {
|
|
1679
|
-
const middlewareList = mockServerMiddleware(
|
|
1680
|
-
viteConfig,
|
|
1681
|
-
pluginOptions,
|
|
1682
|
-
httpServer
|
|
1683
|
-
);
|
|
768
|
+
const middlewareList = mockServerMiddleware(resolvedOptions, httpServer);
|
|
1684
769
|
middlewareList.forEach((middleware) => middlewares.use(middleware));
|
|
1685
770
|
}
|
|
1686
771
|
};
|
|
1687
772
|
}
|
|
1688
773
|
|
|
1689
|
-
// src/defineMock.ts
|
|
1690
|
-
import { isArray as isArray5 } from "@pengzhanbo/utils";
|
|
1691
|
-
function defineMock(config) {
|
|
1692
|
-
return config;
|
|
1693
|
-
}
|
|
1694
|
-
function createDefineMock(transformer) {
|
|
1695
|
-
const define = (config) => {
|
|
1696
|
-
if (isArray5(config))
|
|
1697
|
-
config = config.map((item) => transformer(item) || item);
|
|
1698
|
-
else
|
|
1699
|
-
config = transformer(config) || config;
|
|
1700
|
-
return config;
|
|
1701
|
-
};
|
|
1702
|
-
return define;
|
|
1703
|
-
}
|
|
1704
|
-
|
|
1705
|
-
// src/defineMockData.ts
|
|
1706
|
-
import { deepClone, deepEqual, isFunction as isFunction3 } from "@pengzhanbo/utils";
|
|
1707
|
-
var mockDataCache = /* @__PURE__ */ new Map();
|
|
1708
|
-
var responseCache = /* @__PURE__ */ new WeakMap();
|
|
1709
|
-
var staleInterval = 70;
|
|
1710
|
-
var CacheImpl = class {
|
|
1711
|
-
value;
|
|
1712
|
-
// 初始化数据的备份,用于 判断 传入的初始化数据是否发生变更
|
|
1713
|
-
#initialValue;
|
|
1714
|
-
#lastUpdate;
|
|
1715
|
-
constructor(value) {
|
|
1716
|
-
this.value = value;
|
|
1717
|
-
this.#initialValue = deepClone(value);
|
|
1718
|
-
this.#lastUpdate = Date.now();
|
|
1719
|
-
}
|
|
1720
|
-
hotUpdate(value) {
|
|
1721
|
-
if (Date.now() - this.#lastUpdate < staleInterval)
|
|
1722
|
-
return;
|
|
1723
|
-
if (!deepEqual(value, this.#initialValue)) {
|
|
1724
|
-
this.value = value;
|
|
1725
|
-
this.#initialValue = deepClone(value);
|
|
1726
|
-
this.#lastUpdate = Date.now();
|
|
1727
|
-
}
|
|
1728
|
-
}
|
|
1729
|
-
};
|
|
1730
|
-
function defineMockData(key, initialData) {
|
|
1731
|
-
if (!mockDataCache.has(key))
|
|
1732
|
-
mockDataCache.set(key, new CacheImpl(initialData));
|
|
1733
|
-
const cache2 = mockDataCache.get(key);
|
|
1734
|
-
cache2.hotUpdate(initialData);
|
|
1735
|
-
if (responseCache.has(cache2))
|
|
1736
|
-
return responseCache.get(cache2);
|
|
1737
|
-
const res = [
|
|
1738
|
-
() => cache2.value,
|
|
1739
|
-
(val) => {
|
|
1740
|
-
if (isFunction3(val))
|
|
1741
|
-
val = val(cache2.value) ?? cache2.value;
|
|
1742
|
-
cache2.value = val;
|
|
1743
|
-
}
|
|
1744
|
-
];
|
|
1745
|
-
Object.defineProperty(res, "value", {
|
|
1746
|
-
get() {
|
|
1747
|
-
return cache2.value;
|
|
1748
|
-
},
|
|
1749
|
-
set(val) {
|
|
1750
|
-
cache2.value = val;
|
|
1751
|
-
}
|
|
1752
|
-
});
|
|
1753
|
-
responseCache.set(cache2, res);
|
|
1754
|
-
return res;
|
|
1755
|
-
}
|
|
1756
|
-
|
|
1757
774
|
// src/index.ts
|
|
1758
775
|
var src_default = mockDevServerPlugin;
|
|
1759
776
|
export {
|
|
@@ -1767,5 +784,6 @@ export {
|
|
|
1767
784
|
mockDevServerPlugin,
|
|
1768
785
|
mockWebSocket,
|
|
1769
786
|
sortByValidator,
|
|
1770
|
-
transformMockData
|
|
787
|
+
transformMockData,
|
|
788
|
+
transformRawData
|
|
1771
789
|
};
|