vite-plugin-mock-dev-server
Advanced tools
Comparing version 1.1.6 to 1.1.7
@@ -359,3 +359,2 @@ import { Connect, Plugin, ResolvedConfig } from 'vite'; | ||
} | ||
type MockWebsocketServerDestroy = (() => void) | void; | ||
interface MockWebsocketItem extends MockBaseItem { | ||
@@ -371,6 +370,10 @@ ws: true; | ||
* ws: true | ||
* setup: (wss) => { | ||
* setup: (wss, { onCleanup }) => { | ||
* wss.on('connection', (ws,req) => { | ||
* ws.on('message', (raw) => console.log(raw)) | ||
* ws.send(JSON.stringify({ type: 'connected' })) | ||
* const timer = setInterval( | ||
* () => ws.send(JSON.stringify({ type: 'connected' })), | ||
* 1000, | ||
* ) | ||
* onCleanup(() => clearInterval(timer)) | ||
* }) | ||
@@ -382,4 +385,11 @@ * wss.on('error', (error) => console.error(error)) | ||
*/ | ||
setup: (wss: WebSocketServer) => MockWebsocketServerDestroy; | ||
setup: (wss: WebSocketServer, context: WebSocketSetupContext) => void; | ||
} | ||
interface WebSocketSetupContext { | ||
/** | ||
* 当你在定义 WSS 时,可能会执行一些自动任务或循环任务, | ||
* 但是当热更新时,插件内部会重新执行 setup() ,这可能导致出现 | ||
*/ | ||
onCleanup: (cleanup: () => void) => void; | ||
} | ||
type MockOptions = (MockHttpItem | MockWebsocketItem)[]; | ||
@@ -386,0 +396,0 @@ type FormidableFile = formidable.File | formidable.File[]; |
@@ -1,4 +0,4 @@ | ||
import Fe from"fs";import G from"fs/promises";import I from"path";import{build as Le}from"esbuild";import $e from"fast-glob";import He from"is-core-module";import{createFilter as _e,normalizePath as Ue}from"vite";var re="vite-plugin-mock-dev-server",se="1.1.6";import ne from"fs/promises";import Se from"path";import Re from"json5";var N={name:"externalize-deps",setup(t){t.onResolve({filter:/.*/},({path:o})=>{if(o[0]!=="."&&!Se.isAbsolute(o))return{external:!0}})}},q={name:"json5-loader",setup(t){t.onLoad({filter:/\.json5$/},async({path:o})=>{let e=await ne.readFile(o,"utf-8");return{contents:`export default ${JSON.stringify(Re.parse(e))}`,loader:"js"}})}},A={name:"json-loader",setup(t){t.onLoad({filter:/\.json$/},async({path:o})=>({contents:`export default ${await ne.readFile(o,"utf-8")}`,loader:"js"}))}},B=t=>({name:"alias-plugin",setup(o){o.onResolve({filter:/.*/},async({path:e})=>{let r=t.find(({find:c})=>De(c,e));if(!r)return null;let{find:n,replacement:s}=r;return{path:(await o.resolve(e.replace(n,s),{kind:"import-statement",resolveDir:s,namespace:"file"})).path,external:!1}})}});function De(t,o){return t instanceof RegExp?t.test(o):o.length<t.length?!1:o===t?!0:o.startsWith(`${t}/`)}import K from"fs";import V from"path";import{fileURLToPath as Ce}from"url";import Ee from"debug";import{match as We}from"path-to-regexp";import ie from"picocolors";var P=t=>Array.isArray(t),R=t=>typeof t=="function",Ie=t=>Object.prototype.toString.call(t)==="[object Object]",ce=t=>Ie(t)&&Object.keys(t).length===0,Te=t=>t!==null&&typeof t=="object"&&typeof t.pipe=="function",ae=t=>Te(t)&&t.readable!==!1&&typeof t._read=="function"&&typeof t._readableState=="object";function pe(t){return new Promise(o=>setTimeout(o,t))}function le(t){return V.dirname(Ce(t))}var D=Ee("vite:plugin-mock-dev-server"),j=t=>P(t)?t:t==null?[]:[t],W={info(...t){console.info(ie.cyan("mock-dev-server: "),...t)},error(...t){console.error(` | ||
import Fe from"fs";import Q from"fs/promises";import L from"path";import{build as $e}from"esbuild";import He from"fast-glob";import _e from"is-core-module";import{createFilter as Ue,normalizePath as Ne}from"vite";var re="vite-plugin-mock-dev-server",ne="1.1.7";import se from"fs/promises";import Re from"path";import Ce from"json5";var q={name:"externalize-deps",setup(t){t.onResolve({filter:/.*/},({path:o})=>{if(o[0]!=="."&&!Re.isAbsolute(o))return{external:!0}})}},A={name:"json5-loader",setup(t){t.onLoad({filter:/\.json5$/},async({path:o})=>{let e=await se.readFile(o,"utf-8");return{contents:`export default ${JSON.stringify(Ce.parse(e))}`,loader:"js"}})}},B={name:"json-loader",setup(t){t.onLoad({filter:/\.json$/},async({path:o})=>({contents:`export default ${await se.readFile(o,"utf-8")}`,loader:"js"}))}},J=t=>({name:"alias-plugin",setup(o){o.onResolve({filter:/.*/},async({path:e})=>{let r=t.find(({find:c})=>De(c,e));if(!r)return null;let{find:s,replacement:n}=r;return{path:(await o.resolve(e.replace(s,n),{kind:"import-statement",resolveDir:n,namespace:"file"})).path,external:!1}})}});function De(t,o){return t instanceof RegExp?t.test(o):o.length<t.length?!1:o===t?!0:o.startsWith(`${t}/`)}import K from"fs";import V from"path";import{fileURLToPath as We}from"url";import Ee from"debug";import{match as Ie}from"path-to-regexp";import ie from"picocolors";var S=t=>Array.isArray(t),C=t=>typeof t=="function",Le=t=>Object.prototype.toString.call(t)==="[object Object]",ce=t=>Le(t)&&Object.keys(t).length===0,Te=t=>t!==null&&typeof t=="object"&&typeof t.pipe=="function",ae=t=>Te(t)&&t.readable!==!1&&typeof t._read=="function"&&typeof t._readableState=="object";function pe(t){return new Promise(o=>setTimeout(o,t))}function ue(t){return V.dirname(We(t))}var D=Ee("vite:plugin-mock-dev-server"),P=t=>S(t)?t:t==null?[]:[t],I={info(...t){console.info(ie.cyan("mock-dev-server: "),...t)},error(...t){console.error(` | ||
`,ie.cyan("mock-dev-server: "),...t,` | ||
`)}};function F(t,o,e){for(let n of o){let s=V.join(t,n);if(K.existsSync(s)&&K.statSync(s).isFile()){let i=e!=null&&e.pathOnly?s:K.readFileSync(s,"utf-8");if(!(e!=null&&e.predicate)||e.predicate(i))return i}}let r=V.dirname(t);if(r!==t&&(!(e!=null&&e.rootDir)||r.startsWith(e==null?void 0:e.rootDir)))return F(r,o,e)}var J=(t={})=>{let o=[],e=[];return Object.keys(t).forEach(r=>{var s,i;let n=t[r];typeof n=="string"||!n.ws&&!((s=n.target)!=null&&s.toString().startsWith("ws:"))&&!((i=n.target)!=null&&i.toString().startsWith("wss:"))?o.push(r):e.push(r)}),{httpProxies:o,wsProxies:e}};function z(t,o){return t[0]==="^"&&new RegExp(t).test(o)||o.startsWith(t)}function L(t,o){return(We(t,{decode:decodeURIComponent})(o)||{params:{}}).params||{}}async function ue(t,o,e){let r=j(e.include),n=j(e.exclude),s={};if(o.define)for(let m in o.define){let d=o.define[m];s[m]=typeof d=="string"?d:JSON.stringify(d)}let{httpProxies:i}=J(o.server.proxy||{});i.push(...j(e.prefix));let c=j(e.wsPrefix),a={};try{let m=F(o.root,["package.json"]);m&&(a=JSON.parse(m))}catch{}let p=e.build.dist,u=await Be(process.cwd(),r,n),l=I.join(o.root,`mock-data-${Date.now()}.js`);await G.writeFile(l,u,"utf-8");let{code:v,deps:M}=await Je(l,s,o.resolve.alias),y=Ne(M);await G.unlink(l);let k=[{filename:I.join(p,"mock-data.js"),source:v},{filename:I.join(p,"index.js"),source:Ae(i,c,e.cookiesOptions,e.build.serverPort)},{filename:I.join(p,"package.json"),source:qe(a,y)}];try{if(I.isAbsolute(p)){await G.rm(p,{recursive:!0}),Fe.mkdirSync(p,{recursive:!0});for(let{filename:m,source:d}of k)await G.writeFile(m,d,"utf-8")}else for(let{filename:m,source:d}of k)t.emitFile({type:"asset",fileName:m,source:d})}catch{}}function Ne(t){let o=new Set,e=[re,"connect","cors"];return Object.keys(t).forEach(r=>{t[r].imports.filter(s=>s.external).map(s=>s.path).forEach(s=>{!e.includes(s)&&!He(s)&&o.add(s)})}),Array.from(o)}function qe(t,o){let{dependencies:e={},devDependencies:r={}}=t,n={...e,...r},s={name:"mock-server",type:"module",scripts:{start:"node index.js"},dependencies:{connect:"^3.7.0","vite-plugin-mock-dev-server":`^${se}`,cors:"^2.8.5"},pnpm:{peerDependencyRules:{ignoreMissing:["vite"]}}};return o.forEach(i=>{s.dependencies[i]=n[i]||"latest"}),JSON.stringify(s,null,2)}function Ae(t,o,e={},r=8080){return`import { createServer } from 'node:http'; | ||
`)}};function F(t,o,e){for(let s of o){let n=V.join(t,s);if(K.existsSync(n)&&K.statSync(n).isFile()){let i=e!=null&&e.pathOnly?n:K.readFileSync(n,"utf-8");if(!(e!=null&&e.predicate)||e.predicate(i))return i}}let r=V.dirname(t);if(r!==t&&(!(e!=null&&e.rootDir)||r.startsWith(e==null?void 0:e.rootDir)))return F(r,o,e)}var z=(t={})=>{let o=[],e=[];return Object.keys(t).forEach(r=>{var n,i;let s=t[r];typeof s=="string"||!s.ws&&!((n=s.target)!=null&&n.toString().startsWith("ws:"))&&!((i=s.target)!=null&&i.toString().startsWith("wss:"))?o.push(r):e.push(r)}),{httpProxies:o,wsProxies:e}};function G(t,o){return t[0]==="^"&&new RegExp(t).test(o)||o.startsWith(t)}function $(t,o){return(Ie(t,{decode:decodeURIComponent})(o)||{params:{}}).params||{}}async function le(t,o,e){let r=P(e.include),s=P(e.exclude),n={};if(o.define)for(let f in o.define){let l=o.define[f];n[f]=typeof l=="string"?l:JSON.stringify(l)}let{httpProxies:i}=z(o.server.proxy||{});i.push(...P(e.prefix));let c=P(e.wsPrefix),a={};try{let f=F(o.root,["package.json"]);f&&(a=JSON.parse(f))}catch{}let p=e.build.dist,m=await Je(process.cwd(),r,s),u=L.join(o.root,`mock-data-${Date.now()}.js`);await Q.writeFile(u,m,"utf-8");let{code:b,deps:h}=await ze(u,n,o.resolve.alias),k=qe(h);await Q.unlink(u);let g=[{filename:L.join(p,"mock-data.js"),source:b},{filename:L.join(p,"index.js"),source:Be(i,c,e.cookiesOptions,e.build.serverPort)},{filename:L.join(p,"package.json"),source:Ae(a,k)}];try{if(L.isAbsolute(p)){await Q.rm(p,{recursive:!0}),Fe.mkdirSync(p,{recursive:!0});for(let{filename:f,source:l}of g)await Q.writeFile(f,l,"utf-8")}else for(let{filename:f,source:l}of g)t.emitFile({type:"asset",fileName:f,source:l})}catch{}}function qe(t){let o=new Set,e=[re,"connect","cors"];return Object.keys(t).forEach(r=>{t[r].imports.filter(n=>n.external).map(n=>n.path).forEach(n=>{!e.includes(n)&&!_e(n)&&o.add(n)})}),Array.from(o)}function Ae(t,o){let{dependencies:e={},devDependencies:r={}}=t,s={...e,...r},n={name:"mock-server",type:"module",scripts:{start:"node index.js"},dependencies:{connect:"^3.7.0","vite-plugin-mock-dev-server":`^${ne}`,cors:"^2.8.5"},pnpm:{peerDependencyRules:{ignoreMissing:["vite"]}}};return o.forEach(i=>{n.dependencies[i]=s[i]||"latest"}),JSON.stringify(n,null,2)}function Be(t,o,e={},r=8080){return`import { createServer } from 'node:http'; | ||
import connect from 'connect'; | ||
@@ -27,3 +27,3 @@ import corsMiddleware from 'cors'; | ||
console.log('listen: http://localhost:${r}'); | ||
`}async function Be(t,o,e){let r=await $e(o,{cwd:t}),n=_e(o,e,{resolve:!1}),s=r.filter(n),i="",c="";return s.forEach((a,p)=>{let u=Ue(I.join(t,a));i+=`import * as m${p} from '${u}'; | ||
`}async function Je(t,o,e){let r=await He(o,{cwd:t}),s=Ue(o,e,{resolve:!1}),n=r.filter(s),i="",c="";return n.forEach((a,p)=>{let m=Ne(L.join(t,a));i+=`import * as m${p} from '${m}'; | ||
`,c+=`m${p}, `}),`import { transformMockData } from 'vite-plugin-mock-dev-server'; | ||
@@ -37,7 +37,7 @@ ${i} | ||
export default transformMockData(mockList); | ||
`}async function Je(t,o,e){var r;try{let n=await Le({entryPoints:[t],outfile:"out.js",write:!1,target:["node14.18","node16"],platform:"node",bundle:!0,metafile:!0,format:"esm",define:o,plugins:[B(e),N,q,A]});return{code:n.outputFiles[0].text,deps:((r=n.metafile)==null?void 0:r.inputs)||{}}}catch(n){console.error(n)}return{code:"",deps:{}}}import{Buffer as fe}from"buffer";import{parse as ke}from"url";import Qe from"cookies";import Xe from"http-status";import*as $ from"mime-types";import{pathToRegexp as ye}from"path-to-regexp";import H from"picocolors";import Y from"co-body";import ze from"formidable";async function de(t,o){var n;let e=t.method.toUpperCase();if(["GET","DELETE","HEAD"].includes(e))return;let r=((n=t.headers["content-type"])==null?void 0:n.toLocaleLowerCase())||"";try{if(r.startsWith("application/json"))return await Y.json(t);if(r.startsWith("application/x-www-form-urlencoded"))return await Y.form(t);if(r.startsWith("text/plain"))return await Y.text(t);if(r.startsWith("multipart/form-data"))return await Ge(t,o)}catch(s){console.error(s)}}async function Ge(t,o){let e=ze(o);return new Promise((r,n)=>{e.parse(t,(s,i,c)=>{if(s){n(s);return}r({...i,...c})})})}function me(t,o){return C(t.headers,o.headers)&&C(t.body,o.body)&&C(t.params,o.params)&&C(t.query,o.query)&&C(t.refererQuery,o.refererQuery)}function C(t,o){if(!o)return!0;for(let e in o)if(o[e]!==t[e])return!1;return!0}function he(t,{formidableOptions:o={},proxies:e,cookiesOptions:r}){return async function(n,s,i){let c=Date.now(),{query:a,pathname:p}=ke(n.url,!0);if(!p||e.length===0||!e.some(S=>z(S,n.url)))return i();let u=t.mockData,l=Object.keys(u).find(S=>ye(S).test(p));if(!l)return i();let{query:v}=ke(n.headers.referer||"",!0),M=await de(n,o),y=new Qe(n,s,r),k=y.get.bind(y),m=n.method.toUpperCase(),d=Ke(u[l],{pathname:p,method:m,request:{query:a,refererQuery:v,body:M,headers:n.headers,getCookie:k}});if(!d)return i();D("middleware: ",m,n.url);let h=n,g=s;h.body=M,h.query=a,h.refererQuery=v,h.params=L(d.url,p),h.getCookie=k,g.setCookie=y.set.bind(y);let{body:w,delay:f,type:O="json",response:T,status:X=200,statusText:je}=d;if(Z(g,X,je),await Ve(h,g,d),await Ye(h,g,d),w){try{let S=R(w)?await w(h):w;await ge(c,f),Ze(g,S,O)}catch(S){W.error(`${H.red("[body error]")} ${n.url} | ||
`,S),Z(g,500),s.end("")}return}if(T){try{await ge(c,f),await T(h,g,i)}catch(S){W.error(`${H.red("[response error]")} ${n.url} | ||
`,S),Z(g,500),s.end("")}return}s.end("")}}function Ke(t,{pathname:o,method:e,request:r}){return t.find(n=>{if(!o||!n||!n.url||n.ws===!0||!(n.method?P(n.method)?n.method:[n.method]:["GET","POST"]).includes(e))return!1;let i=ye(n.url).test(o);if(i&&n.validator){let c=L(n.url,o);if(R(n.validator))return n.validator({params:c,...r});try{return me({params:c,...r},n.validator)}catch(a){return W.error(`${H.red("[validator error]")} ${o} | ||
`,a),!1}}return i})}function Z(t,o=200,e){t.statusCode=o,t.statusMessage=e||et(o)}async function Ve(t,o,{headers:e,type:r="json"}){let n=$.contentType(r)||$.contentType($.lookup(r)||"");if(n&&o.setHeader("Content-Type",n),o.setHeader("Cache-Control","no-cache,max-age=0"),o.setHeader("X-Mock","generate by vite:plugin-mock-dev-server"),!!e)try{let s=R(e)?await e(t):e;Object.keys(s).forEach(i=>{o.setHeader(i,s[i])})}catch(s){W.error(`${H.red("[headers error]")} ${t.url} | ||
`,s)}}async function Ye(t,o,{cookies:e}){if(e)try{let r=R(e)?await e(t):e;Object.keys(r).forEach(n=>{let s=r[n];if(P(s)){let[i,c]=s;o.setCookie(n,i,c)}else o.setCookie(n,s)})}catch(r){W.error(`${H.red("[cookies error]")} ${t.url} | ||
`,r)}}function Ze(t,o,e){if(ae(o))o.pipe(t);else if(fe.isBuffer(o))t.end(e==="text"||e==="json"?o.toString("utf-8"):o);else{let r=typeof o=="string"?o:JSON.stringify(o);t.end(e==="buffer"?fe.from(r):r)}}async function ge(t,o){if(!o||o<=0)return;let e=Date.now()-t,r=o-e;r>0&&await pe(r)}function et(t){return Xe[t]||"Unknown"}import rt from"events";import ee from"fs";import{createRequire as st}from"module";import Me from"path";import{pathToFileURL as nt}from"url";import be from"chokidar";import{build as it}from"esbuild";import ct from"fast-glob";import{createFilter as at,normalizePath as U}from"vite";import{parse as tt}from"url";import ot from"lodash.sortby";function ve(t){let o=[];for(let[,r]of t.entries())r&&(P(r)?o.push(...r):o.push(r));let e={};return o.filter(r=>(r.enabled||typeof r.enabled>"u")&&r.url).forEach(r=>{let{pathname:n,query:s}=tt(r.url,!0),i=e[n]??(e[n]=[]),c={...r,url:n};if(c.ws!==!0){let a=c.validator;ce(s)||(R(a)?c.validator=function(p){return C(p.query,s)&&a(p)}:a?(c.validator={...a},c.validator.query=c.validator.query?{...s,...c.validator.query}:s):c.validator={query:s})}i.push(c)}),Object.keys(e).forEach(r=>{e[r]=ot(e[r],n=>{if(n.ws===!0)return 0;let{validator:s}=n;if(!s)return 1;if(R(s))return 0;let{query:i,params:c,headers:a,body:p,refererQuery:u}=s;return 1/(_(i)+_(c)+_(a)+_(p)+_(u))})}),e}function _(t){return t?Object.keys(t).length:0}var pt=le(import.meta.url),E=st(pt),Q=class extends rt{constructor(e){super();this.options=e;this.moduleCache=new Map;this.moduleDeps=new Map;this.moduleType="cjs";this._mockData={};this.cwd=e.cwd||process.cwd();try{let r=F(this.cwd,["package.json"]);this.moduleType=r&&JSON.parse(r).type==="module"?"esm":"cjs"}catch{}}get mockData(){return this._mockData}async load(){let{include:e,exclude:r}=this.options,n=await ct(e,{cwd:this.cwd}),s=at(e,r,{resolve:!1});this.watchMockEntry(),this.watchDeps();for(let c of n.filter(s))await this.loadMock(c);this.updateMockList();let i=null;this.on("mock:update",async c=>{s(c)&&(await this.loadMock(c),i&&clearTimeout(i),i=setTimeout(()=>{this.updateMockList(),this.emit("mock:update-end",c),i=null},0))}),this.on("mock:unlink",async c=>{s(c)&&(this.moduleCache.delete(c),this.updateMockList(),this.emit("mock:update-end",c))})}watchMockEntry(){let{include:e}=this.options,[r,...n]=e,s=be.watch(r,{ignoreInitial:!0,cwd:this.cwd});n.length>0&&n.forEach(i=>s.add(i)),s.on("add",async i=>{i=U(i),this.emit("mock:update",i),D("watcher:add",i)}),s.on("change",async i=>{i=U(i),this.emit("mock:update",i),D("watcher:change",i)}),s.on("unlink",async i=>{i=U(i),this.emit("mock:unlink",i),D("watcher:unlink",i)}),this.mockWatcher=s}watchDeps(){let e=[];this.depsWatcher=be.watch([],{ignoreInitial:!0,cwd:this.cwd}),this.depsWatcher.on("change",r=>{r=U(r);let n=this.moduleDeps.get(r);n&&n.forEach(s=>{this.emit("mock:update",s)})}),this.depsWatcher.on("unlink",r=>{r=U(r),this.moduleDeps.delete(r)}),this.on("update:deps",()=>{let r=[];for(let[s]of this.moduleDeps.entries())r.push(s);let n=r.filter(s=>!e.includes(s));n.length>0&&this.depsWatcher.add(n)})}close(){var e,r;(e=this.mockWatcher)==null||e.close(),(r=this.depsWatcher)==null||r.close()}updateMockList(){this._mockData=ve(this.moduleCache)}updateModuleDeps(e,r){Object.keys(r).forEach(n=>{r[n].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{code:n,deps:s}=await this.transformWithEsbuild(e,r);try{let i=await this.loadFromCode(e,n,r),c=i&&i.default?i.default:Object.keys(i||{}).map(a=>i[a]);P(c)?c.forEach(a=>a.__filepath__=e):c.__filepath__=e,this.moduleCache.set(e,c),this.updateModuleDeps(e,s)}catch(i){console.error(i)}}async loadFromCode(e,r,n){if(n){let s=`${e}.timestamp-${Date.now()}`,i=`${s}.mjs`,c=`${nt(s)}.mjs`;await ee.promises.writeFile(i,r,"utf8");try{return await import(c)}finally{try{ee.unlinkSync(i)}catch{}}}else{e=Me.resolve(this.cwd,e);let s=Me.extname(e),i=ee.realpathSync(e),c=s in E.extensions?s:".js",a=E.extensions[c];E.extensions[c]=(u,l)=>{l===i?u._compile(r,l):a(u,l)},delete E.cache[E.resolve(e)];let p=E(e);return E.extensions[c]=a,p.__esModule?p:{default:p}}}async transformWithEsbuild(e,r){var n;try{let s=await it({entryPoints:[e],outfile:"out.js",write:!1,target:["node14.18","node16"],platform:"node",bundle:!0,metafile:!0,format:r?"esm":"cjs",define:this.options.define,plugins:[B(this.options.alias),N,A,q]});return{code:s.outputFiles[0].text,deps:((n=s.metafile)==null?void 0:n.inputs)||{}}}catch(s){console.error(s)}return{code:"",deps:{}}}};import{parse as xe}from"url";import lt from"cookies";import{pathToRegexp as we}from"path-to-regexp";import{WebSocketServer as ut}from"ws";function Oe(t,o,e,r){var c;let n=new Set,s=new Map,i=new Map;(c=t.on)==null||c.call(t,"mock:update-end",a=>{if(!n.has(a))return;let p={};for(let[u,l]of i.entries())t.mockData[u].forEach(v=>{v.__filepath__===a&&v.ws&&l.forEach(({pathname:M,req:y,ws:k})=>{p[M]??(p[M]={mock:v,list:[],mockUrl:u}),p[M].list.push({req:y,ws:k}),k.removeAllListeners()})});Object.keys(p).forEach(u=>{var k,m;let l=s.get(u),{mock:v,list:M,mockUrl:y}=p[u];l.wss.removeAllListeners(),(k=l.cancel)==null||k.call(l),l.cancel=(m=v.setup)==null?void 0:m.call(v,l.wss),l.wss.on("close",()=>{s.delete(u)}),M.forEach(({req:d,ws:h})=>{l.wss.emit("connection",h,d),h.on("close",()=>{let g=i.get(y),w=(g==null?void 0:g.findIndex(f=>f.ws===h))||-1;w>=0&&(g==null||g.splice(w,1))})})})}),o==null||o.on("upgrade",(a,p,u)=>{var w;let{pathname:l,query:v}=xe(a.url,!0);if(!l||e.length===0||!e.some(f=>z(f,a.url)))return;let M=t.mockData,y=Object.keys(M).find(f=>we(f).test(l));if(!y)return;let k=M[y].find(f=>f.url&&f.ws&&we(f.url).test(l));if(!k)return;n.add(k.__filepath__);let m=s.get(l);if(!m){let f=new ut({noServer:!0}),O=(w=k.setup)==null?void 0:w.call(k,f);f.on("close",()=>{s.delete(l)}),m={wss:f,cancel:O},s.set(l,m)}let d=a,h=new lt(a,a,r),{query:g}=xe(a.headers.referer||"",!0);d.query=v,d.refererQuery=g,d.params=L(y,l),d.getCookie=h.get.bind(h),m.wss.handleUpgrade(d,p,u,f=>{D(`websocket-mock: ${a.url} connected`),m.wss.emit("connection",f,d);let O=i.get(y);O||(O=[],i.set(y,O)),O.push({req:d,ws:f,pathname:l}),f.on("close",()=>{let T=O.findIndex(X=>X.ws===f);T>=0&&O.splice(T,1)})})}),o==null||o.on("close",()=>{s.forEach(({wss:a,cancel:p})=>{p==null||p(),a.close()}),s.clear(),n.clear(),i.clear()})}async function te(t,o,e,r){let n=j(o.include),s=j(o.exclude),i={};if(t.define)for(let u in t.define){let l=t.define[u];i[u]=typeof l=="string"?l:JSON.stringify(l)}let c=new Q({include:n,exclude:s,define:i,alias:t.resolve.alias});await c.load(),c.on("mock:update-end",()=>{o.reload&&(r==null||r.send({type:"full-reload"}))}),e==null||e.on("close",()=>c.close());let{httpProxies:a}=J(t.server.proxy||{}),p=j(o.prefix);return Oe(c,e,j(o.wsPrefix),o.cookiesOptions),he(c,{formidableOptions:o.formidableOptions,proxies:[...p,...a],cookiesOptions:o.cookiesOptions})}function Pe({prefix:t=[],wsPrefix:o=[],include:e=["mock/**/*.mock.{js,ts,cjs,mjs,json,json5}"],exclude:r=["**/node_modules/**","**/.vscode/**","**/.git/**"],reload:n=!1,formidableOptions:s={},build:i=!1,cookiesOptions:c={}}={}){let a={prefix:t,wsPrefix:o,include:e,exclude:r,reload:n,cookiesOptions:c,formidableOptions:{multiples:!0,...s},build:i?Object.assign({serverPort:8080,dist:"mockServer"},typeof i=="object"?i:{}):!1},p=[mt(a)];return a.build&&p.push(dt(a)),p}function dt(t){let o={};return{name:"vite-plugin-mock-dev-server-generator",enforce:"post",apply:"build",configResolved(e){o=e,e.logger.warn("")},async buildEnd(e){e||o.command==="build"&&await ue(this,o,t)}}}function mt(t){let o={};return{name:"vite-plugin-mock-dev-server",enforce:"pre",apply:"serve",configResolved(e){o=e,e.logger.warn("")},async configureServer({middlewares:e,config:r,httpServer:n,ws:s}){let i=await te(r,t,n,s);e.use(i)},async configurePreviewServer({middlewares:e,httpServer:r}){let n=await te(o,t,r);e.use(n)}}}function qo(t){return t}function Ao(t){return e=>(P(e)?e=e.map(r=>t(r)||r):e=t(e)||e,e)}var Go=Pe;export{he as baseMiddleware,Ao as createDefineMock,Go as default,qo as defineMock,Pe as mockDevServerPlugin,Oe as mockWebSocket,ve as transformMockData}; | ||
`}async function ze(t,o,e){var r;try{let s=await $e({entryPoints:[t],outfile:"out.js",write:!1,target:["node14.18","node16"],platform:"node",bundle:!0,metafile:!0,format:"esm",define:o,plugins:[J(e),q,A,B]});return{code:s.outputFiles[0].text,deps:((r=s.metafile)==null?void 0:r.inputs)||{}}}catch(s){console.error(s)}return{code:"",deps:{}}}import{Buffer as fe}from"buffer";import{parse as ke}from"url";import Xe from"cookies";import Ke from"http-status";import*as H from"mime-types";import{pathToRegexp as ye}from"path-to-regexp";import _ from"picocolors";import Y from"co-body";import Ge from"formidable";async function me(t,o){var s;let e=t.method.toUpperCase();if(["GET","DELETE","HEAD"].includes(e))return;let r=((s=t.headers["content-type"])==null?void 0:s.toLocaleLowerCase())||"";try{if(r.startsWith("application/json"))return await Y.json(t);if(r.startsWith("application/x-www-form-urlencoded"))return await Y.form(t);if(r.startsWith("text/plain"))return await Y.text(t);if(r.startsWith("multipart/form-data"))return await Qe(t,o)}catch(n){console.error(n)}}async function Qe(t,o){let e=Ge(o);return new Promise((r,s)=>{e.parse(t,(n,i,c)=>{if(n){s(n);return}r({...i,...c})})})}function de(t,o){return W(t.headers,o.headers)&&W(t.body,o.body)&&W(t.params,o.params)&&W(t.query,o.query)&&W(t.refererQuery,o.refererQuery)}function W(t,o){if(!o)return!0;for(let e in o)if(o[e]!==t[e])return!1;return!0}function he(t,{formidableOptions:o={},proxies:e,cookiesOptions:r}){return async function(s,n,i){let c=Date.now(),{query:a,pathname:p}=ke(s.url,!0);if(!p||e.length===0||!e.some(j=>G(j,s.url)))return i();let m=t.mockData,u=Object.keys(m).find(j=>ye(j).test(p));if(!u)return i();let{query:b}=ke(s.headers.referer||"",!0),h=await me(s,o),k=new Xe(s,n,r),g=k.get.bind(k),f=s.method.toUpperCase(),l=Ve(m[u],{pathname:p,method:f,request:{query:a,refererQuery:b,body:h,headers:s.headers,getCookie:g}});if(!l)return i();D("middleware: ",f,s.url);let v=s,y=n;v.body=h,v.query=a,v.refererQuery=b,v.params=$(l.url,p),v.getCookie=g,y.setCookie=k.set.bind(k);let{body:M,delay:d,type:x="json",response:R,status:T=200,statusText:je}=l;if(Z(y,T,je),await Ye(v,y,l),await Ze(v,y,l),M){try{let j=C(M)?await M(v):M;await ge(c,d),et(y,j,x)}catch(j){I.error(`${_.red("[body error]")} ${s.url} | ||
`,j),Z(y,500),n.end("")}return}if(R){try{await ge(c,d),await R(v,y,i)}catch(j){I.error(`${_.red("[response error]")} ${s.url} | ||
`,j),Z(y,500),n.end("")}return}n.end("")}}function Ve(t,{pathname:o,method:e,request:r}){return t.find(s=>{if(!o||!s||!s.url||s.ws===!0||!(s.method?S(s.method)?s.method:[s.method]:["GET","POST"]).includes(e))return!1;let i=ye(s.url).test(o);if(i&&s.validator){let c=$(s.url,o);if(C(s.validator))return s.validator({params:c,...r});try{return de({params:c,...r},s.validator)}catch(a){return I.error(`${_.red("[validator error]")} ${o} | ||
`,a),!1}}return i})}function Z(t,o=200,e){t.statusCode=o,t.statusMessage=e||tt(o)}async function Ye(t,o,{headers:e,type:r="json"}){let s=H.contentType(r)||H.contentType(H.lookup(r)||"");if(s&&o.setHeader("Content-Type",s),o.setHeader("Cache-Control","no-cache,max-age=0"),o.setHeader("X-Mock","generate by vite:plugin-mock-dev-server"),!!e)try{let n=C(e)?await e(t):e;Object.keys(n).forEach(i=>{o.setHeader(i,n[i])})}catch(n){I.error(`${_.red("[headers error]")} ${t.url} | ||
`,n)}}async function Ze(t,o,{cookies:e}){if(e)try{let r=C(e)?await e(t):e;Object.keys(r).forEach(s=>{let n=r[s];if(S(n)){let[i,c]=n;o.setCookie(s,i,c)}else o.setCookie(s,n)})}catch(r){I.error(`${_.red("[cookies error]")} ${t.url} | ||
`,r)}}function et(t,o,e){if(ae(o))o.pipe(t);else if(fe.isBuffer(o))t.end(e==="text"||e==="json"?o.toString("utf-8"):o);else{let r=typeof o=="string"?o:JSON.stringify(o);t.end(e==="buffer"?fe.from(r):r)}}async function ge(t,o){if(!o||o<=0)return;let e=Date.now()-t,r=o-e;r>0&&await pe(r)}function tt(t){return Ke[t]||"Unknown"}import nt from"events";import ee from"fs";import{createRequire as st}from"module";import Me from"path";import{pathToFileURL as it}from"url";import be from"chokidar";import{build as ct}from"esbuild";import at from"fast-glob";import{createFilter as pt,normalizePath as N}from"vite";import{parse as ot}from"url";import rt from"lodash.sortby";function ve(t){let o=[];for(let[,r]of t.entries())r&&(S(r)?o.push(...r):o.push(r));let e={};return o.filter(r=>(r.enabled||typeof r.enabled>"u")&&r.url).forEach(r=>{let{pathname:s,query:n}=ot(r.url,!0),i=e[s]??(e[s]=[]),c={...r,url:s};if(c.ws!==!0){let a=c.validator;ce(n)||(C(a)?c.validator=function(p){return W(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]=rt(e[r],s=>{if(s.ws===!0)return 0;let{validator:n}=s;if(!n)return 1;if(C(n))return 0;let{query:i,params:c,headers:a,body:p,refererQuery:m}=n;return 1/(U(i)+U(c)+U(a)+U(p)+U(m))})}),e}function U(t){return t?Object.keys(t).length:0}var ut=ue(import.meta.url),E=st(ut),X=class extends nt{constructor(e){super();this.options=e;this.moduleCache=new Map;this.moduleDeps=new Map;this.moduleType="cjs";this._mockData={};this.cwd=e.cwd||process.cwd();try{let r=F(this.cwd,["package.json"]);this.moduleType=r&&JSON.parse(r).type==="module"?"esm":"cjs"}catch{}}get mockData(){return this._mockData}async load(){let{include:e,exclude:r}=this.options,s=await at(e,{cwd:this.cwd}),n=pt(e,r,{resolve:!1});this.watchMockEntry(),this.watchDeps();for(let c of s.filter(n))await this.loadMock(c);this.updateMockList();let i=null;this.on("mock:update",async c=>{n(c)&&(await this.loadMock(c),i&&clearTimeout(i),i=setTimeout(()=>{this.updateMockList(),this.emit("mock:update-end",c),i=null},0))}),this.on("mock:unlink",async c=>{n(c)&&(this.moduleCache.delete(c),this.updateMockList(),this.emit("mock:update-end",c))})}watchMockEntry(){let{include:e}=this.options,[r,...s]=e,n=be.watch(r,{ignoreInitial:!0,cwd:this.cwd});s.length>0&&s.forEach(i=>n.add(i)),n.on("add",async i=>{i=N(i),this.emit("mock:update",i),D("watcher:add",i)}),n.on("change",async i=>{i=N(i),this.emit("mock:update",i),D("watcher:change",i)}),n.on("unlink",async i=>{i=N(i),this.emit("mock:unlink",i),D("watcher:unlink",i)}),this.mockWatcher=n}watchDeps(){let e=[];this.depsWatcher=be.watch([],{ignoreInitial:!0,cwd:this.cwd}),this.depsWatcher.on("change",r=>{r=N(r);let s=this.moduleDeps.get(r);s&&s.forEach(n=>{this.emit("mock:update",n)})}),this.depsWatcher.on("unlink",r=>{r=N(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=ve(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{code:s,deps:n}=await this.transformWithEsbuild(e,r);try{let i=await this.loadFromCode(e,s,r),c=i&&i.default?i.default:Object.keys(i||{}).map(a=>i[a]);S(c)?c.forEach(a=>a.__filepath__=e):c.__filepath__=e,this.moduleCache.set(e,c),this.updateModuleDeps(e,n)}catch(i){console.error(i)}}async loadFromCode(e,r,s){if(s){let n=`${e}.timestamp-${Date.now()}`,i=`${n}.mjs`,c=`${it(n)}.mjs`;await ee.promises.writeFile(i,r,"utf8");try{return await import(c)}finally{try{ee.unlinkSync(i)}catch{}}}else{e=Me.resolve(this.cwd,e);let n=Me.extname(e),i=ee.realpathSync(e),c=n in E.extensions?n:".js",a=E.extensions[c];E.extensions[c]=(m,u)=>{u===i?m._compile(r,u):a(m,u)},delete E.cache[E.resolve(e)];let p=E(e);return E.extensions[c]=a,p.__esModule?p:{default:p}}}async transformWithEsbuild(e,r){var s;try{let n=await ct({entryPoints:[e],outfile:"out.js",write:!1,target:["node14.18","node16"],platform:"node",bundle:!0,metafile:!0,format:r?"esm":"cjs",define:this.options.define,plugins:[J(this.options.alias),q,B,A]});return{code:n.outputFiles[0].text,deps:((s=n.metafile)==null?void 0:s.inputs)||{}}}catch(n){console.error(n)}return{code:"",deps:{}}}};import{parse as xe}from"url";import lt from"cookies";import{pathToRegexp as we}from"path-to-regexp";import{WebSocketServer as mt}from"ws";function Se(t,o,e,r){var c;let s=new Set,n=new Map,i=new Map;(c=t.on)==null||c.call(t,"mock:update-end",a=>{if(!s.has(a))return;let p={};for(let[m,u]of i.entries())t.mockData[m].forEach(b=>{b.ws&&b.__filepath__===a&&u.forEach(({pathname:h,req:k,ws:g})=>{p[h]??(p[h]={mock:b,list:[],mockUrl:m}),p[h].list.push({req:k,ws:g})})});Object.keys(p).forEach(m=>{var l;let{wss:u,cleanupList:b,context:h}=n.get(m),{mock:k,list:g,mockUrl:f}=p[m];Oe(b),u.removeAllListeners(),(l=k.setup)==null||l.call(k,u,h),u.on("close",()=>n.delete(m)),g.forEach(({req:v,ws:y})=>{y.removeAllListeners(),u.emit("connection",y,v),y.on("close",()=>{let M=i.get(f),d=(M==null?void 0:M.findIndex(x=>x.ws===y))||-1;d!==-1&&(M==null||M.splice(d,1))})})})}),o==null||o.on("upgrade",(a,p,m)=>{var M;let{pathname:u,query:b}=xe(a.url,!0);if(!u||e.length===0||!e.some(d=>G(d,a.url)))return;let h=t.mockData,k=Object.keys(h).find(d=>we(d).test(u));if(!k)return;let g=h[k].find(d=>d.url&&d.ws&&we(d.url).test(u));if(!g)return;s.add(g.__filepath__);let f=n.get(u);if(!f){let d=new mt({noServer:!0}),x=[],R={onCleanup:T=>x.push(T)};(M=g.setup)==null||M.call(g,d,R),d.on("close",()=>n.delete(u)),n.set(u,f={wss:d,cleanupList:x,context:R})}let l=a,v=new lt(a,a,r),{query:y}=xe(a.headers.referer||"",!0);l.query=b,l.refererQuery=y,l.params=$(k,u),l.getCookie=v.get.bind(v),f.wss.handleUpgrade(l,p,m,d=>{D(`websocket-mock: ${a.url} connected`),f.wss.emit("connection",d,l);let x=i.get(k);x||i.set(k,x=[]),x.push({req:l,ws:d,pathname:u}),d.on("close",()=>{let R=x.findIndex(T=>T.ws===d);R!==-1&&x.splice(R,1)})})}),o==null||o.on("close",()=>{n.forEach(({wss:a,cleanupList:p})=>{Oe(p),a.close()}),n.clear(),i.clear(),s.clear()})}function Oe(t){let o;for(;o=t.shift();)o==null||o()}async function te(t,o,e,r){let s=P(o.include),n=P(o.exclude),i={};if(t.define)for(let m in t.define){let u=t.define[m];i[m]=typeof u=="string"?u:JSON.stringify(u)}let c=new X({include:s,exclude:n,define:i,alias:t.resolve.alias});await c.load(),c.on("mock:update-end",()=>{o.reload&&(r==null||r.send({type:"full-reload"}))}),e==null||e.on("close",()=>c.close());let{httpProxies:a}=z(t.server.proxy||{}),p=P(o.prefix);return Se(c,e,P(o.wsPrefix),o.cookiesOptions),he(c,{formidableOptions:o.formidableOptions,proxies:[...p,...a],cookiesOptions:o.cookiesOptions})}function Pe({prefix:t=[],wsPrefix:o=[],include:e=["mock/**/*.mock.{js,ts,cjs,mjs,json,json5}"],exclude:r=["**/node_modules/**","**/.vscode/**","**/.git/**"],reload:s=!1,formidableOptions:n={},build:i=!1,cookiesOptions:c={}}={}){let a={prefix:t,wsPrefix:o,include:e,exclude:r,reload:s,cookiesOptions:c,formidableOptions:{multiples:!0,...n},build:i?Object.assign({serverPort:8080,dist:"mockServer"},typeof i=="object"?i:{}):!1},p=[ft(a)];return a.build&&p.push(dt(a)),p}function dt(t){let o={};return{name:"vite-plugin-mock-dev-server-generator",enforce:"post",apply:"build",configResolved(e){o=e,e.logger.warn("")},async buildEnd(e){e||o.command==="build"&&await le(this,o,t)}}}function ft(t){let o={};return{name:"vite-plugin-mock-dev-server",enforce:"pre",apply:"serve",configResolved(e){o=e,e.logger.warn("")},async configureServer({middlewares:e,config:r,httpServer:s,ws:n}){let i=await te(r,t,s,n);e.use(i)},async configurePreviewServer({middlewares:e,httpServer:r}){let s=await te(o,t,r);e.use(s)}}}function Ao(t){return t}function Bo(t){return e=>(S(e)?e=e.map(r=>t(r)||r):e=t(e)||e,e)}var Qo=Pe;export{he as baseMiddleware,Bo as createDefineMock,Qo as default,Ao as defineMock,Pe as mockDevServerPlugin,Se as mockWebSocket,ve as transformMockData}; |
{ | ||
"name": "vite-plugin-mock-dev-server", | ||
"version": "1.1.6", | ||
"version": "1.1.7", | ||
"keywords": [ | ||
@@ -5,0 +5,0 @@ "vite", |
@@ -158,3 +158,3 @@ # vite-plugin-mock-dev-server | ||
If the value of `wsPrefix` starts with `^`, it will be recognized as a RegExp. | ||
If the value of `wsPrefix` starts with `^`, it will be recognized as a RegExp. | ||
@@ -409,7 +409,16 @@ > Different from using `viteConfig.server.proxy` by default for http mock, `websocket mock` does not use the ws-related configuration in `viteConfig.server.proxy`. Also, rules configured in `wsPrefix` cannot be configured simultaneously in `viteConfig.server.proxy`, as it will cause conflicts when starting the vite server because multiple instances of WebSocketServer cannot be implemented for the same request. | ||
* @see https://github.com/websockets/ws/blob/master/doc/ws.md#class-websocketserver | ||
* If there are some additional automatically executed tasks or loop | ||
* tasks in the setup function,a callback needs to be passed in | ||
* `onCleanup()` to clear these tasks. | ||
* This is because when the plugin is hot updated, | ||
* it needs to re-execute setup and clear previous tasks; otherwise, | ||
* duplicate tasks may cause conflicts. | ||
* `onCleanup()` can be called multiple times within setup. | ||
* @type `(wss: WebSocketServer, context: SetupContext) => void` | ||
*/ | ||
setup(wss) { | ||
setup(wss, { onCleanup }) { | ||
wss.on('connection', (ws, request) => { | ||
ws.on('message', (rawData) => {}) | ||
ws.send('data') | ||
const timer = setInterval(() => ws.send('data'), 1000) | ||
onCleanup(() => clearInterval(timer)) | ||
}) | ||
@@ -721,3 +730,3 @@ } | ||
ws: true, | ||
setup(wss) { | ||
setup(wss, { onCleanup }) { | ||
const wsMap = new Map() | ||
@@ -740,5 +749,3 @@ wss.on('connection', (ws, req) => { | ||
}) | ||
return () => { | ||
wsMap.clear() | ||
} | ||
onCleanup(() => wsMap.clear()) | ||
} | ||
@@ -753,3 +760,3 @@ }) | ||
// heartbeat | ||
ws.send({ type: 'ping' }) | ||
ws.send(JSON.stringify({ type: 'ping' })) | ||
}, 1000) | ||
@@ -756,0 +763,0 @@ }, { once: true }) |
@@ -402,7 +402,13 @@ # vite-plugin-mock-dev-server | ||
* @see https://github.com/websockets/ws/blob/master/doc/ws.md#class-websocketserver | ||
* 如果在 setup 函数中有一些 额外的 自动执行任务或循环任务, | ||
* 那么需要在 `onCleanup()` 传入一个回调,用于清除这些任务, | ||
* 这是由于插件在热更新时,需要重新执行 setup,需要清除之前的任务,否则可能会导致重复任务产生冲突。 | ||
* `onCleanup()`可以在 setup 内部多次调用 | ||
* @type `(wss: WebSocketServer, context: SetupContext) => void` | ||
*/ | ||
setup(wss) { | ||
setup(wss, { onCleanup }) { | ||
wss.on('connection', (ws, request) => { | ||
ws.on('message', (rawData) => {}) | ||
ws.send('data') | ||
const timer = setInterval(() => ws.send('data'), 1000) | ||
onCleanup(() => clearInterval(timer)) | ||
}) | ||
@@ -713,3 +719,3 @@ } | ||
ws: true, | ||
setup(wss) { | ||
setup(wss, { onCleanup }) { | ||
const wsMap = new Map() | ||
@@ -732,5 +738,3 @@ wss.on('connection', (ws, req) => { | ||
}) | ||
return () => { | ||
wsMap.clear() | ||
} | ||
onCleanup(() => wsMap.clear()) | ||
} | ||
@@ -745,3 +749,3 @@ }) | ||
// heartbeat | ||
ws.send({ type: 'ping' }) | ||
ws.send(JSON.stringify({ type: 'ping' })) | ||
}, 1000) | ||
@@ -748,0 +752,0 @@ }, { once: true }) |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
100000
654
794