@ts-cloud/core 0.16.67 → 0.16.68

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.
@@ -79,6 +79,7 @@ export interface ResolvedMailService {
79
79
  junkScore: number;
80
80
  rejectScore: number;
81
81
  dnsbl: boolean;
82
+ dnsblReject: boolean;
82
83
  greylist: boolean;
83
84
  };
84
85
  /** Where received mail is POSTed, when configured. */
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ import{createRequire as Bs}from"node:module";var Ms=Object.defineProperty;var Ls
10
10
  `),E=[p,l,m,await Tt(P)].join(`
11
11
  `),I=await qr(s,u,c,o,E,y??Ue);return h.searchParams.set("X-Amz-Signature",I),{url:h.toString(),method:n,headers:{},body:r||void 0}}function Vr(e){let{url:t,method:n="GET",expiresIn:r=3600,...i}=e,s=Math.min(r,604800);return H({...i,url:t,method:n,signQuery:!0,expiresIn:s}).url}async function Qg(e){let{url:t,method:n="GET",expiresIn:r=3600,...i}=e,s=Math.min(r,604800);return(await Wr({...i,url:t,method:n,signQuery:!0,expiresIn:s})).url}function Ur(e){return Object.keys(e).sort().map((t)=>`${t.toLowerCase()}:${e[t].trim().replace(/\s+/g," ")}`).join(`
12
12
  `)+`
