local-traffic 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,7 +5,7 @@ That is a secure http/2 (or insecure http1.1) reverse-proxy installed on your ma
5
5
  - with 0 transitive dependency
6
6
  - with 1 install step
7
7
  - with a startup time of a few milliseconds
8
- - with one 70kb index.js file
8
+ - with one 29kb index.js file
9
9
 
10
10
  How simple is that ?
11
11
 
@@ -72,7 +72,7 @@ npx local-traffic [location-of-the-local-traffic-config-file]
72
72
  ### from a node.js application (>= 0.0.72)
73
73
 
74
74
  ```bash
75
- node -e 'const { start } = require("local-traffic"); start({ /* configuration goes here */ })'
75
+ node -e 'require("local-traffic").start({ /* configuration goes here */ })'
76
76
  ```
77
77
 
78
78
  ## how to change mappings to local / non-local
@@ -95,7 +95,7 @@ All boolean settings default to false when unspecified.
95
95
  - `dontTranslateLocationHeader`: (`boolean`) when getting a response location header, in case `replaceResponseBodyUrls` does not change the URL, change the origin to the proxy anyway
96
96
  - `dontUseHttp2Downstream`: (`boolean`) force calling downstream services in http1.1 only (to save some time)
97
97
  - `simpleLogs`: (`boolean`) disable colored logs for text terminals
98
- - `logAccessInTerminal`: (`boolean`) write an access log in the terminal on each call (defaults to false)
98
+ - `logAccessInTerminal`: (`boolean` | 'with-mapping') write an access log in the terminal on each call (>= 0.1.2 : 'with-mapping' will log the key used to find the target)
99
99
  - `websocket`: (`boolean`) true to activate websocket connections proxying via sockets. Required for logs UI.
100
100
  - `disableWebSecurity`: (`boolean`) true for easygoing values in cross origin requests or content security policy headers
