UNPKG

vite-plugin-mock-dev-server

Version:
1 lines 15.8 kB
import{hasOwn as e,isArray as t,isBoolean as n,isEmptyObject as r,isFunction as i,isPlainObject as a,random as o,sleep as s,sortBy as c,timestamp as l,toArray as u,uniq as d}from"@pengzhanbo/utils";import f from"node:path";import p from"ansis";import m from"picomatch";import{match as h,parse as g,pathToRegexp as _}from"path-to-regexp";import v from"node:os";import y from"debug";import{parse as b}from"node:querystring";import x from"co-body";import S from"formidable";import C from"node:http";import w from"node:crypto";import{Buffer as T}from"node:buffer";import E from"http-status";import*as D from"mime-types";import{WebSocketServer as O}from"ws";function k(e,t){let n=[],r=[`**/node_modules/**`,...u(t)];return u(e).forEach(e=>{e[0]===`!`?r.push(e.slice(1)):n.push(e)}),{pattern:n,ignore:r,isMatch:m(n,{ignore:r})}}function A(e,t){return e[0]===`^`&&new RegExp(e).test(t)||t.startsWith(e)}function j(e){return typeof e==`object`&&!!e&&typeof e.pipe==`function`}function M(e){return j(e)&&e.readable!==!1&&typeof e._read==`function`&&typeof e._readableState==`object`}const N={};async function P(t){if(e(N,t))return N[t];try{return import.meta.resolve?N[t]=!!import.meta.resolve(t):(await import(t),N[t]=!0),N[t]}catch{}return N[t]=!1,!1}function F(e,t){if(!t)return!0;for(let n in t)if(!ee(e[n],t[n]))return!1;return!0}function ee(e,n){if(t(e)&&t(n)){let t=new Set;return n.every(n=>e.some((e,r)=>{if(t.has(r))return!1;let i=ee(e,n);return i&&t.add(r),i}))}return a(e)&&a(n)?F(e,n):Object.is(e,n)}const I=new Map;function L(e,t){let n=I.get(e);return n||(n=_(e).regexp,I.set(e,n)),n.test(t)}const R={silent:0,error:1,warn:2,info:3,debug:4};function te(e,t=`info`){e=`[${e}]`;function r(r,i,a){if(a=n(a)?a?t:`error`:a,R[a]>=R[r]){let t=r===`info`||r===`debug`?`log`:r,n=r===`debug`?p.magenta.bold(e):r===`info`?p.cyan.bold(e):r===`warn`?p.yellow.bold(e):p.red.bold(e),a=`${p.dim(new Date().toLocaleTimeString())} ${n} ${i}`;console[t](a)}}return{debug(e,n=t){r(`debug`,e,n)},info(e,n=t){r(`info`,e,n)},warn(e,n=t){r(`warn`,e,n)},error(e,n=t){r(`error`,e,n)}}}const ne=y(`vite:mock-dev-server`),re=/\\/g,ie=v.platform()===`win32`;function ae(e){return e.replace(re,`/`)}function oe(e){return f.posix.normalize(ie?ae(e):e)}function z(e){let t=new URL(e,`http://example.com`);return{pathname:decodeURIComponent(t.pathname),query:b(t.search.replace(/^\?/,``))}}function se(e,n){let r;return t(e)?r=e.map(e=>({...e,__filepath__:n})):`url`in e?r={...e,__filepath__:n}:(r=[],Object.keys(e).forEach(i=>{let a=e[i];t(a)?r.push(...a.map(e=>({...e,__filepath__:n}))):r.push({...a,__filepath__:n})})),r}function ce(e){let t=[];for(let[,n]of e.entries())n&&t.push(...u(n));let n={};return t.filter(e=>a(e)&&e.enabled!==!1&&e.url).forEach(e=>{let{pathname:t,query:a}=z(e.url),o=n[t]??=[],s={...e,url:t};if(s.ws!==!0){let e=s.validator;r(a)||(i(e)?s.validator=function(t){return F(t.query,a)&&e(t)}:e?(s.validator={...e},s.validator.query=s.validator.query?{...a,...s.validator.query}:a):s.validator={query:a})}o.push(s)}),Object.keys(n).forEach(e=>{n[e]=B(n[e])}),n}function B(e){return c(e,e=>{if(e.ws===!0)return 0;let{validator:t}=e;return!t||r(t)?2:i(t)?0:1/Object.keys(t).reduce((e,n)=>e+le(t[n]),0)})}function le(e){return e?Object.keys(e).length:0}async function ue(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 x.json(e,{limit:s||a,...l});if(i.startsWith(`application/x-www-form-urlencoded`))return await x.form(e,{limit:o||a,...l});if(i.startsWith(`text/plain`))return await x.text(e,{limit:c||a,...l});if(i.startsWith(`multipart/form-data`))return await fe(e,t)}catch(e){console.error(e)}}const de={keepExtensions:!0,filename(e,t,n){return n?.originalFilename||`${e}.${Date.now()}${t?`.${t}`:``}`}};async function fe(e,t){let n=S({...de,...t});return new Promise((t,r)=>{n.parse(e,(e,n,i)=>{if(e){r(e);return}t({...n,...i})})})}const V=new Map;function H(e,t){let n=V.get(e);n||(n=h(e,{decode:decodeURIComponent}),V.set(e,n));let r=n(t);return r?r.params:{}}function pe(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 U(e,t){return!t||r(t)?``:` ${p.gray(`${e}:`)}${JSON.stringify(t)}`}function me(e,t){let{url:n,method:r,query:i,params:a,body:o}=e,{pathname:s}=new URL(n,`http://example.com`);s=p.green(decodeURIComponent(s));let c=p.magenta.bold(r),l=U(`query`,i),u=U(`params`,a),d=U(`body`,o),f=` ${p.dim.underline(`(${t})`)}`;return`${c} ${s}${l}${u}${d}${f}`}function he(e,n,{pathname:r,method:a,request:o}){return e.find(e=>{if(!r||!e||!e.url||e.ws||!(e.method?t(e.method)?e.method:[e.method]:[`GET`,`POST`]).includes(a))return!1;let s=L(e.url,r);if(s&&e.validator){let t=H(e.url,r);if(i(e.validator))return e.validator({params:t,...o});try{return pe({params:t,...o},e.validator)}catch(t){let i=e.__filepath__;return n.error(`${p.red(`mock error at ${r}`)}\n${t}\n at validator (${p.underline(i)})`,e.log),!1}}return s})}const W=/^[\t\u0020-\u007E\u0080-\u00FF]+$/,ge=/^(?:low|medium|high)$/i,G=Object.create(null),_e=/[\^$\\.*+?()[\]{}|]/g,ve=/[;=]/,ye=/;/,be=/^(?:lax|none|strict)$/i;var xe=class{name;value;maxAge;expires;path=`/`;domain;secure=!1;httpOnly=!0;sameSite=!1;overwrite=!1;priority;partitioned;constructor(e,t,n={}){if(!W.test(e)||ve.test(e))throw TypeError(`argument name is invalid`);if(t&&(!W.test(t)||ye.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&&!W.test(this.path))throw TypeError(`[Cookie] option path is invalid`);if(this.domain&&!W.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&&!ge.test(this.priority))throw TypeError(`[Cookie] option priority is invalid`);if(this.sameSite&&this.sameSite!==!0&&!be.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 Se(e,t){if(e.length!==t.length)return!1;if(w.timingSafeEqual)return w.timingSafeEqual(e,t);for(let n=0;n<e.length;n++)if(e[n]!==t[n])return!1;return!0}function K(e,t){return w.createHmac(`sha256`,e).update(t).digest()}function Ce(e,t){let n=String(e),r=String(t),i=w.randomBytes(32);return Se(K(i,n),K(i,r))&&e===t}const we=/[/+=]/g,Te={"/":`_`,"+":`-`,"=":``};var q=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 w.createHmac(this.algorithm,t).update(e).digest(this.encoding).replace(we,e=>Te[e])}index(e,t){for(let n=0,r=this.keys.length;n<r;n++)if(Ce(t,this.sign(e,this.keys[n])))return n;return-1}verify(e,t){return this.index(e,t)>-1}},J=class{request;response;secure;keys;constructor(e,n,r={}){this.request=e,this.response=n,this.secure=r.secure,r.keys instanceof q?this.keys=r.keys:t(r.keys)&&(this.keys=new q(r.keys))}set(e,t,n){let r=this.request,i=this.response,a=u(i.getHeader(`Set-Cookie`)),o=new xe(e,t,n),s=n?.signed??!!this.keys,c=this.secure===void 0?r.protocol===`https`||De(r):!!this.secure;if(!c&&n?.secure)throw Error(`Cannot send secure cookie over unencrypted connection`);if(o.secure=n?.secure??c,Y(a,o),s&&n){if(!this.keys)throw Error(`.keys required for signed cookies`);o.value=this.keys.sign(o.toString()),o.name+=`.sig`,Y(a,o)}return(i.set?C.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(Ee(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 Ee(e){return G[e]||(G[e]=RegExp(`(?:^|;) *${e.replace(_e,`\\$&`)}=([^;]*)`)),G[e]}function De(e){return!!(e.socket?e.socket.encrypted:e.connection.encrypted)}function Y(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 Oe(e){let t=e.map(e=>Z(e).length);return t=t.length===0?[1]:t,Math.max(...t)+2}function ke(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 Ae(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,...c(e,ke).reverse()];return t}function je(e){let t=Oe(e);return c(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 Me(e,n,i){let a=je(Ae(e.filter(e=>L(e,n)))),{global:o=[],special:s={}}=i;if(o.length===0&&r(s)||a.length===0)return a;let[c,l]=Ne(a),u=o.filter(e=>l.includes(e));if(u.length>0&&(a=d([...c,...u,...l])),r(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}=t(p)?{rules:p,when:[]}:p;return m.includes(a[0])&&(h.length===0||h.some(e=>_(e).regexp.test(n)))&&(a=d([f,...a])),a}function Ne(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 Pe(e){let t=[];e.addListener(`data`,e=>{t.push(T.from(e))}),e.addListener(`end`,()=>{t.length&&Q.set(e,T.concat(t))})}function Fe(e){if(!e.server)return;let t=e.server.proxy||{};Object.keys(t).forEach(e=>{let n=t[e],r=typeof n==`string`?{target:n}:n;if(r.ws)return;let{configure:i,...a}=r;t[e]={...a,configure(e,t){i?.(e,t),e.on(`proxyReq`,(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 Ie(e){return E[e]||`Unknown`}function $(e,t=200,n){e.statusCode=t,e.statusMessage=n||Ie(t)}async function Le(e,t,n,r){let{headers:a,type:o=`json`}=n,s=n.__filepath__,c=D.contentType(o)||D.contentType(D.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=i(a)?await a(e):a;Object.keys(n).forEach(e=>{t.setHeader(e,n[e])})}catch(t){r.error(`${p.red(`mock error at ${e.url.split(`?`)[0]}`)}\n${t}\n at headers (${p.underline(s)})`,n.log)}}async function Re(e,n,r,a){let{cookies:o}=r,s=r.__filepath__;if(o)try{let r=i(o)?await o(e):o;Object.keys(r).forEach(e=>{let i=r[e];if(t(i)){let[t,r]=i;n.setCookie(e,t,r)}else n.setCookie(e,i)})}catch(t){a.error(`${p.red(`mock error at ${e.url.split(`?`)[0]}`)}\n${t}\n at cookies (${p.underline(s)})`,r.log)}}function ze(e,t,n){if(M(t))t.pipe(e);else if(T.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`?T.from(r):r)}}async function Be(e,n){if(!n||typeof n==`number`&&n<=0||t(n)&&n.length!==2)return;let r=0;if(t(n)){let[e,t]=n;r=o(e,t)}else r=n-(l()-e);r>0&&await s(r)}function Ve(e,{formidableOptions:t={},bodyParserOptions:n={},proxies:r,cookiesOptions:a,logger:o,priority:s={}}){return async function(c,u,d){let f=l(),{query:m,pathname:h}=z(c.url);if(!h||r.length===0||!r.some(e=>A(e,c.url)))return d();let g=e.mockData,_=Me(Object.keys(g),h,s);if(_.length===0)return d();Pe(c);let{query:v}=z(c.headers.referer||``),y=await ue(c,t,n),b=new J(c,u,a),x=b.get.bind(b),S=c.method.toUpperCase(),C,w;for(let e of _)if(C=he(g[e],o,{pathname:h,method:S,request:{query:m,refererQuery:v,body:y,headers:c.headers,getCookie:x}}),C){w=e;break}if(!C){let e=_.map(e=>e===w?p.underline.bold(e):p.dim(e)).join(`, `);return o.warn(`${p.green(h)} matches ${e} , but mock data is not found.`),d()}let T=c,E=u;T.body=y,T.query=m,T.refererQuery=v,T.params=H(C.url,h),T.getCookie=x,E.setCookie=b.set.bind(b);let{body:D,delay:O,type:k=`json`,response:j,status:M=200,statusText:N,log:P,__filepath__:F}=C;if($(E,M,N),await Le(T,E,C,o),await Re(T,E,C,o),o.info(me(T,F),P),o.debug(`${p.magenta(`DEBUG`)} ${p.underline(h)} matches: [ ${_.map(e=>e===w?p.underline.bold(e):p.dim(e)).join(`, `)} ]\n`),D){try{let e=i(D)?await D(T):D;await Be(f,O),ze(E,e,k)}catch(e){o.error(`${p.red(`mock error at ${h}`)}\n${e}\n at body (${p.underline(F)})`,P),$(E,500),u.end(``)}return}if(j){try{await Be(f,O),await j(T,E,d)}catch(e){o.error(`${p.red(`mock error at ${h}`)}\n${e}\n at response (${p.underline(F)})`,P),$(E,500),u.end(``)}return}u.end(``)}}function He(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=e.get(t);return n||e.set(t,n=new O({noServer:!0})),n},u=(e,t)=>{let n=a.get(e);n||a.set(e,n=new Set),n.add(t)},d=(e,t,n,r,a,o)=>{try{n.setup?.(t,r),t.on(`close`,()=>e.delete(a)),t.on(`error`,e=>{i.error(`${p.red(`WebSocket mock error at ${t.path}`)}\n${e}\n at setup (${o})`,n.log)})}catch(e){i.error(`${p.red(`WebSocket mock error at ${t.path}`)}\n${e}\n at setup (${o})`,n.log)}},f=(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)})},m=(e,t,n,r,i)=>{let{cleanupList:a,connectionList:o,context:c}=s.get(t);Ue(a),o.forEach(({ws:e})=>e.removeAllListeners()),t.removeAllListeners(),d(e,t,n,c,r,i),o.forEach(({ws:e,req:n})=>f(t,e,n,o))};e.on?.(`mock:update-end`,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())m(e,i,n,r,t)}}),t?.on(`upgrade`,(t,a,o)=>{let{pathname:m,query:h}=z(t.url);if(!m||n.length===0||!n.some(e=>A(e,t.url)))return;let g=e.mockData,_=Object.keys(g).find(e=>L(e,m));if(!_)return;let v=g[_].find(e=>e.url&&e.ws&&L(e.url,m));if(!v)return;let y=v.__filepath__;u(y,_);let b=c(_),x=l(b,m),S=s.get(x);if(!S){let e=[],t={onCleanup:t=>e.push(t)};S={cleanupList:e,context:t,connectionList:[]},s.set(x,S),d(b,x,v,t,m,y)}let C=t,w=new J(t,t,r),{query:T}=z(t.headers.referer||``);C.query=h,C.refererQuery=T,C.params=H(_,m),C.getCookie=w.get.bind(w),x.handleUpgrade(C,a,o,e=>{i.info(`${p.magenta.bold(`WebSocket`)} ${p.green(t.url)} connected ${p.dim(`(${y})`)}`,v.log),S.connectionList.push({req:C,ws:e}),f(x,e,C,S.connectionList)})}),t?.on(`close`,()=>{for(let e of o.values()){for(let t of e.values())Ue(s.get(t).cleanupList),t.close();e.clear()}o.clear(),a.clear()})}function Ue(e){let t;for(;t=e.shift();)t?.()}export{se as a,ne as c,R as d,L as f,k as h,ce as i,oe as l,A as m,Ve as n,B as o,P as p,Fe as r,z as s,He as t,te as u};