@stacksjs/ts-cloud 0.16.1 → 0.16.2

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 (84) hide show
  1. package/dist/aws/index.js +1 -1
  2. package/dist/bin/{chunk-ghbd1dcz.js → chunk-35p4sfb5.js} +1 -1
  3. package/dist/bin/{chunk-fae1s9p5.js → chunk-8595qcv0.js} +1 -1
  4. package/dist/bin/{chunk-8qmc6yvq.js → chunk-fqajjdy7.js} +23 -23
  5. package/dist/bin/cli.js +4 -4
  6. package/dist/bin/dashboard-server.js +1 -1
  7. package/dist/{chunk-azcvwr5m.js → chunk-11s59686.js} +2 -2
  8. package/dist/{chunk-etmbw4er.js → chunk-aszeyg2w.js} +2 -2
  9. package/dist/{chunk-xacvkpf8.js → chunk-bvspqd2m.js} +1 -1
  10. package/dist/{chunk-b9pm7mbd.js → chunk-c3pvfcme.js} +13 -13
  11. package/dist/{chunk-f9pzjzye.js → chunk-f0t7y458.js} +2 -2
  12. package/dist/{chunk-tg6yasej.js → chunk-f27a8et2.js} +1 -1
  13. package/dist/{chunk-dky93h4d.js → chunk-fgww8ya2.js} +1 -1
  14. package/dist/chunk-gk5ehe62.js +1 -0
  15. package/dist/{chunk-bkv2p4hp.js → chunk-hhy358y8.js} +2 -2
  16. package/dist/{chunk-jnt7ab86.js → chunk-nnfdz28e.js} +2 -2
  17. package/dist/{chunk-d51q92t7.js → chunk-qzbmm0f6.js} +42 -42
  18. package/dist/{chunk-cwjskpj4.js → chunk-r5pjnw74.js} +2 -2
  19. package/dist/{chunk-epqpf6jd.js → chunk-scy8mzqk.js} +1 -1
  20. package/dist/{chunk-dp93dqcr.js → chunk-ttgff76x.js} +38 -38
  21. package/dist/{chunk-a0d0h33y.js → chunk-yqfkq6q7.js} +1 -1
  22. package/dist/deploy/index.js +1 -1
  23. package/dist/dns/index.js +1 -1
  24. package/dist/drivers/index.js +1 -1
  25. package/dist/index.js +26 -26
  26. package/dist/operations/index.js +1 -1
  27. package/dist/protection/index.js +1 -1
  28. package/dist/spend/index.js +1 -1
  29. package/dist/ui/404.html +1 -1
  30. package/dist/ui/accept-invitation.html +1 -1
  31. package/dist/ui/access-denied.html +1 -1
  32. package/dist/ui/account/automation.html +5 -5
  33. package/dist/ui/account/security.html +2 -2
  34. package/dist/ui/applications/compose.html +6 -6
  35. package/dist/ui/applications/new.html +2 -2
  36. package/dist/ui/data/backups.html +6 -6
  37. package/dist/ui/data/services.html +5 -5
  38. package/dist/ui/data/volumes.html +5 -5
  39. package/dist/ui/index.html +6 -6
  40. package/dist/ui/infrastructure/topology.html +6 -6
  41. package/dist/ui/integrations.html +1 -1
  42. package/dist/ui/operations/alerts.html +5 -5
  43. package/dist/ui/operations/configuration.html +5 -5
  44. package/dist/ui/operations/jobs.html +5 -5
  45. package/dist/ui/operations/maintenance.html +5 -5
  46. package/dist/ui/operations/observability.html +6 -6
  47. package/dist/ui/operations/previews.html +6 -6
  48. package/dist/ui/operations/queue.html +5 -5
  49. package/dist/ui/operations/regions.html +5 -5
  50. package/dist/ui/operations/releases.html +6 -6
  51. package/dist/ui/operations/spend.html +6 -6
  52. package/dist/ui/operations/workloads.html +5 -5
  53. package/dist/ui/security.html +2 -2
  54. package/dist/ui/server/actions.html +6 -6
  55. package/dist/ui/server/activity.html +2 -2
  56. package/dist/ui/server/capacity.html +6 -6
  57. package/dist/ui/server/database.html +6 -6
  58. package/dist/ui/server/deployments.html +6 -6
  59. package/dist/ui/server/diagnostics.html +2 -2
  60. package/dist/ui/server/firewall.html +5 -5
  61. package/dist/ui/server/fleet.html +6 -6
  62. package/dist/ui/server/logs.html +6 -6
  63. package/dist/ui/server/metrics.html +6 -6
  64. package/dist/ui/server/security.html +2 -2
  65. package/dist/ui/server/services.html +1 -1
  66. package/dist/ui/server/sites.html +5 -5
  67. package/dist/ui/server/ssh-keys.html +6 -6
  68. package/dist/ui/server/team.html +6 -6
  69. package/dist/ui/server/terminal.html +2 -2
  70. package/dist/ui/serverless/alarms.html +6 -6
  71. package/dist/ui/serverless/assets.html +2 -2
  72. package/dist/ui/serverless/cost.html +2 -2
  73. package/dist/ui/serverless/data.html +6 -6
  74. package/dist/ui/serverless/deployments.html +2 -2
  75. package/dist/ui/serverless/firewall.html +2 -2
  76. package/dist/ui/serverless/functions.html +6 -6
  77. package/dist/ui/serverless/logs.html +6 -6
  78. package/dist/ui/serverless/metrics.html +2 -2
  79. package/dist/ui/serverless/queues.html +6 -6
  80. package/dist/ui/serverless/secrets.html +6 -6
  81. package/dist/ui/serverless/traces.html +6 -6
  82. package/dist/ui/serverless.html +6 -6
  83. package/package.json +3 -3
  84. package/dist/chunk-h1anhx3y.js +0 -1
