@wraps.dev/cli 2.14.4 → 2.14.5
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.js +46 -12
- package/dist/cli.js.map +1 -1
- package/dist/lambda/event-processor/.bundled +1 -1
- package/dist/lambda/event-processor/index.js +1 -1
- package/dist/lambda/event-processor/index.ts +1 -1
- package/dist/lambda/inbound-processor/.bundled +1 -1
- package/dist/lambda/inbound-processor/index.js +1 -1
- package/dist/lambda/inbound-processor/index.ts +1 -1
- package/dist/lambda/sms-event-processor/.bundled +1 -1
- package/dist/lambda/sms-event-processor/index.js +1 -1
- package/dist/lambda/sms-event-processor/index.ts +13 -14
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
Built at: 2026-02-
|
|
1
|
+
Built at: 2026-02-19T23:01:22.606Z
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var b=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var N=Object.getOwnPropertyNames;var R=Object.prototype.hasOwnProperty;var E=(s,i)=>{for(var c in i)b(s,c,{get:i[c],enumerable:!0})},C=(s,i,c,l)=>{if(i&&typeof i=="object"||typeof i=="function")for(let o of N(i))!R.call(s,o)&&o!==c&&b(s,o,{get:()=>i[o],enumerable:!(l=A(i,o))||l.enumerable});return s};var O=s=>C(b({},"__esModule",{value:!0}),s);var x={};E(x,{handler:()=>h});module.exports=O(x);var S=require("node:crypto"),u=require("@aws-sdk/client-dynamodb"),M=new u.DynamoDBClient({});async function h(s,i){let c=i.awsRequestId,l=(0,S.randomUUID)().slice(0,8),o=(a,p)=>{console.
|
|
1
|
+
"use strict";var b=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var N=Object.getOwnPropertyNames;var R=Object.prototype.hasOwnProperty;var E=(s,i)=>{for(var c in i)b(s,c,{get:i[c],enumerable:!0})},C=(s,i,c,l)=>{if(i&&typeof i=="object"||typeof i=="function")for(let o of N(i))!R.call(s,o)&&o!==c&&b(s,o,{get:()=>i[o],enumerable:!(l=A(i,o))||l.enumerable});return s};var O=s=>C(b({},"__esModule",{value:!0}),s);var x={};E(x,{handler:()=>h});module.exports=O(x);var S=require("node:crypto"),u=require("@aws-sdk/client-dynamodb"),M=new u.DynamoDBClient({});async function h(s,i){let c=i.awsRequestId,l=(0,S.randomUUID)().slice(0,8),o=(a,p)=>{console.info(JSON.stringify({requestId:c,batchId:l,msg:a,...p}))},v=(a,p,e)=>{console.error(JSON.stringify({requestId:c,batchId:l,msg:a,error:String(p),...e}))};o("Processing SES batch",{recordCount:s.Records.length});let y=process.env.TABLE_NAME;if(!y)throw new Error("TABLE_NAME environment variable not set");let f=Number.parseInt(process.env.RETENTION_DAYS||"90",10);for(let a of s.Records)try{let e=JSON.parse(a.body).detail,t=e.eventType||e.notificationType,m=e.mail,g=m.messageId,D=new Date(m.timestamp).getTime(),w=m.source,T=m.destination||[],k=m.commonHeaders?.subject||"";o("Processing email event",{messageId:g,eventType:t,recipientCount:T.length});let n={},r=D;if(t==="Send"&&e.send)n={tags:m.tags||{}};else if(t==="Delivery"&&e.delivery)r=new Date(e.delivery.timestamp).getTime(),n={timestamp:e.delivery.timestamp,processingTimeMillis:e.delivery.processingTimeMillis,recipients:e.delivery.recipients,smtpResponse:e.delivery.smtpResponse,remoteMtaIp:e.delivery.remoteMtaIp};else if(t==="Open"&&e.open)r=new Date(e.open.timestamp).getTime(),n={timestamp:e.open.timestamp,userAgent:e.open.userAgent,ipAddress:e.open.ipAddress};else if(t==="Click"&&e.click)r=new Date(e.click.timestamp).getTime(),n={timestamp:e.click.timestamp,link:e.click.link,linkTags:e.click.linkTags||{},userAgent:e.click.userAgent,ipAddress:e.click.ipAddress};else if(t==="Bounce"&&e.bounce){let d=e.bounce.bounceSubType;d==="Suppressed"||d==="OnAccountSuppressionList"?(t="Suppressed",r=new Date(e.bounce.timestamp).getTime(),n={reason:d,suppressedRecipients:e.bounce.bouncedRecipients,timestamp:e.bounce.timestamp,feedbackId:e.bounce.feedbackId}):(r=new Date(e.bounce.timestamp).getTime(),n={bounceType:e.bounce.bounceType,bounceSubType:e.bounce.bounceSubType,bouncedRecipients:e.bounce.bouncedRecipients,timestamp:e.bounce.timestamp,feedbackId:e.bounce.feedbackId})}else t==="Complaint"&&e.complaint?(r=new Date(e.complaint.timestamp).getTime(),n={complainedRecipients:e.complaint.complainedRecipients,timestamp:e.complaint.timestamp,feedbackId:e.complaint.feedbackId,complaintFeedbackType:e.complaint.complaintFeedbackType,userAgent:e.complaint.userAgent}):t==="Reject"&&e.reject?n={reason:e.reject.reason}:t==="Rendering Failure"&&e.failure?n={errorMessage:e.failure.errorMessage,templateName:e.failure.templateName}:t==="DeliveryDelay"&&e.deliveryDelay?(r=new Date(e.deliveryDelay.timestamp).getTime(),n={timestamp:e.deliveryDelay.timestamp,delayType:e.deliveryDelay.delayType,expirationTime:e.deliveryDelay.expirationTime,delayedRecipients:e.deliveryDelay.delayedRecipients}):t==="Subscription"&&e.subscription&&(r=new Date(e.subscription.timestamp).getTime(),n={contactList:e.subscription.contactList,timestamp:e.subscription.timestamp,source:e.subscription.source,newTopicPreferences:e.subscription.newTopicPreferences,oldTopicPreferences:e.subscription.oldTopicPreferences});let I=f>0?Date.now()+f*24*60*60*1e3:Date.now()+365*24*60*60*1e3;await M.send(new u.PutItemCommand({TableName:y,Item:{messageId:{S:g},sentAt:{N:r.toString()},accountId:{S:process.env.AWS_ACCOUNT_ID||"unknown"},from:{S:w},to:{L:T.map(d=>({S:d}))},subject:{S:k},eventType:{S:t},eventData:{S:JSON.stringify(e)},additionalData:{S:JSON.stringify(n)},createdAt:{N:Date.now().toString()},expiresAt:{N:I.toString()}}})),o("Stored event",{eventType:t,messageId:g})}catch(p){v("Error processing record",p,{sqsMessageId:a.messageId})}return{statusCode:200,body:JSON.stringify({message:"Events processed successfully"})}}0&&(module.exports={handler});
|
|
@@ -24,7 +24,7 @@ export async function handler(event: SQSEvent, context: Context) {
|
|
|
24
24
|
const batchId = randomUUID().slice(0, 8);
|
|
25
25
|
|
|
26
26
|
const log = (msg: string, data?: Record<string, unknown>) => {
|
|
27
|
-
console.
|
|
27
|
+
console.info(JSON.stringify({ requestId, batchId, msg, ...data }));
|
|
28
28
|
};
|
|
29
29
|
const logError = (
|
|
30
30
|
msg: string,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Built at: 2026-02-
|
|
1
|
+
Built at: 2026-02-19T23:01:22.691Z
|
|
@@ -66,7 +66,7 @@ ${W0(e.cont)}`}}function rc(e,x){return x.map((t,i,{length:u})=>Ec(e,t,i===u-1))
|
|
|
66
66
|
`),this.textAsHtml=u.textAsHtml=x.map(a=>this.textToHtml(a)).join(`<br/>
|
|
67
67
|
`)),u}processChunk(x,t){let i=null;switch(x._parentBoundary&&(i=this._getPartId(x._parentBoundary)),x.type){case"node":{let u=this.createNode(x);if(u===this.tree&&(["subject","references","date","to","from","to","cc","bcc","message-id","in-reply-to","reply-to"].forEach(a=>{u.headers.has(a)&&(this[a.replace(/-([a-z])/g,(r,E)=>E.toUpperCase())]=u.headers.get(a))}),this.emit("headers",u.headers),u.headerLines&&this.emit("headerLines",u.headerLines)),x.contentType==="message/rfc822"&&x.messageNode)break;if(x.parentNode&&x.parentNode.contentType==="message/rfc822"&&(u.showMeta=!0),u.isAttachment){let a=u.contentType;u.contentType==="application/octet-stream"&&x.filename&&(a=this.libmime.detectMimeType(x.filename)||"application/octet-stream");let r={type:"attachment",content:null,contentType:a,partId:i,release:()=>{r.release=null,this.waitUntilAttachmentEnd&&typeof this.attachmentCallback=="function"&&setImmediate(this.attachmentCallback),this.attachmentCallback=!1,this.waitUntilAttachmentEnd=!1}},E=this.options.checksumAlgo||"md5",n=new V1(r,E);if(u.decoder.on("error",s=>{n.emit("error",s)}),u.decoder.on("readable",()=>{let s;for(;(s=u.decoder.read())!==null;)n.write(s)}),u.decoder.once("end",()=>{n.end()}),r.content=n,this.waitUntilAttachmentEnd=!0,x.disposition&&(r.contentDisposition=x.disposition),x.filename&&(r.filename=x.filename),u.headers.has("content-id")){r.contentId=[].concat(u.headers.get("content-id")||[]).shift(),r.cid=r.contentId.trim().replace(/^<|>$/g,"").trim();let s=u;for(;s=s.parent;)s.contentType==="multipart/related"&&(r.related=!0)}r.headers=u.headers,this.push(r),this.attachmentList.push(r)}else if(u.disposition==="inline"){let a=[],r=0;if(u.contentStream=u.decoder,u.contentType==="text/plain"?this.hasText=!0:u.contentType==="text/html"?this.hasHtml=!0:u.contentType==="message/delivery-status"&&!this.options.keepDeliveryStatus&&(this.hasText=!0),u.node.flowed){let n=u.contentStream,s=new H1({delSp:u.node.delSp});n.on("error",o=>{s.emit("error",o)}),n.pipe(s),u.contentStream=s}let E=u.charset||"utf-8";if(!["ascii","usascii","utf8"].includes(E.toLowerCase().replace(/[^a-z0-9]+/g,"")))try{let n=u.contentStream,s=this.decoder.decodeStream(E);n.on("error",o=>{s.emit("error",o)}),n.pipe(s),u.contentStream=s}catch{}u.contentStream.on("readable",()=>{let n;for(;(n=u.contentStream.read())!==null;)typeof n=="string"&&(n=Buffer.from(n)),a.push(n),r+=n.length}),u.contentStream.once("end",()=>{u.textContent=Buffer.concat(a,r).toString().replace(/\r?\n/g,`
|
|
68
68
|
`)}),u.contentStream.once("error",n=>{this.emit("error",n)})}break}case"data":if(this.curnode&&this.curnode.decoder&&this.curnode.decoder.end(),this.waitUntilAttachmentEnd){this.attachmentCallback=t;return}break;case"body":if(this.curnode&&this.curnode.decoder&&this.curnode.decoder.writable&&this.curnode.decoder.write(x.value)===!1)return this.curnode.decoder.once("drain",t);break}setImmediate(t)}_getPartId(x){let t=this.boundaries.findIndex(u=>u.name===x);t===-1?(this.boundaries.push({name:x,count:1}),t=this.boundaries.length-1):this.boundaries[t].count++;let i="1";for(let u=0;u<=t;u++)u===0?i=this.boundaries[u].count.toString():i+="."+this.boundaries[u].count.toString();return i}getAddressesHTML(x){let t=i=>i.map(u=>{let a='<span class="mp_address_group">';if(u.name&&(a+='<span class="mp_address_name">'+U0.encode(u.name)+(u.group?": ":"")+"</span>"),u.address){let r='<a href="mailto:'+U0.encode(u.address)+'" class="mp_address_email">'+U0.encode(u.address)+"</a>";u.name?a+=" <"+r+">":a+=r}return u.group&&(a+=t(u.group)+";"),a+"</span>"}).join(", ");return t([].concat(x||[]))}getAddressesText(x){let t=i=>i.map(u=>{let a="";if(u.name&&(a+=`"${u.name}"`+(u.group?": ":"")),u.address){let r=u.address;u.name?a+=" <"+r+">":a+=r}return u.group&&(a+=t(u.group)+";"),a}).join(", ");return t([].concat(x||[]))}updateImageLinks(x,t){if(!this.html)return setImmediate(()=>t(null,!1));let i=new Map,u=(this.html||"").toString();if(this.options.skipImageLinks)return t(null,u);u.replace(/\bcid:([^'"\s]{1,256})/g,(n,s)=>{for(let o=0,c=this.attachmentList.length;o<c;o++)if(this.attachmentList[o].cid===s&&/^image\/[\w]+$/i.test(this.attachmentList[o].contentType)){i.set(s,{attachment:this.attachmentList[o]});break}return n});let a=[];i.forEach(n=>{a.push(n)});let r=0,E=()=>{if(r>=a.length)return u=u.replace(/\bcid:([^'"\s]{1,256})/g,(s,o)=>i.has(o)&&i.get(o).url?i.get(o).url:s),t(null,u);let n=a[r++];x(n.attachment,(s,o)=>{if(s)return setImmediate(()=>t(s));n.url=o,setImmediate(E)})};setImmediate(E)}textToHtml(x){if(this.options.skipTextToHtml)return"";x=(x||"").toString();let t,i=!1;if(!this.options.skipTextLinks)try{if(Kt.pretest(x)){i=!0;let a=Kt.match(x)||[],r=[],E=0;a.forEach(s=>{if(E<s.index){let o=U0.encode(x.slice(E,s.index),{useNamedReferences:!0});r.push(o)}r.push(`<a href="${s.url}">${s.text}</a>`),E=s.lastIndex});let n=U0.encode(x.slice(E),{useNamedReferences:!0});r.push(n),t=r.join("")}}catch{}return i||(t=U0.encode(x,{useNamedReferences:!0})),"<p>"+t.replace(/\r?\n/g,`
|
|
69
|
-
`).trim().replace(/[ \t]+$/gm,"").trim().replace(/\n\n+/g,"</p><p>").trim().replace(/\n/g,"<br/>")+"</p>"}};V9.exports=Ar});var J9=l((uB,G9)=>{"use strict";var Z1=pr();G9.exports=(e,x,t)=>{if(e==null)throw new TypeError("Input cannot be null or undefined.");!t&&typeof x=="function"&&(t=x,x=!1);let i;t||(i=new Promise((s,o)=>{t=K1(s,o)})),x=x||{};let u=!!x.keepCidLinks,a={attachments:[]},r=new Z1(x);r.on("error",s=>{t(s)}),r.on("headers",s=>{a.headers=s,a.headerLines=r.headerLines});let E=!1,n=()=>{E=!0;let s=r.read();if(s===null){E=!1;return}if(s.type==="text"&&Object.keys(s).forEach(o=>{["text","html","textAsHtml"].includes(o)&&(a[o]=s[o])}),s.type==="attachment"){a.attachments.push(s);let o=[],c=0;s.content.on("readable",()=>{let p;for(;(p=s.content.read())!==null;)o.push(p),c+=p.length}),s.content.on("end",()=>{s.content=Buffer.concat(o,c),s.release(),n()})}else n()};return r.on("readable",()=>{E||n()}),r.on("end",()=>{if(["subject","references","date","to","from","to","cc","bcc","message-id","in-reply-to","reply-to"].forEach(s=>{a.headers&&a.headers.has(s)&&(a[s.replace(/-([a-z])/g,(o,c)=>c.toUpperCase())]=a.headers.get(s))}),u)return t(null,a);r.updateImageLinks((s,o)=>o(!1,"data:"+s.contentType+";base64,"+s.content.toString("base64")),(s,o)=>{if(s)return t(s);a.html=o,t(null,a)})}),typeof e=="string"?r.end(Buffer.from(e)):Buffer.isBuffer(e)?r.end(e):e.once("error",s=>{e.destroy(),r.destroy(),t(s)}).pipe(r),i};function K1(e,x){return function(...t){let i=t.shift();i?x(i):e(...t)}}});var $9=l((aB,W9)=>{"use strict";var Y1=pr(),Q1=J9();W9.exports={MailParser:Y1,simpleParser:Q1}});var tl={};u2(tl,{handler:()=>el});module.exports=r2(tl);var fr=require("node:crypto"),Yt=require("@aws-sdk/client-eventbridge"),hx=require("@aws-sdk/client-s3"),Y9=a2($9(),1),dr=new hx.S3Client({}),X1=new Yt.EventBridgeClient({}),Z9=process.env.BUCKET_NAME,xl=process.env.INBOUND_EVENT_SOURCE||"wraps.inbound",K9=200*1024;async function el(e,x){let t=x.awsRequestId,i=(0,fr.randomUUID)().slice(0,8),u=(r,E)=>{console.
|
|
69
|
+
`).trim().replace(/[ \t]+$/gm,"").trim().replace(/\n\n+/g,"</p><p>").trim().replace(/\n/g,"<br/>")+"</p>"}};V9.exports=Ar});var J9=l((uB,G9)=>{"use strict";var Z1=pr();G9.exports=(e,x,t)=>{if(e==null)throw new TypeError("Input cannot be null or undefined.");!t&&typeof x=="function"&&(t=x,x=!1);let i;t||(i=new Promise((s,o)=>{t=K1(s,o)})),x=x||{};let u=!!x.keepCidLinks,a={attachments:[]},r=new Z1(x);r.on("error",s=>{t(s)}),r.on("headers",s=>{a.headers=s,a.headerLines=r.headerLines});let E=!1,n=()=>{E=!0;let s=r.read();if(s===null){E=!1;return}if(s.type==="text"&&Object.keys(s).forEach(o=>{["text","html","textAsHtml"].includes(o)&&(a[o]=s[o])}),s.type==="attachment"){a.attachments.push(s);let o=[],c=0;s.content.on("readable",()=>{let p;for(;(p=s.content.read())!==null;)o.push(p),c+=p.length}),s.content.on("end",()=>{s.content=Buffer.concat(o,c),s.release(),n()})}else n()};return r.on("readable",()=>{E||n()}),r.on("end",()=>{if(["subject","references","date","to","from","to","cc","bcc","message-id","in-reply-to","reply-to"].forEach(s=>{a.headers&&a.headers.has(s)&&(a[s.replace(/-([a-z])/g,(o,c)=>c.toUpperCase())]=a.headers.get(s))}),u)return t(null,a);r.updateImageLinks((s,o)=>o(!1,"data:"+s.contentType+";base64,"+s.content.toString("base64")),(s,o)=>{if(s)return t(s);a.html=o,t(null,a)})}),typeof e=="string"?r.end(Buffer.from(e)):Buffer.isBuffer(e)?r.end(e):e.once("error",s=>{e.destroy(),r.destroy(),t(s)}).pipe(r),i};function K1(e,x){return function(...t){let i=t.shift();i?x(i):e(...t)}}});var $9=l((aB,W9)=>{"use strict";var Y1=pr(),Q1=J9();W9.exports={MailParser:Y1,simpleParser:Q1}});var tl={};u2(tl,{handler:()=>el});module.exports=r2(tl);var fr=require("node:crypto"),Yt=require("@aws-sdk/client-eventbridge"),hx=require("@aws-sdk/client-s3"),Y9=a2($9(),1),dr=new hx.S3Client({}),X1=new Yt.EventBridgeClient({}),Z9=process.env.BUCKET_NAME,xl=process.env.INBOUND_EVENT_SOURCE||"wraps.inbound",K9=200*1024;async function el(e,x){let t=x.awsRequestId,i=(0,fr.randomUUID)().slice(0,8),u=(r,E)=>{console.info(JSON.stringify({requestId:t,batchId:i,msg:r,...E}))},a=(r,E,n)=>{console.error(JSON.stringify({requestId:t,batchId:i,msg:r,error:String(E),...n}))};u("Processing inbound email batch",{recordCount:e.Records.length});for(let r of e.Records){let E=decodeURIComponent(r.s3.object.key.replace(/\+/g," ")),n=r.s3.bucket.name;try{u("Processing raw email",{bucket:n,key:E});let o=await(await dr.send(new hx.GetObjectCommand({Bucket:n,Key:E}))).Body?.transformToString(),c=await(0,Y9.simpleParser)(o),p=`inb_${(0,fr.randomUUID)().replace(/-/g,"").slice(0,12)}`,B={};if(c.headers)for(let[T,z]of c.headers){let P0=typeof z=="object"&&z!==null&&"text"in z?z.text:String(z);B[T]?B[T]=`${B[T]}, ${P0}`:B[T]=P0}let f=B["x-ses-spam-verdict"]||null,_=B["x-ses-virus-verdict"]||null,X=[];if(c.attachments&&c.attachments.length>0)for(let T=0;T<c.attachments.length;T++){let z=c.attachments[T],P0=`att_${T}`,xi=(z.filename||`attachment_${T}`).replace(/[^a-zA-Z0-9._-]/g,"_"),ge=`attachments/${p}/${P0}-${xi}`;await dr.send(new hx.PutObjectCommand({Bucket:Z9,Key:ge,Body:z.content,ContentType:z.contentType||"application/octet-stream"})),X.push({id:P0,filename:z.filename||`attachment_${T}`,contentType:z.contentType||"application/octet-stream",size:z.size,s3Key:ge,contentDisposition:z.contentDisposition||"attachment",cid:z.cid||null})}let xx=c.html||null,Vx=!1;xx&&xx.length>K9&&(xx=xx.slice(0,K9),Vx=!0);let Qt=c.to?(Array.isArray(c.to)?c.to:[c.to]).flatMap(T=>"value"in T?T.value:[T]).map(T=>({address:T.address||"",name:T.name||""})):[],Xt=c.from?.value?.[0]?{address:c.from.value[0].address||"",name:c.from.value[0].name||""}:{address:"",name:""},ex={emailId:p,messageId:c.messageId||E.replace("raw/",""),from:Xt,to:Qt,cc:c.cc?(Array.isArray(c.cc)?c.cc:[c.cc]).flatMap(T=>"value"in T?T.value:[T]).map(T=>({address:T.address||"",name:T.name||""})):[],subject:c.subject||"",date:c.date?.toISOString()||new Date().toISOString(),html:xx,htmlTruncated:Vx,text:c.text||null,headers:B,attachments:X,spamVerdict:f,virusVerdict:_,rawS3Key:E,receivedAt:new Date().toISOString()};await dr.send(new hx.PutObjectCommand({Bucket:Z9,Key:`parsed/${p}.json`,Body:JSON.stringify(ex),ContentType:"application/json"})),u("Stored parsed email",{emailId:p,attachmentCount:X.length}),await X1.send(new Yt.PutEventsCommand({Entries:[{Source:xl,DetailType:"email.received",Detail:JSON.stringify(ex)}]})),u("Published EventBridge event",{emailId:p})}catch(s){throw a("Error processing inbound email",s,{s3Key:E}),s}}return{statusCode:200,body:JSON.stringify({message:"Inbound emails processed"})}}0&&(module.exports={handler});
|
|
70
70
|
/*! Bundled license information:
|
|
71
71
|
|
|
72
72
|
he/he.js:
|
|
@@ -37,7 +37,7 @@ export async function handler(event: S3Event, context: Context) {
|
|
|
37
37
|
const batchId = randomUUID().slice(0, 8);
|
|
38
38
|
|
|
39
39
|
const log = (msg: string, data?: Record<string, unknown>) => {
|
|
40
|
-
console.
|
|
40
|
+
console.info(JSON.stringify({ requestId, batchId, msg, ...data }));
|
|
41
41
|
};
|
|
42
42
|
const logError = (
|
|
43
43
|
msg: string,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Built at: 2026-02-
|
|
1
|
+
Built at: 2026-02-19T23:01:22.611Z
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var c=Object.defineProperty;var
|
|
1
|
+
"use strict";var c=Object.defineProperty;var y=Object.getOwnPropertyDescriptor;var v=Object.getOwnPropertyNames;var f=Object.prototype.hasOwnProperty;var D=(n,t)=>{for(var o in t)c(n,o,{get:t[o],enumerable:!0})},A=(n,t,o,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let e of v(t))!f.call(n,e)&&e!==o&&c(n,e,{get:()=>t[e],enumerable:!(i=y(t,e))||i.enumerable});return n};var C=n=>A(c({},"__esModule",{value:!0}),n);var _={};D(_,{handler:()=>w});module.exports=C(_);var a=require("@aws-sdk/client-dynamodb"),I=new a.DynamoDBClient({}),T=(n,t)=>console.info(JSON.stringify({msg:n,...t})),R=(n,t,o)=>console.error(JSON.stringify({msg:n,error:String(t),...o}));async function w(n){let t=process.env.TABLE_NAME;if(!t)throw new Error("TABLE_NAME environment variable not set");let o=Number.parseInt(process.env.RETENTION_DAYS||"90",10);for(let i of n.Records)try{let e=JSON.parse(i.body),s=e.eventType||e.messageStatus||"UNKNOWN",m=e.messageId,S=e.destinationPhoneNumber,p=e.originationPhoneNumber,d=e.messageBody||"",g=e.isoCountryCode||"US",E=e.messageType||"TRANSACTIONAL",N=e.eventTimestamp?new Date(e.eventTimestamp).getTime():Date.now();T("Processing SMS event",{messageId:m,eventType:s});let r={isoCountryCode:g,messageType:E};s==="TEXT_DELIVERED"||s==="TEXT_SUCCESSFUL"?r={...r,deliveryTimestamp:e.deliveryTimestamp,carrierName:e.carrierName,providerResponse:e.providerResponse}:s==="TEXT_FAILED"||s==="TEXT_INVALID"||s==="TEXT_CARRIER_UNREACHABLE"||s==="TEXT_BLOCKED"?r={...r,failureReason:e.failureReason||e.statusMessage,failureCode:e.failureCode||e.statusCode,providerResponse:e.providerResponse}:s==="TEXT_QUEUED"||s==="TEXT_SENT"?r={...r,queuedTimestamp:e.queuedTimestamp,sentTimestamp:e.sentTimestamp}:s==="TEXT_TTL_EXPIRED"&&(r={...r,expirationTimestamp:e.expirationTimestamp,ttlSeconds:e.ttlSeconds});let u=d?Math.ceil(d.length/160):1,l=o>0?Date.now()+o*24*60*60*1e3:Date.now()+365*24*60*60*1e3;await I.send(new a.PutItemCommand({TableName:t,Item:{messageId:{S:m},sentAt:{N:N.toString()},accountId:{S:process.env.AWS_ACCOUNT_ID||"unknown"},destinationNumber:{S:S||""},originationNumber:{S:p||""},messageBody:{S:d},eventType:{S:s},segments:{N:u.toString()},eventData:{S:JSON.stringify(e)},additionalData:{S:JSON.stringify(r)},createdAt:{N:Date.now().toString()},expiresAt:{N:l.toString()}}})),T("Stored SMS event",{eventType:s,messageId:m})}catch(e){R("Error processing SMS record",e,{recordId:i.messageId})}return{statusCode:200,body:JSON.stringify({message:"SMS events processed successfully"})}}0&&(module.exports={handler});
|
|
@@ -3,6 +3,14 @@ import type { SQSEvent } from "aws-lambda";
|
|
|
3
3
|
|
|
4
4
|
const dynamodb = new DynamoDBClient({});
|
|
5
5
|
|
|
6
|
+
const log = (msg: string, data?: Record<string, unknown>) =>
|
|
7
|
+
console.info(JSON.stringify({ msg, ...data }));
|
|
8
|
+
const logError = (
|
|
9
|
+
msg: string,
|
|
10
|
+
error: unknown,
|
|
11
|
+
data?: Record<string, unknown>
|
|
12
|
+
) => console.error(JSON.stringify({ msg, error: String(error), ...data }));
|
|
13
|
+
|
|
6
14
|
/**
|
|
7
15
|
* Lambda handler for processing SMS events from SQS (via SNS)
|
|
8
16
|
* Events come from AWS End User Messaging via SNS → SQS (raw message delivery)
|
|
@@ -20,8 +28,6 @@ const dynamodb = new DynamoDBClient({});
|
|
|
20
28
|
* - TEXT_UNKNOWN: Unknown status
|
|
21
29
|
*/
|
|
22
30
|
export async function handler(event: SQSEvent) {
|
|
23
|
-
console.log("Processing SMS event from SQS:", JSON.stringify(event, null, 2));
|
|
24
|
-
|
|
25
31
|
const tableName = process.env.TABLE_NAME;
|
|
26
32
|
if (!tableName) {
|
|
27
33
|
throw new Error("TABLE_NAME environment variable not set");
|
|
@@ -51,12 +57,7 @@ export async function handler(event: SQSEvent) {
|
|
|
51
57
|
? new Date(detail.eventTimestamp).getTime()
|
|
52
58
|
: Date.now();
|
|
53
59
|
|
|
54
|
-
|
|
55
|
-
messageId,
|
|
56
|
-
eventType,
|
|
57
|
-
destinationNumber,
|
|
58
|
-
originationNumber,
|
|
59
|
-
});
|
|
60
|
+
log("Processing SMS event", { messageId, eventType });
|
|
60
61
|
|
|
61
62
|
// Extract additional data based on event type
|
|
62
63
|
let additionalData: Record<string, unknown> = {
|
|
@@ -127,13 +128,11 @@ export async function handler(event: SQSEvent) {
|
|
|
127
128
|
})
|
|
128
129
|
);
|
|
129
130
|
|
|
130
|
-
|
|
131
|
-
`Stored ${eventType} event for message ${messageId}`,
|
|
132
|
-
additionalData
|
|
133
|
-
);
|
|
131
|
+
log("Stored SMS event", { eventType, messageId });
|
|
134
132
|
} catch (error) {
|
|
135
|
-
|
|
136
|
-
|
|
133
|
+
logError("Error processing SMS record", error, {
|
|
134
|
+
recordId: record.messageId,
|
|
135
|
+
});
|
|
137
136
|
// Don't throw - continue processing other records
|
|
138
137
|
}
|
|
139
138
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wraps.dev/cli",
|
|
3
|
-
"version": "2.14.
|
|
3
|
+
"version": "2.14.5",
|
|
4
4
|
"description": "CLI for deploying Wraps email infrastructure to your AWS account",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cli.js",
|
|
@@ -86,8 +86,8 @@
|
|
|
86
86
|
"tsx": "4.20.6",
|
|
87
87
|
"typescript": "^5.9.3",
|
|
88
88
|
"vitest": "^4.0.7",
|
|
89
|
-
"@wraps/
|
|
90
|
-
"@wraps/
|
|
89
|
+
"@wraps/core": "0.1.0",
|
|
90
|
+
"@wraps/email-check": "1.0.0"
|
|
91
91
|
},
|
|
92
92
|
"engines": {
|
|
93
93
|
"node": ">=20.0.0"
|