UNPKG

xhr-mocker

Version:

a npm module to mock/modify xhr/fetch responses for front-end development

2 lines (1 loc) 12.1 kB
(function(L,b){typeof exports=="object"&&typeof module!="undefined"?b(exports,require("localforage")):typeof define=="function"&&define.amd?define(["exports","localforage"],b):(L=typeof globalThis!="undefined"?globalThis:L||self,b(L.mockTools={},L.i))})(void 0,function(L,b){"use strict";const W=t=>{try{const e=document.createElement("script");e.src=t,e.onerror=function(){console.error("\u52A0\u8F7Dmock-sdk\u5931\u8D25")},e.onload=function(){console.info("\u52A0\u8F7Dmock-sdk\u6210\u529F"),setTimeout(()=>{const s=new CustomEvent("mock-sdk-loaded",{detail:!0});window.dispatchEvent(s)},100)},document.getElementsByTagName("body")[0].appendChild(e)}catch(e){console.error(`mock-sdk\u52A0\u8F7D\u5931\u8D25, ${e.message}`)}},J=()=>{const t='<div id="mock-tool-web"></div>',e=document.createElement("div");e.innerHTML=t,document.getElementsByTagName("body")[0].appendChild(e)},B=t=>{typeof window!="undefined"&&(J(),W(t))},K=window.XMLHttpRequest;function E(t){return Object.prototype.toString.call(t)==="[object String]"}function G(t){return Object.prototype.toString.call(t)==="[object RegExp]"}function T(t,e){return E(t)?G(e)?e.test(t):typeof e=="string"?t.indexOf(e)!==-1:!1:!1}const M=t=>{let e=t.split("?");return e[0].indexOf("//")>-1?e[0].split("//")[1]:e[0]},R=(t,e,s)=>!(e!=null&&e.length&&!e.some(r=>T(t,r))||s!=null&&s.length&&s.some(r=>T(t,r)));function V(t){const e=new K,s=t._openArgs;e.open(s.method,s.url,s.async,s.username,s.password),t._requestHeaders&&t._requestHeaders.forEach(({value:u,name:a})=>{e.setRequestHeader(a,u)}),["timeout","withCredentials","responseType","msCaching","mimeType"].forEach(u=>{if(t[u]!==void 0)try{e[u]=t[u]}catch(a){console.warn(`Failed to copy property ${u}:`,a)}});const r=["abort","error","load","loadend","loadstart","progress","readystatechange","timeout"];return r.forEach(u=>{const a=t[`on${u}`];typeof a=="function"&&(e[`on${u}`]=a.bind(e))}),t._events&&Object.entries(t._events).forEach(([u,a])=>{a.forEach(({listener:i,options:h})=>{e.addEventListener(u,i.bind(e),h)})}),t.upload&&r.forEach(u=>{const a=t.upload[`on${u}`];typeof a=="function"&&(e.upload[`on${u}`]=a.bind(e.upload))}),e}const q=({url:t,mockUrl:e,method:s,mockData:r})=>{e?(console.groupCollapsed(`%cMatched XHR Response modified\uFF1A${t}`,"background-color: #108ee9; color: white; padding: 4px"),console.info("%cModified Request Url\uFF1A","background-color: #ff5500; color: white;",e,s)):(console.groupCollapsed(`%cMatched XHR Response modified\uFF1A${t}`,"background-color: #108ee9; color: white; padding: 4px"),console.info("%cOriginal Request Url\uFF1A","background-color: #ff8040; color: white;",t),console.info("%cModified Response Payload\uFF1A","background-color: #ff5500; color: white;",JSON.parse(r||null))),console.groupEnd()};function D(t){let e=typeof t=="string"?t:t.toString();return e.startsWith("//")?`${location.protocol}${e}`:e.startsWith("/")?`${location.origin}${e}`:e.startsWith("http")?e:new URL(e,location.href).href}var z=(t,e,s)=>new Promise((r,u)=>{var a=n=>{try{h(s.next(n))}catch(c){u(c)}},i=n=>{try{h(s.throw(n))}catch(c){u(c)}},h=n=>n.done?r(n.value):Promise.resolve(n.value).then(a,i);h((s=s.apply(t,e)).next())});class Q{constructor(e={}){this.expire=e.expire||0;try{this.store=b.createInstance(Object.assign({name:"common_store",driver:[b.INDEXEDDB,b.LOCALSTORAGE]},e))}catch(s){console.log(s)}}setItem(e,s,r=this.expire){return r&&(r=Date.now()+r*24*60*60*1e3),this.store.setItem(e,{value:s,expire:r}).then(u=>u.value)}getItem(e){return this.store.getItem(e).then(s=>{if(!s)return null;const{value:r,expire:u}=s;return u&&u<Date.now()?this.removeItem(e).then(()=>null):r})}removeItem(e){return this.store.removeItem(e)}clear(){return this.store.clear()}clearExpired(){return z(this,null,function*(){const e=yield this.keys();return Promise.all(e.map(s=>new Promise((r,u)=>{this.getItem(s).then(r).catch(u)}))).then(()=>{})})}length(){return this.store.length()}keys(){return this.store.keys()}}var Y=Object.defineProperty,Z=Object.defineProperties,ee=Object.getOwnPropertyDescriptors,j=Object.getOwnPropertySymbols,te=Object.prototype.hasOwnProperty,oe=Object.prototype.propertyIsEnumerable,X=(t,e,s)=>e in t?Y(t,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):t[e]=s,se=(t,e)=>{for(var s in e||(e={}))te.call(e,s)&&X(t,s,e[s]);if(j)for(var s of j(e))oe.call(e,s)&&X(t,s,e[s]);return t},ne=(t,e)=>Z(t,ee(e)),re=(t,e,s)=>new Promise((r,u)=>{var a=n=>{try{h(s.next(n))}catch(c){u(c)}},i=n=>{try{h(s.throw(n))}catch(c){u(c)}},h=n=>n.done?r(n.value):Promise.resolve(n.value).then(a,i);h((s=s.apply(t,e)).next())});const ie=XMLHttpRequest.prototype.open,ae=XMLHttpRequest.prototype.send,U=XMLHttpRequest.prototype.setRequestHeader,F=XMLHttpRequest.prototype.addEventListener,A=window.fetch,l={},H={},I={},$=new WeakMap;let w=!1;const x=t=>{const{requestListData:e,rules:s,excludeRules:r,sdkLoaded:u}=t;let a=Object.entries(e).map(i=>i[1]);if(s!=null&&s.length&&(a=a.filter(i=>s.some(h=>T(i.url,h)))),r!=null&&r.length&&(a=a.filter(i=>r.every(h=>!T(i.url,h)))),a.length)if(u){const i=new CustomEvent("mock-request-end",{detail:a.filter(h=>h.url)});window.dispatchEvent(i)}else a.forEach(i=>{I[i.url]=i})},le=()=>{XMLHttpRequest.prototype.open=ie,XMLHttpRequest.prototype.send=ae,XMLHttpRequest.prototype.addEventListener=F,XMLHttpRequest.prototype.setRequestHeader=U,window.fetch=A},N=t=>l[t]&&l[t].activeType==1?l[t].data:null,S=(t,e)=>{if(H[t]=!0,!e)return;const s=new CustomEvent("mock-request-effect",{detail:t});window.dispatchEvent(s),delete H[t]},C=t=>re(void 0,null,function*(){const e=XMLHttpRequest.prototype.open,s=XMLHttpRequest.prototype.send,{rules:r=[],excludeRules:u=[]}=t||{},a=[...u,/hot-update/,/umiui/,/dev-server/,/devScripts/,/umi/,/undefined/,/localhost/,/favicon\.ico/];((yield new Q().getItem("mock-requestList"))||[]).forEach(n=>{n.isOpen&&(l[n.url]=n)});let i={};const h=({url:n,data:c,status:o,updateData:d})=>{i[n].data=c,i[n].status=o,i[n].updateData=d||c};XMLHttpRequest.prototype.send=function(...n){var c;const o=this,d=this.onreadystatechange,f=M(o.originRequestUrl),p=l[f]&&l[f].isOpen;if($.get(o))return s.apply(o,n);if(this.onreadystatechange=function(...g){if(this.readyState===this.DONE){if(this.responseType==="text"||this.responseType===""?this.originResponse=this.responseText:this.originResponse=this.response,p&&l[f].activeType==1&&l[f].isWaitResponse){const m=N(f);Object.defineProperties(o,{readyState:{get:()=>4,configurable:!0},status:{get:()=>200,configurable:!0},response:{get:()=>m||this.originResponse,configurable:!0},responseText:{get:()=>m||this.originResponse,configurable:!0},statusText:{get:()=>"OK",configurable:!0}}),q({url:f,mockData:m})}f&&i[f]&&R(f,r,a)&&(!p||l[f].isWaitResponse)&&(h({url:f,data:E(o.response)?o.response:JSON.stringify(o.response),status:p?200:o.status,updateData:E(o.originResponse)?o.originResponse:JSON.stringify(o.originResponse)}),x({requestListData:i,rules:r,excludeRules:a,sdkLoaded:w}),delete i[f])}typeof d=="function"&&d.apply(this,g)},p&&((c=l[f])==null?void 0:c.activeType)==1){const g=N(f);if(l[f].isWaitResponse)this.onerror=function(){Object.defineProperties(o,{readyState:{get:()=>4,configurable:!0},status:{get:()=>200,configurable:!0},response:{get:()=>g,configurable:!0},responseText:{get:()=>typeof g=="string"?g:JSON.stringify(g),configurable:!0},statusText:{get:()=>"OK",configurable:!0}});const m=new Event("load");this.dispatchEvent(m)},s.apply(this,n);else{const m=V(o);$.set(m,!0),m.send(n),m.onreadystatechange=function(){if(m.readyState===m.DONE){const y=m.responseType==="text"||m.responseType===""?m.responseText:m.response;f&&i[f]&&R(f,r,a)&&(h({url:f,data:E(g)?g:JSON.stringify(g),status:m.status,updateData:E(y)?y:JSON.stringify(y)}),x({requestListData:i,rules:r,excludeRules:a,sdkLoaded:w}),delete i[f])}},setTimeout(()=>{Object.defineProperties(o,{readyState:{get:()=>4,configurable:!0},status:{get:()=>200,configurable:!0},response:{get:()=>g,configurable:!0},responseText:{get:()=>typeof g=="string"?g:JSON.stringify(g),configurable:!0},statusText:{get:()=>"OK",configurable:!0}}),o.onreadystatechange&&o.onreadystatechange(),o.onload&&o.onload(),["loadstart","load","loadend"].forEach(_=>{const v=new Event(_);o.dispatchEvent(v)});const y=new Event("readystatechange");o.dispatchEvent(y),q({url:f,mockData:g})},0)}}else s.apply(this,n)},XMLHttpRequest.prototype.open=function(n,c,...o){const d=Array.from(arguments),f=this,p=M(D(c)),g={url:p,method:n,status:f.status,effectLocation:location.href.split("?")[0]};p&&R(p,r,a)&&(i[p]=g);const m=l[p]&&l[p].isOpen;this.originRequestUrl=p,m&&l[p]&&(l[p].activeType==2&&l[p].mockUrl&&(d[1]="//"+l[p].mockUrl,l[p].mockMethod&&(d[0]=l[p].mockMethod),q({url:p,mockUrl:l[p].mockUrl,method:l[p].mockMethod||n})),S(p,w)),this._openArgs={method:n,url:c,async:o[0],username:o[1],password:o[2]},this._events=this._events||{},e.apply(this,d)},XMLHttpRequest.prototype.addEventListener=function(n,c,o){return this._events=this._events||{},this._events[n]=this._events[n]||[],this._events[n].push({listener:c,options:o}),F.apply(this,arguments)},XMLHttpRequest.prototype.setRequestHeader=function(n,c){return this._requestHeaders||(this._requestHeaders=[]),this._requestHeaders.push({name:n,value:c}),U.apply(this,arguments)},window.fetch=function(n,c){let o="";n&&(typeof n=="string"?o=M(D(n)):typeof n=="object"&&n instanceof Request&&(o=M(D(n.url))),R(o,r,a)&&(i[o]={method:(c==null?void 0:c.method)||"GET",effectLocation:location.href.split("?")[0],url:o}));const d=Array.from(arguments),f=this,p=l[o]&&l[o].isOpen,g=p&&l[o].activeType==2;if(p){if(g){if(typeof d[0]=="string")d[0]="//"+l[o].mockUrl,l[o].mockMethod&&(d[1]=ne(se({},d[1]),{method:l[o].mockMethod}));else if(d[0]instanceof Request){const y=new Request("//"+l[o].mockUrl,{method:l[o].mockMethod||d[0].method,headers:d[0].headers,body:d[0].body,mode:d[0].mode,credentials:d[0].credentials,cache:d[0].cache,redirect:d[0].redirect,referrer:d[0].referrer,integrity:d[0].integrity,keepalive:d[0].keepalive,signal:d[0].signal});d[0]=y}q({url:o,mockUrl:l[o].mockUrl,method:l[o].mockMethod||(c==null?void 0:c.method)})}S(o,w)}const m=A.apply(f,d);return new Promise((y,_)=>{if(p&&!g){const v=l[o].data;l[o].isWaitResponse?m.then(k=>{const O=k.clone();return k.ok&&i[o]&&O.text().then(P=>{h({url:o,data:P,status:k.status})}),k.text().then(()=>{y(new Response(v,{status:200})),q({url:o,mockData:v})})}).catch(()=>{y(new Response(v,{status:200}))}).finally(()=>{o&&i[o]&&R(o,r,a)&&(x({requestListData:i,rules:r,excludeRules:a,sdkLoaded:w}),setTimeout(()=>{delete i[o]},10))}):(y(new Response(v,{status:200})),q({url:o,mockData:v}),m.then(k=>{const O=k.clone();k.ok&&i[o]&&O.text().then(P=>{h({url:o,data:P,status:k.status})})}).finally(()=>{o&&i[o]&&R(o,r,a)&&(x({requestListData:i,rules:r,excludeRules:a,sdkLoaded:w}),setTimeout(()=>{delete i[o]},10))}))}else m.then(v=>{const k=v.clone();v.ok&&i[o]&&k.text().then(O=>{h({url:o,data:O,status:v.status})}),y(v)}).catch(_).finally(()=>{o&&i[o]&&R(o,r,a)&&(x({requestListData:i,rules:r,excludeRules:a,sdkLoaded:w}),setTimeout(()=>{delete i[o]},10))})})},console.log("fetch XMLHttpRequest\u91CD\u5199\u6210\u529F")}),ue=t=>{window.addEventListener("mock-global-switch",e=>{e.detail?C(t):le()}),window.addEventListener("mock-interface-switch",e=>{if(e.detail){const{url:s,isOpen:r,deleteAll:u}=e.detail;if(u)for(const a in l)delete l[a];else r?l[s]=Object.assign({},l[s],e.detail):delete l[s]}}),window.addEventListener("mock-sdk-loaded",e=>{e.detail&&(w=!0,setTimeout(()=>{const s=Object.keys(H);if(s.length)for(const r of s)S(r,w);x({requestListData:I,sdkLoaded:!0})},1e3))})};var ce=(t,e,s)=>new Promise((r,u)=>{var a=n=>{try{h(s.next(n))}catch(c){u(c)}},i=n=>{try{h(s.throw(n))}catch(c){u(c)}},h=n=>n.done?r(n.value):Promise.resolve(n.value).then(a,i);h((s=s.apply(t,e)).next())});const de=t=>ce(void 0,null,function*(){return t.disabled||(localStorage.getItem("mock_tools_all_opened")!=="false"&&(localStorage.setItem("mock_tools_all_opened","true"),yield C(t)),ue(t),B(t.mockPanelSdkUrl||"https://unpkg.com/xhr-mocker-panel-sdk@latest/dist/index.umd.js")),!0});L.mockInit=de});