rspack-plugin-mock 0.3.4 → 0.4.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 +2 -2
- package/README.zh-CN.md +2 -2
- package/dist/{chunk-O6PRDW23.js → chunk-4XOUX6CL.js} +127 -125
- package/dist/{chunk-EY46RSAC.js → chunk-JMXFIX5Q.js} +274 -272
- package/dist/{chunk-ZEC4FWWY.cjs → chunk-TKSRTJX5.cjs} +254 -252
- package/dist/{chunk-HLMEDDGX.cjs → chunk-YAHWW6TX.cjs} +127 -125
- package/dist/helper.cjs +55 -2
- package/dist/helper.d.cts +21 -7
- package/dist/helper.d.ts +21 -7
- package/dist/helper.js +54 -1
- package/dist/index.cjs +25 -25
- package/dist/index.d.cts +9 -9
- package/dist/index.d.ts +9 -9
- package/dist/index.js +14 -14
- package/dist/{mockWebsocket-CPuTAvL0.d.ts → mockWebsocket-DBgZBsdo.d.ts} +15 -15
- package/dist/{mockWebsocket-Dc9CZBfv.d.cts → mockWebsocket-Ki_cShTv.d.cts} +15 -15
- package/dist/rsbuild.cjs +17 -17
- package/dist/rsbuild.d.cts +5 -5
- package/dist/rsbuild.d.ts +5 -5
- package/dist/rsbuild.js +8 -8
- package/dist/server.cjs +2 -2
- package/dist/server.d.cts +8 -8
- package/dist/server.d.ts +8 -8
- package/dist/server.js +1 -1
- package/dist/{types-BgpcN3jm.d.cts → types-Aw0AciTG.d.cts} +5 -5
- package/dist/{types-BgpcN3jm.d.ts → types-Aw0AciTG.d.ts} +5 -5
- package/package.json +20 -20
|
@@ -1,3 +1,197 @@
|
|
|
1
|
+
// src/core/transform.ts
|
|
2
|
+
import {
|
|
3
|
+
isEmptyObject,
|
|
4
|
+
isFunction,
|
|
5
|
+
isObject as isObject2,
|
|
6
|
+
sortBy,
|
|
7
|
+
toArray
|
|
8
|
+
} from "@pengzhanbo/utils";
|
|
9
|
+
|
|
10
|
+
// src/core/utils.ts
|
|
11
|
+
import fs from "fs";
|
|
12
|
+
import os from "os";
|
|
13
|
+
import path from "path";
|
|
14
|
+
import { parse as queryParse } from "querystring";
|
|
15
|
+
import { fileURLToPath, URL as URL2 } from "url";
|
|
16
|
+
import Debug from "debug";
|
|
17
|
+
import { createFsFromVolume, Volume } from "memfs";
|
|
18
|
+
import { match } from "path-to-regexp";
|
|
19
|
+
var packageDir = getDirname(import.meta.url);
|
|
20
|
+
var vfs = createFsFromVolume(new Volume());
|
|
21
|
+
function isStream(stream) {
|
|
22
|
+
return stream !== null && typeof stream === "object" && typeof stream.pipe === "function";
|
|
23
|
+
}
|
|
24
|
+
function isReadableStream(stream) {
|
|
25
|
+
return isStream(stream) && stream.readable !== false && typeof stream._read === "function" && typeof stream._readableState === "object";
|
|
26
|
+
}
|
|
27
|
+
function getDirname(importMetaUrl) {
|
|
28
|
+
return path.dirname(fileURLToPath(importMetaUrl));
|
|
29
|
+
}
|
|
30
|
+
var debug = Debug("rspack:mock");
|
|
31
|
+
function lookupFile(dir, formats, options) {
|
|
32
|
+
for (const format of formats) {
|
|
33
|
+
const fullPath = path.join(dir, format);
|
|
34
|
+
if (fs.existsSync(fullPath) && fs.statSync(fullPath).isFile()) {
|
|
35
|
+
const result = options?.pathOnly ? fullPath : fs.readFileSync(fullPath, "utf-8");
|
|
36
|
+
if (!options?.predicate || options.predicate(result))
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const parentDir = path.dirname(dir);
|
|
41
|
+
if (parentDir !== dir && (!options?.rootDir || parentDir.startsWith(options?.rootDir))) {
|
|
42
|
+
return lookupFile(parentDir, formats, options);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function doesProxyContextMatchUrl(context, url, req) {
|
|
46
|
+
if (typeof context === "function") {
|
|
47
|
+
return context(url, req);
|
|
48
|
+
}
|
|
49
|
+
return context[0] === "^" && new RegExp(context).test(url) || url.startsWith(context);
|
|
50
|
+
}
|
|
51
|
+
function parseParams(pattern, url) {
|
|
52
|
+
const urlMatch = match(pattern, { decode: decodeURIComponent })(url) || {
|
|
53
|
+
params: {}
|
|
54
|
+
};
|
|
55
|
+
return urlMatch.params || {};
|
|
56
|
+
}
|
|
57
|
+
function urlParse(input) {
|
|
58
|
+
const url = new URL2(input, "http://example.com");
|
|
59
|
+
const pathname = decodeURIComponent(url.pathname);
|
|
60
|
+
const query = queryParse(url.search.replace(/^\?/, ""));
|
|
61
|
+
return { pathname, query };
|
|
62
|
+
}
|
|
63
|
+
var windowsSlashRE = /\\/g;
|
|
64
|
+
var isWindows = os.platform() === "win32";
|
|
65
|
+
function slash(p) {
|
|
66
|
+
return p.replace(windowsSlashRE, "/");
|
|
67
|
+
}
|
|
68
|
+
function normalizePath(id) {
|
|
69
|
+
return path.posix.normalize(isWindows ? slash(id) : id);
|
|
70
|
+
}
|
|
71
|
+
function waitingFor(onSuccess, maxRetry = 5) {
|
|
72
|
+
return function wait(getter, retry = 0) {
|
|
73
|
+
const value = getter();
|
|
74
|
+
if (value) {
|
|
75
|
+
onSuccess(value);
|
|
76
|
+
} else if (retry < maxRetry) {
|
|
77
|
+
setTimeout(() => wait(getter, retry + 1), 100);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// src/core/validator.ts
|
|
83
|
+
import { isArray, isObject } from "@pengzhanbo/utils";
|
|
84
|
+
function validate(request, validator) {
|
|
85
|
+
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);
|
|
86
|
+
}
|
|
87
|
+
function isObjectSubset(source, target) {
|
|
88
|
+
if (!target)
|
|
89
|
+
return true;
|
|
90
|
+
for (const key in target) {
|
|
91
|
+
if (!isIncluded(source[key], target[key]))
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
function isIncluded(source, target) {
|
|
97
|
+
if (isArray(source) && isArray(target)) {
|
|
98
|
+
const seen = /* @__PURE__ */ new Set();
|
|
99
|
+
return target.every(
|
|
100
|
+
(ti) => source.some((si, i) => {
|
|
101
|
+
if (seen.has(i))
|
|
102
|
+
return false;
|
|
103
|
+
const included = isIncluded(si, ti);
|
|
104
|
+
if (included)
|
|
105
|
+
seen.add(i);
|
|
106
|
+
return included;
|
|
107
|
+
})
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
if (isObject(source) && isObject(target))
|
|
111
|
+
return isObjectSubset(source, target);
|
|
112
|
+
return Object.is(source, target);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// src/core/transform.ts
|
|
116
|
+
function transformRawData(rawData) {
|
|
117
|
+
return rawData.filter((item) => item[0]).map(([raw, __filepath__]) => {
|
|
118
|
+
let mockConfig;
|
|
119
|
+
if (raw.default) {
|
|
120
|
+
if (Array.isArray(raw.default)) {
|
|
121
|
+
mockConfig = raw.default.map((item) => ({ ...item, __filepath__ }));
|
|
122
|
+
} else {
|
|
123
|
+
mockConfig = { ...raw.default, __filepath__ };
|
|
124
|
+
}
|
|
125
|
+
} else if ("url" in raw) {
|
|
126
|
+
mockConfig = { ...raw, __filepath__ };
|
|
127
|
+
} else {
|
|
128
|
+
mockConfig = [];
|
|
129
|
+
Object.keys(raw || {}).forEach((key) => {
|
|
130
|
+
if (Array.isArray(raw[key])) {
|
|
131
|
+
mockConfig.push(...raw[key].map((item) => ({ ...item, __filepath__ })));
|
|
132
|
+
} else {
|
|
133
|
+
mockConfig.push({ ...raw[key], __filepath__ });
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
return mockConfig;
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
function transformMockData(mockList) {
|
|
141
|
+
const list = [];
|
|
142
|
+
for (const [, handle] of mockList.entries()) {
|
|
143
|
+
if (handle)
|
|
144
|
+
list.push(...toArray(handle));
|
|
145
|
+
}
|
|
146
|
+
const mocks = {};
|
|
147
|
+
list.filter((mock) => isObject2(mock) && mock.enabled !== false && mock.url).forEach((mock) => {
|
|
148
|
+
const { pathname, query } = urlParse(mock.url);
|
|
149
|
+
const list2 = mocks[pathname] ??= [];
|
|
150
|
+
const current = { ...mock, url: pathname };
|
|
151
|
+
if (current.ws !== true) {
|
|
152
|
+
const validator = current.validator;
|
|
153
|
+
if (!isEmptyObject(query)) {
|
|
154
|
+
if (isFunction(validator)) {
|
|
155
|
+
current.validator = function(request) {
|
|
156
|
+
return isObjectSubset(request.query, query) && validator(request);
|
|
157
|
+
};
|
|
158
|
+
} else if (validator) {
|
|
159
|
+
current.validator = { ...validator };
|
|
160
|
+
current.validator.query = current.validator.query ? { ...query, ...current.validator.query } : query;
|
|
161
|
+
} else {
|
|
162
|
+
current.validator = { query };
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
list2.push(current);
|
|
167
|
+
});
|
|
168
|
+
Object.keys(mocks).forEach((key) => {
|
|
169
|
+
mocks[key] = sortByValidator(mocks[key]);
|
|
170
|
+
});
|
|
171
|
+
return mocks;
|
|
172
|
+
}
|
|
173
|
+
function sortByValidator(mocks) {
|
|
174
|
+
return sortBy(mocks, (item) => {
|
|
175
|
+
if (item.ws === true)
|
|
176
|
+
return 0;
|
|
177
|
+
const { validator } = item;
|
|
178
|
+
if (!validator || isEmptyObject(validator))
|
|
179
|
+
return 2;
|
|
180
|
+
if (isFunction(validator))
|
|
181
|
+
return 0;
|
|
182
|
+
const count = Object.keys(validator).reduce(
|
|
183
|
+
(prev, key) => prev + keysCount(validator[key]),
|
|
184
|
+
0
|
|
185
|
+
);
|
|
186
|
+
return 1 / count;
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
function keysCount(obj) {
|
|
190
|
+
if (!obj)
|
|
191
|
+
return 0;
|
|
192
|
+
return Object.keys(obj).length;
|
|
193
|
+
}
|
|
194
|
+
|
|
1
195
|
// src/core/requestRecovery.ts
|
|
2
196
|
import { Buffer } from "buffer";
|
|
3
197
|
var requestCollectCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -26,8 +220,8 @@ function rewriteRequest(proxyReq, req) {
|
|
|
26
220
|
import { Buffer as Buffer2 } from "buffer";
|
|
27
221
|
import {
|
|
28
222
|
isArray as isArray3,
|
|
29
|
-
isEmptyObject as
|
|
30
|
-
isFunction,
|
|
223
|
+
isEmptyObject as isEmptyObject3,
|
|
224
|
+
isFunction as isFunction2,
|
|
31
225
|
random,
|
|
32
226
|
sleep,
|
|
33
227
|
timestamp
|
|
@@ -40,10 +234,10 @@ import colors from "picocolors";
|
|
|
40
234
|
|
|
41
235
|
// src/core/matchingWeight.ts
|
|
42
236
|
import {
|
|
43
|
-
isArray,
|
|
44
|
-
isEmptyObject,
|
|
237
|
+
isArray as isArray2,
|
|
238
|
+
isEmptyObject as isEmptyObject2,
|
|
45
239
|
isString,
|
|
46
|
-
sortBy,
|
|
240
|
+
sortBy as sortBy2,
|
|
47
241
|
uniq
|
|
48
242
|
} from "@pengzhanbo/utils";
|
|
49
243
|
import { parse, pathToRegexp } from "path-to-regexp";
|
|
@@ -95,12 +289,12 @@ function preSort(rules) {
|
|
|
95
289
|
preMatch[len].push(rule);
|
|
96
290
|
}
|
|
97
291
|
for (const match2 of preMatch.filter((v) => v && v.length > 0))
|
|
98
|
-
matched = [...matched, ...
|
|
292
|
+
matched = [...matched, ...sortBy2(match2, sortFn).reverse()];
|
|
99
293
|
return matched;
|
|
100
294
|
}
|
|
101
295
|
function defaultPriority(rules) {
|
|
102
296
|
const highest = getHighest(rules);
|
|
103
|
-
return
|
|
297
|
+
return sortBy2(rules, (rule) => {
|
|
104
298
|
const tokens = getTokens(rule);
|
|
105
299
|
const dym = tokens.filter((token) => typeof token !== "string");
|
|
106
300
|
if (dym.length === 0)
|
|
@@ -148,14 +342,14 @@ function matchingWeight(rules, url, priority) {
|
|
|
148
342
|
preSort(rules.filter((rule) => pathToRegexp(rule).test(url)))
|
|
149
343
|
);
|
|
150
344
|
const { global = [], special = {} } = priority;
|
|
151
|
-
if (global.length === 0 &&
|
|
345
|
+
if (global.length === 0 && isEmptyObject2(special) || matched.length === 0)
|
|
152
346
|
return matched;
|
|
153
347
|
const [statics, dynamics] = twoPartMatch(matched);
|
|
154
348
|
const globalMatch = global.filter((rule) => dynamics.includes(rule));
|
|
155
349
|
if (globalMatch.length > 0) {
|
|
156
350
|
matched = uniq([...statics, ...globalMatch, ...dynamics]);
|
|
157
351
|
}
|
|
158
|
-
if (
|
|
352
|
+
if (isEmptyObject2(special))
|
|
159
353
|
return matched;
|
|
160
354
|
const specialRule = Object.keys(special).filter(
|
|
161
355
|
(rule) => matched.includes(rule)
|
|
@@ -163,7 +357,7 @@ function matchingWeight(rules, url, priority) {
|
|
|
163
357
|
if (!specialRule)
|
|
164
358
|
return matched;
|
|
165
359
|
const options = special[specialRule];
|
|
166
|
-
const { rules: lowerRules, when } =
|
|
360
|
+
const { rules: lowerRules, when } = isArray2(options) ? { rules: options, when: [] } : options;
|
|
167
361
|
if (lowerRules.includes(matched[0])) {
|
|
168
362
|
if (when.length === 0 || when.some((path2) => pathToRegexp(path2).test(url))) {
|
|
169
363
|
matched = uniq([specialRule, ...matched]);
|
|
@@ -232,111 +426,6 @@ async function parseMultipart(req, options) {
|
|
|
232
426
|
});
|
|
233
427
|
}
|
|
234
428
|
|
|
235
|
-
// src/core/utils.ts
|
|
236
|
-
import fs from "fs";
|
|
237
|
-
import path from "path";
|
|
238
|
-
import { parse as queryParse } from "querystring";
|
|
239
|
-
import { URL as URL2, fileURLToPath } from "url";
|
|
240
|
-
import os from "os";
|
|
241
|
-
import Debug from "debug";
|
|
242
|
-
import { match } from "path-to-regexp";
|
|
243
|
-
import { Volume, createFsFromVolume } from "memfs";
|
|
244
|
-
var packageDir = getDirname(import.meta.url);
|
|
245
|
-
var vfs = createFsFromVolume(new Volume());
|
|
246
|
-
function isStream(stream) {
|
|
247
|
-
return stream !== null && typeof stream === "object" && typeof stream.pipe === "function";
|
|
248
|
-
}
|
|
249
|
-
function isReadableStream(stream) {
|
|
250
|
-
return isStream(stream) && stream.readable !== false && typeof stream._read === "function" && typeof stream._readableState === "object";
|
|
251
|
-
}
|
|
252
|
-
function getDirname(importMetaUrl) {
|
|
253
|
-
return path.dirname(fileURLToPath(importMetaUrl));
|
|
254
|
-
}
|
|
255
|
-
var debug = Debug("rspack:mock");
|
|
256
|
-
function lookupFile(dir, formats, options) {
|
|
257
|
-
for (const format of formats) {
|
|
258
|
-
const fullPath = path.join(dir, format);
|
|
259
|
-
if (fs.existsSync(fullPath) && fs.statSync(fullPath).isFile()) {
|
|
260
|
-
const result = options?.pathOnly ? fullPath : fs.readFileSync(fullPath, "utf-8");
|
|
261
|
-
if (!options?.predicate || options.predicate(result))
|
|
262
|
-
return result;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
const parentDir = path.dirname(dir);
|
|
266
|
-
if (parentDir !== dir && (!options?.rootDir || parentDir.startsWith(options?.rootDir))) {
|
|
267
|
-
return lookupFile(parentDir, formats, options);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
function doesProxyContextMatchUrl(context, url, req) {
|
|
271
|
-
if (typeof context === "function") {
|
|
272
|
-
return context(url, req);
|
|
273
|
-
}
|
|
274
|
-
return context[0] === "^" && new RegExp(context).test(url) || url.startsWith(context);
|
|
275
|
-
}
|
|
276
|
-
function parseParams(pattern, url) {
|
|
277
|
-
const urlMatch = match(pattern, { decode: decodeURIComponent })(url) || {
|
|
278
|
-
params: {}
|
|
279
|
-
};
|
|
280
|
-
return urlMatch.params || {};
|
|
281
|
-
}
|
|
282
|
-
function urlParse(input) {
|
|
283
|
-
const url = new URL2(input, "http://example.com");
|
|
284
|
-
const pathname = decodeURIComponent(url.pathname);
|
|
285
|
-
const query = queryParse(url.search.replace(/^\?/, ""));
|
|
286
|
-
return { pathname, query };
|
|
287
|
-
}
|
|
288
|
-
var windowsSlashRE = /\\/g;
|
|
289
|
-
var isWindows = os.platform() === "win32";
|
|
290
|
-
function slash(p) {
|
|
291
|
-
return p.replace(windowsSlashRE, "/");
|
|
292
|
-
}
|
|
293
|
-
function normalizePath(id) {
|
|
294
|
-
return path.posix.normalize(isWindows ? slash(id) : id);
|
|
295
|
-
}
|
|
296
|
-
function waitingFor(onSuccess, maxRetry = 5) {
|
|
297
|
-
return function wait(getter, retry = 0) {
|
|
298
|
-
const value = getter();
|
|
299
|
-
if (value) {
|
|
300
|
-
onSuccess(value);
|
|
301
|
-
} else if (retry < maxRetry) {
|
|
302
|
-
setTimeout(() => wait(getter, retry + 1), 100);
|
|
303
|
-
}
|
|
304
|
-
};
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
// src/core/validator.ts
|
|
308
|
-
import { isArray as isArray2, isObject } from "@pengzhanbo/utils";
|
|
309
|
-
function validate(request, validator) {
|
|
310
|
-
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);
|
|
311
|
-
}
|
|
312
|
-
function isObjectSubset(source, target) {
|
|
313
|
-
if (!target)
|
|
314
|
-
return true;
|
|
315
|
-
for (const key in target) {
|
|
316
|
-
if (!isIncluded(source[key], target[key]))
|
|
317
|
-
return false;
|
|
318
|
-
}
|
|
319
|
-
return true;
|
|
320
|
-
}
|
|
321
|
-
function isIncluded(source, target) {
|
|
322
|
-
if (isArray2(source) && isArray2(target)) {
|
|
323
|
-
const seen = /* @__PURE__ */ new Set();
|
|
324
|
-
return target.every(
|
|
325
|
-
(ti) => source.some((si, i) => {
|
|
326
|
-
if (seen.has(i))
|
|
327
|
-
return false;
|
|
328
|
-
const included = isIncluded(si, ti);
|
|
329
|
-
if (included)
|
|
330
|
-
seen.add(i);
|
|
331
|
-
return included;
|
|
332
|
-
})
|
|
333
|
-
);
|
|
334
|
-
}
|
|
335
|
-
if (isObject(source) && isObject(target))
|
|
336
|
-
return isObjectSubset(source, target);
|
|
337
|
-
return Object.is(source, target);
|
|
338
|
-
}
|
|
339
|
-
|
|
340
429
|
// src/core/baseMiddleware.ts
|
|
341
430
|
function baseMiddleware(compiler, {
|
|
342
431
|
formidableOptions = {},
|
|
@@ -425,7 +514,7 @@ function baseMiddleware(compiler, {
|
|
|
425
514
|
);
|
|
426
515
|
if (body) {
|
|
427
516
|
try {
|
|
428
|
-
const content =
|
|
517
|
+
const content = isFunction2(body) ? await body(request) : body;
|
|
429
518
|
await realDelay(startTime, delay);
|
|
430
519
|
sendData(response, content, type);
|
|
431
520
|
} catch (e) {
|
|
@@ -477,7 +566,7 @@ function fineMock(mockList, logger, {
|
|
|
477
566
|
const hasMock = pathToRegexp2(mock.url).test(pathname);
|
|
478
567
|
if (hasMock && mock.validator) {
|
|
479
568
|
const params = parseParams(mock.url, pathname);
|
|
480
|
-
if (
|
|
569
|
+
if (isFunction2(mock.validator)) {
|
|
481
570
|
return mock.validator({ params, ...request });
|
|
482
571
|
} else {
|
|
483
572
|
try {
|
|
@@ -516,7 +605,7 @@ async function provideHeaders(req, res, mock, logger) {
|
|
|
516
605
|
if (!headers)
|
|
517
606
|
return;
|
|
518
607
|
try {
|
|
519
|
-
const raw =
|
|
608
|
+
const raw = isFunction2(headers) ? await headers(req) : headers;
|
|
520
609
|
Object.keys(raw).forEach((key) => {
|
|
521
610
|
res.setHeader(key, raw[key]);
|
|
522
611
|
});
|
|
@@ -537,7 +626,7 @@ async function provideCookies(req, res, mock, logger) {
|
|
|
537
626
|
if (!cookies)
|
|
538
627
|
return;
|
|
539
628
|
try {
|
|
540
|
-
const raw =
|
|
629
|
+
const raw = isFunction2(cookies) ? await cookies(req) : cookies;
|
|
541
630
|
Object.keys(raw).forEach((key) => {
|
|
542
631
|
const cookie = raw[key];
|
|
543
632
|
if (isArray3(cookie)) {
|
|
@@ -590,7 +679,7 @@ function requestLog(request, filepath) {
|
|
|
590
679
|
let { pathname } = new URL(url, "http://example.com");
|
|
591
680
|
pathname = colors.green(decodeURIComponent(pathname));
|
|
592
681
|
const format = (prefix, data) => {
|
|
593
|
-
return !data ||
|
|
682
|
+
return !data || isEmptyObject3(data) ? "" : ` ${colors.gray(`${prefix}:`)}${JSON.stringify(data)}`;
|
|
594
683
|
};
|
|
595
684
|
const ms = colors.magenta(colors.bold(method));
|
|
596
685
|
const qs = format("query", query);
|
|
@@ -600,138 +689,10 @@ function requestLog(request, filepath) {
|
|
|
600
689
|
return `${ms} ${pathname}${qs}${ps}${bs}${file}`;
|
|
601
690
|
}
|
|
602
691
|
|
|
603
|
-
// src/core/logger.ts
|
|
604
|
-
import { isBoolean } from "@pengzhanbo/utils";
|
|
605
|
-
import colors2 from "picocolors";
|
|
606
|
-
var logLevels = {
|
|
607
|
-
silent: 0,
|
|
608
|
-
error: 1,
|
|
609
|
-
warn: 2,
|
|
610
|
-
info: 3,
|
|
611
|
-
debug: 4
|
|
612
|
-
};
|
|
613
|
-
function createLogger(prefix, defaultLevel = "info") {
|
|
614
|
-
prefix = `[${prefix}]`;
|
|
615
|
-
function output(type, msg, level) {
|
|
616
|
-
level = isBoolean(level) ? level ? defaultLevel : "error" : level;
|
|
617
|
-
const thresh = logLevels[level];
|
|
618
|
-
if (thresh >= logLevels[type]) {
|
|
619
|
-
const method = type === "info" || type === "debug" ? "log" : type;
|
|
620
|
-
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));
|
|
621
|
-
const format = `${colors2.dim(
|
|
622
|
-
(/* @__PURE__ */ new Date()).toLocaleTimeString()
|
|
623
|
-
)} ${tag} ${msg}`;
|
|
624
|
-
console[method](format);
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
const logger = {
|
|
628
|
-
debug(msg, level = defaultLevel) {
|
|
629
|
-
output("debug", msg, level);
|
|
630
|
-
},
|
|
631
|
-
info(msg, level = defaultLevel) {
|
|
632
|
-
output("info", msg, level);
|
|
633
|
-
},
|
|
634
|
-
warn(msg, level = defaultLevel) {
|
|
635
|
-
output("warn", msg, level);
|
|
636
|
-
},
|
|
637
|
-
error(msg, level = defaultLevel) {
|
|
638
|
-
output("error", msg, level);
|
|
639
|
-
}
|
|
640
|
-
};
|
|
641
|
-
return logger;
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
// src/core/transform.ts
|
|
645
|
-
import {
|
|
646
|
-
isEmptyObject as isEmptyObject3,
|
|
647
|
-
isFunction as isFunction2,
|
|
648
|
-
isObject as isObject2,
|
|
649
|
-
sortBy as sortBy2,
|
|
650
|
-
toArray
|
|
651
|
-
} from "@pengzhanbo/utils";
|
|
652
|
-
function transformRawData(rawData) {
|
|
653
|
-
return rawData.filter((item) => item[0]).map(([raw, __filepath__]) => {
|
|
654
|
-
let mockConfig;
|
|
655
|
-
if (raw.default) {
|
|
656
|
-
if (Array.isArray(raw.default)) {
|
|
657
|
-
mockConfig = raw.default.map((item) => ({ ...item, __filepath__ }));
|
|
658
|
-
} else {
|
|
659
|
-
mockConfig = { ...raw.default, __filepath__ };
|
|
660
|
-
}
|
|
661
|
-
} else if ("url" in raw) {
|
|
662
|
-
mockConfig = { ...raw, __filepath__ };
|
|
663
|
-
} else {
|
|
664
|
-
mockConfig = [];
|
|
665
|
-
Object.keys(raw || {}).forEach((key) => {
|
|
666
|
-
if (Array.isArray(raw[key])) {
|
|
667
|
-
mockConfig.push(...raw[key].map((item) => ({ ...item, __filepath__ })));
|
|
668
|
-
} else {
|
|
669
|
-
mockConfig.push({ ...raw[key], __filepath__ });
|
|
670
|
-
}
|
|
671
|
-
});
|
|
672
|
-
}
|
|
673
|
-
return mockConfig;
|
|
674
|
-
});
|
|
675
|
-
}
|
|
676
|
-
function transformMockData(mockList) {
|
|
677
|
-
const list = [];
|
|
678
|
-
for (const [, handle] of mockList.entries()) {
|
|
679
|
-
if (handle)
|
|
680
|
-
list.push(...toArray(handle));
|
|
681
|
-
}
|
|
682
|
-
const mocks = {};
|
|
683
|
-
list.filter((mock) => isObject2(mock) && mock.enabled !== false && mock.url).forEach((mock) => {
|
|
684
|
-
const { pathname, query } = urlParse(mock.url);
|
|
685
|
-
const list2 = mocks[pathname] ??= [];
|
|
686
|
-
const current = { ...mock, url: pathname };
|
|
687
|
-
if (current.ws !== true) {
|
|
688
|
-
const validator = current.validator;
|
|
689
|
-
if (!isEmptyObject3(query)) {
|
|
690
|
-
if (isFunction2(validator)) {
|
|
691
|
-
current.validator = function(request) {
|
|
692
|
-
return isObjectSubset(request.query, query) && validator(request);
|
|
693
|
-
};
|
|
694
|
-
} else if (validator) {
|
|
695
|
-
current.validator = { ...validator };
|
|
696
|
-
current.validator.query = current.validator.query ? { ...query, ...current.validator.query } : query;
|
|
697
|
-
} else {
|
|
698
|
-
current.validator = { query };
|
|
699
|
-
}
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
list2.push(current);
|
|
703
|
-
});
|
|
704
|
-
Object.keys(mocks).forEach((key) => {
|
|
705
|
-
mocks[key] = sortByValidator(mocks[key]);
|
|
706
|
-
});
|
|
707
|
-
return mocks;
|
|
708
|
-
}
|
|
709
|
-
function sortByValidator(mocks) {
|
|
710
|
-
return sortBy2(mocks, (item) => {
|
|
711
|
-
if (item.ws === true)
|
|
712
|
-
return 0;
|
|
713
|
-
const { validator } = item;
|
|
714
|
-
if (!validator || isEmptyObject3(validator))
|
|
715
|
-
return 2;
|
|
716
|
-
if (isFunction2(validator))
|
|
717
|
-
return 0;
|
|
718
|
-
const count = Object.keys(validator).reduce(
|
|
719
|
-
(prev, key) => prev + keysCount(validator[key]),
|
|
720
|
-
0
|
|
721
|
-
);
|
|
722
|
-
return 1 / count;
|
|
723
|
-
});
|
|
724
|
-
}
|
|
725
|
-
function keysCount(obj) {
|
|
726
|
-
if (!obj)
|
|
727
|
-
return 0;
|
|
728
|
-
return Object.keys(obj).length;
|
|
729
|
-
}
|
|
730
|
-
|
|
731
692
|
// src/core/mockWebsocket.ts
|
|
732
693
|
import Cookies2 from "cookies";
|
|
733
694
|
import { pathToRegexp as pathToRegexp3 } from "path-to-regexp";
|
|
734
|
-
import
|
|
695
|
+
import colors2 from "picocolors";
|
|
735
696
|
import { WebSocketServer } from "ws";
|
|
736
697
|
function mockWebSocket(compiler, httpServer, {
|
|
737
698
|
wsProxies: proxies,
|
|
@@ -747,12 +708,6 @@ function mockWebSocket(compiler, httpServer, {
|
|
|
747
708
|
poolMap.set(mockUrl, wssMap = /* @__PURE__ */ new Map());
|
|
748
709
|
return wssMap;
|
|
749
710
|
};
|
|
750
|
-
const getWss = (wssMap, pathname) => {
|
|
751
|
-
let wss = wssMap.get(pathname);
|
|
752
|
-
if (!wss)
|
|
753
|
-
wssMap.set(pathname, wss = new WebSocketServer({ noServer: true }));
|
|
754
|
-
return wss;
|
|
755
|
-
};
|
|
756
711
|
const addHmr = (filepath, mockUrl) => {
|
|
757
712
|
let urlList = hmrMap.get(filepath);
|
|
758
713
|
if (!urlList)
|
|
@@ -765,7 +720,7 @@ function mockWebSocket(compiler, httpServer, {
|
|
|
765
720
|
wss.on("close", () => wssMap.delete(pathname));
|
|
766
721
|
wss.on("error", (e) => {
|
|
767
722
|
logger.error(
|
|
768
|
-
`${
|
|
723
|
+
`${colors2.red(
|
|
769
724
|
`WebSocket mock error at ${wss.path}`
|
|
770
725
|
)}
|
|
771
726
|
${e}
|
|
@@ -775,7 +730,7 @@ ${e}
|
|
|
775
730
|
});
|
|
776
731
|
} catch (e) {
|
|
777
732
|
logger.error(
|
|
778
|
-
`${
|
|
733
|
+
`${colors2.red(
|
|
779
734
|
`WebSocket mock error at ${wss.path}`
|
|
780
735
|
)}
|
|
781
736
|
${e}
|
|
@@ -784,14 +739,6 @@ ${e}
|
|
|
784
739
|
);
|
|
785
740
|
}
|
|
786
741
|
};
|
|
787
|
-
const emitConnection = (wss, ws, req, connectionList) => {
|
|
788
|
-
wss.emit("connection", ws, req);
|
|
789
|
-
ws.on("close", () => {
|
|
790
|
-
const i = connectionList.findIndex((item) => item.ws === ws);
|
|
791
|
-
if (i !== -1)
|
|
792
|
-
connectionList.splice(i, 1);
|
|
793
|
-
});
|
|
794
|
-
};
|
|
795
742
|
const restartWss = (wssMap, wss, mock, pathname, filepath) => {
|
|
796
743
|
const { cleanupList, connectionList, context } = wssContextMap.get(wss);
|
|
797
744
|
cleanupRunner(cleanupList);
|
|
@@ -857,9 +804,9 @@ ${e}
|
|
|
857
804
|
request.getCookie = cookies.get.bind(cookies);
|
|
858
805
|
wss.handleUpgrade(request, socket, head, (ws) => {
|
|
859
806
|
logger.info(
|
|
860
|
-
`${
|
|
807
|
+
`${colors2.magenta(colors2.bold("WebSocket"))} ${colors2.green(
|
|
861
808
|
req.url
|
|
862
|
-
)} connected ${
|
|
809
|
+
)} connected ${colors2.dim(`(${filepath})`)}`,
|
|
863
810
|
mock.log
|
|
864
811
|
);
|
|
865
812
|
wssContext.connectionList.push({ req: request, ws });
|
|
@@ -879,12 +826,67 @@ ${e}
|
|
|
879
826
|
hmrMap.clear();
|
|
880
827
|
});
|
|
881
828
|
}
|
|
829
|
+
function getWss(wssMap, pathname) {
|
|
830
|
+
let wss = wssMap.get(pathname);
|
|
831
|
+
if (!wss)
|
|
832
|
+
wssMap.set(pathname, wss = new WebSocketServer({ noServer: true }));
|
|
833
|
+
return wss;
|
|
834
|
+
}
|
|
835
|
+
function emitConnection(wss, ws, req, connectionList) {
|
|
836
|
+
wss.emit("connection", ws, req);
|
|
837
|
+
ws.on("close", () => {
|
|
838
|
+
const i = connectionList.findIndex((item) => item.ws === ws);
|
|
839
|
+
if (i !== -1)
|
|
840
|
+
connectionList.splice(i, 1);
|
|
841
|
+
});
|
|
842
|
+
}
|
|
882
843
|
function cleanupRunner(cleanupList) {
|
|
883
844
|
let cleanup;
|
|
884
845
|
while (cleanup = cleanupList.shift())
|
|
885
846
|
cleanup?.();
|
|
886
847
|
}
|
|
887
848
|
|
|
849
|
+
// src/core/logger.ts
|
|
850
|
+
import { isBoolean } from "@pengzhanbo/utils";
|
|
851
|
+
import colors3 from "picocolors";
|
|
852
|
+
var logLevels = {
|
|
853
|
+
silent: 0,
|
|
854
|
+
error: 1,
|
|
855
|
+
warn: 2,
|
|
856
|
+
info: 3,
|
|
857
|
+
debug: 4
|
|
858
|
+
};
|
|
859
|
+
function createLogger(prefix, defaultLevel = "info") {
|
|
860
|
+
prefix = `[${prefix}]`;
|
|
861
|
+
function output(type, msg, level) {
|
|
862
|
+
level = isBoolean(level) ? level ? defaultLevel : "error" : level;
|
|
863
|
+
const thresh = logLevels[level];
|
|
864
|
+
if (thresh >= logLevels[type]) {
|
|
865
|
+
const method = type === "info" || type === "debug" ? "log" : type;
|
|
866
|
+
const tag = type === "debug" ? colors3.magenta(colors3.bold(prefix)) : type === "info" ? colors3.cyan(colors3.bold(prefix)) : type === "warn" ? colors3.yellow(colors3.bold(prefix)) : colors3.red(colors3.bold(prefix));
|
|
867
|
+
const format = `${colors3.dim(
|
|
868
|
+
(/* @__PURE__ */ new Date()).toLocaleTimeString()
|
|
869
|
+
)} ${tag} ${msg}`;
|
|
870
|
+
console[method](format);
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
const logger = {
|
|
874
|
+
debug(msg, level = defaultLevel) {
|
|
875
|
+
output("debug", msg, level);
|
|
876
|
+
},
|
|
877
|
+
info(msg, level = defaultLevel) {
|
|
878
|
+
output("info", msg, level);
|
|
879
|
+
},
|
|
880
|
+
warn(msg, level = defaultLevel) {
|
|
881
|
+
output("warn", msg, level);
|
|
882
|
+
},
|
|
883
|
+
error(msg, level = defaultLevel) {
|
|
884
|
+
output("error", msg, level);
|
|
885
|
+
}
|
|
886
|
+
};
|
|
887
|
+
return logger;
|
|
888
|
+
}
|
|
889
|
+
|
|
888
890
|
export {
|
|
889
891
|
packageDir,
|
|
890
892
|
vfs,
|
|
@@ -893,12 +895,12 @@ export {
|
|
|
893
895
|
urlParse,
|
|
894
896
|
normalizePath,
|
|
895
897
|
waitingFor,
|
|
896
|
-
rewriteRequest,
|
|
897
|
-
baseMiddleware,
|
|
898
|
-
logLevels,
|
|
899
|
-
createLogger,
|
|
900
898
|
transformRawData,
|
|
901
899
|
transformMockData,
|
|
902
900
|
sortByValidator,
|
|
903
|
-
|
|
901
|
+
rewriteRequest,
|
|
902
|
+
baseMiddleware,
|
|
903
|
+
mockWebSocket,
|
|
904
|
+
logLevels,
|
|
905
|
+
createLogger
|
|
904
906
|
};
|