101
101
  - `connectTimeout`: (`number`) max time before aborting the connection (defaults to 3000ms)
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var e,t=this&&this.__awaiter||function(e,t,n,o){return new(n||(n=Promise))((function(r,s){function i(e){try{a(o.next(e))}catch(e){s(e)}}function l(e){try{a(o.throw(e))}catch(e){s(e)}}function a(e){var t;e.done?r(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(i,l)}a((o=o.apply(e,t||[])).next())}))},n=this&&this.__rest||function(e,t){var n={};for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&t.indexOf(o)<0&&(n[o]=e[o]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var r=0;for(o=Object.getOwnPropertySymbols(e);r<o.length;r++)t.indexOf(o[r])<0&&Object.prototype.propertyIsEnumerable.call(e,o[r])&&(n[o[r]]=e[o[r]])}return n};Object.defineProperty(exports,"__esModule",{value:!0}),exports.update=exports.serve=exports.determineMapping=exports.send=exports.cleanEntropy=exports.replaceTextUsingMapping=exports.replaceBody=exports.acknowledgeWebsocket=exports.readWebsocketBuffer=exports.createWebsocketBufferFrom=exports.websocketServe=exports.recorderHandler=exports.quickStatus=exports.errorListener=exports.load=exports.start=void 0;const o=require("http2"),r=require("http"),s=require("https"),i=require("url"),l=require("fs"),a=require("zlib"),d=require("path"),c=require("crypto"),u=require("process"),p=require("os");var m,g,h,f;!function(e){e[e.ERROR=124]="ERROR",e[e.INFO=93]="INFO",e[e.WARNING=172]="WARNING"}(m||(m={})),function(e){e.INBOUND="↘️ ",e.PORT="☎️ ",e.OUTBOUND="↗️ ",e.RULES="🔗",e.MOCKS="🌐",e.STRICT_MOCKS="🕸️",e.AUTO_RECORD="📼",e.REWRITE="✒️ ",e.LOGS="📝",e.RESTART="🔄",e.WEBSOCKET="☄️ ",e.COLORED="✨",e.SHIELD="🛡️ ",e.NO="⛔",e.ERROR_1="❌",e.ERROR_2="⛈️ ",e.ERROR_3="☢️ ",e.ERROR_4="⁉️ ",e.ERROR_5="⚡",e.ERROR_6="☠️ "}(g||(g={})),function(e){e.INBOUND="INBOUND",e.OUTBOUND="OUTBOUND"}(h||(h={})),function(e){e.PROXY="proxy",e.MOCK="mock"}(f||(f={}));const v=null!==(e=u.argv.map((e=>e.trim())).filter((e=>e&&!["ts-node","node","npx","npm","exec"].some((t=>e.includes(t)&&!e.match(/npm-cache/)&&!e.match(/_npx/)))))[0])&&void 0!==e?e:"",y=v.toLowerCase().replace(/[-_]/g,"").includes("localtraffic")&&!v.match(/(.|-)?(test|spec)\.m?[jt]sx?$/),b=y?(0,d.resolve)((0,u.cwd)(),u.argv.slice(-1)[0].endsWith(".json")?u.argv.slice(-1)[0]:(0,d.resolve)((0,p.homedir)(),".local-traffic.json")):`${(0,p.tmpdir)()}${d.sep}local-traffic-temporary-config-${(0,c.randomBytes)(6).toString("hex")}.json`,k=u.argv.some((e=>"--crash-test"===e)),O=()=>{var e,t;return null!==(t=null===(e=u.hrtime.bigint)||void 0===e?void 0:e.call(u.hrtime))&&void 0!==t?t:(()=>{const e=(0,u.hrtime)();return 1e3*e[0]+e[1]/1e6})()},w=e=>{const t=new Date;return`${e?"":""}${`${t.getHours()}`.padStart(2,"0")}${e?":":":"}${`${t.getMinutes()}`.padStart(2,"0")}${e?":":":"}${`${t.getSeconds()}`.padStart(2,"0")}${e?"":""}`},R=function(e,n){return t(this,void 0,void 0,(function*(){var t,o,r,s,i,l,a;const d=n.map((e=>e.map((e=>e.text.replace(/⎸/g,"|").replace(/⎹/g,"|").replace(/\u001b\[[^m]*m/g,"").replace(new RegExp(g.INBOUND,"g"),"inbound:").replace(new RegExp(g.PORT,"g"),"port:").replace(new RegExp(g.OUTBOUND,"g"),"outbound:").replace(new RegExp(g.RULES,"g"),"rules:").replace(new RegExp(g.NO,"g"),"").replace(new RegExp(g.REWRITE,"g"),"+rewrite").replace(new RegExp(g.WEBSOCKET,"g"),"websocket").replace(new RegExp(g.SHIELD,"g"),"web-security").replace(new RegExp(g.MOCKS,"g"),"mocks").replace(new RegExp(g.STRICT_MOCKS,"g"),"mocks (strict)").replace(new RegExp(g.AUTO_RECORD,"g"),"auto record").replace(new RegExp(g.LOGS,"g"),"logs").replace(new RegExp(g.RESTART,"g"),"restart").replace(new RegExp(g.COLORED,"g"),"colored").replace(/\|+/g,"|"))).join(" | ")));if(null===(t=null==e?void 0:e.config)||void 0===t?void 0:t.simpleLogs)for(let t of d)u.stdout.write(`${w(null===(o=null==e?void 0:e.config)||void 0===o?void 0:o.simpleLogs)} | ${t}\n`);else for(let t of n){const n=t.map((e=>`[48;5;${e.color}m${e.text}`));u.stdout.write(`${w(null===(r=null==e?void 0:e.config)||void 0===r?void 0:r.simpleLogs)}${t.map((e=>{var t;return`[48;5;${e.color}m${"".padEnd((null!==(t=e.length)&&void 0!==t?t:64)+1)}`})).join("▐")}\n`),yield new Promise((e=>u.stdout.moveCursor(-1e3,-1,(()=>e(void 0)))));let o=9;for(let e=0;e<n.length;e++)yield new Promise((e=>u.stdout.moveCursor(-1e3,0,(()=>u.stdout.moveCursor(o,0,(()=>e(void 0))))))),u.stdout.write(n[e]),o+=(null!==(s=t[e].length)&&void 0!==s?s:64)+2;u.stdout.write("\n");for(let n of d)null===(i=null==e?void 0:e.notifyLogsListeners)||void 0===i||i.call(e,{event:n,level:(c=null!==(a=null===(l=null==t?void 0:t[0])||void 0===l?void 0:l.color)&&void 0!==a?a:m.INFO,c===m.ERROR?"error":c===m.WARNING?"warning":"info")})}var c}))},$=(e,t)=>{var n;const o=Array(4).fill(0).map((()=>t?Math.floor(256*Math.random()):0)),r=e.split("").map(((e,t)=>e.charCodeAt(0)^o[3&t])),s=e.length,i=t?128:0,l=e.length<126?Buffer.from(Uint8Array.from([129,i+s]).buffer):e.length<65535?Buffer.concat([Buffer.from(Uint8Array.from([129,126|i]).buffer),Buffer.from(Uint8Array.from([s>>8]).buffer),Buffer.from(Uint8Array.from([255&s]).buffer)]):Buffer.concat([Buffer.from(Uint8Array.from([129,127|i]).buffer),Buffer.concat((null!==(n=Number(s).toString(16).padStart(16,"0").match(/.{2}/g))&&void 0!==n?n:["0"]).map((e=>parseInt(e,16))).map((e=>Buffer.from(Uint8Array.from([e]).buffer))))]),a=Buffer.from(Int8Array.from(o).buffer),d=Buffer.from(Int8Array.from(r).buffer);return Buffer.concat(t?[l,a,d]:[l,d])};exports.createWebsocketBufferFrom=$;const E=(e,t)=>{var n;if(!(t||1&e.readUInt8(0)))return{payloadLength:0,mask:[0,0,0,0],body:""};const o=t?0:e.readUInt8(1),r=o>>7,s=127&o,i=t?t.payloadLength:127!==s?s:e.readUInt8(2)<<8+e.readUInt8(3),l=t?t.mask:r?Array(4).fill(0).map(((t,n)=>e.readUInt8(n+4))):[0,0,0,0],a=t?0:r?8:4,d=Array(e.length-a).fill(0).map(((t,n)=>String.fromCharCode(e.readUInt8(n+a)^l[3&n]))).join("");return{payloadLength:i,mask:l,body:(null!==(n=null==t?void 0:t.body)&&void 0!==n?n:"").concat(d)}};exports.readWebsocketBuffer=E;const S=(e,t)=>{const n=(0,c.createHash)("sha1");n.update(t+"258EAFA5-E914-47DA-95CA-C5AB0DC85B11");const o=n.digest("base64");e.allowHalfOpen=!0,e.write(`HTTP/1.1 101 Switching Protocols\r\ndate: ${(new Date).toUTCString()}\r\nconnection: upgrade\r\nupgrade: websocket\r\nserver: local\r\nsec-websocket-accept: ${o}\r\n\r\n`)};exports.acknowledgeWebsocket=S;const x=function(e){return B(e,this.configListeners)},C=function(e){const{response:t}=e,o=n(e,["response"]);return Promise.all([B(e,this.logsListeners.filter((e=>e.wantsResponseMessage))),B(o,this.logsListeners.filter((e=>!e.wantsResponseMessage)))])},B=(e,t)=>{if(!t.length)return;const n=JSON.stringify(e),o=new Set(t.map((e=>e.wantsMask))),r=o.has(!1)&&$(n,!1),s=o.has(!0)&&$(n,!0),i=e=>{e.stream.errored&&e.stream.destroy()};t.forEach((e=>{e.stream.closed||e.stream.errored||(e.wantsMask?e.stream.write(s,"ascii",(()=>i(e))):e.stream.write(r,"ascii",(()=>i(e))))}))},I=function(){var e,t;return[{color:52,text:`${g.PORT} ${(null!==(e=this.config.port)&&void 0!==e?e:"").toString()}`,length:11},{color:53,text:`${g.OUTBOUND} ${this.config.dontUseHttp2Downstream?"H1.1":"H/2 "}${this.config.replaceRequestBodyUrls?g.REWRITE:" "}`,length:11},{color:54,text:`${g.INBOUND} ${this.config.ssl?"H/2 ":"H1.1"}${this.config.replaceResponseBodyUrls?g.REWRITE:" "}`,length:11},{color:55,text:""+(this.mode===f.PROXY&&this.mockConfig.autoRecord?`${g.AUTO_RECORD}${this.mockConfig.mocks.size.toString().padStart(3)}`:this.mode===f.PROXY?`${g.RULES}${Object.keys(null!==(t=this.config.mapping)&&void 0!==t?t:{}).length.toString().padStart(3)}`:`${this.mockConfig.strict?g.STRICT_MOCKS:g.MOCKS}${this.mockConfig.mocks.size.toString().padStart(3)}`),length:7},{color:56,text:`${this.config.websocket?g.WEBSOCKET:g.NO}`,length:4},{color:57,text:`${this.config.simpleLogs?g.NO:g.COLORED}`,length:4},{color:93,text:`${this.config.disableWebSecurity?g.NO:g.SHIELD}`,length:4}]},T=function(e){return t(this,void 0,void 0,(function*(){this.log([...null!=e?e:[],this.buildQuickStatus()]).then((()=>this.notifyConfigListeners(this.config)))}))};exports.quickStatus=T;const N=(e,t,n,o,r)=>`${J(128163,"error",e.message)}\n<p>An error happened while trying to proxy a remote exchange</p>\n<div class="alert alert-warning" role="alert">\n&#x24D8;&nbsp;This is not an error from the downstream service.\n</div>\n<div class="alert alert-danger" role="alert">\n<pre><code>${e.stack||`<i>${e.name} : ${e.message}</i>`}${e.errno?`<br/>(code : ${e.errno})`:""}</code></pre>\n</div>\nMore information about the request :\n<table class="table">\n<tbody>\n<tr>\n<td>server mode</td>\n<td>${t}</td>\n</tr>\n<tr>\n<td>phase</td>\n<td>${n}</td>\n</tr>\n<tr>\n<td>requested URL</td>\n<td>${o}</td>\n</tr>\n<tr>\n<td>downstream URL</td>\n<td>${r||"&lt;no-target-url&gt;"}</td>\n</tr>\n</tbody>\n</table>\n</div></body></html>`,q=(e,t,n)=>`<table id="table-access" class="table table-striped" style="display: block; width: 100%; overflow-y: auto">\n<thead>\n<tr>\n<th scope="col"${!0===n.captureResponseBody?' style="min-width: 120px"':""}>...</th>\n<th scope="col">Date</th>\n<th scope="col">Level</th>\n<th scope="col">Protocol</th>\n<th scope="col">Method</th>\n<th scope="col">Status</th>\n<th scope="col">Duration</th>\n<th scope="col">Upstream Path</th>\n<th scope="col">Downstream Path</th>\n</tr>\n</thead>\n<tbody id="access">\n</tbody>\n</table>\n<table id="table-proxy" class="table table-striped" style="display: none; width: 100%; overflow-y: auto">\n<thead>\n<tr>\n<th scope="col">Date</th>\n<th scope="col">Level</th>\n<th scope="col">Message</th>\n</tr>\n</thead>\n<tbody id="proxy">\n</tbody>\n</table>\n<div class="alert alert-warning" role="alert"\nstyle="display:none;left:20%;right:20%;top:20%;position:absolute;z-index:1;"\nid="websocket-disconnected">\n<p>&#x24D8;&nbsp;Websocket connection is not available at this moment.</p>\n<ul><li>Is local-traffic running ?</li><li>Are websockets enabled ?</li>\n<li>Are you running a network protection tool that disallows websockets ?</li></ul>\n</div>\n<script type="text/javascript">\nlet socket = null;\nfunction start() {\ndocument.getElementById('table-access').style.height =\n(document.documentElement.clientHeight - 150) + 'px';\nif (socket !== null) return;\nsocket = new WebSocket("ws${t.ssl?"s":""}://${e}/local-traffic-logs${n.captureResponseBody?"?wantsResponseMessage=true":""}");\nsocket.onopen = function(event) {\ndocument.getElementById('websocket-disconnected').style.display = 'none';\ndocument.getElementById('table-access').style.filter = null;\n(document.getElementsByTagName('nav')[0]||{style:{}}).style.filter = null;\n(document.getElementsByTagName('form')[0]||{style:{}}).style.filter = null;\n}\nsocket.onmessage = function(event) {\nlet data = event.data\nlet uniqueHash;\ntry {\nconst { uniqueHash: uniqueHash1, ...data1 } = JSON.parse(event.data);\ndata = data1;\nuniqueHash = uniqueHash1;\n} catch(e) { }\nif (document.getElementById('mock-mode')?.checked) return;\nif (${!0===n.captureResponseBody} && \ndata?.downstreamPath?.startsWith('recorder://') &&\n!data?.upstreamPath?.endsWith('?forceLogInRecorderPage=true'))\nreturn;\nconst time = new Date().toISOString().split('T')[1].replace('Z', '');\nconst actions = getActionsHtmlText(uniqueHash, data.response);\nif(data.statusCode && uniqueHash) {\nconst color = getColorFromStatusCode(data.statusCode);\nconst statusCodeColumn = document.querySelector("#event-" + data.randomId + " .statusCode");\nif (statusCodeColumn)\nstatusCodeColumn.innerHTML = '<span class="badge bg-' + color + '">' + data.statusCode + '</span>';\n\nconst durationColumn = document.querySelector("#event-" + data.randomId + " .duration");\nif (durationColumn) {\nconst duration = data.duration > 10000 ? Math.floor(data.duration / 1000) + 's' :\ndata.duration + 'ms';\ndurationColumn.innerHTML = duration;\n}\n\nconst protocolColumn = document.querySelector("#event-" + data.randomId + " .protocol");\nif (protocolColumn) {\nprotocolColumn.innerHTML = data.protocol;\n}\n\nconst replayColumn = document.querySelector("#event-" + data.randomId + " .replay");\nif (replayColumn) {\nreplayColumn.innerHTML = actions;\n}\n} else if (uniqueHash) {\naddNewRequest(data.randomId, actions, time, data.level, data.protocol, data.method, \n'<span class="badge bg-secondary">...</span>', '&#x23F1;',\ndata.upstreamPath, data.downstreamPath);\n} else if(data.event) {\ndocument.getElementById("proxy")\n.insertAdjacentHTML('afterbegin', '<tr><td scope="col">' + time + '</td>' +\n'<td scope="col">' + (data.level || 'info')+ '</td>' + \n'<td scope="col">' + data.event + '</td></tr>');\n}\ncleanup();\n};\nsocket.onerror = function(error) {\nsocket = null;\nsetTimeout(start, 1000);\nif (error.target.readyState === 3) {\ndocument.getElementById('websocket-disconnected').style.display = 'block';\ndocument.getElementById('table-access').style.filter = 'blur(8px)';\n(document.getElementsByTagName('nav')[0]||{style:{}}).style.filter = 'blur(8px)';\n(document.getElementsByTagName('form')[0]||{style:{}}).style.filter = 'blur(8px)';\nreturn;\n}\nthrow new Error(\`[error] \${JSON.stringify(error)}\`);\n};\nsocket.onclose = function(error) {\nsocket = null;\nsetTimeout(start, 1000);\n};\n};\nfunction show(id) {\n[...document.querySelectorAll('table')].forEach((table, index) => {\ntable.style.display = index === id ? 'block': 'none'\n});\n[...document.querySelectorAll('.navbar-nav .nav-item .nav-link')].forEach((link, index) => {\nif (index === id) { link.classList.add('active') } else link.classList.remove('active');\n});\n}\nfunction remove(event) {\nevent.target.closest('tr').remove();\nif (window.updateState) window.updateState();\n}\nfunction cleanup() {\nconst currentLimit = parseInt(document.getElementById('limit').value)\nfor (let table of ['access', 'proxy']) {\nwhile (currentLimit && document.getElementById(table).childNodes.length && \ndocument.getElementById(table).childNodes.length > currentLimit) {\n[...document.getElementById(table).childNodes].slice(-1)[0].remove();\n}\n}\n}\nfunction replay(event) {\nconst uniqueHash = event.target.dataset.uniquehash;\nconst { method, url, headers, body } = JSON.parse(atob(uniqueHash));\nfetch(url, {\nmethod,\nheaders,\nbody: !body || !body.length ? undefined : atob(body)\n});\n}\nfunction getActionsHtmlText(uniqueHash, response) {\nconst edit = ${!0===n.captureResponseBody} && uniqueHash\n? '<button data-response="' + (response ?? "") +\n'" data-uniquehash="' + uniqueHash + \n'" data-bs-toggle="modal" data-bs-target="#edit-request" type="button" ' +\n'class="btn btn-primary">&#x1F4DD;</button>'\n: ''\nconst remove = ${!0===n.captureResponseBody} && uniqueHash\n? '<button onclick="javascript:remove(event)" type="button" ' +\n'class="btn btn-primary">&#x274C;</button>'\n: ''\nconst replay = ${!1===n.captureResponseBody} && uniqueHash ? '<button data-response="' + \nbtoa(JSON.stringify(response ?? {})) +\n'" data-uniquehash="' + uniqueHash + '" onclick="javascript:replay(event)" ' +\n'type="button" class="btn btn-primary">&#x1F501;</button>' : '';\nreturn edit + replay + remove\n}\nfunction addNewRequest(\nrandomId, actions, time, level, protocol, method, \nstatusCode, duration, upstreamPath, downstreamPath\n) {\ndocument.getElementById("access")\n.insertAdjacentHTML('afterbegin', '<tr id="event-' + randomId + '">' +\n'<td scope="col" class="replay">' + actions + '</td>' +\n'<td scope="col">' + time + '</td>' +\n'<td scope="col">' + (level || 'info')+ '</td>' + \n'<td scope="col" class="protocol">' + protocol + '</td>' + \n'<td scope="col" class="method">' + method + '</td>' + \n'<td scope="col" class="statusCode">' + statusCode + '</td>' +\n'<td scope="col" class="duration text-end">' + duration + '</td>' +\n'<td scope="col" class="upstream-path">' + upstreamPath + '</td>' + \n'<td scope="col">' + downstreamPath + '</td>' + \n'</tr>');\n}\nfunction getColorFromStatusCode(statusCode) {\nreturn Math.floor(statusCode / 100) === 1 ? "info" :\nMath.floor(statusCode / 100) === 2 ? "success" :\nMath.floor(statusCode / 100) === 3 ? "dark" :\nMath.floor(statusCode / 100) === 4 ? "warning" :\nMath.floor(statusCode / 100) === 5 ? "danger" :\n"secondary";\n}\nwindow.addEventListener("DOMContentLoaded", start);\n<\/script>`,j=(e,t,n)=>{let o={};try{o=JSON.parse(t.toString("ascii"))}catch(e){}if("object"!=typeof o||Object.keys(o).filter((e=>!["strict","mode","mocks","autoRecord"].includes(e))).length||!Array.isArray(o.mocks)&&void 0!==o.mocks)return void e.log([[{text:`${g.MOCKS} invalid mocks update received`,color:m.WARNING}]]);const{mocks:r,mode:s,strict:i,autoRecord:l}=o,a=r?new Map(r.map((({response:t,uniqueHash:n})=>[Y(e.config,n),t]))):null,d=s!==e.mode&&s===f.PROXY,c=(!d||!0===l)&&(null!=l?l:e.mockConfig.autoRecord),u=void 0!==c&&c!=e.mockConfig.autoRecord,p=s!==e.mode&&s===f.MOCK||null!==a&&e.mockConfig.mocks.size!==a.size,h=null!=i?i:e.mockConfig.strict,v=null!=s?s:e.mode,y=!!h!=!!e.mockConfig.strict,b=n;ne(e,b?{mode:v,mockConfig:{autoRecord:!1,strict:h,mocks:new Map}}:{mode:v,mockConfig:{strict:h,autoRecord:c,mocks:null!=a?a:e.mockConfig.mocks}}),setTimeout((()=>{var t;return e.log([d?[{text:`${g.RULES} ${Object.keys(null!==(t=e.config.mapping)&&void 0!==t?t:{}).length.toString().padStart(5)} loaded mapping rules`,color:m.INFO}]:null,p?[{text:`${h?g.STRICT_MOCKS:g.MOCKS} ${(null!=a?a:e.mockConfig.mocks).size.toString().padStart(5)} loaded mocks`,color:m.INFO}]:null,y?[{text:`${h?g.STRICT_MOCKS:g.MOCKS} mocks strict mode : ${null!=h?h:e.mockConfig.strict}`,color:m.INFO}]:null,u?[{text:`${v===f.PROXY?g.AUTO_RECORD:h?g.STRICT_MOCKS:g.MOCKS} mocks auto-record : ${c}`,color:m.INFO}]:null,d||p||u||y||b?e.buildQuickStatus():null].filter((e=>e)))}),1)};exports.recorderHandler=j;const P=(e,n,o,i,l,a,d,c,u)=>t(void 0,void 0,void 0,(function*(){const t={hostname:e.hostname,path:i,port:e.port?e.port:"https:"===e.protocol?443:80,protocol:e.protocol,rejectUnauthorized:!1,method:l.method,headers:Object.assign(Object.assign({},Object.assign({},...Object.entries(a).filter((([e])=>!e.startsWith(":")&&"transfer-encoding"!==e.toLowerCase())).map((([e,t])=>({[e]:t}))))),{host:e.hostname})};let p=null;const m=p||[...H].includes(e.protocol)?null:yield new Promise((i=>{const a="https:"===e.protocol?(0,s.request)(t,i):(0,r.request)(t,i);a.on("error",(e=>{p=Buffer.from(N(e,u,"request",n,o)),i(null)})),c&&(a.write(d),a.end()),c||(l.on("data",(e=>a.write(e))),l.on("end",(()=>a.end())))}));if(p)throw p;return{alpnProtocol:"HTTP1.1",error:null,data:null,hasRun:!1,events:{},on:function(e,t){return"response"===e?null==t?void 0:t(Object.assign(Object.assign({},m.headers),{":status":m.statusCode,":statusmessage":m.statusMessage})):m.on(e,t)},end:function(){return this},request:function(){return this},write:function(){return this}}})),A={logs:(e,t)=>K(`${J(128250,"logs","")}\n<nav class="navbar navbar-expand-lg navbar-dark bg-primary nav-fill">\n<div class="container-fluid">\n<ul class="navbar-nav">\n<li class="nav-item">\n<a class="nav-link active" aria-current="page" href="javascript:show(0)">Access</a>\n</li>\n<li class="nav-item">\n<a class="nav-link" href="javascript:show(1)">Proxy</a>\n</li>\n</ul>\n<span class="navbar-text">\nLimit : <select id="limit" onchange="javascript:cleanup()"><option value="-1">0 (clear)</option><option value="10">10</option>\n<option value="50">50</option><option value="100">100</option><option value="200">200</option>\n<option selected="selected" value="500">500</option><option value="0">Infinity (discouraged)</option>\n</select> rows\n</span>\n</div>\n</nav>\n${q(e,t.config,{captureResponseBody:!1})}\n</body></html>`),config:(e,t,n,o)=>{var r,s,i,l,a,d;if(["POST","PUT"].includes(n.method)){let e;try{e=JSON.parse(null!==(s=null===(r=null==o?void 0:o.requestBody)||void 0===r?void 0:r.toString("ascii"))&&void 0!==s?s:"{}")}catch(e){return setTimeout((()=>t.log([[{text:`${g.ERROR_4} config update could not be read`,color:m.WARNING}]])),1),K(`{"error":"config update could not be read","stack":"${null===(l=null===(i=e.stack)||void 0===i?void 0:i.replace)||void 0===l?void 0:l.call(i,/"/g,'\\"').replace(/[\s]+/g," ")}"}`,{contentType:"application/json; charset=utf-8"})}return K(new Promise((n=>{var o,r;null===(r=null===(o=t.configFileWatcher)||void 0===o?void 0:o.once)||void 0===r||r.call(o,"change",(()=>{setTimeout((()=>{n(Buffer.from(JSON.stringify(t.config)))}),10)})),ne(t,{pendingConfigSave:e})})),{contentType:"application/json; charset=utf-8"})}return["GET","HEAD"].includes(n.method)&&(null===(d=null===(a=n.headers)||void 0===a?void 0:a.accept)||void 0===d?void 0:d.includes("application/json"))?K(JSON.stringify(t.config),{contentType:"application/json; charset=utf-8"}):K(`${J(127899,"config","")}\n<link href="${D}jsoneditor/dist/jsoneditor.min.css" rel="stylesheet" type="text/css">\n<script src="${D}jsoneditor/dist/jsoneditor.min.js"><\/script>\n<script src="${D}node-forge/dist/forge.min.js"><\/script>\n<div id="ssl-modal" class="modal" tabindex="-1" role="dialog">\n<div class="modal-dialog" role="document">\n<div class="modal-content">\n<div class="modal-header">\n<h5 class="modal-title">SSL keypair generation in progress</h5>\n</div>\n<div class="modal-body">\n<p>Wait a few seconds or move your mouse to increase the entropy.</p>\n</div>\n</div>\n</div>\n</div>\n<div id="jsoneditor" style="width: 400px; height: 400px;"></div>\n<script>\nlet socket = null;\nconst container = document.getElementById("jsoneditor")\nconst options = {mode: "code", allowSchemaSuggestions: true, schema: {\ntype: "object",\nproperties: {\n${Object.entries(Object.assign(Object.assign({},U),{ssl:{cert:"",key:""}})).map((([e,t])=>`${e}: {type: ${"unwantedHeaderNamesInMocks"===e?'"array","items": {"type":"string"}':"number"==typeof t?'"integer"':"string"==typeof t?'"string"':"boolean"==typeof t?'"boolean"':'"object"'}}`)).join(",\n ")}\n},\nrequired: [],\nadditionalProperties: false\n}}\n\nfunction save() {\nif (!socket || socket.readyState !== 1) {\nfetch(window.location.href, {\nmethod: 'POST',\nheaders: {\n'Accept': 'application/json'\n},\nbody: JSON.stringify(editor.get())\n})\n} else socket.send(JSON.stringify(editor.get()));\n}\n\nfunction generateSslCertificate() {\nconst sslModal = new bootstrap.Modal(document.getElementById('ssl-modal'), {});\nsslModal.show()\nsetTimeout(function() {\nconst keypair = forge.pki.rsa.generateKeyPair(2048);\nconst certificate = forge.pki.createCertificate();\nconst now = new Date();\nconst fiveYears = new Date(new Date(now).setFullYear(now.getFullYear() + 5));\nObject.assign(certificate, {\npublicKey: keypair.publicKey,\nserialNumber: "01",\nvalidity: {\nnotBefore: now,\nnotAfter: fiveYears,\n},\n});\ncertificate.sign(keypair.privateKey, forge.md.sha256.create());\nconst key = forge.pki.privateKeyToPem(keypair.privateKey);\nconst cert = forge.pki.certificateToPem(certificate);\nconst existingConfig = editor.get();\neditor.set({ ...existingConfig, ssl: { key, cert },\nport: parseInt(("" + existingConfig.port).replace(/(80|[0-9])80$/, '443'))\n});\nsslModal.hide();\n}, 100);\n}\n\nconst editor = new JSONEditor(container, options);\nconst initialJson = ${JSON.stringify(t.config)}\neditor.set(initialJson)\neditor.validate();\neditor.aceEditor.commands.addCommand({\nname: 'save',\nbindKey: {win: 'Ctrl-S', mac: 'Command-S'},\nexec: save,\n});\nfunction startSocket() {\nif (socket != null) return;\nsocket = new WebSocket("ws${t.config.ssl?"s":""}://${e}/local-traffic-config");\nsocket.onmessage = function(event) {\neditor.set(JSON.parse(event.data))\neditor.validate()\n}\nsocket.onerror = function(error) {\nsocket = null;\nsetTimeout(startSocket, 1000);\nif (error.target.readyState === 3) {\nreturn;\n}\nthrow new Error(\`[error] \${JSON.stringify(error)}\`);\n};\nsocket.onclose = function(error) {\nsocket = null;\nsetTimeout(startSocket, 1000);\n};\n}\nwindow.addEventListener("DOMContentLoaded", function() {\ndocument.getElementById('jsoneditor').style.height =\n(document.documentElement.clientHeight - 150) + 'px';\ndocument.getElementById('jsoneditor').style.width =\nparseInt(window.getComputedStyle(\ndocument.querySelector('.container')).maxWidth) + 'px';\nconst sslButton = document.createElement('button');\nsslButton.addEventListener("click", generateSslCertificate);\nsslButton.type="button";\nsslButton.classList.add("btn");\nsslButton.classList.add("btn-primary");\nsslButton.innerHTML="&#x1F512;";\ndocument.querySelector('.jsoneditor-menu')\n.appendChild(sslButton);\nconst saveButton = document.createElement('button');\nsaveButton.addEventListener("click", save);\nsaveButton.type="button";\nsaveButton.classList.add("btn");\nsaveButton.classList.add("btn-primary");\nsaveButton.innerHTML="&#x1F4BE;";\ndocument.querySelector('.jsoneditor-menu')\n.appendChild(saveButton);\nstartSocket();\n});\n<\/script>\n</body></html>`)},recorder:(e,t,n)=>{var o,r,s,i,l,a,d,c,u,p;return(null===(o=n.url)||void 0===o?void 0:o.endsWith("?forceLogInRecorderPage=true"))?K('{"ping":"pong"}',{contentType:"application/json; charset=utf-8"}):"GET"===n.method&&(null===(s=null===(r=n.headers)||void 0===r?void 0:r.accept)||void 0===s?void 0:s.includes("application/json"))?K(JSON.stringify(Object.assign(Object.assign({},t.mockConfig),{mode:t.mode,mocks:[...t.mockConfig.mocks.entries()].map((([e,t])=>({uniqueHash:e,response:t})))})),{contentType:"application/json; charset=utf-8"}):["PUT","POST","DELETE"].includes(null!==(i=n.method)&&void 0!==i?i:"")?K('{"status": "acknowledged"}',{contentType:"application/json; charset=utf-8",onOutboundWrite:e=>j(t,e,"DELETE"===n.method)}):K(`${J(9210,"recorder","")}\n<link href="${D}jsoneditor/dist/jsoneditor.min.css" rel="stylesheet" type="text/css">\n<script src="${D}jsoneditor/dist/jsoneditor.min.js"><\/script>\n<script src="${D}pako/dist/pako.min.js"><\/script>\n<form>\n<div id="commands"${t.mockConfig.autoRecord?' style="filter:blur(8px)"':""}>\n<span>Mode : </span>\n<div class="btn-group" role="group" aria-label="Server Mode">\n<input type="radio" class="btn-check" name="server-mode" id="record-mode" autocomplete="off"${t.mode===f.PROXY?" checked":""}>\n<label class="btn btn-outline-primary" for="record-mode">&#9210; Record</label>\n<input type="radio" class="btn-check" name="server-mode" id="mock-mode" autocomplete="off"${t.mode===f.MOCK?" checked":""}>\n<label class="btn btn-outline-primary" for="mock-mode">&#x1F310; Mock</label>\n</div>\n<span>Actions : </span>\n<button type="button" class="btn btn-light" id="add-mock">&#x2795; Mock from dummy request</button>\n<button type="button" class="btn btn-light" id="upload-mocks">&#x1F4E5; Upload mocks</button>\n<button type="button" class="btn btn-light" id="download-mocks">&#x1F4E6; Download mocks</button>\n<button type="button" class="btn btn-light" id="delete-mocks">&#x1F5D1; Delete mocks</button>\n</div>\n<div class="row">\n<div class="col-lg" style="max-width: 200px">\n<div class="form-check form-switch" id="strict-mock-mode-form-control">\n<input class="form-check-input" type="checkbox" id="strict-mock-mode"${t.mockConfig.strict?' checked="checked"':""}>\n<label class="form-check-label" for="strict-mock-mode">Strict mock mode</label>\n</div>\n</div>\n<div class="col-lg" style="max-width: 200px">\n<div class="form-check form-switch">\n<input class="form-check-input" type="checkbox" id="auto-record-mode"${t.mockConfig.autoRecord?' checked="checked"':""}>\n<label class="form-check-label" for="auto-record-mode">Auto record mode</label>\n</div>\n</div>\n<div class="col-lg">&nbsp;</div>\n</div>\n<input type="hidden" id="limit" value="0"/>\n<div class="modal fade" id="edit-request" tabindex="-1" \naria-labelledby="edit-request-label" aria-hidden="true">\n<div class="modal-dialog" style="max-width: 900px">\n<div class="modal-content">\n<div class="modal-header">\n<h1 class="modal-title fs-5" id="edit-request-label">Edit request to /</h1>\n<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>\n</div>\n<div class="modal-body">\n<div class="container">\n<div class="row">\n<div class="col-lg">\n<h2>Request :</h2>\n<div id="uniqueHash-editor" style="width: 400px; height: 400px;"></div>\n</div>\n<div class="col-lg">\n<h2>Response : </h2>\n<div id="response-editor" style="width: 400px; height: 400px;"></div>\n</div>\n</div>\n</div>\n</div>\n<div class="modal-footer">\n<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>\n<button type="button" class="btn btn-primary" onclick="javascript:saveRequest()">Save changes</button>\n</div>\n</div>\n</div>\n</div>\n<script>\nconst xmlOrJsonPrologsInBase64 = [\n"eyJ","PD94bWw=","PCFET0NUWVBF","PCFkb2N0eXBl","PGh0bWw","PEhUTUw","H4sIAAAAAAAA", "W3tc"\n];\nfunction getMocksData () {\nreturn JSON.stringify(\n[...document.querySelectorAll('button[data-uniqueHash]')].map(button => ({\nresponse: button.attributes['data-response']?.value,\nuniqueHash: button.attributes['data-uniqueHash']?.value}))\n)\n}\nfunction updateState () {\nfetch("http${t.config.ssl?"s":""}://${e}${null!==(d=null===(a=Object.entries(null!==(l=t.config.mapping)&&void 0!==l?l:{}).find((([e,t])=>{var n;return null===(n=null==t?void 0:t.toString())||void 0===n?void 0:n.startsWith("recorder:")})))||void 0===a?void 0:a[0])&&void 0!==d?d:"/recorder/"}", {\nmethod: 'PUT',\nheaders: { 'Content-Type': 'application/json' },\nbody: '{"strict":' + document.getElementById('strict-mock-mode').checked +\n',"autoRecord":' + document.getElementById('auto-record-mode').checked +\n',"mode":"' + \n(document.getElementById('mock-mode').checked ? "mock" : "proxy") + '"' +\n',"mocks":' + getMocksData() + '}'\n})\n}\nfunction loadMocks(mocksHashes) {\nconst time = new Date().toISOString().split('T')[1].replace('Z', '');\nlet mocks = [];\ntry {\nmocks = mocksHashes.map(mock => ({...mock, \nrequest: JSON.parse(atob(mock.uniqueHash)),\nresponse: JSON.parse(atob(mock.response))\n}));\n} catch(e) { }\nmocks.forEach(mock => {\nconst randomId = window.crypto.randomUUID();\nconst actions = getActionsHtmlText(mock.uniqueHash, mock.response);\naddNewRequest(randomId, actions, time, 'info', 'HTTP/2', mock.request.method, \n'<span class="badge bg-' + \ngetColorFromStatusCode(mock.response.status) + '">' + \nmock.response.status + \n'</span>', \n'0ms', mock.request.url, \n'N/A');\n});\n}\ndocument.getElementById('add-mock').addEventListener('click', () => {\nconst iframe = document.createElement('iframe');\niframe.style.display = 'none';\niframe.onload = function() { iframe.parentNode.removeChild(iframe); };\niframe.src = "http${t.config.ssl?"s":""}://${e}${null!==(p=null===(u=Object.entries(null!==(c=t.config.mapping)&&void 0!==c?c:{}).find((([e,t])=>{var n;return null===(n=null==t?void 0:t.toString())||void 0===n?void 0:n.startsWith("recorder:")})))||void 0===u?void 0:u[0])&&void 0!==p?p:"/recorder/"}?forceLogInRecorderPage=true";\ndocument.body.appendChild(iframe);\n});\ndocument.getElementById('upload-mocks').addEventListener('click', () => {\nconst time = new Date().toISOString().split('T')[1].replace('Z', '');\nconst fileInput = document.createElement('input');\nfileInput.type = "file";\nfileInput.multiple = "multiple";\nfileInput.onchange = function() {\nconst fileReader = new FileReader();\n[...fileInput.files].reduce((promise, file) =>\npromise.then(result => new Promise(resolve => {\nfileReader.readAsText(file);\nfileReader.onload = function(){\nresolve(result.concat(fileReader.result));\n};\n})), Promise.resolve([]))\n.then(files => files.flatMap(file => JSON.parse(file)))\n.catch(e => [])\n.then(mocks => loadMocks(mocks))\n.then(() => updateState());\n}\nfileInput.click();\n});\ndocument.getElementById('download-mocks').addEventListener('click', () => {\nconst link = document.createElement('a');\nlink.href = URL.createObjectURL(new Blob([getMocksData()], {\ntype: "application/json",\n}));\nlink.download = "mocks-" + new Date().toISOString() + ".json";\nlink.click();\nURL.revokeObjectURL(link.href);\n})\ndocument.getElementById('delete-mocks').addEventListener('click', () => {\ndocument.getElementById('limit').value = -1;\ncleanup();\nupdateState();\ndocument.getElementById('limit').value = 0;\n})\ndocument.getElementById('record-mode').addEventListener('change', () => {\ndocument.getElementById('limit').value = 0;\ncleanup();\nupdateState();\n})\ndocument.getElementById('mock-mode').addEventListener('change', () => {\nupdateState();\n})\ndocument.getElementById('auto-record-mode').addEventListener('change', (e) => { \nupdateState();\ndocument.getElementById('table-access').style.filter = \ndocument.getElementById('auto-record-mode').checked ? 'blur(8px)' : 'blur(0px)';\ndocument.getElementById('commands').style.filter = \ndocument.getElementById('auto-record-mode').checked ? 'blur(8px)' : 'blur(0px)';\ndocument.getElementById('alert-about-auto-record-mode').style.display = \ndocument.getElementById('auto-record-mode').checked ? 'block' : 'none';\ndocument.getElementById('strict-mock-mode-form-control').style.filter = \ndocument.getElementById('auto-record-mode').checked ? 'blur(8px)' : 'blur(0px)';\n\n})\ndocument.getElementById('strict-mock-mode').addEventListener('change', (e) => { \nupdateState();\n})\nfunction saveRequest () {\n$('#edit-request').modal("hide");\n\nconst requestBeingEdited = window.requestBeingEdited;\nlet request = uniqueHashEditor.get();\nlet response = responseEditor.get();\nif (typeof request.body === "object") {\nrequest.body = JSON.stringify(request.body);\n}\nif (typeof response.body === "object") {\nresponse.body = JSON.stringify(response.body);\n}\nconst oldRequest = JSON.parse(atob(requestBeingEdited.attributes['data-uniqueHash'].value));\nconst oldResponse = JSON.parse(atob(requestBeingEdited.attributes['data-response'].value));\nconst requestProlog = requestBeingEdited.attributes['data-requestProlog']?.value;\nconst responseProlog = requestBeingEdited.attributes['data-responseProlog']?.value;\nconst requestPrologHasChanged = request.body.substring(0, 10) !== oldRequest.body.substring(0, 10);\nconst responsePrologHasChanged = response.body.substring(0, 10) !== response.body.substring(0, 10);\nif (requestProlog === "H4sIAAAAAAAA" && !requestPrologHasChanged) {\nrequest.body =\nbtoa([...pako.gzip(request.body)].map(e => String.fromCharCode(e)).join(""));\n} else if ((requestProlog === null || !request.body.startsWith(requestProlog ?? "")) && \nrequest.body.substring(0, 10) !== oldRequest.body.substring(0, 10)) {\nrequest.body = btoa(request.body);\n}\nif (responseProlog === "H4sIAAAAAAAA" && !responsePrologHasChanged) {\nresponse.body =\nbtoa([...pako.gzip(response.body)].map(e => String.fromCharCode(e)).join(""));\n} else if ((responseProlog === null || !response.body.startsWith(responseProlog ?? "")) && \nresponse.body.substring(0, 10) !== oldResponse.body.substring(0, 10)) {\nresponse.body = btoa(response.body);\n}\nrequest = btoa(JSON.stringify(request));\nresponse = btoa(JSON.stringify(response));\nrequestBeingEdited.setAttribute('data-uniqueHash', request);\nrequestBeingEdited.setAttribute('data-response', response);\nconst row = requestBeingEdited.closest('tr');\nrow.querySelector("td.method").innerHTML = uniqueHashEditor.get().method;\nrow.querySelector("td.upstream-path").innerHTML = uniqueHashEditor.get().url;\nwindow.requestBeingEdited = undefined;\nupdateState();\n}\ndocument.getElementById('edit-request').addEventListener('show.bs.modal', event => {\nconst request = JSON.parse(atob(event.relatedTarget.attributes['data-uniqueHash'].value));\nconst response = JSON.parse(atob(event.relatedTarget.attributes['data-response'].value));\nconst requestProlog = xmlOrJsonPrologsInBase64.find(prolog => request.body?.startsWith(prolog));\nconst responseProlog = xmlOrJsonPrologsInBase64.find(prolog => response.body?.startsWith(prolog));\nif (requestProlog) {\nevent.relatedTarget.setAttribute('data-requestProlog', requestProlog);\nrequest.body = request.body.startsWith("H4sIAAAAAAAA") \n? pako.ungzip(new Uint8Array(atob(request.body).split("").map(e => e.charCodeAt(0))), {to: "string"})\n: atob(request.body);\nrequest.body = request.body.startsWith("{\\"") || request.body.startsWith("[{\\"")\n? JSON.parse(request.body) : request.body;\n}\nif (responseProlog) {\nevent.relatedTarget.setAttribute('data-responseProlog', responseProlog);\nresponse.body = response.body.startsWith("H4sIAAAAAAAA") \n? pako.ungzip(new Uint8Array(atob(response.body).split("").map(e => e.charCodeAt(0))), {to: "string"})\n: atob(response.body);\nresponse.body = response.body.startsWith("{\\"") || response.body.startsWith("[{\\"")\n? JSON.parse(response.body) : response.body;\n}\nwindow.requestBeingEdited = event.relatedTarget;\nwindow.uniqueHashEditor.set(request);\nwindow.responseEditor.set(response);\ndocument.getElementById('edit-request-label').innerText = "Edit request to " + request.url;\n})\n\nsetTimeout(() => {\nloadMocks(${JSON.stringify([...t.mockConfig.mocks.entries()].map((([e,t])=>({uniqueHash:e,response:t}))))});\nwindow.uniqueHashEditor = new JSONEditor(document.getElementById("uniqueHash-editor"), {\nmode: "code", allowSchemaSuggestions: true, schema: {\ntype: "object",\nproperties: {\nmethod: {type: "string"},\nurl: {type: "string"},\nbody: {oneOf: [{type:"string"},{type:"object"},{type:"array"}]},\nheaders: {type: "object"},\n},\nrequired: [],\nadditionalProperties: false\n}});\nwindow.responseEditor = new JSONEditor(document.getElementById("response-editor"), {\nmode: "code", allowSchemaSuggestions: true, schema: {\ntype: "object",\nproperties: {\nbody: {oneOf: [{type:"string"},{type:"object"},{type:"array"}]},\nheaders: {type: "object"},\nstatus: {type: "integer"}\n},\nrequired: [],\nadditionalProperties: false\n}});\n${t.mockConfig.autoRecord?";document.getElementById('strict-mock-mode-form-control').style.filter='blur(8px)';;document.getElementById('table-access').style.filter='blur(8px)';":""}\ndocument.forms[0].reset();\n}, 10)\n<\/script>\n</form>\n<div class="alert alert-warning" role="alert"\nstyle="display:${t.mockConfig.autoRecord?"block":"none"};left:20%;right:20%;position:absolute;z-index:1;" id="alert-about-auto-record-mode">\n&#x24D8;&nbsp;Auto-record mode and recorder webapp are known to be mutually exclusive.\n<br/><br/>Changing the mocks on both sides is somehow hard to sort out.\n<br/>This is triggering concurrent modifications in the mock config.\n<hr/>\nHere is what you can do :\n<ul>\n<li>If you want to record mocks using a frontend app, turn off the auto-record mode.</li>\n<li>If you want to record mocks with the recorder API only, close this app.</li>\n</ul>\n</div>\n${q(e,t.config,{captureResponseBody:!0})}\n</body>\n</html>`)},file:(e,t,n,o)=>{const r=null==o?void 0:o.target,s=(0,d.resolve)("/",r.hostname,...r.pathname.replace(/[?#].*$/,"").replace(/^\/+/,"").split("/").map(decodeURIComponent));return{alpnProtocol:"file",error:null,data:null,hasRun:!1,run:function(){return this.hasRun?Promise.resolve():new Promise((e=>(0,l.readFile)(s,((t,n)=>{if(this.hasRun=!0,!t||"EISDIR"!==t.code)return this.error=t,this.data=n,void e(void 0);(0,l.readdir)(s,((t,n)=>{this.error=t,this.data=n,t?e(void 0):Promise.all(n.map((e=>new Promise((t=>(0,l.lstat)((0,d.resolve)(r.pathname,e),((n,o)=>t([e,o,n])))))))).then((t=>{const n=t.filter((e=>!e[2]&&e[1].isDirectory())).concat(t.filter((e=>!e[2]&&e[1].isFile())));this.data=`${J(128194,"directory",r.href)}<p>Directory content of <i>${r.href.replace(/\//g,"&#x002F;")}</i></p><ul class="list-group"><li class="list-group-item">&#x1F4C1;<a href="${r.pathname.endsWith("/")?"..":"."}">&lt;parent&gt;</a></li>${n.filter((e=>!e[2])).map((e=>`<li class="list-group-item">&#x${(e[1].isDirectory()?128193:128196).toString(16)};<a href="${r.pathname.endsWith("/")?"":`${r.pathname.split("/").slice(-1)[0]}/`}${e[0]}">${e[0]}</a></li>`)).join("\n")}</li></ul></body></html>`,e(void 0)}))}))}))))},events:{},on:function(e,t){return this.events[e]=t,this.run().then((()=>{"response"===e&&this.events.response(s.endsWith(".svg")?{Server:"local","Content-Type":"image/svg+xml"}:{Server:"local"},0),"data"===e&&this.data&&(this.events.data(this.data),this.events.end()),"error"===e&&this.error&&this.events.error(this.error)})),this},end:function(){return this},request:function(){return this},write:function(){return this}}},data:(e,t,n,o)=>{var r,s,i,l,a,d;const[,c,u,p]=null!==(s=/^data:([^;,]*)?;?([^,]*)?,(.*)$/.exec(null!==(r=null==o?void 0:o.target.href)&&void 0!==r?r:"data:,"))&&void 0!==s?s:["","","",""],m=decodeURIComponent(p),g="base64"===u?Buffer.from(m,"base64url").toString("binary"):m;return K(t.config.replaceResponseBodyUrls?z(Buffer.from(g),{"content-type":c||"text/plain"},{mapping:null!==(i=t.config.mapping)&&void 0!==i?i:{},proxyHostnameAndPort:e,proxyHostname:null!==(l=null==o?void 0:o.proxyHostname)&&void 0!==l?l:"localhost",key:null!==(a=null==o?void 0:o.key)&&void 0!==a?a:"",direction:h.INBOUND,ssl:!!t.config.ssl,port:null!==(d=t.config.port)&&void 0!==d?d:null==U?void 0:U.port}):g,{contentType:c})}},L=Object.keys(A),H=L.map((e=>`${e}:`)),U={mapping:Object.assign({},...L.filter((e=>"data"!==e&&"file"!==e)).map((e=>({[`/${e}/`]:`${e}://`})))),port:8080,replaceRequestBodyUrls:!1,replaceResponseBodyUrls:!1,dontUseHttp2Downstream:!1,dontTranslateLocationHeader:!1,logAccessInTerminal:!1,simpleLogs:!1,websocket:!0,disableWebSecurity:!1,connectTimeout:3e3,socketTimeout:3e3,unwantedHeaderNamesInMocks:[]},M=(...e)=>t(void 0,[...e],void 0,(function*(e=!0){return new Promise((t=>(0,l.readFile)(b,((n,o)=>{if(n&&(R(null,[[{text:`${g.ERROR_1} config error. Using previous value`,color:m.ERROR}]]).then((()=>t(Object.assign({},U)))),"ENOENT"!==n.code))return;let r=null;try{r=Object.assign({},U,JSON.parse((null!=o?o:"{}").toString()))}catch(e){return r=null!=r?r:Object.assign({},U),R({config:void 0},[[{text:`${g.ERROR_2} config syntax incorrect, ignoring`,color:m.ERROR}]]).then((()=>t(r)))}"ENOENT"===(null==n?void 0:n.code)&&e?(0,l.writeFile)(b,JSON.stringify(U,null,2),(e=>R(null,e?[[{text:`${g.ERROR_4} config file NOT created`,color:m.ERROR}]]:[[{text:`${g.COLORED} config file created`,color:m.INFO}]]).then((()=>t(r))))):t(r)})))).then((e=>t(void 0,void 0,void 0,(function*(){return e?yield Promise.all(Object.entries(e.mapping).map((([e,t])=>new Promise((n=>{const o="string"==typeof t?null:t.replaceBody,r="string"==typeof t?t:t.downstreamUrl;if(!r.startsWith("file:")||e.endsWith("(.*)"))return n([e,t]);const s=r.split("").map(((e,t)=>e+r.charAt(t+1))).filter((e=>"$$"===e)).length;return(0,l.lstat)(new i.URL(r.replace(/\$\$[0-9]+/g,"")).pathname,((i,l)=>{if(i)return n([e,t]);const a=l.isDirectory(),c=a?`${null==e?void 0:e.replace(/\/*$/g,"")}/(.*)`:e,u=a?`${null==o?void 0:o.replace(/\/*$/g,"")}/$$${s+1}`:o,p=a?`${r.replace(/\/*$/g,"")}${d.sep}$$${s+1}`:r;return n(o?[c,{replaceBody:u,downstreamUrl:p}]:[c,p])}))}))))).then((t=>Object.assign(Object.assign({},e),{mapping:Object.fromEntries(t)}))):e}))))}));exports.load=M;const W=e=>""==e?"":(0,d.normalize)(e).replace(/\\/g,"/"),D="https://cdn.jsdelivr.net/npm/",F=["host","connection","keep-alive","upgrade","transfer-encoding","upgrade-insecure-requests","proxy-connection"],J=(e,t,n)=>`<!doctype html>\n<html lang="en">\n<head>\n<title>&#x${e.toString(16)}; local-traffic ${t} | ${n}</title>\n<link href="${D}bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"/>\n<script src="${D}jquery/dist/jquery.min.js"><\/script>\n<script src="${D}bootstrap/dist/js/bootstrap.bundle.min.js"><\/script>\n</head>\n<body><div class="container"><h1>&#x${e.toString(16)}; local-traffic ${t}</h1>\n<br/>`,_=({response:e})=>({alpnProtocol:"mock",error:null,data:null,hasRun:!1,run:function(){return this.hasRun?Promise.resolve():new Promise((t=>{try{this.data=JSON.parse(Buffer.from(e,"base64").toString("utf-8"))}catch(e){this.data={}}t(void 0)}))},events:{},on:function(e,t){return this.events[e]=t,this.run().then((()=>{var t;"response"===e&&this.events.response(Object.assign(Object.assign({},this.data.headers),{"X-LocalTraffic-Mock":"1"}),this.data.status),"data"===e&&this.data&&(this.events.data(Buffer.from(null!==(t=this.data.body)&&void 0!==t?t:"","base64")),this.events.end()),"error"===e&&this.error&&this.events.error(this.error)})),this},end:function(){return this},request:function(){return this},write:function(){return this}}),K=(e,t)=>({alpnProtocol:"static",error:null,data:null,outboundData:null,run:function(){return"string"==typeof e?new Promise((t=>{this.data=e,t(void 0)})):e.then((e=>{this.data=e.toString("utf8")}))},events:{},on:function(e,n){return this.events[e]=n,this.run().then((()=>{var n;"response"===e&&this.events.response({Server:"local","Content-Type":null!==(n=null==t?void 0:t.contentType)&&void 0!==n?n:"text/html"},0),"data"===e&&this.data&&(this.events.data(this.data),this.events.end()),"error"===e&&this.error&&this.events.error(this.error)})),this},write:function(e){var n;return this.outboundData=e,e instanceof Buffer&&(null===(n=null==t?void 0:t.onOutboundWrite)||void 0===n||n.call(t,e)),this},end:function(){return this},request:function(){return this}}),z=(e,n,o)=>t(void 0,void 0,void 0,(function*(){var r,s;return(null!==(s=null===(r=n["content-encoding"])||void 0===r?void 0:r.toString())&&void 0!==s?s:"").split(",").reduce(((e,n)=>t(void 0,void 0,void 0,(function*(){const t=n.trim().toLowerCase(),o="gzip"===t||"x-gzip"===t?a.gunzip:"deflate"===t?a.inflate:"br"===t?a.brotliDecompress:"identity"===t||""===t?(e,t)=>{t(null,e)}:null;if(null===o)throw new Error(`${t} compression not supported by the proxy`);const r=yield e;return yield new Promise(((e,t)=>o(r,((n,o)=>{n&&t(n),e(o)}))))}))),Promise.resolve(e)).then((e=>{const t=e.length>1e7,r=["text/html","application/javascript","application/json"].some((e=>{var t;return(null!==(t=n["content-type"])&&void 0!==t?t:"").toString().includes(e)}));return!t&&(r||!/[^\x00-\xFF]/.test(e.toString()))?G(e.toString(),{direction:o.direction,proxyHostnameAndPort:o.proxyHostnameAndPort,ssl:o.ssl,mapping:o.mapping}).replace(/\?protocol=wss?%3A&hostname=[^&]+&port=[0-9]+&pathname=/g,`?protocol=ws${o.ssl?"s":""}%3A&hostname=${o.proxyHostname}&port=${o.port}&pathname=${encodeURIComponent(o.key.replace(/\/+$/,""))}`):e})).then((e=>{var t,o;return(null!==(o=null===(t=n["content-encoding"])||void 0===t?void 0:t.toString())&&void 0!==o?o:"").split(",").reverse().reduce(((e,t)=>{const n=t.trim().toLowerCase(),o="gzip"===n||"x-gzip"===n?a.gzip:"deflate"===n?a.deflate:"br"===n?a.brotliCompress:"identity"===n||""===n?(e,t)=>{t(null,e)}:null;if(null===o)throw new Error(`${n} compression not supported by the proxy`);return e.then((e=>new Promise((t=>o(e,((e,n)=>{if(e)throw e;t(n)}))))))}),Promise.resolve(Buffer.from(e)))}))}));exports.replaceBody=z;const G=(e,{direction:t,proxyHostnameAndPort:n,ssl:o,mapping:r})=>Object.entries(r).map((([e,t])=>[e,"string"==typeof t?t:t.replaceBody])).reduce(((e,[r,s])=>{const i=r.split("").filter((e=>["(",")"].includes(e))).join("").match(/^(\(\))*$/)?r.split("(").flatMap((e=>e.split(")"))).filter(((e,t)=>t%2==1)):[];let l=0;return H.some((e=>s.startsWith(e)))||""!==r&&!r.match(/^[-a-zA-Z0-9()@:%_\+.~#?&//=]*$/)&&!i.length?e:t===h.INBOUND?e.replace(new RegExp(s.replace(new RegExp(`^(${L.join("|")})://`),"").replace(/\$\$(\d+)/g,((e,t)=>{var n;return"("+(null!==(n=i[parseInt(t)-1])&&void 0!==n?n:"")+")"})).replace(/\.\*/g,"[-a-zA-Z0-9()@:%_+.~#?&//=]*").replace(i.length?"":/[*+?^${}()|[\]\\]/g,"").replace(/^https/,"https?")+(i.length?"":"/*"),"ig"),`http${o?"s":""}://${n}${r.replace(/\([^)]+\)/g,(()=>"$"+ ++l)).replace(/\/+$/,"/").replace(/^(?![^/])$/,"/")}`):e.split(`http${o?"s":""}://${n}${r.replace(/\/+$/,"").replace(/^(?![^/])$/,"/")}`).join(s)}),e).split(`${n}/:`).join(`${n}:`);exports.replaceTextUsingMapping=G;const Y=(e,t)=>{try{const n="object"==typeof t?t:JSON.parse(Buffer.from(t,"base64").toString("utf-8"));return["access-control-max-age","authorization","cache-control","cookie","date","dnt","expires","if-modified-since","if-unmodified-since","keep-alive","last-modified","pragma","proxy-authenticate","proxy-authorization","referer","retry-after","signed-headers","server-timing","sec-ch-ua","sec-ch-ua-mobile","sec-ch-ua-platform","sec-fetch-dest","sec-fetch-mode","sec-fetch-site","sec-fetch-user","upgrade-insecure-requests","user-agent",...Array.isArray(e.unwantedHeaderNamesInMocks)?e.unwantedHeaderNamesInMocks:[]].forEach((e=>{var t;null===(t=null==n?void 0:n.headers)||void 0===t||delete t[e]})),n.headers=Object.keys(n.headers).sort().reduce(((e,t)=>(e[t]=n.headers[t],e)),{}),Buffer.from(JSON.stringify(n),"utf-8").toString("base64")}catch(e){return t}};exports.cleanEntropy=Y;const X=(e,t,n)=>{t.writeHead(e,{"content-type":"text/html","content-length":n.length}),t.end(n)};exports.send=X;const Z=(e,t)=>{var n,o,r,s,l,a,d,c;const u=(null!==(r=null!==(o=null===(n=e.headers[":authority"])||void 0===n?void 0:n.toString())&&void 0!==o?o:e.headers.host)&&void 0!==r?r:"localhost").replace(/:.*/,""),p=e.headers[":authority"]||`${e.headers.host}${(null!==(s=e.headers.host)&&void 0!==s?s:"").match(/:[0-9]+$/)?"":80!==t.port||t.ssl?443===t.port&&t.ssl?"":`:${null!==(l=t.port)&&void 0!==l?l:8080}`:""}`,m=new i.URL(`http${t.ssl?"s":""}://${p}${null!==(a=e.url)&&void 0!==a?a:""}`),g=m.href.substring(m.origin.length),h=Object.assign({},Object.assign({},...Object.entries(null!==(d=t.mapping)&&void 0!==d?d:{}).map((([e,t])=>{var n,o,r;const s="string"==typeof t?t:null!==(n=null==t?void 0:t.downstreamUrl)&&void 0!==n?n:"",l="string"==typeof t?e:null!==(o=null==t?void 0:t.replaceBody)&&void 0!==o?o:"",a=new i.URL((null===(r=null==s?void 0:s.startsWith)||void 0===r?void 0:r.call(s,"data:"))?s:W(s));return{[l]:a,[e]:a}}))));let f=null;const[v,y]=null!==(c=Object.entries(h).find((([e])=>{var t;return f=null!==(t=g.match(RegExp(e.replace(/^\//,"^/"))))&&void 0!==t?t:null})))&&void 0!==c?c:["/"],b=f&&y?new i.URL(y.href.replace(/\$\$(\d+)/g,((e,t)=>{var n;return null!==(n=f[parseInt(t)])&&void 0!==n?n:""}))):null;return{proxyHostname:u,proxyHostnameAndPort:p,url:m,path:g,key:v,target:b}};exports.determineMapping=Z;const Q=function(e,t,n){var o,l,a,d,c,u,p,h,f,v;if(n.on("error",(()=>{e.log([[{text:`${g.WEBSOCKET} websocket connection reset`,color:m.WARNING}]])})),!e.config.websocket)return n.end("HTTP/1.1 503 Service Unavailable\r\n\r\n"),{};const{key:y,target:b,path:k,url:O}=Z(t,e.config);if(k.startsWith("/local-traffic-logs"))return S(n,null!==(o=t.headers["sec-websocket-key"])&&void 0!==o?o:""),{logsListeners:e.logsListeners.concat({stream:n,wantsMask:!(null!==(a=null===(l=t.headers["user-agent"])||void 0===l?void 0:l.toString())&&void 0!==a?a:"").includes("Chrome"),wantsResponseMessage:[...O.searchParams.entries()].some((([e,t])=>"wantsResponseMessage"===e&&"true"===t))})};if("/local-traffic-config"===k){S(n,null!==(d=t.headers["sec-websocket-key"])&&void 0!==d?d:"");let o=null;return n.on("data",(t=>{const n=E(t,o);if(null===o&&n.body.length<n.payloadLength)o=n;else{if(n.body.length>=n.payloadLength&&0===n.body.length)return{};if(n.body.length>=n.payloadLength){let t;o=null;try{t=JSON.parse(n.body)}catch(t){return e.log([[{text:`${g.ERROR_4} config file NOT read, try again later`,color:m.WARNING}]]),{}}ne(e,{pendingConfigSave:t})}}})),{configListeners:e.configListeners.concat({stream:n,wantsMask:!(null!==(u=null===(c=t.headers["user-agent"])||void 0===c?void 0:c.toString())&&void 0!==u?u:"").includes("Chrome")})}}const w=new i.URL(`${null!==(p=null==b?void 0:b.protocol)&&void 0!==p?p:"https"}//${null!==(h=null==b?void 0:b.host)&&void 0!==h?h:"localhost"}${null===(v=null===(f=t.url)||void 0===f?void 0:f.replace(new RegExp(`^${y}`,"g"),b.pathname))||void 0===v?void 0:v.replace(/^\/*/,"/")}`),R={hostname:w.hostname,path:w.pathname,port:w.port,protocol:w.protocol,rejectUnauthorized:!1,method:t.method,headers:Object.assign(Object.assign({},t.headers),{host:w.hostname,origin:w.origin}),host:w.hostname},$="https:"===w.protocol?(0,s.request)(R):(0,r.request)(R);return $.end(),$.on("error",(t=>{e.log([[{text:`${g.WEBSOCKET} websocket request has errored ${t.errno?`(${t.errno})`:""}`,color:m.WARNING}]])})),$.on("upgrade",((t,o)=>{const r=`HTTP/${t.httpVersion} ${t.statusCode} ${t.statusMessage}\r\n${Object.entries(t.headers).flatMap((([e,t])=>(Array.isArray(t)?t:[t]).map((t=>[e,t])))).map((([e,t])=>`${e}: ${t}\r\n`)).join("")}\r\n`;n.write(r),n.allowHalfOpen=!0,o.allowHalfOpen=!0,o.on("data",(e=>n.write(e))),n.on("data",(e=>o.write(e))),o.on("error",(t=>{e.log([[{text:`${g.WEBSOCKET} downstream socket has errored ${t.errno?`(${t.errno})`:""}`,color:m.WARNING}]])})),n.on("error",(t=>{e.log([[{text:`${g.WEBSOCKET} upstream socket has errored ${t.errno?`(${t.errno})`:""}`,color:m.WARNING}]])}))})),{}};exports.websocketServe=Q;const V=function(e,n,r){return t(this,void 0,void 0,(function*(){var s,l,a,d,p,v,y,k,w,R,$,E,S,x,C,B,I,T,q,j,L,M,D,J,K,Q,V,ee,te,ne,oe;if(!n.headers.host&&!n.headers[":authority"])return void X(400,r,Buffer.from(N(new Error("client must supply a 'host' header"),e.mode,"proxy",new i.URL(`http${e.config.ssl?"s":""}://unknowndomain${n.url}`))));const{proxyHostname:re,proxyHostnameAndPort:se,url:ie,path:le,key:ae,target:de}=Z(n,e.config),ce=null!=de?de:e.mode===f.MOCK?new i.URL(`http${e.config.ssl?"s":""}://${se}/`):null;if(!ce)return void X(502,r,Buffer.from(N(new Error(`No mapping found in config file ${b}`),e.mode,"proxy",ie)));const ue="data:"===ce.protocol?"":"//",pe=ce.host.replace(RegExp(/\/+$/),""),me=ce.href.substring(`${ce.protocol}${ue}`.length+ce.host.length),ge="file:"===ce.protocol||"data:"===ce.protocol?me:`${me}${W(le.replace(RegExp(W(ae)),""))}`.replace(/^\/*/,"data:"===ce.protocol?"":"/"),he=new i.URL(`${ce.protocol}${ue}${pe}${ge}`),fe=H.some((e=>ce.protocol===e)),ve=(0,c.randomBytes)(20).toString("hex");let ye=null;const be=e.config.replaceRequestBodyUrls||!!e.logsListeners.length;e.config.ssl&&(yield new Promise((e=>setTimeout(e,1))));const ke=parseInt(null!==(s=n.headers["content-length"])&&void 0!==s?s:"0")>0,Oe=!!(null==n?void 0:n.readableLength)||ke,we=!!(null==n?void 0:n.stream)&&ke,Re=!!(null===(a=null===(l=n.headers)||void 0===l?void 0:l.accept)||void 0===a?void 0:a.includes("text/event-stream")),$e=!((e.config.ssl&&!1===we||!e.config.ssl&&!1===Oe)&&("0"===n.headers["content-length"]||void 0===n.headers["content-length"]));if(be){const t=null!==(d=null==n?void 0:n.stream)&&void 0!==d?d:n;let o=Buffer.from([]);yield Promise.race([new Promise((t=>setTimeout(t,e.config.connectTimeout))),new Promise((e=>{$e?(t.on("data",(e=>{o=Buffer.concat([o,e])})),t.on("end",e),t.on("error",e)):e(void 0)}))]),$e&&!o.length&&(yield e.log([[{text:`${g.ERROR_4} body replacement error ${le.slice(-17)}`,color:m.WARNING}]])),ye=e.config.replaceRequestBodyUrls?yield z(o,n.headers,{proxyHostnameAndPort:se,proxyHostname:re,key:ae,mapping:null!==(p=e.config.mapping)&&void 0!==p?p:{},port:null!==(v=e.config.port)&&void 0!==v?v:U.port,ssl:!!e.config.ssl,direction:h.OUTBOUND}):o}const Ee=e.logsListeners.some((e=>e.wantsResponseMessage)),Se=e.mockConfig.autoRecord&&e.mode===f.PROXY,xe=Y(e.config,{method:null!==(y=n.method)&&void 0!==y?y:"GET",url:null!==(k=n.url)&&void 0!==k?k:"",headers:Object.assign({},...Object.entries(n.headers).filter((([e])=>!e.startsWith(":"))).map((([e,t])=>({[e]:t})))),body:(e.mode===f.MOCK||Ee||Se)&&null!==(w=null==ye?void 0:ye.toString("base64"))&&void 0!==w?w:""});e.config.logAccessInTerminal&&!he.pathname.startsWith("/:/")&&(yield e.log([[{color:"GET"===n.method?22:"POST"===n.method?52:"PUT"===n.method?94:"DELETE"===n.method?244:"OPTIONS"===n.method?19:"PATCH"===n.method?162:"HEAD"===n.method?53:"TRACE"===n.method?6:"CONNECT"===n.method?2:0,text:(null!==(R=n.method)&&void 0!==R?R:"GET").toString(),length:null===($=n.method)||void 0===$?void 0:$.length},{color:8,text:he.pathname.toString().padStart(62-(null!==(S=null===(E=n.method)||void 0===E?void 0:E.length)&&void 0!==S?S:3)).substring(0,62-(null!==(C=null===(x=n.method)||void 0===x?void 0:x.length)&&void 0!==C?C:3)),length:62-(null!==(I=null===(B=n.method)||void 0===B?void 0:B.length)&&void 0!==I?I:3)}]]));const Ce=e.mode===f.MOCK&&!fe,Be=Ce?null!==(T=e.mockConfig.mocks.get(xe))&&void 0!==T?T:null===(q=Array.from(e.mockConfig.mocks.entries()).filter((([t])=>{var n;const o=JSON.parse(Buffer.from(xe,"base64").toString("ascii")),r=JSON.parse(Buffer.from(t,"base64").toString("ascii"));return r.method===o.method&&r.url===o.url&&(!r.body||r.body===o.body)&&Object.entries(null!==(n=r.headers)&&void 0!==n?n:{}).every((([t,n])=>{var r,s,i,l;return!n||(null===(i=null===(s=null===(r=e.config)||void 0===r?void 0:r.unwantedHeaderNamesInMocks)||void 0===s?void 0:s.includes)||void 0===i?void 0:i.call(s,t))||(null===(l=o.headers)||void 0===l?void 0:l[t])===n}))})).sort((([e],[t])=>{var n,o;const r=JSON.parse(Buffer.from(t,"base64").toString("ascii")),s=JSON.parse(Buffer.from(e,"base64").toString("ascii")),i=r.body?1:0,l=s.body?1:0;return Object.keys(null!==(n=r.headers)&&void 0!==n?n:{}).length+i-Object.keys(null!==(o=s.headers)&&void 0!==o?o:{}).length-l}))[0])||void 0===q?void 0:q[1]:null;if(Ce&&!Be&&e.mockConfig.strict)return void X(502,r,Buffer.from(N(new Error("No corresponding mock found in the server. \nTry switching back to the proxy mode"),e.mode,"mock",ie)));let Ie=null;const Te=O(),Ne=Object.assign(Object.assign({},[...Object.entries(n.headers)].filter((([e])=>!F.includes(e.toLowerCase()))).reduce(((e,[t,n])=>(e[t]=(e[t]||"")+(Array.isArray(n)?n:[n]).map((e=>null==e?void 0:e.replace(ie.hostname,pe))).join(", "),e)),{})),{origin:ce.href,referer:he.toString(),"content-length":null!==(L=null!==(j=null==ye?void 0:ye.length)&&void 0!==j?j:n.headers["content-length"])&&void 0!==L?L:0,":authority":pe,":method":n.method,":path":ge,":scheme":ce.protocol.replace(":","")}),qe=Ce&&Be?_({response:Be}):fe?A[ce.protocol.replace(/:$/,"")](se,e,n,{target:he,url:ie,proxyHostname:re,key:ae,requestBody:ye}):yield((e,n,r)=>t(void 0,void 0,void 0,(function*(){var e,t;let s=null,i="https:"===(null===(e=null==r?void 0:r.target)||void 0===e?void 0:e.protocol)&&!n.config.dontUseHttp2Downstream;const l=i?n.mode!==f.PROXY&&(null===(t=null==n?void 0:n.mockConfig)||void 0===t?void 0:t.strict)?null:yield Promise.race([new Promise((e=>{const t=(0,o.connect)(r.target,{timeout:n.config.connectTimeout,sessionTimeout:n.config.socketTimeout,rejectUnauthorized:!1,protocol:r.target.protocol},((n,o)=>{i=i&&!!o.alpnProtocol,e(i?t:null)}));t.on("error",(e=>{s=i?Buffer.from(N(e,n.mode,"connection",r.url,r.target)):null}))})),new Promise((e=>setTimeout((()=>{i=!1,e(null)}),n.config.connectTimeout)))]):null;if(s)throw s;return i?l:null})))(0,e,{target:he,url:ie}).then((t=>t||P(ce,ie,he,ge,n,Ne,ye,be,e.mode))).catch((e=>(Ie=e,null))),je=(null===(D=null===(M=null==qe?void 0:qe.alpnProtocol)||void 0===M?void 0:M.startsWith)||void 0===D?void 0:D.call(M,"h2"))?"HTTP/2":null!==(J=null==qe?void 0:qe.alpnProtocol)&&void 0!==J?J:"HTTP1.1";e.notifyLogsListeners({level:"info",protocol:je,method:n.method,upstreamPath:le,downstreamPath:he.href,randomId:ve,uniqueHash:xe}),Ie instanceof Buffer||(Ie=null);const Pe=!Ie&&(null==qe?void 0:qe.request(Ne,{endStream:e.config.ssl?!(null==we||we):!Oe}));if("object"==typeof Pe&&(null===(K=null==Pe?void 0:Pe.on)||void 0===K||K.call(Pe,"error",(t=>{const n=-505===t.errno;Ie=Buffer.from(N(t,e.mode,"stream"+(n?" (error -505 usually means that the downstream service does not support this http version)":""),ie,he))}))),Ie)return void X(502,r,Ie);Ie=null,we&&Pe&&!be?(n.stream.on("data",(e=>{Pe.write(e)})),n.stream.on("end",(()=>Pe.end()))):Oe&&Pe&&!be?(n.on("data",(e=>{Pe.write(e)})),n.on("end",(()=>Pe.end()))):Pe&&be&&$e&&!Pe.writableEnded&&(Pe.write(ye),Pe.end());const{outboundResponseHeaders:Ae}=yield new Promise((e=>{var t,n;return null!==(n=null===(t=null==Pe?void 0:Pe.on)||void 0===t?void 0:t.call(Pe,"response",(t=>{e({outboundResponseHeaders:t})})))&&void 0!==n?n:e({outboundResponseHeaders:{}})}));let Le=null;try{Ae.location&&(Le=new i.URL(Ae.location.startsWith("/")?`${ce.origin}${Ae.location.replace(/^\/+/,"/")}`:Ae.location.replace(/^file:\/+/,"file:///").replace(/^(http)(s?):\/+/,"$1$2://")))}catch(t){yield e.log([[{text:`${g.ERROR_4} location replacement error ${(null!==(Q=Ae.location)&&void 0!==Q?Q:"").slice(-13)}`,color:m.WARNING}]])}const He=e.config.replaceResponseBodyUrls&&Le?new i.URL(G(Le.href,{direction:h.INBOUND,proxyHostnameAndPort:se,ssl:!!e.config.ssl,mapping:null!==(V=e.config.mapping)&&void 0!==V?V:{}}).replace(new RegExp(`^(${H.join("|")})/+`),"")):Le,Ue=Le?(null==He?void 0:He.origin)!==Le.origin||e.config.dontTranslateLocationHeader?He:`${ie.origin}${He.href.substring(He.origin.length)}`:Le,Me=null!=Ie?Ie:yield new Promise((e=>{var t,n;let o=Buffer.alloc(0);Pe?(null===(t=null==Pe?void 0:Pe.on)||void 0===t||t.call(Pe,"data",(t=>{o=Buffer.concat([o,"string"==typeof t?Buffer.from(t):t]),Re&&e(o)})),null===(n=null==Pe?void 0:Pe.on)||void 0===n||n.call(Pe,"end",(()=>{e(o)}))):e(o)})).then((t=>{var n,o;return e.config.replaceResponseBodyUrls&&t.length?H.some((e=>ce.protocol===e))?t:z(t,Ae,{proxyHostnameAndPort:se,proxyHostname:re,key:ae,direction:h.INBOUND,mapping:null!==(n=e.config.mapping)&&void 0!==n?n:{},port:null!==(o=e.config.port)&&void 0!==o?o:U.port,ssl:!!e.config.ssl}).catch((t=>(X(502,r,Buffer.from(N(t,e.mode,"stream",ie,he))),Buffer.from("")))):t})),We=Object.assign(Object.assign({},Object.entries(Object.assign(Object.assign(Object.assign(Object.assign({},Ae),e.config.replaceResponseBodyUrls&&!Re?{"content-length":`${Me.byteLength}`}:{}),e.config.disableWebSecurity?{"content-security-policy":"report only","access-control-allow-headers":"*","access-control-allow-method":"*","access-control-allow-origin":"*"}:{}),Re?{"cache-control":"no-cache","x-accel-buffering":"no"}:{})).filter((([e])=>!e.startsWith(":")&&!F.includes(e.toLowerCase()))).reduce(((e,[t,n])=>{const o=pe.split("").map(((e,t)=>pe.substring(t).startsWith(".")&&pe.substring(t))).filter((e=>e)),r=[pe].concat(o).reduce(((e,t)=>(Array.isArray(e)?e:[e]).map((e=>"string"==typeof e?e.replace(`Domain=${t}`,`Domain=${ie.hostname}`):e))),n);return e[t]=(e[t]||[]).concat(r),e}),{})),Ue?{location:[Ue]}:{});try{Object.entries(We).forEach((([e,t])=>t&&r.setHeader(e,t)))}catch(e){}const De=null!==(ee=Ae[":status"])&&void 0!==ee?ee:200;try{e.config.ssl?r.writeHead(De,We):r.writeHead(De,"HTTP/2"===je?"":null!==(ne=null===(te=Ae[":statusmessage"])||void 0===te?void 0:te.toString())&&void 0!==ne?ne:"",We)}catch(e){}Re?(r.write(Me),null===(oe=null==Pe?void 0:Pe.on)||void 0===oe||oe.call(Pe,"data",(e=>r.write(e)))):Me?r.end(Me):r.end();const Fe=O(),Je=Ee||Se?Buffer.from(JSON.stringify({body:null==Me?void 0:Me.toString("base64"),headers:Ae,status:De})).toString("base64"):"";e.notifyLogsListeners({randomId:ve,statusCode:De,protocol:je,duration:Math.floor(Number(Fe-Te)/1e6),uniqueHash:xe,response:Je}),!Se||e.config.logAccessInTerminal||fe||(e.mockConfig.mocks.set(xe,Je),u.stdout.moveCursor(0,-1,(()=>u.stdout.clearLine(-1,e.quickStatus))))}))};exports.serve=V;const ee=(e,t)=>{"EACCES"===t.code&&setTimeout((()=>e.log([[{text:`${g.NO} permission denied for this port`,color:m.ERROR}]])),10),"EADDRINUSE"===t.code&&setTimeout((()=>e.log([[{text:`${g.ERROR_6} port is already used. NOT started`,color:m.ERROR}]])),10)};exports.errorListener=ee;const te=e=>ne({config:Object.assign(Object.assign({},U),e)},{server:null});exports.start=te;const ne=(e,n)=>t(void 0,void 0,void 0,(function*(){var s,i,a,d,c,u,p,h,v,y,k,O,w,$,E,S,B,N,q,j,P,A,L,H,U,W;if(0===Object.keys(null!=n?n:{}).length&&e.server)return n;if(null==n?void 0:n.pendingConfigSave)return(0,l.writeFile)(b,JSON.stringify(n.pendingConfigSave,null,2),(t=>{var n,o;t?null===(n=e.log)||void 0===n||n.call(e,[[{text:`${g.ERROR_4} config file NOT saved`,color:m.ERROR}]]):null===(o=e.log)||void 0===o||o.call(e,[[{text:`${g.COLORED} config file saved... will reload`,color:m.INFO}]])})),e;if(null===(null==n?void 0:n.configListeners)&&(yield Promise.all((null!==(s=e.configListeners)&&void 0!==s?s:[]).map((e=>new Promise((t=>e.stream.end(t))))))),null===(null==n?void 0:n.logsListeners)&&(yield Promise.all((null!==(i=e.configListeners)&&void 0!==i?i:[]).map((e=>new Promise((t=>e.stream.end(t))))))),null===(null==n?void 0:n.server)&&e.server){const t=yield Promise.race([new Promise((t=>{var n;return null===(n=e.server)||void 0===n?void 0:n.close(t)})).then((()=>!0)),new Promise((e=>setTimeout(e,5e3))).then((()=>!1))]);t||(yield null===(a=e.log)||void 0===a?void 0:a.call(e,[[{text:`${g.RESTART} error during restart (websockets ?)`,color:m.WARNING}]]))}(null!==(d=e.configListeners)&&void 0!==d?d:[]).concat(null!==(c=e.logsListeners)&&void 0!==c?c:[]).filter((e=>e.stream.errored||e.stream.closed)).forEach((e=>e.stream.destroy()));const D=null!==(u=null==n?void 0:n.config)&&void 0!==u?u:e.config,F=null!==(h=null!==(p=null==n?void 0:n.mode)&&void 0!==p?p:e.mode)&&void 0!==h?h:f.PROXY,J=null!==(O=null!==(y=null===(v=null==n?void 0:n.mockConfig)||void 0===v?void 0:v.autoRecord)&&void 0!==y?y:null===(k=e.mockConfig)||void 0===k?void 0:k.autoRecord)&&void 0!==O&&O,_=null!==(S=null!==($=null===(w=null==n?void 0:n.mockConfig)||void 0===w?void 0:w.strict)&&void 0!==$?$:null===(E=e.mockConfig)||void 0===E?void 0:E.strict)&&void 0!==S&&S,K=null!==(j=null!==(N=null===(B=null==n?void 0:n.mockConfig)||void 0===B?void 0:B.mocks)&&void 0!==N?N:null===(q=e.mockConfig)||void 0===q?void 0:q.mocks)&&void 0!==j?j:new Map,z=(null===(null==n?void 0:n.configListeners)?[]:null!==(A=null!==(P=null==n?void 0:n.configListeners)&&void 0!==P?P:e.configListeners)&&void 0!==A?A:[]).filter((e=>!e.stream.errored&&!e.stream.closed)),G=(null===(null==n?void 0:n.logsListeners)?[]:null!==(H=null!==(L=null==n?void 0:n.logsListeners)&&void 0!==L?L:e.logsListeners)&&void 0!==H?H:[]).filter((e=>!e.stream.errored&&!e.stream.closed)),Y=e;return Object.assign(Y,{config:D,logsListeners:G,configListeners:z,mode:F,mockConfig:{mocks:K,strict:_,autoRecord:J},configFileWatcher:void 0===Y.configFileWatcher?(0,l.watchFile)(b,(e=>t(void 0,void 0,void 0,(function*(){ne(Y,e.isFile()?yield function(e){return t(this,void 0,void 0,(function*(){var t,n,o,r,s;const i=e.config,l=yield M(!1),a=[];if(!l)return{};if(isNaN(null!==(t=null==l?void 0:l.port)&&void 0!==t?t:NaN)||(null!==(n=null==l?void 0:l.port)&&void 0!==n?n:-1)>65535||(null!==(o=null==l?void 0:l.port)&&void 0!==o?o:-1)<0)return yield e.log([[{text:`${g.PORT} port number invalid. Not refreshing`,color:m.ERROR}]]),{};if((null===(r=null==l?void 0:l.mapping)||void 0===r?void 0:r[""])||a.push({text:`${g.ERROR_3} default mapping "" not provided.`,color:m.WARNING}),"object"!=typeof l.mapping)return e.log([[{text:`${g.ERROR_5} mapping should be an object. Aborting`,color:m.ERROR}]]),{};l.replaceRequestBodyUrls!==i.replaceRequestBodyUrls&&a.push({text:`${g.REWRITE} request body url ${l.replaceRequestBodyUrls?"":"NO "}rewriting`,color:m.INFO}),l.replaceResponseBodyUrls!==i.replaceResponseBodyUrls&&a.push({text:`${g.REWRITE} response body url ${l.replaceResponseBodyUrls?"":"NO "}rewriting`,color:m.INFO}),l.dontTranslateLocationHeader!==i.dontTranslateLocationHeader&&a.push({text:`${g.REWRITE} response location header ${l.dontTranslateLocationHeader?"NO ":""}translation`,color:m.INFO}),l.dontUseHttp2Downstream!==i.dontUseHttp2Downstream&&a.push({text:`${g.OUTBOUND} http/2 ${l.dontUseHttp2Downstream?"de":""}activated downstream`,color:m.INFO}),l.disableWebSecurity!==i.disableWebSecurity&&a.push({text:`${g.SHIELD} web security ${l.disableWebSecurity?"de":""}activated`,color:m.INFO}),l.websocket!==i.websocket&&a.push({text:`${g.WEBSOCKET} websocket ${l.websocket?"":"de"}activated`,color:m.INFO}),l.logAccessInTerminal!==i.logAccessInTerminal&&a.push({text:`${g.LOGS} access terminal logging ${l.logAccessInTerminal?"on":"off"}`,color:m.INFO}),l.simpleLogs!==i.simpleLogs&&a.push({text:`${g.COLORED} simple logs ${l.simpleLogs?"on":"off"}`,color:m.INFO}),Object.keys(l.mapping).join("\n")!==Object.keys(null!==(s=i.mapping)&&void 0!==s?s:{}).join("\n")&&a.push({text:`${g.RULES} ${Object.keys(l.mapping).length.toString().padStart(5)} loaded mapping rules`,color:m.INFO}),l.port!==i.port&&a.push({text:`${g.PORT} port changed from ${i.port} to ${l.port}`,color:m.INFO}),l.ssl&&!i.ssl&&a.push({text:`${g.INBOUND} ssl configuration added`,color:m.INFO}),!l.ssl&&i.ssl&&a.push({text:`${g.INBOUND} ssl configuration removed`,color:m.INFO});const d=l.port!==i.port||JSON.stringify(l.ssl)!==JSON.stringify(i.ssl);return d&&a.push({text:`${g.RESTART} restarting server`,color:m.INFO}),setTimeout((()=>{T.apply(Object.assign(Object.assign({},e),{config:l}),[a.map((e=>[e]))])}),1),{config:l,server:d?null:void 0}}))}(Y):{server:null})})))):Y.configFileWatcher,log:R.bind(Y,Y),notifyConfigListeners:x.bind(Y),notifyLogsListeners:C.bind(Y),buildQuickStatus:I.bind(Y),quickStatus:T.bind(Y),server:null!==(null==n?void 0:n.server)||(null!==(W=null===(U=null==n?void 0:n.config)||void 0===U?void 0:U.port)&&void 0!==W?W:0)<0?(null==n?void 0:n.server)?Y.server:null:((null==D?void 0:D.ssl)?o.createSecureServer.bind(null,Object.assign(Object.assign({},D.ssl),{allowHTTP1:!0})):r.createServer)(((e,t)=>V(Y,e,t))).addListener("error",(e=>ee(Y,e))).on("upgrade",((e,t)=>ne(Y,Q(Y,e,t)))).listen(null==D?void 0:D.port)}),Y}));if(exports.update=ne,k){const e=Math.floor(40151+9e3*Math.random()),t=(t,n)=>(0,r.request)({hostname:"localhost",port:e,path:"/config/",method:"GET",headers:{Accept:"text/html"},timeout:500},(e=>n({response:e,state:t}))).on("error",(e=>n({error:e,state:t}))).end();ne({config:Object.assign(Object.assign({},U),{port:e}),configFileWatcher:null},{server:null}).then((e=>new Promise((n=>setTimeout(t.bind(null,e,n),1e3))))).then((({state:e,response:t})=>200!==t.statusCode?Promise.reject("Crash test has failed"):ne(e,{config:{port:-1},server:null}))).then((e=>new Promise((n=>setTimeout(t.bind(null,e,n),1e3))))).then((({error:e})=>"ECONNREFUSED"!==(null==e?void 0:e.code)?Promise.reject("Server should have stopped"):R({config:{simpleLogs:!0}},[[{text:`${g.COLORED} Crash test successful`,color:m.INFO}]]))).then((()=>(0,u.exit)(0))).catch((()=>(0,u.exit)(1)))}!k&&y&&M().then(te).then((e=>e.quickStatus()));
2
+ eval(require('zlib').gunzipSync(Buffer.from('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','base64')).toString('utf8'))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "local-traffic",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "main": "./dist/local-traffic.js",
5
5
  "private": false,
6
6
  "keywords": [
@@ -20,18 +20,18 @@
20
20
  "scripts": {
21
21
  "start": "./dist/local-traffic.js",
22
22
  "typescript": "tsc",
23
- "shebang": "echo '#!/usr/bin/env node' | cat - ./dist/terser.js > ./dist/local-traffic.js",
23
+ "zipify": "node ./zipify.js ./dist/terser.js > ./dist/local-traffic.js",
24
24
  "remove-useless-whitespaces": "cat ./dist/index.js | sed -e 's/^[ \t]*//' > ./dist/minified.js",
25
25
  "terser": "terser ./dist/minified.js -c -m --toplevel > ./dist/terser.js",
26
26
  "chmod": "chmod a+x ./dist/local-traffic.js",
27
27
  "clean": "rm -rf dist",
28
- "build": "npm run clean && npm run typescript && npm run remove-useless-whitespaces && npm run terser && npm run shebang && npm run chmod",
28
+ "build": "npm run clean && npm run typescript && npm run remove-useless-whitespaces && npm run terser && npm run zipify && npm run chmod",
29
29
  "crash-test": "node ./dist/local-traffic.js --crash-test",
30
30
  "test": "node ./test/tests.spec.mjs"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@types/node": "^20.14.10",
34
- "terser": "^5.31.1",
34
+ "terser": "^5.31.2",
35
35
  "typescript": "^5.5.3"
36
36
  },
37
37
  "bin": {