rspack-plugin-mock 1.2.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.
@@ -1,14 +1,135 @@
1
- import { Options } from "co-body";
2
- import Cookies from "cookies";
1
+ import { Readable } from "node:stream";
3
2
  import { CorsOptions } from "cors";
3
+ import { Options } from "co-body";
4
4
  import formidable from "formidable";
5
+ import http, { IncomingMessage, ServerResponse } from "node:http";
6
+ import crypto from "node:crypto";
5
7
  import { Buffer } from "node:buffer";
6
- import http from "node:http";
7
- import { Readable } from "node:stream";
8
8
  import { WebSocketServer } from "ws";
9
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
10
132
  //#region src/types.d.ts
11
-
12
133
  /**
13
134
  * Configure plugin
14
135
  *
@@ -48,6 +169,14 @@ interface MockServerPluginOptions {
48
169
  */
49
170
  cwd?: string;
50
171
  /**
172
+ * The directory to store mock files
173
+ *
174
+ * 存储 mock 文件的目录
175
+ *
176
+ * @default 'mock'
177
+ */
178
+ dir?: string;
179
+ /**
51
180
  * glob string matching mock includes files
52
181
  *
53
182
  * glob 字符串匹配 mock 包含的文件
@@ -97,7 +226,7 @@ interface MockServerPluginOptions {
97
226
  * cookies options
98
227
  * @see [cookies](https://github.com/pillarjs/cookies#new-cookiesrequest-response--options)
99
228
  */
100
- cookiesOptions?: Cookies.Option;
229
+ cookiesOptions?: CookiesOption;
101
230
  /**
102
231
  * Configure to `co-body`
103
232
  *
@@ -278,7 +407,7 @@ interface ExtraRequest {
278
407
  * 获取 请求中携带的 cookie
279
408
  * @see [cookies](https://github.com/pillarjs/cookies#cookiesgetname--options)
280
409
  */
281
- getCookie: (name: string, option?: Cookies.GetOption) => string | undefined;
410
+ getCookie: Cookies["get"];
282
411
  }
283
412
  type MockRequest = http.IncomingMessage & ExtraRequest;
