rspack-plugin-mock 1.1.0 → 1.3.0

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.
@@ -0,0 +1,701 @@
1
+ import { Readable } from "node:stream";
2
+ import { CorsOptions } from "cors";
3
+ import { Options } from "co-body";
4
+ import formidable from "formidable";
5
+ import http, { IncomingMessage, ServerResponse } from "node:http";
6
+ import crypto from "node:crypto";
7
+ import { Buffer } from "node:buffer";
8
+ import { WebSocketServer } from "ws";
9
+
10
+ //#region src/cookies/Keygrip.d.ts
11
+ declare class Keygrip {
12
+ private algorithm;
13
+ private encoding;
14
+ private keys;
15
+ constructor(keys: string[], algorithm?: string, encoding?: crypto.BinaryToTextEncoding);
16
+ sign(data: string, key?: string): string;
17
+ index(data: string, digest: string): number;
18
+ verify(data: string, digest: string): boolean;
19
+ }
20
+ //#endregion
21
+ //#region src/cookies/types.d.ts
22
+ interface CookiesOption {
23
+ keys?: string[] | Keygrip;
24
+ secure?: boolean;
25
+ }
26
+ interface SetCookieOption {
27
+ /**
28
+ * a number representing the milliseconds from `Date.now()` for expiry
29
+ *
30
+ * 表示从 `Date.now()` 起至过期的毫秒数
31
+ */
32
+ maxAge?: number;
33
+ /**
34
+ * a Date object indicating the cookie's expiration
35
+ * date (expires at the end of session by default).
36
+ *
37
+ * 一个指示cookie过期时间的 Date 对象(默认在会话结束时过期)。
38
+ */
39
+ expires?: Date;
40
+ /**
41
+ * a string indicating the path of the cookie (`/` by default).
42
+ *
43
+ * 一个指示cookie路径的字符串(默认为 `/`)。
44
+ */
45
+ path?: string;
46
+ /**
47
+ * a string indicating the domain of the cookie (no default).
48
+ *
49
+ * 表示 Cookie 域的字符串(无默认值)。
50
+ */
51
+ domain?: string;
52
+ /**
53
+ * a boolean indicating whether the cookie is only to be sent
54
+ * over HTTPS (false by default for HTTP, true by default for HTTPS).
55
+ *
56
+ * 一个布尔值,指示该 Cookie 是否仅通过 HTTPS 发送(HTTP 默认为 false,HTTPS 默认为 true)。
57
+ */
58
+ secure?: boolean;
59
+ /**
60
+ * a boolean indicating whether the cookie is only to be sent over HTTP(S),
61
+ * and not made available to client JavaScript (true by default).
62
+ *
63
+ * 一个布尔值,指示该 cookie 是否仅通过HTTP(S)发送,而不对客户端JavaScript开放(默认为true)。
64
+ */
65
+ httpOnly?: boolean;
66
+ /**
67
+ * a boolean or string indicating whether the cookie is a "same site" cookie (false by default).
68
+ * This can be set to 'strict', 'lax', or true (which maps to 'strict').
69
+ *
70
+ * 一个布尔值或字符串,用于指示该cookie是否为“同站”cookie(默认为false)。
71
+ * 可将其设置为'strict'、'lax'或true(true会映射为'strict')。
72
+ */
73
+ sameSite?: "strict" | "lax" | "none" | boolean;
74
+ /**
75
+ * a boolean indicating whether the cookie is to be signed (false by default).
76
+ * If this is true, another cookie of the same name with the .sig suffix
77
+ * appended will also be sent, with a 27-byte url-safe base64 SHA1 value
78
+ * representing the hash of cookie-name=cookie-value against the first Keygrip key.
79
+ * This signature key is used to detect tampering the next time a cookie is received.
80
+ *
81
+ * 一个布尔值,指示cookie是否需签名(默认为false)。
82
+ * 若设为true,将同时发送另一个同名但附加 `.sig` 后缀的 cookie,其值为 27 字节的URL安全型 base64 SHA1哈希值,
83
+ * 该哈希由cookie名称=cookie值的字符串与首个 Keygrip 密钥计算生成。
84
+ * 此签名密钥用于在下次接收cookie时检测数据是否被篡改。
85
+ */
86
+ signed?: boolean;
87
+ /**
88
+ * a boolean indicating whether to overwrite previously set
89
+ * cookies of the same name (false by default). If this is true,
90
+ * all cookies set during the same request with the same
91
+ * name (regardless of path or domain) are filtered out of
92
+ * the Set-Cookie header when setting this cookie.
93
+ *
94
+ * 一个布尔值,指示是否覆盖先前设置的同名Cookie(默认为false)。
95
+ * 若设为true,当设置此Cookie时,在同一请求期间设置的所有同名Cookie(无论路径或域)
96
+ * 都将从Set-Cookie标头中过滤掉。
97
+ */
98
+ overwrite?: boolean;
99
+ /**
100
+ * a string indicating the cookie priority.
101
+ * This can be set to 'low', 'medium', or 'high'.
102
+ *
103
+ * 表示Cookie优先级的字符串。可设置为'low'、'medium'或'high'。
104
+ */
105
+ priority?: "low" | "medium" | "high";
106
+ /**
107
+ * a boolean indicating whether to partition the cookie in Chrome
108
+ * for the CHIPS Update (false by default). If this is true,
109
+ * Cookies from embedded sites will be partitioned
110
+ * and only readable from the same top level site from which it was created.
111
+ *
112
+ * 一个布尔值,指示是否在Chrome中为CHIPS更新对Cookie进行分区(默认为false)。
113
+ * 若设为true,来自嵌入式站点的Cookie将被分区,且仅可从创建它的同一顶级站点读取。
114
+ */
115
+ partitioned?: boolean;
116
+ }
117
+ interface GetCookieOption {
118
+ signed: boolean;
119
+ }
120
+ //#endregion
121
+ //#region src/cookies/Cookies.d.ts
122
+ declare class Cookies {
123
+ request: IncomingMessage;
124
+ response: ServerResponse<IncomingMessage>;
125
+ secure: boolean | undefined;
126
+ keys: Keygrip | undefined;
127
+ constructor(req: IncomingMessage, res: ServerResponse<IncomingMessage>, options?: CookiesOption);
128
+ set(name: string, value?: string | null, options?: SetCookieOption): this;
129
+ get(name: string, options?: GetCookieOption): string | void;
130
+ }
131
+ //#endregion
132
+ //#region src/types.d.ts
133
+ /**
134
+ * Configure plugin
135
+ *
136
+ * 插件配置项
137
+ */
138
+ interface MockServerPluginOptions {
139
+ /**
140
+ * To configure the path matching rules for http mock services,
141
+ * any request path starting with prefix will be intercepted and proxied.
142
+ * If the prefix starts with `^`, it will be recognized as a `RegExp`.
143
+ *
144
+ * 为 http mock 服务配置 路径匹配规则,任何请求路径以 prefix 开头的都将被拦截代理。
145
+ * 如果 prefix 以 `^` 开头,将被识别为 `RegExp`。
146
+ * @default []
147
+ * @example ['^/api']
148
+ */
149
+ prefix?: string | string[];
150
+ /**
151
+ * Configure path matching rules for WebSocket mock service.
152
+ * Any ws/wss requests with a request path starting with wsPrefix
153
+ * will be intercepted by the proxy.
154
+ * If wsPrefix starts with `^`, it will be recognized as a `RegExp`.
155
+ *
156
+ * 为 websocket mock 服务配置 路径匹配规则, 任何请求路径以 wsPrefix 开头的 ws/wss请求,
157
+ * 都将被代理拦截。
158
+ * 如果 wsPrefix 以 `^` 开头,将被识别为 `RegExp`。
159
+ * @default []
160
+ * @example ['/socket.io']
161
+ */
162
+ wsPrefix?: string | string[];
163
+ /**
164
+ * Configure the matching context for `include` and `exclude`.
165
+ *
166
+ * 配置 `include` 和 `exclude` 的匹配上下文
167
+ *
168
+ * @default process.cwd()
169
+ */
170
+ cwd?: string;
171
+ /**
172
+ * The directory to store mock files
173
+ *
174
+ * 存储 mock 文件的目录
175
+ *
176
+ * @default 'mock'
177
+ */
178
+ dir?: string;
179
+ /**
180
+ * glob string matching mock includes files
181
+ *
182
+ * glob 字符串匹配 mock 包含的文件
183
+ * @see [picomatch](https://github.com/micromatch/picomatch#globbing-features)
184
+ * @default []
185
+ */
186
+ include?: string | string[];
187
+ /**
188
+ * glob string matching mock excluded files
189
+ *
190
+ * glob 字符串匹配 mock 排除的文件
191
+ * @see [picomatch](https://github.com/micromatch/picomatch#globbing-features)
192
+ */
193
+ exclude?: string | string[];
194
+ /**
195
+ * Enable log and configure log level
196
+ *
197
+ * 开启日志,或配置 日志级别
198
+ * @default 'info'
199
+ */
200
+ log?: boolean | LogLevel;
201
+ /**
202
+ * When the mock resource is hot updated, only the data content is updated,
203
+ * but the page is not refreshed by default.
204
+ * If you want to refresh the page every time you modify a mock file,
205
+ * you can open this option.
206
+ *
207
+ * mock资源热更新时,仅更新了数据内容,但是默认不重新刷新页面。
208
+ * 当你希望每次修改mock文件都刷新页面时,可以打开此选项。
209
+ * @default false
210
+ */
211
+ reload?: boolean;
212
+ /**
213
+ * Configure to `cors`
214
+ *
215
+ * 配置 `cors`
216
+ * @default true
217
+ * @see [cors](https://github.com/expressjs/cors#configuration-options)
218
+ */
219
+ cors?: boolean | CorsOptions;
220
+ /**
221
+ * formidable options
222
+ * @see [formidable](https://github.com/node-formidable/formidable#options)
223
+ */
224
+ formidableOptions?: formidable.Options;
225
+ /**
226
+ * cookies options
227
+ * @see [cookies](https://github.com/pillarjs/cookies#new-cookiesrequest-response--options)
228
+ */
229
+ cookiesOptions?: CookiesOption;
230
+ /**
231
+ * Configure to `co-body`
232
+ *
233
+ * 配置 `co-body`
234
+ *
235
+ * @see [co-body](https://github.com/cojs/co-body#options)
236
+ */
237
+ bodyParserOptions?: BodyParserOptions;
238
+ /**
239
+ * When you need to build a small mock service, you can configure this option.
240
+ *
241
+ * 当需要构建一个小型mock服务时,可配置此项
242
+ * @default false
243
+ */
244
+ build?: boolean | ServerBuildOption;
245
+ /**
246
+ * Priority sorting for path matching rules is valid only for rules containing dynamic parameters.
247
+ * In most cases, the default sorting rules can meet the needs.
248
+ * However, in some cases where custom sorting rules are required, this option can be used.
249
+ *
250
+ * 路径匹配规则优先级排序,仅对包含动态参数的规则有效。
251
+ * 大部分情况下默认的排序规则都可以满足需求。
252
+ * 但有些情况下,需要自定义排序规则时,可以使用此选项。
253
+ *
254
+ * @example
255
+ * ```ts
256
+ * export default {
257
+ * priority: {
258
+ * global: ['/api/:a/b/c', '/api/a/:b/c', '/api/a/b/:c'],
259
+ * special: {
260
+ * '/api/:a/:b/c': {
261
+ * rules: ['/api/a/:b/:c', '/api/a/b/:c'],
262
+ * when: ['/api/a/b/c']
263
+ * }
264
+ * }
265
+ * }
266
+ * }
267
+ * ```
268
+ */
269
+ priority?: MockMatchPriority;
270
+ }
271
+ interface MockMatchPriority {
272
+ /**
273
+ * The priority of matching rules is global.
274
+ * The rules declared in this option will take priority over the default rules.
275
+ * The higher the position of the rule in the array, the higher the priority.
276
+ *
277
+ * Do not declare general rules in this option, such as /api/(.*),
278
+ * as it will prevent subsequent rules from taking effect.
279
+ * Unless you are clear about the priority of the rules,
280
+ * most of the time you do not need to configure this option.
281
+ *
282
+ * 匹配规则优先级, 全局生效。
283
+ * 声明在该选项中的规则将优先于默认规则生效。
284
+ * 规则在数组越靠前的位置,优先级越高。
285
+ *
286
+ * 不要在此选项中声明通用性的规则,比如 `/api/(.*)`,这将导致后续的规则无法生效。
287
+ * 除非你明确知道规则的优先级,否则大多数情况下都不需要配置该选项。
288
+ * @default []
289
+ */
290
+ global?: string[];
291
+ /**
292
+ * For some special cases where the priority of certain rules needs to be adjusted,
293
+ * this option can be used. For example, when a request matches both Rule A and Rule B,
294
+ * and Rule A has a higher priority than Rule B, but it is desired for Rule B to take effect.
295
+ *
296
+ * 对于一些特殊情况,需要调整部分规则的优先级,可以使用此选项。
297
+ * 比如一个请求同时命中了规则 A 和 B,且 A 比 B 优先级高, 但期望规则 B 生效时。
298
+ *
299
+ * @example
300
+ * ```ts
301
+ * {
302
+ * special: {
303
+ * // /api/a/:b/c 优先级将提升到 /api/a/b/:c 前面
304
+ * // The /api/a/:b/c priority is promoted to /api/a/b/:c
305
+ * '/api/a/:b/c': ['/api/a/b/:c'],
306
+ * // 仅在请求满足 /api/a/b/c 时生效
307
+ * // Only when the request satisfies /api/a/b/c
308
+ * '/api/:a/b/c': {
309
+ * rules: ['/api/a/:b/c'],
310
+ * when: ['/api/a/b/c']
311
+ * }
312
+ * }
313
+ * }
314
+ * ```
315
+ */
316
+ special?: MockMatchSpecialPriority;
317
+ }
318
+ interface MockMatchSpecialPriority {
319
+ /**
320
+ * When both A and B or C match, and B or C is at the top of the sort order,
321
+ * insert A into the top position.The `when` option is used to further constrain
322
+ * the priority adjustment to be effective only for certain requests.
323
+ *
324
+ * 当 A 与 B或 C 同时满足匹配,`B` 或 `C` 在排序首位时,将A插入到首位。
325
+ * when 选项用于进一步约束该优先级调整仅针对哪些请求有效。
326
+ *
327
+ * @example
328
+ * ```ts
329
+ * {
330
+ * A: ['B', 'C'],
331
+ * A: { rules: ['B', 'C'], when: ['/api/a/b/c'] }
332
+ * }
333
+ * ```
334
+ */
335
+ [key: string]: string[] | {
336
+ rules: string[];
337
+ when: string[];
338
+ };
339
+ }
340
+ type BodyParserOptions = Options & {
341
+ jsonLimit?: string | number;
342
+ formLimit?: string | number;
343
+ textLimit?: string | number;
344
+ };
345
+ interface ServerBuildOption {
346
+ /**
347
+ * Service startup port
348
+ *
349
+ * 服务启动端口
350
+ * @default 8080
351
+ */
352
+ serverPort?: number;
353
+ /**
354
+ * Service application output directory
355
+ *
356
+ * 服务应用输出目录
357
+ * @default 'dist/mockServer'
358
+ */
359
+ dist?: string;
360
+ /**
361
+ * Service application log level
362
+ *
363
+ * 服务应用日志级别
364
+ * @default 'error'
365
+ */
366
+ log?: LogLevel;
367
+ }
368
+ type Method = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "TRACE" | "OPTIONS";
369
+ type Headers = http.IncomingHttpHeaders;
370
+ type ResponseBody = Record<string, any> | any[] | string | number | Readable | Buffer | null;
371
+ /**
372
+ * 扩展 request,添加额外的属性和方法
373
+ */
374
+ interface ExtraRequest {
375
+ /**
376
+ * The query string located after `?` in the request address has been parsed into JSON.
377
+ *
378
+ * 请求地址中位于 `?` 后面的 queryString,已解析为 json
379
+ */
380
+ query: Record<string, any>;
381
+ /**
382
+ * The queryString located after `?` in the referer request has been parsed as JSON.
383
+ *
384
+ * 请求 referer 中位于 `?` 后面的 queryString,已解析为 json
385
+ */
386
+ refererQuery: Record<string, any>;
387
+ /**
388
+ * Body data in the request
389
+ *
390
+ * 请求体中 body 数据
391
+ */
392
+ body: Record<string, any>;
393
+ /**
394
+ * The params parameter parsed from the `/api/id/:id` in the request address.
395
+ *
396
+ * 请求地址中,`/api/id/:id` 解析后的 params 参数
397
+ */
398
+ params: Record<string, any>;
399
+ /**
400
+ * headers data in the request
401
+ * 请求体中 headers
402
+ */
403
+ headers: Headers;
404
+ /**
405
+ * Get the cookie carried in the request.
406
+ *
407
+ * 获取 请求中携带的 cookie
408
+ * @see [cookies](https://github.com/pillarjs/cookies#cookiesgetname--options)
409
+ */
410
+ getCookie: Cookies["get"];
411
+ }
412
+ type MockRequest = http.IncomingMessage & ExtraRequest;
413
+ type MockResponse = http.ServerResponse<http.IncomingMessage> & {
414
+ /**
415
+ * Set cookie in response
416
+ *
417
+ * 向请求响应中设置 cookie
418
+ * @see [cookies](https://github.com/pillarjs/cookies#cookiessetname--values--options)
419
+ */
420
+ setCookie: Cookies["set"];
421
+ };
422
+ type ResponseBodyFn = (request: MockRequest) => ResponseBody | Promise<ResponseBody>;
423
+ type ResponseHeaderFn = (request: MockRequest) => Headers | Promise<Headers>;
424
+ type CookieValue = string | [string, SetCookieOption];
425
+ type ResponseCookies = Record<string, CookieValue>;
426
+ type ResponseCookiesFn = (request: MockRequest) => ResponseCookies | Promise<ResponseCookies>;
427
+ interface MockBaseItem {
428
+ /**
429
+ * The interface address that needs to be mocked,
430
+ * supported by `path-to-regexp` for path matching.
431
+ *
432
+ * 需要进行 mock 的接口地址, 由 `path-to-regexp` 提供路径匹配支持
433
+ * @see [path-to-regexp](https://github.com/pillarjs/path-to-regexp)
434
+ * @example
435
+ * ```txt
436
+ * /api/login
437
+ * /api/post/:id
438
+ * /api/post/:id
439
+ * /api/anything/(.*)
440
+ * ```
441
+ */
442
+ url: string;
443
+ /**
444
+ * Enable WebSocket interface simulation
445
+ *
446
+ * 开启 websocket 接口模拟
447
+ *
448
+ * @default false
449
+ */
450
+ ws?: boolean;
451
+ /**
452
+ * Whether to enable mock for this interface.
453
+ * In most scenarios, we only need to mock some interfaces instead of all requests that
454
+ * have been configured with mock.
455
+ * Therefore, it is important to be able to configure whether to enable it or not.
456
+ *
457
+ * 是否启动对该接口的mock,在多数场景下,我们仅需要对部分接口进行 mock,
458
+ * 而不是对所有配置了mock的请求进行全量mock,所以是否能够配置是否启用很重要
459
+ * @default true
460
+ */
461
+ enabled?: boolean;
462
+ /**
463
+ * Enable log and configure log level
464
+ *
465
+ * 开启日志,或配置 日志级别
466
+ * @default 'info'
467
+ */
468
+ log?: boolean | LogLevel;
469
+ }
470
+ interface MockHttpItem extends MockBaseItem {
471
+ /**
472
+ * The interface allows request methods, and by default allows both GET and POST.
473
+ *
474
+ * 该接口允许的 请求方法,默认同时支持 GET 和 POST
475
+ * @default ['POST','GET']
476
+ */
477
+ method?: Method | Method[];
478
+ /**
479
+ * Configure the response body headers
480
+ *
481
+ * 配置响应体 headers
482
+ * @default
483
+ * ```json
484
+ * { "Content-Type": "application/json" }
485
+ * ```
486
+ */
487
+ headers?: Headers | ResponseHeaderFn;
488
+ /**
489
+ * Configure Response Header Status Code
490
+ *
491
+ * 配置 响应头状态码
492
+ * @default 200
493
+ */
494
+ status?: number;
495
+ /**
496
+ * Configure response header status text
497
+ *
498
+ * 配置响应头状态文本
499
+ * @default 'OK'
500
+ */
501
+ statusText?: string;
502
+ /**
503
+ * Configure response delay time,
504
+ * If an array is passed in, it represents the range of delay time.
505
+ * unit: `ms`
506
+ *
507
+ * 配置响应延迟时间, 如果传入的是一个数组,则代表延迟时间的范围
508
+ * 单位: `ms`
509
+ * @default 0
510
+ */
511
+ delay?: number | [number, number];
512
+ /**
513
+ * Configure response body cookies
514
+ *
515
+ * 设置响应体 cookies
516
+ * @example
517
+ * ```ts
518
+ * export default {
519
+ * cookies: {
520
+ * 'token1': '1234567',
521
+ * 'token2': ['1234567', { path: '/' }],
522
+ * },
523
+ * }
524
+ * ```
525
+ * @example
526
+ * ```ts
527
+ * export default {
528
+ * cookies: function (request) {
529
+ * return {
530
+ * 'token1': '1234567',
531
+ * 'token2': ['1234567', { path: '/' }],
532
+ * }
533
+ * },
534
+ * }
535
+ * ```
536
+ */
537
+ cookies?: ResponseCookies | ResponseCookiesFn;
538
+ /**
539
+ * Response body data type, optional values include `text, json, buffer`.
540
+ *
541
+ * And also support types included in `mime-db`.
542
+ * When the response body returns a file and you are not sure which type to use,
543
+ * you can pass the file name as the value. The plugin will internally search for matching
544
+ * `content-type` based on the file name suffix.
545
+ *
546
+ * However, if it is a TypeScript file such as `a.ts`, it may not be correctly matched
547
+ * as a JavaScript script. You need to modify `a.ts` to `a.js` as the value passed
548
+ * in order to recognize it correctly.
549
+ *
550
+ * 响应体数据类型, 可选值包括 `text, json, buffer`,
551
+ *
552
+ * 还支持`mime-db`中的包含的类型。
553
+ * 当响应体返回的是一个文件,而你不确定应该使用哪个类型时,可以将文件名作为值传入,
554
+ * 插件内部会根据文件名后缀查找匹配的`content-type`。
555
+ *
556
+ * 但如果是 `typescript`文件如 `a.ts`,可能不会被正确匹配为 `javascript`脚本,
557
+ * 你需要将 `a.ts` 修改为 `a.js`作为值传入才能正确识别。
558
+ * @see [mime-db](https://github.com/jshttp/mime-db)
559
+ * @default 'json'
560
+ * @example
561
+ * ```txt
562
+ * json
563
+ * buffer
564
+ * my-app.dmg
565
+ * music.mp4
566
+ * ```
567
+ */
568
+ type?: "text" | "json" | "buffer" | string;
569
+ /**
570
+ * Configure response body data content
571
+ *
572
+ * 配置响应体数据内容
573
+ * @default ''
574
+ * @example
575
+ * ```ts
576
+ * export default {
577
+ * body: { a: 1 },
578
+ * }
579
+ * ```
580
+ * @example
581
+ * ```ts
582
+ * export default {
583
+ * body: function(request) {
584
+ * return { a: 1, query: request.query }
585
+ * },
586
+ * }
587
+ * ```
588
+ */
589
+ body?: ResponseBody | ResponseBodyFn;
590
+ /**
591
+ * If you need to set complex response content, you can use the response method,
592
+ * which is a middleware. Here, you can get information such as req
593
+ * and res of the http request,
594
+ * and then return response data through res.write() | res.end().
595
+ * Otherwise, you need to execute next() method.
596
+ * In `req`, you can also get parsed request information such as
597
+ * `query`, `params`, `body` and `refererQuery`.
598
+ *
599
+ * 如果需要设置复杂的响应内容,可以使用 response 方法,
600
+ * 该方法是一个 middleware,你可以在这里拿到 http 请求的 req、res等信息,
601
+ * 然后通过 res.write() | res.end() 返回响应数据, 否则需要执行 next() 方法。
602
+ * 在 `req` 中,还可以拿到 query、params、body, refererQuery 等已解析的请求信息。
603
+ *
604
+ * @see [connect](https://github.com/senchalabs/connect#appusefn)
605
+ * @example
606
+ * ```ts
607
+ * export default {
608
+ * response(req, res) {
609
+ * res.setHeader('Content-Type', 'application/json')
610
+ * res.end(JSON.stringify({ a: 1 }))
611
+ * },
612
+ * }
613
+ * ```
614
+ *
615
+ */
616
+ response?: (req: MockRequest, res: MockResponse, next: (err?: any) => void) => void | Promise<void>;
617
+ /**
618
+ * Request Validator
619
+ *
620
+ * Sometimes, for the same API request, data needs to be returned based
621
+ * on different request parameters.
622
+ * However, if all of this is written in a single mock's body or response,
623
+ * the content can become cumbersome and difficult to manage.
624
+ * The function of a validator allows you to configure multiple mocks with
625
+ * the same URL simultaneously and determine which mock should be used through validation.
626
+ *
627
+ * 请求验证器
628
+ *
629
+ * 有时候,一个相同的API请求,需要根据不同的请求参数,来决定返回数据,
630
+ * 但全部都在单个 mock中的 body或者 response 中写,内容会很庞杂,不好管理,
631
+ * 验证器的功能,允许你同时配置多条相同url的mock,通过验证器来判断使哪个mock生效。
632
+ * @example
633
+ * ```ts
634
+ * export default {
635
+ * validator: {
636
+ * query: { id: 123 }
637
+ * }
638
+ * }
639
+ * ```
640
+ * @example
641
+ * ```ts
642
+ * export default {
643
+ * validator: function(request) {
644
+ * return request.query.id === 123
645
+ * }
646
+ * }
647
+ * ```
648
+ */
649
+ validator?: Partial<Omit<ExtraRequest, "getCookie">> | ((request: ExtraRequest) => boolean);
650
+ ws?: false;
651
+ }
652
+ interface MockWebsocketItem extends MockBaseItem {
653
+ ws: true;
654
+ /**
655
+ * Configure Websocket Server
656
+ *
657
+ * 配置 Websocket Server
658
+ * @example
659
+ * ```ts
660
+ * export default {
661
+ * ws: true
662
+ * setup: (wss, { onCleanup }) => {
663
+ * wss.on('connection', (ws,req) => {
664
+ * ws.on('message', (raw) => console.log(raw))
665
+ * const timer = setInterval(
666
+ * () => ws.send(JSON.stringify({ type: 'connected' })),
667
+ * 1000,
668
+ * )
669
+ * onCleanup(() => clearInterval(timer))
670
+ * })
671
+ * wss.on('error', (error) => console.error(error))
672
+ * }
673
+ * }
674
+ * ```
675
+ */
676
+ setup: (wss: WebSocketServer, context: WebSocketSetupContext) => void;
677
+ }
678
+ interface WebSocketSetupContext {
679
+ /**
680
+ * When defining WSS, you may perform some automatic or looping tasks.
681
+ * However, when hot updating, the plugin will re-execute `setup()`,
682
+ * which may result in duplicate registration of listening events and looping tasks
683
+ * such as setTimeout. You can use `onCleanup()` to clear these automatic or looping tasks.
684
+ *
685
+ * 当你在定义 WSS 时,可能会执行一些自动任务或循环任务,
686
+ * 但是当热更新时,插件内部会重新执行 setup() ,
687
+ * 这可能导致出现 重复注册监听事件 和 循环任务如 `setTimeout` 等。
688
+ * 通过 `onCleanup()` 可以来清除这些自动任务或循环任务。
689
+ * @example
690
+ * ``` ts
691
+ * onCleanup(() => clearTimeout(timeId))
692
+ * ```
693
+ */
694
+ onCleanup: (cleanup: () => void) => void;
695
+ }
696
+ type MockOptions = (MockHttpItem | MockWebsocketItem)[];
697
+ type FormidableFile = formidable.File | formidable.File[];
698
+ type LogType = "info" | "warn" | "error" | "debug";
699
+ type LogLevel = LogType | "silent";
700
+ //#endregion
701
+ export { WebSocketSetupContext as _, LogType as a, MockMatchPriority as c, MockRequest as d, MockResponse as f, ServerBuildOption as g, ResponseBody as h, LogLevel as i, MockMatchSpecialPriority as l, MockWebsocketItem as m, ExtraRequest as n, Method as o, MockServerPluginOptions as p, FormidableFile as r, MockHttpItem as s, BodyParserOptions as t, MockOptions as u };