@gcoredev/fastedge-test 0.1.5 → 0.1.6

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.
@@ -2574,7 +2574,7 @@ var ProxyWasmRunner = class {
2574
2574
  }
2575
2575
  }
2576
2576
  createImports() {
2577
- const wasi = new import_node_wasi.WASI({ version: "preview1" });
2577
+ const wasi = new import_node_wasi.WASI({ version: "preview1", env: this.dictionary.getAll() });
2578
2578
  const wasiImport = wasi.wasiImport;
2579
2579
  return {
2580
2580
  env: this.hostFunctions.createImports(),
package/dist/lib/index.js CHANGED
@@ -2530,7 +2530,7 @@ var ProxyWasmRunner = class {
2530
2530
  }
2531
2531
  }
2532
2532
  createImports() {
2533
- const wasi = new WASI({ version: "preview1" });
2533
+ const wasi = new WASI({ version: "preview1", env: this.dictionary.getAll() });
2534
2534
  const wasiImport = wasi.wasiImport;
2535
2535
  return {
2536
2536
  env: this.hostFunctions.createImports(),
@@ -2601,7 +2601,7 @@ var ProxyWasmRunner = class {
2601
2601
  }
2602
2602
  }
2603
2603
  createImports() {
2604
- const wasi = new import_node_wasi.WASI({ version: "preview1" });
2604
+ const wasi = new import_node_wasi.WASI({ version: "preview1", env: this.dictionary.getAll() });
2605
2605
  const wasiImport = wasi.wasiImport;
2606
2606
  return {
2607
2607
  env: this.hostFunctions.createImports(),
@@ -2537,7 +2537,7 @@ var ProxyWasmRunner = class {
2537
2537
  }
2538
2538
  }
2539
2539
  createImports() {
2540
- const wasi = new WASI({ version: "preview1" });
2540
+ const wasi = new WASI({ version: "preview1", env: this.dictionary.getAll() });
2541
2541
  const wasiImport = wasi.wasiImport;
2542
2542
  return {
2543
2543
  env: this.hostFunctions.createImports(),
package/dist/server.js CHANGED
@@ -56,7 +56,7 @@ Please see the 3.x to 4.x migration guide for details on how to update your app.
56
56
  `)+`\r
57
57
  \r
58
58
  `+n)}function mr(t,e,n,i,r,o){if(t.listenerCount("wsClientError")){let a=new Error(r);Error.captureStackTrace(a,mr),t.emit("wsClientError",a,n,e)}else Ii(n,i,r,o)}});var m5={};tt(m5,{startServer:()=>F4});module.exports=V4(m5);var Tc=Ne(gw()),pe=Ne(require("node:path")),ve=require("node:fs"),D4=require("node:http");var kw=require("node:wasi");var Mj=new TextEncoder,Dl=new TextDecoder,xa=class{constructor(){this.memory=null;this.instance=null;this.hostAllocOffset=0;this.logCallback=null;this.isInitializing=!1}setMemory(e){this.memory=e}setInstance(e){this.instance=e}reset(){this.hostAllocOffset=0}setLogCallback(e){this.logCallback=e}setInitializing(e){this.isInitializing=e}readBytes(e,n){if(!this.memory)throw new Error("Memory not available");let i=new Uint8Array(this.memory.buffer,e,n);return new Uint8Array(i)}readString(e,n){return Dl.decode(this.readBytes(e,n))}readOptionalString(e){if(!e||!this.memory)return null;let n=new Uint8Array(this.memory.buffer,e),i=e;for(;i-e<n.length&&n[i-e]!==0;)i+=1;return Dl.decode(new Uint8Array(this.memory.buffer,e,i-e))}writeToWasm(e){let n=this.allocate(e.length);if(!this.memory)throw new Error("Memory not available");return e.length&&new Uint8Array(this.memory.buffer,n,e.length).set(e),n}writeU32(e,n){if(!this.memory)throw new Error("Memory not available");if(!e)return;new DataView(this.memory.buffer).setUint32(e,n,!0)}writeStringResult(e,n,i){let r=Mj.encode(e);this.writeBytesResult(r,n,i)}writeBytesResult(e,n,i){if(!n&&!i)return;let r=this.writeToWasm(e.length?e:new Uint8Array([0]));n&&this.writeU32(n,r),i&&this.writeU32(i,e.length)}captureFdWrite(e,n,i,r){if(!this.memory||i===0)return 0;let o=new DataView(this.memory.buffer),a=0,s="";for(let u=0;u<i;u+=1){let c=n+u*8,l=o.getUint32(c,!0),p=o.getUint32(c+4,!0);p>0&&(a+=p,s+=Dl.decode(new Uint8Array(this.memory.buffer,l,p)))}if(s&&this.logCallback){let u=s.replace(/\n$/,"");if(this.isInitializing&&u.includes("abort:"))return a;let c=1,l=u,p=u.match(/^\[(TRACE|DEBUG|INFO|WARN|ERROR|CRITICAL)\]\s*(.*)$/);if(p){let d=p[1];l=p[2],c={TRACE:0,DEBUG:1,INFO:2,WARN:3,ERROR:4,CRITICAL:5}[d]??1}this.logCallback(c,l)}return r&&this.writeU32(r,a),a}allocate(e){if(!this.instance)throw new Error("WASM module not loaded");let n=this.instance.exports.proxy_on_memory_allocate??this.instance.exports.malloc;if(typeof n!="function")throw new Error("WASM module must export proxy_on_memory_allocate or malloc");let i=n(e);return i!==0?i:this.hostAllocate(e)}hostAllocate(e){if(!this.memory)throw new Error("Memory not available");this.hostAllocOffset===0&&(this.hostAllocOffset=this.memory.buffer.byteLength);let n=e===0?1:e,i=this.hostAllocOffset+n,r=this.memory.buffer.byteLength;if(i>r){let a=i-r,s=Math.ceil(a/65536);this.memory.grow(s)}let o=this.hostAllocOffset;return this.hostAllocOffset=i,o}};var ya=new TextEncoder,ge=class{static normalize(e){let n={};for(let[i,r]of Object.entries(e))n[i.toLowerCase()]=String(r);return n}static serialize(e){let n=Object.entries(e),i=n.length,r=[],o=0;for(let[p,d]of n){let f=ya.encode(p),m=ya.encode(d);r.push({key:f,value:m}),o+=f.length+1+m.length+1}let a=4+i*2*4+o,s=new ArrayBuffer(a),u=new DataView(s),c=new Uint8Array(s);u.setUint32(0,i,!0);let l=4;for(let{key:p,value:d}of r)u.setUint32(l,p.length,!0),l+=4,u.setUint32(l,d.length,!0),l+=4;for(let{key:p,value:d}of r)c.set(p,l),l+=p.length,c[l]=0,l+=1,c.set(d,l),l+=d.length,c[l]=0,l+=1;return c}static deserializeBinary(e){if(e.length<4)return{};let n=new DataView(e.buffer,e.byteOffset,e.byteLength),i=n.getUint32(0,!0),r=[],o=4;for(let u=0;u<i;u++){let c=n.getUint32(o,!0);o+=4;let l=n.getUint32(o,!0);o+=4,r.push({keyLen:c,valLen:l})}let a=new TextDecoder,s={};for(let{keyLen:u,valLen:c}of r){let l=a.decode(e.slice(o,o+u));o+=u+1;let p=a.decode(e.slice(o,o+c));o+=c+1,s[l.toLowerCase()]=p}return s}static deserialize(e){let n=e.split("\0").filter(r=>r.length>0),i={};for(let r=0;r<n.length;r+=2){let o=n[r],a=n[r+1]??"";i[o.toLowerCase()]=a}return i}static recordToTuples(e){return Object.entries(e).map(([n,i])=>[n.toLowerCase(),String(i)])}static tuplesToRecord(e){let n={};for(let[i,r]of e){let o=n[i];n[i]=o!==void 0?`${o},${r}`:r}return n}static normalizeTuples(e){return e.map(([n,i])=>[n.toLowerCase(),String(i)])}static serializeTuples(e){let n=e.length,i=[],r=0;for(let[l,p]of e){let d=ya.encode(l),f=ya.encode(p);i.push({key:d,value:f}),r+=d.length+1+f.length+1}let o=4+n*2*4+r,a=new ArrayBuffer(o),s=new DataView(a),u=new Uint8Array(a);s.setUint32(0,n,!0);let c=4;for(let{key:l,value:p}of i)s.setUint32(c,l.length,!0),c+=4,s.setUint32(c,p.length,!0),c+=4;for(let{key:l,value:p}of i)u.set(l,c),c+=l.length,u[c]=0,c+=1,u.set(p,c),c+=p.length,u[c]=0,c+=1;return u}static deserializeBinaryToTuples(e){if(e.length<4)return[];let n=new DataView(e.buffer,e.byteOffset,e.byteLength),i=n.getUint32(0,!0),r=[],o=4;for(let u=0;u<i;u++){let c=n.getUint32(o,!0);o+=4;let l=n.getUint32(o,!0);o+=4,r.push({keyLen:c,valLen:l})}let a=new TextDecoder,s=[];for(let{keyLen:u,valLen:c}of r){let l=a.decode(e.slice(o,o+u));o+=u+1;let p=a.decode(e.slice(o,o+c));o+=c+1,s.push([l.toLowerCase(),p])}return s}static deserializeToTuples(e){let n=e.split("\0").filter(r=>r.length>0),i=[];for(let r=0;r<n.length;r+=2){let o=n[r],a=n[r+1]??"";i.push([o.toLowerCase(),a])}return i}};var ba=class{constructor(){this.properties={};this.requestHeaders={};this.requestMethod="GET";this.requestPath="/";this.requestScheme="https";this.requestUrl="";this.requestHost="";this.requestQuery="";this.requestExtension="";this.responseHeaders={};this.responseStatus=200;this.responseStatusText="OK"}setProperties(e){this.properties=e}setProperty(e,n){let i=e.replace(/\0/g,".");this.properties[i]=n}getCalculatedProperties(){return{"request.url":this.requestUrl,"request.host":this.requestHost,"request.path":this.requestPath,"request.query":this.requestQuery,"request.scheme":this.requestScheme,"request.extension":this.requestExtension,"request.method":this.requestMethod}}getAllProperties(){return{...this.getCalculatedProperties(),...this.properties}}setRequestMetadata(e,n,i,r){this.requestHeaders=e,this.requestMethod=n,i!==void 0&&i!=="/"&&(this.requestPath=i),r!==void 0&&(this.requestScheme=r)}extractRuntimePropertiesFromUrl(e){try{let n=new URL(e);this.requestUrl=e,this.requestHost=n.hostname+(n.port?`:${n.port}`:""),this.requestPath=n.pathname||"/",this.requestQuery=n.search.startsWith("?")?n.search.substring(1):n.search,this.requestScheme=n.protocol.replace(":","");let i=this.requestPath.split("/"),r=i[i.length-1],o=r.lastIndexOf(".");o>0&&o<r.length-1?this.requestExtension=r.substring(o+1):this.requestExtension=""}catch(n){console.error("Failed to parse target URL:",n),this.requestUrl=e,this.requestHost="localhost",this.requestPath="/",this.requestQuery="",this.requestExtension=""}}setResponseMetadata(e,n,i){this.responseHeaders=e,this.responseStatus=n,this.responseStatusText=i}resolve(e){let n=e.replace(/\0/g,".");if(Object.prototype.hasOwnProperty.call(this.properties,n))return this.properties[n];if(Object.prototype.hasOwnProperty.call(this.properties,e))return this.properties[e];let i=this.resolveStandard(n);if(i!==void 0)return i;let r=this.deriveRootId();if(r){let a=e.replace(/\0/g,"/");if(a==="root_id"||a==="plugin_name"||a==="plugin_root_id"||a==="root_context"||a==="root_context_id")return r}let o=e.split("\0").filter(a=>a.length>0);if(o.length>0){let a=this.resolvePathSegments(o);if(a!==void 0)return a;let s=o.join(".");if(Object.prototype.hasOwnProperty.call(this.properties,s))return this.properties[s];let u=o.join("/");if(Object.prototype.hasOwnProperty.call(this.properties,u))return this.properties[u]}if(e.includes(".")){let a=this.resolvePathSegments(e.split("."));if(a!==void 0)return a}}resolveStandard(e){if(e==="request.method")return this.requestMethod;if(e==="request.path")return this.requestPath;if(e==="request.url")return this.requestUrl||`${this.requestScheme}://${this.requestHost}${this.requestPath}`;if(e==="request.host")return this.requestHost||this.requestHeaders.host||"localhost";if(e==="request.scheme")return this.requestScheme;if(e==="request.protocol")return this.requestScheme;if(e==="request.query")return this.requestQuery;if(e==="request.extension")return this.requestExtension;if(e==="request.content_type")return this.requestHeaders["content-type"]||"";if(e.startsWith("request.headers.")){let n=e.substring(16).toLowerCase();return this.requestHeaders[n]||""}if(e==="response.code")return this.responseStatus;if(e==="response.status")return this.responseStatus;if(e==="response.status_code")return this.responseStatus;if(e==="response.code_details")return this.responseStatusText;if(e==="response.content_type")return this.responseHeaders["content-type"]||"";if(e.startsWith("response.headers.")){let n=e.substring(17).toLowerCase();return this.responseHeaders[n]||""}}resolvePathSegments(e){let n=this.properties;for(let i of e)if(i.length!==0)if(n&&typeof n=="object"&&i in n)n=n[i];else return;return n}deriveRootId(){let e=["root_id","rootId","root_context","rootContext","root_context_name","rootContextName","plugin_name","pluginName","context_name","contextName"];for(let n of e){let i=this.properties[n];if(typeof i=="string"&&i.length>0)return i}return null}};var gt=class{constructor(e){this.secrets=new Map,e&&Object.entries(e).forEach(([n,i])=>{this.secrets.set(n,i)})}get(e){let n=this.secrets.get(e);if(!n)return null;if(typeof n=="string")return n;let i=Math.floor(Date.now()/1e3);return this.getEffectiveAt(e,i)}getEffectiveAt(e,n){let i=this.secrets.get(e);if(!i)return null;if(typeof i=="string")return i;let r=[...i].sort((o,a)=>a.effectiveAt-o.effectiveAt);for(let o of r)if(o.effectiveAt<=n)return o.value;return null}set(e,n){this.secrets.set(e,n)}has(e){return this.secrets.has(e)}clear(){this.secrets.clear()}getAll(){let e={};return this.secrets.forEach((n,i)=>{e[i]=n}),e}load(e){this.clear(),Object.entries(e).forEach(([n,i])=>{this.set(n,i)})}};var At=class{constructor(e){this.data=new Map,e&&Object.entries(e).forEach(([n,i])=>{this.data.set(n,i)})}get(e){return this.data.get(e)??null}set(e,n){this.data.set(e,n)}has(e){return this.data.has(e)}clear(){this.data.clear()}getAll(){let e={};return this.data.forEach((n,i)=>{e[i]=n}),e}load(e){this.clear(),Object.entries(e).forEach(([n,i])=>{this.set(n,i)})}};function _a(t,e,n,i){return{proxy_get_secret:(r,o,a,s)=>{try{i(`proxy_get_secret keyPtr=${r} keyLen=${o} returnValuePtr=${a} returnSizePtr=${s}`);let u=t.readString(r,o);i(`proxy_get_secret key="${u}"`);let c=e.get(u);return c===null?(i(`proxy_get_secret key="${u}" not found`),1):(i(`proxy_get_secret found value (length=${c.length})`),t.writeStringResult(c,a,s),0)}catch(u){return i(`proxy_get_secret error: ${u instanceof Error?u.message:String(u)}`),10}},proxy_get_effective_at_secret:(r,o,a,s,u)=>{try{i(`proxy_get_effective_at_secret keyPtr=${r} keyLen=${o} timestamp=${a}`);let c=t.readString(r,o);i(`proxy_get_effective_at_secret key="${c}" at=${a}`);let l=e.getEffectiveAt(c,a);return l===null?(i(`proxy_get_effective_at_secret key="${c}" not found at timestamp ${a}`),1):(i(`proxy_get_effective_at_secret found value (length=${l.length})`),t.writeStringResult(l,s,u),0)}catch(c){return i(`proxy_get_effective_at_secret error: ${c instanceof Error?c.message:String(c)}`),10}},proxy_secret_get:(r,o,a,s)=>(i("proxy_secret_get (aliased to proxy_get_secret)"),_a(t,e,n,i).proxy_get_secret(r,o,a,s)),proxy_dictionary_get:(r,o,a,s)=>{try{i(`proxy_dictionary_get keyPtr=${r} keyLen=${o} returnValuePtr=${a} returnSizePtr=${s}`);let u=t.readString(r,o);i(`proxy_dictionary_get key="${u}"`);let c=n.get(u);return c===null?(i(`proxy_dictionary_get key="${u}" not found`),1):(i(`proxy_dictionary_get found value="${c}" (length=${c.length})`),t.writeStringResult(c,a,s),0)}catch(u){return i(`proxy_dictionary_get error: ${u instanceof Error?u.message:String(u)}`),10}}}}var Ul=new TextEncoder;var Jr=class{constructor(e,n,i,r,o=!1,a,s){this.logs=[];this.requestHeaders=[];this.responseHeaders=[];this.requestBody="";this.responseBody="";this.vmConfig="";this.pluginConfig="";this.currentContextId=1;this.lastHostCall=null;this.debug=!1;this.currentLogLevel=0;this.nextTokenId=0;this.pendingHttpCall=null;this.httpCallResponse=null;this.streamClosed=!1;this.localResponse=null;this.memory=e,this.propertyResolver=n,this.propertyAccessControl=i,this.getCurrentHook=r,this.debug=o,this.secretStore=a??new gt,this.dictionary=s??new At}setLogs(e){this.logs=e}setHeadersAndBodies(e,n,i,r){this.requestHeaders=ge.recordToTuples(e),this.responseHeaders=ge.recordToTuples(n),this.requestBody=i,this.responseBody=r}setConfigs(e,n){this.vmConfig=e,this.pluginConfig=n}setCurrentContext(e){this.currentContextId=e}getCurrentLogLevel(){return this.currentLogLevel}setLogLevel(e){this.currentLogLevel=e}shouldLog(e){return e>=this.currentLogLevel}hasPendingHttpCall(){return this.pendingHttpCall!==null}takePendingHttpCall(){let e=this.pendingHttpCall;return this.pendingHttpCall=null,e}setHttpCallResponse(e,n,i){this.httpCallResponse={tokenId:e,headers:n,body:i}}clearHttpCallResponse(){this.httpCallResponse=null}isStreamClosed(){return this.streamClosed}resetStreamClosed(){this.streamClosed=!1}hasLocalResponse(){return this.localResponse!==null}getLocalResponse(){return this.localResponse}resetLocalResponse(){this.localResponse=null}getRequestHeaders(){return ge.tuplesToRecord(this.requestHeaders)}getResponseHeaders(){return ge.tuplesToRecord(this.responseHeaders)}getRequestBody(){return this.requestBody}getResponseBody(){return this.responseBody}getSecretStore(){return this.secretStore}getDictionary(){return this.dictionary}createImports(){return{proxy_log:(e,n,i)=>{this.setLastHostCall(`proxy_log level=${e} len=${i}`);let r=this.memory.readString(n,i);return e>=this.currentLogLevel&&this.logs.push({level:e,message:r}),0},proxy_get_log_level:e=>(this.setLastHostCall("proxy_get_log_level"),e&&this.memory.writeU32(e,this.currentLogLevel),0),proxy_set_log_level:e=>(this.setLastHostCall(`proxy_set_log_level level=${e}`),this.currentLogLevel=e,this.logDebug(`Log level set to ${e}`),0),proxy_get_property:(e,n,i,r)=>{this.setLastHostCall(`proxy_get_property pathLen=${n}`);let o=this.memory.readString(e,n),a=this.getCurrentHook();if(a){let l=this.propertyAccessControl.canGetProperty(o,a);if(this.debug&&(console.log(`[property access] ${a}: GET ${o} - ${l.allowed?"ALLOWED":"DENIED"}`),l.allowed||console.log(` Reason: ${l.reason}`)),!l.allowed){let p=`Property access denied: Cannot read '${o}' in ${a}. ${l.reason}`;return!process.env.VITEST&&process.env.NODE_ENV!=="test"&&console.error(`[property access denied] ${l.reason}`),this.logs.push({level:3,message:p}),this.memory.writeStringResult("",i,r),1}}let s=this.propertyResolver.resolve(o);if(s===void 0)return this.logDebug(`get_property miss: ${o}`),this.memory.writeStringResult("",i,r),0;let u=o.replace(/\0/g,".");if((u==="response.status"||u==="response.code"||u==="response.status_code")&&typeof s=="number"){let l=Number.isFinite(s)?Math.trunc(s)&65535:0,p=new Uint8Array(2);return p[0]=l>>8&255,p[1]=l&255,this.memory.writeBytesResult(p,i,r),0}let c=typeof s=="string"?s:JSON.stringify(s);return this.memory.writeStringResult(c??"",i,r),0},proxy_set_property:(e,n,i,r)=>{this.setLastHostCall(`proxy_set_property pathLen=${n} valueLen=${r}`);let o=this.memory.readString(e,n),a=this.memory.readString(i,r),s=this.getCurrentHook();if(s){let u=this.propertyAccessControl.canSetProperty(o,s);if(this.debug&&(console.log(`[property access] ${s}: SET ${o} - ${u.allowed?"ALLOWED":"DENIED"}`),u.allowed||console.log(` Reason: ${u.reason}`)),!u.allowed){let l=`Property access denied: Cannot write '${o}' = '${a}' in ${s}. ${u.reason}`;return!process.env.VITEST&&process.env.NODE_ENV!=="test"&&console.error(`[property access denied] ${u.reason}`),this.logs.push({level:3,message:l}),2}let c=this.memory.readBytes(i,r);this.propertyAccessControl.registerCustomProperty(o,c,s)}return this.propertyResolver.setProperty(o,a),this.logDebug(`set_property: ${o} = ${a}`),0},proxy_get_header_map_value:(e,n,i,r,o)=>{this.setLastHostCall(`proxy_get_header_map_value map=${e} keyLen=${i}`);let a=this.memory.readString(n,i).toLowerCase(),u=this.getInternalHeaders(e).find(([c])=>c===a);return u===void 0?(this.logDebug(`get_header_map_value miss: map=${e} key=${a}`),this.memory.writeStringResult("",r,o),0):(this.memory.writeStringResult(u[1],r,o),0)},proxy_get_header_map_pairs:(e,n,i)=>{this.setLastHostCall(`proxy_get_header_map_pairs map=${e}`);let r=this.getInternalHeaders(e),o=ge.serializeTuples(r),a=this.memory.writeToWasm(o);n&&this.memory.writeU32(n,a),i&&this.memory.writeU32(i,o.length);let s=Array.from(o.slice(0,64)).map(u=>u.toString(16).padStart(2,"0")).join(" ");return this.logDebug(`header_map_pairs ptr=${a} len=${o.length} count=${r.length} hex=${s}`),0},proxy_get_header_map_size:(e,n)=>{this.setLastHostCall(`proxy_get_header_map_size map=${e}`);let r=this.getInternalHeaders(e).length;return this.memory.writeU32(n,r),this.logDebug(`header_map_size map=${e} size=${r} (pair count)`),0},proxy_add_header_map_value:(e,n,i,r,o)=>{this.setLastHostCall(`proxy_add_header_map_value map=${e} keyLen=${i} valueLen=${o}`);let a=this.memory.readString(n,i).toLowerCase(),s=this.memory.readString(r,o),u=this.getInternalHeaders(e);return u.push([a,s]),this.setInternalHeaders(e,u),0},proxy_replace_header_map_value:(e,n,i,r,o)=>{this.setLastHostCall(`proxy_replace_header_map_value map=${e} keyLen=${i} valueLen=${o}`);let a=this.memory.readString(n,i).toLowerCase(),s=this.memory.readString(r,o),c=this.getInternalHeaders(e).filter(([l])=>l!==a);return c.push([a,s]),this.setInternalHeaders(e,c),0},proxy_remove_header_map_value:(e,n,i)=>{this.setLastHostCall(`proxy_remove_header_map_value map=${e} keyLen=${i}`);let r=this.memory.readString(n,i).toLowerCase(),o=this.getInternalHeaders(e);if(o.some(([s])=>s===r)){let s=o.filter(([u])=>u!==r);s.push([r,""]),this.setInternalHeaders(e,s)}return 0},proxy_set_header_map_pairs:(e,n,i)=>{this.setLastHostCall(`proxy_set_header_map_pairs map=${e} valueLen=${i}`);let r=this.memory.readString(n,i),o=ge.deserializeToTuples(r);return this.setInternalHeaders(e,o),0},proxy_get_buffer_bytes:(e,n,i,r,o)=>{if(this.setLastHostCall(`proxy_get_buffer_bytes type=${e} start=${n} length=${i}`),e===4){if(this.httpCallResponse){let l=this.httpCallResponse.body.slice(n,i>0?n+i:void 0);this.memory.writeBytesResult(l,r,o)}return 0}let a=this.getBody(e),u=Ul.encode(a).slice(n,i>0?n+i:void 0);return u.length===0&&this.logDebug(`get_buffer_bytes empty: type=${e} start=${n} length=${i}`),this.memory.writeBytesResult(u,r,o),0},proxy_get_buffer_status:(e,n,i)=>{this.setLastHostCall(`proxy_get_buffer_status type=${e}`);let r=this.getBody(e),o=Zj(r);return this.memory.writeU32(n,o),this.memory.writeU32(i,1),0},proxy_set_buffer_bytes:(e,n,i,r,o)=>{this.setLastHostCall(`proxy_set_buffer_bytes type=${e} start=${n} length=${i} dataLen=${o}`);let a=this.getBody(e),s=Ul.encode(a),u=this.memory.readBytes(r,o),c=s.slice(0,n),l=s.slice(n+i),p=new Uint8Array(c.length+u.length+l.length);p.set(c,0),p.set(u,c.length),p.set(l,c.length+u.length);let d=new TextDecoder().decode(p);return this.setBody(e,d),0},proxy_set_effective_context:e=>(this.setLastHostCall(`proxy_set_effective_context ${e}`),this.currentContextId=e||this.currentContextId,0),proxy_send_local_response:(e,n,i,r,o,a,s,u)=>{this.setLastHostCall(`proxy_send_local_response status=${e} bodyLen=${o}`);let c=this.memory.readString(n,i),l=this.memory.readBytes(r,o);if(s>0){let p=this.memory.readBytes(a,s),d=ge.deserializeBinary(p);this.logDebug(`send_local_response headers (not merged): ${JSON.stringify(d)}`)}return this.localResponse={statusCode:e,statusText:c,body:l},this.logs.push({level:1,message:`local_response status=${e} ${c} bodyLen=${l.byteLength} grpc=${u}`}),0},abort:(e,n,i,r)=>{let o=this.memory.readOptionalString(e),a=this.memory.readOptionalString(n),s=`WASM abort: ${o??"<null>"} at ${a??"<unknown>"}:${i}:${r} lastHostCall=${this.lastHostCall??"<none>"}`;throw this.logs.push({level:3,message:s}),new Error(s)},trace:(e,n,...i)=>{let r=this.memory.readOptionalString(e)??"<trace>";this.logs.push({level:0,message:`trace: ${r}`})},proxy_http_call:(e,n,i,r,o,a,s,u,c,l)=>{this.setLastHostCall(`proxy_http_call upstreamLen=${n}`);let p=this.memory.readString(e,n),d=this.memory.readBytes(i,r),f=ge.deserializeBinary(d),m=a>0?this.memory.readBytes(o,a):null,v=this.nextTokenId++;return this.pendingHttpCall={tokenId:v,upstream:p,headers:f,body:m,timeoutMs:c},this.memory.writeU32(l,v),this.logDebug(`proxy_http_call upstream=${p} tokenId=${v}`),0},proxy_continue_stream:e=>(this.setLastHostCall("proxy_continue_stream"),0),proxy_close_stream:e=>(this.setLastHostCall("proxy_close_stream"),this.streamClosed=!0,0),proxy_get_status:e=>(this.setLastHostCall("proxy_get_status"),e&&this.memory.writeU32(e,200),0),proxy_get_shared_data:(e,n,i,r,o)=>(this.setLastHostCall(`proxy_get_shared_data keyLen=${n}`),this.memory.writeStringResult("",i,r),1),proxy_set_shared_data:(e,n,i,r,o)=>(this.setLastHostCall("proxy_set_shared_data"),0),proxy_set_tick_period_milliseconds:e=>(this.setLastHostCall("proxy_set_tick_period_milliseconds"),0),proxy_get_current_time_nanoseconds:e=>{if(this.setLastHostCall("proxy_get_current_time_nanoseconds"),e){let n=BigInt(Date.now())*1000000n;this.memory.writeU32(e,Number(n&0xffffffffn)),this.memory.writeU32(e+4,Number(n>>32n&0xffffffffn))}return 0},proxy_done:()=>(this.setLastHostCall("proxy_done"),0),proxy_call_foreign_function:(e,n,i,r,o,a)=>(this.setLastHostCall("proxy_call_foreign_function"),1),proxy_register_shared_queue:(e,n,i)=>(this.setLastHostCall("proxy_register_shared_queue"),0),proxy_resolve_shared_queue:(e,n,i,r,o)=>(this.setLastHostCall("proxy_resolve_shared_queue"),1),proxy_enqueue_shared_queue:(e,n,i)=>(this.setLastHostCall("proxy_enqueue_shared_queue"),0),proxy_dequeue_shared_queue:(e,n,i)=>(this.setLastHostCall("proxy_dequeue_shared_queue"),1),proxy_grpc_call:(e,n,i,r,o,a,s,u,c,l,p,d)=>(this.setLastHostCall("proxy_grpc_call"),0),proxy_grpc_stream:(e,n,i,r,o,a,s,u,c)=>(this.setLastHostCall("proxy_grpc_stream"),0),proxy_grpc_cancel:e=>(this.setLastHostCall("proxy_grpc_cancel"),0),proxy_grpc_close:e=>(this.setLastHostCall("proxy_grpc_close"),0),proxy_grpc_send:(e,n,i,r)=>(this.setLastHostCall("proxy_grpc_send"),0),..._a(this.memory,this.secretStore,this.dictionary,e=>this.logs.push({level:0,message:e}))}}getInternalHeaders(e){return e===2||e===3?this.responseHeaders:e===6||e===7?ge.recordToTuples(this.httpCallResponse?.headers??{}):this.requestHeaders}setInternalHeaders(e,n){let i=ge.normalizeTuples(n);e===2||e===3?this.responseHeaders=i:this.requestHeaders=i}getBody(e){return e===1?this.responseBody:e===6?this.vmConfig:e===7?this.pluginConfig:this.requestBody}setBody(e,n){e===1?this.responseBody=n:e===6?this.vmConfig=n:e===7?this.pluginConfig=n:this.requestBody=n}logDebug(e){if(!this.debug)return;let n={level:0,message:`debug: ${e}`};this.logs.push(n),console.warn(n.message)}setLastHostCall(e){this.lastHostCall=e,this.logDebug(`host_call ${e}`)}};function Zj(t){return Ul.encode(t).length}var Wj=[{path:"request.url",type:"string",access:{onRequestHeaders:"read-write",onRequestBody:"read-only",onResponseHeaders:"read-only",onResponseBody:"read-only"},description:"Original URL path before modifications"},{path:"request.host",type:"string",access:{onRequestHeaders:"read-write",onRequestBody:"read-only",onResponseHeaders:"read-only",onResponseBody:"read-only"},description:"Host header value"},{path:"request.path",type:"string",access:{onRequestHeaders:"read-write",onRequestBody:"read-only",onResponseHeaders:"read-only",onResponseBody:"read-only"},description:"Request URL path"},{path:"request.query",type:"string",access:{onRequestHeaders:"read-write",onRequestBody:"read-only",onResponseHeaders:"read-only",onResponseBody:"read-only"},description:"Query string parameters"},{path:"request.scheme",type:"string",access:{onRequestHeaders:"read-only",onRequestBody:"read-only",onResponseHeaders:"read-only",onResponseBody:"read-only"},description:"Protocol scheme (http/https)"},{path:"request.method",type:"string",access:{onRequestHeaders:"read-only",onRequestBody:"read-only",onResponseHeaders:"read-only",onResponseBody:"read-only"},description:"HTTP method (GET, POST, etc.)"},{path:"request.extension",type:"string",access:{onRequestHeaders:"read-only",onRequestBody:"read-only",onResponseHeaders:"read-only",onResponseBody:"read-only"},description:"Request path extension"},{path:"request.x_real_ip",type:"string",access:{onRequestHeaders:"read-only",onRequestBody:"read-only",onResponseHeaders:"read-only",onResponseBody:"read-only"},description:"Client IP address (X-Real-IP)"},{path:"request.country",type:"string",access:{onRequestHeaders:"read-only",onRequestBody:"read-only",onResponseHeaders:"read-only",onResponseBody:"read-only"},description:"Country Code - deciphered from IP"},{path:"request.city",type:"string",access:{onRequestHeaders:"read-only",onRequestBody:"read-only",onResponseHeaders:"read-only",onResponseBody:"read-only"},description:"City name - deciphered from IP"},{path:"request.asn",type:"string",access:{onRequestHeaders:"read-only",onRequestBody:"read-only",onResponseHeaders:"read-only",onResponseBody:"read-only"},description:"ASN of the network/ISP associated with the request IP"},{path:"request.geo.lat",type:"string",access:{onRequestHeaders:"read-only",onRequestBody:"read-only",onResponseHeaders:"read-only",onResponseBody:"read-only"},description:"Latitude - deciphered from IP"},{path:"request.geo.long",type:"string",access:{onRequestHeaders:"read-only",onRequestBody:"read-only",onResponseHeaders:"read-only",onResponseBody:"read-only"},description:"Longitude - deciphered from IP"},{path:"request.region",type:"string",access:{onRequestHeaders:"read-only",onRequestBody:"read-only",onResponseHeaders:"read-only",onResponseBody:"read-only"},description:"Region - deciphered from IP"},{path:"request.continent",type:"string",access:{onRequestHeaders:"read-only",onRequestBody:"read-only",onResponseHeaders:"read-only",onResponseBody:"read-only"},description:"Continent - deciphered from IP"},{path:"request.country.name",type:"string",access:{onRequestHeaders:"read-only",onRequestBody:"read-only",onResponseHeaders:"read-only",onResponseBody:"read-only"},description:"Country name - deciphered from IP"},{path:"nginx.log_field1",type:"string",access:{onRequestHeaders:"write-only"},description:"Adds value to nginx access logs"},{path:"response.status",type:"integer",access:{onResponseHeaders:"read-only",onResponseBody:"read-only"},description:"HTTP status code"}],wa=class{constructor(){this.builtInProperties=new Map,this.customProperties=new Map,this.initializeBuiltInProperties(Wj)}initializeBuiltInProperties(e){this.builtInProperties.clear();for(let n of e)this.builtInProperties.set(n.path,n)}canGetProperty(e,n){let i=this.builtInProperties.get(e);return i?this.canGetBuiltInProperty(i,n):this.canGetCustomProperty(e,n)}canSetProperty(e,n){let i=this.builtInProperties.get(e);return i?this.canSetBuiltInProperty(i,n):this.canSetCustomProperty(e,n)}registerCustomProperty(e,n,i){this.customProperties.has(e)?this.customProperties.get(e).value=n:this.customProperties.set(e,{createdIn:i,value:n})}resetCustomPropertiesForNewContext(){for(let[e,n]of this.customProperties.entries())n.createdIn==="onRequestHeaders"&&this.customProperties.delete(e)}canGetBuiltInProperty(e,n){let i=e.access[n];return i?i==="write-only"?{allowed:!1,reason:`Property '${e.path}' is write-only in ${n}`}:{allowed:!0}:{allowed:!1,reason:`Property '${e.path}' is not accessible in ${n}`}}canSetBuiltInProperty(e,n){let i=e.access[n];return i?i==="read-only"?{allowed:!1,reason:`Property '${e.path}' is read-only in ${n}`}:{allowed:!0}:{allowed:!1,reason:`Property '${e.path}' is not accessible in ${n}`}}canGetCustomProperty(e,n){let i=this.customProperties.get(e);return i?i.createdIn==="onRequestHeaders"&&n!=="onRequestHeaders"?{allowed:!1,reason:`Custom property '${e}' was created in onRequestHeaders and is not available in ${n}`}:{allowed:!0}:{allowed:!1,reason:`Custom property '${e}' does not exist`}}canSetCustomProperty(e,n){let i=this.customProperties.get(e);return i&&i.createdIn==="onRequestHeaders"&&n!=="onRequestHeaders"?{allowed:!1,reason:`Custom property '${e}' was created in onRequestHeaders and cannot be modified in ${n}`}:{allowed:!0}}getPropertyInfo(e){let n=this.builtInProperties.get(e);if(n)return`Built-in property: ${n.description}`;let i=this.customProperties.get(e);return i?`Custom property created in ${i.createdIn}`:"Property does not exist"}};var ka=Ne(require("fs/promises")),Kr=Ne(require("path"));function Nl(t){let e={},n=t.split(`
59
- `);for(let i of n){let r=i.trim();if(!r||r.startsWith("#"))continue;let o=r.indexOf("=");if(o===-1)continue;let a=r.substring(0,o).trim(),s=r.substring(o+1).trim();(s.startsWith('"')&&s.endsWith('"')||s.startsWith("'")&&s.endsWith("'"))&&(s=s.substring(1,s.length-1)),e[a]=s}return e}async function xw(t="."){let e={},n={},i=Kr.default.join(t,".env");try{let a=await ka.default.readFile(i,"utf-8"),s=Nl(a);for(let[u,c]of Object.entries(s))if(u.startsWith("FASTEDGE_VAR_SECRET_")){let l=u.replace("FASTEDGE_VAR_SECRET_","");e[l]=c}else if(u.startsWith("FASTEDGE_VAR_ENV_")){let l=u.replace("FASTEDGE_VAR_ENV_","");n[l]=c}}catch{}let r=Kr.default.join(t,".env.secrets");try{let a=await ka.default.readFile(r,"utf-8"),s=Nl(a);Object.assign(e,s)}catch{}let o=Kr.default.join(t,".env.variables");try{let a=await ka.default.readFile(o,"utf-8"),s=Nl(a);Object.assign(n,s)}catch{}return{secrets:e,dictionary:n}}function yw(t,e){if(t)return Kr.default.isAbsolute(t)?t:Kr.default.resolve(e,t)}var Vj=new TextEncoder,Xr="http://fastedge-builtin.debug",ql="built-in",$a=class{constructor(e,n=!0){this.module=null;this.instance=null;this.currentHook=null;this.logs=[];this.rootContextId=1;this.nextContextId=2;this.currentContextId=1;this.isInitializing=!1;this.debug=process.env.PROXY_RUNNER_DEBUG==="1";this.stateManager=null;this.dotenvEnabled=!0;this.dotenvPath=".";this.memory=new xa,this.propertyResolver=new ba,this.propertyAccessControl=new wa,this.dotenvEnabled=n,this.secretStore=new gt(e?.secrets),this.dictionary=new At(e?.dictionary),this.hostFunctions=new Jr(this.memory,this.propertyResolver,this.propertyAccessControl,()=>this.currentHook,this.debug,this.secretStore,this.dictionary),this.memory.setLogCallback((i,r)=>{this.logs.push({level:i,message:r})})}setStateManager(e){this.stateManager=e}async loadDotenvIfEnabled(){if(!this.dotenvEnabled){this.logDebug("Dotenv disabled, skipping file loading");return}try{let e=await xw(this.dotenvPath);if(e.secrets&&Object.keys(e.secrets).length>0){let n=this.secretStore.getAll();this.secretStore=new gt({...n,...e.secrets}),this.logDebug(`Loaded ${Object.keys(e.secrets).length} secrets from dotenv files`)}if(e.dictionary&&Object.keys(e.dictionary).length>0){for(let[n,i]of Object.entries(e.dictionary))this.dictionary.set(n,i);this.logDebug(`Loaded ${Object.keys(e.dictionary).length} dictionary entries from dotenv files`)}this.hostFunctions=new Jr(this.memory,this.propertyResolver,this.propertyAccessControl,()=>this.currentHook,this.debug,this.secretStore,this.dictionary)}catch(e){console.error("Failed to load dotenv files:",e)}}async applyDotenv(e,n){this.dotenvEnabled=e,n!==void 0&&(this.dotenvPath=n),this.secretStore=new gt,this.dictionary=new At,await this.loadDotenvIfEnabled(),e||(this.hostFunctions=new Jr(this.memory,this.propertyResolver,this.propertyAccessControl,()=>this.currentHook,this.debug,this.secretStore,this.dictionary))}async load(e,n){n?.dotenv?.enabled!==void 0&&(this.dotenvEnabled=n.dotenv.enabled),n?.dotenv?.path!==void 0&&(this.dotenvPath=n.dotenv.path),this.resetState();let i;if(typeof e=="string"){let{readFile:r}=await import("fs/promises");i=await r(e)}else i=e;if(this.module=await WebAssembly.compile(new Uint8Array(i)),this.debug){let r=WebAssembly.Module.imports(this.module),o=WebAssembly.Module.exports(this.module);console.warn(`debug: wasm imports=${r.map(a=>`${a.module}.${a.name}`).join(", ")}`),console.warn(`debug: wasm exports=${o.map(a=>a.name).join(", ")}`)}this.logDebug("WASM module compiled and ready for hook execution"),await this.loadDotenvIfEnabled()}async callFullFlowLegacy(e,n){if(!this.module)throw new Error("WASM module not loaded");let i=n===ql||n===Xr||n.startsWith(Xr+"?")||n.startsWith(Xr+"/");n===ql&&(n=Xr,this.logDebug(`Substituted "${ql}" \u2192 ${Xr}`));let r={};if(this.propertyResolver.extractRuntimePropertiesFromUrl(n),this.logDebug(`Extracted runtime properties from URL: ${n}`),!Object.keys(e.request.headers??{}).some(S=>S.toLowerCase()==="host")){let S=new URL(n),k=S.port&&S.port!=="80"&&S.port!=="443"?`${S.hostname}:${S.port}`:S.hostname;e.request.headers=e.request.headers??{},e.request.headers.host=k,this.logDebug(`Auto-injected Host header: ${k}`)}if(this.stateManager){let S=e.request.method??"GET";this.stateManager.emitRequestStarted(n,S,e.request.headers||{},"system")}if(r.onRequestHeaders=await this.callHook({...e,hook:"onRequestHeaders"}),this.stateManager&&this.stateManager.emitHookExecuted("onRequestHeaders",r.onRequestHeaders.returnCode,r.onRequestHeaders.logs.length,r.onRequestHeaders.input,r.onRequestHeaders.output,"system"),r.onRequestHeaders.returnCode===1&&this.hostFunctions.hasLocalResponse()){let S=this.hostFunctions.getLocalResponse(),k=r.onRequestHeaders.output.response.headers;this.hostFunctions.resetLocalResponse();let P=k["content-type"]||"text/plain",{body:O,isBase64:R}=ww(S.body,P);return{hookResults:r,finalResponse:{status:S.statusCode,statusText:S.statusText,headers:k,body:O,contentType:P,isBase64:R},calculatedProperties:this.propertyResolver.getCalculatedProperties()}}let a=r.onRequestHeaders.output.request.headers,s=r.onRequestHeaders.properties;if(this.logDebug(`Headers after onRequestHeaders: ${JSON.stringify(a)}`),r.onRequestBody=await this.callHook({...e,request:{...e.request,headers:a},properties:s,hook:"onRequestBody"}),this.stateManager&&this.stateManager.emitHookExecuted("onRequestBody",r.onRequestBody.returnCode,r.onRequestBody.logs.length,r.onRequestBody.input,r.onRequestBody.output,"system"),r.onRequestBody.returnCode===1&&this.hostFunctions.hasLocalResponse()){let S=this.hostFunctions.getLocalResponse(),k=r.onRequestBody.output.response.headers;this.hostFunctions.resetLocalResponse();let P=k["content-type"]||"text/plain",{body:O,isBase64:R}=ww(S.body,P);return{hookResults:r,finalResponse:{status:S.statusCode,statusText:S.statusText,headers:k,body:O,contentType:P,isBase64:R},calculatedProperties:this.propertyResolver.getCalculatedProperties()}}let u=r.onRequestBody.output.request.headers,c=r.onRequestBody.output.request.body,l=r.onRequestBody.properties;this.logDebug(`Final headers for fetch: ${JSON.stringify(u)}`);let p=e.request.method??"GET",d,f,m,v,y,z=!1;try{if(i){this.logDebug("Using built-in responder");let V=(u["x-debugger-status"]||"").trim();if(V==="")m=200;else{let he=parseInt(V,10);m=Number.isFinite(he)&&he>=100&&he<=599?he:400,m===400&&V!=="400"&&this.logDebug(`Invalid x-debugger-status "${V}", defaulting to 400`)}v=m===200?"OK":String(m);let te=u["x-debugger-content"]||"";delete u["x-debugger-status"],delete u["x-debugger-content"],te==="status-only"?(f="",y="text/plain"):te==="body-only"?(f=c||"",y=u["content-type"]||"text/plain"):(y="application/json",f=JSON.stringify({method:p,reqHeaders:u,reqBody:c||"",requestUrl:Xr})),d={"content-type":y,"content-length":String(Buffer.byteLength(f))},this.logDebug(`Built-in responder: ${m} ${v}, mode=${te||"full"}`)}else{let V=l["request.scheme"]||"https",te=l["request.host"]||"localhost",he=l["request.path"]||"/",Te=l["request.query"]||"",se=`${V}://${te}${he}${Te?"?"+Te:""}`;this.logDebug(`Original URL: ${n}`),this.logDebug(`Modified URL: ${se}`),this.logDebug(`Fetching ${p} ${se}`);let ne={...u},ie=Object.entries(u).find(([fe])=>fe.toLowerCase()==="host");ie&&(ne["x-forwarded-host"]=ie[1],this.logDebug(`Adding x-forwarded-host: ${ie[1]}`)),ne["x-forwarded-proto"]=V,this.logDebug(`Adding x-forwarded-proto: ${V}`),ne["x-forwarded-port"]=V==="https"?"443":"80",this.logDebug(`Adding x-forwarded-port: ${ne["x-forwarded-port"]}`);let de=this.propertyResolver.resolve("request.x_real_ip");de&&de!==""&&(ne["x-real-ip"]=String(de),ne["x-forwarded-for"]=String(de),this.logDebug(`Adding x-real-ip and x-forwarded-for: ${de}`));let St={method:p,headers:ne};["POST","PUT","PATCH"].includes(p.toUpperCase())&&c&&(St.body=c);let et=await fetch(se,St);if(d={},et.headers.forEach((fe,Rc)=>{d[Rc]=fe}),y=et.headers.get("content-type")||"text/plain",m=et.status,v=et.statusText,y.startsWith("image/")||y.startsWith("video/")||y.startsWith("audio/")||y.includes("application/octet-stream")||y.includes("application/pdf")||y.includes("application/zip")){let fe=await et.arrayBuffer();f=Buffer.from(fe).toString("base64"),z=!0,this.logDebug(`Binary response converted to base64 (${fe.byteLength} bytes)`)}else f=await et.text();this.logDebug(`Fetch completed: ${m} ${v}`)}let S={...e,request:{...e.request,headers:u,body:c},response:{headers:d,body:f,status:m,statusText:v},properties:l};this.propertyAccessControl.resetCustomPropertiesForNewContext(),r.onResponseHeaders=await this.callHook({...S,hook:"onResponseHeaders"}),this.stateManager&&this.stateManager.emitHookExecuted("onResponseHeaders",r.onResponseHeaders.returnCode,r.onResponseHeaders.logs.length,r.onResponseHeaders.input,r.onResponseHeaders.output,"system");let k=r.onResponseHeaders.output.response.headers,P=r.onResponseHeaders.properties;this.logDebug(`Headers after onResponseHeaders: ${JSON.stringify(k)}`),r.onResponseBody=await this.callHook({...S,response:{...S.response,headers:k},properties:P,hook:"onResponseBody"}),this.stateManager&&this.stateManager.emitHookExecuted("onResponseBody",r.onResponseBody.returnCode,r.onResponseBody.logs.length,r.onResponseBody.input,r.onResponseBody.output,"system");let O=r.onResponseBody.output.response.headers,R=r.onResponseBody.output.response.body;this.logDebug(`Final response body length: ${R.length}`);let N=this.propertyResolver.getCalculatedProperties(),D=O["content-type"]||y;return{hookResults:r,finalResponse:{status:m,statusText:v,headers:O,body:R,contentType:D,isBase64:z},calculatedProperties:N}}catch(S){let k="Fetch failed",P="";S instanceof Error?(k=S.message,S.cause&&(P=` (cause: ${String(S.cause)})`)):k=String(S);let O=`Failed to fetch ${p} ${n}: ${k}${P}`;this.logDebug(O);let R=r.onRequestBody?.output?.request||{headers:u,body:c},N={returnCode:null,logs:[{level:4,message:O}],input:{request:R,response:{headers:{},body:""}},output:{request:R,response:{headers:{},body:""}},properties:e.properties};r.onResponseHeaders=N,r.onResponseBody=N;let D=this.propertyResolver.getCalculatedProperties();return{hookResults:r,finalResponse:{status:0,statusText:"Fetch Failed",headers:{},body:O,contentType:"text/plain"},calculatedProperties:D}}}async callHook(e){if(!this.module)throw new Error("WASM module not loaded");this.currentHook=this.getHookContext(e.hook),this.hostFunctions.resetLocalResponse();let n=this.createImports();this.instance=await WebAssembly.instantiate(this.module,n);let i=this.instance.exports.memory;if(!(i instanceof WebAssembly.Memory))throw new Error("WASM module must export memory");this.memory.setMemory(i),this.memory.setInstance(this.instance);let r=n.wasi_snapshot_preview1;if(r.initialize)try{r.initialize(this.instance)}catch{}let o=this.instance.exports._start;if(typeof o=="function")try{this.logDebug("calling _start for runtime init"),o()}catch(D){this.logDebug(`_start failed: ${String(D)}`)}this.logs=[],this.hostFunctions.setLogLevel(0);let a=ge.normalize(e.request.headers??{}),s=ge.normalize(e.response.headers??{}),u=e.request.body??"",c=e.response.body??"",l=e.request.method??"GET",p=e.response.status??200,d=e.response.statusText??"OK";this.propertyResolver.setProperties({...e.properties??{}}),this.propertyResolver.setRequestMetadata(a,l,e.request.path,e.request.scheme),this.propertyResolver.setResponseMetadata(s,p,d);let f=bw(e.properties.vm_config??e.properties.vmConfig),m=bw(e.properties.plugin_config??e.properties.pluginConfig),v=this.deriveRootId(e.properties);(!f||f.trim()==="{}")&&(v?(f=JSON.stringify({test_mode:!0,root_id:v}),this.logDebug(`vm_config defaulted to JSON root_id: ${v}`)):(f=JSON.stringify({test_mode:!0}),this.logDebug("vm_config defaulted to test_mode"))),(!m||m.trim()==="{}")&&(m=JSON.stringify({test_mode:!0}),this.logDebug("plugin_config defaulted to test_mode")),(!m||m.trim()==="{}")&&(m="",this.logDebug("plugin_config defaulted to empty")),f=_w(f),m=_w(m),this.hostFunctions.setLogs(this.logs),this.hostFunctions.setHeadersAndBodies(a,s,u,c),this.hostFunctions.setConfigs(f,m),this.ensureInitialized(f,m);let y=this.nextContextId++;this.currentContextId=y,this.hostFunctions.setCurrentContext(y),this.callIfExported("proxy_on_context_create",y,this.rootContextId);let z={request:{headers:{...a},body:u},response:{headers:{...s},body:c},properties:this.propertyResolver.getAllProperties()},{exportName:S,args:k}=this.buildHookInvocation(e.hook,a,s,u,c),P=this.callIfExported(S,...k),O=1;for(;P===O&&this.hostFunctions.hasPendingHttpCall();){let D=this.hostFunctions.takePendingHttpCall(),V=D.headers[":authority"]||D.upstream,te=D.headers[":scheme"]||"https",he=D.headers[":path"]||"/",Te=D.headers[":method"]||"GET",se=`${te}://${V}${he}`,ne={};for(let[Ce,fe]of Object.entries(D.headers))Ce.startsWith(":")||(ne[Ce]=fe);let ie={},de=new Uint8Array(0);try{let Ce=await fetch(se,{method:Te,headers:ne,body:D.body&&Te!=="GET"&&Te!=="HEAD"?Buffer.from(D.body):void 0,signal:AbortSignal.timeout(D.timeoutMs)});Ce.headers.forEach((fe,Rc)=>{ie[Rc]=fe}),de=new Uint8Array(await Ce.arrayBuffer()),this.logDebug(`http_call response: ${Ce.status} ${Ce.statusText} numHeaders=${Object.keys(ie).length} bodySize=${de.byteLength}`)}catch(Ce){let fe=`http_call failed for ${se}: ${String(Ce)}`;this.logDebug(fe),this.logs.push({level:3,message:`[host] ${fe}`}),ie={},de=new Uint8Array(0)}let St=Object.keys(ie).length,et=de.byteLength;if(this.hostFunctions.setHttpCallResponse(D.tokenId,ie,de),this.hostFunctions.resetStreamClosed(),this.callIfExported("proxy_on_http_call_response",this.currentContextId,D.tokenId,St,et,0),this.hostFunctions.isStreamClosed())break;P=this.callIfExported(S,...k)??0}this.instance=null,this.hostFunctions.clearHttpCallResponse();let R={request:{headers:{...this.hostFunctions.getRequestHeaders()},body:this.hostFunctions.getRequestBody()},response:{headers:{...this.hostFunctions.getResponseHeaders()},body:this.hostFunctions.getResponseBody()},properties:this.propertyResolver.getAllProperties()},N=this.logs.filter(D=>this.hostFunctions.shouldLog(D.level));return{returnCode:P,logs:N,input:z,output:R,properties:this.propertyResolver.getAllProperties()}}resetState(){this.logs=[],this.rootContextId=1,this.nextContextId=2,this.currentContextId=1,this.module=null,this.instance=null,this.memory.reset()}ensureInitialized(e,n){this.isInitializing=!0,this.memory.setInitializing(!0);try{this.callIfExported("proxy_on_context_create",this.rootContextId,0)}catch(o){this.logDebug(`proxy_on_context_create(root) skipped: ${String(o)}`)}let i=xi(e);this.logDebug(`vm_config bytes=${i} value=${e.replace(/\0/g,"\\0")}`);try{this.callIfExported("proxy_on_vm_start",this.rootContextId,i)}catch(o){this.logDebug(`proxy_on_vm_start skipped (expected in test mode): ${String(o)}`)}try{this.callIfExported("proxy_on_plugin_start",this.rootContextId,xi(n))}catch(o){this.logDebug(`proxy_on_plugin_start skipped: ${String(o)}`)}let r=xi(n);this.logDebug(`plugin_config bytes=${r} value=${n.replace(/\0/g,"\\0")}`);try{this.callIfExported("proxy_on_configure",this.rootContextId,r)}catch(o){this.logDebug(`proxy_on_configure skipped (expected in test mode): ${String(o)}`)}this.memory.setInitializing(!1),this.isInitializing=!1}buildHookInvocation(e,n,i,r,o){switch(e){case"onRequestHeaders":return{exportName:"proxy_on_request_headers",args:[this.currentContextId,Object.keys(n).length,0]};case"onRequestBody":return{exportName:"proxy_on_request_body",args:[this.currentContextId,xi(r),1]};case"onResponseHeaders":return{exportName:"proxy_on_response_headers",args:[this.currentContextId,Object.keys(i).length,0]};case"onResponseBody":return{exportName:"proxy_on_response_body",args:[this.currentContextId,xi(o),1]};default:throw new Error(`Unsupported hook: ${e}`)}}callIfExported(e,...n){if(!this.instance)return null;let i=this.instance.exports[e];if(typeof i!="function")return null;try{return i(...n)}catch(r){let o=r instanceof Error?r.message:String(r);throw this.logDebug(`trap in ${e}(${n.join(",")}): ${o}`),r}}createImports(){let e=new kw.WASI({version:"preview1"}),n=e.wasiImport;return{env:this.hostFunctions.createImports(),wasi_snapshot_preview1:{...n,initialize:e.initialize.bind(e),fd_write:(i,r,o,a)=>{let s=this.memory.captureFdWrite(i,r,o,a),u=n.fd_write,c=process.env.VITEST||process.env.NODE_ENV==="test";if(typeof u=="function"&&!c)try{return u(i,r,o,a)}catch(l){this.logDebug(`wasi fd_write failed: ${String(l)}`)}return a&&this.memory.writeU32(a,s),0},proc_exit:i=>((!this.isInitializing||i!==255)&&this.logs.push({level:2,message:`WASI proc_exit(${i}) intercepted`}),0)}}}deriveRootId(e){let n=["root_id","rootId","root_context","rootContext","root_context_name","rootContextName","plugin_name","pluginName","context_name","contextName"];for(let i of n){let r=e[i];if(typeof r=="string"&&r.length>0)return r}return null}getHookContext(e){switch(e){case"onRequestHeaders":return"onRequestHeaders";case"onRequestBody":return"onRequestBody";case"onResponseHeaders":return"onResponseHeaders";case"onResponseBody":return"onResponseBody";default:throw new Error(`Unknown hook name: ${e}`)}}logDebug(e){if(!this.debug)return;let n={level:0,message:`debug: ${e}`};this.logs.push(n),console.warn(n.message)}async callFullFlow(e,n,i,r,o,a,s,u,c,l){let p={hook:"",request:{headers:i,body:r,method:n},response:{headers:o,body:a,status:s,statusText:u},properties:c,enforceProductionPropertyRules:l};return this.callFullFlowLegacy(p,e)}async execute(e){throw new Error("execute() is not supported for Proxy-WASM. Use callHook() or callFullFlow() instead.")}async cleanup(){}getType(){return"proxy-wasm"}};function xi(t){return Vj.encode(t).length}function bw(t){return t==null?"":typeof t=="string"?t:JSON.stringify(t)}function _w(t){return t?t.endsWith("\0")?t:`${t}\0`:""}function ww(t,e){return e.startsWith("image/")||e.startsWith("video/")||e.startsWith("audio/")||e.includes("application/octet-stream")||e.includes("application/pdf")||e.includes("application/zip")?{body:Buffer.from(t).toString("base64"),isBase64:!0}:{body:new TextDecoder().decode(t),isBase64:!1}}var yi=require("child_process");var Sw=require("child_process"),Yr=require("fs"),ur=require("path"),Ew=require("url"),Ll=Ne(require("os")),Sa=(0,ur.dirname)((0,Ew.fileURLToPath)(__importMetaUrl));function Gj(){switch(Ll.default.platform()){case"win32":return"fastedge-run.exe";case"darwin":return"fastedge-run-darwin-arm64";case"linux":return"fastedge-run-linux-x64";default:throw new Error(`Unsupported platform: ${Ll.default.platform()}`)}}function Jj(){let t=Gj();return[(0,ur.join)(Sa,"..","fastedge-cli",t),(0,ur.join)(Sa,"fastedge-cli",t),(0,ur.join)(Sa,"..","..","fastedge-run",t),(0,ur.join)(Sa,"fastedge-run",t)]}function $w(t){if(process.platform!=="win32")try{(0,Yr.chmodSync)(t,493)}catch{}}async function Iw(){let t=process.env.FASTEDGE_RUN_PATH;if(t){if((0,Yr.existsSync)(t))return $w(t),t;throw new Error(`FASTEDGE_RUN_PATH is set to "${t}" but the file does not exist`)}for(let e of Jj())if((0,Yr.existsSync)(e))return $w(e),e;try{let e=process.platform==="win32"?"where fastedge-run":"which fastedge-run",i=(0,Sw.execSync)(e,{encoding:"utf8"}).trim().split(`
59
+ `);for(let i of n){let r=i.trim();if(!r||r.startsWith("#"))continue;let o=r.indexOf("=");if(o===-1)continue;let a=r.substring(0,o).trim(),s=r.substring(o+1).trim();(s.startsWith('"')&&s.endsWith('"')||s.startsWith("'")&&s.endsWith("'"))&&(s=s.substring(1,s.length-1)),e[a]=s}return e}async function xw(t="."){let e={},n={},i=Kr.default.join(t,".env");try{let a=await ka.default.readFile(i,"utf-8"),s=Nl(a);for(let[u,c]of Object.entries(s))if(u.startsWith("FASTEDGE_VAR_SECRET_")){let l=u.replace("FASTEDGE_VAR_SECRET_","");e[l]=c}else if(u.startsWith("FASTEDGE_VAR_ENV_")){let l=u.replace("FASTEDGE_VAR_ENV_","");n[l]=c}}catch{}let r=Kr.default.join(t,".env.secrets");try{let a=await ka.default.readFile(r,"utf-8"),s=Nl(a);Object.assign(e,s)}catch{}let o=Kr.default.join(t,".env.variables");try{let a=await ka.default.readFile(o,"utf-8"),s=Nl(a);Object.assign(n,s)}catch{}return{secrets:e,dictionary:n}}function yw(t,e){if(t)return Kr.default.isAbsolute(t)?t:Kr.default.resolve(e,t)}var Vj=new TextEncoder,Xr="http://fastedge-builtin.debug",ql="built-in",$a=class{constructor(e,n=!0){this.module=null;this.instance=null;this.currentHook=null;this.logs=[];this.rootContextId=1;this.nextContextId=2;this.currentContextId=1;this.isInitializing=!1;this.debug=process.env.PROXY_RUNNER_DEBUG==="1";this.stateManager=null;this.dotenvEnabled=!0;this.dotenvPath=".";this.memory=new xa,this.propertyResolver=new ba,this.propertyAccessControl=new wa,this.dotenvEnabled=n,this.secretStore=new gt(e?.secrets),this.dictionary=new At(e?.dictionary),this.hostFunctions=new Jr(this.memory,this.propertyResolver,this.propertyAccessControl,()=>this.currentHook,this.debug,this.secretStore,this.dictionary),this.memory.setLogCallback((i,r)=>{this.logs.push({level:i,message:r})})}setStateManager(e){this.stateManager=e}async loadDotenvIfEnabled(){if(!this.dotenvEnabled){this.logDebug("Dotenv disabled, skipping file loading");return}try{let e=await xw(this.dotenvPath);if(e.secrets&&Object.keys(e.secrets).length>0){let n=this.secretStore.getAll();this.secretStore=new gt({...n,...e.secrets}),this.logDebug(`Loaded ${Object.keys(e.secrets).length} secrets from dotenv files`)}if(e.dictionary&&Object.keys(e.dictionary).length>0){for(let[n,i]of Object.entries(e.dictionary))this.dictionary.set(n,i);this.logDebug(`Loaded ${Object.keys(e.dictionary).length} dictionary entries from dotenv files`)}this.hostFunctions=new Jr(this.memory,this.propertyResolver,this.propertyAccessControl,()=>this.currentHook,this.debug,this.secretStore,this.dictionary)}catch(e){console.error("Failed to load dotenv files:",e)}}async applyDotenv(e,n){this.dotenvEnabled=e,n!==void 0&&(this.dotenvPath=n),this.secretStore=new gt,this.dictionary=new At,await this.loadDotenvIfEnabled(),e||(this.hostFunctions=new Jr(this.memory,this.propertyResolver,this.propertyAccessControl,()=>this.currentHook,this.debug,this.secretStore,this.dictionary))}async load(e,n){n?.dotenv?.enabled!==void 0&&(this.dotenvEnabled=n.dotenv.enabled),n?.dotenv?.path!==void 0&&(this.dotenvPath=n.dotenv.path),this.resetState();let i;if(typeof e=="string"){let{readFile:r}=await import("fs/promises");i=await r(e)}else i=e;if(this.module=await WebAssembly.compile(new Uint8Array(i)),this.debug){let r=WebAssembly.Module.imports(this.module),o=WebAssembly.Module.exports(this.module);console.warn(`debug: wasm imports=${r.map(a=>`${a.module}.${a.name}`).join(", ")}`),console.warn(`debug: wasm exports=${o.map(a=>a.name).join(", ")}`)}this.logDebug("WASM module compiled and ready for hook execution"),await this.loadDotenvIfEnabled()}async callFullFlowLegacy(e,n){if(!this.module)throw new Error("WASM module not loaded");let i=n===ql||n===Xr||n.startsWith(Xr+"?")||n.startsWith(Xr+"/");n===ql&&(n=Xr,this.logDebug(`Substituted "${ql}" \u2192 ${Xr}`));let r={};if(this.propertyResolver.extractRuntimePropertiesFromUrl(n),this.logDebug(`Extracted runtime properties from URL: ${n}`),!Object.keys(e.request.headers??{}).some(S=>S.toLowerCase()==="host")){let S=new URL(n),k=S.port&&S.port!=="80"&&S.port!=="443"?`${S.hostname}:${S.port}`:S.hostname;e.request.headers=e.request.headers??{},e.request.headers.host=k,this.logDebug(`Auto-injected Host header: ${k}`)}if(this.stateManager){let S=e.request.method??"GET";this.stateManager.emitRequestStarted(n,S,e.request.headers||{},"system")}if(r.onRequestHeaders=await this.callHook({...e,hook:"onRequestHeaders"}),this.stateManager&&this.stateManager.emitHookExecuted("onRequestHeaders",r.onRequestHeaders.returnCode,r.onRequestHeaders.logs.length,r.onRequestHeaders.input,r.onRequestHeaders.output,"system"),r.onRequestHeaders.returnCode===1&&this.hostFunctions.hasLocalResponse()){let S=this.hostFunctions.getLocalResponse(),k=r.onRequestHeaders.output.response.headers;this.hostFunctions.resetLocalResponse();let P=k["content-type"]||"text/plain",{body:O,isBase64:R}=ww(S.body,P);return{hookResults:r,finalResponse:{status:S.statusCode,statusText:S.statusText,headers:k,body:O,contentType:P,isBase64:R},calculatedProperties:this.propertyResolver.getCalculatedProperties()}}let a=r.onRequestHeaders.output.request.headers,s=r.onRequestHeaders.properties;if(this.logDebug(`Headers after onRequestHeaders: ${JSON.stringify(a)}`),r.onRequestBody=await this.callHook({...e,request:{...e.request,headers:a},properties:s,hook:"onRequestBody"}),this.stateManager&&this.stateManager.emitHookExecuted("onRequestBody",r.onRequestBody.returnCode,r.onRequestBody.logs.length,r.onRequestBody.input,r.onRequestBody.output,"system"),r.onRequestBody.returnCode===1&&this.hostFunctions.hasLocalResponse()){let S=this.hostFunctions.getLocalResponse(),k=r.onRequestBody.output.response.headers;this.hostFunctions.resetLocalResponse();let P=k["content-type"]||"text/plain",{body:O,isBase64:R}=ww(S.body,P);return{hookResults:r,finalResponse:{status:S.statusCode,statusText:S.statusText,headers:k,body:O,contentType:P,isBase64:R},calculatedProperties:this.propertyResolver.getCalculatedProperties()}}let u=r.onRequestBody.output.request.headers,c=r.onRequestBody.output.request.body,l=r.onRequestBody.properties;this.logDebug(`Final headers for fetch: ${JSON.stringify(u)}`);let p=e.request.method??"GET",d,f,m,v,y,z=!1;try{if(i){this.logDebug("Using built-in responder");let V=(u["x-debugger-status"]||"").trim();if(V==="")m=200;else{let he=parseInt(V,10);m=Number.isFinite(he)&&he>=100&&he<=599?he:400,m===400&&V!=="400"&&this.logDebug(`Invalid x-debugger-status "${V}", defaulting to 400`)}v=m===200?"OK":String(m);let te=u["x-debugger-content"]||"";delete u["x-debugger-status"],delete u["x-debugger-content"],te==="status-only"?(f="",y="text/plain"):te==="body-only"?(f=c||"",y=u["content-type"]||"text/plain"):(y="application/json",f=JSON.stringify({method:p,reqHeaders:u,reqBody:c||"",requestUrl:Xr})),d={"content-type":y,"content-length":String(Buffer.byteLength(f))},this.logDebug(`Built-in responder: ${m} ${v}, mode=${te||"full"}`)}else{let V=l["request.scheme"]||"https",te=l["request.host"]||"localhost",he=l["request.path"]||"/",Te=l["request.query"]||"",se=`${V}://${te}${he}${Te?"?"+Te:""}`;this.logDebug(`Original URL: ${n}`),this.logDebug(`Modified URL: ${se}`),this.logDebug(`Fetching ${p} ${se}`);let ne={...u},ie=Object.entries(u).find(([fe])=>fe.toLowerCase()==="host");ie&&(ne["x-forwarded-host"]=ie[1],this.logDebug(`Adding x-forwarded-host: ${ie[1]}`)),ne["x-forwarded-proto"]=V,this.logDebug(`Adding x-forwarded-proto: ${V}`),ne["x-forwarded-port"]=V==="https"?"443":"80",this.logDebug(`Adding x-forwarded-port: ${ne["x-forwarded-port"]}`);let de=this.propertyResolver.resolve("request.x_real_ip");de&&de!==""&&(ne["x-real-ip"]=String(de),ne["x-forwarded-for"]=String(de),this.logDebug(`Adding x-real-ip and x-forwarded-for: ${de}`));let St={method:p,headers:ne};["POST","PUT","PATCH"].includes(p.toUpperCase())&&c&&(St.body=c);let et=await fetch(se,St);if(d={},et.headers.forEach((fe,Rc)=>{d[Rc]=fe}),y=et.headers.get("content-type")||"text/plain",m=et.status,v=et.statusText,y.startsWith("image/")||y.startsWith("video/")||y.startsWith("audio/")||y.includes("application/octet-stream")||y.includes("application/pdf")||y.includes("application/zip")){let fe=await et.arrayBuffer();f=Buffer.from(fe).toString("base64"),z=!0,this.logDebug(`Binary response converted to base64 (${fe.byteLength} bytes)`)}else f=await et.text();this.logDebug(`Fetch completed: ${m} ${v}`)}let S={...e,request:{...e.request,headers:u,body:c},response:{headers:d,body:f,status:m,statusText:v},properties:l};this.propertyAccessControl.resetCustomPropertiesForNewContext(),r.onResponseHeaders=await this.callHook({...S,hook:"onResponseHeaders"}),this.stateManager&&this.stateManager.emitHookExecuted("onResponseHeaders",r.onResponseHeaders.returnCode,r.onResponseHeaders.logs.length,r.onResponseHeaders.input,r.onResponseHeaders.output,"system");let k=r.onResponseHeaders.output.response.headers,P=r.onResponseHeaders.properties;this.logDebug(`Headers after onResponseHeaders: ${JSON.stringify(k)}`),r.onResponseBody=await this.callHook({...S,response:{...S.response,headers:k},properties:P,hook:"onResponseBody"}),this.stateManager&&this.stateManager.emitHookExecuted("onResponseBody",r.onResponseBody.returnCode,r.onResponseBody.logs.length,r.onResponseBody.input,r.onResponseBody.output,"system");let O=r.onResponseBody.output.response.headers,R=r.onResponseBody.output.response.body;this.logDebug(`Final response body length: ${R.length}`);let N=this.propertyResolver.getCalculatedProperties(),D=O["content-type"]||y;return{hookResults:r,finalResponse:{status:m,statusText:v,headers:O,body:R,contentType:D,isBase64:z},calculatedProperties:N}}catch(S){let k="Fetch failed",P="";S instanceof Error?(k=S.message,S.cause&&(P=` (cause: ${String(S.cause)})`)):k=String(S);let O=`Failed to fetch ${p} ${n}: ${k}${P}`;this.logDebug(O);let R=r.onRequestBody?.output?.request||{headers:u,body:c},N={returnCode:null,logs:[{level:4,message:O}],input:{request:R,response:{headers:{},body:""}},output:{request:R,response:{headers:{},body:""}},properties:e.properties};r.onResponseHeaders=N,r.onResponseBody=N;let D=this.propertyResolver.getCalculatedProperties();return{hookResults:r,finalResponse:{status:0,statusText:"Fetch Failed",headers:{},body:O,contentType:"text/plain"},calculatedProperties:D}}}async callHook(e){if(!this.module)throw new Error("WASM module not loaded");this.currentHook=this.getHookContext(e.hook),this.hostFunctions.resetLocalResponse();let n=this.createImports();this.instance=await WebAssembly.instantiate(this.module,n);let i=this.instance.exports.memory;if(!(i instanceof WebAssembly.Memory))throw new Error("WASM module must export memory");this.memory.setMemory(i),this.memory.setInstance(this.instance);let r=n.wasi_snapshot_preview1;if(r.initialize)try{r.initialize(this.instance)}catch{}let o=this.instance.exports._start;if(typeof o=="function")try{this.logDebug("calling _start for runtime init"),o()}catch(D){this.logDebug(`_start failed: ${String(D)}`)}this.logs=[],this.hostFunctions.setLogLevel(0);let a=ge.normalize(e.request.headers??{}),s=ge.normalize(e.response.headers??{}),u=e.request.body??"",c=e.response.body??"",l=e.request.method??"GET",p=e.response.status??200,d=e.response.statusText??"OK";this.propertyResolver.setProperties({...e.properties??{}}),this.propertyResolver.setRequestMetadata(a,l,e.request.path,e.request.scheme),this.propertyResolver.setResponseMetadata(s,p,d);let f=bw(e.properties.vm_config??e.properties.vmConfig),m=bw(e.properties.plugin_config??e.properties.pluginConfig),v=this.deriveRootId(e.properties);(!f||f.trim()==="{}")&&(v?(f=JSON.stringify({test_mode:!0,root_id:v}),this.logDebug(`vm_config defaulted to JSON root_id: ${v}`)):(f=JSON.stringify({test_mode:!0}),this.logDebug("vm_config defaulted to test_mode"))),(!m||m.trim()==="{}")&&(m=JSON.stringify({test_mode:!0}),this.logDebug("plugin_config defaulted to test_mode")),(!m||m.trim()==="{}")&&(m="",this.logDebug("plugin_config defaulted to empty")),f=_w(f),m=_w(m),this.hostFunctions.setLogs(this.logs),this.hostFunctions.setHeadersAndBodies(a,s,u,c),this.hostFunctions.setConfigs(f,m),this.ensureInitialized(f,m);let y=this.nextContextId++;this.currentContextId=y,this.hostFunctions.setCurrentContext(y),this.callIfExported("proxy_on_context_create",y,this.rootContextId);let z={request:{headers:{...a},body:u},response:{headers:{...s},body:c},properties:this.propertyResolver.getAllProperties()},{exportName:S,args:k}=this.buildHookInvocation(e.hook,a,s,u,c),P=this.callIfExported(S,...k),O=1;for(;P===O&&this.hostFunctions.hasPendingHttpCall();){let D=this.hostFunctions.takePendingHttpCall(),V=D.headers[":authority"]||D.upstream,te=D.headers[":scheme"]||"https",he=D.headers[":path"]||"/",Te=D.headers[":method"]||"GET",se=`${te}://${V}${he}`,ne={};for(let[Ce,fe]of Object.entries(D.headers))Ce.startsWith(":")||(ne[Ce]=fe);let ie={},de=new Uint8Array(0);try{let Ce=await fetch(se,{method:Te,headers:ne,body:D.body&&Te!=="GET"&&Te!=="HEAD"?Buffer.from(D.body):void 0,signal:AbortSignal.timeout(D.timeoutMs)});Ce.headers.forEach((fe,Rc)=>{ie[Rc]=fe}),de=new Uint8Array(await Ce.arrayBuffer()),this.logDebug(`http_call response: ${Ce.status} ${Ce.statusText} numHeaders=${Object.keys(ie).length} bodySize=${de.byteLength}`)}catch(Ce){let fe=`http_call failed for ${se}: ${String(Ce)}`;this.logDebug(fe),this.logs.push({level:3,message:`[host] ${fe}`}),ie={},de=new Uint8Array(0)}let St=Object.keys(ie).length,et=de.byteLength;if(this.hostFunctions.setHttpCallResponse(D.tokenId,ie,de),this.hostFunctions.resetStreamClosed(),this.callIfExported("proxy_on_http_call_response",this.currentContextId,D.tokenId,St,et,0),this.hostFunctions.isStreamClosed())break;P=this.callIfExported(S,...k)??0}this.instance=null,this.hostFunctions.clearHttpCallResponse();let R={request:{headers:{...this.hostFunctions.getRequestHeaders()},body:this.hostFunctions.getRequestBody()},response:{headers:{...this.hostFunctions.getResponseHeaders()},body:this.hostFunctions.getResponseBody()},properties:this.propertyResolver.getAllProperties()},N=this.logs.filter(D=>this.hostFunctions.shouldLog(D.level));return{returnCode:P,logs:N,input:z,output:R,properties:this.propertyResolver.getAllProperties()}}resetState(){this.logs=[],this.rootContextId=1,this.nextContextId=2,this.currentContextId=1,this.module=null,this.instance=null,this.memory.reset()}ensureInitialized(e,n){this.isInitializing=!0,this.memory.setInitializing(!0);try{this.callIfExported("proxy_on_context_create",this.rootContextId,0)}catch(o){this.logDebug(`proxy_on_context_create(root) skipped: ${String(o)}`)}let i=xi(e);this.logDebug(`vm_config bytes=${i} value=${e.replace(/\0/g,"\\0")}`);try{this.callIfExported("proxy_on_vm_start",this.rootContextId,i)}catch(o){this.logDebug(`proxy_on_vm_start skipped (expected in test mode): ${String(o)}`)}try{this.callIfExported("proxy_on_plugin_start",this.rootContextId,xi(n))}catch(o){this.logDebug(`proxy_on_plugin_start skipped: ${String(o)}`)}let r=xi(n);this.logDebug(`plugin_config bytes=${r} value=${n.replace(/\0/g,"\\0")}`);try{this.callIfExported("proxy_on_configure",this.rootContextId,r)}catch(o){this.logDebug(`proxy_on_configure skipped (expected in test mode): ${String(o)}`)}this.memory.setInitializing(!1),this.isInitializing=!1}buildHookInvocation(e,n,i,r,o){switch(e){case"onRequestHeaders":return{exportName:"proxy_on_request_headers",args:[this.currentContextId,Object.keys(n).length,0]};case"onRequestBody":return{exportName:"proxy_on_request_body",args:[this.currentContextId,xi(r),1]};case"onResponseHeaders":return{exportName:"proxy_on_response_headers",args:[this.currentContextId,Object.keys(i).length,0]};case"onResponseBody":return{exportName:"proxy_on_response_body",args:[this.currentContextId,xi(o),1]};default:throw new Error(`Unsupported hook: ${e}`)}}callIfExported(e,...n){if(!this.instance)return null;let i=this.instance.exports[e];if(typeof i!="function")return null;try{return i(...n)}catch(r){let o=r instanceof Error?r.message:String(r);throw this.logDebug(`trap in ${e}(${n.join(",")}): ${o}`),r}}createImports(){let e=new kw.WASI({version:"preview1",env:this.dictionary.getAll()}),n=e.wasiImport;return{env:this.hostFunctions.createImports(),wasi_snapshot_preview1:{...n,initialize:e.initialize.bind(e),fd_write:(i,r,o,a)=>{let s=this.memory.captureFdWrite(i,r,o,a),u=n.fd_write,c=process.env.VITEST||process.env.NODE_ENV==="test";if(typeof u=="function"&&!c)try{return u(i,r,o,a)}catch(l){this.logDebug(`wasi fd_write failed: ${String(l)}`)}return a&&this.memory.writeU32(a,s),0},proc_exit:i=>((!this.isInitializing||i!==255)&&this.logs.push({level:2,message:`WASI proc_exit(${i}) intercepted`}),0)}}}deriveRootId(e){let n=["root_id","rootId","root_context","rootContext","root_context_name","rootContextName","plugin_name","pluginName","context_name","contextName"];for(let i of n){let r=e[i];if(typeof r=="string"&&r.length>0)return r}return null}getHookContext(e){switch(e){case"onRequestHeaders":return"onRequestHeaders";case"onRequestBody":return"onRequestBody";case"onResponseHeaders":return"onResponseHeaders";case"onResponseBody":return"onResponseBody";default:throw new Error(`Unknown hook name: ${e}`)}}logDebug(e){if(!this.debug)return;let n={level:0,message:`debug: ${e}`};this.logs.push(n),console.warn(n.message)}async callFullFlow(e,n,i,r,o,a,s,u,c,l){let p={hook:"",request:{headers:i,body:r,method:n},response:{headers:o,body:a,status:s,statusText:u},properties:c,enforceProductionPropertyRules:l};return this.callFullFlowLegacy(p,e)}async execute(e){throw new Error("execute() is not supported for Proxy-WASM. Use callHook() or callFullFlow() instead.")}async cleanup(){}getType(){return"proxy-wasm"}};function xi(t){return Vj.encode(t).length}function bw(t){return t==null?"":typeof t=="string"?t:JSON.stringify(t)}function _w(t){return t?t.endsWith("\0")?t:`${t}\0`:""}function ww(t,e){return e.startsWith("image/")||e.startsWith("video/")||e.startsWith("audio/")||e.includes("application/octet-stream")||e.includes("application/pdf")||e.includes("application/zip")?{body:Buffer.from(t).toString("base64"),isBase64:!0}:{body:new TextDecoder().decode(t),isBase64:!1}}var yi=require("child_process");var Sw=require("child_process"),Yr=require("fs"),ur=require("path"),Ew=require("url"),Ll=Ne(require("os")),Sa=(0,ur.dirname)((0,Ew.fileURLToPath)(__importMetaUrl));function Gj(){switch(Ll.default.platform()){case"win32":return"fastedge-run.exe";case"darwin":return"fastedge-run-darwin-arm64";case"linux":return"fastedge-run-linux-x64";default:throw new Error(`Unsupported platform: ${Ll.default.platform()}`)}}function Jj(){let t=Gj();return[(0,ur.join)(Sa,"..","fastedge-cli",t),(0,ur.join)(Sa,"fastedge-cli",t),(0,ur.join)(Sa,"..","..","fastedge-run",t),(0,ur.join)(Sa,"fastedge-run",t)]}function $w(t){if(process.platform!=="win32")try{(0,Yr.chmodSync)(t,493)}catch{}}async function Iw(){let t=process.env.FASTEDGE_RUN_PATH;if(t){if((0,Yr.existsSync)(t))return $w(t),t;throw new Error(`FASTEDGE_RUN_PATH is set to "${t}" but the file does not exist`)}for(let e of Jj())if((0,Yr.existsSync)(e))return $w(e),e;try{let e=process.platform==="win32"?"where fastedge-run":"which fastedge-run",i=(0,Sw.execSync)(e,{encoding:"utf8"}).trim().split(`
60
60
  `)[0].trim();if(i&&(0,Yr.existsSync)(i))return i}catch{}throw new Error(`fastedge-run CLI not found in any of these locations:
61
61
  1. FASTEDGE_RUN_PATH environment variable
62
62
  2. Bundled binary in fastedge-cli/ (project root)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gcoredev/fastedge-test",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -76,8 +76,8 @@
76
76
  },
77
77
  "dependencies": {
78
78
  "@assemblyscript/wasi-shim": "^0.1.0",
79
- "@gcoredev/fastedge-sdk-js": "^2.2.0",
80
- "@gcoredev/proxy-wasm-sdk-as": "^1.2.2",
79
+ "@gcoredev/fastedge-sdk-js": "^2.2.2",
80
+ "@gcoredev/proxy-wasm-sdk-as": "^1.2.3",
81
81
  "@types/ws": "^8.18.1",
82
82
  "express": "^4.19.2",
83
83
  "immer": "^11.1.3",