exlo 0.0.18 → 0.0.19
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/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";var j="exlo",b="0.0.
|
|
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.19";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+=`
|
package/dist/defineConfig.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var h="0.0.
|
|
1
|
+
var h="0.0.19";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:p,esbuild:v,getServices:y,setService:d,addLambda:g,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))g(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:p,esbuild:v,options:e,config:r,getServices:y,setService:d,addLambda:g,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{parentPort as H,workerData as b}from"node:worker_threads";import{DynamoDB as Q}from"@aws-sdk/client-dynamodb";import D,{createServer as W}from"node:http";import{isDeepStrictEqual as w}from"node:util";import{EventSourceMapping as he}from"exlo/internal/esm";import{EventSourceMapping as ae}from"exlo/internal/esm";var g=u=>Object.prototype.toString.call(u)=="[object Object]";import{randomUUID as U}from"node:crypto";var A=new TextEncoder;function O(u){if(!u)return 0;let t=0,e={};for(let a in u){if(!u.hasOwnProperty(a))continue;let n={sizeOfName:A.encode(a).length,attributeSize:_(u[a])};n.total=n.sizeOfName+n.attributeSize,t+=n.total,e[a]=n}return t}function _(u){if(!u)return 0;if(u.hasOwnProperty("B"))return atob(u.B).length;if(u.hasOwnProperty("S"))return A.encode(u.S).length;if(u.hasOwnProperty("N"))return C(u.N);if(u.hasOwnProperty("BS")){let t=0;for(let e=0;e<u.BS.length;e++)t+=atob(u.BS[e]).length;return t}if(u.hasOwnProperty("SS")){let t=0;for(let e=0;e<u.SS.length;e++)t+=A.encode(u.SS[e]).length;return t}if(u.hasOwnProperty("NS")){let t=0;for(let e=0;e<u.NS.length;e++)t+=C(u.NS[e]);return t}if(u.hasOwnProperty("BOOL")||u.hasOwnProperty("NULL"))return 1;if(u.hasOwnProperty("M")){let t=3;for(let e in u.M)u.M.hasOwnProperty(e)&&(t+=A.encode(e).length,t+=_(u.M[e]),t+=1);return t}if(u.hasOwnProperty("L")){let t=3;for(let e=0;e<u.L.length;e++)t+=_(u.L[e]),t+=1;return t}throw`unknown data type in ${JSON.stringify(u)}`}var x=class{value=0;rawValue;constructor(t){this.rawValue=t,this.value=Number(t)}toFixed(){return this.rawValue.split(".")[0]}};function C(u){let t=new x(u);if(t.value==0)return 1;let e=t.toFixed(),a=q(e.replace("-",""))+1;return e.startsWith("-")&&a++,a>21&&(a=21),a}function q(u){if(u.indexOf(".")!==-1){let t=u.split("."),e=t[0],a=t[1];return e==="0"&&(e="",a=V(a,!0)),e.length%2!==0&&(e=`Z${e}`),a.length%2!==0&&(a=`${a}Z`),q(e+a)}return u=V(u,!0,!0),Math.ceil(u.length/2)}function V(u,t,e){for(;t;){let a=u.replace(/^(0{2})/,"");if(a.length==u.length)break;u=a}for(;e;){let a=u.replace(/(0{2})$/,"");if(a.length==u.length)break;u=a}return u}var R=class{#e;constructor(t=new Date){this.#e=t}getRawValue(){return this.#e}eq(t){return this.#e==t.getRawValue()}gt(t){return this.#e>t.getRawValue()}gte(t){return this.#e>=t.getRawValue()}lt(t){return this.#e<t.getRawValue()}lte(t){return this.#e<=t.getRawValue()}toISOString(){return this.#e.toISOString()}getTime(){return this.#e.getTime()}toJSON(){return this.#e.getTime()/1e3}};var T=class u{static create(){return new u(BigInt("100000000000000000000000"))}static createFromString(t){return new u(BigInt(t))}#e;constructor(t){this.#e=t}getRawValue(){return this.#e}plusplus(){this.#e++}dup(){return new u(this.#e)}eq(t){return this.#e==t.getRawValue()}gt(t){return this.#e>t.getRawValue()}gte(t){return this.#e>=t.getRawValue()}lt(t){return this.#e<t.getRawValue()}lte(t){return this.#e<=t.getRawValue()}toJSON(){return this.#e.toString()}toString(){return this.#e.toString()}};var v=class u{constructor(t,e,a,n){this.shardId=t;this.iteratorType=e;this.position=a;this.expires=n}static fromString(t){let e=JSON.parse(Buffer.from(t,"base64").toString("utf-8")),{shardId:a,position:n,expires:o,iteratorType:r}=e;return new u(a,r,n,new Date(o))}isExpired(){return new Date>this.expires}toString(){let t=JSON.stringify({shardId:this.shardId,iteratorType:this.iteratorType,position:this.position,expires:this.expires});return Buffer.from(t,"utf-8").toString("base64")}},B=class{ParentShardId;SequenceNumberRange;ShardId;#e=[];#t;constructor(t){this.#t=t,this.ShardId=`shardId-${U()}`,this.SequenceNumberRange={}}getId(){return this.#t}setRecord(t){this.SequenceNumberRange.StartingSequenceNumber||(this.SequenceNumberRange.StartingSequenceNumber=t.dynamodb.SequenceNumber),this.#e.push(t)}get records(){return this.#e}getRecords(t,e=1e3){let a=this.#e.slice(t.position,t.position+e),n=null,o=t.position+a.length;return n=this.getIterator("LATEST"),n.iteratorType=t.iteratorType,n.position=o,this.SequenceNumberRange.EndingSequenceNumber&&!this.#e[o]&&(n=null),{Records:a,nextIterator:n}}getIterator(t,e){let a;if(t=="TRIM_HORIZON")a=0;else if(t=="LATEST")a=this.#e.length;else if(e){let n=this.#e.findIndex(o=>o.dynamodb.SequenceNumber.eq(e));n==-1?a=this.#e.length+1:t=="AT_SEQUENCE_NUMBER"?a=n:a=n+1}else throw new Error("SequenceNumber is requied for this shardIteratorType");return new v(this.ShardId,t,a,new Date)}},E=class{constructor(t,e,a,n,o="123456789012",r="us-east-1"){this.TableName=t;this.#t=n,this.#n=o,this.#a=r;let i=new R,s=i.toISOString();s=s.split("Z")[0],this.#e=T.create(),this.TableArn=`arn:aws:dynamodb:${r}:${o}:table/${t}`,this.StreamDescription={CreationRequestDateTime:i,KeySchema:a,Shards:[],StreamArn:`${this.TableArn}/stream/${s}`,StreamStatus:"ENABLED",StreamViewType:e,StreamLabel:s,TableName:t};for(let c=1;c<=n;c++)this.StreamDescription.Shards.push(new B(c))}StreamDescription;TableArn;#e;#t;#a;#n;get maxShards(){return this.#t}findShardByHashId(t){let e=this.StreamDescription.Shards.find(n=>n.getId()==t);if(e)return e;let a=new B(t);return this.StreamDescription.Shards.push(a),a}setRecord(t,e,a){let n=this.#a,o=U().replaceAll("-",""),r="1.1",i="aws:dynamodb",s;t&&e?s="MODIFY":t?s="INSERT":s="REMOVE";let c=t??e,d={},m={};for(let{AttributeName:M,KeyType:J}of this.StreamDescription.KeySchema)d[M]=c[M],J=="HASH"&&(m=d[M]);this.#e.plusplus();let h=this.#e.dup(),l=["NEW_IMAGE","NEW_AND_OLD_IMAGES"].includes(this.StreamDescription.StreamViewType)?t:void 0,f=["OLD_IMAGE","NEW_AND_OLD_IMAGES"].includes(this.StreamDescription.StreamViewType)?e:void 0,y=O(l)+O(f)+O(d),I={ApproximateCreationDateTime:new R,Keys:d,NewImage:l,OldImage:f,SequenceNumber:h,SizeBytes:y,StreamViewType:this.StreamDescription.StreamViewType},N={awsRegion:n,dynamodb:I,eventID:o,eventName:s,eventSource:i,eventVersion:r};a&&(N.userIdentity={type:"Service",principalId:"dynamodb.amazonaws.com"});let S=m.S??m.N??m.B,p=k(S,this.maxShards);this.findShardByHashId(p).setRecord(N)}getShardById(t){return this.StreamDescription.Shards.find(e=>e.ShardId==t)}};function $(u){let t=0;for(let e=0;e<u.length;e++)t=t*31+u.charCodeAt(e)>>>0;return t}function k(u,t=3){let a=$(u)%t;return a==0?1:a}var L=class u{constructor(t,e=0,a=3,n=!1,o="123456789012",r="us-east-1"){this.client=t;this.proxyPort=e;this.maxShards=a;this.inheritStreamsFromExistingTables=n;this.accountId=o;this.region=r}static async collectBuffer(t){let e=Buffer.alloc(0);return t.on("data",a=>{e=Buffer.concat([e,a])}),new Promise(a=>{t.on("end",async()=>{a(e)})})}static async collectBody(t){return(await this.collectBuffer(t)).toString("utf-8")}static async collectJsonObjectOrReturnError(t,e){try{let a=JSON.parse(await this.collectBody(t));if(!a||Array.isArray(a)||typeof a!="object")throw new Error("Invalid request");return a}catch{e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.validate#ValidationException",Message:"Invalid Request Body"}));return}}redirect(t,e,a){let n=D.request(new URL(t.url,this.dynamoDbLocalEndpoint),{headers:t.headers,method:t.method},o=>{e.writeHead(o.statusCode,o.statusMessage,o.headers),o.pipe(e)});a&&n.write(a)}safeReturnThrownError(t,e,a,n){if(a?.$response?.body){let o=a.$response.body,r={};for(let c of Object.keys(a))c.startsWith("$")||(r[c]=a[c]);let i={};typeof o.headers.server=="string"&&(i.server=o.headers.server),typeof o.headers.date=="string"&&(i.date=o.headers.date),typeof o.headers["x-amzn-requestid"]=="string"&&(i["x-amzn-requestid"]=o.headers["x-amzn-requestid"]),i["content-type"]="application/x-amz-json-1.0";let s=JSON.stringify(r);i["content-length"]=Buffer.from(s).byteLength,e.writeHead(o.statusCode,o.statusMessage,i),e.end(s)}else return this.redirect(t,e,n)}dynamoDbLocalEndpoint="http://localhost:8000";tableSchemas=[];server;streams=[];itemsWithTTL={};getStreamByTableName(t){return this.streams.find(e=>(e.TableName==t||e.TableArn==t)&&e.StreamDescription.StreamStatus=="ENABLED")}getTableKeySchemaAttributeNames(t){let e=this.streams.find(a=>a.TableName==t||a.TableArn==t);return e?e.StreamDescription.KeySchema.map(a=>a.AttributeName):this.tableSchemas.find(a=>a.TableName==t||a.TableArn==t)?.KeySchema.map(a=>a.AttributeName)}getStreamByArn(t){return this.streams.find(e=>e.StreamDescription.StreamArn==t)}trackTTLRecord(t,e){if(!e)return;let a=this.itemsWithTTL[t];if(a)try{let n={};for(let i of a.keySchema)n[i.AttributeName]=e[i.AttributeName];let o=JSON.stringify(n);if(!e[a.ttlFieldName]){a.items.delete(o);return}let r=new Date(Number(e[a.ttlFieldName].N)*1e3);a.items.set(o,{oldImage:e,ttl:r.getTime(),key:n})}catch(n){console.error(n)}}setRecord(t,e,a,n=!1){let o=this.getStreamByTableName(t);if(o&&o.setRecord(e,a,n),!n&&!e&&a){let r=this.itemsWithTTL[t];if(!r)return;let i={};for(let c of r.keySchema)i[c.AttributeName]=a[c.AttributeName];let s=JSON.stringify(i);r.items.delete(s);return}this.trackTTLRecord(t,e)}async getBodyIfJsonObject(t,e){let a=await u.collectBuffer(t),n=a.toString("utf-8"),o;try{if(o=JSON.parse(n),!o||Array.isArray(o)||typeof o!="object")throw new Error("");return{buf:a,rawBody:n,parsedBody:o}}catch{return this.redirect(t,e,a)}}static isValidStreamArn(t){if(!t||typeof t!="string")return!1;let e=t.split("/");if(e.length!=4)return!1;let[a,n,o,r]=e;if(o!="stream"||!new Date(r).getTime())return!1;let i=a.split(":");if(i.length!=6)return!1;let[s,c,d,m,h,l]=i;return!(!(s=="arn"&&d=="dynamodb"&&l=="table")||!["aws","aws-cn","aws-us-gov"].includes(c))}static isValidShardIteratorType(t){return!t||typeof t!="string"?!1:["AFTER_SEQUENCE_NUMBER","LATEST","AT_SEQUENCE_NUMBER","TRIM_HORIZON"].includes(t)}async GetRecords(t,e){let a=await u.collectJsonObjectOrReturnError(t,e);if(!a)return;let{ShardIterator:n,Limit:o}=a,r=typeof n=="string"?n:"",[i,s,c]=r.split("|"),d=this.getStreamByArn(i);if(!d){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.validate#ValidationException",Message:"Invalid ShardIterator"}));return}let m;try{m=v.fromString(c)}catch{e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.validate#ValidationException",Message:"Invalid ShardIterator"}));return}let h=d.getShardById(m.shardId);if(!h){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.validate#ValidationException",Message:"Invalid ShardIterator"}));return}let{Records:l,nextIterator:f}=h.getRecords(m,o?Number(o):void 0),y=null;f&&(y=`${d.StreamDescription.StreamArn}|${h.getId()}|${f.toString()}`),e.end(JSON.stringify({NextShardIterator:y,Records:l}))}async GetShardIterator(t,e){let a=await u.collectJsonObjectOrReturnError(t,e);if(!a)return;let{ShardId:n,ShardIteratorType:o,StreamArn:r,SequenceNumber:i}=a;if(!u.isValidStreamArn(r)){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.validate#ValidationException",Message:"Invalid StreamArn"}));return}let s=this.getStreamByArn(r);if(!s){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazonaws.dynamodb.v20120810#ResourceNotFoundException",message:`Requested resource not found: Stream: ${r} not found`}));return}if(!u.isValidShardIteratorType(o)){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.validate#ValidationException",message:`1 validation error detected: Value '${o}' at 'shardIteratorType' failed to satisfy constraint: Member must satisfy enum value set: [AFTER_SEQUENCE_NUMBER, LATEST, AT_SEQUENCE_NUMBER, TRIM_HORIZON]`}));return}let c=s.getShardById(n);if(!c){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazonaws.dynamodb.v20120810#ResourceNotFoundException",message:"Requested resource not found: Shard does not exist"}));return}if(["AT_SEQUENCE_NUMBER","AFTER_SEQUENCE_NUMBER"].includes(o)){if(!i){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.validate#ValidationException",Message:"One or more parameter values were invalid: SequenceNumber cannot be null"}));return}}else if(i){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.validate#ValidationException",Message:"One or more parameter values were invalid: SequenceNumber should not be passed for this iterator type"}));return}let d;if(typeof i<"u")if(typeof i=="string"){let m;if(i.length<21)m=`1 validation error detected: Value '${i}' at 'sequenceNumber' failed to satisfy constraint: Member must have length greater than or equal to 21`;else try{d=T.createFromString(i)}catch{m="Invalid SequenceNumber for the shard"}if(m){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.validate#ValidationException",Message:m}));return}}else{let m;if(typeof i=="object"&&i?m="Start of structure or map found where not expected":typeof i=="number"?m="NUMBER_VALUE cannot be converted to String":typeof i=="boolean"&&(m=`${String(i).toUpperCase()}_VALUE cannot be converted to String`),m){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.service#SerializationException",Message:m}));return}}if(d){if(!c.SequenceNumberRange.StartingSequenceNumber){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.validate#ValidationException",Message:"Invalid SequenceNumber for the shard"}));return}if(d.lt(c.SequenceNumberRange.StartingSequenceNumber)){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.validate#ValidationException",Message:"Invalid SequenceNumber for the shard"}));return}if(c.SequenceNumberRange.EndingSequenceNumber&&d.gt(T.createFromString(c.SequenceNumberRange.EndingSequenceNumber))){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.validate#ValidationException",Message:"Invalid SequenceNumber for the shard"}));return}}try{let m=c.getIterator(o,d);e.end(JSON.stringify({ShardIterator:`${s.StreamDescription.StreamArn}|${c.getId()}|${m.toString()}`}))}catch(m){console.error(m),e.end()}}async ListStreams(t,e){let a=await u.collectJsonObjectOrReturnError(t,e);if(!a)return;let{ExclusiveStartStreamArn:n,Limit:o,TableName:r}=a,i=o??100,s=r?this.streams.filter(c=>c.TableName==r||c.TableArn==r):this.streams;if(n){let c=s.findIndex(d=>d.StreamDescription.StreamArn==n);c!=-1&&(s=s.slice(c+1,i-1))}e.end(JSON.stringify({Streams:s.map(({TableName:c,StreamDescription:d})=>({StreamArn:d.StreamArn,StreamLabel:d.StreamLabel,TableName:c}))}))}async DescribeStream(t,e){let a=await u.collectJsonObjectOrReturnError(t,e);if(!a)return;let{StreamArn:n,ExclusiveStartShardId:o,Limit:r}=a;if(!u.isValidStreamArn(n)){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.validate#ValidationException",Message:"Invalid StreamArn"}));return}let i=this.streams.find(d=>d.StreamDescription.StreamArn==n);if(!i){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazonaws.dynamodb.v20120810#ResourceNotFoundException",message:`Requested resource not found: Stream: ${n} not found`}));return}let s=r??100,c=i.StreamDescription.Shards;if(o){let d=c.findIndex(m=>m.ShardId==o);d!=-1&&(c=c.slice(d+1,s-1))}e.end(JSON.stringify({StreamDescription:{...i.StreamDescription,Shards:c}}))}async CreateTable(t,e){t.pipe(D.request(new URL(t.url,this.dynamoDbLocalEndpoint),{headers:t.headers,method:t.method},async a=>{if(e.writeHead(a.statusCode,a.statusMessage,a.headers),a.statusCode==200){let n=await u.collectBuffer(a),o=JSON.parse(n.toString("utf-8")),{TableName:r,KeySchema:i,TableArn:s,StreamSpecification:c}=o.TableDescription;c?.StreamEnabled?this.streams.push(new E(r,c.StreamViewType,i,this.maxShards,this.accountId,this.region)):this.tableSchemas.find(d=>d.TableName==r)||this.tableSchemas.push({TableName:r,TableArn:s,KeySchema:i}),e.end(n)}else a.pipe(e)}))}async DeleteTable(t,e){t.pipe(D.request(new URL(t.url,this.dynamoDbLocalEndpoint),{headers:t.headers,method:t.method},async a=>{if(e.writeHead(a.statusCode,a.statusMessage,a.headers),a.statusCode==200){let n=await u.collectBuffer(a),o=JSON.parse(n.toString("utf-8")),{TableName:r}=o.TableDescription,i=this.streams.findIndex(s=>s.TableName==r||s.TableArn==r);i!=-1&&this.streams.splice(i,1),delete this.itemsWithTTL[r],e.end(n)}else a.pipe(e)}))}async UpdateTable(t,e){t.pipe(D.request(new URL(t.url,this.dynamoDbLocalEndpoint),{headers:t.headers,method:t.method},async a=>{if(e.writeHead(a.statusCode,a.statusMessage,a.headers),a.statusCode!=200){a.pipe(e);return}let n=await u.collectBuffer(a),o=JSON.parse(n.toString("utf-8")),{TableName:r,StreamSpecification:i,KeySchema:s}=o.TableDescription;if(i){let c=this.getStreamByTableName(r);typeof i.StreamEnabled=="boolean"?c?c.StreamDescription.StreamStatus=i.StreamEnabled?"ENABLED":"DISABLED":i.StreamEnabled&&this.streams.push(new E(r,i.StreamViewType,s,this.maxShards)):c?c.StreamDescription.StreamViewType=i.StreamViewType:this.streams.push(new E(r,i.StreamViewType,s,this.maxShards))}else{let c=this.streams.find(d=>d.TableName==r||d.TableArn==r);c&&(c.StreamDescription.StreamStatus="DISABLED")}e.end(n)}))}async UpdateTimeToLive(t,e){let a=await this.getBodyIfJsonObject(t,e);if(!a)return;let{buf:n,parsedBody:o}=a;try{let r=await this.client.updateTimeToLive(o);r.$metadata.httpStatusCode&&(e.statusCode=r.$metadata.httpStatusCode),r.$metadata.requestId&&e.setHeader("x-amzn-RequestId",r.$metadata.requestId);let{TableName:i}=o,s=this.streams.find(c=>c.TableName==i||c.TableArn==i);if(s){let{TimeToLiveSpecification:c}=r,{AttributeName:d,Enabled:m}=c,h=m,l=d;this.itemsWithTTL[i]??={items:new Map,ttlFieldName:l,enabled:h,keySchema:s.StreamDescription.KeySchema},this.itemsWithTTL[i].enabled=h,this.itemsWithTTL[i].ttlFieldName=l}e.end(JSON.stringify(r))}catch(r){this.safeReturnThrownError(t,e,r,n)}}async PutItem(t,e){let a=await this.getBodyIfJsonObject(t,e);if(!a)return;let{buf:n,rawBody:o,parsedBody:r}=a;try{let i=["NONE","ALL_OLD"],s=r.ReturnValues,c="";s?i.includes(s)?c="ALL_OLD":c=s:c="ALL_OLD";let d={...r,ReturnValues:c},m=await this.client.putItem(d);m.$metadata.httpStatusCode&&(e.statusCode=m.$metadata.httpStatusCode),m.$metadata.requestId&&e.setHeader("x-amzn-RequestId",m.$metadata.requestId);let{TableName:h,Item:l}=r,f=l,y=m.Attributes;this.setRecord(h,f,y);let I=JSON.stringify({...m,Attributes:s=="ALL_OLD"?m.Attributes:void 0});e.end(I)}catch(i){this.safeReturnThrownError(t,e,i,n)}}async DeleteItem(t,e){let a=await this.getBodyIfJsonObject(t,e);if(!a)return;let{buf:n,parsedBody:o}=a;try{let r=["NONE","ALL_OLD"],i=o.ReturnValues,s="";i?r.includes(i)?s="ALL_OLD":s=i:s="ALL_OLD";let c={...o,ReturnValues:s},d=await this.client.deleteItem(c);d.$metadata.httpStatusCode&&(e.statusCode=d.$metadata.httpStatusCode),d.$metadata.requestId&&e.setHeader("x-amzn-RequestId",d.$metadata.requestId);let{TableName:m}=o,h=void 0,l=d.Attributes;l&&this.setRecord(m,h,l);let f=JSON.stringify({...d,Attributes:i=="ALL_OLD"?d.Attributes:void 0});e.end(f)}catch(r){this.safeReturnThrownError(t,e,r,n)}}async UpdateItem(t,e){let a=await this.getBodyIfJsonObject(t,e);if(!a)return;let{buf:n,rawBody:o,parsedBody:r}=a;try{let{TableName:i,Key:s}=r,c;try{c=(await this.client.getItem({TableName:i,Key:s,ConsistentRead:!0})).Item}catch{}let d=await this.client.updateItem(r),{Item:m}=await this.client.getItem({TableName:i,Key:s,ConsistentRead:!0});d.$metadata.httpStatusCode&&(e.statusCode=d.$metadata.httpStatusCode),d.$metadata.requestId&&e.setHeader("x-amzn-RequestId",d.$metadata.requestId),this.setRecord(i,m,c);let h=JSON.stringify(d);e.end(h)}catch(i){this.safeReturnThrownError(t,e,i,n)}}async safeBatchGetItems(t){let e={},a=t;do try{let{Responses:n,UnprocessedKeys:o}=await this.client.batchGetItem({RequestItems:a});if(n)for(let[r,i]of Object.entries(n))e[r]?e[r]=e[r].concat(i):e[r]=i;o&&Object.keys(o).length?a=o:a=void 0}catch{a=void 0}while(a);return e}async BatchWriteItem(t,e){let a=await this.getBodyIfJsonObject(t,e);if(!a)return;let{buf:n,parsedBody:o}=a;if(!g(o.RequestItems))return this.redirect(t,e,n);let r={};for(let[s,c]of Object.entries(o.RequestItems)){if(!Array.isArray(c))return this.redirect(t,e,n);let d=this.getTableKeySchemaAttributeNames(s);if(!d)return this.redirect(t,e,n);r[s]={Keys:[],ConsistentRead:!0};for(let m of c){if(!g(m))return this.redirect(t,e,n);if(g(m.DeleteRequest)){if(!g(m.DeleteRequest.Key))return this.redirect(t,e,n);let h={};for(let l of d)h[l]=m.DeleteRequest.Key[l];r[s].Keys.push(h)}else if(g(m.PutRequest)){if(!g(m.PutRequest.Item))return this.redirect(t,e,n);let h={};for(let l of d)h[l]=m.PutRequest.Item[l];r[s].Keys.push(h)}else return this.redirect(t,e,n)}}let i=await this.safeBatchGetItems(r);try{let s=await this.client.batchWriteItem(o),c=await this.safeBatchGetItems(r);for(let[d,m]of Object.entries(r))if(this.getStreamByTableName(d))for(let l of m.Keys){let f=Object.keys(l),y=i[d].find(N=>{let S={};for(let p of f)S[p]=N[p];return w(l,S)}),I=c[d].find(N=>{let S={};for(let p of f)S[p]=N[p];return w(l,S)});(I||y)&&this.setRecord(d,I,y)}s.$metadata.httpStatusCode&&(e.statusCode=s.$metadata.httpStatusCode),s.$metadata.requestId&&e.setHeader("x-amzn-RequestId",s.$metadata.requestId),e.end(JSON.stringify(s))}catch(s){this.safeReturnThrownError(t,e,s,n)}}async TransactWriteItems(t,e){let a=await this.getBodyIfJsonObject(t,e);if(!a)return;let{buf:n,parsedBody:o}=a;if(!Array.isArray(o.TransactItems))return this.redirect(t,e,n);let r={};for(let s of o.TransactItems){if(!g(s))return this.redirect(t,e,n);if(s.Delete){if(!g(s.Delete)||typeof s.Delete.TableName!="string"||!s.Delete.Key)return this.redirect(t,e,n);r[s.Delete.TableName]??={Keys:[],ConsistentRead:!0},r[s.Delete.TableName].Keys.find(d=>w(d,s.Delete.Key))||r[s.Delete.TableName].Keys.push(s.Delete.Key)}else if(s.Update){if(!g(s.Update)||typeof s.Update.TableName!="string"||!s.Update.Key)return this.redirect(t,e,n);r[s.Update.TableName]??={Keys:[],ConsistentRead:!0},r[s.Update.TableName].Keys.find(d=>w(d,s.Update.Key))||r[s.Update.TableName].Keys.push(s.Update.Key)}else if(s.Put){if(!g(s.Put)||typeof s.Put.TableName!="string"||!g(s.Put.Item))return this.redirect(t,e,n);let c=this.getTableKeySchemaAttributeNames(s.Put.TableName);if(!c)return this.redirect(t,e,n);r[s.Put.TableName]??={Keys:[],ConsistentRead:!0};let d={};for(let h of c)d[h]=s.Put.Item[h];r[s.Put.TableName].Keys.find(h=>w(h,d))||r[s.Put.TableName].Keys.push(d)}}let i=await this.safeBatchGetItems(r);try{let s=await this.client.transactWriteItems(o),c=await this.safeBatchGetItems(r);for(let[d,m]of Object.entries(r))if(this.getStreamByTableName(d))for(let l of m.Keys){let f=Object.keys(l),y=i[d].find(N=>{let S={};for(let p of f)S[p]=N[p];return w(l,S)}),I=c[d].find(N=>{let S={};for(let p of f)S[p]=N[p];return w(l,S)});(I||y)&&this.setRecord(d,I,y)}s.$metadata.httpStatusCode&&(e.statusCode=s.$metadata.httpStatusCode),s.$metadata.requestId&&e.setHeader("x-amzn-RequestId",s.$metadata.requestId),e.end(JSON.stringify(s))}catch(s){this.safeReturnThrownError(t,e,s,n)}}async setDynamoDbLocalEndpoint(){try{let t="http://localhost:8000",e=await this.client.config.endpoint?.();e&&(t=`${e.protocol}${e.hostname}`,e.port&&(t+=`:${e.port}`),e.path&&e.path!="/"&&(t+=e.path)),this.dynamoDbLocalEndpoint=t}catch{console.warn("Can not resolve DynamoDB Local endpoint. Using default http://localhost:8000")}}async setupInitialTables(){let t;do{let e={ExclusiveStartTableName:t},{TableNames:a,LastEvaluatedTableName:n}=await this.client.listTables(e);if(!a)return;for(let o of a){let{Table:r}=await this.client.describeTable({TableName:o});if(r?.KeySchema?.every(s=>s.AttributeName&&s.KeyType)){let s=r.KeySchema;if(this.inheritStreamsFromExistingTables&&r.StreamSpecification?.StreamEnabled&&r.StreamSpecification.StreamViewType){let c=new E(o,r.StreamSpecification.StreamViewType,s,this.maxShards);this.streams.push(c)}else{let{TableName:c,TableArn:d}=r;this.tableSchemas.push({TableName:c,TableArn:d,KeySchema:s})}}let{TimeToLiveDescription:i}=await this.client.describeTimeToLive({TableName:o});i?.TimeToLiveStatus=="ENABLED"&&(this.itemsWithTTL[o]={enabled:!0,ttlFieldName:i.AttributeName,keySchema:r.KeySchema,items:new Map})}t=n}while(t)}watchTTL(){setInterval(async()=>{for(let[t,e]of Object.entries(this.itemsWithTTL)){if(!e.enabled)continue;let a=Date.now();for(let[n,o]of e.items.entries())if(!(o.ttl>a))try{(await this.client.getItem({TableName:t,Key:o.key,ConsistentRead:!0})).Item||(e.items.delete(n),this.setRecord(t,void 0,o.oldImage,!0))}catch(r){console.error(r)}}},1e3).unref()}async init(){let t=this;await this.setDynamoDbLocalEndpoint(),await this.setupInitialTables();let e=W(async(a,n)=>{switch(a.headers["x-amz-target"]?.split(".")[1]){case"GetRecords":return t.GetRecords(a,n);case"GetShardIterator":return t.GetShardIterator(a,n);case"ListStreams":return t.ListStreams(a,n);case"DescribeStream":return t.DescribeStream(a,n);case"CreateTable":return t.CreateTable(a,n);case"DeleteTable":return t.DeleteTable(a,n);case"UpdateTable":return t.UpdateTable(a,n);case"PutItem":return t.PutItem(a,n);case"UpdateItem":return t.UpdateItem(a,n);case"DeleteItem":return t.DeleteItem(a,n);case"BatchWriteItem":return t.BatchWriteItem(a,n);case"TransactWriteItems":return t.TransactWriteItems(a,n);case"UpdateTimeToLive":return t.UpdateTimeToLive(a,n);default:a.pipe(D.request(new URL(a.url,this.dynamoDbLocalEndpoint),{headers:a.headers,method:a.method},i=>{n.writeHead(i.statusCode,i.statusMessage,i.headers),i.pipe(n)}))}});return await new Promise(a=>{e.listen(this.proxyPort,()=>{a(void 0)})}),this.server=e,t.watchTTL(),e.address().port}};var K=3,F=!1,P="123456789012",z="us-east-1";b.maxShards&&(typeof b.maxShards=="number"&&b.maxShards>0?K=Math.round(b.maxShards):console.warn("When provided, maxShards must be a positive integer. Using default 3."));typeof b.inheritStreamsFromExistingTables=="boolean"&&(F=b.inheritStreamsFromExistingTables);typeof b.accountId=="string"&&(P=b.accountId);typeof b.region=="string"&&(z=b.region);var G=new Q(b.dynamoDbLocalClientConfig),j=new L(G,b.proxyPort,K,F,P,z),Y=await j.init();H.postMessage({proxyPort:Y});
|
|
1
|
+
import{parentPort as H,workerData as b}from"node:worker_threads";import{DynamoDB as Q}from"@aws-sdk/client-dynamodb";import D,{createServer as W}from"node:http";import{isDeepStrictEqual as w}from"node:util";import{EventSourceMapping as he}from"exlo/internal/esm";import{EventSourceMapping as ae}from"exlo/internal/esm";var g=u=>Object.prototype.toString.call(u)=="[object Object]";import{randomUUID as U}from"node:crypto";var A=new TextEncoder;function O(u){if(!u)return 0;let t=0,e={};for(let a in u){if(!u.hasOwnProperty(a))continue;let n={sizeOfName:A.encode(a).length,attributeSize:_(u[a])};n.total=n.sizeOfName+n.attributeSize,t+=n.total,e[a]=n}return t}function _(u){if(!u)return 0;if(u.hasOwnProperty("B"))return atob(u.B).length;if(u.hasOwnProperty("S"))return A.encode(u.S).length;if(u.hasOwnProperty("N"))return C(u.N);if(u.hasOwnProperty("BS")){let t=0;for(let e=0;e<u.BS.length;e++)t+=atob(u.BS[e]).length;return t}if(u.hasOwnProperty("SS")){let t=0;for(let e=0;e<u.SS.length;e++)t+=A.encode(u.SS[e]).length;return t}if(u.hasOwnProperty("NS")){let t=0;for(let e=0;e<u.NS.length;e++)t+=C(u.NS[e]);return t}if(u.hasOwnProperty("BOOL")||u.hasOwnProperty("NULL"))return 1;if(u.hasOwnProperty("M")){let t=3;for(let e in u.M)u.M.hasOwnProperty(e)&&(t+=A.encode(e).length,t+=_(u.M[e]),t+=1);return t}if(u.hasOwnProperty("L")){let t=3;for(let e=0;e<u.L.length;e++)t+=_(u.L[e]),t+=1;return t}throw`unknown data type in ${JSON.stringify(u)}`}var x=class{value=0;rawValue;constructor(t){this.rawValue=t,this.value=Number(t)}toFixed(){return this.rawValue.split(".")[0]}};function C(u){let t=new x(u);if(t.value==0)return 1;let e=t.toFixed(),a=V(e.replace("-",""))+1;return e.startsWith("-")&&a++,a>21&&(a=21),a}function V(u){if(u.indexOf(".")!==-1){let t=u.split("."),e=t[0],a=t[1];return e==="0"&&(e="",a=q(a,!0)),e.length%2!==0&&(e=`Z${e}`),a.length%2!==0&&(a=`${a}Z`),V(e+a)}return u=q(u,!0,!0),Math.ceil(u.length/2)}function q(u,t,e){for(;t;){let a=u.replace(/^(0{2})/,"");if(a.length==u.length)break;u=a}for(;e;){let a=u.replace(/(0{2})$/,"");if(a.length==u.length)break;u=a}return u}var R=class{#e;constructor(t=new Date){this.#e=t}getRawValue(){return this.#e}eq(t){return this.#e==t.getRawValue()}gt(t){return this.#e>t.getRawValue()}gte(t){return this.#e>=t.getRawValue()}lt(t){return this.#e<t.getRawValue()}lte(t){return this.#e<=t.getRawValue()}toISOString(){return this.#e.toISOString()}getTime(){return this.#e.getTime()}toJSON(){return this.#e.getTime()/1e3}};var T=class u{static create(){return new u(BigInt("100000000000000000000000"))}static createFromString(t){return new u(BigInt(t))}#e;constructor(t){this.#e=t}getRawValue(){return this.#e}plusplus(){this.#e++}dup(){return new u(this.#e)}eq(t){return this.#e==t.getRawValue()}gt(t){return this.#e>t.getRawValue()}gte(t){return this.#e>=t.getRawValue()}lt(t){return this.#e<t.getRawValue()}lte(t){return this.#e<=t.getRawValue()}toJSON(){return this.#e.toString()}toString(){return this.#e.toString()}};var v=class u{constructor(t,e,a,n){this.shardId=t;this.iteratorType=e;this.position=a;this.expires=n}static fromString(t){let e=JSON.parse(Buffer.from(t,"base64").toString("utf-8")),{shardId:a,position:n,expires:o,iteratorType:r}=e;return new u(a,r,n,new Date(o))}isExpired(){return new Date>this.expires}toString(){let t=JSON.stringify({shardId:this.shardId,iteratorType:this.iteratorType,position:this.position,expires:this.expires});return Buffer.from(t,"utf-8").toString("base64")}},B=class{ParentShardId;SequenceNumberRange;ShardId;#e=[];#a=T.create();#t;constructor(t){this.#t=t,this.ShardId=`shardId-${U()}`,this.SequenceNumberRange={StartingSequenceNumber:T.create()}}getId(){return this.#t}setRecord(t){this.SequenceNumberRange.StartingSequenceNumber?.eq(this.#a)&&(this.SequenceNumberRange.StartingSequenceNumber=t.dynamodb.SequenceNumber),this.#e.push(t)}get records(){return this.#e}getRecords(t,e=1e3){let a=this.#e.slice(t.position,t.position+e),n=null,o=t.position+a.length;return n=this.getIterator("LATEST"),n.iteratorType=t.iteratorType,n.position=o,this.SequenceNumberRange.EndingSequenceNumber&&!this.#e[o]&&(n=null),{Records:a,nextIterator:n}}getIterator(t,e){let a;if(t=="TRIM_HORIZON")a=0;else if(t=="LATEST")a=this.#e.length;else if(e){let n=this.#e.findIndex(o=>o.dynamodb.SequenceNumber.eq(e));n==-1?a=this.#e.length+1:t=="AT_SEQUENCE_NUMBER"?a=n:a=n+1}else throw new Error("SequenceNumber is requied for this shardIteratorType");return new v(this.ShardId,t,a,new Date)}},E=class{constructor(t,e,a,n,o="123456789012",r="us-east-1"){this.TableName=t;this.#a=n,this.#n=o,this.#t=r;let i=new R,s=i.toISOString();s=s.split("Z")[0],this.#e=T.create(),this.TableArn=`arn:aws:dynamodb:${r}:${o}:table/${t}`,this.StreamDescription={CreationRequestDateTime:i,KeySchema:a,Shards:[],StreamArn:`${this.TableArn}/stream/${s}`,StreamStatus:"ENABLED",StreamViewType:e,StreamLabel:s,TableName:t};for(let c=1;c<=n;c++)this.StreamDescription.Shards.push(new B(c))}StreamDescription;TableArn;#e;#a;#t;#n;get maxShards(){return this.#a}findShardByHashId(t){let e=this.StreamDescription.Shards.find(n=>n.getId()==t);if(e)return e;let a=new B(t);return this.StreamDescription.Shards.push(a),a}setRecord(t,e,a){let n=this.#t,o=U().replaceAll("-",""),r="1.1",i="aws:dynamodb",s;t&&e?s="MODIFY":t?s="INSERT":s="REMOVE";let c=t??e,d={},m={};for(let{AttributeName:M,KeyType:J}of this.StreamDescription.KeySchema)d[M]=c[M],J=="HASH"&&(m=d[M]);this.#e.plusplus();let h=this.#e.dup(),l=["NEW_IMAGE","NEW_AND_OLD_IMAGES"].includes(this.StreamDescription.StreamViewType)?t:void 0,f=["OLD_IMAGE","NEW_AND_OLD_IMAGES"].includes(this.StreamDescription.StreamViewType)?e:void 0,y=O(l)+O(f)+O(d),I={ApproximateCreationDateTime:new R,Keys:d,NewImage:l,OldImage:f,SequenceNumber:h,SizeBytes:y,StreamViewType:this.StreamDescription.StreamViewType},N={awsRegion:n,dynamodb:I,eventID:o,eventName:s,eventSource:i,eventVersion:r};a&&(N.userIdentity={type:"Service",principalId:"dynamodb.amazonaws.com"});let S=m.S??m.N??m.B,p=k(S,this.maxShards);this.findShardByHashId(p).setRecord(N)}getShardById(t){return this.StreamDescription.Shards.find(e=>e.ShardId==t)}};function $(u){let t=0;for(let e=0;e<u.length;e++)t=t*31+u.charCodeAt(e)>>>0;return t}function k(u,t=3){let a=$(u)%t;return a==0?1:a}var L=class u{constructor(t,e=0,a=3,n=!1,o="123456789012",r="us-east-1"){this.client=t;this.proxyPort=e;this.maxShards=a;this.inheritStreamsFromExistingTables=n;this.accountId=o;this.region=r}static async collectBuffer(t){let e=Buffer.alloc(0);return t.on("data",a=>{e=Buffer.concat([e,a])}),new Promise(a=>{t.on("end",async()=>{a(e)})})}static async collectBody(t){return(await this.collectBuffer(t)).toString("utf-8")}static async collectJsonObjectOrReturnError(t,e){try{let a=JSON.parse(await this.collectBody(t));if(!a||Array.isArray(a)||typeof a!="object")throw new Error("Invalid request");return a}catch{e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.validate#ValidationException",Message:"Invalid Request Body"}));return}}redirect(t,e,a){let n=D.request(new URL(t.url,this.dynamoDbLocalEndpoint),{headers:t.headers,method:t.method},o=>{e.writeHead(o.statusCode,o.statusMessage,o.headers),o.pipe(e)});a&&n.write(a)}safeReturnThrownError(t,e,a,n){if(a?.$response?.body){let o=a.$response.body,r={};for(let c of Object.keys(a))c.startsWith("$")||(r[c]=a[c]);let i={};typeof o.headers.server=="string"&&(i.server=o.headers.server),typeof o.headers.date=="string"&&(i.date=o.headers.date),typeof o.headers["x-amzn-requestid"]=="string"&&(i["x-amzn-requestid"]=o.headers["x-amzn-requestid"]),i["content-type"]="application/x-amz-json-1.0";let s=JSON.stringify(r);i["content-length"]=Buffer.from(s).byteLength,e.writeHead(o.statusCode,o.statusMessage,i),e.end(s)}else return this.redirect(t,e,n)}dynamoDbLocalEndpoint="http://localhost:8000";tableSchemas=[];server;streams=[];itemsWithTTL={};getStreamByTableName(t){return this.streams.find(e=>(e.TableName==t||e.TableArn==t)&&e.StreamDescription.StreamStatus=="ENABLED")}getTableKeySchemaAttributeNames(t){let e=this.streams.find(a=>a.TableName==t||a.TableArn==t);return e?e.StreamDescription.KeySchema.map(a=>a.AttributeName):this.tableSchemas.find(a=>a.TableName==t||a.TableArn==t)?.KeySchema.map(a=>a.AttributeName)}getStreamByArn(t){return this.streams.find(e=>e.StreamDescription.StreamArn==t)}trackTTLRecord(t,e){if(!e)return;let a=this.itemsWithTTL[t];if(a)try{let n={};for(let i of a.keySchema)n[i.AttributeName]=e[i.AttributeName];let o=JSON.stringify(n);if(!e[a.ttlFieldName]){a.items.delete(o);return}let r=new Date(Number(e[a.ttlFieldName].N)*1e3);a.items.set(o,{oldImage:e,ttl:r.getTime(),key:n})}catch(n){console.error(n)}}setRecord(t,e,a,n=!1){let o=this.getStreamByTableName(t);if(o&&o.setRecord(e,a,n),!n&&!e&&a){let r=this.itemsWithTTL[t];if(!r)return;let i={};for(let c of r.keySchema)i[c.AttributeName]=a[c.AttributeName];let s=JSON.stringify(i);r.items.delete(s);return}this.trackTTLRecord(t,e)}async getBodyIfJsonObject(t,e){let a=await u.collectBuffer(t),n=a.toString("utf-8"),o;try{if(o=JSON.parse(n),!o||Array.isArray(o)||typeof o!="object")throw new Error("");return{buf:a,rawBody:n,parsedBody:o}}catch{return this.redirect(t,e,a)}}static isValidStreamArn(t){if(!t||typeof t!="string")return!1;let e=t.split("/");if(e.length!=4)return!1;let[a,n,o,r]=e;if(o!="stream"||!new Date(r).getTime())return!1;let i=a.split(":");if(i.length!=6)return!1;let[s,c,d,m,h,l]=i;return!(!(s=="arn"&&d=="dynamodb"&&l=="table")||!["aws","aws-cn","aws-us-gov"].includes(c))}static isValidShardIteratorType(t){return!t||typeof t!="string"?!1:["AFTER_SEQUENCE_NUMBER","LATEST","AT_SEQUENCE_NUMBER","TRIM_HORIZON"].includes(t)}async GetRecords(t,e){let a=await u.collectJsonObjectOrReturnError(t,e);if(!a)return;let{ShardIterator:n,Limit:o}=a,r=typeof n=="string"?n:"",[i,s,c]=r.split("|"),d=this.getStreamByArn(i);if(!d){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.validate#ValidationException",Message:"Invalid ShardIterator"}));return}let m;try{m=v.fromString(c)}catch{e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.validate#ValidationException",Message:"Invalid ShardIterator"}));return}let h=d.getShardById(m.shardId);if(!h){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.validate#ValidationException",Message:"Invalid ShardIterator"}));return}let{Records:l,nextIterator:f}=h.getRecords(m,o?Number(o):void 0),y=null;f&&(y=`${d.StreamDescription.StreamArn}|${h.getId()}|${f.toString()}`),e.end(JSON.stringify({NextShardIterator:y,Records:l}))}async GetShardIterator(t,e){let a=await u.collectJsonObjectOrReturnError(t,e);if(!a)return;let{ShardId:n,ShardIteratorType:o,StreamArn:r,SequenceNumber:i}=a;if(!u.isValidStreamArn(r)){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.validate#ValidationException",Message:"Invalid StreamArn"}));return}let s=this.getStreamByArn(r);if(!s){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazonaws.dynamodb.v20120810#ResourceNotFoundException",message:`Requested resource not found: Stream: ${r} not found`}));return}if(!u.isValidShardIteratorType(o)){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.validate#ValidationException",message:`1 validation error detected: Value '${o}' at 'shardIteratorType' failed to satisfy constraint: Member must satisfy enum value set: [AFTER_SEQUENCE_NUMBER, LATEST, AT_SEQUENCE_NUMBER, TRIM_HORIZON]`}));return}let c=s.getShardById(n);if(!c){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazonaws.dynamodb.v20120810#ResourceNotFoundException",message:"Requested resource not found: Shard does not exist"}));return}if(["AT_SEQUENCE_NUMBER","AFTER_SEQUENCE_NUMBER"].includes(o)){if(!i){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.validate#ValidationException",Message:"One or more parameter values were invalid: SequenceNumber cannot be null"}));return}}else if(i){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.validate#ValidationException",Message:"One or more parameter values were invalid: SequenceNumber should not be passed for this iterator type"}));return}let d;if(typeof i<"u")if(typeof i=="string"){let m;if(i.length<21)m=`1 validation error detected: Value '${i}' at 'sequenceNumber' failed to satisfy constraint: Member must have length greater than or equal to 21`;else try{d=T.createFromString(i)}catch{m="Invalid SequenceNumber for the shard"}if(m){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.validate#ValidationException",Message:m}));return}}else{let m;if(typeof i=="object"&&i?m="Start of structure or map found where not expected":typeof i=="number"?m="NUMBER_VALUE cannot be converted to String":typeof i=="boolean"&&(m=`${String(i).toUpperCase()}_VALUE cannot be converted to String`),m){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.service#SerializationException",Message:m}));return}}if(d){if(!c.SequenceNumberRange.StartingSequenceNumber){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.validate#ValidationException",Message:"Invalid SequenceNumber for the shard"}));return}if(d.lt(c.SequenceNumberRange.StartingSequenceNumber)){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.validate#ValidationException",Message:"Invalid SequenceNumber for the shard"}));return}if(c.SequenceNumberRange.EndingSequenceNumber&&d.gt(T.createFromString(c.SequenceNumberRange.EndingSequenceNumber))){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.validate#ValidationException",Message:"Invalid SequenceNumber for the shard"}));return}}try{let m=c.getIterator(o,d);e.end(JSON.stringify({ShardIterator:`${s.StreamDescription.StreamArn}|${c.getId()}|${m.toString()}`}))}catch(m){console.error(m),e.end()}}async ListStreams(t,e){let a=await u.collectJsonObjectOrReturnError(t,e);if(!a)return;let{ExclusiveStartStreamArn:n,Limit:o,TableName:r}=a,i=o??100,s=r?this.streams.filter(c=>c.TableName==r||c.TableArn==r):this.streams;if(n){let c=s.findIndex(d=>d.StreamDescription.StreamArn==n);c!=-1&&(s=s.slice(c+1,i-1))}e.end(JSON.stringify({Streams:s.map(({TableName:c,StreamDescription:d})=>({StreamArn:d.StreamArn,StreamLabel:d.StreamLabel,TableName:c}))}))}async DescribeStream(t,e){let a=await u.collectJsonObjectOrReturnError(t,e);if(!a)return;let{StreamArn:n,ExclusiveStartShardId:o,Limit:r}=a;if(!u.isValidStreamArn(n)){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazon.coral.validate#ValidationException",Message:"Invalid StreamArn"}));return}let i=this.streams.find(d=>d.StreamDescription.StreamArn==n);if(!i){e.statusCode=400,e.end(JSON.stringify({__type:"com.amazonaws.dynamodb.v20120810#ResourceNotFoundException",message:`Requested resource not found: Stream: ${n} not found`}));return}let s=r??100,c=i.StreamDescription.Shards;if(o){let d=c.findIndex(m=>m.ShardId==o);d!=-1&&(c=c.slice(d+1,s-1))}e.end(JSON.stringify({StreamDescription:{...i.StreamDescription,Shards:c}}))}async CreateTable(t,e){t.pipe(D.request(new URL(t.url,this.dynamoDbLocalEndpoint),{headers:t.headers,method:t.method},async a=>{if(e.writeHead(a.statusCode,a.statusMessage,a.headers),a.statusCode==200){let n=await u.collectBuffer(a),o=JSON.parse(n.toString("utf-8")),{TableName:r,KeySchema:i,TableArn:s,StreamSpecification:c}=o.TableDescription;c?.StreamEnabled?this.streams.push(new E(r,c.StreamViewType,i,this.maxShards,this.accountId,this.region)):this.tableSchemas.find(d=>d.TableName==r)||this.tableSchemas.push({TableName:r,TableArn:s,KeySchema:i}),e.end(n)}else a.pipe(e)}))}async DeleteTable(t,e){t.pipe(D.request(new URL(t.url,this.dynamoDbLocalEndpoint),{headers:t.headers,method:t.method},async a=>{if(e.writeHead(a.statusCode,a.statusMessage,a.headers),a.statusCode==200){let n=await u.collectBuffer(a),o=JSON.parse(n.toString("utf-8")),{TableName:r}=o.TableDescription,i=this.streams.findIndex(s=>s.TableName==r||s.TableArn==r);i!=-1&&this.streams.splice(i,1),delete this.itemsWithTTL[r],e.end(n)}else a.pipe(e)}))}async UpdateTable(t,e){t.pipe(D.request(new URL(t.url,this.dynamoDbLocalEndpoint),{headers:t.headers,method:t.method},async a=>{if(e.writeHead(a.statusCode,a.statusMessage,a.headers),a.statusCode!=200){a.pipe(e);return}let n=await u.collectBuffer(a),o=JSON.parse(n.toString("utf-8")),{TableName:r,StreamSpecification:i,KeySchema:s}=o.TableDescription;if(i){let c=this.getStreamByTableName(r);typeof i.StreamEnabled=="boolean"?c?c.StreamDescription.StreamStatus=i.StreamEnabled?"ENABLED":"DISABLED":i.StreamEnabled&&this.streams.push(new E(r,i.StreamViewType,s,this.maxShards)):c?c.StreamDescription.StreamViewType=i.StreamViewType:this.streams.push(new E(r,i.StreamViewType,s,this.maxShards))}else{let c=this.streams.find(d=>d.TableName==r||d.TableArn==r);c&&(c.StreamDescription.StreamStatus="DISABLED")}e.end(n)}))}async UpdateTimeToLive(t,e){let a=await this.getBodyIfJsonObject(t,e);if(!a)return;let{buf:n,parsedBody:o}=a;try{let r=await this.client.updateTimeToLive(o);r.$metadata.httpStatusCode&&(e.statusCode=r.$metadata.httpStatusCode),r.$metadata.requestId&&e.setHeader("x-amzn-RequestId",r.$metadata.requestId);let{TableName:i}=o,s=this.streams.find(c=>c.TableName==i||c.TableArn==i);if(s){let{TimeToLiveSpecification:c}=r,{AttributeName:d,Enabled:m}=c,h=m,l=d;this.itemsWithTTL[i]??={items:new Map,ttlFieldName:l,enabled:h,keySchema:s.StreamDescription.KeySchema},this.itemsWithTTL[i].enabled=h,this.itemsWithTTL[i].ttlFieldName=l}e.end(JSON.stringify(r))}catch(r){this.safeReturnThrownError(t,e,r,n)}}async PutItem(t,e){let a=await this.getBodyIfJsonObject(t,e);if(!a)return;let{buf:n,rawBody:o,parsedBody:r}=a;try{let i=["NONE","ALL_OLD"],s=r.ReturnValues,c="";s?i.includes(s)?c="ALL_OLD":c=s:c="ALL_OLD";let d={...r,ReturnValues:c},m=await this.client.putItem(d);m.$metadata.httpStatusCode&&(e.statusCode=m.$metadata.httpStatusCode),m.$metadata.requestId&&e.setHeader("x-amzn-RequestId",m.$metadata.requestId);let{TableName:h,Item:l}=r,f=l,y=m.Attributes;this.setRecord(h,f,y);let I=JSON.stringify({...m,Attributes:s=="ALL_OLD"?m.Attributes:void 0});e.end(I)}catch(i){this.safeReturnThrownError(t,e,i,n)}}async DeleteItem(t,e){let a=await this.getBodyIfJsonObject(t,e);if(!a)return;let{buf:n,parsedBody:o}=a;try{let r=["NONE","ALL_OLD"],i=o.ReturnValues,s="";i?r.includes(i)?s="ALL_OLD":s=i:s="ALL_OLD";let c={...o,ReturnValues:s},d=await this.client.deleteItem(c);d.$metadata.httpStatusCode&&(e.statusCode=d.$metadata.httpStatusCode),d.$metadata.requestId&&e.setHeader("x-amzn-RequestId",d.$metadata.requestId);let{TableName:m}=o,h=void 0,l=d.Attributes;l&&this.setRecord(m,h,l);let f=JSON.stringify({...d,Attributes:i=="ALL_OLD"?d.Attributes:void 0});e.end(f)}catch(r){this.safeReturnThrownError(t,e,r,n)}}async UpdateItem(t,e){let a=await this.getBodyIfJsonObject(t,e);if(!a)return;let{buf:n,rawBody:o,parsedBody:r}=a;try{let{TableName:i,Key:s}=r,c;try{c=(await this.client.getItem({TableName:i,Key:s,ConsistentRead:!0})).Item}catch{}let d=await this.client.updateItem(r),{Item:m}=await this.client.getItem({TableName:i,Key:s,ConsistentRead:!0});d.$metadata.httpStatusCode&&(e.statusCode=d.$metadata.httpStatusCode),d.$metadata.requestId&&e.setHeader("x-amzn-RequestId",d.$metadata.requestId),this.setRecord(i,m,c);let h=JSON.stringify(d);e.end(h)}catch(i){this.safeReturnThrownError(t,e,i,n)}}async safeBatchGetItems(t){let e={},a=t;do try{let{Responses:n,UnprocessedKeys:o}=await this.client.batchGetItem({RequestItems:a});if(n)for(let[r,i]of Object.entries(n))e[r]?e[r]=e[r].concat(i):e[r]=i;o&&Object.keys(o).length?a=o:a=void 0}catch{a=void 0}while(a);return e}async BatchWriteItem(t,e){let a=await this.getBodyIfJsonObject(t,e);if(!a)return;let{buf:n,parsedBody:o}=a;if(!g(o.RequestItems))return this.redirect(t,e,n);let r={};for(let[s,c]of Object.entries(o.RequestItems)){if(!Array.isArray(c))return this.redirect(t,e,n);let d=this.getTableKeySchemaAttributeNames(s);if(!d)return this.redirect(t,e,n);r[s]={Keys:[],ConsistentRead:!0};for(let m of c){if(!g(m))return this.redirect(t,e,n);if(g(m.DeleteRequest)){if(!g(m.DeleteRequest.Key))return this.redirect(t,e,n);let h={};for(let l of d)h[l]=m.DeleteRequest.Key[l];r[s].Keys.push(h)}else if(g(m.PutRequest)){if(!g(m.PutRequest.Item))return this.redirect(t,e,n);let h={};for(let l of d)h[l]=m.PutRequest.Item[l];r[s].Keys.push(h)}else return this.redirect(t,e,n)}}let i=await this.safeBatchGetItems(r);try{let s=await this.client.batchWriteItem(o),c=await this.safeBatchGetItems(r);for(let[d,m]of Object.entries(r))if(this.getStreamByTableName(d))for(let l of m.Keys){let f=Object.keys(l),y=i[d].find(N=>{let S={};for(let p of f)S[p]=N[p];return w(l,S)}),I=c[d].find(N=>{let S={};for(let p of f)S[p]=N[p];return w(l,S)});(I||y)&&this.setRecord(d,I,y)}s.$metadata.httpStatusCode&&(e.statusCode=s.$metadata.httpStatusCode),s.$metadata.requestId&&e.setHeader("x-amzn-RequestId",s.$metadata.requestId),e.end(JSON.stringify(s))}catch(s){this.safeReturnThrownError(t,e,s,n)}}async TransactWriteItems(t,e){let a=await this.getBodyIfJsonObject(t,e);if(!a)return;let{buf:n,parsedBody:o}=a;if(!Array.isArray(o.TransactItems))return this.redirect(t,e,n);let r={};for(let s of o.TransactItems){if(!g(s))return this.redirect(t,e,n);if(s.Delete){if(!g(s.Delete)||typeof s.Delete.TableName!="string"||!s.Delete.Key)return this.redirect(t,e,n);r[s.Delete.TableName]??={Keys:[],ConsistentRead:!0},r[s.Delete.TableName].Keys.find(d=>w(d,s.Delete.Key))||r[s.Delete.TableName].Keys.push(s.Delete.Key)}else if(s.Update){if(!g(s.Update)||typeof s.Update.TableName!="string"||!s.Update.Key)return this.redirect(t,e,n);r[s.Update.TableName]??={Keys:[],ConsistentRead:!0},r[s.Update.TableName].Keys.find(d=>w(d,s.Update.Key))||r[s.Update.TableName].Keys.push(s.Update.Key)}else if(s.Put){if(!g(s.Put)||typeof s.Put.TableName!="string"||!g(s.Put.Item))return this.redirect(t,e,n);let c=this.getTableKeySchemaAttributeNames(s.Put.TableName);if(!c)return this.redirect(t,e,n);r[s.Put.TableName]??={Keys:[],ConsistentRead:!0};let d={};for(let h of c)d[h]=s.Put.Item[h];r[s.Put.TableName].Keys.find(h=>w(h,d))||r[s.Put.TableName].Keys.push(d)}}let i=await this.safeBatchGetItems(r);try{let s=await this.client.transactWriteItems(o),c=await this.safeBatchGetItems(r);for(let[d,m]of Object.entries(r))if(this.getStreamByTableName(d))for(let l of m.Keys){let f=Object.keys(l),y=i[d].find(N=>{let S={};for(let p of f)S[p]=N[p];return w(l,S)}),I=c[d].find(N=>{let S={};for(let p of f)S[p]=N[p];return w(l,S)});(I||y)&&this.setRecord(d,I,y)}s.$metadata.httpStatusCode&&(e.statusCode=s.$metadata.httpStatusCode),s.$metadata.requestId&&e.setHeader("x-amzn-RequestId",s.$metadata.requestId),e.end(JSON.stringify(s))}catch(s){this.safeReturnThrownError(t,e,s,n)}}async setDynamoDbLocalEndpoint(){try{let t="http://localhost:8000",e=await this.client.config.endpoint?.();e&&(t=`${e.protocol}${e.hostname}`,e.port&&(t+=`:${e.port}`),e.path&&e.path!="/"&&(t+=e.path)),this.dynamoDbLocalEndpoint=t}catch{console.warn("Can not resolve DynamoDB Local endpoint. Using default http://localhost:8000")}}async setupInitialTables(){let t;do{let e={ExclusiveStartTableName:t},{TableNames:a,LastEvaluatedTableName:n}=await this.client.listTables(e);if(!a)return;for(let o of a){let{Table:r}=await this.client.describeTable({TableName:o});if(r?.KeySchema?.every(s=>s.AttributeName&&s.KeyType)){let s=r.KeySchema;if(this.inheritStreamsFromExistingTables&&r.StreamSpecification?.StreamEnabled&&r.StreamSpecification.StreamViewType){let c=new E(o,r.StreamSpecification.StreamViewType,s,this.maxShards);this.streams.push(c)}else{let{TableName:c,TableArn:d}=r;this.tableSchemas.push({TableName:c,TableArn:d,KeySchema:s})}}let{TimeToLiveDescription:i}=await this.client.describeTimeToLive({TableName:o});i?.TimeToLiveStatus=="ENABLED"&&(this.itemsWithTTL[o]={enabled:!0,ttlFieldName:i.AttributeName,keySchema:r.KeySchema,items:new Map})}t=n}while(t)}watchTTL(){setInterval(async()=>{for(let[t,e]of Object.entries(this.itemsWithTTL)){if(!e.enabled)continue;let a=Date.now();for(let[n,o]of e.items.entries())if(!(o.ttl>a))try{(await this.client.getItem({TableName:t,Key:o.key,ConsistentRead:!0})).Item||(e.items.delete(n),this.setRecord(t,void 0,o.oldImage,!0))}catch(r){console.error(r)}}},1e3).unref()}async init(){let t=this;await this.setDynamoDbLocalEndpoint(),await this.setupInitialTables();let e=W(async(a,n)=>{switch(a.headers["x-amz-target"]?.split(".")[1]){case"GetRecords":return t.GetRecords(a,n);case"GetShardIterator":return t.GetShardIterator(a,n);case"ListStreams":return t.ListStreams(a,n);case"DescribeStream":return t.DescribeStream(a,n);case"CreateTable":return t.CreateTable(a,n);case"DeleteTable":return t.DeleteTable(a,n);case"UpdateTable":return t.UpdateTable(a,n);case"PutItem":return t.PutItem(a,n);case"UpdateItem":return t.UpdateItem(a,n);case"DeleteItem":return t.DeleteItem(a,n);case"BatchWriteItem":return t.BatchWriteItem(a,n);case"TransactWriteItems":return t.TransactWriteItems(a,n);case"UpdateTimeToLive":return t.UpdateTimeToLive(a,n);default:a.pipe(D.request(new URL(a.url,this.dynamoDbLocalEndpoint),{headers:a.headers,method:a.method},i=>{n.writeHead(i.statusCode,i.statusMessage,i.headers),i.pipe(n)}))}});return await new Promise(a=>{e.listen(this.proxyPort,()=>{a(void 0)})}),this.server=e,t.watchTTL(),e.address().port}};var K=3,F=!1,P="123456789012",z="us-east-1";b.maxShards&&(typeof b.maxShards=="number"&&b.maxShards>0?K=Math.round(b.maxShards):console.warn("When provided, maxShards must be a positive integer. Using default 3."));typeof b.inheritStreamsFromExistingTables=="boolean"&&(F=b.inheritStreamsFromExistingTables);typeof b.accountId=="string"&&(P=b.accountId);typeof b.region=="string"&&(z=b.region);var G=new Q(b.dynamoDbLocalClientConfig),j=new L(G,b.proxyPort,K,F,P,z),Y=await j.init();H.postMessage({proxyPort:Y});
|
package/dist/standalone.js
CHANGED
|
@@ -6,7 +6,7 @@ Please verify provided SQS Client validity.`),console.error(d)}}},cn=/(-|\w+)/g,
|
|
|
6
6
|
`)}else I=E;I.trim()&&console.log(I)}}catch(O){console.log("err",O),y(O)}};this.python.stdout.on("data",u);let v=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",v),y(R)}else console.log(R)};this.python.stderr.on("data",v),this.python.stdin.write(`${f}
|
|
7
7
|
`)}),this.watcherListener=()=>{this.isMounted&&(this.unmount(!0),this.watchers.forEach(d=>d.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"),lt=require("node:fs"),he=require("node:fs/promises"),U=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=U.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},l){this.name=e,this.timeout=n,this.memorySize=r,this.environment=s,this.handlerName=o,this.runtime=a,this.emitRebuild=l;let c=U.default.resolve(i);this.handlerDir=U.default.dirname(c),this.handlerPath=U.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=d=>{d&&(this.ruby?.kill(),this.ruby=void 0,this.isMounted=!1)},this.invoke=async({event:d,info:m,clientContext:h,awsRequestId:p})=>new Promise((g,y)=>{let f=JSON.stringify({event:d,awsRequestId:p,context:h??""}),S=v=>{let w=null,R=v.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",S),this.ruby.stderr.removeListener("data",u),g(w)}else R.trim()&&console.log(R)}catch(E){y(E)}};this.ruby.stdout.on("data",S);let u=v=>{let w=v.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",S),this.ruby.stderr.removeListener("data",u),y(w)}else console.log(w)};this.ruby.stderr.on("data",u),this.ruby.stdin.write(`${f}
|
|
9
|
-
`)}),this.watcherListener=()=>{this.isMounted&&(this.unmount(!0),this.watchers.forEach(d=>d.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,lt.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 gn=["@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=gn.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 bn=mt.default?.url()!=null;bn&&(console.warn("Lambdas timeout are disabled when a Debugger is attached"),$.ENABLE_TIMEOUT=!1);var vn={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,dt.randomUUID)();x.accountId=Buffer.from(r).toString("hex").slice(0,16),x.apiId=Buffer.from(r).toString("ascii").slice(0,10),x.port=this.port}setPort(e){this.port=e,x.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(l=>l.toUpperCase()=="ANY")!==-1||(o=s.method.findIndex(l=>l.toUpperCase()==e)!==-1)),i&&o});if(r)return r.callback}async#r(e,n){let{url:r,method:s}=e,i=new URL(r,x.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",l=>{console.error(l.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(vn,!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.18";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:l,addLambda:c,log:d,setEndpoint:m,getEndpoint:h,getAwsProviderDefaults:p,setAwsProviderDefaults:g}){let y={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)&&g(t.defaults),t.functions&&typeof t.functions=="object"&&!Array.isArray(t.functions))for(let[S,u]of Object.entries(t.functions))c(S,u);t.services&&(t.services.sqs&&l("sqs",t.services.sqs),t.services.sns&&l("sns",t.services.sns),t.services.dynamodb&&l("dynamodb",t.services.dynamodb));let f={stop:r,lambdas:s,region:i,esbuild:o,options:t,config:y,getServices:a,setService:l,addLambda:c,log:d,setEndpoint:m,getEndpoint:h,getAwsProviderDefaults:p};if(t.plugins){y.server.onReady=async(u,v)=>{for(let w of t.plugins)if(w.server?.onReady)try{await w.server.onReady.call(f,u,v)}catch(R){d.RED(w.name),console.error(R)}},y.buildCallback=async(u,v)=>{for(let w of t.plugins)if(w.buildCallback)try{await w.buildCallback.call(f,u,v)}catch(R){d.RED(w.name),console.error(R),v||process.exit(1)}};let S=t.plugins.reduce((u,v)=>(v.server?.request?.length&&u.push(...v.server.request),u),[]);S?.length&&(y.server.request=S.map(u=>(u.callback=u.callback.bind(f),u)));for(let u of t.plugins)if(u.onKill&&y.onKill.push(u.onKill.bind(f)),u.onInit)try{await u.onInit.call(f)}catch(v){throw d.RED(u.name),v}}return y}return n.plugins=t.plugins??[],n}var xn=["js","mjs","cjs","ts","cts","mts"],wn=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);xn.includes(r)&&(s+=`.${r}`);let i;try{i=await wn(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 Rn=t=>{let e=t.split(";");return e.findIndex(r=>r.trim().toLowerCase().startsWith("path="))==-1&&e.push("Path=/"),e.join(";")},ge=(t,e,n)=>{let r={};if(t&&Object.entries(t).forEach(([s,i])=>{r[s.toLowerCase()]=Array.isArray(i)?`[${i.join(", ")}]`:i}),n)for(let[s,i]of Object.entries(n))r[s]=i;if(!Array.isArray(e))return r;if(!e.every(s=>typeof s=="string")){let s=new Error("Wrong 'cookies'. must be string[]",{cause:e}),i={"Content-Type":r["content-type"]??"application/json","x-amzn-ErrorType":"InternalFailure",...n};throw r["set-cookie"]&&(i["set-cookie"]=r["set-cookie"]),s.headers=i,s}return e=e.map(Rn),r["set-cookie"]=r["set-cookie"]?[r["set-cookie"],...e]:e,r};var be=require("node:crypto");var le=class t extends x{res;mockEvent;payload;constructor({res:e,req:n,body:r,mockEvent:s,multiValueHeaders:i,isBase64Encoded:o,lambdaName:a,parsedURL:l,requestId:c}){super(),this.res=e,this.mockEvent=s,this.payload=s.version==1?t.createApgV1Event({req:n,mockEvent:s,parsedURL:l,lambdaName:a,multiValueHeaders:i,isBase64Encoded:o,requestId:c,body:r}):t.createApgV2Event({req:n,mockEvent:s,parsedURL:l,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:l}=e,c=t.getPathParameters(n,r),d,m=n.methods.find(v=>v==a)??"ANY",h={},p="";for(let v of Array.from(new Set(r.searchParams.keys()))){let w=r.searchParams.getAll(v);p+=`&${w.map(R=>encodeURI(`${v}=${R}`)).join("&")}`,h[v]=w.join(",")}p&&(p=p.slice(1));let g=n.paths[0]=="/*"?"$default":`${m} ${r.pathname}`,y=new Date,f="127.0.0.1",S=l.host?.startsWith("localhost")?f:l.host?l.host.split(":")[0]:f,u={version:"2.0",routeKey:g,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:S,userAgent:l["user-agent"]??""},requestId:s,routeKey:g,stage:"$default",time:y.toISOString(),timeEpoch:y.getTime()}};return o?(u.body=o,u.isBase64Encoded=i):u.isBase64Encoded=!1,Object.keys(h).length&&(u.queryStringParameters=h),Object.keys(c).length&&(u.pathParameters=c),l.cookie&&(u.cookies=l.cookie.split("; ")),d=u,d.headers["x-mock-type"]&&delete d.headers["x-mock-type"],d};static createApgV1Event=({req:e,mockEvent:n,parsedURL:r,lambdaName:s,isBase64Encoded:i,requestId:o,body:a})=>{let{method:l}=e,c={};n.proxy=="httpApi"&&(c.version="1.0");let d=n.paths[0];c.resource=d,c.path=r.pathname,c.httpMethod=l;let{headers:m,multiValueHeaders:h,apiKey:p}=t.getApiGV1Headers(e,n);c.headers=m,c.multiValueHeaders=h;let g=String(e.socket.remoteAddress),y=Object.fromEntries(r.searchParams);c.queryStringParameters=Object.keys(y).length?y:null;let f=t.getMultiValueQueryStringParameters(r.searchParams);c.multiValueQueryStringParameters=Object.keys(f).length?f:null;let S=new Date,u={accountId:String(t.accountId),apiId:t.apiId,domainName:`localhost:${t.port}`,domainPrefix:"localhost",extendedRequestId:"fake-id",httpMethod:l,identity:{accessKey:null,accountId:null,caller:null,cognitoAuthenticationProvider:null,cognitoAuthenticationType:null,cognitoIdentityId:null,cognitoIdentityPoolId:null,principalOrgId:null,sourceIp:g,user:null,userAgent:e.headers["user-agent"],userArn:null},path:r.pathname,protocol:"HTTP/1.1",requestId:o,requestTime:S.toISOString(),requestTimeEpoch:S.getTime(),resourceId:"exhmtv",resourcePath:d};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 v=t.getPathParameters(n,r);return c.pathParameters=Object.keys(v).length?v: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(d=>d.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,lt.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 gn=["@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=gn.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 bn=mt.default?.url()!=null;bn&&(console.warn("Lambdas timeout are disabled when a Debugger is attached"),$.ENABLE_TIMEOUT=!1);var vn={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,dt.randomUUID)();x.accountId=Buffer.from(r).toString("hex").slice(0,16),x.apiId=Buffer.from(r).toString("ascii").slice(0,10),x.port=this.port}setPort(e){this.port=e,x.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(l=>l.toUpperCase()=="ANY")!==-1||(o=s.method.findIndex(l=>l.toUpperCase()==e)!==-1)),i&&o});if(r)return r.callback}async#r(e,n){let{url:r,method:s}=e,i=new URL(r,x.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",l=>{console.error(l.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(vn,!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.19";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:l,addLambda:c,log:d,setEndpoint:m,getEndpoint:h,getAwsProviderDefaults:p,setAwsProviderDefaults:g}){let y={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)&&g(t.defaults),t.functions&&typeof t.functions=="object"&&!Array.isArray(t.functions))for(let[S,u]of Object.entries(t.functions))c(S,u);t.services&&(t.services.sqs&&l("sqs",t.services.sqs),t.services.sns&&l("sns",t.services.sns),t.services.dynamodb&&l("dynamodb",t.services.dynamodb));let f={stop:r,lambdas:s,region:i,esbuild:o,options:t,config:y,getServices:a,setService:l,addLambda:c,log:d,setEndpoint:m,getEndpoint:h,getAwsProviderDefaults:p};if(t.plugins){y.server.onReady=async(u,v)=>{for(let w of t.plugins)if(w.server?.onReady)try{await w.server.onReady.call(f,u,v)}catch(R){d.RED(w.name),console.error(R)}},y.buildCallback=async(u,v)=>{for(let w of t.plugins)if(w.buildCallback)try{await w.buildCallback.call(f,u,v)}catch(R){d.RED(w.name),console.error(R),v||process.exit(1)}};let S=t.plugins.reduce((u,v)=>(v.server?.request?.length&&u.push(...v.server.request),u),[]);S?.length&&(y.server.request=S.map(u=>(u.callback=u.callback.bind(f),u)));for(let u of t.plugins)if(u.onKill&&y.onKill.push(u.onKill.bind(f)),u.onInit)try{await u.onInit.call(f)}catch(v){throw d.RED(u.name),v}}return y}return n.plugins=t.plugins??[],n}var xn=["js","mjs","cjs","ts","cts","mts"],wn=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);xn.includes(r)&&(s+=`.${r}`);let i;try{i=await wn(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 Rn=t=>{let e=t.split(";");return e.findIndex(r=>r.trim().toLowerCase().startsWith("path="))==-1&&e.push("Path=/"),e.join(";")},ge=(t,e,n)=>{let r={};if(t&&Object.entries(t).forEach(([s,i])=>{r[s.toLowerCase()]=Array.isArray(i)?`[${i.join(", ")}]`:i}),n)for(let[s,i]of Object.entries(n))r[s]=i;if(!Array.isArray(e))return r;if(!e.every(s=>typeof s=="string")){let s=new Error("Wrong 'cookies'. must be string[]",{cause:e}),i={"Content-Type":r["content-type"]??"application/json","x-amzn-ErrorType":"InternalFailure",...n};throw r["set-cookie"]&&(i["set-cookie"]=r["set-cookie"]),s.headers=i,s}return e=e.map(Rn),r["set-cookie"]=r["set-cookie"]?[r["set-cookie"],...e]:e,r};var be=require("node:crypto");var le=class t extends x{res;mockEvent;payload;constructor({res:e,req:n,body:r,mockEvent:s,multiValueHeaders:i,isBase64Encoded:o,lambdaName:a,parsedURL:l,requestId:c}){super(),this.res=e,this.mockEvent=s,this.payload=s.version==1?t.createApgV1Event({req:n,mockEvent:s,parsedURL:l,lambdaName:a,multiValueHeaders:i,isBase64Encoded:o,requestId:c,body:r}):t.createApgV2Event({req:n,mockEvent:s,parsedURL:l,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:l}=e,c=t.getPathParameters(n,r),d,m=n.methods.find(v=>v==a)??"ANY",h={},p="";for(let v of Array.from(new Set(r.searchParams.keys()))){let w=r.searchParams.getAll(v);p+=`&${w.map(R=>encodeURI(`${v}=${R}`)).join("&")}`,h[v]=w.join(",")}p&&(p=p.slice(1));let g=n.paths[0]=="/*"?"$default":`${m} ${r.pathname}`,y=new Date,f="127.0.0.1",S=l.host?.startsWith("localhost")?f:l.host?l.host.split(":")[0]:f,u={version:"2.0",routeKey:g,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:S,userAgent:l["user-agent"]??""},requestId:s,routeKey:g,stage:"$default",time:y.toISOString(),timeEpoch:y.getTime()}};return o?(u.body=o,u.isBase64Encoded=i):u.isBase64Encoded=!1,Object.keys(h).length&&(u.queryStringParameters=h),Object.keys(c).length&&(u.pathParameters=c),l.cookie&&(u.cookies=l.cookie.split("; ")),d=u,d.headers["x-mock-type"]&&delete d.headers["x-mock-type"],d};static createApgV1Event=({req:e,mockEvent:n,parsedURL:r,lambdaName:s,isBase64Encoded:i,requestId:o,body:a})=>{let{method:l}=e,c={};n.proxy=="httpApi"&&(c.version="1.0");let d=n.paths[0];c.resource=d,c.path=r.pathname,c.httpMethod=l;let{headers:m,multiValueHeaders:h,apiKey:p}=t.getApiGV1Headers(e,n);c.headers=m,c.multiValueHeaders=h;let g=String(e.socket.remoteAddress),y=Object.fromEntries(r.searchParams);c.queryStringParameters=Object.keys(y).length?y:null;let f=t.getMultiValueQueryStringParameters(r.searchParams);c.multiValueQueryStringParameters=Object.keys(f).length?f:null;let S=new Date,u={accountId:String(t.accountId),apiId:t.apiId,domainName:`localhost:${t.port}`,domainPrefix:"localhost",extendedRequestId:"fake-id",httpMethod:l,identity:{accessKey:null,accountId:null,caller:null,cognitoAuthenticationProvider:null,cognitoAuthenticationType:null,cognitoIdentityId:null,cognitoIdentityPoolId:null,principalOrgId:null,sourceIp:g,user:null,userAgent:e.headers["user-agent"],userArn:null},path:r.pathname,protocol:"HTTP/1.1",requestId:o,requestTime:S.toISOString(),requestTimeEpoch:S.getTime(),resourceId:"exhmtv",resourcePath:d};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 v=t.getPathParameters(n,r);return c.pathParameters=Object.keys(v).length?v: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,d])=>{let m=t.normalizeHeaderKey(c),h=this.#e(d);n.push([m,h])}),e.multiValueHeaders&&typeof e.multiValueHeaders=="object"&&!Array.isArray(e.multiValueHeaders)&&Object.entries(e.multiValueHeaders).forEach(([c,d])=>{let m=t.normalizeHeaderKey(c);if(!Array.isArray(d))throw new Error;d.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 l=r==204?"0":s?String(Buffer.from(s).byteLength):"0";n.push(["Content-Length",l]),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 En=(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,l=m=>{a=a?Buffer.concat([a,m]):m},c=()=>{if(a){let m=_e(a),h=m.statusCode??200;try{let p=ge(m.headers,m.cookies);t.writeHead(h,p)}catch(p){t.writeHead(500,p.headers),t.end?.(x.amzMsgNull),delete p.headers}}else t.writeHead(200)};n.setHeader=(m,h)=>{if(m.toLowerCase()=="content-type"){if(h=="application/vnd.awslambda.http-integration-response")return r=!0,i("Content-Type",x.contentType.json);o=h}return i(m,h)};let d=!1;return n.write=(m,h,p)=>{if(n.headersSent)return s(m,h,p);if(d)try{let g=A.codec.decode(m),y=JSON.parse(g);if(Array.isArray(y))throw new Error("Invalid stream response");return y&&typeof y=="object"?(c(),s(m,h,p)):(t.writeHead(200,{"Content-Type":x.contentType.octet}),t.end())}catch(g){let y=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 y.cause=g.message,console.error(y),Z(t)}else if(r)$e(m)?d=!0:l(m);else{if(o==x.contentType.json)try{let y=A.codec.decode(m),f=JSON.parse(y);if(f===null||typeof f=="number")throw new Error(y)}catch(y){let f=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 f.cause=y.message,console.error(f),Z(t)}let g={"Content-Type":o??x.contentType.octet};return n.writeHead(200,g),s(m,h,p)}},n}},In=(t,e,n,r)=>{let s=K(t),i=s?t.getParsedResponse():t,o,a=!1;if(i&&typeof i=="object"&&i.statusCode){let l=isNaN(i.statusCode),c=l?500:i.statusCode;if(a=!l&&(i.isBase64Encoded==!0||i.isBase64Encoded=="true"),i.headers||i.cookies)try{let d=ge(i.headers,i.cookies,r);e.writeHead(c,d)}catch(d){return e.writeHead(500,d.headers),delete d.headers,console.error(d),e.end(x.amzMsgNull)}else e.writeHead(c,{"Content-Type":x.contentType.json,...r});n?o=i:(typeof i.body<"u"&&(o=i.body),e.headersSent||e.setHeader("Content-Type",s?x.contentType.octet:x.contentType.json))}else e.writeHead(200,{"Content-Type":x.contentType.json,...r}),o=i;!e.headersSent&&!n&&s&&e.setHeader("Content-Type",x.contentType.octet),n?o instanceof Uint8Array?e.end(o):e.end(JSON.stringify(o)):((typeof o=="number"||typeof o=="boolean"||o==null||o instanceof Object)&&(o=JSON.stringify(o)),o&&a&&(o=Buffer.from(o,"base64")),e.end(o))};function An(t,e){let n=t["access-control-request-method"];return e=="OPTIONS"&&t.origin&&n&&["GET","HEAD","POST","PUT","DELETE","PATCH"].includes(n)}function vt(t,e){let n=e.origin;return n&&t.allowOrigins.find(s=>s=="*"||s=="http://*"||s=="https://*")?!0:!!t.allowOrigins.find(s=>s==n)}function kn(t,e){if(!t.allowMethods?.length)return!1;if(t.allowMethods.find(s=>s=="*"))return!0;let r=e["access-control-request-method"];return!!t.allowMethods.find(s=>s==r)}function Pn(t,e){if(!kn(t,e)||!vt(t,e))return!1;let n=e["access-control-request-headers"]?e["access-control-request-headers"].split(",").filter(Boolean):[];return n.length?t.allowHeaders?.length?n.every(r=>t.allowHeaders.find(s=>s.toLowerCase()==r.toLowerCase())):!1:!0}var 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,x.dummyHost),a=F(n),l=k.parseNameFromUrl(o.pathname),c=t.handlers.find(f=>f.name==l);if(!c?.url)return n.statusCode=404,n.end("Not Found");let d;if(c.url.cors){if(An(i,s)){let S=Pn(c.url.cors,i),u={"Content-Type":x.contentType.json};return S&&(u["access-control-allow-origin"]=i.origin,c.url.cors.allowMethods.find(v=>v=="*")?u["access-control-allow-methods"]=i["access-control-request-method"]:u["access-control-allow-methods"]=c.url.cors.allowMethods.join(","),c.url.cors.allowHeaders?.length&&(u["access-control-allow-headers"]=c.url.cors.allowHeaders.join(",")),typeof c.url.cors.maxAge=="number"&&c.url.cors.maxAge>-1&&(u["access-control-max-age"]=`${c.url.cors.maxAge}`),c.url.cors.allowCredentials&&(u["access-control-allow-credentials"]="true")),n.writeHead(200,u),n.end()}vt(c.url.cors,i)&&(d={"access-control-allow-origin":i.origin},c.url.cors.exposeHeaders?.length&&(d["access-control-expose-headers"]=c.url.cors.exposeHeaders.join(",")),c.url.cors.allowCredentials&&(d["access-control-allow-credentials"]="true"))}let m=x.getIsBase64Encoded(i),h=await D(e,m),p=le.createApgV2Event({req:e,mockEvent:c.url,parsedURL:o,requestId:a,body:h,isBase64Encoded:m}),g=`/@url/${c.name}`,y=o.pathname.slice(g.length);y||(y="/"),p.requestContext.accountId="anonymous",p.rawPath=y,p.requestContext.http.path=y;try{let f=En(n,c),S=await c.invoke(p,c.url,void 0,f);if(!S)return n.end();In(S,n,f,d)}catch(f){console.error(f),Z(n,d)}}});var xt=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(f=>f.name==o),l=F(n);if(n.setHeader("Content-Type","application/json"),e.on("error",f=>{n.statusCode=502,n.end(JSON.stringify(f))}),!a){let{region:f,accountId:S}=t.aws;return n.statusCode=404,n.setHeader("x-amzn-errortype","ResourceNotFoundException"),n.end(X(o,f,S))}let c=s["x-amz-invocation-type"],d=J(s["x-amz-client-context"]);if(d instanceof Error)return n.setHeader("x-amzn-errortype","InvalidRequestContentException"),n.statusCode=400,n.end(Y);let m=c=="DryRun"?204:c=="Event"?202:200,h=await D(e),p=Q(h);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 g=new Date,y={};n.statusCode=m,m!==200&&n.end(),m==202&&(y.kind="async");try{let f=await a.invoke(p,y,d);if(m==200){if(typeof f>"u"){n.end();return}let S=K(f),u=S?f.buffer:f;S?u=A.codec.decode(u):typeof u!="string"&&(u=JSON.stringify(u)),n.end(u)}}catch(f){n.writableFinished||(n.setHeader("X-Amz-Function-Error",f.errorType??f.message??""),n.statusCode=200,n.end(JSON.stringify(f)))}}});var ve=require("node:crypto"),wt=require("node:timers/promises");var Rt=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:l,Timeout:c,MemorySize:d}=s;t.addLambda(i,{handler:o,environment:a?.Variables,runtime:l,timeout:c,memorySize:d}),t.isDynamicBuild=!0,t.setEsBuildConfig(),await t.buildContext.dispose(),await t.buildAndWatch(),await(0,wt.setTimeout)(100),n.statusCode=201,n.end(r)}}),Et=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:It(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,ve.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))}}),On=["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 It(t){let e={};for(let[n,r]of Object.entries(t))On.includes(n)||(e[n]=String(r));return e}var At=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:It(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,ve.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))}}),kt=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 Pt=require("@smithy/eventstream-codec");var Nn=(t,e)=>{let n=Buffer.from(t,e);return new Uint8Array(n.buffer,n.byteOffset,n.byteLength/Uint8Array.BYTES_PER_ELEMENT)},Dn=t=>Buffer.from(t,t.byteOffset,t.byteLength).toString("utf8"),Se=new Pt.EventStreamCodec(Dn,Nn),de=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(Se.encode({headers:this.#e("PayloadChunk",x.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(Se.encode({headers:this.#e("InvokeComplete",x.contentType.json),body:new Uint8Array(r)}))}endWithJson(e){let n=Array.from(Buffer.from(JSON.stringify(e)).values());this.res.write(Se.encode({headers:this.#e("PayloadChunk",x.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 Lt=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),l=t.handlers.find(p=>p.name==a),c=await D(e),d=Q(c);if(n.setHeader("X-Amzn-Trace-Id","root=1-xxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx;sampled=0"),d instanceof Error)return n.statusCode=400,n.setHeader("x-amzn-errortype","InvalidRequestContentException"),n.end(G(d.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 h=new de(n);if(l){let p=l.url?.stream??{};try{let g=await l.invoke(d,p,m,h);g&&h.endWithJson(g)}catch(g){n.writableFinished||h.endWithError(g)}}else{let{region:p,accountId:g}=t.aws;n.statusCode=404,n.end(X(a,p,g))}}});var Ot=t=>[Rt(t),At(t),kt(t),xt(t),Lt(t),St(t),Et(t)];var we=process.cwd(),Tn=3,Mn=1024,qn={IS_OFFLINE:!0,IS_LOCAL:!0,AWS_SAM_LOCAL:!0},jn=we.split(L.default.sep)[0],Fn=new RegExp(`^.*:${jn}`),Hn=t=>Fn.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,l)=>{let c=`http://localhost:${a}`;b.PINK(`Lambda endpoint: ${c}`),this.endpoints.lambda=c,this.setLambdaEndpointEnvVar&&(this.runtimeConfig.environment.AWS_ENDPOINT_URL_LAMBDA=c,this.aws.environment.AWS_ENDPOINT_URL_LAMBDA=c),await s.load(s.#e);for(let d of s.#e)d.setEnv("LOCAL_PORT",a),d.setEnv("AWS_LAMBDA_RUNTIME_API",`127.0.0.1:${a}`),this.setLambdaEndpointEnvVar&&d.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,l=L.default.extname(a),c=l.slice(1),d=L.default.resolve(a.replace(l,"")),m=n.getFunction(e),h=m.runtime??r,p={name:e,runtime:m.runtime??r,handlerPath:a,handlerName:c,esEntryPoint:d,memorySize:o.memorySize??this.runtimeConfig.memorySize??Mn,timeout:o.timeout??this.runtimeConfig.timeout??Tn,sqs:[],ddb:[],environment:{AWS_EXECUTION_ENV:`AWS_Lambda_${h}`,AWS_LAMBDA_FUNCTION_VERSION:"$LATEST",AWS_LAMBDA_FUNCTION_NAME:e,_HANDLER:L.default.basename(a),...this.runtimeConfig.environment,...o.environment,...qn},invoke:async(g,y)=>{let f=this.getHandlerByName(`/@invoke/${e}`);if(f)return await f.invoke(g,y);b.RED(`'${e}' is not mounted yet.
|
package/dist/standalone.mjs
CHANGED
|
@@ -6,7 +6,7 @@ Please verify provided SQS Client validity.`),console.error(d)}}},Nt=/(-|\w+)/g,
|
|
|
6
6
|
`)}else I=E;I.trim()&&console.log(I)}}catch(P){console.log("err",P),y(P)}};this.python.stdout.on("data",u);let v=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",v),y(R)}else console.log(R)};this.python.stderr.on("data",v),this.python.stdin.write(`${f}
|
|
7
7
|
`)}),this.watcherListener=()=>{this.isMounted&&(this.unmount(!0),this.watchers.forEach(d=>d.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 We(o),this.watchers.push(Bt(o,{persistent:!1},this.watcherListener))}catch{}}catch(n){console.log(n)}};findPython(){let[e]=this.runtime.split("."),n=e.split("python")[1];if(Ce(`${e} --version`))return e;let r=Ce("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=Vt(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 Qt}from"node:child_process";import{watch as Kt}from"node:fs";import{access as ze}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},l){this.name=e,this.timeout=n,this.memorySize=r,this.environment=s,this.handlerName=o,this.runtime=a,this.emitRebuild=l;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 ze(this.modulePath),this.load()}catch{console.error(`Can not find ${this.name}'s handler at: "${this.modulePath}"`),process.exit(1)}},this.unmount=d=>{d&&(this.ruby?.kill(),this.ruby=void 0,this.isMounted=!1)},this.invoke=async({event:d,info:m,clientContext:h,awsRequestId:p})=>new Promise((g,y)=>{let f=JSON.stringify({event:d,awsRequestId:p,context:h??""}),S=v=>{let w=null,R=v.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",S),this.ruby.stderr.removeListener("data",u),g(w)}else R.trim()&&console.log(R)}catch(E){y(E)}};this.ruby.stdout.on("data",S);let u=v=>{let w=v.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",S),this.ruby.stderr.removeListener("data",u),y(w)}else console.log(w)};this.ruby.stderr.on("data",u),this.ruby.stdin.write(`${f}
|
|
9
|
-
`)}),this.watcherListener=()=>{this.isMounted&&(this.unmount(!0),this.watchers.forEach(d=>d.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 ze(i),this.watchers.push(Kt(i,{persistent:!1},this.watcherListener))}catch{}}catch(n){console.log(n)}};load=()=>{this.bin||(this.bin=process.platform==="win32"?"ruby.exe":"ruby"),this.ruby=Qt(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 Gt=["@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=Gt.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 en=Zt?.url()!=null;en&&(console.warn("Lambdas timeout are disabled when a Debugger is attached"),H.ENABLE_TIMEOUT=!1);var tn={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=Xt.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=Yt();x.accountId=Buffer.from(r).toString("hex").slice(0,16),x.apiId=Buffer.from(r).toString("ascii").slice(0,10),x.port=this.port}setPort(e){this.port=e,x.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(l=>l.toUpperCase()=="ANY")!==-1||(o=s.method.findIndex(l=>l.toUpperCase()==e)!==-1)),i&&o});if(r)return r.callback}async#r(e,n){let{url:r,method:s}=e,i=new URL(r,x.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",l=>{console.error(l.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(tn,!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 sn}from"node:fs/promises";import N from"node:path";import{pathToFileURL as on}from"node:url";import an from"esbuild";var rn="0.0.18";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:l,addLambda:c,log:d,setEndpoint:m,getEndpoint:h,getAwsProviderDefaults:p,setAwsProviderDefaults:g}){let y={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)&&g(t.defaults),t.functions&&typeof t.functions=="object"&&!Array.isArray(t.functions))for(let[S,u]of Object.entries(t.functions))c(S,u);t.services&&(t.services.sqs&&l("sqs",t.services.sqs),t.services.sns&&l("sns",t.services.sns),t.services.dynamodb&&l("dynamodb",t.services.dynamodb));let f={stop:r,lambdas:s,region:i,esbuild:o,options:t,config:y,getServices:a,setService:l,addLambda:c,log:d,setEndpoint:m,getEndpoint:h,getAwsProviderDefaults:p};if(t.plugins){y.server.onReady=async(u,v)=>{for(let w of t.plugins)if(w.server?.onReady)try{await w.server.onReady.call(f,u,v)}catch(R){d.RED(w.name),console.error(R)}},y.buildCallback=async(u,v)=>{for(let w of t.plugins)if(w.buildCallback)try{await w.buildCallback.call(f,u,v)}catch(R){d.RED(w.name),console.error(R),v||process.exit(1)}};let S=t.plugins.reduce((u,v)=>(v.server?.request?.length&&u.push(...v.server.request),u),[]);S?.length&&(y.server.request=S.map(u=>(u.callback=u.callback.bind(f),u)));for(let u of t.plugins)if(u.onKill&&y.onKill.push(u.onKill.bind(f)),u.onInit)try{await u.onInit.call(f)}catch(v){throw d.RED(u.name),v}}return y}return n.plugins=t.plugins??[],n}var cn=["js","mjs","cjs","ts","cts","mts"],ln=async t=>{let e=N.dirname(N.toNamespacedPath(t)),n=N.basename(t,N.extname(t)),r=N.join(e,`__${n}.mjs`);await an.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(on(r).href)}catch(s){throw s}finally{await sn(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);cn.includes(r)&&(s+=`.${r}`);let i;try{i=await ln(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.trim().toLowerCase().startsWith("path="))==-1&&e.push("Path=/"),e.join(";")},de=(t,e,n)=>{let r={};if(t&&Object.entries(t).forEach(([s,i])=>{r[s.toLowerCase()]=Array.isArray(i)?`[${i.join(", ")}]`:i}),n)for(let[s,i]of Object.entries(n))r[s]=i;if(!Array.isArray(e))return r;if(!e.every(s=>typeof s=="string")){let s=new Error("Wrong 'cookies'. must be string[]",{cause:e}),i={"Content-Type":r["content-type"]??"application/json","x-amzn-ErrorType":"InternalFailure",...n};throw r["set-cookie"]&&(i["set-cookie"]=r["set-cookie"]),s.headers=i,s}return e=e.map(dn),r["set-cookie"]=r["set-cookie"]?[r["set-cookie"],...e]:e,r};import{randomUUID as Qe}from"node:crypto";var oe=class t extends x{res;mockEvent;payload;constructor({res:e,req:n,body:r,mockEvent:s,multiValueHeaders:i,isBase64Encoded:o,lambdaName:a,parsedURL:l,requestId:c}){super(),this.res=e,this.mockEvent=s,this.payload=s.version==1?t.createApgV1Event({req:n,mockEvent:s,parsedURL:l,lambdaName:a,multiValueHeaders:i,isBase64Encoded:o,requestId:c,body:r}):t.createApgV2Event({req:n,mockEvent:s,parsedURL:l,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:l}=e,c=t.getPathParameters(n,r),d,m=n.methods.find(v=>v==a)??"ANY",h={},p="";for(let v of Array.from(new Set(r.searchParams.keys()))){let w=r.searchParams.getAll(v);p+=`&${w.map(R=>encodeURI(`${v}=${R}`)).join("&")}`,h[v]=w.join(",")}p&&(p=p.slice(1));let g=n.paths[0]=="/*"?"$default":`${m} ${r.pathname}`,y=new Date,f="127.0.0.1",S=l.host?.startsWith("localhost")?f:l.host?l.host.split(":")[0]:f,u={version:"2.0",routeKey:g,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:S,userAgent:l["user-agent"]??""},requestId:s,routeKey:g,stage:"$default",time:y.toISOString(),timeEpoch:y.getTime()}};return o?(u.body=o,u.isBase64Encoded=i):u.isBase64Encoded=!1,Object.keys(h).length&&(u.queryStringParameters=h),Object.keys(c).length&&(u.pathParameters=c),l.cookie&&(u.cookies=l.cookie.split("; ")),d=u,d.headers["x-mock-type"]&&delete d.headers["x-mock-type"],d};static createApgV1Event=({req:e,mockEvent:n,parsedURL:r,lambdaName:s,isBase64Encoded:i,requestId:o,body:a})=>{let{method:l}=e,c={};n.proxy=="httpApi"&&(c.version="1.0");let d=n.paths[0];c.resource=d,c.path=r.pathname,c.httpMethod=l;let{headers:m,multiValueHeaders:h,apiKey:p}=t.getApiGV1Headers(e,n);c.headers=m,c.multiValueHeaders=h;let g=String(e.socket.remoteAddress),y=Object.fromEntries(r.searchParams);c.queryStringParameters=Object.keys(y).length?y:null;let f=t.getMultiValueQueryStringParameters(r.searchParams);c.multiValueQueryStringParameters=Object.keys(f).length?f:null;let S=new Date,u={accountId:String(t.accountId),apiId:t.apiId,domainName:`localhost:${t.port}`,domainPrefix:"localhost",extendedRequestId:"fake-id",httpMethod:l,identity:{accessKey:null,accountId:null,caller:null,cognitoAuthenticationProvider:null,cognitoAuthenticationType:null,cognitoIdentityId:null,cognitoIdentityPoolId:null,principalOrgId:null,sourceIp:g,user:null,userAgent:e.headers["user-agent"],userArn:null},path:r.pathname,protocol:"HTTP/1.1",requestId:o,requestTime:S.toISOString(),requestTimeEpoch:S.getTime(),resourceId:"exhmtv",resourcePath:d};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 v=t.getPathParameters(n,r);return c.pathParameters=Object.keys(v).length?v: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(d=>d.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 ze(i),this.watchers.push(Kt(i,{persistent:!1},this.watcherListener))}catch{}}catch(n){console.log(n)}};load=()=>{this.bin||(this.bin=process.platform==="win32"?"ruby.exe":"ruby"),this.ruby=Qt(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 Gt=["@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=Gt.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 en=Zt?.url()!=null;en&&(console.warn("Lambdas timeout are disabled when a Debugger is attached"),H.ENABLE_TIMEOUT=!1);var tn={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=Xt.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=Yt();x.accountId=Buffer.from(r).toString("hex").slice(0,16),x.apiId=Buffer.from(r).toString("ascii").slice(0,10),x.port=this.port}setPort(e){this.port=e,x.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(l=>l.toUpperCase()=="ANY")!==-1||(o=s.method.findIndex(l=>l.toUpperCase()==e)!==-1)),i&&o});if(r)return r.callback}async#r(e,n){let{url:r,method:s}=e,i=new URL(r,x.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",l=>{console.error(l.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(tn,!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 sn}from"node:fs/promises";import N from"node:path";import{pathToFileURL as on}from"node:url";import an from"esbuild";var rn="0.0.19";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:l,addLambda:c,log:d,setEndpoint:m,getEndpoint:h,getAwsProviderDefaults:p,setAwsProviderDefaults:g}){let y={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)&&g(t.defaults),t.functions&&typeof t.functions=="object"&&!Array.isArray(t.functions))for(let[S,u]of Object.entries(t.functions))c(S,u);t.services&&(t.services.sqs&&l("sqs",t.services.sqs),t.services.sns&&l("sns",t.services.sns),t.services.dynamodb&&l("dynamodb",t.services.dynamodb));let f={stop:r,lambdas:s,region:i,esbuild:o,options:t,config:y,getServices:a,setService:l,addLambda:c,log:d,setEndpoint:m,getEndpoint:h,getAwsProviderDefaults:p};if(t.plugins){y.server.onReady=async(u,v)=>{for(let w of t.plugins)if(w.server?.onReady)try{await w.server.onReady.call(f,u,v)}catch(R){d.RED(w.name),console.error(R)}},y.buildCallback=async(u,v)=>{for(let w of t.plugins)if(w.buildCallback)try{await w.buildCallback.call(f,u,v)}catch(R){d.RED(w.name),console.error(R),v||process.exit(1)}};let S=t.plugins.reduce((u,v)=>(v.server?.request?.length&&u.push(...v.server.request),u),[]);S?.length&&(y.server.request=S.map(u=>(u.callback=u.callback.bind(f),u)));for(let u of t.plugins)if(u.onKill&&y.onKill.push(u.onKill.bind(f)),u.onInit)try{await u.onInit.call(f)}catch(v){throw d.RED(u.name),v}}return y}return n.plugins=t.plugins??[],n}var cn=["js","mjs","cjs","ts","cts","mts"],ln=async t=>{let e=N.dirname(N.toNamespacedPath(t)),n=N.basename(t,N.extname(t)),r=N.join(e,`__${n}.mjs`);await an.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(on(r).href)}catch(s){throw s}finally{await sn(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);cn.includes(r)&&(s+=`.${r}`);let i;try{i=await ln(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.trim().toLowerCase().startsWith("path="))==-1&&e.push("Path=/"),e.join(";")},de=(t,e,n)=>{let r={};if(t&&Object.entries(t).forEach(([s,i])=>{r[s.toLowerCase()]=Array.isArray(i)?`[${i.join(", ")}]`:i}),n)for(let[s,i]of Object.entries(n))r[s]=i;if(!Array.isArray(e))return r;if(!e.every(s=>typeof s=="string")){let s=new Error("Wrong 'cookies'. must be string[]",{cause:e}),i={"Content-Type":r["content-type"]??"application/json","x-amzn-ErrorType":"InternalFailure",...n};throw r["set-cookie"]&&(i["set-cookie"]=r["set-cookie"]),s.headers=i,s}return e=e.map(dn),r["set-cookie"]=r["set-cookie"]?[r["set-cookie"],...e]:e,r};import{randomUUID as Qe}from"node:crypto";var oe=class t extends x{res;mockEvent;payload;constructor({res:e,req:n,body:r,mockEvent:s,multiValueHeaders:i,isBase64Encoded:o,lambdaName:a,parsedURL:l,requestId:c}){super(),this.res=e,this.mockEvent=s,this.payload=s.version==1?t.createApgV1Event({req:n,mockEvent:s,parsedURL:l,lambdaName:a,multiValueHeaders:i,isBase64Encoded:o,requestId:c,body:r}):t.createApgV2Event({req:n,mockEvent:s,parsedURL:l,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:l}=e,c=t.getPathParameters(n,r),d,m=n.methods.find(v=>v==a)??"ANY",h={},p="";for(let v of Array.from(new Set(r.searchParams.keys()))){let w=r.searchParams.getAll(v);p+=`&${w.map(R=>encodeURI(`${v}=${R}`)).join("&")}`,h[v]=w.join(",")}p&&(p=p.slice(1));let g=n.paths[0]=="/*"?"$default":`${m} ${r.pathname}`,y=new Date,f="127.0.0.1",S=l.host?.startsWith("localhost")?f:l.host?l.host.split(":")[0]:f,u={version:"2.0",routeKey:g,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:S,userAgent:l["user-agent"]??""},requestId:s,routeKey:g,stage:"$default",time:y.toISOString(),timeEpoch:y.getTime()}};return o?(u.body=o,u.isBase64Encoded=i):u.isBase64Encoded=!1,Object.keys(h).length&&(u.queryStringParameters=h),Object.keys(c).length&&(u.pathParameters=c),l.cookie&&(u.cookies=l.cookie.split("; ")),d=u,d.headers["x-mock-type"]&&delete d.headers["x-mock-type"],d};static createApgV1Event=({req:e,mockEvent:n,parsedURL:r,lambdaName:s,isBase64Encoded:i,requestId:o,body:a})=>{let{method:l}=e,c={};n.proxy=="httpApi"&&(c.version="1.0");let d=n.paths[0];c.resource=d,c.path=r.pathname,c.httpMethod=l;let{headers:m,multiValueHeaders:h,apiKey:p}=t.getApiGV1Headers(e,n);c.headers=m,c.multiValueHeaders=h;let g=String(e.socket.remoteAddress),y=Object.fromEntries(r.searchParams);c.queryStringParameters=Object.keys(y).length?y:null;let f=t.getMultiValueQueryStringParameters(r.searchParams);c.multiValueQueryStringParameters=Object.keys(f).length?f:null;let S=new Date,u={accountId:String(t.accountId),apiId:t.apiId,domainName:`localhost:${t.port}`,domainPrefix:"localhost",extendedRequestId:"fake-id",httpMethod:l,identity:{accessKey:null,accountId:null,caller:null,cognitoAuthenticationProvider:null,cognitoAuthenticationType:null,cognitoIdentityId:null,cognitoIdentityPoolId:null,principalOrgId:null,sourceIp:g,user:null,userAgent:e.headers["user-agent"],userArn:null},path:r.pathname,protocol:"HTTP/1.1",requestId:o,requestTime:S.toISOString(),requestTimeEpoch:S.getTime(),resourceId:"exhmtv",resourcePath:d};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 v=t.getPathParameters(n,r);return c.pathParameters=Object.keys(v).length?v: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,d])=>{let m=t.normalizeHeaderKey(c),h=this.#e(d);n.push([m,h])}),e.multiValueHeaders&&typeof e.multiValueHeaders=="object"&&!Array.isArray(e.multiValueHeaders)&&Object.entries(e.multiValueHeaders).forEach(([c,d])=>{let m=t.normalizeHeaderKey(c);if(!Array.isArray(d))throw new Error;d.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 l=r==204?"0":s?String(Buffer.from(s).byteLength):"0";n.push(["Content-Length",l]),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 pn=(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,l=m=>{a=a?Buffer.concat([a,m]):m},c=()=>{if(a){let m=Pe(a),h=m.statusCode??200;try{let p=de(m.headers,m.cookies);t.writeHead(h,p)}catch(p){t.writeHead(500,p.headers),t.end?.(x.amzMsgNull),delete p.headers}}else t.writeHead(200)};n.setHeader=(m,h)=>{if(m.toLowerCase()=="content-type"){if(h=="application/vnd.awslambda.http-integration-response")return r=!0,i("Content-Type",x.contentType.json);o=h}return i(m,h)};let d=!1;return n.write=(m,h,p)=>{if(n.headersSent)return s(m,h,p);if(d)try{let g=A.codec.decode(m),y=JSON.parse(g);if(Array.isArray(y))throw new Error("Invalid stream response");return y&&typeof y=="object"?(c(),s(m,h,p)):(t.writeHead(200,{"Content-Type":x.contentType.octet}),t.end())}catch(g){let y=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 y.cause=g.message,console.error(y),G(t)}else if(r)Le(m)?d=!0:l(m);else{if(o==x.contentType.json)try{let y=A.codec.decode(m),f=JSON.parse(y);if(f===null||typeof f=="number")throw new Error(y)}catch(y){let f=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 f.cause=y.message,console.error(f),G(t)}let g={"Content-Type":o??x.contentType.octet};return n.writeHead(200,g),s(m,h,p)}},n}},mn=(t,e,n,r)=>{let s=B(t),i=s?t.getParsedResponse():t,o,a=!1;if(i&&typeof i=="object"&&i.statusCode){let l=isNaN(i.statusCode),c=l?500:i.statusCode;if(a=!l&&(i.isBase64Encoded==!0||i.isBase64Encoded=="true"),i.headers||i.cookies)try{let d=de(i.headers,i.cookies,r);e.writeHead(c,d)}catch(d){return e.writeHead(500,d.headers),delete d.headers,console.error(d),e.end(x.amzMsgNull)}else e.writeHead(c,{"Content-Type":x.contentType.json,...r});n?o=i:(typeof i.body<"u"&&(o=i.body),e.headersSent||e.setHeader("Content-Type",s?x.contentType.octet:x.contentType.json))}else e.writeHead(200,{"Content-Type":x.contentType.json,...r}),o=i;!e.headersSent&&!n&&s&&e.setHeader("Content-Type",x.contentType.octet),n?o instanceof Uint8Array?e.end(o):e.end(JSON.stringify(o)):((typeof o=="number"||typeof o=="boolean"||o==null||o instanceof Object)&&(o=JSON.stringify(o)),o&&a&&(o=Buffer.from(o,"base64")),e.end(o))};function un(t,e){let n=t["access-control-request-method"];return e=="OPTIONS"&&t.origin&&n&&["GET","HEAD","POST","PUT","DELETE","PATCH"].includes(n)}function Ke(t,e){let n=e.origin;return n&&t.allowOrigins.find(s=>s=="*"||s=="http://*"||s=="https://*")?!0:!!t.allowOrigins.find(s=>s==n)}function fn(t,e){if(!t.allowMethods?.length)return!1;if(t.allowMethods.find(s=>s=="*"))return!0;let r=e["access-control-request-method"];return!!t.allowMethods.find(s=>s==r)}function hn(t,e){if(!fn(t,e)||!Ke(t,e))return!1;let n=e["access-control-request-headers"]?e["access-control-request-headers"].split(",").filter(Boolean):[];return n.length?t.allowHeaders?.length?n.every(r=>t.allowHeaders.find(s=>s.toLowerCase()==r.toLowerCase())):!1:!0}var Ge=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,x.dummyHost),a=j(n),l=k.parseNameFromUrl(o.pathname),c=t.handlers.find(f=>f.name==l);if(!c?.url)return n.statusCode=404,n.end("Not Found");let d;if(c.url.cors){if(un(i,s)){let S=hn(c.url.cors,i),u={"Content-Type":x.contentType.json};return S&&(u["access-control-allow-origin"]=i.origin,c.url.cors.allowMethods.find(v=>v=="*")?u["access-control-allow-methods"]=i["access-control-request-method"]:u["access-control-allow-methods"]=c.url.cors.allowMethods.join(","),c.url.cors.allowHeaders?.length&&(u["access-control-allow-headers"]=c.url.cors.allowHeaders.join(",")),typeof c.url.cors.maxAge=="number"&&c.url.cors.maxAge>-1&&(u["access-control-max-age"]=`${c.url.cors.maxAge}`),c.url.cors.allowCredentials&&(u["access-control-allow-credentials"]="true")),n.writeHead(200,u),n.end()}Ke(c.url.cors,i)&&(d={"access-control-allow-origin":i.origin},c.url.cors.exposeHeaders?.length&&(d["access-control-expose-headers"]=c.url.cors.exposeHeaders.join(",")),c.url.cors.allowCredentials&&(d["access-control-allow-credentials"]="true"))}let m=x.getIsBase64Encoded(i),h=await O(e,m),p=oe.createApgV2Event({req:e,mockEvent:c.url,parsedURL:o,requestId:a,body:h,isBase64Encoded:m}),g=`/@url/${c.name}`,y=o.pathname.slice(g.length);y||(y="/"),p.requestContext.accountId="anonymous",p.rawPath=y,p.requestContext.http.path=y;try{let f=pn(n,c),S=await c.invoke(p,c.url,void 0,f);if(!S)return n.end();mn(S,n,f,d)}catch(f){console.error(f),G(n,d)}}});var Ye=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(f=>f.name==o),l=j(n);if(n.setHeader("Content-Type","application/json"),e.on("error",f=>{n.statusCode=502,n.end(JSON.stringify(f))}),!a){let{region:f,accountId:S}=t.aws;return n.statusCode=404,n.setHeader("x-amzn-errortype","ResourceNotFoundException"),n.end(K(o,f,S))}let c=s["x-amz-invocation-type"],d=z(s["x-amz-client-context"]);if(d instanceof Error)return n.setHeader("x-amzn-errortype","InvalidRequestContentException"),n.statusCode=400,n.end(Q);let m=c=="DryRun"?204:c=="Event"?202:200,h=await O(e),p=V(h);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 g=new Date,y={};n.statusCode=m,m!==200&&n.end(),m==202&&(y.kind="async");try{let f=await a.invoke(p,y,d);if(m==200){if(typeof f>"u"){n.end();return}let S=B(f),u=S?f.buffer:f;S?u=A.codec.decode(u):typeof u!="string"&&(u=JSON.stringify(u)),n.end(u)}}catch(f){n.writableFinished||(n.setHeader("X-Amz-Function-Error",f.errorType??f.message??""),n.statusCode=200,n.end(JSON.stringify(f)))}}});import{randomUUID as Xe}from"node:crypto";import{setTimeout as gn}from"node:timers/promises";var Ze=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:l,Timeout:c,MemorySize:d}=s;t.addLambda(i,{handler:o,environment:a?.Variables,runtime:l,timeout:c,memorySize:d}),t.isDynamicBuild=!0,t.setEsBuildConfig(),await t.buildContext.dispose(),await t.buildAndWatch(),await gn(100),n.statusCode=201,n.end(r)}}),et=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:tt(o.environment)},State:"Active",LastUpdateStatus:"Successful",LastModified:new Date().toISOString(),Version:"$LATEST",Role:`arn:aws:iam::${t.aws.accountId}:role/fake-role-name`,RevisionId:Xe(),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))}}),bn=["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 tt(t){let e={};for(let[n,r]of Object.entries(t))bn.includes(n)||(e[n]=String(r));return e}var nt=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:tt(o.environment)},State:"Active",LastUpdateStatus:"Successful",LastModified:new Date().toISOString(),Version:"$LATEST",Role:`arn:aws:iam::${t.aws.accountId}:role/fake-role-name`,RevisionId:Xe(),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))}}),rt=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 vn}from"@smithy/eventstream-codec";var Sn=(t,e)=>{let n=Buffer.from(t,e);return new Uint8Array(n.buffer,n.byteOffset,n.byteLength/Uint8Array.BYTES_PER_ELEMENT)},xn=t=>Buffer.from(t,t.byteOffset,t.byteLength).toString("utf8"),pe=new vn(xn,Sn),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",x.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",x.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",x.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 st=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),l=t.handlers.find(p=>p.name==a),c=await O(e),d=V(c);if(n.setHeader("X-Amzn-Trace-Id","root=1-xxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx;sampled=0"),d instanceof Error)return n.statusCode=400,n.setHeader("x-amzn-errortype","InvalidRequestContentException"),n.end(J(d.message));let m=z(s["x-amz-client-context"]);if(m instanceof Error)return n.setHeader("x-amzn-errortype","InvalidRequestContentException"),n.statusCode=400,n.end(Q);let h=new ae(n);if(l){let p=l.url?.stream??{};try{let g=await l.invoke(d,p,m,h);g&&h.endWithJson(g)}catch(g){n.writableFinished||h.endWithError(g)}}else{let{region:p,accountId:g}=t.aws;n.statusCode=404,n.end(K(a,p,g))}}});var it=t=>[Ze(t),nt(t),rt(t),Ye(t),st(t),Ge(t),et(t)];var me=process.cwd(),Rn=3,En=1024,In={IS_OFFLINE:!0,IS_LOCAL:!0,AWS_SAM_LOCAL:!0},An=me.split(L.sep)[0],kn=new RegExp(`^.*:${An}`),Pn=t=>kn.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 ot.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,l)=>{let c=`http://localhost:${a}`;b.PINK(`Lambda endpoint: ${c}`),this.endpoints.lambda=c,this.setLambdaEndpointEnvVar&&(this.runtimeConfig.environment.AWS_ENDPOINT_URL_LAMBDA=c,this.aws.environment.AWS_ENDPOINT_URL_LAMBDA=c),await s.load(s.#e);for(let d of s.#e)d.setEnv("LOCAL_PORT",a),d.setEnv("AWS_LAMBDA_RUNTIME_API",`127.0.0.1:${a}`),this.setLambdaEndpointEnvVar&&d.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,l=L.extname(a),c=l.slice(1),d=L.resolve(a.replace(l,"")),m=n.getFunction(e),h=m.runtime??r,p={name:e,runtime:m.runtime??r,handlerPath:a,handlerName:c,esEntryPoint:d,memorySize:o.memorySize??this.runtimeConfig.memorySize??En,timeout:o.timeout??this.runtimeConfig.timeout??Rn,sqs:[],ddb:[],environment:{AWS_EXECUTION_ENV:`AWS_Lambda_${h}`,AWS_LAMBDA_FUNCTION_VERSION:"$LATEST",AWS_LAMBDA_FUNCTION_NAME:e,_HANDLER:L.basename(a),...this.runtimeConfig.environment,...o.environment,...In},invoke:async(g,y)=>{let f=this.getHandlerByName(`/@invoke/${e}`);if(f)return await f.invoke(g,y);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.19",
|
|
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",
|