xhr-mocker
Version:
a npm module to mock/modify xhr/fetch responses for front-end development
2 lines (1 loc) • 12.2 kB
JavaScript
(function(R,x){typeof exports=="object"&&typeof module!="undefined"?x(exports,require("localforage")):typeof define=="function"&&define.amd?define(["exports","localforage"],x):(R=typeof globalThis!="undefined"?globalThis:R||self,x(R.mockTools={},R.i))})(this,function(R,x){"use strict";function J(t){return t&&typeof t=="object"&&"default"in t?t.default:t}const M=J(x),B=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}`)}},K=()=>{const t='<div id="mock-tool-web"></div>',e=document.createElement("div");e.innerHTML=t,document.getElementsByTagName("body")[0].appendChild(e)},G=t=>{typeof window!="undefined"&&(K(),B(t))},V=window.XMLHttpRequest;function E(t){return Object.prototype.toString.call(t)==="[object String]"}function z(t){return Object.prototype.toString.call(t)==="[object RegExp]"}function T(t,e){return E(t)?z(e)?e.test(t):typeof e=="string"?t.indexOf(e)!==-1:!1:!1}const D=t=>{let e=t.split("?");return e[0].indexOf("//")>-1?e[0].split("//")[1]:e[0]},b=(t,e,s)=>!(e!=null&&e.length&&!e.some(r=>T(t,r))||s!=null&&s.length&&s.some(r=>T(t,r)));function Q(t){const e=new V,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:f})=>{e.addEventListener(u,i.bind(e),f)})}),t.upload&&r.forEach(u=>{const a=t.upload[`on${u}`];typeof a=="function"&&(e.upload[`on${u}`]=a.bind(e.upload))}),e}const L=({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 H(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 Y=(t,e,s)=>new Promise((r,u)=>{var a=n=>{try{f(s.next(n))}catch(c){u(c)}},i=n=>{try{f(s.throw(n))}catch(c){u(c)}},f=n=>n.done?r(n.value):Promise.resolve(n.value).then(a,i);f((s=s.apply(t,e)).next())});class Z{constructor(e={}){this.expire=e.expire||0;try{this.store=M.createInstance(Object.assign({name:"common_store",driver:[M.INDEXEDDB,M.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 Y(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 ee=Object.defineProperty,te=Object.defineProperties,oe=Object.getOwnPropertyDescriptors,X=Object.getOwnPropertySymbols,se=Object.prototype.hasOwnProperty,ne=Object.prototype.propertyIsEnumerable,U=(t,e,s)=>e in t?ee(t,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):t[e]=s,re=(t,e)=>{for(var s in e||(e={}))se.call(e,s)&&U(t,s,e[s]);if(X)for(var s of X(e))ne.call(e,s)&&U(t,s,e[s]);return t},ie=(t,e)=>te(t,oe(e)),ae=(t,e,s)=>new Promise((r,u)=>{var a=n=>{try{f(s.next(n))}catch(c){u(c)}},i=n=>{try{f(s.throw(n))}catch(c){u(c)}},f=n=>n.done?r(n.value):Promise.resolve(n.value).then(a,i);f((s=s.apply(t,e)).next())});const le=XMLHttpRequest.prototype.open,ue=XMLHttpRequest.prototype.send,F=XMLHttpRequest.prototype.setRequestHeader,A=XMLHttpRequest.prototype.addEventListener,I=window.fetch,l={},_={},$={},C=new WeakMap;let w=!1;const q=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(f=>T(i.url,f)))),r!=null&&r.length&&(a=a.filter(i=>r.every(f=>!T(i.url,f)))),a.length)if(u){const i=new CustomEvent("mock-request-end",{detail:a.filter(f=>f.url)});window.dispatchEvent(i)}else a.forEach(i=>{$[i.url]=i})},ce=()=>{XMLHttpRequest.prototype.open=le,XMLHttpRequest.prototype.send=ue,XMLHttpRequest.prototype.addEventListener=A,XMLHttpRequest.prototype.setRequestHeader=F,window.fetch=I},N=t=>l[t]&&l[t].activeType==1?l[t].data:null,S=(t,e)=>{if(_[t]=!0,!e)return;const s=new CustomEvent("mock-request-effect",{detail:t});window.dispatchEvent(s),delete _[t]},W=t=>ae(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 Z().getItem("mock-requestList"))||[]).forEach(n=>{n.isOpen&&(l[n.url]=n)});let i={};const f=({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,h=D(o.originRequestUrl),p=l[h]&&l[h].isOpen;if(C.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[h].activeType==1&&l[h].isWaitResponse){const m=N(h);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}}),L({url:h,mockData:m})}h&&i[h]&&b(h,r,a)&&(!p||l[h].isWaitResponse)&&(f({url:h,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)}),q({requestListData:i,rules:r,excludeRules:a,sdkLoaded:w}),delete i[h])}typeof d=="function"&&d.apply(this,g)},p&&((c=l[h])==null?void 0:c.activeType)==1){const g=N(h);if(l[h].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=Q(o);C.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;h&&i[h]&&b(h,r,a)&&(f({url:h,data:E(g)?g:JSON.stringify(g),status:m.status,updateData:E(y)?y:JSON.stringify(y)}),q({requestListData:i,rules:r,excludeRules:a,sdkLoaded:w}),delete i[h])}},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(j=>{const v=new Event(j);o.dispatchEvent(v)});const y=new Event("readystatechange");o.dispatchEvent(y),L({url:h,mockData:g})},0)}}else s.apply(this,n)},XMLHttpRequest.prototype.open=function(n,c,...o){const d=Array.from(arguments),h=this,p=D(H(c)),g={url:p,method:n,status:h.status,effectLocation:location.href.split("?")[0]};p&&b(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),L({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}),A.apply(this,arguments)},XMLHttpRequest.prototype.setRequestHeader=function(n,c){return this._requestHeaders||(this._requestHeaders=[]),this._requestHeaders.push({name:n,value:c}),F.apply(this,arguments)},window.fetch=function(n,c){let o="";n&&(typeof n=="string"?o=D(H(n)):typeof n=="object"&&n instanceof Request&&(o=D(H(n.url))),b(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),h=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]=ie(re({},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}L({url:o,mockUrl:l[o].mockUrl,method:l[o].mockMethod||(c==null?void 0:c.method)})}S(o,w)}const m=I.apply(h,d);return new Promise((y,j)=>{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=>{f({url:o,data:P,status:k.status})}),k.text().then(()=>{y(new Response(v,{status:200})),L({url:o,mockData:v})})}).catch(()=>{y(new Response(v,{status:200}))}).finally(()=>{o&&i[o]&&b(o,r,a)&&(q({requestListData:i,rules:r,excludeRules:a,sdkLoaded:w}),setTimeout(()=>{delete i[o]},10))}):(y(new Response(v,{status:200})),L({url:o,mockData:v}),m.then(k=>{const O=k.clone();k.ok&&i[o]&&O.text().then(P=>{f({url:o,data:P,status:k.status})})}).finally(()=>{o&&i[o]&&b(o,r,a)&&(q({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=>{f({url:o,data:O,status:v.status})}),y(v)}).catch(j).finally(()=>{o&&i[o]&&b(o,r,a)&&(q({requestListData:i,rules:r,excludeRules:a,sdkLoaded:w}),setTimeout(()=>{delete i[o]},10))})})},console.log("fetch XMLHttpRequest\u91CD\u5199\u6210\u529F")}),de=t=>{window.addEventListener("mock-global-switch",e=>{e.detail?W(t):ce()}),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(_);if(s.length)for(const r of s)S(r,w);q({requestListData:$,sdkLoaded:!0})},1e3))})};var pe=(t,e,s)=>new Promise((r,u)=>{var a=n=>{try{f(s.next(n))}catch(c){u(c)}},i=n=>{try{f(s.throw(n))}catch(c){u(c)}},f=n=>n.done?r(n.value):Promise.resolve(n.value).then(a,i);f((s=s.apply(t,e)).next())});const fe=t=>pe(void 0,null,function*(){return t.disabled||(localStorage.getItem("mock_tools_all_opened")!=="false"&&(localStorage.setItem("mock_tools_all_opened","true"),yield W(t)),de(t),G(t.mockPanelSdkUrl||"https://unpkg.com/xhr-mocker-panel-sdk@latest/dist/index.umd.js")),!0});R.mockInit=fe});