@@ -1,4 +1,4 @@
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 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 Dp(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:f}=a,S=new URL(i),b=S.hostname,C=Dp(S),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=f||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:S,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=S.pathname||"/",V=ft(S.searchParams),B={host:b,"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),ee=B["x-amz-content-sha256"]||Je(s),te=[n,St(P),V,J,K,ee].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 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 Dp(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:f}=a,S=new URL(i),b=S.hostname,C=Dp(S),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=f||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:S,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=S.pathname||"/",V=ft(S.searchParams),B={host:b,"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),ee=B["x-amz-content-sha256"]||Je(s),te=[n,St(P),V,J,K,ee].join(`
2
2
  `),ne=Je(te),me=[W,w,k,ne].join(`
3
3
  `),oe=a.cache??ke,le=fa(l,R,v,T,me,oe),ie=[`${W} Credential=${c}/${k}`,`SignedHeaders=${K}`,`Signature=${le}`].join(", ");return B.authorization=ie,{url:i,method:n,headers:B,body:s||void 0}}async function Pp(a){let{method:n,url:i,body:s="",accessKeyId:c,secretAccessKey:l,sessionToken:u,signQuery:h=!1,expiresIn:y=86400,datetime:f}=a,S=new URL(i),b=S.hostname,C=Dp(S),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=f||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:S,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=S.pathname||"/",V=ft(S.searchParams),B={host:b,"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),ee=ha(B),te=B["x-amz-content-sha256"]||J,ne=[n,St(P),V,K,ee,te].join(`
4
4
  `),me=await lt(ne),oe=[W,w,k,me].join(`
@@ -20,7 +20,7 @@ ${this.convertToYAML(u,n+2)}`;else s+=`${i} - ${u}
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 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:f=!1,cors:S,lifecycleRules:b}=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(S&&S.length>0)v.Properties.CorsConfiguration={CorsRules:S.map((R)=>({AllowedOrigins:R.allowedOrigins,AllowedMethods:R.allowedMethods,AllowedHeaders:R.allowedHeaders,MaxAge:R.maxAge}))};if(b&&b.length>0)v.Properties.LifecycleConfiguration={Rules:b.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(f&&b){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:f}=a,S=h||r({slug:i,environment:s,resourceType:"backup-vault",suffix:n}),b=t(S),C={Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:S}},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(f&&f<l)W.MoveToColdStorageAfterDays=f;let P={Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:R,BackupPlanRule:[{RuleName:`${n}-daily-backup`,TargetBackupVault:N.Ref(b),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:b,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}}},f={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:f,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},f=be.createBucket({name:"web",slug:n,environment:i,public:!1,versioning:!1,encryption:!0});if(h[f.logicalId]=f.bucket,y.web=!0,u.docs.exists){let S=be.createDocsBucket({slug:n,environment:i,domain:s?`docs.${s}`:void 0});if(h[S.logicalId]=S.bucket,S.bucketPolicy)h[`${S.logicalId}Policy`]=S.bucketPolicy;y.docs=!0}if(u.private.exists){let S=be.createPrivateBucket({slug:n,environment:i,enableVersioning:!0});h[S.logicalId]=S.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:f}=a,S=r({slug:i,environment:s,resourceType:"ecr",suffix:n}),b=t(S),C={Type:"AWS::ECR::Repository",Properties:{RepositoryName:S,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(f)C.Properties.Tags=Object.entries(f).map(([T,v])=>({Key:T,Value:v}));return{repository:C,logicalId:b}}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:f}=a,S=["app","config",...c],b=f||`bun run ${i}`,C=`# Multi-stage build for Bun application
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:f=!1,cors:S,lifecycleRules:b}=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(S&&S.length>0)v.Properties.CorsConfiguration={CorsRules:S.map((R)=>({AllowedOrigins:R.allowedOrigins,AllowedMethods:R.allowedMethods,AllowedHeaders:R.allowedHeaders,MaxAge:R.maxAge}))};if(b&&b.length>0)v.Properties.LifecycleConfiguration={Rules:b.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(f&&b){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:f}=a,S=h||r({slug:i,environment:s,resourceType:"backup-vault",suffix:n}),b=t(S),C={Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:S}},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(f&&f<l)W.MoveToColdStorageAfterDays=f;let P={Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:R,BackupPlanRule:[{RuleName:`${n}-daily-backup`,TargetBackupVault:N.Ref(b),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:b,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}}},f={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:f,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},f=Ee.createBucket({name:"web",slug:n,environment:i,public:!1,versioning:!1,encryption:!0});if(h[f.logicalId]=f.bucket,y.web=!0,u.docs.exists){let S=Ee.createDocsBucket({slug:n,environment:i,domain:s?`docs.${s}`:void 0});if(h[S.logicalId]=S.bucket,S.bucketPolicy)h[`${S.logicalId}Policy`]=S.bucketPolicy;y.docs=!0}if(u.private.exists){let S=Ee.createPrivateBucket({slug:n,environment:i,enableVersioning:!0});h[S.logicalId]=S.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:f}=a,S=r({slug:i,environment:s,resourceType:"ecr",suffix:n}),b=t(S),C={Type:"AWS::ECR::Repository",Properties:{RepositoryName:S,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(f)C.Properties.Tags=Object.entries(f).map(([T,v])=>({Key:T,Value:v}));return{repository:C,logicalId:b}}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:f}=a,S=["app","config",...c],b=f||`bun run ${i}`,C=`# Multi-stage build for Bun application
24
24
  # Generated by ts-cloud
25
25
 
26
26
  # Builder stage
@@ -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 Ee{static createDistribution(a){let{slug:n,environment:i,origin:s,customDomain:c,certificateArn:l,errorPages:u,cachePolicy:h,edgeFunctions:y,http3:f=!1,comment:S}=a,b=r({slug:n,environment:i,resourceType:"cdn"}),C=t(b),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:`${b}-oac`,Description:`Origin Access Control for ${b}`,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:S||`CDN for ${b}`,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:f?"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 Ee.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:f=!1,comment:S}=a,b=r({slug:n,environment:i,resourceType:"cdn"}),C=t(b),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:`${b}-oac`,Description:`Origin Access Control for ${b}`,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:S||`CDN for ${b}`,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:f?"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=`
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=Ee.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)Ee.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:f,customOriginHeaders:S={}}=a,b=r({slug:n,environment:i,resourceType:"cdn-api"}),C=t(b),T=Object.entries(S).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"&&f)w.WhitelistedNames=f;let R={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:`API CDN for ${b}`,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,f=r({slug:n,environment:i,resourceType:"cdn"}),S=t(f),b=`${S}OAC`,C={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${f}-oac`,Description:`Origin Access Control for ${f}`,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(b)},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 ${f}`,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:S,oacLogicalId:b}}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(([S,b])=>({HeaderName:S,HeaderValue:b})),f={Id:i,DomainName:s,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(y.length>0)f.OriginCustomHeaders=y;if(!a.Properties.DistributionConfig.Origins)a.Properties.DistributionConfig.Origins=[];if(a.Properties.DistributionConfig.Origins.push(f),!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:f,customOriginHeaders:S={}}=a,b=r({slug:n,environment:i,resourceType:"cdn-api"}),C=t(b),T=Object.entries(S).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"&&f)w.WhitelistedNames=f;let R={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:`API CDN for ${b}`,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,f=r({slug:n,environment:i,resourceType:"cdn"}),S=t(f),b=`${S}OAC`,C={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${f}-oac`,Description:`Origin Access Control for ${f}`,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(b)},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 ${f}`,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:S,oacLogicalId:b}}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(([S,b])=>({HeaderName:S,HeaderValue:b})),f={Id:i,DomainName:s,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(y.length>0)f.OriginCustomHeaders=y;if(!a.Properties.DistributionConfig.Origins)a.Properties.DistributionConfig.Origins=[];if(a.Properties.DistributionConfig.Origins.push(f),!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:Ee.Config.allowedMethods(c),CachedMethods:Ee.Config.cachedMethods(l),ForwardedValues:{QueryString:h,Headers:y,Cookies:Ee.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=Ee.Config.allowedMethods(n.allowedMethods);if(n.cachedMethods)i.CachedMethods=Ee.Config.cachedMethods(n.cachedMethods);if(n.cookies){if(!i.ForwardedValues)i.ForwardedValues={QueryString:!0};i.ForwardedValues.Cookies=Ee.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}`),f={Type:"AWS::Route53::RecordSet",Properties:{Name:s,Type:c}};if(n)f.Properties.HostedZoneId=n;else if(i)f.Properties.HostedZoneName=i;if(h)f.Properties.AliasTarget={DNSName:h.dnsName,HostedZoneId:h.hostedZoneId,EvaluateTargetHealth:h.evaluateTargetHealth??!1};else f.Properties.TTL=l||300,f.Properties.ResourceRecords=u||[];return{record:f,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,"")}`),f=[n];for(let b of i)if(b==="*")f.push(`*.${n}`);else f.push(`${b}.${n}`);let S={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:n,SubjectAlternativeNames:f,ValidationMethod:l}};if(l==="DNS"&&u)S.Properties.DomainValidationOptions=f.map((b)=>({DomainName:b,HostedZoneId:u}));return{certificate:S,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:"*"}]},f={Type:"AWS::KMS::Key",Properties:{Description:n,Enabled:!0,EnableKeyRotation:c,KeyPolicy:y,KeySpec:"SYMMETRIC_DEFAULT",KeyUsage:"ENCRYPT_DECRYPT",MultiRegion:l}},S=t(`${u}-alias`),b={Type:"AWS::KMS::Alias",Properties:{AliasName:`alias/${i}-${s}`,TargetKeyId:N.Ref(h)}};return{key:f,alias:b,logicalId:h,aliasId:S}}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"}),f=0;if(h=I.addManagedRules(h,{name:"AWSIPReputationList",priority:f++,...I.ManagedRuleGroups.AmazonIpReputation}),h=I.addManagedRules(h,{name:"AWSAnonymousIPList",priority:f++,...I.ManagedRuleGroups.AnonymousIpList}),h=I.addManagedRules(h,{name:"AWSCoreRuleSet",priority:f++,...I.ManagedRuleGroups.CoreRuleSet}),h=I.addManagedRules(h,{name:"AWSKnownBadInputs",priority:f++,...I.ManagedRuleGroups.KnownBadInputs}),h=I.addManagedRules(h,{name:"AWSSQLi",priority:f++,...I.ManagedRuleGroups.SqlDatabase}),c)h=I.addManagedRules(h,{name:"AWSBotControl",priority:f++,...I.ManagedRuleGroups.BotControl});if(l)h=I.setRateLimit(h,{name:"GlobalRateLimit",priority:f++,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:f=20,volumeType:S="gp3",encrypted:b=!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:f,VolumeType:S,Encrypted:b,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),f={Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:c||`Security group for ${n} ${i}`,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:i}]}};if(s)f.Properties.VpcId=s;if(l.length>0)f.Properties.SecurityGroupIngress=l.map((S)=>({IpProtocol:S.protocol,FromPort:S.fromPort,ToPort:S.toPort,CidrIp:S.cidr,SourceSecurityGroupId:S.sourceSecurityGroupId}));if(u.length>0)f.Properties.SecurityGroupEgress=u.map((S)=>({IpProtocol:S.protocol,FromPort:S.fromPort,ToPort:S.toPort,CidrIp:S.cidr,DestinationSecurityGroupId:S.sourceSecurityGroupId}));return{securityGroup:f,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),f={Type:"AWS::ElasticLoadBalancingV2::LoadBalancer",Properties:{Name:h,Scheme:s,Type:u,Subnets:c,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:i}]}};if(l)f.Properties.SecurityGroups=l;return{loadBalancer:f,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:f=5,healthyThreshold:S=2,unhealthyThreshold:b=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:f,HealthyThresholdCount:S,UnhealthyThresholdCount:b,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:f=[],healthCheck:S,logGroup:b,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:f.map((te)=>({Name:te.name,ValueFrom:te.valueFrom}))}],Tags:[{Key:"Name",Value:k},{Key:"Environment",Value:i}]}};if(S)J.Properties.ContainerDefinitions[0].HealthCheck={Command:S.command,Interval:S.interval||30,Timeout:S.timeout||5,Retries:S.retries||3,StartPeriod:60};if(b)J.Properties.ContainerDefinitions[0].LogConfiguration={LogDriver:"awslogs",Options:{"awslogs-group":b,"awslogs-region":N.Ref("AWS::Region"),"awslogs-stream-prefix":n}};let K=t(`${k}-service`),ee={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)ee.Properties.LoadBalancers=[{TargetGroupArn:v,ContainerName:n,ContainerPort:h}];return{cluster:w,taskDefinition:J,service:ee,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:f}=a,S=r({slug:n,environment:i,resourceType:"lambda"}),b=t(S),C=t(`${S}-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(f)T.Properties.ManagedPolicyArns.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");let v={Type:"AWS::Lambda::Function",Properties:{FunctionName:S,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:S},{Key:"Environment",Value:i}]}};if(Object.keys(y).length>0)v.Properties.Environment={Variables:y};if(f)v.Properties.VpcConfig={SecurityGroupIds:f.securityGroupIds,SubnetIds:f.subnetIds};return{lambdaFunction:v,role:T,logicalId:b,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}`),f={Type:"AWS::Route53::RecordSet",Properties:{Name:s,Type:c}};if(n)f.Properties.HostedZoneId=n;else if(i)f.Properties.HostedZoneName=i;if(h)f.Properties.AliasTarget={DNSName:h.dnsName,HostedZoneId:h.hostedZoneId,EvaluateTargetHealth:h.evaluateTargetHealth??!1};else f.Properties.TTL=l||300,f.Properties.ResourceRecords=u||[];return{record:f,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,"")}`),f=[n];for(let b of i)if(b==="*")f.push(`*.${n}`);else f.push(`${b}.${n}`);let S={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:n,SubjectAlternativeNames:f,ValidationMethod:l}};if(l==="DNS"&&u)S.Properties.DomainValidationOptions=f.map((b)=>({DomainName:b,HostedZoneId:u}));return{certificate:S,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:"*"}]},f={Type:"AWS::KMS::Key",Properties:{Description:n,Enabled:!0,EnableKeyRotation:c,KeyPolicy:y,KeySpec:"SYMMETRIC_DEFAULT",KeyUsage:"ENCRYPT_DECRYPT",MultiRegion:l}},S=t(`${u}-alias`),b={Type:"AWS::KMS::Alias",Properties:{AliasName:`alias/${i}-${s}`,TargetKeyId:N.Ref(h)}};return{key:f,alias:b,logicalId:h,aliasId:S}}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"}),f=0;if(h=I.addManagedRules(h,{name:"AWSIPReputationList",priority:f++,...I.ManagedRuleGroups.AmazonIpReputation}),h=I.addManagedRules(h,{name:"AWSAnonymousIPList",priority:f++,...I.ManagedRuleGroups.AnonymousIpList}),h=I.addManagedRules(h,{name:"AWSCoreRuleSet",priority:f++,...I.ManagedRuleGroups.CoreRuleSet}),h=I.addManagedRules(h,{name:"AWSKnownBadInputs",priority:f++,...I.ManagedRuleGroups.KnownBadInputs}),h=I.addManagedRules(h,{name:"AWSSQLi",priority:f++,...I.ManagedRuleGroups.SqlDatabase}),c)h=I.addManagedRules(h,{name:"AWSBotControl",priority:f++,...I.ManagedRuleGroups.BotControl});if(l)h=I.setRateLimit(h,{name:"GlobalRateLimit",priority:f++,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:f=20,volumeType:S="gp3",encrypted:b=!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:f,VolumeType:S,Encrypted:b,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),f={Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:c||`Security group for ${n} ${i}`,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:i}]}};if(s)f.Properties.VpcId=s;if(l.length>0)f.Properties.SecurityGroupIngress=l.map((S)=>({IpProtocol:S.protocol,FromPort:S.fromPort,ToPort:S.toPort,CidrIp:S.cidr,SourceSecurityGroupId:S.sourceSecurityGroupId}));if(u.length>0)f.Properties.SecurityGroupEgress=u.map((S)=>({IpProtocol:S.protocol,FromPort:S.fromPort,ToPort:S.toPort,CidrIp:S.cidr,DestinationSecurityGroupId:S.sourceSecurityGroupId}));return{securityGroup:f,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),f={Type:"AWS::ElasticLoadBalancingV2::LoadBalancer",Properties:{Name:h,Scheme:s,Type:u,Subnets:c,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:i}]}};if(l)f.Properties.SecurityGroups=l;return{loadBalancer:f,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:f=5,healthyThreshold:S=2,unhealthyThreshold:b=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:f,HealthyThresholdCount:S,UnhealthyThresholdCount:b,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:f=[],healthCheck:S,logGroup:b,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:f.map((te)=>({Name:te.name,ValueFrom:te.valueFrom}))}],Tags:[{Key:"Name",Value:k},{Key:"Environment",Value:i}]}};if(S)J.Properties.ContainerDefinitions[0].HealthCheck={Command:S.command,Interval:S.interval||30,Timeout:S.timeout||5,Retries:S.retries||3,StartPeriod:60};if(b)J.Properties.ContainerDefinitions[0].LogConfiguration={LogDriver:"awslogs",Options:{"awslogs-group":b,"awslogs-region":N.Ref("AWS::Region"),"awslogs-stream-prefix":n}};let K=t(`${k}-service`),ee={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)ee.Properties.LoadBalancers=[{TargetGroupArn:v,ContainerName:n,ContainerPort:h}];return{cluster:w,taskDefinition:J,service:ee,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:f}=a,S=r({slug:n,environment:i,resourceType:"lambda"}),b=t(S),C=t(`${S}-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(f)T.Properties.ManagedPolicyArns.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");let v={Type:"AWS::Lambda::Function",Properties:{FunctionName:S,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:S},{Key:"Environment",Value:i}]}};if(Object.keys(y).length>0)v.Properties.Environment={Variables:y};if(f)v.Properties.VpcConfig={SecurityGroupIds:f.securityGroupIds,SubnetIds:f.subnetIds};return{lambdaFunction:v,role:T,logicalId:b,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(`
213
213
  `);return`#!/bin/bash
214
214
  # Update system
215
215
  yum update -y
@@ -2306,7 +2306,7 @@ 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 ud{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,f]of Object.entries(a.users)){if(!/^[a-zA-Z0-9_.@-]{3,100}$/.test(y))throw Error(`sftp: invalid username ${y}`);if(!f.sshPublicKeys.length)throw Error(`sftp: user ${y} requires at least one SSH public key`);let S=wt(y),b=gr(f.homeDirectory,y),C=`${c}${S}User`,T=f.roleArn;if(!T){let v=`${c}${S}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":[b,`${b}/*`]}}},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:GetObjectVersion"],Resource:`${R}/${b}/*`}]}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,b):`/${n.bucket}/${b}`,...n.type==="efs"?{PosixProfile:yr(y,f,n.posixProfile)}:{},SshPublicKeys:f.sshPublicKeys}}}return{resources:u,serverLogicalId:l,domain:i}}}class ve{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),f=["bedrock:InvokeModel"];if(u)f.push("bedrock:InvokeModelWithResponseStream");let S=l.map((b)=>b==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${b}`);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:f,Resource:S}]}}],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"}),f=t(y),S=[];if(l)S.push("bedrock:InvokeModel");if(u)S.push("bedrock:InvokeModelWithResponseStream");if(h)S.push("bedrock:InvokeModelAsync");let b=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:S,Resource:b}]}}},logicalId:f}}static enableBedrockForLambda(a){return ve.createBedrockRole("lambda.amazonaws.com",a)}static enableBedrockForEcs(a){return ve.createBedrockRole("ecs-tasks.amazonaws.com",a)}static enableBedrockForEc2(a){return ve.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:f,databaseName:S,subnetIds:b,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(b&&b.length>0){let ee=r({slug:s,environment:c,resourceType:"db-subnet-group"});J=t(ee),j={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupName:ee,DBSubnetGroupDescription:`Subnet group for ${V}`,SubnetIds:b,Tags:[{Key:"Name",Value:ee},{Key:"Environment",Value:c}]}}}let K={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:V,DBInstanceClass:l,Engine:a,EngineVersion:n,MasterUsername:y,MasterUserPassword:f,AllocatedStorage:u,StorageType:h,StorageEncrypted:T,MultiAZ:w,BackupRetentionPeriod:R,PubliclyAccessible:k,DeletionProtection:P,Tags:[{Key:"Name",Value:V},{Key:"Environment",Value:c}]}};if(S)K.Properties.DBName=S;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),f={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)f.Properties.VPCSecurityGroups=l;return{replica:f,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:f=!1,streamViewType:S="NEW_AND_OLD_IMAGES",encrypted:b=!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(f)P.Properties.StreamSpecification={StreamViewType:S};if(b)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((b)=>b.AttributeName===s.name))a.Properties.AttributeDefinitions.push({AttributeName:s.name,AttributeType:s.type});if(c&&!a.Properties.AttributeDefinitions.some((b)=>b.AttributeName===c.name))a.Properties.AttributeDefinitions.push({AttributeName:c.name,AttributeType:c.type});let f=[{AttributeName:s.name,KeyType:"HASH"}];if(c)f.push({AttributeName:c.name,KeyType:"RANGE"});let S={IndexName:i,KeySchema:f,Projection:{ProjectionType:l,NonKeyAttributes:l==="INCLUDE"?u:void 0},ProvisionedThroughput:void 0};if(a.Properties.BillingMode==="PROVISIONED")S.ProvisionedThroughput={ReadCapacityUnits:h,WriteCapacityUnits:y};if(!a.Properties.GlobalSecondaryIndexes)a.Properties.GlobalSecondaryIndexes=[];return a.Properties.GlobalSecondaryIndexes.push(S),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 Xs{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:f=!0,multiAz:S=!0,clusterMode:b=!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 ee={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:B,ReplicationGroupDescription:`Redis cluster for ${n} ${i}`,Engine:"redis",EngineVersion:c,CacheNodeType:s,Port:l,AutomaticFailoverEnabled:f,MultiAZEnabled:S,AtRestEncryptionEnabled:v,TransitEncryptionEnabled:w,SnapshotRetentionLimit:W,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:B},{Key:"Environment",Value:i}]}};if(b)ee.Properties.NumNodeGroups=C,ee.Properties.ReplicasPerNodeGroup=T;else ee.Properties.NumCacheClusters=y;if(R)ee.Properties.AuthToken=R;if(k)ee.Properties.KmsKeyId=k;if(K)ee.Properties.CacheSubnetGroupName=N.Ref(K);if(h&&h.length>0)ee.Properties.SecurityGroupIds=h;if(P)ee.Properties.SnapshotWindow=P;if(V)ee.Properties.PreferredMaintenanceWindow=V;return{replicationGroup:ee,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:f="cross-az",preferredAzs:S,maintenanceWindow:b}=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:f,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(S&&S.length>0)R.Properties.PreferredAvailabilityZones=S;if(b)R.Properties.PreferredMaintenanceWindow=b;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 X{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),f={};if(c)f.Service=c;if(l)f.AWS=l;let S={Type:"AWS::IAM::Role",Properties:{RoleName:h,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:f,Action:"sts:AssumeRole"}]},Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:i}]}};if(u&&u.length>0)S.Properties.ManagedPolicyArns=u;return{role:S,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((f)=>({Sid:f.sid,Effect:f.effect||"Allow",Action:f.actions,Resource:f.resources,Condition:f.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}=X.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:f,logicalId:S}=X.createUser({slug:n,environment:i,userName:r({slug:n,environment:i,resourceType:"cicd-user"}),managedPolicyArns:[N.Ref(y)]});l[S]=f;let b,C;if(c){let T=X.createAccessKey(S,{slug:n,environment:i});b=T.accessKey,C=T.logicalId,l[C]=b}return{user:f,accessKey:b,policy:h,userLogicalId:S,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:f}=X.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[f]=y;let S=r({slug:n,environment:i,resourceType:"cross-account-role"}),b=t(S),C={};if(c)C.StringEquals={"sts:ExternalId":c};let T={Type:"AWS::IAM::Role",Properties:{RoleName:S,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(f)],Tags:[{Key:"Name",Value:S},{Key:"Environment",Value:i},{Key:"Purpose",Value:"Cross-Account Access"}]}};return h[b]=T,{role:T,policy:y,roleLogicalId:b,policyLogicalId:f,resources:h}}static createCliUser(a){let{slug:n,environment:i,permissions:s="readonly"}=a,c={},l=[],u=[];switch(s){case"readonly":u=[X.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=[X.ManagedPolicies.AdministratorAccess];break}let h,y;if(l.length>0){let T=X.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:f,logicalId:S}=X.createUser({slug:n,environment:i,userName:r({slug:n,environment:i,resourceType:"cli-user"}),managedPolicyArns:u});c[S]=f;let{accessKey:b,logicalId:C}=X.createAccessKey(S,{slug:n,environment:i});return c[C]=b,{user:f,accessKey:b,policy:h,userLogicalId:S,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 pd{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"}),f=t(y),S={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)S.Properties.BinaryMediaTypes=u;if(h!==void 0)S.Properties.MinimumCompressionSize=h;return{restApi:S,logicalId:f}}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:f=86400,corsAllowCredentials:S=!1}=a,b=s||r({slug:n,environment:i,resourceType:"http-api"}),C=t(b),T={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:b,Description:c||`HTTP API for ${n} ${i}`,ProtocolType:"HTTP",Tags:{Name:b,Environment:i}}};if(l)T.Properties.CorsConfiguration={AllowOrigins:u,AllowMethods:h,AllowHeaders:y,MaxAge:f,AllowCredentials:S};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:f,throttling:S}=i,b=r({slug:s,environment:c,resourceType:"api-stage"}),C=t(b),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:b},{Key:"Environment",Value:c}]}};if(h)T.Properties.CacheClusterSize=y;if(f)T.Properties.Variables=f;if(S)T.Properties.MethodSettings=[{HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:S.burstLimit,ThrottlingRateLimit:S.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:f=300}=n,S=c||r({slug:i,environment:s,resourceType:"api-authorizer"}),b=t(S),C={Type:"AWS::ApiGateway::Authorizer",Properties:{Name:S,Type:l,RestApiId:N.Ref(a),AuthorizerResultTtlInSeconds:f}};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:b}}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 Y{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),f={Type:"AWS::SNS::Topic",Properties:{TopicName:h,DisplayName:c||h,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:i}]}};if(l&&u)f.Properties.KmsMasterKeyId=u;return{topic:f,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"}),f=l.replace(/[^a-zA-Z0-9]/g,""),S=f.length>12?f.slice(-12):f,b=t(`${y}-${c}-${S}`),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:b}}static subscribeEmail(a,n,i){return Y.subscribe(a,{...i,protocol:"email",endpoint:n})}static subscribeLambda(a,n,i){return Y.subscribe(a,{...i,protocol:"lambda",endpoint:n,rawMessageDelivery:!0})}static subscribeSqs(a,n,i){return Y.subscribe(a,{...i,protocol:"sqs",endpoint:n})}static subscribeHttp(a,n,i){let s=n.startsWith("https://")?"https":"http";return Y.subscribe(a,{...i,protocol:s,endpoint:n})}static subscribeSms(a,n,i){return Y.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),f={};if(c)f.AWS=c;if(l)f.Service=l;return{policy:{Type:"AWS::SNS::TopicPolicy",Properties:{Topics:[N.Ref(a)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:f,Action:u,Resource:N.Ref(a)}]}}},logicalId:y}}static allowCloudWatchAlarms(a,n){return Y.setTopicPolicy(a,{...n,allowedServices:"cloudwatch.amazonaws.com",actions:"SNS:Publish"})}static allowEventBridge(a,n){return Y.setTopicPolicy(a,{...n,allowedServices:"events.amazonaws.com",actions:"SNS:Publish"})}static allowS3(a,n){return Y.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)=>Y.createTopic({...a,topicName:a.topicName||`${a.slug}-${a.environment}-alerts`,displayName:a.displayName||"Alert Notifications"}),createEventFanout:(a)=>Y.createTopic({...a,topicName:a.topicName||`${a.slug}-${a.environment}-events`,displayName:a.displayName||"Event Fanout"}),createNotificationTopic:(a)=>Y.createTopic({...a,topicName:a.topicName||`${a.slug}-${a.environment}-notifications`,displayName:a.displayName||"User Notifications"})}}class Af{static createStateMachine(a){let{slug:n,environment:i,stateMachineName:s,type:c="STANDARD",definition:l,roleArn:u,loggingConfiguration:h,tracingConfiguration:y}=a,f=s||r({slug:n,environment:i,resourceType:"state-machine"}),S=t(f),b,C,T;if(u)T=u;else{let w=r({slug:n,environment:i,resourceType:"state-machine-role"});C=t(w),b={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:f,StateMachineType:c,DefinitionString:JSON.stringify(l),RoleArn:T,Tags:[{Key:"Name",Value:f},{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:S,role:b,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 Ys{static createAlarm(a){let{slug:n,environment:i,alarmName:s,metricName:c,namespace:l,statistic:u="Average",period:h=300,evaluationPeriods:y=1,threshold:f,comparisonOperator:S,treatMissingData:b="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:f,ComparisonOperator:S,TreatMissingData:b,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,f=s||r({slug:n,environment:i,resourceType:"composite-alarm"}),S=t(f),b={Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:f,AlarmRule:c,ActionsEnabled:l}};if(u&&u.length>0)b.Properties.AlarmActions=u;if(h&&h.length>0)b.Properties.OKActions=h;if(y&&y.length>0)b.Properties.InsufficientDataActions=y;return{alarm:b,logicalId:S}}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((f)=>({MetricName:f.metricName,MetricNamespace:f.metricNamespace,MetricValue:f.metricValue,DefaultValue:f.defaultValue,Unit:f.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 ud{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,f]of Object.entries(a.users)){if(!/^[a-zA-Z0-9_.@-]{3,100}$/.test(y))throw Error(`sftp: invalid username ${y}`);if(!f.sshPublicKeys.length)throw Error(`sftp: user ${y} requires at least one SSH public key`);let S=wt(y),b=gr(f.homeDirectory,y),C=`${c}${S}User`,T=f.roleArn;if(!T){let v=`${c}${S}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":[b,`${b}/*`]}}},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:GetObjectVersion"],Resource:`${R}/${b}/*`}]}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,b):`/${n.bucket}/${b}`,...n.type==="efs"?{PosixProfile:yr(y,f,n.posixProfile)}:{},SshPublicKeys:f.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),f=["bedrock:InvokeModel"];if(u)f.push("bedrock:InvokeModelWithResponseStream");let S=l.map((b)=>b==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${b}`);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:f,Resource:S}]}}],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"}),f=t(y),S=[];if(l)S.push("bedrock:InvokeModel");if(u)S.push("bedrock:InvokeModelWithResponseStream");if(h)S.push("bedrock:InvokeModelAsync");let b=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:S,Resource:b}]}}},logicalId:f}}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:f,databaseName:S,subnetIds:b,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(b&&b.length>0){let ee=r({slug:s,environment:c,resourceType:"db-subnet-group"});J=t(ee),j={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupName:ee,DBSubnetGroupDescription:`Subnet group for ${V}`,SubnetIds:b,Tags:[{Key:"Name",Value:ee},{Key:"Environment",Value:c}]}}}let K={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:V,DBInstanceClass:l,Engine:a,EngineVersion:n,MasterUsername:y,MasterUserPassword:f,AllocatedStorage:u,StorageType:h,StorageEncrypted:T,MultiAZ:w,BackupRetentionPeriod:R,PubliclyAccessible:k,DeletionProtection:P,Tags:[{Key:"Name",Value:V},{Key:"Environment",Value:c}]}};if(S)K.Properties.DBName=S;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),f={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)f.Properties.VPCSecurityGroups=l;return{replica:f,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:f=!1,streamViewType:S="NEW_AND_OLD_IMAGES",encrypted:b=!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(f)P.Properties.StreamSpecification={StreamViewType:S};if(b)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((b)=>b.AttributeName===s.name))a.Properties.AttributeDefinitions.push({AttributeName:s.name,AttributeType:s.type});if(c&&!a.Properties.AttributeDefinitions.some((b)=>b.AttributeName===c.name))a.Properties.AttributeDefinitions.push({AttributeName:c.name,AttributeType:c.type});let f=[{AttributeName:s.name,KeyType:"HASH"}];if(c)f.push({AttributeName:c.name,KeyType:"RANGE"});let S={IndexName:i,KeySchema:f,Projection:{ProjectionType:l,NonKeyAttributes:l==="INCLUDE"?u:void 0},ProvisionedThroughput:void 0};if(a.Properties.BillingMode==="PROVISIONED")S.ProvisionedThroughput={ReadCapacityUnits:h,WriteCapacityUnits:y};if(!a.Properties.GlobalSecondaryIndexes)a.Properties.GlobalSecondaryIndexes=[];return a.Properties.GlobalSecondaryIndexes.push(S),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 Xs{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:f=!0,multiAz:S=!0,clusterMode:b=!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 ee={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:B,ReplicationGroupDescription:`Redis cluster for ${n} ${i}`,Engine:"redis",EngineVersion:c,CacheNodeType:s,Port:l,AutomaticFailoverEnabled:f,MultiAZEnabled:S,AtRestEncryptionEnabled:v,TransitEncryptionEnabled:w,SnapshotRetentionLimit:W,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:B},{Key:"Environment",Value:i}]}};if(b)ee.Properties.NumNodeGroups=C,ee.Properties.ReplicasPerNodeGroup=T;else ee.Properties.NumCacheClusters=y;if(R)ee.Properties.AuthToken=R;if(k)ee.Properties.KmsKeyId=k;if(K)ee.Properties.CacheSubnetGroupName=N.Ref(K);if(h&&h.length>0)ee.Properties.SecurityGroupIds=h;if(P)ee.Properties.SnapshotWindow=P;if(V)ee.Properties.PreferredMaintenanceWindow=V;return{replicationGroup:ee,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:f="cross-az",preferredAzs:S,maintenanceWindow:b}=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:f,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(S&&S.length>0)R.Properties.PreferredAvailabilityZones=S;if(b)R.Properties.PreferredMaintenanceWindow=b;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 X{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),f={};if(c)f.Service=c;if(l)f.AWS=l;let S={Type:"AWS::IAM::Role",Properties:{RoleName:h,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:f,Action:"sts:AssumeRole"}]},Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:i}]}};if(u&&u.length>0)S.Properties.ManagedPolicyArns=u;return{role:S,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((f)=>({Sid:f.sid,Effect:f.effect||"Allow",Action:f.actions,Resource:f.resources,Condition:f.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}=X.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:f,logicalId:S}=X.createUser({slug:n,environment:i,userName:r({slug:n,environment:i,resourceType:"cicd-user"}),managedPolicyArns:[N.Ref(y)]});l[S]=f;let b,C;if(c){let T=X.createAccessKey(S,{slug:n,environment:i});b=T.accessKey,C=T.logicalId,l[C]=b}return{user:f,accessKey:b,policy:h,userLogicalId:S,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:f}=X.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[f]=y;let S=r({slug:n,environment:i,resourceType:"cross-account-role"}),b=t(S),C={};if(c)C.StringEquals={"sts:ExternalId":c};let T={Type:"AWS::IAM::Role",Properties:{RoleName:S,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(f)],Tags:[{Key:"Name",Value:S},{Key:"Environment",Value:i},{Key:"Purpose",Value:"Cross-Account Access"}]}};return h[b]=T,{role:T,policy:y,roleLogicalId:b,policyLogicalId:f,resources:h}}static createCliUser(a){let{slug:n,environment:i,permissions:s="readonly"}=a,c={},l=[],u=[];switch(s){case"readonly":u=[X.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=[X.ManagedPolicies.AdministratorAccess];break}let h,y;if(l.length>0){let T=X.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:f,logicalId:S}=X.createUser({slug:n,environment:i,userName:r({slug:n,environment:i,resourceType:"cli-user"}),managedPolicyArns:u});c[S]=f;let{accessKey:b,logicalId:C}=X.createAccessKey(S,{slug:n,environment:i});return c[C]=b,{user:f,accessKey:b,policy:h,userLogicalId:S,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 pd{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"}),f=t(y),S={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)S.Properties.BinaryMediaTypes=u;if(h!==void 0)S.Properties.MinimumCompressionSize=h;return{restApi:S,logicalId:f}}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:f=86400,corsAllowCredentials:S=!1}=a,b=s||r({slug:n,environment:i,resourceType:"http-api"}),C=t(b),T={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:b,Description:c||`HTTP API for ${n} ${i}`,ProtocolType:"HTTP",Tags:{Name:b,Environment:i}}};if(l)T.Properties.CorsConfiguration={AllowOrigins:u,AllowMethods:h,AllowHeaders:y,MaxAge:f,AllowCredentials:S};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:f,throttling:S}=i,b=r({slug:s,environment:c,resourceType:"api-stage"}),C=t(b),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:b},{Key:"Environment",Value:c}]}};if(h)T.Properties.CacheClusterSize=y;if(f)T.Properties.Variables=f;if(S)T.Properties.MethodSettings=[{HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:S.burstLimit,ThrottlingRateLimit:S.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:f=300}=n,S=c||r({slug:i,environment:s,resourceType:"api-authorizer"}),b=t(S),C={Type:"AWS::ApiGateway::Authorizer",Properties:{Name:S,Type:l,RestApiId:N.Ref(a),AuthorizerResultTtlInSeconds:f}};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:b}}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 Y{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),f={Type:"AWS::SNS::Topic",Properties:{TopicName:h,DisplayName:c||h,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:i}]}};if(l&&u)f.Properties.KmsMasterKeyId=u;return{topic:f,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"}),f=l.replace(/[^a-zA-Z0-9]/g,""),S=f.length>12?f.slice(-12):f,b=t(`${y}-${c}-${S}`),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:b}}static subscribeEmail(a,n,i){return Y.subscribe(a,{...i,protocol:"email",endpoint:n})}static subscribeLambda(a,n,i){return Y.subscribe(a,{...i,protocol:"lambda",endpoint:n,rawMessageDelivery:!0})}static subscribeSqs(a,n,i){return Y.subscribe(a,{...i,protocol:"sqs",endpoint:n})}static subscribeHttp(a,n,i){let s=n.startsWith("https://")?"https":"http";return Y.subscribe(a,{...i,protocol:s,endpoint:n})}static subscribeSms(a,n,i){return Y.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),f={};if(c)f.AWS=c;if(l)f.Service=l;return{policy:{Type:"AWS::SNS::TopicPolicy",Properties:{Topics:[N.Ref(a)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:f,Action:u,Resource:N.Ref(a)}]}}},logicalId:y}}static allowCloudWatchAlarms(a,n){return Y.setTopicPolicy(a,{...n,allowedServices:"cloudwatch.amazonaws.com",actions:"SNS:Publish"})}static allowEventBridge(a,n){return Y.setTopicPolicy(a,{...n,allowedServices:"events.amazonaws.com",actions:"SNS:Publish"})}static allowS3(a,n){return Y.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)=>Y.createTopic({...a,topicName:a.topicName||`${a.slug}-${a.environment}-alerts`,displayName:a.displayName||"Alert Notifications"}),createEventFanout:(a)=>Y.createTopic({...a,topicName:a.topicName||`${a.slug}-${a.environment}-events`,displayName:a.displayName||"Event Fanout"}),createNotificationTopic:(a)=>Y.createTopic({...a,topicName:a.topicName||`${a.slug}-${a.environment}-notifications`,displayName:a.displayName||"User Notifications"})}}class Af{static createStateMachine(a){let{slug:n,environment:i,stateMachineName:s,type:c="STANDARD",definition:l,roleArn:u,loggingConfiguration:h,tracingConfiguration:y}=a,f=s||r({slug:n,environment:i,resourceType:"state-machine"}),S=t(f),b,C,T;if(u)T=u;else{let w=r({slug:n,environment:i,resourceType:"state-machine-role"});C=t(w),b={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:f,StateMachineType:c,DefinitionString:JSON.stringify(l),RoleArn:T,Tags:[{Key:"Name",Value:f},{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:S,role:b,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 Ys{static createAlarm(a){let{slug:n,environment:i,alarmName:s,metricName:c,namespace:l,statistic:u="Average",period:h=300,evaluationPeriods:y=1,threshold:f,comparisonOperator:S,treatMissingData:b="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:f,ComparisonOperator:S,TreatMissingData:b,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,f=s||r({slug:n,environment:i,resourceType:"composite-alarm"}),S=t(f),b={Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:f,AlarmRule:c,ActionsEnabled:l}};if(u&&u.length>0)b.Properties.AlarmActions=u;if(h&&h.length>0)b.Properties.OKActions=h;if(y&&y.length>0)b.Properties.InsufficientDataActions=y;return{alarm:b,logicalId:S}}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((f)=>({MetricName:f.metricName,MetricNamespace:f.metricNamespace,MetricValue:f.metricValue,DefaultValue:f.defaultValue,Unit:f.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 '")}'
@@ -2761,8 +2761,8 @@ ${n.map((i)=>` • ${i}`).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 zf{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 Kf{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
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 fS(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?"✓":"✗",f=l.command;if(f.length>i-30)f=f.substring(0,i-33)+"...";let S=`${u} ${h} ${y} ${f}`;if(l.duration)S+=` (${l.duration}ms)`;s.push(S)}return s.join(`
2763
2763
  `)}function AS(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 Jp{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 yS=new Jp;class Xp{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 Yp{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 Zp{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 eg{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 IS=new Xp,SS=new Yp,CS=new Zp,bS=new eg,Te=[{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 yi(a){return Te.find((n)=>n.code===a)}function ES(){return Te}function vS(a){let n=a.toLowerCase();return Te.filter((i)=>i.location.toLowerCase().includes(n))}function TS(a){return Te.filter((n)=>n.compliance.includes(a))}function wS(a){return Te.filter((n)=>n.pricing.tier===a)}function RS(a){return Te.some((n)=>n.code===a)}function DS(a){if(a.continent==="North America")return yi("us-east-1");if(a.continent==="Europe")return yi("eu-west-1");if(a.continent==="Asia")return yi("ap-southeast-1");return yi("us-east-1")}function PS(a){let n=[...Te];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 NS(a){let n=yi(a);if(!n)throw Error(`Invalid region: ${a}`);let i=[];for(let s of Te){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 Wf(a){return`${a.name} (${a.code})`}function kS(a){return a.map((n)=>Wf(n)).join(`
2765
- `)}function BS(){let a={total:Te.length,byContinent:{},byPricingTier:{}};for(let n of Te){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 tg{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 rg{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 xS=new tg,_S=new rg,Jf={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"}]}},OS={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"]}}}]}}},LS={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 $S(a){return Jf[a]}function MS(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 FS(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,f)=>c.indexOf(y)!==f);if(l.length>0)n.push(`Duplicate email addresses: ${l.join(", ")}`);let u=a.accounts.map((y)=>y.alias),h=u.filter((y,f)=>u.indexOf(y)!==f);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 US(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(`
2764
+ `)}class Jp{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 yS=new Jp;class Xp{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 Yp{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 Zp{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 eg{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 IS=new Xp,SS=new Yp,CS=new Zp,bS=new eg,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 yi(a){return we.find((n)=>n.code===a)}function ES(){return we}function vS(a){let n=a.toLowerCase();return we.filter((i)=>i.location.toLowerCase().includes(n))}function TS(a){return we.filter((n)=>n.compliance.includes(a))}function wS(a){return we.filter((n)=>n.pricing.tier===a)}function RS(a){return we.some((n)=>n.code===a)}function DS(a){if(a.continent==="North America")return yi("us-east-1");if(a.continent==="Europe")return yi("eu-west-1");if(a.continent==="Asia")return yi("ap-southeast-1");return yi("us-east-1")}function PS(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 NS(a){let n=yi(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 Wf(a){return`${a.name} (${a.code})`}function kS(a){return a.map((n)=>Wf(n)).join(`
2765
+ `)}function BS(){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 tg{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 rg{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 xS=new tg,_S=new rg,Jf={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"}]}},OS={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"]}}}]}}},LS={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 $S(a){return Jf[a]}function MS(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 FS(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,f)=>c.indexOf(y)!==f);if(l.length>0)n.push(`Duplicate email addresses: ${l.join(", ")}`);let u=a.accounts.map((y)=>y.alias),h=u.filter((y,f)=>u.indexOf(y)!==f);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 US(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
2766
  `)}function QS(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:f="bun test",buildCommand:S="bun run build"}=a,b=!!u;return`name: ${n}
2767
2767
 
2768
2768
  on:
@@ -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 eA={};Be(eA,{AbTesting:()=>we,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 eA={};Be(eA,{AbTesting:()=>Ce,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 we{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 Ce{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:we.AbTestManagerCode},Environment:{Variables:{AB_TESTS_TABLE:a.abTestsTable}}}}}}static selectVariant(a,n){let i=we.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=we.getMetricValue(i,n);for(let c of a.variants.slice(1)){let l=we.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=we.getMetricValue(a,i)/100,u=we.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 f=Math.abs(l-u)/y;if(f>=2.576)return 99;if(f>=1.96)return 95;if(f>=1.645)return 90;if(f>=1.28)return 80;return Math.round(f*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 Fg{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 QC=new Fg;class Ug{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((S)=>S.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((S,b)=>S+b.messagesReceived,0),u=s.reduce((S,b)=>S+b.messagesDeleted,0),h=s.reduce((S,b)=>S+b.messagesReprocessed,0),y=s.reduce((S,b)=>S+b.approximateAgeOfOldestMessage,0)/s.length,f=h>0?u/h*100:0;return{totalMessages:c.approximateNumberOfMessages,avgAge:y,messagesReceived:l,messagesDeleted:u,messagesReprocessed:h,successRate:f}}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 HC=new Ug;class Qg{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((S)=>S.status==="success").map((S)=>S.processingTime||0).filter((S)=>S>0),c=s.length>0?s.reduce((S,b)=>S+b,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},f=this.metrics.get(a)||[];f.push(y),this.metrics.set(a,f)}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 GC=new Qg;class Hg{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 qC=new Hg,_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 Ii(a){let n=[],i=[],s=0;for(let u of a){let h=Gn(u.data),y=Bn(h),f=Wn(h),S=Buffer.from(u.name.replace(/\\/g,"/"),"utf-8"),{time:b,date:C}=Un(u.date??new Date(0)),T=u.mode??420,v=Buffer.alloc(30+S.length);v.writeUInt32LE(67324752,0),v.writeUInt16LE(20,4),v.writeUInt16LE(0,6),v.writeUInt16LE(8,8),v.writeUInt16LE(b,10),v.writeUInt16LE(C,12),v.writeUInt32LE(f,14),v.writeUInt32LE(y.length,18),v.writeUInt32LE(h.length,22),v.writeUInt16LE(S.length,26),v.writeUInt16LE(0,28),S.copy(v,30);let w=Buffer.alloc(46+S.length);w.writeUInt32LE(33639248,0),w.writeUInt16LE(798,4),w.writeUInt16LE(20,6),w.writeUInt16LE(0,8),w.writeUInt16LE(8,10),w.writeUInt16LE(b,12),w.writeUInt16LE(C,14),w.writeUInt32LE(f,16),w.writeUInt32LE(y.length,20),w.writeUInt32LE(h.length,24),w.writeUInt16LE(S.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),S.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 tA(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: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 f=Math.abs(l-u)/y;if(f>=2.576)return 99;if(f>=1.96)return 95;if(f>=1.645)return 90;if(f>=1.28)return 80;return Math.round(f*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 Fg{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 QC=new Fg;class Ug{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((S)=>S.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((S,b)=>S+b.messagesReceived,0),u=s.reduce((S,b)=>S+b.messagesDeleted,0),h=s.reduce((S,b)=>S+b.messagesReprocessed,0),y=s.reduce((S,b)=>S+b.approximateAgeOfOldestMessage,0)/s.length,f=h>0?u/h*100:0;return{totalMessages:c.approximateNumberOfMessages,avgAge:y,messagesReceived:l,messagesDeleted:u,messagesReprocessed:h,successRate:f}}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 HC=new Ug;class Qg{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((S)=>S.status==="success").map((S)=>S.processingTime||0).filter((S)=>S>0),c=s.length>0?s.reduce((S,b)=>S+b,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},f=this.metrics.get(a)||[];f.push(y),this.metrics.set(a,f)}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 GC=new Qg;class Hg{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 qC=new Hg,_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 Ii(a){let n=[],i=[],s=0;for(let u of a){let h=Gn(u.data),y=Bn(h),f=Wn(h),S=Buffer.from(u.name.replace(/\\/g,"/"),"utf-8"),{time:b,date:C}=Un(u.date??new Date(0)),T=u.mode??420,v=Buffer.alloc(30+S.length);v.writeUInt32LE(67324752,0),v.writeUInt16LE(20,4),v.writeUInt16LE(0,6),v.writeUInt16LE(8,8),v.writeUInt16LE(b,10),v.writeUInt16LE(C,12),v.writeUInt32LE(f,14),v.writeUInt32LE(y.length,18),v.writeUInt32LE(h.length,22),v.writeUInt16LE(S.length,26),v.writeUInt16LE(0,28),S.copy(v,30);let w=Buffer.alloc(46+S.length);w.writeUInt32LE(33639248,0),w.writeUInt16LE(798,4),w.writeUInt16LE(20,6),w.writeUInt16LE(0,8),w.writeUInt16LE(8,10),w.writeUInt16LE(b,12),w.writeUInt16LE(C,14),w.writeUInt32LE(f,16),w.writeUInt32LE(y.length,20),w.writeUInt32LE(h.length,24),w.writeUInt16LE(S.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),S.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 tA(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
 
@@ -7273,7 +7273,7 @@ export const queue = __handlers.queue
7273
7273
  export const cli = __handlers.cli
7274
7274
  `}var Xn=["adapter.ts","recursion.ts","auto-recursion.ts"];function ei(){return Le(Qn(Zn(import.meta.url)),"runtime")}function rA(a,n,i){for(let s of a??[])i?.(`build: ${s}`),Fn(s,{stdio:"inherit",cwd:n})}function no(a){return Vn("sha256").update(a).digest("hex")}function Ad(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)rA(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,tA({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(`
7275
7275
  `);throw Error(`serverless app bundle failed:
7276
- ${C}`)}let y=h.outputs[0],f=Buffer.from(await y.arrayBuffer()),S="index",b=Ii([{name:`${S}.mjs`,data:f}]);return{zip:b,bundle:f,sha256:no(b),handlerFile:S,handlers:{http:i.handlers?.http??`${S}.http`,queue:i.handlers?.queue??`${S}.queue`,cli:i.handlers?.cli??`${S}.cli`},bundleBytes:f.length}}finally{Hn(l,{recursive:!0,force:!0})}}var nA=["18","20","22"];function ti(a){if(!a)return"22";let n=String(a).match(/(\d+)/);return n?n[1]:"22"}function io(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"&&nA.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 yd(a,n,i){return qt(a,n,i).map((s)=>s.name)}function Id(a){let{app:n,environment:i,handlers:s}=a,c=a.config.project.slug,l=io(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 f=qt(n,c,i),S=f.map((z)=>z.name),b=S.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=Js(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(b)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`}:{},...b?{TSCLOUD_QUEUE:S[0]}:{},...n.env??{}}),K=Boolean(n.efs),ee=typeof n.efs==="object"?n.efs:{},te=ee.mountPath??"/mnt/local",ne=K&&!ee.accessPointArn,me=ee.accessPointArn??(ne?e.getAtt("EfsAccessPoint","Arn"):void 0),oe=n.vpc?.subnets??[],le=oe.length>0,ie=n.cache?.driver==="elasticache"||n.database?.connection==="aurora-serverless"||Boolean(n.rdsProxy)||K;if(ie&&!le)throw Error("serverless app: elasticache / aurora-serverless / rdsProxy / efs require app.vpc.subnets (private subnets) to be set.");let Ie=le?{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: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,...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),b)pe("QueueFunction",y.queue,s.queue,"queue",n.queueMemory??1024,n.queueTimeout??120,void 0,n.queueTmpStorage??W);let ue=(n.provisionedConcurrency??0)>0?n.provisionedConcurrency:0,ge=["HttpFunction","CliFunction",...b?["QueueFunction"]:[]];if(ue)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:ue}}};let Re=(z)=>ue?e.ref(`${z}Alias`):e.getAtt(z,"Arn"),he=(z)=>ue?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(b)P.AppQueueDlq={Type:"AWS::SQS::Queue",Properties:{QueueName:`${c}-${i}-dlq`,MessageRetentionPeriod:1209600}},f.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"||b);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(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(le&&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")},b)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:S,resourceSummary:We}}var iA=["cli","fpm","curl","mbstring","xml","pdo","mysqlnd","gd","bcmath","intl","opcache","sodium","process","pecl-redis6","pecl-apcu","pgsql"];function sA(a){let n=`php${a.replace(".","")}`;return iA.map((i)=>`${n}-php-${i}`)}function Gg(a,n){let i=`php${a.replace(".","")}`,s=sA(a).join(" \\\n "),c=`/opt/remi/${i}/root`,l=`/etc/opt/remi/${i}`;return`${n?`FROM almalinux:9 AS ${n}`:"FROM almalinux:9"}
7276
+ ${C}`)}let y=h.outputs[0],f=Buffer.from(await y.arrayBuffer()),S="index",b=Ii([{name:`${S}.mjs`,data:f}]);return{zip:b,bundle:f,sha256:no(b),handlerFile:S,handlers:{http:i.handlers?.http??`${S}.http`,queue:i.handlers?.queue??`${S}.queue`,cli:i.handlers?.cli??`${S}.cli`},bundleBytes:f.length}}finally{Hn(l,{recursive:!0,force:!0})}}var nA=["18","20","22"];function ti(a){if(!a)return"22";let n=String(a).match(/(\d+)/);return n?n[1]:"22"}function io(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"&&nA.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 yd(a,n,i){return qt(a,n,i).map((s)=>s.name)}function Id(a){let{app:n,environment:i,handlers:s}=a,c=a.config.project.slug,l=io(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 f=qt(n,c,i),S=f.map((z)=>z.name),b=S.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=Js(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(b)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`}:{},...b?{TSCLOUD_QUEUE:S[0]}:{},...n.env??{}}),K=Boolean(n.efs),ee=typeof n.efs==="object"?n.efs:{},te=ee.mountPath??"/mnt/local",ne=K&&!ee.accessPointArn,me=ee.accessPointArn??(ne?e.getAtt("EfsAccessPoint","Arn"):void 0),oe=n.vpc?.subnets??[],le=oe.length>0,ie=n.cache?.driver==="elasticache"||n.database?.connection==="aurora-serverless"||Boolean(n.rdsProxy)||K;if(ie&&!le)throw Error("serverless app: elasticache / aurora-serverless / rdsProxy / efs require app.vpc.subnets (private subnets) to be set.");let Ie=le?{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),b)pe("QueueFunction",y.queue,s.queue,"queue",n.queueMemory??1024,n.queueTimeout??120,void 0,n.queueTmpStorage??W);let ue=(n.provisionedConcurrency??0)>0?n.provisionedConcurrency:0,ge=["HttpFunction","CliFunction",...b?["QueueFunction"]:[]];if(ue)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:ue}}};let Re=(z)=>ue?e.ref(`${z}Alias`):e.getAtt(z,"Arn"),he=(z)=>ue?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(b)P.AppQueueDlq={Type:"AWS::SQS::Queue",Properties:{QueueName:`${c}-${i}-dlq`,MessageRetentionPeriod:1209600}},f.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"||b);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(le&&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")},b)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:S,resourceSummary:We}}var iA=["cli","fpm","curl","mbstring","xml","pdo","mysqlnd","gd","bcmath","intl","opcache","sodium","process","pecl-redis6","pecl-apcu","pgsql"];function sA(a){let n=`php${a.replace(".","")}`;return iA.map((i)=>`${n}-php-${i}`)}function Gg(a,n){let i=`php${a.replace(".","")}`,s=sA(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
@@ -7352,4 +7352,4 @@ php_admin_value[error_log] = /dev/stderr
7352
7352
  php_admin_flag[log_errors] = on
7353
7353
  clear_env = no
7354
7354
  `}function bi(){return Ua(pi(gi(import.meta.url)),"runtime-assets")}function Ci(){let a=bi(),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:fA(),mode:420}]}function wd(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 AA=["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 JC(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"),oA(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 b of Va(h)){let C=ki(h,b).replace(/\\/g,"/"),T=Fa(b).mode&73?493:420;y.push({name:C,data:Pi(b),mode:T})}s("Injecting runtime assets");let f=new Set(Ci().map((b)=>b.path)),S=y.filter((b)=>!f.has(b.name));for(let b of Ci())S.push({name:b.path,data:b.contents,mode:b.mode});return s("Packaging layer ZIP"),{zip:Ii(S),architecture:n,fileCount:S.length}}finally{Ri(c,{recursive:!0,force:!0})}}var yA=[".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 lo(a){if(a.skipBuild)return;let n=na(a.projectRoot??process.cwd()),i=a.app.build??AA;for(let s of i)a.onStep?.(`build: ${s}`),$i(s,{stdio:"inherit",cwd:n})}function uo(a,n=[]){let i=na(a),s=[...yA,Ws(),...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 Rd(a){let n=na(a.projectRoot??process.cwd());lo(a),a.onStep?.("packaging application tree");let i=uo(n,a.exclude);if(!i.length)throw Error(`No files to package under ${n}`);let s=Ii(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 zg{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 XC=new zg;class Kg{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 YC=new Kg;class Wg{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 ZC=new Wg;class Jg{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 eb=new Jg;class Xg{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 tb=new Xg;
7355
- export{Dp,x,Pp,uf,Iy,pf,Sy,Cy,by,Ey,vy,Ty,wy,Ry,Dy,Py,Np,kp,nd,id,Ws,_,d,sd,Bp,O,od,p,gf,hi,ad,cd,de,dd,Ny,r,t,ky,By,g,xy,_y,Oy,Ly,$y,Ft,ld,Js,mf,My,Fy,be,He,Ee,L,I,o,A,Ge,m,hf,qe,M,ut,Uy,ff,F,ud,ve,Ut,Xs,X,pd,Y,Af,Ys,U,Q,D,fi,E,Qt,pt,H,e,Zs,Qy,xp,gd,Hy,Gy,qy,Vy,md,jy,zy,Ky,Wy,Jy,Xy,Yy,Zy,eI,tI,rI,nI,yf,If,Sf,Cf,bf,Ef,vf,Ht,_p,Op,_r,Ai,iI,Lp,sI,oI,Or,aI,cI,dI,lI,uI,pI,Tf,wf,Rf,Df,Pf,eo,gI,Nf,kf,Bf,G,mI,Ve,to,Gt,xf,$p,_f,Of,Lf,Mp,Z,hI,fI,yI,II,$f,SI,q,CI,bI,EI,Fp,Up,vI,Qp,Hp,TI,wI,RI,DI,PI,Mf,hd,NI,kI,BI,xI,_I,Ff,Uf,OI,LI,$I,MI,FI,UI,QI,HI,GI,Gp,fd,qI,VI,jI,zI,qp,Vp,jp,KI,zp,WI,JI,XI,YI,Kp,ZI,eS,tS,rS,nS,iS,sS,oS,Qf,Hf,Gf,qf,Wp,aS,cS,dS,lS,uS,pS,gS,mS,hS,Vf,jf,zf,Kf,fS,AS,Jp,yS,Xp,Yp,Zp,eg,IS,SS,CS,bS,Te,yi,ES,vS,TS,wS,RS,DS,PS,NS,Wf,kS,BS,tg,rg,xS,_S,Jf,OS,LS,$S,MS,FS,US,QS,HS,GS,qS,VS,jS,zS,KS,WS,JS,XS,YS,ZS,eC,tC,ng,rC,ig,nC,sg,iC,og,sC,ag,oC,Lr,aC,cg,cC,ro,dC,dg,lC,lg,uC,ug,pC,pg,gC,gg,mC,$r,hC,mg,fC,hg,AC,fg,yC,Ag,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,Xf,Yf,Zf,eA,Fg,QC,Ug,HC,Qg,GC,Hg,qC,Ii,tA,rA,no,Ad,Mr,nA,io,qt,yd,Id,iA,sA,Gg,oA,Sd,qg,VC,jC,so,oo,ao,Cd,Si,bd,Ed,co,vd,Td,Vg,aA,cA,dA,zC,lA,uA,KC,pA,jg,gA,mA,hA,WC,fA,Ci,wd,AA,JC,yA,lo,uo,Rd,zg,XC,Kg,YC,Wg,ZC,Jg,eb,Xg,tb};
7355
+ export{Dp,x,Pp,uf,Iy,pf,Sy,Cy,by,Ey,vy,Ty,wy,Ry,Dy,Py,Np,kp,nd,id,Ws,_,d,sd,Bp,O,od,p,gf,hi,ad,cd,de,dd,Ny,r,t,ky,By,g,xy,_y,Oy,Ly,$y,Ft,ld,Js,mf,My,Fy,Ee,He,ve,L,I,o,A,Ge,m,hf,qe,M,ut,Uy,ff,F,ud,Te,Ut,Xs,X,pd,Y,Af,Ys,U,Q,D,fi,E,Qt,pt,H,e,Zs,Qy,xp,gd,Hy,Gy,qy,Vy,md,jy,zy,Ky,Wy,Jy,Xy,Yy,Zy,eI,tI,rI,nI,yf,If,Sf,Cf,bf,Ef,vf,Ht,_p,Op,_r,Ai,iI,Lp,sI,oI,Or,aI,cI,dI,lI,uI,pI,Tf,wf,Rf,Df,Pf,eo,gI,Nf,kf,Bf,G,mI,Ve,to,Gt,xf,$p,_f,Of,Lf,Mp,Z,hI,fI,yI,II,$f,SI,q,CI,bI,EI,Fp,Up,vI,Qp,Hp,TI,wI,RI,DI,PI,Mf,hd,NI,kI,BI,xI,_I,Ff,Uf,OI,LI,$I,MI,FI,UI,QI,HI,GI,Gp,fd,qI,VI,jI,zI,qp,Vp,jp,KI,zp,WI,JI,XI,YI,Kp,ZI,eS,tS,rS,nS,iS,sS,oS,Qf,Hf,Gf,qf,Wp,aS,cS,dS,lS,uS,pS,gS,mS,hS,Vf,jf,zf,Kf,fS,AS,Jp,yS,Xp,Yp,Zp,eg,IS,SS,CS,bS,we,yi,ES,vS,TS,wS,RS,DS,PS,NS,Wf,kS,BS,tg,rg,xS,_S,Jf,OS,LS,$S,MS,FS,US,QS,HS,GS,qS,VS,jS,zS,KS,WS,JS,XS,YS,ZS,eC,tC,ng,rC,ig,nC,sg,iC,og,sC,ag,oC,Lr,aC,cg,cC,ro,dC,dg,lC,lg,uC,ug,pC,pg,gC,gg,mC,$r,hC,mg,fC,hg,AC,fg,yC,Ag,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,Xf,Yf,Zf,eA,Fg,QC,Ug,HC,Qg,GC,Hg,qC,Ii,tA,rA,no,Ad,Mr,nA,io,qt,yd,Id,iA,sA,Gg,oA,Sd,qg,VC,jC,so,oo,ao,Cd,Si,bd,Ed,co,vd,Td,Vg,aA,cA,dA,zC,lA,uA,KC,pA,jg,gA,mA,hA,WC,fA,Ci,wd,AA,JC,yA,lo,uo,Rd,zg,XC,Kg,YC,Wg,ZC,Jg,eb,Xg,tb};