284
413
  type MockResponse = http.ServerResponse<http.IncomingMessage> & {
@@ -288,11 +417,11 @@ type MockResponse = http.ServerResponse<http.IncomingMessage> & {
288
417
  * 向请求响应中设置 cookie
289
418
  * @see [cookies](https://github.com/pillarjs/cookies#cookiessetname--values--options)
290
419
  */
291
- setCookie: (name: string, value?: string | null, option?: Cookies.SetOption) => void;
420
+ setCookie: Cookies["set"];
292
421
  };
293
422
  type ResponseBodyFn = (request: MockRequest) => ResponseBody | Promise<ResponseBody>;
294
423
  type ResponseHeaderFn = (request: MockRequest) => Headers | Promise<Headers>;
295
- type CookieValue = string | [string, Cookies.SetOption];
424
+ type CookieValue = string | [string, SetCookieOption];
296
425
  type ResponseCookies = Record<string, CookieValue>;
297
426
  type ResponseCookiesFn = (request: MockRequest) => ResponseCookies | Promise<ResponseCookies>;
298
427
  interface MockBaseItem {
@@ -569,4 +698,4 @@ type FormidableFile = formidable.File | formidable.File[];
569
698
  type LogType = "info" | "warn" | "error" | "debug";
570
699
  type LogLevel = LogType | "silent";
571
700
  //#endregion
572
- export { BodyParserOptions, ExtraRequest, FormidableFile, LogLevel, LogType, Method, MockHttpItem, MockMatchPriority, MockMatchSpecialPriority, MockOptions, MockRequest, MockResponse, MockServerPluginOptions, MockWebsocketItem, ResponseBody, ServerBuildOption, WebSocketSetupContext };
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 };
@@ -0,0 +1 @@
1
+ import{isArray as e,isBoolean as t,isEmptyObject as n,isFunction as r,isPlainObject as i,random as a,sleep as o,sortBy as s,timestamp as c,toArray as l,uniq as u}from"@pengzhanbo/utils";import d from"node:path";import f from"ansis";import p from"picomatch";import{loadPackageJSONSync as m}from"local-pkg";import{match as h,parse as g,pathToRegexp as _}from"path-to-regexp";import v from"node:os";import{fileURLToPath as y}from"node:url";import b from"debug";import{Volume as x,createFsFromVolume as S}from"memfs";import{parse as C}from"node:querystring";import w from"co-body";import T from"formidable";import E from"node:http";import D from"node:crypto";import{Buffer as O}from"node:buffer";import k from"http-status";import*as A from"mime-types";import{WebSocketServer as j}from"ws";function ee(e,t){let n=[],r=[`**/node_modules/**`,...l(t)];return l(e).forEach(e=>{e[0]===`!`?r.push(e.slice(1)):n.push(e)}),{pattern:n,ignore:r,isMatch:p(n,{ignore:r})}}function M(e,t,n){return typeof e==`function`?e(t,n):e[0]===`^`&&new RegExp(e).test(t)||t.startsWith(e)}function N(e){let{dependencies:t,devDependencies:n,peerDependencies:r,optionalDependencies:i}=m(e)||{};return{...t,...n,...r,...i}}function P(e){let t=N(e);return u(Object.keys(t))}function te(e){return typeof e==`object`&&!!e&&typeof e.pipe==`function`}function ne(e){return te(e)&&e.readable!==!1&&typeof e._read==`function`&&typeof e._readableState==`object`}function F(e,t){if(!t)return!0;for(let n in t)if(!I(e[n],t[n]))return!1;return!0}function I(t,n){if(e(t)&&e(n)){let e=new Set;return n.every(n=>t.some((t,r)=>{if(e.has(r))return!1;let i=I(t,n);return i&&e.add(r),i}))}return i(t)&&i(n)?F(t,n):Object.is(t,n)}const L=new Map;function R(e,t){let n=L.get(e);return n||(n=_(e).regexp,L.set(e,n)),n.test(t)}const z={silent:0,error:1,warn:2,info:3,debug:4};function re(e,n=`info`){e=`[${e}]`;function r(r,i,a){if(a=t(a)?a?n:`error`:a,z[a]>=z[r]){let t=r===`info`||r===`debug`?`log`:r,n=r===`debug`?f.magenta.bold(e):r===`info`?f.cyan.bold(e):r===`warn`?f.yellow.bold(e):f.red.bold(e),a=`${f.dim(new Date().toLocaleTimeString())} ${n} ${i}`;console[t](a)}}return{debug(e,t=n){r(`debug`,e,t)},info(e,t=n){r(`info`,e,t)},warn(e,t=n){r(`warn`,e,t)},error(e,t=n){r(`error`,e,t)}}}ae(import.meta.url);const ie=S(new x);function ae(e){return d.dirname(y(e))}b(`vite:mock-dev-server`);const oe=/\\/g,se=v.platform()===`win32`;function ce(e){return e.replace(oe,`/`)}function le(e){return d.posix.normalize(se?ce(e):e)}function B(e){let t=new URL(e,`http://example.com`);return{pathname:decodeURIComponent(t.pathname),query:C(t.search.replace(/^\?/,``))}}function ue(e,t=5){return function n(r,i=0){let a=r();a?e(a):i<t&&setTimeout(()=>n(r,i+1),100)}}function de(e){return e.filter(e=>e[0]).map(([e,t])=>{let n;return e.default?n=Array.isArray(e.default)?e.default.map(e=>({...e,__filepath__:t})):{...e.default,__filepath__:t}:`url`in e?n={...e,__filepath__:t}:(n=[],Object.keys(e||{}).forEach(r=>{Array.isArray(e[r])?n.push(...e[r].map(e=>({...e,__filepath__:t}))):n.push({...e[r],__filepath__:t})})),n})}function fe(e){let t=[];for(let[,n]of e.entries())n&&t.push(...l(n));let a={};return t.filter(e=>i(e)&&e.enabled!==!1&&e.url).forEach(e=>{let{pathname:t,query:i}=B(e.url),o=a[t]??=[],s={...e,url:t};if(s.ws!==!0){let e=s.validator;n(i)||(r(e)?s.validator=function(t){return F(t.query,i)&&e(t)}:e?(s.validator={...e},s.validator.query=s.validator.query?{...i,...s.validator.query}:i):s.validator={query:i})}o.push(s)}),Object.keys(a).forEach(e=>{a[e]=V(a[e])}),a}function V(e){return s(e,e=>{if(e.ws===!0)return 0;let{validator:t}=e;return!t||n(t)?2:r(t)?0:1/Object.keys(t).reduce((e,n)=>e+pe(t[n]),0)})}function pe(e){return e?Object.keys(e).length:0}async function me(e,t,n={}){let r=e.method.toUpperCase();if([`HEAD`,`OPTIONS`].includes(r))return;let i=e.headers[`content-type`]?.toLocaleLowerCase()||``,{limit:a,formLimit:o,jsonLimit:s,textLimit:c,...l}=n;try{if(i.startsWith(`application/json`))return await w.json(e,{limit:s||a,...l});if(i.startsWith(`application/x-www-form-urlencoded`))return await w.form(e,{limit:o||a,...l});if(i.startsWith(`text/plain`))return await w.text(e,{limit:c||a,...l});if(i.startsWith(`multipart/form-data`))return await ge(e,t)}catch(e){console.error(e)}}const he={keepExtensions:!0,filename(e,t,n){return n?.originalFilename||`${e}.${Date.now()}${t?`.${t}`:``}`}};async function ge(e,t){let n=T({...he,...t});return new Promise((t,r)=>{n.parse(e,(e,n,i)=>{if(e){r(e);return}t({...n,...i})})})}const H=new Map;function U(e,t){let n=H.get(e);n||(n=h(e,{decode:decodeURIComponent}),H.set(e,n));let r=n(t);return r?r.params:{}}function _e(e,t){return F(e.headers,t.headers)&&F(e.body,t.body)&&F(e.params,t.params)&&F(e.query,t.query)&&F(e.refererQuery,t.refererQuery)}function W(e,t){return!t||n(t)?``:` ${f.gray(`${e}:`)}${JSON.stringify(t)}`}function ve(e,t){let{url:n,method:r,query:i,params:a,body:o}=e,{pathname:s}=new URL(n,`http://example.com`);s=f.green(decodeURIComponent(s));let c=f.magenta.bold(r),l=W(`query`,i),u=W(`params`,a),d=W(`body`,o),p=` ${f.dim.underline(`(${t})`)}`;return`${c} ${s}${l}${u}${d}${p}`}function ye(t,n,{pathname:i,method:a,request:o}){return t.find(t=>{if(!i||!t||!t.url||t.ws||!(t.method?e(t.method)?t.method:[t.method]:[`GET`,`POST`]).includes(a))return!1;let s=R(t.url,i);if(s&&t.validator){let e=U(t.url,i);if(r(t.validator))return t.validator({params:e,...o});try{return _e({params:e,...o},t.validator)}catch(e){let r=t.__filepath__;return n.error(`${f.red(`mock error at ${i}`)}\n${e}\n at validator (${f.underline(r)})`,t.log),!1}}return s})}const G=/^[\t\u0020-\u007E\u0080-\u00FF]+$/,be=/^(?:low|medium|high)$/i,K=Object.create(null),xe=/[\^$\\.*+?()[\]{}|]/g,Se=/[;=]/,Ce=/;/,we=/^(?:lax|none|strict)$/i;var Te=class{name;value;maxAge;expires;path=`/`;domain;secure=!1;httpOnly=!0;sameSite=!1;overwrite=!1;priority;partitioned;constructor(e,t,n={}){if(!G.test(e)||Se.test(e))throw TypeError(`argument name is invalid`);if(t&&(!G.test(t)||Ce.test(t)))throw TypeError(`argument value is invalid`);if(this.name=e,this.value=t,Object.assign(this,n),this.value||(this.expires=new Date(0),this.maxAge=void 0),this.path&&!G.test(this.path))throw TypeError(`[Cookie] option path is invalid`);if(this.domain&&!G.test(this.domain))throw TypeError(`[Cookie] option domain is invalid`);if(typeof this.maxAge==`number`?Number.isNaN(this.maxAge)||!Number.isFinite(this.maxAge):this.maxAge)throw TypeError(`[Cookie] option maxAge is invalid`);if(this.priority&&!be.test(this.priority))throw TypeError(`[Cookie] option priority is invalid`);if(this.sameSite&&this.sameSite!==!0&&!we.test(this.sameSite))throw TypeError(`[Cookie] option sameSite is invalid`)}toString(){return`${this.name}=${this.value}`}toHeader(){let e=this.toString();return this.maxAge&&(this.expires=new Date(Date.now()+this.maxAge)),this.path&&(e+=`; path=${this.path}`),this.expires&&(e+=`; expires=${this.expires.toUTCString()}`),this.domain&&(e+=`; domain=${this.domain}`),this.priority&&(e+=`; priority=${this.priority.toLowerCase()}`),this.sameSite&&(e+=`; samesite=${this.sameSite===!0?`strict`:this.sameSite.toLowerCase()}`),this.secure&&(e+=`; secure`),this.httpOnly&&(e+=`; httponly`),this.partitioned&&(e+=`; partitioned`),e}};function Ee(e,t){if(e.length!==t.length)return!1;if(D.timingSafeEqual)return D.timingSafeEqual(e,t);for(let n=0;n<e.length;n++)if(e[n]!==t[n])return!1;return!0}function q(e,t){return D.createHmac(`sha256`,e).update(t).digest()}function De(e,t){let n=String(e),r=String(t),i=D.randomBytes(32);return Ee(q(i,n),q(i,r))&&e===t}const Oe=/[/+=]/g,ke={"/":`_`,"+":`-`,"=":``};var J=class{algorithm;encoding;keys=[];constructor(e,t,n){this.keys=e,this.algorithm=t||`sha256`,this.encoding=n||`base64`}sign(e,t=this.keys[0]){return D.createHmac(this.algorithm,t).update(e).digest(this.encoding).replace(Oe,e=>ke[e])}index(e,t){for(let n=0,r=this.keys.length;n<r;n++)if(De(t,this.sign(e,this.keys[n])))return n;return-1}verify(e,t){return this.index(e,t)>-1}},Y=class{request;response;secure;keys;constructor(t,n,r={}){this.request=t,this.response=n,this.secure=r.secure,r.keys instanceof J?this.keys=r.keys:e(r.keys)&&(this.keys=new J(r.keys))}set(e,t,n){let r=this.request,i=this.response,a=l(i.getHeader(`Set-Cookie`)),o=new Te(e,t,n),s=n?.signed??!!this.keys,c=this.secure===void 0?r.protocol===`https`||je(r):!!this.secure;if(!c&&n?.secure)throw Error(`Cannot send secure cookie over unencrypted connection`);if(o.secure=n?.secure??c,Me(a,o),s&&n){if(!this.keys)throw Error(`.keys required for signed cookies`);o.value=this.keys.sign(o.toString()),o.name+=`.sig`,Me(a,o)}return(i.set?E.OutgoingMessage.prototype.setHeader:i.setHeader).call(i,`Set-Cookie`,a),this}get(e,t){let n=`${e}.sig`,r=t?.signed??!!this.keys,i=this.request.headers.cookie;if(!i)return;let a=i.match(Ae(e));if(!a)return;let o=a[1];if(o[0]===`"`&&(o=o.slice(1,-1)),!t||!r)return o;let s=this.get(n);if(!s)return;let c=`${e}=${o}`;if(!this.keys)throw Error(`.keys required for signed cookies`);let l=this.keys.index(c,s);if(l<0)this.set(n,null,{path:`/`,signed:!1});else return l&&this.set(n,this.keys.sign(c),{signed:!1}),o}};function Ae(e){return K[e]||(K[e]=RegExp(`(?:^|;) *${e.replace(xe,`\\$&`)}=([^;]*)`)),K[e]}function je(e){return!!(e.socket?e.socket.encrypted:e.connection.encrypted)}function Me(e,t){if(t.overwrite)for(let n=e.length-1;n>=0;n--)e[n].indexOf(`${t.name}=`)===0&&e.splice(n,1);e.push(t.toHeader())}const X={};function Z(e){if(X[e])return X[e];let t=[],n=(e,r=!1)=>{for(let i of e)if(i.type===`text`){let e=i.value.split(`/`).filter(Boolean);e.length&&t.push(...e.map(e=>({type:`text`,value:e})))}else i.type===`group`?n(i.tokens,!0):(r&&(i.optional=!0),t.push(i))};return n(g(e).tokens),X[e]=t,t}function Ne(e){let t=e.map(e=>Z(e).length);return t=t.length===0?[1]:t,Math.max(...t)+2}function Pe(e){let t=Z(e),n=0;for(let e=0;e<t.length;e++)t[e].type!==`text`&&(n+=10**(e+1)),n+=10**(e+1);return n}function Fe(e){let t=[],n=[];for(let t of e){let e=Z(t).filter(e=>e.type!==`text`).length;n[e]||(n[e]=[]),n[e].push(t)}for(let e of n.filter(e=>e&&e.length>0))t=[...t,...s(e,Pe).reverse()];return t}function Ie(e){let t=Ne(e);return s(e,e=>{let n=Z(e),r=n.filter(e=>e.type!==`text`);if(r.length===0)return 0;let i=r.length,a=0;for(let e=0;e<n.length;e++){let r=n[e],o=r.type!==`text`,s=r.type===`wildcard`,c=!!r.optional;a+=o?1:0,e===n.length-1&&s?i+=(c?5:4)*10**(n.length===1?t+1:t):(s?i+=3*10**(t-1):i+=2*10**a,c&&(i+=10**a))}return i})}function Le(t,r,i){let a=Ie(Fe(t.filter(e=>R(e,r)))),{global:o=[],special:s={}}=i;if(o.length===0&&n(s)||a.length===0)return a;let[c,l]=Re(a),d=o.filter(e=>l.includes(e));if(d.length>0&&(a=u([...c,...d,...l])),n(s))return a;let f=Object.keys(s).filter(e=>a.includes(e))[0];if(!f)return a;let p=s[f],{rules:m,when:h}=e(p)?{rules:p,when:[]}:p;return m.includes(a[0])&&(h.length===0||h.some(e=>_(e).regexp.test(r)))&&(a=u([f,...a])),a}function Re(e){let t=[],n=[];for(let r of e)Z(r).filter(e=>e.type!==`text`).length>0?n.push(r):t.push(r);return[t,n]}const Q=new WeakMap;function ze(e){let t=[];e.addListener(`data`,e=>{t.push(O.from(e))}),e.addListener(`end`,()=>{t.length&&Q.set(e,O.concat(t))})}function Be(e,t){let n=Q.get(t);n&&(Q.delete(t),e.headersSent||e.setHeader(`Content-Length`,n.byteLength),e.writableEnded||e.write(n))}function Ve(e){return k[e]||`Unknown`}function $(e,t=200,n){e.statusCode=t,e.statusMessage=n||Ve(t)}async function He(e,t,n,i){let{headers:a,type:o=`json`}=n,s=n.__filepath__,c=A.contentType(o)||A.contentType(A.lookup(o)||``);if(c&&t.setHeader(`Content-Type`,c),t.setHeader(`Cache-Control`,`no-cache,max-age=0`),t.setHeader(`X-Mock-Power-By`,`vite-plugin-mock-dev-server`),s&&t.setHeader(`X-File-Path`,s),a)try{let n=r(a)?await a(e):a;Object.keys(n).forEach(e=>{t.setHeader(e,n[e])})}catch(t){i.error(`${f.red(`mock error at ${e.url.split(`?`)[0]}`)}\n${t}\n at headers (${f.underline(s)})`,n.log)}}async function Ue(t,n,i,a){let{cookies:o}=i,s=i.__filepath__;if(o)try{let i=r(o)?await o(t):o;Object.keys(i).forEach(t=>{let r=i[t];if(e(r)){let[e,i]=r;n.setCookie(t,e,i)}else n.setCookie(t,r)})}catch(e){a.error(`${f.red(`mock error at ${t.url.split(`?`)[0]}`)}\n${e}\n at cookies (${f.underline(s)})`,i.log)}}function We(e,t,n){if(ne(t))t.pipe(e);else if(O.isBuffer(t))e.end(n===`text`||n===`json`?t.toString(`utf-8`):t);else{let r=typeof t==`string`?t:JSON.stringify(t);e.end(n===`buffer`?O.from(r):r)}}async function Ge(t,n){if(!n||typeof n==`number`&&n<=0||e(n)&&n.length!==2)return;let r=0;if(e(n)){let[e,t]=n;r=a(e,t)}else r=n-(c()-t);r>0&&await o(r)}function Ke(e,{formidableOptions:t={},bodyParserOptions:n={},proxies:i,cookiesOptions:a,logger:o,priority:s={}}){return async function(l,u,d){let p=c(),{query:m,pathname:h}=B(l.url);if(!h||i.length===0||!i.some(e=>M(e,l.url,l)))return d();let g=e.mockData,_=Le(Object.keys(g),h,s);if(_.length===0)return d();ze(l);let{query:v}=B(l.headers.referer||``),y=await me(l,t,n),b=new Y(l,u,a),x=b.get.bind(b),S=l.method.toUpperCase(),C,w;for(let e of _)if(C=ye(g[e],o,{pathname:h,method:S,request:{query:m,refererQuery:v,body:y,headers:l.headers,getCookie:x}}),C){w=e;break}if(!C){let e=_.map(e=>e===w?f.underline.bold(e):f.dim(e)).join(`, `);return o.warn(`${f.green(h)} matches ${e} , but mock data is not found.`),d()}let T=l,E=u;T.body=y,T.query=m,T.refererQuery=v,T.params=U(C.url,h),T.getCookie=x,E.setCookie=b.set.bind(b);let{body:D,delay:O,type:k=`json`,response:A,status:j=200,statusText:ee,log:N,__filepath__:P}=C;if($(E,j,ee),await He(T,E,C,o),await Ue(T,E,C,o),o.info(ve(T,P),N),o.debug(`${f.magenta(`DEBUG`)} ${f.underline(h)} matches: [ ${_.map(e=>e===w?f.underline.bold(e):f.dim(e)).join(`, `)} ]\n`),D){try{let e=r(D)?await D(T):D;await Ge(p,O),We(E,e,k)}catch(e){o.error(`${f.red(`mock error at ${h}`)}\n${e}\n at body (${f.underline(P)})`,N),$(E,500),u.end(``)}return}if(A){try{await Ge(p,O),await A(T,E,d)}catch(e){o.error(`${f.red(`mock error at ${h}`)}\n${e}\n at response (${f.underline(P)})`,N),$(E,500),u.end(``)}return}u.end(``)}}function qe(e,t,{wsProxies:n,cookiesOptions:r,logger:i}){let a=new Map,o=new Map,s=new WeakMap,c=e=>{let t=o.get(e);return t||o.set(e,t=new Map),t},l=(e,t)=>{let n=a.get(e);n||a.set(e,n=new Set),n.add(t)},u=(e,t,n,r,a,o)=>{try{n.setup?.(t,r),t.on(`close`,()=>e.delete(a)),t.on(`error`,e=>{i.error(`${f.red(`WebSocket mock error at ${t.path}`)}\n${e}\n at setup (${o})`,n.log)})}catch(e){i.error(`${f.red(`WebSocket mock error at ${t.path}`)}\n${e}\n at setup (${o})`,n.log)}},d=(e,t,n,r,i)=>{let{cleanupList:a,connectionList:o,context:c}=s.get(t);Xe(a),o.forEach(({ws:e})=>e.removeAllListeners()),t.removeAllListeners(),u(e,t,n,c,r,i),o.forEach(({ws:e,req:n})=>Ye(t,e,n,o))};e.on(`update`,({filepath:t})=>{if(!a.has(t))return;let n=a.get(t);if(n)for(let r of n.values())for(let n of e.mockData[r]){if(!n.ws||n.__filepath__!==t)return;let e=c(r);for(let[r,i]of e.entries())d(e,i,n,r,t)}}),t?.on(`upgrade`,(t,a,o)=>{let{pathname:d,query:p}=B(t.url);if(!d||n.length===0||!n.some(e=>M(e,t.url,t)))return;let m=e.mockData,h=Object.keys(m).find(e=>R(e,d));if(!h)return;let g=m[h].find(e=>e.url&&e.ws&&R(e.url,d));if(!g)return;let _=g.__filepath__;l(_,h);let v=c(h),y=Je(v,d),b=s.get(y);if(!b){let e=[],t={onCleanup:t=>e.push(t)};b={cleanupList:e,context:t,connectionList:[]},s.set(y,b),u(v,y,g,t,d,_)}let x=t,S=new Y(t,t,r),{query:C}=B(t.headers.referer||``);x.query=p,x.refererQuery=C,x.params=U(h,d),x.getCookie=S.get.bind(S),y.handleUpgrade(x,a,o,e=>{i.info(`${f.magenta(f.bold(`WebSocket`))} ${f.green(t.url)} connected ${f.dim(`(${_})`)}`,g.log),b.connectionList.push({req:x,ws:e}),Ye(y,e,x,b.connectionList)})}),t?.on(`close`,()=>{for(let e of o.values()){for(let t of e.values())Xe(s.get(t).cleanupList),t.close();e.clear()}o.clear(),a.clear()})}function Je(e,t){let n=e.get(t);return n||e.set(t,n=new j({noServer:!0})),n}function Ye(e,t,n,r){e.emit(`connection`,t,n),t.on(`close`,()=>{let e=r.findIndex(e=>e.ws===t);e!==-1&&r.splice(e,1)})}function Xe(e){let t;for(;t=e.shift();)t?.()}export{ee as _,de as a,B as c,re as d,z as f,M as g,N as h,fe as i,le as l,P as m,Ke as n,V as o,R as p,Be as r,ue as s,qe as t,ie as u};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "rspack-plugin-mock",
3
3
  "type": "module",
4
- "version": "1.2.0",
4
+ "version": "1.3.0",
5
5
  "description": "inject api mock server to development server",
6
6
  "author": "pengzhanbo <q942450674@outlook.com> (https://github.com/pengzhanbo)",
7
7
  "license": "MIT",
@@ -24,53 +24,37 @@
24
24
  "exports": {
25
25
  ".": {
26
26
  "import": {
27
- "types": "./dist/index.d.ts",
28
- "default": "./dist/index.js"
29
- },
30
- "require": {
31
- "types": "./dist/index.d.cts",
32
- "default": "./dist/index.cjs"
27
+ "types": "./dist/index.d.mts",
28
+ "default": "./dist/index.mjs"
33
29
  }
34
30
  },
35
31
  "./server": {
36
32
  "import": {
37
- "types": "./dist/server.d.ts",
38
- "default": "./dist/server.js"
39
- },
40
- "require": {
41
- "types": "./dist/server.d.cts",
42
- "default": "./dist/server.cjs"
33
+ "types": "./dist/server.d.mts",
34
+ "default": "./dist/server.mjs"
43
35
  }
44
36
  },
45
37
  "./rsbuild": {
46
38
  "import": {
47
- "types": "./dist/rsbuild.d.ts",
48
- "default": "./dist/rsbuild.js"
49
- },
50
- "require": {
51
- "types": "./dist/rsbuild.d.cts",
52
- "default": "./dist/rsbuild.cjs"
39
+ "types": "./dist/rsbuild.d.mts",
40
+ "default": "./dist/rsbuild.mjs"
53
41
  }
54
42
  },
55
43
  "./helper": {
56
44
  "import": {
57
- "types": "./dist/helper.d.ts",
58
- "default": "./dist/helper.js"
59
- },
60
- "require": {
61
- "types": "./dist/helper.d.cts",
62
- "default": "./dist/helper.cjs"
45
+ "types": "./dist/helper.d.mts",
46
+ "default": "./dist/helper.mjs"
63
47
  }
64
48
  },
65
49
  "./package.json": "./package.json"
66
50
  },
67
- "main": "dist/index.js",
68
- "types": "dist/index.d.ts",
51
+ "main": "dist/index.mjs",
52
+ "types": "dist/index.d.mts",
69
53
  "files": [
70
54
  "dist"
71
55
  ],
72
56
  "engines": {
73
- "node": ">=18.20.0",
57
+ "node": ">=20.19.0",
74
58
  "pnpm": ">=9"
75
59
  },
76
60
  "peerDependencies": {
@@ -86,54 +70,59 @@
86
70
  }
87
71
  },
88
72
  "dependencies": {
89
- "@pengzhanbo/utils": "^2.1.0",
90
- "@rollup/pluginutils": "^5.2.0",
91
- "chokidar": "3.6.0",
73
+ "@pengzhanbo/utils": "^2.1.2",
74
+ "ansis": "^4.2.0",
75
+ "chokidar": "^5.0.0",
92
76
  "co-body": "^6.2.0",
93
- "cookies": "^0.9.1",
94
77
  "cors": "^2.8.5",
95
- "debug": "^4.4.1",
96
- "fast-glob": "^3.3.3",
78
+ "debug": "^4.4.3",
97
79
  "formidable": "^3.5.4",
98
80
  "http-status": "^2.1.0",
99
81
  "is-core-module": "^2.16.1",
100
82
  "json5": "^2.2.3",
101
- "memfs": "^4.17.2",
102
- "mime-types": "^3.0.1",
103
- "path-to-regexp": "6.3.0",
104
- "picocolors": "^1.1.1",
105
- "portfinder": "^1.0.37",
83
+ "local-pkg": "^1.1.2",
84
+ "memfs": "^4.51.1",
85
+ "mime-types": "^3.0.2",
86
+ "path-to-regexp": "^8.3.0",
87
+ "picomatch": "^4.0.3",
88
+ "portfinder": "^1.0.38",
89
+ "tinyglobby": "^0.2.15",
106
90
  "ws": "^8.18.3"
107
91
  },
108
92
  "devDependencies": {
109
- "@pengzhanbo/eslint-config": "^1.34.0",
110
- "@rsbuild/core": "^1.4.3",
111
- "@rspack/core": "^1.4.2",
93
+ "@pengzhanbo/eslint-config": "^1.45.0",
94
+ "@rsbuild/core": "^1.6.15",
95
+ "@rspack/core": "^1.6.8",
112
96
  "@types/co-body": "^6.1.3",
113
- "@types/cookies": "^0.9.1",
114
97
  "@types/cors": "^2.8.19",
115
98
  "@types/debug": "^4.1.12",
116
- "@types/formidable": "^3.4.5",
99
+ "@types/formidable": "^3.4.6",
117
100
  "@types/is-core-module": "^2.2.2",
118
101
  "@types/mime-types": "^3.0.1",
119
- "@types/node": "^22.16.0",
102
+ "@types/node": "^25.0.3",
103
+ "@types/picomatch": "^4.0.2",
120
104
  "@types/ws": "^8.18.1",
121
- "bumpp": "^10.2.0",
105
+ "bumpp": "^10.3.2",
122
106
  "conventional-changelog-cli": "^5.0.0",
123
- "eslint": "^9.30.1",
107
+ "eslint": "^9.39.2",
124
108
  "husky": "^9.1.7",
125
- "lint-staged": "^16.1.2",
126
- "tsdown": "^0.12.9",
127
- "typescript": "^5.8.3"
109
+ "lint-staged": "^16.2.7",
110
+ "tsdown": "^0.18.3",
111
+ "typescript": "^5.9.3"
128
112
  },
129
113
  "lint-staged": {
130
114
  "*": "eslint --fix"
131
115
  },
116
+ "publishConfig": {
117
+ "access": "public",
118
+ "provenance": true
119
+ },
132
120
  "scripts": {
133
121
  "dev": "tsdown src --watch",
134
122
  "build": "tsdown",
135
123
  "lint": "eslint .",
124
+ "release:publish": "pnpm -r publish",
136
125
  "release:changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
137
- "release": "bumpp package.json --execute=\"pnpm release:changelog\" --commit --all --push --tag && pnpm publish --access public"
126
+ "release": "bumpp package.json --execute=\"pnpm release:changelog\" --commit --all --push --tag"
138
127
  }
139
128
  }
