vite-plugin-mock-dev-server 1.3.1 → 1.3.2
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 +54 -0
- package/README.zh-CN.md +50 -0
- package/dist/index.cjs +19 -16
- package/dist/index.d.cts +84 -3
- package/dist/index.d.ts +84 -3
- package/dist/index.js +19 -16
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -235,6 +235,12 @@ export default defineConfig({
|
|
|
235
235
|
}
|
|
236
236
|
```
|
|
237
237
|
|
|
238
|
+
- `options.priority`
|
|
239
|
+
|
|
240
|
+
Custom path matching rule priority。[read more](#Custom-Path-Matching-Priority)
|
|
241
|
+
|
|
242
|
+
**Default:** `undefined`
|
|
243
|
+
|
|
238
244
|
### defineMock(config)
|
|
239
245
|
|
|
240
246
|
Mock Type Helper
|
|
@@ -518,6 +524,54 @@ export default defineMock([
|
|
|
518
524
|
> The `defineMockData` function relies solely on the shared data support provided by `memory`.
|
|
519
525
|
> If persistent mock data is required, it is recommended to use a `nosql` database like `lowdb` or `level`.
|
|
520
526
|
|
|
527
|
+
## Custom-Path-Matching-Priority
|
|
528
|
+
|
|
529
|
+
> Custom rules only affect links with dynamic parameters, such as: `/api/user/:id`
|
|
530
|
+
|
|
531
|
+
The priority of the path matching rules built into the plugin can already meet most needs, but if you need more flexible customization of the matching rule priority, you can use the `priority` parameter.
|
|
532
|
+
|
|
533
|
+
Exp:
|
|
534
|
+
```ts
|
|
535
|
+
import { defineConfig } from 'vite'
|
|
536
|
+
import mockPlugin from 'vite-plugin-mock-dev-server'
|
|
537
|
+
|
|
538
|
+
export default defineConfig({
|
|
539
|
+
plugins: [
|
|
540
|
+
mockPlugin({
|
|
541
|
+
priority: {
|
|
542
|
+
// The priority of matching rules is global.
|
|
543
|
+
// The rules declared in this option will take priority over the default rules.
|
|
544
|
+
// The higher the position of the rule in the array, the higher the priority.
|
|
545
|
+
global: ['/api/:a/b/c', '/api/a/:b/c', '/api/a/b/:c'],
|
|
546
|
+
// For some special cases where the priority of certain rules needs to be adjusted,
|
|
547
|
+
// this option can be used. For example, when a request matches both Rule A and Rule B,
|
|
548
|
+
// and Rule A has a higher priority than Rule B, but it is desired for Rule B to take effect.
|
|
549
|
+
special: {
|
|
550
|
+
// When both A and B or C match, and B or C is at the top of the sort order,
|
|
551
|
+
// insert A into the top position.
|
|
552
|
+
// The `when` option is used to further constrain the priority adjustment to
|
|
553
|
+
// be effective only for certain requests.
|
|
554
|
+
'/api/:a/:b/c': {
|
|
555
|
+
rules: ['/api/a/:b/:c', '/api/a/b/:c'],
|
|
556
|
+
when: ['/api/a/b/c']
|
|
557
|
+
},
|
|
558
|
+
// If no `when` is specified, it means that all requests matching the rules need to have their priorities adjusted. It can be abbreviated as `[key]: [...rules]`
|
|
559
|
+
'/api/:a/b': ['/api/a/:b'],
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
})
|
|
563
|
+
]
|
|
564
|
+
})
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
> **Tip:**
|
|
568
|
+
>
|
|
569
|
+
> `priority` although it can adjust the priority,
|
|
570
|
+
> most of the time you do not need to do so. For some special requests,
|
|
571
|
+
> you can use static rules instead of `priority`,
|
|
572
|
+
> as static rules always have the highest priority.
|
|
573
|
+
|
|
574
|
+
|
|
521
575
|
## Example
|
|
522
576
|
|
|
523
577
|
`mock/**/*.mock.{ts,js,mjs,cjs,json,json5}`
|
package/README.zh-CN.md
CHANGED
|
@@ -230,6 +230,12 @@ export default defineConfig({
|
|
|
230
230
|
}
|
|
231
231
|
```
|
|
232
232
|
|
|
233
|
+
- `options.priority`
|
|
234
|
+
|
|
235
|
+
自定义 路径匹配规则优先级。[查看更多](#自定义匹配优先级)
|
|
236
|
+
|
|
237
|
+
**默认值:** `undefined`
|
|
238
|
+
|
|
233
239
|
### defineMock(config)
|
|
234
240
|
|
|
235
241
|
mock 配置帮助函数,提供类型检查帮助
|
|
@@ -508,6 +514,50 @@ export default defineMock([
|
|
|
508
514
|
> `defineMockData` 仅是基于 `memory` 提供的共享数据支持,
|
|
509
515
|
> 如果需要做 mock 数据持久化,建议使用 `nosql`, 如 `lowdb` 或 `level` 等。
|
|
510
516
|
|
|
517
|
+
|
|
518
|
+
## 自定义匹配优先级
|
|
519
|
+
|
|
520
|
+
> 自定义规则仅影响包含动态参数的链接,如: `/api/user/:id`
|
|
521
|
+
|
|
522
|
+
插件内置的路径匹配规则优先级,已经能够满足大部分需求,但如果你需要更加灵活的自定义匹配规则优先级,
|
|
523
|
+
可以使用 `priority` 参数。
|
|
524
|
+
|
|
525
|
+
示例:
|
|
526
|
+
```ts
|
|
527
|
+
import { defineConfig } from 'vite'
|
|
528
|
+
import mockPlugin from 'vite-plugin-mock-dev-server'
|
|
529
|
+
|
|
530
|
+
export default defineConfig({
|
|
531
|
+
plugins: [
|
|
532
|
+
mockPlugin({
|
|
533
|
+
priority: {
|
|
534
|
+
// 匹配规则优先级, 全局生效。声明在该选项中的规则将优先于默认规则生效。
|
|
535
|
+
// 规则在数组越靠前的位置,优先级越高。
|
|
536
|
+
global: ['/api/:a/b/c', '/api/a/:b/c', '/api/a/b/:c'],
|
|
537
|
+
// 对于一些特殊情况,需要调整部分规则的优先级,可以使用此选项。
|
|
538
|
+
// 比如一个请求同时命中了规则 A 和 B,且 A 比 B 优先级高, 但期望规则 B 生效时。
|
|
539
|
+
special: {
|
|
540
|
+
// 当请求同时命中 [key] 和 rules 中的任意一个时,优先匹配 [key] 。
|
|
541
|
+
// when 用于进一步约束具体是哪些请求需要调整优先级。
|
|
542
|
+
'/api/:a/:b/c': {
|
|
543
|
+
rules: ['/api/a/:b/:c', '/api/a/b/:c'],
|
|
544
|
+
when: ['/api/a/b/c']
|
|
545
|
+
},
|
|
546
|
+
// 如果不需要 when, 则表示命中规则的请求都需要调整优先级。
|
|
547
|
+
// 可以简写为 [key]: [...rules]
|
|
548
|
+
'/api/:a/b': ['/api/a/:b'],
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
})
|
|
552
|
+
]
|
|
553
|
+
})
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
> **注意:**
|
|
557
|
+
>
|
|
558
|
+
> `priority` 虽然可以调整优先级,但大多数时候,你都没有必要这么做。
|
|
559
|
+
> 对于一些特殊情况的请求,可以使用 静态规则来替代 `priority`,静态规则总是拥有最高优先级。
|
|
560
|
+
|
|
511
561
|
## Example
|
|
512
562
|
|
|
513
563
|
`mock/**/*.mock.{ts,js,mjs,cjs,json,json5}`
|
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var kt=Object.create;var se=Object.defineProperty;var ht=Object.getOwnPropertyDescriptor;var yt=Object.getOwnPropertyNames;var vt=Object.getPrototypeOf,Mt=Object.prototype.hasOwnProperty;var bt=(o,t)=>{for(var e in t)se(o,e,{get:t[e],enumerable:!0})},De=(o,t,e,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of yt(t))!Mt.call(o,s)&&s!==e&&se(o,s,{get:()=>t[s],enumerable:!(r=ht(t,s))||r.enumerable});return o};var h=(o,t,e)=>(e=o!=null?kt(vt(o)):{},De(t||!o||!o.__esModule?se(e,"default",{value:o,enumerable:!0}):e,o)),xt=o=>De(se({},"__esModule",{value:!0}),o);var ro={};bt(ro,{baseMiddleware:()=>xe,createDefineMock:()=>Zt,default:()=>oo,defineMock:()=>Yt,defineMockData:()=>to,mockDevServerPlugin:()=>Re,mockWebSocket:()=>Ce,transformMockData:()=>we});module.exports=xt(ro);var wt=()=>typeof document>"u"?new URL("file:"+__filename).href:document.currentScript&&document.currentScript.src||new URL("main.js",document.baseURI).href,O=wt();var ft=require("@pengzhanbo/utils");var Qe=h(require("fs"),1),Z=h(require("fs/promises"),1),B=h(require("path"),1),ee=require("@pengzhanbo/utils"),Ve=h(require("fast-glob"),1),Ke=h(require("is-core-module"),1),ge=require("vite");var Ee="vite-plugin-mock-dev-server",_e="1.3.2";var q=h(require("fs"),1),Ue=require("module"),ue=h(require("path"),1),qe=require("url"),Be=require("esbuild"),Je=h(require("json5"),1);var ie=h(require("fs"),1),ce=h(require("path"),1),Te=require("querystring"),ae=require("url"),Ie=h(require("debug"),1),Ne=require("path-to-regexp"),St=o=>o!==null&&typeof o=="object"&&typeof o.pipe=="function",He=o=>St(o)&&o.readable!==!1&&typeof o._read=="function"&&typeof o._readableState=="object";function Fe(o){return ce.default.dirname((0,ae.fileURLToPath)(o))}var pe=(0,Ie.default)("vite:mock-dev-server");function X(o,t,e){for(let s of t){let n=ce.default.join(o,s);if(ie.default.existsSync(n)&&ie.default.statSync(n).isFile()){let i=e!=null&&e.pathOnly?n:ie.default.readFileSync(n,"utf-8");if(!(e!=null&&e.predicate)||e.predicate(i))return i}}let r=ce.default.dirname(o);if(r!==o&&(!(e!=null&&e.rootDir)||r.startsWith(e==null?void 0:e.rootDir)))return X(r,t,e)}var le=(o={})=>{let t=[],e=[];return Object.keys(o).forEach(r=>{var n,i;let s=o[r];typeof s=="string"||!s.ws&&!((n=s.target)!=null&&n.toString().startsWith("ws:"))&&!((i=s.target)!=null&&i.toString().startsWith("wss:"))?t.push(r):e.push(r)}),{httpProxies:t,wsProxies:e}};function G(o,t){return o[0]==="^"&&new RegExp(o).test(t)||t.startsWith(o)}function Y(o,t){return((0,Ne.match)(o,{decode:decodeURIComponent})(t)||{params:{}}).params||{}}function D(o){let t=new ae.URL(o,"http://example.com"),e=decodeURIComponent(t.pathname),r=(0,Te.parse)(t.search.replace(/^\?/,""));return{pathname:e,query:r}}var Ot={name:"externalize-deps",setup(o){o.onResolve({filter:/.*/},({path:t})=>{if(t[0]!=="."&&!ue.default.isAbsolute(t))return{external:!0}})}},Ct={name:"json5-loader",setup(o){o.onLoad({filter:/\.json5$/},async({path:t})=>{let e=await q.promises.readFile(t,"utf-8");return{contents:`export default ${JSON.stringify(Je.default.parse(e))}`,loader:"js"}})}},Pt={name:"json-loader",setup(o){o.onLoad({filter:/\.json$/},async({path:t})=>({contents:`export default ${await q.promises.readFile(t,"utf-8")}`,loader:"js"}))}},Rt=o=>({name:"alias-plugin",setup(t){t.onResolve({filter:/.*/},async({path:e})=>{let r=o.find(({find:c})=>Wt(c,e));if(!r)return null;let{find:s,replacement:n}=r;return{path:(await t.resolve(e.replace(s,n),{kind:"import-statement",resolveDir:n,namespace:"file"})).path,external:!1}})}});function Wt(o,t){return o instanceof RegExp?o.test(t):t.length<o.length?!1:t===o?!0:t.startsWith(`${o}/`)}async function me(o,t){var n;let{isESM:e=!0,define:r,alias:s}=t;try{let i=await(0,Be.build)({entryPoints:[o],outfile:"out.js",write:!1,target:["node14.18","node16"],platform:"node",bundle:!0,metafile:!0,format:e?"esm":"cjs",define:r,plugins:[Rt(s),Ot,Pt,Ct]});return{code:i.outputFiles[0].text,deps:((n=i.metafile)==null?void 0:n.inputs)||{}}}catch(i){console.error(i)}return{code:"",deps:{}}}var jt=Fe(O),U=(0,Ue.createRequire)(jt);async function Ae(o,t,e,r){if(e){let s=`${o}.timestamp-${Date.now()}`,n=`${s}.mjs`,i=`${(0,qe.pathToFileURL)(s)}.mjs`;await q.promises.writeFile(n,t,"utf8");try{return await import(i)}finally{try{q.default.unlinkSync(n)}catch{}}}else{o=ue.default.resolve(r,o);let s=ue.default.extname(o),n=q.default.realpathSync(o),i=s in U.extensions?s:".js",c=U.extensions[i];U.extensions[i]=(p,m)=>{m===n?p._compile(t,m):c(p,m)},delete U.cache[U.resolve(o)];let a=U(o);return U.extensions[i]=c,a.__esModule?a:{default:a}}}var ye=h(require("picocolors"),1);var Ge=require("@pengzhanbo/utils"),L=h(require("picocolors"),1),ze={silent:0,error:1,warn:2,info:3,debug:4};function de(o,t="info"){o=`[${o}]`;function e(s,n,i){if(i=(0,Ge.isBoolean)(i)?i?t:"error":i,ze[i]>=ze[s]){let a=s==="info"||s==="debug"?"log":s,p=s==="debug"?L.default.magenta(L.default.bold(o)):s==="info"?L.default.cyan(L.default.bold(o)):s==="warn"?L.default.yellow(L.default.bold(o)):L.default.red(L.default.bold(o)),m=`${L.default.dim(new Date().toLocaleTimeString())} ${p} ${n}`;console[a](m)}}return{debug(s,n=t){e("debug",s,n)},info(s,n=t){e("info",s,n)},warn(s,n=t){e("warn",s,n)},error(s,n=t){e("error",s,n)}}}var $t=/import\.meta\.env\.(.+)/;function fe(o){let t=de("vite:mock-dev-server","warn"),e={},r=process.env.NODE_ENV||o.mode;Object.assign(e,{"process.env.NODE_ENV":JSON.stringify(r),"global.process.env.NODE_ENV":JSON.stringify(r),"globalThis.process.env.NODE_ENV":JSON.stringify(r),__vite_process_env_NODE_ENV:JSON.stringify(r)});let s={},n={},i=[];for(let p in o.define){let m=o.define[p];if(typeof m=="string")try{JSON.parse(m),s[p]=m}catch{i.push(p)}else s[p]=JSON.stringify(m);let d=p.match($t);d&&s[p]&&(n[d[1]]=`__vite__define__${s[p]}`)}i.length&&t.warn(`The following keys: ${ye.default.yellow(ye.default.underline(i.join(", ")))} declared in 'define' cannot be parsed as regular code snippets.`);let c={},a={};c["import.meta.hot"]="undefined";for(let p in o.env)c[`import.meta.env.${p}`]=JSON.stringify(o.env[p]);return Object.assign(a,{"import.meta.env":JSON.stringify({...o.env,...n}).replace(/"__vite__define__(.+?)"([,}])/g,(p,m,d)=>`${m.replace(/(^\\")|(\\"$)/g,'"')}${d}`)}),{...c,...s,...a,...e}}async function Xe(o,t,e){let r=(0,ee.toArray)(e.include),s=(0,ee.toArray)(e.exclude),n=fe(t),{httpProxies:i}=le(t.server.proxy||{});i.push(...(0,ee.toArray)(e.prefix));let c=(0,ee.toArray)(e.wsPrefix),a={};try{let l=X(t.root,["package.json"]);l&&(a=JSON.parse(l))}catch{}let p=e.build.dist,m=await _t(process.cwd(),r,s),d=B.default.join(t.root,`mock-data-${Date.now()}.js`);await Z.default.writeFile(d,m,"utf-8");let{code:y,deps:v}=await me(d,{define:n,alias:t.resolve.alias}),W=Dt(v);await Z.default.unlink(d);let u=[{filename:B.default.join(p,"mock-data.js"),source:y},{filename:B.default.join(p,"index.js"),source:Et(i,c,e.cookiesOptions,e.priority,e.build.serverPort)},{filename:B.default.join(p,"package.json"),source:Lt(a,W)}];try{if(B.default.isAbsolute(p)){await Z.default.rm(p,{recursive:!0}),Qe.default.mkdirSync(p,{recursive:!0});for(let{filename:l,source:f}of u)await Z.default.writeFile(l,f,"utf-8")}else for(let{filename:l,source:f}of u)o.emitFile({type:"asset",fileName:l,source:f})}catch{}}function Dt(o){let t=new Set,e=[Ee,"connect","cors"];return Object.keys(o).forEach(r=>{o[r].imports.filter(n=>n.external&&!n.path.startsWith("<define:")).map(n=>n.path).forEach(n=>{!e.includes(n)&&!(0,Ke.default)(n)&&t.add(n)})}),Array.from(t)}function Lt(o,t){let{dependencies:e={},devDependencies:r={}}=o,s={...e,...r},n={name:"mock-server",type:"module",scripts:{start:"node index.js"},dependencies:{connect:"^3.7.0","vite-plugin-mock-dev-server":`^${_e}`,cors:"^2.8.5"},pnpm:{peerDependencyRules:{ignoreMissing:["vite"]}}};return t.forEach(i=>{n.dependencies[i]=s[i]||"latest"}),JSON.stringify(n,null,2)}function Et(o,t,e={},r={},s=8080){return`import { createServer } from 'node:http';
|
|
2
2
|
import connect from 'connect';
|
|
3
3
|
import corsMiddleware from 'cors';
|
|
4
4
|
import { baseMiddleware, mockWebSocket } from 'vite-plugin-mock-dev-server';
|
|
@@ -9,6 +9,7 @@ const server = createServer(app);
|
|
|
9
9
|
const httpProxies = ${JSON.stringify(o)};
|
|
10
10
|
const wsProxies = ${JSON.stringify(t)};
|
|
11
11
|
const cookiesOptions = ${JSON.stringify(e)};
|
|
12
|
+
const priority = ${JSON.stringify(r)};
|
|
12
13
|
|
|
13
14
|
mockWebSocket({ mockData }, server, wsProxies, cookiesOptions);
|
|
14
15
|
|
|
@@ -16,13 +17,14 @@ app.use(corsMiddleware());
|
|
|
16
17
|
app.use(baseMiddleware({ mockData }, {
|
|
17
18
|
formidableOptions: { multiples: true },
|
|
18
19
|
proxies: httpProxies,
|
|
20
|
+
priority,
|
|
19
21
|
cookiesOptions,
|
|
20
22
|
}));
|
|
21
23
|
|
|
22
|
-
server.listen(${
|
|
24
|
+
server.listen(${s});
|
|
23
25
|
|
|
24
|
-
console.log('listen: http://localhost:${
|
|
25
|
-
`}async function
|
|
26
|
+
console.log('listen: http://localhost:${s}');
|
|
27
|
+
`}async function _t(o,t,e){let r=await(0,Ve.default)(t,{cwd:o}),s=(0,ge.createFilter)(t,e,{resolve:!1}),n=r.filter(s),i="",c="";return n.forEach((a,p)=>{let m=(0,ge.normalizePath)(B.default.join(o,a));i+=`import * as m${p} from '${m}';
|
|
26
28
|
`,c+=`m${p}, `}),`import { transformMockData } from 'vite-plugin-mock-dev-server';
|
|
27
29
|
${i}
|
|
28
30
|
const exporters = [${c}];
|
|
@@ -40,18 +42,19 @@ const mockList = exporters.map((raw) => {
|
|
|
40
42
|
}
|
|
41
43
|
return mockConfig
|
|
42
44
|
});
|
|
43
|
-
export default transformMockData(mockList);`}var
|
|
44
|
-
${
|
|
45
|
-
|
|
46
|
-
${C}
|
|
47
|
-
|
|
45
|
+
export default transformMockData(mockList);`}var A=require("@pengzhanbo/utils"),mt=h(require("cors"),1),dt=require("path-to-regexp");var be=require("buffer"),S=require("@pengzhanbo/utils"),nt=h(require("cookies"),1),st=h(require("http-status"),1),re=h(require("mime-types"),1),it=require("path-to-regexp"),g=h(require("picocolors"),1);var P=require("@pengzhanbo/utils"),te=require("path-to-regexp"),ve={};function oe(o){if(ve[o])return ve[o];let t=(0,te.parse)(o),e=[];for(let r of t)if(!(0,P.isString)(r))e.push(r);else{let s=r[0]==="/",n=s?r.slice(1).split("/"):r.split("/");e.push(`${s?"/":""}${n[0]}`,...n.slice(1).map(i=>`/${i}`))}return ve[o]=e,e}function Tt(o){let t=o.map(e=>oe(e).length);return t=t.length===0?[1]:t,Math.max(...t)+2}function It(o){let t=oe(o),e=0;for(let r=0;r<t.length;r++){let s=t[r];(0,P.isString)(s)||(e+=10**(r+1)),e+=10**(r+1)}return e}function Nt(o){let t=[],e=[];for(let r of o){let n=oe(r).filter(i=>typeof i!="string").length;e[n]||(e[n]=[]),e[n].push(r)}for(let r of e.filter(s=>s&&s.length>0))t=[...t,...(0,P.sortBy)(r,It)];return t}function Ht(o){let t=Tt(o);return(0,P.sortBy)(o,e=>{let r=oe(e),s=r.filter(c=>typeof c!="string");if(s.length===0)return 0;let n=s.length,i=0;for(let c=0;c<r.length;c++){let a=r[c],p=!(0,P.isString)(a),{pattern:m="",modifier:d,prefix:y,name:v}=p?a:{},W=m&&m.includes(".*"),u=y==="/",l=(0,P.isString)(v);i+=p&&u?1:0,c===r.length-1&&W?n+=5*10**t:W?n+=3*10**(t-1):m&&(u?n+=(l?2:1)*10**(i+1):n-=1*10**i),d==="+"&&(n+=1*10**(t-1)),d==="*"&&(n+=1*10**(t-1)+1),d==="?"&&(n+=1*10**(i+(u?1:0)))}return n})}function Ye(o,t,e){let r=Ht(Nt(o.filter(v=>(0,te.pathToRegexp)(v).test(t)))),{global:s=[],special:n={}}=e;if(s.length===0&&(0,P.isEmptyObject)(n)||r.length===0)return r;let[i,c]=Ft(r),a=s.filter(v=>c.includes(v));if(a.length>0&&(r=(0,P.uniq)([...i,...a,...c])),(0,P.isEmptyObject)(n))return r;let p=Object.keys(n).filter(v=>r.includes(v))[0];if(!p)return r;let m=n[p],{rules:d,when:y}=(0,P.isArray)(m)?{rules:m,when:[]}:m;return d.includes(r[0])&&(y.length===0||y.some(v=>(0,te.pathToRegexp)(v).test(t)))&&(r=(0,P.uniq)([p,...r])),r}function Ft(o){let t=[],e=[];for(let r of o)oe(r).filter(i=>typeof i!="string").length>0?e.push(r):t.push(r);return[t,e]}var ke=h(require("co-body"),1),Ze=h(require("formidable"),1);async function et(o,t){var s;let e=o.method.toUpperCase();if(["GET","DELETE","HEAD"].includes(e))return;let r=((s=o.headers["content-type"])==null?void 0:s.toLocaleLowerCase())||"";try{if(r.startsWith("application/json"))return await ke.default.json(o);if(r.startsWith("application/x-www-form-urlencoded"))return await ke.default.form(o);if(r.startsWith("text/plain"))return await ke.default.text(o);if(r.startsWith("multipart/form-data"))return await Ut(o,t)}catch(n){console.error(n)}}async function Ut(o,t){let e=(0,Ze.default)(t);return new Promise((r,s)=>{e.parse(o,(n,i,c)=>{if(n){s(n);return}r({...i,...c})})})}var Q=require("@pengzhanbo/utils");function tt(o,t){return T(o.headers,t.headers)&&T(o.body,t.body)&&T(o.params,t.params)&&T(o.query,t.query)&&T(o.refererQuery,t.refererQuery)}function T(o,t){if(!t)return!0;for(let e in t)if(!ot(o[e],t[e]))return!1;return!0}function ot(o,t){if((0,Q.isArray)(o)&&(0,Q.isArray)(t)){let e=new Set;return t.every(r=>o.some((s,n)=>{if(e.has(n))return!1;let i=ot(s,r);return i&&e.add(n),i}))}return(0,Q.isObject)(o)&&(0,Q.isObject)(t)?T(o,t):Object.is(o,t)}function xe(o,{formidableOptions:t={},proxies:e,cookiesOptions:r,logger:s,priority:n={}}){return async function(i,c,a){let p=(0,S.timestamp)(),{query:m,pathname:d}=D(i.url);if(!d||e.length===0||!e.some(w=>G(w,i.url)))return a();let y=o.mockData,v=Ye(Object.keys(y),d,n);if(v.length===0)return a();let{query:W}=D(i.headers.referer||""),u=await et(i,t),l=new nt.default(i,c,r),f=l.get.bind(l),M=i.method.toUpperCase(),b,R;for(let w of v)if(b=qt(y[w],s,{pathname:d,method:M,request:{query:m,refererQuery:W,body:u,headers:i.headers,getCookie:f}}),b){R=w;break}if(!b){let w=v.map(K=>K===R?g.default.underline(g.default.bold(K)):g.default.dim(K)).join(", ");return s.warn(`${g.default.green(d)} matches ${w} , but mock data is not found.`),a()}let k=i,x=c;k.body=u,k.query=m,k.refererQuery=W,k.params=Y(b.url,d),k.getCookie=f,x.setCookie=l.set.bind(l);let{body:j,delay:H,type:F="json",response:_,status:E=200,statusText:ne,log:V,__filepath__:C}=b;if(Me(x,E,ne),await Bt(k,x,b,s),await Jt(k,x,b,s),s.info(Gt(k,C),V),s.debug(`${g.default.magenta("DEBUG")} ${g.default.underline(d)} matches: [ ${v.map(w=>w===R?g.default.underline(g.default.bold(w)):g.default.dim(w)).join(", ")} ]
|
|
46
|
+
`),j){try{let w=(0,S.isFunction)(j)?await j(k):j;await rt(p,H),At(x,w,F)}catch(w){s.error(`${g.default.red(`mock error at ${d}`)}
|
|
47
|
+
${w}
|
|
48
|
+
at body (${g.default.underline(C)})`,V),Me(x,500),c.end("")}return}if(_){try{await rt(p,H),await _(k,x,a)}catch(w){s.error(`${g.default.red(`mock error at ${d}`)}
|
|
49
|
+
${w}
|
|
50
|
+
at response (${g.default.underline(C)})`,V),Me(x,500),c.end("")}return}c.end("")}}function qt(o,t,{pathname:e,method:r,request:s}){return o.find(n=>{if(!e||!n||!n.url||n.ws===!0||!(n.method?(0,S.isArray)(n.method)?n.method:[n.method]:["GET","POST"]).includes(r))return!1;let c=(0,it.pathToRegexp)(n.url).test(e);if(c&&n.validator){let a=Y(n.url,e);if((0,S.isFunction)(n.validator))return n.validator({params:a,...s});try{return tt({params:a,...s},n.validator)}catch(p){let m=n.__filepath__;return t.error(`${g.default.red(`mock error at ${e}`)}
|
|
48
51
|
${p}
|
|
49
|
-
at validator (${
|
|
52
|
+
at validator (${g.default.underline(m)})`,n.log),!1}}return c})}function Me(o,t=200,e){o.statusCode=t,o.statusMessage=e||zt(t)}async function Bt(o,t,e,r){let{headers:s,type:n="json"}=e,i=e.__filepath__,c=re.contentType(n)||re.contentType(re.lookup(n)||"");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"),t.setHeader("X-File-Path",i),!!s)try{let a=(0,S.isFunction)(s)?await s(o):s;Object.keys(a).forEach(p=>{t.setHeader(p,a[p])})}catch(a){r.error(`${g.default.red(`mock error at ${o.url.split("?")[0]}`)}
|
|
50
53
|
${a}
|
|
51
|
-
at headers (${
|
|
54
|
+
at headers (${g.default.underline(i)})`,e.log)}}async function Jt(o,t,e,r){let{cookies:s}=e,n=e.__filepath__;if(s)try{let i=(0,S.isFunction)(s)?await s(o):s;Object.keys(i).forEach(c=>{let a=i[c];if((0,S.isArray)(a)){let[p,m]=a;t.setCookie(c,p,m)}else t.setCookie(c,a)})}catch(i){r.error(`${g.default.red(`mock error at ${o.url.split("?")[0]}`)}
|
|
52
55
|
${i}
|
|
53
|
-
at cookies (${
|
|
54
|
-
${
|
|
55
|
-
at setup (${
|
|
56
|
-
${
|
|
57
|
-
at setup (${
|
|
56
|
+
at cookies (${g.default.underline(n)})`,e.log)}}function At(o,t,e){if(He(t))t.pipe(o);else if(be.Buffer.isBuffer(t))o.end(e==="text"||e==="json"?t.toString("utf-8"):t);else{let r=typeof t=="string"?t:JSON.stringify(t);o.end(e==="buffer"?be.Buffer.from(r):r)}}async function rt(o,t){if(!t||typeof t=="number"&&t<=0||(0,S.isArray)(t)&&t.length!==2)return;let e=0;if((0,S.isArray)(t)){let[r,s]=t;e=(0,S.random)(r,s)}else e=t-((0,S.timestamp)()-o);e>0&&await(0,S.sleep)(e)}function zt(o){return st.default[o]||"Unknown"}function Gt(o,t){let{url:e,method:r,query:s,params:n,body:i}=o,{pathname:c}=new URL(e,"http://example.com");c=g.default.green(decodeURIComponent(c));let a=(W,u)=>!u||(0,S.isEmptyObject)(u)?"":` ${g.default.gray(`${W}:`)}${JSON.stringify(u)}`,p=g.default.magenta(g.default.bold(r)),m=a("query",s),d=a("params",n),y=a("body",i),v=` ${g.default.dim(g.default.underline(`(${t})`))}`;return`${p} ${c}${m}${d}${y}${v}`}var ct=h(require("events"),1),N=require("@pengzhanbo/utils"),Se=h(require("chokidar"),1),at=h(require("fast-glob"),1),I=require("vite");var $=require("@pengzhanbo/utils");function we(o){let t=[];for(let[,r]of o.entries())r&&((0,$.isArray)(r)?t.push(...r):t.push(r));let e={};return t.filter(r=>(0,$.isObject)(r)&&r.enabled!==!1&&r.url).forEach(r=>{let{pathname:s,query:n}=D(r.url),i=e[s]??=[],c={...r,url:s};if(c.ws!==!0){let a=c.validator;(0,$.isEmptyObject)(n)||((0,$.isFunction)(a)?c.validator=function(p){return T(p.query,n)&&a(p)}:a?(c.validator={...a},c.validator.query=c.validator.query?{...n,...c.validator.query}:n):c.validator={query:n})}i.push(c)}),Object.keys(e).forEach(r=>{e[r]=(0,$.sortBy)(e[r],s=>{if(s.ws===!0)return 0;let{validator:n}=s;return!n||(0,$.isEmptyObject)(n)?2:(0,$.isFunction)(n)?0:1/Object.keys(n).reduce((c,a)=>c+Qt(n[a]),0)})}),e}function Qt(o){return o?Object.keys(o).length:0}var he=class extends ct.default{constructor(e){super();this.options=e;this.cwd=e.cwd||process.cwd();try{let r=X(this.cwd,["package.json"]);this.moduleType=r&&JSON.parse(r).type==="module"?"esm":"cjs"}catch{}}moduleCache=new Map;moduleDeps=new Map;cwd;mockWatcher;depsWatcher;moduleType="cjs";_mockData={};get mockData(){return this._mockData}load(){let{include:e,exclude:r}=this.options,s=(0,I.createFilter)(e,r,{resolve:!1});(0,at.default)(e,{cwd:this.cwd}).then(i=>i.filter(s).map(c=>()=>this.loadMock(c))).then(i=>(0,N.promiseParallel)(i,10)).then(()=>this.updateMockList()),this.watchMockEntry(),this.watchDeps();let n=null;this.on("mock:update",async i=>{s(i)&&(await this.loadMock(i),n&&clearImmediate(n),n=setImmediate(()=>{this.updateMockList(),this.emit("mock:update-end",i),n=null}))}),this.on("mock:unlink",async i=>{s(i)&&(this.moduleCache.delete(i),this.updateMockList(),this.emit("mock:update-end",i))})}watchMockEntry(){let{include:e}=this.options,[r,...s]=e,n=this.mockWatcher=Se.default.watch(r,{ignoreInitial:!0,cwd:this.cwd});s.length>0&&s.forEach(i=>n.add(i)),n.on("add",async i=>{i=(0,I.normalizePath)(i),this.emit("mock:update",i),pe("watcher:add",i)}),n.on("change",async i=>{i=(0,I.normalizePath)(i),this.emit("mock:update",i),pe("watcher:change",i)}),n.on("unlink",async i=>{i=(0,I.normalizePath)(i),this.emit("mock:unlink",i),pe("watcher:unlink",i)})}watchDeps(){let e=[];this.depsWatcher=Se.default.watch([],{ignoreInitial:!0,cwd:this.cwd}),this.depsWatcher.on("change",r=>{r=(0,I.normalizePath)(r);let s=this.moduleDeps.get(r);s&&s.forEach(n=>{this.emit("mock:update",n)})}),this.depsWatcher.on("unlink",r=>{r=(0,I.normalizePath)(r),this.moduleDeps.delete(r)}),this.on("update:deps",()=>{let r=[];for(let[n]of this.moduleDeps.entries())r.push(n);let s=r.filter(n=>!e.includes(n));s.length>0&&this.depsWatcher.add(s)})}close(){var e,r;(e=this.mockWatcher)==null||e.close(),(r=this.depsWatcher)==null||r.close()}updateMockList(){this._mockData=we(this.moduleCache)}updateModuleDeps(e,r){Object.keys(r).forEach(s=>{r[s].imports.map(i=>i.path).forEach(i=>{this.moduleDeps.has(i)||this.moduleDeps.set(i,new Set),this.moduleDeps.get(i).add(e)})}),this.emit("update:deps")}async loadMock(e){if(!e)return;let r=!1;/\.m[jt]s$/.test(e)?r=!0:/\.c[jt]s$/.test(e)?r=!1:r=this.moduleType==="esm";let{define:s,alias:n}=this.options,{code:i,deps:c}=await me(e,{isESM:r,define:s,alias:n});try{let a=await Ae(e,i,r,this.cwd)||{},p;(0,N.hasOwn)(a,"default")?p=a.default:(p=[],Object.keys(a).forEach(m=>p.push(...(0,N.toArray)(a[m])))),(0,N.isArray)(p)?p.forEach(m=>m.__filepath__=e):p.__filepath__=e,this.moduleCache.set(e,p),this.updateModuleDeps(e,c)}catch(a){console.error(a)}}};var lt=h(require("cookies"),1),Oe=require("path-to-regexp"),J=h(require("picocolors"),1),ut=require("ws");function Ce({loader:o,httpServer:t,proxies:e,cookiesOptions:r,logger:s}){var W;let n=new Map,i=new Map,c=new WeakMap,a=u=>{let l=i.get(u);return!l&&i.set(u,l=new Map),l},p=(u,l)=>{let f=u.get(l);return!f&&u.set(l,f=new ut.WebSocketServer({noServer:!0})),f},m=(u,l)=>{let f=n.get(u);!f&&n.set(u,f=new Set),f.add(l)},d=(u,l,f,M,b,R)=>{var k;try{(k=f.setup)==null||k.call(f,l,M),l.on("close",()=>u.delete(b)),l.on("error",x=>{s.error(`${J.default.red(`WebSocket mock error at ${l.path}`)}
|
|
57
|
+
${x}
|
|
58
|
+
at setup (${R})`,f.log)})}catch(x){s.error(`${J.default.red(`WebSocket mock error at ${l.path}`)}
|
|
59
|
+
${x}
|
|
60
|
+
at setup (${R})`,f.log)}},y=(u,l,f,M)=>{u.emit("connection",l,f),l.on("close",()=>{let b=M.findIndex(R=>R.ws===l);b!==-1&&M.splice(b,1)})},v=(u,l,f,M,b)=>{let{cleanupList:R,connectionList:k,context:x}=c.get(l);pt(R),k.forEach(({ws:j})=>j.removeAllListeners()),l.removeAllListeners(),d(u,l,f,x,M,b),k.forEach(({ws:j,req:H})=>y(l,j,H,k))};(W=o.on)==null||W.call(o,"mock:update-end",u=>{if(!n.has(u))return;let l=n.get(u);if(l)for(let f of l.values())for(let M of o.mockData[f]){if(!M.ws||M.__filepath__!==u)return;let b=a(f);for(let[R,k]of b.entries())v(b,k,M,R,u)}}),t==null||t.on("upgrade",(u,l,f)=>{let{pathname:M,query:b}=D(u.url);if(!M||e.length===0||!e.some(C=>G(C,u.url)))return;let R=o.mockData,k=Object.keys(R).find(C=>(0,Oe.pathToRegexp)(C).test(M));if(!k)return;let x=R[k].find(C=>C.url&&C.ws&&(0,Oe.pathToRegexp)(C.url).test(M));if(!x)return;let j=x.__filepath__;m(j,k);let H=a(k),F=p(H,M),_=c.get(F);if(!_){let C=[],w={onCleanup:K=>C.push(K)};_={cleanupList:C,context:w,connectionList:[]},c.set(F,_),d(H,F,x,w,M,j)}let E=u,ne=new lt.default(u,u,r),{query:V}=D(u.headers.referer||"");E.query=b,E.refererQuery=V,E.params=Y(k,M),E.getCookie=ne.get.bind(ne),F.handleUpgrade(E,l,f,C=>{s.info(`${J.default.magenta(J.default.bold("WebSocket"))} ${J.default.green(u.url)} connected ${J.default.dim(`(${j})`)}`,x.log),_.connectionList.push({req:E,ws:C}),y(F,C,E,_.connectionList)})}),t==null||t.on("close",()=>{for(let u of i.values()){for(let l of u.values()){let f=c.get(l);pt(f.cleanupList),l.close()}u.clear()}i.clear(),n.clear()})}function pt(o){let t;for(;t=o.shift();)t==null||t()}function Pe(o,t,e,r){let s=de("vite:mock",(0,A.isBoolean)(t.log)?t.log?"info":"error":t.log),n=new he({include:(0,A.toArray)(t.include),exclude:(0,A.toArray)(t.exclude),define:fe(o),alias:o.resolve.alias});n.load(),n.on("mock:update-end",()=>{t.reload&&(r==null||r.send({type:"full-reload"}))}),e==null||e.on("close",()=>n.close());let{httpProxies:i}=le(o.server.proxy||{}),a=[...(0,A.toArray)(t.prefix),...i];Ce({loader:n,httpServer:e,proxies:(0,A.toArray)(t.wsPrefix),cookiesOptions:t.cookiesOptions,logger:s});let p=[];return p.push(Vt(n,a,o,t),xe(n,{formidableOptions:t.formidableOptions,proxies:a,cookiesOptions:t.cookiesOptions,priority:t.priority,logger:s})),p.filter(Boolean)}function Vt(o,t,e,r){let s={},n=r.cors===!1?!1:e.server.cors!==!1;return n&&e.server.cors!==!1&&(s={...s,...typeof e.server.cors=="boolean"?{}:e.server.cors}),n&&r.cors!==!1&&(s={...s,...typeof r.cors=="boolean"?{}:r.cors}),n?function(i,c,a){let{pathname:p}=D(i.url);if(!p||t.length===0||!t.some(y=>G(y,i.url)))return a();let m=o.mockData;if(!Object.keys(m).find(y=>(0,dt.pathToRegexp)(y).test(p)))return a();(0,mt.default)(s)(i,c,a)}:void 0}function Re({prefix:o=[],wsPrefix:t=[],include:e=["mock/**/*.mock.{js,ts,cjs,mjs,json,json5}"],exclude:r=["**/node_modules/**","**/.vscode/**","**/.git/**"],reload:s=!1,log:n="info",cors:i=!0,formidableOptions:c={},build:a=!1,cookiesOptions:p={},priority:m={}}={}){let d={prefix:o,wsPrefix:t,include:e,exclude:r,reload:s,cors:i,cookiesOptions:p,log:n,formidableOptions:{multiples:!0,...c},priority:m,build:a?Object.assign({serverPort:8080,dist:"mockServer"},typeof a=="object"?a:{}):!1},y=[Xt(d)];return d.build&&y.push(Kt(d)),y}function Kt(o){let t={};return{name:"vite-plugin-mock-dev-server-generator",enforce:"post",apply:"build",configResolved(e){t=e,e.logger.warn("")},async buildEnd(e){e||t.command==="build"&&await Xe(this,t,o)}}}function Xt(o){let t={};return{name:"vite-plugin-mock-dev-server",enforce:"pre",apply:"serve",config(e){var n;let r=(0,ft.toArray)(o.wsPrefix);if(r.length===0||!((n=e.server)!=null&&n.proxy)||Object.keys(e.server.proxy).length===0)return;let s={};Object.keys(e.server.proxy).forEach(i=>{r.includes(i)||(s[i]=e.server.proxy[i])}),e.server.proxy=s},configResolved(e){t=e,e.logger.warn("")},configureServer({middlewares:e,config:r,httpServer:s,ws:n}){Pe(r,o,s,n).forEach(c=>e.use(c))},configurePreviewServer({middlewares:e,httpServer:r}){Pe(t,o,r).forEach(n=>e.use(n))}}}var gt=require("@pengzhanbo/utils");function Yt(o){return o}function Zt(o){return e=>((0,gt.isArray)(e)?e=e.map(r=>o(r)||r):e=o(e)||e,e)}var z=require("@pengzhanbo/utils"),We=new Map,je=new WeakMap,eo=70,$e=class{value;#e;#t;constructor(t){this.value=t,this.#e=(0,z.deepClone)(t),this.#t=Date.now()}hotUpdate(t){Date.now()-this.#t<eo||(0,z.deepEqual)(t,this.#e)||(this.value=t,this.#e=(0,z.deepClone)(t),this.#t=Date.now())}};function to(o,t){We.has(o)||We.set(o,new $e(t));let e=We.get(o);if(e.hotUpdate(t),je.has(e))return je.get(e);let r=[()=>e.value,s=>{(0,z.isFunction)(s)&&(s=s(e.value)??e.value),e.value=s}];return Object.defineProperty(r,"value",{get(){return e.value},set(s){e.value=s}}),je.set(e,r),r}var oo=Re;0&&(module.exports={baseMiddleware,createDefineMock,defineMock,defineMockData,mockDevServerPlugin,mockWebSocket,transformMockData});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Connect, Plugin, ResolvedConfig } from 'vite';
|
|
2
2
|
import { Buffer } from 'node:buffer';
|
|
3
3
|
import http from 'node:http';
|
|
4
4
|
import { Readable } from 'node:stream';
|
|
@@ -97,6 +97,83 @@ interface MockServerPluginOptions {
|
|
|
97
97
|
* @default false
|
|
98
98
|
*/
|
|
99
99
|
build?: boolean | ServerBuildOption;
|
|
100
|
+
/**
|
|
101
|
+
* Priority sorting for path matching rules is valid only for rules containing dynamic parameters.
|
|
102
|
+
* In most cases, the default sorting rules can meet the needs.
|
|
103
|
+
* However, in some cases where custom sorting rules are required, this option can be used.
|
|
104
|
+
*
|
|
105
|
+
* 路径匹配规则优先级排序,仅对包含动态参数的规则有效。
|
|
106
|
+
* 大部分情况下默认的排序规则都可以满足需求。
|
|
107
|
+
* 但有些情况下,需要自定义排序规则时,可以使用此选项。
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```ts
|
|
111
|
+
* export default {
|
|
112
|
+
* priority: {
|
|
113
|
+
* global: ['/api/:a/b/c', '/api/a/:b/c', '/api/a/b/:c'],
|
|
114
|
+
* special: {
|
|
115
|
+
* '/api/:a/:b/c': {
|
|
116
|
+
* rules: ['/api/a/:b/:c', '/api/a/b/:c'],
|
|
117
|
+
* when: ['/api/a/b/c']
|
|
118
|
+
* }
|
|
119
|
+
* }
|
|
120
|
+
* }
|
|
121
|
+
* }
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
priority?: MockMatchPriority;
|
|
125
|
+
}
|
|
126
|
+
interface MockMatchPriority {
|
|
127
|
+
/**
|
|
128
|
+
* The priority of matching rules is global.
|
|
129
|
+
* The rules declared in this option will take priority over the default rules.
|
|
130
|
+
* The higher the position of the rule in the array, the higher the priority.
|
|
131
|
+
*
|
|
132
|
+
* Do not declare general rules in this option, such as /api/(.*),
|
|
133
|
+
* as it will prevent subsequent rules from taking effect.
|
|
134
|
+
* Unless you are clear about the priority of the rules,
|
|
135
|
+
* most of the time you do not need to configure this option.
|
|
136
|
+
|
|
137
|
+
* 匹配规则优先级, 全局生效。
|
|
138
|
+
* 声明在该选项中的规则将优先于默认规则生效。
|
|
139
|
+
* 规则在数组越靠前的位置,优先级越高。
|
|
140
|
+
*
|
|
141
|
+
* 不要在此选项中声明通用性的规则,比如 `/api/(.*)`,这将导致后续的规则无法生效。
|
|
142
|
+
* 除非你明确知道规则的优先级,否则大多数情况下都不需要配置该选项。
|
|
143
|
+
* @default []
|
|
144
|
+
*/
|
|
145
|
+
global?: string[];
|
|
146
|
+
/**
|
|
147
|
+
* For some special cases where the priority of certain rules needs to be adjusted,
|
|
148
|
+
* this option can be used. For example, when a request matches both Rule A and Rule B,
|
|
149
|
+
* and Rule A has a higher priority than Rule B, but it is desired for Rule B to take effect.
|
|
150
|
+
*
|
|
151
|
+
* 对于一些特殊情况,需要调整部分规则的优先级,可以使用此选项。
|
|
152
|
+
* 比如一个请求同时命中了规则 A 和 B,且 A 比 B 优先级高, 但期望规则 B 生效时。
|
|
153
|
+
*/
|
|
154
|
+
special?: MockMatchSpecialPriority;
|
|
155
|
+
}
|
|
156
|
+
interface MockMatchSpecialPriority {
|
|
157
|
+
/**
|
|
158
|
+
* When both A and B or C match, and B or C is at the top of the sort order,
|
|
159
|
+
* insert A into the top position.The `when` option is used to further constrain
|
|
160
|
+
* the priority adjustment to be effective only for certain requests.
|
|
161
|
+
*
|
|
162
|
+
* 当 A 与 B或 C 同时满足匹配,且 B或 C在排序首位时,将A插入到首位。
|
|
163
|
+
* when 选项用于进一步约束该优先级调整仅针对哪些请求有效。
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```ts
|
|
167
|
+
* {
|
|
168
|
+
* A: ['B', 'C'],
|
|
169
|
+
* A: { rules: ['B', 'C'], when: ['/api/a/b/c'] }
|
|
170
|
+
* }
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
[key: string]: string[] | {
|
|
174
|
+
rules: string[];
|
|
175
|
+
when: string[];
|
|
176
|
+
};
|
|
100
177
|
}
|
|
101
178
|
interface ServerBuildOption {
|
|
102
179
|
/**
|
|
@@ -443,8 +520,10 @@ interface WebSocketSetupContext {
|
|
|
443
520
|
}
|
|
444
521
|
type MockOptions = (MockHttpItem | MockWebsocketItem)[];
|
|
445
522
|
type FormidableFile = formidable.File | formidable.File[];
|
|
523
|
+
type LogType = 'info' | 'warn' | 'error' | 'debug';
|
|
524
|
+
type LogLevel = LogType | 'silent';
|
|
446
525
|
|
|
447
|
-
declare function mockDevServerPlugin({ prefix, wsPrefix, include, exclude, reload, log, cors, formidableOptions, build, cookiesOptions, }?: MockServerPluginOptions): Plugin[];
|
|
526
|
+
declare function mockDevServerPlugin({ prefix, wsPrefix, include, exclude, reload, log, cors, formidableOptions, build, cookiesOptions, priority, }?: MockServerPluginOptions): Plugin[];
|
|
448
527
|
|
|
449
528
|
/**
|
|
450
529
|
* mock config Type helper
|
|
@@ -514,6 +593,7 @@ type MockData<T = any> = readonly [
|
|
|
514
593
|
declare function defineMockData<T = any>(key: string, initialData: T): MockData<T>;
|
|
515
594
|
|
|
516
595
|
interface Logger {
|
|
596
|
+
debug(msg: string, level?: boolean | LogLevel): void;
|
|
517
597
|
info(msg: string, level?: boolean | LogLevel): void;
|
|
518
598
|
warn(msg: string, level?: boolean | LogLevel): void;
|
|
519
599
|
error(msg: string, level?: boolean | LogLevel): void;
|
|
@@ -558,8 +638,9 @@ interface BaseMiddlewareOptions {
|
|
|
558
638
|
cookiesOptions: MockServerPluginOptions['cookiesOptions'];
|
|
559
639
|
proxies: string[];
|
|
560
640
|
logger: Logger;
|
|
641
|
+
priority: MockServerPluginOptions['priority'];
|
|
561
642
|
}
|
|
562
|
-
declare function baseMiddleware(mockLoader: MockLoader, { formidableOptions, proxies, cookiesOptions, logger, }: BaseMiddlewareOptions): Connect.NextHandleFunction;
|
|
643
|
+
declare function baseMiddleware(mockLoader: MockLoader, { formidableOptions, proxies, cookiesOptions, logger, priority, }: BaseMiddlewareOptions): Connect.NextHandleFunction;
|
|
563
644
|
|
|
564
645
|
/**
|
|
565
646
|
* 不复用 `viteConfig.server.proxy` 中 websocket proxy的原因是,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Connect, Plugin, ResolvedConfig } from 'vite';
|
|
2
2
|
import { Buffer } from 'node:buffer';
|
|
3
3
|
import http from 'node:http';
|
|
4
4
|
import { Readable } from 'node:stream';
|
|
@@ -97,6 +97,83 @@ interface MockServerPluginOptions {
|
|
|
97
97
|
* @default false
|
|
98
98
|
*/
|
|
99
99
|
build?: boolean | ServerBuildOption;
|
|
100
|
+
/**
|
|
101
|
+
* Priority sorting for path matching rules is valid only for rules containing dynamic parameters.
|
|
102
|
+
* In most cases, the default sorting rules can meet the needs.
|
|
103
|
+
* However, in some cases where custom sorting rules are required, this option can be used.
|
|
104
|
+
*
|
|
105
|
+
* 路径匹配规则优先级排序,仅对包含动态参数的规则有效。
|
|
106
|
+
* 大部分情况下默认的排序规则都可以满足需求。
|
|
107
|
+
* 但有些情况下,需要自定义排序规则时,可以使用此选项。
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```ts
|
|
111
|
+
* export default {
|
|
112
|
+
* priority: {
|
|
113
|
+
* global: ['/api/:a/b/c', '/api/a/:b/c', '/api/a/b/:c'],
|
|
114
|
+
* special: {
|
|
115
|
+
* '/api/:a/:b/c': {
|
|
116
|
+
* rules: ['/api/a/:b/:c', '/api/a/b/:c'],
|
|
117
|
+
* when: ['/api/a/b/c']
|
|
118
|
+
* }
|
|
119
|
+
* }
|
|
120
|
+
* }
|
|
121
|
+
* }
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
priority?: MockMatchPriority;
|
|
125
|
+
}
|
|
126
|
+
interface MockMatchPriority {
|
|
127
|
+
/**
|
|
128
|
+
* The priority of matching rules is global.
|
|
129
|
+
* The rules declared in this option will take priority over the default rules.
|
|
130
|
+
* The higher the position of the rule in the array, the higher the priority.
|
|
131
|
+
*
|
|
132
|
+
* Do not declare general rules in this option, such as /api/(.*),
|
|
133
|
+
* as it will prevent subsequent rules from taking effect.
|
|
134
|
+
* Unless you are clear about the priority of the rules,
|
|
135
|
+
* most of the time you do not need to configure this option.
|
|
136
|
+
|
|
137
|
+
* 匹配规则优先级, 全局生效。
|
|
138
|
+
* 声明在该选项中的规则将优先于默认规则生效。
|
|
139
|
+
* 规则在数组越靠前的位置,优先级越高。
|
|
140
|
+
*
|
|
141
|
+
* 不要在此选项中声明通用性的规则,比如 `/api/(.*)`,这将导致后续的规则无法生效。
|
|
142
|
+
* 除非你明确知道规则的优先级,否则大多数情况下都不需要配置该选项。
|
|
143
|
+
* @default []
|
|
144
|
+
*/
|
|
145
|
+
global?: string[];
|
|
146
|
+
/**
|
|
147
|
+
* For some special cases where the priority of certain rules needs to be adjusted,
|
|
148
|
+
* this option can be used. For example, when a request matches both Rule A and Rule B,
|
|
149
|
+
* and Rule A has a higher priority than Rule B, but it is desired for Rule B to take effect.
|
|
150
|
+
*
|
|
151
|
+
* 对于一些特殊情况,需要调整部分规则的优先级,可以使用此选项。
|
|
152
|
+
* 比如一个请求同时命中了规则 A 和 B,且 A 比 B 优先级高, 但期望规则 B 生效时。
|
|
153
|
+
*/
|
|
154
|
+
special?: MockMatchSpecialPriority;
|
|
155
|
+
}
|
|
156
|
+
interface MockMatchSpecialPriority {
|
|
157
|
+
/**
|
|
158
|
+
* When both A and B or C match, and B or C is at the top of the sort order,
|
|
159
|
+
* insert A into the top position.The `when` option is used to further constrain
|
|
160
|
+
* the priority adjustment to be effective only for certain requests.
|
|
161
|
+
*
|
|
162
|
+
* 当 A 与 B或 C 同时满足匹配,且 B或 C在排序首位时,将A插入到首位。
|
|
163
|
+
* when 选项用于进一步约束该优先级调整仅针对哪些请求有效。
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```ts
|
|
167
|
+
* {
|
|
168
|
+
* A: ['B', 'C'],
|
|
169
|
+
* A: { rules: ['B', 'C'], when: ['/api/a/b/c'] }
|
|
170
|
+
* }
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
[key: string]: string[] | {
|
|
174
|
+
rules: string[];
|
|
175
|
+
when: string[];
|
|
176
|
+
};
|
|
100
177
|
}
|
|
101
178
|
interface ServerBuildOption {
|
|
102
179
|
/**
|
|
@@ -443,8 +520,10 @@ interface WebSocketSetupContext {
|
|
|
443
520
|
}
|
|
444
521
|
type MockOptions = (MockHttpItem | MockWebsocketItem)[];
|
|
445
522
|
type FormidableFile = formidable.File | formidable.File[];
|
|
523
|
+
type LogType = 'info' | 'warn' | 'error' | 'debug';
|
|
524
|
+
type LogLevel = LogType | 'silent';
|
|
446
525
|
|
|
447
|
-
declare function mockDevServerPlugin({ prefix, wsPrefix, include, exclude, reload, log, cors, formidableOptions, build, cookiesOptions, }?: MockServerPluginOptions): Plugin[];
|
|
526
|
+
declare function mockDevServerPlugin({ prefix, wsPrefix, include, exclude, reload, log, cors, formidableOptions, build, cookiesOptions, priority, }?: MockServerPluginOptions): Plugin[];
|
|
448
527
|
|
|
449
528
|
/**
|
|
450
529
|
* mock config Type helper
|
|
@@ -514,6 +593,7 @@ type MockData<T = any> = readonly [
|
|
|
514
593
|
declare function defineMockData<T = any>(key: string, initialData: T): MockData<T>;
|
|
515
594
|
|
|
516
595
|
interface Logger {
|
|
596
|
+
debug(msg: string, level?: boolean | LogLevel): void;
|
|
517
597
|
info(msg: string, level?: boolean | LogLevel): void;
|
|
518
598
|
warn(msg: string, level?: boolean | LogLevel): void;
|
|
519
599
|
error(msg: string, level?: boolean | LogLevel): void;
|
|
@@ -558,8 +638,9 @@ interface BaseMiddlewareOptions {
|
|
|
558
638
|
cookiesOptions: MockServerPluginOptions['cookiesOptions'];
|
|
559
639
|
proxies: string[];
|
|
560
640
|
logger: Logger;
|
|
641
|
+
priority: MockServerPluginOptions['priority'];
|
|
561
642
|
}
|
|
562
|
-
declare function baseMiddleware(mockLoader: MockLoader, { formidableOptions, proxies, cookiesOptions, logger, }: BaseMiddlewareOptions): Connect.NextHandleFunction;
|
|
643
|
+
declare function baseMiddleware(mockLoader: MockLoader, { formidableOptions, proxies, cookiesOptions, logger, priority, }: BaseMiddlewareOptions): Connect.NextHandleFunction;
|
|
563
644
|
|
|
564
645
|
/**
|
|
565
646
|
* 不复用 `viteConfig.server.proxy` 中 websocket proxy的原因是,
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{toArray as
|
|
1
|
+
import{toArray as co}from"@pengzhanbo/utils";import ft from"node:fs";import Z from"node:fs/promises";import N from"node:path";import{toArray as ee}from"@pengzhanbo/utils";import gt from"fast-glob";import kt from"is-core-module";import{createFilter as ht,normalizePath as yt}from"vite";var ye="vite-plugin-mock-dev-server",ve="1.3.2";import xe,{promises as pe}from"node:fs";import{createRequire as ot}from"node:module";import ae from"node:path";import{pathToFileURL as rt}from"node:url";import{build as nt}from"esbuild";import st from"json5";import ie from"node:fs";import ce from"node:path";import{parse as Ke}from"node:querystring";import{URL as Xe,fileURLToPath as Ye}from"node:url";import Ze from"debug";import{match as et}from"path-to-regexp";var tt=o=>o!==null&&typeof o=="object"&&typeof o.pipe=="function",Me=o=>tt(o)&&o.readable!==!1&&typeof o._read=="function"&&typeof o._readableState=="object";function be(o){return ce.dirname(Ye(o))}var Q=Ze("vite:mock-dev-server");function q(o,t,e){for(let s of t){let n=ce.join(o,s);if(ie.existsSync(n)&&ie.statSync(n).isFile()){let i=e!=null&&e.pathOnly?n:ie.readFileSync(n,"utf-8");if(!(e!=null&&e.predicate)||e.predicate(i))return i}}let r=ce.dirname(o);if(r!==o&&(!(e!=null&&e.rootDir)||r.startsWith(e==null?void 0:e.rootDir)))return q(r,t,e)}var V=(o={})=>{let t=[],e=[];return Object.keys(o).forEach(r=>{var n,i;let s=o[r];typeof s=="string"||!s.ws&&!((n=s.target)!=null&&n.toString().startsWith("ws:"))&&!((i=s.target)!=null&&i.toString().startsWith("wss:"))?t.push(r):e.push(r)}),{httpProxies:t,wsProxies:e}};function I(o,t){return o[0]==="^"&&new RegExp(o).test(t)||t.startsWith(o)}function B(o,t){return(et(o,{decode:decodeURIComponent})(t)||{params:{}}).params||{}}function W(o){let t=new Xe(o,"http://example.com"),e=decodeURIComponent(t.pathname),r=Ke(t.search.replace(/^\?/,""));return{pathname:e,query:r}}var it={name:"externalize-deps",setup(o){o.onResolve({filter:/.*/},({path:t})=>{if(t[0]!=="."&&!ae.isAbsolute(t))return{external:!0}})}},ct={name:"json5-loader",setup(o){o.onLoad({filter:/\.json5$/},async({path:t})=>{let e=await pe.readFile(t,"utf-8");return{contents:`export default ${JSON.stringify(st.parse(e))}`,loader:"js"}})}},at={name:"json-loader",setup(o){o.onLoad({filter:/\.json$/},async({path:t})=>({contents:`export default ${await pe.readFile(t,"utf-8")}`,loader:"js"}))}},pt=o=>({name:"alias-plugin",setup(t){t.onResolve({filter:/.*/},async({path:e})=>{let r=o.find(({find:c})=>lt(c,e));if(!r)return null;let{find:s,replacement:n}=r;return{path:(await t.resolve(e.replace(s,n),{kind:"import-statement",resolveDir:n,namespace:"file"})).path,external:!1}})}});function lt(o,t){return o instanceof RegExp?o.test(t):t.length<o.length?!1:t===o?!0:t.startsWith(`${o}/`)}async function K(o,t){var n;let{isESM:e=!0,define:r,alias:s}=t;try{let i=await nt({entryPoints:[o],outfile:"out.js",write:!1,target:["node14.18","node16"],platform:"node",bundle:!0,metafile:!0,format:e?"esm":"cjs",define:r,plugins:[pt(s),it,at,ct]});return{code:i.outputFiles[0].text,deps:((n=i.metafile)==null?void 0:n.inputs)||{}}}catch(i){console.error(i)}return{code:"",deps:{}}}var ut=be(import.meta.url),T=ot(ut);async function we(o,t,e,r){if(e){let s=`${o}.timestamp-${Date.now()}`,n=`${s}.mjs`,i=`${rt(s)}.mjs`;await pe.writeFile(n,t,"utf8");try{return await import(i)}finally{try{xe.unlinkSync(n)}catch{}}}else{o=ae.resolve(r,o);let s=ae.extname(o),n=xe.realpathSync(o),i=s in T.extensions?s:".js",c=T.extensions[i];T.extensions[i]=(p,m)=>{m===n?p._compile(t,m):c(p,m)},delete T.cache[T.resolve(o)];let a=T(o);return T.extensions[i]=c,a.__esModule?a:{default:a}}}import Oe from"picocolors";import{isBoolean as mt}from"@pengzhanbo/utils";import $ from"picocolors";var Se={silent:0,error:1,warn:2,info:3,debug:4};function X(o,t="info"){o=`[${o}]`;function e(s,n,i){if(i=mt(i)?i?t:"error":i,Se[i]>=Se[s]){let a=s==="info"||s==="debug"?"log":s,p=s==="debug"?$.magenta($.bold(o)):s==="info"?$.cyan($.bold(o)):s==="warn"?$.yellow($.bold(o)):$.red($.bold(o)),m=`${$.dim(new Date().toLocaleTimeString())} ${p} ${n}`;console[a](m)}}return{debug(s,n=t){e("debug",s,n)},info(s,n=t){e("info",s,n)},warn(s,n=t){e("warn",s,n)},error(s,n=t){e("error",s,n)}}}var dt=/import\.meta\.env\.(.+)/;function Y(o){let t=X("vite:mock-dev-server","warn"),e={},r=process.env.NODE_ENV||o.mode;Object.assign(e,{"process.env.NODE_ENV":JSON.stringify(r),"global.process.env.NODE_ENV":JSON.stringify(r),"globalThis.process.env.NODE_ENV":JSON.stringify(r),__vite_process_env_NODE_ENV:JSON.stringify(r)});let s={},n={},i=[];for(let p in o.define){let m=o.define[p];if(typeof m=="string")try{JSON.parse(m),s[p]=m}catch{i.push(p)}else s[p]=JSON.stringify(m);let d=p.match(dt);d&&s[p]&&(n[d[1]]=`__vite__define__${s[p]}`)}i.length&&t.warn(`The following keys: ${Oe.yellow(Oe.underline(i.join(", ")))} declared in 'define' cannot be parsed as regular code snippets.`);let c={},a={};c["import.meta.hot"]="undefined";for(let p in o.env)c[`import.meta.env.${p}`]=JSON.stringify(o.env[p]);return Object.assign(a,{"import.meta.env":JSON.stringify({...o.env,...n}).replace(/"__vite__define__(.+?)"([,}])/g,(p,m,d)=>`${m.replace(/(^\\")|(\\"$)/g,'"')}${d}`)}),{...c,...s,...a,...e}}async function Ce(o,t,e){let r=ee(e.include),s=ee(e.exclude),n=Y(t),{httpProxies:i}=V(t.server.proxy||{});i.push(...ee(e.prefix));let c=ee(e.wsPrefix),a={};try{let l=q(t.root,["package.json"]);l&&(a=JSON.parse(l))}catch{}let p=e.build.dist,m=await xt(process.cwd(),r,s),d=N.join(t.root,`mock-data-${Date.now()}.js`);await Z.writeFile(d,m,"utf-8");let{code:h,deps:y}=await K(d,{define:n,alias:t.resolve.alias}),P=vt(y);await Z.unlink(d);let u=[{filename:N.join(p,"mock-data.js"),source:h},{filename:N.join(p,"index.js"),source:bt(i,c,e.cookiesOptions,e.priority,e.build.serverPort)},{filename:N.join(p,"package.json"),source:Mt(a,P)}];try{if(N.isAbsolute(p)){await Z.rm(p,{recursive:!0}),ft.mkdirSync(p,{recursive:!0});for(let{filename:l,source:f}of u)await Z.writeFile(l,f,"utf-8")}else for(let{filename:l,source:f}of u)o.emitFile({type:"asset",fileName:l,source:f})}catch{}}function vt(o){let t=new Set,e=[ye,"connect","cors"];return Object.keys(o).forEach(r=>{o[r].imports.filter(n=>n.external&&!n.path.startsWith("<define:")).map(n=>n.path).forEach(n=>{!e.includes(n)&&!kt(n)&&t.add(n)})}),Array.from(t)}function Mt(o,t){let{dependencies:e={},devDependencies:r={}}=o,s={...e,...r},n={name:"mock-server",type:"module",scripts:{start:"node index.js"},dependencies:{connect:"^3.7.0","vite-plugin-mock-dev-server":`^${ve}`,cors:"^2.8.5"},pnpm:{peerDependencyRules:{ignoreMissing:["vite"]}}};return t.forEach(i=>{n.dependencies[i]=s[i]||"latest"}),JSON.stringify(n,null,2)}function bt(o,t,e={},r={},s=8080){return`import { createServer } from 'node:http';
|
|
2
2
|
import connect from 'connect';
|
|
3
3
|
import corsMiddleware from 'cors';
|
|
4
4
|
import { baseMiddleware, mockWebSocket } from 'vite-plugin-mock-dev-server';
|
|
@@ -9,6 +9,7 @@ const server = createServer(app);
|
|
|
9
9
|
const httpProxies = ${JSON.stringify(o)};
|
|
10
10
|
const wsProxies = ${JSON.stringify(t)};
|
|
11
11
|
const cookiesOptions = ${JSON.stringify(e)};
|
|
12
|
+
const priority = ${JSON.stringify(r)};
|
|
12
13
|
|
|
13
14
|
mockWebSocket({ mockData }, server, wsProxies, cookiesOptions);
|
|
14
15
|
|
|
@@ -16,13 +17,14 @@ app.use(corsMiddleware());
|
|
|
16
17
|
app.use(baseMiddleware({ mockData }, {
|
|
17
18
|
formidableOptions: { multiples: true },
|
|
18
19
|
proxies: httpProxies,
|
|
20
|
+
priority,
|
|
19
21
|
cookiesOptions,
|
|
20
22
|
}));
|
|
21
23
|
|
|
22
|
-
server.listen(${
|
|
24
|
+
server.listen(${s});
|
|
23
25
|
|
|
24
|
-
console.log('listen: http://localhost:${
|
|
25
|
-
`}async function
|
|
26
|
+
console.log('listen: http://localhost:${s}');
|
|
27
|
+
`}async function xt(o,t,e){let r=await gt(t,{cwd:o}),s=ht(t,e,{resolve:!1}),n=r.filter(s),i="",c="";return n.forEach((a,p)=>{let m=yt(N.join(o,a));i+=`import * as m${p} from '${m}';
|
|
26
28
|
`,c+=`m${p}, `}),`import { transformMockData } from 'vite-plugin-mock-dev-server';
|
|
27
29
|
${i}
|
|
28
30
|
const exporters = [${c}];
|
|
@@ -40,18 +42,19 @@ const mockList = exporters.map((raw) => {
|
|
|
40
42
|
}
|
|
41
43
|
return mockConfig
|
|
42
44
|
});
|
|
43
|
-
export default transformMockData(mockList);`}import{isBoolean as
|
|
44
|
-
${
|
|
45
|
-
|
|
46
|
-
${
|
|
47
|
-
|
|
45
|
+
export default transformMockData(mockList);`}import{isBoolean as ro,toArray as se}from"@pengzhanbo/utils";import no from"cors";import{pathToRegexp as so}from"path-to-regexp";import{Buffer as Ie}from"node:buffer";import{isArray as oe,isEmptyObject as Dt,isFunction as re,random as Et,sleep as Lt,timestamp as He}from"@pengzhanbo/utils";import _t from"cookies";import Tt from"http-status";import*as A from"mime-types";import{pathToRegexp as It}from"path-to-regexp";import k from"picocolors";import{isArray as wt,isEmptyObject as Pe,isString as te,sortBy as je,uniq as Re}from"@pengzhanbo/utils";import{parse as St,pathToRegexp as We}from"path-to-regexp";var le={};function J(o){if(le[o])return le[o];let t=St(o),e=[];for(let r of t)if(!te(r))e.push(r);else{let s=r[0]==="/",n=s?r.slice(1).split("/"):r.split("/");e.push(`${s?"/":""}${n[0]}`,...n.slice(1).map(i=>`/${i}`))}return le[o]=e,e}function Ot(o){let t=o.map(e=>J(e).length);return t=t.length===0?[1]:t,Math.max(...t)+2}function Ct(o){let t=J(o),e=0;for(let r=0;r<t.length;r++){let s=t[r];te(s)||(e+=10**(r+1)),e+=10**(r+1)}return e}function Pt(o){let t=[],e=[];for(let r of o){let n=J(r).filter(i=>typeof i!="string").length;e[n]||(e[n]=[]),e[n].push(r)}for(let r of e.filter(s=>s&&s.length>0))t=[...t,...je(r,Ct)];return t}function Rt(o){let t=Ot(o);return je(o,e=>{let r=J(e),s=r.filter(c=>typeof c!="string");if(s.length===0)return 0;let n=s.length,i=0;for(let c=0;c<r.length;c++){let a=r[c],p=!te(a),{pattern:m="",modifier:d,prefix:h,name:y}=p?a:{},P=m&&m.includes(".*"),u=h==="/",l=te(y);i+=p&&u?1:0,c===r.length-1&&P?n+=5*10**t:P?n+=3*10**(t-1):m&&(u?n+=(l?2:1)*10**(i+1):n-=1*10**i),d==="+"&&(n+=1*10**(t-1)),d==="*"&&(n+=1*10**(t-1)+1),d==="?"&&(n+=1*10**(i+(u?1:0)))}return n})}function $e(o,t,e){let r=Rt(Pt(o.filter(y=>We(y).test(t)))),{global:s=[],special:n={}}=e;if(s.length===0&&Pe(n)||r.length===0)return r;let[i,c]=Wt(r),a=s.filter(y=>c.includes(y));if(a.length>0&&(r=Re([...i,...a,...c])),Pe(n))return r;let p=Object.keys(n).filter(y=>r.includes(y))[0];if(!p)return r;let m=n[p],{rules:d,when:h}=wt(m)?{rules:m,when:[]}:m;return d.includes(r[0])&&(h.length===0||h.some(y=>We(y).test(t)))&&(r=Re([p,...r])),r}function Wt(o){let t=[],e=[];for(let r of o)J(r).filter(i=>typeof i!="string").length>0?e.push(r):t.push(r);return[t,e]}import ue from"co-body";import jt from"formidable";async function De(o,t){var s;let e=o.method.toUpperCase();if(["GET","DELETE","HEAD"].includes(e))return;let r=((s=o.headers["content-type"])==null?void 0:s.toLocaleLowerCase())||"";try{if(r.startsWith("application/json"))return await ue.json(o);if(r.startsWith("application/x-www-form-urlencoded"))return await ue.form(o);if(r.startsWith("text/plain"))return await ue.text(o);if(r.startsWith("multipart/form-data"))return await $t(o,t)}catch(n){console.error(n)}}async function $t(o,t){let e=jt(t);return new Promise((r,s)=>{e.parse(o,(n,i,c)=>{if(n){s(n);return}r({...i,...c})})})}import{isArray as Ee,isObject as Le}from"@pengzhanbo/utils";function _e(o,t){return E(o.headers,t.headers)&&E(o.body,t.body)&&E(o.params,t.params)&&E(o.query,t.query)&&E(o.refererQuery,t.refererQuery)}function E(o,t){if(!t)return!0;for(let e in t)if(!Te(o[e],t[e]))return!1;return!0}function Te(o,t){if(Ee(o)&&Ee(t)){let e=new Set;return t.every(r=>o.some((s,n)=>{if(e.has(n))return!1;let i=Te(s,r);return i&&e.add(n),i}))}return Le(o)&&Le(t)?E(o,t):Object.is(o,t)}function Fe(o,{formidableOptions:t={},proxies:e,cookiesOptions:r,logger:s,priority:n={}}){return async function(i,c,a){let p=He(),{query:m,pathname:d}=W(i.url);if(!d||e.length===0||!e.some(x=>I(x,i.url)))return a();let h=o.mockData,y=$e(Object.keys(h),d,n);if(y.length===0)return a();let{query:P}=W(i.headers.referer||""),u=await De(i,t),l=new _t(i,c,r),f=l.get.bind(l),v=i.method.toUpperCase(),M,C;for(let x of y)if(M=Nt(h[x],s,{pathname:d,method:v,request:{query:m,refererQuery:P,body:u,headers:i.headers,getCookie:f}}),M){C=x;break}if(!M){let x=y.map(U=>U===C?k.underline(k.bold(U)):k.dim(U)).join(", ");return s.warn(`${k.green(d)} matches ${x} , but mock data is not found.`),a()}let g=i,b=c;g.body=u,g.query=m,g.refererQuery=P,g.params=B(M.url,d),g.getCookie=f,b.setCookie=l.set.bind(l);let{body:R,delay:L,type:_="json",response:D,status:j=200,statusText:G,log:F,__filepath__:w}=M;if(me(b,j,G),await Ht(g,b,M,s),await Ft(g,b,M,s),s.info(Bt(g,w),F),s.debug(`${k.magenta("DEBUG")} ${k.underline(d)} matches: [ ${y.map(x=>x===C?k.underline(k.bold(x)):k.dim(x)).join(", ")} ]
|
|
46
|
+
`),R){try{let x=re(R)?await R(g):R;await Ne(p,L),Ut(b,x,_)}catch(x){s.error(`${k.red(`mock error at ${d}`)}
|
|
47
|
+
${x}
|
|
48
|
+
at body (${k.underline(w)})`,F),me(b,500),c.end("")}return}if(D){try{await Ne(p,L),await D(g,b,a)}catch(x){s.error(`${k.red(`mock error at ${d}`)}
|
|
49
|
+
${x}
|
|
50
|
+
at response (${k.underline(w)})`,F),me(b,500),c.end("")}return}c.end("")}}function Nt(o,t,{pathname:e,method:r,request:s}){return o.find(n=>{if(!e||!n||!n.url||n.ws===!0||!(n.method?oe(n.method)?n.method:[n.method]:["GET","POST"]).includes(r))return!1;let c=It(n.url).test(e);if(c&&n.validator){let a=B(n.url,e);if(re(n.validator))return n.validator({params:a,...s});try{return _e({params:a,...s},n.validator)}catch(p){let m=n.__filepath__;return t.error(`${k.red(`mock error at ${e}`)}
|
|
48
51
|
${p}
|
|
49
|
-
at validator (${
|
|
52
|
+
at validator (${k.underline(m)})`,n.log),!1}}return c})}function me(o,t=200,e){o.statusCode=t,o.statusMessage=e||qt(t)}async function Ht(o,t,e,r){let{headers:s,type:n="json"}=e,i=e.__filepath__,c=A.contentType(n)||A.contentType(A.lookup(n)||"");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"),t.setHeader("X-File-Path",i),!!s)try{let a=re(s)?await s(o):s;Object.keys(a).forEach(p=>{t.setHeader(p,a[p])})}catch(a){r.error(`${k.red(`mock error at ${o.url.split("?")[0]}`)}
|
|
50
53
|
${a}
|
|
51
|
-
at headers (${
|
|
54
|
+
at headers (${k.underline(i)})`,e.log)}}async function Ft(o,t,e,r){let{cookies:s}=e,n=e.__filepath__;if(s)try{let i=re(s)?await s(o):s;Object.keys(i).forEach(c=>{let a=i[c];if(oe(a)){let[p,m]=a;t.setCookie(c,p,m)}else t.setCookie(c,a)})}catch(i){r.error(`${k.red(`mock error at ${o.url.split("?")[0]}`)}
|
|
52
55
|
${i}
|
|
53
|
-
at cookies (${
|
|
54
|
-
${
|
|
55
|
-
at setup (${
|
|
56
|
-
${
|
|
57
|
-
at setup (${
|
|
56
|
+
at cookies (${k.underline(n)})`,e.log)}}function Ut(o,t,e){if(Me(t))t.pipe(o);else if(Ie.isBuffer(t))o.end(e==="text"||e==="json"?t.toString("utf-8"):t);else{let r=typeof t=="string"?t:JSON.stringify(t);o.end(e==="buffer"?Ie.from(r):r)}}async function Ne(o,t){if(!t||typeof t=="number"&&t<=0||oe(t)&&t.length!==2)return;let e=0;if(oe(t)){let[r,s]=t;e=Et(r,s)}else e=t-(He()-o);e>0&&await Lt(e)}function qt(o){return Tt[o]||"Unknown"}function Bt(o,t){let{url:e,method:r,query:s,params:n,body:i}=o,{pathname:c}=new URL(e,"http://example.com");c=k.green(decodeURIComponent(c));let a=(P,u)=>!u||Dt(u)?"":` ${k.gray(`${P}:`)}${JSON.stringify(u)}`,p=k.magenta(k.bold(r)),m=a("query",s),d=a("params",n),h=a("body",i),y=` ${k.dim(k.underline(`(${t})`))}`;return`${p} ${c}${m}${d}${h}${y}`}import Qt from"node:events";import{hasOwn as Vt,isArray as Kt,promiseParallel as Xt,toArray as Yt}from"@pengzhanbo/utils";import Je from"chokidar";import Zt from"fast-glob";import{createFilter as eo,normalizePath as z}from"vite";import{isArray as Jt,isEmptyObject as Ue,isFunction as qe,isObject as At,sortBy as zt}from"@pengzhanbo/utils";function Be(o){let t=[];for(let[,r]of o.entries())r&&(Jt(r)?t.push(...r):t.push(r));let e={};return t.filter(r=>At(r)&&r.enabled!==!1&&r.url).forEach(r=>{let{pathname:s,query:n}=W(r.url),i=e[s]??=[],c={...r,url:s};if(c.ws!==!0){let a=c.validator;Ue(n)||(qe(a)?c.validator=function(p){return E(p.query,n)&&a(p)}:a?(c.validator={...a},c.validator.query=c.validator.query?{...n,...c.validator.query}:n):c.validator={query:n})}i.push(c)}),Object.keys(e).forEach(r=>{e[r]=zt(e[r],s=>{if(s.ws===!0)return 0;let{validator:n}=s;return!n||Ue(n)?2:qe(n)?0:1/Object.keys(n).reduce((c,a)=>c+Gt(n[a]),0)})}),e}function Gt(o){return o?Object.keys(o).length:0}var ne=class extends Qt{constructor(e){super();this.options=e;this.cwd=e.cwd||process.cwd();try{let r=q(this.cwd,["package.json"]);this.moduleType=r&&JSON.parse(r).type==="module"?"esm":"cjs"}catch{}}moduleCache=new Map;moduleDeps=new Map;cwd;mockWatcher;depsWatcher;moduleType="cjs";_mockData={};get mockData(){return this._mockData}load(){let{include:e,exclude:r}=this.options,s=eo(e,r,{resolve:!1});Zt(e,{cwd:this.cwd}).then(i=>i.filter(s).map(c=>()=>this.loadMock(c))).then(i=>Xt(i,10)).then(()=>this.updateMockList()),this.watchMockEntry(),this.watchDeps();let n=null;this.on("mock:update",async i=>{s(i)&&(await this.loadMock(i),n&&clearImmediate(n),n=setImmediate(()=>{this.updateMockList(),this.emit("mock:update-end",i),n=null}))}),this.on("mock:unlink",async i=>{s(i)&&(this.moduleCache.delete(i),this.updateMockList(),this.emit("mock:update-end",i))})}watchMockEntry(){let{include:e}=this.options,[r,...s]=e,n=this.mockWatcher=Je.watch(r,{ignoreInitial:!0,cwd:this.cwd});s.length>0&&s.forEach(i=>n.add(i)),n.on("add",async i=>{i=z(i),this.emit("mock:update",i),Q("watcher:add",i)}),n.on("change",async i=>{i=z(i),this.emit("mock:update",i),Q("watcher:change",i)}),n.on("unlink",async i=>{i=z(i),this.emit("mock:unlink",i),Q("watcher:unlink",i)})}watchDeps(){let e=[];this.depsWatcher=Je.watch([],{ignoreInitial:!0,cwd:this.cwd}),this.depsWatcher.on("change",r=>{r=z(r);let s=this.moduleDeps.get(r);s&&s.forEach(n=>{this.emit("mock:update",n)})}),this.depsWatcher.on("unlink",r=>{r=z(r),this.moduleDeps.delete(r)}),this.on("update:deps",()=>{let r=[];for(let[n]of this.moduleDeps.entries())r.push(n);let s=r.filter(n=>!e.includes(n));s.length>0&&this.depsWatcher.add(s)})}close(){var e,r;(e=this.mockWatcher)==null||e.close(),(r=this.depsWatcher)==null||r.close()}updateMockList(){this._mockData=Be(this.moduleCache)}updateModuleDeps(e,r){Object.keys(r).forEach(s=>{r[s].imports.map(i=>i.path).forEach(i=>{this.moduleDeps.has(i)||this.moduleDeps.set(i,new Set),this.moduleDeps.get(i).add(e)})}),this.emit("update:deps")}async loadMock(e){if(!e)return;let r=!1;/\.m[jt]s$/.test(e)?r=!0:/\.c[jt]s$/.test(e)?r=!1:r=this.moduleType==="esm";let{define:s,alias:n}=this.options,{code:i,deps:c}=await K(e,{isESM:r,define:s,alias:n});try{let a=await we(e,i,r,this.cwd)||{},p;Vt(a,"default")?p=a.default:(p=[],Object.keys(a).forEach(m=>p.push(...Yt(a[m])))),Kt(p)?p.forEach(m=>m.__filepath__=e):p.__filepath__=e,this.moduleCache.set(e,p),this.updateModuleDeps(e,c)}catch(a){console.error(a)}}};import to from"cookies";import{pathToRegexp as Ae}from"path-to-regexp";import H from"picocolors";import{WebSocketServer as oo}from"ws";function Ge({loader:o,httpServer:t,proxies:e,cookiesOptions:r,logger:s}){var P;let n=new Map,i=new Map,c=new WeakMap,a=u=>{let l=i.get(u);return!l&&i.set(u,l=new Map),l},p=(u,l)=>{let f=u.get(l);return!f&&u.set(l,f=new oo({noServer:!0})),f},m=(u,l)=>{let f=n.get(u);!f&&n.set(u,f=new Set),f.add(l)},d=(u,l,f,v,M,C)=>{var g;try{(g=f.setup)==null||g.call(f,l,v),l.on("close",()=>u.delete(M)),l.on("error",b=>{s.error(`${H.red(`WebSocket mock error at ${l.path}`)}
|
|
57
|
+
${b}
|
|
58
|
+
at setup (${C})`,f.log)})}catch(b){s.error(`${H.red(`WebSocket mock error at ${l.path}`)}
|
|
59
|
+
${b}
|
|
60
|
+
at setup (${C})`,f.log)}},h=(u,l,f,v)=>{u.emit("connection",l,f),l.on("close",()=>{let M=v.findIndex(C=>C.ws===l);M!==-1&&v.splice(M,1)})},y=(u,l,f,v,M)=>{let{cleanupList:C,connectionList:g,context:b}=c.get(l);ze(C),g.forEach(({ws:R})=>R.removeAllListeners()),l.removeAllListeners(),d(u,l,f,b,v,M),g.forEach(({ws:R,req:L})=>h(l,R,L,g))};(P=o.on)==null||P.call(o,"mock:update-end",u=>{if(!n.has(u))return;let l=n.get(u);if(l)for(let f of l.values())for(let v of o.mockData[f]){if(!v.ws||v.__filepath__!==u)return;let M=a(f);for(let[C,g]of M.entries())y(M,g,v,C,u)}}),t==null||t.on("upgrade",(u,l,f)=>{let{pathname:v,query:M}=W(u.url);if(!v||e.length===0||!e.some(w=>I(w,u.url)))return;let C=o.mockData,g=Object.keys(C).find(w=>Ae(w).test(v));if(!g)return;let b=C[g].find(w=>w.url&&w.ws&&Ae(w.url).test(v));if(!b)return;let R=b.__filepath__;m(R,g);let L=a(g),_=p(L,v),D=c.get(_);if(!D){let w=[],x={onCleanup:U=>w.push(U)};D={cleanupList:w,context:x,connectionList:[]},c.set(_,D),d(L,_,b,x,v,R)}let j=u,G=new to(u,u,r),{query:F}=W(u.headers.referer||"");j.query=M,j.refererQuery=F,j.params=B(g,v),j.getCookie=G.get.bind(G),_.handleUpgrade(j,l,f,w=>{s.info(`${H.magenta(H.bold("WebSocket"))} ${H.green(u.url)} connected ${H.dim(`(${R})`)}`,b.log),D.connectionList.push({req:j,ws:w}),h(_,w,j,D.connectionList)})}),t==null||t.on("close",()=>{for(let u of i.values()){for(let l of u.values()){let f=c.get(l);ze(f.cleanupList),l.close()}u.clear()}i.clear(),n.clear()})}function ze(o){let t;for(;t=o.shift();)t==null||t()}function de(o,t,e,r){let s=X("vite:mock",ro(t.log)?t.log?"info":"error":t.log),n=new ne({include:se(t.include),exclude:se(t.exclude),define:Y(o),alias:o.resolve.alias});n.load(),n.on("mock:update-end",()=>{t.reload&&(r==null||r.send({type:"full-reload"}))}),e==null||e.on("close",()=>n.close());let{httpProxies:i}=V(o.server.proxy||{}),a=[...se(t.prefix),...i];Ge({loader:n,httpServer:e,proxies:se(t.wsPrefix),cookiesOptions:t.cookiesOptions,logger:s});let p=[];return p.push(io(n,a,o,t),Fe(n,{formidableOptions:t.formidableOptions,proxies:a,cookiesOptions:t.cookiesOptions,priority:t.priority,logger:s})),p.filter(Boolean)}function io(o,t,e,r){let s={},n=r.cors===!1?!1:e.server.cors!==!1;return n&&e.server.cors!==!1&&(s={...s,...typeof e.server.cors=="boolean"?{}:e.server.cors}),n&&r.cors!==!1&&(s={...s,...typeof r.cors=="boolean"?{}:r.cors}),n?function(i,c,a){let{pathname:p}=W(i.url);if(!p||t.length===0||!t.some(h=>I(h,i.url)))return a();let m=o.mockData;if(!Object.keys(m).find(h=>so(h).test(p)))return a();no(s)(i,c,a)}:void 0}function Qe({prefix:o=[],wsPrefix:t=[],include:e=["mock/**/*.mock.{js,ts,cjs,mjs,json,json5}"],exclude:r=["**/node_modules/**","**/.vscode/**","**/.git/**"],reload:s=!1,log:n="info",cors:i=!0,formidableOptions:c={},build:a=!1,cookiesOptions:p={},priority:m={}}={}){let d={prefix:o,wsPrefix:t,include:e,exclude:r,reload:s,cors:i,cookiesOptions:p,log:n,formidableOptions:{multiples:!0,...c},priority:m,build:a?Object.assign({serverPort:8080,dist:"mockServer"},typeof a=="object"?a:{}):!1},h=[po(d)];return d.build&&h.push(ao(d)),h}function ao(o){let t={};return{name:"vite-plugin-mock-dev-server-generator",enforce:"post",apply:"build",configResolved(e){t=e,e.logger.warn("")},async buildEnd(e){e||t.command==="build"&&await Ce(this,t,o)}}}function po(o){let t={};return{name:"vite-plugin-mock-dev-server",enforce:"pre",apply:"serve",config(e){var n;let r=co(o.wsPrefix);if(r.length===0||!((n=e.server)!=null&&n.proxy)||Object.keys(e.server.proxy).length===0)return;let s={};Object.keys(e.server.proxy).forEach(i=>{r.includes(i)||(s[i]=e.server.proxy[i])}),e.server.proxy=s},configResolved(e){t=e,e.logger.warn("")},configureServer({middlewares:e,config:r,httpServer:s,ws:n}){de(r,o,s,n).forEach(c=>e.use(c))},configurePreviewServer({middlewares:e,httpServer:r}){de(t,o,r).forEach(n=>e.use(n))}}}import{isArray as lo}from"@pengzhanbo/utils";function pn(o){return o}function ln(o){return e=>(lo(e)?e=e.map(r=>o(r)||r):e=o(e)||e,e)}import{deepClone as Ve,deepEqual as uo,isFunction as mo}from"@pengzhanbo/utils";var fe=new Map,ge=new WeakMap,fo=70,ke=class{value;#e;#t;constructor(t){this.value=t,this.#e=Ve(t),this.#t=Date.now()}hotUpdate(t){Date.now()-this.#t<fo||uo(t,this.#e)||(this.value=t,this.#e=Ve(t),this.#t=Date.now())}};function fn(o,t){fe.has(o)||fe.set(o,new ke(t));let e=fe.get(o);if(e.hotUpdate(t),ge.has(e))return ge.get(e);let r=[()=>e.value,s=>{mo(s)&&(s=s(e.value)??e.value),e.value=s}];return Object.defineProperty(r,"value",{get(){return e.value},set(s){e.value=s}}),ge.set(e,r),r}var yn=Qe;export{Fe as baseMiddleware,ln as createDefineMock,yn as default,pn as defineMock,fn as defineMockData,Qe as mockDevServerPlugin,Ge as mockWebSocket,Be as transformMockData};
|