@wraps.dev/cli 2.18.12 → 2.18.14
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 +107 -37
- package/dist/cli.js.map +1 -1
- package/dist/console/assets/index-CXXcMD9d.css +1 -0
- package/dist/console/assets/index-XbwVYQLu.js +127 -0
- package/dist/console/index.html +2 -2
- package/dist/lambda/event-processor/.bundled +1 -1
- package/dist/lambda/event-processor/index.js +2 -2
- package/dist/lambda/event-processor/index.ts +2 -0
- package/dist/lambda/inbound-processor/.bundled +1 -1
- package/dist/lambda/inbound-processor/index.js +39 -39
- package/dist/lambda/inbound-processor/index.ts +3 -0
- package/dist/lambda/sms-event-processor/.bundled +1 -1
- package/dist/lambda/sms-event-processor/index.js +2 -2
- package/package.json +23 -23
- package/dist/console/assets/index-BGDIROiI.css +0 -1
- package/dist/console/assets/index-dD2Skj3E.js +0 -127
package/dist/console/index.html
CHANGED
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
href="https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap"
|
|
12
12
|
rel="stylesheet"
|
|
13
13
|
>
|
|
14
|
-
<script type="module" crossorigin src="/assets/index-
|
|
15
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
14
|
+
<script type="module" crossorigin src="/assets/index-XbwVYQLu.js"></script>
|
|
15
|
+
<link rel="stylesheet" crossorigin href="/assets/index-CXXcMD9d.css">
|
|
16
16
|
</head>
|
|
17
17
|
<body>
|
|
18
18
|
<div id="root"></div>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Built at: 2026-04-
|
|
1
|
+
Built at: 2026-04-16T17:20:24.065Z
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var ye=Object.create;var _=Object.defineProperty;var Te=Object.getOwnPropertyDescriptor;var Ee=Object.getOwnPropertyNames;var be=Object.getPrototypeOf,we=Object.prototype.hasOwnProperty;var I=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),ve=(t,e)=>{for(var n in e)_(t,n,{get:e[n],enumerable:!0})},z=(t,e,n,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Ee(e))!we.call(t,r)&&r!==n&&_(t,r,{get:()=>e[r],enumerable:!(s=Te(e,r))||s.enumerable});return t};var X=(t,e,n)=>(n=t!=null?ye(be(t)):{},z(e||!t||!t.__esModule?_(n,"default",{value:t,enumerable:!0}):n,t)),Ae=t=>z(_({},"__esModule",{value:!0}),t);var G=I(l=>{"use strict";l.HttpAuthLocation=void 0;(function(t){t.HEADER="header",t.QUERY="query"})(l.HttpAuthLocation||(l.HttpAuthLocation={}));l.HttpApiKeyAuthLocation=void 0;(function(t){t.HEADER="header",t.QUERY="query"})(l.HttpApiKeyAuthLocation||(l.HttpApiKeyAuthLocation={}));l.EndpointURLScheme=void 0;(function(t){t.HTTP="http",t.HTTPS="https"})(l.EndpointURLScheme||(l.EndpointURLScheme={}));l.AlgorithmId=void 0;(function(t){t.MD5="md5",t.CRC32="crc32",t.CRC32C="crc32c",t.SHA1="sha1",t.SHA256="sha256"})(l.AlgorithmId||(l.AlgorithmId={}));var Se=t=>{let e=[];return t.sha256!==void 0&&e.push({algorithmId:()=>l.AlgorithmId.SHA256,checksumConstructor:()=>t.sha256}),t.md5!=null&&e.push({algorithmId:()=>l.AlgorithmId.MD5,checksumConstructor:()=>t.md5}),{addChecksumAlgorithm(n){e.push(n)},checksumAlgorithms(){return e}}},Ce=t=>{let e={};return t.checksumAlgorithms().forEach(n=>{e[n.algorithmId()]=n.checksumConstructor()}),e},Re=t=>Se(t),ke=t=>Ce(t);l.FieldPosition=void 0;(function(t){t[t.HEADER=0]="HEADER",t[t.TRAILER=1]="TRAILER"})(l.FieldPosition||(l.FieldPosition={}));var He="__smithy_context";l.IniSectionType=void 0;(function(t){t.PROFILE="profile",t.SSO_SESSION="sso-session",t.SERVICES="services"})(l.IniSectionType||(l.IniSectionType={}));l.RequestHandlerProtocol=void 0;(function(t){t.HTTP_0_9="http/0.9",t.HTTP_1_0="http/1.0",t.TDS_8_0="tds/8.0"})(l.RequestHandlerProtocol||(l.RequestHandlerProtocol={}));l.SMITHY_CONTEXT_KEY=He;l.getDefaultClientConfiguration=Re;l.resolveDefaultRuntimeConfig=ke});var Z=I(C=>{"use strict";var De=G(),Ie=t=>({setHttpHandler(e){t.httpHandler=e},httpHandler(){return t.httpHandler},updateHttpClientConfig(e,n){t.httpHandler?.updateHttpClientConfig(e,n)},httpHandlerConfigs(){return t.httpHandler.httpHandlerConfigs()}}),Pe=t=>({httpHandler:t.httpHandler()}),O=class{name;kind;values;constructor({name:e,kind:n=De.FieldPosition.HEADER,values:s=[]}){this.name=e,this.kind=n,this.values=s}add(e){this.values.push(e)}set(e){this.values=e}remove(e){this.values=this.values.filter(n=>n!==e)}toString(){return this.values.map(e=>e.includes(",")||e.includes(" ")?`"${e}"`:e).join(", ")}get(){return this.values}},j=class{entries={};encoding;constructor({fields:e=[],encoding:n="utf-8"}){e.forEach(this.setField.bind(this)),this.encoding=n}setField(e){this.entries[e.name.toLowerCase()]=e}getField(e){return this.entries[e.toLowerCase()]}removeField(e){delete this.entries[e.toLowerCase()]}getByType(e){return Object.values(this.entries).filter(n=>n.kind===e)}},M=class t{method;protocol;hostname;port;path;query;headers;username;password;fragment;body;constructor(e){this.method=e.method||"GET",this.hostname=e.hostname||"localhost",this.port=e.port,this.query=e.query||{},this.headers=e.headers||{},this.body=e.body,this.protocol=e.protocol?e.protocol.slice(-1)!==":"?`${e.protocol}:`:e.protocol:"https:",this.path=e.path?e.path.charAt(0)!=="/"?`/${e.path}`:e.path:"/",this.username=e.username,this.password=e.password,this.fragment=e.fragment}static clone(e){let n=new t({...e,headers:{...e.headers}});return n.query&&(n.query=xe(n.query)),n}static isInstance(e){if(!e)return!1;let n=e;return"method"in n&&"protocol"in n&&"hostname"in n&&"path"in n&&typeof n.query=="object"&&typeof n.headers=="object"}clone(){return t.clone(this)}};function xe(t){return Object.keys(t).reduce((e,n)=>{let s=t[n];return{...e,[n]:Array.isArray(s)?[...s]:s}},{})}var q=class{statusCode;reason;headers;body;constructor(e){this.statusCode=e.statusCode,this.reason=e.reason,this.headers=e.headers||{},this.body=e.body}static isInstance(e){if(!e)return!1;let n=e;return typeof n.statusCode=="number"&&typeof n.headers=="object"}};function _e(t){return/^[a-z0-9][a-z0-9\.\-]*[a-z0-9]$/.test(t)}C.Field=O;C.Fields=j;C.HttpRequest=M;C.HttpResponse=q;C.getHttpHandlerExtensionConfiguration=Ie;C.isValidHostname=_e;C.resolveHttpHandlerRuntimeConfig=Pe});var te=I(B=>{"use strict";var ee=t=>encodeURIComponent(t).replace(/[!'()*]/g,Le),Le=t=>`%${t.charCodeAt(0).toString(16).toUpperCase()}`,Ue=t=>t.split("/").map(ee).join("/");B.escapeUri=ee;B.escapeUriPath=Ue});var se=I(ne=>{"use strict";var F=te();function Ne(t){let e=[];for(let n of Object.keys(t).sort()){let s=t[n];if(n=F.escapeUri(n),Array.isArray(s))for(let r=0,i=s.length;r<i;r++)e.push(`${n}=${F.escapeUri(s[r])}`);else{let r=n;(s||typeof s=="string")&&(r+=`=${F.escapeUri(s)}`),e.push(r)}}return e.join("&")}ne.buildQueryString=Ne});var me=I(P=>{"use strict";var ae=Z(),ue=se(),L=require("node:https"),de=require("node:stream"),Q=require("node:http2");function N(t){let e=t&&typeof t=="object"&&"reason"in t?t.reason:void 0;if(e){if(e instanceof Error){let r=new Error("Request aborted");return r.name="AbortError",r.cause=e,r}let s=new Error(String(e));return s.name="AbortError",s}let n=new Error("Request aborted");return n.name="AbortError",n}var $e=["ECONNRESET","EPIPE","ETIMEDOUT"],le=t=>{let e={};for(let n of Object.keys(t)){let s=t[n];e[n]=Array.isArray(s)?s.join(","):s}return e},E={setTimeout:(t,e)=>setTimeout(t,e),clearTimeout:t=>clearTimeout(t)},oe=1e3,Oe=(t,e,n=0)=>{if(!n)return-1;let s=r=>{let i=E.setTimeout(()=>{t.destroy(),e(Object.assign(new Error(`@smithy/node-http-handler - the request socket did not establish a connection with the server within the configured timeout of ${n} ms.`),{name:"TimeoutError"}))},n-r),c=u=>{u?.connecting?u.on("connect",()=>{E.clearTimeout(i)}):E.clearTimeout(i)};t.socket?c(t.socket):t.on("socket",c)};return n<2e3?(s(0),0):E.setTimeout(s.bind(null,oe),oe)},je=(t,e,n=0,s,r)=>n?E.setTimeout(()=>{let i=`@smithy/node-http-handler - [${s?"ERROR":"WARN"}] a request has exceeded the configured ${n} ms requestTimeout.`;if(s){let c=Object.assign(new Error(i),{name:"TimeoutError",code:"ETIMEDOUT"});t.destroy(c),e(c)}else i+=" Init client requestHandler with throwOnRequestTimeout=true to turn this into an error.",r?.warn?.(i)},n):-1,Me=3e3,qe=(t,{keepAlive:e,keepAliveMsecs:n},s=Me)=>{if(e!==!0)return-1;let r=()=>{t.socket?t.socket.setKeepAlive(e,n||0):t.on("socket",i=>{i.setKeepAlive(e,n||0)})};return s===0?(r(),0):E.setTimeout(r,s)},re=3e3,Be=(t,e,n=0)=>{let s=r=>{let i=n-r,c=()=>{t.destroy(),e(Object.assign(new Error(`@smithy/node-http-handler - the request socket timed out after ${n} ms of inactivity (configured by client requestHandler).`),{name:"TimeoutError"}))};t.socket?(t.socket.setTimeout(i,c),t.on("close",()=>t.socket?.removeListener("timeout",c))):t.setTimeout(i,c)};return 0<n&&n<6e3?(s(0),0):E.setTimeout(s.bind(null,n===0?0:re),re)},ie=6e3;async function fe(t,e,n=ie,s=!1){let r=e.headers??{},i=r.Expect||r.expect,c=-1,u=!0;!s&&i==="100-continue"&&(u=await Promise.race([new Promise(a=>{c=Number(E.setTimeout(()=>a(!0),Math.max(ie,n)))}),new Promise(a=>{t.on("continue",()=>{E.clearTimeout(c),a(!0)}),t.on("response",()=>{E.clearTimeout(c),a(!1)}),t.on("error",()=>{E.clearTimeout(c),a(!1)})})])),u&&Fe(t,e.body)}function Fe(t,e){if(e instanceof de.Readable){e.pipe(t);return}if(e){let n=Buffer.isBuffer(e);if(n||typeof e=="string"){n&&e.byteLength===0?t.end():t.end(e);return}let r=e;if(typeof r=="object"&&r.buffer&&typeof r.byteOffset=="number"&&typeof r.byteLength=="number"){t.end(Buffer.from(r.buffer,r.byteOffset,r.byteLength));return}t.end(Buffer.from(e));return}t.end()}var Qe=0,U,ce,W=class t{config;configProvider;socketWarningTimestamp=0;externalAgent=!1;metadata={handlerProtocol:"http/1.1"};static create(e){return typeof e?.handle=="function"?e:new t(e)}static checkSocketUsage(e,n,s=console){let{sockets:r,requests:i,maxSockets:c}=e;if(typeof c!="number"||c===1/0||Date.now()-15e3<n)return n;if(r&&i)for(let a in r){let m=r[a]?.length??0,o=i[a]?.length??0;if(m>=c&&o>=2*c)return s?.warn?.(`@smithy/node-http-handler:WARN - socket usage at capacity=${m} and ${o} additional requests are enqueued.
|
|
2
2
|
See https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/node-configuring-maxsockets.html
|
|
3
|
-
or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler config.`),Date.now()}return n}constructor(e){this.configProvider=new Promise((n,s)=>{typeof e=="function"?e().then(r=>{n(this.resolveDefaultConfig(r))}).catch(s):n(this.resolveDefaultConfig(e))})}resolveDefaultConfig(e){let{requestTimeout:n,connectionTimeout:s,socketTimeout:r,socketAcquisitionWarningTimeout:c,httpAgent:i,httpsAgent:u,throwOnRequestTimeout:a,logger:y}=e||{},o=!0,f=50;return{connectionTimeout:s,requestTimeout:n,socketTimeout:r,socketAcquisitionWarningTimeout:c,throwOnRequestTimeout:a,httpAgent:i instanceof _.Agent||typeof i?.destroy=="function"?(this.externalAgent=!0,i):new _.Agent({keepAlive:o,maxSockets:f,...i}),httpsAgent:u instanceof U.Agent||typeof u?.destroy=="function"?(this.externalAgent=!0,u):new U.Agent({keepAlive:o,maxSockets:f,...u}),logger:y}}destroy(){this.config?.httpAgent?.destroy(),this.config?.httpsAgent?.destroy()}async handle(e,{abortSignal:n,requestTimeout:s}={}){return this.config||(this.config=await this.configProvider),new Promise((r,c)=>{let i=this.config,u,a=[],y=async l=>{await u,a.forEach(E.clearTimeout),r(l)},o=async l=>{await u,a.forEach(E.clearTimeout),c(l)};if(n?.aborted){let l=N(n);o(l);return}let f=e.protocol==="https:",b=e.headers??{},A=(b.Expect??b.expect)==="100-continue",C=f?i.httpsAgent:i.httpAgent;A&&!this.externalAgent&&(C=new(f?U.Agent:_.Agent)({keepAlive:!1,maxSockets:1/0})),a.push(E.setTimeout(()=>{this.socketWarningTimestamp=t.checkSocketUsage(C,this.socketWarningTimestamp,i.logger)},i.socketAcquisitionWarningTimeout??(i.requestTimeout??2e3)+(i.connectionTimeout??1e3)));let k=ce.buildQueryString(e.query||{}),R;if(e.username!=null||e.password!=null){let l=e.username??"",p=e.password??"";R=`${l}:${p}`}let H=e.path;k&&(H+=`?${k}`),e.fragment&&(H+=`#${e.fragment}`);let h=e.hostname??"";h[0]==="["&&h.endsWith("]")?h=e.hostname.slice(1,-1):h=e.hostname;let T={headers:e.headers,host:h,method:e.method,path:H,port:e.port,agent:C,auth:R},m=(f?U.request:_.request)(T,l=>{let p=new ie.HttpResponse({statusCode:l.statusCode||-1,reason:l.statusMessage,headers:ue(l.headers),body:l});y({response:p})});if(m.on("error",l=>{Ne.includes(l.code)?o(Object.assign(l,{name:"TimeoutError"})):o(l)}),n){let l=()=>{m.destroy();let p=N(n);o(p)};if(typeof n.addEventListener=="function"){let p=n;p.addEventListener("abort",l,{once:!0}),m.once("close",()=>p.removeEventListener("abort",l))}else n.onabort=l}let v=s??i.requestTimeout;a.push($e(m,o,i.connectionTimeout)),a.push(Oe(m,o,v,i.throwOnRequestTimeout,i.logger??console)),a.push(Be(m,o,i.socketTimeout));let D=T.agent;typeof D=="object"&&"keepAlive"in D&&a.push(Me(m,{keepAlive:D.keepAlive,keepAliveMsecs:D.keepAliveMsecs})),u=de(m,e,v,this.externalAgent).catch(l=>(a.forEach(E.clearTimeout),c(l)))})}updateHttpClientConfig(e,n){this.config=void 0,this.configProvider=this.configProvider.then(s=>({...s,[e]:n}))}httpHandlerConfigs(){return this.config??{}}},K=class{sessions=[];constructor(e){this.sessions=e??[]}poll(){if(this.sessions.length>0)return this.sessions.shift()}offerLast(e){this.sessions.push(e)}contains(e){return this.sessions.includes(e)}remove(e){this.sessions=this.sessions.filter(n=>n!==e)}[Symbol.iterator](){return this.sessions[Symbol.iterator]()}destroy(e){for(let n of this.sessions)n===e&&(n.destroyed||n.destroy())}},J=class{constructor(e){if(this.config=e,this.config.maxConcurrency&&this.config.maxConcurrency<=0)throw new RangeError("maxConcurrency must be greater than zero.")}config;sessionCache=new Map;lease(e,n){let s=this.getUrlString(e),r=this.sessionCache.get(s);if(r){let a=r.poll();if(a&&!this.config.disableConcurrency)return a}let c=Q.connect(s);this.config.maxConcurrency&&c.settings({maxConcurrentStreams:this.config.maxConcurrency},a=>{if(a)throw new Error("Fail to set maxConcurrentStreams to "+this.config.maxConcurrency+"when creating new session for "+e.destination.toString())}),c.unref();let i=()=>{c.destroy(),this.deleteSession(s,c)};c.on("goaway",i),c.on("error",i),c.on("frameError",i),c.on("close",()=>this.deleteSession(s,c)),n.requestTimeout&&c.setTimeout(n.requestTimeout,i);let u=this.sessionCache.get(s)||new K;return u.offerLast(c),this.sessionCache.set(s,u),c}deleteSession(e,n){let s=this.sessionCache.get(e);s&&s.contains(n)&&(s.remove(n),this.sessionCache.set(e,s))}release(e,n){let s=this.getUrlString(e);this.sessionCache.get(s)?.offerLast(n)}destroy(){for(let[e,n]of this.sessionCache){for(let s of n)s.destroyed||s.destroy(),n.remove(s);this.sessionCache.delete(e)}}setMaxConcurrentStreams(e){if(e&&e<=0)throw new RangeError("maxConcurrentStreams must be greater than zero.");this.config.maxConcurrency=e}setDisableConcurrentStreams(e){this.config.disableConcurrency=e}getUrlString(e){return e.destination.toString()}},V=class t{config;configProvider;metadata={handlerProtocol:"h2"};connectionManager=new J({});static create(e){return typeof e?.handle=="function"?e:new t(e)}constructor(e){this.configProvider=new Promise((n,s)=>{typeof e=="function"?e().then(r=>{n(r||{})}).catch(s):n(e||{})})}destroy(){this.connectionManager.destroy()}async handle(e,{abortSignal:n,requestTimeout:s}={}){this.config||(this.config=await this.configProvider,this.connectionManager.setDisableConcurrentStreams(this.config.disableConcurrentStreams||!1),this.config.maxConcurrentStreams&&this.connectionManager.setMaxConcurrentStreams(this.config.maxConcurrentStreams));let{requestTimeout:r,disableConcurrentStreams:c}=this.config,i=s??r;return new Promise((u,a)=>{let y=!1,o,f=async g=>{await o,u(g)},b=async g=>{await o,a(g)};if(n?.aborted){y=!0;let g=N(n);b(g);return}let{hostname:A,method:C,port:k,protocol:R,query:H}=e,h="";if(e.username!=null||e.password!=null){let g=e.username??"",w=e.password??"";h=`${g}:${w}@`}let T=`${R}//${h}${A}${k?`:${k}`:""}`,x={destination:new URL(T)},m=this.connectionManager.lease(x,{requestTimeout:this.config?.sessionTimeout,disableConcurrentStreams:c||!1}),v=g=>{c&&this.destroySession(m),y=!0,b(g)},D=ce.buildQueryString(H||{}),l=e.path;D&&(l+=`?${D}`),e.fragment&&(l+=`#${e.fragment}`);let p=m.request({...e.headers,[Q.constants.HTTP2_HEADER_PATH]:l,[Q.constants.HTTP2_HEADER_METHOD]:C});if(m.ref(),p.on("response",g=>{let w=new ie.HttpResponse({statusCode:g[":status"]||-1,headers:ue(g),body:p});y=!0,f({response:w}),c&&(m.close(),this.connectionManager.deleteSession(T,m))}),i&&p.setTimeout(i,()=>{p.close();let g=new Error(`Stream timed out because of no activity for ${i} ms`);g.name="TimeoutError",v(g)}),n){let g=()=>{p.close();let w=N(n);v(w)};if(typeof n.addEventListener=="function"){let w=n;w.addEventListener("abort",g,{once:!0}),p.once("close",()=>w.removeEventListener("abort",g))}else n.onabort=g}p.on("frameError",(g,w,he)=>{v(new Error(`Frame type id ${g} in stream id ${he} has failed with code ${w}.`))}),p.on("error",v),p.on("aborted",()=>{v(new Error(`HTTP/2 stream is abnormally aborted in mid-communication with result code ${p.rstCode}.`))}),p.on("close",()=>{m.unref(),c&&m.destroy(),y||v(new Error("Unexpected error: http2 request did not get a response"))}),o=de(p,e,i)})}updateHttpClientConfig(e,n){this.config=void 0,this.configProvider=this.configProvider.then(s=>({...s,[e]:n}))}httpHandlerConfigs(){return this.config??{}}destroySession(e){e.destroyed||e.destroy()}},Y=class extends ae.Writable{bufferedBytes=[];_write(e,n,s){this.bufferedBytes.push(e),s()}},Qe=t=>We(t)?Ke(t):new Promise((e,n)=>{let s=new Y;t.pipe(s),t.on("error",r=>{s.end(),n(r)}),s.on("error",n),s.on("finish",function(){let r=new Uint8Array(Buffer.concat(this.bufferedBytes));e(r)})}),We=t=>typeof ReadableStream=="function"&&t instanceof ReadableStream;async function Ke(t){let e=[],n=t.getReader(),s=!1,r=0;for(;!s;){let{done:u,value:a}=await n.read();a&&(e.push(a),r+=a.length),s=u}let c=new Uint8Array(r),i=0;for(let u of e)c.set(u,i),i+=u.length;return c}P.DEFAULT_REQUEST_TIMEOUT=Fe;P.NodeHttp2Handler=V;P.NodeHttpHandler=W;P.streamCollector=Qe});var ze={};be(ze,{handler:()=>Ye});module.exports=ve(ze);var fe=require("node:crypto"),$=require("@aws-sdk/client-dynamodb"),me=we(le(),1),Je={requestHandler:new me.NodeHttpHandler({requestTimeout:1e4,connectionTimeout:5e3}),maxAttempts:5},Ve=new $.DynamoDBClient(Je);async function Ye(t,e){let n=e.awsRequestId,s=(0,fe.randomUUID)().slice(0,8),r=(a,y)=>{console.info(JSON.stringify({requestId:n,batchId:s,msg:a,...y}))},c=(a,y,o)=>{console.error(JSON.stringify({requestId:n,batchId:s,msg:a,error:String(y),...o}))};r("Processing SES batch",{recordCount:t.Records.length});let i=process.env.TABLE_NAME;if(!i)throw new Error("TABLE_NAME environment variable not set");let u=Number.parseInt(process.env.RETENTION_DAYS||"90",10);for(let a of t.Records)try{let o=JSON.parse(a.body).detail,f=o.eventType||o.notificationType,b=o.mail,A=b.messageId,C=new Date(b.timestamp).getTime(),k=b.source,R=b.destination||[],H=b.commonHeaders?.subject||"";r("Processing email event",{messageId:A,eventType:f,recipientCount:R.length});let h={},T=C;if(f==="Send"&&o.send)h={tags:b.tags||{}};else if(f==="Delivery"&&o.delivery)T=new Date(o.delivery.timestamp).getTime(),h={timestamp:o.delivery.timestamp,processingTimeMillis:o.delivery.processingTimeMillis,recipients:o.delivery.recipients,smtpResponse:o.delivery.smtpResponse,remoteMtaIp:o.delivery.remoteMtaIp};else if(f==="Open"&&o.open)T=new Date(o.open.timestamp).getTime(),h={timestamp:o.open.timestamp,userAgent:o.open.userAgent,ipAddress:o.open.ipAddress};else if(f==="Click"&&o.click)T=new Date(o.click.timestamp).getTime(),h={timestamp:o.click.timestamp,link:o.click.link,linkTags:o.click.linkTags||{},userAgent:o.click.userAgent,ipAddress:o.click.ipAddress};else if(f==="Bounce"&&o.bounce){let m=o.bounce.bounceSubType;m==="Suppressed"||m==="OnAccountSuppressionList"?(f="Suppressed",T=new Date(o.bounce.timestamp).getTime(),h={reason:m,suppressedRecipients:o.bounce.bouncedRecipients,timestamp:o.bounce.timestamp,feedbackId:o.bounce.feedbackId}):(T=new Date(o.bounce.timestamp).getTime(),h={bounceType:o.bounce.bounceType,bounceSubType:o.bounce.bounceSubType,bouncedRecipients:o.bounce.bouncedRecipients,timestamp:o.bounce.timestamp,feedbackId:o.bounce.feedbackId})}else f==="Complaint"&&o.complaint?(T=new Date(o.complaint.timestamp).getTime(),h={complainedRecipients:o.complaint.complainedRecipients,timestamp:o.complaint.timestamp,feedbackId:o.complaint.feedbackId,complaintFeedbackType:o.complaint.complaintFeedbackType,userAgent:o.complaint.userAgent}):f==="Reject"&&o.reject?h={reason:o.reject.reason}:f==="Rendering Failure"&&o.failure?h={errorMessage:o.failure.errorMessage,templateName:o.failure.templateName}:f==="DeliveryDelay"&&o.deliveryDelay?(T=new Date(o.deliveryDelay.timestamp).getTime(),h={timestamp:o.deliveryDelay.timestamp,delayType:o.deliveryDelay.delayType,expirationTime:o.deliveryDelay.expirationTime,delayedRecipients:o.deliveryDelay.delayedRecipients}):f==="Subscription"&&o.subscription&&(T=new Date(o.subscription.timestamp).getTime(),h={contactList:o.subscription.contactList,timestamp:o.subscription.timestamp,source:o.subscription.source,newTopicPreferences:o.subscription.newTopicPreferences,oldTopicPreferences:o.subscription.oldTopicPreferences});let x=u>0?Date.now()+u*24*60*60*1e3:Date.now()+365*24*60*60*1e3;await Ve.send(new $.PutItemCommand({TableName:i,Item:{messageId:{S:A},sentAt:{N:T.toString()},accountId:{S:process.env.AWS_ACCOUNT_ID||"unknown"},from:{S:k},to:{L:R.map(m=>({S:m}))},subject:{S:H},eventType:{S:f},eventData:{S:JSON.stringify(o)},additionalData:{S:JSON.stringify(h)},createdAt:{N:Date.now().toString()},expiresAt:{N:x.toString()}}})),r("Stored event",{eventType:f,messageId:A})}catch(y){c("Error processing record",y,{sqsMessageId:a.messageId})}return{statusCode:200,body:JSON.stringify({message:"Events processed successfully"})}}0&&(module.exports={handler});
|
|
3
|
+
or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler config.`),Date.now()}return n}constructor(e){this.configProvider=new Promise((n,s)=>{typeof e=="function"?e().then(r=>{n(this.resolveDefaultConfig(r))}).catch(s):n(this.resolveDefaultConfig(e))})}destroy(){this.config?.httpAgent?.destroy(),this.config?.httpsAgent?.destroy()}async handle(e,{abortSignal:n,requestTimeout:s}={}){this.config||(this.config=await this.configProvider);let r=this.config,i=e.protocol==="https:";return!i&&!this.config.httpAgent&&(this.config.httpAgent=await this.config.httpAgentProvider()),new Promise((c,u)=>{let a,m=[],o=async f=>{await a,m.forEach(E.clearTimeout),c(f)},d=async f=>{await a,m.forEach(E.clearTimeout),u(f)};if(n?.aborted){let f=N(n);d(f);return}let b=e.headers??{},v=(b.Expect??b.expect)==="100-continue",S=i?r.httpsAgent:r.httpAgent;v&&!this.externalAgent&&(S=new(i?L.Agent:U)({keepAlive:!1,maxSockets:1/0})),m.push(E.setTimeout(()=>{this.socketWarningTimestamp=t.checkSocketUsage(S,this.socketWarningTimestamp,r.logger)},r.socketAcquisitionWarningTimeout??(r.requestTimeout??2e3)+(r.connectionTimeout??1e3)));let R=ue.buildQueryString(e.query||{}),k;if(e.username!=null||e.password!=null){let f=e.username??"",g=e.password??"";k=`${f}:${g}`}let H=e.path;R&&(H+=`?${R}`),e.fragment&&(H+=`#${e.fragment}`);let p=e.hostname??"";p[0]==="["&&p.endsWith("]")?p=e.hostname.slice(1,-1):p=e.hostname;let T={headers:e.headers,host:p,method:e.method,path:H,port:e.port,agent:S,auth:k},h=(i?L.request:ce)(T,f=>{let g=new ae.HttpResponse({statusCode:f.statusCode||-1,reason:f.statusMessage,headers:le(f.headers),body:f});o({response:g})});if(h.on("error",f=>{$e.includes(f.code)?d(Object.assign(f,{name:"TimeoutError"})):d(f)}),n){let f=()=>{h.destroy();let g=N(n);d(g)};if(typeof n.addEventListener=="function"){let g=n;g.addEventListener("abort",f,{once:!0}),h.once("close",()=>g.removeEventListener("abort",f))}else n.onabort=f}let A=s??r.requestTimeout;m.push(Oe(h,d,r.connectionTimeout)),m.push(je(h,d,A,r.throwOnRequestTimeout,r.logger??console)),m.push(Be(h,d,r.socketTimeout));let D=T.agent;typeof D=="object"&&"keepAlive"in D&&m.push(qe(h,{keepAlive:D.keepAlive,keepAliveMsecs:D.keepAliveMsecs})),a=fe(h,e,A,this.externalAgent).catch(f=>(m.forEach(E.clearTimeout),u(f)))})}updateHttpClientConfig(e,n){this.config=void 0,this.configProvider=this.configProvider.then(s=>({...s,[e]:n}))}httpHandlerConfigs(){return this.config??{}}resolveDefaultConfig(e){let{requestTimeout:n,connectionTimeout:s,socketTimeout:r,socketAcquisitionWarningTimeout:i,httpAgent:c,httpsAgent:u,throwOnRequestTimeout:a,logger:m}=e||{},o=!0,d=50;return{connectionTimeout:s,requestTimeout:n,socketTimeout:r,socketAcquisitionWarningTimeout:i,throwOnRequestTimeout:a,httpAgentProvider:async()=>{let{Agent:b,request:v}=await import("node:http");return ce=v,U=b,c instanceof U||typeof c?.destroy=="function"?(this.externalAgent=!0,c):new U({keepAlive:o,maxSockets:d,...c})},httpsAgent:u instanceof L.Agent||typeof u?.destroy=="function"?(this.externalAgent=!0,u):new L.Agent({keepAlive:o,maxSockets:d,...u}),logger:m}}},K=class{sessions=[];constructor(e){this.sessions=e??[]}poll(){if(this.sessions.length>0)return this.sessions.shift()}offerLast(e){this.sessions.push(e)}contains(e){return this.sessions.includes(e)}remove(e){this.sessions=this.sessions.filter(n=>n!==e)}[Symbol.iterator](){return this.sessions[Symbol.iterator]()}destroy(e){for(let n of this.sessions)n===e&&(n.destroyed||n.destroy())}},J=class{constructor(e){if(this.config=e,this.config.maxConcurrency&&this.config.maxConcurrency<=0)throw new RangeError("maxConcurrency must be greater than zero.")}config;sessionCache=new Map;lease(e,n){let s=this.getUrlString(e),r=this.sessionCache.get(s);if(r){let a=r.poll();if(a&&!this.config.disableConcurrency)return a}let i=Q.connect(s);this.config.maxConcurrency&&i.settings({maxConcurrentStreams:this.config.maxConcurrency},a=>{if(a)throw new Error("Fail to set maxConcurrentStreams to "+this.config.maxConcurrency+"when creating new session for "+e.destination.toString())}),i.unref();let c=()=>{i.destroy(),this.deleteSession(s,i)};i.on("goaway",c),i.on("error",c),i.on("frameError",c),i.on("close",()=>this.deleteSession(s,i)),n.requestTimeout&&i.setTimeout(n.requestTimeout,c);let u=this.sessionCache.get(s)||new K;return u.offerLast(i),this.sessionCache.set(s,u),i}deleteSession(e,n){let s=this.sessionCache.get(e);s&&s.contains(n)&&(s.remove(n),this.sessionCache.set(e,s))}release(e,n){let s=this.getUrlString(e);this.sessionCache.get(s)?.offerLast(n)}destroy(){for(let[e,n]of this.sessionCache){for(let s of n)s.destroyed||s.destroy(),n.remove(s);this.sessionCache.delete(e)}}setMaxConcurrentStreams(e){if(e&&e<=0)throw new RangeError("maxConcurrentStreams must be greater than zero.");this.config.maxConcurrency=e}setDisableConcurrentStreams(e){this.config.disableConcurrency=e}getUrlString(e){return e.destination.toString()}},V=class t{config;configProvider;metadata={handlerProtocol:"h2"};connectionManager=new J({});static create(e){return typeof e?.handle=="function"?e:new t(e)}constructor(e){this.configProvider=new Promise((n,s)=>{typeof e=="function"?e().then(r=>{n(r||{})}).catch(s):n(e||{})})}destroy(){this.connectionManager.destroy()}async handle(e,{abortSignal:n,requestTimeout:s}={}){this.config||(this.config=await this.configProvider,this.connectionManager.setDisableConcurrentStreams(this.config.disableConcurrentStreams||!1),this.config.maxConcurrentStreams&&this.connectionManager.setMaxConcurrentStreams(this.config.maxConcurrentStreams));let{requestTimeout:r,disableConcurrentStreams:i}=this.config,c=s??r;return new Promise((u,a)=>{let m=!1,o,d=async y=>{await o,u(y)},b=async y=>{await o,a(y)};if(n?.aborted){m=!0;let y=N(n);b(y);return}let{hostname:v,method:S,port:R,protocol:k,query:H}=e,p="";if(e.username!=null||e.password!=null){let y=e.username??"",w=e.password??"";p=`${y}:${w}@`}let T=`${k}//${p}${v}${R?`:${R}`:""}`,x={destination:new URL(T)},h=this.connectionManager.lease(x,{requestTimeout:this.config?.sessionTimeout,disableConcurrentStreams:i||!1}),A=y=>{i&&this.destroySession(h),m=!0,b(y)},D=ue.buildQueryString(H||{}),f=e.path;D&&(f+=`?${D}`),e.fragment&&(f+=`#${e.fragment}`);let g=h.request({...e.headers,[Q.constants.HTTP2_HEADER_PATH]:f,[Q.constants.HTTP2_HEADER_METHOD]:S});if(h.ref(),g.on("response",y=>{let w=new ae.HttpResponse({statusCode:y[":status"]||-1,headers:le(y),body:g});m=!0,d({response:w}),i&&(h.close(),this.connectionManager.deleteSession(T,h))}),c&&g.setTimeout(c,()=>{g.close();let y=new Error(`Stream timed out because of no activity for ${c} ms`);y.name="TimeoutError",A(y)}),n){let y=()=>{g.close();let w=N(n);A(w)};if(typeof n.addEventListener=="function"){let w=n;w.addEventListener("abort",y,{once:!0}),g.once("close",()=>w.removeEventListener("abort",y))}else n.onabort=y}g.on("frameError",(y,w,ge)=>{A(new Error(`Frame type id ${y} in stream id ${ge} has failed with code ${w}.`))}),g.on("error",A),g.on("aborted",()=>{A(new Error(`HTTP/2 stream is abnormally aborted in mid-communication with result code ${g.rstCode}.`))}),g.on("close",()=>{h.unref(),i&&h.destroy(),m||A(new Error("Unexpected error: http2 request did not get a response"))}),o=fe(g,e,c)})}updateHttpClientConfig(e,n){this.config=void 0,this.configProvider=this.configProvider.then(s=>({...s,[e]:n}))}httpHandlerConfigs(){return this.config??{}}destroySession(e){e.destroyed||e.destroy()}},Y=class extends de.Writable{bufferedBytes=[];_write(e,n,s){this.bufferedBytes.push(e),s()}},We=t=>Ke(t)?Je(t):new Promise((e,n)=>{let s=new Y;t.pipe(s),t.on("error",r=>{s.end(),n(r)}),s.on("error",n),s.on("finish",function(){let r=new Uint8Array(Buffer.concat(this.bufferedBytes));e(r)})}),Ke=t=>typeof ReadableStream=="function"&&t instanceof ReadableStream;async function Je(t){let e=[],n=t.getReader(),s=!1,r=0;for(;!s;){let{done:u,value:a}=await n.read();a&&(e.push(a),r+=a.length),s=u}let i=new Uint8Array(r),c=0;for(let u of e)i.set(u,c),c+=u.length;return i}P.DEFAULT_REQUEST_TIMEOUT=Qe;P.NodeHttp2Handler=V;P.NodeHttpHandler=W;P.streamCollector=We});var Xe={};ve(Xe,{handler:()=>ze});module.exports=Ae(Xe);var he=require("node:crypto"),$=require("@aws-sdk/client-dynamodb"),pe=X(me(),1),Ve={requestHandler:new pe.NodeHttpHandler({requestTimeout:1e4,connectionTimeout:5e3}),maxAttempts:5},Ye=new $.DynamoDBClient(Ve);async function ze(t,e){let n=e.awsRequestId,s=(0,he.randomUUID)().slice(0,8),r=(a,m)=>{console.info(JSON.stringify({requestId:n,batchId:s,msg:a,...m}))},i=(a,m,o)=>{console.error(JSON.stringify({requestId:n,batchId:s,msg:a,error:String(m),...o}))};r("Processing SES batch",{recordCount:t.Records.length});let c=process.env.TABLE_NAME;if(!c)throw new Error("TABLE_NAME environment variable not set");let u=Number.parseInt(process.env.RETENTION_DAYS||"90",10);for(let a of t.Records)try{let o=JSON.parse(a.body).detail,d=o.eventType||o.notificationType,b=o.mail,v=b.messageId,S=new Date(b.timestamp).getTime(),R=b.source,k=b.destination||[],H=b.commonHeaders?.subject||"";r("Processing email event",{messageId:v,eventType:d,recipientCount:k.length});let p={},T=S;if(d==="Send"&&o.send)p={tags:b.tags||{}};else if(d==="Delivery"&&o.delivery)T=new Date(o.delivery.timestamp).getTime(),p={timestamp:o.delivery.timestamp,processingTimeMillis:o.delivery.processingTimeMillis,recipients:o.delivery.recipients,smtpResponse:o.delivery.smtpResponse,remoteMtaIp:o.delivery.remoteMtaIp};else if(d==="Open"&&o.open)T=new Date(o.open.timestamp).getTime(),p={timestamp:o.open.timestamp,userAgent:o.open.userAgent,ipAddress:o.open.ipAddress};else if(d==="Click"&&o.click)T=new Date(o.click.timestamp).getTime(),p={timestamp:o.click.timestamp,link:o.click.link,linkTags:o.click.linkTags||{},userAgent:o.click.userAgent,ipAddress:o.click.ipAddress};else if(d==="Bounce"&&o.bounce){let h=o.bounce.bounceSubType;h==="Suppressed"||h==="OnAccountSuppressionList"?(d="Suppressed",T=new Date(o.bounce.timestamp).getTime(),p={reason:h,suppressedRecipients:o.bounce.bouncedRecipients,timestamp:o.bounce.timestamp,feedbackId:o.bounce.feedbackId}):(T=new Date(o.bounce.timestamp).getTime(),p={bounceType:o.bounce.bounceType,bounceSubType:o.bounce.bounceSubType,bouncedRecipients:o.bounce.bouncedRecipients,timestamp:o.bounce.timestamp,feedbackId:o.bounce.feedbackId})}else d==="Complaint"&&o.complaint?(T=new Date(o.complaint.timestamp).getTime(),p={complainedRecipients:o.complaint.complainedRecipients,timestamp:o.complaint.timestamp,feedbackId:o.complaint.feedbackId,complaintFeedbackType:o.complaint.complaintFeedbackType,userAgent:o.complaint.userAgent}):d==="Reject"&&o.reject?p={reason:o.reject.reason}:d==="Rendering Failure"&&o.failure?p={errorMessage:o.failure.errorMessage,templateName:o.failure.templateName}:d==="DeliveryDelay"&&o.deliveryDelay?(T=new Date(o.deliveryDelay.timestamp).getTime(),p={timestamp:o.deliveryDelay.timestamp,delayType:o.deliveryDelay.delayType,expirationTime:o.deliveryDelay.expirationTime,delayedRecipients:o.deliveryDelay.delayedRecipients}):d==="Subscription"&&o.subscription&&(T=new Date(o.subscription.timestamp).getTime(),p={contactList:o.subscription.contactList,timestamp:o.subscription.timestamp,source:o.subscription.source,newTopicPreferences:o.subscription.newTopicPreferences,oldTopicPreferences:o.subscription.oldTopicPreferences});let x=u>0?Date.now()+u*24*60*60*1e3:Date.now()+365*24*60*60*1e3;await Ye.send(new $.PutItemCommand({TableName:c,Item:{messageId:{S:v},sentAt:{N:T.toString()},mailSentAt:{N:S.toString()},accountId:{S:process.env.AWS_ACCOUNT_ID||"unknown"},from:{S:R},to:{L:k.map(h=>({S:h}))},subject:{S:H},eventType:{S:d},eventData:{S:JSON.stringify(o)},additionalData:{S:JSON.stringify(p)},createdAt:{N:Date.now().toString()},expiresAt:{N:x.toString()}}})),r("Stored event",{eventType:d,messageId:v})}catch(m){i("Error processing record",m,{sqsMessageId:a.messageId})}return{statusCode:200,body:JSON.stringify({message:"Events processed successfully"})}}0&&(module.exports={handler});
|
|
@@ -187,6 +187,7 @@ export async function handler(event: SQSEvent, context: Context) {
|
|
|
187
187
|
|
|
188
188
|
// Store event in DynamoDB
|
|
189
189
|
// Use eventTimestamp as sort key to ensure each event type creates a unique record
|
|
190
|
+
// mailSentAt preserves the original mail send time for display (sentAt is the event timestamp for DynamoDB key uniqueness)
|
|
190
191
|
// Note: DynamoDB String Sets (SS) cannot be empty, so we use a List (L) for recipients
|
|
191
192
|
await dynamodb.send(
|
|
192
193
|
new PutItemCommand({
|
|
@@ -194,6 +195,7 @@ export async function handler(event: SQSEvent, context: Context) {
|
|
|
194
195
|
Item: {
|
|
195
196
|
messageId: { S: messageId },
|
|
196
197
|
sentAt: { N: eventTimestamp.toString() },
|
|
198
|
+
mailSentAt: { N: mailTimestamp.toString() },
|
|
197
199
|
accountId: { S: process.env.AWS_ACCOUNT_ID || "unknown" },
|
|
198
200
|
from: { S: from },
|
|
199
201
|
to: { L: to.map((email: string) => ({ S: email })) },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Built at: 2026-04-
|
|
1
|
+
Built at: 2026-04-16T17:20:24.172Z
|