mockforme 4.5.0 → 5.0.0
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
CHANGED
|
@@ -29,8 +29,14 @@ yarn add mockforme -D
|
|
|
29
29
|
```
|
|
30
30
|
* Initialize the SDK using Access Token (Generate access token [here](https://dashboard.mockforme.com/user/token))
|
|
31
31
|
```
|
|
32
|
-
mockforme(
|
|
32
|
+
mockforme().run();
|
|
33
33
|
```
|
|
34
|
+
|
|
35
|
+
> **Note:** MockForMe **client** initialisation doesn't required access token, you can enter the token using MockForMe widget
|
|
36
|
+

|
|
37
|
+
|
|
38
|
+
[](https://www.youtube.com/watch?v=CmG5g94_T_8)
|
|
39
|
+
|
|
34
40
|
|
|
35
41
|
* You can also access mockforme object in your browser from window object:
|
|
36
42
|
```
|
|
@@ -38,7 +44,7 @@ yarn add mockforme -D
|
|
|
38
44
|
```
|
|
39
45
|
And initialize it directly from window:
|
|
40
46
|
```
|
|
41
|
-
window.mockforme(
|
|
47
|
+
window.mockforme().run();
|
|
42
48
|
```
|
|
43
49
|
|
|
44
50
|
* You can also directly use mockforme through script file using jsdelivr CDN.
|
|
@@ -47,7 +53,7 @@ yarn add mockforme -D
|
|
|
47
53
|
|
|
48
54
|
<script>
|
|
49
55
|
console.log(window.mockforme);
|
|
50
|
-
window.mockforme(
|
|
56
|
+
window.mockforme().run();
|
|
51
57
|
</script>
|
|
52
58
|
```
|
|
53
59
|
|
package/dist/index.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!doctype html><html><head><meta charset="utf-8"><title>mockforme - The best way to mock your APIs</title><meta name="viewport" content="width=device-width,initial-scale=1"><script defer="defer" src="mockforme.client.
|
|
1
|
+
<!doctype html><html><head><meta charset="utf-8"><title>mockforme - The best way to mock your APIs</title><meta name="viewport" content="width=device-width,initial-scale=1"><script defer="defer" src="mockforme.client.esm.js"></script></head><body></body></html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(()=>{"use strict";var e={d:(t,r)=>{for(var o in r)e.o(r,o)&&!e.o(t,o)&&Object.defineProperty(t,o,{enumerable:!0,get:r[o]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{mockforme:()=>I});const r=()=>"undefined"!=typeof process&&null!=process.versions?.node,o=e=>{try{return e?e.toLowerCase():e}catch(e){return console.log(e),null}},n=(e,t)=>{const r=e.split("/"),o=t.split("/");if(r.length!==o.length)return!1;for(let e=0;e<r.length;e++){const t=r[e];if(t!==o[e]&&":any"!==t)return!1}return!0};let s=[];function i(e){s=e}function a(){return s}function c(e,t="get"){for(const r of s)if(o(r.apiMethod)===o(t)&&(r.apiEndpoint===e||n(r.apiEndpoint,e))){const t={url:e,method:r.apiMethod,_ack:r._ack||null};return r._ri_&&(t._ri_=r._ri_),t}return null}const d="JAVASCRIPT",l="CHROME_EXTENSION",u="mfmver",h="mockforme",m="4.2.8",f="https://api.mockforme.com",p=`${f}/mockforme`,y=`${f}/gateway/3f4eae522b`;let _=null,g=null,w=null,b=[];function v({_o:e,mk:t,_mck:r,_rules:o}){_=e,g=t,w=r,b=o}function E(){return b}function x(){return`${p}/${_}/${g}`}function k(){return w}const R=e=>{try{return new URL(e,window.location.origin).toString()}catch{return e}};function S({url:e,method:t}){try{const t=E();if(!Array.isArray(t)||0===t.length)return null;const r=globalThis.location?.origin||"http://localhost";for(const o of t){const t=o.rule?.URL;if(!t)continue;const{condition:n}=t;if(!n)continue;let s="";switch(t.type){case"URL":{let t;try{t=new URL(e,r),s=t.pathname}catch{s=e}break}case"QUERY":{let t;try{t=new URL(e,r)}catch{t=null}t&&(s=t.searchParams.get(n.key)||"");break}case"BODY":case"HEADERS":s="";break;default:continue}let i=!1;switch(n.operator){case"contains":i=s.includes(n.value);break;case"equal":case"equals":i=s===n.value;break;case"regexp":try{let e=n.value;if(e.startsWith("/")&&e.lastIndexOf("/")>0){const t=e.lastIndexOf("/"),r=e.slice(1,t),o=e.slice(t+1);i=new RegExp(r,o).test(s)}else i=new RegExp(e).test(s)}catch{i=!1}}if(i){const e=n.activeAction;return{action:e,config:n.actions?.[e]||{}}}}return null}catch(e){return console.error("[mockforme] checkIfRulesToBeApplied error",e),null}}function O(e,t){!function(e,t){const r=window.fetch;window.fetch=function(o,n={}){const s="string"==typeof o?o:o.url;try{const i=new URL(s,window.location.origin),{pathname:a,search:d}=i;let f="get";n&&n.method?f=n.method:o instanceof Request&&o.method&&(f=o.method),f=f.toLowerCase();const p=S({url:s,method:f});if(t!==l&&p){if("delay"===p.action)return new Promise(((e,t)=>{setTimeout((()=>{e(r(o,n))}),1e3*p.config.value)}));if("delay_and_redirect"===p.action)return new Promise(((e,t)=>{setTimeout((()=>{e(r(p.config.redirectUrl,n))}),1e3*p.config.value)}));if("delay_and_timeout"===p.action){if(0===p.config.value){const e=new AbortController,t=r(o,{...n,signal:e.signal});return e.abort(),t.catch((()=>Promise.reject(new Error("Fetch aborted by rules"))))}return new Promise(((e,t)=>{setTimeout((()=>{t(new Error("Fetch timed out by rules"))}),1e3*p.config.value)}))}}const y=c(a,f);if(!y&&!p)return r(o,n);let _=s;p||(_=`${x()}${y.url}${d}`);let g={};if(!p){g={[h]:e,[u]:m,"x-mfm-adaptor":t};const r=k();r&&y._ack&&(g["x-mfm-key"]=`${r}-${y._ack}`),y?._ri_&&(g._ri_=y._ri_)}const w=o instanceof Request?o.headers:n.headers,b=new Headers(w||{});Object.entries(g).forEach((([e,t])=>{b.set(e,t)}));let v=n.body;if(!v&&o instanceof Request){const e=o.clone();"GET"!==e.method&&"HEAD"!==e.method&&(v=e.text())}let E={method:f,headers:b,credentials:"include",mode:"cors"};p&&(E.credentials=o instanceof Request&&o.credentials||n.credentials||"same-origin",E.mode=o instanceof Request&&o.mode||n.mode||"cors");const O=e=>(e&&(E.body=e),t===l?(({actualUrl:e,url:t,method:r,headers:o,body:n,credentials:s,mode:i,rule:a})=>{const c=`${Date.now()}-${Math.random()}`,d=R(t);return new Promise(((t,l)=>{window.addEventListener("message",(function e(r){if(r.source!==window)return;const o=r.data;if("INTERCEPTED_RESPONSE"===o?.type&&o?.requestId===c){if(window.removeEventListener("message",e),o?.response?.error)return l(new Error(o.response.message));const{status:r,headers:n,body:s}=o.response;t(new Response(s,{status:r,headers:n}))}})),window.postMessage({type:"REQUEST_INTERCEPTED",requestId:c,payload:{actualUrl:e,url:d,method:r,headers:o,body:n,credentials:s,mode:i,rule:a}},"*")}))})({actualUrl:s,url:_,method:f,headers:Object.fromEntries(b.entries()),body:e,credentials:E.credentials,mode:E.mode,rule:p}):fetch(_,E).then((e=>{const t=e.clone();return(t.headers.get("content-type")||"").includes("application/json")?t.json().then((r=>new Response(JSON.stringify(r),{status:e.status,headers:t.headers}))):t.text().then((r=>new Response(r,{status:e.status,headers:t.headers})))})).catch((e=>(console.warn("mockforme fetch interceptor error",e),r(o,n)))));return v instanceof Promise?v.then((e=>O(e))):O(v)}catch(e){return console.warn("mockforme fetch interceptor error",e),r(o,n)}}}(e,t),function(e,t){const r=window.XMLHttpRequest;window.XMLHttpRequest=class{constructor(){return this._xhr=new r,this._headers={},this._method=null,this._url=null,this._body=null,new Proxy(this,{get:(e,t)=>{if(t in e)return e[t];const r=e._xhr[t];return"function"==typeof r?r.bind(e._xhr):r},set:(e,t,r)=>t in e?(e[t]=r,!0):(e._xhr[t]=r,!0)})}open(e,t,r=!0,o=null,n=null){return this._method=e.toUpperCase(),this._url=new URL(t,window.location.href).toString(),this._xhr._mockOriginalUrl=this._url,this._xhr._mockMethod=this._method,this._xhr.open(e,t,r,o,n)}setRequestHeader(e,t){return this._headers[e]=t,this._xhr.setRequestHeader(e,t)}send(o){this._body=o;try{const n=new URL(this._url),{pathname:s,search:i}=n,a=S({url:this._url,method:this._method});if(t!==l&&a){if("delay"===a.action)return setTimeout((()=>this._xhr.send(o)),1e3*a.config.value);if("delay_and_redirect"===a.action)return setTimeout((()=>{this._xhr.open(this._method,a.config.redirectUrl,!0),this._xhr.send(o)}),1e3*a.config.value);if("delay_and_timeout"===a.action)return 0===a.config.value?(this._xhr.open(this._method,this._url,!0),this._xhr.send(o),this._xhr.abort(),void("function"==typeof this.onerror&&this.onerror(new Error("XHR aborted by rules")))):setTimeout((()=>{this._xhr.abort(),"function"==typeof this.onerror&&this.onerror(new Error("XHR timed out by rules"))}),1e3*a.config.value)}const d=c(s,this._method);if(!d&&!a)return this._xhr.send(o);let f=this._url;a||(f=`${x()}${d.url}${i}`);let p={};if(!a){p={[h]:e,[u]:m,"x-mfm-adaptor":t};const r=k();r&&d._ack&&(p["x-mfm-key"]=`${r}-${d._ack}`),d?._ri_&&(p._ri_=d._ri_)}const y={...this._headers,...p};if(t===l)(({actualUrl:e,url:t,method:r,headers:o,body:n,onSuccess:s,onError:i,rule:a})=>{const c=`${Date.now()}-${Math.random()}`,d=R(t);window.addEventListener("message",(function e(t){if(t.source!==window)return;const r=t.data;if("INTERCEPTED_RESPONSE"===r.type&&r.requestId===c){if(window.removeEventListener("message",e),r.response?.error)return i?.(r.response.message);const{body:t,status:o,headers:n}=r.response;s?.({body:t,status:o,headers:n})}})),window.postMessage({type:"REQUEST_INTERCEPTED",requestId:c,payload:{actualUrl:e,url:d,method:r,headers:o,body:n,credentials:"same-origin",mode:"cors",rule:a}},"*")})({actualUrl:this._url,url:f,method:this._method,headers:y,body:this._body,rule:a,onSuccess:({body:e,status:t})=>{Object.defineProperty(this,"responseText",{value:e}),Object.defineProperty(this,"status",{value:t}),Object.defineProperty(this,"readyState",{value:4}),this.onreadystatechange?.(),this.onload?.(),this._xhr.dispatchEvent(new Event("readystatechange")),this._xhr.dispatchEvent(new Event("load"))},onError:e=>{Object.defineProperty(this,"readyState",{value:4}),this.onerror?.(new Error(e.message||"XHR mock error")),this._xhr.dispatchEvent(new Event("readystatechange")),this._xhr.dispatchEvent(new Event("error"))}});else{const e=new r;e.open(this._method,f,!0);for(const t in y)e.setRequestHeader(t,y[t]);e.withCredentials=this.withCredentials,e.onload=()=>{Object.defineProperty(this,"responseText",{value:e.responseText}),Object.defineProperty(this,"status",{value:e.status}),Object.defineProperty(this,"readyState",{value:4}),this.onreadystatechange?.(),this.onload?.(),this._xhr.dispatchEvent(new Event("readystatechange")),this._xhr.dispatchEvent(new Event("load"))},e.onerror=()=>{Object.defineProperty(this,"readyState",{value:4}),this.onerror?.(),this._xhr.dispatchEvent(new Event("readystatechange")),this._xhr.dispatchEvent(new Event("error"))},e.send(this._body)}}catch(e){console.error("[mockforme][XHR] interception error",e)}}}}(e,t)}const T=function(e,t,o){const n=r();var s;function i(){if(4==s.readyState)if(s.status.toString().match(/^20[0-9]$/)){var e=function(){var e=s.getResponseHeader("Content-Type"),t=s.responseText;if(e){var r=e.split(";");try{return"application/json"===r[0]?JSON.parse(t):t}catch(e){throw"Unable to convert response header"}}}();t.call(this,e,s)}else o.call(this,s.responseText,s)}function a(e,t){var r=[];for(var o in e)if(e.hasOwnProperty(o)){var n=t?t+"["+o+"]":o,s=e[o];r.push("object"==typeof s?a(s,n):encodeURIComponent(n)+"="+encodeURIComponent(s))}return r.join("&")}return n||(window.XMLHttpRequest?s=new XMLHttpRequest:window.ActiveXObject&&(s=new ActiveXObject("Microsoft.XMLHTTP"))),{request:function(){if(!n){if(window.XMLHttpRequest)s.onload=i;else{if(!window.ActiveXObject)throw"unable to process ajax";s.onreadystatechange=i}var t=a(e.params);if("get"==e.method.toLowerCase()&&"object"==typeof e.params){if(-1==e.url.indexOf("?"))e.url+="?";else{var r=e.url.split("?");r[1]&&r[1].split("=")[1]&&(e.url+="&")}e.url+=t}e.hasOwnProperty("async")||(e.async=!0),s.open(e.method,e.url,e.async),e.headers&&function(e){for(let t in e)s.setRequestHeader(t,e[t])}(e.headers),s.send(t)}}}};function P({di:e,iv:t},r){var o;const n=function(e,t){const r=t.length;return e.split("").map(((e,o)=>String.fromCharCode(e.charCodeAt(0)^t.charCodeAt(o%r)))).join("")}((o=e,"undefined"!=typeof Buffer?Buffer.from(o,"base64").toString("utf8"):decodeURIComponent(escape(atob(o)))),r+t);return JSON.parse(n)}const j=(e,t=null,o=d)=>{if(r())return;if(o===d)try{(()=>{const e=()=>{if(!window.mockforme)return;const e=JSON.parse(localStorage.getItem("mockforme-dot-pos")||"{}"),t=document.createElement("div");t.id="mockforme-dot",Object.assign(t.style,{position:"fixed",bottom:(e.bottom??20)+"px",right:(e.right??20)+"px",width:"42px",height:"42px",borderRadius:"50%",overflow:"hidden",cursor:"grab",zIndex:999999,boxShadow:"0 0 10px rgba(0,0,0,0.25)",backgroundColor:"#fff",display:"flex",alignItems:"center",justifyContent:"center"});const r=document.createElement("img");r.src="https://dashboard.mockforme.com/public/assets/images/icon.png",r.style.objectFit="cover",t.appendChild(r),document.body.appendChild(t);const o=document.createElement("div");o.id="mockforme-widget",o.innerText="MockForMe Enabled",Object.assign(o.style,{position:"fixed",padding:"8px 12px",background:"#2563eb",color:"#fff",fontSize:"13px",fontFamily:"Inter, sans-serif",borderRadius:"8px",bottom:(e.bottom??20)+50+"px",right:(e.right??20)+"px",boxShadow:"0 4px 10px rgba(0,0,0,0.2)",zIndex:999999,display:"none",whiteSpace:"nowrap"}),document.body.appendChild(o),t.addEventListener("click",(e=>{e.stopPropagation(),o.style.display="none"===o.style.display?"block":"none"})),document.addEventListener("click",(()=>{o.style.display="none"}));let n=!1,s=0,i=0;t.addEventListener("mousedown",(e=>{n=!0,t.style.cursor="grabbing";const r=t.getBoundingClientRect();s=e.clientX-r.left,i=e.clientY-r.top,e.preventDefault()})),document.addEventListener("mousemove",(e=>{if(!n)return;const r=e.clientX-s,a=e.clientY-i,c=window.innerHeight-(a+t.offsetHeight),d=window.innerWidth-(r+t.offsetWidth);t.style.bottom=c+"px",t.style.right=d+"px",o.style.bottom=c+50+"px",o.style.right=d+"px"})),document.addEventListener("mouseup",(()=>{if(!n)return;n=!1,t.style.cursor="grab";const e=parseInt(t.style.bottom),r=parseInt(t.style.right);localStorage.setItem("mockforme-dot-pos",JSON.stringify({bottom:e,right:r}))}))};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",e):e()})()}catch(e){console.log("Error in showing mockforme widget")}t||={mappings:[],_o:null,mk:null,_mck:null,_rules:[]};const{mappings:n=[],_o:s,mk:l,_mck:f,_rules:p=[]}=t;return i(n),v({_o:s,mk:l,_mck:f,_rules:p}),{run:(t,r=()=>{})=>{O(e,o),s&&l?t(a(),{_o:s,mk:l,_mck:f,_rules:p}):function(e,r,o,n){T({method:"get",url:y,async:!1,headers:{[h]:e,[u]:m,"x-mfm-adaptor":r}},(e=>{if(e)try{const{di:n,iv:s,_o:a,_mck:c,mk:d,r:l}=e,u=P({di:n,iv:s},a);v({_o:a,mk:d,_mck:c,_rules:l}),u&&(i(u),r=u,o={_o:a,mk:d,_mck:c,_rules:l},t?.(r,o))}catch(e){return void n(new Error("Unable to fetch mocked apis"))}var r,o}),(e=>{console.log("Error in loading mocked apis"),n(e)})).request()}(e,o,0,r)},checkIfApiToBeMocked:c,getMappings:a,doFetchMappings:(t,r)=>{!function(e,t,r,o){fetch(y,{method:"GET",headers:{[h]:e,[u]:m,"x-mfm-adaptor":t}}).then((e=>{if(!e.ok)throw e;return e.json()})).then((e=>{if(e){const{di:t,iv:o,_o:n,_mck:s,mk:a,r:c}=e,d=P({di:t,iv:o},n);v({_o:n,mk:a,_mck:s,_rules:c}),d&&(i(d),r(d,{_o:n,mk:a,_mck:s,_rules:c}))}})).catch((e=>{console.error("Error in loading mocked APIs:",e),o(e)}))}(e,o,((e,r)=>{t?.(e,r)}),r)}}},C=r();C||(globalThis.mockforme=j);let L=j;C&&(L=e=>({run:()=>{}}));const I=L;module.exports=t})();
|
|
1
|
+
(()=>{"use strict";var e={d:(t,n)=>{for(var s in n)e.o(n,s)&&!e.o(t,s)&&Object.defineProperty(t,s,{enumerable:!0,get:n[s]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{mockforme:()=>U});const n=()=>"undefined"!=typeof process&&null!=process.versions?.node,s=e=>{try{return e?e.toLowerCase():e}catch(e){return console.log(e),null}},o=(e,t)=>{const n=e.split("/"),s=t.split("/");if(n.length!==s.length)return!1;for(let e=0;e<n.length;e++){const t=n[e];if(t!==s[e]&&":any"!==t)return!1}return!0};let r=[];function i(e){r=e}function a(){return r}function d(e,t="get"){const n=e=>e.startsWith("/")?e:`/${e}`,i=n(e);for(const a of r)if(s(a.apiMethod)===s(t)){const s=n(a.apiEndpoint);if(s===i||o(s,i)){console.log(`[MockForMe] Match Found: ${t} ${e} -> ${a.apiEndpoint}`);const n={url:e,method:a.apiMethod,_ack:a._ack||null};return a._ri_&&(n._ri_=a._ri_),n}}return null}const c="JAVASCRIPT",l="CHROME_EXTENSION",m="mfmver",u="mockforme",h="4.2.8",p="https://api.mockforme.com",f=`${p}/mockforme`,g=`${p}/gateway/3f4eae522b`;let b=null,x=null,y=null,k=[];function v({_o:e,mk:t,_mck:n,_rules:s}){b=e,x=t,y=n,k=s}function _(){return k}function w(){return`${f}/${b}/${x}`}function q(){return y}const E=e=>{try{return new URL(e,window.location.origin).toString()}catch{return e}};function R({url:e,method:t}){try{const t=_();if(!Array.isArray(t)||0===t.length)return null;const n=globalThis.location?.origin||"http://localhost";for(const s of t){const t=s.rule?.URL;if(!t)continue;const{condition:o}=t;if(!o)continue;let r="";switch(t.type){case"URL":{let t;try{t=new URL(e,n),r=t.pathname}catch{r=e}break}case"QUERY":{let t;try{t=new URL(e,n)}catch{t=null}t&&(r=t.searchParams.get(o.key)||"");break}case"BODY":case"HEADERS":r="";break;default:continue}let i=!1;switch(o.operator){case"contains":i=r.includes(o.value);break;case"equal":case"equals":i=r===o.value;break;case"regexp":try{let e=o.value;if(e.startsWith("/")&&e.lastIndexOf("/")>0){const t=e.lastIndexOf("/"),n=e.slice(1,t),s=e.slice(t+1);i=new RegExp(n,s).test(r)}else i=new RegExp(e).test(r)}catch{i=!1}}if(i){const e=o.activeAction;return{action:e,config:o.actions?.[e]||{}}}}return null}catch(e){return console.error("[mockforme] checkIfRulesToBeApplied error",e),null}}const T=function(e,t,s){const o=n();var r;function i(){if(4==r.readyState)if(r.status.toString().match(/^20[0-9]$/)){var e=function(){var e=r.getResponseHeader("Content-Type"),t=r.responseText;if(e){var n=e.split(";");try{return"application/json"===n[0]?JSON.parse(t):t}catch(e){throw"Unable to convert response header"}}}();t.call(this,e,r)}else s.call(this,r.responseText,r)}function a(e,t){var n=[];for(var s in e)if(e.hasOwnProperty(s)){var o=t?t+"["+s+"]":s,r=e[s];n.push("object"==typeof r?a(r,o):encodeURIComponent(o)+"="+encodeURIComponent(r))}return n.join("&")}return o||(window.XMLHttpRequest?r=new XMLHttpRequest:window.ActiveXObject&&(r=new ActiveXObject("Microsoft.XMLHTTP"))),{request:function(){if(!o){if(window.XMLHttpRequest)r.onload=i;else{if(!window.ActiveXObject)throw"unable to process ajax";r.onreadystatechange=i}var t=a(e.params);if("get"==e.method.toLowerCase()&&"object"==typeof e.params){if(-1==e.url.indexOf("?"))e.url+="?";else{var n=e.url.split("?");n[1]&&n[1].split("=")[1]&&(e.url+="&")}e.url+=t}e.hasOwnProperty("async")||(e.async=!0),r.open(e.method,e.url,e.async),e.headers&&function(e){for(let t in e)r.setRequestHeader(t,e[t])}(e.headers),r.send(t)}}}};function S({di:e,iv:t},n){var s;const o=function(e,t){const n=t.length;return e.split("").map(((e,s)=>String.fromCharCode(e.charCodeAt(0)^t.charCodeAt(s%n)))).join("")}((s=e,"undefined"!=typeof Buffer?Buffer.from(s,"base64").toString("utf8"):decodeURIComponent(escape(atob(s)))),n+t);return JSON.parse(o)}function M(e,t,n,s){fetch(g,{method:"GET",headers:{[u]:e,[m]:h,"x-mfm-adaptor":t}}).then((e=>{if(!e.ok)throw e;return e.json()})).then((e=>{if(e){const{di:t,iv:s,_o:o,_mck:r,mk:a,r:d}=e,c=S({di:t,iv:s},o);v({_o:o,mk:a,_mck:r,_rules:d}),c&&(i(c),n(c,{_o:o,mk:a,_mck:r,_rules:d}))}})).catch((e=>{console.error("Error in loading mocked APIs:",e),s(e)}))}const I=new class{constructor(e={}){n()||(this.token=e.token||("undefined"!=typeof localStorage?localStorage.getItem("mockforme-token"):null),this.isAuthenticated=!!this.token,this.onAuthSuccess=e.onAuthSuccess||(()=>{}),this.mappings=e.mappings||[],this.rules=e.rules||[],this.mockedRequests=[],this.otherRequests=[],this.state={isOpen:!1,activeTab:"mappings",selectedRequest:null,activeRequestTab:"response",lastError:null,searchQuery:""},"undefined"!=typeof document&&("loading"===document.readyState?document.addEventListener("DOMContentLoaded",(()=>this.init())):this.init()))}init(){document.getElementById("mockforme-root")||(this.createStyles(),this.render())}createStyles(){if(document.getElementById("mockforme-styles"))return;const e=document.createElement("style");e.id="mockforme-styles",e.innerHTML="\n #mockforme-root {\n font-family: 'Inter', system-ui, -apple-system, sans-serif;\n z-index: 999999;\n position: fixed;\n }\n .mfm-bubble {\n position: fixed;\n bottom: 20px;\n right: 20px;\n height: 42px;\n padding: 4px 8px;\n border-radius: 24px;\n box-shadow: 0 4px 12px rgba(0,0,0,0.15);\n cursor: pointer;\n z-index: 999999;\n background: white;\n display: flex;\n align-items: center;\n gap: 8px;\n transition: transform 0.2s;\n border: 1px solid #eee;\n }\n .mfm-bubble:hover { transform: scale(1.05); }\n .mfm-bubble img { width: 32px; height: 32px; border-radius: 50%; object-fit: cover; }\n \n .mfm-refresh-icon {\n width: 32px;\n height: 32px;\n background: #f3f4f6;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #2563eb;\n font-size: 18px;\n transition: background 0.2s;\n }\n .mfm-refresh-icon:hover { background: #e5e7eb; }\n .mfm-refresh-icon.loading { animation: mfm-spin 1s linear infinite; }\n @keyframes mfm-spin { 100% { transform: rotate(360deg); } }\n\n .mfm-bottomsheet {\n position: fixed;\n bottom: 0;\n left: 0;\n right: 0;\n background: white;\n border-top-left-radius: 16px;\n border-top-right-radius: 16px;\n box-shadow: 0 -4px 20px rgba(0,0,0,0.15);\n padding: 20px;\n z-index: 999999;\n height: 90vh;\n max-width: 500px;\n margin: 0 auto;\n display: flex;\n flex-direction: column;\n transition: transform 0.3s ease-out;\n transform: translateY(100%);\n visibility: hidden;\n overflow-y: auto;\n }\n .mfm-bottomsheet.open { transform: translateY(0); visibility: visible; }\n \n .mfm-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 20px;\n padding-bottom: 10px;\n border-bottom: 1px solid #eee;\n }\n .mfm-title-group { display: flex; align-items: center; gap: 10px; }\n .mfm-title { font-size: 18px; font-weight: 600; color: #111; }\n .mfm-delete-token-btn { \n background: #fee2e2; \n color: #dc2626; \n font-size: 13px; \n padding: 4px 12px; \n border-radius: 20px; \n cursor: pointer; \n display: flex;\n align-items: center;\n gap: 6px;\n border: none;\n font-weight: 500;\n transition: background 0.2s;\n }\n .mfm-delete-token-btn:hover { background: #fecaca; }\n .mfm-header-actions { display: flex; align-items: center; gap: 10px; }\n .mfm-close { background: none; border: none; font-size: 24px; cursor: pointer; color: #666; }\n /* Login Form */\n .mfm-logo-container { text-align: center; padding: 30px 0; width: 100%; display: flex; justify-content: center; }\n .mfm-logo { width: 150px; height: auto; }\n .mfm-link { color: #2563eb; text-decoration: none; font-size: 14px; margin-top: 5px; cursor: pointer; display: inline-block; }\n .mfm-link:hover { text-decoration: underline; }\n .mfm-form { display: flex; flex-direction: column; gap: 10px; }\n .mfm-input {\n padding: 12px;\n border: 1px solid #ddd;\n border-radius: 8px;\n font-size: 16px;\n outline: none;\n transition: border-color 0.2s;\n }\n .mfm-input:focus { border-color: #2563eb; }\n .mfm-error { color: #dc2626; font-size: 13px; margin-top: -5px; }\n .mfm-btn {\n padding: 12px;\n background: #2563eb;\n color: white;\n border: none;\n border-radius: 8px;\n font-size: 16px;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.2s;\n }\n .mfm-btn:hover { background: #1d4ed8; }\n .mfm-btn:disabled { background: #9ca3af; cursor: not-allowed; }\n\n .mfm-tabs { display: flex; border-bottom: 1px solid #eee; margin-bottom: 15px; }\n .mfm-tab {\n padding: 10px 20px;\n cursor: pointer;\n color: #666;\n border-bottom: 2px solid transparent;\n font-weight: 500;\n }\n .mfm-tab.active { color: #2563eb; border-bottom-color: #2563eb; }\n \n .mfm-list {\n flex: 1;\n overflow-y: auto;\n min-height: 200px;\n max-height: 60vh;\n }\n .mfm-list-item {\n padding: 10px;\n border-bottom: 1px solid #f3f4f6;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: space-between;\n font-size: 14px;\n min-height: 52px;\n box-sizing: border-box;\n }\n .mfm-list-item:hover { background: #f9fafb; }\n .mfm-method { \n font-weight: bold; \n padding: 4px 8px; \n border-radius: 4px; \n margin-right: 10px;\n font-size: 12px;\n }\n .GET { background: #dbfcfe; color: #006064; }\n .POST { background: #dcfce7; color: #14532d; }\n .PUT { background: #fef9c3; color: #713f12; }\n .DELETE { background: #fee2e2; color: #7f1d1d; }\n .PATCH { background: #f3e8ff; color: #581c87; }\n .RULE { background: #f3f4f6; color: #374151; }\n\n /* Search & Actions */\n .mfm-actions-bar { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }\n .mfm-search-input { flex: 1; padding: 8px 12px; border: 1px solid #ddd; border-radius: 6px; font-size: 14px; outline: none; }\n .mfm-search-input:focus { border-color: #2563eb; }\n .mfm-icon-btn { background: none; border: none; font-size: 18px; cursor: pointer; color: #666; display: flex; align-items: center; justify-content: center; padding: 4px; border-radius: 4px; }\n .mfm-icon-btn:hover { background: #f3f4f6; color: #333; }\n .mfm-icon-btn.refresh { color: #2563eb; padding: 0; height: 30px; width:30px; border-radius: 50%; }\n .mfm-icon-btn.refresh.loading { animation: mfm-spin 1s linear infinite; }\n .mfm-icon-btn.delete { color: #dc2626; }\n\n .mfm-url { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n .mfm-status { font-weight: bold; margin-left: 10px; }\n .status-2xx { color: #16a34a; }\n .status-4xx { color: #dc2626; }\n .status-5xx { color: #ea580c; }\n .status-aborted, .status-timeout, .status-error { color: #dc2626; font-size: 11px; font-weight: 500; }\n\n .mfm-rule-tag {\n font-size: 9px;\n padding: 2px 4px;\n border-radius: 4px;\n background: #fef3c7;\n color: #92400e;\n border: 1px solid #fde68a;\n margin-right: 6px;\n text-transform: uppercase;\n font-weight: bold;\n }\n\n .mfm-detail-view { display: flex; flex-direction: column; height: 100%; }\n .mfm-detail-actions { margin-bottom: 10px; }\n .mfm-back-btn { background: none; border: none; color: #2563eb; cursor: pointer; font-size: 14px; display: flex; align-items: center; gap: 4px; padding: 0;}\n \n .mfm-code-block {\n background: #f8fafc;\n padding: 10px;\n border-radius: 8px;\n overflow-x: auto;\n font-family: monospace;\n font-size: 12px;\n white-space: pre-wrap;\n word-break: break-all;\n max-height: 300px;\n border: 1px solid #e2e8f0;\n }\n .section-title { font-size: 14px; font-weight: 600; margin: 10px 0 5px; color: #333; }\n\n /* Snackbar */\n .mfm-snackbar {\n position: fixed;\n bottom: 80px;\n left: 50%;\n transform: translateX(-50%) translateY(20px);\n background: #333;\n color: white;\n padding: 10px 20px;\n border-radius: 8px;\n font-size: 14px;\n z-index: 1000000;\n opacity: 0;\n transition: opacity 0.3s, transform 0.3s;\n pointer-events: none;\n }\n .mfm-snackbar.show { opacity: 1; transform: translateX(-50%) translateY(0); }\n\n /* Confirm Dialog */\n .mfm-modal-overlay {\n position: fixed;\n top: 0; left: 0; right: 0; bottom: 0;\n background: rgba(0,0,0,0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000001;\n opacity: 0;\n transition: opacity 0.2s;\n pointer-events: none;\n }\n .mfm-modal-overlay.show { opacity: 1; pointer-events: auto; }\n .mfm-modal {\n background: white;\n padding: 20px;\n border-radius: 12px;\n width: 300px;\n box-shadow: 0 10px 25px rgba(0,0,0,0.2);\n transform: scale(0.9);\n transition: transform 0.2s;\n }\n .mfm-modal-overlay.show .mfm-modal { transform: scale(1); }\n .mfm-modal-title { font-size: 16px; font-weight: 600; margin-bottom: 10px; }\n .mfm-modal-body { font-size: 14px; color: #666; margin-bottom: 20px; }\n .mfm-modal-actions { display: flex; justify-content: flex-end; gap: 10px; }\n .mfm-btn-alt { background: #f3f4f6; color: #333; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; font-size: 14px; }\n .mfm-btn-danger { background: #dc2626; color: white; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; font-size: 14px; }\n \n .mfm-spinner {\n width: 12px;\n height: 12px;\n border: 2px solid #f3f3f3;\n border-top: 2px solid #2563eb;\n border-radius: 50%;\n animation: mfm-spin 1s linear infinite;\n margin-right: 8px;\n display: inline-block;\n }\n .status-aborted { color: #dc2626; font-weight: bold; }\n .mfm-duration { color: #666; font-size: 11px; margin-left: 8px; font-weight: normal; }\n ",document.head.appendChild(e)}render(){const e=document.createElement("div");e.id="mockforme-root",document.body.appendChild(e),this.root=e,this.bubble=this.renderBubble(),this.root.appendChild(this.bubble),this.sheet=document.createElement("div"),this.sheet.className="mfm-bottomsheet",this.root.appendChild(this.sheet),this.snackbar=document.createElement("div"),this.snackbar.className="mfm-snackbar",this.root.appendChild(this.snackbar),this.modalOverlay=document.createElement("div"),this.modalOverlay.className="mfm-modal-overlay",this.root.appendChild(this.modalOverlay),this.updateUI()}updateUI(){this.state.isOpen?(this.renderBottomSheetContent(),this.sheet.classList.add("open")):this.sheet.classList.remove("open")}renderBubble(){const e=document.createElement("div");e.className="mfm-bubble";const t="undefined"!=typeof localStorage?JSON.parse(localStorage.getItem("mockforme-dot-pos")||"{}"):{};return t.bottom&&(e.style.bottom=t.bottom+"px"),t.right&&(e.style.right=t.right+"px"),e.innerHTML='\n <div class="mfm-refresh-icon" title="Reload Mappings">↻</div>\n <img src="https://ik.imagekit.io/mfm/static-collection/mfm-48x48.png" alt="MFM" />\n ',this.addDragLogic(e),e.querySelector("img").onclick=e=>{this.isDragging||this.toggleSheet()},e.querySelector(".mfm-refresh-icon").onclick=e=>{e.stopPropagation(),this.refreshMappings()},e}addDragLogic(e){let t,n,s,o,r=!1;const i=i=>{const a=t-i.clientX,d=n-i.clientY;(Math.abs(a)>3||Math.abs(d)>3)&&(r=!0,this.isDragging=!0),r&&(e.style.right=s+a+"px",e.style.bottom=o+d+"px")},a=()=>{document.removeEventListener("mousemove",i),document.removeEventListener("mouseup",a),r&&"undefined"!=typeof localStorage&&localStorage.setItem("mockforme-dot-pos",JSON.stringify({bottom:parseInt(e.style.bottom),right:parseInt(e.style.right)}))};e.addEventListener("mousedown",(d=>{r=!1,this.isDragging=!1,t=d.clientX,n=d.clientY;const c=e.getBoundingClientRect();s=window.innerWidth-c.right,o=window.innerHeight-c.bottom,document.addEventListener("mousemove",i),document.addEventListener("mouseup",a)}))}toggleSheet(){this.state.isOpen=!this.state.isOpen,this.updateUI()}showSnackbar(e){this.snackbar.textContent=e,this.snackbar.classList.add("show"),setTimeout((()=>this.snackbar.classList.remove("show")),3e3)}showConfirm(e,t,n){this.modalOverlay.innerHTML=`\n <div class="mfm-modal">\n <div class="mfm-modal-title">${e}</div>\n <div class="mfm-modal-body">${t}</div>\n <div class="mfm-modal-actions">\n <button class="mfm-btn-alt" id="mfm-confirm-cancel">Cancel</button>\n <button class="mfm-btn-danger" id="mfm-confirm-yes">Delete</button>\n </div>\n </div>\n `,this.modalOverlay.classList.add("show"),this.modalOverlay.querySelector("#mfm-confirm-cancel").onclick=()=>{this.modalOverlay.classList.remove("show")},this.modalOverlay.querySelector("#mfm-confirm-yes").onclick=()=>{this.modalOverlay.classList.remove("show"),n()}}refreshMappings(){if(!this.token)return void this.toggleSheet();const e=document.querySelectorAll(".mfm-refresh-icon, #mfm-refresh-mappings-btn");e.forEach((e=>e.classList.add("loading"))),M(this.token,"JAVASCRIPT",((t,n)=>{console.log("[MockForMe] Mappings reloaded",{mappings:t?.length,rules:n?._rules?.length}),e.forEach((e=>e.classList.remove("loading"))),this.mappings=t||[],this.rules=n?._rules||[],this.onAuthSuccess(this.token,this.mappings,n),this.updateUI(),this.showSnackbar("Mappings reloaded!")}),(t=>{e.forEach((e=>e.classList.remove("loading"))),this.showSnackbar("Failed to reload mappings")}))}renderBottomSheetContent(){this.sheet.innerHTML="",this.isAuthenticated?this.state.selectedRequest?this.sheet.appendChild(this.renderRequestDetail(this.state.selectedRequest)):this.sheet.appendChild(this.renderDashboard()):this.sheet.appendChild(this.renderTokenForm())}renderTokenForm(){const e=document.createElement("div");e.innerHTML=`\n <div class="mfm-header">\n <span class="mfm-title">Save Token</span>\n <button class="mfm-close">×</button>\n </div>\n <div class="mfm-logo-container">\n <img src="https://dashboard.mockforme.com/public/assets/images/logo.png" class="mfm-logo" alt="MockForMe Logo" />\n </div>\n <div class="mfm-form">\n <input type="text" class="mfm-input" placeholder="Enter MockForMe Access Token" id="mfm-token-input">\n <div class="mfm-error" id="mfm-error-msg" style="display: ${this.state.lastError?"block":"none"}">${this.state.lastError||""}</div>\n <a href="https://dashboard.mockforme.com/user/token" target="_blank" class="mfm-link">Get Access Token?</a>\n <button class="mfm-btn" id="mfm-save-token-btn">Save</button>\n </div>\n `,e.querySelector(".mfm-close").onclick=()=>{this.state.lastError=null,this.toggleSheet()};const t=e.querySelector("#mfm-save-token-btn"),n=e.querySelector("#mfm-token-input");return t.onclick=()=>{const s=n.value.trim();s&&(t.textContent="Validating...",t.disabled=!0,this.state.lastError=null,e.querySelector("#mfm-error-msg").style.display="none",M(s,c,((e,t)=>{"undefined"!=typeof localStorage&&localStorage.setItem("mockforme-token",s),this.token=s,this.isAuthenticated=!0,this.mappings=e,this.rules=t?._rules||[],this.onAuthSuccess(s,e,t),this.updateUI()}),(e=>{t.textContent="Save",t.disabled=!1;let n="Invalid Token or Network Error";e&&"function"==typeof e.json?e.json().then((e=>{this.state.lastError=e.message||n,this.updateUI()})).catch((()=>{this.state.lastError=n,this.updateUI()})):(this.state.lastError=e.message||n,this.updateUI())})))},e}deleteToken(){"undefined"!=typeof localStorage&&localStorage.removeItem("mockforme-token"),this.token=null,this.isAuthenticated=!1,this.mappings=[],this.rules=[],this.state.lastError=null,this.updateUI()}renderDashboard(){const e=document.createElement("div");e.innerHTML='\n <div class="mfm-header">\n <span class="mfm-title">MockForMe</span>\n <div class="mfm-header-actions">\n <button class="mfm-delete-token-btn" id="mfm-delete-token" title="Delete Token">\n <span>🗑</span>\n <span>Token</span>\n </button>\n <button class="mfm-close">×</button>\n </div>\n </div>\n ';const t=document.createElement("div");t.className="mfm-tabs",["mappings","mocked","other"].forEach((e=>{const n=document.createElement("div");n.className="mfm-tab "+(this.state.activeTab===e?"active":""),n.textContent="mappings"===e?"Api Mappings":"mocked"===e?"Mocked Apis":"Other Apis",n.onclick=()=>{this.state.activeTab=e,this.updateUI()},t.appendChild(n)})),e.querySelector(".mfm-header").after(t);const n=document.createElement("div");n.className="mfm-actions-bar","mappings"===this.state.activeTab?(n.innerHTML=`\n <div style="flex: 1; font-size: 13px; color: #666;">Total: ${this.mappings.length+this.rules.length}</div>\n <div class="mfm-icon-btn refresh" id="mfm-refresh-mappings-btn" title="Refresh Mappings">↻</div>\n `,n.querySelector("#mfm-refresh-mappings-btn").onclick=()=>this.refreshMappings()):(n.innerHTML=`\n <input type="text" class="mfm-search-input" placeholder="Search requests..." id="mfm-search-input" value="${this.state.searchQuery}">\n <button class="mfm-icon-btn delete" id="mfm-clear-requests-btn" title="Clear List">🚫</button>\n `,n.querySelector("#mfm-search-input").oninput=e=>{this.state.searchQuery=e.target.value,this.updateRequestList(s)},n.querySelector("#mfm-clear-requests-btn").onclick=()=>{"mocked"===this.state.activeTab?this.mockedRequests=[]:this.otherRequests=[],this.updateUI()}),t.after(n);const s=document.createElement("div");return s.className="mfm-list",this.updateRequestList(s),e.appendChild(s),e.querySelector(".mfm-close").onclick=()=>this.toggleSheet(),e.querySelector("#mfm-delete-token").onclick=()=>{this.showConfirm("Delete Token","Are you sure you want to Delete Token? This will clear your saved token.",(()=>{this.deleteToken()}))},e}updateRequestList(e){if(e.innerHTML="","mappings"===this.state.activeTab){const t=[...this.mappings.map((e=>({...e,type:"mapping"}))),...this.rules.map((e=>({...e,type:"rule"})))];0===t.length?e.innerHTML='<div style="padding: 20px; text-align: center; color: #999;">No items found</div>':t.forEach((t=>{const n=document.createElement("div");if(n.className="mfm-list-item","mapping"===t.type){const e=(t.apiMethod||"GET").toUpperCase();n.innerHTML=`<div style="display:flex; align-items:center; width:100%"><span class="mfm-method ${e}">${e}</span><span class="mfm-url">${t.apiEndpoint}</span></div>`}else{const e=t.ruleName||"Network Rule",s=(t.rule?.URL?.condition||{}).value||e;n.innerHTML=`<div style="display:flex; align-items:center; width:100%"><span class="mfm-method RULE">RULE</span><span class="mfm-url">${s}</span></div>`}e.appendChild(n)}))}else{let t="mocked"===this.state.activeTab?this.mockedRequests:this.otherRequests;if(this.state.searchQuery){const e=this.state.searchQuery.toLowerCase();t=t.filter((t=>(t.url||"").toLowerCase().includes(e)||(t.method||"").toLowerCase().includes(e)||String(t.status).includes(e)))}0===t.length?e.innerHTML='<div style="padding: 20px; text-align: center; color: #999;">No items found</div>':t.forEach((t=>{const n=document.createElement("div");n.className="mfm-list-item";const s=(t.method||"").toUpperCase(),o=`<span class="mfm-duration" style="color:#2563eb; font-size:11px; font-weight:500; display:block; height:14px; line-height:14px;">${void 0!==t.duration?t.duration+"ms":""}</span>`,r=(()=>{if(!t.rule)return"";let e="delay_and_timeout"===t.rule.action?"Delay and Timout":t.rule.action.split("_")[0];const n=t.rule.config?.value;return void 0!==n&&(t.rule.action.includes("delay")||t.rule.action.includes("timeout"))&&(e+=` (${n}s)`),`<span class="mfm-rule-tag" title="${t.rule.action}">${e}</span>`})();let i=t.status,a="mfm-status";t.pending?i='<span class="mfm-spinner"></span>':t.aborted?(i="Aborted",a+=" status-aborted"):t.timeout?(i="Timeout",a+=" status-timeout"):t.error?(i="Error/CORS",a+=" status-error"):(i=t.status,a+=t.status>=200&&t.status<300?" status-2xx":" status-4xx"),n.innerHTML=`\n <div style="display:flex; align-items:center; width:100%; gap:8px;">\n <span class="mfm-method ${s}">${s}</span>\n <div style="flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; justify-content:center;">\n <span class="mfm-url">${r}${t.url}</span>\n ${o}\n </div>\n <span class="${a}">${i}</span>\n </div>\n `,n.onclick=()=>{this.state.selectedRequest=t,this.updateUI()},e.appendChild(n)}))}}renderRequestDetail(e){const t=document.createElement("div");t.className="mfm-detail-view",t.innerHTML='\n <div class="mfm-header">\n <span class="mfm-title">Details</span>\n <button class="mfm-close">×</button>\n </div>\n <div class="mfm-detail-actions">\n <button class="mfm-back-btn">← Back</button>\n </div>\n ';const n=document.createElement("div");n.className="mfm-tabs",["request","response"].forEach((e=>{const t=document.createElement("div");t.className="mfm-tab "+(this.state.activeRequestTab===e?"active":""),t.textContent=e.charAt(0).toUpperCase()+e.slice(1),t.onclick=()=>{this.state.activeRequestTab=e,this.updateUI()},n.appendChild(t)}));const s=document.createElement("div");s.style.overflowY="auto",s.style.flex="1";const o=(e.method||"").toUpperCase();return s.innerHTML="request"===this.state.activeRequestTab?`\n <div class="section-title">URL</div><div class="mfm-code-block">${o} ${e.url}</div>\n ${e.rule?`<div class="section-title">Matched Rule</div><div class="mfm-code-block">${e.rule.action} (value: ${e.rule.config?.value})</div>`:""}\n <div class="section-title">Headers</div><div class="mfm-code-block">${JSON.stringify(e.requestHeaders||{},null,2)}</div>\n <div class="section-title">Query Params</div><div class="mfm-code-block">${JSON.stringify(e.queryParams||{},null,2)}</div>\n <div class="section-title">Payload</div><div class="mfm-code-block">${this.formatBody(e.requestBody)}</div>\n `:`\n <div class="section-title">Status</div><div class="mfm-code-block">${e.status}</div>\n <div class="section-title">Response Headers</div><div class="mfm-code-block">${JSON.stringify(e.responseHeaders||{},null,2)}</div>\n <div class="section-title">Response Body</div><div class="mfm-code-block">${this.formatBody(e.responseBody)}</div>\n `,t.appendChild(n),t.appendChild(s),t.querySelector(".mfm-close").onclick=()=>this.toggleSheet(),t.querySelector(".mfm-back-btn").onclick=()=>{this.state.selectedRequest=null,this.updateUI()},t}formatBody(e){if(!e)return"";if("object"==typeof e)return JSON.stringify(e,null,2);try{return JSON.stringify(JSON.parse(e),null,2)}catch{return e}}addRequest(e,t){const n=String(t.method||"").toUpperCase().trim(),s=String(t.url||"");console.log(`[MockForMe] addRequest type=${e} method=${n} url=${s} requestId=${t.requestId} pending=${t.pending}`);const o=s.includes("api.mockforme.com")||s.includes("mockforme.com/proxy")||s.includes("mockforme.com/gateway")||f&&s.includes(String(f));if("OPTIONS"===n||o)return;const r="mocked"===e?this.mockedRequests:this.otherRequests,i="mocked"===e?this.otherRequests:this.mockedRequests;if(t.requestId){const n=r.findIndex((e=>e.requestId===t.requestId));if(-1!==n)return r[n]={...r[n],...t},void(this.state.isOpen&&this.state.activeTab===e&&this.updateUI());const s=i.findIndex((e=>e.requestId===t.requestId));if(-1!==s){const e={...i[s],...t};return i.splice(s,1),r.unshift(e),r.length>50&&r.pop(),void(this.state.isOpen&&this.updateUI())}}r.unshift(t),r.length>50&&r.pop(),this.state.isOpen&&this.state.activeTab===e&&this.updateUI()}};function L(e,t){if("undefined"!=typeof window){if(window._mfm_intercepted)return;window._mfm_intercepted=!0}!function(e,t){const n=window.fetch;window.fetch=function(s,o={}){const r="string"==typeof s?s:s.url,i=String(o.method||(s instanceof Request?s.method:"GET")).toUpperCase().trim();if("OPTIONS"===i)return console.log(`[MockForMe] Filtered ${i} ${r} (isInternal=false)`),n(s,o);const a={url:r,method:i,requestHeaders:o.headers||(s instanceof Request?s.headers:{}),requestBody:o.body||(s instanceof Request?"{binary/stream}":null),queryParams:$(r)};try{const c=new URL(r,window.location.origin),{pathname:p,search:f}=c,g=R({url:r,method:i}),b=Math.random().toString(36).substring(7),x=Date.now();if(t!==l&&g){if(I.addRequest("mocked",{...a,requestId:b,pending:!0,startTime:x,rule:g}),"delay"===g.action)return new Promise(((e,t)=>{setTimeout((()=>{const t=n(s,o);t.then((e=>{const t=Date.now()-x;I.addRequest("mocked",{...a,requestId:b,status:e.status,pending:!1,duration:t})})).catch((e=>{const t=Date.now()-x;I.addRequest("mocked",{...a,requestId:b,status:0,pending:!1,duration:t})})),e(t)}),1e3*g.config.value)}));if("delay_and_redirect"===g.action)return new Promise(((e,t)=>{setTimeout((()=>{const t=n(g.config.redirectUrl,o);t.then((e=>{const t=Date.now()-x;I.addRequest("mocked",{...a,requestId:b,status:e.status,pending:!1,duration:t})})).catch((e=>{const t=Date.now()-x;I.addRequest("mocked",{...a,requestId:b,status:0,pending:!1,duration:t})})),e(t)}),1e3*g.config.value)}));if("delay_and_timeout"===g.action){const e=Number(g.config.value||0);if(0===e){const e=new AbortController,t=n(s,{...o,signal:e.signal});e.abort();const r=Date.now()-x;return I.addRequest("mocked",{...a,requestId:b,status:"Aborted",pending:!1,duration:r,aborted:!0}),t.catch((()=>Promise.reject(new Error("Fetch aborted by rules"))))}return new Promise(((t,n)=>{setTimeout((()=>{const e=Date.now()-x;I.addRequest("mocked",{...a,requestId:b,status:"Aborted",pending:!1,duration:e,aborted:!0}),n(new Error("Fetch timed out by rules"))}),1e3*e)}))}}const y=d(p,i),k=I.token||e;if(!y&&!g)return I.addRequest("other",{...a,requestId:b,pending:!0,startTime:x}),n(s,o).then((async e=>{const t=e.clone(),n=Date.now()-x;try{const s=await t.text();I.addRequest("other",{...a,requestId:b,status:e.status,responseHeaders:Object.fromEntries(e.headers.entries()),responseBody:s,pending:!1,duration:n})}catch(e){}return e})).catch((e=>{const t=Date.now()-x,n="AbortError"===e.name||e.message.includes("aborted"),s="TimeoutError"===e.name||e.message.includes("timed out"),o=!n&&!s;throw I.addRequest("other",{...a,requestId:b,status:n?"Aborted":s?"Timeout":"Error",responseHeaders:{},responseBody:e.message,pending:!1,duration:t,aborted:n,timeout:s,error:o}),e}));let v=r;g||(v=`${w()}${y.url}${f}`);let _={};if(!g){_={[u]:k,[m]:h,"x-mfm-adaptor":t};const e=q();e&&y._ack&&(_["x-mfm-key"]=`${e}-${y._ack}`),y?._ri_&&(_._ri_=y._ri_)}const T=s instanceof Request?s.headers:o.headers,S=new Headers(T||{});Object.entries(_).forEach((([e,t])=>{S.set(e,t)}));let M=o.body;if(!M&&s instanceof Request){const e=s.clone();"GET"!==e.method&&"HEAD"!==e.method&&(M=e.text())}let L={method:i,headers:S,credentials:"include",mode:"cors"};g&&(L.credentials=s instanceof Request&&s.credentials||o.credentials||"same-origin",L.mode=s instanceof Request&&s.mode||o.mode||"cors");const $=e=>(e&&(L.body=e),t===l?(I.addRequest("mocked",{...a,requestId:b,pending:!0,startTime:x}),(({actualUrl:e,url:t,method:n,headers:s,body:o,credentials:r,mode:i,rule:a})=>{const d=`${Date.now()}-${Math.random()}`,c=E(t);return new Promise(((t,l)=>{window.addEventListener("message",(function e(n){if(n.source!==window)return;const s=n.data;if("INTERCEPTED_RESPONSE"===s?.type&&s?.requestId===d){if(window.removeEventListener("message",e),s?.response?.error)return l(new Error(s.response.message));const{status:n,headers:o,body:r}=s.response;t(new Response(r,{status:n,headers:o}))}})),window.postMessage({type:"REQUEST_INTERCEPTED",requestId:d,payload:{actualUrl:e,url:c,method:n,headers:s,body:o,credentials:r,mode:i,rule:a}},"*")}))})({actualUrl:r,url:v,method:i,headers:Object.fromEntries(S.entries()),body:e,credentials:L.credentials,mode:L.mode,rule:g}).then((e=>(e.clone().text().then((t=>{const n=Date.now()-x;I.addRequest("mocked",{...a,requestId:b,status:e.status,responseHeaders:Object.fromEntries(e.headers.entries()),responseBody:t,pending:!1,duration:n})})),e))).catch((e=>{const t=Date.now()-x,n="AbortError"===e.name;throw I.addRequest("mocked",{...a,requestId:b,status:n?"Aborted":0,responseHeaders:{},responseBody:e.message,pending:!1,duration:t,aborted:n}),e}))):(I.addRequest("mocked",{...a,requestId:b,pending:!0,startTime:x}),n(v,L).then((e=>{const t=e.clone(),n=t.headers.get("content-type")||"",s=Date.now()-x,o=n=>(I.addRequest("mocked",{...a,requestId:b,status:e.status,responseHeaders:Object.fromEntries(t.headers.entries()),responseBody:n,pending:!1,duration:s}),new Response("string"==typeof n?n:JSON.stringify(n),{status:e.status,headers:t.headers}));return n.includes("application/json")?t.json().then(o):t.text().then(o)})).catch((e=>{console.warn("mockforme fetch interceptor error",e);const t=Date.now()-x,r="AbortError"===e.name;return I.addRequest("mocked",{...a,requestId:b,status:r?"Aborted":0,responseHeaders:{},responseBody:e.message,pending:!1,duration:t,aborted:r}),n(s,o)}))));return M instanceof Promise?M.then((e=>$(e))):$(M)}catch(e){return console.warn("mockforme fetch interceptor error",e),n(s,o)}}}(e,t),function(e,t){const n=window.XMLHttpRequest;window.XMLHttpRequest=class{constructor(){return this._xhr=new n,this._headers={},this._method=null,this._url=null,this._body=null,this._isMocked=!1,this._captured=!1,this._requestId=null,this._startTime=null,this._capture=(e,t,n,s={})=>{if(this._captured)return;this._captured=!0;const o=this._isMocked?"mocked":"other",r=this._startTime?Date.now()-this._startTime:0;console.log(`[MockForMe] XHR Capture: status=${e} method=${this._method} url=${this._url} duration=${r}ms`);const i=e=>{const t=`on${e}`;(this[t]||this._xhr[t])?.(),this._xhr.dispatchEvent(new Event(e))};if(I.addRequest(o,{url:this._url,method:this._method,requestHeaders:this._headers,requestBody:this._body,queryParams:$(this._url),requestId:this._requestId,status:e,responseBody:t,responseHeaders:n,pending:!1,duration:r,...s}),"Aborted"!==e)try{Object.defineProperty(this,"responseText",{value:t,configurable:!0}),Object.defineProperty(this,"response",{value:t,configurable:!0}),Object.defineProperty(this,"status",{value:Number(e)||0,configurable:!0}),Object.defineProperty(this,"statusText",{value:200==e?"OK":"",configurable:!0})}catch(e){console.warn("[MockForMe] Error setting XHR props",e)}Object.defineProperty(this,"readyState",{value:4,configurable:!0}),i("readystatechange"),"Aborted"===e||s.aborted?i("abort"):0===e||"Error"===e||s.error?i("error"):"Timeout"===e||s.timeout?i("timeout"):i("load")},new Proxy(this,{get:(e,t)=>{if(t in e)return e[t];const n=e._xhr[t];return"function"==typeof n?n.bind(e._xhr):n},set:(e,t,n)=>t in e?(e[t]=n,!0):(e._xhr[t]=n,!0)})}open(e,t,n=!0,s=null,o=null){this._method=(e||"").toUpperCase().trim();try{this._url=new URL(t,window.location.href).toString()}catch(e){this._url=t}return console.log(`[MockForMe] XHR.open: ${this._method} ${this._url}`),this._xhr._mockOriginalUrl=this._url,this._xhr._mockMethod=this._method,this._xhr.open(e,t,n,s,o)}setRequestHeader(e,t){return this._headers[e]=t,this._xhr.setRequestHeader(e,t)}send(s){const o=String(this._method||"").toUpperCase().trim();if(console.log(`[MockForMe] XHR send method=${o} url=${this._url}`),"OPTIONS"===o)return console.log("[MockForMe] XHR Skip OPTIONS"),this._xhr.send(s);this._body=s,this._requestId=Math.random().toString(36).substring(7),this._startTime=Date.now(),this._xhr.addEventListener("abort",(()=>{this._capture("Aborted","Request aborted",{},{aborted:!0})}),{once:!0}),this._xhr.addEventListener("error",(()=>{this._capture(0,"Network Error",{},{error:!0})}),{once:!0}),this._xhr.addEventListener("timeout",(()=>{this._capture("Timeout","Request timed out",{},{timeout:!0})}),{once:!0});try{const o=new URL(this._url),{pathname:r,search:i}=o,a=R({url:this._url,method:this._method});a&&(this._isMocked=!0,I.addRequest("mocked",{url:this._url,method:this._method,requestHeaders:this._headers,requestBody:this._body,queryParams:$(this._url),requestId:this._requestId,pending:!0,startTime:this._startTime,rule:a}));const c=I.token||e;if(t!==l&&a){if("delay"===a.action){const e=Number(a.config.value||0);return setTimeout((()=>{this._xhr.addEventListener("load",(()=>{this._capture(this._xhr.status,this._xhr.responseText,this._xhr.getAllResponseHeaders())}),{once:!0}),this._xhr.send(this._body)}),1e3*e)}if("delay_and_redirect"===a.action){const e=Number(a.config.value||0);return setTimeout((()=>{this._xhr.open(this._method,a.config.redirectUrl,!0),this._xhr.addEventListener("load",(()=>{this._capture(this._xhr.status,this._xhr.responseText,this._xhr.getAllResponseHeaders())}),{once:!0}),this._xhr.send(this._body)}),1e3*e)}if("delay_and_timeout"===a.action){const e=Number(a.config.value||0);return 0===e?(this._capture("Aborted","Request aborted by rules",{},{aborted:!0}),void this._xhr.abort()):setTimeout((()=>{this._capture("Aborted","Request timed out by rules",{},{aborted:!0}),this._xhr.abort()}),1e3*e)}}const p=d(r,this._method);if(!p&&!a)return console.log("[MockForMe] XHR No Match:",{pathname:r,method:this._method}),this._isMocked=!1,I.addRequest("other",{url:this._url,method:this._method,requestHeaders:this._headers,requestBody:this._body,queryParams:$(this._url),requestId:this._requestId,pending:!0,startTime:this._startTime}),this._xhr.addEventListener("load",(()=>{this._capture(this._xhr.status,this._xhr.responseText,this._xhr.getAllResponseHeaders())}),{once:!0}),this._xhr.send(s);console.log("[MockForMe] XHR Matched:",{pathname:r,match:p}),this._isMocked=!0;let f=this._url;a||(f=`${w()}${p.url}${i}`);let g={};if(!a){g={[u]:c,[m]:h,"x-mfm-adaptor":t};const e=q();e&&p._ack&&(g["x-mfm-key"]=`${e}-${p._ack}`),p?._ri_&&(g._ri_=p._ri_)}const b={...this._headers,...g};if(I.addRequest("mocked",{url:this._url,method:this._method,requestHeaders:this._headers,requestBody:this._body,queryParams:$(this._url),requestId:this._requestId,pending:!0,startTime:this._startTime}),t===l)(({actualUrl:e,url:t,method:n,headers:s,body:o,onSuccess:r,onError:i,rule:a})=>{const d=`${Date.now()}-${Math.random()}`,c=E(t);window.addEventListener("message",(function e(t){if(t.source!==window)return;const n=t.data;if("INTERCEPTED_RESPONSE"===n.type&&n.requestId===d){if(window.removeEventListener("message",e),n.response?.error)return i?.(n.response.message);const{body:t,status:s,headers:o}=n.response;r?.({body:t,status:s,headers:o})}})),window.postMessage({type:"REQUEST_INTERCEPTED",requestId:d,payload:{actualUrl:e,url:c,method:n,headers:s,body:o,credentials:"same-origin",mode:"cors",rule:a}},"*")})({actualUrl:this._url,url:f,method:this._method,headers:b,body:this._body,rule:a,onSuccess:({body:e,status:t,headers:n})=>{this._capture(t,e,n||{})},onError:e=>{this._capture(0,e.message||"XHR Error",{},{error:!0})}});else{const e=new n;e.open(this._method,f,!0);for(const t in b)e.setRequestHeader(t,b[t]);e.withCredentials=this.withCredentials,e.onload=()=>{this._capture(e.status,e.responseText,e.getAllResponseHeaders())},e.onerror=()=>{this._capture(0,"Network Error",{},{error:!0})},e.ontimeout=()=>{this._capture("Timeout","Request timed out",{},{timeout:!0})},e.send(this._body)}}catch(e){if(console.error("[MockForMe] XHR Interception Error",e),!this._xhr.readyState||1===this._xhr.readyState)return this._xhr.send(s)}}}}(e,t)}function $(e){try{const t=new URL(e,window.location.origin).searchParams;return Object.fromEntries(t.entries())}catch{return{}}}const O=(e,t=null,s=c)=>{if(n())return;if(s===c)try{e&&("undefined"!=typeof localStorage&&localStorage.removeItem("mockforme-token"),I.token=e,I.isAuthenticated=!0),!e&&I.token&&(e=I.token),I.onAuthSuccess=(e,t,n)=>{i(t),v(n),I.mappings=t,I.rules=n?._rules||[]}}catch(e){console.log("Error in showing mockforme widget",e)}t||={mappings:[],_o:null,mk:null,_mck:null,_rules:[]};const{mappings:o=[],_o:r,mk:l,_mck:p,_rules:f=[]}=t;return i(o),v({_o:r,mk:l,_mck:p,_rules:f}),{run:(t,n=()=>{})=>{L(e,s),r&&l?(I.mappings=o,I.rules=f,t?.(o,{_o:r,mk:l,_mck:p,_rules:f})):e&&function(e,n,s,o){T({method:"get",url:g,async:!1,headers:{[u]:e,[m]:h,"x-mfm-adaptor":n}},(e=>{if(e)try{const{di:o,iv:r,_o:a,_mck:d,mk:c,r:l}=e,m=S({di:o,iv:r},a);v({_o:a,mk:c,_mck:d,_rules:l}),m&&(i(m),n=m,s={_o:a,mk:c,_mck:d,_rules:l},I.mappings=n,I.rules=s?._rules||[],t?.(n,s))}catch(e){return void o(new Error("Unable to fetch mocked apis"))}var n,s}),(e=>{console.log("Error in loading mocked apis"),o(e)})).request()}(e,s,0,n)},checkIfApiToBeMocked:d,getMappings:a,doFetchMappings:(t,n)=>{M(e||I.token,s,((e,n)=>{I.mappings=e,I.rules=n?._rules||[],t?.(e,n)}),n)}}},C=n();C||(globalThis.mockforme=O);let H=O;C&&(H=e=>({run:()=>{}}));const U=H;module.exports=t})();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=()=>"undefined"!=typeof process&&null!=process.versions?.node,t=e=>{try{return e?e.toLowerCase():e}catch(e){return console.log(e),null}},r=(e,t)=>{const r=e.split("/"),o=t.split("/");if(r.length!==o.length)return!1;for(let e=0;e<r.length;e++){const t=r[e];if(t!==o[e]&&":any"!==t)return!1}return!0};let o=[];function n(e){o=e}function s(){return o}function i(e,n="get"){for(const s of o)if(t(s.apiMethod)===t(n)&&(s.apiEndpoint===e||r(s.apiEndpoint,e))){const t={url:e,method:s.apiMethod,_ack:s._ack||null};return s._ri_&&(t._ri_=s._ri_),t}return null}const a="JAVASCRIPT",c="CHROME_EXTENSION",d="mfmver",l="mockforme",u="4.2.8",h="https://api.mockforme.com",m=`${h}/mockforme`,f=`${h}/gateway/3f4eae522b`;let p=null,_=null,y=null,g=[];function w({_o:e,mk:t,_mck:r,_rules:o}){p=e,_=t,y=r,g=o}function b(){return g}function v(){return`${m}/${p}/${_}`}function E(){return y}const x=e=>{try{return new URL(e,window.location.origin).toString()}catch{return e}};function k({url:e,method:t}){try{const t=b();if(!Array.isArray(t)||0===t.length)return null;const r=globalThis.location?.origin||"http://localhost";for(const o of t){const t=o.rule?.URL;if(!t)continue;const{condition:n}=t;if(!n)continue;let s="";switch(t.type){case"URL":{let t;try{t=new URL(e,r),s=t.pathname}catch{s=e}break}case"QUERY":{let t;try{t=new URL(e,r)}catch{t=null}t&&(s=t.searchParams.get(n.key)||"");break}case"BODY":case"HEADERS":s="";break;default:continue}let i=!1;switch(n.operator){case"contains":i=s.includes(n.value);break;case"equal":case"equals":i=s===n.value;break;case"regexp":try{let e=n.value;if(e.startsWith("/")&&e.lastIndexOf("/")>0){const t=e.lastIndexOf("/"),r=e.slice(1,t),o=e.slice(t+1);i=new RegExp(r,o).test(s)}else i=new RegExp(e).test(s)}catch{i=!1}}if(i){const e=n.activeAction;return{action:e,config:n.actions?.[e]||{}}}}return null}catch(e){return console.error("[mockforme] checkIfRulesToBeApplied error",e),null}}function R(e,t){!function(e,t){const r=window.fetch;window.fetch=function(o,n={}){const s="string"==typeof o?o:o.url;try{const a=new URL(s,window.location.origin),{pathname:h,search:m}=a;let f="get";n&&n.method?f=n.method:o instanceof Request&&o.method&&(f=o.method),f=f.toLowerCase();const p=k({url:s,method:f});if(t!==c&&p){if("delay"===p.action)return new Promise(((e,t)=>{setTimeout((()=>{e(r(o,n))}),1e3*p.config.value)}));if("delay_and_redirect"===p.action)return new Promise(((e,t)=>{setTimeout((()=>{e(r(p.config.redirectUrl,n))}),1e3*p.config.value)}));if("delay_and_timeout"===p.action){if(0===p.config.value){const e=new AbortController,t=r(o,{...n,signal:e.signal});return e.abort(),t.catch((()=>Promise.reject(new Error("Fetch aborted by rules"))))}return new Promise(((e,t)=>{setTimeout((()=>{t(new Error("Fetch timed out by rules"))}),1e3*p.config.value)}))}}const _=i(h,f);if(!_&&!p)return r(o,n);let y=s;p||(y=`${v()}${_.url}${m}`);let g={};if(!p){g={[l]:e,[d]:u,"x-mfm-adaptor":t};const r=E();r&&_._ack&&(g["x-mfm-key"]=`${r}-${_._ack}`),_?._ri_&&(g._ri_=_._ri_)}const w=o instanceof Request?o.headers:n.headers,b=new Headers(w||{});Object.entries(g).forEach((([e,t])=>{b.set(e,t)}));let R=n.body;if(!R&&o instanceof Request){const e=o.clone();"GET"!==e.method&&"HEAD"!==e.method&&(R=e.text())}let S={method:f,headers:b,credentials:"include",mode:"cors"};p&&(S.credentials=o instanceof Request&&o.credentials||n.credentials||"same-origin",S.mode=o instanceof Request&&o.mode||n.mode||"cors");const T=e=>(e&&(S.body=e),t===c?(({actualUrl:e,url:t,method:r,headers:o,body:n,credentials:s,mode:i,rule:a})=>{const c=`${Date.now()}-${Math.random()}`,d=x(t);return new Promise(((t,l)=>{window.addEventListener("message",(function e(r){if(r.source!==window)return;const o=r.data;if("INTERCEPTED_RESPONSE"===o?.type&&o?.requestId===c){if(window.removeEventListener("message",e),o?.response?.error)return l(new Error(o.response.message));const{status:r,headers:n,body:s}=o.response;t(new Response(s,{status:r,headers:n}))}})),window.postMessage({type:"REQUEST_INTERCEPTED",requestId:c,payload:{actualUrl:e,url:d,method:r,headers:o,body:n,credentials:s,mode:i,rule:a}},"*")}))})({actualUrl:s,url:y,method:f,headers:Object.fromEntries(b.entries()),body:e,credentials:S.credentials,mode:S.mode,rule:p}):fetch(y,S).then((e=>{const t=e.clone();return(t.headers.get("content-type")||"").includes("application/json")?t.json().then((r=>new Response(JSON.stringify(r),{status:e.status,headers:t.headers}))):t.text().then((r=>new Response(r,{status:e.status,headers:t.headers})))})).catch((e=>(console.warn("mockforme fetch interceptor error",e),r(o,n)))));return R instanceof Promise?R.then((e=>T(e))):T(R)}catch(e){return console.warn("mockforme fetch interceptor error",e),r(o,n)}}}(e,t),function(e,t){const r=window.XMLHttpRequest;window.XMLHttpRequest=class{constructor(){return this._xhr=new r,this._headers={},this._method=null,this._url=null,this._body=null,new Proxy(this,{get:(e,t)=>{if(t in e)return e[t];const r=e._xhr[t];return"function"==typeof r?r.bind(e._xhr):r},set:(e,t,r)=>t in e?(e[t]=r,!0):(e._xhr[t]=r,!0)})}open(e,t,r=!0,o=null,n=null){return this._method=e.toUpperCase(),this._url=new URL(t,window.location.href).toString(),this._xhr._mockOriginalUrl=this._url,this._xhr._mockMethod=this._method,this._xhr.open(e,t,r,o,n)}setRequestHeader(e,t){return this._headers[e]=t,this._xhr.setRequestHeader(e,t)}send(o){this._body=o;try{const n=new URL(this._url),{pathname:s,search:a}=n,h=k({url:this._url,method:this._method});if(t!==c&&h){if("delay"===h.action)return setTimeout((()=>this._xhr.send(o)),1e3*h.config.value);if("delay_and_redirect"===h.action)return setTimeout((()=>{this._xhr.open(this._method,h.config.redirectUrl,!0),this._xhr.send(o)}),1e3*h.config.value);if("delay_and_timeout"===h.action)return 0===h.config.value?(this._xhr.open(this._method,this._url,!0),this._xhr.send(o),this._xhr.abort(),void("function"==typeof this.onerror&&this.onerror(new Error("XHR aborted by rules")))):setTimeout((()=>{this._xhr.abort(),"function"==typeof this.onerror&&this.onerror(new Error("XHR timed out by rules"))}),1e3*h.config.value)}const m=i(s,this._method);if(!m&&!h)return this._xhr.send(o);let f=this._url;h||(f=`${v()}${m.url}${a}`);let p={};if(!h){p={[l]:e,[d]:u,"x-mfm-adaptor":t};const r=E();r&&m._ack&&(p["x-mfm-key"]=`${r}-${m._ack}`),m?._ri_&&(p._ri_=m._ri_)}const _={...this._headers,...p};if(t===c)(({actualUrl:e,url:t,method:r,headers:o,body:n,onSuccess:s,onError:i,rule:a})=>{const c=`${Date.now()}-${Math.random()}`,d=x(t);window.addEventListener("message",(function e(t){if(t.source!==window)return;const r=t.data;if("INTERCEPTED_RESPONSE"===r.type&&r.requestId===c){if(window.removeEventListener("message",e),r.response?.error)return i?.(r.response.message);const{body:t,status:o,headers:n}=r.response;s?.({body:t,status:o,headers:n})}})),window.postMessage({type:"REQUEST_INTERCEPTED",requestId:c,payload:{actualUrl:e,url:d,method:r,headers:o,body:n,credentials:"same-origin",mode:"cors",rule:a}},"*")})({actualUrl:this._url,url:f,method:this._method,headers:_,body:this._body,rule:h,onSuccess:({body:e,status:t})=>{Object.defineProperty(this,"responseText",{value:e}),Object.defineProperty(this,"status",{value:t}),Object.defineProperty(this,"readyState",{value:4}),this.onreadystatechange?.(),this.onload?.(),this._xhr.dispatchEvent(new Event("readystatechange")),this._xhr.dispatchEvent(new Event("load"))},onError:e=>{Object.defineProperty(this,"readyState",{value:4}),this.onerror?.(new Error(e.message||"XHR mock error")),this._xhr.dispatchEvent(new Event("readystatechange")),this._xhr.dispatchEvent(new Event("error"))}});else{const e=new r;e.open(this._method,f,!0);for(const t in _)e.setRequestHeader(t,_[t]);e.withCredentials=this.withCredentials,e.onload=()=>{Object.defineProperty(this,"responseText",{value:e.responseText}),Object.defineProperty(this,"status",{value:e.status}),Object.defineProperty(this,"readyState",{value:4}),this.onreadystatechange?.(),this.onload?.(),this._xhr.dispatchEvent(new Event("readystatechange")),this._xhr.dispatchEvent(new Event("load"))},e.onerror=()=>{Object.defineProperty(this,"readyState",{value:4}),this.onerror?.(),this._xhr.dispatchEvent(new Event("readystatechange")),this._xhr.dispatchEvent(new Event("error"))},e.send(this._body)}}catch(e){console.error("[mockforme][XHR] interception error",e)}}}}(e,t)}const S=function(t,r,o){const n=e();var s;function i(){if(4==s.readyState)if(s.status.toString().match(/^20[0-9]$/)){var e=function(){var e=s.getResponseHeader("Content-Type"),t=s.responseText;if(e){var r=e.split(";");try{return"application/json"===r[0]?JSON.parse(t):t}catch(e){throw"Unable to convert response header"}}}();r.call(this,e,s)}else o.call(this,s.responseText,s)}function a(e,t){var r=[];for(var o in e)if(e.hasOwnProperty(o)){var n=t?t+"["+o+"]":o,s=e[o];r.push("object"==typeof s?a(s,n):encodeURIComponent(n)+"="+encodeURIComponent(s))}return r.join("&")}return n||(window.XMLHttpRequest?s=new XMLHttpRequest:window.ActiveXObject&&(s=new ActiveXObject("Microsoft.XMLHTTP"))),{request:function(){if(!n){if(window.XMLHttpRequest)s.onload=i;else{if(!window.ActiveXObject)throw"unable to process ajax";s.onreadystatechange=i}var e=a(t.params);if("get"==t.method.toLowerCase()&&"object"==typeof t.params){if(-1==t.url.indexOf("?"))t.url+="?";else{var r=t.url.split("?");r[1]&&r[1].split("=")[1]&&(t.url+="&")}t.url+=e}t.hasOwnProperty("async")||(t.async=!0),s.open(t.method,t.url,t.async),t.headers&&function(e){for(let t in e)s.setRequestHeader(t,e[t])}(t.headers),s.send(e)}}}};function T({di:e,iv:t},r){var o;const n=function(e,t){const r=t.length;return e.split("").map(((e,o)=>String.fromCharCode(e.charCodeAt(0)^t.charCodeAt(o%r)))).join("")}((o=e,"undefined"!=typeof Buffer?Buffer.from(o,"base64").toString("utf8"):decodeURIComponent(escape(atob(o)))),r+t);return JSON.parse(n)}const O=(t,r=null,o=a)=>{if(e())return;if(o===a)try{(()=>{const e=()=>{if(!window.mockforme)return;const e=JSON.parse(localStorage.getItem("mockforme-dot-pos")||"{}"),t=document.createElement("div");t.id="mockforme-dot",Object.assign(t.style,{position:"fixed",bottom:(e.bottom??20)+"px",right:(e.right??20)+"px",width:"42px",height:"42px",borderRadius:"50%",overflow:"hidden",cursor:"grab",zIndex:999999,boxShadow:"0 0 10px rgba(0,0,0,0.25)",backgroundColor:"#fff",display:"flex",alignItems:"center",justifyContent:"center"});const r=document.createElement("img");r.src="https://dashboard.mockforme.com/public/assets/images/icon.png",r.style.objectFit="cover",t.appendChild(r),document.body.appendChild(t);const o=document.createElement("div");o.id="mockforme-widget",o.innerText="MockForMe Enabled",Object.assign(o.style,{position:"fixed",padding:"8px 12px",background:"#2563eb",color:"#fff",fontSize:"13px",fontFamily:"Inter, sans-serif",borderRadius:"8px",bottom:(e.bottom??20)+50+"px",right:(e.right??20)+"px",boxShadow:"0 4px 10px rgba(0,0,0,0.2)",zIndex:999999,display:"none",whiteSpace:"nowrap"}),document.body.appendChild(o),t.addEventListener("click",(e=>{e.stopPropagation(),o.style.display="none"===o.style.display?"block":"none"})),document.addEventListener("click",(()=>{o.style.display="none"}));let n=!1,s=0,i=0;t.addEventListener("mousedown",(e=>{n=!0,t.style.cursor="grabbing";const r=t.getBoundingClientRect();s=e.clientX-r.left,i=e.clientY-r.top,e.preventDefault()})),document.addEventListener("mousemove",(e=>{if(!n)return;const r=e.clientX-s,a=e.clientY-i,c=window.innerHeight-(a+t.offsetHeight),d=window.innerWidth-(r+t.offsetWidth);t.style.bottom=c+"px",t.style.right=d+"px",o.style.bottom=c+50+"px",o.style.right=d+"px"})),document.addEventListener("mouseup",(()=>{if(!n)return;n=!1,t.style.cursor="grab";const e=parseInt(t.style.bottom),r=parseInt(t.style.right);localStorage.setItem("mockforme-dot-pos",JSON.stringify({bottom:e,right:r}))}))};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",e):e()})()}catch(e){console.log("Error in showing mockforme widget")}r||={mappings:[],_o:null,mk:null,_mck:null,_rules:[]};const{mappings:c=[],_o:h,mk:m,_mck:p,_rules:_=[]}=r;return n(c),w({_o:h,mk:m,_mck:p,_rules:_}),{run:(e,r=()=>{})=>{R(t,o),h&&m?e(s(),{_o:h,mk:m,_mck:p,_rules:_}):function(t,r,o,s){S({method:"get",url:f,async:!1,headers:{[l]:t,[d]:u,"x-mfm-adaptor":r}},(t=>{if(t)try{const{di:s,iv:i,_o:a,_mck:c,mk:d,r:l}=t,u=T({di:s,iv:i},a);w({_o:a,mk:d,_mck:c,_rules:l}),u&&(n(u),r=u,o={_o:a,mk:d,_mck:c,_rules:l},e?.(r,o))}catch(e){return void s(new Error("Unable to fetch mocked apis"))}var r,o}),(e=>{console.log("Error in loading mocked apis"),s(e)})).request()}(t,o,0,r)},checkIfApiToBeMocked:i,getMappings:s,doFetchMappings:(e,r)=>{!function(e,t,r,o){fetch(f,{method:"GET",headers:{[l]:e,[d]:u,"x-mfm-adaptor":t}}).then((e=>{if(!e.ok)throw e;return e.json()})).then((e=>{if(e){const{di:t,iv:o,_o:s,_mck:i,mk:a,r:c}=e,d=T({di:t,iv:o},s);w({_o:s,mk:a,_mck:i,_rules:c}),d&&(n(d),r(d,{_o:s,mk:a,_mck:i,_rules:c}))}})).catch((e=>{console.error("Error in loading mocked APIs:",e),o(e)}))}(t,o,((t,r)=>{e?.(t,r)}),r)}}},C=e();C||(globalThis.mockforme=O);let L=O;C&&(L=e=>({run:()=>{}}));const P=L;export{P as mockforme};
|
|
1
|
+
const e=()=>"undefined"!=typeof process&&null!=process.versions?.node,t=e=>{try{return e?e.toLowerCase():e}catch(e){return console.log(e),null}},n=(e,t)=>{const n=e.split("/"),s=t.split("/");if(n.length!==s.length)return!1;for(let e=0;e<n.length;e++){const t=n[e];if(t!==s[e]&&":any"!==t)return!1}return!0};let s=[];function o(e){s=e}function r(){return s}function i(e,o="get"){const r=e=>e.startsWith("/")?e:`/${e}`,i=r(e);for(const a of s)if(t(a.apiMethod)===t(o)){const t=r(a.apiEndpoint);if(t===i||n(t,i)){console.log(`[MockForMe] Match Found: ${o} ${e} -> ${a.apiEndpoint}`);const t={url:e,method:a.apiMethod,_ack:a._ack||null};return a._ri_&&(t._ri_=a._ri_),t}}return null}const a="JAVASCRIPT",d="CHROME_EXTENSION",c="mfmver",l="mockforme",m="4.2.8",u="https://api.mockforme.com",h=`${u}/mockforme`,p=`${u}/gateway/3f4eae522b`;let f=null,g=null,b=null,x=[];function y({_o:e,mk:t,_mck:n,_rules:s}){f=e,g=t,b=n,x=s}function k(){return x}function v(){return`${h}/${f}/${g}`}function _(){return b}const w=e=>{try{return new URL(e,window.location.origin).toString()}catch{return e}};function q({url:e,method:t}){try{const t=k();if(!Array.isArray(t)||0===t.length)return null;const n=globalThis.location?.origin||"http://localhost";for(const s of t){const t=s.rule?.URL;if(!t)continue;const{condition:o}=t;if(!o)continue;let r="";switch(t.type){case"URL":{let t;try{t=new URL(e,n),r=t.pathname}catch{r=e}break}case"QUERY":{let t;try{t=new URL(e,n)}catch{t=null}t&&(r=t.searchParams.get(o.key)||"");break}case"BODY":case"HEADERS":r="";break;default:continue}let i=!1;switch(o.operator){case"contains":i=r.includes(o.value);break;case"equal":case"equals":i=r===o.value;break;case"regexp":try{let e=o.value;if(e.startsWith("/")&&e.lastIndexOf("/")>0){const t=e.lastIndexOf("/"),n=e.slice(1,t),s=e.slice(t+1);i=new RegExp(n,s).test(r)}else i=new RegExp(e).test(r)}catch{i=!1}}if(i){const e=o.activeAction;return{action:e,config:o.actions?.[e]||{}}}}return null}catch(e){return console.error("[mockforme] checkIfRulesToBeApplied error",e),null}}const E=function(t,n,s){const o=e();var r;function i(){if(4==r.readyState)if(r.status.toString().match(/^20[0-9]$/)){var e=function(){var e=r.getResponseHeader("Content-Type"),t=r.responseText;if(e){var n=e.split(";");try{return"application/json"===n[0]?JSON.parse(t):t}catch(e){throw"Unable to convert response header"}}}();n.call(this,e,r)}else s.call(this,r.responseText,r)}function a(e,t){var n=[];for(var s in e)if(e.hasOwnProperty(s)){var o=t?t+"["+s+"]":s,r=e[s];n.push("object"==typeof r?a(r,o):encodeURIComponent(o)+"="+encodeURIComponent(r))}return n.join("&")}return o||(window.XMLHttpRequest?r=new XMLHttpRequest:window.ActiveXObject&&(r=new ActiveXObject("Microsoft.XMLHTTP"))),{request:function(){if(!o){if(window.XMLHttpRequest)r.onload=i;else{if(!window.ActiveXObject)throw"unable to process ajax";r.onreadystatechange=i}var e=a(t.params);if("get"==t.method.toLowerCase()&&"object"==typeof t.params){if(-1==t.url.indexOf("?"))t.url+="?";else{var n=t.url.split("?");n[1]&&n[1].split("=")[1]&&(t.url+="&")}t.url+=e}t.hasOwnProperty("async")||(t.async=!0),r.open(t.method,t.url,t.async),t.headers&&function(e){for(let t in e)r.setRequestHeader(t,e[t])}(t.headers),r.send(e)}}}};function R({di:e,iv:t},n){var s;const o=function(e,t){const n=t.length;return e.split("").map(((e,s)=>String.fromCharCode(e.charCodeAt(0)^t.charCodeAt(s%n)))).join("")}((s=e,"undefined"!=typeof Buffer?Buffer.from(s,"base64").toString("utf8"):decodeURIComponent(escape(atob(s)))),n+t);return JSON.parse(o)}function T(e,t,n,s){fetch(p,{method:"GET",headers:{[l]:e,[c]:m,"x-mfm-adaptor":t}}).then((e=>{if(!e.ok)throw e;return e.json()})).then((e=>{if(e){const{di:t,iv:s,_o:r,_mck:i,mk:a,r:d}=e,c=R({di:t,iv:s},r);y({_o:r,mk:a,_mck:i,_rules:d}),c&&(o(c),n(c,{_o:r,mk:a,_mck:i,_rules:d}))}})).catch((e=>{console.error("Error in loading mocked APIs:",e),s(e)}))}const S=new class{constructor(t={}){e()||(this.token=t.token||("undefined"!=typeof localStorage?localStorage.getItem("mockforme-token"):null),this.isAuthenticated=!!this.token,this.onAuthSuccess=t.onAuthSuccess||(()=>{}),this.mappings=t.mappings||[],this.rules=t.rules||[],this.mockedRequests=[],this.otherRequests=[],this.state={isOpen:!1,activeTab:"mappings",selectedRequest:null,activeRequestTab:"response",lastError:null,searchQuery:""},"undefined"!=typeof document&&("loading"===document.readyState?document.addEventListener("DOMContentLoaded",(()=>this.init())):this.init()))}init(){document.getElementById("mockforme-root")||(this.createStyles(),this.render())}createStyles(){if(document.getElementById("mockforme-styles"))return;const e=document.createElement("style");e.id="mockforme-styles",e.innerHTML="\n #mockforme-root {\n font-family: 'Inter', system-ui, -apple-system, sans-serif;\n z-index: 999999;\n position: fixed;\n }\n .mfm-bubble {\n position: fixed;\n bottom: 20px;\n right: 20px;\n height: 42px;\n padding: 4px 8px;\n border-radius: 24px;\n box-shadow: 0 4px 12px rgba(0,0,0,0.15);\n cursor: pointer;\n z-index: 999999;\n background: white;\n display: flex;\n align-items: center;\n gap: 8px;\n transition: transform 0.2s;\n border: 1px solid #eee;\n }\n .mfm-bubble:hover { transform: scale(1.05); }\n .mfm-bubble img { width: 32px; height: 32px; border-radius: 50%; object-fit: cover; }\n \n .mfm-refresh-icon {\n width: 32px;\n height: 32px;\n background: #f3f4f6;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #2563eb;\n font-size: 18px;\n transition: background 0.2s;\n }\n .mfm-refresh-icon:hover { background: #e5e7eb; }\n .mfm-refresh-icon.loading { animation: mfm-spin 1s linear infinite; }\n @keyframes mfm-spin { 100% { transform: rotate(360deg); } }\n\n .mfm-bottomsheet {\n position: fixed;\n bottom: 0;\n left: 0;\n right: 0;\n background: white;\n border-top-left-radius: 16px;\n border-top-right-radius: 16px;\n box-shadow: 0 -4px 20px rgba(0,0,0,0.15);\n padding: 20px;\n z-index: 999999;\n height: 90vh;\n max-width: 500px;\n margin: 0 auto;\n display: flex;\n flex-direction: column;\n transition: transform 0.3s ease-out;\n transform: translateY(100%);\n visibility: hidden;\n overflow-y: auto;\n }\n .mfm-bottomsheet.open { transform: translateY(0); visibility: visible; }\n \n .mfm-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 20px;\n padding-bottom: 10px;\n border-bottom: 1px solid #eee;\n }\n .mfm-title-group { display: flex; align-items: center; gap: 10px; }\n .mfm-title { font-size: 18px; font-weight: 600; color: #111; }\n .mfm-delete-token-btn { \n background: #fee2e2; \n color: #dc2626; \n font-size: 13px; \n padding: 4px 12px; \n border-radius: 20px; \n cursor: pointer; \n display: flex;\n align-items: center;\n gap: 6px;\n border: none;\n font-weight: 500;\n transition: background 0.2s;\n }\n .mfm-delete-token-btn:hover { background: #fecaca; }\n .mfm-header-actions { display: flex; align-items: center; gap: 10px; }\n .mfm-close { background: none; border: none; font-size: 24px; cursor: pointer; color: #666; }\n /* Login Form */\n .mfm-logo-container { text-align: center; padding: 30px 0; width: 100%; display: flex; justify-content: center; }\n .mfm-logo { width: 150px; height: auto; }\n .mfm-link { color: #2563eb; text-decoration: none; font-size: 14px; margin-top: 5px; cursor: pointer; display: inline-block; }\n .mfm-link:hover { text-decoration: underline; }\n .mfm-form { display: flex; flex-direction: column; gap: 10px; }\n .mfm-input {\n padding: 12px;\n border: 1px solid #ddd;\n border-radius: 8px;\n font-size: 16px;\n outline: none;\n transition: border-color 0.2s;\n }\n .mfm-input:focus { border-color: #2563eb; }\n .mfm-error { color: #dc2626; font-size: 13px; margin-top: -5px; }\n .mfm-btn {\n padding: 12px;\n background: #2563eb;\n color: white;\n border: none;\n border-radius: 8px;\n font-size: 16px;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.2s;\n }\n .mfm-btn:hover { background: #1d4ed8; }\n .mfm-btn:disabled { background: #9ca3af; cursor: not-allowed; }\n\n .mfm-tabs { display: flex; border-bottom: 1px solid #eee; margin-bottom: 15px; }\n .mfm-tab {\n padding: 10px 20px;\n cursor: pointer;\n color: #666;\n border-bottom: 2px solid transparent;\n font-weight: 500;\n }\n .mfm-tab.active { color: #2563eb; border-bottom-color: #2563eb; }\n \n .mfm-list {\n flex: 1;\n overflow-y: auto;\n min-height: 200px;\n max-height: 60vh;\n }\n .mfm-list-item {\n padding: 10px;\n border-bottom: 1px solid #f3f4f6;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: space-between;\n font-size: 14px;\n min-height: 52px;\n box-sizing: border-box;\n }\n .mfm-list-item:hover { background: #f9fafb; }\n .mfm-method { \n font-weight: bold; \n padding: 4px 8px; \n border-radius: 4px; \n margin-right: 10px;\n font-size: 12px;\n }\n .GET { background: #dbfcfe; color: #006064; }\n .POST { background: #dcfce7; color: #14532d; }\n .PUT { background: #fef9c3; color: #713f12; }\n .DELETE { background: #fee2e2; color: #7f1d1d; }\n .PATCH { background: #f3e8ff; color: #581c87; }\n .RULE { background: #f3f4f6; color: #374151; }\n\n /* Search & Actions */\n .mfm-actions-bar { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }\n .mfm-search-input { flex: 1; padding: 8px 12px; border: 1px solid #ddd; border-radius: 6px; font-size: 14px; outline: none; }\n .mfm-search-input:focus { border-color: #2563eb; }\n .mfm-icon-btn { background: none; border: none; font-size: 18px; cursor: pointer; color: #666; display: flex; align-items: center; justify-content: center; padding: 4px; border-radius: 4px; }\n .mfm-icon-btn:hover { background: #f3f4f6; color: #333; }\n .mfm-icon-btn.refresh { color: #2563eb; padding: 0; height: 30px; width:30px; border-radius: 50%; }\n .mfm-icon-btn.refresh.loading { animation: mfm-spin 1s linear infinite; }\n .mfm-icon-btn.delete { color: #dc2626; }\n\n .mfm-url { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n .mfm-status { font-weight: bold; margin-left: 10px; }\n .status-2xx { color: #16a34a; }\n .status-4xx { color: #dc2626; }\n .status-5xx { color: #ea580c; }\n .status-aborted, .status-timeout, .status-error { color: #dc2626; font-size: 11px; font-weight: 500; }\n\n .mfm-rule-tag {\n font-size: 9px;\n padding: 2px 4px;\n border-radius: 4px;\n background: #fef3c7;\n color: #92400e;\n border: 1px solid #fde68a;\n margin-right: 6px;\n text-transform: uppercase;\n font-weight: bold;\n }\n\n .mfm-detail-view { display: flex; flex-direction: column; height: 100%; }\n .mfm-detail-actions { margin-bottom: 10px; }\n .mfm-back-btn { background: none; border: none; color: #2563eb; cursor: pointer; font-size: 14px; display: flex; align-items: center; gap: 4px; padding: 0;}\n \n .mfm-code-block {\n background: #f8fafc;\n padding: 10px;\n border-radius: 8px;\n overflow-x: auto;\n font-family: monospace;\n font-size: 12px;\n white-space: pre-wrap;\n word-break: break-all;\n max-height: 300px;\n border: 1px solid #e2e8f0;\n }\n .section-title { font-size: 14px; font-weight: 600; margin: 10px 0 5px; color: #333; }\n\n /* Snackbar */\n .mfm-snackbar {\n position: fixed;\n bottom: 80px;\n left: 50%;\n transform: translateX(-50%) translateY(20px);\n background: #333;\n color: white;\n padding: 10px 20px;\n border-radius: 8px;\n font-size: 14px;\n z-index: 1000000;\n opacity: 0;\n transition: opacity 0.3s, transform 0.3s;\n pointer-events: none;\n }\n .mfm-snackbar.show { opacity: 1; transform: translateX(-50%) translateY(0); }\n\n /* Confirm Dialog */\n .mfm-modal-overlay {\n position: fixed;\n top: 0; left: 0; right: 0; bottom: 0;\n background: rgba(0,0,0,0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000001;\n opacity: 0;\n transition: opacity 0.2s;\n pointer-events: none;\n }\n .mfm-modal-overlay.show { opacity: 1; pointer-events: auto; }\n .mfm-modal {\n background: white;\n padding: 20px;\n border-radius: 12px;\n width: 300px;\n box-shadow: 0 10px 25px rgba(0,0,0,0.2);\n transform: scale(0.9);\n transition: transform 0.2s;\n }\n .mfm-modal-overlay.show .mfm-modal { transform: scale(1); }\n .mfm-modal-title { font-size: 16px; font-weight: 600; margin-bottom: 10px; }\n .mfm-modal-body { font-size: 14px; color: #666; margin-bottom: 20px; }\n .mfm-modal-actions { display: flex; justify-content: flex-end; gap: 10px; }\n .mfm-btn-alt { background: #f3f4f6; color: #333; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; font-size: 14px; }\n .mfm-btn-danger { background: #dc2626; color: white; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; font-size: 14px; }\n \n .mfm-spinner {\n width: 12px;\n height: 12px;\n border: 2px solid #f3f3f3;\n border-top: 2px solid #2563eb;\n border-radius: 50%;\n animation: mfm-spin 1s linear infinite;\n margin-right: 8px;\n display: inline-block;\n }\n .status-aborted { color: #dc2626; font-weight: bold; }\n .mfm-duration { color: #666; font-size: 11px; margin-left: 8px; font-weight: normal; }\n ",document.head.appendChild(e)}render(){const e=document.createElement("div");e.id="mockforme-root",document.body.appendChild(e),this.root=e,this.bubble=this.renderBubble(),this.root.appendChild(this.bubble),this.sheet=document.createElement("div"),this.sheet.className="mfm-bottomsheet",this.root.appendChild(this.sheet),this.snackbar=document.createElement("div"),this.snackbar.className="mfm-snackbar",this.root.appendChild(this.snackbar),this.modalOverlay=document.createElement("div"),this.modalOverlay.className="mfm-modal-overlay",this.root.appendChild(this.modalOverlay),this.updateUI()}updateUI(){this.state.isOpen?(this.renderBottomSheetContent(),this.sheet.classList.add("open")):this.sheet.classList.remove("open")}renderBubble(){const e=document.createElement("div");e.className="mfm-bubble";const t="undefined"!=typeof localStorage?JSON.parse(localStorage.getItem("mockforme-dot-pos")||"{}"):{};return t.bottom&&(e.style.bottom=t.bottom+"px"),t.right&&(e.style.right=t.right+"px"),e.innerHTML='\n <div class="mfm-refresh-icon" title="Reload Mappings">↻</div>\n <img src="https://ik.imagekit.io/mfm/static-collection/mfm-48x48.png" alt="MFM" />\n ',this.addDragLogic(e),e.querySelector("img").onclick=e=>{this.isDragging||this.toggleSheet()},e.querySelector(".mfm-refresh-icon").onclick=e=>{e.stopPropagation(),this.refreshMappings()},e}addDragLogic(e){let t,n,s,o,r=!1;const i=i=>{const a=t-i.clientX,d=n-i.clientY;(Math.abs(a)>3||Math.abs(d)>3)&&(r=!0,this.isDragging=!0),r&&(e.style.right=s+a+"px",e.style.bottom=o+d+"px")},a=()=>{document.removeEventListener("mousemove",i),document.removeEventListener("mouseup",a),r&&"undefined"!=typeof localStorage&&localStorage.setItem("mockforme-dot-pos",JSON.stringify({bottom:parseInt(e.style.bottom),right:parseInt(e.style.right)}))};e.addEventListener("mousedown",(d=>{r=!1,this.isDragging=!1,t=d.clientX,n=d.clientY;const c=e.getBoundingClientRect();s=window.innerWidth-c.right,o=window.innerHeight-c.bottom,document.addEventListener("mousemove",i),document.addEventListener("mouseup",a)}))}toggleSheet(){this.state.isOpen=!this.state.isOpen,this.updateUI()}showSnackbar(e){this.snackbar.textContent=e,this.snackbar.classList.add("show"),setTimeout((()=>this.snackbar.classList.remove("show")),3e3)}showConfirm(e,t,n){this.modalOverlay.innerHTML=`\n <div class="mfm-modal">\n <div class="mfm-modal-title">${e}</div>\n <div class="mfm-modal-body">${t}</div>\n <div class="mfm-modal-actions">\n <button class="mfm-btn-alt" id="mfm-confirm-cancel">Cancel</button>\n <button class="mfm-btn-danger" id="mfm-confirm-yes">Delete</button>\n </div>\n </div>\n `,this.modalOverlay.classList.add("show"),this.modalOverlay.querySelector("#mfm-confirm-cancel").onclick=()=>{this.modalOverlay.classList.remove("show")},this.modalOverlay.querySelector("#mfm-confirm-yes").onclick=()=>{this.modalOverlay.classList.remove("show"),n()}}refreshMappings(){if(!this.token)return void this.toggleSheet();const e=document.querySelectorAll(".mfm-refresh-icon, #mfm-refresh-mappings-btn");e.forEach((e=>e.classList.add("loading"))),T(this.token,"JAVASCRIPT",((t,n)=>{console.log("[MockForMe] Mappings reloaded",{mappings:t?.length,rules:n?._rules?.length}),e.forEach((e=>e.classList.remove("loading"))),this.mappings=t||[],this.rules=n?._rules||[],this.onAuthSuccess(this.token,this.mappings,n),this.updateUI(),this.showSnackbar("Mappings reloaded!")}),(t=>{e.forEach((e=>e.classList.remove("loading"))),this.showSnackbar("Failed to reload mappings")}))}renderBottomSheetContent(){this.sheet.innerHTML="",this.isAuthenticated?this.state.selectedRequest?this.sheet.appendChild(this.renderRequestDetail(this.state.selectedRequest)):this.sheet.appendChild(this.renderDashboard()):this.sheet.appendChild(this.renderTokenForm())}renderTokenForm(){const e=document.createElement("div");e.innerHTML=`\n <div class="mfm-header">\n <span class="mfm-title">Save Token</span>\n <button class="mfm-close">×</button>\n </div>\n <div class="mfm-logo-container">\n <img src="https://dashboard.mockforme.com/public/assets/images/logo.png" class="mfm-logo" alt="MockForMe Logo" />\n </div>\n <div class="mfm-form">\n <input type="text" class="mfm-input" placeholder="Enter MockForMe Access Token" id="mfm-token-input">\n <div class="mfm-error" id="mfm-error-msg" style="display: ${this.state.lastError?"block":"none"}">${this.state.lastError||""}</div>\n <a href="https://dashboard.mockforme.com/user/token" target="_blank" class="mfm-link">Get Access Token?</a>\n <button class="mfm-btn" id="mfm-save-token-btn">Save</button>\n </div>\n `,e.querySelector(".mfm-close").onclick=()=>{this.state.lastError=null,this.toggleSheet()};const t=e.querySelector("#mfm-save-token-btn"),n=e.querySelector("#mfm-token-input");return t.onclick=()=>{const s=n.value.trim();s&&(t.textContent="Validating...",t.disabled=!0,this.state.lastError=null,e.querySelector("#mfm-error-msg").style.display="none",T(s,a,((e,t)=>{"undefined"!=typeof localStorage&&localStorage.setItem("mockforme-token",s),this.token=s,this.isAuthenticated=!0,this.mappings=e,this.rules=t?._rules||[],this.onAuthSuccess(s,e,t),this.updateUI()}),(e=>{t.textContent="Save",t.disabled=!1;let n="Invalid Token or Network Error";e&&"function"==typeof e.json?e.json().then((e=>{this.state.lastError=e.message||n,this.updateUI()})).catch((()=>{this.state.lastError=n,this.updateUI()})):(this.state.lastError=e.message||n,this.updateUI())})))},e}deleteToken(){"undefined"!=typeof localStorage&&localStorage.removeItem("mockforme-token"),this.token=null,this.isAuthenticated=!1,this.mappings=[],this.rules=[],this.state.lastError=null,this.updateUI()}renderDashboard(){const e=document.createElement("div");e.innerHTML='\n <div class="mfm-header">\n <span class="mfm-title">MockForMe</span>\n <div class="mfm-header-actions">\n <button class="mfm-delete-token-btn" id="mfm-delete-token" title="Delete Token">\n <span>🗑</span>\n <span>Token</span>\n </button>\n <button class="mfm-close">×</button>\n </div>\n </div>\n ';const t=document.createElement("div");t.className="mfm-tabs",["mappings","mocked","other"].forEach((e=>{const n=document.createElement("div");n.className="mfm-tab "+(this.state.activeTab===e?"active":""),n.textContent="mappings"===e?"Api Mappings":"mocked"===e?"Mocked Apis":"Other Apis",n.onclick=()=>{this.state.activeTab=e,this.updateUI()},t.appendChild(n)})),e.querySelector(".mfm-header").after(t);const n=document.createElement("div");n.className="mfm-actions-bar","mappings"===this.state.activeTab?(n.innerHTML=`\n <div style="flex: 1; font-size: 13px; color: #666;">Total: ${this.mappings.length+this.rules.length}</div>\n <div class="mfm-icon-btn refresh" id="mfm-refresh-mappings-btn" title="Refresh Mappings">↻</div>\n `,n.querySelector("#mfm-refresh-mappings-btn").onclick=()=>this.refreshMappings()):(n.innerHTML=`\n <input type="text" class="mfm-search-input" placeholder="Search requests..." id="mfm-search-input" value="${this.state.searchQuery}">\n <button class="mfm-icon-btn delete" id="mfm-clear-requests-btn" title="Clear List">🚫</button>\n `,n.querySelector("#mfm-search-input").oninput=e=>{this.state.searchQuery=e.target.value,this.updateRequestList(s)},n.querySelector("#mfm-clear-requests-btn").onclick=()=>{"mocked"===this.state.activeTab?this.mockedRequests=[]:this.otherRequests=[],this.updateUI()}),t.after(n);const s=document.createElement("div");return s.className="mfm-list",this.updateRequestList(s),e.appendChild(s),e.querySelector(".mfm-close").onclick=()=>this.toggleSheet(),e.querySelector("#mfm-delete-token").onclick=()=>{this.showConfirm("Delete Token","Are you sure you want to Delete Token? This will clear your saved token.",(()=>{this.deleteToken()}))},e}updateRequestList(e){if(e.innerHTML="","mappings"===this.state.activeTab){const t=[...this.mappings.map((e=>({...e,type:"mapping"}))),...this.rules.map((e=>({...e,type:"rule"})))];0===t.length?e.innerHTML='<div style="padding: 20px; text-align: center; color: #999;">No items found</div>':t.forEach((t=>{const n=document.createElement("div");if(n.className="mfm-list-item","mapping"===t.type){const e=(t.apiMethod||"GET").toUpperCase();n.innerHTML=`<div style="display:flex; align-items:center; width:100%"><span class="mfm-method ${e}">${e}</span><span class="mfm-url">${t.apiEndpoint}</span></div>`}else{const e=t.ruleName||"Network Rule",s=(t.rule?.URL?.condition||{}).value||e;n.innerHTML=`<div style="display:flex; align-items:center; width:100%"><span class="mfm-method RULE">RULE</span><span class="mfm-url">${s}</span></div>`}e.appendChild(n)}))}else{let t="mocked"===this.state.activeTab?this.mockedRequests:this.otherRequests;if(this.state.searchQuery){const e=this.state.searchQuery.toLowerCase();t=t.filter((t=>(t.url||"").toLowerCase().includes(e)||(t.method||"").toLowerCase().includes(e)||String(t.status).includes(e)))}0===t.length?e.innerHTML='<div style="padding: 20px; text-align: center; color: #999;">No items found</div>':t.forEach((t=>{const n=document.createElement("div");n.className="mfm-list-item";const s=(t.method||"").toUpperCase(),o=`<span class="mfm-duration" style="color:#2563eb; font-size:11px; font-weight:500; display:block; height:14px; line-height:14px;">${void 0!==t.duration?t.duration+"ms":""}</span>`,r=(()=>{if(!t.rule)return"";let e="delay_and_timeout"===t.rule.action?"Delay and Timout":t.rule.action.split("_")[0];const n=t.rule.config?.value;return void 0!==n&&(t.rule.action.includes("delay")||t.rule.action.includes("timeout"))&&(e+=` (${n}s)`),`<span class="mfm-rule-tag" title="${t.rule.action}">${e}</span>`})();let i=t.status,a="mfm-status";t.pending?i='<span class="mfm-spinner"></span>':t.aborted?(i="Aborted",a+=" status-aborted"):t.timeout?(i="Timeout",a+=" status-timeout"):t.error?(i="Error/CORS",a+=" status-error"):(i=t.status,a+=t.status>=200&&t.status<300?" status-2xx":" status-4xx"),n.innerHTML=`\n <div style="display:flex; align-items:center; width:100%; gap:8px;">\n <span class="mfm-method ${s}">${s}</span>\n <div style="flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; justify-content:center;">\n <span class="mfm-url">${r}${t.url}</span>\n ${o}\n </div>\n <span class="${a}">${i}</span>\n </div>\n `,n.onclick=()=>{this.state.selectedRequest=t,this.updateUI()},e.appendChild(n)}))}}renderRequestDetail(e){const t=document.createElement("div");t.className="mfm-detail-view",t.innerHTML='\n <div class="mfm-header">\n <span class="mfm-title">Details</span>\n <button class="mfm-close">×</button>\n </div>\n <div class="mfm-detail-actions">\n <button class="mfm-back-btn">← Back</button>\n </div>\n ';const n=document.createElement("div");n.className="mfm-tabs",["request","response"].forEach((e=>{const t=document.createElement("div");t.className="mfm-tab "+(this.state.activeRequestTab===e?"active":""),t.textContent=e.charAt(0).toUpperCase()+e.slice(1),t.onclick=()=>{this.state.activeRequestTab=e,this.updateUI()},n.appendChild(t)}));const s=document.createElement("div");s.style.overflowY="auto",s.style.flex="1";const o=(e.method||"").toUpperCase();return s.innerHTML="request"===this.state.activeRequestTab?`\n <div class="section-title">URL</div><div class="mfm-code-block">${o} ${e.url}</div>\n ${e.rule?`<div class="section-title">Matched Rule</div><div class="mfm-code-block">${e.rule.action} (value: ${e.rule.config?.value})</div>`:""}\n <div class="section-title">Headers</div><div class="mfm-code-block">${JSON.stringify(e.requestHeaders||{},null,2)}</div>\n <div class="section-title">Query Params</div><div class="mfm-code-block">${JSON.stringify(e.queryParams||{},null,2)}</div>\n <div class="section-title">Payload</div><div class="mfm-code-block">${this.formatBody(e.requestBody)}</div>\n `:`\n <div class="section-title">Status</div><div class="mfm-code-block">${e.status}</div>\n <div class="section-title">Response Headers</div><div class="mfm-code-block">${JSON.stringify(e.responseHeaders||{},null,2)}</div>\n <div class="section-title">Response Body</div><div class="mfm-code-block">${this.formatBody(e.responseBody)}</div>\n `,t.appendChild(n),t.appendChild(s),t.querySelector(".mfm-close").onclick=()=>this.toggleSheet(),t.querySelector(".mfm-back-btn").onclick=()=>{this.state.selectedRequest=null,this.updateUI()},t}formatBody(e){if(!e)return"";if("object"==typeof e)return JSON.stringify(e,null,2);try{return JSON.stringify(JSON.parse(e),null,2)}catch{return e}}addRequest(e,t){const n=String(t.method||"").toUpperCase().trim(),s=String(t.url||"");console.log(`[MockForMe] addRequest type=${e} method=${n} url=${s} requestId=${t.requestId} pending=${t.pending}`);const o=s.includes("api.mockforme.com")||s.includes("mockforme.com/proxy")||s.includes("mockforme.com/gateway")||h&&s.includes(String(h));if("OPTIONS"===n||o)return;const r="mocked"===e?this.mockedRequests:this.otherRequests,i="mocked"===e?this.otherRequests:this.mockedRequests;if(t.requestId){const n=r.findIndex((e=>e.requestId===t.requestId));if(-1!==n)return r[n]={...r[n],...t},void(this.state.isOpen&&this.state.activeTab===e&&this.updateUI());const s=i.findIndex((e=>e.requestId===t.requestId));if(-1!==s){const e={...i[s],...t};return i.splice(s,1),r.unshift(e),r.length>50&&r.pop(),void(this.state.isOpen&&this.updateUI())}}r.unshift(t),r.length>50&&r.pop(),this.state.isOpen&&this.state.activeTab===e&&this.updateUI()}};function M(e,t){if("undefined"!=typeof window){if(window._mfm_intercepted)return;window._mfm_intercepted=!0}!function(e,t){const n=window.fetch;window.fetch=function(s,o={}){const r="string"==typeof s?s:s.url,a=String(o.method||(s instanceof Request?s.method:"GET")).toUpperCase().trim();if("OPTIONS"===a)return console.log(`[MockForMe] Filtered ${a} ${r} (isInternal=false)`),n(s,o);const u={url:r,method:a,requestHeaders:o.headers||(s instanceof Request?s.headers:{}),requestBody:o.body||(s instanceof Request?"{binary/stream}":null),queryParams:I(r)};try{const h=new URL(r,window.location.origin),{pathname:p,search:f}=h,g=q({url:r,method:a}),b=Math.random().toString(36).substring(7),x=Date.now();if(t!==d&&g){if(S.addRequest("mocked",{...u,requestId:b,pending:!0,startTime:x,rule:g}),"delay"===g.action)return new Promise(((e,t)=>{setTimeout((()=>{const t=n(s,o);t.then((e=>{const t=Date.now()-x;S.addRequest("mocked",{...u,requestId:b,status:e.status,pending:!1,duration:t})})).catch((e=>{const t=Date.now()-x;S.addRequest("mocked",{...u,requestId:b,status:0,pending:!1,duration:t})})),e(t)}),1e3*g.config.value)}));if("delay_and_redirect"===g.action)return new Promise(((e,t)=>{setTimeout((()=>{const t=n(g.config.redirectUrl,o);t.then((e=>{const t=Date.now()-x;S.addRequest("mocked",{...u,requestId:b,status:e.status,pending:!1,duration:t})})).catch((e=>{const t=Date.now()-x;S.addRequest("mocked",{...u,requestId:b,status:0,pending:!1,duration:t})})),e(t)}),1e3*g.config.value)}));if("delay_and_timeout"===g.action){const e=Number(g.config.value||0);if(0===e){const e=new AbortController,t=n(s,{...o,signal:e.signal});e.abort();const r=Date.now()-x;return S.addRequest("mocked",{...u,requestId:b,status:"Aborted",pending:!1,duration:r,aborted:!0}),t.catch((()=>Promise.reject(new Error("Fetch aborted by rules"))))}return new Promise(((t,n)=>{setTimeout((()=>{const e=Date.now()-x;S.addRequest("mocked",{...u,requestId:b,status:"Aborted",pending:!1,duration:e,aborted:!0}),n(new Error("Fetch timed out by rules"))}),1e3*e)}))}}const y=i(p,a),k=S.token||e;if(!y&&!g)return S.addRequest("other",{...u,requestId:b,pending:!0,startTime:x}),n(s,o).then((async e=>{const t=e.clone(),n=Date.now()-x;try{const s=await t.text();S.addRequest("other",{...u,requestId:b,status:e.status,responseHeaders:Object.fromEntries(e.headers.entries()),responseBody:s,pending:!1,duration:n})}catch(e){}return e})).catch((e=>{const t=Date.now()-x,n="AbortError"===e.name||e.message.includes("aborted"),s="TimeoutError"===e.name||e.message.includes("timed out"),o=!n&&!s;throw S.addRequest("other",{...u,requestId:b,status:n?"Aborted":s?"Timeout":"Error",responseHeaders:{},responseBody:e.message,pending:!1,duration:t,aborted:n,timeout:s,error:o}),e}));let E=r;g||(E=`${v()}${y.url}${f}`);let R={};if(!g){R={[l]:k,[c]:m,"x-mfm-adaptor":t};const e=_();e&&y._ack&&(R["x-mfm-key"]=`${e}-${y._ack}`),y?._ri_&&(R._ri_=y._ri_)}const T=s instanceof Request?s.headers:o.headers,M=new Headers(T||{});Object.entries(R).forEach((([e,t])=>{M.set(e,t)}));let I=o.body;if(!I&&s instanceof Request){const e=s.clone();"GET"!==e.method&&"HEAD"!==e.method&&(I=e.text())}let L={method:a,headers:M,credentials:"include",mode:"cors"};g&&(L.credentials=s instanceof Request&&s.credentials||o.credentials||"same-origin",L.mode=s instanceof Request&&s.mode||o.mode||"cors");const $=e=>(e&&(L.body=e),t===d?(S.addRequest("mocked",{...u,requestId:b,pending:!0,startTime:x}),(({actualUrl:e,url:t,method:n,headers:s,body:o,credentials:r,mode:i,rule:a})=>{const d=`${Date.now()}-${Math.random()}`,c=w(t);return new Promise(((t,l)=>{window.addEventListener("message",(function e(n){if(n.source!==window)return;const s=n.data;if("INTERCEPTED_RESPONSE"===s?.type&&s?.requestId===d){if(window.removeEventListener("message",e),s?.response?.error)return l(new Error(s.response.message));const{status:n,headers:o,body:r}=s.response;t(new Response(r,{status:n,headers:o}))}})),window.postMessage({type:"REQUEST_INTERCEPTED",requestId:d,payload:{actualUrl:e,url:c,method:n,headers:s,body:o,credentials:r,mode:i,rule:a}},"*")}))})({actualUrl:r,url:E,method:a,headers:Object.fromEntries(M.entries()),body:e,credentials:L.credentials,mode:L.mode,rule:g}).then((e=>(e.clone().text().then((t=>{const n=Date.now()-x;S.addRequest("mocked",{...u,requestId:b,status:e.status,responseHeaders:Object.fromEntries(e.headers.entries()),responseBody:t,pending:!1,duration:n})})),e))).catch((e=>{const t=Date.now()-x,n="AbortError"===e.name;throw S.addRequest("mocked",{...u,requestId:b,status:n?"Aborted":0,responseHeaders:{},responseBody:e.message,pending:!1,duration:t,aborted:n}),e}))):(S.addRequest("mocked",{...u,requestId:b,pending:!0,startTime:x}),n(E,L).then((e=>{const t=e.clone(),n=t.headers.get("content-type")||"",s=Date.now()-x,o=n=>(S.addRequest("mocked",{...u,requestId:b,status:e.status,responseHeaders:Object.fromEntries(t.headers.entries()),responseBody:n,pending:!1,duration:s}),new Response("string"==typeof n?n:JSON.stringify(n),{status:e.status,headers:t.headers}));return n.includes("application/json")?t.json().then(o):t.text().then(o)})).catch((e=>{console.warn("mockforme fetch interceptor error",e);const t=Date.now()-x,r="AbortError"===e.name;return S.addRequest("mocked",{...u,requestId:b,status:r?"Aborted":0,responseHeaders:{},responseBody:e.message,pending:!1,duration:t,aborted:r}),n(s,o)}))));return I instanceof Promise?I.then((e=>$(e))):$(I)}catch(e){return console.warn("mockforme fetch interceptor error",e),n(s,o)}}}(e,t),function(e,t){const n=window.XMLHttpRequest;window.XMLHttpRequest=class{constructor(){return this._xhr=new n,this._headers={},this._method=null,this._url=null,this._body=null,this._isMocked=!1,this._captured=!1,this._requestId=null,this._startTime=null,this._capture=(e,t,n,s={})=>{if(this._captured)return;this._captured=!0;const o=this._isMocked?"mocked":"other",r=this._startTime?Date.now()-this._startTime:0;console.log(`[MockForMe] XHR Capture: status=${e} method=${this._method} url=${this._url} duration=${r}ms`);const i=e=>{const t=`on${e}`;(this[t]||this._xhr[t])?.(),this._xhr.dispatchEvent(new Event(e))};if(S.addRequest(o,{url:this._url,method:this._method,requestHeaders:this._headers,requestBody:this._body,queryParams:I(this._url),requestId:this._requestId,status:e,responseBody:t,responseHeaders:n,pending:!1,duration:r,...s}),"Aborted"!==e)try{Object.defineProperty(this,"responseText",{value:t,configurable:!0}),Object.defineProperty(this,"response",{value:t,configurable:!0}),Object.defineProperty(this,"status",{value:Number(e)||0,configurable:!0}),Object.defineProperty(this,"statusText",{value:200==e?"OK":"",configurable:!0})}catch(e){console.warn("[MockForMe] Error setting XHR props",e)}Object.defineProperty(this,"readyState",{value:4,configurable:!0}),i("readystatechange"),"Aborted"===e||s.aborted?i("abort"):0===e||"Error"===e||s.error?i("error"):"Timeout"===e||s.timeout?i("timeout"):i("load")},new Proxy(this,{get:(e,t)=>{if(t in e)return e[t];const n=e._xhr[t];return"function"==typeof n?n.bind(e._xhr):n},set:(e,t,n)=>t in e?(e[t]=n,!0):(e._xhr[t]=n,!0)})}open(e,t,n=!0,s=null,o=null){this._method=(e||"").toUpperCase().trim();try{this._url=new URL(t,window.location.href).toString()}catch(e){this._url=t}return console.log(`[MockForMe] XHR.open: ${this._method} ${this._url}`),this._xhr._mockOriginalUrl=this._url,this._xhr._mockMethod=this._method,this._xhr.open(e,t,n,s,o)}setRequestHeader(e,t){return this._headers[e]=t,this._xhr.setRequestHeader(e,t)}send(s){const o=String(this._method||"").toUpperCase().trim();if(console.log(`[MockForMe] XHR send method=${o} url=${this._url}`),"OPTIONS"===o)return console.log("[MockForMe] XHR Skip OPTIONS"),this._xhr.send(s);this._body=s,this._requestId=Math.random().toString(36).substring(7),this._startTime=Date.now(),this._xhr.addEventListener("abort",(()=>{this._capture("Aborted","Request aborted",{},{aborted:!0})}),{once:!0}),this._xhr.addEventListener("error",(()=>{this._capture(0,"Network Error",{},{error:!0})}),{once:!0}),this._xhr.addEventListener("timeout",(()=>{this._capture("Timeout","Request timed out",{},{timeout:!0})}),{once:!0});try{const o=new URL(this._url),{pathname:r,search:a}=o,u=q({url:this._url,method:this._method});u&&(this._isMocked=!0,S.addRequest("mocked",{url:this._url,method:this._method,requestHeaders:this._headers,requestBody:this._body,queryParams:I(this._url),requestId:this._requestId,pending:!0,startTime:this._startTime,rule:u}));const h=S.token||e;if(t!==d&&u){if("delay"===u.action){const e=Number(u.config.value||0);return setTimeout((()=>{this._xhr.addEventListener("load",(()=>{this._capture(this._xhr.status,this._xhr.responseText,this._xhr.getAllResponseHeaders())}),{once:!0}),this._xhr.send(this._body)}),1e3*e)}if("delay_and_redirect"===u.action){const e=Number(u.config.value||0);return setTimeout((()=>{this._xhr.open(this._method,u.config.redirectUrl,!0),this._xhr.addEventListener("load",(()=>{this._capture(this._xhr.status,this._xhr.responseText,this._xhr.getAllResponseHeaders())}),{once:!0}),this._xhr.send(this._body)}),1e3*e)}if("delay_and_timeout"===u.action){const e=Number(u.config.value||0);return 0===e?(this._capture("Aborted","Request aborted by rules",{},{aborted:!0}),void this._xhr.abort()):setTimeout((()=>{this._capture("Aborted","Request timed out by rules",{},{aborted:!0}),this._xhr.abort()}),1e3*e)}}const p=i(r,this._method);if(!p&&!u)return console.log("[MockForMe] XHR No Match:",{pathname:r,method:this._method}),this._isMocked=!1,S.addRequest("other",{url:this._url,method:this._method,requestHeaders:this._headers,requestBody:this._body,queryParams:I(this._url),requestId:this._requestId,pending:!0,startTime:this._startTime}),this._xhr.addEventListener("load",(()=>{this._capture(this._xhr.status,this._xhr.responseText,this._xhr.getAllResponseHeaders())}),{once:!0}),this._xhr.send(s);console.log("[MockForMe] XHR Matched:",{pathname:r,match:p}),this._isMocked=!0;let f=this._url;u||(f=`${v()}${p.url}${a}`);let g={};if(!u){g={[l]:h,[c]:m,"x-mfm-adaptor":t};const e=_();e&&p._ack&&(g["x-mfm-key"]=`${e}-${p._ack}`),p?._ri_&&(g._ri_=p._ri_)}const b={...this._headers,...g};if(S.addRequest("mocked",{url:this._url,method:this._method,requestHeaders:this._headers,requestBody:this._body,queryParams:I(this._url),requestId:this._requestId,pending:!0,startTime:this._startTime}),t===d)(({actualUrl:e,url:t,method:n,headers:s,body:o,onSuccess:r,onError:i,rule:a})=>{const d=`${Date.now()}-${Math.random()}`,c=w(t);window.addEventListener("message",(function e(t){if(t.source!==window)return;const n=t.data;if("INTERCEPTED_RESPONSE"===n.type&&n.requestId===d){if(window.removeEventListener("message",e),n.response?.error)return i?.(n.response.message);const{body:t,status:s,headers:o}=n.response;r?.({body:t,status:s,headers:o})}})),window.postMessage({type:"REQUEST_INTERCEPTED",requestId:d,payload:{actualUrl:e,url:c,method:n,headers:s,body:o,credentials:"same-origin",mode:"cors",rule:a}},"*")})({actualUrl:this._url,url:f,method:this._method,headers:b,body:this._body,rule:u,onSuccess:({body:e,status:t,headers:n})=>{this._capture(t,e,n||{})},onError:e=>{this._capture(0,e.message||"XHR Error",{},{error:!0})}});else{const e=new n;e.open(this._method,f,!0);for(const t in b)e.setRequestHeader(t,b[t]);e.withCredentials=this.withCredentials,e.onload=()=>{this._capture(e.status,e.responseText,e.getAllResponseHeaders())},e.onerror=()=>{this._capture(0,"Network Error",{},{error:!0})},e.ontimeout=()=>{this._capture("Timeout","Request timed out",{},{timeout:!0})},e.send(this._body)}}catch(e){if(console.error("[MockForMe] XHR Interception Error",e),!this._xhr.readyState||1===this._xhr.readyState)return this._xhr.send(s)}}}}(e,t)}function I(e){try{const t=new URL(e,window.location.origin).searchParams;return Object.fromEntries(t.entries())}catch{return{}}}const L=(t,n=null,s=a)=>{if(e())return;if(s===a)try{t&&("undefined"!=typeof localStorage&&localStorage.removeItem("mockforme-token"),S.token=t,S.isAuthenticated=!0),!t&&S.token&&(t=S.token),S.onAuthSuccess=(e,t,n)=>{o(t),y(n),S.mappings=t,S.rules=n?._rules||[]}}catch(e){console.log("Error in showing mockforme widget",e)}n||={mappings:[],_o:null,mk:null,_mck:null,_rules:[]};const{mappings:d=[],_o:u,mk:h,_mck:f,_rules:g=[]}=n;return o(d),y({_o:u,mk:h,_mck:f,_rules:g}),{run:(e,n=()=>{})=>{M(t,s),u&&h?(S.mappings=d,S.rules=g,e?.(d,{_o:u,mk:h,_mck:f,_rules:g})):t&&function(t,n,s,r){E({method:"get",url:p,async:!1,headers:{[l]:t,[c]:m,"x-mfm-adaptor":n}},(t=>{if(t)try{const{di:r,iv:i,_o:a,_mck:d,mk:c,r:l}=t,m=R({di:r,iv:i},a);y({_o:a,mk:c,_mck:d,_rules:l}),m&&(o(m),n=m,s={_o:a,mk:c,_mck:d,_rules:l},S.mappings=n,S.rules=s?._rules||[],e?.(n,s))}catch(e){return void r(new Error("Unable to fetch mocked apis"))}var n,s}),(e=>{console.log("Error in loading mocked apis"),r(e)})).request()}(t,s,0,n)},checkIfApiToBeMocked:i,getMappings:r,doFetchMappings:(e,n)=>{T(t||S.token,s,((t,n)=>{S.mappings=t,S.rules=n?._rules||[],e?.(t,n)}),n)}}},$=e();$||(globalThis.mockforme=L);let O=L;$&&(O=e=>({run:()=>{}}));const C=O;export{C as mockforme};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.mockforme=t():e.mockforme=t()}(this,(()=>(()=>{"use strict";var e={d:(t,o)=>{for(var r in o)e.o(o,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:o[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},t={};e.d(t,{mockforme:()=>I});const o=()=>"undefined"!=typeof process&&null!=process.versions?.node,r=e=>{try{return e?e.toLowerCase():e}catch(e){return console.log(e),null}},n=(e,t)=>{const o=e.split("/"),r=t.split("/");if(o.length!==r.length)return!1;for(let e=0;e<o.length;e++){const t=o[e];if(t!==r[e]&&":any"!==t)return!1}return!0};let s=[];function i(e){s=e}function a(){return s}function c(e,t="get"){for(const o of s)if(r(o.apiMethod)===r(t)&&(o.apiEndpoint===e||n(o.apiEndpoint,e))){const t={url:e,method:o.apiMethod,_ack:o._ack||null};return o._ri_&&(t._ri_=o._ri_),t}return null}const d="JAVASCRIPT",l="CHROME_EXTENSION",u="mfmver",h="mockforme",f="4.2.8",m="https://api.mockforme.com",p=`${m}/mockforme`,y=`${m}/gateway/3f4eae522b`;let _=null,g=null,w=null,b=[];function v({_o:e,mk:t,_mck:o,_rules:r}){_=e,g=t,w=o,b=r}function E(){return b}function x(){return`${p}/${_}/${g}`}function k(){return w}const R=e=>{try{return new URL(e,window.location.origin).toString()}catch{return e}};function O({url:e,method:t}){try{const t=E();if(!Array.isArray(t)||0===t.length)return null;const o=globalThis.location?.origin||"http://localhost";for(const r of t){const t=r.rule?.URL;if(!t)continue;const{condition:n}=t;if(!n)continue;let s="";switch(t.type){case"URL":{let t;try{t=new URL(e,o),s=t.pathname}catch{s=e}break}case"QUERY":{let t;try{t=new URL(e,o)}catch{t=null}t&&(s=t.searchParams.get(n.key)||"");break}case"BODY":case"HEADERS":s="";break;default:continue}let i=!1;switch(n.operator){case"contains":i=s.includes(n.value);break;case"equal":case"equals":i=s===n.value;break;case"regexp":try{let e=n.value;if(e.startsWith("/")&&e.lastIndexOf("/")>0){const t=e.lastIndexOf("/"),o=e.slice(1,t),r=e.slice(t+1);i=new RegExp(o,r).test(s)}else i=new RegExp(e).test(s)}catch{i=!1}}if(i){const e=n.activeAction;return{action:e,config:n.actions?.[e]||{}}}}return null}catch(e){return console.error("[mockforme] checkIfRulesToBeApplied error",e),null}}function S(e,t){!function(e,t){const o=window.fetch;window.fetch=function(r,n={}){const s="string"==typeof r?r:r.url;try{const i=new URL(s,window.location.origin),{pathname:a,search:d}=i;let m="get";n&&n.method?m=n.method:r instanceof Request&&r.method&&(m=r.method),m=m.toLowerCase();const p=O({url:s,method:m});if(t!==l&&p){if("delay"===p.action)return new Promise(((e,t)=>{setTimeout((()=>{e(o(r,n))}),1e3*p.config.value)}));if("delay_and_redirect"===p.action)return new Promise(((e,t)=>{setTimeout((()=>{e(o(p.config.redirectUrl,n))}),1e3*p.config.value)}));if("delay_and_timeout"===p.action){if(0===p.config.value){const e=new AbortController,t=o(r,{...n,signal:e.signal});return e.abort(),t.catch((()=>Promise.reject(new Error("Fetch aborted by rules"))))}return new Promise(((e,t)=>{setTimeout((()=>{t(new Error("Fetch timed out by rules"))}),1e3*p.config.value)}))}}const y=c(a,m);if(!y&&!p)return o(r,n);let _=s;p||(_=`${x()}${y.url}${d}`);let g={};if(!p){g={[h]:e,[u]:f,"x-mfm-adaptor":t};const o=k();o&&y._ack&&(g["x-mfm-key"]=`${o}-${y._ack}`),y?._ri_&&(g._ri_=y._ri_)}const w=r instanceof Request?r.headers:n.headers,b=new Headers(w||{});Object.entries(g).forEach((([e,t])=>{b.set(e,t)}));let v=n.body;if(!v&&r instanceof Request){const e=r.clone();"GET"!==e.method&&"HEAD"!==e.method&&(v=e.text())}let E={method:m,headers:b,credentials:"include",mode:"cors"};p&&(E.credentials=r instanceof Request&&r.credentials||n.credentials||"same-origin",E.mode=r instanceof Request&&r.mode||n.mode||"cors");const S=e=>(e&&(E.body=e),t===l?(({actualUrl:e,url:t,method:o,headers:r,body:n,credentials:s,mode:i,rule:a})=>{const c=`${Date.now()}-${Math.random()}`,d=R(t);return new Promise(((t,l)=>{window.addEventListener("message",(function e(o){if(o.source!==window)return;const r=o.data;if("INTERCEPTED_RESPONSE"===r?.type&&r?.requestId===c){if(window.removeEventListener("message",e),r?.response?.error)return l(new Error(r.response.message));const{status:o,headers:n,body:s}=r.response;t(new Response(s,{status:o,headers:n}))}})),window.postMessage({type:"REQUEST_INTERCEPTED",requestId:c,payload:{actualUrl:e,url:d,method:o,headers:r,body:n,credentials:s,mode:i,rule:a}},"*")}))})({actualUrl:s,url:_,method:m,headers:Object.fromEntries(b.entries()),body:e,credentials:E.credentials,mode:E.mode,rule:p}):fetch(_,E).then((e=>{const t=e.clone();return(t.headers.get("content-type")||"").includes("application/json")?t.json().then((o=>new Response(JSON.stringify(o),{status:e.status,headers:t.headers}))):t.text().then((o=>new Response(o,{status:e.status,headers:t.headers})))})).catch((e=>(console.warn("mockforme fetch interceptor error",e),o(r,n)))));return v instanceof Promise?v.then((e=>S(e))):S(v)}catch(e){return console.warn("mockforme fetch interceptor error",e),o(r,n)}}}(e,t),function(e,t){const o=window.XMLHttpRequest;window.XMLHttpRequest=class{constructor(){return this._xhr=new o,this._headers={},this._method=null,this._url=null,this._body=null,new Proxy(this,{get:(e,t)=>{if(t in e)return e[t];const o=e._xhr[t];return"function"==typeof o?o.bind(e._xhr):o},set:(e,t,o)=>t in e?(e[t]=o,!0):(e._xhr[t]=o,!0)})}open(e,t,o=!0,r=null,n=null){return this._method=e.toUpperCase(),this._url=new URL(t,window.location.href).toString(),this._xhr._mockOriginalUrl=this._url,this._xhr._mockMethod=this._method,this._xhr.open(e,t,o,r,n)}setRequestHeader(e,t){return this._headers[e]=t,this._xhr.setRequestHeader(e,t)}send(r){this._body=r;try{const n=new URL(this._url),{pathname:s,search:i}=n,a=O({url:this._url,method:this._method});if(t!==l&&a){if("delay"===a.action)return setTimeout((()=>this._xhr.send(r)),1e3*a.config.value);if("delay_and_redirect"===a.action)return setTimeout((()=>{this._xhr.open(this._method,a.config.redirectUrl,!0),this._xhr.send(r)}),1e3*a.config.value);if("delay_and_timeout"===a.action)return 0===a.config.value?(this._xhr.open(this._method,this._url,!0),this._xhr.send(r),this._xhr.abort(),void("function"==typeof this.onerror&&this.onerror(new Error("XHR aborted by rules")))):setTimeout((()=>{this._xhr.abort(),"function"==typeof this.onerror&&this.onerror(new Error("XHR timed out by rules"))}),1e3*a.config.value)}const d=c(s,this._method);if(!d&&!a)return this._xhr.send(r);let m=this._url;a||(m=`${x()}${d.url}${i}`);let p={};if(!a){p={[h]:e,[u]:f,"x-mfm-adaptor":t};const o=k();o&&d._ack&&(p["x-mfm-key"]=`${o}-${d._ack}`),d?._ri_&&(p._ri_=d._ri_)}const y={...this._headers,...p};if(t===l)(({actualUrl:e,url:t,method:o,headers:r,body:n,onSuccess:s,onError:i,rule:a})=>{const c=`${Date.now()}-${Math.random()}`,d=R(t);window.addEventListener("message",(function e(t){if(t.source!==window)return;const o=t.data;if("INTERCEPTED_RESPONSE"===o.type&&o.requestId===c){if(window.removeEventListener("message",e),o.response?.error)return i?.(o.response.message);const{body:t,status:r,headers:n}=o.response;s?.({body:t,status:r,headers:n})}})),window.postMessage({type:"REQUEST_INTERCEPTED",requestId:c,payload:{actualUrl:e,url:d,method:o,headers:r,body:n,credentials:"same-origin",mode:"cors",rule:a}},"*")})({actualUrl:this._url,url:m,method:this._method,headers:y,body:this._body,rule:a,onSuccess:({body:e,status:t})=>{Object.defineProperty(this,"responseText",{value:e}),Object.defineProperty(this,"status",{value:t}),Object.defineProperty(this,"readyState",{value:4}),this.onreadystatechange?.(),this.onload?.(),this._xhr.dispatchEvent(new Event("readystatechange")),this._xhr.dispatchEvent(new Event("load"))},onError:e=>{Object.defineProperty(this,"readyState",{value:4}),this.onerror?.(new Error(e.message||"XHR mock error")),this._xhr.dispatchEvent(new Event("readystatechange")),this._xhr.dispatchEvent(new Event("error"))}});else{const e=new o;e.open(this._method,m,!0);for(const t in y)e.setRequestHeader(t,y[t]);e.withCredentials=this.withCredentials,e.onload=()=>{Object.defineProperty(this,"responseText",{value:e.responseText}),Object.defineProperty(this,"status",{value:e.status}),Object.defineProperty(this,"readyState",{value:4}),this.onreadystatechange?.(),this.onload?.(),this._xhr.dispatchEvent(new Event("readystatechange")),this._xhr.dispatchEvent(new Event("load"))},e.onerror=()=>{Object.defineProperty(this,"readyState",{value:4}),this.onerror?.(),this._xhr.dispatchEvent(new Event("readystatechange")),this._xhr.dispatchEvent(new Event("error"))},e.send(this._body)}}catch(e){console.error("[mockforme][XHR] interception error",e)}}}}(e,t)}const T=function(e,t,r){const n=o();var s;function i(){if(4==s.readyState)if(s.status.toString().match(/^20[0-9]$/)){var e=function(){var e=s.getResponseHeader("Content-Type"),t=s.responseText;if(e){var o=e.split(";");try{return"application/json"===o[0]?JSON.parse(t):t}catch(e){throw"Unable to convert response header"}}}();t.call(this,e,s)}else r.call(this,s.responseText,s)}function a(e,t){var o=[];for(var r in e)if(e.hasOwnProperty(r)){var n=t?t+"["+r+"]":r,s=e[r];o.push("object"==typeof s?a(s,n):encodeURIComponent(n)+"="+encodeURIComponent(s))}return o.join("&")}return n||(window.XMLHttpRequest?s=new XMLHttpRequest:window.ActiveXObject&&(s=new ActiveXObject("Microsoft.XMLHTTP"))),{request:function(){if(!n){if(window.XMLHttpRequest)s.onload=i;else{if(!window.ActiveXObject)throw"unable to process ajax";s.onreadystatechange=i}var t=a(e.params);if("get"==e.method.toLowerCase()&&"object"==typeof e.params){if(-1==e.url.indexOf("?"))e.url+="?";else{var o=e.url.split("?");o[1]&&o[1].split("=")[1]&&(e.url+="&")}e.url+=t}e.hasOwnProperty("async")||(e.async=!0),s.open(e.method,e.url,e.async),e.headers&&function(e){for(let t in e)s.setRequestHeader(t,e[t])}(e.headers),s.send(t)}}}};function j({di:e,iv:t},o){var r;const n=function(e,t){const o=t.length;return e.split("").map(((e,r)=>String.fromCharCode(e.charCodeAt(0)^t.charCodeAt(r%o)))).join("")}((r=e,"undefined"!=typeof Buffer?Buffer.from(r,"base64").toString("utf8"):decodeURIComponent(escape(atob(r)))),o+t);return JSON.parse(n)}const P=(e,t=null,r=d)=>{if(o())return;if(r===d)try{(()=>{const e=()=>{if(!window.mockforme)return;const e=JSON.parse(localStorage.getItem("mockforme-dot-pos")||"{}"),t=document.createElement("div");t.id="mockforme-dot",Object.assign(t.style,{position:"fixed",bottom:(e.bottom??20)+"px",right:(e.right??20)+"px",width:"42px",height:"42px",borderRadius:"50%",overflow:"hidden",cursor:"grab",zIndex:999999,boxShadow:"0 0 10px rgba(0,0,0,0.25)",backgroundColor:"#fff",display:"flex",alignItems:"center",justifyContent:"center"});const o=document.createElement("img");o.src="https://dashboard.mockforme.com/public/assets/images/icon.png",o.style.objectFit="cover",t.appendChild(o),document.body.appendChild(t);const r=document.createElement("div");r.id="mockforme-widget",r.innerText="MockForMe Enabled",Object.assign(r.style,{position:"fixed",padding:"8px 12px",background:"#2563eb",color:"#fff",fontSize:"13px",fontFamily:"Inter, sans-serif",borderRadius:"8px",bottom:(e.bottom??20)+50+"px",right:(e.right??20)+"px",boxShadow:"0 4px 10px rgba(0,0,0,0.2)",zIndex:999999,display:"none",whiteSpace:"nowrap"}),document.body.appendChild(r),t.addEventListener("click",(e=>{e.stopPropagation(),r.style.display="none"===r.style.display?"block":"none"})),document.addEventListener("click",(()=>{r.style.display="none"}));let n=!1,s=0,i=0;t.addEventListener("mousedown",(e=>{n=!0,t.style.cursor="grabbing";const o=t.getBoundingClientRect();s=e.clientX-o.left,i=e.clientY-o.top,e.preventDefault()})),document.addEventListener("mousemove",(e=>{if(!n)return;const o=e.clientX-s,a=e.clientY-i,c=window.innerHeight-(a+t.offsetHeight),d=window.innerWidth-(o+t.offsetWidth);t.style.bottom=c+"px",t.style.right=d+"px",r.style.bottom=c+50+"px",r.style.right=d+"px"})),document.addEventListener("mouseup",(()=>{if(!n)return;n=!1,t.style.cursor="grab";const e=parseInt(t.style.bottom),o=parseInt(t.style.right);localStorage.setItem("mockforme-dot-pos",JSON.stringify({bottom:e,right:o}))}))};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",e):e()})()}catch(e){console.log("Error in showing mockforme widget")}t||={mappings:[],_o:null,mk:null,_mck:null,_rules:[]};const{mappings:n=[],_o:s,mk:l,_mck:m,_rules:p=[]}=t;return i(n),v({_o:s,mk:l,_mck:m,_rules:p}),{run:(t,o=()=>{})=>{S(e,r),s&&l?t(a(),{_o:s,mk:l,_mck:m,_rules:p}):function(e,o,r,n){T({method:"get",url:y,async:!1,headers:{[h]:e,[u]:f,"x-mfm-adaptor":o}},(e=>{if(e)try{const{di:n,iv:s,_o:a,_mck:c,mk:d,r:l}=e,u=j({di:n,iv:s},a);v({_o:a,mk:d,_mck:c,_rules:l}),u&&(i(u),o=u,r={_o:a,mk:d,_mck:c,_rules:l},t?.(o,r))}catch(e){return void n(new Error("Unable to fetch mocked apis"))}var o,r}),(e=>{console.log("Error in loading mocked apis"),n(e)})).request()}(e,r,0,o)},checkIfApiToBeMocked:c,getMappings:a,doFetchMappings:(t,o)=>{!function(e,t,o,r){fetch(y,{method:"GET",headers:{[h]:e,[u]:f,"x-mfm-adaptor":t}}).then((e=>{if(!e.ok)throw e;return e.json()})).then((e=>{if(e){const{di:t,iv:r,_o:n,_mck:s,mk:a,r:c}=e,d=j({di:t,iv:r},n);v({_o:n,mk:a,_mck:s,_rules:c}),d&&(i(d),o(d,{_o:n,mk:a,_mck:s,_rules:c}))}})).catch((e=>{console.error("Error in loading mocked APIs:",e),r(e)}))}(e,r,((e,o)=>{t?.(e,o)}),o)}}},C=o();C||(globalThis.mockforme=P);let L=P;C&&(L=e=>({run:()=>{}}));const I=L;return t.mockforme})()));
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.mockforme=t():e.mockforme=t()}(this,(()=>(()=>{"use strict";var e={d:(t,n)=>{for(var s in n)e.o(n,s)&&!e.o(t,s)&&Object.defineProperty(t,s,{enumerable:!0,get:n[s]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},t={};e.d(t,{mockforme:()=>U});const n=()=>"undefined"!=typeof process&&null!=process.versions?.node,s=e=>{try{return e?e.toLowerCase():e}catch(e){return console.log(e),null}},o=(e,t)=>{const n=e.split("/"),s=t.split("/");if(n.length!==s.length)return!1;for(let e=0;e<n.length;e++){const t=n[e];if(t!==s[e]&&":any"!==t)return!1}return!0};let r=[];function i(e){r=e}function a(){return r}function d(e,t="get"){const n=e=>e.startsWith("/")?e:`/${e}`,i=n(e);for(const a of r)if(s(a.apiMethod)===s(t)){const s=n(a.apiEndpoint);if(s===i||o(s,i)){console.log(`[MockForMe] Match Found: ${t} ${e} -> ${a.apiEndpoint}`);const n={url:e,method:a.apiMethod,_ack:a._ack||null};return a._ri_&&(n._ri_=a._ri_),n}}return null}const c="JAVASCRIPT",l="CHROME_EXTENSION",m="mfmver",u="mockforme",h="4.2.8",p="https://api.mockforme.com",f=`${p}/mockforme`,g=`${p}/gateway/3f4eae522b`;let b=null,x=null,y=null,k=[];function v({_o:e,mk:t,_mck:n,_rules:s}){b=e,x=t,y=n,k=s}function _(){return k}function w(){return`${f}/${b}/${x}`}function q(){return y}const E=e=>{try{return new URL(e,window.location.origin).toString()}catch{return e}};function R({url:e,method:t}){try{const t=_();if(!Array.isArray(t)||0===t.length)return null;const n=globalThis.location?.origin||"http://localhost";for(const s of t){const t=s.rule?.URL;if(!t)continue;const{condition:o}=t;if(!o)continue;let r="";switch(t.type){case"URL":{let t;try{t=new URL(e,n),r=t.pathname}catch{r=e}break}case"QUERY":{let t;try{t=new URL(e,n)}catch{t=null}t&&(r=t.searchParams.get(o.key)||"");break}case"BODY":case"HEADERS":r="";break;default:continue}let i=!1;switch(o.operator){case"contains":i=r.includes(o.value);break;case"equal":case"equals":i=r===o.value;break;case"regexp":try{let e=o.value;if(e.startsWith("/")&&e.lastIndexOf("/")>0){const t=e.lastIndexOf("/"),n=e.slice(1,t),s=e.slice(t+1);i=new RegExp(n,s).test(r)}else i=new RegExp(e).test(r)}catch{i=!1}}if(i){const e=o.activeAction;return{action:e,config:o.actions?.[e]||{}}}}return null}catch(e){return console.error("[mockforme] checkIfRulesToBeApplied error",e),null}}const T=function(e,t,s){const o=n();var r;function i(){if(4==r.readyState)if(r.status.toString().match(/^20[0-9]$/)){var e=function(){var e=r.getResponseHeader("Content-Type"),t=r.responseText;if(e){var n=e.split(";");try{return"application/json"===n[0]?JSON.parse(t):t}catch(e){throw"Unable to convert response header"}}}();t.call(this,e,r)}else s.call(this,r.responseText,r)}function a(e,t){var n=[];for(var s in e)if(e.hasOwnProperty(s)){var o=t?t+"["+s+"]":s,r=e[s];n.push("object"==typeof r?a(r,o):encodeURIComponent(o)+"="+encodeURIComponent(r))}return n.join("&")}return o||(window.XMLHttpRequest?r=new XMLHttpRequest:window.ActiveXObject&&(r=new ActiveXObject("Microsoft.XMLHTTP"))),{request:function(){if(!o){if(window.XMLHttpRequest)r.onload=i;else{if(!window.ActiveXObject)throw"unable to process ajax";r.onreadystatechange=i}var t=a(e.params);if("get"==e.method.toLowerCase()&&"object"==typeof e.params){if(-1==e.url.indexOf("?"))e.url+="?";else{var n=e.url.split("?");n[1]&&n[1].split("=")[1]&&(e.url+="&")}e.url+=t}e.hasOwnProperty("async")||(e.async=!0),r.open(e.method,e.url,e.async),e.headers&&function(e){for(let t in e)r.setRequestHeader(t,e[t])}(e.headers),r.send(t)}}}};function S({di:e,iv:t},n){var s;const o=function(e,t){const n=t.length;return e.split("").map(((e,s)=>String.fromCharCode(e.charCodeAt(0)^t.charCodeAt(s%n)))).join("")}((s=e,"undefined"!=typeof Buffer?Buffer.from(s,"base64").toString("utf8"):decodeURIComponent(escape(atob(s)))),n+t);return JSON.parse(o)}function M(e,t,n,s){fetch(g,{method:"GET",headers:{[u]:e,[m]:h,"x-mfm-adaptor":t}}).then((e=>{if(!e.ok)throw e;return e.json()})).then((e=>{if(e){const{di:t,iv:s,_o:o,_mck:r,mk:a,r:d}=e,c=S({di:t,iv:s},o);v({_o:o,mk:a,_mck:r,_rules:d}),c&&(i(c),n(c,{_o:o,mk:a,_mck:r,_rules:d}))}})).catch((e=>{console.error("Error in loading mocked APIs:",e),s(e)}))}const I=new class{constructor(e={}){n()||(this.token=e.token||("undefined"!=typeof localStorage?localStorage.getItem("mockforme-token"):null),this.isAuthenticated=!!this.token,this.onAuthSuccess=e.onAuthSuccess||(()=>{}),this.mappings=e.mappings||[],this.rules=e.rules||[],this.mockedRequests=[],this.otherRequests=[],this.state={isOpen:!1,activeTab:"mappings",selectedRequest:null,activeRequestTab:"response",lastError:null,searchQuery:""},"undefined"!=typeof document&&("loading"===document.readyState?document.addEventListener("DOMContentLoaded",(()=>this.init())):this.init()))}init(){document.getElementById("mockforme-root")||(this.createStyles(),this.render())}createStyles(){if(document.getElementById("mockforme-styles"))return;const e=document.createElement("style");e.id="mockforme-styles",e.innerHTML="\n #mockforme-root {\n font-family: 'Inter', system-ui, -apple-system, sans-serif;\n z-index: 999999;\n position: fixed;\n }\n .mfm-bubble {\n position: fixed;\n bottom: 20px;\n right: 20px;\n height: 42px;\n padding: 4px 8px;\n border-radius: 24px;\n box-shadow: 0 4px 12px rgba(0,0,0,0.15);\n cursor: pointer;\n z-index: 999999;\n background: white;\n display: flex;\n align-items: center;\n gap: 8px;\n transition: transform 0.2s;\n border: 1px solid #eee;\n }\n .mfm-bubble:hover { transform: scale(1.05); }\n .mfm-bubble img { width: 32px; height: 32px; border-radius: 50%; object-fit: cover; }\n \n .mfm-refresh-icon {\n width: 32px;\n height: 32px;\n background: #f3f4f6;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #2563eb;\n font-size: 18px;\n transition: background 0.2s;\n }\n .mfm-refresh-icon:hover { background: #e5e7eb; }\n .mfm-refresh-icon.loading { animation: mfm-spin 1s linear infinite; }\n @keyframes mfm-spin { 100% { transform: rotate(360deg); } }\n\n .mfm-bottomsheet {\n position: fixed;\n bottom: 0;\n left: 0;\n right: 0;\n background: white;\n border-top-left-radius: 16px;\n border-top-right-radius: 16px;\n box-shadow: 0 -4px 20px rgba(0,0,0,0.15);\n padding: 20px;\n z-index: 999999;\n height: 90vh;\n max-width: 500px;\n margin: 0 auto;\n display: flex;\n flex-direction: column;\n transition: transform 0.3s ease-out;\n transform: translateY(100%);\n visibility: hidden;\n overflow-y: auto;\n }\n .mfm-bottomsheet.open { transform: translateY(0); visibility: visible; }\n \n .mfm-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 20px;\n padding-bottom: 10px;\n border-bottom: 1px solid #eee;\n }\n .mfm-title-group { display: flex; align-items: center; gap: 10px; }\n .mfm-title { font-size: 18px; font-weight: 600; color: #111; }\n .mfm-delete-token-btn { \n background: #fee2e2; \n color: #dc2626; \n font-size: 13px; \n padding: 4px 12px; \n border-radius: 20px; \n cursor: pointer; \n display: flex;\n align-items: center;\n gap: 6px;\n border: none;\n font-weight: 500;\n transition: background 0.2s;\n }\n .mfm-delete-token-btn:hover { background: #fecaca; }\n .mfm-header-actions { display: flex; align-items: center; gap: 10px; }\n .mfm-close { background: none; border: none; font-size: 24px; cursor: pointer; color: #666; }\n /* Login Form */\n .mfm-logo-container { text-align: center; padding: 30px 0; width: 100%; display: flex; justify-content: center; }\n .mfm-logo { width: 150px; height: auto; }\n .mfm-link { color: #2563eb; text-decoration: none; font-size: 14px; margin-top: 5px; cursor: pointer; display: inline-block; }\n .mfm-link:hover { text-decoration: underline; }\n .mfm-form { display: flex; flex-direction: column; gap: 10px; }\n .mfm-input {\n padding: 12px;\n border: 1px solid #ddd;\n border-radius: 8px;\n font-size: 16px;\n outline: none;\n transition: border-color 0.2s;\n }\n .mfm-input:focus { border-color: #2563eb; }\n .mfm-error { color: #dc2626; font-size: 13px; margin-top: -5px; }\n .mfm-btn {\n padding: 12px;\n background: #2563eb;\n color: white;\n border: none;\n border-radius: 8px;\n font-size: 16px;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.2s;\n }\n .mfm-btn:hover { background: #1d4ed8; }\n .mfm-btn:disabled { background: #9ca3af; cursor: not-allowed; }\n\n .mfm-tabs { display: flex; border-bottom: 1px solid #eee; margin-bottom: 15px; }\n .mfm-tab {\n padding: 10px 20px;\n cursor: pointer;\n color: #666;\n border-bottom: 2px solid transparent;\n font-weight: 500;\n }\n .mfm-tab.active { color: #2563eb; border-bottom-color: #2563eb; }\n \n .mfm-list {\n flex: 1;\n overflow-y: auto;\n min-height: 200px;\n max-height: 60vh;\n }\n .mfm-list-item {\n padding: 10px;\n border-bottom: 1px solid #f3f4f6;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: space-between;\n font-size: 14px;\n min-height: 52px;\n box-sizing: border-box;\n }\n .mfm-list-item:hover { background: #f9fafb; }\n .mfm-method { \n font-weight: bold; \n padding: 4px 8px; \n border-radius: 4px; \n margin-right: 10px;\n font-size: 12px;\n }\n .GET { background: #dbfcfe; color: #006064; }\n .POST { background: #dcfce7; color: #14532d; }\n .PUT { background: #fef9c3; color: #713f12; }\n .DELETE { background: #fee2e2; color: #7f1d1d; }\n .PATCH { background: #f3e8ff; color: #581c87; }\n .RULE { background: #f3f4f6; color: #374151; }\n\n /* Search & Actions */\n .mfm-actions-bar { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }\n .mfm-search-input { flex: 1; padding: 8px 12px; border: 1px solid #ddd; border-radius: 6px; font-size: 14px; outline: none; }\n .mfm-search-input:focus { border-color: #2563eb; }\n .mfm-icon-btn { background: none; border: none; font-size: 18px; cursor: pointer; color: #666; display: flex; align-items: center; justify-content: center; padding: 4px; border-radius: 4px; }\n .mfm-icon-btn:hover { background: #f3f4f6; color: #333; }\n .mfm-icon-btn.refresh { color: #2563eb; padding: 0; height: 30px; width:30px; border-radius: 50%; }\n .mfm-icon-btn.refresh.loading { animation: mfm-spin 1s linear infinite; }\n .mfm-icon-btn.delete { color: #dc2626; }\n\n .mfm-url { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n .mfm-status { font-weight: bold; margin-left: 10px; }\n .status-2xx { color: #16a34a; }\n .status-4xx { color: #dc2626; }\n .status-5xx { color: #ea580c; }\n .status-aborted, .status-timeout, .status-error { color: #dc2626; font-size: 11px; font-weight: 500; }\n\n .mfm-rule-tag {\n font-size: 9px;\n padding: 2px 4px;\n border-radius: 4px;\n background: #fef3c7;\n color: #92400e;\n border: 1px solid #fde68a;\n margin-right: 6px;\n text-transform: uppercase;\n font-weight: bold;\n }\n\n .mfm-detail-view { display: flex; flex-direction: column; height: 100%; }\n .mfm-detail-actions { margin-bottom: 10px; }\n .mfm-back-btn { background: none; border: none; color: #2563eb; cursor: pointer; font-size: 14px; display: flex; align-items: center; gap: 4px; padding: 0;}\n \n .mfm-code-block {\n background: #f8fafc;\n padding: 10px;\n border-radius: 8px;\n overflow-x: auto;\n font-family: monospace;\n font-size: 12px;\n white-space: pre-wrap;\n word-break: break-all;\n max-height: 300px;\n border: 1px solid #e2e8f0;\n }\n .section-title { font-size: 14px; font-weight: 600; margin: 10px 0 5px; color: #333; }\n\n /* Snackbar */\n .mfm-snackbar {\n position: fixed;\n bottom: 80px;\n left: 50%;\n transform: translateX(-50%) translateY(20px);\n background: #333;\n color: white;\n padding: 10px 20px;\n border-radius: 8px;\n font-size: 14px;\n z-index: 1000000;\n opacity: 0;\n transition: opacity 0.3s, transform 0.3s;\n pointer-events: none;\n }\n .mfm-snackbar.show { opacity: 1; transform: translateX(-50%) translateY(0); }\n\n /* Confirm Dialog */\n .mfm-modal-overlay {\n position: fixed;\n top: 0; left: 0; right: 0; bottom: 0;\n background: rgba(0,0,0,0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000001;\n opacity: 0;\n transition: opacity 0.2s;\n pointer-events: none;\n }\n .mfm-modal-overlay.show { opacity: 1; pointer-events: auto; }\n .mfm-modal {\n background: white;\n padding: 20px;\n border-radius: 12px;\n width: 300px;\n box-shadow: 0 10px 25px rgba(0,0,0,0.2);\n transform: scale(0.9);\n transition: transform 0.2s;\n }\n .mfm-modal-overlay.show .mfm-modal { transform: scale(1); }\n .mfm-modal-title { font-size: 16px; font-weight: 600; margin-bottom: 10px; }\n .mfm-modal-body { font-size: 14px; color: #666; margin-bottom: 20px; }\n .mfm-modal-actions { display: flex; justify-content: flex-end; gap: 10px; }\n .mfm-btn-alt { background: #f3f4f6; color: #333; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; font-size: 14px; }\n .mfm-btn-danger { background: #dc2626; color: white; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; font-size: 14px; }\n \n .mfm-spinner {\n width: 12px;\n height: 12px;\n border: 2px solid #f3f3f3;\n border-top: 2px solid #2563eb;\n border-radius: 50%;\n animation: mfm-spin 1s linear infinite;\n margin-right: 8px;\n display: inline-block;\n }\n .status-aborted { color: #dc2626; font-weight: bold; }\n .mfm-duration { color: #666; font-size: 11px; margin-left: 8px; font-weight: normal; }\n ",document.head.appendChild(e)}render(){const e=document.createElement("div");e.id="mockforme-root",document.body.appendChild(e),this.root=e,this.bubble=this.renderBubble(),this.root.appendChild(this.bubble),this.sheet=document.createElement("div"),this.sheet.className="mfm-bottomsheet",this.root.appendChild(this.sheet),this.snackbar=document.createElement("div"),this.snackbar.className="mfm-snackbar",this.root.appendChild(this.snackbar),this.modalOverlay=document.createElement("div"),this.modalOverlay.className="mfm-modal-overlay",this.root.appendChild(this.modalOverlay),this.updateUI()}updateUI(){this.state.isOpen?(this.renderBottomSheetContent(),this.sheet.classList.add("open")):this.sheet.classList.remove("open")}renderBubble(){const e=document.createElement("div");e.className="mfm-bubble";const t="undefined"!=typeof localStorage?JSON.parse(localStorage.getItem("mockforme-dot-pos")||"{}"):{};return t.bottom&&(e.style.bottom=t.bottom+"px"),t.right&&(e.style.right=t.right+"px"),e.innerHTML='\n <div class="mfm-refresh-icon" title="Reload Mappings">↻</div>\n <img src="https://ik.imagekit.io/mfm/static-collection/mfm-48x48.png" alt="MFM" />\n ',this.addDragLogic(e),e.querySelector("img").onclick=e=>{this.isDragging||this.toggleSheet()},e.querySelector(".mfm-refresh-icon").onclick=e=>{e.stopPropagation(),this.refreshMappings()},e}addDragLogic(e){let t,n,s,o,r=!1;const i=i=>{const a=t-i.clientX,d=n-i.clientY;(Math.abs(a)>3||Math.abs(d)>3)&&(r=!0,this.isDragging=!0),r&&(e.style.right=s+a+"px",e.style.bottom=o+d+"px")},a=()=>{document.removeEventListener("mousemove",i),document.removeEventListener("mouseup",a),r&&"undefined"!=typeof localStorage&&localStorage.setItem("mockforme-dot-pos",JSON.stringify({bottom:parseInt(e.style.bottom),right:parseInt(e.style.right)}))};e.addEventListener("mousedown",(d=>{r=!1,this.isDragging=!1,t=d.clientX,n=d.clientY;const c=e.getBoundingClientRect();s=window.innerWidth-c.right,o=window.innerHeight-c.bottom,document.addEventListener("mousemove",i),document.addEventListener("mouseup",a)}))}toggleSheet(){this.state.isOpen=!this.state.isOpen,this.updateUI()}showSnackbar(e){this.snackbar.textContent=e,this.snackbar.classList.add("show"),setTimeout((()=>this.snackbar.classList.remove("show")),3e3)}showConfirm(e,t,n){this.modalOverlay.innerHTML=`\n <div class="mfm-modal">\n <div class="mfm-modal-title">${e}</div>\n <div class="mfm-modal-body">${t}</div>\n <div class="mfm-modal-actions">\n <button class="mfm-btn-alt" id="mfm-confirm-cancel">Cancel</button>\n <button class="mfm-btn-danger" id="mfm-confirm-yes">Delete</button>\n </div>\n </div>\n `,this.modalOverlay.classList.add("show"),this.modalOverlay.querySelector("#mfm-confirm-cancel").onclick=()=>{this.modalOverlay.classList.remove("show")},this.modalOverlay.querySelector("#mfm-confirm-yes").onclick=()=>{this.modalOverlay.classList.remove("show"),n()}}refreshMappings(){if(!this.token)return void this.toggleSheet();const e=document.querySelectorAll(".mfm-refresh-icon, #mfm-refresh-mappings-btn");e.forEach((e=>e.classList.add("loading"))),M(this.token,"JAVASCRIPT",((t,n)=>{console.log("[MockForMe] Mappings reloaded",{mappings:t?.length,rules:n?._rules?.length}),e.forEach((e=>e.classList.remove("loading"))),this.mappings=t||[],this.rules=n?._rules||[],this.onAuthSuccess(this.token,this.mappings,n),this.updateUI(),this.showSnackbar("Mappings reloaded!")}),(t=>{e.forEach((e=>e.classList.remove("loading"))),this.showSnackbar("Failed to reload mappings")}))}renderBottomSheetContent(){this.sheet.innerHTML="",this.isAuthenticated?this.state.selectedRequest?this.sheet.appendChild(this.renderRequestDetail(this.state.selectedRequest)):this.sheet.appendChild(this.renderDashboard()):this.sheet.appendChild(this.renderTokenForm())}renderTokenForm(){const e=document.createElement("div");e.innerHTML=`\n <div class="mfm-header">\n <span class="mfm-title">Save Token</span>\n <button class="mfm-close">×</button>\n </div>\n <div class="mfm-logo-container">\n <img src="https://dashboard.mockforme.com/public/assets/images/logo.png" class="mfm-logo" alt="MockForMe Logo" />\n </div>\n <div class="mfm-form">\n <input type="text" class="mfm-input" placeholder="Enter MockForMe Access Token" id="mfm-token-input">\n <div class="mfm-error" id="mfm-error-msg" style="display: ${this.state.lastError?"block":"none"}">${this.state.lastError||""}</div>\n <a href="https://dashboard.mockforme.com/user/token" target="_blank" class="mfm-link">Get Access Token?</a>\n <button class="mfm-btn" id="mfm-save-token-btn">Save</button>\n </div>\n `,e.querySelector(".mfm-close").onclick=()=>{this.state.lastError=null,this.toggleSheet()};const t=e.querySelector("#mfm-save-token-btn"),n=e.querySelector("#mfm-token-input");return t.onclick=()=>{const s=n.value.trim();s&&(t.textContent="Validating...",t.disabled=!0,this.state.lastError=null,e.querySelector("#mfm-error-msg").style.display="none",M(s,c,((e,t)=>{"undefined"!=typeof localStorage&&localStorage.setItem("mockforme-token",s),this.token=s,this.isAuthenticated=!0,this.mappings=e,this.rules=t?._rules||[],this.onAuthSuccess(s,e,t),this.updateUI()}),(e=>{t.textContent="Save",t.disabled=!1;let n="Invalid Token or Network Error";e&&"function"==typeof e.json?e.json().then((e=>{this.state.lastError=e.message||n,this.updateUI()})).catch((()=>{this.state.lastError=n,this.updateUI()})):(this.state.lastError=e.message||n,this.updateUI())})))},e}deleteToken(){"undefined"!=typeof localStorage&&localStorage.removeItem("mockforme-token"),this.token=null,this.isAuthenticated=!1,this.mappings=[],this.rules=[],this.state.lastError=null,this.updateUI()}renderDashboard(){const e=document.createElement("div");e.innerHTML='\n <div class="mfm-header">\n <span class="mfm-title">MockForMe</span>\n <div class="mfm-header-actions">\n <button class="mfm-delete-token-btn" id="mfm-delete-token" title="Delete Token">\n <span>🗑</span>\n <span>Token</span>\n </button>\n <button class="mfm-close">×</button>\n </div>\n </div>\n ';const t=document.createElement("div");t.className="mfm-tabs",["mappings","mocked","other"].forEach((e=>{const n=document.createElement("div");n.className="mfm-tab "+(this.state.activeTab===e?"active":""),n.textContent="mappings"===e?"Api Mappings":"mocked"===e?"Mocked Apis":"Other Apis",n.onclick=()=>{this.state.activeTab=e,this.updateUI()},t.appendChild(n)})),e.querySelector(".mfm-header").after(t);const n=document.createElement("div");n.className="mfm-actions-bar","mappings"===this.state.activeTab?(n.innerHTML=`\n <div style="flex: 1; font-size: 13px; color: #666;">Total: ${this.mappings.length+this.rules.length}</div>\n <div class="mfm-icon-btn refresh" id="mfm-refresh-mappings-btn" title="Refresh Mappings">↻</div>\n `,n.querySelector("#mfm-refresh-mappings-btn").onclick=()=>this.refreshMappings()):(n.innerHTML=`\n <input type="text" class="mfm-search-input" placeholder="Search requests..." id="mfm-search-input" value="${this.state.searchQuery}">\n <button class="mfm-icon-btn delete" id="mfm-clear-requests-btn" title="Clear List">🚫</button>\n `,n.querySelector("#mfm-search-input").oninput=e=>{this.state.searchQuery=e.target.value,this.updateRequestList(s)},n.querySelector("#mfm-clear-requests-btn").onclick=()=>{"mocked"===this.state.activeTab?this.mockedRequests=[]:this.otherRequests=[],this.updateUI()}),t.after(n);const s=document.createElement("div");return s.className="mfm-list",this.updateRequestList(s),e.appendChild(s),e.querySelector(".mfm-close").onclick=()=>this.toggleSheet(),e.querySelector("#mfm-delete-token").onclick=()=>{this.showConfirm("Delete Token","Are you sure you want to Delete Token? This will clear your saved token.",(()=>{this.deleteToken()}))},e}updateRequestList(e){if(e.innerHTML="","mappings"===this.state.activeTab){const t=[...this.mappings.map((e=>({...e,type:"mapping"}))),...this.rules.map((e=>({...e,type:"rule"})))];0===t.length?e.innerHTML='<div style="padding: 20px; text-align: center; color: #999;">No items found</div>':t.forEach((t=>{const n=document.createElement("div");if(n.className="mfm-list-item","mapping"===t.type){const e=(t.apiMethod||"GET").toUpperCase();n.innerHTML=`<div style="display:flex; align-items:center; width:100%"><span class="mfm-method ${e}">${e}</span><span class="mfm-url">${t.apiEndpoint}</span></div>`}else{const e=t.ruleName||"Network Rule",s=(t.rule?.URL?.condition||{}).value||e;n.innerHTML=`<div style="display:flex; align-items:center; width:100%"><span class="mfm-method RULE">RULE</span><span class="mfm-url">${s}</span></div>`}e.appendChild(n)}))}else{let t="mocked"===this.state.activeTab?this.mockedRequests:this.otherRequests;if(this.state.searchQuery){const e=this.state.searchQuery.toLowerCase();t=t.filter((t=>(t.url||"").toLowerCase().includes(e)||(t.method||"").toLowerCase().includes(e)||String(t.status).includes(e)))}0===t.length?e.innerHTML='<div style="padding: 20px; text-align: center; color: #999;">No items found</div>':t.forEach((t=>{const n=document.createElement("div");n.className="mfm-list-item";const s=(t.method||"").toUpperCase(),o=`<span class="mfm-duration" style="color:#2563eb; font-size:11px; font-weight:500; display:block; height:14px; line-height:14px;">${void 0!==t.duration?t.duration+"ms":""}</span>`,r=(()=>{if(!t.rule)return"";let e="delay_and_timeout"===t.rule.action?"Delay and Timout":t.rule.action.split("_")[0];const n=t.rule.config?.value;return void 0!==n&&(t.rule.action.includes("delay")||t.rule.action.includes("timeout"))&&(e+=` (${n}s)`),`<span class="mfm-rule-tag" title="${t.rule.action}">${e}</span>`})();let i=t.status,a="mfm-status";t.pending?i='<span class="mfm-spinner"></span>':t.aborted?(i="Aborted",a+=" status-aborted"):t.timeout?(i="Timeout",a+=" status-timeout"):t.error?(i="Error/CORS",a+=" status-error"):(i=t.status,a+=t.status>=200&&t.status<300?" status-2xx":" status-4xx"),n.innerHTML=`\n <div style="display:flex; align-items:center; width:100%; gap:8px;">\n <span class="mfm-method ${s}">${s}</span>\n <div style="flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; justify-content:center;">\n <span class="mfm-url">${r}${t.url}</span>\n ${o}\n </div>\n <span class="${a}">${i}</span>\n </div>\n `,n.onclick=()=>{this.state.selectedRequest=t,this.updateUI()},e.appendChild(n)}))}}renderRequestDetail(e){const t=document.createElement("div");t.className="mfm-detail-view",t.innerHTML='\n <div class="mfm-header">\n <span class="mfm-title">Details</span>\n <button class="mfm-close">×</button>\n </div>\n <div class="mfm-detail-actions">\n <button class="mfm-back-btn">← Back</button>\n </div>\n ';const n=document.createElement("div");n.className="mfm-tabs",["request","response"].forEach((e=>{const t=document.createElement("div");t.className="mfm-tab "+(this.state.activeRequestTab===e?"active":""),t.textContent=e.charAt(0).toUpperCase()+e.slice(1),t.onclick=()=>{this.state.activeRequestTab=e,this.updateUI()},n.appendChild(t)}));const s=document.createElement("div");s.style.overflowY="auto",s.style.flex="1";const o=(e.method||"").toUpperCase();return s.innerHTML="request"===this.state.activeRequestTab?`\n <div class="section-title">URL</div><div class="mfm-code-block">${o} ${e.url}</div>\n ${e.rule?`<div class="section-title">Matched Rule</div><div class="mfm-code-block">${e.rule.action} (value: ${e.rule.config?.value})</div>`:""}\n <div class="section-title">Headers</div><div class="mfm-code-block">${JSON.stringify(e.requestHeaders||{},null,2)}</div>\n <div class="section-title">Query Params</div><div class="mfm-code-block">${JSON.stringify(e.queryParams||{},null,2)}</div>\n <div class="section-title">Payload</div><div class="mfm-code-block">${this.formatBody(e.requestBody)}</div>\n `:`\n <div class="section-title">Status</div><div class="mfm-code-block">${e.status}</div>\n <div class="section-title">Response Headers</div><div class="mfm-code-block">${JSON.stringify(e.responseHeaders||{},null,2)}</div>\n <div class="section-title">Response Body</div><div class="mfm-code-block">${this.formatBody(e.responseBody)}</div>\n `,t.appendChild(n),t.appendChild(s),t.querySelector(".mfm-close").onclick=()=>this.toggleSheet(),t.querySelector(".mfm-back-btn").onclick=()=>{this.state.selectedRequest=null,this.updateUI()},t}formatBody(e){if(!e)return"";if("object"==typeof e)return JSON.stringify(e,null,2);try{return JSON.stringify(JSON.parse(e),null,2)}catch{return e}}addRequest(e,t){const n=String(t.method||"").toUpperCase().trim(),s=String(t.url||"");console.log(`[MockForMe] addRequest type=${e} method=${n} url=${s} requestId=${t.requestId} pending=${t.pending}`);const o=s.includes("api.mockforme.com")||s.includes("mockforme.com/proxy")||s.includes("mockforme.com/gateway")||f&&s.includes(String(f));if("OPTIONS"===n||o)return;const r="mocked"===e?this.mockedRequests:this.otherRequests,i="mocked"===e?this.otherRequests:this.mockedRequests;if(t.requestId){const n=r.findIndex((e=>e.requestId===t.requestId));if(-1!==n)return r[n]={...r[n],...t},void(this.state.isOpen&&this.state.activeTab===e&&this.updateUI());const s=i.findIndex((e=>e.requestId===t.requestId));if(-1!==s){const e={...i[s],...t};return i.splice(s,1),r.unshift(e),r.length>50&&r.pop(),void(this.state.isOpen&&this.updateUI())}}r.unshift(t),r.length>50&&r.pop(),this.state.isOpen&&this.state.activeTab===e&&this.updateUI()}};function L(e,t){if("undefined"!=typeof window){if(window._mfm_intercepted)return;window._mfm_intercepted=!0}!function(e,t){const n=window.fetch;window.fetch=function(s,o={}){const r="string"==typeof s?s:s.url,i=String(o.method||(s instanceof Request?s.method:"GET")).toUpperCase().trim();if("OPTIONS"===i)return console.log(`[MockForMe] Filtered ${i} ${r} (isInternal=false)`),n(s,o);const a={url:r,method:i,requestHeaders:o.headers||(s instanceof Request?s.headers:{}),requestBody:o.body||(s instanceof Request?"{binary/stream}":null),queryParams:$(r)};try{const c=new URL(r,window.location.origin),{pathname:p,search:f}=c,g=R({url:r,method:i}),b=Math.random().toString(36).substring(7),x=Date.now();if(t!==l&&g){if(I.addRequest("mocked",{...a,requestId:b,pending:!0,startTime:x,rule:g}),"delay"===g.action)return new Promise(((e,t)=>{setTimeout((()=>{const t=n(s,o);t.then((e=>{const t=Date.now()-x;I.addRequest("mocked",{...a,requestId:b,status:e.status,pending:!1,duration:t})})).catch((e=>{const t=Date.now()-x;I.addRequest("mocked",{...a,requestId:b,status:0,pending:!1,duration:t})})),e(t)}),1e3*g.config.value)}));if("delay_and_redirect"===g.action)return new Promise(((e,t)=>{setTimeout((()=>{const t=n(g.config.redirectUrl,o);t.then((e=>{const t=Date.now()-x;I.addRequest("mocked",{...a,requestId:b,status:e.status,pending:!1,duration:t})})).catch((e=>{const t=Date.now()-x;I.addRequest("mocked",{...a,requestId:b,status:0,pending:!1,duration:t})})),e(t)}),1e3*g.config.value)}));if("delay_and_timeout"===g.action){const e=Number(g.config.value||0);if(0===e){const e=new AbortController,t=n(s,{...o,signal:e.signal});e.abort();const r=Date.now()-x;return I.addRequest("mocked",{...a,requestId:b,status:"Aborted",pending:!1,duration:r,aborted:!0}),t.catch((()=>Promise.reject(new Error("Fetch aborted by rules"))))}return new Promise(((t,n)=>{setTimeout((()=>{const e=Date.now()-x;I.addRequest("mocked",{...a,requestId:b,status:"Aborted",pending:!1,duration:e,aborted:!0}),n(new Error("Fetch timed out by rules"))}),1e3*e)}))}}const y=d(p,i),k=I.token||e;if(!y&&!g)return I.addRequest("other",{...a,requestId:b,pending:!0,startTime:x}),n(s,o).then((async e=>{const t=e.clone(),n=Date.now()-x;try{const s=await t.text();I.addRequest("other",{...a,requestId:b,status:e.status,responseHeaders:Object.fromEntries(e.headers.entries()),responseBody:s,pending:!1,duration:n})}catch(e){}return e})).catch((e=>{const t=Date.now()-x,n="AbortError"===e.name||e.message.includes("aborted"),s="TimeoutError"===e.name||e.message.includes("timed out"),o=!n&&!s;throw I.addRequest("other",{...a,requestId:b,status:n?"Aborted":s?"Timeout":"Error",responseHeaders:{},responseBody:e.message,pending:!1,duration:t,aborted:n,timeout:s,error:o}),e}));let v=r;g||(v=`${w()}${y.url}${f}`);let _={};if(!g){_={[u]:k,[m]:h,"x-mfm-adaptor":t};const e=q();e&&y._ack&&(_["x-mfm-key"]=`${e}-${y._ack}`),y?._ri_&&(_._ri_=y._ri_)}const T=s instanceof Request?s.headers:o.headers,S=new Headers(T||{});Object.entries(_).forEach((([e,t])=>{S.set(e,t)}));let M=o.body;if(!M&&s instanceof Request){const e=s.clone();"GET"!==e.method&&"HEAD"!==e.method&&(M=e.text())}let L={method:i,headers:S,credentials:"include",mode:"cors"};g&&(L.credentials=s instanceof Request&&s.credentials||o.credentials||"same-origin",L.mode=s instanceof Request&&s.mode||o.mode||"cors");const $=e=>(e&&(L.body=e),t===l?(I.addRequest("mocked",{...a,requestId:b,pending:!0,startTime:x}),(({actualUrl:e,url:t,method:n,headers:s,body:o,credentials:r,mode:i,rule:a})=>{const d=`${Date.now()}-${Math.random()}`,c=E(t);return new Promise(((t,l)=>{window.addEventListener("message",(function e(n){if(n.source!==window)return;const s=n.data;if("INTERCEPTED_RESPONSE"===s?.type&&s?.requestId===d){if(window.removeEventListener("message",e),s?.response?.error)return l(new Error(s.response.message));const{status:n,headers:o,body:r}=s.response;t(new Response(r,{status:n,headers:o}))}})),window.postMessage({type:"REQUEST_INTERCEPTED",requestId:d,payload:{actualUrl:e,url:c,method:n,headers:s,body:o,credentials:r,mode:i,rule:a}},"*")}))})({actualUrl:r,url:v,method:i,headers:Object.fromEntries(S.entries()),body:e,credentials:L.credentials,mode:L.mode,rule:g}).then((e=>(e.clone().text().then((t=>{const n=Date.now()-x;I.addRequest("mocked",{...a,requestId:b,status:e.status,responseHeaders:Object.fromEntries(e.headers.entries()),responseBody:t,pending:!1,duration:n})})),e))).catch((e=>{const t=Date.now()-x,n="AbortError"===e.name;throw I.addRequest("mocked",{...a,requestId:b,status:n?"Aborted":0,responseHeaders:{},responseBody:e.message,pending:!1,duration:t,aborted:n}),e}))):(I.addRequest("mocked",{...a,requestId:b,pending:!0,startTime:x}),n(v,L).then((e=>{const t=e.clone(),n=t.headers.get("content-type")||"",s=Date.now()-x,o=n=>(I.addRequest("mocked",{...a,requestId:b,status:e.status,responseHeaders:Object.fromEntries(t.headers.entries()),responseBody:n,pending:!1,duration:s}),new Response("string"==typeof n?n:JSON.stringify(n),{status:e.status,headers:t.headers}));return n.includes("application/json")?t.json().then(o):t.text().then(o)})).catch((e=>{console.warn("mockforme fetch interceptor error",e);const t=Date.now()-x,r="AbortError"===e.name;return I.addRequest("mocked",{...a,requestId:b,status:r?"Aborted":0,responseHeaders:{},responseBody:e.message,pending:!1,duration:t,aborted:r}),n(s,o)}))));return M instanceof Promise?M.then((e=>$(e))):$(M)}catch(e){return console.warn("mockforme fetch interceptor error",e),n(s,o)}}}(e,t),function(e,t){const n=window.XMLHttpRequest;window.XMLHttpRequest=class{constructor(){return this._xhr=new n,this._headers={},this._method=null,this._url=null,this._body=null,this._isMocked=!1,this._captured=!1,this._requestId=null,this._startTime=null,this._capture=(e,t,n,s={})=>{if(this._captured)return;this._captured=!0;const o=this._isMocked?"mocked":"other",r=this._startTime?Date.now()-this._startTime:0;console.log(`[MockForMe] XHR Capture: status=${e} method=${this._method} url=${this._url} duration=${r}ms`);const i=e=>{const t=`on${e}`;(this[t]||this._xhr[t])?.(),this._xhr.dispatchEvent(new Event(e))};if(I.addRequest(o,{url:this._url,method:this._method,requestHeaders:this._headers,requestBody:this._body,queryParams:$(this._url),requestId:this._requestId,status:e,responseBody:t,responseHeaders:n,pending:!1,duration:r,...s}),"Aborted"!==e)try{Object.defineProperty(this,"responseText",{value:t,configurable:!0}),Object.defineProperty(this,"response",{value:t,configurable:!0}),Object.defineProperty(this,"status",{value:Number(e)||0,configurable:!0}),Object.defineProperty(this,"statusText",{value:200==e?"OK":"",configurable:!0})}catch(e){console.warn("[MockForMe] Error setting XHR props",e)}Object.defineProperty(this,"readyState",{value:4,configurable:!0}),i("readystatechange"),"Aborted"===e||s.aborted?i("abort"):0===e||"Error"===e||s.error?i("error"):"Timeout"===e||s.timeout?i("timeout"):i("load")},new Proxy(this,{get:(e,t)=>{if(t in e)return e[t];const n=e._xhr[t];return"function"==typeof n?n.bind(e._xhr):n},set:(e,t,n)=>t in e?(e[t]=n,!0):(e._xhr[t]=n,!0)})}open(e,t,n=!0,s=null,o=null){this._method=(e||"").toUpperCase().trim();try{this._url=new URL(t,window.location.href).toString()}catch(e){this._url=t}return console.log(`[MockForMe] XHR.open: ${this._method} ${this._url}`),this._xhr._mockOriginalUrl=this._url,this._xhr._mockMethod=this._method,this._xhr.open(e,t,n,s,o)}setRequestHeader(e,t){return this._headers[e]=t,this._xhr.setRequestHeader(e,t)}send(s){const o=String(this._method||"").toUpperCase().trim();if(console.log(`[MockForMe] XHR send method=${o} url=${this._url}`),"OPTIONS"===o)return console.log("[MockForMe] XHR Skip OPTIONS"),this._xhr.send(s);this._body=s,this._requestId=Math.random().toString(36).substring(7),this._startTime=Date.now(),this._xhr.addEventListener("abort",(()=>{this._capture("Aborted","Request aborted",{},{aborted:!0})}),{once:!0}),this._xhr.addEventListener("error",(()=>{this._capture(0,"Network Error",{},{error:!0})}),{once:!0}),this._xhr.addEventListener("timeout",(()=>{this._capture("Timeout","Request timed out",{},{timeout:!0})}),{once:!0});try{const o=new URL(this._url),{pathname:r,search:i}=o,a=R({url:this._url,method:this._method});a&&(this._isMocked=!0,I.addRequest("mocked",{url:this._url,method:this._method,requestHeaders:this._headers,requestBody:this._body,queryParams:$(this._url),requestId:this._requestId,pending:!0,startTime:this._startTime,rule:a}));const c=I.token||e;if(t!==l&&a){if("delay"===a.action){const e=Number(a.config.value||0);return setTimeout((()=>{this._xhr.addEventListener("load",(()=>{this._capture(this._xhr.status,this._xhr.responseText,this._xhr.getAllResponseHeaders())}),{once:!0}),this._xhr.send(this._body)}),1e3*e)}if("delay_and_redirect"===a.action){const e=Number(a.config.value||0);return setTimeout((()=>{this._xhr.open(this._method,a.config.redirectUrl,!0),this._xhr.addEventListener("load",(()=>{this._capture(this._xhr.status,this._xhr.responseText,this._xhr.getAllResponseHeaders())}),{once:!0}),this._xhr.send(this._body)}),1e3*e)}if("delay_and_timeout"===a.action){const e=Number(a.config.value||0);return 0===e?(this._capture("Aborted","Request aborted by rules",{},{aborted:!0}),void this._xhr.abort()):setTimeout((()=>{this._capture("Aborted","Request timed out by rules",{},{aborted:!0}),this._xhr.abort()}),1e3*e)}}const p=d(r,this._method);if(!p&&!a)return console.log("[MockForMe] XHR No Match:",{pathname:r,method:this._method}),this._isMocked=!1,I.addRequest("other",{url:this._url,method:this._method,requestHeaders:this._headers,requestBody:this._body,queryParams:$(this._url),requestId:this._requestId,pending:!0,startTime:this._startTime}),this._xhr.addEventListener("load",(()=>{this._capture(this._xhr.status,this._xhr.responseText,this._xhr.getAllResponseHeaders())}),{once:!0}),this._xhr.send(s);console.log("[MockForMe] XHR Matched:",{pathname:r,match:p}),this._isMocked=!0;let f=this._url;a||(f=`${w()}${p.url}${i}`);let g={};if(!a){g={[u]:c,[m]:h,"x-mfm-adaptor":t};const e=q();e&&p._ack&&(g["x-mfm-key"]=`${e}-${p._ack}`),p?._ri_&&(g._ri_=p._ri_)}const b={...this._headers,...g};if(I.addRequest("mocked",{url:this._url,method:this._method,requestHeaders:this._headers,requestBody:this._body,queryParams:$(this._url),requestId:this._requestId,pending:!0,startTime:this._startTime}),t===l)(({actualUrl:e,url:t,method:n,headers:s,body:o,onSuccess:r,onError:i,rule:a})=>{const d=`${Date.now()}-${Math.random()}`,c=E(t);window.addEventListener("message",(function e(t){if(t.source!==window)return;const n=t.data;if("INTERCEPTED_RESPONSE"===n.type&&n.requestId===d){if(window.removeEventListener("message",e),n.response?.error)return i?.(n.response.message);const{body:t,status:s,headers:o}=n.response;r?.({body:t,status:s,headers:o})}})),window.postMessage({type:"REQUEST_INTERCEPTED",requestId:d,payload:{actualUrl:e,url:c,method:n,headers:s,body:o,credentials:"same-origin",mode:"cors",rule:a}},"*")})({actualUrl:this._url,url:f,method:this._method,headers:b,body:this._body,rule:a,onSuccess:({body:e,status:t,headers:n})=>{this._capture(t,e,n||{})},onError:e=>{this._capture(0,e.message||"XHR Error",{},{error:!0})}});else{const e=new n;e.open(this._method,f,!0);for(const t in b)e.setRequestHeader(t,b[t]);e.withCredentials=this.withCredentials,e.onload=()=>{this._capture(e.status,e.responseText,e.getAllResponseHeaders())},e.onerror=()=>{this._capture(0,"Network Error",{},{error:!0})},e.ontimeout=()=>{this._capture("Timeout","Request timed out",{},{timeout:!0})},e.send(this._body)}}catch(e){if(console.error("[MockForMe] XHR Interception Error",e),!this._xhr.readyState||1===this._xhr.readyState)return this._xhr.send(s)}}}}(e,t)}function $(e){try{const t=new URL(e,window.location.origin).searchParams;return Object.fromEntries(t.entries())}catch{return{}}}const O=(e,t=null,s=c)=>{if(n())return;if(s===c)try{e&&("undefined"!=typeof localStorage&&localStorage.removeItem("mockforme-token"),I.token=e,I.isAuthenticated=!0),!e&&I.token&&(e=I.token),I.onAuthSuccess=(e,t,n)=>{i(t),v(n),I.mappings=t,I.rules=n?._rules||[]}}catch(e){console.log("Error in showing mockforme widget",e)}t||={mappings:[],_o:null,mk:null,_mck:null,_rules:[]};const{mappings:o=[],_o:r,mk:l,_mck:p,_rules:f=[]}=t;return i(o),v({_o:r,mk:l,_mck:p,_rules:f}),{run:(t,n=()=>{})=>{L(e,s),r&&l?(I.mappings=o,I.rules=f,t?.(o,{_o:r,mk:l,_mck:p,_rules:f})):e&&function(e,n,s,o){T({method:"get",url:g,async:!1,headers:{[u]:e,[m]:h,"x-mfm-adaptor":n}},(e=>{if(e)try{const{di:o,iv:r,_o:a,_mck:d,mk:c,r:l}=e,m=S({di:o,iv:r},a);v({_o:a,mk:c,_mck:d,_rules:l}),m&&(i(m),n=m,s={_o:a,mk:c,_mck:d,_rules:l},I.mappings=n,I.rules=s?._rules||[],t?.(n,s))}catch(e){return void o(new Error("Unable to fetch mocked apis"))}var n,s}),(e=>{console.log("Error in loading mocked apis"),o(e)})).request()}(e,s,0,n)},checkIfApiToBeMocked:d,getMappings:a,doFetchMappings:(t,n)=>{M(e||I.token,s,((e,n)=>{I.mappings=e,I.rules=n?._rules||[],t?.(e,n)}),n)}}},C=n();C||(globalThis.mockforme=O);let H=O;C&&(H=e=>({run:()=>{}}));const U=H;return t.mockforme})()));
|
package/dist/mockforme.d.ts
CHANGED
|
@@ -4,9 +4,9 @@ export = mockforme;
|
|
|
4
4
|
|
|
5
5
|
declare namespace mockforme {
|
|
6
6
|
/**
|
|
7
|
-
* Initialize mockforme
|
|
7
|
+
* Initialize mockforme.
|
|
8
8
|
*
|
|
9
|
-
* @param token -
|
|
9
|
+
* @param token - Optional on client side (managed by widget), required for Node/SSR.
|
|
10
10
|
* @returns An object with a method to start mock API interception.
|
|
11
11
|
*
|
|
12
12
|
* @example
|
|
@@ -14,7 +14,7 @@ declare namespace mockforme {
|
|
|
14
14
|
* console.log("Available APIs for mock:", apis);
|
|
15
15
|
* });
|
|
16
16
|
*/
|
|
17
|
-
function mockforme(token
|
|
17
|
+
function mockforme(token?: string, options?: {
|
|
18
18
|
mappings: [],
|
|
19
19
|
_o: string,
|
|
20
20
|
mk: string,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mockforme",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "MockForMe is a fast and simple mock API solution for CSR and SSR apps. Create mock APIs in 2 minutes with support for delays, conditional responses, public URLs, random data, variables, Faker, and postFunctions — all designed to boost developer productivity.",
|
|
5
5
|
"main": "dist/mockforme.client.cjs.js",
|
|
6
6
|
"module": "dist/mockforme.client.esm.js",
|