mockforme 5.0.2 → 6.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/dist/index.html +1 -1
- package/dist/mockforme.client.cjs.js +1 -1
- package/dist/mockforme.client.esm.js +1 -1
- package/dist/mockforme.client.umd.js +1 -1
- package/dist/mockforme.d.ts +28 -9
- package/dist/mockforme.server.cjs.js +1 -1
- package/dist/mockforme.server.esm.js +1 -1
- package/package.json +1 -1
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.umd.js"></script></head><body></body></html>
|
|
@@ -1 +1 @@
|
|
|
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,y=null,x=null,k=[];function v({_o:e,mk:t,_mck:n,_rules:s}){b=e,y=t,x=n,k=s}function _(){return k}function w(){return`${f}/${b}/${y}`}function q(){return x}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 I(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 M=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&&(window.addEventListener("resize",(()=>{this.bubble&&this.keepInBounds(this.bubble)})),"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: 25px;\n height: 25px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #2563eb;\n font-size: 25px;\n transition: background 0.2s;\n margin-right: 10px;\n background: #f3f4f6;\n padding: 8px;\n }\n .mfm-refresh-icon:hover { }\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: 80vh;\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 @media (max-width: 480px) {\n .mfm-bottomsheet { padding: 16px; }\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: 15px;\n padding-bottom: 10px;\n border-bottom: 1px solid #eee;\n flex-shrink: 0;\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: 20px 0; width: 100%; display: flex; justify-content: center; flex-shrink: 0; }\n .mfm-logo { width: 120px; 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: 10px; flex-shrink: 0; }\n .mfm-tab {\n padding: 8px 16px;\n cursor: pointer;\n color: #666;\n border-bottom: 2px solid transparent;\n font-weight: 500;\n font-size: 14px;\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; flex-shrink: 0; }\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: 25px; cursor: pointer; color: #666; display: flex; align-items: center; justify-content: center; padding: 4px; border-radius: 4px; }\n .mfm-icon-btn:hover { color: #333; }\n .mfm-icon-btn.refresh { color: #2563eb; padding: 0; height: 20px; width:20px; border-radius: 50%; }\n .mfm-icon-btn.refresh.loading { animation: mfm-spin 1s linear infinite; }\n .mfm-icon-btn.delete { color: #dc2626; }\n\n @media (max-height: 700px) {\n .mfm-bottomsheet { height: 85vh; padding: 12px; }\n .mfm-logo-container { padding: 10px 0; }\n .mfm-logo { width: 100px; }\n .mfm-header { margin-bottom: 10px; }\n .mfm-form { gap: 8px; }\n .mfm-input { padding: 10px; font-size: 14px; }\n .mfm-btn { padding: 10px; font-size: 14px; }\n }\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),this.keepInBounds(e),e.querySelector("img").onclick=e=>{this.isDragging||this.toggleSheet()},e.querySelector(".mfm-refresh-icon").onclick=e=>{e.stopPropagation(),this.refreshMappings()},e}keepInBounds(e){const t=e.getBoundingClientRect(),n=10;let s=parseInt(e.style.right)||20,o=parseInt(e.style.bottom)||20;const r=window.innerWidth-t.width-n,i=window.innerHeight-t.height-n;s<n&&(s=n),o<n&&(o=n),s>r&&(s=r),o>i&&(o=i),e.style.right=s+"px",e.style.bottom=o+"px"}addDragLogic(e){let t,n,s,o,r=!1;const i=(i,a)=>{r=!1,this.isDragging=!1,t=i,n=a;const d=e.getBoundingClientRect();s=window.innerWidth-d.right,o=window.innerHeight-d.bottom},a=(i,a)=>{const d=t-i,c=n-a;(Math.abs(d)>3||Math.abs(c)>3)&&(r=!0,this.isDragging=!0),r&&(e.style.right=s+d+"px",e.style.bottom=o+c+"px")},d=()=>{r&&(this.keepInBounds(e),"undefined"!=typeof localStorage&&localStorage.setItem("mockforme-dot-pos",JSON.stringify({bottom:parseInt(e.style.bottom),right:parseInt(e.style.right)})))},c=e=>{a(e.clientX,e.clientY)},l=()=>{document.removeEventListener("mousemove",c),document.removeEventListener("mouseup",l),d()},m=e=>{const t=e.touches[0];a(t.clientX,t.clientY),r&&e.cancelable&&e.preventDefault()},u=()=>{document.removeEventListener("touchmove",m),document.removeEventListener("touchend",u),d()};e.addEventListener("mousedown",(e=>{i(e.clientX,e.clientY),document.addEventListener("mousemove",c),document.addEventListener("mouseup",l)})),e.addEventListener("touchstart",(e=>{const t=e.touches[0];i(t.clientX,t.clientY),document.addEventListener("touchmove",m,{passive:!1}),document.addEventListener("touchend",u)}),{passive:!0})}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"))),I(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",I(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("undefined"!=typeof FormData&&e instanceof FormData){const t={};return e.forEach(((e,n)=>{"undefined"!=typeof File&&e instanceof File?t[n]=`[File: ${e.name} (${e.size} bytes)]`:"undefined"!=typeof Blob&&e instanceof Blob?t[n]=`[Blob: ${e.type} (${e.size} bytes)]`:t[n]=e})),JSON.stringify(t,null,2)}if("undefined"!=typeof URLSearchParams&&e instanceof URLSearchParams)return JSON.stringify(Object.fromEntries(e.entries()),null,2);if("undefined"!=typeof Blob&&e instanceof Blob)return`[${"undefined"!=typeof File&&e instanceof File?"File":"Blob"}: ${e.type||"binary"} (${e.size} bytes)]`;if(e instanceof ArrayBuffer||"undefined"!=typeof Uint8Array&&e instanceof Uint8Array)return`[Binary Data: ${e.byteLength||e.length} bytes]`;if("object"==typeof e)try{return JSON.stringify(e,null,2)}catch{return String(e)}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),y=Date.now();if(t!==l&&g){if(M.addRequest("mocked",{...a,requestId:b,pending:!0,startTime:y,rule:g}),"delay"===g.action)return new Promise(((e,t)=>{setTimeout((()=>{const t=n(s,o);t.then((e=>{const t=Date.now()-y;M.addRequest("mocked",{...a,requestId:b,status:e.status,pending:!1,duration:t})})).catch((e=>{const t=Date.now()-y;M.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()-y;M.addRequest("mocked",{...a,requestId:b,status:e.status,pending:!1,duration:t})})).catch((e=>{const t=Date.now()-y;M.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()-y;return M.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()-y;M.addRequest("mocked",{...a,requestId:b,status:"Aborted",pending:!1,duration:e,aborted:!0}),n(new Error("Fetch timed out by rules"))}),1e3*e)}))}}const x=d(p,i),k=M.token||e;if(!x&&!g)return M.addRequest("other",{...a,requestId:b,pending:!0,startTime:y}),n(s,o).then((async e=>{const t=e.clone(),n=Date.now()-y;try{const s=await t.text();M.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()-y,n="AbortError"===e.name||e.message.includes("aborted"),s="TimeoutError"===e.name||e.message.includes("timed out"),o=!n&&!s;throw M.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()}${x.url}${f}`);let _={};if(!g){_={[u]:k,[m]:h,"x-mfm-adaptor":t};const e=q();e&&x._ack&&(_["x-mfm-key"]=`${e}-${x._ack}`),x?._ri_&&(_._ri_=x._ri_)}const T=s instanceof Request?s.headers:o.headers,S=new Headers(T||{});Object.entries(_).forEach((([e,t])=>{S.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: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?(M.addRequest("mocked",{...a,requestBody:e||a.requestBody,requestId:b,pending:!0,startTime:y}),(({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()-y;M.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()-y,n="AbortError"===e.name;throw M.addRequest("mocked",{...a,requestId:b,status:n?"Aborted":0,responseHeaders:{},responseBody:e.message,pending:!1,duration:t,aborted:n}),e}))):(M.addRequest("mocked",{...a,requestBody:e||a.requestBody,requestId:b,pending:!0,startTime:y}),n(v,L).then((e=>{const t=e.clone(),n=t.headers.get("content-type")||"",s=Date.now()-y,o=n=>(M.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()-y,r="AbortError"===e.name;return M.addRequest("mocked",{...a,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(M.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,M.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=M.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,M.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(M.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"),M.token=e,M.isAuthenticated=!0),!e&&M.token&&(e=M.token),M.onAuthSuccess=(e,t,n)=>{i(t),v(n),M.mappings=t,M.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?(M.mappings=o,M.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},M.mappings=n,M.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)=>{I(e||M.token,s,((e,n)=>{M.mappings=e,M.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
|
+
(()=>{"use strict";var e={d:(t,n)=>{for(var o in n)e.o(n,o)&&!e.o(t,o)&&Object.defineProperty(t,o,{enumerable:!0,get:n[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:()=>D});const n=()=>"undefined"!=typeof process&&null!=process.versions?.node,o=e=>{try{return e?e.toLowerCase():e}catch(e){return console.log(e),null}},r=(e,t)=>{const n=e.split("/"),o=t.split("/");if(n.length!==o.length)return!1;for(let e=0;e<n.length;e++){const t=n[e];if(t!==o[e]&&":any"!==t)return!1}return!0};let s=[];function i(e){s=e}function a(){return s}function d(e,t="get"){const n=e=>e.startsWith("/")?e:`/${e}`,i=n(e);for(const a of s)if(o(a.apiMethod)===o(t)){const o=n(a.apiEndpoint);if(o===i||r(o,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",p="4.2.7",h="https://api.mockforme.com",f=`${h}/mockforme`,g=`${h}/gateway/3f4eae522b`;let y=null,b=null,x=null,v=[];function w({_o:e,mk:t,_mck:n,_rules:o}){y=e,b=t,x=n,v=o}function k(){return v}function q(){return`${f}/${y}/${b}`}function E(){return x}const R=e=>{try{return new URL(e,window.location.origin).toString()}catch{return e}},S=function(e,t,o){const r=n();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 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,s)}else o.call(this,s.responseText,s)}function a(e,t){var n=[];for(var o in e)if(e.hasOwnProperty(o)){var r=t?t+"["+o+"]":o,s=e[o];n.push("object"==typeof s?a(s,r):encodeURIComponent(r)+"="+encodeURIComponent(s))}return n.join("&")}return r||(window.XMLHttpRequest?s=new XMLHttpRequest:window.ActiveXObject&&(s=new ActiveXObject("Microsoft.XMLHTTP"))),{request:function(){if(!r){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 n=e.url.split("?");n[1]&&n[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 _({di:e,iv:t},n){var o;const r=function(e,t){const n=t.length;return e.split("").map(((e,o)=>String.fromCharCode(e.charCodeAt(0)^t.charCodeAt(o%n)))).join("")}((o=e,"undefined"!=typeof Buffer?Buffer.from(o,"base64").toString("utf8"):decodeURIComponent(escape(atob(o)))),n+t);return JSON.parse(r)}function T(e,t,n,o){fetch(g,{method:"GET",headers:{[u]:e,[m]:p,"x-mfm-adaptor":t}}).then((e=>{if(!e.ok)throw e;return e.json()})).then((e=>{if(e){const{di:t,iv:o,_o:r,_mck:s,mk:a,r:d}=e,c=_({di:t,iv:o},r);w({_o:r,mk:a,_mck:s,_rules:d}),c&&(i(c),n(c,{_o:r,mk:a,_mck:s,_rules:d}))}})).catch((e=>{console.error("Error in loading mocked APIs:",e),o(e)}))}const M='<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:block;"><path d="M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8"></path><polyline points="21 3 21 8 16 8"></polyline></svg>',L='<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:block;"><circle cx="12" cy="12" r="1.5"></circle><circle cx="12" cy="5" r="1.5"></circle><circle cx="12" cy="19" r="1.5"></circle></svg>',$='<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:block;"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>',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.widgetKey=e.widgetKey||null,this.mockedRequests=[],this.otherRequests=[],this.state={isOpen:"undefined"!=typeof localStorage&&"true"===localStorage.getItem("mockforme-widget-open"),activeTab:"mappings",selectedRequest:null,activeRequestTab:"response",lastError:null,searchQuery:""},"undefined"!=typeof document&&(window.addEventListener("resize",(()=>{this.bubble&&this.keepInBounds(this.bubble)})),document.addEventListener("click",(e=>{this.sharedDropdown&&this.sharedDropdown.classList.remove("show")}))))}init(){if("undefined"!=typeof document&&document.getElementById)if(this.checkVisibility())if(document.body)this.initWidget();else{const e=()=>{document.body&&this.initWidget()};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",e,{once:!0}):"interactive"===document.readyState||"complete"===document.readyState?setTimeout(e,0):window.addEventListener("load",e,{once:!0})}else{const e=document.getElementById("mockforme-root");e&&e.remove()}}initWidget(){document.getElementById("mockforme-root")||(this.createStyles(),this.render())}setWidgetKey(e){this.widgetKey=e,this.init()}checkVisibility(){return!this.widgetKey||"undefined"!=typeof localStorage&&localStorage.getItem("widgetKey")===this.widgetKey}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: 0px 12px;\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: 28px;\n height: 28px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #2563eb;\n transition: background 0.2s;\n margin-right: 10px;\n background: #f3f4f6;\n padding: 0;\n }\n .mfm-refresh-icon svg { width: 16px; height: 16px; }\n .mfm-refresh-icon:hover { }\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: 80vh;\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 @media (max-width: 480px) {\n .mfm-bottomsheet { padding: 16px; }\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: 15px;\n padding-bottom: 10px;\n border-bottom: 1px solid #eee;\n flex-shrink: 0;\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-title img { height: 30px; }\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; padding: 4px; cursor: pointer; color: #666; display: flex; align-items: center; justify-content: center; }\n .mfm-close:hover { color: #111; background: #f3f4f6; border-radius: 4px; }\n /* Login Form */\n .mfm-logo-container { text-align: center; padding: 20px 0; width: 100%; display: flex; justify-content: center; flex-shrink: 0; }\n .mfm-logo { width: 120px; 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 { \n display: flex; \n border-bottom: 1px solid #dee2e6; \n margin-bottom: 10px; \n flex-shrink: 0; \n gap: 2px;\n }\n .mfm-tab {\n padding: 8px 16px;\n cursor: pointer;\n color: #666;\n border: 1px solid transparent;\n border-bottom: none;\n border-top-left-radius: 6px;\n border-top-right-radius: 6px;\n font-weight: 300;\n font-size: 14px;\n margin-bottom: -1px;\n transition: all 0.2s;\n }\n .mfm-tab:hover {\n background-color: #f8f9fa;\n border-color: #e9ecef #e9ecef transparent;\n }\n .mfm-tab.active { \n color: #2563eb; \n background-color: white;\n border: 1px solid #dee2e6;\n border-bottom: 1px solid white;\n font-weight: 500;\n }\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 flex-wrap: wrap;\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; flex-shrink: 0; }\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; cursor: pointer; color: #666; display: flex; align-items: center; justify-content: center; padding: 4px; border-radius: 4px; }\n .mfm-icon-btn:hover { color: #333; background: #f3f4f6; }\n .mfm-icon-btn.refresh { color: #2563eb; padding: 0; height: 24px; width:24px; 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-non-2xx { color: #dc2626; }\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-redirect-badge {\n font-size: 10px;\n color: #166534;\n background: #dcfce7;\n padding: 2px 6px;\n border-radius: 10px;\n margin-top: 2px;\n display: inline-block;\n font-weight: 500;\n border: 1px solid #bbf7d0;\n }\n\n /* Mapping UI Enhanced */\n .mfm-mapping-info { display: flex; flex-direction: column; flex: 1; overflow: hidden; }\n .mfm-rule-name { font-weight: 600; color: #1f2937; margin-bottom: 2px; display: block; overflow: hidden; text-overflow: ellipsis; }\n .mfm-condition-brief { font-size: 11px; color: #6b7280; font-family: monospace; cursor: pointer; }\n .mfm-condition-brief:hover { color: #2563eb; text-decoration: underline; }\n .mfm-mod-actions-count { \n font-size: 10px; \n background: #eff6ff; \n color: #1d4ed8; \n padding: 2px 6px; \n border-radius: 12px; \n cursor: pointer; \n font-weight: 600;\n margin-top: 4px;\n display: inline-block;\n width: fit-content;\n }\n .mfm-mod-actions-count:hover { background: #dbeafe; }\n\n /* Modals */\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: 90%;\n max-width: 400px;\n max-height: 80vh;\n overflow-y: auto;\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: 12px; display: flex; justify-content: space-between; align-items: center; }\n .mfm-modal-body { font-size: 14px; color: #4b5563; }\n .mfm-modal-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 20px; }\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 .mfm-mod-item { border-bottom: 1px solid #eee; padding-bottom: 8px; margin-bottom: 8px; }\n .mfm-mod-item:last-child { border-bottom: none; margin-bottom: 0; }\n .mfm-mod-type { font-weight: 600; font-size: 12px; color: #2563eb; text-transform: uppercase; margin-bottom: 4px; }\n .mfm-mod-detail { font-size: 11px; font-family: monospace; word-break: break-all; }\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 .mfm-duration { color: #666; font-size: 11px; margin-left: 8px; font-weight: normal; }\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 .section-header { display: flex; align-items: center; justify-content: space-between; margin: 10px 0 5px; }\n .mfm-copy-btn {\n background: #f1f5f9;\n color: #64748b;\n padding: 2px 8px;\n border-radius: 4px;\n font-size: 10px;\n cursor: pointer;\n border: 1px solid #e2e8f0;\n transition: all 0.2s;\n font-weight: 600;\n text-transform: uppercase;\n }\n .mfm-copy-btn:hover { background: #e2e8f0; color: #334155; }\n \n .mfm-copy-group {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n margin-top: 4px;\n }\n .mfm-copy-group .mfm-copy-btn {\n font-size: 9px;\n padding: 2px 6px;\n }\n\n /* Dropdown Menu */\n .mfm-menu-dots {\n cursor: pointer;\n padding: 4px;\n color: #666;\n border-radius: 4px;\n transition: background 0.2s;\n line-height: 1;\n margin-left: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n .mfm-menu-dots:hover { background: #f3f4f6; color: #333; }\n \n .mfm-dropdown-shared {\n position: fixed;\n background: white;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0,0,0,0.15);\n z-index: 1000005;\n display: none;\n flex-direction: column;\n width: 160px;\n overflow: hidden;\n }\n .mfm-dropdown-shared.show { display: flex; }\n .mfm-dropdown-item {\n padding: 10px 14px;\n font-size: 13px;\n color: #334155;\n cursor: pointer;\n transition: background 0.2s;\n text-align: left;\n border-bottom: 1px solid #f1f5f9;\n white-space: nowrap;\n }\n .mfm-dropdown-item:last-child { border-bottom: none; }\n .mfm-dropdown-item:hover { background: #f8fafc; color: #2563eb; }\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 ",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.sharedDropdown=document.createElement("div"),this.sharedDropdown.className="mfm-dropdown-shared",this.sharedDropdown.innerHTML='\n <div class="mfm-dropdown-item" data-format="curl">Copy as cURL</div>\n <div class="mfm-dropdown-item" data-format="fetch">Copy as Fetch</div>\n <div class="mfm-dropdown-item" data-format="xhr">Copy as XHR</div>\n ',this.root.appendChild(this.sharedDropdown),this.updateUI()}updateUI(){this.sheet&&(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">${M}</div>\n <img src="https://ik.imagekit.io/mfm/static-collection/mfm-48x48.png" alt="MFM" />\n `,this.addDragLogic(e),this.keepInBounds(e),e.querySelector("img").onclick=e=>{this.isDragging||this.toggleSheet()},e.querySelector(".mfm-refresh-icon").onclick=e=>{e.stopPropagation(),this.refreshMappings()},e}keepInBounds(e){const t=e.getBoundingClientRect(),n=10;let o=parseInt(e.style.right)||20,r=parseInt(e.style.bottom)||20;const s=window.innerWidth-t.width-n,i=window.innerHeight-t.height-n;o<n&&(o=n),r<n&&(r=n),o>s&&(o=s),r>i&&(r=i),e.style.right=o+"px",e.style.bottom=r+"px"}addDragLogic(e){let t,n,o,r,s=!1;const i=(i,a)=>{s=!1,this.isDragging=!1,t=i,n=a;const d=e.getBoundingClientRect();o=window.innerWidth-d.right,r=window.innerHeight-d.bottom},a=(i,a)=>{const d=t-i,c=n-a;(Math.abs(d)>3||Math.abs(c)>3)&&(s=!0,this.isDragging=!0),s&&(e.style.right=o+d+"px",e.style.bottom=r+c+"px")},d=()=>{s&&(this.keepInBounds(e),"undefined"!=typeof localStorage&&localStorage.setItem("mockforme-dot-pos",JSON.stringify({bottom:parseInt(e.style.bottom),right:parseInt(e.style.right)})))},c=e=>{a(e.clientX,e.clientY)},l=()=>{document.removeEventListener("mousemove",c),document.removeEventListener("mouseup",l),d()},m=e=>{const t=e.touches[0];a(t.clientX,t.clientY),s&&e.cancelable&&e.preventDefault()},u=()=>{document.removeEventListener("touchmove",m),document.removeEventListener("touchend",u),d()};e.addEventListener("mousedown",(e=>{i(e.clientX,e.clientY),document.addEventListener("mousemove",c),document.addEventListener("mouseup",l)})),e.addEventListener("touchstart",(e=>{const t=e.touches[0];i(t.clientX,t.clientY),document.addEventListener("touchmove",m,{passive:!1}),document.addEventListener("touchend",u)}),{passive:!0})}toggleSheet(){this.state.isOpen=!this.state.isOpen,"undefined"!=typeof localStorage&&localStorage.setItem("mockforme-widget-open",this.state.isOpen),this.updateUI()}showSnackbar(e){this.snackbar&&(this.snackbar.textContent=e,this.snackbar.classList.add("show"),setTimeout((()=>this.snackbar.classList.remove("show")),3e3))}showConfirm(e,t,n){this.showModal(e,t,[{label:"Cancel",className:"mfm-btn-alt",onClick:e=>e.classList.remove("show")},{label:"Delete",className:"mfm-btn-danger",onClick:e=>{e.classList.remove("show"),n()}}])}showModal(e,t,n=[]){if(!this.modalOverlay)return;this.modalOverlay.innerHTML=`\n <div class="mfm-modal">\n <div class="mfm-modal-title">\n <span>${e}</span>\n <span style="cursor:pointer;" id="mfm-modal-close">${$}</span>\n </div>\n <div class="mfm-modal-body">${t}</div>\n <div class="mfm-modal-actions" id="mfm-modal-actions"></div>\n </div>\n `;const o=this.modalOverlay.querySelector("#mfm-modal-actions");if(n.forEach((e=>{const t=document.createElement("button");t.className=e.className||"mfm-btn-alt",t.textContent=e.label,t.onclick=()=>e.onClick(this.modalOverlay),o.appendChild(t)})),0===n.length){const e=document.createElement("button");e.className="mfm-btn",e.textContent="OK",e.onclick=()=>this.modalOverlay.classList.remove("show"),o.appendChild(e)}this.modalOverlay.querySelector("#mfm-modal-close").onclick=()=>{this.modalOverlay.classList.remove("show")},this.modalOverlay.classList.add("show")}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 o=n.value.trim();o&&(t.textContent="Validating...",t.disabled=!0,this.state.lastError=null,e.querySelector("#mfm-error-msg").style.display="none",T(o,c,((e,t)=>{"undefined"!=typeof localStorage&&localStorage.setItem("mockforme-token",o),this.token=o,this.isAuthenticated=!0,this.mappings=e,this.rules=t?._rules||[],this.onAuthSuccess(o,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}updateMappings(e,t){this.mappings=e||[],this.rules=t?._rules||[],this.root&&this.updateUI()}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"><img src="https://www.mockforme.com/assets/images/logo.png" /></span>\n <div class="mfm-header-actions">\n <button class="mfm-close">${$}</button>\n </div>\n </div>\n `;const t=document.createElement("div");t.className="mfm-tabs",["mappings","mocked","other","settings"].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"===e?"Other Apis":"Settings",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">${M}</div>\n `,n.querySelector("#mfm-refresh-mappings-btn").onclick=()=>this.refreshMappings()):"settings"!==this.state.activeTab?(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"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:block;"><circle cx="12" cy="12" r="10"></circle><line x1="4.93" y1="4.93" x2="19.07" y2="19.07"></line></svg></button>\n `,n.querySelector("#mfm-search-input").oninput=e=>{this.state.searchQuery=e.target.value,this.updateRequestList(o)},n.querySelector("#mfm-clear-requests-btn").onclick=()=>{"mocked"===this.state.activeTab?this.mockedRequests=[]:this.otherRequests=[],this.updateUI()}):n.style.display="none",t.after(n);const o=document.createElement("div");return o.className="mfm-list",this.updateRequestList(o),e.appendChild(o),e.querySelector(".mfm-close").onclick=()=>this.toggleSheet(),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.rule||t,o=e.timingAction||{},r=o.activeAction||"none",s=o.actions?.[r]?.value,i=`Rule (${r}${void 0!==s?` ${s}s`:""})`;let a="{}";e.conditions&&Array.isArray(e.conditions)&&(a=e.conditions.map((e=>`${e.type}:${e.operator}:${e.value}`)).join(" AND "));const d=a.length>40?a.substring(0,40)+"...":a;let c=0;const l=e.modificationActions||{};Object.values(l).forEach((e=>{e.enabled&&(e.add&&(c+=e.add.length),e.remove&&(c+=e.remove.length),e.update&&(c+=e.update.length))})),n.innerHTML=`\n <div class="mfm-mapping-info">\n <span class="mfm-rule-name" style="cursor:pointer; color:#2563eb; text-decoration:underline;" id="mfm-view-full-rule" title="View full rule details">${i}</span>\n <span class="mfm-condition-brief" title="View condition">\n ${d} <span style="font-weight:bold; color:#2563eb; margin-left:4px; cursor:pointer;" id="mfm-view-cond-dots">${L}</span>\n </span>\n ${c>0?`<div class="mfm-mod-actions-count" id="mfm-view-mods">${c} Modification Actions</div>`:""}\n </div>\n <span class="mfm-method RULE">RULE</span>\n `,n.querySelector("#mfm-view-full-rule").onclick=t=>{t.stopPropagation();const n=JSON.stringify(e,null,2);this.showModal("Full Rule Information",`<pre class="mfm-code-block">${n}</pre>`)},n.querySelector("#mfm-view-cond-dots").onclick=t=>{t.stopPropagation();const n=e.conditions.map((e=>`\n <div class="mfm-mod-item">\n <div class="mfm-mod-type">${e.type} (${e.operator})</div>\n <div class="mfm-mod-detail"><b>Key:</b> ${e.key||"N/A"}<br><b>Value:</b> ${e.value}</div>\n </div>\n `)).join("");this.showModal("Rule Conditions",n)},c>0&&(n.querySelector("#mfm-view-mods").onclick=e=>{e.stopPropagation();let t="";Object.entries(l).forEach((([e,n])=>{n.enabled&&(t+=`<div class="mfm-mod-item"><div class="mfm-mod-type">${e.replace("modify","")}</div>`,n.add?.length&&(t+=`<div class="mfm-mod-detail"><b>Add:</b> ${JSON.stringify(n.add)}</div>`),n.update?.length&&(t+=`<div class="mfm-mod-detail"><b>Update:</b> ${JSON.stringify(n.update)}</div>`),n.remove?.length&&(t+=`<div class="mfm-mod-detail"><b>Remove:</b> ${JSON.stringify(n.remove)}</div>`),t+="</div>")})),this.showModal("Modification Actions",t)})}e.appendChild(n)}))}else if("settings"===this.state.activeTab)e.innerHTML='\n <div style="padding: 16px;">\n <div class="section-title" style="margin-top: 0; margin-bottom: 12px; font-size: 15px; border-bottom: 1px solid #eee; padding-bottom: 8px;">Token Management</div>\n <p style="font-size: 13px; color: #666; margin-bottom: 16px;">Removing your token will clear all saved mappings and rules from this browser instance.</p>\n <button class="mfm-delete-token-btn" id="mfm-settings-delete-token" style="padding: 8px 16px; font-size: 14px; width: fit-content;">\n <span><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:block;"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path><line x1="10" y1="11" x2="10" y2="17"></line><line x1="14" y1="11" x2="14" y2="17"></line></svg></span>\n <span>Delete Token</span>\n </button>\n </div>\n ',e.querySelector("#mfm-settings-delete-token").onclick=()=>{this.showConfirm("Delete Token","Are you sure you want to Delete Token? This will clear your saved token.",(()=>{this.deleteToken()}))};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 o=(t.method||"").toUpperCase(),r=`<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>`;let s="",i="";if(t.rule){const e=t.rule.action||"";let n="delay_and_timeout"===e?"Delay and Timout":e.split("_")[0];const o=t.rule.config?.value;void 0!==o&&(e.includes("delay")||e.includes("timeout"))&&(n+=` (${o}s)`),s=`<span class="mfm-rule-tag" title="${e}">${n}</span>`,"delay_and_redirect"===e&&t.rule.config?.redirectUrl&&(i=`<div class="mfm-redirect-badge">Redirected to: ${t.rule.config.redirectUrl}</div>`)}let a=t.status,d="mfm-status";t.pending?a='<span class="mfm-spinner"></span>':t.aborted?(a="Aborted",d+=" status-aborted"):t.timeout?(a="Timeout",d+=" status-timeout"):t.error?(a="Error/CORS",d+=" status-error"):(a=t.status,d+=t.status>=200&&t.status<300?" status-2xx":" status-non-2xx"),n.innerHTML=`\n <div style="display:flex; align-items:center; width:100%; gap:8px;">\n <span class="mfm-method ${o}">${o}</span>\n <div style="flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; justify-content:center;">\n <span class="mfm-url">${s}${t.url}</span>\n ${i}\n ${r}\n </div>\n <span class="${d}">${a}</span>\n <span class="mfm-menu-dots" title="Copy As...">${L}</span>\n </div>\n `;const c=n.querySelector(".mfm-menu-dots");c.onclick=e=>{e.stopPropagation();const n=c.getBoundingClientRect();this.sharedDropdown.style.top=n.bottom+5+"px",this.sharedDropdown.style.left=n.right-160+"px",this.sharedDropdown.classList.toggle("show"),this.sharedDropdown.onclick=e=>{e.stopPropagation();const n=e.target.getAttribute("data-format");if(!n)return;let o="";"curl"===n?o=this.generateCurl(t):"fetch"===n?o=this.generateFetch(t):"xhr"===n&&(o=this.generateXHR(t)),o&&navigator.clipboard.writeText(o).then((()=>{this.showSnackbar(`${n.toUpperCase()} copied!`),this.sharedDropdown.classList.remove("show")}))}},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"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:inline-block; vertical-align:middle; margin-right:4px;"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg>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 o=document.createElement("div");o.style.overflowY="auto",o.style.flex="1";const r=(e.method||"").toUpperCase(),s=this.formatBody(e.requestBody),i=this.formatBody(e.responseBody);o.innerHTML="request"===this.state.activeRequestTab?`\n <div class="section-title">URL</div><div class="mfm-code-block">${r} ${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-header">\n <div class="section-title" style="margin: 0;">Payload</div>\n <div class="mfm-copy-btn" id="mfm-copy-payload">Copy</div>\n </div>\n <div class="mfm-code-block">${s}</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-header">\n <div class="section-title" style="margin: 0;">Response Body</div>\n <div class="mfm-copy-btn" id="mfm-copy-response">Copy</div>\n </div>\n <div class="mfm-code-block">${i}</div>\n `,t.appendChild(n),t.appendChild(o);const a=o.querySelector("#mfm-copy-payload");a&&(a.onclick=()=>{navigator.clipboard.writeText(s).then((()=>{this.showSnackbar("Payload copied!")}))});const d=o.querySelector("#mfm-copy-response");return d&&(d.onclick=()=>{navigator.clipboard.writeText(i).then((()=>{this.showSnackbar("Response copied!")}))}),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("undefined"!=typeof FormData&&e instanceof FormData){const t={};return e.forEach(((e,n)=>{"undefined"!=typeof File&&e instanceof File?t[n]=`[File: ${e.name} (${e.size} bytes)]`:"undefined"!=typeof Blob&&e instanceof Blob?t[n]=`[Blob: ${e.type} (${e.size} bytes)]`:t[n]=e})),JSON.stringify(t,null,2)}if("undefined"!=typeof URLSearchParams&&e instanceof URLSearchParams)return JSON.stringify(Object.fromEntries(e.entries()),null,2);if("undefined"!=typeof Blob&&e instanceof Blob)return`[${"undefined"!=typeof File&&e instanceof File?"File":"Blob"}: ${e.type||"binary"} (${e.size} bytes)]`;if(e instanceof ArrayBuffer||"undefined"!=typeof Uint8Array&&e instanceof Uint8Array)return`[Binary Data: ${e.byteLength||e.length} bytes]`;if("object"==typeof e)try{return JSON.stringify(e,null,2)}catch{return String(e)}try{return JSON.stringify(JSON.parse(e),null,2)}catch{return e}}generateCurl(e){const t=(e.method||"GET").toUpperCase();let n=`curl -X ${t} "${e.url}"`;if(e.requestHeaders&&Object.entries(e.requestHeaders).forEach((([e,t])=>{n+=` \\\n -H "${e}: ${t}"`})),e.requestBody&&"GET"!==t){const t=("string"==typeof e.requestBody?e.requestBody:JSON.stringify(e.requestBody)).replace(/'/g,"'\\''");n+=` \\\n --data-raw '${t}'`}return n}generateFetch(e){const t=(e.method||"GET").toUpperCase();let n=`{\n method: "${t}",\n headers: ${(e.requestHeaders?JSON.stringify(e.requestHeaders,null,2):"{}").replace(/\n/g,"\n ")}`;if(e.requestBody&&"GET"!==t){const t="string"==typeof e.requestBody?e.requestBody:JSON.stringify(e.requestBody,null,2);n+=`,\n body: ${"string"==typeof e.requestBody?"`"+t+"`":JSON.stringify(e.requestBody,null,2).replace(/\n/g,"\n ")}`}return n+="\n}",`fetch("${e.url}", ${n})\n .then(response => response.json())\n .then(data => console.log(data))\n .catch(error => console.error(error));`}generateXHR(e){const t=(e.method||"GET").toUpperCase();let n=`var xhr = new XMLHttpRequest();\nxhr.open("${t}", "${e.url}");\n`;if(e.requestHeaders&&Object.entries(e.requestHeaders).forEach((([e,t])=>{n+=`xhr.setRequestHeader("${e}", "${t}");\n`})),n+="\nxhr.onload = function() {\n console.log(xhr.responseText);\n};\n",e.requestBody&&"GET"!==t){const t="string"==typeof e.requestBody?e.requestBody:JSON.stringify(e.requestBody);n+=`\nxhr.send(${"string"==typeof e.requestBody?"`"+t+"`":JSON.stringify(e.requestBody)});`}else n+="\nxhr.send();";return n}addRequest(e,t){const n=String(t.method||"").toUpperCase().trim(),o=String(t.url||"");console.log(`[MockForMe] addRequest type=${e} method=${n} url=${o} requestId=${t.requestId} pending=${t.pending}`);const r=o.includes("api.mockforme.com")||o.includes("mockforme.com/proxy")||o.includes("mockforme.com/gateway")||o.includes("/3f4eae522b")||f&&o.includes(String(f));if("OPTIONS"===n||r)return;const s="mocked"===e?this.mockedRequests:this.otherRequests,i="mocked"===e?this.otherRequests:this.mockedRequests;if(t.requestId){const e=s.findIndex((e=>e.requestId===t.requestId));if(-1!==e)return s[e]={...s[e],...t},void this.updateUI();const n=i.findIndex((e=>e.requestId===t.requestId));if(-1!==n){const e={...i[n],...t};return i.splice(n,1),s.unshift(e),s.length>100&&s.pop(),void this.updateUI()}}s.unshift(t),s.length>100&&s.pop(),this.updateUI()}};class A{static match(e,t){if(!Array.isArray(t)||0===t.length)return!1;const{url:n,headers:o,queryParams:r,body:s}=e,i="undefined"!=typeof window?window.location.origin:globalThis.location?.origin||"http://localhost";for(const e of t){let t="";const{type:a,key:d,operator:c,value:l}=e;switch(a){case"URL":try{t=new URL(n,i).pathname}catch{t=n}break;case"QUERY_PARAM":if(r&&void 0!==r[d])t=String(r[d]);else try{t=new URL(n,i).searchParams.get(d)||""}catch{t=""}break;case"REQUEST_BODY":if(d){if("object"==typeof s&&null!==s)t=void 0!==s[d]?String(s[d]):"";else if("string"==typeof s)try{const e=JSON.parse(s);t=void 0!==e[d]?String(e[d]):""}catch{t=""}}else t="object"==typeof s?JSON.stringify(s):String(s||"");break;case"REQUEST_HEADER":if(d){const e=d?.toLowerCase();if(t="",o){const n=Object.keys(o).find((t=>t.toLowerCase()===e));t=n?String(o[n]):""}}else t=JSON.stringify(o||{});break;default:return!1}if(!this.evaluate(t,c,l))return!1}return!0}static evaluate(e,t,n){const o=t?.toLowerCase(),r=String(e),s=String(n);switch(o){case"contains":return r.includes(s);case"equal":case"equals":return r===s;case"regexp":try{let e=s;if(e.startsWith("/")&&e.lastIndexOf("/")>0){const t=e.lastIndexOf("/"),n=e.slice(1,t),o=e.slice(t+1);return new RegExp(n,o).test(r)}return new RegExp(e).test(r)}catch{return!1}default:return!1}}}class O{static async apply(e){if(!e||!e.activeAction)return{type:"passThrough",delay:0};const{activeAction:t,actions:n}=e,o=n?.[t];if(!o)return{type:"passThrough",delay:0};const r={type:"passThrough",delay:0},s=Number(o.value||0);switch(t){case"delay":r.delay=s,r.delay>0&&await new Promise((e=>setTimeout(e,1e3*r.delay)));break;case"delay_and_redirect":r.type="redirect",r.delay=s,r.redirectUrl=o.redirectUrl,r.delay>0&&await new Promise((e=>setTimeout(e,1e3*r.delay)));break;case"delay_and_timeout":r.type="timeout",r.delay=s,r.delay>0&&await new Promise((e=>setTimeout(e,1e3*r.delay)))}return r}}class C{static applyRequestModifications(e,t){if(!t)return e;let{url:n,headers:o,queryParams:r,body:s}={...e};o&&(o={...o}),r&&(r={...r});const{modifyQueryParams:i,modifyRequestBody:a,modifyRequestHeaders:d}=t;if(i?.enabled)try{const e=new URL(n,"undefined"!=typeof window?window.location.href:"http://localhost");Array.isArray(i.remove)&&i.remove.forEach((t=>{e.searchParams.delete(t),r&&delete r[t]})),Array.isArray(i.add)&&i.add.forEach((({key:t,value:n})=>{e.searchParams.set(t,n),r&&(r[t]=n)})),n=e.toString()}catch(e){console.error("[MockForMe] Failed to modify query params",e)}if(d?.enabled&&(o={...o},Array.isArray(d.remove)&&d.remove.forEach((e=>{const t=e.toLowerCase(),n=Object.keys(o).find((e=>e.toLowerCase()===t));n&&delete o[n]})),Array.isArray(d.add)&&d.add.forEach((({key:e,value:t})=>{o[e]=t}))),a?.enabled)try{let t=null;if("string"==typeof s)try{t=JSON.parse(s)}catch{}else if("object"==typeof s&&null!==s)try{t=JSON.parse(JSON.stringify(s))}catch{t={...s}}t&&(Array.isArray(a.remove)&&a.remove.forEach((e=>delete t[e])),Array.isArray(a.add)&&a.add.forEach((({key:e,value:n})=>t[e]=n)),Array.isArray(a.update)&&a.update.forEach((({key:e,value:n})=>t[e]=n)),s="string"==typeof e.body?JSON.stringify(t):t)}catch(e){console.error("[MockForMe] Failed to modify request body",e)}return{...e,url:n,headers:o,queryParams:r,body:s}}static applyResponseModifications(e,t){if(!t?.modifyResponseHeaders?.enabled)return e;const{modifyResponseHeaders:n}=t,o={...e};return Array.isArray(n.remove)&&n.remove.forEach((e=>{const t=e.toLowerCase(),n=Object.keys(o).find((e=>e.toLowerCase()===t));n&&delete o[n]})),Array.isArray(n.add)&&n.add.forEach((({key:e,value:t})=>{o[e]=t})),o}}class H{static match(e,t){if(!Array.isArray(t)||0===t.length)return null;for(const n of t){const t=n.rule||n;if(t.conditions&&Array.isArray(t.conditions)&&A.match(e,t.conditions)){const e=t.timingAction?.activeAction||"";return{action:e,config:t.timingAction?.actions?.[e]||{},rule:t}}}return null}static async apply(e,t){if(!e)return null;const n=e.rule||e,o=C.applyRequestModifications(t,n.modificationActions);return{...await O.apply(n.timingAction),modifiedRequest:o,rule:n}}static applyResponseModifications(e,t){return C.applyResponseModifications(e,t)}}class U{static apply({target:e=("undefined"!=typeof window?window:globalThis),originalFetch:t=e.fetch,ruleProvider:n=()=>[],mappingProvider:o=e=>null,onBeforeRequest:r=e=>{},onRuleMatch:s=async(e,t,n,o,r)=>null,onMockMatch:i=async(e,t,n,o,r)=>null,onOtherRequest:a=async(e,t,n,o)=>null}){t&&(e.fetch=async function(e,d={}){let c;try{const t="string"==typeof e?e:e.url,n=String(d.method||(e instanceof Request?e.method:"GET")).toUpperCase().trim(),o=Math.random().toString(36).substring(7);c={url:t,method:n,headers:d.headers||(e instanceof Request?e.headers:{}),body:d.body||(e instanceof Request?"{binary/stream}":null),requestId:o,queryParams:U.getQueryParams(t)},r(c)}catch(n){return console.warn("[MockForMe] Fetch Interceptor Setup Error:",n),t(e,d)}try{const r=n(),l=H.match(c,r);if(l){const n=await s(l,c,e,d,t);if(n)return n}const m=o(c);if(m){const n=await i(m,c,e,d,t);if(n)return n}const u=await a(c,e,d,t);if(u)return u}catch(e){if(e.message.includes("timed out")||"AbortError"===e.name||e.message.includes("rules"))throw e;console.warn("[MockForMe] Interceptor Hook Error:",e)}return t(e,d)})}static getQueryParams(e){try{const t="undefined"!=typeof window?window.location.origin:"http://localhost",n=new URL(e,t).searchParams;return Object.fromEntries(n.entries())}catch{return{}}}}class B{static apply({target:e=("undefined"!=typeof window?window:{}),OriginalXHR:t=e.XMLHttpRequest,ruleProvider:n=()=>[],mappingProvider:o=e=>null,onBeforeRequest:r=e=>{},onRuleMatch:s=(e,t,n,o)=>{o.call(n.proxy,t.body)},onMockMatch:i=(e,t,n,o)=>{o.call(n.proxy,t.body)},onOtherRequest:a=(e,t,n)=>{n.call(t.proxy,e.body)}}){t&&(e.XMLHttpRequest=class{constructor(){return this._xhr=new t,this._headers={},this._method=null,this._url=null,this._body=null,this._requestId=null,this._startTime=null,this._captured=!1,this._isMocked=!1,this.proxy=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)}),this.proxy}_capture(e,t,n,o={}){if(this._captured)return;this._captured=!0;const r=e=>{const t=`on${e}`;(this[t]||this._xhr[t])?.(),this._xhr.dispatchEvent(new Event(e))};if("Aborted"!==e)try{Object.defineProperty(this.proxy,"responseText",{value:t,configurable:!0}),Object.defineProperty(this.proxy,"response",{value:t,configurable:!0}),Object.defineProperty(this.proxy,"status",{value:Number(e)||0,configurable:!0}),Object.defineProperty(this.proxy,"statusText",{value:200==e?"OK":"",configurable:!0})}catch(e){console.warn("[MockForMe] Error setting XHR props",e)}Object.defineProperty(this.proxy,"readyState",{value:4,configurable:!0}),r("readystatechange"),"Aborted"===e||o.aborted?r("abort"):0===e||"Error"===e||o.error?r("error"):"Timeout"===e||o.timeout?r("timeout"):r("load")}open(e,t,n=!0,o=null,r=null){this._method=(e||"").toUpperCase().trim();try{this._url=new URL(t,"undefined"!=typeof window?window.location.href:"http://localhost").toString()}catch(e){this._url=t}return this._xhr.open(e,t,n,o,r)}setRequestHeader(e,t){return this._headers[e]=t,this._xhr.setRequestHeader(e,t)}send(e){this._body=e,this._requestId=Math.random().toString(36).substring(7),this._startTime=Date.now();const t={url:this._url,method:this._method,headers:this._headers,body:this._body,requestId:this._requestId,startTime:this._startTime,queryParams:B.getQueryParams(this._url)};r(t);const d=n(),c=H.match(t,d),l=e=>this._xhr.send(e);if(c)return this._isMocked=!0,s(c,t,this,l);const m=o(t);return m?(this._isMocked=!0,i(m,t,this,l)):(this._isMocked=!1,a(t,this,l))}})}static getQueryParams(e){try{const t="undefined"!=typeof window?window.location.origin:"http://localhost",n=new URL(e,t).searchParams;return Object.fromEntries(n.entries())}catch{return{}}}}const P=(e,t=null,o=c)=>{if(n())return;let r="string"==typeof e?e:e?.token,s="object"==typeof e?e?.widgetKey:null;if(s?I.setWidgetKey(s):I.init(),o===c)try{r&&("undefined"!=typeof localStorage&&localStorage.removeItem("mockforme-token"),I.token=r,I.isAuthenticated=!0),!r&&I.token&&(r=I.token),I.onAuthSuccess=(e,t,n)=>{i(t),w(n),I.updateMappings(t,n)}}catch(e){console.log("Error in showing mockforme widget",e)}t||={mappings:[],_o:null,mk:null,_mck:null,_rules:[]};const{mappings:h=[],_o:f,mk:y,_mck:b,_rules:x=[]}=t;return i(h),w({_o:f,mk:y,_mck:b,_rules:x}),{run:(e,t=()=>{})=>{!function(e,t){if("undefined"!=typeof window){if(window._mfm_intercepted)return;window._mfm_intercepted=!0}const n=()=>I.token||e;U.apply({ruleProvider:()=>k(),mappingProvider:e=>{try{return d(new URL(e.url,window.location.origin).pathname,e.method)}catch{return null}},onRuleMatch:async(e,t,n,o,r)=>{const s=t.requestId||Math.random().toString(36).substring(7),i=Date.now();I.addRequest("mocked",{...t,requestId:s,pending:!0,startTime:i,rule:e});const a=await H.apply(e,t),{modifiedRequest:d,type:c,delay:l,redirectUrl:m}=a;if("timeout"!==c&&I.addRequest("mocked",{...d,requestId:s,pending:!0,startTime:i,rule:e}),"timeout"===c){const e=Date.now()-i;throw I.addRequest("mocked",{...d,requestId:s,status:"Aborted",pending:!1,duration:e,aborted:!0}),new Error("Fetch timed out by rules")}let u="redirect"===c?m:d.url,p={...o};d.headers&&(p.headers=d.headers),d.body&&(p.body=d.body);let h=null;if("redirect"===c){h=Math.random().toString(36).substring(7);const e={url:m,method:d.method,headers:p.headers||{},body:p.body,requestId:h,queryParams:U.getQueryParams(m),requestHeaders:p.headers||{},requestBody:p.body,pending:!0,startTime:Date.now()};I.addRequest("mocked",e)}return r(u,p).then((async e=>{const t=Date.now()-i;let n=Object.fromEntries(e.headers.entries());if(a.rule.modificationActions?.modifyResponseHeaders?.enabled&&(n=H.applyResponseModifications(n,a.rule.modificationActions)),"redirect"===c&&h){const t=e.clone(),o=t.headers.get("content-type")||"",r=Date.now()-i;try{let s;s=o.includes("application/json")?await t.json():await t.text(),I.addRequest("mocked",{url:m,method:d.method,requestId:h,status:e.status,pending:!1,duration:r,responseHeaders:n,responseBody:s,requestHeaders:p.headers||{},requestBody:p.body})}catch(t){I.addRequest("mocked",{url:m,method:d.method,requestId:h,status:e.status,pending:!1,duration:r,responseHeaders:n,requestHeaders:p.headers||{},requestBody:p.body})}}return I.addRequest("mocked",{...d,requestId:s,status:e.status,pending:!1,duration:t,responseHeaders:n}),e})).catch((e=>{const t=Date.now()-i,n="AbortError"===e.name||e.message.includes("aborted");throw I.addRequest("mocked",{...d,requestId:s,status:n?"Aborted":0,pending:!1,duration:t}),"redirect"===c&&h&&I.addRequest("mocked",{url:m,method:d.method,requestId:h,status:n?"Aborted":0,pending:!1,duration:t,error:!n}),e}))},onMockMatch:async(e,o,r,s,i)=>{const a=o.requestId||Math.random().toString(36).substring(7),d=Date.now();I.addRequest("mocked",{...o,requestId:a,pending:!0,startTime:d});const c=n(),h=new URL(o.url,window.location.origin).search;let f=`${q()}${e.url}${h}`,g={[u]:c,[m]:p,"x-mfm-adaptor":t};const y=E();y&&e._ack&&(g["x-mfm-key"]=`${y}-${e._ack}`),e?._ri_&&(g._ri_=e._ri_);const b=r instanceof Request?r.headers:s.headers,x=new Headers(b||{});Object.entries(g).forEach((([e,t])=>x.set(e,t)));let v=s.body;if(!v&&r instanceof Request){const e=r.clone();"GET"!==e.method&&"HEAD"!==e.method&&(v=await e.text())}const w={method:o.method,headers:x,credentials:r instanceof Request&&r.credentials||s.credentials||"include",mode:r instanceof Request&&r.mode||s.mode||"cors"};return t===l?(({actualUrl:e,url:t,method:n,headers:o,body:r,credentials:s,mode:i,rule:a})=>{const d=`${Date.now()}-${Math.random()}`,c=R(t);return new Promise(((t,l)=>{window.addEventListener("message",(function e(n){if(n.source!==window)return;const o=n.data;if("INTERCEPTED_RESPONSE"===o?.type&&o?.requestId===d){if(window.removeEventListener("message",e),o?.response?.error)return l(new Error(o.response.message));const{status:n,headers:r,body:s}=o.response;t(new Response(s,{status:n,headers:r}))}})),window.postMessage({type:"REQUEST_INTERCEPTED",requestId:d,payload:{actualUrl:e,url:c,method:n,headers:o,body:r,credentials:s,mode:i,rule:a}},"*")}))})({actualUrl:o.url,url:f,method:o.method,headers:Object.fromEntries(x.entries()),body:v,credentials:w.credentials,mode:w.mode}).then((e=>(e.clone().text().then((t=>{const n=Date.now()-d;I.addRequest("mocked",{...o,requestId:a,status:e.status,responseHeaders:Object.fromEntries(e.headers.entries()),responseBody:t,pending:!1,duration:n})})),e))):(v&&(w.body=v),i(f,w).then((async e=>{const t=e.clone(),n=t.headers.get("content-type")||"",r=Date.now()-d,s=n=>(I.addRequest("mocked",{...o,requestId:a,status:e.status,responseHeaders:Object.fromEntries(t.headers.entries()),responseBody:n,pending:!1,duration:r}),new Response("string"==typeof n?n:JSON.stringify(n),{status:e.status,headers:t.headers}));return n.includes("application/json")?t.json().then(s):t.text().then(s)})).catch((e=>{const t=Date.now()-d;return I.addRequest("mocked",{...o,requestId:a,status:0,pending:!1,duration:t}),i(r,s)})))},onOtherRequest:async(e,t,n,o)=>{if("OPTIONS"===e.method)return o(t,n);const r=e.requestId,s=Date.now();return I.addRequest("other",{...e,requestId:r,pending:!0,startTime:s}),o(t,n).then((async t=>{const n=t.clone(),o=Date.now()-s;try{const s=await n.text();I.addRequest("other",{...e,requestId:r,status:t.status,responseHeaders:Object.fromEntries(t.headers.entries()),responseBody:s,pending:!1,duration:o})}catch(e){}return t})).catch((t=>{const n=Date.now()-s,o="AbortError"===t.name||t.message.includes("aborted"),i="TimeoutError"===t.name||t.message.includes("timed out");throw I.addRequest("other",{...e,requestId:r,status:o?"Aborted":i?"Timeout":"Error",pending:!1,duration:n,aborted:o,timeout:i,error:!o&&!i}),t}))}}),B.apply({ruleProvider:()=>k(),mappingProvider:e=>{try{return d(new URL(e.url,window.location.origin).pathname,e.method)}catch{return null}},onRuleMatch:async(e,t,n,o)=>{const r=t.requestId,s=Date.now();I.addRequest("mocked",{...t,requestId:r,pending:!0,startTime:s,rule:e});const i=await H.apply(e,t),{modifiedRequest:a,type:d,redirectUrl:c}=i;"timeout"!==d&&I.addRequest("mocked",{...a,requestId:r,pending:!0,startTime:s,rule:e});let l=null;if("redirect"===d){l=Math.random().toString(36).substring(7);const e={url:c,method:a.method,headers:a.headers||{},body:a.body,requestId:l,queryParams:(()=>{try{const e="undefined"!=typeof window?window.location.origin:"http://localhost",t=new URL(c,e).searchParams;return Object.fromEntries(t.entries())}catch{return{}}})(),requestHeaders:a.headers||{},requestBody:a.body,pending:!0,startTime:Date.now()};I.addRequest("mocked",e)}const m=(e,t,o,m={})=>{const u=Date.now()-s;if(i.rule.modificationActions?.modifyResponseHeaders?.enabled){let e="string"==typeof o?Object.fromEntries(o.split("\r\n").filter((e=>e)).map((e=>e.split(": ")))):o;e=H.applyResponseModifications(e,i.rule.modificationActions),o=e}I.addRequest("mocked",{...a,requestId:r,status:e,responseBody:t,responseHeaders:o,pending:!1,duration:u,...m}),"redirect"===d&&l&&I.addRequest("mocked",{url:c,method:a.method,requestId:l,status:e,responseBody:t,responseHeaders:o,pending:!1,duration:u,requestHeaders:a.headers||{},requestBody:a.body,...m}),n._capture(e,t,o,m)};if("timeout"===d)return m("Aborted","Timed out by rule",{},{aborted:!0}),void n._xhr.abort();"redirect"===d?n._xhr.open(a.method,c,!0):a.url!==t.url&&n._xhr.open(a.method,a.url,!0),a.headers&&Object.entries(a.headers).forEach((([e,t])=>{try{n._xhr.setRequestHeader(e,t)}catch(e){}})),n._xhr.addEventListener("abort",(()=>m("Aborted","Aborted",{},{aborted:!0})),{once:!0}),n._xhr.addEventListener("error",(()=>m(0,"Error",{},{error:!0})),{once:!0}),n._xhr.addEventListener("timeout",(()=>m("Timeout","Timeout",{},{timeout:!0})),{once:!0}),n._xhr.addEventListener("load",(()=>m(n._xhr.status,n._xhr.responseText,n._xhr.getAllResponseHeaders())),{once:!0}),o(a.body)},onMockMatch:(e,o,r,s)=>{const i=o.requestId,a=Date.now(),d=n(),c=new URL(o.url,window.location.origin);let h=`${q()}${e.url}${c.search}`,f={[u]:d,[m]:p,"x-mfm-adaptor":t};const g=E();g&&e._ack&&(f["x-mfm-key"]=`${g}-${e._ack}`),e?._ri_&&(f._ri_=e._ri_);const y={...o.headers,...f};I.addRequest("mocked",{...o,requestId:i,pending:!0,startTime:a});const b=(e,t,n,s={})=>{const d=Date.now()-a;I.addRequest("mocked",{...o,requestId:i,status:e,responseBody:t,responseHeaders:n,pending:!1,duration:d,...s}),r._capture(e,t,n,s)};if(r._xhr.addEventListener("abort",(()=>b("Aborted","Aborted",{},{aborted:!0})),{once:!0}),r._xhr.addEventListener("error",(()=>b(0,"Error",{},{error:!0})),{once:!0}),r._xhr.addEventListener("timeout",(()=>b("Timeout","Timeout",{},{timeout:!0})),{once:!0}),t===l)(({actualUrl:e,url:t,method:n,headers:o,body:r,onSuccess:s,onError:i,rule:a})=>{const d=`${Date.now()}-${Math.random()}`,c=R(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:o,headers:r}=n.response;s?.({body:t,status:o,headers:r})}})),window.postMessage({type:"REQUEST_INTERCEPTED",requestId:d,payload:{actualUrl:e,url:c,method:n,headers:o,body:r,credentials:"same-origin",mode:"cors",rule:a}},"*")})({actualUrl:o.url,url:h,method:o.method,headers:y,body:o.body,onSuccess:({body:e,status:t,headers:n})=>b(t,e,n||{}),onError:e=>b(0,e.message||"XHR Error",{},{error:!0})});else{const e=new window.XMLHttpRequest;e.open(o.method,h,!0);for(const t in y)e.setRequestHeader(t,y[t]);e.withCredentials=r.proxy.withCredentials,e.onload=()=>b(e.status,e.responseText,e.getAllResponseHeaders()),e.onerror=()=>b(0,"Network Error",{},{error:!0}),e.ontimeout=()=>b("Timeout","Request timed out",{},{timeout:!0}),e.send(o.body)}},onOtherRequest:(e,t,n)=>{if("OPTIONS"===e.method)return n(e.body);const o=Date.now();I.addRequest("other",{...e,pending:!0,startTime:o});const r=(n,r,s,i={})=>{const a=Date.now()-o;I.addRequest("other",{...e,status:n,responseBody:r,responseHeaders:s,pending:!1,duration:a,...i}),t._capture(n,r,s,i)};t._xhr.addEventListener("abort",(()=>r("Aborted","Aborted",{},{aborted:!0})),{once:!0}),t._xhr.addEventListener("error",(()=>r(0,"Error",{},{error:!0})),{once:!0}),t._xhr.addEventListener("timeout",(()=>r("Timeout","Timeout",{},{timeout:!0})),{once:!0}),t._xhr.addEventListener("load",(()=>r(t._xhr.status,t._xhr.responseText,t._xhr.getAllResponseHeaders())),{once:!0}),n(e.body)}})}(r,o),f&&y?(I.mappings=h,I.rules=x,e?.(h,{_o:f,mk:y,_mck:b,_rules:x})):r&&function(t,n,o,r){S({method:"get",url:g,async:!1,headers:{[u]:t,[m]:p,"x-mfm-adaptor":n}},(t=>{if(t)try{const{di:r,iv:s,_o:a,_mck:d,mk:c,r:l}=t,m=_({di:r,iv:s},a);w({_o:a,mk:c,_mck:d,_rules:l}),m&&(i(m),n=m,o={_o:a,mk:c,_mck:d,_rules:l},I.updateMappings(n,o),e?.(n,o))}catch(e){return void r(new Error("Unable to fetch mocked apis"))}var n,o}),(e=>{console.log("Error in loading mocked apis"),r(e)})).request()}(r,o,0,t)},checkIfApiToBeMocked:d,getMappings:a,doFetchMappings:(e,t)=>{T(r||I.token,o,((t,n)=>{I.updateMappings(t,n),e?.(t,n)}),t)},recheckWidgetVisibility:()=>{I.init()}}},j=n();j||(globalThis.mockforme=P);let N=P;j&&(N=e=>({run:()=>{}}));const D=N;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}},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&&(window.addEventListener("resize",(()=>{this.bubble&&this.keepInBounds(this.bubble)})),"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: 25px;\n height: 25px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #2563eb;\n font-size: 25px;\n transition: background 0.2s;\n margin-right: 10px;\n background: #f3f4f6;\n padding: 8px;\n }\n .mfm-refresh-icon:hover { }\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: 80vh;\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 @media (max-width: 480px) {\n .mfm-bottomsheet { padding: 16px; }\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: 15px;\n padding-bottom: 10px;\n border-bottom: 1px solid #eee;\n flex-shrink: 0;\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: 20px 0; width: 100%; display: flex; justify-content: center; flex-shrink: 0; }\n .mfm-logo { width: 120px; 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: 10px; flex-shrink: 0; }\n .mfm-tab {\n padding: 8px 16px;\n cursor: pointer;\n color: #666;\n border-bottom: 2px solid transparent;\n font-weight: 500;\n font-size: 14px;\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; flex-shrink: 0; }\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: 25px; cursor: pointer; color: #666; display: flex; align-items: center; justify-content: center; padding: 4px; border-radius: 4px; }\n .mfm-icon-btn:hover { color: #333; }\n .mfm-icon-btn.refresh { color: #2563eb; padding: 0; height: 20px; width:20px; border-radius: 50%; }\n .mfm-icon-btn.refresh.loading { animation: mfm-spin 1s linear infinite; }\n .mfm-icon-btn.delete { color: #dc2626; }\n\n @media (max-height: 700px) {\n .mfm-bottomsheet { height: 85vh; padding: 12px; }\n .mfm-logo-container { padding: 10px 0; }\n .mfm-logo { width: 100px; }\n .mfm-header { margin-bottom: 10px; }\n .mfm-form { gap: 8px; }\n .mfm-input { padding: 10px; font-size: 14px; }\n .mfm-btn { padding: 10px; font-size: 14px; }\n }\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),this.keepInBounds(e),e.querySelector("img").onclick=e=>{this.isDragging||this.toggleSheet()},e.querySelector(".mfm-refresh-icon").onclick=e=>{e.stopPropagation(),this.refreshMappings()},e}keepInBounds(e){const t=e.getBoundingClientRect(),n=10;let s=parseInt(e.style.right)||20,o=parseInt(e.style.bottom)||20;const r=window.innerWidth-t.width-n,i=window.innerHeight-t.height-n;s<n&&(s=n),o<n&&(o=n),s>r&&(s=r),o>i&&(o=i),e.style.right=s+"px",e.style.bottom=o+"px"}addDragLogic(e){let t,n,s,o,r=!1;const i=(i,a)=>{r=!1,this.isDragging=!1,t=i,n=a;const d=e.getBoundingClientRect();s=window.innerWidth-d.right,o=window.innerHeight-d.bottom},a=(i,a)=>{const d=t-i,c=n-a;(Math.abs(d)>3||Math.abs(c)>3)&&(r=!0,this.isDragging=!0),r&&(e.style.right=s+d+"px",e.style.bottom=o+c+"px")},d=()=>{r&&(this.keepInBounds(e),"undefined"!=typeof localStorage&&localStorage.setItem("mockforme-dot-pos",JSON.stringify({bottom:parseInt(e.style.bottom),right:parseInt(e.style.right)})))},c=e=>{a(e.clientX,e.clientY)},l=()=>{document.removeEventListener("mousemove",c),document.removeEventListener("mouseup",l),d()},m=e=>{const t=e.touches[0];a(t.clientX,t.clientY),r&&e.cancelable&&e.preventDefault()},u=()=>{document.removeEventListener("touchmove",m),document.removeEventListener("touchend",u),d()};e.addEventListener("mousedown",(e=>{i(e.clientX,e.clientY),document.addEventListener("mousemove",c),document.addEventListener("mouseup",l)})),e.addEventListener("touchstart",(e=>{const t=e.touches[0];i(t.clientX,t.clientY),document.addEventListener("touchmove",m,{passive:!1}),document.addEventListener("touchend",u)}),{passive:!0})}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("undefined"!=typeof FormData&&e instanceof FormData){const t={};return e.forEach(((e,n)=>{"undefined"!=typeof File&&e instanceof File?t[n]=`[File: ${e.name} (${e.size} bytes)]`:"undefined"!=typeof Blob&&e instanceof Blob?t[n]=`[Blob: ${e.type} (${e.size} bytes)]`:t[n]=e})),JSON.stringify(t,null,2)}if("undefined"!=typeof URLSearchParams&&e instanceof URLSearchParams)return JSON.stringify(Object.fromEntries(e.entries()),null,2);if("undefined"!=typeof Blob&&e instanceof Blob)return`[${"undefined"!=typeof File&&e instanceof File?"File":"Blob"}: ${e.type||"binary"} (${e.size} bytes)]`;if(e instanceof ArrayBuffer||"undefined"!=typeof Uint8Array&&e instanceof Uint8Array)return`[Binary Data: ${e.byteLength||e.length} bytes]`;if("object"==typeof e)try{return JSON.stringify(e,null,2)}catch{return String(e)}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 I(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:M(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,I=new Headers(T||{});Object.entries(R).forEach((([e,t])=>{I.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:a,headers:I,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,requestBody:e||u.requestBody,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(I.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,requestBody:e||u.requestBody,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 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(S.addRequest(o,{url:this._url,method:this._method,requestHeaders:this._headers,requestBody:this._body,queryParams:M(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:M(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:M(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:M(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 M(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=()=>{})=>{I(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
|
+
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("/"),o=t.split("/");if(n.length!==o.length)return!1;for(let e=0;e<n.length;e++){const t=n[e];if(t!==o[e]&&":any"!==t)return!1}return!0};let o=[];function r(e){o=e}function s(){return o}function i(e,r="get"){const s=e=>e.startsWith("/")?e:`/${e}`,i=s(e);for(const a of o)if(t(a.apiMethod)===t(r)){const t=s(a.apiEndpoint);if(t===i||n(t,i)){console.log(`[MockForMe] Match Found: ${r} ${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.7",u="https://api.mockforme.com",p=`${u}/mockforme`,h=`${u}/gateway/3f4eae522b`;let f=null,g=null,y=null,b=[];function x({_o:e,mk:t,_mck:n,_rules:o}){f=e,g=t,y=n,b=o}function w(){return b}function v(){return`${p}/${f}/${g}`}function k(){return y}const q=e=>{try{return new URL(e,window.location.origin).toString()}catch{return e}},E=function(t,n,o){const r=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 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,s)}else o.call(this,s.responseText,s)}function a(e,t){var n=[];for(var o in e)if(e.hasOwnProperty(o)){var r=t?t+"["+o+"]":o,s=e[o];n.push("object"==typeof s?a(s,r):encodeURIComponent(r)+"="+encodeURIComponent(s))}return n.join("&")}return r||(window.XMLHttpRequest?s=new XMLHttpRequest:window.ActiveXObject&&(s=new ActiveXObject("Microsoft.XMLHTTP"))),{request:function(){if(!r){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 n=t.url.split("?");n[1]&&n[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 R({di:e,iv:t},n){var o;const r=function(e,t){const n=t.length;return e.split("").map(((e,o)=>String.fromCharCode(e.charCodeAt(0)^t.charCodeAt(o%n)))).join("")}((o=e,"undefined"!=typeof Buffer?Buffer.from(o,"base64").toString("utf8"):decodeURIComponent(escape(atob(o)))),n+t);return JSON.parse(r)}function S(e,t,n,o){fetch(h,{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:o,_o:s,_mck:i,mk:a,r:d}=e,c=R({di:t,iv:o},s);x({_o:s,mk:a,_mck:i,_rules:d}),c&&(r(c),n(c,{_o:s,mk:a,_mck:i,_rules:d}))}})).catch((e=>{console.error("Error in loading mocked APIs:",e),o(e)}))}const _='<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:block;"><path d="M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8"></path><polyline points="21 3 21 8 16 8"></polyline></svg>',T='<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:block;"><circle cx="12" cy="12" r="1.5"></circle><circle cx="12" cy="5" r="1.5"></circle><circle cx="12" cy="19" r="1.5"></circle></svg>',M='<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:block;"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>',L=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.widgetKey=t.widgetKey||null,this.mockedRequests=[],this.otherRequests=[],this.state={isOpen:"undefined"!=typeof localStorage&&"true"===localStorage.getItem("mockforme-widget-open"),activeTab:"mappings",selectedRequest:null,activeRequestTab:"response",lastError:null,searchQuery:""},"undefined"!=typeof document&&(window.addEventListener("resize",(()=>{this.bubble&&this.keepInBounds(this.bubble)})),document.addEventListener("click",(e=>{this.sharedDropdown&&this.sharedDropdown.classList.remove("show")}))))}init(){if("undefined"!=typeof document&&document.getElementById)if(this.checkVisibility())if(document.body)this.initWidget();else{const e=()=>{document.body&&this.initWidget()};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",e,{once:!0}):"interactive"===document.readyState||"complete"===document.readyState?setTimeout(e,0):window.addEventListener("load",e,{once:!0})}else{const e=document.getElementById("mockforme-root");e&&e.remove()}}initWidget(){document.getElementById("mockforme-root")||(this.createStyles(),this.render())}setWidgetKey(e){this.widgetKey=e,this.init()}checkVisibility(){return!this.widgetKey||"undefined"!=typeof localStorage&&localStorage.getItem("widgetKey")===this.widgetKey}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: 0px 12px;\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: 28px;\n height: 28px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #2563eb;\n transition: background 0.2s;\n margin-right: 10px;\n background: #f3f4f6;\n padding: 0;\n }\n .mfm-refresh-icon svg { width: 16px; height: 16px; }\n .mfm-refresh-icon:hover { }\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: 80vh;\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 @media (max-width: 480px) {\n .mfm-bottomsheet { padding: 16px; }\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: 15px;\n padding-bottom: 10px;\n border-bottom: 1px solid #eee;\n flex-shrink: 0;\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-title img { height: 30px; }\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; padding: 4px; cursor: pointer; color: #666; display: flex; align-items: center; justify-content: center; }\n .mfm-close:hover { color: #111; background: #f3f4f6; border-radius: 4px; }\n /* Login Form */\n .mfm-logo-container { text-align: center; padding: 20px 0; width: 100%; display: flex; justify-content: center; flex-shrink: 0; }\n .mfm-logo { width: 120px; 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 { \n display: flex; \n border-bottom: 1px solid #dee2e6; \n margin-bottom: 10px; \n flex-shrink: 0; \n gap: 2px;\n }\n .mfm-tab {\n padding: 8px 16px;\n cursor: pointer;\n color: #666;\n border: 1px solid transparent;\n border-bottom: none;\n border-top-left-radius: 6px;\n border-top-right-radius: 6px;\n font-weight: 300;\n font-size: 14px;\n margin-bottom: -1px;\n transition: all 0.2s;\n }\n .mfm-tab:hover {\n background-color: #f8f9fa;\n border-color: #e9ecef #e9ecef transparent;\n }\n .mfm-tab.active { \n color: #2563eb; \n background-color: white;\n border: 1px solid #dee2e6;\n border-bottom: 1px solid white;\n font-weight: 500;\n }\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 flex-wrap: wrap;\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; flex-shrink: 0; }\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; cursor: pointer; color: #666; display: flex; align-items: center; justify-content: center; padding: 4px; border-radius: 4px; }\n .mfm-icon-btn:hover { color: #333; background: #f3f4f6; }\n .mfm-icon-btn.refresh { color: #2563eb; padding: 0; height: 24px; width:24px; 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-non-2xx { color: #dc2626; }\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-redirect-badge {\n font-size: 10px;\n color: #166534;\n background: #dcfce7;\n padding: 2px 6px;\n border-radius: 10px;\n margin-top: 2px;\n display: inline-block;\n font-weight: 500;\n border: 1px solid #bbf7d0;\n }\n\n /* Mapping UI Enhanced */\n .mfm-mapping-info { display: flex; flex-direction: column; flex: 1; overflow: hidden; }\n .mfm-rule-name { font-weight: 600; color: #1f2937; margin-bottom: 2px; display: block; overflow: hidden; text-overflow: ellipsis; }\n .mfm-condition-brief { font-size: 11px; color: #6b7280; font-family: monospace; cursor: pointer; }\n .mfm-condition-brief:hover { color: #2563eb; text-decoration: underline; }\n .mfm-mod-actions-count { \n font-size: 10px; \n background: #eff6ff; \n color: #1d4ed8; \n padding: 2px 6px; \n border-radius: 12px; \n cursor: pointer; \n font-weight: 600;\n margin-top: 4px;\n display: inline-block;\n width: fit-content;\n }\n .mfm-mod-actions-count:hover { background: #dbeafe; }\n\n /* Modals */\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: 90%;\n max-width: 400px;\n max-height: 80vh;\n overflow-y: auto;\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: 12px; display: flex; justify-content: space-between; align-items: center; }\n .mfm-modal-body { font-size: 14px; color: #4b5563; }\n .mfm-modal-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 20px; }\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 .mfm-mod-item { border-bottom: 1px solid #eee; padding-bottom: 8px; margin-bottom: 8px; }\n .mfm-mod-item:last-child { border-bottom: none; margin-bottom: 0; }\n .mfm-mod-type { font-weight: 600; font-size: 12px; color: #2563eb; text-transform: uppercase; margin-bottom: 4px; }\n .mfm-mod-detail { font-size: 11px; font-family: monospace; word-break: break-all; }\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 .mfm-duration { color: #666; font-size: 11px; margin-left: 8px; font-weight: normal; }\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 .section-header { display: flex; align-items: center; justify-content: space-between; margin: 10px 0 5px; }\n .mfm-copy-btn {\n background: #f1f5f9;\n color: #64748b;\n padding: 2px 8px;\n border-radius: 4px;\n font-size: 10px;\n cursor: pointer;\n border: 1px solid #e2e8f0;\n transition: all 0.2s;\n font-weight: 600;\n text-transform: uppercase;\n }\n .mfm-copy-btn:hover { background: #e2e8f0; color: #334155; }\n \n .mfm-copy-group {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n margin-top: 4px;\n }\n .mfm-copy-group .mfm-copy-btn {\n font-size: 9px;\n padding: 2px 6px;\n }\n\n /* Dropdown Menu */\n .mfm-menu-dots {\n cursor: pointer;\n padding: 4px;\n color: #666;\n border-radius: 4px;\n transition: background 0.2s;\n line-height: 1;\n margin-left: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n .mfm-menu-dots:hover { background: #f3f4f6; color: #333; }\n \n .mfm-dropdown-shared {\n position: fixed;\n background: white;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0,0,0,0.15);\n z-index: 1000005;\n display: none;\n flex-direction: column;\n width: 160px;\n overflow: hidden;\n }\n .mfm-dropdown-shared.show { display: flex; }\n .mfm-dropdown-item {\n padding: 10px 14px;\n font-size: 13px;\n color: #334155;\n cursor: pointer;\n transition: background 0.2s;\n text-align: left;\n border-bottom: 1px solid #f1f5f9;\n white-space: nowrap;\n }\n .mfm-dropdown-item:last-child { border-bottom: none; }\n .mfm-dropdown-item:hover { background: #f8fafc; color: #2563eb; }\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 ",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.sharedDropdown=document.createElement("div"),this.sharedDropdown.className="mfm-dropdown-shared",this.sharedDropdown.innerHTML='\n <div class="mfm-dropdown-item" data-format="curl">Copy as cURL</div>\n <div class="mfm-dropdown-item" data-format="fetch">Copy as Fetch</div>\n <div class="mfm-dropdown-item" data-format="xhr">Copy as XHR</div>\n ',this.root.appendChild(this.sharedDropdown),this.updateUI()}updateUI(){this.sheet&&(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),this.keepInBounds(e),e.querySelector("img").onclick=e=>{this.isDragging||this.toggleSheet()},e.querySelector(".mfm-refresh-icon").onclick=e=>{e.stopPropagation(),this.refreshMappings()},e}keepInBounds(e){const t=e.getBoundingClientRect(),n=10;let o=parseInt(e.style.right)||20,r=parseInt(e.style.bottom)||20;const s=window.innerWidth-t.width-n,i=window.innerHeight-t.height-n;o<n&&(o=n),r<n&&(r=n),o>s&&(o=s),r>i&&(r=i),e.style.right=o+"px",e.style.bottom=r+"px"}addDragLogic(e){let t,n,o,r,s=!1;const i=(i,a)=>{s=!1,this.isDragging=!1,t=i,n=a;const d=e.getBoundingClientRect();o=window.innerWidth-d.right,r=window.innerHeight-d.bottom},a=(i,a)=>{const d=t-i,c=n-a;(Math.abs(d)>3||Math.abs(c)>3)&&(s=!0,this.isDragging=!0),s&&(e.style.right=o+d+"px",e.style.bottom=r+c+"px")},d=()=>{s&&(this.keepInBounds(e),"undefined"!=typeof localStorage&&localStorage.setItem("mockforme-dot-pos",JSON.stringify({bottom:parseInt(e.style.bottom),right:parseInt(e.style.right)})))},c=e=>{a(e.clientX,e.clientY)},l=()=>{document.removeEventListener("mousemove",c),document.removeEventListener("mouseup",l),d()},m=e=>{const t=e.touches[0];a(t.clientX,t.clientY),s&&e.cancelable&&e.preventDefault()},u=()=>{document.removeEventListener("touchmove",m),document.removeEventListener("touchend",u),d()};e.addEventListener("mousedown",(e=>{i(e.clientX,e.clientY),document.addEventListener("mousemove",c),document.addEventListener("mouseup",l)})),e.addEventListener("touchstart",(e=>{const t=e.touches[0];i(t.clientX,t.clientY),document.addEventListener("touchmove",m,{passive:!1}),document.addEventListener("touchend",u)}),{passive:!0})}toggleSheet(){this.state.isOpen=!this.state.isOpen,"undefined"!=typeof localStorage&&localStorage.setItem("mockforme-widget-open",this.state.isOpen),this.updateUI()}showSnackbar(e){this.snackbar&&(this.snackbar.textContent=e,this.snackbar.classList.add("show"),setTimeout((()=>this.snackbar.classList.remove("show")),3e3))}showConfirm(e,t,n){this.showModal(e,t,[{label:"Cancel",className:"mfm-btn-alt",onClick:e=>e.classList.remove("show")},{label:"Delete",className:"mfm-btn-danger",onClick:e=>{e.classList.remove("show"),n()}}])}showModal(e,t,n=[]){if(!this.modalOverlay)return;this.modalOverlay.innerHTML=`\n <div class="mfm-modal">\n <div class="mfm-modal-title">\n <span>${e}</span>\n <span style="cursor:pointer;" id="mfm-modal-close">${M}</span>\n </div>\n <div class="mfm-modal-body">${t}</div>\n <div class="mfm-modal-actions" id="mfm-modal-actions"></div>\n </div>\n `;const o=this.modalOverlay.querySelector("#mfm-modal-actions");if(n.forEach((e=>{const t=document.createElement("button");t.className=e.className||"mfm-btn-alt",t.textContent=e.label,t.onclick=()=>e.onClick(this.modalOverlay),o.appendChild(t)})),0===n.length){const e=document.createElement("button");e.className="mfm-btn",e.textContent="OK",e.onclick=()=>this.modalOverlay.classList.remove("show"),o.appendChild(e)}this.modalOverlay.querySelector("#mfm-modal-close").onclick=()=>{this.modalOverlay.classList.remove("show")},this.modalOverlay.classList.add("show")}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"))),S(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">${M}</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 o=n.value.trim();o&&(t.textContent="Validating...",t.disabled=!0,this.state.lastError=null,e.querySelector("#mfm-error-msg").style.display="none",S(o,a,((e,t)=>{"undefined"!=typeof localStorage&&localStorage.setItem("mockforme-token",o),this.token=o,this.isAuthenticated=!0,this.mappings=e,this.rules=t?._rules||[],this.onAuthSuccess(o,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}updateMappings(e,t){this.mappings=e||[],this.rules=t?._rules||[],this.root&&this.updateUI()}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"><img src="https://www.mockforme.com/assets/images/logo.png" /></span>\n <div class="mfm-header-actions">\n <button class="mfm-close">${M}</button>\n </div>\n </div>\n `;const t=document.createElement("div");t.className="mfm-tabs",["mappings","mocked","other","settings"].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"===e?"Other Apis":"Settings",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()):"settings"!==this.state.activeTab?(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"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:block;"><circle cx="12" cy="12" r="10"></circle><line x1="4.93" y1="4.93" x2="19.07" y2="19.07"></line></svg></button>\n `,n.querySelector("#mfm-search-input").oninput=e=>{this.state.searchQuery=e.target.value,this.updateRequestList(o)},n.querySelector("#mfm-clear-requests-btn").onclick=()=>{"mocked"===this.state.activeTab?this.mockedRequests=[]:this.otherRequests=[],this.updateUI()}):n.style.display="none",t.after(n);const o=document.createElement("div");return o.className="mfm-list",this.updateRequestList(o),e.appendChild(o),e.querySelector(".mfm-close").onclick=()=>this.toggleSheet(),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.rule||t,o=e.timingAction||{},r=o.activeAction||"none",s=o.actions?.[r]?.value,i=`Rule (${r}${void 0!==s?` ${s}s`:""})`;let a="{}";e.conditions&&Array.isArray(e.conditions)&&(a=e.conditions.map((e=>`${e.type}:${e.operator}:${e.value}`)).join(" AND "));const d=a.length>40?a.substring(0,40)+"...":a;let c=0;const l=e.modificationActions||{};Object.values(l).forEach((e=>{e.enabled&&(e.add&&(c+=e.add.length),e.remove&&(c+=e.remove.length),e.update&&(c+=e.update.length))})),n.innerHTML=`\n <div class="mfm-mapping-info">\n <span class="mfm-rule-name" style="cursor:pointer; color:#2563eb; text-decoration:underline;" id="mfm-view-full-rule" title="View full rule details">${i}</span>\n <span class="mfm-condition-brief" title="View condition">\n ${d} <span style="font-weight:bold; color:#2563eb; margin-left:4px; cursor:pointer;" id="mfm-view-cond-dots">${T}</span>\n </span>\n ${c>0?`<div class="mfm-mod-actions-count" id="mfm-view-mods">${c} Modification Actions</div>`:""}\n </div>\n <span class="mfm-method RULE">RULE</span>\n `,n.querySelector("#mfm-view-full-rule").onclick=t=>{t.stopPropagation();const n=JSON.stringify(e,null,2);this.showModal("Full Rule Information",`<pre class="mfm-code-block">${n}</pre>`)},n.querySelector("#mfm-view-cond-dots").onclick=t=>{t.stopPropagation();const n=e.conditions.map((e=>`\n <div class="mfm-mod-item">\n <div class="mfm-mod-type">${e.type} (${e.operator})</div>\n <div class="mfm-mod-detail"><b>Key:</b> ${e.key||"N/A"}<br><b>Value:</b> ${e.value}</div>\n </div>\n `)).join("");this.showModal("Rule Conditions",n)},c>0&&(n.querySelector("#mfm-view-mods").onclick=e=>{e.stopPropagation();let t="";Object.entries(l).forEach((([e,n])=>{n.enabled&&(t+=`<div class="mfm-mod-item"><div class="mfm-mod-type">${e.replace("modify","")}</div>`,n.add?.length&&(t+=`<div class="mfm-mod-detail"><b>Add:</b> ${JSON.stringify(n.add)}</div>`),n.update?.length&&(t+=`<div class="mfm-mod-detail"><b>Update:</b> ${JSON.stringify(n.update)}</div>`),n.remove?.length&&(t+=`<div class="mfm-mod-detail"><b>Remove:</b> ${JSON.stringify(n.remove)}</div>`),t+="</div>")})),this.showModal("Modification Actions",t)})}e.appendChild(n)}))}else if("settings"===this.state.activeTab)e.innerHTML='\n <div style="padding: 16px;">\n <div class="section-title" style="margin-top: 0; margin-bottom: 12px; font-size: 15px; border-bottom: 1px solid #eee; padding-bottom: 8px;">Token Management</div>\n <p style="font-size: 13px; color: #666; margin-bottom: 16px;">Removing your token will clear all saved mappings and rules from this browser instance.</p>\n <button class="mfm-delete-token-btn" id="mfm-settings-delete-token" style="padding: 8px 16px; font-size: 14px; width: fit-content;">\n <span><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:block;"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path><line x1="10" y1="11" x2="10" y2="17"></line><line x1="14" y1="11" x2="14" y2="17"></line></svg></span>\n <span>Delete Token</span>\n </button>\n </div>\n ',e.querySelector("#mfm-settings-delete-token").onclick=()=>{this.showConfirm("Delete Token","Are you sure you want to Delete Token? This will clear your saved token.",(()=>{this.deleteToken()}))};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 o=(t.method||"").toUpperCase(),r=`<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>`;let s="",i="";if(t.rule){const e=t.rule.action||"";let n="delay_and_timeout"===e?"Delay and Timout":e.split("_")[0];const o=t.rule.config?.value;void 0!==o&&(e.includes("delay")||e.includes("timeout"))&&(n+=` (${o}s)`),s=`<span class="mfm-rule-tag" title="${e}">${n}</span>`,"delay_and_redirect"===e&&t.rule.config?.redirectUrl&&(i=`<div class="mfm-redirect-badge">Redirected to: ${t.rule.config.redirectUrl}</div>`)}let a=t.status,d="mfm-status";t.pending?a='<span class="mfm-spinner"></span>':t.aborted?(a="Aborted",d+=" status-aborted"):t.timeout?(a="Timeout",d+=" status-timeout"):t.error?(a="Error/CORS",d+=" status-error"):(a=t.status,d+=t.status>=200&&t.status<300?" status-2xx":" status-non-2xx"),n.innerHTML=`\n <div style="display:flex; align-items:center; width:100%; gap:8px;">\n <span class="mfm-method ${o}">${o}</span>\n <div style="flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; justify-content:center;">\n <span class="mfm-url">${s}${t.url}</span>\n ${i}\n ${r}\n </div>\n <span class="${d}">${a}</span>\n <span class="mfm-menu-dots" title="Copy As...">${T}</span>\n </div>\n `;const c=n.querySelector(".mfm-menu-dots");c.onclick=e=>{e.stopPropagation();const n=c.getBoundingClientRect();this.sharedDropdown.style.top=n.bottom+5+"px",this.sharedDropdown.style.left=n.right-160+"px",this.sharedDropdown.classList.toggle("show"),this.sharedDropdown.onclick=e=>{e.stopPropagation();const n=e.target.getAttribute("data-format");if(!n)return;let o="";"curl"===n?o=this.generateCurl(t):"fetch"===n?o=this.generateFetch(t):"xhr"===n&&(o=this.generateXHR(t)),o&&navigator.clipboard.writeText(o).then((()=>{this.showSnackbar(`${n.toUpperCase()} copied!`),this.sharedDropdown.classList.remove("show")}))}},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">${M}</button>\n </div>\n <div class="mfm-detail-actions">\n <button class="mfm-back-btn"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:inline-block; vertical-align:middle; margin-right:4px;"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg>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 o=document.createElement("div");o.style.overflowY="auto",o.style.flex="1";const r=(e.method||"").toUpperCase(),s=this.formatBody(e.requestBody),i=this.formatBody(e.responseBody);o.innerHTML="request"===this.state.activeRequestTab?`\n <div class="section-title">URL</div><div class="mfm-code-block">${r} ${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-header">\n <div class="section-title" style="margin: 0;">Payload</div>\n <div class="mfm-copy-btn" id="mfm-copy-payload">Copy</div>\n </div>\n <div class="mfm-code-block">${s}</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-header">\n <div class="section-title" style="margin: 0;">Response Body</div>\n <div class="mfm-copy-btn" id="mfm-copy-response">Copy</div>\n </div>\n <div class="mfm-code-block">${i}</div>\n `,t.appendChild(n),t.appendChild(o);const a=o.querySelector("#mfm-copy-payload");a&&(a.onclick=()=>{navigator.clipboard.writeText(s).then((()=>{this.showSnackbar("Payload copied!")}))});const d=o.querySelector("#mfm-copy-response");return d&&(d.onclick=()=>{navigator.clipboard.writeText(i).then((()=>{this.showSnackbar("Response copied!")}))}),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("undefined"!=typeof FormData&&e instanceof FormData){const t={};return e.forEach(((e,n)=>{"undefined"!=typeof File&&e instanceof File?t[n]=`[File: ${e.name} (${e.size} bytes)]`:"undefined"!=typeof Blob&&e instanceof Blob?t[n]=`[Blob: ${e.type} (${e.size} bytes)]`:t[n]=e})),JSON.stringify(t,null,2)}if("undefined"!=typeof URLSearchParams&&e instanceof URLSearchParams)return JSON.stringify(Object.fromEntries(e.entries()),null,2);if("undefined"!=typeof Blob&&e instanceof Blob)return`[${"undefined"!=typeof File&&e instanceof File?"File":"Blob"}: ${e.type||"binary"} (${e.size} bytes)]`;if(e instanceof ArrayBuffer||"undefined"!=typeof Uint8Array&&e instanceof Uint8Array)return`[Binary Data: ${e.byteLength||e.length} bytes]`;if("object"==typeof e)try{return JSON.stringify(e,null,2)}catch{return String(e)}try{return JSON.stringify(JSON.parse(e),null,2)}catch{return e}}generateCurl(e){const t=(e.method||"GET").toUpperCase();let n=`curl -X ${t} "${e.url}"`;if(e.requestHeaders&&Object.entries(e.requestHeaders).forEach((([e,t])=>{n+=` \\\n -H "${e}: ${t}"`})),e.requestBody&&"GET"!==t){const t=("string"==typeof e.requestBody?e.requestBody:JSON.stringify(e.requestBody)).replace(/'/g,"'\\''");n+=` \\\n --data-raw '${t}'`}return n}generateFetch(e){const t=(e.method||"GET").toUpperCase();let n=`{\n method: "${t}",\n headers: ${(e.requestHeaders?JSON.stringify(e.requestHeaders,null,2):"{}").replace(/\n/g,"\n ")}`;if(e.requestBody&&"GET"!==t){const t="string"==typeof e.requestBody?e.requestBody:JSON.stringify(e.requestBody,null,2);n+=`,\n body: ${"string"==typeof e.requestBody?"`"+t+"`":JSON.stringify(e.requestBody,null,2).replace(/\n/g,"\n ")}`}return n+="\n}",`fetch("${e.url}", ${n})\n .then(response => response.json())\n .then(data => console.log(data))\n .catch(error => console.error(error));`}generateXHR(e){const t=(e.method||"GET").toUpperCase();let n=`var xhr = new XMLHttpRequest();\nxhr.open("${t}", "${e.url}");\n`;if(e.requestHeaders&&Object.entries(e.requestHeaders).forEach((([e,t])=>{n+=`xhr.setRequestHeader("${e}", "${t}");\n`})),n+="\nxhr.onload = function() {\n console.log(xhr.responseText);\n};\n",e.requestBody&&"GET"!==t){const t="string"==typeof e.requestBody?e.requestBody:JSON.stringify(e.requestBody);n+=`\nxhr.send(${"string"==typeof e.requestBody?"`"+t+"`":JSON.stringify(e.requestBody)});`}else n+="\nxhr.send();";return n}addRequest(e,t){const n=String(t.method||"").toUpperCase().trim(),o=String(t.url||"");console.log(`[MockForMe] addRequest type=${e} method=${n} url=${o} requestId=${t.requestId} pending=${t.pending}`);const r=o.includes("api.mockforme.com")||o.includes("mockforme.com/proxy")||o.includes("mockforme.com/gateway")||o.includes("/3f4eae522b")||p&&o.includes(String(p));if("OPTIONS"===n||r)return;const s="mocked"===e?this.mockedRequests:this.otherRequests,i="mocked"===e?this.otherRequests:this.mockedRequests;if(t.requestId){const e=s.findIndex((e=>e.requestId===t.requestId));if(-1!==e)return s[e]={...s[e],...t},void this.updateUI();const n=i.findIndex((e=>e.requestId===t.requestId));if(-1!==n){const e={...i[n],...t};return i.splice(n,1),s.unshift(e),s.length>100&&s.pop(),void this.updateUI()}}s.unshift(t),s.length>100&&s.pop(),this.updateUI()}};class ${static match(e,t){if(!Array.isArray(t)||0===t.length)return!1;const{url:n,headers:o,queryParams:r,body:s}=e,i="undefined"!=typeof window?window.location.origin:globalThis.location?.origin||"http://localhost";for(const e of t){let t="";const{type:a,key:d,operator:c,value:l}=e;switch(a){case"URL":try{t=new URL(n,i).pathname}catch{t=n}break;case"QUERY_PARAM":if(r&&void 0!==r[d])t=String(r[d]);else try{t=new URL(n,i).searchParams.get(d)||""}catch{t=""}break;case"REQUEST_BODY":if(d){if("object"==typeof s&&null!==s)t=void 0!==s[d]?String(s[d]):"";else if("string"==typeof s)try{const e=JSON.parse(s);t=void 0!==e[d]?String(e[d]):""}catch{t=""}}else t="object"==typeof s?JSON.stringify(s):String(s||"");break;case"REQUEST_HEADER":if(d){const e=d?.toLowerCase();if(t="",o){const n=Object.keys(o).find((t=>t.toLowerCase()===e));t=n?String(o[n]):""}}else t=JSON.stringify(o||{});break;default:return!1}if(!this.evaluate(t,c,l))return!1}return!0}static evaluate(e,t,n){const o=t?.toLowerCase(),r=String(e),s=String(n);switch(o){case"contains":return r.includes(s);case"equal":case"equals":return r===s;case"regexp":try{let e=s;if(e.startsWith("/")&&e.lastIndexOf("/")>0){const t=e.lastIndexOf("/"),n=e.slice(1,t),o=e.slice(t+1);return new RegExp(n,o).test(r)}return new RegExp(e).test(r)}catch{return!1}default:return!1}}}class I{static async apply(e){if(!e||!e.activeAction)return{type:"passThrough",delay:0};const{activeAction:t,actions:n}=e,o=n?.[t];if(!o)return{type:"passThrough",delay:0};const r={type:"passThrough",delay:0},s=Number(o.value||0);switch(t){case"delay":r.delay=s,r.delay>0&&await new Promise((e=>setTimeout(e,1e3*r.delay)));break;case"delay_and_redirect":r.type="redirect",r.delay=s,r.redirectUrl=o.redirectUrl,r.delay>0&&await new Promise((e=>setTimeout(e,1e3*r.delay)));break;case"delay_and_timeout":r.type="timeout",r.delay=s,r.delay>0&&await new Promise((e=>setTimeout(e,1e3*r.delay)))}return r}}class A{static applyRequestModifications(e,t){if(!t)return e;let{url:n,headers:o,queryParams:r,body:s}={...e};o&&(o={...o}),r&&(r={...r});const{modifyQueryParams:i,modifyRequestBody:a,modifyRequestHeaders:d}=t;if(i?.enabled)try{const e=new URL(n,"undefined"!=typeof window?window.location.href:"http://localhost");Array.isArray(i.remove)&&i.remove.forEach((t=>{e.searchParams.delete(t),r&&delete r[t]})),Array.isArray(i.add)&&i.add.forEach((({key:t,value:n})=>{e.searchParams.set(t,n),r&&(r[t]=n)})),n=e.toString()}catch(e){console.error("[MockForMe] Failed to modify query params",e)}if(d?.enabled&&(o={...o},Array.isArray(d.remove)&&d.remove.forEach((e=>{const t=e.toLowerCase(),n=Object.keys(o).find((e=>e.toLowerCase()===t));n&&delete o[n]})),Array.isArray(d.add)&&d.add.forEach((({key:e,value:t})=>{o[e]=t}))),a?.enabled)try{let t=null;if("string"==typeof s)try{t=JSON.parse(s)}catch{}else if("object"==typeof s&&null!==s)try{t=JSON.parse(JSON.stringify(s))}catch{t={...s}}t&&(Array.isArray(a.remove)&&a.remove.forEach((e=>delete t[e])),Array.isArray(a.add)&&a.add.forEach((({key:e,value:n})=>t[e]=n)),Array.isArray(a.update)&&a.update.forEach((({key:e,value:n})=>t[e]=n)),s="string"==typeof e.body?JSON.stringify(t):t)}catch(e){console.error("[MockForMe] Failed to modify request body",e)}return{...e,url:n,headers:o,queryParams:r,body:s}}static applyResponseModifications(e,t){if(!t?.modifyResponseHeaders?.enabled)return e;const{modifyResponseHeaders:n}=t,o={...e};return Array.isArray(n.remove)&&n.remove.forEach((e=>{const t=e.toLowerCase(),n=Object.keys(o).find((e=>e.toLowerCase()===t));n&&delete o[n]})),Array.isArray(n.add)&&n.add.forEach((({key:e,value:t})=>{o[e]=t})),o}}class O{static match(e,t){if(!Array.isArray(t)||0===t.length)return null;for(const n of t){const t=n.rule||n;if(t.conditions&&Array.isArray(t.conditions)&&$.match(e,t.conditions)){const e=t.timingAction?.activeAction||"";return{action:e,config:t.timingAction?.actions?.[e]||{},rule:t}}}return null}static async apply(e,t){if(!e)return null;const n=e.rule||e,o=A.applyRequestModifications(t,n.modificationActions);return{...await I.apply(n.timingAction),modifiedRequest:o,rule:n}}static applyResponseModifications(e,t){return A.applyResponseModifications(e,t)}}class C{static apply({target:e=("undefined"!=typeof window?window:globalThis),originalFetch:t=e.fetch,ruleProvider:n=()=>[],mappingProvider:o=e=>null,onBeforeRequest:r=e=>{},onRuleMatch:s=async(e,t,n,o,r)=>null,onMockMatch:i=async(e,t,n,o,r)=>null,onOtherRequest:a=async(e,t,n,o)=>null}){t&&(e.fetch=async function(e,d={}){let c;try{const t="string"==typeof e?e:e.url,n=String(d.method||(e instanceof Request?e.method:"GET")).toUpperCase().trim(),o=Math.random().toString(36).substring(7);c={url:t,method:n,headers:d.headers||(e instanceof Request?e.headers:{}),body:d.body||(e instanceof Request?"{binary/stream}":null),requestId:o,queryParams:C.getQueryParams(t)},r(c)}catch(n){return console.warn("[MockForMe] Fetch Interceptor Setup Error:",n),t(e,d)}try{const r=n(),l=O.match(c,r);if(l){const n=await s(l,c,e,d,t);if(n)return n}const m=o(c);if(m){const n=await i(m,c,e,d,t);if(n)return n}const u=await a(c,e,d,t);if(u)return u}catch(e){if(e.message.includes("timed out")||"AbortError"===e.name||e.message.includes("rules"))throw e;console.warn("[MockForMe] Interceptor Hook Error:",e)}return t(e,d)})}static getQueryParams(e){try{const t="undefined"!=typeof window?window.location.origin:"http://localhost",n=new URL(e,t).searchParams;return Object.fromEntries(n.entries())}catch{return{}}}}class H{static apply({target:e=("undefined"!=typeof window?window:{}),OriginalXHR:t=e.XMLHttpRequest,ruleProvider:n=()=>[],mappingProvider:o=e=>null,onBeforeRequest:r=e=>{},onRuleMatch:s=(e,t,n,o)=>{o.call(n.proxy,t.body)},onMockMatch:i=(e,t,n,o)=>{o.call(n.proxy,t.body)},onOtherRequest:a=(e,t,n)=>{n.call(t.proxy,e.body)}}){t&&(e.XMLHttpRequest=class{constructor(){return this._xhr=new t,this._headers={},this._method=null,this._url=null,this._body=null,this._requestId=null,this._startTime=null,this._captured=!1,this._isMocked=!1,this.proxy=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)}),this.proxy}_capture(e,t,n,o={}){if(this._captured)return;this._captured=!0;const r=e=>{const t=`on${e}`;(this[t]||this._xhr[t])?.(),this._xhr.dispatchEvent(new Event(e))};if("Aborted"!==e)try{Object.defineProperty(this.proxy,"responseText",{value:t,configurable:!0}),Object.defineProperty(this.proxy,"response",{value:t,configurable:!0}),Object.defineProperty(this.proxy,"status",{value:Number(e)||0,configurable:!0}),Object.defineProperty(this.proxy,"statusText",{value:200==e?"OK":"",configurable:!0})}catch(e){console.warn("[MockForMe] Error setting XHR props",e)}Object.defineProperty(this.proxy,"readyState",{value:4,configurable:!0}),r("readystatechange"),"Aborted"===e||o.aborted?r("abort"):0===e||"Error"===e||o.error?r("error"):"Timeout"===e||o.timeout?r("timeout"):r("load")}open(e,t,n=!0,o=null,r=null){this._method=(e||"").toUpperCase().trim();try{this._url=new URL(t,"undefined"!=typeof window?window.location.href:"http://localhost").toString()}catch(e){this._url=t}return this._xhr.open(e,t,n,o,r)}setRequestHeader(e,t){return this._headers[e]=t,this._xhr.setRequestHeader(e,t)}send(e){this._body=e,this._requestId=Math.random().toString(36).substring(7),this._startTime=Date.now();const t={url:this._url,method:this._method,headers:this._headers,body:this._body,requestId:this._requestId,startTime:this._startTime,queryParams:H.getQueryParams(this._url)};r(t);const d=n(),c=O.match(t,d),l=e=>this._xhr.send(e);if(c)return this._isMocked=!0,s(c,t,this,l);const m=o(t);return m?(this._isMocked=!0,i(m,t,this,l)):(this._isMocked=!1,a(t,this,l))}})}static getQueryParams(e){try{const t="undefined"!=typeof window?window.location.origin:"http://localhost",n=new URL(e,t).searchParams;return Object.fromEntries(n.entries())}catch{return{}}}}const U=(t,n=null,o=a)=>{if(e())return;let u="string"==typeof t?t:t?.token,p="object"==typeof t?t?.widgetKey:null;if(p?L.setWidgetKey(p):L.init(),o===a)try{u&&("undefined"!=typeof localStorage&&localStorage.removeItem("mockforme-token"),L.token=u,L.isAuthenticated=!0),!u&&L.token&&(u=L.token),L.onAuthSuccess=(e,t,n)=>{r(t),x(n),L.updateMappings(t,n)}}catch(e){console.log("Error in showing mockforme widget",e)}n||={mappings:[],_o:null,mk:null,_mck:null,_rules:[]};const{mappings:f=[],_o:g,mk:y,_mck:b,_rules:_=[]}=n;return r(f),x({_o:g,mk:y,_mck:b,_rules:_}),{run:(e,t=()=>{})=>{!function(e,t){if("undefined"!=typeof window){if(window._mfm_intercepted)return;window._mfm_intercepted=!0}const n=()=>L.token||e;C.apply({ruleProvider:()=>w(),mappingProvider:e=>{try{return i(new URL(e.url,window.location.origin).pathname,e.method)}catch{return null}},onRuleMatch:async(e,t,n,o,r)=>{const s=t.requestId||Math.random().toString(36).substring(7),i=Date.now();L.addRequest("mocked",{...t,requestId:s,pending:!0,startTime:i,rule:e});const a=await O.apply(e,t),{modifiedRequest:d,type:c,delay:l,redirectUrl:m}=a;if("timeout"!==c&&L.addRequest("mocked",{...d,requestId:s,pending:!0,startTime:i,rule:e}),"timeout"===c){const e=Date.now()-i;throw L.addRequest("mocked",{...d,requestId:s,status:"Aborted",pending:!1,duration:e,aborted:!0}),new Error("Fetch timed out by rules")}let u="redirect"===c?m:d.url,p={...o};d.headers&&(p.headers=d.headers),d.body&&(p.body=d.body);let h=null;if("redirect"===c){h=Math.random().toString(36).substring(7);const e={url:m,method:d.method,headers:p.headers||{},body:p.body,requestId:h,queryParams:C.getQueryParams(m),requestHeaders:p.headers||{},requestBody:p.body,pending:!0,startTime:Date.now()};L.addRequest("mocked",e)}return r(u,p).then((async e=>{const t=Date.now()-i;let n=Object.fromEntries(e.headers.entries());if(a.rule.modificationActions?.modifyResponseHeaders?.enabled&&(n=O.applyResponseModifications(n,a.rule.modificationActions)),"redirect"===c&&h){const t=e.clone(),o=t.headers.get("content-type")||"",r=Date.now()-i;try{let s;s=o.includes("application/json")?await t.json():await t.text(),L.addRequest("mocked",{url:m,method:d.method,requestId:h,status:e.status,pending:!1,duration:r,responseHeaders:n,responseBody:s,requestHeaders:p.headers||{},requestBody:p.body})}catch(t){L.addRequest("mocked",{url:m,method:d.method,requestId:h,status:e.status,pending:!1,duration:r,responseHeaders:n,requestHeaders:p.headers||{},requestBody:p.body})}}return L.addRequest("mocked",{...d,requestId:s,status:e.status,pending:!1,duration:t,responseHeaders:n}),e})).catch((e=>{const t=Date.now()-i,n="AbortError"===e.name||e.message.includes("aborted");throw L.addRequest("mocked",{...d,requestId:s,status:n?"Aborted":0,pending:!1,duration:t}),"redirect"===c&&h&&L.addRequest("mocked",{url:m,method:d.method,requestId:h,status:n?"Aborted":0,pending:!1,duration:t,error:!n}),e}))},onMockMatch:async(e,o,r,s,i)=>{const a=o.requestId||Math.random().toString(36).substring(7),u=Date.now();L.addRequest("mocked",{...o,requestId:a,pending:!0,startTime:u});const p=n(),h=new URL(o.url,window.location.origin).search;let f=`${v()}${e.url}${h}`,g={[l]:p,[c]:m,"x-mfm-adaptor":t};const y=k();y&&e._ack&&(g["x-mfm-key"]=`${y}-${e._ack}`),e?._ri_&&(g._ri_=e._ri_);const b=r instanceof Request?r.headers:s.headers,x=new Headers(b||{});Object.entries(g).forEach((([e,t])=>x.set(e,t)));let w=s.body;if(!w&&r instanceof Request){const e=r.clone();"GET"!==e.method&&"HEAD"!==e.method&&(w=await e.text())}const E={method:o.method,headers:x,credentials:r instanceof Request&&r.credentials||s.credentials||"include",mode:r instanceof Request&&r.mode||s.mode||"cors"};return t===d?(({actualUrl:e,url:t,method:n,headers:o,body:r,credentials:s,mode:i,rule:a})=>{const d=`${Date.now()}-${Math.random()}`,c=q(t);return new Promise(((t,l)=>{window.addEventListener("message",(function e(n){if(n.source!==window)return;const o=n.data;if("INTERCEPTED_RESPONSE"===o?.type&&o?.requestId===d){if(window.removeEventListener("message",e),o?.response?.error)return l(new Error(o.response.message));const{status:n,headers:r,body:s}=o.response;t(new Response(s,{status:n,headers:r}))}})),window.postMessage({type:"REQUEST_INTERCEPTED",requestId:d,payload:{actualUrl:e,url:c,method:n,headers:o,body:r,credentials:s,mode:i,rule:a}},"*")}))})({actualUrl:o.url,url:f,method:o.method,headers:Object.fromEntries(x.entries()),body:w,credentials:E.credentials,mode:E.mode}).then((e=>(e.clone().text().then((t=>{const n=Date.now()-u;L.addRequest("mocked",{...o,requestId:a,status:e.status,responseHeaders:Object.fromEntries(e.headers.entries()),responseBody:t,pending:!1,duration:n})})),e))):(w&&(E.body=w),i(f,E).then((async e=>{const t=e.clone(),n=t.headers.get("content-type")||"",r=Date.now()-u,s=n=>(L.addRequest("mocked",{...o,requestId:a,status:e.status,responseHeaders:Object.fromEntries(t.headers.entries()),responseBody:n,pending:!1,duration:r}),new Response("string"==typeof n?n:JSON.stringify(n),{status:e.status,headers:t.headers}));return n.includes("application/json")?t.json().then(s):t.text().then(s)})).catch((e=>{const t=Date.now()-u;return L.addRequest("mocked",{...o,requestId:a,status:0,pending:!1,duration:t}),i(r,s)})))},onOtherRequest:async(e,t,n,o)=>{if("OPTIONS"===e.method)return o(t,n);const r=e.requestId,s=Date.now();return L.addRequest("other",{...e,requestId:r,pending:!0,startTime:s}),o(t,n).then((async t=>{const n=t.clone(),o=Date.now()-s;try{const s=await n.text();L.addRequest("other",{...e,requestId:r,status:t.status,responseHeaders:Object.fromEntries(t.headers.entries()),responseBody:s,pending:!1,duration:o})}catch(e){}return t})).catch((t=>{const n=Date.now()-s,o="AbortError"===t.name||t.message.includes("aborted"),i="TimeoutError"===t.name||t.message.includes("timed out");throw L.addRequest("other",{...e,requestId:r,status:o?"Aborted":i?"Timeout":"Error",pending:!1,duration:n,aborted:o,timeout:i,error:!o&&!i}),t}))}}),H.apply({ruleProvider:()=>w(),mappingProvider:e=>{try{return i(new URL(e.url,window.location.origin).pathname,e.method)}catch{return null}},onRuleMatch:async(e,t,n,o)=>{const r=t.requestId,s=Date.now();L.addRequest("mocked",{...t,requestId:r,pending:!0,startTime:s,rule:e});const i=await O.apply(e,t),{modifiedRequest:a,type:d,redirectUrl:c}=i;"timeout"!==d&&L.addRequest("mocked",{...a,requestId:r,pending:!0,startTime:s,rule:e});let l=null;if("redirect"===d){l=Math.random().toString(36).substring(7);const e={url:c,method:a.method,headers:a.headers||{},body:a.body,requestId:l,queryParams:(()=>{try{const e="undefined"!=typeof window?window.location.origin:"http://localhost",t=new URL(c,e).searchParams;return Object.fromEntries(t.entries())}catch{return{}}})(),requestHeaders:a.headers||{},requestBody:a.body,pending:!0,startTime:Date.now()};L.addRequest("mocked",e)}const m=(e,t,o,m={})=>{const u=Date.now()-s;if(i.rule.modificationActions?.modifyResponseHeaders?.enabled){let e="string"==typeof o?Object.fromEntries(o.split("\r\n").filter((e=>e)).map((e=>e.split(": ")))):o;e=O.applyResponseModifications(e,i.rule.modificationActions),o=e}L.addRequest("mocked",{...a,requestId:r,status:e,responseBody:t,responseHeaders:o,pending:!1,duration:u,...m}),"redirect"===d&&l&&L.addRequest("mocked",{url:c,method:a.method,requestId:l,status:e,responseBody:t,responseHeaders:o,pending:!1,duration:u,requestHeaders:a.headers||{},requestBody:a.body,...m}),n._capture(e,t,o,m)};if("timeout"===d)return m("Aborted","Timed out by rule",{},{aborted:!0}),void n._xhr.abort();"redirect"===d?n._xhr.open(a.method,c,!0):a.url!==t.url&&n._xhr.open(a.method,a.url,!0),a.headers&&Object.entries(a.headers).forEach((([e,t])=>{try{n._xhr.setRequestHeader(e,t)}catch(e){}})),n._xhr.addEventListener("abort",(()=>m("Aborted","Aborted",{},{aborted:!0})),{once:!0}),n._xhr.addEventListener("error",(()=>m(0,"Error",{},{error:!0})),{once:!0}),n._xhr.addEventListener("timeout",(()=>m("Timeout","Timeout",{},{timeout:!0})),{once:!0}),n._xhr.addEventListener("load",(()=>m(n._xhr.status,n._xhr.responseText,n._xhr.getAllResponseHeaders())),{once:!0}),o(a.body)},onMockMatch:(e,o,r,s)=>{const i=o.requestId,a=Date.now(),u=n(),p=new URL(o.url,window.location.origin);let h=`${v()}${e.url}${p.search}`,f={[l]:u,[c]:m,"x-mfm-adaptor":t};const g=k();g&&e._ack&&(f["x-mfm-key"]=`${g}-${e._ack}`),e?._ri_&&(f._ri_=e._ri_);const y={...o.headers,...f};L.addRequest("mocked",{...o,requestId:i,pending:!0,startTime:a});const b=(e,t,n,s={})=>{const d=Date.now()-a;L.addRequest("mocked",{...o,requestId:i,status:e,responseBody:t,responseHeaders:n,pending:!1,duration:d,...s}),r._capture(e,t,n,s)};if(r._xhr.addEventListener("abort",(()=>b("Aborted","Aborted",{},{aborted:!0})),{once:!0}),r._xhr.addEventListener("error",(()=>b(0,"Error",{},{error:!0})),{once:!0}),r._xhr.addEventListener("timeout",(()=>b("Timeout","Timeout",{},{timeout:!0})),{once:!0}),t===d)(({actualUrl:e,url:t,method:n,headers:o,body:r,onSuccess:s,onError:i,rule:a})=>{const d=`${Date.now()}-${Math.random()}`,c=q(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:o,headers:r}=n.response;s?.({body:t,status:o,headers:r})}})),window.postMessage({type:"REQUEST_INTERCEPTED",requestId:d,payload:{actualUrl:e,url:c,method:n,headers:o,body:r,credentials:"same-origin",mode:"cors",rule:a}},"*")})({actualUrl:o.url,url:h,method:o.method,headers:y,body:o.body,onSuccess:({body:e,status:t,headers:n})=>b(t,e,n||{}),onError:e=>b(0,e.message||"XHR Error",{},{error:!0})});else{const e=new window.XMLHttpRequest;e.open(o.method,h,!0);for(const t in y)e.setRequestHeader(t,y[t]);e.withCredentials=r.proxy.withCredentials,e.onload=()=>b(e.status,e.responseText,e.getAllResponseHeaders()),e.onerror=()=>b(0,"Network Error",{},{error:!0}),e.ontimeout=()=>b("Timeout","Request timed out",{},{timeout:!0}),e.send(o.body)}},onOtherRequest:(e,t,n)=>{if("OPTIONS"===e.method)return n(e.body);const o=Date.now();L.addRequest("other",{...e,pending:!0,startTime:o});const r=(n,r,s,i={})=>{const a=Date.now()-o;L.addRequest("other",{...e,status:n,responseBody:r,responseHeaders:s,pending:!1,duration:a,...i}),t._capture(n,r,s,i)};t._xhr.addEventListener("abort",(()=>r("Aborted","Aborted",{},{aborted:!0})),{once:!0}),t._xhr.addEventListener("error",(()=>r(0,"Error",{},{error:!0})),{once:!0}),t._xhr.addEventListener("timeout",(()=>r("Timeout","Timeout",{},{timeout:!0})),{once:!0}),t._xhr.addEventListener("load",(()=>r(t._xhr.status,t._xhr.responseText,t._xhr.getAllResponseHeaders())),{once:!0}),n(e.body)}})}(u,o),g&&y?(L.mappings=f,L.rules=_,e?.(f,{_o:g,mk:y,_mck:b,_rules:_})):u&&function(t,n,o,s){E({method:"get",url:h,async:!1,headers:{[l]:t,[c]:m,"x-mfm-adaptor":n}},(t=>{if(t)try{const{di:s,iv:i,_o:a,_mck:d,mk:c,r:l}=t,m=R({di:s,iv:i},a);x({_o:a,mk:c,_mck:d,_rules:l}),m&&(r(m),n=m,o={_o:a,mk:c,_mck:d,_rules:l},L.updateMappings(n,o),e?.(n,o))}catch(e){return void s(new Error("Unable to fetch mocked apis"))}var n,o}),(e=>{console.log("Error in loading mocked apis"),s(e)})).request()}(u,o,0,t)},checkIfApiToBeMocked:i,getMappings:s,doFetchMappings:(e,t)=>{S(u||L.token,o,((t,n)=>{L.updateMappings(t,n),e?.(t,n)}),t)},recheckWidgetVisibility:()=>{L.init()}}},B=e();B||(globalThis.mockforme=U);let N=U;B&&(N=e=>({run:()=>{}}));const P=N;export{P 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,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 I(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 M=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&&(window.addEventListener("resize",(()=>{this.bubble&&this.keepInBounds(this.bubble)})),"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: 25px;\n height: 25px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #2563eb;\n font-size: 25px;\n transition: background 0.2s;\n margin-right: 10px;\n background: #f3f4f6;\n padding: 8px;\n }\n .mfm-refresh-icon:hover { }\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: 80vh;\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 @media (max-width: 480px) {\n .mfm-bottomsheet { padding: 16px; }\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: 15px;\n padding-bottom: 10px;\n border-bottom: 1px solid #eee;\n flex-shrink: 0;\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: 20px 0; width: 100%; display: flex; justify-content: center; flex-shrink: 0; }\n .mfm-logo { width: 120px; 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: 10px; flex-shrink: 0; }\n .mfm-tab {\n padding: 8px 16px;\n cursor: pointer;\n color: #666;\n border-bottom: 2px solid transparent;\n font-weight: 500;\n font-size: 14px;\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; flex-shrink: 0; }\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: 25px; cursor: pointer; color: #666; display: flex; align-items: center; justify-content: center; padding: 4px; border-radius: 4px; }\n .mfm-icon-btn:hover { color: #333; }\n .mfm-icon-btn.refresh { color: #2563eb; padding: 0; height: 20px; width:20px; border-radius: 50%; }\n .mfm-icon-btn.refresh.loading { animation: mfm-spin 1s linear infinite; }\n .mfm-icon-btn.delete { color: #dc2626; }\n\n @media (max-height: 700px) {\n .mfm-bottomsheet { height: 85vh; padding: 12px; }\n .mfm-logo-container { padding: 10px 0; }\n .mfm-logo { width: 100px; }\n .mfm-header { margin-bottom: 10px; }\n .mfm-form { gap: 8px; }\n .mfm-input { padding: 10px; font-size: 14px; }\n .mfm-btn { padding: 10px; font-size: 14px; }\n }\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),this.keepInBounds(e),e.querySelector("img").onclick=e=>{this.isDragging||this.toggleSheet()},e.querySelector(".mfm-refresh-icon").onclick=e=>{e.stopPropagation(),this.refreshMappings()},e}keepInBounds(e){const t=e.getBoundingClientRect(),n=10;let s=parseInt(e.style.right)||20,o=parseInt(e.style.bottom)||20;const r=window.innerWidth-t.width-n,i=window.innerHeight-t.height-n;s<n&&(s=n),o<n&&(o=n),s>r&&(s=r),o>i&&(o=i),e.style.right=s+"px",e.style.bottom=o+"px"}addDragLogic(e){let t,n,s,o,r=!1;const i=(i,a)=>{r=!1,this.isDragging=!1,t=i,n=a;const d=e.getBoundingClientRect();s=window.innerWidth-d.right,o=window.innerHeight-d.bottom},a=(i,a)=>{const d=t-i,c=n-a;(Math.abs(d)>3||Math.abs(c)>3)&&(r=!0,this.isDragging=!0),r&&(e.style.right=s+d+"px",e.style.bottom=o+c+"px")},d=()=>{r&&(this.keepInBounds(e),"undefined"!=typeof localStorage&&localStorage.setItem("mockforme-dot-pos",JSON.stringify({bottom:parseInt(e.style.bottom),right:parseInt(e.style.right)})))},c=e=>{a(e.clientX,e.clientY)},l=()=>{document.removeEventListener("mousemove",c),document.removeEventListener("mouseup",l),d()},m=e=>{const t=e.touches[0];a(t.clientX,t.clientY),r&&e.cancelable&&e.preventDefault()},u=()=>{document.removeEventListener("touchmove",m),document.removeEventListener("touchend",u),d()};e.addEventListener("mousedown",(e=>{i(e.clientX,e.clientY),document.addEventListener("mousemove",c),document.addEventListener("mouseup",l)})),e.addEventListener("touchstart",(e=>{const t=e.touches[0];i(t.clientX,t.clientY),document.addEventListener("touchmove",m,{passive:!1}),document.addEventListener("touchend",u)}),{passive:!0})}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"))),I(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",I(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("undefined"!=typeof FormData&&e instanceof FormData){const t={};return e.forEach(((e,n)=>{"undefined"!=typeof File&&e instanceof File?t[n]=`[File: ${e.name} (${e.size} bytes)]`:"undefined"!=typeof Blob&&e instanceof Blob?t[n]=`[Blob: ${e.type} (${e.size} bytes)]`:t[n]=e})),JSON.stringify(t,null,2)}if("undefined"!=typeof URLSearchParams&&e instanceof URLSearchParams)return JSON.stringify(Object.fromEntries(e.entries()),null,2);if("undefined"!=typeof Blob&&e instanceof Blob)return`[${"undefined"!=typeof File&&e instanceof File?"File":"Blob"}: ${e.type||"binary"} (${e.size} bytes)]`;if(e instanceof ArrayBuffer||"undefined"!=typeof Uint8Array&&e instanceof Uint8Array)return`[Binary Data: ${e.byteLength||e.length} bytes]`;if("object"==typeof e)try{return JSON.stringify(e,null,2)}catch{return String(e)}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(M.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;M.addRequest("mocked",{...a,requestId:b,status:e.status,pending:!1,duration:t})})).catch((e=>{const t=Date.now()-x;M.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;M.addRequest("mocked",{...a,requestId:b,status:e.status,pending:!1,duration:t})})).catch((e=>{const t=Date.now()-x;M.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 M.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;M.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=M.token||e;if(!y&&!g)return M.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();M.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 M.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 I=o.body;if(!I&&s instanceof Request){const e=s.clone();"GET"!==e.method&&"HEAD"!==e.method&&(I=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?(M.addRequest("mocked",{...a,requestBody:e||a.requestBody,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;M.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 M.addRequest("mocked",{...a,requestId:b,status:n?"Aborted":0,responseHeaders:{},responseBody:e.message,pending:!1,duration:t,aborted:n}),e}))):(M.addRequest("mocked",{...a,requestBody:e||a.requestBody,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=>(M.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 M.addRequest("mocked",{...a,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(M.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,M.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=M.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,M.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(M.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"),M.token=e,M.isAuthenticated=!0),!e&&M.token&&(e=M.token),M.onAuthSuccess=(e,t,n)=>{i(t),v(n),M.mappings=t,M.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?(M.mappings=o,M.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},M.mappings=n,M.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)=>{I(e||M.token,s,((e,n)=>{M.mappings=e,M.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})()));
|
|
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 o in n)e.o(n,o)&&!e.o(t,o)&&Object.defineProperty(t,o,{enumerable:!0,get:n[o]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},t={};e.d(t,{mockforme:()=>D});const n=()=>"undefined"!=typeof process&&null!=process.versions?.node,o=e=>{try{return e?e.toLowerCase():e}catch(e){return console.log(e),null}},r=(e,t)=>{const n=e.split("/"),o=t.split("/");if(n.length!==o.length)return!1;for(let e=0;e<n.length;e++){const t=n[e];if(t!==o[e]&&":any"!==t)return!1}return!0};let s=[];function i(e){s=e}function a(){return s}function d(e,t="get"){const n=e=>e.startsWith("/")?e:`/${e}`,i=n(e);for(const a of s)if(o(a.apiMethod)===o(t)){const o=n(a.apiEndpoint);if(o===i||r(o,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",p="4.2.7",h="https://api.mockforme.com",f=`${h}/mockforme`,g=`${h}/gateway/3f4eae522b`;let y=null,b=null,x=null,w=[];function v({_o:e,mk:t,_mck:n,_rules:o}){y=e,b=t,x=n,w=o}function k(){return w}function q(){return`${f}/${y}/${b}`}function E(){return x}const R=e=>{try{return new URL(e,window.location.origin).toString()}catch{return e}},S=function(e,t,o){const r=n();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 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,s)}else o.call(this,s.responseText,s)}function a(e,t){var n=[];for(var o in e)if(e.hasOwnProperty(o)){var r=t?t+"["+o+"]":o,s=e[o];n.push("object"==typeof s?a(s,r):encodeURIComponent(r)+"="+encodeURIComponent(s))}return n.join("&")}return r||(window.XMLHttpRequest?s=new XMLHttpRequest:window.ActiveXObject&&(s=new ActiveXObject("Microsoft.XMLHTTP"))),{request:function(){if(!r){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 n=e.url.split("?");n[1]&&n[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 _({di:e,iv:t},n){var o;const r=function(e,t){const n=t.length;return e.split("").map(((e,o)=>String.fromCharCode(e.charCodeAt(0)^t.charCodeAt(o%n)))).join("")}((o=e,"undefined"!=typeof Buffer?Buffer.from(o,"base64").toString("utf8"):decodeURIComponent(escape(atob(o)))),n+t);return JSON.parse(r)}function T(e,t,n,o){fetch(g,{method:"GET",headers:{[u]:e,[m]:p,"x-mfm-adaptor":t}}).then((e=>{if(!e.ok)throw e;return e.json()})).then((e=>{if(e){const{di:t,iv:o,_o:r,_mck:s,mk:a,r:d}=e,c=_({di:t,iv:o},r);v({_o:r,mk:a,_mck:s,_rules:d}),c&&(i(c),n(c,{_o:r,mk:a,_mck:s,_rules:d}))}})).catch((e=>{console.error("Error in loading mocked APIs:",e),o(e)}))}const M='<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:block;"><path d="M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8"></path><polyline points="21 3 21 8 16 8"></polyline></svg>',L='<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:block;"><circle cx="12" cy="12" r="1.5"></circle><circle cx="12" cy="5" r="1.5"></circle><circle cx="12" cy="19" r="1.5"></circle></svg>',$='<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:block;"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>',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.widgetKey=e.widgetKey||null,this.mockedRequests=[],this.otherRequests=[],this.state={isOpen:"undefined"!=typeof localStorage&&"true"===localStorage.getItem("mockforme-widget-open"),activeTab:"mappings",selectedRequest:null,activeRequestTab:"response",lastError:null,searchQuery:""},"undefined"!=typeof document&&(window.addEventListener("resize",(()=>{this.bubble&&this.keepInBounds(this.bubble)})),document.addEventListener("click",(e=>{this.sharedDropdown&&this.sharedDropdown.classList.remove("show")}))))}init(){if("undefined"!=typeof document&&document.getElementById)if(this.checkVisibility())if(document.body)this.initWidget();else{const e=()=>{document.body&&this.initWidget()};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",e,{once:!0}):"interactive"===document.readyState||"complete"===document.readyState?setTimeout(e,0):window.addEventListener("load",e,{once:!0})}else{const e=document.getElementById("mockforme-root");e&&e.remove()}}initWidget(){document.getElementById("mockforme-root")||(this.createStyles(),this.render())}setWidgetKey(e){this.widgetKey=e,this.init()}checkVisibility(){return!this.widgetKey||"undefined"!=typeof localStorage&&localStorage.getItem("widgetKey")===this.widgetKey}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: 0px 12px;\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: 28px;\n height: 28px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #2563eb;\n transition: background 0.2s;\n margin-right: 10px;\n background: #f3f4f6;\n padding: 0;\n }\n .mfm-refresh-icon svg { width: 16px; height: 16px; }\n .mfm-refresh-icon:hover { }\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: 80vh;\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 @media (max-width: 480px) {\n .mfm-bottomsheet { padding: 16px; }\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: 15px;\n padding-bottom: 10px;\n border-bottom: 1px solid #eee;\n flex-shrink: 0;\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-title img { height: 30px; }\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; padding: 4px; cursor: pointer; color: #666; display: flex; align-items: center; justify-content: center; }\n .mfm-close:hover { color: #111; background: #f3f4f6; border-radius: 4px; }\n /* Login Form */\n .mfm-logo-container { text-align: center; padding: 20px 0; width: 100%; display: flex; justify-content: center; flex-shrink: 0; }\n .mfm-logo { width: 120px; 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 { \n display: flex; \n border-bottom: 1px solid #dee2e6; \n margin-bottom: 10px; \n flex-shrink: 0; \n gap: 2px;\n }\n .mfm-tab {\n padding: 8px 16px;\n cursor: pointer;\n color: #666;\n border: 1px solid transparent;\n border-bottom: none;\n border-top-left-radius: 6px;\n border-top-right-radius: 6px;\n font-weight: 300;\n font-size: 14px;\n margin-bottom: -1px;\n transition: all 0.2s;\n }\n .mfm-tab:hover {\n background-color: #f8f9fa;\n border-color: #e9ecef #e9ecef transparent;\n }\n .mfm-tab.active { \n color: #2563eb; \n background-color: white;\n border: 1px solid #dee2e6;\n border-bottom: 1px solid white;\n font-weight: 500;\n }\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 flex-wrap: wrap;\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; flex-shrink: 0; }\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; cursor: pointer; color: #666; display: flex; align-items: center; justify-content: center; padding: 4px; border-radius: 4px; }\n .mfm-icon-btn:hover { color: #333; background: #f3f4f6; }\n .mfm-icon-btn.refresh { color: #2563eb; padding: 0; height: 24px; width:24px; 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-non-2xx { color: #dc2626; }\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-redirect-badge {\n font-size: 10px;\n color: #166534;\n background: #dcfce7;\n padding: 2px 6px;\n border-radius: 10px;\n margin-top: 2px;\n display: inline-block;\n font-weight: 500;\n border: 1px solid #bbf7d0;\n }\n\n /* Mapping UI Enhanced */\n .mfm-mapping-info { display: flex; flex-direction: column; flex: 1; overflow: hidden; }\n .mfm-rule-name { font-weight: 600; color: #1f2937; margin-bottom: 2px; display: block; overflow: hidden; text-overflow: ellipsis; }\n .mfm-condition-brief { font-size: 11px; color: #6b7280; font-family: monospace; cursor: pointer; }\n .mfm-condition-brief:hover { color: #2563eb; text-decoration: underline; }\n .mfm-mod-actions-count { \n font-size: 10px; \n background: #eff6ff; \n color: #1d4ed8; \n padding: 2px 6px; \n border-radius: 12px; \n cursor: pointer; \n font-weight: 600;\n margin-top: 4px;\n display: inline-block;\n width: fit-content;\n }\n .mfm-mod-actions-count:hover { background: #dbeafe; }\n\n /* Modals */\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: 90%;\n max-width: 400px;\n max-height: 80vh;\n overflow-y: auto;\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: 12px; display: flex; justify-content: space-between; align-items: center; }\n .mfm-modal-body { font-size: 14px; color: #4b5563; }\n .mfm-modal-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 20px; }\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 .mfm-mod-item { border-bottom: 1px solid #eee; padding-bottom: 8px; margin-bottom: 8px; }\n .mfm-mod-item:last-child { border-bottom: none; margin-bottom: 0; }\n .mfm-mod-type { font-weight: 600; font-size: 12px; color: #2563eb; text-transform: uppercase; margin-bottom: 4px; }\n .mfm-mod-detail { font-size: 11px; font-family: monospace; word-break: break-all; }\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 .mfm-duration { color: #666; font-size: 11px; margin-left: 8px; font-weight: normal; }\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 .section-header { display: flex; align-items: center; justify-content: space-between; margin: 10px 0 5px; }\n .mfm-copy-btn {\n background: #f1f5f9;\n color: #64748b;\n padding: 2px 8px;\n border-radius: 4px;\n font-size: 10px;\n cursor: pointer;\n border: 1px solid #e2e8f0;\n transition: all 0.2s;\n font-weight: 600;\n text-transform: uppercase;\n }\n .mfm-copy-btn:hover { background: #e2e8f0; color: #334155; }\n \n .mfm-copy-group {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n margin-top: 4px;\n }\n .mfm-copy-group .mfm-copy-btn {\n font-size: 9px;\n padding: 2px 6px;\n }\n\n /* Dropdown Menu */\n .mfm-menu-dots {\n cursor: pointer;\n padding: 4px;\n color: #666;\n border-radius: 4px;\n transition: background 0.2s;\n line-height: 1;\n margin-left: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n .mfm-menu-dots:hover { background: #f3f4f6; color: #333; }\n \n .mfm-dropdown-shared {\n position: fixed;\n background: white;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0,0,0,0.15);\n z-index: 1000005;\n display: none;\n flex-direction: column;\n width: 160px;\n overflow: hidden;\n }\n .mfm-dropdown-shared.show { display: flex; }\n .mfm-dropdown-item {\n padding: 10px 14px;\n font-size: 13px;\n color: #334155;\n cursor: pointer;\n transition: background 0.2s;\n text-align: left;\n border-bottom: 1px solid #f1f5f9;\n white-space: nowrap;\n }\n .mfm-dropdown-item:last-child { border-bottom: none; }\n .mfm-dropdown-item:hover { background: #f8fafc; color: #2563eb; }\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 ",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.sharedDropdown=document.createElement("div"),this.sharedDropdown.className="mfm-dropdown-shared",this.sharedDropdown.innerHTML='\n <div class="mfm-dropdown-item" data-format="curl">Copy as cURL</div>\n <div class="mfm-dropdown-item" data-format="fetch">Copy as Fetch</div>\n <div class="mfm-dropdown-item" data-format="xhr">Copy as XHR</div>\n ',this.root.appendChild(this.sharedDropdown),this.updateUI()}updateUI(){this.sheet&&(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">${M}</div>\n <img src="https://ik.imagekit.io/mfm/static-collection/mfm-48x48.png" alt="MFM" />\n `,this.addDragLogic(e),this.keepInBounds(e),e.querySelector("img").onclick=e=>{this.isDragging||this.toggleSheet()},e.querySelector(".mfm-refresh-icon").onclick=e=>{e.stopPropagation(),this.refreshMappings()},e}keepInBounds(e){const t=e.getBoundingClientRect(),n=10;let o=parseInt(e.style.right)||20,r=parseInt(e.style.bottom)||20;const s=window.innerWidth-t.width-n,i=window.innerHeight-t.height-n;o<n&&(o=n),r<n&&(r=n),o>s&&(o=s),r>i&&(r=i),e.style.right=o+"px",e.style.bottom=r+"px"}addDragLogic(e){let t,n,o,r,s=!1;const i=(i,a)=>{s=!1,this.isDragging=!1,t=i,n=a;const d=e.getBoundingClientRect();o=window.innerWidth-d.right,r=window.innerHeight-d.bottom},a=(i,a)=>{const d=t-i,c=n-a;(Math.abs(d)>3||Math.abs(c)>3)&&(s=!0,this.isDragging=!0),s&&(e.style.right=o+d+"px",e.style.bottom=r+c+"px")},d=()=>{s&&(this.keepInBounds(e),"undefined"!=typeof localStorage&&localStorage.setItem("mockforme-dot-pos",JSON.stringify({bottom:parseInt(e.style.bottom),right:parseInt(e.style.right)})))},c=e=>{a(e.clientX,e.clientY)},l=()=>{document.removeEventListener("mousemove",c),document.removeEventListener("mouseup",l),d()},m=e=>{const t=e.touches[0];a(t.clientX,t.clientY),s&&e.cancelable&&e.preventDefault()},u=()=>{document.removeEventListener("touchmove",m),document.removeEventListener("touchend",u),d()};e.addEventListener("mousedown",(e=>{i(e.clientX,e.clientY),document.addEventListener("mousemove",c),document.addEventListener("mouseup",l)})),e.addEventListener("touchstart",(e=>{const t=e.touches[0];i(t.clientX,t.clientY),document.addEventListener("touchmove",m,{passive:!1}),document.addEventListener("touchend",u)}),{passive:!0})}toggleSheet(){this.state.isOpen=!this.state.isOpen,"undefined"!=typeof localStorage&&localStorage.setItem("mockforme-widget-open",this.state.isOpen),this.updateUI()}showSnackbar(e){this.snackbar&&(this.snackbar.textContent=e,this.snackbar.classList.add("show"),setTimeout((()=>this.snackbar.classList.remove("show")),3e3))}showConfirm(e,t,n){this.showModal(e,t,[{label:"Cancel",className:"mfm-btn-alt",onClick:e=>e.classList.remove("show")},{label:"Delete",className:"mfm-btn-danger",onClick:e=>{e.classList.remove("show"),n()}}])}showModal(e,t,n=[]){if(!this.modalOverlay)return;this.modalOverlay.innerHTML=`\n <div class="mfm-modal">\n <div class="mfm-modal-title">\n <span>${e}</span>\n <span style="cursor:pointer;" id="mfm-modal-close">${$}</span>\n </div>\n <div class="mfm-modal-body">${t}</div>\n <div class="mfm-modal-actions" id="mfm-modal-actions"></div>\n </div>\n `;const o=this.modalOverlay.querySelector("#mfm-modal-actions");if(n.forEach((e=>{const t=document.createElement("button");t.className=e.className||"mfm-btn-alt",t.textContent=e.label,t.onclick=()=>e.onClick(this.modalOverlay),o.appendChild(t)})),0===n.length){const e=document.createElement("button");e.className="mfm-btn",e.textContent="OK",e.onclick=()=>this.modalOverlay.classList.remove("show"),o.appendChild(e)}this.modalOverlay.querySelector("#mfm-modal-close").onclick=()=>{this.modalOverlay.classList.remove("show")},this.modalOverlay.classList.add("show")}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 o=n.value.trim();o&&(t.textContent="Validating...",t.disabled=!0,this.state.lastError=null,e.querySelector("#mfm-error-msg").style.display="none",T(o,c,((e,t)=>{"undefined"!=typeof localStorage&&localStorage.setItem("mockforme-token",o),this.token=o,this.isAuthenticated=!0,this.mappings=e,this.rules=t?._rules||[],this.onAuthSuccess(o,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}updateMappings(e,t){this.mappings=e||[],this.rules=t?._rules||[],this.root&&this.updateUI()}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"><img src="https://www.mockforme.com/assets/images/logo.png" /></span>\n <div class="mfm-header-actions">\n <button class="mfm-close">${$}</button>\n </div>\n </div>\n `;const t=document.createElement("div");t.className="mfm-tabs",["mappings","mocked","other","settings"].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"===e?"Other Apis":"Settings",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">${M}</div>\n `,n.querySelector("#mfm-refresh-mappings-btn").onclick=()=>this.refreshMappings()):"settings"!==this.state.activeTab?(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"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:block;"><circle cx="12" cy="12" r="10"></circle><line x1="4.93" y1="4.93" x2="19.07" y2="19.07"></line></svg></button>\n `,n.querySelector("#mfm-search-input").oninput=e=>{this.state.searchQuery=e.target.value,this.updateRequestList(o)},n.querySelector("#mfm-clear-requests-btn").onclick=()=>{"mocked"===this.state.activeTab?this.mockedRequests=[]:this.otherRequests=[],this.updateUI()}):n.style.display="none",t.after(n);const o=document.createElement("div");return o.className="mfm-list",this.updateRequestList(o),e.appendChild(o),e.querySelector(".mfm-close").onclick=()=>this.toggleSheet(),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.rule||t,o=e.timingAction||{},r=o.activeAction||"none",s=o.actions?.[r]?.value,i=`Rule (${r}${void 0!==s?` ${s}s`:""})`;let a="{}";e.conditions&&Array.isArray(e.conditions)&&(a=e.conditions.map((e=>`${e.type}:${e.operator}:${e.value}`)).join(" AND "));const d=a.length>40?a.substring(0,40)+"...":a;let c=0;const l=e.modificationActions||{};Object.values(l).forEach((e=>{e.enabled&&(e.add&&(c+=e.add.length),e.remove&&(c+=e.remove.length),e.update&&(c+=e.update.length))})),n.innerHTML=`\n <div class="mfm-mapping-info">\n <span class="mfm-rule-name" style="cursor:pointer; color:#2563eb; text-decoration:underline;" id="mfm-view-full-rule" title="View full rule details">${i}</span>\n <span class="mfm-condition-brief" title="View condition">\n ${d} <span style="font-weight:bold; color:#2563eb; margin-left:4px; cursor:pointer;" id="mfm-view-cond-dots">${L}</span>\n </span>\n ${c>0?`<div class="mfm-mod-actions-count" id="mfm-view-mods">${c} Modification Actions</div>`:""}\n </div>\n <span class="mfm-method RULE">RULE</span>\n `,n.querySelector("#mfm-view-full-rule").onclick=t=>{t.stopPropagation();const n=JSON.stringify(e,null,2);this.showModal("Full Rule Information",`<pre class="mfm-code-block">${n}</pre>`)},n.querySelector("#mfm-view-cond-dots").onclick=t=>{t.stopPropagation();const n=e.conditions.map((e=>`\n <div class="mfm-mod-item">\n <div class="mfm-mod-type">${e.type} (${e.operator})</div>\n <div class="mfm-mod-detail"><b>Key:</b> ${e.key||"N/A"}<br><b>Value:</b> ${e.value}</div>\n </div>\n `)).join("");this.showModal("Rule Conditions",n)},c>0&&(n.querySelector("#mfm-view-mods").onclick=e=>{e.stopPropagation();let t="";Object.entries(l).forEach((([e,n])=>{n.enabled&&(t+=`<div class="mfm-mod-item"><div class="mfm-mod-type">${e.replace("modify","")}</div>`,n.add?.length&&(t+=`<div class="mfm-mod-detail"><b>Add:</b> ${JSON.stringify(n.add)}</div>`),n.update?.length&&(t+=`<div class="mfm-mod-detail"><b>Update:</b> ${JSON.stringify(n.update)}</div>`),n.remove?.length&&(t+=`<div class="mfm-mod-detail"><b>Remove:</b> ${JSON.stringify(n.remove)}</div>`),t+="</div>")})),this.showModal("Modification Actions",t)})}e.appendChild(n)}))}else if("settings"===this.state.activeTab)e.innerHTML='\n <div style="padding: 16px;">\n <div class="section-title" style="margin-top: 0; margin-bottom: 12px; font-size: 15px; border-bottom: 1px solid #eee; padding-bottom: 8px;">Token Management</div>\n <p style="font-size: 13px; color: #666; margin-bottom: 16px;">Removing your token will clear all saved mappings and rules from this browser instance.</p>\n <button class="mfm-delete-token-btn" id="mfm-settings-delete-token" style="padding: 8px 16px; font-size: 14px; width: fit-content;">\n <span><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:block;"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path><line x1="10" y1="11" x2="10" y2="17"></line><line x1="14" y1="11" x2="14" y2="17"></line></svg></span>\n <span>Delete Token</span>\n </button>\n </div>\n ',e.querySelector("#mfm-settings-delete-token").onclick=()=>{this.showConfirm("Delete Token","Are you sure you want to Delete Token? This will clear your saved token.",(()=>{this.deleteToken()}))};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 o=(t.method||"").toUpperCase(),r=`<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>`;let s="",i="";if(t.rule){const e=t.rule.action||"";let n="delay_and_timeout"===e?"Delay and Timout":e.split("_")[0];const o=t.rule.config?.value;void 0!==o&&(e.includes("delay")||e.includes("timeout"))&&(n+=` (${o}s)`),s=`<span class="mfm-rule-tag" title="${e}">${n}</span>`,"delay_and_redirect"===e&&t.rule.config?.redirectUrl&&(i=`<div class="mfm-redirect-badge">Redirected to: ${t.rule.config.redirectUrl}</div>`)}let a=t.status,d="mfm-status";t.pending?a='<span class="mfm-spinner"></span>':t.aborted?(a="Aborted",d+=" status-aborted"):t.timeout?(a="Timeout",d+=" status-timeout"):t.error?(a="Error/CORS",d+=" status-error"):(a=t.status,d+=t.status>=200&&t.status<300?" status-2xx":" status-non-2xx"),n.innerHTML=`\n <div style="display:flex; align-items:center; width:100%; gap:8px;">\n <span class="mfm-method ${o}">${o}</span>\n <div style="flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; justify-content:center;">\n <span class="mfm-url">${s}${t.url}</span>\n ${i}\n ${r}\n </div>\n <span class="${d}">${a}</span>\n <span class="mfm-menu-dots" title="Copy As...">${L}</span>\n </div>\n `;const c=n.querySelector(".mfm-menu-dots");c.onclick=e=>{e.stopPropagation();const n=c.getBoundingClientRect();this.sharedDropdown.style.top=n.bottom+5+"px",this.sharedDropdown.style.left=n.right-160+"px",this.sharedDropdown.classList.toggle("show"),this.sharedDropdown.onclick=e=>{e.stopPropagation();const n=e.target.getAttribute("data-format");if(!n)return;let o="";"curl"===n?o=this.generateCurl(t):"fetch"===n?o=this.generateFetch(t):"xhr"===n&&(o=this.generateXHR(t)),o&&navigator.clipboard.writeText(o).then((()=>{this.showSnackbar(`${n.toUpperCase()} copied!`),this.sharedDropdown.classList.remove("show")}))}},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"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:inline-block; vertical-align:middle; margin-right:4px;"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg>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 o=document.createElement("div");o.style.overflowY="auto",o.style.flex="1";const r=(e.method||"").toUpperCase(),s=this.formatBody(e.requestBody),i=this.formatBody(e.responseBody);o.innerHTML="request"===this.state.activeRequestTab?`\n <div class="section-title">URL</div><div class="mfm-code-block">${r} ${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-header">\n <div class="section-title" style="margin: 0;">Payload</div>\n <div class="mfm-copy-btn" id="mfm-copy-payload">Copy</div>\n </div>\n <div class="mfm-code-block">${s}</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-header">\n <div class="section-title" style="margin: 0;">Response Body</div>\n <div class="mfm-copy-btn" id="mfm-copy-response">Copy</div>\n </div>\n <div class="mfm-code-block">${i}</div>\n `,t.appendChild(n),t.appendChild(o);const a=o.querySelector("#mfm-copy-payload");a&&(a.onclick=()=>{navigator.clipboard.writeText(s).then((()=>{this.showSnackbar("Payload copied!")}))});const d=o.querySelector("#mfm-copy-response");return d&&(d.onclick=()=>{navigator.clipboard.writeText(i).then((()=>{this.showSnackbar("Response copied!")}))}),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("undefined"!=typeof FormData&&e instanceof FormData){const t={};return e.forEach(((e,n)=>{"undefined"!=typeof File&&e instanceof File?t[n]=`[File: ${e.name} (${e.size} bytes)]`:"undefined"!=typeof Blob&&e instanceof Blob?t[n]=`[Blob: ${e.type} (${e.size} bytes)]`:t[n]=e})),JSON.stringify(t,null,2)}if("undefined"!=typeof URLSearchParams&&e instanceof URLSearchParams)return JSON.stringify(Object.fromEntries(e.entries()),null,2);if("undefined"!=typeof Blob&&e instanceof Blob)return`[${"undefined"!=typeof File&&e instanceof File?"File":"Blob"}: ${e.type||"binary"} (${e.size} bytes)]`;if(e instanceof ArrayBuffer||"undefined"!=typeof Uint8Array&&e instanceof Uint8Array)return`[Binary Data: ${e.byteLength||e.length} bytes]`;if("object"==typeof e)try{return JSON.stringify(e,null,2)}catch{return String(e)}try{return JSON.stringify(JSON.parse(e),null,2)}catch{return e}}generateCurl(e){const t=(e.method||"GET").toUpperCase();let n=`curl -X ${t} "${e.url}"`;if(e.requestHeaders&&Object.entries(e.requestHeaders).forEach((([e,t])=>{n+=` \\\n -H "${e}: ${t}"`})),e.requestBody&&"GET"!==t){const t=("string"==typeof e.requestBody?e.requestBody:JSON.stringify(e.requestBody)).replace(/'/g,"'\\''");n+=` \\\n --data-raw '${t}'`}return n}generateFetch(e){const t=(e.method||"GET").toUpperCase();let n=`{\n method: "${t}",\n headers: ${(e.requestHeaders?JSON.stringify(e.requestHeaders,null,2):"{}").replace(/\n/g,"\n ")}`;if(e.requestBody&&"GET"!==t){const t="string"==typeof e.requestBody?e.requestBody:JSON.stringify(e.requestBody,null,2);n+=`,\n body: ${"string"==typeof e.requestBody?"`"+t+"`":JSON.stringify(e.requestBody,null,2).replace(/\n/g,"\n ")}`}return n+="\n}",`fetch("${e.url}", ${n})\n .then(response => response.json())\n .then(data => console.log(data))\n .catch(error => console.error(error));`}generateXHR(e){const t=(e.method||"GET").toUpperCase();let n=`var xhr = new XMLHttpRequest();\nxhr.open("${t}", "${e.url}");\n`;if(e.requestHeaders&&Object.entries(e.requestHeaders).forEach((([e,t])=>{n+=`xhr.setRequestHeader("${e}", "${t}");\n`})),n+="\nxhr.onload = function() {\n console.log(xhr.responseText);\n};\n",e.requestBody&&"GET"!==t){const t="string"==typeof e.requestBody?e.requestBody:JSON.stringify(e.requestBody);n+=`\nxhr.send(${"string"==typeof e.requestBody?"`"+t+"`":JSON.stringify(e.requestBody)});`}else n+="\nxhr.send();";return n}addRequest(e,t){const n=String(t.method||"").toUpperCase().trim(),o=String(t.url||"");console.log(`[MockForMe] addRequest type=${e} method=${n} url=${o} requestId=${t.requestId} pending=${t.pending}`);const r=o.includes("api.mockforme.com")||o.includes("mockforme.com/proxy")||o.includes("mockforme.com/gateway")||o.includes("/3f4eae522b")||f&&o.includes(String(f));if("OPTIONS"===n||r)return;const s="mocked"===e?this.mockedRequests:this.otherRequests,i="mocked"===e?this.otherRequests:this.mockedRequests;if(t.requestId){const e=s.findIndex((e=>e.requestId===t.requestId));if(-1!==e)return s[e]={...s[e],...t},void this.updateUI();const n=i.findIndex((e=>e.requestId===t.requestId));if(-1!==n){const e={...i[n],...t};return i.splice(n,1),s.unshift(e),s.length>100&&s.pop(),void this.updateUI()}}s.unshift(t),s.length>100&&s.pop(),this.updateUI()}};class A{static match(e,t){if(!Array.isArray(t)||0===t.length)return!1;const{url:n,headers:o,queryParams:r,body:s}=e,i="undefined"!=typeof window?window.location.origin:globalThis.location?.origin||"http://localhost";for(const e of t){let t="";const{type:a,key:d,operator:c,value:l}=e;switch(a){case"URL":try{t=new URL(n,i).pathname}catch{t=n}break;case"QUERY_PARAM":if(r&&void 0!==r[d])t=String(r[d]);else try{t=new URL(n,i).searchParams.get(d)||""}catch{t=""}break;case"REQUEST_BODY":if(d){if("object"==typeof s&&null!==s)t=void 0!==s[d]?String(s[d]):"";else if("string"==typeof s)try{const e=JSON.parse(s);t=void 0!==e[d]?String(e[d]):""}catch{t=""}}else t="object"==typeof s?JSON.stringify(s):String(s||"");break;case"REQUEST_HEADER":if(d){const e=d?.toLowerCase();if(t="",o){const n=Object.keys(o).find((t=>t.toLowerCase()===e));t=n?String(o[n]):""}}else t=JSON.stringify(o||{});break;default:return!1}if(!this.evaluate(t,c,l))return!1}return!0}static evaluate(e,t,n){const o=t?.toLowerCase(),r=String(e),s=String(n);switch(o){case"contains":return r.includes(s);case"equal":case"equals":return r===s;case"regexp":try{let e=s;if(e.startsWith("/")&&e.lastIndexOf("/")>0){const t=e.lastIndexOf("/"),n=e.slice(1,t),o=e.slice(t+1);return new RegExp(n,o).test(r)}return new RegExp(e).test(r)}catch{return!1}default:return!1}}}class O{static async apply(e){if(!e||!e.activeAction)return{type:"passThrough",delay:0};const{activeAction:t,actions:n}=e,o=n?.[t];if(!o)return{type:"passThrough",delay:0};const r={type:"passThrough",delay:0},s=Number(o.value||0);switch(t){case"delay":r.delay=s,r.delay>0&&await new Promise((e=>setTimeout(e,1e3*r.delay)));break;case"delay_and_redirect":r.type="redirect",r.delay=s,r.redirectUrl=o.redirectUrl,r.delay>0&&await new Promise((e=>setTimeout(e,1e3*r.delay)));break;case"delay_and_timeout":r.type="timeout",r.delay=s,r.delay>0&&await new Promise((e=>setTimeout(e,1e3*r.delay)))}return r}}class C{static applyRequestModifications(e,t){if(!t)return e;let{url:n,headers:o,queryParams:r,body:s}={...e};o&&(o={...o}),r&&(r={...r});const{modifyQueryParams:i,modifyRequestBody:a,modifyRequestHeaders:d}=t;if(i?.enabled)try{const e=new URL(n,"undefined"!=typeof window?window.location.href:"http://localhost");Array.isArray(i.remove)&&i.remove.forEach((t=>{e.searchParams.delete(t),r&&delete r[t]})),Array.isArray(i.add)&&i.add.forEach((({key:t,value:n})=>{e.searchParams.set(t,n),r&&(r[t]=n)})),n=e.toString()}catch(e){console.error("[MockForMe] Failed to modify query params",e)}if(d?.enabled&&(o={...o},Array.isArray(d.remove)&&d.remove.forEach((e=>{const t=e.toLowerCase(),n=Object.keys(o).find((e=>e.toLowerCase()===t));n&&delete o[n]})),Array.isArray(d.add)&&d.add.forEach((({key:e,value:t})=>{o[e]=t}))),a?.enabled)try{let t=null;if("string"==typeof s)try{t=JSON.parse(s)}catch{}else if("object"==typeof s&&null!==s)try{t=JSON.parse(JSON.stringify(s))}catch{t={...s}}t&&(Array.isArray(a.remove)&&a.remove.forEach((e=>delete t[e])),Array.isArray(a.add)&&a.add.forEach((({key:e,value:n})=>t[e]=n)),Array.isArray(a.update)&&a.update.forEach((({key:e,value:n})=>t[e]=n)),s="string"==typeof e.body?JSON.stringify(t):t)}catch(e){console.error("[MockForMe] Failed to modify request body",e)}return{...e,url:n,headers:o,queryParams:r,body:s}}static applyResponseModifications(e,t){if(!t?.modifyResponseHeaders?.enabled)return e;const{modifyResponseHeaders:n}=t,o={...e};return Array.isArray(n.remove)&&n.remove.forEach((e=>{const t=e.toLowerCase(),n=Object.keys(o).find((e=>e.toLowerCase()===t));n&&delete o[n]})),Array.isArray(n.add)&&n.add.forEach((({key:e,value:t})=>{o[e]=t})),o}}class H{static match(e,t){if(!Array.isArray(t)||0===t.length)return null;for(const n of t){const t=n.rule||n;if(t.conditions&&Array.isArray(t.conditions)&&A.match(e,t.conditions)){const e=t.timingAction?.activeAction||"";return{action:e,config:t.timingAction?.actions?.[e]||{},rule:t}}}return null}static async apply(e,t){if(!e)return null;const n=e.rule||e,o=C.applyRequestModifications(t,n.modificationActions);return{...await O.apply(n.timingAction),modifiedRequest:o,rule:n}}static applyResponseModifications(e,t){return C.applyResponseModifications(e,t)}}class U{static apply({target:e=("undefined"!=typeof window?window:globalThis),originalFetch:t=e.fetch,ruleProvider:n=()=>[],mappingProvider:o=e=>null,onBeforeRequest:r=e=>{},onRuleMatch:s=async(e,t,n,o,r)=>null,onMockMatch:i=async(e,t,n,o,r)=>null,onOtherRequest:a=async(e,t,n,o)=>null}){t&&(e.fetch=async function(e,d={}){let c;try{const t="string"==typeof e?e:e.url,n=String(d.method||(e instanceof Request?e.method:"GET")).toUpperCase().trim(),o=Math.random().toString(36).substring(7);c={url:t,method:n,headers:d.headers||(e instanceof Request?e.headers:{}),body:d.body||(e instanceof Request?"{binary/stream}":null),requestId:o,queryParams:U.getQueryParams(t)},r(c)}catch(n){return console.warn("[MockForMe] Fetch Interceptor Setup Error:",n),t(e,d)}try{const r=n(),l=H.match(c,r);if(l){const n=await s(l,c,e,d,t);if(n)return n}const m=o(c);if(m){const n=await i(m,c,e,d,t);if(n)return n}const u=await a(c,e,d,t);if(u)return u}catch(e){if(e.message.includes("timed out")||"AbortError"===e.name||e.message.includes("rules"))throw e;console.warn("[MockForMe] Interceptor Hook Error:",e)}return t(e,d)})}static getQueryParams(e){try{const t="undefined"!=typeof window?window.location.origin:"http://localhost",n=new URL(e,t).searchParams;return Object.fromEntries(n.entries())}catch{return{}}}}class j{static apply({target:e=("undefined"!=typeof window?window:{}),OriginalXHR:t=e.XMLHttpRequest,ruleProvider:n=()=>[],mappingProvider:o=e=>null,onBeforeRequest:r=e=>{},onRuleMatch:s=(e,t,n,o)=>{o.call(n.proxy,t.body)},onMockMatch:i=(e,t,n,o)=>{o.call(n.proxy,t.body)},onOtherRequest:a=(e,t,n)=>{n.call(t.proxy,e.body)}}){t&&(e.XMLHttpRequest=class{constructor(){return this._xhr=new t,this._headers={},this._method=null,this._url=null,this._body=null,this._requestId=null,this._startTime=null,this._captured=!1,this._isMocked=!1,this.proxy=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)}),this.proxy}_capture(e,t,n,o={}){if(this._captured)return;this._captured=!0;const r=e=>{const t=`on${e}`;(this[t]||this._xhr[t])?.(),this._xhr.dispatchEvent(new Event(e))};if("Aborted"!==e)try{Object.defineProperty(this.proxy,"responseText",{value:t,configurable:!0}),Object.defineProperty(this.proxy,"response",{value:t,configurable:!0}),Object.defineProperty(this.proxy,"status",{value:Number(e)||0,configurable:!0}),Object.defineProperty(this.proxy,"statusText",{value:200==e?"OK":"",configurable:!0})}catch(e){console.warn("[MockForMe] Error setting XHR props",e)}Object.defineProperty(this.proxy,"readyState",{value:4,configurable:!0}),r("readystatechange"),"Aborted"===e||o.aborted?r("abort"):0===e||"Error"===e||o.error?r("error"):"Timeout"===e||o.timeout?r("timeout"):r("load")}open(e,t,n=!0,o=null,r=null){this._method=(e||"").toUpperCase().trim();try{this._url=new URL(t,"undefined"!=typeof window?window.location.href:"http://localhost").toString()}catch(e){this._url=t}return this._xhr.open(e,t,n,o,r)}setRequestHeader(e,t){return this._headers[e]=t,this._xhr.setRequestHeader(e,t)}send(e){this._body=e,this._requestId=Math.random().toString(36).substring(7),this._startTime=Date.now();const t={url:this._url,method:this._method,headers:this._headers,body:this._body,requestId:this._requestId,startTime:this._startTime,queryParams:j.getQueryParams(this._url)};r(t);const d=n(),c=H.match(t,d),l=e=>this._xhr.send(e);if(c)return this._isMocked=!0,s(c,t,this,l);const m=o(t);return m?(this._isMocked=!0,i(m,t,this,l)):(this._isMocked=!1,a(t,this,l))}})}static getQueryParams(e){try{const t="undefined"!=typeof window?window.location.origin:"http://localhost",n=new URL(e,t).searchParams;return Object.fromEntries(n.entries())}catch{return{}}}}const B=(e,t=null,o=c)=>{if(n())return;let r="string"==typeof e?e:e?.token,s="object"==typeof e?e?.widgetKey:null;if(s?I.setWidgetKey(s):I.init(),o===c)try{r&&("undefined"!=typeof localStorage&&localStorage.removeItem("mockforme-token"),I.token=r,I.isAuthenticated=!0),!r&&I.token&&(r=I.token),I.onAuthSuccess=(e,t,n)=>{i(t),v(n),I.updateMappings(t,n)}}catch(e){console.log("Error in showing mockforme widget",e)}t||={mappings:[],_o:null,mk:null,_mck:null,_rules:[]};const{mappings:h=[],_o:f,mk:y,_mck:b,_rules:x=[]}=t;return i(h),v({_o:f,mk:y,_mck:b,_rules:x}),{run:(e,t=()=>{})=>{!function(e,t){if("undefined"!=typeof window){if(window._mfm_intercepted)return;window._mfm_intercepted=!0}const n=()=>I.token||e;U.apply({ruleProvider:()=>k(),mappingProvider:e=>{try{return d(new URL(e.url,window.location.origin).pathname,e.method)}catch{return null}},onRuleMatch:async(e,t,n,o,r)=>{const s=t.requestId||Math.random().toString(36).substring(7),i=Date.now();I.addRequest("mocked",{...t,requestId:s,pending:!0,startTime:i,rule:e});const a=await H.apply(e,t),{modifiedRequest:d,type:c,delay:l,redirectUrl:m}=a;if("timeout"!==c&&I.addRequest("mocked",{...d,requestId:s,pending:!0,startTime:i,rule:e}),"timeout"===c){const e=Date.now()-i;throw I.addRequest("mocked",{...d,requestId:s,status:"Aborted",pending:!1,duration:e,aborted:!0}),new Error("Fetch timed out by rules")}let u="redirect"===c?m:d.url,p={...o};d.headers&&(p.headers=d.headers),d.body&&(p.body=d.body);let h=null;if("redirect"===c){h=Math.random().toString(36).substring(7);const e={url:m,method:d.method,headers:p.headers||{},body:p.body,requestId:h,queryParams:U.getQueryParams(m),requestHeaders:p.headers||{},requestBody:p.body,pending:!0,startTime:Date.now()};I.addRequest("mocked",e)}return r(u,p).then((async e=>{const t=Date.now()-i;let n=Object.fromEntries(e.headers.entries());if(a.rule.modificationActions?.modifyResponseHeaders?.enabled&&(n=H.applyResponseModifications(n,a.rule.modificationActions)),"redirect"===c&&h){const t=e.clone(),o=t.headers.get("content-type")||"",r=Date.now()-i;try{let s;s=o.includes("application/json")?await t.json():await t.text(),I.addRequest("mocked",{url:m,method:d.method,requestId:h,status:e.status,pending:!1,duration:r,responseHeaders:n,responseBody:s,requestHeaders:p.headers||{},requestBody:p.body})}catch(t){I.addRequest("mocked",{url:m,method:d.method,requestId:h,status:e.status,pending:!1,duration:r,responseHeaders:n,requestHeaders:p.headers||{},requestBody:p.body})}}return I.addRequest("mocked",{...d,requestId:s,status:e.status,pending:!1,duration:t,responseHeaders:n}),e})).catch((e=>{const t=Date.now()-i,n="AbortError"===e.name||e.message.includes("aborted");throw I.addRequest("mocked",{...d,requestId:s,status:n?"Aborted":0,pending:!1,duration:t}),"redirect"===c&&h&&I.addRequest("mocked",{url:m,method:d.method,requestId:h,status:n?"Aborted":0,pending:!1,duration:t,error:!n}),e}))},onMockMatch:async(e,o,r,s,i)=>{const a=o.requestId||Math.random().toString(36).substring(7),d=Date.now();I.addRequest("mocked",{...o,requestId:a,pending:!0,startTime:d});const c=n(),h=new URL(o.url,window.location.origin).search;let f=`${q()}${e.url}${h}`,g={[u]:c,[m]:p,"x-mfm-adaptor":t};const y=E();y&&e._ack&&(g["x-mfm-key"]=`${y}-${e._ack}`),e?._ri_&&(g._ri_=e._ri_);const b=r instanceof Request?r.headers:s.headers,x=new Headers(b||{});Object.entries(g).forEach((([e,t])=>x.set(e,t)));let w=s.body;if(!w&&r instanceof Request){const e=r.clone();"GET"!==e.method&&"HEAD"!==e.method&&(w=await e.text())}const v={method:o.method,headers:x,credentials:r instanceof Request&&r.credentials||s.credentials||"include",mode:r instanceof Request&&r.mode||s.mode||"cors"};return t===l?(({actualUrl:e,url:t,method:n,headers:o,body:r,credentials:s,mode:i,rule:a})=>{const d=`${Date.now()}-${Math.random()}`,c=R(t);return new Promise(((t,l)=>{window.addEventListener("message",(function e(n){if(n.source!==window)return;const o=n.data;if("INTERCEPTED_RESPONSE"===o?.type&&o?.requestId===d){if(window.removeEventListener("message",e),o?.response?.error)return l(new Error(o.response.message));const{status:n,headers:r,body:s}=o.response;t(new Response(s,{status:n,headers:r}))}})),window.postMessage({type:"REQUEST_INTERCEPTED",requestId:d,payload:{actualUrl:e,url:c,method:n,headers:o,body:r,credentials:s,mode:i,rule:a}},"*")}))})({actualUrl:o.url,url:f,method:o.method,headers:Object.fromEntries(x.entries()),body:w,credentials:v.credentials,mode:v.mode}).then((e=>(e.clone().text().then((t=>{const n=Date.now()-d;I.addRequest("mocked",{...o,requestId:a,status:e.status,responseHeaders:Object.fromEntries(e.headers.entries()),responseBody:t,pending:!1,duration:n})})),e))):(w&&(v.body=w),i(f,v).then((async e=>{const t=e.clone(),n=t.headers.get("content-type")||"",r=Date.now()-d,s=n=>(I.addRequest("mocked",{...o,requestId:a,status:e.status,responseHeaders:Object.fromEntries(t.headers.entries()),responseBody:n,pending:!1,duration:r}),new Response("string"==typeof n?n:JSON.stringify(n),{status:e.status,headers:t.headers}));return n.includes("application/json")?t.json().then(s):t.text().then(s)})).catch((e=>{const t=Date.now()-d;return I.addRequest("mocked",{...o,requestId:a,status:0,pending:!1,duration:t}),i(r,s)})))},onOtherRequest:async(e,t,n,o)=>{if("OPTIONS"===e.method)return o(t,n);const r=e.requestId,s=Date.now();return I.addRequest("other",{...e,requestId:r,pending:!0,startTime:s}),o(t,n).then((async t=>{const n=t.clone(),o=Date.now()-s;try{const s=await n.text();I.addRequest("other",{...e,requestId:r,status:t.status,responseHeaders:Object.fromEntries(t.headers.entries()),responseBody:s,pending:!1,duration:o})}catch(e){}return t})).catch((t=>{const n=Date.now()-s,o="AbortError"===t.name||t.message.includes("aborted"),i="TimeoutError"===t.name||t.message.includes("timed out");throw I.addRequest("other",{...e,requestId:r,status:o?"Aborted":i?"Timeout":"Error",pending:!1,duration:n,aborted:o,timeout:i,error:!o&&!i}),t}))}}),j.apply({ruleProvider:()=>k(),mappingProvider:e=>{try{return d(new URL(e.url,window.location.origin).pathname,e.method)}catch{return null}},onRuleMatch:async(e,t,n,o)=>{const r=t.requestId,s=Date.now();I.addRequest("mocked",{...t,requestId:r,pending:!0,startTime:s,rule:e});const i=await H.apply(e,t),{modifiedRequest:a,type:d,redirectUrl:c}=i;"timeout"!==d&&I.addRequest("mocked",{...a,requestId:r,pending:!0,startTime:s,rule:e});let l=null;if("redirect"===d){l=Math.random().toString(36).substring(7);const e={url:c,method:a.method,headers:a.headers||{},body:a.body,requestId:l,queryParams:(()=>{try{const e="undefined"!=typeof window?window.location.origin:"http://localhost",t=new URL(c,e).searchParams;return Object.fromEntries(t.entries())}catch{return{}}})(),requestHeaders:a.headers||{},requestBody:a.body,pending:!0,startTime:Date.now()};I.addRequest("mocked",e)}const m=(e,t,o,m={})=>{const u=Date.now()-s;if(i.rule.modificationActions?.modifyResponseHeaders?.enabled){let e="string"==typeof o?Object.fromEntries(o.split("\r\n").filter((e=>e)).map((e=>e.split(": ")))):o;e=H.applyResponseModifications(e,i.rule.modificationActions),o=e}I.addRequest("mocked",{...a,requestId:r,status:e,responseBody:t,responseHeaders:o,pending:!1,duration:u,...m}),"redirect"===d&&l&&I.addRequest("mocked",{url:c,method:a.method,requestId:l,status:e,responseBody:t,responseHeaders:o,pending:!1,duration:u,requestHeaders:a.headers||{},requestBody:a.body,...m}),n._capture(e,t,o,m)};if("timeout"===d)return m("Aborted","Timed out by rule",{},{aborted:!0}),void n._xhr.abort();"redirect"===d?n._xhr.open(a.method,c,!0):a.url!==t.url&&n._xhr.open(a.method,a.url,!0),a.headers&&Object.entries(a.headers).forEach((([e,t])=>{try{n._xhr.setRequestHeader(e,t)}catch(e){}})),n._xhr.addEventListener("abort",(()=>m("Aborted","Aborted",{},{aborted:!0})),{once:!0}),n._xhr.addEventListener("error",(()=>m(0,"Error",{},{error:!0})),{once:!0}),n._xhr.addEventListener("timeout",(()=>m("Timeout","Timeout",{},{timeout:!0})),{once:!0}),n._xhr.addEventListener("load",(()=>m(n._xhr.status,n._xhr.responseText,n._xhr.getAllResponseHeaders())),{once:!0}),o(a.body)},onMockMatch:(e,o,r,s)=>{const i=o.requestId,a=Date.now(),d=n(),c=new URL(o.url,window.location.origin);let h=`${q()}${e.url}${c.search}`,f={[u]:d,[m]:p,"x-mfm-adaptor":t};const g=E();g&&e._ack&&(f["x-mfm-key"]=`${g}-${e._ack}`),e?._ri_&&(f._ri_=e._ri_);const y={...o.headers,...f};I.addRequest("mocked",{...o,requestId:i,pending:!0,startTime:a});const b=(e,t,n,s={})=>{const d=Date.now()-a;I.addRequest("mocked",{...o,requestId:i,status:e,responseBody:t,responseHeaders:n,pending:!1,duration:d,...s}),r._capture(e,t,n,s)};if(r._xhr.addEventListener("abort",(()=>b("Aborted","Aborted",{},{aborted:!0})),{once:!0}),r._xhr.addEventListener("error",(()=>b(0,"Error",{},{error:!0})),{once:!0}),r._xhr.addEventListener("timeout",(()=>b("Timeout","Timeout",{},{timeout:!0})),{once:!0}),t===l)(({actualUrl:e,url:t,method:n,headers:o,body:r,onSuccess:s,onError:i,rule:a})=>{const d=`${Date.now()}-${Math.random()}`,c=R(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:o,headers:r}=n.response;s?.({body:t,status:o,headers:r})}})),window.postMessage({type:"REQUEST_INTERCEPTED",requestId:d,payload:{actualUrl:e,url:c,method:n,headers:o,body:r,credentials:"same-origin",mode:"cors",rule:a}},"*")})({actualUrl:o.url,url:h,method:o.method,headers:y,body:o.body,onSuccess:({body:e,status:t,headers:n})=>b(t,e,n||{}),onError:e=>b(0,e.message||"XHR Error",{},{error:!0})});else{const e=new window.XMLHttpRequest;e.open(o.method,h,!0);for(const t in y)e.setRequestHeader(t,y[t]);e.withCredentials=r.proxy.withCredentials,e.onload=()=>b(e.status,e.responseText,e.getAllResponseHeaders()),e.onerror=()=>b(0,"Network Error",{},{error:!0}),e.ontimeout=()=>b("Timeout","Request timed out",{},{timeout:!0}),e.send(o.body)}},onOtherRequest:(e,t,n)=>{if("OPTIONS"===e.method)return n(e.body);const o=Date.now();I.addRequest("other",{...e,pending:!0,startTime:o});const r=(n,r,s,i={})=>{const a=Date.now()-o;I.addRequest("other",{...e,status:n,responseBody:r,responseHeaders:s,pending:!1,duration:a,...i}),t._capture(n,r,s,i)};t._xhr.addEventListener("abort",(()=>r("Aborted","Aborted",{},{aborted:!0})),{once:!0}),t._xhr.addEventListener("error",(()=>r(0,"Error",{},{error:!0})),{once:!0}),t._xhr.addEventListener("timeout",(()=>r("Timeout","Timeout",{},{timeout:!0})),{once:!0}),t._xhr.addEventListener("load",(()=>r(t._xhr.status,t._xhr.responseText,t._xhr.getAllResponseHeaders())),{once:!0}),n(e.body)}})}(r,o),f&&y?(I.mappings=h,I.rules=x,e?.(h,{_o:f,mk:y,_mck:b,_rules:x})):r&&function(t,n,o,r){S({method:"get",url:g,async:!1,headers:{[u]:t,[m]:p,"x-mfm-adaptor":n}},(t=>{if(t)try{const{di:r,iv:s,_o:a,_mck:d,mk:c,r:l}=t,m=_({di:r,iv:s},a);v({_o:a,mk:c,_mck:d,_rules:l}),m&&(i(m),n=m,o={_o:a,mk:c,_mck:d,_rules:l},I.updateMappings(n,o),e?.(n,o))}catch(e){return void r(new Error("Unable to fetch mocked apis"))}var n,o}),(e=>{console.log("Error in loading mocked apis"),r(e)})).request()}(r,o,0,t)},checkIfApiToBeMocked:d,getMappings:a,doFetchMappings:(e,t)=>{T(r||I.token,o,((t,n)=>{I.updateMappings(t,n),e?.(t,n)}),t)},recheckWidgetVisibility:()=>{I.init()}}},P=n();P||(globalThis.mockforme=B);let N=B;P&&(N=e=>({run:()=>{}}));const D=N;return t.mockforme})()));
|
package/dist/mockforme.d.ts
CHANGED
|
@@ -7,28 +7,47 @@ declare namespace mockforme {
|
|
|
7
7
|
* Initialize mockforme.
|
|
8
8
|
*
|
|
9
9
|
* @param token - Optional on client side (managed by widget), required for Node/SSR.
|
|
10
|
-
* @
|
|
10
|
+
* @param options - Optional configuration object with mappings and rules
|
|
11
|
+
* @param adaptor - Optional adaptor type (e.g., 'JAVASCRIPT', 'CHROME_EXTENSION')
|
|
12
|
+
* @returns An object with methods to start mock API interception.
|
|
11
13
|
*
|
|
12
14
|
* @example
|
|
13
|
-
*
|
|
15
|
+
* // Client-side usage
|
|
16
|
+
* mockforme("ACCESS_TOKEN").run((apis, meta) => {
|
|
14
17
|
* console.log("Available APIs for mock:", apis);
|
|
18
|
+
* console.log("Rules:", meta._rules);
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* // Server-side usage
|
|
23
|
+
* import { mockforme } from 'mockforme';
|
|
24
|
+
* mockforme("ACCESS_TOKEN").run((apis, meta) => {
|
|
25
|
+
* console.log("Server interceptors ready");
|
|
15
26
|
* });
|
|
16
27
|
*/
|
|
17
28
|
function mockforme(token?: string, options?: {
|
|
18
|
-
mappings
|
|
19
|
-
_o
|
|
20
|
-
mk
|
|
21
|
-
_mck
|
|
22
|
-
_rules
|
|
29
|
+
mappings?: any[];
|
|
30
|
+
_o?: string;
|
|
31
|
+
mk?: string;
|
|
32
|
+
_mck?: string;
|
|
33
|
+
_rules?: any[];
|
|
23
34
|
}, adaptor?: string): MockForMe;
|
|
24
35
|
|
|
25
36
|
interface MockForMe {
|
|
26
37
|
/**
|
|
27
38
|
* Starts intercepting and loading mockable APIs.
|
|
28
39
|
*
|
|
29
|
-
* @param callback - Optional. Called with the list of available APIs once loaded.
|
|
40
|
+
* @param callback - Optional. Called with the list of available APIs and metadata once loaded.
|
|
41
|
+
* @param errorCallback - Optional. Called if there's an error loading the APIs.
|
|
42
|
+
*/
|
|
43
|
+
run(callback?: (apis: any[], meta: { _rules?: any[] }) => void, errorCallback?: (err: Error) => void): void;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Fetches the API mappings from the server.
|
|
47
|
+
*
|
|
48
|
+
* @param successCallback - Optional. Called with the response and metadata on success.
|
|
49
|
+
* @param errorCallback - Optional. Called if there's an error fetching mappings.
|
|
30
50
|
*/
|
|
31
|
-
run(callback?: (apis: [], { _rules: [] }) => void, errorCallback?: (err: Error) => void): void;
|
|
32
51
|
doFetchMappings(successCallback?: (res: any, meta: any) => void, errorCallback?: (err: Error) => void): void;
|
|
33
52
|
}
|
|
34
53
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(()=>{var e={56:e=>{"use strict";e.exports=JSON.parse('{"name":"dotenv","version":"16.5.0","description":"Loads environment variables from .env file","main":"lib/main.js","types":"lib/main.d.ts","exports":{".":{"types":"./lib/main.d.ts","require":"./lib/main.js","default":"./lib/main.js"},"./config":"./config.js","./config.js":"./config.js","./lib/env-options":"./lib/env-options.js","./lib/env-options.js":"./lib/env-options.js","./lib/cli-options":"./lib/cli-options.js","./lib/cli-options.js":"./lib/cli-options.js","./package.json":"./package.json"},"scripts":{"dts-check":"tsc --project tests/types/tsconfig.json","lint":"standard","pretest":"npm run lint && npm run dts-check","test":"tap run --allow-empty-coverage --disable-coverage --timeout=60000","test:coverage":"tap run --show-full-coverage --timeout=60000 --coverage-report=lcov","prerelease":"npm test","release":"standard-version"},"repository":{"type":"git","url":"git://github.com/motdotla/dotenv.git"},"homepage":"https://github.com/motdotla/dotenv#readme","funding":"https://dotenvx.com","keywords":["dotenv","env",".env","environment","variables","config","settings"],"readmeFilename":"README.md","license":"BSD-2-Clause","devDependencies":{"@types/node":"^18.11.3","decache":"^4.6.2","sinon":"^14.0.1","standard":"^17.0.0","standard-version":"^9.5.0","tap":"^19.2.0","typescript":"^4.8.4"},"engines":{"node":">=12"},"browser":{"fs":false}}')},857:e=>{"use strict";e.exports=require("os")},896:e=>{"use strict";e.exports=require("fs")},928:e=>{"use strict";e.exports=require("path")},982:e=>{"use strict";e.exports=require("crypto")},998:(e,t,r)=>{const n=r(896),o=r(928),s=r(857),i=r(982),a=r(56).version,c=/(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/gm;function l(e){console.log(`[dotenv@${a}][DEBUG] ${e}`)}function p(e){return e&&e.DOTENV_KEY&&e.DOTENV_KEY.length>0?e.DOTENV_KEY:process.env.DOTENV_KEY&&process.env.DOTENV_KEY.length>0?process.env.DOTENV_KEY:""}function u(e,t){let r;try{r=new URL(t)}catch(e){if("ERR_INVALID_URL"===e.code){const e=new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development");throw e.code="INVALID_DOTENV_KEY",e}throw e}const n=r.password;if(!n){const e=new Error("INVALID_DOTENV_KEY: Missing key part");throw e.code="INVALID_DOTENV_KEY",e}const o=r.searchParams.get("environment");if(!o){const e=new Error("INVALID_DOTENV_KEY: Missing environment part");throw e.code="INVALID_DOTENV_KEY",e}const s=`DOTENV_VAULT_${o.toUpperCase()}`,i=e.parsed[s];if(!i){const e=new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${s} in your .env.vault file.`);throw e.code="NOT_FOUND_DOTENV_ENVIRONMENT",e}return{ciphertext:i,key:n}}function h(e){let t=null;if(e&&e.path&&e.path.length>0)if(Array.isArray(e.path))for(const r of e.path)n.existsSync(r)&&(t=r.endsWith(".vault")?r:`${r}.vault`);else t=e.path.endsWith(".vault")?e.path:`${e.path}.vault`;else t=o.resolve(process.cwd(),".env.vault");return n.existsSync(t)?t:null}function d(e){return"~"===e[0]?o.join(s.homedir(),e.slice(1)):e}const f={configDotenv:function(e){const t=o.resolve(process.cwd(),".env");let r="utf8";const s=Boolean(e&&e.debug);e&&e.encoding?r=e.encoding:s&&l("No encoding is specified. UTF-8 is used by default");let i,a=[t];if(e&&e.path)if(Array.isArray(e.path)){a=[];for(const t of e.path)a.push(d(t))}else a=[d(e.path)];const c={};for(const t of a)try{const o=f.parse(n.readFileSync(t,{encoding:r}));f.populate(c,o,e)}catch(e){s&&l(`Failed to load ${t} ${e.message}`),i=e}let p=process.env;return e&&null!=e.processEnv&&(p=e.processEnv),f.populate(p,c,e),i?{parsed:c,error:i}:{parsed:c}},_configVault:function(e){Boolean(e&&e.debug)&&l("Loading env from encrypted .env.vault");const t=f._parseVault(e);let r=process.env;return e&&null!=e.processEnv&&(r=e.processEnv),f.populate(r,t,e),{parsed:t}},_parseVault:function(e){const t=h(e),r=f.configDotenv({path:t});if(!r.parsed){const e=new Error(`MISSING_DATA: Cannot parse ${t} for an unknown reason`);throw e.code="MISSING_DATA",e}const n=p(e).split(","),o=n.length;let s;for(let e=0;e<o;e++)try{const t=u(r,n[e].trim());s=f.decrypt(t.ciphertext,t.key);break}catch(t){if(e+1>=o)throw t}return f.parse(s)},config:function(e){if(0===p(e).length)return f.configDotenv(e);const t=h(e);return t?f._configVault(e):(r=`You set DOTENV_KEY but you are missing a .env.vault file at ${t}. Did you forget to build it?`,console.log(`[dotenv@${a}][WARN] ${r}`),f.configDotenv(e));var r},decrypt:function(e,t){const r=Buffer.from(t.slice(-64),"hex");let n=Buffer.from(e,"base64");const o=n.subarray(0,12),s=n.subarray(-16);n=n.subarray(12,-16);try{const e=i.createDecipheriv("aes-256-gcm",r,o);return e.setAuthTag(s),`${e.update(n)}${e.final()}`}catch(e){const t=e instanceof RangeError,r="Invalid key length"===e.message,n="Unsupported state or unable to authenticate data"===e.message;if(t||r){const e=new Error("INVALID_DOTENV_KEY: It must be 64 characters long (or more)");throw e.code="INVALID_DOTENV_KEY",e}if(n){const e=new Error("DECRYPTION_FAILED: Please check your DOTENV_KEY");throw e.code="DECRYPTION_FAILED",e}throw e}},parse:function(e){const t={};let r,n=e.toString();for(n=n.replace(/\r\n?/gm,"\n");null!=(r=c.exec(n));){const e=r[1];let n=r[2]||"";n=n.trim();const o=n[0];n=n.replace(/^(['"`])([\s\S]*)\1$/gm,"$2"),'"'===o&&(n=n.replace(/\\n/g,"\n"),n=n.replace(/\\r/g,"\r")),t[e]=n}return t},populate:function(e,t,r={}){const n=Boolean(r&&r.debug),o=Boolean(r&&r.override);if("object"!=typeof t){const e=new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");throw e.code="OBJECT_REQUIRED",e}for(const r of Object.keys(t))Object.prototype.hasOwnProperty.call(e,r)?(!0===o&&(e[r]=t[r]),n&&l(!0===o?`"${r}" is already defined and WAS overwritten`:`"${r}" is already defined and was NOT overwritten`)):e[r]=t[r]}};e.exports.configDotenv=f.configDotenv,e.exports._configVault=f._configVault,e.exports._parseVault=f._parseVault,e.exports.config=f.config,e.exports.decrypt=f.decrypt,e.exports.parse=f.parse,e.exports.populate=f.populate,e.exports=f}},t={};function r(n){var o=t[n];if(void 0!==o)return o.exports;var s=t[n]={exports:{}};return e[n](s,s.exports,r),s.exports}r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},r.d=(e,t)=>{for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var n={};(()=>{"use strict";r.r(n),r.d(n,{mockforme:()=>v});const e=require("http");var t=r.n(e);const o=require("https");var s=r.n(o);const i=require("child_process");var a=r(998);const c=e=>{try{return e?e.toLowerCase():e}catch(e){return console.log(e),null}},l=(e,t)=>{const r=e.split("/"),n=t.split("/");if(r.length!==n.length)return!1;for(let e=0;e<r.length;e++){const t=r[e];if(t!==n[e]&&":any"!==t)return!1}return!0},p=(e,t=null,r=2)=>{try{return JSON.stringify(e,t,r)}catch(e){return null}};r.n(a)().config("../../.env");const u="https://api.mockforme.com",h=`${u}/mockforme`,d="mfmver",f="4.2.8";let m=`${u}/gateway/3f4eae522b`,g=null;class y{constructor(e){this.token=e,this.apiMappings=[],this.rules=[],this.isReady=!1,this.originalHttpRequest=t().request,this.originalHttpGet=t().get,this.originalHttpsRequest=s().request,this.originalHttpsGet=s().get,this.originalFetch=globalThis.fetch,this.fetchApiMappings(),this.setupInterceptor()}checkIsErrorInFetchMappings(e){try{const t=JSON.parse(e);if(0==t?.status)throw new Error(t?.message||"Failed to fetch mockforme mappings")}catch(e){throw new Error(e.message||"Failed to fetch mockforme mappings")}}fetchApiMappings(){this.apiMappings=[],this.rules=[],this.isReady=!1;try{const e=`curl -s -H "mockforme: ${this.token}" "${m}"`,t=(0,i.execSync)(e,{encoding:"utf8"});if(t&&this.checkIsErrorInFetchMappings(t),!t)throw new Error("Failed to fetch mockforme mappings: No response");{const{di:e,iv:r,_o:n,_mck:o,mk:s,r:i}=JSON.parse(t);this.organisationId=n,this.memberKey=s,this.memberCacheKey=o;const a=function({di:e,iv:t},r){var n;const o=function(e,t){const r=t.length;return e.split("").map(((e,n)=>String.fromCharCode(e.charCodeAt(0)^t.charCodeAt(n%r)))).join("")}((n=e,"undefined"!=typeof Buffer?Buffer.from(n,"base64").toString("utf8"):decodeURIComponent(escape(atob(n)))),r+t);return JSON.parse(o)}({di:e,iv:r},n);a&&(this.apiMappings=a),i&&(this.rules=i)}this.isReady=!0}catch(e){console.error("[mockforme] Failed to fetch mappings:",e.message)}}getProxyUrl(){return`${h}/${this.organisationId}/${this.memberKey}`}checkRules(e){return this.rules&&this.rules.length&&this.rules.find((t=>{const r=t.rule.URL.condition,{operator:n,value:o}=r;return"equals"===n?e.pathname===o:"contains"===n&&e.pathname.includes(o)}))||null}async applyRuleBehavior(e,t,r){if(!e)return null;const{activeAction:n,actions:o}=e.rule.URL.condition;if("delay"===n&&o.delay.value>=0)return await new Promise((e=>setTimeout(e,1e3*o.delay.value))),{type:"passThrough"};if("delay_and_redirect"===n){const{value:e,redirectUrl:t}=o.delay_and_redirect;return e>0&&await new Promise((t=>setTimeout(t,1e3*e))),{type:"redirect",redirectUrl:t}}return"delay_and_timeout"===n&&o.delay_and_timeout.value>=0&&await new Promise(((e,t)=>setTimeout((()=>t(new Error("Request timed out by rule"))),1e3*o.delay_and_timeout.value))),null}interceptFetch(e,t){const r=(t.method||"GET").toUpperCase(),n=this.apiMappings.find((t=>{const n=c(t.apiMethod)===c(r),o=t.apiEndpoint===e.pathname||l(t.apiEndpoint,e.pathname);return n&&o}));if(n){console.log("[mockforme] [api intercepted]: ",n);const r={mockforme:this.token,[d]:f},o=n?._ack||null;this.memberCacheKey&&o&&(r["x-mfm-key"]=`${this.memberCacheKey}-${o}`);let s=`${this.getProxyUrl()}${e.pathname}`;return e.search&&(s+=e.search),{url:s,init:{...t,headers:{...t.headers,...r}}}}return{url:e.href,init:t}}setupInterceptor(){const e=this;globalThis.fetch=async function(t,r={}){if(!e.isReady)return e.originalFetch(t,r);const n=t instanceof Request?new URL(t.url):new URL(t,"http://localhost"),o=e.checkRules(n);if(o){console.log("[mockforme] [fetch] [rule matched]: ",p(o));try{const t=await e.applyRuleBehavior(o,n,r);if("redirect"===t?.type)return e.originalFetch(t.redirectUrl,r);if("passThrough"===t?.type)return e.originalFetch(n.href,r)}catch(e){throw e}}const{url:s,init:i}=e.interceptFetch(n,r);try{const t=await e.originalFetch(s,i);if(!t.ok)throw new Error(`[mockforme] Proxy fetch failed: ${t.status} ${t.statusText}`);return t}catch(e){throw e}};const r=(t,r)=>async function(...n){let o=n[0];if("string"==typeof o&&(o=new URL(o)),!e.isReady)return t.apply(null,[o,...n.slice(1)]);const s=e.checkRules(o);if(s){console.log(`[mockforme] [${r}] [rule matched]: `,p(s));try{const r=await e.applyRuleBehavior(s,o,{});if("passThrough"===r?.type)return t.apply(null,[o,...n.slice(1)])}catch(e){throw e}}const i=e.interceptRequest(o);try{return t.apply(null,[i,...n.slice(1)])}catch(e){throw e}};t().request=r(this.originalHttpRequest,"http.request"),s().request=r(this.originalHttpsRequest,"https.request"),t().get=r(this.originalHttpGet,"http.get"),s().get=r(this.originalHttpsGet,"https.get")}interceptRequest(e){const t=this.apiMappings.find((t=>{if(c(t.apiMethod)===c(e.method))return t.apiEndpoint===e.path||l(t.apiEndpoint,e.path)}));if(t){console.log("[mockforme] [matched request]: ",t,e);const r={mockforme:this.token,[d]:f},n=t?._ack||null;this.memberCacheKey&&n&&(r["x-mfm-key"]=`${this.memberCacheKey}-${n}`);let o=`${this.getProxyUrl()}${e.path}`;e.search&&(o+=e.search);const s=new URL(o);return{...e,hostname:s.hostname,path:s.pathname,headers:{...e.headers,...r}}}return e}run(e){e&&e(this.apiMappings,{_rules:this.rules})}}function v(e){return g?(g.token=e,g.fetchApiMappings()):g=new y(e),g}})(),module.exports=n})();
|
|
1
|
+
(()=>{var e={56:e=>{"use strict";e.exports=JSON.parse('{"name":"dotenv","version":"16.5.0","description":"Loads environment variables from .env file","main":"lib/main.js","types":"lib/main.d.ts","exports":{".":{"types":"./lib/main.d.ts","require":"./lib/main.js","default":"./lib/main.js"},"./config":"./config.js","./config.js":"./config.js","./lib/env-options":"./lib/env-options.js","./lib/env-options.js":"./lib/env-options.js","./lib/cli-options":"./lib/cli-options.js","./lib/cli-options.js":"./lib/cli-options.js","./package.json":"./package.json"},"scripts":{"dts-check":"tsc --project tests/types/tsconfig.json","lint":"standard","pretest":"npm run lint && npm run dts-check","test":"tap run --allow-empty-coverage --disable-coverage --timeout=60000","test:coverage":"tap run --show-full-coverage --timeout=60000 --coverage-report=lcov","prerelease":"npm test","release":"standard-version"},"repository":{"type":"git","url":"git://github.com/motdotla/dotenv.git"},"homepage":"https://github.com/motdotla/dotenv#readme","funding":"https://dotenvx.com","keywords":["dotenv","env",".env","environment","variables","config","settings"],"readmeFilename":"README.md","license":"BSD-2-Clause","devDependencies":{"@types/node":"^18.11.3","decache":"^4.6.2","sinon":"^14.0.1","standard":"^17.0.0","standard-version":"^9.5.0","tap":"^19.2.0","typescript":"^4.8.4"},"engines":{"node":">=12"},"browser":{"fs":false}}')},857:e=>{"use strict";e.exports=require("os")},896:e=>{"use strict";e.exports=require("fs")},928:e=>{"use strict";e.exports=require("path")},982:e=>{"use strict";e.exports=require("crypto")},998:(e,t,r)=>{const o=r(896),s=r(928),n=r(857),a=r(982),i=r(56).version,c=/(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/gm;function l(e){console.log(`[dotenv@${i}][DEBUG] ${e}`)}function p(e){return e&&e.DOTENV_KEY&&e.DOTENV_KEY.length>0?e.DOTENV_KEY:process.env.DOTENV_KEY&&process.env.DOTENV_KEY.length>0?process.env.DOTENV_KEY:""}function u(e,t){let r;try{r=new URL(t)}catch(e){if("ERR_INVALID_URL"===e.code){const e=new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development");throw e.code="INVALID_DOTENV_KEY",e}throw e}const o=r.password;if(!o){const e=new Error("INVALID_DOTENV_KEY: Missing key part");throw e.code="INVALID_DOTENV_KEY",e}const s=r.searchParams.get("environment");if(!s){const e=new Error("INVALID_DOTENV_KEY: Missing environment part");throw e.code="INVALID_DOTENV_KEY",e}const n=`DOTENV_VAULT_${s.toUpperCase()}`,a=e.parsed[n];if(!a){const e=new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${n} in your .env.vault file.`);throw e.code="NOT_FOUND_DOTENV_ENVIRONMENT",e}return{ciphertext:a,key:o}}function d(e){let t=null;if(e&&e.path&&e.path.length>0)if(Array.isArray(e.path))for(const r of e.path)o.existsSync(r)&&(t=r.endsWith(".vault")?r:`${r}.vault`);else t=e.path.endsWith(".vault")?e.path:`${e.path}.vault`;else t=s.resolve(process.cwd(),".env.vault");return o.existsSync(t)?t:null}function h(e){return"~"===e[0]?s.join(n.homedir(),e.slice(1)):e}const f={configDotenv:function(e){const t=s.resolve(process.cwd(),".env");let r="utf8";const n=Boolean(e&&e.debug);e&&e.encoding?r=e.encoding:n&&l("No encoding is specified. UTF-8 is used by default");let a,i=[t];if(e&&e.path)if(Array.isArray(e.path)){i=[];for(const t of e.path)i.push(h(t))}else i=[h(e.path)];const c={};for(const t of i)try{const s=f.parse(o.readFileSync(t,{encoding:r}));f.populate(c,s,e)}catch(e){n&&l(`Failed to load ${t} ${e.message}`),a=e}let p=process.env;return e&&null!=e.processEnv&&(p=e.processEnv),f.populate(p,c,e),a?{parsed:c,error:a}:{parsed:c}},_configVault:function(e){Boolean(e&&e.debug)&&l("Loading env from encrypted .env.vault");const t=f._parseVault(e);let r=process.env;return e&&null!=e.processEnv&&(r=e.processEnv),f.populate(r,t,e),{parsed:t}},_parseVault:function(e){const t=d(e),r=f.configDotenv({path:t});if(!r.parsed){const e=new Error(`MISSING_DATA: Cannot parse ${t} for an unknown reason`);throw e.code="MISSING_DATA",e}const o=p(e).split(","),s=o.length;let n;for(let e=0;e<s;e++)try{const t=u(r,o[e].trim());n=f.decrypt(t.ciphertext,t.key);break}catch(t){if(e+1>=s)throw t}return f.parse(n)},config:function(e){if(0===p(e).length)return f.configDotenv(e);const t=d(e);return t?f._configVault(e):(r=`You set DOTENV_KEY but you are missing a .env.vault file at ${t}. Did you forget to build it?`,console.log(`[dotenv@${i}][WARN] ${r}`),f.configDotenv(e));var r},decrypt:function(e,t){const r=Buffer.from(t.slice(-64),"hex");let o=Buffer.from(e,"base64");const s=o.subarray(0,12),n=o.subarray(-16);o=o.subarray(12,-16);try{const e=a.createDecipheriv("aes-256-gcm",r,s);return e.setAuthTag(n),`${e.update(o)}${e.final()}`}catch(e){const t=e instanceof RangeError,r="Invalid key length"===e.message,o="Unsupported state or unable to authenticate data"===e.message;if(t||r){const e=new Error("INVALID_DOTENV_KEY: It must be 64 characters long (or more)");throw e.code="INVALID_DOTENV_KEY",e}if(o){const e=new Error("DECRYPTION_FAILED: Please check your DOTENV_KEY");throw e.code="DECRYPTION_FAILED",e}throw e}},parse:function(e){const t={};let r,o=e.toString();for(o=o.replace(/\r\n?/gm,"\n");null!=(r=c.exec(o));){const e=r[1];let o=r[2]||"";o=o.trim();const s=o[0];o=o.replace(/^(['"`])([\s\S]*)\1$/gm,"$2"),'"'===s&&(o=o.replace(/\\n/g,"\n"),o=o.replace(/\\r/g,"\r")),t[e]=o}return t},populate:function(e,t,r={}){const o=Boolean(r&&r.debug),s=Boolean(r&&r.override);if("object"!=typeof t){const e=new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");throw e.code="OBJECT_REQUIRED",e}for(const r of Object.keys(t))Object.prototype.hasOwnProperty.call(e,r)?(!0===s&&(e[r]=t[r]),o&&l(!0===s?`"${r}" is already defined and WAS overwritten`:`"${r}" is already defined and was NOT overwritten`)):e[r]=t[r]}};e.exports.configDotenv=f.configDotenv,e.exports._configVault=f._configVault,e.exports._parseVault=f._parseVault,e.exports.config=f.config,e.exports.decrypt=f.decrypt,e.exports.parse=f.parse,e.exports.populate=f.populate,e.exports=f}},t={};function r(o){var s=t[o];if(void 0!==s)return s.exports;var n=t[o]={exports:{}};return e[o](n,n.exports,r),n.exports}r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},r.d=(e,t)=>{for(var o in t)r.o(t,o)&&!r.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var o={};(()=>{"use strict";r.r(o),r.d(o,{mockforme:()=>k});const e=require("http");var t=r.n(e);const s=require("https");var n=r.n(s);const a=require("child_process");var i=r(998),c=r.n(i);const l=e=>{try{return e?e.toLowerCase():e}catch(e){return console.log(e),null}},p=(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},u=(e,t=null,r=2)=>{try{return JSON.stringify(e,t,r)}catch(e){return null}};class d{static match(e,t){if(!Array.isArray(t)||0===t.length)return!1;const{url:r,headers:o,queryParams:s,body:n}=e,a="undefined"!=typeof window?window.location.origin:globalThis.location?.origin||"http://localhost";for(const e of t){let t="";const{type:i,key:c,operator:l,value:p}=e;switch(i){case"URL":try{t=new URL(r,a).pathname}catch{t=r}break;case"QUERY_PARAM":if(s&&void 0!==s[c])t=String(s[c]);else try{t=new URL(r,a).searchParams.get(c)||""}catch{t=""}break;case"REQUEST_BODY":if(c){if("object"==typeof n&&null!==n)t=void 0!==n[c]?String(n[c]):"";else if("string"==typeof n)try{const e=JSON.parse(n);t=void 0!==e[c]?String(e[c]):""}catch{t=""}}else t="object"==typeof n?JSON.stringify(n):String(n||"");break;case"REQUEST_HEADER":if(c){const e=c?.toLowerCase();if(t="",o){const r=Object.keys(o).find((t=>t.toLowerCase()===e));t=r?String(o[r]):""}}else t=JSON.stringify(o||{});break;default:return!1}if(!this.evaluate(t,l,p))return!1}return!0}static evaluate(e,t,r){const o=t?.toLowerCase(),s=String(e),n=String(r);switch(o){case"contains":return s.includes(n);case"equal":case"equals":return s===n;case"regexp":try{let e=n;if(e.startsWith("/")&&e.lastIndexOf("/")>0){const t=e.lastIndexOf("/"),r=e.slice(1,t),o=e.slice(t+1);return new RegExp(r,o).test(s)}return new RegExp(e).test(s)}catch{return!1}default:return!1}}}class h{static async apply(e){if(!e||!e.activeAction)return{type:"passThrough",delay:0};const{activeAction:t,actions:r}=e,o=r?.[t];if(!o)return{type:"passThrough",delay:0};const s={type:"passThrough",delay:0},n=Number(o.value||0);switch(t){case"delay":s.delay=n,s.delay>0&&await new Promise((e=>setTimeout(e,1e3*s.delay)));break;case"delay_and_redirect":s.type="redirect",s.delay=n,s.redirectUrl=o.redirectUrl,s.delay>0&&await new Promise((e=>setTimeout(e,1e3*s.delay)));break;case"delay_and_timeout":s.type="timeout",s.delay=n,s.delay>0&&await new Promise((e=>setTimeout(e,1e3*s.delay)))}return s}}class f{static applyRequestModifications(e,t){if(!t)return e;let{url:r,headers:o,queryParams:s,body:n}={...e};o&&(o={...o}),s&&(s={...s});const{modifyQueryParams:a,modifyRequestBody:i,modifyRequestHeaders:c}=t;if(a?.enabled)try{const e=new URL(r,"undefined"!=typeof window?window.location.href:"http://localhost");Array.isArray(a.remove)&&a.remove.forEach((t=>{e.searchParams.delete(t),s&&delete s[t]})),Array.isArray(a.add)&&a.add.forEach((({key:t,value:r})=>{e.searchParams.set(t,r),s&&(s[t]=r)})),r=e.toString()}catch(e){console.error("[MockForMe] Failed to modify query params",e)}if(c?.enabled&&(o={...o},Array.isArray(c.remove)&&c.remove.forEach((e=>{const t=e.toLowerCase(),r=Object.keys(o).find((e=>e.toLowerCase()===t));r&&delete o[r]})),Array.isArray(c.add)&&c.add.forEach((({key:e,value:t})=>{o[e]=t}))),i?.enabled)try{let t=null;if("string"==typeof n)try{t=JSON.parse(n)}catch{}else if("object"==typeof n&&null!==n)try{t=JSON.parse(JSON.stringify(n))}catch{t={...n}}t&&(Array.isArray(i.remove)&&i.remove.forEach((e=>delete t[e])),Array.isArray(i.add)&&i.add.forEach((({key:e,value:r})=>t[e]=r)),Array.isArray(i.update)&&i.update.forEach((({key:e,value:r})=>t[e]=r)),n="string"==typeof e.body?JSON.stringify(t):t)}catch(e){console.error("[MockForMe] Failed to modify request body",e)}return{...e,url:r,headers:o,queryParams:s,body:n}}static applyResponseModifications(e,t){if(!t?.modifyResponseHeaders?.enabled)return e;const{modifyResponseHeaders:r}=t,o={...e};return Array.isArray(r.remove)&&r.remove.forEach((e=>{const t=e.toLowerCase(),r=Object.keys(o).find((e=>e.toLowerCase()===t));r&&delete o[r]})),Array.isArray(r.add)&&r.add.forEach((({key:e,value:t})=>{o[e]=t})),o}}class y{static match(e,t){if(!Array.isArray(t)||0===t.length)return null;for(const r of t){const t=r.rule||r;if(t.conditions&&Array.isArray(t.conditions)&&d.match(e,t.conditions)){const e=t.timingAction?.activeAction||"";return{action:e,config:t.timingAction?.actions?.[e]||{},rule:t}}}return null}static async apply(e,t){if(!e)return null;const r=e.rule||e,o=f.applyRequestModifications(t,r.modificationActions);return{...await h.apply(r.timingAction),modifiedRequest:o,rule:r}}static applyResponseModifications(e,t){return f.applyResponseModifications(e,t)}}c().config("../../.env");const m="https://api.mockforme.com",g=`${m}/mockforme`,v="mfmver",E="4.2.7";let w=`${m}/gateway/3f4eae522b`,b=null;class _{constructor(e){this.token=e,this.apiMappings=[],this.rules=[],this.isReady=!1,this.originalHttpRequest=t().request,this.originalHttpGet=t().get,this.originalHttpsRequest=n().request,this.originalHttpsGet=n().get,this.originalFetch=globalThis.fetch,this.fetchApiMappings(),this.setupInterceptor()}checkIsErrorInFetchMappings(e){try{const t=JSON.parse(e);if(0==t?.status)throw new Error(t?.message||"Failed to fetch mockforme mappings")}catch(e){throw new Error(e.message||"Failed to fetch mockforme mappings")}}fetchApiMappings(){this.apiMappings=[],this.rules=[],this.isReady=!1;try{const e=`curl -s -H "mockforme: ${this.token}" "${w}"`,t=(0,a.execSync)(e,{encoding:"utf8"});if(t&&this.checkIsErrorInFetchMappings(t),!t)throw new Error("Failed to fetch mockforme mappings: No response");{const{di:e,iv:r,_o:o,_mck:s,mk:n,r:a}=JSON.parse(t);this.organisationId=o,this.memberKey=n,this.memberCacheKey=s;const i=function({di:e,iv:t},r){var o;const s=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(s)}({di:e,iv:r},o);i&&(this.apiMappings=i),a&&(this.rules=a)}this.isReady=!0}catch(e){console.error("[mockforme] Failed to fetch mappings:",e.message)}}getProxyUrl(){return`${g}/${this.organisationId}/${this.memberKey}`}checkRules(e){return y.match(e,this.rules)}async applyRuleBehavior(e,t){return await y.apply(e,t)}interceptFetch(e,t){const r=(t.method||"GET").toUpperCase(),o=this.apiMappings.find((t=>{const o=l(t.apiMethod)===l(r),s=t.apiEndpoint===e.pathname||p(t.apiEndpoint,e.pathname);return o&&s}));if(o){console.log("[mockforme] [api intercepted]: ",o);const r={mockforme:this.token,[v]:E},s=o?._ack||null;this.memberCacheKey&&s&&(r["x-mfm-key"]=`${this.memberCacheKey}-${s}`);let n=`${this.getProxyUrl()}${e.pathname}`;return e.search&&(n+=e.search),{url:n,init:{...t,headers:{...t.headers,...r}}}}return{url:e.href,init:t}}setupInterceptor(){const e=this;globalThis.fetch=async function(t,r={}){if(!e.isReady)return e.originalFetch(t,r);const o=t instanceof Request?new URL(t.url):new URL(t,"http://localhost"),s={url:o.href,method:(r.method||"GET").toUpperCase(),headers:r.headers||{},queryParams:Object.fromEntries(o.searchParams.entries())},n=e.checkRules(s);if(n){console.log("[mockforme] [fetch] [rule matched]: ",u(n));try{const t=await e.applyRuleBehavior(n,s),{modifiedRequest:o,type:a,redirectUrl:i}=t;return"redirect"===a?e.originalFetch(i,{...r,method:o.method,headers:o.headers,body:o.body}):e.originalFetch(o.url,{...r,method:o.method,headers:o.headers,body:o.body})}catch(e){throw e}}const{url:a,init:i}=e.interceptFetch(o,r);try{const t=await e.originalFetch(a,i);if(!t.ok)throw new Error(`[mockforme] Proxy fetch failed: ${t.status} ${t.statusText}`);return t}catch(e){throw e}};const r=(t,r)=>async function(...o){let s=o[0];if("string"==typeof s&&(s=new URL(s)),!e.isReady)return t.apply(null,[s,...o.slice(1)]);const n={url:s.href||s.url||`http://${s.hostname}${s.path}`,method:(s.method||"GET").toUpperCase(),headers:s.headers||{}},a=e.checkRules(n);if(a){console.log(`[mockforme] [${r}] [rule matched]: `,u(a));try{const r=await e.applyRuleBehavior(a,n),{modifiedRequest:i,type:c,redirectUrl:l}=r;if("passThrough"===c){const e={...s};try{const t=new URL(i.url);e.hostname=t.hostname,e.path=t.pathname+t.search,e.port=t.port,e.protocol=t.protocol}catch(e){}return i.headers&&(e.headers=i.headers),i.method&&(e.method=i.method),t.apply(null,[e,...o.slice(1)])}}catch(e){throw e}}const i=e.interceptRequest(s);try{return t.apply(null,[i,...o.slice(1)])}catch(e){throw e}};t().request=r(this.originalHttpRequest,"http.request"),n().request=r(this.originalHttpsRequest,"https.request"),t().get=r(this.originalHttpGet,"http.get"),n().get=r(this.originalHttpsGet,"https.get")}interceptRequest(e){const t=this.apiMappings.find((t=>{if(l(t.apiMethod)===l(e.method))return t.apiEndpoint===e.path||p(t.apiEndpoint,e.path)}));if(t){console.log("[mockforme] [matched request]: ",t,e);const r={mockforme:this.token,[v]:E},o=t?._ack||null;this.memberCacheKey&&o&&(r["x-mfm-key"]=`${this.memberCacheKey}-${o}`);let s=`${this.getProxyUrl()}${e.path}`;e.search&&(s+=e.search);const n=new URL(s);return{...e,hostname:n.hostname,path:n.pathname,headers:{...e.headers,...r}}}return e}run(e){e&&e(this.apiMappings,{_rules:this.rules})}}function k(e){return b?(b.token=e,b.fetchApiMappings()):b=new _(e),b}})(),module.exports=o})();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createRequire as e}from"node:module";var t={56:e=>{e.exports=JSON.parse('{"name":"dotenv","version":"16.5.0","description":"Loads environment variables from .env file","main":"lib/main.js","types":"lib/main.d.ts","exports":{".":{"types":"./lib/main.d.ts","require":"./lib/main.js","default":"./lib/main.js"},"./config":"./config.js","./config.js":"./config.js","./lib/env-options":"./lib/env-options.js","./lib/env-options.js":"./lib/env-options.js","./lib/cli-options":"./lib/cli-options.js","./lib/cli-options.js":"./lib/cli-options.js","./package.json":"./package.json"},"scripts":{"dts-check":"tsc --project tests/types/tsconfig.json","lint":"standard","pretest":"npm run lint && npm run dts-check","test":"tap run --allow-empty-coverage --disable-coverage --timeout=60000","test:coverage":"tap run --show-full-coverage --timeout=60000 --coverage-report=lcov","prerelease":"npm test","release":"standard-version"},"repository":{"type":"git","url":"git://github.com/motdotla/dotenv.git"},"homepage":"https://github.com/motdotla/dotenv#readme","funding":"https://dotenvx.com","keywords":["dotenv","env",".env","environment","variables","config","settings"],"readmeFilename":"README.md","license":"BSD-2-Clause","devDependencies":{"@types/node":"^18.11.3","decache":"^4.6.2","sinon":"^14.0.1","standard":"^17.0.0","standard-version":"^9.5.0","tap":"^19.2.0","typescript":"^4.8.4"},"engines":{"node":">=12"},"browser":{"fs":false}}')},857:t=>{t.exports=e(import.meta.url)("os")},896:t=>{t.exports=e(import.meta.url)("fs")},928:t=>{t.exports=e(import.meta.url)("path")},982:t=>{t.exports=e(import.meta.url)("crypto")},998:(e,t,r)=>{const o=r(896),n=r(928),s=r(857),i=r(982),a=r(56).version,c=/(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/gm;function p(e){console.log(`[dotenv@${a}][DEBUG] ${e}`)}function l(e){return e&&e.DOTENV_KEY&&e.DOTENV_KEY.length>0?e.DOTENV_KEY:process.env.DOTENV_KEY&&process.env.DOTENV_KEY.length>0?process.env.DOTENV_KEY:""}function u(e,t){let r;try{r=new URL(t)}catch(e){if("ERR_INVALID_URL"===e.code){const e=new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development");throw e.code="INVALID_DOTENV_KEY",e}throw e}const o=r.password;if(!o){const e=new Error("INVALID_DOTENV_KEY: Missing key part");throw e.code="INVALID_DOTENV_KEY",e}const n=r.searchParams.get("environment");if(!n){const e=new Error("INVALID_DOTENV_KEY: Missing environment part");throw e.code="INVALID_DOTENV_KEY",e}const s=`DOTENV_VAULT_${n.toUpperCase()}`,i=e.parsed[s];if(!i){const e=new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${s} in your .env.vault file.`);throw e.code="NOT_FOUND_DOTENV_ENVIRONMENT",e}return{ciphertext:i,key:o}}function h(e){let t=null;if(e&&e.path&&e.path.length>0)if(Array.isArray(e.path))for(const r of e.path)o.existsSync(r)&&(t=r.endsWith(".vault")?r:`${r}.vault`);else t=e.path.endsWith(".vault")?e.path:`${e.path}.vault`;else t=n.resolve(process.cwd(),".env.vault");return o.existsSync(t)?t:null}function d(e){return"~"===e[0]?n.join(s.homedir(),e.slice(1)):e}const f={configDotenv:function(e){const t=n.resolve(process.cwd(),".env");let r="utf8";const s=Boolean(e&&e.debug);e&&e.encoding?r=e.encoding:s&&p("No encoding is specified. UTF-8 is used by default");let i,a=[t];if(e&&e.path)if(Array.isArray(e.path)){a=[];for(const t of e.path)a.push(d(t))}else a=[d(e.path)];const c={};for(const t of a)try{const n=f.parse(o.readFileSync(t,{encoding:r}));f.populate(c,n,e)}catch(e){s&&p(`Failed to load ${t} ${e.message}`),i=e}let l=process.env;return e&&null!=e.processEnv&&(l=e.processEnv),f.populate(l,c,e),i?{parsed:c,error:i}:{parsed:c}},_configVault:function(e){Boolean(e&&e.debug)&&p("Loading env from encrypted .env.vault");const t=f._parseVault(e);let r=process.env;return e&&null!=e.processEnv&&(r=e.processEnv),f.populate(r,t,e),{parsed:t}},_parseVault:function(e){const t=h(e),r=f.configDotenv({path:t});if(!r.parsed){const e=new Error(`MISSING_DATA: Cannot parse ${t} for an unknown reason`);throw e.code="MISSING_DATA",e}const o=l(e).split(","),n=o.length;let s;for(let e=0;e<n;e++)try{const t=u(r,o[e].trim());s=f.decrypt(t.ciphertext,t.key);break}catch(t){if(e+1>=n)throw t}return f.parse(s)},config:function(e){if(0===l(e).length)return f.configDotenv(e);const t=h(e);return t?f._configVault(e):(r=`You set DOTENV_KEY but you are missing a .env.vault file at ${t}. Did you forget to build it?`,console.log(`[dotenv@${a}][WARN] ${r}`),f.configDotenv(e));var r},decrypt:function(e,t){const r=Buffer.from(t.slice(-64),"hex");let o=Buffer.from(e,"base64");const n=o.subarray(0,12),s=o.subarray(-16);o=o.subarray(12,-16);try{const e=i.createDecipheriv("aes-256-gcm",r,n);return e.setAuthTag(s),`${e.update(o)}${e.final()}`}catch(e){const t=e instanceof RangeError,r="Invalid key length"===e.message,o="Unsupported state or unable to authenticate data"===e.message;if(t||r){const e=new Error("INVALID_DOTENV_KEY: It must be 64 characters long (or more)");throw e.code="INVALID_DOTENV_KEY",e}if(o){const e=new Error("DECRYPTION_FAILED: Please check your DOTENV_KEY");throw e.code="DECRYPTION_FAILED",e}throw e}},parse:function(e){const t={};let r,o=e.toString();for(o=o.replace(/\r\n?/gm,"\n");null!=(r=c.exec(o));){const e=r[1];let o=r[2]||"";o=o.trim();const n=o[0];o=o.replace(/^(['"`])([\s\S]*)\1$/gm,"$2"),'"'===n&&(o=o.replace(/\\n/g,"\n"),o=o.replace(/\\r/g,"\r")),t[e]=o}return t},populate:function(e,t,r={}){const o=Boolean(r&&r.debug),n=Boolean(r&&r.override);if("object"!=typeof t){const e=new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");throw e.code="OBJECT_REQUIRED",e}for(const r of Object.keys(t))Object.prototype.hasOwnProperty.call(e,r)?(!0===n&&(e[r]=t[r]),o&&p(!0===n?`"${r}" is already defined and WAS overwritten`:`"${r}" is already defined and was NOT overwritten`)):e[r]=t[r]}};e.exports.configDotenv=f.configDotenv,e.exports._configVault=f._configVault,e.exports._parseVault=f._parseVault,e.exports.config=f.config,e.exports.decrypt=f.decrypt,e.exports.parse=f.parse,e.exports.populate=f.populate,e.exports=f}},r={};function o(e){var n=r[e];if(void 0!==n)return n.exports;var s=r[e]={exports:{}};return t[e](s,s.exports,o),s.exports}o.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return o.d(t,{a:t}),t},o.d=(e,t)=>{for(var r in t)o.o(t,r)&&!o.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);const n=e(import.meta.url)("http");var s=o.n(n);const i=e(import.meta.url)("https");var a=o.n(i);const c=e(import.meta.url)("child_process");var p=o(998);const l=e=>{try{return e?e.toLowerCase():e}catch(e){return console.log(e),null}},u=(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},h=(e,t=null,r=2)=>{try{return JSON.stringify(e,t,r)}catch(e){return null}};o.n(p)().config("../../.env");const d="https://api.mockforme.com",f=`${d}/mockforme`,m="mfmver",g="4.2.8";let v=`${d}/gateway/3f4eae522b`,y=null;class E{constructor(e){this.token=e,this.apiMappings=[],this.rules=[],this.isReady=!1,this.originalHttpRequest=s().request,this.originalHttpGet=s().get,this.originalHttpsRequest=a().request,this.originalHttpsGet=a().get,this.originalFetch=globalThis.fetch,this.fetchApiMappings(),this.setupInterceptor()}checkIsErrorInFetchMappings(e){try{const t=JSON.parse(e);if(0==t?.status)throw new Error(t?.message||"Failed to fetch mockforme mappings")}catch(e){throw new Error(e.message||"Failed to fetch mockforme mappings")}}fetchApiMappings(){this.apiMappings=[],this.rules=[],this.isReady=!1;try{const e=`curl -s -H "mockforme: ${this.token}" "${v}"`,t=(0,c.execSync)(e,{encoding:"utf8"});if(t&&this.checkIsErrorInFetchMappings(t),!t)throw new Error("Failed to fetch mockforme mappings: No response");{const{di:e,iv:r,_o:o,_mck:n,mk:s,r:i}=JSON.parse(t);this.organisationId=o,this.memberKey=s,this.memberCacheKey=n;const a=function({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)}({di:e,iv:r},o);a&&(this.apiMappings=a),i&&(this.rules=i)}this.isReady=!0}catch(e){console.error("[mockforme] Failed to fetch mappings:",e.message)}}getProxyUrl(){return`${f}/${this.organisationId}/${this.memberKey}`}checkRules(e){return this.rules&&this.rules.length&&this.rules.find((t=>{const r=t.rule.URL.condition,{operator:o,value:n}=r;return"equals"===o?e.pathname===n:"contains"===o&&e.pathname.includes(n)}))||null}async applyRuleBehavior(e,t,r){if(!e)return null;const{activeAction:o,actions:n}=e.rule.URL.condition;if("delay"===o&&n.delay.value>=0)return await new Promise((e=>setTimeout(e,1e3*n.delay.value))),{type:"passThrough"};if("delay_and_redirect"===o){const{value:e,redirectUrl:t}=n.delay_and_redirect;return e>0&&await new Promise((t=>setTimeout(t,1e3*e))),{type:"redirect",redirectUrl:t}}return"delay_and_timeout"===o&&n.delay_and_timeout.value>=0&&await new Promise(((e,t)=>setTimeout((()=>t(new Error("Request timed out by rule"))),1e3*n.delay_and_timeout.value))),null}interceptFetch(e,t){const r=(t.method||"GET").toUpperCase(),o=this.apiMappings.find((t=>{const o=l(t.apiMethod)===l(r),n=t.apiEndpoint===e.pathname||u(t.apiEndpoint,e.pathname);return o&&n}));if(o){console.log("[mockforme] [api intercepted]: ",o);const r={mockforme:this.token,[m]:g},n=o?._ack||null;this.memberCacheKey&&n&&(r["x-mfm-key"]=`${this.memberCacheKey}-${n}`);let s=`${this.getProxyUrl()}${e.pathname}`;return e.search&&(s+=e.search),{url:s,init:{...t,headers:{...t.headers,...r}}}}return{url:e.href,init:t}}setupInterceptor(){const e=this;globalThis.fetch=async function(t,r={}){if(!e.isReady)return e.originalFetch(t,r);const o=t instanceof Request?new URL(t.url):new URL(t,"http://localhost"),n=e.checkRules(o);if(n){console.log("[mockforme] [fetch] [rule matched]: ",h(n));try{const t=await e.applyRuleBehavior(n,o,r);if("redirect"===t?.type)return e.originalFetch(t.redirectUrl,r);if("passThrough"===t?.type)return e.originalFetch(o.href,r)}catch(e){throw e}}const{url:s,init:i}=e.interceptFetch(o,r);try{const t=await e.originalFetch(s,i);if(!t.ok)throw new Error(`[mockforme] Proxy fetch failed: ${t.status} ${t.statusText}`);return t}catch(e){throw e}};const t=(t,r)=>async function(...o){let n=o[0];if("string"==typeof n&&(n=new URL(n)),!e.isReady)return t.apply(null,[n,...o.slice(1)]);const s=e.checkRules(n);if(s){console.log(`[mockforme] [${r}] [rule matched]: `,h(s));try{const r=await e.applyRuleBehavior(s,n,{});if("passThrough"===r?.type)return t.apply(null,[n,...o.slice(1)])}catch(e){throw e}}const i=e.interceptRequest(n);try{return t.apply(null,[i,...o.slice(1)])}catch(e){throw e}};s().request=t(this.originalHttpRequest,"http.request"),a().request=t(this.originalHttpsRequest,"https.request"),s().get=t(this.originalHttpGet,"http.get"),a().get=t(this.originalHttpsGet,"https.get")}interceptRequest(e){const t=this.apiMappings.find((t=>{if(l(t.apiMethod)===l(e.method))return t.apiEndpoint===e.path||u(t.apiEndpoint,e.path)}));if(t){console.log("[mockforme] [matched request]: ",t,e);const r={mockforme:this.token,[m]:g},o=t?._ack||null;this.memberCacheKey&&o&&(r["x-mfm-key"]=`${this.memberCacheKey}-${o}`);let n=`${this.getProxyUrl()}${e.path}`;e.search&&(n+=e.search);const s=new URL(n);return{...e,hostname:s.hostname,path:s.pathname,headers:{...e.headers,...r}}}return e}run(e){e&&e(this.apiMappings,{_rules:this.rules})}}function _(e){return y?(y.token=e,y.fetchApiMappings()):y=new E(e),y}export{_ as mockforme};
|
|
1
|
+
import{createRequire as e}from"node:module";var t={56:e=>{e.exports=JSON.parse('{"name":"dotenv","version":"16.5.0","description":"Loads environment variables from .env file","main":"lib/main.js","types":"lib/main.d.ts","exports":{".":{"types":"./lib/main.d.ts","require":"./lib/main.js","default":"./lib/main.js"},"./config":"./config.js","./config.js":"./config.js","./lib/env-options":"./lib/env-options.js","./lib/env-options.js":"./lib/env-options.js","./lib/cli-options":"./lib/cli-options.js","./lib/cli-options.js":"./lib/cli-options.js","./package.json":"./package.json"},"scripts":{"dts-check":"tsc --project tests/types/tsconfig.json","lint":"standard","pretest":"npm run lint && npm run dts-check","test":"tap run --allow-empty-coverage --disable-coverage --timeout=60000","test:coverage":"tap run --show-full-coverage --timeout=60000 --coverage-report=lcov","prerelease":"npm test","release":"standard-version"},"repository":{"type":"git","url":"git://github.com/motdotla/dotenv.git"},"homepage":"https://github.com/motdotla/dotenv#readme","funding":"https://dotenvx.com","keywords":["dotenv","env",".env","environment","variables","config","settings"],"readmeFilename":"README.md","license":"BSD-2-Clause","devDependencies":{"@types/node":"^18.11.3","decache":"^4.6.2","sinon":"^14.0.1","standard":"^17.0.0","standard-version":"^9.5.0","tap":"^19.2.0","typescript":"^4.8.4"},"engines":{"node":">=12"},"browser":{"fs":false}}')},857:t=>{t.exports=e(import.meta.url)("os")},896:t=>{t.exports=e(import.meta.url)("fs")},928:t=>{t.exports=e(import.meta.url)("path")},982:t=>{t.exports=e(import.meta.url)("crypto")},998:(e,t,r)=>{const o=r(896),s=r(928),n=r(857),a=r(982),i=r(56).version,c=/(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/gm;function l(e){console.log(`[dotenv@${i}][DEBUG] ${e}`)}function p(e){return e&&e.DOTENV_KEY&&e.DOTENV_KEY.length>0?e.DOTENV_KEY:process.env.DOTENV_KEY&&process.env.DOTENV_KEY.length>0?process.env.DOTENV_KEY:""}function h(e,t){let r;try{r=new URL(t)}catch(e){if("ERR_INVALID_URL"===e.code){const e=new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development");throw e.code="INVALID_DOTENV_KEY",e}throw e}const o=r.password;if(!o){const e=new Error("INVALID_DOTENV_KEY: Missing key part");throw e.code="INVALID_DOTENV_KEY",e}const s=r.searchParams.get("environment");if(!s){const e=new Error("INVALID_DOTENV_KEY: Missing environment part");throw e.code="INVALID_DOTENV_KEY",e}const n=`DOTENV_VAULT_${s.toUpperCase()}`,a=e.parsed[n];if(!a){const e=new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${n} in your .env.vault file.`);throw e.code="NOT_FOUND_DOTENV_ENVIRONMENT",e}return{ciphertext:a,key:o}}function u(e){let t=null;if(e&&e.path&&e.path.length>0)if(Array.isArray(e.path))for(const r of e.path)o.existsSync(r)&&(t=r.endsWith(".vault")?r:`${r}.vault`);else t=e.path.endsWith(".vault")?e.path:`${e.path}.vault`;else t=s.resolve(process.cwd(),".env.vault");return o.existsSync(t)?t:null}function d(e){return"~"===e[0]?s.join(n.homedir(),e.slice(1)):e}const f={configDotenv:function(e){const t=s.resolve(process.cwd(),".env");let r="utf8";const n=Boolean(e&&e.debug);e&&e.encoding?r=e.encoding:n&&l("No encoding is specified. UTF-8 is used by default");let a,i=[t];if(e&&e.path)if(Array.isArray(e.path)){i=[];for(const t of e.path)i.push(d(t))}else i=[d(e.path)];const c={};for(const t of i)try{const s=f.parse(o.readFileSync(t,{encoding:r}));f.populate(c,s,e)}catch(e){n&&l(`Failed to load ${t} ${e.message}`),a=e}let p=process.env;return e&&null!=e.processEnv&&(p=e.processEnv),f.populate(p,c,e),a?{parsed:c,error:a}:{parsed:c}},_configVault:function(e){Boolean(e&&e.debug)&&l("Loading env from encrypted .env.vault");const t=f._parseVault(e);let r=process.env;return e&&null!=e.processEnv&&(r=e.processEnv),f.populate(r,t,e),{parsed:t}},_parseVault:function(e){const t=u(e),r=f.configDotenv({path:t});if(!r.parsed){const e=new Error(`MISSING_DATA: Cannot parse ${t} for an unknown reason`);throw e.code="MISSING_DATA",e}const o=p(e).split(","),s=o.length;let n;for(let e=0;e<s;e++)try{const t=h(r,o[e].trim());n=f.decrypt(t.ciphertext,t.key);break}catch(t){if(e+1>=s)throw t}return f.parse(n)},config:function(e){if(0===p(e).length)return f.configDotenv(e);const t=u(e);return t?f._configVault(e):(r=`You set DOTENV_KEY but you are missing a .env.vault file at ${t}. Did you forget to build it?`,console.log(`[dotenv@${i}][WARN] ${r}`),f.configDotenv(e));var r},decrypt:function(e,t){const r=Buffer.from(t.slice(-64),"hex");let o=Buffer.from(e,"base64");const s=o.subarray(0,12),n=o.subarray(-16);o=o.subarray(12,-16);try{const e=a.createDecipheriv("aes-256-gcm",r,s);return e.setAuthTag(n),`${e.update(o)}${e.final()}`}catch(e){const t=e instanceof RangeError,r="Invalid key length"===e.message,o="Unsupported state or unable to authenticate data"===e.message;if(t||r){const e=new Error("INVALID_DOTENV_KEY: It must be 64 characters long (or more)");throw e.code="INVALID_DOTENV_KEY",e}if(o){const e=new Error("DECRYPTION_FAILED: Please check your DOTENV_KEY");throw e.code="DECRYPTION_FAILED",e}throw e}},parse:function(e){const t={};let r,o=e.toString();for(o=o.replace(/\r\n?/gm,"\n");null!=(r=c.exec(o));){const e=r[1];let o=r[2]||"";o=o.trim();const s=o[0];o=o.replace(/^(['"`])([\s\S]*)\1$/gm,"$2"),'"'===s&&(o=o.replace(/\\n/g,"\n"),o=o.replace(/\\r/g,"\r")),t[e]=o}return t},populate:function(e,t,r={}){const o=Boolean(r&&r.debug),s=Boolean(r&&r.override);if("object"!=typeof t){const e=new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");throw e.code="OBJECT_REQUIRED",e}for(const r of Object.keys(t))Object.prototype.hasOwnProperty.call(e,r)?(!0===s&&(e[r]=t[r]),o&&l(!0===s?`"${r}" is already defined and WAS overwritten`:`"${r}" is already defined and was NOT overwritten`)):e[r]=t[r]}};e.exports.configDotenv=f.configDotenv,e.exports._configVault=f._configVault,e.exports._parseVault=f._parseVault,e.exports.config=f.config,e.exports.decrypt=f.decrypt,e.exports.parse=f.parse,e.exports.populate=f.populate,e.exports=f}},r={};function o(e){var s=r[e];if(void 0!==s)return s.exports;var n=r[e]={exports:{}};return t[e](n,n.exports,o),n.exports}o.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return o.d(t,{a:t}),t},o.d=(e,t)=>{for(var r in t)o.o(t,r)&&!o.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);const s=e(import.meta.url)("http");var n=o.n(s);const a=e(import.meta.url)("https");var i=o.n(a);const c=e(import.meta.url)("child_process");var l=o(998),p=o.n(l);const h=e=>{try{return e?e.toLowerCase():e}catch(e){return console.log(e),null}},u=(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},d=(e,t=null,r=2)=>{try{return JSON.stringify(e,t,r)}catch(e){return null}};class f{static match(e,t){if(!Array.isArray(t)||0===t.length)return!1;const{url:r,headers:o,queryParams:s,body:n}=e,a="undefined"!=typeof window?window.location.origin:globalThis.location?.origin||"http://localhost";for(const e of t){let t="";const{type:i,key:c,operator:l,value:p}=e;switch(i){case"URL":try{t=new URL(r,a).pathname}catch{t=r}break;case"QUERY_PARAM":if(s&&void 0!==s[c])t=String(s[c]);else try{t=new URL(r,a).searchParams.get(c)||""}catch{t=""}break;case"REQUEST_BODY":if(c){if("object"==typeof n&&null!==n)t=void 0!==n[c]?String(n[c]):"";else if("string"==typeof n)try{const e=JSON.parse(n);t=void 0!==e[c]?String(e[c]):""}catch{t=""}}else t="object"==typeof n?JSON.stringify(n):String(n||"");break;case"REQUEST_HEADER":if(c){const e=c?.toLowerCase();if(t="",o){const r=Object.keys(o).find((t=>t.toLowerCase()===e));t=r?String(o[r]):""}}else t=JSON.stringify(o||{});break;default:return!1}if(!this.evaluate(t,l,p))return!1}return!0}static evaluate(e,t,r){const o=t?.toLowerCase(),s=String(e),n=String(r);switch(o){case"contains":return s.includes(n);case"equal":case"equals":return s===n;case"regexp":try{let e=n;if(e.startsWith("/")&&e.lastIndexOf("/")>0){const t=e.lastIndexOf("/"),r=e.slice(1,t),o=e.slice(t+1);return new RegExp(r,o).test(s)}return new RegExp(e).test(s)}catch{return!1}default:return!1}}}class m{static async apply(e){if(!e||!e.activeAction)return{type:"passThrough",delay:0};const{activeAction:t,actions:r}=e,o=r?.[t];if(!o)return{type:"passThrough",delay:0};const s={type:"passThrough",delay:0},n=Number(o.value||0);switch(t){case"delay":s.delay=n,s.delay>0&&await new Promise((e=>setTimeout(e,1e3*s.delay)));break;case"delay_and_redirect":s.type="redirect",s.delay=n,s.redirectUrl=o.redirectUrl,s.delay>0&&await new Promise((e=>setTimeout(e,1e3*s.delay)));break;case"delay_and_timeout":s.type="timeout",s.delay=n,s.delay>0&&await new Promise((e=>setTimeout(e,1e3*s.delay)))}return s}}class y{static applyRequestModifications(e,t){if(!t)return e;let{url:r,headers:o,queryParams:s,body:n}={...e};o&&(o={...o}),s&&(s={...s});const{modifyQueryParams:a,modifyRequestBody:i,modifyRequestHeaders:c}=t;if(a?.enabled)try{const e=new URL(r,"undefined"!=typeof window?window.location.href:"http://localhost");Array.isArray(a.remove)&&a.remove.forEach((t=>{e.searchParams.delete(t),s&&delete s[t]})),Array.isArray(a.add)&&a.add.forEach((({key:t,value:r})=>{e.searchParams.set(t,r),s&&(s[t]=r)})),r=e.toString()}catch(e){console.error("[MockForMe] Failed to modify query params",e)}if(c?.enabled&&(o={...o},Array.isArray(c.remove)&&c.remove.forEach((e=>{const t=e.toLowerCase(),r=Object.keys(o).find((e=>e.toLowerCase()===t));r&&delete o[r]})),Array.isArray(c.add)&&c.add.forEach((({key:e,value:t})=>{o[e]=t}))),i?.enabled)try{let t=null;if("string"==typeof n)try{t=JSON.parse(n)}catch{}else if("object"==typeof n&&null!==n)try{t=JSON.parse(JSON.stringify(n))}catch{t={...n}}t&&(Array.isArray(i.remove)&&i.remove.forEach((e=>delete t[e])),Array.isArray(i.add)&&i.add.forEach((({key:e,value:r})=>t[e]=r)),Array.isArray(i.update)&&i.update.forEach((({key:e,value:r})=>t[e]=r)),n="string"==typeof e.body?JSON.stringify(t):t)}catch(e){console.error("[MockForMe] Failed to modify request body",e)}return{...e,url:r,headers:o,queryParams:s,body:n}}static applyResponseModifications(e,t){if(!t?.modifyResponseHeaders?.enabled)return e;const{modifyResponseHeaders:r}=t,o={...e};return Array.isArray(r.remove)&&r.remove.forEach((e=>{const t=e.toLowerCase(),r=Object.keys(o).find((e=>e.toLowerCase()===t));r&&delete o[r]})),Array.isArray(r.add)&&r.add.forEach((({key:e,value:t})=>{o[e]=t})),o}}class g{static match(e,t){if(!Array.isArray(t)||0===t.length)return null;for(const r of t){const t=r.rule||r;if(t.conditions&&Array.isArray(t.conditions)&&f.match(e,t.conditions)){const e=t.timingAction?.activeAction||"";return{action:e,config:t.timingAction?.actions?.[e]||{},rule:t}}}return null}static async apply(e,t){if(!e)return null;const r=e.rule||e,o=y.applyRequestModifications(t,r.modificationActions);return{...await m.apply(r.timingAction),modifiedRequest:o,rule:r}}static applyResponseModifications(e,t){return y.applyResponseModifications(e,t)}}p().config("../../.env");const v="https://api.mockforme.com",E=`${v}/mockforme`,w="mfmver",b="4.2.7";let k=`${v}/gateway/3f4eae522b`,_=null;class A{constructor(e){this.token=e,this.apiMappings=[],this.rules=[],this.isReady=!1,this.originalHttpRequest=n().request,this.originalHttpGet=n().get,this.originalHttpsRequest=i().request,this.originalHttpsGet=i().get,this.originalFetch=globalThis.fetch,this.fetchApiMappings(),this.setupInterceptor()}checkIsErrorInFetchMappings(e){try{const t=JSON.parse(e);if(0==t?.status)throw new Error(t?.message||"Failed to fetch mockforme mappings")}catch(e){throw new Error(e.message||"Failed to fetch mockforme mappings")}}fetchApiMappings(){this.apiMappings=[],this.rules=[],this.isReady=!1;try{const e=`curl -s -H "mockforme: ${this.token}" "${k}"`,t=(0,c.execSync)(e,{encoding:"utf8"});if(t&&this.checkIsErrorInFetchMappings(t),!t)throw new Error("Failed to fetch mockforme mappings: No response");{const{di:e,iv:r,_o:o,_mck:s,mk:n,r:a}=JSON.parse(t);this.organisationId=o,this.memberKey=n,this.memberCacheKey=s;const i=function({di:e,iv:t},r){var o;const s=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(s)}({di:e,iv:r},o);i&&(this.apiMappings=i),a&&(this.rules=a)}this.isReady=!0}catch(e){console.error("[mockforme] Failed to fetch mappings:",e.message)}}getProxyUrl(){return`${E}/${this.organisationId}/${this.memberKey}`}checkRules(e){return g.match(e,this.rules)}async applyRuleBehavior(e,t){return await g.apply(e,t)}interceptFetch(e,t){const r=(t.method||"GET").toUpperCase(),o=this.apiMappings.find((t=>{const o=h(t.apiMethod)===h(r),s=t.apiEndpoint===e.pathname||u(t.apiEndpoint,e.pathname);return o&&s}));if(o){console.log("[mockforme] [api intercepted]: ",o);const r={mockforme:this.token,[w]:b},s=o?._ack||null;this.memberCacheKey&&s&&(r["x-mfm-key"]=`${this.memberCacheKey}-${s}`);let n=`${this.getProxyUrl()}${e.pathname}`;return e.search&&(n+=e.search),{url:n,init:{...t,headers:{...t.headers,...r}}}}return{url:e.href,init:t}}setupInterceptor(){const e=this;globalThis.fetch=async function(t,r={}){if(!e.isReady)return e.originalFetch(t,r);const o=t instanceof Request?new URL(t.url):new URL(t,"http://localhost"),s={url:o.href,method:(r.method||"GET").toUpperCase(),headers:r.headers||{},queryParams:Object.fromEntries(o.searchParams.entries())},n=e.checkRules(s);if(n){console.log("[mockforme] [fetch] [rule matched]: ",d(n));try{const t=await e.applyRuleBehavior(n,s),{modifiedRequest:o,type:a,redirectUrl:i}=t;return"redirect"===a?e.originalFetch(i,{...r,method:o.method,headers:o.headers,body:o.body}):e.originalFetch(o.url,{...r,method:o.method,headers:o.headers,body:o.body})}catch(e){throw e}}const{url:a,init:i}=e.interceptFetch(o,r);try{const t=await e.originalFetch(a,i);if(!t.ok)throw new Error(`[mockforme] Proxy fetch failed: ${t.status} ${t.statusText}`);return t}catch(e){throw e}};const t=(t,r)=>async function(...o){let s=o[0];if("string"==typeof s&&(s=new URL(s)),!e.isReady)return t.apply(null,[s,...o.slice(1)]);const n={url:s.href||s.url||`http://${s.hostname}${s.path}`,method:(s.method||"GET").toUpperCase(),headers:s.headers||{}},a=e.checkRules(n);if(a){console.log(`[mockforme] [${r}] [rule matched]: `,d(a));try{const r=await e.applyRuleBehavior(a,n),{modifiedRequest:i,type:c,redirectUrl:l}=r;if("passThrough"===c){const e={...s};try{const t=new URL(i.url);e.hostname=t.hostname,e.path=t.pathname+t.search,e.port=t.port,e.protocol=t.protocol}catch(e){}return i.headers&&(e.headers=i.headers),i.method&&(e.method=i.method),t.apply(null,[e,...o.slice(1)])}}catch(e){throw e}}const i=e.interceptRequest(s);try{return t.apply(null,[i,...o.slice(1)])}catch(e){throw e}};n().request=t(this.originalHttpRequest,"http.request"),i().request=t(this.originalHttpsRequest,"https.request"),n().get=t(this.originalHttpGet,"http.get"),i().get=t(this.originalHttpsGet,"https.get")}interceptRequest(e){const t=this.apiMappings.find((t=>{if(h(t.apiMethod)===h(e.method))return t.apiEndpoint===e.path||u(t.apiEndpoint,e.path)}));if(t){console.log("[mockforme] [matched request]: ",t,e);const r={mockforme:this.token,[w]:b},o=t?._ack||null;this.memberCacheKey&&o&&(r["x-mfm-key"]=`${this.memberCacheKey}-${o}`);let s=`${this.getProxyUrl()}${e.path}`;e.search&&(s+=e.search);const n=new URL(s);return{...e,hostname:n.hostname,path:n.pathname,headers:{...e.headers,...r}}}return e}run(e){e&&e(this.apiMappings,{_rules:this.rules})}}function R(e){return _?(_.token=e,_.fetchApiMappings()):_=new A(e),_}export{R as mockforme};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mockforme",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.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",
|