13
- `}function Hr(e){return Object.keys(e).sort().map((t)=>t.toLowerCase()).join(";")}function Et(e){let t=[];return e.forEach((n,r)=>{t.push([Xt(r),Xt(n)])}),t.sort((n,r)=>{if(n[0]<r[0])return-1;if(n[0]>r[0])return 1;if(n[1]<r[1])return-1;if(n[1]>r[1])return 1;return 0}),t.map(([n,r])=>`${n}=${r}`).join("&")}function wt(e){return e.split("/").map((t)=>Xt(t)).join("/")}function Xt(e){return encodeURIComponent(e).replace(/[!'()*]/g,(t)=>`%${t.charCodeAt(0).toString(16).toUpperCase()}`)}function at(e){if(!Ve)throw Error("Synchronous hash not available in browser. Use signRequestAsync() instead.");return Ve.createHash("sha256").update(e,"utf8").digest("hex")}function it(e,t){if(!Ve)throw Error("Synchronous hmac not available in browser. Use signRequestAsync() instead.");return Ve.createHmac("sha256",e).update(t,"utf8").digest()}async function Tt(e){let n=new TextEncoder().encode(e),r=await crypto.subtle.digest("SHA-256",n);return jr(new Uint8Array(r))}async function st(e,t){let n=new TextEncoder,r=typeof e==="string"?n.encode(e):e,i=n.encode(t),s=await crypto.subtle.importKey("raw",r.buffer,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),a=await crypto.subtle.sign("HMAC",s,i.buffer);return new Uint8Array(a)}function jr(e){return Array.from(e).map((t)=>t.toString(16).padStart(2,"0")).join("")}function Kr(e,t,n,r,i,s){let a=`${e}:${t}:${n}:${r}`,o=s.get(a);if(!o){let c=it(`AWS4${e}`,t),l=it(c,n),u=it(l,r);if(o=it(u,"aws4_request"),s.size>=Gr){let m=s.keys().next().value;if(m)s.delete(m)}s.set(a,o)}return it(o,i).toString("hex")}async function qr(e,t,n,r,i,s){let a=`${e}:${t}:${n}:${r}`,o=s.get(a);if(!o){let l=await st(`AWS4${e}`,t),u=await st(l,n),m=await st(u,r);if(o=await st(m,"aws4_request"),s.size>=Gr){let p=s.keys().next().value;if(p)s.delete(p)}s.set(a,o)}let c=await st(o,i);return jr(c)}function zr(e,t){return t.includes(e)}function Rt(e,t,n){let r=t*Math.pow(2,e),i=Math.random()*0.3*r;return Math.min(r+i,n)}function Pt(e){return new Promise((t)=>setTimeout(t,e))}async function Ne(e,t){let{maxRetries:n=3,initialDelayMs:r=100,maxDelayMs:i=5000,retryableStatusCodes:s=[429,500,502,503,504],timeoutMs:a=30000}=t??{},o,c;for(let l=0;l<=n;l++){let u=H(e),m={method:u.method,headers:u.headers};if(u.body)m.body=u.body;let p=new AbortController,g=setTimeout(()=>p.abort(),a);m.signal=p.signal;try{let y=await fetch(u.url,m);if(clearTimeout(g),c=y,y.ok)return y;if(l<n&&zr(y.status,s)){let b=Rt(l,r,i);await Pt(b);continue}let h=await y.text();throw Error(`AWS API request failed (${y.status}): ${h}`)}catch(y){if(clearTimeout(g),o=y,y instanceof Error&&y.name==="AbortError")o=Error(`Request timed out after ${a}ms`);if(l<n&&!(y instanceof Error&&y.message.includes("AWS API request failed"))){let h=Rt(l,r,i);await Pt(h);continue}throw o}}throw o??Error("Request failed after retries")}async function Jg(e){return Ne(e,{maxRetries:0})}async function Yg(e,t){let{maxRetries:n=3,initialDelayMs:r=100,maxDelayMs:i=5000,retryableStatusCodes:s=[429,500,502,503,504],timeoutMs:a=30000}=t??{},o;for(let c=0;c<=n;c++){let l=await Wr(e),u={method:l.method,headers:l.headers};if(l.body)u.body=l.body;let m=new AbortController,p=setTimeout(()=>m.abort(),a);u.signal=m.signal;try{let g=await fetch(l.url,u);if(clearTimeout(p),g.ok)return g;if(c<n&&zr(g.status,s)){let h=Rt(c,r,i);await Pt(h);continue}let y=await g.text();throw Error(`AWS API request failed (${g.status}): ${y}`)}catch(g){if(clearTimeout(p),o=g,g instanceof Error&&g.name==="AbortError")o=Error(`Request timed out after ${a}ms`);if(c<n&&!(g instanceof Error&&g.message.includes("AWS API request failed"))){let y=Rt(c,r,i);await Pt(y);continue}throw o}}throw o??Error("Request failed after retries")}async function It(e){let t=await e.text(),n={},r=/<(\w+)>([^<]+)<\/\1>/g,i;while((i=r.exec(t))!==null){let[,s,a]=i;n[s]=a}return n}async function Zg(e){return await e.json()}function Xg(){Ue.clear()}function ey(){return Ue.size}function ty(){return Ve!==void 0}function ny(){return typeof crypto<"u"&&typeof crypto.subtle<"u"}var Ve,Ue,Gr=100,So;var He=$s(async()=>{try{Ve=await import("node:crypto")}catch{}Ue=new Map,So={appstream2:"appstream",cloudhsmv2:"cloudhsm",email:"ses",marketplace:"aws-marketplace",mobile:"AWSMobileHubService",pinpoint:"mobiletargeting",queue:"sqs","git-codecommit":"codecommit","mturk-requester-sandbox":"mturk-requester","personalize-runtime":"personalize"}});var ur={};Be(ur,{default:()=>ba,handler:()=>jt});var yr={};Be(yr,{default:()=>Sa,handler:()=>Kt});var Hi={};Be(Hi,{EmailAnalyticsModule:()=>gt,EmailRules:()=>Mn,EmailScheduling:()=>xn,EmailSearch:()=>Dn,EmailTemplates:()=>Me,EmailThreading:()=>Nn,SharedMailboxes:()=>kn});var ji={};Be(ji,{default:()=>Hc,handler:()=>Uc});var Ki={};Be(Ki,{CallAnalytics:()=>On,CallRecording:()=>Ln,Callbacks:()=>kt,IVRBuilder:()=>Ke});var qi={};Be(qi,{AbTesting:()=>Pe,LinkTracking:()=>_n,MmsSupport:()=>Fn,SmsAnalytics:()=>Bn,SmsCampaigns:()=>$n,SmsChatbot:()=>Gn});var au={backgroundJobs:{visibilityTimeout:120,messageRetentionPeriod:604800,deadLetterQueue:!0,maxReceiveCount:3,encrypted:!0},fifo:{fifo:!0,contentBasedDeduplication:!0,visibilityTimeout:30,encrypted:!0},highThroughput:{visibilityTimeout:30,receiveMessageWaitTime:20,encrypted:!0},delayed:{delaySeconds:60,visibilityTimeout:60,encrypted:!0},longRunning:{visibilityTimeout:900,messageRetentionPeriod:1209600,deadLetterQueue:!0,maxReceiveCount:2,encrypted:!0},monitored:{visibilityTimeout:60,messageRetentionPeriod:604800,deadLetterQueue:!0,maxReceiveCount:3,encrypted:!0,alarms:{enabled:!0,queueDepthThreshold:1000,messageAgeThreshold:3600,dlqAlarm:!0}},lambdaOptimized:{visibilityTimeout:360,receiveMessageWaitTime:20,deadLetterQueue:!0,maxReceiveCount:3,encrypted:!0},fanOut:{visibilityTimeout:30,receiveMessageWaitTime:20,encrypted:!0}},ou={serverless:{development:{enabled:!0,mode:"serverless",channels:{public:!0,private:!0,presence:!0},storage:{type:"dynamodb",dynamodb:{billingMode:"PAY_PER_REQUEST"}},scaling:{maxConnections:1000,handlerMemory:128}},production:{enabled:!0,mode:"serverless",channels:{public:!0,private:!0,presence:{enabled:!0,maxMembers:100,heartbeatInterval:30,inactivityTimeout:60}},storage:{type:"dynamodb",dynamodb:{billingMode:"PAY_PER_REQUEST",pointInTimeRecovery:!0,connectionTTL:86400}},scaling:{maxConnections:50000,messagesPerSecond:5000,handlerMemory:256,handlerTimeout:30},monitoring:{enabled:!0,connectionThreshold:40000,errorThreshold:100,latencyThreshold:500},keepAlive:!0,keepAliveInterval:30,idleTimeout:600},notifications:{enabled:!0,mode:"serverless",channels:{public:!1,private:!0,presence:!1},storage:{type:"dynamodb",dynamodb:{billingMode:"PAY_PER_REQUEST"}},scaling:{maxConnections:50000,messagesPerSecond:2000,handlerMemory:128},keepAlive:!0,keepAliveInterval:60,idleTimeout:1800}},server:{development:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:!0},server:{host:"0.0.0.0",port:6001,scheme:"ws",driver:"bun",idleTimeout:120,perMessageDeflate:!1,metrics:!1}},production:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:!0},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:120,maxPayloadLength:16777216,backpressureLimit:1048576,sendPings:!0,perMessageDeflate:!0,instances:2,redis:{enabled:!0,keyPrefix:"broadcasting:"},rateLimit:{enabled:!0,max:100,window:60000,perChannel:!0,perUser:!0},loadManagement:{enabled:!0,maxConnections:1e4,maxSubscriptionsPerConnection:100,shedLoadThreshold:0.8},metrics:!0,autoScaling:{min:2,max:10,targetCPU:70}},monitoring:{enabled:!0,connectionThreshold:8000,errorThreshold:100}},highPerformance:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:!0},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:60,maxPayloadLength:8388608,backpressureLimit:2097152,closeOnBackpressureLimit:!0,sendPings:!0,perMessageDeflate:!0,instances:4,redis:{enabled:!0,useElastiCache:!0,keyPrefix:"rt:"},rateLimit:{enabled:!0,max:200,window:60000,perChannel:!0},loadManagement:{enabled:!0,maxConnections:25000,maxSubscriptionsPerConnection:50,shedLoadThreshold:0.7},metrics:{enabled:!0,path:"/metrics"},autoScaling:{min:4,max:20,targetCPU:60,targetConnections:20000}},monitoring:{enabled:!0,connectionThreshold:80000,errorThreshold:50,latencyThreshold:50}},chat:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:{enabled:!0,maxMembers:200,heartbeatInterval:20,inactivityTimeout:60}},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:300,maxPayloadLength:1048576,sendPings:!0,perMessageDeflate:!0,instances:2,redis:{enabled:!0,keyPrefix:"chat:"},rateLimit:{enabled:!0,max:60,window:60000,perChannel:!0},loadManagement:{enabled:!0,maxConnections:15000,maxSubscriptionsPerConnection:20},metrics:!0},keepAlive:!0,keepAliveInterval:25,idleTimeout:900},gaming:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:{enabled:!0,maxMembers:100,heartbeatInterval:10,inactivityTimeout:30}},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:30,maxPayloadLength:65536,backpressureLimit:524288,closeOnBackpressureLimit:!0,sendPings:!0,perMessageDeflate:!1,instances:4,redis:{enabled:!0,useElastiCache:!0},rateLimit:{enabled:!0,max:120,window:60000},loadManagement:{enabled:!0,maxConnections:5000,maxSubscriptionsPerConnection:10,shedLoadThreshold:0.6},metrics:!0,autoScaling:{min:4,max:16,targetCPU:50}},keepAlive:!0,keepAliveInterval:10,idleTimeout:60},single:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:!0},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:120,sendPings:!0,perMessageDeflate:!0,instances:1,rateLimit:{enabled:!0,max:100,window:60000},loadManagement:{enabled:!0,maxConnections:1e4},metrics:!0}}}};import{isAbsolute as Gt,join as yt,relative as Gs}from"node:path";var _t=".ts-cloud",Qn="TS_CLOUD_STATE_DIR",Wt=null;function uu(e){Wt=e?.trim()||null}function du(){return Boolean(process.env[Qn]?.trim()||Wt)}function Fe(){return process.env[Qn]?.trim()||Wt||_t}function Jn(...e){return yt(Fe(),...e)}function _s(e,...t){let n=Fe();return Gt(n)?yt(n,...t):yt(e,n,...t)}function mu(e,t=process.cwd()){let n=(i,s)=>{let a=Gs(i,s);return a===""||!a.startsWith("..")&&!Gt(a)},r=Gt(e)?e:yt(t,e);return n(_s(t),r)}function Yn(e){let t=e.infrastructure?.compute!=null,n=Object.values(e.environments??{}).some((r)=>r?.app!=null);return{server:t,serverless:n}}function gu(e){if(e.mode==="server"||e.mode==="serverless")return e.mode;let{serverless:t}=Yn(e);return t?"serverless":"server"}function yu(e){let{server:t,serverless:n}=Yn(e);if(t&&n)return"A project cannot be both a server and a serverless deployment. Found `infrastructure.compute` (server) AND `environments.<env>.app` (serverless Lambda). Keep one: remove `infrastructure.compute` for a serverless app, or remove `environments.<env>.app` for a server.";if(e.mode==="server"&&n&&!t)return"Config sets `mode: 'server'` but declares a serverless app (`environments.<env>.app`). Remove the app or change the mode.";if(e.mode==="serverless"&&t&&!n)return"Config sets `mode: 'serverless'` but declares a server (`infrastructure.compute`). Remove the compute block or change the mode.";return null}function hu(e){return e.infrastructure?.appDatabase??e.infrastructure?.compute?.database}function Ws(e){return typeof e==="object"&&e!==null?e:{}}function Vs(e){return e===!0||typeof e==="object"&&e!==null}function Us(e,t){let n=t?e.environments?.[t]:void 0;if(n?.domain)return n.domain;let r=Object.values(e.sites??{}),i=e.sites?.main?.domain??r.find((s)=>s.domain)?.domain;if(i)return i;return`${e.project?.slug??"app"}.local`}function Hs(e){let t=e.indexOf(".");return t>0?e.slice(t+1):void 0}function js(e,t={}){let n=e.infrastructure?.compute?.managedServices?.mail,r=Ws(n),i=t.environmentType??(t.environment?e.environments?.[t.environment]?.type:void 0),s=r.mode??(i==="production"?"server":"catcher"),a=s==="server",o=Us(e,t.environment),c=r.hostname??(a?`mail.${o}`:"localhost"),l=r.ports??{},u=a?{smtp:l.smtp??25,submission:l.submission??587,submissions:l.submissions??465,imap:l.imap??143,imaps:l.imaps??993,webmail:l.webmail??8080,managesieve:l.managesieve}:{smtp:l.smtp??1025,submission:l.submission,submissions:l.submissions,imap:l.imap,imaps:l.imaps,webmail:l.webmail??8025,managesieve:l.managesieve},m=r.tls??{},p=m.enabled??a,g=!!(m.certPath&&m.keyPath),y=(r.accounts??[]).map((K)=>({address:K.address,password:K.password,passwordPolicy:K.passwordPolicy??"initial"})),h=typeof r.dkim==="object"&&r.dkim!==null?r.dkim:{},b=r.dkim===!1?!1:r.dkim===!0||a,C=typeof r.webmail==="object"&&r.webmail!==null?r.webmail:{},T=r.webmail===!1?!1:C.enabled??!0,A=c.includes(".")&&!c.endsWith(".local")&&!/^\d+\.\d+\.\d+\.\d+$/.test(c),R=C.domain===!1?void 0:C.domain??(a&&A?c:void 0),P=C.tls??(R?!1:p),E=[...new Set(C.aliases??[])].filter((K)=>K!==R),w=r.spam??{},I=r.delivery??(a?"direct":"none"),D=r.expose??a,k=Hs(c),O=[...new Set([c,...k?[k]:[],...r.domains??[]])],ne=C.attachments?.maxFileBytes??20971520,_=C.attachments?.maxTotalBytes??20971520,q=C.attachments?.maxCount??20,F=C.undoSendSeconds??10;for(let[K,de,Oe]of[["maxFileBytes",ne,104857600],["maxTotalBytes",_,104857600],["maxCount",q,100],["undoSendSeconds",F,30]])if(!Number.isInteger(de)||de<0||de>Oe)throw Error(`Mail webmail ${K} must be an integer from 0 to ${Oe}`);return{enabled:Vs(n),mode:s,version:r.version,hostname:c,domains:O,ports:u,tls:{enabled:p,acme:p&&!g&&(m.acme??!0),certPath:m.certPath,keyPath:m.keyPath,requireForAuth:m.requireForAuth??(p&&a),acmeEmail:m.acmeEmail??y[0]?.address},dkim:{enabled:b,selector:h.selector??"default",rotate:h.rotate??!1,rotateIntervalDays:h.rotateIntervalDays??90},webmail:{enabled:T,port:C.port??u.webmail,domain:R,aliases:E,tls:P,secureCookies:C.secureCookies??(!!R||P),attachmentMaxFileBytes:ne,attachmentMaxTotalBytes:_,attachmentMaxCount:q,undoSendSeconds:F},delivery:I,sesRegion:r.sesRegion??"us-east-1",accounts:y,storagePath:r.storagePath??"/var/lib/mail",maxMessageSize:r.maxMessageSize??26214400,spam:{enabled:w.enabled??a,enforce:w.enforce??!1,junkScore:w.junkScore??5,rejectScore:w.rejectScore??12,dnsbl:w.dnsbl??a,greylist:w.greylist??!1},webhookUrl:r.webhookUrl,expose:D,bindAddress:D?"0.0.0.0":"127.0.0.1"}}function Su(e){if(!e.enabled||!e.expose)return[];let t=[e.ports.smtp,e.ports.submission,e.ports.submissions,e.ports.imap,e.ports.imaps,e.ports.managesieve].filter((n)=>typeof n==="number");if(e.webmail.enabled&&!e.webmail.domain)t.push(e.webmail.port);return[...new Set(t)].sort((n,r)=>n-r)}function Au(e){if(!e.enabled)return{};let t=e.ports.submission??e.ports.smtp,n={MAIL_MAILER:"smtp",MAIL_HOST:"127.0.0.1",MAIL_PORT:String(t)};if(e.mode==="server"){n.MAIL_ENCRYPTION=e.tls.enabled?"tls":"null";let r=e.accounts[0];if(r)n.MAIL_USERNAME=r.address,n.MAIL_PASSWORD=r.password}else n.MAIL_ENCRYPTION="null",n.MAIL_USERNAME="null",n.MAIL_PASSWORD="null";return n}function Cu(e){if(!e.enabled||!e.webmail.enabled||!e.webmail.domain)return{};let t=[e.webmail.domain,...e.webmail.aliases];if(!Number.isInteger(e.webmail.port)||e.webmail.port<1||e.webmail.port>65535)throw Error("Mail webmail port must be between 1 and 65535");return Object.fromEntries(t.map((n,r)=>{if(!/^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/i.test(n))throw Error(`Invalid mail webmail hostname: ${n}`);return[`__mail_webmail_${r}`,{domain:n,proxyTo:`localhost:${e.webmail.port}`}]}))}function vu(e,t={}){let n=e.infrastructure?.compute?.proxy,r=js(e,t);if(!r.enabled||!r.webmail.enabled||!r.webmail.domain)return n;return{engine:"rpx",onDemandTls:!0,onDemandTlsEmail:r.tls.acmeEmail??`webmaster@${r.webmail.domain}`,...n}}function Ru(e){if(e.cloud?.provider)return e.cloud.provider;if(e.ssh?.hosts?.length)return"ssh";if(e.hetzner?.apiToken)return"hetzner";return"aws"}class Ks{template;constructor(e){this.template={AWSTemplateFormatVersion:"2010-09-09",Description:e,Resources:{}}}addResource(e,t){return this.template.Resources[e]=t,this}addResources(e){return Object.assign(this.template.Resources,e),this}addParameter(e,t){if(!this.template.Parameters)this.template.Parameters={};return this.template.Parameters[e]=t,this}addOutput(e,t){if(!this.template.Outputs)this.template.Outputs={};return this.template.Outputs[e]=t,this}addMetadata(e,t){if(!this.template.Metadata)this.template.Metadata={};return this.template.Metadata[e]=t,this}hasResource(e){return e in this.template.Resources}getResources(){return this.template.Resources}build(){return this.template}toJSON(e=!0){return JSON.stringify(this.template,null,e?2:0)}toYAML(){return this.convertToYAML(this.template)}convertToYAML(e,t=0){let n=" ".repeat(t),r="";for(let[i,s]of Object.entries(e)){if(s===null||s===void 0)continue;if(typeof s==="object"&&!Array.isArray(s))r+=`${n}${i}:
13
+ `}function Hr(e){return Object.keys(e).sort().map((t)=>t.toLowerCase()).join(";")}function Et(e){let t=[];return e.forEach((n,r)=>{t.push([Xt(r),Xt(n)])}),t.sort((n,r)=>{if(n[0]<r[0])return-1;if(n[0]>r[0])return 1;if(n[1]<r[1])return-1;if(n[1]>r[1])return 1;return 0}),t.map(([n,r])=>`${n}=${r}`).join("&")}function wt(e){return e.split("/").map((t)=>Xt(t)).join("/")}function Xt(e){return encodeURIComponent(e).replace(/[!'()*]/g,(t)=>`%${t.charCodeAt(0).toString(16).toUpperCase()}`)}function at(e){if(!Ve)throw Error("Synchronous hash not available in browser. Use signRequestAsync() instead.");return Ve.createHash("sha256").update(e,"utf8").digest("hex")}function it(e,t){if(!Ve)throw Error("Synchronous hmac not available in browser. Use signRequestAsync() instead.");return Ve.createHmac("sha256",e).update(t,"utf8").digest()}async function Tt(e){let n=new TextEncoder().encode(e),r=await crypto.subtle.digest("SHA-256",n);return jr(new Uint8Array(r))}async function st(e,t){let n=new TextEncoder,r=typeof e==="string"?n.encode(e):e,i=n.encode(t),s=await crypto.subtle.importKey("raw",r.buffer,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),a=await crypto.subtle.sign("HMAC",s,i.buffer);return new Uint8Array(a)}function jr(e){return Array.from(e).map((t)=>t.toString(16).padStart(2,"0")).join("")}function Kr(e,t,n,r,i,s){let a=`${e}:${t}:${n}:${r}`,o=s.get(a);if(!o){let c=it(`AWS4${e}`,t),l=it(c,n),u=it(l,r);if(o=it(u,"aws4_request"),s.size>=Gr){let m=s.keys().next().value;if(m)s.delete(m)}s.set(a,o)}return it(o,i).toString("hex")}async function qr(e,t,n,r,i,s){let a=`${e}:${t}:${n}:${r}`,o=s.get(a);if(!o){let l=await st(`AWS4${e}`,t),u=await st(l,n),m=await st(u,r);if(o=await st(m,"aws4_request"),s.size>=Gr){let p=s.keys().next().value;if(p)s.delete(p)}s.set(a,o)}let c=await st(o,i);return jr(c)}function zr(e,t){return t.includes(e)}function Rt(e,t,n){let r=t*Math.pow(2,e),i=Math.random()*0.3*r;return Math.min(r+i,n)}function Pt(e){return new Promise((t)=>setTimeout(t,e))}async function Ne(e,t){let{maxRetries:n=3,initialDelayMs:r=100,maxDelayMs:i=5000,retryableStatusCodes:s=[429,500,502,503,504],timeoutMs:a=30000}=t??{},o,c;for(let l=0;l<=n;l++){let u=H(e),m={method:u.method,headers:u.headers};if(u.body)m.body=u.body;let p=new AbortController,g=setTimeout(()=>p.abort(),a);m.signal=p.signal;try{let y=await fetch(u.url,m);if(clearTimeout(g),c=y,y.ok)return y;if(l<n&&zr(y.status,s)){let b=Rt(l,r,i);await Pt(b);continue}let h=await y.text();throw Error(`AWS API request failed (${y.status}): ${h}`)}catch(y){if(clearTimeout(g),o=y,y instanceof Error&&y.name==="AbortError")o=Error(`Request timed out after ${a}ms`);if(l<n&&!(y instanceof Error&&y.message.includes("AWS API request failed"))){let h=Rt(l,r,i);await Pt(h);continue}throw o}}throw o??Error("Request failed after retries")}async function Jg(e){return Ne(e,{maxRetries:0})}async function Yg(e,t){let{maxRetries:n=3,initialDelayMs:r=100,maxDelayMs:i=5000,retryableStatusCodes:s=[429,500,502,503,504],timeoutMs:a=30000}=t??{},o;for(let c=0;c<=n;c++){let l=await Wr(e),u={method:l.method,headers:l.headers};if(l.body)u.body=l.body;let m=new AbortController,p=setTimeout(()=>m.abort(),a);u.signal=m.signal;try{let g=await fetch(l.url,u);if(clearTimeout(p),g.ok)return g;if(c<n&&zr(g.status,s)){let h=Rt(c,r,i);await Pt(h);continue}let y=await g.text();throw Error(`AWS API request failed (${g.status}): ${y}`)}catch(g){if(clearTimeout(p),o=g,g instanceof Error&&g.name==="AbortError")o=Error(`Request timed out after ${a}ms`);if(c<n&&!(g instanceof Error&&g.message.includes("AWS API request failed"))){let y=Rt(c,r,i);await Pt(y);continue}throw o}}throw o??Error("Request failed after retries")}async function It(e){let t=await e.text(),n={},r=/<(\w+)>([^<]+)<\/\1>/g,i;while((i=r.exec(t))!==null){let[,s,a]=i;n[s]=a}return n}async function Zg(e){return await e.json()}function Xg(){Ue.clear()}function ey(){return Ue.size}function ty(){return Ve!==void 0}function ny(){return typeof crypto<"u"&&typeof crypto.subtle<"u"}var Ve,Ue,Gr=100,So;var He=$s(async()=>{try{Ve=await import("node:crypto")}catch{}Ue=new Map,So={appstream2:"appstream",cloudhsmv2:"cloudhsm",email:"ses",marketplace:"aws-marketplace",mobile:"AWSMobileHubService",pinpoint:"mobiletargeting",queue:"sqs","git-codecommit":"codecommit","mturk-requester-sandbox":"mturk-requester","personalize-runtime":"personalize"}});var ur={};Be(ur,{default:()=>ba,handler:()=>jt});var yr={};Be(yr,{default:()=>Sa,handler:()=>Kt});var Hi={};Be(Hi,{EmailAnalyticsModule:()=>gt,EmailRules:()=>Mn,EmailScheduling:()=>xn,EmailSearch:()=>Dn,EmailTemplates:()=>Me,EmailThreading:()=>Nn,SharedMailboxes:()=>kn});var ji={};Be(ji,{default:()=>Hc,handler:()=>Uc});var Ki={};Be(Ki,{CallAnalytics:()=>On,CallRecording:()=>Ln,Callbacks:()=>kt,IVRBuilder:()=>Ke});var qi={};Be(qi,{AbTesting:()=>Pe,LinkTracking:()=>_n,MmsSupport:()=>Fn,SmsAnalytics:()=>Bn,SmsCampaigns:()=>$n,SmsChatbot:()=>Gn});var au={backgroundJobs:{visibilityTimeout:120,messageRetentionPeriod:604800,deadLetterQueue:!0,maxReceiveCount:3,encrypted:!0},fifo:{fifo:!0,contentBasedDeduplication:!0,visibilityTimeout:30,encrypted:!0},highThroughput:{visibilityTimeout:30,receiveMessageWaitTime:20,encrypted:!0},delayed:{delaySeconds:60,visibilityTimeout:60,encrypted:!0},longRunning:{visibilityTimeout:900,messageRetentionPeriod:1209600,deadLetterQueue:!0,maxReceiveCount:2,encrypted:!0},monitored:{visibilityTimeout:60,messageRetentionPeriod:604800,deadLetterQueue:!0,maxReceiveCount:3,encrypted:!0,alarms:{enabled:!0,queueDepthThreshold:1000,messageAgeThreshold:3600,dlqAlarm:!0}},lambdaOptimized:{visibilityTimeout:360,receiveMessageWaitTime:20,deadLetterQueue:!0,maxReceiveCount:3,encrypted:!0},fanOut:{visibilityTimeout:30,receiveMessageWaitTime:20,encrypted:!0}},ou={serverless:{development:{enabled:!0,mode:"serverless",channels:{public:!0,private:!0,presence:!0},storage:{type:"dynamodb",dynamodb:{billingMode:"PAY_PER_REQUEST"}},scaling:{maxConnections:1000,handlerMemory:128}},production:{enabled:!0,mode:"serverless",channels:{public:!0,private:!0,presence:{enabled:!0,maxMembers:100,heartbeatInterval:30,inactivityTimeout:60}},storage:{type:"dynamodb",dynamodb:{billingMode:"PAY_PER_REQUEST",pointInTimeRecovery:!0,connectionTTL:86400}},scaling:{maxConnections:50000,messagesPerSecond:5000,handlerMemory:256,handlerTimeout:30},monitoring:{enabled:!0,connectionThreshold:40000,errorThreshold:100,latencyThreshold:500},keepAlive:!0,keepAliveInterval:30,idleTimeout:600},notifications:{enabled:!0,mode:"serverless",channels:{public:!1,private:!0,presence:!1},storage:{type:"dynamodb",dynamodb:{billingMode:"PAY_PER_REQUEST"}},scaling:{maxConnections:50000,messagesPerSecond:2000,handlerMemory:128},keepAlive:!0,keepAliveInterval:60,idleTimeout:1800}},server:{development:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:!0},server:{host:"0.0.0.0",port:6001,scheme:"ws",driver:"bun",idleTimeout:120,perMessageDeflate:!1,metrics:!1}},production:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:!0},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:120,maxPayloadLength:16777216,backpressureLimit:1048576,sendPings:!0,perMessageDeflate:!0,instances:2,redis:{enabled:!0,keyPrefix:"broadcasting:"},rateLimit:{enabled:!0,max:100,window:60000,perChannel:!0,perUser:!0},loadManagement:{enabled:!0,maxConnections:1e4,maxSubscriptionsPerConnection:100,shedLoadThreshold:0.8},metrics:!0,autoScaling:{min:2,max:10,targetCPU:70}},monitoring:{enabled:!0,connectionThreshold:8000,errorThreshold:100}},highPerformance:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:!0},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:60,maxPayloadLength:8388608,backpressureLimit:2097152,closeOnBackpressureLimit:!0,sendPings:!0,perMessageDeflate:!0,instances:4,redis:{enabled:!0,useElastiCache:!0,keyPrefix:"rt:"},rateLimit:{enabled:!0,max:200,window:60000,perChannel:!0},loadManagement:{enabled:!0,maxConnections:25000,maxSubscriptionsPerConnection:50,shedLoadThreshold:0.7},metrics:{enabled:!0,path:"/metrics"},autoScaling:{min:4,max:20,targetCPU:60,targetConnections:20000}},monitoring:{enabled:!0,connectionThreshold:80000,errorThreshold:50,latencyThreshold:50}},chat:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:{enabled:!0,maxMembers:200,heartbeatInterval:20,inactivityTimeout:60}},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:300,maxPayloadLength:1048576,sendPings:!0,perMessageDeflate:!0,instances:2,redis:{enabled:!0,keyPrefix:"chat:"},rateLimit:{enabled:!0,max:60,window:60000,perChannel:!0},loadManagement:{enabled:!0,maxConnections:15000,maxSubscriptionsPerConnection:20},metrics:!0},keepAlive:!0,keepAliveInterval:25,idleTimeout:900},gaming:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:{enabled:!0,maxMembers:100,heartbeatInterval:10,inactivityTimeout:30}},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:30,maxPayloadLength:65536,backpressureLimit:524288,closeOnBackpressureLimit:!0,sendPings:!0,perMessageDeflate:!1,instances:4,redis:{enabled:!0,useElastiCache:!0},rateLimit:{enabled:!0,max:120,window:60000},loadManagement:{enabled:!0,maxConnections:5000,maxSubscriptionsPerConnection:10,shedLoadThreshold:0.6},metrics:!0,autoScaling:{min:4,max:16,targetCPU:50}},keepAlive:!0,keepAliveInterval:10,idleTimeout:60},single:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:!0},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:120,sendPings:!0,perMessageDeflate:!0,instances:1,rateLimit:{enabled:!0,max:100,window:60000},loadManagement:{enabled:!0,maxConnections:1e4},metrics:!0}}}};import{isAbsolute as Gt,join as yt,relative as Gs}from"node:path";var _t=".ts-cloud",Qn="TS_CLOUD_STATE_DIR",Wt=null;function uu(e){Wt=e?.trim()||null}function du(){return Boolean(process.env[Qn]?.trim()||Wt)}function Fe(){return process.env[Qn]?.trim()||Wt||_t}function Jn(...e){return yt(Fe(),...e)}function _s(e,...t){let n=Fe();return Gt(n)?yt(n,...t):yt(e,n,...t)}function mu(e,t=process.cwd()){let n=(i,s)=>{let a=Gs(i,s);return a===""||!a.startsWith("..")&&!Gt(a)},r=Gt(e)?e:yt(t,e);return n(_s(t),r)}function Yn(e){let t=e.infrastructure?.compute!=null,n=Object.values(e.environments??{}).some((r)=>r?.app!=null);return{server:t,serverless:n}}function gu(e){if(e.mode==="server"||e.mode==="serverless")return e.mode;let{serverless:t}=Yn(e);return t?"serverless":"server"}function yu(e){let{server:t,serverless:n}=Yn(e);if(t&&n)return"A project cannot be both a server and a serverless deployment. Found `infrastructure.compute` (server) AND `environments.<env>.app` (serverless Lambda). Keep one: remove `infrastructure.compute` for a serverless app, or remove `environments.<env>.app` for a server.";if(e.mode==="server"&&n&&!t)return"Config sets `mode: 'server'` but declares a serverless app (`environments.<env>.app`). Remove the app or change the mode.";if(e.mode==="serverless"&&t&&!n)return"Config sets `mode: 'serverless'` but declares a server (`infrastructure.compute`). Remove the compute block or change the mode.";return null}function hu(e){return e.infrastructure?.appDatabase??e.infrastructure?.compute?.database}function Ws(e){return typeof e==="object"&&e!==null?e:{}}function Vs(e){return e===!0||typeof e==="object"&&e!==null}function Us(e,t){let n=t?e.environments?.[t]:void 0;if(n?.domain)return n.domain;let r=Object.values(e.sites??{}),i=e.sites?.main?.domain??r.find((s)=>s.domain)?.domain;if(i)return i;return`${e.project?.slug??"app"}.local`}function Hs(e){let t=e.indexOf(".");return t>0?e.slice(t+1):void 0}function js(e,t={}){let n=e.infrastructure?.compute?.managedServices?.mail,r=Ws(n),i=t.environmentType??(t.environment?e.environments?.[t.environment]?.type:void 0),s=r.mode??(i==="production"?"server":"catcher"),a=s==="server",o=Us(e,t.environment),c=r.hostname??(a?`mail.${o}`:"localhost"),l=r.ports??{},u=a?{smtp:l.smtp??25,submission:l.submission??587,submissions:l.submissions??465,imap:l.imap??143,imaps:l.imaps??993,webmail:l.webmail??8080,managesieve:l.managesieve}:{smtp:l.smtp??1025,submission:l.submission,submissions:l.submissions,imap:l.imap,imaps:l.imaps,webmail:l.webmail??8025,managesieve:l.managesieve},m=r.tls??{},p=m.enabled??a,g=!!(m.certPath&&m.keyPath),y=(r.accounts??[]).map((K)=>({address:K.address,password:K.password,passwordPolicy:K.passwordPolicy??"initial"})),h=typeof r.dkim==="object"&&r.dkim!==null?r.dkim:{},b=r.dkim===!1?!1:r.dkim===!0||a,C=typeof r.webmail==="object"&&r.webmail!==null?r.webmail:{},T=r.webmail===!1?!1:C.enabled??!0,A=c.includes(".")&&!c.endsWith(".local")&&!/^\d+\.\d+\.\d+\.\d+$/.test(c),R=C.domain===!1?void 0:C.domain??(a&&A?c:void 0),P=C.tls??(R?!1:p),E=[...new Set(C.aliases??[])].filter((K)=>K!==R),w=r.spam??{},I=r.delivery??(a?"direct":"none"),D=r.expose??a,k=Hs(c),O=[...new Set([c,...k?[k]:[],...r.domains??[]])],ne=C.attachments?.maxFileBytes??20971520,_=C.attachments?.maxTotalBytes??20971520,q=C.attachments?.maxCount??20,F=C.undoSendSeconds??10;for(let[K,de,Oe]of[["maxFileBytes",ne,104857600],["maxTotalBytes",_,104857600],["maxCount",q,100],["undoSendSeconds",F,30]])if(!Number.isInteger(de)||de<0||de>Oe)throw Error(`Mail webmail ${K} must be an integer from 0 to ${Oe}`);return{enabled:Vs(n),mode:s,version:r.version,hostname:c,domains:O,ports:u,tls:{enabled:p,acme:p&&!g&&(m.acme??!0),certPath:m.certPath,keyPath:m.keyPath,requireForAuth:m.requireForAuth??(p&&a),acmeEmail:m.acmeEmail??y[0]?.address},dkim:{enabled:b,selector:h.selector??"default",rotate:h.rotate??!1,rotateIntervalDays:h.rotateIntervalDays??90},webmail:{enabled:T,port:C.port??u.webmail,domain:R,aliases:E,tls:P,secureCookies:C.secureCookies??(!!R||P),attachmentMaxFileBytes:ne,attachmentMaxTotalBytes:_,attachmentMaxCount:q,undoSendSeconds:F},delivery:I,sesRegion:r.sesRegion??"us-east-1",accounts:y,storagePath:r.storagePath??"/var/lib/mail",maxMessageSize:r.maxMessageSize??26214400,spam:{enabled:w.enabled??a,enforce:w.enforce??!1,junkScore:w.junkScore??5,rejectScore:w.rejectScore??12,dnsbl:w.dnsbl??a,dnsblReject:w.dnsblReject??!1,greylist:w.greylist??!1},webhookUrl:r.webhookUrl,expose:D,bindAddress:D?"0.0.0.0":"127.0.0.1"}}function Su(e){if(!e.enabled||!e.expose)return[];let t=[e.ports.smtp,e.ports.submission,e.ports.submissions,e.ports.imap,e.ports.imaps,e.ports.managesieve].filter((n)=>typeof n==="number");if(e.webmail.enabled&&!e.webmail.domain)t.push(e.webmail.port);return[...new Set(t)].sort((n,r)=>n-r)}function Au(e){if(!e.enabled)return{};let t=e.ports.submission??e.ports.smtp,n={MAIL_MAILER:"smtp",MAIL_HOST:"127.0.0.1",MAIL_PORT:String(t)};if(e.mode==="server"){n.MAIL_ENCRYPTION=e.tls.enabled?"tls":"null";let r=e.accounts[0];if(r)n.MAIL_USERNAME=r.address,n.MAIL_PASSWORD=r.password}else n.MAIL_ENCRYPTION="null",n.MAIL_USERNAME="null",n.MAIL_PASSWORD="null";return n}function Cu(e){if(!e.enabled||!e.webmail.enabled||!e.webmail.domain)return{};let t=[e.webmail.domain,...e.webmail.aliases];if(!Number.isInteger(e.webmail.port)||e.webmail.port<1||e.webmail.port>65535)throw Error("Mail webmail port must be between 1 and 65535");return Object.fromEntries(t.map((n,r)=>{if(!/^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/i.test(n))throw Error(`Invalid mail webmail hostname: ${n}`);return[`__mail_webmail_${r}`,{domain:n,proxyTo:`localhost:${e.webmail.port}`}]}))}function vu(e,t={}){let n=e.infrastructure?.compute?.proxy,r=js(e,t);if(!r.enabled||!r.webmail.enabled||!r.webmail.domain)return n;return{engine:"rpx",onDemandTls:!0,onDemandTlsEmail:r.tls.acmeEmail??`webmaster@${r.webmail.domain}`,...n}}function Ru(e){if(e.cloud?.provider)return e.cloud.provider;if(e.ssh?.hosts?.length)return"ssh";if(e.hetzner?.apiToken)return"hetzner";return"aws"}class Ks{template;constructor(e){this.template={AWSTemplateFormatVersion:"2010-09-09",Description:e,Resources:{}}}addResource(e,t){return this.template.Resources[e]=t,this}addResources(e){return Object.assign(this.template.Resources,e),this}addParameter(e,t){if(!this.template.Parameters)this.template.Parameters={};return this.template.Parameters[e]=t,this}addOutput(e,t){if(!this.template.Outputs)this.template.Outputs={};return this.template.Outputs[e]=t,this}addMetadata(e,t){if(!this.template.Metadata)this.template.Metadata={};return this.template.Metadata[e]=t,this}hasResource(e){return e in this.template.Resources}getResources(){return this.template.Resources}build(){return this.template}toJSON(e=!0){return JSON.stringify(this.template,null,e?2:0)}toYAML(){return this.convertToYAML(this.template)}convertToYAML(e,t=0){let n=" ".repeat(t),r="";for(let[i,s]of Object.entries(e)){if(s===null||s===void 0)continue;if(typeof s==="object"&&!Array.isArray(s))r+=`${n}${i}:
14
14
  ${this.convertToYAML(s,t+1)}`;else if(Array.isArray(s)){r+=`${n}${i}:
