serverless-aws-lambda
Version:
AWS Application Load Balancer and API Gateway - Lambda dev tool for Serverless. Allows Express synthax in handlers. Supports packaging, local invoking and offline ALB, APG, S3, SNS, SQS, DynamoDB Stream server mocking.
39 lines (38 loc) • 11.9 kB
JavaScript
;var R=Object.defineProperty;var H=Object.getOwnPropertyDescriptor;var q=Object.getOwnPropertyNames;var z=Object.prototype.hasOwnProperty;var J=(t,e,s)=>e in t?R(t,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):t[e]=s;var W=(t,e)=>{for(var s in e)R(t,s,{get:e[s],enumerable:!0})},_=(t,e,s,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of q(e))!z.call(t,a)&&a!==s&&R(t,a,{get:()=>e[a],enumerable:!(n=H(e,a))||n.enumerable});return t};var G=t=>_(R({},"__esModule",{value:!0}),t);var $=(t,e,s)=>J(t,typeof e!="symbol"?e+"":e,s);var w=(t,e,s)=>new Promise((n,a)=>{var l=f=>{try{u(s.next(f))}catch(c){a(c)}},i=f=>{try{u(s.throw(f))}catch(c){a(c)}},u=f=>f.done?n(f.value):Promise.resolve(f.value).then(l,i);u((s=s.apply(t,e)).next())});var Z={};W(Z,{default:()=>K,snsPlugin:()=>D});module.exports=G(Z);var v=require("crypto");var T=require("crypto");var N=(t,e,s)=>{switch(t){case"=":return e==s;case">":return e>s;case"<":return e<s;case">=":return e>=s;case"<=":return e>=s;default:return!1}},j={exists:(t,e,s)=>{if(s===!0)return e in t;if(s===!1)return!(e in t);throw new Error("stream filter 'exists' value must be 'true' or 'false'")},prefix:(t,e,s)=>{if(typeof s!="string")throw new Error("SQS filter 'prefix' value must be typeof 'string'");let n=typeof t[e]=="string"?t[e]:void 0;return n?n.startsWith(s):!1},numeric:(t,e,s)=>{if(!Array.isArray(s)||![2,4].includes(s.length))throw new Error("SQS filter 'numeric' value must be an array with 2 or 4 items");if(!(e in t))return!1;let n=[],[a,l]=s;if(n.push(N(a,t[e],l)),s.length==4){let[,,i,u]=s;n.push(N(i,t[e],u))}return n.every(i=>i===!0)},"anything-but":(t,e,s)=>{if(!Array.isArray(s)||!s.every(a=>typeof a=="string"))throw new Error("SQS filter 'anything-but' value must be an array of string");let n=typeof t[e]=="string"?t[e]:void 0;return n?!s.includes(n):!1}},Y=(t,e,s)=>{let n=typeof s;if(n=="string"||n===null)return t[e]==s;if(n=="object"&&!Array.isArray(s)){let a=[];for(let[l,i]of Object.entries(s))l in j&&a.push(j[l](t,e,i));return a.every(l=>l===!0)}return!1},P=(t,e)=>{let s=[];for(let[n,a]of Object.entries(t)){let l=[];Array.isArray(a)?l=a.map(i=>Y(e,n,i)):e[n]&&(l=[P(a,e[n])]),s.push(l.some(i=>i===!0))}return s.every(n=>n===!0)};var m=class t extends Error{constructor({Code:s,Message:n,SenderFault:a}){super(n);$(this,"Code");$(this,"SenderFault",!0);this.Code=s,typeof a=="boolean"&&(this.SenderFault=a)}toXml(s){return t.genericErrorResponse({RequestId:s,Code:this.Code,Message:this.message,SenderFault:this.SenderFault})}static genericErrorResponse({RequestId:s,Code:n,Message:a,SenderFault:l}){return`<?xml version="1.0"?>
<ErrorResponse xmlns="http://sns.amazonaws.com/doc/2010-03-31/">
<Error>
<Type>${l?"Sender":"Server"}</Type>
<Code>${n!=null?n:"UnknownOperation"}</Code>
<Message>${a}</Message>
</Error>
<RequestId>${s}</RequestId>
</ErrorResponse>`}};var Q=new Set(["Binary","Number","String"]),F=t=>{let e={},s={},n={},a=new Set([]);for(let l of t){let[i,u,...f]=l.split("=");if(i.startsWith("MessageAttributes")){let[c,r,o,d,g]=i.split(".");if(d=="Name")s[u]={Type:"",Value:""},n[o]=u;else if(d=="Value")if(g=="DataType")s[n[o]].Type=u;else{let M=n[o];if(a.has(M))throw new m({Code:"ParameterValueInvalid",Message:`Message attribute name '${M}' has multiple values.`});let p=[u,...f].join("="),h=s[M].Type;if(p){if(h=="Binary"&&g=="StringValue")throw new m({Code:"ParameterValueInvalid",Message:`The message attribute '${M}' with type 'Binary' must use field 'Binary'.`});if((h=="String"||h=="Number")&&g=="BinaryValue")throw new m({Code:"ParameterValueInvalid",Message:`The message attribute '${M}' with type '${h}' must use field 'String'.`})}s[M].Value=p,a.add(M)}}else e[i]=[u,...f].join("=")}return Object.keys(s).length&&(V(s),e.MessageAttributes=s),e},X=t=>{for(let e of t)if(t.filter(s=>s==e).length>1)throw new m({Code:"BatchEntryIdsNotDistinct",Message:"Two or more batch entries in the request have the same Id."})},V=t=>{for(let[e,s]of Object.entries(t)){let{Type:n,Value:a}=s;if(!Q.has(n))throw new m({Code:"ParameterValueInvalid",Message:`The message attribute '${e}' has an invalid message attribute type, the set of supported type prefixes is Binary, Number, and String.`});if((n=="String"||n=="Number")&&!a)throw new m({Code:"ParameterValueInvalid",Message:`The message attribute '${e}' must contain non-empty message attribute value for message attribute type '${n}'.`});if(n=="Number"&&isNaN(a))throw new m({Code:"ParameterValueInvalid",Message:`Could not cast message attribute '${e}' value to number.`})}},k=t=>{var f;let e={},s=[],n=(0,T.randomUUID)(),a=[],l=[],i=new Map,u=new Set([]);for(let c of t){let[r,o]=c.split("=");if(r.startsWith("PublishBatchRequestEntries")){let[,,d,g,M,p,h,S]=r.split("."),y=i.get(d);if(y){if(g=="Message"||g=="MessageStructure"||g=="Subject"||g=="Id")y.value[g]=o;else if(g=="MessageAttributes"){let b=y.attributes[p];if(b)if(S=="DataType")y.value.MessageAttributes[b].Type=o;else{let I=`${d}-${b}`;if(u.has(I))throw new m({Code:"ParameterValueInvalid",Message:`Message attribute name '${b}' has multiple values.`});let[,...L]=c.split("="),B=L.join("="),A=y.value.MessageAttributes[b].Type;if(B){if(A=="Binary"&&S=="StringValue")throw new m({Code:"ParameterValueInvalid",Message:`The message attribute '${b}' with type 'Binary' must use field 'Binary'.`});if((A=="String"||A=="Number")&&S=="BinaryValue")throw new m({Code:"ParameterValueInvalid",Message:`The message attribute '${b}' with type '${A}' must use field 'String'.`})}y.value.MessageAttributes[b].Value=B,u.add(I)}else y.attributes[p]=o,y.value.MessageAttributes?y.value.MessageAttributes[o]={}:y.value.MessageAttributes={[o]:{}}}}else{let b={attributes:{},value:{}};g=="Message"||g=="MessageStructure"||g=="Subject"||g=="Id"?b.value[g]=o:g=="MessageAttributes"&&(b.attributes[p]=o,b.value.MessageAttributes={[o]:{}}),i.set(d,b)}}else e[r]=o}for(let c of i.values()){let r={Type:"Notification",MessageId:(0,T.randomUUID)(),TopicArn:e.TopicArn,Subject:(f=c.value.Subject)!=null?f:null,Timestamp:new Date().toISOString(),SignatureVersion:"1",Signature:"fake",SigningCertUrl:"fake",UnsubscribeUrl:"fake",MessageStructure:c.value.MessageStructure};"Message"in c.value&&(r.Message=c.value.Message),c.value.MessageAttributes&&(r.MessageAttributes=c.value.MessageAttributes);let o={EventSource:"aws:sns",EventVersion:"1.0",EventSubscriptionArn:`${e.TopicArn}:${n}`,Sns:r};try{O(r),delete r.MessageStructure,a.push(o)}catch(d){d instanceof m&&l.push({Id:c.value.Id,Code:d.Code,SenderFault:d.SenderFault,Message:d.message})}finally{s.push(c.value.Id)}}return X(s),a.forEach(c=>{c.Sns.MessageAttributes&&V(c.Sns.MessageAttributes)}),{Records:a,Ids:s,Failed:l}},O=t=>{if(!("Message"in t))throw new m({Code:"ValidationError",Message:"1 validation error detected: Value null at 'message' failed to satisfy constraint: Member must not be null"});if(t.Message=="")throw new m({Code:"InvalidParameter",Message:"Invalid parameter: Empty message"});if(t.MessageStructure=="json"){try{t.Message=JSON.parse(t.Message)}catch(s){throw new m({Code:"InvalidParameter",Message:"Invalid parameter: Message Structure - Failed to parse JSON"})}let e=typeof t.Message.default;if(e=="number"||e=="boolean"||t.Message.default===null)t.Message=String(t.Message.default);else if(e=="string")t.Message=t.Message.default;else throw new m({Code:"InvalidParameter",Message:"Invalid parameter: Message Structure - No default entry in JSON message body"})}},E=(t,e)=>{var s;return O(t),{Records:[{EventSource:"aws:sns",EventVersion:"1.0",EventSubscriptionArn:t.TopicArn,Sns:{Type:"Notification",MessageId:e,TopicArn:t.TopicArn,Subject:(s=t.Subject)!=null?s:null,Message:t.Message,Timestamp:new Date().toISOString(),SignatureVersion:"1",Signature:"fake",SigningCertUrl:"fake",UnsubscribeUrl:"fake",MessageAttributes:t.MessageAttributes}}]}},C=(t,e)=>{let s=t.TopicArn.split(":"),n=s[s.length-1],a=[];return e.forEach(l=>{let i=l.sns.find(u=>{if(!u||u.name!==n)return!1;if(!u.filter)return!0;let f={};if(u.filterScope=="MessageAttributes"){if(!t.MessageAttributes)return!1;for(let[c,r]of Object.entries(t.MessageAttributes))f[c]=r.Value}else if(u.filterScope=="MessageBody"){if(t.MessageStructure!="json"||!t.Message)return!1;try{f=JSON.parse(t.Message)}catch(c){}}return P(u.filter,f)});i&&a.push({handler:l,event:i})}),a},x=(t,e)=>`<PublishResponse xmlns="http://sns.amazonaws.com/doc/2010-03-31/">
<PublishResult>
<MessageId>${t}</MessageId>
</PublishResult>
<ResponseMetadata>
<RequestId>${e}</RequestId>
</ResponseMetadata>
</PublishResponse>`,U=(t,e,s)=>{let n="<Successful/>",a="<Failed/>";return e.length&&(n=`<Successful>
${e.map(i=>`<member>
<MessageId>${i.MessageId}</MessageId>
<Id>${i.Id}</Id>
</member>`).join(`
`)}
</Successful>`),s.length&&(a=`<Failed>
${s.map(i=>`<member>
<Code>${i.Code}</Code>
<SenderFault>${i.SenderFault}</SenderFault>
<Id>${i.Id}</Id>
<Message>${i.Message}</Message>
</member>`).join(`
`)}
</Failed>`),`<PublishBatchResponse xmlns="http://sns.amazonaws.com/doc/2010-03-31/">
<PublishBatchResult>
${a}
${n}
</PublishBatchResult>
<ResponseMetadata>
<RequestId>${t}</RequestId>
</ResponseMetadata>
</PublishBatchResponse>`};var D=()=>({name:"sns-plugin",offline:{request:[{method:"POST",filter:"/@sns/parsed",callback:function(t,e){return w(this,null,function*(){var c;let s=Buffer.alloc(0),n=(0,v.randomUUID)(),a=(c=t.headers["amz-sdk-invocation-id"])!=null?c:(0,v.randomUUID)();t.on("data",r=>{s+=r});let l=yield new Promise(r=>{t.on("end",()=>w(this,null,function*(){r(JSON.parse(s.toString()))}))}),i=C(l,this.lambdas),u=[];if(i.length){let r=E(l,n);i.forEach(o=>{u.find(d=>d.handler.name==o.handler.name)||u.push(o)});for(let{handler:o,event:d}of u){let g=`SNS: ${d.name}`;d.displayName&&(g+=` | ${d.displayName}`),console.log(`\x1B[35m${g}\x1B[0m`);try{yield o.invoke(r,{kind:"sns",event:d})}catch(M){console.log(M)}}}e.statusCode=200,e.setHeader("Content-Type","text/xml");let f=x(n,a);e.end(f)})}},{method:"POST",filter:"/@sns",callback:function(t,e){return w(this,null,function*(){var f,c;let s=Buffer.alloc(0),n=(0,v.randomUUID)(),a=(f=t.headers["amz-sdk-invocation-id"])!=null?f:(0,v.randomUUID)(),l=r=>{var o,d;e.statusCode=400,r instanceof m?e.end(r.toXml(a)):e.end(m.genericErrorResponse({RequestId:a,Message:(d=(o=r.toString)==null?void 0:o.call(r))!=null?d:"Unknown error"}))};e.setHeader("Content-Type","text/xml"),e.setHeader("x-amzn-requestid",(0,v.randomUUID)()),t.on("data",r=>{s+=r});let i=yield new Promise(r=>{t.on("end",()=>w(this,null,function*(){var o;r((o=decodeURIComponent(s.toString()))==null?void 0:o.split("&"))}))}),u=(c=i.find(r=>r.startsWith("Action=")))==null?void 0:c.split("=")[1];if(u)if(u=="Publish")try{let r=F(i),o=C(r,this.lambdas),d=[],g=E(r,n);if(o.length){o.forEach(p=>{d.find(h=>h.handler.name==p.handler.name)||d.push(p)});for(let{handler:p,event:h}of d){let S=`SNS: ${h.name}`;h.displayName&&(S+=` | ${h.displayName}`),console.log(`\x1B[35m${S}\x1B[0m`);try{yield p.invoke(g,{kind:"sns",event:h})}catch(y){console.log(y)}}}e.statusCode=200;let M=x(n,a);e.end(M)}catch(r){l(r)}else if(u=="PublishBatch")try{let r=k(i),o=[],d=r.Failed,g=[];r.Records.forEach((p,h)=>{let S=r.Ids[h];o.push({Id:S,MessageId:p.Sns.MessageId});let y=C(p.Sns,this.lambdas);y.length&&y.forEach(b=>{g.find(I=>I.handler.name==b.handler.name)||g.push(b)})}),e.statusCode=200;let M=U(a,o,d);e.end(M);for(let{handler:p,event:h}of g)try{yield p.invoke({Records:r.Records},{kind:"sns",event:h})}catch(S){console.log(S)}}catch(r){l(r)}else e.statusCode=400,e.end(m.genericErrorResponse({RequestId:a,Message:`Action "${u}" is currently not supported`}))})}}]}}),K=D;0&&(module.exports={snsPlugin});