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.
@@ -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 isEmptyObject2,
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, ...sortBy(match2, sortFn).reverse()];
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 sortBy(rules, (rule) => {
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 && isEmptyObject(special) || matched.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 (isEmptyObject(special))
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 } = isArray(options) ? { rules: options, when: [] } : options;
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 = isFunction(body) ? await body(request) : body;
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 (isFunction(mock.validator)) {
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 = isFunction(headers) ? await headers(req) : headers;
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 = isFunction(cookies) ? await cookies(req) : cookies;
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 || isEmptyObject2(data) ? "" : ` ${colors.gray(`${prefix}:`)}${JSON.stringify(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 colors3 from "picocolors";
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
- `${colors3.red(
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
- `${colors3.red(
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
- `${colors3.magenta(colors3.bold("WebSocket"))} ${colors3.green(
807
+ `${colors2.magenta(colors2.bold("WebSocket"))} ${colors2.green(
861
808
  req.url
862
- )} connected ${colors3.dim(`(${filepath})`)}`,
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
- mockWebSocket
901
+ rewriteRequest,
902
+ baseMiddleware,
903
+ mockWebSocket,
904
+ logLevels,
905
+ createLogger
904
906
  };