@@ -1,30 +0,0 @@
1
- //#region rolldown:runtime
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __copyProps = (to, from, except, desc) => {
9
- if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
- key = keys[i];
11
- if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
- get: ((k) => from[k]).bind(null, key),
13
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
- });
15
- }
16
- return to;
17
- };
18
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
- value: mod,
20
- enumerable: true
21
- }) : target, mod));
22
-
23
- //#endregion
24
-
25
- Object.defineProperty(exports, '__toESM', {
26
- enumerable: true,
27
- get: function () {
28
- return __toESM;
29
- }
30
- });
package/dist/helper.cjs DELETED
@@ -1,140 +0,0 @@
1
- const require_chunk = require('./chunk-CUT6urMc.cjs');
2
- const __pengzhanbo_utils = require_chunk.__toESM(require("@pengzhanbo/utils"));
3
- const node_stream = require_chunk.__toESM(require("node:stream"));
4
-
5
- //#region src/core/defineMock.ts
6
- function defineMock(config) {
7
- return config;
8
- }
9
- /**
10
- * Return a custom defineMock function to support preprocessing of mock config.
11
- *
12
- * 返回一个自定义的 defineMock 函数,用于支持对 mock config 的预处理。
13
- * @param transformer preprocessing function
14
- * @example
15
- * ```ts
16
- * const definePostMock = createDefineMock((mock) => {
17
- * mock.url = '/api/post/' + mock.url
18
- * })
19
- * export default definePostMock({
20
- * url: 'list',
21
- * body: [{ title: '1' }, { title: '2' }],
22
- * })
23
- * ```
24
- */
25
- function createDefineMock(transformer) {
26
- const define = (config) => {
27
- if ((0, __pengzhanbo_utils.isArray)(config)) config = config.map((item) => transformer(item) || item);
28
- else config = transformer(config) || config;
29
- return config;
30
- };
31
- return define;
32
- }
33
-
34
- //#endregion
35
- //#region src/core/defineMockData.ts
36
- const mockDataCache = /* @__PURE__ */ new Map();
37
- const responseCache = /* @__PURE__ */ new WeakMap();
38
- const staleInterval = 70;
39
- var CacheImpl = class {
40
- value;
41
- #initialValue;
42
- #lastUpdate;
43
- constructor(value) {
44
- this.value = value;
45
- this.#initialValue = (0, __pengzhanbo_utils.deepClone)(value);
46
- this.#lastUpdate = Date.now();
47
- }
48
- hotUpdate(value) {
49
- if (Date.now() - this.#lastUpdate < staleInterval) return;
50
- if (!(0, __pengzhanbo_utils.deepEqual)(value, this.#initialValue)) {
51
- this.value = value;
52
- this.#initialValue = (0, __pengzhanbo_utils.deepClone)(value);
53
- this.#lastUpdate = Date.now();
54
- }
55
- }
56
- };
57
- function defineMockData(key, initialData) {
58
- if (!mockDataCache.has(key)) mockDataCache.set(key, new CacheImpl(initialData));
59
- const cache = mockDataCache.get(key);
60
- cache.hotUpdate(initialData);
61
- if (responseCache.has(cache)) return responseCache.get(cache);
62
- const res = [() => cache.value, (val) => {
63
- if ((0, __pengzhanbo_utils.isFunction)(val)) val = val(cache.value) ?? cache.value;
64
- cache.value = val;
65
- }];
66
- Object.defineProperty(res, "value", {
67
- get() {
68
- return cache.value;
69
- },
70
- set(val) {
71
- cache.value = val;
72
- }
73
- });
74
- responseCache.set(cache, res);
75
- return res;
76
- }
77
-
78
- //#endregion
79
- //#region src/core/sse.ts
80
- /**
81
- * Transforms "messages" to W3C event stream content.
82
- * See https://html.spec.whatwg.org/multipage/server-sent-events.html
83
- * A message is an object with one or more of the following properties:
84
- * - data (String or object, which gets turned into JSON)
85
- * - event
86
- * - id
87
- * - retry
88
- * - comment
89
- *
90
- * If constructed with a HTTP Request, it will optimise the socket for streaming.
91
- * If this stream is piped to an HTTP Response, it will set appropriate headers.
92
- */
93
- var SSEStream = class extends node_stream.Transform {
94
- constructor(req) {
95
- super({ objectMode: true });
96
- req.socket.setKeepAlive(true);
97
- req.socket.setNoDelay(true);
98
- req.socket.setTimeout(0);
99
- }
100
- pipe(destination, options) {
101
- if (destination.writeHead) {
102
- destination.writeHead(200, {
103
- "Content-Type": "text/event-stream; charset=utf-8",
104
- "Transfer-Encoding": "identity",
105
- "Cache-Control": "no-cache",
106
- "Connection": "keep-alive"
107
- });
108
- destination.flushHeaders?.();
109
- }
110
- destination.write(":ok\n\n");
111
- return super.pipe(destination, options);
112
- }
113
- _transform(message, encoding, callback) {
114
- if (message.comment) this.push(`: ${message.comment}\n`);
115
- if (message.event) this.push(`event: ${message.event}\n`);
116
- if (message.id) this.push(`id: ${message.id}\n`);
117
- if (message.retry) this.push(`retry: ${message.retry}\n`);
118
- if (message.data) this.push(dataString(message.data));
119
- this.push("\n");
120
- callback();
121
- }
122
- write(message, ...args) {
123
- return super.write(message, ...args);
124
- }
125
- };
126
- function dataString(data) {
127
- if (typeof data === "object") return dataString(JSON.stringify(data));
128
- return data.split(/\r\n|\r|\n/).map((line) => `data: ${line}\n`).join("");
129
- }
130
- function createSSEStream(req, res) {
131
- const sse = new SSEStream(req);
132
- sse.pipe(res);
133
- return sse;
134
- }
135
-
136
- //#endregion
137
- exports.createDefineMock = createDefineMock;
138
- exports.createSSEStream = createSSEStream;
139
- exports.defineMock = defineMock;
140
- exports.defineMockData = defineMockData;
package/dist/helper.d.ts DELETED
@@ -1,110 +0,0 @@
1
- import { BodyParserOptions, ExtraRequest, FormidableFile, LogLevel, LogType, Method, MockHttpItem, MockMatchPriority, MockMatchSpecialPriority, MockOptions, MockRequest, MockResponse, MockServerPluginOptions, MockWebsocketItem, ResponseBody, ServerBuildOption, WebSocketSetupContext } from "./types-DPzh7nJq.js";
2
- import { Transform } from "node:stream";
3
- import { IncomingMessage, OutgoingHttpHeaders, ServerResponse } from "node:http";
4
-
5
- //#region src/core/defineMock.d.ts
6
-
7
- /**
8
- * mock config Type helper
9
- *
10
- * mock配置 类型帮助函数
11
- * @param config see config docs:
12
- * {@link https://vite-plugin-mock-dev-server.netlify.app/en/guide/mock-config en-US DOC} |
13
- * {@link https://vite-plugin-mock-dev-server.netlify.app/guide/mock-config zh-CN DOC}
14
- *
15
- * @example
16
- * Mock Http Request
17
- * ```ts
18
- * export default defineMock({
19
- * url: '/api/example',
20
- * method: ['GET', 'POST'],
21
- * body: { a: 1 },
22
- * })
23
- * ```
24
- * ```ts
25
- * export default defineMock({
26
- * url: '/api/example',
27
- * method: 'GET',
28
- * body: ({ query }) => ({ a: 1, b: query.b }),
29
- * })
30
- * ```
31
- * @example
32
- * Mock WebSocket
33
- * ```ts
34
- * export default defineMock({
35
- * url: '/socket.io',
36
- * ws: true,
37
- * setup(wss) {
38
- * wss.on('connection', (ws) => {
39
- * ws.on('message', (rawData) => console.log(rawData))
40
- * ws.send('data')
41
- * })
42
- * },
43
- * })
44
- * ```
45
- */
46
- declare function defineMock(config: MockHttpItem): MockHttpItem;
47
- declare function defineMock(config: MockWebsocketItem): MockWebsocketItem;
48
- declare function defineMock(config: MockOptions): MockOptions;
49
- /**
50
- * Return a custom defineMock function to support preprocessing of mock config.
51
- *
52
- * 返回一个自定义的 defineMock 函数,用于支持对 mock config 的预处理。
53
- * @param transformer preprocessing function
54
- * @example
55
- * ```ts
56
- * const definePostMock = createDefineMock((mock) => {
57
- * mock.url = '/api/post/' + mock.url
58
- * })
59
- * export default definePostMock({
60
- * url: 'list',
61
- * body: [{ title: '1' }, { title: '2' }],
62
- * })
63
- * ```
64
- */
65
- declare function createDefineMock(transformer: (mock: MockHttpItem | MockWebsocketItem) => MockHttpItem | MockWebsocketItem | void): typeof defineMock;
66
- //#endregion
67
- //#region src/core/defineMockData.d.ts
68
- type MockData<T = any> = readonly [() => T, (val: T | ((val: T) => T | void)) => void] & {
69
- value: T;
70
- };
71
- declare function defineMockData<T = any>(key: string, initialData: T): MockData<T>;
72
- //#endregion
73
- //#region src/core/sse.d.ts
74
- interface SSEMessage {
75
- data?: string | object;
76
- comment?: string;
77
- event?: string;
78
- id?: string;
79
- retry?: number;
80
- }
81
- interface WriteHeaders {
82
- writeHead?: (statusCode: number, headers?: OutgoingHttpHeaders) => WriteHeaders;
83
- flushHeaders?: () => void;
84
- }
85
- type HeaderStream = NodeJS.WritableStream & WriteHeaders;
86
- /**
87
- * Transforms "messages" to W3C event stream content.
88
- * See https://html.spec.whatwg.org/multipage/server-sent-events.html
89
- * A message is an object with one or more of the following properties:
90
- * - data (String or object, which gets turned into JSON)
91
- * - event
92
- * - id
93
- * - retry
94
- * - comment
95
- *
96
- * If constructed with a HTTP Request, it will optimise the socket for streaming.
97
- * If this stream is piped to an HTTP Response, it will set appropriate headers.
98
- */
99
- declare class SSEStream extends Transform {
100
- constructor(req: IncomingMessage);
101
- pipe<T extends HeaderStream>(destination: T, options?: {
102
- end?: boolean;
103
- }): T;
104
- _transform(message: SSEMessage, encoding: string, callback: (error?: (Error | null), data?: any) => void): void;
105
- write(message: SSEMessage, encoding?: BufferEncoding, cb?: (error: Error | null | undefined) => void): boolean;
106
- write(message: SSEMessage, cb?: (error: Error | null | undefined) => void): boolean;
107
- }
108
- declare function createSSEStream(req: IncomingMessage, res: ServerResponse): SSEStream;
109
- //#endregion
110
- export { BodyParserOptions, ExtraRequest, FormidableFile, HeaderStream, LogLevel, LogType, Method, MockData, MockHttpItem, MockMatchPriority, MockMatchSpecialPriority, MockOptions, MockRequest, MockResponse, MockServerPluginOptions, MockWebsocketItem, ResponseBody, SSEMessage, ServerBuildOption, WebSocketSetupContext, createDefineMock, createSSEStream, defineMock, defineMockData };