exlo 0.0.7 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/createConfig.mjs +5 -5
- package/dist/cli/index.mjs +2 -2
- package/dist/defineConfig.mjs +1 -1
- package/dist/plugins/restApi/index.mjs +1 -1
- package/dist/standalone.js +1 -1
- package/dist/standalone.mjs +1 -1
- package/package.json +12 -12
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{access as
|
|
2
|
-
`;
|
|
3
|
-
`),
|
|
4
|
-
`,u=u.replace('"#plugins"',
|
|
5
|
-
export default defineConfig(${u})`,y.extname(t)||(t+=".ts");try{await
|
|
1
|
+
import{access as w,writeFile as v}from"node:fs/promises";import y from"node:path";import o from"node:path";var O=new Set(["NODE_ENV","AWS_SAM_LOCAL","IS_OFFLINE","IS_LOCAL","AWS_EXECUTION_ENV","AWS_LAMBDA_FUNCTION_VERSION","AWS_LAMBDA_FUNCTION_NAME","_HANDLER"]),k=/process\.env(?:\??)\s*(?:\.\s*([A-Za-z_$][A-Za-z0-9_$]*)|\[\s*(['"])(.*?)\2\s*\])\s*(=)?/g,N=/\{\s*([^}]+?)\s*\}\s*=\s*process\.env\b/g;function h(e){let n=new Set,t;for(;t=k.exec(e);){let r=t[1]||t[3];t[4]!=="="&&n.add(r)}let i;for(;i=N.exec(e);){let u=i[1].split(",").map(a=>a.trim());for(let a of u){if(!a)continue;let s=a.split(/[:=]/)[0].trim();s&&(O.has(s)||n.add(s))}}return[...n]}async function p(e){let n=new Set;if(!e.functions)return{plugins:[]};let t=[],i={};for(let[s,l]of Object.entries(e.functions)){let d=l.handler,f=o.resolve(d.slice(0,d.lastIndexOf(".")));i[f]=s,t.push(f)}let r=await import("esbuild"),u={packages:"external",format:"esm",...e.build?.esbuild,platform:"node",target:"node24",write:!1,metafile:!0,bundle:!0,minify:!0,outdir:"dist",entryPoints:t},a=await r.build(u);for(let[s,l]of Object.entries(a.metafile.outputs)){if(!l.entryPoint)continue;let d=l.entryPoint.slice(0,-o.extname(l.entryPoint).length),f=i[o.resolve(d)],x=o.resolve(s),m=a.outputFiles.find(c=>c.path==x);if(!m)continue;let g=h(m.text);if(g.length){e.functions[f].environment??={};for(let c of g)e.functions[f].environment[c]="TODO"}if(l.exports.length==1){let c=e.functions[f].handler,b=l.exports[0];c.endsWith(`.${b}`)||(e.functions[f].handler=c.slice(0,c.lastIndexOf(".")),e.functions[f].handler+=`.${b}`)}for(let c of l.imports)switch(c.path){case"@aws-sdk/client-s3":n.add("s3");break;case"@aws-sdk/client-sns":n.add("sns");break;case"@aws-sdk/client-sqs":n.add("sqs");break;case"@aws-sdk/client-dynamodb":n.add("dynamodb");break;case"@aws-sdk/client-secrets-manager":n.add("secrets-manager");break;default:break}}return{plugins:Array.from(n.values())}}function A(e){delete e.config,delete e.debug,e.port||delete e.port;let n=new Set;if(e.functions){for(let t of Object.values(e.functions))delete t.name,n.add(t.runtime);if(n.size<2)for(let t of Object.values(e.functions))delete t.runtime}e.build&&(e.build.esbuild&&(Object.keys(e.build.esbuild).length||delete e.build.esbuild),e.build.optimizeBuild||delete e.build.optimizeBuild,e.build.shimRequire||delete e.build.shimRequire,Object.keys(e.build).length||delete e.build),e.defaults&&(e.defaults.environment&&(Object.keys(e.defaults.environment).length||delete e.defaults.environment),e.defaults.timeout==3&&delete e.defaults.timeout,e.defaults.runtime||delete e.defaults.runtime,Object.keys(e.defaults).length||delete e.defaults)}async function M(e){let{plugins:n}=await p(e),t=typeof e.config=="string"?e.config:"exlo.config.ts";A(e);let i=[],r=[];if(n.length){e.plugins=["#plugins"];for(let s of n)switch(s){case"s3":r.push('import { s3Plugin } from "exlo/s3"'),i.push("s3Plugin({ buckets: {} })");break;case"sns":r.push('import { snsPlugin } from "exlo/sns"'),i.push("snsPlugin()");break;case"sqs":r.push('import { sqsPlugin } from "exlo/sqs"'),i.push("sqsPlugin()");break;case"dynamodb":r.push('import { dynamoDbPlugin } from "exlo/dynamodb"'),i.push("dynamoDbPlugin()");break;case"secrets-manager":r.push('import { secretsManagerPlugin } from "exlo/secretsManager"'),i.push("secretsManagerPlugin()");break;default:break}}let u=JSON.stringify(e,null,2),a=`import { defineConfig } from "exlo/defineConfig";
|
|
2
|
+
`;r.length&&(a+=r.sort((s,l)=>s.localeCompare(l)).join(`;
|
|
3
|
+
`),a+=`
|
|
4
|
+
`,u=u.replace('"#plugins"',i.join(", "))),a+=`
|
|
5
|
+
export default defineConfig(${u})`,y.extname(t)||(t+=".ts");try{await w(t);let s=y.extname(t);t=`${t.slice(0,t.lastIndexOf("."))}.${Date.now()}${s}`}catch{}await v(t,a),process.exit(0)}export{M as createConfig};
|
package/dist/cli/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{readFile as I}from"node:fs/promises";import p from"node:path";import{pathToFileURL as O}from"node:url";import{parseArgs as Y}from"node:util";
|
|
2
|
+
import{readFile as I}from"node:fs/promises";import p from"node:path";import{pathToFileURL as O}from"node:url";import{parseArgs as Y}from"node:util";var j="exlo",b="0.0.8";var g=!1,R=e=>{g=e},A=()=>g,l=(e,t)=>{g&&console.log(`\x1B[${e}m${t}\x1B[0m`)},C=e=>console.log(`\x1B[31m${e}\x1B[0m`),$=e=>l("32",e),q=e=>l("33",e),L=e=>l("36",e),S=e=>l("90",e),F=e=>l("94",e),_=e=>l("95",e),D=e=>g?console.log(e):void 0,n={GREEN:$,YELLOW:q,CYAN:L,BR_BLUE:F,RED:C,GREY:S,PINK:_,setDebug:R,getDebug:A,info:D};var y={config:{type:"string",short:"c",default:"exlo.config.ts",description:"Path to exlo 'defineConfig' file."},debug:{type:"boolean",default:!1,description:"Enable debug mode. When enabled exlo will print usefull informations."},create:{type:"boolean",default:!1,description:"Create exlo 'defineConfig' file based on passed options."},runtime:{type:"string",short:"r",description:"Lambda default runtime (ex: nodejs22.x, python3.7, ruby2.7 etc.)."},timeout:{type:"string",short:"t",default:"3",description:"Lambda default timeout."},port:{type:"string",short:"p",default:"0",description:"Lambda server port."},definitions:{type:"string",short:"d",description:"Path to .json, .mjs, .cjs file with Lambda function definitions."},functions:{type:"string",short:"f",multiple:!0,description:"Glob pattern to automatically find and define Lambda handlers."},exclude:{type:"string",short:"X",multiple:!0,default:[".(test|spec)."],description:"RegExp string to exclude found enteries from --functions."},"handler-name":{type:"string",default:"handler",description:"Handler function name. To be used with --functions."},env:{type:"string",short:"e",multiple:!0,default:[],description:"Environment variables to be injected into Lambdas. All existing AWS_* are automatically injected.",example:"-e API_KEY=supersecret -e API_URL=https://website.com"},"optimize-build":{type:"boolean",default:!1,description:"externalize dependencies and other stuff"},"shim-require":{type:"boolean",default:!1,description:"shim 'require()', '__dirname' and '__filename' when bundeling Lambdas with ESM format"},help:{type:"boolean",short:"h",skipFullPrint:!0},version:{type:"boolean",short:"v",skipFullPrint:!0},"esbuild-external":{type:"string",multiple:!0,skip:!0},"esbuild-resolveExtensions":{type:"string",multiple:!0,skip:!0},"esbuild-mainFields":{type:"string",multiple:!0,skip:!0},"esbuild-conditions":{type:"string",multiple:!0,skip:!0},"esbuild-entryPoints":{type:"string",multiple:!0,skip:!0},"esbuild-inject":{type:"string",multiple:!0,skip:!0},"esbuild-nodePaths":{type:"string",multiple:!0,skip:!0}};function M(){n.setDebug(!0),n.GREY("Usage examples:"),console.log("exlo -c exlo.config.ts"),console.log(`exlo -p 3000 --debug --functions "src/lambdas/**/*.ts"
|
|
3
3
|
`),n.BR_BLUE("Options:");for(let[e,t]of Object.entries(y)){let i=e;if(t.skip)continue;if(t.short&&(i+=`, -${t.short}`),t.skipFullPrint){n.CYAN(` --${i}
|
|
4
4
|
`);continue}let s=` type: ${t.type}`;t.description&&(s+=`
|
|
5
5
|
description: ${t.description}`),"default"in t&&(s+=`
|
|
@@ -8,4 +8,4 @@ import{readFile as I}from"node:fs/promises";import p from"node:path";import{path
|
|
|
8
8
|
`,n.CYAN(` --${i}`),n.GREY(s)}n.CYAN(" --esbuild-[option]"),n.GREY(`
|
|
9
9
|
description: where 'options' is one of esbuild build options`),n.GREY(`
|
|
10
10
|
example: exlo --esbuild-external="@aws-sdk/*" --esbuild-external=react --esbuild-format=esm --esbuild-outExtension..js=.mjs --esbuild-outExtension..css=.CSS`),console.log(`
|
|
11
|
-
${j} v${b}`),process.exit(0)}function v(e,t){return!e||Number.isNaN(e)?t:Number(e)}async function
|
|
11
|
+
${j} v${b}`),process.exit(0)}function v(e,t){return!e||Number.isNaN(e)?t:Number(e)}async function P(e){if(e){if(e.endsWith(".js"))throw new Error("Only .json, .mjs and .cjs are supported for --definitions option.");if(e.endsWith(".json"))return JSON.parse(await I(e,"utf-8")).functions;if(e.endsWith(".mjs")||e.endsWith(".cjs"))return(await import(O(p.resolve(process.cwd(),e)).href)).functions}}async function G(e,t,i){if(!i)return;let s=Number(process.versions.node.slice(0,process.versions.node.indexOf(".")));if(s<22)throw new Error("--functions option is only supported on Node22 and higher.");let{glob:u}=await import("node:fs/promises"),m={};for await(let a of u(i)){if(e.some(N=>a.match(N)))continue;let f=p.basename(p.dirname(a)),r=p.parse(a),d;r.name=="index"?m[f]?d=a.replaceAll(p.sep,"_"):d=f:m[r.name]?m[`${f}_${r.name}`]?d=a.replaceAll(p.sep,"_"):d=`${f}_${r.name}`:d=r.name,m[d]={name:d,handler:a.replace(r.ext,`.${t}`),runtime:r.ext==".py"?"python3.7":r.ext==".rb"?"ruby2.7":`nodejs${s}.x`}}return m}function W(e){let t={};for(let i of e){let[s,...u]=i.split("=");t[s]=u.join("=")}return t}var{values:o}=Y({strict:!1,options:y}),{port:B,config:U,debug:z,help:T,runtime:V,definitions:k,timeout:H,functions:x,exclude:w,env:K,create:J}=o;o.version?(console.log(b),process.exit(0)):T&&M();if(k&&x)throw new Error("Can not use --definitions (-d) and --functions (-f) together.");o.handlerName=o["handler-name"];var Q=o.handlerName,X=Array.isArray(w)?w.filter(e=>typeof e=="string").map(e=>new RegExp(e)):[],Z=x?await G(X,Q,x):await P(k),c={};for(let e of Object.keys(o).filter(t=>t.startsWith("esbuild-"))){let t=e.split("esbuild-")[1];if(t.includes(".")){let i=t.indexOf("."),s=t.slice(0,i),u=t.slice(i+1);c[s]||(c[s]={}),c[s][u]=o[e]}else c[t]=o[e]}var ee=o["optimize-build"],te=o["shim-require"],E={debug:z,config:U,port:v(B,0),functions:Z,build:{esbuild:c,optimizeBuild:ee,shimRequire:te},defaults:{environment:W(K),runtime:V,timeout:v(H,3)}};J?import("exlo/internal/createConfig").then(async({createConfig:e})=>{await e(E)}):import("exlo").then(async({run:e})=>{await e(E)});
|
package/dist/defineConfig.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var h="0.0.
|
|
1
|
+
var h="0.0.8";function k(e){let c=new Set;e.plugins&&(e.plugins=e.plugins.filter((i,a)=>typeof i!="object"||!i||!("name"in i)?!1:((!i.name||!i.name.length||typeof i.name!="string")&&(i.name=`plugin-${a}`,console.warn(`No Plugin name provided at index ${a}`)),c.has(i.name)?i.name=i.name+a:c.add(i.name),!0)));async function f({stop:i,lambdas:a,region:g,esbuild:v,getServices:y,setService:d,addLambda:p,log:l,setEndpoint:b,getEndpoint:x,getAwsProviderDefaults:C,setAwsProviderDefaults:S}){let r={build:{esbuild:e?.build?.esbuild??{},shimRequire:e?.build?.shimRequire,optimizeBuild:e?.build?.optimizeBuild},server:{port:e.server?.port,setEndpointEnvVar:e.server?.setEndpointEnvVar},onKill:[]};if(e.defaults&&typeof e.defaults=="object"&&!Array.isArray(e.defaults)&&S(e.defaults),e.functions&&typeof e.functions=="object"&&!Array.isArray(e.functions))for(let[m,s]of Object.entries(e.functions))p(m,s);e.services&&(e.services.sqs&&d("sqs",e.services.sqs),e.services.sns&&d("sns",e.services.sns),e.services.dynamodb&&d("dynamodb",e.services.dynamodb));let o={stop:i,lambdas:a,region:g,esbuild:v,options:e,config:r,getServices:y,setService:d,addLambda:p,log:l,setEndpoint:b,getEndpoint:x,getAwsProviderDefaults:C};if(e.plugins){r.server.onReady=async(s,n)=>{for(let t of e.plugins)if(t.server?.onReady)try{await t.server.onReady.call(o,s,n)}catch(u){l.RED(t.name),console.error(u)}},r.buildCallback=async(s,n)=>{for(let t of e.plugins)if(t.buildCallback)try{await t.buildCallback.call(o,s,n)}catch(u){l.RED(t.name),console.error(u),n||process.exit(1)}};let m=e.plugins.reduce((s,n)=>(n.server?.request?.length&&s.push(...n.server.request),s),[]);m?.length&&(r.server.request=m.map(s=>(s.callback=s.callback.bind(o),s)));for(let s of e.plugins)if(s.onKill&&r.onKill.push(s.onKill.bind(o)),s.onInit)try{await s.onInit.call(o)}catch(n){throw l.RED(s.name),n}}return r}return f.plugins=e.plugins??[],f}export{k as defineConfig,h as exloVersion};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{randomUUID as oe}from"node:crypto";import{randomUUID as $}from"node:crypto";import{createServer as te}from"node:http";import{EventSourceMapping as Ae}from"exlo/internal/esm";import{EventSourceMapping as pe}from"exlo/internal/esm";var S=c=>Object.prototype.toString.call(c)=="[object Object]";import _ from"ajv";import A from"ajv-formats";var g=new _({discriminator:!1,useDefaults:!1,validateFormats:!0,jtd:!1,strictRequired:!0,allowUnionTypes:!0,unevaluated:!1,formats:{"date-time":A.get("date-time"),email:A.get("email"),hostname:A.get("hostname"),ipv4:A.get("ipv4"),ipv6:A.get("ipv6"),uri:A.get("uri")}});g.removeKeyword("if");g.removeKeyword("else");g.removeKeyword("then");g.removeKeyword("const");g.removeKeyword("contains");g.removeKeyword("contentEncoding");g.removeKeyword("contentMediaType");g.removeKeyword("contentSchema");g.removeKeyword("nullable");g.removeKeyword("prefixItems");g.removeKeyword("example");g.removeKeyword("examples");g.removeKeyword("deprecated");g.removeKeyword("readOnly");g.removeKeyword("writeOnly");g.removeKeyword("$comment");g.removeKeyword("$defs");g.removeKeyword("exclusiveMinimum");g.removeKeyword("exclusiveMaximum");g.removeKeyword("propertyNames");g.removeKeyword("$id");g.removeKeyword("id");g.addKeyword({keyword:["exclusiveMaximum","exclusiveMinimum"],type:["number"],schemaType:["number"],$data:!0,code(c){if(c.it.rootId!="http://json-schema.org/draft-07/schema#")throw new Error(`unsupported keyword "${c.keyword}"`)}});g.addKeyword({keyword:"propertyNames",type:["object"],schemaType:["object","boolean"],code(c){if(c.it.rootId!="http://json-schema.org/draft-07/schema#")throw new Error('unsupported keyword "propertyNames"')}});g.addKeyword({keyword:"$id",type:["object"],schemaType:["string"],code(c){if(c.it.rootId!="http://json-schema.org/draft-07/schema#")throw new Error('unsupported keyword "$id"')}});g.addKeyword({keyword:"id",schemaType:["string"]});var F=c=>{if(c&&typeof c=="object"&&!Array.isArray(c)){let e;return c.$schema?e={...c,$schema:"http://json-schema.org/draft-07/schema#"}:e=c,g.compile(e)}throw new Error("API Gateway validator Schema must be an object")};var w=class extends Error{res;constructor(e){super("RestApiError"),this.res=e}setHeaders(e){this.res.headers.Connection="keep-alive",this.res.headers["x-amzn-RequestId"]=e,this.res.body?this.res.headers["Content-Length"]=Buffer.byteLength(this.res.body,"utf-8").toString():this.res.headers["Content-Length"]="0"}completeRequest(e,t){e.shouldKeepAlive=!1,this.setHeaders(t),e.writeHead(this.res.statusCode,this.res.statusText,this.res.headers),e.end(this.res.body)}},P=class extends w{constructor(){super({statusCode:405,statusText:"Method Not Allowed",headers:{"Content-Type":"null"},body:"Unsupported HTTP method"})}},M=class extends w{constructor(){super({statusCode:415,statusText:"Unsupported Media Type",headers:{"Content-Type":"application/json","x-amzn-ErrorType":"BadRequestException"},body:'{"message": "Unsupported Media Type"}'})}},I=class extends w{constructor(e){super({statusCode:400,statusText:"Bad Request",headers:{"Content-Type":"application/json","x-amzn-ErrorType":"BadRequestException"},body:e})}},T=class extends w{constructor(){super({statusCode:403,statusText:"Forbidden",headers:{"Content-Type":"application/json","x-amzn-ErrorType":"ForbiddenException"},body:'{"message": "Forbidden"}'})}},E=class extends w{constructor(){super({statusCode:403,statusText:"Forbidden",headers:{"Content-Type":"application/json","x-amzn-ErrorType":"MissingAuthenticationTokenException"},body:'{"message": "Missing Authentication Token"}'})}},f=class extends w{constructor(e=502){super({statusCode:e,statusText:"BadGateway",headers:{"Content-Type":"application/json","x-amzn-ErrorType":"InternalServerErrorException"},body:'{"message": "Internal server error"}'})}};function N(c,e,t){let n=e.split("/").filter(Boolean),a={};if(!n.length){let o;return t[c]?o=c:t.ANY&&(o="ANY"),o?{matchedMethod:o,pathParams:a,resource:t,resourcePath:"/"}:void 0}let d=q(c,n,t,a,"");if(d?.resource)return{matchedMethod:d.matchedMethod,pathParams:a,resource:d.resource,resourcePath:d?.resourcePath}}function q(c,e,t,n,a){if(!e.length)return;let d=`/${e[0]}`;if(d in t){let r=t[d],i=`${a}${d}`;if(e.length===1){let u=r[c]?c:r.ANY?"ANY":null;if(u)return{matchedMethod:u,resource:r,resourcePath:i}}return q(c,e.slice(1),r,n,i)}let o=Object.keys(t).find(r=>r.startsWith("/{")&&!r.endsWith("+}"));if(o){let r=o.slice(2,-1);n[r]=encodeURIComponent(e[0]);let i=t[o],u=`${a}${o}`;if(e.length===1){let h=i[c]?c:i.ANY?"ANY":void 0;if(h)return{matchedMethod:h,resource:i,resourcePath:u}}return q(c,e.slice(1),i,n,u)}let s=Object.keys(t).find(r=>r.startsWith("/{")&&r.endsWith("+}"));if(s){let r=s.match(/\{(.+?)\+\}/)?.[1];r&&(n[r]=e.map(encodeURIComponent).join("/"));let i=t[s],u=`${a}${s}`;if(i.ANY)return{matchedMethod:"ANY",resource:i,resourcePath:u}}}import{getRandomValues as k}from"node:crypto";import{networkInterfaces as B}from"node:os";var C="abcdefghijklmnopqrstuvwxyz0123456789",H=`ABCDEFGHIJKLMNOPQRSTUVWXYZ${C}`,J=40;function O(){let c="",e=new Uint8Array(45);k(e);for(let t=0;t<J;t++)c+=H[e[t]%H.length];return c}var X=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function j(){let c=new Date,e=String(c.getUTCDate()).padStart(2,"0"),t=X[c.getUTCMonth()],n=c.getUTCFullYear(),a=String(c.getUTCHours()).padStart(2,"0"),d=String(c.getUTCMinutes()).padStart(2,"0"),o=String(c.getUTCSeconds()).padStart(2,"0");return{requestTime:`${e}/${t}/${n}:${a}:${d}:${o} +0000`,requestTimeEpoch:c.getTime()}}function U(){let c="127.0.0.1";if(B){let e=Object.values(B()).reduce((t,n)=>(t.push(...n),t),[])?.filter(t=>!t.internal&&t.family==="IPv4").find(Boolean)?.address;e&&(c=e)}return c}function L(){let c=Math.floor(Date.now()/1e3).toString(16),e=k(new Uint8Array(12)).reduce((t,n)=>t+n.toString(16).padStart(2,"0"),"");return`1-${c}-${e}`}function Z(){return k(new Uint8Array(8)).reduce((c,e)=>c+e.toString(16).padStart(2,"0"),"")}function ee(c){let e=c.split("-");if(e.length===3){let t=(BigInt(`0x${e[2]}`)+BigInt(2)).toString(16).padStart(24,"0");return`${e[0]}-${e[1]}-${t}`}return c}function D(c){if(!c)return`Root=${L()}`;let e=c.match(/Root=([^\s;]+)/),t=e?e[1]:L(),n=ee(t);return`Self=1-${Z()};Root=${n}`}function Q(){let c="",e=new Uint8Array(6);crypto.getRandomValues(e);for(let t=0;t<6;t++)c+=C[e[t]%C.length];return c}function V(){let c=new Uint8Array(8);return crypto.getRandomValues(c),Buffer.from(String.fromCharCode(...c),"utf-8").toString("base64url")}var se=["connection","content-md5","content-length","expect","max-forwards","proxy-authenticate","server","te","host","trailer","transfer-encoding","upgrade","www-authenticate","x-forwarded-port","x-forwarded-proto"],re=["AWS4-HMAC-SHA256","Credential","SignedHeaders","Signature"],K=["DELETE","GET","HEAD","OPTIONS","PATCH","POST","PUT"],G=["authorization","connection","content-md5","max-forwards","user-agent","www-authenticate","date","server","content-length"],z=["expect","host","proxy-authenticate","te","transfer-encoding","trailer","upgrade","via"],ne=/^[a-z0-9-.+#!{}_'`]+\/([a-z0-9-.+#!{}_'`]+|\*{1})$/,v=class c{constructor({id:e,ip:t,getLambdas:n,port:a,stage:d,resources:o,requireStagePrefixInRequestPath:s,models:r,binaryMediaTypes:i,resolveLambdaNameFromArn:u},h){this.logger=h;if(e)this.id=e;else{let l=$();this.id=l.slice(0,l.indexOf("-"))}if(c.servers.find(l=>l.id==this.id))throw new Error(`[REST API Gateway] An API with the same id (${this.id}) already exists.`);this.ip=t,this.port=a,this.stage=d??"dev",this.getLambdas=n,this.resources=o,this.resolveLambdaNameFromArn=u,this.deploymentId=Q(),r&&typeof r=="object"?this.models=r:this.models={},typeof s=="boolean"&&(this.requireStagePrefixInRequestPath=s),Array.isArray(i)&&this.compileBinaryTypes(i),this.compileResources(this.resources)}static servers=[];server;id;ip;port;stage;requireStagePrefixInRequestPath=!0;deploymentId;apiKeys=[];resolveLambdaNameFromArn;binaryMediaTypes=[];getLambdas;resources;compiledResources={};sockets=[];models;compileBinaryTypes(e){for(let t of e){let n=t.toLowerCase();if(n=="*/*"){this.binaryMediaTypes.push(/^.*$/);continue}if(ne.test(n))if(n.endsWith("/*")){let a=new RegExp(`^${n.slice(0,-1)}[a-z0-9-_.$~+#'{}\`!*]+$`);this.binaryMediaTypes.push(a)}else{let a=new RegExp(`^${n}$`);this.binaryMediaTypes.push(a)}}}compileResources(e){for(let[t,n]of Object.entries(e))t.startsWith("/")&&this.compileResources(n);if(!e.resourceId){let t=$();e.resourceId=t.slice(0,t.indexOf("-"))}this.compiledResources[e.resourceId]={};for(let t of K){let n=e[t];if(!n)continue;let a=[],d=[],o={};if(n.request){if(n.request.queryStringParameters)for(let[s,r]of Object.entries(n.request.queryStringParameters))r.required&&a.push(s);if(n.request.headers)for(let[s,r]of Object.entries(n.request.headers))r.required&&d.push(s);if(n.request.body)for(let[s,r]of Object.entries(n.request.body)){let i=this.models[r];o[s]=F(i)}}this.compiledResources[e.resourceId][t]={requiredQueryParams:a,requiredHeaders:d,body:o}}}async start(){this.server=te((t,n)=>{this.requestHandler(t,n)}),await new Promise(t=>{this.server.listen(this.port,t)}),c.servers.push(this),this.port=this.server.address().port,this.server.on("connection",t=>{t.on("close",()=>{let n=this.sockets.findIndex(a=>a==t);n!=-1&&this.sockets.splice(n,1)}),this.sockets.push(t)});let e=this.requireStagePrefixInRequestPath?`/${this.stage}`:"";this.printPaths(this.resources,e)}printPaths(e,t){let n=Object.keys(e);for(let a of n){let d=e[a];if(!a.startsWith("/"))continue;let o=Object.keys(d).filter(r=>K.includes(r)),s=`${t}${a}`;o.length&&this.logger.CYAN(`${o.join(", ")} http://localhost:${this.port}${s}`),this.printPaths(d,s)}}dropConnections(){for(let e of this.sockets)e.writable&&e.destroy()}stop(){this.server?.close()}findResourceFromRequest(e){let{method:t,url:n}=e,a=n.indexOf("?");a==-1&&(a=void 0);let d=n.slice(0,a),o=d;for(;o!="/"&&o.endsWith("/");)o=o.slice(0,-1);let s;a&&(s=n.slice(a));let r=o;if(this.requireStagePrefixInRequestPath){if(!o.startsWith(`/${this.stage}`))return;r=o.slice(`/${this.stage}`.length)}let i=N(t,r,this.resources);if(i)return{resource:i.resource,pathname:o,requestPath:d,rawQueryStringParameters:s,matchedMethod:i.matchedMethod,requestMethod:t,pathParams:i.pathParams,resourcePath:i.resourcePath}}static async collectBody(e,t){let n=Buffer.alloc(0);return e.on("data",a=>{n=Buffer.concat([n,a])}),new Promise(a=>{e.on("end",async()=>{a(n?n.toString(t?"base64":"utf-8"):null)})})}static getQueryStrings(e){let t=null,n=null;if(!e)return{queryStringParameters:n,multiValueQueryStringParameters:t};let a=e.slice(1).split("&"),d={};for(let s of a){let[r,i]=s.split("="),u=r.split(";"),h=i?.split(";")??[""];if(u.length==1&&h.length==1){let R=decodeURIComponent(u[0]),b=decodeURIComponent(h[0]);R in d?d[R].push(b):d[R]=[b];continue}let l=u.slice(0,-1),p=u[u.length-1],m=decodeURIComponent(p),y=decodeURIComponent(h[0]);if(m in d?d[m].push(y):d[m]=[y],h.length>1){let R=h.slice(1);for(let b of R)l.push(b)}for(let R of l){let b=decodeURIComponent(R);b in d?d[b].push(""):d[b]=[""]}}let o=Object.keys(d);if(o.length){n={},t={};for(let s of o.sort()){let r=d[s];t[s]=r,n[s]=r[r.length-1]}}return{queryStringParameters:n,multiValueQueryStringParameters:t}}static shouldDropHeader(e){return!!se.includes(e)}static parseMultiValueHeaders(e){let t={},n={},a={};for(let o=0;o<e.length;o=o+2){let s=e[o],r=s.toLowerCase(),i=e[o+1]?.trim()??"";if(i=Buffer.from(i,"utf-8").toString("latin1"),r=="x-amzn-trace-id"){t["X-Amzn-Trace-Id"]=[i];continue}if(r=="user-agent"){t["User-Agent"]=[i];continue}if(r=="x-forwarded-for"){a[s]||(a[s]=[]),a[s].push(i);continue}if(c.shouldDropHeader(r))continue;let u=n[r];u&&u!=s&&delete t[u],s in t||(t[s]=[]),t[s].push(i),n[r]=s}let d=Object.keys(a);if(d.length){let o=d[d.length-1];t["X-Forwarded-For"]=a[o]}return t}getHeaders(e){let t=c.parseMultiValueHeaders(e),n=t["X-Amzn-Trace-Id"]?t["X-Amzn-Trace-Id"][0]:void 0;t.Host=[`localhost:${this.port}`],t["X-Amzn-Trace-Id"]=[D(n)],t["X-Forwarded-Proto"]=["http"],t["X-Forwarded-Port"]=[String(this.port)],t["X-Forwarded-For"]||(t["X-Forwarded-For"]=[]),t["X-Forwarded-For"].push(this.ip);let a={},d={},o=Object.keys(t).sort((l,p)=>l.toLowerCase().localeCompare(p.toLowerCase())),s,r,i,u="*/*",h;for(let l of o){let p=t[l],m=l.toLowerCase();if(m=="x-http-method-override"){s=p[p.length-1];continue}if(m=="x-api-key")r=p[p.length-1];else if(m=="authorization"){if(h=p[p.length-1],h.startsWith("AWS4-HMAC-SHA256 Credential=")&&re.every(y=>h.includes(y)))continue}else if(m=="content-type")i=p[p.length-1].toLowerCase();else if(m=="accept")u=p[p.length-1].toLowerCase().split(",")[0];else if(l=="X-Forwarded-For"){let y=p.join(", ");a[l]=[y],d[l]=y;continue}a[l]=p,d[l]=p[p.length-1]}return{headers:d,multiValueHeaders:a,overrideMethod:s,apiKey:r,contentType:i,accept:u,authorization:h}}createRequestContext({foundRequest:e,requestId:t,httpMethod:n,req:a,headers:d,apiKey:o}){let s,r;if(o){s={apiKey:o};let m=this.apiKeys.find(y=>y.value==o)?.id;m&&(r={apiKeyId:m})}let i={cognitoIdentityPoolId:null,accountId:null,cognitoIdentityId:null,...s,caller:null,sourceIp:a.socket.remoteAddress?.includes(":")?this.ip:a.socket.remoteAddress,principalOrgId:null,accessKey:null,cognitoAuthenticationType:null,cognitoAuthenticationProvider:null,userArn:null,...r,userAgent:d["User-Agent"]??null,user:null},{requestTime:u,requestTimeEpoch:h}=j(),l=e.requestPath;return this.requireStagePrefixInRequestPath||(l=`/${this.stage}${e.requestPath}`),{resourceId:e.resource.resourceId,resourcePath:e.resourcePath,httpMethod:n,extendedRequestId:V(),requestTime:u,path:l,accountId:"123456789012",protocol:"HTTP/1.1",stage:this.stage,domainPrefix:"localhost",requestTimeEpoch:h,requestId:t,identity:i,domainName:`http://localhost:${this.port}`,deploymentId:this.deploymentId,apiId:this.id}}async createPayloadFromRequest(e,t,n){let{rawHeaders:a,method:d}=e,{headers:o,multiValueHeaders:s,overrideMethod:r,apiKey:i,contentType:u,accept:h}=this.getHeaders(a),l=!1;u&&this.binaryMediaTypes.find(Y=>Y.test(u))&&(l=!0);let p=await c.collectBody(e,l)||null,{queryStringParameters:m,multiValueQueryStringParameters:y}=c.getQueryStrings(t.rawQueryStringParameters),R=null;Object.keys(t.pathParams).length&&(R=t.pathParams);let b=r??d,W=`/${this.stage}`,x=t.requestPath;return this.requireStagePrefixInRequestPath&&(x=x.slice(W.length),x||(x="/")),{payload:{resource:t.resourcePath,path:x,httpMethod:b,headers:o,multiValueHeaders:s,queryStringParameters:m,multiValueQueryStringParameters:y,pathParameters:R,stageVariables:null,requestContext:this.createRequestContext({foundRequest:t,requestId:n,apiKey:i,req:e,headers:o,httpMethod:b}),isBase64Encoded:l,body:p},contentType:u,accept:h}}validateRequest(e,t,n,a){let{payload:d,contentType:o}=e;if(!K.includes(d.httpMethod))throw new P;if(t.requiresApiKey&&!d.requestContext.identity.apiKeyId)throw new T;let s=o??"application/json";if(s.startsWith("application/json;")){let u=s.replaceAll(" ","").split(";").find(h=>h.startsWith("charset="));if(u&&u.replaceAll(",","")!="charset=utf-8")throw new M;s="application/json"}let r=this.compiledResources[n]?.[a];if(t.validate&&r){if(t.validate.query&&r.requiredQueryParams.length){if(!d.queryStringParameters)throw new I(`{"message": "Missing required request parameters: [${r.requiredQueryParams.join(", ")}]"}`);let l=r.requiredQueryParams.filter(p=>!d.queryStringParameters[p]);if(l.length)throw new I(`{"message": "Missing required request parameters: [${l.join(", ")}]"}`)}if(t.validate.headers&&r.requiredHeaders.length){let l=r.requiredHeaders.filter(p=>!d.headers[p]);if(l.length)throw new I(`{"message": "Missing required request parameters: [${l.join(", ")}]"}`)}if(!t.validate.body||d.isBase64Encoded||this.binaryMediaTypes.find(l=>l.test("anything")))return;let i=r.body[s];if(typeof i!="function")return;if(!d.body)throw new I('{"message":[Unknown error parsing request body]}');let u;try{u=JSON.parse(d.body)}catch{throw new I('{"message":[Unknown error parsing request body]}')}if(!i(u)){this.logger.getDebug()&&console.warn(i.errors);let l=i.errors.map(p=>`instancePath '${p.instancePath}' ${p.message}`).join(", ");throw new I(JSON.stringify({message:`[${l}]`}))}}}async invokeProxyLambda(e,t){let d=e;if(d.startsWith("arn:aws:lambda")){let i=d.split(":");(i.length==7||i.length==8)&&(d=i[6])}let o=this.getLambdas(),s=o.find(i=>i.name==d);if(!s&&typeof this.resolveLambdaNameFromArn=="function"){let i=this.resolveLambdaNameFromArn(e);s=o.find(u=>u.name==i)}if(!s)throw this.logger.RED(`REST APiG can not find Lambda ${e}`),new f;return await s.invoke(t)}async invokeIntegration(e,t,n,a){let d=e.matchedMethod,o=e.requestMethod,s=e.resource[d];try{let r=await this.createPayloadFromRequest(t,e,a),{payload:i,accept:u}=r;if(this.validateRequest(r,s,e.resource.resourceId,d),s.integration.lambda?.arn){let h=await this.invokeProxyLambda(s.integration.lambda.arn,i);this.responseFromIntegration(n,h,"lambda-proxy",a,u,o)}else if(typeof s.integration.mock=="function"){let h=await s.integration.mock(i);this.responseFromIntegration(n,h,"lambda-proxy",a,u,o)}else this.logger.RED("REST APiG must have integration"),n.statusCode=500,n.end("No resource integration found")}catch(r){if(r instanceof w){r.completeRequest(n,a);return}console.error(r),new f().completeRequest(n,a)}}async requestHandler(e,t){let n=this.findResourceFromRequest(e),a=$();n?await this.invokeIntegration(n,e,t,a):new E().completeRequest(t,a)}parseIntegrationResponseHeaders(e){let t={},n=typeof e.multiValueHeaders;if(S(e.multiValueHeaders))for(let[o,s]of Object.entries(e.multiValueHeaders)){let r=o,i=o.toLowerCase();if(i=="content-type")r="Content-Type";else if(G.includes(i)||i.startsWith("x-amzn-remapped-"))r=`x-amzn-Remapped-${r}`;else if(z.includes(i))continue;t[r]=[];for(let u of s)if(typeof u=="string")t[r].push(u);else if(typeof u=="number"||typeof u=="boolean")t[r].push(String(u));else if(u===null)t[r].includes("")||t[r].push("");else throw this.logger.RED(`Invalid integration response headers. MultiValueHeader '${r}' values must be string, number, boolean or null.`),new f}else if(n!="undefined"&&n!==null)throw this.logger.RED("Invalid integration response headers. multiValueHeaders must be an object of with string[] as value type."),new f;if(typeof e.headers=="undefined")return t;if(S(e.headers))for(let[o,s]of Object.entries(e.headers)){let r=o,i=o.toLowerCase();if(i=="content-type")r="Content-Type";else if(G.includes(i)||i.startsWith("x-amzn-remapped-"))r=`x-amzn-Remapped-${r}`;else if(z.includes(i))continue;if(t[r]||(t[r]=[]),typeof s=="string")t[r].includes(s)||t[r].push(s);else if(typeof s=="number"||typeof s=="boolean"){let u=String(s);t[r].includes(u)||t[r].push(u)}else if(s===null)t[r].includes("")||t[r].push("");else if(typeof s<"u")throw this.logger.RED(`Invalid integration response headers. Header '${r}' must be string, number, boolean or null.`),new f}else if(e.headers!==null)throw this.logger.RED("Invalid integration response headers. Headers must be an object or null."),new f;return t}parseIntegrationResponse(e,t){if(!S(e))throw this.logger.RED("Invalid integration response."),new f;let n=["statusCode","body","headers","isBase64Encoded","multiValueHeaders"],a=Object.keys(e).find(i=>!n.includes(i));if(a)throw this.logger.RED(`Invalid integration response. Field '${a}' is not supported.`),new f;let d=200,o;if(e.statusCode){if(Number.isNaN(e.statusCode))throw this.logger.RED("Invalid integration response statusCode"),new f;let i=Number(e.statusCode);if(!(i>99&&i<600))throw this.logger.RED("Invalid integration response statusCode"),new f;d=i}let s=typeof e.body;if(s=="string")o=e.body;else if(s=="number")Number.isNaN(e.body)||(o=String(e.body));else if(s=="boolean")o=String(e.body);else if(s!="undefined"&&e.body!==null)throw this.logger.RED("Invalid integration response body"),new f;if(o&&e.isBase64Encoded&&this.binaryMediaTypes.find(i=>i.test(t))){let i=Buffer.from(o,"base64");if(i.toString("base64")!=o)throw this.logger.RED("Invalid integration response body. Incorrect body base64 encoding"),new f;o=i}let r=this.parseIntegrationResponseHeaders(e);return{statusCode:d,body:o,headers:r}}responseFromIntegration(e,t,n,a,d,o){try{let s=this.parseIntegrationResponse(t,d);e.shouldKeepAlive=!1,s.headers.Connection=["keep-alive"],s.headers["x-amzn-RequestId"]=[a],s.headers["Content-Length"]=["0"],s.body&&s.statusCode!=204&&(s.headers["Content-Length"]=[Buffer.byteLength(s.body,typeof s.body=="string"?"utf-8":"base64").toString()]),s.headers["Content-Type"]?s.headers["Content-Type"]=[s.headers["Content-Type"][0]]:s.headers["Content-Type"]=["application/json"],o=="HEAD"&&s.headers["Content-Length"][0]!="0"&&(s.headers["x-amzn-Remapped-Content-Length"]||(s.headers["x-amzn-Remapped-Content-Length"]=[]),s.headers["x-amzn-Remapped-Content-Length"].push(s.headers["Content-Length"][0])),e.writeHead(s.statusCode,s.headers),o=="HEAD"?e.end():e.end(s.body)}catch(s){if(s instanceof w){s.completeRequest(e,a);return}console.error(s),new f().completeRequest(e,a)}}};var ie=U(),Ge=c=>{let e=c.gateways,t=c.apiKeys??[],n=c.usagePlans??[],a={name:"rest-api-plugin",onKill(){for(let d of v.servers)d.stop();v.servers=[]},shared:{gateways:e},server:{async onReady(){let d=[];for(let s of t){if(!s.id){let r=oe();s.id=r.slice(0,r.indexOf("-"))}s.value||(s.value=O(),console.log("API Key",s.name,":",s.value)),d.push(s)}let o={};for(let s of n)for(let r of s.apiKeys){let i=d.find(u=>u.id==r.keyId||u.name==r.keyId);if(!i)throw new Error(`[REST Api - Usage Plan] Can not find API Key with id: "${r.keyId}"`);o[r.apiId]||(o[r.apiId]=[]),o[r.apiId].push(i)}for(let s of e){let r=new v({ip:ie,...s,getLambdas:()=>this.lambdas},this.log),i=o[r.id];i&&(r.apiKeys=i),await r.start();let u=a.shared.gateways.find(h=>h.id==s.id);u&&(u.id=r.id,u.port=r.port,u.stage=r.stage),console.log(`REST API [${r.id}]`,`http://localhost:${r.port}`),r.server?.unref()}}},buildCallback(d,o){if(o)for(let s of v.servers)s.dropConnections()}};return a};export{Ge as restApiPlugin};
|
|
1
|
+
import{randomUUID as oe}from"node:crypto";import{randomUUID as $}from"node:crypto";import{createServer as te}from"node:http";import{EventSourceMapping as Ae}from"exlo/internal/esm";import{EventSourceMapping as pe}from"exlo/internal/esm";var S=a=>Object.prototype.toString.call(a)=="[object Object]";import _ from"ajv";import A from"ajv-formats";var g=new _({discriminator:!1,useDefaults:!1,validateFormats:!0,jtd:!1,strictRequired:!0,allowUnionTypes:!0,unevaluated:!1,formats:{"date-time":A.get("date-time"),email:A.get("email"),hostname:A.get("hostname"),ipv4:A.get("ipv4"),ipv6:A.get("ipv6"),uri:A.get("uri")}});g.removeKeyword("if");g.removeKeyword("else");g.removeKeyword("then");g.removeKeyword("const");g.removeKeyword("contains");g.removeKeyword("contentEncoding");g.removeKeyword("contentMediaType");g.removeKeyword("contentSchema");g.removeKeyword("nullable");g.removeKeyword("prefixItems");g.removeKeyword("example");g.removeKeyword("examples");g.removeKeyword("deprecated");g.removeKeyword("readOnly");g.removeKeyword("writeOnly");g.removeKeyword("$comment");g.removeKeyword("$defs");g.removeKeyword("exclusiveMinimum");g.removeKeyword("exclusiveMaximum");g.removeKeyword("propertyNames");g.removeKeyword("$id");g.removeKeyword("id");g.addKeyword({keyword:["exclusiveMaximum","exclusiveMinimum"],type:["number"],schemaType:["number"],$data:!0,code(a){if(a.it.rootId!="http://json-schema.org/draft-07/schema#")throw new Error(`unsupported keyword "${a.keyword}"`)}});g.addKeyword({keyword:"propertyNames",type:["object"],schemaType:["object","boolean"],code(a){if(a.it.rootId!="http://json-schema.org/draft-07/schema#")throw new Error('unsupported keyword "propertyNames"')}});g.addKeyword({keyword:"$id",type:["object"],schemaType:["string"],code(a){if(a.it.rootId!="http://json-schema.org/draft-07/schema#")throw new Error('unsupported keyword "$id"')}});g.addKeyword({keyword:"id",schemaType:["string"]});var F=a=>{if(a&&typeof a=="object"&&!Array.isArray(a)){let e;return a.$schema?e={...a,$schema:"http://json-schema.org/draft-07/schema#"}:e=a,g.compile(e)}throw new Error("API Gateway validator Schema must be an object")};var w=class extends Error{res;constructor(e){super("RestApiError"),this.res=e}setHeaders(e){this.res.headers.Connection="keep-alive",this.res.headers["x-amzn-RequestId"]=e,this.res.body?this.res.headers["Content-Length"]=Buffer.byteLength(this.res.body,"utf-8").toString():this.res.headers["Content-Length"]="0"}completeRequest(e,t){e.shouldKeepAlive=!1,this.setHeaders(t),e.writeHead(this.res.statusCode,this.res.statusText,this.res.headers),e.end(this.res.body)}},P=class extends w{constructor(){super({statusCode:405,statusText:"Method Not Allowed",headers:{"Content-Type":"null"},body:"Unsupported HTTP method"})}},M=class extends w{constructor(){super({statusCode:415,statusText:"Unsupported Media Type",headers:{"Content-Type":"application/json","x-amzn-ErrorType":"BadRequestException"},body:'{"message": "Unsupported Media Type"}'})}},I=class extends w{constructor(e){super({statusCode:400,statusText:"Bad Request",headers:{"Content-Type":"application/json","x-amzn-ErrorType":"BadRequestException"},body:e})}},T=class extends w{constructor(){super({statusCode:403,statusText:"Forbidden",headers:{"Content-Type":"application/json","x-amzn-ErrorType":"ForbiddenException"},body:'{"message": "Forbidden"}'})}},E=class extends w{constructor(){super({statusCode:403,statusText:"Forbidden",headers:{"Content-Type":"application/json","x-amzn-ErrorType":"MissingAuthenticationTokenException"},body:'{"message": "Missing Authentication Token"}'})}},f=class extends w{constructor(e=502){super({statusCode:e,statusText:"BadGateway",headers:{"Content-Type":"application/json","x-amzn-ErrorType":"InternalServerErrorException"},body:'{"message": "Internal server error"}'})}};function N(a,e,t){let n=e.split("/").filter(Boolean),c={};if(!n.length){let i;return t[a]?i=a:t.ANY&&(i="ANY"),i?{matchedMethod:i,pathParams:c,resource:t,resourcePath:"/"}:void 0}let d=q(a,n,t,c,"");if(d?.resource)return{matchedMethod:d.matchedMethod,pathParams:c,resource:d.resource,resourcePath:d?.resourcePath}}function q(a,e,t,n,c){if(!e.length)return;let d=`/${e[0]}`;if(d in t){let r=t[d],o=`${c}${d}`;if(e.length===1){let u=r[a]?a:r.ANY?"ANY":null;if(u)return{matchedMethod:u,resource:r,resourcePath:o}}return q(a,e.slice(1),r,n,o)}let i=Object.keys(t).find(r=>r.startsWith("/{")&&!r.endsWith("+}"));if(i){let r=i.slice(2,-1);n[r]=encodeURIComponent(e[0]);let o=t[i],u=`${c}${i}`;if(e.length===1){let h=o[a]?a:o.ANY?"ANY":void 0;if(h)return{matchedMethod:h,resource:o,resourcePath:u}}return q(a,e.slice(1),o,n,u)}let s=Object.keys(t).find(r=>r.startsWith("/{")&&r.endsWith("+}"));if(s){let r=s.match(/\{(.+?)\+\}/)?.[1];r&&(n[r]=e.map(encodeURIComponent).join("/"));let o=t[s],u=`${c}${s}`;if(o[a])return{matchedMethod:a,resource:o,resourcePath:u};if(o.ANY)return{matchedMethod:"ANY",resource:o,resourcePath:u}}}import{getRandomValues as k}from"node:crypto";import{networkInterfaces as B}from"node:os";var C="abcdefghijklmnopqrstuvwxyz0123456789",H=`ABCDEFGHIJKLMNOPQRSTUVWXYZ${C}`,J=40;function O(){let a="",e=new Uint8Array(45);k(e);for(let t=0;t<J;t++)a+=H[e[t]%H.length];return a}var X=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function j(){let a=new Date,e=String(a.getUTCDate()).padStart(2,"0"),t=X[a.getUTCMonth()],n=a.getUTCFullYear(),c=String(a.getUTCHours()).padStart(2,"0"),d=String(a.getUTCMinutes()).padStart(2,"0"),i=String(a.getUTCSeconds()).padStart(2,"0");return{requestTime:`${e}/${t}/${n}:${c}:${d}:${i} +0000`,requestTimeEpoch:a.getTime()}}function U(){let a="127.0.0.1";if(B){let e=Object.values(B()).reduce((t,n)=>(t.push(...n),t),[])?.filter(t=>!t.internal&&t.family==="IPv4").find(Boolean)?.address;e&&(a=e)}return a}function L(){let a=Math.floor(Date.now()/1e3).toString(16),e=k(new Uint8Array(12)).reduce((t,n)=>t+n.toString(16).padStart(2,"0"),"");return`1-${a}-${e}`}function Z(){return k(new Uint8Array(8)).reduce((a,e)=>a+e.toString(16).padStart(2,"0"),"")}function ee(a){let e=a.split("-");if(e.length===3){let t=(BigInt(`0x${e[2]}`)+BigInt(2)).toString(16).padStart(24,"0");return`${e[0]}-${e[1]}-${t}`}return a}function D(a){if(!a)return`Root=${L()}`;let e=a.match(/Root=([^\s;]+)/),t=e?e[1]:L(),n=ee(t);return`Self=1-${Z()};Root=${n}`}function Q(){let a="",e=new Uint8Array(6);crypto.getRandomValues(e);for(let t=0;t<6;t++)a+=C[e[t]%C.length];return a}function V(){let a=new Uint8Array(8);return crypto.getRandomValues(a),Buffer.from(String.fromCharCode(...a),"utf-8").toString("base64url")}var se=["connection","content-md5","content-length","expect","max-forwards","proxy-authenticate","server","te","host","trailer","transfer-encoding","upgrade","www-authenticate","x-forwarded-port","x-forwarded-proto"],re=["AWS4-HMAC-SHA256","Credential","SignedHeaders","Signature"],K=["DELETE","GET","HEAD","OPTIONS","PATCH","POST","PUT"],G=["authorization","connection","content-md5","max-forwards","user-agent","www-authenticate","date","server","content-length"],z=["expect","host","proxy-authenticate","te","transfer-encoding","trailer","upgrade","via"],ne=/^[a-z0-9-.+#!{}_'`]+\/([a-z0-9-.+#!{}_'`]+|\*{1})$/,v=class a{constructor({id:e,ip:t,getLambdas:n,port:c,stage:d,resources:i,requireStagePrefixInRequestPath:s,models:r,binaryMediaTypes:o,resolveLambdaNameFromArn:u},h){this.logger=h;if(e)this.id=e;else{let l=$();this.id=l.slice(0,l.indexOf("-"))}if(a.servers.find(l=>l.id==this.id))throw new Error(`[REST API Gateway] An API with the same id (${this.id}) already exists.`);this.ip=t,this.port=c,this.stage=d??"dev",this.getLambdas=n,this.resources=i,this.resolveLambdaNameFromArn=u,this.deploymentId=Q(),r&&typeof r=="object"?this.models=r:this.models={},typeof s=="boolean"&&(this.requireStagePrefixInRequestPath=s),Array.isArray(o)&&this.compileBinaryTypes(o),this.compileResources(this.resources)}static servers=[];server;id;ip;port;stage;requireStagePrefixInRequestPath=!0;deploymentId;apiKeys=[];resolveLambdaNameFromArn;binaryMediaTypes=[];getLambdas;resources;compiledResources={};sockets=[];models;compileBinaryTypes(e){for(let t of e){let n=t.toLowerCase();if(n=="*/*"){this.binaryMediaTypes.push(/^.*$/);continue}if(ne.test(n))if(n.endsWith("/*")){let c=new RegExp(`^${n.slice(0,-1)}[a-z0-9-_.$~+#'{}\`!*]+$`);this.binaryMediaTypes.push(c)}else{let c=new RegExp(`^${n}$`);this.binaryMediaTypes.push(c)}}}compileResources(e){for(let[t,n]of Object.entries(e))t.startsWith("/")&&this.compileResources(n);if(!e.resourceId){let t=$();e.resourceId=t.slice(0,t.indexOf("-"))}this.compiledResources[e.resourceId]={};for(let t of K){let n=e[t];if(!n)continue;let c=[],d=[],i={};if(n.request){if(n.request.queryStringParameters)for(let[s,r]of Object.entries(n.request.queryStringParameters))r.required&&c.push(s);if(n.request.headers)for(let[s,r]of Object.entries(n.request.headers))r.required&&d.push(s);if(n.request.body)for(let[s,r]of Object.entries(n.request.body)){let o=this.models[r];i[s]=F(o)}}this.compiledResources[e.resourceId][t]={requiredQueryParams:c,requiredHeaders:d,body:i}}}async start(){this.server=te((t,n)=>{this.requestHandler(t,n)}),await new Promise(t=>{this.server.listen(this.port,t)}),a.servers.push(this),this.port=this.server.address().port,this.server.on("connection",t=>{t.on("close",()=>{let n=this.sockets.findIndex(c=>c==t);n!=-1&&this.sockets.splice(n,1)}),this.sockets.push(t)});let e=this.requireStagePrefixInRequestPath?`/${this.stage}`:"";this.printPaths(this.resources,e)}printPaths(e,t){let n=Object.keys(e);for(let c of n){let d=e[c];if(!c.startsWith("/"))continue;let i=Object.keys(d).filter(r=>K.includes(r)),s=`${t}${c}`;i.length&&this.logger.CYAN(`${i.join(", ")} http://localhost:${this.port}${s}`),this.printPaths(d,s)}}dropConnections(){for(let e of this.sockets)e.writable&&e.destroy()}stop(){this.server?.close()}findResourceFromRequest(e){let{method:t,url:n}=e,c=n.indexOf("?");c==-1&&(c=void 0);let d=n.slice(0,c),i=d;for(;i!="/"&&i.endsWith("/");)i=i.slice(0,-1);let s;c&&(s=n.slice(c));let r=i;if(this.requireStagePrefixInRequestPath){if(!i.startsWith(`/${this.stage}`))return;r=i.slice(`/${this.stage}`.length)}let o=N(t,r,this.resources);if(o)return{resource:o.resource,pathname:i,requestPath:d,rawQueryStringParameters:s,matchedMethod:o.matchedMethod,requestMethod:t,pathParams:o.pathParams,resourcePath:o.resourcePath}}static async collectBody(e,t){let n=Buffer.alloc(0);return e.on("data",c=>{n=Buffer.concat([n,c])}),new Promise(c=>{e.on("end",async()=>{c(n?n.toString(t?"base64":"utf-8"):null)})})}static getQueryStrings(e){let t=null,n=null;if(!e)return{queryStringParameters:n,multiValueQueryStringParameters:t};let c=e.slice(1).split("&"),d={};for(let s of c){let[r,o]=s.split("="),u=r.split(";"),h=o?.split(";")??[""];if(u.length==1&&h.length==1){let R=decodeURIComponent(u[0]),b=decodeURIComponent(h[0]);R in d?d[R].push(b):d[R]=[b];continue}let l=u.slice(0,-1),p=u[u.length-1],m=decodeURIComponent(p),y=decodeURIComponent(h[0]);if(m in d?d[m].push(y):d[m]=[y],h.length>1){let R=h.slice(1);for(let b of R)l.push(b)}for(let R of l){let b=decodeURIComponent(R);b in d?d[b].push(""):d[b]=[""]}}let i=Object.keys(d);if(i.length){n={},t={};for(let s of i.sort()){let r=d[s];t[s]=r,n[s]=r[r.length-1]}}return{queryStringParameters:n,multiValueQueryStringParameters:t}}static shouldDropHeader(e){return!!se.includes(e)}static parseMultiValueHeaders(e){let t={},n={},c={};for(let i=0;i<e.length;i=i+2){let s=e[i],r=s.toLowerCase(),o=e[i+1]?.trim()??"";if(o=Buffer.from(o,"utf-8").toString("latin1"),r=="x-amzn-trace-id"){t["X-Amzn-Trace-Id"]=[o];continue}if(r=="user-agent"){t["User-Agent"]=[o];continue}if(r=="x-forwarded-for"){c[s]||(c[s]=[]),c[s].push(o);continue}if(a.shouldDropHeader(r))continue;let u=n[r];u&&u!=s&&delete t[u],s in t||(t[s]=[]),t[s].push(o),n[r]=s}let d=Object.keys(c);if(d.length){let i=d[d.length-1];t["X-Forwarded-For"]=c[i]}return t}getHeaders(e){let t=a.parseMultiValueHeaders(e),n=t["X-Amzn-Trace-Id"]?t["X-Amzn-Trace-Id"][0]:void 0;t.Host=[`localhost:${this.port}`],t["X-Amzn-Trace-Id"]=[D(n)],t["X-Forwarded-Proto"]=["http"],t["X-Forwarded-Port"]=[String(this.port)],t["X-Forwarded-For"]||(t["X-Forwarded-For"]=[]),t["X-Forwarded-For"].push(this.ip);let c={},d={},i=Object.keys(t).sort((l,p)=>l.toLowerCase().localeCompare(p.toLowerCase())),s,r,o,u="*/*",h;for(let l of i){let p=t[l],m=l.toLowerCase();if(m=="x-http-method-override"){s=p[p.length-1];continue}if(m=="x-api-key")r=p[p.length-1];else if(m=="authorization"){if(h=p[p.length-1],h.startsWith("AWS4-HMAC-SHA256 Credential=")&&re.every(y=>h.includes(y)))continue}else if(m=="content-type")o=p[p.length-1].toLowerCase();else if(m=="accept")u=p[p.length-1].toLowerCase().split(",")[0];else if(l=="X-Forwarded-For"){let y=p.join(", ");c[l]=[y],d[l]=y;continue}c[l]=p,d[l]=p[p.length-1]}return{headers:d,multiValueHeaders:c,overrideMethod:s,apiKey:r,contentType:o,accept:u,authorization:h}}createRequestContext({foundRequest:e,requestId:t,httpMethod:n,req:c,headers:d,apiKey:i}){let s,r;if(i){s={apiKey:i};let m=this.apiKeys.find(y=>y.value==i)?.id;m&&(r={apiKeyId:m})}let o={cognitoIdentityPoolId:null,accountId:null,cognitoIdentityId:null,...s,caller:null,sourceIp:c.socket.remoteAddress?.includes(":")?this.ip:c.socket.remoteAddress,principalOrgId:null,accessKey:null,cognitoAuthenticationType:null,cognitoAuthenticationProvider:null,userArn:null,...r,userAgent:d["User-Agent"]??null,user:null},{requestTime:u,requestTimeEpoch:h}=j(),l=e.requestPath;return this.requireStagePrefixInRequestPath||(l=`/${this.stage}${e.requestPath}`),{resourceId:e.resource.resourceId,resourcePath:e.resourcePath,httpMethod:n,extendedRequestId:V(),requestTime:u,path:l,accountId:"123456789012",protocol:"HTTP/1.1",stage:this.stage,domainPrefix:"localhost",requestTimeEpoch:h,requestId:t,identity:o,domainName:`http://localhost:${this.port}`,deploymentId:this.deploymentId,apiId:this.id}}async createPayloadFromRequest(e,t,n){let{rawHeaders:c,method:d}=e,{headers:i,multiValueHeaders:s,overrideMethod:r,apiKey:o,contentType:u,accept:h}=this.getHeaders(c),l=!1;u&&this.binaryMediaTypes.find(Y=>Y.test(u))&&(l=!0);let p=await a.collectBody(e,l)||null,{queryStringParameters:m,multiValueQueryStringParameters:y}=a.getQueryStrings(t.rawQueryStringParameters),R=null;Object.keys(t.pathParams).length&&(R=t.pathParams);let b=r??d,W=`/${this.stage}`,x=t.requestPath;return this.requireStagePrefixInRequestPath&&(x=x.slice(W.length),x||(x="/")),{payload:{resource:t.resourcePath,path:x,httpMethod:b,headers:i,multiValueHeaders:s,queryStringParameters:m,multiValueQueryStringParameters:y,pathParameters:R,stageVariables:null,requestContext:this.createRequestContext({foundRequest:t,requestId:n,apiKey:o,req:e,headers:i,httpMethod:b}),isBase64Encoded:l,body:p},contentType:u,accept:h}}validateRequest(e,t,n,c){let{payload:d,contentType:i}=e;if(!K.includes(d.httpMethod))throw new P;if(t.requiresApiKey&&!d.requestContext.identity.apiKeyId)throw new T;let s=i??"application/json";if(s.startsWith("application/json;")){let u=s.replaceAll(" ","").split(";").find(h=>h.startsWith("charset="));if(u&&u.replaceAll(",","")!="charset=utf-8")throw new M;s="application/json"}let r=this.compiledResources[n]?.[c];if(t.validate&&r){if(t.validate.query&&r.requiredQueryParams.length){if(!d.queryStringParameters)throw new I(`{"message": "Missing required request parameters: [${r.requiredQueryParams.join(", ")}]"}`);let l=r.requiredQueryParams.filter(p=>!d.queryStringParameters[p]);if(l.length)throw new I(`{"message": "Missing required request parameters: [${l.join(", ")}]"}`)}if(t.validate.headers&&r.requiredHeaders.length){let l=r.requiredHeaders.filter(p=>!d.headers[p]);if(l.length)throw new I(`{"message": "Missing required request parameters: [${l.join(", ")}]"}`)}if(!t.validate.body||d.isBase64Encoded||this.binaryMediaTypes.find(l=>l.test("anything")))return;let o=r.body[s];if(typeof o!="function")return;if(!d.body)throw new I('{"message":[Unknown error parsing request body]}');let u;try{u=JSON.parse(d.body)}catch{throw new I('{"message":[Unknown error parsing request body]}')}if(!o(u)){this.logger.getDebug()&&console.warn(o.errors);let l=o.errors.map(p=>`instancePath '${p.instancePath}' ${p.message}`).join(", ");throw new I(JSON.stringify({message:`[${l}]`}))}}}async invokeProxyLambda(e,t){let d=e;if(d.startsWith("arn:aws:lambda")){let o=d.split(":");(o.length==7||o.length==8)&&(d=o[6])}let i=this.getLambdas(),s=i.find(o=>o.name==d);if(!s&&typeof this.resolveLambdaNameFromArn=="function"){let o=this.resolveLambdaNameFromArn(e);s=i.find(u=>u.name==o)}if(!s)throw this.logger.RED(`REST APiG can not find Lambda ${e}`),new f;return await s.invoke(t)}async invokeIntegration(e,t,n,c){let d=e.matchedMethod,i=e.requestMethod,s=e.resource[d];try{let r=await this.createPayloadFromRequest(t,e,c),{payload:o,accept:u}=r;if(this.validateRequest(r,s,e.resource.resourceId,d),s.integration.lambda?.arn){let h=await this.invokeProxyLambda(s.integration.lambda.arn,o);this.responseFromIntegration(n,h,"lambda-proxy",c,u,i)}else if(typeof s.integration.mock=="function"){let h=await s.integration.mock(o);this.responseFromIntegration(n,h,"lambda-proxy",c,u,i)}else this.logger.RED("REST APiG must have integration"),n.statusCode=500,n.end("No resource integration found")}catch(r){if(r instanceof w){r.completeRequest(n,c);return}console.error(r),new f().completeRequest(n,c)}}async requestHandler(e,t){let n=this.findResourceFromRequest(e),c=$();n?await this.invokeIntegration(n,e,t,c):new E().completeRequest(t,c)}parseIntegrationResponseHeaders(e){let t={},n=typeof e.multiValueHeaders;if(S(e.multiValueHeaders))for(let[i,s]of Object.entries(e.multiValueHeaders)){let r=i,o=i.toLowerCase();if(o=="content-type")r="Content-Type";else if(G.includes(o)||o.startsWith("x-amzn-remapped-"))r=`x-amzn-Remapped-${r}`;else if(z.includes(o))continue;t[r]=[];for(let u of s)if(typeof u=="string")t[r].push(u);else if(typeof u=="number"||typeof u=="boolean")t[r].push(String(u));else if(u===null)t[r].includes("")||t[r].push("");else throw this.logger.RED(`Invalid integration response headers. MultiValueHeader '${r}' values must be string, number, boolean or null.`),new f}else if(n!="undefined"&&n!==null)throw this.logger.RED("Invalid integration response headers. multiValueHeaders must be an object of with string[] as value type."),new f;if(typeof e.headers=="undefined")return t;if(S(e.headers))for(let[i,s]of Object.entries(e.headers)){let r=i,o=i.toLowerCase();if(o=="content-type")r="Content-Type";else if(G.includes(o)||o.startsWith("x-amzn-remapped-"))r=`x-amzn-Remapped-${r}`;else if(z.includes(o))continue;if(t[r]||(t[r]=[]),typeof s=="string")t[r].includes(s)||t[r].push(s);else if(typeof s=="number"||typeof s=="boolean"){let u=String(s);t[r].includes(u)||t[r].push(u)}else if(s===null)t[r].includes("")||t[r].push("");else if(typeof s<"u")throw this.logger.RED(`Invalid integration response headers. Header '${r}' must be string, number, boolean or null.`),new f}else if(e.headers!==null)throw this.logger.RED("Invalid integration response headers. Headers must be an object or null."),new f;return t}parseIntegrationResponse(e,t){if(!S(e))throw this.logger.RED("Invalid integration response."),new f;let n=["statusCode","body","headers","isBase64Encoded","multiValueHeaders"],c=Object.keys(e).find(o=>!n.includes(o));if(c)throw this.logger.RED(`Invalid integration response. Field '${c}' is not supported.`),new f;let d=200,i;if(e.statusCode){if(Number.isNaN(e.statusCode))throw this.logger.RED("Invalid integration response statusCode"),new f;let o=Number(e.statusCode);if(!(o>99&&o<600))throw this.logger.RED("Invalid integration response statusCode"),new f;d=o}let s=typeof e.body;if(s=="string")i=e.body;else if(s=="number")Number.isNaN(e.body)||(i=String(e.body));else if(s=="boolean")i=String(e.body);else if(s!="undefined"&&e.body!==null)throw this.logger.RED("Invalid integration response body"),new f;if(i&&e.isBase64Encoded&&this.binaryMediaTypes.find(o=>o.test(t))){let o=Buffer.from(i,"base64");if(o.toString("base64")!=i)throw this.logger.RED("Invalid integration response body. Incorrect body base64 encoding"),new f;i=o}let r=this.parseIntegrationResponseHeaders(e);return{statusCode:d,body:i,headers:r}}responseFromIntegration(e,t,n,c,d,i){try{let s=this.parseIntegrationResponse(t,d);e.shouldKeepAlive=!1,s.headers.Connection=["keep-alive"],s.headers["x-amzn-RequestId"]=[c],s.headers["Content-Length"]=["0"],s.body&&s.statusCode!=204&&(s.headers["Content-Length"]=[Buffer.byteLength(s.body,typeof s.body=="string"?"utf-8":"base64").toString()]),s.headers["Content-Type"]?s.headers["Content-Type"]=[s.headers["Content-Type"][0]]:s.headers["Content-Type"]=["application/json"],i=="HEAD"&&s.headers["Content-Length"][0]!="0"&&(s.headers["x-amzn-Remapped-Content-Length"]||(s.headers["x-amzn-Remapped-Content-Length"]=[]),s.headers["x-amzn-Remapped-Content-Length"].push(s.headers["Content-Length"][0])),e.writeHead(s.statusCode,s.headers),i=="HEAD"?e.end():e.end(s.body)}catch(s){if(s instanceof w){s.completeRequest(e,c);return}console.error(s),new f().completeRequest(e,c)}}};var ie=U(),Ge=a=>{let e=a.gateways,t=a.apiKeys??[],n=a.usagePlans??[],c={name:"rest-api-plugin",onKill(){for(let d of v.servers)d.stop();v.servers=[]},shared:{gateways:e},server:{async onReady(){let d=[];for(let s of t){if(!s.id){let r=oe();s.id=r.slice(0,r.indexOf("-"))}s.value||(s.value=O(),console.log("API Key",s.name,":",s.value)),d.push(s)}let i={};for(let s of n)for(let r of s.apiKeys){let o=d.find(u=>u.id==r.keyId||u.name==r.keyId);if(!o)throw new Error(`[REST Api - Usage Plan] Can not find API Key with id: "${r.keyId}"`);i[r.apiId]||(i[r.apiId]=[]),i[r.apiId].push(o)}for(let s of e){let r=new v({ip:ie,...s,getLambdas:()=>this.lambdas},this.log),o=i[r.id];o&&(r.apiKeys=o),await r.start();let u=c.shared.gateways.find(h=>h.id==s.id);u&&(u.id=r.id,u.port=r.port,u.stage=r.stage),console.log(`REST API [${r.id}]`,`http://localhost:${r.port}`),r.server?.unref()}}},buildCallback(d,i){if(i)for(let s of v.servers)s.dropConnections()}};return c};export{Ge as restApiPlugin};
|
package/dist/standalone.js
CHANGED
|
@@ -6,7 +6,7 @@ Please verify provided SQS Client validity.`),console.error(l)}}},an=/(-|\w+)/g,
|
|
|
6
6
|
`)}else I=E;I.trim()&&console.log(I)}}catch(O){console.log("err",O),h(O)}};this.python.stdout.on("data",u);let S=w=>{let R=w.toString();if(R.includes(t.ERR_RESPONSE))try{R=JSON.parse(R.split(t.ERR_RESPONSE)[1]),R.requestId=p}catch{}finally{this.python.stdout.removeListener("data",u),this.python.stderr.removeListener("data",S),h(R)}else console.log(R)};this.python.stderr.on("data",S),this.python.stdin.write(`${g}
|
|
7
7
|
`)}),this.watcherListener=()=>{this.isMounted&&(this.unmount(!0),this.watchers.forEach(l=>l.close()),this.watchers=[],this.emitRebuild())}}setWatchFiles=async e=>{try{let n=e.split(t.WATCH),s=n[n.length-1].split(t.WATCHEND)[0],i=JSON.parse(s).map(o=>`${o.replace(/\./g,H.default.sep)}.py`);for(let o of i)try{await(0,fe.access)(o),this.watchers.push((0,at.watch)(o,{persistent:!1},this.watcherListener))}catch{}}catch(n){console.log(n)}};findPython(){let[e]=this.runtime.split("."),n=e.split("python")[1];if(ot(`${e} --version`))return e;let r=ot("python --version");if(!r)throw new Error("Can not find python on your OS. Make sure it is installed.");if(n){let s=r.split(" ")[1]?.split(".")[0];s&&s!=n&&b.YELLOW("found python binary but with different version")}return"python"}load=()=>{this.bin||(this.bin=this.findPython()),this.python=(0,ie.spawn)(this.bin,["-u",t.wrapper,this.handlerFileAbsolutePath,this.pyModulePath,this.handlerName,String(this.timeout)],{env:this.environment}),this.python.pid||(console.error(`Can not find ${this.bin} in your PATH`),process.exit(1)),this.isMounted=!0};onComplete=e=>{}};var ct=require("node:child_process"),dt=require("node:fs"),he=require("node:fs/promises"),W=P(require("node:path"));var oe=class t{invoke;mount;unmount;name;timeout;memorySize;environment;handlerPath;modulePath;handlerDir;handlerName;runtime;bin;ruby;isMounted=!1;emitRebuild;watcherListener;watchers=[];static wrapper=W.default.resolve(q("exlo"),"./src/lib/runtime/runners/ruby/index.rb");static DELIMITER="__|response|__";static ERR_RESPONSE="__|error|__";static WATCH="__|watch|__";constructor({name:e,timeout:n,memorySize:r,environment:s,handlerPath:i,handlerName:o,runtime:a},d){this.name=e,this.timeout=n,this.memorySize=r,this.environment=s,this.handlerName=o,this.runtime=a,this.emitRebuild=d;let c=W.default.resolve(i);this.handlerDir=W.default.dirname(c),this.handlerPath=W.default.basename(c,`.${this.handlerName}`),this.modulePath=`${this.handlerDir}/${this.handlerPath}.rb`,this.mount=async()=>{if(!this.ruby)try{await(0,he.access)(this.modulePath),this.load()}catch{console.error(`Can not find ${this.name}'s handler at: "${this.modulePath}"`),process.exit(1)}},this.unmount=l=>{l&&(this.ruby?.kill(),this.ruby=void 0,this.isMounted=!1)},this.invoke=async({event:l,info:m,clientContext:f,awsRequestId:p})=>new Promise((y,h)=>{let g=JSON.stringify({event:l,awsRequestId:p,context:f??""}),x=S=>{let w=null,R=S.toString();try{if(R.includes(t.WATCH))this.setWatchFiles(R);else if(R.includes(t.DELIMITER)){let E=R.split(t.DELIMITER),O=E[E.length-1];if(E.length>1){let I=E.slice(0,-1).join(`
|
|
8
8
|
`);I.trim()&&console.log(I)}O&&(w=JSON.parse(O)),this.ruby.stdout.removeListener("data",x),this.ruby.stderr.removeListener("data",u),y(w)}else R.trim()&&console.log(R)}catch(E){h(E)}};this.ruby.stdout.on("data",x);let u=S=>{let w=S.toString();if(w.includes(t.ERR_RESPONSE))try{w=JSON.parse(w.split(t.ERR_RESPONSE)[1]),w.requestId=p}catch{}finally{this.ruby.stdout.removeListener("data",x),this.ruby.stderr.removeListener("data",u),h(w)}else console.log(w)};this.ruby.stderr.on("data",u),this.ruby.stdin.write(`${g}
|
|
9
|
-
`)}),this.watcherListener=()=>{this.isMounted&&(this.unmount(!0),this.watchers.forEach(l=>l.close()),this.watchers=[],this.emitRebuild())}}setWatchFiles=async e=>{try{let n=e.split(t.WATCH),r=n[n.length-1],s=JSON.parse(r);s.push(this.modulePath);for(let i of s)try{await(0,he.access)(i),this.watchers.push((0,dt.watch)(i,{persistent:!1},this.watcherListener))}catch{}}catch(n){console.log(n)}};load=()=>{this.bin||(this.bin=process.platform==="win32"?"ruby.exe":"ruby"),this.ruby=(0,ct.spawn)(this.bin,[t.wrapper,this.modulePath,this.handlerName,this.name,String(this.timeout)],{env:this.environment,shell:!0}),this.ruby.pid||(console.error(`Can not find ${this.bin} in your PATH`),process.exit(1)),this.isMounted=!0};onComplete=e=>{}};var yn=["@invoke","@url"],k=class t{handlers=[];static ip="127.0.0.1";debug=!1;port=0;constructor(e){this.debug=e.debug}static parseNameFromUrl(e){let n=e.split("/"),r=yn.includes(n[1])?n[2]:n[3];if(r=decodeURIComponent(r),r.includes(":function:")){let s=r.split(":function:");r=s[s.length-1]}if(r.includes(":")){let s=r.split(":");s.length==2&&(r=s[0])}return r}getHandlerByName(e){if(!e)return;let n=t.parseNameFromUrl(e);return this.handlers.find(r=>r.name==n)}addHandler(e){let n=this.handlers.findIndex(r=>r.name==e.name&&r.esOutputPath==e.esOutputPath);n==-1?(this.handlers.push(e),this.#e("POST",`/2015-03-31/functions/${e.name}/invocations`),e.url&&this.#e("ANY",`/@url/${e.name}`,"34")):this.handlers[n].runtime.startsWith("n")&&(this.handlers[n].clear(),this.handlers[n]=e)}#e(e,n,r="90"){let s=`${e} http://localhost:${this.port}${n}`;console.log(`\x1B[${r}m${s}\x1B[0m`)}};var ae;ye.networkInterfaces&&(ae=Object.values((0,ye.networkInterfaces)()).reduce((t,e)=>(t.push(...e),t),[])?.filter(t=>!t.internal&&t.family==="IPv4").find(Boolean)?.address);var gn=mt.default?.url()!=null;gn&&(console.warn("Lambdas timeout are disabled when a Debugger is attached"),$.ENABLE_TIMEOUT=!1);var bn={errors:[],warnings:[],outputFiles:[],metafile:{inputs:{},outputs:{}},mangleCache:{}},ce=class extends k{#e;runtimeConfig={};#t;sco=[];aws;customOfflineRequests=[];customBuildCallback;onReady;stop(e){this.#e.close(e)}constructor(e,n={debug:!1}){super(n),b.setDebug(n.debug),this.aws=e.aws,this.sco=[],this.#e=pt.default.createServer({maxHeaderSize:105536},this.#r.bind(this)),this.#e.on("connection",s=>{s.on("close",()=>{let i=this.sco.findIndex(o=>o==s);i!=-1&&this.sco.splice(i,1)}),this.sco.push(s)});let r=(0,lt.randomUUID)();v.accountId=Buffer.from(r).toString("hex").slice(0,16),v.apiId=Buffer.from(r).toString("ascii").slice(0,10),v.port=this.port}setPort(e){this.port=e,v.port=e}listen(e=0,n){if(isNaN(e))throw Error("port should be a number");this.#e.once("error",async r=>{r.code==="EADDRINUSE"?(b.RED(r.message),process.exit(1)):console.log(r)}),this.#e.listen(e,async()=>{let{port:r,address:s}=this.#e.address();this.setPort(r),ae&&(k.ip=ae),typeof n=="function"&&await n(r,ae);try{await this.onReady?.(r,k.ip),await Ke(this.handlers,this.aws)}catch(i){console.error(i)}})}#n(e,n){n=n.endsWith("/")?n:`${n}/`;let r=this.customOfflineRequests.find(s=>{let i=!1,o=!0;return typeof s.filter=="string"?(s.filter.endsWith("/")||(s.filter+="/"),i=s.filter==n):s.filter instanceof RegExp&&(i=s.filter.test(n)),typeof s.method=="string"&&s.method.toUpperCase()!="ANY"?o=s.method.toUpperCase()==e:Array.isArray(s.method)&&(s.method.findIndex(d=>d.toUpperCase()=="ANY")!==-1||(o=s.method.findIndex(d=>d.toUpperCase()==e)!==-1)),i&&o});if(r)return r.callback}async#r(e,n){let{url:r,method:s}=e,i=new URL(r,v.dummyHost),o=this.#n(s,i.pathname);if(o)try{await o(e,n)}catch{n.writableFinished||n.end("Internal Server Error")}else{e.on("error",d=>{console.error(d.stack)});let a=()=>{n.setHeader("Content-Type","text/html"),n.statusCode=404,n.end(qe)};this.#t?this.#t(e,n,a):a()}}fakeRebuildEmitter=async()=>{if(this.customBuildCallback)try{await this.customBuildCallback(bn,!0)}catch(e){console.log(e)}console.log(`\x1B[32m${new Date().toLocaleString()} \u{1F504}\u2705 Rebuild\x1B[0m`)};async load(e){for(let n of e){let r=n.runtime.charAt(0);n.runner=r=="n"?new re(n):r=="p"?new se(n,this.fakeRebuildEmitter):r=="r"?new oe(n,this.fakeRebuildEmitter):new ne(n.runtime);let s=new $(n);this.addHandler(s)}}};var ht=require("node:fs/promises"),N=P(require("node:path")),yt=require("node:url"),gt=P(require("esbuild"));var ut="0.0.7";function ft(t){let e=new Set;t.plugins&&(t.plugins=t.plugins.filter((r,s)=>typeof r!="object"||!r||!("name"in r)?!1:((!r.name||!r.name.length||typeof r.name!="string")&&(r.name=`plugin-${s}`,console.warn(`No Plugin name provided at index ${s}`)),e.has(r.name)?r.name=r.name+s:e.add(r.name),!0)));async function n({stop:r,lambdas:s,region:i,esbuild:o,getServices:a,setService:d,addLambda:c,log:l,setEndpoint:m,getEndpoint:f,getAwsProviderDefaults:p,setAwsProviderDefaults:y}){let h={build:{esbuild:t?.build?.esbuild??{},shimRequire:t?.build?.shimRequire,optimizeBuild:t?.build?.optimizeBuild},server:{port:t.server?.port,setEndpointEnvVar:t.server?.setEndpointEnvVar},onKill:[]};if(t.defaults&&typeof t.defaults=="object"&&!Array.isArray(t.defaults)&&y(t.defaults),t.functions&&typeof t.functions=="object"&&!Array.isArray(t.functions))for(let[x,u]of Object.entries(t.functions))c(x,u);t.services&&(t.services.sqs&&d("sqs",t.services.sqs),t.services.sns&&d("sns",t.services.sns),t.services.dynamodb&&d("dynamodb",t.services.dynamodb));let g={stop:r,lambdas:s,region:i,esbuild:o,options:t,config:h,getServices:a,setService:d,addLambda:c,log:l,setEndpoint:m,getEndpoint:f,getAwsProviderDefaults:p};if(t.plugins){h.server.onReady=async(u,S)=>{for(let w of t.plugins)if(w.server?.onReady)try{await w.server.onReady.call(g,u,S)}catch(R){l.RED(w.name),console.error(R)}},h.buildCallback=async(u,S)=>{for(let w of t.plugins)if(w.buildCallback)try{await w.buildCallback.call(g,u,S)}catch(R){l.RED(w.name),console.error(R),S||process.exit(1)}};let x=t.plugins.reduce((u,S)=>(S.server?.request?.length&&u.push(...S.server.request),u),[]);x?.length&&(h.server.request=x.map(u=>(u.callback=u.callback.bind(g),u)));for(let u of t.plugins)if(u.onKill&&h.onKill.push(u.onKill.bind(g)),u.onInit)try{await u.onInit.call(g)}catch(S){throw l.RED(u.name),S}}return h}return n.plugins=t.plugins??[],n}var vn=["js","mjs","cjs","ts","cts","mts"],xn=async t=>{let e=N.default.dirname(N.default.toNamespacedPath(t)),n=N.default.basename(t,N.default.extname(t)),r=N.default.join(e,`__${n}.mjs`);await gt.default.build({outfile:r,entryPoints:[t],bundle:!0,packages:"external",platform:"node",format:"esm",target:`node${process.versions.node.split(".")[0]}`,minify:!0,sourcemap:"inline",sourcesContent:!0});try{return await import((0,yt.pathToFileURL)(r).href)}catch(s){throw s}finally{await(0,ht.rm)(r)}},bt=async t=>{if(t){if(typeof t=="string"){let e=N.default.posix.parse(t),n=N.default.posix.join(e.dir,e.name),r=e.ext.slice(1),s=N.default.posix.resolve(n);vn.includes(r)&&(s+=`.${r}`);let i;try{i=await xn(s)}catch(o){b.YELLOW(`Can not read 'defineConfig' from ${t}`),console.error(o),process.exit(1)}return{exportedFunc:i,configObjectName:r,configPath:s}}if(typeof t=="object"&&!Array.isArray(t))return{configObjectName:"__inline_config__",configPath:"inline define config",exportedFunc:ft(t)}}};var wn=t=>{let e=t.split(";");return e.findIndex(r=>r.toLowerCase().startsWith("path="))==-1&&e.push("Path=/"),e.join(";")},ge=(t,e)=>{let n={};if(t&&Object.entries(t).forEach(([r,s])=>{n[r.toLowerCase()]=Array.isArray(s)?`[${s.join(", ")}]`:s}),Array.isArray(e)){if(!e.every(r=>typeof r=="string")){let r=new Error("Wrong 'cookies'. must be string[]",{cause:e}),s={"Content-Type":n["content-type"]??"application/json","x-amzn-ErrorType":"InternalFailure"};throw n["set-cookie"]&&(s["set-cookie"]=n["set-cookie"]),r.headers=s,r}e=e.map(wn),n["set-cookie"]=n["set-cookie"]?[n["set-cookie"],...e]:e}return n};var be=require("node:crypto");var de=class t extends v{res;mockEvent;payload;constructor({res:e,req:n,body:r,mockEvent:s,multiValueHeaders:i,isBase64Encoded:o,lambdaName:a,parsedURL:d,requestId:c}){super(),this.res=e,this.mockEvent=s,this.payload=s.version==1?t.createApgV1Event({req:n,mockEvent:s,parsedURL:d,lambdaName:a,multiValueHeaders:i,isBase64Encoded:o,requestId:c,body:r}):t.createApgV2Event({req:n,mockEvent:s,parsedURL:d,requestId:c,isBase64Encoded:o,body:r})}static skipHeaders=["connection","content"];static createApgV2Event=({req:e,mockEvent:n,parsedURL:r,requestId:s,isBase64Encoded:i,body:o})=>{let{method:a,headers:d}=e,c=t.getPathParameters(n,r),l,m=n.methods.find(S=>S==a)??"ANY",f={},p="";for(let S of Array.from(new Set(r.searchParams.keys()))){let w=r.searchParams.getAll(S);p+=`&${w.map(R=>encodeURI(`${S}=${R}`)).join("&")}`,f[S]=w.join(",")}p&&(p=p.slice(1));let y=n.paths[0]=="/*"?"$default":`${m} ${r.pathname}`,h=new Date,g="127.0.0.1",x=d.host?.startsWith("localhost")?g:d.host?d.host.split(":")[0]:g,u={version:"2.0",routeKey:y,rawPath:r.pathname,rawQueryString:p,headers:t.getCustomHeaders(e,n),requestContext:{accountId:String(t.accountId),apiId:t.apiId,domainName:`localhost:${t.port}`,domainPrefix:"localhost",http:{method:a,path:r.pathname,protocol:"HTTP/1.1",sourceIp:x,userAgent:d["user-agent"]??""},requestId:s,routeKey:y,stage:"$default",time:h.toISOString(),timeEpoch:h.getTime()}};return o?(u.body=o,u.isBase64Encoded=i):u.isBase64Encoded=!1,Object.keys(f).length&&(u.queryStringParameters=f),Object.keys(c).length&&(u.pathParameters=c),d.cookie&&(u.cookies=d.cookie.split("; ")),l=u,l.headers["x-mock-type"]&&delete l.headers["x-mock-type"],l};static createApgV1Event=({req:e,mockEvent:n,parsedURL:r,lambdaName:s,isBase64Encoded:i,requestId:o,body:a})=>{let{method:d}=e,c={};n.proxy=="httpApi"&&(c.version="1.0");let l=n.paths[0];c.resource=l,c.path=r.pathname,c.httpMethod=d;let{headers:m,multiValueHeaders:f,apiKey:p}=t.getApiGV1Headers(e,n);c.headers=m,c.multiValueHeaders=f;let y=String(e.socket.remoteAddress),h=Object.fromEntries(r.searchParams);c.queryStringParameters=Object.keys(h).length?h:null;let g=t.getMultiValueQueryStringParameters(r.searchParams);c.multiValueQueryStringParameters=Object.keys(g).length?g:null;let x=new Date,u={accountId:String(t.accountId),apiId:t.apiId,domainName:`localhost:${t.port}`,domainPrefix:"localhost",extendedRequestId:"fake-id",httpMethod:d,identity:{accessKey:null,accountId:null,caller:null,cognitoAuthenticationProvider:null,cognitoAuthenticationType:null,cognitoIdentityId:null,cognitoIdentityPoolId:null,principalOrgId:null,sourceIp:y,user:null,userAgent:e.headers["user-agent"],userArn:null},path:r.pathname,protocol:"HTTP/1.1",requestId:o,requestTime:x.toISOString(),requestTimeEpoch:x.getTime(),resourceId:"exhmtv",resourcePath:l};n.proxy=="httpApi"?(u.identity.cognitoAmr=null,u.stage="$default"):(u.stage="dev",n.private&&(u.identity.apiKey=p,u.identity.apiKeyId="abcdefghjk")),c.requestContext=u;let S=t.getPathParameters(n,r);return c.pathParameters=Object.keys(S).length?S:null,c.stageVariables=null,c.body=a??null,c.isBase64Encoded=a?i:!1,c};returnError=e=>{if(this.res.writableFinished)return!0;let n=500,r=t.httpErrMsg;e&&t.isEndpointTimeoutError(e.errorMessage)&&(this.mockEvent.proxy=="httpApi"?(n=503,r=t.unavailable):(n=504,r=t.apgTimeoutMsg));let s=[["Date",new Date().toUTCString()],["Content-Type",t.contentType.json],["Content-Length",String(r.length)],t.keepAlive,["Apigw-Requestid","ETuSEj-PiGYEJdQ="]];return this.res.shouldKeepAlive=!1,this.res.writeHead(n,s),this.res.end(r)};#e=e=>{let n="",r=typeof e;if(r=="string"||r=="number"||r=="boolean")n=String(e);else if(e===null)n="";else throw new Error("");return n};sendV1Response=e=>{let n=[["Date",new Date().toUTCString()],["Apigw-Requestid",Buffer.from((0,be.randomUUID)()).toString("base64").slice(0,16)],t.keepAlive],r=200;if(!e||isNaN(e.statusCode))throw b.RED(`Valid 'http' response payload must be an object which includes a valid 'statusCode'.
|
|
9
|
+
`)}),this.watcherListener=()=>{this.isMounted&&(this.unmount(!0),this.watchers.forEach(l=>l.close()),this.watchers=[],this.emitRebuild())}}setWatchFiles=async e=>{try{let n=e.split(t.WATCH),r=n[n.length-1],s=JSON.parse(r);s.push(this.modulePath);for(let i of s)try{await(0,he.access)(i),this.watchers.push((0,dt.watch)(i,{persistent:!1},this.watcherListener))}catch{}}catch(n){console.log(n)}};load=()=>{this.bin||(this.bin=process.platform==="win32"?"ruby.exe":"ruby"),this.ruby=(0,ct.spawn)(this.bin,[t.wrapper,this.modulePath,this.handlerName,this.name,String(this.timeout)],{env:this.environment,shell:!0}),this.ruby.pid||(console.error(`Can not find ${this.bin} in your PATH`),process.exit(1)),this.isMounted=!0};onComplete=e=>{}};var yn=["@invoke","@url"],k=class t{handlers=[];static ip="127.0.0.1";debug=!1;port=0;constructor(e){this.debug=e.debug}static parseNameFromUrl(e){let n=e.split("/"),r=yn.includes(n[1])?n[2]:n[3];if(r=decodeURIComponent(r),r.includes(":function:")){let s=r.split(":function:");r=s[s.length-1]}if(r.includes(":")){let s=r.split(":");s.length==2&&(r=s[0])}return r}getHandlerByName(e){if(!e)return;let n=t.parseNameFromUrl(e);return this.handlers.find(r=>r.name==n)}addHandler(e){let n=this.handlers.findIndex(r=>r.name==e.name&&r.esOutputPath==e.esOutputPath);n==-1?(this.handlers.push(e),this.#e("POST",`/2015-03-31/functions/${e.name}/invocations`),e.url&&this.#e("ANY",`/@url/${e.name}`,"34")):this.handlers[n].runtime.startsWith("n")&&(this.handlers[n].clear(),this.handlers[n]=e)}#e(e,n,r="90"){let s=`${e} http://localhost:${this.port}${n}`;console.log(`\x1B[${r}m${s}\x1B[0m`)}};var ae;ye.networkInterfaces&&(ae=Object.values((0,ye.networkInterfaces)()).reduce((t,e)=>(t.push(...e),t),[])?.filter(t=>!t.internal&&t.family==="IPv4").find(Boolean)?.address);var gn=mt.default?.url()!=null;gn&&(console.warn("Lambdas timeout are disabled when a Debugger is attached"),$.ENABLE_TIMEOUT=!1);var bn={errors:[],warnings:[],outputFiles:[],metafile:{inputs:{},outputs:{}},mangleCache:{}},ce=class extends k{#e;runtimeConfig={};#t;sco=[];aws;customOfflineRequests=[];customBuildCallback;onReady;stop(e){this.#e.close(e)}constructor(e,n={debug:!1}){super(n),b.setDebug(n.debug),this.aws=e.aws,this.sco=[],this.#e=pt.default.createServer({maxHeaderSize:105536},this.#r.bind(this)),this.#e.on("connection",s=>{s.on("close",()=>{let i=this.sco.findIndex(o=>o==s);i!=-1&&this.sco.splice(i,1)}),this.sco.push(s)});let r=(0,lt.randomUUID)();v.accountId=Buffer.from(r).toString("hex").slice(0,16),v.apiId=Buffer.from(r).toString("ascii").slice(0,10),v.port=this.port}setPort(e){this.port=e,v.port=e}listen(e=0,n){if(isNaN(e))throw Error("port should be a number");this.#e.once("error",async r=>{r.code==="EADDRINUSE"?(b.RED(r.message),process.exit(1)):console.log(r)}),this.#e.listen(e,async()=>{let{port:r,address:s}=this.#e.address();this.setPort(r),ae&&(k.ip=ae),typeof n=="function"&&await n(r,ae);try{await this.onReady?.(r,k.ip),await Ke(this.handlers,this.aws)}catch(i){console.error(i)}})}#n(e,n){n=n.endsWith("/")?n:`${n}/`;let r=this.customOfflineRequests.find(s=>{let i=!1,o=!0;return typeof s.filter=="string"?(s.filter.endsWith("/")||(s.filter+="/"),i=s.filter==n):s.filter instanceof RegExp&&(i=s.filter.test(n)),typeof s.method=="string"&&s.method.toUpperCase()!="ANY"?o=s.method.toUpperCase()==e:Array.isArray(s.method)&&(s.method.findIndex(d=>d.toUpperCase()=="ANY")!==-1||(o=s.method.findIndex(d=>d.toUpperCase()==e)!==-1)),i&&o});if(r)return r.callback}async#r(e,n){let{url:r,method:s}=e,i=new URL(r,v.dummyHost),o=this.#n(s,i.pathname);if(o)try{await o(e,n)}catch{n.writableFinished||n.end("Internal Server Error")}else{e.on("error",d=>{console.error(d.stack)});let a=()=>{n.setHeader("Content-Type","text/html"),n.statusCode=404,n.end(qe)};this.#t?this.#t(e,n,a):a()}}fakeRebuildEmitter=async()=>{if(this.customBuildCallback)try{await this.customBuildCallback(bn,!0)}catch(e){console.log(e)}console.log(`\x1B[32m${new Date().toLocaleString()} \u{1F504}\u2705 Rebuild\x1B[0m`)};async load(e){for(let n of e){let r=n.runtime.charAt(0);n.runner=r=="n"?new re(n):r=="p"?new se(n,this.fakeRebuildEmitter):r=="r"?new oe(n,this.fakeRebuildEmitter):new ne(n.runtime);let s=new $(n);this.addHandler(s)}}};var ht=require("node:fs/promises"),N=P(require("node:path")),yt=require("node:url"),gt=P(require("esbuild"));var ut="0.0.8";function ft(t){let e=new Set;t.plugins&&(t.plugins=t.plugins.filter((r,s)=>typeof r!="object"||!r||!("name"in r)?!1:((!r.name||!r.name.length||typeof r.name!="string")&&(r.name=`plugin-${s}`,console.warn(`No Plugin name provided at index ${s}`)),e.has(r.name)?r.name=r.name+s:e.add(r.name),!0)));async function n({stop:r,lambdas:s,region:i,esbuild:o,getServices:a,setService:d,addLambda:c,log:l,setEndpoint:m,getEndpoint:f,getAwsProviderDefaults:p,setAwsProviderDefaults:y}){let h={build:{esbuild:t?.build?.esbuild??{},shimRequire:t?.build?.shimRequire,optimizeBuild:t?.build?.optimizeBuild},server:{port:t.server?.port,setEndpointEnvVar:t.server?.setEndpointEnvVar},onKill:[]};if(t.defaults&&typeof t.defaults=="object"&&!Array.isArray(t.defaults)&&y(t.defaults),t.functions&&typeof t.functions=="object"&&!Array.isArray(t.functions))for(let[x,u]of Object.entries(t.functions))c(x,u);t.services&&(t.services.sqs&&d("sqs",t.services.sqs),t.services.sns&&d("sns",t.services.sns),t.services.dynamodb&&d("dynamodb",t.services.dynamodb));let g={stop:r,lambdas:s,region:i,esbuild:o,options:t,config:h,getServices:a,setService:d,addLambda:c,log:l,setEndpoint:m,getEndpoint:f,getAwsProviderDefaults:p};if(t.plugins){h.server.onReady=async(u,S)=>{for(let w of t.plugins)if(w.server?.onReady)try{await w.server.onReady.call(g,u,S)}catch(R){l.RED(w.name),console.error(R)}},h.buildCallback=async(u,S)=>{for(let w of t.plugins)if(w.buildCallback)try{await w.buildCallback.call(g,u,S)}catch(R){l.RED(w.name),console.error(R),S||process.exit(1)}};let x=t.plugins.reduce((u,S)=>(S.server?.request?.length&&u.push(...S.server.request),u),[]);x?.length&&(h.server.request=x.map(u=>(u.callback=u.callback.bind(g),u)));for(let u of t.plugins)if(u.onKill&&h.onKill.push(u.onKill.bind(g)),u.onInit)try{await u.onInit.call(g)}catch(S){throw l.RED(u.name),S}}return h}return n.plugins=t.plugins??[],n}var vn=["js","mjs","cjs","ts","cts","mts"],xn=async t=>{let e=N.default.dirname(N.default.toNamespacedPath(t)),n=N.default.basename(t,N.default.extname(t)),r=N.default.join(e,`__${n}.mjs`);await gt.default.build({outfile:r,entryPoints:[t],bundle:!0,packages:"external",platform:"node",format:"esm",target:`node${process.versions.node.split(".")[0]}`,minify:!0,sourcemap:"inline",sourcesContent:!0});try{return await import((0,yt.pathToFileURL)(r).href)}catch(s){throw s}finally{await(0,ht.rm)(r)}},bt=async t=>{if(t){if(typeof t=="string"){let e=N.default.posix.parse(t),n=N.default.posix.join(e.dir,e.name),r=e.ext.slice(1),s=N.default.posix.resolve(n);vn.includes(r)&&(s+=`.${r}`);let i;try{i=await xn(s)}catch(o){b.YELLOW(`Can not read 'defineConfig' from ${t}`),console.error(o),process.exit(1)}return{exportedFunc:i,configObjectName:r,configPath:s}}if(typeof t=="object"&&!Array.isArray(t))return{configObjectName:"__inline_config__",configPath:"inline define config",exportedFunc:ft(t)}}};var wn=t=>{let e=t.split(";");return e.findIndex(r=>r.toLowerCase().startsWith("path="))==-1&&e.push("Path=/"),e.join(";")},ge=(t,e)=>{let n={};if(t&&Object.entries(t).forEach(([r,s])=>{n[r.toLowerCase()]=Array.isArray(s)?`[${s.join(", ")}]`:s}),Array.isArray(e)){if(!e.every(r=>typeof r=="string")){let r=new Error("Wrong 'cookies'. must be string[]",{cause:e}),s={"Content-Type":n["content-type"]??"application/json","x-amzn-ErrorType":"InternalFailure"};throw n["set-cookie"]&&(s["set-cookie"]=n["set-cookie"]),r.headers=s,r}e=e.map(wn),n["set-cookie"]=n["set-cookie"]?[n["set-cookie"],...e]:e}return n};var be=require("node:crypto");var de=class t extends v{res;mockEvent;payload;constructor({res:e,req:n,body:r,mockEvent:s,multiValueHeaders:i,isBase64Encoded:o,lambdaName:a,parsedURL:d,requestId:c}){super(),this.res=e,this.mockEvent=s,this.payload=s.version==1?t.createApgV1Event({req:n,mockEvent:s,parsedURL:d,lambdaName:a,multiValueHeaders:i,isBase64Encoded:o,requestId:c,body:r}):t.createApgV2Event({req:n,mockEvent:s,parsedURL:d,requestId:c,isBase64Encoded:o,body:r})}static skipHeaders=["connection","content"];static createApgV2Event=({req:e,mockEvent:n,parsedURL:r,requestId:s,isBase64Encoded:i,body:o})=>{let{method:a,headers:d}=e,c=t.getPathParameters(n,r),l,m=n.methods.find(S=>S==a)??"ANY",f={},p="";for(let S of Array.from(new Set(r.searchParams.keys()))){let w=r.searchParams.getAll(S);p+=`&${w.map(R=>encodeURI(`${S}=${R}`)).join("&")}`,f[S]=w.join(",")}p&&(p=p.slice(1));let y=n.paths[0]=="/*"?"$default":`${m} ${r.pathname}`,h=new Date,g="127.0.0.1",x=d.host?.startsWith("localhost")?g:d.host?d.host.split(":")[0]:g,u={version:"2.0",routeKey:y,rawPath:r.pathname,rawQueryString:p,headers:t.getCustomHeaders(e,n),requestContext:{accountId:String(t.accountId),apiId:t.apiId,domainName:`localhost:${t.port}`,domainPrefix:"localhost",http:{method:a,path:r.pathname,protocol:"HTTP/1.1",sourceIp:x,userAgent:d["user-agent"]??""},requestId:s,routeKey:y,stage:"$default",time:h.toISOString(),timeEpoch:h.getTime()}};return o?(u.body=o,u.isBase64Encoded=i):u.isBase64Encoded=!1,Object.keys(f).length&&(u.queryStringParameters=f),Object.keys(c).length&&(u.pathParameters=c),d.cookie&&(u.cookies=d.cookie.split("; ")),l=u,l.headers["x-mock-type"]&&delete l.headers["x-mock-type"],l};static createApgV1Event=({req:e,mockEvent:n,parsedURL:r,lambdaName:s,isBase64Encoded:i,requestId:o,body:a})=>{let{method:d}=e,c={};n.proxy=="httpApi"&&(c.version="1.0");let l=n.paths[0];c.resource=l,c.path=r.pathname,c.httpMethod=d;let{headers:m,multiValueHeaders:f,apiKey:p}=t.getApiGV1Headers(e,n);c.headers=m,c.multiValueHeaders=f;let y=String(e.socket.remoteAddress),h=Object.fromEntries(r.searchParams);c.queryStringParameters=Object.keys(h).length?h:null;let g=t.getMultiValueQueryStringParameters(r.searchParams);c.multiValueQueryStringParameters=Object.keys(g).length?g:null;let x=new Date,u={accountId:String(t.accountId),apiId:t.apiId,domainName:`localhost:${t.port}`,domainPrefix:"localhost",extendedRequestId:"fake-id",httpMethod:d,identity:{accessKey:null,accountId:null,caller:null,cognitoAuthenticationProvider:null,cognitoAuthenticationType:null,cognitoIdentityId:null,cognitoIdentityPoolId:null,principalOrgId:null,sourceIp:y,user:null,userAgent:e.headers["user-agent"],userArn:null},path:r.pathname,protocol:"HTTP/1.1",requestId:o,requestTime:x.toISOString(),requestTimeEpoch:x.getTime(),resourceId:"exhmtv",resourcePath:l};n.proxy=="httpApi"?(u.identity.cognitoAmr=null,u.stage="$default"):(u.stage="dev",n.private&&(u.identity.apiKey=p,u.identity.apiKeyId="abcdefghjk")),c.requestContext=u;let S=t.getPathParameters(n,r);return c.pathParameters=Object.keys(S).length?S:null,c.stageVariables=null,c.body=a??null,c.isBase64Encoded=a?i:!1,c};returnError=e=>{if(this.res.writableFinished)return!0;let n=500,r=t.httpErrMsg;e&&t.isEndpointTimeoutError(e.errorMessage)&&(this.mockEvent.proxy=="httpApi"?(n=503,r=t.unavailable):(n=504,r=t.apgTimeoutMsg));let s=[["Date",new Date().toUTCString()],["Content-Type",t.contentType.json],["Content-Length",String(r.length)],t.keepAlive,["Apigw-Requestid","ETuSEj-PiGYEJdQ="]];return this.res.shouldKeepAlive=!1,this.res.writeHead(n,s),this.res.end(r)};#e=e=>{let n="",r=typeof e;if(r=="string"||r=="number"||r=="boolean")n=String(e);else if(e===null)n="";else throw new Error("");return n};sendV1Response=e=>{let n=[["Date",new Date().toUTCString()],["Apigw-Requestid",Buffer.from((0,be.randomUUID)()).toString("base64").slice(0,16)],t.keepAlive],r=200;if(!e||isNaN(e.statusCode))throw b.RED(`Valid 'http' response payload must be an object which includes a valid 'statusCode'.
|
|
10
10
|
Received:`),console.log(e),new Error;r=e.statusCode,e.headers&&typeof e.headers=="object"&&!Array.isArray(e.headers)&&Object.entries(e.headers).forEach(([c,l])=>{let m=t.normalizeHeaderKey(c),f=this.#e(l);n.push([m,f])}),e.multiValueHeaders&&typeof e.multiValueHeaders=="object"&&!Array.isArray(e.multiValueHeaders)&&Object.entries(e.multiValueHeaders).forEach(([c,l])=>{let m=t.normalizeHeaderKey(c);if(!Array.isArray(l))throw new Error;l.map(p=>this.#e(p)).forEach(p=>{n.push([m,p])})});let s=e.body;if(e.isBase64Encoded&&s){if(typeof s!="string")throw new Error;let c=Buffer.from(s,"base64").toString();if(Buffer.from(c).toString("base64")!=s)throw b.RED("response body is not properly base64 encoded"),new Error;s=c}n.findIndex(c=>c[0].toLowerCase()=="content-type")==-1&&n.push(["Content-Type",t.contentType.json]);let o=n.findIndex(c=>c[0].toLowerCase()=="content-length");o!=-1&&n.splice(o,1);let a=typeof s;a=="number"||a=="boolean"?s=String(s):s&&a!="string"&&b.YELLOW("API Gateway payload v1 return body must be typeof string, number or boolean ");let d=r==204?"0":s?String(Buffer.from(s).byteLength):"0";n.push(["Content-Length",d]),this.res.shouldKeepAlive=!1,this.res.writeHead(r,n),this.res.end(s)};sendV2Response=e=>{this.res.setHeader("Apigw-Requestid",Buffer.from((0,be.randomUUID)()).toString("base64").slice(0,16)),this.res.setHeader("Date",new Date().toUTCString()),e?(typeof e.headers=="object"&&!Array.isArray(e.headers)&&Object.keys(e.headers).filter(s=>s!=="Apigw-Requestid"&&s!=="Date").forEach(s=>{this.res.setHeader(s,e.headers[s])}),e.statusCode?(this.res.statusCode=e.statusCode,e.cookies?.length&&this.res.setHeader("Set-Cookie",e.cookies)):this.res.statusCode=200):this.res.statusCode=200;let n="";if(!e)return this.res.end();if(typeof e=="object"&&typeof e.body=="string"&&(n=e.body,e.isBase64Encoded)){let r=Buffer.from(n,"base64").toString();if(Buffer.from(r).toString("base64")!=n)throw b.RED("response body is not properly base64 encoded"),new Error;n=r}typeof e=="string"?(this.res.setHeader("Content-Type",t.contentType.json),n=e):typeof e=="object"&&!e.statusCode&&(this.res.setHeader("Content-Type",t.contentType.json),n=JSON.stringify(e)),this.res.end(n)};sendResponse=e=>{if(!this.res.writableFinished)return this.mockEvent.version==1?this.sendV1Response(e):this.sendV2Response(e)}};var Rn=(t,e)=>{let n=e.url.stream?t:void 0;if(n){let r=!1,s=t.write.bind(t),i=t.setHeader.bind(t),o,a,d=m=>{a=a?Buffer.concat([a,m]):m},c=()=>{if(a){let m=_e(a),f=m.statusCode??200;try{let p=ge(m.headers,m.cookies);t.writeHead(f,p)}catch(p){t.writeHead(500,p.headers),t.end?.(v.amzMsgNull),delete p.headers}}else t.writeHead(200)};n.setHeader=(m,f)=>{if(m.toLowerCase()=="content-type"){if(f=="application/vnd.awslambda.http-integration-response")return r=!0,i("Content-Type",v.contentType.json);o=f}return i(m,f)};let l=!1;return n.write=(m,f,p)=>{if(n.headersSent)return s(m,f,p);if(l)try{let y=A.codec.decode(m),h=JSON.parse(y);if(Array.isArray(h))throw new Error("Invalid stream response");return h&&typeof h=="object"?(c(),s(m,f,p)):(t.writeHead(200,{"Content-Type":v.contentType.octet}),t.end())}catch(y){let h=new Error(`When using HttpResponseStream first chunk of .write() must be valid JSON and not be Array. Number and null will respones with 200.
|
|
11
11
|
'${e.name}'`);return h.cause=y.message,console.error(h),Z(t)}else if(r)$e(m)?l=!0:d(m);else{if(o==v.contentType.json)try{let h=A.codec.decode(m),g=JSON.parse(h);if(g===null||typeof g=="number")throw new Error(h)}catch(h){let g=new Error(`When 'Content-Type' is 'application/json' first chunk of .write() must be parsable JSON and not be null or number.
|
|
12
12
|
'${e.name}'`);return g.cause=h.message,console.error(g),Z(t)}let y={"Content-Type":o??v.contentType.octet};return n.writeHead(200,y),s(m,f,p)}},n}},En=(t,e,n)=>{let r=K(t),s=r?t.getParsedResponse():t,i,o=!1;if(s&&typeof s=="object"&&s.statusCode){let a=isNaN(s.statusCode),d=a?500:s.statusCode;if(o=!a&&(s.isBase64Encoded==!0||s.isBase64Encoded=="true"),s.headers||s.cookies)try{let c=ge(s.headers,s.cookies);e.writeHead(d,c)}catch(c){return e.writeHead(500,c.headers),delete c.headers,console.error(c),e.end(v.amzMsgNull)}else e.writeHead(d,{"Content-Type":v.contentType.json});n?i=s:(typeof s.body<"u"&&(i=s.body),e.headersSent||e.setHeader("Content-Type",r?v.contentType.octet:v.contentType.json))}else e.writeHead(200,{"Content-Type":v.contentType.json}),i=s;!e.headersSent&&!n&&r&&e.setHeader("Content-Type",v.contentType.octet),n?i instanceof Uint8Array?e.end(i):e.end(JSON.stringify(i)):((typeof i=="number"||typeof i=="boolean"||i==null||i instanceof Object)&&(i=JSON.stringify(i)),i&&o&&(i=Buffer.from(i,"base64")),e.end(i))},St=t=>({filter:/^\/@url\//,callback:async(e,n)=>{let{url:r,method:s,headers:i}=e;if(He(n,s))return;let o=new URL(r,v.dummyHost),a=F(n),d=k.parseNameFromUrl(o.pathname),c=t.handlers.find(h=>h.name==d);if(!c?.url)return n.statusCode=404,n.end("Not Found");let l=v.getIsBase64Encoded(i),m=await D(e,l),f=de.createApgV2Event({req:e,mockEvent:c.url,parsedURL:o,requestId:a,body:m,isBase64Encoded:l}),p=`/@url/${c.name}`,y=o.pathname.slice(p.length);y||(y="/"),f.requestContext.accountId="anonymous",f.rawPath=y,f.requestContext.http.path=y;try{let h=Rn(n,c),g=await c.invoke(f,c.url,void 0,h);if(!g)return n.end();En(g,n,h)}catch(h){console.error(h),Z(n)}}});var vt=t=>({filter:/(^\/2015-03-31\/functions\/.*\/invocations)|(^\/@invoke\/)/,callback:async(e,n)=>{let{url:r,headers:s}=e,i=new URL(r,"http://localhost:3003"),o=k.parseNameFromUrl(i.pathname),a=t.handlers.find(g=>g.name==o),d=F(n);if(n.setHeader("Content-Type","application/json"),e.on("error",g=>{n.statusCode=502,n.end(JSON.stringify(g))}),!a){let{region:g,accountId:x}=t.aws;return n.statusCode=404,n.setHeader("x-amzn-errortype","ResourceNotFoundException"),n.end(X(o,g,x))}let c=s["x-amz-invocation-type"],l=J(s["x-amz-client-context"]);if(l instanceof Error)return n.setHeader("x-amzn-errortype","InvalidRequestContentException"),n.statusCode=400,n.end(Y);let m=c=="DryRun"?204:c=="Event"?202:200,f=await D(e),p=Q(f);if(n.setHeader("X-Amzn-Trace-Id","root=1-xxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx;sampled=0"),p instanceof Error)return n.statusCode=400,n.setHeader("x-amzn-errortype","InvalidRequestContentException"),n.end(G(p.message));n.setHeader("X-Amz-Executed-Version","$LATEST");let y=new Date,h={};n.statusCode=m,m!==200&&n.end(),m==202&&(h.kind="async");try{let g=await a.invoke(p,h,l);if(m==200){if(typeof g>"u"){n.end();return}let x=K(g),u=x?g.buffer:g;x?u=A.codec.decode(u):typeof u!="string"&&(u=JSON.stringify(u)),n.end(u)}}catch(g){n.writableFinished||(n.setHeader("X-Amz-Function-Error",g.errorType??g.message??""),n.statusCode=200,n.end(JSON.stringify(g)))}}});var Se=require("node:crypto"),xt=require("node:timers/promises");var wt=t=>({filter:"/2015-03-31/functions",method:"POST",async callback(e,n){let r=await D(e),s=JSON.parse(r),{FunctionName:i,Handler:o,Environment:a,Runtime:d,Timeout:c,MemorySize:l}=s;t.addLambda(i,{handler:o,environment:a?.Variables,runtime:d,timeout:c,memorySize:l}),t.isDynamicBuild=!0,t.setEsBuildConfig(),await t.buildContext.dispose(),await t.buildAndWatch(),await(0,xt.setTimeout)(100),n.statusCode=201,n.end(r)}}),Rt=t=>({filter:/\/2015-03-31\/functions\/*/,method:"GET",async callback(e,n){let{url:r}=e,i=new URL(r,"http://localhost:3003").pathname.slice(22),o=t.getLambdaByName(i);if(!o){n.statusCode=404,n.end();return}let a={Code:{RepositoryType:"S3",Location:"https://s3.com/snapshots/1234543"},Tags:{},Configuration:{Architectures:["arm64"],CodeSha256:"WrLckXVmmfsSPvP/15FqPi9Nt9qQBaspP6RV3T137K4=",SigningJobArn:"",FunctionArn:`arn:aws:lambda:${t.aws.region}:${t.aws.accountId}:function:${i}`,FunctionName:i,Handler:o.handlerPath,Timeout:o.timeout,Runtime:o.runtime,MemorySize:o.memorySize,Environment:{Variables:Et(o.environment)},State:"Active",LastUpdateStatus:"Successful",LastModified:new Date().toISOString(),Version:"$LATEST",Role:`arn:aws:iam::${t.aws.accountId}:role/fake-role-name`,RevisionId:(0,Se.randomUUID)(),PackageType:"Zip",Description:"",EphemeralStorage:{Size:512},TracingConfig:{Mode:"PassThrough"},VpcConfig:{Ipv6AllowedForDualStack:!1,VpcId:"",SecurityGroupIds:[],SubnetIds:[]},CodeSize:5867,SnapStart:{OptimizationStatus:"Off",ApplyOn:"None"},LoggingConfig:{LogFormat:"Text",LogGroup:`/aws/lambda/${i}`}}};n.end(JSON.stringify(a))}}),An=["AWS_EXECUTION_ENV","AWS_LAMBDA_FUNCTION_VERSION","AWS_LAMBDA_FUNCTION_NAME","_HANDLER","IS_OFFLINE","IS_LOCAL","AWS_SAM_LOCAL","AWS_LAMBDA_FUNCTION_MEMORY_SIZE"];function Et(t){let e={};for(let[n,r]of Object.entries(t))An.includes(n)||(e[n]=String(r));return e}var It=t=>({method:"GET",filter:/\/2015-03-31\/functions\/.*\/versions/,async callback(e,n){let{url:r}=e,i=new URL(r,"http://localhost:3003").pathname.slice(22);i=i.slice(0,i.indexOf("/"));let o=t.getLambdaByName(i);if(!o){n.statusCode=404,n.end();return}let a={Versions:[{Architectures:["arm64"],CodeSha256:"WrLckXVmmfsSPvP/15FqPi9Nt9qQBaspP6RV3T137K4=",SigningJobArn:"",FunctionArn:`arn:aws:lambda:${t.aws.region}:${t.aws.accountId}:function:${i}`,FunctionName:i,Handler:o.handlerPath,Timeout:o.timeout,Runtime:o.runtime,MemorySize:o.memorySize,Environment:{Variables:Et(o.environment)},State:"Active",LastUpdateStatus:"Successful",LastModified:new Date().toISOString(),Version:"$LATEST",Role:`arn:aws:iam::${t.aws.accountId}:role/fake-role-name`,RevisionId:(0,Se.randomUUID)(),PackageType:"Zip",Description:"",EphemeralStorage:{Size:512},TracingConfig:{Mode:"PassThrough"},VpcConfig:{Ipv6AllowedForDualStack:!1,VpcId:"",SecurityGroupIds:[],SubnetIds:[]},CodeSize:5867,SnapStart:{OptimizationStatus:"Off",ApplyOn:"None"},LoggingConfig:{LogFormat:"Text",LogGroup:`/aws/lambda/${i}`}}]};n.end(JSON.stringify(a))}}),At=t=>({method:"GET",filter:/\/2020-06-30\/functions\/.*\/code-signing-config/,async callback(e,n){let{url:r}=e,i=new URL(r,"http://localhost:3003").pathname.slice(22);if(i=i.slice(0,i.indexOf("/")),!t.getLambdaByName(i)){n.statusCode=404,n.end();return}let a={CodeSigningConfigArn:"",FunctionName:i};n.end(JSON.stringify(a))}});var kt=require("@smithy/eventstream-codec");var kn=(t,e)=>{let n=Buffer.from(t,e);return new Uint8Array(n.buffer,n.byteOffset,n.byteLength/Uint8Array.BYTES_PER_ELEMENT)},Pn=t=>Buffer.from(t,t.byteOffset,t.byteLength).toString("utf8"),ve=new kt.EventStreamCodec(Pn,kn),le=class t{res;static complete=Buffer.from([0,0,0,102,0,0,0,84,31,86,200,105,11,58,101,118,101,110,116,45,116,121,112,101,7,0,14,73,110,118,111,107,101,67,111,109,112,108,101,116,101,13,58,99,111,110,116,101,110,116,45,116,121,112,101,7,0,16,97,112,112,108,105,99,97,116,105,111,110,47,106,115,111,110,13,58,109,101,115,115,97,103,101,45,116,121,112,101,7,0,5,101,118,101,110,116,123,125,112,6,212,103]);constructor(e){this.res=e}write(e,n,r){this.res.write(ve.encode({headers:this.#e("PayloadChunk",v.contentType.octet),body:e}),n,r)}end(e){e?this.write(e,"utf8",()=>{this.res.end(t.complete)}):this.res.end(t.complete)}setHeader(e,n){e=="Content-Type"&&this.res.setHeader("Content-Type",n)}destroy(){this.res.destroy()}endWithError(e){let n={ErrorCode:e.errorType,ErrorDetails:JSON.stringify(e)},r=Array.from(Buffer.from(JSON.stringify(n)).values());this.res.end(ve.encode({headers:this.#e("InvokeComplete",v.contentType.json),body:new Uint8Array(r)}))}endWithJson(e){let n=Array.from(Buffer.from(JSON.stringify(e)).values());this.res.write(ve.encode({headers:this.#e("PayloadChunk",v.contentType.octet),body:new Uint8Array(n)}),()=>{this.res.end(t.complete)})}#e(e,n,r="event"){return{":event-type":{type:"string",value:e},":content-type":{type:"string",value:n},":message-type":{type:"string",value:r}}}};var Pt=t=>({filter:/^\/2021-11-15\/functions\//,callback:async(e,n)=>{let{url:r,headers:s}=e,i=new URL(r,"http://localhost:3003"),o=F(n),a=k.parseNameFromUrl(i.pathname),d=t.handlers.find(p=>p.name==a),c=await D(e),l=Q(c);if(n.setHeader("X-Amzn-Trace-Id","root=1-xxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx;sampled=0"),l instanceof Error)return n.statusCode=400,n.setHeader("x-amzn-errortype","InvalidRequestContentException"),n.end(G(l.message));let m=J(s["x-amz-client-context"]);if(m instanceof Error)return n.setHeader("x-amzn-errortype","InvalidRequestContentException"),n.statusCode=400,n.end(Y);let f=new le(n);if(d){let p=d.url?.stream??{};try{let y=await d.invoke(l,p,m,f);y&&f.endWithJson(y)}catch(y){n.writableFinished||f.endWithError(y)}}else{let{region:p,accountId:y}=t.aws;n.statusCode=404,n.end(X(a,p,y))}}});var Lt=t=>[wt(t),It(t),At(t),vt(t),Pt(t),St(t),Rt(t)];var we=process.cwd(),Ln=3,On=1024,Nn={IS_OFFLINE:!0,IS_LOCAL:!0,AWS_SAM_LOCAL:!0},Dn=we.split(L.default.sep)[0],Tn=new RegExp(`^.*:${Dn}`),Mn=t=>Tn.test(t);process.title="node (exlo)";var pe=class extends ce{#e;options;config;esBuildConfig;buildContext={};customEsBuildConfig;optimizeBuild=!1;nodeVersion=!1;onKill=[];shimRequire=!1;port=0;onceServerReady=[];isDynamicBuild=!1;endpoints={};setLambdaEndpointEnvVar=!0;constructor(e,n){super(e,{debug:typeof n.debug=="boolean"?n.debug:!1}),this.#e=[],this.options=n,this.options.customEsBuildConfig&&(this.customEsBuildConfig=this.options.customEsBuildConfig),typeof this.options.config?.server?.setEndpointEnvVar=="boolean"&&(this.setLambdaEndpointEnvVar=this.options.config.server.setEndpointEnvVar),this.options.config&&(typeof this.options.config=="string"||typeof this.options.config=="object"&&!Array.isArray(this.options.config))&&(this.config=this.options.config),typeof this.options.optimizeBuild=="boolean"&&(this.optimizeBuild=this.options.optimizeBuild),typeof this.options.shimRequire=="boolean"&&(this.shimRequire=this.options.shimRequire),this.aws.runtime?.startsWith("node")?this.nodeVersion=this.aws.runtime?.replace(/[^0-9]/g,""):this.nodeVersion="20",b.BR_BLUE("Starting exlo...")}async start(){this.#s(),this.#e=this.#r(),await this.#o(),this.setEsBuildConfig(),await this.buildAndWatch()}setEsBuildConfig(){let n={sourcemap:!0,minify:!1,entryPoints:this.#e.filter(r=>r.runtime.startsWith("n")).map(r=>r.esEntryPoint),outdir:L.default.join(we,".exlo","build"),metafile:!0,bundle:!0,platform:"node",target:"node20",format:"cjs",outbase:"src",plugins:[],external:["esbuild"],dropLabels:[]};if(typeof process.env.NODE_ENV=="string"&&(n.define={"process.env.NODE_ENV":`"${process.env.NODE_ENV}"`}),typeof this.nodeVersion=="string"&&!isNaN(Number(this.nodeVersion))){Number(process.versions.node.slice(0,2))<Number(this.nodeVersion)&&b.RED(`You are running on NodeJS ${process.version} which is lower than defined '${this.nodeVersion}'.`),n.target=`node${this.nodeVersion}`;let r=()=>this.sco;n.plugins?.push(ke({nodeVersion:Number(this.nodeVersion),shimRequire:this.shimRequire,optimizeBuild:this.optimizeBuild,buildCallback:this.buildCallback,getSockets:r}))}this.customEsBuildConfig&&(n=Pe(n,this.customEsBuildConfig)),this.esBuildConfig=n}async buildAndWatch(){this.buildContext=await xe.default.context(this.esBuildConfig),await this.buildContext.watch()}buildCallback=async(e,n)=>{if(n||this.isDynamicBuild)await this.#t(e);else{let{outputs:r}=e.metafile;if(this.#i(r),this.customBuildCallback)try{await this.customBuildCallback(e,!1)}catch(o){console.log(o)}this.#a();let s=this,i=await new Promise(o=>{this.listen(this.port,async(a,d)=>{let c=`http://localhost:${a}`;b.PINK(`Lambda endpoint: ${c}`),this.endpoints.lambda=c,this.setLambdaEndpointEnvVar&&(this.runtimeConfig.environment.AWS_ENDPOINT_URL_LAMBDA=c),await s.load(s.#e);for(let l of s.#e)l.setEnv("LOCAL_PORT",a),l.setEnv("AWS_LAMBDA_RUNTIME_API",`127.0.0.1:${a}`),this.setLambdaEndpointEnvVar&&l.setEnv("AWS_ENDPOINT_URL_LAMBDA",c);o({url:c,port:a})})});this.onceServerReady.forEach(o=>{o(i)})}};async#t(e){if(e?.errors?.length)b.RED("Build failed:"),console.error(e.errors);else{this.#i(e.metafile.outputs);try{await this.load(this.#e),this.customBuildCallback&&await this.customBuildCallback(e,!0)}catch(n){console.error(n)}console.log(`\x1B[32m${new Date().toLocaleString()} \u{1F504}\u2705 Rebuild\x1B[0m`)}}#n(e){let n=this.aws,r=n.runtime,s=this.runtimeConfig.environment.AWS_REGION??this.runtimeConfig.environment.REGION,o=n.functions[e],a=o.handler,d=L.default.extname(a),c=d.slice(1),l=L.default.resolve(a.replace(d,"")),m=n.getFunction(e),f=m.runtime??r,p={name:e,runtime:m.runtime??r,handlerPath:a,handlerName:c,esEntryPoint:l,memorySize:o.memorySize??this.runtimeConfig.memorySize??On,timeout:o.timeout??this.runtimeConfig.timeout??Ln,sqs:[],ddb:[],environment:{AWS_EXECUTION_ENV:`AWS_Lambda_${f}`,AWS_LAMBDA_FUNCTION_VERSION:"$LATEST",AWS_LAMBDA_FUNCTION_NAME:e,_HANDLER:L.default.basename(a),...this.runtimeConfig.environment,...o.environment,...Nn},invoke:async(y,h)=>{let g=this.getHandlerByName(`/@invoke/${e}`);if(g)return await g.invoke(y,h);b.RED(`'${e}' is not mounted yet.
|
package/dist/standalone.mjs
CHANGED
|
@@ -6,7 +6,7 @@ Please verify provided SQS Client validity.`),console.error(l)}}},Ot=/(-|\w+)/g,
|
|
|
6
6
|
`)}else I=E;I.trim()&&console.log(I)}}catch(P){console.log("err",P),h(P)}};this.python.stdout.on("data",u);let S=w=>{let R=w.toString();if(R.includes(t.ERR_RESPONSE))try{R=JSON.parse(R.split(t.ERR_RESPONSE)[1]),R.requestId=p}catch{}finally{this.python.stdout.removeListener("data",u),this.python.stderr.removeListener("data",S),h(R)}else console.log(R)};this.python.stderr.on("data",S),this.python.stdin.write(`${g}
|
|
7
7
|
`)}),this.watcherListener=()=>{this.isMounted&&(this.unmount(!0),this.watchers.forEach(l=>l.close()),this.watchers=[],this.emitRebuild())}}setWatchFiles=async e=>{try{let n=e.split(t.WATCH),s=n[n.length-1].split(t.WATCHEND)[0],i=JSON.parse(s).map(o=>`${o.replace(/\./g,_.sep)}.py`);for(let o of i)try{await Ue(o),this.watchers.push(Vt(o,{persistent:!1},this.watcherListener))}catch{}}catch(n){console.log(n)}};findPython(){let[e]=this.runtime.split("."),n=e.split("python")[1];if(ze(`${e} --version`))return e;let r=ze("python --version");if(!r)throw new Error("Can not find python on your OS. Make sure it is installed.");if(n){let s=r.split(" ")[1]?.split(".")[0];s&&s!=n&&b.YELLOW("found python binary but with different version")}return"python"}load=()=>{this.bin||(this.bin=this.findPython()),this.python=Ct(this.bin,["-u",t.wrapper,this.handlerFileAbsolutePath,this.pyModulePath,this.handlerName,String(this.timeout)],{env:this.environment}),this.python.pid||(console.error(`Can not find ${this.bin} in your PATH`),process.exit(1)),this.isMounted=!0};onComplete=e=>{}};import{spawn as Jt}from"node:child_process";import{watch as Qt}from"node:fs";import{access as Ce}from"node:fs/promises";import ne from"node:path";var re=class t{invoke;mount;unmount;name;timeout;memorySize;environment;handlerPath;modulePath;handlerDir;handlerName;runtime;bin;ruby;isMounted=!1;emitRebuild;watcherListener;watchers=[];static wrapper=ne.resolve(M("exlo"),"./src/lib/runtime/runners/ruby/index.rb");static DELIMITER="__|response|__";static ERR_RESPONSE="__|error|__";static WATCH="__|watch|__";constructor({name:e,timeout:n,memorySize:r,environment:s,handlerPath:i,handlerName:o,runtime:a},d){this.name=e,this.timeout=n,this.memorySize=r,this.environment=s,this.handlerName=o,this.runtime=a,this.emitRebuild=d;let c=ne.resolve(i);this.handlerDir=ne.dirname(c),this.handlerPath=ne.basename(c,`.${this.handlerName}`),this.modulePath=`${this.handlerDir}/${this.handlerPath}.rb`,this.mount=async()=>{if(!this.ruby)try{await Ce(this.modulePath),this.load()}catch{console.error(`Can not find ${this.name}'s handler at: "${this.modulePath}"`),process.exit(1)}},this.unmount=l=>{l&&(this.ruby?.kill(),this.ruby=void 0,this.isMounted=!1)},this.invoke=async({event:l,info:m,clientContext:f,awsRequestId:p})=>new Promise((y,h)=>{let g=JSON.stringify({event:l,awsRequestId:p,context:f??""}),x=S=>{let w=null,R=S.toString();try{if(R.includes(t.WATCH))this.setWatchFiles(R);else if(R.includes(t.DELIMITER)){let E=R.split(t.DELIMITER),P=E[E.length-1];if(E.length>1){let I=E.slice(0,-1).join(`
|
|
8
8
|
`);I.trim()&&console.log(I)}P&&(w=JSON.parse(P)),this.ruby.stdout.removeListener("data",x),this.ruby.stderr.removeListener("data",u),y(w)}else R.trim()&&console.log(R)}catch(E){h(E)}};this.ruby.stdout.on("data",x);let u=S=>{let w=S.toString();if(w.includes(t.ERR_RESPONSE))try{w=JSON.parse(w.split(t.ERR_RESPONSE)[1]),w.requestId=p}catch{}finally{this.ruby.stdout.removeListener("data",x),this.ruby.stderr.removeListener("data",u),h(w)}else console.log(w)};this.ruby.stderr.on("data",u),this.ruby.stdin.write(`${g}
|
|
9
|
-
`)}),this.watcherListener=()=>{this.isMounted&&(this.unmount(!0),this.watchers.forEach(l=>l.close()),this.watchers=[],this.emitRebuild())}}setWatchFiles=async e=>{try{let n=e.split(t.WATCH),r=n[n.length-1],s=JSON.parse(r);s.push(this.modulePath);for(let i of s)try{await Ce(i),this.watchers.push(Qt(i,{persistent:!1},this.watcherListener))}catch{}}catch(n){console.log(n)}};load=()=>{this.bin||(this.bin=process.platform==="win32"?"ruby.exe":"ruby"),this.ruby=Jt(this.bin,[t.wrapper,this.modulePath,this.handlerName,this.name,String(this.timeout)],{env:this.environment,shell:!0}),this.ruby.pid||(console.error(`Can not find ${this.bin} in your PATH`),process.exit(1)),this.isMounted=!0};onComplete=e=>{}};var Kt=["@invoke","@url"],k=class t{handlers=[];static ip="127.0.0.1";debug=!1;port=0;constructor(e){this.debug=e.debug}static parseNameFromUrl(e){let n=e.split("/"),r=Kt.includes(n[1])?n[2]:n[3];if(r=decodeURIComponent(r),r.includes(":function:")){let s=r.split(":function:");r=s[s.length-1]}if(r.includes(":")){let s=r.split(":");s.length==2&&(r=s[0])}return r}getHandlerByName(e){if(!e)return;let n=t.parseNameFromUrl(e);return this.handlers.find(r=>r.name==n)}addHandler(e){let n=this.handlers.findIndex(r=>r.name==e.name&&r.esOutputPath==e.esOutputPath);n==-1?(this.handlers.push(e),this.#e("POST",`/2015-03-31/functions/${e.name}/invocations`),e.url&&this.#e("ANY",`/@url/${e.name}`,"34")):this.handlers[n].runtime.startsWith("n")&&(this.handlers[n].clear(),this.handlers[n]=e)}#e(e,n,r="90"){let s=`${e} http://localhost:${this.port}${n}`;console.log(`\x1B[${r}m${s}\x1B[0m`)}};var se;Ve&&(se=Object.values(Ve()).reduce((t,e)=>(t.push(...e),t),[])?.filter(t=>!t.internal&&t.family==="IPv4").find(Boolean)?.address);var Zt=Xt?.url()!=null;Zt&&(console.warn("Lambdas timeout are disabled when a Debugger is attached"),H.ENABLE_TIMEOUT=!1);var en={errors:[],warnings:[],outputFiles:[],metafile:{inputs:{},outputs:{}},mangleCache:{}},ie=class extends k{#e;runtimeConfig={};#t;sco=[];aws;customOfflineRequests=[];customBuildCallback;onReady;stop(e){this.#e.close(e)}constructor(e,n={debug:!1}){super(n),b.setDebug(n.debug),this.aws=e.aws,this.sco=[],this.#e=Yt.createServer({maxHeaderSize:105536},this.#r.bind(this)),this.#e.on("connection",s=>{s.on("close",()=>{let i=this.sco.findIndex(o=>o==s);i!=-1&&this.sco.splice(i,1)}),this.sco.push(s)});let r=Gt();v.accountId=Buffer.from(r).toString("hex").slice(0,16),v.apiId=Buffer.from(r).toString("ascii").slice(0,10),v.port=this.port}setPort(e){this.port=e,v.port=e}listen(e=0,n){if(isNaN(e))throw Error("port should be a number");this.#e.once("error",async r=>{r.code==="EADDRINUSE"?(b.RED(r.message),process.exit(1)):console.log(r)}),this.#e.listen(e,async()=>{let{port:r,address:s}=this.#e.address();this.setPort(r),se&&(k.ip=se),typeof n=="function"&&await n(r,se);try{await this.onReady?.(r,k.ip),await je(this.handlers,this.aws)}catch(i){console.error(i)}})}#n(e,n){n=n.endsWith("/")?n:`${n}/`;let r=this.customOfflineRequests.find(s=>{let i=!1,o=!0;return typeof s.filter=="string"?(s.filter.endsWith("/")||(s.filter+="/"),i=s.filter==n):s.filter instanceof RegExp&&(i=s.filter.test(n)),typeof s.method=="string"&&s.method.toUpperCase()!="ANY"?o=s.method.toUpperCase()==e:Array.isArray(s.method)&&(s.method.findIndex(d=>d.toUpperCase()=="ANY")!==-1||(o=s.method.findIndex(d=>d.toUpperCase()==e)!==-1)),i&&o});if(r)return r.callback}async#r(e,n){let{url:r,method:s}=e,i=new URL(r,v.dummyHost),o=this.#n(s,i.pathname);if(o)try{await o(e,n)}catch{n.writableFinished||n.end("Internal Server Error")}else{e.on("error",d=>{console.error(d.stack)});let a=()=>{n.setHeader("Content-Type","text/html"),n.statusCode=404,n.end(Ie)};this.#t?this.#t(e,n,a):a()}}fakeRebuildEmitter=async()=>{if(this.customBuildCallback)try{await this.customBuildCallback(en,!0)}catch(e){console.log(e)}console.log(`\x1B[32m${new Date().toLocaleString()} \u{1F504}\u2705 Rebuild\x1B[0m`)};async load(e){for(let n of e){let r=n.runtime.charAt(0);n.runner=r=="n"?new ee(n):r=="p"?new te(n,this.fakeRebuildEmitter):r=="r"?new re(n,this.fakeRebuildEmitter):new Z(n.runtime);let s=new H(n);this.addHandler(s)}}};import{rm as rn}from"node:fs/promises";import N from"node:path";import{pathToFileURL as sn}from"node:url";import on from"esbuild";var nn="0.0.7";function Be(t){let e=new Set;t.plugins&&(t.plugins=t.plugins.filter((r,s)=>typeof r!="object"||!r||!("name"in r)?!1:((!r.name||!r.name.length||typeof r.name!="string")&&(r.name=`plugin-${s}`,console.warn(`No Plugin name provided at index ${s}`)),e.has(r.name)?r.name=r.name+s:e.add(r.name),!0)));async function n({stop:r,lambdas:s,region:i,esbuild:o,getServices:a,setService:d,addLambda:c,log:l,setEndpoint:m,getEndpoint:f,getAwsProviderDefaults:p,setAwsProviderDefaults:y}){let h={build:{esbuild:t?.build?.esbuild??{},shimRequire:t?.build?.shimRequire,optimizeBuild:t?.build?.optimizeBuild},server:{port:t.server?.port,setEndpointEnvVar:t.server?.setEndpointEnvVar},onKill:[]};if(t.defaults&&typeof t.defaults=="object"&&!Array.isArray(t.defaults)&&y(t.defaults),t.functions&&typeof t.functions=="object"&&!Array.isArray(t.functions))for(let[x,u]of Object.entries(t.functions))c(x,u);t.services&&(t.services.sqs&&d("sqs",t.services.sqs),t.services.sns&&d("sns",t.services.sns),t.services.dynamodb&&d("dynamodb",t.services.dynamodb));let g={stop:r,lambdas:s,region:i,esbuild:o,options:t,config:h,getServices:a,setService:d,addLambda:c,log:l,setEndpoint:m,getEndpoint:f,getAwsProviderDefaults:p};if(t.plugins){h.server.onReady=async(u,S)=>{for(let w of t.plugins)if(w.server?.onReady)try{await w.server.onReady.call(g,u,S)}catch(R){l.RED(w.name),console.error(R)}},h.buildCallback=async(u,S)=>{for(let w of t.plugins)if(w.buildCallback)try{await w.buildCallback.call(g,u,S)}catch(R){l.RED(w.name),console.error(R),S||process.exit(1)}};let x=t.plugins.reduce((u,S)=>(S.server?.request?.length&&u.push(...S.server.request),u),[]);x?.length&&(h.server.request=x.map(u=>(u.callback=u.callback.bind(g),u)));for(let u of t.plugins)if(u.onKill&&h.onKill.push(u.onKill.bind(g)),u.onInit)try{await u.onInit.call(g)}catch(S){throw l.RED(u.name),S}}return h}return n.plugins=t.plugins??[],n}var an=["js","mjs","cjs","ts","cts","mts"],cn=async t=>{let e=N.dirname(N.toNamespacedPath(t)),n=N.basename(t,N.extname(t)),r=N.join(e,`__${n}.mjs`);await on.build({outfile:r,entryPoints:[t],bundle:!0,packages:"external",platform:"node",format:"esm",target:`node${process.versions.node.split(".")[0]}`,minify:!0,sourcemap:"inline",sourcesContent:!0});try{return await import(sn(r).href)}catch(s){throw s}finally{await rn(r)}},Je=async t=>{if(t){if(typeof t=="string"){let e=N.posix.parse(t),n=N.posix.join(e.dir,e.name),r=e.ext.slice(1),s=N.posix.resolve(n);an.includes(r)&&(s+=`.${r}`);let i;try{i=await cn(s)}catch(o){b.YELLOW(`Can not read 'defineConfig' from ${t}`),console.error(o),process.exit(1)}return{exportedFunc:i,configObjectName:r,configPath:s}}if(typeof t=="object"&&!Array.isArray(t))return{configObjectName:"__inline_config__",configPath:"inline define config",exportedFunc:Be(t)}}};var dn=t=>{let e=t.split(";");return e.findIndex(r=>r.toLowerCase().startsWith("path="))==-1&&e.push("Path=/"),e.join(";")},le=(t,e)=>{let n={};if(t&&Object.entries(t).forEach(([r,s])=>{n[r.toLowerCase()]=Array.isArray(s)?`[${s.join(", ")}]`:s}),Array.isArray(e)){if(!e.every(r=>typeof r=="string")){let r=new Error("Wrong 'cookies'. must be string[]",{cause:e}),s={"Content-Type":n["content-type"]??"application/json","x-amzn-ErrorType":"InternalFailure"};throw n["set-cookie"]&&(s["set-cookie"]=n["set-cookie"]),r.headers=s,r}e=e.map(dn),n["set-cookie"]=n["set-cookie"]?[n["set-cookie"],...e]:e}return n};import{randomUUID as Qe}from"node:crypto";var oe=class t extends v{res;mockEvent;payload;constructor({res:e,req:n,body:r,mockEvent:s,multiValueHeaders:i,isBase64Encoded:o,lambdaName:a,parsedURL:d,requestId:c}){super(),this.res=e,this.mockEvent=s,this.payload=s.version==1?t.createApgV1Event({req:n,mockEvent:s,parsedURL:d,lambdaName:a,multiValueHeaders:i,isBase64Encoded:o,requestId:c,body:r}):t.createApgV2Event({req:n,mockEvent:s,parsedURL:d,requestId:c,isBase64Encoded:o,body:r})}static skipHeaders=["connection","content"];static createApgV2Event=({req:e,mockEvent:n,parsedURL:r,requestId:s,isBase64Encoded:i,body:o})=>{let{method:a,headers:d}=e,c=t.getPathParameters(n,r),l,m=n.methods.find(S=>S==a)??"ANY",f={},p="";for(let S of Array.from(new Set(r.searchParams.keys()))){let w=r.searchParams.getAll(S);p+=`&${w.map(R=>encodeURI(`${S}=${R}`)).join("&")}`,f[S]=w.join(",")}p&&(p=p.slice(1));let y=n.paths[0]=="/*"?"$default":`${m} ${r.pathname}`,h=new Date,g="127.0.0.1",x=d.host?.startsWith("localhost")?g:d.host?d.host.split(":")[0]:g,u={version:"2.0",routeKey:y,rawPath:r.pathname,rawQueryString:p,headers:t.getCustomHeaders(e,n),requestContext:{accountId:String(t.accountId),apiId:t.apiId,domainName:`localhost:${t.port}`,domainPrefix:"localhost",http:{method:a,path:r.pathname,protocol:"HTTP/1.1",sourceIp:x,userAgent:d["user-agent"]??""},requestId:s,routeKey:y,stage:"$default",time:h.toISOString(),timeEpoch:h.getTime()}};return o?(u.body=o,u.isBase64Encoded=i):u.isBase64Encoded=!1,Object.keys(f).length&&(u.queryStringParameters=f),Object.keys(c).length&&(u.pathParameters=c),d.cookie&&(u.cookies=d.cookie.split("; ")),l=u,l.headers["x-mock-type"]&&delete l.headers["x-mock-type"],l};static createApgV1Event=({req:e,mockEvent:n,parsedURL:r,lambdaName:s,isBase64Encoded:i,requestId:o,body:a})=>{let{method:d}=e,c={};n.proxy=="httpApi"&&(c.version="1.0");let l=n.paths[0];c.resource=l,c.path=r.pathname,c.httpMethod=d;let{headers:m,multiValueHeaders:f,apiKey:p}=t.getApiGV1Headers(e,n);c.headers=m,c.multiValueHeaders=f;let y=String(e.socket.remoteAddress),h=Object.fromEntries(r.searchParams);c.queryStringParameters=Object.keys(h).length?h:null;let g=t.getMultiValueQueryStringParameters(r.searchParams);c.multiValueQueryStringParameters=Object.keys(g).length?g:null;let x=new Date,u={accountId:String(t.accountId),apiId:t.apiId,domainName:`localhost:${t.port}`,domainPrefix:"localhost",extendedRequestId:"fake-id",httpMethod:d,identity:{accessKey:null,accountId:null,caller:null,cognitoAuthenticationProvider:null,cognitoAuthenticationType:null,cognitoIdentityId:null,cognitoIdentityPoolId:null,principalOrgId:null,sourceIp:y,user:null,userAgent:e.headers["user-agent"],userArn:null},path:r.pathname,protocol:"HTTP/1.1",requestId:o,requestTime:x.toISOString(),requestTimeEpoch:x.getTime(),resourceId:"exhmtv",resourcePath:l};n.proxy=="httpApi"?(u.identity.cognitoAmr=null,u.stage="$default"):(u.stage="dev",n.private&&(u.identity.apiKey=p,u.identity.apiKeyId="abcdefghjk")),c.requestContext=u;let S=t.getPathParameters(n,r);return c.pathParameters=Object.keys(S).length?S:null,c.stageVariables=null,c.body=a??null,c.isBase64Encoded=a?i:!1,c};returnError=e=>{if(this.res.writableFinished)return!0;let n=500,r=t.httpErrMsg;e&&t.isEndpointTimeoutError(e.errorMessage)&&(this.mockEvent.proxy=="httpApi"?(n=503,r=t.unavailable):(n=504,r=t.apgTimeoutMsg));let s=[["Date",new Date().toUTCString()],["Content-Type",t.contentType.json],["Content-Length",String(r.length)],t.keepAlive,["Apigw-Requestid","ETuSEj-PiGYEJdQ="]];return this.res.shouldKeepAlive=!1,this.res.writeHead(n,s),this.res.end(r)};#e=e=>{let n="",r=typeof e;if(r=="string"||r=="number"||r=="boolean")n=String(e);else if(e===null)n="";else throw new Error("");return n};sendV1Response=e=>{let n=[["Date",new Date().toUTCString()],["Apigw-Requestid",Buffer.from(Qe()).toString("base64").slice(0,16)],t.keepAlive],r=200;if(!e||isNaN(e.statusCode))throw b.RED(`Valid 'http' response payload must be an object which includes a valid 'statusCode'.
|
|
9
|
+
`)}),this.watcherListener=()=>{this.isMounted&&(this.unmount(!0),this.watchers.forEach(l=>l.close()),this.watchers=[],this.emitRebuild())}}setWatchFiles=async e=>{try{let n=e.split(t.WATCH),r=n[n.length-1],s=JSON.parse(r);s.push(this.modulePath);for(let i of s)try{await Ce(i),this.watchers.push(Qt(i,{persistent:!1},this.watcherListener))}catch{}}catch(n){console.log(n)}};load=()=>{this.bin||(this.bin=process.platform==="win32"?"ruby.exe":"ruby"),this.ruby=Jt(this.bin,[t.wrapper,this.modulePath,this.handlerName,this.name,String(this.timeout)],{env:this.environment,shell:!0}),this.ruby.pid||(console.error(`Can not find ${this.bin} in your PATH`),process.exit(1)),this.isMounted=!0};onComplete=e=>{}};var Kt=["@invoke","@url"],k=class t{handlers=[];static ip="127.0.0.1";debug=!1;port=0;constructor(e){this.debug=e.debug}static parseNameFromUrl(e){let n=e.split("/"),r=Kt.includes(n[1])?n[2]:n[3];if(r=decodeURIComponent(r),r.includes(":function:")){let s=r.split(":function:");r=s[s.length-1]}if(r.includes(":")){let s=r.split(":");s.length==2&&(r=s[0])}return r}getHandlerByName(e){if(!e)return;let n=t.parseNameFromUrl(e);return this.handlers.find(r=>r.name==n)}addHandler(e){let n=this.handlers.findIndex(r=>r.name==e.name&&r.esOutputPath==e.esOutputPath);n==-1?(this.handlers.push(e),this.#e("POST",`/2015-03-31/functions/${e.name}/invocations`),e.url&&this.#e("ANY",`/@url/${e.name}`,"34")):this.handlers[n].runtime.startsWith("n")&&(this.handlers[n].clear(),this.handlers[n]=e)}#e(e,n,r="90"){let s=`${e} http://localhost:${this.port}${n}`;console.log(`\x1B[${r}m${s}\x1B[0m`)}};var se;Ve&&(se=Object.values(Ve()).reduce((t,e)=>(t.push(...e),t),[])?.filter(t=>!t.internal&&t.family==="IPv4").find(Boolean)?.address);var Zt=Xt?.url()!=null;Zt&&(console.warn("Lambdas timeout are disabled when a Debugger is attached"),H.ENABLE_TIMEOUT=!1);var en={errors:[],warnings:[],outputFiles:[],metafile:{inputs:{},outputs:{}},mangleCache:{}},ie=class extends k{#e;runtimeConfig={};#t;sco=[];aws;customOfflineRequests=[];customBuildCallback;onReady;stop(e){this.#e.close(e)}constructor(e,n={debug:!1}){super(n),b.setDebug(n.debug),this.aws=e.aws,this.sco=[],this.#e=Yt.createServer({maxHeaderSize:105536},this.#r.bind(this)),this.#e.on("connection",s=>{s.on("close",()=>{let i=this.sco.findIndex(o=>o==s);i!=-1&&this.sco.splice(i,1)}),this.sco.push(s)});let r=Gt();v.accountId=Buffer.from(r).toString("hex").slice(0,16),v.apiId=Buffer.from(r).toString("ascii").slice(0,10),v.port=this.port}setPort(e){this.port=e,v.port=e}listen(e=0,n){if(isNaN(e))throw Error("port should be a number");this.#e.once("error",async r=>{r.code==="EADDRINUSE"?(b.RED(r.message),process.exit(1)):console.log(r)}),this.#e.listen(e,async()=>{let{port:r,address:s}=this.#e.address();this.setPort(r),se&&(k.ip=se),typeof n=="function"&&await n(r,se);try{await this.onReady?.(r,k.ip),await je(this.handlers,this.aws)}catch(i){console.error(i)}})}#n(e,n){n=n.endsWith("/")?n:`${n}/`;let r=this.customOfflineRequests.find(s=>{let i=!1,o=!0;return typeof s.filter=="string"?(s.filter.endsWith("/")||(s.filter+="/"),i=s.filter==n):s.filter instanceof RegExp&&(i=s.filter.test(n)),typeof s.method=="string"&&s.method.toUpperCase()!="ANY"?o=s.method.toUpperCase()==e:Array.isArray(s.method)&&(s.method.findIndex(d=>d.toUpperCase()=="ANY")!==-1||(o=s.method.findIndex(d=>d.toUpperCase()==e)!==-1)),i&&o});if(r)return r.callback}async#r(e,n){let{url:r,method:s}=e,i=new URL(r,v.dummyHost),o=this.#n(s,i.pathname);if(o)try{await o(e,n)}catch{n.writableFinished||n.end("Internal Server Error")}else{e.on("error",d=>{console.error(d.stack)});let a=()=>{n.setHeader("Content-Type","text/html"),n.statusCode=404,n.end(Ie)};this.#t?this.#t(e,n,a):a()}}fakeRebuildEmitter=async()=>{if(this.customBuildCallback)try{await this.customBuildCallback(en,!0)}catch(e){console.log(e)}console.log(`\x1B[32m${new Date().toLocaleString()} \u{1F504}\u2705 Rebuild\x1B[0m`)};async load(e){for(let n of e){let r=n.runtime.charAt(0);n.runner=r=="n"?new ee(n):r=="p"?new te(n,this.fakeRebuildEmitter):r=="r"?new re(n,this.fakeRebuildEmitter):new Z(n.runtime);let s=new H(n);this.addHandler(s)}}};import{rm as rn}from"node:fs/promises";import N from"node:path";import{pathToFileURL as sn}from"node:url";import on from"esbuild";var nn="0.0.8";function Be(t){let e=new Set;t.plugins&&(t.plugins=t.plugins.filter((r,s)=>typeof r!="object"||!r||!("name"in r)?!1:((!r.name||!r.name.length||typeof r.name!="string")&&(r.name=`plugin-${s}`,console.warn(`No Plugin name provided at index ${s}`)),e.has(r.name)?r.name=r.name+s:e.add(r.name),!0)));async function n({stop:r,lambdas:s,region:i,esbuild:o,getServices:a,setService:d,addLambda:c,log:l,setEndpoint:m,getEndpoint:f,getAwsProviderDefaults:p,setAwsProviderDefaults:y}){let h={build:{esbuild:t?.build?.esbuild??{},shimRequire:t?.build?.shimRequire,optimizeBuild:t?.build?.optimizeBuild},server:{port:t.server?.port,setEndpointEnvVar:t.server?.setEndpointEnvVar},onKill:[]};if(t.defaults&&typeof t.defaults=="object"&&!Array.isArray(t.defaults)&&y(t.defaults),t.functions&&typeof t.functions=="object"&&!Array.isArray(t.functions))for(let[x,u]of Object.entries(t.functions))c(x,u);t.services&&(t.services.sqs&&d("sqs",t.services.sqs),t.services.sns&&d("sns",t.services.sns),t.services.dynamodb&&d("dynamodb",t.services.dynamodb));let g={stop:r,lambdas:s,region:i,esbuild:o,options:t,config:h,getServices:a,setService:d,addLambda:c,log:l,setEndpoint:m,getEndpoint:f,getAwsProviderDefaults:p};if(t.plugins){h.server.onReady=async(u,S)=>{for(let w of t.plugins)if(w.server?.onReady)try{await w.server.onReady.call(g,u,S)}catch(R){l.RED(w.name),console.error(R)}},h.buildCallback=async(u,S)=>{for(let w of t.plugins)if(w.buildCallback)try{await w.buildCallback.call(g,u,S)}catch(R){l.RED(w.name),console.error(R),S||process.exit(1)}};let x=t.plugins.reduce((u,S)=>(S.server?.request?.length&&u.push(...S.server.request),u),[]);x?.length&&(h.server.request=x.map(u=>(u.callback=u.callback.bind(g),u)));for(let u of t.plugins)if(u.onKill&&h.onKill.push(u.onKill.bind(g)),u.onInit)try{await u.onInit.call(g)}catch(S){throw l.RED(u.name),S}}return h}return n.plugins=t.plugins??[],n}var an=["js","mjs","cjs","ts","cts","mts"],cn=async t=>{let e=N.dirname(N.toNamespacedPath(t)),n=N.basename(t,N.extname(t)),r=N.join(e,`__${n}.mjs`);await on.build({outfile:r,entryPoints:[t],bundle:!0,packages:"external",platform:"node",format:"esm",target:`node${process.versions.node.split(".")[0]}`,minify:!0,sourcemap:"inline",sourcesContent:!0});try{return await import(sn(r).href)}catch(s){throw s}finally{await rn(r)}},Je=async t=>{if(t){if(typeof t=="string"){let e=N.posix.parse(t),n=N.posix.join(e.dir,e.name),r=e.ext.slice(1),s=N.posix.resolve(n);an.includes(r)&&(s+=`.${r}`);let i;try{i=await cn(s)}catch(o){b.YELLOW(`Can not read 'defineConfig' from ${t}`),console.error(o),process.exit(1)}return{exportedFunc:i,configObjectName:r,configPath:s}}if(typeof t=="object"&&!Array.isArray(t))return{configObjectName:"__inline_config__",configPath:"inline define config",exportedFunc:Be(t)}}};var dn=t=>{let e=t.split(";");return e.findIndex(r=>r.toLowerCase().startsWith("path="))==-1&&e.push("Path=/"),e.join(";")},le=(t,e)=>{let n={};if(t&&Object.entries(t).forEach(([r,s])=>{n[r.toLowerCase()]=Array.isArray(s)?`[${s.join(", ")}]`:s}),Array.isArray(e)){if(!e.every(r=>typeof r=="string")){let r=new Error("Wrong 'cookies'. must be string[]",{cause:e}),s={"Content-Type":n["content-type"]??"application/json","x-amzn-ErrorType":"InternalFailure"};throw n["set-cookie"]&&(s["set-cookie"]=n["set-cookie"]),r.headers=s,r}e=e.map(dn),n["set-cookie"]=n["set-cookie"]?[n["set-cookie"],...e]:e}return n};import{randomUUID as Qe}from"node:crypto";var oe=class t extends v{res;mockEvent;payload;constructor({res:e,req:n,body:r,mockEvent:s,multiValueHeaders:i,isBase64Encoded:o,lambdaName:a,parsedURL:d,requestId:c}){super(),this.res=e,this.mockEvent=s,this.payload=s.version==1?t.createApgV1Event({req:n,mockEvent:s,parsedURL:d,lambdaName:a,multiValueHeaders:i,isBase64Encoded:o,requestId:c,body:r}):t.createApgV2Event({req:n,mockEvent:s,parsedURL:d,requestId:c,isBase64Encoded:o,body:r})}static skipHeaders=["connection","content"];static createApgV2Event=({req:e,mockEvent:n,parsedURL:r,requestId:s,isBase64Encoded:i,body:o})=>{let{method:a,headers:d}=e,c=t.getPathParameters(n,r),l,m=n.methods.find(S=>S==a)??"ANY",f={},p="";for(let S of Array.from(new Set(r.searchParams.keys()))){let w=r.searchParams.getAll(S);p+=`&${w.map(R=>encodeURI(`${S}=${R}`)).join("&")}`,f[S]=w.join(",")}p&&(p=p.slice(1));let y=n.paths[0]=="/*"?"$default":`${m} ${r.pathname}`,h=new Date,g="127.0.0.1",x=d.host?.startsWith("localhost")?g:d.host?d.host.split(":")[0]:g,u={version:"2.0",routeKey:y,rawPath:r.pathname,rawQueryString:p,headers:t.getCustomHeaders(e,n),requestContext:{accountId:String(t.accountId),apiId:t.apiId,domainName:`localhost:${t.port}`,domainPrefix:"localhost",http:{method:a,path:r.pathname,protocol:"HTTP/1.1",sourceIp:x,userAgent:d["user-agent"]??""},requestId:s,routeKey:y,stage:"$default",time:h.toISOString(),timeEpoch:h.getTime()}};return o?(u.body=o,u.isBase64Encoded=i):u.isBase64Encoded=!1,Object.keys(f).length&&(u.queryStringParameters=f),Object.keys(c).length&&(u.pathParameters=c),d.cookie&&(u.cookies=d.cookie.split("; ")),l=u,l.headers["x-mock-type"]&&delete l.headers["x-mock-type"],l};static createApgV1Event=({req:e,mockEvent:n,parsedURL:r,lambdaName:s,isBase64Encoded:i,requestId:o,body:a})=>{let{method:d}=e,c={};n.proxy=="httpApi"&&(c.version="1.0");let l=n.paths[0];c.resource=l,c.path=r.pathname,c.httpMethod=d;let{headers:m,multiValueHeaders:f,apiKey:p}=t.getApiGV1Headers(e,n);c.headers=m,c.multiValueHeaders=f;let y=String(e.socket.remoteAddress),h=Object.fromEntries(r.searchParams);c.queryStringParameters=Object.keys(h).length?h:null;let g=t.getMultiValueQueryStringParameters(r.searchParams);c.multiValueQueryStringParameters=Object.keys(g).length?g:null;let x=new Date,u={accountId:String(t.accountId),apiId:t.apiId,domainName:`localhost:${t.port}`,domainPrefix:"localhost",extendedRequestId:"fake-id",httpMethod:d,identity:{accessKey:null,accountId:null,caller:null,cognitoAuthenticationProvider:null,cognitoAuthenticationType:null,cognitoIdentityId:null,cognitoIdentityPoolId:null,principalOrgId:null,sourceIp:y,user:null,userAgent:e.headers["user-agent"],userArn:null},path:r.pathname,protocol:"HTTP/1.1",requestId:o,requestTime:x.toISOString(),requestTimeEpoch:x.getTime(),resourceId:"exhmtv",resourcePath:l};n.proxy=="httpApi"?(u.identity.cognitoAmr=null,u.stage="$default"):(u.stage="dev",n.private&&(u.identity.apiKey=p,u.identity.apiKeyId="abcdefghjk")),c.requestContext=u;let S=t.getPathParameters(n,r);return c.pathParameters=Object.keys(S).length?S:null,c.stageVariables=null,c.body=a??null,c.isBase64Encoded=a?i:!1,c};returnError=e=>{if(this.res.writableFinished)return!0;let n=500,r=t.httpErrMsg;e&&t.isEndpointTimeoutError(e.errorMessage)&&(this.mockEvent.proxy=="httpApi"?(n=503,r=t.unavailable):(n=504,r=t.apgTimeoutMsg));let s=[["Date",new Date().toUTCString()],["Content-Type",t.contentType.json],["Content-Length",String(r.length)],t.keepAlive,["Apigw-Requestid","ETuSEj-PiGYEJdQ="]];return this.res.shouldKeepAlive=!1,this.res.writeHead(n,s),this.res.end(r)};#e=e=>{let n="",r=typeof e;if(r=="string"||r=="number"||r=="boolean")n=String(e);else if(e===null)n="";else throw new Error("");return n};sendV1Response=e=>{let n=[["Date",new Date().toUTCString()],["Apigw-Requestid",Buffer.from(Qe()).toString("base64").slice(0,16)],t.keepAlive],r=200;if(!e||isNaN(e.statusCode))throw b.RED(`Valid 'http' response payload must be an object which includes a valid 'statusCode'.
|
|
10
10
|
Received:`),console.log(e),new Error;r=e.statusCode,e.headers&&typeof e.headers=="object"&&!Array.isArray(e.headers)&&Object.entries(e.headers).forEach(([c,l])=>{let m=t.normalizeHeaderKey(c),f=this.#e(l);n.push([m,f])}),e.multiValueHeaders&&typeof e.multiValueHeaders=="object"&&!Array.isArray(e.multiValueHeaders)&&Object.entries(e.multiValueHeaders).forEach(([c,l])=>{let m=t.normalizeHeaderKey(c);if(!Array.isArray(l))throw new Error;l.map(p=>this.#e(p)).forEach(p=>{n.push([m,p])})});let s=e.body;if(e.isBase64Encoded&&s){if(typeof s!="string")throw new Error;let c=Buffer.from(s,"base64").toString();if(Buffer.from(c).toString("base64")!=s)throw b.RED("response body is not properly base64 encoded"),new Error;s=c}n.findIndex(c=>c[0].toLowerCase()=="content-type")==-1&&n.push(["Content-Type",t.contentType.json]);let o=n.findIndex(c=>c[0].toLowerCase()=="content-length");o!=-1&&n.splice(o,1);let a=typeof s;a=="number"||a=="boolean"?s=String(s):s&&a!="string"&&b.YELLOW("API Gateway payload v1 return body must be typeof string, number or boolean ");let d=r==204?"0":s?String(Buffer.from(s).byteLength):"0";n.push(["Content-Length",d]),this.res.shouldKeepAlive=!1,this.res.writeHead(r,n),this.res.end(s)};sendV2Response=e=>{this.res.setHeader("Apigw-Requestid",Buffer.from(Qe()).toString("base64").slice(0,16)),this.res.setHeader("Date",new Date().toUTCString()),e?(typeof e.headers=="object"&&!Array.isArray(e.headers)&&Object.keys(e.headers).filter(s=>s!=="Apigw-Requestid"&&s!=="Date").forEach(s=>{this.res.setHeader(s,e.headers[s])}),e.statusCode?(this.res.statusCode=e.statusCode,e.cookies?.length&&this.res.setHeader("Set-Cookie",e.cookies)):this.res.statusCode=200):this.res.statusCode=200;let n="";if(!e)return this.res.end();if(typeof e=="object"&&typeof e.body=="string"&&(n=e.body,e.isBase64Encoded)){let r=Buffer.from(n,"base64").toString();if(Buffer.from(r).toString("base64")!=n)throw b.RED("response body is not properly base64 encoded"),new Error;n=r}typeof e=="string"?(this.res.setHeader("Content-Type",t.contentType.json),n=e):typeof e=="object"&&!e.statusCode&&(this.res.setHeader("Content-Type",t.contentType.json),n=JSON.stringify(e)),this.res.end(n)};sendResponse=e=>{if(!this.res.writableFinished)return this.mockEvent.version==1?this.sendV1Response(e):this.sendV2Response(e)}};var ln=(t,e)=>{let n=e.url.stream?t:void 0;if(n){let r=!1,s=t.write.bind(t),i=t.setHeader.bind(t),o,a,d=m=>{a=a?Buffer.concat([a,m]):m},c=()=>{if(a){let m=Pe(a),f=m.statusCode??200;try{let p=le(m.headers,m.cookies);t.writeHead(f,p)}catch(p){t.writeHead(500,p.headers),t.end?.(v.amzMsgNull),delete p.headers}}else t.writeHead(200)};n.setHeader=(m,f)=>{if(m.toLowerCase()=="content-type"){if(f=="application/vnd.awslambda.http-integration-response")return r=!0,i("Content-Type",v.contentType.json);o=f}return i(m,f)};let l=!1;return n.write=(m,f,p)=>{if(n.headersSent)return s(m,f,p);if(l)try{let y=A.codec.decode(m),h=JSON.parse(y);if(Array.isArray(h))throw new Error("Invalid stream response");return h&&typeof h=="object"?(c(),s(m,f,p)):(t.writeHead(200,{"Content-Type":v.contentType.octet}),t.end())}catch(y){let h=new Error(`When using HttpResponseStream first chunk of .write() must be valid JSON and not be Array. Number and null will respones with 200.
|
|
11
11
|
'${e.name}'`);return h.cause=y.message,console.error(h),G(t)}else if(r)Le(m)?l=!0:d(m);else{if(o==v.contentType.json)try{let h=A.codec.decode(m),g=JSON.parse(h);if(g===null||typeof g=="number")throw new Error(h)}catch(h){let g=new Error(`When 'Content-Type' is 'application/json' first chunk of .write() must be parsable JSON and not be null or number.
|
|
12
12
|
'${e.name}'`);return g.cause=h.message,console.error(g),G(t)}let y={"Content-Type":o??v.contentType.octet};return n.writeHead(200,y),s(m,f,p)}},n}},pn=(t,e,n)=>{let r=B(t),s=r?t.getParsedResponse():t,i,o=!1;if(s&&typeof s=="object"&&s.statusCode){let a=isNaN(s.statusCode),d=a?500:s.statusCode;if(o=!a&&(s.isBase64Encoded==!0||s.isBase64Encoded=="true"),s.headers||s.cookies)try{let c=le(s.headers,s.cookies);e.writeHead(d,c)}catch(c){return e.writeHead(500,c.headers),delete c.headers,console.error(c),e.end(v.amzMsgNull)}else e.writeHead(d,{"Content-Type":v.contentType.json});n?i=s:(typeof s.body<"u"&&(i=s.body),e.headersSent||e.setHeader("Content-Type",r?v.contentType.octet:v.contentType.json))}else e.writeHead(200,{"Content-Type":v.contentType.json}),i=s;!e.headersSent&&!n&&r&&e.setHeader("Content-Type",v.contentType.octet),n?i instanceof Uint8Array?e.end(i):e.end(JSON.stringify(i)):((typeof i=="number"||typeof i=="boolean"||i==null||i instanceof Object)&&(i=JSON.stringify(i)),i&&o&&(i=Buffer.from(i,"base64")),e.end(i))},Ke=t=>({filter:/^\/@url\//,callback:async(e,n)=>{let{url:r,method:s,headers:i}=e;if(ke(n,s))return;let o=new URL(r,v.dummyHost),a=j(n),d=k.parseNameFromUrl(o.pathname),c=t.handlers.find(h=>h.name==d);if(!c?.url)return n.statusCode=404,n.end("Not Found");let l=v.getIsBase64Encoded(i),m=await O(e,l),f=oe.createApgV2Event({req:e,mockEvent:c.url,parsedURL:o,requestId:a,body:m,isBase64Encoded:l}),p=`/@url/${c.name}`,y=o.pathname.slice(p.length);y||(y="/"),f.requestContext.accountId="anonymous",f.rawPath=y,f.requestContext.http.path=y;try{let h=ln(n,c),g=await c.invoke(f,c.url,void 0,h);if(!g)return n.end();pn(g,n,h)}catch(h){console.error(h),G(n)}}});var Ge=t=>({filter:/(^\/2015-03-31\/functions\/.*\/invocations)|(^\/@invoke\/)/,callback:async(e,n)=>{let{url:r,headers:s}=e,i=new URL(r,"http://localhost:3003"),o=k.parseNameFromUrl(i.pathname),a=t.handlers.find(g=>g.name==o),d=j(n);if(n.setHeader("Content-Type","application/json"),e.on("error",g=>{n.statusCode=502,n.end(JSON.stringify(g))}),!a){let{region:g,accountId:x}=t.aws;return n.statusCode=404,n.setHeader("x-amzn-errortype","ResourceNotFoundException"),n.end(K(o,g,x))}let c=s["x-amz-invocation-type"],l=C(s["x-amz-client-context"]);if(l instanceof Error)return n.setHeader("x-amzn-errortype","InvalidRequestContentException"),n.statusCode=400,n.end(Q);let m=c=="DryRun"?204:c=="Event"?202:200,f=await O(e),p=V(f);if(n.setHeader("X-Amzn-Trace-Id","root=1-xxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx;sampled=0"),p instanceof Error)return n.statusCode=400,n.setHeader("x-amzn-errortype","InvalidRequestContentException"),n.end(J(p.message));n.setHeader("X-Amz-Executed-Version","$LATEST");let y=new Date,h={};n.statusCode=m,m!==200&&n.end(),m==202&&(h.kind="async");try{let g=await a.invoke(p,h,l);if(m==200){if(typeof g>"u"){n.end();return}let x=B(g),u=x?g.buffer:g;x?u=A.codec.decode(u):typeof u!="string"&&(u=JSON.stringify(u)),n.end(u)}}catch(g){n.writableFinished||(n.setHeader("X-Amz-Function-Error",g.errorType??g.message??""),n.statusCode=200,n.end(JSON.stringify(g)))}}});import{randomUUID as Ye}from"node:crypto";import{setTimeout as un}from"node:timers/promises";var Xe=t=>({filter:"/2015-03-31/functions",method:"POST",async callback(e,n){let r=await O(e),s=JSON.parse(r),{FunctionName:i,Handler:o,Environment:a,Runtime:d,Timeout:c,MemorySize:l}=s;t.addLambda(i,{handler:o,environment:a?.Variables,runtime:d,timeout:c,memorySize:l}),t.isDynamicBuild=!0,t.setEsBuildConfig(),await t.buildContext.dispose(),await t.buildAndWatch(),await un(100),n.statusCode=201,n.end(r)}}),Ze=t=>({filter:/\/2015-03-31\/functions\/*/,method:"GET",async callback(e,n){let{url:r}=e,i=new URL(r,"http://localhost:3003").pathname.slice(22),o=t.getLambdaByName(i);if(!o){n.statusCode=404,n.end();return}let a={Code:{RepositoryType:"S3",Location:"https://s3.com/snapshots/1234543"},Tags:{},Configuration:{Architectures:["arm64"],CodeSha256:"WrLckXVmmfsSPvP/15FqPi9Nt9qQBaspP6RV3T137K4=",SigningJobArn:"",FunctionArn:`arn:aws:lambda:${t.aws.region}:${t.aws.accountId}:function:${i}`,FunctionName:i,Handler:o.handlerPath,Timeout:o.timeout,Runtime:o.runtime,MemorySize:o.memorySize,Environment:{Variables:et(o.environment)},State:"Active",LastUpdateStatus:"Successful",LastModified:new Date().toISOString(),Version:"$LATEST",Role:`arn:aws:iam::${t.aws.accountId}:role/fake-role-name`,RevisionId:Ye(),PackageType:"Zip",Description:"",EphemeralStorage:{Size:512},TracingConfig:{Mode:"PassThrough"},VpcConfig:{Ipv6AllowedForDualStack:!1,VpcId:"",SecurityGroupIds:[],SubnetIds:[]},CodeSize:5867,SnapStart:{OptimizationStatus:"Off",ApplyOn:"None"},LoggingConfig:{LogFormat:"Text",LogGroup:`/aws/lambda/${i}`}}};n.end(JSON.stringify(a))}}),fn=["AWS_EXECUTION_ENV","AWS_LAMBDA_FUNCTION_VERSION","AWS_LAMBDA_FUNCTION_NAME","_HANDLER","IS_OFFLINE","IS_LOCAL","AWS_SAM_LOCAL","AWS_LAMBDA_FUNCTION_MEMORY_SIZE"];function et(t){let e={};for(let[n,r]of Object.entries(t))fn.includes(n)||(e[n]=String(r));return e}var tt=t=>({method:"GET",filter:/\/2015-03-31\/functions\/.*\/versions/,async callback(e,n){let{url:r}=e,i=new URL(r,"http://localhost:3003").pathname.slice(22);i=i.slice(0,i.indexOf("/"));let o=t.getLambdaByName(i);if(!o){n.statusCode=404,n.end();return}let a={Versions:[{Architectures:["arm64"],CodeSha256:"WrLckXVmmfsSPvP/15FqPi9Nt9qQBaspP6RV3T137K4=",SigningJobArn:"",FunctionArn:`arn:aws:lambda:${t.aws.region}:${t.aws.accountId}:function:${i}`,FunctionName:i,Handler:o.handlerPath,Timeout:o.timeout,Runtime:o.runtime,MemorySize:o.memorySize,Environment:{Variables:et(o.environment)},State:"Active",LastUpdateStatus:"Successful",LastModified:new Date().toISOString(),Version:"$LATEST",Role:`arn:aws:iam::${t.aws.accountId}:role/fake-role-name`,RevisionId:Ye(),PackageType:"Zip",Description:"",EphemeralStorage:{Size:512},TracingConfig:{Mode:"PassThrough"},VpcConfig:{Ipv6AllowedForDualStack:!1,VpcId:"",SecurityGroupIds:[],SubnetIds:[]},CodeSize:5867,SnapStart:{OptimizationStatus:"Off",ApplyOn:"None"},LoggingConfig:{LogFormat:"Text",LogGroup:`/aws/lambda/${i}`}}]};n.end(JSON.stringify(a))}}),nt=t=>({method:"GET",filter:/\/2020-06-30\/functions\/.*\/code-signing-config/,async callback(e,n){let{url:r}=e,i=new URL(r,"http://localhost:3003").pathname.slice(22);if(i=i.slice(0,i.indexOf("/")),!t.getLambdaByName(i)){n.statusCode=404,n.end();return}let a={CodeSigningConfigArn:"",FunctionName:i};n.end(JSON.stringify(a))}});import{EventStreamCodec as hn}from"@smithy/eventstream-codec";var yn=(t,e)=>{let n=Buffer.from(t,e);return new Uint8Array(n.buffer,n.byteOffset,n.byteLength/Uint8Array.BYTES_PER_ELEMENT)},gn=t=>Buffer.from(t,t.byteOffset,t.byteLength).toString("utf8"),pe=new hn(gn,yn),ae=class t{res;static complete=Buffer.from([0,0,0,102,0,0,0,84,31,86,200,105,11,58,101,118,101,110,116,45,116,121,112,101,7,0,14,73,110,118,111,107,101,67,111,109,112,108,101,116,101,13,58,99,111,110,116,101,110,116,45,116,121,112,101,7,0,16,97,112,112,108,105,99,97,116,105,111,110,47,106,115,111,110,13,58,109,101,115,115,97,103,101,45,116,121,112,101,7,0,5,101,118,101,110,116,123,125,112,6,212,103]);constructor(e){this.res=e}write(e,n,r){this.res.write(pe.encode({headers:this.#e("PayloadChunk",v.contentType.octet),body:e}),n,r)}end(e){e?this.write(e,"utf8",()=>{this.res.end(t.complete)}):this.res.end(t.complete)}setHeader(e,n){e=="Content-Type"&&this.res.setHeader("Content-Type",n)}destroy(){this.res.destroy()}endWithError(e){let n={ErrorCode:e.errorType,ErrorDetails:JSON.stringify(e)},r=Array.from(Buffer.from(JSON.stringify(n)).values());this.res.end(pe.encode({headers:this.#e("InvokeComplete",v.contentType.json),body:new Uint8Array(r)}))}endWithJson(e){let n=Array.from(Buffer.from(JSON.stringify(e)).values());this.res.write(pe.encode({headers:this.#e("PayloadChunk",v.contentType.octet),body:new Uint8Array(n)}),()=>{this.res.end(t.complete)})}#e(e,n,r="event"){return{":event-type":{type:"string",value:e},":content-type":{type:"string",value:n},":message-type":{type:"string",value:r}}}};var rt=t=>({filter:/^\/2021-11-15\/functions\//,callback:async(e,n)=>{let{url:r,headers:s}=e,i=new URL(r,"http://localhost:3003"),o=j(n),a=k.parseNameFromUrl(i.pathname),d=t.handlers.find(p=>p.name==a),c=await O(e),l=V(c);if(n.setHeader("X-Amzn-Trace-Id","root=1-xxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx;sampled=0"),l instanceof Error)return n.statusCode=400,n.setHeader("x-amzn-errortype","InvalidRequestContentException"),n.end(J(l.message));let m=C(s["x-amz-client-context"]);if(m instanceof Error)return n.setHeader("x-amzn-errortype","InvalidRequestContentException"),n.statusCode=400,n.end(Q);let f=new ae(n);if(d){let p=d.url?.stream??{};try{let y=await d.invoke(l,p,m,f);y&&f.endWithJson(y)}catch(y){n.writableFinished||f.endWithError(y)}}else{let{region:p,accountId:y}=t.aws;n.statusCode=404,n.end(K(a,p,y))}}});var st=t=>[Xe(t),tt(t),nt(t),Ge(t),rt(t),Ke(t),Ze(t)];var me=process.cwd(),Sn=3,vn=1024,xn={IS_OFFLINE:!0,IS_LOCAL:!0,AWS_SAM_LOCAL:!0},wn=me.split(L.sep)[0],Rn=new RegExp(`^.*:${wn}`),En=t=>Rn.test(t);process.title="node (exlo)";var ce=class extends ie{#e;options;config;esBuildConfig;buildContext={};customEsBuildConfig;optimizeBuild=!1;nodeVersion=!1;onKill=[];shimRequire=!1;port=0;onceServerReady=[];isDynamicBuild=!1;endpoints={};setLambdaEndpointEnvVar=!0;constructor(e,n){super(e,{debug:typeof n.debug=="boolean"?n.debug:!1}),this.#e=[],this.options=n,this.options.customEsBuildConfig&&(this.customEsBuildConfig=this.options.customEsBuildConfig),typeof this.options.config?.server?.setEndpointEnvVar=="boolean"&&(this.setLambdaEndpointEnvVar=this.options.config.server.setEndpointEnvVar),this.options.config&&(typeof this.options.config=="string"||typeof this.options.config=="object"&&!Array.isArray(this.options.config))&&(this.config=this.options.config),typeof this.options.optimizeBuild=="boolean"&&(this.optimizeBuild=this.options.optimizeBuild),typeof this.options.shimRequire=="boolean"&&(this.shimRequire=this.options.shimRequire),this.aws.runtime?.startsWith("node")?this.nodeVersion=this.aws.runtime?.replace(/[^0-9]/g,""):this.nodeVersion="20",b.BR_BLUE("Starting exlo...")}async start(){this.#s(),this.#e=this.#r(),await this.#o(),this.setEsBuildConfig(),await this.buildAndWatch()}setEsBuildConfig(){let n={sourcemap:!0,minify:!1,entryPoints:this.#e.filter(r=>r.runtime.startsWith("n")).map(r=>r.esEntryPoint),outdir:L.join(me,".exlo","build"),metafile:!0,bundle:!0,platform:"node",target:"node20",format:"cjs",outbase:"src",plugins:[],external:["esbuild"],dropLabels:[]};if(typeof process.env.NODE_ENV=="string"&&(n.define={"process.env.NODE_ENV":`"${process.env.NODE_ENV}"`}),typeof this.nodeVersion=="string"&&!isNaN(Number(this.nodeVersion))){Number(process.versions.node.slice(0,2))<Number(this.nodeVersion)&&b.RED(`You are running on NodeJS ${process.version} which is lower than defined '${this.nodeVersion}'.`),n.target=`node${this.nodeVersion}`;let r=()=>this.sco;n.plugins?.push(ge({nodeVersion:Number(this.nodeVersion),shimRequire:this.shimRequire,optimizeBuild:this.optimizeBuild,buildCallback:this.buildCallback,getSockets:r}))}this.customEsBuildConfig&&(n=be(n,this.customEsBuildConfig)),this.esBuildConfig=n}async buildAndWatch(){this.buildContext=await it.context(this.esBuildConfig),await this.buildContext.watch()}buildCallback=async(e,n)=>{if(n||this.isDynamicBuild)await this.#t(e);else{let{outputs:r}=e.metafile;if(this.#i(r),this.customBuildCallback)try{await this.customBuildCallback(e,!1)}catch(o){console.log(o)}this.#a();let s=this,i=await new Promise(o=>{this.listen(this.port,async(a,d)=>{let c=`http://localhost:${a}`;b.PINK(`Lambda endpoint: ${c}`),this.endpoints.lambda=c,this.setLambdaEndpointEnvVar&&(this.runtimeConfig.environment.AWS_ENDPOINT_URL_LAMBDA=c),await s.load(s.#e);for(let l of s.#e)l.setEnv("LOCAL_PORT",a),l.setEnv("AWS_LAMBDA_RUNTIME_API",`127.0.0.1:${a}`),this.setLambdaEndpointEnvVar&&l.setEnv("AWS_ENDPOINT_URL_LAMBDA",c);o({url:c,port:a})})});this.onceServerReady.forEach(o=>{o(i)})}};async#t(e){if(e?.errors?.length)b.RED("Build failed:"),console.error(e.errors);else{this.#i(e.metafile.outputs);try{await this.load(this.#e),this.customBuildCallback&&await this.customBuildCallback(e,!0)}catch(n){console.error(n)}console.log(`\x1B[32m${new Date().toLocaleString()} \u{1F504}\u2705 Rebuild\x1B[0m`)}}#n(e){let n=this.aws,r=n.runtime,s=this.runtimeConfig.environment.AWS_REGION??this.runtimeConfig.environment.REGION,o=n.functions[e],a=o.handler,d=L.extname(a),c=d.slice(1),l=L.resolve(a.replace(d,"")),m=n.getFunction(e),f=m.runtime??r,p={name:e,runtime:m.runtime??r,handlerPath:a,handlerName:c,esEntryPoint:l,memorySize:o.memorySize??this.runtimeConfig.memorySize??vn,timeout:o.timeout??this.runtimeConfig.timeout??Sn,sqs:[],ddb:[],environment:{AWS_EXECUTION_ENV:`AWS_Lambda_${f}`,AWS_LAMBDA_FUNCTION_VERSION:"$LATEST",AWS_LAMBDA_FUNCTION_NAME:e,_HANDLER:L.basename(a),...this.runtimeConfig.environment,...o.environment,...xn},invoke:async(y,h)=>{let g=this.getHandlerByName(`/@invoke/${e}`);if(g)return await g.invoke(y,h);b.RED(`'${e}' is not mounted yet.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "exlo",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"description": "A modular toolkit to emulate cloud services locally using high-quality built-in plugins and custom extensions. Includes support for Lambda, S3, SNS, SQS, Secrets Manager, DynamoDB, REST API Gateway and more.",
|
|
5
5
|
"author": "Inqnuam",
|
|
6
6
|
"license": "MIT",
|
|
@@ -82,8 +82,8 @@
|
|
|
82
82
|
"exlo": "dist/cli/index.mjs"
|
|
83
83
|
},
|
|
84
84
|
"dependencies": {
|
|
85
|
-
"@aws-sdk/client-sns": "^3.
|
|
86
|
-
"@aws-sdk/client-sqs": "^3.
|
|
85
|
+
"@aws-sdk/client-sns": "^3.936.0",
|
|
86
|
+
"@aws-sdk/client-sqs": "^3.936.0",
|
|
87
87
|
"@smithy/eventstream-codec": "^4.2.5",
|
|
88
88
|
"ajv": "^8.17.1",
|
|
89
89
|
"ajv-formats": "^3.0.1",
|
|
@@ -93,18 +93,18 @@
|
|
|
93
93
|
"local-aws-sqs": "^2.0.1"
|
|
94
94
|
},
|
|
95
95
|
"devDependencies": {
|
|
96
|
-
"@aws-sdk/client-dynamodb": "^3.
|
|
97
|
-
"@aws-sdk/client-dynamodb-streams": "^3.
|
|
98
|
-
"@aws-sdk/client-lambda": "^3.
|
|
99
|
-
"@aws-sdk/client-s3": "^3.
|
|
100
|
-
"@aws-sdk/client-secrets-manager": "^3.
|
|
101
|
-
"@biomejs/biome": "^2.3.
|
|
96
|
+
"@aws-sdk/client-dynamodb": "^3.936.0",
|
|
97
|
+
"@aws-sdk/client-dynamodb-streams": "^3.936.0",
|
|
98
|
+
"@aws-sdk/client-lambda": "^3.936.0",
|
|
99
|
+
"@aws-sdk/client-s3": "^3.936.0",
|
|
100
|
+
"@aws-sdk/client-secrets-manager": "^3.936.0",
|
|
101
|
+
"@biomejs/biome": "^2.3.6",
|
|
102
102
|
"@types/node": "^22.13.1",
|
|
103
|
-
"@vitest/coverage-istanbul": "^4.0.
|
|
104
|
-
"@vitest/coverage-v8": "^4.0.
|
|
103
|
+
"@vitest/coverage-istanbul": "^4.0.10",
|
|
104
|
+
"@vitest/coverage-v8": "^4.0.10",
|
|
105
105
|
"monocart-coverage-reports": "^2.12.9",
|
|
106
106
|
"typescript": "^5.9.3",
|
|
107
|
-
"vitest": "^4.0.
|
|
107
|
+
"vitest": "^4.0.10"
|
|
108
108
|
},
|
|
109
109
|
"keywords": [
|
|
110
110
|
"aws",
|