@stacksjs/ts-cloud 0.16.14 → 0.16.15

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.
Files changed (86) hide show
  1. package/dist/aws/index.js +1 -1
  2. package/dist/bin/{chunk-9bshng4v.js → chunk-8t0mrz5d.js} +77 -77
  3. package/dist/bin/{chunk-e4gqzp7n.js → chunk-r35q7kve.js} +1 -1
  4. package/dist/bin/{chunk-0ed5yh3v.js → chunk-trdteh51.js} +1 -1
  5. package/dist/bin/cli.js +4 -4
  6. package/dist/bin/dashboard-server.js +1 -1
  7. package/dist/{chunk-tgzp1h6j.js → chunk-2rt6xbmv.js} +2 -2
  8. package/dist/{chunk-xdsaxgny.js → chunk-2vgdfywj.js} +1 -1
  9. package/dist/{chunk-d72ddm5x.js → chunk-42ngwzvc.js} +79 -79
  10. package/dist/{chunk-7pk6cctr.js → chunk-8x24tv2g.js} +38 -38
  11. package/dist/{chunk-0hf0rdze.js → chunk-97a7sxpe.js} +1 -1
  12. package/dist/{chunk-nw5yqgtn.js → chunk-9nxb5fyp.js} +4 -4
  13. package/dist/{chunk-bpvpq6w6.js → chunk-bd75na8x.js} +86 -86
  14. package/dist/{chunk-aesvajfc.js → chunk-fs78rxy1.js} +2 -2
  15. package/dist/chunk-gj27zyk5.js +1 -0
  16. package/dist/{chunk-s40cx3fh.js → chunk-ht8rawp1.js} +2 -2
  17. package/dist/{chunk-ffjc6gev.js → chunk-kx7zw3xn.js} +128 -128
  18. package/dist/{chunk-2jgx2s5y.js → chunk-p0w0kwhx.js} +5 -5
  19. package/dist/{chunk-4yb7hf91.js → chunk-pc0tz6be.js} +2 -2
  20. package/dist/{chunk-mmdd5thg.js → chunk-s1bfyvmc.js} +1 -1
  21. package/dist/{chunk-55cmjg49.js → chunk-tznx5510.js} +3 -3
  22. package/dist/{chunk-kt6qnc6f.js → chunk-y59rkb2n.js} +1 -1
  23. package/dist/deploy/index.js +1 -1
  24. package/dist/dns/index.js +1 -1
  25. package/dist/drivers/index.js +1 -1
  26. package/dist/drivers/shared/deploy-script.d.ts +62 -29
  27. package/dist/index.js +32 -32
  28. package/dist/operations/index.js +1 -1
  29. package/dist/protection/index.js +1 -1
  30. package/dist/spend/index.js +1 -1
  31. package/dist/ui/404.html +1 -1
  32. package/dist/ui/accept-invitation.html +1 -1
  33. package/dist/ui/access-denied.html +1 -1
  34. package/dist/ui/account/automation.html +6 -6
  35. package/dist/ui/account/security.html +2 -2
  36. package/dist/ui/applications/compose.html +5 -5
  37. package/dist/ui/applications/new.html +2 -2
  38. package/dist/ui/data/backups.html +6 -6
  39. package/dist/ui/data/services.html +6 -6
  40. package/dist/ui/data/volumes.html +6 -6
  41. package/dist/ui/index.html +5 -5
  42. package/dist/ui/infrastructure/topology.html +6 -6
  43. package/dist/ui/integrations.html +2 -2
  44. package/dist/ui/operations/alerts.html +5 -5
  45. package/dist/ui/operations/configuration.html +5 -5
  46. package/dist/ui/operations/jobs.html +6 -6
  47. package/dist/ui/operations/maintenance.html +6 -6
  48. package/dist/ui/operations/observability.html +6 -6
  49. package/dist/ui/operations/previews.html +6 -6
  50. package/dist/ui/operations/queue.html +6 -6
  51. package/dist/ui/operations/regions.html +6 -6
  52. package/dist/ui/operations/releases.html +6 -6
  53. package/dist/ui/operations/spend.html +6 -6
  54. package/dist/ui/operations/workloads.html +6 -6
  55. package/dist/ui/security.html +2 -2
  56. package/dist/ui/server/actions.html +6 -6
  57. package/dist/ui/server/activity.html +2 -2
  58. package/dist/ui/server/capacity.html +6 -6
  59. package/dist/ui/server/database.html +6 -6
  60. package/dist/ui/server/deployments.html +6 -6
  61. package/dist/ui/server/diagnostics.html +2 -2
  62. package/dist/ui/server/firewall.html +6 -6
  63. package/dist/ui/server/fleet.html +6 -6
  64. package/dist/ui/server/logs.html +6 -6
  65. package/dist/ui/server/metrics.html +6 -6
  66. package/dist/ui/server/security.html +2 -2
  67. package/dist/ui/server/services.html +2 -2
  68. package/dist/ui/server/sites.html +6 -6
  69. package/dist/ui/server/ssh-keys.html +5 -5
  70. package/dist/ui/server/team.html +6 -6
  71. package/dist/ui/server/terminal.html +2 -2
  72. package/dist/ui/serverless/alarms.html +6 -6
  73. package/dist/ui/serverless/assets.html +2 -2
  74. package/dist/ui/serverless/cost.html +2 -2
  75. package/dist/ui/serverless/data.html +6 -6
  76. package/dist/ui/serverless/deployments.html +2 -2
  77. package/dist/ui/serverless/firewall.html +1 -1
  78. package/dist/ui/serverless/functions.html +6 -6
  79. package/dist/ui/serverless/logs.html +6 -6
  80. package/dist/ui/serverless/metrics.html +2 -2
  81. package/dist/ui/serverless/queues.html +5 -5
  82. package/dist/ui/serverless/secrets.html +6 -6
  83. package/dist/ui/serverless/traces.html +6 -6
  84. package/dist/ui/serverless.html +6 -6
  85. package/package.json +3 -3
  86. package/dist/chunk-6n5wgv3d.js +0 -1
@@ -1,26 +1,26 @@
1
- import{createRequire as qa}from"node:module";import{isAbsolute as $t,join as gt,relative as tr}from"node:path";import{existsSync as je,readdirSync as or}from"node:fs";import{join as Ae}from"node:path";import{createHash as br}from"node:crypto";import{copyFileSync as Ar,existsSync as Et,readdirSync as Cr,readFileSync as rt,statSync as Tr,writeFileSync as nt}from"node:fs";import{basename as vr,dirname as ia,extname as sa,join as Ke}from"node:path";import{existsSync as Ia,readFileSync as _t}from"node:fs";import{homedir as Ra}from"node:os";import{join as Na}from"node:path";import{createHash as ka}from"node:crypto";import{existsSync as st,mkdirSync as Tn,readdirSync as ua,readFileSync as da,unlinkSync as ze,writeFileSync as vn}from"node:fs";import{join as It}from"node:path";import{createHash as Wt}from"node:crypto";import{createReadStream as wn,readdirSync as En,statSync as ht}from"node:fs";import{join as Pn,relative as In}from"node:path";import{deflateRawSync as Bn}from"node:zlib";import{execSync as Fn}from"node:child_process";import{createHash as Vn}from"node:crypto";import{cpSync as jn,mkdtempSync as Kn,rmSync as Hn,writeFileSync as qn}from"node:fs";import{tmpdir as zn}from"node:os";import{dirname as Qn,isAbsolute as Jn,join as Le,resolve as Yn}from"node:path";import{fileURLToPath as Zn}from"node:url";import{execFileSync as bt}from"node:child_process";import{mkdtempSync as Ma,readFileSync as At,rmSync as xa}from"node:fs";import{tmpdir as Oa}from"node:os";import{dirname as ai,join as Pe}from"node:path";import{fileURLToPath as ri}from"node:url";import{AsyncLocalStorage as ii}from"node:async_hooks";import{createHash as si}from"node:crypto";import{readFileSync as mi}from"node:fs";import{dirname as pi,join as Ua}from"node:path";import{fileURLToPath as gi}from"node:url";import{execFileSync as ot}from"node:child_process";import{existsSync as Ti,mkdirSync as vi,mkdtempSync as wi,readdirSync as Ei,readFileSync as Pi,rmSync as Ri,statSync as Fa,writeFileSync as Ni}from"node:fs";import{tmpdir as Di}from"node:os";import{join as Me,relative as ki}from"node:path";import{execSync as $i}from"node:child_process";import{createHash as Li}from"node:crypto";import{readdirSync as Mi,readFileSync as xi,statSync as ja}from"node:fs";import{join as Oi,relative as Ka,resolve as na}from"node:path";var za=Object.defineProperty,Qa=(a)=>a;function Ja(a,n){this[a]=Qa.bind(null,n)}var Be=(a,n)=>{for(var i in n)za(a,i,{get:n[i],enumerable:!0,configurable:!0,set:Ja.bind(n,i)})},Ya=(a,n,i)=>()=>{if(a)try{n=a(a=0)}catch(s){i=[s]}if(i)throw i[0];return n},Za=qa(import.meta.url);function Bp(a){let n=typeof a==="string"?new URL(a):a,{hostname:i,pathname:s}=n;if(i.endsWith(".on.aws")){let h=i.match(/^[^.]+\.lambda-url\.([^.]+)\.on\.aws$/);if(h)return{service:"lambda",region:h[1]};return{service:"",region:""}}if(i.endsWith(".r2.cloudflarestorage.com"))return{service:"s3",region:"auto"};if(i.endsWith(".backblazeb2.com")){let h=i.match(/^(?:[^.]+\.)?s3\.([^.]+)\.backblazeb2\.com$/);if(h)return{service:"s3",region:h[1]};return{service:"",region:""}}let c=i.replace("dualstack.","").match(/([^.]+)\.(?:([^.]+)\.)?amazonaws\.com(?:\.cn)?$/);if(!c)return{service:"",region:""};let l=c[1],u=c[2]||"";if(u==="us-gov")u="us-gov-west-1";else if(u==="s3"||u==="s3-accelerate")u="us-east-1",l="s3";else if(l==="iot")if(i.startsWith("iot."))l="execute-api";else if(i.startsWith("data.jobs.iot."))l="iot-jobs-data";else l=s==="/mqtt"?"iotdevicegateway":"iotdata";else if(l==="autoscaling");else if(!u&&l.startsWith("s3-"))u=l.slice(3).replace(/^fips-|^external-1/,""),l="s3";else if(l.endsWith("-fips"))l=l.slice(0,-5);else if(u&&/-\d$/.test(l)&&!/-\d$/.test(u))[l,u]=[u,l];return l=Ca[l]||l,{service:l,region:u||"us-east-1"}}function x(a){let{method:n,url:i,body:s="",accessKeyId:c,secretAccessKey:l,sessionToken:u,signQuery:h=!1,expiresIn:y=86400,datetime:S}=a,b=new URL(i),A=b.hostname,C=Bp(b),T=a.service||C.service,v=a.region||C.region;if(!T)throw Error("Could not detect service from URL. Please provide service explicitly.");if(!v)throw Error("Could not detect region from URL. Please provide region explicitly.");let w=S||new Date().toISOString().replace(/[:-]|\.\d{3}/g,""),R=w.substring(0,8),k=[R,v,T,"aws4_request"].join("/"),W="AWS4-HMAC-SHA256";if(h)return Xa({urlObj:b,method:n,body:s,accessKeyId:c,secretAccessKey:l,sessionToken:u,service:T,region:v,timestamp:w,date:R,credentialScope:k,algorithm:W,expiresIn:y,cache:a.cache});let P=b.pathname||"/",V=ft(b.searchParams),B={host:A,"x-amz-date":w,...a.headers};if(u)B["x-amz-security-token"]=u;let j=Object.keys(B).some((Ie)=>Ie.toLowerCase()==="content-type");if(s&&!j)B["content-type"]="application/x-amz-json-1.0";if(T==="s3"&&!B["x-amz-content-sha256"])B["x-amz-content-sha256"]=Je(s);let J=ga(B),K=ha(B),X=B["x-amz-content-sha256"]||Je(s),te=[n,St(P),V,J,K,X].join(`
2
- `),ne=Je(te),me=[W,w,k,ne].join(`
3
- `),oe=a.cache??ke,ue=fa(l,R,v,T,me,oe),ie=[`${W} Credential=${c}/${k}`,`SignedHeaders=${K}`,`Signature=${ue}`].join(", ");return B.authorization=ie,{url:i,method:n,headers:B,body:s||void 0}}async function xp(a){let{method:n,url:i,body:s="",accessKeyId:c,secretAccessKey:l,sessionToken:u,signQuery:h=!1,expiresIn:y=86400,datetime:S}=a,b=new URL(i),A=b.hostname,C=Bp(b),T=a.service||C.service,v=a.region||C.region;if(!T)throw Error("Could not detect service from URL. Please provide service explicitly.");if(!v)throw Error("Could not detect region from URL. Please provide region explicitly.");let w=S||new Date().toISOString().replace(/[:-]|\.\d{3}/g,""),R=w.substring(0,8),k=[R,v,T,"aws4_request"].join("/"),W="AWS4-HMAC-SHA256";if(h)return er({urlObj:b,method:n,body:s,accessKeyId:c,secretAccessKey:l,sessionToken:u,service:T,region:v,timestamp:w,date:R,credentialScope:k,algorithm:W,expiresIn:y,cache:a.cache});let P=b.pathname||"/",V=ft(b.searchParams),B={host:A,"x-amz-date":w,...a.headers};if(u)B["x-amz-security-token"]=u;let j=Object.keys(B).some((_e)=>_e.toLowerCase()==="content-type");if(s&&!j)B["content-type"]="application/x-amz-json-1.0";let J=await lt(s);if(T==="s3"&&!B["x-amz-content-sha256"])B["x-amz-content-sha256"]=J;let K=ga(B),X=ha(B),te=B["x-amz-content-sha256"]||J,ne=[n,St(P),V,K,X,te].join(`
4
- `),me=await lt(ne),oe=[W,w,k,me].join(`
5
- `),ue=a.cache??ke,ie=await Sa(l,R,v,T,oe,ue),Ie=[`${W} Credential=${c}/${k}`,`SignedHeaders=${X}`,`Signature=${ie}`].join(", ");return B.authorization=Ie,{url:i,method:n,headers:B,body:s||void 0}}function Xa(a){let{urlObj:n,method:i,body:s,accessKeyId:c,secretAccessKey:l,sessionToken:u,service:h,region:y,timestamp:S,date:b,credentialScope:A,algorithm:C,expiresIn:T,cache:v}=a,w=new URL(n.toString());w.searchParams.set("X-Amz-Algorithm",C),w.searchParams.set("X-Amz-Credential",`${c}/${A}`),w.searchParams.set("X-Amz-Date",S),w.searchParams.set("X-Amz-Expires",String(T));let R=h==="s3"?"UNSIGNED-PAYLOAD":Je(s);if(h==="s3")w.searchParams.set("X-Amz-Content-Sha256",R);let k="host";if(w.searchParams.set("X-Amz-SignedHeaders",k),u)w.searchParams.set("X-Amz-Security-Token",u);let W=St(w.pathname||"/"),P=`host:${w.hostname}
6
- `,V=ft(w.searchParams),B=[i,W,V,P,k,R].join(`
7
- `),j=[C,S,A,Je(B)].join(`
8
- `),J=fa(l,b,y,h,j,v??ke);return w.searchParams.set("X-Amz-Signature",J),{url:w.toString(),method:i,headers:{},body:s||void 0}}async function er(a){let{urlObj:n,method:i,body:s,accessKeyId:c,secretAccessKey:l,sessionToken:u,service:h,region:y,timestamp:S,date:b,credentialScope:A,algorithm:C,expiresIn:T,cache:v}=a,w=new URL(n.toString());w.searchParams.set("X-Amz-Algorithm",C),w.searchParams.set("X-Amz-Credential",`${c}/${A}`),w.searchParams.set("X-Amz-Date",S),w.searchParams.set("X-Amz-Expires",String(T));let R=h==="s3"?"UNSIGNED-PAYLOAD":await lt(s);if(h==="s3")w.searchParams.set("X-Amz-Content-Sha256",R);let k="host";if(w.searchParams.set("X-Amz-SignedHeaders",k),u)w.searchParams.set("X-Amz-Security-Token",u);let W=St(w.pathname||"/"),P=`host:${w.hostname}
9
- `,V=ft(w.searchParams),B=[i,W,V,P,k,R].join(`
10
- `),j=[C,S,A,await lt(B)].join(`
11
- `),J=await Sa(l,b,y,h,j,v??ke);return w.searchParams.set("X-Amz-Signature",J),{url:w.toString(),method:i,headers:{},body:s||void 0}}function hf(a){let{url:n,method:i="GET",expiresIn:s=3600,...c}=a,l=Math.min(s,604800);return x({...c,url:n,method:i,signQuery:!0,expiresIn:l}).url}async function Ey(a){let{url:n,method:i="GET",expiresIn:s=3600,...c}=a,l=Math.min(s,604800);return(await xp({...c,url:n,method:i,signQuery:!0,expiresIn:l})).url}function ga(a){return Object.keys(a).sort().map((n)=>`${n.toLowerCase()}:${a[n].trim().replace(/\s+/g," ")}`).join(`
1
+ import{createRequire as qa}from"node:module";import{isAbsolute as $t,join as gt,relative as tr}from"node:path";import{existsSync as je,readdirSync as or}from"node:fs";import{join as Ce}from"node:path";import{createHash as br}from"node:crypto";import{copyFileSync as Ar,existsSync as Et,readdirSync as Cr,readFileSync as rt,statSync as Tr,writeFileSync as nt}from"node:fs";import{basename as vr,dirname as ia,extname as sa,join as Ke}from"node:path";import{existsSync as Ia,readFileSync as _t}from"node:fs";import{homedir as Ra}from"node:os";import{join as Na}from"node:path";import{createHash as ka}from"node:crypto";import{existsSync as st,mkdirSync as Tn,readdirSync as ua,readFileSync as da,unlinkSync as ze,writeFileSync as vn}from"node:fs";import{join as It}from"node:path";import{createHash as Wt}from"node:crypto";import{createReadStream as wn,readdirSync as En,statSync as ht}from"node:fs";import{join as Pn,relative as In}from"node:path";import{deflateRawSync as Bn}from"node:zlib";import{execSync as Fn}from"node:child_process";import{createHash as Vn}from"node:crypto";import{cpSync as jn,mkdtempSync as Kn,rmSync as Hn,writeFileSync as qn}from"node:fs";import{tmpdir as zn}from"node:os";import{dirname as Qn,isAbsolute as Jn,join as Le,resolve as Yn}from"node:path";import{fileURLToPath as Zn}from"node:url";import{execFileSync as bt}from"node:child_process";import{mkdtempSync as Ma,readFileSync as At,rmSync as xa}from"node:fs";import{tmpdir as Oa}from"node:os";import{dirname as ai,join as Pe}from"node:path";import{fileURLToPath as ri}from"node:url";import{AsyncLocalStorage as ii}from"node:async_hooks";import{createHash as si}from"node:crypto";import{readFileSync as mi}from"node:fs";import{dirname as pi,join as Ua}from"node:path";import{fileURLToPath as gi}from"node:url";import{execFileSync as ot}from"node:child_process";import{existsSync as bi,mkdirSync as Ti,mkdtempSync as vi,readdirSync as wi,readFileSync as Pi,rmSync as Ri,statSync as Fa,writeFileSync as Ni}from"node:fs";import{tmpdir as Di}from"node:os";import{join as Me,relative as ki}from"node:path";import{execSync as $i}from"node:child_process";import{createHash as Li}from"node:crypto";import{readdirSync as Mi,readFileSync as xi,statSync as ja}from"node:fs";import{join as Oi,relative as Ka,resolve as na}from"node:path";var za=Object.defineProperty,Qa=(a)=>a;function Ja(a,n){this[a]=Qa.bind(null,n)}var Be=(a,n)=>{for(var i in n)za(a,i,{get:n[i],enumerable:!0,configurable:!0,set:Ja.bind(n,i)})},Ya=(a,n,i)=>()=>{if(a)try{n=a(a=0)}catch(s){i=[s]}if(i)throw i[0];return n},Za=qa(import.meta.url);function Bp(a){let n=typeof a==="string"?new URL(a):a,{hostname:i,pathname:s}=n;if(i.endsWith(".on.aws")){let h=i.match(/^[^.]+\.lambda-url\.([^.]+)\.on\.aws$/);if(h)return{service:"lambda",region:h[1]};return{service:"",region:""}}if(i.endsWith(".r2.cloudflarestorage.com"))return{service:"s3",region:"auto"};if(i.endsWith(".backblazeb2.com")){let h=i.match(/^(?:[^.]+\.)?s3\.([^.]+)\.backblazeb2\.com$/);if(h)return{service:"s3",region:h[1]};return{service:"",region:""}}let c=i.replace("dualstack.","").match(/([^.]+)\.(?:([^.]+)\.)?amazonaws\.com(?:\.cn)?$/);if(!c)return{service:"",region:""};let l=c[1],u=c[2]||"";if(u==="us-gov")u="us-gov-west-1";else if(u==="s3"||u==="s3-accelerate")u="us-east-1",l="s3";else if(l==="iot")if(i.startsWith("iot."))l="execute-api";else if(i.startsWith("data.jobs.iot."))l="iot-jobs-data";else l=s==="/mqtt"?"iotdevicegateway":"iotdata";else if(l==="autoscaling");else if(!u&&l.startsWith("s3-"))u=l.slice(3).replace(/^fips-|^external-1/,""),l="s3";else if(l.endsWith("-fips"))l=l.slice(0,-5);else if(u&&/-\d$/.test(l)&&!/-\d$/.test(u))[l,u]=[u,l];return l=Ca[l]||l,{service:l,region:u||"us-east-1"}}function _(a){let{method:n,url:i,body:s="",accessKeyId:c,secretAccessKey:l,sessionToken:u,signQuery:h=!1,expiresIn:y=86400,datetime:S}=a,A=new URL(i),C=A.hostname,T=Bp(A),v=a.service||T.service,w=a.region||T.region;if(!v)throw Error("Could not detect service from URL. Please provide service explicitly.");if(!w)throw Error("Could not detect region from URL. Please provide region explicitly.");let E=S||new Date().toISOString().replace(/[:-]|\.\d{3}/g,""),R=E.substring(0,8),k=[R,w,v,"aws4_request"].join("/"),W="AWS4-HMAC-SHA256";if(h)return Xa({urlObj:A,method:n,body:s,accessKeyId:c,secretAccessKey:l,sessionToken:u,service:v,region:w,timestamp:E,date:R,credentialScope:k,algorithm:W,expiresIn:y,cache:a.cache});let P=A.pathname||"/",V=ft(A.searchParams),B={host:C,"x-amz-date":E,...a.headers};if(u)B["x-amz-security-token"]=u;let j=Object.keys(B).some((Ie)=>Ie.toLowerCase()==="content-type");if(s&&!j)B["content-type"]="application/x-amz-json-1.0";if(v==="s3"&&!B["x-amz-content-sha256"])B["x-amz-content-sha256"]=Je(s);let J=ga(B),K=ha(B),X=B["x-amz-content-sha256"]||Je(s),te=[n,St(P),V,J,K,X].join(`
2
+ `),ne=Je(te),me=[W,E,k,ne].join(`
3
+ `),oe=a.cache??ke,ue=fa(l,R,w,v,me,oe),ie=[`${W} Credential=${c}/${k}`,`SignedHeaders=${K}`,`Signature=${ue}`].join(", ");return B.authorization=ie,{url:i,method:n,headers:B,body:s||void 0}}async function _p(a){let{method:n,url:i,body:s="",accessKeyId:c,secretAccessKey:l,sessionToken:u,signQuery:h=!1,expiresIn:y=86400,datetime:S}=a,A=new URL(i),C=A.hostname,T=Bp(A),v=a.service||T.service,w=a.region||T.region;if(!v)throw Error("Could not detect service from URL. Please provide service explicitly.");if(!w)throw Error("Could not detect region from URL. Please provide region explicitly.");let E=S||new Date().toISOString().replace(/[:-]|\.\d{3}/g,""),R=E.substring(0,8),k=[R,w,v,"aws4_request"].join("/"),W="AWS4-HMAC-SHA256";if(h)return er({urlObj:A,method:n,body:s,accessKeyId:c,secretAccessKey:l,sessionToken:u,service:v,region:w,timestamp:E,date:R,credentialScope:k,algorithm:W,expiresIn:y,cache:a.cache});let P=A.pathname||"/",V=ft(A.searchParams),B={host:C,"x-amz-date":E,...a.headers};if(u)B["x-amz-security-token"]=u;let j=Object.keys(B).some((_e)=>_e.toLowerCase()==="content-type");if(s&&!j)B["content-type"]="application/x-amz-json-1.0";let J=await lt(s);if(v==="s3"&&!B["x-amz-content-sha256"])B["x-amz-content-sha256"]=J;let K=ga(B),X=ha(B),te=B["x-amz-content-sha256"]||J,ne=[n,St(P),V,K,X,te].join(`
4
+ `),me=await lt(ne),oe=[W,E,k,me].join(`
5
+ `),ue=a.cache??ke,ie=await Sa(l,R,w,v,oe,ue),Ie=[`${W} Credential=${c}/${k}`,`SignedHeaders=${X}`,`Signature=${ie}`].join(", ");return B.authorization=Ie,{url:i,method:n,headers:B,body:s||void 0}}function Xa(a){let{urlObj:n,method:i,body:s,accessKeyId:c,secretAccessKey:l,sessionToken:u,service:h,region:y,timestamp:S,date:A,credentialScope:C,algorithm:T,expiresIn:v,cache:w}=a,E=new URL(n.toString());E.searchParams.set("X-Amz-Algorithm",T),E.searchParams.set("X-Amz-Credential",`${c}/${C}`),E.searchParams.set("X-Amz-Date",S),E.searchParams.set("X-Amz-Expires",String(v));let R=h==="s3"?"UNSIGNED-PAYLOAD":Je(s);if(h==="s3")E.searchParams.set("X-Amz-Content-Sha256",R);let k="host";if(E.searchParams.set("X-Amz-SignedHeaders",k),u)E.searchParams.set("X-Amz-Security-Token",u);let W=St(E.pathname||"/"),P=`host:${E.hostname}
6
+ `,V=ft(E.searchParams),B=[i,W,V,P,k,R].join(`
7
+ `),j=[T,S,C,Je(B)].join(`
8
+ `),J=fa(l,A,y,h,j,w??ke);return E.searchParams.set("X-Amz-Signature",J),{url:E.toString(),method:i,headers:{},body:s||void 0}}async function er(a){let{urlObj:n,method:i,body:s,accessKeyId:c,secretAccessKey:l,sessionToken:u,service:h,region:y,timestamp:S,date:A,credentialScope:C,algorithm:T,expiresIn:v,cache:w}=a,E=new URL(n.toString());E.searchParams.set("X-Amz-Algorithm",T),E.searchParams.set("X-Amz-Credential",`${c}/${C}`),E.searchParams.set("X-Amz-Date",S),E.searchParams.set("X-Amz-Expires",String(v));let R=h==="s3"?"UNSIGNED-PAYLOAD":await lt(s);if(h==="s3")E.searchParams.set("X-Amz-Content-Sha256",R);let k="host";if(E.searchParams.set("X-Amz-SignedHeaders",k),u)E.searchParams.set("X-Amz-Security-Token",u);let W=St(E.pathname||"/"),P=`host:${E.hostname}
9
+ `,V=ft(E.searchParams),B=[i,W,V,P,k,R].join(`
10
+ `),j=[T,S,C,await lt(B)].join(`
11
+ `),J=await Sa(l,A,y,h,j,w??ke);return E.searchParams.set("X-Amz-Signature",J),{url:E.toString(),method:i,headers:{},body:s||void 0}}function hf(a){let{url:n,method:i="GET",expiresIn:s=3600,...c}=a,l=Math.min(s,604800);return _({...c,url:n,method:i,signQuery:!0,expiresIn:l}).url}async function by(a){let{url:n,method:i="GET",expiresIn:s=3600,...c}=a,l=Math.min(s,604800);return(await _p({...c,url:n,method:i,signQuery:!0,expiresIn:l})).url}function ga(a){return Object.keys(a).sort().map((n)=>`${n.toLowerCase()}:${a[n].trim().replace(/\s+/g," ")}`).join(`
12
12
  `)+`
13
- `}function ha(a){return Object.keys(a).sort().map((n)=>n.toLowerCase()).join(";")}function ft(a){let n=[];return a.forEach((i,s)=>{n.push([kt(s),kt(i)])}),n.sort((i,s)=>{if(i[0]<s[0])return-1;if(i[0]>s[0])return 1;if(i[1]<s[1])return-1;if(i[1]>s[1])return 1;return 0}),n.map(([i,s])=>`${i}=${s}`).join("&")}function St(a){return a.split("/").map((n)=>kt(n)).join("/")}function kt(a){return encodeURIComponent(a).replace(/[!'()*]/g,(n)=>`%${n.charCodeAt(0).toString(16).toUpperCase()}`)}function Je(a){if(!Oe)throw Error("Synchronous hash not available in browser. Use signRequestAsync() instead.");return Oe.createHash("sha256").update(a,"utf8").digest("hex")}function Ue(a,n){if(!Oe)throw Error("Synchronous hmac not available in browser. Use signRequestAsync() instead.");return Oe.createHmac("sha256",a).update(n,"utf8").digest()}async function lt(a){let n=new TextEncoder().encode(a),i=await crypto.subtle.digest("SHA-256",n);return ya(new Uint8Array(i))}async function Fe(a,n){let i=new TextEncoder,s=typeof a==="string"?i.encode(a):a,c=i.encode(n),l=await crypto.subtle.importKey("raw",s.buffer,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),u=await crypto.subtle.sign("HMAC",l,c.buffer);return new Uint8Array(u)}function ya(a){return Array.from(a).map((n)=>n.toString(16).padStart(2,"0")).join("")}function fa(a,n,i,s,c,l){let u=`${a}:${n}:${i}:${s}`,h=l.get(u);if(!h){let y=Ue(`AWS4${a}`,n),S=Ue(y,i),b=Ue(S,s);if(h=Ue(b,"aws4_request"),l.size>=Aa){let A=l.keys().next().value;if(A)l.delete(A)}l.set(u,h)}return Ue(h,c).toString("hex")}async function Sa(a,n,i,s,c,l){let u=`${a}:${n}:${i}:${s}`,h=l.get(u);if(!h){let S=await Fe(`AWS4${a}`,n),b=await Fe(S,i),A=await Fe(b,s);if(h=await Fe(A,"aws4_request"),l.size>=Aa){let C=l.keys().next().value;if(C)l.delete(C)}l.set(u,h)}let y=await Fe(h,c);return ya(y)}function ba(a,n){return n.includes(a)}function dt(a,n,i){let s=n*Math.pow(2,a),c=Math.random()*0.3*s;return Math.min(s+c,i)}function mt(a){return new Promise((n)=>setTimeout(n,a))}async function ff(a,n){let{maxRetries:i=3,initialDelayMs:s=100,maxDelayMs:c=5000,retryableStatusCodes:l=[429,500,502,503,504],timeoutMs:u=30000}=n??{},h,y;for(let S=0;S<=i;S++){let b=x(a),A={method:b.method,headers:b.headers};if(b.body)A.body=b.body;let C=new AbortController,T=setTimeout(()=>C.abort(),u);A.signal=C.signal;try{let v=await fetch(b.url,A);if(clearTimeout(T),y=v,v.ok)return v;if(S<i&&ba(v.status,l)){let R=dt(S,s,c);await mt(R);continue}let w=await v.text();throw Error(`AWS API request failed (${v.status}): ${w}`)}catch(v){if(clearTimeout(T),h=v,v instanceof Error&&v.name==="AbortError")h=Error(`Request timed out after ${u}ms`);if(S<i&&!(v instanceof Error&&v.message.includes("AWS API request failed"))){let w=dt(S,s,c);await mt(w);continue}throw h}}throw h??Error("Request failed after retries")}async function vy(a){return ff(a,{maxRetries:0})}async function Ty(a,n){let{maxRetries:i=3,initialDelayMs:s=100,maxDelayMs:c=5000,retryableStatusCodes:l=[429,500,502,503,504],timeoutMs:u=30000}=n??{},h;for(let y=0;y<=i;y++){let S=await xp(a),b={method:S.method,headers:S.headers};if(S.body)b.body=S.body;let A=new AbortController,C=setTimeout(()=>A.abort(),u);b.signal=A.signal;try{let T=await fetch(S.url,b);if(clearTimeout(C),T.ok)return T;if(y<i&&ba(T.status,l)){let w=dt(y,s,c);await mt(w);continue}let v=await T.text();throw Error(`AWS API request failed (${T.status}): ${v}`)}catch(T){if(clearTimeout(C),h=T,T instanceof Error&&T.name==="AbortError")h=Error(`Request timed out after ${u}ms`);if(y<i&&!(T instanceof Error&&T.message.includes("AWS API request failed"))){let v=dt(y,s,c);await mt(v);continue}throw h}}throw h??Error("Request failed after retries")}async function wy(a){let n=await a.text(),i={},s=/<(\w+)>([^<]+)<\/\1>/g,c;while((c=s.exec(n))!==null){let[,l,u]=c;i[l]=u}return i}async function Ry(a){return await a.json()}function Dy(){ke.clear()}function Py(){return ke.size}function Ny(){return Oe!==void 0}function ky(){return typeof crypto<"u"&&typeof crypto.subtle<"u"}var Oe,ke,Aa=100,Ca,et=Ya(async()=>{try{Oe=await import("node:crypto")}catch{}ke=new Map,Ca={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"}}),By={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}},xy={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}}}},_p=".ts-cloud",Op="TS_CLOUD_STATE_DIR",xt=null;function od(a){xt=a?.trim()||null}function ad(){return Boolean(process.env[Op]?.trim()||xt)}function Js(){return process.env[Op]?.trim()||xt||_p}function _(...a){return gt(Js(),...a)}function d(a,...n){let i=Js();return $t(i)?gt(i,...n):gt(a,i,...n)}function cd(a,n=process.cwd()){let i=(c,l)=>{let u=tr(c,l);return u===""||!u.startsWith("..")&&!$t(u)},s=$t(a)?a:gt(n,a);return i(d(n),s)}function Lp(a){let n=a.infrastructure?.compute!=null,i=Object.values(a.environments??{}).some((s)=>s?.app!=null);return{server:n,serverless:i}}function O(a){if(a.mode==="server"||a.mode==="serverless")return a.mode;let{serverless:n}=Lp(a);return n?"serverless":"server"}function dd(a){let{server:n,serverless:i}=Lp(a);if(n&&i)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(a.mode==="server"&&i&&!n)return"Config sets `mode: 'server'` but declares a serverless app (`environments.<env>.app`). Remove the app or change the mode.";if(a.mode==="serverless"&&n&&!i)return"Config sets `mode: 'serverless'` but declares a server (`infrastructure.compute`). Remove the compute block or change the mode.";return null}function p(a){return a.infrastructure?.appDatabase??a.infrastructure?.compute?.database}function ar(a){return typeof a==="object"&&a!==null?a:{}}function Af(a){return a===!0||typeof a==="object"&&a!==null}function rr(a,n){let i=n?a.environments?.[n]:void 0;if(i?.domain)return i.domain;let s=Object.values(a.sites??{}),c=a.sites?.main?.domain??s.find((l)=>l.domain)?.domain;if(c)return c;return`${a.project?.slug??"app"}.local`}function nr(a){let n=a.indexOf(".");return n>0?a.slice(n+1):void 0}function fi(a,n={}){let i=a.infrastructure?.compute?.managedServices?.mail,s=ar(i),c=n.environmentType??(n.environment?a.environments?.[n.environment]?.type:void 0),l=s.mode??(c==="production"?"server":"catcher"),u=l==="server",h=rr(a,n.environment),y=s.hostname??(u?`mail.${h}`:"localhost"),S=s.ports??{},b=u?{smtp:S.smtp??25,submission:S.submission??587,submissions:S.submissions??465,imap:S.imap??143,imaps:S.imaps??993,webmail:S.webmail??8080,managesieve:S.managesieve}:{smtp:S.smtp??1025,submission:S.submission,submissions:S.submissions,imap:S.imap,imaps:S.imaps,webmail:S.webmail??8025,managesieve:S.managesieve},A=s.tls??{},C=A.enabled??u,T=!!(A.certPath&&A.keyPath),v=(s.accounts??[]).map((K)=>({address:K.address,password:K.password})),w=typeof s.dkim==="object"&&s.dkim!==null?s.dkim:{},R=s.dkim===!1?!1:s.dkim===!0||u,k=typeof s.webmail==="object"&&s.webmail!==null?s.webmail:{},W=s.webmail===!1?!1:k.enabled??!0,P=s.spam??{},V=s.delivery??(u?"direct":"none"),B=s.expose??u,j=nr(y),J=[...new Set([y,...j?[j]:[],...s.domains??[]])];return{enabled:Af(i),mode:l,version:s.version,hostname:y,domains:J,ports:b,tls:{enabled:C,acme:C&&!T&&(A.acme??!0),certPath:A.certPath,keyPath:A.keyPath,requireForAuth:A.requireForAuth??(C&&u),acmeEmail:A.acmeEmail??v[0]?.address},dkim:{enabled:R,selector:w.selector??"default",rotate:w.rotate??!1,rotateIntervalDays:w.rotateIntervalDays??90},webmail:{enabled:W,port:k.port??b.webmail,domain:k.domain},delivery:V,sesRegion:s.sesRegion??"us-east-1",accounts:v,storagePath:s.storagePath??"/var/lib/mail",maxMessageSize:s.maxMessageSize??26214400,spam:{enabled:P.enabled??u,enforce:P.enforce??!1,junkScore:P.junkScore??5,rejectScore:P.rejectScore??12,dnsbl:P.dnsbl??u,greylist:P.greylist??!1},webhookUrl:s.webhookUrl,expose:B,bindAddress:B?"0.0.0.0":"127.0.0.1"}}function ld(a){if(!a.enabled||!a.expose)return[];let n=[a.ports.smtp,a.ports.submission,a.ports.submissions,a.ports.imap,a.ports.imaps,a.ports.managesieve].filter((i)=>typeof i==="number");if(a.webmail.enabled&&!a.webmail.domain)n.push(a.webmail.port);return[...new Set(n)].sort((i,s)=>i-s)}function ud(a){if(!a.enabled)return{};let n=a.ports.submission??a.ports.smtp,i={MAIL_MAILER:"smtp",MAIL_HOST:"127.0.0.1",MAIL_PORT:String(n)};if(a.mode==="server"){i.MAIL_ENCRYPTION=a.tls.enabled?"tls":"null";let s=a.accounts[0];if(s)i.MAIL_USERNAME=s.address,i.MAIL_PASSWORD=s.password}else i.MAIL_ENCRYPTION="null",i.MAIL_USERNAME="null",i.MAIL_PASSWORD="null";return i}function le(a){if(a.cloud?.provider)return a.cloud.provider;if(a.ssh?.hosts?.length)return"ssh";if(a.hetzner?.apiToken)return"hetzner";return"aws"}class pd{template;constructor(a){this.template={AWSTemplateFormatVersion:"2010-09-09",Description:a,Resources:{}}}addResource(a,n){return this.template.Resources[a]=n,this}addResources(a){return Object.assign(this.template.Resources,a),this}addParameter(a,n){if(!this.template.Parameters)this.template.Parameters={};return this.template.Parameters[a]=n,this}addOutput(a,n){if(!this.template.Outputs)this.template.Outputs={};return this.template.Outputs[a]=n,this}hasResource(a){return a in this.template.Resources}getResources(){return this.template.Resources}build(){return this.template}toJSON(a=!0){return JSON.stringify(this.template,null,a?2:0)}toYAML(){return this.convertToYAML(this.template)}convertToYAML(a,n=0){let i=" ".repeat(n),s="";for(let[c,l]of Object.entries(a)){if(l===null||l===void 0)continue;if(typeof l==="object"&&!Array.isArray(l))s+=`${i}${c}:
13
+ `}function ha(a){return Object.keys(a).sort().map((n)=>n.toLowerCase()).join(";")}function ft(a){let n=[];return a.forEach((i,s)=>{n.push([kt(s),kt(i)])}),n.sort((i,s)=>{if(i[0]<s[0])return-1;if(i[0]>s[0])return 1;if(i[1]<s[1])return-1;if(i[1]>s[1])return 1;return 0}),n.map(([i,s])=>`${i}=${s}`).join("&")}function St(a){return a.split("/").map((n)=>kt(n)).join("/")}function kt(a){return encodeURIComponent(a).replace(/[!'()*]/g,(n)=>`%${n.charCodeAt(0).toString(16).toUpperCase()}`)}function Je(a){if(!Oe)throw Error("Synchronous hash not available in browser. Use signRequestAsync() instead.");return Oe.createHash("sha256").update(a,"utf8").digest("hex")}function Ue(a,n){if(!Oe)throw Error("Synchronous hmac not available in browser. Use signRequestAsync() instead.");return Oe.createHmac("sha256",a).update(n,"utf8").digest()}async function lt(a){let n=new TextEncoder().encode(a),i=await crypto.subtle.digest("SHA-256",n);return ya(new Uint8Array(i))}async function Fe(a,n){let i=new TextEncoder,s=typeof a==="string"?i.encode(a):a,c=i.encode(n),l=await crypto.subtle.importKey("raw",s.buffer,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),u=await crypto.subtle.sign("HMAC",l,c.buffer);return new Uint8Array(u)}function ya(a){return Array.from(a).map((n)=>n.toString(16).padStart(2,"0")).join("")}function fa(a,n,i,s,c,l){let u=`${a}:${n}:${i}:${s}`,h=l.get(u);if(!h){let y=Ue(`AWS4${a}`,n),S=Ue(y,i),A=Ue(S,s);if(h=Ue(A,"aws4_request"),l.size>=Aa){let C=l.keys().next().value;if(C)l.delete(C)}l.set(u,h)}return Ue(h,c).toString("hex")}async function Sa(a,n,i,s,c,l){let u=`${a}:${n}:${i}:${s}`,h=l.get(u);if(!h){let S=await Fe(`AWS4${a}`,n),A=await Fe(S,i),C=await Fe(A,s);if(h=await Fe(C,"aws4_request"),l.size>=Aa){let T=l.keys().next().value;if(T)l.delete(T)}l.set(u,h)}let y=await Fe(h,c);return ya(y)}function ba(a,n){return n.includes(a)}function dt(a,n,i){let s=n*Math.pow(2,a),c=Math.random()*0.3*s;return Math.min(s+c,i)}function mt(a){return new Promise((n)=>setTimeout(n,a))}async function ff(a,n){let{maxRetries:i=3,initialDelayMs:s=100,maxDelayMs:c=5000,retryableStatusCodes:l=[429,500,502,503,504],timeoutMs:u=30000}=n??{},h,y;for(let S=0;S<=i;S++){let A=_(a),C={method:A.method,headers:A.headers};if(A.body)C.body=A.body;let T=new AbortController,v=setTimeout(()=>T.abort(),u);C.signal=T.signal;try{let w=await fetch(A.url,C);if(clearTimeout(v),y=w,w.ok)return w;if(S<i&&ba(w.status,l)){let R=dt(S,s,c);await mt(R);continue}let E=await w.text();throw Error(`AWS API request failed (${w.status}): ${E}`)}catch(w){if(clearTimeout(v),h=w,w instanceof Error&&w.name==="AbortError")h=Error(`Request timed out after ${u}ms`);if(S<i&&!(w instanceof Error&&w.message.includes("AWS API request failed"))){let E=dt(S,s,c);await mt(E);continue}throw h}}throw h??Error("Request failed after retries")}async function vy(a){return ff(a,{maxRetries:0})}async function Ty(a,n){let{maxRetries:i=3,initialDelayMs:s=100,maxDelayMs:c=5000,retryableStatusCodes:l=[429,500,502,503,504],timeoutMs:u=30000}=n??{},h;for(let y=0;y<=i;y++){let S=await _p(a),A={method:S.method,headers:S.headers};if(S.body)A.body=S.body;let C=new AbortController,T=setTimeout(()=>C.abort(),u);A.signal=C.signal;try{let v=await fetch(S.url,A);if(clearTimeout(T),v.ok)return v;if(y<i&&ba(v.status,l)){let E=dt(y,s,c);await mt(E);continue}let w=await v.text();throw Error(`AWS API request failed (${v.status}): ${w}`)}catch(v){if(clearTimeout(T),h=v,v instanceof Error&&v.name==="AbortError")h=Error(`Request timed out after ${u}ms`);if(y<i&&!(v instanceof Error&&v.message.includes("AWS API request failed"))){let w=dt(y,s,c);await mt(w);continue}throw h}}throw h??Error("Request failed after retries")}async function wy(a){let n=await a.text(),i={},s=/<(\w+)>([^<]+)<\/\1>/g,c;while((c=s.exec(n))!==null){let[,l,u]=c;i[l]=u}return i}async function Ry(a){return await a.json()}function Dy(){ke.clear()}function Py(){return ke.size}function Ny(){return Oe!==void 0}function ky(){return typeof crypto<"u"&&typeof crypto.subtle<"u"}var Oe,ke,Aa=100,Ca,et=Ya(async()=>{try{Oe=await import("node:crypto")}catch{}ke=new Map,Ca={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"}}),By={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}},_y={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}}}},xp=".ts-cloud",Op="TS_CLOUD_STATE_DIR",xt=null;function od(a){xt=a?.trim()||null}function ad(){return Boolean(process.env[Op]?.trim()||xt)}function Js(){return process.env[Op]?.trim()||xt||xp}function x(...a){return gt(Js(),...a)}function d(a,...n){let i=Js();return $t(i)?gt(i,...n):gt(a,i,...n)}function cd(a,n=process.cwd()){let i=(c,l)=>{let u=tr(c,l);return u===""||!u.startsWith("..")&&!$t(u)},s=$t(a)?a:gt(n,a);return i(d(n),s)}function Lp(a){let n=a.infrastructure?.compute!=null,i=Object.values(a.environments??{}).some((s)=>s?.app!=null);return{server:n,serverless:i}}function O(a){if(a.mode==="server"||a.mode==="serverless")return a.mode;let{serverless:n}=Lp(a);return n?"serverless":"server"}function dd(a){let{server:n,serverless:i}=Lp(a);if(n&&i)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(a.mode==="server"&&i&&!n)return"Config sets `mode: 'server'` but declares a serverless app (`environments.<env>.app`). Remove the app or change the mode.";if(a.mode==="serverless"&&n&&!i)return"Config sets `mode: 'serverless'` but declares a server (`infrastructure.compute`). Remove the compute block or change the mode.";return null}function p(a){return a.infrastructure?.appDatabase??a.infrastructure?.compute?.database}function ar(a){return typeof a==="object"&&a!==null?a:{}}function Af(a){return a===!0||typeof a==="object"&&a!==null}function rr(a,n){let i=n?a.environments?.[n]:void 0;if(i?.domain)return i.domain;let s=Object.values(a.sites??{}),c=a.sites?.main?.domain??s.find((l)=>l.domain)?.domain;if(c)return c;return`${a.project?.slug??"app"}.local`}function nr(a){let n=a.indexOf(".");return n>0?a.slice(n+1):void 0}function fi(a,n={}){let i=a.infrastructure?.compute?.managedServices?.mail,s=ar(i),c=n.environmentType??(n.environment?a.environments?.[n.environment]?.type:void 0),l=s.mode??(c==="production"?"server":"catcher"),u=l==="server",h=rr(a,n.environment),y=s.hostname??(u?`mail.${h}`:"localhost"),S=s.ports??{},A=u?{smtp:S.smtp??25,submission:S.submission??587,submissions:S.submissions??465,imap:S.imap??143,imaps:S.imaps??993,webmail:S.webmail??8080,managesieve:S.managesieve}:{smtp:S.smtp??1025,submission:S.submission,submissions:S.submissions,imap:S.imap,imaps:S.imaps,webmail:S.webmail??8025,managesieve:S.managesieve},C=s.tls??{},T=C.enabled??u,v=!!(C.certPath&&C.keyPath),w=(s.accounts??[]).map((K)=>({address:K.address,password:K.password})),E=typeof s.dkim==="object"&&s.dkim!==null?s.dkim:{},R=s.dkim===!1?!1:s.dkim===!0||u,k=typeof s.webmail==="object"&&s.webmail!==null?s.webmail:{},W=s.webmail===!1?!1:k.enabled??!0,P=s.spam??{},V=s.delivery??(u?"direct":"none"),B=s.expose??u,j=nr(y),J=[...new Set([y,...j?[j]:[],...s.domains??[]])];return{enabled:Af(i),mode:l,version:s.version,hostname:y,domains:J,ports:A,tls:{enabled:T,acme:T&&!v&&(C.acme??!0),certPath:C.certPath,keyPath:C.keyPath,requireForAuth:C.requireForAuth??(T&&u),acmeEmail:C.acmeEmail??w[0]?.address},dkim:{enabled:R,selector:E.selector??"default",rotate:E.rotate??!1,rotateIntervalDays:E.rotateIntervalDays??90},webmail:{enabled:W,port:k.port??A.webmail,domain:k.domain},delivery:V,sesRegion:s.sesRegion??"us-east-1",accounts:w,storagePath:s.storagePath??"/var/lib/mail",maxMessageSize:s.maxMessageSize??26214400,spam:{enabled:P.enabled??u,enforce:P.enforce??!1,junkScore:P.junkScore??5,rejectScore:P.rejectScore??12,dnsbl:P.dnsbl??u,greylist:P.greylist??!1},webhookUrl:s.webhookUrl,expose:B,bindAddress:B?"0.0.0.0":"127.0.0.1"}}function ld(a){if(!a.enabled||!a.expose)return[];let n=[a.ports.smtp,a.ports.submission,a.ports.submissions,a.ports.imap,a.ports.imaps,a.ports.managesieve].filter((i)=>typeof i==="number");if(a.webmail.enabled&&!a.webmail.domain)n.push(a.webmail.port);return[...new Set(n)].sort((i,s)=>i-s)}function ud(a){if(!a.enabled)return{};let n=a.ports.submission??a.ports.smtp,i={MAIL_MAILER:"smtp",MAIL_HOST:"127.0.0.1",MAIL_PORT:String(n)};if(a.mode==="server"){i.MAIL_ENCRYPTION=a.tls.enabled?"tls":"null";let s=a.accounts[0];if(s)i.MAIL_USERNAME=s.address,i.MAIL_PASSWORD=s.password}else i.MAIL_ENCRYPTION="null",i.MAIL_USERNAME="null",i.MAIL_PASSWORD="null";return i}function le(a){if(a.cloud?.provider)return a.cloud.provider;if(a.ssh?.hosts?.length)return"ssh";if(a.hetzner?.apiToken)return"hetzner";return"aws"}class pd{template;constructor(a){this.template={AWSTemplateFormatVersion:"2010-09-09",Description:a,Resources:{}}}addResource(a,n){return this.template.Resources[a]=n,this}addResources(a){return Object.assign(this.template.Resources,a),this}addParameter(a,n){if(!this.template.Parameters)this.template.Parameters={};return this.template.Parameters[a]=n,this}addOutput(a,n){if(!this.template.Outputs)this.template.Outputs={};return this.template.Outputs[a]=n,this}hasResource(a){return a in this.template.Resources}getResources(){return this.template.Resources}build(){return this.template}toJSON(a=!0){return JSON.stringify(this.template,null,a?2:0)}toYAML(){return this.convertToYAML(this.template)}convertToYAML(a,n=0){let i=" ".repeat(n),s="";for(let[c,l]of Object.entries(a)){if(l===null||l===void 0)continue;if(typeof l==="object"&&!Array.isArray(l))s+=`${i}${c}:
14
14
  ${this.convertToYAML(l,n+1)}`;else if(Array.isArray(l)){s+=`${i}${c}:
15
15
  `;for(let u of l)if(typeof u==="object")s+=`${i} -
16
16
  ${this.convertToYAML(u,n+2)}`;else s+=`${i} - ${u}
17
17
  `}else s+=`${i}${c}: ${l}
18
- `}return s}}var N={Ref:(a)=>({Ref:a}),GetAtt:(a,n)=>({"Fn::GetAtt":[a,n]}),Sub:(a,n)=>{if(n)return{"Fn::Sub":[a,n]};return{"Fn::Sub":a}},Join:(a,n)=>({"Fn::Join":[a,n]}),Select:(a,n)=>({"Fn::Select":[a,n]}),Split:(a,n)=>({"Fn::Split":[a,n]}),GetAZs:(a="")=>({"Fn::GetAZs":a}),ImportValue:(a)=>({"Fn::ImportValue":a}),If:(a,n,i)=>({"Fn::If":[a,n,i]}),Equals:(a,n)=>({"Fn::Equals":[a,n]}),And:(...a)=>({"Fn::And":a}),Or:(...a)=>({"Fn::Or":a}),Not:(a)=>({"Fn::Not":[a]}),Base64:(a)=>({"Fn::Base64":a})},_y={AccountId:{Ref:"AWS::AccountId"},Region:{Ref:"AWS::Region"},StackId:{Ref:"AWS::StackId"},StackName:{Ref:"AWS::StackName"},NotificationARNs:{Ref:"AWS::NotificationARNs"},Partition:{Ref:"AWS::Partition"},URLSuffix:{Ref:"AWS::URLSuffix"},NoValue:{Ref:"AWS::NoValue"}};function r(a){let{slug:n,environment:i,resourceType:s,timestamp:c,suffix:l}=a,u=[n,i,s];if(c)u.push(c);if(l)u.push(l);return u.join("-")}function t(a){return a.split("-").map((n)=>n.charAt(0).toUpperCase()+n.slice(1)).join("")}function Oy(){return Date.now().toString()}function Ly(a){return a.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/^-+|-+$/g,"").replace(/-+/g,"-")}function g(a,n){return a.project.stackName??`${a.project.slug}-${n}`}function $y(a,n,i,s){return i.stackName??`${a.project.slug}-${s}-${n}-site`}function My(a,n){return`${a.project.slug}-${n}`}function Fy(a,n,i,s){if(s)return s;if(i==="main")return`${a}-${n}-site`;return`${a}-${n}-${i}`}function Uy(a,n,i,s){return s??`${a}-${n}-${i}`}function Qy(a,n){return`${a}-${n}-deploy`}function Ft(a,n){return`${a.project.slug}-${n}-app`}function gd(a,n){return`${a}-${n}-deployments`}function Xs(a,n){return`${a}-${n}-assets`}class yf{nodes=new Map;addResource(a,n){let i=this.extractDependencies(n);this.nodes.set(a,{logicalId:a,resource:n,dependencies:i})}extractDependencies(a){let n=new Set;if(a.DependsOn)if(Array.isArray(a.DependsOn))a.DependsOn.forEach((i)=>n.add(i));else n.add(a.DependsOn);return this.findReferences(a.Properties||{},n),n}findReferences(a,n){if(!a||typeof a!=="object")return;if("Ref"in a&&typeof a.Ref==="string"){if(!a.Ref.startsWith("AWS::"))n.add(a.Ref)}if("Fn::GetAtt"in a&&Array.isArray(a["Fn::GetAtt"]))n.add(a["Fn::GetAtt"][0]);for(let i of Object.values(a))if(typeof i==="object")this.findReferences(i,n)}topologicalSort(){let a=[],n=new Set,i=new Set,s=(c)=>{if(n.has(c))return;if(i.has(c))throw Error(`Circular dependency detected: ${c}`);i.add(c);let l=this.nodes.get(c);if(l)for(let u of l.dependencies)s(u);i.delete(c),n.add(c),a.push(c)};for(let c of this.nodes.keys())s(c);return a}validate(){for(let[a,n]of this.nodes.entries())for(let i of n.dependencies)if(!this.nodes.has(i))throw Error(`Resource "${a}" depends on "${i}" which does not exist`)}getDependents(a){let n=[];for(let[i,s]of this.nodes.entries())if(s.dependencies.has(a))n.push(i);return n}}function Hy(a,n){let i=[],s=[],c=[],l=[],u=[],h=a.Resources||{},y=n.Resources||{},S=new Set([...Object.keys(h),...Object.keys(y)]);for(let A of S){let C=h[A],T=y[A];if(!C&&T)i.push({logicalId:A,action:"add",resourceType:T.Type});else if(C&&!T)s.push({logicalId:A,action:"remove",resourceType:C.Type});else if(C&&T)if(C.Type!==T.Type)l.push({logicalId:A,action:"replace",resourceType:T.Type,reason:`Type changed from ${C.Type} to ${T.Type}`});else{let v=Ta(C.Properties||{},T.Properties||{});if(v.length>0)if(ir(C.Type,v))l.push({logicalId:A,action:"replace",resourceType:T.Type,changes:v,reason:"Property changes require replacement"});else c.push({logicalId:A,action:"update",resourceType:T.Type,changes:v});else u.push(A)}}let b=sr([...s,...l,...c]);return{added:i,removed:s,updated:c,replaced:l,unchanged:u,summary:{totalChanges:i.length+s.length+c.length+l.length,requiresReplacement:l.length>0,dangerousChanges:b}}}function Ta(a,n,i=""){let s=[],c=new Set([...Object.keys(a),...Object.keys(n)]);for(let l of c){let u=i?`${i}.${l}`:l,h=a[l],y=n[l];if(h===void 0&&y!==void 0)s.push({path:u,oldValue:void 0,newValue:y});else if(h!==void 0&&y===void 0)s.push({path:u,oldValue:h,newValue:void 0});else if(typeof h!==typeof y)s.push({path:u,oldValue:h,newValue:y});else if(typeof h==="object"&&h!==null)if(Array.isArray(h)&&Array.isArray(y)){if(JSON.stringify(h)!==JSON.stringify(y))s.push({path:u,oldValue:h,newValue:y})}else if(!Array.isArray(h)&&!Array.isArray(y)){let S=Ta(h,y,u);s.push(...S)}else s.push({path:u,oldValue:h,newValue:y});else if(h!==y)s.push({path:u,oldValue:h,newValue:y})}return s}function ir(a,n){let i={"AWS::S3::Bucket":new Set(["BucketName"]),"AWS::DynamoDB::Table":new Set(["TableName","KeySchema"]),"AWS::RDS::DBInstance":new Set(["DBInstanceIdentifier","DBName","Engine"]),"AWS::Lambda::Function":new Set(["FunctionName"]),"AWS::EC2::Instance":new Set(["ImageId","InstanceType","KeyName"]),"AWS::ECS::TaskDefinition":new Set(["Family","ContainerDefinitions"]),"AWS::ElastiCache::CacheCluster":new Set(["CacheNodeType","Engine"]),"AWS::CloudFront::Distribution":new Set([]),"AWS::Route53::HostedZone":new Set(["Name"]),"AWS::IAM::Role":new Set(["RoleName","Path"]),"AWS::KMS::Key":new Set(["KeyPolicy"]),"AWS::Cognito::UserPool":new Set(["UserPoolName"]),"AWS::OpenSearchService::Domain":new Set(["DomainName"])}[a];if(!i)return!1;for(let s of n){let c=s.path.split(".")[0];if(i.has(c))return!0}return!1}function sr(a){let n=[];for(let i of a){if(i.action==="remove"&&(i.resourceType==="AWS::RDS::DBInstance"||i.resourceType==="AWS::DynamoDB::Table"||i.resourceType==="AWS::ElastiCache::CacheCluster"))n.push(`Removing ${i.resourceType} ${i.logicalId} - data loss risk!`);if(i.action==="replace"&&(i.resourceType==="AWS::RDS::DBInstance"||i.resourceType==="AWS::DynamoDB::Table"))n.push(`Replacing ${i.resourceType} ${i.logicalId} - data loss risk!`);if((i.action==="remove"||i.action==="replace")&&i.resourceType==="AWS::S3::Bucket")n.push(`${i.action==="remove"?"Removing":"Replacing"} S3 bucket ${i.logicalId} - data loss risk!`);if(i.action==="replace"&&i.resourceType==="AWS::EC2::Instance")n.push(`Replacing EC2 instance ${i.logicalId} - downtime expected`);if(i.action==="update"&&i.resourceType==="AWS::EC2::SecurityGroup")n.push(`Updating security group ${i.logicalId} - may affect connectivity`);if((i.action==="update"||i.action==="replace")&&(i.resourceType==="AWS::IAM::Role"||i.resourceType==="AWS::IAM::Policy"))n.push(`Modifying IAM ${i.resourceType.split("::")[2]} ${i.logicalId} - may affect permissions`)}return n}function Gy(a){let n=[];if(n.push(`=== Stack Update Analysis ===
18
+ `}return s}}var N={Ref:(a)=>({Ref:a}),GetAtt:(a,n)=>({"Fn::GetAtt":[a,n]}),Sub:(a,n)=>{if(n)return{"Fn::Sub":[a,n]};return{"Fn::Sub":a}},Join:(a,n)=>({"Fn::Join":[a,n]}),Select:(a,n)=>({"Fn::Select":[a,n]}),Split:(a,n)=>({"Fn::Split":[a,n]}),GetAZs:(a="")=>({"Fn::GetAZs":a}),ImportValue:(a)=>({"Fn::ImportValue":a}),If:(a,n,i)=>({"Fn::If":[a,n,i]}),Equals:(a,n)=>({"Fn::Equals":[a,n]}),And:(...a)=>({"Fn::And":a}),Or:(...a)=>({"Fn::Or":a}),Not:(a)=>({"Fn::Not":[a]}),Base64:(a)=>({"Fn::Base64":a})},xy={AccountId:{Ref:"AWS::AccountId"},Region:{Ref:"AWS::Region"},StackId:{Ref:"AWS::StackId"},StackName:{Ref:"AWS::StackName"},NotificationARNs:{Ref:"AWS::NotificationARNs"},Partition:{Ref:"AWS::Partition"},URLSuffix:{Ref:"AWS::URLSuffix"},NoValue:{Ref:"AWS::NoValue"}};function r(a){let{slug:n,environment:i,resourceType:s,timestamp:c,suffix:l}=a,u=[n,i,s];if(c)u.push(c);if(l)u.push(l);return u.join("-")}function t(a){return a.split("-").map((n)=>n.charAt(0).toUpperCase()+n.slice(1)).join("")}function Oy(){return Date.now().toString()}function Ly(a){return a.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/^-+|-+$/g,"").replace(/-+/g,"-")}function g(a,n){return a.project.stackName??`${a.project.slug}-${n}`}function $y(a,n,i,s){return i.stackName??`${a.project.slug}-${s}-${n}-site`}function My(a,n){return`${a.project.slug}-${n}`}function Fy(a,n,i,s){if(s)return s;if(i==="main")return`${a}-${n}-site`;return`${a}-${n}-${i}`}function Uy(a,n,i,s){return s??`${a}-${n}-${i}`}function Qy(a,n){return`${a}-${n}-deploy`}function Ft(a,n){return`${a.project.slug}-${n}-app`}function gd(a,n){return`${a}-${n}-deployments`}function Xs(a,n){return`${a}-${n}-assets`}class yf{nodes=new Map;addResource(a,n){let i=this.extractDependencies(n);this.nodes.set(a,{logicalId:a,resource:n,dependencies:i})}extractDependencies(a){let n=new Set;if(a.DependsOn)if(Array.isArray(a.DependsOn))a.DependsOn.forEach((i)=>n.add(i));else n.add(a.DependsOn);return this.findReferences(a.Properties||{},n),n}findReferences(a,n){if(!a||typeof a!=="object")return;if("Ref"in a&&typeof a.Ref==="string"){if(!a.Ref.startsWith("AWS::"))n.add(a.Ref)}if("Fn::GetAtt"in a&&Array.isArray(a["Fn::GetAtt"]))n.add(a["Fn::GetAtt"][0]);for(let i of Object.values(a))if(typeof i==="object")this.findReferences(i,n)}topologicalSort(){let a=[],n=new Set,i=new Set,s=(c)=>{if(n.has(c))return;if(i.has(c))throw Error(`Circular dependency detected: ${c}`);i.add(c);let l=this.nodes.get(c);if(l)for(let u of l.dependencies)s(u);i.delete(c),n.add(c),a.push(c)};for(let c of this.nodes.keys())s(c);return a}validate(){for(let[a,n]of this.nodes.entries())for(let i of n.dependencies)if(!this.nodes.has(i))throw Error(`Resource "${a}" depends on "${i}" which does not exist`)}getDependents(a){let n=[];for(let[i,s]of this.nodes.entries())if(s.dependencies.has(a))n.push(i);return n}}function Hy(a,n){let i=[],s=[],c=[],l=[],u=[],h=a.Resources||{},y=n.Resources||{},S=new Set([...Object.keys(h),...Object.keys(y)]);for(let C of S){let T=h[C],v=y[C];if(!T&&v)i.push({logicalId:C,action:"add",resourceType:v.Type});else if(T&&!v)s.push({logicalId:C,action:"remove",resourceType:T.Type});else if(T&&v)if(T.Type!==v.Type)l.push({logicalId:C,action:"replace",resourceType:v.Type,reason:`Type changed from ${T.Type} to ${v.Type}`});else{let w=Ta(T.Properties||{},v.Properties||{});if(w.length>0)if(ir(T.Type,w))l.push({logicalId:C,action:"replace",resourceType:v.Type,changes:w,reason:"Property changes require replacement"});else c.push({logicalId:C,action:"update",resourceType:v.Type,changes:w});else u.push(C)}}let A=sr([...s,...l,...c]);return{added:i,removed:s,updated:c,replaced:l,unchanged:u,summary:{totalChanges:i.length+s.length+c.length+l.length,requiresReplacement:l.length>0,dangerousChanges:A}}}function Ta(a,n,i=""){let s=[],c=new Set([...Object.keys(a),...Object.keys(n)]);for(let l of c){let u=i?`${i}.${l}`:l,h=a[l],y=n[l];if(h===void 0&&y!==void 0)s.push({path:u,oldValue:void 0,newValue:y});else if(h!==void 0&&y===void 0)s.push({path:u,oldValue:h,newValue:void 0});else if(typeof h!==typeof y)s.push({path:u,oldValue:h,newValue:y});else if(typeof h==="object"&&h!==null)if(Array.isArray(h)&&Array.isArray(y)){if(JSON.stringify(h)!==JSON.stringify(y))s.push({path:u,oldValue:h,newValue:y})}else if(!Array.isArray(h)&&!Array.isArray(y)){let S=Ta(h,y,u);s.push(...S)}else s.push({path:u,oldValue:h,newValue:y});else if(h!==y)s.push({path:u,oldValue:h,newValue:y})}return s}function ir(a,n){let i={"AWS::S3::Bucket":new Set(["BucketName"]),"AWS::DynamoDB::Table":new Set(["TableName","KeySchema"]),"AWS::RDS::DBInstance":new Set(["DBInstanceIdentifier","DBName","Engine"]),"AWS::Lambda::Function":new Set(["FunctionName"]),"AWS::EC2::Instance":new Set(["ImageId","InstanceType","KeyName"]),"AWS::ECS::TaskDefinition":new Set(["Family","ContainerDefinitions"]),"AWS::ElastiCache::CacheCluster":new Set(["CacheNodeType","Engine"]),"AWS::CloudFront::Distribution":new Set([]),"AWS::Route53::HostedZone":new Set(["Name"]),"AWS::IAM::Role":new Set(["RoleName","Path"]),"AWS::KMS::Key":new Set(["KeyPolicy"]),"AWS::Cognito::UserPool":new Set(["UserPoolName"]),"AWS::OpenSearchService::Domain":new Set(["DomainName"])}[a];if(!i)return!1;for(let s of n){let c=s.path.split(".")[0];if(i.has(c))return!0}return!1}function sr(a){let n=[];for(let i of a){if(i.action==="remove"&&(i.resourceType==="AWS::RDS::DBInstance"||i.resourceType==="AWS::DynamoDB::Table"||i.resourceType==="AWS::ElastiCache::CacheCluster"))n.push(`Removing ${i.resourceType} ${i.logicalId} - data loss risk!`);if(i.action==="replace"&&(i.resourceType==="AWS::RDS::DBInstance"||i.resourceType==="AWS::DynamoDB::Table"))n.push(`Replacing ${i.resourceType} ${i.logicalId} - data loss risk!`);if((i.action==="remove"||i.action==="replace")&&i.resourceType==="AWS::S3::Bucket")n.push(`${i.action==="remove"?"Removing":"Replacing"} S3 bucket ${i.logicalId} - data loss risk!`);if(i.action==="replace"&&i.resourceType==="AWS::EC2::Instance")n.push(`Replacing EC2 instance ${i.logicalId} - downtime expected`);if(i.action==="update"&&i.resourceType==="AWS::EC2::SecurityGroup")n.push(`Updating security group ${i.logicalId} - may affect connectivity`);if((i.action==="update"||i.action==="replace")&&(i.resourceType==="AWS::IAM::Role"||i.resourceType==="AWS::IAM::Policy"))n.push(`Modifying IAM ${i.resourceType.split("::")[2]} ${i.logicalId} - may affect permissions`)}return n}function Gy(a){let n=[];if(n.push(`=== Stack Update Analysis ===
19
19
  `),a.summary.totalChanges===0)return n.push(`No changes detected.
20
20
  `),n.join(`
21
21
  `);if(n.push(`Total changes: ${a.summary.totalChanges}`),n.push(`Requires replacement: ${a.summary.requiresReplacement?"Yes":"No"}
22
22
  `),a.summary.dangerousChanges.length>0){n.push("⚠️ DANGEROUS CHANGES DETECTED:");for(let i of a.summary.dangerousChanges)n.push(` • ${i}`);n.push("")}if(a.added.length>0){n.push(`✅ Resources to Add (${a.added.length}):`);for(let i of a.added)n.push(` + ${i.logicalId} (${i.resourceType})`);n.push("")}if(a.removed.length>0){n.push(`❌ Resources to Remove (${a.removed.length}):`);for(let i of a.removed)n.push(` - ${i.logicalId} (${i.resourceType})`);n.push("")}if(a.replaced.length>0){n.push(`\uD83D\uDD04 Resources to Replace (${a.replaced.length}):`);for(let i of a.replaced){if(n.push(` ~ ${i.logicalId} (${i.resourceType})`),i.reason)n.push(` Reason: ${i.reason}`);if(i.changes){for(let s of i.changes.slice(0,3))n.push(` • ${s.path}: ${JSON.stringify(s.oldValue)} → ${JSON.stringify(s.newValue)}`);if(i.changes.length>3)n.push(` ... and ${i.changes.length-3} more changes`)}}n.push("")}if(a.updated.length>0){n.push(`\uD83D\uDCDD Resources to Update (${a.updated.length}):`);for(let i of a.updated)if(n.push(` ~ ${i.logicalId} (${i.resourceType})`),i.changes){for(let s of i.changes.slice(0,3))n.push(` • ${s.path}: ${JSON.stringify(s.oldValue)} → ${JSON.stringify(s.newValue)}`);if(i.changes.length>3)n.push(` ... and ${i.changes.length-3} more changes`)}n.push("")}if(a.unchanged.length>0)n.push(`⚪ Unchanged Resources (${a.unchanged.length})`);return n.join(`
23
- `)}class Ee{static createBucket(a){let{name:n,bucketName:i,slug:s,environment:c,public:l=!1,versioning:u=!1,website:h=!1,encryption:y=!0,intelligentTiering:S=!1,cors:b,lifecycleRules:A}=a,C=i??r({slug:s,environment:c,resourceType:"s3",suffix:n}),T=t(C),v={Type:"AWS::S3::Bucket",Properties:{BucketName:C}};if(y)v.Properties.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(u)v.Properties.VersioningConfiguration={Status:"Enabled"};if(h)v.Properties.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"error.html"};if(!l)v.Properties.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(b&&b.length>0)v.Properties.CorsConfiguration={CorsRules:b.map((R)=>({AllowedOrigins:R.allowedOrigins,AllowedMethods:R.allowedMethods,AllowedHeaders:R.allowedHeaders,MaxAge:R.maxAge}))};if(A&&A.length>0)v.Properties.LifecycleConfiguration={Rules:A.map((R)=>({Id:R.id,Status:R.enabled?"Enabled":"Disabled",ExpirationInDays:R.expirationDays,Transitions:R.transitions?.map((k)=>({TransitionInDays:k.days,StorageClass:k.storageClass}))}))};if(S&&A){let R={id:"IntelligentTieringRule",enabled:!0,transitions:[{days:0,storageClass:"INTELLIGENT_TIERING"}]};if(!v.Properties.LifecycleConfiguration)v.Properties.LifecycleConfiguration={Rules:[]};v.Properties.LifecycleConfiguration.Rules.push({Id:R.id,Status:"Enabled",Transitions:R.transitions?.map((k)=>({TransitionInDays:k.days,StorageClass:k.storageClass}))})}let w;if(l)w={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:N.Ref(T),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[N.Join("",[N.GetAtt(T,"Arn"),"/*"])]}]}}};return{bucket:v,bucketPolicy:w,logicalId:T}}static enableVersioning(a){if(!a.Properties)a.Properties={};return a.Properties.VersioningConfiguration={Status:"Enabled"},a}static enableWebsiteHosting(a,n="index.html",i="error.html"){if(!a.Properties)a.Properties={};return a.Properties.WebsiteConfiguration={IndexDocument:n,ErrorDocument:i},a}static setLifecycleRules(a,n){if(!a.Properties)a.Properties={};return a.Properties.LifecycleConfiguration={Rules:n.map((i)=>({Id:i.id,Status:i.enabled?"Enabled":"Disabled",ExpirationInDays:i.expirationDays,Transitions:i.transitions?.map((s)=>({TransitionInDays:s.days,StorageClass:s.storageClass}))}))},a}static enableIntelligentTiering(a){if(!a.Properties)a.Properties={};if(!a.Properties.LifecycleConfiguration)a.Properties.LifecycleConfiguration={Rules:[]};return a.Properties.LifecycleConfiguration.Rules.push({Id:"IntelligentTieringRule",Status:"Enabled",Transitions:[{TransitionInDays:0,StorageClass:"INTELLIGENT_TIERING"}]}),a}static addLambdaNotification(a,n){if(!a.Properties)a.Properties={};if(!a.Properties.NotificationConfiguration)a.Properties.NotificationConfiguration={};if(!a.Properties.NotificationConfiguration.LambdaConfigurations)a.Properties.NotificationConfiguration.LambdaConfigurations=[];let i={Event:n.events[0],Function:n.functionArn};if(n.filter)i.Filter={S3Key:{Rules:[...n.filter.prefix?[{Name:"prefix",Value:n.filter.prefix}]:[],...n.filter.suffix?[{Name:"suffix",Value:n.filter.suffix}]:[]]}};for(let s of n.events){let c={...i,Event:s};a.Properties.NotificationConfiguration.LambdaConfigurations.push(c)}return a}static Notifications={onObjectCreated:(a)=>({functionArn:a,events:["s3:ObjectCreated:*"]}),onObjectRemoved:(a)=>({functionArn:a,events:["s3:ObjectRemoved:*"]}),onImageUpload:(a,n)=>({functionArn:a,events:["s3:ObjectCreated:*"],filter:{prefix:n,suffix:".jpg"}}),onFileType:(a,n,i)=>({functionArn:a,events:["s3:ObjectCreated:*"],filter:{prefix:i,suffix:n}}),onFolderUpload:(a,n)=>({functionArn:a,events:["s3:ObjectCreated:*"],filter:{prefix:n.endsWith("/")?n:`${n}/`}})};static createBackupPlan(a){let{name:n,slug:i,environment:s,bucketLogicalIds:c,retentionDays:l,schedule:u="cron(0 5 * * ? *)",vaultName:h,enableContinuousBackup:y=!1,moveToColdStorageAfterDays:S}=a,b=h||r({slug:i,environment:s,resourceType:"backup-vault",suffix:n}),A=t(b),C={Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:b}},T=r({slug:i,environment:s,resourceType:"backup-role",suffix:n}),v=t(T),w={Type:"AWS::IAM::Role",Properties:{RoleName:T,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"backup.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup","arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForRestores"]}},R=r({slug:i,environment:s,resourceType:"backup-plan",suffix:n}),k=t(R),W={DeleteAfterDays:l};if(S&&S<l)W.MoveToColdStorageAfterDays=S;let P={Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:R,BackupPlanRule:[{RuleName:`${n}-daily-backup`,TargetBackupVault:N.Ref(A),ScheduleExpression:u,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:W,EnableContinuousBackup:y}]}}},V=r({slug:i,environment:s,resourceType:"backup-selection",suffix:n}),B=t(V),j=c.map((K)=>N.GetAtt(K,"Arn")),J={Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:N.Ref(k),BackupSelection:{SelectionName:V,IamRoleArn:N.GetAtt(v,"Arn"),Resources:j}}};return{vault:C,plan:P,selection:J,role:w,vaultLogicalId:A,planLogicalId:k,selectionLogicalId:B,roleLogicalId:v}}static BackupSchedules={HOURLY:"cron(0 * * * ? *)",DAILY_5AM:"cron(0 5 * * ? *)",DAILY_MIDNIGHT:"cron(0 0 * * ? *)",WEEKLY_SUNDAY:"cron(0 5 ? * SUN *)",WEEKLY_SATURDAY:"cron(0 5 ? * SAT *)",MONTHLY_FIRST:"cron(0 5 1 * ? *)",EVERY_12_HOURS:"cron(0 */12 * * ? *)",EVERY_6_HOURS:"cron(0 */6 * * ? *)"};static BackupRetention={ONE_DAY:1,ONE_WEEK:7,TWO_WEEKS:14,ONE_MONTH:30,THREE_MONTHS:90,SIX_MONTHS:180,ONE_YEAR:365,TWO_YEARS:730,FIVE_YEARS:1825,SEVEN_YEARS:2555};static createWwwRedirectBucket(a){let{slug:n,environment:i,sourceDomain:s,targetDomain:c,protocol:l="https"}=a,u=r({slug:n,environment:i,resourceType:"s3",suffix:"www-redirect"}),h=t(u),y={Type:"AWS::S3::Bucket",Properties:{BucketName:s,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:c,Protocol:l}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1}}},S={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:N.Ref(h),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[N.Join("",[N.GetAtt(h,"Arn"),"/*"])]}]}}};return{bucket:y,bucketPolicy:S,logicalId:h}}static createDocsBucket(a){let{slug:n,environment:i,domain:s}=a,c=s||r({slug:n,environment:i,resourceType:"s3",suffix:"docs"}),l=t(c);return{bucket:{Type:"AWS::S3::Bucket",Properties:{BucketName:c,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},Tags:[{Key:"backup",Value:"weekly"}]}},logicalId:l}}static createEmailBucket(a){let{slug:n,environment:i}=a,s=r({slug:n,environment:i,resourceType:"s3",suffix:"email"}),c=t(s),l={Type:"AWS::S3::Bucket",Properties:{BucketName:s,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},LifecycleConfiguration:{Rules:[{Id:"EmailRetention",Status:"Enabled",ExpirationInDays:90,Transitions:[{TransitionInDays:30,StorageClass:"STANDARD_IA"}]}]}}},u={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:N.Ref(c),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowSESPuts",Effect:"Allow",Principal:{Service:"ses.amazonaws.com"},Action:"s3:PutObject",Resource:N.Join("",[N.GetAtt(c,"Arn"),"/*"]),Condition:{StringEquals:{"AWS:SourceAccount":N.Ref("AWS::AccountId")}}}]}}};return{bucket:l,bucketPolicy:u,logicalId:c}}static docsExist(a={}){let{projectRoot:n=process.cwd(),docsPaths:i=["docs","documentation","doc"]}=a;for(let s of i){let c=Ae(n,s);if(je(c)){let l=["dist","build",".bunpress/dist","_site","out","public"];for(let u of l){let h=Ae(c,u);if(je(h))try{if(or(h).length>0)return{exists:!0,path:c,hasDistFolder:!0,distPath:h}}catch{}}return{exists:!0,path:c,hasDistFolder:!1,distPath:null}}}return{exists:!1,path:null,hasDistFolder:!1,distPath:null}}static createDocsBucketIfExists(a){let n=Ee.docsExist({projectRoot:a.projectRoot,docsPaths:a.docsPaths});if(!n.exists)return{bucket:null,logicalId:null,docsInfo:n};let i=Ee.createDocsBucket({slug:a.slug,environment:a.environment,domain:a.domain});return{bucket:i.bucket,bucketPolicy:i.bucketPolicy,logicalId:i.logicalId,docsInfo:n}}static createPrivateBucket(a){let{slug:n,environment:i,enableVersioning:s=!0,retentionDays:c,encryptionKeyArn:l}=a,u=r({slug:n,environment:i,resourceType:"s3",suffix:"private"}),h=t(u);return{bucket:{Type:"AWS::S3::Bucket",Properties:{BucketName:u,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:l?{SSEAlgorithm:"aws:kms",KMSMasterKeyID:l}:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},VersioningConfiguration:s?{Status:"Enabled"}:void 0,LifecycleConfiguration:c?{Rules:[{Id:"RetentionPolicy",Status:"Enabled",ExpirationInDays:c}]}:void 0,Tags:[{Key:"backup",Value:"daily"}]}},logicalId:h}}static checkSourcePaths(a={}){let{projectRoot:n=process.cwd(),paths:i={}}=a,s=i.web||"views/web/dist",c=i.docs||"docs/dist",l=i.private||"private";return{web:{exists:je(Ae(n,s)),path:Ae(n,s)},docs:{exists:je(Ae(n,c)),path:Ae(n,c)},private:{exists:je(Ae(n,l)),path:Ae(n,l)}}}static createDeploymentBuckets(a){let{slug:n,environment:i,domain:s,projectRoot:c,paths:l}=a,u=Ee.checkSourcePaths({projectRoot:c,paths:l}),h={},y={web:!1,docs:!1,private:!1},S=Ee.createBucket({name:"web",slug:n,environment:i,public:!1,versioning:!1,encryption:!0});if(h[S.logicalId]=S.bucket,y.web=!0,u.docs.exists){let b=Ee.createDocsBucket({slug:n,environment:i,domain:s?`docs.${s}`:void 0});if(h[b.logicalId]=b.bucket,b.bucketPolicy)h[`${b.logicalId}Policy`]=b.bucketPolicy;y.docs=!0}if(u.private.exists){let b=Ee.createPrivateBucket({slug:n,environment:i,enableVersioning:!0});h[b.logicalId]=b.bucket,y.private=!0}return{resources:h,created:y,sourcePaths:u}}}class He{static createRepository(a){let{name:n,slug:i,environment:s,scanOnPush:c=!0,imageMutability:l="MUTABLE",encryption:u="AES256",kmsKey:h,lifecyclePolicy:y,tags:S}=a,b=r({slug:i,environment:s,resourceType:"ecr",suffix:n}),A=t(b),C={Type:"AWS::ECR::Repository",Properties:{RepositoryName:b,ImageTagMutability:l,ImageScanningConfiguration:{ScanOnPush:c},EncryptionConfiguration:{EncryptionType:u,...h&&u==="KMS"?{KmsKey:h}:{}}}};if(y)C.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(He.generateLifecyclePolicy(y))};if(S)C.Properties.Tags=Object.entries(S).map(([T,v])=>({Key:T,Value:v}));return{repository:C,logicalId:A}}static generateLifecyclePolicy(a){let n=[];if(a.untaggedImageExpireDays!==void 0)n.push({rulePriority:1,description:"Delete untagged images",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:a.untaggedImageExpireDays,countUnit:"days"},action:{type:"expire"}});if(a.maxImageCount!==void 0)n.push({rulePriority:n.length+1,description:"Keep only most recent images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:a.maxImageCount},action:{type:"expire"}});if(a.maxImageAgeDays!==void 0)n.push({rulePriority:n.length+1,description:"Delete images older than specified days",selection:{tagStatus:"any",countType:"sinceImagePushed",countNumber:a.maxImageAgeDays,countUnit:"days"},action:{type:"expire"}});return{rules:n}}static LifecyclePolicies={production:{maxImageCount:10,untaggedImageExpireDays:7},development:{maxImageCount:5,untaggedImageExpireDays:3},minimal:{maxImageCount:3,untaggedImageExpireDays:1},archive:{maxImageCount:50,untaggedImageExpireDays:30}};static enableImmutableTags(a){if(!a.Properties)a.Properties={};return a.Properties.ImageTagMutability="IMMUTABLE",a}static enableScanOnPush(a){if(!a.Properties)a.Properties={};return a.Properties.ImageScanningConfiguration={ScanOnPush:!0},a}static setLifecyclePolicy(a,n){if(!a.Properties)a.Properties={};return a.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(He.generateLifecyclePolicy(n))},a}static addCrossAccountAccess(a,n){if(!a.Properties)a.Properties={};return a.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"CrossAccountPull",Effect:"Allow",Principal:{AWS:n.map((i)=>`arn:aws:iam::${i}:root`)},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:BatchCheckLayerAvailability"]}]},a}static addLambdaAccess(a){if(!a.Properties)a.Properties={};return a.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"LambdaECRImageRetrievalPolicy",Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage"]}]},a}static generateBunDockerfile(a){let{baseImage:n="oven/bun:1-debian",serverPath:i,port:s=3000,additionalDirs:c=[],healthCheckEndpoint:l="/health",nodeCompatible:u=!1,envVars:h={},buildCommands:y=[],runCommand:S}=a,b=["app","config",...c],A=S||`bun run ${i}`,C=`# Multi-stage build for Bun application
23
+ `)}class be{static createBucket(a){let{name:n,bucketName:i,slug:s,environment:c,public:l=!1,versioning:u=!1,website:h=!1,encryption:y=!0,intelligentTiering:S=!1,cors:A,lifecycleRules:C}=a,T=i??r({slug:s,environment:c,resourceType:"s3",suffix:n}),v=t(T),w={Type:"AWS::S3::Bucket",Properties:{BucketName:T}};if(y)w.Properties.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(u)w.Properties.VersioningConfiguration={Status:"Enabled"};if(h)w.Properties.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"error.html"};if(!l)w.Properties.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(A&&A.length>0)w.Properties.CorsConfiguration={CorsRules:A.map((R)=>({AllowedOrigins:R.allowedOrigins,AllowedMethods:R.allowedMethods,AllowedHeaders:R.allowedHeaders,MaxAge:R.maxAge}))};if(C&&C.length>0)w.Properties.LifecycleConfiguration={Rules:C.map((R)=>({Id:R.id,Status:R.enabled?"Enabled":"Disabled",ExpirationInDays:R.expirationDays,Transitions:R.transitions?.map((k)=>({TransitionInDays:k.days,StorageClass:k.storageClass}))}))};if(S&&C){let R={id:"IntelligentTieringRule",enabled:!0,transitions:[{days:0,storageClass:"INTELLIGENT_TIERING"}]};if(!w.Properties.LifecycleConfiguration)w.Properties.LifecycleConfiguration={Rules:[]};w.Properties.LifecycleConfiguration.Rules.push({Id:R.id,Status:"Enabled",Transitions:R.transitions?.map((k)=>({TransitionInDays:k.days,StorageClass:k.storageClass}))})}let E;if(l)E={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:N.Ref(v),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[N.Join("",[N.GetAtt(v,"Arn"),"/*"])]}]}}};return{bucket:w,bucketPolicy:E,logicalId:v}}static enableVersioning(a){if(!a.Properties)a.Properties={};return a.Properties.VersioningConfiguration={Status:"Enabled"},a}static enableWebsiteHosting(a,n="index.html",i="error.html"){if(!a.Properties)a.Properties={};return a.Properties.WebsiteConfiguration={IndexDocument:n,ErrorDocument:i},a}static setLifecycleRules(a,n){if(!a.Properties)a.Properties={};return a.Properties.LifecycleConfiguration={Rules:n.map((i)=>({Id:i.id,Status:i.enabled?"Enabled":"Disabled",ExpirationInDays:i.expirationDays,Transitions:i.transitions?.map((s)=>({TransitionInDays:s.days,StorageClass:s.storageClass}))}))},a}static enableIntelligentTiering(a){if(!a.Properties)a.Properties={};if(!a.Properties.LifecycleConfiguration)a.Properties.LifecycleConfiguration={Rules:[]};return a.Properties.LifecycleConfiguration.Rules.push({Id:"IntelligentTieringRule",Status:"Enabled",Transitions:[{TransitionInDays:0,StorageClass:"INTELLIGENT_TIERING"}]}),a}static addLambdaNotification(a,n){if(!a.Properties)a.Properties={};if(!a.Properties.NotificationConfiguration)a.Properties.NotificationConfiguration={};if(!a.Properties.NotificationConfiguration.LambdaConfigurations)a.Properties.NotificationConfiguration.LambdaConfigurations=[];let i={Event:n.events[0],Function:n.functionArn};if(n.filter)i.Filter={S3Key:{Rules:[...n.filter.prefix?[{Name:"prefix",Value:n.filter.prefix}]:[],...n.filter.suffix?[{Name:"suffix",Value:n.filter.suffix}]:[]]}};for(let s of n.events){let c={...i,Event:s};a.Properties.NotificationConfiguration.LambdaConfigurations.push(c)}return a}static Notifications={onObjectCreated:(a)=>({functionArn:a,events:["s3:ObjectCreated:*"]}),onObjectRemoved:(a)=>({functionArn:a,events:["s3:ObjectRemoved:*"]}),onImageUpload:(a,n)=>({functionArn:a,events:["s3:ObjectCreated:*"],filter:{prefix:n,suffix:".jpg"}}),onFileType:(a,n,i)=>({functionArn:a,events:["s3:ObjectCreated:*"],filter:{prefix:i,suffix:n}}),onFolderUpload:(a,n)=>({functionArn:a,events:["s3:ObjectCreated:*"],filter:{prefix:n.endsWith("/")?n:`${n}/`}})};static createBackupPlan(a){let{name:n,slug:i,environment:s,bucketLogicalIds:c,retentionDays:l,schedule:u="cron(0 5 * * ? *)",vaultName:h,enableContinuousBackup:y=!1,moveToColdStorageAfterDays:S}=a,A=h||r({slug:i,environment:s,resourceType:"backup-vault",suffix:n}),C=t(A),T={Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:A}},v=r({slug:i,environment:s,resourceType:"backup-role",suffix:n}),w=t(v),E={Type:"AWS::IAM::Role",Properties:{RoleName:v,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"backup.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup","arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForRestores"]}},R=r({slug:i,environment:s,resourceType:"backup-plan",suffix:n}),k=t(R),W={DeleteAfterDays:l};if(S&&S<l)W.MoveToColdStorageAfterDays=S;let P={Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:R,BackupPlanRule:[{RuleName:`${n}-daily-backup`,TargetBackupVault:N.Ref(C),ScheduleExpression:u,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:W,EnableContinuousBackup:y}]}}},V=r({slug:i,environment:s,resourceType:"backup-selection",suffix:n}),B=t(V),j=c.map((K)=>N.GetAtt(K,"Arn")),J={Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:N.Ref(k),BackupSelection:{SelectionName:V,IamRoleArn:N.GetAtt(w,"Arn"),Resources:j}}};return{vault:T,plan:P,selection:J,role:E,vaultLogicalId:C,planLogicalId:k,selectionLogicalId:B,roleLogicalId:w}}static BackupSchedules={HOURLY:"cron(0 * * * ? *)",DAILY_5AM:"cron(0 5 * * ? *)",DAILY_MIDNIGHT:"cron(0 0 * * ? *)",WEEKLY_SUNDAY:"cron(0 5 ? * SUN *)",WEEKLY_SATURDAY:"cron(0 5 ? * SAT *)",MONTHLY_FIRST:"cron(0 5 1 * ? *)",EVERY_12_HOURS:"cron(0 */12 * * ? *)",EVERY_6_HOURS:"cron(0 */6 * * ? *)"};static BackupRetention={ONE_DAY:1,ONE_WEEK:7,TWO_WEEKS:14,ONE_MONTH:30,THREE_MONTHS:90,SIX_MONTHS:180,ONE_YEAR:365,TWO_YEARS:730,FIVE_YEARS:1825,SEVEN_YEARS:2555};static createWwwRedirectBucket(a){let{slug:n,environment:i,sourceDomain:s,targetDomain:c,protocol:l="https"}=a,u=r({slug:n,environment:i,resourceType:"s3",suffix:"www-redirect"}),h=t(u),y={Type:"AWS::S3::Bucket",Properties:{BucketName:s,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:c,Protocol:l}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1}}},S={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:N.Ref(h),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[N.Join("",[N.GetAtt(h,"Arn"),"/*"])]}]}}};return{bucket:y,bucketPolicy:S,logicalId:h}}static createDocsBucket(a){let{slug:n,environment:i,domain:s}=a,c=s||r({slug:n,environment:i,resourceType:"s3",suffix:"docs"}),l=t(c);return{bucket:{Type:"AWS::S3::Bucket",Properties:{BucketName:c,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},Tags:[{Key:"backup",Value:"weekly"}]}},logicalId:l}}static createEmailBucket(a){let{slug:n,environment:i}=a,s=r({slug:n,environment:i,resourceType:"s3",suffix:"email"}),c=t(s),l={Type:"AWS::S3::Bucket",Properties:{BucketName:s,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},LifecycleConfiguration:{Rules:[{Id:"EmailRetention",Status:"Enabled",ExpirationInDays:90,Transitions:[{TransitionInDays:30,StorageClass:"STANDARD_IA"}]}]}}},u={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:N.Ref(c),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowSESPuts",Effect:"Allow",Principal:{Service:"ses.amazonaws.com"},Action:"s3:PutObject",Resource:N.Join("",[N.GetAtt(c,"Arn"),"/*"]),Condition:{StringEquals:{"AWS:SourceAccount":N.Ref("AWS::AccountId")}}}]}}};return{bucket:l,bucketPolicy:u,logicalId:c}}static docsExist(a={}){let{projectRoot:n=process.cwd(),docsPaths:i=["docs","documentation","doc"]}=a;for(let s of i){let c=Ce(n,s);if(je(c)){let l=["dist","build",".bunpress/dist","_site","out","public"];for(let u of l){let h=Ce(c,u);if(je(h))try{if(or(h).length>0)return{exists:!0,path:c,hasDistFolder:!0,distPath:h}}catch{}}return{exists:!0,path:c,hasDistFolder:!1,distPath:null}}}return{exists:!1,path:null,hasDistFolder:!1,distPath:null}}static createDocsBucketIfExists(a){let n=be.docsExist({projectRoot:a.projectRoot,docsPaths:a.docsPaths});if(!n.exists)return{bucket:null,logicalId:null,docsInfo:n};let i=be.createDocsBucket({slug:a.slug,environment:a.environment,domain:a.domain});return{bucket:i.bucket,bucketPolicy:i.bucketPolicy,logicalId:i.logicalId,docsInfo:n}}static createPrivateBucket(a){let{slug:n,environment:i,enableVersioning:s=!0,retentionDays:c,encryptionKeyArn:l}=a,u=r({slug:n,environment:i,resourceType:"s3",suffix:"private"}),h=t(u);return{bucket:{Type:"AWS::S3::Bucket",Properties:{BucketName:u,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:l?{SSEAlgorithm:"aws:kms",KMSMasterKeyID:l}:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},VersioningConfiguration:s?{Status:"Enabled"}:void 0,LifecycleConfiguration:c?{Rules:[{Id:"RetentionPolicy",Status:"Enabled",ExpirationInDays:c}]}:void 0,Tags:[{Key:"backup",Value:"daily"}]}},logicalId:h}}static checkSourcePaths(a={}){let{projectRoot:n=process.cwd(),paths:i={}}=a,s=i.web||"views/web/dist",c=i.docs||"docs/dist",l=i.private||"private";return{web:{exists:je(Ce(n,s)),path:Ce(n,s)},docs:{exists:je(Ce(n,c)),path:Ce(n,c)},private:{exists:je(Ce(n,l)),path:Ce(n,l)}}}static createDeploymentBuckets(a){let{slug:n,environment:i,domain:s,projectRoot:c,paths:l}=a,u=be.checkSourcePaths({projectRoot:c,paths:l}),h={},y={web:!1,docs:!1,private:!1},S=be.createBucket({name:"web",slug:n,environment:i,public:!1,versioning:!1,encryption:!0});if(h[S.logicalId]=S.bucket,y.web=!0,u.docs.exists){let A=be.createDocsBucket({slug:n,environment:i,domain:s?`docs.${s}`:void 0});if(h[A.logicalId]=A.bucket,A.bucketPolicy)h[`${A.logicalId}Policy`]=A.bucketPolicy;y.docs=!0}if(u.private.exists){let A=be.createPrivateBucket({slug:n,environment:i,enableVersioning:!0});h[A.logicalId]=A.bucket,y.private=!0}return{resources:h,created:y,sourcePaths:u}}}class He{static createRepository(a){let{name:n,slug:i,environment:s,scanOnPush:c=!0,imageMutability:l="MUTABLE",encryption:u="AES256",kmsKey:h,lifecyclePolicy:y,tags:S}=a,A=r({slug:i,environment:s,resourceType:"ecr",suffix:n}),C=t(A),T={Type:"AWS::ECR::Repository",Properties:{RepositoryName:A,ImageTagMutability:l,ImageScanningConfiguration:{ScanOnPush:c},EncryptionConfiguration:{EncryptionType:u,...h&&u==="KMS"?{KmsKey:h}:{}}}};if(y)T.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(He.generateLifecyclePolicy(y))};if(S)T.Properties.Tags=Object.entries(S).map(([v,w])=>({Key:v,Value:w}));return{repository:T,logicalId:C}}static generateLifecyclePolicy(a){let n=[];if(a.untaggedImageExpireDays!==void 0)n.push({rulePriority:1,description:"Delete untagged images",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:a.untaggedImageExpireDays,countUnit:"days"},action:{type:"expire"}});if(a.maxImageCount!==void 0)n.push({rulePriority:n.length+1,description:"Keep only most recent images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:a.maxImageCount},action:{type:"expire"}});if(a.maxImageAgeDays!==void 0)n.push({rulePriority:n.length+1,description:"Delete images older than specified days",selection:{tagStatus:"any",countType:"sinceImagePushed",countNumber:a.maxImageAgeDays,countUnit:"days"},action:{type:"expire"}});return{rules:n}}static LifecyclePolicies={production:{maxImageCount:10,untaggedImageExpireDays:7},development:{maxImageCount:5,untaggedImageExpireDays:3},minimal:{maxImageCount:3,untaggedImageExpireDays:1},archive:{maxImageCount:50,untaggedImageExpireDays:30}};static enableImmutableTags(a){if(!a.Properties)a.Properties={};return a.Properties.ImageTagMutability="IMMUTABLE",a}static enableScanOnPush(a){if(!a.Properties)a.Properties={};return a.Properties.ImageScanningConfiguration={ScanOnPush:!0},a}static setLifecyclePolicy(a,n){if(!a.Properties)a.Properties={};return a.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(He.generateLifecyclePolicy(n))},a}static addCrossAccountAccess(a,n){if(!a.Properties)a.Properties={};return a.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"CrossAccountPull",Effect:"Allow",Principal:{AWS:n.map((i)=>`arn:aws:iam::${i}:root`)},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:BatchCheckLayerAvailability"]}]},a}static addLambdaAccess(a){if(!a.Properties)a.Properties={};return a.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"LambdaECRImageRetrievalPolicy",Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage"]}]},a}static generateBunDockerfile(a){let{baseImage:n="oven/bun:1-debian",serverPath:i,port:s=3000,additionalDirs:c=[],healthCheckEndpoint:l="/health",nodeCompatible:u=!1,envVars:h={},buildCommands:y=[],runCommand:S}=a,A=["app","config",...c],C=S||`bun run ${i}`,T=`# Multi-stage build for Bun application
24
24
  # Generated by ts-cloud
25
25
 
26
26
  # Builder stage
@@ -47,18 +47,18 @@ COPY --from=builder /app/node_modules ./node_modules
47
47
 
48
48
  # Copy application code
49
49
  COPY package.json ./
50
- `;for(let T of b)C+=`COPY ${T} ./${T}
51
- `;if(C+=`COPY ${i} ./${i}
52
- `,y.length>0){C+=`
50
+ `;for(let v of A)T+=`COPY ${v} ./${v}
51
+ `;if(T+=`COPY ${i} ./${i}
52
+ `,y.length>0){T+=`
53
53
  # Build commands
54
- `;for(let T of y)C+=`RUN ${T}
55
- `}C+=`
54
+ `;for(let v of y)T+=`RUN ${v}
55
+ `}T+=`
56
56
  # Environment variables
57
- `,C+=`ENV NODE_ENV=production
58
- `,C+=`ENV PORT=${s}
59
- `;for(let[T,v]of Object.entries(h))C+=`ENV ${T}=${v}
60
- `;if(u)C+=`ENV BUN_INSTALL_FORCE_NODE_API=1
61
- `;return C+=`
57
+ `,T+=`ENV NODE_ENV=production
58
+ `,T+=`ENV PORT=${s}
59
+ `;for(let[v,w]of Object.entries(h))T+=`ENV ${v}=${w}
60
+ `;if(u)T+=`ENV BUN_INSTALL_FORCE_NODE_API=1
61
+ `;return T+=`
62
62
  # Create storage directory
63
63
  RUN mkdir -p /app/storage && chown -R app:app /app/storage
64
64
 
@@ -74,7 +74,7 @@ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \\
74
74
 
75
75
  # Start application
76
76
  CMD ["bun", "run", "${i}"]
77
- `,C}static generateDockerBuildCommands(a){let{repositoryUri:n,tag:i="latest",dockerfilePath:s="Dockerfile",context:c=".",additionalTags:l=[],buildArgs:u={},platform:h="linux/amd64",noCache:y=!1}=a,S=`${n}:${i}`,b=[i,...l],A=`docker build -f ${s} -t ${S}`;if(h)A+=` --platform ${h}`;if(y)A+=" --no-cache";for(let[v,w]of Object.entries(u))A+=` --build-arg ${v}=${w}`;A+=` ${c}`;let C=b.slice(1).map((v)=>`docker tag ${S} ${n}:${v}`),T=b.map((v)=>`docker push ${n}:${v}`);return{build:A,tag:C,push:T,all:[A,...C,...T]}}static generateEcrLoginCommand(a,n){return`aws ecr get-login-password --region ${a} | docker login --username AWS --password-stdin ${n}.dkr.ecr.${a}.amazonaws.com`}static buildRepositoryUri(a){return`${a.accountId}.dkr.ecr.${a.region}.amazonaws.com/${a.repositoryName}`}static generateImageTags(a){let n=["latest"];if(a.version){n.push(a.version);let i=a.version.split(".");if(i.length>=2)n.push(`${i[0]}.${i[1]}`);if(i.length>=1)n.push(i[0])}if(a.gitSha)n.push(a.gitSha.substring(0,7)),n.push(a.gitSha);if(a.gitBranch){let i=a.gitBranch.replace(/[^a-zA-Z0-9.-]/g,"-").replace(/^-+|-+$/g,"");n.push(i)}if(a.environment)n.push(a.environment);if(a.timestamp){let i=new Date().toISOString().replace(/[:.]/g,"-").substring(0,19);n.push(i)}return[...new Set(n)]}static DeploymentWorkflow={generateDeployScript:(a)=>{let n=He.buildRepositoryUri({accountId:a.accountId,region:a.region,repositoryName:a.repositoryName}),i=a.tags||["latest"],s=i[0];return`#!/bin/bash
77
+ `,T}static generateDockerBuildCommands(a){let{repositoryUri:n,tag:i="latest",dockerfilePath:s="Dockerfile",context:c=".",additionalTags:l=[],buildArgs:u={},platform:h="linux/amd64",noCache:y=!1}=a,S=`${n}:${i}`,A=[i,...l],C=`docker build -f ${s} -t ${S}`;if(h)C+=` --platform ${h}`;if(y)C+=" --no-cache";for(let[w,E]of Object.entries(u))C+=` --build-arg ${w}=${E}`;C+=` ${c}`;let T=A.slice(1).map((w)=>`docker tag ${S} ${n}:${w}`),v=A.map((w)=>`docker push ${n}:${w}`);return{build:C,tag:T,push:v,all:[C,...T,...v]}}static generateEcrLoginCommand(a,n){return`aws ecr get-login-password --region ${a} | docker login --username AWS --password-stdin ${n}.dkr.ecr.${a}.amazonaws.com`}static buildRepositoryUri(a){return`${a.accountId}.dkr.ecr.${a.region}.amazonaws.com/${a.repositoryName}`}static generateImageTags(a){let n=["latest"];if(a.version){n.push(a.version);let i=a.version.split(".");if(i.length>=2)n.push(`${i[0]}.${i[1]}`);if(i.length>=1)n.push(i[0])}if(a.gitSha)n.push(a.gitSha.substring(0,7)),n.push(a.gitSha);if(a.gitBranch){let i=a.gitBranch.replace(/[^a-zA-Z0-9.-]/g,"-").replace(/^-+|-+$/g,"");n.push(i)}if(a.environment)n.push(a.environment);if(a.timestamp){let i=new Date().toISOString().replace(/[:.]/g,"-").substring(0,19);n.push(i)}return[...new Set(n)]}static DeploymentWorkflow={generateDeployScript:(a)=>{let n=He.buildRepositoryUri({accountId:a.accountId,region:a.region,repositoryName:a.repositoryName}),i=a.tags||["latest"],s=i[0];return`#!/bin/bash
78
78
  set -e
79
79
 
80
80
  # Configuration
@@ -103,7 +103,7 @@ echo "Image: $IMAGE_URI:${s}"
103
103
  docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
104
104
  docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest`},...a.ecsCluster&&a.ecsService?[{name:"Deploy to ECS",run:`aws ecs update-service --cluster ${a.ecsCluster} --service ${a.ecsService} --force-new-deployment`}]:[]]}}};return`# Generated by ts-cloud
105
105
  ${JSON.stringify(n,null,2).replace(/"/g,"").replace(/,\n/g,`
106
- `)}`}};static DockerfileTemplates={bunServer:(a,n=3000)=>He.generateBunDockerfile({serverPath:a,port:n}),bunWithBuild:(a,n,i=3000)=>He.generateBunDockerfile({serverPath:a,port:i,buildCommands:[n]}),bunFullStack:(a,n=3000)=>He.generateBunDockerfile({serverPath:a,port:n,additionalDirs:["public","views","dist"],buildCommands:["bun run build"]}),bunApi:(a,n=3000)=>He.generateBunDockerfile({serverPath:a,port:n,healthCheckEndpoint:"/api/health"})}}class ve{static createDistribution(a){let{slug:n,environment:i,origin:s,customDomain:c,certificateArn:l,errorPages:u,cachePolicy:h,edgeFunctions:y,http3:S=!1,comment:b}=a,A=r({slug:n,environment:i,resourceType:"cdn"}),C=t(A),T={Id:"DefaultOrigin",DomainName:s.domainName,OriginPath:s.originPath||""},v;if(s.type==="s3"){let R=`${C}OAC`;v={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${A}-oac`,Description:`Origin Access Control for ${A}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},T.OriginAccessControlId=N.Ref(R)}else if(s.type==="alb"||s.type==="custom")T.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only"};let w={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:b||`CDN for ${A}`,DefaultRootObject:"index.html",Origins:[T],DefaultCacheBehavior:{TargetOriginId:"DefaultOrigin",ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0},PriceClass:"PriceClass_100",HttpVersion:S?"http2and3":"http2"}}};if(c&&l)w.Properties.DistributionConfig.Aliases=[c],w.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:l,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};if(u&&u.length>0)w.Properties.DistributionConfig.CustomErrorResponses=u.map((R)=>({ErrorCode:R.errorCode,ResponseCode:R.responseCode,ResponsePagePath:R.responsePagePath}));if(y&&y.length>0)w.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=y.map((R)=>({EventType:R.event,LambdaFunctionARN:R.functionArn}));return{distribution:w,originAccessControl:v,logicalId:C}}static setCustomDomain(a,n,i){return a.Properties.DistributionConfig.Aliases=[n],a.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:i,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"},a}static setErrorPages(a,n){return a.Properties.DistributionConfig.CustomErrorResponses=n.map((i)=>({ErrorCode:i.errorCode,ResponseCode:i.responseCode,ResponsePagePath:i.responsePagePath})),a}static enableHttp3(a){return a.Properties.DistributionConfig.HttpVersion="http2and3",a}static addEdgeFunction(a,n,i){if(!a.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations)a.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=[];return a.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations.push({EventType:n,LambdaFunctionARN:i}),a}static setCachePolicy(a,n){return a.Properties.DistributionConfig.Comment=`${a.Properties.DistributionConfig.Comment||""} (TTL: ${n.default||86400}s)`,a}static createSpaDistribution(a){return ve.createDistribution({...a,errorPages:[{errorCode:404,responseCode:200,responsePagePath:"/index.html"},{errorCode:403,responseCode:200,responsePagePath:"/index.html"}]})}static createDocsOriginRequestFunction(a){let{slug:n,environment:i}=a,s=r({slug:n,environment:i,resourceType:"edge-docs"}),c=t(s),l=t(`${s}-role`),u=t(`${s}-version`),h={Type:"AWS::IAM::Role",Properties:{RoleName:`${s}-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["lambda.amazonaws.com","edgelambda.amazonaws.com"]},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]}},y=`
106
+ `)}`}};static DockerfileTemplates={bunServer:(a,n=3000)=>He.generateBunDockerfile({serverPath:a,port:n}),bunWithBuild:(a,n,i=3000)=>He.generateBunDockerfile({serverPath:a,port:i,buildCommands:[n]}),bunFullStack:(a,n=3000)=>He.generateBunDockerfile({serverPath:a,port:n,additionalDirs:["public","views","dist"],buildCommands:["bun run build"]}),bunApi:(a,n=3000)=>He.generateBunDockerfile({serverPath:a,port:n,healthCheckEndpoint:"/api/health"})}}class ve{static createDistribution(a){let{slug:n,environment:i,origin:s,customDomain:c,certificateArn:l,errorPages:u,cachePolicy:h,edgeFunctions:y,http3:S=!1,comment:A}=a,C=r({slug:n,environment:i,resourceType:"cdn"}),T=t(C),v={Id:"DefaultOrigin",DomainName:s.domainName,OriginPath:s.originPath||""},w;if(s.type==="s3"){let R=`${T}OAC`;w={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${C}-oac`,Description:`Origin Access Control for ${C}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},v.OriginAccessControlId=N.Ref(R)}else if(s.type==="alb"||s.type==="custom")v.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only"};let E={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:A||`CDN for ${C}`,DefaultRootObject:"index.html",Origins:[v],DefaultCacheBehavior:{TargetOriginId:"DefaultOrigin",ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0},PriceClass:"PriceClass_100",HttpVersion:S?"http2and3":"http2"}}};if(c&&l)E.Properties.DistributionConfig.Aliases=[c],E.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:l,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};if(u&&u.length>0)E.Properties.DistributionConfig.CustomErrorResponses=u.map((R)=>({ErrorCode:R.errorCode,ResponseCode:R.responseCode,ResponsePagePath:R.responsePagePath}));if(y&&y.length>0)E.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=y.map((R)=>({EventType:R.event,LambdaFunctionARN:R.functionArn}));return{distribution:E,originAccessControl:w,logicalId:T}}static setCustomDomain(a,n,i){return a.Properties.DistributionConfig.Aliases=[n],a.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:i,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"},a}static setErrorPages(a,n){return a.Properties.DistributionConfig.CustomErrorResponses=n.map((i)=>({ErrorCode:i.errorCode,ResponseCode:i.responseCode,ResponsePagePath:i.responsePagePath})),a}static enableHttp3(a){return a.Properties.DistributionConfig.HttpVersion="http2and3",a}static addEdgeFunction(a,n,i){if(!a.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations)a.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=[];return a.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations.push({EventType:n,LambdaFunctionARN:i}),a}static setCachePolicy(a,n){return a.Properties.DistributionConfig.Comment=`${a.Properties.DistributionConfig.Comment||""} (TTL: ${n.default||86400}s)`,a}static createSpaDistribution(a){return ve.createDistribution({...a,errorPages:[{errorCode:404,responseCode:200,responsePagePath:"/index.html"},{errorCode:403,responseCode:200,responsePagePath:"/index.html"}]})}static createDocsOriginRequestFunction(a){let{slug:n,environment:i}=a,s=r({slug:n,environment:i,resourceType:"edge-docs"}),c=t(s),l=t(`${s}-role`),u=t(`${s}-version`),h={Type:"AWS::IAM::Role",Properties:{RoleName:`${s}-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["lambda.amazonaws.com","edgelambda.amazonaws.com"]},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]}},y=`
107
107
  'use strict';
108
108
 
109
109
  exports.handler = async (event) => {
@@ -136,7 +136,7 @@ exports.handler = async (event) => {
136
136
 
137
137
  return request;
138
138
  };
139
- `.trim();return{lambdaFunction:{Type:"AWS::Lambda::Function",Properties:{FunctionName:s,Description:"Lambda@Edge origin request handler for docs routing",Runtime:"nodejs20.x",Handler:"index.handler",Role:N.GetAtt(l,"Arn"),Code:{ZipFile:y},MemorySize:128,Timeout:5}},role:h,functionLogicalId:c,roleLogicalId:l,versionLogicalId:u}}static createDocsDistribution(a){let{slug:n,environment:i,origin:s,customDomain:c,certificateArn:l,lambdaEdgeFunctionArn:u}=a,h=ve.createDistribution({slug:n,environment:i,origin:s,customDomain:c,certificateArn:l,comment:`Docs CDN for ${n}`,errorPages:[{errorCode:404,responseCode:404,responsePagePath:"/404.html"},{errorCode:403,responseCode:403,responsePagePath:"/404.html"}]});if(u)ve.addEdgeFunction(h.distribution,"origin-request",u);return h.distribution.Properties.DistributionConfig.DefaultCacheBehavior.DefaultTTL=86400,h.distribution.Properties.DistributionConfig.DefaultCacheBehavior.MaxTTL=604800,h.distribution.Properties.DistributionConfig.DefaultCacheBehavior.MinTTL=0,h}static createApiDistribution(a){let{slug:n,environment:i,albDomainName:s,customDomain:c,certificateArn:l,pathPattern:u="/api/*",forwardHeaders:h=["Host","Origin","Authorization","Content-Type","Accept"],forwardCookies:y="all",whitelistedCookies:S,customOriginHeaders:b={}}=a,A=r({slug:n,environment:i,resourceType:"cdn-api"}),C=t(A),T=Object.entries(b).map(([k,W])=>({HeaderName:k,HeaderValue:W})),v={Id:"ALBOrigin",DomainName:s,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(T.length>0)v.OriginCustomHeaders=T;let w={Forward:y};if(y==="whitelist"&&S)w.WhitelistedNames=S;let R={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:`API CDN for ${A}`,Origins:[v],DefaultCacheBehavior:{TargetOriginId:"ALBOrigin",ViewerProtocolPolicy:"https-only",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,DefaultTTL:0,MaxTTL:0,MinTTL:0,ForwardedValues:{QueryString:!0,Headers:h,Cookies:w}},PriceClass:"PriceClass_100",HttpVersion:"http2"}}};if(c&&l)R.Properties.DistributionConfig.Aliases=[c],R.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:l,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};return{distribution:R,logicalId:C}}static createMultiOriginDistribution(a){let{slug:n,environment:i,s3BucketDomainName:s,albDomainName:c,apiPathPattern:l="/api/*",customDomain:u,certificateArn:h,customOriginHeaders:y={}}=a,S=r({slug:n,environment:i,resourceType:"cdn"}),b=t(S),A=`${b}OAC`,C={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${S}-oac`,Description:`Origin Access Control for ${S}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},T=Object.entries(y).map(([k,W])=>({HeaderName:k,HeaderValue:W})),v={Id:"S3Origin",DomainName:s,OriginAccessControlId:N.Ref(A)},w={Id:"ALBOrigin",DomainName:c,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(T.length>0)w.OriginCustomHeaders=T;let R={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:`Multi-origin CDN for ${S}`,DefaultRootObject:"index.html",Origins:[v,w],DefaultCacheBehavior:{TargetOriginId:"S3Origin",ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0},CacheBehaviors:[{PathPattern:l,TargetOriginId:"ALBOrigin",ViewerProtocolPolicy:"https-only",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,DefaultTTL:0,MaxTTL:0,MinTTL:0,ForwardedValues:{QueryString:!0,Headers:["Host","Origin","Authorization","Content-Type","Accept"],Cookies:{Forward:"all"}}}],PriceClass:"PriceClass_100",HttpVersion:"http2",CustomErrorResponses:[{ErrorCode:404,ResponseCode:200,ResponsePagePath:"/index.html"},{ErrorCode:403,ResponseCode:200,ResponsePagePath:"/index.html"}]}}};if(u&&h)R.Properties.DistributionConfig.Aliases=[u],R.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:h,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};return{distribution:R,originAccessControl:C,logicalId:b,oacLogicalId:A}}static addAlbOrigin(a,n){let{originId:i,domainName:s,pathPattern:c,customHeaders:l={},forwardHeaders:u=["Host","Origin","Authorization","Content-Type","Accept"],cacheTtl:h={default:0,max:0,min:0}}=n,y=Object.entries(l).map(([b,A])=>({HeaderName:b,HeaderValue:A})),S={Id:i,DomainName:s,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(y.length>0)S.OriginCustomHeaders=y;if(!a.Properties.DistributionConfig.Origins)a.Properties.DistributionConfig.Origins=[];if(a.Properties.DistributionConfig.Origins.push(S),!a.Properties.DistributionConfig.CacheBehaviors)a.Properties.DistributionConfig.CacheBehaviors=[];return a.Properties.DistributionConfig.CacheBehaviors.push({PathPattern:c,TargetOriginId:i,ViewerProtocolPolicy:"https-only",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,DefaultTTL:h.default,MaxTTL:h.max,MinTTL:h.min,ForwardedValues:{QueryString:!0,Headers:u,Cookies:{Forward:"all"}}}),a}static addOriginHeader(a,n,i,s){let c=a.Properties.DistributionConfig.Origins?.find((l)=>l.Id===n);if(c){if(!c.OriginCustomHeaders)c.OriginCustomHeaders=[];c.OriginCustomHeaders.push({HeaderName:i,HeaderValue:s})}return a}static EdgeFunctionTemplates={docsOriginRequest:`
139
+ `.trim();return{lambdaFunction:{Type:"AWS::Lambda::Function",Properties:{FunctionName:s,Description:"Lambda@Edge origin request handler for docs routing",Runtime:"nodejs20.x",Handler:"index.handler",Role:N.GetAtt(l,"Arn"),Code:{ZipFile:y},MemorySize:128,Timeout:5}},role:h,functionLogicalId:c,roleLogicalId:l,versionLogicalId:u}}static createDocsDistribution(a){let{slug:n,environment:i,origin:s,customDomain:c,certificateArn:l,lambdaEdgeFunctionArn:u}=a,h=ve.createDistribution({slug:n,environment:i,origin:s,customDomain:c,certificateArn:l,comment:`Docs CDN for ${n}`,errorPages:[{errorCode:404,responseCode:404,responsePagePath:"/404.html"},{errorCode:403,responseCode:403,responsePagePath:"/404.html"}]});if(u)ve.addEdgeFunction(h.distribution,"origin-request",u);return h.distribution.Properties.DistributionConfig.DefaultCacheBehavior.DefaultTTL=86400,h.distribution.Properties.DistributionConfig.DefaultCacheBehavior.MaxTTL=604800,h.distribution.Properties.DistributionConfig.DefaultCacheBehavior.MinTTL=0,h}static createApiDistribution(a){let{slug:n,environment:i,albDomainName:s,customDomain:c,certificateArn:l,pathPattern:u="/api/*",forwardHeaders:h=["Host","Origin","Authorization","Content-Type","Accept"],forwardCookies:y="all",whitelistedCookies:S,customOriginHeaders:A={}}=a,C=r({slug:n,environment:i,resourceType:"cdn-api"}),T=t(C),v=Object.entries(A).map(([k,W])=>({HeaderName:k,HeaderValue:W})),w={Id:"ALBOrigin",DomainName:s,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(v.length>0)w.OriginCustomHeaders=v;let E={Forward:y};if(y==="whitelist"&&S)E.WhitelistedNames=S;let R={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:`API CDN for ${C}`,Origins:[w],DefaultCacheBehavior:{TargetOriginId:"ALBOrigin",ViewerProtocolPolicy:"https-only",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,DefaultTTL:0,MaxTTL:0,MinTTL:0,ForwardedValues:{QueryString:!0,Headers:h,Cookies:E}},PriceClass:"PriceClass_100",HttpVersion:"http2"}}};if(c&&l)R.Properties.DistributionConfig.Aliases=[c],R.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:l,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};return{distribution:R,logicalId:T}}static createMultiOriginDistribution(a){let{slug:n,environment:i,s3BucketDomainName:s,albDomainName:c,apiPathPattern:l="/api/*",customDomain:u,certificateArn:h,customOriginHeaders:y={}}=a,S=r({slug:n,environment:i,resourceType:"cdn"}),A=t(S),C=`${A}OAC`,T={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${S}-oac`,Description:`Origin Access Control for ${S}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},v=Object.entries(y).map(([k,W])=>({HeaderName:k,HeaderValue:W})),w={Id:"S3Origin",DomainName:s,OriginAccessControlId:N.Ref(C)},E={Id:"ALBOrigin",DomainName:c,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(v.length>0)E.OriginCustomHeaders=v;let R={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:`Multi-origin CDN for ${S}`,DefaultRootObject:"index.html",Origins:[w,E],DefaultCacheBehavior:{TargetOriginId:"S3Origin",ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0},CacheBehaviors:[{PathPattern:l,TargetOriginId:"ALBOrigin",ViewerProtocolPolicy:"https-only",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,DefaultTTL:0,MaxTTL:0,MinTTL:0,ForwardedValues:{QueryString:!0,Headers:["Host","Origin","Authorization","Content-Type","Accept"],Cookies:{Forward:"all"}}}],PriceClass:"PriceClass_100",HttpVersion:"http2",CustomErrorResponses:[{ErrorCode:404,ResponseCode:200,ResponsePagePath:"/index.html"},{ErrorCode:403,ResponseCode:200,ResponsePagePath:"/index.html"}]}}};if(u&&h)R.Properties.DistributionConfig.Aliases=[u],R.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:h,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};return{distribution:R,originAccessControl:T,logicalId:A,oacLogicalId:C}}static addAlbOrigin(a,n){let{originId:i,domainName:s,pathPattern:c,customHeaders:l={},forwardHeaders:u=["Host","Origin","Authorization","Content-Type","Accept"],cacheTtl:h={default:0,max:0,min:0}}=n,y=Object.entries(l).map(([A,C])=>({HeaderName:A,HeaderValue:C})),S={Id:i,DomainName:s,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(y.length>0)S.OriginCustomHeaders=y;if(!a.Properties.DistributionConfig.Origins)a.Properties.DistributionConfig.Origins=[];if(a.Properties.DistributionConfig.Origins.push(S),!a.Properties.DistributionConfig.CacheBehaviors)a.Properties.DistributionConfig.CacheBehaviors=[];return a.Properties.DistributionConfig.CacheBehaviors.push({PathPattern:c,TargetOriginId:i,ViewerProtocolPolicy:"https-only",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,DefaultTTL:h.default,MaxTTL:h.max,MinTTL:h.min,ForwardedValues:{QueryString:!0,Headers:u,Cookies:{Forward:"all"}}}),a}static addOriginHeader(a,n,i,s){let c=a.Properties.DistributionConfig.Origins?.find((l)=>l.Id===n);if(c){if(!c.OriginCustomHeaders)c.OriginCustomHeaders=[];c.OriginCustomHeaders.push({HeaderName:i,HeaderValue:s})}return a}static EdgeFunctionTemplates={docsOriginRequest:`
140
140
  'use strict';
141
141
  exports.handler = async (event) => {
142
142
  const request = event.Records[0].cf.request;
@@ -209,7 +209,7 @@ exports.handler = async (event) => {
209
209
 
210
210
  return request;
211
211
  };
212
- `.trim()};static Config={ttl:(a)=>{let{min:n=0,max:i=86400,default:s=86400}=a;return{MinTTL:n,MaxTTL:i,DefaultTTL:s}},cookies:(a,n)=>{let i={Forward:a==="allowList"?"whitelist":a};if(a==="allowList"&&n)i.WhitelistedNames=n;return i},allowedMethods:(a)=>{let n={ALL:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return n[a]||n.GET_HEAD},cachedMethods:(a)=>{let n={GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return n[a]||n.GET_HEAD},ttlPresets:{static:{min:0,max:31536000,default:31536000},dynamic:{min:0,max:0,default:0},api:{min:0,max:3600,default:60},html:{min:0,max:86400,default:86400},images:{min:0,max:604800,default:604800}},cacheBehavior:(a)=>{let{ttl:n={min:0,max:86400,default:86400},cookies:i="none",allowedCookies:s,allowedMethods:c="GET_HEAD",cachedMethods:l="GET_HEAD",compress:u=!0,forwardQueryString:h=!0,forwardHeaders:y=[]}=a;return{MinTTL:n.min,MaxTTL:n.max,DefaultTTL:n.default,Compress:u,AllowedMethods:ve.Config.allowedMethods(c),CachedMethods:ve.Config.cachedMethods(l),ForwardedValues:{QueryString:h,Headers:y,Cookies:ve.Config.cookies(i,s)}}}};static applyConfig(a,n){let i=a.Properties.DistributionConfig.DefaultCacheBehavior;if(n.ttl)i.MinTTL=n.ttl.min,i.MaxTTL=n.ttl.max,i.DefaultTTL=n.ttl.default;if(n.compress!==void 0)i.Compress=n.compress;if(n.allowedMethods)i.AllowedMethods=ve.Config.allowedMethods(n.allowedMethods);if(n.cachedMethods)i.CachedMethods=ve.Config.cachedMethods(n.cachedMethods);if(n.cookies){if(!i.ForwardedValues)i.ForwardedValues={QueryString:!0};i.ForwardedValues.Cookies=ve.Config.cookies(n.cookies,n.allowedCookies)}return a}}class L{static createHostedZone(a){let{domain:n,slug:i,environment:s,comment:c}=a,l=r({slug:i,environment:s,resourceType:"hostedzone"}),u=t(`${l}-${n.replace(/\./g,"")}`);return{zone:{Type:"AWS::Route53::HostedZone",Properties:{Name:n,HostedZoneConfig:{Comment:c||`Hosted zone for ${n}`}}},logicalId:u}}static createRecord(a){let{hostedZoneId:n,hostedZoneName:i,name:s,type:c,ttl:l,values:u,aliasTarget:h}=a,y=t(`record-${s.replace(/\./g,"")}-${c}`),S={Type:"AWS::Route53::RecordSet",Properties:{Name:s,Type:c}};if(n)S.Properties.HostedZoneId=n;else if(i)S.Properties.HostedZoneName=i;if(h)S.Properties.AliasTarget={DNSName:h.dnsName,HostedZoneId:h.hostedZoneId,EvaluateTargetHealth:h.evaluateTargetHealth??!1};else S.Properties.TTL=l||300,S.Properties.ResourceRecords=u||[];return{record:S,logicalId:y}}static createCloudFrontAlias(a,n,i){return L.createRecord({hostedZoneId:i,name:a,type:"A",aliasTarget:{dnsName:n,hostedZoneId:"Z2FDTNDATAQYW2",evaluateTargetHealth:!1}})}static createAlbAlias(a,n,i,s){return L.createRecord({hostedZoneId:s,name:a,type:"A",aliasTarget:{dnsName:n,hostedZoneId:i,evaluateTargetHealth:!0}})}static createCname(a,n,i,s=300){return L.createRecord({hostedZoneId:i,name:a,type:"CNAME",ttl:s,values:[n]})}static createWwwRedirect(a,n){return L.createRecord({hostedZoneId:n,name:`www.${a}`,type:"CNAME",ttl:300,values:[a]})}static createMxRecords(a,n,i,s=300){return L.createRecord({hostedZoneId:i,name:a,type:"MX",ttl:s,values:n.map((c)=>`${c.priority} ${c.server}`)})}static createTxtRecord(a,n,i,s=300){return L.createRecord({hostedZoneId:i,name:a,type:"TXT",ttl:s,values:[`"${n}"`]})}static createSpfRecord(a,n,i){return L.createTxtRecord(a,n,i)}static createDmarcRecord(a,n,i,s){let c=`v=DMARC1; p=${n}; rua=mailto:${i}`;return L.createTxtRecord(`_dmarc.${a}`,c,s)}static createS3WebsiteAlias(a,n,i,s){return L.createRecord({hostedZoneId:s,name:a,type:"A",aliasTarget:{dnsName:n,hostedZoneId:i,evaluateTargetHealth:!1}})}static S3WebsiteHostedZoneIds={"us-east-1":"Z3AQBSTGFYJSTF","us-east-2":"Z2O1EMRO9K5GLX","us-west-1":"Z2F56UZL2M1ACD","us-west-2":"Z3BJ6K6RIION7M","af-south-1":"Z83WF9RJE8B12","ap-east-1":"ZNB98KWMFR0R6","ap-south-1":"Z11RGJOFQNVJUP","ap-south-2":"Z02976202B4EZMXIPMXF7","ap-northeast-1":"Z2M4EHUR26P7ZW","ap-northeast-2":"Z3W03O7B5YMIYP","ap-northeast-3":"Z2YQB5RD63NC85","ap-southeast-1":"Z3O0J2DXBE1FTB","ap-southeast-2":"Z1WCIBER6CPFUU","ap-southeast-3":"Z01613992JD795ZI93075","ca-central-1":"Z1QDHH18159H29","eu-central-1":"Z21DNDUVLTQW6Q","eu-central-2":"Z030506016YDQGETNASS","eu-west-1":"Z1BKCTXD74EZPE","eu-west-2":"Z3GKZC51ZF0DB4","eu-west-3":"Z3R1K369G5AVDG","eu-north-1":"Z3BAZG2TWCNX0D","eu-south-1":"Z30OZKI7KPW7MI","eu-south-2":"Z0081959F7139GRJC19J","me-south-1":"Z1MPMWCPA7YB62","me-central-1":"Z06143092I8HRBER9VXCO","sa-east-1":"Z7KQH4QJS55SO"};static getS3WebsiteEndpoint(a,n){return`${a}.s3-website-${n}.amazonaws.com`}static createStoreRecord(a,n,i){return L.createCname(`store.${a}`,n,i)}static createApiRecord(a,n,i){return L.createCname(`api.${a}`,n,i)}static createDocsRecord(a,n,i){return L.createCname(`docs.${a}`,n,i)}static CloudFrontHostedZoneId="Z2FDTNDATAQYW2"}class I{static createCertificate(a){let{domain:n,subdomains:i=[],slug:s,environment:c,validationMethod:l="DNS",hostedZoneId:u}=a,h=r({slug:s,environment:c,resourceType:"acm"}),y=t(`${h}-${n.replace(/\./g,"")}`),S=[n];for(let A of i)if(A==="*")S.push(`*.${n}`);else S.push(`${A}.${n}`);let b={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:n,SubjectAlternativeNames:S,ValidationMethod:l}};if(l==="DNS"&&u)b.Properties.DomainValidationOptions=S.map((A)=>({DomainName:A,HostedZoneId:u}));return{certificate:b,logicalId:y}}static createKmsKey(a){let{description:n,slug:i,environment:s,enableRotation:c=!0,multiRegion:l=!1}=a,u=r({slug:i,environment:s,resourceType:"kms"}),h=t(u),y={Version:"2012-10-17",Statement:[{Sid:"Enable IAM User Permissions",Effect:"Allow",Principal:{AWS:N.Sub("arn:aws:iam::${AWS::AccountId}:root")},Action:"kms:*",Resource:"*"},{Sid:"Allow services to use the key",Effect:"Allow",Principal:{Service:["s3.amazonaws.com","cloudfront.amazonaws.com","logs.amazonaws.com","secretsmanager.amazonaws.com"]},Action:["kms:Decrypt","kms:GenerateDataKey"],Resource:"*"}]},S={Type:"AWS::KMS::Key",Properties:{Description:n,Enabled:!0,EnableKeyRotation:c,KeyPolicy:y,KeySpec:"SYMMETRIC_DEFAULT",KeyUsage:"ENCRYPT_DECRYPT",MultiRegion:l}},b=t(`${u}-alias`),A={Type:"AWS::KMS::Alias",Properties:{AliasName:`alias/${i}-${s}`,TargetKeyId:N.Ref(h)}};return{key:S,alias:A,logicalId:h,aliasId:b}}static createFirewall(a){let{slug:n,environment:i,scope:s="CLOUDFRONT",defaultAction:c="allow"}=a,l=r({slug:n,environment:i,resourceType:"waf"}),u=t(l);return{webAcl:{Type:"AWS::WAFv2::WebACL",Properties:{Name:l,Scope:s,DefaultAction:c==="allow"?{Allow:{}}:{Block:{}},Description:`WAF for ${n} ${i}`,Rules:[],VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${l}-metric`}}},logicalId:u}}static setRateLimit(a,n){if(!a.Properties.Rules)a.Properties.Rules=[];return a.Properties.Rules.push({Name:n.name,Priority:n.priority,Statement:{RateBasedStatement:{Limit:n.requestsPerWindow,AggregateKeyType:n.aggregateKeyType||"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n.name}-metric`}}),a}static blockCountries(a,n){if(!a.Properties.Rules)a.Properties.Rules=[];return a.Properties.Rules.push({Name:n.name,Priority:n.priority,Statement:{GeoMatchStatement:{CountryCodes:n.countryCodes}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n.name}-metric`}}),a}static blockIpAddresses(a,n,i,s){let c=r({slug:i,environment:s,resourceType:"ipset"}),l=t(`${c}-${n.name}`),u={Type:"AWS::WAFv2::IPSet",Properties:{Name:`${c}-${n.name}`,Scope:a.Properties.Scope,IPAddressVersion:n.ipVersion||"IPV4",Addresses:n.ipAddresses,Description:`Blocked IPs for ${n.name}`}};if(!a.Properties.Rules)a.Properties.Rules=[];return a.Properties.Rules.push({Name:n.name,Priority:n.priority,Statement:{IPSetReferenceStatement:{Arn:N.GetAtt(l,"Arn")}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n.name}-metric`}}),{webAcl:a,ipSet:u,ipSetLogicalId:l}}static addManagedRules(a,n){if(!a.Properties.Rules)a.Properties.Rules=[];let i={ManagedRuleGroupStatement:{VendorName:n.vendorName,Name:n.ruleName}};if(n.excludedRules&&n.excludedRules.length>0)i.ManagedRuleGroupStatement.ExcludedRules=n.excludedRules.map((s)=>({Name:s}));return a.Properties.Rules.push({Name:n.name,Priority:n.priority,Statement:i,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n.name}-metric`}}),a}static ManagedRuleGroups={CoreRuleSet:{vendorName:"AWS",ruleName:"AWSManagedRulesCommonRuleSet"},KnownBadInputs:{vendorName:"AWS",ruleName:"AWSManagedRulesKnownBadInputsRuleSet"},SqlDatabase:{vendorName:"AWS",ruleName:"AWSManagedRulesSQLiRuleSet"},LinuxOS:{vendorName:"AWS",ruleName:"AWSManagedRulesLinuxRuleSet"},PosixOS:{vendorName:"AWS",ruleName:"AWSManagedRulesUnixRuleSet"},AmazonIpReputation:{vendorName:"AWS",ruleName:"AWSManagedRulesAmazonIpReputationList"},AnonymousIpList:{vendorName:"AWS",ruleName:"AWSManagedRulesAnonymousIpList"},BotControl:{vendorName:"AWS",ruleName:"AWSManagedRulesBotControlRuleSet"}};static setPathRateLimit(a,n){if(!a.Properties.Rules)a.Properties.Rules=[];let i=n.paths.map((s)=>({SearchString:s,FieldToMatch:{UriPath:{}},TextTransformation:[{Priority:0,Type:"LOWERCASE"}],PositionalConstraint:"STARTS_WITH"}));return a.Properties.Rules.push({Name:n.name,Priority:n.priority,Statement:{RateBasedStatement:{Limit:n.requestsPerWindow,AggregateKeyType:n.aggregateKeyType||"IP",ScopeDownStatement:{OrStatement:{Statements:i.map((s)=>({ByteMatchStatement:s}))}}}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n.name}-metric`}}),a}static setHeaderRateLimit(a,n){if(!a.Properties.Rules)a.Properties.Rules=[];let i={RateBasedStatement:{Limit:n.requestsPerWindow,AggregateKeyType:"CUSTOM_KEYS",CustomKeys:[{Header:{Name:n.headerName,TextTransformations:[{Priority:0,Type:"NONE"}]}}]}};if(n.headerValue)i.RateBasedStatement.ScopeDownStatement={ByteMatchStatement:{SearchString:n.headerValue,FieldToMatch:{SingleHeader:{Name:n.headerName}},TextTransformation:[{Priority:0,Type:"NONE"}],PositionalConstraint:"EXACTLY"}};return a.Properties.Rules.push({Name:n.name,Priority:n.priority,Statement:i,Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n.name}-metric`}}),a}static protectLoginEndpoint(a,n){let{loginPaths:i,priority:s,requestsPerMinute:c=10}=n;return I.setPathRateLimit(a,{name:"LoginRateLimit",priority:s,requestsPerWindow:c*5,paths:i}),a}static protectApiEndpoints(a,n){let{apiPaths:i,priority:s,requestsPerMinute:c=100}=n;return I.setPathRateLimit(a,{name:"ApiRateLimit",priority:s,requestsPerWindow:c*5,paths:i}),a}static createProtectedFirewall(a){let{slug:n,environment:i,scope:s="CLOUDFRONT",enableBotControl:c=!1,enableRateLimiting:l=!0,rateLimitPerMinute:u=2000}=a,{webAcl:h,logicalId:y}=I.createFirewall({slug:n,environment:i,scope:s,defaultAction:"allow"}),S=0;if(h=I.addManagedRules(h,{name:"AWSIPReputationList",priority:S++,...I.ManagedRuleGroups.AmazonIpReputation}),h=I.addManagedRules(h,{name:"AWSAnonymousIPList",priority:S++,...I.ManagedRuleGroups.AnonymousIpList}),h=I.addManagedRules(h,{name:"AWSCoreRuleSet",priority:S++,...I.ManagedRuleGroups.CoreRuleSet}),h=I.addManagedRules(h,{name:"AWSKnownBadInputs",priority:S++,...I.ManagedRuleGroups.KnownBadInputs}),h=I.addManagedRules(h,{name:"AWSSQLi",priority:S++,...I.ManagedRuleGroups.SqlDatabase}),c)h=I.addManagedRules(h,{name:"AWSBotControl",priority:S++,...I.ManagedRuleGroups.BotControl});if(l)h=I.setRateLimit(h,{name:"GlobalRateLimit",priority:S++,requestsPerWindow:u*5});return{webAcl:h,logicalId:y}}static RateLimitPresets={STANDARD:2000,HIGH_TRAFFIC:1e4,STRICT:100,LOGIN:10,API:100}}class o{static createServer(a){let{slug:n,environment:i,instanceType:s="t3.micro",imageId:c="ami-0f3caa1cf4417e51b",keyName:l,securityGroupIds:u,subnetId:h,userData:y,volumeSize:S=20,volumeType:b="gp3",encrypted:A=!0}=a,C=r({slug:n,environment:i,resourceType:"ec2"}),T=t(C),v={Type:"AWS::EC2::Instance",Properties:{ImageId:c,InstanceType:s,Tags:[{Key:"Name",Value:C},{Key:"Environment",Value:i}]}};if(l)v.Properties.KeyName=l;if(u)v.Properties.SecurityGroupIds=u;if(h)v.Properties.SubnetId=h;if(y)v.Properties.UserData=N.Base64(y);return v.Properties.BlockDeviceMappings=[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:S,VolumeType:b,Encrypted:A,DeleteOnTermination:!0}}],{instance:v,logicalId:T}}static createSecurityGroup(a){let{slug:n,environment:i,vpcId:s,description:c,ingress:l=[],egress:u=[]}=a,h=r({slug:n,environment:i,resourceType:"sg"}),y=t(h),S={Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:c||`Security group for ${n} ${i}`,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:i}]}};if(s)S.Properties.VpcId=s;if(l.length>0)S.Properties.SecurityGroupIngress=l.map((b)=>({IpProtocol:b.protocol,FromPort:b.fromPort,ToPort:b.toPort,CidrIp:b.cidr,SourceSecurityGroupId:b.sourceSecurityGroupId}));if(u.length>0)S.Properties.SecurityGroupEgress=u.map((b)=>({IpProtocol:b.protocol,FromPort:b.fromPort,ToPort:b.toPort,CidrIp:b.cidr,DestinationSecurityGroupId:b.sourceSecurityGroupId}));return{securityGroup:S,logicalId:y}}static createWebServerSecurityGroup(a,n,i){return o.createSecurityGroup({slug:a,environment:n,vpcId:i,description:"Security group for web servers - HTTP, HTTPS, SSH",ingress:[{protocol:"tcp",fromPort:80,toPort:80,cidr:"0.0.0.0/0"},{protocol:"tcp",fromPort:443,toPort:443,cidr:"0.0.0.0/0"},{protocol:"tcp",fromPort:22,toPort:22,cidr:"0.0.0.0/0"}],egress:[{protocol:"-1",fromPort:0,toPort:0,cidr:"0.0.0.0/0"}]})}static createLoadBalancer(a){let{slug:n,environment:i,scheme:s="internet-facing",subnets:c,securityGroups:l,type:u="application"}=a,h=r({slug:n,environment:i,resourceType:"alb"}),y=t(h),S={Type:"AWS::ElasticLoadBalancingV2::LoadBalancer",Properties:{Name:h,Scheme:s,Type:u,Subnets:c,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:i}]}};if(l)S.Properties.SecurityGroups=l;return{loadBalancer:S,logicalId:y}}static createTargetGroup(a){let{slug:n,environment:i,port:s,protocol:c="HTTP",vpcId:l,targetType:u="ip",healthCheckPath:h="/",healthCheckInterval:y=30,healthCheckTimeout:S=5,healthyThreshold:b=2,unhealthyThreshold:A=3}=a,C=r({slug:n,environment:i,resourceType:"tg"}),T=t(C);return{targetGroup:{Type:"AWS::ElasticLoadBalancingV2::TargetGroup",Properties:{Name:C,Port:s,Protocol:c,VpcId:l,TargetType:u,HealthCheckEnabled:!0,HealthCheckProtocol:c,HealthCheckPath:h,HealthCheckIntervalSeconds:y,HealthCheckTimeoutSeconds:S,HealthyThresholdCount:b,UnhealthyThresholdCount:A,Tags:[{Key:"Name",Value:C},{Key:"Environment",Value:i}]}},logicalId:T}}static createListener(a,n){let{port:i,protocol:s="HTTP",certificateArn:c,defaultTargetGroupArn:l}=n,u=t(`listener-${a}-${i}`),h={Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:N.Ref(a),Port:i,Protocol:s,DefaultActions:[{Type:"forward",TargetGroupArn:l}]}};if(s==="HTTPS"&&c)h.Properties.Certificates=[{CertificateArn:c}],h.Properties.SslPolicy="ELBSecurityPolicy-TLS13-1-2-2021-06";return{listener:h,logicalId:u}}static createEcsCluster(a,n){let i=r({slug:a,environment:n,resourceType:"ecs-cluster"}),s=t(i);return{cluster:{Type:"AWS::ECS::Cluster",Properties:{ClusterName:i,Tags:[{Key:"Name",Value:i},{Key:"Environment",Value:n}]}},logicalId:s}}static createFargateService(a){let{slug:n,environment:i,image:s,cpu:c="256",memory:l="512",desiredCount:u=1,containerPort:h=8080,environmentVariables:y={},secrets:S=[],healthCheck:b,logGroup:A,subnets:C,securityGroups:T,targetGroupArn:v}=a,{cluster:w,logicalId:R}=o.createEcsCluster(n,i),k=r({slug:n,environment:i,resourceType:"fargate"}),W=t(`${k}-execution-role`),P={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"]}},V=t(`${k}-task-role`),B={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]}}},j=t(`${k}-task`),J={Type:"AWS::ECS::TaskDefinition",Properties:{Family:k,TaskRoleArn:N.GetAtt(V,"Arn"),ExecutionRoleArn:N.GetAtt(W,"Arn"),NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:c,Memory:l,ContainerDefinitions:[{Name:n,Image:s,Essential:!0,PortMappings:[{ContainerPort:h,Protocol:"tcp"}],Environment:Object.entries(y).map(([te,ne])=>({Name:te,Value:ne})),Secrets:S.map((te)=>({Name:te.name,ValueFrom:te.valueFrom}))}],Tags:[{Key:"Name",Value:k},{Key:"Environment",Value:i}]}};if(b)J.Properties.ContainerDefinitions[0].HealthCheck={Command:b.command,Interval:b.interval||30,Timeout:b.timeout||5,Retries:b.retries||3,StartPeriod:60};if(A)J.Properties.ContainerDefinitions[0].LogConfiguration={LogDriver:"awslogs",Options:{"awslogs-group":A,"awslogs-region":N.Ref("AWS::Region"),"awslogs-stream-prefix":n}};let K=t(`${k}-service`),X={Type:"AWS::ECS::Service",Properties:{ServiceName:k,Cluster:N.Ref(R),TaskDefinition:N.Ref(j),DesiredCount:u,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{Subnets:C,SecurityGroups:T,AssignPublicIp:"ENABLED"}},Tags:[{Key:"Name",Value:k},{Key:"Environment",Value:i}]}};if(v)X.Properties.LoadBalancers=[{TargetGroupArn:v,ContainerName:n,ContainerPort:h}];return{cluster:w,taskDefinition:J,service:X,taskRole:B,executionRole:P,clusterLogicalId:R,taskDefinitionLogicalId:j,serviceLogicalId:K,taskRoleLogicalId:V,executionRoleLogicalId:W}}static createLambdaFunction(a){let{slug:n,environment:i,runtime:s,handler:c,code:l,timeout:u=30,memorySize:h=128,environmentVariables:y={},vpcConfig:S}=a,b=r({slug:n,environment:i,resourceType:"lambda"}),A=t(b),C=t(`${b}-role`),T={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]}};if(S)T.Properties.ManagedPolicyArns.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");let v={Type:"AWS::Lambda::Function",Properties:{FunctionName:b,Runtime:s,Role:N.GetAtt(C,"Arn"),Handler:c,Code:{...l.s3Bucket&&{S3Bucket:l.s3Bucket},...l.s3Key&&{S3Key:l.s3Key},...l.zipFile&&{ZipFile:l.zipFile}},Timeout:u,MemorySize:h,Tags:[{Key:"Name",Value:b},{Key:"Environment",Value:i}]}};if(Object.keys(y).length>0)v.Properties.Environment={Variables:y};if(S)v.Properties.VpcConfig={SecurityGroupIds:S.securityGroupIds,SubnetIds:S.subnetIds};return{lambdaFunction:v,role:T,logicalId:A,roleLogicalId:C}}static generateNodeServerUserData(a={}){let{nodeVersion:n="20",appRepo:i,environment:s={}}=a,c=Object.entries(s).map(([l,u])=>`echo "export ${l}='${u}'" >> /etc/environment`).join(`
212
+ `.trim()};static Config={ttl:(a)=>{let{min:n=0,max:i=86400,default:s=86400}=a;return{MinTTL:n,MaxTTL:i,DefaultTTL:s}},cookies:(a,n)=>{let i={Forward:a==="allowList"?"whitelist":a};if(a==="allowList"&&n)i.WhitelistedNames=n;return i},allowedMethods:(a)=>{let n={ALL:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return n[a]||n.GET_HEAD},cachedMethods:(a)=>{let n={GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return n[a]||n.GET_HEAD},ttlPresets:{static:{min:0,max:31536000,default:31536000},dynamic:{min:0,max:0,default:0},api:{min:0,max:3600,default:60},html:{min:0,max:86400,default:86400},images:{min:0,max:604800,default:604800}},cacheBehavior:(a)=>{let{ttl:n={min:0,max:86400,default:86400},cookies:i="none",allowedCookies:s,allowedMethods:c="GET_HEAD",cachedMethods:l="GET_HEAD",compress:u=!0,forwardQueryString:h=!0,forwardHeaders:y=[]}=a;return{MinTTL:n.min,MaxTTL:n.max,DefaultTTL:n.default,Compress:u,AllowedMethods:ve.Config.allowedMethods(c),CachedMethods:ve.Config.cachedMethods(l),ForwardedValues:{QueryString:h,Headers:y,Cookies:ve.Config.cookies(i,s)}}}};static applyConfig(a,n){let i=a.Properties.DistributionConfig.DefaultCacheBehavior;if(n.ttl)i.MinTTL=n.ttl.min,i.MaxTTL=n.ttl.max,i.DefaultTTL=n.ttl.default;if(n.compress!==void 0)i.Compress=n.compress;if(n.allowedMethods)i.AllowedMethods=ve.Config.allowedMethods(n.allowedMethods);if(n.cachedMethods)i.CachedMethods=ve.Config.cachedMethods(n.cachedMethods);if(n.cookies){if(!i.ForwardedValues)i.ForwardedValues={QueryString:!0};i.ForwardedValues.Cookies=ve.Config.cookies(n.cookies,n.allowedCookies)}return a}}class L{static createHostedZone(a){let{domain:n,slug:i,environment:s,comment:c}=a,l=r({slug:i,environment:s,resourceType:"hostedzone"}),u=t(`${l}-${n.replace(/\./g,"")}`);return{zone:{Type:"AWS::Route53::HostedZone",Properties:{Name:n,HostedZoneConfig:{Comment:c||`Hosted zone for ${n}`}}},logicalId:u}}static createRecord(a){let{hostedZoneId:n,hostedZoneName:i,name:s,type:c,ttl:l,values:u,aliasTarget:h}=a,y=t(`record-${s.replace(/\./g,"")}-${c}`),S={Type:"AWS::Route53::RecordSet",Properties:{Name:s,Type:c}};if(n)S.Properties.HostedZoneId=n;else if(i)S.Properties.HostedZoneName=i;if(h)S.Properties.AliasTarget={DNSName:h.dnsName,HostedZoneId:h.hostedZoneId,EvaluateTargetHealth:h.evaluateTargetHealth??!1};else S.Properties.TTL=l||300,S.Properties.ResourceRecords=u||[];return{record:S,logicalId:y}}static createCloudFrontAlias(a,n,i){return L.createRecord({hostedZoneId:i,name:a,type:"A",aliasTarget:{dnsName:n,hostedZoneId:"Z2FDTNDATAQYW2",evaluateTargetHealth:!1}})}static createAlbAlias(a,n,i,s){return L.createRecord({hostedZoneId:s,name:a,type:"A",aliasTarget:{dnsName:n,hostedZoneId:i,evaluateTargetHealth:!0}})}static createCname(a,n,i,s=300){return L.createRecord({hostedZoneId:i,name:a,type:"CNAME",ttl:s,values:[n]})}static createWwwRedirect(a,n){return L.createRecord({hostedZoneId:n,name:`www.${a}`,type:"CNAME",ttl:300,values:[a]})}static createMxRecords(a,n,i,s=300){return L.createRecord({hostedZoneId:i,name:a,type:"MX",ttl:s,values:n.map((c)=>`${c.priority} ${c.server}`)})}static createTxtRecord(a,n,i,s=300){return L.createRecord({hostedZoneId:i,name:a,type:"TXT",ttl:s,values:[`"${n}"`]})}static createSpfRecord(a,n,i){return L.createTxtRecord(a,n,i)}static createDmarcRecord(a,n,i,s){let c=`v=DMARC1; p=${n}; rua=mailto:${i}`;return L.createTxtRecord(`_dmarc.${a}`,c,s)}static createS3WebsiteAlias(a,n,i,s){return L.createRecord({hostedZoneId:s,name:a,type:"A",aliasTarget:{dnsName:n,hostedZoneId:i,evaluateTargetHealth:!1}})}static S3WebsiteHostedZoneIds={"us-east-1":"Z3AQBSTGFYJSTF","us-east-2":"Z2O1EMRO9K5GLX","us-west-1":"Z2F56UZL2M1ACD","us-west-2":"Z3BJ6K6RIION7M","af-south-1":"Z83WF9RJE8B12","ap-east-1":"ZNB98KWMFR0R6","ap-south-1":"Z11RGJOFQNVJUP","ap-south-2":"Z02976202B4EZMXIPMXF7","ap-northeast-1":"Z2M4EHUR26P7ZW","ap-northeast-2":"Z3W03O7B5YMIYP","ap-northeast-3":"Z2YQB5RD63NC85","ap-southeast-1":"Z3O0J2DXBE1FTB","ap-southeast-2":"Z1WCIBER6CPFUU","ap-southeast-3":"Z01613992JD795ZI93075","ca-central-1":"Z1QDHH18159H29","eu-central-1":"Z21DNDUVLTQW6Q","eu-central-2":"Z030506016YDQGETNASS","eu-west-1":"Z1BKCTXD74EZPE","eu-west-2":"Z3GKZC51ZF0DB4","eu-west-3":"Z3R1K369G5AVDG","eu-north-1":"Z3BAZG2TWCNX0D","eu-south-1":"Z30OZKI7KPW7MI","eu-south-2":"Z0081959F7139GRJC19J","me-south-1":"Z1MPMWCPA7YB62","me-central-1":"Z06143092I8HRBER9VXCO","sa-east-1":"Z7KQH4QJS55SO"};static getS3WebsiteEndpoint(a,n){return`${a}.s3-website-${n}.amazonaws.com`}static createStoreRecord(a,n,i){return L.createCname(`store.${a}`,n,i)}static createApiRecord(a,n,i){return L.createCname(`api.${a}`,n,i)}static createDocsRecord(a,n,i){return L.createCname(`docs.${a}`,n,i)}static CloudFrontHostedZoneId="Z2FDTNDATAQYW2"}class I{static createCertificate(a){let{domain:n,subdomains:i=[],slug:s,environment:c,validationMethod:l="DNS",hostedZoneId:u}=a,h=r({slug:s,environment:c,resourceType:"acm"}),y=t(`${h}-${n.replace(/\./g,"")}`),S=[n];for(let C of i)if(C==="*")S.push(`*.${n}`);else S.push(`${C}.${n}`);let A={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:n,SubjectAlternativeNames:S,ValidationMethod:l}};if(l==="DNS"&&u)A.Properties.DomainValidationOptions=S.map((C)=>({DomainName:C,HostedZoneId:u}));return{certificate:A,logicalId:y}}static createKmsKey(a){let{description:n,slug:i,environment:s,enableRotation:c=!0,multiRegion:l=!1}=a,u=r({slug:i,environment:s,resourceType:"kms"}),h=t(u),y={Version:"2012-10-17",Statement:[{Sid:"Enable IAM User Permissions",Effect:"Allow",Principal:{AWS:N.Sub("arn:aws:iam::${AWS::AccountId}:root")},Action:"kms:*",Resource:"*"},{Sid:"Allow services to use the key",Effect:"Allow",Principal:{Service:["s3.amazonaws.com","cloudfront.amazonaws.com","logs.amazonaws.com","secretsmanager.amazonaws.com"]},Action:["kms:Decrypt","kms:GenerateDataKey"],Resource:"*"}]},S={Type:"AWS::KMS::Key",Properties:{Description:n,Enabled:!0,EnableKeyRotation:c,KeyPolicy:y,KeySpec:"SYMMETRIC_DEFAULT",KeyUsage:"ENCRYPT_DECRYPT",MultiRegion:l}},A=t(`${u}-alias`),C={Type:"AWS::KMS::Alias",Properties:{AliasName:`alias/${i}-${s}`,TargetKeyId:N.Ref(h)}};return{key:S,alias:C,logicalId:h,aliasId:A}}static createFirewall(a){let{slug:n,environment:i,scope:s="CLOUDFRONT",defaultAction:c="allow"}=a,l=r({slug:n,environment:i,resourceType:"waf"}),u=t(l);return{webAcl:{Type:"AWS::WAFv2::WebACL",Properties:{Name:l,Scope:s,DefaultAction:c==="allow"?{Allow:{}}:{Block:{}},Description:`WAF for ${n} ${i}`,Rules:[],VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${l}-metric`}}},logicalId:u}}static setRateLimit(a,n){if(!a.Properties.Rules)a.Properties.Rules=[];return a.Properties.Rules.push({Name:n.name,Priority:n.priority,Statement:{RateBasedStatement:{Limit:n.requestsPerWindow,AggregateKeyType:n.aggregateKeyType||"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n.name}-metric`}}),a}static blockCountries(a,n){if(!a.Properties.Rules)a.Properties.Rules=[];return a.Properties.Rules.push({Name:n.name,Priority:n.priority,Statement:{GeoMatchStatement:{CountryCodes:n.countryCodes}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n.name}-metric`}}),a}static blockIpAddresses(a,n,i,s){let c=r({slug:i,environment:s,resourceType:"ipset"}),l=t(`${c}-${n.name}`),u={Type:"AWS::WAFv2::IPSet",Properties:{Name:`${c}-${n.name}`,Scope:a.Properties.Scope,IPAddressVersion:n.ipVersion||"IPV4",Addresses:n.ipAddresses,Description:`Blocked IPs for ${n.name}`}};if(!a.Properties.Rules)a.Properties.Rules=[];return a.Properties.Rules.push({Name:n.name,Priority:n.priority,Statement:{IPSetReferenceStatement:{Arn:N.GetAtt(l,"Arn")}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n.name}-metric`}}),{webAcl:a,ipSet:u,ipSetLogicalId:l}}static addManagedRules(a,n){if(!a.Properties.Rules)a.Properties.Rules=[];let i={ManagedRuleGroupStatement:{VendorName:n.vendorName,Name:n.ruleName}};if(n.excludedRules&&n.excludedRules.length>0)i.ManagedRuleGroupStatement.ExcludedRules=n.excludedRules.map((s)=>({Name:s}));return a.Properties.Rules.push({Name:n.name,Priority:n.priority,Statement:i,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n.name}-metric`}}),a}static ManagedRuleGroups={CoreRuleSet:{vendorName:"AWS",ruleName:"AWSManagedRulesCommonRuleSet"},KnownBadInputs:{vendorName:"AWS",ruleName:"AWSManagedRulesKnownBadInputsRuleSet"},SqlDatabase:{vendorName:"AWS",ruleName:"AWSManagedRulesSQLiRuleSet"},LinuxOS:{vendorName:"AWS",ruleName:"AWSManagedRulesLinuxRuleSet"},PosixOS:{vendorName:"AWS",ruleName:"AWSManagedRulesUnixRuleSet"},AmazonIpReputation:{vendorName:"AWS",ruleName:"AWSManagedRulesAmazonIpReputationList"},AnonymousIpList:{vendorName:"AWS",ruleName:"AWSManagedRulesAnonymousIpList"},BotControl:{vendorName:"AWS",ruleName:"AWSManagedRulesBotControlRuleSet"}};static setPathRateLimit(a,n){if(!a.Properties.Rules)a.Properties.Rules=[];let i=n.paths.map((s)=>({SearchString:s,FieldToMatch:{UriPath:{}},TextTransformation:[{Priority:0,Type:"LOWERCASE"}],PositionalConstraint:"STARTS_WITH"}));return a.Properties.Rules.push({Name:n.name,Priority:n.priority,Statement:{RateBasedStatement:{Limit:n.requestsPerWindow,AggregateKeyType:n.aggregateKeyType||"IP",ScopeDownStatement:{OrStatement:{Statements:i.map((s)=>({ByteMatchStatement:s}))}}}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n.name}-metric`}}),a}static setHeaderRateLimit(a,n){if(!a.Properties.Rules)a.Properties.Rules=[];let i={RateBasedStatement:{Limit:n.requestsPerWindow,AggregateKeyType:"CUSTOM_KEYS",CustomKeys:[{Header:{Name:n.headerName,TextTransformations:[{Priority:0,Type:"NONE"}]}}]}};if(n.headerValue)i.RateBasedStatement.ScopeDownStatement={ByteMatchStatement:{SearchString:n.headerValue,FieldToMatch:{SingleHeader:{Name:n.headerName}},TextTransformation:[{Priority:0,Type:"NONE"}],PositionalConstraint:"EXACTLY"}};return a.Properties.Rules.push({Name:n.name,Priority:n.priority,Statement:i,Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n.name}-metric`}}),a}static protectLoginEndpoint(a,n){let{loginPaths:i,priority:s,requestsPerMinute:c=10}=n;return I.setPathRateLimit(a,{name:"LoginRateLimit",priority:s,requestsPerWindow:c*5,paths:i}),a}static protectApiEndpoints(a,n){let{apiPaths:i,priority:s,requestsPerMinute:c=100}=n;return I.setPathRateLimit(a,{name:"ApiRateLimit",priority:s,requestsPerWindow:c*5,paths:i}),a}static createProtectedFirewall(a){let{slug:n,environment:i,scope:s="CLOUDFRONT",enableBotControl:c=!1,enableRateLimiting:l=!0,rateLimitPerMinute:u=2000}=a,{webAcl:h,logicalId:y}=I.createFirewall({slug:n,environment:i,scope:s,defaultAction:"allow"}),S=0;if(h=I.addManagedRules(h,{name:"AWSIPReputationList",priority:S++,...I.ManagedRuleGroups.AmazonIpReputation}),h=I.addManagedRules(h,{name:"AWSAnonymousIPList",priority:S++,...I.ManagedRuleGroups.AnonymousIpList}),h=I.addManagedRules(h,{name:"AWSCoreRuleSet",priority:S++,...I.ManagedRuleGroups.CoreRuleSet}),h=I.addManagedRules(h,{name:"AWSKnownBadInputs",priority:S++,...I.ManagedRuleGroups.KnownBadInputs}),h=I.addManagedRules(h,{name:"AWSSQLi",priority:S++,...I.ManagedRuleGroups.SqlDatabase}),c)h=I.addManagedRules(h,{name:"AWSBotControl",priority:S++,...I.ManagedRuleGroups.BotControl});if(l)h=I.setRateLimit(h,{name:"GlobalRateLimit",priority:S++,requestsPerWindow:u*5});return{webAcl:h,logicalId:y}}static RateLimitPresets={STANDARD:2000,HIGH_TRAFFIC:1e4,STRICT:100,LOGIN:10,API:100}}class o{static createServer(a){let{slug:n,environment:i,instanceType:s="t3.micro",imageId:c="ami-0f3caa1cf4417e51b",keyName:l,securityGroupIds:u,subnetId:h,userData:y,volumeSize:S=20,volumeType:A="gp3",encrypted:C=!0}=a,T=r({slug:n,environment:i,resourceType:"ec2"}),v=t(T),w={Type:"AWS::EC2::Instance",Properties:{ImageId:c,InstanceType:s,Tags:[{Key:"Name",Value:T},{Key:"Environment",Value:i}]}};if(l)w.Properties.KeyName=l;if(u)w.Properties.SecurityGroupIds=u;if(h)w.Properties.SubnetId=h;if(y)w.Properties.UserData=N.Base64(y);return w.Properties.BlockDeviceMappings=[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:S,VolumeType:A,Encrypted:C,DeleteOnTermination:!0}}],{instance:w,logicalId:v}}static createSecurityGroup(a){let{slug:n,environment:i,vpcId:s,description:c,ingress:l=[],egress:u=[]}=a,h=r({slug:n,environment:i,resourceType:"sg"}),y=t(h),S={Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:c||`Security group for ${n} ${i}`,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:i}]}};if(s)S.Properties.VpcId=s;if(l.length>0)S.Properties.SecurityGroupIngress=l.map((A)=>({IpProtocol:A.protocol,FromPort:A.fromPort,ToPort:A.toPort,CidrIp:A.cidr,SourceSecurityGroupId:A.sourceSecurityGroupId}));if(u.length>0)S.Properties.SecurityGroupEgress=u.map((A)=>({IpProtocol:A.protocol,FromPort:A.fromPort,ToPort:A.toPort,CidrIp:A.cidr,DestinationSecurityGroupId:A.sourceSecurityGroupId}));return{securityGroup:S,logicalId:y}}static createWebServerSecurityGroup(a,n,i){return o.createSecurityGroup({slug:a,environment:n,vpcId:i,description:"Security group for web servers - HTTP, HTTPS, SSH",ingress:[{protocol:"tcp",fromPort:80,toPort:80,cidr:"0.0.0.0/0"},{protocol:"tcp",fromPort:443,toPort:443,cidr:"0.0.0.0/0"},{protocol:"tcp",fromPort:22,toPort:22,cidr:"0.0.0.0/0"}],egress:[{protocol:"-1",fromPort:0,toPort:0,cidr:"0.0.0.0/0"}]})}static createLoadBalancer(a){let{slug:n,environment:i,scheme:s="internet-facing",subnets:c,securityGroups:l,type:u="application"}=a,h=r({slug:n,environment:i,resourceType:"alb"}),y=t(h),S={Type:"AWS::ElasticLoadBalancingV2::LoadBalancer",Properties:{Name:h,Scheme:s,Type:u,Subnets:c,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:i}]}};if(l)S.Properties.SecurityGroups=l;return{loadBalancer:S,logicalId:y}}static createTargetGroup(a){let{slug:n,environment:i,port:s,protocol:c="HTTP",vpcId:l,targetType:u="ip",healthCheckPath:h="/",healthCheckInterval:y=30,healthCheckTimeout:S=5,healthyThreshold:A=2,unhealthyThreshold:C=3}=a,T=r({slug:n,environment:i,resourceType:"tg"}),v=t(T);return{targetGroup:{Type:"AWS::ElasticLoadBalancingV2::TargetGroup",Properties:{Name:T,Port:s,Protocol:c,VpcId:l,TargetType:u,HealthCheckEnabled:!0,HealthCheckProtocol:c,HealthCheckPath:h,HealthCheckIntervalSeconds:y,HealthCheckTimeoutSeconds:S,HealthyThresholdCount:A,UnhealthyThresholdCount:C,Tags:[{Key:"Name",Value:T},{Key:"Environment",Value:i}]}},logicalId:v}}static createListener(a,n){let{port:i,protocol:s="HTTP",certificateArn:c,defaultTargetGroupArn:l}=n,u=t(`listener-${a}-${i}`),h={Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:N.Ref(a),Port:i,Protocol:s,DefaultActions:[{Type:"forward",TargetGroupArn:l}]}};if(s==="HTTPS"&&c)h.Properties.Certificates=[{CertificateArn:c}],h.Properties.SslPolicy="ELBSecurityPolicy-TLS13-1-2-2021-06";return{listener:h,logicalId:u}}static createEcsCluster(a,n){let i=r({slug:a,environment:n,resourceType:"ecs-cluster"}),s=t(i);return{cluster:{Type:"AWS::ECS::Cluster",Properties:{ClusterName:i,Tags:[{Key:"Name",Value:i},{Key:"Environment",Value:n}]}},logicalId:s}}static createFargateService(a){let{slug:n,environment:i,image:s,cpu:c="256",memory:l="512",desiredCount:u=1,containerPort:h=8080,environmentVariables:y={},secrets:S=[],healthCheck:A,logGroup:C,subnets:T,securityGroups:v,targetGroupArn:w}=a,{cluster:E,logicalId:R}=o.createEcsCluster(n,i),k=r({slug:n,environment:i,resourceType:"fargate"}),W=t(`${k}-execution-role`),P={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"]}},V=t(`${k}-task-role`),B={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]}}},j=t(`${k}-task`),J={Type:"AWS::ECS::TaskDefinition",Properties:{Family:k,TaskRoleArn:N.GetAtt(V,"Arn"),ExecutionRoleArn:N.GetAtt(W,"Arn"),NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:c,Memory:l,ContainerDefinitions:[{Name:n,Image:s,Essential:!0,PortMappings:[{ContainerPort:h,Protocol:"tcp"}],Environment:Object.entries(y).map(([te,ne])=>({Name:te,Value:ne})),Secrets:S.map((te)=>({Name:te.name,ValueFrom:te.valueFrom}))}],Tags:[{Key:"Name",Value:k},{Key:"Environment",Value:i}]}};if(A)J.Properties.ContainerDefinitions[0].HealthCheck={Command:A.command,Interval:A.interval||30,Timeout:A.timeout||5,Retries:A.retries||3,StartPeriod:60};if(C)J.Properties.ContainerDefinitions[0].LogConfiguration={LogDriver:"awslogs",Options:{"awslogs-group":C,"awslogs-region":N.Ref("AWS::Region"),"awslogs-stream-prefix":n}};let K=t(`${k}-service`),X={Type:"AWS::ECS::Service",Properties:{ServiceName:k,Cluster:N.Ref(R),TaskDefinition:N.Ref(j),DesiredCount:u,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{Subnets:T,SecurityGroups:v,AssignPublicIp:"ENABLED"}},Tags:[{Key:"Name",Value:k},{Key:"Environment",Value:i}]}};if(w)X.Properties.LoadBalancers=[{TargetGroupArn:w,ContainerName:n,ContainerPort:h}];return{cluster:E,taskDefinition:J,service:X,taskRole:B,executionRole:P,clusterLogicalId:R,taskDefinitionLogicalId:j,serviceLogicalId:K,taskRoleLogicalId:V,executionRoleLogicalId:W}}static createLambdaFunction(a){let{slug:n,environment:i,runtime:s,handler:c,code:l,timeout:u=30,memorySize:h=128,environmentVariables:y={},vpcConfig:S}=a,A=r({slug:n,environment:i,resourceType:"lambda"}),C=t(A),T=t(`${A}-role`),v={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]}};if(S)v.Properties.ManagedPolicyArns.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");let w={Type:"AWS::Lambda::Function",Properties:{FunctionName:A,Runtime:s,Role:N.GetAtt(T,"Arn"),Handler:c,Code:{...l.s3Bucket&&{S3Bucket:l.s3Bucket},...l.s3Key&&{S3Key:l.s3Key},...l.zipFile&&{ZipFile:l.zipFile}},Timeout:u,MemorySize:h,Tags:[{Key:"Name",Value:A},{Key:"Environment",Value:i}]}};if(Object.keys(y).length>0)w.Properties.Environment={Variables:y};if(S)w.Properties.VpcConfig={SecurityGroupIds:S.securityGroupIds,SubnetIds:S.subnetIds};return{lambdaFunction:w,role:v,logicalId:C,roleLogicalId:T}}static generateNodeServerUserData(a={}){let{nodeVersion:n="20",appRepo:i,environment:s={}}=a,c=Object.entries(s).map(([l,u])=>`echo "export ${l}='${u}'" >> /etc/environment`).join(`
213
213
  `);return`#!/bin/bash
214
214
  # Update system
215
215
  yum update -y
@@ -310,7 +310,7 @@ systemctl enable caddy
310
310
  systemctl start caddy
311
311
 
312
312
  echo "Bun server setup complete!"
313
- `}static createLaunchConfiguration(a){let{slug:n,environment:i,imageId:s,instanceType:c,keyName:l,securityGroups:u,userData:h,volumeSize:y=20,volumeType:S="gp3",encrypted:b=!0,iamInstanceProfile:A}=a,C=r({slug:n,environment:i,resourceType:"launch-config"}),T=t(C),v={Type:"AWS::AutoScaling::LaunchConfiguration",Properties:{ImageId:s,InstanceType:c,BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:y,VolumeType:S,Encrypted:b,DeleteOnTermination:!0}}]}};if(l)v.Properties.KeyName=l;if(u)v.Properties.SecurityGroups=u;if(h)v.Properties.UserData=N.Base64(h);if(A)v.Properties.IamInstanceProfile=A;return{launchConfiguration:v,logicalId:T}}static createAutoScalingGroup(a){let{slug:n,environment:i,launchConfigurationName:s,minSize:c,maxSize:l,desiredCapacity:u,vpcZoneIdentifier:h,targetGroupArns:y,healthCheckType:S="EC2",healthCheckGracePeriod:b=300,cooldown:A=300,tags:C={}}=a,T=r({slug:n,environment:i,resourceType:"asg"}),v=t(T),w={Type:"AWS::AutoScaling::AutoScalingGroup",Properties:{AutoScalingGroupName:T,LaunchConfigurationName:s,MinSize:c,MaxSize:l,HealthCheckType:S,HealthCheckGracePeriod:b,Cooldown:A,Tags:[{Key:"Name",Value:T,PropagateAtLaunch:!0},{Key:"Environment",Value:i,PropagateAtLaunch:!0},...Object.entries(C).map(([R,k])=>({Key:R,Value:k,PropagateAtLaunch:!0}))]}};if(u!==void 0)w.Properties.DesiredCapacity=u;if(h)w.Properties.VPCZoneIdentifier=h;if(y)w.Properties.TargetGroupARNs=y;return w.UpdatePolicy={AutoScalingRollingUpdate:{MaxBatchSize:1,MinInstancesInService:Math.max(0,c-1),PauseTime:"PT5M",WaitOnResourceSignals:!1}},{autoScalingGroup:w,logicalId:v}}static createScalingPolicy(a){let{slug:n,environment:i,autoScalingGroupName:s,policyType:c="TargetTrackingScaling",targetValue:l=70,predefinedMetricType:u="ASGAverageCPUUtilization"}=a,h=r({slug:n,environment:i,resourceType:"scaling-policy"}),y=t(h),S={Type:"AWS::AutoScaling::ScalingPolicy",Properties:{AutoScalingGroupName:s,PolicyType:c}};if(c==="TargetTrackingScaling")S.Properties.TargetTrackingConfiguration={PredefinedMetricSpecification:{PredefinedMetricType:u},TargetValue:l};return{scalingPolicy:S,logicalId:y}}static AutoScaling={smallWebServer:(a,n,i,s,c)=>o.createAutoScalingGroup({slug:a,environment:n,launchConfigurationName:i,minSize:2,maxSize:4,desiredCapacity:2,vpcZoneIdentifier:s,targetGroupArns:c,healthCheckType:c?"ELB":"EC2",healthCheckGracePeriod:300}),mediumWebServer:(a,n,i,s,c)=>o.createAutoScalingGroup({slug:a,environment:n,launchConfigurationName:i,minSize:3,maxSize:10,desiredCapacity:3,vpcZoneIdentifier:s,targetGroupArns:c,healthCheckType:c?"ELB":"EC2",healthCheckGracePeriod:300}),largeWebServer:(a,n,i,s,c)=>o.createAutoScalingGroup({slug:a,environment:n,launchConfigurationName:i,minSize:5,maxSize:20,desiredCapacity:5,vpcZoneIdentifier:s,targetGroupArns:c,healthCheckType:c?"ELB":"EC2",healthCheckGracePeriod:300}),cpuScaling:(a,n,i,s=70)=>o.createScalingPolicy({slug:a,environment:n,autoScalingGroupName:i,policyType:"TargetTrackingScaling",predefinedMetricType:"ASGAverageCPUUtilization",targetValue:s}),requestCountScaling:(a,n,i,s=1000)=>o.createScalingPolicy({slug:a,environment:n,autoScalingGroupName:i,policyType:"TargetTrackingScaling",predefinedMetricType:"ALBRequestCountPerTarget",targetValue:s})};static Secrets={fromSecretsManager:(a)=>Object.entries(a).map(([n,i])=>({name:n,valueFrom:i})),fromJsonSecret:(a,n)=>`${a}:${n}::`,fromSecretVersion:(a,n)=>`${a}::${n}:`,fromSecretVersionStage:(a,n)=>`${a}:::${n}`,createAccessPolicy:(a)=>({PolicyName:"SecretsManagerAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],Resource:a}]}}),createKmsPolicy:(a)=>({PolicyName:"KMSDecryptAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["kms:Decrypt"],Resource:a}]}}),buildSecretArn:(a)=>`arn:aws:secretsmanager:${a.region}:${a.accountId}:secret:${a.secretName}`,buildSecretArnPattern:(a)=>{let n=a.region||"*",i=a.accountId||"*";return`arn:aws:secretsmanager:${n}:${i}:secret:${a.secretNamePrefix}*`},commonAppSecrets:(a)=>({DATABASE_URL:`${a}/database-url`,DATABASE_PASSWORD:`${a}/database-password`,REDIS_URL:`${a}/redis-url`,REDIS_PASSWORD:`${a}/redis-password`,API_KEY:`${a}/api-key`,JWT_SECRET:`${a}/jwt-secret`,ENCRYPTION_KEY:`${a}/encryption-key`,AWS_ACCESS_KEY_ID:`${a}/aws-access-key-id`,AWS_SECRET_ACCESS_KEY:`${a}/aws-secret-access-key`,MAIL_PASSWORD:`${a}/mail-password`,STRIPE_SECRET_KEY:`${a}/stripe-secret-key`,STRIPE_WEBHOOK_SECRET:`${a}/stripe-webhook-secret`})};static createFargateServiceWithSecrets(a){let{secretArns:n=[],kmsKeyArns:i=[],...s}=a,c=o.createFargateService(s);if(n.length>0){if(!c.executionRole.Properties.Policies)c.executionRole.Properties.Policies=[];if(c.executionRole.Properties.Policies.push(o.Secrets.createAccessPolicy(n)),i.length>0)c.executionRole.Properties.Policies.push(o.Secrets.createKmsPolicy(i))}return c}static generateSecretReferences(a){return a.secrets.map((n)=>{let i=`arn:aws:secretsmanager:${a.region}:${a.accountId}:secret:${a.secretPrefix}/${n}`;return{name:n.toUpperCase().replace(/-/g,"_"),valueFrom:i}})}static EnvSecrets={database:(a)=>[{name:"DB_HOST",valueFrom:`${a}:host::`},{name:"DB_PORT",valueFrom:`${a}:port::`},{name:"DB_USERNAME",valueFrom:`${a}:username::`},{name:"DB_PASSWORD",valueFrom:`${a}:password::`},{name:"DB_NAME",valueFrom:`${a}:dbname::`}],redis:(a)=>[{name:"REDIS_HOST",valueFrom:`${a}:host::`},{name:"REDIS_PORT",valueFrom:`${a}:port::`},{name:"REDIS_PASSWORD",valueFrom:`${a}:password::`}],apiCredentials:(a)=>[{name:"API_KEY",valueFrom:`${a}:apiKey::`},{name:"API_SECRET",valueFrom:`${a}:apiSecret::`}],mail:(a)=>[{name:"MAIL_HOST",valueFrom:`${a}:host::`},{name:"MAIL_PORT",valueFrom:`${a}:port::`},{name:"MAIL_USERNAME",valueFrom:`${a}:username::`},{name:"MAIL_PASSWORD",valueFrom:`${a}:password::`}],awsCredentials:(a)=>[{name:"AWS_ACCESS_KEY_ID",valueFrom:`${a}:accessKeyId::`},{name:"AWS_SECRET_ACCESS_KEY",valueFrom:`${a}:secretAccessKey::`}]};static createJumpBox(a){let{slug:n,environment:i,vpcId:s,subnetId:c,keyName:l,instanceType:u="t3.micro",imageId:h="ami-0f3caa1cf4417e51b",allowedCidrs:y=["0.0.0.0/0"],mountEfs:S}=a,b=r({slug:n,environment:i,resourceType:"jumpbox"}),A=t(`${b}-sg`),C={Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:`${b}-sg`,GroupDescription:`Security group for ${b} JumpBox SSH access`,VpcId:s,SecurityGroupIngress:y.map((B)=>({IpProtocol:"tcp",FromPort:22,ToPort:22,CidrIp:B,Description:`SSH access from ${B}`})),SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound traffic"}],Tags:[{Key:"Name",Value:`${b}-sg`},{Key:"Environment",Value:i}]}},T=t(`${b}-role`),v={Type:"AWS::IAM::Role",Properties:{RoleName:`${b}-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ec2.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"],Policies:S?[{PolicyName:"EFSAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess"],Resource:"*"}]}}]:void 0}},w=t(`${b}-profile`),R={Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:`${b}-profile`,Roles:[N.Ref(T)]}},k=`#!/bin/bash
313
+ `}static createLaunchConfiguration(a){let{slug:n,environment:i,imageId:s,instanceType:c,keyName:l,securityGroups:u,userData:h,volumeSize:y=20,volumeType:S="gp3",encrypted:A=!0,iamInstanceProfile:C}=a,T=r({slug:n,environment:i,resourceType:"launch-config"}),v=t(T),w={Type:"AWS::AutoScaling::LaunchConfiguration",Properties:{ImageId:s,InstanceType:c,BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:y,VolumeType:S,Encrypted:A,DeleteOnTermination:!0}}]}};if(l)w.Properties.KeyName=l;if(u)w.Properties.SecurityGroups=u;if(h)w.Properties.UserData=N.Base64(h);if(C)w.Properties.IamInstanceProfile=C;return{launchConfiguration:w,logicalId:v}}static createAutoScalingGroup(a){let{slug:n,environment:i,launchConfigurationName:s,minSize:c,maxSize:l,desiredCapacity:u,vpcZoneIdentifier:h,targetGroupArns:y,healthCheckType:S="EC2",healthCheckGracePeriod:A=300,cooldown:C=300,tags:T={}}=a,v=r({slug:n,environment:i,resourceType:"asg"}),w=t(v),E={Type:"AWS::AutoScaling::AutoScalingGroup",Properties:{AutoScalingGroupName:v,LaunchConfigurationName:s,MinSize:c,MaxSize:l,HealthCheckType:S,HealthCheckGracePeriod:A,Cooldown:C,Tags:[{Key:"Name",Value:v,PropagateAtLaunch:!0},{Key:"Environment",Value:i,PropagateAtLaunch:!0},...Object.entries(T).map(([R,k])=>({Key:R,Value:k,PropagateAtLaunch:!0}))]}};if(u!==void 0)E.Properties.DesiredCapacity=u;if(h)E.Properties.VPCZoneIdentifier=h;if(y)E.Properties.TargetGroupARNs=y;return E.UpdatePolicy={AutoScalingRollingUpdate:{MaxBatchSize:1,MinInstancesInService:Math.max(0,c-1),PauseTime:"PT5M",WaitOnResourceSignals:!1}},{autoScalingGroup:E,logicalId:w}}static createScalingPolicy(a){let{slug:n,environment:i,autoScalingGroupName:s,policyType:c="TargetTrackingScaling",targetValue:l=70,predefinedMetricType:u="ASGAverageCPUUtilization"}=a,h=r({slug:n,environment:i,resourceType:"scaling-policy"}),y=t(h),S={Type:"AWS::AutoScaling::ScalingPolicy",Properties:{AutoScalingGroupName:s,PolicyType:c}};if(c==="TargetTrackingScaling")S.Properties.TargetTrackingConfiguration={PredefinedMetricSpecification:{PredefinedMetricType:u},TargetValue:l};return{scalingPolicy:S,logicalId:y}}static AutoScaling={smallWebServer:(a,n,i,s,c)=>o.createAutoScalingGroup({slug:a,environment:n,launchConfigurationName:i,minSize:2,maxSize:4,desiredCapacity:2,vpcZoneIdentifier:s,targetGroupArns:c,healthCheckType:c?"ELB":"EC2",healthCheckGracePeriod:300}),mediumWebServer:(a,n,i,s,c)=>o.createAutoScalingGroup({slug:a,environment:n,launchConfigurationName:i,minSize:3,maxSize:10,desiredCapacity:3,vpcZoneIdentifier:s,targetGroupArns:c,healthCheckType:c?"ELB":"EC2",healthCheckGracePeriod:300}),largeWebServer:(a,n,i,s,c)=>o.createAutoScalingGroup({slug:a,environment:n,launchConfigurationName:i,minSize:5,maxSize:20,desiredCapacity:5,vpcZoneIdentifier:s,targetGroupArns:c,healthCheckType:c?"ELB":"EC2",healthCheckGracePeriod:300}),cpuScaling:(a,n,i,s=70)=>o.createScalingPolicy({slug:a,environment:n,autoScalingGroupName:i,policyType:"TargetTrackingScaling",predefinedMetricType:"ASGAverageCPUUtilization",targetValue:s}),requestCountScaling:(a,n,i,s=1000)=>o.createScalingPolicy({slug:a,environment:n,autoScalingGroupName:i,policyType:"TargetTrackingScaling",predefinedMetricType:"ALBRequestCountPerTarget",targetValue:s})};static Secrets={fromSecretsManager:(a)=>Object.entries(a).map(([n,i])=>({name:n,valueFrom:i})),fromJsonSecret:(a,n)=>`${a}:${n}::`,fromSecretVersion:(a,n)=>`${a}::${n}:`,fromSecretVersionStage:(a,n)=>`${a}:::${n}`,createAccessPolicy:(a)=>({PolicyName:"SecretsManagerAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],Resource:a}]}}),createKmsPolicy:(a)=>({PolicyName:"KMSDecryptAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["kms:Decrypt"],Resource:a}]}}),buildSecretArn:(a)=>`arn:aws:secretsmanager:${a.region}:${a.accountId}:secret:${a.secretName}`,buildSecretArnPattern:(a)=>{let n=a.region||"*",i=a.accountId||"*";return`arn:aws:secretsmanager:${n}:${i}:secret:${a.secretNamePrefix}*`},commonAppSecrets:(a)=>({DATABASE_URL:`${a}/database-url`,DATABASE_PASSWORD:`${a}/database-password`,REDIS_URL:`${a}/redis-url`,REDIS_PASSWORD:`${a}/redis-password`,API_KEY:`${a}/api-key`,JWT_SECRET:`${a}/jwt-secret`,ENCRYPTION_KEY:`${a}/encryption-key`,AWS_ACCESS_KEY_ID:`${a}/aws-access-key-id`,AWS_SECRET_ACCESS_KEY:`${a}/aws-secret-access-key`,MAIL_PASSWORD:`${a}/mail-password`,STRIPE_SECRET_KEY:`${a}/stripe-secret-key`,STRIPE_WEBHOOK_SECRET:`${a}/stripe-webhook-secret`})};static createFargateServiceWithSecrets(a){let{secretArns:n=[],kmsKeyArns:i=[],...s}=a,c=o.createFargateService(s);if(n.length>0){if(!c.executionRole.Properties.Policies)c.executionRole.Properties.Policies=[];if(c.executionRole.Properties.Policies.push(o.Secrets.createAccessPolicy(n)),i.length>0)c.executionRole.Properties.Policies.push(o.Secrets.createKmsPolicy(i))}return c}static generateSecretReferences(a){return a.secrets.map((n)=>{let i=`arn:aws:secretsmanager:${a.region}:${a.accountId}:secret:${a.secretPrefix}/${n}`;return{name:n.toUpperCase().replace(/-/g,"_"),valueFrom:i}})}static EnvSecrets={database:(a)=>[{name:"DB_HOST",valueFrom:`${a}:host::`},{name:"DB_PORT",valueFrom:`${a}:port::`},{name:"DB_USERNAME",valueFrom:`${a}:username::`},{name:"DB_PASSWORD",valueFrom:`${a}:password::`},{name:"DB_NAME",valueFrom:`${a}:dbname::`}],redis:(a)=>[{name:"REDIS_HOST",valueFrom:`${a}:host::`},{name:"REDIS_PORT",valueFrom:`${a}:port::`},{name:"REDIS_PASSWORD",valueFrom:`${a}:password::`}],apiCredentials:(a)=>[{name:"API_KEY",valueFrom:`${a}:apiKey::`},{name:"API_SECRET",valueFrom:`${a}:apiSecret::`}],mail:(a)=>[{name:"MAIL_HOST",valueFrom:`${a}:host::`},{name:"MAIL_PORT",valueFrom:`${a}:port::`},{name:"MAIL_USERNAME",valueFrom:`${a}:username::`},{name:"MAIL_PASSWORD",valueFrom:`${a}:password::`}],awsCredentials:(a)=>[{name:"AWS_ACCESS_KEY_ID",valueFrom:`${a}:accessKeyId::`},{name:"AWS_SECRET_ACCESS_KEY",valueFrom:`${a}:secretAccessKey::`}]};static createJumpBox(a){let{slug:n,environment:i,vpcId:s,subnetId:c,keyName:l,instanceType:u="t3.micro",imageId:h="ami-0f3caa1cf4417e51b",allowedCidrs:y=["0.0.0.0/0"],mountEfs:S}=a,A=r({slug:n,environment:i,resourceType:"jumpbox"}),C=t(`${A}-sg`),T={Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:`${A}-sg`,GroupDescription:`Security group for ${A} JumpBox SSH access`,VpcId:s,SecurityGroupIngress:y.map((B)=>({IpProtocol:"tcp",FromPort:22,ToPort:22,CidrIp:B,Description:`SSH access from ${B}`})),SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound traffic"}],Tags:[{Key:"Name",Value:`${A}-sg`},{Key:"Environment",Value:i}]}},v=t(`${A}-role`),w={Type:"AWS::IAM::Role",Properties:{RoleName:`${A}-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ec2.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"],Policies:S?[{PolicyName:"EFSAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess"],Resource:"*"}]}}]:void 0}},E=t(`${A}-profile`),R={Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:`${A}-profile`,Roles:[N.Ref(v)]}},k=`#!/bin/bash
314
314
  yum update -y
315
315
  yum install -y amazon-efs-utils nfs-utils jq curl wget htop
316
316
  `;if(S){let B=S.mountPath||"/mnt/efs";k+=`
@@ -318,7 +318,7 @@ yum install -y amazon-efs-utils nfs-utils jq curl wget htop
318
318
  mkdir -p ${B}
319
319
  mount -t efs ${S.fileSystemId}:/ ${B}
320
320
  echo "${S.fileSystemId}:/ ${B} efs defaults,_netdev 0 0" >> /etc/fstab
321
- `}let W=t(b),P={Type:"AWS::EC2::Instance",DependsOn:[w],Properties:{ImageId:h,InstanceType:u,KeyName:l,SubnetId:c,SecurityGroupIds:[N.Ref(A)],IamInstanceProfile:N.Ref(w),UserData:N.Base64(k),BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:20,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0}}],Tags:[{Key:"Name",Value:b},{Key:"Environment",Value:i},{Key:"Purpose",Value:"JumpBox/Bastion"}]}},V={[A]:C,[T]:v,[w]:R,[W]:P};return{instance:P,securityGroup:C,instanceProfile:R,instanceRole:v,instanceLogicalId:W,securityGroupLogicalId:A,instanceProfileLogicalId:w,instanceRoleLogicalId:T,resources:V}}static JumpBox={withEfsMount:(a)=>o.createJumpBox({slug:a.slug,environment:a.environment,vpcId:a.vpcId,subnetId:a.subnetId,keyName:a.keyName,allowedCidrs:a.allowedCidrs,mountEfs:{fileSystemId:a.fileSystemId,mountPath:a.mountPath||"/mnt/efs"}}),minimal:(a)=>o.createJumpBox({slug:a.slug,environment:a.environment,vpcId:a.vpcId,subnetId:a.subnetId,keyName:a.keyName,instanceType:"t3.nano",allowedCidrs:a.allowedCidrs}),withDatabaseTools:(a)=>{let n=o.createJumpBox({slug:a.slug,environment:a.environment,vpcId:a.vpcId,subnetId:a.subnetId,keyName:a.keyName,allowedCidrs:a.allowedCidrs}),i=`#!/bin/bash
321
+ `}let W=t(A),P={Type:"AWS::EC2::Instance",DependsOn:[E],Properties:{ImageId:h,InstanceType:u,KeyName:l,SubnetId:c,SecurityGroupIds:[N.Ref(C)],IamInstanceProfile:N.Ref(E),UserData:N.Base64(k),BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:20,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0}}],Tags:[{Key:"Name",Value:A},{Key:"Environment",Value:i},{Key:"Purpose",Value:"JumpBox/Bastion"}]}},V={[C]:T,[v]:w,[E]:R,[W]:P};return{instance:P,securityGroup:T,instanceProfile:R,instanceRole:w,instanceLogicalId:W,securityGroupLogicalId:C,instanceProfileLogicalId:E,instanceRoleLogicalId:v,resources:V}}static JumpBox={withEfsMount:(a)=>o.createJumpBox({slug:a.slug,environment:a.environment,vpcId:a.vpcId,subnetId:a.subnetId,keyName:a.keyName,allowedCidrs:a.allowedCidrs,mountEfs:{fileSystemId:a.fileSystemId,mountPath:a.mountPath||"/mnt/efs"}}),minimal:(a)=>o.createJumpBox({slug:a.slug,environment:a.environment,vpcId:a.vpcId,subnetId:a.subnetId,keyName:a.keyName,instanceType:"t3.nano",allowedCidrs:a.allowedCidrs}),withDatabaseTools:(a)=>{let n=o.createJumpBox({slug:a.slug,environment:a.environment,vpcId:a.vpcId,subnetId:a.subnetId,keyName:a.keyName,allowedCidrs:a.allowedCidrs}),i=`#!/bin/bash
322
322
  yum update -y
323
323
  yum install -y amazon-efs-utils nfs-utils jq curl wget htop
324
324
 
@@ -346,7 +346,7 @@ yum install -y mysql
346
346
  yum install -y redis
347
347
 
348
348
  echo "Database tools installed!"
349
- `),n},commonCidrs:{any:["0.0.0.0/0"],privateOnly:["10.0.0.0/8","172.16.0.0/12","192.168.0.0/16"]}};static InstanceSize={toInstanceType:(a,n="t3")=>`${n}.${a}`,specs:{nano:{vcpu:2,memory:0.5,instanceType:"t3.nano"},micro:{vcpu:2,memory:1,instanceType:"t3.micro"},small:{vcpu:2,memory:2,instanceType:"t3.small"},medium:{vcpu:2,memory:4,instanceType:"t3.medium"},large:{vcpu:2,memory:8,instanceType:"t3.large"},xlarge:{vcpu:4,memory:16,instanceType:"t3.xlarge"},"2xlarge":{vcpu:8,memory:32,instanceType:"t3.2xlarge"}},toFargateSpecs:(a)=>{let n={nano:{cpu:"256",memory:"512"},micro:{cpu:"256",memory:"1024"},small:{cpu:"512",memory:"1024"},medium:{cpu:"1024",memory:"2048"},large:{cpu:"2048",memory:"4096"},xlarge:{cpu:"4096",memory:"8192"},"2xlarge":{cpu:"4096",memory:"16384"}};return n[a]||n.medium},toLambdaMemory:(a)=>({nano:128,micro:256,small:512,medium:1024,large:2048,xlarge:4096,"2xlarge":8192})[a]||1024,presets:{webServer:"t3.small",apiServer:"t3.medium",worker:"t3.medium",database:"r6i.large",cache:"r6i.medium",compute:"c6i.large",general:"m6i.medium"}};static DiskConfig={create:(a)=>{let{size:n,type:i="ssd",encrypted:s=!0,iops:c,throughput:l,deleteOnTermination:u=!0}=a,h={standard:"gp2",ssd:"gp3",premium:"io2",gp2:"gp2",gp3:"gp3",io1:"io1",io2:"io2"}[i]||"gp3",y={VolumeSize:n,VolumeType:h,Encrypted:s,DeleteOnTermination:u};if((h==="io1"||h==="io2"||h==="gp3")&&c)y.Iops=c;if(h==="gp3"&&l)y.Throughput=l;return y},presets:{standard:{VolumeSize:20,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0},large:{VolumeSize:100,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0},highPerformance:{VolumeSize:50,VolumeType:"io2",Iops:3000,Encrypted:!0,DeleteOnTermination:!0},database:{VolumeSize:100,VolumeType:"io2",Iops:1e4,Encrypted:!0,DeleteOnTermination:!1}}};static SpotConfig={create:(a)=>{let{maxPrice:n,spotInstanceType:i="one-time",interruptionBehavior:s="terminate",blockDurationMinutes:c}=a,l={SpotInstanceType:i,InstanceInterruptionBehavior:s};if(n)l.MaxPrice=n;if(c)l.BlockDurationMinutes=c;return{SpotOptions:l}},presets:{standard:{spotInstanceType:"one-time",interruptionBehavior:"terminate"},persistent:{spotInstanceType:"persistent",interruptionBehavior:"stop"},costOptimized:{maxPrice:"0.05",spotInstanceType:"one-time",interruptionBehavior:"terminate"}}};static MixedInstances={create:(a)=>{let{instanceTypes:n,baseCapacity:i=0,onDemandPercentage:s=20,spotAllocationStrategy:c="capacity-optimized",spotMaxPrice:l}=a,u={OnDemandBaseCapacity:i,OnDemandPercentageAboveBaseCapacity:s,SpotAllocationStrategy:c};if(l)u.SpotMaxPrice=l;let h=n.map(({size:y,weight:S})=>{let b={InstanceType:o.InstanceSize.toInstanceType(y)};if(S)b.WeightedCapacity=String(S);return b});return{MixedInstancesPolicy:{InstancesDistribution:u,LaunchTemplate:{Overrides:h}}}},presets:{costOptimized:{baseCapacity:0,onDemandPercentage:20,spotAllocationStrategy:"lowest-price",instanceTypes:[{size:"small",weight:1},{size:"medium",weight:2}]},balanced:{baseCapacity:1,onDemandPercentage:50,spotAllocationStrategy:"capacity-optimized",instanceTypes:[{size:"medium",weight:1},{size:"large",weight:2}]},highAvailability:{baseCapacity:2,onDemandPercentage:80,spotAllocationStrategy:"capacity-optimized-prioritized",instanceTypes:[{size:"medium",weight:1}]}}};static AutoScalingConfig={create:(a)=>{let{min:n,max:i,desired:s=n,scaleUpThreshold:c=70,scaleDownThreshold:l=30,cooldownSeconds:u=300,targetMetric:h="cpu"}=a,y={cpu:"ASGAverageCPUUtilization",memory:"ASGAverageMemoryUtilization",requests:"ALBRequestCountPerTarget"};return{minSize:n,maxSize:i,desiredCapacity:s,scalingPolicies:[{policyType:"TargetTrackingScaling",targetValue:c,predefinedMetricType:y[h]||y.cpu,scaleInCooldown:u,scaleOutCooldown:u}]}},forEcs:(a)=>{let{min:n,max:i,cpuTarget:s=70,memoryTarget:c}=a,l=[{predefinedMetricType:"ECSServiceAverageCPUUtilization",targetValue:s}];if(c)l.push({predefinedMetricType:"ECSServiceAverageMemoryUtilization",targetValue:c});return{minCapacity:n,maxCapacity:i,targetTrackingPolicies:l}},presets:{small:{min:1,max:3,scaleUpThreshold:70,scaleDownThreshold:30},medium:{min:2,max:10,scaleUpThreshold:70,scaleDownThreshold:30},large:{min:3,max:50,scaleUpThreshold:60,scaleDownThreshold:40},highAvailability:{min:2,max:20,scaleUpThreshold:60,scaleDownThreshold:30}}};static LoadBalancerConfig={healthCheck:(a)=>{let{path:n="/",interval:i=30,timeout:s=5,healthyThreshold:c=2,unhealthyThreshold:l=5,protocol:u="HTTP"}=a,h={HealthCheckIntervalSeconds:i,HealthCheckTimeoutSeconds:s,HealthyThresholdCount:c,UnhealthyThresholdCount:l};if(u!=="TCP")h.HealthCheckPath=n,h.HealthCheckProtocol=u;return h},presets:{standard:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:5},fast:{path:"/health",interval:10,timeout:3,healthyThreshold:2,unhealthyThreshold:2},relaxed:{path:"/health",interval:60,timeout:30,healthyThreshold:2,unhealthyThreshold:10}}};static SslConfig={httpsListener:(a)=>{let{certificateArn:n,targetGroupArn:i,port:s=443,sslPolicy:c="ELBSecurityPolicy-TLS13-1-2-2021-06"}=a;return{Port:s,Protocol:"HTTPS",Certificates:[{CertificateArn:n}],SslPolicy:c,DefaultActions:[{Type:"forward",TargetGroupArn:i}]}},httpRedirectListener:(a=80)=>({Port:a,Protocol:"HTTP",DefaultActions:[{Type:"redirect",RedirectConfig:{Protocol:"HTTPS",Port:"443",StatusCode:"HTTP_301"}}]}),policies:{tls13:"ELBSecurityPolicy-TLS13-1-2-2021-06",tls12:"ELBSecurityPolicy-TLS-1-2-Ext-2018-06",tls11:"ELBSecurityPolicy-TLS-1-1-2017-01",fips:"ELBSecurityPolicy-TLS-1-2-Ext-FIPS-2022-05"}};static FunctionConfig={create:(a)=>{let{handler:n,runtime:i="nodejs20.x",timeout:s=30,memorySize:c=256,environmentVariables:l,reservedConcurrency:u}=a,h={Handler:n,Runtime:i,Timeout:s,MemorySize:c};if(l)h.Environment={Variables:l};if(u)h.ReservedConcurrentExecutions=u;return h},runtimes:{nodejs20:"nodejs20.x",nodejs18:"nodejs18.x",python312:"python3.12",python311:"python3.11",java21:"java21",java17:"java17",go:"provided.al2023",rust:"provided.al2023",bun:"provided.al2023"},presets:{api:{runtime:"nodejs20.x",timeout:30,memorySize:256},worker:{runtime:"nodejs20.x",timeout:300,memorySize:512},cron:{runtime:"nodejs20.x",timeout:900,memorySize:1024},dataProcessing:{runtime:"nodejs20.x",timeout:900,memorySize:3008}}};static UserData={generateAppServerScript:(a)=>{let{runtime:n="bun",runtimeVersion:i="latest",webServer:s="nginx",processManager:c="systemd",enableSsl:l=!0,sslEmail:u="admin@example.com",domain:h,appPort:y=3000,installDatabaseClients:S=!1,installRedis:b=!1,extraPackages:A=[]}=a,C=`#!/bin/bash
349
+ `),n},commonCidrs:{any:["0.0.0.0/0"],privateOnly:["10.0.0.0/8","172.16.0.0/12","192.168.0.0/16"]}};static InstanceSize={toInstanceType:(a,n="t3")=>`${n}.${a}`,specs:{nano:{vcpu:2,memory:0.5,instanceType:"t3.nano"},micro:{vcpu:2,memory:1,instanceType:"t3.micro"},small:{vcpu:2,memory:2,instanceType:"t3.small"},medium:{vcpu:2,memory:4,instanceType:"t3.medium"},large:{vcpu:2,memory:8,instanceType:"t3.large"},xlarge:{vcpu:4,memory:16,instanceType:"t3.xlarge"},"2xlarge":{vcpu:8,memory:32,instanceType:"t3.2xlarge"}},toFargateSpecs:(a)=>{let n={nano:{cpu:"256",memory:"512"},micro:{cpu:"256",memory:"1024"},small:{cpu:"512",memory:"1024"},medium:{cpu:"1024",memory:"2048"},large:{cpu:"2048",memory:"4096"},xlarge:{cpu:"4096",memory:"8192"},"2xlarge":{cpu:"4096",memory:"16384"}};return n[a]||n.medium},toLambdaMemory:(a)=>({nano:128,micro:256,small:512,medium:1024,large:2048,xlarge:4096,"2xlarge":8192})[a]||1024,presets:{webServer:"t3.small",apiServer:"t3.medium",worker:"t3.medium",database:"r6i.large",cache:"r6i.medium",compute:"c6i.large",general:"m6i.medium"}};static DiskConfig={create:(a)=>{let{size:n,type:i="ssd",encrypted:s=!0,iops:c,throughput:l,deleteOnTermination:u=!0}=a,h={standard:"gp2",ssd:"gp3",premium:"io2",gp2:"gp2",gp3:"gp3",io1:"io1",io2:"io2"}[i]||"gp3",y={VolumeSize:n,VolumeType:h,Encrypted:s,DeleteOnTermination:u};if((h==="io1"||h==="io2"||h==="gp3")&&c)y.Iops=c;if(h==="gp3"&&l)y.Throughput=l;return y},presets:{standard:{VolumeSize:20,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0},large:{VolumeSize:100,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0},highPerformance:{VolumeSize:50,VolumeType:"io2",Iops:3000,Encrypted:!0,DeleteOnTermination:!0},database:{VolumeSize:100,VolumeType:"io2",Iops:1e4,Encrypted:!0,DeleteOnTermination:!1}}};static SpotConfig={create:(a)=>{let{maxPrice:n,spotInstanceType:i="one-time",interruptionBehavior:s="terminate",blockDurationMinutes:c}=a,l={SpotInstanceType:i,InstanceInterruptionBehavior:s};if(n)l.MaxPrice=n;if(c)l.BlockDurationMinutes=c;return{SpotOptions:l}},presets:{standard:{spotInstanceType:"one-time",interruptionBehavior:"terminate"},persistent:{spotInstanceType:"persistent",interruptionBehavior:"stop"},costOptimized:{maxPrice:"0.05",spotInstanceType:"one-time",interruptionBehavior:"terminate"}}};static MixedInstances={create:(a)=>{let{instanceTypes:n,baseCapacity:i=0,onDemandPercentage:s=20,spotAllocationStrategy:c="capacity-optimized",spotMaxPrice:l}=a,u={OnDemandBaseCapacity:i,OnDemandPercentageAboveBaseCapacity:s,SpotAllocationStrategy:c};if(l)u.SpotMaxPrice=l;let h=n.map(({size:y,weight:S})=>{let A={InstanceType:o.InstanceSize.toInstanceType(y)};if(S)A.WeightedCapacity=String(S);return A});return{MixedInstancesPolicy:{InstancesDistribution:u,LaunchTemplate:{Overrides:h}}}},presets:{costOptimized:{baseCapacity:0,onDemandPercentage:20,spotAllocationStrategy:"lowest-price",instanceTypes:[{size:"small",weight:1},{size:"medium",weight:2}]},balanced:{baseCapacity:1,onDemandPercentage:50,spotAllocationStrategy:"capacity-optimized",instanceTypes:[{size:"medium",weight:1},{size:"large",weight:2}]},highAvailability:{baseCapacity:2,onDemandPercentage:80,spotAllocationStrategy:"capacity-optimized-prioritized",instanceTypes:[{size:"medium",weight:1}]}}};static AutoScalingConfig={create:(a)=>{let{min:n,max:i,desired:s=n,scaleUpThreshold:c=70,scaleDownThreshold:l=30,cooldownSeconds:u=300,targetMetric:h="cpu"}=a,y={cpu:"ASGAverageCPUUtilization",memory:"ASGAverageMemoryUtilization",requests:"ALBRequestCountPerTarget"};return{minSize:n,maxSize:i,desiredCapacity:s,scalingPolicies:[{policyType:"TargetTrackingScaling",targetValue:c,predefinedMetricType:y[h]||y.cpu,scaleInCooldown:u,scaleOutCooldown:u}]}},forEcs:(a)=>{let{min:n,max:i,cpuTarget:s=70,memoryTarget:c}=a,l=[{predefinedMetricType:"ECSServiceAverageCPUUtilization",targetValue:s}];if(c)l.push({predefinedMetricType:"ECSServiceAverageMemoryUtilization",targetValue:c});return{minCapacity:n,maxCapacity:i,targetTrackingPolicies:l}},presets:{small:{min:1,max:3,scaleUpThreshold:70,scaleDownThreshold:30},medium:{min:2,max:10,scaleUpThreshold:70,scaleDownThreshold:30},large:{min:3,max:50,scaleUpThreshold:60,scaleDownThreshold:40},highAvailability:{min:2,max:20,scaleUpThreshold:60,scaleDownThreshold:30}}};static LoadBalancerConfig={healthCheck:(a)=>{let{path:n="/",interval:i=30,timeout:s=5,healthyThreshold:c=2,unhealthyThreshold:l=5,protocol:u="HTTP"}=a,h={HealthCheckIntervalSeconds:i,HealthCheckTimeoutSeconds:s,HealthyThresholdCount:c,UnhealthyThresholdCount:l};if(u!=="TCP")h.HealthCheckPath=n,h.HealthCheckProtocol=u;return h},presets:{standard:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:5},fast:{path:"/health",interval:10,timeout:3,healthyThreshold:2,unhealthyThreshold:2},relaxed:{path:"/health",interval:60,timeout:30,healthyThreshold:2,unhealthyThreshold:10}}};static SslConfig={httpsListener:(a)=>{let{certificateArn:n,targetGroupArn:i,port:s=443,sslPolicy:c="ELBSecurityPolicy-TLS13-1-2-2021-06"}=a;return{Port:s,Protocol:"HTTPS",Certificates:[{CertificateArn:n}],SslPolicy:c,DefaultActions:[{Type:"forward",TargetGroupArn:i}]}},httpRedirectListener:(a=80)=>({Port:a,Protocol:"HTTP",DefaultActions:[{Type:"redirect",RedirectConfig:{Protocol:"HTTPS",Port:"443",StatusCode:"HTTP_301"}}]}),policies:{tls13:"ELBSecurityPolicy-TLS13-1-2-2021-06",tls12:"ELBSecurityPolicy-TLS-1-2-Ext-2018-06",tls11:"ELBSecurityPolicy-TLS-1-1-2017-01",fips:"ELBSecurityPolicy-TLS-1-2-Ext-FIPS-2022-05"}};static FunctionConfig={create:(a)=>{let{handler:n,runtime:i="nodejs20.x",timeout:s=30,memorySize:c=256,environmentVariables:l,reservedConcurrency:u}=a,h={Handler:n,Runtime:i,Timeout:s,MemorySize:c};if(l)h.Environment={Variables:l};if(u)h.ReservedConcurrentExecutions=u;return h},runtimes:{nodejs20:"nodejs20.x",nodejs18:"nodejs18.x",python312:"python3.12",python311:"python3.11",java21:"java21",java17:"java17",go:"provided.al2023",rust:"provided.al2023",bun:"provided.al2023"},presets:{api:{runtime:"nodejs20.x",timeout:30,memorySize:256},worker:{runtime:"nodejs20.x",timeout:300,memorySize:512},cron:{runtime:"nodejs20.x",timeout:900,memorySize:1024},dataProcessing:{runtime:"nodejs20.x",timeout:900,memorySize:3008}}};static UserData={generateAppServerScript:(a)=>{let{runtime:n="bun",runtimeVersion:i="latest",webServer:s="nginx",processManager:c="systemd",enableSsl:l=!0,sslEmail:u="admin@example.com",domain:h,appPort:y=3000,installDatabaseClients:S=!1,installRedis:A=!1,extraPackages:C=[]}=a,T=`#!/bin/bash
350
350
  set -e
351
351
 
352
352
  # Update system
@@ -356,7 +356,7 @@ apt-get update && apt-get upgrade -y
356
356
  # Install basic tools
357
357
  apt-get install -y curl wget git jq htop unzip
358
358
 
359
- `;if(n==="bun")C+=o.UserData.Scripts.bun(i);else C+=o.UserData.Scripts.nodeJs(i);if(s==="nginx"){if(C+=o.UserData.Scripts.nginx(),h&&l)C+=o.UserData.Scripts.nginxProxy(h,y)}else if(s==="caddy"){if(C+=o.UserData.Scripts.caddy(),h)C+=o.UserData.Scripts.caddyProxy(h,y)}if(c==="pm2"&&n==="node")C+=o.UserData.Scripts.pm2();if(l&&s==="nginx"&&h)C+=o.UserData.Scripts.letsEncrypt(h,u);if(S)C+=o.UserData.Scripts.databaseClients();if(b)C+=o.UserData.Scripts.redis();if(C+=`
359
+ `;if(n==="bun")T+=o.UserData.Scripts.bun(i);else T+=o.UserData.Scripts.nodeJs(i);if(s==="nginx"){if(T+=o.UserData.Scripts.nginx(),h&&l)T+=o.UserData.Scripts.nginxProxy(h,y)}else if(s==="caddy"){if(T+=o.UserData.Scripts.caddy(),h)T+=o.UserData.Scripts.caddyProxy(h,y)}if(c==="pm2"&&n==="node")T+=o.UserData.Scripts.pm2();if(l&&s==="nginx"&&h)T+=o.UserData.Scripts.letsEncrypt(h,u);if(S)T+=o.UserData.Scripts.databaseClients();if(A)T+=o.UserData.Scripts.redis();if(T+=`
360
360
  # Install AWS CLI
361
361
  if ! command -v aws &> /dev/null; then
362
362
  curl -fsSL "https://awscli.amazonaws.com/awscli-exe-linux-$(uname -m).zip" -o /tmp/awscliv2.zip
@@ -364,10 +364,10 @@ if ! command -v aws &> /dev/null; then
364
364
  /tmp/aws/install
365
365
  rm -rf /tmp/aws /tmp/awscliv2.zip
366
366
  fi
367
- `,A.length>0)C+=`
367
+ `,C.length>0)T+=`
368
368
  # Install extra packages
369
- apt-get install -y ${A.join(" ")}
370
- `;return C+=`
369
+ apt-get install -y ${C.join(" ")}
370
+ `;return T+=`
371
371
  # Create API server directory
372
372
  mkdir -p /var/www/api
373
373
 
@@ -391,9 +391,9 @@ SERVICEFILE
391
391
 
392
392
  systemctl daemon-reload
393
393
  systemctl enable stacks-api
394
- `,C+=`
394
+ `,T+=`
395
395
  echo "Server setup complete!"
396
- `,C},generateBunAppScript:(a)=>{let{runtime:n="bun",runtimeVersion:i="latest",systemPackages:s=[],database:c,caddyfile:l}=a,u=new Set(s);if(c==="sqlite")u.add("sqlite");else if(c==="mysql")u.add("mysql");else if(c==="postgres")u.add("postgresql15");let h=`#!/bin/bash
396
+ `,T},generateBunAppScript:(a)=>{let{runtime:n="bun",runtimeVersion:i="latest",systemPackages:s=[],database:c,caddyfile:l}=a,u=new Set(s);if(c==="sqlite")u.add("sqlite");else if(c==="mysql")u.add("mysql");else if(c==="postgres")u.add("postgresql15");let h=`#!/bin/bash
397
397
  set -euo pipefail
398
398
 
399
399
  # Amazon Linux 2023 base setup
@@ -604,7 +604,7 @@ ufw default allow outgoing
604
604
  ${a.map((n)=>`ufw allow ${n}`).join(`
605
605
  `)}
606
606
  ufw --force enable
607
- `},Presets:{bunWithNginx:(a,n=3000)=>o.UserData.generateAppServerScript({runtime:"bun",webServer:"nginx",processManager:"systemd",domain:a,appPort:n,enableSsl:!0}),bunWithCaddy:(a,n=3000)=>o.UserData.generateAppServerScript({runtime:"bun",webServer:"caddy",processManager:"systemd",domain:a,appPort:n,enableSsl:!1}),nodeWithPm2:(a,n=3000)=>o.UserData.generateAppServerScript({runtime:"node",webServer:"nginx",processManager:"pm2",domain:a,appPort:n,enableSsl:!0}),worker:(a="bun")=>o.UserData.generateAppServerScript({runtime:a,webServer:"none",processManager:"systemd",enableSsl:!1})}};static createElasticIp(a){let{slug:n,environment:i,domain:s,instanceLogicalId:c}=a,l=r({slug:n,environment:i,resourceType:"eip"}),u=t(l),h={Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:i},...s?[{Key:"Domain",Value:s}]:[]]}},y={[u]:h},S,b;if(c)b=t(`${l}-assoc`),S={Type:"AWS::EC2::EIPAssociation",Properties:{AllocationId:N.GetAtt(u,"AllocationId"),InstanceId:N.Ref(c)}},y[b]=S;return{eip:h,eipAssociation:S,eipLogicalId:u,associationLogicalId:b,resources:y}}static createServerModeStack(a){let{slug:n,environment:i,vpcId:s,subnetId:c,instanceType:l="t3.small",imageId:u="ami-0f3caa1cf4417e51b",keyName:h,domain:y,userData:S,allowedPorts:b=[22,80,443],volumeSize:A=20,volumeType:C="gp3"}=a,T={},v=r({slug:n,environment:i,resourceType:"server-sg"}),w=t(v),R={Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:v,GroupDescription:`Security group for ${n} server`,VpcId:s,SecurityGroupIngress:b.map((ie)=>({IpProtocol:"tcp",FromPort:ie,ToPort:ie,CidrIp:"0.0.0.0/0",Description:`Port ${ie}`})),SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound"}],Tags:[{Key:"Name",Value:v},{Key:"Environment",Value:i}]}};T[w]=R;let k=r({slug:n,environment:i,resourceType:"server-role"}),W=t(k),P={Type:"AWS::IAM::Role",Properties:{RoleName:k,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ec2.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore","arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"],Policies:[{PolicyName:"StacksServerPermissions",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail","ses:SendBulkEmail","ses:VerifyDomainIdentity","ses:VerifyDomainDkim","ses:GetIdentityDkimAttributes","ses:GetIdentityVerificationAttributes"],Resource:"*"},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:ListBucket"],Resource:"*"},{Effect:"Allow",Action:["route53:ChangeResourceRecordSets","route53:ListResourceRecordSets","route53:GetHostedZone"],Resource:"*"},{Effect:"Allow",Action:["ssm:GetParameter","ssm:GetParameters"],Resource:"*"}]}}]}};T[W]=P;let V=r({slug:n,environment:i,resourceType:"server-profile"}),B=t(V),j={Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:V,Roles:[N.Ref(W)]}};T[B]=j;let J=r({slug:n,environment:i,resourceType:"server"}),K=t(J),X={Type:"AWS::EC2::Instance",DependsOn:[B],Properties:{ImageId:u,InstanceType:l,KeyName:h,SubnetId:c,SecurityGroupIds:[N.Ref(w)],IamInstanceProfile:N.Ref(B),BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:A,VolumeType:C,Encrypted:!0,DeleteOnTermination:!0}}],Tags:[{Key:"Name",Value:J},{Key:"Environment",Value:i},...y?[{Key:"Domain",Value:y}]:[]]}};if(S)X.Properties.UserData=N.Base64(S);T[K]=X;let{eip:te,eipAssociation:ne,eipLogicalId:me,associationLogicalId:oe,resources:ue}=o.createElasticIp({slug:n,environment:i,domain:y,instanceLogicalId:K});return Object.assign(T,ue),{instance:X,securityGroup:R,eip:te,eipAssociation:ne,instanceRole:P,instanceProfile:j,resources:T,outputs:{instanceLogicalId:K,securityGroupLogicalId:w,eipLogicalId:me,associationLogicalId:oe,roleLogicalId:W,profileLogicalId:B}}}static ServerMode={webServer:(a)=>{let n=o.UserData.generateAppServerScript({runtime:a.runtime||"bun",webServer:a.webServer||"nginx",domain:a.domain,enableSsl:!0});return o.createServerModeStack({...a,userData:n,instanceType:"t3.small",allowedPorts:[22,80,443]})},workerServer:(a)=>{let n=o.UserData.generateAppServerScript({runtime:a.runtime||"bun",webServer:"none",installRedis:a.installRedis});return o.createServerModeStack({...a,userData:n,instanceType:"t3.medium",allowedPorts:[22]})},cacheServer:(a)=>o.createServerModeStack({...a,userData:`#!/bin/bash
607
+ `},Presets:{bunWithNginx:(a,n=3000)=>o.UserData.generateAppServerScript({runtime:"bun",webServer:"nginx",processManager:"systemd",domain:a,appPort:n,enableSsl:!0}),bunWithCaddy:(a,n=3000)=>o.UserData.generateAppServerScript({runtime:"bun",webServer:"caddy",processManager:"systemd",domain:a,appPort:n,enableSsl:!1}),nodeWithPm2:(a,n=3000)=>o.UserData.generateAppServerScript({runtime:"node",webServer:"nginx",processManager:"pm2",domain:a,appPort:n,enableSsl:!0}),worker:(a="bun")=>o.UserData.generateAppServerScript({runtime:a,webServer:"none",processManager:"systemd",enableSsl:!1})}};static createElasticIp(a){let{slug:n,environment:i,domain:s,instanceLogicalId:c}=a,l=r({slug:n,environment:i,resourceType:"eip"}),u=t(l),h={Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:i},...s?[{Key:"Domain",Value:s}]:[]]}},y={[u]:h},S,A;if(c)A=t(`${l}-assoc`),S={Type:"AWS::EC2::EIPAssociation",Properties:{AllocationId:N.GetAtt(u,"AllocationId"),InstanceId:N.Ref(c)}},y[A]=S;return{eip:h,eipAssociation:S,eipLogicalId:u,associationLogicalId:A,resources:y}}static createServerModeStack(a){let{slug:n,environment:i,vpcId:s,subnetId:c,instanceType:l="t3.small",imageId:u="ami-0f3caa1cf4417e51b",keyName:h,domain:y,userData:S,allowedPorts:A=[22,80,443],volumeSize:C=20,volumeType:T="gp3"}=a,v={},w=r({slug:n,environment:i,resourceType:"server-sg"}),E=t(w),R={Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:w,GroupDescription:`Security group for ${n} server`,VpcId:s,SecurityGroupIngress:A.map((ie)=>({IpProtocol:"tcp",FromPort:ie,ToPort:ie,CidrIp:"0.0.0.0/0",Description:`Port ${ie}`})),SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound"}],Tags:[{Key:"Name",Value:w},{Key:"Environment",Value:i}]}};v[E]=R;let k=r({slug:n,environment:i,resourceType:"server-role"}),W=t(k),P={Type:"AWS::IAM::Role",Properties:{RoleName:k,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ec2.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore","arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"],Policies:[{PolicyName:"StacksServerPermissions",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail","ses:SendBulkEmail","ses:VerifyDomainIdentity","ses:VerifyDomainDkim","ses:GetIdentityDkimAttributes","ses:GetIdentityVerificationAttributes"],Resource:"*"},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:ListBucket"],Resource:"*"},{Effect:"Allow",Action:["route53:ChangeResourceRecordSets","route53:ListResourceRecordSets","route53:GetHostedZone"],Resource:"*"},{Effect:"Allow",Action:["ssm:GetParameter","ssm:GetParameters"],Resource:"*"}]}}]}};v[W]=P;let V=r({slug:n,environment:i,resourceType:"server-profile"}),B=t(V),j={Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:V,Roles:[N.Ref(W)]}};v[B]=j;let J=r({slug:n,environment:i,resourceType:"server"}),K=t(J),X={Type:"AWS::EC2::Instance",DependsOn:[B],Properties:{ImageId:u,InstanceType:l,KeyName:h,SubnetId:c,SecurityGroupIds:[N.Ref(E)],IamInstanceProfile:N.Ref(B),BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:C,VolumeType:T,Encrypted:!0,DeleteOnTermination:!0}}],Tags:[{Key:"Name",Value:J},{Key:"Environment",Value:i},...y?[{Key:"Domain",Value:y}]:[]]}};if(S)X.Properties.UserData=N.Base64(S);v[K]=X;let{eip:te,eipAssociation:ne,eipLogicalId:me,associationLogicalId:oe,resources:ue}=o.createElasticIp({slug:n,environment:i,domain:y,instanceLogicalId:K});return Object.assign(v,ue),{instance:X,securityGroup:R,eip:te,eipAssociation:ne,instanceRole:P,instanceProfile:j,resources:v,outputs:{instanceLogicalId:K,securityGroupLogicalId:E,eipLogicalId:me,associationLogicalId:oe,roleLogicalId:W,profileLogicalId:B}}}static ServerMode={webServer:(a)=>{let n=o.UserData.generateAppServerScript({runtime:a.runtime||"bun",webServer:a.webServer||"nginx",domain:a.domain,enableSsl:!0});return o.createServerModeStack({...a,userData:n,instanceType:"t3.small",allowedPorts:[22,80,443]})},workerServer:(a)=>{let n=o.UserData.generateAppServerScript({runtime:a.runtime||"bun",webServer:"none",installRedis:a.installRedis});return o.createServerModeStack({...a,userData:n,instanceType:"t3.medium",allowedPorts:[22]})},cacheServer:(a)=>o.createServerModeStack({...a,userData:`#!/bin/bash
608
608
  set -e
609
609
  apt-get update && apt-get upgrade -y
610
610
  apt-get install -y redis-server
@@ -612,7 +612,7 @@ sed -i 's/bind 127.0.0.1/bind 0.0.0.0/' /etc/redis/redis.conf
612
612
  systemctl enable redis-server
613
613
  systemctl restart redis-server
614
614
  echo "Redis server setup complete!"
615
- `,instanceType:"t3.medium",allowedPorts:[22,6379]})}}class f{static createVpc(a){let{slug:n,environment:i,cidr:s="10.0.0.0/16",enableDnsHostnames:c=!0,enableDnsSupport:l=!0}=a,u=r({slug:n,environment:i,resourceType:"vpc"}),h=t(u);return{vpc:{Type:"AWS::EC2::VPC",Properties:{CidrBlock:s,EnableDnsHostnames:c,EnableDnsSupport:l,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:i}]}},logicalId:h}}static createSubnet(a){let{slug:n,environment:i,vpcId:s,type:c,cidr:l,availabilityZone:u,mapPublicIp:h=c==="public"}=a,y=r({slug:n,environment:i,resourceType:`subnet-${c}`}),S=t(`${y}-${u}`);return{subnet:{Type:"AWS::EC2::Subnet",Properties:{VpcId:s,CidrBlock:l,AvailabilityZone:u,MapPublicIpOnLaunch:h,Tags:[{Key:"Name",Value:`${y}-${u}`},{Key:"Environment",Value:i},{Key:"Type",Value:c}]}},logicalId:S}}static createInternetGateway(a,n){let i=r({slug:a,environment:n,resourceType:"igw"}),s=t(i);return{internetGateway:{Type:"AWS::EC2::InternetGateway",Properties:{Tags:[{Key:"Name",Value:i},{Key:"Environment",Value:n}]}},logicalId:s}}static attachInternetGateway(a,n){let i=t(`${a}-igw-attachment`);return{attachment:{Type:"AWS::EC2::VPCGatewayAttachment",Properties:{VpcId:N.Ref(a),InternetGatewayId:N.Ref(n)}},logicalId:i}}static createEip(a,n){let i=r({slug:a,environment:n,resourceType:"eip"}),s=t(i);return{eip:{Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:i},{Key:"Environment",Value:n}]}},logicalId:s}}static createNatGateway(a,n){let{slug:i,environment:s,subnetId:c}=a,l=r({slug:i,environment:s,resourceType:"nat"}),u=t(l);return{natGateway:{Type:"AWS::EC2::NatGateway",Properties:{AllocationId:N.GetAtt(n,"AllocationId"),SubnetId:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s},{Key:"Warning",Value:"NAT Gateway incurs hourly charges"}]}},logicalId:u}}static createRouteTable(a,n,i,s){let c=r({slug:a,environment:n,resourceType:`rt-${s}`}),l=t(c);return{routeTable:{Type:"AWS::EC2::RouteTable",Properties:{VpcId:N.Ref(i),Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:n},{Key:"Type",Value:s}]}},logicalId:l}}static createRoute(a,n,i){let s=t(`${a}-route-${i.type}`),c={Type:"AWS::EC2::Route",Properties:{RouteTableId:N.Ref(a),DestinationCidrBlock:n}};if(i.type==="igw")c.Properties.GatewayId=N.Ref(i.logicalId);else if(i.type==="nat")c.Properties.NatGatewayId=N.Ref(i.logicalId);else if(i.type==="instance")c.Properties.InstanceId=N.Ref(i.logicalId);return{route:c,logicalId:s}}static associateSubnetWithRouteTable(a,n){let i=t(`${a}-rt-assoc`);return{association:{Type:"AWS::EC2::SubnetRouteTableAssociation",Properties:{SubnetId:N.Ref(a),RouteTableId:N.Ref(n)}},logicalId:i}}static enableFlowLogs(a){let{slug:n,environment:i,resourceId:s,resourceType:c,trafficType:l="ALL",logGroupName:u}=a,h=r({slug:n,environment:i,resourceType:"flowlog"}),y=t(h);return{flowLog:{Type:"AWS::EC2::FlowLog",Properties:{ResourceType:c,ResourceIds:[s],TrafficType:l,LogDestinationType:"cloud-watch-logs",LogGroupName:u||`/aws/vpc/${n}-${i}`,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:i}]}},logicalId:y}}static calculateSubnetCidrs(a,n,i=3){let[s,c]=a.split("/"),l=Number.parseInt(c,10),u=Math.ceil(Math.log2(n*i)),h=l+u;if(h>28)throw Error("VPC CIDR is too small to accommodate requested subnets");let[y,S,b,A]=s.split(".").map(Number),C=(y<<24)+(S<<16)+(b<<8)+A,T=2**(32-h),v=[];for(let w=0;w<n*i;w++){let R=C+w*T,k=[R>>>24&255,R>>>16&255,R>>>8&255,R&255].join(".");v.push(`${k}/${h}`)}return v}static getAvailabilityZones(a,n){return["a","b","c","d","e","f"].slice(0,n).map((i)=>`${a}${i}`)}static createMultiAzNetwork(a){let{slug:n,environment:i,region:s,cidr:c="10.0.0.0/16",zones:l=3,enableNatGateway:u=!1,singleNatGateway:h=!1,enableFlowLogs:y=!1}=a,S={},b=[],A=[],C=[],{vpc:T,logicalId:v}=f.createVpc({slug:n,environment:i,cidr:c});S[v]=T;let{internetGateway:w,logicalId:R}=f.createInternetGateway(n,i);S[R]=w;let{attachment:k,logicalId:W}=f.attachInternetGateway(v,R);S[W]=k;let{routeTable:P,logicalId:V}=f.createRouteTable(n,i,v,"public");S[V]=P;let{route:B,logicalId:j}=f.createRoute(V,"0.0.0.0/0",{type:"igw",logicalId:R});B.DependsOn=W,S[j]=B;let J=f.calculateSubnetCidrs(c,l,2),K=f.getAvailabilityZones(s,l),X=[];for(let te=0;te<l;te++){let ne=K[te],me=J[te*2],oe=J[te*2+1],{subnet:ue,logicalId:ie}=f.createSubnet({slug:n,environment:i,vpcId:N.Ref(v),type:"public",cidr:me,availabilityZone:ne});S[ie]=ue,b.push(ie);let{association:Ie,logicalId:_e}=f.associateSubnetWithRouteTable(ie,V);S[_e]=Ie;let{subnet:Ct,logicalId:pe}=f.createSubnet({slug:n,environment:i,vpcId:N.Ref(v),type:"private",cidr:oe,availabilityZone:ne});if(S[pe]=Ct,A.push(pe),u&&(!h||te===0)){let{eip:de,logicalId:ge}=f.createEip(`${n}-${ne}`,i);S[ge]=de;let{natGateway:Re,logicalId:he}=f.createNatGateway({slug:`${n}-${ne}`,environment:i,subnetId:N.Ref(ie)},ge);Re.DependsOn=W,S[he]=Re,C.push(he);let{routeTable:Se,logicalId:$e}=f.createRouteTable(`${n}-${ne}`,i,v,"private");S[$e]=Se,X.push($e);let{route:We,logicalId:z}=f.createRoute($e,"0.0.0.0/0",{type:"nat",logicalId:he});S[z]=We;let{association:re,logicalId:ae}=f.associateSubnetWithRouteTable(pe,$e);S[ae]=re}else if(u&&h&&te>0){let{association:de,logicalId:ge}=f.associateSubnetWithRouteTable(pe,X[0]);S[ge]=de}else{let{routeTable:de,logicalId:ge}=f.createRouteTable(`${n}-${ne}-isolated`,i,v,"private");S[ge]=de;let{association:Re,logicalId:he}=f.associateSubnetWithRouteTable(pe,ge);S[he]=Re}}if(y){let{flowLog:te,logicalId:ne}=f.enableFlowLogs({slug:n,environment:i,resourceId:N.Ref(v),resourceType:"VPC"});S[ne]=te}return{resources:S,outputs:{vpcId:v,publicSubnetIds:b,privateSubnetIds:A,natGatewayIds:C.length>0?C:void 0}}}static NatGatewayCostWarning=`
615
+ `,instanceType:"t3.medium",allowedPorts:[22,6379]})}}class f{static createVpc(a){let{slug:n,environment:i,cidr:s="10.0.0.0/16",enableDnsHostnames:c=!0,enableDnsSupport:l=!0}=a,u=r({slug:n,environment:i,resourceType:"vpc"}),h=t(u);return{vpc:{Type:"AWS::EC2::VPC",Properties:{CidrBlock:s,EnableDnsHostnames:c,EnableDnsSupport:l,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:i}]}},logicalId:h}}static createSubnet(a){let{slug:n,environment:i,vpcId:s,type:c,cidr:l,availabilityZone:u,mapPublicIp:h=c==="public"}=a,y=r({slug:n,environment:i,resourceType:`subnet-${c}`}),S=t(`${y}-${u}`);return{subnet:{Type:"AWS::EC2::Subnet",Properties:{VpcId:s,CidrBlock:l,AvailabilityZone:u,MapPublicIpOnLaunch:h,Tags:[{Key:"Name",Value:`${y}-${u}`},{Key:"Environment",Value:i},{Key:"Type",Value:c}]}},logicalId:S}}static createInternetGateway(a,n){let i=r({slug:a,environment:n,resourceType:"igw"}),s=t(i);return{internetGateway:{Type:"AWS::EC2::InternetGateway",Properties:{Tags:[{Key:"Name",Value:i},{Key:"Environment",Value:n}]}},logicalId:s}}static attachInternetGateway(a,n){let i=t(`${a}-igw-attachment`);return{attachment:{Type:"AWS::EC2::VPCGatewayAttachment",Properties:{VpcId:N.Ref(a),InternetGatewayId:N.Ref(n)}},logicalId:i}}static createEip(a,n){let i=r({slug:a,environment:n,resourceType:"eip"}),s=t(i);return{eip:{Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:i},{Key:"Environment",Value:n}]}},logicalId:s}}static createNatGateway(a,n){let{slug:i,environment:s,subnetId:c}=a,l=r({slug:i,environment:s,resourceType:"nat"}),u=t(l);return{natGateway:{Type:"AWS::EC2::NatGateway",Properties:{AllocationId:N.GetAtt(n,"AllocationId"),SubnetId:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s},{Key:"Warning",Value:"NAT Gateway incurs hourly charges"}]}},logicalId:u}}static createRouteTable(a,n,i,s){let c=r({slug:a,environment:n,resourceType:`rt-${s}`}),l=t(c);return{routeTable:{Type:"AWS::EC2::RouteTable",Properties:{VpcId:N.Ref(i),Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:n},{Key:"Type",Value:s}]}},logicalId:l}}static createRoute(a,n,i){let s=t(`${a}-route-${i.type}`),c={Type:"AWS::EC2::Route",Properties:{RouteTableId:N.Ref(a),DestinationCidrBlock:n}};if(i.type==="igw")c.Properties.GatewayId=N.Ref(i.logicalId);else if(i.type==="nat")c.Properties.NatGatewayId=N.Ref(i.logicalId);else if(i.type==="instance")c.Properties.InstanceId=N.Ref(i.logicalId);return{route:c,logicalId:s}}static associateSubnetWithRouteTable(a,n){let i=t(`${a}-rt-assoc`);return{association:{Type:"AWS::EC2::SubnetRouteTableAssociation",Properties:{SubnetId:N.Ref(a),RouteTableId:N.Ref(n)}},logicalId:i}}static enableFlowLogs(a){let{slug:n,environment:i,resourceId:s,resourceType:c,trafficType:l="ALL",logGroupName:u}=a,h=r({slug:n,environment:i,resourceType:"flowlog"}),y=t(h);return{flowLog:{Type:"AWS::EC2::FlowLog",Properties:{ResourceType:c,ResourceIds:[s],TrafficType:l,LogDestinationType:"cloud-watch-logs",LogGroupName:u||`/aws/vpc/${n}-${i}`,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:i}]}},logicalId:y}}static calculateSubnetCidrs(a,n,i=3){let[s,c]=a.split("/"),l=Number.parseInt(c,10),u=Math.ceil(Math.log2(n*i)),h=l+u;if(h>28)throw Error("VPC CIDR is too small to accommodate requested subnets");let[y,S,A,C]=s.split(".").map(Number),T=(y<<24)+(S<<16)+(A<<8)+C,v=2**(32-h),w=[];for(let E=0;E<n*i;E++){let R=T+E*v,k=[R>>>24&255,R>>>16&255,R>>>8&255,R&255].join(".");w.push(`${k}/${h}`)}return w}static getAvailabilityZones(a,n){return["a","b","c","d","e","f"].slice(0,n).map((i)=>`${a}${i}`)}static createMultiAzNetwork(a){let{slug:n,environment:i,region:s,cidr:c="10.0.0.0/16",zones:l=3,enableNatGateway:u=!1,singleNatGateway:h=!1,enableFlowLogs:y=!1}=a,S={},A=[],C=[],T=[],{vpc:v,logicalId:w}=f.createVpc({slug:n,environment:i,cidr:c});S[w]=v;let{internetGateway:E,logicalId:R}=f.createInternetGateway(n,i);S[R]=E;let{attachment:k,logicalId:W}=f.attachInternetGateway(w,R);S[W]=k;let{routeTable:P,logicalId:V}=f.createRouteTable(n,i,w,"public");S[V]=P;let{route:B,logicalId:j}=f.createRoute(V,"0.0.0.0/0",{type:"igw",logicalId:R});B.DependsOn=W,S[j]=B;let J=f.calculateSubnetCidrs(c,l,2),K=f.getAvailabilityZones(s,l),X=[];for(let te=0;te<l;te++){let ne=K[te],me=J[te*2],oe=J[te*2+1],{subnet:ue,logicalId:ie}=f.createSubnet({slug:n,environment:i,vpcId:N.Ref(w),type:"public",cidr:me,availabilityZone:ne});S[ie]=ue,A.push(ie);let{association:Ie,logicalId:_e}=f.associateSubnetWithRouteTable(ie,V);S[_e]=Ie;let{subnet:Ct,logicalId:pe}=f.createSubnet({slug:n,environment:i,vpcId:N.Ref(w),type:"private",cidr:oe,availabilityZone:ne});if(S[pe]=Ct,C.push(pe),u&&(!h||te===0)){let{eip:de,logicalId:ge}=f.createEip(`${n}-${ne}`,i);S[ge]=de;let{natGateway:Re,logicalId:he}=f.createNatGateway({slug:`${n}-${ne}`,environment:i,subnetId:N.Ref(ie)},ge);Re.DependsOn=W,S[he]=Re,T.push(he);let{routeTable:Se,logicalId:$e}=f.createRouteTable(`${n}-${ne}`,i,w,"private");S[$e]=Se,X.push($e);let{route:We,logicalId:z}=f.createRoute($e,"0.0.0.0/0",{type:"nat",logicalId:he});S[z]=We;let{association:re,logicalId:ae}=f.associateSubnetWithRouteTable(pe,$e);S[ae]=re}else if(u&&h&&te>0){let{association:de,logicalId:ge}=f.associateSubnetWithRouteTable(pe,X[0]);S[ge]=de}else{let{routeTable:de,logicalId:ge}=f.createRouteTable(`${n}-${ne}-isolated`,i,w,"private");S[ge]=de;let{association:Re,logicalId:he}=f.associateSubnetWithRouteTable(pe,ge);S[he]=Re}}if(y){let{flowLog:te,logicalId:ne}=f.enableFlowLogs({slug:n,environment:i,resourceId:N.Ref(w),resourceType:"VPC"});S[ne]=te}return{resources:S,outputs:{vpcId:w,publicSubnetIds:A,privateSubnetIds:C,natGatewayIds:T.length>0?T:void 0}}}static NatGatewayCostWarning=`
616
616
  ⚠️ NAT Gateway Cost Warning:
617
617
  - Each NAT Gateway costs approximately $32-45/month (hourly charges)
618
618
  - Data processing charges: $0.045/GB processed
@@ -620,7 +620,7 @@ echo "Redis server setup complete!"
620
620
  - Using a single NAT Gateway (singleNatGateway: true)
621
621
  - Using NAT Instances instead (cheaper but requires management)
622
622
  - Disabling NAT entirely for isolated private subnets
623
- `}class Ge{static createFileSystem(a){let{slug:n,environment:i,encrypted:s=!0,kmsKeyId:c,performanceMode:l="generalPurpose",throughputMode:u="bursting",provisionedThroughput:h,enableBackup:y=!0}=a,S=r({slug:n,environment:i,resourceType:"efs"}),b=t(S),A={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:s,PerformanceMode:l,ThroughputMode:u,FileSystemTags:[{Key:"Name",Value:S},{Key:"Environment",Value:i}]}};if(c)A.Properties.KmsKeyId=c;if(u==="provisioned"&&h)A.Properties.ProvisionedThroughputInMibps=h;if(y)A.Properties.BackupPolicy={Status:"ENABLED"};return{fileSystem:A,logicalId:b}}static createMountTarget(a,n){let{slug:i,environment:s,subnetId:c,securityGroups:l,ipAddress:u}=n,h=r({slug:i,environment:s,resourceType:"efs-mt"}),y=t(`${h}-${c}`),S={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:N.Ref(a),SubnetId:c,SecurityGroups:l}};if(u)S.Properties.IpAddress=u;return{mountTarget:S,logicalId:y}}static createAccessPoint(a,n){let{slug:i,environment:s,path:c="/",uid:l="1000",gid:u="1000",permissions:h="755"}=n,y=r({slug:i,environment:s,resourceType:"efs-ap"}),S=t(`${y}-${c.replace(/\//g,"-")}`);return{accessPoint:{Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:N.Ref(a),PosixUser:{Uid:l,Gid:u},RootDirectory:{Path:c,CreationInfo:{OwnerUid:l,OwnerGid:u,Permissions:h}},AccessPointTags:[{Key:"Name",Value:`${y}-${c}`},{Key:"Environment",Value:s}]}},logicalId:S}}static setLifecyclePolicy(a,n){let{transitionToIA:i,transitionToPrimary:s=!1}=n;if(!a.Properties)a.Properties={};if(a.Properties.LifecyclePolicies=[],i){let c=`AFTER_${i}_DAYS`;a.Properties.LifecyclePolicies.push({TransitionToIA:c})}if(s)a.Properties.LifecyclePolicies.push({TransitionToPrimaryStorageClass:"AFTER_1_ACCESS"});return a}static enableBackup(a){if(!a.Properties)a.Properties={};return a.Properties.BackupPolicy={Status:"ENABLED"},a}static disableBackup(a){if(!a.Properties)a.Properties={};return a.Properties.BackupPolicy={Status:"DISABLED"},a}static setProvisionedThroughput(a,n){if(!a.Properties)a.Properties={};return a.Properties.ThroughputMode="provisioned",a.Properties.ProvisionedThroughputInMibps=n,a}static setElasticThroughput(a){if(!a.Properties)a.Properties={};return a.Properties.ThroughputMode="elastic",a}static enableMaxIO(a){if(!a.Properties)a.Properties={};return a.Properties.PerformanceMode="maxIO",a}static createEfsSecurityGroup(a){let{slug:n,environment:i,vpcId:s,sourceSecurityGroupIds:c=[],sourceCidrBlocks:l=[],description:u}=a,h=r({slug:n,environment:i,resourceType:"efs-sg"}),y=t(h),S=[];for(let b of c)S.push({IpProtocol:"tcp",FromPort:2049,ToPort:2049,SourceSecurityGroupId:b,Description:"NFS from security group"});for(let b of l)S.push({IpProtocol:"tcp",FromPort:2049,ToPort:2049,CidrIp:b,Description:"NFS from CIDR block"});return{securityGroup:{Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:h,GroupDescription:u||`Security group for EFS mount targets - ${n} ${i}`,VpcId:s,SecurityGroupIngress:S,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:i}]}},logicalId:y}}static createMultiAzMountTargets(a,n){let{slug:i,environment:s,subnetIds:c,securityGroupId:l}=n,u=[],h=[];for(let y=0;y<c.length;y++){let S=c[y],b=r({slug:i,environment:s,resourceType:"efs-mt"}),A=t(`${b}-az${y+1}`),C={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:N.Ref(a),SubnetId:S,SecurityGroups:[l]}};u.push(C),h.push(A)}return{mountTargets:u,logicalIds:h}}static createCompleteFileSystem(a){let{slug:n,environment:i,vpcId:s,subnetIds:c,sourceSecurityGroupIds:l=[],encrypted:u=!0,performanceMode:h="generalPurpose",throughputMode:y="elastic",enableBackup:S=!0,transitionToIA:b}=a,A={},{fileSystem:C,logicalId:T}=Ge.createFileSystem({slug:n,environment:i,encrypted:u,performanceMode:h,throughputMode:y,enableBackup:S});if(b)Ge.setLifecyclePolicy(C,{transitionToIA:b,transitionToPrimary:!0});A[T]=C;let{securityGroup:v,logicalId:w}=Ge.createEfsSecurityGroup({slug:n,environment:i,vpcId:s,sourceSecurityGroupIds:l});A[w]=v;let{mountTargets:R,logicalIds:k}=Ge.createMultiAzMountTargets(T,{slug:n,environment:i,subnetIds:c,securityGroupId:N.Ref(w)});for(let W=0;W<R.length;W++)A[k[W]]=R[W];return{resources:A,outputs:{fileSystemId:T,securityGroupId:w,mountTargetIds:k}}}}class m{static verifyDomain(a){let{domain:n,slug:i,environment:s,enableDkim:c=!0,dkimKeyLength:l="RSA_2048_BIT"}=a,u=r({slug:i,environment:s,resourceType:"ses-identity"}),h=t(`${u}-${n.replace(/\./g,"")}`),y={Type:"AWS::SES::EmailIdentity",Properties:{EmailIdentity:n,FeedbackAttributes:{EmailForwardingEnabled:!0}}};if(c)y.Properties.DkimSigningAttributes={NextSigningKeyLength:l};return{emailIdentity:y,logicalId:h}}static createDkimRecords(a,n,i){let s=[];for(let c=0;c<n.length;c++){let l=n[c],u=t(`dkim-${a.replace(/\./g,"")}-${c+1}`),h={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:`${l}._domainkey.${a}`,Type:"CNAME",TTL:1800,ResourceRecords:[`${l}.dkim.amazonses.com`]}};s.push({record:h,logicalId:u})}return s}static createConfigurationSet(a){let{slug:n,environment:i,name:s,reputationMetrics:c=!0,sendingEnabled:l=!0,suppressBounces:u=!0,suppressComplaints:h=!0}=a,y=s||r({slug:n,environment:i,resourceType:"ses-config"}),S=t(y),b=[];if(u)b.push("BOUNCE");if(h)b.push("COMPLAINT");return{configurationSet:{Type:"AWS::SES::ConfigurationSet",Properties:{Name:y,ReputationOptions:{ReputationMetricsEnabled:c},SendingOptions:{SendingEnabled:l},SuppressionOptions:{SuppressedReasons:b}}},logicalId:S}}static createReceiptRuleSet(a){let{slug:n,environment:i,name:s}=a,c=s||r({slug:n,environment:i,resourceType:"ses-ruleset"}),l=t(c);return{ruleSet:{Type:"AWS::SES::ReceiptRuleSet",Properties:{RuleSetName:c}},logicalId:l}}static createReceiptRule(a,n){let{slug:i,environment:s,ruleSetName:c,recipients:l,enabled:u=!0,scanEnabled:h=!0,tlsPolicy:y="Require",s3Action:S,lambdaAction:b,snsAction:A}=n,C=r({slug:i,environment:s,resourceType:"ses-rule"}),T=t(C),v=[];if(S)v.push({S3Action:{BucketName:S.bucketName,ObjectKeyPrefix:S.prefix,KmsKeyArn:S.kmsKeyArn}});if(b)v.push({LambdaAction:{FunctionArn:b.functionArn,InvocationType:b.invocationType||"Event"}});if(A)v.push({SNSAction:{TopicArn:A.topicArn,Encoding:A.encoding||"UTF-8"}});return{receiptRule:{Type:"AWS::SES::ReceiptRule",Properties:{RuleSetName:c,Rule:{Name:C,Enabled:u,ScanEnabled:h,TlsPolicy:y,Recipients:l,Actions:v.length>0?v:void 0}}},logicalId:T}}static createMxRecord(a,n,i){let s=t(`mx-${a.replace(/\./g,"")}`);return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n,Name:a,Type:"MX",TTL:300,ResourceRecords:[`10 inbound-smtp.${i}.amazonaws.com`]}},logicalId:s}}static createVerificationRecord(a,n,i){let s=t(`verification-${a.replace(/\./g,"")}`);return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:`_amazonses.${a}`,Type:"TXT",TTL:1800,ResourceRecords:[`"${n}"`]}},logicalId:s}}static getSmtpEndpoint(a){return`email-smtp.${a}.amazonaws.com`}static SmtpPorts={TLS:587,SSL:465,Unencrypted:25};static createSpfRecord(a,n,i){let{includeDomains:s=[],softFail:c=!1}=i||{},l=t(`spf-${a.replace(/\./g,"")}`),u="v=spf1 include:amazonses.com";for(let h of s)u+=` include:${h}`;return u+=c?" ~all":" -all",{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n,Name:a,Type:"TXT",TTL:300,ResourceRecords:[`"${u}"`]}},logicalId:l}}static createDmarcRecord(a,n,i){let{policy:s="none",subdomainPolicy:c,percentage:l=100,reportingEmail:u,forensicEmail:h}=i||{},y=t(`dmarc-${a.replace(/\./g,"")}`),S=`v=DMARC1; p=${s}; pct=${l}`;if(c)S+=`; sp=${c}`;if(u)S+=`; rua=mailto:${u}`;if(h)S+=`; ruf=mailto:${h}`;return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n,Name:`_dmarc.${a}`,Type:"TXT",TTL:300,ResourceRecords:[`"${S}"`]}},logicalId:y}}static createInboundEmailSetup(a){let{slug:n,environment:i,domain:s,s3BucketName:c,s3KeyPrefix:l="inbound/",region:u,hostedZoneId:h,lambdaFunctionArn:y,snsTopicArn:S}=a,b={},{ruleSet:A,logicalId:C}=m.createReceiptRuleSet({slug:n,environment:i});b[C]=A;let{receiptRule:T,logicalId:v}=m.createReceiptRule(C,{slug:n,environment:i,ruleSetName:A.Properties.RuleSetName||`${n}-${i}-receipt-rule-set`,recipients:[s],s3Action:{bucketName:c,prefix:l},lambdaAction:y?{functionArn:y,invocationType:"Event"}:void 0,snsAction:S?{topicArn:S}:void 0});b[v]=T;let{record:w,logicalId:R}=m.createMxRecord(s,h,u);return b[R]=w,{resources:b,outputs:{ruleSetLogicalId:C,ruleLogicalId:v,mxRecordLogicalId:R}}}static createCompleteDomainSetup(a){let{slug:n,environment:i,domain:s,hostedZoneId:c,region:l,enableInbound:u=!1,inboundS3Bucket:h,dmarcReportingEmail:y}=a,S={},{emailIdentity:b,logicalId:A}=m.verifyDomain({domain:s,slug:n,environment:i});S[A]=b;let{configurationSet:C,logicalId:T}=m.createConfigurationSet({slug:n,environment:i});S[T]=C;let{record:v,logicalId:w}=m.createSpfRecord(s,c);S[w]=v;let{record:R,logicalId:k}=m.createDmarcRecord(s,c,{policy:"none",reportingEmail:y||`dmarc-reports@${s}`});if(S[k]=R,u&&h){let W=m.createInboundEmailSetup({slug:n,environment:i,domain:s,s3BucketName:h,region:l,hostedZoneId:c});Object.assign(S,W.resources)}return{resources:S,outputs:{identityLogicalId:A,configSetLogicalId:T}}}static InboundSmtpEndpoints={"us-east-1":"inbound-smtp.us-east-1.amazonaws.com","us-west-2":"inbound-smtp.us-west-2.amazonaws.com","eu-west-1":"inbound-smtp.eu-west-1.amazonaws.com"};static supportsInboundEmail(a){return a in m.InboundSmtpEndpoints}static createEmailLambdaRole(a){let{slug:n,environment:i,s3BucketArn:s,sesIdentityArn:c}=a,l=r({slug:n,environment:i,resourceType:"email-lambda-role"}),u=t(l),h=t(`${l}-policy`),y={Type:"AWS::IAM::Role",Properties:{RoleName:l,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:i}]}},S=[{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[s,`${s}/*`]}];if(c)S.push({Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail"],Resource:c});let b={Type:"AWS::IAM::Policy",Properties:{PolicyName:`${l}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:S},Roles:[N.Ref(u)]}};return{role:y,policy:b,roleLogicalId:u,policyLogicalId:h}}static createOutboundEmailLambda(a){let{slug:n,environment:i,roleArn:s,domain:c,configurationSetName:l,timeout:u=30,memorySize:h=256}=a,y=r({slug:n,environment:i,resourceType:"outbound-email"}),S=t(y);return{function:{Type:"AWS::Lambda::Function",Properties:{FunctionName:y,Runtime:"nodejs20.x",Handler:"index.handler",Role:s,Timeout:u,MemorySize:h,Environment:{Variables:{DOMAIN:c,CONFIGURATION_SET:l||""}},Code:{ZipFile:m.LambdaCode.outboundEmail},Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:i},{Key:"Purpose",Value:"OutboundEmail"}]}},logicalId:S}}static createInboundEmailLambda(a){let{slug:n,environment:i,roleArn:s,s3BucketName:c,organizedPrefix:l="organized/",timeout:u=60,memorySize:h=512}=a,y=r({slug:n,environment:i,resourceType:"inbound-email"}),S=t(y),b=t(`${y}-permission`),A={Type:"AWS::Lambda::Function",Properties:{FunctionName:y,Runtime:"nodejs20.x",Handler:"index.handler",Role:s,Timeout:u,MemorySize:h,Environment:{Variables:{S3_BUCKET:c,ORGANIZED_PREFIX:l}},Code:{ZipFile:m.LambdaCode.inboundEmail},Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:i},{Key:"Purpose",Value:"InboundEmail"}]}},C={Type:"AWS::Lambda::Permission",Properties:{FunctionName:N.Ref(S),Action:"lambda:InvokeFunction",Principal:"ses.amazonaws.com",SourceAccount:N.Ref("AWS::AccountId")}};return{function:A,permission:C,logicalId:S,permissionLogicalId:b}}static createEmailConversionLambda(a){let{slug:n,environment:i,roleArn:s,s3BucketName:c,convertedPrefix:l="converted/",timeout:u=60,memorySize:h=512}=a,y=r({slug:n,environment:i,resourceType:"email-conversion"}),S=t(y);return{function:{Type:"AWS::Lambda::Function",Properties:{FunctionName:y,Runtime:"nodejs20.x",Handler:"index.handler",Role:s,Timeout:u,MemorySize:h,Environment:{Variables:{S3_BUCKET:c,CONVERTED_PREFIX:l}},Code:{ZipFile:m.LambdaCode.emailConversion},Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:i},{Key:"Purpose",Value:"EmailConversion"}]}},logicalId:S}}static createEmailBucketNotification(a){let{lambdaArn:n,prefix:i="inbound/",suffix:s,events:c}=a,l=c??["s3:ObjectCreated:*"],u={};if(i||s){if(u.S3Key={Rules:[]},i)u.S3Key.Rules.push({Name:"prefix",Value:i});if(s)u.S3Key.Rules.push({Name:"suffix",Value:s})}return{notificationConfiguration:{LambdaConfigurations:[{Event:l[0],Function:n,Filter:Object.keys(u).length>0?u:void 0}]}}}static createS3LambdaPermission(a){let{slug:n,environment:i,lambdaLogicalId:s,s3BucketArn:c}=a,l=r({slug:n,environment:i,resourceType:"s3-lambda-permission"}),u=t(l);return{permission:{Type:"AWS::Lambda::Permission",Properties:{FunctionName:N.Ref(s),Action:"lambda:InvokeFunction",Principal:"s3.amazonaws.com",SourceArn:c}},logicalId:u}}static createEmailProcessingStack(a){let{slug:n,environment:i,domain:s,s3BucketName:c,s3BucketArn:l,configurationSetName:u,enableInbound:h=!0,enableConversion:y=!0}=a,S={},{role:b,policy:A,roleLogicalId:C,policyLogicalId:T}=m.createEmailLambdaRole({slug:n,environment:i,s3BucketArn:l,sesIdentityArn:`arn:aws:ses:*:*:identity/${s}`});S[C]=b,S[T]=A;let{function:v,logicalId:w}=m.createOutboundEmailLambda({slug:n,environment:i,roleArn:N.GetAtt(C,"Arn"),domain:s,configurationSetName:u});S[w]=v;let R={roleLogicalId:C,outboundLambdaLogicalId:w};if(h){let{function:k,permission:W,logicalId:P,permissionLogicalId:V}=m.createInboundEmailLambda({slug:n,environment:i,roleArn:N.GetAtt(C,"Arn"),s3BucketName:c});S[P]=k,S[V]=W;let{permission:B,logicalId:j}=m.createS3LambdaPermission({slug:n,environment:i,lambdaLogicalId:P,s3BucketArn:l});S[j]=B,R.inboundLambdaLogicalId=P}if(y){let{function:k,logicalId:W}=m.createEmailConversionLambda({slug:n,environment:i,roleArn:N.GetAtt(C,"Arn"),s3BucketName:c});S[W]=k,R.conversionLambdaLogicalId=W}return{resources:S,outputs:R}}static LambdaCode={outboundEmail:`
623
+ `}class Ge{static createFileSystem(a){let{slug:n,environment:i,encrypted:s=!0,kmsKeyId:c,performanceMode:l="generalPurpose",throughputMode:u="bursting",provisionedThroughput:h,enableBackup:y=!0}=a,S=r({slug:n,environment:i,resourceType:"efs"}),A=t(S),C={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:s,PerformanceMode:l,ThroughputMode:u,FileSystemTags:[{Key:"Name",Value:S},{Key:"Environment",Value:i}]}};if(c)C.Properties.KmsKeyId=c;if(u==="provisioned"&&h)C.Properties.ProvisionedThroughputInMibps=h;if(y)C.Properties.BackupPolicy={Status:"ENABLED"};return{fileSystem:C,logicalId:A}}static createMountTarget(a,n){let{slug:i,environment:s,subnetId:c,securityGroups:l,ipAddress:u}=n,h=r({slug:i,environment:s,resourceType:"efs-mt"}),y=t(`${h}-${c}`),S={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:N.Ref(a),SubnetId:c,SecurityGroups:l}};if(u)S.Properties.IpAddress=u;return{mountTarget:S,logicalId:y}}static createAccessPoint(a,n){let{slug:i,environment:s,path:c="/",uid:l="1000",gid:u="1000",permissions:h="755"}=n,y=r({slug:i,environment:s,resourceType:"efs-ap"}),S=t(`${y}-${c.replace(/\//g,"-")}`);return{accessPoint:{Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:N.Ref(a),PosixUser:{Uid:l,Gid:u},RootDirectory:{Path:c,CreationInfo:{OwnerUid:l,OwnerGid:u,Permissions:h}},AccessPointTags:[{Key:"Name",Value:`${y}-${c}`},{Key:"Environment",Value:s}]}},logicalId:S}}static setLifecyclePolicy(a,n){let{transitionToIA:i,transitionToPrimary:s=!1}=n;if(!a.Properties)a.Properties={};if(a.Properties.LifecyclePolicies=[],i){let c=`AFTER_${i}_DAYS`;a.Properties.LifecyclePolicies.push({TransitionToIA:c})}if(s)a.Properties.LifecyclePolicies.push({TransitionToPrimaryStorageClass:"AFTER_1_ACCESS"});return a}static enableBackup(a){if(!a.Properties)a.Properties={};return a.Properties.BackupPolicy={Status:"ENABLED"},a}static disableBackup(a){if(!a.Properties)a.Properties={};return a.Properties.BackupPolicy={Status:"DISABLED"},a}static setProvisionedThroughput(a,n){if(!a.Properties)a.Properties={};return a.Properties.ThroughputMode="provisioned",a.Properties.ProvisionedThroughputInMibps=n,a}static setElasticThroughput(a){if(!a.Properties)a.Properties={};return a.Properties.ThroughputMode="elastic",a}static enableMaxIO(a){if(!a.Properties)a.Properties={};return a.Properties.PerformanceMode="maxIO",a}static createEfsSecurityGroup(a){let{slug:n,environment:i,vpcId:s,sourceSecurityGroupIds:c=[],sourceCidrBlocks:l=[],description:u}=a,h=r({slug:n,environment:i,resourceType:"efs-sg"}),y=t(h),S=[];for(let A of c)S.push({IpProtocol:"tcp",FromPort:2049,ToPort:2049,SourceSecurityGroupId:A,Description:"NFS from security group"});for(let A of l)S.push({IpProtocol:"tcp",FromPort:2049,ToPort:2049,CidrIp:A,Description:"NFS from CIDR block"});return{securityGroup:{Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:h,GroupDescription:u||`Security group for EFS mount targets - ${n} ${i}`,VpcId:s,SecurityGroupIngress:S,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:i}]}},logicalId:y}}static createMultiAzMountTargets(a,n){let{slug:i,environment:s,subnetIds:c,securityGroupId:l}=n,u=[],h=[];for(let y=0;y<c.length;y++){let S=c[y],A=r({slug:i,environment:s,resourceType:"efs-mt"}),C=t(`${A}-az${y+1}`),T={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:N.Ref(a),SubnetId:S,SecurityGroups:[l]}};u.push(T),h.push(C)}return{mountTargets:u,logicalIds:h}}static createCompleteFileSystem(a){let{slug:n,environment:i,vpcId:s,subnetIds:c,sourceSecurityGroupIds:l=[],encrypted:u=!0,performanceMode:h="generalPurpose",throughputMode:y="elastic",enableBackup:S=!0,transitionToIA:A}=a,C={},{fileSystem:T,logicalId:v}=Ge.createFileSystem({slug:n,environment:i,encrypted:u,performanceMode:h,throughputMode:y,enableBackup:S});if(A)Ge.setLifecyclePolicy(T,{transitionToIA:A,transitionToPrimary:!0});C[v]=T;let{securityGroup:w,logicalId:E}=Ge.createEfsSecurityGroup({slug:n,environment:i,vpcId:s,sourceSecurityGroupIds:l});C[E]=w;let{mountTargets:R,logicalIds:k}=Ge.createMultiAzMountTargets(v,{slug:n,environment:i,subnetIds:c,securityGroupId:N.Ref(E)});for(let W=0;W<R.length;W++)C[k[W]]=R[W];return{resources:C,outputs:{fileSystemId:v,securityGroupId:E,mountTargetIds:k}}}}class m{static verifyDomain(a){let{domain:n,slug:i,environment:s,enableDkim:c=!0,dkimKeyLength:l="RSA_2048_BIT"}=a,u=r({slug:i,environment:s,resourceType:"ses-identity"}),h=t(`${u}-${n.replace(/\./g,"")}`),y={Type:"AWS::SES::EmailIdentity",Properties:{EmailIdentity:n,FeedbackAttributes:{EmailForwardingEnabled:!0}}};if(c)y.Properties.DkimSigningAttributes={NextSigningKeyLength:l};return{emailIdentity:y,logicalId:h}}static createDkimRecords(a,n,i){let s=[];for(let c=0;c<n.length;c++){let l=n[c],u=t(`dkim-${a.replace(/\./g,"")}-${c+1}`),h={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:`${l}._domainkey.${a}`,Type:"CNAME",TTL:1800,ResourceRecords:[`${l}.dkim.amazonses.com`]}};s.push({record:h,logicalId:u})}return s}static createConfigurationSet(a){let{slug:n,environment:i,name:s,reputationMetrics:c=!0,sendingEnabled:l=!0,suppressBounces:u=!0,suppressComplaints:h=!0}=a,y=s||r({slug:n,environment:i,resourceType:"ses-config"}),S=t(y),A=[];if(u)A.push("BOUNCE");if(h)A.push("COMPLAINT");return{configurationSet:{Type:"AWS::SES::ConfigurationSet",Properties:{Name:y,ReputationOptions:{ReputationMetricsEnabled:c},SendingOptions:{SendingEnabled:l},SuppressionOptions:{SuppressedReasons:A}}},logicalId:S}}static createReceiptRuleSet(a){let{slug:n,environment:i,name:s}=a,c=s||r({slug:n,environment:i,resourceType:"ses-ruleset"}),l=t(c);return{ruleSet:{Type:"AWS::SES::ReceiptRuleSet",Properties:{RuleSetName:c}},logicalId:l}}static createReceiptRule(a,n){let{slug:i,environment:s,ruleSetName:c,recipients:l,enabled:u=!0,scanEnabled:h=!0,tlsPolicy:y="Require",s3Action:S,lambdaAction:A,snsAction:C}=n,T=r({slug:i,environment:s,resourceType:"ses-rule"}),v=t(T),w=[];if(S)w.push({S3Action:{BucketName:S.bucketName,ObjectKeyPrefix:S.prefix,KmsKeyArn:S.kmsKeyArn}});if(A)w.push({LambdaAction:{FunctionArn:A.functionArn,InvocationType:A.invocationType||"Event"}});if(C)w.push({SNSAction:{TopicArn:C.topicArn,Encoding:C.encoding||"UTF-8"}});return{receiptRule:{Type:"AWS::SES::ReceiptRule",Properties:{RuleSetName:c,Rule:{Name:T,Enabled:u,ScanEnabled:h,TlsPolicy:y,Recipients:l,Actions:w.length>0?w:void 0}}},logicalId:v}}static createMxRecord(a,n,i){let s=t(`mx-${a.replace(/\./g,"")}`);return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n,Name:a,Type:"MX",TTL:300,ResourceRecords:[`10 inbound-smtp.${i}.amazonaws.com`]}},logicalId:s}}static createVerificationRecord(a,n,i){let s=t(`verification-${a.replace(/\./g,"")}`);return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:`_amazonses.${a}`,Type:"TXT",TTL:1800,ResourceRecords:[`"${n}"`]}},logicalId:s}}static getSmtpEndpoint(a){return`email-smtp.${a}.amazonaws.com`}static SmtpPorts={TLS:587,SSL:465,Unencrypted:25};static createSpfRecord(a,n,i){let{includeDomains:s=[],softFail:c=!1}=i||{},l=t(`spf-${a.replace(/\./g,"")}`),u="v=spf1 include:amazonses.com";for(let h of s)u+=` include:${h}`;return u+=c?" ~all":" -all",{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n,Name:a,Type:"TXT",TTL:300,ResourceRecords:[`"${u}"`]}},logicalId:l}}static createDmarcRecord(a,n,i){let{policy:s="none",subdomainPolicy:c,percentage:l=100,reportingEmail:u,forensicEmail:h}=i||{},y=t(`dmarc-${a.replace(/\./g,"")}`),S=`v=DMARC1; p=${s}; pct=${l}`;if(c)S+=`; sp=${c}`;if(u)S+=`; rua=mailto:${u}`;if(h)S+=`; ruf=mailto:${h}`;return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n,Name:`_dmarc.${a}`,Type:"TXT",TTL:300,ResourceRecords:[`"${S}"`]}},logicalId:y}}static createInboundEmailSetup(a){let{slug:n,environment:i,domain:s,s3BucketName:c,s3KeyPrefix:l="inbound/",region:u,hostedZoneId:h,lambdaFunctionArn:y,snsTopicArn:S}=a,A={},{ruleSet:C,logicalId:T}=m.createReceiptRuleSet({slug:n,environment:i});A[T]=C;let{receiptRule:v,logicalId:w}=m.createReceiptRule(T,{slug:n,environment:i,ruleSetName:C.Properties.RuleSetName||`${n}-${i}-receipt-rule-set`,recipients:[s],s3Action:{bucketName:c,prefix:l},lambdaAction:y?{functionArn:y,invocationType:"Event"}:void 0,snsAction:S?{topicArn:S}:void 0});A[w]=v;let{record:E,logicalId:R}=m.createMxRecord(s,h,u);return A[R]=E,{resources:A,outputs:{ruleSetLogicalId:T,ruleLogicalId:w,mxRecordLogicalId:R}}}static createCompleteDomainSetup(a){let{slug:n,environment:i,domain:s,hostedZoneId:c,region:l,enableInbound:u=!1,inboundS3Bucket:h,dmarcReportingEmail:y}=a,S={},{emailIdentity:A,logicalId:C}=m.verifyDomain({domain:s,slug:n,environment:i});S[C]=A;let{configurationSet:T,logicalId:v}=m.createConfigurationSet({slug:n,environment:i});S[v]=T;let{record:w,logicalId:E}=m.createSpfRecord(s,c);S[E]=w;let{record:R,logicalId:k}=m.createDmarcRecord(s,c,{policy:"none",reportingEmail:y||`dmarc-reports@${s}`});if(S[k]=R,u&&h){let W=m.createInboundEmailSetup({slug:n,environment:i,domain:s,s3BucketName:h,region:l,hostedZoneId:c});Object.assign(S,W.resources)}return{resources:S,outputs:{identityLogicalId:C,configSetLogicalId:v}}}static InboundSmtpEndpoints={"us-east-1":"inbound-smtp.us-east-1.amazonaws.com","us-west-2":"inbound-smtp.us-west-2.amazonaws.com","eu-west-1":"inbound-smtp.eu-west-1.amazonaws.com"};static supportsInboundEmail(a){return a in m.InboundSmtpEndpoints}static createEmailLambdaRole(a){let{slug:n,environment:i,s3BucketArn:s,sesIdentityArn:c}=a,l=r({slug:n,environment:i,resourceType:"email-lambda-role"}),u=t(l),h=t(`${l}-policy`),y={Type:"AWS::IAM::Role",Properties:{RoleName:l,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:i}]}},S=[{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[s,`${s}/*`]}];if(c)S.push({Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail"],Resource:c});let A={Type:"AWS::IAM::Policy",Properties:{PolicyName:`${l}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:S},Roles:[N.Ref(u)]}};return{role:y,policy:A,roleLogicalId:u,policyLogicalId:h}}static createOutboundEmailLambda(a){let{slug:n,environment:i,roleArn:s,domain:c,configurationSetName:l,timeout:u=30,memorySize:h=256}=a,y=r({slug:n,environment:i,resourceType:"outbound-email"}),S=t(y);return{function:{Type:"AWS::Lambda::Function",Properties:{FunctionName:y,Runtime:"nodejs20.x",Handler:"index.handler",Role:s,Timeout:u,MemorySize:h,Environment:{Variables:{DOMAIN:c,CONFIGURATION_SET:l||""}},Code:{ZipFile:m.LambdaCode.outboundEmail},Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:i},{Key:"Purpose",Value:"OutboundEmail"}]}},logicalId:S}}static createInboundEmailLambda(a){let{slug:n,environment:i,roleArn:s,s3BucketName:c,organizedPrefix:l="organized/",timeout:u=60,memorySize:h=512}=a,y=r({slug:n,environment:i,resourceType:"inbound-email"}),S=t(y),A=t(`${y}-permission`),C={Type:"AWS::Lambda::Function",Properties:{FunctionName:y,Runtime:"nodejs20.x",Handler:"index.handler",Role:s,Timeout:u,MemorySize:h,Environment:{Variables:{S3_BUCKET:c,ORGANIZED_PREFIX:l}},Code:{ZipFile:m.LambdaCode.inboundEmail},Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:i},{Key:"Purpose",Value:"InboundEmail"}]}},T={Type:"AWS::Lambda::Permission",Properties:{FunctionName:N.Ref(S),Action:"lambda:InvokeFunction",Principal:"ses.amazonaws.com",SourceAccount:N.Ref("AWS::AccountId")}};return{function:C,permission:T,logicalId:S,permissionLogicalId:A}}static createEmailConversionLambda(a){let{slug:n,environment:i,roleArn:s,s3BucketName:c,convertedPrefix:l="converted/",timeout:u=60,memorySize:h=512}=a,y=r({slug:n,environment:i,resourceType:"email-conversion"}),S=t(y);return{function:{Type:"AWS::Lambda::Function",Properties:{FunctionName:y,Runtime:"nodejs20.x",Handler:"index.handler",Role:s,Timeout:u,MemorySize:h,Environment:{Variables:{S3_BUCKET:c,CONVERTED_PREFIX:l}},Code:{ZipFile:m.LambdaCode.emailConversion},Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:i},{Key:"Purpose",Value:"EmailConversion"}]}},logicalId:S}}static createEmailBucketNotification(a){let{lambdaArn:n,prefix:i="inbound/",suffix:s,events:c}=a,l=c??["s3:ObjectCreated:*"],u={};if(i||s){if(u.S3Key={Rules:[]},i)u.S3Key.Rules.push({Name:"prefix",Value:i});if(s)u.S3Key.Rules.push({Name:"suffix",Value:s})}return{notificationConfiguration:{LambdaConfigurations:[{Event:l[0],Function:n,Filter:Object.keys(u).length>0?u:void 0}]}}}static createS3LambdaPermission(a){let{slug:n,environment:i,lambdaLogicalId:s,s3BucketArn:c}=a,l=r({slug:n,environment:i,resourceType:"s3-lambda-permission"}),u=t(l);return{permission:{Type:"AWS::Lambda::Permission",Properties:{FunctionName:N.Ref(s),Action:"lambda:InvokeFunction",Principal:"s3.amazonaws.com",SourceArn:c}},logicalId:u}}static createEmailProcessingStack(a){let{slug:n,environment:i,domain:s,s3BucketName:c,s3BucketArn:l,configurationSetName:u,enableInbound:h=!0,enableConversion:y=!0}=a,S={},{role:A,policy:C,roleLogicalId:T,policyLogicalId:v}=m.createEmailLambdaRole({slug:n,environment:i,s3BucketArn:l,sesIdentityArn:`arn:aws:ses:*:*:identity/${s}`});S[T]=A,S[v]=C;let{function:w,logicalId:E}=m.createOutboundEmailLambda({slug:n,environment:i,roleArn:N.GetAtt(T,"Arn"),domain:s,configurationSetName:u});S[E]=w;let R={roleLogicalId:T,outboundLambdaLogicalId:E};if(h){let{function:k,permission:W,logicalId:P,permissionLogicalId:V}=m.createInboundEmailLambda({slug:n,environment:i,roleArn:N.GetAtt(T,"Arn"),s3BucketName:c});S[P]=k,S[V]=W;let{permission:B,logicalId:j}=m.createS3LambdaPermission({slug:n,environment:i,lambdaLogicalId:P,s3BucketArn:l});S[j]=B,R.inboundLambdaLogicalId=P}if(y){let{function:k,logicalId:W}=m.createEmailConversionLambda({slug:n,environment:i,roleArn:N.GetAtt(T,"Arn"),s3BucketName:c});S[W]=k,R.conversionLambdaLogicalId=W}return{resources:S,outputs:R}}static LambdaCode={outboundEmail:`
624
624
  const { SESClient, SendRawEmailCommand } = require('@aws-sdk/client-ses');
625
625
  const ses = new SESClient({});
626
626
 
@@ -1658,7 +1658,7 @@ catch (error) {
1658
1658
 
1659
1659
  return { statusCode: 200, body: 'OK' };
1660
1660
  };
1661
- `;class qe{static LambdaCode={incomingCall:va,voicemail:ur,missedCall:lr};static createConnectInstance(a){let{slug:n,environment:i,instanceAlias:s,inboundCallsEnabled:c=!0,outboundCallsEnabled:l=!0}=a;return{[`${n}ConnectInstance`]:{Type:"AWS::Connect::Instance",Properties:{InstanceAlias:s,IdentityManagementType:"CONNECT_MANAGED",Attributes:{InboundCalls:c,OutboundCalls:l,ContactflowLogs:!0,ContactLens:!0,AutoResolveBestVoices:!0,UseCustomTTSVoices:!1,EarlyMedia:!0}}}}}static createHoursOfOperation(a){return{[`${a.slug}HoursOfOperation`]:{Type:"AWS::Connect::HoursOfOperation",Properties:{InstanceArn:a.instanceArn,Name:a.name,TimeZone:a.timezone,Config:a.schedule.map((n)=>({Day:n.day,StartTime:{Hours:n.startHour,Minutes:n.startMinute},EndTime:{Hours:n.endHour,Minutes:n.endMinute}}))}}}}static createQueue(a){return{[`${a.slug}Queue`]:{Type:"AWS::Connect::Queue",Properties:{InstanceArn:a.instanceArn,Name:a.name,HoursOfOperationArn:a.hoursOfOperationArn,MaxContacts:a.maxContacts||10}}}}static createContactFlow(a){return{[`${a.slug}ContactFlow`]:{Type:"AWS::Connect::ContactFlow",Properties:{InstanceArn:a.instanceArn,Name:a.name,Type:a.type,Content:a.content}}}}static createBasicIvrFlow(a){let n={Version:"2019-10-30",StartAction:"greeting",Actions:[{Identifier:"greeting",Type:"MessageParticipant",Parameters:{Text:a.greeting},Transitions:{NextAction:"transfer_to_queue",Errors:[{NextAction:"disconnect"}]}},{Identifier:"transfer_to_queue",Type:"TransferToQueue",Parameters:{QueueId:a.queueArn},Transitions:{NextAction:a.voicemailLambdaArn?"voicemail":"disconnect",Errors:[{NextAction:"disconnect"}]}},...a.voicemailLambdaArn?[{Identifier:"voicemail",Type:"InvokeLambdaFunction",Parameters:{LambdaFunctionARN:a.voicemailLambdaArn},Transitions:{NextAction:"disconnect",Errors:[{NextAction:"disconnect"}]}}]:[],{Identifier:"disconnect",Type:"DisconnectParticipant",Parameters:{},Transitions:{}}]};return JSON.stringify(n)}static createPhoneLambdaRole(a){return{[`${a.slug}PhoneLambdaRole`]:{Type:"AWS::IAM::Role",Properties:{RoleName:`${a.slug}-phone-lambda-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],Policies:[{PolicyName:"PhoneLambdaPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:GetItem"],Resource:"*"},{Effect:"Allow",Action:["sns:Publish"],Resource:"*"},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject"],Resource:"*"},{Effect:"Allow",Action:["transcribe:StartTranscriptionJob","transcribe:GetTranscriptionJob"],Resource:"*"},{Effect:"Allow",Action:["connect:*"],Resource:"*"}]}}]}}}}static createIncomingCallLambda(a){return{[`${a.slug}IncomingCallLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-incoming-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:qe.LambdaCode.incomingCall},Environment:{Variables:{NOTIFICATION_TOPIC_ARN:a.notificationTopicArn||"",CALL_LOG_TABLE:a.callLogTable||"",WEBHOOK_URL:a.webhookUrl||""}}}}}}static createVoicemailLambda(a){return{[`${a.slug}VoicemailLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-voicemail`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:300,MemorySize:512,Code:{ZipFile:qe.LambdaCode.voicemail},Environment:{Variables:{VOICEMAIL_BUCKET:a.voicemailBucket,NOTIFICATION_TOPIC_ARN:a.notificationTopicArn||"",CALL_LOG_TABLE:a.callLogTable||"",TRANSCRIPTION_ENABLED:a.transcriptionEnabled?"true":"false"}}}}}}static createMissedCallLambda(a){return{[`${a.slug}MissedCallLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-missed-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:qe.LambdaCode.missedCall},Environment:{Variables:{NOTIFICATION_TOPIC_ARN:a.notificationTopicArn||"",CALL_LOG_TABLE:a.callLogTable||"",WEBHOOK_URL:a.webhookUrl||""}}}}}}static createCallLogTable(a){return{[`${a.slug}CallLogTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${a.slug}-call-log`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"contactId",AttributeType:"S"}],KeySchema:[{AttributeName:"contactId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createCompleteSetup(a){let n={},i={};Object.assign(n,qe.createPhoneLambdaRole({slug:a.slug})),Object.assign(n,qe.createCallLogTable({slug:a.slug})),n[`${a.slug}PhoneNotificationTopic`]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${a.slug}-phone-notifications`}},n[`${a.slug}VoicemailBucket`]={Type:"AWS::S3::Bucket",Properties:{BucketName:`${a.slug}-voicemails`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldVoicemails",Status:"Enabled",ExpirationInDays:90}]}}};let s={"Fn::GetAtt":[`${a.slug}PhoneLambdaRole`,"Arn"]},c={Ref:`${a.slug}PhoneNotificationTopic`},l={Ref:`${a.slug}CallLogTable`},u={Ref:`${a.slug}VoicemailBucket`};if(Object.assign(n,qe.createIncomingCallLambda({slug:a.slug,roleArn:s,notificationTopicArn:c,callLogTable:l,webhookUrl:a.webhookUrl})),a.voicemailEnabled!==!1)Object.assign(n,qe.createVoicemailLambda({slug:a.slug,roleArn:s,voicemailBucket:u,notificationTopicArn:c,callLogTable:l,transcriptionEnabled:a.transcriptionEnabled}));return Object.assign(n,qe.createMissedCallLambda({slug:a.slug,roleArn:s,notificationTopicArn:c,callLogTable:l,webhookUrl:a.webhookUrl})),i[`${a.slug}PhoneNotificationTopicArn`]={Description:"Phone notification topic ARN",Value:{Ref:`${a.slug}PhoneNotificationTopic`}},i[`${a.slug}CallLogTableName`]={Description:"Call log table name",Value:{Ref:`${a.slug}CallLogTable`}},i[`${a.slug}VoicemailBucketName`]={Description:"Voicemail bucket name",Value:{Ref:`${a.slug}VoicemailBucket`}},{resources:n,outputs:i}}}class M{static createQueue(a){let{slug:n,environment:i,name:s,delaySeconds:c=0,visibilityTimeout:l=30,messageRetentionPeriod:u=345600,maxMessageSize:h=262144,receiveMessageWaitTime:y=0,fifo:S=!1,contentBasedDeduplication:b=!1,encrypted:A=!0,kmsKeyId:C}=a,T=s||r({slug:n,environment:i,resourceType:"queue"}),v=S?`${T}.fifo`:T,w=t(T),R={Type:"AWS::SQS::Queue",Properties:{QueueName:v,DelaySeconds:c,MaximumMessageSize:h,MessageRetentionPeriod:u,ReceiveMessageWaitTimeSeconds:y,VisibilityTimeout:l,Tags:[{Key:"Name",Value:v},{Key:"Environment",Value:i}]}};if(S)R.Properties.FifoQueue=!0,R.Properties.ContentBasedDeduplication=b;if(A)if(C)R.Properties.KmsMasterKeyId=C;else R.Properties.SqsManagedSseEnabled=!0;return{queue:R,logicalId:w}}static createDeadLetterQueue(a,n){let{slug:i,environment:s,maxReceiveCount:c=3}=n,l=r({slug:i,environment:s,resourceType:"dlq"}),u=t(l),h={Type:"AWS::SQS::Queue",Properties:{QueueName:l,MessageRetentionPeriod:1209600,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s},{Key:"Type",Value:"DeadLetterQueue"}]}},y={Type:"AWS::SQS::Queue",Properties:{RedrivePolicy:{deadLetterTargetArn:N.GetAtt(u,"Arn"),maxReceiveCount:c}}};return{deadLetterQueue:h,updatedSourceQueue:y,deadLetterLogicalId:u}}static createSchedule(a,n){let{slug:i,environment:s,name:c,description:l,enabled:u=!0}=n,h=c||r({slug:i,environment:s,resourceType:"schedule"}),y=t(h);return{rule:{Type:"AWS::Events::Rule",Properties:{Name:h,Description:l,ScheduleExpression:a,State:u?"ENABLED":"DISABLED",Targets:[]}},logicalId:y}}static scheduleEcsTask(a,n,i){let{slug:s,environment:c,name:l,description:u,enabled:h=!0,taskDefinitionArn:y,clusterArn:S,subnets:b,securityGroups:A=[],assignPublicIp:C=!1,taskCount:T=1,containerOverrides:v}=i,w=l||r({slug:s,environment:c,resourceType:"ecs-schedule"}),R=t(w),k={Id:"1",Arn:S,RoleArn:n,EcsParameters:{TaskDefinitionArn:y,TaskCount:T,LaunchType:"FARGATE",NetworkConfiguration:{awsvpcConfiguration:{Subnets:b,SecurityGroups:A,AssignPublicIp:C?"ENABLED":"DISABLED"}},PlatformVersion:"LATEST"}};if(v&&v.length>0)k.Input=JSON.stringify({containerOverrides:v});return{rule:{Type:"AWS::Events::Rule",Properties:{Name:w,Description:u||`Scheduled ECS task: ${y}`,ScheduleExpression:a,State:h?"ENABLED":"DISABLED",Targets:[k]}},logicalId:R}}static scheduleLambda(a,n){let{slug:i,environment:s,name:c,description:l,enabled:u=!0,functionArn:h,input:y}=n,S=c||r({slug:i,environment:s,resourceType:"lambda-schedule"}),b=t(S),A={Id:"1",Arn:h};if(y)A.Input=JSON.stringify(y);return{rule:{Type:"AWS::Events::Rule",Properties:{Name:S,Description:l||`Scheduled Lambda: ${h}`,ScheduleExpression:a,State:u?"ENABLED":"DISABLED",Targets:[A]}},logicalId:b}}static scheduleSqsMessage(a,n){let{slug:i,environment:s,name:c,description:l,enabled:u=!0,queueArn:h,messageGroupId:y}=n,S=c||r({slug:i,environment:s,resourceType:"sqs-schedule"}),b=t(S),A={Id:"1",Arn:h};if(y)A.SqsParameters={MessageGroupId:y};return{rule:{Type:"AWS::Events::Rule",Properties:{Name:S,Description:l||`Scheduled SQS message: ${h}`,ScheduleExpression:a,State:u?"ENABLED":"DISABLED",Targets:[A]}},logicalId:b}}static addTarget(a,n){if(!a.Properties.Targets)a.Properties.Targets=[];let i={Id:n.id,Arn:n.arn};if(n.roleArn)i.RoleArn=n.roleArn;if(n.input)i.Input=JSON.stringify(n.input);return a.Properties.Targets.push(i),a}static toCronExpression(a){if(a.startsWith("cron(")||a.startsWith("rate("))return a;return`cron(${a})`}static rateExpression(a,n){return`rate(${a} ${n})`}static CronExpressions={EveryMinute:"cron(* * * * ? *)",Every5Minutes:"cron(*/5 * * * ? *)",Every15Minutes:"cron(*/15 * * * ? *)",Every30Minutes:"cron(*/30 * * * ? *)",Hourly:"cron(0 * * * ? *)",Daily:"cron(0 0 * * ? *)",DailyAt9AM:"cron(0 9 * * ? *)",DailyAtMidnight:"cron(0 0 * * ? *)",Weekly:"cron(0 0 ? * SUN *)",Monthly:"cron(0 0 1 * ? *)"};static RateExpressions={Every1Minute:"rate(1 minute)",Every5Minutes:"rate(5 minutes)",Every10Minutes:"rate(10 minutes)",Every15Minutes:"rate(15 minutes)",Every30Minutes:"rate(30 minutes)",Every1Hour:"rate(1 hour)",Every6Hours:"rate(6 hours)",Every12Hours:"rate(12 hours)",Every1Day:"rate(1 day)"};static rateStringToExpression(a){let n=a.toLowerCase().trim(),i=n.match(/^every\s+(\d+)\s+(minute|minutes|hour|hours|day|days)$/i);if(i){let S=parseInt(i[1],10),b=i[2].toLowerCase(),A=b.endsWith("s")&&S===1?b.slice(0,-1):b,C=!b.endsWith("s")&&S>1?`${b}s`:b;return`rate(${S} ${S===1?A:C})`}let s=n.match(/^every\s+(minute|hour|day)$/i);if(s)return`rate(1 ${s[1]})`;let c={"every minute":"rate(1 minute)","every hour":"rate(1 hour)","every day":"rate(1 day)",hourly:"cron(0 * * * ? *)",daily:"cron(0 0 * * ? *)","daily at midnight":"cron(0 0 * * ? *)",weekly:"cron(0 0 ? * SUN *)",monthly:"cron(0 0 1 * ? *)",yearly:"cron(0 0 1 1 ? *)"};if(c[n])return c[n];let l=n.match(/^daily\s+at\s+(\d{1,2})\s*(am|pm)?$/i);if(l){let S=parseInt(l[1],10),b=l[2]?.toLowerCase();if(b==="pm"&&S!==12)S+=12;else if(b==="am"&&S===12)S=0;return`cron(0 ${S} * * ? *)`}let u=n.match(/^at\s+(\d{1,2}):(\d{2})$/i);if(u){let S=parseInt(u[1],10);return`cron(${parseInt(u[2],10)} ${S} * * ? *)`}let h={monday:"MON",tuesday:"TUE",wednesday:"WED",thursday:"THU",friday:"FRI",saturday:"SAT",sunday:"SUN"},y=n.match(/^every\s+(monday|tuesday|wednesday|thursday|friday|saturday|sunday)$/i);if(y)return`cron(0 0 ? * ${h[y[1].toLowerCase()]} *)`;return M.toCronExpression(a)}static JobConfig={create:(a)=>{let{name:n,handler:i,retries:s=3,backoff:c="exponential",backoffDelay:l=1000,maxDelay:u=30000,timeout:h=60000,jitter:y=!0}=a;return{name:n,handler:i,retries:s,backoff:c,backoffDelay:l,maxDelay:u,timeout:h,jitter:y}},calculateDelay:(a,n)=>{let{backoff:i,backoffDelay:s,maxDelay:c,jitter:l}=n,u;switch(i){case"linear":u=s*a;break;case"exponential":u=s*2**(a-1);break;case"fixed":default:u=s}if(u=Math.min(u,c||Number.MAX_SAFE_INTEGER),l){let h=u*0.25*Math.random();u+=h}return Math.floor(u)},presets:{fastRetry:{retries:5,backoff:"exponential",backoffDelay:100,maxDelay:5000,jitter:!0},standard:{retries:3,backoff:"exponential",backoffDelay:1000,maxDelay:30000,jitter:!0},longRunning:{retries:2,backoff:"exponential",backoffDelay:5000,maxDelay:60000,timeout:300000,jitter:!0},critical:{retries:10,backoff:"exponential",backoffDelay:500,maxDelay:60000,jitter:!0},noRetry:{retries:0,backoff:"fixed",backoffDelay:0,maxDelay:0,jitter:!1}}};static createJobContainerOverride(a){let{containerName:n,jobClass:i,jobData:s,environment:c={}}=a,l=[{name:"JOB_CLASS",value:i}];if(s)l.push({name:"JOB_DATA",value:JSON.stringify(s)});for(let[u,h]of Object.entries(c))l.push({name:u,value:h});return{name:n,command:["bun","run","app/Jobs/runner.ts"],environment:l}}static createScheduledJob(a){let{slug:n,environment:i,schedule:s,jobClass:c,jobData:l,taskDefinitionArn:u,clusterArn:h,subnets:y,securityGroups:S=[],roleArn:b,containerName:A="app"}=a,C=M.rateStringToExpression(s),T=M.createJobContainerOverride({containerName:A,jobClass:c,jobData:l});return M.scheduleEcsTask(C,b,{slug:n,environment:i,name:`${n}-${c.toLowerCase().replace(/[^a-z0-9]/g,"-")}`,description:`Scheduled job: ${c}`,taskDefinitionArn:u,clusterArn:h,subnets:y,securityGroups:S,containerOverrides:[T]})}static QueuePresets={highThroughput:(a,n)=>M.createQueue({slug:a,environment:n,visibilityTimeout:30,receiveMessageWaitTime:0,delaySeconds:0}),longRunning:(a,n)=>M.createQueue({slug:a,environment:n,visibilityTimeout:300,messageRetentionPeriod:1209600}),fifo:(a,n)=>M.createQueue({slug:a,environment:n,fifo:!0,contentBasedDeduplication:!0}),delayed:(a,n,i=60)=>M.createQueue({slug:a,environment:n,delaySeconds:i})}}class ut{static async discoverJobs(a){let{projectRoot:n,jobsPath:i="app/Jobs"}=a,s=`${n}/${i}`,c=[];try{let l=await import("node:fs"),u=await import("node:path");if(!l.existsSync(s))return[];let h=l.readdirSync(s).filter((y)=>y.endsWith(".ts")&&!y.startsWith("_")&&y!=="runner.ts");for(let y of h){let S=u.join(s,y),b=y.replace(".ts",""),A=l.readFileSync(S,"utf-8"),C=ut.parseJobMetadata(A,b,S);if(C)c.push(C)}}catch{return[]}return c}static parseJobMetadata(a,n,i){let s=a.match(/export\s + const\s + schedule\s*=\s*['"`]([^'"`]+)['"`]/)||a.match(/schedule:\s*['"`]([^'"`]+)['"`]/),c=a.match(/export\s+const\s+enabled\s*=\s*(true|false)/)||a.match(/enabled:\s*(true|false)/),l=a.match(/export\s+const\s+retries\s*=\s*(\d+)/)||a.match(/retries:\s*(\d+)/),u=a.match(/export\s+const\s+timeout\s*=\s*(\d+)/)||a.match(/timeout:\s*(\d+)/),h=a.match(/export\s+const\s+backoff\s*=\s*['"`](linear|exponential|fixed)['"`]/)||a.match(/backoff:\s*['"`](linear|exponential|fixed)['"`]/),y=a.match(/export\s + const\s + description\s*=\s*['"`]([^'"`]+)['"`]/)||a.match(/description:\s*['"`]([^'"`]+)['"`]/);if(!(a.includes("export async function handle")||a.includes("export function handle")||a.includes("export default")))return null;return{name:n,path:i,schedule:s?.[1],handler:`${n}.handle`,enabled:c?.[1]!=="false",retries:l?parseInt(l[1],10):void 0,backoff:h?.[1],timeout:u?parseInt(u[1],10):void 0,description:y?.[1]}}static async discoverActions(a){let{projectRoot:n,actionsPath:i="app/Actions"}=a,s=`${n}/${i}`,c=[];try{let l=await import("node:fs"),u=await import("node:path");if(!l.existsSync(s))return[];let h=l.readdirSync(s).filter((y)=>y.endsWith(".ts")&&!y.startsWith("_"));for(let y of h){let S=u.join(s,y),b=y.replace(".ts",""),A=l.readFileSync(S,"utf-8"),C=ut.parseActionMetadata(A,b,S);if(C)c.push(C)}}catch{return[]}return c}static parseActionMetadata(a,n,i){if(!(a.includes("export async function handle")||a.includes("export function handle")||a.includes("export default")))return null;let s=a.match(/export\s + const\s + description\s*=\s*['"`]([^'"`]+)['"`]/)||a.match(/description:\s*['"`]([^'"`]+)['"`]/);return{name:n,path:i,handler:`${n}.handle`,description:s?.[1]}}static generateScheduledJobResources(a){let{slug:n,environment:i,jobs:s,taskDefinitionArn:c,clusterArn:l,subnets:u,securityGroups:h=[],roleArn:y,containerName:S="app"}=a,b={},A=0;for(let C of s){if(!C.schedule||!C.enabled)continue;let{rule:T,logicalId:v}=M.createScheduledJob({slug:n,environment:i,schedule:C.schedule,jobClass:C.name,taskDefinitionArn:c,clusterArn:l,subnets:u,securityGroups:h,roleArn:y,containerName:S});b[v]=T,A++}return{rules:b,count:A}}static generateJobRunnerScript(){return`#!/usr/bin/env bun
1661
+ `;class qe{static LambdaCode={incomingCall:va,voicemail:ur,missedCall:lr};static createConnectInstance(a){let{slug:n,environment:i,instanceAlias:s,inboundCallsEnabled:c=!0,outboundCallsEnabled:l=!0}=a;return{[`${n}ConnectInstance`]:{Type:"AWS::Connect::Instance",Properties:{InstanceAlias:s,IdentityManagementType:"CONNECT_MANAGED",Attributes:{InboundCalls:c,OutboundCalls:l,ContactflowLogs:!0,ContactLens:!0,AutoResolveBestVoices:!0,UseCustomTTSVoices:!1,EarlyMedia:!0}}}}}static createHoursOfOperation(a){return{[`${a.slug}HoursOfOperation`]:{Type:"AWS::Connect::HoursOfOperation",Properties:{InstanceArn:a.instanceArn,Name:a.name,TimeZone:a.timezone,Config:a.schedule.map((n)=>({Day:n.day,StartTime:{Hours:n.startHour,Minutes:n.startMinute},EndTime:{Hours:n.endHour,Minutes:n.endMinute}}))}}}}static createQueue(a){return{[`${a.slug}Queue`]:{Type:"AWS::Connect::Queue",Properties:{InstanceArn:a.instanceArn,Name:a.name,HoursOfOperationArn:a.hoursOfOperationArn,MaxContacts:a.maxContacts||10}}}}static createContactFlow(a){return{[`${a.slug}ContactFlow`]:{Type:"AWS::Connect::ContactFlow",Properties:{InstanceArn:a.instanceArn,Name:a.name,Type:a.type,Content:a.content}}}}static createBasicIvrFlow(a){let n={Version:"2019-10-30",StartAction:"greeting",Actions:[{Identifier:"greeting",Type:"MessageParticipant",Parameters:{Text:a.greeting},Transitions:{NextAction:"transfer_to_queue",Errors:[{NextAction:"disconnect"}]}},{Identifier:"transfer_to_queue",Type:"TransferToQueue",Parameters:{QueueId:a.queueArn},Transitions:{NextAction:a.voicemailLambdaArn?"voicemail":"disconnect",Errors:[{NextAction:"disconnect"}]}},...a.voicemailLambdaArn?[{Identifier:"voicemail",Type:"InvokeLambdaFunction",Parameters:{LambdaFunctionARN:a.voicemailLambdaArn},Transitions:{NextAction:"disconnect",Errors:[{NextAction:"disconnect"}]}}]:[],{Identifier:"disconnect",Type:"DisconnectParticipant",Parameters:{},Transitions:{}}]};return JSON.stringify(n)}static createPhoneLambdaRole(a){return{[`${a.slug}PhoneLambdaRole`]:{Type:"AWS::IAM::Role",Properties:{RoleName:`${a.slug}-phone-lambda-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],Policies:[{PolicyName:"PhoneLambdaPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:GetItem"],Resource:"*"},{Effect:"Allow",Action:["sns:Publish"],Resource:"*"},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject"],Resource:"*"},{Effect:"Allow",Action:["transcribe:StartTranscriptionJob","transcribe:GetTranscriptionJob"],Resource:"*"},{Effect:"Allow",Action:["connect:*"],Resource:"*"}]}}]}}}}static createIncomingCallLambda(a){return{[`${a.slug}IncomingCallLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-incoming-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:qe.LambdaCode.incomingCall},Environment:{Variables:{NOTIFICATION_TOPIC_ARN:a.notificationTopicArn||"",CALL_LOG_TABLE:a.callLogTable||"",WEBHOOK_URL:a.webhookUrl||""}}}}}}static createVoicemailLambda(a){return{[`${a.slug}VoicemailLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-voicemail`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:300,MemorySize:512,Code:{ZipFile:qe.LambdaCode.voicemail},Environment:{Variables:{VOICEMAIL_BUCKET:a.voicemailBucket,NOTIFICATION_TOPIC_ARN:a.notificationTopicArn||"",CALL_LOG_TABLE:a.callLogTable||"",TRANSCRIPTION_ENABLED:a.transcriptionEnabled?"true":"false"}}}}}}static createMissedCallLambda(a){return{[`${a.slug}MissedCallLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-missed-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:qe.LambdaCode.missedCall},Environment:{Variables:{NOTIFICATION_TOPIC_ARN:a.notificationTopicArn||"",CALL_LOG_TABLE:a.callLogTable||"",WEBHOOK_URL:a.webhookUrl||""}}}}}}static createCallLogTable(a){return{[`${a.slug}CallLogTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${a.slug}-call-log`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"contactId",AttributeType:"S"}],KeySchema:[{AttributeName:"contactId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createCompleteSetup(a){let n={},i={};Object.assign(n,qe.createPhoneLambdaRole({slug:a.slug})),Object.assign(n,qe.createCallLogTable({slug:a.slug})),n[`${a.slug}PhoneNotificationTopic`]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${a.slug}-phone-notifications`}},n[`${a.slug}VoicemailBucket`]={Type:"AWS::S3::Bucket",Properties:{BucketName:`${a.slug}-voicemails`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldVoicemails",Status:"Enabled",ExpirationInDays:90}]}}};let s={"Fn::GetAtt":[`${a.slug}PhoneLambdaRole`,"Arn"]},c={Ref:`${a.slug}PhoneNotificationTopic`},l={Ref:`${a.slug}CallLogTable`},u={Ref:`${a.slug}VoicemailBucket`};if(Object.assign(n,qe.createIncomingCallLambda({slug:a.slug,roleArn:s,notificationTopicArn:c,callLogTable:l,webhookUrl:a.webhookUrl})),a.voicemailEnabled!==!1)Object.assign(n,qe.createVoicemailLambda({slug:a.slug,roleArn:s,voicemailBucket:u,notificationTopicArn:c,callLogTable:l,transcriptionEnabled:a.transcriptionEnabled}));return Object.assign(n,qe.createMissedCallLambda({slug:a.slug,roleArn:s,notificationTopicArn:c,callLogTable:l,webhookUrl:a.webhookUrl})),i[`${a.slug}PhoneNotificationTopicArn`]={Description:"Phone notification topic ARN",Value:{Ref:`${a.slug}PhoneNotificationTopic`}},i[`${a.slug}CallLogTableName`]={Description:"Call log table name",Value:{Ref:`${a.slug}CallLogTable`}},i[`${a.slug}VoicemailBucketName`]={Description:"Voicemail bucket name",Value:{Ref:`${a.slug}VoicemailBucket`}},{resources:n,outputs:i}}}class M{static createQueue(a){let{slug:n,environment:i,name:s,delaySeconds:c=0,visibilityTimeout:l=30,messageRetentionPeriod:u=345600,maxMessageSize:h=262144,receiveMessageWaitTime:y=0,fifo:S=!1,contentBasedDeduplication:A=!1,encrypted:C=!0,kmsKeyId:T}=a,v=s||r({slug:n,environment:i,resourceType:"queue"}),w=S?`${v}.fifo`:v,E=t(v),R={Type:"AWS::SQS::Queue",Properties:{QueueName:w,DelaySeconds:c,MaximumMessageSize:h,MessageRetentionPeriod:u,ReceiveMessageWaitTimeSeconds:y,VisibilityTimeout:l,Tags:[{Key:"Name",Value:w},{Key:"Environment",Value:i}]}};if(S)R.Properties.FifoQueue=!0,R.Properties.ContentBasedDeduplication=A;if(C)if(T)R.Properties.KmsMasterKeyId=T;else R.Properties.SqsManagedSseEnabled=!0;return{queue:R,logicalId:E}}static createDeadLetterQueue(a,n){let{slug:i,environment:s,maxReceiveCount:c=3}=n,l=r({slug:i,environment:s,resourceType:"dlq"}),u=t(l),h={Type:"AWS::SQS::Queue",Properties:{QueueName:l,MessageRetentionPeriod:1209600,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s},{Key:"Type",Value:"DeadLetterQueue"}]}},y={Type:"AWS::SQS::Queue",Properties:{RedrivePolicy:{deadLetterTargetArn:N.GetAtt(u,"Arn"),maxReceiveCount:c}}};return{deadLetterQueue:h,updatedSourceQueue:y,deadLetterLogicalId:u}}static createSchedule(a,n){let{slug:i,environment:s,name:c,description:l,enabled:u=!0}=n,h=c||r({slug:i,environment:s,resourceType:"schedule"}),y=t(h);return{rule:{Type:"AWS::Events::Rule",Properties:{Name:h,Description:l,ScheduleExpression:a,State:u?"ENABLED":"DISABLED",Targets:[]}},logicalId:y}}static scheduleEcsTask(a,n,i){let{slug:s,environment:c,name:l,description:u,enabled:h=!0,taskDefinitionArn:y,clusterArn:S,subnets:A,securityGroups:C=[],assignPublicIp:T=!1,taskCount:v=1,containerOverrides:w}=i,E=l||r({slug:s,environment:c,resourceType:"ecs-schedule"}),R=t(E),k={Id:"1",Arn:S,RoleArn:n,EcsParameters:{TaskDefinitionArn:y,TaskCount:v,LaunchType:"FARGATE",NetworkConfiguration:{awsvpcConfiguration:{Subnets:A,SecurityGroups:C,AssignPublicIp:T?"ENABLED":"DISABLED"}},PlatformVersion:"LATEST"}};if(w&&w.length>0)k.Input=JSON.stringify({containerOverrides:w});return{rule:{Type:"AWS::Events::Rule",Properties:{Name:E,Description:u||`Scheduled ECS task: ${y}`,ScheduleExpression:a,State:h?"ENABLED":"DISABLED",Targets:[k]}},logicalId:R}}static scheduleLambda(a,n){let{slug:i,environment:s,name:c,description:l,enabled:u=!0,functionArn:h,input:y}=n,S=c||r({slug:i,environment:s,resourceType:"lambda-schedule"}),A=t(S),C={Id:"1",Arn:h};if(y)C.Input=JSON.stringify(y);return{rule:{Type:"AWS::Events::Rule",Properties:{Name:S,Description:l||`Scheduled Lambda: ${h}`,ScheduleExpression:a,State:u?"ENABLED":"DISABLED",Targets:[C]}},logicalId:A}}static scheduleSqsMessage(a,n){let{slug:i,environment:s,name:c,description:l,enabled:u=!0,queueArn:h,messageGroupId:y}=n,S=c||r({slug:i,environment:s,resourceType:"sqs-schedule"}),A=t(S),C={Id:"1",Arn:h};if(y)C.SqsParameters={MessageGroupId:y};return{rule:{Type:"AWS::Events::Rule",Properties:{Name:S,Description:l||`Scheduled SQS message: ${h}`,ScheduleExpression:a,State:u?"ENABLED":"DISABLED",Targets:[C]}},logicalId:A}}static addTarget(a,n){if(!a.Properties.Targets)a.Properties.Targets=[];let i={Id:n.id,Arn:n.arn};if(n.roleArn)i.RoleArn=n.roleArn;if(n.input)i.Input=JSON.stringify(n.input);return a.Properties.Targets.push(i),a}static toCronExpression(a){if(a.startsWith("cron(")||a.startsWith("rate("))return a;return`cron(${a})`}static rateExpression(a,n){return`rate(${a} ${n})`}static CronExpressions={EveryMinute:"cron(* * * * ? *)",Every5Minutes:"cron(*/5 * * * ? *)",Every15Minutes:"cron(*/15 * * * ? *)",Every30Minutes:"cron(*/30 * * * ? *)",Hourly:"cron(0 * * * ? *)",Daily:"cron(0 0 * * ? *)",DailyAt9AM:"cron(0 9 * * ? *)",DailyAtMidnight:"cron(0 0 * * ? *)",Weekly:"cron(0 0 ? * SUN *)",Monthly:"cron(0 0 1 * ? *)"};static RateExpressions={Every1Minute:"rate(1 minute)",Every5Minutes:"rate(5 minutes)",Every10Minutes:"rate(10 minutes)",Every15Minutes:"rate(15 minutes)",Every30Minutes:"rate(30 minutes)",Every1Hour:"rate(1 hour)",Every6Hours:"rate(6 hours)",Every12Hours:"rate(12 hours)",Every1Day:"rate(1 day)"};static rateStringToExpression(a){let n=a.toLowerCase().trim(),i=n.match(/^every\s+(\d+)\s+(minute|minutes|hour|hours|day|days)$/i);if(i){let S=parseInt(i[1],10),A=i[2].toLowerCase(),C=A.endsWith("s")&&S===1?A.slice(0,-1):A,T=!A.endsWith("s")&&S>1?`${A}s`:A;return`rate(${S} ${S===1?C:T})`}let s=n.match(/^every\s+(minute|hour|day)$/i);if(s)return`rate(1 ${s[1]})`;let c={"every minute":"rate(1 minute)","every hour":"rate(1 hour)","every day":"rate(1 day)",hourly:"cron(0 * * * ? *)",daily:"cron(0 0 * * ? *)","daily at midnight":"cron(0 0 * * ? *)",weekly:"cron(0 0 ? * SUN *)",monthly:"cron(0 0 1 * ? *)",yearly:"cron(0 0 1 1 ? *)"};if(c[n])return c[n];let l=n.match(/^daily\s+at\s+(\d{1,2})\s*(am|pm)?$/i);if(l){let S=parseInt(l[1],10),A=l[2]?.toLowerCase();if(A==="pm"&&S!==12)S+=12;else if(A==="am"&&S===12)S=0;return`cron(0 ${S} * * ? *)`}let u=n.match(/^at\s+(\d{1,2}):(\d{2})$/i);if(u){let S=parseInt(u[1],10);return`cron(${parseInt(u[2],10)} ${S} * * ? *)`}let h={monday:"MON",tuesday:"TUE",wednesday:"WED",thursday:"THU",friday:"FRI",saturday:"SAT",sunday:"SUN"},y=n.match(/^every\s+(monday|tuesday|wednesday|thursday|friday|saturday|sunday)$/i);if(y)return`cron(0 0 ? * ${h[y[1].toLowerCase()]} *)`;return M.toCronExpression(a)}static JobConfig={create:(a)=>{let{name:n,handler:i,retries:s=3,backoff:c="exponential",backoffDelay:l=1000,maxDelay:u=30000,timeout:h=60000,jitter:y=!0}=a;return{name:n,handler:i,retries:s,backoff:c,backoffDelay:l,maxDelay:u,timeout:h,jitter:y}},calculateDelay:(a,n)=>{let{backoff:i,backoffDelay:s,maxDelay:c,jitter:l}=n,u;switch(i){case"linear":u=s*a;break;case"exponential":u=s*2**(a-1);break;case"fixed":default:u=s}if(u=Math.min(u,c||Number.MAX_SAFE_INTEGER),l){let h=u*0.25*Math.random();u+=h}return Math.floor(u)},presets:{fastRetry:{retries:5,backoff:"exponential",backoffDelay:100,maxDelay:5000,jitter:!0},standard:{retries:3,backoff:"exponential",backoffDelay:1000,maxDelay:30000,jitter:!0},longRunning:{retries:2,backoff:"exponential",backoffDelay:5000,maxDelay:60000,timeout:300000,jitter:!0},critical:{retries:10,backoff:"exponential",backoffDelay:500,maxDelay:60000,jitter:!0},noRetry:{retries:0,backoff:"fixed",backoffDelay:0,maxDelay:0,jitter:!1}}};static createJobContainerOverride(a){let{containerName:n,jobClass:i,jobData:s,environment:c={}}=a,l=[{name:"JOB_CLASS",value:i}];if(s)l.push({name:"JOB_DATA",value:JSON.stringify(s)});for(let[u,h]of Object.entries(c))l.push({name:u,value:h});return{name:n,command:["bun","run","app/Jobs/runner.ts"],environment:l}}static createScheduledJob(a){let{slug:n,environment:i,schedule:s,jobClass:c,jobData:l,taskDefinitionArn:u,clusterArn:h,subnets:y,securityGroups:S=[],roleArn:A,containerName:C="app"}=a,T=M.rateStringToExpression(s),v=M.createJobContainerOverride({containerName:C,jobClass:c,jobData:l});return M.scheduleEcsTask(T,A,{slug:n,environment:i,name:`${n}-${c.toLowerCase().replace(/[^a-z0-9]/g,"-")}`,description:`Scheduled job: ${c}`,taskDefinitionArn:u,clusterArn:h,subnets:y,securityGroups:S,containerOverrides:[v]})}static QueuePresets={highThroughput:(a,n)=>M.createQueue({slug:a,environment:n,visibilityTimeout:30,receiveMessageWaitTime:0,delaySeconds:0}),longRunning:(a,n)=>M.createQueue({slug:a,environment:n,visibilityTimeout:300,messageRetentionPeriod:1209600}),fifo:(a,n)=>M.createQueue({slug:a,environment:n,fifo:!0,contentBasedDeduplication:!0}),delayed:(a,n,i=60)=>M.createQueue({slug:a,environment:n,delaySeconds:i})}}class ut{static async discoverJobs(a){let{projectRoot:n,jobsPath:i="app/Jobs"}=a,s=`${n}/${i}`,c=[];try{let l=await import("node:fs"),u=await import("node:path");if(!l.existsSync(s))return[];let h=l.readdirSync(s).filter((y)=>y.endsWith(".ts")&&!y.startsWith("_")&&y!=="runner.ts");for(let y of h){let S=u.join(s,y),A=y.replace(".ts",""),C=l.readFileSync(S,"utf-8"),T=ut.parseJobMetadata(C,A,S);if(T)c.push(T)}}catch{return[]}return c}static parseJobMetadata(a,n,i){let s=a.match(/export\s + const\s + schedule\s*=\s*['"`]([^'"`]+)['"`]/)||a.match(/schedule:\s*['"`]([^'"`]+)['"`]/),c=a.match(/export\s+const\s+enabled\s*=\s*(true|false)/)||a.match(/enabled:\s*(true|false)/),l=a.match(/export\s+const\s+retries\s*=\s*(\d+)/)||a.match(/retries:\s*(\d+)/),u=a.match(/export\s+const\s+timeout\s*=\s*(\d+)/)||a.match(/timeout:\s*(\d+)/),h=a.match(/export\s+const\s+backoff\s*=\s*['"`](linear|exponential|fixed)['"`]/)||a.match(/backoff:\s*['"`](linear|exponential|fixed)['"`]/),y=a.match(/export\s + const\s + description\s*=\s*['"`]([^'"`]+)['"`]/)||a.match(/description:\s*['"`]([^'"`]+)['"`]/);if(!(a.includes("export async function handle")||a.includes("export function handle")||a.includes("export default")))return null;return{name:n,path:i,schedule:s?.[1],handler:`${n}.handle`,enabled:c?.[1]!=="false",retries:l?parseInt(l[1],10):void 0,backoff:h?.[1],timeout:u?parseInt(u[1],10):void 0,description:y?.[1]}}static async discoverActions(a){let{projectRoot:n,actionsPath:i="app/Actions"}=a,s=`${n}/${i}`,c=[];try{let l=await import("node:fs"),u=await import("node:path");if(!l.existsSync(s))return[];let h=l.readdirSync(s).filter((y)=>y.endsWith(".ts")&&!y.startsWith("_"));for(let y of h){let S=u.join(s,y),A=y.replace(".ts",""),C=l.readFileSync(S,"utf-8"),T=ut.parseActionMetadata(C,A,S);if(T)c.push(T)}}catch{return[]}return c}static parseActionMetadata(a,n,i){if(!(a.includes("export async function handle")||a.includes("export function handle")||a.includes("export default")))return null;let s=a.match(/export\s + const\s + description\s*=\s*['"`]([^'"`]+)['"`]/)||a.match(/description:\s*['"`]([^'"`]+)['"`]/);return{name:n,path:i,handler:`${n}.handle`,description:s?.[1]}}static generateScheduledJobResources(a){let{slug:n,environment:i,jobs:s,taskDefinitionArn:c,clusterArn:l,subnets:u,securityGroups:h=[],roleArn:y,containerName:S="app"}=a,A={},C=0;for(let T of s){if(!T.schedule||!T.enabled)continue;let{rule:v,logicalId:w}=M.createScheduledJob({slug:n,environment:i,schedule:T.schedule,jobClass:T.name,taskDefinitionArn:c,clusterArn:l,subnets:u,securityGroups:h,roleArn:y,containerName:S});A[w]=v,C++}return{rules:A,count:C}}static generateJobRunnerScript(){return`#!/usr/bin/env bun
1662
1662
  /**
1663
1663
  * Job Runner Script
1664
1664
  * This script is invoked by ECS scheduled tasks to run jobs
@@ -2306,14 +2306,14 @@ function resolveTemplate(template, data) {
2306
2306
  }
2307
2307
  return result;
2308
2308
  }
2309
- `;class F{static LambdaCode={send:wa,receive:mr,deliveryStatus:dr};static createPinpointApp(a){return{[`${a.slug}PinpointApp`]:{Type:"AWS::Pinpoint::App",Properties:{Name:a.name||`${a.slug}-sms`}}}}static createSmsChannel(a){let n={ApplicationId:a.applicationId,Enabled:a.enabled!==!1};if(a.senderId)n.SenderId=a.senderId;if(a.shortCode)n.ShortCode=a.shortCode;return{[`${a.slug}SmsChannel`]:{Type:"AWS::Pinpoint::SMSChannel",Properties:n}}}static createSmsLambdaRole(a){return{[`${a.slug}SmsLambdaRole`]:{Type:"AWS::IAM::Role",Properties:{RoleName:`${a.slug}-sms-lambda-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],Policies:[{PolicyName:"SmsLambdaPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["mobiletargeting:SendMessages","mobiletargeting:GetSmsChannel"],Resource:"*"},{Effect:"Allow",Action:["sns:Publish"],Resource:"*"},{Effect:"Allow",Action:["dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:GetItem","dynamodb:DeleteItem"],Resource:"*"}]}}]}}}}static createSendLambda(a){return{[`${a.slug}SmsSendLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-sms-send`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:F.LambdaCode.send},Environment:{Variables:{PINPOINT_APP_ID:a.pinpointAppId,MESSAGE_LOG_TABLE:a.messageLogTable||"",SMS_SENDER_ID:a.senderId||"",SMS_ORIGINATION_NUMBER:a.originationNumber||""}}}}}}static createReceiveLambda(a){return{[`${a.slug}SmsReceiveLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-sms-receive`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:F.LambdaCode.receive},Environment:{Variables:{OPT_OUT_TABLE:a.optOutTable||"",MESSAGE_LOG_TABLE:a.messageLogTable||"",NOTIFICATION_TOPIC_ARN:a.notificationTopicArn||"",WEBHOOK_URL:a.webhookUrl||""}}}}}}static createDeliveryStatusLambda(a){return{[`${a.slug}SmsDeliveryStatusLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-sms-delivery-status`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:F.LambdaCode.deliveryStatus},Environment:{Variables:{MESSAGE_LOG_TABLE:a.messageLogTable||"",NOTIFICATION_TOPIC_ARN:a.notificationTopicArn||"",WEBHOOK_URL:a.webhookUrl||""}}}}}}static createMessageLogTable(a){return{[`${a.slug}SmsMessageLogTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${a.slug}-sms-messages`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createOptOutTable(a){return{[`${a.slug}SmsOptOutTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${a.slug}-sms-optouts`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}]}}}}static createNotificationTopic(a){return{[`${a.slug}SmsNotificationTopic`]:{Type:"AWS::SNS::Topic",Properties:{TopicName:`${a.slug}-sms-notifications`}}}}static createCompleteSetup(a){let n={},i={};Object.assign(n,F.createPinpointApp({slug:a.slug})),Object.assign(n,F.createSmsChannel({slug:a.slug,applicationId:{Ref:`${a.slug}PinpointApp`},senderId:a.senderId})),Object.assign(n,F.createSmsLambdaRole({slug:a.slug})),Object.assign(n,F.createMessageLogTable({slug:a.slug})),Object.assign(n,F.createOptOutTable({slug:a.slug})),Object.assign(n,F.createNotificationTopic({slug:a.slug}));let s={"Fn::GetAtt":[`${a.slug}SmsLambdaRole`,"Arn"]},c={Ref:`${a.slug}PinpointApp`},l={Ref:`${a.slug}SmsMessageLogTable`},u={Ref:`${a.slug}SmsOptOutTable`},h={Ref:`${a.slug}SmsNotificationTopic`};if(Object.assign(n,F.createSendLambda({slug:a.slug,roleArn:s,pinpointAppId:c,messageLogTable:l,senderId:a.senderId,originationNumber:a.originationNumber})),a.twoWayEnabled)Object.assign(n,F.createReceiveLambda({slug:a.slug,roleArn:s,optOutTable:u,messageLogTable:l,notificationTopicArn:h,webhookUrl:a.webhookUrl}));return Object.assign(n,F.createDeliveryStatusLambda({slug:a.slug,roleArn:s,messageLogTable:l,notificationTopicArn:h,webhookUrl:a.webhookUrl})),i[`${a.slug}PinpointAppId`]={Description:"Pinpoint application ID",Value:{Ref:`${a.slug}PinpointApp`}},i[`${a.slug}SmsSendLambdaArn`]={Description:"SMS send Lambda ARN",Value:{"Fn::GetAtt":[`${a.slug}SmsSendLambda`,"Arn"]}},i[`${a.slug}SmsNotificationTopicArn`]={Description:"SMS notification topic ARN",Value:{Ref:`${a.slug}SmsNotificationTopic`}},i[`${a.slug}SmsMessageLogTableName`]={Description:"SMS message log table name",Value:{Ref:`${a.slug}SmsMessageLogTable`}},{resources:n,outputs:i}}}function wt(a){return a.replace(/[^a-zA-Z0-9]/g," ").trim().split(/\s+/).map((n)=>n.charAt(0).toUpperCase()+n.slice(1)).join("")||"User"}function gr(a,n){let i=(a||n).replace(/^\/+|\/+$/g,"");if(!i||i.split("/").includes(".."))throw Error(`sftp: invalid homeDirectory for user ${n}`);return i}function hr(a){let n=a.storage;if(n?.type==="efs"){let s="fileSystemId"in n?n.fileSystemId:void 0;if(!s||typeof s==="string"&&!s.trim())throw Error("sftp: EFS storage requires fileSystemId, or a fileSystem name defined in infrastructure.fileSystem");return{type:"efs",fileSystemId:s,posixProfile:n.posixProfile}}let i=(n?.type==="s3"?n.bucket??a.bucket:a.bucket)?.trim();if(!i)throw Error("sftp: S3 storage requires bucket, or a storageBucket name defined in infrastructure.storage");return{type:"s3",bucket:i}}function yr(a,n,i){let s=n.posixProfile??i;if(!s)throw Error(`sftp: user ${a} requires a posixProfile (uid/gid) on an EFS-backed server`);for(let c of[s.uid,s.gid,...s.secondaryGids??[]])if(!Number.isInteger(c)||c<0||c>4294967295)throw Error(`sftp: user ${a} has an invalid posixProfile id ${c}`);return{Uid:s.uid,Gid:s.gid,...s.secondaryGids?.length?{SecondaryGids:s.secondaryGids}:{}}}function fr(a,n){return typeof a==="string"?`/${a}/${n}`:{"Fn::Sub":[`/\${FileSystemId}/${n}`,{FileSystemId:a}]}}function Sr(a){return typeof a==="string"?{"Fn::Sub":"arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}".replace("${FileSystemId}",a)}:{"Fn::Sub":["arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}",{FileSystemId:a}]}}class md{static create(a){let n=hr(a),i=n.type==="efs"?"EFS":"S3",s=a.endpointType??"PUBLIC";if(s==="VPC"&&(!a.endpointDetails?.vpcId||!a.endpointDetails.subnetIds.length))throw Error("sftp: VPC endpoints require endpointDetails.vpcId and at least one subnet");let c=`${wt(a.slug)}${wt(a.environment)}Sftp`,l=`${c}Server`,u={},h;if(a.logging!==!1){let y=`${c}LoggingRole`;u[y]={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"transfer.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"TransferLogging",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:DescribeLogStreams","logs:PutLogEvents"],Resource:"arn:aws:logs:*:*:log-group:/aws/transfer/*"}]}}]}},h={"Fn::GetAtt":[y,"Arn"]}}u[l]={Type:"AWS::Transfer::Server",Properties:{Domain:i,EndpointType:s,IdentityProviderType:"SERVICE_MANAGED",Protocols:["SFTP"],...s==="VPC"?{EndpointDetails:{VpcId:a.endpointDetails.vpcId,SubnetIds:a.endpointDetails.subnetIds,...a.endpointDetails.securityGroupIds?.length?{SecurityGroupIds:a.endpointDetails.securityGroupIds}:{},...a.endpointDetails.addressAllocationIds?.length?{AddressAllocationIds:a.endpointDetails.addressAllocationIds}:{}}}:{},...a.securityPolicyName?{SecurityPolicyName:a.securityPolicyName}:{},...h?{LoggingRole:h}:{},Tags:[{Key:"Project",Value:a.slug},{Key:"Environment",Value:a.environment},{Key:"ManagedBy",Value:"ts-cloud"}]}};for(let[y,S]of Object.entries(a.users)){if(!/^[a-zA-Z0-9_.@-]{3,100}$/.test(y))throw Error(`sftp: invalid username ${y}`);if(!S.sshPublicKeys.length)throw Error(`sftp: user ${y} requires at least one SSH public key`);let b=wt(y),A=gr(S.homeDirectory,y),C=`${c}${b}User`,T=S.roleArn;if(!T){let v=`${c}${b}Role`,w;if(n.type==="efs")w=[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:DescribeMountTargets"],Resource:Sr(n.fileSystemId)}];else{let R=`arn:aws:s3:::${n.bucket}`;w=[{Effect:"Allow",Action:["s3:ListBucket","s3:GetBucketLocation"],Resource:R,Condition:{StringLike:{"s3:prefix":[A,`${A}/*`]}}},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:GetObjectVersion"],Resource:`${R}/${A}/*`}]}u[v]={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"transfer.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"SftpHomeDirectory",PolicyDocument:{Version:"2012-10-17",Statement:w}}]}},T={"Fn::GetAtt":[v,"Arn"]}}u[C]={Type:"AWS::Transfer::User",DependsOn:[l],Properties:{ServerId:{Ref:l},UserName:y,Role:T,HomeDirectoryType:"PATH",HomeDirectory:n.type==="efs"?fr(n.fileSystemId,A):`/${n.bucket}/${A}`,...n.type==="efs"?{PosixProfile:yr(y,S,n.posixProfile)}:{},SshPublicKeys:S.sshPublicKeys}}}return{resources:u,serverLogicalId:l,domain:i}}}class Te{static createBedrockRole(a,n){let{slug:i,environment:s,name:c,models:l=["*"],allowStreaming:u=!0}=n,h=c||r({slug:i,environment:s,resourceType:"bedrock-role"}),y=t(h),S=["bedrock:InvokeModel"];if(u)S.push("bedrock:InvokeModelWithResponseStream");let b=l.map((A)=>A==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${A}`);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:h,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:a},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:`${h}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:S,Resource:b}]}}],Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}},logicalId:y}}static createBedrockPolicy(a){let{slug:n,environment:i,name:s,models:c=["*"],allowInvoke:l=!0,allowStreaming:u=!0,allowAsync:h=!1}=a,y=s||r({slug:n,environment:i,resourceType:"bedrock-policy"}),S=t(y),b=[];if(l)b.push("bedrock:InvokeModel");if(u)b.push("bedrock:InvokeModelWithResponseStream");if(h)b.push("bedrock:InvokeModelAsync");let A=c.map((C)=>C==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${C}`);return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:y,PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"BedrockModelInvocation",Effect:"Allow",Action:b,Resource:A}]}}},logicalId:S}}static enableBedrockForLambda(a){return Te.createBedrockRole("lambda.amazonaws.com",a)}static enableBedrockForEcs(a){return Te.createBedrockRole("ecs-tasks.amazonaws.com",a)}static enableBedrockForEc2(a){return Te.createBedrockRole("ec2.amazonaws.com",a)}static addBedrockPermissions(a,n=["*"],i=!0){let s=["bedrock:InvokeModel"];if(i)s.push("bedrock:InvokeModelWithResponseStream");let c=n.map((l)=>l==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${l}`);if(!a.Properties.Policies)a.Properties.Policies=[];return a.Properties.Policies.push({PolicyName:"bedrock-permissions",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:s,Resource:c}]}}),a}static Models={Claude3_5_Sonnet:"anthropic.claude-3-5-sonnet-20241022-v2:0",Claude3_5_Haiku:"anthropic.claude-3-5-haiku-20241022-v1:0",Claude3_Opus:"anthropic.claude-3-opus-20240229-v1:0",Claude3_Sonnet:"anthropic.claude-3-sonnet-20240229-v1:0",Claude3_Haiku:"anthropic.claude-3-haiku-20240307-v1:0",TitanTextG1Express:"amazon.titan-text-express-v1",TitanTextG1Lite:"amazon.titan-text-lite-v1",TitanEmbedG1Text:"amazon.titan-embed-text-v1",TitanImageG1:"amazon.titan-image-generator-v1",JurassicUltra:"ai21.j2-ultra-v1",JurassicMid:"ai21.j2-mid-v1",CommandText:"cohere.command-text-v14",CommandLight:"cohere.command-light-text-v14",EmbedEnglish:"cohere.embed-english-v3",EmbedMultilingual:"cohere.embed-multilingual-v3",Llama3_2_1B:"meta.llama3-2-1b-instruct-v1:0",Llama3_2_3B:"meta.llama3-2-3b-instruct-v1:0",Llama3_2_11B:"meta.llama3-2-11b-instruct-v1:0",Llama3_2_90B:"meta.llama3-2-90b-instruct-v1:0",Llama3_1_8B:"meta.llama3-1-8b-instruct-v1:0",Llama3_1_70B:"meta.llama3-1-70b-instruct-v1:0",Llama3_1_405B:"meta.llama3-1-405b-instruct-v1:0",Mistral7B:"mistral.mistral-7b-instruct-v0:2",Mixtral8x7B:"mistral.mixtral-8x7b-instruct-v0:1",MistralLarge:"mistral.mistral-large-2402-v1:0",StableDiffusionXL:"stability.stable-diffusion-xl-v1"};static ModelGroups={AllClaude:["anthropic.claude-3-5-sonnet-20241022-v2:0","anthropic.claude-3-5-haiku-20241022-v1:0","anthropic.claude-3-opus-20240229-v1:0","anthropic.claude-3-sonnet-20240229-v1:0","anthropic.claude-3-haiku-20240307-v1:0"],AllTitan:["amazon.titan-text-express-v1","amazon.titan-text-lite-v1","amazon.titan-embed-text-v1","amazon.titan-image-generator-v1"],AllLlama:["meta.llama3-2-1b-instruct-v1:0","meta.llama3-2-3b-instruct-v1:0","meta.llama3-2-11b-instruct-v1:0","meta.llama3-2-90b-instruct-v1:0","meta.llama3-1-8b-instruct-v1:0","meta.llama3-1-70b-instruct-v1:0","meta.llama3-1-405b-instruct-v1:0"],TextModels:["anthropic.claude-3-5-sonnet-20241022-v2:0","anthropic.claude-3-5-haiku-20241022-v1:0","amazon.titan-text-express-v1","meta.llama3-2-11b-instruct-v1:0","mistral.mistral-7b-instruct-v0:2"],EmbeddingModels:["amazon.titan-embed-text-v1","cohere.embed-english-v3","cohere.embed-multilingual-v3"],ImageModels:["amazon.titan-image-generator-v1","stability.stable-diffusion-xl-v1"]}}class Ut{static createPostgres(a){return Ut.createRDSInstance("postgres","16.2",a)}static createMysql(a){return Ut.createRDSInstance("mysql","8.0.35",a)}static createRDSInstance(a,n,i){let{slug:s,environment:c,instanceClass:l="db.t3.micro",allocatedStorage:u=20,storageType:h="gp3",masterUsername:y="admin",masterPassword:S,databaseName:b,subnetIds:A,securityGroupIds:C,encrypted:T=!0,kmsKeyId:v,multiAz:w=!1,backupRetentionDays:R=7,publiclyAccessible:k=!1,enableCloudwatchLogs:W=!0,deletionProtection:P=!0}=i,V=r({slug:s,environment:c,resourceType:`${a}-db`}),B=t(V),j,J;if(A&&A.length>0){let X=r({slug:s,environment:c,resourceType:"db-subnet-group"});J=t(X),j={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupName:X,DBSubnetGroupDescription:`Subnet group for ${V}`,SubnetIds:A,Tags:[{Key:"Name",Value:X},{Key:"Environment",Value:c}]}}}let K={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:V,DBInstanceClass:l,Engine:a,EngineVersion:n,MasterUsername:y,MasterUserPassword:S,AllocatedStorage:u,StorageType:h,StorageEncrypted:T,MultiAZ:w,BackupRetentionPeriod:R,PubliclyAccessible:k,DeletionProtection:P,Tags:[{Key:"Name",Value:V},{Key:"Environment",Value:c}]}};if(b)K.Properties.DBName=b;if(v)K.Properties.KmsKeyId=v;if(J)K.Properties.DBSubnetGroupName=N.Ref(J);if(C&&C.length>0)K.Properties.VPCSecurityGroups=C;if(W)K.Properties.EnableCloudwatchLogsExports=a==="postgres"?["postgresql"]:["error","general","slowquery"];return{dbInstance:K,subnetGroup:j,logicalId:B,subnetGroupId:J}}static createReadReplica(a,n){let{slug:i,environment:s,instanceClass:c="db.t3.micro",securityGroupIds:l,publiclyAccessible:u=!1}=n,h=r({slug:i,environment:s,resourceType:"db-replica"}),y=t(h),S={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:h,DBInstanceClass:c,SourceDBInstanceIdentifier:N.Ref(a),PubliclyAccessible:u,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s},{Key:"Type",Value:"ReadReplica"}]}};if(l&&l.length>0)S.Properties.VPCSecurityGroups=l;return{replica:S,logicalId:y}}static createParameterGroup(a,n,i){let{slug:s,environment:c,parameters:l={}}=i,u=r({slug:s,environment:c,resourceType:"db-params"}),h=t(u),y=a==="postgres"?`postgres${n.split(".")[0]}`:`mysql${n.split(".")[0]}.${n.split(".")[1]}`;return{parameterGroup:{Type:"AWS::RDS::DBParameterGroup",Properties:{DBParameterGroupName:u,Description:`Parameter group for ${u}`,Family:y,Parameters:l,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:c}]}},logicalId:h}}static enableBackup(a,n=7){return a.Properties.BackupRetentionPeriod=n,a}static createTable(a){let{slug:n,environment:i,tableName:s,partitionKey:c,sortKey:l,billingMode:u="PAY_PER_REQUEST",readCapacity:h=5,writeCapacity:y=5,streamEnabled:S=!1,streamViewType:b="NEW_AND_OLD_IMAGES",encrypted:A=!0,kmsKeyId:C,pointInTimeRecovery:T=!0,ttlAttribute:v}=a,w=s||r({slug:n,environment:i,resourceType:"table"}),R=t(w),k=[{AttributeName:c.name,AttributeType:c.type}];if(l)k.push({AttributeName:l.name,AttributeType:l.type});let W=[{AttributeName:c.name,KeyType:"HASH"}];if(l)W.push({AttributeName:l.name,KeyType:"RANGE"});let P={Type:"AWS::DynamoDB::Table",Properties:{TableName:w,BillingMode:u,AttributeDefinitions:k,KeySchema:W,Tags:[{Key:"Name",Value:w},{Key:"Environment",Value:i}]}};if(u==="PROVISIONED")P.Properties.ProvisionedThroughput={ReadCapacityUnits:h,WriteCapacityUnits:y};if(S)P.Properties.StreamSpecification={StreamViewType:b};if(A)P.Properties.SSESpecification={SSEEnabled:!0,SSEType:C?"KMS":"AES256",KMSMasterKeyId:C};if(T)P.Properties.PointInTimeRecoverySpecification={PointInTimeRecoveryEnabled:!0};if(v)P.Properties.TimeToLiveSpecification={AttributeName:v,Enabled:!0};return{table:P,logicalId:R}}static addGlobalSecondaryIndex(a,n){let{indexName:i,partitionKey:s,sortKey:c,projectionType:l="ALL",nonKeyAttributes:u,readCapacity:h=5,writeCapacity:y=5}=n;if(!a.Properties.AttributeDefinitions.some((A)=>A.AttributeName===s.name))a.Properties.AttributeDefinitions.push({AttributeName:s.name,AttributeType:s.type});if(c&&!a.Properties.AttributeDefinitions.some((A)=>A.AttributeName===c.name))a.Properties.AttributeDefinitions.push({AttributeName:c.name,AttributeType:c.type});let S=[{AttributeName:s.name,KeyType:"HASH"}];if(c)S.push({AttributeName:c.name,KeyType:"RANGE"});let b={IndexName:i,KeySchema:S,Projection:{ProjectionType:l,NonKeyAttributes:l==="INCLUDE"?u:void 0},ProvisionedThroughput:void 0};if(a.Properties.BillingMode==="PROVISIONED")b.ProvisionedThroughput={ReadCapacityUnits:h,WriteCapacityUnits:y};if(!a.Properties.GlobalSecondaryIndexes)a.Properties.GlobalSecondaryIndexes=[];return a.Properties.GlobalSecondaryIndexes.push(b),a}static enableStreams(a,n="NEW_AND_OLD_IMAGES"){return a.Properties.StreamSpecification={StreamViewType:n},a}static InstanceClasses={T3_Micro:"db.t3.micro",T3_Small:"db.t3.small",T3_Medium:"db.t3.medium",T3_Large:"db.t3.large",T4g_Micro:"db.t4g.micro",T4g_Small:"db.t4g.small",T4g_Medium:"db.t4g.medium",M5_Large:"db.m5.large",M5_XLarge:"db.m5.xlarge",M5_2XLarge:"db.m5.2xlarge",R5_Large:"db.r5.large",R5_XLarge:"db.r5.xlarge",R5_2XLarge:"db.r5.2xlarge"}}class Ys{static createRedis(a){let{slug:n,environment:i,nodeType:s="cache.t3.micro",engineVersion:c="7.1",port:l=6379,subnetIds:u,securityGroupIds:h,numCacheClusters:y=2,automaticFailover:S=!0,multiAz:b=!0,clusterMode:A=!1,numNodeGroups:C=1,replicasPerNodeGroup:T=1,atRestEncryption:v=!0,transitEncryption:w=!0,authToken:R,kmsKeyId:k,snapshotRetentionDays:W=7,snapshotWindow:P,maintenanceWindow:V}=a,B=r({slug:n,environment:i,resourceType:"redis"}),j=t(B),J,K;if(u&&u.length>0){let te=r({slug:n,environment:i,resourceType:"cache-subnet-group"});K=t(te),J={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:te,Description:`Subnet group for ${B}`,SubnetIds:u,Tags:[{Key:"Name",Value:te},{Key:"Environment",Value:i}]}}}let X={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:B,ReplicationGroupDescription:`Redis cluster for ${n} ${i}`,Engine:"redis",EngineVersion:c,CacheNodeType:s,Port:l,AutomaticFailoverEnabled:S,MultiAZEnabled:b,AtRestEncryptionEnabled:v,TransitEncryptionEnabled:w,SnapshotRetentionLimit:W,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:B},{Key:"Environment",Value:i}]}};if(A)X.Properties.NumNodeGroups=C,X.Properties.ReplicasPerNodeGroup=T;else X.Properties.NumCacheClusters=y;if(R)X.Properties.AuthToken=R;if(k)X.Properties.KmsKeyId=k;if(K)X.Properties.CacheSubnetGroupName=N.Ref(K);if(h&&h.length>0)X.Properties.SecurityGroupIds=h;if(P)X.Properties.SnapshotWindow=P;if(V)X.Properties.PreferredMaintenanceWindow=V;return{replicationGroup:X,subnetGroup:J,logicalId:j,subnetGroupId:K}}static createMemcached(a){let{slug:n,environment:i,nodeType:s="cache.t3.micro",engineVersion:c="1.6.22",port:l=11211,numCacheNodes:u=2,subnetIds:h,securityGroupIds:y,azMode:S="cross-az",preferredAzs:b,maintenanceWindow:A}=a,C=r({slug:n,environment:i,resourceType:"memcached"}),T=t(C),v,w;if(h&&h.length>0){let k=r({slug:n,environment:i,resourceType:"cache-subnet-group"});w=t(k),v={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:k,Description:`Subnet group for ${C}`,SubnetIds:h,Tags:[{Key:"Name",Value:k},{Key:"Environment",Value:i}]}}}let R={Type:"AWS::ElastiCache::CacheCluster",Properties:{ClusterName:C,CacheNodeType:s,Engine:"memcached",EngineVersion:c,NumCacheNodes:u,Port:l,AZMode:S,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:C},{Key:"Environment",Value:i}]}};if(w)R.Properties.CacheSubnetGroupName=N.Ref(w);if(y&&y.length>0)R.Properties.VpcSecurityGroupIds=y;if(b&&b.length>0)R.Properties.PreferredAvailabilityZones=b;if(A)R.Properties.PreferredMaintenanceWindow=A;return{cluster:R,subnetGroup:v,logicalId:T,subnetGroupId:w}}static enableClusterMode(a,n=3,i=2){return delete a.Properties.NumCacheClusters,a.Properties.NumNodeGroups=n,a.Properties.ReplicasPerNodeGroup=i,a}static createRedisParameterGroup(a,n){let{slug:i,environment:s,parameters:c={}}=n,l=r({slug:i,environment:s,resourceType:"redis-params"}),u=t(l);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`redis${a.split(".")[0]}.x`,Description:`Parameter group for ${l}`,Properties:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s}]}},logicalId:u}}static createMemcachedParameterGroup(a,n){let{slug:i,environment:s,parameters:c={}}=n,l=r({slug:i,environment:s,resourceType:"memcached-params"}),u=t(l);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`memcached${a.split(".")[0]}.${a.split(".")[1]}`,Description:`Parameter group for ${l}`,Properties:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s}]}},logicalId:u}}static NodeTypes={T3_Micro:"cache.t3.micro",T3_Small:"cache.t3.small",T3_Medium:"cache.t3.medium",T4g_Micro:"cache.t4g.micro",T4g_Small:"cache.t4g.small",T4g_Medium:"cache.t4g.medium",M5_Large:"cache.m5.large",M5_XLarge:"cache.m5.xlarge",M5_2XLarge:"cache.m5.2xlarge",R5_Large:"cache.r5.large",R5_XLarge:"cache.r5.xlarge",R5_2XLarge:"cache.r5.2xlarge",R5_4XLarge:"cache.r5.4xlarge",R6g_Large:"cache.r6g.large",R6g_XLarge:"cache.r6g.xlarge",R6g_2XLarge:"cache.r6g.2xlarge"}}class Y{static createUser(a){let{slug:n,environment:i,userName:s,groups:c,managedPolicyArns:l}=a,u=s||r({slug:n,environment:i,resourceType:"user"}),h=t(u),y={Type:"AWS::IAM::User",Properties:{UserName:u,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:i}]}};if(c&&c.length>0)y.Properties.Groups=c;if(l&&l.length>0)y.Properties.ManagedPolicyArns=l;return{user:y,logicalId:h}}static createRole(a){let{slug:n,environment:i,roleName:s,servicePrincipal:c,awsPrincipal:l,managedPolicyArns:u}=a,h=s||r({slug:n,environment:i,resourceType:"role"}),y=t(h),S={};if(c)S.Service=c;if(l)S.AWS=l;let b={Type:"AWS::IAM::Role",Properties:{RoleName:h,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:S,Action:"sts:AssumeRole"}]},Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:i}]}};if(u&&u.length>0)b.Properties.ManagedPolicyArns=u;return{role:b,logicalId:y}}static createGroup(a){let{slug:n,environment:i,groupName:s,managedPolicyArns:c}=a,l=s||r({slug:n,environment:i,resourceType:"group"}),u=t(l),h={Type:"AWS::IAM::Group",Properties:{GroupName:l}};if(c&&c.length>0)h.Properties.ManagedPolicyArns=c;return{group:h,logicalId:u}}static createPolicy(a){let{slug:n,environment:i,policyName:s,description:c,statements:l}=a,u=s||r({slug:n,environment:i,resourceType:"policy"}),h=t(u),y=l.map((S)=>({Sid:S.sid,Effect:S.effect||"Allow",Action:S.actions,Resource:S.resources,Condition:S.conditions}));return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:u,Description:c||`Managed policy for ${u}`,PolicyDocument:{Version:"2012-10-17",Statement:y}}},logicalId:h}}static attachPolicyToRole(a,n){if(!a.Properties.ManagedPolicyArns)a.Properties.ManagedPolicyArns=[];if(!a.Properties.ManagedPolicyArns.includes(n))a.Properties.ManagedPolicyArns.push(n);return a}static attachPolicyToUser(a,n){if(!a.Properties.ManagedPolicyArns)a.Properties.ManagedPolicyArns=[];if(!a.Properties.ManagedPolicyArns.includes(n))a.Properties.ManagedPolicyArns.push(n);return a}static attachPolicyToGroup(a,n){if(!a.Properties.ManagedPolicyArns)a.Properties.ManagedPolicyArns=[];if(!a.Properties.ManagedPolicyArns.includes(n))a.Properties.ManagedPolicyArns.push(n);return a}static addInlinePolicyToRole(a,n,i){if(!a.Properties.Policies)a.Properties.Policies=[];let s=i.map((c)=>({Effect:c.effect||"Allow",Action:c.actions,Resource:c.resources}));return a.Properties.Policies.push({PolicyName:n,PolicyDocument:{Version:"2012-10-17",Statement:s}}),a}static addInlinePolicyToUser(a,n,i){if(!a.Properties.Policies)a.Properties.Policies=[];let s=i.map((c)=>({Effect:c.effect||"Allow",Action:c.actions,Resource:c.resources}));return a.Properties.Policies.push({PolicyName:n,PolicyDocument:{Version:"2012-10-17",Statement:s}}),a}static createAccessKey(a,n){let{slug:i,environment:s,status:c="Active"}=n,l=r({slug:i,environment:s,resourceType:"access-key"}),u=t(l);return{accessKey:{Type:"AWS::IAM::AccessKey",Properties:{UserName:N.Ref(a),Status:c}},logicalId:u}}static createInstanceProfile(a,n){let{slug:i,environment:s,profileName:c}=n,l=c||r({slug:i,environment:s,resourceType:"instance-profile"}),u=t(l);return{instanceProfile:{Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:l,Roles:[N.Ref(a)]}},logicalId:u}}static ManagedPolicies={AdministratorAccess:"arn:aws:iam::aws:policy/AdministratorAccess",PowerUserAccess:"arn:aws:iam::aws:policy/PowerUserAccess",ReadOnlyAccess:"arn:aws:iam::aws:policy/ReadOnlyAccess",S3FullAccess:"arn:aws:iam::aws:policy/AmazonS3FullAccess",S3ReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess",DynamoDBFullAccess:"arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess",DynamoDBReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonDynamoDBReadOnlyAccess",RDSFullAccess:"arn:aws:iam::aws:policy/AmazonRDSFullAccess",RDSReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonRDSReadOnlyAccess",LambdaFullAccess:"arn:aws:iam::aws:policy/AWSLambda_FullAccess",LambdaReadOnlyAccess:"arn:aws:iam::aws:policy/AWSLambda_ReadOnlyAccess",LambdaBasicExecutionRole:"arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",LambdaVPCAccessExecutionRole:"arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole",EC2FullAccess:"arn:aws:iam::aws:policy/AmazonEC2FullAccess",EC2ReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess",EC2ContainerRegistryReadOnly:"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly",EC2ContainerRegistryPowerUser:"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPowerUser",ECSTaskExecutionRole:"arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy",ECSFullAccess:"arn:aws:iam::aws:policy/AmazonECS_FullAccess",CloudWatchFullAccess:"arn:aws:iam::aws:policy/CloudWatchFullAccess",CloudWatchLogsFullAccess:"arn:aws:iam::aws:policy/CloudWatchLogsFullAccess",SESFullAccess:"arn:aws:iam::aws:policy/AmazonSESFullAccess",SNSFullAccess:"arn:aws:iam::aws:policy/AmazonSNSFullAccess",SQSFullAccess:"arn:aws:iam::aws:policy/AmazonSQSFullAccess",SecretsManagerReadWrite:"arn:aws:iam::aws:policy/SecretsManagerReadWrite"};static ServicePrincipals={Lambda:"lambda.amazonaws.com",EC2:"ec2.amazonaws.com",ECS:"ecs.amazonaws.com",ECSTaskExecution:"ecs-tasks.amazonaws.com",APIGateway:"apigateway.amazonaws.com",Events:"events.amazonaws.com",States:"states.amazonaws.com",CodeBuild:"codebuild.amazonaws.com",CodeDeploy:"codedeploy.amazonaws.com",CloudFormation:"cloudformation.amazonaws.com"};static createCiCdUser(a){let{slug:n,environment:i,permissions:s,createAccessKey:c=!0}=a,l={},u=[];if(s.s3Buckets&&s.s3Buckets.length>0)u.push({sid:"S3Access",actions:["s3:GetBucketLocation","s3:ListBucket","s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucketMultipartUploads","s3:AbortMultipartUpload"],resources:[...s.s3Buckets,...s.s3Buckets.map((T)=>`${T}/*`)]});if(s.cloudFrontDistributions&&s.cloudFrontDistributions.length>0)u.push({sid:"CloudFrontAccess",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations","cloudfront:GetDistribution"],resources:s.cloudFrontDistributions});if(s.ecrRepositories&&s.ecrRepositories.length>0)u.push({sid:"ECRAccess",actions:["ecr:GetAuthorizationToken","ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:GetRepositoryPolicy","ecr:DescribeRepositories","ecr:ListImages","ecr:DescribeImages","ecr:BatchGetImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:PutImage"],resources:s.ecrRepositories}),u.push({sid:"ECRLogin",actions:["ecr:GetAuthorizationToken"],resources:"*"});if(s.ecsServices&&s.ecsServices.length>0)u.push({sid:"ECSAccess",actions:["ecs:DescribeServices","ecs:DescribeTaskDefinition","ecs:DescribeTasks","ecs:ListTasks","ecs:RegisterTaskDefinition","ecs:UpdateService","ecs:RunTask","ecs:StopTask"],resources:s.ecsServices}),u.push({sid:"ECSTaskDefinitions",actions:["ecs:RegisterTaskDefinition","ecs:DeregisterTaskDefinition"],resources:"*"}),u.push({sid:"ECSPassRole",actions:["iam:PassRole"],resources:"*",conditions:{StringLike:{"iam:PassedToService":"ecs-tasks.amazonaws.com"}}});if(s.cloudFormationStacks&&s.cloudFormationStacks.length>0)u.push({sid:"CloudFormationAccess",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:DescribeStackResources","cloudformation:GetTemplate","cloudformation:ListStackResources","cloudformation:ValidateTemplate"],resources:s.cloudFormationStacks});if(s.lambdaFunctions&&s.lambdaFunctions.length>0)u.push({sid:"LambdaAccess",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion","lambda:UpdateAlias","lambda:CreateAlias"],resources:s.lambdaFunctions});if(s.secretsManagerSecrets&&s.secretsManagerSecrets.length>0)u.push({sid:"SecretsManagerAccess",actions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],resources:s.secretsManagerSecrets});let{policy:h,logicalId:y}=Y.createPolicy({slug:n,environment:i,policyName:r({slug:n,environment:i,resourceType:"cicd-policy"}),description:`CI/CD deployment policy for ${n} (${i})`,statements:u});l[y]=h;let{user:S,logicalId:b}=Y.createUser({slug:n,environment:i,userName:r({slug:n,environment:i,resourceType:"cicd-user"}),managedPolicyArns:[N.Ref(y)]});l[b]=S;let A,C;if(c){let T=Y.createAccessKey(b,{slug:n,environment:i});A=T.accessKey,C=T.logicalId,l[C]=A}return{user:S,accessKey:A,policy:h,userLogicalId:b,accessKeyLogicalId:C,policyLogicalId:y,resources:l}}static createCrossAccountRole(a){let{slug:n,environment:i,trustedAccountIds:s,externalId:c,permissions:l,maxSessionDuration:u=3600}=a,h={},{policy:y,logicalId:S}=Y.createPolicy({slug:n,environment:i,policyName:r({slug:n,environment:i,resourceType:"cross-account-policy"}),description:`Cross-account access policy for ${n} (${i})`,statements:l});h[S]=y;let b=r({slug:n,environment:i,resourceType:"cross-account-role"}),A=t(b),C={};if(c)C.StringEquals={"sts:ExternalId":c};let T={Type:"AWS::IAM::Role",Properties:{RoleName:b,MaxSessionDuration:u,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:s.map((v)=>`arn:aws:iam::${v}:root`)},Action:"sts:AssumeRole",...Object.keys(C).length>0?{Condition:C}:{}}]},ManagedPolicyArns:[N.Ref(S)],Tags:[{Key:"Name",Value:b},{Key:"Environment",Value:i},{Key:"Purpose",Value:"Cross-Account Access"}]}};return h[A]=T,{role:T,policy:y,roleLogicalId:A,policyLogicalId:S,resources:h}}static createCliUser(a){let{slug:n,environment:i,permissions:s="readonly"}=a,c={},l=[],u=[];switch(s){case"readonly":u=[Y.ManagedPolicies.ReadOnlyAccess];break;case"deploy":l=[{sid:"S3Deploy",actions:["s3:*"],resources:"*"},{sid:"CloudFrontDeploy",actions:["cloudfront:*"],resources:"*"},{sid:"ECSDeploy",actions:["ecs:*"],resources:"*"},{sid:"ECRDeploy",actions:["ecr:*"],resources:"*"},{sid:"LambdaDeploy",actions:["lambda:*"],resources:"*"},{sid:"CloudFormationDeploy",actions:["cloudformation:*"],resources:"*"},{sid:"IAMPassRole",actions:["iam:PassRole"],resources:"*"}];break;case"admin":u=[Y.ManagedPolicies.AdministratorAccess];break}let h,y;if(l.length>0){let T=Y.createPolicy({slug:n,environment:i,policyName:r({slug:n,environment:i,resourceType:"cli-policy"}),description:`CLI access policy for ${n} (${i})`,statements:l});h=T.policy,y=T.logicalId,c[y]=h,u=[N.Ref(y)]}let{user:S,logicalId:b}=Y.createUser({slug:n,environment:i,userName:r({slug:n,environment:i,resourceType:"cli-user"}),managedPolicyArns:u});c[b]=S;let{accessKey:A,logicalId:C}=Y.createAccessKey(b,{slug:n,environment:i});return c[C]=A,{user:S,accessKey:A,policy:h,userLogicalId:b,accessKeyLogicalId:C,policyLogicalId:y,resources:c}}static CiCdPolicies={s3Deployment:(a)=>[{sid:"S3ListBuckets",actions:["s3:ListBucket","s3:GetBucketLocation"],resources:a},{sid:"S3Objects",actions:["s3:GetObject","s3:PutObject","s3:DeleteObject"],resources:a.map((n)=>`${n}/*`)}],cloudFrontInvalidation:(a)=>[{sid:"CloudFrontInvalidation",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations"],resources:a}],ecsDeployment:()=>[{sid:"ECSServices",actions:["ecs:DescribeServices","ecs:UpdateService","ecs:DescribeTaskDefinition","ecs:RegisterTaskDefinition"],resources:"*"},{sid:"ECSPassRole",actions:["iam:PassRole"],resources:"*",conditions:{StringLike:{"iam:PassedToService":"ecs-tasks.amazonaws.com"}}}],ecrPush:(a)=>[{sid:"ECRAuth",actions:["ecr:GetAuthorizationToken"],resources:"*"},{sid:"ECRPush",actions:["ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:PutImage"],resources:a}],lambdaDeployment:(a)=>[{sid:"LambdaDeploy",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion"],resources:a}],cloudFormationDeployment:(a)=>[{sid:"CloudFormationDeploy",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate"],resources:a}]}}class hd{static createRestApi(a){let{slug:n,environment:i,name:s,description:c,endpointType:l="REGIONAL",binaryMediaTypes:u,compressionSize:h}=a,y=s||r({slug:n,environment:i,resourceType:"rest-api"}),S=t(y),b={Type:"AWS::ApiGateway::RestApi",Properties:{Name:y,Description:c||`REST API for ${n} ${i}`,EndpointConfiguration:{Types:[l]},Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:i}]}};if(u&&u.length>0)b.Properties.BinaryMediaTypes=u;if(h!==void 0)b.Properties.MinimumCompressionSize=h;return{restApi:b,logicalId:S}}static createHttpApi(a){let{slug:n,environment:i,name:s,description:c,corsEnabled:l=!0,corsOrigins:u=["*"],corsMethods:h=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],corsHeaders:y=["*"],corsMaxAge:S=86400,corsAllowCredentials:b=!1}=a,A=s||r({slug:n,environment:i,resourceType:"http-api"}),C=t(A),T={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:A,Description:c||`HTTP API for ${n} ${i}`,ProtocolType:"HTTP",Tags:{Name:A,Environment:i}}};if(l)T.Properties.CorsConfiguration={AllowOrigins:u,AllowMethods:h,AllowHeaders:y,MaxAge:S,AllowCredentials:b};return{httpApi:T,logicalId:C}}static createWebSocketApi(a){let{slug:n,environment:i,name:s,description:c}=a,l=s||r({slug:n,environment:i,resourceType:"ws-api"}),u=t(l);return{webSocketApi:{Type:"AWS::ApiGatewayV2::Api",Properties:{Name:l,Description:c||`WebSocket API for ${n} ${i}`,ProtocolType:"WEBSOCKET",Tags:{Name:l,Environment:i}}},logicalId:u}}static createDeployment(a,n){let{slug:i,environment:s,description:c}=n,l=r({slug:i,environment:s,resourceType:"api-deployment"}),u=t(l);return{deployment:{Type:"AWS::ApiGateway::Deployment",Properties:{RestApiId:N.Ref(a),Description:c||`Deployment for ${l}`}},logicalId:u}}static createStage(a,n,i){let{slug:s,environment:c,stageName:l,description:u,cacheEnabled:h=!1,cacheSize:y="0.5",variables:S,throttling:b}=i,A=r({slug:s,environment:c,resourceType:"api-stage"}),C=t(A),T={Type:"AWS::ApiGateway::Stage",Properties:{StageName:l||c,RestApiId:N.Ref(a),DeploymentId:N.Ref(n),Description:u,CacheClusterEnabled:h,Tags:[{Key:"Name",Value:A},{Key:"Environment",Value:c}]}};if(h)T.Properties.CacheClusterSize=y;if(S)T.Properties.Variables=S;if(b)T.Properties.MethodSettings=[{HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:b.burstLimit,ThrottlingRateLimit:b.rateLimit}];return{stage:T,logicalId:C}}static createAuthorizer(a,n){let{slug:i,environment:s,name:c,type:l,functionArn:u,identitySource:h,userPoolArns:y,ttl:S=300}=n,b=c||r({slug:i,environment:s,resourceType:"api-authorizer"}),A=t(b),C={Type:"AWS::ApiGateway::Authorizer",Properties:{Name:b,Type:l,RestApiId:N.Ref(a),AuthorizerResultTtlInSeconds:S}};if(l==="TOKEN"||l==="REQUEST"){if(!u)throw Error("Lambda authorizer requires functionArn");C.Properties.AuthorizerUri=u,C.Properties.IdentitySource=h||"method.request.header.Authorization"}if(l==="COGNITO_USER_POOLS"){if(!y||y.length===0)throw Error("Cognito authorizer requires userPoolArns");C.Properties.ProviderARNs=y,C.Properties.IdentitySource=h||"method.request.header.Authorization"}return{authorizer:C,logicalId:A}}static setCors(a,n={}){let{origins:i=["*"],methods:s=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],headers:c=["*"],maxAge:l=86400,allowCredentials:u=!1}=n;return a.Properties.CorsConfiguration={AllowOrigins:i,AllowMethods:s,AllowHeaders:c,MaxAge:l,AllowCredentials:u},a}static addThrottling(a,n=5000,i=1e4){if(!a.Properties.MethodSettings)a.Properties.MethodSettings=[];return a.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:n,ThrottlingRateLimit:i}),a}static enableCaching(a,n="0.5",i=300){if(a.Properties.CacheClusterEnabled=!0,a.Properties.CacheClusterSize=n,!a.Properties.MethodSettings)a.Properties.MethodSettings=[];return a.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",CachingEnabled:!0,CacheTtlInSeconds:i}),a}static CacheSizes={Small:"0.5",Medium:"1.6",Large:"6.1",XLarge:"13.5",XXLarge:"28.4",XXXLarge:"58.2",Huge:"118",Massive:"237"};static ThrottlingPresets={Light:{burstLimit:100,rateLimit:50},Medium:{burstLimit:500,rateLimit:250},Heavy:{burstLimit:2000,rateLimit:1000},Default:{burstLimit:5000,rateLimit:1e4}}}class Z{static createTopic(a){let{slug:n,environment:i,topicName:s,displayName:c,encrypted:l=!1,kmsKeyId:u}=a,h=s||r({slug:n,environment:i,resourceType:"topic"}),y=t(h),S={Type:"AWS::SNS::Topic",Properties:{TopicName:h,DisplayName:c||h,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:i}]}};if(l&&u)S.Properties.KmsMasterKeyId=u;return{topic:S,logicalId:y}}static subscribe(a,n){let{slug:i,environment:s,protocol:c,endpoint:l,filterPolicy:u,rawMessageDelivery:h=!1}=n,y=r({slug:i,environment:s,resourceType:"subscription"}),S=l.replace(/[^a-zA-Z0-9]/g,""),b=S.length>12?S.slice(-12):S,A=t(`${y}-${c}-${b}`),C={Type:"AWS::SNS::Subscription",Properties:{TopicArn:N.Ref(a),Protocol:c,Endpoint:l,RawMessageDelivery:h}};if(u)C.Properties.FilterPolicy=u;return{subscription:C,logicalId:A}}static subscribeEmail(a,n,i){return Z.subscribe(a,{...i,protocol:"email",endpoint:n})}static subscribeLambda(a,n,i){return Z.subscribe(a,{...i,protocol:"lambda",endpoint:n,rawMessageDelivery:!0})}static subscribeSqs(a,n,i){return Z.subscribe(a,{...i,protocol:"sqs",endpoint:n})}static subscribeHttp(a,n,i){let s=n.startsWith("https://")?"https":"http";return Z.subscribe(a,{...i,protocol:s,endpoint:n})}static subscribeSms(a,n,i){return Z.subscribe(a,{...i,protocol:"sms",endpoint:n})}static setTopicPolicy(a,n){let{slug:i,environment:s,allowedPrincipals:c,allowedServices:l,actions:u="SNS:Publish"}=n,h=r({slug:i,environment:s,resourceType:"topic-policy"}),y=t(h),S={};if(c)S.AWS=c;if(l)S.Service=l;return{policy:{Type:"AWS::SNS::TopicPolicy",Properties:{Topics:[N.Ref(a)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:S,Action:u,Resource:N.Ref(a)}]}}},logicalId:y}}static allowCloudWatchAlarms(a,n){return Z.setTopicPolicy(a,{...n,allowedServices:"cloudwatch.amazonaws.com",actions:"SNS:Publish"})}static allowEventBridge(a,n){return Z.setTopicPolicy(a,{...n,allowedServices:"events.amazonaws.com",actions:"SNS:Publish"})}static allowS3(a,n){return Z.setTopicPolicy(a,{...n,allowedServices:"s3.amazonaws.com",actions:"SNS:Publish"})}static enableEncryption(a,n){if(!a.Properties)a.Properties={};return a.Properties.KmsMasterKeyId=n,a}static addInlineSubscription(a,n,i){if(!a.Properties)a.Properties={};if(!a.Properties.Subscription)a.Properties.Subscription=[];return a.Properties.Subscription.push({Protocol:n,Endpoint:i}),a}static FilterPolicies={eventType:(a)=>({eventType:a}),status:(a)=>({status:a}),numericRange:(a,n,i)=>({[a]:[{numeric:[">=",n,"<=",i]}]}),prefix:(a,n)=>({[a]:[{prefix:n}]}),and:(...a)=>Object.assign({},...a),exists:(a,n)=>({[a]:[{exists:n}]})};static UseCases={createAlertTopic:(a)=>Z.createTopic({...a,topicName:a.topicName||`${a.slug}-${a.environment}-alerts`,displayName:a.displayName||"Alert Notifications"}),createEventFanout:(a)=>Z.createTopic({...a,topicName:a.topicName||`${a.slug}-${a.environment}-events`,displayName:a.displayName||"Event Fanout"}),createNotificationTopic:(a)=>Z.createTopic({...a,topicName:a.topicName||`${a.slug}-${a.environment}-notifications`,displayName:a.displayName||"User Notifications"})}}class Cf{static createStateMachine(a){let{slug:n,environment:i,stateMachineName:s,type:c="STANDARD",definition:l,roleArn:u,loggingConfiguration:h,tracingConfiguration:y}=a,S=s||r({slug:n,environment:i,resourceType:"state-machine"}),b=t(S),A,C,T;if(u)T=u;else{let w=r({slug:n,environment:i,resourceType:"state-machine-role"});C=t(w),A={Type:"AWS::IAM::Role",Properties:{RoleName:w,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"states.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/CloudWatchLogsFullAccess"],Tags:[{Key:"Name",Value:w},{Key:"Environment",Value:i}]}},T=N.GetAtt(C,"Arn")}let v={Type:"AWS::StepFunctions::StateMachine",Properties:{StateMachineName:S,StateMachineType:c,DefinitionString:JSON.stringify(l),RoleArn:T,Tags:[{Key:"Name",Value:S},{Key:"Environment",Value:i}]}};if(h)v.Properties.LoggingConfiguration={Level:h.level,IncludeExecutionData:h.includeExecutionData,Destinations:h.destinations?.map((w)=>({CloudWatchLogsLogGroup:{LogGroupArn:w}}))};if(y)v.Properties.TracingConfiguration={Enabled:y.enabled};return{stateMachine:v,logicalId:b,role:A,roleLogicalId:C}}static createLambdaTask(a,n){return{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Parameters:{FunctionName:a,Payload:n?.parameters||{"Input.$":"$"}},ResultPath:n?.resultPath,Retry:n?.retry,Catch:n?.catch,Next:n?.next,End:n?.end}}static createDynamoDBTask(a,n,i,s){return{Type:"Task",Resource:{GetItem:"arn:aws:states:::dynamodb:getItem",PutItem:"arn:aws:states:::dynamodb:putItem",UpdateItem:"arn:aws:states:::dynamodb:updateItem",DeleteItem:"arn:aws:states:::dynamodb:deleteItem"}[a],Parameters:{TableName:n,...i},ResultPath:s?.resultPath,Retry:s?.retry,Catch:s?.catch,Next:s?.next,End:s?.end}}static createSNSPublishTask(a,n,i){return{Type:"Task",Resource:"arn:aws:states:::sns:publish",Parameters:{TopicArn:a,Message:n},ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createSQSSendMessageTask(a,n,i){return{Type:"Task",Resource:"arn:aws:states:::sqs:sendMessage",Parameters:{QueueUrl:a,MessageBody:n},ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createPassState(a){return{Type:"Pass",Result:a?.result,ResultPath:a?.resultPath,Parameters:a?.parameters,Next:a?.next,End:a?.end}}static createWaitState(a){return{Type:"Wait",Seconds:a.seconds,Timestamp:a.timestamp,SecondsPath:a.secondsPath,TimestampPath:a.timestampPath,Next:a.next,End:a.end}}static createChoiceState(a,n){return{Type:"Choice",Choices:a,Default:n}}static createParallelState(a,n){return{Type:"Parallel",Branches:a,ResultPath:n?.resultPath,Retry:n?.retry,Catch:n?.catch,Next:n?.next,End:n?.end}}static createMapState(a,n){return{Type:"Map",ItemsPath:n?.itemsPath||"$.items",Iterator:a,MaxConcurrency:n?.maxConcurrency,ResultPath:n?.resultPath,Retry:n?.retry,Catch:n?.catch,Next:n?.next,End:n?.end}}static createSucceedState(){return{Type:"Succeed"}}static createFailState(a,n){return{Type:"Fail",Error:a,Cause:n}}static RetryPolicies={standard:()=>({ErrorEquals:["States.ALL"],IntervalSeconds:2,MaxAttempts:3,BackoffRate:2}),aggressive:()=>({ErrorEquals:["States.TaskFailed","States.Timeout"],IntervalSeconds:1,MaxAttempts:5,BackoffRate:1.5}),custom:(a,n,i,s)=>({ErrorEquals:a,IntervalSeconds:n,MaxAttempts:i,BackoffRate:s})};static CatchPolicies={all:(a,n)=>({ErrorEquals:["States.ALL"],Next:a,ResultPath:n||"$.error"}),specific:(a,n,i)=>({ErrorEquals:a,Next:n,ResultPath:i||"$.error"})};static Patterns={sequential:(a,n,i)=>{let s={};return i.forEach((c,l)=>{let u=l===i.length-1;s[c.name]={...c.state,Next:u?void 0:i[l+1].name,End:u}}),{Comment:"Sequential workflow",StartAt:i[0].name,States:s}},fanout:(a,n,i)=>({Comment:"Fan-out workflow",StartAt:"Parallel",States:{Parallel:{Type:"Parallel",Branches:i.map((s)=>s.definition),End:!0}}}),map:(a,n,i,s)=>({Comment:"Map workflow",StartAt:"Map",States:{Map:{Type:"Map",ItemsPath:"$.items",Iterator:i,MaxConcurrency:s,End:!0}}}),withErrorHandling:(a,n,i,s)=>({Comment:"Workflow with error handling",StartAt:"Main",States:{Main:{...i,Catch:[{ErrorEquals:["States.ALL"],Next:"ErrorHandler"}],Next:"Success"},ErrorHandler:s,Success:{Type:"Succeed"}}})}}class Zs{static createAlarm(a){let{slug:n,environment:i,alarmName:s,metricName:c,namespace:l,statistic:u="Average",period:h=300,evaluationPeriods:y=1,threshold:S,comparisonOperator:b,treatMissingData:A="notBreaching",actionsEnabled:C=!0,alarmActions:T,okActions:v,insufficientDataActions:w,dimensions:R,unit:k,datapointsToAlarm:W}=a,P=s||r({slug:n,environment:i,resourceType:"alarm"}),V=t(P),B={Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:P,MetricName:c,Namespace:l,Statistic:u,Period:h,EvaluationPeriods:y,Threshold:S,ComparisonOperator:b,TreatMissingData:A,ActionsEnabled:C}};if(T&&T.length>0)B.Properties.AlarmActions=T;if(v&&v.length>0)B.Properties.OKActions=v;if(w&&w.length>0)B.Properties.InsufficientDataActions=w;if(R)B.Properties.Dimensions=Object.entries(R).map(([j,J])=>({Name:j,Value:J}));if(k)B.Properties.Unit=k;if(W!==void 0)B.Properties.DatapointsToAlarm=W;return{alarm:B,logicalId:V}}static createCompositeAlarm(a){let{slug:n,environment:i,alarmName:s,alarmRule:c,actionsEnabled:l=!0,alarmActions:u,okActions:h,insufficientDataActions:y}=a,S=s||r({slug:n,environment:i,resourceType:"composite-alarm"}),b=t(S),A={Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:S,AlarmRule:c,ActionsEnabled:l}};if(u&&u.length>0)A.Properties.AlarmActions=u;if(h&&h.length>0)A.Properties.OKActions=h;if(y&&y.length>0)A.Properties.InsufficientDataActions=y;return{alarm:A,logicalId:b}}static createDashboard(a){let{slug:n,environment:i,dashboardName:s,widgets:c}=a,l=s||r({slug:n,environment:i,resourceType:"dashboard"}),u=t(l),h={widgets:c.map((y)=>({type:y.type,x:y.x,y:y.y,width:y.width,height:y.height,properties:y.properties}))};return{dashboard:{Type:"AWS::CloudWatch::Dashboard",Properties:{DashboardName:l,DashboardBody:JSON.stringify(h)}},logicalId:u}}static createLogGroup(a){let{slug:n,environment:i,logGroupName:s,retentionInDays:c,kmsKeyId:l}=a,u=s||r({slug:n,environment:i,resourceType:"log-group"}),h=t(u),y={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:u}};if(c!==void 0)y.Properties.RetentionInDays=c;if(l)y.Properties.KmsKeyId=l;return{logGroup:y,logicalId:h}}static createLogStream(a,n){let{slug:i,environment:s,logStreamName:c}=n,l=c||r({slug:i,environment:s,resourceType:"log-stream"}),u=t(l);return{logStream:{Type:"AWS::Logs::LogStream",Properties:{LogGroupName:N.Ref(a),LogStreamName:l}},logicalId:u}}static createMetricFilter(a,n){let{slug:i,environment:s,filterName:c,filterPattern:l,metricTransformations:u}=n,h=c||r({slug:i,environment:s,resourceType:"metric-filter"}),y=t(h);return{metricFilter:{Type:"AWS::Logs::MetricFilter",Properties:{LogGroupName:N.Ref(a),FilterPattern:l,MetricTransformations:u.map((S)=>({MetricName:S.metricName,MetricNamespace:S.metricNamespace,MetricValue:S.metricValue,DefaultValue:S.defaultValue,Unit:S.unit}))}},logicalId:y}}static AlarmTypes={highCpu:(a,n,i,s=80,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-high-cpu`,metricName:"CPUUtilization",namespace:"AWS/EC2",statistic:"Average",period:300,evaluationPeriods:2,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:i},alarmActions:c?[c]:void 0}),highMemory:(a,n,i,s=80,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-high-memory`,metricName:"MemoryUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:i},alarmActions:c?[c]:void 0}),highDisk:(a,n,i,s=80,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-high-disk`,metricName:"DiskSpaceUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:i,Filesystem:"/dev/xvda1",MountPath:"/"},alarmActions:c?[c]:void 0}),lambdaErrors:(a,n,i,s=5,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-lambda-errors`,metricName:"Errors",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:i},alarmActions:c?[c]:void 0}),lambdaThrottles:(a,n,i,s=10,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-lambda-throttles`,metricName:"Throttles",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:i},alarmActions:c?[c]:void 0}),apiGateway5xxErrors:(a,n,i,s=10,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-api-5xx-errors`,metricName:"5XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:i},alarmActions:c?[c]:void 0}),apiGateway4xxErrors:(a,n,i,s=50,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-api-4xx-errors`,metricName:"4XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:2,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:i},alarmActions:c?[c]:void 0}),dynamoDBThrottles:(a,n,i,s=5,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-dynamodb-throttles`,metricName:"UserErrors",namespace:"AWS/DynamoDB",statistic:"Sum",period:300,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{TableName:i},alarmActions:c?[c]:void 0}),rdsCpu:(a,n,i,s=80,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-rds-cpu`,metricName:"CPUUtilization",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:2,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{DBInstanceIdentifier:i},alarmActions:c?[c]:void 0}),rdsFreeStorage:(a,n,i,s=5368709120,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-rds-storage`,metricName:"FreeStorageSpace",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:1,threshold:s,comparisonOperator:"LessThanThreshold",dimensions:{DBInstanceIdentifier:i},alarmActions:c?[c]:void 0,unit:"Bytes"}),sqsQueueDepth:(a,n,i,s=100,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-sqs-depth`,metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",statistic:"Average",period:300,evaluationPeriods:2,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{QueueName:i},alarmActions:c?[c]:void 0}),albUnhealthyTargets:(a,n,i,s,c=1,l)=>({slug:a,environment:n,alarmName:`${a}-${n}-alb-unhealthy`,metricName:"UnHealthyHostCount",namespace:"AWS/ApplicationELB",statistic:"Average",period:300,evaluationPeriods:2,threshold:c,comparisonOperator:"GreaterThanThreshold",dimensions:{LoadBalancer:i,TargetGroup:s},alarmActions:l?[l]:void 0}),sesBounceRate:(a,n,i=5,s)=>({slug:a,environment:n,alarmName:`${a}-${n}-ses-bounce-rate`,metricName:"Reputation.BounceRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:i/100,comparisonOperator:"GreaterThanThreshold",alarmActions:s?[s]:void 0}),sesComplaintRate:(a,n,i=0.1,s)=>({slug:a,environment:n,alarmName:`${a}-${n}-ses-complaint-rate`,metricName:"Reputation.ComplaintRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:i/100,comparisonOperator:"GreaterThanThreshold",alarmActions:s?[s]:void 0}),smsDeliveryFailure:(a,n,i,s=10,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-sms-delivery-failure`,metricName:"DirectSendMessagePermanentFailure",namespace:"AWS/Pinpoint",statistic:"Sum",period:300,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{ApplicationId:i},alarmActions:c?[c]:void 0}),smsSpendLimit:(a,n,i=100,s)=>({slug:a,environment:n,alarmName:`${a}-${n}-sms-spend-limit`,metricName:"DirectSendMessageSpend",namespace:"AWS/Pinpoint",statistic:"Sum",period:86400,evaluationPeriods:1,threshold:i,comparisonOperator:"GreaterThanThreshold",alarmActions:s?[s]:void 0}),connectMissedCalls:(a,n,i,s=5,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-connect-missed-calls`,metricName:"MissedCalls",namespace:"AWS/Connect",statistic:"Sum",period:3600,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:i},alarmActions:c?[c]:void 0})};static DashboardWidgets={metric:(a,n,i,s,c,l)=>({type:"metric",x:a,y:n,width:i,height:s,properties:{metrics:c,title:l||"Metrics",region:"us-east-1",period:300}}),text:(a,n,i,s,c)=>({type:"text",x:a,y:n,width:i,height:s,properties:{markdown:c}}),log:(a,n,i,s,c,l)=>({type:"log",x:a,y:n,width:i,height:s,properties:{query:`SOURCE '${c.join("' | SOURCE '")}'
2309
+ `;class F{static LambdaCode={send:wa,receive:mr,deliveryStatus:dr};static createPinpointApp(a){return{[`${a.slug}PinpointApp`]:{Type:"AWS::Pinpoint::App",Properties:{Name:a.name||`${a.slug}-sms`}}}}static createSmsChannel(a){let n={ApplicationId:a.applicationId,Enabled:a.enabled!==!1};if(a.senderId)n.SenderId=a.senderId;if(a.shortCode)n.ShortCode=a.shortCode;return{[`${a.slug}SmsChannel`]:{Type:"AWS::Pinpoint::SMSChannel",Properties:n}}}static createSmsLambdaRole(a){return{[`${a.slug}SmsLambdaRole`]:{Type:"AWS::IAM::Role",Properties:{RoleName:`${a.slug}-sms-lambda-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],Policies:[{PolicyName:"SmsLambdaPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["mobiletargeting:SendMessages","mobiletargeting:GetSmsChannel"],Resource:"*"},{Effect:"Allow",Action:["sns:Publish"],Resource:"*"},{Effect:"Allow",Action:["dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:GetItem","dynamodb:DeleteItem"],Resource:"*"}]}}]}}}}static createSendLambda(a){return{[`${a.slug}SmsSendLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-sms-send`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:F.LambdaCode.send},Environment:{Variables:{PINPOINT_APP_ID:a.pinpointAppId,MESSAGE_LOG_TABLE:a.messageLogTable||"",SMS_SENDER_ID:a.senderId||"",SMS_ORIGINATION_NUMBER:a.originationNumber||""}}}}}}static createReceiveLambda(a){return{[`${a.slug}SmsReceiveLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-sms-receive`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:F.LambdaCode.receive},Environment:{Variables:{OPT_OUT_TABLE:a.optOutTable||"",MESSAGE_LOG_TABLE:a.messageLogTable||"",NOTIFICATION_TOPIC_ARN:a.notificationTopicArn||"",WEBHOOK_URL:a.webhookUrl||""}}}}}}static createDeliveryStatusLambda(a){return{[`${a.slug}SmsDeliveryStatusLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-sms-delivery-status`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:F.LambdaCode.deliveryStatus},Environment:{Variables:{MESSAGE_LOG_TABLE:a.messageLogTable||"",NOTIFICATION_TOPIC_ARN:a.notificationTopicArn||"",WEBHOOK_URL:a.webhookUrl||""}}}}}}static createMessageLogTable(a){return{[`${a.slug}SmsMessageLogTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${a.slug}-sms-messages`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createOptOutTable(a){return{[`${a.slug}SmsOptOutTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${a.slug}-sms-optouts`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}]}}}}static createNotificationTopic(a){return{[`${a.slug}SmsNotificationTopic`]:{Type:"AWS::SNS::Topic",Properties:{TopicName:`${a.slug}-sms-notifications`}}}}static createCompleteSetup(a){let n={},i={};Object.assign(n,F.createPinpointApp({slug:a.slug})),Object.assign(n,F.createSmsChannel({slug:a.slug,applicationId:{Ref:`${a.slug}PinpointApp`},senderId:a.senderId})),Object.assign(n,F.createSmsLambdaRole({slug:a.slug})),Object.assign(n,F.createMessageLogTable({slug:a.slug})),Object.assign(n,F.createOptOutTable({slug:a.slug})),Object.assign(n,F.createNotificationTopic({slug:a.slug}));let s={"Fn::GetAtt":[`${a.slug}SmsLambdaRole`,"Arn"]},c={Ref:`${a.slug}PinpointApp`},l={Ref:`${a.slug}SmsMessageLogTable`},u={Ref:`${a.slug}SmsOptOutTable`},h={Ref:`${a.slug}SmsNotificationTopic`};if(Object.assign(n,F.createSendLambda({slug:a.slug,roleArn:s,pinpointAppId:c,messageLogTable:l,senderId:a.senderId,originationNumber:a.originationNumber})),a.twoWayEnabled)Object.assign(n,F.createReceiveLambda({slug:a.slug,roleArn:s,optOutTable:u,messageLogTable:l,notificationTopicArn:h,webhookUrl:a.webhookUrl}));return Object.assign(n,F.createDeliveryStatusLambda({slug:a.slug,roleArn:s,messageLogTable:l,notificationTopicArn:h,webhookUrl:a.webhookUrl})),i[`${a.slug}PinpointAppId`]={Description:"Pinpoint application ID",Value:{Ref:`${a.slug}PinpointApp`}},i[`${a.slug}SmsSendLambdaArn`]={Description:"SMS send Lambda ARN",Value:{"Fn::GetAtt":[`${a.slug}SmsSendLambda`,"Arn"]}},i[`${a.slug}SmsNotificationTopicArn`]={Description:"SMS notification topic ARN",Value:{Ref:`${a.slug}SmsNotificationTopic`}},i[`${a.slug}SmsMessageLogTableName`]={Description:"SMS message log table name",Value:{Ref:`${a.slug}SmsMessageLogTable`}},{resources:n,outputs:i}}}function wt(a){return a.replace(/[^a-zA-Z0-9]/g," ").trim().split(/\s+/).map((n)=>n.charAt(0).toUpperCase()+n.slice(1)).join("")||"User"}function gr(a,n){let i=(a||n).replace(/^\/+|\/+$/g,"");if(!i||i.split("/").includes(".."))throw Error(`sftp: invalid homeDirectory for user ${n}`);return i}function hr(a){let n=a.storage;if(n?.type==="efs"){let s="fileSystemId"in n?n.fileSystemId:void 0;if(!s||typeof s==="string"&&!s.trim())throw Error("sftp: EFS storage requires fileSystemId, or a fileSystem name defined in infrastructure.fileSystem");return{type:"efs",fileSystemId:s,posixProfile:n.posixProfile}}let i=(n?.type==="s3"?n.bucket??a.bucket:a.bucket)?.trim();if(!i)throw Error("sftp: S3 storage requires bucket, or a storageBucket name defined in infrastructure.storage");return{type:"s3",bucket:i}}function yr(a,n,i){let s=n.posixProfile??i;if(!s)throw Error(`sftp: user ${a} requires a posixProfile (uid/gid) on an EFS-backed server`);for(let c of[s.uid,s.gid,...s.secondaryGids??[]])if(!Number.isInteger(c)||c<0||c>4294967295)throw Error(`sftp: user ${a} has an invalid posixProfile id ${c}`);return{Uid:s.uid,Gid:s.gid,...s.secondaryGids?.length?{SecondaryGids:s.secondaryGids}:{}}}function fr(a,n){return typeof a==="string"?`/${a}/${n}`:{"Fn::Sub":[`/\${FileSystemId}/${n}`,{FileSystemId:a}]}}function Sr(a){return typeof a==="string"?{"Fn::Sub":"arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}".replace("${FileSystemId}",a)}:{"Fn::Sub":["arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}",{FileSystemId:a}]}}class md{static create(a){let n=hr(a),i=n.type==="efs"?"EFS":"S3",s=a.endpointType??"PUBLIC";if(s==="VPC"&&(!a.endpointDetails?.vpcId||!a.endpointDetails.subnetIds.length))throw Error("sftp: VPC endpoints require endpointDetails.vpcId and at least one subnet");let c=`${wt(a.slug)}${wt(a.environment)}Sftp`,l=`${c}Server`,u={},h;if(a.logging!==!1){let y=`${c}LoggingRole`;u[y]={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"transfer.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"TransferLogging",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:DescribeLogStreams","logs:PutLogEvents"],Resource:"arn:aws:logs:*:*:log-group:/aws/transfer/*"}]}}]}},h={"Fn::GetAtt":[y,"Arn"]}}u[l]={Type:"AWS::Transfer::Server",Properties:{Domain:i,EndpointType:s,IdentityProviderType:"SERVICE_MANAGED",Protocols:["SFTP"],...s==="VPC"?{EndpointDetails:{VpcId:a.endpointDetails.vpcId,SubnetIds:a.endpointDetails.subnetIds,...a.endpointDetails.securityGroupIds?.length?{SecurityGroupIds:a.endpointDetails.securityGroupIds}:{},...a.endpointDetails.addressAllocationIds?.length?{AddressAllocationIds:a.endpointDetails.addressAllocationIds}:{}}}:{},...a.securityPolicyName?{SecurityPolicyName:a.securityPolicyName}:{},...h?{LoggingRole:h}:{},Tags:[{Key:"Project",Value:a.slug},{Key:"Environment",Value:a.environment},{Key:"ManagedBy",Value:"ts-cloud"}]}};for(let[y,S]of Object.entries(a.users)){if(!/^[a-zA-Z0-9_.@-]{3,100}$/.test(y))throw Error(`sftp: invalid username ${y}`);if(!S.sshPublicKeys.length)throw Error(`sftp: user ${y} requires at least one SSH public key`);let A=wt(y),C=gr(S.homeDirectory,y),T=`${c}${A}User`,v=S.roleArn;if(!v){let w=`${c}${A}Role`,E;if(n.type==="efs")E=[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:DescribeMountTargets"],Resource:Sr(n.fileSystemId)}];else{let R=`arn:aws:s3:::${n.bucket}`;E=[{Effect:"Allow",Action:["s3:ListBucket","s3:GetBucketLocation"],Resource:R,Condition:{StringLike:{"s3:prefix":[C,`${C}/*`]}}},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:GetObjectVersion"],Resource:`${R}/${C}/*`}]}u[w]={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"transfer.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"SftpHomeDirectory",PolicyDocument:{Version:"2012-10-17",Statement:E}}]}},v={"Fn::GetAtt":[w,"Arn"]}}u[T]={Type:"AWS::Transfer::User",DependsOn:[l],Properties:{ServerId:{Ref:l},UserName:y,Role:v,HomeDirectoryType:"PATH",HomeDirectory:n.type==="efs"?fr(n.fileSystemId,C):`/${n.bucket}/${C}`,...n.type==="efs"?{PosixProfile:yr(y,S,n.posixProfile)}:{},SshPublicKeys:S.sshPublicKeys}}}return{resources:u,serverLogicalId:l,domain:i}}}class Te{static createBedrockRole(a,n){let{slug:i,environment:s,name:c,models:l=["*"],allowStreaming:u=!0}=n,h=c||r({slug:i,environment:s,resourceType:"bedrock-role"}),y=t(h),S=["bedrock:InvokeModel"];if(u)S.push("bedrock:InvokeModelWithResponseStream");let A=l.map((C)=>C==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${C}`);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:h,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:a},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:`${h}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:S,Resource:A}]}}],Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}},logicalId:y}}static createBedrockPolicy(a){let{slug:n,environment:i,name:s,models:c=["*"],allowInvoke:l=!0,allowStreaming:u=!0,allowAsync:h=!1}=a,y=s||r({slug:n,environment:i,resourceType:"bedrock-policy"}),S=t(y),A=[];if(l)A.push("bedrock:InvokeModel");if(u)A.push("bedrock:InvokeModelWithResponseStream");if(h)A.push("bedrock:InvokeModelAsync");let C=c.map((T)=>T==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${T}`);return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:y,PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"BedrockModelInvocation",Effect:"Allow",Action:A,Resource:C}]}}},logicalId:S}}static enableBedrockForLambda(a){return Te.createBedrockRole("lambda.amazonaws.com",a)}static enableBedrockForEcs(a){return Te.createBedrockRole("ecs-tasks.amazonaws.com",a)}static enableBedrockForEc2(a){return Te.createBedrockRole("ec2.amazonaws.com",a)}static addBedrockPermissions(a,n=["*"],i=!0){let s=["bedrock:InvokeModel"];if(i)s.push("bedrock:InvokeModelWithResponseStream");let c=n.map((l)=>l==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${l}`);if(!a.Properties.Policies)a.Properties.Policies=[];return a.Properties.Policies.push({PolicyName:"bedrock-permissions",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:s,Resource:c}]}}),a}static Models={Claude3_5_Sonnet:"anthropic.claude-3-5-sonnet-20241022-v2:0",Claude3_5_Haiku:"anthropic.claude-3-5-haiku-20241022-v1:0",Claude3_Opus:"anthropic.claude-3-opus-20240229-v1:0",Claude3_Sonnet:"anthropic.claude-3-sonnet-20240229-v1:0",Claude3_Haiku:"anthropic.claude-3-haiku-20240307-v1:0",TitanTextG1Express:"amazon.titan-text-express-v1",TitanTextG1Lite:"amazon.titan-text-lite-v1",TitanEmbedG1Text:"amazon.titan-embed-text-v1",TitanImageG1:"amazon.titan-image-generator-v1",JurassicUltra:"ai21.j2-ultra-v1",JurassicMid:"ai21.j2-mid-v1",CommandText:"cohere.command-text-v14",CommandLight:"cohere.command-light-text-v14",EmbedEnglish:"cohere.embed-english-v3",EmbedMultilingual:"cohere.embed-multilingual-v3",Llama3_2_1B:"meta.llama3-2-1b-instruct-v1:0",Llama3_2_3B:"meta.llama3-2-3b-instruct-v1:0",Llama3_2_11B:"meta.llama3-2-11b-instruct-v1:0",Llama3_2_90B:"meta.llama3-2-90b-instruct-v1:0",Llama3_1_8B:"meta.llama3-1-8b-instruct-v1:0",Llama3_1_70B:"meta.llama3-1-70b-instruct-v1:0",Llama3_1_405B:"meta.llama3-1-405b-instruct-v1:0",Mistral7B:"mistral.mistral-7b-instruct-v0:2",Mixtral8x7B:"mistral.mixtral-8x7b-instruct-v0:1",MistralLarge:"mistral.mistral-large-2402-v1:0",StableDiffusionXL:"stability.stable-diffusion-xl-v1"};static ModelGroups={AllClaude:["anthropic.claude-3-5-sonnet-20241022-v2:0","anthropic.claude-3-5-haiku-20241022-v1:0","anthropic.claude-3-opus-20240229-v1:0","anthropic.claude-3-sonnet-20240229-v1:0","anthropic.claude-3-haiku-20240307-v1:0"],AllTitan:["amazon.titan-text-express-v1","amazon.titan-text-lite-v1","amazon.titan-embed-text-v1","amazon.titan-image-generator-v1"],AllLlama:["meta.llama3-2-1b-instruct-v1:0","meta.llama3-2-3b-instruct-v1:0","meta.llama3-2-11b-instruct-v1:0","meta.llama3-2-90b-instruct-v1:0","meta.llama3-1-8b-instruct-v1:0","meta.llama3-1-70b-instruct-v1:0","meta.llama3-1-405b-instruct-v1:0"],TextModels:["anthropic.claude-3-5-sonnet-20241022-v2:0","anthropic.claude-3-5-haiku-20241022-v1:0","amazon.titan-text-express-v1","meta.llama3-2-11b-instruct-v1:0","mistral.mistral-7b-instruct-v0:2"],EmbeddingModels:["amazon.titan-embed-text-v1","cohere.embed-english-v3","cohere.embed-multilingual-v3"],ImageModels:["amazon.titan-image-generator-v1","stability.stable-diffusion-xl-v1"]}}class Ut{static createPostgres(a){return Ut.createRDSInstance("postgres","16.2",a)}static createMysql(a){return Ut.createRDSInstance("mysql","8.0.35",a)}static createRDSInstance(a,n,i){let{slug:s,environment:c,instanceClass:l="db.t3.micro",allocatedStorage:u=20,storageType:h="gp3",masterUsername:y="admin",masterPassword:S,databaseName:A,subnetIds:C,securityGroupIds:T,encrypted:v=!0,kmsKeyId:w,multiAz:E=!1,backupRetentionDays:R=7,publiclyAccessible:k=!1,enableCloudwatchLogs:W=!0,deletionProtection:P=!0}=i,V=r({slug:s,environment:c,resourceType:`${a}-db`}),B=t(V),j,J;if(C&&C.length>0){let X=r({slug:s,environment:c,resourceType:"db-subnet-group"});J=t(X),j={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupName:X,DBSubnetGroupDescription:`Subnet group for ${V}`,SubnetIds:C,Tags:[{Key:"Name",Value:X},{Key:"Environment",Value:c}]}}}let K={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:V,DBInstanceClass:l,Engine:a,EngineVersion:n,MasterUsername:y,MasterUserPassword:S,AllocatedStorage:u,StorageType:h,StorageEncrypted:v,MultiAZ:E,BackupRetentionPeriod:R,PubliclyAccessible:k,DeletionProtection:P,Tags:[{Key:"Name",Value:V},{Key:"Environment",Value:c}]}};if(A)K.Properties.DBName=A;if(w)K.Properties.KmsKeyId=w;if(J)K.Properties.DBSubnetGroupName=N.Ref(J);if(T&&T.length>0)K.Properties.VPCSecurityGroups=T;if(W)K.Properties.EnableCloudwatchLogsExports=a==="postgres"?["postgresql"]:["error","general","slowquery"];return{dbInstance:K,subnetGroup:j,logicalId:B,subnetGroupId:J}}static createReadReplica(a,n){let{slug:i,environment:s,instanceClass:c="db.t3.micro",securityGroupIds:l,publiclyAccessible:u=!1}=n,h=r({slug:i,environment:s,resourceType:"db-replica"}),y=t(h),S={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:h,DBInstanceClass:c,SourceDBInstanceIdentifier:N.Ref(a),PubliclyAccessible:u,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s},{Key:"Type",Value:"ReadReplica"}]}};if(l&&l.length>0)S.Properties.VPCSecurityGroups=l;return{replica:S,logicalId:y}}static createParameterGroup(a,n,i){let{slug:s,environment:c,parameters:l={}}=i,u=r({slug:s,environment:c,resourceType:"db-params"}),h=t(u),y=a==="postgres"?`postgres${n.split(".")[0]}`:`mysql${n.split(".")[0]}.${n.split(".")[1]}`;return{parameterGroup:{Type:"AWS::RDS::DBParameterGroup",Properties:{DBParameterGroupName:u,Description:`Parameter group for ${u}`,Family:y,Parameters:l,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:c}]}},logicalId:h}}static enableBackup(a,n=7){return a.Properties.BackupRetentionPeriod=n,a}static createTable(a){let{slug:n,environment:i,tableName:s,partitionKey:c,sortKey:l,billingMode:u="PAY_PER_REQUEST",readCapacity:h=5,writeCapacity:y=5,streamEnabled:S=!1,streamViewType:A="NEW_AND_OLD_IMAGES",encrypted:C=!0,kmsKeyId:T,pointInTimeRecovery:v=!0,ttlAttribute:w}=a,E=s||r({slug:n,environment:i,resourceType:"table"}),R=t(E),k=[{AttributeName:c.name,AttributeType:c.type}];if(l)k.push({AttributeName:l.name,AttributeType:l.type});let W=[{AttributeName:c.name,KeyType:"HASH"}];if(l)W.push({AttributeName:l.name,KeyType:"RANGE"});let P={Type:"AWS::DynamoDB::Table",Properties:{TableName:E,BillingMode:u,AttributeDefinitions:k,KeySchema:W,Tags:[{Key:"Name",Value:E},{Key:"Environment",Value:i}]}};if(u==="PROVISIONED")P.Properties.ProvisionedThroughput={ReadCapacityUnits:h,WriteCapacityUnits:y};if(S)P.Properties.StreamSpecification={StreamViewType:A};if(C)P.Properties.SSESpecification={SSEEnabled:!0,SSEType:T?"KMS":"AES256",KMSMasterKeyId:T};if(v)P.Properties.PointInTimeRecoverySpecification={PointInTimeRecoveryEnabled:!0};if(w)P.Properties.TimeToLiveSpecification={AttributeName:w,Enabled:!0};return{table:P,logicalId:R}}static addGlobalSecondaryIndex(a,n){let{indexName:i,partitionKey:s,sortKey:c,projectionType:l="ALL",nonKeyAttributes:u,readCapacity:h=5,writeCapacity:y=5}=n;if(!a.Properties.AttributeDefinitions.some((C)=>C.AttributeName===s.name))a.Properties.AttributeDefinitions.push({AttributeName:s.name,AttributeType:s.type});if(c&&!a.Properties.AttributeDefinitions.some((C)=>C.AttributeName===c.name))a.Properties.AttributeDefinitions.push({AttributeName:c.name,AttributeType:c.type});let S=[{AttributeName:s.name,KeyType:"HASH"}];if(c)S.push({AttributeName:c.name,KeyType:"RANGE"});let A={IndexName:i,KeySchema:S,Projection:{ProjectionType:l,NonKeyAttributes:l==="INCLUDE"?u:void 0},ProvisionedThroughput:void 0};if(a.Properties.BillingMode==="PROVISIONED")A.ProvisionedThroughput={ReadCapacityUnits:h,WriteCapacityUnits:y};if(!a.Properties.GlobalSecondaryIndexes)a.Properties.GlobalSecondaryIndexes=[];return a.Properties.GlobalSecondaryIndexes.push(A),a}static enableStreams(a,n="NEW_AND_OLD_IMAGES"){return a.Properties.StreamSpecification={StreamViewType:n},a}static InstanceClasses={T3_Micro:"db.t3.micro",T3_Small:"db.t3.small",T3_Medium:"db.t3.medium",T3_Large:"db.t3.large",T4g_Micro:"db.t4g.micro",T4g_Small:"db.t4g.small",T4g_Medium:"db.t4g.medium",M5_Large:"db.m5.large",M5_XLarge:"db.m5.xlarge",M5_2XLarge:"db.m5.2xlarge",R5_Large:"db.r5.large",R5_XLarge:"db.r5.xlarge",R5_2XLarge:"db.r5.2xlarge"}}class Ys{static createRedis(a){let{slug:n,environment:i,nodeType:s="cache.t3.micro",engineVersion:c="7.1",port:l=6379,subnetIds:u,securityGroupIds:h,numCacheClusters:y=2,automaticFailover:S=!0,multiAz:A=!0,clusterMode:C=!1,numNodeGroups:T=1,replicasPerNodeGroup:v=1,atRestEncryption:w=!0,transitEncryption:E=!0,authToken:R,kmsKeyId:k,snapshotRetentionDays:W=7,snapshotWindow:P,maintenanceWindow:V}=a,B=r({slug:n,environment:i,resourceType:"redis"}),j=t(B),J,K;if(u&&u.length>0){let te=r({slug:n,environment:i,resourceType:"cache-subnet-group"});K=t(te),J={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:te,Description:`Subnet group for ${B}`,SubnetIds:u,Tags:[{Key:"Name",Value:te},{Key:"Environment",Value:i}]}}}let X={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:B,ReplicationGroupDescription:`Redis cluster for ${n} ${i}`,Engine:"redis",EngineVersion:c,CacheNodeType:s,Port:l,AutomaticFailoverEnabled:S,MultiAZEnabled:A,AtRestEncryptionEnabled:w,TransitEncryptionEnabled:E,SnapshotRetentionLimit:W,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:B},{Key:"Environment",Value:i}]}};if(C)X.Properties.NumNodeGroups=T,X.Properties.ReplicasPerNodeGroup=v;else X.Properties.NumCacheClusters=y;if(R)X.Properties.AuthToken=R;if(k)X.Properties.KmsKeyId=k;if(K)X.Properties.CacheSubnetGroupName=N.Ref(K);if(h&&h.length>0)X.Properties.SecurityGroupIds=h;if(P)X.Properties.SnapshotWindow=P;if(V)X.Properties.PreferredMaintenanceWindow=V;return{replicationGroup:X,subnetGroup:J,logicalId:j,subnetGroupId:K}}static createMemcached(a){let{slug:n,environment:i,nodeType:s="cache.t3.micro",engineVersion:c="1.6.22",port:l=11211,numCacheNodes:u=2,subnetIds:h,securityGroupIds:y,azMode:S="cross-az",preferredAzs:A,maintenanceWindow:C}=a,T=r({slug:n,environment:i,resourceType:"memcached"}),v=t(T),w,E;if(h&&h.length>0){let k=r({slug:n,environment:i,resourceType:"cache-subnet-group"});E=t(k),w={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:k,Description:`Subnet group for ${T}`,SubnetIds:h,Tags:[{Key:"Name",Value:k},{Key:"Environment",Value:i}]}}}let R={Type:"AWS::ElastiCache::CacheCluster",Properties:{ClusterName:T,CacheNodeType:s,Engine:"memcached",EngineVersion:c,NumCacheNodes:u,Port:l,AZMode:S,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:T},{Key:"Environment",Value:i}]}};if(E)R.Properties.CacheSubnetGroupName=N.Ref(E);if(y&&y.length>0)R.Properties.VpcSecurityGroupIds=y;if(A&&A.length>0)R.Properties.PreferredAvailabilityZones=A;if(C)R.Properties.PreferredMaintenanceWindow=C;return{cluster:R,subnetGroup:w,logicalId:v,subnetGroupId:E}}static enableClusterMode(a,n=3,i=2){return delete a.Properties.NumCacheClusters,a.Properties.NumNodeGroups=n,a.Properties.ReplicasPerNodeGroup=i,a}static createRedisParameterGroup(a,n){let{slug:i,environment:s,parameters:c={}}=n,l=r({slug:i,environment:s,resourceType:"redis-params"}),u=t(l);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`redis${a.split(".")[0]}.x`,Description:`Parameter group for ${l}`,Properties:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s}]}},logicalId:u}}static createMemcachedParameterGroup(a,n){let{slug:i,environment:s,parameters:c={}}=n,l=r({slug:i,environment:s,resourceType:"memcached-params"}),u=t(l);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`memcached${a.split(".")[0]}.${a.split(".")[1]}`,Description:`Parameter group for ${l}`,Properties:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s}]}},logicalId:u}}static NodeTypes={T3_Micro:"cache.t3.micro",T3_Small:"cache.t3.small",T3_Medium:"cache.t3.medium",T4g_Micro:"cache.t4g.micro",T4g_Small:"cache.t4g.small",T4g_Medium:"cache.t4g.medium",M5_Large:"cache.m5.large",M5_XLarge:"cache.m5.xlarge",M5_2XLarge:"cache.m5.2xlarge",R5_Large:"cache.r5.large",R5_XLarge:"cache.r5.xlarge",R5_2XLarge:"cache.r5.2xlarge",R5_4XLarge:"cache.r5.4xlarge",R6g_Large:"cache.r6g.large",R6g_XLarge:"cache.r6g.xlarge",R6g_2XLarge:"cache.r6g.2xlarge"}}class Y{static createUser(a){let{slug:n,environment:i,userName:s,groups:c,managedPolicyArns:l}=a,u=s||r({slug:n,environment:i,resourceType:"user"}),h=t(u),y={Type:"AWS::IAM::User",Properties:{UserName:u,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:i}]}};if(c&&c.length>0)y.Properties.Groups=c;if(l&&l.length>0)y.Properties.ManagedPolicyArns=l;return{user:y,logicalId:h}}static createRole(a){let{slug:n,environment:i,roleName:s,servicePrincipal:c,awsPrincipal:l,managedPolicyArns:u}=a,h=s||r({slug:n,environment:i,resourceType:"role"}),y=t(h),S={};if(c)S.Service=c;if(l)S.AWS=l;let A={Type:"AWS::IAM::Role",Properties:{RoleName:h,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:S,Action:"sts:AssumeRole"}]},Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:i}]}};if(u&&u.length>0)A.Properties.ManagedPolicyArns=u;return{role:A,logicalId:y}}static createGroup(a){let{slug:n,environment:i,groupName:s,managedPolicyArns:c}=a,l=s||r({slug:n,environment:i,resourceType:"group"}),u=t(l),h={Type:"AWS::IAM::Group",Properties:{GroupName:l}};if(c&&c.length>0)h.Properties.ManagedPolicyArns=c;return{group:h,logicalId:u}}static createPolicy(a){let{slug:n,environment:i,policyName:s,description:c,statements:l}=a,u=s||r({slug:n,environment:i,resourceType:"policy"}),h=t(u),y=l.map((S)=>({Sid:S.sid,Effect:S.effect||"Allow",Action:S.actions,Resource:S.resources,Condition:S.conditions}));return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:u,Description:c||`Managed policy for ${u}`,PolicyDocument:{Version:"2012-10-17",Statement:y}}},logicalId:h}}static attachPolicyToRole(a,n){if(!a.Properties.ManagedPolicyArns)a.Properties.ManagedPolicyArns=[];if(!a.Properties.ManagedPolicyArns.includes(n))a.Properties.ManagedPolicyArns.push(n);return a}static attachPolicyToUser(a,n){if(!a.Properties.ManagedPolicyArns)a.Properties.ManagedPolicyArns=[];if(!a.Properties.ManagedPolicyArns.includes(n))a.Properties.ManagedPolicyArns.push(n);return a}static attachPolicyToGroup(a,n){if(!a.Properties.ManagedPolicyArns)a.Properties.ManagedPolicyArns=[];if(!a.Properties.ManagedPolicyArns.includes(n))a.Properties.ManagedPolicyArns.push(n);return a}static addInlinePolicyToRole(a,n,i){if(!a.Properties.Policies)a.Properties.Policies=[];let s=i.map((c)=>({Effect:c.effect||"Allow",Action:c.actions,Resource:c.resources}));return a.Properties.Policies.push({PolicyName:n,PolicyDocument:{Version:"2012-10-17",Statement:s}}),a}static addInlinePolicyToUser(a,n,i){if(!a.Properties.Policies)a.Properties.Policies=[];let s=i.map((c)=>({Effect:c.effect||"Allow",Action:c.actions,Resource:c.resources}));return a.Properties.Policies.push({PolicyName:n,PolicyDocument:{Version:"2012-10-17",Statement:s}}),a}static createAccessKey(a,n){let{slug:i,environment:s,status:c="Active"}=n,l=r({slug:i,environment:s,resourceType:"access-key"}),u=t(l);return{accessKey:{Type:"AWS::IAM::AccessKey",Properties:{UserName:N.Ref(a),Status:c}},logicalId:u}}static createInstanceProfile(a,n){let{slug:i,environment:s,profileName:c}=n,l=c||r({slug:i,environment:s,resourceType:"instance-profile"}),u=t(l);return{instanceProfile:{Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:l,Roles:[N.Ref(a)]}},logicalId:u}}static ManagedPolicies={AdministratorAccess:"arn:aws:iam::aws:policy/AdministratorAccess",PowerUserAccess:"arn:aws:iam::aws:policy/PowerUserAccess",ReadOnlyAccess:"arn:aws:iam::aws:policy/ReadOnlyAccess",S3FullAccess:"arn:aws:iam::aws:policy/AmazonS3FullAccess",S3ReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess",DynamoDBFullAccess:"arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess",DynamoDBReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonDynamoDBReadOnlyAccess",RDSFullAccess:"arn:aws:iam::aws:policy/AmazonRDSFullAccess",RDSReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonRDSReadOnlyAccess",LambdaFullAccess:"arn:aws:iam::aws:policy/AWSLambda_FullAccess",LambdaReadOnlyAccess:"arn:aws:iam::aws:policy/AWSLambda_ReadOnlyAccess",LambdaBasicExecutionRole:"arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",LambdaVPCAccessExecutionRole:"arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole",EC2FullAccess:"arn:aws:iam::aws:policy/AmazonEC2FullAccess",EC2ReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess",EC2ContainerRegistryReadOnly:"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly",EC2ContainerRegistryPowerUser:"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPowerUser",ECSTaskExecutionRole:"arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy",ECSFullAccess:"arn:aws:iam::aws:policy/AmazonECS_FullAccess",CloudWatchFullAccess:"arn:aws:iam::aws:policy/CloudWatchFullAccess",CloudWatchLogsFullAccess:"arn:aws:iam::aws:policy/CloudWatchLogsFullAccess",SESFullAccess:"arn:aws:iam::aws:policy/AmazonSESFullAccess",SNSFullAccess:"arn:aws:iam::aws:policy/AmazonSNSFullAccess",SQSFullAccess:"arn:aws:iam::aws:policy/AmazonSQSFullAccess",SecretsManagerReadWrite:"arn:aws:iam::aws:policy/SecretsManagerReadWrite"};static ServicePrincipals={Lambda:"lambda.amazonaws.com",EC2:"ec2.amazonaws.com",ECS:"ecs.amazonaws.com",ECSTaskExecution:"ecs-tasks.amazonaws.com",APIGateway:"apigateway.amazonaws.com",Events:"events.amazonaws.com",States:"states.amazonaws.com",CodeBuild:"codebuild.amazonaws.com",CodeDeploy:"codedeploy.amazonaws.com",CloudFormation:"cloudformation.amazonaws.com"};static createCiCdUser(a){let{slug:n,environment:i,permissions:s,createAccessKey:c=!0}=a,l={},u=[];if(s.s3Buckets&&s.s3Buckets.length>0)u.push({sid:"S3Access",actions:["s3:GetBucketLocation","s3:ListBucket","s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucketMultipartUploads","s3:AbortMultipartUpload"],resources:[...s.s3Buckets,...s.s3Buckets.map((v)=>`${v}/*`)]});if(s.cloudFrontDistributions&&s.cloudFrontDistributions.length>0)u.push({sid:"CloudFrontAccess",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations","cloudfront:GetDistribution"],resources:s.cloudFrontDistributions});if(s.ecrRepositories&&s.ecrRepositories.length>0)u.push({sid:"ECRAccess",actions:["ecr:GetAuthorizationToken","ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:GetRepositoryPolicy","ecr:DescribeRepositories","ecr:ListImages","ecr:DescribeImages","ecr:BatchGetImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:PutImage"],resources:s.ecrRepositories}),u.push({sid:"ECRLogin",actions:["ecr:GetAuthorizationToken"],resources:"*"});if(s.ecsServices&&s.ecsServices.length>0)u.push({sid:"ECSAccess",actions:["ecs:DescribeServices","ecs:DescribeTaskDefinition","ecs:DescribeTasks","ecs:ListTasks","ecs:RegisterTaskDefinition","ecs:UpdateService","ecs:RunTask","ecs:StopTask"],resources:s.ecsServices}),u.push({sid:"ECSTaskDefinitions",actions:["ecs:RegisterTaskDefinition","ecs:DeregisterTaskDefinition"],resources:"*"}),u.push({sid:"ECSPassRole",actions:["iam:PassRole"],resources:"*",conditions:{StringLike:{"iam:PassedToService":"ecs-tasks.amazonaws.com"}}});if(s.cloudFormationStacks&&s.cloudFormationStacks.length>0)u.push({sid:"CloudFormationAccess",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:DescribeStackResources","cloudformation:GetTemplate","cloudformation:ListStackResources","cloudformation:ValidateTemplate"],resources:s.cloudFormationStacks});if(s.lambdaFunctions&&s.lambdaFunctions.length>0)u.push({sid:"LambdaAccess",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion","lambda:UpdateAlias","lambda:CreateAlias"],resources:s.lambdaFunctions});if(s.secretsManagerSecrets&&s.secretsManagerSecrets.length>0)u.push({sid:"SecretsManagerAccess",actions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],resources:s.secretsManagerSecrets});let{policy:h,logicalId:y}=Y.createPolicy({slug:n,environment:i,policyName:r({slug:n,environment:i,resourceType:"cicd-policy"}),description:`CI/CD deployment policy for ${n} (${i})`,statements:u});l[y]=h;let{user:S,logicalId:A}=Y.createUser({slug:n,environment:i,userName:r({slug:n,environment:i,resourceType:"cicd-user"}),managedPolicyArns:[N.Ref(y)]});l[A]=S;let C,T;if(c){let v=Y.createAccessKey(A,{slug:n,environment:i});C=v.accessKey,T=v.logicalId,l[T]=C}return{user:S,accessKey:C,policy:h,userLogicalId:A,accessKeyLogicalId:T,policyLogicalId:y,resources:l}}static createCrossAccountRole(a){let{slug:n,environment:i,trustedAccountIds:s,externalId:c,permissions:l,maxSessionDuration:u=3600}=a,h={},{policy:y,logicalId:S}=Y.createPolicy({slug:n,environment:i,policyName:r({slug:n,environment:i,resourceType:"cross-account-policy"}),description:`Cross-account access policy for ${n} (${i})`,statements:l});h[S]=y;let A=r({slug:n,environment:i,resourceType:"cross-account-role"}),C=t(A),T={};if(c)T.StringEquals={"sts:ExternalId":c};let v={Type:"AWS::IAM::Role",Properties:{RoleName:A,MaxSessionDuration:u,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:s.map((w)=>`arn:aws:iam::${w}:root`)},Action:"sts:AssumeRole",...Object.keys(T).length>0?{Condition:T}:{}}]},ManagedPolicyArns:[N.Ref(S)],Tags:[{Key:"Name",Value:A},{Key:"Environment",Value:i},{Key:"Purpose",Value:"Cross-Account Access"}]}};return h[C]=v,{role:v,policy:y,roleLogicalId:C,policyLogicalId:S,resources:h}}static createCliUser(a){let{slug:n,environment:i,permissions:s="readonly"}=a,c={},l=[],u=[];switch(s){case"readonly":u=[Y.ManagedPolicies.ReadOnlyAccess];break;case"deploy":l=[{sid:"S3Deploy",actions:["s3:*"],resources:"*"},{sid:"CloudFrontDeploy",actions:["cloudfront:*"],resources:"*"},{sid:"ECSDeploy",actions:["ecs:*"],resources:"*"},{sid:"ECRDeploy",actions:["ecr:*"],resources:"*"},{sid:"LambdaDeploy",actions:["lambda:*"],resources:"*"},{sid:"CloudFormationDeploy",actions:["cloudformation:*"],resources:"*"},{sid:"IAMPassRole",actions:["iam:PassRole"],resources:"*"}];break;case"admin":u=[Y.ManagedPolicies.AdministratorAccess];break}let h,y;if(l.length>0){let v=Y.createPolicy({slug:n,environment:i,policyName:r({slug:n,environment:i,resourceType:"cli-policy"}),description:`CLI access policy for ${n} (${i})`,statements:l});h=v.policy,y=v.logicalId,c[y]=h,u=[N.Ref(y)]}let{user:S,logicalId:A}=Y.createUser({slug:n,environment:i,userName:r({slug:n,environment:i,resourceType:"cli-user"}),managedPolicyArns:u});c[A]=S;let{accessKey:C,logicalId:T}=Y.createAccessKey(A,{slug:n,environment:i});return c[T]=C,{user:S,accessKey:C,policy:h,userLogicalId:A,accessKeyLogicalId:T,policyLogicalId:y,resources:c}}static CiCdPolicies={s3Deployment:(a)=>[{sid:"S3ListBuckets",actions:["s3:ListBucket","s3:GetBucketLocation"],resources:a},{sid:"S3Objects",actions:["s3:GetObject","s3:PutObject","s3:DeleteObject"],resources:a.map((n)=>`${n}/*`)}],cloudFrontInvalidation:(a)=>[{sid:"CloudFrontInvalidation",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations"],resources:a}],ecsDeployment:()=>[{sid:"ECSServices",actions:["ecs:DescribeServices","ecs:UpdateService","ecs:DescribeTaskDefinition","ecs:RegisterTaskDefinition"],resources:"*"},{sid:"ECSPassRole",actions:["iam:PassRole"],resources:"*",conditions:{StringLike:{"iam:PassedToService":"ecs-tasks.amazonaws.com"}}}],ecrPush:(a)=>[{sid:"ECRAuth",actions:["ecr:GetAuthorizationToken"],resources:"*"},{sid:"ECRPush",actions:["ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:PutImage"],resources:a}],lambdaDeployment:(a)=>[{sid:"LambdaDeploy",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion"],resources:a}],cloudFormationDeployment:(a)=>[{sid:"CloudFormationDeploy",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate"],resources:a}]}}class hd{static createRestApi(a){let{slug:n,environment:i,name:s,description:c,endpointType:l="REGIONAL",binaryMediaTypes:u,compressionSize:h}=a,y=s||r({slug:n,environment:i,resourceType:"rest-api"}),S=t(y),A={Type:"AWS::ApiGateway::RestApi",Properties:{Name:y,Description:c||`REST API for ${n} ${i}`,EndpointConfiguration:{Types:[l]},Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:i}]}};if(u&&u.length>0)A.Properties.BinaryMediaTypes=u;if(h!==void 0)A.Properties.MinimumCompressionSize=h;return{restApi:A,logicalId:S}}static createHttpApi(a){let{slug:n,environment:i,name:s,description:c,corsEnabled:l=!0,corsOrigins:u=["*"],corsMethods:h=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],corsHeaders:y=["*"],corsMaxAge:S=86400,corsAllowCredentials:A=!1}=a,C=s||r({slug:n,environment:i,resourceType:"http-api"}),T=t(C),v={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:C,Description:c||`HTTP API for ${n} ${i}`,ProtocolType:"HTTP",Tags:{Name:C,Environment:i}}};if(l)v.Properties.CorsConfiguration={AllowOrigins:u,AllowMethods:h,AllowHeaders:y,MaxAge:S,AllowCredentials:A};return{httpApi:v,logicalId:T}}static createWebSocketApi(a){let{slug:n,environment:i,name:s,description:c}=a,l=s||r({slug:n,environment:i,resourceType:"ws-api"}),u=t(l);return{webSocketApi:{Type:"AWS::ApiGatewayV2::Api",Properties:{Name:l,Description:c||`WebSocket API for ${n} ${i}`,ProtocolType:"WEBSOCKET",Tags:{Name:l,Environment:i}}},logicalId:u}}static createDeployment(a,n){let{slug:i,environment:s,description:c}=n,l=r({slug:i,environment:s,resourceType:"api-deployment"}),u=t(l);return{deployment:{Type:"AWS::ApiGateway::Deployment",Properties:{RestApiId:N.Ref(a),Description:c||`Deployment for ${l}`}},logicalId:u}}static createStage(a,n,i){let{slug:s,environment:c,stageName:l,description:u,cacheEnabled:h=!1,cacheSize:y="0.5",variables:S,throttling:A}=i,C=r({slug:s,environment:c,resourceType:"api-stage"}),T=t(C),v={Type:"AWS::ApiGateway::Stage",Properties:{StageName:l||c,RestApiId:N.Ref(a),DeploymentId:N.Ref(n),Description:u,CacheClusterEnabled:h,Tags:[{Key:"Name",Value:C},{Key:"Environment",Value:c}]}};if(h)v.Properties.CacheClusterSize=y;if(S)v.Properties.Variables=S;if(A)v.Properties.MethodSettings=[{HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:A.burstLimit,ThrottlingRateLimit:A.rateLimit}];return{stage:v,logicalId:T}}static createAuthorizer(a,n){let{slug:i,environment:s,name:c,type:l,functionArn:u,identitySource:h,userPoolArns:y,ttl:S=300}=n,A=c||r({slug:i,environment:s,resourceType:"api-authorizer"}),C=t(A),T={Type:"AWS::ApiGateway::Authorizer",Properties:{Name:A,Type:l,RestApiId:N.Ref(a),AuthorizerResultTtlInSeconds:S}};if(l==="TOKEN"||l==="REQUEST"){if(!u)throw Error("Lambda authorizer requires functionArn");T.Properties.AuthorizerUri=u,T.Properties.IdentitySource=h||"method.request.header.Authorization"}if(l==="COGNITO_USER_POOLS"){if(!y||y.length===0)throw Error("Cognito authorizer requires userPoolArns");T.Properties.ProviderARNs=y,T.Properties.IdentitySource=h||"method.request.header.Authorization"}return{authorizer:T,logicalId:C}}static setCors(a,n={}){let{origins:i=["*"],methods:s=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],headers:c=["*"],maxAge:l=86400,allowCredentials:u=!1}=n;return a.Properties.CorsConfiguration={AllowOrigins:i,AllowMethods:s,AllowHeaders:c,MaxAge:l,AllowCredentials:u},a}static addThrottling(a,n=5000,i=1e4){if(!a.Properties.MethodSettings)a.Properties.MethodSettings=[];return a.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:n,ThrottlingRateLimit:i}),a}static enableCaching(a,n="0.5",i=300){if(a.Properties.CacheClusterEnabled=!0,a.Properties.CacheClusterSize=n,!a.Properties.MethodSettings)a.Properties.MethodSettings=[];return a.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",CachingEnabled:!0,CacheTtlInSeconds:i}),a}static CacheSizes={Small:"0.5",Medium:"1.6",Large:"6.1",XLarge:"13.5",XXLarge:"28.4",XXXLarge:"58.2",Huge:"118",Massive:"237"};static ThrottlingPresets={Light:{burstLimit:100,rateLimit:50},Medium:{burstLimit:500,rateLimit:250},Heavy:{burstLimit:2000,rateLimit:1000},Default:{burstLimit:5000,rateLimit:1e4}}}class Z{static createTopic(a){let{slug:n,environment:i,topicName:s,displayName:c,encrypted:l=!1,kmsKeyId:u}=a,h=s||r({slug:n,environment:i,resourceType:"topic"}),y=t(h),S={Type:"AWS::SNS::Topic",Properties:{TopicName:h,DisplayName:c||h,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:i}]}};if(l&&u)S.Properties.KmsMasterKeyId=u;return{topic:S,logicalId:y}}static subscribe(a,n){let{slug:i,environment:s,protocol:c,endpoint:l,filterPolicy:u,rawMessageDelivery:h=!1}=n,y=r({slug:i,environment:s,resourceType:"subscription"}),S=l.replace(/[^a-zA-Z0-9]/g,""),A=S.length>12?S.slice(-12):S,C=t(`${y}-${c}-${A}`),T={Type:"AWS::SNS::Subscription",Properties:{TopicArn:N.Ref(a),Protocol:c,Endpoint:l,RawMessageDelivery:h}};if(u)T.Properties.FilterPolicy=u;return{subscription:T,logicalId:C}}static subscribeEmail(a,n,i){return Z.subscribe(a,{...i,protocol:"email",endpoint:n})}static subscribeLambda(a,n,i){return Z.subscribe(a,{...i,protocol:"lambda",endpoint:n,rawMessageDelivery:!0})}static subscribeSqs(a,n,i){return Z.subscribe(a,{...i,protocol:"sqs",endpoint:n})}static subscribeHttp(a,n,i){let s=n.startsWith("https://")?"https":"http";return Z.subscribe(a,{...i,protocol:s,endpoint:n})}static subscribeSms(a,n,i){return Z.subscribe(a,{...i,protocol:"sms",endpoint:n})}static setTopicPolicy(a,n){let{slug:i,environment:s,allowedPrincipals:c,allowedServices:l,actions:u="SNS:Publish"}=n,h=r({slug:i,environment:s,resourceType:"topic-policy"}),y=t(h),S={};if(c)S.AWS=c;if(l)S.Service=l;return{policy:{Type:"AWS::SNS::TopicPolicy",Properties:{Topics:[N.Ref(a)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:S,Action:u,Resource:N.Ref(a)}]}}},logicalId:y}}static allowCloudWatchAlarms(a,n){return Z.setTopicPolicy(a,{...n,allowedServices:"cloudwatch.amazonaws.com",actions:"SNS:Publish"})}static allowEventBridge(a,n){return Z.setTopicPolicy(a,{...n,allowedServices:"events.amazonaws.com",actions:"SNS:Publish"})}static allowS3(a,n){return Z.setTopicPolicy(a,{...n,allowedServices:"s3.amazonaws.com",actions:"SNS:Publish"})}static enableEncryption(a,n){if(!a.Properties)a.Properties={};return a.Properties.KmsMasterKeyId=n,a}static addInlineSubscription(a,n,i){if(!a.Properties)a.Properties={};if(!a.Properties.Subscription)a.Properties.Subscription=[];return a.Properties.Subscription.push({Protocol:n,Endpoint:i}),a}static FilterPolicies={eventType:(a)=>({eventType:a}),status:(a)=>({status:a}),numericRange:(a,n,i)=>({[a]:[{numeric:[">=",n,"<=",i]}]}),prefix:(a,n)=>({[a]:[{prefix:n}]}),and:(...a)=>Object.assign({},...a),exists:(a,n)=>({[a]:[{exists:n}]})};static UseCases={createAlertTopic:(a)=>Z.createTopic({...a,topicName:a.topicName||`${a.slug}-${a.environment}-alerts`,displayName:a.displayName||"Alert Notifications"}),createEventFanout:(a)=>Z.createTopic({...a,topicName:a.topicName||`${a.slug}-${a.environment}-events`,displayName:a.displayName||"Event Fanout"}),createNotificationTopic:(a)=>Z.createTopic({...a,topicName:a.topicName||`${a.slug}-${a.environment}-notifications`,displayName:a.displayName||"User Notifications"})}}class Cf{static createStateMachine(a){let{slug:n,environment:i,stateMachineName:s,type:c="STANDARD",definition:l,roleArn:u,loggingConfiguration:h,tracingConfiguration:y}=a,S=s||r({slug:n,environment:i,resourceType:"state-machine"}),A=t(S),C,T,v;if(u)v=u;else{let E=r({slug:n,environment:i,resourceType:"state-machine-role"});T=t(E),C={Type:"AWS::IAM::Role",Properties:{RoleName:E,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"states.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/CloudWatchLogsFullAccess"],Tags:[{Key:"Name",Value:E},{Key:"Environment",Value:i}]}},v=N.GetAtt(T,"Arn")}let w={Type:"AWS::StepFunctions::StateMachine",Properties:{StateMachineName:S,StateMachineType:c,DefinitionString:JSON.stringify(l),RoleArn:v,Tags:[{Key:"Name",Value:S},{Key:"Environment",Value:i}]}};if(h)w.Properties.LoggingConfiguration={Level:h.level,IncludeExecutionData:h.includeExecutionData,Destinations:h.destinations?.map((E)=>({CloudWatchLogsLogGroup:{LogGroupArn:E}}))};if(y)w.Properties.TracingConfiguration={Enabled:y.enabled};return{stateMachine:w,logicalId:A,role:C,roleLogicalId:T}}static createLambdaTask(a,n){return{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Parameters:{FunctionName:a,Payload:n?.parameters||{"Input.$":"$"}},ResultPath:n?.resultPath,Retry:n?.retry,Catch:n?.catch,Next:n?.next,End:n?.end}}static createDynamoDBTask(a,n,i,s){return{Type:"Task",Resource:{GetItem:"arn:aws:states:::dynamodb:getItem",PutItem:"arn:aws:states:::dynamodb:putItem",UpdateItem:"arn:aws:states:::dynamodb:updateItem",DeleteItem:"arn:aws:states:::dynamodb:deleteItem"}[a],Parameters:{TableName:n,...i},ResultPath:s?.resultPath,Retry:s?.retry,Catch:s?.catch,Next:s?.next,End:s?.end}}static createSNSPublishTask(a,n,i){return{Type:"Task",Resource:"arn:aws:states:::sns:publish",Parameters:{TopicArn:a,Message:n},ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createSQSSendMessageTask(a,n,i){return{Type:"Task",Resource:"arn:aws:states:::sqs:sendMessage",Parameters:{QueueUrl:a,MessageBody:n},ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createPassState(a){return{Type:"Pass",Result:a?.result,ResultPath:a?.resultPath,Parameters:a?.parameters,Next:a?.next,End:a?.end}}static createWaitState(a){return{Type:"Wait",Seconds:a.seconds,Timestamp:a.timestamp,SecondsPath:a.secondsPath,TimestampPath:a.timestampPath,Next:a.next,End:a.end}}static createChoiceState(a,n){return{Type:"Choice",Choices:a,Default:n}}static createParallelState(a,n){return{Type:"Parallel",Branches:a,ResultPath:n?.resultPath,Retry:n?.retry,Catch:n?.catch,Next:n?.next,End:n?.end}}static createMapState(a,n){return{Type:"Map",ItemsPath:n?.itemsPath||"$.items",Iterator:a,MaxConcurrency:n?.maxConcurrency,ResultPath:n?.resultPath,Retry:n?.retry,Catch:n?.catch,Next:n?.next,End:n?.end}}static createSucceedState(){return{Type:"Succeed"}}static createFailState(a,n){return{Type:"Fail",Error:a,Cause:n}}static RetryPolicies={standard:()=>({ErrorEquals:["States.ALL"],IntervalSeconds:2,MaxAttempts:3,BackoffRate:2}),aggressive:()=>({ErrorEquals:["States.TaskFailed","States.Timeout"],IntervalSeconds:1,MaxAttempts:5,BackoffRate:1.5}),custom:(a,n,i,s)=>({ErrorEquals:a,IntervalSeconds:n,MaxAttempts:i,BackoffRate:s})};static CatchPolicies={all:(a,n)=>({ErrorEquals:["States.ALL"],Next:a,ResultPath:n||"$.error"}),specific:(a,n,i)=>({ErrorEquals:a,Next:n,ResultPath:i||"$.error"})};static Patterns={sequential:(a,n,i)=>{let s={};return i.forEach((c,l)=>{let u=l===i.length-1;s[c.name]={...c.state,Next:u?void 0:i[l+1].name,End:u}}),{Comment:"Sequential workflow",StartAt:i[0].name,States:s}},fanout:(a,n,i)=>({Comment:"Fan-out workflow",StartAt:"Parallel",States:{Parallel:{Type:"Parallel",Branches:i.map((s)=>s.definition),End:!0}}}),map:(a,n,i,s)=>({Comment:"Map workflow",StartAt:"Map",States:{Map:{Type:"Map",ItemsPath:"$.items",Iterator:i,MaxConcurrency:s,End:!0}}}),withErrorHandling:(a,n,i,s)=>({Comment:"Workflow with error handling",StartAt:"Main",States:{Main:{...i,Catch:[{ErrorEquals:["States.ALL"],Next:"ErrorHandler"}],Next:"Success"},ErrorHandler:s,Success:{Type:"Succeed"}}})}}class Zs{static createAlarm(a){let{slug:n,environment:i,alarmName:s,metricName:c,namespace:l,statistic:u="Average",period:h=300,evaluationPeriods:y=1,threshold:S,comparisonOperator:A,treatMissingData:C="notBreaching",actionsEnabled:T=!0,alarmActions:v,okActions:w,insufficientDataActions:E,dimensions:R,unit:k,datapointsToAlarm:W}=a,P=s||r({slug:n,environment:i,resourceType:"alarm"}),V=t(P),B={Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:P,MetricName:c,Namespace:l,Statistic:u,Period:h,EvaluationPeriods:y,Threshold:S,ComparisonOperator:A,TreatMissingData:C,ActionsEnabled:T}};if(v&&v.length>0)B.Properties.AlarmActions=v;if(w&&w.length>0)B.Properties.OKActions=w;if(E&&E.length>0)B.Properties.InsufficientDataActions=E;if(R)B.Properties.Dimensions=Object.entries(R).map(([j,J])=>({Name:j,Value:J}));if(k)B.Properties.Unit=k;if(W!==void 0)B.Properties.DatapointsToAlarm=W;return{alarm:B,logicalId:V}}static createCompositeAlarm(a){let{slug:n,environment:i,alarmName:s,alarmRule:c,actionsEnabled:l=!0,alarmActions:u,okActions:h,insufficientDataActions:y}=a,S=s||r({slug:n,environment:i,resourceType:"composite-alarm"}),A=t(S),C={Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:S,AlarmRule:c,ActionsEnabled:l}};if(u&&u.length>0)C.Properties.AlarmActions=u;if(h&&h.length>0)C.Properties.OKActions=h;if(y&&y.length>0)C.Properties.InsufficientDataActions=y;return{alarm:C,logicalId:A}}static createDashboard(a){let{slug:n,environment:i,dashboardName:s,widgets:c}=a,l=s||r({slug:n,environment:i,resourceType:"dashboard"}),u=t(l),h={widgets:c.map((y)=>({type:y.type,x:y.x,y:y.y,width:y.width,height:y.height,properties:y.properties}))};return{dashboard:{Type:"AWS::CloudWatch::Dashboard",Properties:{DashboardName:l,DashboardBody:JSON.stringify(h)}},logicalId:u}}static createLogGroup(a){let{slug:n,environment:i,logGroupName:s,retentionInDays:c,kmsKeyId:l}=a,u=s||r({slug:n,environment:i,resourceType:"log-group"}),h=t(u),y={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:u}};if(c!==void 0)y.Properties.RetentionInDays=c;if(l)y.Properties.KmsKeyId=l;return{logGroup:y,logicalId:h}}static createLogStream(a,n){let{slug:i,environment:s,logStreamName:c}=n,l=c||r({slug:i,environment:s,resourceType:"log-stream"}),u=t(l);return{logStream:{Type:"AWS::Logs::LogStream",Properties:{LogGroupName:N.Ref(a),LogStreamName:l}},logicalId:u}}static createMetricFilter(a,n){let{slug:i,environment:s,filterName:c,filterPattern:l,metricTransformations:u}=n,h=c||r({slug:i,environment:s,resourceType:"metric-filter"}),y=t(h);return{metricFilter:{Type:"AWS::Logs::MetricFilter",Properties:{LogGroupName:N.Ref(a),FilterPattern:l,MetricTransformations:u.map((S)=>({MetricName:S.metricName,MetricNamespace:S.metricNamespace,MetricValue:S.metricValue,DefaultValue:S.defaultValue,Unit:S.unit}))}},logicalId:y}}static AlarmTypes={highCpu:(a,n,i,s=80,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-high-cpu`,metricName:"CPUUtilization",namespace:"AWS/EC2",statistic:"Average",period:300,evaluationPeriods:2,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:i},alarmActions:c?[c]:void 0}),highMemory:(a,n,i,s=80,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-high-memory`,metricName:"MemoryUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:i},alarmActions:c?[c]:void 0}),highDisk:(a,n,i,s=80,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-high-disk`,metricName:"DiskSpaceUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:i,Filesystem:"/dev/xvda1",MountPath:"/"},alarmActions:c?[c]:void 0}),lambdaErrors:(a,n,i,s=5,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-lambda-errors`,metricName:"Errors",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:i},alarmActions:c?[c]:void 0}),lambdaThrottles:(a,n,i,s=10,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-lambda-throttles`,metricName:"Throttles",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:i},alarmActions:c?[c]:void 0}),apiGateway5xxErrors:(a,n,i,s=10,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-api-5xx-errors`,metricName:"5XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:i},alarmActions:c?[c]:void 0}),apiGateway4xxErrors:(a,n,i,s=50,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-api-4xx-errors`,metricName:"4XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:2,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:i},alarmActions:c?[c]:void 0}),dynamoDBThrottles:(a,n,i,s=5,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-dynamodb-throttles`,metricName:"UserErrors",namespace:"AWS/DynamoDB",statistic:"Sum",period:300,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{TableName:i},alarmActions:c?[c]:void 0}),rdsCpu:(a,n,i,s=80,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-rds-cpu`,metricName:"CPUUtilization",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:2,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{DBInstanceIdentifier:i},alarmActions:c?[c]:void 0}),rdsFreeStorage:(a,n,i,s=5368709120,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-rds-storage`,metricName:"FreeStorageSpace",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:1,threshold:s,comparisonOperator:"LessThanThreshold",dimensions:{DBInstanceIdentifier:i},alarmActions:c?[c]:void 0,unit:"Bytes"}),sqsQueueDepth:(a,n,i,s=100,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-sqs-depth`,metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",statistic:"Average",period:300,evaluationPeriods:2,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{QueueName:i},alarmActions:c?[c]:void 0}),albUnhealthyTargets:(a,n,i,s,c=1,l)=>({slug:a,environment:n,alarmName:`${a}-${n}-alb-unhealthy`,metricName:"UnHealthyHostCount",namespace:"AWS/ApplicationELB",statistic:"Average",period:300,evaluationPeriods:2,threshold:c,comparisonOperator:"GreaterThanThreshold",dimensions:{LoadBalancer:i,TargetGroup:s},alarmActions:l?[l]:void 0}),sesBounceRate:(a,n,i=5,s)=>({slug:a,environment:n,alarmName:`${a}-${n}-ses-bounce-rate`,metricName:"Reputation.BounceRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:i/100,comparisonOperator:"GreaterThanThreshold",alarmActions:s?[s]:void 0}),sesComplaintRate:(a,n,i=0.1,s)=>({slug:a,environment:n,alarmName:`${a}-${n}-ses-complaint-rate`,metricName:"Reputation.ComplaintRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:i/100,comparisonOperator:"GreaterThanThreshold",alarmActions:s?[s]:void 0}),smsDeliveryFailure:(a,n,i,s=10,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-sms-delivery-failure`,metricName:"DirectSendMessagePermanentFailure",namespace:"AWS/Pinpoint",statistic:"Sum",period:300,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{ApplicationId:i},alarmActions:c?[c]:void 0}),smsSpendLimit:(a,n,i=100,s)=>({slug:a,environment:n,alarmName:`${a}-${n}-sms-spend-limit`,metricName:"DirectSendMessageSpend",namespace:"AWS/Pinpoint",statistic:"Sum",period:86400,evaluationPeriods:1,threshold:i,comparisonOperator:"GreaterThanThreshold",alarmActions:s?[s]:void 0}),connectMissedCalls:(a,n,i,s=5,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-connect-missed-calls`,metricName:"MissedCalls",namespace:"AWS/Connect",statistic:"Sum",period:3600,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:i},alarmActions:c?[c]:void 0})};static DashboardWidgets={metric:(a,n,i,s,c,l)=>({type:"metric",x:a,y:n,width:i,height:s,properties:{metrics:c,title:l||"Metrics",region:"us-east-1",period:300}}),text:(a,n,i,s,c)=>({type:"text",x:a,y:n,width:i,height:s,properties:{markdown:c}}),log:(a,n,i,s,c,l)=>({type:"log",x:a,y:n,width:i,height:s,properties:{query:`SOURCE '${c.join("' | SOURCE '")}'
2310
2310
  | fields @timestamp, @message
2311
2311
  | sort @timestamp desc
2312
2312
  | limit 20`,region:"us-east-1",title:l||"Logs"}})};static RetentionPeriods={ONE_DAY:1,THREE_DAYS:3,FIVE_DAYS:5,ONE_WEEK:7,TWO_WEEKS:14,ONE_MONTH:30,TWO_MONTHS:60,THREE_MONTHS:90,FOUR_MONTHS:120,FIVE_MONTHS:150,SIX_MONTHS:180,ONE_YEAR:365,THIRTEEN_MONTHS:400,EIGHTEEN_MONTHS:545,TWO_YEARS:731,FIVE_YEARS:1827,TEN_YEARS:3653,NEVER_EXPIRE:void 0};static FilterPatterns={errors:"[time, request_id, event_type = ERROR*, ...]",all:"",jsonField:(a,n)=>`{ $.${a} = "${n}" }`,httpStatus:(a)=>`[..., status_code = ${a}, ...]`,http4xx:"[..., status_code = 4*, ...]",http5xx:"[..., status_code = 5*, ...]"};static createApplicationDashboard(a){let{slug:n,environment:i,region:s="us-east-1",components:c={}}=a,l=[],u=0;if(l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:`# ${n.toUpperCase()} Dashboard (${i})`}}),u+=1,c.ec2InstanceIds&&c.ec2InstanceIds.length>0)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## EC2 Instances"}}),u+=1,l.push({type:"metric",x:0,y:u,width:8,height:6,properties:{title:"CPU Utilization",region:s,metrics:c.ec2InstanceIds.map((h)=>["AWS/EC2","CPUUtilization","InstanceId",h]),period:300,stat:"Average"}}),l.push({type:"metric",x:8,y:u,width:8,height:6,properties:{title:"Network Traffic",region:s,metrics:[...c.ec2InstanceIds.flatMap((h)=>[["AWS/EC2","NetworkIn","InstanceId",h,{label:`${h} In`}],["AWS/EC2","NetworkOut","InstanceId",h,{label:`${h} Out`}]])],period:300,stat:"Sum"}}),l.push({type:"metric",x:16,y:u,width:8,height:6,properties:{title:"Status Checks",region:s,metrics:c.ec2InstanceIds.map((h)=>["AWS/EC2","StatusCheckFailed","InstanceId",h]),period:60,stat:"Maximum"}}),u+=6;if(c.lambdaFunctionNames&&c.lambdaFunctionNames.length>0)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## Lambda Functions"}}),u+=1,l.push({type:"metric",x:0,y:u,width:8,height:6,properties:{title:"Invocations",region:s,metrics:c.lambdaFunctionNames.map((h)=>["AWS/Lambda","Invocations","FunctionName",h]),period:300,stat:"Sum"}}),l.push({type:"metric",x:8,y:u,width:8,height:6,properties:{title:"Duration",region:s,metrics:c.lambdaFunctionNames.map((h)=>["AWS/Lambda","Duration","FunctionName",h]),period:300,stat:"Average"}}),l.push({type:"metric",x:16,y:u,width:8,height:6,properties:{title:"Errors",region:s,metrics:c.lambdaFunctionNames.map((h)=>["AWS/Lambda","Errors","FunctionName",h]),period:300,stat:"Sum"}}),u+=6;if(c.ecsClusterName&&c.ecsServiceName)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## ECS Service"}}),u+=1,l.push({type:"metric",x:0,y:u,width:8,height:6,properties:{title:"CPU Utilization",region:s,metrics:[["AWS/ECS","CPUUtilization","ClusterName",c.ecsClusterName,"ServiceName",c.ecsServiceName]],period:300,stat:"Average"}}),l.push({type:"metric",x:8,y:u,width:8,height:6,properties:{title:"Memory Utilization",region:s,metrics:[["AWS/ECS","MemoryUtilization","ClusterName",c.ecsClusterName,"ServiceName",c.ecsServiceName]],period:300,stat:"Average"}}),l.push({type:"metric",x:16,y:u,width:8,height:6,properties:{title:"Running Tasks",region:s,metrics:[["ECS/ContainerInsights","RunningTaskCount","ClusterName",c.ecsClusterName,"ServiceName",c.ecsServiceName]],period:60,stat:"Average"}}),u+=6;if(c.albName)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## Application Load Balancer"}}),u+=1,l.push({type:"metric",x:0,y:u,width:8,height:6,properties:{title:"Request Count",region:s,metrics:[["AWS/ApplicationELB","RequestCount","LoadBalancer",c.albName]],period:60,stat:"Sum"}}),l.push({type:"metric",x:8,y:u,width:8,height:6,properties:{title:"Response Time",region:s,metrics:[["AWS/ApplicationELB","TargetResponseTime","LoadBalancer",c.albName]],period:60,stat:"Average"}}),l.push({type:"metric",x:16,y:u,width:8,height:6,properties:{title:"HTTP Errors",region:s,metrics:[["AWS/ApplicationELB","HTTPCode_Target_4XX_Count","LoadBalancer",c.albName,{label:"4XX"}],["AWS/ApplicationELB","HTTPCode_Target_5XX_Count","LoadBalancer",c.albName,{label:"5XX"}]],period:60,stat:"Sum"}}),u+=6;if(c.rdsInstanceId)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## RDS Database"}}),u+=1,l.push({type:"metric",x:0,y:u,width:8,height:6,properties:{title:"CPU Utilization",region:s,metrics:[["AWS/RDS","CPUUtilization","DBInstanceIdentifier",c.rdsInstanceId]],period:300,stat:"Average"}}),l.push({type:"metric",x:8,y:u,width:8,height:6,properties:{title:"Database Connections",region:s,metrics:[["AWS/RDS","DatabaseConnections","DBInstanceIdentifier",c.rdsInstanceId]],period:60,stat:"Sum"}}),l.push({type:"metric",x:16,y:u,width:8,height:6,properties:{title:"Free Storage Space",region:s,metrics:[["AWS/RDS","FreeStorageSpace","DBInstanceIdentifier",c.rdsInstanceId]],period:300,stat:"Average"}}),u+=6;if(c.sqsQueueNames&&c.sqsQueueNames.length>0)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## SQS Queues"}}),u+=1,l.push({type:"metric",x:0,y:u,width:12,height:6,properties:{title:"Messages Visible",region:s,metrics:c.sqsQueueNames.map((h)=>["AWS/SQS","ApproximateNumberOfMessagesVisible","QueueName",h]),period:60,stat:"Sum"}}),l.push({type:"metric",x:12,y:u,width:12,height:6,properties:{title:"Message Age",region:s,metrics:c.sqsQueueNames.map((h)=>["AWS/SQS","ApproximateAgeOfOldestMessage","QueueName",h]),period:60,stat:"Maximum"}}),u+=6;if(c.logGroupNames&&c.logGroupNames.length>0)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## Application Logs"}}),u+=1,l.push({type:"log",x:0,y:u,width:24,height:6,properties:{query:`SOURCE '${c.logGroupNames.join("' | SOURCE '")}'
2313
2313
  | fields @timestamp, @message
2314
2314
  | filter @message like /ERROR|WARN|Exception/
2315
2315
  | sort @timestamp desc
2316
- | limit 50`,region:s,title:"Recent Errors and Warnings"}}),u+=6;return Zs.createDashboard({slug:n,environment:i,widgets:l})}static DashboardTemplates={staticWebsite:(a)=>({slug:a.slug,environment:a.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${a.slug.toUpperCase()} Static Website Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"CloudFront Requests",region:"us-east-1",metrics:[["AWS/CloudFront","Requests","DistributionId",a.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"Error Rate",region:"us-east-1",metrics:[["AWS/CloudFront","4xxErrorRate","DistributionId",a.cloudFrontDistributionId,"Region","Global",{label:"4XX"}],["AWS/CloudFront","5xxErrorRate","DistributionId",a.cloudFrontDistributionId,"Region","Global",{label:"5XX"}]],period:300,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Bytes Downloaded",region:"us-east-1",metrics:[["AWS/CloudFront","BytesDownloaded","DistributionId",a.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:0,y:7,width:12,height:6,properties:{title:"S3 Bucket Size",region:a.region||"us-east-1",metrics:[["AWS/S3","BucketSizeBytes","BucketName",a.s3BucketName,"StorageType","StandardStorage"]],period:86400,stat:"Average"}},{type:"metric",x:12,y:7,width:12,height:6,properties:{title:"S3 Number of Objects",region:a.region||"us-east-1",metrics:[["AWS/S3","NumberOfObjects","BucketName",a.s3BucketName,"StorageType","AllStorageTypes"]],period:86400,stat:"Average"}}]}),serverlessApi:(a)=>({slug:a.slug,environment:a.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${a.slug.toUpperCase()} Serverless API Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"API Requests",region:a.region||"us-east-1",metrics:[["AWS/ApiGateway","Count","ApiName",a.apiGatewayName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"API Latency",region:a.region||"us-east-1",metrics:[["AWS/ApiGateway","Latency","ApiName",a.apiGatewayName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"API Errors",region:a.region||"us-east-1",metrics:[["AWS/ApiGateway","4XXError","ApiName",a.apiGatewayName,{label:"4XX"}],["AWS/ApiGateway","5XXError","ApiName",a.apiGatewayName,{label:"5XX"}]],period:60,stat:"Sum"}},...a.lambdaFunctionNames.map((n,i)=>({type:"metric",x:i%3*8,y:7+Math.floor(i/3)*6,width:8,height:6,properties:{title:`${n} Metrics`,region:a.region||"us-east-1",metrics:[["AWS/Lambda","Invocations","FunctionName",n],["AWS/Lambda","Duration","FunctionName",n],["AWS/Lambda","Errors","FunctionName",n]],period:300,stat:"Sum"}}))]}),containerService:(a)=>({slug:a.slug,environment:a.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${a.slug.toUpperCase()} Container Service Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"ECS CPU",region:a.region||"us-east-1",metrics:[["AWS/ECS","CPUUtilization","ClusterName",a.ecsClusterName,"ServiceName",a.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"ECS Memory",region:a.region||"us-east-1",metrics:[["AWS/ECS","MemoryUtilization","ClusterName",a.ecsClusterName,"ServiceName",a.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Running Tasks",region:a.region||"us-east-1",metrics:[["ECS/ContainerInsights","RunningTaskCount","ClusterName",a.ecsClusterName,"ServiceName",a.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:0,y:7,width:8,height:6,properties:{title:"ALB Requests",region:a.region||"us-east-1",metrics:[["AWS/ApplicationELB","RequestCount","LoadBalancer",a.albName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:7,width:8,height:6,properties:{title:"Response Time",region:a.region||"us-east-1",metrics:[["AWS/ApplicationELB","TargetResponseTime","LoadBalancer",a.albName]],period:60,stat:"Average"}},{type:"metric",x:16,y:7,width:8,height:6,properties:{title:"Healthy Hosts",region:a.region||"us-east-1",metrics:[["AWS/ApplicationELB","HealthyHostCount","LoadBalancer",a.albName]],period:60,stat:"Average"}},...a.rdsInstanceId?[{type:"metric",x:0,y:13,width:12,height:6,properties:{title:"RDS CPU",region:a.region||"us-east-1",metrics:[["AWS/RDS","CPUUtilization","DBInstanceIdentifier",a.rdsInstanceId]],period:300,stat:"Average"}},{type:"metric",x:12,y:13,width:12,height:6,properties:{title:"RDS Connections",region:a.region||"us-east-1",metrics:[["AWS/RDS","DatabaseConnections","DBInstanceIdentifier",a.rdsInstanceId]],period:60,stat:"Sum"}}]:[]]})};static Config={createAlarmConfig:(a)=>{let{metricName:n,namespace:i,threshold:s,comparisonOperator:c="GreaterThanThreshold",evaluationPeriods:l=1,period:u=300,statistic:h="Average",treatMissingData:y="missing"}=a;return{MetricName:n,Namespace:i,Threshold:s,ComparisonOperator:c,EvaluationPeriods:l,Period:u,Statistic:h,TreatMissingData:y}},namespaces:{ec2:"AWS/EC2",ecs:"AWS/ECS",lambda:"AWS/Lambda",rds:"AWS/RDS",sqs:"AWS/SQS",sns:"AWS/SNS",s3:"AWS/S3",cloudfront:"AWS/CloudFront",alb:"AWS/ApplicationELB",nlb:"AWS/NetworkELB",apiGateway:"AWS/ApiGateway",dynamodb:"AWS/DynamoDB",elasticache:"AWS/ElastiCache"},comparisonOperators:{greaterThan:"GreaterThanThreshold",greaterOrEqual:"GreaterThanOrEqualToThreshold",lessThan:"LessThanThreshold",lessOrEqual:"LessThanOrEqualToThreshold"},metrics:{ec2:{cpu:{metricName:"CPUUtilization",namespace:"AWS/EC2"},networkIn:{metricName:"NetworkIn",namespace:"AWS/EC2"},networkOut:{metricName:"NetworkOut",namespace:"AWS/EC2"},statusCheck:{metricName:"StatusCheckFailed",namespace:"AWS/EC2"}},ecs:{cpu:{metricName:"CPUUtilization",namespace:"AWS/ECS"},memory:{metricName:"MemoryUtilization",namespace:"AWS/ECS"}},lambda:{invocations:{metricName:"Invocations",namespace:"AWS/Lambda"},errors:{metricName:"Errors",namespace:"AWS/Lambda"},duration:{metricName:"Duration",namespace:"AWS/Lambda"},throttles:{metricName:"Throttles",namespace:"AWS/Lambda"},concurrentExecutions:{metricName:"ConcurrentExecutions",namespace:"AWS/Lambda"}},rds:{cpu:{metricName:"CPUUtilization",namespace:"AWS/RDS"},connections:{metricName:"DatabaseConnections",namespace:"AWS/RDS"},freeStorage:{metricName:"FreeStorageSpace",namespace:"AWS/RDS"},readLatency:{metricName:"ReadLatency",namespace:"AWS/RDS"},writeLatency:{metricName:"WriteLatency",namespace:"AWS/RDS"}},alb:{requestCount:{metricName:"RequestCount",namespace:"AWS/ApplicationELB"},responseTime:{metricName:"TargetResponseTime",namespace:"AWS/ApplicationELB"},httpCode4xx:{metricName:"HTTPCode_Target_4XX_Count",namespace:"AWS/ApplicationELB"},httpCode5xx:{metricName:"HTTPCode_Target_5XX_Count",namespace:"AWS/ApplicationELB"},healthyHosts:{metricName:"HealthyHostCount",namespace:"AWS/ApplicationELB"}},sqs:{messagesVisible:{metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS"},messagesDelayed:{metricName:"ApproximateNumberOfMessagesDelayed",namespace:"AWS/SQS"},messageAge:{metricName:"ApproximateAgeOfOldestMessage",namespace:"AWS/SQS"}}},presets:{highCpu:(a=80)=>({metricName:"CPUUtilization",threshold:a,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highMemory:(a=80)=>({metricName:"MemoryUtilization",threshold:a,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highErrors:(a=10)=>({metricName:"Errors",threshold:a,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:1,period:60,statistic:"Sum"}),highLatency:(a=5000)=>({metricName:"Duration",threshold:a,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowHealthyHosts:(a=1)=>({metricName:"HealthyHostCount",namespace:"AWS/ApplicationELB",threshold:a,comparisonOperator:"LessThanThreshold",evaluationPeriods:2,period:60,statistic:"Minimum"}),queueDepth:(a=1000)=>({metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",threshold:a,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowStorage:(a=10737418240)=>({metricName:"FreeStorageSpace",namespace:"AWS/RDS",threshold:a,comparisonOperator:"LessThanThreshold",evaluationPeriods:1,period:300,statistic:"Average"})}}}class U{static createUserPool(a){let{slug:n,environment:i,userPoolName:s,aliasAttributes:c,autoVerifiedAttributes:l,passwordPolicy:u,mfaConfiguration:h,emailConfiguration:y,smsConfiguration:S,lambdaTriggers:b,userPoolAddOns:A,accountRecoverySetting:C}=a,T=s||r({slug:n,environment:i,resourceType:"user-pool"}),v=t(T),w={Type:"AWS::Cognito::UserPool",Properties:{UserPoolName:T,Policies:u?{PasswordPolicy:{MinimumLength:u.minimumLength,RequireLowercase:u.requireLowercase,RequireUppercase:u.requireUppercase,RequireNumbers:u.requireNumbers,RequireSymbols:u.requireSymbols,TemporaryPasswordValidityDays:u.temporaryPasswordValidityDays}}:void 0,MfaConfiguration:h,Schema:[{Name:"email",AttributeDataType:"String",Required:!0,Mutable:!1}]}};if(c&&c.length>0)w.Properties.UsernameAttributes=c;if(l&&l.length>0)w.Properties.AutoVerifiedAttributes=l;if(y)w.Properties.EmailConfiguration={EmailSendingAccount:y.emailSendingAccount,From:y.from,ReplyToEmailAddress:y.replyToEmailAddress,SourceArn:y.sourceArn,ConfigurationSet:y.configurationSet};if(S)w.Properties.SmsConfiguration={ExternalId:S.externalId,SnsCallerArn:S.snsCallerArn};if(b)w.Properties.LambdaConfig={PreSignUp:b.preSignUp,PostConfirmation:b.postConfirmation,PreAuthentication:b.preAuthentication,PostAuthentication:b.postAuthentication,CustomMessage:b.customMessage,DefineAuthChallenge:b.defineAuthChallenge,CreateAuthChallenge:b.createAuthChallenge,VerifyAuthChallengeResponse:b.verifyAuthChallengeResponse,PreTokenGeneration:b.preTokenGeneration,UserMigration:b.userMigration};if(A)w.Properties.UserPoolAddOns={AdvancedSecurityMode:A.advancedSecurityMode};if(C)w.Properties.AccountRecoverySetting={RecoveryMechanisms:C.recoveryMechanisms};return{userPool:w,logicalId:v}}static createUserPoolClient(a,n){let{slug:i,environment:s,clientName:c,generateSecret:l=!1,refreshTokenValidity:u,accessTokenValidity:h,idTokenValidity:y,tokenValidityUnits:S,readAttributes:b,writeAttributes:A,explicitAuthFlows:C,preventUserExistenceErrors:T,enableTokenRevocation:v,callbackURLs:w,logoutURLs:R,allowedOAuthFlows:k,allowedOAuthScopes:W,allowedOAuthFlowsUserPoolClient:P,supportedIdentityProviders:V}=n,B=c||r({slug:i,environment:s,resourceType:"user-pool-client"}),j=t(B);return{client:{Type:"AWS::Cognito::UserPoolClient",Properties:{ClientName:B,UserPoolId:N.Ref(a),GenerateSecret:l,RefreshTokenValidity:u,AccessTokenValidity:h,IdTokenValidity:y,TokenValidityUnits:S,ReadAttributes:b,WriteAttributes:A,ExplicitAuthFlows:C,PreventUserExistenceErrors:T,EnableTokenRevocation:v,CallbackURLs:w,LogoutURLs:R,AllowedOAuthFlows:k,AllowedOAuthScopes:W,AllowedOAuthFlowsUserPoolClient:P,SupportedIdentityProviders:V}},logicalId:j}}static createUserPoolDomain(a,n){let{slug:i,environment:s,domain:c,customDomainConfig:l}=n,u=r({slug:i,environment:s,resourceType:"user-pool-domain"}),h=t(u);return{domain:{Type:"AWS::Cognito::UserPoolDomain",Properties:{Domain:c,UserPoolId:N.Ref(a),CustomDomainConfig:l}},logicalId:h}}static createIdentityPool(a){let{slug:n,environment:i,identityPoolName:s,allowUnauthenticatedIdentities:c=!1,cognitoIdentityProviders:l,supportedLoginProviders:u,samlProviderARNs:h,openIdConnectProviderARNs:y}=a,S=s||r({slug:n,environment:i,resourceType:"identity-pool"}),b=t(S);return{identityPool:{Type:"AWS::Cognito::IdentityPool",Properties:{IdentityPoolName:S,AllowUnauthenticatedIdentities:c,CognitoIdentityProviders:l,SupportedLoginProviders:u,SamlProviderARNs:h,OpenIdConnectProviderARNs:y}},logicalId:b}}static createIdentityPoolRoleAttachment(a,n){let{slug:i,environment:s,authenticatedRole:c,unauthenticatedRole:l,roleMappings:u}=n,h=r({slug:i,environment:s,resourceType:"identity-pool-role-attachment"}),y=t(h),S={authenticated:c};if(l)S.unauthenticated=l;return{attachment:{Type:"AWS::Cognito::IdentityPoolRoleAttachment",Properties:{IdentityPoolId:N.Ref(a),Roles:S,RoleMappings:u}},logicalId:y}}static createAuthenticatedRole(a){let{slug:n,environment:i,identityPoolLogicalId:s}=a,c=r({slug:n,environment:i,resourceType:"cognito-authenticated-role"}),l=t(c);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:c,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":N.Ref(s)},"ForAnyValue:StringLike":{"cognito-identity.amazonaws.com:amr":"authenticated"}}}]},Policies:[{PolicyName:"CognitoAuthenticatedPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["cognito-sync:*","cognito-identity:*"],Resource:"*"}]}}],Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:i}]}},logicalId:l}}static createUnauthenticatedRole(a){let{slug:n,environment:i,identityPoolLogicalId:s}=a,c=r({slug:n,environment:i,resourceType:"cognito-unauthenticated-role"}),l=t(c);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:c,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":N.Ref(s)},"ForAnyValue:StringLike":{"cognito-identity.amazonaws.com:amr":"unauthenticated"}}}]},Policies:[{PolicyName:"CognitoUnauthenticatedPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["cognito-sync:*"],Resource:"*"}]}}],Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:i}]}},logicalId:l}}static PasswordPolicies={relaxed:()=>({minimumLength:8,requireLowercase:!1,requireUppercase:!1,requireNumbers:!1,requireSymbols:!1,temporaryPasswordValidityDays:7}),standard:()=>({minimumLength:8,requireLowercase:!0,requireUppercase:!0,requireNumbers:!0,requireSymbols:!1,temporaryPasswordValidityDays:3}),strict:()=>({minimumLength:12,requireLowercase:!0,requireUppercase:!0,requireNumbers:!0,requireSymbols:!0,temporaryPasswordValidityDays:1})};static AuthFlows={standard:["ALLOW_USER_SRP_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],admin:["ALLOW_ADMIN_USER_PASSWORD_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],custom:["ALLOW_CUSTOM_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],all:["ALLOW_USER_SRP_AUTH","ALLOW_USER_PASSWORD_AUTH","ALLOW_ADMIN_USER_PASSWORD_AUTH","ALLOW_CUSTOM_AUTH","ALLOW_REFRESH_TOKEN_AUTH"]};static OAuthScopes={basic:["openid","email","profile"],all:["openid","email","profile","phone","aws.cognito.signin.user.admin"]};static UseCases={webApp:(a,n,i)=>{let{userPool:s,logicalId:c}=U.createUserPool({slug:a,environment:n,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:U.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:l,logicalId:u}=U.createUserPoolClient(c,{slug:a,environment:n,explicitAuthFlows:[...U.AuthFlows.standard],callbackURLs:[i],allowedOAuthFlows:["code"],allowedOAuthScopes:[...U.OAuthScopes.basic],allowedOAuthFlowsUserPoolClient:!0});return{userPool:s,poolId:c,client:l,clientId:u}},mobileApp:(a,n)=>{let{userPool:i,logicalId:s}=U.createUserPool({slug:a,environment:n,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:U.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:c,logicalId:l}=U.createUserPoolClient(s,{slug:a,environment:n,explicitAuthFlows:[...U.AuthFlows.standard]}),{identityPool:u,logicalId:h}=U.createIdentityPool({slug:a,environment:n,allowUnauthenticatedIdentities:!1,cognitoIdentityProviders:[{ClientId:N.Ref(l),ProviderName:N.GetAtt(s,"ProviderName")}]}),{role:y,logicalId:S}=U.createAuthenticatedRole({slug:a,environment:n,identityPoolLogicalId:h}),{attachment:b,logicalId:A}=U.createIdentityPoolRoleAttachment(h,{slug:a,environment:n,authenticatedRole:N.GetAtt(S,"Arn")});return{userPool:i,poolId:s,client:c,clientId:l,identityPool:u,identityPoolId:h,authRole:y,authRoleId:S,attachment:b,attachmentId:A}}}}class Q{static createApplication(a){let{slug:n,environment:i,applicationName:s,computePlatform:c}=a,l=s||r({slug:n,environment:i,resourceType:"deploy-app"}),u=t(l);return{application:{Type:"AWS::CodeDeploy::Application",Properties:{ApplicationName:l,ComputePlatform:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:i}]}},logicalId:u}}static createDeploymentGroup(a,n){let{slug:i,environment:s,deploymentGroupName:c,serviceRoleArn:l,autoScalingGroups:u,ec2TagFilters:h,deploymentConfigName:y,autoRollbackConfiguration:S,alarmConfiguration:b,loadBalancerInfo:A,blueGreenDeploymentConfiguration:C}=n,T=c||r({slug:i,environment:s,resourceType:"deploy-group"}),v=t(T);return{deploymentGroup:{Type:"AWS::CodeDeploy::DeploymentGroup",Properties:{ApplicationName:N.Ref(a),DeploymentGroupName:T,ServiceRoleArn:l,AutoScalingGroups:u,Ec2TagFilters:h?.map((w)=>({Key:w.key,Value:w.value,Type:w.type})),DeploymentConfigName:y,AutoRollbackConfiguration:S?{Enabled:S.enabled,Events:S.events}:void 0,AlarmConfiguration:b?{Enabled:b.enabled,Alarms:b.alarms?.map((w)=>({Name:w.name})),IgnorePollAlarmFailure:b.ignorePollAlarmFailure}:void 0,LoadBalancerInfo:A?{TargetGroupInfoList:A.targetGroupInfoList?.map((w)=>({Name:w.name})),ElbInfoList:A.elbInfoList?.map((w)=>({Name:w.name}))}:void 0,BlueGreenDeploymentConfiguration:C?{TerminateBlueInstancesOnDeploymentSuccess:C.terminateBlueInstancesOnDeploymentSuccess?{Action:C.terminateBlueInstancesOnDeploymentSuccess.action,TerminationWaitTimeInMinutes:C.terminateBlueInstancesOnDeploymentSuccess.terminationWaitTimeInMinutes}:void 0,DeploymentReadyOption:C.deploymentReadyOption?{ActionOnTimeout:C.deploymentReadyOption.actionOnTimeout,WaitTimeInMinutes:C.deploymentReadyOption.waitTimeInMinutes}:void 0,GreenFleetProvisioningOption:C.greenFleetProvisioningOption?{Action:C.greenFleetProvisioningOption.action}:void 0}:void 0,Tags:[{Key:"Name",Value:T},{Key:"Environment",Value:s}]}},logicalId:v}}static createDeploymentConfig(a){let{slug:n,environment:i,deploymentConfigName:s,minimumHealthyHosts:c,trafficRoutingConfig:l}=a,u=s||r({slug:n,environment:i,resourceType:"deploy-config"}),h=t(u);return{deploymentConfig:{Type:"AWS::CodeDeploy::DeploymentConfig",Properties:{DeploymentConfigName:u,MinimumHealthyHosts:c?{Type:c.type,Value:c.value}:void 0,TrafficRoutingConfig:l?{Type:l.type,TimeBasedCanary:l.timeBasedCanary?{CanaryPercentage:l.timeBasedCanary.canaryPercentage,CanaryInterval:l.timeBasedCanary.canaryInterval}:void 0,TimeBasedLinear:l.timeBasedLinear?{LinearPercentage:l.timeBasedLinear.linearPercentage,LinearInterval:l.timeBasedLinear.linearInterval}:void 0}:void 0}},logicalId:h}}static DeploymentConfigs={allAtOnce:()=>({type:"FLEET_PERCENT",value:0}),halfAtATime:()=>({type:"FLEET_PERCENT",value:50}),oneAtATime:()=>({type:"HOST_COUNT",value:1}),custom:(a,n)=>({type:a,value:n})};static TrafficRouting={allAtOnce:()=>({type:"AllAtOnce"}),canary:(a,n)=>({type:"TimeBasedCanary",timeBasedCanary:{canaryPercentage:a,canaryInterval:n}}),linear:(a,n)=>({type:"TimeBasedLinear",timeBasedLinear:{linearPercentage:a,linearInterval:n}})};static RollbackConfigs={onFailure:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE"]}),onAlarmOrFailure:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE","DEPLOYMENT_STOP_ON_ALARM"]}),onAllEvents:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE","DEPLOYMENT_STOP_ON_ALARM","DEPLOYMENT_STOP_ON_REQUEST"]}),disabled:()=>({enabled:!1})};static BlueGreenConfigs={standard:()=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withDelay:(a)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:a},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withManualApproval:(a)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"STOP_DEPLOYMENT",waitTimeInMinutes:a},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),keepBlue:()=>({terminateBlueInstancesOnDeploymentSuccess:{action:"KEEP_ALIVE"},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}})};static UseCases={ec2Deployment:(a,n,i,s)=>{let{application:c,logicalId:l}=Q.createApplication({slug:a,environment:n,computePlatform:"Server"}),{deploymentGroup:u,logicalId:h}=Q.createDeploymentGroup(l,{slug:a,environment:n,serviceRoleArn:i,autoScalingGroups:s,deploymentConfigName:"CodeDeployDefault.OneAtATime",autoRollbackConfiguration:Q.RollbackConfigs.onFailure()});return{application:c,appId:l,deploymentGroup:u,groupId:h}},lambdaCanaryDeployment:(a,n,i,s=10,c=5)=>{let{application:l,logicalId:u}=Q.createApplication({slug:a,environment:n,computePlatform:"Lambda"}),{deploymentConfig:h,logicalId:y}=Q.createDeploymentConfig({slug:a,environment:n,trafficRoutingConfig:Q.TrafficRouting.canary(s,c)}),{deploymentGroup:S,logicalId:b}=Q.createDeploymentGroup(u,{slug:a,environment:n,serviceRoleArn:i,deploymentConfigName:N.Ref(y),autoRollbackConfiguration:Q.RollbackConfigs.onAlarmOrFailure()});return{application:l,appId:u,deploymentConfig:h,configId:y,deploymentGroup:S,groupId:b}},ecsBlueGreenDeployment:(a,n,i,s)=>{let{application:c,logicalId:l}=Q.createApplication({slug:a,environment:n,computePlatform:"ECS"}),{deploymentGroup:u,logicalId:h}=Q.createDeploymentGroup(l,{slug:a,environment:n,serviceRoleArn:i,loadBalancerInfo:{targetGroupInfoList:[{name:s}]},blueGreenDeploymentConfiguration:Q.BlueGreenConfigs.standard(),autoRollbackConfiguration:Q.RollbackConfigs.onFailure()});return{application:c,appId:l,deploymentGroup:u,groupId:h}}};static Strategies={rolling:(a=25)=>({type:"rolling",batchPercentage:a}),blueGreen:()=>({type:"blue-green"}),canary:(a=10,n=5)=>({type:"canary",canaryPercentage:a,canaryInterval:n}),allAtOnce:()=>({type:"all-at-once"})}}class D{static ContentTypes={".html":"text/html",".htm":"text/html",".css":"text/css",".js":"application/javascript",".mjs":"application/javascript",".json":"application/json",".xml":"application/xml",".svg":"image/svg+xml",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".avif":"image/avif",".ico":"image/x-icon",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".otf":"font/otf",".eot":"application/vnd.ms-fontobject",".pdf":"application/pdf",".txt":"text/plain",".md":"text/markdown",".map":"application/json"};static NoHashPatterns=[/^index\.html$/,/^favicon\.ico$/,/^robots\.txt$/,/^sitemap\.xml$/,/^manifest\.json$/,/^\.well-known\//,/^_redirects$/,/^_headers$/];static computeFileHash(a,n="md5"){let i=rt(a);return br(n).update(i).digest("hex")}static computeShortHash(a){return D.computeFileHash(a).slice(0,8)}static getContentType(a){let n=sa(a).toLowerCase();return D.ContentTypes[n]||"application/octet-stream"}static shouldHashFile(a,n){return![...D.NoHashPatterns,...n||[]].some((i)=>i.test(a))}static generateHashedFilename(a,n){let i=sa(a),s=vr(a,i),c=ia(a);if(c===".")return`${s}.${n}${i}`;return Ke(c,`${s}.${n}${i}`)}static collectFiles(a,n){let i=[],s=n||a;if(!Et(a))return i;let c=Cr(a,{withFileTypes:!0});for(let l of c){let u=Ke(a,l.name);if(l.isDirectory())i.push(...D.collectFiles(u,s));else if(l.isFile())i.push(u)}return i}static hashDirectory(a){let{sourceDir:n,outputDir:i,excludePatterns:s=[],hashAlgorithm:c="md5",copyUnhashed:l=!0}=a,u=D.collectFiles(n),h=[],y={};for(let b of u){let A=b.replace(n,"").replace(/^[/\\]/,""),C=D.shouldHashFile(A,s),T=Tr(b),v=C?D.computeFileHash(b,c).slice(0,8):"",w=C?D.generateHashedFilename(A,v):A,R={originalPath:A,hashedPath:w,hash:v,size:T.size,contentType:D.getContentType(b)};if(h.push(R),y[A]=w,i){let k=Ke(i,w),W=ia(k);if(!Et(W)){let{mkdirSync:P}=Za("node:fs");P(W,{recursive:!0})}if(C||l)Ar(b,k)}}let S={version:"1.0",timestamp:new Date().toISOString(),assets:h,hashMap:y};if(i){let b=Ke(i,"asset-manifest.json");nt(b,JSON.stringify(S,null,2))}return S}static getInvalidationPaths(a,n){let i=[];if(!a)return["/*"];let s=a.hashMap,c=n.hashMap;for(let[l,u]of Object.entries(c)){let h=s[l];if(!h||h!==u){if(i.push(`/${l}`),h&&h!==u)i.push(`/${h}`)}}for(let[l,u]of Object.entries(s))if(!c[l])i.push(`/${l}`),i.push(`/${u}`);if(i.length>100)return["/*"];return[...new Set(i)]}static updateHtmlReferences(a){let{htmlDir:n,manifest:i,basePath:s=""}=a,c=D.collectFiles(n).filter((l)=>l.endsWith(".html")||l.endsWith(".htm"));for(let l of c){let u=rt(l,"utf-8");for(let[h,y]of Object.entries(i.hashMap)){if(h===y)continue;let S=[new RegExp(`(src|href)=["']${s}/?${D.escapeRegExp(h)}["']`,"g"),new RegExp(`url\\(["']?${s}/?${D.escapeRegExp(h)}["']?\\)`,"g")];for(let b of S)u=u.replace(b,(A)=>A.replace(h,y))}nt(l,u)}}static updateCssReferences(a){let{cssDir:n,manifest:i,basePath:s=""}=a,c=D.collectFiles(n).filter((l)=>l.endsWith(".css"));for(let l of c){let u=rt(l,"utf-8");for(let[h,y]of Object.entries(i.hashMap)){if(h===y)continue;let S=new RegExp(`url\\(["']?${s}/?${D.escapeRegExp(h)}["']?\\)`,"g");u=u.replace(S,`url(${s}/${y})`)}nt(l,u)}}static escapeRegExp(a){return a.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}static generateS3DeploymentManifest(a){let{sourceDir:n,keyPrefix:i="",excludePatterns:s=[],cacheControl:c={hashed:"public, max-age=31536000, immutable",unhashed:"public, max-age=3600",html:"public, max-age=0, must-revalidate"}}=a;return D.hashDirectory({sourceDir:n,excludePatterns:s}).assets.map((l)=>{let u=l.hash!=="",h=l.contentType==="text/html",y=c.unhashed||"public, max-age=3600";if(h)y=c.html||"public, max-age=0, must-revalidate";else if(u)y=c.hashed||"public, max-age=31536000, immutable";return{localPath:Ke(n,l.originalPath),s3Key:i?`${i}/${l.hashedPath}`:l.hashedPath,contentType:l.contentType,cacheControl:y,hash:l.hash}})}static compareManifests(a,n){let i={added:[],removed:[],changed:[],unchanged:[]},s=new Set(Object.keys(a.hashMap)),c=new Set(Object.keys(n.hashMap));for(let l of c)if(!s.has(l))i.added.push(l);for(let l of s)if(!c.has(l))i.removed.push(l);for(let l of c)if(s.has(l))if(a.hashMap[l]!==n.hashMap[l])i.changed.push(l);else i.unchanged.push(l);return i}static loadManifest(a){if(!Et(a))return null;try{let n=rt(a,"utf-8");return JSON.parse(n)}catch{return null}}static saveManifest(a,n){nt(n,JSON.stringify(a,null,2))}}class Ai{static createSecret(a){let{slug:n,environment:i,secretName:s,description:c,secretString:l,kmsKeyId:u,tags:h}=a,y=s||r({slug:n,environment:i,resourceType:"secret"}),S=t(y),b={Type:"AWS::SecretsManager::Secret",Properties:{Name:y,Description:c,SecretString:l,Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:i},...h?Object.entries(h).map(([A,C])=>({Key:A,Value:C})):[]]}};if(u)b.Properties.KmsKeyId=u;return{secret:b,logicalId:S}}static createGeneratedSecret(a){let{slug:n,environment:i,secretName:s,description:c,excludeCharacters:l,excludeLowercase:u,excludeNumbers:h,excludePunctuation:y,excludeUppercase:S,passwordLength:b,requireEachIncludedType:A,kmsKeyId:C,tags:T}=a,v=s||r({slug:n,environment:i,resourceType:"secret"}),w=t(v),R={Type:"AWS::SecretsManager::Secret",Properties:{Name:v,Description:c,GenerateSecretString:{ExcludeCharacters:l,ExcludeLowercase:u,ExcludeNumbers:h,ExcludePunctuation:y,ExcludeUppercase:S,PasswordLength:b||32,RequireEachIncludedType:A!==!1},Tags:[{Key:"Name",Value:v},{Key:"Environment",Value:i},...T?Object.entries(T).map(([k,W])=>({Key:k,Value:W})):[]]}};if(C)R.Properties.KmsKeyId=C;return{secret:R,logicalId:w}}static createDatabaseSecret(a){let{slug:n,environment:i,secretName:s,username:c,dbname:l,engine:u,host:h,port:y,kmsKeyId:S}=a,b=s||r({slug:n,environment:i,resourceType:"db-secret"}),A=t(b),C={username:c};if(l)C.dbname=l;if(u)C.engine=u;if(h)C.host=h;if(y)C.port=y;let T={Type:"AWS::SecretsManager::Secret",Properties:{Name:b,Description:`Database credentials for ${c}`,GenerateSecretString:{SecretStringTemplate:JSON.stringify(C),GenerateStringKey:"password",PasswordLength:32,ExcludeCharacters:'"@/\\',RequireEachIncludedType:!0},Tags:[{Key:"Name",Value:b},{Key:"Environment",Value:i},{Key:"Type",Value:"database"}]}};if(S)T.Properties.KmsKeyId=S;return{secret:T,logicalId:A}}static attachToDatabase(a){let{slug:n,environment:i,secretId:s,targetId:c,targetType:l}=a,u=r({slug:n,environment:i,resourceType:"secret-attachment"}),h=t(u);return{attachment:{Type:"AWS::SecretsManager::SecretTargetAttachment",Properties:{SecretId:s,TargetId:c,TargetType:l}},logicalId:h}}static enableRotation(a){let{slug:n,environment:i,secretId:s,rotationLambdaArn:c,automaticallyAfterDays:l,rotationType:u,kmsKeyArn:h,vpcSecurityGroupIds:y,vpcSubnetIds:S}=a,b=r({slug:n,environment:i,resourceType:"secret-rotation"}),A=t(b),C={Type:"AWS::SecretsManager::RotationSchedule",Properties:{SecretId:s,RotationRules:{AutomaticallyAfterDays:l||30}}};if(c)C.Properties.RotationLambdaARN=c;else if(u)C.Properties.HostedRotationLambda={RotationType:u,KmsKeyArn:h,VpcSecurityGroupIds:y,VpcSubnetIds:S};return{rotation:C,logicalId:A}}static SecretTypes={apiKey:(a,n,i)=>Ai.createGeneratedSecret({slug:a,environment:n,secretName:`${a}-${n}-${i}-api-key`,description:`API key for ${i}`,passwordLength:32,excludePunctuation:!0,excludeLowercase:!1,excludeUppercase:!1,excludeNumbers:!1}),oauthClientSecret:(a,n,i)=>Ai.createGeneratedSecret({slug:a,environment:n,secretName:`${a}-${n}-${i}-oauth-secret`,description:`OAuth client secret for ${i}`,passwordLength:64,excludeCharacters:"\"'`\\/@",requireEachIncludedType:!0}),jwtSecret:(a,n)=>Ai.createGeneratedSecret({slug:a,environment:n,secretName:`${a}-${n}-jwt-secret`,description:"JWT signing secret",passwordLength:64,excludePunctuation:!0}),encryptionKey:(a,n)=>Ai.createGeneratedSecret({slug:a,environment:n,secretName:`${a}-${n}-encryption-key`,description:"Data encryption key",passwordLength:64,excludeCharacters:"+/=",excludePunctuation:!0})};static RotationTypes={MySQLSingleUser:"MySQLSingleUser",MySQLMultiUser:"MySQLMultiUser",PostgreSQLSingleUser:"PostgreSQLSingleUser",PostgreSQLMultiUser:"PostgreSQLMultiUser",OracleSingleUser:"OracleSingleUser",OracleMultiUser:"OracleMultiUser",MariaDBSingleUser:"MariaDBSingleUser",MariaDBMultiUser:"MariaDBMultiUser",SQLServerSingleUser:"SQLServerSingleUser",SQLServerMultiUser:"SQLServerMultiUser",RedshiftSingleUser:"RedshiftSingleUser",RedshiftMultiUser:"RedshiftMultiUser",MongoDBSingleUser:"MongoDBSingleUser",MongoDBMultiUser:"MongoDBMultiUser"}}class E{static createParameter(a){let{slug:n,environment:i,parameterName:s,value:c,type:l="String",description:u,tier:h="Standard",tags:y}=a,S=s||r({slug:n,environment:i,resourceType:"parameter"}),b=t(S);return{parameter:{Type:"AWS::SSM::Parameter",Properties:{Name:`/${n}/${i}/${S}`,Type:l,Value:c,Description:u,Tier:h,Tags:{Name:S,Environment:i,...y}}},logicalId:b}}static createString(a,n,i,s,c){return E.createParameter({slug:a,environment:n,parameterName:i,value:s,type:"String",description:c})}static createSecureString(a,n,i,s,c){return E.createParameter({slug:a,environment:n,parameterName:i,value:s,type:"SecureString",description:c})}static createStringList(a,n,i,s,c){return E.createParameter({slug:a,environment:n,parameterName:i,value:s.join(","),type:"StringList",description:c})}static Parameters={databaseUrl:(a,n,i)=>E.createSecureString(a,n,"database-url",i,"Database connection URL"),apiEndpoint:(a,n,i)=>E.createString(a,n,"api-endpoint",i,"API endpoint URL"),appVersion:(a,n,i)=>E.createString(a,n,"app-version",i,"Application version"),featureFlags:(a,n,i)=>E.createStringList(a,n,"feature-flags",i,"Enabled feature flags"),apiKey:(a,n,i,s)=>E.createSecureString(a,n,`${i}-api-key`,s,`API key for ${i}`),oauthCredentials:(a,n,i,s)=>{let c=E.createString(a,n,"oauth-client-id",i,"OAuth client ID"),l=E.createSecureString(a,n,"oauth-client-secret",s,"OAuth client secret");return{clientId:c,clientSecret:l}},smtpCredentials:(a,n,i,s,c,l)=>{let u=E.createString(a,n,"smtp-username",i,"SMTP username"),h=E.createSecureString(a,n,"smtp-password",s,"SMTP password"),y=E.createString(a,n,"smtp-host",c,"SMTP host"),S=E.createString(a,n,"smtp-port",l.toString(),"SMTP port");return{username:u,password:h,host:y,port:S}},redisUrl:(a,n,i)=>E.createSecureString(a,n,"redis-url",i,"Redis connection URL"),s3Bucket:(a,n,i)=>E.createString(a,n,"s3-bucket",i,"S3 bucket name"),cloudFrontDistribution:(a,n,i)=>E.createString(a,n,"cloudfront-distribution-id",i,"CloudFront distribution ID")}}class Qt{static createDomain(a){let{slug:n,environment:i,domainName:s,engineVersion:c="OpenSearch_2.11",instanceType:l="t3.small.search",instanceCount:u=1,volumeSize:h=10,volumeType:y="gp3",dedicatedMaster:S=!1,dedicatedMasterType:b,dedicatedMasterCount:A=3,multiAz:C=!1,availabilityZoneCount:T=2,vpc:v,encryption:w,enforceHttps:R=!0,tlsSecurityPolicy:k="Policy-Min-TLS-1-2-2019-07",advancedSecurity:W,autoSnapshotHour:P=0,autoTune:V=!0,tags:B={}}=a,j=s||r({slug:n,environment:i,resourceType:"search"}),J=t(j);return{domain:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:j,EngineVersion:c,ClusterConfig:{InstanceType:l,InstanceCount:u,DedicatedMasterEnabled:S,...S&&{DedicatedMasterType:b||l,DedicatedMasterCount:A},ZoneAwarenessEnabled:C,...C&&{ZoneAwarenessConfig:{AvailabilityZoneCount:T}}},EBSOptions:{EBSEnabled:!0,VolumeType:y,VolumeSize:h},DomainEndpointOptions:{EnforceHTTPS:R,TLSSecurityPolicy:k},SnapshotOptions:{AutomatedSnapshotStartHour:P},...v&&{VPCOptions:{SubnetIds:v.subnetIds,SecurityGroupIds:v.securityGroupIds}},...w&&{EncryptionAtRestOptions:{Enabled:w.atRest??!0,...w.kmsKeyId&&{KmsKeyId:w.kmsKeyId}},NodeToNodeEncryptionOptions:{Enabled:w.nodeToNode??!0}},...W&&{AdvancedSecurityOptions:{Enabled:W.enabled,InternalUserDatabaseEnabled:W.internalUserDatabase??!0,...W.masterUserName&&W.masterUserPassword&&{MasterUserOptions:{MasterUserName:W.masterUserName,MasterUserPassword:W.masterUserPassword}},...W.masterUserArn&&{MasterUserOptions:{MasterUserARN:W.masterUserArn}}}},...V&&{AutoTuneOptions:{DesiredState:"ENABLED"}},Tags:[{Key:"Name",Value:j},{Key:"Environment",Value:i},...Object.entries(B).map(([K,X])=>({Key:K,Value:X}))]}},logicalId:J}}static createAccessPolicy(a,n){let{ipAddresses:i,iamPrincipalArns:s,allowAll:c,vpcEndpoint:l}=n;if(c)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:a}]};let u=[];if(s&&s.length>0)u.push({Effect:"Allow",Principal:{AWS:s},Action:"es:*",Resource:a});if(i&&i.length>0)u.push({Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:a,Condition:{IpAddress:{"aws:SourceIp":i}}});if(l)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:a}]};return{Version:"2012-10-17",Statement:u}}static DomainPresets={development:(a,n)=>Qt.createDomain({slug:a,environment:n,instanceType:"t3.small.search",instanceCount:1,volumeSize:10,multiAz:!1,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!1}),production:(a,n,i)=>Qt.createDomain({slug:a,environment:n,instanceType:"m6g.large.search",instanceCount:3,volumeSize:100,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"m6g.large.search",dedicatedMasterCount:3,vpc:i,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!0},autoTune:!0}),costOptimized:(a,n)=>Qt.createDomain({slug:a,environment:n,instanceType:"t3.medium.search",instanceCount:2,volumeSize:20,volumeType:"gp3",multiAz:!0,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!0}),highPerformance:(a,n,i)=>Qt.createDomain({slug:a,environment:n,instanceType:"r6g.2xlarge.search",instanceCount:6,volumeSize:500,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"c6g.xlarge.search",dedicatedMasterCount:3,vpc:i,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!1},autoTune:!0})};static InstanceTypes={"t3.small.search":"t3.small.search","t3.medium.search":"t3.medium.search","m6g.large.search":"m6g.large.search","m6g.xlarge.search":"m6g.xlarge.search","m6g.2xlarge.search":"m6g.2xlarge.search","r6g.large.search":"r6g.large.search","r6g.xlarge.search":"r6g.xlarge.search","r6g.2xlarge.search":"r6g.2xlarge.search","r6g.4xlarge.search":"r6g.4xlarge.search","c6g.large.search":"c6g.large.search","c6g.xlarge.search":"c6g.xlarge.search","c6g.2xlarge.search":"c6g.2xlarge.search"};static EngineVersions={"OpenSearch_2.11":"OpenSearch_2.11","OpenSearch_2.9":"OpenSearch_2.9","OpenSearch_2.7":"OpenSearch_2.7","OpenSearch_1.3":"OpenSearch_1.3","Elasticsearch_7.10":"Elasticsearch_7.10"}}class pt{static createDomainRedirectBucket(a){let{slug:n,environment:i,sourceDomain:s,targetDomain:c,protocol:l="https"}=a,u=r({slug:n,environment:i,resourceType:"s3",suffix:"redirect"}),h=t(u),y=t(`${u}-policy`),S={Type:"AWS::S3::Bucket",Properties:{BucketName:s,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:c,Protocol:l}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1},Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:i},{Key:"Purpose",Value:"Domain Redirect"}]}},b={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:N.Ref(h),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[N.Join("",[N.GetAtt(h,"Arn"),"/*"])]}]}}};return{bucket:S,bucketPolicy:b,logicalId:h,policyLogicalId:y}}static createPathRedirectFunction(a){let{slug:n,environment:i,rules:s}=a,c=r({slug:n,environment:i,resourceType:"cf-redirect"}),l=t(c),u=pt.generateRedirectFunctionCode(s);return{function:{Type:"AWS::CloudFront::Function",Properties:{Name:c,AutoPublish:!0,FunctionConfig:{Comment:`Path redirect function for ${n} (${i})`,Runtime:"cloudfront-js-2.0"},FunctionCode:u}},logicalId:l,functionCode:u}}static generateRedirectFunctionCode(a){return`function handler(event) {
2316
+ | limit 50`,region:s,title:"Recent Errors and Warnings"}}),u+=6;return Zs.createDashboard({slug:n,environment:i,widgets:l})}static DashboardTemplates={staticWebsite:(a)=>({slug:a.slug,environment:a.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${a.slug.toUpperCase()} Static Website Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"CloudFront Requests",region:"us-east-1",metrics:[["AWS/CloudFront","Requests","DistributionId",a.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"Error Rate",region:"us-east-1",metrics:[["AWS/CloudFront","4xxErrorRate","DistributionId",a.cloudFrontDistributionId,"Region","Global",{label:"4XX"}],["AWS/CloudFront","5xxErrorRate","DistributionId",a.cloudFrontDistributionId,"Region","Global",{label:"5XX"}]],period:300,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Bytes Downloaded",region:"us-east-1",metrics:[["AWS/CloudFront","BytesDownloaded","DistributionId",a.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:0,y:7,width:12,height:6,properties:{title:"S3 Bucket Size",region:a.region||"us-east-1",metrics:[["AWS/S3","BucketSizeBytes","BucketName",a.s3BucketName,"StorageType","StandardStorage"]],period:86400,stat:"Average"}},{type:"metric",x:12,y:7,width:12,height:6,properties:{title:"S3 Number of Objects",region:a.region||"us-east-1",metrics:[["AWS/S3","NumberOfObjects","BucketName",a.s3BucketName,"StorageType","AllStorageTypes"]],period:86400,stat:"Average"}}]}),serverlessApi:(a)=>({slug:a.slug,environment:a.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${a.slug.toUpperCase()} Serverless API Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"API Requests",region:a.region||"us-east-1",metrics:[["AWS/ApiGateway","Count","ApiName",a.apiGatewayName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"API Latency",region:a.region||"us-east-1",metrics:[["AWS/ApiGateway","Latency","ApiName",a.apiGatewayName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"API Errors",region:a.region||"us-east-1",metrics:[["AWS/ApiGateway","4XXError","ApiName",a.apiGatewayName,{label:"4XX"}],["AWS/ApiGateway","5XXError","ApiName",a.apiGatewayName,{label:"5XX"}]],period:60,stat:"Sum"}},...a.lambdaFunctionNames.map((n,i)=>({type:"metric",x:i%3*8,y:7+Math.floor(i/3)*6,width:8,height:6,properties:{title:`${n} Metrics`,region:a.region||"us-east-1",metrics:[["AWS/Lambda","Invocations","FunctionName",n],["AWS/Lambda","Duration","FunctionName",n],["AWS/Lambda","Errors","FunctionName",n]],period:300,stat:"Sum"}}))]}),containerService:(a)=>({slug:a.slug,environment:a.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${a.slug.toUpperCase()} Container Service Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"ECS CPU",region:a.region||"us-east-1",metrics:[["AWS/ECS","CPUUtilization","ClusterName",a.ecsClusterName,"ServiceName",a.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"ECS Memory",region:a.region||"us-east-1",metrics:[["AWS/ECS","MemoryUtilization","ClusterName",a.ecsClusterName,"ServiceName",a.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Running Tasks",region:a.region||"us-east-1",metrics:[["ECS/ContainerInsights","RunningTaskCount","ClusterName",a.ecsClusterName,"ServiceName",a.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:0,y:7,width:8,height:6,properties:{title:"ALB Requests",region:a.region||"us-east-1",metrics:[["AWS/ApplicationELB","RequestCount","LoadBalancer",a.albName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:7,width:8,height:6,properties:{title:"Response Time",region:a.region||"us-east-1",metrics:[["AWS/ApplicationELB","TargetResponseTime","LoadBalancer",a.albName]],period:60,stat:"Average"}},{type:"metric",x:16,y:7,width:8,height:6,properties:{title:"Healthy Hosts",region:a.region||"us-east-1",metrics:[["AWS/ApplicationELB","HealthyHostCount","LoadBalancer",a.albName]],period:60,stat:"Average"}},...a.rdsInstanceId?[{type:"metric",x:0,y:13,width:12,height:6,properties:{title:"RDS CPU",region:a.region||"us-east-1",metrics:[["AWS/RDS","CPUUtilization","DBInstanceIdentifier",a.rdsInstanceId]],period:300,stat:"Average"}},{type:"metric",x:12,y:13,width:12,height:6,properties:{title:"RDS Connections",region:a.region||"us-east-1",metrics:[["AWS/RDS","DatabaseConnections","DBInstanceIdentifier",a.rdsInstanceId]],period:60,stat:"Sum"}}]:[]]})};static Config={createAlarmConfig:(a)=>{let{metricName:n,namespace:i,threshold:s,comparisonOperator:c="GreaterThanThreshold",evaluationPeriods:l=1,period:u=300,statistic:h="Average",treatMissingData:y="missing"}=a;return{MetricName:n,Namespace:i,Threshold:s,ComparisonOperator:c,EvaluationPeriods:l,Period:u,Statistic:h,TreatMissingData:y}},namespaces:{ec2:"AWS/EC2",ecs:"AWS/ECS",lambda:"AWS/Lambda",rds:"AWS/RDS",sqs:"AWS/SQS",sns:"AWS/SNS",s3:"AWS/S3",cloudfront:"AWS/CloudFront",alb:"AWS/ApplicationELB",nlb:"AWS/NetworkELB",apiGateway:"AWS/ApiGateway",dynamodb:"AWS/DynamoDB",elasticache:"AWS/ElastiCache"},comparisonOperators:{greaterThan:"GreaterThanThreshold",greaterOrEqual:"GreaterThanOrEqualToThreshold",lessThan:"LessThanThreshold",lessOrEqual:"LessThanOrEqualToThreshold"},metrics:{ec2:{cpu:{metricName:"CPUUtilization",namespace:"AWS/EC2"},networkIn:{metricName:"NetworkIn",namespace:"AWS/EC2"},networkOut:{metricName:"NetworkOut",namespace:"AWS/EC2"},statusCheck:{metricName:"StatusCheckFailed",namespace:"AWS/EC2"}},ecs:{cpu:{metricName:"CPUUtilization",namespace:"AWS/ECS"},memory:{metricName:"MemoryUtilization",namespace:"AWS/ECS"}},lambda:{invocations:{metricName:"Invocations",namespace:"AWS/Lambda"},errors:{metricName:"Errors",namespace:"AWS/Lambda"},duration:{metricName:"Duration",namespace:"AWS/Lambda"},throttles:{metricName:"Throttles",namespace:"AWS/Lambda"},concurrentExecutions:{metricName:"ConcurrentExecutions",namespace:"AWS/Lambda"}},rds:{cpu:{metricName:"CPUUtilization",namespace:"AWS/RDS"},connections:{metricName:"DatabaseConnections",namespace:"AWS/RDS"},freeStorage:{metricName:"FreeStorageSpace",namespace:"AWS/RDS"},readLatency:{metricName:"ReadLatency",namespace:"AWS/RDS"},writeLatency:{metricName:"WriteLatency",namespace:"AWS/RDS"}},alb:{requestCount:{metricName:"RequestCount",namespace:"AWS/ApplicationELB"},responseTime:{metricName:"TargetResponseTime",namespace:"AWS/ApplicationELB"},httpCode4xx:{metricName:"HTTPCode_Target_4XX_Count",namespace:"AWS/ApplicationELB"},httpCode5xx:{metricName:"HTTPCode_Target_5XX_Count",namespace:"AWS/ApplicationELB"},healthyHosts:{metricName:"HealthyHostCount",namespace:"AWS/ApplicationELB"}},sqs:{messagesVisible:{metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS"},messagesDelayed:{metricName:"ApproximateNumberOfMessagesDelayed",namespace:"AWS/SQS"},messageAge:{metricName:"ApproximateAgeOfOldestMessage",namespace:"AWS/SQS"}}},presets:{highCpu:(a=80)=>({metricName:"CPUUtilization",threshold:a,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highMemory:(a=80)=>({metricName:"MemoryUtilization",threshold:a,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highErrors:(a=10)=>({metricName:"Errors",threshold:a,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:1,period:60,statistic:"Sum"}),highLatency:(a=5000)=>({metricName:"Duration",threshold:a,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowHealthyHosts:(a=1)=>({metricName:"HealthyHostCount",namespace:"AWS/ApplicationELB",threshold:a,comparisonOperator:"LessThanThreshold",evaluationPeriods:2,period:60,statistic:"Minimum"}),queueDepth:(a=1000)=>({metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",threshold:a,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowStorage:(a=10737418240)=>({metricName:"FreeStorageSpace",namespace:"AWS/RDS",threshold:a,comparisonOperator:"LessThanThreshold",evaluationPeriods:1,period:300,statistic:"Average"})}}}class U{static createUserPool(a){let{slug:n,environment:i,userPoolName:s,aliasAttributes:c,autoVerifiedAttributes:l,passwordPolicy:u,mfaConfiguration:h,emailConfiguration:y,smsConfiguration:S,lambdaTriggers:A,userPoolAddOns:C,accountRecoverySetting:T}=a,v=s||r({slug:n,environment:i,resourceType:"user-pool"}),w=t(v),E={Type:"AWS::Cognito::UserPool",Properties:{UserPoolName:v,Policies:u?{PasswordPolicy:{MinimumLength:u.minimumLength,RequireLowercase:u.requireLowercase,RequireUppercase:u.requireUppercase,RequireNumbers:u.requireNumbers,RequireSymbols:u.requireSymbols,TemporaryPasswordValidityDays:u.temporaryPasswordValidityDays}}:void 0,MfaConfiguration:h,Schema:[{Name:"email",AttributeDataType:"String",Required:!0,Mutable:!1}]}};if(c&&c.length>0)E.Properties.UsernameAttributes=c;if(l&&l.length>0)E.Properties.AutoVerifiedAttributes=l;if(y)E.Properties.EmailConfiguration={EmailSendingAccount:y.emailSendingAccount,From:y.from,ReplyToEmailAddress:y.replyToEmailAddress,SourceArn:y.sourceArn,ConfigurationSet:y.configurationSet};if(S)E.Properties.SmsConfiguration={ExternalId:S.externalId,SnsCallerArn:S.snsCallerArn};if(A)E.Properties.LambdaConfig={PreSignUp:A.preSignUp,PostConfirmation:A.postConfirmation,PreAuthentication:A.preAuthentication,PostAuthentication:A.postAuthentication,CustomMessage:A.customMessage,DefineAuthChallenge:A.defineAuthChallenge,CreateAuthChallenge:A.createAuthChallenge,VerifyAuthChallengeResponse:A.verifyAuthChallengeResponse,PreTokenGeneration:A.preTokenGeneration,UserMigration:A.userMigration};if(C)E.Properties.UserPoolAddOns={AdvancedSecurityMode:C.advancedSecurityMode};if(T)E.Properties.AccountRecoverySetting={RecoveryMechanisms:T.recoveryMechanisms};return{userPool:E,logicalId:w}}static createUserPoolClient(a,n){let{slug:i,environment:s,clientName:c,generateSecret:l=!1,refreshTokenValidity:u,accessTokenValidity:h,idTokenValidity:y,tokenValidityUnits:S,readAttributes:A,writeAttributes:C,explicitAuthFlows:T,preventUserExistenceErrors:v,enableTokenRevocation:w,callbackURLs:E,logoutURLs:R,allowedOAuthFlows:k,allowedOAuthScopes:W,allowedOAuthFlowsUserPoolClient:P,supportedIdentityProviders:V}=n,B=c||r({slug:i,environment:s,resourceType:"user-pool-client"}),j=t(B);return{client:{Type:"AWS::Cognito::UserPoolClient",Properties:{ClientName:B,UserPoolId:N.Ref(a),GenerateSecret:l,RefreshTokenValidity:u,AccessTokenValidity:h,IdTokenValidity:y,TokenValidityUnits:S,ReadAttributes:A,WriteAttributes:C,ExplicitAuthFlows:T,PreventUserExistenceErrors:v,EnableTokenRevocation:w,CallbackURLs:E,LogoutURLs:R,AllowedOAuthFlows:k,AllowedOAuthScopes:W,AllowedOAuthFlowsUserPoolClient:P,SupportedIdentityProviders:V}},logicalId:j}}static createUserPoolDomain(a,n){let{slug:i,environment:s,domain:c,customDomainConfig:l}=n,u=r({slug:i,environment:s,resourceType:"user-pool-domain"}),h=t(u);return{domain:{Type:"AWS::Cognito::UserPoolDomain",Properties:{Domain:c,UserPoolId:N.Ref(a),CustomDomainConfig:l}},logicalId:h}}static createIdentityPool(a){let{slug:n,environment:i,identityPoolName:s,allowUnauthenticatedIdentities:c=!1,cognitoIdentityProviders:l,supportedLoginProviders:u,samlProviderARNs:h,openIdConnectProviderARNs:y}=a,S=s||r({slug:n,environment:i,resourceType:"identity-pool"}),A=t(S);return{identityPool:{Type:"AWS::Cognito::IdentityPool",Properties:{IdentityPoolName:S,AllowUnauthenticatedIdentities:c,CognitoIdentityProviders:l,SupportedLoginProviders:u,SamlProviderARNs:h,OpenIdConnectProviderARNs:y}},logicalId:A}}static createIdentityPoolRoleAttachment(a,n){let{slug:i,environment:s,authenticatedRole:c,unauthenticatedRole:l,roleMappings:u}=n,h=r({slug:i,environment:s,resourceType:"identity-pool-role-attachment"}),y=t(h),S={authenticated:c};if(l)S.unauthenticated=l;return{attachment:{Type:"AWS::Cognito::IdentityPoolRoleAttachment",Properties:{IdentityPoolId:N.Ref(a),Roles:S,RoleMappings:u}},logicalId:y}}static createAuthenticatedRole(a){let{slug:n,environment:i,identityPoolLogicalId:s}=a,c=r({slug:n,environment:i,resourceType:"cognito-authenticated-role"}),l=t(c);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:c,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":N.Ref(s)},"ForAnyValue:StringLike":{"cognito-identity.amazonaws.com:amr":"authenticated"}}}]},Policies:[{PolicyName:"CognitoAuthenticatedPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["cognito-sync:*","cognito-identity:*"],Resource:"*"}]}}],Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:i}]}},logicalId:l}}static createUnauthenticatedRole(a){let{slug:n,environment:i,identityPoolLogicalId:s}=a,c=r({slug:n,environment:i,resourceType:"cognito-unauthenticated-role"}),l=t(c);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:c,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":N.Ref(s)},"ForAnyValue:StringLike":{"cognito-identity.amazonaws.com:amr":"unauthenticated"}}}]},Policies:[{PolicyName:"CognitoUnauthenticatedPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["cognito-sync:*"],Resource:"*"}]}}],Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:i}]}},logicalId:l}}static PasswordPolicies={relaxed:()=>({minimumLength:8,requireLowercase:!1,requireUppercase:!1,requireNumbers:!1,requireSymbols:!1,temporaryPasswordValidityDays:7}),standard:()=>({minimumLength:8,requireLowercase:!0,requireUppercase:!0,requireNumbers:!0,requireSymbols:!1,temporaryPasswordValidityDays:3}),strict:()=>({minimumLength:12,requireLowercase:!0,requireUppercase:!0,requireNumbers:!0,requireSymbols:!0,temporaryPasswordValidityDays:1})};static AuthFlows={standard:["ALLOW_USER_SRP_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],admin:["ALLOW_ADMIN_USER_PASSWORD_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],custom:["ALLOW_CUSTOM_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],all:["ALLOW_USER_SRP_AUTH","ALLOW_USER_PASSWORD_AUTH","ALLOW_ADMIN_USER_PASSWORD_AUTH","ALLOW_CUSTOM_AUTH","ALLOW_REFRESH_TOKEN_AUTH"]};static OAuthScopes={basic:["openid","email","profile"],all:["openid","email","profile","phone","aws.cognito.signin.user.admin"]};static UseCases={webApp:(a,n,i)=>{let{userPool:s,logicalId:c}=U.createUserPool({slug:a,environment:n,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:U.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:l,logicalId:u}=U.createUserPoolClient(c,{slug:a,environment:n,explicitAuthFlows:[...U.AuthFlows.standard],callbackURLs:[i],allowedOAuthFlows:["code"],allowedOAuthScopes:[...U.OAuthScopes.basic],allowedOAuthFlowsUserPoolClient:!0});return{userPool:s,poolId:c,client:l,clientId:u}},mobileApp:(a,n)=>{let{userPool:i,logicalId:s}=U.createUserPool({slug:a,environment:n,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:U.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:c,logicalId:l}=U.createUserPoolClient(s,{slug:a,environment:n,explicitAuthFlows:[...U.AuthFlows.standard]}),{identityPool:u,logicalId:h}=U.createIdentityPool({slug:a,environment:n,allowUnauthenticatedIdentities:!1,cognitoIdentityProviders:[{ClientId:N.Ref(l),ProviderName:N.GetAtt(s,"ProviderName")}]}),{role:y,logicalId:S}=U.createAuthenticatedRole({slug:a,environment:n,identityPoolLogicalId:h}),{attachment:A,logicalId:C}=U.createIdentityPoolRoleAttachment(h,{slug:a,environment:n,authenticatedRole:N.GetAtt(S,"Arn")});return{userPool:i,poolId:s,client:c,clientId:l,identityPool:u,identityPoolId:h,authRole:y,authRoleId:S,attachment:A,attachmentId:C}}}}class Q{static createApplication(a){let{slug:n,environment:i,applicationName:s,computePlatform:c}=a,l=s||r({slug:n,environment:i,resourceType:"deploy-app"}),u=t(l);return{application:{Type:"AWS::CodeDeploy::Application",Properties:{ApplicationName:l,ComputePlatform:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:i}]}},logicalId:u}}static createDeploymentGroup(a,n){let{slug:i,environment:s,deploymentGroupName:c,serviceRoleArn:l,autoScalingGroups:u,ec2TagFilters:h,deploymentConfigName:y,autoRollbackConfiguration:S,alarmConfiguration:A,loadBalancerInfo:C,blueGreenDeploymentConfiguration:T}=n,v=c||r({slug:i,environment:s,resourceType:"deploy-group"}),w=t(v);return{deploymentGroup:{Type:"AWS::CodeDeploy::DeploymentGroup",Properties:{ApplicationName:N.Ref(a),DeploymentGroupName:v,ServiceRoleArn:l,AutoScalingGroups:u,Ec2TagFilters:h?.map((E)=>({Key:E.key,Value:E.value,Type:E.type})),DeploymentConfigName:y,AutoRollbackConfiguration:S?{Enabled:S.enabled,Events:S.events}:void 0,AlarmConfiguration:A?{Enabled:A.enabled,Alarms:A.alarms?.map((E)=>({Name:E.name})),IgnorePollAlarmFailure:A.ignorePollAlarmFailure}:void 0,LoadBalancerInfo:C?{TargetGroupInfoList:C.targetGroupInfoList?.map((E)=>({Name:E.name})),ElbInfoList:C.elbInfoList?.map((E)=>({Name:E.name}))}:void 0,BlueGreenDeploymentConfiguration:T?{TerminateBlueInstancesOnDeploymentSuccess:T.terminateBlueInstancesOnDeploymentSuccess?{Action:T.terminateBlueInstancesOnDeploymentSuccess.action,TerminationWaitTimeInMinutes:T.terminateBlueInstancesOnDeploymentSuccess.terminationWaitTimeInMinutes}:void 0,DeploymentReadyOption:T.deploymentReadyOption?{ActionOnTimeout:T.deploymentReadyOption.actionOnTimeout,WaitTimeInMinutes:T.deploymentReadyOption.waitTimeInMinutes}:void 0,GreenFleetProvisioningOption:T.greenFleetProvisioningOption?{Action:T.greenFleetProvisioningOption.action}:void 0}:void 0,Tags:[{Key:"Name",Value:v},{Key:"Environment",Value:s}]}},logicalId:w}}static createDeploymentConfig(a){let{slug:n,environment:i,deploymentConfigName:s,minimumHealthyHosts:c,trafficRoutingConfig:l}=a,u=s||r({slug:n,environment:i,resourceType:"deploy-config"}),h=t(u);return{deploymentConfig:{Type:"AWS::CodeDeploy::DeploymentConfig",Properties:{DeploymentConfigName:u,MinimumHealthyHosts:c?{Type:c.type,Value:c.value}:void 0,TrafficRoutingConfig:l?{Type:l.type,TimeBasedCanary:l.timeBasedCanary?{CanaryPercentage:l.timeBasedCanary.canaryPercentage,CanaryInterval:l.timeBasedCanary.canaryInterval}:void 0,TimeBasedLinear:l.timeBasedLinear?{LinearPercentage:l.timeBasedLinear.linearPercentage,LinearInterval:l.timeBasedLinear.linearInterval}:void 0}:void 0}},logicalId:h}}static DeploymentConfigs={allAtOnce:()=>({type:"FLEET_PERCENT",value:0}),halfAtATime:()=>({type:"FLEET_PERCENT",value:50}),oneAtATime:()=>({type:"HOST_COUNT",value:1}),custom:(a,n)=>({type:a,value:n})};static TrafficRouting={allAtOnce:()=>({type:"AllAtOnce"}),canary:(a,n)=>({type:"TimeBasedCanary",timeBasedCanary:{canaryPercentage:a,canaryInterval:n}}),linear:(a,n)=>({type:"TimeBasedLinear",timeBasedLinear:{linearPercentage:a,linearInterval:n}})};static RollbackConfigs={onFailure:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE"]}),onAlarmOrFailure:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE","DEPLOYMENT_STOP_ON_ALARM"]}),onAllEvents:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE","DEPLOYMENT_STOP_ON_ALARM","DEPLOYMENT_STOP_ON_REQUEST"]}),disabled:()=>({enabled:!1})};static BlueGreenConfigs={standard:()=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withDelay:(a)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:a},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withManualApproval:(a)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"STOP_DEPLOYMENT",waitTimeInMinutes:a},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),keepBlue:()=>({terminateBlueInstancesOnDeploymentSuccess:{action:"KEEP_ALIVE"},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}})};static UseCases={ec2Deployment:(a,n,i,s)=>{let{application:c,logicalId:l}=Q.createApplication({slug:a,environment:n,computePlatform:"Server"}),{deploymentGroup:u,logicalId:h}=Q.createDeploymentGroup(l,{slug:a,environment:n,serviceRoleArn:i,autoScalingGroups:s,deploymentConfigName:"CodeDeployDefault.OneAtATime",autoRollbackConfiguration:Q.RollbackConfigs.onFailure()});return{application:c,appId:l,deploymentGroup:u,groupId:h}},lambdaCanaryDeployment:(a,n,i,s=10,c=5)=>{let{application:l,logicalId:u}=Q.createApplication({slug:a,environment:n,computePlatform:"Lambda"}),{deploymentConfig:h,logicalId:y}=Q.createDeploymentConfig({slug:a,environment:n,trafficRoutingConfig:Q.TrafficRouting.canary(s,c)}),{deploymentGroup:S,logicalId:A}=Q.createDeploymentGroup(u,{slug:a,environment:n,serviceRoleArn:i,deploymentConfigName:N.Ref(y),autoRollbackConfiguration:Q.RollbackConfigs.onAlarmOrFailure()});return{application:l,appId:u,deploymentConfig:h,configId:y,deploymentGroup:S,groupId:A}},ecsBlueGreenDeployment:(a,n,i,s)=>{let{application:c,logicalId:l}=Q.createApplication({slug:a,environment:n,computePlatform:"ECS"}),{deploymentGroup:u,logicalId:h}=Q.createDeploymentGroup(l,{slug:a,environment:n,serviceRoleArn:i,loadBalancerInfo:{targetGroupInfoList:[{name:s}]},blueGreenDeploymentConfiguration:Q.BlueGreenConfigs.standard(),autoRollbackConfiguration:Q.RollbackConfigs.onFailure()});return{application:c,appId:l,deploymentGroup:u,groupId:h}}};static Strategies={rolling:(a=25)=>({type:"rolling",batchPercentage:a}),blueGreen:()=>({type:"blue-green"}),canary:(a=10,n=5)=>({type:"canary",canaryPercentage:a,canaryInterval:n}),allAtOnce:()=>({type:"all-at-once"})}}class D{static ContentTypes={".html":"text/html",".htm":"text/html",".css":"text/css",".js":"application/javascript",".mjs":"application/javascript",".json":"application/json",".xml":"application/xml",".svg":"image/svg+xml",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".avif":"image/avif",".ico":"image/x-icon",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".otf":"font/otf",".eot":"application/vnd.ms-fontobject",".pdf":"application/pdf",".txt":"text/plain",".md":"text/markdown",".map":"application/json"};static NoHashPatterns=[/^index\.html$/,/^favicon\.ico$/,/^robots\.txt$/,/^sitemap\.xml$/,/^manifest\.json$/,/^\.well-known\//,/^_redirects$/,/^_headers$/];static computeFileHash(a,n="md5"){let i=rt(a);return br(n).update(i).digest("hex")}static computeShortHash(a){return D.computeFileHash(a).slice(0,8)}static getContentType(a){let n=sa(a).toLowerCase();return D.ContentTypes[n]||"application/octet-stream"}static shouldHashFile(a,n){return![...D.NoHashPatterns,...n||[]].some((i)=>i.test(a))}static generateHashedFilename(a,n){let i=sa(a),s=vr(a,i),c=ia(a);if(c===".")return`${s}.${n}${i}`;return Ke(c,`${s}.${n}${i}`)}static collectFiles(a,n){let i=[],s=n||a;if(!Et(a))return i;let c=Cr(a,{withFileTypes:!0});for(let l of c){let u=Ke(a,l.name);if(l.isDirectory())i.push(...D.collectFiles(u,s));else if(l.isFile())i.push(u)}return i}static hashDirectory(a){let{sourceDir:n,outputDir:i,excludePatterns:s=[],hashAlgorithm:c="md5",copyUnhashed:l=!0}=a,u=D.collectFiles(n),h=[],y={};for(let A of u){let C=A.replace(n,"").replace(/^[/\\]/,""),T=D.shouldHashFile(C,s),v=Tr(A),w=T?D.computeFileHash(A,c).slice(0,8):"",E=T?D.generateHashedFilename(C,w):C,R={originalPath:C,hashedPath:E,hash:w,size:v.size,contentType:D.getContentType(A)};if(h.push(R),y[C]=E,i){let k=Ke(i,E),W=ia(k);if(!Et(W)){let{mkdirSync:P}=Za("node:fs");P(W,{recursive:!0})}if(T||l)Ar(A,k)}}let S={version:"1.0",timestamp:new Date().toISOString(),assets:h,hashMap:y};if(i){let A=Ke(i,"asset-manifest.json");nt(A,JSON.stringify(S,null,2))}return S}static getInvalidationPaths(a,n){let i=[];if(!a)return["/*"];let s=a.hashMap,c=n.hashMap;for(let[l,u]of Object.entries(c)){let h=s[l];if(!h||h!==u){if(i.push(`/${l}`),h&&h!==u)i.push(`/${h}`)}}for(let[l,u]of Object.entries(s))if(!c[l])i.push(`/${l}`),i.push(`/${u}`);if(i.length>100)return["/*"];return[...new Set(i)]}static updateHtmlReferences(a){let{htmlDir:n,manifest:i,basePath:s=""}=a,c=D.collectFiles(n).filter((l)=>l.endsWith(".html")||l.endsWith(".htm"));for(let l of c){let u=rt(l,"utf-8");for(let[h,y]of Object.entries(i.hashMap)){if(h===y)continue;let S=[new RegExp(`(src|href)=["']${s}/?${D.escapeRegExp(h)}["']`,"g"),new RegExp(`url\\(["']?${s}/?${D.escapeRegExp(h)}["']?\\)`,"g")];for(let A of S)u=u.replace(A,(C)=>C.replace(h,y))}nt(l,u)}}static updateCssReferences(a){let{cssDir:n,manifest:i,basePath:s=""}=a,c=D.collectFiles(n).filter((l)=>l.endsWith(".css"));for(let l of c){let u=rt(l,"utf-8");for(let[h,y]of Object.entries(i.hashMap)){if(h===y)continue;let S=new RegExp(`url\\(["']?${s}/?${D.escapeRegExp(h)}["']?\\)`,"g");u=u.replace(S,`url(${s}/${y})`)}nt(l,u)}}static escapeRegExp(a){return a.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}static generateS3DeploymentManifest(a){let{sourceDir:n,keyPrefix:i="",excludePatterns:s=[],cacheControl:c={hashed:"public, max-age=31536000, immutable",unhashed:"public, max-age=3600",html:"public, max-age=0, must-revalidate"}}=a;return D.hashDirectory({sourceDir:n,excludePatterns:s}).assets.map((l)=>{let u=l.hash!=="",h=l.contentType==="text/html",y=c.unhashed||"public, max-age=3600";if(h)y=c.html||"public, max-age=0, must-revalidate";else if(u)y=c.hashed||"public, max-age=31536000, immutable";return{localPath:Ke(n,l.originalPath),s3Key:i?`${i}/${l.hashedPath}`:l.hashedPath,contentType:l.contentType,cacheControl:y,hash:l.hash}})}static compareManifests(a,n){let i={added:[],removed:[],changed:[],unchanged:[]},s=new Set(Object.keys(a.hashMap)),c=new Set(Object.keys(n.hashMap));for(let l of c)if(!s.has(l))i.added.push(l);for(let l of s)if(!c.has(l))i.removed.push(l);for(let l of c)if(s.has(l))if(a.hashMap[l]!==n.hashMap[l])i.changed.push(l);else i.unchanged.push(l);return i}static loadManifest(a){if(!Et(a))return null;try{let n=rt(a,"utf-8");return JSON.parse(n)}catch{return null}}static saveManifest(a,n){nt(n,JSON.stringify(a,null,2))}}class Ai{static createSecret(a){let{slug:n,environment:i,secretName:s,description:c,secretString:l,kmsKeyId:u,tags:h}=a,y=s||r({slug:n,environment:i,resourceType:"secret"}),S=t(y),A={Type:"AWS::SecretsManager::Secret",Properties:{Name:y,Description:c,SecretString:l,Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:i},...h?Object.entries(h).map(([C,T])=>({Key:C,Value:T})):[]]}};if(u)A.Properties.KmsKeyId=u;return{secret:A,logicalId:S}}static createGeneratedSecret(a){let{slug:n,environment:i,secretName:s,description:c,excludeCharacters:l,excludeLowercase:u,excludeNumbers:h,excludePunctuation:y,excludeUppercase:S,passwordLength:A,requireEachIncludedType:C,kmsKeyId:T,tags:v}=a,w=s||r({slug:n,environment:i,resourceType:"secret"}),E=t(w),R={Type:"AWS::SecretsManager::Secret",Properties:{Name:w,Description:c,GenerateSecretString:{ExcludeCharacters:l,ExcludeLowercase:u,ExcludeNumbers:h,ExcludePunctuation:y,ExcludeUppercase:S,PasswordLength:A||32,RequireEachIncludedType:C!==!1},Tags:[{Key:"Name",Value:w},{Key:"Environment",Value:i},...v?Object.entries(v).map(([k,W])=>({Key:k,Value:W})):[]]}};if(T)R.Properties.KmsKeyId=T;return{secret:R,logicalId:E}}static createDatabaseSecret(a){let{slug:n,environment:i,secretName:s,username:c,dbname:l,engine:u,host:h,port:y,kmsKeyId:S}=a,A=s||r({slug:n,environment:i,resourceType:"db-secret"}),C=t(A),T={username:c};if(l)T.dbname=l;if(u)T.engine=u;if(h)T.host=h;if(y)T.port=y;let v={Type:"AWS::SecretsManager::Secret",Properties:{Name:A,Description:`Database credentials for ${c}`,GenerateSecretString:{SecretStringTemplate:JSON.stringify(T),GenerateStringKey:"password",PasswordLength:32,ExcludeCharacters:'"@/\\',RequireEachIncludedType:!0},Tags:[{Key:"Name",Value:A},{Key:"Environment",Value:i},{Key:"Type",Value:"database"}]}};if(S)v.Properties.KmsKeyId=S;return{secret:v,logicalId:C}}static attachToDatabase(a){let{slug:n,environment:i,secretId:s,targetId:c,targetType:l}=a,u=r({slug:n,environment:i,resourceType:"secret-attachment"}),h=t(u);return{attachment:{Type:"AWS::SecretsManager::SecretTargetAttachment",Properties:{SecretId:s,TargetId:c,TargetType:l}},logicalId:h}}static enableRotation(a){let{slug:n,environment:i,secretId:s,rotationLambdaArn:c,automaticallyAfterDays:l,rotationType:u,kmsKeyArn:h,vpcSecurityGroupIds:y,vpcSubnetIds:S}=a,A=r({slug:n,environment:i,resourceType:"secret-rotation"}),C=t(A),T={Type:"AWS::SecretsManager::RotationSchedule",Properties:{SecretId:s,RotationRules:{AutomaticallyAfterDays:l||30}}};if(c)T.Properties.RotationLambdaARN=c;else if(u)T.Properties.HostedRotationLambda={RotationType:u,KmsKeyArn:h,VpcSecurityGroupIds:y,VpcSubnetIds:S};return{rotation:T,logicalId:C}}static SecretTypes={apiKey:(a,n,i)=>Ai.createGeneratedSecret({slug:a,environment:n,secretName:`${a}-${n}-${i}-api-key`,description:`API key for ${i}`,passwordLength:32,excludePunctuation:!0,excludeLowercase:!1,excludeUppercase:!1,excludeNumbers:!1}),oauthClientSecret:(a,n,i)=>Ai.createGeneratedSecret({slug:a,environment:n,secretName:`${a}-${n}-${i}-oauth-secret`,description:`OAuth client secret for ${i}`,passwordLength:64,excludeCharacters:"\"'`\\/@",requireEachIncludedType:!0}),jwtSecret:(a,n)=>Ai.createGeneratedSecret({slug:a,environment:n,secretName:`${a}-${n}-jwt-secret`,description:"JWT signing secret",passwordLength:64,excludePunctuation:!0}),encryptionKey:(a,n)=>Ai.createGeneratedSecret({slug:a,environment:n,secretName:`${a}-${n}-encryption-key`,description:"Data encryption key",passwordLength:64,excludeCharacters:"+/=",excludePunctuation:!0})};static RotationTypes={MySQLSingleUser:"MySQLSingleUser",MySQLMultiUser:"MySQLMultiUser",PostgreSQLSingleUser:"PostgreSQLSingleUser",PostgreSQLMultiUser:"PostgreSQLMultiUser",OracleSingleUser:"OracleSingleUser",OracleMultiUser:"OracleMultiUser",MariaDBSingleUser:"MariaDBSingleUser",MariaDBMultiUser:"MariaDBMultiUser",SQLServerSingleUser:"SQLServerSingleUser",SQLServerMultiUser:"SQLServerMultiUser",RedshiftSingleUser:"RedshiftSingleUser",RedshiftMultiUser:"RedshiftMultiUser",MongoDBSingleUser:"MongoDBSingleUser",MongoDBMultiUser:"MongoDBMultiUser"}}class b{static createParameter(a){let{slug:n,environment:i,parameterName:s,value:c,type:l="String",description:u,tier:h="Standard",tags:y}=a,S=s||r({slug:n,environment:i,resourceType:"parameter"}),A=t(S);return{parameter:{Type:"AWS::SSM::Parameter",Properties:{Name:`/${n}/${i}/${S}`,Type:l,Value:c,Description:u,Tier:h,Tags:{Name:S,Environment:i,...y}}},logicalId:A}}static createString(a,n,i,s,c){return b.createParameter({slug:a,environment:n,parameterName:i,value:s,type:"String",description:c})}static createSecureString(a,n,i,s,c){return b.createParameter({slug:a,environment:n,parameterName:i,value:s,type:"SecureString",description:c})}static createStringList(a,n,i,s,c){return b.createParameter({slug:a,environment:n,parameterName:i,value:s.join(","),type:"StringList",description:c})}static Parameters={databaseUrl:(a,n,i)=>b.createSecureString(a,n,"database-url",i,"Database connection URL"),apiEndpoint:(a,n,i)=>b.createString(a,n,"api-endpoint",i,"API endpoint URL"),appVersion:(a,n,i)=>b.createString(a,n,"app-version",i,"Application version"),featureFlags:(a,n,i)=>b.createStringList(a,n,"feature-flags",i,"Enabled feature flags"),apiKey:(a,n,i,s)=>b.createSecureString(a,n,`${i}-api-key`,s,`API key for ${i}`),oauthCredentials:(a,n,i,s)=>{let c=b.createString(a,n,"oauth-client-id",i,"OAuth client ID"),l=b.createSecureString(a,n,"oauth-client-secret",s,"OAuth client secret");return{clientId:c,clientSecret:l}},smtpCredentials:(a,n,i,s,c,l)=>{let u=b.createString(a,n,"smtp-username",i,"SMTP username"),h=b.createSecureString(a,n,"smtp-password",s,"SMTP password"),y=b.createString(a,n,"smtp-host",c,"SMTP host"),S=b.createString(a,n,"smtp-port",l.toString(),"SMTP port");return{username:u,password:h,host:y,port:S}},redisUrl:(a,n,i)=>b.createSecureString(a,n,"redis-url",i,"Redis connection URL"),s3Bucket:(a,n,i)=>b.createString(a,n,"s3-bucket",i,"S3 bucket name"),cloudFrontDistribution:(a,n,i)=>b.createString(a,n,"cloudfront-distribution-id",i,"CloudFront distribution ID")}}class Qt{static createDomain(a){let{slug:n,environment:i,domainName:s,engineVersion:c="OpenSearch_2.11",instanceType:l="t3.small.search",instanceCount:u=1,volumeSize:h=10,volumeType:y="gp3",dedicatedMaster:S=!1,dedicatedMasterType:A,dedicatedMasterCount:C=3,multiAz:T=!1,availabilityZoneCount:v=2,vpc:w,encryption:E,enforceHttps:R=!0,tlsSecurityPolicy:k="Policy-Min-TLS-1-2-2019-07",advancedSecurity:W,autoSnapshotHour:P=0,autoTune:V=!0,tags:B={}}=a,j=s||r({slug:n,environment:i,resourceType:"search"}),J=t(j);return{domain:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:j,EngineVersion:c,ClusterConfig:{InstanceType:l,InstanceCount:u,DedicatedMasterEnabled:S,...S&&{DedicatedMasterType:A||l,DedicatedMasterCount:C},ZoneAwarenessEnabled:T,...T&&{ZoneAwarenessConfig:{AvailabilityZoneCount:v}}},EBSOptions:{EBSEnabled:!0,VolumeType:y,VolumeSize:h},DomainEndpointOptions:{EnforceHTTPS:R,TLSSecurityPolicy:k},SnapshotOptions:{AutomatedSnapshotStartHour:P},...w&&{VPCOptions:{SubnetIds:w.subnetIds,SecurityGroupIds:w.securityGroupIds}},...E&&{EncryptionAtRestOptions:{Enabled:E.atRest??!0,...E.kmsKeyId&&{KmsKeyId:E.kmsKeyId}},NodeToNodeEncryptionOptions:{Enabled:E.nodeToNode??!0}},...W&&{AdvancedSecurityOptions:{Enabled:W.enabled,InternalUserDatabaseEnabled:W.internalUserDatabase??!0,...W.masterUserName&&W.masterUserPassword&&{MasterUserOptions:{MasterUserName:W.masterUserName,MasterUserPassword:W.masterUserPassword}},...W.masterUserArn&&{MasterUserOptions:{MasterUserARN:W.masterUserArn}}}},...V&&{AutoTuneOptions:{DesiredState:"ENABLED"}},Tags:[{Key:"Name",Value:j},{Key:"Environment",Value:i},...Object.entries(B).map(([K,X])=>({Key:K,Value:X}))]}},logicalId:J}}static createAccessPolicy(a,n){let{ipAddresses:i,iamPrincipalArns:s,allowAll:c,vpcEndpoint:l}=n;if(c)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:a}]};let u=[];if(s&&s.length>0)u.push({Effect:"Allow",Principal:{AWS:s},Action:"es:*",Resource:a});if(i&&i.length>0)u.push({Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:a,Condition:{IpAddress:{"aws:SourceIp":i}}});if(l)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:a}]};return{Version:"2012-10-17",Statement:u}}static DomainPresets={development:(a,n)=>Qt.createDomain({slug:a,environment:n,instanceType:"t3.small.search",instanceCount:1,volumeSize:10,multiAz:!1,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!1}),production:(a,n,i)=>Qt.createDomain({slug:a,environment:n,instanceType:"m6g.large.search",instanceCount:3,volumeSize:100,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"m6g.large.search",dedicatedMasterCount:3,vpc:i,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!0},autoTune:!0}),costOptimized:(a,n)=>Qt.createDomain({slug:a,environment:n,instanceType:"t3.medium.search",instanceCount:2,volumeSize:20,volumeType:"gp3",multiAz:!0,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!0}),highPerformance:(a,n,i)=>Qt.createDomain({slug:a,environment:n,instanceType:"r6g.2xlarge.search",instanceCount:6,volumeSize:500,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"c6g.xlarge.search",dedicatedMasterCount:3,vpc:i,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!1},autoTune:!0})};static InstanceTypes={"t3.small.search":"t3.small.search","t3.medium.search":"t3.medium.search","m6g.large.search":"m6g.large.search","m6g.xlarge.search":"m6g.xlarge.search","m6g.2xlarge.search":"m6g.2xlarge.search","r6g.large.search":"r6g.large.search","r6g.xlarge.search":"r6g.xlarge.search","r6g.2xlarge.search":"r6g.2xlarge.search","r6g.4xlarge.search":"r6g.4xlarge.search","c6g.large.search":"c6g.large.search","c6g.xlarge.search":"c6g.xlarge.search","c6g.2xlarge.search":"c6g.2xlarge.search"};static EngineVersions={"OpenSearch_2.11":"OpenSearch_2.11","OpenSearch_2.9":"OpenSearch_2.9","OpenSearch_2.7":"OpenSearch_2.7","OpenSearch_1.3":"OpenSearch_1.3","Elasticsearch_7.10":"Elasticsearch_7.10"}}class pt{static createDomainRedirectBucket(a){let{slug:n,environment:i,sourceDomain:s,targetDomain:c,protocol:l="https"}=a,u=r({slug:n,environment:i,resourceType:"s3",suffix:"redirect"}),h=t(u),y=t(`${u}-policy`),S={Type:"AWS::S3::Bucket",Properties:{BucketName:s,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:c,Protocol:l}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1},Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:i},{Key:"Purpose",Value:"Domain Redirect"}]}},A={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:N.Ref(h),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[N.Join("",[N.GetAtt(h,"Arn"),"/*"])]}]}}};return{bucket:S,bucketPolicy:A,logicalId:h,policyLogicalId:y}}static createPathRedirectFunction(a){let{slug:n,environment:i,rules:s}=a,c=r({slug:n,environment:i,resourceType:"cf-redirect"}),l=t(c),u=pt.generateRedirectFunctionCode(s);return{function:{Type:"AWS::CloudFront::Function",Properties:{Name:c,AutoPublish:!0,FunctionConfig:{Comment:`Path redirect function for ${n} (${i})`,Runtime:"cloudfront-js-2.0"},FunctionCode:u}},logicalId:l,functionCode:u}}static generateRedirectFunctionCode(a){return`function handler(event) {
2317
2317
  const request = event.request;
2318
2318
  const uri = request.uri;
2319
2319
  const querystring = request.querystring;
@@ -2367,7 +2367,7 @@ ${a.map((n)=>{let i=n.preserveQueryString!==!1,s=n.statusCode||301;return` '${n
2367
2367
  }
2368
2368
 
2369
2369
  return request;
2370
- }`}static CommonRedirects={wwwToApex:(a,n="https")=>({slug:a.replace(/\./g,"-"),environment:"production",sourceDomain:`www.${a}`,targetDomain:a,protocol:n,preservePath:!0}),apexToWww:(a,n="https")=>({slug:a.replace(/\./g,"-"),environment:"production",sourceDomain:a,targetDomain:`www.${a}`,protocol:n,preservePath:!0}),httpToHttps:(a="/")=>({source:a,target:a,statusCode:301}),addTrailingSlash:(a)=>a.map((n)=>({source:n.endsWith("/")?n.slice(0,-1):n,target:n.endsWith("/")?n:`${n}/`,statusCode:301})),removeTrailingSlash:(a)=>a.map((n)=>({source:n.endsWith("/")&&n!=="/"?n:`${n}/`,target:n.endsWith("/")&&n!=="/"?n.slice(0,-1):n,statusCode:301}))};static Patterns={flattenBlogUrls:(a)=>a.map(({oldPath:n,newPath:i})=>({source:n,target:i,statusCode:301,preserveQueryString:!0})),categoryRename:(a,n)=>[{source:`/${a}`,target:`/${n}`,statusCode:301},{source:`/${a}/`,target:`/${n}/`,statusCode:301}],productSlugChange:(a)=>a.map(({oldSlug:n,newSlug:i})=>({source:`/products/${n}`,target:`/products/${i}`,statusCode:301})),apiVersionRedirect:(a,n,i)=>i.map((s)=>({source:`/api/${a}/${s}`,target:`/api/${n}/${s}`,statusCode:307,preserveQueryString:!0})),gonePages:(a)=>a.map((n)=>({source:n,target:"/410",statusCode:301}))};static createRedirectSetup(a){let{slug:n,environment:i,domainRedirects:s=[],pathRedirects:c=[]}=a,l={},u=[];for(let y of s){let{bucket:S,bucketPolicy:b,logicalId:A,policyLogicalId:C}=pt.createDomainRedirectBucket({...y,slug:n,environment:i});l[A]=S,l[C]=b,u.push(A)}let h=null;if(c.length>0){let{function:y,logicalId:S}=pt.createPathRedirectFunction({slug:n,environment:i,rules:c});l[S]=y,h=S}return{resources:l,outputs:{domainRedirectBuckets:u,pathRedirectFunctionLogicalId:h}}}static fromMapping(a,n){return Object.entries(a).map(([i,s])=>({source:i,target:s,statusCode:n?.statusCode||301,preserveQueryString:n?.preserveQueryString??!0}))}static validateRules(a){let n=[],i=[],s=new Set;for(let c of a){if(s.has(c.source))n.push(`Duplicate source path: ${c.source}`);if(s.add(c.source),c.source===c.target)n.push(`Redirect loop detected: ${c.source} -> ${c.target}`);if(!c.target.startsWith("/")&&!c.target.startsWith("http"))i.push(`Target URL should start with / or http: ${c.target}`);if(!c.source||c.source.trim()==="")n.push("Source path cannot be empty");if(!c.target||c.target.trim()==="")n.push("Target path cannot be empty")}for(let c of a){let l=a.find((u)=>u.source===c.target);if(l)i.push(`Potential redirect chain: ${c.source} -> ${c.target} -> ${l.target}`)}return{valid:n.length===0,errors:n,warnings:i}}}class H{static generate(a){let n={},{slug:i,environment:s,region:c="us-east-1"}=a,l=H.createLambdaExecutionRole(i,s);if(Object.assign(n,l.resources),a.email?.enabled){let u=H.generateEmailResources(a,l.roleArn);Object.assign(n,u)}if(a.phone?.enabled){let u=H.generatePhoneResources(a,l.roleArn);Object.assign(n,u)}if(a.sms?.enabled){let u=H.generateSmsResources(a,l.roleArn);Object.assign(n,u)}return n}static createLambdaExecutionRole(a,n){let i=`${a}-${n}-communication-role`,s=t(i);return{resources:{[s]:{Type:"AWS::IAM::Role",Properties:{RoleName:i,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],Policies:[{PolicyName:"CommunicationPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:"*"},{Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail","ses:GetIdentityVerificationAttributes"],Resource:"*"},{Effect:"Allow",Action:["sns:Publish","sns:Subscribe"],Resource:"*"},{Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:BatchWriteItem","dynamodb:BatchGetItem"],Resource:"*"},{Effect:"Allow",Action:["connect:*"],Resource:"*"},{Effect:"Allow",Action:["mobiletargeting:SendMessages","mobiletargeting:GetEndpoint","mobiletargeting:UpdateEndpoint"],Resource:"*"},{Effect:"Allow",Action:["transcribe:StartTranscriptionJob","transcribe:GetTranscriptionJob"],Resource:"*"},{Effect:"Allow",Action:["bedrock:InvokeModel"],Resource:"*"},{Effect:"Allow",Action:["es:ESHttpGet","es:ESHttpPost","es:ESHttpPut","es:ESHttpDelete"],Resource:"*"}]}}]}}},roleArn:N.GetAtt(s,"Arn"),roleName:i}}static generateEmailResources(a,n){let{slug:i,environment:s,email:c}=a;if(!c)return{};let l={},u=`${i}-${s}`,h=`${u}-email-storage`,y=t(h);l[y]={Type:"AWS::S3::Bucket",Properties:{BucketName:h,LifecycleConfiguration:{Rules:[{Id:"ArchiveOldEmails",Status:"Enabled",Transitions:c.server?.storage?.archiveAfterDays?[{StorageClass:"GLACIER",TransitionInDays:c.server.storage.archiveAfterDays}]:[],ExpirationInDays:c.server?.storage?.retentionDays||365}]},NotificationConfiguration:{LambdaConfigurations:[]}}};let S=t(`${u}-ses-identity`);if(l[S]={Type:"AWS::SES::EmailIdentity",Properties:{EmailIdentity:c.domain,DkimSigningAttributes:{NextSigningKeyLength:"RSA_2048_BIT"},FeedbackAttributes:{EmailForwardingEnabled:!0}}},c.notifications?.bounces||c.notifications?.complaints){let b=t(`${u}-bounce-topic`);l[b]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${u}-email-bounces`}};let A=t(`${u}-complaint-topic`);l[A]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${u}-email-complaints`}}}if(c.server?.enabled){let b=t(`${u}-inbound-email`);l[b]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-inbound-email`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n,Timeout:60,MemorySize:256,Code:{ZipFile:H.InboundEmailCode},Environment:{Variables:{EMAIL_BUCKET:h,DOMAIN:c.domain}}}};let A=t(`${u}-outbound-email`);l[A]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-outbound-email`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n,Timeout:30,MemorySize:256,Code:{ZipFile:H.OutboundEmailCode},Environment:{Variables:{EMAIL_BUCKET:h,DOMAIN:c.domain}}}}}if(c.advanced?.analytics){let b=t(`${u}-email-analytics`);l[b]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-email-analytics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.scheduling){let b=t(`${u}-email-scheduler`);l[b]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-email-scheduler`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n,Timeout:300,MemorySize:256,Code:{ZipFile:H.EmailSchedulerCode},Environment:{Variables:{EMAIL_BUCKET:h}}}};let A=t(`${u}-email-scheduler-rule`);l[A]={Type:"AWS::Events::Rule",Properties:{Name:`${u}-email-scheduler`,ScheduleExpression:"rate(1 minute)",State:"ENABLED",Targets:[{Id:"EmailSchedulerTarget",Arn:N.GetAtt(b,"Arn")}]}}}if(c.advanced?.threading){let b=t(`${u}-email-threading`);l[b]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-email-threading`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n,Timeout:60,MemorySize:256,Code:{ZipFile:H.EmailThreadingCode},Environment:{Variables:{EMAIL_BUCKET:h}}}}}if(c.advanced?.rules){let b=t(`${u}-email-rules`);l[b]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-email-rules`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"mailbox",AttributeType:"S"},{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"mailbox",KeyType:"HASH"},{AttributeName:"id",KeyType:"RANGE"}]}}}if(c.advanced?.sharedMailboxes){let b=t(`${u}-shared-mailboxes`);l[b]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-shared-mailboxes`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"},{AttributeName:"type",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],GlobalSecondaryIndexes:[{IndexName:"type-index",KeySchema:[{AttributeName:"type",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"}}]}}}if(c.advanced?.search){let b=t(`${u}-email-search`);l[b]={Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:`${u}-email-search`.toLowerCase().replace(/[^a-z0-9-]/g,"-").substring(0,28),EngineVersion:"OpenSearch_2.11",ClusterConfig:{InstanceType:"t3.small.search",InstanceCount:1},EBSOptions:{EBSEnabled:!0,VolumeType:"gp3",VolumeSize:10},NodeToNodeEncryptionOptions:{Enabled:!0},EncryptionAtRestOptions:{Enabled:!0},DomainEndpointOptions:{EnforceHTTPS:!0}}}}return l}static generatePhoneResources(a,n){let{slug:i,environment:s,phone:c}=a;if(!c)return{};let l={},u=`${i}-${s}`,h=t(`${u}-call-log`);if(l[h]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-call-log`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"contactId",AttributeType:"S"}],KeySchema:[{AttributeName:"contactId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}},c.voicemail?.enabled){let b=t(`${u}-voicemail`);l[b]={Type:"AWS::S3::Bucket",Properties:{BucketName:`${u}-voicemail`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldVoicemails",Status:"Enabled",ExpirationInDays:90}]}}}}let y=t(`${u}-phone-notifications`);l[y]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${u}-phone-notifications`}};let S=t(`${u}-incoming-call`);if(l[S]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-incoming-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n,Timeout:30,MemorySize:256,Code:{ZipFile:H.IncomingCallCode},Environment:{Variables:{CALL_LOG_TABLE:`${u}-call-log`,NOTIFICATION_TOPIC_ARN:N.Ref(y)}}}},c.voicemail?.enabled){let b=t(`${u}-voicemail-handler`);l[b]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-voicemail-handler`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n,Timeout:c.voicemail.transcription?300:60,MemorySize:256,Code:{ZipFile:H.VoicemailCode},Environment:{Variables:{VOICEMAIL_BUCKET:`${u}-voicemail`,TRANSCRIPTION_ENABLED:String(c.voicemail.transcription||!1),NOTIFICATION_TOPIC_ARN:N.Ref(y)}}}}}if(c.advanced?.recording){let b=t(`${u}-call-recordings`);l[b]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-call-recordings`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"recordingId",AttributeType:"S"}],KeySchema:[{AttributeName:"recordingId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.callbacks){let b=t(`${u}-callbacks`);l[b]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-callbacks`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.analytics){let b=t(`${u}-call-metrics`);l[b]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-call-metrics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"period",AttributeType:"S"}],KeySchema:[{AttributeName:"period",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}return l}static generateSmsResources(a,n){let{slug:i,environment:s,sms:c}=a;if(!c)return{};let l={},u=`${i}-${s}`,h=t(`${u}-pinpoint-app`);l[h]={Type:"AWS::Pinpoint::App",Properties:{Name:`${u}-sms`}};let y=t(`${u}-sms-channel`);l[y]={Type:"AWS::Pinpoint::SMSChannel",Properties:{ApplicationId:N.Ref(h),Enabled:!0,SenderId:c.senderId}};let S=t(`${u}-sms-log`);if(l[S]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-sms-log`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}},c.optOut?.enabled){let T=t(`${u}-sms-optout`);l[T]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-sms-optout`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}]}}}let b=t(`${u}-sms-notifications`);l[b]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${u}-sms-notifications`}};let A=t(`${u}-send-sms`);l[A]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-send-sms`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n,Timeout:30,MemorySize:256,Code:{ZipFile:H.SendSmsCode},Environment:{Variables:{PINPOINT_APP_ID:N.Ref(h),MESSAGE_LOG_TABLE:`${u}-sms-log`,OPT_OUT_TABLE:c.optOut?.enabled?`${u}-sms-optout`:"",MESSAGE_TYPE:c.messageType||"TRANSACTIONAL"}}}};let C=t(`${u}-receive-sms`);if(l[C]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-receive-sms`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n,Timeout:30,MemorySize:256,Code:{ZipFile:H.ReceiveSmsCode},Environment:{Variables:{MESSAGE_LOG_TABLE:`${u}-sms-log`,OPT_OUT_TABLE:c.optOut?.enabled?`${u}-sms-optout`:"",NOTIFICATION_TOPIC_ARN:N.Ref(b)}}}},c.advanced?.campaigns){let T=t(`${u}-sms-campaigns`);l[T]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-sms-campaigns`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}if(c.advanced?.analytics){let T=t(`${u}-sms-analytics`);l[T]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-sms-analytics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"period",AttributeType:"S"}],KeySchema:[{AttributeName:"period",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.linkTracking){let T=t(`${u}-short-links`);l[T]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-short-links`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.chatbot){let T=t(`${u}-chatbot-sessions`);l[T]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-chatbot-sessions`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}};let v=t(`${u}-chatbot-rules`);l[v]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-chatbot-rules`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}if(c.advanced?.abTesting){let T=t(`${u}-ab-tests`);l[T]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-ab-tests`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}if(c.advanced?.mms){let T=t(`${u}-mms-media`);l[T]={Type:"AWS::S3::Bucket",Properties:{BucketName:`${u}-mms-media`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldMedia",Status:"Enabled",ExpirationInDays:30}]}}}}return l}static InboundEmailCode=`
2370
+ }`}static CommonRedirects={wwwToApex:(a,n="https")=>({slug:a.replace(/\./g,"-"),environment:"production",sourceDomain:`www.${a}`,targetDomain:a,protocol:n,preservePath:!0}),apexToWww:(a,n="https")=>({slug:a.replace(/\./g,"-"),environment:"production",sourceDomain:a,targetDomain:`www.${a}`,protocol:n,preservePath:!0}),httpToHttps:(a="/")=>({source:a,target:a,statusCode:301}),addTrailingSlash:(a)=>a.map((n)=>({source:n.endsWith("/")?n.slice(0,-1):n,target:n.endsWith("/")?n:`${n}/`,statusCode:301})),removeTrailingSlash:(a)=>a.map((n)=>({source:n.endsWith("/")&&n!=="/"?n:`${n}/`,target:n.endsWith("/")&&n!=="/"?n.slice(0,-1):n,statusCode:301}))};static Patterns={flattenBlogUrls:(a)=>a.map(({oldPath:n,newPath:i})=>({source:n,target:i,statusCode:301,preserveQueryString:!0})),categoryRename:(a,n)=>[{source:`/${a}`,target:`/${n}`,statusCode:301},{source:`/${a}/`,target:`/${n}/`,statusCode:301}],productSlugChange:(a)=>a.map(({oldSlug:n,newSlug:i})=>({source:`/products/${n}`,target:`/products/${i}`,statusCode:301})),apiVersionRedirect:(a,n,i)=>i.map((s)=>({source:`/api/${a}/${s}`,target:`/api/${n}/${s}`,statusCode:307,preserveQueryString:!0})),gonePages:(a)=>a.map((n)=>({source:n,target:"/410",statusCode:301}))};static createRedirectSetup(a){let{slug:n,environment:i,domainRedirects:s=[],pathRedirects:c=[]}=a,l={},u=[];for(let y of s){let{bucket:S,bucketPolicy:A,logicalId:C,policyLogicalId:T}=pt.createDomainRedirectBucket({...y,slug:n,environment:i});l[C]=S,l[T]=A,u.push(C)}let h=null;if(c.length>0){let{function:y,logicalId:S}=pt.createPathRedirectFunction({slug:n,environment:i,rules:c});l[S]=y,h=S}return{resources:l,outputs:{domainRedirectBuckets:u,pathRedirectFunctionLogicalId:h}}}static fromMapping(a,n){return Object.entries(a).map(([i,s])=>({source:i,target:s,statusCode:n?.statusCode||301,preserveQueryString:n?.preserveQueryString??!0}))}static validateRules(a){let n=[],i=[],s=new Set;for(let c of a){if(s.has(c.source))n.push(`Duplicate source path: ${c.source}`);if(s.add(c.source),c.source===c.target)n.push(`Redirect loop detected: ${c.source} -> ${c.target}`);if(!c.target.startsWith("/")&&!c.target.startsWith("http"))i.push(`Target URL should start with / or http: ${c.target}`);if(!c.source||c.source.trim()==="")n.push("Source path cannot be empty");if(!c.target||c.target.trim()==="")n.push("Target path cannot be empty")}for(let c of a){let l=a.find((u)=>u.source===c.target);if(l)i.push(`Potential redirect chain: ${c.source} -> ${c.target} -> ${l.target}`)}return{valid:n.length===0,errors:n,warnings:i}}}class H{static generate(a){let n={},{slug:i,environment:s,region:c="us-east-1"}=a,l=H.createLambdaExecutionRole(i,s);if(Object.assign(n,l.resources),a.email?.enabled){let u=H.generateEmailResources(a,l.roleArn);Object.assign(n,u)}if(a.phone?.enabled){let u=H.generatePhoneResources(a,l.roleArn);Object.assign(n,u)}if(a.sms?.enabled){let u=H.generateSmsResources(a,l.roleArn);Object.assign(n,u)}return n}static createLambdaExecutionRole(a,n){let i=`${a}-${n}-communication-role`,s=t(i);return{resources:{[s]:{Type:"AWS::IAM::Role",Properties:{RoleName:i,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],Policies:[{PolicyName:"CommunicationPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:"*"},{Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail","ses:GetIdentityVerificationAttributes"],Resource:"*"},{Effect:"Allow",Action:["sns:Publish","sns:Subscribe"],Resource:"*"},{Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:BatchWriteItem","dynamodb:BatchGetItem"],Resource:"*"},{Effect:"Allow",Action:["connect:*"],Resource:"*"},{Effect:"Allow",Action:["mobiletargeting:SendMessages","mobiletargeting:GetEndpoint","mobiletargeting:UpdateEndpoint"],Resource:"*"},{Effect:"Allow",Action:["transcribe:StartTranscriptionJob","transcribe:GetTranscriptionJob"],Resource:"*"},{Effect:"Allow",Action:["bedrock:InvokeModel"],Resource:"*"},{Effect:"Allow",Action:["es:ESHttpGet","es:ESHttpPost","es:ESHttpPut","es:ESHttpDelete"],Resource:"*"}]}}]}}},roleArn:N.GetAtt(s,"Arn"),roleName:i}}static generateEmailResources(a,n){let{slug:i,environment:s,email:c}=a;if(!c)return{};let l={},u=`${i}-${s}`,h=`${u}-email-storage`,y=t(h);l[y]={Type:"AWS::S3::Bucket",Properties:{BucketName:h,LifecycleConfiguration:{Rules:[{Id:"ArchiveOldEmails",Status:"Enabled",Transitions:c.server?.storage?.archiveAfterDays?[{StorageClass:"GLACIER",TransitionInDays:c.server.storage.archiveAfterDays}]:[],ExpirationInDays:c.server?.storage?.retentionDays||365}]},NotificationConfiguration:{LambdaConfigurations:[]}}};let S=t(`${u}-ses-identity`);if(l[S]={Type:"AWS::SES::EmailIdentity",Properties:{EmailIdentity:c.domain,DkimSigningAttributes:{NextSigningKeyLength:"RSA_2048_BIT"},FeedbackAttributes:{EmailForwardingEnabled:!0}}},c.notifications?.bounces||c.notifications?.complaints){let A=t(`${u}-bounce-topic`);l[A]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${u}-email-bounces`}};let C=t(`${u}-complaint-topic`);l[C]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${u}-email-complaints`}}}if(c.server?.enabled){let A=t(`${u}-inbound-email`);l[A]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-inbound-email`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n,Timeout:60,MemorySize:256,Code:{ZipFile:H.InboundEmailCode},Environment:{Variables:{EMAIL_BUCKET:h,DOMAIN:c.domain}}}};let C=t(`${u}-outbound-email`);l[C]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-outbound-email`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n,Timeout:30,MemorySize:256,Code:{ZipFile:H.OutboundEmailCode},Environment:{Variables:{EMAIL_BUCKET:h,DOMAIN:c.domain}}}}}if(c.advanced?.analytics){let A=t(`${u}-email-analytics`);l[A]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-email-analytics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.scheduling){let A=t(`${u}-email-scheduler`);l[A]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-email-scheduler`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n,Timeout:300,MemorySize:256,Code:{ZipFile:H.EmailSchedulerCode},Environment:{Variables:{EMAIL_BUCKET:h}}}};let C=t(`${u}-email-scheduler-rule`);l[C]={Type:"AWS::Events::Rule",Properties:{Name:`${u}-email-scheduler`,ScheduleExpression:"rate(1 minute)",State:"ENABLED",Targets:[{Id:"EmailSchedulerTarget",Arn:N.GetAtt(A,"Arn")}]}}}if(c.advanced?.threading){let A=t(`${u}-email-threading`);l[A]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-email-threading`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n,Timeout:60,MemorySize:256,Code:{ZipFile:H.EmailThreadingCode},Environment:{Variables:{EMAIL_BUCKET:h}}}}}if(c.advanced?.rules){let A=t(`${u}-email-rules`);l[A]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-email-rules`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"mailbox",AttributeType:"S"},{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"mailbox",KeyType:"HASH"},{AttributeName:"id",KeyType:"RANGE"}]}}}if(c.advanced?.sharedMailboxes){let A=t(`${u}-shared-mailboxes`);l[A]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-shared-mailboxes`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"},{AttributeName:"type",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],GlobalSecondaryIndexes:[{IndexName:"type-index",KeySchema:[{AttributeName:"type",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"}}]}}}if(c.advanced?.search){let A=t(`${u}-email-search`);l[A]={Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:`${u}-email-search`.toLowerCase().replace(/[^a-z0-9-]/g,"-").substring(0,28),EngineVersion:"OpenSearch_2.11",ClusterConfig:{InstanceType:"t3.small.search",InstanceCount:1},EBSOptions:{EBSEnabled:!0,VolumeType:"gp3",VolumeSize:10},NodeToNodeEncryptionOptions:{Enabled:!0},EncryptionAtRestOptions:{Enabled:!0},DomainEndpointOptions:{EnforceHTTPS:!0}}}}return l}static generatePhoneResources(a,n){let{slug:i,environment:s,phone:c}=a;if(!c)return{};let l={},u=`${i}-${s}`,h=t(`${u}-call-log`);if(l[h]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-call-log`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"contactId",AttributeType:"S"}],KeySchema:[{AttributeName:"contactId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}},c.voicemail?.enabled){let A=t(`${u}-voicemail`);l[A]={Type:"AWS::S3::Bucket",Properties:{BucketName:`${u}-voicemail`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldVoicemails",Status:"Enabled",ExpirationInDays:90}]}}}}let y=t(`${u}-phone-notifications`);l[y]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${u}-phone-notifications`}};let S=t(`${u}-incoming-call`);if(l[S]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-incoming-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n,Timeout:30,MemorySize:256,Code:{ZipFile:H.IncomingCallCode},Environment:{Variables:{CALL_LOG_TABLE:`${u}-call-log`,NOTIFICATION_TOPIC_ARN:N.Ref(y)}}}},c.voicemail?.enabled){let A=t(`${u}-voicemail-handler`);l[A]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-voicemail-handler`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n,Timeout:c.voicemail.transcription?300:60,MemorySize:256,Code:{ZipFile:H.VoicemailCode},Environment:{Variables:{VOICEMAIL_BUCKET:`${u}-voicemail`,TRANSCRIPTION_ENABLED:String(c.voicemail.transcription||!1),NOTIFICATION_TOPIC_ARN:N.Ref(y)}}}}}if(c.advanced?.recording){let A=t(`${u}-call-recordings`);l[A]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-call-recordings`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"recordingId",AttributeType:"S"}],KeySchema:[{AttributeName:"recordingId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.callbacks){let A=t(`${u}-callbacks`);l[A]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-callbacks`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.analytics){let A=t(`${u}-call-metrics`);l[A]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-call-metrics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"period",AttributeType:"S"}],KeySchema:[{AttributeName:"period",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}return l}static generateSmsResources(a,n){let{slug:i,environment:s,sms:c}=a;if(!c)return{};let l={},u=`${i}-${s}`,h=t(`${u}-pinpoint-app`);l[h]={Type:"AWS::Pinpoint::App",Properties:{Name:`${u}-sms`}};let y=t(`${u}-sms-channel`);l[y]={Type:"AWS::Pinpoint::SMSChannel",Properties:{ApplicationId:N.Ref(h),Enabled:!0,SenderId:c.senderId}};let S=t(`${u}-sms-log`);if(l[S]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-sms-log`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}},c.optOut?.enabled){let v=t(`${u}-sms-optout`);l[v]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-sms-optout`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}]}}}let A=t(`${u}-sms-notifications`);l[A]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${u}-sms-notifications`}};let C=t(`${u}-send-sms`);l[C]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-send-sms`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n,Timeout:30,MemorySize:256,Code:{ZipFile:H.SendSmsCode},Environment:{Variables:{PINPOINT_APP_ID:N.Ref(h),MESSAGE_LOG_TABLE:`${u}-sms-log`,OPT_OUT_TABLE:c.optOut?.enabled?`${u}-sms-optout`:"",MESSAGE_TYPE:c.messageType||"TRANSACTIONAL"}}}};let T=t(`${u}-receive-sms`);if(l[T]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-receive-sms`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n,Timeout:30,MemorySize:256,Code:{ZipFile:H.ReceiveSmsCode},Environment:{Variables:{MESSAGE_LOG_TABLE:`${u}-sms-log`,OPT_OUT_TABLE:c.optOut?.enabled?`${u}-sms-optout`:"",NOTIFICATION_TOPIC_ARN:N.Ref(A)}}}},c.advanced?.campaigns){let v=t(`${u}-sms-campaigns`);l[v]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-sms-campaigns`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}if(c.advanced?.analytics){let v=t(`${u}-sms-analytics`);l[v]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-sms-analytics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"period",AttributeType:"S"}],KeySchema:[{AttributeName:"period",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.linkTracking){let v=t(`${u}-short-links`);l[v]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-short-links`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.chatbot){let v=t(`${u}-chatbot-sessions`);l[v]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-chatbot-sessions`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}};let w=t(`${u}-chatbot-rules`);l[w]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-chatbot-rules`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}if(c.advanced?.abTesting){let v=t(`${u}-ab-tests`);l[v]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-ab-tests`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}if(c.advanced?.mms){let v=t(`${u}-mms-media`);l[v]={Type:"AWS::S3::Bucket",Properties:{BucketName:`${u}-mms-media`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldMedia",Status:"Enabled",ExpirationInDays:30}]}}}}return l}static InboundEmailCode=`
2371
2371
  const { S3Client, GetObjectCommand, PutObjectCommand } = require('@aws-sdk/client-s3');
2372
2372
  const s3 = new S3Client({});
2373
2373
  exports.handler = async (event) => {
@@ -2465,7 +2465,7 @@ exports.handler = async (event) => {
2465
2465
  console.log('Receive SMS:', JSON.stringify(event, null, 2));
2466
2466
  // Process inbound SMS, handle opt-out keywords
2467
2467
  return { statusCode: 200 };
2468
- };`}var e={ref:(a)=>({Ref:a}),getAtt:(a,n)=>({"Fn::GetAtt":[a,n]}),join:(a,n)=>({"Fn::Join":[a,n]}),sub:(a,n)=>n?{"Fn::Sub":[a,n]}:{"Fn::Sub":a},select:(a,n)=>({"Fn::Select":[a,n]}),split:(a,n)=>({"Fn::Split":[a,n]}),getAZs:(a="")=>({"Fn::GetAZs":a}),importValue:(a)=>({"Fn::ImportValue":a}),findInMap:(a,n,i)=>({"Fn::FindInMap":[a,n,i]}),base64:(a)=>({"Fn::Base64":a}),cidr:(a,n,i)=>({"Fn::Cidr":[a,n,i]}),equals:(a,n)=>({"Fn::Equals":[a,n]}),if:(a,n,i)=>({"Fn::If":[a,n,i]}),not:(a)=>({"Fn::Not":[a]}),and:(...a)=>({"Fn::And":a}),or:(...a)=>({"Fn::Or":a})},eo={s3Bucket:(a)=>e.sub(`arn:aws:s3:::${a}`),s3Object:(a,n="*")=>e.sub(`arn:aws:s3:::${a}/${n}`),lambda:(a,n,i)=>e.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${a}`,n&&i?{"AWS::Region":n,"AWS::AccountId":i}:void 0),dynamodb:(a)=>e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${a}`),sqs:(a)=>e.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${a}`),sns:(a)=>e.sub(`arn:aws:sns:\${AWS::Region}:\${AWS::AccountId}:${a}`),kinesis:(a)=>e.sub(`arn:aws:kinesis:\${AWS::Region}:\${AWS::AccountId}:stream/${a}`),iam:(a,n)=>e.sub(`arn:aws:iam::\${AWS::AccountId}:${a}/${n}`),secretsManager:(a)=>e.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${a}`),cloudwatch:(a)=>e.sub(`arn:aws:logs:\${AWS::Region}:\${AWS::AccountId}:log-group:${a}`)},Vy={ACCOUNT_ID:{Ref:"AWS::AccountId"},NOTIFICATION_ARNS:{Ref:"AWS::NotificationARNs"},NO_VALUE:{Ref:"AWS::NoValue"},PARTITION:{Ref:"AWS::Partition"},REGION:{Ref:"AWS::Region"},STACK_ID:{Ref:"AWS::StackId"},STACK_NAME:{Ref:"AWS::StackName"},URL_SUFFIX:{Ref:"AWS::URLSuffix"}};function wr(a,n){if(n.type==="http")Er(a,n);else if(n.type==="rest")Pr(a,n);else if(n.type==="websocket")Ir(a,n)}function Er(a,n){let i={Name:e.sub("${AWS::StackName}-http-api"),ProtocolType:"HTTP"};if(n.cors)i.CorsConfiguration={AllowOrigins:n.cors.allowOrigins,AllowMethods:n.cors.allowMethods,AllowHeaders:n.cors.allowHeaders||["*"],MaxAge:n.cors.maxAge||300};if(a.addResource("HttpApi","AWS::ApiGatewayV2::Api",i),a.addResource("HttpApiStage","AWS::ApiGatewayV2::Stage",{ApiId:e.ref("HttpApi"),StageName:"$default",AutoDeploy:!0,DefaultRouteSettings:n.throttling?{ThrottlingBurstLimit:n.throttling.burstLimit,ThrottlingRateLimit:n.throttling.rateLimit}:void 0,AccessLogSettings:{DestinationArn:e.getAtt("ApiLogGroup","Arn"),Format:"$context.requestId $context.error.message $context.error.messageString"}},{dependsOn:["HttpApi","ApiLogGroup"]}),a.addResource("ApiLogGroup","AWS::Logs::LogGroup",{LogGroupName:e.sub("/aws/apigateway/${AWS::StackName}-http-api"),RetentionInDays:14}),n.authorizer)Rr(a,"HttpApi",n.authorizer);if(n.customDomain)Ot(a,"HttpApi",n.customDomain,"HTTP");a.addOutputs({HttpApiId:{Description:"HTTP API ID",Value:e.ref("HttpApi"),Export:{Name:e.sub("${AWS::StackName}-http-api-id")}},HttpApiEndpoint:{Description:"HTTP API endpoint",Value:e.getAtt("HttpApi","ApiEndpoint"),Export:{Name:e.sub("${AWS::StackName}-http-api-endpoint")}}})}function Pr(a,n){a.addResource("RestApi","AWS::ApiGateway::RestApi",{Name:e.sub("${AWS::StackName}-rest-api"),Description:e.sub("REST API for ${AWS::StackName}"),EndpointConfiguration:{Types:["REGIONAL"]}}),a.addResource("ApiGatewayAccount","AWS::ApiGateway::Account",{CloudWatchRoleArn:e.getAtt("ApiGatewayCloudWatchRole","Arn")},{dependsOn:"ApiGatewayCloudWatchRole"}),a.addResource("ApiGatewayCloudWatchRole","AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"apigateway.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs"]}),a.addResource("RestApiDeployment","AWS::ApiGateway::Deployment",{RestApiId:e.ref("RestApi"),Description:"Initial deployment"},{dependsOn:"RestApi"});let i={RestApiId:e.ref("RestApi"),DeploymentId:e.ref("RestApiDeployment"),StageName:"prod",Description:"Production stage",MethodSettings:[{ResourcePath:"/*",HttpMethod:"*",LoggingLevel:"INFO",DataTraceEnabled:!0,MetricsEnabled:!0}]};if(n.throttling)i.MethodSettings[0].ThrottlingBurstLimit=n.throttling.burstLimit,i.MethodSettings[0].ThrottlingRateLimit=n.throttling.rateLimit;if(a.addResource("RestApiStage","AWS::ApiGateway::Stage",i,{dependsOn:["RestApi","RestApiDeployment"]}),n.customDomain)Ot(a,"RestApi",n.customDomain,"REST");a.addOutputs({RestApiId:{Description:"REST API ID",Value:e.ref("RestApi"),Export:{Name:e.sub("${AWS::StackName}-rest-api-id")}},RestApiEndpoint:{Description:"REST API endpoint",Value:e.sub("https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/prod"),Export:{Name:e.sub("${AWS::StackName}-rest-api-endpoint")}}})}function Ir(a,n){if(a.addResource("WebSocketApi","AWS::ApiGatewayV2::Api",{Name:e.sub("${AWS::StackName}-websocket-api"),ProtocolType:"WEBSOCKET",RouteSelectionExpression:"$request.body.action"}),n.routes){if(n.routes.connect)it(a,"$connect",n.routes.connect.functionName);if(n.routes.disconnect)it(a,"$disconnect",n.routes.disconnect.functionName);if(n.routes.default)it(a,"$default",n.routes.default.functionName);if(n.routes.custom)n.routes.custom.forEach((i)=>{it(a,i.routeKey,i.functionName)})}if(a.addResource("WebSocketApiStage","AWS::ApiGatewayV2::Stage",{ApiId:e.ref("WebSocketApi"),StageName:"prod",AutoDeploy:!0,DefaultRouteSettings:n.throttling?{ThrottlingBurstLimit:n.throttling.burstLimit,ThrottlingRateLimit:n.throttling.rateLimit}:void 0},{dependsOn:"WebSocketApi"}),n.customDomain)Ot(a,"WebSocketApi",n.customDomain,"WEBSOCKET");a.addOutputs({WebSocketApiId:{Description:"WebSocket API ID",Value:e.ref("WebSocketApi"),Export:{Name:e.sub("${AWS::StackName}-websocket-api-id")}},WebSocketApiEndpoint:{Description:"WebSocket API endpoint",Value:e.getAtt("WebSocketApi","ApiEndpoint"),Export:{Name:e.sub("${AWS::StackName}-websocket-api-endpoint")}}})}function it(a,n,i){let s=a.toLogicalId(`websocket-route-${n}`),c=a.toLogicalId(`websocket-integration-${n}`),l=a.toLogicalId(`${i}-function`);a.addResource(c,"AWS::ApiGatewayV2::Integration",{ApiId:e.ref("WebSocketApi"),IntegrationType:"AWS_PROXY",IntegrationUri:e.sub(`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${l}.Arn}/invocations`)},{dependsOn:["WebSocketApi",l]}),a.addResource(s,"AWS::ApiGatewayV2::Route",{ApiId:e.ref("WebSocketApi"),RouteKey:n,Target:e.join("/",["integrations",e.ref(c)])},{dependsOn:["WebSocketApi",c]}),a.addResource(`${s}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(l),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:e.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${WebSocketApi}/*")},{dependsOn:[l,"WebSocketApi"]})}function Ot(a,n,i,s){let c={DomainName:i.domain};if(s==="REST")c.CertificateArn=i.certificateArn,c.EndpointConfiguration={Types:["REGIONAL"]},a.addResource("ApiCustomDomain","AWS::ApiGateway::DomainName",c),a.addResource("ApiBasePathMapping","AWS::ApiGateway::BasePathMapping",{DomainName:e.ref("ApiCustomDomain"),RestApiId:e.ref(n),Stage:e.ref("RestApiStage")},{dependsOn:["ApiCustomDomain",n,"RestApiStage"]});else c.DomainNameConfigurations=[{CertificateArn:i.certificateArn,EndpointType:"REGIONAL"}],a.addResource("ApiCustomDomain","AWS::ApiGatewayV2::DomainName",c),a.addResource("ApiMapping","AWS::ApiGatewayV2::ApiMapping",{ApiId:e.ref(n),DomainName:e.ref("ApiCustomDomain"),Stage:s==="HTTP"?e.ref("HttpApiStage"):e.ref("WebSocketApiStage")},{dependsOn:["ApiCustomDomain",n]});if(i.dnsProvider!=="external")a.addResource("ApiDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:e.sub(`${Nr(i.domain)}.`),Name:i.domain,Type:"A",AliasTarget:{HostedZoneId:e.getAtt("ApiCustomDomain","RegionalHostedZoneId"),DNSName:e.getAtt("ApiCustomDomain","RegionalDomainName"),EvaluateTargetHealth:!1}},{dependsOn:"ApiCustomDomain"});a.addOutputs({ApiCustomDomainName:{Description:"Configured API custom domain",Value:i.domain},ApiCustomDomainTarget:{Description:"DNS target for Route53 or an external DNS provider",Value:e.getAtt("ApiCustomDomain","RegionalDomainName")},ApiCustomDomainHostedZoneId:{Description:"Regional API Gateway hosted zone ID",Value:e.getAtt("ApiCustomDomain","RegionalHostedZoneId")}})}function Rr(a,n,i){if(!i)return;if(i.type==="jwt")a.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:e.ref(n),AuthorizerType:"JWT",IdentitySource:[i.identitySource||"$request.header.Authorization"],JwtConfiguration:{Issuer:i.issuer,Audience:i.audience},Name:"JWTAuthorizer"},{dependsOn:n});else if(i.type==="lambda")a.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:e.ref(n),AuthorizerType:"REQUEST",AuthorizerUri:i.authorizerUri,IdentitySource:[i.identitySource||"$request.header.Authorization"],Name:"LambdaAuthorizer"},{dependsOn:n})}function Nr(a){let n=a.split(".");if(n.length>=2)return n.slice(-2).join(".");return a}function Dr(a,n){if(n.redis)kr(a,n.redis);if(n.memcached)xr(a,n.memcached);if(n.elasticache)Br(a,n.elasticache)}function kr(a,n){if(!n)return;if(a.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache Redis cluster",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-subnet-group")}]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]}),a.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Redis",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:n.port||6379,ToPort:n.port||6379,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]}),n.parameterGroup&&Object.keys(n.parameterGroup).length>0)a.addResource("CacheParameterGroup","AWS::ElastiCache::ParameterGroup",{Description:"Parameter group for Redis",CacheParameterGroupFamily:`redis${n.engineVersion.split(".")[0]}`,Properties:n.parameterGroup});if(n.numCacheNodes>1||n.automaticFailoverEnabled)a.addResource("RedisReplicationGroup","AWS::ElastiCache::ReplicationGroup",{ReplicationGroupDescription:"Redis replication group",ReplicationGroupId:e.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:n.engineVersion,CacheNodeType:n.nodeType,NumCacheClusters:n.numCacheNodes,AutomaticFailoverEnabled:n.automaticFailoverEnabled||!1,MultiAZEnabled:n.automaticFailoverEnabled||!1,Port:n.port||6379,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),SecurityGroupIds:[e.ref("CacheSecurityGroup")],CacheParameterGroupName:n.parameterGroup?e.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:n.snapshotRetentionLimit||5,SnapshotWindow:n.snapshotWindow||"03:00-05:00",PreferredMaintenanceWindow:"sun:05:00-sun:06:00",AtRestEncryptionEnabled:!0,TransitEncryptionEnabled:!0,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-redis")}]},{dependsOn:n.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),a.addOutputs({RedisEndpoint:{Description:"Redis primary endpoint",Value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Address"),Export:{Name:e.sub("${AWS::StackName}-redis-endpoint")}},RedisPort:{Description:"Redis port",Value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Port"),Export:{Name:e.sub("${AWS::StackName}-redis-port")}}});else a.addResource("RedisCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:n.engineVersion,CacheNodeType:n.nodeType,NumCacheNodes:1,Port:n.port||6379,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],CacheParameterGroupName:n.parameterGroup?e.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:n.snapshotRetentionLimit||5,SnapshotWindow:n.snapshotWindow||"03:00-05:00",PreferredMaintenanceWindow:"sun:05:00-sun:06:00",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-redis")}]},{dependsOn:n.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),a.addOutputs({RedisEndpoint:{Description:"Redis endpoint",Value:e.getAtt("RedisCacheCluster","RedisEndpoint.Address"),Export:{Name:e.sub("${AWS::StackName}-redis-endpoint")}},RedisPort:{Description:"Redis port",Value:e.getAtt("RedisCacheCluster","RedisEndpoint.Port"),Export:{Name:e.sub("${AWS::StackName}-redis-port")}}})}function xr(a,n){if(!n)return;if(!a.hasResource("CacheSubnetGroup"))a.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!a.hasResource("CacheSecurityGroup"))a.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Memcached",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:n.port||11211,ToPort:n.port||11211,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});a.addResource("MemcachedCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub("${AWS::StackName}-memcached"),Engine:"memcached",EngineVersion:n.engineVersion,CacheNodeType:n.nodeType,NumCacheNodes:n.numCacheNodes,Port:n.port||11211,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],PreferredMaintenanceWindow:"sun:05:00-sun:06:00",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-memcached")}]},{dependsOn:["CacheSubnetGroup","CacheSecurityGroup"]}),a.addOutputs({MemcachedEndpoint:{Description:"Memcached configuration endpoint",Value:e.getAtt("MemcachedCacheCluster","ConfigurationEndpoint.Address"),Export:{Name:e.sub("${AWS::StackName}-memcached-endpoint")}},MemcachedPort:{Description:"Memcached port",Value:e.getAtt("MemcachedCacheCluster","ConfigurationEndpoint.Port"),Export:{Name:e.sub("${AWS::StackName}-memcached-port")}}})}function Br(a,n){if(!n)return;let i=n.engine==="redis";if(!a.hasResource("CacheSubnetGroup"))a.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!a.hasResource("CacheSecurityGroup"))a.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:i?6379:11211,ToPort:i?6379:11211,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});a.addResource("CacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub(`\${AWS::StackName}-${n.engine}`),Engine:n.engine,EngineVersion:n.engineVersion,CacheNodeType:n.nodeType,NumCacheNodes:n.numCacheNodes,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n.engine}`)}]},{dependsOn:["CacheSubnetGroup","CacheSecurityGroup"]})}function Wr(a,n){if(!n.enabled)return;a.addResource("CloudFrontOriginAccessIdentity","AWS::CloudFront::CloudFrontOriginAccessIdentity",{CloudFrontOriginAccessIdentityConfig:{Comment:e.sub("${AWS::StackName} CloudFront OAI")}});let i=[],s=[];if(!n.origins||n.origins.length===0)i.push({Id:"S3Origin",DomainName:e.getAtt("StaticBucket","DomainName"),S3OriginConfig:{OriginAccessIdentity:e.sub("origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}")}});else n.origins.forEach((u,h)=>{let y={Id:u.id,DomainName:u.domainName};if(u.originPath)y.OriginPath=u.originPath;if(u.domainName.includes("s3"))y.S3OriginConfig={OriginAccessIdentity:e.sub("origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}")};else y.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"]};if(i.push(y),h>0||u.pathPattern)s.push({PathPattern:u.pathPattern||`/${u.id}/*`,TargetOriginId:u.id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:n.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:n.cachePolicy?.minTTL||0,DefaultTTL:n.cachePolicy?.defaultTTL||86400,MaxTTL:n.cachePolicy?.maxTTL||31536000})});let c={TargetOriginId:i[0].Id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:n.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:n.cachePolicy?.minTTL||0,DefaultTTL:n.cachePolicy?.defaultTTL||86400,MaxTTL:n.cachePolicy?.maxTTL||31536000};if(n.edgeFunctions&&n.edgeFunctions.length>0)c.LambdaFunctionAssociations=n.edgeFunctions.map((u)=>({EventType:u.eventType,LambdaFunctionARN:u.functionArn}));let l={Enabled:!0,HttpVersion:n.http3?"http3":"http2",IPV6Enabled:!0,Origins:i,DefaultCacheBehavior:c,PriceClass:n.priceClass||"PriceClass_100",ViewerCertificate:{}};if(s.length>0)l.CacheBehaviors=s;if(n.customDomain)l.Aliases=[n.customDomain.domain],l.ViewerCertificate={AcmCertificateArn:n.customDomain.certificateArn,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};else l.ViewerCertificate={CloudFrontDefaultCertificate:!0};if(n.errorPages)l.CustomErrorResponses=Object.entries(n.errorPages).map(([u,h])=>({ErrorCode:Number.parseInt(u),ResponseCode:200,ResponsePagePath:h,ErrorCachingMinTTL:300}));if(l.DefaultRootObject="index.html",l.Comment=e.sub("${AWS::StackName} CloudFront Distribution"),a.addResource("CloudFrontDistribution","AWS::CloudFront::Distribution",{DistributionConfig:l},{dependsOn:"CloudFrontOriginAccessIdentity"}),!n.origins||n.origins.length===0)a.addResource("StaticBucketPolicyForCloudFront","AWS::S3::BucketPolicy",{Bucket:e.ref("StaticBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowCloudFrontAccess",Effect:"Allow",Principal:{CanonicalUser:e.getAtt("CloudFrontOriginAccessIdentity","S3CanonicalUserId")},Action:"s3:GetObject",Resource:e.join("",[e.getAtt("StaticBucket","Arn"),"/*"])}]}},{dependsOn:["StaticBucket","CloudFrontOriginAccessIdentity"]});if(n.customDomain)a.addResource("CloudFrontDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:e.sub(`${Gr(n.customDomain.domain)}.`),Name:n.customDomain.domain,Type:"A",AliasTarget:{HostedZoneId:"Z2FDTNDATAQYW2",DNSName:e.getAtt("CloudFrontDistribution","DomainName"),EvaluateTargetHealth:!1}},{dependsOn:"CloudFrontDistribution"});if(a.addOutputs({CloudFrontDistributionId:{Description:"CloudFront distribution ID",Value:e.ref("CloudFrontDistribution"),Export:{Name:e.sub("${AWS::StackName}-cloudfront-id")}},CloudFrontDomainName:{Description:"CloudFront distribution domain name",Value:e.getAtt("CloudFrontDistribution","DomainName"),Export:{Name:e.sub("${AWS::StackName}-cloudfront-domain")}}}),n.customDomain)a.addOutputs({CloudFrontURL:{Description:"CloudFront custom domain URL",Value:e.sub(`https://${n.customDomain.domain}`)}})}function Gr(a){let n=a.split(".");if(n.length>=2)return n.slice(-2).join(".");return a}function Ur(a,n){if(n.server)Fr(a,n.server);if(n.fargate)oa(a,"app",n.fargate);if(n.services)n.services.forEach((i)=>{if(i.type==="fargate")oa(a,i.name,{taskDefinition:i.taskDefinition,service:i.service})})}function Fr(a,n){if(!n)return;a.addResource("AppSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for application instances",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:3000,ToPort:3000,SourceSecurityGroupId:e.ref("ALBSecurityGroup")},{IpProtocol:"tcp",FromPort:22,ToPort:22,CidrIp:"0.0.0.0/0"}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-app-sg")}]},{dependsOn:"VPC"}),a.addResource("EC2InstanceRole","AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ec2.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore","arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-ec2-role")}]}),a.addResource("EC2InstanceProfile","AWS::IAM::InstanceProfile",{Roles:[e.ref("EC2InstanceRole")]},{dependsOn:"EC2InstanceRole"});let i=n.userData||`#!/bin/bash
2468
+ };`}var e={ref:(a)=>({Ref:a}),getAtt:(a,n)=>({"Fn::GetAtt":[a,n]}),join:(a,n)=>({"Fn::Join":[a,n]}),sub:(a,n)=>n?{"Fn::Sub":[a,n]}:{"Fn::Sub":a},select:(a,n)=>({"Fn::Select":[a,n]}),split:(a,n)=>({"Fn::Split":[a,n]}),getAZs:(a="")=>({"Fn::GetAZs":a}),importValue:(a)=>({"Fn::ImportValue":a}),findInMap:(a,n,i)=>({"Fn::FindInMap":[a,n,i]}),base64:(a)=>({"Fn::Base64":a}),cidr:(a,n,i)=>({"Fn::Cidr":[a,n,i]}),equals:(a,n)=>({"Fn::Equals":[a,n]}),if:(a,n,i)=>({"Fn::If":[a,n,i]}),not:(a)=>({"Fn::Not":[a]}),and:(...a)=>({"Fn::And":a}),or:(...a)=>({"Fn::Or":a})},eo={s3Bucket:(a)=>e.sub(`arn:aws:s3:::${a}`),s3Object:(a,n="*")=>e.sub(`arn:aws:s3:::${a}/${n}`),lambda:(a,n,i)=>e.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${a}`,n&&i?{"AWS::Region":n,"AWS::AccountId":i}:void 0),dynamodb:(a)=>e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${a}`),sqs:(a)=>e.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${a}`),sns:(a)=>e.sub(`arn:aws:sns:\${AWS::Region}:\${AWS::AccountId}:${a}`),kinesis:(a)=>e.sub(`arn:aws:kinesis:\${AWS::Region}:\${AWS::AccountId}:stream/${a}`),iam:(a,n)=>e.sub(`arn:aws:iam::\${AWS::AccountId}:${a}/${n}`),secretsManager:(a)=>e.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${a}`),cloudwatch:(a)=>e.sub(`arn:aws:logs:\${AWS::Region}:\${AWS::AccountId}:log-group:${a}`)},Vy={ACCOUNT_ID:{Ref:"AWS::AccountId"},NOTIFICATION_ARNS:{Ref:"AWS::NotificationARNs"},NO_VALUE:{Ref:"AWS::NoValue"},PARTITION:{Ref:"AWS::Partition"},REGION:{Ref:"AWS::Region"},STACK_ID:{Ref:"AWS::StackId"},STACK_NAME:{Ref:"AWS::StackName"},URL_SUFFIX:{Ref:"AWS::URLSuffix"}};function wr(a,n){if(n.type==="http")Er(a,n);else if(n.type==="rest")Pr(a,n);else if(n.type==="websocket")Ir(a,n)}function Er(a,n){let i={Name:e.sub("${AWS::StackName}-http-api"),ProtocolType:"HTTP"};if(n.cors)i.CorsConfiguration={AllowOrigins:n.cors.allowOrigins,AllowMethods:n.cors.allowMethods,AllowHeaders:n.cors.allowHeaders||["*"],MaxAge:n.cors.maxAge||300};if(a.addResource("HttpApi","AWS::ApiGatewayV2::Api",i),a.addResource("HttpApiStage","AWS::ApiGatewayV2::Stage",{ApiId:e.ref("HttpApi"),StageName:"$default",AutoDeploy:!0,DefaultRouteSettings:n.throttling?{ThrottlingBurstLimit:n.throttling.burstLimit,ThrottlingRateLimit:n.throttling.rateLimit}:void 0,AccessLogSettings:{DestinationArn:e.getAtt("ApiLogGroup","Arn"),Format:"$context.requestId $context.error.message $context.error.messageString"}},{dependsOn:["HttpApi","ApiLogGroup"]}),a.addResource("ApiLogGroup","AWS::Logs::LogGroup",{LogGroupName:e.sub("/aws/apigateway/${AWS::StackName}-http-api"),RetentionInDays:14}),n.authorizer)Rr(a,"HttpApi",n.authorizer);if(n.customDomain)Ot(a,"HttpApi",n.customDomain,"HTTP");a.addOutputs({HttpApiId:{Description:"HTTP API ID",Value:e.ref("HttpApi"),Export:{Name:e.sub("${AWS::StackName}-http-api-id")}},HttpApiEndpoint:{Description:"HTTP API endpoint",Value:e.getAtt("HttpApi","ApiEndpoint"),Export:{Name:e.sub("${AWS::StackName}-http-api-endpoint")}}})}function Pr(a,n){a.addResource("RestApi","AWS::ApiGateway::RestApi",{Name:e.sub("${AWS::StackName}-rest-api"),Description:e.sub("REST API for ${AWS::StackName}"),EndpointConfiguration:{Types:["REGIONAL"]}}),a.addResource("ApiGatewayAccount","AWS::ApiGateway::Account",{CloudWatchRoleArn:e.getAtt("ApiGatewayCloudWatchRole","Arn")},{dependsOn:"ApiGatewayCloudWatchRole"}),a.addResource("ApiGatewayCloudWatchRole","AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"apigateway.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs"]}),a.addResource("RestApiDeployment","AWS::ApiGateway::Deployment",{RestApiId:e.ref("RestApi"),Description:"Initial deployment"},{dependsOn:"RestApi"});let i={RestApiId:e.ref("RestApi"),DeploymentId:e.ref("RestApiDeployment"),StageName:"prod",Description:"Production stage",MethodSettings:[{ResourcePath:"/*",HttpMethod:"*",LoggingLevel:"INFO",DataTraceEnabled:!0,MetricsEnabled:!0}]};if(n.throttling)i.MethodSettings[0].ThrottlingBurstLimit=n.throttling.burstLimit,i.MethodSettings[0].ThrottlingRateLimit=n.throttling.rateLimit;if(a.addResource("RestApiStage","AWS::ApiGateway::Stage",i,{dependsOn:["RestApi","RestApiDeployment"]}),n.customDomain)Ot(a,"RestApi",n.customDomain,"REST");a.addOutputs({RestApiId:{Description:"REST API ID",Value:e.ref("RestApi"),Export:{Name:e.sub("${AWS::StackName}-rest-api-id")}},RestApiEndpoint:{Description:"REST API endpoint",Value:e.sub("https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/prod"),Export:{Name:e.sub("${AWS::StackName}-rest-api-endpoint")}}})}function Ir(a,n){if(a.addResource("WebSocketApi","AWS::ApiGatewayV2::Api",{Name:e.sub("${AWS::StackName}-websocket-api"),ProtocolType:"WEBSOCKET",RouteSelectionExpression:"$request.body.action"}),n.routes){if(n.routes.connect)it(a,"$connect",n.routes.connect.functionName);if(n.routes.disconnect)it(a,"$disconnect",n.routes.disconnect.functionName);if(n.routes.default)it(a,"$default",n.routes.default.functionName);if(n.routes.custom)n.routes.custom.forEach((i)=>{it(a,i.routeKey,i.functionName)})}if(a.addResource("WebSocketApiStage","AWS::ApiGatewayV2::Stage",{ApiId:e.ref("WebSocketApi"),StageName:"prod",AutoDeploy:!0,DefaultRouteSettings:n.throttling?{ThrottlingBurstLimit:n.throttling.burstLimit,ThrottlingRateLimit:n.throttling.rateLimit}:void 0},{dependsOn:"WebSocketApi"}),n.customDomain)Ot(a,"WebSocketApi",n.customDomain,"WEBSOCKET");a.addOutputs({WebSocketApiId:{Description:"WebSocket API ID",Value:e.ref("WebSocketApi"),Export:{Name:e.sub("${AWS::StackName}-websocket-api-id")}},WebSocketApiEndpoint:{Description:"WebSocket API endpoint",Value:e.getAtt("WebSocketApi","ApiEndpoint"),Export:{Name:e.sub("${AWS::StackName}-websocket-api-endpoint")}}})}function it(a,n,i){let s=a.toLogicalId(`websocket-route-${n}`),c=a.toLogicalId(`websocket-integration-${n}`),l=a.toLogicalId(`${i}-function`);a.addResource(c,"AWS::ApiGatewayV2::Integration",{ApiId:e.ref("WebSocketApi"),IntegrationType:"AWS_PROXY",IntegrationUri:e.sub(`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${l}.Arn}/invocations`)},{dependsOn:["WebSocketApi",l]}),a.addResource(s,"AWS::ApiGatewayV2::Route",{ApiId:e.ref("WebSocketApi"),RouteKey:n,Target:e.join("/",["integrations",e.ref(c)])},{dependsOn:["WebSocketApi",c]}),a.addResource(`${s}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(l),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:e.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${WebSocketApi}/*")},{dependsOn:[l,"WebSocketApi"]})}function Ot(a,n,i,s){let c={DomainName:i.domain};if(s==="REST")c.CertificateArn=i.certificateArn,c.EndpointConfiguration={Types:["REGIONAL"]},a.addResource("ApiCustomDomain","AWS::ApiGateway::DomainName",c),a.addResource("ApiBasePathMapping","AWS::ApiGateway::BasePathMapping",{DomainName:e.ref("ApiCustomDomain"),RestApiId:e.ref(n),Stage:e.ref("RestApiStage")},{dependsOn:["ApiCustomDomain",n,"RestApiStage"]});else c.DomainNameConfigurations=[{CertificateArn:i.certificateArn,EndpointType:"REGIONAL"}],a.addResource("ApiCustomDomain","AWS::ApiGatewayV2::DomainName",c),a.addResource("ApiMapping","AWS::ApiGatewayV2::ApiMapping",{ApiId:e.ref(n),DomainName:e.ref("ApiCustomDomain"),Stage:s==="HTTP"?e.ref("HttpApiStage"):e.ref("WebSocketApiStage")},{dependsOn:["ApiCustomDomain",n]});if(i.dnsProvider!=="external")a.addResource("ApiDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:e.sub(`${Nr(i.domain)}.`),Name:i.domain,Type:"A",AliasTarget:{HostedZoneId:e.getAtt("ApiCustomDomain","RegionalHostedZoneId"),DNSName:e.getAtt("ApiCustomDomain","RegionalDomainName"),EvaluateTargetHealth:!1}},{dependsOn:"ApiCustomDomain"});a.addOutputs({ApiCustomDomainName:{Description:"Configured API custom domain",Value:i.domain},ApiCustomDomainTarget:{Description:"DNS target for Route53 or an external DNS provider",Value:e.getAtt("ApiCustomDomain","RegionalDomainName")},ApiCustomDomainHostedZoneId:{Description:"Regional API Gateway hosted zone ID",Value:e.getAtt("ApiCustomDomain","RegionalHostedZoneId")}})}function Rr(a,n,i){if(!i)return;if(i.type==="jwt")a.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:e.ref(n),AuthorizerType:"JWT",IdentitySource:[i.identitySource||"$request.header.Authorization"],JwtConfiguration:{Issuer:i.issuer,Audience:i.audience},Name:"JWTAuthorizer"},{dependsOn:n});else if(i.type==="lambda")a.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:e.ref(n),AuthorizerType:"REQUEST",AuthorizerUri:i.authorizerUri,IdentitySource:[i.identitySource||"$request.header.Authorization"],Name:"LambdaAuthorizer"},{dependsOn:n})}function Nr(a){let n=a.split(".");if(n.length>=2)return n.slice(-2).join(".");return a}function Dr(a,n){if(n.redis)kr(a,n.redis);if(n.memcached)Br(a,n.memcached);if(n.elasticache)_r(a,n.elasticache)}function kr(a,n){if(!n)return;if(a.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache Redis cluster",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-subnet-group")}]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]}),a.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Redis",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:n.port||6379,ToPort:n.port||6379,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]}),n.parameterGroup&&Object.keys(n.parameterGroup).length>0)a.addResource("CacheParameterGroup","AWS::ElastiCache::ParameterGroup",{Description:"Parameter group for Redis",CacheParameterGroupFamily:`redis${n.engineVersion.split(".")[0]}`,Properties:n.parameterGroup});if(n.numCacheNodes>1||n.automaticFailoverEnabled)a.addResource("RedisReplicationGroup","AWS::ElastiCache::ReplicationGroup",{ReplicationGroupDescription:"Redis replication group",ReplicationGroupId:e.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:n.engineVersion,CacheNodeType:n.nodeType,NumCacheClusters:n.numCacheNodes,AutomaticFailoverEnabled:n.automaticFailoverEnabled||!1,MultiAZEnabled:n.automaticFailoverEnabled||!1,Port:n.port||6379,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),SecurityGroupIds:[e.ref("CacheSecurityGroup")],CacheParameterGroupName:n.parameterGroup?e.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:n.snapshotRetentionLimit||5,SnapshotWindow:n.snapshotWindow||"03:00-05:00",PreferredMaintenanceWindow:"sun:05:00-sun:06:00",AtRestEncryptionEnabled:!0,TransitEncryptionEnabled:!0,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-redis")}]},{dependsOn:n.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),a.addOutputs({RedisEndpoint:{Description:"Redis primary endpoint",Value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Address"),Export:{Name:e.sub("${AWS::StackName}-redis-endpoint")}},RedisPort:{Description:"Redis port",Value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Port"),Export:{Name:e.sub("${AWS::StackName}-redis-port")}}});else a.addResource("RedisCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:n.engineVersion,CacheNodeType:n.nodeType,NumCacheNodes:1,Port:n.port||6379,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],CacheParameterGroupName:n.parameterGroup?e.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:n.snapshotRetentionLimit||5,SnapshotWindow:n.snapshotWindow||"03:00-05:00",PreferredMaintenanceWindow:"sun:05:00-sun:06:00",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-redis")}]},{dependsOn:n.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),a.addOutputs({RedisEndpoint:{Description:"Redis endpoint",Value:e.getAtt("RedisCacheCluster","RedisEndpoint.Address"),Export:{Name:e.sub("${AWS::StackName}-redis-endpoint")}},RedisPort:{Description:"Redis port",Value:e.getAtt("RedisCacheCluster","RedisEndpoint.Port"),Export:{Name:e.sub("${AWS::StackName}-redis-port")}}})}function Br(a,n){if(!n)return;if(!a.hasResource("CacheSubnetGroup"))a.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!a.hasResource("CacheSecurityGroup"))a.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Memcached",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:n.port||11211,ToPort:n.port||11211,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});a.addResource("MemcachedCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub("${AWS::StackName}-memcached"),Engine:"memcached",EngineVersion:n.engineVersion,CacheNodeType:n.nodeType,NumCacheNodes:n.numCacheNodes,Port:n.port||11211,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],PreferredMaintenanceWindow:"sun:05:00-sun:06:00",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-memcached")}]},{dependsOn:["CacheSubnetGroup","CacheSecurityGroup"]}),a.addOutputs({MemcachedEndpoint:{Description:"Memcached configuration endpoint",Value:e.getAtt("MemcachedCacheCluster","ConfigurationEndpoint.Address"),Export:{Name:e.sub("${AWS::StackName}-memcached-endpoint")}},MemcachedPort:{Description:"Memcached port",Value:e.getAtt("MemcachedCacheCluster","ConfigurationEndpoint.Port"),Export:{Name:e.sub("${AWS::StackName}-memcached-port")}}})}function _r(a,n){if(!n)return;let i=n.engine==="redis";if(!a.hasResource("CacheSubnetGroup"))a.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!a.hasResource("CacheSecurityGroup"))a.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:i?6379:11211,ToPort:i?6379:11211,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});a.addResource("CacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub(`\${AWS::StackName}-${n.engine}`),Engine:n.engine,EngineVersion:n.engineVersion,CacheNodeType:n.nodeType,NumCacheNodes:n.numCacheNodes,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n.engine}`)}]},{dependsOn:["CacheSubnetGroup","CacheSecurityGroup"]})}function Wr(a,n){if(!n.enabled)return;a.addResource("CloudFrontOriginAccessIdentity","AWS::CloudFront::CloudFrontOriginAccessIdentity",{CloudFrontOriginAccessIdentityConfig:{Comment:e.sub("${AWS::StackName} CloudFront OAI")}});let i=[],s=[];if(!n.origins||n.origins.length===0)i.push({Id:"S3Origin",DomainName:e.getAtt("StaticBucket","DomainName"),S3OriginConfig:{OriginAccessIdentity:e.sub("origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}")}});else n.origins.forEach((u,h)=>{let y={Id:u.id,DomainName:u.domainName};if(u.originPath)y.OriginPath=u.originPath;if(u.domainName.includes("s3"))y.S3OriginConfig={OriginAccessIdentity:e.sub("origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}")};else y.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"]};if(i.push(y),h>0||u.pathPattern)s.push({PathPattern:u.pathPattern||`/${u.id}/*`,TargetOriginId:u.id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:n.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:n.cachePolicy?.minTTL||0,DefaultTTL:n.cachePolicy?.defaultTTL||86400,MaxTTL:n.cachePolicy?.maxTTL||31536000})});let c={TargetOriginId:i[0].Id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:n.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:n.cachePolicy?.minTTL||0,DefaultTTL:n.cachePolicy?.defaultTTL||86400,MaxTTL:n.cachePolicy?.maxTTL||31536000};if(n.edgeFunctions&&n.edgeFunctions.length>0)c.LambdaFunctionAssociations=n.edgeFunctions.map((u)=>({EventType:u.eventType,LambdaFunctionARN:u.functionArn}));let l={Enabled:!0,HttpVersion:n.http3?"http3":"http2",IPV6Enabled:!0,Origins:i,DefaultCacheBehavior:c,PriceClass:n.priceClass||"PriceClass_100",ViewerCertificate:{}};if(s.length>0)l.CacheBehaviors=s;if(n.customDomain)l.Aliases=[n.customDomain.domain],l.ViewerCertificate={AcmCertificateArn:n.customDomain.certificateArn,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};else l.ViewerCertificate={CloudFrontDefaultCertificate:!0};if(n.errorPages)l.CustomErrorResponses=Object.entries(n.errorPages).map(([u,h])=>({ErrorCode:Number.parseInt(u),ResponseCode:200,ResponsePagePath:h,ErrorCachingMinTTL:300}));if(l.DefaultRootObject="index.html",l.Comment=e.sub("${AWS::StackName} CloudFront Distribution"),a.addResource("CloudFrontDistribution","AWS::CloudFront::Distribution",{DistributionConfig:l},{dependsOn:"CloudFrontOriginAccessIdentity"}),!n.origins||n.origins.length===0)a.addResource("StaticBucketPolicyForCloudFront","AWS::S3::BucketPolicy",{Bucket:e.ref("StaticBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowCloudFrontAccess",Effect:"Allow",Principal:{CanonicalUser:e.getAtt("CloudFrontOriginAccessIdentity","S3CanonicalUserId")},Action:"s3:GetObject",Resource:e.join("",[e.getAtt("StaticBucket","Arn"),"/*"])}]}},{dependsOn:["StaticBucket","CloudFrontOriginAccessIdentity"]});if(n.customDomain)a.addResource("CloudFrontDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:e.sub(`${Gr(n.customDomain.domain)}.`),Name:n.customDomain.domain,Type:"A",AliasTarget:{HostedZoneId:"Z2FDTNDATAQYW2",DNSName:e.getAtt("CloudFrontDistribution","DomainName"),EvaluateTargetHealth:!1}},{dependsOn:"CloudFrontDistribution"});if(a.addOutputs({CloudFrontDistributionId:{Description:"CloudFront distribution ID",Value:e.ref("CloudFrontDistribution"),Export:{Name:e.sub("${AWS::StackName}-cloudfront-id")}},CloudFrontDomainName:{Description:"CloudFront distribution domain name",Value:e.getAtt("CloudFrontDistribution","DomainName"),Export:{Name:e.sub("${AWS::StackName}-cloudfront-domain")}}}),n.customDomain)a.addOutputs({CloudFrontURL:{Description:"CloudFront custom domain URL",Value:e.sub(`https://${n.customDomain.domain}`)}})}function Gr(a){let n=a.split(".");if(n.length>=2)return n.slice(-2).join(".");return a}function Ur(a,n){if(n.server)Fr(a,n.server);if(n.fargate)oa(a,"app",n.fargate);if(n.services)n.services.forEach((i)=>{if(i.type==="fargate")oa(a,i.name,{taskDefinition:i.taskDefinition,service:i.service})})}function Fr(a,n){if(!n)return;a.addResource("AppSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for application instances",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:3000,ToPort:3000,SourceSecurityGroupId:e.ref("ALBSecurityGroup")},{IpProtocol:"tcp",FromPort:22,ToPort:22,CidrIp:"0.0.0.0/0"}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-app-sg")}]},{dependsOn:"VPC"}),a.addResource("EC2InstanceRole","AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ec2.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore","arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-ec2-role")}]}),a.addResource("EC2InstanceProfile","AWS::IAM::InstanceProfile",{Roles:[e.ref("EC2InstanceRole")]},{dependsOn:"EC2InstanceRole"});let i=n.userData||`#!/bin/bash
2469
2469
  set -e
2470
2470
  # Update system
2471
2471
  yum update -y || apt-get update -y
@@ -2480,19 +2480,19 @@ rpm -U ./amazon-cloudwatch-agent.rpm || true
2480
2480
 
2481
2481
  # Signal completion
2482
2482
  /opt/aws/bin/cfn-signal -e $? --stack \${AWS::StackName} --resource AutoScalingGroup --region \${AWS::Region}
2483
- `;if(a.addResource("LaunchTemplate","AWS::EC2::LaunchTemplate",{LaunchTemplateName:e.sub("${AWS::StackName}-template"),LaunchTemplateData:{ImageId:n.ami||e.findInMap("RegionMap",e.ref("AWS::Region"),"AMI"),InstanceType:n.instanceType,IamInstanceProfile:{Arn:e.getAtt("EC2InstanceProfile","Arn")},SecurityGroupIds:[e.ref("AppSecurityGroup")],UserData:e.base64(e.sub(i)),TagSpecifications:[{ResourceType:"instance",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-instance")}]}],MetadataOptions:{HttpTokens:"required",HttpPutResponseHopLimit:1}}},{dependsOn:["AppSecurityGroup","EC2InstanceProfile"]}),n.loadBalancer){Vr(a,n.loadBalancer);let s={LaunchTemplate:{LaunchTemplateId:e.ref("LaunchTemplate"),Version:e.getAtt("LaunchTemplate","LatestVersionNumber")},MinSize:n.autoScaling?.min.toString()||"1",MaxSize:n.autoScaling?.max.toString()||"3",DesiredCapacity:n.autoScaling?.min.toString()||"2",VPCZoneIdentifier:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],TargetGroupARNs:[e.ref("TargetGroup")],HealthCheckType:"ELB",HealthCheckGracePeriod:300,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-asg"),PropagateAtLaunch:!0}]};if(a.addResource("AutoScalingGroup","AWS::AutoScaling::AutoScalingGroup",s,{dependsOn:["LaunchTemplate","TargetGroup"]}),n.autoScaling)a.addResource("ScaleUpPolicy","AWS::AutoScaling::ScalingPolicy",{AdjustmentType:"ChangeInCapacity",AutoScalingGroupName:e.ref("AutoScalingGroup"),Cooldown:n.autoScaling.scaleUpCooldown?.toString()||"300",ScalingAdjustment:"1"},{dependsOn:"AutoScalingGroup"}),a.addResource("ScaleDownPolicy","AWS::AutoScaling::ScalingPolicy",{AdjustmentType:"ChangeInCapacity",AutoScalingGroupName:e.ref("AutoScalingGroup"),Cooldown:n.autoScaling.scaleDownCooldown?.toString()||"300",ScalingAdjustment:"-1"},{dependsOn:"AutoScalingGroup"}),a.addResource("HighCPUAlarm","AWS::CloudWatch::Alarm",{AlarmDescription:"Scale up when CPU exceeds target",MetricName:"CPUUtilization",Namespace:"AWS/EC2",Statistic:"Average",Period:"300",EvaluationPeriods:"2",Threshold:(n.autoScaling.targetCPU||70).toString(),AlarmActions:[e.ref("ScaleUpPolicy")],Dimensions:[{Name:"AutoScalingGroupName",Value:e.ref("AutoScalingGroup")}],ComparisonOperator:"GreaterThanThreshold"},{dependsOn:["AutoScalingGroup","ScaleUpPolicy"]}),a.addResource("LowCPUAlarm","AWS::CloudWatch::Alarm",{AlarmDescription:"Scale down when CPU is below threshold",MetricName:"CPUUtilization",Namespace:"AWS/EC2",Statistic:"Average",Period:"300",EvaluationPeriods:"2",Threshold:((n.autoScaling.targetCPU||70)-20).toString(),AlarmActions:[e.ref("ScaleDownPolicy")],Dimensions:[{Name:"AutoScalingGroupName",Value:e.ref("AutoScalingGroup")}],ComparisonOperator:"LessThanThreshold"},{dependsOn:["AutoScalingGroup","ScaleDownPolicy"]})}}function Vr(a,n){if(!n)return;a.addResource("ALBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for Application Load Balancer",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:80,ToPort:80,CidrIp:"0.0.0.0/0"},{IpProtocol:"tcp",FromPort:443,ToPort:443,CidrIp:"0.0.0.0/0"}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-alb-sg")}]},{dependsOn:"VPC"}),a.addResource("LoadBalancer","AWS::ElasticLoadBalancingV2::LoadBalancer",{Name:e.sub("${AWS::StackName}-alb"),Type:n.type||"application",Scheme:"internet-facing",IpAddressType:"ipv4",Subnets:[e.ref("PublicSubnet1"),e.ref("PublicSubnet2")],SecurityGroups:[e.ref("ALBSecurityGroup")],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-alb")}]},{dependsOn:["PublicSubnet1","PublicSubnet2","ALBSecurityGroup"]}),a.addResource("TargetGroup","AWS::ElasticLoadBalancingV2::TargetGroup",{Name:e.sub("${AWS::StackName}-tg"),Port:3000,Protocol:"HTTP",VpcId:e.ref("VPC"),HealthCheckEnabled:!0,HealthCheckPath:n.healthCheck?.path||"/health",HealthCheckProtocol:"HTTP",HealthCheckIntervalSeconds:n.healthCheck?.interval||30,HealthCheckTimeoutSeconds:n.healthCheck?.timeout||5,HealthyThresholdCount:n.healthCheck?.healthyThreshold||2,UnhealthyThresholdCount:n.healthCheck?.unhealthyThreshold||3,TargetType:"instance",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-tg")}]},{dependsOn:"VPC"}),a.addResource("LoadBalancerListener","AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:e.ref("LoadBalancer"),Port:80,Protocol:"HTTP",DefaultActions:[{Type:"forward",TargetGroupArn:e.ref("TargetGroup")}]},{dependsOn:["LoadBalancer","TargetGroup"]}),a.addOutputs({LoadBalancerDNS:{Description:"Load Balancer DNS Name",Value:e.getAtt("LoadBalancer","DNSName"),Export:{Name:e.sub("${AWS::StackName}-alb-dns")}}})}function oa(a,n,i){let s=a.toLogicalId(n),c=i.taskDefinition.containerDefinitions?.[0],l=c?.name||c?.Name||n,u=c?.portMappings?.[0]?.containerPort||c?.PortMappings?.[0]?.ContainerPort||3000,h=(i.taskDefinition.containerDefinitions||[]).flatMap((C)=>(C.secrets||C.Secrets||[]).map((T)=>T.valueFrom||T.ValueFrom)).filter(Boolean);if(!a.hasResource("ECSCluster"))a.addResource("ECSCluster","AWS::ECS::Cluster",{ClusterName:e.sub("${AWS::StackName}-cluster"),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cluster")}]});if(a.addResource(`${s}TaskExecutionRole`,"AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"],...h.length?{Policies:[{PolicyName:"read-task-secrets",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameters"],Resource:h},{Effect:"Allow",Action:"kms:Decrypt",Resource:"*"}]}}]}:{}}),a.addResource(`${s}TaskRole`,"AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"application-services",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes","sqs:SendMessage"],Resource:e.sub("arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:${AWS::StackName}-*")},{Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail"],Resource:"*"}]}}]}),!a.hasResource("ALBSecurityGroup"))a.addResource("ALBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Public ingress for the application load balancer",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:80,ToPort:80,CidrIp:"0.0.0.0/0"},...i.loadBalancer?.customDomain?.certificateArn?[{IpProtocol:"tcp",FromPort:443,ToPort:443,CidrIp:"0.0.0.0/0"}]:[]],SecurityGroupEgress:[{IpProtocol:"tcp",FromPort:u,ToPort:u,CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-alb-sg")}]},{dependsOn:"VPC"});if(!a.hasResource("AppSecurityGroup"))a.addResource("AppSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Only the application load balancer may reach Fargate tasks",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:u,ToPort:u,SourceSecurityGroupId:e.ref("ALBSecurityGroup")}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-app-sg")}]},{dependsOn:["VPC","ALBSecurityGroup"]});let y=(i.taskDefinition.containerDefinitions||[{name:n,image:e.sub(`\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.amazonaws.com/${n}:latest`),portMappings:[{containerPort:3000}]}]).map((C)=>({Name:C.Name||C.name,Image:C.Image||C.image,Essential:C.Essential??C.essential??!0,PortMappings:(C.PortMappings||C.portMappings||[]).map((T)=>({ContainerPort:T.ContainerPort??T.containerPort,Protocol:T.Protocol||T.protocol||"tcp"})),Environment:Array.isArray(C.Environment||C.environment)?(C.Environment||C.environment).map((T)=>({Name:T.Name||T.name,Value:T.Value??T.value})):Object.entries(C.Environment||C.environment||{}).map(([T,v])=>({Name:T,Value:v})),Secrets:(C.Secrets||C.secrets||[]).map((T)=>({Name:T.Name||T.name,ValueFrom:T.ValueFrom||T.valueFrom})),HealthCheck:C.HealthCheck||C.healthCheck,Command:C.Command||C.command,EntryPoint:C.EntryPoint||C.entryPoint,LogConfiguration:C.LogConfiguration||C.logConfiguration||{LogDriver:"awslogs",Options:{"awslogs-group":e.ref(`${s}LogGroup`),"awslogs-region":e.ref("AWS::Region"),"awslogs-stream-prefix":n}}}));a.addResource(`${s}TaskDefinition`,"AWS::ECS::TaskDefinition",{Family:e.sub(`\${AWS::StackName}-${n}`),NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:i.taskDefinition.cpu,Memory:i.taskDefinition.memory,ExecutionRoleArn:e.getAtt(`${s}TaskExecutionRole`,"Arn"),TaskRoleArn:e.getAtt(`${s}TaskRole`,"Arn"),ContainerDefinitions:y},{dependsOn:[`${s}TaskExecutionRole`,`${s}TaskRole`,`${s}LogGroup`]}),a.addResource(`${s}LogGroup`,"AWS::Logs::LogGroup",{LogGroupName:e.sub(`/ecs/\${AWS::StackName}/${n}`),RetentionInDays:14});let S=i.service.healthCheck||{};a.addResource(`${s}TargetGroup`,"AWS::ElasticLoadBalancingV2::TargetGroup",{VpcId:e.ref("VPC"),Port:u,Protocol:"HTTP",TargetType:"ip",HealthCheckEnabled:!0,HealthCheckPath:S.path||"/health",HealthCheckProtocol:"HTTP",HealthCheckIntervalSeconds:S.interval||30,HealthCheckTimeoutSeconds:S.timeout||5,HealthyThresholdCount:S.healthyThreshold||2,UnhealthyThresholdCount:S.unhealthyThreshold||3,Matcher:{HttpCode:"200-399"},TargetGroupAttributes:[{Key:"deregistration_delay.timeout_seconds",Value:"30"}]},{dependsOn:"VPC"}),a.addResource(`${s}LoadBalancer`,"AWS::ElasticLoadBalancingV2::LoadBalancer",{Type:"application",Scheme:"internet-facing",IpAddressType:"ipv4",Subnets:[e.ref("PublicSubnet1"),e.ref("PublicSubnet2")],SecurityGroups:[e.ref("ALBSecurityGroup")],LoadBalancerAttributes:[{Key:"routing.http.drop_invalid_header_fields.enabled",Value:"true"},{Key:"deletion_protection.enabled",Value:String(i.loadBalancer?.deletionProtection===!0)}],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}-alb`)}]},{dependsOn:["PublicSubnet1","PublicSubnet2","ALBSecurityGroup"]});let b=i.loadBalancer?.customDomain?.certificateArn,A=i.loadBalancer?.originVerifyHeader;if(a.addResource(`${s}HttpListener`,"AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:e.ref(`${s}LoadBalancer`),Port:80,Protocol:"HTTP",DefaultActions:b?[{Type:"redirect",RedirectConfig:{Protocol:"HTTPS",Port:"443",StatusCode:"HTTP_301"}}]:A?[{Type:"fixed-response",FixedResponseConfig:{StatusCode:"403",ContentType:"text/plain",MessageBody:"Forbidden"}}]:[{Type:"forward",TargetGroupArn:e.ref(`${s}TargetGroup`)}]},{dependsOn:[`${s}LoadBalancer`,`${s}TargetGroup`]}),b)a.addResource(`${s}HttpsListener`,"AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:e.ref(`${s}LoadBalancer`),Port:443,Protocol:"HTTPS",Certificates:[{CertificateArn:b}],SslPolicy:"ELBSecurityPolicy-TLS13-1-2-2021-06",DefaultActions:A?[{Type:"fixed-response",FixedResponseConfig:{StatusCode:"403",ContentType:"text/plain",MessageBody:"Forbidden"}}]:[{Type:"forward",TargetGroupArn:e.ref(`${s}TargetGroup`)}]},{dependsOn:[`${s}LoadBalancer`,`${s}TargetGroup`]});if(A){let C=b?`${s}HttpsListener`:`${s}HttpListener`;a.addResource(`${s}OriginVerifyRule`,"AWS::ElasticLoadBalancingV2::ListenerRule",{ListenerArn:e.ref(C),Priority:1,Conditions:[{Field:"http-header",HttpHeaderConfig:{HttpHeaderName:A.name,Values:[A.value]}}],Actions:[{Type:"forward",TargetGroupArn:e.ref(`${s}TargetGroup`)}]},{dependsOn:[C,`${s}TargetGroup`]})}if(a.addResource(`${s}Service`,"AWS::ECS::Service",{ServiceName:e.sub(`\${AWS::StackName}-${n}`),Cluster:e.ref("ECSCluster"),TaskDefinition:e.ref(`${s}TaskDefinition`),DesiredCount:i.service.desiredCount,LaunchType:"FARGATE",PlatformVersion:"LATEST",HealthCheckGracePeriodSeconds:60,DeploymentConfiguration:{MinimumHealthyPercent:100,MaximumPercent:200,DeploymentCircuitBreaker:{Enable:!0,Rollback:!0}},LoadBalancers:[{ContainerName:l,ContainerPort:u,TargetGroupArn:e.ref(`${s}TargetGroup`)}],NetworkConfiguration:{AwsvpcConfiguration:{AssignPublicIp:"DISABLED",Subnets:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],SecurityGroups:[e.ref("AppSecurityGroup")]}}},{dependsOn:["ECSCluster",`${s}TaskDefinition`,A?`${s}OriginVerifyRule`:b?`${s}HttpsListener`:`${s}HttpListener`]}),i.service.autoScaling){let C=i.service.autoScaling;a.addResource(`${s}ScalableTarget`,"AWS::ApplicationAutoScaling::ScalableTarget",{MinCapacity:C.min,MaxCapacity:C.max,ResourceId:e.join("/",["service",e.ref("ECSCluster"),e.getAtt(`${s}Service`,"Name")]),RoleARN:e.sub("arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService"),ScalableDimension:"ecs:service:DesiredCount",ServiceNamespace:"ecs"},{dependsOn:`${s}Service`}),a.addResource(`${s}ScalingPolicy`,"AWS::ApplicationAutoScaling::ScalingPolicy",{PolicyType:"TargetTrackingScaling",ScalingTargetId:e.ref(`${s}ScalableTarget`),TargetTrackingScalingPolicyConfiguration:{TargetValue:C.targetCPU||70,PredefinedMetricSpecification:{PredefinedMetricType:"ECSServiceAverageCPUUtilization"},ScaleInCooldown:60,ScaleOutCooldown:30}},{dependsOn:`${s}ScalableTarget`})}a.addOutputs({[`${s}ClusterName`]:{Description:"ECS cluster name",Value:e.ref("ECSCluster")},[`${s}ServiceName`]:{Description:"ECS service name",Value:e.getAtt(`${s}Service`,"Name")},[`${s}LoadBalancerDnsName`]:{Description:"ALB origin hostname",Value:e.getAtt(`${s}LoadBalancer`,"DNSName")},[`${s}LoadBalancerHostedZoneId`]:{Description:"ALB canonical hosted zone ID",Value:e.getAtt(`${s}LoadBalancer`,"CanonicalHostedZoneID")},[`${s}TargetGroupArn`]:{Description:"ECS target group ARN",Value:e.ref(`${s}TargetGroup`)}})}function jr(a,n){if(n.postgres)ca(a,"postgres",n.postgres);if(n.mysql)ca(a,"mysql",n.mysql);if(n.dynamodb?.tables)n.dynamodb.tables.forEach((i)=>{Kr(a,i)})}function ca(a,n,i){if(!i)return;let s=n==="postgres"?"postgres":"mysql",c=a.toLogicalId(`${s}-db`);a.addResource("DBSubnetGroup","AWS::RDS::DBSubnetGroup",{DBSubnetGroupDescription:"Subnet group for RDS instance",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-db-subnet-group")}]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]}),a.addResource("DBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for RDS instance",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:n==="postgres"?5432:3306,ToPort:n==="postgres"?5432:3306,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-db-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});let l=n==="postgres"?`postgres${i.version.split(".")[0]}`:`mysql${i.version.split(".")[0]}.${i.version.split(".")[1]||"0"}`;if(i.parameters&&Object.keys(i.parameters).length>0)a.addResource("DBParameterGroup","AWS::RDS::DBParameterGroup",{Description:`Parameter group for ${s}`,Family:l,Parameters:i.parameters,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-db-params")}]});a.addResource("DBSecret","AWS::SecretsManager::Secret",{Description:"Database credentials",GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"admin"}),GenerateStringKey:"password",PasswordLength:32,ExcludeCharacters:'"@/\\'},Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-db-secret")}]},{deletionPolicy:"Retain",updateReplacePolicy:"Retain"});let u={Engine:s,EngineVersion:i.version,DBInstanceClass:i.instanceClass,AllocatedStorage:i.allocatedStorage.toString(),MaxAllocatedStorage:i.maxAllocatedStorage?.toString(),StorageType:"gp3",StorageEncrypted:!0,MultiAZ:i.multiAZ!==!1,DBSubnetGroupName:e.ref("DBSubnetGroup"),VPCSecurityGroups:[e.ref("DBSecurityGroup")],MasterUsername:e.sub("{{resolve:secretsmanager:${DBSecret}:SecretString:username}}"),MasterUserPassword:e.sub("{{resolve:secretsmanager:${DBSecret}:SecretString:password}}"),BackupRetentionPeriod:i.backupRetentionDays||7,PreferredBackupWindow:i.preferredBackupWindow||"03:00-04:00",PreferredMaintenanceWindow:i.preferredMaintenanceWindow||"sun:04:00-sun:05:00",EnablePerformanceInsights:i.enablePerformanceInsights!==!1,PerformanceInsightsRetentionPeriod:i.performanceInsightsRetention||7,DeletionProtection:i.deletionProtection!==!1,CopyTagsToSnapshot:!0,EnableCloudwatchLogsExports:n==="postgres"?["postgresql"]:["error","general","slowquery"],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${s}-db`)}]};if(i.parameters&&Object.keys(i.parameters).length>0)u.DBParameterGroupName=e.ref("DBParameterGroup");a.addResource(c,"AWS::RDS::DBInstance",u,{dependsOn:["DBSubnetGroup","DBSecurityGroup","DBSecret"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),a.addResource("DBSecretAttachment","AWS::SecretsManager::SecretTargetAttachment",{SecretId:e.ref("DBSecret"),TargetId:e.ref(c),TargetType:"AWS::RDS::DBInstance"},{dependsOn:[c,"DBSecret"]}),a.addOutputs({DBEndpoint:{Description:"Database endpoint",Value:e.getAtt(c,"Endpoint.Address"),Export:{Name:e.sub("${AWS::StackName}-db-endpoint")}},DBPort:{Description:"Database port",Value:e.getAtt(c,"Endpoint.Port"),Export:{Name:e.sub("${AWS::StackName}-db-port")}},DBSecretArn:{Description:"ARN of the database credentials secret",Value:e.ref("DBSecret"),Export:{Name:e.sub("${AWS::StackName}-db-secret-arn")}}})}function Kr(a,n){let i=a.toLogicalId(`${n.name}-table`),s={TableName:e.sub(`\${AWS::StackName}-${n.name}`),BillingMode:n.billingMode||"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:n.partitionKey,AttributeType:"S"}],KeySchema:[{AttributeName:n.partitionKey,KeyType:"HASH"}],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n.name}`)}]};if(n.sortKey)s.AttributeDefinitions.push({AttributeName:n.sortKey,AttributeType:"S"}),s.KeySchema.push({AttributeName:n.sortKey,KeyType:"RANGE"});if(n.billingMode==="PROVISIONED")s.ProvisionedThroughput={ReadCapacityUnits:n.readCapacity||5,WriteCapacityUnits:n.writeCapacity||5};if(n.streamEnabled)s.StreamSpecification={StreamViewType:"NEW_AND_OLD_IMAGES"};if(n.pointInTimeRecovery)s.PointInTimeRecoverySpecification={PointInTimeRecoveryEnabled:!0};if(n.ttl?.enabled)s.TimeToLiveSpecification={Enabled:!0,AttributeName:n.ttl.attributeName};if(n.globalSecondaryIndexes&&n.globalSecondaryIndexes.length>0)s.GlobalSecondaryIndexes=n.globalSecondaryIndexes.map((c)=>{let l=new Set(s.AttributeDefinitions.map((h)=>h.AttributeName));if(!l.has(c.partitionKey))s.AttributeDefinitions.push({AttributeName:c.partitionKey,AttributeType:"S"});if(c.sortKey&&!l.has(c.sortKey))s.AttributeDefinitions.push({AttributeName:c.sortKey,AttributeType:"S"});let u={IndexName:c.name,KeySchema:[{AttributeName:c.partitionKey,KeyType:"HASH"}],Projection:{ProjectionType:c.projectionType||"ALL"}};if(c.sortKey)u.KeySchema.push({AttributeName:c.sortKey,KeyType:"RANGE"});if(c.projectionType==="INCLUDE"&&c.nonKeyAttributes)u.Projection.NonKeyAttributes=c.nonKeyAttributes;if(n.billingMode==="PROVISIONED")u.ProvisionedThroughput={ReadCapacityUnits:n.readCapacity||5,WriteCapacityUnits:n.writeCapacity||5};return u});if(a.addResource(i,"AWS::DynamoDB::Table",s,{deletionPolicy:"Retain"}),a.addOutputs({[`${i}Name`]:{Description:`${n.name} table name`,Value:e.ref(i),Export:{Name:e.sub(`\${AWS::StackName}-${n.name}-table`)}},[`${i}Arn`]:{Description:`${n.name} table ARN`,Value:e.getAtt(i,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${n.name}-table-arn`)}}}),n.streamEnabled)a.addOutputs({[`${i}StreamArn`]:{Description:`${n.name} stream ARN`,Value:e.getAtt(i,"StreamArn"),Export:{Name:e.sub(`\${AWS::StackName}-${n.name}-stream-arn`)}}})}function Hr(a,n){for(let[i,s]of Object.entries(n))s.forEach((c)=>{qr(a,c,i)})}function qr(a,n,i){let s=a.toLogicalId(`${i}-${n.name}-function`),c=`${s}Role`;a.addResource(c,"AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole","arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"],Policies:[{PolicyName:"LambdaExecutionPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[...Qr(n.events||[])]}}],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n.name}-role`)}]});let l={FunctionName:e.sub(`\${AWS::StackName}-${n.name}`),Runtime:n.runtime,Handler:n.handler,Role:e.getAtt(c,"Arn"),MemorySize:n.memory,Timeout:n.timeout,Code:{ZipFile:`exports.handler = async (event) => {
2483
+ `;if(a.addResource("LaunchTemplate","AWS::EC2::LaunchTemplate",{LaunchTemplateName:e.sub("${AWS::StackName}-template"),LaunchTemplateData:{ImageId:n.ami||e.findInMap("RegionMap",e.ref("AWS::Region"),"AMI"),InstanceType:n.instanceType,IamInstanceProfile:{Arn:e.getAtt("EC2InstanceProfile","Arn")},SecurityGroupIds:[e.ref("AppSecurityGroup")],UserData:e.base64(e.sub(i)),TagSpecifications:[{ResourceType:"instance",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-instance")}]}],MetadataOptions:{HttpTokens:"required",HttpPutResponseHopLimit:1}}},{dependsOn:["AppSecurityGroup","EC2InstanceProfile"]}),n.loadBalancer){Vr(a,n.loadBalancer);let s={LaunchTemplate:{LaunchTemplateId:e.ref("LaunchTemplate"),Version:e.getAtt("LaunchTemplate","LatestVersionNumber")},MinSize:n.autoScaling?.min.toString()||"1",MaxSize:n.autoScaling?.max.toString()||"3",DesiredCapacity:n.autoScaling?.min.toString()||"2",VPCZoneIdentifier:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],TargetGroupARNs:[e.ref("TargetGroup")],HealthCheckType:"ELB",HealthCheckGracePeriod:300,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-asg"),PropagateAtLaunch:!0}]};if(a.addResource("AutoScalingGroup","AWS::AutoScaling::AutoScalingGroup",s,{dependsOn:["LaunchTemplate","TargetGroup"]}),n.autoScaling)a.addResource("ScaleUpPolicy","AWS::AutoScaling::ScalingPolicy",{AdjustmentType:"ChangeInCapacity",AutoScalingGroupName:e.ref("AutoScalingGroup"),Cooldown:n.autoScaling.scaleUpCooldown?.toString()||"300",ScalingAdjustment:"1"},{dependsOn:"AutoScalingGroup"}),a.addResource("ScaleDownPolicy","AWS::AutoScaling::ScalingPolicy",{AdjustmentType:"ChangeInCapacity",AutoScalingGroupName:e.ref("AutoScalingGroup"),Cooldown:n.autoScaling.scaleDownCooldown?.toString()||"300",ScalingAdjustment:"-1"},{dependsOn:"AutoScalingGroup"}),a.addResource("HighCPUAlarm","AWS::CloudWatch::Alarm",{AlarmDescription:"Scale up when CPU exceeds target",MetricName:"CPUUtilization",Namespace:"AWS/EC2",Statistic:"Average",Period:"300",EvaluationPeriods:"2",Threshold:(n.autoScaling.targetCPU||70).toString(),AlarmActions:[e.ref("ScaleUpPolicy")],Dimensions:[{Name:"AutoScalingGroupName",Value:e.ref("AutoScalingGroup")}],ComparisonOperator:"GreaterThanThreshold"},{dependsOn:["AutoScalingGroup","ScaleUpPolicy"]}),a.addResource("LowCPUAlarm","AWS::CloudWatch::Alarm",{AlarmDescription:"Scale down when CPU is below threshold",MetricName:"CPUUtilization",Namespace:"AWS/EC2",Statistic:"Average",Period:"300",EvaluationPeriods:"2",Threshold:((n.autoScaling.targetCPU||70)-20).toString(),AlarmActions:[e.ref("ScaleDownPolicy")],Dimensions:[{Name:"AutoScalingGroupName",Value:e.ref("AutoScalingGroup")}],ComparisonOperator:"LessThanThreshold"},{dependsOn:["AutoScalingGroup","ScaleDownPolicy"]})}}function Vr(a,n){if(!n)return;a.addResource("ALBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for Application Load Balancer",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:80,ToPort:80,CidrIp:"0.0.0.0/0"},{IpProtocol:"tcp",FromPort:443,ToPort:443,CidrIp:"0.0.0.0/0"}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-alb-sg")}]},{dependsOn:"VPC"}),a.addResource("LoadBalancer","AWS::ElasticLoadBalancingV2::LoadBalancer",{Name:e.sub("${AWS::StackName}-alb"),Type:n.type||"application",Scheme:"internet-facing",IpAddressType:"ipv4",Subnets:[e.ref("PublicSubnet1"),e.ref("PublicSubnet2")],SecurityGroups:[e.ref("ALBSecurityGroup")],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-alb")}]},{dependsOn:["PublicSubnet1","PublicSubnet2","ALBSecurityGroup"]}),a.addResource("TargetGroup","AWS::ElasticLoadBalancingV2::TargetGroup",{Name:e.sub("${AWS::StackName}-tg"),Port:3000,Protocol:"HTTP",VpcId:e.ref("VPC"),HealthCheckEnabled:!0,HealthCheckPath:n.healthCheck?.path||"/health",HealthCheckProtocol:"HTTP",HealthCheckIntervalSeconds:n.healthCheck?.interval||30,HealthCheckTimeoutSeconds:n.healthCheck?.timeout||5,HealthyThresholdCount:n.healthCheck?.healthyThreshold||2,UnhealthyThresholdCount:n.healthCheck?.unhealthyThreshold||3,TargetType:"instance",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-tg")}]},{dependsOn:"VPC"}),a.addResource("LoadBalancerListener","AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:e.ref("LoadBalancer"),Port:80,Protocol:"HTTP",DefaultActions:[{Type:"forward",TargetGroupArn:e.ref("TargetGroup")}]},{dependsOn:["LoadBalancer","TargetGroup"]}),a.addOutputs({LoadBalancerDNS:{Description:"Load Balancer DNS Name",Value:e.getAtt("LoadBalancer","DNSName"),Export:{Name:e.sub("${AWS::StackName}-alb-dns")}}})}function oa(a,n,i){let s=a.toLogicalId(n),c=i.taskDefinition.containerDefinitions?.[0],l=c?.name||c?.Name||n,u=c?.portMappings?.[0]?.containerPort||c?.PortMappings?.[0]?.ContainerPort||3000,h=(i.taskDefinition.containerDefinitions||[]).flatMap((T)=>(T.secrets||T.Secrets||[]).map((v)=>v.valueFrom||v.ValueFrom)).filter(Boolean);if(!a.hasResource("ECSCluster"))a.addResource("ECSCluster","AWS::ECS::Cluster",{ClusterName:e.sub("${AWS::StackName}-cluster"),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cluster")}]});if(a.addResource(`${s}TaskExecutionRole`,"AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"],...h.length?{Policies:[{PolicyName:"read-task-secrets",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameters"],Resource:h},{Effect:"Allow",Action:"kms:Decrypt",Resource:"*"}]}}]}:{}}),a.addResource(`${s}TaskRole`,"AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"application-services",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes","sqs:SendMessage"],Resource:e.sub("arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:${AWS::StackName}-*")},{Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail"],Resource:"*"}]}}]}),!a.hasResource("ALBSecurityGroup"))a.addResource("ALBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Public ingress for the application load balancer",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:80,ToPort:80,CidrIp:"0.0.0.0/0"},...i.loadBalancer?.customDomain?.certificateArn?[{IpProtocol:"tcp",FromPort:443,ToPort:443,CidrIp:"0.0.0.0/0"}]:[]],SecurityGroupEgress:[{IpProtocol:"tcp",FromPort:u,ToPort:u,CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-alb-sg")}]},{dependsOn:"VPC"});if(!a.hasResource("AppSecurityGroup"))a.addResource("AppSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Only the application load balancer may reach Fargate tasks",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:u,ToPort:u,SourceSecurityGroupId:e.ref("ALBSecurityGroup")}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-app-sg")}]},{dependsOn:["VPC","ALBSecurityGroup"]});let y=(i.taskDefinition.containerDefinitions||[{name:n,image:e.sub(`\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.amazonaws.com/${n}:latest`),portMappings:[{containerPort:3000}]}]).map((T)=>({Name:T.Name||T.name,Image:T.Image||T.image,Essential:T.Essential??T.essential??!0,PortMappings:(T.PortMappings||T.portMappings||[]).map((v)=>({ContainerPort:v.ContainerPort??v.containerPort,Protocol:v.Protocol||v.protocol||"tcp"})),Environment:Array.isArray(T.Environment||T.environment)?(T.Environment||T.environment).map((v)=>({Name:v.Name||v.name,Value:v.Value??v.value})):Object.entries(T.Environment||T.environment||{}).map(([v,w])=>({Name:v,Value:w})),Secrets:(T.Secrets||T.secrets||[]).map((v)=>({Name:v.Name||v.name,ValueFrom:v.ValueFrom||v.valueFrom})),HealthCheck:T.HealthCheck||T.healthCheck,Command:T.Command||T.command,EntryPoint:T.EntryPoint||T.entryPoint,LogConfiguration:T.LogConfiguration||T.logConfiguration||{LogDriver:"awslogs",Options:{"awslogs-group":e.ref(`${s}LogGroup`),"awslogs-region":e.ref("AWS::Region"),"awslogs-stream-prefix":n}}}));a.addResource(`${s}TaskDefinition`,"AWS::ECS::TaskDefinition",{Family:e.sub(`\${AWS::StackName}-${n}`),NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:i.taskDefinition.cpu,Memory:i.taskDefinition.memory,ExecutionRoleArn:e.getAtt(`${s}TaskExecutionRole`,"Arn"),TaskRoleArn:e.getAtt(`${s}TaskRole`,"Arn"),ContainerDefinitions:y},{dependsOn:[`${s}TaskExecutionRole`,`${s}TaskRole`,`${s}LogGroup`]}),a.addResource(`${s}LogGroup`,"AWS::Logs::LogGroup",{LogGroupName:e.sub(`/ecs/\${AWS::StackName}/${n}`),RetentionInDays:14});let S=i.service.healthCheck||{};a.addResource(`${s}TargetGroup`,"AWS::ElasticLoadBalancingV2::TargetGroup",{VpcId:e.ref("VPC"),Port:u,Protocol:"HTTP",TargetType:"ip",HealthCheckEnabled:!0,HealthCheckPath:S.path||"/health",HealthCheckProtocol:"HTTP",HealthCheckIntervalSeconds:S.interval||30,HealthCheckTimeoutSeconds:S.timeout||5,HealthyThresholdCount:S.healthyThreshold||2,UnhealthyThresholdCount:S.unhealthyThreshold||3,Matcher:{HttpCode:"200-399"},TargetGroupAttributes:[{Key:"deregistration_delay.timeout_seconds",Value:"30"}]},{dependsOn:"VPC"}),a.addResource(`${s}LoadBalancer`,"AWS::ElasticLoadBalancingV2::LoadBalancer",{Type:"application",Scheme:"internet-facing",IpAddressType:"ipv4",Subnets:[e.ref("PublicSubnet1"),e.ref("PublicSubnet2")],SecurityGroups:[e.ref("ALBSecurityGroup")],LoadBalancerAttributes:[{Key:"routing.http.drop_invalid_header_fields.enabled",Value:"true"},{Key:"deletion_protection.enabled",Value:String(i.loadBalancer?.deletionProtection===!0)}],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}-alb`)}]},{dependsOn:["PublicSubnet1","PublicSubnet2","ALBSecurityGroup"]});let A=i.loadBalancer?.customDomain?.certificateArn,C=i.loadBalancer?.originVerifyHeader;if(a.addResource(`${s}HttpListener`,"AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:e.ref(`${s}LoadBalancer`),Port:80,Protocol:"HTTP",DefaultActions:A?[{Type:"redirect",RedirectConfig:{Protocol:"HTTPS",Port:"443",StatusCode:"HTTP_301"}}]:C?[{Type:"fixed-response",FixedResponseConfig:{StatusCode:"403",ContentType:"text/plain",MessageBody:"Forbidden"}}]:[{Type:"forward",TargetGroupArn:e.ref(`${s}TargetGroup`)}]},{dependsOn:[`${s}LoadBalancer`,`${s}TargetGroup`]}),A)a.addResource(`${s}HttpsListener`,"AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:e.ref(`${s}LoadBalancer`),Port:443,Protocol:"HTTPS",Certificates:[{CertificateArn:A}],SslPolicy:"ELBSecurityPolicy-TLS13-1-2-2021-06",DefaultActions:C?[{Type:"fixed-response",FixedResponseConfig:{StatusCode:"403",ContentType:"text/plain",MessageBody:"Forbidden"}}]:[{Type:"forward",TargetGroupArn:e.ref(`${s}TargetGroup`)}]},{dependsOn:[`${s}LoadBalancer`,`${s}TargetGroup`]});if(C){let T=A?`${s}HttpsListener`:`${s}HttpListener`;a.addResource(`${s}OriginVerifyRule`,"AWS::ElasticLoadBalancingV2::ListenerRule",{ListenerArn:e.ref(T),Priority:1,Conditions:[{Field:"http-header",HttpHeaderConfig:{HttpHeaderName:C.name,Values:[C.value]}}],Actions:[{Type:"forward",TargetGroupArn:e.ref(`${s}TargetGroup`)}]},{dependsOn:[T,`${s}TargetGroup`]})}if(a.addResource(`${s}Service`,"AWS::ECS::Service",{ServiceName:e.sub(`\${AWS::StackName}-${n}`),Cluster:e.ref("ECSCluster"),TaskDefinition:e.ref(`${s}TaskDefinition`),DesiredCount:i.service.desiredCount,LaunchType:"FARGATE",PlatformVersion:"LATEST",HealthCheckGracePeriodSeconds:60,DeploymentConfiguration:{MinimumHealthyPercent:100,MaximumPercent:200,DeploymentCircuitBreaker:{Enable:!0,Rollback:!0}},LoadBalancers:[{ContainerName:l,ContainerPort:u,TargetGroupArn:e.ref(`${s}TargetGroup`)}],NetworkConfiguration:{AwsvpcConfiguration:{AssignPublicIp:"DISABLED",Subnets:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],SecurityGroups:[e.ref("AppSecurityGroup")]}}},{dependsOn:["ECSCluster",`${s}TaskDefinition`,C?`${s}OriginVerifyRule`:A?`${s}HttpsListener`:`${s}HttpListener`]}),i.service.autoScaling){let T=i.service.autoScaling;a.addResource(`${s}ScalableTarget`,"AWS::ApplicationAutoScaling::ScalableTarget",{MinCapacity:T.min,MaxCapacity:T.max,ResourceId:e.join("/",["service",e.ref("ECSCluster"),e.getAtt(`${s}Service`,"Name")]),RoleARN:e.sub("arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService"),ScalableDimension:"ecs:service:DesiredCount",ServiceNamespace:"ecs"},{dependsOn:`${s}Service`}),a.addResource(`${s}ScalingPolicy`,"AWS::ApplicationAutoScaling::ScalingPolicy",{PolicyType:"TargetTrackingScaling",ScalingTargetId:e.ref(`${s}ScalableTarget`),TargetTrackingScalingPolicyConfiguration:{TargetValue:T.targetCPU||70,PredefinedMetricSpecification:{PredefinedMetricType:"ECSServiceAverageCPUUtilization"},ScaleInCooldown:60,ScaleOutCooldown:30}},{dependsOn:`${s}ScalableTarget`})}a.addOutputs({[`${s}ClusterName`]:{Description:"ECS cluster name",Value:e.ref("ECSCluster")},[`${s}ServiceName`]:{Description:"ECS service name",Value:e.getAtt(`${s}Service`,"Name")},[`${s}LoadBalancerDnsName`]:{Description:"ALB origin hostname",Value:e.getAtt(`${s}LoadBalancer`,"DNSName")},[`${s}LoadBalancerHostedZoneId`]:{Description:"ALB canonical hosted zone ID",Value:e.getAtt(`${s}LoadBalancer`,"CanonicalHostedZoneID")},[`${s}TargetGroupArn`]:{Description:"ECS target group ARN",Value:e.ref(`${s}TargetGroup`)}})}function jr(a,n){if(n.postgres)ca(a,"postgres",n.postgres);if(n.mysql)ca(a,"mysql",n.mysql);if(n.dynamodb?.tables)n.dynamodb.tables.forEach((i)=>{Kr(a,i)})}function ca(a,n,i){if(!i)return;let s=n==="postgres"?"postgres":"mysql",c=a.toLogicalId(`${s}-db`);a.addResource("DBSubnetGroup","AWS::RDS::DBSubnetGroup",{DBSubnetGroupDescription:"Subnet group for RDS instance",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-db-subnet-group")}]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]}),a.addResource("DBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for RDS instance",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:n==="postgres"?5432:3306,ToPort:n==="postgres"?5432:3306,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-db-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});let l=n==="postgres"?`postgres${i.version.split(".")[0]}`:`mysql${i.version.split(".")[0]}.${i.version.split(".")[1]||"0"}`;if(i.parameters&&Object.keys(i.parameters).length>0)a.addResource("DBParameterGroup","AWS::RDS::DBParameterGroup",{Description:`Parameter group for ${s}`,Family:l,Parameters:i.parameters,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-db-params")}]});a.addResource("DBSecret","AWS::SecretsManager::Secret",{Description:"Database credentials",GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"admin"}),GenerateStringKey:"password",PasswordLength:32,ExcludeCharacters:'"@/\\'},Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-db-secret")}]},{deletionPolicy:"Retain",updateReplacePolicy:"Retain"});let u={Engine:s,EngineVersion:i.version,DBInstanceClass:i.instanceClass,AllocatedStorage:i.allocatedStorage.toString(),MaxAllocatedStorage:i.maxAllocatedStorage?.toString(),StorageType:"gp3",StorageEncrypted:!0,MultiAZ:i.multiAZ!==!1,DBSubnetGroupName:e.ref("DBSubnetGroup"),VPCSecurityGroups:[e.ref("DBSecurityGroup")],MasterUsername:e.sub("{{resolve:secretsmanager:${DBSecret}:SecretString:username}}"),MasterUserPassword:e.sub("{{resolve:secretsmanager:${DBSecret}:SecretString:password}}"),BackupRetentionPeriod:i.backupRetentionDays||7,PreferredBackupWindow:i.preferredBackupWindow||"03:00-04:00",PreferredMaintenanceWindow:i.preferredMaintenanceWindow||"sun:04:00-sun:05:00",EnablePerformanceInsights:i.enablePerformanceInsights!==!1,PerformanceInsightsRetentionPeriod:i.performanceInsightsRetention||7,DeletionProtection:i.deletionProtection!==!1,CopyTagsToSnapshot:!0,EnableCloudwatchLogsExports:n==="postgres"?["postgresql"]:["error","general","slowquery"],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${s}-db`)}]};if(i.parameters&&Object.keys(i.parameters).length>0)u.DBParameterGroupName=e.ref("DBParameterGroup");a.addResource(c,"AWS::RDS::DBInstance",u,{dependsOn:["DBSubnetGroup","DBSecurityGroup","DBSecret"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),a.addResource("DBSecretAttachment","AWS::SecretsManager::SecretTargetAttachment",{SecretId:e.ref("DBSecret"),TargetId:e.ref(c),TargetType:"AWS::RDS::DBInstance"},{dependsOn:[c,"DBSecret"]}),a.addOutputs({DBEndpoint:{Description:"Database endpoint",Value:e.getAtt(c,"Endpoint.Address"),Export:{Name:e.sub("${AWS::StackName}-db-endpoint")}},DBPort:{Description:"Database port",Value:e.getAtt(c,"Endpoint.Port"),Export:{Name:e.sub("${AWS::StackName}-db-port")}},DBSecretArn:{Description:"ARN of the database credentials secret",Value:e.ref("DBSecret"),Export:{Name:e.sub("${AWS::StackName}-db-secret-arn")}}})}function Kr(a,n){let i=a.toLogicalId(`${n.name}-table`),s={TableName:e.sub(`\${AWS::StackName}-${n.name}`),BillingMode:n.billingMode||"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:n.partitionKey,AttributeType:"S"}],KeySchema:[{AttributeName:n.partitionKey,KeyType:"HASH"}],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n.name}`)}]};if(n.sortKey)s.AttributeDefinitions.push({AttributeName:n.sortKey,AttributeType:"S"}),s.KeySchema.push({AttributeName:n.sortKey,KeyType:"RANGE"});if(n.billingMode==="PROVISIONED")s.ProvisionedThroughput={ReadCapacityUnits:n.readCapacity||5,WriteCapacityUnits:n.writeCapacity||5};if(n.streamEnabled)s.StreamSpecification={StreamViewType:"NEW_AND_OLD_IMAGES"};if(n.pointInTimeRecovery)s.PointInTimeRecoverySpecification={PointInTimeRecoveryEnabled:!0};if(n.ttl?.enabled)s.TimeToLiveSpecification={Enabled:!0,AttributeName:n.ttl.attributeName};if(n.globalSecondaryIndexes&&n.globalSecondaryIndexes.length>0)s.GlobalSecondaryIndexes=n.globalSecondaryIndexes.map((c)=>{let l=new Set(s.AttributeDefinitions.map((h)=>h.AttributeName));if(!l.has(c.partitionKey))s.AttributeDefinitions.push({AttributeName:c.partitionKey,AttributeType:"S"});if(c.sortKey&&!l.has(c.sortKey))s.AttributeDefinitions.push({AttributeName:c.sortKey,AttributeType:"S"});let u={IndexName:c.name,KeySchema:[{AttributeName:c.partitionKey,KeyType:"HASH"}],Projection:{ProjectionType:c.projectionType||"ALL"}};if(c.sortKey)u.KeySchema.push({AttributeName:c.sortKey,KeyType:"RANGE"});if(c.projectionType==="INCLUDE"&&c.nonKeyAttributes)u.Projection.NonKeyAttributes=c.nonKeyAttributes;if(n.billingMode==="PROVISIONED")u.ProvisionedThroughput={ReadCapacityUnits:n.readCapacity||5,WriteCapacityUnits:n.writeCapacity||5};return u});if(a.addResource(i,"AWS::DynamoDB::Table",s,{deletionPolicy:"Retain"}),a.addOutputs({[`${i}Name`]:{Description:`${n.name} table name`,Value:e.ref(i),Export:{Name:e.sub(`\${AWS::StackName}-${n.name}-table`)}},[`${i}Arn`]:{Description:`${n.name} table ARN`,Value:e.getAtt(i,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${n.name}-table-arn`)}}}),n.streamEnabled)a.addOutputs({[`${i}StreamArn`]:{Description:`${n.name} stream ARN`,Value:e.getAtt(i,"StreamArn"),Export:{Name:e.sub(`\${AWS::StackName}-${n.name}-stream-arn`)}}})}function Hr(a,n){for(let[i,s]of Object.entries(n))s.forEach((c)=>{qr(a,c,i)})}function qr(a,n,i){let s=a.toLogicalId(`${i}-${n.name}-function`),c=`${s}Role`;a.addResource(c,"AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole","arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"],Policies:[{PolicyName:"LambdaExecutionPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[...Qr(n.events||[])]}}],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n.name}-role`)}]});let l={FunctionName:e.sub(`\${AWS::StackName}-${n.name}`),Runtime:n.runtime,Handler:n.handler,Role:e.getAtt(c,"Arn"),MemorySize:n.memory,Timeout:n.timeout,Code:{ZipFile:`exports.handler = async (event) => {
2484
2484
  console.log('Event:', JSON.stringify(event, null, 2));
2485
2485
  return { statusCode: 200, body: 'Function not yet implemented' };
2486
2486
  };`},Environment:n.environment?{Variables:n.environment}:void 0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n.name}`)}]};if(i!=="edge")l.VpcConfig={SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],SecurityGroupIds:[e.ref("AppSecurityGroup")]};if(a.addResource(s,"AWS::Lambda::Function",l,{dependsOn:c}),a.addResource(`${s}LogGroup`,"AWS::Logs::LogGroup",{LogGroupName:e.sub(`/aws/lambda/\${AWS::StackName}-${n.name}`),RetentionInDays:14}),n.events)n.events.forEach((u,h)=>{zr(a,s,u,h)});a.addOutputs({[`${s}Arn`]:{Description:`${n.name} function ARN`,Value:e.getAtt(s,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${n.name}-function-arn`)}}})}function zr(a,n,i,s){let c=`${n}EventSource${s}`;switch(i.type){case"http":break;case"s3":if(i.bucket){let l=a.toLogicalId(`${i.bucket}-bucket`);a.addResource(`${c}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(n),Action:"lambda:InvokeFunction",Principal:"s3.amazonaws.com",SourceArn:eo.s3Bucket(e.ref(l))},{dependsOn:[n,l]})}break;case"sqs":if(i.queueName){let l=a.toLogicalId(`${i.queueName}-queue`);a.addResource(c,"AWS::Lambda::EventSourceMapping",{EventSourceArn:e.getAtt(l,"Arn"),FunctionName:e.ref(n),BatchSize:i.batchSize||10},{dependsOn:[n,l]})}break;case"kinesis":if(i.streamName){let l=a.toLogicalId(`${i.streamName}-stream`);a.addResource(c,"AWS::Lambda::EventSourceMapping",{EventSourceArn:e.getAtt(l,"Arn"),FunctionName:e.ref(n),BatchSize:i.batchSize||100,StartingPosition:i.startingPosition||"LATEST",ParallelizationFactor:i.parallelizationFactor||1},{dependsOn:[n,l]})}break;case"dynamodb-stream":if(i.tableName){let l=a.toLogicalId(`${i.tableName}-table`);a.addResource(c,"AWS::Lambda::EventSourceMapping",{EventSourceArn:e.getAtt(l,"StreamArn"),FunctionName:e.ref(n),BatchSize:i.batchSize||100,StartingPosition:i.startingPosition||"LATEST"},{dependsOn:[n,l]})}break;case"schedule":if(i.expression)a.addResource(`${c}Rule`,"AWS::Events::Rule",{ScheduleExpression:i.expression,State:"ENABLED",Targets:[{Arn:e.getAtt(n,"Arn"),Id:`${n}Target`}]},{dependsOn:n}),a.addResource(`${c}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(n),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.getAtt(`${c}Rule`,"Arn")},{dependsOn:[n,`${c}Rule`]});break}}function Qr(a){let n=[];if(!a)return n;if(a.forEach((i)=>{switch(i.type){case"s3":n.push({Effect:"Allow",Action:["s3:GetObject","s3:GetObjectVersion"],Resource:i.bucket?`arn:aws:s3:::${i.bucket}/*`:"arn:aws:s3:::*/*"});break;case"sqs":n.push({Effect:"Allow",Action:["sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes"],Resource:i.queueName?eo.sqs(i.queueName):"arn:aws:sqs:*:*:*"});break;case"kinesis":n.push({Effect:"Allow",Action:["kinesis:GetRecords","kinesis:GetShardIterator","kinesis:DescribeStream","kinesis:ListStreams"],Resource:i.streamName?eo.kinesis(i.streamName):"arn:aws:kinesis:*:*:stream/*"});break;case"dynamodb-stream":n.push({Effect:"Allow",Action:["dynamodb:GetRecords","dynamodb:GetShardIterator","dynamodb:DescribeStream","dynamodb:ListStreams"],Resource:i.tableName?e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${i.tableName}/stream/*`):"arn:aws:dynamodb:*:*:table/*/stream/*"});break}}),n.length===0)n.push({Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:"arn:aws:logs:*:*:*"});return n}function Jr(a,n){if(n.topics)n.topics.forEach((i)=>{Yr(a,i)})}function Yr(a,n){let i=a.toLogicalId(`${n.name}-topic`);if(a.addResource(i,"AWS::SNS::Topic",{TopicName:e.sub(`\${AWS::StackName}-${n.name}`),DisplayName:n.displayName||n.name,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n.name}`)}]}),a.addResource(`${i}Policy`,"AWS::SNS::TopicPolicy",{Topics:[e.ref(i)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["events.amazonaws.com","cloudwatch.amazonaws.com","s3.amazonaws.com"]},Action:"sns:Publish",Resource:e.ref(i)},{Effect:"Allow",Principal:{AWS:e.sub("arn:aws:iam::${AWS::AccountId}:root")},Action:["sns:Subscribe","sns:Publish","sns:Receive"],Resource:e.ref(i)}]}},{dependsOn:i}),n.subscriptions)n.subscriptions.forEach((s,c)=>{let l=`${i}Subscription${c+1}`,u={Protocol:s.protocol,TopicArn:e.ref(i),Endpoint:s.endpoint};if(s.filterPolicy)u.FilterPolicy=s.filterPolicy;if(s.protocol==="sqs"){let h=a.toLogicalId(`${s.endpoint}-queue`);u.Endpoint=e.getAtt(h,"Arn")}if(s.protocol==="lambda"){let h=a.toLogicalId(s.endpoint);u.Endpoint=e.getAtt(h,"Arn"),a.addResource(`${l}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(h),Action:"lambda:InvokeFunction",Principal:"sns.amazonaws.com",SourceArn:e.ref(i)},{dependsOn:[h,i]})}a.addResource(l,"AWS::SNS::Subscription",u,{dependsOn:i})});a.addOutputs({[`${i}Arn`]:{Description:`${n.name} topic ARN`,Value:e.ref(i),Export:{Name:e.sub(`\${AWS::StackName}-${n.name}-topic-arn`)}}})}function Zr(a,n){if(n.alarms&&n.alarms.length>0)a.addResource("AlarmTopic","AWS::SNS::Topic",{TopicName:e.sub("${AWS::StackName}-alarms"),DisplayName:"CloudWatch Alarms",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-alarms")}]}),n.alarms.forEach((i,s)=>{Xr(a,i,s)});if(n.dashboard)en(a,n.dashboard);if(n.logs?.groups)n.logs.groups.forEach((i)=>{tn(a,i,n.logs?.retention)})}function Xr(a,n,i){let s=a.toLogicalId(`alarm-${n.name||n.metric}-${i}`),c={AlarmName:n.name||e.sub(`\${AWS::StackName}-${n.metric}`),AlarmDescription:`Alarm for ${n.metric}`,MetricName:n.metric,Namespace:n.namespace||Lt(n.metric,n.service),Statistic:n.statistic||"Average",Period:n.period||300,EvaluationPeriods:n.evaluationPeriods||1,Threshold:n.threshold,ComparisonOperator:n.comparisonOperator||"GreaterThanThreshold",TreatMissingData:n.treatMissingData||"notBreaching",AlarmActions:[e.ref("AlarmTopic")],OKActions:[e.ref("AlarmTopic")]};if(n.dimensions)c.Dimensions=Object.entries(n.dimensions).map(([l,u])=>({Name:l,Value:u}));else if(n.service)c.Dimensions=an(n.service);a.addResource(s,"AWS::CloudWatch::Alarm",c,{dependsOn:"AlarmTopic"})}function en(a,n){if(!n)return;let i=[],s=0,c=0;n.widgets?.forEach((l)=>{let u=l.width||12,h=l.height||6;if(l.type==="metric"&&l.metrics){let y=l.metrics.map((S)=>{if(typeof S==="string")return[Lt(S),S];else return[Lt(S.metric,S.service),S.metric]});i.push({type:"metric",x:s,y:c,width:u,height:h,properties:{metrics:y,period:300,stat:"Average",region:e.ref("AWS::Region"),title:l.metrics.length>1?"Multiple Metrics":typeof l.metrics[0]==="string"?l.metrics[0]:l.metrics[0].metric}})}else if(l.type==="log"&&l.logGroup)i.push({type:"log",x:s,y:c,width:u,height:h,properties:{query:`SOURCE '${l.logGroup}'
2487
2487
  | fields @timestamp, @message
2488
2488
  | sort @timestamp desc
2489
- | limit 20`,region:e.ref("AWS::Region"),title:`Logs: ${l.logGroup}`}});else if(l.type==="text"&&l.text)i.push({type:"text",x:s,y:c,width:u,height:h,properties:{markdown:l.text}});if(s+=u,s>=24)s=0,c+=h}),a.addResource("CloudWatchDashboard","AWS::CloudWatch::Dashboard",{DashboardName:e.sub(`\${AWS::StackName}-${n.name}`),DashboardBody:JSON.stringify({widgets:i})}),a.addOutputs({DashboardURL:{Description:"CloudWatch Dashboard URL",Value:e.sub("https://console.aws.amazon.com/cloudwatch/home?region=${AWS::Region}#dashboards:name=${CloudWatchDashboard}")}})}function tn(a,n,i){let s=a.toLogicalId(`${n}-log-group`);a.addResource(s,"AWS::Logs::LogGroup",{LogGroupName:e.sub(`/aws/\${AWS::StackName}/${n}`),RetentionInDays:i||14,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}`)}]})}function Lt(a,n){if(n)return{ec2:"AWS/EC2",ecs:"AWS/ECS",lambda:"AWS/Lambda",rds:"AWS/RDS",dynamodb:"AWS/DynamoDB",s3:"AWS/S3",cloudfront:"AWS/CloudFront",alb:"AWS/ApplicationELB",nlb:"AWS/NetworkELB",apigateway:"AWS/ApiGateway",sqs:"AWS/SQS",sns:"AWS/SNS",kinesis:"AWS/Kinesis",elasticache:"AWS/ElastiCache"}[n.toLowerCase()]||"AWS/CloudWatch";let i=a.toLowerCase();if(i.includes("cpu")||i.includes("memory")||i.includes("network"))return"AWS/EC2";if(i.includes("lambda")||i.includes("invocation")||i.includes("duration"))return"AWS/Lambda";if(i.includes("request")||i.includes("latency")||i.includes("target"))return"AWS/ApplicationELB";if(i.includes("database")||i.includes("connection"))return"AWS/RDS";if(i.includes("read")||i.includes("write")||i.includes("consumed"))return"AWS/DynamoDB";return"AWS/CloudWatch"}function an(a){return{ec2:[{Name:"InstanceId",Value:e.ref("EC2Instance")}],ecs:[{Name:"ClusterName",Value:e.ref("ECSCluster")},{Name:"ServiceName",Value:e.getAtt("ECSService","Name")}],lambda:[{Name:"FunctionName",Value:e.ref("LambdaFunction")}],rds:[{Name:"DBInstanceIdentifier",Value:e.ref("Database")}],dynamodb:[{Name:"TableName",Value:e.ref("DynamoDBTable")}],alb:[{Name:"LoadBalancer",Value:e.getAtt("LoadBalancer","LoadBalancerFullName")}],apigateway:[{Name:"ApiName",Value:e.ref("HttpApi")}]}[a.toLowerCase()]||[]}function rn(a,n){if(!n.vpc)return;let{cidr:i="10.0.0.0/16",availabilityZones:s=2,natGateways:c=1,enableDnsHostnames:l=!0,enableDnsSupport:u=!0}=n.vpc;a.addResource("VPC","AWS::EC2::VPC",{CidrBlock:i,EnableDnsHostnames:l,EnableDnsSupport:u,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-vpc")}]}),a.addResource("InternetGateway","AWS::EC2::InternetGateway",{Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-igw")}]}),a.addResource("VPCGatewayAttachment","AWS::EC2::VPCGatewayAttachment",{VpcId:e.ref("VPC"),InternetGatewayId:e.ref("InternetGateway")},{dependsOn:["VPC","InternetGateway"]});let h=[];for(let A=0;A<s;A++){let C=`PublicSubnet${A+1}`;h.push(C),a.addResource(C,"AWS::EC2::Subnet",{VpcId:e.ref("VPC"),CidrBlock:e.select(A,e.cidr(e.getAtt("VPC","CidrBlock"),s*2,8)),AvailabilityZone:e.select(A,e.getAZs()),MapPublicIpOnLaunch:!0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-public-${A+1}`)},{Key:"Type",Value:"public"}]},{dependsOn:"VPC"})}let y=[];for(let A=0;A<s;A++){let C=`PrivateSubnet${A+1}`;y.push(C),a.addResource(C,"AWS::EC2::Subnet",{VpcId:e.ref("VPC"),CidrBlock:e.select(A+s,e.cidr(e.getAtt("VPC","CidrBlock"),s*2,8)),AvailabilityZone:e.select(A,e.getAZs()),MapPublicIpOnLaunch:!1,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-private-${A+1}`)},{Key:"Type",Value:"private"}]},{dependsOn:"VPC"})}let S=[];for(let A=0;A<c;A++){let C=`NatEIP${A+1}`;S.push(C),a.addResource(C,"AWS::EC2::EIP",{Domain:"vpc",Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-nat-eip-${A+1}`)}]},{dependsOn:"VPCGatewayAttachment"})}let b=[];for(let A=0;A<c;A++){let C=`NatGateway${A+1}`;b.push(C);let T=A%s;a.addResource(C,"AWS::EC2::NatGateway",{AllocationId:e.getAtt(S[A],"AllocationId"),SubnetId:e.ref(h[T]),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-nat-${A+1}`)}]},{dependsOn:[S[A],h[T]]})}a.addResource("PublicRouteTable","AWS::EC2::RouteTable",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-public-rt")}]},{dependsOn:"VPC"}),a.addResource("PublicRoute","AWS::EC2::Route",{RouteTableId:e.ref("PublicRouteTable"),DestinationCidrBlock:"0.0.0.0/0",GatewayId:e.ref("InternetGateway")},{dependsOn:["PublicRouteTable","VPCGatewayAttachment"]}),h.forEach((A,C)=>{a.addResource(`PublicSubnetRouteTableAssociation${C+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:e.ref(A),RouteTableId:e.ref("PublicRouteTable")},{dependsOn:[A,"PublicRouteTable"]})}),y.forEach((A,C)=>{let T=`PrivateRouteTable${C+1}`,v=C%c;a.addResource(T,"AWS::EC2::RouteTable",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-private-rt-${C+1}`)}]},{dependsOn:"VPC"}),a.addResource(`PrivateRoute${C+1}`,"AWS::EC2::Route",{RouteTableId:e.ref(T),DestinationCidrBlock:"0.0.0.0/0",NatGatewayId:e.ref(b[v])},{dependsOn:[T,b[v]]}),a.addResource(`PrivateSubnetRouteTableAssociation${C+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:e.ref(A),RouteTableId:e.ref(T)},{dependsOn:[A,T]})}),a.addResource("S3VPCEndpoint","AWS::EC2::VPCEndpoint",{VpcId:e.ref("VPC"),ServiceName:e.sub("com.amazonaws.${AWS::Region}.s3"),VpcEndpointType:"Gateway",RouteTableIds:[e.ref("PublicRouteTable"),...Array.from({length:s},(A,C)=>e.ref(`PrivateRouteTable${C+1}`))]},{dependsOn:"VPC"}),a.addResource("NetworkAcl","AWS::EC2::NetworkAcl",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-nacl")}]},{dependsOn:"VPC"}),a.addResource("NetworkAclEntryInbound","AWS::EC2::NetworkAclEntry",{NetworkAclId:e.ref("NetworkAcl"),RuleNumber:100,Protocol:-1,RuleAction:"allow",CidrBlock:"0.0.0.0/0"},{dependsOn:"NetworkAcl"}),a.addResource("NetworkAclEntryOutbound","AWS::EC2::NetworkAclEntry",{NetworkAclId:e.ref("NetworkAcl"),RuleNumber:100,Protocol:-1,Egress:!0,RuleAction:"allow",CidrBlock:"0.0.0.0/0"},{dependsOn:"NetworkAcl"}),a.addOutputs({VPCId:{Description:"VPC ID",Value:e.ref("VPC"),Export:{Name:e.sub("${AWS::StackName}-VPC")}},PublicSubnets:{Description:"Public subnet IDs",Value:e.join(",",h.map((A)=>e.ref(A))),Export:{Name:e.sub("${AWS::StackName}-PublicSubnets")}},PrivateSubnets:{Description:"Private subnet IDs",Value:e.join(",",y.map((A)=>e.ref(A))),Export:{Name:e.sub("${AWS::StackName}-PrivateSubnets")}}})}function nn(a,n){for(let[i,s]of Object.entries(n))sn(a,i,s)}function sn(a,n,i){let s=a.toLogicalId(`${n}-queue`),c=i.fifo||!1,l;if(i.deadLetterQueue){let h=`${s}DLQ`;a.addResource(h,"AWS::SQS::Queue",{QueueName:c?e.sub(`\${AWS::StackName}-${n}-dlq.fifo`):e.sub(`\${AWS::StackName}-${n}-dlq`),FifoQueue:c,MessageRetentionPeriod:1209600,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}-dlq`)}]},{deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),l=e.getAtt(h,"Arn")}let u={QueueName:c?e.sub(`\${AWS::StackName}-${n}.fifo`):e.sub(`\${AWS::StackName}-${n}`),FifoQueue:c,VisibilityTimeout:i.visibilityTimeout||30,MessageRetentionPeriod:i.messageRetentionPeriod||345600,ReceiveMessageWaitTimeSeconds:i.receiveMessageWaitTime||0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}`)}]};if(c&&i.contentBasedDeduplication)u.ContentBasedDeduplication=!0;if(i.deadLetterQueue&&l)u.RedrivePolicy={deadLetterTargetArn:l,maxReceiveCount:i.maxReceiveCount||3};if(a.addResource(s,"AWS::SQS::Queue",u,{dependsOn:i.deadLetterQueue?`${s}DLQ`:void 0,deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),a.addResource(`${s}Policy`,"AWS::SQS::QueuePolicy",{Queues:[e.ref(s)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["lambda.amazonaws.com","events.amazonaws.com","sns.amazonaws.com"]},Action:"sqs:SendMessage",Resource:e.getAtt(s,"Arn"),Condition:{ArnEquals:{"aws:SourceArn":e.sub("arn:aws:*:${AWS::Region}:${AWS::AccountId}:*")}}}]}},{dependsOn:s}),a.addOutputs({[`${s}Url`]:{Description:`${n} queue URL`,Value:e.ref(s),Export:{Name:e.sub(`\${AWS::StackName}-${n}-queue-url`)}},[`${s}Arn`]:{Description:`${n} queue ARN`,Value:e.getAtt(s,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${n}-queue-arn`)}}}),i.deadLetterQueue)a.addOutputs({[`${s}DLQUrl`]:{Description:`${n} dead letter queue URL`,Value:e.ref(`${s}DLQ`),Export:{Name:e.sub(`\${AWS::StackName}-${n}-dlq-url`)}}})}function on(a,n){if(n.certificate)cn(a,n.certificate);if(n.waf?.enabled)ln(a,n.waf);if(n.securityGroups)for(let[i,s]of Object.entries(n.securityGroups))un(a,i,s)}function cn(a,n){if(!n)return;let i=[n.domain];if(n.subdomains)i.push(...n.subdomains);a.addResource("Certificate","AWS::CertificateManager::Certificate",{DomainName:n.domain,SubjectAlternativeNames:n.subdomains,ValidationMethod:n.validationMethod||"DNS",DomainValidationOptions:i.map((s)=>({DomainName:s,HostedZoneId:e.ref("HostedZone")})),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-certificate")}]}),a.addOutputs({CertificateArn:{Description:"ACM Certificate ARN",Value:e.ref("Certificate"),Export:{Name:e.sub("${AWS::StackName}-certificate-arn")}}})}function ln(a,n){if(!n)return;let i=[],s=n.rules||["rateLimit","sqlInjection","xss"];if(s.includes("rateLimit"))i.push({Name:"RateLimitRule",Priority:1,Statement:{RateBasedStatement:{Limit:n.rateLimit||2000,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"RateLimitRule"}});let c=i.length+1;if(s.includes("sqlInjection"))i.push({Name:"AWSManagedRulesSQLi",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesSQLiRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesSQLi"}});if(s.includes("xss"))i.push({Name:"AWSManagedRulesXSS",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesXSS"}});if(s.includes("knownBadInputs"))i.push({Name:"AWSManagedRulesKnownBadInputs",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesKnownBadInputs"}});if(s.includes("coreRuleSet"))i.push({Name:"AWSManagedRulesCoreRuleSet",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesCommonRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesCoreRuleSet"}});if(s.includes("linuxRuleSet"))i.push({Name:"AWSManagedRulesLinuxRuleSet",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesLinuxRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesLinuxRuleSet"}});if(s.includes("apiProtection"))i.push({Name:"AWSManagedRulesAPIProtection",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesAmazonIpReputationList"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesAPIProtection"}});if(s.includes("geoBlock"))i.push({Name:"GeoBlockRule",Priority:c++,Statement:{GeoMatchStatement:{CountryCodes:["CN","RU"]}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"GeoBlockRule"}});if(s.includes("connectionLimit"))i.push({Name:"ConnectionLimitRule",Priority:c++,Statement:{RateBasedStatement:{Limit:100,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"ConnectionLimitRule"}});if(a.addResource("WebACL","AWS::WAFv2::WebACL",{Name:e.sub("${AWS::StackName}-waf"),Scope:n.scope||"REGIONAL",DefaultAction:{Allow:{}},Rules:i,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:e.sub("${AWS::StackName}-waf")},Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-waf")}]}),a.hasResource("LoadBalancer"))a.addResource("WebACLAssociation","AWS::WAFv2::WebACLAssociation",{ResourceArn:e.ref("LoadBalancer"),WebACLArn:e.getAtt("WebACL","Arn")},{dependsOn:["WebACL","LoadBalancer"]});a.addOutputs({WebACLId:{Description:"WAF Web ACL ID",Value:e.ref("WebACL"),Export:{Name:e.sub("${AWS::StackName}-waf-id")}},WebACLArn:{Description:"WAF Web ACL ARN",Value:e.getAtt("WebACL","Arn"),Export:{Name:e.sub("${AWS::StackName}-waf-arn")}}})}function un(a,n,i){if(!i)return;let s=a.toLogicalId(`${n}-security-group`),c=i.ingress?.map((u)=>({IpProtocol:u.protocol,FromPort:u.port,ToPort:u.port,CidrIp:u.cidr,SourceSecurityGroupId:u.source?e.ref(u.source):void 0}))||[],l=i.egress?.map((u)=>({IpProtocol:u.protocol,FromPort:u.port,ToPort:u.port,CidrIp:u.cidr||"0.0.0.0/0"}))||[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}];a.addResource(s,"AWS::EC2::SecurityGroup",{GroupDescription:`Security group for ${n}`,VpcId:e.ref("VPC"),SecurityGroupIngress:c,SecurityGroupEgress:l,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}-sg`)}]},{dependsOn:"VPC"}),a.addOutputs({[`${s}Id`]:{Description:`${n} security group ID`,Value:e.ref(s),Export:{Name:e.sub(`\${AWS::StackName}-${n}-sg-id`)}}})}function dn(a,n){for(let[i,s]of Object.entries(n)){if(s.type==="efs"){pn(a,i,s);continue}mn(a,i,s)}}function mn(a,n,i){let s=a.toLogicalId(`${n}-bucket`),c={BucketName:e.sub(`\${AWS::StackName}-${n}`),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}`)}]};if(i.versioning)c.VersioningConfiguration={Status:"Enabled"};if(i.encryption)c.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(!i.public)c.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(i.website)c.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"index.html"};if(i.cors&&i.cors.length>0)c.CorsConfiguration={CorsRules:i.cors.map((l)=>({AllowedOrigins:l.allowedOrigins,AllowedMethods:l.allowedMethods,AllowedHeaders:l.allowedHeaders||["*"],MaxAge:l.maxAge||3600}))};if(i.lifecycleRules&&i.lifecycleRules.length>0)c.LifecycleConfiguration={Rules:i.lifecycleRules.map((l)=>({Id:l.id,Status:l.enabled?"Enabled":"Disabled",ExpirationInDays:l.expirationDays,Transitions:l.transitions?.map((u)=>({TransitionInDays:u.days,StorageClass:u.storageClass}))}))};if(i.intelligentTiering)c.IntelligentTieringConfigurations=[{Id:"EntireBucket",Status:"Enabled",Tierings:[{AccessTier:"ARCHIVE_ACCESS",Days:90},{AccessTier:"DEEP_ARCHIVE_ACCESS",Days:180}]}];if(a.addResource(s,"AWS::S3::Bucket",c,{deletionPolicy:i.versioning?"Retain":"Delete"}),i.public)a.addResource(`${s}Policy`,"AWS::S3::BucketPolicy",{Bucket:e.ref(s),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:"s3:GetObject",Resource:e.join("",[eo.s3Bucket(e.ref(s)),"/*"])}]}},{dependsOn:s});if(a.addOutputs({[`${s}Name`]:{Description:`${n} bucket name`,Value:e.ref(s),Export:{Name:e.sub(`\${AWS::StackName}-${n}-bucket`)}},[`${s}Arn`]:{Description:`${n} bucket ARN`,Value:e.getAtt(s,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${n}-bucket-arn`)}}}),i.website)a.addOutputs({[`${s}WebsiteURL`]:{Description:`${n} website URL`,Value:e.getAtt(s,"WebsiteURL")}})}function pn(a,n,i){let s=a.toLogicalId(`${n}-efs`),c={Encrypted:i.encryption!==!1,PerformanceMode:i.performanceMode||"generalPurpose",ThroughputMode:i.throughputMode||"bursting",FileSystemTags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}`)}]};if(i.lifecyclePolicy){if(c.LifecyclePolicies=[],i.lifecyclePolicy.transitionToIA)c.LifecyclePolicies.push({TransitionToIA:`AFTER_${i.lifecyclePolicy.transitionToIA}_DAYS`});if(i.lifecyclePolicy.transitionToPrimaryStorageClass)c.LifecyclePolicies.push({TransitionToPrimaryStorageClass:"AFTER_1_ACCESS"})}a.addResource(s,"AWS::EFS::FileSystem",c,{deletionPolicy:"Retain"});let l=2;for(let u=0;u<l;u++)a.addResource(`${s}MountTarget${u+1}`,"AWS::EFS::MountTarget",{FileSystemId:e.ref(s),SubnetId:e.ref(`PrivateSubnet${u+1}`),SecurityGroups:[e.ref("EFSSecurityGroup")]},{dependsOn:[s,`PrivateSubnet${u+1}`]});a.addResource("EFSSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for EFS mount targets",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:2049,ToPort:2049,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-efs-sg")}]},{dependsOn:"VPC"}),a.addOutputs({[`${s}Id`]:{Description:`${n} EFS file system ID`,Value:e.ref(s),Export:{Name:e.sub(`\${AWS::StackName}-${n}-efs`)}}})}class $p{template;config;resourceDependencies;constructor(a){this.config=a,this.resourceDependencies=new Map,this.template={AWSTemplateFormatVersion:"2010-09-09",Description:`Infrastructure for ${a.project.name} (${a.project.slug})`,Resources:{}}}build(){return this.addParameters(),this.addMappings(),this.addConditions(),this.addResources(),this.initializeOutputs(),this.resolveDependencies(),this.template}addParameters(){this.template.Parameters={Environment:{Type:"String",Default:"production",AllowedValues:["development","staging","production"],Description:"Environment name"}}}addMappings(){this.template.Mappings={RegionMap:{"us-east-1":{AMI:"ami-0f3caa1cf4417e51b"},"us-west-2":{AMI:"ami-0d1cd67c26f5fca19"},"eu-west-1":{AMI:"ami-0bbc25e23a7640b9b"}}}}addConditions(){this.template.Conditions={IsProduction:e.equals(e.ref("Environment"),"production"),HasDomain:e.not([e.equals(this.config.environments?.production?.domain||"","")])}}addResources(){let{infrastructure:a}=this.config;if(!a)return;if(a.network)this.addNetworkResources(a.network);if(a.storage)this.addStorageResources(a.storage);if(a.compute)this.addComputeResources(a.compute);if(a.databases)this.addDatabaseResources(a.databases);if(a.cache)this.addCacheResources(a.cache);if(a.cdn)this.addCDNResources(a.cdn);if(a.apiGateway)this.addApiGatewayResources(a.apiGateway);if(a.functions)this.addFunctionResources(a.functions);if(a.queues)this.addQueueResources(a.queues);if(a.messaging)this.addMessagingResources(a.messaging);if(a.monitoring)this.addMonitoringResources(a.monitoring);if(a.security)this.addSecurityResources(a.security)}initializeOutputs(){let a=this.template.Outputs||{};if(this.template.Outputs={StackName:{Description:"Stack name",Value:e.ref("AWS::StackName"),Export:{Name:e.sub("${AWS::StackName}-Name")}},Region:{Description:"AWS Region",Value:e.ref("AWS::Region"),Export:{Name:e.sub("${AWS::StackName}-Region")}},...a},this.config.environments?.production?.domain)this.template.Outputs.Domain={Description:"Production domain",Value:this.config.environments.production.domain,Condition:"HasDomain"}}addResource(a,n,i,s){let c={Type:n,Properties:i};if(s?.dependsOn)c.DependsOn=s.dependsOn,this.trackDependency(a,s.dependsOn);if(s?.condition)c.Condition=s.condition;if(s?.deletionPolicy)c.DeletionPolicy=s.deletionPolicy;if(s?.updateReplacePolicy)c.UpdateReplacePolicy=s.updateReplacePolicy;this.template.Resources[a]=c}addOutputs(a){this.template.Outputs={...this.template.Outputs,...a}}getOutputs(){return this.template.Outputs||{}}hasResource(a){return a in this.template.Resources}getResource(a){return this.template.Resources[a]}trackDependency(a,n){if(!this.resourceDependencies.has(a))this.resourceDependencies.set(a,new Set);(Array.isArray(n)?n:[n]).forEach((i)=>this.resourceDependencies.get(a).add(i))}resolveDependencies(){let a=new Set,n=new Set,i=(s)=>{if(n.has(s))throw Error(`Circular dependency detected involving resource: ${s}`);if(a.has(s))return!0;a.add(s),n.add(s);let c=this.resourceDependencies.get(s);if(c)for(let l of c)i(l);return n.delete(s),!0};for(let s of this.resourceDependencies.keys())i(s)}toLogicalId(a){return a.split(/[-_\s]/).map((n)=>n.charAt(0).toUpperCase()+n.slice(1).toLowerCase()).join("")}addNetworkResources(a){rn(this,a)}addStorageResources(a){dn(this,a)}addComputeResources(a){Ur(this,a)}addDatabaseResources(a){jr(this,a)}addFunctionResources(a){Hr(this,a)}addCacheResources(a){Dr(this,a)}addQueueResources(a){nn(this,a)}addMessagingResources(a){Jr(this,a)}addCDNResources(a){Wr(this,a)}addApiGatewayResources(a){wr(this,a)}addMonitoringResources(a){Zr(this,a)}addSecurityResources(a){on(this,a)}}function fd(a){return new $p(a).build()}function jy(a){let{name:n,slug:i,domain:s,subdomain:c}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:c&&s?`${c}.${s}`:s}},infrastructure:{storage:{assets:{public:!0,versioning:!1,website:!0,encryption:!1,cors:[{allowedOrigins:["*"],allowedMethods:["GET","HEAD"],allowedHeaders:["*"],maxAge:3600}]}},cdn:{enabled:!0,customDomain:s?{domain:c&&s?`${c}.${s}`:s,certificateArn:"TO_BE_GENERATED"}:void 0,cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0,errorPages:{404:"/index.html",403:"/index.html"}}}}}function zy(a){let{name:n,slug:i,domain:s,instanceType:c="t3.small",minInstances:l=2,maxInstances:u=10}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:s}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",keyPair:`${i}-key`,autoScaling:{min:l,max:u,desired:l,targetCPU:70},loadBalancer:{type:"application",healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3}},userData:{packages:["nodejs","npm","nginx"],commands:["curl -fsSL https://bun.sh/install | bash","npm install -g pm2"]}}},databases:{postgres:{engine:"postgres",version:"15",instanceClass:"db.t3.micro",allocatedStorage:20,multiAZ:!0,backupRetentionDays:7,deletionProtection:!0}},cache:{redis:{nodeType:"cache.t3.micro",numCacheNodes:1,engine:"redis",engineVersion:"7.0"}},security:{certificate:s?{domain:s,subdomains:[`*.${s}`],validationMethod:"DNS"}:void 0}}}}function Ky(a){let{name:n,slug:i,domain:s,taskCpu:c="256",taskMemory:l="512",desiredCount:u=2}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:s}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:0}},compute:{fargate:{taskDefinition:{cpu:c,memory:l,containerDefinitions:[{name:"app",image:`${i}-app:latest`,portMappings:[{containerPort:3000}],environment:[],secrets:[]}]},service:{desiredCount:u,healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3},autoScaling:{min:u,max:u*5,targetCPU:70,targetMemory:80}},loadBalancer:{type:"application"}}},databases:{dynamodb:{tables:{[`${i}-main`]:{partitionKey:{name:"id",type:"S"},sortKey:{name:"createdAt",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0}}}},functions:{"process-queue":{runtime:"nodejs20.x",handler:"dist/workers/queue.handler",memory:512,timeout:60,events:[{type:"sqs",queueName:`${i}-queue`}]}},security:{certificate:s?{domain:s,subdomains:[`*.${s}`],validationMethod:"DNS"}:void 0}}}}function Wy(a){let{name:n,slug:i,entry:s,domain:c,runtime:l="nodejs20.x",memory:u=1024,build:h,deploy:y,assets:S,queues:b=!0,scheduler:A="on",region:C="us-east-1"}=a;return{project:{name:n,slug:i,region:C},mode:"serverless",environments:{production:{type:"production",domain:c,app:{kind:"node",runtime:l,entry:s,memory:u,build:h,deploy:y,assets:S,queues:b,scheduler:A,domain:c}}}}}function Ad(a){let n=a.database!==!1,i=a.cache!==!1,s=a.queue!==!1;return{project:{name:a.name,slug:a.slug,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:a.domain}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{fargate:{taskDefinition:{cpu:"256",memory:"512",containerDefinitions:[{name:"api",image:a.imageUri,portMappings:[{containerPort:3000}],environment:[{name:"NODE_ENV",value:"production"},{name:"PORT",value:"3000"},{name:"AWS_REGION",value:e.ref("AWS::Region")},...n?[{name:"DB_HOST",value:e.getAtt("PostgresDb","Endpoint.Address")},{name:"DB_PORT",value:e.getAtt("PostgresDb","Endpoint.Port")}]:[],...i?[{name:"REDIS_HOST",value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Address")},{name:"REDIS_PORT",value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Port")},{name:"REDIS_TLS",value:"true"}]:[],...s?[{name:"QUEUE_URL",value:e.ref("JobsQueue")}]:[],{name:"MAIL_TRANSPORT",value:"ses"}],secrets:n?[{name:"DB_USERNAME",valueFrom:e.sub("${DBSecret}:username::")},{name:"DB_PASSWORD",valueFrom:e.sub("${DBSecret}:password::")}]:[]}]},service:{desiredCount:a.desiredCount||1,healthCheck:{path:"/api/health",interval:30,timeout:5},autoScaling:{min:a.desiredCount||1,max:6,targetCPU:70}},loadBalancer:{type:"application",...a.certificateArn?{customDomain:{domain:a.domain,certificateArn:a.certificateArn}}:{},...a.originVerifySecret?{originVerifyHeader:{name:"X-Origin-Verify",value:a.originVerifySecret}}:{}}}},...n?{databases:{postgres:{engine:"postgres",version:"16",instanceClass:"db.t4g.micro",allocatedStorage:20,maxAllocatedStorage:100,multiAZ:!1,backupRetentionDays:7,deletionProtection:!0}}}:{},...i?{cache:{redis:{nodeType:"cache.t4g.micro",numCacheNodes:2,engine:"redis",engineVersion:"7.1",automaticFailoverEnabled:!0,snapshotRetentionLimit:5}}}:{},...s?{queues:{jobs:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0,maxReceiveCount:3,receiveMessageWaitTime:20}}}:{}}}}function Jy(a){let{name:n,slug:i,domain:s,apiSubdomain:c="api"}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:s}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},storage:{frontend:{public:!0,versioning:!0,website:!0,encryption:!1}},cdn:{enabled:!0,customDomain:{domain:s,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0,errorPages:{404:"/index.html"}},compute:{fargate:{taskDefinition:{cpu:"512",memory:"1024",containerDefinitions:[{name:"api",image:`${i}-api:latest`,portMappings:[{containerPort:3000}]}]},service:{desiredCount:2,healthCheck:{path:"/api/health",interval:30},autoScaling:{min:2,max:10,targetCPU:70}},loadBalancer:{type:"application",customDomain:{domain:`${c}.${s}`,certificateArn:"TO_BE_GENERATED"}}}},databases:{postgres:{engine:"postgres",version:"15",instanceClass:"db.t3.small",allocatedStorage:50,multiAZ:!0,backupRetentionDays:14,deletionProtection:!0}},cache:{redis:{nodeType:"cache.t3.small",numCacheNodes:2,engine:"redis",engineVersion:"7.0"}},queues:{jobs:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0}},security:{certificate:{domain:s,subdomains:[`*.${s}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss"]}}}}}function Xy(a){let{name:n,slug:i,domain:s}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:s}},infrastructure:{apiGateway:{type:"HTTP",cors:{allowOrigins:["*"],allowMethods:["GET","POST","PUT","DELETE","PATCH"],allowHeaders:["Content-Type","Authorization"],maxAge:3600},customDomain:s?{domain:s,certificateArn:"TO_BE_GENERATED"}:void 0,throttling:{rateLimit:1e4,burstLimit:5000},authorizer:{type:"JWT",identitySource:"$request.header.Authorization"}},functions:{users:{runtime:"nodejs20.x",handler:"dist/api/users.handler",memory:512,timeout:30,events:[{type:"http",path:"/users",method:"GET"},{type:"http",path:"/users",method:"POST"}]},products:{runtime:"nodejs20.x",handler:"dist/api/products.handler",memory:512,timeout:30,events:[{type:"http",path:"/products",method:"GET"}]}},databases:{dynamodb:{tables:{[`${i}-users`]:{partitionKey:{name:"userId",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0,globalSecondaryIndexes:[{name:"EmailIndex",partitionKey:{name:"email",type:"S"},projection:"ALL"}]},[`${i}-products`]:{partitionKey:{name:"productId",type:"S"},sortKey:{name:"category",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!1}}}},cache:{elasticache:{nodeType:"cache.t3.micro",numCacheNodes:1,engine:"redis",engineVersion:"7.0"}},security:{certificate:s?{domain:s,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","sqlInjection"]}},monitoring:{alarms:[{metric:"Errors",threshold:10,period:300,evaluationPeriods:1},{metric:"Duration",threshold:3000,period:300,evaluationPeriods:2}]}}}}function Yy(a){let{name:n,slug:i,domain:s,instanceType:c="t3.small"}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:s}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",keyPair:`${i}-key`,autoScaling:{min:2,max:6,desired:2,targetCPU:75},loadBalancer:{type:"application",healthCheck:{path:"/wp-admin/install.php",interval:30}},userData:{packages:["nginx","php8.1-fpm","php8.1-mysql","php8.1-curl","php8.1-gd","php8.1-mbstring","php8.1-xml","php8.1-zip"],commands:["cd /var/www","wget https://wordpress.org/latest.tar.gz","tar -xzf latest.tar.gz","chown -R www-data:www-data wordpress","rm /etc/nginx/sites-enabled/default","systemctl restart nginx","systemctl restart php8.1-fpm"]}}},fileSystem:{uploads:{performanceMode:"generalPurpose",throughputMode:"bursting",encrypted:!0,lifecyclePolicy:{transitionToIA:30},mountPath:"/var/www/wordpress/wp-content/uploads"}},databases:{mysql:{engine:"mysql",version:"8.0",instanceClass:"db.t3.small",allocatedStorage:50,multiAZ:!0,backupRetentionDays:7,deletionProtection:!0,databaseName:"wordpress"}},cache:{redis:{nodeType:"cache.t3.micro",numCacheNodes:1,engine:"redis",engineVersion:"7.0"}},cdn:{enabled:!0,customDomain:{domain:s,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,origins:[{type:"alb",pathPattern:"/wp-content/*"}]},security:{certificate:{domain:s,subdomains:[`www.${s}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss","wordpressRules"]}}}}}function Zy(a){let{name:n,slug:i,domain:s,apiDomain:c}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:s}},infrastructure:{storage:{static:{public:!0,versioning:!0,website:!0,encryption:!1,cors:[{allowedOrigins:["*"],allowedMethods:["GET","HEAD"]}],lifecycleRules:[{id:"DeleteOldVersions",enabled:!0,expirationDays:90}]}},cdn:{enabled:!0,customDomain:{domain:s,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:0,maxTTL:31536000},compress:!0,http3:!0,errorPages:{404:"/404.html",500:"/500.html"},edgeFunctions:[{eventType:"origin-request",functionArn:"TO_BE_CREATED",name:"ssr-handler"}]},functions:{ssr:{runtime:"nodejs20.x",handler:"dist/edge/ssr.handler",memory:512,timeout:5},...c?{api:{runtime:"nodejs20.x",handler:"dist/api/index.handler",memory:1024,timeout:30,events:[{type:"http",path:"/{proxy+}",method:"ANY"}]}}:{}},apiGateway:c?{type:"HTTP",customDomain:{domain:c,certificateArn:"TO_BE_GENERATED"},cors:{allowOrigins:[s],allowMethods:["GET","POST","PUT","DELETE"],allowHeaders:["Content-Type","Authorization"]}}:void 0,databases:{dynamodb:{tables:{content:{partitionKey:{name:"id",type:"S"},sortKey:{name:"type",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!1}}}},security:{certificate:{domain:s,subdomains:c?[c]:[],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","geoBlock"]}}}}}function eI(a){let{name:n,slug:i,domain:s,services:c}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:s}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:3,natGateways:2}},compute:{services:c.map((l)=>({name:l.name,type:"fargate",taskDefinition:{cpu:l.cpu||"256",memory:l.memory||"512",containerDefinitions:[{name:l.name,image:`${i}-${l.name}:latest`,portMappings:[{containerPort:l.port}],healthCheck:{command:["CMD-SHELL",`curl -f http://localhost:${l.port}/health || exit 1`],interval:30,timeout:5,retries:3}}]},service:{desiredCount:l.desiredCount||2,serviceDiscovery:{enabled:!0,namespace:`${i}.local`},autoScaling:{min:2,max:10,targetCPU:70}}}))},apiGateway:{type:"HTTP",customDomain:{domain:s,certificateArn:"TO_BE_GENERATED"},cors:{allowOrigins:["*"],allowMethods:["GET","POST","PUT","DELETE","PATCH"]},routes:c.map((l)=>({path:`/${l.name}/{proxy+}`,integration:{type:"vpc-link",service:l.name}}))},databases:{dynamodb:{tables:Object.fromEntries(c.map((l)=>[`${i}-${l.name}`,{partitionKey:{name:"id",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0}]))}},queues:{events:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0}},messaging:{topics:{events:{name:`${i}-events`,subscriptions:c.map((l)=>({protocol:"sqs",endpoint:`${i}-${l.name}-queue`,filterPolicy:{service:[l.name]}}))}}},monitoring:{dashboard:{name:`${i}-microservices`,widgets:c.map((l)=>({type:"metric",metrics:[{service:l.name,metric:"CPUUtilization"},{service:l.name,metric:"MemoryUtilization"},{service:l.name,metric:"RequestCount"}]}))},alarms:c.flatMap((l)=>[{name:`${l.name}-high-cpu`,metric:"CPUUtilization",threshold:80,service:l.name},{name:`${l.name}-errors`,metric:"Errors",threshold:10,service:l.name}])},security:{certificate:{domain:s,validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection"]}}}}}function tI(a){let{name:n,slug:i,domain:s}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:s}},infrastructure:{apiGateway:{type:"websocket",customDomain:s?{domain:s,certificateArn:"TO_BE_GENERATED"}:void 0,routes:[{path:"$connect",method:"WEBSOCKET",integration:"websocket-connect"},{path:"$disconnect",method:"WEBSOCKET",integration:"websocket-disconnect"},{path:"$default",method:"WEBSOCKET",integration:"websocket-default"},{path:"sendMessage",method:"WEBSOCKET",integration:"websocket-send-message"},{path:"joinRoom",method:"WEBSOCKET",integration:"websocket-join-room"}]},functions:{connect:{runtime:"nodejs20.x",handler:"dist/websocket/connect.handler",memory:512,timeout:30},disconnect:{runtime:"nodejs20.x",handler:"dist/websocket/disconnect.handler",memory:512,timeout:30},default:{runtime:"nodejs20.x",handler:"dist/websocket/default.handler",memory:512,timeout:30},"send-message":{runtime:"nodejs20.x",handler:"dist/websocket/sendMessage.handler",memory:512,timeout:30},"join-room":{runtime:"nodejs20.x",handler:"dist/websocket/joinRoom.handler",memory:512,timeout:30},broadcast:{runtime:"nodejs20.x",handler:"dist/streams/broadcast.handler",memory:1024,timeout:60,events:[{type:"dynamodb-stream",tableName:`${i}-messages`,startingPosition:"LATEST",batchSize:100}]}},databases:{dynamodb:{tables:{[`${i}-connections`]:{partitionKey:{name:"connectionId",type:"S"},billingMode:"PAY_PER_REQUEST",globalSecondaryIndexes:[{name:"RoomIndex",partitionKey:{name:"roomId",type:"S"},sortKey:{name:"connectionId",type:"S"},projection:"ALL"}]},[`${i}-messages`]:{partitionKey:{name:"roomId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0,globalSecondaryIndexes:[{name:"UserIndex",partitionKey:{name:"userId",type:"S"},sortKey:{name:"timestamp",type:"S"},projection:"ALL"}]},[`${i}-rooms`]:{partitionKey:{name:"roomId",type:"S"},billingMode:"PAY_PER_REQUEST"}}}},cache:{elasticache:{nodeType:"cache.t3.small",numCacheNodes:2,engine:"redis",engineVersion:"7.0"}},monitoring:{alarms:[{metric:"WebSocketConnections",threshold:1e4,evaluationPeriods:1},{metric:"IntegrationLatency",threshold:1000,evaluationPeriods:2}],dashboard:{name:`${i}-realtime`,widgets:[{type:"metric",metrics:["WebSocketConnections","MessagesSent","IntegrationLatency"]}]}},security:{certificate:s?{domain:s,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","connectionLimit"]}}}}}function rI(a){let{name:n,slug:i,retentionDays:s=7}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",infrastructure:{streaming:{dataStream:{name:`${i}-stream`,shardCount:2,retentionPeriod:s*24,encryption:!0}},storage:{raw:{public:!1,versioning:!0,encryption:!0,intelligentTiering:!0,lifecycleRules:[{id:"ArchiveOldData",enabled:!0,transitions:[{days:30,storageClass:"GLACIER"},{days:90,storageClass:"DEEP_ARCHIVE"}]}]},processed:{public:!1,versioning:!0,encryption:!0,intelligentTiering:!0}},functions:{"stream-processor":{runtime:"nodejs20.x",handler:"dist/processors/stream.handler",memory:2048,timeout:300,events:[{type:"kinesis",streamName:`${i}-stream`,batchSize:1000,startingPosition:"LATEST",parallelizationFactor:10}]},transformer:{runtime:"nodejs20.x",handler:"dist/processors/transform.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${i}-raw`,prefix:"incoming/"}]},aggregator:{runtime:"nodejs20.x",handler:"dist/processors/aggregate.handler",memory:2048,timeout:600,events:[{type:"schedule",expression:"cron(0 * * * ? *)"}]}},analytics:{athena:{database:`${i}_analytics`,workgroup:`${i}-workgroup`,outputBucket:`${i}-query-results`,tables:[{name:"raw_events",location:`s3://${i}-raw/events/`,format:"parquet",partitionKeys:["year","month","day"]},{name:"processed_events",location:`s3://${i}-processed/events/`,format:"parquet",partitionKeys:["year","month","day"]}]},glue:{crawlers:[{name:`${i}-crawler`,databaseName:`${i}_analytics`,s3Targets:[`s3://${i}-raw/`,`s3://${i}-processed/`],schedule:"cron(0 2 * * ? *)"}],jobs:[{name:`${i}-etl-job`,scriptLocation:`s3://${i}-scripts/etl.py`,role:`${i}-glue-role`,maxCapacity:10,timeout:120}]}},databases:{dynamodb:{tables:{[`${i}-metadata`]:{partitionKey:{name:"pipelineId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST"}}}},queues:{failedJobs:{fifo:!1,visibilityTimeout:900,messageRetentionPeriod:1209600,deadLetterQueue:!0,maxReceiveCount:3}},workflow:{pipelines:[{name:`${i}-daily-pipeline`,type:"stepFunctions",definition:{StartAt:"ExtractData",States:{ExtractData:{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Next:"TransformData"},TransformData:{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Next:"LoadData"},LoadData:{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",End:!0}}},schedule:"cron(0 0 * * ? *)"}]},monitoring:{dashboard:{name:`${i}-pipeline`,widgets:[{type:"metric",metrics:["KinesisIncomingRecords","LambdaInvocations","S3ObjectsCreated","GlueJobsSucceeded"]}]},alarms:[{metric:"LambdaErrors",threshold:10,evaluationPeriods:1},{metric:"KinesisIteratorAge",threshold:60000,evaluationPeriods:2}]}}}}function nI(a){let{name:n,slug:i,domain:s,modelS3Path:c=`s3://${i}-models/`,instanceType:l="ml.t3.medium"}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:s}},infrastructure:{storage:{models:{public:!1,versioning:!0,encryption:!0,intelligentTiering:!0},datasets:{public:!1,versioning:!0,encryption:!0,lifecycleRules:[{id:"ArchiveOldDatasets",enabled:!0,transitions:[{days:90,storageClass:"GLACIER"}]}]},predictions:{public:!1,versioning:!1,encryption:!0,lifecycleRules:[{id:"DeleteOldPredictions",enabled:!0,expirationDays:30}]}},machineLearning:{sagemaker:{endpoints:[{name:`${i}-inference`,modelS3Path:c,instanceType:l,initialInstanceCount:1,autoScaling:{minInstances:1,maxInstances:5,targetInvocationsPerInstance:1000}}],trainingJobs:[{name:`${i}-training`,algorithmSpecification:{trainingImage:"TO_BE_SPECIFIED",trainingInputMode:"File"},instanceType:"ml.p3.2xlarge",instanceCount:1,volumeSizeInGB:50,maxRuntimeInSeconds:86400}]}},apiGateway:{type:"HTTP",customDomain:s?{domain:s,certificateArn:"TO_BE_GENERATED"}:void 0,cors:{allowOrigins:["*"],allowMethods:["POST"],allowHeaders:["Content-Type","Authorization"]},throttling:{rateLimit:1000,burstLimit:500}},functions:{predict:{runtime:"python3.11",handler:"handlers/predict.handler",memory:2048,timeout:60,events:[{type:"http",path:"/predict",method:"POST"}],environment:{SAGEMAKER_ENDPOINT:`${i}-inference`,MODEL_BUCKET:`${i}-models`}},"batch-predict":{runtime:"python3.11",handler:"handlers/batchPredict.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${i}-datasets`,suffix:".csv"}]},"trigger-training":{runtime:"python3.11",handler:"handlers/training.handler",memory:1024,timeout:300,events:[{type:"schedule",expression:"cron(0 2 * * ? *)"}]}},databases:{dynamodb:{tables:{[`${i}-predictions`]:{partitionKey:{name:"requestId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0},[`${i}-models`]:{partitionKey:{name:"modelId",type:"S"},sortKey:{name:"version",type:"S"},billingMode:"PAY_PER_REQUEST"}}}},queues:{predictions:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:86400,deadLetterQueue:!0}},monitoring:{dashboard:{name:`${i}-ml`,widgets:[{type:"metric",metrics:["SageMakerInvocations","SageMakerModelLatency","APIGatewayRequests","LambdaErrors"]}]},alarms:[{metric:"SageMakerModelLatency",threshold:1000,evaluationPeriods:2},{metric:"SageMakerInvocationErrors",threshold:10,evaluationPeriods:1}]},security:{certificate:s?{domain:s,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","apiProtection"]}}}}}function iI(a){let{name:n,slug:i,domain:s,instanceType:c="t3.medium",minInstances:l=2,maxInstances:u=10,databaseEngine:h="mysql",sessionStore:y="redis"}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:s}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:2}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",autoScaling:{min:l,max:u,targetCPU:70,scaleUpCooldown:300,scaleDownCooldown:300},loadBalancer:{type:"application",healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3},stickySession:{enabled:!0,duration:86400}},userData:`#!/bin/bash
2489
+ | limit 20`,region:e.ref("AWS::Region"),title:`Logs: ${l.logGroup}`}});else if(l.type==="text"&&l.text)i.push({type:"text",x:s,y:c,width:u,height:h,properties:{markdown:l.text}});if(s+=u,s>=24)s=0,c+=h}),a.addResource("CloudWatchDashboard","AWS::CloudWatch::Dashboard",{DashboardName:e.sub(`\${AWS::StackName}-${n.name}`),DashboardBody:JSON.stringify({widgets:i})}),a.addOutputs({DashboardURL:{Description:"CloudWatch Dashboard URL",Value:e.sub("https://console.aws.amazon.com/cloudwatch/home?region=${AWS::Region}#dashboards:name=${CloudWatchDashboard}")}})}function tn(a,n,i){let s=a.toLogicalId(`${n}-log-group`);a.addResource(s,"AWS::Logs::LogGroup",{LogGroupName:e.sub(`/aws/\${AWS::StackName}/${n}`),RetentionInDays:i||14,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}`)}]})}function Lt(a,n){if(n)return{ec2:"AWS/EC2",ecs:"AWS/ECS",lambda:"AWS/Lambda",rds:"AWS/RDS",dynamodb:"AWS/DynamoDB",s3:"AWS/S3",cloudfront:"AWS/CloudFront",alb:"AWS/ApplicationELB",nlb:"AWS/NetworkELB",apigateway:"AWS/ApiGateway",sqs:"AWS/SQS",sns:"AWS/SNS",kinesis:"AWS/Kinesis",elasticache:"AWS/ElastiCache"}[n.toLowerCase()]||"AWS/CloudWatch";let i=a.toLowerCase();if(i.includes("cpu")||i.includes("memory")||i.includes("network"))return"AWS/EC2";if(i.includes("lambda")||i.includes("invocation")||i.includes("duration"))return"AWS/Lambda";if(i.includes("request")||i.includes("latency")||i.includes("target"))return"AWS/ApplicationELB";if(i.includes("database")||i.includes("connection"))return"AWS/RDS";if(i.includes("read")||i.includes("write")||i.includes("consumed"))return"AWS/DynamoDB";return"AWS/CloudWatch"}function an(a){return{ec2:[{Name:"InstanceId",Value:e.ref("EC2Instance")}],ecs:[{Name:"ClusterName",Value:e.ref("ECSCluster")},{Name:"ServiceName",Value:e.getAtt("ECSService","Name")}],lambda:[{Name:"FunctionName",Value:e.ref("LambdaFunction")}],rds:[{Name:"DBInstanceIdentifier",Value:e.ref("Database")}],dynamodb:[{Name:"TableName",Value:e.ref("DynamoDBTable")}],alb:[{Name:"LoadBalancer",Value:e.getAtt("LoadBalancer","LoadBalancerFullName")}],apigateway:[{Name:"ApiName",Value:e.ref("HttpApi")}]}[a.toLowerCase()]||[]}function rn(a,n){if(!n.vpc)return;let{cidr:i="10.0.0.0/16",availabilityZones:s=2,natGateways:c=1,enableDnsHostnames:l=!0,enableDnsSupport:u=!0}=n.vpc;a.addResource("VPC","AWS::EC2::VPC",{CidrBlock:i,EnableDnsHostnames:l,EnableDnsSupport:u,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-vpc")}]}),a.addResource("InternetGateway","AWS::EC2::InternetGateway",{Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-igw")}]}),a.addResource("VPCGatewayAttachment","AWS::EC2::VPCGatewayAttachment",{VpcId:e.ref("VPC"),InternetGatewayId:e.ref("InternetGateway")},{dependsOn:["VPC","InternetGateway"]});let h=[];for(let C=0;C<s;C++){let T=`PublicSubnet${C+1}`;h.push(T),a.addResource(T,"AWS::EC2::Subnet",{VpcId:e.ref("VPC"),CidrBlock:e.select(C,e.cidr(e.getAtt("VPC","CidrBlock"),s*2,8)),AvailabilityZone:e.select(C,e.getAZs()),MapPublicIpOnLaunch:!0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-public-${C+1}`)},{Key:"Type",Value:"public"}]},{dependsOn:"VPC"})}let y=[];for(let C=0;C<s;C++){let T=`PrivateSubnet${C+1}`;y.push(T),a.addResource(T,"AWS::EC2::Subnet",{VpcId:e.ref("VPC"),CidrBlock:e.select(C+s,e.cidr(e.getAtt("VPC","CidrBlock"),s*2,8)),AvailabilityZone:e.select(C,e.getAZs()),MapPublicIpOnLaunch:!1,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-private-${C+1}`)},{Key:"Type",Value:"private"}]},{dependsOn:"VPC"})}let S=[];for(let C=0;C<c;C++){let T=`NatEIP${C+1}`;S.push(T),a.addResource(T,"AWS::EC2::EIP",{Domain:"vpc",Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-nat-eip-${C+1}`)}]},{dependsOn:"VPCGatewayAttachment"})}let A=[];for(let C=0;C<c;C++){let T=`NatGateway${C+1}`;A.push(T);let v=C%s;a.addResource(T,"AWS::EC2::NatGateway",{AllocationId:e.getAtt(S[C],"AllocationId"),SubnetId:e.ref(h[v]),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-nat-${C+1}`)}]},{dependsOn:[S[C],h[v]]})}a.addResource("PublicRouteTable","AWS::EC2::RouteTable",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-public-rt")}]},{dependsOn:"VPC"}),a.addResource("PublicRoute","AWS::EC2::Route",{RouteTableId:e.ref("PublicRouteTable"),DestinationCidrBlock:"0.0.0.0/0",GatewayId:e.ref("InternetGateway")},{dependsOn:["PublicRouteTable","VPCGatewayAttachment"]}),h.forEach((C,T)=>{a.addResource(`PublicSubnetRouteTableAssociation${T+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:e.ref(C),RouteTableId:e.ref("PublicRouteTable")},{dependsOn:[C,"PublicRouteTable"]})}),y.forEach((C,T)=>{let v=`PrivateRouteTable${T+1}`,w=T%c;a.addResource(v,"AWS::EC2::RouteTable",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-private-rt-${T+1}`)}]},{dependsOn:"VPC"}),a.addResource(`PrivateRoute${T+1}`,"AWS::EC2::Route",{RouteTableId:e.ref(v),DestinationCidrBlock:"0.0.0.0/0",NatGatewayId:e.ref(A[w])},{dependsOn:[v,A[w]]}),a.addResource(`PrivateSubnetRouteTableAssociation${T+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:e.ref(C),RouteTableId:e.ref(v)},{dependsOn:[C,v]})}),a.addResource("S3VPCEndpoint","AWS::EC2::VPCEndpoint",{VpcId:e.ref("VPC"),ServiceName:e.sub("com.amazonaws.${AWS::Region}.s3"),VpcEndpointType:"Gateway",RouteTableIds:[e.ref("PublicRouteTable"),...Array.from({length:s},(C,T)=>e.ref(`PrivateRouteTable${T+1}`))]},{dependsOn:"VPC"}),a.addResource("NetworkAcl","AWS::EC2::NetworkAcl",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-nacl")}]},{dependsOn:"VPC"}),a.addResource("NetworkAclEntryInbound","AWS::EC2::NetworkAclEntry",{NetworkAclId:e.ref("NetworkAcl"),RuleNumber:100,Protocol:-1,RuleAction:"allow",CidrBlock:"0.0.0.0/0"},{dependsOn:"NetworkAcl"}),a.addResource("NetworkAclEntryOutbound","AWS::EC2::NetworkAclEntry",{NetworkAclId:e.ref("NetworkAcl"),RuleNumber:100,Protocol:-1,Egress:!0,RuleAction:"allow",CidrBlock:"0.0.0.0/0"},{dependsOn:"NetworkAcl"}),a.addOutputs({VPCId:{Description:"VPC ID",Value:e.ref("VPC"),Export:{Name:e.sub("${AWS::StackName}-VPC")}},PublicSubnets:{Description:"Public subnet IDs",Value:e.join(",",h.map((C)=>e.ref(C))),Export:{Name:e.sub("${AWS::StackName}-PublicSubnets")}},PrivateSubnets:{Description:"Private subnet IDs",Value:e.join(",",y.map((C)=>e.ref(C))),Export:{Name:e.sub("${AWS::StackName}-PrivateSubnets")}}})}function nn(a,n){for(let[i,s]of Object.entries(n))sn(a,i,s)}function sn(a,n,i){let s=a.toLogicalId(`${n}-queue`),c=i.fifo||!1,l;if(i.deadLetterQueue){let h=`${s}DLQ`;a.addResource(h,"AWS::SQS::Queue",{QueueName:c?e.sub(`\${AWS::StackName}-${n}-dlq.fifo`):e.sub(`\${AWS::StackName}-${n}-dlq`),FifoQueue:c,MessageRetentionPeriod:1209600,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}-dlq`)}]},{deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),l=e.getAtt(h,"Arn")}let u={QueueName:c?e.sub(`\${AWS::StackName}-${n}.fifo`):e.sub(`\${AWS::StackName}-${n}`),FifoQueue:c,VisibilityTimeout:i.visibilityTimeout||30,MessageRetentionPeriod:i.messageRetentionPeriod||345600,ReceiveMessageWaitTimeSeconds:i.receiveMessageWaitTime||0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}`)}]};if(c&&i.contentBasedDeduplication)u.ContentBasedDeduplication=!0;if(i.deadLetterQueue&&l)u.RedrivePolicy={deadLetterTargetArn:l,maxReceiveCount:i.maxReceiveCount||3};if(a.addResource(s,"AWS::SQS::Queue",u,{dependsOn:i.deadLetterQueue?`${s}DLQ`:void 0,deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),a.addResource(`${s}Policy`,"AWS::SQS::QueuePolicy",{Queues:[e.ref(s)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["lambda.amazonaws.com","events.amazonaws.com","sns.amazonaws.com"]},Action:"sqs:SendMessage",Resource:e.getAtt(s,"Arn"),Condition:{ArnEquals:{"aws:SourceArn":e.sub("arn:aws:*:${AWS::Region}:${AWS::AccountId}:*")}}}]}},{dependsOn:s}),a.addOutputs({[`${s}Url`]:{Description:`${n} queue URL`,Value:e.ref(s),Export:{Name:e.sub(`\${AWS::StackName}-${n}-queue-url`)}},[`${s}Arn`]:{Description:`${n} queue ARN`,Value:e.getAtt(s,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${n}-queue-arn`)}}}),i.deadLetterQueue)a.addOutputs({[`${s}DLQUrl`]:{Description:`${n} dead letter queue URL`,Value:e.ref(`${s}DLQ`),Export:{Name:e.sub(`\${AWS::StackName}-${n}-dlq-url`)}}})}function on(a,n){if(n.certificate)cn(a,n.certificate);if(n.waf?.enabled)ln(a,n.waf);if(n.securityGroups)for(let[i,s]of Object.entries(n.securityGroups))un(a,i,s)}function cn(a,n){if(!n)return;let i=[n.domain];if(n.subdomains)i.push(...n.subdomains);a.addResource("Certificate","AWS::CertificateManager::Certificate",{DomainName:n.domain,SubjectAlternativeNames:n.subdomains,ValidationMethod:n.validationMethod||"DNS",DomainValidationOptions:i.map((s)=>({DomainName:s,HostedZoneId:e.ref("HostedZone")})),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-certificate")}]}),a.addOutputs({CertificateArn:{Description:"ACM Certificate ARN",Value:e.ref("Certificate"),Export:{Name:e.sub("${AWS::StackName}-certificate-arn")}}})}function ln(a,n){if(!n)return;let i=[],s=n.rules||["rateLimit","sqlInjection","xss"];if(s.includes("rateLimit"))i.push({Name:"RateLimitRule",Priority:1,Statement:{RateBasedStatement:{Limit:n.rateLimit||2000,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"RateLimitRule"}});let c=i.length+1;if(s.includes("sqlInjection"))i.push({Name:"AWSManagedRulesSQLi",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesSQLiRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesSQLi"}});if(s.includes("xss"))i.push({Name:"AWSManagedRulesXSS",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesXSS"}});if(s.includes("knownBadInputs"))i.push({Name:"AWSManagedRulesKnownBadInputs",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesKnownBadInputs"}});if(s.includes("coreRuleSet"))i.push({Name:"AWSManagedRulesCoreRuleSet",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesCommonRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesCoreRuleSet"}});if(s.includes("linuxRuleSet"))i.push({Name:"AWSManagedRulesLinuxRuleSet",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesLinuxRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesLinuxRuleSet"}});if(s.includes("apiProtection"))i.push({Name:"AWSManagedRulesAPIProtection",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesAmazonIpReputationList"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesAPIProtection"}});if(s.includes("geoBlock"))i.push({Name:"GeoBlockRule",Priority:c++,Statement:{GeoMatchStatement:{CountryCodes:["CN","RU"]}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"GeoBlockRule"}});if(s.includes("connectionLimit"))i.push({Name:"ConnectionLimitRule",Priority:c++,Statement:{RateBasedStatement:{Limit:100,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"ConnectionLimitRule"}});if(a.addResource("WebACL","AWS::WAFv2::WebACL",{Name:e.sub("${AWS::StackName}-waf"),Scope:n.scope||"REGIONAL",DefaultAction:{Allow:{}},Rules:i,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:e.sub("${AWS::StackName}-waf")},Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-waf")}]}),a.hasResource("LoadBalancer"))a.addResource("WebACLAssociation","AWS::WAFv2::WebACLAssociation",{ResourceArn:e.ref("LoadBalancer"),WebACLArn:e.getAtt("WebACL","Arn")},{dependsOn:["WebACL","LoadBalancer"]});a.addOutputs({WebACLId:{Description:"WAF Web ACL ID",Value:e.ref("WebACL"),Export:{Name:e.sub("${AWS::StackName}-waf-id")}},WebACLArn:{Description:"WAF Web ACL ARN",Value:e.getAtt("WebACL","Arn"),Export:{Name:e.sub("${AWS::StackName}-waf-arn")}}})}function un(a,n,i){if(!i)return;let s=a.toLogicalId(`${n}-security-group`),c=i.ingress?.map((u)=>({IpProtocol:u.protocol,FromPort:u.port,ToPort:u.port,CidrIp:u.cidr,SourceSecurityGroupId:u.source?e.ref(u.source):void 0}))||[],l=i.egress?.map((u)=>({IpProtocol:u.protocol,FromPort:u.port,ToPort:u.port,CidrIp:u.cidr||"0.0.0.0/0"}))||[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}];a.addResource(s,"AWS::EC2::SecurityGroup",{GroupDescription:`Security group for ${n}`,VpcId:e.ref("VPC"),SecurityGroupIngress:c,SecurityGroupEgress:l,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}-sg`)}]},{dependsOn:"VPC"}),a.addOutputs({[`${s}Id`]:{Description:`${n} security group ID`,Value:e.ref(s),Export:{Name:e.sub(`\${AWS::StackName}-${n}-sg-id`)}}})}function dn(a,n){for(let[i,s]of Object.entries(n)){if(s.type==="efs"){pn(a,i,s);continue}mn(a,i,s)}}function mn(a,n,i){let s=a.toLogicalId(`${n}-bucket`),c={BucketName:e.sub(`\${AWS::StackName}-${n}`),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}`)}]};if(i.versioning)c.VersioningConfiguration={Status:"Enabled"};if(i.encryption)c.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(!i.public)c.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(i.website)c.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"index.html"};if(i.cors&&i.cors.length>0)c.CorsConfiguration={CorsRules:i.cors.map((l)=>({AllowedOrigins:l.allowedOrigins,AllowedMethods:l.allowedMethods,AllowedHeaders:l.allowedHeaders||["*"],MaxAge:l.maxAge||3600}))};if(i.lifecycleRules&&i.lifecycleRules.length>0)c.LifecycleConfiguration={Rules:i.lifecycleRules.map((l)=>({Id:l.id,Status:l.enabled?"Enabled":"Disabled",ExpirationInDays:l.expirationDays,Transitions:l.transitions?.map((u)=>({TransitionInDays:u.days,StorageClass:u.storageClass}))}))};if(i.intelligentTiering)c.IntelligentTieringConfigurations=[{Id:"EntireBucket",Status:"Enabled",Tierings:[{AccessTier:"ARCHIVE_ACCESS",Days:90},{AccessTier:"DEEP_ARCHIVE_ACCESS",Days:180}]}];if(a.addResource(s,"AWS::S3::Bucket",c,{deletionPolicy:i.versioning?"Retain":"Delete"}),i.public)a.addResource(`${s}Policy`,"AWS::S3::BucketPolicy",{Bucket:e.ref(s),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:"s3:GetObject",Resource:e.join("",[eo.s3Bucket(e.ref(s)),"/*"])}]}},{dependsOn:s});if(a.addOutputs({[`${s}Name`]:{Description:`${n} bucket name`,Value:e.ref(s),Export:{Name:e.sub(`\${AWS::StackName}-${n}-bucket`)}},[`${s}Arn`]:{Description:`${n} bucket ARN`,Value:e.getAtt(s,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${n}-bucket-arn`)}}}),i.website)a.addOutputs({[`${s}WebsiteURL`]:{Description:`${n} website URL`,Value:e.getAtt(s,"WebsiteURL")}})}function pn(a,n,i){let s=a.toLogicalId(`${n}-efs`),c={Encrypted:i.encryption!==!1,PerformanceMode:i.performanceMode||"generalPurpose",ThroughputMode:i.throughputMode||"bursting",FileSystemTags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}`)}]};if(i.lifecyclePolicy){if(c.LifecyclePolicies=[],i.lifecyclePolicy.transitionToIA)c.LifecyclePolicies.push({TransitionToIA:`AFTER_${i.lifecyclePolicy.transitionToIA}_DAYS`});if(i.lifecyclePolicy.transitionToPrimaryStorageClass)c.LifecyclePolicies.push({TransitionToPrimaryStorageClass:"AFTER_1_ACCESS"})}a.addResource(s,"AWS::EFS::FileSystem",c,{deletionPolicy:"Retain"});let l=2;for(let u=0;u<l;u++)a.addResource(`${s}MountTarget${u+1}`,"AWS::EFS::MountTarget",{FileSystemId:e.ref(s),SubnetId:e.ref(`PrivateSubnet${u+1}`),SecurityGroups:[e.ref("EFSSecurityGroup")]},{dependsOn:[s,`PrivateSubnet${u+1}`]});a.addResource("EFSSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for EFS mount targets",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:2049,ToPort:2049,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-efs-sg")}]},{dependsOn:"VPC"}),a.addOutputs({[`${s}Id`]:{Description:`${n} EFS file system ID`,Value:e.ref(s),Export:{Name:e.sub(`\${AWS::StackName}-${n}-efs`)}}})}class $p{template;config;resourceDependencies;constructor(a){this.config=a,this.resourceDependencies=new Map,this.template={AWSTemplateFormatVersion:"2010-09-09",Description:`Infrastructure for ${a.project.name} (${a.project.slug})`,Resources:{}}}build(){return this.addParameters(),this.addMappings(),this.addConditions(),this.addResources(),this.initializeOutputs(),this.resolveDependencies(),this.template}addParameters(){this.template.Parameters={Environment:{Type:"String",Default:"production",AllowedValues:["development","staging","production"],Description:"Environment name"}}}addMappings(){this.template.Mappings={RegionMap:{"us-east-1":{AMI:"ami-0f3caa1cf4417e51b"},"us-west-2":{AMI:"ami-0d1cd67c26f5fca19"},"eu-west-1":{AMI:"ami-0bbc25e23a7640b9b"}}}}addConditions(){this.template.Conditions={IsProduction:e.equals(e.ref("Environment"),"production"),HasDomain:e.not([e.equals(this.config.environments?.production?.domain||"","")])}}addResources(){let{infrastructure:a}=this.config;if(!a)return;if(a.network)this.addNetworkResources(a.network);if(a.storage)this.addStorageResources(a.storage);if(a.compute)this.addComputeResources(a.compute);if(a.databases)this.addDatabaseResources(a.databases);if(a.cache)this.addCacheResources(a.cache);if(a.cdn)this.addCDNResources(a.cdn);if(a.apiGateway)this.addApiGatewayResources(a.apiGateway);if(a.functions)this.addFunctionResources(a.functions);if(a.queues)this.addQueueResources(a.queues);if(a.messaging)this.addMessagingResources(a.messaging);if(a.monitoring)this.addMonitoringResources(a.monitoring);if(a.security)this.addSecurityResources(a.security)}initializeOutputs(){let a=this.template.Outputs||{};if(this.template.Outputs={StackName:{Description:"Stack name",Value:e.ref("AWS::StackName"),Export:{Name:e.sub("${AWS::StackName}-Name")}},Region:{Description:"AWS Region",Value:e.ref("AWS::Region"),Export:{Name:e.sub("${AWS::StackName}-Region")}},...a},this.config.environments?.production?.domain)this.template.Outputs.Domain={Description:"Production domain",Value:this.config.environments.production.domain,Condition:"HasDomain"}}addResource(a,n,i,s){let c={Type:n,Properties:i};if(s?.dependsOn)c.DependsOn=s.dependsOn,this.trackDependency(a,s.dependsOn);if(s?.condition)c.Condition=s.condition;if(s?.deletionPolicy)c.DeletionPolicy=s.deletionPolicy;if(s?.updateReplacePolicy)c.UpdateReplacePolicy=s.updateReplacePolicy;this.template.Resources[a]=c}addOutputs(a){this.template.Outputs={...this.template.Outputs,...a}}getOutputs(){return this.template.Outputs||{}}hasResource(a){return a in this.template.Resources}getResource(a){return this.template.Resources[a]}trackDependency(a,n){if(!this.resourceDependencies.has(a))this.resourceDependencies.set(a,new Set);(Array.isArray(n)?n:[n]).forEach((i)=>this.resourceDependencies.get(a).add(i))}resolveDependencies(){let a=new Set,n=new Set,i=(s)=>{if(n.has(s))throw Error(`Circular dependency detected involving resource: ${s}`);if(a.has(s))return!0;a.add(s),n.add(s);let c=this.resourceDependencies.get(s);if(c)for(let l of c)i(l);return n.delete(s),!0};for(let s of this.resourceDependencies.keys())i(s)}toLogicalId(a){return a.split(/[-_\s]/).map((n)=>n.charAt(0).toUpperCase()+n.slice(1).toLowerCase()).join("")}addNetworkResources(a){rn(this,a)}addStorageResources(a){dn(this,a)}addComputeResources(a){Ur(this,a)}addDatabaseResources(a){jr(this,a)}addFunctionResources(a){Hr(this,a)}addCacheResources(a){Dr(this,a)}addQueueResources(a){nn(this,a)}addMessagingResources(a){Jr(this,a)}addCDNResources(a){Wr(this,a)}addApiGatewayResources(a){wr(this,a)}addMonitoringResources(a){Zr(this,a)}addSecurityResources(a){on(this,a)}}function fd(a){return new $p(a).build()}function jy(a){let{name:n,slug:i,domain:s,subdomain:c}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:c&&s?`${c}.${s}`:s}},infrastructure:{storage:{assets:{public:!0,versioning:!1,website:!0,encryption:!1,cors:[{allowedOrigins:["*"],allowedMethods:["GET","HEAD"],allowedHeaders:["*"],maxAge:3600}]}},cdn:{enabled:!0,customDomain:s?{domain:c&&s?`${c}.${s}`:s,certificateArn:"TO_BE_GENERATED"}:void 0,cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0,errorPages:{404:"/index.html",403:"/index.html"}}}}}function zy(a){let{name:n,slug:i,domain:s,instanceType:c="t3.small",minInstances:l=2,maxInstances:u=10}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:s}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",keyPair:`${i}-key`,autoScaling:{min:l,max:u,desired:l,targetCPU:70},loadBalancer:{type:"application",healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3}},userData:{packages:["nodejs","npm","nginx"],commands:["curl -fsSL https://bun.sh/install | bash","npm install -g pm2"]}}},databases:{postgres:{engine:"postgres",version:"15",instanceClass:"db.t3.micro",allocatedStorage:20,multiAZ:!0,backupRetentionDays:7,deletionProtection:!0}},cache:{redis:{nodeType:"cache.t3.micro",numCacheNodes:1,engine:"redis",engineVersion:"7.0"}},security:{certificate:s?{domain:s,subdomains:[`*.${s}`],validationMethod:"DNS"}:void 0}}}}function Ky(a){let{name:n,slug:i,domain:s,taskCpu:c="256",taskMemory:l="512",desiredCount:u=2}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:s}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:0}},compute:{fargate:{taskDefinition:{cpu:c,memory:l,containerDefinitions:[{name:"app",image:`${i}-app:latest`,portMappings:[{containerPort:3000}],environment:[],secrets:[]}]},service:{desiredCount:u,healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3},autoScaling:{min:u,max:u*5,targetCPU:70,targetMemory:80}},loadBalancer:{type:"application"}}},databases:{dynamodb:{tables:{[`${i}-main`]:{partitionKey:{name:"id",type:"S"},sortKey:{name:"createdAt",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0}}}},functions:{"process-queue":{runtime:"nodejs20.x",handler:"dist/workers/queue.handler",memory:512,timeout:60,events:[{type:"sqs",queueName:`${i}-queue`}]}},security:{certificate:s?{domain:s,subdomains:[`*.${s}`],validationMethod:"DNS"}:void 0}}}}function Wy(a){let{name:n,slug:i,entry:s,domain:c,runtime:l="nodejs20.x",memory:u=1024,build:h,deploy:y,assets:S,queues:A=!0,scheduler:C="on",region:T="us-east-1"}=a;return{project:{name:n,slug:i,region:T},mode:"serverless",environments:{production:{type:"production",domain:c,app:{kind:"node",runtime:l,entry:s,memory:u,build:h,deploy:y,assets:S,queues:A,scheduler:C,domain:c}}}}}function Ad(a){let n=a.database!==!1,i=a.cache!==!1,s=a.queue!==!1;return{project:{name:a.name,slug:a.slug,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:a.domain}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{fargate:{taskDefinition:{cpu:"256",memory:"512",containerDefinitions:[{name:"api",image:a.imageUri,portMappings:[{containerPort:3000}],environment:[{name:"NODE_ENV",value:"production"},{name:"PORT",value:"3000"},{name:"AWS_REGION",value:e.ref("AWS::Region")},...n?[{name:"DB_HOST",value:e.getAtt("PostgresDb","Endpoint.Address")},{name:"DB_PORT",value:e.getAtt("PostgresDb","Endpoint.Port")}]:[],...i?[{name:"REDIS_HOST",value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Address")},{name:"REDIS_PORT",value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Port")},{name:"REDIS_TLS",value:"true"}]:[],...s?[{name:"QUEUE_URL",value:e.ref("JobsQueue")}]:[],{name:"MAIL_TRANSPORT",value:"ses"}],secrets:n?[{name:"DB_USERNAME",valueFrom:e.sub("${DBSecret}:username::")},{name:"DB_PASSWORD",valueFrom:e.sub("${DBSecret}:password::")}]:[]}]},service:{desiredCount:a.desiredCount||1,healthCheck:{path:"/api/health",interval:30,timeout:5},autoScaling:{min:a.desiredCount||1,max:6,targetCPU:70}},loadBalancer:{type:"application",...a.certificateArn?{customDomain:{domain:a.domain,certificateArn:a.certificateArn}}:{},...a.originVerifySecret?{originVerifyHeader:{name:"X-Origin-Verify",value:a.originVerifySecret}}:{}}}},...n?{databases:{postgres:{engine:"postgres",version:"16",instanceClass:"db.t4g.micro",allocatedStorage:20,maxAllocatedStorage:100,multiAZ:!1,backupRetentionDays:7,deletionProtection:!0}}}:{},...i?{cache:{redis:{nodeType:"cache.t4g.micro",numCacheNodes:2,engine:"redis",engineVersion:"7.1",automaticFailoverEnabled:!0,snapshotRetentionLimit:5}}}:{},...s?{queues:{jobs:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0,maxReceiveCount:3,receiveMessageWaitTime:20}}}:{}}}}function Jy(a){let{name:n,slug:i,domain:s,apiSubdomain:c="api"}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:s}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},storage:{frontend:{public:!0,versioning:!0,website:!0,encryption:!1}},cdn:{enabled:!0,customDomain:{domain:s,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0,errorPages:{404:"/index.html"}},compute:{fargate:{taskDefinition:{cpu:"512",memory:"1024",containerDefinitions:[{name:"api",image:`${i}-api:latest`,portMappings:[{containerPort:3000}]}]},service:{desiredCount:2,healthCheck:{path:"/api/health",interval:30},autoScaling:{min:2,max:10,targetCPU:70}},loadBalancer:{type:"application",customDomain:{domain:`${c}.${s}`,certificateArn:"TO_BE_GENERATED"}}}},databases:{postgres:{engine:"postgres",version:"15",instanceClass:"db.t3.small",allocatedStorage:50,multiAZ:!0,backupRetentionDays:14,deletionProtection:!0}},cache:{redis:{nodeType:"cache.t3.small",numCacheNodes:2,engine:"redis",engineVersion:"7.0"}},queues:{jobs:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0}},security:{certificate:{domain:s,subdomains:[`*.${s}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss"]}}}}}function Xy(a){let{name:n,slug:i,domain:s}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:s}},infrastructure:{apiGateway:{type:"HTTP",cors:{allowOrigins:["*"],allowMethods:["GET","POST","PUT","DELETE","PATCH"],allowHeaders:["Content-Type","Authorization"],maxAge:3600},customDomain:s?{domain:s,certificateArn:"TO_BE_GENERATED"}:void 0,throttling:{rateLimit:1e4,burstLimit:5000},authorizer:{type:"JWT",identitySource:"$request.header.Authorization"}},functions:{users:{runtime:"nodejs20.x",handler:"dist/api/users.handler",memory:512,timeout:30,events:[{type:"http",path:"/users",method:"GET"},{type:"http",path:"/users",method:"POST"}]},products:{runtime:"nodejs20.x",handler:"dist/api/products.handler",memory:512,timeout:30,events:[{type:"http",path:"/products",method:"GET"}]}},databases:{dynamodb:{tables:{[`${i}-users`]:{partitionKey:{name:"userId",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0,globalSecondaryIndexes:[{name:"EmailIndex",partitionKey:{name:"email",type:"S"},projection:"ALL"}]},[`${i}-products`]:{partitionKey:{name:"productId",type:"S"},sortKey:{name:"category",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!1}}}},cache:{elasticache:{nodeType:"cache.t3.micro",numCacheNodes:1,engine:"redis",engineVersion:"7.0"}},security:{certificate:s?{domain:s,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","sqlInjection"]}},monitoring:{alarms:[{metric:"Errors",threshold:10,period:300,evaluationPeriods:1},{metric:"Duration",threshold:3000,period:300,evaluationPeriods:2}]}}}}function Yy(a){let{name:n,slug:i,domain:s,instanceType:c="t3.small"}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:s}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",keyPair:`${i}-key`,autoScaling:{min:2,max:6,desired:2,targetCPU:75},loadBalancer:{type:"application",healthCheck:{path:"/wp-admin/install.php",interval:30}},userData:{packages:["nginx","php8.1-fpm","php8.1-mysql","php8.1-curl","php8.1-gd","php8.1-mbstring","php8.1-xml","php8.1-zip"],commands:["cd /var/www","wget https://wordpress.org/latest.tar.gz","tar -xzf latest.tar.gz","chown -R www-data:www-data wordpress","rm /etc/nginx/sites-enabled/default","systemctl restart nginx","systemctl restart php8.1-fpm"]}}},fileSystem:{uploads:{performanceMode:"generalPurpose",throughputMode:"bursting",encrypted:!0,lifecyclePolicy:{transitionToIA:30},mountPath:"/var/www/wordpress/wp-content/uploads"}},databases:{mysql:{engine:"mysql",version:"8.0",instanceClass:"db.t3.small",allocatedStorage:50,multiAZ:!0,backupRetentionDays:7,deletionProtection:!0,databaseName:"wordpress"}},cache:{redis:{nodeType:"cache.t3.micro",numCacheNodes:1,engine:"redis",engineVersion:"7.0"}},cdn:{enabled:!0,customDomain:{domain:s,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,origins:[{type:"alb",pathPattern:"/wp-content/*"}]},security:{certificate:{domain:s,subdomains:[`www.${s}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss","wordpressRules"]}}}}}function Zy(a){let{name:n,slug:i,domain:s,apiDomain:c}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:s}},infrastructure:{storage:{static:{public:!0,versioning:!0,website:!0,encryption:!1,cors:[{allowedOrigins:["*"],allowedMethods:["GET","HEAD"]}],lifecycleRules:[{id:"DeleteOldVersions",enabled:!0,expirationDays:90}]}},cdn:{enabled:!0,customDomain:{domain:s,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:0,maxTTL:31536000},compress:!0,http3:!0,errorPages:{404:"/404.html",500:"/500.html"},edgeFunctions:[{eventType:"origin-request",functionArn:"TO_BE_CREATED",name:"ssr-handler"}]},functions:{ssr:{runtime:"nodejs20.x",handler:"dist/edge/ssr.handler",memory:512,timeout:5},...c?{api:{runtime:"nodejs20.x",handler:"dist/api/index.handler",memory:1024,timeout:30,events:[{type:"http",path:"/{proxy+}",method:"ANY"}]}}:{}},apiGateway:c?{type:"HTTP",customDomain:{domain:c,certificateArn:"TO_BE_GENERATED"},cors:{allowOrigins:[s],allowMethods:["GET","POST","PUT","DELETE"],allowHeaders:["Content-Type","Authorization"]}}:void 0,databases:{dynamodb:{tables:{content:{partitionKey:{name:"id",type:"S"},sortKey:{name:"type",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!1}}}},security:{certificate:{domain:s,subdomains:c?[c]:[],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","geoBlock"]}}}}}function eI(a){let{name:n,slug:i,domain:s,services:c}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:s}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:3,natGateways:2}},compute:{services:c.map((l)=>({name:l.name,type:"fargate",taskDefinition:{cpu:l.cpu||"256",memory:l.memory||"512",containerDefinitions:[{name:l.name,image:`${i}-${l.name}:latest`,portMappings:[{containerPort:l.port}],healthCheck:{command:["CMD-SHELL",`curl -f http://localhost:${l.port}/health || exit 1`],interval:30,timeout:5,retries:3}}]},service:{desiredCount:l.desiredCount||2,serviceDiscovery:{enabled:!0,namespace:`${i}.local`},autoScaling:{min:2,max:10,targetCPU:70}}}))},apiGateway:{type:"HTTP",customDomain:{domain:s,certificateArn:"TO_BE_GENERATED"},cors:{allowOrigins:["*"],allowMethods:["GET","POST","PUT","DELETE","PATCH"]},routes:c.map((l)=>({path:`/${l.name}/{proxy+}`,integration:{type:"vpc-link",service:l.name}}))},databases:{dynamodb:{tables:Object.fromEntries(c.map((l)=>[`${i}-${l.name}`,{partitionKey:{name:"id",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0}]))}},queues:{events:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0}},messaging:{topics:{events:{name:`${i}-events`,subscriptions:c.map((l)=>({protocol:"sqs",endpoint:`${i}-${l.name}-queue`,filterPolicy:{service:[l.name]}}))}}},monitoring:{dashboard:{name:`${i}-microservices`,widgets:c.map((l)=>({type:"metric",metrics:[{service:l.name,metric:"CPUUtilization"},{service:l.name,metric:"MemoryUtilization"},{service:l.name,metric:"RequestCount"}]}))},alarms:c.flatMap((l)=>[{name:`${l.name}-high-cpu`,metric:"CPUUtilization",threshold:80,service:l.name},{name:`${l.name}-errors`,metric:"Errors",threshold:10,service:l.name}])},security:{certificate:{domain:s,validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection"]}}}}}function tI(a){let{name:n,slug:i,domain:s}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:s}},infrastructure:{apiGateway:{type:"websocket",customDomain:s?{domain:s,certificateArn:"TO_BE_GENERATED"}:void 0,routes:[{path:"$connect",method:"WEBSOCKET",integration:"websocket-connect"},{path:"$disconnect",method:"WEBSOCKET",integration:"websocket-disconnect"},{path:"$default",method:"WEBSOCKET",integration:"websocket-default"},{path:"sendMessage",method:"WEBSOCKET",integration:"websocket-send-message"},{path:"joinRoom",method:"WEBSOCKET",integration:"websocket-join-room"}]},functions:{connect:{runtime:"nodejs20.x",handler:"dist/websocket/connect.handler",memory:512,timeout:30},disconnect:{runtime:"nodejs20.x",handler:"dist/websocket/disconnect.handler",memory:512,timeout:30},default:{runtime:"nodejs20.x",handler:"dist/websocket/default.handler",memory:512,timeout:30},"send-message":{runtime:"nodejs20.x",handler:"dist/websocket/sendMessage.handler",memory:512,timeout:30},"join-room":{runtime:"nodejs20.x",handler:"dist/websocket/joinRoom.handler",memory:512,timeout:30},broadcast:{runtime:"nodejs20.x",handler:"dist/streams/broadcast.handler",memory:1024,timeout:60,events:[{type:"dynamodb-stream",tableName:`${i}-messages`,startingPosition:"LATEST",batchSize:100}]}},databases:{dynamodb:{tables:{[`${i}-connections`]:{partitionKey:{name:"connectionId",type:"S"},billingMode:"PAY_PER_REQUEST",globalSecondaryIndexes:[{name:"RoomIndex",partitionKey:{name:"roomId",type:"S"},sortKey:{name:"connectionId",type:"S"},projection:"ALL"}]},[`${i}-messages`]:{partitionKey:{name:"roomId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0,globalSecondaryIndexes:[{name:"UserIndex",partitionKey:{name:"userId",type:"S"},sortKey:{name:"timestamp",type:"S"},projection:"ALL"}]},[`${i}-rooms`]:{partitionKey:{name:"roomId",type:"S"},billingMode:"PAY_PER_REQUEST"}}}},cache:{elasticache:{nodeType:"cache.t3.small",numCacheNodes:2,engine:"redis",engineVersion:"7.0"}},monitoring:{alarms:[{metric:"WebSocketConnections",threshold:1e4,evaluationPeriods:1},{metric:"IntegrationLatency",threshold:1000,evaluationPeriods:2}],dashboard:{name:`${i}-realtime`,widgets:[{type:"metric",metrics:["WebSocketConnections","MessagesSent","IntegrationLatency"]}]}},security:{certificate:s?{domain:s,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","connectionLimit"]}}}}}function rI(a){let{name:n,slug:i,retentionDays:s=7}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",infrastructure:{streaming:{dataStream:{name:`${i}-stream`,shardCount:2,retentionPeriod:s*24,encryption:!0}},storage:{raw:{public:!1,versioning:!0,encryption:!0,intelligentTiering:!0,lifecycleRules:[{id:"ArchiveOldData",enabled:!0,transitions:[{days:30,storageClass:"GLACIER"},{days:90,storageClass:"DEEP_ARCHIVE"}]}]},processed:{public:!1,versioning:!0,encryption:!0,intelligentTiering:!0}},functions:{"stream-processor":{runtime:"nodejs20.x",handler:"dist/processors/stream.handler",memory:2048,timeout:300,events:[{type:"kinesis",streamName:`${i}-stream`,batchSize:1000,startingPosition:"LATEST",parallelizationFactor:10}]},transformer:{runtime:"nodejs20.x",handler:"dist/processors/transform.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${i}-raw`,prefix:"incoming/"}]},aggregator:{runtime:"nodejs20.x",handler:"dist/processors/aggregate.handler",memory:2048,timeout:600,events:[{type:"schedule",expression:"cron(0 * * * ? *)"}]}},analytics:{athena:{database:`${i}_analytics`,workgroup:`${i}-workgroup`,outputBucket:`${i}-query-results`,tables:[{name:"raw_events",location:`s3://${i}-raw/events/`,format:"parquet",partitionKeys:["year","month","day"]},{name:"processed_events",location:`s3://${i}-processed/events/`,format:"parquet",partitionKeys:["year","month","day"]}]},glue:{crawlers:[{name:`${i}-crawler`,databaseName:`${i}_analytics`,s3Targets:[`s3://${i}-raw/`,`s3://${i}-processed/`],schedule:"cron(0 2 * * ? *)"}],jobs:[{name:`${i}-etl-job`,scriptLocation:`s3://${i}-scripts/etl.py`,role:`${i}-glue-role`,maxCapacity:10,timeout:120}]}},databases:{dynamodb:{tables:{[`${i}-metadata`]:{partitionKey:{name:"pipelineId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST"}}}},queues:{failedJobs:{fifo:!1,visibilityTimeout:900,messageRetentionPeriod:1209600,deadLetterQueue:!0,maxReceiveCount:3}},workflow:{pipelines:[{name:`${i}-daily-pipeline`,type:"stepFunctions",definition:{StartAt:"ExtractData",States:{ExtractData:{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Next:"TransformData"},TransformData:{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Next:"LoadData"},LoadData:{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",End:!0}}},schedule:"cron(0 0 * * ? *)"}]},monitoring:{dashboard:{name:`${i}-pipeline`,widgets:[{type:"metric",metrics:["KinesisIncomingRecords","LambdaInvocations","S3ObjectsCreated","GlueJobsSucceeded"]}]},alarms:[{metric:"LambdaErrors",threshold:10,evaluationPeriods:1},{metric:"KinesisIteratorAge",threshold:60000,evaluationPeriods:2}]}}}}function nI(a){let{name:n,slug:i,domain:s,modelS3Path:c=`s3://${i}-models/`,instanceType:l="ml.t3.medium"}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:s}},infrastructure:{storage:{models:{public:!1,versioning:!0,encryption:!0,intelligentTiering:!0},datasets:{public:!1,versioning:!0,encryption:!0,lifecycleRules:[{id:"ArchiveOldDatasets",enabled:!0,transitions:[{days:90,storageClass:"GLACIER"}]}]},predictions:{public:!1,versioning:!1,encryption:!0,lifecycleRules:[{id:"DeleteOldPredictions",enabled:!0,expirationDays:30}]}},machineLearning:{sagemaker:{endpoints:[{name:`${i}-inference`,modelS3Path:c,instanceType:l,initialInstanceCount:1,autoScaling:{minInstances:1,maxInstances:5,targetInvocationsPerInstance:1000}}],trainingJobs:[{name:`${i}-training`,algorithmSpecification:{trainingImage:"TO_BE_SPECIFIED",trainingInputMode:"File"},instanceType:"ml.p3.2xlarge",instanceCount:1,volumeSizeInGB:50,maxRuntimeInSeconds:86400}]}},apiGateway:{type:"HTTP",customDomain:s?{domain:s,certificateArn:"TO_BE_GENERATED"}:void 0,cors:{allowOrigins:["*"],allowMethods:["POST"],allowHeaders:["Content-Type","Authorization"]},throttling:{rateLimit:1000,burstLimit:500}},functions:{predict:{runtime:"python3.11",handler:"handlers/predict.handler",memory:2048,timeout:60,events:[{type:"http",path:"/predict",method:"POST"}],environment:{SAGEMAKER_ENDPOINT:`${i}-inference`,MODEL_BUCKET:`${i}-models`}},"batch-predict":{runtime:"python3.11",handler:"handlers/batchPredict.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${i}-datasets`,suffix:".csv"}]},"trigger-training":{runtime:"python3.11",handler:"handlers/training.handler",memory:1024,timeout:300,events:[{type:"schedule",expression:"cron(0 2 * * ? *)"}]}},databases:{dynamodb:{tables:{[`${i}-predictions`]:{partitionKey:{name:"requestId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0},[`${i}-models`]:{partitionKey:{name:"modelId",type:"S"},sortKey:{name:"version",type:"S"},billingMode:"PAY_PER_REQUEST"}}}},queues:{predictions:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:86400,deadLetterQueue:!0}},monitoring:{dashboard:{name:`${i}-ml`,widgets:[{type:"metric",metrics:["SageMakerInvocations","SageMakerModelLatency","APIGatewayRequests","LambdaErrors"]}]},alarms:[{metric:"SageMakerModelLatency",threshold:1000,evaluationPeriods:2},{metric:"SageMakerInvocationErrors",threshold:10,evaluationPeriods:1}]},security:{certificate:s?{domain:s,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","apiProtection"]}}}}}function iI(a){let{name:n,slug:i,domain:s,instanceType:c="t3.medium",minInstances:l=2,maxInstances:u=10,databaseEngine:h="mysql",sessionStore:y="redis"}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:s}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:2}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",autoScaling:{min:l,max:u,targetCPU:70,scaleUpCooldown:300,scaleDownCooldown:300},loadBalancer:{type:"application",healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3},stickySession:{enabled:!0,duration:86400}},userData:`#!/bin/bash
2490
2490
  # Install Node.js or PHP/Python based on app needs
2491
2491
  # Configure application server (PM2, Nginx, Apache)
2492
2492
  # Mount EFS for shared file storage
2493
- `}},storage:{uploads:{type:"efs",performanceMode:"generalPurpose",throughputMode:"bursting",encrypted:!0,lifecyclePolicy:{transitionToIA:30}},backups:{public:!1,versioning:!0,encryption:!0,lifecycleRules:[{id:"ArchiveOldBackups",enabled:!0,transitions:[{days:90,storageClass:"GLACIER"}]}]},static:{public:!0,versioning:!1,encryption:!1,cors:[{allowedOrigins:[s||"*"],allowedMethods:["GET","HEAD"]}]}},cdn:{enabled:!0,origins:[{originId:"static-assets",domainName:`${i}-static.s3.amazonaws.com`,pathPattern:"/static/*"}],customDomain:s?{domain:s,certificateArn:"TO_BE_GENERATED"}:void 0,cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0},databases:h==="mysql"?{mysql:{engine:"mysql",version:"8.0",instanceClass:"db.t3.medium",allocatedStorage:100,maxAllocatedStorage:500,multiAZ:!0,backupRetentionDays:14,preferredBackupWindow:"03:00-04:00",preferredMaintenanceWindow:"sun:04:00-sun:05:00",enablePerformanceInsights:!0,performanceInsightsRetention:7,deletionProtection:!0,parameters:{max_connections:"500",innodb_buffer_pool_size:"{DBInstanceClassMemory*3/4}",slow_query_log:"1",long_query_time:"2"}}}:{postgres:{engine:"postgres",version:"15",instanceClass:"db.t3.medium",allocatedStorage:100,maxAllocatedStorage:500,multiAZ:!0,backupRetentionDays:14,preferredBackupWindow:"03:00-04:00",preferredMaintenanceWindow:"sun:04:00-sun:05:00",enablePerformanceInsights:!0,performanceInsightsRetention:7,deletionProtection:!0,parameters:{max_connections:"500",shared_buffers:"{DBInstanceClassMemory/4}",log_min_duration_statement:"2000"}}},cache:y==="redis"?{redis:{nodeType:"cache.t3.medium",numCacheNodes:2,engine:"redis",engineVersion:"7.0",port:6379,parameterGroup:{maxmemoryPolicy:"allkeys-lru",timeout:"300"},snapshotRetentionLimit:5,snapshotWindow:"03:00-05:00",automaticFailoverEnabled:!0}}:void 0,queues:{jobs:{fifo:!1,visibilityTimeout:900,messageRetentionPeriod:345600,receiveMessageWaitTime:20,deadLetterQueue:!0,maxReceiveCount:3},emails:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:86400,deadLetterQueue:!0}},functions:{"job-worker":{runtime:"nodejs20.x",handler:"dist/workers/jobs.handler",memory:2048,timeout:900,events:[{type:"sqs",queueName:`${i}-jobs`,batchSize:10}]},"email-sender":{runtime:"nodejs20.x",handler:"dist/workers/email.handler",memory:512,timeout:60,events:[{type:"sqs",queueName:`${i}-emails`,batchSize:10}]},cleanup:{runtime:"nodejs20.x",handler:"dist/tasks/cleanup.handler",memory:512,timeout:300,events:[{type:"schedule",expression:"cron(0 2 * * ? *)"}]}},monitoring:{dashboard:{name:`${i}-web-app`,widgets:[{type:"metric",metrics:["EC2CPUUtilization","ALBRequestCount","ALBTargetResponseTime","RDSCPUUtilization","RDSDatabaseConnections","RDSReadLatency","RDSWriteLatency"]}]},alarms:[{metric:"EC2CPUUtilization",threshold:80,evaluationPeriods:2},{metric:"RDSCPUUtilization",threshold:80,evaluationPeriods:2},{metric:"RDSDatabaseConnections",threshold:400,evaluationPeriods:1},{metric:"ALBTargetResponseTime",threshold:2000,evaluationPeriods:2},{metric:"ALBUnhealthyHostCount",threshold:1,evaluationPeriods:1}],logs:{retention:14,groups:[`${i}-app`,`${i}-nginx`,`${i}-workers`]}},security:{certificate:s?{domain:s,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss","knownBadInputs"]},securityGroups:{alb:{ingress:[{port:80,protocol:"tcp",cidr:"0.0.0.0/0"},{port:443,protocol:"tcp",cidr:"0.0.0.0/0"}]},app:{ingress:[{port:3000,protocol:"tcp",source:"alb-sg"}]},database:{ingress:[{port:h==="mysql"?3306:5432,protocol:"tcp",source:"app-sg"}]},...y==="redis"&&{cache:{ingress:[{port:6379,protocol:"tcp",source:"app-sg"}]}}}}}}}function sI(a){let{name:n,slug:i,domain:s,repository:c,phpVersion:l="8.3",size:u="small",database:h=i.replace(/-/g,"_"),databasePassword:y,sslEmail:S,deployStrategy:b="push",provider:A="hetzner"}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"server",cloud:{provider:A},environments:{production:{type:"production",domain:s}},infrastructure:{compute:{mode:"server",size:u,runtime:"php",webServer:"nginx",php:{versions:[l],default:l},managedServices:{mysql:!0,redis:!0},firewall:{enabled:!0},autoUpdates:!0,monitoring:!0,backups:{enabled:!0,schedule:"0 2 * * *",retentionCount:7}},appDatabase:{engine:"mysql",name:h,username:h,password:y}},sites:{main:{root:".",type:"laravel",domain:s,phpVersion:l,repository:{...c,strategy:b},scheduler:!0,queues:[{connection:"redis",queue:"default",processes:1}],ssl:{provider:"letsencrypt",email:S}}}}}function oI(a){let{name:n,slug:i,domain:s,layers:c,phpVersion:l="8.3",architecture:u="x86_64",memory:h=1024,build:y,deploy:S=["migrate --force"],cache:b="dynamodb",scheduler:A="on",region:C="us-east-1"}=a;return{project:{name:n,slug:i,region:C},mode:"serverless",environments:{production:{type:"production",domain:s,app:{kind:"php",runtime:"provided.al2023",phpVersion:l,architecture:u,layers:c,memory:h,build:y,deploy:S,assets:"public",queues:!0,scheduler:A,cache:{driver:b},domain:s}}}}}function aI(a){return{root:a.root??"packages/ui/dist",deploy:"server",type:"static",domain:a.domain,build:a.build??"cd packages/ui && bun install && bun run build",ssl:{provider:"letsencrypt"},auth:{username:a.username??"admin",password:a.password}}}var bf=_p,Ef="./node_modules/@stacksjs/ts-cloud/dist/bin/dashboard-server.js";function gn(a){let n=a.split(".").filter(Boolean);return n.length<=2?a:n.slice(-2).join(".")}function hn(a){let n=2166136261;for(let i=0;i<a.length;i++)n^=a.charCodeAt(i),n=Math.imul(n,16777619);return n>>>0}var vf=20000,Tf=12000;function wf(a){return vf+hn(a)%Tf}function Ea(a,n){let i=gn(a);if(i===a)return`dashboard.${i}`;for(let s of n)if(s===i)return`dashboard.${i}`;return`dashboard.${a}`}function Pa(a,n){let i=[],s=a.infrastructure?.dns?.domain;if(s&&!a.cloud?.attachTo)i.push(s);if(n&&a.environments?.[n]?.domain)i.push(a.environments[n].domain);for(let c of Object.values(a.sites??{})){let l=c;if(!l||l.redirect)continue;let u=l.domain;if(typeof u==="string")i.push(u);else if(Array.isArray(u))i.push(...u.filter((h)=>typeof h==="string"))}return i.filter((c)=>c&&!c.startsWith("dashboard."))}function Rf(a,n,i){if(i)return i;let s=Pa(a,n),c=s[0];if(!c)return null;return Ea(c,s)}function Df(a,n,i){if(i)return[i];let s=Pa(a,n),c=[];for(let l of s){let u=Ea(l,s);if(!c.includes(u))c.push(u)}return c}function Ht(a){return Object.entries(a.sites??{}).some(([n,i])=>{if(!i)return!1;let s=i.root??"";return _r(n)||s==="ui/dist"||s.endsWith("/ui/dist")||s.endsWith("/dist/ui")})}var Mp="dashboard-";function Fp(a){return Mp+a.replace(/^dashboard\./,"").replace(/\./g,"-")}function _r(a){return a==="dashboard"||a.startsWith(Mp)}function yi(a,n,i){if(Ht(a))return[];if(a.cloud?.attachTo)return[];let s=i.password?{auth:{username:i.username||"admin",password:i.password,realm:i.realm}}:{},c=i.build===!1||i.build===void 0?{}:{build:i.build};if(i.live!==!1){let l=Rf(a,n,i.domain);if(!l)return[];let u=i.port??wf(l),h=a.infrastructure?.appDatabase??a.infrastructure?.compute?.database,y={root:i.uiRoot,deploy:"server",domain:l,preStart:["bun install --production --no-save"],start:`bun ${Ef} --box --host 127.0.0.1 --port ${u}`,port:u,cpuWeight:10,ioWeight:10,tasksMax:128,env:{APP_ENV:"production",NODE_ENV:"production",TS_CLOUD_DASHBOARD_TELEMETRY:"1",...h?.password?{TS_CLOUD_DASHBOARD_DB_PASSWORD:h.password}:{}},zeroDowntime:!1,sharedPaths:[bf],healthCheck:{path:"/login"},ssl:{provider:"letsencrypt"}};return[{name:Fp(l),site:y}]}return Df(a,n,i.domain).map((l)=>({name:Fp(l),site:{root:i.uiRoot,deploy:"server",type:"static",domain:l,ssl:{provider:"letsencrypt"},...c,...s}}))}function cI(a,n,i){return yi(a,n,i)[0]??null}function Bt(a,n){let i={...a};for(let s in n){let c=n[s],l=i[s];if(c===void 0)continue;if(Array.isArray(c)&&Array.isArray(l))i[s]=[...l,...c];else if(typeof c==="object"&&c!==null&&!Array.isArray(c)&&typeof l==="object"&&l!==null&&!Array.isArray(l))i[s]=Bt(l,c);else i[s]=c}return i}function Up(a,n){return Bt(a,n)}function dI(...a){return a.reduce((n,i)=>Bt(n,i),{})}function lI(a,n){return(i)=>{let s=a(i);if(typeof n==="function")return Up(s,n(s,i));return Up(s,n)}}function Or(a){return{infrastructure:a}}function uI(a){return Or({monitoring:a})}function pI(a){return Or({security:a})}function gI(a){return Or({databases:a})}function mI(a){return Or({cache:a})}function hI(a){return Or({cdn:a})}function fI(a){return Or({queues:a})}et();function Pf(){let a=process.env.AWS_ACCESS_KEY_ID,n=process.env.AWS_SECRET_ACCESS_KEY;if(!a||!n)return null;return{accessKeyId:a,secretAccessKey:n,sessionToken:process.env.AWS_SESSION_TOKEN}}function Nf(a){let n=a?.profile||process.env.AWS_PROFILE||"default",i=a?.credentialsFile||Na(Ra(),".aws","credentials");if(!Ia(i))return null;try{let s=_t(i,"utf-8");return yn(s,n)}catch{return null}}function yn(a,n){let i=a.split(`
2494
- `),s=null,c,l,u;for(let h of i){let y=h.trim();if(!y||y.startsWith("#")||y.startsWith(";"))continue;let S=y.match(/^\[([^\]]+)\]$/);if(S){if(s===n&&c&&l)return{accessKeyId:c,secretAccessKey:l,sessionToken:u};s=S[1],c=void 0,l=void 0,u=void 0;continue}if(s===n){let[b,...A]=y.split("="),C=A.join("=").trim();switch(b.trim().toLowerCase()){case"aws_access_key_id":c=C;break;case"aws_secret_access_key":l=C;break;case"aws_session_token":u=C;break}}}if(s===n&&c&&l)return{accessKeyId:c,secretAccessKey:l,sessionToken:u};return null}async function kf(a){let n=a?.timeout??1000,i="http://169.254.169.254";try{let s=await Ye("http://169.254.169.254/latest/api/token",{method:"PUT",headers:{"X-aws-ec2-metadata-token-ttl-seconds":"21600"}},n);if(!s.ok)return null;let c=await s.text(),l=await Ye("http://169.254.169.254/latest/meta-data/iam/security-credentials/",{headers:{"X-aws-ec2-metadata-token":c}},n);if(!l.ok)return null;let u=(await l.text()).trim(),h=await Ye(`http://169.254.169.254/latest/meta-data/iam/security-credentials/${u}`,{headers:{"X-aws-ec2-metadata-token":c}},n);if(!h.ok)return null;let y=await h.json();return{accessKeyId:y.AccessKeyId,secretAccessKey:y.SecretAccessKey,sessionToken:y.Token,expiration:new Date(y.Expiration)}}catch{return null}}async function Bf(a){let n=a?.timeout??1000,i=process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI,s=process.env.AWS_CONTAINER_CREDENTIALS_FULL_URI,c=null;if(i)c=`http://169.254.170.2${i}`;else if(s)c=s;if(!c)return null;try{let l={},u=process.env.AWS_CONTAINER_AUTHORIZATION_TOKEN;if(u)l.Authorization=u;let h=await Ye(c,{headers:l},n);if(!h.ok)return null;let y=await h.json();return{accessKeyId:y.AccessKeyId,secretAccessKey:y.SecretAccessKey,sessionToken:y.Token,expiration:new Date(y.Expiration)}}catch{return null}}async function xf(a){let n=a?.timeout??5000,i=process.env.AWS_WEB_IDENTITY_TOKEN_FILE,s=process.env.AWS_ROLE_ARN,c=process.env.AWS_ROLE_SESSION_NAME||"ts-cloud-session";if(!i||!s)return null;try{let l=_t(i,"utf-8").trim(),u=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION||"us-east-1",h=u.startsWith("us-gov")?`https://sts.${u}.amazonaws.com`:u==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${u}.amazonaws.com`,y=new URLSearchParams({Action:"AssumeRoleWithWebIdentity",Version:"2011-06-15",RoleArn:s,RoleSessionName:c,WebIdentityToken:l}),S=await Ye(`${h}/?${y.toString()}`,{method:"POST"},n);if(!S.ok)return null;let b=await S.text(),A=Qe(b,"AccessKeyId"),C=Qe(b,"SecretAccessKey"),T=Qe(b,"SessionToken"),v=Qe(b,"Expiration");if(!A||!C)return null;return{accessKeyId:A,secretAccessKey:C,sessionToken:T??void 0,expiration:v?new Date(v):void 0}}catch{return null}}async function to(a){let n=Pf();if(n)return n;let i=Nf(a);if(i)return i;let s=await xf(a);if(s)return s;let c=await Bf(a);if(c)return c;let l=await kf(a);if(l)return l;throw Error("Could not find AWS credentials. Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables, or configure ~/.aws/credentials, or run on an EC2 instance with an IAM role.")}function yI(a){let n=null,i=null;return async()=>{if(n){if(!n.expiration)return n;let s=300000;if(n.expiration.getTime()-Date.now()>s)return n}if(i)return i;return i=to(a).then((s)=>(n=s,i=null,s)).catch((s)=>{throw i=null,s}),i}}async function Ye(a,n,i){let s=new AbortController,c=setTimeout(()=>s.abort(),i);try{let l=await fetch(a,{...n,signal:s.signal});return clearTimeout(c),l}catch(l){throw clearTimeout(c),l}}function Qe(a,n){let i=new RegExp(`<${n}>([^<]+)</${n}>`),s=a.match(i);return s?s[1]:null}async function _f(a){return to({profile:a})}function Of(a){let n=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION;if(n)return n;let i=Na(Ra(),".aws","config");if(Ia(i))try{let s=_t(i,"utf-8"),c=a||process.env.AWS_PROFILE||"default",l=c==="default"?"[default]":`[profile ${c}]`,u=s.split(`
2495
- `),h=!1;for(let y of u){let S=y.trim();if(S.startsWith("[")){h=S===l;continue}if(h&&S.startsWith("region")){let[,b]=S.split("=");if(b)return b.trim()}}}catch{}return"us-east-1"}async function Lf(a){let n=a||await to(),i=Of();await et();let s=i.startsWith("us-gov")?`https://sts.${i}.amazonaws.com`:i==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${i}.amazonaws.com`,c="Action=GetCallerIdentity&Version=2011-06-15",l=x({method:"POST",url:s,body:"Action=GetCallerIdentity&Version=2011-06-15",headers:{"Content-Type":"application/x-www-form-urlencoded"},...n,service:"sts",region:i}),u=await fetch(l.url,{method:l.method,headers:l.headers,body:l.body});if(!u.ok)throw Error(`Failed to get account ID: ${await u.text()}`);let h=await u.text(),y=Qe(h,"Account");if(!y)throw Error("Failed to parse account ID from response");return y}await et();await et();var fn=5242880,Pt=5242880,Sn=5242880;class Da{region;endpoint;forcePathStyle;credentials;credentialOptions;retryOptions;constructor(a={}){this.region=a.region||process.env.AWS_REGION||"us-east-1",this.endpoint=a.endpoint||`https://s3.${this.region}.amazonaws.com`,this.forcePathStyle=a.forcePathStyle||!1,this.credentials=a.credentials,this.credentialOptions=a.credentialOptions,this.retryOptions=a.retryOptions||{}}async getCredentials(){if(this.credentials)return this.credentials;return to(this.credentialOptions)}buildUrl(a,n){let i=n?encodeURIComponent(n).replace(/%2F/g,"/"):"";if(this.forcePathStyle)return n?`${this.endpoint}/${a}/${i}`:`${this.endpoint}/${a}`;let s=new URL(this.endpoint);return s.hostname=`${a}.${s.hostname}`,n?`${s.origin}/${i}`:s.origin}async get(a,n,i={}){let s=await this.getCredentials(),c=this.buildUrl(a,n),l={};if(i.range)l.Range=i.range;if(i.ifModifiedSince)l["If-Modified-Since"]=i.ifModifiedSince.toUTCString();if(i.ifMatch)l["If-Match"]=i.ifMatch;if(i.ifNoneMatch)l["If-None-Match"]=i.ifNoneMatch;let u=new URL(c);if(i.responseContentType)u.searchParams.set("response-content-type",i.responseContentType);if(i.responseContentDisposition)u.searchParams.set("response-content-disposition",i.responseContentDisposition);let h=x({method:"GET",url:u.toString(),headers:l,...s,service:"s3",region:this.region}),y=await fetch(h.url,{method:h.method,headers:h.headers});if(!y.ok&&y.status!==304){let S=await y.text();throw new G(`Failed to get object: ${S}`,y.status,a,n)}return y}async getText(a,n,i={}){return(await this.get(a,n,i)).text()}async getJSON(a,n,i={}){return(await this.get(a,n,i)).json()}async getBuffer(a,n,i={}){return(await this.get(a,n,i)).arrayBuffer()}async put(a,n,i,s={}){let c,l;if(typeof i==="string")c=new TextEncoder().encode(i).length,l=i;else if(i instanceof ArrayBuffer)c=i.byteLength,l=i;else if(i instanceof Uint8Array)c=i.byteLength,l=i;else if(i instanceof Blob)c=i.size,l=i;else return this.uploadMultipart(a,n,i,{...s,partSize:Pt});if(c>Sn){let u=Cn(l).stream();return this.uploadMultipart(a,n,u,{...s,partSize:Pt})}return this.putSimple(a,n,l,c,s)}async putSimple(a,n,i,s,c){let l=await this.getCredentials(),u=this.buildUrl(a,n),h={"Content-Length":String(s),"Content-Type":c.contentType||la(n)};if(c.contentEncoding)h["Content-Encoding"]=c.contentEncoding;if(c.cacheControl)h["Cache-Control"]=c.cacheControl;if(c.contentDisposition)h["Content-Disposition"]=c.contentDisposition;if(c.storageClass)h["x-amz-storage-class"]=c.storageClass;if(c.serverSideEncryption)h["x-amz-server-side-encryption"]=c.serverSideEncryption;if(c.acl)h["x-amz-acl"]=c.acl;if(c.tagging)h["x-amz-tagging"]=c.tagging;if(c.metadata)for(let[A,C]of Object.entries(c.metadata))h[`x-amz-meta-${A.toLowerCase()}`]=C;let y;if(typeof i==="string")y=i;else if(i instanceof Blob)y=await i.text();else y=new TextDecoder().decode(i instanceof ArrayBuffer?new Uint8Array(i):i);let S=x({method:"PUT",url:u,headers:h,body:y,...l,service:"s3",region:this.region}),b=await fetch(S.url,{method:S.method,headers:S.headers,body:i});if(!b.ok){let A=await b.text();throw new G(`Failed to put object: ${A}`,b.status,a,n)}return{etag:(b.headers.get("ETag")||"").replace(/"/g,"")}}async delete(a,n){let i=await this.getCredentials(),s=this.buildUrl(a,n),c=x({method:"DELETE",url:s,...i,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(!l.ok&&l.status!==204){let u=await l.text();throw new G(`Failed to delete object: ${u}`,l.status,a,n)}}async deleteMany(a,n){let i=await this.getCredentials(),s=`${this.buildUrl(a)}?delete`,c=`<?xml version="1.0" encoding="UTF-8"?><Delete><Quiet>false</Quiet>${n.map((T)=>`<Object><Key>${An(T)}</Key></Object>`).join("")}</Delete>`,l=x({method:"POST",url:s,headers:{"Content-Type":"application/xml"},body:c,...i,service:"s3",region:this.region}),u=await fetch(l.url,{method:l.method,headers:l.headers,body:c});if(!u.ok){let T=await u.text();throw new G(`Failed to delete objects: ${T}`,u.status,a)}let h=await u.text(),y=[],S=[],b=/<Deleted><Key>([^<]+)<\/Key>/g,A;while((A=b.exec(h))!==null)y.push(A[1]);let C=/<Error><Key>([^<]+)<\/Key><Code>([^<]+)<\/Code><Message>([^<]+)<\/Message>/g;while((A=C.exec(h))!==null)S.push({key:A[1],error:`${A[2]}: ${A[3]}`});return{deleted:y,errors:S}}async list(a,n={}){let i=await this.getCredentials(),s=new URL(this.buildUrl(a));if(s.searchParams.set("list-type","2"),n.prefix)s.searchParams.set("prefix",n.prefix);if(n.delimiter)s.searchParams.set("delimiter",n.delimiter);if(n.maxKeys)s.searchParams.set("max-keys",String(n.maxKeys));if(n.continuationToken)s.searchParams.set("continuation-token",n.continuationToken);if(n.startAfter)s.searchParams.set("start-after",n.startAfter);let c=x({method:"GET",url:s.toString(),...i,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(!l.ok){let h=await l.text();throw new G(`Failed to list objects: ${h}`,l.status,a)}let u=await l.text();return bn(u)}async*listAll(a,n={}){let i;do{let s=await this.list(a,{...n,continuationToken:i});for(let c of s.contents)yield c;i=s.nextContinuationToken}while(i)}async head(a,n){let i=await this.getCredentials(),s=this.buildUrl(a,n),c=x({method:"HEAD",url:s,...i,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(l.status===404)return null;if(!l.ok){let h=await l.text();throw new G(`Failed to head object: ${h}`,l.status,a,n)}let u={};return l.headers.forEach((h,y)=>{if(y.toLowerCase().startsWith("x-amz-meta-"))u[y.slice(11)]=h}),{contentLength:Number(l.headers.get("Content-Length")||0),contentType:l.headers.get("Content-Type")||"application/octet-stream",etag:(l.headers.get("ETag")||"").replace(/"/g,""),lastModified:new Date(l.headers.get("Last-Modified")||0),metadata:u,storageClass:l.headers.get("x-amz-storage-class")||void 0,serverSideEncryption:l.headers.get("x-amz-server-side-encryption")||void 0}}async exists(a,n){return await this.head(a,n)!==null}async copy(a,n,i,s,c={}){let l=await this.getCredentials(),u=this.buildUrl(i,s),h={"x-amz-copy-source":`/${a}/${encodeURIComponent(n)}`};if(c.metadataDirective)h["x-amz-metadata-directive"]=c.metadataDirective;if(c.contentType)h["Content-Type"]=c.contentType;if(c.storageClass)h["x-amz-storage-class"]=c.storageClass;if(c.acl)h["x-amz-acl"]=c.acl;if(c.metadata)for(let[A,C]of Object.entries(c.metadata))h[`x-amz-meta-${A.toLowerCase()}`]=C;let y=x({method:"PUT",url:u,headers:h,...l,service:"s3",region:this.region}),S=await fetch(y.url,{method:y.method,headers:y.headers});if(!S.ok){let A=await S.text();throw new G(`Failed to copy object: ${A}`,S.status,i,s)}let b=(await S.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:b?b[1]:""}}async getPresignedUrl(a,n,i={}){let s=await this.getCredentials(),c=this.buildUrl(a,n);return hf({url:c,method:i.method||"GET",expiresIn:i.expiresIn||3600,...s,service:"s3",region:this.region})}async uploadMultipart(a,n,i,s={}){let c=await this.getCredentials(),l=Math.max(s.partSize||Pt,fn),u,h;if(i instanceof ReadableStream)u=i;else if(i instanceof Blob)u=i.stream(),h=i.size;else{let b=new Blob([i]);u=b.stream(),h=b.size}let{uploadId:y,baseUrl:S}=await this.initiateMultipartUpload(a,n,s);try{let b=await this.uploadParts(a,n,S,y,u,l,c,h,s.concurrency||4,s.onProgress);return await this.completeMultipartUpload(a,n,S,y,b)}catch(b){throw await this.abortMultipartUpload(a,n,y,S).catch(()=>{}),b}}async initiateMultipartUpload(a,n,i){let s=await this.getCredentials(),c=this.buildUrl(a,n),l=`${c}?uploads`,u={"Content-Type":i.contentType||la(n)};if(i.storageClass)u["x-amz-storage-class"]=i.storageClass;if(i.serverSideEncryption)u["x-amz-server-side-encryption"]=i.serverSideEncryption;if(i.acl)u["x-amz-acl"]=i.acl;if(i.metadata)for(let[A,C]of Object.entries(i.metadata))u[`x-amz-meta-${A.toLowerCase()}`]=C;let h=x({method:"POST",url:l,headers:u,...s,service:"s3",region:this.region}),y=await fetch(h.url,{method:h.method,headers:h.headers});if(!y.ok){let A=await y.text();throw new G(`Failed to initiate multipart upload: ${A}`,y.status,a,n)}let S=(await y.text()).match(/<UploadId>([^<]+)<\/UploadId>/);if(!S)throw new G("Failed to parse upload ID from response",0,a,n);let b=c;if(y.url)try{let A=new URL(y.url);A.search="",b=A.toString()}catch{}return{uploadId:S[1],baseUrl:b}}async uploadParts(a,n,i,s,c,l,u,h,y,S){let b=[],A=c.getReader(),C=1,T=new Uint8Array(0),v=0,w=h?Math.ceil(h/l):void 0,R=new Map,k=async(P,V)=>{let B=`${i}?partNumber=${V}&uploadId=${encodeURIComponent(s)}`,j={"Content-Length":String(P.byteLength),"x-amz-content-sha256":"UNSIGNED-PAYLOAD"},J=x({method:"PUT",url:B,headers:j,...u,service:"s3",region:this.region}),K=await fetch(J.url,{method:J.method,headers:J.headers,body:P,redirect:"error"});if(!K.ok){let te=await K.text();throw new G(`Failed to upload part ${V}: ${te}`,K.status,a,n)}let X=(K.headers.get("ETag")||"").replace(/"/g,"");if(!X)throw new G(`Missing ETag for part ${V}`,K.status,a,n);return{partNumber:V,etag:X}},W=async()=>{let P=await Promise.race(R.values());R.delete(P.partNumber),b.push(P)};while(!0){let{done:P,value:V}=await A.read();if(V){let B=new Uint8Array(T.length+V.length);B.set(T),B.set(V,T.length),T=B}while(T.length>=l||P&&T.length>0){let B=T.slice(0,l);T=T.slice(l);let j=C++;if(R.size>=y)await W();if(R.set(j,k(B,j)),v+=B.byteLength,S)S({loaded:v,total:h||v,part:j,totalParts:w||j})}if(P)break}while(R.size>0)await W();return b.sort((P,V)=>P.partNumber-V.partNumber),b}async completeMultipartUpload(a,n,i,s,c){let l=await this.getCredentials(),u=`${i}?uploadId=${encodeURIComponent(s)}`,h=`<?xml version="1.0" encoding="UTF-8"?><CompleteMultipartUpload>${c.map((A)=>`<Part><PartNumber>${A.partNumber}</PartNumber><ETag>"${A.etag}"</ETag></Part>`).join("")}</CompleteMultipartUpload>`,y=x({method:"POST",url:u,headers:{"Content-Type":"application/xml"},body:h,...l,service:"s3",region:this.region}),S=await fetch(y.url,{method:y.method,headers:y.headers,body:h});if(!S.ok){let A=await S.text();throw new G(`Failed to complete multipart upload: ${A}`,S.status,a,n)}let b=(await S.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:b?b[1]:""}}async abortMultipartUpload(a,n,i,s){let c=await this.getCredentials(),l=`${s??this.buildUrl(a,n)}?uploadId=${encodeURIComponent(i)}`,u=x({method:"DELETE",url:l,...c,service:"s3",region:this.region});await fetch(u.url,{method:u.method,headers:u.headers})}async emptyAndDeleteBucket(a){let n=[];for await(let l of this.listAll(a,{}))if(n.push(l.key),n.length>=1000)await this.deleteMany(a,n),n=[];if(n.length>0)await this.deleteMany(a,n);let i=await this.getCredentials(),s=this.buildUrl(a),c=x({method:"DELETE",url:s,...i,service:"s3",region:this.region});await fetch(c.url,{method:c.method,headers:c.headers})}}class G extends Error{statusCode;bucket;key;constructor(a,n,i,s){super(a);this.statusCode=n,this.bucket=i,this.key=s,this.name="S3Error"}}function bn(a){let n=[],i=[],s=/<Contents>([\s\S]*?)<\/Contents>/g,c;while((c=s.exec(a))!==null){let u=c[1];n.push({key:ce(u,"Key")||"",lastModified:new Date(ce(u,"LastModified")||0),etag:(ce(u,"ETag")||"").replace(/"/g,""),size:Number(ce(u,"Size")||0),storageClass:ce(u,"StorageClass")||"STANDARD"})}let l=/<CommonPrefixes><Prefix>([^<]+)<\/Prefix><\/CommonPrefixes>/g;while((c=l.exec(a))!==null)i.push(c[1]);return{contents:n,commonPrefixes:i,isTruncated:ce(a,"IsTruncated")==="true",continuationToken:ce(a,"ContinuationToken")||void 0,nextContinuationToken:ce(a,"NextContinuationToken")||void 0,keyCount:Number(ce(a,"KeyCount")||0),maxKeys:Number(ce(a,"MaxKeys")||1000),prefix:ce(a,"Prefix")||void 0,delimiter:ce(a,"Delimiter")||void 0}}function ce(a,n){let i=new RegExp(`<${n}>([^<]*)</${n}>`),s=a.match(i);return s?s[1]:null}function An(a){return a.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function la(a){let n=a.split(".").pop()?.toLowerCase();return{html:"text/html",htm:"text/html",css:"text/css",js:"application/javascript",mjs:"application/javascript",json:"application/json",xml:"application/xml",txt:"text/plain",md:"text/markdown",csv:"text/csv",jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",gif:"image/gif",webp:"image/webp",svg:"image/svg+xml",ico:"image/x-icon",avif:"image/avif",mp4:"video/mp4",webm:"video/webm",mov:"video/quicktime",avi:"video/x-msvideo",mp3:"audio/mpeg",wav:"audio/wav",ogg:"audio/ogg",pdf:"application/pdf",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xls:"application/vnd.ms-excel",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",ppt:"application/vnd.ms-powerpoint",pptx:"application/vnd.openxmlformats-officedocument.presentationml.presentation",zip:"application/zip",gz:"application/gzip",tar:"application/x-tar",rar:"application/vnd.rar","7z":"application/x-7z-compressed",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf",otf:"font/otf",eot:"application/vnd.ms-fontobject",wasm:"application/wasm"}[n||""]||"application/octet-stream"}function Cn(a){if(a instanceof Blob)return a;if(typeof a==="string")return new Blob([a],{type:"text/plain"});return new Blob([a])}function II(a){return new Da(a)}await et();class Ve extends Error{code;solution;details;constructor(a,n,i,s){super(a);this.code=n,this.solution=i,this.details=s,this.name="CloudError",Error.captureStackTrace?.(this,Ve)}toString(){let a=`${this.name} [${this.code}]: ${this.message}`;if(this.solution)a+=`
2493
+ `}},storage:{uploads:{type:"efs",performanceMode:"generalPurpose",throughputMode:"bursting",encrypted:!0,lifecyclePolicy:{transitionToIA:30}},backups:{public:!1,versioning:!0,encryption:!0,lifecycleRules:[{id:"ArchiveOldBackups",enabled:!0,transitions:[{days:90,storageClass:"GLACIER"}]}]},static:{public:!0,versioning:!1,encryption:!1,cors:[{allowedOrigins:[s||"*"],allowedMethods:["GET","HEAD"]}]}},cdn:{enabled:!0,origins:[{originId:"static-assets",domainName:`${i}-static.s3.amazonaws.com`,pathPattern:"/static/*"}],customDomain:s?{domain:s,certificateArn:"TO_BE_GENERATED"}:void 0,cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0},databases:h==="mysql"?{mysql:{engine:"mysql",version:"8.0",instanceClass:"db.t3.medium",allocatedStorage:100,maxAllocatedStorage:500,multiAZ:!0,backupRetentionDays:14,preferredBackupWindow:"03:00-04:00",preferredMaintenanceWindow:"sun:04:00-sun:05:00",enablePerformanceInsights:!0,performanceInsightsRetention:7,deletionProtection:!0,parameters:{max_connections:"500",innodb_buffer_pool_size:"{DBInstanceClassMemory*3/4}",slow_query_log:"1",long_query_time:"2"}}}:{postgres:{engine:"postgres",version:"15",instanceClass:"db.t3.medium",allocatedStorage:100,maxAllocatedStorage:500,multiAZ:!0,backupRetentionDays:14,preferredBackupWindow:"03:00-04:00",preferredMaintenanceWindow:"sun:04:00-sun:05:00",enablePerformanceInsights:!0,performanceInsightsRetention:7,deletionProtection:!0,parameters:{max_connections:"500",shared_buffers:"{DBInstanceClassMemory/4}",log_min_duration_statement:"2000"}}},cache:y==="redis"?{redis:{nodeType:"cache.t3.medium",numCacheNodes:2,engine:"redis",engineVersion:"7.0",port:6379,parameterGroup:{maxmemoryPolicy:"allkeys-lru",timeout:"300"},snapshotRetentionLimit:5,snapshotWindow:"03:00-05:00",automaticFailoverEnabled:!0}}:void 0,queues:{jobs:{fifo:!1,visibilityTimeout:900,messageRetentionPeriod:345600,receiveMessageWaitTime:20,deadLetterQueue:!0,maxReceiveCount:3},emails:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:86400,deadLetterQueue:!0}},functions:{"job-worker":{runtime:"nodejs20.x",handler:"dist/workers/jobs.handler",memory:2048,timeout:900,events:[{type:"sqs",queueName:`${i}-jobs`,batchSize:10}]},"email-sender":{runtime:"nodejs20.x",handler:"dist/workers/email.handler",memory:512,timeout:60,events:[{type:"sqs",queueName:`${i}-emails`,batchSize:10}]},cleanup:{runtime:"nodejs20.x",handler:"dist/tasks/cleanup.handler",memory:512,timeout:300,events:[{type:"schedule",expression:"cron(0 2 * * ? *)"}]}},monitoring:{dashboard:{name:`${i}-web-app`,widgets:[{type:"metric",metrics:["EC2CPUUtilization","ALBRequestCount","ALBTargetResponseTime","RDSCPUUtilization","RDSDatabaseConnections","RDSReadLatency","RDSWriteLatency"]}]},alarms:[{metric:"EC2CPUUtilization",threshold:80,evaluationPeriods:2},{metric:"RDSCPUUtilization",threshold:80,evaluationPeriods:2},{metric:"RDSDatabaseConnections",threshold:400,evaluationPeriods:1},{metric:"ALBTargetResponseTime",threshold:2000,evaluationPeriods:2},{metric:"ALBUnhealthyHostCount",threshold:1,evaluationPeriods:1}],logs:{retention:14,groups:[`${i}-app`,`${i}-nginx`,`${i}-workers`]}},security:{certificate:s?{domain:s,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss","knownBadInputs"]},securityGroups:{alb:{ingress:[{port:80,protocol:"tcp",cidr:"0.0.0.0/0"},{port:443,protocol:"tcp",cidr:"0.0.0.0/0"}]},app:{ingress:[{port:3000,protocol:"tcp",source:"alb-sg"}]},database:{ingress:[{port:h==="mysql"?3306:5432,protocol:"tcp",source:"app-sg"}]},...y==="redis"&&{cache:{ingress:[{port:6379,protocol:"tcp",source:"app-sg"}]}}}}}}}function sI(a){let{name:n,slug:i,domain:s,repository:c,phpVersion:l="8.3",size:u="small",database:h=i.replace(/-/g,"_"),databasePassword:y,sslEmail:S,deployStrategy:A="push",provider:C="hetzner"}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"server",cloud:{provider:C},environments:{production:{type:"production",domain:s}},infrastructure:{compute:{mode:"server",size:u,runtime:"php",webServer:"nginx",php:{versions:[l],default:l},managedServices:{mysql:!0,redis:!0},firewall:{enabled:!0},autoUpdates:!0,monitoring:!0,backups:{enabled:!0,schedule:"0 2 * * *",retentionCount:7}},appDatabase:{engine:"mysql",name:h,username:h,password:y}},sites:{main:{root:".",type:"laravel",domain:s,phpVersion:l,repository:{...c,strategy:A},scheduler:!0,queues:[{connection:"redis",queue:"default",processes:1}],ssl:{provider:"letsencrypt",email:S}}}}}function oI(a){let{name:n,slug:i,domain:s,layers:c,phpVersion:l="8.3",architecture:u="x86_64",memory:h=1024,build:y,deploy:S=["migrate --force"],cache:A="dynamodb",scheduler:C="on",region:T="us-east-1"}=a;return{project:{name:n,slug:i,region:T},mode:"serverless",environments:{production:{type:"production",domain:s,app:{kind:"php",runtime:"provided.al2023",phpVersion:l,architecture:u,layers:c,memory:h,build:y,deploy:S,assets:"public",queues:!0,scheduler:C,cache:{driver:A},domain:s}}}}}function aI(a){return{root:a.root??"packages/ui/dist",deploy:"server",type:"static",domain:a.domain,build:a.build??"cd packages/ui && bun install && bun run build",ssl:{provider:"letsencrypt"},auth:{username:a.username??"admin",password:a.password}}}var Ef=xp,bf="./node_modules/@stacksjs/ts-cloud/dist/bin/dashboard-server.js";function gn(a){let n=a.split(".").filter(Boolean);return n.length<=2?a:n.slice(-2).join(".")}function hn(a){let n=2166136261;for(let i=0;i<a.length;i++)n^=a.charCodeAt(i),n=Math.imul(n,16777619);return n>>>0}var vf=20000,Tf=12000;function wf(a){return vf+hn(a)%Tf}function Ea(a,n){let i=gn(a);if(i===a)return`dashboard.${i}`;for(let s of n)if(s===i)return`dashboard.${i}`;return`dashboard.${a}`}function Pa(a,n){let i=[],s=a.infrastructure?.dns?.domain;if(s&&!a.cloud?.attachTo)i.push(s);if(n&&a.environments?.[n]?.domain)i.push(a.environments[n].domain);for(let c of Object.values(a.sites??{})){let l=c;if(!l||l.redirect)continue;let u=l.domain;if(typeof u==="string")i.push(u);else if(Array.isArray(u))i.push(...u.filter((h)=>typeof h==="string"))}return i.filter((c)=>c&&!c.startsWith("dashboard."))}function Rf(a,n,i){if(i)return i;let s=Pa(a,n),c=s[0];if(!c)return null;return Ea(c,s)}function Df(a,n,i){if(i)return[i];let s=Pa(a,n),c=[];for(let l of s){let u=Ea(l,s);if(!c.includes(u))c.push(u)}return c}function Ht(a){return Object.entries(a.sites??{}).some(([n,i])=>{if(!i)return!1;let s=i.root??"";return xr(n)||s==="ui/dist"||s.endsWith("/ui/dist")||s.endsWith("/dist/ui")})}var Mp="dashboard-";function Fp(a){return Mp+a.replace(/^dashboard\./,"").replace(/\./g,"-")}function xr(a){return a==="dashboard"||a.startsWith(Mp)}function yi(a,n,i){if(Ht(a))return[];if(a.cloud?.attachTo)return[];let s=i.password?{auth:{username:i.username||"admin",password:i.password,realm:i.realm}}:{},c=i.build===!1||i.build===void 0?{}:{build:i.build};if(i.live!==!1){let l=Rf(a,n,i.domain);if(!l)return[];let u=i.port??wf(l),h=a.infrastructure?.appDatabase??a.infrastructure?.compute?.database,y={root:i.uiRoot,deploy:"server",domain:l,preStart:["bun install --production --no-save"],start:`bun ${bf} --box --host 127.0.0.1 --port ${u}`,port:u,cpuWeight:10,ioWeight:10,tasksMax:128,env:{APP_ENV:"production",NODE_ENV:"production",TS_CLOUD_DASHBOARD_TELEMETRY:"1",...h?.password?{TS_CLOUD_DASHBOARD_DB_PASSWORD:h.password}:{}},zeroDowntime:!1,sharedPaths:[Ef],healthCheck:{path:"/login"},ssl:{provider:"letsencrypt"}};return[{name:Fp(l),site:y}]}return Df(a,n,i.domain).map((l)=>({name:Fp(l),site:{root:i.uiRoot,deploy:"server",type:"static",domain:l,ssl:{provider:"letsencrypt"},...c,...s}}))}function cI(a,n,i){return yi(a,n,i)[0]??null}function Bt(a,n){let i={...a};for(let s in n){let c=n[s],l=i[s];if(c===void 0)continue;if(Array.isArray(c)&&Array.isArray(l))i[s]=[...l,...c];else if(typeof c==="object"&&c!==null&&!Array.isArray(c)&&typeof l==="object"&&l!==null&&!Array.isArray(l))i[s]=Bt(l,c);else i[s]=c}return i}function Up(a,n){return Bt(a,n)}function dI(...a){return a.reduce((n,i)=>Bt(n,i),{})}function lI(a,n){return(i)=>{let s=a(i);if(typeof n==="function")return Up(s,n(s,i));return Up(s,n)}}function Or(a){return{infrastructure:a}}function uI(a){return Or({monitoring:a})}function pI(a){return Or({security:a})}function gI(a){return Or({databases:a})}function mI(a){return Or({cache:a})}function hI(a){return Or({cdn:a})}function fI(a){return Or({queues:a})}et();function Pf(){let a=process.env.AWS_ACCESS_KEY_ID,n=process.env.AWS_SECRET_ACCESS_KEY;if(!a||!n)return null;return{accessKeyId:a,secretAccessKey:n,sessionToken:process.env.AWS_SESSION_TOKEN}}function Nf(a){let n=a?.profile||process.env.AWS_PROFILE||"default",i=a?.credentialsFile||Na(Ra(),".aws","credentials");if(!Ia(i))return null;try{let s=_t(i,"utf-8");return yn(s,n)}catch{return null}}function yn(a,n){let i=a.split(`
2494
+ `),s=null,c,l,u;for(let h of i){let y=h.trim();if(!y||y.startsWith("#")||y.startsWith(";"))continue;let S=y.match(/^\[([^\]]+)\]$/);if(S){if(s===n&&c&&l)return{accessKeyId:c,secretAccessKey:l,sessionToken:u};s=S[1],c=void 0,l=void 0,u=void 0;continue}if(s===n){let[A,...C]=y.split("="),T=C.join("=").trim();switch(A.trim().toLowerCase()){case"aws_access_key_id":c=T;break;case"aws_secret_access_key":l=T;break;case"aws_session_token":u=T;break}}}if(s===n&&c&&l)return{accessKeyId:c,secretAccessKey:l,sessionToken:u};return null}async function kf(a){let n=a?.timeout??1000,i="http://169.254.169.254";try{let s=await Ye("http://169.254.169.254/latest/api/token",{method:"PUT",headers:{"X-aws-ec2-metadata-token-ttl-seconds":"21600"}},n);if(!s.ok)return null;let c=await s.text(),l=await Ye("http://169.254.169.254/latest/meta-data/iam/security-credentials/",{headers:{"X-aws-ec2-metadata-token":c}},n);if(!l.ok)return null;let u=(await l.text()).trim(),h=await Ye(`http://169.254.169.254/latest/meta-data/iam/security-credentials/${u}`,{headers:{"X-aws-ec2-metadata-token":c}},n);if(!h.ok)return null;let y=await h.json();return{accessKeyId:y.AccessKeyId,secretAccessKey:y.SecretAccessKey,sessionToken:y.Token,expiration:new Date(y.Expiration)}}catch{return null}}async function Bf(a){let n=a?.timeout??1000,i=process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI,s=process.env.AWS_CONTAINER_CREDENTIALS_FULL_URI,c=null;if(i)c=`http://169.254.170.2${i}`;else if(s)c=s;if(!c)return null;try{let l={},u=process.env.AWS_CONTAINER_AUTHORIZATION_TOKEN;if(u)l.Authorization=u;let h=await Ye(c,{headers:l},n);if(!h.ok)return null;let y=await h.json();return{accessKeyId:y.AccessKeyId,secretAccessKey:y.SecretAccessKey,sessionToken:y.Token,expiration:new Date(y.Expiration)}}catch{return null}}async function _f(a){let n=a?.timeout??5000,i=process.env.AWS_WEB_IDENTITY_TOKEN_FILE,s=process.env.AWS_ROLE_ARN,c=process.env.AWS_ROLE_SESSION_NAME||"ts-cloud-session";if(!i||!s)return null;try{let l=_t(i,"utf-8").trim(),u=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION||"us-east-1",h=u.startsWith("us-gov")?`https://sts.${u}.amazonaws.com`:u==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${u}.amazonaws.com`,y=new URLSearchParams({Action:"AssumeRoleWithWebIdentity",Version:"2011-06-15",RoleArn:s,RoleSessionName:c,WebIdentityToken:l}),S=await Ye(`${h}/?${y.toString()}`,{method:"POST"},n);if(!S.ok)return null;let A=await S.text(),C=Qe(A,"AccessKeyId"),T=Qe(A,"SecretAccessKey"),v=Qe(A,"SessionToken"),w=Qe(A,"Expiration");if(!C||!T)return null;return{accessKeyId:C,secretAccessKey:T,sessionToken:v??void 0,expiration:w?new Date(w):void 0}}catch{return null}}async function to(a){let n=Pf();if(n)return n;let i=Nf(a);if(i)return i;let s=await _f(a);if(s)return s;let c=await Bf(a);if(c)return c;let l=await kf(a);if(l)return l;throw Error("Could not find AWS credentials. Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables, or configure ~/.aws/credentials, or run on an EC2 instance with an IAM role.")}function yI(a){let n=null,i=null;return async()=>{if(n){if(!n.expiration)return n;let s=300000;if(n.expiration.getTime()-Date.now()>s)return n}if(i)return i;return i=to(a).then((s)=>(n=s,i=null,s)).catch((s)=>{throw i=null,s}),i}}async function Ye(a,n,i){let s=new AbortController,c=setTimeout(()=>s.abort(),i);try{let l=await fetch(a,{...n,signal:s.signal});return clearTimeout(c),l}catch(l){throw clearTimeout(c),l}}function Qe(a,n){let i=new RegExp(`<${n}>([^<]+)</${n}>`),s=a.match(i);return s?s[1]:null}async function xf(a){return to({profile:a})}function Of(a){let n=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION;if(n)return n;let i=Na(Ra(),".aws","config");if(Ia(i))try{let s=_t(i,"utf-8"),c=a||process.env.AWS_PROFILE||"default",l=c==="default"?"[default]":`[profile ${c}]`,u=s.split(`
2495
+ `),h=!1;for(let y of u){let S=y.trim();if(S.startsWith("[")){h=S===l;continue}if(h&&S.startsWith("region")){let[,A]=S.split("=");if(A)return A.trim()}}}catch{}return"us-east-1"}async function Lf(a){let n=a||await to(),i=Of();await et();let s=i.startsWith("us-gov")?`https://sts.${i}.amazonaws.com`:i==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${i}.amazonaws.com`,c="Action=GetCallerIdentity&Version=2011-06-15",l=_({method:"POST",url:s,body:"Action=GetCallerIdentity&Version=2011-06-15",headers:{"Content-Type":"application/x-www-form-urlencoded"},...n,service:"sts",region:i}),u=await fetch(l.url,{method:l.method,headers:l.headers,body:l.body});if(!u.ok)throw Error(`Failed to get account ID: ${await u.text()}`);let h=await u.text(),y=Qe(h,"Account");if(!y)throw Error("Failed to parse account ID from response");return y}await et();await et();var fn=5242880,Pt=5242880,Sn=5242880;class Da{region;endpoint;forcePathStyle;credentials;credentialOptions;retryOptions;constructor(a={}){this.region=a.region||process.env.AWS_REGION||"us-east-1",this.endpoint=a.endpoint||`https://s3.${this.region}.amazonaws.com`,this.forcePathStyle=a.forcePathStyle||!1,this.credentials=a.credentials,this.credentialOptions=a.credentialOptions,this.retryOptions=a.retryOptions||{}}async getCredentials(){if(this.credentials)return this.credentials;return to(this.credentialOptions)}buildUrl(a,n){let i=n?encodeURIComponent(n).replace(/%2F/g,"/"):"";if(this.forcePathStyle)return n?`${this.endpoint}/${a}/${i}`:`${this.endpoint}/${a}`;let s=new URL(this.endpoint);return s.hostname=`${a}.${s.hostname}`,n?`${s.origin}/${i}`:s.origin}async get(a,n,i={}){let s=await this.getCredentials(),c=this.buildUrl(a,n),l={};if(i.range)l.Range=i.range;if(i.ifModifiedSince)l["If-Modified-Since"]=i.ifModifiedSince.toUTCString();if(i.ifMatch)l["If-Match"]=i.ifMatch;if(i.ifNoneMatch)l["If-None-Match"]=i.ifNoneMatch;let u=new URL(c);if(i.responseContentType)u.searchParams.set("response-content-type",i.responseContentType);if(i.responseContentDisposition)u.searchParams.set("response-content-disposition",i.responseContentDisposition);let h=_({method:"GET",url:u.toString(),headers:l,...s,service:"s3",region:this.region}),y=await fetch(h.url,{method:h.method,headers:h.headers});if(!y.ok&&y.status!==304){let S=await y.text();throw new G(`Failed to get object: ${S}`,y.status,a,n)}return y}async getText(a,n,i={}){return(await this.get(a,n,i)).text()}async getJSON(a,n,i={}){return(await this.get(a,n,i)).json()}async getBuffer(a,n,i={}){return(await this.get(a,n,i)).arrayBuffer()}async put(a,n,i,s={}){let c,l;if(typeof i==="string")c=new TextEncoder().encode(i).length,l=i;else if(i instanceof ArrayBuffer)c=i.byteLength,l=i;else if(i instanceof Uint8Array)c=i.byteLength,l=i;else if(i instanceof Blob)c=i.size,l=i;else return this.uploadMultipart(a,n,i,{...s,partSize:Pt});if(c>Sn){let u=Cn(l).stream();return this.uploadMultipart(a,n,u,{...s,partSize:Pt})}return this.putSimple(a,n,l,c,s)}async putSimple(a,n,i,s,c){let l=await this.getCredentials(),u=this.buildUrl(a,n),h={"Content-Length":String(s),"Content-Type":c.contentType||la(n)};if(c.contentEncoding)h["Content-Encoding"]=c.contentEncoding;if(c.cacheControl)h["Cache-Control"]=c.cacheControl;if(c.contentDisposition)h["Content-Disposition"]=c.contentDisposition;if(c.storageClass)h["x-amz-storage-class"]=c.storageClass;if(c.serverSideEncryption)h["x-amz-server-side-encryption"]=c.serverSideEncryption;if(c.acl)h["x-amz-acl"]=c.acl;if(c.tagging)h["x-amz-tagging"]=c.tagging;if(c.metadata)for(let[C,T]of Object.entries(c.metadata))h[`x-amz-meta-${C.toLowerCase()}`]=T;let y;if(typeof i==="string")y=i;else if(i instanceof Blob)y=await i.text();else y=new TextDecoder().decode(i instanceof ArrayBuffer?new Uint8Array(i):i);let S=_({method:"PUT",url:u,headers:h,body:y,...l,service:"s3",region:this.region}),A=await fetch(S.url,{method:S.method,headers:S.headers,body:i});if(!A.ok){let C=await A.text();throw new G(`Failed to put object: ${C}`,A.status,a,n)}return{etag:(A.headers.get("ETag")||"").replace(/"/g,"")}}async delete(a,n){let i=await this.getCredentials(),s=this.buildUrl(a,n),c=_({method:"DELETE",url:s,...i,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(!l.ok&&l.status!==204){let u=await l.text();throw new G(`Failed to delete object: ${u}`,l.status,a,n)}}async deleteMany(a,n){let i=await this.getCredentials(),s=`${this.buildUrl(a)}?delete`,c=`<?xml version="1.0" encoding="UTF-8"?><Delete><Quiet>false</Quiet>${n.map((v)=>`<Object><Key>${An(v)}</Key></Object>`).join("")}</Delete>`,l=_({method:"POST",url:s,headers:{"Content-Type":"application/xml"},body:c,...i,service:"s3",region:this.region}),u=await fetch(l.url,{method:l.method,headers:l.headers,body:c});if(!u.ok){let v=await u.text();throw new G(`Failed to delete objects: ${v}`,u.status,a)}let h=await u.text(),y=[],S=[],A=/<Deleted><Key>([^<]+)<\/Key>/g,C;while((C=A.exec(h))!==null)y.push(C[1]);let T=/<Error><Key>([^<]+)<\/Key><Code>([^<]+)<\/Code><Message>([^<]+)<\/Message>/g;while((C=T.exec(h))!==null)S.push({key:C[1],error:`${C[2]}: ${C[3]}`});return{deleted:y,errors:S}}async list(a,n={}){let i=await this.getCredentials(),s=new URL(this.buildUrl(a));if(s.searchParams.set("list-type","2"),n.prefix)s.searchParams.set("prefix",n.prefix);if(n.delimiter)s.searchParams.set("delimiter",n.delimiter);if(n.maxKeys)s.searchParams.set("max-keys",String(n.maxKeys));if(n.continuationToken)s.searchParams.set("continuation-token",n.continuationToken);if(n.startAfter)s.searchParams.set("start-after",n.startAfter);let c=_({method:"GET",url:s.toString(),...i,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(!l.ok){let h=await l.text();throw new G(`Failed to list objects: ${h}`,l.status,a)}let u=await l.text();return bn(u)}async*listAll(a,n={}){let i;do{let s=await this.list(a,{...n,continuationToken:i});for(let c of s.contents)yield c;i=s.nextContinuationToken}while(i)}async head(a,n){let i=await this.getCredentials(),s=this.buildUrl(a,n),c=_({method:"HEAD",url:s,...i,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(l.status===404)return null;if(!l.ok){let h=await l.text();throw new G(`Failed to head object: ${h}`,l.status,a,n)}let u={};return l.headers.forEach((h,y)=>{if(y.toLowerCase().startsWith("x-amz-meta-"))u[y.slice(11)]=h}),{contentLength:Number(l.headers.get("Content-Length")||0),contentType:l.headers.get("Content-Type")||"application/octet-stream",etag:(l.headers.get("ETag")||"").replace(/"/g,""),lastModified:new Date(l.headers.get("Last-Modified")||0),metadata:u,storageClass:l.headers.get("x-amz-storage-class")||void 0,serverSideEncryption:l.headers.get("x-amz-server-side-encryption")||void 0}}async exists(a,n){return await this.head(a,n)!==null}async copy(a,n,i,s,c={}){let l=await this.getCredentials(),u=this.buildUrl(i,s),h={"x-amz-copy-source":`/${a}/${encodeURIComponent(n)}`};if(c.metadataDirective)h["x-amz-metadata-directive"]=c.metadataDirective;if(c.contentType)h["Content-Type"]=c.contentType;if(c.storageClass)h["x-amz-storage-class"]=c.storageClass;if(c.acl)h["x-amz-acl"]=c.acl;if(c.metadata)for(let[C,T]of Object.entries(c.metadata))h[`x-amz-meta-${C.toLowerCase()}`]=T;let y=_({method:"PUT",url:u,headers:h,...l,service:"s3",region:this.region}),S=await fetch(y.url,{method:y.method,headers:y.headers});if(!S.ok){let C=await S.text();throw new G(`Failed to copy object: ${C}`,S.status,i,s)}let A=(await S.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:A?A[1]:""}}async getPresignedUrl(a,n,i={}){let s=await this.getCredentials(),c=this.buildUrl(a,n);return hf({url:c,method:i.method||"GET",expiresIn:i.expiresIn||3600,...s,service:"s3",region:this.region})}async uploadMultipart(a,n,i,s={}){let c=await this.getCredentials(),l=Math.max(s.partSize||Pt,fn),u,h;if(i instanceof ReadableStream)u=i;else if(i instanceof Blob)u=i.stream(),h=i.size;else{let A=new Blob([i]);u=A.stream(),h=A.size}let{uploadId:y,baseUrl:S}=await this.initiateMultipartUpload(a,n,s);try{let A=await this.uploadParts(a,n,S,y,u,l,c,h,s.concurrency||4,s.onProgress);return await this.completeMultipartUpload(a,n,S,y,A)}catch(A){throw await this.abortMultipartUpload(a,n,y,S).catch(()=>{}),A}}async initiateMultipartUpload(a,n,i){let s=await this.getCredentials(),c=this.buildUrl(a,n),l=`${c}?uploads`,u={"Content-Type":i.contentType||la(n)};if(i.storageClass)u["x-amz-storage-class"]=i.storageClass;if(i.serverSideEncryption)u["x-amz-server-side-encryption"]=i.serverSideEncryption;if(i.acl)u["x-amz-acl"]=i.acl;if(i.metadata)for(let[C,T]of Object.entries(i.metadata))u[`x-amz-meta-${C.toLowerCase()}`]=T;let h=_({method:"POST",url:l,headers:u,...s,service:"s3",region:this.region}),y=await fetch(h.url,{method:h.method,headers:h.headers});if(!y.ok){let C=await y.text();throw new G(`Failed to initiate multipart upload: ${C}`,y.status,a,n)}let S=(await y.text()).match(/<UploadId>([^<]+)<\/UploadId>/);if(!S)throw new G("Failed to parse upload ID from response",0,a,n);let A=c;if(y.url)try{let C=new URL(y.url);C.search="",A=C.toString()}catch{}return{uploadId:S[1],baseUrl:A}}async uploadParts(a,n,i,s,c,l,u,h,y,S){let A=[],C=c.getReader(),T=1,v=new Uint8Array(0),w=0,E=h?Math.ceil(h/l):void 0,R=new Map,k=async(P,V)=>{let B=`${i}?partNumber=${V}&uploadId=${encodeURIComponent(s)}`,j={"Content-Length":String(P.byteLength),"x-amz-content-sha256":"UNSIGNED-PAYLOAD"},J=_({method:"PUT",url:B,headers:j,...u,service:"s3",region:this.region}),K=await fetch(J.url,{method:J.method,headers:J.headers,body:P,redirect:"error"});if(!K.ok){let te=await K.text();throw new G(`Failed to upload part ${V}: ${te}`,K.status,a,n)}let X=(K.headers.get("ETag")||"").replace(/"/g,"");if(!X)throw new G(`Missing ETag for part ${V}`,K.status,a,n);return{partNumber:V,etag:X}},W=async()=>{let P=await Promise.race(R.values());R.delete(P.partNumber),A.push(P)};while(!0){let{done:P,value:V}=await C.read();if(V){let B=new Uint8Array(v.length+V.length);B.set(v),B.set(V,v.length),v=B}while(v.length>=l||P&&v.length>0){let B=v.slice(0,l);v=v.slice(l);let j=T++;if(R.size>=y)await W();if(R.set(j,k(B,j)),w+=B.byteLength,S)S({loaded:w,total:h||w,part:j,totalParts:E||j})}if(P)break}while(R.size>0)await W();return A.sort((P,V)=>P.partNumber-V.partNumber),A}async completeMultipartUpload(a,n,i,s,c){let l=await this.getCredentials(),u=`${i}?uploadId=${encodeURIComponent(s)}`,h=`<?xml version="1.0" encoding="UTF-8"?><CompleteMultipartUpload>${c.map((C)=>`<Part><PartNumber>${C.partNumber}</PartNumber><ETag>"${C.etag}"</ETag></Part>`).join("")}</CompleteMultipartUpload>`,y=_({method:"POST",url:u,headers:{"Content-Type":"application/xml"},body:h,...l,service:"s3",region:this.region}),S=await fetch(y.url,{method:y.method,headers:y.headers,body:h});if(!S.ok){let C=await S.text();throw new G(`Failed to complete multipart upload: ${C}`,S.status,a,n)}let A=(await S.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:A?A[1]:""}}async abortMultipartUpload(a,n,i,s){let c=await this.getCredentials(),l=`${s??this.buildUrl(a,n)}?uploadId=${encodeURIComponent(i)}`,u=_({method:"DELETE",url:l,...c,service:"s3",region:this.region});await fetch(u.url,{method:u.method,headers:u.headers})}async emptyAndDeleteBucket(a){let n=[];for await(let l of this.listAll(a,{}))if(n.push(l.key),n.length>=1000)await this.deleteMany(a,n),n=[];if(n.length>0)await this.deleteMany(a,n);let i=await this.getCredentials(),s=this.buildUrl(a),c=_({method:"DELETE",url:s,...i,service:"s3",region:this.region});await fetch(c.url,{method:c.method,headers:c.headers})}}class G extends Error{statusCode;bucket;key;constructor(a,n,i,s){super(a);this.statusCode=n,this.bucket=i,this.key=s,this.name="S3Error"}}function bn(a){let n=[],i=[],s=/<Contents>([\s\S]*?)<\/Contents>/g,c;while((c=s.exec(a))!==null){let u=c[1];n.push({key:ce(u,"Key")||"",lastModified:new Date(ce(u,"LastModified")||0),etag:(ce(u,"ETag")||"").replace(/"/g,""),size:Number(ce(u,"Size")||0),storageClass:ce(u,"StorageClass")||"STANDARD"})}let l=/<CommonPrefixes><Prefix>([^<]+)<\/Prefix><\/CommonPrefixes>/g;while((c=l.exec(a))!==null)i.push(c[1]);return{contents:n,commonPrefixes:i,isTruncated:ce(a,"IsTruncated")==="true",continuationToken:ce(a,"ContinuationToken")||void 0,nextContinuationToken:ce(a,"NextContinuationToken")||void 0,keyCount:Number(ce(a,"KeyCount")||0),maxKeys:Number(ce(a,"MaxKeys")||1000),prefix:ce(a,"Prefix")||void 0,delimiter:ce(a,"Delimiter")||void 0}}function ce(a,n){let i=new RegExp(`<${n}>([^<]*)</${n}>`),s=a.match(i);return s?s[1]:null}function An(a){return a.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function la(a){let n=a.split(".").pop()?.toLowerCase();return{html:"text/html",htm:"text/html",css:"text/css",js:"application/javascript",mjs:"application/javascript",json:"application/json",xml:"application/xml",txt:"text/plain",md:"text/markdown",csv:"text/csv",jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",gif:"image/gif",webp:"image/webp",svg:"image/svg+xml",ico:"image/x-icon",avif:"image/avif",mp4:"video/mp4",webm:"video/webm",mov:"video/quicktime",avi:"video/x-msvideo",mp3:"audio/mpeg",wav:"audio/wav",ogg:"audio/ogg",pdf:"application/pdf",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xls:"application/vnd.ms-excel",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",ppt:"application/vnd.ms-powerpoint",pptx:"application/vnd.openxmlformats-officedocument.presentationml.presentation",zip:"application/zip",gz:"application/gzip",tar:"application/x-tar",rar:"application/vnd.rar","7z":"application/x-7z-compressed",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf",otf:"font/otf",eot:"application/vnd.ms-fontobject",wasm:"application/wasm"}[n||""]||"application/octet-stream"}function Cn(a){if(a instanceof Blob)return a;if(typeof a==="string")return new Blob([a],{type:"text/plain"});return new Blob([a])}function II(a){return new Da(a)}await et();class Ve extends Error{code;solution;details;constructor(a,n,i,s){super(a);this.code=n,this.solution=i,this.details=s,this.name="CloudError",Error.captureStackTrace?.(this,Ve)}toString(){let a=`${this.name} [${this.code}]: ${this.message}`;if(this.solution)a+=`
2496
2496
 
2497
2497
  \uD83D\uDCA1 Solution: ${this.solution}`;if(this.details&&Object.keys(this.details).length>0){a+=`
2498
2498
 
@@ -2502,14 +2502,14 @@ Details:`;for(let[n,i]of Object.entries(this.details))a+=`
2502
2502
  2. Create ~/.aws/credentials file with your credentials
2503
2503
  3. Use an IAM role (for EC2 instances)
2504
2504
  4. Run 'aws configure' if you have AWS CLI installed`},INVALID_CREDENTIALS:{message:"AWS credentials are invalid",solution:"Verify your AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are correct. Run: aws sts get-caller-identity"},EXPIRED_CREDENTIALS:{message:"AWS credentials have expired",solution:"Refresh your AWS credentials. If using temporary credentials, generate new ones."},MISSING_CONFIG:{message:"Configuration file not found",solution:"Create a cloud.config.ts file in your project root. Use: cloud init"},INVALID_CONFIG:{message:"Configuration is invalid",solution:"Check your cloud.config.ts file for syntax errors. Use: cloud config:validate"},MISSING_REQUIRED_FIELD:{message:"Required configuration field is missing",solution:"Add the missing field to your cloud.config.ts file"},INVALID_REGION:{message:"AWS region is invalid",solution:"Use a valid AWS region like us-east-1, us-west-2, eu-west-1, etc."},STACK_ALREADY_EXISTS:{message:"CloudFormation stack already exists",solution:"Use: cloud deploy --update to update the existing stack, or cloud destroy to delete it first"},STACK_IN_PROGRESS:{message:"Stack operation already in progress",solution:"Wait for the current operation to complete, or cancel it in the AWS Console"},INSUFFICIENT_PERMISSIONS:{message:"Insufficient IAM permissions",solution:"Ensure your IAM user/role has the necessary permissions for CloudFormation and the resources you're deploying"},RESOURCE_LIMIT_EXCEEDED:{message:"AWS service limit exceeded",solution:"Request a service limit increase in the AWS Console, or clean up unused resources"},ROLLBACK_COMPLETE:{message:"Stack creation failed and rolled back",solution:"Check the CloudFormation events to see which resource failed. Fix the issue and try again."},CIRCULAR_DEPENDENCY:{message:"Circular dependency detected in resources",solution:"Review your resource dependencies and remove the circular reference"},INVALID_RESOURCE_NAME:{message:"Resource name contains invalid characters",solution:"Use only alphanumeric characters and hyphens in resource names"},DUPLICATE_RESOURCE:{message:"Duplicate resource name detected",solution:"Ensure all resource names are unique in your configuration"},VPC_CIDR_CONFLICT:{message:"VPC CIDR block conflicts with existing VPC",solution:"Use a different CIDR block that doesn't overlap with existing VPCs"},SUBNET_CIDR_INVALID:{message:"Subnet CIDR block is invalid or outside VPC range",solution:"Ensure subnet CIDR is within the VPC CIDR range and properly sized"},DB_INSTANCE_LIMIT:{message:"RDS instance limit reached",solution:"Delete unused RDS instances or request a limit increase"},INVALID_DB_NAME:{message:"Database name contains invalid characters",solution:"Use only alphanumeric characters and underscores, starting with a letter"},BUCKET_ALREADY_EXISTS:{message:"S3 bucket name already exists globally",solution:"S3 bucket names must be globally unique. Try a different name with your organization prefix"},INVALID_BUCKET_NAME:{message:"S3 bucket name is invalid",solution:"Use lowercase letters, numbers, and hyphens. Must start/end with letter/number. 3-63 characters."},TEMPLATE_TOO_LARGE:{message:"CloudFormation template exceeds size limit",solution:"Split your infrastructure into multiple stacks or use nested stacks"},INVALID_TEMPLATE:{message:"CloudFormation template is invalid",solution:"Validate your template with: cloud config:validate"},PARAMETER_NOT_FOUND:{message:"CloudFormation parameter not found",solution:"Check that all referenced parameters are defined in your template"}};function Uf(a){return Ff[a]}function Hp(a,n){let i=Uf(a);return new Ve(i.message,a,i.solution,n)}class ee{static verboseMode=!1;static debugMode=!1;static setVerbose(a){this.verboseMode=a}static setDebug(a){this.debugMode=a}static verbose(a,...n){if(this.verboseMode)console.log(`[VERBOSE] ${a}`,...n)}static debug(a,...n){if(this.debugMode)console.log(`[DEBUG] ${a}`,...n)}static info(a,...n){console.log(`ℹ ${a}`,...n)}static warn(a,...n){console.warn(`⚠ ${a}`,...n)}static error(a,n){if(console.error(`✖ ${a}`),n){if(n instanceof Ve)console.error(n.toString());else console.error(n.message);if(this.debugMode&&n.stack)console.error(`
2505
- Stack trace:`),console.error(n.stack)}}static success(a){console.log(`✔ ${a}`)}}function SI(a){if(!a)throw Hp("MISSING_CONFIG");if(!a.project)throw new ro("Missing required field: project","Add a project configuration with name, slug, and region",{field:"project"});if(!a.project.name)throw new ro("Missing required field: project.name","Add a project name to your configuration",{field:"project.name"});if(!a.project.slug)throw new ro("Missing required field: project.slug","Add a project slug (lowercase, alphanumeric with hyphens)",{field:"project.slug"});if(!/^[a-z0-9-]+$/.test(a.project.slug))throw new Qp("Invalid project slug format","Use only lowercase letters, numbers, and hyphens",{slug:a.project.slug});if(a.project.region){if(!["us-east-1","us-east-2","us-west-1","us-west-2","eu-west-1","eu-west-2","eu-west-3","eu-central-1","ap-southeast-1","ap-southeast-2","ap-northeast-1","ap-northeast-2","sa-east-1","ca-central-1"].includes(a.project.region))throw Hp("INVALID_REGION",{region:a.project.region})}ee.success("Configuration validation passed")}function CI(a){let n=[];if(a.environments?.production&&a.infrastructure?.database){let i=a.infrastructure.database;if((i.postgres||i.mysql)&&!i.postgres?.multiAZ&&!i.mysql?.multiAZ)n.push("Production database should use Multi-AZ for high availability")}if(a.infrastructure?.storage){for(let[i,s]of Object.entries(a.infrastructure.storage))if(s.encryption===!1)n.push(`Storage "${i}" is not encrypted - consider enabling encryption for security`)}if(a.infrastructure?.storage){for(let[i,s]of Object.entries(a.infrastructure.storage))if(s.public===!0)n.push(`Storage "${i}" is publicly accessible - ensure this is intentional`)}if(a.infrastructure?.database){let i=a.infrastructure.database;if(i.postgres||i.mysql){let s=i.postgres?.backupRetentionDays||i.mysql?.backupRetentionDays;if(!s||s<7)n.push("Database backup retention is less than 7 days - consider increasing for production")}}if(!a.infrastructure?.monitoring)n.push("No monitoring configured - consider adding CloudWatch alarms");return n}async function bI(a="default"){try{ee.verbose("Resolving AWS credentials...");let n=await _f(a);if(!n.accessKeyId||!n.secretAccessKey)throw new Gt("AWS credentials are incomplete","Ensure both AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are set");ee.verbose("Credentials resolved successfully"),ee.debug("Access Key ID:",n.accessKeyId.substring(0,8)+"..."),ee.verbose("Testing credentials with GetCallerIdentity...");let i;try{i=await Lf(n),ee.verbose("Credentials are valid"),ee.debug("Account ID:",i)}catch(s){if(s instanceof Error)if(s.message.includes("InvalidClientTokenId"))throw new Gt("Invalid AWS access key ID","Check that your AWS_ACCESS_KEY_ID is correct");else if(s.message.includes("SignatureDoesNotMatch"))throw new Gt("Invalid AWS secret access key","Check that your AWS_SECRET_ACCESS_KEY is correct");else if(s.message.includes("ExpiredToken"))throw new Gt("AWS credentials have expired","Refresh your temporary credentials or use long-term credentials");else throw new Gt(`Failed to validate credentials: ${s.message}`,"Verify your AWS credentials are correct and have the necessary permissions");throw s}return{valid:!0,accountId:i,region:n.region}}catch(n){if(n instanceof Gt)throw n;return{valid:!1,error:n instanceof Error?n.message:"Unknown error"}}}async function EI(a,n){return{allowed:n,denied:[]}}function Qf(a){let n=new Set(["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate","cloudformation:ListStacks"]);if(a.infrastructure){if(a.infrastructure.storage)n.add("s3:CreateBucket"),n.add("s3:DeleteBucket"),n.add("s3:PutBucketPolicy"),n.add("s3:PutBucketVersioning"),n.add("s3:PutBucketEncryption"),n.add("s3:PutObject"),n.add("s3:GetObject");if(a.infrastructure.compute){if(a.infrastructure.compute.server)n.add("ec2:RunInstances"),n.add("ec2:TerminateInstances"),n.add("ec2:DescribeInstances"),n.add("autoscaling:CreateAutoScalingGroup"),n.add("autoscaling:UpdateAutoScalingGroup"),n.add("autoscaling:DeleteAutoScalingGroup"),n.add("elasticloadbalancing:CreateLoadBalancer"),n.add("elasticloadbalancing:DeleteLoadBalancer");if(a.infrastructure.compute.fargate)n.add("ecs:CreateCluster"),n.add("ecs:DeleteCluster"),n.add("ecs:CreateService"),n.add("ecs:UpdateService"),n.add("ecs:DeleteService"),n.add("ecs:RegisterTaskDefinition")}if(a.infrastructure.database){if(a.infrastructure.database.postgres||a.infrastructure.database.mysql)n.add("rds:CreateDBInstance"),n.add("rds:DeleteDBInstance"),n.add("rds:ModifyDBInstance"),n.add("rds:DescribeDBInstances");if(a.infrastructure.database.dynamodb)n.add("dynamodb:CreateTable"),n.add("dynamodb:DeleteTable"),n.add("dynamodb:UpdateTable"),n.add("dynamodb:DescribeTable")}if(a.infrastructure.functions)n.add("lambda:CreateFunction"),n.add("lambda:DeleteFunction"),n.add("lambda:UpdateFunctionCode"),n.add("lambda:UpdateFunctionConfiguration"),n.add("lambda:AddPermission");if(a.infrastructure.cdn)n.add("cloudfront:CreateDistribution"),n.add("cloudfront:UpdateDistribution"),n.add("cloudfront:DeleteDistribution"),n.add("cloudfront:GetDistribution");if(a.infrastructure.network)n.add("ec2:CreateVpc"),n.add("ec2:DeleteVpc"),n.add("ec2:CreateSubnet"),n.add("ec2:DeleteSubnet"),n.add("ec2:CreateInternetGateway"),n.add("ec2:DeleteInternetGateway"),n.add("ec2:CreateNatGateway"),n.add("ec2:DeleteNatGateway"),n.add("ec2:CreateRouteTable"),n.add("ec2:DeleteRouteTable"),n.add("ec2:CreateSecurityGroup"),n.add("ec2:DeleteSecurityGroup")}return n.add("iam:CreateRole"),n.add("iam:DeleteRole"),n.add("iam:AttachRolePolicy"),n.add("iam:DetachRolePolicy"),n.add("iam:PutRolePolicy"),n.add("iam:GetRole"),n.add("iam:PassRole"),Array.from(n).sort()}function vI(a){let n=Qf(a);return JSON.stringify({Version:"2012-10-17",Statement:[{Effect:"Allow",Action:n,Resource:"*"}]},null,2)}var q={ec2:{"Running On-Demand Instances":20,"Elastic IPs":5,VPCs:5,"Internet Gateways":5,"NAT Gateways":5,"Security Groups":500},rds:{"DB Instances":40,"DB Snapshots":100,"DB Parameter Groups":50},lambda:{"Concurrent Executions":1000,"Function Storage":80530636800},s3:{Buckets:100},cloudformation:{Stacks:200,StackSets:100},elasticache:{Nodes:100,Clusters:100},dynamodb:{Tables:256},ecs:{Clusters:1e4,"Services per Cluster":2000}};async function TI(a){let n=[];if(ee.verbose("Checking AWS service quotas..."),a.infrastructure?.compute?.server){let s=a.infrastructure.compute.server.autoScaling?.max||1;n.push({service:"EC2",quotaName:"Running On-Demand Instances",currentValue:s,limit:q.ec2["Running On-Demand Instances"],percentage:s/q.ec2["Running On-Demand Instances"]*100,warning:s>q.ec2["Running On-Demand Instances"]*0.8})}if(a.infrastructure?.network?.vpc)n.push({service:"EC2",quotaName:"VPCs",currentValue:1,limit:q.ec2.VPCs,percentage:1/q.ec2.VPCs*100,warning:!1});if(a.infrastructure?.database?.postgres||a.infrastructure?.database?.mysql)n.push({service:"RDS",quotaName:"DB Instances",currentValue:1,limit:q.rds["DB Instances"],percentage:1/q.rds["DB Instances"]*100,warning:!1});if(a.infrastructure?.storage){let s=Object.keys(a.infrastructure.storage).length;n.push({service:"S3",quotaName:"Buckets",currentValue:s,limit:q.s3.Buckets,percentage:s/q.s3.Buckets*100,warning:s>q.s3.Buckets*0.8})}if(a.infrastructure?.functions){let s=0;for(let c of Object.values(a.infrastructure.functions))if(Array.isArray(c))s+=c.length;n.push({service:"Lambda",quotaName:"Functions (estimated)",currentValue:s,limit:1000,percentage:s/1000*100,warning:s>800})}if(a.infrastructure?.database?.dynamodb){let s=a.infrastructure.database.dynamodb.tables?.length||0;n.push({service:"DynamoDB",quotaName:"Tables",currentValue:s,limit:q.dynamodb.Tables,percentage:s/q.dynamodb.Tables*100,warning:s>q.dynamodb.Tables*0.8})}let i=n.filter((s)=>s.warning);if(i.length>0){ee.warn("Service quota warnings detected:");for(let s of i)ee.warn(` ${s.service} - ${s.quotaName}: ${s.currentValue}/${s.limit} (${s.percentage.toFixed(1)}%)`)}else ee.verbose("All service quotas are within limits");return n}function wI(a){if(a.length===0)return"No quotas to check";let n=`Service Quota Usage:
2505
+ Stack trace:`),console.error(n.stack)}}static success(a){console.log(`✔ ${a}`)}}function SI(a){if(!a)throw Hp("MISSING_CONFIG");if(!a.project)throw new ro("Missing required field: project","Add a project configuration with name, slug, and region",{field:"project"});if(!a.project.name)throw new ro("Missing required field: project.name","Add a project name to your configuration",{field:"project.name"});if(!a.project.slug)throw new ro("Missing required field: project.slug","Add a project slug (lowercase, alphanumeric with hyphens)",{field:"project.slug"});if(!/^[a-z0-9-]+$/.test(a.project.slug))throw new Qp("Invalid project slug format","Use only lowercase letters, numbers, and hyphens",{slug:a.project.slug});if(a.project.region){if(!["us-east-1","us-east-2","us-west-1","us-west-2","eu-west-1","eu-west-2","eu-west-3","eu-central-1","ap-southeast-1","ap-southeast-2","ap-northeast-1","ap-northeast-2","sa-east-1","ca-central-1"].includes(a.project.region))throw Hp("INVALID_REGION",{region:a.project.region})}ee.success("Configuration validation passed")}function CI(a){let n=[];if(a.environments?.production&&a.infrastructure?.database){let i=a.infrastructure.database;if((i.postgres||i.mysql)&&!i.postgres?.multiAZ&&!i.mysql?.multiAZ)n.push("Production database should use Multi-AZ for high availability")}if(a.infrastructure?.storage){for(let[i,s]of Object.entries(a.infrastructure.storage))if(s.encryption===!1)n.push(`Storage "${i}" is not encrypted - consider enabling encryption for security`)}if(a.infrastructure?.storage){for(let[i,s]of Object.entries(a.infrastructure.storage))if(s.public===!0)n.push(`Storage "${i}" is publicly accessible - ensure this is intentional`)}if(a.infrastructure?.database){let i=a.infrastructure.database;if(i.postgres||i.mysql){let s=i.postgres?.backupRetentionDays||i.mysql?.backupRetentionDays;if(!s||s<7)n.push("Database backup retention is less than 7 days - consider increasing for production")}}if(!a.infrastructure?.monitoring)n.push("No monitoring configured - consider adding CloudWatch alarms");return n}async function EI(a="default"){try{ee.verbose("Resolving AWS credentials...");let n=await xf(a);if(!n.accessKeyId||!n.secretAccessKey)throw new Gt("AWS credentials are incomplete","Ensure both AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are set");ee.verbose("Credentials resolved successfully"),ee.debug("Access Key ID:",n.accessKeyId.substring(0,8)+"..."),ee.verbose("Testing credentials with GetCallerIdentity...");let i;try{i=await Lf(n),ee.verbose("Credentials are valid"),ee.debug("Account ID:",i)}catch(s){if(s instanceof Error)if(s.message.includes("InvalidClientTokenId"))throw new Gt("Invalid AWS access key ID","Check that your AWS_ACCESS_KEY_ID is correct");else if(s.message.includes("SignatureDoesNotMatch"))throw new Gt("Invalid AWS secret access key","Check that your AWS_SECRET_ACCESS_KEY is correct");else if(s.message.includes("ExpiredToken"))throw new Gt("AWS credentials have expired","Refresh your temporary credentials or use long-term credentials");else throw new Gt(`Failed to validate credentials: ${s.message}`,"Verify your AWS credentials are correct and have the necessary permissions");throw s}return{valid:!0,accountId:i,region:n.region}}catch(n){if(n instanceof Gt)throw n;return{valid:!1,error:n instanceof Error?n.message:"Unknown error"}}}async function bI(a,n){return{allowed:n,denied:[]}}function Qf(a){let n=new Set(["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate","cloudformation:ListStacks"]);if(a.infrastructure){if(a.infrastructure.storage)n.add("s3:CreateBucket"),n.add("s3:DeleteBucket"),n.add("s3:PutBucketPolicy"),n.add("s3:PutBucketVersioning"),n.add("s3:PutBucketEncryption"),n.add("s3:PutObject"),n.add("s3:GetObject");if(a.infrastructure.compute){if(a.infrastructure.compute.server)n.add("ec2:RunInstances"),n.add("ec2:TerminateInstances"),n.add("ec2:DescribeInstances"),n.add("autoscaling:CreateAutoScalingGroup"),n.add("autoscaling:UpdateAutoScalingGroup"),n.add("autoscaling:DeleteAutoScalingGroup"),n.add("elasticloadbalancing:CreateLoadBalancer"),n.add("elasticloadbalancing:DeleteLoadBalancer");if(a.infrastructure.compute.fargate)n.add("ecs:CreateCluster"),n.add("ecs:DeleteCluster"),n.add("ecs:CreateService"),n.add("ecs:UpdateService"),n.add("ecs:DeleteService"),n.add("ecs:RegisterTaskDefinition")}if(a.infrastructure.database){if(a.infrastructure.database.postgres||a.infrastructure.database.mysql)n.add("rds:CreateDBInstance"),n.add("rds:DeleteDBInstance"),n.add("rds:ModifyDBInstance"),n.add("rds:DescribeDBInstances");if(a.infrastructure.database.dynamodb)n.add("dynamodb:CreateTable"),n.add("dynamodb:DeleteTable"),n.add("dynamodb:UpdateTable"),n.add("dynamodb:DescribeTable")}if(a.infrastructure.functions)n.add("lambda:CreateFunction"),n.add("lambda:DeleteFunction"),n.add("lambda:UpdateFunctionCode"),n.add("lambda:UpdateFunctionConfiguration"),n.add("lambda:AddPermission");if(a.infrastructure.cdn)n.add("cloudfront:CreateDistribution"),n.add("cloudfront:UpdateDistribution"),n.add("cloudfront:DeleteDistribution"),n.add("cloudfront:GetDistribution");if(a.infrastructure.network)n.add("ec2:CreateVpc"),n.add("ec2:DeleteVpc"),n.add("ec2:CreateSubnet"),n.add("ec2:DeleteSubnet"),n.add("ec2:CreateInternetGateway"),n.add("ec2:DeleteInternetGateway"),n.add("ec2:CreateNatGateway"),n.add("ec2:DeleteNatGateway"),n.add("ec2:CreateRouteTable"),n.add("ec2:DeleteRouteTable"),n.add("ec2:CreateSecurityGroup"),n.add("ec2:DeleteSecurityGroup")}return n.add("iam:CreateRole"),n.add("iam:DeleteRole"),n.add("iam:AttachRolePolicy"),n.add("iam:DetachRolePolicy"),n.add("iam:PutRolePolicy"),n.add("iam:GetRole"),n.add("iam:PassRole"),Array.from(n).sort()}function vI(a){let n=Qf(a);return JSON.stringify({Version:"2012-10-17",Statement:[{Effect:"Allow",Action:n,Resource:"*"}]},null,2)}var q={ec2:{"Running On-Demand Instances":20,"Elastic IPs":5,VPCs:5,"Internet Gateways":5,"NAT Gateways":5,"Security Groups":500},rds:{"DB Instances":40,"DB Snapshots":100,"DB Parameter Groups":50},lambda:{"Concurrent Executions":1000,"Function Storage":80530636800},s3:{Buckets:100},cloudformation:{Stacks:200,StackSets:100},elasticache:{Nodes:100,Clusters:100},dynamodb:{Tables:256},ecs:{Clusters:1e4,"Services per Cluster":2000}};async function TI(a){let n=[];if(ee.verbose("Checking AWS service quotas..."),a.infrastructure?.compute?.server){let s=a.infrastructure.compute.server.autoScaling?.max||1;n.push({service:"EC2",quotaName:"Running On-Demand Instances",currentValue:s,limit:q.ec2["Running On-Demand Instances"],percentage:s/q.ec2["Running On-Demand Instances"]*100,warning:s>q.ec2["Running On-Demand Instances"]*0.8})}if(a.infrastructure?.network?.vpc)n.push({service:"EC2",quotaName:"VPCs",currentValue:1,limit:q.ec2.VPCs,percentage:1/q.ec2.VPCs*100,warning:!1});if(a.infrastructure?.database?.postgres||a.infrastructure?.database?.mysql)n.push({service:"RDS",quotaName:"DB Instances",currentValue:1,limit:q.rds["DB Instances"],percentage:1/q.rds["DB Instances"]*100,warning:!1});if(a.infrastructure?.storage){let s=Object.keys(a.infrastructure.storage).length;n.push({service:"S3",quotaName:"Buckets",currentValue:s,limit:q.s3.Buckets,percentage:s/q.s3.Buckets*100,warning:s>q.s3.Buckets*0.8})}if(a.infrastructure?.functions){let s=0;for(let c of Object.values(a.infrastructure.functions))if(Array.isArray(c))s+=c.length;n.push({service:"Lambda",quotaName:"Functions (estimated)",currentValue:s,limit:1000,percentage:s/1000*100,warning:s>800})}if(a.infrastructure?.database?.dynamodb){let s=a.infrastructure.database.dynamodb.tables?.length||0;n.push({service:"DynamoDB",quotaName:"Tables",currentValue:s,limit:q.dynamodb.Tables,percentage:s/q.dynamodb.Tables*100,warning:s>q.dynamodb.Tables*0.8})}let i=n.filter((s)=>s.warning);if(i.length>0){ee.warn("Service quota warnings detected:");for(let s of i)ee.warn(` ${s.service} - ${s.quotaName}: ${s.currentValue}/${s.limit} (${s.percentage.toFixed(1)}%)`)}else ee.verbose("All service quotas are within limits");return n}function wI(a){if(a.length===0)return"No quotas to check";let n=`Service Quota Usage:
2506
2506
 
2507
2507
  `,i=a.reduce((s,c)=>{if(!s[c.service])s[c.service]=[];return s[c.service].push(c),s},{});for(let[s,c]of Object.entries(i)){n+=`${s}:
2508
2508
  `;for(let l of c){let u=l.warning?"⚠":"✓";n+=` ${u} ${l.quotaName}: ${l.currentValue}/${l.limit} (${l.percentage.toFixed(1)}%)
2509
2509
  `}n+=`
2510
- `}return n}function RI(a){let n=[];for(let i of a)if(i.percentage>=100)n.push(`Request quota increase for ${i.service} - ${i.quotaName} (currently ${i.limit})`);else if(i.warning)n.push(`Consider requesting quota increase for ${i.service} - ${i.quotaName} (${i.percentage.toFixed(1)}% used)`);return n}class Gp{cacheDir;ttl;constructor(a,n={}){this.cacheDir=a,this.ttl=n.ttl||86400000}ensureCacheDir(){if(!st(this.cacheDir))Tn(this.cacheDir,{recursive:!0})}getCachePath(a){let n=ka("sha256").update(a).digest("hex");return It(this.cacheDir,`${n}.json`)}get(a){let n=this.getCachePath(a);if(!st(n))return;try{let i=da(n,"utf-8"),s=JSON.parse(i);if(Date.now()-s.timestamp>this.ttl){ze(n);return}return s.value}catch{ze(n);return}}set(a,n,i){this.ensureCacheDir();let s=this.getCachePath(a),c={value:n,timestamp:Date.now(),hash:i};vn(s,JSON.stringify(c),"utf-8")}has(a){return this.get(a)!==void 0}clear(){if(!st(this.cacheDir))return;let a=ua(this.cacheDir);for(let n of a)ze(It(this.cacheDir,n))}prune(){if(!st(this.cacheDir))return;let a=ua(this.cacheDir),n=Date.now();for(let i of a){let s=It(this.cacheDir,i);try{let c=da(s,"utf-8"),l=JSON.parse(c);if(n-l.timestamp>this.ttl)ze(s)}catch{ze(s)}}}}class qp{cache;constructor(a=_("cache","templates")){this.cache=new Gp(a,{ttl:86400000})}getTemplate(a){return this.cache.get(`template:${a}`)}setTemplate(a,n){let i=this.hashTemplate(n);this.cache.set(`template:${a}`,n,i)}hasChanged(a,n){let i=this.cache.get(`template:${a}`);if(!i)return!0;let s=this.hashTemplate(i),c=this.hashTemplate(n);return s!==c}hashTemplate(a){return ka("sha256").update(a).digest("hex")}clear(){this.cache.clear()}prune(){this.cache.prune()}}var Rt=null;function DI(){if(!Rt)Rt=new qp;return Rt}async function Vp(a,n={}){let i=n.algorithm||"sha256",s=n.chunkSize||65536;return new Promise((c,l)=>{let u=Wt(i),h=wn(a,{highWaterMark:s});h.on("data",(y)=>u.update(y)),h.on("end",()=>c(u.digest("hex"))),h.on("error",l)})}function jp(a,n="sha256"){return Wt(n).update(a).digest("hex")}function PI(a,n="sha256"){return Wt(n).update(a).digest("hex")}async function NI(a,n={}){let i=n.ignorePatterns||["node_modules",".git","dist","build",Js()],s=[];async function c(l){let u=En(l,{withFileTypes:!0});for(let h of u){let y=Pn(l,h.name),S=In(a,y);if(i.some((b)=>S.includes(b)))continue;if(h.isDirectory())await c(y);else if(h.isFile()){let b=ht(y),A=await Vp(y,n);s.push({path:S,hash:A,size:b.size,mtime:b.mtimeMs})}}}return await c(a),s}function kI(a){let n=[...a].sort((i,s)=>i.path.localeCompare(s.path)).map((i)=>`${i.path}:${i.hash}`).join(`
2511
- `);return jp(n)}function BI(a){let n=ht(a);return jp(`${a}:${n.size}:${n.mtimeMs}`)}function xI(a,n){let i=new Map(a.map((h)=>[h.path,h])),s=new Map(n.map((h)=>[h.path,h])),c=[],l=[],u=[];for(let[h,y]of s){let S=i.get(h);if(!S)c.push(y);else if(S.hash!==y.hash)l.push(y)}for(let[h,y]of i)if(!s.has(h))u.push(y);return{added:c,modified:l,deleted:u}}class Hf{cache;constructor(){this.cache=new Map}get(a){let n=ht(a),i=this.cache.get(a);if(i&&i.mtime===n.mtimeMs&&i.size===n.size)return i.hash;return}set(a,n){let i=ht(a);this.cache.set(a,{hash:n,mtime:i.mtimeMs,size:i.size})}async getOrCompute(a,n={}){let i=this.get(a);if(i)return i;let s=await Vp(a,n);return this.set(a,s),s}clear(){this.cache.clear()}}async function yd(a,n={}){let i=n.concurrency||5,s=n.stopOnError??!0,c=[],l=[],u=Date.now(),h=[...a],y=[];async function S(C,T){try{let v=await C();c[T]=v}catch(v){let w=v instanceof Error?v:Error(String(v));if(l.push(w),s)throw h.length=0,w}}let b=0;while(h.length>0||y.length>0){while(y.length<i&&h.length>0){let C=h.shift(),T=b++,v=S(C,T);y.push(v)}if(y.length>0){await Promise.race(y);for(let C=y.length-1;C>=0;C--)if(await Promise.race([y[C].then(()=>!0),Promise.resolve(!1)]))y.splice(C,1)}if(s&&l.length>0)break}let A=Date.now()-u;return{results:c.filter((C)=>C!==void 0),errors:l,duration:A}}async function _I(a,n,i={}){let s=a.map((c)=>()=>n(c));return yd(s,i)}async function OI(a,n,i=5){let s=a.map((l,u)=>()=>n(l,u)),c=await yd(s,{concurrency:i,stopOnError:!1});if(c.errors.length>0)throw AggregateError(c.errors,"Parallel map failed");return c.results}async function LI(a,n={}){let i=n.retries||3,s=n.retryDelay||1000,c=a.map((l)=>async()=>{let u;for(let h=0;h<=i;h++)try{return await l()}catch(y){if(u=y instanceof Error?y:Error(String(y)),h<i)await $a(s*(h+1))}throw u});return yd(c,n)}async function $I(a){let n=[];for(let i of a){let s=await i();n.push(s)}return n}function $a(a){return new Promise((n)=>setTimeout(n,a))}async function MI(a,n,i="Operation timed out"){return Promise.race([a(),new Promise((s,c)=>setTimeout(()=>c(Error(i)),n))])}class Gf{maxConcurrent;minInterval;queue=[];running=0;lastExecution=0;constructor(a=5,n=100){this.maxConcurrent=a,this.minInterval=n}async execute(a){await this.waitForSlot(),this.running++,this.lastExecution=Date.now();try{return await a()}finally{this.running--,this.processQueue()}}waitForSlot(){if(this.running<this.maxConcurrent){let a=Date.now()-this.lastExecution;if(a>=this.minInterval)return Promise.resolve();return $a(this.minInterval-a)}return new Promise((a)=>this.queue.push(a))}processQueue(){if(this.queue.length>0&&this.running<this.maxConcurrent)this.queue.shift()()}stats(){return{running:this.running,queued:this.queue.length}}}function qf(a,n){let i=[];for(let s=0;s<a.length;s+=n)i.push(a.slice(s,s+n));return i}async function FI(a,n,i){let s=qf(a,n),c=[];for(let l of s){let u=await i(l);c.push(...u)}return c}function UI(a,n){let i=[],s=[],c=[],l=[],u=a.Resources||{},h=n.Resources||{},y=new Set(Object.keys(u)),S=new Set(Object.keys(h));for(let C of S)if(!y.has(C))i.push(C);for(let C of y)if(!S.has(C))c.push(C);for(let C of S)if(y.has(C)){let T=u[C],v=h[C];if(JSON.stringify(T)!==JSON.stringify(v))s.push(C);else l.push(C)}let b=JSON.stringify(a.Parameters||{})!==JSON.stringify(n.Parameters||{}),A=JSON.stringify(a.Outputs||{})!==JSON.stringify(n.Outputs||{});return{added:i,modified:s,deleted:c,unchanged:l,parametersChanged:b,outputsChanged:A,hasChanges:i.length>0||s.length>0||c.length>0||b||A}}function QI(a){let n=[];if(!a.hasChanges)return"No changes detected";if(a.added.length>0){n.push(`Added resources (${a.added.length}):`);for(let i of a.added)n.push(` + ${i}`)}if(a.modified.length>0){n.push(`Modified resources (${a.modified.length}):`);for(let i of a.modified)n.push(` ~ ${i}`)}if(a.deleted.length>0){n.push(`Deleted resources (${a.deleted.length}):`);for(let i of a.deleted)n.push(` - ${i}`)}if(a.parametersChanged)n.push("Parameters changed");if(a.outputsChanged)n.push("Outputs changed");return n.join(`
2512
- `)}function HI(a,n,i){if(a.deleted.length>0)return!0;for(let s of a.modified){let c=n.Resources[s],l=i.Resources[s];if(c.Type!==l.Type)return!0;let u=Rn(l.Type);for(let h of u){let y=c.Properties?.[h],S=l.Properties?.[h];if(JSON.stringify(y)!==JSON.stringify(S))return!0}}return!1}function Rn(a){return{"AWS::S3::Bucket":["BucketName"],"AWS::EC2::Instance":["ImageId","InstanceType","KeyName"],"AWS::RDS::DBInstance":["DBInstanceIdentifier","Engine"],"AWS::DynamoDB::Table":["TableName","KeySchema"],"AWS::Lambda::Function":["FunctionName"],"AWS::ECS::Service":["ServiceName"],"AWS::ElasticLoadBalancingV2::LoadBalancer":["Name","Type"]}[a]||[]}function GI(a){let n=[],i=[],s=[];n.push(...a.added);for(let c of a.modified)i.push(c);return s.push(...a.deleted),{safe:n,caution:i,dangerous:s}}function qI(a){if(!a.hasChanges)return{strategy:"skip",reason:"No changes detected"};if(a.deleted.length>0)return{strategy:"replace",reason:"Resources will be deleted"};if(a.added.length>0&&a.modified.length===0)return{strategy:"update",reason:"Only new resources added"};return{strategy:"update",reason:"Resources will be updated"}}function VI(a){let n=a.added.length+a.modified.length+a.deleted.length+a.unchanged.length,i=a.added.length+a.modified.length+a.deleted.length,s=n>0?i/n*100:0;return{total:n,added:a.added.length,modified:a.modified.length,deleted:a.deleted.length,unchanged:a.unchanged.length,changePercentage:s}}var jI={$schema:"http://json-schema.org/draft-07/schema#",title:"ts-cloud Configuration",description:"Configuration schema for ts-cloud infrastructure-as-code",type:"object",required:["project"],properties:{project:{type:"object",description:"Project configuration",required:["name","slug"],properties:{name:{type:"string",description:"Human-readable project name",minLength:1},slug:{type:"string",description:"URL-safe project identifier (lowercase, alphanumeric, hyphens only)",pattern:"^[a-z0-9-]+$",minLength:1,maxLength:63},region:{type:"string",description:"Default AWS region",enum:["us-east-1","us-east-2","us-west-1","us-west-2","eu-west-1","eu-west-2","eu-west-3","eu-central-1","ap-southeast-1","ap-southeast-2","ap-northeast-1","ap-northeast-2","sa-east-1","ca-central-1"]}}},mode:{type:"string",description:"Deployment mode (server and serverless are mutually exclusive; auto-detected when omitted)",enum:["server","serverless"]},environments:{type:"object",description:"Environment-specific configurations",properties:{production:{$ref:"#/definitions/environment"},staging:{$ref:"#/definitions/environment"},development:{$ref:"#/definitions/environment"}}},infrastructure:{type:"object",description:"Infrastructure configuration",properties:{network:{$ref:"#/definitions/network"},storage:{type:"object",description:"S3 storage configuration",additionalProperties:{$ref:"#/definitions/storage"}},compute:{$ref:"#/definitions/compute"},database:{$ref:"#/definitions/database"},cache:{$ref:"#/definitions/cache"},cdn:{$ref:"#/definitions/cdn"},sftp:{$ref:"#/definitions/sftp"},functions:{type:"object",description:"Lambda functions configuration",additionalProperties:{type:"array",items:{$ref:"#/definitions/function"}}},monitoring:{$ref:"#/definitions/monitoring"},security:{$ref:"#/definitions/security"},queue:{type:"object",description:"SQS queue configuration",additionalProperties:{$ref:"#/definitions/queue"}}}}},definitions:{environment:{type:"object",properties:{domain:{type:"string",description:"Custom domain for this environment"},region:{type:"string",description:"AWS region override for this environment"},app:{type:"object",description:"Serverless application manifest (Laravel-Vapor-equivalent). Defining this opts the environment into the serverless app deploy pipeline (http/queue/cli Lambda functions, assets, build/deploy hooks).",properties:{runtime:{type:"string",description:"Lambda runtime override (usually derived from kind + runtimeVersion)"},runtimeVersion:{type:"string",description:"Node major (18/20/22 managed, 24+ custom layer) or Bun release for node/bun apps"},kind:{type:"string",enum:["node","bun","php"],description:"Application kind (drives packaging + runtime)"},entry:{type:"string",description:"Entry file exporting the request handler"},memory:{type:"number",description:"HTTP function memory in MB"},timeout:{type:"number",description:"HTTP request timeout in seconds"},gatewayVersion:{type:"number",enum:[1,2],description:"API Gateway version (2 = HTTP API, 1 = REST)"},warm:{type:"number",description:"Keep-warm / provisioned concurrency count"},lambdaInsights:{type:"object",description:"CloudWatch Lambda Insights extension configuration for zip deployments",required:["layerArn"],properties:{layerArn:{type:"string",description:"Region- and architecture-specific Lambda Insights extension layer ARN"}}},queues:{description:"Queue names (true = single default queue, false = disabled)"},scheduler:{type:"string",enum:["off","on","sub-minute"],description:"Task scheduler mode"},build:{type:"array",items:{type:"string"},description:"Commands run locally before packaging"},deploy:{type:"array",items:{type:"string"},description:"Commands run remotely after activation (e.g. migrations)"},octane:{type:"boolean",description:"Persistent application mode (Laravel Octane)"},packaging:{type:"string",enum:["zip","image"],description:"Deployment package format (zip or container image)"},phpVersion:{type:"string",description:"PHP version for the runtime layer (kind: php)"},architecture:{type:"string",enum:["x86_64","arm64"],description:"CPU architecture"}}}}},network:{type:"object",properties:{vpc:{type:"object",properties:{cidr:{type:"string",description:"VPC CIDR block",pattern:"^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]{1,2}$",default:"10.0.0.0/16"},availabilityZones:{type:"number",description:"Number of availability zones",minimum:1,maximum:3,default:2},natGateways:{type:"number",description:"Number of NAT gateways (0 for no NAT, saves cost)",minimum:0,maximum:3,default:1}}}}},storage:{type:"object",properties:{public:{type:"boolean",description:"Allow public access",default:!1},versioning:{type:"boolean",description:"Enable versioning",default:!1},encryption:{type:"boolean",description:"Enable server-side encryption",default:!0},website:{type:"boolean",description:"Enable static website hosting",default:!1},cors:{type:"object",description:"CORS configuration",properties:{allowedOrigins:{type:"array",items:{type:"string"}},allowedMethods:{type:"array",items:{type:"string",enum:["GET","PUT","POST","DELETE","HEAD"]}}}}}},compute:{type:"object",properties:{server:{type:"object",description:"EC2 server configuration",properties:{instanceType:{type:"string",description:"EC2 instance type",enum:["t3.micro","t3.small","t3.medium","t3.large","t3.xlarge","t3.2xlarge"]},autoScaling:{type:"object",properties:{min:{type:"number",minimum:1},max:{type:"number",minimum:1},desired:{type:"number",minimum:1}}}}},fargate:{type:"object",description:"ECS Fargate configuration",properties:{cpu:{type:"number",description:"CPU units (256, 512, 1024, 2048, 4096)",enum:[256,512,1024,2048,4096]},memory:{type:"number",description:"Memory in MB"},desiredCount:{type:"number",description:"Desired number of tasks",minimum:1}}}}},database:{type:"object",properties:{postgres:{type:"object",properties:{instanceClass:{type:"string",description:"RDS instance class",pattern:"^db\\.[a-z0-9]+\\.[a-z0-9]+$"},engine:{type:"string",const:"postgres"},version:{type:"string",description:"PostgreSQL version"},multiAZ:{type:"boolean",description:"Enable Multi-AZ deployment",default:!1},backupRetentionDays:{type:"number",description:"Backup retention period in days",minimum:0,maximum:35,default:7}}},mysql:{type:"object",properties:{instanceClass:{type:"string",pattern:"^db\\.[a-z0-9]+\\.[a-z0-9]+$"},engine:{type:"string",const:"mysql"},version:{type:"string"},multiAZ:{type:"boolean",default:!1},backupRetentionDays:{type:"number",minimum:0,maximum:35,default:7}}},dynamodb:{type:"object",properties:{tables:{type:"array",items:{type:"object",required:["name","partitionKey"],properties:{name:{type:"string"},partitionKey:{type:"string"},sortKey:{type:"string"},billingMode:{type:"string",enum:["PAY_PER_REQUEST","PROVISIONED"],default:"PAY_PER_REQUEST"}}}}}}}},cache:{type:"object",properties:{redis:{type:"object",properties:{nodeType:{type:"string",description:"ElastiCache node type",pattern:"^cache\\.[a-z0-9]+\\.[a-z0-9]+$"},numCacheNodes:{type:"number",minimum:1,default:1},engineVersion:{type:"string",description:"Redis engine version"}}},memcached:{type:"object",properties:{nodeType:{type:"string",pattern:"^cache\\.[a-z0-9]+\\.[a-z0-9]+$"},numCacheNodes:{type:"number",minimum:1,default:1}}}}},cdn:{type:"object",properties:{enabled:{type:"boolean",default:!0},originShield:{type:"boolean",description:"Enable CloudFront Origin Shield",default:!1},originShieldRegion:{type:"string",description:"AWS region used by CloudFront Origin Shield"},compress:{type:"boolean",description:"Enable automatic compression",default:!0},http3:{type:"boolean",description:"Enable HTTP/3 support",default:!0},customDomain:{type:"object",properties:{domain:{type:"string"},certificateArn:{type:"string"}}},cachePolicy:{type:"object",properties:{minTTL:{type:"number",minimum:0},defaultTTL:{type:"number",minimum:0},maxTTL:{type:"number",minimum:0}}}}},sftp:{type:"object",required:["bucket","users"],properties:{bucket:{type:"string",description:"S3 bucket backing the SFTP server"},endpointType:{type:"string",enum:["PUBLIC","VPC"],default:"PUBLIC"},endpointDetails:{type:"object",required:["vpcId","subnetIds"],properties:{vpcId:{type:"string"},subnetIds:{type:"array",items:{type:"string"},minItems:1},securityGroupIds:{type:"array",items:{type:"string"}},addressAllocationIds:{type:"array",items:{type:"string"}}}},securityPolicyName:{type:"string"},logging:{type:"boolean",default:!0},users:{type:"object",additionalProperties:{type:"object",required:["sshPublicKeys"],properties:{sshPublicKeys:{type:"array",items:{type:"string"},minItems:1},homeDirectory:{type:"string"},roleArn:{type:"string"}}}}}},function:{type:"object",required:["name","runtime"],properties:{name:{type:"string"},runtime:{type:"string",enum:["nodejs18.x","nodejs20.x","python3.10","python3.11","python3.12"]},handler:{type:"string",default:"index.handler"},timeout:{type:"number",minimum:1,maximum:900,default:30},memory:{type:"number",minimum:128,maximum:10240,default:1024}}},monitoring:{type:"object",properties:{alarms:{type:"array",items:{type:"object",required:["metric","threshold"],properties:{metric:{type:"string"},threshold:{type:"number"},evaluationPeriods:{type:"number",minimum:1,default:2}}}},dashboard:{type:"object",properties:{name:{type:"string"},widgets:{type:"array"}}}}},security:{type:"object",properties:{waf:{type:"boolean",description:"Enable AWS WAF",default:!1},certificates:{type:"array",items:{type:"object",required:["domain"],properties:{domain:{type:"string"},subdomains:{type:"array",items:{type:"string"}}}}}}},queue:{type:"object",properties:{fifo:{type:"boolean",default:!1},deadLetterQueue:{type:"boolean",default:!0},visibilityTimeout:{type:"number",minimum:0,maximum:43200,default:30},messageRetentionPeriod:{type:"number",minimum:60,maximum:1209600,default:345600}}}}};function zI(a){let n=[];if(!a.project)n.push("Missing required field: project");else{if(!a.project.name)n.push("Missing required field: project.name");if(!a.project.slug)n.push("Missing required field: project.slug")}if(a.project?.slug&&!/^[a-z0-9-]+$/.test(a.project.slug))n.push("Invalid project.slug: must contain only lowercase letters, numbers, and hyphens");let i=["us-east-1","us-east-2","us-west-1","us-west-2","eu-west-1","eu-west-2","eu-west-3","eu-central-1","ap-southeast-1","ap-southeast-2","ap-northeast-1","ap-northeast-2","sa-east-1","ca-central-1"];if(a.project?.region&&!i.includes(a.project.region))n.push(`Invalid region: ${a.project.region}. Must be one of: ${i.join(", ")}`);if(a.mode&&!["server","serverless"].includes(a.mode))n.push("Invalid mode: must be one of server or serverless");return{valid:n.length===0,errors:n}}var zp={enabled:process.env.TS_CLOUD_LOCAL==="true"||!0,localstackEndpoint:process.env.LOCALSTACK_ENDPOINT||"http://localhost:4566",postgresUrl:process.env.POSTGRES_URL||"postgresql://tscloud:tscloud@localhost:5432/tscloud",redisUrl:process.env.REDIS_URL||"redis://localhost:6379",dynamodbEndpoint:process.env.DYNAMODB_ENDPOINT||"http://localhost:8000",s3Endpoint:process.env.S3_ENDPOINT||"http://localhost:9000",emailEndpoint:process.env.EMAIL_ENDPOINT||"smtp://localhost:1025",awsRegion:process.env.AWS_REGION||"us-east-1",awsAccessKeyId:process.env.AWS_ACCESS_KEY_ID||"test",awsSecretAccessKey:process.env.AWS_SECRET_ACCESS_KEY||"test"};function Id(){return zp}function KI(){return zp.enabled}function WI(a){let n=Id();if(!n.enabled)return"";switch(a.toLowerCase()){case"dynamodb":return n.dynamodbEndpoint;case"s3":return n.s3Endpoint;case"localstack":case"cloudformation":case"lambda":case"apigateway":case"sns":case"sqs":case"cloudwatch":case"iam":case"sts":return n.localstackEndpoint;default:return n.localstackEndpoint}}function JI(){let a=Id();return{accessKeyId:a.awsAccessKeyId,secretAccessKey:a.awsSecretAccessKey,region:a.awsRegion}}function XI(){let a=Id();if(!a.enabled)return{};return{AWS_ACCESS_KEY_ID:a.awsAccessKeyId,AWS_SECRET_ACCESS_KEY:a.awsSecretAccessKey,AWS_REGION:a.awsRegion,AWS_ENDPOINT_URL:a.localstackEndpoint,LOCALSTACK_ENDPOINT:a.localstackEndpoint,TS_CLOUD_LOCAL:"true"}}class Kp{stacks=new Map;stackEvents=new Map;async createStack(a){let n=`arn:aws:cloudformation:${a.region||"us-east-1"}:123456789012:stack/${a.StackName}/${Date.now()}`;return this.stacks.set(a.StackName,{StackId:n,StackName:a.StackName,StackStatus:"CREATE_IN_PROGRESS",CreationTime:new Date().toISOString(),TemplateBody:a.TemplateBody,Parameters:a.Parameters||[]}),this.addEvent(a.StackName,{EventId:Date.now().toString(),StackName:a.StackName,LogicalResourceId:a.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_IN_PROGRESS"}),setTimeout(()=>{let i=this.stacks.get(a.StackName);if(i)i.StackStatus="CREATE_COMPLETE",this.addEvent(a.StackName,{EventId:(Date.now()+1).toString(),StackName:a.StackName,LogicalResourceId:a.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_COMPLETE"})},100),{StackId:n}}async updateStack(a){let n=this.stacks.get(a.StackName);if(!n)throw Error(`Stack ${a.StackName} does not exist`);return n.StackStatus="UPDATE_IN_PROGRESS",n.TemplateBody=a.TemplateBody||n.TemplateBody,this.addEvent(a.StackName,{EventId:Date.now().toString(),StackName:a.StackName,LogicalResourceId:a.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_IN_PROGRESS"}),setTimeout(()=>{n.StackStatus="UPDATE_COMPLETE",this.addEvent(a.StackName,{EventId:(Date.now()+1).toString(),StackName:a.StackName,LogicalResourceId:a.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_COMPLETE"})},100),{StackId:n.StackId}}async deleteStack(a){let n=this.stacks.get(a.StackName);if(!n)throw Error(`Stack ${a.StackName} does not exist`);n.StackStatus="DELETE_IN_PROGRESS",this.addEvent(a.StackName,{EventId:Date.now().toString(),StackName:a.StackName,LogicalResourceId:a.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_IN_PROGRESS"}),setTimeout(()=>{this.stacks.delete(a.StackName),this.addEvent(a.StackName,{EventId:(Date.now()+1).toString(),StackName:a.StackName,LogicalResourceId:a.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_COMPLETE"})},100)}async describeStacks(a){if(a.StackName){let n=this.stacks.get(a.StackName);if(!n)throw Error(`Stack ${a.StackName} does not exist`);return{Stacks:[n]}}return{Stacks:Array.from(this.stacks.values())}}async describeStackEvents(a){return{StackEvents:this.stackEvents.get(a.StackName)||[]}}addEvent(a,n){if(!this.stackEvents.has(a))this.stackEvents.set(a,[]);this.stackEvents.get(a).unshift(n)}reset(){this.stacks.clear(),this.stackEvents.clear()}}class Wp{buckets=new Map;async createBucket(a){return this.buckets.set(a.Bucket,new Map),{Location:`/${a.Bucket}`}}async deleteBucket(a){this.buckets.delete(a.Bucket)}async putObject(a){let n=this.buckets.get(a.Bucket);if(!n)n=new Map,this.buckets.set(a.Bucket,n);return n.set(a.Key,Buffer.from(a.Body||"")),{ETag:`"${Date.now()}"`}}async getObject(a){let n=this.buckets.get(a.Bucket);if(!n)throw Error(`Bucket ${a.Bucket} does not exist`);let i=n.get(a.Key);if(!i)throw Error(`Object ${a.Key} does not exist`);return{Body:i,ContentLength:i.length}}async deleteObject(a){let n=this.buckets.get(a.Bucket);if(n)n.delete(a.Key)}async listObjects(a){let n=this.buckets.get(a.Bucket);if(!n)throw Error(`Bucket ${a.Bucket} does not exist`);return{Contents:Array.from(n.keys()).map((i)=>({Key:i,Size:n.get(i).length,LastModified:new Date().toISOString()}))}}reset(){this.buckets.clear()}}class Jp{tables=new Map;data=new Map;async createTable(a){return this.tables.set(a.TableName,{TableName:a.TableName,KeySchema:a.KeySchema,AttributeDefinitions:a.AttributeDefinitions,TableStatus:"ACTIVE",CreationDateTime:new Date().toISOString()}),this.data.set(a.TableName,new Map),{TableDescription:this.tables.get(a.TableName)}}async deleteTable(a){this.tables.delete(a.TableName),this.data.delete(a.TableName)}async putItem(a){let n=this.data.get(a.TableName);if(!n)n=new Map,this.data.set(a.TableName,n);let i=JSON.stringify(a.Item);n.set(i,a.Item)}async getItem(a){let n=this.data.get(a.TableName);if(!n)return{};let i=JSON.stringify(a.Key),s=n.get(i);return s?{Item:s}:{}}async deleteItem(a){let n=this.data.get(a.TableName);if(n){let i=JSON.stringify(a.Key);n.delete(i)}}async scan(a){let n=this.data.get(a.TableName);if(!n)return{Items:[]};return{Items:Array.from(n.values())}}reset(){this.tables.clear(),this.data.clear()}}function YI(a){return{cloudformation:new Kp,s3:new Wp,dynamodb:new Jp}}class Xp{environments=new Map;async createPreviewEnvironment(a){let{branch:n,pr:i,commitSha:s,ttl:c=24,baseConfig:l,region:u="us-east-1"}=a,h=this.generatePreviewId(n,i,s),y=this.generatePreviewName(n,i),S=`preview-${y}`,b=new Date,A=new Date(b.getTime()+c*60*60*1000),C={id:h,name:y,branch:n,pr:i,commitSha:s,createdAt:b,expiresAt:A,status:"creating",stackName:S,region:u,resources:[]};this.environments.set(h,C);try{let T=this.createPreviewConfig(l,y);return C.status="active",C.url=`https://${y}.preview.example.com`,C}catch(T){throw C.status="failed",T}}async destroyPreviewEnvironment(a){let n=this.environments.get(a);if(!n)throw Error(`Preview environment ${a} not found`);n.status="destroying";try{n.status="destroyed",this.environments.delete(a)}catch(i){throw Error(`Failed to destroy preview environment: ${i}`)}}getPreviewEnvironment(a){return this.environments.get(a)}getPreviewEnvironmentByBranch(a){return Array.from(this.environments.values()).find((n)=>n.branch===a)}getPreviewEnvironmentByPR(a){return Array.from(this.environments.values()).find((n)=>n.pr===a)}listPreviewEnvironments(){return Array.from(this.environments.values())}listActivePreviewEnvironments(){return this.listPreviewEnvironments().filter((a)=>a.status==="active")}async cleanupExpiredEnvironments(a={}){let{maxAge:n,keepCount:i,dryRun:s=!1}=a,c=[],l=[],u=new Date,h=this.listPreviewEnvironments().sort((y,S)=>S.createdAt.getTime()-y.createdAt.getTime());for(let y=0;y<h.length;y++){let S=h[y];if(S.status!=="active")continue;let b=!1;if(S.expiresAt<u)b=!0;if(n){if((u.getTime()-S.createdAt.getTime())/3600000>n)b=!0}if(i&&y>=i)b=!0;if(b)if(s)c.push(S.id);else try{await this.destroyPreviewEnvironment(S.id),c.push(S.id)}catch(A){l.push(S.id)}}return{destroyed:c,failed:l}}async updatePreviewEnvironment(a,n){let i=this.environments.get(a);if(!i)throw Error(`Preview environment ${a} not found`);i.commitSha=n,i.status="creating";try{return i.status="active",i}catch(s){throw i.status="failed",s}}async getPreviewEnvironmentsCost(){let a={},n=0;for(let i of this.environments.values())a[i.id]=0,n+=0;return{total:n,byEnvironment:a}}generatePreviewId(a,n,i){let s=a.replace(/[^a-z0-9-]/gi,"-").toLowerCase(),c=i?.substring(0,7)||Date.now().toString();return n?`pr-${n}-${c}`:`${s}-${c}`}generatePreviewName(a,n){let i=a.replace(/[^a-z0-9-]/gi,"-").toLowerCase();return n?`pr-${n}`:i}createPreviewConfig(a,n){return{...a,project:{...a.project,name:`${a.project.name} Preview (${n})`,slug:`${a.project.slug}-preview-${n}`}}}}var ZI=new Xp;function eS(a={}){let{workflowName:n="Preview Environment",trigger:i="pull_request",branches:s=["main","develop"],awsRegion:c="us-east-1",awsRole:l,configFile:u="cloud.config.ts",ttl:h=24}=a;return`name: ${n}
2510
+ `}return n}function RI(a){let n=[];for(let i of a)if(i.percentage>=100)n.push(`Request quota increase for ${i.service} - ${i.quotaName} (currently ${i.limit})`);else if(i.warning)n.push(`Consider requesting quota increase for ${i.service} - ${i.quotaName} (${i.percentage.toFixed(1)}% used)`);return n}class Gp{cacheDir;ttl;constructor(a,n={}){this.cacheDir=a,this.ttl=n.ttl||86400000}ensureCacheDir(){if(!st(this.cacheDir))Tn(this.cacheDir,{recursive:!0})}getCachePath(a){let n=ka("sha256").update(a).digest("hex");return It(this.cacheDir,`${n}.json`)}get(a){let n=this.getCachePath(a);if(!st(n))return;try{let i=da(n,"utf-8"),s=JSON.parse(i);if(Date.now()-s.timestamp>this.ttl){ze(n);return}return s.value}catch{ze(n);return}}set(a,n,i){this.ensureCacheDir();let s=this.getCachePath(a),c={value:n,timestamp:Date.now(),hash:i};vn(s,JSON.stringify(c),"utf-8")}has(a){return this.get(a)!==void 0}clear(){if(!st(this.cacheDir))return;let a=ua(this.cacheDir);for(let n of a)ze(It(this.cacheDir,n))}prune(){if(!st(this.cacheDir))return;let a=ua(this.cacheDir),n=Date.now();for(let i of a){let s=It(this.cacheDir,i);try{let c=da(s,"utf-8"),l=JSON.parse(c);if(n-l.timestamp>this.ttl)ze(s)}catch{ze(s)}}}}class qp{cache;constructor(a=x("cache","templates")){this.cache=new Gp(a,{ttl:86400000})}getTemplate(a){return this.cache.get(`template:${a}`)}setTemplate(a,n){let i=this.hashTemplate(n);this.cache.set(`template:${a}`,n,i)}hasChanged(a,n){let i=this.cache.get(`template:${a}`);if(!i)return!0;let s=this.hashTemplate(i),c=this.hashTemplate(n);return s!==c}hashTemplate(a){return ka("sha256").update(a).digest("hex")}clear(){this.cache.clear()}prune(){this.cache.prune()}}var Rt=null;function DI(){if(!Rt)Rt=new qp;return Rt}async function Vp(a,n={}){let i=n.algorithm||"sha256",s=n.chunkSize||65536;return new Promise((c,l)=>{let u=Wt(i),h=wn(a,{highWaterMark:s});h.on("data",(y)=>u.update(y)),h.on("end",()=>c(u.digest("hex"))),h.on("error",l)})}function jp(a,n="sha256"){return Wt(n).update(a).digest("hex")}function PI(a,n="sha256"){return Wt(n).update(a).digest("hex")}async function NI(a,n={}){let i=n.ignorePatterns||["node_modules",".git","dist","build",Js()],s=[];async function c(l){let u=En(l,{withFileTypes:!0});for(let h of u){let y=Pn(l,h.name),S=In(a,y);if(i.some((A)=>S.includes(A)))continue;if(h.isDirectory())await c(y);else if(h.isFile()){let A=ht(y),C=await Vp(y,n);s.push({path:S,hash:C,size:A.size,mtime:A.mtimeMs})}}}return await c(a),s}function kI(a){let n=[...a].sort((i,s)=>i.path.localeCompare(s.path)).map((i)=>`${i.path}:${i.hash}`).join(`
2511
+ `);return jp(n)}function BI(a){let n=ht(a);return jp(`${a}:${n.size}:${n.mtimeMs}`)}function _I(a,n){let i=new Map(a.map((h)=>[h.path,h])),s=new Map(n.map((h)=>[h.path,h])),c=[],l=[],u=[];for(let[h,y]of s){let S=i.get(h);if(!S)c.push(y);else if(S.hash!==y.hash)l.push(y)}for(let[h,y]of i)if(!s.has(h))u.push(y);return{added:c,modified:l,deleted:u}}class Hf{cache;constructor(){this.cache=new Map}get(a){let n=ht(a),i=this.cache.get(a);if(i&&i.mtime===n.mtimeMs&&i.size===n.size)return i.hash;return}set(a,n){let i=ht(a);this.cache.set(a,{hash:n,mtime:i.mtimeMs,size:i.size})}async getOrCompute(a,n={}){let i=this.get(a);if(i)return i;let s=await Vp(a,n);return this.set(a,s),s}clear(){this.cache.clear()}}async function yd(a,n={}){let i=n.concurrency||5,s=n.stopOnError??!0,c=[],l=[],u=Date.now(),h=[...a],y=[];async function S(T,v){try{let w=await T();c[v]=w}catch(w){let E=w instanceof Error?w:Error(String(w));if(l.push(E),s)throw h.length=0,E}}let A=0;while(h.length>0||y.length>0){while(y.length<i&&h.length>0){let T=h.shift(),v=A++,w=S(T,v);y.push(w)}if(y.length>0){await Promise.race(y);for(let T=y.length-1;T>=0;T--)if(await Promise.race([y[T].then(()=>!0),Promise.resolve(!1)]))y.splice(T,1)}if(s&&l.length>0)break}let C=Date.now()-u;return{results:c.filter((T)=>T!==void 0),errors:l,duration:C}}async function xI(a,n,i={}){let s=a.map((c)=>()=>n(c));return yd(s,i)}async function OI(a,n,i=5){let s=a.map((l,u)=>()=>n(l,u)),c=await yd(s,{concurrency:i,stopOnError:!1});if(c.errors.length>0)throw AggregateError(c.errors,"Parallel map failed");return c.results}async function LI(a,n={}){let i=n.retries||3,s=n.retryDelay||1000,c=a.map((l)=>async()=>{let u;for(let h=0;h<=i;h++)try{return await l()}catch(y){if(u=y instanceof Error?y:Error(String(y)),h<i)await $a(s*(h+1))}throw u});return yd(c,n)}async function $I(a){let n=[];for(let i of a){let s=await i();n.push(s)}return n}function $a(a){return new Promise((n)=>setTimeout(n,a))}async function MI(a,n,i="Operation timed out"){return Promise.race([a(),new Promise((s,c)=>setTimeout(()=>c(Error(i)),n))])}class Gf{maxConcurrent;minInterval;queue=[];running=0;lastExecution=0;constructor(a=5,n=100){this.maxConcurrent=a,this.minInterval=n}async execute(a){await this.waitForSlot(),this.running++,this.lastExecution=Date.now();try{return await a()}finally{this.running--,this.processQueue()}}waitForSlot(){if(this.running<this.maxConcurrent){let a=Date.now()-this.lastExecution;if(a>=this.minInterval)return Promise.resolve();return $a(this.minInterval-a)}return new Promise((a)=>this.queue.push(a))}processQueue(){if(this.queue.length>0&&this.running<this.maxConcurrent)this.queue.shift()()}stats(){return{running:this.running,queued:this.queue.length}}}function qf(a,n){let i=[];for(let s=0;s<a.length;s+=n)i.push(a.slice(s,s+n));return i}async function FI(a,n,i){let s=qf(a,n),c=[];for(let l of s){let u=await i(l);c.push(...u)}return c}function UI(a,n){let i=[],s=[],c=[],l=[],u=a.Resources||{},h=n.Resources||{},y=new Set(Object.keys(u)),S=new Set(Object.keys(h));for(let T of S)if(!y.has(T))i.push(T);for(let T of y)if(!S.has(T))c.push(T);for(let T of S)if(y.has(T)){let v=u[T],w=h[T];if(JSON.stringify(v)!==JSON.stringify(w))s.push(T);else l.push(T)}let A=JSON.stringify(a.Parameters||{})!==JSON.stringify(n.Parameters||{}),C=JSON.stringify(a.Outputs||{})!==JSON.stringify(n.Outputs||{});return{added:i,modified:s,deleted:c,unchanged:l,parametersChanged:A,outputsChanged:C,hasChanges:i.length>0||s.length>0||c.length>0||A||C}}function QI(a){let n=[];if(!a.hasChanges)return"No changes detected";if(a.added.length>0){n.push(`Added resources (${a.added.length}):`);for(let i of a.added)n.push(` + ${i}`)}if(a.modified.length>0){n.push(`Modified resources (${a.modified.length}):`);for(let i of a.modified)n.push(` ~ ${i}`)}if(a.deleted.length>0){n.push(`Deleted resources (${a.deleted.length}):`);for(let i of a.deleted)n.push(` - ${i}`)}if(a.parametersChanged)n.push("Parameters changed");if(a.outputsChanged)n.push("Outputs changed");return n.join(`
2512
+ `)}function HI(a,n,i){if(a.deleted.length>0)return!0;for(let s of a.modified){let c=n.Resources[s],l=i.Resources[s];if(c.Type!==l.Type)return!0;let u=Rn(l.Type);for(let h of u){let y=c.Properties?.[h],S=l.Properties?.[h];if(JSON.stringify(y)!==JSON.stringify(S))return!0}}return!1}function Rn(a){return{"AWS::S3::Bucket":["BucketName"],"AWS::EC2::Instance":["ImageId","InstanceType","KeyName"],"AWS::RDS::DBInstance":["DBInstanceIdentifier","Engine"],"AWS::DynamoDB::Table":["TableName","KeySchema"],"AWS::Lambda::Function":["FunctionName"],"AWS::ECS::Service":["ServiceName"],"AWS::ElasticLoadBalancingV2::LoadBalancer":["Name","Type"]}[a]||[]}function GI(a){let n=[],i=[],s=[];n.push(...a.added);for(let c of a.modified)i.push(c);return s.push(...a.deleted),{safe:n,caution:i,dangerous:s}}function qI(a){if(!a.hasChanges)return{strategy:"skip",reason:"No changes detected"};if(a.deleted.length>0)return{strategy:"replace",reason:"Resources will be deleted"};if(a.added.length>0&&a.modified.length===0)return{strategy:"update",reason:"Only new resources added"};return{strategy:"update",reason:"Resources will be updated"}}function VI(a){let n=a.added.length+a.modified.length+a.deleted.length+a.unchanged.length,i=a.added.length+a.modified.length+a.deleted.length,s=n>0?i/n*100:0;return{total:n,added:a.added.length,modified:a.modified.length,deleted:a.deleted.length,unchanged:a.unchanged.length,changePercentage:s}}var jI={$schema:"http://json-schema.org/draft-07/schema#",title:"ts-cloud Configuration",description:"Configuration schema for ts-cloud infrastructure-as-code",type:"object",required:["project"],properties:{project:{type:"object",description:"Project configuration",required:["name","slug"],properties:{name:{type:"string",description:"Human-readable project name",minLength:1},slug:{type:"string",description:"URL-safe project identifier (lowercase, alphanumeric, hyphens only)",pattern:"^[a-z0-9-]+$",minLength:1,maxLength:63},region:{type:"string",description:"Default AWS region",enum:["us-east-1","us-east-2","us-west-1","us-west-2","eu-west-1","eu-west-2","eu-west-3","eu-central-1","ap-southeast-1","ap-southeast-2","ap-northeast-1","ap-northeast-2","sa-east-1","ca-central-1"]}}},mode:{type:"string",description:"Deployment mode (server and serverless are mutually exclusive; auto-detected when omitted)",enum:["server","serverless"]},environments:{type:"object",description:"Environment-specific configurations",properties:{production:{$ref:"#/definitions/environment"},staging:{$ref:"#/definitions/environment"},development:{$ref:"#/definitions/environment"}}},infrastructure:{type:"object",description:"Infrastructure configuration",properties:{network:{$ref:"#/definitions/network"},storage:{type:"object",description:"S3 storage configuration",additionalProperties:{$ref:"#/definitions/storage"}},compute:{$ref:"#/definitions/compute"},database:{$ref:"#/definitions/database"},cache:{$ref:"#/definitions/cache"},cdn:{$ref:"#/definitions/cdn"},sftp:{$ref:"#/definitions/sftp"},functions:{type:"object",description:"Lambda functions configuration",additionalProperties:{type:"array",items:{$ref:"#/definitions/function"}}},monitoring:{$ref:"#/definitions/monitoring"},security:{$ref:"#/definitions/security"},queue:{type:"object",description:"SQS queue configuration",additionalProperties:{$ref:"#/definitions/queue"}}}}},definitions:{environment:{type:"object",properties:{domain:{type:"string",description:"Custom domain for this environment"},region:{type:"string",description:"AWS region override for this environment"},app:{type:"object",description:"Serverless application manifest (Laravel-Vapor-equivalent). Defining this opts the environment into the serverless app deploy pipeline (http/queue/cli Lambda functions, assets, build/deploy hooks).",properties:{runtime:{type:"string",description:"Lambda runtime override (usually derived from kind + runtimeVersion)"},runtimeVersion:{type:"string",description:"Node major (18/20/22 managed, 24+ custom layer) or Bun release for node/bun apps"},kind:{type:"string",enum:["node","bun","php"],description:"Application kind (drives packaging + runtime)"},entry:{type:"string",description:"Entry file exporting the request handler"},memory:{type:"number",description:"HTTP function memory in MB"},timeout:{type:"number",description:"HTTP request timeout in seconds"},gatewayVersion:{type:"number",enum:[1,2],description:"API Gateway version (2 = HTTP API, 1 = REST)"},warm:{type:"number",description:"Keep-warm / provisioned concurrency count"},lambdaInsights:{type:"object",description:"CloudWatch Lambda Insights extension configuration for zip deployments",required:["layerArn"],properties:{layerArn:{type:"string",description:"Region- and architecture-specific Lambda Insights extension layer ARN"}}},queues:{description:"Queue names (true = single default queue, false = disabled)"},scheduler:{type:"string",enum:["off","on","sub-minute"],description:"Task scheduler mode"},build:{type:"array",items:{type:"string"},description:"Commands run locally before packaging"},deploy:{type:"array",items:{type:"string"},description:"Commands run remotely after activation (e.g. migrations)"},octane:{type:"boolean",description:"Persistent application mode (Laravel Octane)"},packaging:{type:"string",enum:["zip","image"],description:"Deployment package format (zip or container image)"},phpVersion:{type:"string",description:"PHP version for the runtime layer (kind: php)"},architecture:{type:"string",enum:["x86_64","arm64"],description:"CPU architecture"}}}}},network:{type:"object",properties:{vpc:{type:"object",properties:{cidr:{type:"string",description:"VPC CIDR block",pattern:"^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]{1,2}$",default:"10.0.0.0/16"},availabilityZones:{type:"number",description:"Number of availability zones",minimum:1,maximum:3,default:2},natGateways:{type:"number",description:"Number of NAT gateways (0 for no NAT, saves cost)",minimum:0,maximum:3,default:1}}}}},storage:{type:"object",properties:{public:{type:"boolean",description:"Allow public access",default:!1},versioning:{type:"boolean",description:"Enable versioning",default:!1},encryption:{type:"boolean",description:"Enable server-side encryption",default:!0},website:{type:"boolean",description:"Enable static website hosting",default:!1},cors:{type:"object",description:"CORS configuration",properties:{allowedOrigins:{type:"array",items:{type:"string"}},allowedMethods:{type:"array",items:{type:"string",enum:["GET","PUT","POST","DELETE","HEAD"]}}}}}},compute:{type:"object",properties:{server:{type:"object",description:"EC2 server configuration",properties:{instanceType:{type:"string",description:"EC2 instance type",enum:["t3.micro","t3.small","t3.medium","t3.large","t3.xlarge","t3.2xlarge"]},autoScaling:{type:"object",properties:{min:{type:"number",minimum:1},max:{type:"number",minimum:1},desired:{type:"number",minimum:1}}}}},fargate:{type:"object",description:"ECS Fargate configuration",properties:{cpu:{type:"number",description:"CPU units (256, 512, 1024, 2048, 4096)",enum:[256,512,1024,2048,4096]},memory:{type:"number",description:"Memory in MB"},desiredCount:{type:"number",description:"Desired number of tasks",minimum:1}}}}},database:{type:"object",properties:{postgres:{type:"object",properties:{instanceClass:{type:"string",description:"RDS instance class",pattern:"^db\\.[a-z0-9]+\\.[a-z0-9]+$"},engine:{type:"string",const:"postgres"},version:{type:"string",description:"PostgreSQL version"},multiAZ:{type:"boolean",description:"Enable Multi-AZ deployment",default:!1},backupRetentionDays:{type:"number",description:"Backup retention period in days",minimum:0,maximum:35,default:7}}},mysql:{type:"object",properties:{instanceClass:{type:"string",pattern:"^db\\.[a-z0-9]+\\.[a-z0-9]+$"},engine:{type:"string",const:"mysql"},version:{type:"string"},multiAZ:{type:"boolean",default:!1},backupRetentionDays:{type:"number",minimum:0,maximum:35,default:7}}},dynamodb:{type:"object",properties:{tables:{type:"array",items:{type:"object",required:["name","partitionKey"],properties:{name:{type:"string"},partitionKey:{type:"string"},sortKey:{type:"string"},billingMode:{type:"string",enum:["PAY_PER_REQUEST","PROVISIONED"],default:"PAY_PER_REQUEST"}}}}}}}},cache:{type:"object",properties:{redis:{type:"object",properties:{nodeType:{type:"string",description:"ElastiCache node type",pattern:"^cache\\.[a-z0-9]+\\.[a-z0-9]+$"},numCacheNodes:{type:"number",minimum:1,default:1},engineVersion:{type:"string",description:"Redis engine version"}}},memcached:{type:"object",properties:{nodeType:{type:"string",pattern:"^cache\\.[a-z0-9]+\\.[a-z0-9]+$"},numCacheNodes:{type:"number",minimum:1,default:1}}}}},cdn:{type:"object",properties:{enabled:{type:"boolean",default:!0},originShield:{type:"boolean",description:"Enable CloudFront Origin Shield",default:!1},originShieldRegion:{type:"string",description:"AWS region used by CloudFront Origin Shield"},compress:{type:"boolean",description:"Enable automatic compression",default:!0},http3:{type:"boolean",description:"Enable HTTP/3 support",default:!0},customDomain:{type:"object",properties:{domain:{type:"string"},certificateArn:{type:"string"}}},cachePolicy:{type:"object",properties:{minTTL:{type:"number",minimum:0},defaultTTL:{type:"number",minimum:0},maxTTL:{type:"number",minimum:0}}}}},sftp:{type:"object",required:["bucket","users"],properties:{bucket:{type:"string",description:"S3 bucket backing the SFTP server"},endpointType:{type:"string",enum:["PUBLIC","VPC"],default:"PUBLIC"},endpointDetails:{type:"object",required:["vpcId","subnetIds"],properties:{vpcId:{type:"string"},subnetIds:{type:"array",items:{type:"string"},minItems:1},securityGroupIds:{type:"array",items:{type:"string"}},addressAllocationIds:{type:"array",items:{type:"string"}}}},securityPolicyName:{type:"string"},logging:{type:"boolean",default:!0},users:{type:"object",additionalProperties:{type:"object",required:["sshPublicKeys"],properties:{sshPublicKeys:{type:"array",items:{type:"string"},minItems:1},homeDirectory:{type:"string"},roleArn:{type:"string"}}}}}},function:{type:"object",required:["name","runtime"],properties:{name:{type:"string"},runtime:{type:"string",enum:["nodejs18.x","nodejs20.x","python3.10","python3.11","python3.12"]},handler:{type:"string",default:"index.handler"},timeout:{type:"number",minimum:1,maximum:900,default:30},memory:{type:"number",minimum:128,maximum:10240,default:1024}}},monitoring:{type:"object",properties:{alarms:{type:"array",items:{type:"object",required:["metric","threshold"],properties:{metric:{type:"string"},threshold:{type:"number"},evaluationPeriods:{type:"number",minimum:1,default:2}}}},dashboard:{type:"object",properties:{name:{type:"string"},widgets:{type:"array"}}}}},security:{type:"object",properties:{waf:{type:"boolean",description:"Enable AWS WAF",default:!1},certificates:{type:"array",items:{type:"object",required:["domain"],properties:{domain:{type:"string"},subdomains:{type:"array",items:{type:"string"}}}}}}},queue:{type:"object",properties:{fifo:{type:"boolean",default:!1},deadLetterQueue:{type:"boolean",default:!0},visibilityTimeout:{type:"number",minimum:0,maximum:43200,default:30},messageRetentionPeriod:{type:"number",minimum:60,maximum:1209600,default:345600}}}}};function zI(a){let n=[];if(!a.project)n.push("Missing required field: project");else{if(!a.project.name)n.push("Missing required field: project.name");if(!a.project.slug)n.push("Missing required field: project.slug")}if(a.project?.slug&&!/^[a-z0-9-]+$/.test(a.project.slug))n.push("Invalid project.slug: must contain only lowercase letters, numbers, and hyphens");let i=["us-east-1","us-east-2","us-west-1","us-west-2","eu-west-1","eu-west-2","eu-west-3","eu-central-1","ap-southeast-1","ap-southeast-2","ap-northeast-1","ap-northeast-2","sa-east-1","ca-central-1"];if(a.project?.region&&!i.includes(a.project.region))n.push(`Invalid region: ${a.project.region}. Must be one of: ${i.join(", ")}`);if(a.mode&&!["server","serverless"].includes(a.mode))n.push("Invalid mode: must be one of server or serverless");return{valid:n.length===0,errors:n}}var zp={enabled:process.env.TS_CLOUD_LOCAL==="true"||!0,localstackEndpoint:process.env.LOCALSTACK_ENDPOINT||"http://localhost:4566",postgresUrl:process.env.POSTGRES_URL||"postgresql://tscloud:tscloud@localhost:5432/tscloud",redisUrl:process.env.REDIS_URL||"redis://localhost:6379",dynamodbEndpoint:process.env.DYNAMODB_ENDPOINT||"http://localhost:8000",s3Endpoint:process.env.S3_ENDPOINT||"http://localhost:9000",emailEndpoint:process.env.EMAIL_ENDPOINT||"smtp://localhost:1025",awsRegion:process.env.AWS_REGION||"us-east-1",awsAccessKeyId:process.env.AWS_ACCESS_KEY_ID||"test",awsSecretAccessKey:process.env.AWS_SECRET_ACCESS_KEY||"test"};function Id(){return zp}function KI(){return zp.enabled}function WI(a){let n=Id();if(!n.enabled)return"";switch(a.toLowerCase()){case"dynamodb":return n.dynamodbEndpoint;case"s3":return n.s3Endpoint;case"localstack":case"cloudformation":case"lambda":case"apigateway":case"sns":case"sqs":case"cloudwatch":case"iam":case"sts":return n.localstackEndpoint;default:return n.localstackEndpoint}}function JI(){let a=Id();return{accessKeyId:a.awsAccessKeyId,secretAccessKey:a.awsSecretAccessKey,region:a.awsRegion}}function XI(){let a=Id();if(!a.enabled)return{};return{AWS_ACCESS_KEY_ID:a.awsAccessKeyId,AWS_SECRET_ACCESS_KEY:a.awsSecretAccessKey,AWS_REGION:a.awsRegion,AWS_ENDPOINT_URL:a.localstackEndpoint,LOCALSTACK_ENDPOINT:a.localstackEndpoint,TS_CLOUD_LOCAL:"true"}}class Kp{stacks=new Map;stackEvents=new Map;async createStack(a){let n=`arn:aws:cloudformation:${a.region||"us-east-1"}:123456789012:stack/${a.StackName}/${Date.now()}`;return this.stacks.set(a.StackName,{StackId:n,StackName:a.StackName,StackStatus:"CREATE_IN_PROGRESS",CreationTime:new Date().toISOString(),TemplateBody:a.TemplateBody,Parameters:a.Parameters||[]}),this.addEvent(a.StackName,{EventId:Date.now().toString(),StackName:a.StackName,LogicalResourceId:a.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_IN_PROGRESS"}),setTimeout(()=>{let i=this.stacks.get(a.StackName);if(i)i.StackStatus="CREATE_COMPLETE",this.addEvent(a.StackName,{EventId:(Date.now()+1).toString(),StackName:a.StackName,LogicalResourceId:a.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_COMPLETE"})},100),{StackId:n}}async updateStack(a){let n=this.stacks.get(a.StackName);if(!n)throw Error(`Stack ${a.StackName} does not exist`);return n.StackStatus="UPDATE_IN_PROGRESS",n.TemplateBody=a.TemplateBody||n.TemplateBody,this.addEvent(a.StackName,{EventId:Date.now().toString(),StackName:a.StackName,LogicalResourceId:a.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_IN_PROGRESS"}),setTimeout(()=>{n.StackStatus="UPDATE_COMPLETE",this.addEvent(a.StackName,{EventId:(Date.now()+1).toString(),StackName:a.StackName,LogicalResourceId:a.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_COMPLETE"})},100),{StackId:n.StackId}}async deleteStack(a){let n=this.stacks.get(a.StackName);if(!n)throw Error(`Stack ${a.StackName} does not exist`);n.StackStatus="DELETE_IN_PROGRESS",this.addEvent(a.StackName,{EventId:Date.now().toString(),StackName:a.StackName,LogicalResourceId:a.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_IN_PROGRESS"}),setTimeout(()=>{this.stacks.delete(a.StackName),this.addEvent(a.StackName,{EventId:(Date.now()+1).toString(),StackName:a.StackName,LogicalResourceId:a.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_COMPLETE"})},100)}async describeStacks(a){if(a.StackName){let n=this.stacks.get(a.StackName);if(!n)throw Error(`Stack ${a.StackName} does not exist`);return{Stacks:[n]}}return{Stacks:Array.from(this.stacks.values())}}async describeStackEvents(a){return{StackEvents:this.stackEvents.get(a.StackName)||[]}}addEvent(a,n){if(!this.stackEvents.has(a))this.stackEvents.set(a,[]);this.stackEvents.get(a).unshift(n)}reset(){this.stacks.clear(),this.stackEvents.clear()}}class Wp{buckets=new Map;async createBucket(a){return this.buckets.set(a.Bucket,new Map),{Location:`/${a.Bucket}`}}async deleteBucket(a){this.buckets.delete(a.Bucket)}async putObject(a){let n=this.buckets.get(a.Bucket);if(!n)n=new Map,this.buckets.set(a.Bucket,n);return n.set(a.Key,Buffer.from(a.Body||"")),{ETag:`"${Date.now()}"`}}async getObject(a){let n=this.buckets.get(a.Bucket);if(!n)throw Error(`Bucket ${a.Bucket} does not exist`);let i=n.get(a.Key);if(!i)throw Error(`Object ${a.Key} does not exist`);return{Body:i,ContentLength:i.length}}async deleteObject(a){let n=this.buckets.get(a.Bucket);if(n)n.delete(a.Key)}async listObjects(a){let n=this.buckets.get(a.Bucket);if(!n)throw Error(`Bucket ${a.Bucket} does not exist`);return{Contents:Array.from(n.keys()).map((i)=>({Key:i,Size:n.get(i).length,LastModified:new Date().toISOString()}))}}reset(){this.buckets.clear()}}class Jp{tables=new Map;data=new Map;async createTable(a){return this.tables.set(a.TableName,{TableName:a.TableName,KeySchema:a.KeySchema,AttributeDefinitions:a.AttributeDefinitions,TableStatus:"ACTIVE",CreationDateTime:new Date().toISOString()}),this.data.set(a.TableName,new Map),{TableDescription:this.tables.get(a.TableName)}}async deleteTable(a){this.tables.delete(a.TableName),this.data.delete(a.TableName)}async putItem(a){let n=this.data.get(a.TableName);if(!n)n=new Map,this.data.set(a.TableName,n);let i=JSON.stringify(a.Item);n.set(i,a.Item)}async getItem(a){let n=this.data.get(a.TableName);if(!n)return{};let i=JSON.stringify(a.Key),s=n.get(i);return s?{Item:s}:{}}async deleteItem(a){let n=this.data.get(a.TableName);if(n){let i=JSON.stringify(a.Key);n.delete(i)}}async scan(a){let n=this.data.get(a.TableName);if(!n)return{Items:[]};return{Items:Array.from(n.values())}}reset(){this.tables.clear(),this.data.clear()}}function YI(a){return{cloudformation:new Kp,s3:new Wp,dynamodb:new Jp}}class Xp{environments=new Map;async createPreviewEnvironment(a){let{branch:n,pr:i,commitSha:s,ttl:c=24,baseConfig:l,region:u="us-east-1"}=a,h=this.generatePreviewId(n,i,s),y=this.generatePreviewName(n,i),S=`preview-${y}`,A=new Date,C=new Date(A.getTime()+c*60*60*1000),T={id:h,name:y,branch:n,pr:i,commitSha:s,createdAt:A,expiresAt:C,status:"creating",stackName:S,region:u,resources:[]};this.environments.set(h,T);try{let v=this.createPreviewConfig(l,y);return T.status="active",T.url=`https://${y}.preview.example.com`,T}catch(v){throw T.status="failed",v}}async destroyPreviewEnvironment(a){let n=this.environments.get(a);if(!n)throw Error(`Preview environment ${a} not found`);n.status="destroying";try{n.status="destroyed",this.environments.delete(a)}catch(i){throw Error(`Failed to destroy preview environment: ${i}`)}}getPreviewEnvironment(a){return this.environments.get(a)}getPreviewEnvironmentByBranch(a){return Array.from(this.environments.values()).find((n)=>n.branch===a)}getPreviewEnvironmentByPR(a){return Array.from(this.environments.values()).find((n)=>n.pr===a)}listPreviewEnvironments(){return Array.from(this.environments.values())}listActivePreviewEnvironments(){return this.listPreviewEnvironments().filter((a)=>a.status==="active")}async cleanupExpiredEnvironments(a={}){let{maxAge:n,keepCount:i,dryRun:s=!1}=a,c=[],l=[],u=new Date,h=this.listPreviewEnvironments().sort((y,S)=>S.createdAt.getTime()-y.createdAt.getTime());for(let y=0;y<h.length;y++){let S=h[y];if(S.status!=="active")continue;let A=!1;if(S.expiresAt<u)A=!0;if(n){if((u.getTime()-S.createdAt.getTime())/3600000>n)A=!0}if(i&&y>=i)A=!0;if(A)if(s)c.push(S.id);else try{await this.destroyPreviewEnvironment(S.id),c.push(S.id)}catch(C){l.push(S.id)}}return{destroyed:c,failed:l}}async updatePreviewEnvironment(a,n){let i=this.environments.get(a);if(!i)throw Error(`Preview environment ${a} not found`);i.commitSha=n,i.status="creating";try{return i.status="active",i}catch(s){throw i.status="failed",s}}async getPreviewEnvironmentsCost(){let a={},n=0;for(let i of this.environments.values())a[i.id]=0,n+=0;return{total:n,byEnvironment:a}}generatePreviewId(a,n,i){let s=a.replace(/[^a-z0-9-]/gi,"-").toLowerCase(),c=i?.substring(0,7)||Date.now().toString();return n?`pr-${n}-${c}`:`${s}-${c}`}generatePreviewName(a,n){let i=a.replace(/[^a-z0-9-]/gi,"-").toLowerCase();return n?`pr-${n}`:i}createPreviewConfig(a,n){return{...a,project:{...a.project,name:`${a.project.name} Preview (${n})`,slug:`${a.project.slug}-preview-${n}`}}}}var ZI=new Xp;function eS(a={}){let{workflowName:n="Preview Environment",trigger:i="pull_request",branches:s=["main","develop"],awsRegion:c="us-east-1",awsRole:l,configFile:u="cloud.config.ts",ttl:h=24}=a;return`name: ${n}
2513
2513
 
2514
2514
  on:
2515
2515
  ${i}:
@@ -2737,9 +2737,9 @@ jobs:
2737
2737
  curl -X POST -H 'Content-type: application/json' \\
2738
2738
  --data '{"text":"Preview Environment Cost Report\\n\${{ steps.cost.outputs.cost_json }}"}' \\
2739
2739
  $SLACK_WEBHOOK_URL`:'run: |\n echo "${{ steps.cost.outputs.cost_json }}"'}
2740
- `}class Yp{channels=[];addChannel(a){this.channels.push(a)}removeChannel(a){this.channels=this.channels.filter((n)=>n.type!==a)}async notify(a){let n=this.channels.map((i)=>this.sendToChannel(i,a));await Promise.allSettled(n)}async sendToChannel(a,n){switch(a.type){case"slack":await this.sendToSlack(a.config,n);break;case"discord":await this.sendToDiscord(a.config,n);break;case"email":await this.sendToEmail(a.config,n);break;case"webhook":await this.sendToWebhook(a.config,n);break}}async sendToSlack(a,n){let i=this.formatSlackMessage(n,a),s=await fetch(a.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)});if(!s.ok)throw Error(`Failed to send Slack notification: ${s.statusText}`)}formatSlackMessage(a,n){let{environment:i,type:s}=a,c={created:":rocket:",updated:":arrows_counterclockwise:",destroyed:":wastebasket:",failed:":x:",expired:":hourglass_flowing_sand:"}[s],l={created:"#36a64f",updated:"#2196F3",destroyed:"#808080",failed:"#f44336",expired:"#ff9800"}[s],u={created:"Preview Environment Created",updated:"Preview Environment Updated",destroyed:"Preview Environment Destroyed",failed:"Preview Environment Failed",expired:"Preview Environment Expired"}[s];return{username:n.username||"ts-cloud",icon_emoji:n.iconEmoji||":cloud:",channel:n.channel,attachments:[{color:l,title:`${c} ${u}`,fields:[{title:"Environment",value:i.name,short:!0},{title:"Branch",value:i.branch,short:!0},...i.pr?[{title:"PR",value:`#${i.pr}`,short:!0}]:[],{title:"Commit",value:i.commitSha.substring(0,7),short:!0},...i.url?[{title:"URL",value:i.url,short:!1}]:[],...s==="created"?[{title:"Expires",value:i.expiresAt.toLocaleString(),short:!0}]:[]],footer:"ts-cloud Preview Environments",ts:Math.floor(a.timestamp.getTime()/1000)}]}}async sendToDiscord(a,n){let i=this.formatDiscordMessage(n,a),s=await fetch(a.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)});if(!s.ok)throw Error(`Failed to send Discord notification: ${s.statusText}`)}formatDiscordMessage(a,n){let{environment:i,type:s}=a,c={created:":rocket:",updated:":arrows_counterclockwise:",destroyed:":wastebasket:",failed:":x:",expired:":hourglass:"}[s],l={created:3581519,updated:2201331,destroyed:8421504,failed:16007990,expired:16750592}[s],u={created:"Preview Environment Created",updated:"Preview Environment Updated",destroyed:"Preview Environment Destroyed",failed:"Preview Environment Failed",expired:"Preview Environment Expired"}[s];return{username:n.username||"ts-cloud",avatar_url:n.avatarUrl,embeds:[{title:`${c} ${u}`,color:l,fields:[{name:"Environment",value:i.name,inline:!0},{name:"Branch",value:i.branch,inline:!0},...i.pr?[{name:"PR",value:`#${i.pr}`,inline:!0}]:[],{name:"Commit",value:`\`${i.commitSha.substring(0,7)}\``,inline:!0},...i.url?[{name:"URL",value:i.url,inline:!1}]:[]],timestamp:a.timestamp.toISOString(),footer:{text:"ts-cloud Preview Environments"}}]}}async sendToEmail(a,n){console.log(`Email notification would be sent to ${a.to.join(", ")}`)}async sendToWebhook(a,n){let i=await fetch(a.url,{method:a.method||"POST",headers:{"Content-Type":"application/json",...a.headers},body:JSON.stringify({event:n.type,environment:n.environment,timestamp:n.timestamp.toISOString(),metadata:n.metadata})});if(!i.ok)throw Error(`Failed to send webhook notification: ${i.statusText}`)}}var nS=new Yp;function iS(a){let{columns:n,data:i,border:s=!0,header:c=!0,compact:l=!1,maxWidth:u}=a;if(i.length===0)return"No data to display";let h=n.map((S)=>{let b=S.label.length,A=Math.max(...i.map((T)=>(S.formatter?S.formatter(T[S.key]):String(T[S.key]||"")).length)),C=S.width||Math.max(b,A);if(u&&C>u)C=u;return C}),y=[];if(s)y.push(Nt(h,"top",l));if(c){if(y.push(ma(n.map((S)=>S.label),h,n.map((S)=>S.align||"left"),s)),s)y.push(Nt(h,"middle",l))}for(let S of i){let b=n.map((A)=>{let C=A.formatter?A.formatter(S[A.key]):String(S[A.key]||"");return Dn(C,h[n.indexOf(A)])});y.push(ma(b,h,n.map((A)=>A.align||"left"),s))}if(s)y.push(Nt(h,"bottom",l));return y.join(`
2741
- `)}function ma(a,n,i,s){let c=a.map((l,u)=>{let h=n[u],y=i[u];return Nn(l,h,y)});if(s)return`│ ${c.join(" │ ")} │`;return c.join(" ")}function Nt(a,n,i){let s=n==="top"?"┌":n==="middle"?"├":"└",c=n==="top"?"┐":n==="middle"?"┤":"┘",l=n==="top"?"┬":n==="middle"?"┼":"┴",u="─";if(i)return s+a.map((h)=>"─".repeat(h+2)).join(l)+c;return s+a.map((h)=>"─".repeat(h+2)).join(l)+c}function Nn(a,n,i){let s=La(a).length;if(s>=n)return a;let c=n-s;switch(i){case"right":return" ".repeat(c)+a;case"center":{let l=Math.floor(c/2),u=c-l;return" ".repeat(l)+a+" ".repeat(u)}default:return a+" ".repeat(c)}}function Dn(a,n){if(La(a).length<=n)return a;return a.substring(0,n-1)+"…"}function La(a){return a.replace(/\x1B\[[0-9;]*m/g,"")}function sS(a,n={}){let{indent:i=" ",showMetadata:s=!1}=n,c=[];function l(u,h,y){let S=h+(y?"└─ ":"├─ ")+u.label;if(c.push(S),s&&u.metadata){let b=h+(y?" ":"│ ");for(let[A,C]of Object.entries(u.metadata))c.push(`${b}${A}: ${C}`)}if(u.children&&u.children.length>0){let b=h+(y?" ":"│ ");u.children.forEach((A,C)=>{l(A,b,C===u.children.length-1)})}}return a.forEach((u,h)=>{l(u,"",h===a.length-1)}),c.join(`
2742
- `)}function oS(a){let{total:n,current:i,width:s=40,format:c=":bar :percent :current/:total",complete:l="█",incomplete:u="░"}=a,h=Math.min(100,Math.max(0,i/n*100)),y=Math.floor(s*i/n),S=s-y,b=l.repeat(y)+u.repeat(S);return c.replace(":bar",b).replace(":percent",`${h.toFixed(0)}%`).replace(":current",String(i)).replace(":total",String(n))}function aS(a,n=2){if(a===0)return"0 Bytes";let i=1024,s=n<0?0:n,c=["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"],l=Math.floor(Math.log(a)/Math.log(i));return`${Number.parseFloat((a/Math.pow(i,l)).toFixed(s))} ${c[l]}`}function cS(a){if(a<1000)return`${a}ms`;let n=Math.floor(a/1000);if(n<60)return`${n}s`;let i=Math.floor(n/60),s=n%60;if(i<60)return s>0?`${i}m ${s}s`:`${i}m`;let c=Math.floor(i/60),l=i%60;if(c<24)return l>0?`${c}h ${l}m`:`${c}h`;let u=Math.floor(c/24),h=c%24;return h>0?`${u}d ${h}h`:`${u}d`}function dS(a,n="•"){return a.map((i)=>`${n} ${i}`).join(`
2740
+ `}class Yp{channels=[];addChannel(a){this.channels.push(a)}removeChannel(a){this.channels=this.channels.filter((n)=>n.type!==a)}async notify(a){let n=this.channels.map((i)=>this.sendToChannel(i,a));await Promise.allSettled(n)}async sendToChannel(a,n){switch(a.type){case"slack":await this.sendToSlack(a.config,n);break;case"discord":await this.sendToDiscord(a.config,n);break;case"email":await this.sendToEmail(a.config,n);break;case"webhook":await this.sendToWebhook(a.config,n);break}}async sendToSlack(a,n){let i=this.formatSlackMessage(n,a),s=await fetch(a.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)});if(!s.ok)throw Error(`Failed to send Slack notification: ${s.statusText}`)}formatSlackMessage(a,n){let{environment:i,type:s}=a,c={created:":rocket:",updated:":arrows_counterclockwise:",destroyed:":wastebasket:",failed:":x:",expired:":hourglass_flowing_sand:"}[s],l={created:"#36a64f",updated:"#2196F3",destroyed:"#808080",failed:"#f44336",expired:"#ff9800"}[s],u={created:"Preview Environment Created",updated:"Preview Environment Updated",destroyed:"Preview Environment Destroyed",failed:"Preview Environment Failed",expired:"Preview Environment Expired"}[s];return{username:n.username||"ts-cloud",icon_emoji:n.iconEmoji||":cloud:",channel:n.channel,attachments:[{color:l,title:`${c} ${u}`,fields:[{title:"Environment",value:i.name,short:!0},{title:"Branch",value:i.branch,short:!0},...i.pr?[{title:"PR",value:`#${i.pr}`,short:!0}]:[],{title:"Commit",value:i.commitSha.substring(0,7),short:!0},...i.url?[{title:"URL",value:i.url,short:!1}]:[],...s==="created"?[{title:"Expires",value:i.expiresAt.toLocaleString(),short:!0}]:[]],footer:"ts-cloud Preview Environments",ts:Math.floor(a.timestamp.getTime()/1000)}]}}async sendToDiscord(a,n){let i=this.formatDiscordMessage(n,a),s=await fetch(a.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)});if(!s.ok)throw Error(`Failed to send Discord notification: ${s.statusText}`)}formatDiscordMessage(a,n){let{environment:i,type:s}=a,c={created:":rocket:",updated:":arrows_counterclockwise:",destroyed:":wastebasket:",failed:":x:",expired:":hourglass:"}[s],l={created:3581519,updated:2201331,destroyed:8421504,failed:16007990,expired:16750592}[s],u={created:"Preview Environment Created",updated:"Preview Environment Updated",destroyed:"Preview Environment Destroyed",failed:"Preview Environment Failed",expired:"Preview Environment Expired"}[s];return{username:n.username||"ts-cloud",avatar_url:n.avatarUrl,embeds:[{title:`${c} ${u}`,color:l,fields:[{name:"Environment",value:i.name,inline:!0},{name:"Branch",value:i.branch,inline:!0},...i.pr?[{name:"PR",value:`#${i.pr}`,inline:!0}]:[],{name:"Commit",value:`\`${i.commitSha.substring(0,7)}\``,inline:!0},...i.url?[{name:"URL",value:i.url,inline:!1}]:[]],timestamp:a.timestamp.toISOString(),footer:{text:"ts-cloud Preview Environments"}}]}}async sendToEmail(a,n){console.log(`Email notification would be sent to ${a.to.join(", ")}`)}async sendToWebhook(a,n){let i=await fetch(a.url,{method:a.method||"POST",headers:{"Content-Type":"application/json",...a.headers},body:JSON.stringify({event:n.type,environment:n.environment,timestamp:n.timestamp.toISOString(),metadata:n.metadata})});if(!i.ok)throw Error(`Failed to send webhook notification: ${i.statusText}`)}}var nS=new Yp;function iS(a){let{columns:n,data:i,border:s=!0,header:c=!0,compact:l=!1,maxWidth:u}=a;if(i.length===0)return"No data to display";let h=n.map((S)=>{let A=S.label.length,C=Math.max(...i.map((v)=>(S.formatter?S.formatter(v[S.key]):String(v[S.key]||"")).length)),T=S.width||Math.max(A,C);if(u&&T>u)T=u;return T}),y=[];if(s)y.push(Nt(h,"top",l));if(c){if(y.push(ma(n.map((S)=>S.label),h,n.map((S)=>S.align||"left"),s)),s)y.push(Nt(h,"middle",l))}for(let S of i){let A=n.map((C)=>{let T=C.formatter?C.formatter(S[C.key]):String(S[C.key]||"");return Dn(T,h[n.indexOf(C)])});y.push(ma(A,h,n.map((C)=>C.align||"left"),s))}if(s)y.push(Nt(h,"bottom",l));return y.join(`
2741
+ `)}function ma(a,n,i,s){let c=a.map((l,u)=>{let h=n[u],y=i[u];return Nn(l,h,y)});if(s)return`│ ${c.join(" │ ")} │`;return c.join(" ")}function Nt(a,n,i){let s=n==="top"?"┌":n==="middle"?"├":"└",c=n==="top"?"┐":n==="middle"?"┤":"┘",l=n==="top"?"┬":n==="middle"?"┼":"┴",u="─";if(i)return s+a.map((h)=>"─".repeat(h+2)).join(l)+c;return s+a.map((h)=>"─".repeat(h+2)).join(l)+c}function Nn(a,n,i){let s=La(a).length;if(s>=n)return a;let c=n-s;switch(i){case"right":return" ".repeat(c)+a;case"center":{let l=Math.floor(c/2),u=c-l;return" ".repeat(l)+a+" ".repeat(u)}default:return a+" ".repeat(c)}}function Dn(a,n){if(La(a).length<=n)return a;return a.substring(0,n-1)+"…"}function La(a){return a.replace(/\x1B\[[0-9;]*m/g,"")}function sS(a,n={}){let{indent:i=" ",showMetadata:s=!1}=n,c=[];function l(u,h,y){let S=h+(y?"└─ ":"├─ ")+u.label;if(c.push(S),s&&u.metadata){let A=h+(y?" ":"│ ");for(let[C,T]of Object.entries(u.metadata))c.push(`${A}${C}: ${T}`)}if(u.children&&u.children.length>0){let A=h+(y?" ":"│ ");u.children.forEach((C,T)=>{l(C,A,T===u.children.length-1)})}}return a.forEach((u,h)=>{l(u,"",h===a.length-1)}),c.join(`
2742
+ `)}function oS(a){let{total:n,current:i,width:s=40,format:c=":bar :percent :current/:total",complete:l="█",incomplete:u="░"}=a,h=Math.min(100,Math.max(0,i/n*100)),y=Math.floor(s*i/n),S=s-y,A=l.repeat(y)+u.repeat(S);return c.replace(":bar",A).replace(":percent",`${h.toFixed(0)}%`).replace(":current",String(i)).replace(":total",String(n))}function aS(a,n=2){if(a===0)return"0 Bytes";let i=1024,s=n<0?0:n,c=["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"],l=Math.floor(Math.log(a)/Math.log(i));return`${Number.parseFloat((a/Math.pow(i,l)).toFixed(s))} ${c[l]}`}function cS(a){if(a<1000)return`${a}ms`;let n=Math.floor(a/1000);if(n<60)return`${n}s`;let i=Math.floor(n/60),s=n%60;if(i<60)return s>0?`${i}m ${s}s`:`${i}m`;let c=Math.floor(i/60),l=i%60;if(c<24)return l>0?`${c}h ${l}m`:`${c}h`;let u=Math.floor(c/24),h=c%24;return h>0?`${u}d ${h}h`:`${u}d`}function dS(a,n="•"){return a.map((i)=>`${n} ${i}`).join(`
2743
2743
  `)}function lS(a,n={}){let{indent:i="",separator:s=": "}=n,c=Math.max(...Object.keys(a).map((l)=>l.length));return Object.entries(a).map(([l,u])=>{let h=l.padEnd(c);return`${i}${h}${s}${u}`}).join(`
2744
2744
  `)}class Vf{total;current=0;width;format;message;showETA;showPercentage;showCounter;startTime=Date.now();lastUpdate=0;constructor(a){this.total=a.total,this.current=a.current||0,this.width=a.width||40,this.format=a.format||":message :bar :percent :eta",this.message=a.message||"Progress",this.showETA=a.showETA!==!1,this.showPercentage=a.showPercentage!==!1,this.showCounter=a.showCounter!==!1}tick(a=1){this.current=Math.min(this.total,this.current+a),this.lastUpdate=Date.now()}update(a){this.current=Math.min(this.total,Math.max(0,a)),this.lastUpdate=Date.now()}setMessage(a){this.message=a}getPercentage(){return Math.min(100,this.current/this.total*100)}getETA(){if(this.current===0)return 0;let a=Date.now()-this.startTime,n=this.current/a,i=this.total-this.current;return Math.round(i/n)}getETAFormatted(){if(this.current===0)return"calculating...";if(this.current===this.total)return"complete";let a=this.getETA();if(a<1000)return"< 1s";if(a<60000)return`${Math.round(a/1000)}s`;let n=Math.floor(a/60000);if(n<60)return`${n}m`;let i=Math.floor(n/60),s=n%60;if(i<24)return s>0?`${i}h ${s}m`:`${i}h`;let c=Math.floor(i/24),l=i%24;return l>0?`${c}d ${l}h`:`${c}d`}render(){let a=this.getPercentage(),n=Math.floor(this.width*this.current/this.total),i=this.width-n,s="█".repeat(n)+"░".repeat(i),c=`${a.toFixed(1)}%`,l=`${this.current}/${this.total}`,u=this.showETA?`ETA: ${this.getETAFormatted()}`:"",h=this.format.replace(":message",this.message).replace(":bar",s).replace(":percent",this.showPercentage?c:"").replace(":counter",this.showCounter?l:"").replace(":eta",u).replace(":current",String(this.current)).replace(":total",String(this.total));return h=h.replace(/\s+/g," ").trim(),h}isComplete(){return this.current>=this.total}}class jf{steps;currentStepIndex=0;constructor(a){this.steps=a.map((n)=>({name:n,status:"pending"}))}startStep(a,n){if(a>=0&&a<this.steps.length)this.steps[a].status="active",this.steps[a].message=n,this.currentStepIndex=a}completeStep(a){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="completed",this.steps[this.currentStepIndex].message=a,this.currentStepIndex++}failStep(a){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="failed",this.steps[this.currentStepIndex].error=a}skipStep(a){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="skipped",this.steps[this.currentStepIndex].message=a,this.currentStepIndex++}getStep(a){return this.steps[a]}getSteps(){return this.steps}render(){let a=[];for(let n of this.steps){let i=`${this.getStatusIcon(n.status)} ${n.name}`;if(n.message)i+=` - ${n.message}`;if(n.error)i+=`
2745
2745
  Error: ${n.error}`;a.push(i)}return a.join(`
@@ -2759,16 +2759,16 @@ ${n.map((i)=>` • ${i}`).join(`
2759
2759
  `)}function IS(a,n,i=[]){let s={valid:!0,errors:[],warnings:[],suggestions:[]},[c,...l]=a.split(" ");if(!n.includes(c)){s.valid=!1,s.errors.push(`Unknown command: ${c}`);let u=Zp(c,n);if(u.length>0)s.suggestions.push(...u)}for(let u of i)if(!l.some((h)=>h===`--${u}`||h.startsWith(`--${u}=`)))s.valid=!1,s.errors.push(`Missing required flag: --${u}`);return s}class Wf{options;running=!1;history={commands:[],maxSize:1000};historyIndex=-1;constructor(a){this.options={prompt:a.prompt||"> ",welcome:a.welcome||'Welcome to ts-cloud interactive mode. Type "help" for available commands.',...a}}async start(){if(this.running=!0,this.options.welcome)console.log(this.options.welcome),console.log("");if(this.options.historyFile)await this.loadHistory();while(this.running)try{let a=await this.readInput();if(!a.trim())continue;this.addToHistory(a),await this.executeCommand(a)}catch(a){if(a instanceof Error)console.error(`Error: ${a.message}`)}if(this.options.historyFile)await this.saveHistory()}stop(){this.running=!1}async readInput(){return new Promise((a)=>{process.stdout.write(this.options.prompt||"> "),a("")})}async executeCommand(a){let[n,...i]=this.parseCommand(a);if(n==="exit"||n==="quit"){this.stop();return}if(n==="help"){this.showHelp();return}if(n==="history"){this.showHistory();return}if(n==="clear"){console.clear();return}let s=this.findCommand(n);if(!s){console.error(`Unknown command: ${n}`),console.log('Type "help" to see available commands.');return}try{await s.handler(i)}catch(c){if(c instanceof Error)console.error(`Command failed: ${c.message}`)}}parseCommand(a){return a.trim().split(/\s+/)}findCommand(a){for(let[n,i]of this.options.commands)if(i.name===a||i.aliases?.includes(a))return i;return}showHelp(){console.log("Available commands:"),console.log("");let a=Array.from(this.options.commands.values());console.log(" help Show this help message"),console.log(" history Show command history"),console.log(" clear Clear screen"),console.log(" exit, quit Exit interactive mode"),console.log("");for(let n of a){let i=` ${n.name.padEnd(20)} ${n.description}`;if(n.aliases&&n.aliases.length>0)i+=` (aliases: ${n.aliases.join(", ")})`;console.log(i)}}showHistory(){if(this.history.commands.length===0){console.log("No command history");return}console.log("Command history:"),this.history.commands.forEach((a,n)=>{console.log(` ${(n+1).toString().padStart(4)} ${a}`)})}addToHistory(a){if(this.history.commands[this.history.commands.length-1]===a)return;if(this.history.commands.push(a),this.history.commands.length>this.history.maxSize)this.history.commands=this.history.commands.slice(-this.history.maxSize);this.historyIndex=this.history.commands.length}historyBack(){if(this.historyIndex>0)return this.historyIndex--,this.history.commands[this.historyIndex];return}historyForward(){if(this.historyIndex<this.history.commands.length-1)return this.historyIndex++,this.history.commands[this.historyIndex];return this.historyIndex=this.history.commands.length,""}autocomplete(a){let n=[],i=["help","history","clear","exit","quit"];for(let s of i)if(s.startsWith(a))n.push(s);for(let[s,c]of this.options.commands){if(c.name.startsWith(a))n.push(c.name);if(c.aliases){for(let l of c.aliases)if(l.startsWith(a))n.push(l)}}return n}async loadHistory(){if(!this.options.historyFile)return;try{let a=await import("node:fs/promises"),n=await a.readFile(this.options.historyFile,"utf-8");this.history.commands=n.split(`
2760
2760
  `).filter((i)=>i.trim()),this.historyIndex=this.history.commands.length}catch{}}async saveHistory(){if(!this.options.historyFile)return;try{let a=await import("node:fs/promises");await a.writeFile(this.options.historyFile,this.history.commands.join(`
2761
2761
  `))}catch(a){console.error(`Failed to save history: ${a}`)}}searchHistory(a){return this.history.commands.filter((n)=>n.includes(a))}clearHistory(){this.history.commands=[],this.historyIndex=0}}class Jf{variables=new Map;workingDirectory=process.cwd();set(a,n){this.variables.set(a,n)}get(a){return this.variables.get(a)}has(a){return this.variables.has(a)}delete(a){this.variables.delete(a)}getAll(){return Object.fromEntries(this.variables)}clear(){this.variables.clear()}setWorkingDirectory(a){this.workingDirectory=a}getWorkingDirectory(){return this.workingDirectory}}class Xf{command={};name(a){return this.command.name=a,this}description(a){return this.command.description=a,this}aliases(...a){return this.command.aliases=a,this}handler(a){return this.command.handler=a,this}autocomplete(a){return this.command.autocomplete=a,this}build(){if(!this.command.name||!this.command.description||!this.command.handler)throw Error("Command must have name, description, and handler");return this.command}}class Yf{entries=[];maxSize;persistFile;trackOutput;constructor(a={}){this.maxSize=a.maxSize||1000,this.persistFile=a.persistFile,this.trackOutput=a.trackOutput||!1}add(a){if(this.entries.push({...a,timestamp:new Date}),this.entries.length>this.maxSize)this.entries=this.entries.slice(-this.maxSize)}getAll(){return[...this.entries]}getRecent(a=10){return this.entries.slice(-a)}search(a){let n=a.toLowerCase();return this.entries.filter((i)=>i.command.toLowerCase().includes(n))}searchByDate(a,n){return this.entries.filter((i)=>i.timestamp>=a&&i.timestamp<=n)}getSuccessful(){return this.entries.filter((a)=>a.success)}getFailed(){return this.entries.filter((a)=>!a.success)}getMostUsed(a=10){let n=new Map;for(let i of this.entries){let s=i.command.split(" ")[0];n.set(s,(n.get(s)||0)+1)}return Array.from(n.entries()).map(([i,s])=>({command:i,count:s})).sort((i,s)=>s.count-i.count).slice(0,a)}getStats(){let a=this.entries.length,n=this.entries.filter((h)=>h.success).length,i=this.entries.filter((h)=>!h.success).length,s=this.entries.filter((h)=>h.duration!==void 0),c=s.length>0?s.reduce((h,y)=>h+(y.duration||0),0)/s.length:0,l=this.getMostUsed(1),u=l.length>0?l[0].command:"N/A";return{total:a,successful:n,failed:i,averageDuration:c,mostUsed:u}}clear(){this.entries=[]}getByIndex(a){if(a<0||a>=this.entries.length)return;return this.entries[a]}removeByIndex(a){if(a>=0&&a<this.entries.length)this.entries.splice(a,1)}async save(){if(!this.persistFile)return;try{let a=await import("node:fs/promises"),n=JSON.stringify(this.entries,null,2);await a.writeFile(this.persistFile,n,"utf-8")}catch(a){throw Error(`Failed to save history: ${a}`)}}async load(){if(!this.persistFile)return;try{let a=await import("node:fs/promises"),n=await a.readFile(this.persistFile,"utf-8"),i=JSON.parse(n);this.entries=i.map((s)=>({...s,timestamp:new Date(s.timestamp)}))}catch{this.entries=[]}}exportJSON(){return JSON.stringify(this.entries,null,2)}exportCSV(){return["Timestamp,Command,Success,Duration",...this.entries.map((a)=>[a.timestamp.toISOString(),`"${a.command.replace(/"/g,'""')}"`,a.success,a.duration||""].join(","))].join(`
2762
- `)}importJSON(a){let n=JSON.parse(a).map((i)=>({...i,timestamp:new Date(i.timestamp)}));if(this.entries.push(...n),this.entries.length>this.maxSize)this.entries=this.entries.slice(-this.maxSize)}groupByDate(){let a=new Map;for(let n of this.entries){let i=n.timestamp.toISOString().split("T")[0];if(!a.has(i))a.set(i,[]);a.get(i).push(n)}return a}groupByCommand(){let a=new Map;for(let n of this.entries){let i=n.command.split(" ")[0];if(!a.has(i))a.set(i,[]);a.get(i).push(n)}return a}replay(a){return this.getByIndex(a)?.command}getSuggestions(a,n=5){let i=a.toLowerCase(),s=this.entries.filter((c)=>c.command.toLowerCase().startsWith(i)).map((c)=>c.command);return[...new Set(s)].slice(0,n)}analyzePatterns(){let a=new Map,n=new Map;for(let s of this.entries){let c=s.timestamp.getHours(),l=s.timestamp.getDay();a.set(c,(a.get(c)||0)+1),n.set(l,(n.get(l)||0)+1)}let i=this.entries.length>0?this.getSuccessful().length/this.entries.length:0;return{timeOfDay:a,dayOfWeek:n,successRate:i}}}function SS(a,n={}){let{maxWidth:i=100}=n;if(a.length===0)return"No command history";let s=[];for(let c=0;c<a.length;c++){let l=a[c],u=(c+1).toString().padStart(4),h=l.timestamp.toLocaleString(),y=l.success?"✓":"✗",S=l.command;if(S.length>i-30)S=S.substring(0,i-33)+"...";let b=`${u} ${h} ${y} ${S}`;if(l.duration)b+=` (${l.duration}ms)`;s.push(b)}return s.join(`
2762
+ `)}importJSON(a){let n=JSON.parse(a).map((i)=>({...i,timestamp:new Date(i.timestamp)}));if(this.entries.push(...n),this.entries.length>this.maxSize)this.entries=this.entries.slice(-this.maxSize)}groupByDate(){let a=new Map;for(let n of this.entries){let i=n.timestamp.toISOString().split("T")[0];if(!a.has(i))a.set(i,[]);a.get(i).push(n)}return a}groupByCommand(){let a=new Map;for(let n of this.entries){let i=n.command.split(" ")[0];if(!a.has(i))a.set(i,[]);a.get(i).push(n)}return a}replay(a){return this.getByIndex(a)?.command}getSuggestions(a,n=5){let i=a.toLowerCase(),s=this.entries.filter((c)=>c.command.toLowerCase().startsWith(i)).map((c)=>c.command);return[...new Set(s)].slice(0,n)}analyzePatterns(){let a=new Map,n=new Map;for(let s of this.entries){let c=s.timestamp.getHours(),l=s.timestamp.getDay();a.set(c,(a.get(c)||0)+1),n.set(l,(n.get(l)||0)+1)}let i=this.entries.length>0?this.getSuccessful().length/this.entries.length:0;return{timeOfDay:a,dayOfWeek:n,successRate:i}}}function SS(a,n={}){let{maxWidth:i=100}=n;if(a.length===0)return"No command history";let s=[];for(let c=0;c<a.length;c++){let l=a[c],u=(c+1).toString().padStart(4),h=l.timestamp.toLocaleString(),y=l.success?"✓":"✗",S=l.command;if(S.length>i-30)S=S.substring(0,i-33)+"...";let A=`${u} ${h} ${y} ${S}`;if(l.duration)A+=` (${l.duration}ms)`;s.push(A)}return s.join(`
2763
2763
  `)}function CS(a){let n=[];return n.push("Command History Statistics"),n.push("─".repeat(30)),n.push(`Total commands: ${a.total}`),n.push(`Successful: ${a.successful}`),n.push(`Failed: ${a.failed}`),n.push(`Success rate: ${(a.successful/a.total*100).toFixed(1)}%`),n.push(`Average duration: ${a.averageDuration.toFixed(0)}ms`),n.push(`Most used: ${a.mostUsed}`),n.join(`
2764
- `)}class eg{deployments=new Map;async deploy(a,n){let i=this.generateDeploymentId(),s={id:i,regions:n.regions.map((c)=>({region:c.code,stackName:this.getStackName(a,c.code),status:"pending"})),status:"deploying",startTime:new Date};this.deployments.set(i,s);try{let c=n.regions.find((u)=>u.isPrimary)||n.regions[0];await this.deployToRegion(a,c,s);let l=n.regions.filter((u)=>u.code!==c.code);if(await Promise.all(l.map((u)=>this.deployToRegion(a,u,s))),n.globalResources)await this.deployGlobalResources(s,n);if(n.replication)await this.setupReplication(s,n);if(n.failover?.enabled)await this.setupFailover(s,n);return s.status="deployed",s.endTime=new Date,s}catch(c){throw s.status="failed",s.endTime=new Date,c}}async deployToRegion(a,n,i){let s=i.regions.find((c)=>c.region===n.code);if(!s)throw Error(`Region deployment not found: ${n.code}`);s.status="deploying",s.startTime=new Date;try{let c=this.createRegionConfig(a,n);await this.deployStack(s.stackName,c,n.code),s.status="deployed",s.endTime=new Date,s.outputs={stackId:`arn:aws:cloudformation:${n.code}:123456789012:stack/${s.stackName}/guid`,endpoint:`https://${s.stackName}.${n.code}.example.com`}}catch(c){throw s.status="failed",s.endTime=new Date,s.error=c instanceof Error?c.message:String(c),c}}async deployGlobalResources(a,n){let i={};if(n.globalResources?.route53)i.route53=await this.deployRoute53(a,n);if(n.globalResources?.cloudfront)i.cloudfront=await this.deployCloudFront(a,n);if(n.globalResources?.waf)i.waf=await this.deployWAF(a);a.globalResources=i}async deployRoute53(a,n){let i=[],s=[];for(let c of a.regions){if(c.status!=="deployed")continue;let l={id:`health-${c.region}`,endpoint:c.outputs?.endpoint,path:n.failover?.healthCheckPath||"/health",region:c.region};i.push(l);let u={name:"example.com",type:"A",region:c.region,setIdentifier:c.region,healthCheckId:l.id,resourceRecords:[c.outputs?.endpoint]};s.push(u)}return{healthChecks:i,recordSets:s,hostedZoneId:"Z1234567890ABC"}}async deployCloudFront(a,n){return{distributionId:"E1234567890ABC",domainName:"d1234567890abc.cloudfront.net",origins:a.regions.filter((i)=>i.status==="deployed").map((i,s)=>{let c=n.regions[s];return{id:`origin-${i.region}`,domainName:i.outputs?.endpoint,weight:c?.weight||100}}),status:"Deployed"}}async deployWAF(a){return{webAclId:"arn:aws:wafv2:us-east-1:123456789012:global/webacl/test/a1234567-b890-c123-d456-e789012345f6",webAclArn:"arn:aws:wafv2:us-east-1:123456789012:global/webacl/test/a1234567-b890-c123-d456-e789012345f6"}}async setupReplication(a,n){if(n.replication?.s3)await this.setupS3Replication(a);if(n.replication?.dynamodb)await this.setupDynamoDBReplication(a);if(n.replication?.secrets)await this.setupSecretsReplication(a)}async setupS3Replication(a){let n=a.regions.filter((i)=>i.status==="deployed");for(let i=0;i<n.length-1;i++){let s=n[i],c=n[i+1];console.log(`Setting up S3 replication: ${s.region} -> ${c.region}`)}}async setupDynamoDBReplication(a){let n=a.regions.filter((i)=>i.status==="deployed").map((i)=>i.region);console.log(`Setting up DynamoDB global table in regions: ${n.join(", ")}`)}async setupSecretsReplication(a){let n=a.regions.filter((i)=>i.status==="deployed").map((i)=>i.region);console.log(`Setting up Secrets Manager replication in regions: ${n.join(", ")}`)}async setupFailover(a,n){let i=a.regions.find((c,l)=>n.regions[l]?.isPrimary)||a.regions[0],s=a.regions.filter((c)=>c.region!==i.region);console.log(`Setting up failover: primary=${i.region}, secondary=${s.map((c)=>c.region).join(", ")}`)}async destroy(a){let n=this.deployments.get(a);if(!n)throw Error(`Deployment not found: ${a}`);n.status="rolling-back";try{if(n.globalResources)await this.destroyGlobalResources(n.globalResources);await Promise.all(n.regions.map((i)=>this.destroyRegionStack(i))),this.deployments.delete(a)}catch(i){throw n.status="failed",i}}async destroyGlobalResources(a){if(a.waf)console.log("Destroying WAF resources");if(a.cloudfront)console.log("Destroying CloudFront distribution");if(a.route53)console.log("Destroying Route53 resources")}async destroyRegionStack(a){if(a.status!=="deployed")return;a.status="rolling-back";try{console.log(`Destroying stack ${a.stackName} in ${a.region}`),a.status="pending"}catch(n){throw a.status="failed",a.error=n instanceof Error?n.message:String(n),n}}getDeployment(a){return this.deployments.get(a)}listDeployments(){return Array.from(this.deployments.values())}getStackName(a,n){return`${a.project.slug}-${n}`}createRegionConfig(a,n){return{...a,infrastructure:{...a.infrastructure}}}async deployStack(a,n,i){console.log(`Deploying stack ${a} to ${i}`)}generateDeploymentId(){return`deploy-${Date.now()}-${Math.random().toString(36).substring(7)}`}}var bS=new eg;class tg{references=[];exports=new Map;addExport(a){let n=`${a.region}:${a.exportName}`;if(!this.exports.has(a.region))this.exports.set(a.region,[]);this.exports.get(a.region).push(a)}getExport(a,n){let i=this.exports.get(a);if(!i)return;return i.find((s)=>s.exportName===n)?.value}createReference(a,n,i,s){let c=`/cross-region/${a}/${i}/${s}`;return this.references.push({sourceRegion:a,targetRegion:n,resourceType:i,resourceId:s,value:c}),c}async resolveReference(a,n){let i=this.references.find((s)=>s.targetRegion===a&&s.value===n);if(!i)throw Error(`Reference not found: ${n}`);return`arn:aws:resource:${i.sourceRegion}:123456789012:${i.resourceType}/${i.resourceId}`}getReferencesForRegion(a){return this.references.filter((n)=>n.sourceRegion===a||n.targetRegion===a)}clear(){this.references=[],this.exports.clear()}}class rg{resources=new Map;register(a){this.resources.set(a.id,a)}get(a){return this.resources.get(a)}getByType(a){return Array.from(this.resources.values()).filter((n)=>n.type===a)}getCloudFrontDistributions(){return this.getByType("cloudfront")}getRoute53HostedZones(){return this.getByType("route53")}getWAFWebACLs(){return this.getByType("waf")}remove(a){this.resources.delete(a)}clear(){this.resources.clear()}}class ng{pairs=[];addPair(a){this.pairs.push(a)}getPairedRegion(a){let n=this.pairs.find((i)=>i.primary===a||i.secondary===a);if(!n)return;return n.primary===a?n.secondary:n.primary}getAllPairs(){return[...this.pairs]}getReplicatedPairs(){return this.pairs.filter((a)=>a.replicationConfig)}getFailoverPairs(){return this.pairs.filter((a)=>a.failoverConfig?.automatic)}arePaired(a,n){return this.pairs.some((i)=>i.primary===a&&i.secondary===n||i.primary===n&&i.secondary===a)}clear(){this.pairs=[]}}class ig{dependencies=[];addDependency(a){this.dependencies.push(a)}getDependencies(a,n){return this.dependencies.filter((i)=>i.dependentStack===a&&i.dependentRegion===n)}getDependents(a,n){return this.dependencies.filter((i)=>i.dependsOnStack===a&&i.dependsOnRegion===n)}hasDependencies(a,n){return this.getDependencies(a,n).length>0}getDeploymentOrder(a){let n=new Set,i=[],s=(c)=>{let l=`${c.name}:${c.region}`;if(n.has(l))return;n.add(l);let u=this.getDependencies(c.name,c.region);for(let h of u)s({name:h.dependsOnStack,region:h.dependsOnRegion});i.push(c)};for(let c of a)s(c);return i}detectCircularDependencies(){let a=new Set,n=new Set,i=(s,c)=>{let l=`${s}:${c}`;if(n.has(l))return!0;if(a.has(l))return!1;a.add(l),n.add(l);let u=this.getDependencies(s,c);for(let h of u)if(i(h.dependsOnStack,h.dependsOnRegion))return!0;return n.delete(l),!1};for(let s of this.dependencies)if(i(s.dependentStack,s.dependentRegion))return!0;return!1}clear(){this.dependencies=[]}}var ES=new tg,vS=new rg,TS=new ng,wS=new ig,we=[{code:"us-east-1",name:"US East (N. Virginia)",location:"Virginia, USA",launchYear:2006,availabilityZones:6,localZones:16,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"standard",multiplier:1},compliance:["PCI-DSS","HIPAA","SOC","ISO","FedRAMP"]},{code:"us-east-2",name:"US East (Ohio)",location:"Ohio, USA",launchYear:2016,availabilityZones:3,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"standard",multiplier:1},compliance:["PCI-DSS","HIPAA","SOC","ISO"]},{code:"us-west-1",name:"US West (N. California)",location:"California, USA",launchYear:2009,availabilityZones:3,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"premium",multiplier:1.1},compliance:["PCI-DSS","HIPAA","SOC","ISO"]},{code:"us-west-2",name:"US West (Oregon)",location:"Oregon, USA",launchYear:2011,availabilityZones:4,localZones:2,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"standard",multiplier:1},compliance:["PCI-DSS","HIPAA","SOC","ISO"]},{code:"eu-west-1",name:"Europe (Ireland)",location:"Dublin, Ireland",launchYear:2007,availabilityZones:3,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"standard",multiplier:1.05},compliance:["PCI-DSS","GDPR","SOC","ISO"]},{code:"eu-central-1",name:"Europe (Frankfurt)",location:"Frankfurt, Germany",launchYear:2014,availabilityZones:3,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"premium",multiplier:1.1},compliance:["PCI-DSS","GDPR","SOC","ISO"]},{code:"ap-southeast-1",name:"Asia Pacific (Singapore)",location:"Singapore",launchYear:2010,availabilityZones:3,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"premium",multiplier:1.12},compliance:["PCI-DSS","SOC","ISO","MTCS"]},{code:"ap-northeast-1",name:"Asia Pacific (Tokyo)",location:"Tokyo, Japan",launchYear:2011,availabilityZones:4,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"premium",multiplier:1.15},compliance:["PCI-DSS","SOC","ISO"]}];function Ii(a){return we.find((n)=>n.code===a)}function RS(){return we}function DS(a){let n=a.toLowerCase();return we.filter((i)=>i.location.toLowerCase().includes(n))}function PS(a){return we.filter((n)=>n.compliance.includes(a))}function NS(a){return we.filter((n)=>n.pricing.tier===a)}function kS(a){return we.some((n)=>n.code===a)}function BS(a){if(a.continent==="North America")return Ii("us-east-1");if(a.continent==="Europe")return Ii("eu-west-1");if(a.continent==="Asia")return Ii("ap-southeast-1");return Ii("us-east-1")}function xS(a){let n=[...we];if(a.compliance)n=n.filter((i)=>a.compliance.every((s)=>i.compliance.includes(s)));if(a.requiredServices)n=n.filter((i)=>a.requiredServices.every((s)=>i.services[s]));if(a.pricingSensitive)n.sort((i,s)=>i.pricing.multiplier-s.pricing.multiplier);return n.slice(0,5)}function _S(a){let n=Ii(a);if(!n)throw Error(`Invalid region: ${a}`);let i=[];for(let s of we){if(s.code===a)continue;let c=Ln(n,s),l=Mn(n,s);i.push({primary:n,secondary:s,distance:c,sameContinent:l})}return i.sort((s,c)=>{if(s.sameContinent!==c.sameContinent)return s.sameContinent?1:-1;return s.distance-c.distance}),i.slice(0,3)}function Ln(a,n){let i={"North America":0,"South America":1,Europe:2,Asia:3,Africa:4,Oceania:5},s=Xe(a.location),c=Xe(n.location);return Math.abs((i[s]||0)-(i[c]||0))}function Mn(a,n){return Xe(a.location)===Xe(n.location)}function Xe(a){if(a.includes("USA")||a.includes("Canada"))return"North America";if(a.includes("Europe")||a.includes("Ireland")||a.includes("Germany"))return"Europe";if(a.includes("Asia")||a.includes("Singapore")||a.includes("Japan"))return"Asia";if(a.includes("Brazil"))return"South America";if(a.includes("Australia"))return"Oceania";return"Unknown"}function Zf(a){return`${a.name} (${a.code})`}function OS(a){return a.map((n)=>Zf(n)).join(`
2764
+ `)}class eg{deployments=new Map;async deploy(a,n){let i=this.generateDeploymentId(),s={id:i,regions:n.regions.map((c)=>({region:c.code,stackName:this.getStackName(a,c.code),status:"pending"})),status:"deploying",startTime:new Date};this.deployments.set(i,s);try{let c=n.regions.find((u)=>u.isPrimary)||n.regions[0];await this.deployToRegion(a,c,s);let l=n.regions.filter((u)=>u.code!==c.code);if(await Promise.all(l.map((u)=>this.deployToRegion(a,u,s))),n.globalResources)await this.deployGlobalResources(s,n);if(n.replication)await this.setupReplication(s,n);if(n.failover?.enabled)await this.setupFailover(s,n);return s.status="deployed",s.endTime=new Date,s}catch(c){throw s.status="failed",s.endTime=new Date,c}}async deployToRegion(a,n,i){let s=i.regions.find((c)=>c.region===n.code);if(!s)throw Error(`Region deployment not found: ${n.code}`);s.status="deploying",s.startTime=new Date;try{let c=this.createRegionConfig(a,n);await this.deployStack(s.stackName,c,n.code),s.status="deployed",s.endTime=new Date,s.outputs={stackId:`arn:aws:cloudformation:${n.code}:123456789012:stack/${s.stackName}/guid`,endpoint:`https://${s.stackName}.${n.code}.example.com`}}catch(c){throw s.status="failed",s.endTime=new Date,s.error=c instanceof Error?c.message:String(c),c}}async deployGlobalResources(a,n){let i={};if(n.globalResources?.route53)i.route53=await this.deployRoute53(a,n);if(n.globalResources?.cloudfront)i.cloudfront=await this.deployCloudFront(a,n);if(n.globalResources?.waf)i.waf=await this.deployWAF(a);a.globalResources=i}async deployRoute53(a,n){let i=[],s=[];for(let c of a.regions){if(c.status!=="deployed")continue;let l={id:`health-${c.region}`,endpoint:c.outputs?.endpoint,path:n.failover?.healthCheckPath||"/health",region:c.region};i.push(l);let u={name:"example.com",type:"A",region:c.region,setIdentifier:c.region,healthCheckId:l.id,resourceRecords:[c.outputs?.endpoint]};s.push(u)}return{healthChecks:i,recordSets:s,hostedZoneId:"Z1234567890ABC"}}async deployCloudFront(a,n){return{distributionId:"E1234567890ABC",domainName:"d1234567890abc.cloudfront.net",origins:a.regions.filter((i)=>i.status==="deployed").map((i,s)=>{let c=n.regions[s];return{id:`origin-${i.region}`,domainName:i.outputs?.endpoint,weight:c?.weight||100}}),status:"Deployed"}}async deployWAF(a){return{webAclId:"arn:aws:wafv2:us-east-1:123456789012:global/webacl/test/a1234567-b890-c123-d456-e789012345f6",webAclArn:"arn:aws:wafv2:us-east-1:123456789012:global/webacl/test/a1234567-b890-c123-d456-e789012345f6"}}async setupReplication(a,n){if(n.replication?.s3)await this.setupS3Replication(a);if(n.replication?.dynamodb)await this.setupDynamoDBReplication(a);if(n.replication?.secrets)await this.setupSecretsReplication(a)}async setupS3Replication(a){let n=a.regions.filter((i)=>i.status==="deployed");for(let i=0;i<n.length-1;i++){let s=n[i],c=n[i+1];console.log(`Setting up S3 replication: ${s.region} -> ${c.region}`)}}async setupDynamoDBReplication(a){let n=a.regions.filter((i)=>i.status==="deployed").map((i)=>i.region);console.log(`Setting up DynamoDB global table in regions: ${n.join(", ")}`)}async setupSecretsReplication(a){let n=a.regions.filter((i)=>i.status==="deployed").map((i)=>i.region);console.log(`Setting up Secrets Manager replication in regions: ${n.join(", ")}`)}async setupFailover(a,n){let i=a.regions.find((c,l)=>n.regions[l]?.isPrimary)||a.regions[0],s=a.regions.filter((c)=>c.region!==i.region);console.log(`Setting up failover: primary=${i.region}, secondary=${s.map((c)=>c.region).join(", ")}`)}async destroy(a){let n=this.deployments.get(a);if(!n)throw Error(`Deployment not found: ${a}`);n.status="rolling-back";try{if(n.globalResources)await this.destroyGlobalResources(n.globalResources);await Promise.all(n.regions.map((i)=>this.destroyRegionStack(i))),this.deployments.delete(a)}catch(i){throw n.status="failed",i}}async destroyGlobalResources(a){if(a.waf)console.log("Destroying WAF resources");if(a.cloudfront)console.log("Destroying CloudFront distribution");if(a.route53)console.log("Destroying Route53 resources")}async destroyRegionStack(a){if(a.status!=="deployed")return;a.status="rolling-back";try{console.log(`Destroying stack ${a.stackName} in ${a.region}`),a.status="pending"}catch(n){throw a.status="failed",a.error=n instanceof Error?n.message:String(n),n}}getDeployment(a){return this.deployments.get(a)}listDeployments(){return Array.from(this.deployments.values())}getStackName(a,n){return`${a.project.slug}-${n}`}createRegionConfig(a,n){return{...a,infrastructure:{...a.infrastructure}}}async deployStack(a,n,i){console.log(`Deploying stack ${a} to ${i}`)}generateDeploymentId(){return`deploy-${Date.now()}-${Math.random().toString(36).substring(7)}`}}var ES=new eg;class tg{references=[];exports=new Map;addExport(a){let n=`${a.region}:${a.exportName}`;if(!this.exports.has(a.region))this.exports.set(a.region,[]);this.exports.get(a.region).push(a)}getExport(a,n){let i=this.exports.get(a);if(!i)return;return i.find((s)=>s.exportName===n)?.value}createReference(a,n,i,s){let c=`/cross-region/${a}/${i}/${s}`;return this.references.push({sourceRegion:a,targetRegion:n,resourceType:i,resourceId:s,value:c}),c}async resolveReference(a,n){let i=this.references.find((s)=>s.targetRegion===a&&s.value===n);if(!i)throw Error(`Reference not found: ${n}`);return`arn:aws:resource:${i.sourceRegion}:123456789012:${i.resourceType}/${i.resourceId}`}getReferencesForRegion(a){return this.references.filter((n)=>n.sourceRegion===a||n.targetRegion===a)}clear(){this.references=[],this.exports.clear()}}class rg{resources=new Map;register(a){this.resources.set(a.id,a)}get(a){return this.resources.get(a)}getByType(a){return Array.from(this.resources.values()).filter((n)=>n.type===a)}getCloudFrontDistributions(){return this.getByType("cloudfront")}getRoute53HostedZones(){return this.getByType("route53")}getWAFWebACLs(){return this.getByType("waf")}remove(a){this.resources.delete(a)}clear(){this.resources.clear()}}class ng{pairs=[];addPair(a){this.pairs.push(a)}getPairedRegion(a){let n=this.pairs.find((i)=>i.primary===a||i.secondary===a);if(!n)return;return n.primary===a?n.secondary:n.primary}getAllPairs(){return[...this.pairs]}getReplicatedPairs(){return this.pairs.filter((a)=>a.replicationConfig)}getFailoverPairs(){return this.pairs.filter((a)=>a.failoverConfig?.automatic)}arePaired(a,n){return this.pairs.some((i)=>i.primary===a&&i.secondary===n||i.primary===n&&i.secondary===a)}clear(){this.pairs=[]}}class ig{dependencies=[];addDependency(a){this.dependencies.push(a)}getDependencies(a,n){return this.dependencies.filter((i)=>i.dependentStack===a&&i.dependentRegion===n)}getDependents(a,n){return this.dependencies.filter((i)=>i.dependsOnStack===a&&i.dependsOnRegion===n)}hasDependencies(a,n){return this.getDependencies(a,n).length>0}getDeploymentOrder(a){let n=new Set,i=[],s=(c)=>{let l=`${c.name}:${c.region}`;if(n.has(l))return;n.add(l);let u=this.getDependencies(c.name,c.region);for(let h of u)s({name:h.dependsOnStack,region:h.dependsOnRegion});i.push(c)};for(let c of a)s(c);return i}detectCircularDependencies(){let a=new Set,n=new Set,i=(s,c)=>{let l=`${s}:${c}`;if(n.has(l))return!0;if(a.has(l))return!1;a.add(l),n.add(l);let u=this.getDependencies(s,c);for(let h of u)if(i(h.dependsOnStack,h.dependsOnRegion))return!0;return n.delete(l),!1};for(let s of this.dependencies)if(i(s.dependentStack,s.dependentRegion))return!0;return!1}clear(){this.dependencies=[]}}var bS=new tg,vS=new rg,TS=new ng,wS=new ig,we=[{code:"us-east-1",name:"US East (N. Virginia)",location:"Virginia, USA",launchYear:2006,availabilityZones:6,localZones:16,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"standard",multiplier:1},compliance:["PCI-DSS","HIPAA","SOC","ISO","FedRAMP"]},{code:"us-east-2",name:"US East (Ohio)",location:"Ohio, USA",launchYear:2016,availabilityZones:3,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"standard",multiplier:1},compliance:["PCI-DSS","HIPAA","SOC","ISO"]},{code:"us-west-1",name:"US West (N. California)",location:"California, USA",launchYear:2009,availabilityZones:3,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"premium",multiplier:1.1},compliance:["PCI-DSS","HIPAA","SOC","ISO"]},{code:"us-west-2",name:"US West (Oregon)",location:"Oregon, USA",launchYear:2011,availabilityZones:4,localZones:2,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"standard",multiplier:1},compliance:["PCI-DSS","HIPAA","SOC","ISO"]},{code:"eu-west-1",name:"Europe (Ireland)",location:"Dublin, Ireland",launchYear:2007,availabilityZones:3,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"standard",multiplier:1.05},compliance:["PCI-DSS","GDPR","SOC","ISO"]},{code:"eu-central-1",name:"Europe (Frankfurt)",location:"Frankfurt, Germany",launchYear:2014,availabilityZones:3,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"premium",multiplier:1.1},compliance:["PCI-DSS","GDPR","SOC","ISO"]},{code:"ap-southeast-1",name:"Asia Pacific (Singapore)",location:"Singapore",launchYear:2010,availabilityZones:3,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"premium",multiplier:1.12},compliance:["PCI-DSS","SOC","ISO","MTCS"]},{code:"ap-northeast-1",name:"Asia Pacific (Tokyo)",location:"Tokyo, Japan",launchYear:2011,availabilityZones:4,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"premium",multiplier:1.15},compliance:["PCI-DSS","SOC","ISO"]}];function Ii(a){return we.find((n)=>n.code===a)}function RS(){return we}function DS(a){let n=a.toLowerCase();return we.filter((i)=>i.location.toLowerCase().includes(n))}function PS(a){return we.filter((n)=>n.compliance.includes(a))}function NS(a){return we.filter((n)=>n.pricing.tier===a)}function kS(a){return we.some((n)=>n.code===a)}function BS(a){if(a.continent==="North America")return Ii("us-east-1");if(a.continent==="Europe")return Ii("eu-west-1");if(a.continent==="Asia")return Ii("ap-southeast-1");return Ii("us-east-1")}function _S(a){let n=[...we];if(a.compliance)n=n.filter((i)=>a.compliance.every((s)=>i.compliance.includes(s)));if(a.requiredServices)n=n.filter((i)=>a.requiredServices.every((s)=>i.services[s]));if(a.pricingSensitive)n.sort((i,s)=>i.pricing.multiplier-s.pricing.multiplier);return n.slice(0,5)}function xS(a){let n=Ii(a);if(!n)throw Error(`Invalid region: ${a}`);let i=[];for(let s of we){if(s.code===a)continue;let c=Ln(n,s),l=Mn(n,s);i.push({primary:n,secondary:s,distance:c,sameContinent:l})}return i.sort((s,c)=>{if(s.sameContinent!==c.sameContinent)return s.sameContinent?1:-1;return s.distance-c.distance}),i.slice(0,3)}function Ln(a,n){let i={"North America":0,"South America":1,Europe:2,Asia:3,Africa:4,Oceania:5},s=Xe(a.location),c=Xe(n.location);return Math.abs((i[s]||0)-(i[c]||0))}function Mn(a,n){return Xe(a.location)===Xe(n.location)}function Xe(a){if(a.includes("USA")||a.includes("Canada"))return"North America";if(a.includes("Europe")||a.includes("Ireland")||a.includes("Germany"))return"Europe";if(a.includes("Asia")||a.includes("Singapore")||a.includes("Japan"))return"Asia";if(a.includes("Brazil"))return"South America";if(a.includes("Australia"))return"Oceania";return"Unknown"}function Zf(a){return`${a.name} (${a.code})`}function OS(a){return a.map((n)=>Zf(n)).join(`
2765
2765
  `)}function LS(){let a={total:we.length,byContinent:{},byPricingTier:{}};for(let n of we){let i=Xe(n.location);a.byContinent[i]=(a.byContinent[i]||0)+1,a.byPricingTier[n.pricing.tier]=(a.byPricingTier[n.pricing.tier]||0)+1}return a}class sg{accounts=new Map;crossAccountRoles=[];accountMappings=[];registerAccount(a){this.accounts.set(a.id,a)}getAccount(a){return this.accounts.get(a)}getAccountByAlias(a){return Array.from(this.accounts.values()).find((n)=>n.alias===a)}listAccounts(){return Array.from(this.accounts.values())}getAccountsByRole(a){return Array.from(this.accounts.values()).filter((n)=>n.role===a)}createCrossAccountRole(a,n,i,s,c){let l={roleArn:`arn:aws:iam::${n}:role/${i}`,roleName:i,sourceAccountId:a,targetAccountId:n,permissions:s,externalId:c?.externalId,sessionDuration:c?.sessionDuration||3600};return this.crossAccountRoles.push(l),l}getAssumeRolePolicyDocument(a,n){let i={Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${a}:root`},Action:"sts:AssumeRole"}]};if(n)i.Statement[0].Condition={StringEquals:{"sts:ExternalId":n}};return i}generateCrossAccountPolicy(a){return{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:a,Resource:"*"}]}}mapEnvironmentToAccount(a,n,i){this.accountMappings.push({environment:a,accountId:n,region:i})}getAccountForEnvironment(a){return this.accountMappings.find((n)=>n.environment===a)}async assumeRole(a,n,i){return console.log(`Assuming role: ${a} with session: ${n}`),{accessKeyId:"AKIAIOSFODNN7EXAMPLE",secretAccessKey:"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",sessionToken:"token",expiration:new Date(Date.now()+3600000)}}async getCredentialsForAccount(a){let n=this.accounts.get(a);if(!n)throw Error(`Account not found: ${a}`);if(n.assumeRoleArn){let i=await this.assumeRole(n.assumeRoleArn,`ts-cloud-${Date.now()}`);return{accessKeyId:i.accessKeyId,secretAccessKey:i.secretAccessKey,sessionToken:i.sessionToken}}throw Error("No credentials available for account")}listCrossAccountRoles(){return[...this.crossAccountRoles]}getCrossAccountRolesForAccount(a){return this.crossAccountRoles.filter((n)=>n.sourceAccountId===a||n.targetAccountId===a)}async validateAccountAccess(a){try{let n=await this.getCredentialsForAccount(a);return console.log(`Validating access to account: ${a}`),!0}catch{return!1}}async getConsolidatedBilling(){let a={};for(let n of this.accounts.values())a[n.id]=Math.random()*1000;return{totalCost:Object.values(a).reduce((n,i)=>n+i,0),byAccount:a}}clear(){this.accounts.clear(),this.crossAccountRoles=[],this.accountMappings=[]}}class og{organizationId;organizationalUnits=new Map;getOrganizationId(){return this.organizationId}setOrganizationId(a){this.organizationId=a}createOrganizationalUnit(a,n){let i={id:`ou-${Date.now()}`,name:a,parentId:n,accounts:[]};return this.organizationalUnits.set(i.id,i),i}getOrganizationalUnit(a){return this.organizationalUnits.get(a)}listOrganizationalUnits(){return Array.from(this.organizationalUnits.values())}addAccountToOU(a,n){let i=this.organizationalUnits.get(a);if(!i)throw Error(`Organizational unit not found: ${a}`);if(!i.accounts.includes(n))i.accounts.push(n)}removeAccountFromOU(a,n){let i=this.organizationalUnits.get(a);if(!i)throw Error(`Organizational unit not found: ${a}`);i.accounts=i.accounts.filter((s)=>s!==n)}getAccountsInOU(a){let n=this.organizationalUnits.get(a);if(!n)return[];return[...n.accounts]}applyServiceControlPolicy(a,n){return{id:`scp-${Date.now()}`,name:"Custom SCP",targetId:a,policyDocument:n}}clear(){this.organizationId=void 0,this.organizationalUnits.clear()}}var $S=new sg,MS=new og,eA={basic:{name:"Basic (3 Accounts)",description:"Simple structure for small teams",accounts:[{alias:"management",email:"aws+management@example.com",role:"management",ou:"root",description:"Management account for AWS Organizations"},{alias:"production",email:"aws+production@example.com",role:"production",ou:"workloads",description:"Production workloads"},{alias:"development",email:"aws+development@example.com",role:"development",ou:"workloads",description:"Development and testing"}],organizationalUnits:[{name:"root"},{name:"workloads",parent:"root"}]},standard:{name:"Standard (5 Accounts)",description:"Recommended for most organizations",accounts:[{alias:"management",email:"aws+management@example.com",role:"management",ou:"root",description:"Management account"},{alias:"security",email:"aws+security@example.com",role:"security",ou:"security",description:"Security tooling and audit logs"},{alias:"shared-services",email:"aws+shared@example.com",role:"shared-services",ou:"infrastructure",description:"Shared services (CI/CD, monitoring)"},{alias:"production",email:"aws+production@example.com",role:"production",ou:"workloads",description:"Production environment"},{alias:"staging",email:"aws+staging@example.com",role:"staging",ou:"workloads",description:"Staging environment"},{alias:"development",email:"aws+development@example.com",role:"development",ou:"workloads",description:"Development environment"}],organizationalUnits:[{name:"root"},{name:"security",parent:"root"},{name:"infrastructure",parent:"root"},{name:"workloads",parent:"root"}]},enterprise:{name:"Enterprise (7+ Accounts)",description:"For large organizations with strict compliance requirements",accounts:[{alias:"management",email:"aws+management@example.com",role:"management",ou:"root",description:"Management account"},{alias:"audit",email:"aws+audit@example.com",role:"security",ou:"security",description:"Audit and compliance"},{alias:"log-archive",email:"aws+logs@example.com",role:"security",ou:"security",description:"Centralized log storage"},{alias:"shared-services",email:"aws+shared@example.com",role:"shared-services",ou:"infrastructure",description:"Shared infrastructure"},{alias:"network",email:"aws+network@example.com",role:"shared-services",ou:"infrastructure",description:"Network infrastructure (Transit Gateway)"},{alias:"production",email:"aws+production@example.com",role:"production",ou:"production-ou",description:"Production workloads"},{alias:"staging",email:"aws+staging@example.com",role:"staging",ou:"non-production-ou",description:"Staging environment"},{alias:"development",email:"aws+development@example.com",role:"development",ou:"non-production-ou",description:"Development environment"}],organizationalUnits:[{name:"root"},{name:"security",parent:"root",policies:["deny-root-access"]},{name:"infrastructure",parent:"root"},{name:"production-ou",parent:"root",policies:["require-mfa"]},{name:"non-production-ou",parent:"root"}]}},FS={denyRootAccess:{name:"Deny Root User Access",description:"Prevent root user from performing any actions",policyDocument:{Version:"2012-10-17",Statement:[{Sid:"DenyRootUser",Effect:"Deny",Action:"*",Resource:"*",Condition:{StringLike:{"aws:PrincipalArn":"arn:aws:iam::*:root"}}}]}},requireMFA:{name:"Require MFA for All Actions",description:"Require MFA for console and API access",policyDocument:{Version:"2012-10-17",Statement:[{Sid:"RequireMFA",Effect:"Deny",Action:"*",Resource:"*",Condition:{BoolIfExists:{"aws:MultiFactorAuthPresent":"false"}}}]}},denyRegions:{name:"Deny Access to Non-Approved Regions",description:"Restrict operations to specific regions",policyDocument:{Version:"2012-10-17",Statement:[{Sid:"DenyNonApprovedRegions",Effect:"Deny",NotAction:["iam:*","organizations:*","route53:*","cloudfront:*","support:*","s3:*"],Resource:"*",Condition:{StringNotEquals:{"aws:RequestedRegion":["us-east-1","us-west-2"]}}}]}},preventLeaving:{name:"Prevent Leaving Organization",description:"Prevent accounts from leaving the organization",policyDocument:{Version:"2012-10-17",Statement:[{Sid:"PreventLeaving",Effect:"Deny",Action:"organizations:LeaveOrganization",Resource:"*"}]}},denyS3Unencrypted:{name:"Deny Unencrypted S3 Uploads",description:"Require encryption for all S3 uploads",policyDocument:{Version:"2012-10-17",Statement:[{Sid:"DenyUnencryptedS3Uploads",Effect:"Deny",Action:"s3:PutObject",Resource:"*",Condition:{StringNotEquals:{"s3:x-amz-server-side-encryption":["AES256","aws:kms"]}}}]}}},US={deploymentRole:{name:"CrossAccountDeploymentRole",description:"Role for deploying infrastructure from CI/CD",permissions:["cloudformation:*","s3:*","ec2:*","ecs:*","lambda:*","iam:GetRole","iam:PassRole","logs:*","events:*"]},readOnlyRole:{name:"CrossAccountReadOnlyRole",description:"Read-only access for monitoring and auditing",permissions:["cloudformation:Describe*","cloudformation:List*","ec2:Describe*","ecs:Describe*","lambda:Get*","lambda:List*","s3:Get*","s3:List*","logs:Get*","logs:Describe*"]},securityAuditRole:{name:"CrossAccountSecurityAuditRole",description:"Security audit and compliance checks",permissions:["iam:Get*","iam:List*","iam:Generate*","access-analyzer:*","guardduty:Get*","guardduty:List*","securityhub:Get*","securityhub:List*","config:Describe*","config:Get*","config:List*"]},breakGlassRole:{name:"CrossAccountBreakGlassRole",description:"Emergency access role (use with caution)",permissions:["*"]}};function QS(a){return eA[a]}function HS(a,n){return{Type:"AWS::IAM::Role",Properties:{RoleName:a.roleName,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${a.sourceAccountId}:root`},Action:"sts:AssumeRole",...a.externalId&&{Condition:{StringEquals:{"sts:ExternalId":a.externalId}}}}]},Policies:[{PolicyName:`${a.roleName}Policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:a.permissions,Resource:"*"}]}}],...n&&{ManagedPolicyArns:n},MaxSessionDuration:a.sessionDuration||3600,Tags:[{Key:"ManagedBy",Value:"TS-Cloud"},{Key:"SourceAccount",Value:a.sourceAccountId}]}}}function GS(a){let n=[],i=[],s=a.accounts.filter((y)=>y.role==="management");if(s.length===0)n.push("No management account defined");if(s.length>1)n.push("Multiple management accounts defined");let c=a.accounts.map((y)=>y.email),l=c.filter((y,S)=>c.indexOf(y)!==S);if(l.length>0)n.push(`Duplicate email addresses: ${l.join(", ")}`);let u=a.accounts.map((y)=>y.alias),h=u.filter((y,S)=>u.indexOf(y)!==S);if(h.length>0)n.push(`Duplicate aliases: ${h.join(", ")}`);if(!a.accounts.some((y)=>y.role==="security"))i.push("No dedicated security account - consider adding one for audit logs");if(a.accounts.length<3)i.push("Less than 3 accounts - consider separating environments");if(!a.accounts.some((y)=>y.role==="production"))i.push("No production account defined");return{valid:n.length===0,errors:n,warnings:i}}function qS(a){let n=[];if(n.push(`${a.name}`),n.push("─".repeat(a.name.length)),n.push(a.description),n.push(""),a.organizationalUnits){n.push("Organizational Units:");for(let i of a.organizationalUnits){let s=i.parent?" └─ ":" ";n.push(`${s}${i.name}`)}n.push("")}n.push("Accounts:");for(let i of a.accounts)n.push(` ${i.alias.padEnd(20)} ${i.role.padEnd(15)} ${i.email}`),n.push(` ${"".padEnd(20)} ${i.description}`),n.push("");return n.join(`
2766
- `)}function VS(a={}){let{workflowName:n="Deploy",trigger:i="push",branches:s=["main"],environments:c=["production"],awsRegion:l="us-east-1",awsRole:u,bunVersion:h="latest",deployCommand:y="bun run cloud deploy",testCommand:S="bun test",buildCommand:b="bun run build"}=a,A=!!u;return`name: ${n}
2766
+ `)}function VS(a={}){let{workflowName:n="Deploy",trigger:i="push",branches:s=["main"],environments:c=["production"],awsRegion:l="us-east-1",awsRole:u,bunVersion:h="latest",deployCommand:y="bun run cloud deploy",testCommand:S="bun test",buildCommand:A="bun run build"}=a,C=!!u;return`name: ${n}
2767
2767
 
2768
2768
  on:
2769
2769
  ${i}:
2770
2770
  branches:
2771
- ${s.map((C)=>` - ${C}`).join(`
2771
+ ${s.map((T)=>` - ${T}`).join(`
2772
2772
  `)}
2773
2773
 
2774
2774
  env:
@@ -2794,7 +2794,7 @@ jobs:
2794
2794
  run: ${S}
2795
2795
 
2796
2796
  - name: Build
2797
- run: ${b}
2797
+ run: ${A}
2798
2798
 
2799
2799
  deploy:
2800
2800
  needs: test
@@ -2816,7 +2816,7 @@ jobs:
2816
2816
  - name: Install dependencies
2817
2817
  run: bun install
2818
2818
 
2819
- ${A?`- name: Configure AWS credentials (OIDC)
2819
+ ${C?`- name: Configure AWS credentials (OIDC)
2820
2820
  uses: aws-actions/configure-aws-credentials@v4
2821
2821
  with:
2822
2822
  role-to-assume: ${u}
@@ -3597,7 +3597,7 @@ workflows:
3597
3597
  requires:
3598
3598
  - test
3599
3599
  ${c}
3600
- `}class ag{backupPlans=new Map;backupVaults=new Map;restoreJobs=new Map;continuousBackups=new Map;planCounter=0;restoreCounter=0;continuousBackupCounter=0;createVault(a){this.backupVaults.set(a.name,a)}getVault(a){return this.backupVaults.get(a)}createBackupPlan(a){let n=`backup-plan-${Date.now()}-${this.planCounter++}`,i={id:n,...a};return this.backupPlans.set(n,i),i}getBackupPlan(a){return this.backupPlans.get(a)}listBackupPlans(){return Array.from(this.backupPlans.values())}createRDSBackupPlan(a){let{dbInstanceArn:n,schedule:i="0 2 * * *",retentionDays:s=7,vaultName:c="default-vault"}=a;return this.createBackupPlan({name:"RDS Daily Backup",schedule:i,retentionDays:s,vaultName:c,resources:[{resourceArn:n,resourceType:"rds",region:"us-east-1"}],lifecycle:{moveTocoldStorageAfterDays:30,deleteAfterDays:s}})}createDynamoDBBackupPlan(a){let{tableArn:n,schedule:i="0 3 * * *",retentionDays:s=35,crossRegionCopy:c}=a;return this.createBackupPlan({name:"DynamoDB Daily Backup",schedule:i,retentionDays:s,vaultName:"dynamodb-vault",resources:[{resourceArn:n,resourceType:"dynamodb",region:"us-east-1"}],lifecycle:{deleteAfterDays:s},tags:c?{CrossRegionCopy:c.join(",")}:void 0})}createEFSBackupPlan(a){let{fileSystemArn:n,schedule:i="0 1 * * *",retentionDays:s=30}=a;return this.createBackupPlan({name:"EFS Daily Backup",schedule:i,retentionDays:s,vaultName:"efs-vault",resources:[{resourceArn:n,resourceType:"efs",region:"us-east-1"}],lifecycle:{deleteAfterDays:s}})}enableContinuousBackup(a,n=35){let i=`continuous-backup-${Date.now()}-${this.continuousBackupCounter++}`,s={id:i,resourceId:a,enabled:!0,retentionDays:n};return this.continuousBackups.set(i,s),s}getContinuousBackup(a){return this.continuousBackups.get(a)}enablePointInTimeRecovery(a,n){return{enabled:!0,earliestRestorableTime:new Date(Date.now()-604800000),latestRestorableTime:new Date}}async restoreFromBackup(a){let{backupId:n,resourceType:i,targetRegion:s}=a,c={id:`restore-${Date.now()}-${this.restoreCounter++}`,backupId:n,resourceType:i,status:"pending",startTime:new Date,targetRegion:s};return this.restoreJobs.set(c.id,c),setTimeout(()=>{c.status="running"},100),setTimeout(()=>{c.status="completed",c.endTime=new Date},1000),c}async restoreToPointInTime(a){let{sourceResourceArn:n,targetResourceName:i,restoreTime:s,resourceType:c}=a,l={id:`pitr-${Date.now()}-${this.restoreCounter++}`,backupId:`pitr-${s.getTime()}`,resourceType:c,status:"pending",startTime:new Date};return this.restoreJobs.set(l.id,l),console.log(`Restoring ${c} from ${n} to ${i} at ${s.toISOString()}`),setTimeout(()=>{l.status="completed",l.endTime=new Date},2000),l}getRestoreJob(a){return this.restoreJobs.get(a)}listRestoreJobs(){return Array.from(this.restoreJobs.values())}setupCrossRegionReplication(a){let{sourceVault:n,sourceRegion:i,targetRegions:s}=a;console.log("Setting up cross-region replication:"),console.log(` Source: ${n} in ${i}`),console.log(` Targets: ${s.join(", ")}`)}generateBackupVaultCF(a){return{Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:a.name,...a.encryptionKeyArn&&{EncryptionKeyArn:a.encryptionKeyArn},...a.accessPolicy&&{AccessPolicy:a.accessPolicy}}}}generateBackupPlanCF(a){return{Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:a.name,BackupPlanRule:[{RuleName:"DailyBackup",TargetBackupVault:a.vaultName,ScheduleExpression:`cron(${a.schedule})`,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:a.lifecycle?{...a.lifecycle.moveTocoldStorageAfterDays&&{MoveToColdStorageAfterDays:a.lifecycle.moveTocoldStorageAfterDays},...a.lifecycle.deleteAfterDays&&{DeleteAfterDays:a.lifecycle.deleteAfterDays}}:void 0}]},...a.tags&&{BackupPlanTags:a.tags}}}}generateBackupSelectionCF(a){return{Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:{Ref:`BackupPlan${a.id}`},BackupSelection:{SelectionName:`${a.name}Selection`,IamRoleArn:"arn:aws:iam::123456789012:role/service-role/AWSBackupDefaultServiceRole",Resources:a.resources.map((n)=>n.resourceArn)}}}}clear(){this.backupPlans.clear(),this.backupVaults.clear(),this.restoreJobs.clear(),this.continuousBackups.clear(),this.planCounter=0,this.restoreCounter=0,this.continuousBackupCounter=0}}var oC=new ag;class cg{drPlans=new Map;failoverTests=new Map;planCounter=0;testCounter=0;createDRPlan(a){let n=`dr-plan-${Date.now()}-${this.planCounter++}`,i={id:n,...a};return this.drPlans.set(n,i),i}createRDSDRPlan(a){let{primaryDbArn:n,secondaryDbArn:i,primaryRegion:s,secondaryRegion:c,rto:l=60,rpo:u=5}=a;return this.createDRPlan({name:"RDS Multi-Region DR",primaryRegion:s,secondaryRegion:c,rto:l,rpo:u,resources:[{resourceId:"primary-db",resourceType:"rds",primaryArn:n,secondaryArn:i,replicationEnabled:!0}],runbook:this.generateRDSRunbook(s,c),testSchedule:"0 0 1 * *"})}createDynamoDBDRPlan(a){let{tableArn:n,regions:i,rto:s=15,rpo:c=1}=a;return this.createDRPlan({name:"DynamoDB Global Tables DR",primaryRegion:i[0],secondaryRegion:i[1],rto:s,rpo:c,resources:[{resourceId:"dynamodb-table",resourceType:"dynamodb",primaryArn:n,replicationEnabled:!0}],runbook:this.generateDynamoDBRunbook(i)})}generateRDSRunbook(a,n){return{estimatedDuration:60,requiredApprovals:["cto","engineering-lead"],steps:[{order:1,name:"Verify Primary Database Failure",description:"Confirm that the primary database is truly unavailable and not experiencing temporary issues",action:"aws rds describe-db-instances --region "+a,automatable:!0,estimatedDuration:2,rollbackable:!1},{order:2,name:"Check Replication Lag",description:"Verify that the read replica is up to date",action:"Check ReplicaLag metric in CloudWatch",automatable:!0,estimatedDuration:1,rollbackable:!1},{order:3,name:"Promote Read Replica",description:"Promote the read replica in the secondary region to be the new primary",action:"aws rds promote-read-replica --db-instance-identifier replica --region "+n,automatable:!0,estimatedDuration:10,rollbackable:!1},{order:4,name:"Update DNS Records",description:"Update Route53 records to point to the new primary database",action:"Update Route53 failover record set",automatable:!0,estimatedDuration:5,rollbackable:!0},{order:5,name:"Update Application Configuration",description:"Update application connection strings if needed",action:"Deploy configuration update to ECS/Lambda",automatable:!0,estimatedDuration:10,rollbackable:!0},{order:6,name:"Verify Application Connectivity",description:"Test that applications can connect to the new primary",action:"Run smoke tests",automatable:!0,estimatedDuration:5,rollbackable:!1},{order:7,name:"Monitor for Issues",description:"Monitor CloudWatch metrics and application logs",action:"Monitor for 30 minutes",automatable:!1,estimatedDuration:30,rollbackable:!1}]}}generateDynamoDBRunbook(a){return{estimatedDuration:15,steps:[{order:1,name:"Verify Primary Region Failure",description:"Confirm that the primary region is experiencing an outage",action:"Check AWS Health Dashboard",automatable:!0,estimatedDuration:2,rollbackable:!1},{order:2,name:"Update Route53 Failover",description:"Update Route53 to direct traffic to secondary region",action:"Update Route53 health check and failover records",automatable:!0,estimatedDuration:5,rollbackable:!0},{order:3,name:"Update Application Endpoints",description:"Update Lambda/ECS to use secondary region DynamoDB endpoint",action:"Deploy configuration update",automatable:!0,estimatedDuration:5,rollbackable:!0},{order:4,name:"Verify Data Consistency",description:"Verify that data is consistent in secondary region",action:"Run data validation queries",automatable:!0,estimatedDuration:3,rollbackable:!1}]}}async executeFailover(a,n=!1){let i=this.drPlans.get(a);if(!i)throw Error(`DR plan not found: ${a}`);let s=Date.now(),c=0;console.log(`${n?"[DRY RUN] ":""}Executing failover for plan: ${i.name}`),console.log(`Primary: ${i.primaryRegion} -> Secondary: ${i.secondaryRegion}`),console.log(`RTO: ${i.rto} minutes, RPO: ${i.rpo} minutes`),console.log("");for(let l of i.runbook.steps){if(console.log(`Step ${l.order}: ${l.name}`),console.log(` ${l.description}`),console.log(` Action: ${l.action}`),console.log(` Estimated: ${l.estimatedDuration} minutes`),n)console.log(" [SKIPPED - DRY RUN]");else if(l.automatable)console.log(" [AUTOMATED]");else console.log(" [MANUAL - WAITING]");c++,console.log("")}return{success:!0,duration:(Date.now()-s)/1000/60,completedSteps:c}}scheduleFailoverTest(a,n){let i={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:a,status:"scheduled",startTime:n};return this.failoverTests.set(i.id,i),i}async runFailoverTest(a){let n=this.drPlans.get(a);if(!n)throw Error(`DR plan not found: ${a}`);let i={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:a,status:"running",startTime:new Date,results:[]};this.failoverTests.set(i.id,i),console.log(`Running failover test for plan: ${n.name}`),console.log("This is a non-destructive test using test resources"),console.log("");for(let s of n.runbook.steps){let c=Date.now();console.log(`Testing step ${s.order}: ${s.name}`);let l={step:s.name,status:"success",duration:(Date.now()-c)/1000,message:`Successfully validated step ${s.order}`};i.results.push(l)}return i.status="completed",i.endTime=new Date,i}getDRPlan(a){return this.drPlans.get(a)}listDRPlans(){return Array.from(this.drPlans.values())}getFailoverTest(a){return this.failoverTests.get(a)}listFailoverTests(){return Array.from(this.failoverTests.values())}validateDRPlan(a){let n=[],i=[];if(a.rto<a.rpo)i.push("RTO cannot be less than RPO");if(a.rto>240)n.push("RTO exceeds 4 hours - consider improving recovery time");if(a.rpo>60)n.push("RPO exceeds 1 hour - consider more frequent backups");if(a.resources.length===0)i.push("No resources defined in DR plan");for(let l of a.resources){if(!l.replicationEnabled)n.push(`Resource ${l.resourceId} does not have replication enabled`);if(!l.secondaryArn&&l.resourceType!=="dynamodb")n.push(`Resource ${l.resourceId} does not have secondary resource defined`)}if(a.runbook.steps.length===0)i.push("No recovery steps defined in runbook");let s=a.runbook.steps.reduce((l,u)=>l+u.estimatedDuration,0);if(s>a.rto)n.push(`Estimated recovery duration (${s}m) exceeds RTO (${a.rto}m)`);let c=a.runbook.steps.filter((l)=>!l.automatable);if(c.length>0)n.push(`${c.length} manual steps in runbook - consider automation`);return{valid:i.length===0,warnings:n,errors:i}}clear(){this.drPlans.clear(),this.failoverTests.clear(),this.planCounter=0,this.testCounter=0}}var aC=new cg;class dg{configRules=new Map;configRecorders=new Map;deliveryChannels=new Map;ruleCounter=0;createConfigRecorder(a){return this.configRecorders.set(a.name,a),a}createDeliveryChannel(a){return this.deliveryChannels.set(a.name,a),a}createConfigRule(a){let n=`config-rule-${Date.now()}-${this.ruleCounter++}`,i={id:n,...a};return this.configRules.set(n,i),i}createS3EncryptionRule(){return this.createConfigRule({name:"s3-bucket-server-side-encryption-enabled",description:"Checks that S3 buckets have server-side encryption enabled",source:"AWS_MANAGED",identifier:"S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED",scope:{complianceResourceTypes:["AWS::S3::Bucket"]}})}createS3PublicAccessBlockRule(){return this.createConfigRule({name:"s3-bucket-public-read-prohibited",description:"Checks that S3 buckets do not allow public read access",source:"AWS_MANAGED",identifier:"S3_BUCKET_PUBLIC_READ_PROHIBITED",scope:{complianceResourceTypes:["AWS::S3::Bucket"]}})}createS3VersioningRule(){return this.createConfigRule({name:"s3-bucket-versioning-enabled",description:"Checks whether versioning is enabled for S3 buckets",source:"AWS_MANAGED",identifier:"S3_BUCKET_VERSIONING_ENABLED",scope:{complianceResourceTypes:["AWS::S3::Bucket"]}})}createRdsEncryptionRule(){return this.createConfigRule({name:"rds-storage-encrypted",description:"Checks whether storage encryption is enabled for RDS DB instances",source:"AWS_MANAGED",identifier:"RDS_STORAGE_ENCRYPTED",scope:{complianceResourceTypes:["AWS::RDS::DBInstance"]}})}createRdsSnapshotEncryptionRule(){return this.createConfigRule({name:"rds-snapshots-public-prohibited",description:"Checks if RDS snapshots are public",source:"AWS_MANAGED",identifier:"RDS_SNAPSHOTS_PUBLIC_PROHIBITED",scope:{complianceResourceTypes:["AWS::RDS::DBSnapshot","AWS::RDS::DBClusterSnapshot"]}})}createRdsBackupRule(a=7){return this.createConfigRule({name:"db-backup-enabled",description:"Checks whether RDS DB instances have backups enabled",source:"AWS_MANAGED",identifier:"DB_BACKUP_ENABLED",inputParameters:{backupRetentionPeriod:a},scope:{complianceResourceTypes:["AWS::RDS::DBInstance"]}})}createEc2InstanceProfileRule(){return this.createConfigRule({name:"ec2-instance-managed-by-systems-manager",description:"Checks if EC2 instances are managed by Systems Manager",source:"AWS_MANAGED",identifier:"EC2_INSTANCE_MANAGED_BY_SSM",scope:{complianceResourceTypes:["AWS::EC2::Instance"]}})}createEbsEncryptionRule(){return this.createConfigRule({name:"encrypted-volumes",description:"Checks whether EBS volumes are encrypted",source:"AWS_MANAGED",identifier:"ENCRYPTED_VOLUMES",scope:{complianceResourceTypes:["AWS::EC2::Volume"]}})}createIamPasswordPolicyRule(){return this.createConfigRule({name:"iam-password-policy",description:"Checks whether the IAM password policy meets specified requirements",source:"AWS_MANAGED",identifier:"IAM_PASSWORD_POLICY",inputParameters:{RequireUppercaseCharacters:!0,RequireLowercaseCharacters:!0,RequireSymbols:!0,RequireNumbers:!0,MinimumPasswordLength:14,PasswordReusePrevention:24,MaxPasswordAge:90}})}createIamMfaRule(){return this.createConfigRule({name:"iam-user-mfa-enabled",description:"Checks whether IAM users have MFA enabled",source:"AWS_MANAGED",identifier:"IAM_USER_MFA_ENABLED"})}createRootAccountMfaRule(){return this.createConfigRule({name:"root-account-mfa-enabled",description:"Checks whether the root account has MFA enabled",source:"AWS_MANAGED",identifier:"ROOT_ACCOUNT_MFA_ENABLED"})}createVpcFlowLogsRule(){return this.createConfigRule({name:"vpc-flow-logs-enabled",description:"Checks whether VPC Flow Logs is enabled",source:"AWS_MANAGED",identifier:"VPC_FLOW_LOGS_ENABLED",scope:{complianceResourceTypes:["AWS::EC2::VPC"]}})}createCloudTrailEnabledRule(){return this.createConfigRule({name:"cloudtrail-enabled",description:"Checks whether CloudTrail is enabled",source:"AWS_MANAGED",identifier:"CLOUD_TRAIL_ENABLED",maxExecutionFrequency:"TwentyFour_Hours"})}createCloudWatchAlarmRule(){return this.createConfigRule({name:"cloudwatch-alarm-action-check",description:"Checks whether CloudWatch alarms have actions configured",source:"AWS_MANAGED",identifier:"CLOUDWATCH_ALARM_ACTION_CHECK",inputParameters:{alarmActionRequired:!0,insufficientDataActionRequired:!1,okActionRequired:!1},scope:{complianceResourceTypes:["AWS::CloudWatch::Alarm"]}})}createCustomLambdaRule(a){return this.createConfigRule({name:a.name,description:a.description,source:"CUSTOM_LAMBDA",lambdaFunctionArn:a.lambdaFunctionArn,scope:a.resourceTypes?{complianceResourceTypes:a.resourceTypes}:void 0,maxExecutionFrequency:a.maxExecutionFrequency,inputParameters:a.inputParameters})}createCompliancePreset(a){let n=[];switch(a){case"hipaa":n.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createRdsBackupRule(7),this.createVpcFlowLogsRule());break;case"pci-dss":n.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createIamMfaRule(),this.createRootAccountMfaRule(),this.createVpcFlowLogsRule());break;case"sox":n.push(this.createS3VersioningRule(),this.createCloudTrailEnabledRule(),this.createRdsBackupRule(30),this.createIamPasswordPolicyRule());break;case"gdpr":n.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createRdsSnapshotEncryptionRule());break;case"basic":n.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamMfaRule(),this.createRootAccountMfaRule());break}return n}getConfigRule(a){return this.configRules.get(a)}listConfigRules(){return Array.from(this.configRules.values())}getConfigRecorder(a){return this.configRecorders.get(a)}listConfigRecorders(){return Array.from(this.configRecorders.values())}getDeliveryChannel(a){return this.deliveryChannels.get(a)}listDeliveryChannels(){return Array.from(this.deliveryChannels.values())}generateConfigRuleCF(a){let n={Type:"AWS::Config::ConfigRule",Properties:{ConfigRuleName:a.name,Description:a.description,Source:{Owner:a.source==="AWS_MANAGED"?"AWS":"CUSTOM_LAMBDA"}}};if(a.source==="AWS_MANAGED"&&a.identifier)n.Properties.Source.SourceIdentifier=a.identifier;if(a.source==="CUSTOM_LAMBDA"&&a.lambdaFunctionArn)n.Properties.Source.SourceIdentifier=a.lambdaFunctionArn,n.Properties.Source.SourceDetails=[{EventSource:"aws.config",MessageType:"ConfigurationItemChangeNotification"}];if(a.inputParameters)n.Properties.InputParameters=JSON.stringify(a.inputParameters);if(a.scope){if(n.Properties.Scope={},a.scope.complianceResourceTypes)n.Properties.Scope.ComplianceResourceTypes=a.scope.complianceResourceTypes;if(a.scope.tagKey)n.Properties.Scope.TagKey=a.scope.tagKey;if(a.scope.tagValue)n.Properties.Scope.TagValue=a.scope.tagValue}if(a.maxExecutionFrequency)n.Properties.MaximumExecutionFrequency=a.maxExecutionFrequency;return n}generateConfigRecorderCF(a){return{Type:"AWS::Config::ConfigurationRecorder",Properties:{Name:a.name,RoleArn:a.roleArn,RecordingGroup:a.recordingGroup||{AllSupported:!0,IncludeGlobalResourceTypes:!0}}}}generateDeliveryChannelCF(a){return{Type:"AWS::Config::DeliveryChannel",Properties:{Name:a.name,S3BucketName:a.s3BucketName,...a.s3KeyPrefix&&{S3KeyPrefix:a.s3KeyPrefix},...a.snsTopicArn&&{SnsTopicARN:a.snsTopicArn},...a.configSnapshotDeliveryProperties&&{ConfigSnapshotDeliveryProperties:a.configSnapshotDeliveryProperties}}}}clear(){this.configRules.clear(),this.configRecorders.clear(),this.deliveryChannels.clear(),this.ruleCounter=0}}var cC=new dg;class lg{trails=new Map;trailCounter=0;createTrail(a){let n=`trail-${Date.now()}-${this.trailCounter++}`,i={id:n,...a};return this.trails.set(n,i),i}createOrganizationTrail(a){return this.createTrail({name:a.name,s3BucketName:a.s3BucketName,s3KeyPrefix:"organization-trail",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:a.kmsKeyId,cloudWatchLogsLogGroupArn:a.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:a.cloudWatchLogsRoleArn})}createSecurityAuditTrail(a){return this.createTrail({name:a.name,s3BucketName:a.s3BucketName,s3KeyPrefix:"security-audit",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:a.kmsKeyId,cloudWatchLogsLogGroupArn:a.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:a.cloudWatchLogsRoleArn,eventSelectors:[{readWriteType:"All",includeManagementEvents:!0,excludeManagementEventSources:[]}],insightSelectors:[{insightType:"ApiCallRateInsight"},{insightType:"ApiErrorRateInsight"}]})}createDataEventsTrail(a){let n=[];if(a.s3DataBuckets&&a.s3DataBuckets.length>0)n.push({type:"AWS::S3::Object",values:a.s3DataBuckets.map((i)=>`arn:aws:s3:::${i}/*`)});if(a.lambdaFunctions&&a.lambdaFunctions.length>0)n.push({type:"AWS::Lambda::Function",values:a.lambdaFunctions});return this.createTrail({name:a.name,s3BucketName:a.s3BucketName,s3KeyPrefix:"data-events",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"All",includeManagementEvents:!1,dataResources:n}]})}createAdvancedTrail(a){return this.createTrail({name:a.name,s3BucketName:a.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,advancedEventSelectors:a.selectors})}createReadOnlyTrail(a){return this.createTrail({name:a.name,s3BucketName:a.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"ReadOnly",includeManagementEvents:!0}]})}createWriteOnlyTrail(a){return this.createTrail({name:a.name,s3BucketName:a.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"WriteOnly",includeManagementEvents:!0}]})}getTrail(a){return this.trails.get(a)}listTrails(){return Array.from(this.trails.values())}generateTrailCF(a){let n={Type:"AWS::CloudTrail::Trail",Properties:{TrailName:a.name,S3BucketName:a.s3BucketName,IsLogging:!0,IncludeGlobalServiceEvents:a.includeGlobalServiceEvents??!0,IsMultiRegionTrail:a.isMultiRegionTrail??!0,EnableLogFileValidation:a.enableLogFileValidation??!0}};if(a.s3KeyPrefix)n.Properties.S3KeyPrefix=a.s3KeyPrefix;if(a.cloudWatchLogsLogGroupArn)n.Properties.CloudWatchLogsLogGroupArn=a.cloudWatchLogsLogGroupArn;if(a.cloudWatchLogsRoleArn)n.Properties.CloudWatchLogsRoleArn=a.cloudWatchLogsRoleArn;if(a.snsTopicName)n.Properties.SnsTopicName=a.snsTopicName;if(a.kmsKeyId)n.Properties.KMSKeyId=a.kmsKeyId;if(a.eventSelectors)n.Properties.EventSelectors=a.eventSelectors.map((i)=>({ReadWriteType:i.readWriteType,IncludeManagementEvents:i.includeManagementEvents??!0,...i.dataResources&&{DataResources:i.dataResources.map((s)=>({Type:s.type,Values:s.values}))},...i.excludeManagementEventSources&&{ExcludeManagementEventSources:i.excludeManagementEventSources}}));if(a.insightSelectors)n.Properties.InsightSelectors=a.insightSelectors.map((i)=>({InsightType:i.insightType}));if(a.advancedEventSelectors)n.Properties.AdvancedEventSelectors=a.advancedEventSelectors.map((i)=>({Name:i.name,FieldSelectors:i.fieldSelectors.map((s)=>({Field:s.field,...s.equals&&{Equals:s.equals},...s.startsWith&&{StartsWith:s.startsWith},...s.endsWith&&{EndsWith:s.endsWith},...s.notEquals&&{NotEquals:s.notEquals},...s.notStartsWith&&{NotStartsWith:s.notStartsWith},...s.notEndsWith&&{NotEndsWith:s.notEndsWith}}))}));return n}generateBucketPolicy(a,n){return{Version:"2012-10-17",Statement:[{Sid:"AWSCloudTrailAclCheck",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:GetBucketAcl",Resource:`arn:aws:s3:::${a}`},{Sid:"AWSCloudTrailWrite",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:PutObject",Resource:n.map((i)=>`arn:aws:s3:::${a}/AWSLogs/${i}/*`),Condition:{StringEquals:{"s3:x-amz-acl":"bucket-owner-full-control"}}}]}}clear(){this.trails.clear(),this.trailCounter=0}}var dC=new lg;class ug{detectors=new Map;threatIntelSets=new Map;ipSets=new Map;filters=new Map;detectorCounter=0;threatIntelCounter=0;ipSetCounter=0;filterCounter=0;createDetector(a){let n=`detector-${Date.now()}-${this.detectorCounter++}`,i={id:n,...a};return this.detectors.set(n,i),i}createComprehensiveDetector(){return this.createDetector({enable:!0,findingPublishingFrequency:"FIFTEEN_MINUTES",dataSources:{s3Logs:{enable:!0},kubernetes:{auditLogs:{enable:!0}},malwareProtection:{scanEc2InstanceWithFindings:{ebsVolumes:{enable:!0}}}},features:[{name:"S3_DATA_EVENTS",status:"ENABLED"},{name:"EKS_AUDIT_LOGS",status:"ENABLED"},{name:"EBS_MALWARE_PROTECTION",status:"ENABLED"},{name:"RDS_LOGIN_EVENTS",status:"ENABLED"},{name:"LAMBDA_NETWORK_LOGS",status:"ENABLED"}]})}createBasicDetector(){return this.createDetector({enable:!0,findingPublishingFrequency:"SIX_HOURS"})}createThreatIntelSet(a){let n=`threat-intel-${Date.now()}-${this.threatIntelCounter++}`,i={id:n,...a};return this.threatIntelSets.set(n,i),i}createIPSet(a){let n=`ip-set-${Date.now()}-${this.ipSetCounter++}`,i={id:n,...a};return this.ipSets.set(n,i),i}createFindingFilter(a){let n=`filter-${Date.now()}-${this.filterCounter++}`,i={id:n,...a};return this.filters.set(n,i),i}createLowSeverityArchiveFilter(a){return this.createFindingFilter({detectorId:a,name:"archive-low-severity",description:"Automatically archive low severity findings",action:"ARCHIVE",rank:1,findingCriteria:{criterion:{severity:{lt:4}}}})}createFindingTypeFilter(a,n,i){return this.createFindingFilter({detectorId:a,name:`filter-finding-types-${i.toLowerCase()}`,description:`${i==="ARCHIVE"?"Archive":"Keep"} specific finding types`,action:i,rank:2,findingCriteria:{criterion:{type:{eq:n}}}})}createTrustedIPFilter(a,n){return this.createFindingFilter({detectorId:a,name:"trusted-ip-addresses",description:"Archive findings from trusted IP addresses",action:"ARCHIVE",rank:3,findingCriteria:{criterion:{"resource.instanceDetails.networkInterfaces.privateIpAddress":{eq:n}}}})}getDetector(a){return this.detectors.get(a)}listDetectors(){return Array.from(this.detectors.values())}getThreatIntelSet(a){return this.threatIntelSets.get(a)}listThreatIntelSets(){return Array.from(this.threatIntelSets.values())}getIPSet(a){return this.ipSets.get(a)}listIPSets(){return Array.from(this.ipSets.values())}getFindingFilter(a){return this.filters.get(a)}listFindingFilters(){return Array.from(this.filters.values())}generateDetectorCF(a){let n={Type:"AWS::GuardDuty::Detector",Properties:{Enable:a.enable}};if(a.findingPublishingFrequency)n.Properties.FindingPublishingFrequency=a.findingPublishingFrequency;if(a.dataSources){if(n.Properties.DataSources={},a.dataSources.s3Logs)n.Properties.DataSources.S3Logs={Enable:a.dataSources.s3Logs.enable};if(a.dataSources.kubernetes)n.Properties.DataSources.Kubernetes={AuditLogs:{Enable:a.dataSources.kubernetes.auditLogs.enable}};if(a.dataSources.malwareProtection)n.Properties.DataSources.MalwareProtection={ScanEc2InstanceWithFindings:{EbsVolumes:{Enable:a.dataSources.malwareProtection.scanEc2InstanceWithFindings.ebsVolumes.enable}}}}if(a.features)n.Properties.Features=a.features.map((i)=>({Name:i.name,Status:i.status,...i.additionalConfiguration&&{AdditionalConfiguration:i.additionalConfiguration}}));return n}generateThreatIntelSetCF(a){return{Type:"AWS::GuardDuty::ThreatIntelSet",Properties:{DetectorId:a.detectorId,Name:a.name,Format:a.format,Location:a.location,Activate:a.activate}}}generateIPSetCF(a){return{Type:"AWS::GuardDuty::IPSet",Properties:{DetectorId:a.detectorId,Name:a.name,Format:a.format,Location:a.location,Activate:a.activate}}}generateFilterCF(a){return{Type:"AWS::GuardDuty::Filter",Properties:{DetectorId:a.detectorId,Name:a.name,Description:a.description,Action:a.action,Rank:a.rank,FindingCriteria:{Criterion:a.findingCriteria.criterion}}}}clear(){this.detectors.clear(),this.threatIntelSets.clear(),this.ipSets.clear(),this.filters.clear(),this.detectorCounter=0,this.threatIntelCounter=0,this.ipSetCounter=0,this.filterCounter=0}}var lC=new ug;class Lr{hubs=new Map;hubCounter=0;ruleCounter=0;static Standards={AWS_FOUNDATIONAL_SECURITY:{arn:"arn:aws:securityhub:::ruleset/aws-foundational-security-best-practices/v/1.0.0",name:"AWS Foundational Security Best Practices",description:"AWS recommended security best practices"},CIS_AWS_FOUNDATIONS_1_2:{arn:"arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0",name:"CIS AWS Foundations Benchmark v1.2.0",description:"CIS AWS Foundations Benchmark v1.2.0"},CIS_AWS_FOUNDATIONS_1_4:{arn:"arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.4.0",name:"CIS AWS Foundations Benchmark v1.4.0",description:"CIS AWS Foundations Benchmark v1.4.0"},PCI_DSS:{arn:"arn:aws:securityhub:us-east-1::standards/pci-dss/v/3.2.1",name:"PCI DSS v3.2.1",description:"Payment Card Industry Data Security Standard"},NIST_800_53:{arn:"arn:aws:securityhub:us-east-1::standards/nist-800-53/v/5.0.0",name:"NIST SP 800-53 Rev. 5",description:"NIST Special Publication 800-53 Revision 5"}};createHub(a){let n=`hub-${Date.now()}-${this.hubCounter++}`,i={id:n,...a};return this.hubs.set(n,i),i}createComprehensiveHub(){return this.createHub({enable:!0,controlFindingGenerator:"SECURITY_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...Lr.Standards.AWS_FOUNDATIONAL_SECURITY,enabled:!0},{id:"cis-1-4",...Lr.Standards.CIS_AWS_FOUNDATIONS_1_4,enabled:!0},{id:"pci-dss",...Lr.Standards.PCI_DSS,enabled:!0}]})}createBasicHub(){return this.createHub({enable:!0,controlFindingGenerator:"STANDARD_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...Lr.Standards.AWS_FOUNDATIONAL_SECURITY,enabled:!0}]})}createLowSeveritySuppressionRule(){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:"Suppress Low Severity Informational Findings",description:"Automatically suppress informational findings",actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"SUPPRESSED"},note:{text:"Automatically suppressed low severity finding",updatedBy:"SecurityHub Automation"}}}],criteria:{severityLabel:[{value:"INFORMATIONAL",comparison:"EQUALS"}],recordState:[{value:"ACTIVE",comparison:"EQUALS"}]},ruleStatus:"ENABLED",ruleOrder:1}}createResourceTypeNotificationRule(a){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:"Notify on Critical Resource Findings",description:"Set findings for critical resources to NOTIFIED status",actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"NOTIFIED"},note:{text:"Critical resource finding requires attention",updatedBy:"SecurityHub Automation"}}}],criteria:{resourceType:a.map((n)=>({value:n,comparison:"EQUALS"})),severityLabel:[{value:"HIGH",comparison:"EQUALS"},{value:"CRITICAL",comparison:"EQUALS"}],workflowStatus:[{value:"NEW",comparison:"EQUALS"}]},ruleStatus:"ENABLED",ruleOrder:2}}createComplianceFailureRule(){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:"Flag Compliance Failures",description:"Increase severity for compliance failures",actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{severity:{label:"HIGH"},workflow:{status:"NOTIFIED"},note:{text:"Compliance failure detected - requires immediate attention",updatedBy:"SecurityHub Automation"}}}],criteria:{complianceStatus:[{value:"FAILED",comparison:"EQUALS"}],recordState:[{value:"ACTIVE",comparison:"EQUALS"}]},ruleStatus:"ENABLED",ruleOrder:3}}createFalsePositiveSuppressionRule(a,n){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:`Suppress False Positives - ${a}`,description:`Automatically suppress known false positives from ${a}`,actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"SUPPRESSED"},note:{text:"Known false positive - automatically suppressed",updatedBy:"SecurityHub Automation"}}}],criteria:{productName:[{value:a,comparison:"EQUALS"}],title:n.map((i)=>({value:i,comparison:"PREFIX"}))},ruleStatus:"ENABLED",ruleOrder:10}}getHub(a){return this.hubs.get(a)}listHubs(){return Array.from(this.hubs.values())}generateHubCF(a){let n={Type:"AWS::SecurityHub::Hub",Properties:{}};if(a.controlFindingGenerator)n.Properties.ControlFindingGenerator=a.controlFindingGenerator;if(a.enableDefaultStandards!==void 0)n.Properties.EnableDefaultStandards=a.enableDefaultStandards;return n}generateStandardCF(a){let n={Type:"AWS::SecurityHub::Standard",Properties:{StandardsArn:a.arn}};if(a.disabledControls&&a.disabledControls.length>0)n.Properties.DisabledStandardsControls=a.disabledControls.map((i)=>({StandardsControlArn:i,Reason:"Disabled by configuration"}));return n}generateAutomationRuleCF(a){return{Type:"AWS::SecurityHub::AutomationRule",Properties:{RuleName:a.ruleName,Description:a.description,Actions:a.actions.map((n)=>({Type:n.type,FindingFieldsUpdate:n.findingFieldsUpdate})),Criteria:a.criteria,RuleStatus:a.ruleStatus,RuleOrder:a.ruleOrder}}}clear(){this.hubs.clear(),this.hubCounter=0,this.ruleCounter=0}}var uC=new Lr;class pg{deployments=new Map;deploymentHistory=new Map;deploymentCounter=0;resultCounter=0;createDeployment(a){let n=`bg-deployment-${Date.now()}-${this.deploymentCounter++}`,i={id:n,...a};return this.deployments.set(n,i),i}createALBDeployment(a){return this.createDeployment({name:a.name,blueEnvironment:{name:"blue",targetGroupArn:a.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:a.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:a.listenerArn,switchoverTimeSeconds:0},autoPromote:a.autoPromote,healthCheckConfig:a.healthCheckConfig})}createRoute53Deployment(a){return this.createDeployment({name:a.name,blueEnvironment:{name:"blue",targetGroupArn:a.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:a.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"route53",hostedZoneId:a.hostedZoneId,switchoverTimeSeconds:a.switchoverTimeSeconds||60}})}createECSDeployment(a){return this.createDeployment({name:a.name,blueEnvironment:{name:"blue",targetGroupArn:a.blueTargetGroupArn,taskDefinitionArn:a.blueTaskDefinitionArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:a.greenTargetGroupArn,taskDefinitionArn:a.greenTaskDefinitionArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:a.listenerArn},autoRollback:a.autoRollback??!0})}async executeDeployment(a,n=!1){let i=this.deployments.get(a);if(!i)throw Error(`Deployment not found: ${a}`);let s={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!1,errors:[]};console.log(`${n?"[DRY RUN] ":""}Starting blue/green deployment: ${i.name}`),console.log(` Active environment: ${i.activeEnvironment}`),console.log(` Routing type: ${i.routingConfig.type}`);let c=i.activeEnvironment==="blue"?"green":"blue";if(console.log(` Switching to: ${c}`),console.log(`\\n1. Deploying to ${c} environment`),!n)await new Promise((l)=>setTimeout(l,100));if(console.log(`\\n2. Running health checks on ${c} environment`),i.healthCheckConfig){let l=await this.runHealthChecks(i,c,n);if(s.healthChecksPassed=l,!l){if(s.errors?.push("Health checks failed"),s.endTime=new Date,i.autoRollback)console.log(" Auto-rollback enabled - keeping current environment active"),s.rolledBackAt=new Date;return this.recordDeployment(a,s),s}}else s.healthChecksPassed=!0;if(console.log(`\\n3. Switching traffic to ${c} environment`),!n)i.activeEnvironment=c,s.switchedAt=new Date;if(console.log(`\\n4. Monitoring ${c} environment`),!n)await new Promise((l)=>setTimeout(l,100));return s.success=!0,s.endTime=new Date,console.log("\\n✓ Deployment completed successfully"),this.recordDeployment(a,s),s}async rollback(a){let n=this.deployments.get(a);if(!n)throw Error(`Deployment not found: ${a}`);let i={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!0,errors:[]};console.log(`Rolling back deployment: ${n.name}`);let s=n.activeEnvironment==="blue"?"green":"blue";return n.activeEnvironment=s,i.success=!0,i.rolledBackAt=new Date,i.endTime=new Date,console.log(` Switched back to: ${s}`),this.recordDeployment(a,i),i}async runHealthChecks(a,n,i){let s=a.healthCheckConfig;if(console.log(` Health check path: ${s.path||"/"}`),console.log(` Healthy threshold: ${s.healthyThreshold}`),console.log(` Interval: ${s.interval}s`),i)return console.log(" [SKIPPED - DRY RUN]"),!0;let c=0,l=s.healthyThreshold+2;for(let u=0;u<l;u++)if(await new Promise((h)=>setTimeout(h,50)),Math.random()>0.1){if(c++,console.log(` Check ${u+1}: ✓ Healthy (${c}/${s.healthyThreshold})`),c>=s.healthyThreshold)return!0}else c=0,console.log(` Check ${u+1}: ✗ Unhealthy`);return!1}recordDeployment(a,n){if(!this.deploymentHistory.has(a))this.deploymentHistory.set(a,[]);this.deploymentHistory.get(a).push(n)}getDeployment(a){return this.deployments.get(a)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(a){return this.deploymentHistory.get(a)||[]}generateALBListenerCF(a){let n=a.activeEnvironment==="blue"?a.blueEnvironment:a.greenEnvironment;return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:a.routingConfig.listenerArn,Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",TargetGroupArn:n.targetGroupArn}]}}}generateRoute53RecordSetCF(a,n){return[{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:a.routingConfig.hostedZoneId,Name:n,Type:"A",SetIdentifier:"blue",Weight:a.activeEnvironment==="blue"?100:0,AliasTarget:{HostedZoneId:a.routingConfig.hostedZoneId,DNSName:a.blueEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}},{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:a.routingConfig.hostedZoneId,Name:n,Type:"A",SetIdentifier:"green",Weight:a.activeEnvironment==="green"?100:0,AliasTarget:{HostedZoneId:a.routingConfig.hostedZoneId,DNSName:a.greenEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}}]}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var pC=new pg;class no{deployments=new Map;deploymentHistory=new Map;deploymentCounter=0;resultCounter=0;static Strategies={CONSERVATIVE:[{name:"Initial Canary",trafficPercentage:10,durationMinutes:10},{name:"Quarter Traffic",trafficPercentage:25,durationMinutes:10},{name:"Half Traffic",trafficPercentage:50,durationMinutes:15},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}],BALANCED:[{name:"Initial Canary",trafficPercentage:20,durationMinutes:5},{name:"Half Traffic",trafficPercentage:50,durationMinutes:10},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}],AGGRESSIVE:[{name:"Half Traffic",trafficPercentage:50,durationMinutes:5},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}],LINEAR_10:[{name:"Canary 10%",trafficPercentage:10,durationMinutes:5},{name:"Canary 20%",trafficPercentage:20,durationMinutes:5},{name:"Canary 30%",trafficPercentage:30,durationMinutes:5},{name:"Canary 40%",trafficPercentage:40,durationMinutes:5},{name:"Canary 50%",trafficPercentage:50,durationMinutes:5},{name:"Canary 60%",trafficPercentage:60,durationMinutes:5},{name:"Canary 70%",trafficPercentage:70,durationMinutes:5},{name:"Canary 80%",trafficPercentage:80,durationMinutes:5},{name:"Canary 90%",trafficPercentage:90,durationMinutes:5},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}]};createDeployment(a){let n=`canary-${Date.now()}-${this.deploymentCounter++}`,i={id:n,...a};return this.deployments.set(n,i),i}createLambdaCanaryDeployment(a){let n=a.strategy||"BALANCED",i=no.Strategies[n].map((s)=>({...s,alarmThresholds:{errorRate:a.errorRateThreshold||1,latencyP99:a.latencyThreshold||1000}}));return this.createDeployment({name:a.name,baselineVersion:{version:"baseline",functionVersionArn:a.baselineVersionArn,weight:100},canaryVersion:{version:"canary",functionVersionArn:a.canaryVersionArn,weight:0},stages:i,currentStage:0,status:"pending",autoPromote:a.autoPromote??!0,autoRollback:!0})}createECSCanaryDeployment(a){let n=a.strategy||"CONSERVATIVE",i=no.Strategies[n];return this.createDeployment({name:a.name,baselineVersion:{version:"baseline",taskDefinitionArn:a.baselineTaskDefinitionArn,targetGroupArn:a.baselineTargetGroupArn,weight:100},canaryVersion:{version:"canary",taskDefinitionArn:a.canaryTaskDefinitionArn,targetGroupArn:a.canaryTargetGroupArn,weight:0},stages:i,currentStage:0,status:"pending",autoRollback:!0})}async executeDeployment(a,n=!1){let i=this.deployments.get(a);if(!i)throw Error(`Deployment not found: ${a}`);let s={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,completedStages:0,rolledBack:!1};console.log(`${n?"[DRY RUN] ":""}Starting canary deployment: ${i.name}`),console.log(` Strategy: ${i.stages.length} stages`),console.log(` Auto-promote: ${i.autoPromote}`),console.log(` Auto-rollback: ${i.autoRollback}`),console.log(""),i.status="in_progress";for(let c=0;c<i.stages.length;c++){let l=i.stages[c];if(i.currentStage=c,console.log(`Stage ${c+1}/${i.stages.length}: ${l.name}`),console.log(` Traffic: ${l.trafficPercentage}% canary, ${100-l.trafficPercentage}% baseline`),console.log(` Duration: ${l.durationMinutes} minutes`),!n)i.baselineVersion.weight=100-l.trafficPercentage,i.canaryVersion.weight=l.trafficPercentage;if(!await this.monitorStage(i,l,n)){if(console.log(" ✗ Stage failed - metrics exceeded thresholds"),i.autoRollback)console.log("\\n Rolling back deployment..."),await this.rollback(a,n),s.rolledBack=!0,s.reason="Metrics exceeded thresholds";return s.endTime=new Date,i.status="rolled_back",this.recordDeployment(a,s),s}console.log(" ✓ Stage completed successfully"),s.completedStages++,console.log("")}return i.status="completed",s.success=!0,s.endTime=new Date,console.log("✓ Canary deployment completed successfully"),this.recordDeployment(a,s),s}async monitorStage(a,n,i){if(console.log(" Monitoring metrics..."),i)return console.log(" [SKIPPED - DRY RUN]"),!0;await new Promise((c)=>setTimeout(c,100));let s={baselineErrorRate:Math.random()*0.5,canaryErrorRate:Math.random()*0.8,baselineLatencyP99:200+Math.random()*100,canaryLatencyP99:180+Math.random()*150,baselineRequestCount:Math.floor(Math.random()*1000)+500,canaryRequestCount:Math.floor((Math.random()*1000+500)*n.trafficPercentage/100)};if(a.metrics=s,console.log(` Baseline: ${s.baselineErrorRate.toFixed(2)}% errors, ${s.baselineLatencyP99.toFixed(0)}ms P99`),console.log(` Canary: ${s.canaryErrorRate.toFixed(2)}% errors, ${s.canaryLatencyP99.toFixed(0)}ms P99`),n.alarmThresholds){let{errorRate:c,latencyP99:l}=n.alarmThresholds;if(c&&s.canaryErrorRate>c)return console.log(` ⚠ Error rate exceeded threshold: ${s.canaryErrorRate.toFixed(2)}% > ${c}%`),!1;if(l&&s.canaryLatencyP99>l)return console.log(` ⚠ Latency P99 exceeded threshold: ${s.canaryLatencyP99.toFixed(0)}ms > ${l}ms`),!1}return!0}async rollback(a,n=!1){let i=this.deployments.get(a);if(!i)throw Error(`Deployment not found: ${a}`);if(console.log(`${n?"[DRY RUN] ":""}Rolling back canary deployment: ${i.name}`),!n)i.baselineVersion.weight=100,i.canaryVersion.weight=0,i.status="rolled_back";console.log(" Traffic restored to baseline: 100%")}promoteCanary(a){let n=this.deployments.get(a);if(!n)throw Error(`Deployment not found: ${a}`);console.log(`Promoting canary to baseline: ${n.name}`);let i=n.baselineVersion;n.baselineVersion=n.canaryVersion,n.canaryVersion=i,n.baselineVersion.weight=100,n.canaryVersion.weight=0,n.status="completed",console.log(" Canary promoted successfully")}recordDeployment(a,n){if(!this.deploymentHistory.has(a))this.deploymentHistory.set(a,[]);this.deploymentHistory.get(a).push(n)}getDeployment(a){return this.deployments.get(a)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(a){return this.deploymentHistory.get(a)||[]}generateLambdaAliasCF(a,n){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:{Ref:"LambdaFunction"},Name:n,FunctionVersion:a.canaryVersion.version,RoutingConfig:{AdditionalVersionWeights:[{FunctionVersion:a.baselineVersion.version,FunctionWeight:a.baselineVersion.weight/100}]}}}}generateALBListenerRuleCF(a){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:[{TargetGroupArn:a.baselineVersion.targetGroupArn,Weight:a.baselineVersion.weight},{TargetGroupArn:a.canaryVersion.targetGroupArn,Weight:a.canaryVersion.weight}],TargetGroupStickinessConfig:{Enabled:!1}}}]}}}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var gC=new no;class gg{tests=new Map;testCounter=0;createTest(a){let n=`abtest-${Date.now()}-${this.testCounter++}`,i={id:n,...a};return this.tests.set(n,i),i}createSimpleABTest(a){let n=a.variantTrafficPercentage||50;return this.createTest({name:a.name,description:a.description,variants:[{id:"control",name:"Control",description:"Original version",trafficPercentage:100-n,targetGroupArn:a.controlTargetGroupArn,weight:100-n},{id:"variant-a",name:"Variant A",description:"Test version",trafficPercentage:n,targetGroupArn:a.variantTargetGroupArn,weight:n}],routingStrategy:{type:a.stickySession?"cookie":"random",cookieName:a.stickySession?"ab_variant":void 0,stickySession:a.stickySession??!1,sessionDuration:1440},startTime:new Date,status:"draft"})}createMultivariateTest(a){let n=a.variants.reduce((i,s)=>i+s.trafficPercentage,0);if(n!==100)throw Error(`Traffic percentages must sum to 100, got ${n}`);return this.createTest({name:a.name,description:a.description,variants:a.variants.map((i,s)=>({id:`variant-${s}`,name:i.name,description:i.description,trafficPercentage:i.trafficPercentage,targetGroupArn:i.targetGroupArn,weight:i.trafficPercentage})),routingStrategy:a.routingStrategy||{type:"random",stickySession:!1},startTime:new Date,status:"draft"})}createHeaderBasedTest(a){return this.createTest({name:a.name,description:`Route based on ${a.headerName} header`,variants:[{id:"control",name:"Control",trafficPercentage:50,targetGroupArn:a.controlTargetGroupArn,weight:50},{id:"variant-a",name:"Variant A",trafficPercentage:50,targetGroupArn:a.variantTargetGroupArn,weight:50}],routingStrategy:{type:"header",headerName:a.headerName,stickySession:!1},startTime:new Date,status:"draft"})}createGeoBasedTest(a){return this.createTest({name:a.name,description:"Route based on geographic location",variants:[{id:"control",name:"Control (Rest of World)",trafficPercentage:50,targetGroupArn:a.controlTargetGroupArn,weight:50},{id:"variant-a",name:`Variant A (${a.regions.join(", ")})`,trafficPercentage:50,targetGroupArn:a.variantTargetGroupArn,weight:50}],routingStrategy:{type:"geo",stickySession:!0,sessionDuration:1440},startTime:new Date,status:"draft"})}startTest(a){let n=this.tests.get(a);if(!n)throw Error(`Test not found: ${a}`);if(n.status!=="draft"&&n.status!=="paused")throw Error(`Cannot start test in ${n.status} status`);n.status="active",n.startTime=new Date,console.log(`Started A/B test: ${n.name}`),console.log(` Variants: ${n.variants.length}`),n.variants.forEach((i)=>{console.log(` - ${i.name}: ${i.trafficPercentage}%`)})}pauseTest(a){let n=this.tests.get(a);if(!n)throw Error(`Test not found: ${a}`);n.status="paused",console.log(`Paused A/B test: ${n.name}`)}updateTrafficSplit(a,n,i){let s=this.tests.get(a);if(!s)throw Error(`Test not found: ${a}`);let c=s.variants.find((u)=>u.id===n);if(!c)throw Error(`Variant not found: ${n}`);let l=c.trafficPercentage;c.trafficPercentage=i,c.weight=i,console.log(`Updated ${c.name} traffic: ${l}% → ${i}%`)}analyzeResults(a){let n=this.tests.get(a);if(!n)throw Error(`Test not found: ${a}`);if(!n.metrics)n.metrics=this.collectMetrics(n);let i=n.variants[0],s=0;for(let S of n.variants){let b=n.metrics.variants[S.id];if(b&&b.conversionRate>s)s=b.conversionRate,i=S}let c=n.metrics.variants.control||n.metrics.variants[n.variants[0].id],l=n.metrics.variants[i.id],u=(l.conversionRate-c.conversionRate)/c.conversionRate*100,h=100,y=l.requests>h&&c.requests>h&&Math.abs(u)>10;return{testId:a,winningVariant:i.name,confidence:y?95:75,improvement:u,statisticalSignificance:y,metrics:n.metrics,recommendation:this.generateRecommendation(u,y,i.name)}}declareWinner(a,n){let i=this.tests.get(a);if(!i)throw Error(`Test not found: ${a}`);let s=i.variants.find((c)=>c.id===n);if(!s)throw Error(`Variant not found: ${n}`);i.variants.forEach((c)=>{if(c.id===n)c.trafficPercentage=100,c.weight=100;else c.trafficPercentage=0,c.weight=0}),i.status="completed",i.endTime=new Date,i.winner=n,console.log(`Declared winner: ${s.name}`),console.log(` All traffic now routed to ${s.name}`)}collectMetrics(a){let n={},i=0;for(let s of a.variants){let c=Math.floor(Math.random()*1000)+500,l=Math.floor(c*(Math.random()*0.1+0.05)),u=l/c*100;n[s.id]={requests:c,conversions:l,conversionRate:u,averageLatency:150+Math.random()*100,errorRate:Math.random()*0.5,revenue:l*(Math.random()*50+100)},i+=c}return{variants:n,totalRequests:i,startTime:a.startTime,lastUpdated:new Date}}generateRecommendation(a,n,i){if(!n)return"Continue test - sample size too small or no significant difference detected";if(a>20)return`Strong winner detected - ${i} shows ${a.toFixed(1)}% improvement. Recommend deploying to all traffic.`;if(a>10)return`Moderate improvement - ${i} shows ${a.toFixed(1)}% improvement. Consider deploying.`;if(a>0)return`Minor improvement - ${i} shows ${a.toFixed(1)}% improvement. May not be worth the complexity.`;return"No improvement detected - consider reverting to control variant"}getTest(a){return this.tests.get(a)}listTests(){return Array.from(this.tests.values())}generateALBListenerRuleCF(a){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:a.variants.map((n)=>({TargetGroupArn:n.targetGroupArn,Weight:n.weight})),TargetGroupStickinessConfig:{Enabled:a.routingStrategy.stickySession||!1,DurationSeconds:a.routingStrategy.sessionDuration?a.routingStrategy.sessionDuration*60:void 0}}}]}}}generateLambdaEdgeFunction(a){return`'use strict';
3600
+ `}class ag{backupPlans=new Map;backupVaults=new Map;restoreJobs=new Map;continuousBackups=new Map;planCounter=0;restoreCounter=0;continuousBackupCounter=0;createVault(a){this.backupVaults.set(a.name,a)}getVault(a){return this.backupVaults.get(a)}createBackupPlan(a){let n=`backup-plan-${Date.now()}-${this.planCounter++}`,i={id:n,...a};return this.backupPlans.set(n,i),i}getBackupPlan(a){return this.backupPlans.get(a)}listBackupPlans(){return Array.from(this.backupPlans.values())}createRDSBackupPlan(a){let{dbInstanceArn:n,schedule:i="0 2 * * *",retentionDays:s=7,vaultName:c="default-vault"}=a;return this.createBackupPlan({name:"RDS Daily Backup",schedule:i,retentionDays:s,vaultName:c,resources:[{resourceArn:n,resourceType:"rds",region:"us-east-1"}],lifecycle:{moveTocoldStorageAfterDays:30,deleteAfterDays:s}})}createDynamoDBBackupPlan(a){let{tableArn:n,schedule:i="0 3 * * *",retentionDays:s=35,crossRegionCopy:c}=a;return this.createBackupPlan({name:"DynamoDB Daily Backup",schedule:i,retentionDays:s,vaultName:"dynamodb-vault",resources:[{resourceArn:n,resourceType:"dynamodb",region:"us-east-1"}],lifecycle:{deleteAfterDays:s},tags:c?{CrossRegionCopy:c.join(",")}:void 0})}createEFSBackupPlan(a){let{fileSystemArn:n,schedule:i="0 1 * * *",retentionDays:s=30}=a;return this.createBackupPlan({name:"EFS Daily Backup",schedule:i,retentionDays:s,vaultName:"efs-vault",resources:[{resourceArn:n,resourceType:"efs",region:"us-east-1"}],lifecycle:{deleteAfterDays:s}})}enableContinuousBackup(a,n=35){let i=`continuous-backup-${Date.now()}-${this.continuousBackupCounter++}`,s={id:i,resourceId:a,enabled:!0,retentionDays:n};return this.continuousBackups.set(i,s),s}getContinuousBackup(a){return this.continuousBackups.get(a)}enablePointInTimeRecovery(a,n){return{enabled:!0,earliestRestorableTime:new Date(Date.now()-604800000),latestRestorableTime:new Date}}async restoreFromBackup(a){let{backupId:n,resourceType:i,targetRegion:s}=a,c={id:`restore-${Date.now()}-${this.restoreCounter++}`,backupId:n,resourceType:i,status:"pending",startTime:new Date,targetRegion:s};return this.restoreJobs.set(c.id,c),setTimeout(()=>{c.status="running"},100),setTimeout(()=>{c.status="completed",c.endTime=new Date},1000),c}async restoreToPointInTime(a){let{sourceResourceArn:n,targetResourceName:i,restoreTime:s,resourceType:c}=a,l={id:`pitr-${Date.now()}-${this.restoreCounter++}`,backupId:`pitr-${s.getTime()}`,resourceType:c,status:"pending",startTime:new Date};return this.restoreJobs.set(l.id,l),console.log(`Restoring ${c} from ${n} to ${i} at ${s.toISOString()}`),setTimeout(()=>{l.status="completed",l.endTime=new Date},2000),l}getRestoreJob(a){return this.restoreJobs.get(a)}listRestoreJobs(){return Array.from(this.restoreJobs.values())}setupCrossRegionReplication(a){let{sourceVault:n,sourceRegion:i,targetRegions:s}=a;console.log("Setting up cross-region replication:"),console.log(` Source: ${n} in ${i}`),console.log(` Targets: ${s.join(", ")}`)}generateBackupVaultCF(a){return{Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:a.name,...a.encryptionKeyArn&&{EncryptionKeyArn:a.encryptionKeyArn},...a.accessPolicy&&{AccessPolicy:a.accessPolicy}}}}generateBackupPlanCF(a){return{Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:a.name,BackupPlanRule:[{RuleName:"DailyBackup",TargetBackupVault:a.vaultName,ScheduleExpression:`cron(${a.schedule})`,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:a.lifecycle?{...a.lifecycle.moveTocoldStorageAfterDays&&{MoveToColdStorageAfterDays:a.lifecycle.moveTocoldStorageAfterDays},...a.lifecycle.deleteAfterDays&&{DeleteAfterDays:a.lifecycle.deleteAfterDays}}:void 0}]},...a.tags&&{BackupPlanTags:a.tags}}}}generateBackupSelectionCF(a){return{Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:{Ref:`BackupPlan${a.id}`},BackupSelection:{SelectionName:`${a.name}Selection`,IamRoleArn:"arn:aws:iam::123456789012:role/service-role/AWSBackupDefaultServiceRole",Resources:a.resources.map((n)=>n.resourceArn)}}}}clear(){this.backupPlans.clear(),this.backupVaults.clear(),this.restoreJobs.clear(),this.continuousBackups.clear(),this.planCounter=0,this.restoreCounter=0,this.continuousBackupCounter=0}}var oC=new ag;class cg{drPlans=new Map;failoverTests=new Map;planCounter=0;testCounter=0;createDRPlan(a){let n=`dr-plan-${Date.now()}-${this.planCounter++}`,i={id:n,...a};return this.drPlans.set(n,i),i}createRDSDRPlan(a){let{primaryDbArn:n,secondaryDbArn:i,primaryRegion:s,secondaryRegion:c,rto:l=60,rpo:u=5}=a;return this.createDRPlan({name:"RDS Multi-Region DR",primaryRegion:s,secondaryRegion:c,rto:l,rpo:u,resources:[{resourceId:"primary-db",resourceType:"rds",primaryArn:n,secondaryArn:i,replicationEnabled:!0}],runbook:this.generateRDSRunbook(s,c),testSchedule:"0 0 1 * *"})}createDynamoDBDRPlan(a){let{tableArn:n,regions:i,rto:s=15,rpo:c=1}=a;return this.createDRPlan({name:"DynamoDB Global Tables DR",primaryRegion:i[0],secondaryRegion:i[1],rto:s,rpo:c,resources:[{resourceId:"dynamodb-table",resourceType:"dynamodb",primaryArn:n,replicationEnabled:!0}],runbook:this.generateDynamoDBRunbook(i)})}generateRDSRunbook(a,n){return{estimatedDuration:60,requiredApprovals:["cto","engineering-lead"],steps:[{order:1,name:"Verify Primary Database Failure",description:"Confirm that the primary database is truly unavailable and not experiencing temporary issues",action:"aws rds describe-db-instances --region "+a,automatable:!0,estimatedDuration:2,rollbackable:!1},{order:2,name:"Check Replication Lag",description:"Verify that the read replica is up to date",action:"Check ReplicaLag metric in CloudWatch",automatable:!0,estimatedDuration:1,rollbackable:!1},{order:3,name:"Promote Read Replica",description:"Promote the read replica in the secondary region to be the new primary",action:"aws rds promote-read-replica --db-instance-identifier replica --region "+n,automatable:!0,estimatedDuration:10,rollbackable:!1},{order:4,name:"Update DNS Records",description:"Update Route53 records to point to the new primary database",action:"Update Route53 failover record set",automatable:!0,estimatedDuration:5,rollbackable:!0},{order:5,name:"Update Application Configuration",description:"Update application connection strings if needed",action:"Deploy configuration update to ECS/Lambda",automatable:!0,estimatedDuration:10,rollbackable:!0},{order:6,name:"Verify Application Connectivity",description:"Test that applications can connect to the new primary",action:"Run smoke tests",automatable:!0,estimatedDuration:5,rollbackable:!1},{order:7,name:"Monitor for Issues",description:"Monitor CloudWatch metrics and application logs",action:"Monitor for 30 minutes",automatable:!1,estimatedDuration:30,rollbackable:!1}]}}generateDynamoDBRunbook(a){return{estimatedDuration:15,steps:[{order:1,name:"Verify Primary Region Failure",description:"Confirm that the primary region is experiencing an outage",action:"Check AWS Health Dashboard",automatable:!0,estimatedDuration:2,rollbackable:!1},{order:2,name:"Update Route53 Failover",description:"Update Route53 to direct traffic to secondary region",action:"Update Route53 health check and failover records",automatable:!0,estimatedDuration:5,rollbackable:!0},{order:3,name:"Update Application Endpoints",description:"Update Lambda/ECS to use secondary region DynamoDB endpoint",action:"Deploy configuration update",automatable:!0,estimatedDuration:5,rollbackable:!0},{order:4,name:"Verify Data Consistency",description:"Verify that data is consistent in secondary region",action:"Run data validation queries",automatable:!0,estimatedDuration:3,rollbackable:!1}]}}async executeFailover(a,n=!1){let i=this.drPlans.get(a);if(!i)throw Error(`DR plan not found: ${a}`);let s=Date.now(),c=0;console.log(`${n?"[DRY RUN] ":""}Executing failover for plan: ${i.name}`),console.log(`Primary: ${i.primaryRegion} -> Secondary: ${i.secondaryRegion}`),console.log(`RTO: ${i.rto} minutes, RPO: ${i.rpo} minutes`),console.log("");for(let l of i.runbook.steps){if(console.log(`Step ${l.order}: ${l.name}`),console.log(` ${l.description}`),console.log(` Action: ${l.action}`),console.log(` Estimated: ${l.estimatedDuration} minutes`),n)console.log(" [SKIPPED - DRY RUN]");else if(l.automatable)console.log(" [AUTOMATED]");else console.log(" [MANUAL - WAITING]");c++,console.log("")}return{success:!0,duration:(Date.now()-s)/1000/60,completedSteps:c}}scheduleFailoverTest(a,n){let i={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:a,status:"scheduled",startTime:n};return this.failoverTests.set(i.id,i),i}async runFailoverTest(a){let n=this.drPlans.get(a);if(!n)throw Error(`DR plan not found: ${a}`);let i={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:a,status:"running",startTime:new Date,results:[]};this.failoverTests.set(i.id,i),console.log(`Running failover test for plan: ${n.name}`),console.log("This is a non-destructive test using test resources"),console.log("");for(let s of n.runbook.steps){let c=Date.now();console.log(`Testing step ${s.order}: ${s.name}`);let l={step:s.name,status:"success",duration:(Date.now()-c)/1000,message:`Successfully validated step ${s.order}`};i.results.push(l)}return i.status="completed",i.endTime=new Date,i}getDRPlan(a){return this.drPlans.get(a)}listDRPlans(){return Array.from(this.drPlans.values())}getFailoverTest(a){return this.failoverTests.get(a)}listFailoverTests(){return Array.from(this.failoverTests.values())}validateDRPlan(a){let n=[],i=[];if(a.rto<a.rpo)i.push("RTO cannot be less than RPO");if(a.rto>240)n.push("RTO exceeds 4 hours - consider improving recovery time");if(a.rpo>60)n.push("RPO exceeds 1 hour - consider more frequent backups");if(a.resources.length===0)i.push("No resources defined in DR plan");for(let l of a.resources){if(!l.replicationEnabled)n.push(`Resource ${l.resourceId} does not have replication enabled`);if(!l.secondaryArn&&l.resourceType!=="dynamodb")n.push(`Resource ${l.resourceId} does not have secondary resource defined`)}if(a.runbook.steps.length===0)i.push("No recovery steps defined in runbook");let s=a.runbook.steps.reduce((l,u)=>l+u.estimatedDuration,0);if(s>a.rto)n.push(`Estimated recovery duration (${s}m) exceeds RTO (${a.rto}m)`);let c=a.runbook.steps.filter((l)=>!l.automatable);if(c.length>0)n.push(`${c.length} manual steps in runbook - consider automation`);return{valid:i.length===0,warnings:n,errors:i}}clear(){this.drPlans.clear(),this.failoverTests.clear(),this.planCounter=0,this.testCounter=0}}var aC=new cg;class dg{configRules=new Map;configRecorders=new Map;deliveryChannels=new Map;ruleCounter=0;createConfigRecorder(a){return this.configRecorders.set(a.name,a),a}createDeliveryChannel(a){return this.deliveryChannels.set(a.name,a),a}createConfigRule(a){let n=`config-rule-${Date.now()}-${this.ruleCounter++}`,i={id:n,...a};return this.configRules.set(n,i),i}createS3EncryptionRule(){return this.createConfigRule({name:"s3-bucket-server-side-encryption-enabled",description:"Checks that S3 buckets have server-side encryption enabled",source:"AWS_MANAGED",identifier:"S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED",scope:{complianceResourceTypes:["AWS::S3::Bucket"]}})}createS3PublicAccessBlockRule(){return this.createConfigRule({name:"s3-bucket-public-read-prohibited",description:"Checks that S3 buckets do not allow public read access",source:"AWS_MANAGED",identifier:"S3_BUCKET_PUBLIC_READ_PROHIBITED",scope:{complianceResourceTypes:["AWS::S3::Bucket"]}})}createS3VersioningRule(){return this.createConfigRule({name:"s3-bucket-versioning-enabled",description:"Checks whether versioning is enabled for S3 buckets",source:"AWS_MANAGED",identifier:"S3_BUCKET_VERSIONING_ENABLED",scope:{complianceResourceTypes:["AWS::S3::Bucket"]}})}createRdsEncryptionRule(){return this.createConfigRule({name:"rds-storage-encrypted",description:"Checks whether storage encryption is enabled for RDS DB instances",source:"AWS_MANAGED",identifier:"RDS_STORAGE_ENCRYPTED",scope:{complianceResourceTypes:["AWS::RDS::DBInstance"]}})}createRdsSnapshotEncryptionRule(){return this.createConfigRule({name:"rds-snapshots-public-prohibited",description:"Checks if RDS snapshots are public",source:"AWS_MANAGED",identifier:"RDS_SNAPSHOTS_PUBLIC_PROHIBITED",scope:{complianceResourceTypes:["AWS::RDS::DBSnapshot","AWS::RDS::DBClusterSnapshot"]}})}createRdsBackupRule(a=7){return this.createConfigRule({name:"db-backup-enabled",description:"Checks whether RDS DB instances have backups enabled",source:"AWS_MANAGED",identifier:"DB_BACKUP_ENABLED",inputParameters:{backupRetentionPeriod:a},scope:{complianceResourceTypes:["AWS::RDS::DBInstance"]}})}createEc2InstanceProfileRule(){return this.createConfigRule({name:"ec2-instance-managed-by-systems-manager",description:"Checks if EC2 instances are managed by Systems Manager",source:"AWS_MANAGED",identifier:"EC2_INSTANCE_MANAGED_BY_SSM",scope:{complianceResourceTypes:["AWS::EC2::Instance"]}})}createEbsEncryptionRule(){return this.createConfigRule({name:"encrypted-volumes",description:"Checks whether EBS volumes are encrypted",source:"AWS_MANAGED",identifier:"ENCRYPTED_VOLUMES",scope:{complianceResourceTypes:["AWS::EC2::Volume"]}})}createIamPasswordPolicyRule(){return this.createConfigRule({name:"iam-password-policy",description:"Checks whether the IAM password policy meets specified requirements",source:"AWS_MANAGED",identifier:"IAM_PASSWORD_POLICY",inputParameters:{RequireUppercaseCharacters:!0,RequireLowercaseCharacters:!0,RequireSymbols:!0,RequireNumbers:!0,MinimumPasswordLength:14,PasswordReusePrevention:24,MaxPasswordAge:90}})}createIamMfaRule(){return this.createConfigRule({name:"iam-user-mfa-enabled",description:"Checks whether IAM users have MFA enabled",source:"AWS_MANAGED",identifier:"IAM_USER_MFA_ENABLED"})}createRootAccountMfaRule(){return this.createConfigRule({name:"root-account-mfa-enabled",description:"Checks whether the root account has MFA enabled",source:"AWS_MANAGED",identifier:"ROOT_ACCOUNT_MFA_ENABLED"})}createVpcFlowLogsRule(){return this.createConfigRule({name:"vpc-flow-logs-enabled",description:"Checks whether VPC Flow Logs is enabled",source:"AWS_MANAGED",identifier:"VPC_FLOW_LOGS_ENABLED",scope:{complianceResourceTypes:["AWS::EC2::VPC"]}})}createCloudTrailEnabledRule(){return this.createConfigRule({name:"cloudtrail-enabled",description:"Checks whether CloudTrail is enabled",source:"AWS_MANAGED",identifier:"CLOUD_TRAIL_ENABLED",maxExecutionFrequency:"TwentyFour_Hours"})}createCloudWatchAlarmRule(){return this.createConfigRule({name:"cloudwatch-alarm-action-check",description:"Checks whether CloudWatch alarms have actions configured",source:"AWS_MANAGED",identifier:"CLOUDWATCH_ALARM_ACTION_CHECK",inputParameters:{alarmActionRequired:!0,insufficientDataActionRequired:!1,okActionRequired:!1},scope:{complianceResourceTypes:["AWS::CloudWatch::Alarm"]}})}createCustomLambdaRule(a){return this.createConfigRule({name:a.name,description:a.description,source:"CUSTOM_LAMBDA",lambdaFunctionArn:a.lambdaFunctionArn,scope:a.resourceTypes?{complianceResourceTypes:a.resourceTypes}:void 0,maxExecutionFrequency:a.maxExecutionFrequency,inputParameters:a.inputParameters})}createCompliancePreset(a){let n=[];switch(a){case"hipaa":n.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createRdsBackupRule(7),this.createVpcFlowLogsRule());break;case"pci-dss":n.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createIamMfaRule(),this.createRootAccountMfaRule(),this.createVpcFlowLogsRule());break;case"sox":n.push(this.createS3VersioningRule(),this.createCloudTrailEnabledRule(),this.createRdsBackupRule(30),this.createIamPasswordPolicyRule());break;case"gdpr":n.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createRdsSnapshotEncryptionRule());break;case"basic":n.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamMfaRule(),this.createRootAccountMfaRule());break}return n}getConfigRule(a){return this.configRules.get(a)}listConfigRules(){return Array.from(this.configRules.values())}getConfigRecorder(a){return this.configRecorders.get(a)}listConfigRecorders(){return Array.from(this.configRecorders.values())}getDeliveryChannel(a){return this.deliveryChannels.get(a)}listDeliveryChannels(){return Array.from(this.deliveryChannels.values())}generateConfigRuleCF(a){let n={Type:"AWS::Config::ConfigRule",Properties:{ConfigRuleName:a.name,Description:a.description,Source:{Owner:a.source==="AWS_MANAGED"?"AWS":"CUSTOM_LAMBDA"}}};if(a.source==="AWS_MANAGED"&&a.identifier)n.Properties.Source.SourceIdentifier=a.identifier;if(a.source==="CUSTOM_LAMBDA"&&a.lambdaFunctionArn)n.Properties.Source.SourceIdentifier=a.lambdaFunctionArn,n.Properties.Source.SourceDetails=[{EventSource:"aws.config",MessageType:"ConfigurationItemChangeNotification"}];if(a.inputParameters)n.Properties.InputParameters=JSON.stringify(a.inputParameters);if(a.scope){if(n.Properties.Scope={},a.scope.complianceResourceTypes)n.Properties.Scope.ComplianceResourceTypes=a.scope.complianceResourceTypes;if(a.scope.tagKey)n.Properties.Scope.TagKey=a.scope.tagKey;if(a.scope.tagValue)n.Properties.Scope.TagValue=a.scope.tagValue}if(a.maxExecutionFrequency)n.Properties.MaximumExecutionFrequency=a.maxExecutionFrequency;return n}generateConfigRecorderCF(a){return{Type:"AWS::Config::ConfigurationRecorder",Properties:{Name:a.name,RoleArn:a.roleArn,RecordingGroup:a.recordingGroup||{AllSupported:!0,IncludeGlobalResourceTypes:!0}}}}generateDeliveryChannelCF(a){return{Type:"AWS::Config::DeliveryChannel",Properties:{Name:a.name,S3BucketName:a.s3BucketName,...a.s3KeyPrefix&&{S3KeyPrefix:a.s3KeyPrefix},...a.snsTopicArn&&{SnsTopicARN:a.snsTopicArn},...a.configSnapshotDeliveryProperties&&{ConfigSnapshotDeliveryProperties:a.configSnapshotDeliveryProperties}}}}clear(){this.configRules.clear(),this.configRecorders.clear(),this.deliveryChannels.clear(),this.ruleCounter=0}}var cC=new dg;class lg{trails=new Map;trailCounter=0;createTrail(a){let n=`trail-${Date.now()}-${this.trailCounter++}`,i={id:n,...a};return this.trails.set(n,i),i}createOrganizationTrail(a){return this.createTrail({name:a.name,s3BucketName:a.s3BucketName,s3KeyPrefix:"organization-trail",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:a.kmsKeyId,cloudWatchLogsLogGroupArn:a.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:a.cloudWatchLogsRoleArn})}createSecurityAuditTrail(a){return this.createTrail({name:a.name,s3BucketName:a.s3BucketName,s3KeyPrefix:"security-audit",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:a.kmsKeyId,cloudWatchLogsLogGroupArn:a.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:a.cloudWatchLogsRoleArn,eventSelectors:[{readWriteType:"All",includeManagementEvents:!0,excludeManagementEventSources:[]}],insightSelectors:[{insightType:"ApiCallRateInsight"},{insightType:"ApiErrorRateInsight"}]})}createDataEventsTrail(a){let n=[];if(a.s3DataBuckets&&a.s3DataBuckets.length>0)n.push({type:"AWS::S3::Object",values:a.s3DataBuckets.map((i)=>`arn:aws:s3:::${i}/*`)});if(a.lambdaFunctions&&a.lambdaFunctions.length>0)n.push({type:"AWS::Lambda::Function",values:a.lambdaFunctions});return this.createTrail({name:a.name,s3BucketName:a.s3BucketName,s3KeyPrefix:"data-events",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"All",includeManagementEvents:!1,dataResources:n}]})}createAdvancedTrail(a){return this.createTrail({name:a.name,s3BucketName:a.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,advancedEventSelectors:a.selectors})}createReadOnlyTrail(a){return this.createTrail({name:a.name,s3BucketName:a.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"ReadOnly",includeManagementEvents:!0}]})}createWriteOnlyTrail(a){return this.createTrail({name:a.name,s3BucketName:a.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"WriteOnly",includeManagementEvents:!0}]})}getTrail(a){return this.trails.get(a)}listTrails(){return Array.from(this.trails.values())}generateTrailCF(a){let n={Type:"AWS::CloudTrail::Trail",Properties:{TrailName:a.name,S3BucketName:a.s3BucketName,IsLogging:!0,IncludeGlobalServiceEvents:a.includeGlobalServiceEvents??!0,IsMultiRegionTrail:a.isMultiRegionTrail??!0,EnableLogFileValidation:a.enableLogFileValidation??!0}};if(a.s3KeyPrefix)n.Properties.S3KeyPrefix=a.s3KeyPrefix;if(a.cloudWatchLogsLogGroupArn)n.Properties.CloudWatchLogsLogGroupArn=a.cloudWatchLogsLogGroupArn;if(a.cloudWatchLogsRoleArn)n.Properties.CloudWatchLogsRoleArn=a.cloudWatchLogsRoleArn;if(a.snsTopicName)n.Properties.SnsTopicName=a.snsTopicName;if(a.kmsKeyId)n.Properties.KMSKeyId=a.kmsKeyId;if(a.eventSelectors)n.Properties.EventSelectors=a.eventSelectors.map((i)=>({ReadWriteType:i.readWriteType,IncludeManagementEvents:i.includeManagementEvents??!0,...i.dataResources&&{DataResources:i.dataResources.map((s)=>({Type:s.type,Values:s.values}))},...i.excludeManagementEventSources&&{ExcludeManagementEventSources:i.excludeManagementEventSources}}));if(a.insightSelectors)n.Properties.InsightSelectors=a.insightSelectors.map((i)=>({InsightType:i.insightType}));if(a.advancedEventSelectors)n.Properties.AdvancedEventSelectors=a.advancedEventSelectors.map((i)=>({Name:i.name,FieldSelectors:i.fieldSelectors.map((s)=>({Field:s.field,...s.equals&&{Equals:s.equals},...s.startsWith&&{StartsWith:s.startsWith},...s.endsWith&&{EndsWith:s.endsWith},...s.notEquals&&{NotEquals:s.notEquals},...s.notStartsWith&&{NotStartsWith:s.notStartsWith},...s.notEndsWith&&{NotEndsWith:s.notEndsWith}}))}));return n}generateBucketPolicy(a,n){return{Version:"2012-10-17",Statement:[{Sid:"AWSCloudTrailAclCheck",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:GetBucketAcl",Resource:`arn:aws:s3:::${a}`},{Sid:"AWSCloudTrailWrite",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:PutObject",Resource:n.map((i)=>`arn:aws:s3:::${a}/AWSLogs/${i}/*`),Condition:{StringEquals:{"s3:x-amz-acl":"bucket-owner-full-control"}}}]}}clear(){this.trails.clear(),this.trailCounter=0}}var dC=new lg;class ug{detectors=new Map;threatIntelSets=new Map;ipSets=new Map;filters=new Map;detectorCounter=0;threatIntelCounter=0;ipSetCounter=0;filterCounter=0;createDetector(a){let n=`detector-${Date.now()}-${this.detectorCounter++}`,i={id:n,...a};return this.detectors.set(n,i),i}createComprehensiveDetector(){return this.createDetector({enable:!0,findingPublishingFrequency:"FIFTEEN_MINUTES",dataSources:{s3Logs:{enable:!0},kubernetes:{auditLogs:{enable:!0}},malwareProtection:{scanEc2InstanceWithFindings:{ebsVolumes:{enable:!0}}}},features:[{name:"S3_DATA_EVENTS",status:"ENABLED"},{name:"EKS_AUDIT_LOGS",status:"ENABLED"},{name:"EBS_MALWARE_PROTECTION",status:"ENABLED"},{name:"RDS_LOGIN_EVENTS",status:"ENABLED"},{name:"LAMBDA_NETWORK_LOGS",status:"ENABLED"}]})}createBasicDetector(){return this.createDetector({enable:!0,findingPublishingFrequency:"SIX_HOURS"})}createThreatIntelSet(a){let n=`threat-intel-${Date.now()}-${this.threatIntelCounter++}`,i={id:n,...a};return this.threatIntelSets.set(n,i),i}createIPSet(a){let n=`ip-set-${Date.now()}-${this.ipSetCounter++}`,i={id:n,...a};return this.ipSets.set(n,i),i}createFindingFilter(a){let n=`filter-${Date.now()}-${this.filterCounter++}`,i={id:n,...a};return this.filters.set(n,i),i}createLowSeverityArchiveFilter(a){return this.createFindingFilter({detectorId:a,name:"archive-low-severity",description:"Automatically archive low severity findings",action:"ARCHIVE",rank:1,findingCriteria:{criterion:{severity:{lt:4}}}})}createFindingTypeFilter(a,n,i){return this.createFindingFilter({detectorId:a,name:`filter-finding-types-${i.toLowerCase()}`,description:`${i==="ARCHIVE"?"Archive":"Keep"} specific finding types`,action:i,rank:2,findingCriteria:{criterion:{type:{eq:n}}}})}createTrustedIPFilter(a,n){return this.createFindingFilter({detectorId:a,name:"trusted-ip-addresses",description:"Archive findings from trusted IP addresses",action:"ARCHIVE",rank:3,findingCriteria:{criterion:{"resource.instanceDetails.networkInterfaces.privateIpAddress":{eq:n}}}})}getDetector(a){return this.detectors.get(a)}listDetectors(){return Array.from(this.detectors.values())}getThreatIntelSet(a){return this.threatIntelSets.get(a)}listThreatIntelSets(){return Array.from(this.threatIntelSets.values())}getIPSet(a){return this.ipSets.get(a)}listIPSets(){return Array.from(this.ipSets.values())}getFindingFilter(a){return this.filters.get(a)}listFindingFilters(){return Array.from(this.filters.values())}generateDetectorCF(a){let n={Type:"AWS::GuardDuty::Detector",Properties:{Enable:a.enable}};if(a.findingPublishingFrequency)n.Properties.FindingPublishingFrequency=a.findingPublishingFrequency;if(a.dataSources){if(n.Properties.DataSources={},a.dataSources.s3Logs)n.Properties.DataSources.S3Logs={Enable:a.dataSources.s3Logs.enable};if(a.dataSources.kubernetes)n.Properties.DataSources.Kubernetes={AuditLogs:{Enable:a.dataSources.kubernetes.auditLogs.enable}};if(a.dataSources.malwareProtection)n.Properties.DataSources.MalwareProtection={ScanEc2InstanceWithFindings:{EbsVolumes:{Enable:a.dataSources.malwareProtection.scanEc2InstanceWithFindings.ebsVolumes.enable}}}}if(a.features)n.Properties.Features=a.features.map((i)=>({Name:i.name,Status:i.status,...i.additionalConfiguration&&{AdditionalConfiguration:i.additionalConfiguration}}));return n}generateThreatIntelSetCF(a){return{Type:"AWS::GuardDuty::ThreatIntelSet",Properties:{DetectorId:a.detectorId,Name:a.name,Format:a.format,Location:a.location,Activate:a.activate}}}generateIPSetCF(a){return{Type:"AWS::GuardDuty::IPSet",Properties:{DetectorId:a.detectorId,Name:a.name,Format:a.format,Location:a.location,Activate:a.activate}}}generateFilterCF(a){return{Type:"AWS::GuardDuty::Filter",Properties:{DetectorId:a.detectorId,Name:a.name,Description:a.description,Action:a.action,Rank:a.rank,FindingCriteria:{Criterion:a.findingCriteria.criterion}}}}clear(){this.detectors.clear(),this.threatIntelSets.clear(),this.ipSets.clear(),this.filters.clear(),this.detectorCounter=0,this.threatIntelCounter=0,this.ipSetCounter=0,this.filterCounter=0}}var lC=new ug;class Lr{hubs=new Map;hubCounter=0;ruleCounter=0;static Standards={AWS_FOUNDATIONAL_SECURITY:{arn:"arn:aws:securityhub:::ruleset/aws-foundational-security-best-practices/v/1.0.0",name:"AWS Foundational Security Best Practices",description:"AWS recommended security best practices"},CIS_AWS_FOUNDATIONS_1_2:{arn:"arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0",name:"CIS AWS Foundations Benchmark v1.2.0",description:"CIS AWS Foundations Benchmark v1.2.0"},CIS_AWS_FOUNDATIONS_1_4:{arn:"arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.4.0",name:"CIS AWS Foundations Benchmark v1.4.0",description:"CIS AWS Foundations Benchmark v1.4.0"},PCI_DSS:{arn:"arn:aws:securityhub:us-east-1::standards/pci-dss/v/3.2.1",name:"PCI DSS v3.2.1",description:"Payment Card Industry Data Security Standard"},NIST_800_53:{arn:"arn:aws:securityhub:us-east-1::standards/nist-800-53/v/5.0.0",name:"NIST SP 800-53 Rev. 5",description:"NIST Special Publication 800-53 Revision 5"}};createHub(a){let n=`hub-${Date.now()}-${this.hubCounter++}`,i={id:n,...a};return this.hubs.set(n,i),i}createComprehensiveHub(){return this.createHub({enable:!0,controlFindingGenerator:"SECURITY_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...Lr.Standards.AWS_FOUNDATIONAL_SECURITY,enabled:!0},{id:"cis-1-4",...Lr.Standards.CIS_AWS_FOUNDATIONS_1_4,enabled:!0},{id:"pci-dss",...Lr.Standards.PCI_DSS,enabled:!0}]})}createBasicHub(){return this.createHub({enable:!0,controlFindingGenerator:"STANDARD_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...Lr.Standards.AWS_FOUNDATIONAL_SECURITY,enabled:!0}]})}createLowSeveritySuppressionRule(){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:"Suppress Low Severity Informational Findings",description:"Automatically suppress informational findings",actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"SUPPRESSED"},note:{text:"Automatically suppressed low severity finding",updatedBy:"SecurityHub Automation"}}}],criteria:{severityLabel:[{value:"INFORMATIONAL",comparison:"EQUALS"}],recordState:[{value:"ACTIVE",comparison:"EQUALS"}]},ruleStatus:"ENABLED",ruleOrder:1}}createResourceTypeNotificationRule(a){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:"Notify on Critical Resource Findings",description:"Set findings for critical resources to NOTIFIED status",actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"NOTIFIED"},note:{text:"Critical resource finding requires attention",updatedBy:"SecurityHub Automation"}}}],criteria:{resourceType:a.map((n)=>({value:n,comparison:"EQUALS"})),severityLabel:[{value:"HIGH",comparison:"EQUALS"},{value:"CRITICAL",comparison:"EQUALS"}],workflowStatus:[{value:"NEW",comparison:"EQUALS"}]},ruleStatus:"ENABLED",ruleOrder:2}}createComplianceFailureRule(){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:"Flag Compliance Failures",description:"Increase severity for compliance failures",actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{severity:{label:"HIGH"},workflow:{status:"NOTIFIED"},note:{text:"Compliance failure detected - requires immediate attention",updatedBy:"SecurityHub Automation"}}}],criteria:{complianceStatus:[{value:"FAILED",comparison:"EQUALS"}],recordState:[{value:"ACTIVE",comparison:"EQUALS"}]},ruleStatus:"ENABLED",ruleOrder:3}}createFalsePositiveSuppressionRule(a,n){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:`Suppress False Positives - ${a}`,description:`Automatically suppress known false positives from ${a}`,actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"SUPPRESSED"},note:{text:"Known false positive - automatically suppressed",updatedBy:"SecurityHub Automation"}}}],criteria:{productName:[{value:a,comparison:"EQUALS"}],title:n.map((i)=>({value:i,comparison:"PREFIX"}))},ruleStatus:"ENABLED",ruleOrder:10}}getHub(a){return this.hubs.get(a)}listHubs(){return Array.from(this.hubs.values())}generateHubCF(a){let n={Type:"AWS::SecurityHub::Hub",Properties:{}};if(a.controlFindingGenerator)n.Properties.ControlFindingGenerator=a.controlFindingGenerator;if(a.enableDefaultStandards!==void 0)n.Properties.EnableDefaultStandards=a.enableDefaultStandards;return n}generateStandardCF(a){let n={Type:"AWS::SecurityHub::Standard",Properties:{StandardsArn:a.arn}};if(a.disabledControls&&a.disabledControls.length>0)n.Properties.DisabledStandardsControls=a.disabledControls.map((i)=>({StandardsControlArn:i,Reason:"Disabled by configuration"}));return n}generateAutomationRuleCF(a){return{Type:"AWS::SecurityHub::AutomationRule",Properties:{RuleName:a.ruleName,Description:a.description,Actions:a.actions.map((n)=>({Type:n.type,FindingFieldsUpdate:n.findingFieldsUpdate})),Criteria:a.criteria,RuleStatus:a.ruleStatus,RuleOrder:a.ruleOrder}}}clear(){this.hubs.clear(),this.hubCounter=0,this.ruleCounter=0}}var uC=new Lr;class pg{deployments=new Map;deploymentHistory=new Map;deploymentCounter=0;resultCounter=0;createDeployment(a){let n=`bg-deployment-${Date.now()}-${this.deploymentCounter++}`,i={id:n,...a};return this.deployments.set(n,i),i}createALBDeployment(a){return this.createDeployment({name:a.name,blueEnvironment:{name:"blue",targetGroupArn:a.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:a.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:a.listenerArn,switchoverTimeSeconds:0},autoPromote:a.autoPromote,healthCheckConfig:a.healthCheckConfig})}createRoute53Deployment(a){return this.createDeployment({name:a.name,blueEnvironment:{name:"blue",targetGroupArn:a.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:a.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"route53",hostedZoneId:a.hostedZoneId,switchoverTimeSeconds:a.switchoverTimeSeconds||60}})}createECSDeployment(a){return this.createDeployment({name:a.name,blueEnvironment:{name:"blue",targetGroupArn:a.blueTargetGroupArn,taskDefinitionArn:a.blueTaskDefinitionArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:a.greenTargetGroupArn,taskDefinitionArn:a.greenTaskDefinitionArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:a.listenerArn},autoRollback:a.autoRollback??!0})}async executeDeployment(a,n=!1){let i=this.deployments.get(a);if(!i)throw Error(`Deployment not found: ${a}`);let s={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!1,errors:[]};console.log(`${n?"[DRY RUN] ":""}Starting blue/green deployment: ${i.name}`),console.log(` Active environment: ${i.activeEnvironment}`),console.log(` Routing type: ${i.routingConfig.type}`);let c=i.activeEnvironment==="blue"?"green":"blue";if(console.log(` Switching to: ${c}`),console.log(`\\n1. Deploying to ${c} environment`),!n)await new Promise((l)=>setTimeout(l,100));if(console.log(`\\n2. Running health checks on ${c} environment`),i.healthCheckConfig){let l=await this.runHealthChecks(i,c,n);if(s.healthChecksPassed=l,!l){if(s.errors?.push("Health checks failed"),s.endTime=new Date,i.autoRollback)console.log(" Auto-rollback enabled - keeping current environment active"),s.rolledBackAt=new Date;return this.recordDeployment(a,s),s}}else s.healthChecksPassed=!0;if(console.log(`\\n3. Switching traffic to ${c} environment`),!n)i.activeEnvironment=c,s.switchedAt=new Date;if(console.log(`\\n4. Monitoring ${c} environment`),!n)await new Promise((l)=>setTimeout(l,100));return s.success=!0,s.endTime=new Date,console.log("\\n✓ Deployment completed successfully"),this.recordDeployment(a,s),s}async rollback(a){let n=this.deployments.get(a);if(!n)throw Error(`Deployment not found: ${a}`);let i={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!0,errors:[]};console.log(`Rolling back deployment: ${n.name}`);let s=n.activeEnvironment==="blue"?"green":"blue";return n.activeEnvironment=s,i.success=!0,i.rolledBackAt=new Date,i.endTime=new Date,console.log(` Switched back to: ${s}`),this.recordDeployment(a,i),i}async runHealthChecks(a,n,i){let s=a.healthCheckConfig;if(console.log(` Health check path: ${s.path||"/"}`),console.log(` Healthy threshold: ${s.healthyThreshold}`),console.log(` Interval: ${s.interval}s`),i)return console.log(" [SKIPPED - DRY RUN]"),!0;let c=0,l=s.healthyThreshold+2;for(let u=0;u<l;u++)if(await new Promise((h)=>setTimeout(h,50)),Math.random()>0.1){if(c++,console.log(` Check ${u+1}: ✓ Healthy (${c}/${s.healthyThreshold})`),c>=s.healthyThreshold)return!0}else c=0,console.log(` Check ${u+1}: ✗ Unhealthy`);return!1}recordDeployment(a,n){if(!this.deploymentHistory.has(a))this.deploymentHistory.set(a,[]);this.deploymentHistory.get(a).push(n)}getDeployment(a){return this.deployments.get(a)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(a){return this.deploymentHistory.get(a)||[]}generateALBListenerCF(a){let n=a.activeEnvironment==="blue"?a.blueEnvironment:a.greenEnvironment;return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:a.routingConfig.listenerArn,Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",TargetGroupArn:n.targetGroupArn}]}}}generateRoute53RecordSetCF(a,n){return[{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:a.routingConfig.hostedZoneId,Name:n,Type:"A",SetIdentifier:"blue",Weight:a.activeEnvironment==="blue"?100:0,AliasTarget:{HostedZoneId:a.routingConfig.hostedZoneId,DNSName:a.blueEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}},{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:a.routingConfig.hostedZoneId,Name:n,Type:"A",SetIdentifier:"green",Weight:a.activeEnvironment==="green"?100:0,AliasTarget:{HostedZoneId:a.routingConfig.hostedZoneId,DNSName:a.greenEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}}]}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var pC=new pg;class no{deployments=new Map;deploymentHistory=new Map;deploymentCounter=0;resultCounter=0;static Strategies={CONSERVATIVE:[{name:"Initial Canary",trafficPercentage:10,durationMinutes:10},{name:"Quarter Traffic",trafficPercentage:25,durationMinutes:10},{name:"Half Traffic",trafficPercentage:50,durationMinutes:15},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}],BALANCED:[{name:"Initial Canary",trafficPercentage:20,durationMinutes:5},{name:"Half Traffic",trafficPercentage:50,durationMinutes:10},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}],AGGRESSIVE:[{name:"Half Traffic",trafficPercentage:50,durationMinutes:5},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}],LINEAR_10:[{name:"Canary 10%",trafficPercentage:10,durationMinutes:5},{name:"Canary 20%",trafficPercentage:20,durationMinutes:5},{name:"Canary 30%",trafficPercentage:30,durationMinutes:5},{name:"Canary 40%",trafficPercentage:40,durationMinutes:5},{name:"Canary 50%",trafficPercentage:50,durationMinutes:5},{name:"Canary 60%",trafficPercentage:60,durationMinutes:5},{name:"Canary 70%",trafficPercentage:70,durationMinutes:5},{name:"Canary 80%",trafficPercentage:80,durationMinutes:5},{name:"Canary 90%",trafficPercentage:90,durationMinutes:5},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}]};createDeployment(a){let n=`canary-${Date.now()}-${this.deploymentCounter++}`,i={id:n,...a};return this.deployments.set(n,i),i}createLambdaCanaryDeployment(a){let n=a.strategy||"BALANCED",i=no.Strategies[n].map((s)=>({...s,alarmThresholds:{errorRate:a.errorRateThreshold||1,latencyP99:a.latencyThreshold||1000}}));return this.createDeployment({name:a.name,baselineVersion:{version:"baseline",functionVersionArn:a.baselineVersionArn,weight:100},canaryVersion:{version:"canary",functionVersionArn:a.canaryVersionArn,weight:0},stages:i,currentStage:0,status:"pending",autoPromote:a.autoPromote??!0,autoRollback:!0})}createECSCanaryDeployment(a){let n=a.strategy||"CONSERVATIVE",i=no.Strategies[n];return this.createDeployment({name:a.name,baselineVersion:{version:"baseline",taskDefinitionArn:a.baselineTaskDefinitionArn,targetGroupArn:a.baselineTargetGroupArn,weight:100},canaryVersion:{version:"canary",taskDefinitionArn:a.canaryTaskDefinitionArn,targetGroupArn:a.canaryTargetGroupArn,weight:0},stages:i,currentStage:0,status:"pending",autoRollback:!0})}async executeDeployment(a,n=!1){let i=this.deployments.get(a);if(!i)throw Error(`Deployment not found: ${a}`);let s={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,completedStages:0,rolledBack:!1};console.log(`${n?"[DRY RUN] ":""}Starting canary deployment: ${i.name}`),console.log(` Strategy: ${i.stages.length} stages`),console.log(` Auto-promote: ${i.autoPromote}`),console.log(` Auto-rollback: ${i.autoRollback}`),console.log(""),i.status="in_progress";for(let c=0;c<i.stages.length;c++){let l=i.stages[c];if(i.currentStage=c,console.log(`Stage ${c+1}/${i.stages.length}: ${l.name}`),console.log(` Traffic: ${l.trafficPercentage}% canary, ${100-l.trafficPercentage}% baseline`),console.log(` Duration: ${l.durationMinutes} minutes`),!n)i.baselineVersion.weight=100-l.trafficPercentage,i.canaryVersion.weight=l.trafficPercentage;if(!await this.monitorStage(i,l,n)){if(console.log(" ✗ Stage failed - metrics exceeded thresholds"),i.autoRollback)console.log("\\n Rolling back deployment..."),await this.rollback(a,n),s.rolledBack=!0,s.reason="Metrics exceeded thresholds";return s.endTime=new Date,i.status="rolled_back",this.recordDeployment(a,s),s}console.log(" ✓ Stage completed successfully"),s.completedStages++,console.log("")}return i.status="completed",s.success=!0,s.endTime=new Date,console.log("✓ Canary deployment completed successfully"),this.recordDeployment(a,s),s}async monitorStage(a,n,i){if(console.log(" Monitoring metrics..."),i)return console.log(" [SKIPPED - DRY RUN]"),!0;await new Promise((c)=>setTimeout(c,100));let s={baselineErrorRate:Math.random()*0.5,canaryErrorRate:Math.random()*0.8,baselineLatencyP99:200+Math.random()*100,canaryLatencyP99:180+Math.random()*150,baselineRequestCount:Math.floor(Math.random()*1000)+500,canaryRequestCount:Math.floor((Math.random()*1000+500)*n.trafficPercentage/100)};if(a.metrics=s,console.log(` Baseline: ${s.baselineErrorRate.toFixed(2)}% errors, ${s.baselineLatencyP99.toFixed(0)}ms P99`),console.log(` Canary: ${s.canaryErrorRate.toFixed(2)}% errors, ${s.canaryLatencyP99.toFixed(0)}ms P99`),n.alarmThresholds){let{errorRate:c,latencyP99:l}=n.alarmThresholds;if(c&&s.canaryErrorRate>c)return console.log(` ⚠ Error rate exceeded threshold: ${s.canaryErrorRate.toFixed(2)}% > ${c}%`),!1;if(l&&s.canaryLatencyP99>l)return console.log(` ⚠ Latency P99 exceeded threshold: ${s.canaryLatencyP99.toFixed(0)}ms > ${l}ms`),!1}return!0}async rollback(a,n=!1){let i=this.deployments.get(a);if(!i)throw Error(`Deployment not found: ${a}`);if(console.log(`${n?"[DRY RUN] ":""}Rolling back canary deployment: ${i.name}`),!n)i.baselineVersion.weight=100,i.canaryVersion.weight=0,i.status="rolled_back";console.log(" Traffic restored to baseline: 100%")}promoteCanary(a){let n=this.deployments.get(a);if(!n)throw Error(`Deployment not found: ${a}`);console.log(`Promoting canary to baseline: ${n.name}`);let i=n.baselineVersion;n.baselineVersion=n.canaryVersion,n.canaryVersion=i,n.baselineVersion.weight=100,n.canaryVersion.weight=0,n.status="completed",console.log(" Canary promoted successfully")}recordDeployment(a,n){if(!this.deploymentHistory.has(a))this.deploymentHistory.set(a,[]);this.deploymentHistory.get(a).push(n)}getDeployment(a){return this.deployments.get(a)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(a){return this.deploymentHistory.get(a)||[]}generateLambdaAliasCF(a,n){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:{Ref:"LambdaFunction"},Name:n,FunctionVersion:a.canaryVersion.version,RoutingConfig:{AdditionalVersionWeights:[{FunctionVersion:a.baselineVersion.version,FunctionWeight:a.baselineVersion.weight/100}]}}}}generateALBListenerRuleCF(a){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:[{TargetGroupArn:a.baselineVersion.targetGroupArn,Weight:a.baselineVersion.weight},{TargetGroupArn:a.canaryVersion.targetGroupArn,Weight:a.canaryVersion.weight}],TargetGroupStickinessConfig:{Enabled:!1}}}]}}}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var gC=new no;class gg{tests=new Map;testCounter=0;createTest(a){let n=`abtest-${Date.now()}-${this.testCounter++}`,i={id:n,...a};return this.tests.set(n,i),i}createSimpleABTest(a){let n=a.variantTrafficPercentage||50;return this.createTest({name:a.name,description:a.description,variants:[{id:"control",name:"Control",description:"Original version",trafficPercentage:100-n,targetGroupArn:a.controlTargetGroupArn,weight:100-n},{id:"variant-a",name:"Variant A",description:"Test version",trafficPercentage:n,targetGroupArn:a.variantTargetGroupArn,weight:n}],routingStrategy:{type:a.stickySession?"cookie":"random",cookieName:a.stickySession?"ab_variant":void 0,stickySession:a.stickySession??!1,sessionDuration:1440},startTime:new Date,status:"draft"})}createMultivariateTest(a){let n=a.variants.reduce((i,s)=>i+s.trafficPercentage,0);if(n!==100)throw Error(`Traffic percentages must sum to 100, got ${n}`);return this.createTest({name:a.name,description:a.description,variants:a.variants.map((i,s)=>({id:`variant-${s}`,name:i.name,description:i.description,trafficPercentage:i.trafficPercentage,targetGroupArn:i.targetGroupArn,weight:i.trafficPercentage})),routingStrategy:a.routingStrategy||{type:"random",stickySession:!1},startTime:new Date,status:"draft"})}createHeaderBasedTest(a){return this.createTest({name:a.name,description:`Route based on ${a.headerName} header`,variants:[{id:"control",name:"Control",trafficPercentage:50,targetGroupArn:a.controlTargetGroupArn,weight:50},{id:"variant-a",name:"Variant A",trafficPercentage:50,targetGroupArn:a.variantTargetGroupArn,weight:50}],routingStrategy:{type:"header",headerName:a.headerName,stickySession:!1},startTime:new Date,status:"draft"})}createGeoBasedTest(a){return this.createTest({name:a.name,description:"Route based on geographic location",variants:[{id:"control",name:"Control (Rest of World)",trafficPercentage:50,targetGroupArn:a.controlTargetGroupArn,weight:50},{id:"variant-a",name:`Variant A (${a.regions.join(", ")})`,trafficPercentage:50,targetGroupArn:a.variantTargetGroupArn,weight:50}],routingStrategy:{type:"geo",stickySession:!0,sessionDuration:1440},startTime:new Date,status:"draft"})}startTest(a){let n=this.tests.get(a);if(!n)throw Error(`Test not found: ${a}`);if(n.status!=="draft"&&n.status!=="paused")throw Error(`Cannot start test in ${n.status} status`);n.status="active",n.startTime=new Date,console.log(`Started A/B test: ${n.name}`),console.log(` Variants: ${n.variants.length}`),n.variants.forEach((i)=>{console.log(` - ${i.name}: ${i.trafficPercentage}%`)})}pauseTest(a){let n=this.tests.get(a);if(!n)throw Error(`Test not found: ${a}`);n.status="paused",console.log(`Paused A/B test: ${n.name}`)}updateTrafficSplit(a,n,i){let s=this.tests.get(a);if(!s)throw Error(`Test not found: ${a}`);let c=s.variants.find((u)=>u.id===n);if(!c)throw Error(`Variant not found: ${n}`);let l=c.trafficPercentage;c.trafficPercentage=i,c.weight=i,console.log(`Updated ${c.name} traffic: ${l}% → ${i}%`)}analyzeResults(a){let n=this.tests.get(a);if(!n)throw Error(`Test not found: ${a}`);if(!n.metrics)n.metrics=this.collectMetrics(n);let i=n.variants[0],s=0;for(let S of n.variants){let A=n.metrics.variants[S.id];if(A&&A.conversionRate>s)s=A.conversionRate,i=S}let c=n.metrics.variants.control||n.metrics.variants[n.variants[0].id],l=n.metrics.variants[i.id],u=(l.conversionRate-c.conversionRate)/c.conversionRate*100,h=100,y=l.requests>h&&c.requests>h&&Math.abs(u)>10;return{testId:a,winningVariant:i.name,confidence:y?95:75,improvement:u,statisticalSignificance:y,metrics:n.metrics,recommendation:this.generateRecommendation(u,y,i.name)}}declareWinner(a,n){let i=this.tests.get(a);if(!i)throw Error(`Test not found: ${a}`);let s=i.variants.find((c)=>c.id===n);if(!s)throw Error(`Variant not found: ${n}`);i.variants.forEach((c)=>{if(c.id===n)c.trafficPercentage=100,c.weight=100;else c.trafficPercentage=0,c.weight=0}),i.status="completed",i.endTime=new Date,i.winner=n,console.log(`Declared winner: ${s.name}`),console.log(` All traffic now routed to ${s.name}`)}collectMetrics(a){let n={},i=0;for(let s of a.variants){let c=Math.floor(Math.random()*1000)+500,l=Math.floor(c*(Math.random()*0.1+0.05)),u=l/c*100;n[s.id]={requests:c,conversions:l,conversionRate:u,averageLatency:150+Math.random()*100,errorRate:Math.random()*0.5,revenue:l*(Math.random()*50+100)},i+=c}return{variants:n,totalRequests:i,startTime:a.startTime,lastUpdated:new Date}}generateRecommendation(a,n,i){if(!n)return"Continue test - sample size too small or no significant difference detected";if(a>20)return`Strong winner detected - ${i} shows ${a.toFixed(1)}% improvement. Recommend deploying to all traffic.`;if(a>10)return`Moderate improvement - ${i} shows ${a.toFixed(1)}% improvement. Consider deploying.`;if(a>0)return`Minor improvement - ${i} shows ${a.toFixed(1)}% improvement. May not be worth the complexity.`;return"No improvement detected - consider reverting to control variant"}getTest(a){return this.tests.get(a)}listTests(){return Array.from(this.tests.values())}generateALBListenerRuleCF(a){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:a.variants.map((n)=>({TargetGroupArn:n.targetGroupArn,Weight:n.weight})),TargetGroupStickinessConfig:{Enabled:a.routingStrategy.stickySession||!1,DurationSeconds:a.routingStrategy.sessionDuration?a.routingStrategy.sessionDuration*60:void 0}}}]}}}generateLambdaEdgeFunction(a){return`'use strict';
3601
3601
 
3602
3602
  exports.handler = (event, _context, _callback) => {
3603
3603
  const request = event.Records[0].cf.request;
@@ -3757,12 +3757,12 @@ exports.handler = async () => {
3757
3757
  2. Promoting replica to standalone instance...`),console.log(`
3758
3758
  3. Updating DNS records...`),console.log(`
3759
3759
  4. Updating application configuration...`),console.log(`
3760
- ✓ Promotion completed successfully`),n.status="available",{success:!0,message:"Replica promoted successfully"}}getReplicationLag(a){if(!this.replicas.get(a))throw Error(`Replica not found: ${a}`);return Math.floor(Math.random()*1000)}getReplica(a){return this.replicas.get(a)}listReplicas(){return Array.from(this.replicas.values())}getReplicationGroup(a){return this.replicationGroups.get(a)}listReplicationGroups(){return Array.from(this.replicationGroups.values())}getProxy(a){return this.proxies.get(a)}listProxies(){return Array.from(this.proxies.values())}generateReplicaCF(a){return{Type:"AWS::RDS::DBInstance",Properties:{SourceDBInstanceIdentifier:a.sourceDatabase,DBInstanceIdentifier:a.name,DBInstanceClass:a.instanceClass,MultiAZ:a.multiAZ||!1,AutoMinorVersionUpgrade:a.autoMinorVersionUpgrade??!0,...a.backupRetentionPeriod&&{BackupRetentionPeriod:a.backupRetentionPeriod},...a.preferredBackupWindow&&{PreferredBackupWindow:a.preferredBackupWindow},...a.preferredMaintenanceWindow&&{PreferredMaintenanceWindow:a.preferredMaintenanceWindow}}}}generateProxyCF(a){return{Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:a.name,EngineFamily:a.engineFamily,Auth:[{AuthScheme:"SECRETS",SecretArn:a.secretArn,IAMAuth:"DISABLED"}],RoleArn:{"Fn::GetAtt":["RDSProxyRole","Arn"]},VpcSubnetIds:a.vpcSubnetIds,VpcSecurityGroupIds:a.securityGroupIds,RequireTLS:a.requireTLS??!0,IdleClientTimeout:a.idleClientTimeout||1800,...a.maxConnectionsPercent&&{MaxConnectionsPercent:a.maxConnectionsPercent},...a.maxIdleConnectionsPercent&&{MaxIdleConnectionsPercent:a.maxIdleConnectionsPercent},...a.connectionBorrowTimeout&&{ConnectionBorrowTimeout:a.connectionBorrowTimeout}}}}generateProxyTargetCF(a,n){return{Type:"AWS::RDS::DBProxyTargetGroup",Properties:{DBProxyName:n.name,TargetGroupName:"default",DBInstanceIdentifiers:[a.targetArn],ConnectionPoolConfig:{MaxConnectionsPercent:100,MaxIdleConnectionsPercent:50,ConnectionBorrowTimeout:120}}}}generateProxyRoleCF(){return{Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"rds.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"RDSProxySecretsPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],Resource:"arn:aws:secretsmanager:*:*:secret:*"},{Effect:"Allow",Action:["kms:Decrypt"],Resource:"arn:aws:kms:*:*:key/*",Condition:{StringEquals:{"kms:ViaService":"secretsmanager.*.amazonaws.com"}}}]}}]}}}clear(){this.replicas.clear(),this.replicationGroups.clear(),this.proxies.clear(),this.proxyTargets.clear(),this.replicaCounter=0,this.groupCounter=0,this.proxyCounter=0,this.targetCounter=0}}var CC=new Ig;class Sg{insights=new Map;slowQueryLogs=new Map;queryMetrics=new Map;reports=new Map;indexRecommendations=new Map;insightsCounter=0;logCounter=0;metricCounter=0;reportCounter=0;recommendationCounter=0;enablePerformanceInsights(a){let n=`pi-${Date.now()}-${this.insightsCounter++}`,i={id:n,name:a.name,databaseIdentifier:a.databaseIdentifier,enabled:!0,retentionPeriod:a.retentionPeriod||7,kmsKeyId:a.kmsKeyId};return this.insights.set(n,i),i}enableSlowQueryLog(a){let n=`slow-query-${Date.now()}-${this.logCounter++}`,i={id:n,name:a.name,databaseIdentifier:a.databaseIdentifier,enabled:!0,logDestination:a.logDestination,cloudwatchLogGroup:a.cloudwatchLogGroup,s3Bucket:a.s3Bucket,s3Prefix:a.s3Bucket?"slow-queries/":void 0,minExecutionTime:a.minExecutionTime||1000};return this.slowQueryLogs.set(n,i),i}recordQueryMetric(a){let n=`metric-${Date.now()}-${this.metricCounter++}`,i={id:n,timestamp:new Date,...a};return this.queryMetrics.set(n,i),i}generatePerformanceReport(a){let n=`report-${Date.now()}-${this.reportCounter++}`,i={avgCPU:Math.random()*60+20,maxCPU:Math.random()*30+70,avgConnections:Math.floor(Math.random()*50+10),maxConnections:Math.floor(Math.random()*50+100),avgReadIOPS:Math.floor(Math.random()*1000+500),avgWriteIOPS:Math.floor(Math.random()*500+200),avgReadThroughput:Math.random()*50+10,avgWriteThroughput:Math.random()*20+5,avgReadLatency:Math.random()*5+1,avgWriteLatency:Math.random()*8+2,cacheHitRatio:Math.random()*10+90,deadlocks:Math.floor(Math.random()*5),longRunningTransactions:Math.floor(Math.random()*10)},s=Array.from(this.queryMetrics.values()),c=s.sort((y,S)=>S.executionCount-y.executionCount).slice(0,10),l=s.filter((y)=>y.avgExecutionTime>1000).sort((y,S)=>S.avgExecutionTime-y.avgExecutionTime).slice(0,10),u=this.generateRecommendations(i,l),h={id:n,name:a.name,databaseIdentifier:a.databaseIdentifier,reportType:a.reportType,metrics:i,topQueries:c,slowQueries:l,recommendations:u,generatedAt:new Date};return this.reports.set(n,h),h}generateRecommendations(a,n){let i=[];if(a.avgCPU>70)i.push({type:"scaling",severity:"high",title:"High CPU Usage",description:`Average CPU usage is ${a.avgCPU.toFixed(1)}%, which is above the recommended threshold of 70%.`,impact:"Performance degradation, increased latency, potential timeouts",effort:"medium"});if(a.cacheHitRatio<95)i.push({type:"configuration",severity:"medium",title:"Low Cache Hit Ratio",description:`Cache hit ratio is ${a.cacheHitRatio.toFixed(1)}%. Consider increasing buffer pool size.`,impact:"Increased disk I/O, slower query performance",effort:"low"});if(a.deadlocks>0)i.push({type:"query",severity:"medium",title:"Deadlocks Detected",description:`${a.deadlocks} deadlock(s) detected. Review transaction isolation levels and query patterns.`,impact:"Transaction failures, application errors",effort:"high"});if(n.length>0)i.push({type:"index",severity:"high",title:"Slow Queries Detected",description:`${n.length} slow queries detected. Consider adding indexes or optimizing queries.`,impact:"High latency, poor user experience",effort:"medium"});if(a.avgReadLatency>10||a.avgWriteLatency>10)i.push({type:"scaling",severity:"high",title:"High I/O Latency",description:"Read or write latency is high. Consider upgrading to Provisioned IOPS or moving to a larger instance.",impact:"Slow query execution, application timeouts",effort:"medium"});return i}analyzeQuery(a){let n=`analysis-${Date.now()}-${Math.random().toString(36).slice(2,9)}`,i=[{id:1,operation:"Seq Scan",table:"users",rows:1e4,cost:850.5,children:[]}],s=[];if(a.toLowerCase().includes("select *"))s.push({type:"full_table_scan",severity:"warning",description:"Query selects all columns. Consider selecting only required columns."});if(!a.toLowerCase().includes("where")&&a.toLowerCase().includes("select"))s.push({type:"full_table_scan",severity:"critical",description:"Query has no WHERE clause and may scan entire table."});return{id:n,queryId:n,sql:a,executionPlan:i,bottlenecks:s,recommendations:["Add appropriate indexes on WHERE clause columns","Consider using EXPLAIN ANALYZE to get actual execution statistics","Review and optimize JOIN conditions"],estimatedCost:i[0].cost}}recommendIndex(a){let n=`index-rec-${Date.now()}-${this.recommendationCounter++}`,i=`idx_${a.tableName}_${a.columns.join("_")}`,s={id:n,tableName:a.tableName,columns:a.columns,reason:a.reason,estimatedImprovement:a.estimatedImprovement||50,estimatedSize:a.columns.length*10,createSQL:`CREATE INDEX ${i} ON ${a.tableName} (${a.columns.join(", ")});`};return this.indexRecommendations.set(n,s),s}getInsights(a){return this.insights.get(a)}listInsights(){return Array.from(this.insights.values())}getSlowQueryLog(a){return this.slowQueryLogs.get(a)}listSlowQueryLogs(){return Array.from(this.slowQueryLogs.values())}getReport(a){return this.reports.get(a)}listReports(){return Array.from(this.reports.values())}listIndexRecommendations(){return Array.from(this.indexRecommendations.values())}generatePerformanceInsightsCF(a){return{EnablePerformanceInsights:a.enabled,PerformanceInsightsRetentionPeriod:a.retentionPeriod,...a.kmsKeyId&&{PerformanceInsightsKMSKeyId:a.kmsKeyId}}}generateSlowQueryAlarmCF(a){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:a.alarmName,AlarmDescription:"Alert when slow queries exceed threshold",MetricName:"SlowQueryCount",Namespace:"AWS/RDS",Statistic:"Sum",Period:300,EvaluationPeriods:1,Threshold:a.threshold,ComparisonOperator:"GreaterThanThreshold",...a.snsTopicArn&&{AlarmActions:[a.snsTopicArn]}}}}clear(){this.insights.clear(),this.slowQueryLogs.clear(),this.queryMetrics.clear(),this.reports.clear(),this.indexRecommendations.clear(),this.insightsCounter=0,this.logCounter=0,this.metricCounter=0,this.reportCounter=0,this.recommendationCounter=0}}var bC=new Sg;class Cg{users=new Map;roles=new Map;audits=new Map;userCounter=0;roleCounter=0;auditCounter=0;createUser(a){let n=`db-user-${Date.now()}-${this.userCounter++}`,i={id:n,createdAt:new Date,...a};return this.users.set(n,i),i}createReadOnlyUser(a){let n=a.tables?a.tables.map((i)=>({database:a.database,table:i,privileges:["SELECT"]})):[{database:a.database,privileges:["SELECT"]}];return this.createUser({username:a.username,database:a.database,privileges:n,passwordSecretArn:a.passwordSecretArn,rotationEnabled:!0,rotationDays:90})}createReadWriteUser(a){let n=a.tables?a.tables.map((i)=>({database:a.database,table:i,privileges:["SELECT","INSERT","UPDATE","DELETE"]})):[{database:a.database,privileges:["SELECT","INSERT","UPDATE","DELETE"]}];return this.createUser({username:a.username,database:a.database,privileges:n,passwordSecretArn:a.passwordSecretArn,rotationEnabled:!0,rotationDays:60})}createAdminUser(a){return this.createUser({username:a.username,database:a.database,privileges:[{database:a.database,privileges:["ALL"]}],passwordSecretArn:a.passwordSecretArn,rotationEnabled:!0,rotationDays:30})}createApplicationUser(a){let n=a.tables.map((i)=>({database:a.database,table:i.name,privileges:i.privileges}));return this.createUser({username:a.username,database:a.database,privileges:n,passwordSecretArn:a.passwordSecretArn,rotationEnabled:!0,rotationDays:90})}createRole(a){let n=`role-${Date.now()}-${this.roleCounter++}`,i={id:n,users:[],...a};return this.roles.set(n,i),i}assignUserToRole(a,n){let i=this.users.get(a),s=this.roles.get(n);if(!i)throw Error(`User not found: ${a}`);if(!s)throw Error(`Role not found: ${n}`);s.users.push(a);for(let c of s.privileges){let l=i.privileges.find((u)=>u.database===c.database&&u.table===c.table);if(l)l.privileges=Array.from(new Set([...l.privileges,...c.privileges]));else i.privileges.push({...c})}}grantPrivileges(a,n){let i=this.users.get(a);if(!i)return{success:!1,message:"User not found"};for(let s of n){let c=i.privileges.find((l)=>l.database===s.database&&l.table===s.table);if(c)c.privileges=Array.from(new Set([...c.privileges,...s.privileges]));else i.privileges.push(s)}return this.auditAccess({username:i.username,action:"GRANT",database:n[0]?.database,table:n[0]?.table,success:!0}),{success:!0,message:"Privileges granted successfully"}}revokePrivileges(a,n){let i=this.users.get(a);if(!i)return{success:!1,message:"User not found"};for(let s of n){let c=i.privileges.findIndex((l)=>l.database===s.database&&l.table===s.table);if(c!==-1){let l=i.privileges[c];if(l.privileges=l.privileges.filter((u)=>!s.privileges.includes(u)),l.privileges.length===0)i.privileges.splice(c,1)}}return this.auditAccess({username:i.username,action:"REVOKE",database:n[0]?.database,table:n[0]?.table,success:!0}),{success:!0,message:"Privileges revoked successfully"}}rotatePassword(a){let n=this.users.get(a);if(!n)return{success:!1};let i=`arn:aws:secretsmanager:us-east-1:123456789012:secret:db-${n.username}-${Date.now()}`;return n.passwordSecretArn=i,n.lastRotated=new Date,console.log(`Password rotated for user: ${n.username}`),{success:!0,newSecretArn:i}}needsPasswordRotation(a){let n=this.users.get(a);if(!n||!n.rotationEnabled||!n.lastRotated||!n.rotationDays)return!1;return(Date.now()-n.lastRotated.getTime())/86400000>=n.rotationDays}auditAccess(a){let n=`audit-${Date.now()}-${this.auditCounter++}`,i={id:n,timestamp:new Date,...a};return this.audits.set(n,i),i}getUserAccessHistory(a,n=100){return Array.from(this.audits.values()).filter((i)=>i.username===a).sort((i,s)=>s.timestamp.getTime()-i.timestamp.getTime()).slice(0,n)}getFailedLoginAttempts(a,n=24){let i=Date.now()-n*60*60*1000;return Array.from(this.audits.values()).filter((s)=>s.username===a&&s.action==="LOGIN"&&!s.success&&s.timestamp.getTime()>i)}generateCreateUserSQL(a,n="postgres"){let i=[];if(n==="postgres"){i.push(`CREATE USER ${a.username} WITH PASSWORD '${a.passwordSecretArn}';`);for(let s of a.privileges)if(s.privileges.includes("ALL"))i.push(`GRANT ALL PRIVILEGES ON DATABASE ${s.database} TO ${a.username};`);else{let c=s.privileges.join(", ");if(s.table)i.push(`GRANT ${c} ON ${s.database}.${s.table} TO ${a.username};`);else i.push(`GRANT ${c} ON DATABASE ${s.database} TO ${a.username};`)}}else{i.push(`CREATE USER '${a.username}'@'%' IDENTIFIED BY '${a.passwordSecretArn}';`);for(let s of a.privileges){let c=s.privileges.includes("ALL")?"ALL PRIVILEGES":s.privileges.join(", "),l=s.table?`${s.database}.${s.table}`:`${s.database}.*`;i.push(`GRANT ${c} ON ${l} TO '${a.username}'@'%';`)}i.push("FLUSH PRIVILEGES;")}return i.join(`
3761
- `)}getUser(a){return this.users.get(a)}listUsers(){return Array.from(this.users.values())}getRole(a){return this.roles.get(a)}listRoles(){return Array.from(this.roles.values())}clear(){this.users.clear(),this.roles.clear(),this.audits.clear(),this.userCounter=0,this.roleCounter=0,this.auditCounter=0}}var EC=new Cg;class bg{rotations=new Map;schedules=new Map;rotationCounter=0;scheduleCounter=0;createRotation(a){let n=`rotation-${Date.now()}-${this.rotationCounter++}`,i={id:n,...a};return this.rotations.set(n,i),i}enableRDSRotation(a){let n=this.createRotation({secretId:a.secretId,secretType:"rds_credentials",rotationEnabled:!0,rotationDays:a.rotationDays||30,rotationLambdaArn:this.generateRDSRotationLambdaArn(a.engine)});return n.nextRotation=new Date(Date.now()+n.rotationDays*24*60*60*1000),n}enableAPIKeyRotation(a){return this.createRotation({secretId:a.secretId,secretType:"api_key",rotationEnabled:!0,rotationDays:a.rotationDays||90,rotationLambdaArn:a.rotationLambdaArn})}enableOAuthRotation(a){return this.createRotation({secretId:a.secretId,secretType:"oauth_token",rotationEnabled:!0,rotationDays:a.rotationDays||60,rotationLambdaArn:a.rotationLambdaArn})}enableSSHKeyRotation(a){return this.createRotation({secretId:a.secretId,secretType:"ssh_key",rotationEnabled:!0,rotationDays:a.rotationDays||180,rotationLambdaArn:a.rotationLambdaArn})}createSchedule(a){let n=`schedule-${Date.now()}-${this.scheduleCounter++}`,i={id:n,...a};return this.schedules.set(n,i),i}async executeRotation(a){let n=this.rotations.get(a);if(!n)throw Error(`Rotation not found: ${a}`);console.log(`
3760
+ ✓ Promotion completed successfully`),n.status="available",{success:!0,message:"Replica promoted successfully"}}getReplicationLag(a){if(!this.replicas.get(a))throw Error(`Replica not found: ${a}`);return Math.floor(Math.random()*1000)}getReplica(a){return this.replicas.get(a)}listReplicas(){return Array.from(this.replicas.values())}getReplicationGroup(a){return this.replicationGroups.get(a)}listReplicationGroups(){return Array.from(this.replicationGroups.values())}getProxy(a){return this.proxies.get(a)}listProxies(){return Array.from(this.proxies.values())}generateReplicaCF(a){return{Type:"AWS::RDS::DBInstance",Properties:{SourceDBInstanceIdentifier:a.sourceDatabase,DBInstanceIdentifier:a.name,DBInstanceClass:a.instanceClass,MultiAZ:a.multiAZ||!1,AutoMinorVersionUpgrade:a.autoMinorVersionUpgrade??!0,...a.backupRetentionPeriod&&{BackupRetentionPeriod:a.backupRetentionPeriod},...a.preferredBackupWindow&&{PreferredBackupWindow:a.preferredBackupWindow},...a.preferredMaintenanceWindow&&{PreferredMaintenanceWindow:a.preferredMaintenanceWindow}}}}generateProxyCF(a){return{Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:a.name,EngineFamily:a.engineFamily,Auth:[{AuthScheme:"SECRETS",SecretArn:a.secretArn,IAMAuth:"DISABLED"}],RoleArn:{"Fn::GetAtt":["RDSProxyRole","Arn"]},VpcSubnetIds:a.vpcSubnetIds,VpcSecurityGroupIds:a.securityGroupIds,RequireTLS:a.requireTLS??!0,IdleClientTimeout:a.idleClientTimeout||1800,...a.maxConnectionsPercent&&{MaxConnectionsPercent:a.maxConnectionsPercent},...a.maxIdleConnectionsPercent&&{MaxIdleConnectionsPercent:a.maxIdleConnectionsPercent},...a.connectionBorrowTimeout&&{ConnectionBorrowTimeout:a.connectionBorrowTimeout}}}}generateProxyTargetCF(a,n){return{Type:"AWS::RDS::DBProxyTargetGroup",Properties:{DBProxyName:n.name,TargetGroupName:"default",DBInstanceIdentifiers:[a.targetArn],ConnectionPoolConfig:{MaxConnectionsPercent:100,MaxIdleConnectionsPercent:50,ConnectionBorrowTimeout:120}}}}generateProxyRoleCF(){return{Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"rds.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"RDSProxySecretsPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],Resource:"arn:aws:secretsmanager:*:*:secret:*"},{Effect:"Allow",Action:["kms:Decrypt"],Resource:"arn:aws:kms:*:*:key/*",Condition:{StringEquals:{"kms:ViaService":"secretsmanager.*.amazonaws.com"}}}]}}]}}}clear(){this.replicas.clear(),this.replicationGroups.clear(),this.proxies.clear(),this.proxyTargets.clear(),this.replicaCounter=0,this.groupCounter=0,this.proxyCounter=0,this.targetCounter=0}}var CC=new Ig;class Sg{insights=new Map;slowQueryLogs=new Map;queryMetrics=new Map;reports=new Map;indexRecommendations=new Map;insightsCounter=0;logCounter=0;metricCounter=0;reportCounter=0;recommendationCounter=0;enablePerformanceInsights(a){let n=`pi-${Date.now()}-${this.insightsCounter++}`,i={id:n,name:a.name,databaseIdentifier:a.databaseIdentifier,enabled:!0,retentionPeriod:a.retentionPeriod||7,kmsKeyId:a.kmsKeyId};return this.insights.set(n,i),i}enableSlowQueryLog(a){let n=`slow-query-${Date.now()}-${this.logCounter++}`,i={id:n,name:a.name,databaseIdentifier:a.databaseIdentifier,enabled:!0,logDestination:a.logDestination,cloudwatchLogGroup:a.cloudwatchLogGroup,s3Bucket:a.s3Bucket,s3Prefix:a.s3Bucket?"slow-queries/":void 0,minExecutionTime:a.minExecutionTime||1000};return this.slowQueryLogs.set(n,i),i}recordQueryMetric(a){let n=`metric-${Date.now()}-${this.metricCounter++}`,i={id:n,timestamp:new Date,...a};return this.queryMetrics.set(n,i),i}generatePerformanceReport(a){let n=`report-${Date.now()}-${this.reportCounter++}`,i={avgCPU:Math.random()*60+20,maxCPU:Math.random()*30+70,avgConnections:Math.floor(Math.random()*50+10),maxConnections:Math.floor(Math.random()*50+100),avgReadIOPS:Math.floor(Math.random()*1000+500),avgWriteIOPS:Math.floor(Math.random()*500+200),avgReadThroughput:Math.random()*50+10,avgWriteThroughput:Math.random()*20+5,avgReadLatency:Math.random()*5+1,avgWriteLatency:Math.random()*8+2,cacheHitRatio:Math.random()*10+90,deadlocks:Math.floor(Math.random()*5),longRunningTransactions:Math.floor(Math.random()*10)},s=Array.from(this.queryMetrics.values()),c=s.sort((y,S)=>S.executionCount-y.executionCount).slice(0,10),l=s.filter((y)=>y.avgExecutionTime>1000).sort((y,S)=>S.avgExecutionTime-y.avgExecutionTime).slice(0,10),u=this.generateRecommendations(i,l),h={id:n,name:a.name,databaseIdentifier:a.databaseIdentifier,reportType:a.reportType,metrics:i,topQueries:c,slowQueries:l,recommendations:u,generatedAt:new Date};return this.reports.set(n,h),h}generateRecommendations(a,n){let i=[];if(a.avgCPU>70)i.push({type:"scaling",severity:"high",title:"High CPU Usage",description:`Average CPU usage is ${a.avgCPU.toFixed(1)}%, which is above the recommended threshold of 70%.`,impact:"Performance degradation, increased latency, potential timeouts",effort:"medium"});if(a.cacheHitRatio<95)i.push({type:"configuration",severity:"medium",title:"Low Cache Hit Ratio",description:`Cache hit ratio is ${a.cacheHitRatio.toFixed(1)}%. Consider increasing buffer pool size.`,impact:"Increased disk I/O, slower query performance",effort:"low"});if(a.deadlocks>0)i.push({type:"query",severity:"medium",title:"Deadlocks Detected",description:`${a.deadlocks} deadlock(s) detected. Review transaction isolation levels and query patterns.`,impact:"Transaction failures, application errors",effort:"high"});if(n.length>0)i.push({type:"index",severity:"high",title:"Slow Queries Detected",description:`${n.length} slow queries detected. Consider adding indexes or optimizing queries.`,impact:"High latency, poor user experience",effort:"medium"});if(a.avgReadLatency>10||a.avgWriteLatency>10)i.push({type:"scaling",severity:"high",title:"High I/O Latency",description:"Read or write latency is high. Consider upgrading to Provisioned IOPS or moving to a larger instance.",impact:"Slow query execution, application timeouts",effort:"medium"});return i}analyzeQuery(a){let n=`analysis-${Date.now()}-${Math.random().toString(36).slice(2,9)}`,i=[{id:1,operation:"Seq Scan",table:"users",rows:1e4,cost:850.5,children:[]}],s=[];if(a.toLowerCase().includes("select *"))s.push({type:"full_table_scan",severity:"warning",description:"Query selects all columns. Consider selecting only required columns."});if(!a.toLowerCase().includes("where")&&a.toLowerCase().includes("select"))s.push({type:"full_table_scan",severity:"critical",description:"Query has no WHERE clause and may scan entire table."});return{id:n,queryId:n,sql:a,executionPlan:i,bottlenecks:s,recommendations:["Add appropriate indexes on WHERE clause columns","Consider using EXPLAIN ANALYZE to get actual execution statistics","Review and optimize JOIN conditions"],estimatedCost:i[0].cost}}recommendIndex(a){let n=`index-rec-${Date.now()}-${this.recommendationCounter++}`,i=`idx_${a.tableName}_${a.columns.join("_")}`,s={id:n,tableName:a.tableName,columns:a.columns,reason:a.reason,estimatedImprovement:a.estimatedImprovement||50,estimatedSize:a.columns.length*10,createSQL:`CREATE INDEX ${i} ON ${a.tableName} (${a.columns.join(", ")});`};return this.indexRecommendations.set(n,s),s}getInsights(a){return this.insights.get(a)}listInsights(){return Array.from(this.insights.values())}getSlowQueryLog(a){return this.slowQueryLogs.get(a)}listSlowQueryLogs(){return Array.from(this.slowQueryLogs.values())}getReport(a){return this.reports.get(a)}listReports(){return Array.from(this.reports.values())}listIndexRecommendations(){return Array.from(this.indexRecommendations.values())}generatePerformanceInsightsCF(a){return{EnablePerformanceInsights:a.enabled,PerformanceInsightsRetentionPeriod:a.retentionPeriod,...a.kmsKeyId&&{PerformanceInsightsKMSKeyId:a.kmsKeyId}}}generateSlowQueryAlarmCF(a){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:a.alarmName,AlarmDescription:"Alert when slow queries exceed threshold",MetricName:"SlowQueryCount",Namespace:"AWS/RDS",Statistic:"Sum",Period:300,EvaluationPeriods:1,Threshold:a.threshold,ComparisonOperator:"GreaterThanThreshold",...a.snsTopicArn&&{AlarmActions:[a.snsTopicArn]}}}}clear(){this.insights.clear(),this.slowQueryLogs.clear(),this.queryMetrics.clear(),this.reports.clear(),this.indexRecommendations.clear(),this.insightsCounter=0,this.logCounter=0,this.metricCounter=0,this.reportCounter=0,this.recommendationCounter=0}}var EC=new Sg;class Cg{users=new Map;roles=new Map;audits=new Map;userCounter=0;roleCounter=0;auditCounter=0;createUser(a){let n=`db-user-${Date.now()}-${this.userCounter++}`,i={id:n,createdAt:new Date,...a};return this.users.set(n,i),i}createReadOnlyUser(a){let n=a.tables?a.tables.map((i)=>({database:a.database,table:i,privileges:["SELECT"]})):[{database:a.database,privileges:["SELECT"]}];return this.createUser({username:a.username,database:a.database,privileges:n,passwordSecretArn:a.passwordSecretArn,rotationEnabled:!0,rotationDays:90})}createReadWriteUser(a){let n=a.tables?a.tables.map((i)=>({database:a.database,table:i,privileges:["SELECT","INSERT","UPDATE","DELETE"]})):[{database:a.database,privileges:["SELECT","INSERT","UPDATE","DELETE"]}];return this.createUser({username:a.username,database:a.database,privileges:n,passwordSecretArn:a.passwordSecretArn,rotationEnabled:!0,rotationDays:60})}createAdminUser(a){return this.createUser({username:a.username,database:a.database,privileges:[{database:a.database,privileges:["ALL"]}],passwordSecretArn:a.passwordSecretArn,rotationEnabled:!0,rotationDays:30})}createApplicationUser(a){let n=a.tables.map((i)=>({database:a.database,table:i.name,privileges:i.privileges}));return this.createUser({username:a.username,database:a.database,privileges:n,passwordSecretArn:a.passwordSecretArn,rotationEnabled:!0,rotationDays:90})}createRole(a){let n=`role-${Date.now()}-${this.roleCounter++}`,i={id:n,users:[],...a};return this.roles.set(n,i),i}assignUserToRole(a,n){let i=this.users.get(a),s=this.roles.get(n);if(!i)throw Error(`User not found: ${a}`);if(!s)throw Error(`Role not found: ${n}`);s.users.push(a);for(let c of s.privileges){let l=i.privileges.find((u)=>u.database===c.database&&u.table===c.table);if(l)l.privileges=Array.from(new Set([...l.privileges,...c.privileges]));else i.privileges.push({...c})}}grantPrivileges(a,n){let i=this.users.get(a);if(!i)return{success:!1,message:"User not found"};for(let s of n){let c=i.privileges.find((l)=>l.database===s.database&&l.table===s.table);if(c)c.privileges=Array.from(new Set([...c.privileges,...s.privileges]));else i.privileges.push(s)}return this.auditAccess({username:i.username,action:"GRANT",database:n[0]?.database,table:n[0]?.table,success:!0}),{success:!0,message:"Privileges granted successfully"}}revokePrivileges(a,n){let i=this.users.get(a);if(!i)return{success:!1,message:"User not found"};for(let s of n){let c=i.privileges.findIndex((l)=>l.database===s.database&&l.table===s.table);if(c!==-1){let l=i.privileges[c];if(l.privileges=l.privileges.filter((u)=>!s.privileges.includes(u)),l.privileges.length===0)i.privileges.splice(c,1)}}return this.auditAccess({username:i.username,action:"REVOKE",database:n[0]?.database,table:n[0]?.table,success:!0}),{success:!0,message:"Privileges revoked successfully"}}rotatePassword(a){let n=this.users.get(a);if(!n)return{success:!1};let i=`arn:aws:secretsmanager:us-east-1:123456789012:secret:db-${n.username}-${Date.now()}`;return n.passwordSecretArn=i,n.lastRotated=new Date,console.log(`Password rotated for user: ${n.username}`),{success:!0,newSecretArn:i}}needsPasswordRotation(a){let n=this.users.get(a);if(!n||!n.rotationEnabled||!n.lastRotated||!n.rotationDays)return!1;return(Date.now()-n.lastRotated.getTime())/86400000>=n.rotationDays}auditAccess(a){let n=`audit-${Date.now()}-${this.auditCounter++}`,i={id:n,timestamp:new Date,...a};return this.audits.set(n,i),i}getUserAccessHistory(a,n=100){return Array.from(this.audits.values()).filter((i)=>i.username===a).sort((i,s)=>s.timestamp.getTime()-i.timestamp.getTime()).slice(0,n)}getFailedLoginAttempts(a,n=24){let i=Date.now()-n*60*60*1000;return Array.from(this.audits.values()).filter((s)=>s.username===a&&s.action==="LOGIN"&&!s.success&&s.timestamp.getTime()>i)}generateCreateUserSQL(a,n="postgres"){let i=[];if(n==="postgres"){i.push(`CREATE USER ${a.username} WITH PASSWORD '${a.passwordSecretArn}';`);for(let s of a.privileges)if(s.privileges.includes("ALL"))i.push(`GRANT ALL PRIVILEGES ON DATABASE ${s.database} TO ${a.username};`);else{let c=s.privileges.join(", ");if(s.table)i.push(`GRANT ${c} ON ${s.database}.${s.table} TO ${a.username};`);else i.push(`GRANT ${c} ON DATABASE ${s.database} TO ${a.username};`)}}else{i.push(`CREATE USER '${a.username}'@'%' IDENTIFIED BY '${a.passwordSecretArn}';`);for(let s of a.privileges){let c=s.privileges.includes("ALL")?"ALL PRIVILEGES":s.privileges.join(", "),l=s.table?`${s.database}.${s.table}`:`${s.database}.*`;i.push(`GRANT ${c} ON ${l} TO '${a.username}'@'%';`)}i.push("FLUSH PRIVILEGES;")}return i.join(`
3761
+ `)}getUser(a){return this.users.get(a)}listUsers(){return Array.from(this.users.values())}getRole(a){return this.roles.get(a)}listRoles(){return Array.from(this.roles.values())}clear(){this.users.clear(),this.roles.clear(),this.audits.clear(),this.userCounter=0,this.roleCounter=0,this.auditCounter=0}}var bC=new Cg;class Eg{rotations=new Map;schedules=new Map;rotationCounter=0;scheduleCounter=0;createRotation(a){let n=`rotation-${Date.now()}-${this.rotationCounter++}`,i={id:n,...a};return this.rotations.set(n,i),i}enableRDSRotation(a){let n=this.createRotation({secretId:a.secretId,secretType:"rds_credentials",rotationEnabled:!0,rotationDays:a.rotationDays||30,rotationLambdaArn:this.generateRDSRotationLambdaArn(a.engine)});return n.nextRotation=new Date(Date.now()+n.rotationDays*24*60*60*1000),n}enableAPIKeyRotation(a){return this.createRotation({secretId:a.secretId,secretType:"api_key",rotationEnabled:!0,rotationDays:a.rotationDays||90,rotationLambdaArn:a.rotationLambdaArn})}enableOAuthRotation(a){return this.createRotation({secretId:a.secretId,secretType:"oauth_token",rotationEnabled:!0,rotationDays:a.rotationDays||60,rotationLambdaArn:a.rotationLambdaArn})}enableSSHKeyRotation(a){return this.createRotation({secretId:a.secretId,secretType:"ssh_key",rotationEnabled:!0,rotationDays:a.rotationDays||180,rotationLambdaArn:a.rotationLambdaArn})}createSchedule(a){let n=`schedule-${Date.now()}-${this.scheduleCounter++}`,i={id:n,...a};return this.schedules.set(n,i),i}async executeRotation(a){let n=this.rotations.get(a);if(!n)throw Error(`Rotation not found: ${a}`);console.log(`
3762
3762
  Executing rotation for secret: ${n.secretId}`),console.log(`Secret type: ${n.secretType}`),console.log(`Rotation interval: ${n.rotationDays} days`);try{console.log(`
3763
3763
  Rotation steps:`),console.log("1. Creating new secret version...");let i=`v${Date.now()}`;console.log("2. Testing new credentials..."),console.log("3. Updating application references..."),console.log("4. Marking previous version as deprecated...");let s=n.versionStages?.[0]||"v1";return console.log("5. Finalizing rotation..."),n.lastRotated=new Date,n.nextRotation=new Date(Date.now()+n.rotationDays*24*60*60*1000),console.log(`
3764
3764
  ✓ Rotation completed successfully`),console.log(` New version: ${i}`),console.log(` Next rotation: ${n.nextRotation.toISOString()}`),{success:!0,secretId:n.secretId,oldVersion:s,newVersion:i,rotatedAt:new Date}}catch(i){return console.error(`
3765
- ✗ Rotation failed:`,i),{success:!1,secretId:n.secretId,oldVersion:"unknown",newVersion:"unknown",rotatedAt:new Date,error:i instanceof Error?i.message:String(i)}}}needsRotation(a){let n=this.rotations.get(a);if(!n||!n.rotationEnabled)return!1;if(!n.lastRotated)return!0;return(Date.now()-n.lastRotated.getTime())/86400000>=n.rotationDays}getSecretsNeedingRotation(){return Array.from(this.rotations.values()).filter((a)=>this.needsRotation(a.id))}generateRDSRotationLambdaArn(a){let n={postgres:"SecretsManagerRDSPostgreSQLRotationSingleUser",mysql:"SecretsManagerRDSMySQLRotationSingleUser",sqlserver:"SecretsManagerRDSSQLServerRotationSingleUser",oracle:"SecretsManagerRDSOracleRotationSingleUser"};return`arn:aws:lambda:us-east-1:123456789012:function:${n[a]||n.postgres}`}getRotation(a){return this.rotations.get(a)}listRotations(){return Array.from(this.rotations.values())}getSchedule(a){return this.schedules.get(a)}listSchedules(){return Array.from(this.schedules.values())}generateRotationCF(a){return{RotationEnabled:a.rotationEnabled,RotationRules:{AutomaticallyAfterDays:a.rotationDays},...a.rotationLambdaArn&&{RotationLambdaARN:a.rotationLambdaArn}}}generateRotationLambdaCF(a){return{Type:"AWS::Lambda::Function",Properties:{FunctionName:a.functionName,Runtime:"python3.11",Handler:"lambda_function.lambda_handler",Role:{"Fn::GetAtt":["RotationLambdaRole","Arn"]},Timeout:30,Environment:{Variables:{SECRETS_MANAGER_ENDPOINT:"https://secretsmanager.us-east-1.amazonaws.com"}},...a.vpcConfig&&{VpcConfig:{SubnetIds:a.vpcConfig.subnetIds,SecurityGroupIds:a.vpcConfig.securityGroupIds}}}}}generateRotationLambdaRoleCF(){return{Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole","arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"],Policies:[{PolicyName:"SecretsRotationPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:DescribeSecret","secretsmanager:GetSecretValue","secretsmanager:PutSecretValue","secretsmanager:UpdateSecretVersionStage"],Resource:"*"},{Effect:"Allow",Action:["secretsmanager:GetRandomPassword"],Resource:"*"}]}}]}}}generateRotationScheduleCF(a){return{Type:"AWS::Events::Rule",Properties:{Name:a.name,Description:`Rotation schedule for ${a.secrets.length} secrets`,ScheduleExpression:a.schedule,State:a.enabled?"ENABLED":"DISABLED",Targets:[{Arn:{"Fn::GetAtt":["RotationStateMachine","Arn"]},RoleArn:{"Fn::GetAtt":["EventBridgeRotationRole","Arn"]},Input:JSON.stringify({secrets:a.secrets})}]}}}clear(){this.rotations.clear(),this.schedules.clear(),this.rotationCounter=0,this.scheduleCounter=0}}var vC=new bg;class Eg{versions=new Map;audits=new Map;externalManagers=new Map;replications=new Map;policies=new Map;versionCounter=0;auditCounter=0;managerCounter=0;replicationCounter=0;policyCounter=0;createVersion(a){let n=`version-${Date.now()}-${this.versionCounter++}`,i={id:n,...a};return this.versions.set(n,i),this.auditAction({secretId:a.secretId,action:"CREATE",actor:"system",versionId:a.versionId,success:!0}),i}getVersionByStage(a,n){return Array.from(this.versions.values()).find((i)=>i.secretId===a&&i.versionStages.includes(n))}listVersions(a){return Array.from(this.versions.values()).filter((n)=>n.secretId===a).sort((n,i)=>i.createdAt.getTime()-n.createdAt.getTime())}deprecateVersion(a){let n=Array.from(this.versions.values()).find((i)=>i.versionId===a);if(n)n.deprecatedAt=new Date,n.versionStages=n.versionStages.filter((i)=>i!=="AWSCURRENT"),this.auditAction({secretId:n.secretId,action:"UPDATE",actor:"system",versionId:a,success:!0})}restoreVersion(a){let n=Array.from(this.versions.values()).find((i)=>i.versionId===a);if(n)Array.from(this.versions.values()).filter((i)=>i.secretId===n.secretId&&i.versionId!==a).forEach((i)=>{i.versionStages=i.versionStages.filter((s)=>s!=="AWSCURRENT")}),n.versionStages.push("AWSCURRENT"),n.deprecatedAt=void 0,this.auditAction({secretId:n.secretId,action:"RESTORE",actor:"system",versionId:a,success:!0})}auditAction(a){let n=`audit-${Date.now()}-${this.auditCounter++}`,i={id:n,timestamp:new Date,...a};return this.audits.set(n,i),i}getAuditTrail(a,n=100){return Array.from(this.audits.values()).filter((i)=>i.secretId===a).sort((i,s)=>s.timestamp.getTime()-i.timestamp.getTime()).slice(0,n)}getFailedAccesses(a,n=24){let i=Date.now()-n*60*60*1000;return Array.from(this.audits.values()).filter((s)=>s.secretId===a&&!s.success&&s.timestamp.getTime()>i)}registerExternalManager(a){let n=`ext-manager-${Date.now()}-${this.managerCounter++}`,i={id:n,...a};return this.externalManagers.set(n,i),i}registerVault(a){return this.registerExternalManager({type:"vault",name:a.name,endpoint:a.endpoint,authentication:{type:a.token?"token":"iam",credentials:a.token?{token:a.token}:void 0,roleArn:a.roleArn},syncEnabled:a.syncEnabled||!1,syncInterval:60})}registerOnePassword(a){return this.registerExternalManager({type:"onepassword",name:a.name,endpoint:a.endpoint||"https://my.1password.com",authentication:{type:"apikey",credentials:{apiKey:a.apiKey}},syncEnabled:a.syncEnabled||!1,syncInterval:30})}enableReplication(a){let n=`replication-${Date.now()}-${this.replicationCounter++}`,i={id:n,secretId:a.secretId,sourceRegion:a.sourceRegion,replicaRegions:a.replicaRegions,kmsKeyIds:a.kmsKeyIds,status:"replicating"};return this.replications.set(n,i),this.auditAction({secretId:a.secretId,action:"REPLICATE",actor:"system",success:!0}),setTimeout(()=>{i.status="completed"},100),i}createPolicy(a){let n=`policy-${Date.now()}-${this.policyCounter++}`,i={id:n,secretId:a.secretId,policy:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:a.allowedPrincipals},Action:a.allowedActions,Resource:"*"}]}};return this.policies.set(n,i),i}createCrossAccountPolicy(a){let n=a.roleNames.map((i)=>`arn:aws:iam::${a.accountId}:role/${i}`);return this.createPolicy({secretId:a.secretId,allowedPrincipals:n,allowedActions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"]})}getVersion(a){return this.versions.get(a)}getExternalManager(a){return this.externalManagers.get(a)}listExternalManagers(){return Array.from(this.externalManagers.values())}getReplication(a){return this.replications.get(a)}listReplications(){return Array.from(this.replications.values())}generateSecretCF(a){return{Type:"AWS::SecretsManager::Secret",Properties:{Name:a.name,Description:a.description,...a.kmsKeyId&&{KmsKeyId:a.kmsKeyId},...a.replicaRegions&&{ReplicaRegions:a.replicaRegions.map((n)=>({Region:n}))}}}}generateSecretPolicyCF(a){return{Type:"AWS::SecretsManager::ResourcePolicy",Properties:{SecretId:a.secretId,ResourcePolicy:a.policy}}}clear(){this.versions.clear(),this.audits.clear(),this.externalManagers.clear(),this.replications.clear(),this.policies.clear(),this.versionCounter=0,this.auditCounter=0,this.managerCounter=0,this.replicationCounter=0,this.policyCounter=0}}var TC=new Eg;class vg{certificates=new Map;renewals=new Map;validations=new Map;monitors=new Map;alerts=new Map;certificateCounter=0;renewalCounter=0;validationCounter=0;monitorCounter=0;alertCounter=0;requestCertificate(a){let n=`cert-${Date.now()}-${this.certificateCounter++}`,i=`arn:aws:acm:us-east-1:123456789012:certificate/${n}`,s={id:n,arn:i,domainName:a.domainName,subjectAlternativeNames:a.subjectAlternativeNames,validationMethod:a.validationMethod||"DNS",status:"PENDING_VALIDATION"};return this.certificates.set(n,s),this.createValidation(s),s}requestWildcardCertificate(a){let n=[];if(a.includeApex)n.push(a.domainName.replace("*.",""));return this.requestCertificate({domainName:a.domainName,subjectAlternativeNames:n.length>0?n:void 0,validationMethod:"DNS"})}requestMultiDomainCertificate(a){return this.requestCertificate({domainName:a.primaryDomain,subjectAlternativeNames:a.additionalDomains,validationMethod:a.validationMethod||"DNS"})}createValidation(a){let n={domainName:a.domainName,validationMethod:a.validationMethod,validationStatus:"PENDING"};if(a.validationMethod==="DNS")n.resourceRecords=[{name:`_${Math.random().toString(36).slice(2)}.${a.domainName}`,type:"CNAME",value:`_${Math.random().toString(36).slice(2)}.acm-validations.aws.`}];else n.validationEmails=[`admin@${a.domainName}`,`administrator@${a.domainName}`,`hostmaster@${a.domainName}`];return this.validations.set(a.id,n),n}validateCertificate(a){let n=this.certificates.get(a),i=this.validations.get(a);if(!n||!i)return{success:!1,message:"Certificate or validation not found"};return i.validationStatus="SUCCESS",n.status="ISSUED",n.issuedAt=new Date,n.expiresAt=new Date(Date.now()+31536000000),n.renewalEligibility=!0,n.issuer="Amazon",{success:!0,message:"Certificate validated and issued successfully"}}enableAutoRenewal(a){let n=`renewal-${Date.now()}-${this.renewalCounter++}`,i={id:n,certificateArn:a.certificateArn,autoRenew:!0,renewBeforeDays:a.renewBeforeDays||30};return this.renewals.set(n,i),i}async renewCertificate(a){let n=this.renewals.get(a);if(!n)return{success:!1,message:"Renewal configuration not found"};let i=Array.from(this.certificates.values()).find((s)=>s.arn===n.certificateArn);if(!i)return{success:!1,message:"Certificate not found"};console.log(`
3765
+ ✗ Rotation failed:`,i),{success:!1,secretId:n.secretId,oldVersion:"unknown",newVersion:"unknown",rotatedAt:new Date,error:i instanceof Error?i.message:String(i)}}}needsRotation(a){let n=this.rotations.get(a);if(!n||!n.rotationEnabled)return!1;if(!n.lastRotated)return!0;return(Date.now()-n.lastRotated.getTime())/86400000>=n.rotationDays}getSecretsNeedingRotation(){return Array.from(this.rotations.values()).filter((a)=>this.needsRotation(a.id))}generateRDSRotationLambdaArn(a){let n={postgres:"SecretsManagerRDSPostgreSQLRotationSingleUser",mysql:"SecretsManagerRDSMySQLRotationSingleUser",sqlserver:"SecretsManagerRDSSQLServerRotationSingleUser",oracle:"SecretsManagerRDSOracleRotationSingleUser"};return`arn:aws:lambda:us-east-1:123456789012:function:${n[a]||n.postgres}`}getRotation(a){return this.rotations.get(a)}listRotations(){return Array.from(this.rotations.values())}getSchedule(a){return this.schedules.get(a)}listSchedules(){return Array.from(this.schedules.values())}generateRotationCF(a){return{RotationEnabled:a.rotationEnabled,RotationRules:{AutomaticallyAfterDays:a.rotationDays},...a.rotationLambdaArn&&{RotationLambdaARN:a.rotationLambdaArn}}}generateRotationLambdaCF(a){return{Type:"AWS::Lambda::Function",Properties:{FunctionName:a.functionName,Runtime:"python3.11",Handler:"lambda_function.lambda_handler",Role:{"Fn::GetAtt":["RotationLambdaRole","Arn"]},Timeout:30,Environment:{Variables:{SECRETS_MANAGER_ENDPOINT:"https://secretsmanager.us-east-1.amazonaws.com"}},...a.vpcConfig&&{VpcConfig:{SubnetIds:a.vpcConfig.subnetIds,SecurityGroupIds:a.vpcConfig.securityGroupIds}}}}}generateRotationLambdaRoleCF(){return{Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole","arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"],Policies:[{PolicyName:"SecretsRotationPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:DescribeSecret","secretsmanager:GetSecretValue","secretsmanager:PutSecretValue","secretsmanager:UpdateSecretVersionStage"],Resource:"*"},{Effect:"Allow",Action:["secretsmanager:GetRandomPassword"],Resource:"*"}]}}]}}}generateRotationScheduleCF(a){return{Type:"AWS::Events::Rule",Properties:{Name:a.name,Description:`Rotation schedule for ${a.secrets.length} secrets`,ScheduleExpression:a.schedule,State:a.enabled?"ENABLED":"DISABLED",Targets:[{Arn:{"Fn::GetAtt":["RotationStateMachine","Arn"]},RoleArn:{"Fn::GetAtt":["EventBridgeRotationRole","Arn"]},Input:JSON.stringify({secrets:a.secrets})}]}}}clear(){this.rotations.clear(),this.schedules.clear(),this.rotationCounter=0,this.scheduleCounter=0}}var vC=new Eg;class bg{versions=new Map;audits=new Map;externalManagers=new Map;replications=new Map;policies=new Map;versionCounter=0;auditCounter=0;managerCounter=0;replicationCounter=0;policyCounter=0;createVersion(a){let n=`version-${Date.now()}-${this.versionCounter++}`,i={id:n,...a};return this.versions.set(n,i),this.auditAction({secretId:a.secretId,action:"CREATE",actor:"system",versionId:a.versionId,success:!0}),i}getVersionByStage(a,n){return Array.from(this.versions.values()).find((i)=>i.secretId===a&&i.versionStages.includes(n))}listVersions(a){return Array.from(this.versions.values()).filter((n)=>n.secretId===a).sort((n,i)=>i.createdAt.getTime()-n.createdAt.getTime())}deprecateVersion(a){let n=Array.from(this.versions.values()).find((i)=>i.versionId===a);if(n)n.deprecatedAt=new Date,n.versionStages=n.versionStages.filter((i)=>i!=="AWSCURRENT"),this.auditAction({secretId:n.secretId,action:"UPDATE",actor:"system",versionId:a,success:!0})}restoreVersion(a){let n=Array.from(this.versions.values()).find((i)=>i.versionId===a);if(n)Array.from(this.versions.values()).filter((i)=>i.secretId===n.secretId&&i.versionId!==a).forEach((i)=>{i.versionStages=i.versionStages.filter((s)=>s!=="AWSCURRENT")}),n.versionStages.push("AWSCURRENT"),n.deprecatedAt=void 0,this.auditAction({secretId:n.secretId,action:"RESTORE",actor:"system",versionId:a,success:!0})}auditAction(a){let n=`audit-${Date.now()}-${this.auditCounter++}`,i={id:n,timestamp:new Date,...a};return this.audits.set(n,i),i}getAuditTrail(a,n=100){return Array.from(this.audits.values()).filter((i)=>i.secretId===a).sort((i,s)=>s.timestamp.getTime()-i.timestamp.getTime()).slice(0,n)}getFailedAccesses(a,n=24){let i=Date.now()-n*60*60*1000;return Array.from(this.audits.values()).filter((s)=>s.secretId===a&&!s.success&&s.timestamp.getTime()>i)}registerExternalManager(a){let n=`ext-manager-${Date.now()}-${this.managerCounter++}`,i={id:n,...a};return this.externalManagers.set(n,i),i}registerVault(a){return this.registerExternalManager({type:"vault",name:a.name,endpoint:a.endpoint,authentication:{type:a.token?"token":"iam",credentials:a.token?{token:a.token}:void 0,roleArn:a.roleArn},syncEnabled:a.syncEnabled||!1,syncInterval:60})}registerOnePassword(a){return this.registerExternalManager({type:"onepassword",name:a.name,endpoint:a.endpoint||"https://my.1password.com",authentication:{type:"apikey",credentials:{apiKey:a.apiKey}},syncEnabled:a.syncEnabled||!1,syncInterval:30})}enableReplication(a){let n=`replication-${Date.now()}-${this.replicationCounter++}`,i={id:n,secretId:a.secretId,sourceRegion:a.sourceRegion,replicaRegions:a.replicaRegions,kmsKeyIds:a.kmsKeyIds,status:"replicating"};return this.replications.set(n,i),this.auditAction({secretId:a.secretId,action:"REPLICATE",actor:"system",success:!0}),setTimeout(()=>{i.status="completed"},100),i}createPolicy(a){let n=`policy-${Date.now()}-${this.policyCounter++}`,i={id:n,secretId:a.secretId,policy:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:a.allowedPrincipals},Action:a.allowedActions,Resource:"*"}]}};return this.policies.set(n,i),i}createCrossAccountPolicy(a){let n=a.roleNames.map((i)=>`arn:aws:iam::${a.accountId}:role/${i}`);return this.createPolicy({secretId:a.secretId,allowedPrincipals:n,allowedActions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"]})}getVersion(a){return this.versions.get(a)}getExternalManager(a){return this.externalManagers.get(a)}listExternalManagers(){return Array.from(this.externalManagers.values())}getReplication(a){return this.replications.get(a)}listReplications(){return Array.from(this.replications.values())}generateSecretCF(a){return{Type:"AWS::SecretsManager::Secret",Properties:{Name:a.name,Description:a.description,...a.kmsKeyId&&{KmsKeyId:a.kmsKeyId},...a.replicaRegions&&{ReplicaRegions:a.replicaRegions.map((n)=>({Region:n}))}}}}generateSecretPolicyCF(a){return{Type:"AWS::SecretsManager::ResourcePolicy",Properties:{SecretId:a.secretId,ResourcePolicy:a.policy}}}clear(){this.versions.clear(),this.audits.clear(),this.externalManagers.clear(),this.replications.clear(),this.policies.clear(),this.versionCounter=0,this.auditCounter=0,this.managerCounter=0,this.replicationCounter=0,this.policyCounter=0}}var TC=new bg;class vg{certificates=new Map;renewals=new Map;validations=new Map;monitors=new Map;alerts=new Map;certificateCounter=0;renewalCounter=0;validationCounter=0;monitorCounter=0;alertCounter=0;requestCertificate(a){let n=`cert-${Date.now()}-${this.certificateCounter++}`,i=`arn:aws:acm:us-east-1:123456789012:certificate/${n}`,s={id:n,arn:i,domainName:a.domainName,subjectAlternativeNames:a.subjectAlternativeNames,validationMethod:a.validationMethod||"DNS",status:"PENDING_VALIDATION"};return this.certificates.set(n,s),this.createValidation(s),s}requestWildcardCertificate(a){let n=[];if(a.includeApex)n.push(a.domainName.replace("*.",""));return this.requestCertificate({domainName:a.domainName,subjectAlternativeNames:n.length>0?n:void 0,validationMethod:"DNS"})}requestMultiDomainCertificate(a){return this.requestCertificate({domainName:a.primaryDomain,subjectAlternativeNames:a.additionalDomains,validationMethod:a.validationMethod||"DNS"})}createValidation(a){let n={domainName:a.domainName,validationMethod:a.validationMethod,validationStatus:"PENDING"};if(a.validationMethod==="DNS")n.resourceRecords=[{name:`_${Math.random().toString(36).slice(2)}.${a.domainName}`,type:"CNAME",value:`_${Math.random().toString(36).slice(2)}.acm-validations.aws.`}];else n.validationEmails=[`admin@${a.domainName}`,`administrator@${a.domainName}`,`hostmaster@${a.domainName}`];return this.validations.set(a.id,n),n}validateCertificate(a){let n=this.certificates.get(a),i=this.validations.get(a);if(!n||!i)return{success:!1,message:"Certificate or validation not found"};return i.validationStatus="SUCCESS",n.status="ISSUED",n.issuedAt=new Date,n.expiresAt=new Date(Date.now()+31536000000),n.renewalEligibility=!0,n.issuer="Amazon",{success:!0,message:"Certificate validated and issued successfully"}}enableAutoRenewal(a){let n=`renewal-${Date.now()}-${this.renewalCounter++}`,i={id:n,certificateArn:a.certificateArn,autoRenew:!0,renewBeforeDays:a.renewBeforeDays||30};return this.renewals.set(n,i),i}async renewCertificate(a){let n=this.renewals.get(a);if(!n)return{success:!1,message:"Renewal configuration not found"};let i=Array.from(this.certificates.values()).find((s)=>s.arn===n.certificateArn);if(!i)return{success:!1,message:"Certificate not found"};console.log(`
3766
3766
  Renewing certificate: ${i.domainName}`),console.log(`Certificate ARN: ${i.arn}`);try{return console.log(`
3767
3767
  1. Requesting new certificate...`),console.log("2. Validating domain ownership..."),console.log("3. Issuing renewed certificate..."),console.log("4. Updating resource associations..."),i.issuedAt=new Date,i.expiresAt=new Date(Date.now()+31536000000),n.lastRenewal=new Date,n.renewalStatus="success",n.nextRenewal=new Date(i.expiresAt.getTime()-n.renewBeforeDays*24*60*60*1000),console.log(`
3768
3768
  ✓ Certificate renewed successfully`),console.log(` New expiration: ${i.expiresAt.toISOString()}`),console.log(` Next renewal: ${n.nextRenewal.toISOString()}`),{success:!0,message:"Certificate renewed successfully"}}catch(s){return n.renewalStatus="failed",this.createAlert({certificateArn:i.arn,alertType:"renewal_failed",severity:"critical",message:`Certificate renewal failed: ${s}`}),{success:!1,message:s instanceof Error?s.message:String(s)}}}createMonitor(a){let n=`monitor-${Date.now()}-${this.monitorCounter++}`,i={id:n,...a};return this.monitors.set(n,i),i}checkExpiration(){let a=[],n=Date.now();for(let i of this.certificates.values()){if(!i.expiresAt)continue;let s=(i.expiresAt.getTime()-n)/86400000;if(s<0)a.push(this.createAlert({certificateArn:i.arn,alertType:"expired",severity:"critical",message:`Certificate has expired for ${i.domainName}`}));else if(s<30)a.push(this.createAlert({certificateArn:i.arn,alertType:"expiring_soon",severity:s<7?"critical":"warning",message:`Certificate expiring in ${Math.floor(s)} days for ${i.domainName}`}))}return a}createAlert(a){let n=`alert-${Date.now()}-${this.alertCounter++}`,i={id:n,timestamp:new Date,acknowledged:!1,...a};return this.alerts.set(n,i),i}acknowledgeAlert(a){let n=this.alerts.get(a);if(n)n.acknowledged=!0}getCertificate(a){return this.certificates.get(a)}listCertificates(){return Array.from(this.certificates.values())}getExpiringCertificates(a=30){let n=Date.now()+a*24*60*60*1000;return Array.from(this.certificates.values()).filter((i)=>i.expiresAt&&i.expiresAt.getTime()<n)}getValidation(a){return this.validations.get(a)}getRenewal(a){return this.renewals.get(a)}listRenewals(){return Array.from(this.renewals.values())}listAlerts(a=!1){return Array.from(this.alerts.values()).filter((n)=>n.acknowledged===a)}generateCertificateCF(a){return{Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:a.domainName,...a.subjectAlternativeNames&&{SubjectAlternativeNames:a.subjectAlternativeNames},ValidationMethod:a.validationMethod}}}generateExpirationAlarmCF(a){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:a.alarmName,AlarmDescription:`Certificate expiring in ${a.daysBeforeExpiration} days`,MetricName:"DaysToExpiry",Namespace:"AWS/CertificateManager",Statistic:"Minimum",Period:86400,EvaluationPeriods:1,Threshold:a.daysBeforeExpiration,ComparisonOperator:"LessThanThreshold",Dimensions:[{Name:"CertificateArn",Value:a.certificateArn}],...a.snsTopicArn&&{AlarmActions:[a.snsTopicArn]}}}}clear(){this.certificates.clear(),this.renewals.clear(),this.validations.clear(),this.monitors.clear(),this.alerts.clear(),this.certificateCounter=0,this.renewalCounter=0,this.validationCounter=0,this.monitorCounter=0,this.alertCounter=0}}var wC=new vg;class Tg{scans=new Map;findings=new Map;reports=new Map;complianceChecks=new Map;postures=new Map;scanCounter=0;findingCounter=0;reportCounter=0;checkCounter=0;postureCounter=0;createScan(a){let n=`scan-${Date.now()}-${this.scanCounter++}`,i={id:n,status:"queued",findings:[],...a};return this.scans.set(n,i),i}createContainerScan(a){return this.createScan({name:a.name,scanType:"container_image",target:{type:"ecr_image",identifier:a.imageUri,region:a.region||"us-east-1"}})}createLambdaScan(a){return this.createScan({name:a.name,scanType:"vulnerability",target:{type:"lambda",identifier:a.functionName,region:a.region||"us-east-1"}})}createSecretsDetectionScan(a){return this.createScan({name:a.name,scanType:"secrets_detection",target:{type:"repository",identifier:a.repositoryUrl}})}async executeScan(a){let n=this.scans.get(a);if(!n)throw Error(`Scan not found: ${a}`);console.log(`
@@ -3773,7 +3773,7 @@ Scanning image: ${i}`),console.log(`Scanner: ${n.scanner}`);let s=`scan-result-$
3773
3773
  Scan Results:`),console.log(` Total vulnerabilities: ${l.total}`),console.log(` Critical: ${l.critical}`),console.log(` High: ${l.high}`),console.log(` Medium: ${l.medium}`),console.log(` Low: ${l.low}`),console.log(` Status: ${u?"✓ PASSED":"✗ FAILED"}`),h}simulateVulnerabilities(a){let n=[];if(a.scanner==="trivy"||a.scanner==="ecr")n.push({id:"vuln-1",cve:"CVE-2024-1234",severity:"HIGH",packageName:"openssl",installedVersion:"1.1.1k",fixedVersion:"1.1.1l",title:"OpenSSL buffer overflow",description:"Buffer overflow vulnerability in OpenSSL",references:["https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-1234"],cvss:7.5}),n.push({id:"vuln-2",cve:"CVE-2024-5678",severity:"MEDIUM",packageName:"curl",installedVersion:"7.68.0",fixedVersion:"7.79.0",title:"curl remote code execution",description:"Remote code execution in curl",references:["https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-5678"],cvss:5.3});return n}evaluateScanResult(a,n){if(!a.failOnSeverity)return!0;switch(a.failOnSeverity){case"CRITICAL":return n.critical===0;case"HIGH":return n.critical===0&&n.high===0;case"MEDIUM":return n.critical===0&&n.high===0&&n.medium===0;case"LOW":return n.total===0;default:return!0}}createPolicy(a){let n=`policy-${Date.now()}-${this.policyCounter++}`,i={id:n,...a};return this.policies.set(n,i),i}createStrictPolicy(a){return this.createPolicy({name:a,allowedSeverities:[],maxCritical:0,maxHigh:0,blockOnFailure:!0,exemptions:[]})}createPermissivePolicy(a){return this.createPolicy({name:a,allowedSeverities:["CRITICAL","HIGH","MEDIUM","LOW"],maxCritical:5,maxHigh:10,blockOnFailure:!1,exemptions:[]})}getConfig(a){return this.configs.get(a)}listConfigs(){return Array.from(this.configs.values())}getResult(a){return this.results.get(a)}listResults(){return Array.from(this.results.values())}generateECRScanCF(a){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:a.repository,ImageScanningConfiguration:{ScanOnPush:a.scanOnPush},ImageTagMutability:"IMMUTABLE",EncryptionConfiguration:{EncryptionType:"AES256"}}}}clear(){this.configs.clear(),this.results.clear(),this.policies.clear(),this.configCounter=0,this.resultCounter=0,this.policyCounter=0}}var DC=new wg;class Rg{configs=new Map;multiStageConfigs=new Map;optimizations=new Map;analyses=new Map;configCounter=0;multiStageCounter=0;optimizationCounter=0;analysisCounter=0;createBuildConfig(a){let n=`build-config-${Date.now()}-${this.configCounter++}`,i={id:n,...a};return this.configs.set(n,i),i}createOptimizedBuildConfig(a){let n={type:a.enableCache?"registry":"inline",cacheFrom:a.registry?[`${a.registry}/cache`]:void 0,cacheTo:a.registry?`${a.registry}/cache`:void 0,maxCacheAge:7};return this.createBuildConfig({name:a.name,dockerfile:a.dockerfile,context:".",cacheStrategy:n,buildArgs:{BUILDKIT_INLINE_CACHE:"1"}})}createMultiStageConfig(a){let n=`multi-stage-${Date.now()}-${this.multiStageCounter++}`,i={id:n,...a};return this.multiStageConfigs.set(n,i),i}createNodeMultiStageBuild(a){let n=a.nodeVersion||"18-alpine";return this.createMultiStageConfig({name:a.name,targetStage:a.targetStage||"production",stages:[{name:"dependencies",baseImage:`node:${n}`,workdir:"/app",commands:["COPY package*.json ./","RUN npm ci --only=production"]},{name:"build",baseImage:`node:${n}`,workdir:"/app",commands:["COPY package*.json ./","RUN npm ci","COPY . .","RUN npm run build"]},{name:"production",baseImage:`node:${n}`,workdir:"/app",copyFrom:["dependencies:/app/node_modules","build:/app/dist"],commands:["COPY package*.json ./","ENV NODE_ENV=production",'CMD ["node", "dist/index.js"]']}]})}generateDockerfile(a){let n=this.multiStageConfigs.get(a);if(!n)throw Error(`Multi-stage config not found: ${a}`);let i=[];for(let s of n.stages){if(i.push(`# Stage: ${s.name}`),i.push(`FROM ${s.baseImage} AS ${s.name}`),s.workdir)i.push(`WORKDIR ${s.workdir}`);if(s.env)for(let[c,l]of Object.entries(s.env))i.push(`ENV ${c}=${l}`);for(let c of s.commands)i.push(c);i.push("")}return i.join(`
3774
3774
  `)}analyzeImage(a,n){let i=`analysis-${Date.now()}-${this.analysisCounter++}`,s=n.map((h)=>({...h,cacheable:this.isLayerCacheable(h.command)})),c=s.reduce((h,y)=>h+y.size,0),l=s.filter((h)=>!h.cacheable&&h.size>100).length,u={id:i,imageId:a,layers:s,totalSize:c,unnecessaryLayers:l};return this.analyses.set(i,u),u}isLayerCacheable(a){let n=["FROM","RUN","COPY","ADD","WORKDIR","ENV"],i=["CMD","ENTRYPOINT","LABEL"];for(let s of n)if(a.startsWith(s))return!0;for(let s of i)if(a.startsWith(s))return!1;return!1}generateOptimizations(a){let n=this.analyses.get(a);if(!n)throw Error(`Analysis not found: ${a}`);let i=`optimization-${Date.now()}-${this.optimizationCounter++}`,s=[],c=n.layers.filter((S)=>S.command.startsWith("RUN"));if(c.length>5)s.push({type:"layer_reduction",priority:"high",title:"Combine RUN commands",description:`${c.length} RUN commands found. Combine them to reduce layers.`,example:"RUN apt-get update && apt-get install -y package1 package2",impact:"Reduce image size by 20-30% and improve build time"});let l=n.layers[0];if(l.command.includes("ubuntu")||l.command.includes("debian"))s.push({type:"base_image",priority:"medium",title:"Use Alpine base image",description:"Switch to Alpine Linux for smaller image size",example:"FROM node:18-alpine",impact:"Reduce image size by 50-70%"});let u=n.layers.filter((S)=>S.command.startsWith("COPY"));if(u.length>0&&u[0].index>3)s.push({type:"cache_optimization",priority:"high",title:"Copy dependencies first",description:"Copy package files before source code to leverage layer caching",example:`COPY package*.json ./
3775
3775
  RUN npm install
3776
- COPY . .`,impact:"Improve build time by 60-80% on subsequent builds"});let h={sizeBefore:n.totalSize,sizeAfter:n.totalSize*0.6,timeBefore:300,timeAfter:120},y={id:i,name:`Optimization for ${n.imageId}`,recommendations:s,estimatedSavings:h};return this.optimizations.set(i,y),y}getBuildConfig(a){return this.configs.get(a)}listBuildConfigs(){return Array.from(this.configs.values())}getMultiStageConfig(a){return this.multiStageConfigs.get(a)}listMultiStageConfigs(){return Array.from(this.multiStageConfigs.values())}getOptimization(a){return this.optimizations.get(a)}listOptimizations(){return Array.from(this.optimizations.values())}clear(){this.configs.clear(),this.multiStageConfigs.clear(),this.optimizations.clear(),this.analyses.clear(),this.configCounter=0,this.multiStageCounter=0,this.optimizationCounter=0,this.analysisCounter=0}}var PC=new Rg;class Dg{registries=new Map;credentials=new Map;registryCounter=0;credentialsCounter=0;createRegistry(a){let n=`registry-${Date.now()}-${this.registryCounter++}`,i={id:n,...a};return this.registries.set(n,i),i}createECRRepository(a){return this.createRegistry({name:a.name,registryType:"ecr",repositoryUri:`123456789012.dkr.ecr.${a.region||"us-east-1"}.amazonaws.com/${a.name}`,region:a.region||"us-east-1",encryption:{encryptionType:a.encryption||"AES256",kmsKeyId:a.kmsKeyId},scanning:{scanOnPush:a.scanOnPush??!0}})}createManagedRepository(a){let n=this.createECRRepository({name:a.name,region:a.region,scanOnPush:!0,encryption:"KMS"});return n.lifecycle={id:`lifecycle-${Date.now()}`,rules:[{rulePriority:1,description:"Keep only last N images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:a.maxImageCount||10},action:{type:"expire"}},{rulePriority:2,description:"Remove images older than N days",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:a.maxImageAgeDays||30,countUnit:"days"},action:{type:"expire"}}]},n}enableReplication(a,n){let i=this.registries.get(a);if(!i)throw Error(`Registry not found: ${a}`);return i.replication={enabled:!0,destinations:n},i}createCredentials(a){let n=`creds-${Date.now()}-${this.credentialsCounter++}`,i={id:n,...a};return this.credentials.set(n,i),i}getRegistry(a){return this.registries.get(a)}listRegistries(){return Array.from(this.registries.values())}generateECRRepositoryCF(a){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:a.name,ImageScanningConfiguration:{ScanOnPush:a.scanning?.scanOnPush??!1},EncryptionConfiguration:{EncryptionType:a.encryption?.encryptionType||"AES256",...a.encryption?.kmsKeyId&&{KmsKey:a.encryption.kmsKeyId}},ImageTagMutability:"MUTABLE",...a.lifecycle&&{LifecyclePolicy:{LifecyclePolicyText:JSON.stringify({rules:a.lifecycle.rules})}}}}}generateReplicationConfigCF(a){return{Type:"AWS::ECR::ReplicationConfiguration",Properties:{ReplicationConfiguration:{Rules:a.destinations.map((n)=>({Destinations:[{Region:n.region,...n.registryId&&{RegistryId:n.registryId}}]}))}}}}clear(){this.registries.clear(),this.credentials.clear(),this.registryCounter=0,this.credentialsCounter=0}}var NC=new Dg;class Pg{meshes=new Map;virtualNodes=new Map;virtualRouters=new Map;virtualGateways=new Map;meshCounter=0;nodeCounter=0;routerCounter=0;gatewayCounter=0;createMesh(a){let n=`mesh-${Date.now()}-${this.meshCounter++}`,i={id:n,...a};return this.meshes.set(n,i),i}createAppMesh(a){return this.createMesh({name:a.name,meshType:"app_mesh",services:a.services,virtualNodes:[],virtualRouters:[],virtualGateways:[]})}createVirtualNode(a){let n=`vnode-${Date.now()}-${this.nodeCounter++}`,i={id:n,...a};return this.virtualNodes.set(n,i),i}createHTTPVirtualNode(a){return this.createVirtualNode({name:a.name,serviceName:a.serviceName,listeners:[{port:a.port,protocol:"http",healthCheck:{protocol:"http",path:"/health",interval:30,timeout:10,healthyThreshold:2,unhealthyThreshold:3},timeout:{perRequest:15000,idle:300000}}],serviceDiscovery:{type:"aws_cloud_map",namespace:a.namespace,serviceName:a.serviceName}})}createVirtualRouter(a){let n=`vrouter-${Date.now()}-${this.routerCounter++}`,i={id:n,...a};return this.virtualRouters.set(n,i),i}createCanaryRoute(a){return this.createVirtualRouter({name:a.name,listeners:[{port:a.port,protocol:a.protocol}],routes:[{name:"canary-route",match:{prefix:"/"},action:{weightedTargets:[{virtualNode:a.stableTarget,weight:100-a.canaryWeight},{virtualNode:a.canaryTarget,weight:a.canaryWeight}]},retryPolicy:{maxRetries:3,perRetryTimeout:5000,httpRetryEvents:["server-error","gateway-error"],tcpRetryEvents:["connection-error"]}}]})}createVirtualGateway(a){let n=`vgateway-${Date.now()}-${this.gatewayCounter++}`,i={id:n,...a};return this.virtualGateways.set(n,i),i}createIngressGateway(a){let n={port:a.port,protocol:"http",healthCheck:{protocol:"http",path:"/health",interval:30,timeout:10,healthyThreshold:2,unhealthyThreshold:3}};if(a.enableTLS&&a.certificateArn)n.tls={mode:"STRICT",certificate:{acm:a.certificateArn}};return this.createVirtualGateway({name:a.name,listeners:[n],logging:{accessLog:{file:{path:"/dev/stdout"}}}})}getMesh(a){return this.meshes.get(a)}listMeshes(){return Array.from(this.meshes.values())}getVirtualNode(a){return this.virtualNodes.get(a)}listVirtualNodes(){return Array.from(this.virtualNodes.values())}generateMeshCF(a){return{Type:"AWS::AppMesh::Mesh",Properties:{MeshName:a.name,Spec:{EgressFilter:{Type:"ALLOW_ALL"}}}}}generateVirtualNodeCF(a,n){return{Type:"AWS::AppMesh::VirtualNode",Properties:{MeshName:n,VirtualNodeName:a.name,Spec:{Listeners:a.listeners.map((i)=>({PortMapping:{Port:i.port,Protocol:i.protocol},...i.healthCheck&&{HealthCheck:{Protocol:i.healthCheck.protocol,...i.healthCheck.path&&{Path:i.healthCheck.path},IntervalMillis:i.healthCheck.interval*1000,TimeoutMillis:i.healthCheck.timeout*1000,HealthyThreshold:i.healthCheck.healthyThreshold,UnhealthyThreshold:i.healthCheck.unhealthyThreshold}}})),ServiceDiscovery:{AWSCloudMap:{NamespaceName:a.serviceDiscovery.namespace,ServiceName:a.serviceDiscovery.serviceName}}}}}}generateVirtualRouterCF(a,n){return{Type:"AWS::AppMesh::VirtualRouter",Properties:{MeshName:n,VirtualRouterName:a.name,Spec:{Listeners:a.listeners.map((i)=>({PortMapping:{Port:i.port,Protocol:i.protocol}}))}}}}clear(){this.meshes.clear(),this.virtualNodes.clear(),this.virtualRouters.clear(),this.virtualGateways.clear(),this.meshCounter=0,this.nodeCounter=0,this.routerCounter=0,this.gatewayCounter=0}}var kC=new Pg;class Ng{layers=new Map;versions=new Map;permissions=new Map;layerCounter=0;versionCounter=0;permissionCounter=0;createLayer(a){let n=`layer-${Date.now()}-${this.layerCounter++}`,i=1,s={id:n,layerArn:`arn:aws:lambda:us-east-1:123456789012:layer:${a.layerName}:1`,version:1,...a};return this.layers.set(n,s),s}createNodeDependenciesLayer(a){return this.createLayer({layerName:a.layerName,description:"Node.js dependencies layer",compatibleRuntimes:[`nodejs${a.nodeVersion}`],content:{type:"s3",s3Bucket:a.s3Bucket,s3Key:a.s3Key},size:5242880})}createUtilitiesLayer(a){return this.createLayer({layerName:a.layerName,description:"Shared utilities and helpers",compatibleRuntimes:a.runtimes,content:{type:"s3",s3Bucket:a.s3Bucket,s3Key:a.s3Key},size:1048576})}publishVersion(a){let n=this.layers.get(a);if(!n)throw Error(`Layer not found: ${a}`);let i=`version-${Date.now()}-${this.versionCounter++}`,s=n.version+1,c={id:i,layerName:n.layerName,version:s,createdAt:new Date,compatibleRuntimes:n.compatibleRuntimes,size:n.size,codeHash:this.generateHash()};return this.versions.set(i,c),n.version=s,n.layerArn=`arn:aws:lambda:us-east-1:123456789012:layer:${n.layerName}:${s}`,c}addPermission(a){let n=`permission-${Date.now()}-${this.permissionCounter++}`,i={id:n,layerName:a.layerName,version:a.version,principal:a.principal,action:"lambda:GetLayerVersion",organizationId:a.organizationId};return this.permissions.set(n,i),i}generateHash(){return Math.random().toString(36).substring(2,15)}getLayer(a){return this.layers.get(a)}listLayers(){return Array.from(this.layers.values())}getLayerVersions(a){return Array.from(this.versions.values()).filter((n)=>n.layerName===a)}generateLayerCF(a){return{Type:"AWS::Lambda::LayerVersion",Properties:{LayerName:a.layerName,Description:a.description,Content:a.content.type==="s3"?{S3Bucket:a.content.s3Bucket,S3Key:a.content.s3Key,...a.content.s3ObjectVersion&&{S3ObjectVersion:a.content.s3ObjectVersion}}:{ZipFile:a.content.zipFile},CompatibleRuntimes:a.compatibleRuntimes,...a.licenseInfo&&{LicenseInfo:a.licenseInfo}}}}generateLayerPermissionCF(a){return{Type:"AWS::Lambda::LayerVersionPermission",Properties:{LayerVersionArn:`arn:aws:lambda:us-east-1:123456789012:layer:${a.layerName}:${a.version}`,Action:a.action,Principal:a.principal,...a.organizationId&&{OrganizationId:a.organizationId}}}}clear(){this.layers.clear(),this.versions.clear(),this.permissions.clear(),this.layerCounter=0,this.versionCounter=0,this.permissionCounter=0}}var BC=new Ng;class kg{versions=new Map;aliases=new Map;deployments=new Map;versionCounter=0;aliasCounter=0;deploymentCounter=0;publishVersion(a){let n=`version-${Date.now()}-${this.versionCounter++}`,i=this.getNextVersionNumber(a.functionName),s={id:n,functionName:a.functionName,version:i.toString(),functionArn:`arn:aws:lambda:us-east-1:123456789012:function:${a.functionName}:${i}`,codeHash:this.generateHash(),description:a.description,runtime:a.runtime,memorySize:a.memorySize,timeout:a.timeout,publishedAt:new Date};return this.versions.set(n,s),s}getNextVersionNumber(a){let n=Array.from(this.versions.values()).filter((i)=>i.functionName===a).map((i)=>parseInt(i.version));return n.length>0?Math.max(...n)+1:1}createAlias(a){let n=`alias-${Date.now()}-${this.aliasCounter++}`,i={id:n,aliasArn:`arn:aws:lambda:us-east-1:123456789012:function:${a.functionName}:${a.aliasName}`,revisionId:this.generateHash(),...a};return this.aliases.set(n,i),i}createProductionAlias(a){return this.createAlias({functionName:a.functionName,aliasName:"production",functionVersion:a.version,description:"Production alias"})}createStagingAlias(a){return this.createAlias({functionName:a.functionName,aliasName:"staging",functionVersion:a.version,description:"Staging alias"})}updateAlias(a,n){let i=this.aliases.get(a);if(!i)throw Error(`Alias not found: ${a}`);return i.functionVersion=n,i.revisionId=this.generateHash(),i}configureWeightedRouting(a,n){let i=this.aliases.get(a);if(!i)throw Error(`Alias not found: ${a}`);return i.routingConfig={additionalVersionWeights:n},i}createCanaryDeployment(a){let n=`deployment-${Date.now()}-${this.deploymentCounter++}`,i=Array.from(this.aliases.values()).find((c)=>c.functionName===a.functionName&&c.aliasName===a.aliasName);if(!i)i=this.createAlias({functionName:a.functionName,aliasName:a.aliasName,functionVersion:a.fromVersion});this.configureWeightedRouting(i.id,{[a.toVersion]:a.canaryWeight});let s={id:n,functionName:a.functionName,fromVersion:a.fromVersion,toVersion:a.toVersion,aliasName:a.aliasName,strategy:"canary",status:"in_progress",startedAt:new Date};return this.deployments.set(n,s),s}completeDeployment(a){let n=this.deployments.get(a);if(!n)throw Error(`Deployment not found: ${a}`);let i=Array.from(this.aliases.values()).find((s)=>s.functionName===n.functionName&&s.aliasName===n.aliasName);if(i)i.functionVersion=n.toVersion,i.routingConfig=void 0;return n.status="completed",n.completedAt=new Date,n}rollbackDeployment(a){let n=this.deployments.get(a);if(!n)throw Error(`Deployment not found: ${a}`);let i=Array.from(this.aliases.values()).find((s)=>s.functionName===n.functionName&&s.aliasName===n.aliasName);if(i)i.functionVersion=n.fromVersion,i.routingConfig=void 0;return n.status="failed",n.completedAt=new Date,n}generateHash(){return Math.random().toString(36).substring(2,15)}getVersion(a){return this.versions.get(a)}listVersions(a){let n=Array.from(this.versions.values());return a?n.filter((i)=>i.functionName===a):n}getAlias(a){return this.aliases.get(a)}listAliases(a){let n=Array.from(this.aliases.values());return a?n.filter((i)=>i.functionName===a):n}generateVersionCF(a){return{Type:"AWS::Lambda::Version",Properties:{FunctionName:a.functionName,Description:a.description}}}generateAliasCF(a){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:a.functionName,Name:a.aliasName,FunctionVersion:a.functionVersion,Description:a.description,...a.routingConfig&&{RoutingConfig:{AdditionalVersionWeights:Object.entries(a.routingConfig.additionalVersionWeights||{}).map(([n,i])=>({FunctionVersion:n,FunctionWeight:i}))}}}}}clear(){this.versions.clear(),this.aliases.clear(),this.deployments.clear(),this.versionCounter=0,this.aliasCounter=0,this.deploymentCounter=0}}var xC=new kg;class Bg{configs=new Map;provisionedConfigs=new Map;schedules=new Map;autoScalingConfigs=new Map;configCounter=0;provisionedCounter=0;scheduleCounter=0;autoScalingCounter=0;setReservedConcurrency(a){let n=`concurrency-${Date.now()}-${this.configCounter++}`,i={id:n,functionName:a.functionName,reservedConcurrency:a.reservedConcurrency};return this.configs.set(n,i),i}setProvisionedConcurrency(a){let n=`provisioned-${Date.now()}-${this.provisionedCounter++}`,i={id:n,functionName:a.functionName,qualifier:a.qualifier,provisionedConcurrentExecutions:a.provisionedConcurrentExecutions,status:"pending",lastModified:new Date};return this.provisionedConfigs.set(n,i),setTimeout(()=>{i.status="ready",i.allocatedConcurrency=a.provisionedConcurrentExecutions,i.availableConcurrency=a.provisionedConcurrentExecutions},100),i}configureWarmPool(a){return this.setProvisionedConcurrency({functionName:a.functionName,qualifier:a.alias,provisionedConcurrentExecutions:a.minInstances})}createSchedule(a){let n=`schedule-${Date.now()}-${this.scheduleCounter++}`,i={id:n,...a};return this.schedules.set(n,i),i}createBusinessHoursSchedule(a){return this.createSchedule({name:`${a.functionName}-business-hours`,functionName:a.functionName,qualifier:a.qualifier,schedule:[{name:"business-hours",cronExpression:"0 8 * * MON-FRI",targetConcurrency:a.businessHoursConcurrency},{name:"off-hours",cronExpression:"0 18 * * MON-FRI",targetConcurrency:a.offHoursConcurrency},{name:"weekend",cronExpression:"0 0 * * SAT",targetConcurrency:a.offHoursConcurrency}]})}configureAutoScaling(a){let n=`autoscaling-${Date.now()}-${this.autoScalingCounter++}`,i={id:n,...a};return this.autoScalingConfigs.set(n,i),i}configurePredictiveScaling(a){return this.configureAutoScaling({functionName:a.functionName,qualifier:a.qualifier,minCapacity:a.baselineCapacity,maxCapacity:a.peakCapacity,targetUtilization:0.7,scaleInCooldown:300,scaleOutCooldown:60})}getConfig(a){return this.configs.get(a)}listConfigs(){return Array.from(this.configs.values())}getProvisionedConfig(a){return this.provisionedConfigs.get(a)}listProvisionedConfigs(){return Array.from(this.provisionedConfigs.values())}generateReservedConcurrencyCF(a){return{Type:"AWS::Lambda::Function",Properties:{FunctionName:a.functionName,ReservedConcurrentExecutions:a.reservedConcurrency}}}generateProvisionedConcurrencyCF(a){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:a.functionName,Name:a.qualifier,ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:a.provisionedConcurrentExecutions}}}}generateAutoScalingTargetCF(a){return{Type:"AWS::ApplicationAutoScaling::ScalableTarget",Properties:{ServiceNamespace:"lambda",ResourceId:`function:${a.functionName}:${a.qualifier}`,ScalableDimension:"lambda:function:ProvisionedConcurrentExecutions",MinCapacity:a.minCapacity,MaxCapacity:a.maxCapacity}}}generateAutoScalingPolicyCF(a){return{Type:"AWS::ApplicationAutoScaling::ScalingPolicy",Properties:{PolicyName:`${a.functionName}-autoscaling`,PolicyType:"TargetTrackingScaling",ScalingTargetId:{Ref:`${a.functionName}AutoScalingTarget`},TargetTrackingScalingPolicyConfiguration:{TargetValue:a.targetUtilization*100,PredefinedMetricSpecification:{PredefinedMetricType:"LambdaProvisionedConcurrencyUtilization"},ScaleInCooldown:a.scaleInCooldown||300,ScaleOutCooldown:a.scaleOutCooldown||60}}}}clear(){this.configs.clear(),this.provisionedConfigs.clear(),this.schedules.clear(),this.autoScalingConfigs.clear(),this.configCounter=0,this.provisionedCounter=0,this.scheduleCounter=0,this.autoScalingCounter=0}}var _C=new Bg;class xg{destinations=new Map;records=new Map;eventBridgeDestinations=new Map;destinationCounter=0;recordCounter=0;eventBridgeCounter=0;configureDestinations(a){let n=`destination-${Date.now()}-${this.destinationCounter++}`,i={id:n,...a};return this.destinations.set(n,i),i}configureSQSDestination(a){let n={type:"sqs",arn:a.queueArn};return this.configureDestinations({functionName:a.functionName,successDestination:a.onSuccess?n:void 0,failureDestination:a.onFailure?n:void 0,maxEventAge:21600,maxRetries:2})}configureSNSDestination(a){let n={type:"sns",arn:a.topicArn};return this.configureDestinations({functionName:a.functionName,successDestination:a.onSuccess?n:void 0,failureDestination:a.onFailure?n:void 0,maxEventAge:21600,maxRetries:2})}configureEventBridgeDestination(a){let n={type:"eventbridge",arn:a.eventBusArn};return this.configureDestinations({functionName:a.functionName,successDestination:a.onSuccess?n:void 0,failureDestination:a.onFailure?n:void 0,maxEventAge:21600,maxRetries:2})}configureLambdaDestination(a){let n={type:"lambda",arn:a.destinationFunctionArn};return this.configureDestinations({functionName:a.functionName,successDestination:a.onSuccess?n:void 0,failureDestination:a.onFailure?n:void 0,maxEventAge:21600,maxRetries:2})}configureDLQWithNotification(a){return this.configureDestinations({functionName:a.functionName,failureDestination:{type:"sqs",arn:a.dlqArn},maxEventAge:3600,maxRetries:0})}createEventBridgeIntegration(a){let n=`eventbridge-${Date.now()}-${this.eventBridgeCounter++}`,i={id:n,functionName:a.functionName,eventBusArn:a.eventBusArn,detailType:a.detailType||"Lambda Function Invocation Result",source:a.source||`lambda.${a.functionName}`};return this.eventBridgeDestinations.set(n,i),i}sendToDestination(a){let n=Array.from(this.destinations.values()).find((l)=>l.functionName===a.functionName);if(!n)return null;let i=a.status==="success"?n.successDestination:n.failureDestination;if(!i)return null;let s=`record-${Date.now()}-${this.recordCounter++}`,c={id:s,timestamp:new Date,functionName:a.functionName,requestId:a.requestId,status:a.status,destinationType:i.type,destinationArn:i.arn,payload:a.payload,error:a.error};return this.records.set(s,c),c}getDestination(a){return this.destinations.get(a)}listDestinations(a){let n=Array.from(this.destinations.values());return a?n.filter((i)=>i.functionName===a):n}getDestinationRecords(a){let n=Array.from(this.records.values());return a?n.filter((i)=>i.functionName===a):n}generateEventInvokeConfigCF(a){return{Type:"AWS::Lambda::EventInvokeConfig",Properties:{FunctionName:a.functionName,Qualifier:a.qualifier||"$LATEST",MaximumEventAgeInSeconds:a.maxEventAge||21600,MaximumRetryAttempts:a.maxRetries??2,...a.successDestination&&{DestinationConfig:{OnSuccess:{Destination:a.successDestination.arn}}},...a.failureDestination&&{DestinationConfig:{OnFailure:{Destination:a.failureDestination.arn}}}}}}generateEventBridgeRuleCF(a){return{Type:"AWS::Events::Rule",Properties:{EventBusName:a.eventBusArn.split("/").pop(),EventPattern:{source:[a.source],"detail-type":[a.detailType]},State:"ENABLED",Targets:[{Arn:`arn:aws:lambda:us-east-1:123456789012:function:${a.functionName}`,Id:a.id}]}}}clear(){this.destinations.clear(),this.records.clear(),this.eventBridgeDestinations.clear(),this.destinationCounter=0,this.recordCounter=0,this.eventBridgeCounter=0}}var OC=new xg;class _g{vpcConfigs=new Map;endpoints=new Map;networkInterfaces=new Map;connectivity=new Map;configCounter=0;endpointCounter=0;eniCounter=0;connectivityCounter=0;configureVPC(a){let n=`vpc-config-${Date.now()}-${this.configCounter++}`,i={id:n,...a};this.vpcConfigs.set(n,i);for(let s of a.subnetIds)this.createNetworkInterface({functionName:a.functionName,subnetId:s});return i}configurePrivateVPC(a){return this.configureVPC({functionName:a.functionName,vpcId:a.vpcId,subnetIds:a.privateSubnetIds,securityGroupIds:[a.securityGroupId],ipv6Allowed:!1})}configureMultiAZVPC(a){if(a.subnetIds.length<2)throw Error("Multi-AZ configuration requires at least 2 subnets");return this.configureVPC({functionName:a.functionName,vpcId:a.vpcId,subnetIds:a.subnetIds,securityGroupIds:a.securityGroupIds})}createVPCEndpoint(a){let n=`endpoint-${Date.now()}-${this.endpointCounter++}`,i={id:n,...a};return this.endpoints.set(n,i),i}createS3Endpoint(a){return this.createVPCEndpoint({vpcId:a.vpcId,serviceName:"com.amazonaws.us-east-1.s3",endpointType:"Gateway",privateDnsEnabled:!1})}createDynamoDBEndpoint(a){return this.createVPCEndpoint({vpcId:a.vpcId,serviceName:"com.amazonaws.us-east-1.dynamodb",endpointType:"Gateway",privateDnsEnabled:!1})}createSecretsManagerEndpoint(a){return this.createVPCEndpoint({vpcId:a.vpcId,serviceName:"com.amazonaws.us-east-1.secretsmanager",endpointType:"Interface",subnetIds:a.subnetIds,securityGroupIds:a.securityGroupIds,privateDnsEnabled:!0})}createNetworkInterface(a){let n=`eni-${Date.now()}-${this.eniCounter++}`,i={id:n,functionName:a.functionName,networkInterfaceId:`eni-${Math.random().toString(36).substring(2,15)}`,subnetId:a.subnetId,privateIpAddress:`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`,status:"creating",attachedAt:new Date};return this.networkInterfaces.set(n,i),setTimeout(()=>{i.status="available"},100),i}analyzeConnectivity(a){let n=`connectivity-${Date.now()}-${this.connectivityCounter++}`,i=Array.from(this.vpcConfigs.values()).find((y)=>y.functionName===a.functionName),s=Array.from(this.endpoints.values()).filter((y)=>y.vpcId===i?.vpcId).map((y)=>y.serviceName),c=[],l=a.hasNATGateway??!1,u=a.hasInternetGateway??!1;if(!l&&!u)c.push("Add NAT Gateway for internet access");if(!s.includes("com.amazonaws.us-east-1.s3"))c.push("Add S3 VPC endpoint to reduce NAT costs");if(!s.includes("com.amazonaws.us-east-1.dynamodb"))c.push("Add DynamoDB VPC endpoint for private access");let h={id:n,functionName:a.functionName,hasInternetAccess:l||u,hasNATGateway:l,hasVPCEndpoints:s.length>0,endpoints:s,recommendations:c};return this.connectivity.set(n,h),h}getVPCConfig(a){return this.vpcConfigs.get(a)}listVPCConfigs(a){let n=Array.from(this.vpcConfigs.values());return a?n.filter((i)=>i.functionName===a):n}getNetworkInterfaces(a){return Array.from(this.networkInterfaces.values()).filter((n)=>n.functionName===a)}listVPCEndpoints(a){let n=Array.from(this.endpoints.values());return a?n.filter((i)=>i.vpcId===a):n}generateVPCConfigCF(a){return{VpcConfig:{SubnetIds:a.subnetIds,SecurityGroupIds:a.securityGroupIds,...a.ipv6Allowed&&{Ipv6AllowedForDualStack:!0}}}}generateVPCEndpointCF(a){return{Type:"AWS::EC2::VPCEndpoint",Properties:{VpcId:a.vpcId,ServiceName:a.serviceName,VpcEndpointType:a.endpointType,...a.subnetIds&&{SubnetIds:a.subnetIds},...a.securityGroupIds&&{SecurityGroupIds:a.securityGroupIds},...a.privateDnsEnabled!==void 0&&{PrivateDnsEnabled:a.privateDnsEnabled}}}}generateSecurityGroupCF(a){return{Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:a.groupName,GroupDescription:`Security group for Lambda ${a.groupName}`,VpcId:a.vpcId,...a.ingressRules&&{SecurityGroupIngress:a.ingressRules.map((n)=>({IpProtocol:n.protocol,FromPort:n.fromPort,ToPort:n.toPort,...n.cidrIp&&{CidrIp:n.cidrIp},...n.sourceSecurityGroupId&&{SourceSecurityGroupId:n.sourceSecurityGroupId}}))},...a.egressRules&&{SecurityGroupEgress:a.egressRules.map((n)=>({IpProtocol:n.protocol,FromPort:n.fromPort,ToPort:n.toPort,CidrIp:n.cidrIp||"0.0.0.0/0"}))}}}}clear(){this.vpcConfigs.clear(),this.endpoints.clear(),this.networkInterfaces.clear(),this.connectivity.clear(),this.configCounter=0,this.endpointCounter=0,this.eniCounter=0,this.connectivityCounter=0}}var LC=new _g;class Og{dlqConfigs=new Map;messages=new Map;alarms=new Map;reprocessing=new Map;configCounter=0;messageCounter=0;alarmCounter=0;reprocessCounter=0;configureDLQ(a){let n=`dlq-${Date.now()}-${this.configCounter++}`,i={id:n,...a};return this.dlqConfigs.set(n,i),i}configureSQSDLQ(a){return this.configureDLQ({functionName:a.functionName,targetArn:a.queueArn,targetType:"sqs",maxReceiveCount:a.maxReceiveCount||3,retentionPeriod:a.retentionPeriod||1209600})}configureSNSDLQ(a){return this.configureDLQ({functionName:a.functionName,targetArn:a.topicArn,targetType:"sns"})}configureDLQWithAlarm(a){let n=this.configureSQSDLQ({functionName:a.functionName,queueArn:a.queueArn});return this.createDLQAlarm({dlqConfigId:n.id,alarmName:`${a.functionName}-dlq-alarm`,threshold:a.alarmThreshold,evaluationPeriods:1,notificationTopicArn:a.notificationTopicArn,enabled:!0}),n}sendToDLQ(a){let n=`message-${Date.now()}-${this.messageCounter++}`,i={id:n,timestamp:new Date,...a};return this.messages.set(n,i),i}createDLQAlarm(a){let n=`alarm-${Date.now()}-${this.alarmCounter++}`,i={id:n,...a};return this.alarms.set(n,i),i}createAgeAlarm(a){let n=this.dlqConfigs.get(a.dlqConfigId);if(!n)throw Error(`DLQ config not found: ${a.dlqConfigId}`);return this.createDLQAlarm({dlqConfigId:a.dlqConfigId,alarmName:`${n.functionName}-dlq-age-alarm`,threshold:a.maxAgeSeconds,evaluationPeriods:1,notificationTopicArn:a.notificationTopicArn,enabled:!0})}async reprocessMessage(a){let n=this.messages.get(a);if(!n)throw Error(`Message not found: ${a}`);let i=Array.from(this.dlqConfigs.values()).find((l)=>l.functionName===n.functionName);if(!i)throw Error(`DLQ config not found for function: ${n.functionName}`);let s=`reprocess-${Date.now()}-${this.reprocessCounter++}`,c={id:s,dlqConfigId:i.id,messageId:a,status:"pending",startedAt:new Date};return this.reprocessing.set(s,c),setTimeout(()=>{c.status="processing",setTimeout(()=>{let l=Math.random()>0.3;if(c.status=l?"success":"failed",c.completedAt=new Date,!l)c.error="Reprocessing failed - same error occurred";else this.messages.delete(a)},100)},50),c}async batchReprocess(a){let n=this.dlqConfigs.get(a.dlqConfigId);if(!n)throw Error(`DLQ config not found: ${a.dlqConfigId}`);let i=Array.from(this.messages.values()).filter((s)=>s.functionName===n.functionName).slice(0,a.maxMessages||10).map((s)=>this.reprocessMessage(s.id));return Promise.all(i)}getDLQStats(a){let n=this.dlqConfigs.get(a);if(!n)throw Error(`DLQ config not found: ${a}`);let i=Array.from(this.messages.values()).filter((u)=>u.functionName===n.functionName),s={},c=0;for(let u of i)s[u.errorType]=(s[u.errorType]||0)+1,c+=u.attemptCount;let l=i.map((u)=>u.timestamp);return{totalMessages:i.length,oldestMessage:l.length>0?new Date(Math.min(...l.map((u)=>u.getTime()))):void 0,newestMessage:l.length>0?new Date(Math.max(...l.map((u)=>u.getTime()))):void 0,averageAttempts:i.length>0?c/i.length:0,errorTypes:s}}getDLQConfig(a){return this.dlqConfigs.get(a)}listDLQConfigs(){return Array.from(this.dlqConfigs.values())}getDLQMessages(a){let n=this.dlqConfigs.get(a);if(!n)return[];return Array.from(this.messages.values()).filter((i)=>i.functionName===n.functionName)}generateDLQCF(a){return{DeadLetterConfig:{TargetArn:a.targetArn}}}generateSQSDLQCF(a){return{Type:"AWS::SQS::Queue",Properties:{QueueName:`${a.functionName}-dlq`,MessageRetentionPeriod:a.retentionPeriod||1209600,...a.maxReceiveCount&&{RedrivePolicy:{deadLetterTargetArn:a.targetArn,maxReceiveCount:a.maxReceiveCount}}}}}generateDLQAlarmCF(a){let n=this.dlqConfigs.get(a.dlqConfigId);if(!n)throw Error(`DLQ config not found: ${a.dlqConfigId}`);return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:a.alarmName,AlarmDescription:`DLQ alarm for ${n.functionName}`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Sum",Period:300,EvaluationPeriods:a.evaluationPeriods,Threshold:a.threshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:n.targetArn.split(":").pop()}],...a.notificationTopicArn&&{AlarmActions:[a.notificationTopicArn]}}}}clear(){this.dlqConfigs.clear(),this.messages.clear(),this.alarms.clear(),this.reprocessing.clear(),this.configCounter=0,this.messageCounter=0,this.alarmCounter=0,this.reprocessCounter=0}}var $C=new Og;class Lg{policies=new Map;healthChecks=new Map;trafficPolicies=new Map;policyCounter=0;healthCheckCounter=0;trafficPolicyCounter=0;createWeightedPolicy(a){let n=`policy-${Date.now()}-${this.policyCounter++}`,i={id:n,type:"weighted",...a};return this.policies.set(n,i),i}createLatencyPolicy(a){let n=`policy-${Date.now()}-${this.policyCounter++}`,i={id:n,type:"latency",...a};return this.policies.set(n,i),i}createFailoverPolicy(a){let n=`policy-${Date.now()}-${this.policyCounter++}`,i={id:n,type:"failover",...a};return this.policies.set(n,i),i}createGeolocationPolicy(a){let n=`policy-${Date.now()}-${this.policyCounter++}`,i={id:n,type:"geolocation",...a};return this.policies.set(n,i),i}createGeoproximityPolicy(a){let n=`policy-${Date.now()}-${this.policyCounter++}`,i={id:n,type:"geoproximity",...a};return this.policies.set(n,i),i}createHTTPHealthCheck(a){let n=`health-check-${Date.now()}-${this.healthCheckCounter++}`,i={id:n,type:a.port===443?"https":"http",requestInterval:a.requestInterval||30,failureThreshold:a.failureThreshold||3,healthCheckStatus:"Unknown",port:a.port||(a.port===443?443:80),...a};return this.healthChecks.set(n,i),setTimeout(()=>{i.healthCheckStatus=Math.random()>0.2?"Healthy":"Unhealthy"},100),i}createTCPHealthCheck(a){let n=`health-check-${Date.now()}-${this.healthCheckCounter++}`,i={id:n,type:"tcp",fullyQualifiedDomainName:a.ipAddress,requestInterval:a.requestInterval||30,failureThreshold:a.failureThreshold||3,healthCheckStatus:"Unknown",...a};return this.healthChecks.set(n,i),setTimeout(()=>{i.healthCheckStatus=Math.random()>0.1?"Healthy":"Unhealthy"},100),i}createCalculatedHealthCheck(a){let n=`health-check-${Date.now()}-${this.healthCheckCounter++}`,i={id:n,type:"calculated",requestInterval:30,failureThreshold:0,healthCheckStatus:"Unknown",...a};return this.healthChecks.set(n,i),setTimeout(()=>{let s=a.childHealthChecks.filter((c)=>this.healthChecks.get(c)?.healthCheckStatus==="Healthy").length;i.healthCheckStatus=s>=a.healthThreshold?"Healthy":"Unhealthy"},150),i}createTrafficPolicy(a){let n=`traffic-policy-${Date.now()}-${this.trafficPolicyCounter++}`,i={id:n,version:1,...a};return this.trafficPolicies.set(n,i),i}createFailoverTrafficPolicy(a){return this.createTrafficPolicy({name:a.name,document:{recordType:a.recordType||"A",startRule:"failover",endpoints:{primary:{type:"value",value:a.primaryEndpoint},secondary:{type:"value",value:a.secondaryEndpoint}},rules:{failover:{ruleType:"failover",primary:"primary",secondary:"secondary"}}}})}createGeoproximityTrafficPolicy(a){let n={},i=[];return a.locations.forEach((s,c)=>{let l=`endpoint${c}`;n[l]={type:"value",value:s.endpoint},i.push({endpointReference:l,region:s.region,latitude:s.latitude,longitude:s.longitude,bias:s.bias})}),this.createTrafficPolicy({name:a.name,document:{recordType:"A",startRule:"geoproximity",endpoints:n,rules:{geoproximity:{ruleType:"geoproximity",locations:i}}}})}getPolicy(a){return this.policies.get(a)}listPolicies(){return Array.from(this.policies.values())}getHealthCheck(a){return this.healthChecks.get(a)}listHealthChecks(){return Array.from(this.healthChecks.values())}getHealthCheckStatus(a){return this.healthChecks.get(a)?.healthCheckStatus||"Unknown"}generateHealthCheckCF(a){let n={Type:"AWS::Route53::HealthCheck",Properties:{HealthCheckConfig:{Type:a.type.toUpperCase(),RequestInterval:a.requestInterval,FailureThreshold:a.failureThreshold,...a.measureLatency&&{MeasureLatency:!0}},HealthCheckTags:[{Key:"Name",Value:a.name}]}};if(a.type==="calculated"){let i=a;n.Properties.HealthCheckConfig.ChildHealthChecks=i.childHealthChecks,n.Properties.HealthCheckConfig.HealthThreshold=i.healthThreshold}else{if(a.ipAddress)n.Properties.HealthCheckConfig.IPAddress=a.ipAddress;if(a.fullyQualifiedDomainName)n.Properties.HealthCheckConfig.FullyQualifiedDomainName=a.fullyQualifiedDomainName;if(a.port)n.Properties.HealthCheckConfig.Port=a.port;if(a.resourcePath)n.Properties.HealthCheckConfig.ResourcePath=a.resourcePath;if(a.enableSNI)n.Properties.HealthCheckConfig.EnableSNI=!0}return n}generateWeightedRecordSetCF(a){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:a.hostedZoneId,Name:a.name,Type:a.type,TTL:a.ttl,ResourceRecords:a.resourceRecords,Weight:a.weight,SetIdentifier:a.setIdentifier,...a.healthCheckId&&{HealthCheckId:a.healthCheckId}}}}generateFailoverRecordSetCF(a){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:a.hostedZoneId,Name:a.name,Type:a.type,TTL:a.ttl,ResourceRecords:a.resourceRecords,Failover:a.failover,SetIdentifier:a.setIdentifier,...a.healthCheckId&&{HealthCheckId:a.healthCheckId}}}}clear(){this.policies.clear(),this.healthChecks.clear(),this.trafficPolicies.clear(),this.policyCounter=0,this.healthCheckCounter=0,this.trafficPolicyCounter=0}}var MC=new Lg;class $g{configs=new Map;ksks=new Map;validations=new Map;configCounter=0;kskCounter=0;validationCounter=0;enableDNSSEC(a){let n=`dnssec-${Date.now()}-${this.configCounter++}`,i={id:n,hostedZoneId:a.hostedZoneId,status:"SIGNING",signingStatus:"Initializing DNSSEC signing"};if(this.configs.set(n,i),a.kmsKeyArn)this.createKSK({name:`ksk-${a.hostedZoneId}`,hostedZoneId:a.hostedZoneId,kmsKeyArn:a.kmsKeyArn});return setTimeout(()=>{i.status="SIGNED",i.signingStatus="DNSSEC signing complete"},100),i}disableDNSSEC(a){let n=this.configs.get(a);if(!n)throw Error(`DNSSEC config not found: ${a}`);return n.status="DELETING",n.signingStatus="Removing DNSSEC signing",setTimeout(()=>{n.status="NOT_SIGNING",n.signingStatus="DNSSEC signing removed"},100),n}createKSK(a){let n=`ksk-${Date.now()}-${this.kskCounter++}`,i={id:n,status:"ACTIVE",flag:257,keyManagementServiceArn:a.kmsKeyArn,digestAlgorithm:2,keyTag:Math.floor(Math.random()*65535),publicKey:this.generatePublicKey(),...a};i.dnskeyRecord=`${i.flag} 3 8 ${i.publicKey}`;let s=this.generateDigest(i.dnskeyRecord);return i.digestValue=s,i.dsRecord=`${i.keyTag} 8 ${i.digestAlgorithm} ${s}`,this.ksks.set(n,i),i}deactivateKSK(a){let n=this.ksks.get(a);if(!n)throw Error(`KSK not found: ${a}`);return n.status="INACTIVE",n}validateDNSSEC(a){let n=`validation-${Date.now()}-${this.validationCounter++}`,i=a.checkDNSKEY!==!1?Math.random()>0.1:!1,s=a.checkRRSIG!==!1?Math.random()>0.1:!1,c=i&&s,l=[];if(!i)l.push("DNSKEY record not found");if(!s)l.push("RRSIG record not found");let u;if(!i&&!s)u="INSECURE";else if(i&&s&&c)u="VALID";else if(i||s)u="BOGUS",l.push("Invalid signature or incomplete DNSSEC chain");else u="INVALID";let h={id:n,domain:a.domain,validationStatus:u,dnskeyPresent:i,rrsigPresent:s,validSignature:c,errors:l};return this.validations.set(n,h),h}getDNSSECConfig(a){return this.configs.get(a)}listDNSSECConfigs(){return Array.from(this.configs.values())}getKSK(a){return this.ksks.get(a)}listKSKs(a){let n=Array.from(this.ksks.values());return a?n.filter((i)=>i.hostedZoneId===a):n}getDSRecord(a){let n=this.ksks.get(a);if(!n||!n.dsRecord)throw Error("DS record not available");return n.dsRecord}generatePublicKey(){let a="";for(let n=0;n<256;n++)a+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(Math.floor(Math.random()*64));return a}generateDigest(a){let n="";for(let i=0;i<64;i++)n+="0123456789ABCDEF".charAt(Math.floor(Math.random()*16));return n}generateDNSSECCF(a){return{Type:"AWS::Route53::DNSSEC",Properties:{HostedZoneId:a.hostedZoneId}}}generateKSKCF(a){return{Type:"AWS::Route53::KeySigningKey",Properties:{Name:a.name,HostedZoneId:a.hostedZoneId,KeyManagementServiceArn:a.keyManagementServiceArn,Status:a.status}}}clear(){this.configs.clear(),this.ksks.clear(),this.validations.clear(),this.configCounter=0,this.kskCounter=0,this.validationCounter=0}}var FC=new $g;class Mg{endpoints=new Map;rules=new Map;firewalls=new Map;ruleGroups=new Map;domainLists=new Map;endpointCounter=0;ruleCounter=0;firewallCounter=0;ruleGroupCounter=0;domainListCounter=0;createResolverEndpoint(a){let n=`endpoint-${Date.now()}-${this.endpointCounter++}`,i={id:n,status:"CREATING",...a};return this.endpoints.set(n,i),setTimeout(()=>{i.status="OPERATIONAL",i.ipAddresses.forEach((s)=>{if(!s.ip)s.ip=`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`})},100),i}createInboundEndpoint(a){return this.createResolverEndpoint({name:a.name,direction:"INBOUND",ipAddresses:a.subnetIds.map((n)=>({subnetId:n})),securityGroupIds:a.securityGroupIds})}createOutboundEndpoint(a){return this.createResolverEndpoint({name:a.name,direction:"OUTBOUND",ipAddresses:a.subnetIds.map((n)=>({subnetId:n})),securityGroupIds:a.securityGroupIds})}createResolverRule(a){let n=`rule-${Date.now()}-${this.ruleCounter++}`,i={id:n,status:"CREATING",...a};return this.rules.set(n,i),setTimeout(()=>{i.status="COMPLETE"},100),i}createForwardRule(a){return this.createResolverRule({name:a.name,ruleType:"FORWARD",domainName:a.domainName,targetIps:a.targetIps,resolverEndpointId:a.resolverEndpointId})}createSystemRule(a){return this.createResolverRule({name:a.name,ruleType:"SYSTEM",domainName:a.domainName})}createFirewallDomainList(a){let n=`domain-list-${Date.now()}-${this.domainListCounter++}`,i={id:n,status:"CREATING",...a};return this.domainLists.set(n,i),setTimeout(()=>{i.status="COMPLETE"},100),i}createFirewallRuleGroup(a){let n=`rule-group-${Date.now()}-${this.ruleGroupCounter++}`,i={id:n,name:a.name,rules:a.rules.map((s,c)=>({id:`rule-${n}-${c}`,...s})),shareStatus:"NOT_SHARED"};return this.ruleGroups.set(n,i),i}createBlockRule(a){return this.createFirewallRuleGroup({name:a.name,rules:[{name:a.name,priority:a.priority,action:"BLOCK",blockResponse:a.blockResponse||"NODATA",blockOverrideDomain:a.blockOverrideDomain,firewallDomainListId:a.domainListId}]})}createAllowRule(a){return this.createFirewallRuleGroup({name:a.name,rules:[{name:a.name,priority:a.priority,action:"ALLOW",firewallDomainListId:a.domainListId}]})}createDNSFirewall(a){let n=`firewall-${Date.now()}-${this.firewallCounter++}`,i={id:n,name:a.name,firewallRuleGroupAssociations:a.ruleGroupAssociations.map((s,c)=>({id:`assoc-${n}-${c}`,vpcId:a.vpcId,firewallRuleGroupId:s.firewallRuleGroupId,priority:s.priority,mutationProtection:s.mutationProtection||"DISABLED",status:"COMPLETE"}))};return this.firewalls.set(n,i),i}createMalwareProtectionFirewall(a){let n=this.createFirewallDomainList({name:`${a.name}-malware-domains`,domains:a.maliciousDomains}),i=this.createBlockRule({name:`${a.name}-block-malware`,priority:100,domainListId:n.id,blockResponse:"NXDOMAIN"});return this.createDNSFirewall({name:a.name,vpcId:a.vpcId,ruleGroupAssociations:[{firewallRuleGroupId:i.id,priority:100,mutationProtection:"ENABLED"}]})}getEndpoint(a){return this.endpoints.get(a)}listEndpoints(a){let n=Array.from(this.endpoints.values());return a?n.filter((i)=>i.direction===a):n}getRule(a){return this.rules.get(a)}listRules(){return Array.from(this.rules.values())}getFirewall(a){return this.firewalls.get(a)}listFirewalls(){return Array.from(this.firewalls.values())}generateResolverEndpointCF(a){return{Type:"AWS::Route53Resolver::ResolverEndpoint",Properties:{Name:a.name,Direction:a.direction,IpAddresses:a.ipAddresses.map((n)=>({SubnetId:n.subnetId,...n.ip&&{Ip:n.ip}})),SecurityGroupIds:a.securityGroupIds}}}generateResolverRuleCF(a){return{Type:"AWS::Route53Resolver::ResolverRule",Properties:{Name:a.name,RuleType:a.ruleType,DomainName:a.domainName,...a.targetIps&&{TargetIps:a.targetIps.map((n)=>({Ip:n.ip,Port:n.port||53}))},...a.resolverEndpointId&&{ResolverEndpointId:a.resolverEndpointId}}}}generateFirewallRuleGroupCF(a){return{Type:"AWS::Route53Resolver::FirewallRuleGroup",Properties:{Name:a.name,FirewallRules:a.rules.map((n)=>({Name:n.name,Priority:n.priority,Action:n.action,FirewallDomainListId:n.firewallDomainListId,...n.blockResponse&&{BlockResponse:n.blockResponse},...n.blockOverrideDomain&&{BlockOverrideDomain:n.blockOverrideDomain},...n.blockOverrideTTL&&{BlockOverrideTtl:n.blockOverrideTTL}}))}}}clear(){this.endpoints.clear(),this.rules.clear(),this.firewalls.clear(),this.ruleGroups.clear(),this.domainLists.clear(),this.endpointCounter=0,this.ruleCounter=0,this.firewallCounter=0,this.ruleGroupCounter=0,this.domainListCounter=0}}var UC=new Mg;class Fg{bounces=new Map;complaints=new Map;handlers=new Map;suppressionList=new Map;metrics=new Map;bounceCounter=0;complaintCounter=0;handlerCounter=0;suppressionCounter=0;metricsCounter=0;recordBounce(a){let n=`bounce-${Date.now()}-${this.bounceCounter++}`,i={id:n,...a};if(this.bounces.set(n,i),a.bounceType==="Permanent")this.addToSuppressionList({emailAddress:a.recipient,reason:"BOUNCE"});return i}recordComplaint(a){let n=`complaint-${Date.now()}-${this.complaintCounter++}`,i={id:n,...a};this.complaints.set(n,i);for(let s of a.recipients)this.addToSuppressionList({emailAddress:s,reason:"COMPLAINT"});return i}createBounceHandler(a){let n=`handler-${Date.now()}-${this.handlerCounter++}`,i={id:n,...a};return this.handlers.set(n,i),i}createAutomaticBounceHandler(a){return this.createBounceHandler({name:a.name,bounceThreshold:5,complaintThreshold:0.1,suppressionDuration:2592000,autoSuppress:!0,notificationTopicArn:a.notificationTopicArn})}addToSuppressionList(a){let n=`suppression-${Date.now()}-${this.suppressionCounter++}`,i=a.expirationDays?new Date(Date.now()+a.expirationDays*24*60*60*1000):void 0,s={id:n,emailAddress:a.emailAddress,reason:a.reason,suppressedAt:new Date,expiresAt:i,bounceCount:a.reason==="BOUNCE"?1:0,complaintCount:a.reason==="COMPLAINT"?1:0};return this.suppressionList.set(a.emailAddress,s),s}removeFromSuppressionList(a){return this.suppressionList.delete(a)}isSuppressed(a){let n=this.suppressionList.get(a);if(!n)return!1;if(n.expiresAt&&n.expiresAt<new Date)return this.suppressionList.delete(a),!1;return!0}getBounceStatistics(a,n){let i=Array.from(this.bounces.values()).filter((b)=>b.timestamp>=a&&b.timestamp<=n),s=i.length,c=i.filter((b)=>b.bounceType==="Permanent").length,l=i.filter((b)=>b.bounceType==="Transient").length,u=s*10,h=s/u*100,y=new Map;for(let b of i)y.set(b.recipient,(y.get(b.recipient)||0)+1);let S=Array.from(y.entries()).map(([b,A])=>({email:b,count:A})).sort((b,A)=>A.count-b.count).slice(0,10);return{totalBounces:s,permanentBounces:c,transientBounces:l,bounceRate:h,topRecipients:S}}getComplaintStatistics(a,n){let i=Array.from(this.complaints.values()).filter((y)=>y.timestamp>=a&&y.timestamp<=n),s=i.length,c=new Set;for(let y of i)for(let S of y.recipients)c.add(S);let l=c.size,u=s*1000,h=s/u*100;return{totalComplaints:s,uniqueComplainters:l,complaintRate:h}}calculateReputationMetrics(){let a=`metrics-${Date.now()}-${this.metricsCounter++}`,n=new Date,i=new Date(n.getTime()-86400000),s=this.getBounceStatistics(i,n),c=this.getComplaintStatistics(i,n),l;if(s.bounceRate>10||c.complaintRate>0.5)l="Shutdown";else if(s.bounceRate>5||c.complaintRate>0.1)l="Probation";else if(s.bounceRate>2||c.complaintRate>0.05)l="Warning";else l="Good";let u={id:a,timestamp:n,bounceRate:s.bounceRate,complaintRate:c.complaintRate,sendingQuota:50000,maxSendRate:14,sentLast24Hours:s.totalBounces*10,reputationStatus:l};return this.metrics.set(a,u),u}getBounces(a){let n=Array.from(this.bounces.values());return a?n.filter((i)=>i.messageId===a):n}getComplaints(a){let n=Array.from(this.complaints.values());return a?n.filter((i)=>i.messageId===a):n}listSuppressionList(a){let n=Array.from(this.suppressionList.values());return a?n.filter((i)=>i.reason===a):n}generateSNSSubscriptionCF(a){return{Type:"AWS::SNS::Subscription",Properties:{TopicArn:a.topicArn,Endpoint:a.endpoint,Protocol:a.protocol}}}generateEventDestinationCF(a){return{Type:"AWS::SES::ConfigurationSetEventDestination",Properties:{ConfigurationSetName:a.configurationSetName,EventDestination:{Name:a.eventDestinationName,Enabled:!0,MatchingEventTypes:a.eventTypes,...a.snsTopicArn&&{SnsDestination:{TopicARN:a.snsTopicArn}},...a.cloudWatchDestination&&{CloudWatchDestination:a.cloudWatchDestination}}}}}clear(){this.bounces.clear(),this.complaints.clear(),this.handlers.clear(),this.suppressionList.clear(),this.metrics.clear(),this.bounceCounter=0,this.complaintCounter=0,this.handlerCounter=0,this.suppressionCounter=0,this.metricsCounter=0}}var QC=new Fg;class Ug{events=new Map;campaigns=new Map;reports=new Map;abTests=new Map;eventCounter=0;campaignCounter=0;reportCounter=0;abTestCounter=0;trackEvent(a){let n=`event-${Date.now()}-${this.eventCounter++}`,i={id:n,...a};if(this.events.set(n,i),a.tags?.campaignId)this.updateCampaignStats(a.tags.campaignId,a.eventType);return i}trackOpen(a){return this.trackEvent({...a,eventType:"open",timestamp:new Date})}trackClick(a){return this.trackEvent({...a,eventType:"click",timestamp:new Date})}createCampaign(a){let n=`campaign-${Date.now()}-${this.campaignCounter++}`,i={id:n,sentCount:0,deliveredCount:0,openCount:0,clickCount:0,bounceCount:0,complaintCount:0,createdAt:new Date,...a};return this.campaigns.set(n,i),i}updateCampaignStats(a,n){let i=this.campaigns.get(a);if(!i)return;switch(n){case"send":i.sentCount++;break;case"delivery":i.deliveredCount++;break;case"open":i.openCount++;break;case"click":i.clickCount++;break;case"bounce":i.bounceCount++;break;case"complaint":i.complaintCount++;break}}generateReport(a){let n=`report-${Date.now()}-${this.reportCounter++}`,i=Array.from(this.events.values()).filter((P)=>{let V=P.timestamp>=a.startDate&&P.timestamp<=a.endDate,B=!a.campaignId||P.tags?.campaignId===a.campaignId;return V&&B}),s=i.filter((P)=>P.eventType==="send").length,c=i.filter((P)=>P.eventType==="delivery").length,l=i.filter((P)=>P.eventType==="open").length,u=i.filter((P)=>P.eventType==="click").length,h=i.filter((P)=>P.eventType==="bounce").length,y=i.filter((P)=>P.eventType==="complaint").length,S=s>0?c/s*100:0,b=c>0?l/c*100:0,A=c>0?u/c*100:0,C=l>0?u/l*100:0,T=s>0?h/s*100:0,v=c>0?y/c*100:0,w=new Map;for(let P of i)if(P.eventType==="click"){let V=P;w.set(V.link,(w.get(V.link)||0)+1)}let R=Array.from(w.entries()).map(([P,V])=>({link:P,clicks:V})).sort((P,V)=>V.clicks-P.clicks).slice(0,10),k={desktop:0,mobile:0,tablet:0,unknown:0};for(let P of i)if(P.eventType==="open"||P.eventType==="click"){let V=P.userAgent.toLowerCase();if(V.includes("mobile"))k.mobile++;else if(V.includes("tablet"))k.tablet++;else if(V.includes("mozilla"))k.desktop++;else k.unknown++}let W={id:n,campaignId:a.campaignId,startDate:a.startDate,endDate:a.endDate,totalSent:s,totalDelivered:c,totalOpened:l,totalClicked:u,totalBounced:h,totalComplaints:y,deliveryRate:S,openRate:b,clickRate:A,clickToOpenRate:C,bounceRate:T,complaintRate:v,topLinks:R,deviceBreakdown:k,locationBreakdown:{}};return this.reports.set(n,W),W}createABTest(a){let n=`abtest-${Date.now()}-${this.abTestCounter++}`,i={id:n,name:a.name,variants:a.variants.map((s,c)=>({id:`variant-${n}-${c}`,sentCount:0,openCount:0,clickCount:0,conversionCount:0,...s})),status:"draft"};return this.abTests.set(n,i),i}startABTest(a){let n=this.abTests.get(a);if(!n)throw Error(`A/B test not found: ${a}`);return n.status="running",n.startedAt=new Date,n}completeABTest(a){let n=this.abTests.get(a);if(!n)throw Error(`A/B test not found: ${a}`);let i=n.variants[0],s=0;for(let c of n.variants){let l=c.sentCount>0?c.openCount/c.sentCount:0;if(l>s)s=l,i=c}return n.status="completed",n.completedAt=new Date,n.winner=i.id,n}getCampaign(a){return this.campaigns.get(a)}listCampaigns(){return Array.from(this.campaigns.values())}getEvents(a){let n=Array.from(this.events.values());if(a?.messageId)n=n.filter((i)=>i.messageId===a.messageId);if(a?.eventType)n=n.filter((i)=>i.eventType===a.eventType);if(a?.startDate)n=n.filter((i)=>i.timestamp>=a.startDate);if(a?.endDate)n=n.filter((i)=>i.timestamp<=a.endDate);return n}generateTrackingConfigurationCF(a){return{Type:"AWS::SES::ConfigurationSet",Properties:{Name:a.configurationSetName,...a.openTracking&&{TrackingOptions:{CustomRedirectDomain:"tracking.example.com"}}}}}clear(){this.events.clear(),this.campaigns.clear(),this.reports.clear(),this.abTests.clear(),this.eventCounter=0,this.campaignCounter=0,this.reportCounter=0,this.abTestCounter=0}}var HC=new Ug;class Qg{dashboards=new Map;warmupPlans=new Map;domainReputations=new Map;dashboardCounter=0;warmupCounter=0;domainCounter=0;getReputationDashboard(){let a=`dashboard-${Date.now()}-${this.dashboardCounter++}`,n=Math.random()*5,i=Math.random()*0.5,s=Math.floor(Math.random()*10),c=Math.max(0,100-n*10-i*100-s*2),l=[];if(n>2)l.push("Reduce bounce rate by cleaning email list");if(i>0.1)l.push("Review email content and unsubscribe process");if(s>5)l.push("Improve email relevance and targeting");let u={id:a,timestamp:new Date,overallScore:c,bounceRate:n,complaintRate:i,spamReports:s,blacklistStatus:this.checkBlacklists(),dkimStatus:"VERIFIED",spfStatus:"PASS",dmarcStatus:"PASS",sendingLimits:{maxSendRate:14,max24HourSend:50000,sentLast24Hours:12000,remainingQuota:38000,quotaResetTime:new Date(Date.now()+86400000)},recommendations:l};return this.dashboards.set(a,u),u}checkBlacklists(){return["Spamhaus ZEN","Spamcop","SORBS","Barracuda","URIBL"].map((a)=>({listName:a,listed:Math.random()>0.95,delistUrl:`https://www.${a.toLowerCase().replace(/\s/g,"")}.org/delist`}))}createWarmupPlan(a){let n=`warmup-${Date.now()}-${this.warmupCounter++}`,i=[],s=(a.targetDailyLimit-a.initialDailyLimit)/a.durationDays;for(let l=0;l<a.durationDays;l++)i.push(Math.floor(a.initialDailyLimit+s*l));let c={id:n,name:a.name,startDate:new Date,currentDay:1,totalDays:a.durationDays,dailyLimits:i,currentLimit:i[0],status:"active"};return this.warmupPlans.set(n,c),c}createAggressiveWarmupPlan(a){return this.createWarmupPlan({name:a.name,initialDailyLimit:500,targetDailyLimit:50000,durationDays:14})}createConservativeWarmupPlan(a){return this.createWarmupPlan({name:a.name,initialDailyLimit:200,targetDailyLimit:50000,durationDays:30})}advanceWarmupPlan(a){let n=this.warmupPlans.get(a);if(!n)throw Error(`Warmup plan not found: ${a}`);if(n.currentDay<n.totalDays)n.currentDay++,n.currentLimit=n.dailyLimits[n.currentDay-1];if(n.currentDay>=n.totalDays)n.status="completed";return n}trackDomainReputation(a){let n=`domain-${Date.now()}-${this.domainCounter++}`,i=a.delivered/a.totalSent*100,s=a.delivered>0?a.opened/a.delivered*100:0,c=a.delivered>0?a.clicked/a.delivered*100:0,l=a.bounced/a.totalSent*100,u=a.delivered>0?a.complained/a.delivered*100:0,h=s*0.4+c*0.6,y=Math.max(0,100-l*10-u*100+h*0.2),S={id:n,domain:a.domain,reputationScore:y,totalSent:a.totalSent,deliveryRate:i,openRate:s,clickRate:c,bounceRate:l,complaintRate:u,engagementScore:h};return this.domainReputations.set(a.domain,S),S}getDomainReputation(a){return this.domainReputations.get(a)}listDomainReputations(){return Array.from(this.domainReputations.values())}getWarmupPlan(a){return this.warmupPlans.get(a)}listWarmupPlans(){return Array.from(this.warmupPlans.values())}clear(){this.dashboards.clear(),this.warmupPlans.clear(),this.domainReputations.clear(),this.dashboardCounter=0,this.warmupCounter=0,this.domainCounter=0}}var GC=new Qg;class Hg{templates=new Map;versions=new Map;tests=new Map;templateCounter=0;testCounter=0;createTemplate(a){let n=`template-${Date.now()}-${this.templateCounter++}`,i=this.extractVariables(a.subject+a.htmlPart+a.textPart),s={id:n,variables:i,createdAt:new Date,updatedAt:new Date,version:1,...a};return this.templates.set(n,s),this.addVersion({templateId:n,version:1,subject:a.subject,htmlPart:a.htmlPart,textPart:a.textPart,createdBy:"system"}),s}createWelcomeTemplate(a){return this.createTemplate({name:a.name,subject:"Welcome to {{companyName}}!",htmlPart:`
3776
+ COPY . .`,impact:"Improve build time by 60-80% on subsequent builds"});let h={sizeBefore:n.totalSize,sizeAfter:n.totalSize*0.6,timeBefore:300,timeAfter:120},y={id:i,name:`Optimization for ${n.imageId}`,recommendations:s,estimatedSavings:h};return this.optimizations.set(i,y),y}getBuildConfig(a){return this.configs.get(a)}listBuildConfigs(){return Array.from(this.configs.values())}getMultiStageConfig(a){return this.multiStageConfigs.get(a)}listMultiStageConfigs(){return Array.from(this.multiStageConfigs.values())}getOptimization(a){return this.optimizations.get(a)}listOptimizations(){return Array.from(this.optimizations.values())}clear(){this.configs.clear(),this.multiStageConfigs.clear(),this.optimizations.clear(),this.analyses.clear(),this.configCounter=0,this.multiStageCounter=0,this.optimizationCounter=0,this.analysisCounter=0}}var PC=new Rg;class Dg{registries=new Map;credentials=new Map;registryCounter=0;credentialsCounter=0;createRegistry(a){let n=`registry-${Date.now()}-${this.registryCounter++}`,i={id:n,...a};return this.registries.set(n,i),i}createECRRepository(a){return this.createRegistry({name:a.name,registryType:"ecr",repositoryUri:`123456789012.dkr.ecr.${a.region||"us-east-1"}.amazonaws.com/${a.name}`,region:a.region||"us-east-1",encryption:{encryptionType:a.encryption||"AES256",kmsKeyId:a.kmsKeyId},scanning:{scanOnPush:a.scanOnPush??!0}})}createManagedRepository(a){let n=this.createECRRepository({name:a.name,region:a.region,scanOnPush:!0,encryption:"KMS"});return n.lifecycle={id:`lifecycle-${Date.now()}`,rules:[{rulePriority:1,description:"Keep only last N images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:a.maxImageCount||10},action:{type:"expire"}},{rulePriority:2,description:"Remove images older than N days",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:a.maxImageAgeDays||30,countUnit:"days"},action:{type:"expire"}}]},n}enableReplication(a,n){let i=this.registries.get(a);if(!i)throw Error(`Registry not found: ${a}`);return i.replication={enabled:!0,destinations:n},i}createCredentials(a){let n=`creds-${Date.now()}-${this.credentialsCounter++}`,i={id:n,...a};return this.credentials.set(n,i),i}getRegistry(a){return this.registries.get(a)}listRegistries(){return Array.from(this.registries.values())}generateECRRepositoryCF(a){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:a.name,ImageScanningConfiguration:{ScanOnPush:a.scanning?.scanOnPush??!1},EncryptionConfiguration:{EncryptionType:a.encryption?.encryptionType||"AES256",...a.encryption?.kmsKeyId&&{KmsKey:a.encryption.kmsKeyId}},ImageTagMutability:"MUTABLE",...a.lifecycle&&{LifecyclePolicy:{LifecyclePolicyText:JSON.stringify({rules:a.lifecycle.rules})}}}}}generateReplicationConfigCF(a){return{Type:"AWS::ECR::ReplicationConfiguration",Properties:{ReplicationConfiguration:{Rules:a.destinations.map((n)=>({Destinations:[{Region:n.region,...n.registryId&&{RegistryId:n.registryId}}]}))}}}}clear(){this.registries.clear(),this.credentials.clear(),this.registryCounter=0,this.credentialsCounter=0}}var NC=new Dg;class Pg{meshes=new Map;virtualNodes=new Map;virtualRouters=new Map;virtualGateways=new Map;meshCounter=0;nodeCounter=0;routerCounter=0;gatewayCounter=0;createMesh(a){let n=`mesh-${Date.now()}-${this.meshCounter++}`,i={id:n,...a};return this.meshes.set(n,i),i}createAppMesh(a){return this.createMesh({name:a.name,meshType:"app_mesh",services:a.services,virtualNodes:[],virtualRouters:[],virtualGateways:[]})}createVirtualNode(a){let n=`vnode-${Date.now()}-${this.nodeCounter++}`,i={id:n,...a};return this.virtualNodes.set(n,i),i}createHTTPVirtualNode(a){return this.createVirtualNode({name:a.name,serviceName:a.serviceName,listeners:[{port:a.port,protocol:"http",healthCheck:{protocol:"http",path:"/health",interval:30,timeout:10,healthyThreshold:2,unhealthyThreshold:3},timeout:{perRequest:15000,idle:300000}}],serviceDiscovery:{type:"aws_cloud_map",namespace:a.namespace,serviceName:a.serviceName}})}createVirtualRouter(a){let n=`vrouter-${Date.now()}-${this.routerCounter++}`,i={id:n,...a};return this.virtualRouters.set(n,i),i}createCanaryRoute(a){return this.createVirtualRouter({name:a.name,listeners:[{port:a.port,protocol:a.protocol}],routes:[{name:"canary-route",match:{prefix:"/"},action:{weightedTargets:[{virtualNode:a.stableTarget,weight:100-a.canaryWeight},{virtualNode:a.canaryTarget,weight:a.canaryWeight}]},retryPolicy:{maxRetries:3,perRetryTimeout:5000,httpRetryEvents:["server-error","gateway-error"],tcpRetryEvents:["connection-error"]}}]})}createVirtualGateway(a){let n=`vgateway-${Date.now()}-${this.gatewayCounter++}`,i={id:n,...a};return this.virtualGateways.set(n,i),i}createIngressGateway(a){let n={port:a.port,protocol:"http",healthCheck:{protocol:"http",path:"/health",interval:30,timeout:10,healthyThreshold:2,unhealthyThreshold:3}};if(a.enableTLS&&a.certificateArn)n.tls={mode:"STRICT",certificate:{acm:a.certificateArn}};return this.createVirtualGateway({name:a.name,listeners:[n],logging:{accessLog:{file:{path:"/dev/stdout"}}}})}getMesh(a){return this.meshes.get(a)}listMeshes(){return Array.from(this.meshes.values())}getVirtualNode(a){return this.virtualNodes.get(a)}listVirtualNodes(){return Array.from(this.virtualNodes.values())}generateMeshCF(a){return{Type:"AWS::AppMesh::Mesh",Properties:{MeshName:a.name,Spec:{EgressFilter:{Type:"ALLOW_ALL"}}}}}generateVirtualNodeCF(a,n){return{Type:"AWS::AppMesh::VirtualNode",Properties:{MeshName:n,VirtualNodeName:a.name,Spec:{Listeners:a.listeners.map((i)=>({PortMapping:{Port:i.port,Protocol:i.protocol},...i.healthCheck&&{HealthCheck:{Protocol:i.healthCheck.protocol,...i.healthCheck.path&&{Path:i.healthCheck.path},IntervalMillis:i.healthCheck.interval*1000,TimeoutMillis:i.healthCheck.timeout*1000,HealthyThreshold:i.healthCheck.healthyThreshold,UnhealthyThreshold:i.healthCheck.unhealthyThreshold}}})),ServiceDiscovery:{AWSCloudMap:{NamespaceName:a.serviceDiscovery.namespace,ServiceName:a.serviceDiscovery.serviceName}}}}}}generateVirtualRouterCF(a,n){return{Type:"AWS::AppMesh::VirtualRouter",Properties:{MeshName:n,VirtualRouterName:a.name,Spec:{Listeners:a.listeners.map((i)=>({PortMapping:{Port:i.port,Protocol:i.protocol}}))}}}}clear(){this.meshes.clear(),this.virtualNodes.clear(),this.virtualRouters.clear(),this.virtualGateways.clear(),this.meshCounter=0,this.nodeCounter=0,this.routerCounter=0,this.gatewayCounter=0}}var kC=new Pg;class Ng{layers=new Map;versions=new Map;permissions=new Map;layerCounter=0;versionCounter=0;permissionCounter=0;createLayer(a){let n=`layer-${Date.now()}-${this.layerCounter++}`,i=1,s={id:n,layerArn:`arn:aws:lambda:us-east-1:123456789012:layer:${a.layerName}:1`,version:1,...a};return this.layers.set(n,s),s}createNodeDependenciesLayer(a){return this.createLayer({layerName:a.layerName,description:"Node.js dependencies layer",compatibleRuntimes:[`nodejs${a.nodeVersion}`],content:{type:"s3",s3Bucket:a.s3Bucket,s3Key:a.s3Key},size:5242880})}createUtilitiesLayer(a){return this.createLayer({layerName:a.layerName,description:"Shared utilities and helpers",compatibleRuntimes:a.runtimes,content:{type:"s3",s3Bucket:a.s3Bucket,s3Key:a.s3Key},size:1048576})}publishVersion(a){let n=this.layers.get(a);if(!n)throw Error(`Layer not found: ${a}`);let i=`version-${Date.now()}-${this.versionCounter++}`,s=n.version+1,c={id:i,layerName:n.layerName,version:s,createdAt:new Date,compatibleRuntimes:n.compatibleRuntimes,size:n.size,codeHash:this.generateHash()};return this.versions.set(i,c),n.version=s,n.layerArn=`arn:aws:lambda:us-east-1:123456789012:layer:${n.layerName}:${s}`,c}addPermission(a){let n=`permission-${Date.now()}-${this.permissionCounter++}`,i={id:n,layerName:a.layerName,version:a.version,principal:a.principal,action:"lambda:GetLayerVersion",organizationId:a.organizationId};return this.permissions.set(n,i),i}generateHash(){return Math.random().toString(36).substring(2,15)}getLayer(a){return this.layers.get(a)}listLayers(){return Array.from(this.layers.values())}getLayerVersions(a){return Array.from(this.versions.values()).filter((n)=>n.layerName===a)}generateLayerCF(a){return{Type:"AWS::Lambda::LayerVersion",Properties:{LayerName:a.layerName,Description:a.description,Content:a.content.type==="s3"?{S3Bucket:a.content.s3Bucket,S3Key:a.content.s3Key,...a.content.s3ObjectVersion&&{S3ObjectVersion:a.content.s3ObjectVersion}}:{ZipFile:a.content.zipFile},CompatibleRuntimes:a.compatibleRuntimes,...a.licenseInfo&&{LicenseInfo:a.licenseInfo}}}}generateLayerPermissionCF(a){return{Type:"AWS::Lambda::LayerVersionPermission",Properties:{LayerVersionArn:`arn:aws:lambda:us-east-1:123456789012:layer:${a.layerName}:${a.version}`,Action:a.action,Principal:a.principal,...a.organizationId&&{OrganizationId:a.organizationId}}}}clear(){this.layers.clear(),this.versions.clear(),this.permissions.clear(),this.layerCounter=0,this.versionCounter=0,this.permissionCounter=0}}var BC=new Ng;class kg{versions=new Map;aliases=new Map;deployments=new Map;versionCounter=0;aliasCounter=0;deploymentCounter=0;publishVersion(a){let n=`version-${Date.now()}-${this.versionCounter++}`,i=this.getNextVersionNumber(a.functionName),s={id:n,functionName:a.functionName,version:i.toString(),functionArn:`arn:aws:lambda:us-east-1:123456789012:function:${a.functionName}:${i}`,codeHash:this.generateHash(),description:a.description,runtime:a.runtime,memorySize:a.memorySize,timeout:a.timeout,publishedAt:new Date};return this.versions.set(n,s),s}getNextVersionNumber(a){let n=Array.from(this.versions.values()).filter((i)=>i.functionName===a).map((i)=>parseInt(i.version));return n.length>0?Math.max(...n)+1:1}createAlias(a){let n=`alias-${Date.now()}-${this.aliasCounter++}`,i={id:n,aliasArn:`arn:aws:lambda:us-east-1:123456789012:function:${a.functionName}:${a.aliasName}`,revisionId:this.generateHash(),...a};return this.aliases.set(n,i),i}createProductionAlias(a){return this.createAlias({functionName:a.functionName,aliasName:"production",functionVersion:a.version,description:"Production alias"})}createStagingAlias(a){return this.createAlias({functionName:a.functionName,aliasName:"staging",functionVersion:a.version,description:"Staging alias"})}updateAlias(a,n){let i=this.aliases.get(a);if(!i)throw Error(`Alias not found: ${a}`);return i.functionVersion=n,i.revisionId=this.generateHash(),i}configureWeightedRouting(a,n){let i=this.aliases.get(a);if(!i)throw Error(`Alias not found: ${a}`);return i.routingConfig={additionalVersionWeights:n},i}createCanaryDeployment(a){let n=`deployment-${Date.now()}-${this.deploymentCounter++}`,i=Array.from(this.aliases.values()).find((c)=>c.functionName===a.functionName&&c.aliasName===a.aliasName);if(!i)i=this.createAlias({functionName:a.functionName,aliasName:a.aliasName,functionVersion:a.fromVersion});this.configureWeightedRouting(i.id,{[a.toVersion]:a.canaryWeight});let s={id:n,functionName:a.functionName,fromVersion:a.fromVersion,toVersion:a.toVersion,aliasName:a.aliasName,strategy:"canary",status:"in_progress",startedAt:new Date};return this.deployments.set(n,s),s}completeDeployment(a){let n=this.deployments.get(a);if(!n)throw Error(`Deployment not found: ${a}`);let i=Array.from(this.aliases.values()).find((s)=>s.functionName===n.functionName&&s.aliasName===n.aliasName);if(i)i.functionVersion=n.toVersion,i.routingConfig=void 0;return n.status="completed",n.completedAt=new Date,n}rollbackDeployment(a){let n=this.deployments.get(a);if(!n)throw Error(`Deployment not found: ${a}`);let i=Array.from(this.aliases.values()).find((s)=>s.functionName===n.functionName&&s.aliasName===n.aliasName);if(i)i.functionVersion=n.fromVersion,i.routingConfig=void 0;return n.status="failed",n.completedAt=new Date,n}generateHash(){return Math.random().toString(36).substring(2,15)}getVersion(a){return this.versions.get(a)}listVersions(a){let n=Array.from(this.versions.values());return a?n.filter((i)=>i.functionName===a):n}getAlias(a){return this.aliases.get(a)}listAliases(a){let n=Array.from(this.aliases.values());return a?n.filter((i)=>i.functionName===a):n}generateVersionCF(a){return{Type:"AWS::Lambda::Version",Properties:{FunctionName:a.functionName,Description:a.description}}}generateAliasCF(a){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:a.functionName,Name:a.aliasName,FunctionVersion:a.functionVersion,Description:a.description,...a.routingConfig&&{RoutingConfig:{AdditionalVersionWeights:Object.entries(a.routingConfig.additionalVersionWeights||{}).map(([n,i])=>({FunctionVersion:n,FunctionWeight:i}))}}}}}clear(){this.versions.clear(),this.aliases.clear(),this.deployments.clear(),this.versionCounter=0,this.aliasCounter=0,this.deploymentCounter=0}}var _C=new kg;class Bg{configs=new Map;provisionedConfigs=new Map;schedules=new Map;autoScalingConfigs=new Map;configCounter=0;provisionedCounter=0;scheduleCounter=0;autoScalingCounter=0;setReservedConcurrency(a){let n=`concurrency-${Date.now()}-${this.configCounter++}`,i={id:n,functionName:a.functionName,reservedConcurrency:a.reservedConcurrency};return this.configs.set(n,i),i}setProvisionedConcurrency(a){let n=`provisioned-${Date.now()}-${this.provisionedCounter++}`,i={id:n,functionName:a.functionName,qualifier:a.qualifier,provisionedConcurrentExecutions:a.provisionedConcurrentExecutions,status:"pending",lastModified:new Date};return this.provisionedConfigs.set(n,i),setTimeout(()=>{i.status="ready",i.allocatedConcurrency=a.provisionedConcurrentExecutions,i.availableConcurrency=a.provisionedConcurrentExecutions},100),i}configureWarmPool(a){return this.setProvisionedConcurrency({functionName:a.functionName,qualifier:a.alias,provisionedConcurrentExecutions:a.minInstances})}createSchedule(a){let n=`schedule-${Date.now()}-${this.scheduleCounter++}`,i={id:n,...a};return this.schedules.set(n,i),i}createBusinessHoursSchedule(a){return this.createSchedule({name:`${a.functionName}-business-hours`,functionName:a.functionName,qualifier:a.qualifier,schedule:[{name:"business-hours",cronExpression:"0 8 * * MON-FRI",targetConcurrency:a.businessHoursConcurrency},{name:"off-hours",cronExpression:"0 18 * * MON-FRI",targetConcurrency:a.offHoursConcurrency},{name:"weekend",cronExpression:"0 0 * * SAT",targetConcurrency:a.offHoursConcurrency}]})}configureAutoScaling(a){let n=`autoscaling-${Date.now()}-${this.autoScalingCounter++}`,i={id:n,...a};return this.autoScalingConfigs.set(n,i),i}configurePredictiveScaling(a){return this.configureAutoScaling({functionName:a.functionName,qualifier:a.qualifier,minCapacity:a.baselineCapacity,maxCapacity:a.peakCapacity,targetUtilization:0.7,scaleInCooldown:300,scaleOutCooldown:60})}getConfig(a){return this.configs.get(a)}listConfigs(){return Array.from(this.configs.values())}getProvisionedConfig(a){return this.provisionedConfigs.get(a)}listProvisionedConfigs(){return Array.from(this.provisionedConfigs.values())}generateReservedConcurrencyCF(a){return{Type:"AWS::Lambda::Function",Properties:{FunctionName:a.functionName,ReservedConcurrentExecutions:a.reservedConcurrency}}}generateProvisionedConcurrencyCF(a){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:a.functionName,Name:a.qualifier,ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:a.provisionedConcurrentExecutions}}}}generateAutoScalingTargetCF(a){return{Type:"AWS::ApplicationAutoScaling::ScalableTarget",Properties:{ServiceNamespace:"lambda",ResourceId:`function:${a.functionName}:${a.qualifier}`,ScalableDimension:"lambda:function:ProvisionedConcurrentExecutions",MinCapacity:a.minCapacity,MaxCapacity:a.maxCapacity}}}generateAutoScalingPolicyCF(a){return{Type:"AWS::ApplicationAutoScaling::ScalingPolicy",Properties:{PolicyName:`${a.functionName}-autoscaling`,PolicyType:"TargetTrackingScaling",ScalingTargetId:{Ref:`${a.functionName}AutoScalingTarget`},TargetTrackingScalingPolicyConfiguration:{TargetValue:a.targetUtilization*100,PredefinedMetricSpecification:{PredefinedMetricType:"LambdaProvisionedConcurrencyUtilization"},ScaleInCooldown:a.scaleInCooldown||300,ScaleOutCooldown:a.scaleOutCooldown||60}}}}clear(){this.configs.clear(),this.provisionedConfigs.clear(),this.schedules.clear(),this.autoScalingConfigs.clear(),this.configCounter=0,this.provisionedCounter=0,this.scheduleCounter=0,this.autoScalingCounter=0}}var xC=new Bg;class _g{destinations=new Map;records=new Map;eventBridgeDestinations=new Map;destinationCounter=0;recordCounter=0;eventBridgeCounter=0;configureDestinations(a){let n=`destination-${Date.now()}-${this.destinationCounter++}`,i={id:n,...a};return this.destinations.set(n,i),i}configureSQSDestination(a){let n={type:"sqs",arn:a.queueArn};return this.configureDestinations({functionName:a.functionName,successDestination:a.onSuccess?n:void 0,failureDestination:a.onFailure?n:void 0,maxEventAge:21600,maxRetries:2})}configureSNSDestination(a){let n={type:"sns",arn:a.topicArn};return this.configureDestinations({functionName:a.functionName,successDestination:a.onSuccess?n:void 0,failureDestination:a.onFailure?n:void 0,maxEventAge:21600,maxRetries:2})}configureEventBridgeDestination(a){let n={type:"eventbridge",arn:a.eventBusArn};return this.configureDestinations({functionName:a.functionName,successDestination:a.onSuccess?n:void 0,failureDestination:a.onFailure?n:void 0,maxEventAge:21600,maxRetries:2})}configureLambdaDestination(a){let n={type:"lambda",arn:a.destinationFunctionArn};return this.configureDestinations({functionName:a.functionName,successDestination:a.onSuccess?n:void 0,failureDestination:a.onFailure?n:void 0,maxEventAge:21600,maxRetries:2})}configureDLQWithNotification(a){return this.configureDestinations({functionName:a.functionName,failureDestination:{type:"sqs",arn:a.dlqArn},maxEventAge:3600,maxRetries:0})}createEventBridgeIntegration(a){let n=`eventbridge-${Date.now()}-${this.eventBridgeCounter++}`,i={id:n,functionName:a.functionName,eventBusArn:a.eventBusArn,detailType:a.detailType||"Lambda Function Invocation Result",source:a.source||`lambda.${a.functionName}`};return this.eventBridgeDestinations.set(n,i),i}sendToDestination(a){let n=Array.from(this.destinations.values()).find((l)=>l.functionName===a.functionName);if(!n)return null;let i=a.status==="success"?n.successDestination:n.failureDestination;if(!i)return null;let s=`record-${Date.now()}-${this.recordCounter++}`,c={id:s,timestamp:new Date,functionName:a.functionName,requestId:a.requestId,status:a.status,destinationType:i.type,destinationArn:i.arn,payload:a.payload,error:a.error};return this.records.set(s,c),c}getDestination(a){return this.destinations.get(a)}listDestinations(a){let n=Array.from(this.destinations.values());return a?n.filter((i)=>i.functionName===a):n}getDestinationRecords(a){let n=Array.from(this.records.values());return a?n.filter((i)=>i.functionName===a):n}generateEventInvokeConfigCF(a){return{Type:"AWS::Lambda::EventInvokeConfig",Properties:{FunctionName:a.functionName,Qualifier:a.qualifier||"$LATEST",MaximumEventAgeInSeconds:a.maxEventAge||21600,MaximumRetryAttempts:a.maxRetries??2,...a.successDestination&&{DestinationConfig:{OnSuccess:{Destination:a.successDestination.arn}}},...a.failureDestination&&{DestinationConfig:{OnFailure:{Destination:a.failureDestination.arn}}}}}}generateEventBridgeRuleCF(a){return{Type:"AWS::Events::Rule",Properties:{EventBusName:a.eventBusArn.split("/").pop(),EventPattern:{source:[a.source],"detail-type":[a.detailType]},State:"ENABLED",Targets:[{Arn:`arn:aws:lambda:us-east-1:123456789012:function:${a.functionName}`,Id:a.id}]}}}clear(){this.destinations.clear(),this.records.clear(),this.eventBridgeDestinations.clear(),this.destinationCounter=0,this.recordCounter=0,this.eventBridgeCounter=0}}var OC=new _g;class xg{vpcConfigs=new Map;endpoints=new Map;networkInterfaces=new Map;connectivity=new Map;configCounter=0;endpointCounter=0;eniCounter=0;connectivityCounter=0;configureVPC(a){let n=`vpc-config-${Date.now()}-${this.configCounter++}`,i={id:n,...a};this.vpcConfigs.set(n,i);for(let s of a.subnetIds)this.createNetworkInterface({functionName:a.functionName,subnetId:s});return i}configurePrivateVPC(a){return this.configureVPC({functionName:a.functionName,vpcId:a.vpcId,subnetIds:a.privateSubnetIds,securityGroupIds:[a.securityGroupId],ipv6Allowed:!1})}configureMultiAZVPC(a){if(a.subnetIds.length<2)throw Error("Multi-AZ configuration requires at least 2 subnets");return this.configureVPC({functionName:a.functionName,vpcId:a.vpcId,subnetIds:a.subnetIds,securityGroupIds:a.securityGroupIds})}createVPCEndpoint(a){let n=`endpoint-${Date.now()}-${this.endpointCounter++}`,i={id:n,...a};return this.endpoints.set(n,i),i}createS3Endpoint(a){return this.createVPCEndpoint({vpcId:a.vpcId,serviceName:"com.amazonaws.us-east-1.s3",endpointType:"Gateway",privateDnsEnabled:!1})}createDynamoDBEndpoint(a){return this.createVPCEndpoint({vpcId:a.vpcId,serviceName:"com.amazonaws.us-east-1.dynamodb",endpointType:"Gateway",privateDnsEnabled:!1})}createSecretsManagerEndpoint(a){return this.createVPCEndpoint({vpcId:a.vpcId,serviceName:"com.amazonaws.us-east-1.secretsmanager",endpointType:"Interface",subnetIds:a.subnetIds,securityGroupIds:a.securityGroupIds,privateDnsEnabled:!0})}createNetworkInterface(a){let n=`eni-${Date.now()}-${this.eniCounter++}`,i={id:n,functionName:a.functionName,networkInterfaceId:`eni-${Math.random().toString(36).substring(2,15)}`,subnetId:a.subnetId,privateIpAddress:`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`,status:"creating",attachedAt:new Date};return this.networkInterfaces.set(n,i),setTimeout(()=>{i.status="available"},100),i}analyzeConnectivity(a){let n=`connectivity-${Date.now()}-${this.connectivityCounter++}`,i=Array.from(this.vpcConfigs.values()).find((y)=>y.functionName===a.functionName),s=Array.from(this.endpoints.values()).filter((y)=>y.vpcId===i?.vpcId).map((y)=>y.serviceName),c=[],l=a.hasNATGateway??!1,u=a.hasInternetGateway??!1;if(!l&&!u)c.push("Add NAT Gateway for internet access");if(!s.includes("com.amazonaws.us-east-1.s3"))c.push("Add S3 VPC endpoint to reduce NAT costs");if(!s.includes("com.amazonaws.us-east-1.dynamodb"))c.push("Add DynamoDB VPC endpoint for private access");let h={id:n,functionName:a.functionName,hasInternetAccess:l||u,hasNATGateway:l,hasVPCEndpoints:s.length>0,endpoints:s,recommendations:c};return this.connectivity.set(n,h),h}getVPCConfig(a){return this.vpcConfigs.get(a)}listVPCConfigs(a){let n=Array.from(this.vpcConfigs.values());return a?n.filter((i)=>i.functionName===a):n}getNetworkInterfaces(a){return Array.from(this.networkInterfaces.values()).filter((n)=>n.functionName===a)}listVPCEndpoints(a){let n=Array.from(this.endpoints.values());return a?n.filter((i)=>i.vpcId===a):n}generateVPCConfigCF(a){return{VpcConfig:{SubnetIds:a.subnetIds,SecurityGroupIds:a.securityGroupIds,...a.ipv6Allowed&&{Ipv6AllowedForDualStack:!0}}}}generateVPCEndpointCF(a){return{Type:"AWS::EC2::VPCEndpoint",Properties:{VpcId:a.vpcId,ServiceName:a.serviceName,VpcEndpointType:a.endpointType,...a.subnetIds&&{SubnetIds:a.subnetIds},...a.securityGroupIds&&{SecurityGroupIds:a.securityGroupIds},...a.privateDnsEnabled!==void 0&&{PrivateDnsEnabled:a.privateDnsEnabled}}}}generateSecurityGroupCF(a){return{Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:a.groupName,GroupDescription:`Security group for Lambda ${a.groupName}`,VpcId:a.vpcId,...a.ingressRules&&{SecurityGroupIngress:a.ingressRules.map((n)=>({IpProtocol:n.protocol,FromPort:n.fromPort,ToPort:n.toPort,...n.cidrIp&&{CidrIp:n.cidrIp},...n.sourceSecurityGroupId&&{SourceSecurityGroupId:n.sourceSecurityGroupId}}))},...a.egressRules&&{SecurityGroupEgress:a.egressRules.map((n)=>({IpProtocol:n.protocol,FromPort:n.fromPort,ToPort:n.toPort,CidrIp:n.cidrIp||"0.0.0.0/0"}))}}}}clear(){this.vpcConfigs.clear(),this.endpoints.clear(),this.networkInterfaces.clear(),this.connectivity.clear(),this.configCounter=0,this.endpointCounter=0,this.eniCounter=0,this.connectivityCounter=0}}var LC=new xg;class Og{dlqConfigs=new Map;messages=new Map;alarms=new Map;reprocessing=new Map;configCounter=0;messageCounter=0;alarmCounter=0;reprocessCounter=0;configureDLQ(a){let n=`dlq-${Date.now()}-${this.configCounter++}`,i={id:n,...a};return this.dlqConfigs.set(n,i),i}configureSQSDLQ(a){return this.configureDLQ({functionName:a.functionName,targetArn:a.queueArn,targetType:"sqs",maxReceiveCount:a.maxReceiveCount||3,retentionPeriod:a.retentionPeriod||1209600})}configureSNSDLQ(a){return this.configureDLQ({functionName:a.functionName,targetArn:a.topicArn,targetType:"sns"})}configureDLQWithAlarm(a){let n=this.configureSQSDLQ({functionName:a.functionName,queueArn:a.queueArn});return this.createDLQAlarm({dlqConfigId:n.id,alarmName:`${a.functionName}-dlq-alarm`,threshold:a.alarmThreshold,evaluationPeriods:1,notificationTopicArn:a.notificationTopicArn,enabled:!0}),n}sendToDLQ(a){let n=`message-${Date.now()}-${this.messageCounter++}`,i={id:n,timestamp:new Date,...a};return this.messages.set(n,i),i}createDLQAlarm(a){let n=`alarm-${Date.now()}-${this.alarmCounter++}`,i={id:n,...a};return this.alarms.set(n,i),i}createAgeAlarm(a){let n=this.dlqConfigs.get(a.dlqConfigId);if(!n)throw Error(`DLQ config not found: ${a.dlqConfigId}`);return this.createDLQAlarm({dlqConfigId:a.dlqConfigId,alarmName:`${n.functionName}-dlq-age-alarm`,threshold:a.maxAgeSeconds,evaluationPeriods:1,notificationTopicArn:a.notificationTopicArn,enabled:!0})}async reprocessMessage(a){let n=this.messages.get(a);if(!n)throw Error(`Message not found: ${a}`);let i=Array.from(this.dlqConfigs.values()).find((l)=>l.functionName===n.functionName);if(!i)throw Error(`DLQ config not found for function: ${n.functionName}`);let s=`reprocess-${Date.now()}-${this.reprocessCounter++}`,c={id:s,dlqConfigId:i.id,messageId:a,status:"pending",startedAt:new Date};return this.reprocessing.set(s,c),setTimeout(()=>{c.status="processing",setTimeout(()=>{let l=Math.random()>0.3;if(c.status=l?"success":"failed",c.completedAt=new Date,!l)c.error="Reprocessing failed - same error occurred";else this.messages.delete(a)},100)},50),c}async batchReprocess(a){let n=this.dlqConfigs.get(a.dlqConfigId);if(!n)throw Error(`DLQ config not found: ${a.dlqConfigId}`);let i=Array.from(this.messages.values()).filter((s)=>s.functionName===n.functionName).slice(0,a.maxMessages||10).map((s)=>this.reprocessMessage(s.id));return Promise.all(i)}getDLQStats(a){let n=this.dlqConfigs.get(a);if(!n)throw Error(`DLQ config not found: ${a}`);let i=Array.from(this.messages.values()).filter((u)=>u.functionName===n.functionName),s={},c=0;for(let u of i)s[u.errorType]=(s[u.errorType]||0)+1,c+=u.attemptCount;let l=i.map((u)=>u.timestamp);return{totalMessages:i.length,oldestMessage:l.length>0?new Date(Math.min(...l.map((u)=>u.getTime()))):void 0,newestMessage:l.length>0?new Date(Math.max(...l.map((u)=>u.getTime()))):void 0,averageAttempts:i.length>0?c/i.length:0,errorTypes:s}}getDLQConfig(a){return this.dlqConfigs.get(a)}listDLQConfigs(){return Array.from(this.dlqConfigs.values())}getDLQMessages(a){let n=this.dlqConfigs.get(a);if(!n)return[];return Array.from(this.messages.values()).filter((i)=>i.functionName===n.functionName)}generateDLQCF(a){return{DeadLetterConfig:{TargetArn:a.targetArn}}}generateSQSDLQCF(a){return{Type:"AWS::SQS::Queue",Properties:{QueueName:`${a.functionName}-dlq`,MessageRetentionPeriod:a.retentionPeriod||1209600,...a.maxReceiveCount&&{RedrivePolicy:{deadLetterTargetArn:a.targetArn,maxReceiveCount:a.maxReceiveCount}}}}}generateDLQAlarmCF(a){let n=this.dlqConfigs.get(a.dlqConfigId);if(!n)throw Error(`DLQ config not found: ${a.dlqConfigId}`);return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:a.alarmName,AlarmDescription:`DLQ alarm for ${n.functionName}`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Sum",Period:300,EvaluationPeriods:a.evaluationPeriods,Threshold:a.threshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:n.targetArn.split(":").pop()}],...a.notificationTopicArn&&{AlarmActions:[a.notificationTopicArn]}}}}clear(){this.dlqConfigs.clear(),this.messages.clear(),this.alarms.clear(),this.reprocessing.clear(),this.configCounter=0,this.messageCounter=0,this.alarmCounter=0,this.reprocessCounter=0}}var $C=new Og;class Lg{policies=new Map;healthChecks=new Map;trafficPolicies=new Map;policyCounter=0;healthCheckCounter=0;trafficPolicyCounter=0;createWeightedPolicy(a){let n=`policy-${Date.now()}-${this.policyCounter++}`,i={id:n,type:"weighted",...a};return this.policies.set(n,i),i}createLatencyPolicy(a){let n=`policy-${Date.now()}-${this.policyCounter++}`,i={id:n,type:"latency",...a};return this.policies.set(n,i),i}createFailoverPolicy(a){let n=`policy-${Date.now()}-${this.policyCounter++}`,i={id:n,type:"failover",...a};return this.policies.set(n,i),i}createGeolocationPolicy(a){let n=`policy-${Date.now()}-${this.policyCounter++}`,i={id:n,type:"geolocation",...a};return this.policies.set(n,i),i}createGeoproximityPolicy(a){let n=`policy-${Date.now()}-${this.policyCounter++}`,i={id:n,type:"geoproximity",...a};return this.policies.set(n,i),i}createHTTPHealthCheck(a){let n=`health-check-${Date.now()}-${this.healthCheckCounter++}`,i={id:n,type:a.port===443?"https":"http",requestInterval:a.requestInterval||30,failureThreshold:a.failureThreshold||3,healthCheckStatus:"Unknown",port:a.port||(a.port===443?443:80),...a};return this.healthChecks.set(n,i),setTimeout(()=>{i.healthCheckStatus=Math.random()>0.2?"Healthy":"Unhealthy"},100),i}createTCPHealthCheck(a){let n=`health-check-${Date.now()}-${this.healthCheckCounter++}`,i={id:n,type:"tcp",fullyQualifiedDomainName:a.ipAddress,requestInterval:a.requestInterval||30,failureThreshold:a.failureThreshold||3,healthCheckStatus:"Unknown",...a};return this.healthChecks.set(n,i),setTimeout(()=>{i.healthCheckStatus=Math.random()>0.1?"Healthy":"Unhealthy"},100),i}createCalculatedHealthCheck(a){let n=`health-check-${Date.now()}-${this.healthCheckCounter++}`,i={id:n,type:"calculated",requestInterval:30,failureThreshold:0,healthCheckStatus:"Unknown",...a};return this.healthChecks.set(n,i),setTimeout(()=>{let s=a.childHealthChecks.filter((c)=>this.healthChecks.get(c)?.healthCheckStatus==="Healthy").length;i.healthCheckStatus=s>=a.healthThreshold?"Healthy":"Unhealthy"},150),i}createTrafficPolicy(a){let n=`traffic-policy-${Date.now()}-${this.trafficPolicyCounter++}`,i={id:n,version:1,...a};return this.trafficPolicies.set(n,i),i}createFailoverTrafficPolicy(a){return this.createTrafficPolicy({name:a.name,document:{recordType:a.recordType||"A",startRule:"failover",endpoints:{primary:{type:"value",value:a.primaryEndpoint},secondary:{type:"value",value:a.secondaryEndpoint}},rules:{failover:{ruleType:"failover",primary:"primary",secondary:"secondary"}}}})}createGeoproximityTrafficPolicy(a){let n={},i=[];return a.locations.forEach((s,c)=>{let l=`endpoint${c}`;n[l]={type:"value",value:s.endpoint},i.push({endpointReference:l,region:s.region,latitude:s.latitude,longitude:s.longitude,bias:s.bias})}),this.createTrafficPolicy({name:a.name,document:{recordType:"A",startRule:"geoproximity",endpoints:n,rules:{geoproximity:{ruleType:"geoproximity",locations:i}}}})}getPolicy(a){return this.policies.get(a)}listPolicies(){return Array.from(this.policies.values())}getHealthCheck(a){return this.healthChecks.get(a)}listHealthChecks(){return Array.from(this.healthChecks.values())}getHealthCheckStatus(a){return this.healthChecks.get(a)?.healthCheckStatus||"Unknown"}generateHealthCheckCF(a){let n={Type:"AWS::Route53::HealthCheck",Properties:{HealthCheckConfig:{Type:a.type.toUpperCase(),RequestInterval:a.requestInterval,FailureThreshold:a.failureThreshold,...a.measureLatency&&{MeasureLatency:!0}},HealthCheckTags:[{Key:"Name",Value:a.name}]}};if(a.type==="calculated"){let i=a;n.Properties.HealthCheckConfig.ChildHealthChecks=i.childHealthChecks,n.Properties.HealthCheckConfig.HealthThreshold=i.healthThreshold}else{if(a.ipAddress)n.Properties.HealthCheckConfig.IPAddress=a.ipAddress;if(a.fullyQualifiedDomainName)n.Properties.HealthCheckConfig.FullyQualifiedDomainName=a.fullyQualifiedDomainName;if(a.port)n.Properties.HealthCheckConfig.Port=a.port;if(a.resourcePath)n.Properties.HealthCheckConfig.ResourcePath=a.resourcePath;if(a.enableSNI)n.Properties.HealthCheckConfig.EnableSNI=!0}return n}generateWeightedRecordSetCF(a){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:a.hostedZoneId,Name:a.name,Type:a.type,TTL:a.ttl,ResourceRecords:a.resourceRecords,Weight:a.weight,SetIdentifier:a.setIdentifier,...a.healthCheckId&&{HealthCheckId:a.healthCheckId}}}}generateFailoverRecordSetCF(a){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:a.hostedZoneId,Name:a.name,Type:a.type,TTL:a.ttl,ResourceRecords:a.resourceRecords,Failover:a.failover,SetIdentifier:a.setIdentifier,...a.healthCheckId&&{HealthCheckId:a.healthCheckId}}}}clear(){this.policies.clear(),this.healthChecks.clear(),this.trafficPolicies.clear(),this.policyCounter=0,this.healthCheckCounter=0,this.trafficPolicyCounter=0}}var MC=new Lg;class $g{configs=new Map;ksks=new Map;validations=new Map;configCounter=0;kskCounter=0;validationCounter=0;enableDNSSEC(a){let n=`dnssec-${Date.now()}-${this.configCounter++}`,i={id:n,hostedZoneId:a.hostedZoneId,status:"SIGNING",signingStatus:"Initializing DNSSEC signing"};if(this.configs.set(n,i),a.kmsKeyArn)this.createKSK({name:`ksk-${a.hostedZoneId}`,hostedZoneId:a.hostedZoneId,kmsKeyArn:a.kmsKeyArn});return setTimeout(()=>{i.status="SIGNED",i.signingStatus="DNSSEC signing complete"},100),i}disableDNSSEC(a){let n=this.configs.get(a);if(!n)throw Error(`DNSSEC config not found: ${a}`);return n.status="DELETING",n.signingStatus="Removing DNSSEC signing",setTimeout(()=>{n.status="NOT_SIGNING",n.signingStatus="DNSSEC signing removed"},100),n}createKSK(a){let n=`ksk-${Date.now()}-${this.kskCounter++}`,i={id:n,status:"ACTIVE",flag:257,keyManagementServiceArn:a.kmsKeyArn,digestAlgorithm:2,keyTag:Math.floor(Math.random()*65535),publicKey:this.generatePublicKey(),...a};i.dnskeyRecord=`${i.flag} 3 8 ${i.publicKey}`;let s=this.generateDigest(i.dnskeyRecord);return i.digestValue=s,i.dsRecord=`${i.keyTag} 8 ${i.digestAlgorithm} ${s}`,this.ksks.set(n,i),i}deactivateKSK(a){let n=this.ksks.get(a);if(!n)throw Error(`KSK not found: ${a}`);return n.status="INACTIVE",n}validateDNSSEC(a){let n=`validation-${Date.now()}-${this.validationCounter++}`,i=a.checkDNSKEY!==!1?Math.random()>0.1:!1,s=a.checkRRSIG!==!1?Math.random()>0.1:!1,c=i&&s,l=[];if(!i)l.push("DNSKEY record not found");if(!s)l.push("RRSIG record not found");let u;if(!i&&!s)u="INSECURE";else if(i&&s&&c)u="VALID";else if(i||s)u="BOGUS",l.push("Invalid signature or incomplete DNSSEC chain");else u="INVALID";let h={id:n,domain:a.domain,validationStatus:u,dnskeyPresent:i,rrsigPresent:s,validSignature:c,errors:l};return this.validations.set(n,h),h}getDNSSECConfig(a){return this.configs.get(a)}listDNSSECConfigs(){return Array.from(this.configs.values())}getKSK(a){return this.ksks.get(a)}listKSKs(a){let n=Array.from(this.ksks.values());return a?n.filter((i)=>i.hostedZoneId===a):n}getDSRecord(a){let n=this.ksks.get(a);if(!n||!n.dsRecord)throw Error("DS record not available");return n.dsRecord}generatePublicKey(){let a="";for(let n=0;n<256;n++)a+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(Math.floor(Math.random()*64));return a}generateDigest(a){let n="";for(let i=0;i<64;i++)n+="0123456789ABCDEF".charAt(Math.floor(Math.random()*16));return n}generateDNSSECCF(a){return{Type:"AWS::Route53::DNSSEC",Properties:{HostedZoneId:a.hostedZoneId}}}generateKSKCF(a){return{Type:"AWS::Route53::KeySigningKey",Properties:{Name:a.name,HostedZoneId:a.hostedZoneId,KeyManagementServiceArn:a.keyManagementServiceArn,Status:a.status}}}clear(){this.configs.clear(),this.ksks.clear(),this.validations.clear(),this.configCounter=0,this.kskCounter=0,this.validationCounter=0}}var FC=new $g;class Mg{endpoints=new Map;rules=new Map;firewalls=new Map;ruleGroups=new Map;domainLists=new Map;endpointCounter=0;ruleCounter=0;firewallCounter=0;ruleGroupCounter=0;domainListCounter=0;createResolverEndpoint(a){let n=`endpoint-${Date.now()}-${this.endpointCounter++}`,i={id:n,status:"CREATING",...a};return this.endpoints.set(n,i),setTimeout(()=>{i.status="OPERATIONAL",i.ipAddresses.forEach((s)=>{if(!s.ip)s.ip=`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`})},100),i}createInboundEndpoint(a){return this.createResolverEndpoint({name:a.name,direction:"INBOUND",ipAddresses:a.subnetIds.map((n)=>({subnetId:n})),securityGroupIds:a.securityGroupIds})}createOutboundEndpoint(a){return this.createResolverEndpoint({name:a.name,direction:"OUTBOUND",ipAddresses:a.subnetIds.map((n)=>({subnetId:n})),securityGroupIds:a.securityGroupIds})}createResolverRule(a){let n=`rule-${Date.now()}-${this.ruleCounter++}`,i={id:n,status:"CREATING",...a};return this.rules.set(n,i),setTimeout(()=>{i.status="COMPLETE"},100),i}createForwardRule(a){return this.createResolverRule({name:a.name,ruleType:"FORWARD",domainName:a.domainName,targetIps:a.targetIps,resolverEndpointId:a.resolverEndpointId})}createSystemRule(a){return this.createResolverRule({name:a.name,ruleType:"SYSTEM",domainName:a.domainName})}createFirewallDomainList(a){let n=`domain-list-${Date.now()}-${this.domainListCounter++}`,i={id:n,status:"CREATING",...a};return this.domainLists.set(n,i),setTimeout(()=>{i.status="COMPLETE"},100),i}createFirewallRuleGroup(a){let n=`rule-group-${Date.now()}-${this.ruleGroupCounter++}`,i={id:n,name:a.name,rules:a.rules.map((s,c)=>({id:`rule-${n}-${c}`,...s})),shareStatus:"NOT_SHARED"};return this.ruleGroups.set(n,i),i}createBlockRule(a){return this.createFirewallRuleGroup({name:a.name,rules:[{name:a.name,priority:a.priority,action:"BLOCK",blockResponse:a.blockResponse||"NODATA",blockOverrideDomain:a.blockOverrideDomain,firewallDomainListId:a.domainListId}]})}createAllowRule(a){return this.createFirewallRuleGroup({name:a.name,rules:[{name:a.name,priority:a.priority,action:"ALLOW",firewallDomainListId:a.domainListId}]})}createDNSFirewall(a){let n=`firewall-${Date.now()}-${this.firewallCounter++}`,i={id:n,name:a.name,firewallRuleGroupAssociations:a.ruleGroupAssociations.map((s,c)=>({id:`assoc-${n}-${c}`,vpcId:a.vpcId,firewallRuleGroupId:s.firewallRuleGroupId,priority:s.priority,mutationProtection:s.mutationProtection||"DISABLED",status:"COMPLETE"}))};return this.firewalls.set(n,i),i}createMalwareProtectionFirewall(a){let n=this.createFirewallDomainList({name:`${a.name}-malware-domains`,domains:a.maliciousDomains}),i=this.createBlockRule({name:`${a.name}-block-malware`,priority:100,domainListId:n.id,blockResponse:"NXDOMAIN"});return this.createDNSFirewall({name:a.name,vpcId:a.vpcId,ruleGroupAssociations:[{firewallRuleGroupId:i.id,priority:100,mutationProtection:"ENABLED"}]})}getEndpoint(a){return this.endpoints.get(a)}listEndpoints(a){let n=Array.from(this.endpoints.values());return a?n.filter((i)=>i.direction===a):n}getRule(a){return this.rules.get(a)}listRules(){return Array.from(this.rules.values())}getFirewall(a){return this.firewalls.get(a)}listFirewalls(){return Array.from(this.firewalls.values())}generateResolverEndpointCF(a){return{Type:"AWS::Route53Resolver::ResolverEndpoint",Properties:{Name:a.name,Direction:a.direction,IpAddresses:a.ipAddresses.map((n)=>({SubnetId:n.subnetId,...n.ip&&{Ip:n.ip}})),SecurityGroupIds:a.securityGroupIds}}}generateResolverRuleCF(a){return{Type:"AWS::Route53Resolver::ResolverRule",Properties:{Name:a.name,RuleType:a.ruleType,DomainName:a.domainName,...a.targetIps&&{TargetIps:a.targetIps.map((n)=>({Ip:n.ip,Port:n.port||53}))},...a.resolverEndpointId&&{ResolverEndpointId:a.resolverEndpointId}}}}generateFirewallRuleGroupCF(a){return{Type:"AWS::Route53Resolver::FirewallRuleGroup",Properties:{Name:a.name,FirewallRules:a.rules.map((n)=>({Name:n.name,Priority:n.priority,Action:n.action,FirewallDomainListId:n.firewallDomainListId,...n.blockResponse&&{BlockResponse:n.blockResponse},...n.blockOverrideDomain&&{BlockOverrideDomain:n.blockOverrideDomain},...n.blockOverrideTTL&&{BlockOverrideTtl:n.blockOverrideTTL}}))}}}clear(){this.endpoints.clear(),this.rules.clear(),this.firewalls.clear(),this.ruleGroups.clear(),this.domainLists.clear(),this.endpointCounter=0,this.ruleCounter=0,this.firewallCounter=0,this.ruleGroupCounter=0,this.domainListCounter=0}}var UC=new Mg;class Fg{bounces=new Map;complaints=new Map;handlers=new Map;suppressionList=new Map;metrics=new Map;bounceCounter=0;complaintCounter=0;handlerCounter=0;suppressionCounter=0;metricsCounter=0;recordBounce(a){let n=`bounce-${Date.now()}-${this.bounceCounter++}`,i={id:n,...a};if(this.bounces.set(n,i),a.bounceType==="Permanent")this.addToSuppressionList({emailAddress:a.recipient,reason:"BOUNCE"});return i}recordComplaint(a){let n=`complaint-${Date.now()}-${this.complaintCounter++}`,i={id:n,...a};this.complaints.set(n,i);for(let s of a.recipients)this.addToSuppressionList({emailAddress:s,reason:"COMPLAINT"});return i}createBounceHandler(a){let n=`handler-${Date.now()}-${this.handlerCounter++}`,i={id:n,...a};return this.handlers.set(n,i),i}createAutomaticBounceHandler(a){return this.createBounceHandler({name:a.name,bounceThreshold:5,complaintThreshold:0.1,suppressionDuration:2592000,autoSuppress:!0,notificationTopicArn:a.notificationTopicArn})}addToSuppressionList(a){let n=`suppression-${Date.now()}-${this.suppressionCounter++}`,i=a.expirationDays?new Date(Date.now()+a.expirationDays*24*60*60*1000):void 0,s={id:n,emailAddress:a.emailAddress,reason:a.reason,suppressedAt:new Date,expiresAt:i,bounceCount:a.reason==="BOUNCE"?1:0,complaintCount:a.reason==="COMPLAINT"?1:0};return this.suppressionList.set(a.emailAddress,s),s}removeFromSuppressionList(a){return this.suppressionList.delete(a)}isSuppressed(a){let n=this.suppressionList.get(a);if(!n)return!1;if(n.expiresAt&&n.expiresAt<new Date)return this.suppressionList.delete(a),!1;return!0}getBounceStatistics(a,n){let i=Array.from(this.bounces.values()).filter((A)=>A.timestamp>=a&&A.timestamp<=n),s=i.length,c=i.filter((A)=>A.bounceType==="Permanent").length,l=i.filter((A)=>A.bounceType==="Transient").length,u=s*10,h=s/u*100,y=new Map;for(let A of i)y.set(A.recipient,(y.get(A.recipient)||0)+1);let S=Array.from(y.entries()).map(([A,C])=>({email:A,count:C})).sort((A,C)=>C.count-A.count).slice(0,10);return{totalBounces:s,permanentBounces:c,transientBounces:l,bounceRate:h,topRecipients:S}}getComplaintStatistics(a,n){let i=Array.from(this.complaints.values()).filter((y)=>y.timestamp>=a&&y.timestamp<=n),s=i.length,c=new Set;for(let y of i)for(let S of y.recipients)c.add(S);let l=c.size,u=s*1000,h=s/u*100;return{totalComplaints:s,uniqueComplainters:l,complaintRate:h}}calculateReputationMetrics(){let a=`metrics-${Date.now()}-${this.metricsCounter++}`,n=new Date,i=new Date(n.getTime()-86400000),s=this.getBounceStatistics(i,n),c=this.getComplaintStatistics(i,n),l;if(s.bounceRate>10||c.complaintRate>0.5)l="Shutdown";else if(s.bounceRate>5||c.complaintRate>0.1)l="Probation";else if(s.bounceRate>2||c.complaintRate>0.05)l="Warning";else l="Good";let u={id:a,timestamp:n,bounceRate:s.bounceRate,complaintRate:c.complaintRate,sendingQuota:50000,maxSendRate:14,sentLast24Hours:s.totalBounces*10,reputationStatus:l};return this.metrics.set(a,u),u}getBounces(a){let n=Array.from(this.bounces.values());return a?n.filter((i)=>i.messageId===a):n}getComplaints(a){let n=Array.from(this.complaints.values());return a?n.filter((i)=>i.messageId===a):n}listSuppressionList(a){let n=Array.from(this.suppressionList.values());return a?n.filter((i)=>i.reason===a):n}generateSNSSubscriptionCF(a){return{Type:"AWS::SNS::Subscription",Properties:{TopicArn:a.topicArn,Endpoint:a.endpoint,Protocol:a.protocol}}}generateEventDestinationCF(a){return{Type:"AWS::SES::ConfigurationSetEventDestination",Properties:{ConfigurationSetName:a.configurationSetName,EventDestination:{Name:a.eventDestinationName,Enabled:!0,MatchingEventTypes:a.eventTypes,...a.snsTopicArn&&{SnsDestination:{TopicARN:a.snsTopicArn}},...a.cloudWatchDestination&&{CloudWatchDestination:a.cloudWatchDestination}}}}}clear(){this.bounces.clear(),this.complaints.clear(),this.handlers.clear(),this.suppressionList.clear(),this.metrics.clear(),this.bounceCounter=0,this.complaintCounter=0,this.handlerCounter=0,this.suppressionCounter=0,this.metricsCounter=0}}var QC=new Fg;class Ug{events=new Map;campaigns=new Map;reports=new Map;abTests=new Map;eventCounter=0;campaignCounter=0;reportCounter=0;abTestCounter=0;trackEvent(a){let n=`event-${Date.now()}-${this.eventCounter++}`,i={id:n,...a};if(this.events.set(n,i),a.tags?.campaignId)this.updateCampaignStats(a.tags.campaignId,a.eventType);return i}trackOpen(a){return this.trackEvent({...a,eventType:"open",timestamp:new Date})}trackClick(a){return this.trackEvent({...a,eventType:"click",timestamp:new Date})}createCampaign(a){let n=`campaign-${Date.now()}-${this.campaignCounter++}`,i={id:n,sentCount:0,deliveredCount:0,openCount:0,clickCount:0,bounceCount:0,complaintCount:0,createdAt:new Date,...a};return this.campaigns.set(n,i),i}updateCampaignStats(a,n){let i=this.campaigns.get(a);if(!i)return;switch(n){case"send":i.sentCount++;break;case"delivery":i.deliveredCount++;break;case"open":i.openCount++;break;case"click":i.clickCount++;break;case"bounce":i.bounceCount++;break;case"complaint":i.complaintCount++;break}}generateReport(a){let n=`report-${Date.now()}-${this.reportCounter++}`,i=Array.from(this.events.values()).filter((P)=>{let V=P.timestamp>=a.startDate&&P.timestamp<=a.endDate,B=!a.campaignId||P.tags?.campaignId===a.campaignId;return V&&B}),s=i.filter((P)=>P.eventType==="send").length,c=i.filter((P)=>P.eventType==="delivery").length,l=i.filter((P)=>P.eventType==="open").length,u=i.filter((P)=>P.eventType==="click").length,h=i.filter((P)=>P.eventType==="bounce").length,y=i.filter((P)=>P.eventType==="complaint").length,S=s>0?c/s*100:0,A=c>0?l/c*100:0,C=c>0?u/c*100:0,T=l>0?u/l*100:0,v=s>0?h/s*100:0,w=c>0?y/c*100:0,E=new Map;for(let P of i)if(P.eventType==="click"){let V=P;E.set(V.link,(E.get(V.link)||0)+1)}let R=Array.from(E.entries()).map(([P,V])=>({link:P,clicks:V})).sort((P,V)=>V.clicks-P.clicks).slice(0,10),k={desktop:0,mobile:0,tablet:0,unknown:0};for(let P of i)if(P.eventType==="open"||P.eventType==="click"){let V=P.userAgent.toLowerCase();if(V.includes("mobile"))k.mobile++;else if(V.includes("tablet"))k.tablet++;else if(V.includes("mozilla"))k.desktop++;else k.unknown++}let W={id:n,campaignId:a.campaignId,startDate:a.startDate,endDate:a.endDate,totalSent:s,totalDelivered:c,totalOpened:l,totalClicked:u,totalBounced:h,totalComplaints:y,deliveryRate:S,openRate:A,clickRate:C,clickToOpenRate:T,bounceRate:v,complaintRate:w,topLinks:R,deviceBreakdown:k,locationBreakdown:{}};return this.reports.set(n,W),W}createABTest(a){let n=`abtest-${Date.now()}-${this.abTestCounter++}`,i={id:n,name:a.name,variants:a.variants.map((s,c)=>({id:`variant-${n}-${c}`,sentCount:0,openCount:0,clickCount:0,conversionCount:0,...s})),status:"draft"};return this.abTests.set(n,i),i}startABTest(a){let n=this.abTests.get(a);if(!n)throw Error(`A/B test not found: ${a}`);return n.status="running",n.startedAt=new Date,n}completeABTest(a){let n=this.abTests.get(a);if(!n)throw Error(`A/B test not found: ${a}`);let i=n.variants[0],s=0;for(let c of n.variants){let l=c.sentCount>0?c.openCount/c.sentCount:0;if(l>s)s=l,i=c}return n.status="completed",n.completedAt=new Date,n.winner=i.id,n}getCampaign(a){return this.campaigns.get(a)}listCampaigns(){return Array.from(this.campaigns.values())}getEvents(a){let n=Array.from(this.events.values());if(a?.messageId)n=n.filter((i)=>i.messageId===a.messageId);if(a?.eventType)n=n.filter((i)=>i.eventType===a.eventType);if(a?.startDate)n=n.filter((i)=>i.timestamp>=a.startDate);if(a?.endDate)n=n.filter((i)=>i.timestamp<=a.endDate);return n}generateTrackingConfigurationCF(a){return{Type:"AWS::SES::ConfigurationSet",Properties:{Name:a.configurationSetName,...a.openTracking&&{TrackingOptions:{CustomRedirectDomain:"tracking.example.com"}}}}}clear(){this.events.clear(),this.campaigns.clear(),this.reports.clear(),this.abTests.clear(),this.eventCounter=0,this.campaignCounter=0,this.reportCounter=0,this.abTestCounter=0}}var HC=new Ug;class Qg{dashboards=new Map;warmupPlans=new Map;domainReputations=new Map;dashboardCounter=0;warmupCounter=0;domainCounter=0;getReputationDashboard(){let a=`dashboard-${Date.now()}-${this.dashboardCounter++}`,n=Math.random()*5,i=Math.random()*0.5,s=Math.floor(Math.random()*10),c=Math.max(0,100-n*10-i*100-s*2),l=[];if(n>2)l.push("Reduce bounce rate by cleaning email list");if(i>0.1)l.push("Review email content and unsubscribe process");if(s>5)l.push("Improve email relevance and targeting");let u={id:a,timestamp:new Date,overallScore:c,bounceRate:n,complaintRate:i,spamReports:s,blacklistStatus:this.checkBlacklists(),dkimStatus:"VERIFIED",spfStatus:"PASS",dmarcStatus:"PASS",sendingLimits:{maxSendRate:14,max24HourSend:50000,sentLast24Hours:12000,remainingQuota:38000,quotaResetTime:new Date(Date.now()+86400000)},recommendations:l};return this.dashboards.set(a,u),u}checkBlacklists(){return["Spamhaus ZEN","Spamcop","SORBS","Barracuda","URIBL"].map((a)=>({listName:a,listed:Math.random()>0.95,delistUrl:`https://www.${a.toLowerCase().replace(/\s/g,"")}.org/delist`}))}createWarmupPlan(a){let n=`warmup-${Date.now()}-${this.warmupCounter++}`,i=[],s=(a.targetDailyLimit-a.initialDailyLimit)/a.durationDays;for(let l=0;l<a.durationDays;l++)i.push(Math.floor(a.initialDailyLimit+s*l));let c={id:n,name:a.name,startDate:new Date,currentDay:1,totalDays:a.durationDays,dailyLimits:i,currentLimit:i[0],status:"active"};return this.warmupPlans.set(n,c),c}createAggressiveWarmupPlan(a){return this.createWarmupPlan({name:a.name,initialDailyLimit:500,targetDailyLimit:50000,durationDays:14})}createConservativeWarmupPlan(a){return this.createWarmupPlan({name:a.name,initialDailyLimit:200,targetDailyLimit:50000,durationDays:30})}advanceWarmupPlan(a){let n=this.warmupPlans.get(a);if(!n)throw Error(`Warmup plan not found: ${a}`);if(n.currentDay<n.totalDays)n.currentDay++,n.currentLimit=n.dailyLimits[n.currentDay-1];if(n.currentDay>=n.totalDays)n.status="completed";return n}trackDomainReputation(a){let n=`domain-${Date.now()}-${this.domainCounter++}`,i=a.delivered/a.totalSent*100,s=a.delivered>0?a.opened/a.delivered*100:0,c=a.delivered>0?a.clicked/a.delivered*100:0,l=a.bounced/a.totalSent*100,u=a.delivered>0?a.complained/a.delivered*100:0,h=s*0.4+c*0.6,y=Math.max(0,100-l*10-u*100+h*0.2),S={id:n,domain:a.domain,reputationScore:y,totalSent:a.totalSent,deliveryRate:i,openRate:s,clickRate:c,bounceRate:l,complaintRate:u,engagementScore:h};return this.domainReputations.set(a.domain,S),S}getDomainReputation(a){return this.domainReputations.get(a)}listDomainReputations(){return Array.from(this.domainReputations.values())}getWarmupPlan(a){return this.warmupPlans.get(a)}listWarmupPlans(){return Array.from(this.warmupPlans.values())}clear(){this.dashboards.clear(),this.warmupPlans.clear(),this.domainReputations.clear(),this.dashboardCounter=0,this.warmupCounter=0,this.domainCounter=0}}var GC=new Qg;class Hg{templates=new Map;versions=new Map;tests=new Map;templateCounter=0;testCounter=0;createTemplate(a){let n=`template-${Date.now()}-${this.templateCounter++}`,i=this.extractVariables(a.subject+a.htmlPart+a.textPart),s={id:n,variables:i,createdAt:new Date,updatedAt:new Date,version:1,...a};return this.templates.set(n,s),this.addVersion({templateId:n,version:1,subject:a.subject,htmlPart:a.htmlPart,textPart:a.textPart,createdBy:"system"}),s}createWelcomeTemplate(a){return this.createTemplate({name:a.name,subject:"Welcome to {{companyName}}!",htmlPart:`
3777
3777
  <html>
3778
3778
  <body>
3779
3779
  <h1>Welcome, {{userName}}!</h1>
@@ -4033,7 +4033,7 @@ catch {
4033
4033
  ContentType: 'application/json',
4034
4034
  }));
4035
4035
  }
4036
- `;static createThreadingLambda(a){return{[`${a.slug}EmailThreadingLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-email-threading`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:jt.ThreadingLambdaCode},Environment:{Variables:{EMAIL_BUCKET:a.emailBucket}}}}}}static async getThreads(a){let{s3Client:n,bucket:i,mailbox:s,limit:c=50,offset:l=0}=a,[u,h]=s.includes("@")?s.split("@"):[s,"default"],y=`mailboxes/${h}/${u}/threads.json`;try{let S=await n.send({Bucket:i,Key:y}),b=JSON.parse(S.Body),A=Object.values(b);return A.sort((C,T)=>new Date(T.lastMessageDate).getTime()-new Date(C.lastMessageDate).getTime()),A.slice(l,l+c)}catch{return[]}}static async getThread(a){let{s3Client:n,bucket:i,mailbox:s,threadId:c}=a,[l,u]=s.includes("@")?s.split("@"):[s,"default"],h=`mailboxes/${u}/${l}/threads.json`;try{let y=await n.send({Bucket:i,Key:h});return JSON.parse(y.Body)[c]||null}catch{return null}}}class Kt{static SchedulerLambdaCode=`
4036
+ `;static createThreadingLambda(a){return{[`${a.slug}EmailThreadingLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-email-threading`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:jt.ThreadingLambdaCode},Environment:{Variables:{EMAIL_BUCKET:a.emailBucket}}}}}}static async getThreads(a){let{s3Client:n,bucket:i,mailbox:s,limit:c=50,offset:l=0}=a,[u,h]=s.includes("@")?s.split("@"):[s,"default"],y=`mailboxes/${h}/${u}/threads.json`;try{let S=await n.send({Bucket:i,Key:y}),A=JSON.parse(S.Body),C=Object.values(A);return C.sort((T,v)=>new Date(v.lastMessageDate).getTime()-new Date(T.lastMessageDate).getTime()),C.slice(l,l+c)}catch{return[]}}static async getThread(a){let{s3Client:n,bucket:i,mailbox:s,threadId:c}=a,[l,u]=s.includes("@")?s.split("@"):[s,"default"],h=`mailboxes/${u}/${l}/threads.json`;try{let y=await n.send({Bucket:i,Key:h});return JSON.parse(y.Body)[c]||null}catch{return null}}}class Kt{static SchedulerLambdaCode=`
4037
4037
  const { S3Client, GetObjectCommand, PutObjectCommand, DeleteObjectCommand, ListObjectsV2Command } = require('@aws-sdk/client-s3');
4038
4038
  const { SESClient, SendRawEmailCommand } = require('@aws-sdk/client-ses');
4039
4039
 
@@ -4620,7 +4620,7 @@ The {{appName}} Team`,variables:["appName","userName","resetUrl","expiresIn"],ca
4620
4620
 
4621
4621
  <p>Best regards,<br>The {{appName}} Team</p>
4622
4622
  </body>
4623
- </html>`,variables:["invoiceNumber","customerName","period","items","total","paymentUrl","appName"],category:"billing"}};static createTemplateBucket(a){return{[`${a.slug}EmailTemplateBucket`]:{Type:"AWS::S3::Bucket",Properties:{BucketName:`${a.slug}-email-templates`,VersioningConfiguration:{Status:"Enabled"}}}}}static createTemplateRendererLambda(a){return{[`${a.slug}TemplateRendererLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-template-renderer`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Ne.TemplateRendererCode},Environment:{Variables:{TEMPLATE_BUCKET:a.templateBucket}}}}}}static render(a,n){if(!a||!n)return a;let i=a;return i=i.replace(/\{\{\s*([\w.]+)\s*\}\}/g,(s,c)=>{let l=Ne.getNestedValue(n,c);return l!==void 0?String(l):s}),i=i.replace(/\{\{#if\s+([\w.]+)\}\}([\s\S]*?)\{\{\/if\}\}/g,(s,c,l)=>Ne.getNestedValue(n,c)?l:""),i=i.replace(/\{\{#unless\s+([\w.]+)\}\}([\s\S]*?)\{\{\/unless\}\}/g,(s,c,l)=>!Ne.getNestedValue(n,c)?l:""),i=i.replace(/\{\{#each\s+([\w.]+)\}\}([\s\S]*?)\{\{\/each\}\}/g,(s,c,l)=>{let u=Ne.getNestedValue(n,c);if(!Array.isArray(u))return"";return u.map((h,y)=>{let S=l;if(S=S.replace(/\{\{this\}\}/g,String(h)),S=S.replace(/\{\{@index\}\}/g,String(y)),typeof h==="object")Object.entries(h).forEach(([b,A])=>{S=S.replace(new RegExp(`\\{\\{\\s*${b}\\s*\\}\\}`,"g"),String(A))});return S}).join("")}),i}static getNestedValue(a,n){return n.split(".").reduce((i,s)=>i?.[s],a)}static extractVariables(a){let n=new Set,i=a.matchAll(/\{\{\s*([\w.]+)\s*\}\}/g);for(let c of i)if(!c[1].startsWith("#")&&!c[1].startsWith("/")&&!c[1].startsWith("@"))n.add(c[1].split(".")[0]);let s=a.matchAll(/\{\{#(?:if|unless|each)\s+([\w.]+)\}\}/g);for(let c of s)n.add(c[1].split(".")[0]);return Array.from(n)}}class zt{static SharedMailboxLambdaCode=`
4623
+ </html>`,variables:["invoiceNumber","customerName","period","items","total","paymentUrl","appName"],category:"billing"}};static createTemplateBucket(a){return{[`${a.slug}EmailTemplateBucket`]:{Type:"AWS::S3::Bucket",Properties:{BucketName:`${a.slug}-email-templates`,VersioningConfiguration:{Status:"Enabled"}}}}}static createTemplateRendererLambda(a){return{[`${a.slug}TemplateRendererLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-template-renderer`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Ne.TemplateRendererCode},Environment:{Variables:{TEMPLATE_BUCKET:a.templateBucket}}}}}}static render(a,n){if(!a||!n)return a;let i=a;return i=i.replace(/\{\{\s*([\w.]+)\s*\}\}/g,(s,c)=>{let l=Ne.getNestedValue(n,c);return l!==void 0?String(l):s}),i=i.replace(/\{\{#if\s+([\w.]+)\}\}([\s\S]*?)\{\{\/if\}\}/g,(s,c,l)=>Ne.getNestedValue(n,c)?l:""),i=i.replace(/\{\{#unless\s+([\w.]+)\}\}([\s\S]*?)\{\{\/unless\}\}/g,(s,c,l)=>!Ne.getNestedValue(n,c)?l:""),i=i.replace(/\{\{#each\s+([\w.]+)\}\}([\s\S]*?)\{\{\/each\}\}/g,(s,c,l)=>{let u=Ne.getNestedValue(n,c);if(!Array.isArray(u))return"";return u.map((h,y)=>{let S=l;if(S=S.replace(/\{\{this\}\}/g,String(h)),S=S.replace(/\{\{@index\}\}/g,String(y)),typeof h==="object")Object.entries(h).forEach(([A,C])=>{S=S.replace(new RegExp(`\\{\\{\\s*${A}\\s*\\}\\}`,"g"),String(C))});return S}).join("")}),i}static getNestedValue(a,n){return n.split(".").reduce((i,s)=>i?.[s],a)}static extractVariables(a){let n=new Set,i=a.matchAll(/\{\{\s*([\w.]+)\s*\}\}/g);for(let c of i)if(!c[1].startsWith("#")&&!c[1].startsWith("/")&&!c[1].startsWith("@"))n.add(c[1].split(".")[0]);let s=a.matchAll(/\{\{#(?:if|unless|each)\s+([\w.]+)\}\}/g);for(let c of s)n.add(c[1].split(".")[0]);return Array.from(n)}}class zt{static SharedMailboxLambdaCode=`
4624
4624
  const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
4625
4625
  const { DynamoDBClient, GetItemCommand, PutItemCommand, QueryCommand, UpdateItemCommand } = require('@aws-sdk/client-dynamodb');
4626
4626
 
@@ -6161,7 +6161,7 @@ catch (error) {
6161
6161
  return { statusCode: 500, error: error.message };
6162
6162
  }
6163
6163
  };
6164
- `;static createCallbacksTable(a){return{[`${a.slug}CallbacksTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${a.slug}-callbacks`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createCallbackRequestLambda(a){return{[`${a.slug}CallbackRequestLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-callback-request`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:yt.CallbackRequestCode},Environment:{Variables:{CALLBACKS_TABLE:a.callbacksTable,NOTIFICATION_TOPIC_ARN:a.notificationTopicArn||""}}}}}}static createCallbackProcessorLambda(a){return{[`${a.slug}CallbackProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-callback-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:300,MemorySize:256,Code:{ZipFile:yt.CallbackProcessorCode},Environment:{Variables:{CALLBACKS_TABLE:a.callbacksTable,CONNECT_INSTANCE_ID:a.connectInstanceId,CONTACT_FLOW_ID:a.contactFlowId,SOURCE_PHONE_NUMBER:a.sourcePhoneNumber,QUEUE_ID:a.queueId||""}}}}}}}var iA={};Be(iA,{AbTesting:()=>Ce,LinkTracking:()=>ra,MmsSupport:()=>ta,SmsAnalytics:()=>ea,SmsCampaigns:()=>Xt,SmsChatbot:()=>aa});class Xt{static CampaignManagerCode=`
6164
+ `;static createCallbacksTable(a){return{[`${a.slug}CallbacksTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${a.slug}-callbacks`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createCallbackRequestLambda(a){return{[`${a.slug}CallbackRequestLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-callback-request`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:yt.CallbackRequestCode},Environment:{Variables:{CALLBACKS_TABLE:a.callbacksTable,NOTIFICATION_TOPIC_ARN:a.notificationTopicArn||""}}}}}}static createCallbackProcessorLambda(a){return{[`${a.slug}CallbackProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-callback-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:300,MemorySize:256,Code:{ZipFile:yt.CallbackProcessorCode},Environment:{Variables:{CALLBACKS_TABLE:a.callbacksTable,CONNECT_INSTANCE_ID:a.connectInstanceId,CONTACT_FLOW_ID:a.contactFlowId,SOURCE_PHONE_NUMBER:a.sourcePhoneNumber,QUEUE_ID:a.queueId||""}}}}}}}var iA={};Be(iA,{AbTesting:()=>Ee,LinkTracking:()=>ra,MmsSupport:()=>ta,SmsAnalytics:()=>ea,SmsCampaigns:()=>Xt,SmsChatbot:()=>aa});class Xt{static CampaignManagerCode=`
6165
6165
  const { DynamoDBClient, PutItemCommand, GetItemCommand, UpdateItemCommand, ScanCommand } = require('@aws-sdk/client-dynamodb');
6166
6166
 
6167
6167
  const dynamodb = new DynamoDBClient({});
@@ -7067,7 +7067,7 @@ function generateShortId() {
7067
7067
  }
7068
7068
  return id;
7069
7069
  }
7070
- `;static createLinksTable(a){return{[`${a.slug}ShortLinksTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${a.slug}-short-links`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createLinkShortenerLambda(a){return{[`${a.slug}LinkShortenerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-link-shortener`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:10,MemorySize:128,Code:{ZipFile:ra.LinkShortenerCode},Environment:{Variables:{LINKS_TABLE:a.linksTable,SHORT_DOMAIN:a.shortDomain||""}}}}}}static shortenUrlsInMessage(a,n,i){let s=/(https?:\/\/[^\s]+)/g,c=[],l=0;return{message:a.replace(s,(u)=>{let h=`${i}-${l++}`,y=`https://${n}/l/${h}`;return c.push({original:u,short:y,id:h}),y}),links:c}}}class Ce{static AbTestManagerCode=`
7070
+ `;static createLinksTable(a){return{[`${a.slug}ShortLinksTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${a.slug}-short-links`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createLinkShortenerLambda(a){return{[`${a.slug}LinkShortenerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-link-shortener`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:10,MemorySize:128,Code:{ZipFile:ra.LinkShortenerCode},Environment:{Variables:{LINKS_TABLE:a.linksTable,SHORT_DOMAIN:a.shortDomain||""}}}}}}static shortenUrlsInMessage(a,n,i){let s=/(https?:\/\/[^\s]+)/g,c=[],l=0;return{message:a.replace(s,(u)=>{let h=`${i}-${l++}`,y=`https://${n}/l/${h}`;return c.push({original:u,short:y,id:h}),y}),links:c}}}class Ee{static AbTestManagerCode=`
7071
7071
  const { DynamoDBClient, PutItemCommand, GetItemCommand, UpdateItemCommand, ScanCommand } = require('@aws-sdk/client-dynamodb');
7072
7072
 
7073
7073
  const dynamodb = new DynamoDBClient({});
@@ -7261,7 +7261,7 @@ function unmarshallTest(item) {
7261
7261
 
7262
7262
  return test;
7263
7263
  }
7264
- `;static createAbTestsTable(a){return{[`${a.slug}AbTestsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${a.slug}-ab-tests`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}}static createAbTestManagerLambda(a){return{[`${a.slug}AbTestManagerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-ab-test-manager`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Ce.AbTestManagerCode},Environment:{Variables:{AB_TESTS_TABLE:a.abTestsTable}}}}}}static selectVariant(a,n){let i=Ce.hashString(n+a.id)%100,s=0;for(let c=0;c<a.variants.length;c++)if(s+=a.trafficSplit[c],i<s)return a.variants[c];return a.variants[a.variants.length-1]}static determineWinner(a){if(a.variants.length===0)return null;let n=a.winningCriteria,i=a.variants[0],s=Ce.getMetricValue(i,n);for(let c of a.variants.slice(1)){let l=Ce.getMetricValue(c,n);if(l>s)s=l,i=c}return i}static calculateSignificance(a,n,i){let s=a.stats.sent,c=n.stats.sent;if(s<30||c<30)return 0;let l=Ce.getMetricValue(a,i)/100,u=Ce.getMetricValue(n,i)/100,h=(l*s+u*c)/(s+c),y=Math.sqrt(h*(1-h)*(1/s+1/c));if(y===0)return 0;let S=Math.abs(l-u)/y;if(S>=2.576)return 99;if(S>=1.96)return 95;if(S>=1.645)return 90;if(S>=1.28)return 80;return Math.round(S*30)}static getMetricValue(a,n){switch(n){case"delivery_rate":return a.stats.deliveryRate;case"click_rate":return a.stats.clickRate;case"reply_rate":return a.stats.replyRate;case"conversion_rate":return a.stats.conversionRate;default:return a.stats.deliveryRate}}static hashString(a){let n=0;for(let i=0;i<a.length;i++){let s=a.charCodeAt(i);n=(n<<5)-n+s,n=n&n}return Math.abs(n)}}class Gg{queues=new Map;messageGroups=new Map;deduplicationConfigs=new Map;messages=new Map;queueCounter=0;groupCounter=0;deduplicationCounter=0;messageCounter=0;sequenceCounter=0;createFIFOQueue(a){let n=`fifo-queue-${Date.now()}-${this.queueCounter++}`,i=a.name.endsWith(".fifo")?a.name:`${a.name}.fifo`,{name:s,...c}=a,l={id:n,name:i,queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${i}`,...c};return this.queues.set(n,l),this.createDeduplicationConfig({queueId:n,contentBasedDeduplication:a.contentBasedDeduplication,deduplicationInterval:300}),l}createHighThroughputFIFO(a){return this.createFIFOQueue({name:a.name,contentBasedDeduplication:a.contentBasedDeduplication??!0,deduplicationScope:"messageGroup",fifoThroughputLimit:"perMessageGroupId",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createStandardFIFO(a){return this.createFIFOQueue({name:a.name,contentBasedDeduplication:a.contentBasedDeduplication??!1,deduplicationScope:"queue",fifoThroughputLimit:"perQueue",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createDeduplicationConfig(a){let n={id:`dedup-${Date.now()}-${this.deduplicationCounter++}`,deduplicationHashes:new Map,...a};return this.deduplicationConfigs.set(a.queueId,n),n}sendMessage(a){let n=this.queues.get(a.queueId);if(!n)throw Error(`Queue not found: ${a.queueId}`);let i=this.deduplicationConfigs.get(a.queueId);if(i){let u=a.messageDeduplicationId||(n.contentBasedDeduplication?this.generateHash(a.messageBody):void 0);if(u&&this.isDuplicate(i,u))return null;if(u)i.deduplicationHashes.set(u,new Date)}let s=`msg-${Date.now()}-${this.messageCounter++}`,c=this.generateSequenceNumber(),l={id:s,messageId:s,messageGroupId:a.messageGroupId,messageDeduplicationId:a.messageDeduplicationId,body:a.messageBody,attributes:a.messageAttributes||{},sentTimestamp:new Date,sequenceNumber:c};return this.messages.set(s,l),this.updateMessageGroup(a.queueId,a.messageGroupId),l}isDuplicate(a,n){let i=a.deduplicationHashes.get(n);if(!i)return!1;if((Date.now()-i.getTime())/1000>a.deduplicationInterval)return a.deduplicationHashes.delete(n),!1;return!0}generateHash(a){let n=0;for(let i=0;i<a.length;i++){let s=a.charCodeAt(i);n=(n<<5)-n+s,n=n&n}return Math.abs(n).toString(36)}generateSequenceNumber(){return`${Date.now()}${this.sequenceCounter++}`.padStart(20,"0")}updateMessageGroup(a,n){let i=`${a}-${n}`,s=this.messageGroups.get(i);if(!s)s={id:`group-${Date.now()}-${this.groupCounter++}`,messageGroupId:n,queueId:a,messagesInFlight:0},this.messageGroups.set(i,s);s.messagesInFlight++,s.lastMessageTimestamp=new Date}getMessageGroups(a){return Array.from(this.messageGroups.values()).filter((n)=>n.queueId===a)}getQueue(a){return this.queues.get(a)}listQueues(){return Array.from(this.queues.values())}getMessages(a,n){let i=Array.from(this.messages.values());if(n)i=i.filter((s)=>s.messageGroupId===n);return i.sort((s,c)=>s.sequenceNumber.localeCompare(c.sequenceNumber))}generateFIFOQueueCF(a){return{Type:"AWS::SQS::Queue",Properties:{QueueName:a.name,FifoQueue:!0,ContentBasedDeduplication:a.contentBasedDeduplication,DeduplicationScope:a.deduplicationScope,FifoThroughputLimit:a.fifoThroughputLimit,MessageRetentionPeriod:a.messageRetentionPeriod,VisibilityTimeout:a.visibilityTimeout,ReceiveMessageWaitTimeSeconds:a.receiveMessageWaitTime,...a.deadLetterTargetArn&&{RedrivePolicy:{deadLetterTargetArn:a.deadLetterTargetArn,maxReceiveCount:a.maxReceiveCount||3}}}}}clear(){this.queues.clear(),this.messageGroups.clear(),this.deduplicationConfigs.clear(),this.messages.clear(),this.queueCounter=0,this.groupCounter=0,this.deduplicationCounter=0,this.messageCounter=0,this.sequenceCounter=0}}var VC=new Gg;class qg{monitors=new Map;metrics=new Map;alerts=new Map;reprocessJobs=new Map;monitorCounter=0;metricsCounter=0;alertCounter=0;jobCounter=0;createDLQMonitor(a){let n=`dlq-monitor-${Date.now()}-${this.monitorCounter++}`,i={id:n,...a};return this.monitors.set(n,i),i}createAutomatedMonitor(a){return this.createDLQMonitor({name:a.name,queueUrl:a.queueUrl,sourceQueues:a.sourceQueues,maxReceiveCount:3,alarmThreshold:10,autoReprocess:!0,reprocessStrategy:"scheduled",notificationTopicArn:a.notificationTopicArn})}collectMetrics(a){let n={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:a,timestamp:new Date,approximateNumberOfMessages:Math.floor(Math.random()*100),approximateAgeOfOldestMessage:Math.floor(Math.random()*86400),messagesReceived:Math.floor(Math.random()*50),messagesDeleted:Math.floor(Math.random()*30),messagesReprocessed:Math.floor(Math.random()*20)},i=this.metrics.get(a)||[];return i.push(n),this.metrics.set(a,i),this.checkForAlerts(a,n),n}checkForAlerts(a,n){let i=Array.from(this.monitors.values()).find((c)=>c.queueUrl===a);if(!i)return;if(n.approximateNumberOfMessages>=i.alarmThreshold)this.createAlert({monitorId:i.id,alertType:"threshold_exceeded",severity:"high",message:`DLQ ${i.name} has ${n.approximateNumberOfMessages} messages (threshold: ${i.alarmThreshold})`});let s=3600;if(n.approximateAgeOfOldestMessage>s)this.createAlert({monitorId:i.id,alertType:"old_message",severity:"medium",message:`DLQ ${i.name} has messages older than ${s} seconds`})}createAlert(a){let n=`alert-${Date.now()}-${this.alertCounter++}`,i={id:n,timestamp:new Date,acknowledged:!1,...a};return this.alerts.set(n,i),i}acknowledgeAlert(a){let n=this.alerts.get(a);if(!n)throw Error(`Alert not found: ${a}`);return n.acknowledged=!0,n}createReprocessJob(a){let n=`reprocess-${Date.now()}-${this.jobCounter++}`,i={id:n,queueUrl:a.queueUrl,messageId:a.messageId,attempts:0,status:"pending"};return this.reprocessJobs.set(n,i),i}async executeReprocessJob(a){let n=this.reprocessJobs.get(a);if(!n)throw Error(`Reprocess job not found: ${a}`);n.status="processing",n.startedAt=new Date,n.attempts++,await new Promise((s)=>setTimeout(s,100));let i=Math.random()>0.3;if(n.status=i?"success":"failed",n.completedAt=new Date,!i)n.error="Reprocessing failed - original error still present";return n}async batchReprocess(a){let n=[];for(let i=0;i<a.maxMessages;i++){let s=this.createReprocessJob({queueUrl:a.queueUrl,messageId:`msg-${i}`});await this.executeReprocessJob(s.id),n.push(s)}return n}getDLQStatistics(a,n=24){let i=new Date(Date.now()-n*60*60*1000),s=(this.metrics.get(a)||[]).filter((b)=>b.timestamp>=i);if(s.length===0)return{totalMessages:0,avgAge:0,messagesReceived:0,messagesDeleted:0,messagesReprocessed:0,successRate:0};let c=s[s.length-1],l=s.reduce((b,A)=>b+A.messagesReceived,0),u=s.reduce((b,A)=>b+A.messagesDeleted,0),h=s.reduce((b,A)=>b+A.messagesReprocessed,0),y=s.reduce((b,A)=>b+A.approximateAgeOfOldestMessage,0)/s.length,S=h>0?u/h*100:0;return{totalMessages:c.approximateNumberOfMessages,avgAge:y,messagesReceived:l,messagesDeleted:u,messagesReprocessed:h,successRate:S}}getMonitor(a){return this.monitors.get(a)}listMonitors(){return Array.from(this.monitors.values())}getAlerts(a,n){let i=Array.from(this.alerts.values());if(a)i=i.filter((s)=>s.monitorId===a);if(n!==void 0)i=i.filter((s)=>s.acknowledged===n);return i.sort((s,c)=>c.timestamp.getTime()-s.timestamp.getTime())}getReprocessJobs(a){let n=Array.from(this.reprocessJobs.values());if(a)n=n.filter((i)=>i.queueUrl===a);return n}generateDLQAlarmCF(a){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${a.name}-messages-alarm`,AlarmDescription:`Alert when DLQ ${a.name} exceeds threshold`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Average",Period:300,EvaluationPeriods:1,Threshold:a.alarmThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:a.queueUrl.split("/").pop()}],...a.notificationTopicArn&&{AlarmActions:[a.notificationTopicArn]}}}}clear(){this.monitors.clear(),this.metrics.clear(),this.alerts.clear(),this.reprocessJobs.clear(),this.monitorCounter=0,this.metricsCounter=0,this.alertCounter=0,this.jobCounter=0}}var jC=new qg;class Vg{configs=new Map;jobs=new Map;metrics=new Map;configCounter=0;jobCounter=0;metricsCounter=0;createBatchConfig(a){let n=`batch-config-${Date.now()}-${this.configCounter++}`,i={id:n,...a};return this.configs.set(n,i),i}createHighThroughputConfig(a){return this.createBatchConfig({queueUrl:a.queueUrl,batchSize:10,maxWaitTime:100,parallelProcessors:10,retryAttempts:3,visibilityTimeout:30})}createLowLatencyConfig(a){return this.createBatchConfig({queueUrl:a.queueUrl,batchSize:1,maxWaitTime:0,parallelProcessors:5,retryAttempts:2,visibilityTimeout:10})}createBatchJob(a){let n=`batch-job-${Date.now()}-${this.jobCounter++}`;if(!this.configs.get(a.configId))throw Error(`Batch config not found: ${a.configId}`);let i=[];for(let c=0;c<a.messageCount;c++)i.push({id:`msg-${n}-${c}`,messageId:`${n}-${c}`,body:`Message ${c}`,receiptHandle:`receipt-${n}-${c}`,attributes:{},status:"pending"});let s={id:n,configId:a.configId,messages:i,status:"pending",processedCount:0,failedCount:0};return this.jobs.set(n,s),s}async processBatchJob(a){let n=this.jobs.get(a);if(!n)throw Error(`Batch job not found: ${a}`);let i=this.configs.get(n.configId);if(!i)throw Error(`Batch config not found: ${n.configId}`);n.status="processing",n.startedAt=new Date;let s=this.chunkArray(n.messages,i.batchSize);for(let c of s)await this.processBatch(c,i);return n.processedCount=n.messages.filter((c)=>c.status==="success").length,n.failedCount=n.messages.filter((c)=>c.status==="failed").length,n.status=n.failedCount===0?"completed":"failed",n.completedAt=new Date,this.collectProcessorMetrics(i.id,n),n}async processBatch(a,n){let i=a.map((s)=>this.processMessage(s,n));await Promise.all(i)}async processMessage(a,n){a.status="processing";let i=Date.now();await new Promise((c)=>setTimeout(c,Math.random()*100));let s=Date.now()-i;if(a.processingTime=s,Math.random()>0.1)a.status="success";else a.status="failed",a.error="Processing error"}chunkArray(a,n){let i=[];for(let s=0;s<a.length;s+=n)i.push(a.slice(s,s+n));return i}collectProcessorMetrics(a,n){let i=`metrics-${Date.now()}-${this.metricsCounter++}`,s=n.messages.filter((b)=>b.status==="success").map((b)=>b.processingTime||0).filter((b)=>b>0),c=s.length>0?s.reduce((b,A)=>b+A,0)/s.length:0,l=n.completedAt&&n.startedAt?(n.completedAt.getTime()-n.startedAt.getTime())/1000:1,u=n.processedCount/l,h=n.messages.length>0?n.failedCount/n.messages.length*100:0,y={id:i,configId:a,timestamp:new Date,messagesProcessed:n.processedCount,averageProcessingTime:c,throughput:u,errorRate:h},S=this.metrics.get(a)||[];S.push(y),this.metrics.set(a,S)}getBatchStatistics(a){let n=this.metrics.get(a)||[];if(n.length===0)return{totalJobsProcessed:0,totalMessagesProcessed:0,averageThroughput:0,averageErrorRate:0,averageProcessingTime:0};let i=n.reduce((u,h)=>u+h.messagesProcessed,0),s=n.reduce((u,h)=>u+h.throughput,0)/n.length,c=n.reduce((u,h)=>u+h.errorRate,0)/n.length,l=n.reduce((u,h)=>u+h.averageProcessingTime,0)/n.length;return{totalJobsProcessed:n.length,totalMessagesProcessed:i,averageThroughput:s,averageErrorRate:c,averageProcessingTime:l}}optimizeBatchConfig(a){let n=this.configs.get(a);if(!n)throw Error(`Batch config not found: ${a}`);let i=this.getBatchStatistics(a);if(i.averageErrorRate<5&&n.batchSize<10)n.batchSize=Math.min(10,n.batchSize+1);if(i.averageErrorRate>20&&n.batchSize>1)n.batchSize=Math.max(1,n.batchSize-1);if(i.averageThroughput<5&&n.parallelProcessors<20)n.parallelProcessors++;return n}getConfig(a){return this.configs.get(a)}listConfigs(){return Array.from(this.configs.values())}getJob(a){return this.jobs.get(a)}listJobs(a){let n=Array.from(this.jobs.values());if(a)n=n.filter((i)=>i.configId===a);return n}generateBatchProcessorCF(a){return{Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:`arn:aws:sqs:us-east-1:123456789012:${a.queueUrl.split("/").pop()}`,FunctionName:"batch-processor-function",BatchSize:a.batchSize,MaximumBatchingWindowInSeconds:a.maxWaitTime/1000,FunctionResponseTypes:["ReportBatchItemFailures"]}}}clear(){this.configs.clear(),this.jobs.clear(),this.metrics.clear(),this.configCounter=0,this.jobCounter=0,this.metricsCounter=0}}var zC=new Vg;class jg{queues=new Map;retentionPolicies=new Map;delayQueues=new Map;purgeOperations=new Map;metrics=new Map;queueCounter=0;retentionCounter=0;delayCounter=0;purgeCounter=0;metricsCounter=0;createQueue(a){let n=`queue-${Date.now()}-${this.queueCounter++}`,i={id:n,purgeInProgress:!1,...a};return this.queues.set(n,i),i}createStandardQueue(a){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${a.queueName}`,queueName:a.queueName,messageRetentionPeriod:(a.messageRetentionDays||4)*24*60*60,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:0})}createLongPollingQueue(a){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${a.queueName}`,queueName:a.queueName,messageRetentionPeriod:345600,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:a.waitTimeSeconds||20})}createRetentionPolicy(a){let n=`retention-${Date.now()}-${this.retentionCounter++}`,i={id:n,...a};this.retentionPolicies.set(n,i);let s=this.queues.get(a.queueId);if(s)s.messageRetentionPeriod=a.retentionPeriod;return i}createShortRetentionPolicy(a){return this.createRetentionPolicy({queueId:a.queueId,retentionPeriod:a.retentionHours*60*60,autoCleanup:!0,archiveExpiredMessages:!1})}createArchivalRetentionPolicy(a){return this.createRetentionPolicy({queueId:a.queueId,retentionPeriod:a.retentionDays*24*60*60,autoCleanup:!0,cleanupSchedule:"cron(0 0 * * ? *)",archiveExpiredMessages:!0,archiveS3Bucket:a.s3Bucket})}createDelayQueue(a){let n=`delay-${Date.now()}-${this.delayCounter++}`,i={id:n,...a};this.delayQueues.set(n,i);let s=Array.from(this.queues.values()).find((c)=>c.queueUrl===a.queueUrl);if(s)s.delaySeconds=a.defaultDelay;return i}createScheduledDelayQueue(a){return this.createDelayQueue({queueUrl:a.queueUrl,defaultDelay:a.delayMinutes*60,perMessageDelay:!1,maxDelay:900})}async purgeQueue(a){let n=this.queues.get(a);if(!n)throw Error(`Queue not found: ${a}`);if(n.purgeInProgress)throw Error("Purge already in progress for this queue");let i=`purge-${Date.now()}-${this.purgeCounter++}`,s={id:i,queueUrl:n.queueUrl,status:"in_progress",startedAt:new Date};return this.purgeOperations.set(i,s),n.purgeInProgress=!0,setTimeout(()=>{s.status="completed",s.completedAt=new Date,s.messagesPurged=Math.floor(Math.random()*1000),n.purgeInProgress=!1},100),s}collectQueueMetrics(a){let n={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:a,timestamp:new Date,approximateNumberOfMessages:Math.floor(Math.random()*1000),approximateNumberOfMessagesNotVisible:Math.floor(Math.random()*100),approximateNumberOfMessagesDelayed:Math.floor(Math.random()*50),oldestMessageAge:Math.floor(Math.random()*86400)},i=this.metrics.get(a)||[];return i.push(n),this.metrics.set(a,i),n}getQueueHealth(a){let n=this.metrics.get(a)||[];if(n.length===0)return{status:"healthy",issues:[],recommendations:[]};let i=n[n.length-1],s=[],c=[],l="healthy";if(i.approximateNumberOfMessages>1e4)l="critical",s.push("Large message backlog detected"),c.push("Increase consumer capacity");else if(i.approximateNumberOfMessages>1000)l="warning",s.push("Growing message backlog"),c.push("Monitor consumer performance");if(i.oldestMessageAge&&i.oldestMessageAge>3600){if(l!=="critical")l="warning";s.push("Old messages in queue"),c.push("Review message processing")}if(i.approximateNumberOfMessagesDelayed>100){if(l!=="critical")l="warning";s.push("High number of delayed messages")}return{status:l,issues:s,recommendations:c}}getQueue(a){return this.queues.get(a)}listQueues(){return Array.from(this.queues.values())}getRetentionPolicy(a){return this.retentionPolicies.get(a)}listRetentionPolicies(){return Array.from(this.retentionPolicies.values())}getPurgeOperations(a){let n=Array.from(this.purgeOperations.values());if(a)n=n.filter((i)=>i.queueUrl===a);return n}generateQueueCF(a){return{Type:"AWS::SQS::Queue",Properties:{QueueName:a.queueName,MessageRetentionPeriod:a.messageRetentionPeriod,DelaySeconds:a.delaySeconds,MaximumMessageSize:a.maximumMessageSize,ReceiveMessageWaitTimeSeconds:a.receiveMessageWaitTime}}}generateCleanupRuleCF(a){return{Type:"AWS::Events::Rule",Properties:{Name:`${a.id}-cleanup`,Description:"Automated queue cleanup",ScheduleExpression:a.cleanupSchedule||"cron(0 0 * * ? *)",State:"ENABLED",Targets:[{Arn:"arn:aws:lambda:us-east-1:123456789012:function:queue-cleanup",Id:a.id,Input:JSON.stringify({queueId:a.queueId,archiveBucket:a.archiveS3Bucket})}]}}}clear(){this.queues.clear(),this.retentionPolicies.clear(),this.delayQueues.clear(),this.purgeOperations.clear(),this.metrics.clear(),this.queueCounter=0,this.retentionCounter=0,this.delayCounter=0,this.purgeCounter=0,this.metricsCounter=0}}var KC=new jg,_n=(()=>{let a=[];for(let n=0;n<256;n++){let i=n;for(let s=0;s<8;s++)i=i&1?3988292384^i>>>1:i>>>1;a[n]=i>>>0}return a})();function Wn(a){let n=4294967295;for(let i=0;i<a.length;i++)n=_n[(n^a[i])&255]^n>>>8;return(n^4294967295)>>>0}function Gn(a){if(typeof a==="string")return Buffer.from(a,"utf-8");if(Buffer.isBuffer(a))return a;return Buffer.from(a)}function Un(a){let n=Math.max(1980,a.getFullYear()),i=(a.getHours()<<11|a.getMinutes()<<5|a.getSeconds()>>1)&65535,s=(n-1980<<9|a.getMonth()+1<<5|a.getDate())&65535;return{time:i,date:s}}function Si(a){let n=[],i=[],s=0;for(let u of a){let h=Gn(u.data),y=Bn(h),S=Wn(h),b=Buffer.from(u.name.replace(/\\/g,"/"),"utf-8"),{time:A,date:C}=Un(u.date??new Date(0)),T=u.mode??420,v=Buffer.alloc(30+b.length);v.writeUInt32LE(67324752,0),v.writeUInt16LE(20,4),v.writeUInt16LE(0,6),v.writeUInt16LE(8,8),v.writeUInt16LE(A,10),v.writeUInt16LE(C,12),v.writeUInt32LE(S,14),v.writeUInt32LE(y.length,18),v.writeUInt32LE(h.length,22),v.writeUInt16LE(b.length,26),v.writeUInt16LE(0,28),b.copy(v,30);let w=Buffer.alloc(46+b.length);w.writeUInt32LE(33639248,0),w.writeUInt16LE(798,4),w.writeUInt16LE(20,6),w.writeUInt16LE(0,8),w.writeUInt16LE(8,10),w.writeUInt16LE(A,12),w.writeUInt16LE(C,14),w.writeUInt32LE(S,16),w.writeUInt32LE(y.length,20),w.writeUInt32LE(h.length,24),w.writeUInt16LE(b.length,28),w.writeUInt16LE(0,30),w.writeUInt16LE(0,32),w.writeUInt16LE(0,34),w.writeUInt16LE(0,36),w.writeUInt32LE((T&65535)<<16,38),w.writeUInt32LE(s,42),b.copy(w,46),n.push(v,y),i.push(w),s+=v.length+y.length}let c=Buffer.concat(i),l=Buffer.alloc(22);return l.writeUInt32LE(101010256,0),l.writeUInt16LE(0,4),l.writeUInt16LE(0,6),l.writeUInt16LE(a.length,8),l.writeUInt16LE(a.length,10),l.writeUInt32LE(c.length,12),l.writeUInt32LE(s,16),l.writeUInt16LE(0,20),Buffer.concat([...n,c,l])}function sA(a){let n=a.adapterImport??"./adapter",i=a.entryImport.replace(/\\/g,"/");return`// Generated by ts-cloud — serverless app bootstrap. Do not edit.
7264
+ `;static createAbTestsTable(a){return{[`${a.slug}AbTestsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${a.slug}-ab-tests`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}}static createAbTestManagerLambda(a){return{[`${a.slug}AbTestManagerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-ab-test-manager`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Ee.AbTestManagerCode},Environment:{Variables:{AB_TESTS_TABLE:a.abTestsTable}}}}}}static selectVariant(a,n){let i=Ee.hashString(n+a.id)%100,s=0;for(let c=0;c<a.variants.length;c++)if(s+=a.trafficSplit[c],i<s)return a.variants[c];return a.variants[a.variants.length-1]}static determineWinner(a){if(a.variants.length===0)return null;let n=a.winningCriteria,i=a.variants[0],s=Ee.getMetricValue(i,n);for(let c of a.variants.slice(1)){let l=Ee.getMetricValue(c,n);if(l>s)s=l,i=c}return i}static calculateSignificance(a,n,i){let s=a.stats.sent,c=n.stats.sent;if(s<30||c<30)return 0;let l=Ee.getMetricValue(a,i)/100,u=Ee.getMetricValue(n,i)/100,h=(l*s+u*c)/(s+c),y=Math.sqrt(h*(1-h)*(1/s+1/c));if(y===0)return 0;let S=Math.abs(l-u)/y;if(S>=2.576)return 99;if(S>=1.96)return 95;if(S>=1.645)return 90;if(S>=1.28)return 80;return Math.round(S*30)}static getMetricValue(a,n){switch(n){case"delivery_rate":return a.stats.deliveryRate;case"click_rate":return a.stats.clickRate;case"reply_rate":return a.stats.replyRate;case"conversion_rate":return a.stats.conversionRate;default:return a.stats.deliveryRate}}static hashString(a){let n=0;for(let i=0;i<a.length;i++){let s=a.charCodeAt(i);n=(n<<5)-n+s,n=n&n}return Math.abs(n)}}class Gg{queues=new Map;messageGroups=new Map;deduplicationConfigs=new Map;messages=new Map;queueCounter=0;groupCounter=0;deduplicationCounter=0;messageCounter=0;sequenceCounter=0;createFIFOQueue(a){let n=`fifo-queue-${Date.now()}-${this.queueCounter++}`,i=a.name.endsWith(".fifo")?a.name:`${a.name}.fifo`,{name:s,...c}=a,l={id:n,name:i,queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${i}`,...c};return this.queues.set(n,l),this.createDeduplicationConfig({queueId:n,contentBasedDeduplication:a.contentBasedDeduplication,deduplicationInterval:300}),l}createHighThroughputFIFO(a){return this.createFIFOQueue({name:a.name,contentBasedDeduplication:a.contentBasedDeduplication??!0,deduplicationScope:"messageGroup",fifoThroughputLimit:"perMessageGroupId",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createStandardFIFO(a){return this.createFIFOQueue({name:a.name,contentBasedDeduplication:a.contentBasedDeduplication??!1,deduplicationScope:"queue",fifoThroughputLimit:"perQueue",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createDeduplicationConfig(a){let n={id:`dedup-${Date.now()}-${this.deduplicationCounter++}`,deduplicationHashes:new Map,...a};return this.deduplicationConfigs.set(a.queueId,n),n}sendMessage(a){let n=this.queues.get(a.queueId);if(!n)throw Error(`Queue not found: ${a.queueId}`);let i=this.deduplicationConfigs.get(a.queueId);if(i){let u=a.messageDeduplicationId||(n.contentBasedDeduplication?this.generateHash(a.messageBody):void 0);if(u&&this.isDuplicate(i,u))return null;if(u)i.deduplicationHashes.set(u,new Date)}let s=`msg-${Date.now()}-${this.messageCounter++}`,c=this.generateSequenceNumber(),l={id:s,messageId:s,messageGroupId:a.messageGroupId,messageDeduplicationId:a.messageDeduplicationId,body:a.messageBody,attributes:a.messageAttributes||{},sentTimestamp:new Date,sequenceNumber:c};return this.messages.set(s,l),this.updateMessageGroup(a.queueId,a.messageGroupId),l}isDuplicate(a,n){let i=a.deduplicationHashes.get(n);if(!i)return!1;if((Date.now()-i.getTime())/1000>a.deduplicationInterval)return a.deduplicationHashes.delete(n),!1;return!0}generateHash(a){let n=0;for(let i=0;i<a.length;i++){let s=a.charCodeAt(i);n=(n<<5)-n+s,n=n&n}return Math.abs(n).toString(36)}generateSequenceNumber(){return`${Date.now()}${this.sequenceCounter++}`.padStart(20,"0")}updateMessageGroup(a,n){let i=`${a}-${n}`,s=this.messageGroups.get(i);if(!s)s={id:`group-${Date.now()}-${this.groupCounter++}`,messageGroupId:n,queueId:a,messagesInFlight:0},this.messageGroups.set(i,s);s.messagesInFlight++,s.lastMessageTimestamp=new Date}getMessageGroups(a){return Array.from(this.messageGroups.values()).filter((n)=>n.queueId===a)}getQueue(a){return this.queues.get(a)}listQueues(){return Array.from(this.queues.values())}getMessages(a,n){let i=Array.from(this.messages.values());if(n)i=i.filter((s)=>s.messageGroupId===n);return i.sort((s,c)=>s.sequenceNumber.localeCompare(c.sequenceNumber))}generateFIFOQueueCF(a){return{Type:"AWS::SQS::Queue",Properties:{QueueName:a.name,FifoQueue:!0,ContentBasedDeduplication:a.contentBasedDeduplication,DeduplicationScope:a.deduplicationScope,FifoThroughputLimit:a.fifoThroughputLimit,MessageRetentionPeriod:a.messageRetentionPeriod,VisibilityTimeout:a.visibilityTimeout,ReceiveMessageWaitTimeSeconds:a.receiveMessageWaitTime,...a.deadLetterTargetArn&&{RedrivePolicy:{deadLetterTargetArn:a.deadLetterTargetArn,maxReceiveCount:a.maxReceiveCount||3}}}}}clear(){this.queues.clear(),this.messageGroups.clear(),this.deduplicationConfigs.clear(),this.messages.clear(),this.queueCounter=0,this.groupCounter=0,this.deduplicationCounter=0,this.messageCounter=0,this.sequenceCounter=0}}var VC=new Gg;class qg{monitors=new Map;metrics=new Map;alerts=new Map;reprocessJobs=new Map;monitorCounter=0;metricsCounter=0;alertCounter=0;jobCounter=0;createDLQMonitor(a){let n=`dlq-monitor-${Date.now()}-${this.monitorCounter++}`,i={id:n,...a};return this.monitors.set(n,i),i}createAutomatedMonitor(a){return this.createDLQMonitor({name:a.name,queueUrl:a.queueUrl,sourceQueues:a.sourceQueues,maxReceiveCount:3,alarmThreshold:10,autoReprocess:!0,reprocessStrategy:"scheduled",notificationTopicArn:a.notificationTopicArn})}collectMetrics(a){let n={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:a,timestamp:new Date,approximateNumberOfMessages:Math.floor(Math.random()*100),approximateAgeOfOldestMessage:Math.floor(Math.random()*86400),messagesReceived:Math.floor(Math.random()*50),messagesDeleted:Math.floor(Math.random()*30),messagesReprocessed:Math.floor(Math.random()*20)},i=this.metrics.get(a)||[];return i.push(n),this.metrics.set(a,i),this.checkForAlerts(a,n),n}checkForAlerts(a,n){let i=Array.from(this.monitors.values()).find((c)=>c.queueUrl===a);if(!i)return;if(n.approximateNumberOfMessages>=i.alarmThreshold)this.createAlert({monitorId:i.id,alertType:"threshold_exceeded",severity:"high",message:`DLQ ${i.name} has ${n.approximateNumberOfMessages} messages (threshold: ${i.alarmThreshold})`});let s=3600;if(n.approximateAgeOfOldestMessage>s)this.createAlert({monitorId:i.id,alertType:"old_message",severity:"medium",message:`DLQ ${i.name} has messages older than ${s} seconds`})}createAlert(a){let n=`alert-${Date.now()}-${this.alertCounter++}`,i={id:n,timestamp:new Date,acknowledged:!1,...a};return this.alerts.set(n,i),i}acknowledgeAlert(a){let n=this.alerts.get(a);if(!n)throw Error(`Alert not found: ${a}`);return n.acknowledged=!0,n}createReprocessJob(a){let n=`reprocess-${Date.now()}-${this.jobCounter++}`,i={id:n,queueUrl:a.queueUrl,messageId:a.messageId,attempts:0,status:"pending"};return this.reprocessJobs.set(n,i),i}async executeReprocessJob(a){let n=this.reprocessJobs.get(a);if(!n)throw Error(`Reprocess job not found: ${a}`);n.status="processing",n.startedAt=new Date,n.attempts++,await new Promise((s)=>setTimeout(s,100));let i=Math.random()>0.3;if(n.status=i?"success":"failed",n.completedAt=new Date,!i)n.error="Reprocessing failed - original error still present";return n}async batchReprocess(a){let n=[];for(let i=0;i<a.maxMessages;i++){let s=this.createReprocessJob({queueUrl:a.queueUrl,messageId:`msg-${i}`});await this.executeReprocessJob(s.id),n.push(s)}return n}getDLQStatistics(a,n=24){let i=new Date(Date.now()-n*60*60*1000),s=(this.metrics.get(a)||[]).filter((A)=>A.timestamp>=i);if(s.length===0)return{totalMessages:0,avgAge:0,messagesReceived:0,messagesDeleted:0,messagesReprocessed:0,successRate:0};let c=s[s.length-1],l=s.reduce((A,C)=>A+C.messagesReceived,0),u=s.reduce((A,C)=>A+C.messagesDeleted,0),h=s.reduce((A,C)=>A+C.messagesReprocessed,0),y=s.reduce((A,C)=>A+C.approximateAgeOfOldestMessage,0)/s.length,S=h>0?u/h*100:0;return{totalMessages:c.approximateNumberOfMessages,avgAge:y,messagesReceived:l,messagesDeleted:u,messagesReprocessed:h,successRate:S}}getMonitor(a){return this.monitors.get(a)}listMonitors(){return Array.from(this.monitors.values())}getAlerts(a,n){let i=Array.from(this.alerts.values());if(a)i=i.filter((s)=>s.monitorId===a);if(n!==void 0)i=i.filter((s)=>s.acknowledged===n);return i.sort((s,c)=>c.timestamp.getTime()-s.timestamp.getTime())}getReprocessJobs(a){let n=Array.from(this.reprocessJobs.values());if(a)n=n.filter((i)=>i.queueUrl===a);return n}generateDLQAlarmCF(a){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${a.name}-messages-alarm`,AlarmDescription:`Alert when DLQ ${a.name} exceeds threshold`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Average",Period:300,EvaluationPeriods:1,Threshold:a.alarmThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:a.queueUrl.split("/").pop()}],...a.notificationTopicArn&&{AlarmActions:[a.notificationTopicArn]}}}}clear(){this.monitors.clear(),this.metrics.clear(),this.alerts.clear(),this.reprocessJobs.clear(),this.monitorCounter=0,this.metricsCounter=0,this.alertCounter=0,this.jobCounter=0}}var jC=new qg;class Vg{configs=new Map;jobs=new Map;metrics=new Map;configCounter=0;jobCounter=0;metricsCounter=0;createBatchConfig(a){let n=`batch-config-${Date.now()}-${this.configCounter++}`,i={id:n,...a};return this.configs.set(n,i),i}createHighThroughputConfig(a){return this.createBatchConfig({queueUrl:a.queueUrl,batchSize:10,maxWaitTime:100,parallelProcessors:10,retryAttempts:3,visibilityTimeout:30})}createLowLatencyConfig(a){return this.createBatchConfig({queueUrl:a.queueUrl,batchSize:1,maxWaitTime:0,parallelProcessors:5,retryAttempts:2,visibilityTimeout:10})}createBatchJob(a){let n=`batch-job-${Date.now()}-${this.jobCounter++}`;if(!this.configs.get(a.configId))throw Error(`Batch config not found: ${a.configId}`);let i=[];for(let c=0;c<a.messageCount;c++)i.push({id:`msg-${n}-${c}`,messageId:`${n}-${c}`,body:`Message ${c}`,receiptHandle:`receipt-${n}-${c}`,attributes:{},status:"pending"});let s={id:n,configId:a.configId,messages:i,status:"pending",processedCount:0,failedCount:0};return this.jobs.set(n,s),s}async processBatchJob(a){let n=this.jobs.get(a);if(!n)throw Error(`Batch job not found: ${a}`);let i=this.configs.get(n.configId);if(!i)throw Error(`Batch config not found: ${n.configId}`);n.status="processing",n.startedAt=new Date;let s=this.chunkArray(n.messages,i.batchSize);for(let c of s)await this.processBatch(c,i);return n.processedCount=n.messages.filter((c)=>c.status==="success").length,n.failedCount=n.messages.filter((c)=>c.status==="failed").length,n.status=n.failedCount===0?"completed":"failed",n.completedAt=new Date,this.collectProcessorMetrics(i.id,n),n}async processBatch(a,n){let i=a.map((s)=>this.processMessage(s,n));await Promise.all(i)}async processMessage(a,n){a.status="processing";let i=Date.now();await new Promise((c)=>setTimeout(c,Math.random()*100));let s=Date.now()-i;if(a.processingTime=s,Math.random()>0.1)a.status="success";else a.status="failed",a.error="Processing error"}chunkArray(a,n){let i=[];for(let s=0;s<a.length;s+=n)i.push(a.slice(s,s+n));return i}collectProcessorMetrics(a,n){let i=`metrics-${Date.now()}-${this.metricsCounter++}`,s=n.messages.filter((A)=>A.status==="success").map((A)=>A.processingTime||0).filter((A)=>A>0),c=s.length>0?s.reduce((A,C)=>A+C,0)/s.length:0,l=n.completedAt&&n.startedAt?(n.completedAt.getTime()-n.startedAt.getTime())/1000:1,u=n.processedCount/l,h=n.messages.length>0?n.failedCount/n.messages.length*100:0,y={id:i,configId:a,timestamp:new Date,messagesProcessed:n.processedCount,averageProcessingTime:c,throughput:u,errorRate:h},S=this.metrics.get(a)||[];S.push(y),this.metrics.set(a,S)}getBatchStatistics(a){let n=this.metrics.get(a)||[];if(n.length===0)return{totalJobsProcessed:0,totalMessagesProcessed:0,averageThroughput:0,averageErrorRate:0,averageProcessingTime:0};let i=n.reduce((u,h)=>u+h.messagesProcessed,0),s=n.reduce((u,h)=>u+h.throughput,0)/n.length,c=n.reduce((u,h)=>u+h.errorRate,0)/n.length,l=n.reduce((u,h)=>u+h.averageProcessingTime,0)/n.length;return{totalJobsProcessed:n.length,totalMessagesProcessed:i,averageThroughput:s,averageErrorRate:c,averageProcessingTime:l}}optimizeBatchConfig(a){let n=this.configs.get(a);if(!n)throw Error(`Batch config not found: ${a}`);let i=this.getBatchStatistics(a);if(i.averageErrorRate<5&&n.batchSize<10)n.batchSize=Math.min(10,n.batchSize+1);if(i.averageErrorRate>20&&n.batchSize>1)n.batchSize=Math.max(1,n.batchSize-1);if(i.averageThroughput<5&&n.parallelProcessors<20)n.parallelProcessors++;return n}getConfig(a){return this.configs.get(a)}listConfigs(){return Array.from(this.configs.values())}getJob(a){return this.jobs.get(a)}listJobs(a){let n=Array.from(this.jobs.values());if(a)n=n.filter((i)=>i.configId===a);return n}generateBatchProcessorCF(a){return{Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:`arn:aws:sqs:us-east-1:123456789012:${a.queueUrl.split("/").pop()}`,FunctionName:"batch-processor-function",BatchSize:a.batchSize,MaximumBatchingWindowInSeconds:a.maxWaitTime/1000,FunctionResponseTypes:["ReportBatchItemFailures"]}}}clear(){this.configs.clear(),this.jobs.clear(),this.metrics.clear(),this.configCounter=0,this.jobCounter=0,this.metricsCounter=0}}var zC=new Vg;class jg{queues=new Map;retentionPolicies=new Map;delayQueues=new Map;purgeOperations=new Map;metrics=new Map;queueCounter=0;retentionCounter=0;delayCounter=0;purgeCounter=0;metricsCounter=0;createQueue(a){let n=`queue-${Date.now()}-${this.queueCounter++}`,i={id:n,purgeInProgress:!1,...a};return this.queues.set(n,i),i}createStandardQueue(a){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${a.queueName}`,queueName:a.queueName,messageRetentionPeriod:(a.messageRetentionDays||4)*24*60*60,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:0})}createLongPollingQueue(a){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${a.queueName}`,queueName:a.queueName,messageRetentionPeriod:345600,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:a.waitTimeSeconds||20})}createRetentionPolicy(a){let n=`retention-${Date.now()}-${this.retentionCounter++}`,i={id:n,...a};this.retentionPolicies.set(n,i);let s=this.queues.get(a.queueId);if(s)s.messageRetentionPeriod=a.retentionPeriod;return i}createShortRetentionPolicy(a){return this.createRetentionPolicy({queueId:a.queueId,retentionPeriod:a.retentionHours*60*60,autoCleanup:!0,archiveExpiredMessages:!1})}createArchivalRetentionPolicy(a){return this.createRetentionPolicy({queueId:a.queueId,retentionPeriod:a.retentionDays*24*60*60,autoCleanup:!0,cleanupSchedule:"cron(0 0 * * ? *)",archiveExpiredMessages:!0,archiveS3Bucket:a.s3Bucket})}createDelayQueue(a){let n=`delay-${Date.now()}-${this.delayCounter++}`,i={id:n,...a};this.delayQueues.set(n,i);let s=Array.from(this.queues.values()).find((c)=>c.queueUrl===a.queueUrl);if(s)s.delaySeconds=a.defaultDelay;return i}createScheduledDelayQueue(a){return this.createDelayQueue({queueUrl:a.queueUrl,defaultDelay:a.delayMinutes*60,perMessageDelay:!1,maxDelay:900})}async purgeQueue(a){let n=this.queues.get(a);if(!n)throw Error(`Queue not found: ${a}`);if(n.purgeInProgress)throw Error("Purge already in progress for this queue");let i=`purge-${Date.now()}-${this.purgeCounter++}`,s={id:i,queueUrl:n.queueUrl,status:"in_progress",startedAt:new Date};return this.purgeOperations.set(i,s),n.purgeInProgress=!0,setTimeout(()=>{s.status="completed",s.completedAt=new Date,s.messagesPurged=Math.floor(Math.random()*1000),n.purgeInProgress=!1},100),s}collectQueueMetrics(a){let n={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:a,timestamp:new Date,approximateNumberOfMessages:Math.floor(Math.random()*1000),approximateNumberOfMessagesNotVisible:Math.floor(Math.random()*100),approximateNumberOfMessagesDelayed:Math.floor(Math.random()*50),oldestMessageAge:Math.floor(Math.random()*86400)},i=this.metrics.get(a)||[];return i.push(n),this.metrics.set(a,i),n}getQueueHealth(a){let n=this.metrics.get(a)||[];if(n.length===0)return{status:"healthy",issues:[],recommendations:[]};let i=n[n.length-1],s=[],c=[],l="healthy";if(i.approximateNumberOfMessages>1e4)l="critical",s.push("Large message backlog detected"),c.push("Increase consumer capacity");else if(i.approximateNumberOfMessages>1000)l="warning",s.push("Growing message backlog"),c.push("Monitor consumer performance");if(i.oldestMessageAge&&i.oldestMessageAge>3600){if(l!=="critical")l="warning";s.push("Old messages in queue"),c.push("Review message processing")}if(i.approximateNumberOfMessagesDelayed>100){if(l!=="critical")l="warning";s.push("High number of delayed messages")}return{status:l,issues:s,recommendations:c}}getQueue(a){return this.queues.get(a)}listQueues(){return Array.from(this.queues.values())}getRetentionPolicy(a){return this.retentionPolicies.get(a)}listRetentionPolicies(){return Array.from(this.retentionPolicies.values())}getPurgeOperations(a){let n=Array.from(this.purgeOperations.values());if(a)n=n.filter((i)=>i.queueUrl===a);return n}generateQueueCF(a){return{Type:"AWS::SQS::Queue",Properties:{QueueName:a.queueName,MessageRetentionPeriod:a.messageRetentionPeriod,DelaySeconds:a.delaySeconds,MaximumMessageSize:a.maximumMessageSize,ReceiveMessageWaitTimeSeconds:a.receiveMessageWaitTime}}}generateCleanupRuleCF(a){return{Type:"AWS::Events::Rule",Properties:{Name:`${a.id}-cleanup`,Description:"Automated queue cleanup",ScheduleExpression:a.cleanupSchedule||"cron(0 0 * * ? *)",State:"ENABLED",Targets:[{Arn:"arn:aws:lambda:us-east-1:123456789012:function:queue-cleanup",Id:a.id,Input:JSON.stringify({queueId:a.queueId,archiveBucket:a.archiveS3Bucket})}]}}}clear(){this.queues.clear(),this.retentionPolicies.clear(),this.delayQueues.clear(),this.purgeOperations.clear(),this.metrics.clear(),this.queueCounter=0,this.retentionCounter=0,this.delayCounter=0,this.purgeCounter=0,this.metricsCounter=0}}var KC=new jg,_n=(()=>{let a=[];for(let n=0;n<256;n++){let i=n;for(let s=0;s<8;s++)i=i&1?3988292384^i>>>1:i>>>1;a[n]=i>>>0}return a})();function Wn(a){let n=4294967295;for(let i=0;i<a.length;i++)n=_n[(n^a[i])&255]^n>>>8;return(n^4294967295)>>>0}function Gn(a){if(typeof a==="string")return Buffer.from(a,"utf-8");if(Buffer.isBuffer(a))return a;return Buffer.from(a)}function Un(a){let n=Math.max(1980,a.getFullYear()),i=(a.getHours()<<11|a.getMinutes()<<5|a.getSeconds()>>1)&65535,s=(n-1980<<9|a.getMonth()+1<<5|a.getDate())&65535;return{time:i,date:s}}function Si(a){let n=[],i=[],s=0;for(let u of a){let h=Gn(u.data),y=Bn(h),S=Wn(h),A=Buffer.from(u.name.replace(/\\/g,"/"),"utf-8"),{time:C,date:T}=Un(u.date??new Date(0)),v=u.mode??420,w=Buffer.alloc(30+A.length);w.writeUInt32LE(67324752,0),w.writeUInt16LE(20,4),w.writeUInt16LE(0,6),w.writeUInt16LE(8,8),w.writeUInt16LE(C,10),w.writeUInt16LE(T,12),w.writeUInt32LE(S,14),w.writeUInt32LE(y.length,18),w.writeUInt32LE(h.length,22),w.writeUInt16LE(A.length,26),w.writeUInt16LE(0,28),A.copy(w,30);let E=Buffer.alloc(46+A.length);E.writeUInt32LE(33639248,0),E.writeUInt16LE(798,4),E.writeUInt16LE(20,6),E.writeUInt16LE(0,8),E.writeUInt16LE(8,10),E.writeUInt16LE(C,12),E.writeUInt16LE(T,14),E.writeUInt32LE(S,16),E.writeUInt32LE(y.length,20),E.writeUInt32LE(h.length,24),E.writeUInt16LE(A.length,28),E.writeUInt16LE(0,30),E.writeUInt16LE(0,32),E.writeUInt16LE(0,34),E.writeUInt16LE(0,36),E.writeUInt32LE((v&65535)<<16,38),E.writeUInt32LE(s,42),A.copy(E,46),n.push(w,y),i.push(E),s+=w.length+y.length}let c=Buffer.concat(i),l=Buffer.alloc(22);return l.writeUInt32LE(101010256,0),l.writeUInt16LE(0,4),l.writeUInt16LE(0,6),l.writeUInt16LE(a.length,8),l.writeUInt16LE(a.length,10),l.writeUInt32LE(c.length,12),l.writeUInt32LE(s,16),l.writeUInt16LE(0,20),Buffer.concat([...n,c,l])}function sA(a){let n=a.adapterImport??"./adapter",i=a.entryImport.replace(/\\/g,"/");return`// Generated by ts-cloud — serverless app bootstrap. Do not edit.
7265
7265
  import * as __userModule from ${JSON.stringify(i)}
7266
7266
  import { resolveApp, createHandlers } from ${JSON.stringify(n)}
7267
7267
 
@@ -7271,9 +7271,9 @@ const __handlers = createHandlers(__app)
7271
7271
  export const http = __handlers.http
7272
7272
  export const queue = __handlers.queue
7273
7273
  export const cli = __handlers.cli
7274
- `}var Xn=["adapter.ts","recursion.ts","auto-recursion.ts"];function ei(){return Le(Qn(Zn(import.meta.url)),"runtime")}function oA(a,n,i){for(let s of a??[])i?.(`build: ${s}`),Fn(s,{stdio:"inherit",cwd:n})}function io(a){return Vn("sha256").update(a).digest("hex")}function Sd(a,n,i){return`deployments/${a}/${n}/${i}.zip`}async function Mr(a){let n=Yn(a.projectRoot??process.cwd()),{app:i}=a;if(!a.skipBuild)oA(i.build,n,a.onStep);let s=i.entry;if(!s)throw Error("serverless app: `entry` is required to package a Node/Bun application");let c=Jn(s)?s:Le(n,s),l=Kn(Le(zn(),"tscloud-pkg-"));try{for(let C of Xn)jn(Le(ei(),C),Le(l,C));let u=Le(l,"bootstrap.ts");qn(u,sA({entryImport:c,adapterImport:"./adapter"})),a.onStep?.("bundling application");let h=await Bun.build({entrypoints:[u],target:i.kind==="bun"?"bun":"node",format:"esm",minify:!1,sourcemap:"none"});if(!h.success){let C=h.logs.map((T)=>String(T)).join(`
7274
+ `}var Xn=["adapter.ts","recursion.ts","auto-recursion.ts"];function ei(){return Le(Qn(Zn(import.meta.url)),"runtime")}function oA(a,n,i){for(let s of a??[])i?.(`build: ${s}`),Fn(s,{stdio:"inherit",cwd:n})}function io(a){return Vn("sha256").update(a).digest("hex")}function Sd(a,n,i){return`deployments/${a}/${n}/${i}.zip`}async function Mr(a){let n=Yn(a.projectRoot??process.cwd()),{app:i}=a;if(!a.skipBuild)oA(i.build,n,a.onStep);let s=i.entry;if(!s)throw Error("serverless app: `entry` is required to package a Node/Bun application");let c=Jn(s)?s:Le(n,s),l=Kn(Le(zn(),"tscloud-pkg-"));try{for(let T of Xn)jn(Le(ei(),T),Le(l,T));let u=Le(l,"bootstrap.ts");qn(u,sA({entryImport:c,adapterImport:"./adapter"})),a.onStep?.("bundling application");let h=await Bun.build({entrypoints:[u],target:i.kind==="bun"?"bun":"node",format:"esm",minify:!1,sourcemap:"none"});if(!h.success){let T=h.logs.map((v)=>String(v)).join(`
7275
7275
  `);throw Error(`serverless app bundle failed:
7276
- ${C}`)}let y=h.outputs[0],S=Buffer.from(await y.arrayBuffer()),b="index",A=Si([{name:`${b}.mjs`,data:S}]);return{zip:A,bundle:S,sha256:io(A),handlerFile:b,handlers:{http:i.handlers?.http??`${b}.http`,queue:i.handlers?.queue??`${b}.queue`,cli:i.handlers?.cli??`${b}.cli`},bundleBytes:S.length}}finally{Hn(l,{recursive:!0,force:!0})}}var aA=["18","20","22"];function ti(a){if(!a)return"22";let n=String(a).match(/(\d+)/);return n?n[1]:"22"}function so(a){let n=a.kind??"node";if(n==="php")return{lambdaRuntime:"provided.al2023",kind:"php",version:a.phpVersion??"8.3",usesLayer:!0,layerKind:"php",layerEnvVar:"TSCLOUD_PHP_LAYER_ARN"};if(n==="bun")return{lambdaRuntime:"provided.al2023",kind:"bun",version:a.runtimeVersion??"latest",usesLayer:!0,layerKind:"bun",layerEnvVar:"TSCLOUD_BUN_LAYER_ARN"};let i=ti(a.runtimeVersion);if(a.runtime!=="provided.al2023"&&aA.includes(i))return{lambdaRuntime:a.runtime&&a.runtime.startsWith("nodejs")?a.runtime:`nodejs${i}.x`,kind:"node",version:i,usesLayer:!1};return{lambdaRuntime:"provided.al2023",kind:"node",version:i,usesLayer:!0,layerKind:"node",layerEnvVar:"TSCLOUD_NODE_LAYER_ARN"}}function qt(a,n,i){if(a.queues===!1)return[];if(a.queues===void 0||a.queues===!0)return[{name:`${n}-${i}-default`}];return a.queues.map((s)=>{if(typeof s==="string")return{name:`${n}-${i}-${s}`};let[c,l]=Object.entries(s)[0];return{name:`${n}-${i}-${c}`,concurrency:l}})}function Cd(a,n,i){return qt(a,n,i).map((s)=>s.name)}function bd(a){let{app:n,environment:i,handlers:s}=a,c=a.config.project.slug,l=so(n).lambdaRuntime,u=n.architecture??"x86_64",h=a.config.project.region,y={http:`${c}-${i}-http`,queue:`${c}-${i}-queue`,cli:`${c}-${i}-cli`};if(n.gatewayVersion===1)throw Error("serverless app: `gatewayVersion: 1` (REST API) is not supported — ts-cloud uses API Gateway HTTP API (v2). Remove `gatewayVersion` or set it to 2.");let S=qt(n,c,i),b=S.map((z)=>z.name),A=b.length>0,C=n.logRetention??14,T=n.packaging==="image";if(T&&n.lambdaInsights)throw Error("serverless app: `lambdaInsights` layer attachment is only supported for zip packaging. Container images must install the Lambda Insights extension in the image.");let v=(n.scheduler??"on")!=="off",w=(n.cache?.driver??"dynamodb")==="dynamodb",R=Boolean(n.assets),k=Xs(c,i),W=n.tmpStorage??512,P={},V={},B=[{PolicyName:"tscloud-serverless-app",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:e.sub("arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*")},{Effect:"Allow",Action:["lambda:InvokeFunction"],Resource:e.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${c}-${i}-*`)},{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameter","ssm:GetParameters","ssm:GetParametersByPath"],Resource:[e.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${c}/${i}/*`),e.sub(`arn:aws:ssm:\${AWS::Region}:\${AWS::AccountId}:parameter/${c}/${i}/*`)]},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[e.sub(`arn:aws:s3:::${k}`),e.sub(`arn:aws:s3:::${k}/*`),...n.storage?.bucket?[e.sub(`arn:aws:s3:::${n.storage.bucket}`),e.sub(`arn:aws:s3:::${n.storage.bucket}/*`)]:[]]}]}}];if(A)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["sqs:SendMessage","sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes","sqs:GetQueueUrl"],Resource:e.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${c}-${i}-*`)});if(w)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:BatchGetItem","dynamodb:BatchWriteItem"],Resource:e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${c}-${i}-cache*`)});let j=["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"];if(n.vpc?.subnets?.length)j.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");if(n.lambdaInsights)j.push("arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy");P.AppRole={Type:"AWS::IAM::Role",Properties:{RoleName:`${c}-${i}-app-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:j,Policies:B}};let J=(z)=>({TSCLOUD_LAMBDA_MODE:z,TSCLOUD_ENV:i,...n.octane?{TSCLOUD_OCTANE:"1"}:{},...n.scheduler==="sub-minute"?{TSCLOUD_SCHEDULER:"sub-minute"}:{},...w?{TSCLOUD_CACHE_TABLE:`${c}-${i}-cache`}:{},...A?{TSCLOUD_QUEUE:b[0]}:{},...n.env??{}}),K=Boolean(n.efs),X=typeof n.efs==="object"?n.efs:{},te=X.mountPath??"/mnt/local",ne=K&&!X.accessPointArn,me=X.accessPointArn??(ne?e.getAtt("EfsAccessPoint","Arn"):void 0),oe=n.vpc?.subnets??[],ue=oe.length>0,ie=n.cache?.driver==="elasticache"||n.database?.connection==="aurora-serverless"||Boolean(n.rdsProxy)||K;if(ie&&!ue)throw Error("serverless app: elasticache / aurora-serverless / rdsProxy / efs require app.vpc.subnets (private subnets) to be set.");let Ie=ue?{VpcConfig:{SubnetIds:oe,SecurityGroupIds:[...n.vpc?.securityGroups??[],...ie?[e.getAtt("DataSecurityGroup","GroupId")]:[]]}}:{},_e=ne?oe.map((z,re)=>`EfsMountTarget${re}`):[],Ct=K?{FileSystemConfigs:[{Arn:me,LocalMountPath:te}]}:{};if(K)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess","elasticfilesystem:DescribeMountTargets"],Resource:"*"});function pe(z,re,ae,se,ye,tt,be,at=W){P[`${z}LogGroup`]={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:`/aws/lambda/${re}`,RetentionInDays:C}};let Tt=[...a.runtimeLayers??[],...n.lambdaInsights?[n.lambdaInsights.layerArn]:[]],vt=T?{PackageType:"Image",Code:{ImageUri:e.ref("ImageUri")},...n.kind==="php"?{}:{ImageConfig:{Command:[ae]}}}:{Runtime:l,Handler:ae,Code:{S3Bucket:e.ref("ArtifactBucket"),S3Key:e.ref("ArtifactKey")},...Tt.length?{Layers:[...new Set(Tt)]}:{}};P[z]={Type:"AWS::Lambda::Function",DependsOn:[`${z}LogGroup`,..._e],Properties:{FunctionName:re,Architectures:[u],MemorySize:ye,Timeout:tt,Role:e.getAtt("AppRole","Arn"),Environment:{Variables:J(se)},EphemeralStorage:{Size:at},...vt,...be!==void 0?{ReservedConcurrentExecutions:be}:{},...Ie,...Ct}}}if(pe("HttpFunction",y.http,s.http,"http",n.memory??1024,n.timeout??28,n.concurrency,W),pe("CliFunction",y.cli,s.cli,"cli",n.cliMemory??1024,n.cliTimeout??900,void 0,n.cliTmpStorage??W),A)pe("QueueFunction",y.queue,s.queue,"queue",n.queueMemory??1024,n.queueTimeout??120,void 0,n.queueTmpStorage??W);let de=(n.provisionedConcurrency??0)>0?n.provisionedConcurrency:0,ge=["HttpFunction","CliFunction",...A?["QueueFunction"]:[]];if(de)for(let z of ge)P[`${z}Version`]={Type:"AWS::Lambda::Version",DeletionPolicy:"Retain",Properties:{FunctionName:e.ref(z)}},P[`${z}Alias`]={Type:"AWS::Lambda::Alias",Properties:{FunctionName:e.ref(z),Name:"live",FunctionVersion:e.getAtt(`${z}Version`,"Version"),ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:de}}};let Re=(z)=>de?e.ref(`${z}Alias`):e.getAtt(z,"Arn"),he=(z)=>de?e.ref(`${z}Alias`):e.ref(z);P.HttpApi={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:`${c}-${i}`,ProtocolType:"HTTP"}},P.HttpIntegration={Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:e.ref("HttpApi"),IntegrationType:"AWS_PROXY",IntegrationUri:Re("HttpFunction"),PayloadFormatVersion:"2.0"}},P.HttpRoute={Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:e.ref("HttpApi"),RouteKey:"$default",Target:e.join("/",["integrations",e.ref("HttpIntegration")])}},P.HttpStage={Type:"AWS::ApiGatewayV2::Stage",Properties:{ApiId:e.ref("HttpApi"),StageName:"$default",AutoDeploy:!0}},P.HttpPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:he("HttpFunction"),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:e.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${HttpApi}/*/*")}},V.HttpApiEndpoint={Description:"HTTP API endpoint",Value:e.getAtt("HttpApi","ApiEndpoint")},V.HttpApiId={Description:"HTTP API id",Value:e.ref("HttpApi")};let Se=(Array.isArray(n.domain)?n.domain:n.domain?[n.domain]:[]).filter(Boolean);if(Se.length){if(!n.certificateArn&&!n.hostedZoneId)throw Error("serverless app: a custom `domain` needs either `certificateArn` (pre-issued, regional) or `hostedZoneId` (to auto-issue + validate an ACM cert).");let z=n.certificateArn;if(!z)P.HttpCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:Se[0],...Se.length>1?{SubjectAlternativeNames:Se.slice(1)}:{},ValidationMethod:"DNS",DomainValidationOptions:Se.map((re)=>({DomainName:re,HostedZoneId:n.hostedZoneId}))}},z=e.ref("HttpCertificate");Se.forEach((re,ae)=>{let se=`HttpDomain${ae}`;if(P[se]={Type:"AWS::ApiGatewayV2::DomainName",Properties:{DomainName:re,DomainNameConfigurations:[{CertificateArn:z,EndpointType:"REGIONAL"}]}},P[`HttpApiMapping${ae}`]={Type:"AWS::ApiGatewayV2::ApiMapping",DependsOn:["HttpStage"],Properties:{ApiId:e.ref("HttpApi"),DomainName:e.ref(se),Stage:"$default"}},n.hostedZoneId)P[`HttpDomainRecord${ae}`]={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:re,Type:"A",AliasTarget:{DNSName:e.getAtt(se,"RegionalDomainName"),HostedZoneId:e.getAtt(se,"RegionalHostedZoneId")}}};V[`CustomDomain${ae}`]={Description:`Custom domain ${re}`,Value:re},V[`CustomDomainTarget${ae}`]={Description:`Point ${re} (CNAME/alias) at this APIGW regional domain`,Value:e.getAtt(se,"RegionalDomainName")}})}if(A)P.AppQueueDlq={Type:"AWS::SQS::Queue",Properties:{QueueName:`${c}-${i}-dlq`,MessageRetentionPeriod:1209600}},S.forEach((z,re)=>{let ae=`AppQueue${re}`,se=n.queueTimeout??120;P[ae]={Type:"AWS::SQS::Queue",Properties:{QueueName:z.name,VisibilityTimeout:Math.min(43200,se*6),RedrivePolicy:{deadLetterTargetArn:e.getAtt("AppQueueDlq","Arn"),maxReceiveCount:n.queueTries??3}}};let ye=z.concurrency??n.queueConcurrency;P[`${ae}Mapping`]={Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:e.getAtt(ae,"Arn"),FunctionName:he("QueueFunction"),BatchSize:1,FunctionResponseTypes:["ReportBatchItemFailures"],...ye?{ScalingConfig:{MaximumConcurrency:Math.max(2,ye)}}:{}}},V[`QueueUrl${re}`]={Description:`Queue URL: ${z.name}`,Value:e.ref(ae)}});if(v)P.SchedulerRule={Type:"AWS::Events::Rule",Properties:{Name:`${c}-${i}-scheduler`,ScheduleExpression:"rate(1 minute)",State:"ENABLED",Targets:[{Id:"cli",Arn:Re("CliFunction"),Input:JSON.stringify({command:"schedule:run"})}]}},P.SchedulerPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:he("CliFunction"),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.getAtt("SchedulerRule","Arn")}};if(n.warm&&n.warm>0){let z={http:"HttpFunction",queue:"QueueFunction",cli:"CliFunction"},re=(n.warmFunctions??["http"]).filter((ae)=>ae!=="queue"||A);for(let ae of re){let se=ae.charAt(0).toUpperCase()+ae.slice(1),ye=Math.ceil(n.warm/5),tt=0;for(let be=0;be<ye;be++){let at=Math.min(5,n.warm-tt);P[`Warmer${se}Rule${be}`]={Type:"AWS::Events::Rule",Properties:{Name:`${c}-${i}-warmer-${ae}-${be}`,ScheduleExpression:"rate(5 minutes)",State:"ENABLED",Targets:Array.from({length:at},(Tt,vt)=>({Id:`warm-${ae}-${be}-${vt}`,Arn:e.getAtt(z[ae],"Arn"),Input:JSON.stringify({warmer:!0})}))}},tt+=at}P[`Warmer${se}Permission`]={Type:"AWS::Lambda::Permission",Properties:{FunctionName:e.ref(z[ae]),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.sub(`arn:aws:events:\${AWS::Region}:\${AWS::AccountId}:rule/${c}-${i}-warmer-${ae}-*`)}}}}if(w)P.CacheTable={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${c}-${i}-cache`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"key",AttributeType:"S"}],KeySchema:[{AttributeName:"key",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"expires_at",Enabled:!0}}},V.CacheTableName={Description:"DynamoDB cache table",Value:e.ref("CacheTable")};if(R){if(P.AssetsBucket={Type:"AWS::S3::Bucket",Properties:{BucketName:k,PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}}},P.AssetsOAC={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${c}-${i}-assets-oac`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},P.AssetsDistribution={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,DefaultCacheBehavior:{TargetOriginId:"assets",ViewerProtocolPolicy:"redirect-to-https",Compress:!0,CachePolicyId:"658327ea-f89d-4fab-a63d-7e88639e58f6"},Origins:[{Id:"assets",DomainName:e.getAtt("AssetsBucket","RegionalDomainName"),OriginAccessControlId:e.ref("AssetsOAC"),S3OriginConfig:{OriginAccessIdentity:""}}],...n.assetDomain?{Aliases:[n.assetDomain],ViewerCertificate:{AcmCertificateArn:n.assetCertificateArn??e.ref("AssetsCertificate"),SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}}:{}}}},n.assetDomain){if(!n.assetCertificateArn){if(!n.hostedZoneId)throw Error("serverless app: `assetDomain` requires either `assetCertificateArn` (a us-east-1 ACM cert) or `hostedZoneId` (to auto-issue + validate one). CloudFront only accepts certs from us-east-1.");if(h!=="us-east-1")throw Error(`serverless app: auto-issuing an asset-domain cert needs a us-east-1 app (CloudFront certs must be us-east-1); this app is in ${h}. Supply a pre-issued us-east-1 \`assetCertificateArn\` instead.`);P.AssetsCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:n.assetDomain,ValidationMethod:"DNS",DomainValidationOptions:[{DomainName:n.assetDomain,HostedZoneId:n.hostedZoneId}]}}}if(n.hostedZoneId)P.AssetsDomainRecord={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:n.assetDomain,Type:"A",AliasTarget:{DNSName:e.getAtt("AssetsDistribution","DomainName"),HostedZoneId:"Z2FDTNDATAQYW2"}}};V.AssetDomain={Description:"Custom asset CDN host",Value:n.assetDomain}}P.AssetsBucketPolicy={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:e.ref("AssetsBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:e.sub(`arn:aws:s3:::${k}/*`),Condition:{StringEquals:{"AWS:SourceArn":e.sub("arn:aws:cloudfront::${AWS::AccountId}:distribution/${AssetsDistribution}")}}}]}}},V.AssetsBucketName={Description:"Assets bucket",Value:e.ref("AssetsBucket")},V.AssetsCdnDomain={Description:"Assets CloudFront domain",Value:e.getAtt("AssetsDistribution","DomainName")}}if(n.firewall?.enabled){let z=[],re=0;if(n.firewall.rateLimit)z.push({Name:"rate-limit",Priority:re++,Action:{Block:{}},Statement:{RateBasedStatement:{Limit:n.firewall.rateLimit,AggregateKeyType:"IP"}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${i}-rate`}});let ae={sqlInjection:"AWSManagedRulesSQLiRuleSet",xss:"AWSManagedRulesCommonRuleSet",common:"AWSManagedRulesCommonRuleSet",botControl:"AWSManagedRulesBotControlRuleSet",ipReputation:"AWSManagedRulesAmazonIpReputationList"};for(let se of n.firewall.rules??[]){let ye=ae[se];if(!ye)continue;z.push({Name:`managed-${se}`,Priority:re++,OverrideAction:{None:{}},Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:ye}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${i}-${se}`}})}P.WebAcl={Type:"AWS::WAFv2::WebACL",Properties:{Name:`${c}-${i}-waf`,Scope:"REGIONAL",DefaultAction:{Allow:{}},Rules:z,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${i}-waf`}}},V.WafAclArn={Description:"WAF web ACL ARN. Attach to a CloudFront distribution fronting the API to enforce (HTTP API v2 stages do not support direct WAF association).",Value:e.getAtt("WebAcl","Arn")}}if(ue&&ie){if(!n.vpc?.id)throw Error("serverless app: data services (elasticache / aurora-serverless / rdsProxy / efs) need app.vpc.id (the VPC id) so the managed security group is created in the right VPC.");P.DataSecurityGroup={Type:"AWS::EC2::SecurityGroup",Properties:{VpcId:n.vpc.id,GroupDescription:`${c}-${i} serverless data access`,SecurityGroupIngress:[{IpProtocol:"-1",CidrIp:"10.0.0.0/8"}]}}}if(ne)P.EfsFileSystem={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:!0,FileSystemTags:[{Key:"Name",Value:`${c}-${i}-efs`}]}},oe.forEach((z,re)=>{P[`EfsMountTarget${re}`]={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:e.ref("EfsFileSystem"),SubnetId:z,SecurityGroups:[e.getAtt("DataSecurityGroup","GroupId")]}}}),P.EfsAccessPoint={Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:e.ref("EfsFileSystem"),PosixUser:{Uid:1001,Gid:1001},RootDirectory:{Path:"/lambda",CreationInfo:{OwnerUid:1001,OwnerGid:1001,Permissions:"0755"}}}},V.EfsFileSystemId={Description:"EFS file system id",Value:e.ref("EfsFileSystem")};if(n.cache?.driver==="elasticache")P.CacheSubnetGroup={Type:"AWS::ElastiCache::SubnetGroup",Properties:{Description:`${c}-${i} cache subnets`,SubnetIds:oe}},P.CacheCluster={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:`${c}-${i}-cache`,ReplicationGroupDescription:`${c}-${i} redis`,Engine:"redis",CacheNodeType:"cache.t4g.micro",NumCacheClusters:1,AutomaticFailoverEnabled:!1,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),SecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")],TransitEncryptionEnabled:!1}},V.CacheEndpoint={Description:"Redis primary endpoint",Value:e.getAtt("CacheCluster","PrimaryEndPoint.Address")};if(n.database?.connection==="aurora-serverless")P.DbSubnetGroup={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupDescription:`${c}-${i} db subnets`,SubnetIds:oe}},P.DbSecret={Type:"AWS::SecretsManager::Secret",Properties:{Name:`${c}/${i}/db`,GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"app"}),GenerateStringKey:"password",PasswordLength:32,ExcludePunctuation:!0}}},P.DbCluster={Type:"AWS::RDS::DBCluster",Properties:{Engine:"aurora-mysql",EngineMode:"provisioned",DBClusterIdentifier:`${c}-${i}-db`,DatabaseName:"app",MasterUsername:e.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:username}}"),MasterUserPassword:e.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:password}}"),ServerlessV2ScalingConfiguration:{MinCapacity:n.database?.minCapacity??0.5,MaxCapacity:n.database?.maxCapacity??4},DBSubnetGroupName:e.ref("DbSubnetGroup"),VpcSecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")]}},P.DbInstance={Type:"AWS::RDS::DBInstance",Properties:{Engine:"aurora-mysql",DBInstanceClass:"db.serverless",DBClusterIdentifier:e.ref("DbCluster")}},V.DbEndpoint={Description:"Aurora cluster endpoint",Value:e.getAtt("DbCluster","Endpoint.Address")};if(n.rdsProxy&&n.database?.connection==="aurora-serverless")P.DbProxyRole={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"rds.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"read-db-secret",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue"],Resource:e.ref("DbSecret")}]}}]}},P.DbProxy={Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:typeof n.rdsProxy==="object"&&n.rdsProxy.name?n.rdsProxy.name:`${c}-${i}-proxy`,EngineFamily:"MYSQL",RoleArn:e.getAtt("DbProxyRole","Arn"),Auth:[{AuthScheme:"SECRETS",SecretArn:e.ref("DbSecret"),IAMAuth:"DISABLED"}],VpcSubnetIds:oe,VpcSecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")],RequireTLS:!1}},P.DbProxyTargetGroup={Type:"AWS::RDS::DBProxyTargetGroup",DependsOn:["DbInstance"],Properties:{DBProxyName:e.ref("DbProxy"),TargetGroupName:"default",DBClusterIdentifiers:[e.ref("DbCluster")]}},V.DbProxyEndpoint={Description:"RDS Proxy endpoint",Value:e.getAtt("DbProxy","Endpoint")};if(V.HttpFunctionName={Description:"HTTP function name",Value:e.ref("HttpFunction")},V.CliFunctionName={Description:"CLI function name",Value:e.ref("CliFunction")},A)V.QueueFunctionName={Description:"Queue function name",Value:e.ref("QueueFunction")};let $e={AWSTemplateFormatVersion:"2010-09-09",Description:`Serverless application for ${a.config.project.name} (${c}-${i})`,Parameters:T?{ImageUri:{Type:"String",Description:"ECR image URI of the deployment artifact"}}:{ArtifactBucket:{Type:"String",Description:"S3 bucket holding the deployment artifact"},ArtifactKey:{Type:"String",Description:"S3 key of the deployment artifact (zip)"}},Resources:P,Outputs:V},We={};for(let z of Object.values(P))We[z.Type]=(We[z.Type]??0)+1;return{template:$e,functionNames:y,queueNames:b,resourceSummary:We}}var cA=["cli","fpm","curl","mbstring","xml","pdo","mysqlnd","gd","bcmath","intl","opcache","sodium","process","pecl-redis6","pecl-apcu","pgsql"];function dA(a){let n=`php${a.replace(".","")}`;return cA.map((i)=>`${n}-php-${i}`)}function zg(a,n){let i=`php${a.replace(".","")}`,s=dA(a).join(" \\\n "),c=`/opt/remi/${i}/root`,l=`/etc/opt/remi/${i}`;return`${n?`FROM almalinux:9 AS ${n}`:"FROM almalinux:9"}
7276
+ ${T}`)}let y=h.outputs[0],S=Buffer.from(await y.arrayBuffer()),A="index",C=Si([{name:`${A}.mjs`,data:S}]);return{zip:C,bundle:S,sha256:io(C),handlerFile:A,handlers:{http:i.handlers?.http??`${A}.http`,queue:i.handlers?.queue??`${A}.queue`,cli:i.handlers?.cli??`${A}.cli`},bundleBytes:S.length}}finally{Hn(l,{recursive:!0,force:!0})}}var aA=["18","20","22"];function ti(a){if(!a)return"22";let n=String(a).match(/(\d+)/);return n?n[1]:"22"}function so(a){let n=a.kind??"node";if(n==="php")return{lambdaRuntime:"provided.al2023",kind:"php",version:a.phpVersion??"8.3",usesLayer:!0,layerKind:"php",layerEnvVar:"TSCLOUD_PHP_LAYER_ARN"};if(n==="bun")return{lambdaRuntime:"provided.al2023",kind:"bun",version:a.runtimeVersion??"latest",usesLayer:!0,layerKind:"bun",layerEnvVar:"TSCLOUD_BUN_LAYER_ARN"};let i=ti(a.runtimeVersion);if(a.runtime!=="provided.al2023"&&aA.includes(i))return{lambdaRuntime:a.runtime&&a.runtime.startsWith("nodejs")?a.runtime:`nodejs${i}.x`,kind:"node",version:i,usesLayer:!1};return{lambdaRuntime:"provided.al2023",kind:"node",version:i,usesLayer:!0,layerKind:"node",layerEnvVar:"TSCLOUD_NODE_LAYER_ARN"}}function qt(a,n,i){if(a.queues===!1)return[];if(a.queues===void 0||a.queues===!0)return[{name:`${n}-${i}-default`}];return a.queues.map((s)=>{if(typeof s==="string")return{name:`${n}-${i}-${s}`};let[c,l]=Object.entries(s)[0];return{name:`${n}-${i}-${c}`,concurrency:l}})}function Cd(a,n,i){return qt(a,n,i).map((s)=>s.name)}function Ed(a){let{app:n,environment:i,handlers:s}=a,c=a.config.project.slug,l=so(n).lambdaRuntime,u=n.architecture??"x86_64",h=a.config.project.region,y={http:`${c}-${i}-http`,queue:`${c}-${i}-queue`,cli:`${c}-${i}-cli`};if(n.gatewayVersion===1)throw Error("serverless app: `gatewayVersion: 1` (REST API) is not supported — ts-cloud uses API Gateway HTTP API (v2). Remove `gatewayVersion` or set it to 2.");let S=qt(n,c,i),A=S.map((z)=>z.name),C=A.length>0,T=n.logRetention??14,v=n.packaging==="image";if(v&&n.lambdaInsights)throw Error("serverless app: `lambdaInsights` layer attachment is only supported for zip packaging. Container images must install the Lambda Insights extension in the image.");let w=(n.scheduler??"on")!=="off",E=(n.cache?.driver??"dynamodb")==="dynamodb",R=Boolean(n.assets),k=Xs(c,i),W=n.tmpStorage??512,P={},V={},B=[{PolicyName:"tscloud-serverless-app",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:e.sub("arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*")},{Effect:"Allow",Action:["lambda:InvokeFunction"],Resource:e.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${c}-${i}-*`)},{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameter","ssm:GetParameters","ssm:GetParametersByPath"],Resource:[e.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${c}/${i}/*`),e.sub(`arn:aws:ssm:\${AWS::Region}:\${AWS::AccountId}:parameter/${c}/${i}/*`)]},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[e.sub(`arn:aws:s3:::${k}`),e.sub(`arn:aws:s3:::${k}/*`),...n.storage?.bucket?[e.sub(`arn:aws:s3:::${n.storage.bucket}`),e.sub(`arn:aws:s3:::${n.storage.bucket}/*`)]:[]]}]}}];if(C)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["sqs:SendMessage","sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes","sqs:GetQueueUrl"],Resource:e.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${c}-${i}-*`)});if(E)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:BatchGetItem","dynamodb:BatchWriteItem"],Resource:e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${c}-${i}-cache*`)});let j=["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"];if(n.vpc?.subnets?.length)j.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");if(n.lambdaInsights)j.push("arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy");P.AppRole={Type:"AWS::IAM::Role",Properties:{RoleName:`${c}-${i}-app-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:j,Policies:B}};let J=(z)=>({TSCLOUD_LAMBDA_MODE:z,TSCLOUD_ENV:i,...n.octane?{TSCLOUD_OCTANE:"1"}:{},...n.scheduler==="sub-minute"?{TSCLOUD_SCHEDULER:"sub-minute"}:{},...E?{TSCLOUD_CACHE_TABLE:`${c}-${i}-cache`}:{},...C?{TSCLOUD_QUEUE:A[0]}:{},...n.env??{}}),K=Boolean(n.efs),X=typeof n.efs==="object"?n.efs:{},te=X.mountPath??"/mnt/local",ne=K&&!X.accessPointArn,me=X.accessPointArn??(ne?e.getAtt("EfsAccessPoint","Arn"):void 0),oe=n.vpc?.subnets??[],ue=oe.length>0,ie=n.cache?.driver==="elasticache"||n.database?.connection==="aurora-serverless"||Boolean(n.rdsProxy)||K;if(ie&&!ue)throw Error("serverless app: elasticache / aurora-serverless / rdsProxy / efs require app.vpc.subnets (private subnets) to be set.");let Ie=ue?{VpcConfig:{SubnetIds:oe,SecurityGroupIds:[...n.vpc?.securityGroups??[],...ie?[e.getAtt("DataSecurityGroup","GroupId")]:[]]}}:{},_e=ne?oe.map((z,re)=>`EfsMountTarget${re}`):[],Ct=K?{FileSystemConfigs:[{Arn:me,LocalMountPath:te}]}:{};if(K)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess","elasticfilesystem:DescribeMountTargets"],Resource:"*"});function pe(z,re,ae,se,ye,tt,Ae,at=W){P[`${z}LogGroup`]={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:`/aws/lambda/${re}`,RetentionInDays:T}};let Tt=[...a.runtimeLayers??[],...n.lambdaInsights?[n.lambdaInsights.layerArn]:[]],vt=v?{PackageType:"Image",Code:{ImageUri:e.ref("ImageUri")},...n.kind==="php"?{}:{ImageConfig:{Command:[ae]}}}:{Runtime:l,Handler:ae,Code:{S3Bucket:e.ref("ArtifactBucket"),S3Key:e.ref("ArtifactKey")},...Tt.length?{Layers:[...new Set(Tt)]}:{}};P[z]={Type:"AWS::Lambda::Function",DependsOn:[`${z}LogGroup`,..._e],Properties:{FunctionName:re,Architectures:[u],MemorySize:ye,Timeout:tt,Role:e.getAtt("AppRole","Arn"),Environment:{Variables:J(se)},EphemeralStorage:{Size:at},...vt,...Ae!==void 0?{ReservedConcurrentExecutions:Ae}:{},...Ie,...Ct}}}if(pe("HttpFunction",y.http,s.http,"http",n.memory??1024,n.timeout??28,n.concurrency,W),pe("CliFunction",y.cli,s.cli,"cli",n.cliMemory??1024,n.cliTimeout??900,void 0,n.cliTmpStorage??W),C)pe("QueueFunction",y.queue,s.queue,"queue",n.queueMemory??1024,n.queueTimeout??120,void 0,n.queueTmpStorage??W);let de=(n.provisionedConcurrency??0)>0?n.provisionedConcurrency:0,ge=["HttpFunction","CliFunction",...C?["QueueFunction"]:[]];if(de)for(let z of ge)P[`${z}Version`]={Type:"AWS::Lambda::Version",DeletionPolicy:"Retain",Properties:{FunctionName:e.ref(z)}},P[`${z}Alias`]={Type:"AWS::Lambda::Alias",Properties:{FunctionName:e.ref(z),Name:"live",FunctionVersion:e.getAtt(`${z}Version`,"Version"),ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:de}}};let Re=(z)=>de?e.ref(`${z}Alias`):e.getAtt(z,"Arn"),he=(z)=>de?e.ref(`${z}Alias`):e.ref(z);P.HttpApi={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:`${c}-${i}`,ProtocolType:"HTTP"}},P.HttpIntegration={Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:e.ref("HttpApi"),IntegrationType:"AWS_PROXY",IntegrationUri:Re("HttpFunction"),PayloadFormatVersion:"2.0"}},P.HttpRoute={Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:e.ref("HttpApi"),RouteKey:"$default",Target:e.join("/",["integrations",e.ref("HttpIntegration")])}},P.HttpStage={Type:"AWS::ApiGatewayV2::Stage",Properties:{ApiId:e.ref("HttpApi"),StageName:"$default",AutoDeploy:!0}},P.HttpPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:he("HttpFunction"),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:e.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${HttpApi}/*/*")}},V.HttpApiEndpoint={Description:"HTTP API endpoint",Value:e.getAtt("HttpApi","ApiEndpoint")},V.HttpApiId={Description:"HTTP API id",Value:e.ref("HttpApi")};let Se=(Array.isArray(n.domain)?n.domain:n.domain?[n.domain]:[]).filter(Boolean);if(Se.length){if(!n.certificateArn&&!n.hostedZoneId)throw Error("serverless app: a custom `domain` needs either `certificateArn` (pre-issued, regional) or `hostedZoneId` (to auto-issue + validate an ACM cert).");let z=n.certificateArn;if(!z)P.HttpCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:Se[0],...Se.length>1?{SubjectAlternativeNames:Se.slice(1)}:{},ValidationMethod:"DNS",DomainValidationOptions:Se.map((re)=>({DomainName:re,HostedZoneId:n.hostedZoneId}))}},z=e.ref("HttpCertificate");Se.forEach((re,ae)=>{let se=`HttpDomain${ae}`;if(P[se]={Type:"AWS::ApiGatewayV2::DomainName",Properties:{DomainName:re,DomainNameConfigurations:[{CertificateArn:z,EndpointType:"REGIONAL"}]}},P[`HttpApiMapping${ae}`]={Type:"AWS::ApiGatewayV2::ApiMapping",DependsOn:["HttpStage"],Properties:{ApiId:e.ref("HttpApi"),DomainName:e.ref(se),Stage:"$default"}},n.hostedZoneId)P[`HttpDomainRecord${ae}`]={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:re,Type:"A",AliasTarget:{DNSName:e.getAtt(se,"RegionalDomainName"),HostedZoneId:e.getAtt(se,"RegionalHostedZoneId")}}};V[`CustomDomain${ae}`]={Description:`Custom domain ${re}`,Value:re},V[`CustomDomainTarget${ae}`]={Description:`Point ${re} (CNAME/alias) at this APIGW regional domain`,Value:e.getAtt(se,"RegionalDomainName")}})}if(C)P.AppQueueDlq={Type:"AWS::SQS::Queue",Properties:{QueueName:`${c}-${i}-dlq`,MessageRetentionPeriod:1209600}},S.forEach((z,re)=>{let ae=`AppQueue${re}`,se=n.queueTimeout??120;P[ae]={Type:"AWS::SQS::Queue",Properties:{QueueName:z.name,VisibilityTimeout:Math.min(43200,se*6),RedrivePolicy:{deadLetterTargetArn:e.getAtt("AppQueueDlq","Arn"),maxReceiveCount:n.queueTries??3}}};let ye=z.concurrency??n.queueConcurrency;P[`${ae}Mapping`]={Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:e.getAtt(ae,"Arn"),FunctionName:he("QueueFunction"),BatchSize:1,FunctionResponseTypes:["ReportBatchItemFailures"],...ye?{ScalingConfig:{MaximumConcurrency:Math.max(2,ye)}}:{}}},V[`QueueUrl${re}`]={Description:`Queue URL: ${z.name}`,Value:e.ref(ae)}});if(w)P.SchedulerRule={Type:"AWS::Events::Rule",Properties:{Name:`${c}-${i}-scheduler`,ScheduleExpression:"rate(1 minute)",State:"ENABLED",Targets:[{Id:"cli",Arn:Re("CliFunction"),Input:JSON.stringify({command:"schedule:run"})}]}},P.SchedulerPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:he("CliFunction"),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.getAtt("SchedulerRule","Arn")}};if(n.warm&&n.warm>0){let z={http:"HttpFunction",queue:"QueueFunction",cli:"CliFunction"},re=(n.warmFunctions??["http"]).filter((ae)=>ae!=="queue"||C);for(let ae of re){let se=ae.charAt(0).toUpperCase()+ae.slice(1),ye=Math.ceil(n.warm/5),tt=0;for(let Ae=0;Ae<ye;Ae++){let at=Math.min(5,n.warm-tt);P[`Warmer${se}Rule${Ae}`]={Type:"AWS::Events::Rule",Properties:{Name:`${c}-${i}-warmer-${ae}-${Ae}`,ScheduleExpression:"rate(5 minutes)",State:"ENABLED",Targets:Array.from({length:at},(Tt,vt)=>({Id:`warm-${ae}-${Ae}-${vt}`,Arn:e.getAtt(z[ae],"Arn"),Input:JSON.stringify({warmer:!0})}))}},tt+=at}P[`Warmer${se}Permission`]={Type:"AWS::Lambda::Permission",Properties:{FunctionName:e.ref(z[ae]),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.sub(`arn:aws:events:\${AWS::Region}:\${AWS::AccountId}:rule/${c}-${i}-warmer-${ae}-*`)}}}}if(E)P.CacheTable={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${c}-${i}-cache`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"key",AttributeType:"S"}],KeySchema:[{AttributeName:"key",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"expires_at",Enabled:!0}}},V.CacheTableName={Description:"DynamoDB cache table",Value:e.ref("CacheTable")};if(R){if(P.AssetsBucket={Type:"AWS::S3::Bucket",Properties:{BucketName:k,PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}}},P.AssetsOAC={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${c}-${i}-assets-oac`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},P.AssetsDistribution={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,DefaultCacheBehavior:{TargetOriginId:"assets",ViewerProtocolPolicy:"redirect-to-https",Compress:!0,CachePolicyId:"658327ea-f89d-4fab-a63d-7e88639e58f6"},Origins:[{Id:"assets",DomainName:e.getAtt("AssetsBucket","RegionalDomainName"),OriginAccessControlId:e.ref("AssetsOAC"),S3OriginConfig:{OriginAccessIdentity:""}}],...n.assetDomain?{Aliases:[n.assetDomain],ViewerCertificate:{AcmCertificateArn:n.assetCertificateArn??e.ref("AssetsCertificate"),SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}}:{}}}},n.assetDomain){if(!n.assetCertificateArn){if(!n.hostedZoneId)throw Error("serverless app: `assetDomain` requires either `assetCertificateArn` (a us-east-1 ACM cert) or `hostedZoneId` (to auto-issue + validate one). CloudFront only accepts certs from us-east-1.");if(h!=="us-east-1")throw Error(`serverless app: auto-issuing an asset-domain cert needs a us-east-1 app (CloudFront certs must be us-east-1); this app is in ${h}. Supply a pre-issued us-east-1 \`assetCertificateArn\` instead.`);P.AssetsCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:n.assetDomain,ValidationMethod:"DNS",DomainValidationOptions:[{DomainName:n.assetDomain,HostedZoneId:n.hostedZoneId}]}}}if(n.hostedZoneId)P.AssetsDomainRecord={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:n.assetDomain,Type:"A",AliasTarget:{DNSName:e.getAtt("AssetsDistribution","DomainName"),HostedZoneId:"Z2FDTNDATAQYW2"}}};V.AssetDomain={Description:"Custom asset CDN host",Value:n.assetDomain}}P.AssetsBucketPolicy={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:e.ref("AssetsBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:e.sub(`arn:aws:s3:::${k}/*`),Condition:{StringEquals:{"AWS:SourceArn":e.sub("arn:aws:cloudfront::${AWS::AccountId}:distribution/${AssetsDistribution}")}}}]}}},V.AssetsBucketName={Description:"Assets bucket",Value:e.ref("AssetsBucket")},V.AssetsCdnDomain={Description:"Assets CloudFront domain",Value:e.getAtt("AssetsDistribution","DomainName")}}if(n.firewall?.enabled){let z=[],re=0;if(n.firewall.rateLimit)z.push({Name:"rate-limit",Priority:re++,Action:{Block:{}},Statement:{RateBasedStatement:{Limit:n.firewall.rateLimit,AggregateKeyType:"IP"}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${i}-rate`}});let ae={sqlInjection:"AWSManagedRulesSQLiRuleSet",xss:"AWSManagedRulesCommonRuleSet",common:"AWSManagedRulesCommonRuleSet",botControl:"AWSManagedRulesBotControlRuleSet",ipReputation:"AWSManagedRulesAmazonIpReputationList"};for(let se of n.firewall.rules??[]){let ye=ae[se];if(!ye)continue;z.push({Name:`managed-${se}`,Priority:re++,OverrideAction:{None:{}},Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:ye}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${i}-${se}`}})}P.WebAcl={Type:"AWS::WAFv2::WebACL",Properties:{Name:`${c}-${i}-waf`,Scope:"REGIONAL",DefaultAction:{Allow:{}},Rules:z,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${i}-waf`}}},V.WafAclArn={Description:"WAF web ACL ARN. Attach to a CloudFront distribution fronting the API to enforce (HTTP API v2 stages do not support direct WAF association).",Value:e.getAtt("WebAcl","Arn")}}if(ue&&ie){if(!n.vpc?.id)throw Error("serverless app: data services (elasticache / aurora-serverless / rdsProxy / efs) need app.vpc.id (the VPC id) so the managed security group is created in the right VPC.");P.DataSecurityGroup={Type:"AWS::EC2::SecurityGroup",Properties:{VpcId:n.vpc.id,GroupDescription:`${c}-${i} serverless data access`,SecurityGroupIngress:[{IpProtocol:"-1",CidrIp:"10.0.0.0/8"}]}}}if(ne)P.EfsFileSystem={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:!0,FileSystemTags:[{Key:"Name",Value:`${c}-${i}-efs`}]}},oe.forEach((z,re)=>{P[`EfsMountTarget${re}`]={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:e.ref("EfsFileSystem"),SubnetId:z,SecurityGroups:[e.getAtt("DataSecurityGroup","GroupId")]}}}),P.EfsAccessPoint={Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:e.ref("EfsFileSystem"),PosixUser:{Uid:1001,Gid:1001},RootDirectory:{Path:"/lambda",CreationInfo:{OwnerUid:1001,OwnerGid:1001,Permissions:"0755"}}}},V.EfsFileSystemId={Description:"EFS file system id",Value:e.ref("EfsFileSystem")};if(n.cache?.driver==="elasticache")P.CacheSubnetGroup={Type:"AWS::ElastiCache::SubnetGroup",Properties:{Description:`${c}-${i} cache subnets`,SubnetIds:oe}},P.CacheCluster={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:`${c}-${i}-cache`,ReplicationGroupDescription:`${c}-${i} redis`,Engine:"redis",CacheNodeType:"cache.t4g.micro",NumCacheClusters:1,AutomaticFailoverEnabled:!1,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),SecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")],TransitEncryptionEnabled:!1}},V.CacheEndpoint={Description:"Redis primary endpoint",Value:e.getAtt("CacheCluster","PrimaryEndPoint.Address")};if(n.database?.connection==="aurora-serverless")P.DbSubnetGroup={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupDescription:`${c}-${i} db subnets`,SubnetIds:oe}},P.DbSecret={Type:"AWS::SecretsManager::Secret",Properties:{Name:`${c}/${i}/db`,GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"app"}),GenerateStringKey:"password",PasswordLength:32,ExcludePunctuation:!0}}},P.DbCluster={Type:"AWS::RDS::DBCluster",Properties:{Engine:"aurora-mysql",EngineMode:"provisioned",DBClusterIdentifier:`${c}-${i}-db`,DatabaseName:"app",MasterUsername:e.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:username}}"),MasterUserPassword:e.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:password}}"),ServerlessV2ScalingConfiguration:{MinCapacity:n.database?.minCapacity??0.5,MaxCapacity:n.database?.maxCapacity??4},DBSubnetGroupName:e.ref("DbSubnetGroup"),VpcSecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")]}},P.DbInstance={Type:"AWS::RDS::DBInstance",Properties:{Engine:"aurora-mysql",DBInstanceClass:"db.serverless",DBClusterIdentifier:e.ref("DbCluster")}},V.DbEndpoint={Description:"Aurora cluster endpoint",Value:e.getAtt("DbCluster","Endpoint.Address")};if(n.rdsProxy&&n.database?.connection==="aurora-serverless")P.DbProxyRole={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"rds.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"read-db-secret",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue"],Resource:e.ref("DbSecret")}]}}]}},P.DbProxy={Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:typeof n.rdsProxy==="object"&&n.rdsProxy.name?n.rdsProxy.name:`${c}-${i}-proxy`,EngineFamily:"MYSQL",RoleArn:e.getAtt("DbProxyRole","Arn"),Auth:[{AuthScheme:"SECRETS",SecretArn:e.ref("DbSecret"),IAMAuth:"DISABLED"}],VpcSubnetIds:oe,VpcSecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")],RequireTLS:!1}},P.DbProxyTargetGroup={Type:"AWS::RDS::DBProxyTargetGroup",DependsOn:["DbInstance"],Properties:{DBProxyName:e.ref("DbProxy"),TargetGroupName:"default",DBClusterIdentifiers:[e.ref("DbCluster")]}},V.DbProxyEndpoint={Description:"RDS Proxy endpoint",Value:e.getAtt("DbProxy","Endpoint")};if(V.HttpFunctionName={Description:"HTTP function name",Value:e.ref("HttpFunction")},V.CliFunctionName={Description:"CLI function name",Value:e.ref("CliFunction")},C)V.QueueFunctionName={Description:"Queue function name",Value:e.ref("QueueFunction")};let $e={AWSTemplateFormatVersion:"2010-09-09",Description:`Serverless application for ${a.config.project.name} (${c}-${i})`,Parameters:v?{ImageUri:{Type:"String",Description:"ECR image URI of the deployment artifact"}}:{ArtifactBucket:{Type:"String",Description:"S3 bucket holding the deployment artifact"},ArtifactKey:{Type:"String",Description:"S3 key of the deployment artifact (zip)"}},Resources:P,Outputs:V},We={};for(let z of Object.values(P))We[z.Type]=(We[z.Type]??0)+1;return{template:$e,functionNames:y,queueNames:A,resourceSummary:We}}var cA=["cli","fpm","curl","mbstring","xml","pdo","mysqlnd","gd","bcmath","intl","opcache","sodium","process","pecl-redis6","pecl-apcu","pgsql"];function dA(a){let n=`php${a.replace(".","")}`;return cA.map((i)=>`${n}-php-${i}`)}function zg(a,n){let i=`php${a.replace(".","")}`,s=dA(a).join(" \\\n "),c=`/opt/remi/${i}/root`,l=`/etc/opt/remi/${i}`;return`${n?`FROM almalinux:9 AS ${n}`:"FROM almalinux:9"}
7277
7277
 
7278
7278
  # Build PHP on AlmaLinux 9 (where Remi's version-isolated SCL packages install
7279
7279
  # cleanly — Remi's release RPM rejects Amazon Linux 2023). AlmaLinux 9 shares
@@ -7314,7 +7314,7 @@ RUN printf 'extension_dir=/opt/php/lib/php/modules\\n' > /opt/php/etc/php.ini &&
7314
7314
  # orchestrator after the image is produced. Export /opt as the layer payload.
7315
7315
  CMD ["true"]
7316
7316
  `}function lA(a={}){let n=a.phpVersion??"8.3";return`# ts-cloud PHP ${n} runtime layer (generated) — AWS Lambda provided.al2023.
7317
- ${zg(n)}`}function Ed(a){if(a.kind==="php"){let n=a.phpVersion??"8.3";return`# ts-cloud serverless PHP app image (generated, multi-stage).
7317
+ ${zg(n)}`}function bd(a){if(a.kind==="php"){let n=a.phpVersion??"8.3";return`# ts-cloud serverless PHP app image (generated, multi-stage).
7318
7318
  ${zg(n,"phpbuild")}
7319
7319
 
7320
7320
  FROM public.ecr.aws/lambda/provided:al2023
@@ -7334,7 +7334,7 @@ COPY app/ \${LAMBDA_TASK_ROOT}/
7334
7334
 
7335
7335
  # Per-function CMD (e.g. index.http) is supplied via ImageConfig.Command.
7336
7336
  CMD [ "index.http" ]
7337
- `}function Ba(){return ai(ri(import.meta.url))}function Kg(){return At(Pe(Ba(),"runtime.mjs"),"utf-8")}function _a(a){return At(Pe(Ba(),`${a}-bootstrap`),"utf-8")}function WC(a){let n=a.architecture??"x86_64",i=n==="arm64"?"arm64":"x64",s=a.version.replace(/^v/,""),c=a.onStep??(()=>{}),l=Ma(Pe(Oa(),"tscloud-node-layer-"));try{let u=s.includes(".")?s:ni(s),h=`node-v${u}-linux-${i}`,y=`https://nodejs.org/dist/v${u}/${h}.tar.xz`;c(`downloading Node ${u} (${n})`);let S=Pe(l,"node.tar.xz");Wa(y,S),c("extracting node binary"),bt("tar",["-xf",S,"-C",l,`${h}/bin/node`],{stdio:"inherit"});let b=At(Pe(l,h,"bin","node"));c("packaging layer");let A=[{name:"bootstrap",data:_a("node"),mode:493},{name:"runtime.mjs",data:Kg(),mode:420},{name:"bin/node",data:b,mode:493}];return{zip:Si(A),architecture:n,version:u,fileCount:A.length}}finally{xa(l,{recursive:!0,force:!0})}}function JC(a){let n=a.architecture??"x86_64",i=n==="arm64"?"bun-linux-aarch64":"bun-linux-x64",s=a.version==="latest"?"":a.version.replace(/^v/,""),c=a.onStep??(()=>{}),l=Ma(Pe(Oa(),"tscloud-bun-layer-"));try{let u=s?`https://github.com/oven-sh/bun/releases/download/bun-v${s}/${i}.zip`:`https://github.com/oven-sh/bun/releases/latest/download/${i}.zip`;c(`downloading Bun ${s||"latest"} (${n})`);let h=Pe(l,"bun.zip");Wa(u,h),c("extracting bun binary"),bt("unzip",["-o","-q",h,"-d",l],{stdio:"inherit"});let y=At(Pe(l,i,"bun"));c("packaging layer");let S=[{name:"bootstrap",data:_a("bun"),mode:493},{name:"runtime.mjs",data:Kg(),mode:420},{name:"bin/bun",data:y,mode:493}];return{zip:Si(S),architecture:n,version:s||"latest",fileCount:S.length}}finally{xa(l,{recursive:!0,force:!0})}}function Wa(a,n){bt("curl",["-fsSL","-o",n,a],{stdio:["ignore","ignore","inherit"]})}function ni(a){let n=bt("curl",["-fsSL","https://nodejs.org/dist/index.json"],{encoding:"utf-8"}),i=JSON.parse(n).find((s)=>s.version.startsWith(`v${a}.`));if(!i)throw Error(`No Node release found for major version ${a}`);return i.version.replace(/^v/,"")}var oo="x-ts-cloud-invoke-depth",ao="x-ts-cloud-invoke-chain",co="x-ts-cloud-trace-id";function vd(a){return si("sha256").update(a).digest("hex").slice(0,8)}var Ci={maxDepth:10,maxRepeats:3,maxInvocationsPerTrace:100,traceWindowMs:60000,breakerThreshold:5,breakerCooldownMs:60000};function Dt(a,n){if(typeof a.get==="function")return a.get(n)??void 0;let i=a;return i[n]??i[n.toLowerCase()]??i[n.toUpperCase()]}function Td(a,n=64){if(!a)return[];return a.split(".").map((i)=>i.trim()).filter((i)=>/^[0-9a-f]{8}$/.test(i)).slice(-n)}function wd(a,n=Ci){let i=vd(a.functionId),s=Td(Dt(a.headers,ao)),c=a.traceId??Dt(a.headers,co)??crypto.randomUUID(),l=[...s,i],u=s.filter((A)=>A===i).length,h=s[s.length-1]===i,y=Number.parseInt(Dt(a.headers,oo)??"",10),S=Math.max(l.length,Number.isFinite(y)?y+1:0),b="ok";if(S>n.maxDepth)b="depth_exceeded";else if(u>=n.maxRepeats)b="cycle_detected";else if(h&&n.maxRepeats<=1)b="self_invocation";return{reason:b,depth:S,chain:l,traceId:c,selfInvocation:h,repeats:u,propagate:{[oo]:String(S),[ao]:l.join("."),[co]:c}}}var Ga={ok:"",depth_exceeded:"Invocation chain is deeper than the configured limit; the call was refused to stop a runaway loop.",cycle_detected:"This function already appears in the invocation chain; the call was refused as a recursion loop.",self_invocation:"This function invoked itself directly; the call was refused.",trace_budget_exceeded:"This request has already made more invocations than its budget allows.",breaker_open:"Recursion protection is open for this function after repeated loop detections."};class lo{limits;clock;traces=new Map;breakers=new Map;constructor(a=Ci,n=()=>Date.now()){this.limits=a,this.clock=n}check(a){let n=this.clock();this.expireTraces(n);let i=wd(a,this.limits),s=this.breakers.get(a.functionId);if(s?.openUntil!=null&&s.openUntil>n)return this.deny(a.functionId,i,"breaker_open",n,!1);if(i.reason!=="ok")return this.deny(a.functionId,i,i.reason,n,!0);let c=this.traces.get(i.traceId)??{count:0,firstAt:n};if(c.count>=this.limits.maxInvocationsPerTrace)return this.traces.set(i.traceId,c),this.deny(a.functionId,i,"trace_budget_exceeded",n,!0);if(this.traces.set(i.traceId,{count:c.count+1,firstAt:c.firstAt}),s)this.breakers.set(a.functionId,{consecutiveBlocks:0});return{...i,allowed:!0,reason:"ok",propagate:i.propagate}}deny(a,n,i,s,c){if(c){let l=this.breakers.get(a)??{consecutiveBlocks:0},u=l.consecutiveBlocks+1;this.breakers.set(a,{consecutiveBlocks:u,openUntil:u>=this.limits.breakerThreshold?s+this.limits.breakerCooldownMs:l.openUntil})}return{...n,allowed:!1,reason:i,message:Ga[i]}}breakerOpen(a){let n=this.breakers.get(a);return n?.openUntil!=null&&n.openUntil>this.clock()}reset(a){if(a){this.breakers.delete(a);return}this.breakers.clear(),this.traces.clear()}expireTraces(a){if(this.traces.size===0)return;for(let[n,i]of this.traces)if(a-i.firstAt>this.limits.traceWindowMs)this.traces.delete(n)}get trackedTraces(){return this.traces.size}}function Rd(a){return{...a.propagate}}function Dd(a){return{status:508,headers:{"content-type":"application/json","x-ts-cloud-recursion-blocked":a.reason},body:{error:"recursion_blocked",reason:a.reason,message:a.message??Ga[a.reason],depth:a.depth,traceId:a.traceId}}}var Wg=new ii;function pa(a){let n=globalThis.process?.env?.[a];if(n==null||n==="")return;return n!=="0"&&n.toLowerCase()!=="false"}function oi(){let a=globalThis.process?.env??{};return a.TS_CLOUD_FUNCTION_ID||a.AWS_LAMBDA_FUNCTION_NAME||a.FUNCTION_NAME||"function"}function uA(a){let n=a===!1?{enabled:!1}:a??{},i=pa("TS_CLOUD_RECURSION_PROTECTION"),s=pa("TS_CLOUD_RECURSION_DETECTION_ONLY");return{enabled:i??n.enabled??!0,detectionOnly:s??n.detectionOnly??!1,limits:{...Ci,...n.limits},functionId:n.functionId??oi()}}var De,fe;function pA(){let a=globalThis.fetch;if(!a||De===a)return()=>{};fe=a;let n=async(i,s)=>{let c=Wg.getStore();if(!c)return fe(i,s);let l=new Headers(s?.headers??(i instanceof Request?i.headers:void 0));for(let[u,h]of Object.entries(Rd(c)))l.set(u,h);if(i instanceof Request)return fe(new Request(i,{headers:l}),s);return fe(i,{...s,headers:l})};return Object.assign(n,a),globalThis.fetch=n,De=n,()=>{if(globalThis.fetch===De&&fe)globalThis.fetch=fe;De=void 0}}var ct,Mt;function gA(a){if(!ct||JSON.stringify(Mt)!==JSON.stringify(a))ct=new lo(a),Mt=a;return ct}function XC(){if(ct=void 0,Mt=void 0,De&&fe&&globalThis.fetch===De)globalThis.fetch=fe;De=void 0,fe=void 0}function mA(a,n){let i=uA(n);if(!i.enabled)return;let s=gA(i.limits),c={functionId:i.functionId,headers:a},l=s.check(c);return{verdict:l,blocked:!l.allowed&&!i.detectionOnly,observed:!l.allowed&&i.detectionOnly}}function hA(a,n){return pA(),Wg.run(a,n)}function YC(a){let n=a,i=n?.default??n;if(typeof i==="function")return{fetch:i};return{fetch:i?.fetch??n?.fetch,queue:i?.queue??n?.queue,cli:i?.cli??n?.cli}}var ci=/^(?:text\/|application\/(?:json|xml|javascript|graphql|x-www-form-urlencoded|.*\+json|.*\+xml)|image\/svg)/i;function li(a){if(!a)return!0;return ci.test(a)}function ui(a){if(a?.maintenance)return a.maintenance;let n=globalThis.process?.env??{};return{enabled:n.MAINTENANCE_MODE==="1"||n.MAINTENANCE_MODE==="true",bypassSecret:n.MAINTENANCE_BYPASS_SECRET}}function fA(a){let n=a.requestContext?.domainName??"localhost",i=a.rawQueryString?`?${a.rawQueryString}`:"",s=`https://${n}${a.rawPath||"/"}${i}`,c=new Headers;for(let[h,y]of Object.entries(a.headers??{}))if(y!==void 0)c.set(h,y);if(a.cookies?.length)c.set("cookie",a.cookies.join("; "));let l=a.requestContext.http.method,u;if(a.body!==void 0&&l!=="GET"&&l!=="HEAD")u=a.isBase64Encoded?new Uint8Array(Buffer.from(a.body,"base64")):new TextEncoder().encode(a.body);return new Request(s,{method:l,headers:c,body:u})}async function Jg(a){let n={},i=[],s=typeof a.headers.getSetCookie==="function"?a.headers.getSetCookie():[];for(let u of s)i.push(u);a.headers.forEach((u,h)=>{if(h.toLowerCase()==="set-cookie")return;n[h]=u});let c=Buffer.from(await a.arrayBuffer()),l=li(a.headers.get("content-type"));return{statusCode:a.status,headers:n,...i.length?{cookies:i}:{},body:l?c.toString("utf-8"):c.toString("base64"),isBase64Encoded:!l}}function AA(a,n){return async(i)=>{if(i.warmer)return{statusCode:200,headers:{"content-type":"text/plain"},body:"warm",isBase64Encoded:!1};if(!a)return{statusCode:501,headers:{"content-type":"text/plain"},body:"No HTTP handler configured",isBase64Encoded:!1};let s=ui(n);if(s.enabled){let u=i.headers?.["x-maintenance-bypass"]??i.cookies?.find((h)=>h.startsWith("tscloud_bypass="))?.split("=")[1];if(!s.bypassSecret||u!==s.bypassSecret)return{statusCode:503,headers:{"content-type":"text/plain","retry-after":"120"},body:"Service temporarily unavailable (maintenance mode)",isBase64Encoded:!1}}let c=mA(i.headers??{},n?.recursionProtection);if(c?.blocked){let u=Dd(c.verdict);return{statusCode:u.status,headers:{...u.headers,"retry-after":"60"},body:JSON.stringify(u.body),isBase64Encoded:!1}}let l=fA(i);if(!c){let u=await a(l);return Jg(u)}if(c.observed)console.warn(`[ts-cloud] recursion detected (${c.verdict.reason}) at depth ${c.verdict.depth}; detection-only mode let it run`);return hA(c.verdict,async()=>Jg(await a(l)))}}function di(a){try{return JSON.parse(a)}catch{return a}}function yA(a){return async(n)=>{let i=[];if(n.warmer)return{batchItemFailures:i};if(!a)return{batchItemFailures:i};for(let s of n.Records??[])try{await a(di(s.body),s)}catch{i.push({itemIdentifier:s.messageId})}return{batchItemFailures:i}}}function IA(a){return async(n)=>{if(n.warmer)return{statusCode:0,output:"warm"};if(!a)return{statusCode:501,output:"No CLI handler configured"};return a(n)}}function ZC(a,n){return{http:AA(a.fetch,n),queue:yA(a.queue),cli:IA(a.cli)}}function SA(a={}){let n=a.socketPath??"/tmp/.tscloud-fpm.sock",i=a.maxChildren??1;return`; ts-cloud php-fpm configuration (generated) — AWS Lambda custom runtime.
7337
+ `}function Ba(){return ai(ri(import.meta.url))}function Kg(){return At(Pe(Ba(),"runtime.mjs"),"utf-8")}function _a(a){return At(Pe(Ba(),`${a}-bootstrap`),"utf-8")}function WC(a){let n=a.architecture??"x86_64",i=n==="arm64"?"arm64":"x64",s=a.version.replace(/^v/,""),c=a.onStep??(()=>{}),l=Ma(Pe(Oa(),"tscloud-node-layer-"));try{let u=s.includes(".")?s:ni(s),h=`node-v${u}-linux-${i}`,y=`https://nodejs.org/dist/v${u}/${h}.tar.xz`;c(`downloading Node ${u} (${n})`);let S=Pe(l,"node.tar.xz");Wa(y,S),c("extracting node binary"),bt("tar",["-xf",S,"-C",l,`${h}/bin/node`],{stdio:"inherit"});let A=At(Pe(l,h,"bin","node"));c("packaging layer");let C=[{name:"bootstrap",data:_a("node"),mode:493},{name:"runtime.mjs",data:Kg(),mode:420},{name:"bin/node",data:A,mode:493}];return{zip:Si(C),architecture:n,version:u,fileCount:C.length}}finally{xa(l,{recursive:!0,force:!0})}}function JC(a){let n=a.architecture??"x86_64",i=n==="arm64"?"bun-linux-aarch64":"bun-linux-x64",s=a.version==="latest"?"":a.version.replace(/^v/,""),c=a.onStep??(()=>{}),l=Ma(Pe(Oa(),"tscloud-bun-layer-"));try{let u=s?`https://github.com/oven-sh/bun/releases/download/bun-v${s}/${i}.zip`:`https://github.com/oven-sh/bun/releases/latest/download/${i}.zip`;c(`downloading Bun ${s||"latest"} (${n})`);let h=Pe(l,"bun.zip");Wa(u,h),c("extracting bun binary"),bt("unzip",["-o","-q",h,"-d",l],{stdio:"inherit"});let y=At(Pe(l,i,"bun"));c("packaging layer");let S=[{name:"bootstrap",data:_a("bun"),mode:493},{name:"runtime.mjs",data:Kg(),mode:420},{name:"bin/bun",data:y,mode:493}];return{zip:Si(S),architecture:n,version:s||"latest",fileCount:S.length}}finally{xa(l,{recursive:!0,force:!0})}}function Wa(a,n){bt("curl",["-fsSL","-o",n,a],{stdio:["ignore","ignore","inherit"]})}function ni(a){let n=bt("curl",["-fsSL","https://nodejs.org/dist/index.json"],{encoding:"utf-8"}),i=JSON.parse(n).find((s)=>s.version.startsWith(`v${a}.`));if(!i)throw Error(`No Node release found for major version ${a}`);return i.version.replace(/^v/,"")}var oo="x-ts-cloud-invoke-depth",ao="x-ts-cloud-invoke-chain",co="x-ts-cloud-trace-id";function vd(a){return si("sha256").update(a).digest("hex").slice(0,8)}var Ci={maxDepth:10,maxRepeats:3,maxInvocationsPerTrace:100,traceWindowMs:60000,breakerThreshold:5,breakerCooldownMs:60000};function Dt(a,n){if(typeof a.get==="function")return a.get(n)??void 0;let i=a;return i[n]??i[n.toLowerCase()]??i[n.toUpperCase()]}function Td(a,n=64){if(!a)return[];return a.split(".").map((i)=>i.trim()).filter((i)=>/^[0-9a-f]{8}$/.test(i)).slice(-n)}function wd(a,n=Ci){let i=vd(a.functionId),s=Td(Dt(a.headers,ao)),c=a.traceId??Dt(a.headers,co)??crypto.randomUUID(),l=[...s,i],u=s.filter((C)=>C===i).length,h=s[s.length-1]===i,y=Number.parseInt(Dt(a.headers,oo)??"",10),S=Math.max(l.length,Number.isFinite(y)?y+1:0),A="ok";if(S>n.maxDepth)A="depth_exceeded";else if(u>=n.maxRepeats)A="cycle_detected";else if(h&&n.maxRepeats<=1)A="self_invocation";return{reason:A,depth:S,chain:l,traceId:c,selfInvocation:h,repeats:u,propagate:{[oo]:String(S),[ao]:l.join("."),[co]:c}}}var Ga={ok:"",depth_exceeded:"Invocation chain is deeper than the configured limit; the call was refused to stop a runaway loop.",cycle_detected:"This function already appears in the invocation chain; the call was refused as a recursion loop.",self_invocation:"This function invoked itself directly; the call was refused.",trace_budget_exceeded:"This request has already made more invocations than its budget allows.",breaker_open:"Recursion protection is open for this function after repeated loop detections."};class lo{limits;clock;traces=new Map;breakers=new Map;constructor(a=Ci,n=()=>Date.now()){this.limits=a,this.clock=n}check(a){let n=this.clock();this.expireTraces(n);let i=wd(a,this.limits),s=this.breakers.get(a.functionId);if(s?.openUntil!=null&&s.openUntil>n)return this.deny(a.functionId,i,"breaker_open",n,!1);if(i.reason!=="ok")return this.deny(a.functionId,i,i.reason,n,!0);let c=this.traces.get(i.traceId)??{count:0,firstAt:n};if(c.count>=this.limits.maxInvocationsPerTrace)return this.traces.set(i.traceId,c),this.deny(a.functionId,i,"trace_budget_exceeded",n,!0);if(this.traces.set(i.traceId,{count:c.count+1,firstAt:c.firstAt}),s)this.breakers.set(a.functionId,{consecutiveBlocks:0});return{...i,allowed:!0,reason:"ok",propagate:i.propagate}}deny(a,n,i,s,c){if(c){let l=this.breakers.get(a)??{consecutiveBlocks:0},u=l.consecutiveBlocks+1;this.breakers.set(a,{consecutiveBlocks:u,openUntil:u>=this.limits.breakerThreshold?s+this.limits.breakerCooldownMs:l.openUntil})}return{...n,allowed:!1,reason:i,message:Ga[i]}}breakerOpen(a){let n=this.breakers.get(a);return n?.openUntil!=null&&n.openUntil>this.clock()}reset(a){if(a){this.breakers.delete(a);return}this.breakers.clear(),this.traces.clear()}expireTraces(a){if(this.traces.size===0)return;for(let[n,i]of this.traces)if(a-i.firstAt>this.limits.traceWindowMs)this.traces.delete(n)}get trackedTraces(){return this.traces.size}}function Rd(a){return{...a.propagate}}function Dd(a){return{status:508,headers:{"content-type":"application/json","x-ts-cloud-recursion-blocked":a.reason},body:{error:"recursion_blocked",reason:a.reason,message:a.message??Ga[a.reason],depth:a.depth,traceId:a.traceId}}}var Wg=new ii;function pa(a){let n=globalThis.process?.env?.[a];if(n==null||n==="")return;return n!=="0"&&n.toLowerCase()!=="false"}function oi(){let a=globalThis.process?.env??{};return a.TS_CLOUD_FUNCTION_ID||a.AWS_LAMBDA_FUNCTION_NAME||a.FUNCTION_NAME||"function"}function uA(a){let n=a===!1?{enabled:!1}:a??{},i=pa("TS_CLOUD_RECURSION_PROTECTION"),s=pa("TS_CLOUD_RECURSION_DETECTION_ONLY");return{enabled:i??n.enabled??!0,detectionOnly:s??n.detectionOnly??!1,limits:{...Ci,...n.limits},functionId:n.functionId??oi()}}var De,fe;function pA(){let a=globalThis.fetch;if(!a||De===a)return()=>{};fe=a;let n=async(i,s)=>{let c=Wg.getStore();if(!c)return fe(i,s);let l=new Headers(s?.headers??(i instanceof Request?i.headers:void 0));for(let[u,h]of Object.entries(Rd(c)))l.set(u,h);if(i instanceof Request)return fe(new Request(i,{headers:l}),s);return fe(i,{...s,headers:l})};return Object.assign(n,a),globalThis.fetch=n,De=n,()=>{if(globalThis.fetch===De&&fe)globalThis.fetch=fe;De=void 0}}var ct,Mt;function gA(a){if(!ct||JSON.stringify(Mt)!==JSON.stringify(a))ct=new lo(a),Mt=a;return ct}function XC(){if(ct=void 0,Mt=void 0,De&&fe&&globalThis.fetch===De)globalThis.fetch=fe;De=void 0,fe=void 0}function mA(a,n){let i=uA(n);if(!i.enabled)return;let s=gA(i.limits),c={functionId:i.functionId,headers:a},l=s.check(c);return{verdict:l,blocked:!l.allowed&&!i.detectionOnly,observed:!l.allowed&&i.detectionOnly}}function hA(a,n){return pA(),Wg.run(a,n)}function YC(a){let n=a,i=n?.default??n;if(typeof i==="function")return{fetch:i};return{fetch:i?.fetch??n?.fetch,queue:i?.queue??n?.queue,cli:i?.cli??n?.cli}}var ci=/^(?:text\/|application\/(?:json|xml|javascript|graphql|x-www-form-urlencoded|.*\+json|.*\+xml)|image\/svg)/i;function li(a){if(!a)return!0;return ci.test(a)}function ui(a){if(a?.maintenance)return a.maintenance;let n=globalThis.process?.env??{};return{enabled:n.MAINTENANCE_MODE==="1"||n.MAINTENANCE_MODE==="true",bypassSecret:n.MAINTENANCE_BYPASS_SECRET}}function fA(a){let n=a.requestContext?.domainName??"localhost",i=a.rawQueryString?`?${a.rawQueryString}`:"",s=`https://${n}${a.rawPath||"/"}${i}`,c=new Headers;for(let[h,y]of Object.entries(a.headers??{}))if(y!==void 0)c.set(h,y);if(a.cookies?.length)c.set("cookie",a.cookies.join("; "));let l=a.requestContext.http.method,u;if(a.body!==void 0&&l!=="GET"&&l!=="HEAD")u=a.isBase64Encoded?new Uint8Array(Buffer.from(a.body,"base64")):new TextEncoder().encode(a.body);return new Request(s,{method:l,headers:c,body:u})}async function Jg(a){let n={},i=[],s=typeof a.headers.getSetCookie==="function"?a.headers.getSetCookie():[];for(let u of s)i.push(u);a.headers.forEach((u,h)=>{if(h.toLowerCase()==="set-cookie")return;n[h]=u});let c=Buffer.from(await a.arrayBuffer()),l=li(a.headers.get("content-type"));return{statusCode:a.status,headers:n,...i.length?{cookies:i}:{},body:l?c.toString("utf-8"):c.toString("base64"),isBase64Encoded:!l}}function AA(a,n){return async(i)=>{if(i.warmer)return{statusCode:200,headers:{"content-type":"text/plain"},body:"warm",isBase64Encoded:!1};if(!a)return{statusCode:501,headers:{"content-type":"text/plain"},body:"No HTTP handler configured",isBase64Encoded:!1};let s=ui(n);if(s.enabled){let u=i.headers?.["x-maintenance-bypass"]??i.cookies?.find((h)=>h.startsWith("tscloud_bypass="))?.split("=")[1];if(!s.bypassSecret||u!==s.bypassSecret)return{statusCode:503,headers:{"content-type":"text/plain","retry-after":"120"},body:"Service temporarily unavailable (maintenance mode)",isBase64Encoded:!1}}let c=mA(i.headers??{},n?.recursionProtection);if(c?.blocked){let u=Dd(c.verdict);return{statusCode:u.status,headers:{...u.headers,"retry-after":"60"},body:JSON.stringify(u.body),isBase64Encoded:!1}}let l=fA(i);if(!c){let u=await a(l);return Jg(u)}if(c.observed)console.warn(`[ts-cloud] recursion detected (${c.verdict.reason}) at depth ${c.verdict.depth}; detection-only mode let it run`);return hA(c.verdict,async()=>Jg(await a(l)))}}function di(a){try{return JSON.parse(a)}catch{return a}}function yA(a){return async(n)=>{let i=[];if(n.warmer)return{batchItemFailures:i};if(!a)return{batchItemFailures:i};for(let s of n.Records??[])try{await a(di(s.body),s)}catch{i.push({itemIdentifier:s.messageId})}return{batchItemFailures:i}}}function IA(a){return async(n)=>{if(n.warmer)return{statusCode:0,output:"warm"};if(!a)return{statusCode:501,output:"No CLI handler configured"};return a(n)}}function ZC(a,n){return{http:AA(a.fetch,n),queue:yA(a.queue),cli:IA(a.cli)}}function SA(a={}){let n=a.socketPath??"/tmp/.tscloud-fpm.sock",i=a.maxChildren??1;return`; ts-cloud php-fpm configuration (generated) — AWS Lambda custom runtime.
7338
7338
  [global]
7339
7339
  daemonize = no
7340
7340
  error_log = ${a.errorLog??"/tmp/storage/logs/php-fpm.log"}
@@ -7351,5 +7351,5 @@ decorate_workers_output = no
7351
7351
  php_admin_value[error_log] = /dev/stderr
7352
7352
  php_admin_flag[log_errors] = on
7353
7353
  clear_env = no
7354
- `}function hi(){return Ua(pi(gi(import.meta.url)),"runtime-assets")}function bi(){let a=hi(),n=(i)=>mi(Ua(a,i),"utf-8");return[{path:"bootstrap",contents:n("bootstrap"),mode:493},{path:"tscloud/runtime.php",contents:n("runtime.php"),mode:420},{path:"tscloud/octane-runtime.php",contents:n("octane-runtime.php"),mode:420},{path:"tscloud/cli-runtime.php",contents:n("cli-runtime.php"),mode:420},{path:"tscloud/fastcgi-client.php",contents:n("fastcgi-client.php"),mode:420},{path:"tscloud/php-fpm.conf",contents:SA(),mode:420}]}function Pd(a={}){let n=a.cacheDriver??"dynamodb";return{APP_ENV:"production",LOG_CHANNEL:"stderr",CACHE_STORE:n,CACHE_DRIVER:n,SESSION_DRIVER:n,QUEUE_CONNECTION:"sqs",FILESYSTEM_DISK:"s3",VIEW_COMPILED_PATH:"/tmp/storage/framework/views",APP_SERVICES_CACHE:"/tmp/bootstrap/cache/services.php",APP_PACKAGES_CACHE:"/tmp/bootstrap/cache/packages.php",APP_CONFIG_CACHE:"/tmp/bootstrap/cache/config.php",APP_ROUTES_CACHE:"/tmp/bootstrap/cache/routes.php",APP_EVENTS_CACHE:"/tmp/bootstrap/cache/events.php"}}var CA=["composer install --no-dev --optimize-autoloader --no-interaction","php artisan config:cache","php artisan route:cache","php artisan event:cache","php artisan view:cache"];function*Va(a){for(let n of Ei(a)){let i=Me(a,n);if(Fa(i).isDirectory())yield*Va(i);else yield i}}function eb(a={}){let n=a.architecture??"x86_64",i=a.platform??(n==="arm64"?"linux/arm64":"linux/amd64"),s=a.onStep??(()=>{}),c=wi(Me(Di(),"tscloud-php-layer-")),l="tscloud-php-layer:build";try{Ni(Me(c,"Dockerfile"),lA(a)),s("Building PHP runtime image (docker)"),ot("docker",["build","--platform",i,"-t","tscloud-php-layer:build",c],{stdio:"inherit"}),s("Extracting /opt/php from image");let u=ot("docker",["create","--platform",i,"tscloud-php-layer:build"],{encoding:"utf-8"}).trim(),h=Me(c,"opt");vi(h,{recursive:!0});try{ot("docker",["cp",`${u}:/opt/php`,Me(h,"php")],{stdio:"inherit"})}finally{ot("docker",["rm",u],{stdio:"ignore"})}if(!Ti(Me(h,"php","bin","php")))throw Error("layer build produced no /opt/php/bin/php");let y=[];for(let A of Va(h)){let C=ki(h,A).replace(/\\/g,"/"),T=Fa(A).mode&73?493:420;y.push({name:C,data:Pi(A),mode:T})}s("Injecting runtime assets");let S=new Set(bi().map((A)=>A.path)),b=y.filter((A)=>!S.has(A.name));for(let A of bi())b.push({name:A.path,data:A.contents,mode:A.mode});return s("Packaging layer ZIP"),{zip:Si(b),architecture:n,fileCount:b.length}}finally{Ri(c,{recursive:!0,force:!0})}}var bA=[".git",".github","node_modules","tests","storage/logs","storage/framework/cache","storage/framework/sessions","storage/framework/views",".env",".env.local",".vapor",".ts-cloud","dist-lambda"];function Bi(a,n){return n.some((i)=>a===i||a.startsWith(`${i}/`))}function*Ha(a,n,i){for(let s of Mi(a)){let c=Oi(a,s),l=Ka(n,c).replace(/\\/g,"/");if(Bi(l,i))continue;if(ja(c).isDirectory())yield*Ha(c,n,i);else yield c}}function uo(a){if(a.skipBuild)return;let n=na(a.projectRoot??process.cwd()),i=a.app.build??CA;for(let s of i)a.onStep?.(`build: ${s}`),$i(s,{stdio:"inherit",cwd:n})}function po(a,n=[]){let i=na(a),s=[...bA,Js(),...n],c=[];for(let l of Ha(i,i,s)){let u=Ka(i,l).replace(/\\/g,"/"),h=(ja(l).mode&73)!==0;c.push({name:u,data:xi(l),mode:h?493:420})}return c}function Nd(a){let n=na(a.projectRoot??process.cwd());uo(a),a.onStep?.("packaging application tree");let i=po(n,a.exclude);if(!i.length)throw Error(`No files to package under ${n}`);let s=Si(i),c=a.app.handlers?.http??"public/index.php";return{zip:s,sha256:Li("sha256").update(s).digest("hex"),handlers:{http:c,queue:a.app.handlers?.queue??c,cli:a.app.handlers?.cli??c},fileCount:i.length}}class Xg{optimizations=new Map;imageConfigs=new Map;ssgConfigs=new Map;prerenderConfigs=new Map;counter=0;createAssetOptimization(a){let n=`asset-opt-${Date.now()}-${this.counter++}`,i={id:n,...a};return this.optimizations.set(n,i),i}createImageOptimization(a){let n=`image-opt-${Date.now()}-${this.counter++}`,i={id:n,...a};return this.imageConfigs.set(n,i),i}createSSGConfig(a){let n=`ssg-${Date.now()}-${this.counter++}`,i={id:n,...a};return this.ssgConfigs.set(n,i),i}createPrerenderConfig(a){let n=`prerender-${Date.now()}-${this.counter++}`,i={id:n,...a};return this.prerenderConfigs.set(n,i),i}listOptimizations(){return Array.from(this.optimizations.values())}listImageConfigs(){return Array.from(this.imageConfigs.values())}clear(){this.optimizations.clear(),this.imageConfigs.clear(),this.ssgConfigs.clear(),this.prerenderConfigs.clear()}}var tb=new Xg;class Yg{policies=new Map;versioningConfigs=new Map;replicationRules=new Map;tieringConfigs=new Map;objectLocks=new Map;transferAcceleration=new Map;accessPoints=new Map;glacierConfigs=new Map;inventories=new Map;batchOps=new Map;eventNotifications=new Map;counter=0;createLifecyclePolicy(a,n){let i=`lifecycle-${Date.now()}-${this.counter++}`,s={id:i,transitions:a,expiration:n};return this.policies.set(i,s),s}enableVersioning(a=!1){let n=`versioning-${Date.now()}-${this.counter++}`,i={id:n,enabled:!0,mfaDelete:a};return this.versioningConfigs.set(n,i),i}createReplicationRule(a,n,i){let s=`replication-${Date.now()}-${this.counter++}`,c={id:s,sourceRegion:a,destRegion:n,destBucket:i};return this.replicationRules.set(s,c),c}createIntelligentTiering(a,n){let i=`tiering-${Date.now()}-${this.counter++}`,s={id:i,archiveDays:a,deepArchiveDays:n};return this.tieringConfigs.set(i,s),s}enableObjectLock(a){let n=`object-lock-${Date.now()}-${this.counter++}`,i={id:n,bucketName:a.bucketName,mode:a.mode||"COMPLIANCE",retentionDays:a.retentionDays,retentionYears:a.retentionYears,legalHoldEnabled:a.legalHoldEnabled||!1};return this.objectLocks.set(n,i),i}enableTransferAcceleration(a){let n=`transfer-accel-${Date.now()}-${this.counter++}`,i={id:n,bucketName:a,enabled:!0,endpoint:`${a}.s3-accelerate.amazonaws.com`};return this.transferAcceleration.set(n,i),i}createAccessPoint(a){let n=`access-point-${Date.now()}-${this.counter++}`,i={id:n,name:a.name,bucketName:a.bucketName,vpcId:a.vpcId,publicAccessBlock:a.publicAccessBlock!==!1,policy:a.policy};return this.accessPoints.set(n,i),i}createGlacierArchive(a){let n=`glacier-${Date.now()}-${this.counter++}`,i={id:n,bucketName:a.bucketName,archiveType:a.archiveType,transitionDays:a.transitionDays,restoreConfig:a.restoreTier?{tier:a.restoreTier,days:a.restoreDays||7}:void 0};return this.glacierConfigs.set(n,i),i}createInventory(a){let n=`inventory-${Date.now()}-${this.counter++}`,i={id:n,sourceBucket:a.sourceBucket,destinationBucket:a.destinationBucket,schedule:a.schedule||"Daily",format:a.format||"CSV",includedFields:a.includedFields||["Size","LastModifiedDate","StorageClass","ETag"],prefix:a.prefix};return this.inventories.set(n,i),i}createBatchOperation(a){let n=`batch-op-${Date.now()}-${this.counter++}`,i={id:n,operation:a.operation,manifestBucket:a.manifestBucket,manifestKey:a.manifestKey,priority:a.priority||10,status:"pending"};return this.batchOps.set(n,i),i}executeBatchOperation(a){let n=this.batchOps.get(a);if(!n)throw Error(`Batch operation not found: ${a}`);return n.status="in_progress",n.totalObjects=1000,n.processedObjects=0,n}getBatchOperationStatus(a){return this.batchOps.get(a)}createLambdaNotification(a){let n=`event-${Date.now()}-${this.counter++}`,i={id:n,bucketName:a.bucketName,events:a.events,destination:{type:"Lambda",arn:a.lambdaArn},filter:a.prefix||a.suffix?{prefix:a.prefix,suffix:a.suffix}:void 0};return this.eventNotifications.set(n,i),i}createSQSNotification(a){let n=`event-${Date.now()}-${this.counter++}`,i={id:n,bucketName:a.bucketName,events:a.events,destination:{type:"SQS",arn:a.queueArn},filter:a.prefix||a.suffix?{prefix:a.prefix,suffix:a.suffix}:void 0};return this.eventNotifications.set(n,i),i}createSNSNotification(a){let n=`event-${Date.now()}-${this.counter++}`,i={id:n,bucketName:a.bucketName,events:a.events,destination:{type:"SNS",arn:a.topicArn},filter:a.prefix||a.suffix?{prefix:a.prefix,suffix:a.suffix}:void 0};return this.eventNotifications.set(n,i),i}generateObjectLockCF(a){let n={ObjectLockEnabled:"Enabled",ObjectLockConfiguration:{ObjectLockEnabled:"Enabled",Rule:{DefaultRetention:{Mode:a.mode}}}};if(a.retentionDays)n.ObjectLockConfiguration.Rule.DefaultRetention.Days=a.retentionDays;if(a.retentionYears)n.ObjectLockConfiguration.Rule.DefaultRetention.Years=a.retentionYears;return n}generateTransferAccelerationCF(a){return{AccelerateConfiguration:{AccelerationStatus:a.enabled?"Enabled":"Suspended"}}}generateAccessPointCF(a){return{Type:"AWS::S3::AccessPoint",Properties:{Name:a.name,Bucket:a.bucketName,...a.vpcId&&{VpcConfiguration:{VpcId:a.vpcId}},PublicAccessBlockConfiguration:a.publicAccessBlock?{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}:void 0,...a.policy&&{Policy:a.policy}}}}generateInventoryCF(a){return{Type:"AWS::S3::Bucket",Properties:{InventoryConfigurations:[{Id:a.id,Destination:{BucketArn:`arn:aws:s3:::${a.destinationBucket}`,Format:a.format},Enabled:!0,IncludedObjectVersions:"Current",OptionalFields:a.includedFields,ScheduleFrequency:a.schedule,...a.prefix&&{Prefix:a.prefix}}]}}}generateEventNotificationCF(a){let n=a.destination.type==="Lambda"?"LambdaConfigurations":a.destination.type==="SQS"?"QueueConfigurations":"TopicConfigurations",i=a.destination.type==="Lambda"?"Function":a.destination.type==="SQS"?"Queue":"Topic",s={Event:a.events[0],[i]:a.destination.arn};if(a.filter)s.Filter={S3Key:{Rules:[...a.filter.prefix?[{Name:"prefix",Value:a.filter.prefix}]:[],...a.filter.suffix?[{Name:"suffix",Value:a.filter.suffix}]:[]]}};return{NotificationConfiguration:{[n]:[s]}}}clear(){this.policies.clear(),this.versioningConfigs.clear(),this.replicationRules.clear(),this.tieringConfigs.clear(),this.objectLocks.clear(),this.transferAcceleration.clear(),this.accessPoints.clear(),this.glacierConfigs.clear(),this.inventories.clear(),this.batchOps.clear(),this.eventNotifications.clear()}}var rb=new Yg;class Zg{checks=new Map;synthetics=new Map;uptimeTrackers=new Map;counter=0;createHealthCheck(a,n=30,i=10){let s=`health-${Date.now()}-${this.counter++}`,c={id:s,url:a,interval:n,timeout:i,status:"healthy"};return this.checks.set(s,c),c}createSyntheticMonitor(a,n,i,s){let c=`synthetic-${Date.now()}-${this.counter++}`,l={id:c,name:a,script:n,frequency:i,locations:s};return this.synthetics.set(c,l),l}trackUptime(a,n,i){let s=`uptime-${Date.now()}-${this.counter++}`,c=n/(n+i)*100,l={id:s,resource:a,uptime:n,downtime:i,availability:c};return this.uptimeTrackers.set(s,l),l}clear(){this.checks.clear(),this.synthetics.clear(),this.uptimeTrackers.clear()}}var nb=new Zg;class em{wafRules=new Map;shieldProtections=new Map;securityGroups=new Map;nacls=new Map;counter=0;createWAFRule(a,n,i,s){let c=`waf-${Date.now()}-${this.counter++}`,l={id:c,name:a,priority:n,action:i,conditions:s};return this.wafRules.set(c,l),l}enableShield(a,n="standard"){let i=`shield-${Date.now()}-${this.counter++}`,s={id:i,resourceArn:a,protectionType:n};return this.shieldProtections.set(i,s),s}createSecurityGroup(a,n,i){let s=`sg-${Date.now()}-${this.counter++}`,c={id:s,name:a,vpcId:n,rules:i};return this.securityGroups.set(s,c),c}createNACL(a,n){let i=`nacl-${Date.now()}-${this.counter++}`,s={id:i,vpcId:a,rules:n};return this.nacls.set(i,s),s}clear(){this.wafRules.clear(),this.shieldProtections.clear(),this.securityGroups.clear(),this.nacls.clear()}}var ib=new em;class tm{strategies=new Map;allocations=new Map;groups=new Map;counter=0;createTaggingStrategy(a,n){let i=`tagging-${Date.now()}-${this.counter++}`,s={id:i,tags:a,resources:n};return this.strategies.set(i,s),s}createCostAllocation(a,n){let i=`cost-${Date.now()}-${this.counter++}`,s={id:i,tagKey:a,allocations:n};return this.allocations.set(i,s),s}createResourceGroup(a,n,i){let s=`group-${Date.now()}-${this.counter++}`,c={id:s,name:a,query:{resourceTypeFilters:n,tagFilters:i}};return this.groups.set(s,c),c}clear(){this.strategies.clear(),this.allocations.clear(),this.groups.clear()}}var sb=new tm;
7355
- export{Bp,x,xp,hf,Ey,ff,vy,Ty,wy,Ry,Dy,Py,Ny,ky,By,xy,_p,Op,od,ad,Js,_,d,cd,Lp,O,dd,p,Af,fi,ld,ud,le,pd,_y,r,t,Oy,Ly,g,$y,My,Fy,Uy,Qy,Ft,gd,Xs,yf,Hy,Gy,Ee,He,ve,L,I,o,f,Ge,m,If,qe,M,ut,qy,Sf,F,md,Te,Ut,Ys,Y,hd,Z,Cf,Zs,U,Q,D,Ai,E,Qt,pt,H,e,eo,Vy,$p,fd,jy,zy,Ky,Wy,Ad,Jy,Xy,Yy,Zy,eI,tI,rI,nI,iI,sI,oI,aI,bf,Ef,vf,Tf,wf,Rf,Df,Ht,Mp,Fp,_r,yi,cI,Up,dI,lI,Or,uI,pI,gI,mI,hI,fI,Pf,Nf,kf,Bf,xf,to,yI,_f,Of,Lf,G,II,Ve,ro,Gt,$f,Qp,Mf,Ff,Uf,Hp,ee,SI,CI,bI,EI,Qf,vI,q,TI,wI,RI,Gp,qp,DI,Vp,jp,PI,NI,kI,BI,xI,Hf,yd,_I,OI,LI,$I,MI,Gf,qf,FI,UI,QI,HI,GI,qI,VI,jI,zI,zp,Id,KI,WI,JI,XI,Kp,Wp,Jp,YI,Xp,ZI,eS,tS,rS,Yp,nS,iS,sS,oS,aS,cS,dS,lS,Vf,jf,zf,Kf,Zp,uS,pS,gS,mS,hS,fS,AS,yS,IS,Wf,Jf,Xf,Yf,SS,CS,eg,bS,tg,rg,ng,ig,ES,vS,TS,wS,we,Ii,RS,DS,PS,NS,kS,BS,xS,_S,Zf,OS,LS,sg,og,$S,MS,eA,FS,US,QS,HS,GS,qS,VS,jS,zS,KS,WS,JS,XS,YS,ZS,eC,tC,rC,nC,iC,sC,ag,oC,cg,aC,dg,cC,lg,dC,ug,lC,Lr,uC,pg,pC,no,gC,gg,mC,mg,hC,hg,fC,fg,AC,Ag,yC,$r,IC,yg,SC,Ig,CC,Sg,bC,Cg,EC,bg,vC,Eg,TC,vg,wC,Tg,RC,wg,DC,Rg,PC,Dg,NC,Pg,kC,Ng,BC,kg,xC,Bg,_C,xg,OC,_g,LC,Og,$C,Lg,MC,$g,FC,Mg,UC,Fg,QC,Ug,HC,Qg,GC,Hg,qC,tA,rA,nA,iA,Gg,VC,qg,jC,Vg,zC,jg,KC,Si,sA,oA,io,Sd,Mr,aA,so,qt,Cd,bd,cA,dA,zg,lA,Ed,Kg,WC,JC,oo,ao,co,vd,Ci,Td,wd,lo,Rd,Dd,Wg,uA,pA,gA,XC,mA,hA,YC,fA,Jg,AA,yA,IA,ZC,SA,bi,Pd,CA,eb,bA,uo,po,Nd,Xg,tb,Yg,rb,Zg,nb,em,ib,tm,sb};
7354
+ `}function hi(){return Ua(pi(gi(import.meta.url)),"runtime-assets")}function Ei(){let a=hi(),n=(i)=>mi(Ua(a,i),"utf-8");return[{path:"bootstrap",contents:n("bootstrap"),mode:493},{path:"tscloud/runtime.php",contents:n("runtime.php"),mode:420},{path:"tscloud/octane-runtime.php",contents:n("octane-runtime.php"),mode:420},{path:"tscloud/cli-runtime.php",contents:n("cli-runtime.php"),mode:420},{path:"tscloud/fastcgi-client.php",contents:n("fastcgi-client.php"),mode:420},{path:"tscloud/php-fpm.conf",contents:SA(),mode:420}]}function Pd(a={}){let n=a.cacheDriver??"dynamodb";return{APP_ENV:"production",LOG_CHANNEL:"stderr",CACHE_STORE:n,CACHE_DRIVER:n,SESSION_DRIVER:n,QUEUE_CONNECTION:"sqs",FILESYSTEM_DISK:"s3",VIEW_COMPILED_PATH:"/tmp/storage/framework/views",APP_SERVICES_CACHE:"/tmp/bootstrap/cache/services.php",APP_PACKAGES_CACHE:"/tmp/bootstrap/cache/packages.php",APP_CONFIG_CACHE:"/tmp/bootstrap/cache/config.php",APP_ROUTES_CACHE:"/tmp/bootstrap/cache/routes.php",APP_EVENTS_CACHE:"/tmp/bootstrap/cache/events.php"}}var CA=["composer install --no-dev --optimize-autoloader --no-interaction","php artisan config:cache","php artisan route:cache","php artisan event:cache","php artisan view:cache"];function*Va(a){for(let n of wi(a)){let i=Me(a,n);if(Fa(i).isDirectory())yield*Va(i);else yield i}}function eE(a={}){let n=a.architecture??"x86_64",i=a.platform??(n==="arm64"?"linux/arm64":"linux/amd64"),s=a.onStep??(()=>{}),c=vi(Me(Di(),"tscloud-php-layer-")),l="tscloud-php-layer:build";try{Ni(Me(c,"Dockerfile"),lA(a)),s("Building PHP runtime image (docker)"),ot("docker",["build","--platform",i,"-t","tscloud-php-layer:build",c],{stdio:"inherit"}),s("Extracting /opt/php from image");let u=ot("docker",["create","--platform",i,"tscloud-php-layer:build"],{encoding:"utf-8"}).trim(),h=Me(c,"opt");Ti(h,{recursive:!0});try{ot("docker",["cp",`${u}:/opt/php`,Me(h,"php")],{stdio:"inherit"})}finally{ot("docker",["rm",u],{stdio:"ignore"})}if(!bi(Me(h,"php","bin","php")))throw Error("layer build produced no /opt/php/bin/php");let y=[];for(let C of Va(h)){let T=ki(h,C).replace(/\\/g,"/"),v=Fa(C).mode&73?493:420;y.push({name:T,data:Pi(C),mode:v})}s("Injecting runtime assets");let S=new Set(Ei().map((C)=>C.path)),A=y.filter((C)=>!S.has(C.name));for(let C of Ei())A.push({name:C.path,data:C.contents,mode:C.mode});return s("Packaging layer ZIP"),{zip:Si(A),architecture:n,fileCount:A.length}}finally{Ri(c,{recursive:!0,force:!0})}}var EA=[".git",".github","node_modules","tests","storage/logs","storage/framework/cache","storage/framework/sessions","storage/framework/views",".env",".env.local",".vapor",".ts-cloud","dist-lambda"];function Bi(a,n){return n.some((i)=>a===i||a.startsWith(`${i}/`))}function*Ha(a,n,i){for(let s of Mi(a)){let c=Oi(a,s),l=Ka(n,c).replace(/\\/g,"/");if(Bi(l,i))continue;if(ja(c).isDirectory())yield*Ha(c,n,i);else yield c}}function uo(a){if(a.skipBuild)return;let n=na(a.projectRoot??process.cwd()),i=a.app.build??CA;for(let s of i)a.onStep?.(`build: ${s}`),$i(s,{stdio:"inherit",cwd:n})}function po(a,n=[]){let i=na(a),s=[...EA,Js(),...n],c=[];for(let l of Ha(i,i,s)){let u=Ka(i,l).replace(/\\/g,"/"),h=(ja(l).mode&73)!==0;c.push({name:u,data:xi(l),mode:h?493:420})}return c}function Nd(a){let n=na(a.projectRoot??process.cwd());uo(a),a.onStep?.("packaging application tree");let i=po(n,a.exclude);if(!i.length)throw Error(`No files to package under ${n}`);let s=Si(i),c=a.app.handlers?.http??"public/index.php";return{zip:s,sha256:Li("sha256").update(s).digest("hex"),handlers:{http:c,queue:a.app.handlers?.queue??c,cli:a.app.handlers?.cli??c},fileCount:i.length}}class Xg{optimizations=new Map;imageConfigs=new Map;ssgConfigs=new Map;prerenderConfigs=new Map;counter=0;createAssetOptimization(a){let n=`asset-opt-${Date.now()}-${this.counter++}`,i={id:n,...a};return this.optimizations.set(n,i),i}createImageOptimization(a){let n=`image-opt-${Date.now()}-${this.counter++}`,i={id:n,...a};return this.imageConfigs.set(n,i),i}createSSGConfig(a){let n=`ssg-${Date.now()}-${this.counter++}`,i={id:n,...a};return this.ssgConfigs.set(n,i),i}createPrerenderConfig(a){let n=`prerender-${Date.now()}-${this.counter++}`,i={id:n,...a};return this.prerenderConfigs.set(n,i),i}listOptimizations(){return Array.from(this.optimizations.values())}listImageConfigs(){return Array.from(this.imageConfigs.values())}clear(){this.optimizations.clear(),this.imageConfigs.clear(),this.ssgConfigs.clear(),this.prerenderConfigs.clear()}}var tE=new Xg;class Yg{policies=new Map;versioningConfigs=new Map;replicationRules=new Map;tieringConfigs=new Map;objectLocks=new Map;transferAcceleration=new Map;accessPoints=new Map;glacierConfigs=new Map;inventories=new Map;batchOps=new Map;eventNotifications=new Map;counter=0;createLifecyclePolicy(a,n){let i=`lifecycle-${Date.now()}-${this.counter++}`,s={id:i,transitions:a,expiration:n};return this.policies.set(i,s),s}enableVersioning(a=!1){let n=`versioning-${Date.now()}-${this.counter++}`,i={id:n,enabled:!0,mfaDelete:a};return this.versioningConfigs.set(n,i),i}createReplicationRule(a,n,i){let s=`replication-${Date.now()}-${this.counter++}`,c={id:s,sourceRegion:a,destRegion:n,destBucket:i};return this.replicationRules.set(s,c),c}createIntelligentTiering(a,n){let i=`tiering-${Date.now()}-${this.counter++}`,s={id:i,archiveDays:a,deepArchiveDays:n};return this.tieringConfigs.set(i,s),s}enableObjectLock(a){let n=`object-lock-${Date.now()}-${this.counter++}`,i={id:n,bucketName:a.bucketName,mode:a.mode||"COMPLIANCE",retentionDays:a.retentionDays,retentionYears:a.retentionYears,legalHoldEnabled:a.legalHoldEnabled||!1};return this.objectLocks.set(n,i),i}enableTransferAcceleration(a){let n=`transfer-accel-${Date.now()}-${this.counter++}`,i={id:n,bucketName:a,enabled:!0,endpoint:`${a}.s3-accelerate.amazonaws.com`};return this.transferAcceleration.set(n,i),i}createAccessPoint(a){let n=`access-point-${Date.now()}-${this.counter++}`,i={id:n,name:a.name,bucketName:a.bucketName,vpcId:a.vpcId,publicAccessBlock:a.publicAccessBlock!==!1,policy:a.policy};return this.accessPoints.set(n,i),i}createGlacierArchive(a){let n=`glacier-${Date.now()}-${this.counter++}`,i={id:n,bucketName:a.bucketName,archiveType:a.archiveType,transitionDays:a.transitionDays,restoreConfig:a.restoreTier?{tier:a.restoreTier,days:a.restoreDays||7}:void 0};return this.glacierConfigs.set(n,i),i}createInventory(a){let n=`inventory-${Date.now()}-${this.counter++}`,i={id:n,sourceBucket:a.sourceBucket,destinationBucket:a.destinationBucket,schedule:a.schedule||"Daily",format:a.format||"CSV",includedFields:a.includedFields||["Size","LastModifiedDate","StorageClass","ETag"],prefix:a.prefix};return this.inventories.set(n,i),i}createBatchOperation(a){let n=`batch-op-${Date.now()}-${this.counter++}`,i={id:n,operation:a.operation,manifestBucket:a.manifestBucket,manifestKey:a.manifestKey,priority:a.priority||10,status:"pending"};return this.batchOps.set(n,i),i}executeBatchOperation(a){let n=this.batchOps.get(a);if(!n)throw Error(`Batch operation not found: ${a}`);return n.status="in_progress",n.totalObjects=1000,n.processedObjects=0,n}getBatchOperationStatus(a){return this.batchOps.get(a)}createLambdaNotification(a){let n=`event-${Date.now()}-${this.counter++}`,i={id:n,bucketName:a.bucketName,events:a.events,destination:{type:"Lambda",arn:a.lambdaArn},filter:a.prefix||a.suffix?{prefix:a.prefix,suffix:a.suffix}:void 0};return this.eventNotifications.set(n,i),i}createSQSNotification(a){let n=`event-${Date.now()}-${this.counter++}`,i={id:n,bucketName:a.bucketName,events:a.events,destination:{type:"SQS",arn:a.queueArn},filter:a.prefix||a.suffix?{prefix:a.prefix,suffix:a.suffix}:void 0};return this.eventNotifications.set(n,i),i}createSNSNotification(a){let n=`event-${Date.now()}-${this.counter++}`,i={id:n,bucketName:a.bucketName,events:a.events,destination:{type:"SNS",arn:a.topicArn},filter:a.prefix||a.suffix?{prefix:a.prefix,suffix:a.suffix}:void 0};return this.eventNotifications.set(n,i),i}generateObjectLockCF(a){let n={ObjectLockEnabled:"Enabled",ObjectLockConfiguration:{ObjectLockEnabled:"Enabled",Rule:{DefaultRetention:{Mode:a.mode}}}};if(a.retentionDays)n.ObjectLockConfiguration.Rule.DefaultRetention.Days=a.retentionDays;if(a.retentionYears)n.ObjectLockConfiguration.Rule.DefaultRetention.Years=a.retentionYears;return n}generateTransferAccelerationCF(a){return{AccelerateConfiguration:{AccelerationStatus:a.enabled?"Enabled":"Suspended"}}}generateAccessPointCF(a){return{Type:"AWS::S3::AccessPoint",Properties:{Name:a.name,Bucket:a.bucketName,...a.vpcId&&{VpcConfiguration:{VpcId:a.vpcId}},PublicAccessBlockConfiguration:a.publicAccessBlock?{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}:void 0,...a.policy&&{Policy:a.policy}}}}generateInventoryCF(a){return{Type:"AWS::S3::Bucket",Properties:{InventoryConfigurations:[{Id:a.id,Destination:{BucketArn:`arn:aws:s3:::${a.destinationBucket}`,Format:a.format},Enabled:!0,IncludedObjectVersions:"Current",OptionalFields:a.includedFields,ScheduleFrequency:a.schedule,...a.prefix&&{Prefix:a.prefix}}]}}}generateEventNotificationCF(a){let n=a.destination.type==="Lambda"?"LambdaConfigurations":a.destination.type==="SQS"?"QueueConfigurations":"TopicConfigurations",i=a.destination.type==="Lambda"?"Function":a.destination.type==="SQS"?"Queue":"Topic",s={Event:a.events[0],[i]:a.destination.arn};if(a.filter)s.Filter={S3Key:{Rules:[...a.filter.prefix?[{Name:"prefix",Value:a.filter.prefix}]:[],...a.filter.suffix?[{Name:"suffix",Value:a.filter.suffix}]:[]]}};return{NotificationConfiguration:{[n]:[s]}}}clear(){this.policies.clear(),this.versioningConfigs.clear(),this.replicationRules.clear(),this.tieringConfigs.clear(),this.objectLocks.clear(),this.transferAcceleration.clear(),this.accessPoints.clear(),this.glacierConfigs.clear(),this.inventories.clear(),this.batchOps.clear(),this.eventNotifications.clear()}}var rE=new Yg;class Zg{checks=new Map;synthetics=new Map;uptimeTrackers=new Map;counter=0;createHealthCheck(a,n=30,i=10){let s=`health-${Date.now()}-${this.counter++}`,c={id:s,url:a,interval:n,timeout:i,status:"healthy"};return this.checks.set(s,c),c}createSyntheticMonitor(a,n,i,s){let c=`synthetic-${Date.now()}-${this.counter++}`,l={id:c,name:a,script:n,frequency:i,locations:s};return this.synthetics.set(c,l),l}trackUptime(a,n,i){let s=`uptime-${Date.now()}-${this.counter++}`,c=n/(n+i)*100,l={id:s,resource:a,uptime:n,downtime:i,availability:c};return this.uptimeTrackers.set(s,l),l}clear(){this.checks.clear(),this.synthetics.clear(),this.uptimeTrackers.clear()}}var nE=new Zg;class em{wafRules=new Map;shieldProtections=new Map;securityGroups=new Map;nacls=new Map;counter=0;createWAFRule(a,n,i,s){let c=`waf-${Date.now()}-${this.counter++}`,l={id:c,name:a,priority:n,action:i,conditions:s};return this.wafRules.set(c,l),l}enableShield(a,n="standard"){let i=`shield-${Date.now()}-${this.counter++}`,s={id:i,resourceArn:a,protectionType:n};return this.shieldProtections.set(i,s),s}createSecurityGroup(a,n,i){let s=`sg-${Date.now()}-${this.counter++}`,c={id:s,name:a,vpcId:n,rules:i};return this.securityGroups.set(s,c),c}createNACL(a,n){let i=`nacl-${Date.now()}-${this.counter++}`,s={id:i,vpcId:a,rules:n};return this.nacls.set(i,s),s}clear(){this.wafRules.clear(),this.shieldProtections.clear(),this.securityGroups.clear(),this.nacls.clear()}}var iE=new em;class tm{strategies=new Map;allocations=new Map;groups=new Map;counter=0;createTaggingStrategy(a,n){let i=`tagging-${Date.now()}-${this.counter++}`,s={id:i,tags:a,resources:n};return this.strategies.set(i,s),s}createCostAllocation(a,n){let i=`cost-${Date.now()}-${this.counter++}`,s={id:i,tagKey:a,allocations:n};return this.allocations.set(i,s),s}createResourceGroup(a,n,i){let s=`group-${Date.now()}-${this.counter++}`,c={id:s,name:a,query:{resourceTypeFilters:n,tagFilters:i}};return this.groups.set(s,c),c}clear(){this.strategies.clear(),this.allocations.clear(),this.groups.clear()}}var sE=new tm;
7355
+ export{Bp,_,_p,hf,by,ff,vy,Ty,wy,Ry,Dy,Py,Ny,ky,By,_y,xp,Op,od,ad,Js,x,d,cd,Lp,O,dd,p,Af,fi,ld,ud,le,pd,xy,r,t,Oy,Ly,g,$y,My,Fy,Uy,Qy,Ft,gd,Xs,yf,Hy,Gy,be,He,ve,L,I,o,f,Ge,m,If,qe,M,ut,qy,Sf,F,md,Te,Ut,Ys,Y,hd,Z,Cf,Zs,U,Q,D,Ai,b,Qt,pt,H,e,eo,Vy,$p,fd,jy,zy,Ky,Wy,Ad,Jy,Xy,Yy,Zy,eI,tI,rI,nI,iI,sI,oI,aI,Ef,bf,vf,Tf,wf,Rf,Df,Ht,Mp,Fp,xr,yi,cI,Up,dI,lI,Or,uI,pI,gI,mI,hI,fI,Pf,Nf,kf,Bf,_f,to,yI,xf,Of,Lf,G,II,Ve,ro,Gt,$f,Qp,Mf,Ff,Uf,Hp,ee,SI,CI,EI,bI,Qf,vI,q,TI,wI,RI,Gp,qp,DI,Vp,jp,PI,NI,kI,BI,_I,Hf,yd,xI,OI,LI,$I,MI,Gf,qf,FI,UI,QI,HI,GI,qI,VI,jI,zI,zp,Id,KI,WI,JI,XI,Kp,Wp,Jp,YI,Xp,ZI,eS,tS,rS,Yp,nS,iS,sS,oS,aS,cS,dS,lS,Vf,jf,zf,Kf,Zp,uS,pS,gS,mS,hS,fS,AS,yS,IS,Wf,Jf,Xf,Yf,SS,CS,eg,ES,tg,rg,ng,ig,bS,vS,TS,wS,we,Ii,RS,DS,PS,NS,kS,BS,_S,xS,Zf,OS,LS,sg,og,$S,MS,eA,FS,US,QS,HS,GS,qS,VS,jS,zS,KS,WS,JS,XS,YS,ZS,eC,tC,rC,nC,iC,sC,ag,oC,cg,aC,dg,cC,lg,dC,ug,lC,Lr,uC,pg,pC,no,gC,gg,mC,mg,hC,hg,fC,fg,AC,Ag,yC,$r,IC,yg,SC,Ig,CC,Sg,EC,Cg,bC,Eg,vC,bg,TC,vg,wC,Tg,RC,wg,DC,Rg,PC,Dg,NC,Pg,kC,Ng,BC,kg,_C,Bg,xC,_g,OC,xg,LC,Og,$C,Lg,MC,$g,FC,Mg,UC,Fg,QC,Ug,HC,Qg,GC,Hg,qC,tA,rA,nA,iA,Gg,VC,qg,jC,Vg,zC,jg,KC,Si,sA,oA,io,Sd,Mr,aA,so,qt,Cd,Ed,cA,dA,zg,lA,bd,Kg,WC,JC,oo,ao,co,vd,Ci,Td,wd,lo,Rd,Dd,Wg,uA,pA,gA,XC,mA,hA,YC,fA,Jg,AA,yA,IA,ZC,SA,Ei,Pd,CA,eE,EA,uo,po,Nd,Xg,tE,Yg,rE,Zg,nE,em,iE,tm,sE};