15
15
  `;for(let a of s)if(typeof a==="object")r+=`${n} -
16
16
  ${this.convertToYAML(a,t+2)}`;else r+=`${n} - ${a}
package/dist/types.d.ts CHANGED
@@ -4293,6 +4293,8 @@ export interface MailSpamConfig {
4293
4293
  rejectScore?: number;
4294
4294
  /** Consult DNS blocklists. @default true for a server. */
4295
4295
  dnsbl?: boolean;
4296
+ /** Reject DNSBL-listed peers at SMTP RCPT instead of scoring them. @default false */
4297
+ dnsblReject?: boolean;
4296
4298
  /** Greylist unknown senders. Off by default - it delays first contact. */
4297
4299
  greylist?: boolean;
4298
4300
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ts-cloud/core",
3
3
  "type": "module",
4
- "version": "0.16.67",
4
+ "version": "0.16.68",
5
5
  "description": "Core CloudFormation generation library for ts-cloud",
6
6
  "author": "Chris Breuer <chris@stacksjs.com>",
7
7
  "license": "MIT",
@@ -31,7 +31,7 @@
31
31
  "typecheck": "tsc --noEmit"
32
32
  },
33
33
  "dependencies": {
34
- "@ts-cloud/aws-types": "0.16.67"
34
+ "@ts-cloud/aws-types": "0.16.68"
35
35
  },
36
36
  "devDependencies": {
37
37
  "typescript": "^7.0.2"