@stacksjs/ts-cloud 0.16.31 → 0.16.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aws/index.js +1 -1
- package/dist/bin/{chunk-5nf3fxgw.js → chunk-12j17qm5.js} +1 -1
- package/dist/bin/{chunk-0n0jscsr.js → chunk-24473jks.js} +1 -1
- package/dist/bin/chunk-3932p1z3.js +1 -0
- package/dist/bin/chunk-3eztnxgw.js +1 -0
- package/dist/bin/{chunk-10sypz59.js → chunk-4182gadf.js} +1 -1
- package/dist/bin/chunk-4er4ktcs.js +1 -0
- package/dist/bin/{chunk-7577ykbj.js → chunk-6wz04wnk.js} +1 -1
- package/dist/bin/{chunk-remzfbhd.js → chunk-6yr12f64.js} +3 -3
- package/dist/bin/{chunk-8c4fnga8.js → chunk-79sd00d1.js} +1 -1
- package/dist/bin/{chunk-bkzt5ntz.js → chunk-81mt497w.js} +1 -1
- package/dist/bin/{chunk-dmyr6etw.js → chunk-8mgwqpmx.js} +1 -1
- package/dist/bin/{chunk-e6xn8g28.js → chunk-985ev3ns.js} +1 -1
- package/dist/bin/{chunk-bvtpvstn.js → chunk-9e62z9je.js} +11 -11
- package/dist/bin/{chunk-g1krw34t.js → chunk-9eq18gds.js} +1 -1
- package/dist/bin/chunk-9zhp2z0s.js +1 -0
- package/dist/bin/{chunk-f00ytxnx.js → chunk-b9psp74n.js} +14 -14
- package/dist/bin/chunk-bmmr5mq6.js +1 -0
- package/dist/bin/{chunk-je602ntp.js → chunk-cr56pxpt.js} +1 -1
- package/dist/bin/chunk-dvv2z19r.js +1 -0
- package/dist/bin/{chunk-y9cdqk8c.js → chunk-efbmb8rw.js} +1 -1
- package/dist/bin/chunk-eyrmv6c4.js +1 -0
- package/dist/bin/{chunk-9nnfyqme.js → chunk-f7dtn45y.js} +3 -3
- package/dist/bin/chunk-fnnv0t66.js +1 -0
- package/dist/bin/{chunk-1chq0c2k.js → chunk-fpxb97q5.js} +1 -1
- package/dist/bin/chunk-fwmje99n.js +1 -0
- package/dist/bin/{chunk-k8r5zfnf.js → chunk-gcm9n6ww.js} +1 -1
- package/dist/bin/{chunk-6hrycgbh.js → chunk-gzxpkk0c.js} +1 -1
- package/dist/bin/{chunk-s3mv4z3f.js → chunk-jhp53qsd.js} +1 -1
- package/dist/bin/{chunk-jeg6vw5v.js → chunk-jzby2kzy.js} +1 -1
- package/dist/bin/{chunk-xtqx4v3f.js → chunk-kgtzvh2k.js} +1 -1
- package/dist/bin/{chunk-a9yp82q5.js → chunk-kqf19j9m.js} +1 -1
- package/dist/bin/{chunk-nb5vjsdg.js → chunk-mpq5ct10.js} +4 -4
- package/dist/bin/chunk-n775dk3f.js +1 -0
- package/dist/bin/{chunk-kne9dmwr.js → chunk-nnawqw34.js} +32 -32
- package/dist/bin/chunk-ppj604c9.js +1 -0
- package/dist/bin/chunk-prq5gw4j.js +1 -0
- package/dist/bin/chunk-pt71fyem.js +1 -0
- package/dist/bin/{chunk-1wtkv65w.js → chunk-py8cvqvx.js} +1 -1
- package/dist/bin/{chunk-3ykx59eg.js → chunk-q6z8wvvb.js} +1 -1
- package/dist/bin/{chunk-q9tvzcr7.js → chunk-qe56mnjc.js} +3 -3
- package/dist/bin/chunk-qvj454fy.js +1 -0
- package/dist/bin/{chunk-j8dkatkk.js → chunk-sdy79wz7.js} +4 -4
- package/dist/bin/chunk-smj97rs5.js +1 -0
- package/dist/bin/{chunk-yrq5bkxe.js → chunk-tg45thhb.js} +1 -1
- package/dist/bin/{chunk-e4p6hwct.js → chunk-tgwx5haz.js} +1 -1
- package/dist/bin/{chunk-5sr8x2ce.js → chunk-vhz2wmb8.js} +75 -75
- package/dist/bin/{chunk-a1kpwbjg.js → chunk-wt7wjgcr.js} +3 -3
- package/dist/bin/{chunk-j2yy3tth.js → chunk-x56s9b7f.js} +1 -1
- package/dist/bin/chunk-yf3zys06.js +1 -0
- package/dist/bin/{chunk-ee6ssn26.js → chunk-zhkbdsfs.js} +1 -1
- package/dist/bin/{chunk-jf8jp6f5.js → chunk-zk3nm0td.js} +1 -1
- package/dist/bin/chunk-zmjm7bmm.js +1 -0
- package/dist/bin/cli.js +46 -46
- package/dist/bin/dashboard-server.js +1 -1
- package/dist/chunk-05bmq0z1.js +1 -0
- package/dist/chunk-0qdgw73b.js +1 -0
- package/dist/{chunk-75bga11p.js → chunk-2mw7bjhn.js} +1 -1
- package/dist/{chunk-92w1g5d9.js → chunk-4hdp9ms2.js} +1 -1
- package/dist/{chunk-m3a4brpj.js → chunk-4jgy95bv.js} +5 -5
- package/dist/{chunk-z8qz33yk.js → chunk-57fhsqzb.js} +2 -2
- package/dist/{chunk-3kpnn06d.js → chunk-983txhkg.js} +1 -1
- package/dist/{chunk-b6ar7eqc.js → chunk-efssa93f.js} +1 -1
- package/dist/{chunk-26cq0zjv.js → chunk-jh38v9zp.js} +2 -2
- package/dist/{chunk-f733qy2d.js → chunk-kavwrxm8.js} +2 -2
- package/dist/{chunk-9n0q2cxj.js → chunk-nq51dyxz.js} +4 -4
- package/dist/{chunk-xcq2sb1d.js → chunk-peeqkk92.js} +72 -72
- package/dist/chunk-pf6sanwe.js +1 -0
- package/dist/{chunk-2c8pcbq8.js → chunk-r45340yc.js} +34 -34
- package/dist/{chunk-mqm1hxaw.js → chunk-rqe0sfqw.js} +2 -2
- package/dist/{chunk-1erk1r1m.js → chunk-s909414m.js} +1 -1
- package/dist/{chunk-t3yzfbe7.js → chunk-t1gts5j9.js} +4 -4
- package/dist/{chunk-yc2rm4v9.js → chunk-wbabf3hg.js} +1 -1
- package/dist/{chunk-d5f9nh99.js → chunk-xbh2vr95.js} +34 -34
- package/dist/deploy/index.js +1 -1
- package/dist/drivers/index.js +1 -1
- package/dist/drivers/shared/deploy-script.d.ts +42 -0
- package/dist/index.js +3 -3
- package/dist/operations/index.js +1 -1
- package/dist/protection/index.js +1 -1
- package/dist/spend/index.js +1 -1
- package/dist/ui/404.html +1 -1
- package/dist/ui/accept-invitation.html +1 -1
- package/dist/ui/access-denied.html +1 -1
- package/dist/ui/account/automation.html +5 -5
- package/dist/ui/account/security.html +1 -1
- package/dist/ui/applications/compose.html +6 -6
- package/dist/ui/applications/new.html +2 -2
- package/dist/ui/data/backups.html +6 -6
- package/dist/ui/data/services.html +6 -6
- package/dist/ui/data/volumes.html +6 -6
- package/dist/ui/index.html +6 -6
- package/dist/ui/infrastructure/topology.html +6 -6
- package/dist/ui/integrations.html +2 -2
- package/dist/ui/operations/alerts.html +6 -6
- package/dist/ui/operations/configuration.html +6 -6
- package/dist/ui/operations/jobs.html +6 -6
- package/dist/ui/operations/maintenance.html +5 -5
- package/dist/ui/operations/observability.html +6 -6
- package/dist/ui/operations/previews.html +6 -6
- package/dist/ui/operations/queue.html +6 -6
- package/dist/ui/operations/regions.html +5 -5
- package/dist/ui/operations/releases.html +6 -6
- package/dist/ui/operations/spend.html +6 -6
- package/dist/ui/operations/workloads.html +6 -6
- package/dist/ui/security.html +1 -1
- package/dist/ui/server/actions.html +6 -6
- package/dist/ui/server/activity.html +1 -1
- package/dist/ui/server/capacity.html +6 -6
- package/dist/ui/server/database.html +6 -6
- package/dist/ui/server/deployments.html +6 -6
- package/dist/ui/server/diagnostics.html +2 -2
- package/dist/ui/server/firewall.html +6 -6
- package/dist/ui/server/fleet.html +6 -6
- package/dist/ui/server/logs.html +6 -6
- package/dist/ui/server/metrics.html +6 -6
- package/dist/ui/server/security.html +2 -2
- package/dist/ui/server/services.html +2 -2
- package/dist/ui/server/sites.html +6 -6
- package/dist/ui/server/ssh-keys.html +6 -6
- package/dist/ui/server/team.html +6 -6
- package/dist/ui/server/terminal.html +2 -2
- package/dist/ui/serverless/alarms.html +6 -6
- package/dist/ui/serverless/assets.html +2 -2
- package/dist/ui/serverless/cost.html +2 -2
- package/dist/ui/serverless/data.html +6 -6
- package/dist/ui/serverless/deployments.html +2 -2
- package/dist/ui/serverless/firewall.html +2 -2
- package/dist/ui/serverless/functions.html +6 -6
- package/dist/ui/serverless/logs.html +6 -6
- package/dist/ui/serverless/metrics.html +2 -2
- package/dist/ui/serverless/queues.html +6 -6
- package/dist/ui/serverless/secrets.html +6 -6
- package/dist/ui/serverless/traces.html +6 -6
- package/dist/ui/serverless.html +6 -6
- package/package.json +3 -3
- package/dist/bin/chunk-052sk11z.js +0 -1
- package/dist/bin/chunk-1d4663e1.js +0 -1
- package/dist/bin/chunk-223yq2z0.js +0 -1
- package/dist/bin/chunk-675txngy.js +0 -1
- package/dist/bin/chunk-98e48n5j.js +0 -1
- package/dist/bin/chunk-ecxchy9q.js +0 -1
- package/dist/bin/chunk-gcazbfsv.js +0 -1
- package/dist/bin/chunk-gg6vwdnn.js +0 -1
- package/dist/bin/chunk-gz0gahzh.js +0 -1
- package/dist/bin/chunk-hdkxj8p9.js +0 -1
- package/dist/bin/chunk-hg60j47r.js +0 -1
- package/dist/bin/chunk-jxh78anm.js +0 -1
- package/dist/bin/chunk-mv0t7j76.js +0 -1
- package/dist/bin/chunk-p8f1qgz2.js +0 -1
- package/dist/bin/chunk-pa106cr4.js +0 -1
- package/dist/bin/chunk-w3815pxd.js +0 -1
- package/dist/bin/chunk-x46p60ym.js +0 -1
- package/dist/chunk-43pe4shw.js +0 -1
- package/dist/chunk-94tb2msg.js +0 -1
- package/dist/chunk-d8wcqgpx.js +0 -1
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import{createRequire as er}from"node:module";import{isAbsolute as xt,join as ht,relative as cr}from"node:path";import{existsSync as qe,readdirSync as gr}from"node:fs";import{join as ve}from"node:path";import{createHash as Nr}from"node:crypto";import{copyFileSync as Dr,existsSync as Nt,readdirSync as kr,readFileSync as st,statSync as $r,writeFileSync as ot}from"node:fs";import{basename as Lr,dirname as da,extname as ma,join as Qe}from"node:path";import{existsSync as Ma,readFileSync as Ht}from"node:fs";import{homedir as Oa}from"node:os";import{join as xa}from"node:path";import{createHash as _a}from"node:crypto";import{existsSync as lt,mkdirSync as Ln,readdirSync as ya,readFileSync as fa,unlinkSync as Ye,writeFileSync as Mn}from"node:fs";import{join as kt}from"node:path";import{createHash as Qt}from"node:crypto";import{createReadStream as On,readdirSync as xn,statSync as St}from"node:fs";import{join as Bn,relative as _n}from"node:path";import{deflateRawSync as zn}from"node:zlib";import{execSync as Xn}from"node:child_process";import{createHash as ei}from"node:crypto";import{cpSync as ti,mkdtempSync as ai,rmSync as ri,writeFileSync as ni}from"node:fs";import{tmpdir as ii}from"node:os";import{dirname as si,isAbsolute as oi,join as Oe,resolve as ci}from"node:path";import{fileURLToPath as li}from"node:url";import{execFileSync as Tt}from"node:child_process";import{mkdtempSync as Fa,readFileSync as wt,rmSync as Ua}from"node:fs";import{tmpdir as Va}from"node:os";import{dirname as pi,join as we}from"node:path";import{fileURLToPath as gi}from"node:url";import{AsyncLocalStorage as yi}from"node:async_hooks";import{createHash as fi}from"node:crypto";import{readFileSync as Ti}from"node:fs";import{dirname as wi,join as za}from"node:path";import{fileURLToPath as Ei}from"node:url";import{execFileSync as ut}from"node:child_process";import{existsSync as Ri,mkdirSync as Di,mkdtempSync as $i,readdirSync as Li,readFileSync as Mi,rmSync as Wi,statSync as Qa,writeFileSync as Gi}from"node:fs";import{tmpdir as Fi}from"node:os";import{join as xe,relative as Ui}from"node:path";import{execSync as Vi}from"node:child_process";import{createHash as ji}from"node:crypto";import{readdirSync as Ki,readFileSync as qi,statSync as Ya}from"node:fs";import{join as Hi,relative as Za,resolve as ua}from"node:path";var tr=Object.defineProperty,ar=(n)=>n;function rr(n,i){this[n]=ar.bind(null,i)}var Ge=(n,i)=>{for(var s in i)tr(n,s,{get:i[s],enumerable:!0,configurable:!0,set:rr.bind(i,s)})},nr=(n,i,s)=>()=>{if(n)try{i=n(n=0)}catch(o){s=[o]}if(s)throw s[0];return i},ir=er(import.meta.url);function lg(n){let i=typeof n==="string"?new URL(n):n,{hostname:s,pathname:o}=i;if(s.endsWith(".on.aws")){let h=s.match(/^[^.]+\.lambda-url\.([^.]+)\.on\.aws$/);if(h)return{service:"lambda",region:h[1]};return{service:"",region:""}}if(s.endsWith(".r2.cloudflarestorage.com"))return{service:"s3",region:"auto"};if(s.endsWith(".backblazeb2.com")){let h=s.match(/^(?:[^.]+\.)?s3\.([^.]+)\.backblazeb2\.com$/);if(h)return{service:"s3",region:h[1]};return{service:"",region:""}}let c=s.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(s.startsWith("iot."))l="execute-api";else if(s.startsWith("data.jobs.iot."))l="iot-jobs-data";else l=o==="/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=Ia[l]||l,{service:l,region:u||"us-east-1"}}function
|
|
2
|
-
`),ne=Xe(Z),de=[
|
|
3
|
-
`),oe=n.cache??Le,le=Ta(l,R,E,w,de,oe),ie=[`${
|
|
4
|
-
`),de=await mt(ne),oe=[
|
|
5
|
-
`),le=n.cache??Le,ie=await wa(l,R,E,w,oe,le),Ee=[`${
|
|
6
|
-
`,_=Ct(P.searchParams),B=[s,
|
|
1
|
+
import{createRequire as er}from"node:module";import{isAbsolute as xt,join as ht,relative as cr}from"node:path";import{existsSync as qe,readdirSync as gr}from"node:fs";import{join as ve}from"node:path";import{createHash as Nr}from"node:crypto";import{copyFileSync as Dr,existsSync as Nt,readdirSync as kr,readFileSync as st,statSync as $r,writeFileSync as ot}from"node:fs";import{basename as Lr,dirname as da,extname as ma,join as Qe}from"node:path";import{existsSync as Ma,readFileSync as Ht}from"node:fs";import{homedir as Oa}from"node:os";import{join as xa}from"node:path";import{createHash as _a}from"node:crypto";import{existsSync as lt,mkdirSync as Ln,readdirSync as ya,readFileSync as fa,unlinkSync as Ye,writeFileSync as Mn}from"node:fs";import{join as kt}from"node:path";import{createHash as Qt}from"node:crypto";import{createReadStream as On,readdirSync as xn,statSync as St}from"node:fs";import{join as Bn,relative as _n}from"node:path";import{deflateRawSync as zn}from"node:zlib";import{execSync as Xn}from"node:child_process";import{createHash as ei}from"node:crypto";import{cpSync as ti,mkdtempSync as ai,rmSync as ri,writeFileSync as ni}from"node:fs";import{tmpdir as ii}from"node:os";import{dirname as si,isAbsolute as oi,join as Oe,resolve as ci}from"node:path";import{fileURLToPath as li}from"node:url";import{execFileSync as Tt}from"node:child_process";import{mkdtempSync as Fa,readFileSync as wt,rmSync as Ua}from"node:fs";import{tmpdir as Va}from"node:os";import{dirname as pi,join as we}from"node:path";import{fileURLToPath as gi}from"node:url";import{AsyncLocalStorage as yi}from"node:async_hooks";import{createHash as fi}from"node:crypto";import{readFileSync as Ti}from"node:fs";import{dirname as wi,join as za}from"node:path";import{fileURLToPath as Ei}from"node:url";import{execFileSync as ut}from"node:child_process";import{existsSync as Ri,mkdirSync as Di,mkdtempSync as $i,readdirSync as Li,readFileSync as Mi,rmSync as Wi,statSync as Qa,writeFileSync as Gi}from"node:fs";import{tmpdir as Fi}from"node:os";import{join as xe,relative as Ui}from"node:path";import{execSync as Vi}from"node:child_process";import{createHash as ji}from"node:crypto";import{readdirSync as Ki,readFileSync as qi,statSync as Ya}from"node:fs";import{join as Hi,relative as Za,resolve as ua}from"node:path";var tr=Object.defineProperty,ar=(n)=>n;function rr(n,i){this[n]=ar.bind(null,i)}var Ge=(n,i)=>{for(var s in i)tr(n,s,{get:i[s],enumerable:!0,configurable:!0,set:rr.bind(i,s)})},nr=(n,i,s)=>()=>{if(n)try{i=n(n=0)}catch(o){s=[o]}if(s)throw s[0];return i},ir=er(import.meta.url);function lg(n){let i=typeof n==="string"?new URL(n):n,{hostname:s,pathname:o}=i;if(s.endsWith(".on.aws")){let h=s.match(/^[^.]+\.lambda-url\.([^.]+)\.on\.aws$/);if(h)return{service:"lambda",region:h[1]};return{service:"",region:""}}if(s.endsWith(".r2.cloudflarestorage.com"))return{service:"s3",region:"auto"};if(s.endsWith(".backblazeb2.com")){let h=s.match(/^(?:[^.]+\.)?s3\.([^.]+)\.backblazeb2\.com$/);if(h)return{service:"s3",region:h[1]};return{service:"",region:""}}let c=s.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(s.startsWith("iot."))l="execute-api";else if(s.startsWith("data.jobs.iot."))l="iot-jobs-data";else l=o==="/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=Ia[l]||l,{service:l,region:u||"us-east-1"}}function x(n){let{method:i,url:s,body:o="",accessKeyId:c,secretAccessKey:l,sessionToken:u,signQuery:h=!1,expiresIn:f=86400,datetime:S}=n,b=new URL(s),A=b.hostname,v=lg(b),w=n.service||v.service,E=n.region||v.region;if(!w)throw Error("Could not detect service from URL. Please provide service explicitly.");if(!E)throw Error("Could not detect region from URL. Please provide region explicitly.");let P=S||new Date().toISOString().replace(/[:-]|\.\d{3}/g,""),R=P.substring(0,8),D=[R,E,w,"aws4_request"].join("/"),O="AWS4-HMAC-SHA256";if(h)return sr({urlObj:b,method:i,body:o,accessKeyId:c,secretAccessKey:l,sessionToken:u,service:w,region:E,timestamp:P,date:R,credentialScope:D,algorithm:O,expiresIn:f,cache:n.cache});let I=b.pathname||"/",_=Ct(b.searchParams),B={host:A,"x-amz-date":P,...n.headers};if(u)B["x-amz-security-token"]=u;let W=Object.keys(B).some((Ee)=>Ee.toLowerCase()==="content-type");if(o&&!W)B["content-type"]="application/x-amz-json-1.0";if(w==="s3"&&!B["x-amz-content-sha256"])B["x-amz-content-sha256"]=Xe(o);let J=Aa(B),K=Ca(B),Y=B["x-amz-content-sha256"]||Xe(o),Z=[i,vt(I),_,J,K,Y].join(`
|
|
2
|
+
`),ne=Xe(Z),de=[O,P,D,ne].join(`
|
|
3
|
+
`),oe=n.cache??Le,le=Ta(l,R,E,w,de,oe),ie=[`${O} Credential=${c}/${D}`,`SignedHeaders=${K}`,`Signature=${le}`].join(", ");return B.authorization=ie,{url:s,method:i,headers:B,body:o||void 0}}async function ug(n){let{method:i,url:s,body:o="",accessKeyId:c,secretAccessKey:l,sessionToken:u,signQuery:h=!1,expiresIn:f=86400,datetime:S}=n,b=new URL(s),A=b.hostname,v=lg(b),w=n.service||v.service,E=n.region||v.region;if(!w)throw Error("Could not detect service from URL. Please provide service explicitly.");if(!E)throw Error("Could not detect region from URL. Please provide region explicitly.");let P=S||new Date().toISOString().replace(/[:-]|\.\d{3}/g,""),R=P.substring(0,8),D=[R,E,w,"aws4_request"].join("/"),O="AWS4-HMAC-SHA256";if(h)return or({urlObj:b,method:i,body:o,accessKeyId:c,secretAccessKey:l,sessionToken:u,service:w,region:E,timestamp:P,date:R,credentialScope:D,algorithm:O,expiresIn:f,cache:n.cache});let I=b.pathname||"/",_=Ct(b.searchParams),B={host:A,"x-amz-date":P,...n.headers};if(u)B["x-amz-security-token"]=u;let W=Object.keys(B).some((Fe)=>Fe.toLowerCase()==="content-type");if(o&&!W)B["content-type"]="application/x-amz-json-1.0";let J=await mt(o);if(w==="s3"&&!B["x-amz-content-sha256"])B["x-amz-content-sha256"]=J;let K=Aa(B),Y=Ca(B),Z=B["x-amz-content-sha256"]||J,ne=[i,vt(I),_,K,Y,Z].join(`
|
|
4
|
+
`),de=await mt(ne),oe=[O,P,D,de].join(`
|
|
5
|
+
`),le=n.cache??Le,ie=await wa(l,R,E,w,oe,le),Ee=[`${O} Credential=${c}/${D}`,`SignedHeaders=${Y}`,`Signature=${ie}`].join(", ");return B.authorization=Ee,{url:s,method:i,headers:B,body:o||void 0}}function sr(n){let{urlObj:i,method:s,body:o,accessKeyId:c,secretAccessKey:l,sessionToken:u,service:h,region:f,timestamp:S,date:b,credentialScope:A,algorithm:v,expiresIn:w,cache:E}=n,P=new URL(i.toString());P.searchParams.set("X-Amz-Algorithm",v),P.searchParams.set("X-Amz-Credential",`${c}/${A}`),P.searchParams.set("X-Amz-Date",S),P.searchParams.set("X-Amz-Expires",String(w));let R=h==="s3"?"UNSIGNED-PAYLOAD":Xe(o);if(h==="s3")P.searchParams.set("X-Amz-Content-Sha256",R);let D="host";if(P.searchParams.set("X-Amz-SignedHeaders",D),u)P.searchParams.set("X-Amz-Security-Token",u);let O=vt(P.pathname||"/"),I=`host:${P.hostname}
|
|
6
|
+
`,_=Ct(P.searchParams),B=[s,O,_,I,D,R].join(`
|
|
7
7
|
`),W=[v,S,A,Xe(B)].join(`
|
|
8
|
-
`),J=Ta(l,b,f,h,W,E??Le);return P.searchParams.set("X-Amz-Signature",J),{url:P.toString(),method:s,headers:{},body:o||void 0}}async function or(n){let{urlObj:i,method:s,body:o,accessKeyId:c,secretAccessKey:l,sessionToken:u,service:h,region:f,timestamp:S,date:b,credentialScope:A,algorithm:v,expiresIn:w,cache:E}=n,P=new URL(i.toString());P.searchParams.set("X-Amz-Algorithm",v),P.searchParams.set("X-Amz-Credential",`${c}/${A}`),P.searchParams.set("X-Amz-Date",S),P.searchParams.set("X-Amz-Expires",String(w));let R=h==="s3"?"UNSIGNED-PAYLOAD":await mt(o);if(h==="s3")P.searchParams.set("X-Amz-Content-Sha256",R);let D="host";if(P.searchParams.set("X-Amz-SignedHeaders",D),u)P.searchParams.set("X-Amz-Security-Token",u);let
|
|
9
|
-
`,_=Ct(P.searchParams),B=[s,
|
|
8
|
+
`),J=Ta(l,b,f,h,W,E??Le);return P.searchParams.set("X-Amz-Signature",J),{url:P.toString(),method:s,headers:{},body:o||void 0}}async function or(n){let{urlObj:i,method:s,body:o,accessKeyId:c,secretAccessKey:l,sessionToken:u,service:h,region:f,timestamp:S,date:b,credentialScope:A,algorithm:v,expiresIn:w,cache:E}=n,P=new URL(i.toString());P.searchParams.set("X-Amz-Algorithm",v),P.searchParams.set("X-Amz-Credential",`${c}/${A}`),P.searchParams.set("X-Amz-Date",S),P.searchParams.set("X-Amz-Expires",String(w));let R=h==="s3"?"UNSIGNED-PAYLOAD":await mt(o);if(h==="s3")P.searchParams.set("X-Amz-Content-Sha256",R);let D="host";if(P.searchParams.set("X-Amz-SignedHeaders",D),u)P.searchParams.set("X-Amz-Security-Token",u);let O=vt(P.pathname||"/"),I=`host:${P.hostname}
|
|
9
|
+
`,_=Ct(P.searchParams),B=[s,O,_,I,D,R].join(`
|
|
10
10
|
`),W=[v,S,A,await mt(B)].join(`
|
|
11
|
-
`),J=await wa(l,b,f,h,W,E??Le);return P.searchParams.set("X-Amz-Signature",J),{url:P.toString(),method:s,headers:{},body:o||void 0}}function sA(n){let{url:i,method:s="GET",expiresIn:o=3600,...c}=n,l=Math.min(o,604800);return
|
|
11
|
+
`),J=await wa(l,b,f,h,W,E??Le);return P.searchParams.set("X-Amz-Signature",J),{url:P.toString(),method:s,headers:{},body:o||void 0}}function sA(n){let{url:i,method:s="GET",expiresIn:o=3600,...c}=n,l=Math.min(o,604800);return x({...c,url:i,method:s,signQuery:!0,expiresIn:l}).url}async function mI(n){let{url:i,method:s="GET",expiresIn:o=3600,...c}=n,l=Math.min(o,604800);return(await ug({...c,url:i,method:s,signQuery:!0,expiresIn:l})).url}function Aa(n){return Object.keys(n).sort().map((i)=>`${i.toLowerCase()}:${n[i].trim().replace(/\s+/g," ")}`).join(`
|
|
12
12
|
`)+`
|
|
13
|
-
`}function Ca(n){return Object.keys(n).sort().map((i)=>i.toLowerCase()).join(";")}function Ct(n){let i=[];return n.forEach((s,o)=>{i.push([Ot(o),Ot(s)])}),i.sort((s,o)=>{if(s[0]<o[0])return-1;if(s[0]>o[0])return 1;if(s[1]<o[1])return-1;if(s[1]>o[1])return 1;return 0}),i.map(([s,o])=>`${s}=${o}`).join("&")}function vt(n){return n.split("/").map((i)=>Ot(i)).join("/")}function Ot(n){return encodeURIComponent(n).replace(/[!'()*]/g,(i)=>`%${i.charCodeAt(0).toString(16).toUpperCase()}`)}function Xe(n){if(!_e)throw Error("Synchronous hash not available in browser. Use signRequestAsync() instead.");return _e.createHash("sha256").update(n,"utf8").digest("hex")}function Ve(n,i){if(!_e)throw Error("Synchronous hmac not available in browser. Use signRequestAsync() instead.");return _e.createHmac("sha256",n).update(i,"utf8").digest()}async function mt(n){let i=new TextEncoder().encode(n),s=await crypto.subtle.digest("SHA-256",i);return va(new Uint8Array(s))}async function je(n,i){let s=new TextEncoder,o=typeof n==="string"?s.encode(n):n,c=s.encode(i),l=await crypto.subtle.importKey("raw",o.buffer,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),u=await crypto.subtle.sign("HMAC",l,c.buffer);return new Uint8Array(u)}function va(n){return Array.from(n).map((i)=>i.toString(16).padStart(2,"0")).join("")}function Ta(n,i,s,o,c,l){let u=`${n}:${i}:${s}:${o}`,h=l.get(u);if(!h){let f=Ve(`AWS4${n}`,i),S=Ve(f,s),b=Ve(S,o);if(h=Ve(b,"aws4_request"),l.size>=Pa){let A=l.keys().next().value;if(A)l.delete(A)}l.set(u,h)}return Ve(h,c).toString("hex")}async function wa(n,i,s,o,c,l){let u=`${n}:${i}:${s}:${o}`,h=l.get(u);if(!h){let S=await je(`AWS4${n}`,i),b=await je(S,s),A=await je(b,o);if(h=await je(A,"aws4_request"),l.size>=Pa){let v=l.keys().next().value;if(v)l.delete(v)}l.set(u,h)}let f=await je(h,c);return va(f)}function Ea(n,i){return i.includes(n)}function pt(n,i,s){let o=i*Math.pow(2,n),c=Math.random()*0.3*o;return Math.min(o+c,s)}function gt(n){return new Promise((i)=>setTimeout(i,n))}async function oA(n,i){let{maxRetries:s=3,initialDelayMs:o=100,maxDelayMs:c=5000,retryableStatusCodes:l=[429,500,502,503,504],timeoutMs:u=30000}=i??{},h,f;for(let S=0;S<=s;S++){let b=O(n),A={method:b.method,headers:b.headers};if(b.body)A.body=b.body;let v=new AbortController,w=setTimeout(()=>v.abort(),u);A.signal=v.signal;try{let E=await fetch(b.url,A);if(clearTimeout(w),f=E,E.ok)return E;if(S<s&&Ea(E.status,l)){let R=pt(S,o,c);await gt(R);continue}let P=await E.text();throw Error(`AWS API request failed (${E.status}): ${P}`)}catch(E){if(clearTimeout(w),h=E,E instanceof Error&&E.name==="AbortError")h=Error(`Request timed out after ${u}ms`);if(S<s&&!(E instanceof Error&&E.message.includes("AWS API request failed"))){let P=pt(S,o,c);await gt(P);continue}throw h}}throw h??Error("Request failed after retries")}async function hI(n){return oA(n,{maxRetries:0})}async function fI(n,i){let{maxRetries:s=3,initialDelayMs:o=100,maxDelayMs:c=5000,retryableStatusCodes:l=[429,500,502,503,504],timeoutMs:u=30000}=i??{},h;for(let f=0;f<=s;f++){let S=await ug(n),b={method:S.method,headers:S.headers};if(S.body)b.body=S.body;let A=new AbortController,v=setTimeout(()=>A.abort(),u);b.signal=A.signal;try{let w=await fetch(S.url,b);if(clearTimeout(v),w.ok)return w;if(f<s&&Ea(w.status,l)){let P=pt(f,o,c);await gt(P);continue}let E=await w.text();throw Error(`AWS API request failed (${w.status}): ${E}`)}catch(w){if(clearTimeout(v),h=w,w instanceof Error&&w.name==="AbortError")h=Error(`Request timed out after ${u}ms`);if(f<s&&!(w instanceof Error&&w.message.includes("AWS API request failed"))){let E=pt(f,o,c);await gt(E);continue}throw h}}throw h??Error("Request failed after retries")}async function yI(n){let i=await n.text(),s={},o=/<(\w+)>([^<]+)<\/\1>/g,c;while((c=o.exec(i))!==null){let[,l,u]=c;s[l]=u}return s}async function II(n){return await n.json()}function SI(){Le.clear()}function CI(){return Le.size}function EI(){return _e!==void 0}function bI(){return typeof crypto<"u"&&typeof crypto.subtle<"u"}var _e,Le,Pa=100,Ia,rt=nr(async()=>{try{_e=await import("node:crypto")}catch{}Le=new Map,Ia={appstream2:"appstream",cloudhsmv2:"cloudhsm",email:"ses",marketplace:"aws-marketplace",mobile:"AWSMobileHubService",pinpoint:"mobiletargeting",queue:"sqs","git-codecommit":"codecommit","mturk-requester-sandbox":"mturk-requester","personalize-runtime":"personalize"}}),vI={backgroundJobs:{visibilityTimeout:120,messageRetentionPeriod:604800,deadLetterQueue:!0,maxReceiveCount:3,encrypted:!0},fifo:{fifo:!0,contentBasedDeduplication:!0,visibilityTimeout:30,encrypted:!0},highThroughput:{visibilityTimeout:30,receiveMessageWaitTime:20,encrypted:!0},delayed:{delaySeconds:60,visibilityTimeout:60,encrypted:!0},longRunning:{visibilityTimeout:900,messageRetentionPeriod:1209600,deadLetterQueue:!0,maxReceiveCount:2,encrypted:!0},monitored:{visibilityTimeout:60,messageRetentionPeriod:604800,deadLetterQueue:!0,maxReceiveCount:3,encrypted:!0,alarms:{enabled:!0,queueDepthThreshold:1000,messageAgeThreshold:3600,dlqAlarm:!0}},lambdaOptimized:{visibilityTimeout:360,receiveMessageWaitTime:20,deadLetterQueue:!0,maxReceiveCount:3,encrypted:!0},fanOut:{visibilityTimeout:30,receiveMessageWaitTime:20,encrypted:!0}},TI={serverless:{development:{enabled:!0,mode:"serverless",channels:{public:!0,private:!0,presence:!0},storage:{type:"dynamodb",dynamodb:{billingMode:"PAY_PER_REQUEST"}},scaling:{maxConnections:1000,handlerMemory:128}},production:{enabled:!0,mode:"serverless",channels:{public:!0,private:!0,presence:{enabled:!0,maxMembers:100,heartbeatInterval:30,inactivityTimeout:60}},storage:{type:"dynamodb",dynamodb:{billingMode:"PAY_PER_REQUEST",pointInTimeRecovery:!0,connectionTTL:86400}},scaling:{maxConnections:50000,messagesPerSecond:5000,handlerMemory:256,handlerTimeout:30},monitoring:{enabled:!0,connectionThreshold:40000,errorThreshold:100,latencyThreshold:500},keepAlive:!0,keepAliveInterval:30,idleTimeout:600},notifications:{enabled:!0,mode:"serverless",channels:{public:!1,private:!0,presence:!1},storage:{type:"dynamodb",dynamodb:{billingMode:"PAY_PER_REQUEST"}},scaling:{maxConnections:50000,messagesPerSecond:2000,handlerMemory:128},keepAlive:!0,keepAliveInterval:60,idleTimeout:1800}},server:{development:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:!0},server:{host:"0.0.0.0",port:6001,scheme:"ws",driver:"bun",idleTimeout:120,perMessageDeflate:!1,metrics:!1}},production:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:!0},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:120,maxPayloadLength:16777216,backpressureLimit:1048576,sendPings:!0,perMessageDeflate:!0,instances:2,redis:{enabled:!0,keyPrefix:"broadcasting:"},rateLimit:{enabled:!0,max:100,window:60000,perChannel:!0,perUser:!0},loadManagement:{enabled:!0,maxConnections:1e4,maxSubscriptionsPerConnection:100,shedLoadThreshold:0.8},metrics:!0,autoScaling:{min:2,max:10,targetCPU:70}},monitoring:{enabled:!0,connectionThreshold:8000,errorThreshold:100}},highPerformance:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:!0},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:60,maxPayloadLength:8388608,backpressureLimit:2097152,closeOnBackpressureLimit:!0,sendPings:!0,perMessageDeflate:!0,instances:4,redis:{enabled:!0,useElastiCache:!0,keyPrefix:"rt:"},rateLimit:{enabled:!0,max:200,window:60000,perChannel:!0},loadManagement:{enabled:!0,maxConnections:25000,maxSubscriptionsPerConnection:50,shedLoadThreshold:0.7},metrics:{enabled:!0,path:"/metrics"},autoScaling:{min:4,max:20,targetCPU:60,targetConnections:20000}},monitoring:{enabled:!0,connectionThreshold:80000,errorThreshold:50,latencyThreshold:50}},chat:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:{enabled:!0,maxMembers:200,heartbeatInterval:20,inactivityTimeout:60}},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:300,maxPayloadLength:1048576,sendPings:!0,perMessageDeflate:!0,instances:2,redis:{enabled:!0,keyPrefix:"chat:"},rateLimit:{enabled:!0,max:60,window:60000,perChannel:!0},loadManagement:{enabled:!0,maxConnections:15000,maxSubscriptionsPerConnection:20},metrics:!0},keepAlive:!0,keepAliveInterval:25,idleTimeout:900},gaming:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:{enabled:!0,maxMembers:100,heartbeatInterval:10,inactivityTimeout:30}},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:30,maxPayloadLength:65536,backpressureLimit:524288,closeOnBackpressureLimit:!0,sendPings:!0,perMessageDeflate:!1,instances:4,redis:{enabled:!0,useElastiCache:!0},rateLimit:{enabled:!0,max:120,window:60000},loadManagement:{enabled:!0,maxConnections:5000,maxSubscriptionsPerConnection:10,shedLoadThreshold:0.6},metrics:!0,autoScaling:{min:4,max:16,targetCPU:50}},keepAlive:!0,keepAliveInterval:10,idleTimeout:60},single:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:!0},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:120,sendPings:!0,perMessageDeflate:!0,instances:1,rateLimit:{enabled:!0,max:100,window:60000},loadManagement:{enabled:!0,maxConnections:1e4},metrics:!0}}}},pg=".ts-cloud",gg="TS_CLOUD_STATE_DIR",Gt=null;function bd(n){Gt=n?.trim()||null}function vd(){return Boolean(process.env[gg]?.trim()||Gt)}function uo(){return process.env[gg]?.trim()||Gt||pg}function L(...n){return ht(uo(),...n)}function d(n,...i){let s=uo();return xt(s)?ht(s,...i):ht(n,s,...i)}function Td(n,i=process.cwd()){let s=(c,l)=>{let u=cr(c,l);return u===""||!u.startsWith("..")&&!xt(u)},o=xt(n)?n:ht(i,n);return s(d(i),o)}function mg(n){let i=n.infrastructure?.compute!=null,s=Object.values(n.environments??{}).some((o)=>o?.app!=null);return{server:i,serverless:s}}function M(n){if(n.mode==="server"||n.mode==="serverless")return n.mode;let{serverless:i}=mg(n);return i?"serverless":"server"}function wd(n){let{server:i,serverless:s}=mg(n);if(i&&s)return"A project cannot be both a server and a serverless deployment. Found `infrastructure.compute` (server) AND `environments.<env>.app` (serverless Lambda). Keep one: remove `infrastructure.compute` for a serverless app, or remove `environments.<env>.app` for a server.";if(n.mode==="server"&&s&&!i)return"Config sets `mode: 'server'` but declares a serverless app (`environments.<env>.app`). Remove the app or change the mode.";if(n.mode==="serverless"&&i&&!s)return"Config sets `mode: 'serverless'` but declares a server (`infrastructure.compute`). Remove the compute block or change the mode.";return null}function p(n){return n.infrastructure?.appDatabase??n.infrastructure?.compute?.database}function lr(n){return typeof n==="object"&&n!==null?n:{}}function aA(n){return n===!0||typeof n==="object"&&n!==null}function ur(n,i){let s=i?n.environments?.[i]:void 0;if(s?.domain)return s.domain;let o=Object.values(n.sites??{}),c=n.sites?.main?.domain??o.find((l)=>l.domain)?.domain;if(c)return c;return`${n.project?.slug??"app"}.local`}function dr(n){let i=n.indexOf(".");return i>0?n.slice(i+1):void 0}function Pi(n,i={}){let s=n.infrastructure?.compute?.managedServices?.mail,o=lr(s),c=i.environmentType??(i.environment?n.environments?.[i.environment]?.type:void 0),l=o.mode??(c==="production"?"server":"catcher"),u=l==="server",h=ur(n,i.environment),f=o.hostname??(u?`mail.${h}`:"localhost"),S=o.ports??{},b=u?{smtp:S.smtp??25,submission:S.submission??587,submissions:S.submissions??465,imap:S.imap??143,imaps:S.imaps??993,webmail:S.webmail??8080,managesieve:S.managesieve}:{smtp:S.smtp??1025,submission:S.submission,submissions:S.submissions,imap:S.imap,imaps:S.imaps,webmail:S.webmail??8025,managesieve:S.managesieve},A=o.tls??{},v=A.enabled??u,w=!!(A.certPath&&A.keyPath),E=(o.accounts??[]).map((K)=>({address:K.address,password:K.password})),P=typeof o.dkim==="object"&&o.dkim!==null?o.dkim:{},R=o.dkim===!1?!1:o.dkim===!0||u,D=typeof o.webmail==="object"&&o.webmail!==null?o.webmail:{},x=o.webmail===!1?!1:D.enabled??!0,I=o.spam??{},_=o.delivery??(u?"direct":"none"),B=o.expose??u,W=dr(f),J=[...new Set([f,...W?[W]:[],...o.domains??[]])];return{enabled:aA(s),mode:l,version:o.version,hostname:f,domains:J,ports:b,tls:{enabled:v,acme:v&&!w&&(A.acme??!0),certPath:A.certPath,keyPath:A.keyPath,requireForAuth:A.requireForAuth??(v&&u),acmeEmail:A.acmeEmail??E[0]?.address},dkim:{enabled:R,selector:P.selector??"default",rotate:P.rotate??!1,rotateIntervalDays:P.rotateIntervalDays??90},webmail:{enabled:x,port:D.port??b.webmail,domain:D.domain},delivery:_,sesRegion:o.sesRegion??"us-east-1",accounts:E,storagePath:o.storagePath??"/var/lib/mail",maxMessageSize:o.maxMessageSize??26214400,spam:{enabled:I.enabled??u,enforce:I.enforce??!1,junkScore:I.junkScore??5,rejectScore:I.rejectScore??12,dnsbl:I.dnsbl??u,greylist:I.greylist??!1},webhookUrl:o.webhookUrl,expose:B,bindAddress:B?"0.0.0.0":"127.0.0.1"}}function Rd(n){if(!n.enabled||!n.expose)return[];let i=[n.ports.smtp,n.ports.submission,n.ports.submissions,n.ports.imap,n.ports.imaps,n.ports.managesieve].filter((s)=>typeof s==="number");if(n.webmail.enabled&&!n.webmail.domain)i.push(n.webmail.port);return[...new Set(i)].sort((s,o)=>s-o)}function Dd(n){if(!n.enabled)return{};let i=n.ports.submission??n.ports.smtp,s={MAIL_MAILER:"smtp",MAIL_HOST:"127.0.0.1",MAIL_PORT:String(i)};if(n.mode==="server"){s.MAIL_ENCRYPTION=n.tls.enabled?"tls":"null";let o=n.accounts[0];if(o)s.MAIL_USERNAME=o.address,s.MAIL_PASSWORD=o.password}else s.MAIL_ENCRYPTION="null",s.MAIL_USERNAME="null",s.MAIL_PASSWORD="null";return s}function ge(n){if(n.cloud?.provider)return n.cloud.provider;if(n.ssh?.hosts?.length)return"ssh";if(n.hetzner?.apiToken)return"hetzner";return"aws"}class Pd{template;constructor(n){this.template={AWSTemplateFormatVersion:"2010-09-09",Description:n,Resources:{}}}addResource(n,i){return this.template.Resources[n]=i,this}addResources(n){return Object.assign(this.template.Resources,n),this}addParameter(n,i){if(!this.template.Parameters)this.template.Parameters={};return this.template.Parameters[n]=i,this}addOutput(n,i){if(!this.template.Outputs)this.template.Outputs={};return this.template.Outputs[n]=i,this}addMetadata(n,i){if(!this.template.Metadata)this.template.Metadata={};return this.template.Metadata[n]=i,this}hasResource(n){return n in this.template.Resources}getResources(){return this.template.Resources}build(){return this.template}toJSON(n=!0){return JSON.stringify(this.template,null,n?2:0)}toYAML(){return this.convertToYAML(this.template)}convertToYAML(n,i=0){let s=" ".repeat(i),o="";for(let[c,l]of Object.entries(n)){if(l===null||l===void 0)continue;if(typeof l==="object"&&!Array.isArray(l))o+=`${s}${c}:
|
|
13
|
+
`}function Ca(n){return Object.keys(n).sort().map((i)=>i.toLowerCase()).join(";")}function Ct(n){let i=[];return n.forEach((s,o)=>{i.push([Ot(o),Ot(s)])}),i.sort((s,o)=>{if(s[0]<o[0])return-1;if(s[0]>o[0])return 1;if(s[1]<o[1])return-1;if(s[1]>o[1])return 1;return 0}),i.map(([s,o])=>`${s}=${o}`).join("&")}function vt(n){return n.split("/").map((i)=>Ot(i)).join("/")}function Ot(n){return encodeURIComponent(n).replace(/[!'()*]/g,(i)=>`%${i.charCodeAt(0).toString(16).toUpperCase()}`)}function Xe(n){if(!_e)throw Error("Synchronous hash not available in browser. Use signRequestAsync() instead.");return _e.createHash("sha256").update(n,"utf8").digest("hex")}function Ve(n,i){if(!_e)throw Error("Synchronous hmac not available in browser. Use signRequestAsync() instead.");return _e.createHmac("sha256",n).update(i,"utf8").digest()}async function mt(n){let i=new TextEncoder().encode(n),s=await crypto.subtle.digest("SHA-256",i);return va(new Uint8Array(s))}async function je(n,i){let s=new TextEncoder,o=typeof n==="string"?s.encode(n):n,c=s.encode(i),l=await crypto.subtle.importKey("raw",o.buffer,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),u=await crypto.subtle.sign("HMAC",l,c.buffer);return new Uint8Array(u)}function va(n){return Array.from(n).map((i)=>i.toString(16).padStart(2,"0")).join("")}function Ta(n,i,s,o,c,l){let u=`${n}:${i}:${s}:${o}`,h=l.get(u);if(!h){let f=Ve(`AWS4${n}`,i),S=Ve(f,s),b=Ve(S,o);if(h=Ve(b,"aws4_request"),l.size>=Pa){let A=l.keys().next().value;if(A)l.delete(A)}l.set(u,h)}return Ve(h,c).toString("hex")}async function wa(n,i,s,o,c,l){let u=`${n}:${i}:${s}:${o}`,h=l.get(u);if(!h){let S=await je(`AWS4${n}`,i),b=await je(S,s),A=await je(b,o);if(h=await je(A,"aws4_request"),l.size>=Pa){let v=l.keys().next().value;if(v)l.delete(v)}l.set(u,h)}let f=await je(h,c);return va(f)}function Ea(n,i){return i.includes(n)}function pt(n,i,s){let o=i*Math.pow(2,n),c=Math.random()*0.3*o;return Math.min(o+c,s)}function gt(n){return new Promise((i)=>setTimeout(i,n))}async function oA(n,i){let{maxRetries:s=3,initialDelayMs:o=100,maxDelayMs:c=5000,retryableStatusCodes:l=[429,500,502,503,504],timeoutMs:u=30000}=i??{},h,f;for(let S=0;S<=s;S++){let b=x(n),A={method:b.method,headers:b.headers};if(b.body)A.body=b.body;let v=new AbortController,w=setTimeout(()=>v.abort(),u);A.signal=v.signal;try{let E=await fetch(b.url,A);if(clearTimeout(w),f=E,E.ok)return E;if(S<s&&Ea(E.status,l)){let R=pt(S,o,c);await gt(R);continue}let P=await E.text();throw Error(`AWS API request failed (${E.status}): ${P}`)}catch(E){if(clearTimeout(w),h=E,E instanceof Error&&E.name==="AbortError")h=Error(`Request timed out after ${u}ms`);if(S<s&&!(E instanceof Error&&E.message.includes("AWS API request failed"))){let P=pt(S,o,c);await gt(P);continue}throw h}}throw h??Error("Request failed after retries")}async function hI(n){return oA(n,{maxRetries:0})}async function fI(n,i){let{maxRetries:s=3,initialDelayMs:o=100,maxDelayMs:c=5000,retryableStatusCodes:l=[429,500,502,503,504],timeoutMs:u=30000}=i??{},h;for(let f=0;f<=s;f++){let S=await ug(n),b={method:S.method,headers:S.headers};if(S.body)b.body=S.body;let A=new AbortController,v=setTimeout(()=>A.abort(),u);b.signal=A.signal;try{let w=await fetch(S.url,b);if(clearTimeout(v),w.ok)return w;if(f<s&&Ea(w.status,l)){let P=pt(f,o,c);await gt(P);continue}let E=await w.text();throw Error(`AWS API request failed (${w.status}): ${E}`)}catch(w){if(clearTimeout(v),h=w,w instanceof Error&&w.name==="AbortError")h=Error(`Request timed out after ${u}ms`);if(f<s&&!(w instanceof Error&&w.message.includes("AWS API request failed"))){let E=pt(f,o,c);await gt(E);continue}throw h}}throw h??Error("Request failed after retries")}async function yI(n){let i=await n.text(),s={},o=/<(\w+)>([^<]+)<\/\1>/g,c;while((c=o.exec(i))!==null){let[,l,u]=c;s[l]=u}return s}async function II(n){return await n.json()}function SI(){Le.clear()}function CI(){return Le.size}function EI(){return _e!==void 0}function bI(){return typeof crypto<"u"&&typeof crypto.subtle<"u"}var _e,Le,Pa=100,Ia,rt=nr(async()=>{try{_e=await import("node:crypto")}catch{}Le=new Map,Ia={appstream2:"appstream",cloudhsmv2:"cloudhsm",email:"ses",marketplace:"aws-marketplace",mobile:"AWSMobileHubService",pinpoint:"mobiletargeting",queue:"sqs","git-codecommit":"codecommit","mturk-requester-sandbox":"mturk-requester","personalize-runtime":"personalize"}}),vI={backgroundJobs:{visibilityTimeout:120,messageRetentionPeriod:604800,deadLetterQueue:!0,maxReceiveCount:3,encrypted:!0},fifo:{fifo:!0,contentBasedDeduplication:!0,visibilityTimeout:30,encrypted:!0},highThroughput:{visibilityTimeout:30,receiveMessageWaitTime:20,encrypted:!0},delayed:{delaySeconds:60,visibilityTimeout:60,encrypted:!0},longRunning:{visibilityTimeout:900,messageRetentionPeriod:1209600,deadLetterQueue:!0,maxReceiveCount:2,encrypted:!0},monitored:{visibilityTimeout:60,messageRetentionPeriod:604800,deadLetterQueue:!0,maxReceiveCount:3,encrypted:!0,alarms:{enabled:!0,queueDepthThreshold:1000,messageAgeThreshold:3600,dlqAlarm:!0}},lambdaOptimized:{visibilityTimeout:360,receiveMessageWaitTime:20,deadLetterQueue:!0,maxReceiveCount:3,encrypted:!0},fanOut:{visibilityTimeout:30,receiveMessageWaitTime:20,encrypted:!0}},TI={serverless:{development:{enabled:!0,mode:"serverless",channels:{public:!0,private:!0,presence:!0},storage:{type:"dynamodb",dynamodb:{billingMode:"PAY_PER_REQUEST"}},scaling:{maxConnections:1000,handlerMemory:128}},production:{enabled:!0,mode:"serverless",channels:{public:!0,private:!0,presence:{enabled:!0,maxMembers:100,heartbeatInterval:30,inactivityTimeout:60}},storage:{type:"dynamodb",dynamodb:{billingMode:"PAY_PER_REQUEST",pointInTimeRecovery:!0,connectionTTL:86400}},scaling:{maxConnections:50000,messagesPerSecond:5000,handlerMemory:256,handlerTimeout:30},monitoring:{enabled:!0,connectionThreshold:40000,errorThreshold:100,latencyThreshold:500},keepAlive:!0,keepAliveInterval:30,idleTimeout:600},notifications:{enabled:!0,mode:"serverless",channels:{public:!1,private:!0,presence:!1},storage:{type:"dynamodb",dynamodb:{billingMode:"PAY_PER_REQUEST"}},scaling:{maxConnections:50000,messagesPerSecond:2000,handlerMemory:128},keepAlive:!0,keepAliveInterval:60,idleTimeout:1800}},server:{development:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:!0},server:{host:"0.0.0.0",port:6001,scheme:"ws",driver:"bun",idleTimeout:120,perMessageDeflate:!1,metrics:!1}},production:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:!0},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:120,maxPayloadLength:16777216,backpressureLimit:1048576,sendPings:!0,perMessageDeflate:!0,instances:2,redis:{enabled:!0,keyPrefix:"broadcasting:"},rateLimit:{enabled:!0,max:100,window:60000,perChannel:!0,perUser:!0},loadManagement:{enabled:!0,maxConnections:1e4,maxSubscriptionsPerConnection:100,shedLoadThreshold:0.8},metrics:!0,autoScaling:{min:2,max:10,targetCPU:70}},monitoring:{enabled:!0,connectionThreshold:8000,errorThreshold:100}},highPerformance:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:!0},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:60,maxPayloadLength:8388608,backpressureLimit:2097152,closeOnBackpressureLimit:!0,sendPings:!0,perMessageDeflate:!0,instances:4,redis:{enabled:!0,useElastiCache:!0,keyPrefix:"rt:"},rateLimit:{enabled:!0,max:200,window:60000,perChannel:!0},loadManagement:{enabled:!0,maxConnections:25000,maxSubscriptionsPerConnection:50,shedLoadThreshold:0.7},metrics:{enabled:!0,path:"/metrics"},autoScaling:{min:4,max:20,targetCPU:60,targetConnections:20000}},monitoring:{enabled:!0,connectionThreshold:80000,errorThreshold:50,latencyThreshold:50}},chat:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:{enabled:!0,maxMembers:200,heartbeatInterval:20,inactivityTimeout:60}},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:300,maxPayloadLength:1048576,sendPings:!0,perMessageDeflate:!0,instances:2,redis:{enabled:!0,keyPrefix:"chat:"},rateLimit:{enabled:!0,max:60,window:60000,perChannel:!0},loadManagement:{enabled:!0,maxConnections:15000,maxSubscriptionsPerConnection:20},metrics:!0},keepAlive:!0,keepAliveInterval:25,idleTimeout:900},gaming:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:{enabled:!0,maxMembers:100,heartbeatInterval:10,inactivityTimeout:30}},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:30,maxPayloadLength:65536,backpressureLimit:524288,closeOnBackpressureLimit:!0,sendPings:!0,perMessageDeflate:!1,instances:4,redis:{enabled:!0,useElastiCache:!0},rateLimit:{enabled:!0,max:120,window:60000},loadManagement:{enabled:!0,maxConnections:5000,maxSubscriptionsPerConnection:10,shedLoadThreshold:0.6},metrics:!0,autoScaling:{min:4,max:16,targetCPU:50}},keepAlive:!0,keepAliveInterval:10,idleTimeout:60},single:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:!0},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:120,sendPings:!0,perMessageDeflate:!0,instances:1,rateLimit:{enabled:!0,max:100,window:60000},loadManagement:{enabled:!0,maxConnections:1e4},metrics:!0}}}},pg=".ts-cloud",gg="TS_CLOUD_STATE_DIR",Gt=null;function bd(n){Gt=n?.trim()||null}function vd(){return Boolean(process.env[gg]?.trim()||Gt)}function uo(){return process.env[gg]?.trim()||Gt||pg}function L(...n){return ht(uo(),...n)}function d(n,...i){let s=uo();return xt(s)?ht(s,...i):ht(n,s,...i)}function Td(n,i=process.cwd()){let s=(c,l)=>{let u=cr(c,l);return u===""||!u.startsWith("..")&&!xt(u)},o=xt(n)?n:ht(i,n);return s(d(i),o)}function mg(n){let i=n.infrastructure?.compute!=null,s=Object.values(n.environments??{}).some((o)=>o?.app!=null);return{server:i,serverless:s}}function M(n){if(n.mode==="server"||n.mode==="serverless")return n.mode;let{serverless:i}=mg(n);return i?"serverless":"server"}function wd(n){let{server:i,serverless:s}=mg(n);if(i&&s)return"A project cannot be both a server and a serverless deployment. Found `infrastructure.compute` (server) AND `environments.<env>.app` (serverless Lambda). Keep one: remove `infrastructure.compute` for a serverless app, or remove `environments.<env>.app` for a server.";if(n.mode==="server"&&s&&!i)return"Config sets `mode: 'server'` but declares a serverless app (`environments.<env>.app`). Remove the app or change the mode.";if(n.mode==="serverless"&&i&&!s)return"Config sets `mode: 'serverless'` but declares a server (`infrastructure.compute`). Remove the compute block or change the mode.";return null}function p(n){return n.infrastructure?.appDatabase??n.infrastructure?.compute?.database}function lr(n){return typeof n==="object"&&n!==null?n:{}}function aA(n){return n===!0||typeof n==="object"&&n!==null}function ur(n,i){let s=i?n.environments?.[i]:void 0;if(s?.domain)return s.domain;let o=Object.values(n.sites??{}),c=n.sites?.main?.domain??o.find((l)=>l.domain)?.domain;if(c)return c;return`${n.project?.slug??"app"}.local`}function dr(n){let i=n.indexOf(".");return i>0?n.slice(i+1):void 0}function Pi(n,i={}){let s=n.infrastructure?.compute?.managedServices?.mail,o=lr(s),c=i.environmentType??(i.environment?n.environments?.[i.environment]?.type:void 0),l=o.mode??(c==="production"?"server":"catcher"),u=l==="server",h=ur(n,i.environment),f=o.hostname??(u?`mail.${h}`:"localhost"),S=o.ports??{},b=u?{smtp:S.smtp??25,submission:S.submission??587,submissions:S.submissions??465,imap:S.imap??143,imaps:S.imaps??993,webmail:S.webmail??8080,managesieve:S.managesieve}:{smtp:S.smtp??1025,submission:S.submission,submissions:S.submissions,imap:S.imap,imaps:S.imaps,webmail:S.webmail??8025,managesieve:S.managesieve},A=o.tls??{},v=A.enabled??u,w=!!(A.certPath&&A.keyPath),E=(o.accounts??[]).map((K)=>({address:K.address,password:K.password})),P=typeof o.dkim==="object"&&o.dkim!==null?o.dkim:{},R=o.dkim===!1?!1:o.dkim===!0||u,D=typeof o.webmail==="object"&&o.webmail!==null?o.webmail:{},O=o.webmail===!1?!1:D.enabled??!0,I=o.spam??{},_=o.delivery??(u?"direct":"none"),B=o.expose??u,W=dr(f),J=[...new Set([f,...W?[W]:[],...o.domains??[]])];return{enabled:aA(s),mode:l,version:o.version,hostname:f,domains:J,ports:b,tls:{enabled:v,acme:v&&!w&&(A.acme??!0),certPath:A.certPath,keyPath:A.keyPath,requireForAuth:A.requireForAuth??(v&&u),acmeEmail:A.acmeEmail??E[0]?.address},dkim:{enabled:R,selector:P.selector??"default",rotate:P.rotate??!1,rotateIntervalDays:P.rotateIntervalDays??90},webmail:{enabled:O,port:D.port??b.webmail,domain:D.domain},delivery:_,sesRegion:o.sesRegion??"us-east-1",accounts:E,storagePath:o.storagePath??"/var/lib/mail",maxMessageSize:o.maxMessageSize??26214400,spam:{enabled:I.enabled??u,enforce:I.enforce??!1,junkScore:I.junkScore??5,rejectScore:I.rejectScore??12,dnsbl:I.dnsbl??u,greylist:I.greylist??!1},webhookUrl:o.webhookUrl,expose:B,bindAddress:B?"0.0.0.0":"127.0.0.1"}}function Rd(n){if(!n.enabled||!n.expose)return[];let i=[n.ports.smtp,n.ports.submission,n.ports.submissions,n.ports.imap,n.ports.imaps,n.ports.managesieve].filter((s)=>typeof s==="number");if(n.webmail.enabled&&!n.webmail.domain)i.push(n.webmail.port);return[...new Set(i)].sort((s,o)=>s-o)}function Dd(n){if(!n.enabled)return{};let i=n.ports.submission??n.ports.smtp,s={MAIL_MAILER:"smtp",MAIL_HOST:"127.0.0.1",MAIL_PORT:String(i)};if(n.mode==="server"){s.MAIL_ENCRYPTION=n.tls.enabled?"tls":"null";let o=n.accounts[0];if(o)s.MAIL_USERNAME=o.address,s.MAIL_PASSWORD=o.password}else s.MAIL_ENCRYPTION="null",s.MAIL_USERNAME="null",s.MAIL_PASSWORD="null";return s}function ge(n){if(n.cloud?.provider)return n.cloud.provider;if(n.ssh?.hosts?.length)return"ssh";if(n.hetzner?.apiToken)return"hetzner";return"aws"}class Pd{template;constructor(n){this.template={AWSTemplateFormatVersion:"2010-09-09",Description:n,Resources:{}}}addResource(n,i){return this.template.Resources[n]=i,this}addResources(n){return Object.assign(this.template.Resources,n),this}addParameter(n,i){if(!this.template.Parameters)this.template.Parameters={};return this.template.Parameters[n]=i,this}addOutput(n,i){if(!this.template.Outputs)this.template.Outputs={};return this.template.Outputs[n]=i,this}addMetadata(n,i){if(!this.template.Metadata)this.template.Metadata={};return this.template.Metadata[n]=i,this}hasResource(n){return n in this.template.Resources}getResources(){return this.template.Resources}build(){return this.template}toJSON(n=!0){return JSON.stringify(this.template,null,n?2:0)}toYAML(){return this.convertToYAML(this.template)}convertToYAML(n,i=0){let s=" ".repeat(i),o="";for(let[c,l]of Object.entries(n)){if(l===null||l===void 0)continue;if(typeof l==="object"&&!Array.isArray(l))o+=`${s}${c}:
|
|
14
14
|
${this.convertToYAML(l,i+1)}`;else if(Array.isArray(l)){o+=`${s}${c}:
|
|
15
15
|
`;for(let u of l)if(typeof u==="object")o+=`${s} -
|
|
16
16
|
${this.convertToYAML(u,i+2)}`;else o+=`${s} - ${u}
|
|
17
17
|
`}else o+=`${s}${c}: ${l}
|
|
18
|
-
`}return o}}var k={Ref:(n)=>({Ref:n}),GetAtt:(n,i)=>({"Fn::GetAtt":[n,i]}),Sub:(n,i)=>{if(i)return{"Fn::Sub":[n,i]};return{"Fn::Sub":n}},Join:(n,i)=>({"Fn::Join":[n,i]}),Select:(n,i)=>({"Fn::Select":[n,i]}),Split:(n,i)=>({"Fn::Split":[n,i]}),GetAZs:(n="")=>({"Fn::GetAZs":n}),ImportValue:(n)=>({"Fn::ImportValue":n}),If:(n,i,s)=>({"Fn::If":[n,i,s]}),Equals:(n,i)=>({"Fn::Equals":[n,i]}),And:(...n)=>({"Fn::And":n}),Or:(...n)=>({"Fn::Or":n}),Not:(n)=>({"Fn::Not":[n]}),Base64:(n)=>({"Fn::Base64":n})},wI={AccountId:{Ref:"AWS::AccountId"},Region:{Ref:"AWS::Region"},StackId:{Ref:"AWS::StackId"},StackName:{Ref:"AWS::StackName"},NotificationARNs:{Ref:"AWS::NotificationARNs"},Partition:{Ref:"AWS::Partition"},URLSuffix:{Ref:"AWS::URLSuffix"},NoValue:{Ref:"AWS::NoValue"}};function r(n){let{slug:i,environment:s,resourceType:o,timestamp:c,suffix:l}=n,u=[i,s,o];if(c)u.push(c);if(l)u.push(l);return u.join("-")}function t(n){return n.split("-").map((i)=>i.charAt(0).toUpperCase()+i.slice(1)).join("")}function RI(){return Date.now().toString()}function DI(n){return n.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/^-+|-+$/g,"").replace(/-+/g,"-")}function g(n,i){return n.project.stackName??`${n.project.slug}-${i}`}function PI(n,i,s,o){return s.stackName??`${n.project.slug}-${o}-${i}-site`}function NI(n,i){return`${n.project.slug}-${i}`}function kI(n,i,s,o){if(o)return o;if(s==="main")return`${n}-${i}-site`;return`${n}-${i}-${s}`}function BI(n,i,s,o){return o??`${n}-${i}-${s}`}function _I(n,i){return`${n}-${i}-deploy`}function qt(n,i){return`${n.project.slug}-${i}-app`}function Nd(n,i){return`${n}-${i}-deployments`}function po(n,i){return`${n}-${i}-assets`}class cA{nodes=new Map;addResource(n,i){let s=this.extractDependencies(i);this.nodes.set(n,{logicalId:n,resource:i,dependencies:s})}extractDependencies(n){let i=new Set;if(n.DependsOn)if(Array.isArray(n.DependsOn))n.DependsOn.forEach((s)=>i.add(s));else i.add(n.DependsOn);return this.findReferences(n.Properties||{},i),i}findReferences(n,i){if(!n||typeof n!=="object")return;if("Ref"in n&&typeof n.Ref==="string"){if(!n.Ref.startsWith("AWS::"))i.add(n.Ref)}if("Fn::GetAtt"in n&&Array.isArray(n["Fn::GetAtt"]))i.add(n["Fn::GetAtt"][0]);for(let s of Object.values(n))if(typeof s==="object")this.findReferences(s,i)}topologicalSort(){let n=[],i=new Set,s=new Set,o=(c)=>{if(i.has(c))return;if(s.has(c))throw Error(`Circular dependency detected: ${c}`);s.add(c);let l=this.nodes.get(c);if(l)for(let u of l.dependencies)o(u);s.delete(c),i.add(c),n.push(c)};for(let c of this.nodes.keys())o(c);return n}validate(){for(let[n,i]of this.nodes.entries())for(let s of i.dependencies)if(!this.nodes.has(s))throw Error(`Resource "${n}" depends on "${s}" which does not exist`)}getDependents(n){let i=[];for(let[s,o]of this.nodes.entries())if(o.dependencies.has(n))i.push(s);return i}}function
|
|
18
|
+
`}return o}}var k={Ref:(n)=>({Ref:n}),GetAtt:(n,i)=>({"Fn::GetAtt":[n,i]}),Sub:(n,i)=>{if(i)return{"Fn::Sub":[n,i]};return{"Fn::Sub":n}},Join:(n,i)=>({"Fn::Join":[n,i]}),Select:(n,i)=>({"Fn::Select":[n,i]}),Split:(n,i)=>({"Fn::Split":[n,i]}),GetAZs:(n="")=>({"Fn::GetAZs":n}),ImportValue:(n)=>({"Fn::ImportValue":n}),If:(n,i,s)=>({"Fn::If":[n,i,s]}),Equals:(n,i)=>({"Fn::Equals":[n,i]}),And:(...n)=>({"Fn::And":n}),Or:(...n)=>({"Fn::Or":n}),Not:(n)=>({"Fn::Not":[n]}),Base64:(n)=>({"Fn::Base64":n})},wI={AccountId:{Ref:"AWS::AccountId"},Region:{Ref:"AWS::Region"},StackId:{Ref:"AWS::StackId"},StackName:{Ref:"AWS::StackName"},NotificationARNs:{Ref:"AWS::NotificationARNs"},Partition:{Ref:"AWS::Partition"},URLSuffix:{Ref:"AWS::URLSuffix"},NoValue:{Ref:"AWS::NoValue"}};function r(n){let{slug:i,environment:s,resourceType:o,timestamp:c,suffix:l}=n,u=[i,s,o];if(c)u.push(c);if(l)u.push(l);return u.join("-")}function t(n){return n.split("-").map((i)=>i.charAt(0).toUpperCase()+i.slice(1)).join("")}function RI(){return Date.now().toString()}function DI(n){return n.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/^-+|-+$/g,"").replace(/-+/g,"-")}function g(n,i){return n.project.stackName??`${n.project.slug}-${i}`}function PI(n,i,s,o){return s.stackName??`${n.project.slug}-${o}-${i}-site`}function NI(n,i){return`${n.project.slug}-${i}`}function kI(n,i,s,o){if(o)return o;if(s==="main")return`${n}-${i}-site`;return`${n}-${i}-${s}`}function BI(n,i,s,o){return o??`${n}-${i}-${s}`}function _I(n,i){return`${n}-${i}-deploy`}function qt(n,i){return`${n.project.slug}-${i}-app`}function Nd(n,i){return`${n}-${i}-deployments`}function po(n,i){return`${n}-${i}-assets`}class cA{nodes=new Map;addResource(n,i){let s=this.extractDependencies(i);this.nodes.set(n,{logicalId:n,resource:i,dependencies:s})}extractDependencies(n){let i=new Set;if(n.DependsOn)if(Array.isArray(n.DependsOn))n.DependsOn.forEach((s)=>i.add(s));else i.add(n.DependsOn);return this.findReferences(n.Properties||{},i),i}findReferences(n,i){if(!n||typeof n!=="object")return;if("Ref"in n&&typeof n.Ref==="string"){if(!n.Ref.startsWith("AWS::"))i.add(n.Ref)}if("Fn::GetAtt"in n&&Array.isArray(n["Fn::GetAtt"]))i.add(n["Fn::GetAtt"][0]);for(let s of Object.values(n))if(typeof s==="object")this.findReferences(s,i)}topologicalSort(){let n=[],i=new Set,s=new Set,o=(c)=>{if(i.has(c))return;if(s.has(c))throw Error(`Circular dependency detected: ${c}`);s.add(c);let l=this.nodes.get(c);if(l)for(let u of l.dependencies)o(u);s.delete(c),i.add(c),n.push(c)};for(let c of this.nodes.keys())o(c);return n}validate(){for(let[n,i]of this.nodes.entries())for(let s of i.dependencies)if(!this.nodes.has(s))throw Error(`Resource "${n}" depends on "${s}" which does not exist`)}getDependents(n){let i=[];for(let[s,o]of this.nodes.entries())if(o.dependencies.has(n))i.push(s);return i}}function OI(n,i){let s=[],o=[],c=[],l=[],u=[],h=n.Resources||{},f=i.Resources||{},S=new Set([...Object.keys(h),...Object.keys(f)]);for(let A of S){let v=h[A],w=f[A];if(!v&&w)s.push({logicalId:A,action:"add",resourceType:w.Type});else if(v&&!w)o.push({logicalId:A,action:"remove",resourceType:v.Type});else if(v&&w)if(v.Type!==w.Type)l.push({logicalId:A,action:"replace",resourceType:w.Type,reason:`Type changed from ${v.Type} to ${w.Type}`});else{let E=Ra(v.Properties||{},w.Properties||{});if(E.length>0)if(mr(v.Type,E))l.push({logicalId:A,action:"replace",resourceType:w.Type,changes:E,reason:"Property changes require replacement"});else c.push({logicalId:A,action:"update",resourceType:w.Type,changes:E});else u.push(A)}}let b=pr([...o,...l,...c]);return{added:s,removed:o,updated:c,replaced:l,unchanged:u,summary:{totalChanges:s.length+o.length+c.length+l.length,requiresReplacement:l.length>0,dangerousChanges:b}}}function Ra(n,i,s=""){let o=[],c=new Set([...Object.keys(n),...Object.keys(i)]);for(let l of c){let u=s?`${s}.${l}`:l,h=n[l],f=i[l];if(h===void 0&&f!==void 0)o.push({path:u,oldValue:void 0,newValue:f});else if(h!==void 0&&f===void 0)o.push({path:u,oldValue:h,newValue:void 0});else if(typeof h!==typeof f)o.push({path:u,oldValue:h,newValue:f});else if(typeof h==="object"&&h!==null)if(Array.isArray(h)&&Array.isArray(f)){if(JSON.stringify(h)!==JSON.stringify(f))o.push({path:u,oldValue:h,newValue:f})}else if(!Array.isArray(h)&&!Array.isArray(f)){let S=Ra(h,f,u);o.push(...S)}else o.push({path:u,oldValue:h,newValue:f});else if(h!==f)o.push({path:u,oldValue:h,newValue:f})}return o}function mr(n,i){let s={"AWS::S3::Bucket":new Set(["BucketName"]),"AWS::DynamoDB::Table":new Set(["TableName","KeySchema"]),"AWS::RDS::DBInstance":new Set(["DBInstanceIdentifier","DBName","Engine"]),"AWS::Lambda::Function":new Set(["FunctionName"]),"AWS::EC2::Instance":new Set(["ImageId","InstanceType","KeyName"]),"AWS::ECS::TaskDefinition":new Set(["Family","ContainerDefinitions"]),"AWS::ElastiCache::CacheCluster":new Set(["CacheNodeType","Engine"]),"AWS::CloudFront::Distribution":new Set([]),"AWS::Route53::HostedZone":new Set(["Name"]),"AWS::IAM::Role":new Set(["RoleName","Path"]),"AWS::KMS::Key":new Set(["KeyPolicy"]),"AWS::Cognito::UserPool":new Set(["UserPoolName"]),"AWS::OpenSearchService::Domain":new Set(["DomainName"])}[n];if(!s)return!1;for(let o of i){let c=o.path.split(".")[0];if(s.has(c))return!0}return!1}function pr(n){let i=[];for(let s of n){if(s.action==="remove"&&(s.resourceType==="AWS::RDS::DBInstance"||s.resourceType==="AWS::DynamoDB::Table"||s.resourceType==="AWS::ElastiCache::CacheCluster"))i.push(`Removing ${s.resourceType} ${s.logicalId} - data loss risk!`);if(s.action==="replace"&&(s.resourceType==="AWS::RDS::DBInstance"||s.resourceType==="AWS::DynamoDB::Table"))i.push(`Replacing ${s.resourceType} ${s.logicalId} - data loss risk!`);if((s.action==="remove"||s.action==="replace")&&s.resourceType==="AWS::S3::Bucket")i.push(`${s.action==="remove"?"Removing":"Replacing"} S3 bucket ${s.logicalId} - data loss risk!`);if(s.action==="replace"&&s.resourceType==="AWS::EC2::Instance")i.push(`Replacing EC2 instance ${s.logicalId} - downtime expected`);if(s.action==="update"&&s.resourceType==="AWS::EC2::SecurityGroup")i.push(`Updating security group ${s.logicalId} - may affect connectivity`);if((s.action==="update"||s.action==="replace")&&(s.resourceType==="AWS::IAM::Role"||s.resourceType==="AWS::IAM::Policy"))i.push(`Modifying IAM ${s.resourceType.split("::")[2]} ${s.logicalId} - may affect permissions`)}return i}function xI(n){let i=[];if(i.push(`=== Stack Update Analysis ===
|
|
19
19
|
`),n.summary.totalChanges===0)return i.push(`No changes detected.
|
|
20
20
|
`),i.join(`
|
|
21
21
|
`);if(i.push(`Total changes: ${n.summary.totalChanges}`),i.push(`Requires replacement: ${n.summary.requiresReplacement?"Yes":"No"}
|
|
22
22
|
`),n.summary.dangerousChanges.length>0){i.push("⚠️ DANGEROUS CHANGES DETECTED:");for(let s of n.summary.dangerousChanges)i.push(` • ${s}`);i.push("")}if(n.added.length>0){i.push(`✅ Resources to Add (${n.added.length}):`);for(let s of n.added)i.push(` + ${s.logicalId} (${s.resourceType})`);i.push("")}if(n.removed.length>0){i.push(`❌ Resources to Remove (${n.removed.length}):`);for(let s of n.removed)i.push(` - ${s.logicalId} (${s.resourceType})`);i.push("")}if(n.replaced.length>0){i.push(`\uD83D\uDD04 Resources to Replace (${n.replaced.length}):`);for(let s of n.replaced){if(i.push(` ~ ${s.logicalId} (${s.resourceType})`),s.reason)i.push(` Reason: ${s.reason}`);if(s.changes){for(let o of s.changes.slice(0,3))i.push(` • ${o.path}: ${JSON.stringify(o.oldValue)} → ${JSON.stringify(o.newValue)}`);if(s.changes.length>3)i.push(` ... and ${s.changes.length-3} more changes`)}}i.push("")}if(n.updated.length>0){i.push(`\uD83D\uDCDD Resources to Update (${n.updated.length}):`);for(let s of n.updated)if(i.push(` ~ ${s.logicalId} (${s.resourceType})`),s.changes){for(let o of s.changes.slice(0,3))i.push(` • ${o.path}: ${JSON.stringify(o.oldValue)} → ${JSON.stringify(o.newValue)}`);if(s.changes.length>3)i.push(` ... and ${s.changes.length-3} more changes`)}i.push("")}if(n.unchanged.length>0)i.push(`⚪ Unchanged Resources (${n.unchanged.length})`);return i.join(`
|
|
23
|
-
`)}class Re{static createBucket(n){let{name:i,bucketName:s,slug:o,environment:c,public:l=!1,versioning:u=!1,website:h=!1,encryption:f=!0,intelligentTiering:S=!1,cors:b,lifecycleRules:A}=n,v=s??r({slug:o,environment:c,resourceType:"s3",suffix:i}),w=t(v),E={Type:"AWS::S3::Bucket",Properties:{BucketName:v}};if(f)E.Properties.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(u)E.Properties.VersioningConfiguration={Status:"Enabled"};if(h)E.Properties.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"error.html"};if(!l)E.Properties.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(b&&b.length>0)E.Properties.CorsConfiguration={CorsRules:b.map((R)=>({AllowedOrigins:R.allowedOrigins,AllowedMethods:R.allowedMethods,AllowedHeaders:R.allowedHeaders,MaxAge:R.maxAge}))};if(A&&A.length>0)E.Properties.LifecycleConfiguration={Rules:A.map((R)=>({Id:R.id,Status:R.enabled?"Enabled":"Disabled",ExpirationInDays:R.expirationDays,Transitions:R.transitions?.map((D)=>({TransitionInDays:D.days,StorageClass:D.storageClass}))}))};if(S&&A){let R={id:"IntelligentTieringRule",enabled:!0,transitions:[{days:0,storageClass:"INTELLIGENT_TIERING"}]};if(!E.Properties.LifecycleConfiguration)E.Properties.LifecycleConfiguration={Rules:[]};E.Properties.LifecycleConfiguration.Rules.push({Id:R.id,Status:"Enabled",Transitions:R.transitions?.map((D)=>({TransitionInDays:D.days,StorageClass:D.storageClass}))})}let P;if(l)P={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:k.Ref(w),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[k.Join("",[k.GetAtt(w,"Arn"),"/*"])]}]}}};return{bucket:E,bucketPolicy:P,logicalId:w}}static enableVersioning(n){if(!n.Properties)n.Properties={};return n.Properties.VersioningConfiguration={Status:"Enabled"},n}static enableWebsiteHosting(n,i="index.html",s="error.html"){if(!n.Properties)n.Properties={};return n.Properties.WebsiteConfiguration={IndexDocument:i,ErrorDocument:s},n}static setLifecycleRules(n,i){if(!n.Properties)n.Properties={};return n.Properties.LifecycleConfiguration={Rules:i.map((s)=>({Id:s.id,Status:s.enabled?"Enabled":"Disabled",ExpirationInDays:s.expirationDays,Transitions:s.transitions?.map((o)=>({TransitionInDays:o.days,StorageClass:o.storageClass}))}))},n}static enableIntelligentTiering(n){if(!n.Properties)n.Properties={};if(!n.Properties.LifecycleConfiguration)n.Properties.LifecycleConfiguration={Rules:[]};return n.Properties.LifecycleConfiguration.Rules.push({Id:"IntelligentTieringRule",Status:"Enabled",Transitions:[{TransitionInDays:0,StorageClass:"INTELLIGENT_TIERING"}]}),n}static addLambdaNotification(n,i){if(!n.Properties)n.Properties={};if(!n.Properties.NotificationConfiguration)n.Properties.NotificationConfiguration={};if(!n.Properties.NotificationConfiguration.LambdaConfigurations)n.Properties.NotificationConfiguration.LambdaConfigurations=[];let s={Event:i.events[0],Function:i.functionArn};if(i.filter)s.Filter={S3Key:{Rules:[...i.filter.prefix?[{Name:"prefix",Value:i.filter.prefix}]:[],...i.filter.suffix?[{Name:"suffix",Value:i.filter.suffix}]:[]]}};for(let o of i.events){let c={...s,Event:o};n.Properties.NotificationConfiguration.LambdaConfigurations.push(c)}return n}static Notifications={onObjectCreated:(n)=>({functionArn:n,events:["s3:ObjectCreated:*"]}),onObjectRemoved:(n)=>({functionArn:n,events:["s3:ObjectRemoved:*"]}),onImageUpload:(n,i)=>({functionArn:n,events:["s3:ObjectCreated:*"],filter:{prefix:i,suffix:".jpg"}}),onFileType:(n,i,s)=>({functionArn:n,events:["s3:ObjectCreated:*"],filter:{prefix:s,suffix:i}}),onFolderUpload:(n,i)=>({functionArn:n,events:["s3:ObjectCreated:*"],filter:{prefix:i.endsWith("/")?i:`${i}/`}})};static createBackupPlan(n){let{name:i,slug:s,environment:o,bucketLogicalIds:c,retentionDays:l,schedule:u="cron(0 5 * * ? *)",vaultName:h,enableContinuousBackup:f=!1,moveToColdStorageAfterDays:S}=n,b=h||r({slug:s,environment:o,resourceType:"backup-vault",suffix:i}),A=t(b),v={Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:b}},w=r({slug:s,environment:o,resourceType:"backup-role",suffix:i}),E=t(w),P={Type:"AWS::IAM::Role",Properties:{RoleName:w,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:s,environment:o,resourceType:"backup-plan",suffix:i}),D=t(R),x={DeleteAfterDays:l};if(S&&S<l)x.MoveToColdStorageAfterDays=S;let I={Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:R,BackupPlanRule:[{RuleName:`${i}-daily-backup`,TargetBackupVault:k.Ref(A),ScheduleExpression:u,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:x,EnableContinuousBackup:f}]}}},_=r({slug:s,environment:o,resourceType:"backup-selection",suffix:i}),B=t(_),W=c.map((K)=>k.GetAtt(K,"Arn")),J={Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:k.Ref(D),BackupSelection:{SelectionName:_,IamRoleArn:k.GetAtt(E,"Arn"),Resources:W}}};return{vault:v,plan:I,selection:J,role:P,vaultLogicalId:A,planLogicalId:D,selectionLogicalId:B,roleLogicalId:E}}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(n){let{slug:i,environment:s,sourceDomain:o,targetDomain:c,protocol:l="https"}=n,u=r({slug:i,environment:s,resourceType:"s3",suffix:"www-redirect"}),h=t(u),f={Type:"AWS::S3::Bucket",Properties:{BucketName:o,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:c,Protocol:l}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1}}},S={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:k.Ref(h),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[k.Join("",[k.GetAtt(h,"Arn"),"/*"])]}]}}};return{bucket:f,bucketPolicy:S,logicalId:h}}static createDocsBucket(n){let{slug:i,environment:s,domain:o}=n,c=o||r({slug:i,environment:s,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(n){let{slug:i,environment:s}=n,o=r({slug:i,environment:s,resourceType:"s3",suffix:"email"}),c=t(o),l={Type:"AWS::S3::Bucket",Properties:{BucketName:o,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:k.Ref(c),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowSESPuts",Effect:"Allow",Principal:{Service:"ses.amazonaws.com"},Action:"s3:PutObject",Resource:k.Join("",[k.GetAtt(c,"Arn"),"/*"]),Condition:{StringEquals:{"AWS:SourceAccount":k.Ref("AWS::AccountId")}}}]}}};return{bucket:l,bucketPolicy:u,logicalId:c}}static docsExist(n={}){let{projectRoot:i=process.cwd(),docsPaths:s=["docs","documentation","doc"]}=n;for(let o of s){let c=ve(i,o);if(qe(c)){let l=["dist","build",".bunpress/dist","_site","out","public"];for(let u of l){let h=ve(c,u);if(qe(h))try{if(gr(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(n){let i=Re.docsExist({projectRoot:n.projectRoot,docsPaths:n.docsPaths});if(!i.exists)return{bucket:null,logicalId:null,docsInfo:i};let s=Re.createDocsBucket({slug:n.slug,environment:n.environment,domain:n.domain});return{bucket:s.bucket,bucketPolicy:s.bucketPolicy,logicalId:s.logicalId,docsInfo:i}}static createPrivateBucket(n){let{slug:i,environment:s,enableVersioning:o=!0,retentionDays:c,encryptionKeyArn:l}=n,u=r({slug:i,environment:s,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:o?{Status:"Enabled"}:void 0,LifecycleConfiguration:c?{Rules:[{Id:"RetentionPolicy",Status:"Enabled",ExpirationInDays:c}]}:void 0,Tags:[{Key:"backup",Value:"daily"}]}},logicalId:h}}static checkSourcePaths(n={}){let{projectRoot:i=process.cwd(),paths:s={}}=n,o=s.web||"views/web/dist",c=s.docs||"docs/dist",l=s.private||"private";return{web:{exists:qe(ve(i,o)),path:ve(i,o)},docs:{exists:qe(ve(i,c)),path:ve(i,c)},private:{exists:qe(ve(i,l)),path:ve(i,l)}}}static createDeploymentBuckets(n){let{slug:i,environment:s,domain:o,projectRoot:c,paths:l}=n,u=Re.checkSourcePaths({projectRoot:c,paths:l}),h={},f={web:!1,docs:!1,private:!1},S=Re.createBucket({name:"web",slug:i,environment:s,public:!1,versioning:!1,encryption:!0});if(h[S.logicalId]=S.bucket,f.web=!0,u.docs.exists){let b=Re.createDocsBucket({slug:i,environment:s,domain:o?`docs.${o}`:void 0});if(h[b.logicalId]=b.bucket,b.bucketPolicy)h[`${b.logicalId}Policy`]=b.bucketPolicy;f.docs=!0}if(u.private.exists){let b=Re.createPrivateBucket({slug:i,environment:s,enableVersioning:!0});h[b.logicalId]=b.bucket,f.private=!0}return{resources:h,created:f,sourcePaths:u}}}class ze{static createRepository(n){let{name:i,slug:s,environment:o,scanOnPush:c=!0,imageMutability:l="MUTABLE",encryption:u="AES256",kmsKey:h,lifecyclePolicy:f,tags:S}=n,b=r({slug:s,environment:o,resourceType:"ecr",suffix:i}),A=t(b),v={Type:"AWS::ECR::Repository",Properties:{RepositoryName:b,ImageTagMutability:l,ImageScanningConfiguration:{ScanOnPush:c},EncryptionConfiguration:{EncryptionType:u,...h&&u==="KMS"?{KmsKey:h}:{}}}};if(f)v.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(ze.generateLifecyclePolicy(f))};if(S)v.Properties.Tags=Object.entries(S).map(([w,E])=>({Key:w,Value:E}));return{repository:v,logicalId:A}}static generateLifecyclePolicy(n){let i=[];if(n.untaggedImageExpireDays!==void 0)i.push({rulePriority:1,description:"Delete untagged images",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:n.untaggedImageExpireDays,countUnit:"days"},action:{type:"expire"}});if(n.maxImageCount!==void 0)i.push({rulePriority:i.length+1,description:"Keep only most recent images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:n.maxImageCount},action:{type:"expire"}});if(n.maxImageAgeDays!==void 0)i.push({rulePriority:i.length+1,description:"Delete images older than specified days",selection:{tagStatus:"any",countType:"sinceImagePushed",countNumber:n.maxImageAgeDays,countUnit:"days"},action:{type:"expire"}});return{rules:i}}static LifecyclePolicies={production:{maxImageCount:10,untaggedImageExpireDays:7},development:{maxImageCount:5,untaggedImageExpireDays:3},minimal:{maxImageCount:3,untaggedImageExpireDays:1},archive:{maxImageCount:50,untaggedImageExpireDays:30}};static enableImmutableTags(n){if(!n.Properties)n.Properties={};return n.Properties.ImageTagMutability="IMMUTABLE",n}static enableScanOnPush(n){if(!n.Properties)n.Properties={};return n.Properties.ImageScanningConfiguration={ScanOnPush:!0},n}static setLifecyclePolicy(n,i){if(!n.Properties)n.Properties={};return n.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(ze.generateLifecyclePolicy(i))},n}static addCrossAccountAccess(n,i){if(!n.Properties)n.Properties={};return n.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"CrossAccountPull",Effect:"Allow",Principal:{AWS:i.map((s)=>`arn:aws:iam::${s}:root`)},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:BatchCheckLayerAvailability"]}]},n}static addLambdaAccess(n){if(!n.Properties)n.Properties={};return n.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"LambdaECRImageRetrievalPolicy",Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage"]}]},n}static generateBunDockerfile(n){let{baseImage:i="oven/bun:1-debian",serverPath:s,port:o=3000,additionalDirs:c=[],healthCheckEndpoint:l="/health",nodeCompatible:u=!1,envVars:h={},buildCommands:f=[],runCommand:S}=n,b=["app","config",...c],A=S||`bun run ${s}`,v=`# Multi-stage build for Bun application
|
|
23
|
+
`)}class Re{static createBucket(n){let{name:i,bucketName:s,slug:o,environment:c,public:l=!1,versioning:u=!1,website:h=!1,encryption:f=!0,intelligentTiering:S=!1,cors:b,lifecycleRules:A}=n,v=s??r({slug:o,environment:c,resourceType:"s3",suffix:i}),w=t(v),E={Type:"AWS::S3::Bucket",Properties:{BucketName:v}};if(f)E.Properties.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(u)E.Properties.VersioningConfiguration={Status:"Enabled"};if(h)E.Properties.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"error.html"};if(!l)E.Properties.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(b&&b.length>0)E.Properties.CorsConfiguration={CorsRules:b.map((R)=>({AllowedOrigins:R.allowedOrigins,AllowedMethods:R.allowedMethods,AllowedHeaders:R.allowedHeaders,MaxAge:R.maxAge}))};if(A&&A.length>0)E.Properties.LifecycleConfiguration={Rules:A.map((R)=>({Id:R.id,Status:R.enabled?"Enabled":"Disabled",ExpirationInDays:R.expirationDays,Transitions:R.transitions?.map((D)=>({TransitionInDays:D.days,StorageClass:D.storageClass}))}))};if(S&&A){let R={id:"IntelligentTieringRule",enabled:!0,transitions:[{days:0,storageClass:"INTELLIGENT_TIERING"}]};if(!E.Properties.LifecycleConfiguration)E.Properties.LifecycleConfiguration={Rules:[]};E.Properties.LifecycleConfiguration.Rules.push({Id:R.id,Status:"Enabled",Transitions:R.transitions?.map((D)=>({TransitionInDays:D.days,StorageClass:D.storageClass}))})}let P;if(l)P={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:k.Ref(w),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[k.Join("",[k.GetAtt(w,"Arn"),"/*"])]}]}}};return{bucket:E,bucketPolicy:P,logicalId:w}}static enableVersioning(n){if(!n.Properties)n.Properties={};return n.Properties.VersioningConfiguration={Status:"Enabled"},n}static enableWebsiteHosting(n,i="index.html",s="error.html"){if(!n.Properties)n.Properties={};return n.Properties.WebsiteConfiguration={IndexDocument:i,ErrorDocument:s},n}static setLifecycleRules(n,i){if(!n.Properties)n.Properties={};return n.Properties.LifecycleConfiguration={Rules:i.map((s)=>({Id:s.id,Status:s.enabled?"Enabled":"Disabled",ExpirationInDays:s.expirationDays,Transitions:s.transitions?.map((o)=>({TransitionInDays:o.days,StorageClass:o.storageClass}))}))},n}static enableIntelligentTiering(n){if(!n.Properties)n.Properties={};if(!n.Properties.LifecycleConfiguration)n.Properties.LifecycleConfiguration={Rules:[]};return n.Properties.LifecycleConfiguration.Rules.push({Id:"IntelligentTieringRule",Status:"Enabled",Transitions:[{TransitionInDays:0,StorageClass:"INTELLIGENT_TIERING"}]}),n}static addLambdaNotification(n,i){if(!n.Properties)n.Properties={};if(!n.Properties.NotificationConfiguration)n.Properties.NotificationConfiguration={};if(!n.Properties.NotificationConfiguration.LambdaConfigurations)n.Properties.NotificationConfiguration.LambdaConfigurations=[];let s={Event:i.events[0],Function:i.functionArn};if(i.filter)s.Filter={S3Key:{Rules:[...i.filter.prefix?[{Name:"prefix",Value:i.filter.prefix}]:[],...i.filter.suffix?[{Name:"suffix",Value:i.filter.suffix}]:[]]}};for(let o of i.events){let c={...s,Event:o};n.Properties.NotificationConfiguration.LambdaConfigurations.push(c)}return n}static Notifications={onObjectCreated:(n)=>({functionArn:n,events:["s3:ObjectCreated:*"]}),onObjectRemoved:(n)=>({functionArn:n,events:["s3:ObjectRemoved:*"]}),onImageUpload:(n,i)=>({functionArn:n,events:["s3:ObjectCreated:*"],filter:{prefix:i,suffix:".jpg"}}),onFileType:(n,i,s)=>({functionArn:n,events:["s3:ObjectCreated:*"],filter:{prefix:s,suffix:i}}),onFolderUpload:(n,i)=>({functionArn:n,events:["s3:ObjectCreated:*"],filter:{prefix:i.endsWith("/")?i:`${i}/`}})};static createBackupPlan(n){let{name:i,slug:s,environment:o,bucketLogicalIds:c,retentionDays:l,schedule:u="cron(0 5 * * ? *)",vaultName:h,enableContinuousBackup:f=!1,moveToColdStorageAfterDays:S}=n,b=h||r({slug:s,environment:o,resourceType:"backup-vault",suffix:i}),A=t(b),v={Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:b}},w=r({slug:s,environment:o,resourceType:"backup-role",suffix:i}),E=t(w),P={Type:"AWS::IAM::Role",Properties:{RoleName:w,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:s,environment:o,resourceType:"backup-plan",suffix:i}),D=t(R),O={DeleteAfterDays:l};if(S&&S<l)O.MoveToColdStorageAfterDays=S;let I={Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:R,BackupPlanRule:[{RuleName:`${i}-daily-backup`,TargetBackupVault:k.Ref(A),ScheduleExpression:u,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:O,EnableContinuousBackup:f}]}}},_=r({slug:s,environment:o,resourceType:"backup-selection",suffix:i}),B=t(_),W=c.map((K)=>k.GetAtt(K,"Arn")),J={Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:k.Ref(D),BackupSelection:{SelectionName:_,IamRoleArn:k.GetAtt(E,"Arn"),Resources:W}}};return{vault:v,plan:I,selection:J,role:P,vaultLogicalId:A,planLogicalId:D,selectionLogicalId:B,roleLogicalId:E}}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(n){let{slug:i,environment:s,sourceDomain:o,targetDomain:c,protocol:l="https"}=n,u=r({slug:i,environment:s,resourceType:"s3",suffix:"www-redirect"}),h=t(u),f={Type:"AWS::S3::Bucket",Properties:{BucketName:o,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:c,Protocol:l}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1}}},S={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:k.Ref(h),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[k.Join("",[k.GetAtt(h,"Arn"),"/*"])]}]}}};return{bucket:f,bucketPolicy:S,logicalId:h}}static createDocsBucket(n){let{slug:i,environment:s,domain:o}=n,c=o||r({slug:i,environment:s,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(n){let{slug:i,environment:s}=n,o=r({slug:i,environment:s,resourceType:"s3",suffix:"email"}),c=t(o),l={Type:"AWS::S3::Bucket",Properties:{BucketName:o,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:k.Ref(c),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowSESPuts",Effect:"Allow",Principal:{Service:"ses.amazonaws.com"},Action:"s3:PutObject",Resource:k.Join("",[k.GetAtt(c,"Arn"),"/*"]),Condition:{StringEquals:{"AWS:SourceAccount":k.Ref("AWS::AccountId")}}}]}}};return{bucket:l,bucketPolicy:u,logicalId:c}}static docsExist(n={}){let{projectRoot:i=process.cwd(),docsPaths:s=["docs","documentation","doc"]}=n;for(let o of s){let c=ve(i,o);if(qe(c)){let l=["dist","build",".bunpress/dist","_site","out","public"];for(let u of l){let h=ve(c,u);if(qe(h))try{if(gr(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(n){let i=Re.docsExist({projectRoot:n.projectRoot,docsPaths:n.docsPaths});if(!i.exists)return{bucket:null,logicalId:null,docsInfo:i};let s=Re.createDocsBucket({slug:n.slug,environment:n.environment,domain:n.domain});return{bucket:s.bucket,bucketPolicy:s.bucketPolicy,logicalId:s.logicalId,docsInfo:i}}static createPrivateBucket(n){let{slug:i,environment:s,enableVersioning:o=!0,retentionDays:c,encryptionKeyArn:l}=n,u=r({slug:i,environment:s,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:o?{Status:"Enabled"}:void 0,LifecycleConfiguration:c?{Rules:[{Id:"RetentionPolicy",Status:"Enabled",ExpirationInDays:c}]}:void 0,Tags:[{Key:"backup",Value:"daily"}]}},logicalId:h}}static checkSourcePaths(n={}){let{projectRoot:i=process.cwd(),paths:s={}}=n,o=s.web||"views/web/dist",c=s.docs||"docs/dist",l=s.private||"private";return{web:{exists:qe(ve(i,o)),path:ve(i,o)},docs:{exists:qe(ve(i,c)),path:ve(i,c)},private:{exists:qe(ve(i,l)),path:ve(i,l)}}}static createDeploymentBuckets(n){let{slug:i,environment:s,domain:o,projectRoot:c,paths:l}=n,u=Re.checkSourcePaths({projectRoot:c,paths:l}),h={},f={web:!1,docs:!1,private:!1},S=Re.createBucket({name:"web",slug:i,environment:s,public:!1,versioning:!1,encryption:!0});if(h[S.logicalId]=S.bucket,f.web=!0,u.docs.exists){let b=Re.createDocsBucket({slug:i,environment:s,domain:o?`docs.${o}`:void 0});if(h[b.logicalId]=b.bucket,b.bucketPolicy)h[`${b.logicalId}Policy`]=b.bucketPolicy;f.docs=!0}if(u.private.exists){let b=Re.createPrivateBucket({slug:i,environment:s,enableVersioning:!0});h[b.logicalId]=b.bucket,f.private=!0}return{resources:h,created:f,sourcePaths:u}}}class ze{static createRepository(n){let{name:i,slug:s,environment:o,scanOnPush:c=!0,imageMutability:l="MUTABLE",encryption:u="AES256",kmsKey:h,lifecyclePolicy:f,tags:S}=n,b=r({slug:s,environment:o,resourceType:"ecr",suffix:i}),A=t(b),v={Type:"AWS::ECR::Repository",Properties:{RepositoryName:b,ImageTagMutability:l,ImageScanningConfiguration:{ScanOnPush:c},EncryptionConfiguration:{EncryptionType:u,...h&&u==="KMS"?{KmsKey:h}:{}}}};if(f)v.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(ze.generateLifecyclePolicy(f))};if(S)v.Properties.Tags=Object.entries(S).map(([w,E])=>({Key:w,Value:E}));return{repository:v,logicalId:A}}static generateLifecyclePolicy(n){let i=[];if(n.untaggedImageExpireDays!==void 0)i.push({rulePriority:1,description:"Delete untagged images",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:n.untaggedImageExpireDays,countUnit:"days"},action:{type:"expire"}});if(n.maxImageCount!==void 0)i.push({rulePriority:i.length+1,description:"Keep only most recent images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:n.maxImageCount},action:{type:"expire"}});if(n.maxImageAgeDays!==void 0)i.push({rulePriority:i.length+1,description:"Delete images older than specified days",selection:{tagStatus:"any",countType:"sinceImagePushed",countNumber:n.maxImageAgeDays,countUnit:"days"},action:{type:"expire"}});return{rules:i}}static LifecyclePolicies={production:{maxImageCount:10,untaggedImageExpireDays:7},development:{maxImageCount:5,untaggedImageExpireDays:3},minimal:{maxImageCount:3,untaggedImageExpireDays:1},archive:{maxImageCount:50,untaggedImageExpireDays:30}};static enableImmutableTags(n){if(!n.Properties)n.Properties={};return n.Properties.ImageTagMutability="IMMUTABLE",n}static enableScanOnPush(n){if(!n.Properties)n.Properties={};return n.Properties.ImageScanningConfiguration={ScanOnPush:!0},n}static setLifecyclePolicy(n,i){if(!n.Properties)n.Properties={};return n.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(ze.generateLifecyclePolicy(i))},n}static addCrossAccountAccess(n,i){if(!n.Properties)n.Properties={};return n.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"CrossAccountPull",Effect:"Allow",Principal:{AWS:i.map((s)=>`arn:aws:iam::${s}:root`)},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:BatchCheckLayerAvailability"]}]},n}static addLambdaAccess(n){if(!n.Properties)n.Properties={};return n.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"LambdaECRImageRetrievalPolicy",Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage"]}]},n}static generateBunDockerfile(n){let{baseImage:i="oven/bun:1-debian",serverPath:s,port:o=3000,additionalDirs:c=[],healthCheckEndpoint:l="/health",nodeCompatible:u=!1,envVars:h={},buildCommands:f=[],runCommand:S}=n,b=["app","config",...c],A=S||`bun run ${s}`,v=`# 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:${o}"
|
|
|
103
103
|
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
|
|
104
104
|
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest`},...n.ecsCluster&&n.ecsService?[{name:"Deploy to ECS",run:`aws ecs update-service --cluster ${n.ecsCluster} --service ${n.ecsService} --force-new-deployment`}]:[]]}}};return`# Generated by ts-cloud
|
|
105
105
|
${JSON.stringify(i,null,2).replace(/"/g,"").replace(/,\n/g,`
|
|
106
|
-
`)}`}};static DockerfileTemplates={bunServer:(n,i=3000)=>ze.generateBunDockerfile({serverPath:n,port:i}),bunWithBuild:(n,i,s=3000)=>ze.generateBunDockerfile({serverPath:n,port:s,buildCommands:[i]}),bunFullStack:(n,i=3000)=>ze.generateBunDockerfile({serverPath:n,port:i,additionalDirs:["public","views","dist"],buildCommands:["bun run build"]}),bunApi:(n,i=3000)=>ze.generateBunDockerfile({serverPath:n,port:i,healthCheckEndpoint:"/api/health"})}}var kd=[400,403,404,416,429,500,502,503,504],hg=[500,502,503,504],fg=["GET","HEAD","OPTIONS"],LI="-failover-group",Ag=["default","media-quality-based"],yg={min:1,max:3},Ig={min:1,max:10};function Bd(n){if(n===void 0)return[...hg];if(n.length===0)throw Error(`CloudFront origin failover: statusCodes must list at least one code (allowed: ${kd.join(", ")}). Omit it to use the default ${hg.join(", ")}.`);let i=n.filter((s)=>!kd.includes(s));if(i.length>0)throw Error(`CloudFront origin failover: ${i.join(", ")} ${i.length===1?"is not a status code":"are not status codes"} CloudFront can fail over on. Allowed: ${kd.join(", ")}.`);return[...new Set(n)].sort((s,o)=>s-o)}function Sg(n){let{primaryOriginId:i,secondaryOriginId:s}=n;if(!i||!s)throw Error("CloudFront origin failover: both a primary and a secondary origin id are required");if(i===s)throw Error(`CloudFront origin failover: the secondary origin must differ from the primary (both are "${i}")`);let o=Bd(n.statusCodes);return Na(n.selectionCriteria),{Id:n.groupId??`${i}-failover-group`,FailoverCriteria:{StatusCodes:{Quantity:o.length,Items:o}},Members:{Quantity:2,Items:[{OriginId:i},{OriginId:s}]},...n.selectionCriteria?{SelectionCriteria:n.selectionCriteria}:{}}}function Na(n,i="the origin group"){if(n===void 0)return;if(!Ag.includes(n))throw Error(`CloudFront origin failover: ${i} has selection criteria ${JSON.stringify(n)}. Allowed: ${Ag.join(", ")}.`)}function ft(n,i,s){if(typeof n!=="number"||!Number.isInteger(n)||n<i.min||n>i.max)throw Error(`CloudFront origin: ${s} must be a whole number from ${i.min} to ${i.max}, got ${JSON.stringify(n)}.`)}function De(n,i="the origin"){let s={};if(n?.connectionAttempts!==void 0)ft(n.connectionAttempts,yg,`${i} connectionAttempts`),s.ConnectionAttempts=n.connectionAttempts;if(n?.connectionTimeout!==void 0)ft(n.connectionTimeout,Ig,`${i} connectionTimeout (seconds)`),s.ConnectionTimeout=n.connectionTimeout;return s}function qr(n){return{Quantity:1,Items:[Sg(n)]}}function Vt(n,i="the cache behavior"){let s=(Array.isArray(n)?n:n?.Items??[]).filter((o)=>!fg.includes(o.toUpperCase()));if(s.length>0)throw Error(`CloudFront origin failover: ${i} allows ${s.join(", ")}, but a cache behavior that targets an origin group may only allow ${fg.join(", ")}. CloudFront never fails over a write, so point the write paths at a single origin in their own cache behavior.`)}function _d(n){return/\.s3[.-](?:[a-z0-9-]+\.)?amazonaws\.com(?:\.cn)?$/i.test(n)&&!/s3-website/i.test(n)}function He(n){if(!n)return[];if(Array.isArray(n))return n;return n.Items??[]}function Se(n){return typeof n==="string"?n:void 0}var hr=/\.mediapackagev2\.[a-z0-9-]+\.amazonaws\.com$/i;function jt(n,i="the distribution"){let s=He(n.Origins),o=new Set(s.map((b)=>Se(b.Id)).filter((b)=>!!b)),c=new Map(s.map((b)=>[Se(b.Id)??"",b.DomainName])),l=s.some((b)=>Se(b.Id)===void 0);for(let b of s){let A=Se(b.Id)??"(unnamed origin)";if(b.ConnectionAttempts!==void 0)ft(b.ConnectionAttempts,yg,`${i} origin "${A}" ConnectionAttempts`);if(b.ConnectionTimeout!==void 0)ft(b.ConnectionTimeout,Ig,`${i} origin "${A}" ConnectionTimeout (seconds)`)}let u=n.OriginGroups,h=He(u);if(u&&!Array.isArray(u)&&u.Quantity!==void 0&&u.Quantity!==h.length)throw Error(`CloudFront origin failover: ${i} OriginGroups.Quantity is ${u.Quantity} but it lists ${h.length} group(s).`);let f=new Set;for(let b of h){let A=Se(b.Id);if(b.Id===void 0||b.Id==="")throw Error(`CloudFront origin failover: ${i} has an origin group without an Id.`);let v=`${i} origin group "${A??"(intrinsic id)"}"`;if(A){if(f.has(A))throw Error(`CloudFront origin failover: ${i} declares origin group "${A}" twice.`);if(o.has(A))throw Error(`CloudFront origin failover: ${v} has the same id as an origin. Cache behaviors target groups and origins by id, so the two must differ.`);f.add(A)}let w=b.Members,E=He(w);if(E.length!==2||w?.Quantity!==void 0&&w.Quantity!==E.length)throw Error(`CloudFront origin failover: ${v} must have exactly 2 members (a primary and a secondary), it has ${E.length}${w?.Quantity!==void 0&&w.Quantity!==E.length?` with Quantity ${w.Quantity}`:""}.`);let P=E.map((x)=>Se(x.OriginId));for(let x of P)if(x&&!o.has(x)&&!l)throw Error(`CloudFront origin failover: ${v} lists member "${x}", which is not an origin of this distribution. Origins: ${[...o].join(", ")||"(none)"}.`);if(P[0]&&P[0]===P[1])throw Error(`CloudFront origin failover: ${v} lists "${P[0]}" as both primary and secondary.`);let R=b.FailoverCriteria?.StatusCodes,D=He(R);if(Bd(D),R?.Quantity!==void 0&&R.Quantity!==D.length)throw Error(`CloudFront origin failover: ${v} FailoverCriteria.StatusCodes.Quantity is ${R.Quantity} but it lists ${D.length} code(s).`);if(Na(b.SelectionCriteria,v),b.SelectionCriteria==="media-quality-based")for(let x of P){let I=x?Se(c.get(x)):void 0;if(I&&!hr.test(I))throw Error(`CloudFront origin failover: ${v} uses media-quality-based selection, which only works between AWS Elemental MediaPackage v2 origins, but member "${x}" is ${I}. Use 'default'.`)}}let S=[];if(n.DefaultCacheBehavior)S.push({behavior:n.DefaultCacheBehavior,name:"the default cache behavior"});for(let b of He(n.CacheBehaviors))S.push({behavior:b,name:`the cache behavior for ${JSON.stringify(b.PathPattern)}`});for(let{behavior:b,name:A}of S){let v=Se(b.TargetOriginId);if(!v)continue;if(f.has(v))Vt(b.AllowedMethods??["GET","HEAD"],`${A} of ${i} (origin group "${v}")`);else if(!o.has(v)&&!l&&h.every((w)=>Se(w.Id)!==void 0))throw Error(`CloudFront: ${A} of ${i} targets "${v}", which is neither an origin nor an origin group of this distribution.`)}}class me{static createDistribution(n){let{slug:i,environment:s,origin:o,customDomain:c,certificateArn:l,errorPages:u,cachePolicy:h,edgeFunctions:f,http3:S=!1,comment:b,failoverOrigin:A}=n,v=r({slug:i,environment:s,resourceType:"cdn"}),w=t(v),E={Id:"DefaultOrigin",DomainName:o.domainName,OriginPath:o.originPath||"",...De(o,"the CDN origin")},P;if(o.type==="s3"){let D=`${w}OAC`;P={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${v}-oac`,Description:`Origin Access Control for ${v}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},E.OriginAccessControlId=k.Ref(D)}else if(o.type==="alb"||o.type==="custom")E.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only"};let R={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:b||`CDN for ${v}`,DefaultRootObject:"index.html",Origins:[E],DefaultCacheBehavior:{TargetOriginId:"DefaultOrigin",ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0},PriceClass:"PriceClass_100",HttpVersion:S?"http2and3":"http2"}}};if(c&&l)R.Properties.DistributionConfig.Aliases=[c],R.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:l,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};if(u&&u.length>0)R.Properties.DistributionConfig.CustomErrorResponses=u.map((D)=>({ErrorCode:D.errorCode,ResponseCode:D.responseCode,ResponsePagePath:D.responsePagePath}));if(f&&f.length>0)R.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=f.map((D)=>({EventType:D.event,LambdaFunctionARN:D.functionArn}));if(A)me.addOriginFailover(R,A);return{distribution:R,originAccessControl:P,logicalId:w}}static addOriginFailover(n,i){let s=n.Properties.DistributionConfig,o=s.DefaultCacheBehavior,c=o.TargetOriginId,l=i.id??"FailoverOrigin";if(s.OriginGroups&&s.OriginGroups.Quantity>0)throw Error("CloudFront origin failover: this distribution already has an origin group");if(Vt(o.AllowedMethods??["GET","HEAD"],"the default cache behavior"),s.Origins.some((b)=>b.Id===l))throw Error(`CloudFront origin failover: an origin with id "${l}" already exists`);let u=Sg({primaryOriginId:c,secondaryOriginId:l,statusCodes:i.statusCodes,selectionCriteria:i.selectionCriteria}),h=i.type??(_d(i.domainName)?"s3":"custom"),f={Id:l,DomainName:i.domainName,OriginPath:i.originPath||"",...De(i,"the failover origin")},S=De(i.primary,"the primary origin");if(Object.keys(S).length>0){let b=s.Origins.find((A)=>A.Id===c);if(b)Object.assign(b,S)}if(h==="s3"){let b=s.Origins.find((A)=>A.Id===c);if(f.S3OriginConfig={OriginAccessIdentity:""},b?.OriginAccessControlId)f.OriginAccessControlId=b.OriginAccessControlId}else f.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only"};return s.Origins.push(f),s.OriginGroups={Quantity:1,Items:[u]},o.TargetOriginId=u.Id,jt(s),n}static setCustomDomain(n,i,s){return n.Properties.DistributionConfig.Aliases=[i],n.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:s,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"},n}static setErrorPages(n,i){return n.Properties.DistributionConfig.CustomErrorResponses=i.map((s)=>({ErrorCode:s.errorCode,ResponseCode:s.responseCode,ResponsePagePath:s.responsePagePath})),n}static enableHttp3(n){return n.Properties.DistributionConfig.HttpVersion="http2and3",n}static addEdgeFunction(n,i,s){if(!n.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations)n.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=[];return n.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations.push({EventType:i,LambdaFunctionARN:s}),n}static setCachePolicy(n,i){return n.Properties.DistributionConfig.Comment=`${n.Properties.DistributionConfig.Comment||""} (TTL: ${i.default||86400}s)`,n}static createSpaDistribution(n){return me.createDistribution({...n,errorPages:[{errorCode:404,responseCode:200,responsePagePath:"/index.html"},{errorCode:403,responseCode:200,responsePagePath:"/index.html"}]})}static createDocsOriginRequestFunction(n){let{slug:i,environment:s}=n,o=r({slug:i,environment:s,resourceType:"edge-docs"}),c=t(o),l=t(`${o}-role`),u=t(`${o}-version`),h={Type:"AWS::IAM::Role",Properties:{RoleName:`${o}-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"]}},f=`
|
|
106
|
+
`)}`}};static DockerfileTemplates={bunServer:(n,i=3000)=>ze.generateBunDockerfile({serverPath:n,port:i}),bunWithBuild:(n,i,s=3000)=>ze.generateBunDockerfile({serverPath:n,port:s,buildCommands:[i]}),bunFullStack:(n,i=3000)=>ze.generateBunDockerfile({serverPath:n,port:i,additionalDirs:["public","views","dist"],buildCommands:["bun run build"]}),bunApi:(n,i=3000)=>ze.generateBunDockerfile({serverPath:n,port:i,healthCheckEndpoint:"/api/health"})}}var kd=[400,403,404,416,429,500,502,503,504],hg=[500,502,503,504],fg=["GET","HEAD","OPTIONS"],LI="-failover-group",Ag=["default","media-quality-based"],yg={min:1,max:3},Ig={min:1,max:10};function Bd(n){if(n===void 0)return[...hg];if(n.length===0)throw Error(`CloudFront origin failover: statusCodes must list at least one code (allowed: ${kd.join(", ")}). Omit it to use the default ${hg.join(", ")}.`);let i=n.filter((s)=>!kd.includes(s));if(i.length>0)throw Error(`CloudFront origin failover: ${i.join(", ")} ${i.length===1?"is not a status code":"are not status codes"} CloudFront can fail over on. Allowed: ${kd.join(", ")}.`);return[...new Set(n)].sort((s,o)=>s-o)}function Sg(n){let{primaryOriginId:i,secondaryOriginId:s}=n;if(!i||!s)throw Error("CloudFront origin failover: both a primary and a secondary origin id are required");if(i===s)throw Error(`CloudFront origin failover: the secondary origin must differ from the primary (both are "${i}")`);let o=Bd(n.statusCodes);return Na(n.selectionCriteria),{Id:n.groupId??`${i}-failover-group`,FailoverCriteria:{StatusCodes:{Quantity:o.length,Items:o}},Members:{Quantity:2,Items:[{OriginId:i},{OriginId:s}]},...n.selectionCriteria?{SelectionCriteria:n.selectionCriteria}:{}}}function Na(n,i="the origin group"){if(n===void 0)return;if(!Ag.includes(n))throw Error(`CloudFront origin failover: ${i} has selection criteria ${JSON.stringify(n)}. Allowed: ${Ag.join(", ")}.`)}function ft(n,i,s){if(typeof n!=="number"||!Number.isInteger(n)||n<i.min||n>i.max)throw Error(`CloudFront origin: ${s} must be a whole number from ${i.min} to ${i.max}, got ${JSON.stringify(n)}.`)}function De(n,i="the origin"){let s={};if(n?.connectionAttempts!==void 0)ft(n.connectionAttempts,yg,`${i} connectionAttempts`),s.ConnectionAttempts=n.connectionAttempts;if(n?.connectionTimeout!==void 0)ft(n.connectionTimeout,Ig,`${i} connectionTimeout (seconds)`),s.ConnectionTimeout=n.connectionTimeout;return s}function qr(n){return{Quantity:1,Items:[Sg(n)]}}function Vt(n,i="the cache behavior"){let s=(Array.isArray(n)?n:n?.Items??[]).filter((o)=>!fg.includes(o.toUpperCase()));if(s.length>0)throw Error(`CloudFront origin failover: ${i} allows ${s.join(", ")}, but a cache behavior that targets an origin group may only allow ${fg.join(", ")}. CloudFront never fails over a write, so point the write paths at a single origin in their own cache behavior.`)}function _d(n){return/\.s3[.-](?:[a-z0-9-]+\.)?amazonaws\.com(?:\.cn)?$/i.test(n)&&!/s3-website/i.test(n)}function He(n){if(!n)return[];if(Array.isArray(n))return n;return n.Items??[]}function Se(n){return typeof n==="string"?n:void 0}var hr=/\.mediapackagev2\.[a-z0-9-]+\.amazonaws\.com$/i;function jt(n,i="the distribution"){let s=He(n.Origins),o=new Set(s.map((b)=>Se(b.Id)).filter((b)=>!!b)),c=new Map(s.map((b)=>[Se(b.Id)??"",b.DomainName])),l=s.some((b)=>Se(b.Id)===void 0);for(let b of s){let A=Se(b.Id)??"(unnamed origin)";if(b.ConnectionAttempts!==void 0)ft(b.ConnectionAttempts,yg,`${i} origin "${A}" ConnectionAttempts`);if(b.ConnectionTimeout!==void 0)ft(b.ConnectionTimeout,Ig,`${i} origin "${A}" ConnectionTimeout (seconds)`)}let u=n.OriginGroups,h=He(u);if(u&&!Array.isArray(u)&&u.Quantity!==void 0&&u.Quantity!==h.length)throw Error(`CloudFront origin failover: ${i} OriginGroups.Quantity is ${u.Quantity} but it lists ${h.length} group(s).`);let f=new Set;for(let b of h){let A=Se(b.Id);if(b.Id===void 0||b.Id==="")throw Error(`CloudFront origin failover: ${i} has an origin group without an Id.`);let v=`${i} origin group "${A??"(intrinsic id)"}"`;if(A){if(f.has(A))throw Error(`CloudFront origin failover: ${i} declares origin group "${A}" twice.`);if(o.has(A))throw Error(`CloudFront origin failover: ${v} has the same id as an origin. Cache behaviors target groups and origins by id, so the two must differ.`);f.add(A)}let w=b.Members,E=He(w);if(E.length!==2||w?.Quantity!==void 0&&w.Quantity!==E.length)throw Error(`CloudFront origin failover: ${v} must have exactly 2 members (a primary and a secondary), it has ${E.length}${w?.Quantity!==void 0&&w.Quantity!==E.length?` with Quantity ${w.Quantity}`:""}.`);let P=E.map((O)=>Se(O.OriginId));for(let O of P)if(O&&!o.has(O)&&!l)throw Error(`CloudFront origin failover: ${v} lists member "${O}", which is not an origin of this distribution. Origins: ${[...o].join(", ")||"(none)"}.`);if(P[0]&&P[0]===P[1])throw Error(`CloudFront origin failover: ${v} lists "${P[0]}" as both primary and secondary.`);let R=b.FailoverCriteria?.StatusCodes,D=He(R);if(Bd(D),R?.Quantity!==void 0&&R.Quantity!==D.length)throw Error(`CloudFront origin failover: ${v} FailoverCriteria.StatusCodes.Quantity is ${R.Quantity} but it lists ${D.length} code(s).`);if(Na(b.SelectionCriteria,v),b.SelectionCriteria==="media-quality-based")for(let O of P){let I=O?Se(c.get(O)):void 0;if(I&&!hr.test(I))throw Error(`CloudFront origin failover: ${v} uses media-quality-based selection, which only works between AWS Elemental MediaPackage v2 origins, but member "${O}" is ${I}. Use 'default'.`)}}let S=[];if(n.DefaultCacheBehavior)S.push({behavior:n.DefaultCacheBehavior,name:"the default cache behavior"});for(let b of He(n.CacheBehaviors))S.push({behavior:b,name:`the cache behavior for ${JSON.stringify(b.PathPattern)}`});for(let{behavior:b,name:A}of S){let v=Se(b.TargetOriginId);if(!v)continue;if(f.has(v))Vt(b.AllowedMethods??["GET","HEAD"],`${A} of ${i} (origin group "${v}")`);else if(!o.has(v)&&!l&&h.every((w)=>Se(w.Id)!==void 0))throw Error(`CloudFront: ${A} of ${i} targets "${v}", which is neither an origin nor an origin group of this distribution.`)}}class me{static createDistribution(n){let{slug:i,environment:s,origin:o,customDomain:c,certificateArn:l,errorPages:u,cachePolicy:h,edgeFunctions:f,http3:S=!1,comment:b,failoverOrigin:A}=n,v=r({slug:i,environment:s,resourceType:"cdn"}),w=t(v),E={Id:"DefaultOrigin",DomainName:o.domainName,OriginPath:o.originPath||"",...De(o,"the CDN origin")},P;if(o.type==="s3"){let D=`${w}OAC`;P={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${v}-oac`,Description:`Origin Access Control for ${v}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},E.OriginAccessControlId=k.Ref(D)}else if(o.type==="alb"||o.type==="custom")E.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only"};let R={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:b||`CDN for ${v}`,DefaultRootObject:"index.html",Origins:[E],DefaultCacheBehavior:{TargetOriginId:"DefaultOrigin",ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0},PriceClass:"PriceClass_100",HttpVersion:S?"http2and3":"http2"}}};if(c&&l)R.Properties.DistributionConfig.Aliases=[c],R.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:l,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};if(u&&u.length>0)R.Properties.DistributionConfig.CustomErrorResponses=u.map((D)=>({ErrorCode:D.errorCode,ResponseCode:D.responseCode,ResponsePagePath:D.responsePagePath}));if(f&&f.length>0)R.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=f.map((D)=>({EventType:D.event,LambdaFunctionARN:D.functionArn}));if(A)me.addOriginFailover(R,A);return{distribution:R,originAccessControl:P,logicalId:w}}static addOriginFailover(n,i){let s=n.Properties.DistributionConfig,o=s.DefaultCacheBehavior,c=o.TargetOriginId,l=i.id??"FailoverOrigin";if(s.OriginGroups&&s.OriginGroups.Quantity>0)throw Error("CloudFront origin failover: this distribution already has an origin group");if(Vt(o.AllowedMethods??["GET","HEAD"],"the default cache behavior"),s.Origins.some((b)=>b.Id===l))throw Error(`CloudFront origin failover: an origin with id "${l}" already exists`);let u=Sg({primaryOriginId:c,secondaryOriginId:l,statusCodes:i.statusCodes,selectionCriteria:i.selectionCriteria}),h=i.type??(_d(i.domainName)?"s3":"custom"),f={Id:l,DomainName:i.domainName,OriginPath:i.originPath||"",...De(i,"the failover origin")},S=De(i.primary,"the primary origin");if(Object.keys(S).length>0){let b=s.Origins.find((A)=>A.Id===c);if(b)Object.assign(b,S)}if(h==="s3"){let b=s.Origins.find((A)=>A.Id===c);if(f.S3OriginConfig={OriginAccessIdentity:""},b?.OriginAccessControlId)f.OriginAccessControlId=b.OriginAccessControlId}else f.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only"};return s.Origins.push(f),s.OriginGroups={Quantity:1,Items:[u]},o.TargetOriginId=u.Id,jt(s),n}static setCustomDomain(n,i,s){return n.Properties.DistributionConfig.Aliases=[i],n.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:s,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"},n}static setErrorPages(n,i){return n.Properties.DistributionConfig.CustomErrorResponses=i.map((s)=>({ErrorCode:s.errorCode,ResponseCode:s.responseCode,ResponsePagePath:s.responsePagePath})),n}static enableHttp3(n){return n.Properties.DistributionConfig.HttpVersion="http2and3",n}static addEdgeFunction(n,i,s){if(!n.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations)n.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=[];return n.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations.push({EventType:i,LambdaFunctionARN:s}),n}static setCachePolicy(n,i){return n.Properties.DistributionConfig.Comment=`${n.Properties.DistributionConfig.Comment||""} (TTL: ${i.default||86400}s)`,n}static createSpaDistribution(n){return me.createDistribution({...n,errorPages:[{errorCode:404,responseCode:200,responsePagePath:"/index.html"},{errorCode:403,responseCode:200,responsePagePath:"/index.html"}]})}static createDocsOriginRequestFunction(n){let{slug:i,environment:s}=n,o=r({slug:i,environment:s,resourceType:"edge-docs"}),c=t(o),l=t(`${o}-role`),u=t(`${o}-version`),h={Type:"AWS::IAM::Role",Properties:{RoleName:`${o}-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"]}},f=`
|
|
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:o,Description:"Lambda@Edge origin request handler for docs routing",Runtime:"nodejs20.x",Handler:"index.handler",Role:k.GetAtt(l,"Arn"),Code:{ZipFile:f},MemorySize:128,Timeout:5}},role:h,functionLogicalId:c,roleLogicalId:l,versionLogicalId:u}}static createDocsDistribution(n){let{slug:i,environment:s,origin:o,customDomain:c,certificateArn:l,lambdaEdgeFunctionArn:u}=n,h=me.createDistribution({slug:i,environment:s,origin:o,customDomain:c,certificateArn:l,comment:`Docs CDN for ${i}`,errorPages:[{errorCode:404,responseCode:404,responsePagePath:"/404.html"},{errorCode:403,responseCode:403,responsePagePath:"/404.html"}]});if(u)me.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(n){let{slug:i,environment:s,albDomainName:o,customDomain:c,certificateArn:l,pathPattern:u="/api/*",forwardHeaders:h=["Host","Origin","Authorization","Content-Type","Accept"],forwardCookies:f="all",whitelistedCookies:S,customOriginHeaders:b={}}=n,A=r({slug:i,environment:s,resourceType:"cdn-api"}),v=t(A),w=Object.entries(b).map(([D,
|
|
139
|
+
`.trim();return{lambdaFunction:{Type:"AWS::Lambda::Function",Properties:{FunctionName:o,Description:"Lambda@Edge origin request handler for docs routing",Runtime:"nodejs20.x",Handler:"index.handler",Role:k.GetAtt(l,"Arn"),Code:{ZipFile:f},MemorySize:128,Timeout:5}},role:h,functionLogicalId:c,roleLogicalId:l,versionLogicalId:u}}static createDocsDistribution(n){let{slug:i,environment:s,origin:o,customDomain:c,certificateArn:l,lambdaEdgeFunctionArn:u}=n,h=me.createDistribution({slug:i,environment:s,origin:o,customDomain:c,certificateArn:l,comment:`Docs CDN for ${i}`,errorPages:[{errorCode:404,responseCode:404,responsePagePath:"/404.html"},{errorCode:403,responseCode:403,responsePagePath:"/404.html"}]});if(u)me.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(n){let{slug:i,environment:s,albDomainName:o,customDomain:c,certificateArn:l,pathPattern:u="/api/*",forwardHeaders:h=["Host","Origin","Authorization","Content-Type","Accept"],forwardCookies:f="all",whitelistedCookies:S,customOriginHeaders:b={}}=n,A=r({slug:i,environment:s,resourceType:"cdn-api"}),v=t(A),w=Object.entries(b).map(([D,O])=>({HeaderName:D,HeaderValue:O})),E={Id:"ALBOrigin",DomainName:o,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(w.length>0)E.OriginCustomHeaders=w;let P={Forward:f};if(f==="whitelist"&&S)P.WhitelistedNames=S;let R={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:`API CDN for ${A}`,Origins:[E],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:P}},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:v}}static createMultiOriginDistribution(n){let{slug:i,environment:s,s3BucketDomainName:o,albDomainName:c,apiPathPattern:l="/api/*",customDomain:u,certificateArn:h,customOriginHeaders:f={}}=n,S=r({slug:i,environment:s,resourceType:"cdn"}),b=t(S),A=`${b}OAC`,v={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${S}-oac`,Description:`Origin Access Control for ${S}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},w=Object.entries(f).map(([D,O])=>({HeaderName:D,HeaderValue:O})),E={Id:"S3Origin",DomainName:o,OriginAccessControlId:k.Ref(A)},P={Id:"ALBOrigin",DomainName:c,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(w.length>0)P.OriginCustomHeaders=w;let R={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:`Multi-origin CDN for ${S}`,DefaultRootObject:"index.html",Origins:[E,P],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:v,logicalId:b,oacLogicalId:A}}static addAlbOrigin(n,i){let{originId:s,domainName:o,pathPattern:c,customHeaders:l={},forwardHeaders:u=["Host","Origin","Authorization","Content-Type","Accept"],cacheTtl:h={default:0,max:0,min:0}}=i,f=Object.entries(l).map(([b,A])=>({HeaderName:b,HeaderValue:A})),S={Id:s,DomainName:o,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(f.length>0)S.OriginCustomHeaders=f;if(!n.Properties.DistributionConfig.Origins)n.Properties.DistributionConfig.Origins=[];if(n.Properties.DistributionConfig.Origins.push(S),!n.Properties.DistributionConfig.CacheBehaviors)n.Properties.DistributionConfig.CacheBehaviors=[];return n.Properties.DistributionConfig.CacheBehaviors.push({PathPattern:c,TargetOriginId:s,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"}}}),n}static addOriginHeader(n,i,s,o){let c=n.Properties.DistributionConfig.Origins?.find((l)=>l.Id===i);if(c){if(!c.OriginCustomHeaders)c.OriginCustomHeaders=[];c.OriginCustomHeaders.push({HeaderName:s,HeaderValue:o})}return n}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:(n)=>{let{min:i=0,max:s=86400,default:o=86400}=n;return{MinTTL:i,MaxTTL:s,DefaultTTL:o}},cookies:(n,i)=>{let s={Forward:n==="allowList"?"whitelist":n};if(n==="allowList"&&i)s.WhitelistedNames=i;return s},allowedMethods:(n)=>{let i={ALL:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return i[n]||i.GET_HEAD},cachedMethods:(n)=>{let i={GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return i[n]||i.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:(n)=>{let{ttl:i={min:0,max:86400,default:86400},cookies:s="none",allowedCookies:o,allowedMethods:c="GET_HEAD",cachedMethods:l="GET_HEAD",compress:u=!0,forwardQueryString:h=!0,forwardHeaders:f=[]}=n;return{MinTTL:i.min,MaxTTL:i.max,DefaultTTL:i.default,Compress:u,AllowedMethods:me.Config.allowedMethods(c),CachedMethods:me.Config.cachedMethods(l),ForwardedValues:{QueryString:h,Headers:f,Cookies:me.Config.cookies(s,o)}}}};static applyConfig(n,i){let s=n.Properties.DistributionConfig.DefaultCacheBehavior;if(i.ttl)s.MinTTL=i.ttl.min,s.MaxTTL=i.ttl.max,s.DefaultTTL=i.ttl.default;if(i.compress!==void 0)s.Compress=i.compress;if(i.allowedMethods)s.AllowedMethods=me.Config.allowedMethods(i.allowedMethods);if(i.cachedMethods)s.CachedMethods=me.Config.cachedMethods(i.cachedMethods);if(i.cookies){if(!s.ForwardedValues)s.ForwardedValues={QueryString:!0};s.ForwardedValues.Cookies=me.Config.cookies(i.cookies,i.allowedCookies)}return n}}var dA=[403,404,500,502,503,504],xd="TsCloud::StorageFailover",go="AllowCloudFrontFailoverRead",yr=/^[a-z]{2}(?:-gov)?-[a-z]+-\d$/,fr=/^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/;function Cg(n){let{failover:i,primaryBucket:s,primaryRegion:o}=n,c=n.where??"storage failover";if(!i||typeof i!=="object")throw Error(`${c}.failover must be an object such as { region: 'us-west-2' }.`);if(!i.region||!yr.test(i.region))throw Error(`${c}.failover.region must be an AWS region such as 'us-west-2', got ${JSON.stringify(i.region)}.`);if(i.region===o)throw Error(`${c}.failover.region is ${i.region}, the same region as the primary bucket. Failover only helps when the replica is in another region.`);let l=i.bucket??`${s}-${i.region}`;if(!fr.test(l)||l.includes("..")){let u=i.bucket===void 0&&l.length>63?` The default name (<primary bucket>-<region>) is ${l.length} characters; S3 allows 63. Set ${c}.failover.bucket.`:"";throw Error(`${c}.failover: "${l}" is not a valid S3 bucket name.${u}`)}if(l===s)throw Error(`${c}.failover.bucket must differ from the primary bucket "${s}".`);return{replicaBucket:l,replicaRegion:i.region,replicate:i.replicate!==!1,statusCodes:Bd(i.statusCodes??dA),primaryConnection:De(i,`${c}.failover`)}}function Eg(n,i){return`${n}.s3.${i}.amazonaws.com`}function bg(n){let i=`arn:aws:s3:::${n.primaryBucket}`,s=`arn:aws:s3:::${n.replicaBucket}`;return{Type:"AWS::IAM::Role",Properties:{...n.roleName?{RoleName:n.roleName}:{},AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"s3.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"failover-replication",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["s3:GetReplicationConfiguration","s3:ListBucket"],Resource:i},{Effect:"Allow",Action:["s3:GetObjectVersionForReplication","s3:GetObjectVersionAcl","s3:GetObjectVersionTagging"],Resource:`${i}/*`},{Effect:"Allow",Action:["s3:ReplicateObject","s3:ReplicateDelete","s3:ReplicateTags"],Resource:`${s}/*`}]}}]}}}function vg(n){return{Role:n.roleArn,Rules:[{Id:"cloudfront-failover-replica",Status:"Enabled",Priority:1,Filter:{Prefix:""},DeleteMarkerReplication:{Status:"Enabled"},Destination:{Bucket:`arn:aws:s3:::${n.replicaBucket}`}}]}}function Od(n){return{Sid:go,Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:`arn:aws:s3:::${n.replicaBucket}/*`,Condition:{StringEquals:{"AWS:SourceArn":n.distributionArn}}}}function $I(n){let i=(typeof n==="string"?JSON.parse(n):n)?.Metadata?.[xd];return Array.isArray(i)?i:[]}class F{static createHostedZone(n){let{domain:i,slug:s,environment:o,comment:c}=n,l=r({slug:s,environment:o,resourceType:"hostedzone"}),u=t(`${l}-${i.replace(/\./g,"")}`);return{zone:{Type:"AWS::Route53::HostedZone",Properties:{Name:i,HostedZoneConfig:{Comment:c||`Hosted zone for ${i}`}}},logicalId:u}}static createRecord(n){let{hostedZoneId:i,hostedZoneName:s,name:o,type:c,ttl:l,values:u,aliasTarget:h}=n,f=t(`record-${o.replace(/\./g,"")}-${c}`),S={Type:"AWS::Route53::RecordSet",Properties:{Name:o,Type:c}};if(i)S.Properties.HostedZoneId=i;else if(s)S.Properties.HostedZoneName=s;if(h)S.Properties.AliasTarget={DNSName:h.dnsName,HostedZoneId:h.hostedZoneId,EvaluateTargetHealth:h.evaluateTargetHealth??!1};else S.Properties.TTL=l||300,S.Properties.ResourceRecords=u||[];return{record:S,logicalId:f}}static createCloudFrontAlias(n,i,s){return F.createRecord({hostedZoneId:s,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:"Z2FDTNDATAQYW2",evaluateTargetHealth:!1}})}static createAlbAlias(n,i,s,o){return F.createRecord({hostedZoneId:o,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:s,evaluateTargetHealth:!0}})}static createCname(n,i,s,o=300){return F.createRecord({hostedZoneId:s,name:n,type:"CNAME",ttl:o,values:[i]})}static createWwwRedirect(n,i){return F.createRecord({hostedZoneId:i,name:`www.${n}`,type:"CNAME",ttl:300,values:[n]})}static createMxRecords(n,i,s,o=300){return F.createRecord({hostedZoneId:s,name:n,type:"MX",ttl:o,values:i.map((c)=>`${c.priority} ${c.server}`)})}static createTxtRecord(n,i,s,o=300){return F.createRecord({hostedZoneId:s,name:n,type:"TXT",ttl:o,values:[`"${i}"`]})}static createSpfRecord(n,i,s){return F.createTxtRecord(n,i,s)}static createDmarcRecord(n,i,s,o){let c=`v=DMARC1; p=${i}; rua=mailto:${s}`;return F.createTxtRecord(`_dmarc.${n}`,c,o)}static createS3WebsiteAlias(n,i,s,o){return F.createRecord({hostedZoneId:o,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:s,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(n,i){return`${n}.s3-website-${i}.amazonaws.com`}static createStoreRecord(n,i,s){return F.createCname(`store.${n}`,i,s)}static createApiRecord(n,i,s){return F.createCname(`api.${n}`,i,s)}static createDocsRecord(n,i,s){return F.createCname(`docs.${n}`,i,s)}static CloudFrontHostedZoneId="Z2FDTNDATAQYW2"}class C{static createCertificate(n){let{domain:i,subdomains:s=[],slug:o,environment:c,validationMethod:l="DNS",hostedZoneId:u}=n,h=r({slug:o,environment:c,resourceType:"acm"}),f=t(`${h}-${i.replace(/\./g,"")}`),S=[i];for(let A of s)if(A==="*")S.push(`*.${i}`);else S.push(`${A}.${i}`);let b={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:i,SubjectAlternativeNames:S,ValidationMethod:l}};if(l==="DNS"&&u)b.Properties.DomainValidationOptions=S.map((A)=>({DomainName:A,HostedZoneId:u}));return{certificate:b,logicalId:f}}static createKmsKey(n){let{description:i,slug:s,environment:o,enableRotation:c=!0,multiRegion:l=!1}=n,u=r({slug:s,environment:o,resourceType:"kms"}),h=t(u),f={Version:"2012-10-17",Statement:[{Sid:"Enable IAM User Permissions",Effect:"Allow",Principal:{AWS:k.Sub("arn:aws:iam::${AWS::AccountId}:root")},Action:"kms:*",Resource:"*"},{Sid:"Allow services to use the key",Effect:"Allow",Principal:{Service:["s3.amazonaws.com","cloudfront.amazonaws.com","logs.amazonaws.com","secretsmanager.amazonaws.com"]},Action:["kms:Decrypt","kms:GenerateDataKey"],Resource:"*"}]},S={Type:"AWS::KMS::Key",Properties:{Description:i,Enabled:!0,EnableKeyRotation:c,KeyPolicy:f,KeySpec:"SYMMETRIC_DEFAULT",KeyUsage:"ENCRYPT_DECRYPT",MultiRegion:l}},b=t(`${u}-alias`),A={Type:"AWS::KMS::Alias",Properties:{AliasName:`alias/${s}-${o}`,TargetKeyId:k.Ref(h)}};return{key:S,alias:A,logicalId:h,aliasId:b}}static createFirewall(n){let{slug:i,environment:s,scope:o="CLOUDFRONT",defaultAction:c="allow"}=n,l=r({slug:i,environment:s,resourceType:"waf"}),u=t(l);return{webAcl:{Type:"AWS::WAFv2::WebACL",Properties:{Name:l,Scope:o,DefaultAction:c==="allow"?{Allow:{}}:{Block:{}},Description:`WAF for ${i} ${s}`,Rules:[],VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${l}-metric`}}},logicalId:u}}static setRateLimit(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{RateBasedStatement:{Limit:i.requestsPerWindow,AggregateKeyType:i.aggregateKeyType||"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static blockCountries(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{GeoMatchStatement:{CountryCodes:i.countryCodes}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static blockIpAddresses(n,i,s,o){let c=r({slug:s,environment:o,resourceType:"ipset"}),l=t(`${c}-${i.name}`),u={Type:"AWS::WAFv2::IPSet",Properties:{Name:`${c}-${i.name}`,Scope:n.Properties.Scope,IPAddressVersion:i.ipVersion||"IPV4",Addresses:i.ipAddresses,Description:`Blocked IPs for ${i.name}`}};if(!n.Properties.Rules)n.Properties.Rules=[];return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{IPSetReferenceStatement:{Arn:k.GetAtt(l,"Arn")}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),{webAcl:n,ipSet:u,ipSetLogicalId:l}}static addManagedRules(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];let s={ManagedRuleGroupStatement:{VendorName:i.vendorName,Name:i.ruleName}};if(i.excludedRules&&i.excludedRules.length>0)s.ManagedRuleGroupStatement.ExcludedRules=i.excludedRules.map((o)=>({Name:o}));return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:s,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}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(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];let s=i.paths.map((o)=>({SearchString:o,FieldToMatch:{UriPath:{}},TextTransformation:[{Priority:0,Type:"LOWERCASE"}],PositionalConstraint:"STARTS_WITH"}));return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{RateBasedStatement:{Limit:i.requestsPerWindow,AggregateKeyType:i.aggregateKeyType||"IP",ScopeDownStatement:{OrStatement:{Statements:s.map((o)=>({ByteMatchStatement:o}))}}}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static setHeaderRateLimit(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];let s={RateBasedStatement:{Limit:i.requestsPerWindow,AggregateKeyType:"CUSTOM_KEYS",CustomKeys:[{Header:{Name:i.headerName,TextTransformations:[{Priority:0,Type:"NONE"}]}}]}};if(i.headerValue)s.RateBasedStatement.ScopeDownStatement={ByteMatchStatement:{SearchString:i.headerValue,FieldToMatch:{SingleHeader:{Name:i.headerName}},TextTransformation:[{Priority:0,Type:"NONE"}],PositionalConstraint:"EXACTLY"}};return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:s,Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static protectLoginEndpoint(n,i){let{loginPaths:s,priority:o,requestsPerMinute:c=10}=i;return C.setPathRateLimit(n,{name:"LoginRateLimit",priority:o,requestsPerWindow:c*5,paths:s}),n}static protectApiEndpoints(n,i){let{apiPaths:s,priority:o,requestsPerMinute:c=100}=i;return C.setPathRateLimit(n,{name:"ApiRateLimit",priority:o,requestsPerWindow:c*5,paths:s}),n}static createProtectedFirewall(n){let{slug:i,environment:s,scope:o="CLOUDFRONT",enableBotControl:c=!1,enableRateLimiting:l=!0,rateLimitPerMinute:u=2000}=n,{webAcl:h,logicalId:f}=C.createFirewall({slug:i,environment:s,scope:o,defaultAction:"allow"}),S=0;if(h=C.addManagedRules(h,{name:"AWSIPReputationList",priority:S++,...C.ManagedRuleGroups.AmazonIpReputation}),h=C.addManagedRules(h,{name:"AWSAnonymousIPList",priority:S++,...C.ManagedRuleGroups.AnonymousIpList}),h=C.addManagedRules(h,{name:"AWSCoreRuleSet",priority:S++,...C.ManagedRuleGroups.CoreRuleSet}),h=C.addManagedRules(h,{name:"AWSKnownBadInputs",priority:S++,...C.ManagedRuleGroups.KnownBadInputs}),h=C.addManagedRules(h,{name:"AWSSQLi",priority:S++,...C.ManagedRuleGroups.SqlDatabase}),c)h=C.addManagedRules(h,{name:"AWSBotControl",priority:S++,...C.ManagedRuleGroups.BotControl});if(l)h=C.setRateLimit(h,{name:"GlobalRateLimit",priority:S++,requestsPerWindow:u*5});return{webAcl:h,logicalId:f}}static RateLimitPresets={STANDARD:2000,HIGH_TRAFFIC:1e4,STRICT:100,LOGIN:10,API:100}}class a{static createServer(n){let{slug:i,environment:s,instanceType:o="t3.micro",imageId:c="ami-0f3caa1cf4417e51b",keyName:l,securityGroupIds:u,subnetId:h,userData:f,volumeSize:S=20,volumeType:b="gp3",encrypted:A=!0}=n,v=r({slug:i,environment:s,resourceType:"ec2"}),w=t(v),E={Type:"AWS::EC2::Instance",Properties:{ImageId:c,InstanceType:o,Tags:[{Key:"Name",Value:v},{Key:"Environment",Value:s}]}};if(l)E.Properties.KeyName=l;if(u)E.Properties.SecurityGroupIds=u;if(h)E.Properties.SubnetId=h;if(f)E.Properties.UserData=k.Base64(f);return E.Properties.BlockDeviceMappings=[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:S,VolumeType:b,Encrypted:A,DeleteOnTermination:!0}}],{instance:E,logicalId:w}}static createSecurityGroup(n){let{slug:i,environment:s,vpcId:o,description:c,ingress:l=[],egress:u=[]}=n,h=r({slug:i,environment:s,resourceType:"sg"}),f=t(h),S={Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:c||`Security group for ${i} ${s}`,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(o)S.Properties.VpcId=o;if(l.length>0)S.Properties.SecurityGroupIngress=l.map((b)=>({IpProtocol:b.protocol,FromPort:b.fromPort,ToPort:b.toPort,CidrIp:b.cidr,SourceSecurityGroupId:b.sourceSecurityGroupId}));if(u.length>0)S.Properties.SecurityGroupEgress=u.map((b)=>({IpProtocol:b.protocol,FromPort:b.fromPort,ToPort:b.toPort,CidrIp:b.cidr,DestinationSecurityGroupId:b.sourceSecurityGroupId}));return{securityGroup:S,logicalId:f}}static createWebServerSecurityGroup(n,i,s){return a.createSecurityGroup({slug:n,environment:i,vpcId:s,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(n){let{slug:i,environment:s,scheme:o="internet-facing",subnets:c,securityGroups:l,type:u="application"}=n,h=r({slug:i,environment:s,resourceType:"alb"}),f=t(h),S={Type:"AWS::ElasticLoadBalancingV2::LoadBalancer",Properties:{Name:h,Scheme:o,Type:u,Subnets:c,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(l)S.Properties.SecurityGroups=l;return{loadBalancer:S,logicalId:f}}static createTargetGroup(n){let{slug:i,environment:s,port:o,protocol:c="HTTP",vpcId:l,targetType:u="ip",healthCheckPath:h="/",healthCheckInterval:f=30,healthCheckTimeout:S=5,healthyThreshold:b=2,unhealthyThreshold:A=3}=n,v=r({slug:i,environment:s,resourceType:"tg"}),w=t(v);return{targetGroup:{Type:"AWS::ElasticLoadBalancingV2::TargetGroup",Properties:{Name:v,Port:o,Protocol:c,VpcId:l,TargetType:u,HealthCheckEnabled:!0,HealthCheckProtocol:c,HealthCheckPath:h,HealthCheckIntervalSeconds:f,HealthCheckTimeoutSeconds:S,HealthyThresholdCount:b,UnhealthyThresholdCount:A,Tags:[{Key:"Name",Value:v},{Key:"Environment",Value:s}]}},logicalId:w}}static createListener(n,i){let{port:s,protocol:o="HTTP",certificateArn:c,defaultTargetGroupArn:l}=i,u=t(`listener-${n}-${s}`),h={Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:k.Ref(n),Port:s,Protocol:o,DefaultActions:[{Type:"forward",TargetGroupArn:l}]}};if(o==="HTTPS"&&c)h.Properties.Certificates=[{CertificateArn:c}],h.Properties.SslPolicy="ELBSecurityPolicy-TLS13-1-2-2021-06";return{listener:h,logicalId:u}}static createEcsCluster(n,i){let s=r({slug:n,environment:i,resourceType:"ecs-cluster"}),o=t(s);return{cluster:{Type:"AWS::ECS::Cluster",Properties:{ClusterName:s,Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:i}]}},logicalId:o}}static createFargateService(n){let{slug:i,environment:s,image:o,cpu:c="256",memory:l="512",desiredCount:u=1,containerPort:h=8080,environmentVariables:f={},secrets:S=[],healthCheck:b,logGroup:A,subnets:v,securityGroups:w,targetGroupArn:E}=n,{cluster:P,logicalId:R}=a.createEcsCluster(i,s),D=r({slug:i,environment:s,resourceType:"fargate"}),x=t(`${D}-execution-role`),I={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"]}},_=t(`${D}-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"}]}}},W=t(`${D}-task`),J={Type:"AWS::ECS::TaskDefinition",Properties:{Family:D,TaskRoleArn:k.GetAtt(_,"Arn"),ExecutionRoleArn:k.GetAtt(x,"Arn"),NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:c,Memory:l,ContainerDefinitions:[{Name:i,Image:o,Essential:!0,PortMappings:[{ContainerPort:h,Protocol:"tcp"}],Environment:Object.entries(f).map(([Z,ne])=>({Name:Z,Value:ne})),Secrets:S.map((Z)=>({Name:Z.name,ValueFrom:Z.valueFrom}))}],Tags:[{Key:"Name",Value:D},{Key:"Environment",Value:s}]}};if(b)J.Properties.ContainerDefinitions[0].HealthCheck={Command:b.command,Interval:b.interval||30,Timeout:b.timeout||5,Retries:b.retries||3,StartPeriod:60};if(A)J.Properties.ContainerDefinitions[0].LogConfiguration={LogDriver:"awslogs",Options:{"awslogs-group":A,"awslogs-region":k.Ref("AWS::Region"),"awslogs-stream-prefix":i}};let K=t(`${D}-service`),Y={Type:"AWS::ECS::Service",Properties:{ServiceName:D,Cluster:k.Ref(R),TaskDefinition:k.Ref(W),DesiredCount:u,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{Subnets:v,SecurityGroups:w,AssignPublicIp:"ENABLED"}},Tags:[{Key:"Name",Value:D},{Key:"Environment",Value:s}]}};if(E)Y.Properties.LoadBalancers=[{TargetGroupArn:E,ContainerName:i,ContainerPort:h}];return{cluster:P,taskDefinition:J,service:Y,taskRole:B,executionRole:I,clusterLogicalId:R,taskDefinitionLogicalId:W,serviceLogicalId:K,taskRoleLogicalId:_,executionRoleLogicalId:x}}static createLambdaFunction(n){let{slug:i,environment:s,runtime:o,handler:c,code:l,timeout:u=30,memorySize:h=128,environmentVariables:f={},vpcConfig:S}=n,b=r({slug:i,environment:s,resourceType:"lambda"}),A=t(b),v=t(`${b}-role`),w={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]}};if(S)w.Properties.ManagedPolicyArns.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");let E={Type:"AWS::Lambda::Function",Properties:{FunctionName:b,Runtime:o,Role:k.GetAtt(v,"Arn"),Handler:c,Code:{...l.s3Bucket&&{S3Bucket:l.s3Bucket},...l.s3Key&&{S3Key:l.s3Key},...l.zipFile&&{ZipFile:l.zipFile}},Timeout:u,MemorySize:h,Tags:[{Key:"Name",Value:b},{Key:"Environment",Value:s}]}};if(Object.keys(f).length>0)E.Properties.Environment={Variables:f};if(S)E.Properties.VpcConfig={SecurityGroupIds:S.securityGroupIds,SubnetIds:S.subnetIds};return{lambdaFunction:E,role:w,logicalId:A,roleLogicalId:v}}static generateNodeServerUserData(n={}){let{nodeVersion:i="20",appRepo:s,environment:o={}}=n,c=Object.entries(o).map(([l,u])=>`echo "export ${l}='${u}'" >> /etc/environment`).join(`
|
|
212
|
+
`.trim()};static Config={ttl:(n)=>{let{min:i=0,max:s=86400,default:o=86400}=n;return{MinTTL:i,MaxTTL:s,DefaultTTL:o}},cookies:(n,i)=>{let s={Forward:n==="allowList"?"whitelist":n};if(n==="allowList"&&i)s.WhitelistedNames=i;return s},allowedMethods:(n)=>{let i={ALL:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return i[n]||i.GET_HEAD},cachedMethods:(n)=>{let i={GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return i[n]||i.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:(n)=>{let{ttl:i={min:0,max:86400,default:86400},cookies:s="none",allowedCookies:o,allowedMethods:c="GET_HEAD",cachedMethods:l="GET_HEAD",compress:u=!0,forwardQueryString:h=!0,forwardHeaders:f=[]}=n;return{MinTTL:i.min,MaxTTL:i.max,DefaultTTL:i.default,Compress:u,AllowedMethods:me.Config.allowedMethods(c),CachedMethods:me.Config.cachedMethods(l),ForwardedValues:{QueryString:h,Headers:f,Cookies:me.Config.cookies(s,o)}}}};static applyConfig(n,i){let s=n.Properties.DistributionConfig.DefaultCacheBehavior;if(i.ttl)s.MinTTL=i.ttl.min,s.MaxTTL=i.ttl.max,s.DefaultTTL=i.ttl.default;if(i.compress!==void 0)s.Compress=i.compress;if(i.allowedMethods)s.AllowedMethods=me.Config.allowedMethods(i.allowedMethods);if(i.cachedMethods)s.CachedMethods=me.Config.cachedMethods(i.cachedMethods);if(i.cookies){if(!s.ForwardedValues)s.ForwardedValues={QueryString:!0};s.ForwardedValues.Cookies=me.Config.cookies(i.cookies,i.allowedCookies)}return n}}var dA=[403,404,500,502,503,504],Od="TsCloud::StorageFailover",go="AllowCloudFrontFailoverRead",yr=/^[a-z]{2}(?:-gov)?-[a-z]+-\d$/,fr=/^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/;function Cg(n){let{failover:i,primaryBucket:s,primaryRegion:o}=n,c=n.where??"storage failover";if(!i||typeof i!=="object")throw Error(`${c}.failover must be an object such as { region: 'us-west-2' }.`);if(!i.region||!yr.test(i.region))throw Error(`${c}.failover.region must be an AWS region such as 'us-west-2', got ${JSON.stringify(i.region)}.`);if(i.region===o)throw Error(`${c}.failover.region is ${i.region}, the same region as the primary bucket. Failover only helps when the replica is in another region.`);let l=i.bucket??`${s}-${i.region}`;if(!fr.test(l)||l.includes("..")){let u=i.bucket===void 0&&l.length>63?` The default name (<primary bucket>-<region>) is ${l.length} characters; S3 allows 63. Set ${c}.failover.bucket.`:"";throw Error(`${c}.failover: "${l}" is not a valid S3 bucket name.${u}`)}if(l===s)throw Error(`${c}.failover.bucket must differ from the primary bucket "${s}".`);return{replicaBucket:l,replicaRegion:i.region,replicate:i.replicate!==!1,statusCodes:Bd(i.statusCodes??dA),primaryConnection:De(i,`${c}.failover`)}}function Eg(n,i){return`${n}.s3.${i}.amazonaws.com`}function bg(n){let i=`arn:aws:s3:::${n.primaryBucket}`,s=`arn:aws:s3:::${n.replicaBucket}`;return{Type:"AWS::IAM::Role",Properties:{...n.roleName?{RoleName:n.roleName}:{},AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"s3.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"failover-replication",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["s3:GetReplicationConfiguration","s3:ListBucket"],Resource:i},{Effect:"Allow",Action:["s3:GetObjectVersionForReplication","s3:GetObjectVersionAcl","s3:GetObjectVersionTagging"],Resource:`${i}/*`},{Effect:"Allow",Action:["s3:ReplicateObject","s3:ReplicateDelete","s3:ReplicateTags"],Resource:`${s}/*`}]}}]}}}function vg(n){return{Role:n.roleArn,Rules:[{Id:"cloudfront-failover-replica",Status:"Enabled",Priority:1,Filter:{Prefix:""},DeleteMarkerReplication:{Status:"Enabled"},Destination:{Bucket:`arn:aws:s3:::${n.replicaBucket}`}}]}}function xd(n){return{Sid:go,Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:`arn:aws:s3:::${n.replicaBucket}/*`,Condition:{StringEquals:{"AWS:SourceArn":n.distributionArn}}}}function $I(n){let i=(typeof n==="string"?JSON.parse(n):n)?.Metadata?.[Od];return Array.isArray(i)?i:[]}class F{static createHostedZone(n){let{domain:i,slug:s,environment:o,comment:c}=n,l=r({slug:s,environment:o,resourceType:"hostedzone"}),u=t(`${l}-${i.replace(/\./g,"")}`);return{zone:{Type:"AWS::Route53::HostedZone",Properties:{Name:i,HostedZoneConfig:{Comment:c||`Hosted zone for ${i}`}}},logicalId:u}}static createRecord(n){let{hostedZoneId:i,hostedZoneName:s,name:o,type:c,ttl:l,values:u,aliasTarget:h}=n,f=t(`record-${o.replace(/\./g,"")}-${c}`),S={Type:"AWS::Route53::RecordSet",Properties:{Name:o,Type:c}};if(i)S.Properties.HostedZoneId=i;else if(s)S.Properties.HostedZoneName=s;if(h)S.Properties.AliasTarget={DNSName:h.dnsName,HostedZoneId:h.hostedZoneId,EvaluateTargetHealth:h.evaluateTargetHealth??!1};else S.Properties.TTL=l||300,S.Properties.ResourceRecords=u||[];return{record:S,logicalId:f}}static createCloudFrontAlias(n,i,s){return F.createRecord({hostedZoneId:s,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:"Z2FDTNDATAQYW2",evaluateTargetHealth:!1}})}static createAlbAlias(n,i,s,o){return F.createRecord({hostedZoneId:o,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:s,evaluateTargetHealth:!0}})}static createCname(n,i,s,o=300){return F.createRecord({hostedZoneId:s,name:n,type:"CNAME",ttl:o,values:[i]})}static createWwwRedirect(n,i){return F.createRecord({hostedZoneId:i,name:`www.${n}`,type:"CNAME",ttl:300,values:[n]})}static createMxRecords(n,i,s,o=300){return F.createRecord({hostedZoneId:s,name:n,type:"MX",ttl:o,values:i.map((c)=>`${c.priority} ${c.server}`)})}static createTxtRecord(n,i,s,o=300){return F.createRecord({hostedZoneId:s,name:n,type:"TXT",ttl:o,values:[`"${i}"`]})}static createSpfRecord(n,i,s){return F.createTxtRecord(n,i,s)}static createDmarcRecord(n,i,s,o){let c=`v=DMARC1; p=${i}; rua=mailto:${s}`;return F.createTxtRecord(`_dmarc.${n}`,c,o)}static createS3WebsiteAlias(n,i,s,o){return F.createRecord({hostedZoneId:o,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:s,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(n,i){return`${n}.s3-website-${i}.amazonaws.com`}static createStoreRecord(n,i,s){return F.createCname(`store.${n}`,i,s)}static createApiRecord(n,i,s){return F.createCname(`api.${n}`,i,s)}static createDocsRecord(n,i,s){return F.createCname(`docs.${n}`,i,s)}static CloudFrontHostedZoneId="Z2FDTNDATAQYW2"}class C{static createCertificate(n){let{domain:i,subdomains:s=[],slug:o,environment:c,validationMethod:l="DNS",hostedZoneId:u}=n,h=r({slug:o,environment:c,resourceType:"acm"}),f=t(`${h}-${i.replace(/\./g,"")}`),S=[i];for(let A of s)if(A==="*")S.push(`*.${i}`);else S.push(`${A}.${i}`);let b={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:i,SubjectAlternativeNames:S,ValidationMethod:l}};if(l==="DNS"&&u)b.Properties.DomainValidationOptions=S.map((A)=>({DomainName:A,HostedZoneId:u}));return{certificate:b,logicalId:f}}static createKmsKey(n){let{description:i,slug:s,environment:o,enableRotation:c=!0,multiRegion:l=!1}=n,u=r({slug:s,environment:o,resourceType:"kms"}),h=t(u),f={Version:"2012-10-17",Statement:[{Sid:"Enable IAM User Permissions",Effect:"Allow",Principal:{AWS:k.Sub("arn:aws:iam::${AWS::AccountId}:root")},Action:"kms:*",Resource:"*"},{Sid:"Allow services to use the key",Effect:"Allow",Principal:{Service:["s3.amazonaws.com","cloudfront.amazonaws.com","logs.amazonaws.com","secretsmanager.amazonaws.com"]},Action:["kms:Decrypt","kms:GenerateDataKey"],Resource:"*"}]},S={Type:"AWS::KMS::Key",Properties:{Description:i,Enabled:!0,EnableKeyRotation:c,KeyPolicy:f,KeySpec:"SYMMETRIC_DEFAULT",KeyUsage:"ENCRYPT_DECRYPT",MultiRegion:l}},b=t(`${u}-alias`),A={Type:"AWS::KMS::Alias",Properties:{AliasName:`alias/${s}-${o}`,TargetKeyId:k.Ref(h)}};return{key:S,alias:A,logicalId:h,aliasId:b}}static createFirewall(n){let{slug:i,environment:s,scope:o="CLOUDFRONT",defaultAction:c="allow"}=n,l=r({slug:i,environment:s,resourceType:"waf"}),u=t(l);return{webAcl:{Type:"AWS::WAFv2::WebACL",Properties:{Name:l,Scope:o,DefaultAction:c==="allow"?{Allow:{}}:{Block:{}},Description:`WAF for ${i} ${s}`,Rules:[],VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${l}-metric`}}},logicalId:u}}static setRateLimit(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{RateBasedStatement:{Limit:i.requestsPerWindow,AggregateKeyType:i.aggregateKeyType||"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static blockCountries(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{GeoMatchStatement:{CountryCodes:i.countryCodes}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static blockIpAddresses(n,i,s,o){let c=r({slug:s,environment:o,resourceType:"ipset"}),l=t(`${c}-${i.name}`),u={Type:"AWS::WAFv2::IPSet",Properties:{Name:`${c}-${i.name}`,Scope:n.Properties.Scope,IPAddressVersion:i.ipVersion||"IPV4",Addresses:i.ipAddresses,Description:`Blocked IPs for ${i.name}`}};if(!n.Properties.Rules)n.Properties.Rules=[];return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{IPSetReferenceStatement:{Arn:k.GetAtt(l,"Arn")}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),{webAcl:n,ipSet:u,ipSetLogicalId:l}}static addManagedRules(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];let s={ManagedRuleGroupStatement:{VendorName:i.vendorName,Name:i.ruleName}};if(i.excludedRules&&i.excludedRules.length>0)s.ManagedRuleGroupStatement.ExcludedRules=i.excludedRules.map((o)=>({Name:o}));return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:s,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}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(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];let s=i.paths.map((o)=>({SearchString:o,FieldToMatch:{UriPath:{}},TextTransformation:[{Priority:0,Type:"LOWERCASE"}],PositionalConstraint:"STARTS_WITH"}));return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{RateBasedStatement:{Limit:i.requestsPerWindow,AggregateKeyType:i.aggregateKeyType||"IP",ScopeDownStatement:{OrStatement:{Statements:s.map((o)=>({ByteMatchStatement:o}))}}}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static setHeaderRateLimit(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];let s={RateBasedStatement:{Limit:i.requestsPerWindow,AggregateKeyType:"CUSTOM_KEYS",CustomKeys:[{Header:{Name:i.headerName,TextTransformations:[{Priority:0,Type:"NONE"}]}}]}};if(i.headerValue)s.RateBasedStatement.ScopeDownStatement={ByteMatchStatement:{SearchString:i.headerValue,FieldToMatch:{SingleHeader:{Name:i.headerName}},TextTransformation:[{Priority:0,Type:"NONE"}],PositionalConstraint:"EXACTLY"}};return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:s,Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static protectLoginEndpoint(n,i){let{loginPaths:s,priority:o,requestsPerMinute:c=10}=i;return C.setPathRateLimit(n,{name:"LoginRateLimit",priority:o,requestsPerWindow:c*5,paths:s}),n}static protectApiEndpoints(n,i){let{apiPaths:s,priority:o,requestsPerMinute:c=100}=i;return C.setPathRateLimit(n,{name:"ApiRateLimit",priority:o,requestsPerWindow:c*5,paths:s}),n}static createProtectedFirewall(n){let{slug:i,environment:s,scope:o="CLOUDFRONT",enableBotControl:c=!1,enableRateLimiting:l=!0,rateLimitPerMinute:u=2000}=n,{webAcl:h,logicalId:f}=C.createFirewall({slug:i,environment:s,scope:o,defaultAction:"allow"}),S=0;if(h=C.addManagedRules(h,{name:"AWSIPReputationList",priority:S++,...C.ManagedRuleGroups.AmazonIpReputation}),h=C.addManagedRules(h,{name:"AWSAnonymousIPList",priority:S++,...C.ManagedRuleGroups.AnonymousIpList}),h=C.addManagedRules(h,{name:"AWSCoreRuleSet",priority:S++,...C.ManagedRuleGroups.CoreRuleSet}),h=C.addManagedRules(h,{name:"AWSKnownBadInputs",priority:S++,...C.ManagedRuleGroups.KnownBadInputs}),h=C.addManagedRules(h,{name:"AWSSQLi",priority:S++,...C.ManagedRuleGroups.SqlDatabase}),c)h=C.addManagedRules(h,{name:"AWSBotControl",priority:S++,...C.ManagedRuleGroups.BotControl});if(l)h=C.setRateLimit(h,{name:"GlobalRateLimit",priority:S++,requestsPerWindow:u*5});return{webAcl:h,logicalId:f}}static RateLimitPresets={STANDARD:2000,HIGH_TRAFFIC:1e4,STRICT:100,LOGIN:10,API:100}}class a{static createServer(n){let{slug:i,environment:s,instanceType:o="t3.micro",imageId:c="ami-0f3caa1cf4417e51b",keyName:l,securityGroupIds:u,subnetId:h,userData:f,volumeSize:S=20,volumeType:b="gp3",encrypted:A=!0}=n,v=r({slug:i,environment:s,resourceType:"ec2"}),w=t(v),E={Type:"AWS::EC2::Instance",Properties:{ImageId:c,InstanceType:o,Tags:[{Key:"Name",Value:v},{Key:"Environment",Value:s}]}};if(l)E.Properties.KeyName=l;if(u)E.Properties.SecurityGroupIds=u;if(h)E.Properties.SubnetId=h;if(f)E.Properties.UserData=k.Base64(f);return E.Properties.BlockDeviceMappings=[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:S,VolumeType:b,Encrypted:A,DeleteOnTermination:!0}}],{instance:E,logicalId:w}}static createSecurityGroup(n){let{slug:i,environment:s,vpcId:o,description:c,ingress:l=[],egress:u=[]}=n,h=r({slug:i,environment:s,resourceType:"sg"}),f=t(h),S={Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:c||`Security group for ${i} ${s}`,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(o)S.Properties.VpcId=o;if(l.length>0)S.Properties.SecurityGroupIngress=l.map((b)=>({IpProtocol:b.protocol,FromPort:b.fromPort,ToPort:b.toPort,CidrIp:b.cidr,SourceSecurityGroupId:b.sourceSecurityGroupId}));if(u.length>0)S.Properties.SecurityGroupEgress=u.map((b)=>({IpProtocol:b.protocol,FromPort:b.fromPort,ToPort:b.toPort,CidrIp:b.cidr,DestinationSecurityGroupId:b.sourceSecurityGroupId}));return{securityGroup:S,logicalId:f}}static createWebServerSecurityGroup(n,i,s){return a.createSecurityGroup({slug:n,environment:i,vpcId:s,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(n){let{slug:i,environment:s,scheme:o="internet-facing",subnets:c,securityGroups:l,type:u="application"}=n,h=r({slug:i,environment:s,resourceType:"alb"}),f=t(h),S={Type:"AWS::ElasticLoadBalancingV2::LoadBalancer",Properties:{Name:h,Scheme:o,Type:u,Subnets:c,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(l)S.Properties.SecurityGroups=l;return{loadBalancer:S,logicalId:f}}static createTargetGroup(n){let{slug:i,environment:s,port:o,protocol:c="HTTP",vpcId:l,targetType:u="ip",healthCheckPath:h="/",healthCheckInterval:f=30,healthCheckTimeout:S=5,healthyThreshold:b=2,unhealthyThreshold:A=3}=n,v=r({slug:i,environment:s,resourceType:"tg"}),w=t(v);return{targetGroup:{Type:"AWS::ElasticLoadBalancingV2::TargetGroup",Properties:{Name:v,Port:o,Protocol:c,VpcId:l,TargetType:u,HealthCheckEnabled:!0,HealthCheckProtocol:c,HealthCheckPath:h,HealthCheckIntervalSeconds:f,HealthCheckTimeoutSeconds:S,HealthyThresholdCount:b,UnhealthyThresholdCount:A,Tags:[{Key:"Name",Value:v},{Key:"Environment",Value:s}]}},logicalId:w}}static createListener(n,i){let{port:s,protocol:o="HTTP",certificateArn:c,defaultTargetGroupArn:l}=i,u=t(`listener-${n}-${s}`),h={Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:k.Ref(n),Port:s,Protocol:o,DefaultActions:[{Type:"forward",TargetGroupArn:l}]}};if(o==="HTTPS"&&c)h.Properties.Certificates=[{CertificateArn:c}],h.Properties.SslPolicy="ELBSecurityPolicy-TLS13-1-2-2021-06";return{listener:h,logicalId:u}}static createEcsCluster(n,i){let s=r({slug:n,environment:i,resourceType:"ecs-cluster"}),o=t(s);return{cluster:{Type:"AWS::ECS::Cluster",Properties:{ClusterName:s,Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:i}]}},logicalId:o}}static createFargateService(n){let{slug:i,environment:s,image:o,cpu:c="256",memory:l="512",desiredCount:u=1,containerPort:h=8080,environmentVariables:f={},secrets:S=[],healthCheck:b,logGroup:A,subnets:v,securityGroups:w,targetGroupArn:E}=n,{cluster:P,logicalId:R}=a.createEcsCluster(i,s),D=r({slug:i,environment:s,resourceType:"fargate"}),O=t(`${D}-execution-role`),I={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"]}},_=t(`${D}-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"}]}}},W=t(`${D}-task`),J={Type:"AWS::ECS::TaskDefinition",Properties:{Family:D,TaskRoleArn:k.GetAtt(_,"Arn"),ExecutionRoleArn:k.GetAtt(O,"Arn"),NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:c,Memory:l,ContainerDefinitions:[{Name:i,Image:o,Essential:!0,PortMappings:[{ContainerPort:h,Protocol:"tcp"}],Environment:Object.entries(f).map(([Z,ne])=>({Name:Z,Value:ne})),Secrets:S.map((Z)=>({Name:Z.name,ValueFrom:Z.valueFrom}))}],Tags:[{Key:"Name",Value:D},{Key:"Environment",Value:s}]}};if(b)J.Properties.ContainerDefinitions[0].HealthCheck={Command:b.command,Interval:b.interval||30,Timeout:b.timeout||5,Retries:b.retries||3,StartPeriod:60};if(A)J.Properties.ContainerDefinitions[0].LogConfiguration={LogDriver:"awslogs",Options:{"awslogs-group":A,"awslogs-region":k.Ref("AWS::Region"),"awslogs-stream-prefix":i}};let K=t(`${D}-service`),Y={Type:"AWS::ECS::Service",Properties:{ServiceName:D,Cluster:k.Ref(R),TaskDefinition:k.Ref(W),DesiredCount:u,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{Subnets:v,SecurityGroups:w,AssignPublicIp:"ENABLED"}},Tags:[{Key:"Name",Value:D},{Key:"Environment",Value:s}]}};if(E)Y.Properties.LoadBalancers=[{TargetGroupArn:E,ContainerName:i,ContainerPort:h}];return{cluster:P,taskDefinition:J,service:Y,taskRole:B,executionRole:I,clusterLogicalId:R,taskDefinitionLogicalId:W,serviceLogicalId:K,taskRoleLogicalId:_,executionRoleLogicalId:O}}static createLambdaFunction(n){let{slug:i,environment:s,runtime:o,handler:c,code:l,timeout:u=30,memorySize:h=128,environmentVariables:f={},vpcConfig:S}=n,b=r({slug:i,environment:s,resourceType:"lambda"}),A=t(b),v=t(`${b}-role`),w={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]}};if(S)w.Properties.ManagedPolicyArns.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");let E={Type:"AWS::Lambda::Function",Properties:{FunctionName:b,Runtime:o,Role:k.GetAtt(v,"Arn"),Handler:c,Code:{...l.s3Bucket&&{S3Bucket:l.s3Bucket},...l.s3Key&&{S3Key:l.s3Key},...l.zipFile&&{ZipFile:l.zipFile}},Timeout:u,MemorySize:h,Tags:[{Key:"Name",Value:b},{Key:"Environment",Value:s}]}};if(Object.keys(f).length>0)E.Properties.Environment={Variables:f};if(S)E.Properties.VpcConfig={SecurityGroupIds:S.securityGroupIds,SubnetIds:S.subnetIds};return{lambdaFunction:E,role:w,logicalId:A,roleLogicalId:v}}static generateNodeServerUserData(n={}){let{nodeVersion:i="20",appRepo:s,environment:o={}}=n,c=Object.entries(o).map(([l,u])=>`echo "export ${l}='${u}'" >> /etc/environment`).join(`
|
|
213
213
|
`);return`#!/bin/bash
|
|
214
214
|
# Update system
|
|
215
215
|
yum update -y
|
|
@@ -318,7 +318,7 @@ yum install -y amazon-efs-utils nfs-utils jq curl wget htop
|
|
|
318
318
|
mkdir -p ${B}
|
|
319
319
|
mount -t efs ${S.fileSystemId}:/ ${B}
|
|
320
320
|
echo "${S.fileSystemId}:/ ${B} efs defaults,_netdev 0 0" >> /etc/fstab
|
|
321
|
-
`}let
|
|
321
|
+
`}let O=t(b),I={Type:"AWS::EC2::Instance",DependsOn:[P],Properties:{ImageId:h,InstanceType:u,KeyName:l,SubnetId:c,SecurityGroupIds:[k.Ref(A)],IamInstanceProfile:k.Ref(P),UserData:k.Base64(D),BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:20,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0}}],Tags:[{Key:"Name",Value:b},{Key:"Environment",Value:s},{Key:"Purpose",Value:"JumpBox/Bastion"}]}},_={[A]:v,[w]:E,[P]:R,[O]:I};return{instance:I,securityGroup:v,instanceProfile:R,instanceRole:E,instanceLogicalId:O,securityGroupLogicalId:A,instanceProfileLogicalId:P,instanceRoleLogicalId:w,resources:_}}static JumpBox={withEfsMount:(n)=>a.createJumpBox({slug:n.slug,environment:n.environment,vpcId:n.vpcId,subnetId:n.subnetId,keyName:n.keyName,allowedCidrs:n.allowedCidrs,mountEfs:{fileSystemId:n.fileSystemId,mountPath:n.mountPath||"/mnt/efs"}}),minimal:(n)=>a.createJumpBox({slug:n.slug,environment:n.environment,vpcId:n.vpcId,subnetId:n.subnetId,keyName:n.keyName,instanceType:"t3.nano",allowedCidrs:n.allowedCidrs}),withDatabaseTools:(n)=>{let i=a.createJumpBox({slug:n.slug,environment:n.environment,vpcId:n.vpcId,subnetId:n.subnetId,keyName:n.keyName,allowedCidrs:n.allowedCidrs}),s=`#!/bin/bash
|
|
322
322
|
yum update -y
|
|
323
323
|
yum install -y amazon-efs-utils nfs-utils jq curl wget htop
|
|
324
324
|
|
|
@@ -604,7 +604,7 @@ ufw default allow outgoing
|
|
|
604
604
|
${n.map((i)=>`ufw allow ${i}`).join(`
|
|
605
605
|
`)}
|
|
606
606
|
ufw --force enable
|
|
607
|
-
`},Presets:{bunWithNginx:(n,i=3000)=>a.UserData.generateAppServerScript({runtime:"bun",webServer:"nginx",processManager:"systemd",domain:n,appPort:i,enableSsl:!0}),bunWithCaddy:(n,i=3000)=>a.UserData.generateAppServerScript({runtime:"bun",webServer:"caddy",processManager:"systemd",domain:n,appPort:i,enableSsl:!1}),nodeWithPm2:(n,i=3000)=>a.UserData.generateAppServerScript({runtime:"node",webServer:"nginx",processManager:"pm2",domain:n,appPort:i,enableSsl:!0}),worker:(n="bun")=>a.UserData.generateAppServerScript({runtime:n,webServer:"none",processManager:"systemd",enableSsl:!1})}};static createElasticIp(n){let{slug:i,environment:s,domain:o,instanceLogicalId:c}=n,l=r({slug:i,environment:s,resourceType:"eip"}),u=t(l),h={Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s},...o?[{Key:"Domain",Value:o}]:[]]}},f={[u]:h},S,b;if(c)b=t(`${l}-assoc`),S={Type:"AWS::EC2::EIPAssociation",Properties:{AllocationId:k.GetAtt(u,"AllocationId"),InstanceId:k.Ref(c)}},f[b]=S;return{eip:h,eipAssociation:S,eipLogicalId:u,associationLogicalId:b,resources:f}}static createServerModeStack(n){let{slug:i,environment:s,vpcId:o,subnetId:c,instanceType:l="t3.small",imageId:u="ami-0f3caa1cf4417e51b",keyName:h,domain:f,userData:S,allowedPorts:b=[22,80,443],volumeSize:A=20,volumeType:v="gp3"}=n,w={},E=r({slug:i,environment:s,resourceType:"server-sg"}),P=t(E),R={Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:E,GroupDescription:`Security group for ${i} server`,VpcId:o,SecurityGroupIngress:b.map((ie)=>({IpProtocol:"tcp",FromPort:ie,ToPort:ie,CidrIp:"0.0.0.0/0",Description:`Port ${ie}`})),SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound"}],Tags:[{Key:"Name",Value:E},{Key:"Environment",Value:s}]}};w[P]=R;let D=r({slug:i,environment:s,resourceType:"server-role"}),
|
|
607
|
+
`},Presets:{bunWithNginx:(n,i=3000)=>a.UserData.generateAppServerScript({runtime:"bun",webServer:"nginx",processManager:"systemd",domain:n,appPort:i,enableSsl:!0}),bunWithCaddy:(n,i=3000)=>a.UserData.generateAppServerScript({runtime:"bun",webServer:"caddy",processManager:"systemd",domain:n,appPort:i,enableSsl:!1}),nodeWithPm2:(n,i=3000)=>a.UserData.generateAppServerScript({runtime:"node",webServer:"nginx",processManager:"pm2",domain:n,appPort:i,enableSsl:!0}),worker:(n="bun")=>a.UserData.generateAppServerScript({runtime:n,webServer:"none",processManager:"systemd",enableSsl:!1})}};static createElasticIp(n){let{slug:i,environment:s,domain:o,instanceLogicalId:c}=n,l=r({slug:i,environment:s,resourceType:"eip"}),u=t(l),h={Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s},...o?[{Key:"Domain",Value:o}]:[]]}},f={[u]:h},S,b;if(c)b=t(`${l}-assoc`),S={Type:"AWS::EC2::EIPAssociation",Properties:{AllocationId:k.GetAtt(u,"AllocationId"),InstanceId:k.Ref(c)}},f[b]=S;return{eip:h,eipAssociation:S,eipLogicalId:u,associationLogicalId:b,resources:f}}static createServerModeStack(n){let{slug:i,environment:s,vpcId:o,subnetId:c,instanceType:l="t3.small",imageId:u="ami-0f3caa1cf4417e51b",keyName:h,domain:f,userData:S,allowedPorts:b=[22,80,443],volumeSize:A=20,volumeType:v="gp3"}=n,w={},E=r({slug:i,environment:s,resourceType:"server-sg"}),P=t(E),R={Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:E,GroupDescription:`Security group for ${i} server`,VpcId:o,SecurityGroupIngress:b.map((ie)=>({IpProtocol:"tcp",FromPort:ie,ToPort:ie,CidrIp:"0.0.0.0/0",Description:`Port ${ie}`})),SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound"}],Tags:[{Key:"Name",Value:E},{Key:"Environment",Value:s}]}};w[P]=R;let D=r({slug:i,environment:s,resourceType:"server-role"}),O=t(D),I={Type:"AWS::IAM::Role",Properties:{RoleName:D,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ec2.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore","arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"],Policies:[{PolicyName:"StacksServerPermissions",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail","ses:SendBulkEmail","ses:VerifyDomainIdentity","ses:VerifyDomainDkim","ses:GetIdentityDkimAttributes","ses:GetIdentityVerificationAttributes"],Resource:"*"},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:ListBucket"],Resource:"*"},{Effect:"Allow",Action:["route53:ChangeResourceRecordSets","route53:ListResourceRecordSets","route53:GetHostedZone"],Resource:"*"},{Effect:"Allow",Action:["ssm:GetParameter","ssm:GetParameters"],Resource:"*"}]}}]}};w[O]=I;let _=r({slug:i,environment:s,resourceType:"server-profile"}),B=t(_),W={Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:_,Roles:[k.Ref(O)]}};w[B]=W;let J=r({slug:i,environment:s,resourceType:"server"}),K=t(J),Y={Type:"AWS::EC2::Instance",DependsOn:[B],Properties:{ImageId:u,InstanceType:l,KeyName:h,SubnetId:c,SecurityGroupIds:[k.Ref(P)],IamInstanceProfile:k.Ref(B),BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:A,VolumeType:v,Encrypted:!0,DeleteOnTermination:!0}}],Tags:[{Key:"Name",Value:J},{Key:"Environment",Value:s},...f?[{Key:"Domain",Value:f}]:[]]}};if(S)Y.Properties.UserData=k.Base64(S);w[K]=Y;let{eip:Z,eipAssociation:ne,eipLogicalId:de,associationLogicalId:oe,resources:le}=a.createElasticIp({slug:i,environment:s,domain:f,instanceLogicalId:K});return Object.assign(w,le),{instance:Y,securityGroup:R,eip:Z,eipAssociation:ne,instanceRole:I,instanceProfile:W,resources:w,outputs:{instanceLogicalId:K,securityGroupLogicalId:P,eipLogicalId:de,associationLogicalId:oe,roleLogicalId:O,profileLogicalId:B}}}static ServerMode={webServer:(n)=>{let i=a.UserData.generateAppServerScript({runtime:n.runtime||"bun",webServer:n.webServer||"nginx",domain:n.domain,enableSsl:!0});return a.createServerModeStack({...n,userData:i,instanceType:"t3.small",allowedPorts:[22,80,443]})},workerServer:(n)=>{let i=a.UserData.generateAppServerScript({runtime:n.runtime||"bun",webServer:"none",installRedis:n.installRedis});return a.createServerModeStack({...n,userData:i,instanceType:"t3.medium",allowedPorts:[22]})},cacheServer:(n)=>a.createServerModeStack({...n,userData:`#!/bin/bash
|
|
608
608
|
set -e
|
|
609
609
|
apt-get update && apt-get upgrade -y
|
|
610
610
|
apt-get install -y redis-server
|
|
@@ -612,7 +612,7 @@ sed -i 's/bind 127.0.0.1/bind 0.0.0.0/' /etc/redis/redis.conf
|
|
|
612
612
|
systemctl enable redis-server
|
|
613
613
|
systemctl restart redis-server
|
|
614
614
|
echo "Redis server setup complete!"
|
|
615
|
-
`,instanceType:"t3.medium",allowedPorts:[22,6379]})}}class y{static createVpc(n){let{slug:i,environment:s,cidr:o="10.0.0.0/16",enableDnsHostnames:c=!0,enableDnsSupport:l=!0}=n,u=r({slug:i,environment:s,resourceType:"vpc"}),h=t(u);return{vpc:{Type:"AWS::EC2::VPC",Properties:{CidrBlock:o,EnableDnsHostnames:c,EnableDnsSupport:l,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:s}]}},logicalId:h}}static createSubnet(n){let{slug:i,environment:s,vpcId:o,type:c,cidr:l,availabilityZone:u,mapPublicIp:h=c==="public"}=n,f=r({slug:i,environment:s,resourceType:`subnet-${c}`}),S=t(`${f}-${u}`);return{subnet:{Type:"AWS::EC2::Subnet",Properties:{VpcId:o,CidrBlock:l,AvailabilityZone:u,MapPublicIpOnLaunch:h,Tags:[{Key:"Name",Value:`${f}-${u}`},{Key:"Environment",Value:s},{Key:"Type",Value:c}]}},logicalId:S}}static createInternetGateway(n,i){let s=r({slug:n,environment:i,resourceType:"igw"}),o=t(s);return{internetGateway:{Type:"AWS::EC2::InternetGateway",Properties:{Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:i}]}},logicalId:o}}static attachInternetGateway(n,i){let s=t(`${n}-igw-attachment`);return{attachment:{Type:"AWS::EC2::VPCGatewayAttachment",Properties:{VpcId:k.Ref(n),InternetGatewayId:k.Ref(i)}},logicalId:s}}static createEip(n,i){let s=r({slug:n,environment:i,resourceType:"eip"}),o=t(s);return{eip:{Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:i}]}},logicalId:o}}static createNatGateway(n,i){let{slug:s,environment:o,subnetId:c}=n,l=r({slug:s,environment:o,resourceType:"nat"}),u=t(l);return{natGateway:{Type:"AWS::EC2::NatGateway",Properties:{AllocationId:k.GetAtt(i,"AllocationId"),SubnetId:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:o},{Key:"Warning",Value:"NAT Gateway incurs hourly charges"}]}},logicalId:u}}static createRouteTable(n,i,s,o){let c=r({slug:n,environment:i,resourceType:`rt-${o}`}),l=t(c);return{routeTable:{Type:"AWS::EC2::RouteTable",Properties:{VpcId:k.Ref(s),Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:i},{Key:"Type",Value:o}]}},logicalId:l}}static createRoute(n,i,s){let o=t(`${n}-route-${s.type}`),c={Type:"AWS::EC2::Route",Properties:{RouteTableId:k.Ref(n),DestinationCidrBlock:i}};if(s.type==="igw")c.Properties.GatewayId=k.Ref(s.logicalId);else if(s.type==="nat")c.Properties.NatGatewayId=k.Ref(s.logicalId);else if(s.type==="instance")c.Properties.InstanceId=k.Ref(s.logicalId);return{route:c,logicalId:o}}static associateSubnetWithRouteTable(n,i){let s=t(`${n}-rt-assoc`);return{association:{Type:"AWS::EC2::SubnetRouteTableAssociation",Properties:{SubnetId:k.Ref(n),RouteTableId:k.Ref(i)}},logicalId:s}}static enableFlowLogs(n){let{slug:i,environment:s,resourceId:o,resourceType:c,trafficType:l="ALL",logGroupName:u}=n,h=r({slug:i,environment:s,resourceType:"flowlog"}),f=t(h);return{flowLog:{Type:"AWS::EC2::FlowLog",Properties:{ResourceType:c,ResourceIds:[o],TrafficType:l,LogDestinationType:"cloud-watch-logs",LogGroupName:u||`/aws/vpc/${i}-${s}`,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}},logicalId:f}}static calculateSubnetCidrs(n,i,s=3){let[o,c]=n.split("/"),l=Number.parseInt(c,10),u=Math.ceil(Math.log2(i*s)),h=l+u;if(h>28)throw Error("VPC CIDR is too small to accommodate requested subnets");let[f,S,b,A]=o.split(".").map(Number),v=(f<<24)+(S<<16)+(b<<8)+A,w=2**(32-h),E=[];for(let P=0;P<i*s;P++){let R=v+P*w,D=[R>>>24&255,R>>>16&255,R>>>8&255,R&255].join(".");E.push(`${D}/${h}`)}return E}static getAvailabilityZones(n,i){return["a","b","c","d","e","f"].slice(0,i).map((s)=>`${n}${s}`)}static createMultiAzNetwork(n){let{slug:i,environment:s,region:o,cidr:c="10.0.0.0/16",zones:l=3,enableNatGateway:u=!1,singleNatGateway:h=!1,enableFlowLogs:f=!1}=n,S={},b=[],A=[],v=[],{vpc:w,logicalId:E}=y.createVpc({slug:i,environment:s,cidr:c});S[E]=w;let{internetGateway:P,logicalId:R}=y.createInternetGateway(i,s);S[R]=P;let{attachment:D,logicalId:
|
|
615
|
+
`,instanceType:"t3.medium",allowedPorts:[22,6379]})}}class y{static createVpc(n){let{slug:i,environment:s,cidr:o="10.0.0.0/16",enableDnsHostnames:c=!0,enableDnsSupport:l=!0}=n,u=r({slug:i,environment:s,resourceType:"vpc"}),h=t(u);return{vpc:{Type:"AWS::EC2::VPC",Properties:{CidrBlock:o,EnableDnsHostnames:c,EnableDnsSupport:l,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:s}]}},logicalId:h}}static createSubnet(n){let{slug:i,environment:s,vpcId:o,type:c,cidr:l,availabilityZone:u,mapPublicIp:h=c==="public"}=n,f=r({slug:i,environment:s,resourceType:`subnet-${c}`}),S=t(`${f}-${u}`);return{subnet:{Type:"AWS::EC2::Subnet",Properties:{VpcId:o,CidrBlock:l,AvailabilityZone:u,MapPublicIpOnLaunch:h,Tags:[{Key:"Name",Value:`${f}-${u}`},{Key:"Environment",Value:s},{Key:"Type",Value:c}]}},logicalId:S}}static createInternetGateway(n,i){let s=r({slug:n,environment:i,resourceType:"igw"}),o=t(s);return{internetGateway:{Type:"AWS::EC2::InternetGateway",Properties:{Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:i}]}},logicalId:o}}static attachInternetGateway(n,i){let s=t(`${n}-igw-attachment`);return{attachment:{Type:"AWS::EC2::VPCGatewayAttachment",Properties:{VpcId:k.Ref(n),InternetGatewayId:k.Ref(i)}},logicalId:s}}static createEip(n,i){let s=r({slug:n,environment:i,resourceType:"eip"}),o=t(s);return{eip:{Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:i}]}},logicalId:o}}static createNatGateway(n,i){let{slug:s,environment:o,subnetId:c}=n,l=r({slug:s,environment:o,resourceType:"nat"}),u=t(l);return{natGateway:{Type:"AWS::EC2::NatGateway",Properties:{AllocationId:k.GetAtt(i,"AllocationId"),SubnetId:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:o},{Key:"Warning",Value:"NAT Gateway incurs hourly charges"}]}},logicalId:u}}static createRouteTable(n,i,s,o){let c=r({slug:n,environment:i,resourceType:`rt-${o}`}),l=t(c);return{routeTable:{Type:"AWS::EC2::RouteTable",Properties:{VpcId:k.Ref(s),Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:i},{Key:"Type",Value:o}]}},logicalId:l}}static createRoute(n,i,s){let o=t(`${n}-route-${s.type}`),c={Type:"AWS::EC2::Route",Properties:{RouteTableId:k.Ref(n),DestinationCidrBlock:i}};if(s.type==="igw")c.Properties.GatewayId=k.Ref(s.logicalId);else if(s.type==="nat")c.Properties.NatGatewayId=k.Ref(s.logicalId);else if(s.type==="instance")c.Properties.InstanceId=k.Ref(s.logicalId);return{route:c,logicalId:o}}static associateSubnetWithRouteTable(n,i){let s=t(`${n}-rt-assoc`);return{association:{Type:"AWS::EC2::SubnetRouteTableAssociation",Properties:{SubnetId:k.Ref(n),RouteTableId:k.Ref(i)}},logicalId:s}}static enableFlowLogs(n){let{slug:i,environment:s,resourceId:o,resourceType:c,trafficType:l="ALL",logGroupName:u}=n,h=r({slug:i,environment:s,resourceType:"flowlog"}),f=t(h);return{flowLog:{Type:"AWS::EC2::FlowLog",Properties:{ResourceType:c,ResourceIds:[o],TrafficType:l,LogDestinationType:"cloud-watch-logs",LogGroupName:u||`/aws/vpc/${i}-${s}`,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}},logicalId:f}}static calculateSubnetCidrs(n,i,s=3){let[o,c]=n.split("/"),l=Number.parseInt(c,10),u=Math.ceil(Math.log2(i*s)),h=l+u;if(h>28)throw Error("VPC CIDR is too small to accommodate requested subnets");let[f,S,b,A]=o.split(".").map(Number),v=(f<<24)+(S<<16)+(b<<8)+A,w=2**(32-h),E=[];for(let P=0;P<i*s;P++){let R=v+P*w,D=[R>>>24&255,R>>>16&255,R>>>8&255,R&255].join(".");E.push(`${D}/${h}`)}return E}static getAvailabilityZones(n,i){return["a","b","c","d","e","f"].slice(0,i).map((s)=>`${n}${s}`)}static createMultiAzNetwork(n){let{slug:i,environment:s,region:o,cidr:c="10.0.0.0/16",zones:l=3,enableNatGateway:u=!1,singleNatGateway:h=!1,enableFlowLogs:f=!1}=n,S={},b=[],A=[],v=[],{vpc:w,logicalId:E}=y.createVpc({slug:i,environment:s,cidr:c});S[E]=w;let{internetGateway:P,logicalId:R}=y.createInternetGateway(i,s);S[R]=P;let{attachment:D,logicalId:O}=y.attachInternetGateway(E,R);S[O]=D;let{routeTable:I,logicalId:_}=y.createRouteTable(i,s,E,"public");S[_]=I;let{route:B,logicalId:W}=y.createRoute(_,"0.0.0.0/0",{type:"igw",logicalId:R});B.DependsOn=O,S[W]=B;let J=y.calculateSubnetCidrs(c,l,2),K=y.getAvailabilityZones(o,l),Y=[];for(let Z=0;Z<l;Z++){let ne=K[Z],de=J[Z*2],oe=J[Z*2+1],{subnet:le,logicalId:ie}=y.createSubnet({slug:i,environment:s,vpcId:k.Ref(E),type:"public",cidr:de,availabilityZone:ne});S[ie]=le,b.push(ie);let{association:Ee,logicalId:Fe}=y.associateSubnetWithRouteTable(ie,_);S[Fe]=Ee;let{subnet:Et,logicalId:pe}=y.createSubnet({slug:i,environment:s,vpcId:k.Ref(E),type:"private",cidr:oe,availabilityZone:ne});if(S[pe]=Et,A.push(pe),u&&(!h||Z===0)){let{eip:ue,logicalId:he}=y.createEip(`${i}-${ne}`,s);S[he]=ue;let{natGateway:Ie,logicalId:ye}=y.createNatGateway({slug:`${i}-${ne}`,environment:s,subnetId:k.Ref(ie)},he);Ie.DependsOn=O,S[ye]=Ie,v.push(ye);let{routeTable:Ae,logicalId:Me}=y.createRouteTable(`${i}-${ne}`,s,E,"private");S[Me]=Ae,Y.push(Me);let{route:Ue,logicalId:z}=y.createRoute(Me,"0.0.0.0/0",{type:"nat",logicalId:ye});S[z]=Ue;let{association:ae,logicalId:X}=y.associateSubnetWithRouteTable(pe,Me);S[X]=ae}else if(u&&h&&Z>0){let{association:ue,logicalId:he}=y.associateSubnetWithRouteTable(pe,Y[0]);S[he]=ue}else{let{routeTable:ue,logicalId:he}=y.createRouteTable(`${i}-${ne}-isolated`,s,E,"private");S[he]=ue;let{association:Ie,logicalId:ye}=y.associateSubnetWithRouteTable(pe,he);S[ye]=Ie}}if(f){let{flowLog:Z,logicalId:ne}=y.enableFlowLogs({slug:i,environment:s,resourceId:k.Ref(E),resourceType:"VPC"});S[ne]=Z}return{resources:S,outputs:{vpcId:E,publicSubnetIds:b,privateSubnetIds:A,natGatewayIds:v.length>0?v:void 0}}}static NatGatewayCostWarning=`
|
|
616
616
|
⚠️ NAT Gateway Cost Warning:
|
|
617
617
|
- Each NAT Gateway costs approximately $32-45/month (hourly charges)
|
|
618
618
|
- Data processing charges: $0.045/GB processed
|
|
@@ -620,7 +620,7 @@ echo "Redis server setup complete!"
|
|
|
620
620
|
- Using a single NAT Gateway (singleNatGateway: true)
|
|
621
621
|
- Using NAT Instances instead (cheaper but requires management)
|
|
622
622
|
- Disabling NAT entirely for isolated private subnets
|
|
623
|
-
`}class Ke{static createFileSystem(n){let{slug:i,environment:s,encrypted:o=!0,kmsKeyId:c,performanceMode:l="generalPurpose",throughputMode:u="bursting",provisionedThroughput:h,enableBackup:f=!0}=n,S=r({slug:i,environment:s,resourceType:"efs"}),b=t(S),A={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:o,PerformanceMode:l,ThroughputMode:u,FileSystemTags:[{Key:"Name",Value:S},{Key:"Environment",Value:s}]}};if(c)A.Properties.KmsKeyId=c;if(u==="provisioned"&&h)A.Properties.ProvisionedThroughputInMibps=h;if(f)A.Properties.BackupPolicy={Status:"ENABLED"};return{fileSystem:A,logicalId:b}}static createMountTarget(n,i){let{slug:s,environment:o,subnetId:c,securityGroups:l,ipAddress:u}=i,h=r({slug:s,environment:o,resourceType:"efs-mt"}),f=t(`${h}-${c}`),S={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:k.Ref(n),SubnetId:c,SecurityGroups:l}};if(u)S.Properties.IpAddress=u;return{mountTarget:S,logicalId:f}}static createAccessPoint(n,i){let{slug:s,environment:o,path:c="/",uid:l="1000",gid:u="1000",permissions:h="755"}=i,f=r({slug:s,environment:o,resourceType:"efs-ap"}),S=t(`${f}-${c.replace(/\//g,"-")}`);return{accessPoint:{Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:k.Ref(n),PosixUser:{Uid:l,Gid:u},RootDirectory:{Path:c,CreationInfo:{OwnerUid:l,OwnerGid:u,Permissions:h}},AccessPointTags:[{Key:"Name",Value:`${f}-${c}`},{Key:"Environment",Value:o}]}},logicalId:S}}static setLifecyclePolicy(n,i){let{transitionToIA:s,transitionToPrimary:o=!1}=i;if(!n.Properties)n.Properties={};if(n.Properties.LifecyclePolicies=[],s){let c=`AFTER_${s}_DAYS`;n.Properties.LifecyclePolicies.push({TransitionToIA:c})}if(o)n.Properties.LifecyclePolicies.push({TransitionToPrimaryStorageClass:"AFTER_1_ACCESS"});return n}static enableBackup(n){if(!n.Properties)n.Properties={};return n.Properties.BackupPolicy={Status:"ENABLED"},n}static disableBackup(n){if(!n.Properties)n.Properties={};return n.Properties.BackupPolicy={Status:"DISABLED"},n}static setProvisionedThroughput(n,i){if(!n.Properties)n.Properties={};return n.Properties.ThroughputMode="provisioned",n.Properties.ProvisionedThroughputInMibps=i,n}static setElasticThroughput(n){if(!n.Properties)n.Properties={};return n.Properties.ThroughputMode="elastic",n}static enableMaxIO(n){if(!n.Properties)n.Properties={};return n.Properties.PerformanceMode="maxIO",n}static createEfsSecurityGroup(n){let{slug:i,environment:s,vpcId:o,sourceSecurityGroupIds:c=[],sourceCidrBlocks:l=[],description:u}=n,h=r({slug:i,environment:s,resourceType:"efs-sg"}),f=t(h),S=[];for(let b of c)S.push({IpProtocol:"tcp",FromPort:2049,ToPort:2049,SourceSecurityGroupId:b,Description:"NFS from security group"});for(let b of l)S.push({IpProtocol:"tcp",FromPort:2049,ToPort:2049,CidrIp:b,Description:"NFS from CIDR block"});return{securityGroup:{Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:h,GroupDescription:u||`Security group for EFS mount targets - ${i} ${s}`,VpcId:o,SecurityGroupIngress:S,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}},logicalId:f}}static createMultiAzMountTargets(n,i){let{slug:s,environment:o,subnetIds:c,securityGroupId:l}=i,u=[],h=[];for(let f=0;f<c.length;f++){let S=c[f],b=r({slug:s,environment:o,resourceType:"efs-mt"}),A=t(`${b}-az${f+1}`),v={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:k.Ref(n),SubnetId:S,SecurityGroups:[l]}};u.push(v),h.push(A)}return{mountTargets:u,logicalIds:h}}static createCompleteFileSystem(n){let{slug:i,environment:s,vpcId:o,subnetIds:c,sourceSecurityGroupIds:l=[],encrypted:u=!0,performanceMode:h="generalPurpose",throughputMode:f="elastic",enableBackup:S=!0,transitionToIA:b}=n,A={},{fileSystem:v,logicalId:w}=Ke.createFileSystem({slug:i,environment:s,encrypted:u,performanceMode:h,throughputMode:f,enableBackup:S});if(b)Ke.setLifecyclePolicy(v,{transitionToIA:b,transitionToPrimary:!0});A[w]=v;let{securityGroup:E,logicalId:P}=Ke.createEfsSecurityGroup({slug:i,environment:s,vpcId:o,sourceSecurityGroupIds:l});A[P]=E;let{mountTargets:R,logicalIds:D}=Ke.createMultiAzMountTargets(w,{slug:i,environment:s,subnetIds:c,securityGroupId:k.Ref(P)});for(let x=0;x<R.length;x++)A[D[x]]=R[x];return{resources:A,outputs:{fileSystemId:w,securityGroupId:P,mountTargetIds:D}}}}class m{static verifyDomain(n){let{domain:i,slug:s,environment:o,enableDkim:c=!0,dkimKeyLength:l="RSA_2048_BIT"}=n,u=r({slug:s,environment:o,resourceType:"ses-identity"}),h=t(`${u}-${i.replace(/\./g,"")}`),f={Type:"AWS::SES::EmailIdentity",Properties:{EmailIdentity:i,FeedbackAttributes:{EmailForwardingEnabled:!0}}};if(c)f.Properties.DkimSigningAttributes={NextSigningKeyLength:l};return{emailIdentity:f,logicalId:h}}static createDkimRecords(n,i,s){let o=[];for(let c=0;c<i.length;c++){let l=i[c],u=t(`dkim-${n.replace(/\./g,"")}-${c+1}`),h={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:s,Name:`${l}._domainkey.${n}`,Type:"CNAME",TTL:1800,ResourceRecords:[`${l}.dkim.amazonses.com`]}};o.push({record:h,logicalId:u})}return o}static createConfigurationSet(n){let{slug:i,environment:s,name:o,reputationMetrics:c=!0,sendingEnabled:l=!0,suppressBounces:u=!0,suppressComplaints:h=!0}=n,f=o||r({slug:i,environment:s,resourceType:"ses-config"}),S=t(f),b=[];if(u)b.push("BOUNCE");if(h)b.push("COMPLAINT");return{configurationSet:{Type:"AWS::SES::ConfigurationSet",Properties:{Name:f,ReputationOptions:{ReputationMetricsEnabled:c},SendingOptions:{SendingEnabled:l},SuppressionOptions:{SuppressedReasons:b}}},logicalId:S}}static createReceiptRuleSet(n){let{slug:i,environment:s,name:o}=n,c=o||r({slug:i,environment:s,resourceType:"ses-ruleset"}),l=t(c);return{ruleSet:{Type:"AWS::SES::ReceiptRuleSet",Properties:{RuleSetName:c}},logicalId:l}}static createReceiptRule(n,i){let{slug:s,environment:o,ruleSetName:c,recipients:l,enabled:u=!0,scanEnabled:h=!0,tlsPolicy:f="Require",s3Action:S,lambdaAction:b,snsAction:A}=i,v=r({slug:s,environment:o,resourceType:"ses-rule"}),w=t(v),E=[];if(S)E.push({S3Action:{BucketName:S.bucketName,ObjectKeyPrefix:S.prefix,KmsKeyArn:S.kmsKeyArn}});if(b)E.push({LambdaAction:{FunctionArn:b.functionArn,InvocationType:b.invocationType||"Event"}});if(A)E.push({SNSAction:{TopicArn:A.topicArn,Encoding:A.encoding||"UTF-8"}});return{receiptRule:{Type:"AWS::SES::ReceiptRule",Properties:{RuleSetName:c,Rule:{Name:v,Enabled:u,ScanEnabled:h,TlsPolicy:f,Recipients:l,Actions:E.length>0?E:void 0}}},logicalId:w}}static createMxRecord(n,i,s){let o=t(`mx-${n.replace(/\./g,"")}`);return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:n,Type:"MX",TTL:300,ResourceRecords:[`10 inbound-smtp.${s}.amazonaws.com`]}},logicalId:o}}static createVerificationRecord(n,i,s){let o=t(`verification-${n.replace(/\./g,"")}`);return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:s,Name:`_amazonses.${n}`,Type:"TXT",TTL:1800,ResourceRecords:[`"${i}"`]}},logicalId:o}}static getSmtpEndpoint(n){return`email-smtp.${n}.amazonaws.com`}static SmtpPorts={TLS:587,SSL:465,Unencrypted:25};static createSpfRecord(n,i,s){let{includeDomains:o=[],softFail:c=!1}=s||{},l=t(`spf-${n.replace(/\./g,"")}`),u="v=spf1 include:amazonses.com";for(let h of o)u+=` include:${h}`;return u+=c?" ~all":" -all",{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:n,Type:"TXT",TTL:300,ResourceRecords:[`"${u}"`]}},logicalId:l}}static createDmarcRecord(n,i,s){let{policy:o="none",subdomainPolicy:c,percentage:l=100,reportingEmail:u,forensicEmail:h}=s||{},f=t(`dmarc-${n.replace(/\./g,"")}`),S=`v=DMARC1; p=${o}; pct=${l}`;if(c)S+=`; sp=${c}`;if(u)S+=`; rua=mailto:${u}`;if(h)S+=`; ruf=mailto:${h}`;return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:`_dmarc.${n}`,Type:"TXT",TTL:300,ResourceRecords:[`"${S}"`]}},logicalId:f}}static createInboundEmailSetup(n){let{slug:i,environment:s,domain:o,s3BucketName:c,s3KeyPrefix:l="inbound/",region:u,hostedZoneId:h,lambdaFunctionArn:f,snsTopicArn:S}=n,b={},{ruleSet:A,logicalId:v}=m.createReceiptRuleSet({slug:i,environment:s});b[v]=A;let{receiptRule:w,logicalId:E}=m.createReceiptRule(v,{slug:i,environment:s,ruleSetName:A.Properties.RuleSetName||`${i}-${s}-receipt-rule-set`,recipients:[o],s3Action:{bucketName:c,prefix:l},lambdaAction:f?{functionArn:f,invocationType:"Event"}:void 0,snsAction:S?{topicArn:S}:void 0});b[E]=w;let{record:P,logicalId:R}=m.createMxRecord(o,h,u);return b[R]=P,{resources:b,outputs:{ruleSetLogicalId:v,ruleLogicalId:E,mxRecordLogicalId:R}}}static createCompleteDomainSetup(n){let{slug:i,environment:s,domain:o,hostedZoneId:c,region:l,enableInbound:u=!1,inboundS3Bucket:h,dmarcReportingEmail:f}=n,S={},{emailIdentity:b,logicalId:A}=m.verifyDomain({domain:o,slug:i,environment:s});S[A]=b;let{configurationSet:v,logicalId:w}=m.createConfigurationSet({slug:i,environment:s});S[w]=v;let{record:E,logicalId:P}=m.createSpfRecord(o,c);S[P]=E;let{record:R,logicalId:D}=m.createDmarcRecord(o,c,{policy:"none",reportingEmail:f||`dmarc-reports@${o}`});if(S[D]=R,u&&h){let x=m.createInboundEmailSetup({slug:i,environment:s,domain:o,s3BucketName:h,region:l,hostedZoneId:c});Object.assign(S,x.resources)}return{resources:S,outputs:{identityLogicalId:A,configSetLogicalId:w}}}static InboundSmtpEndpoints={"us-east-1":"inbound-smtp.us-east-1.amazonaws.com","us-west-2":"inbound-smtp.us-west-2.amazonaws.com","eu-west-1":"inbound-smtp.eu-west-1.amazonaws.com"};static supportsInboundEmail(n){return n in m.InboundSmtpEndpoints}static createEmailLambdaRole(n){let{slug:i,environment:s,s3BucketArn:o,sesIdentityArn:c}=n,l=r({slug:i,environment:s,resourceType:"email-lambda-role"}),u=t(l),h=t(`${l}-policy`),f={Type:"AWS::IAM::Role",Properties:{RoleName:l,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s}]}},S=[{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[o,`${o}/*`]}];if(c)S.push({Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail"],Resource:c});let b={Type:"AWS::IAM::Policy",Properties:{PolicyName:`${l}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:S},Roles:[k.Ref(u)]}};return{role:f,policy:b,roleLogicalId:u,policyLogicalId:h}}static createOutboundEmailLambda(n){let{slug:i,environment:s,roleArn:o,domain:c,configurationSetName:l,timeout:u=30,memorySize:h=256}=n,f=r({slug:i,environment:s,resourceType:"outbound-email"}),S=t(f);return{function:{Type:"AWS::Lambda::Function",Properties:{FunctionName:f,Runtime:"nodejs20.x",Handler:"index.handler",Role:o,Timeout:u,MemorySize:h,Environment:{Variables:{DOMAIN:c,CONFIGURATION_SET:l||""}},Code:{ZipFile:m.LambdaCode.outboundEmail},Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s},{Key:"Purpose",Value:"OutboundEmail"}]}},logicalId:S}}static createInboundEmailLambda(n){let{slug:i,environment:s,roleArn:o,s3BucketName:c,organizedPrefix:l="organized/",timeout:u=60,memorySize:h=512}=n,f=r({slug:i,environment:s,resourceType:"inbound-email"}),S=t(f),b=t(`${f}-permission`),A={Type:"AWS::Lambda::Function",Properties:{FunctionName:f,Runtime:"nodejs20.x",Handler:"index.handler",Role:o,Timeout:u,MemorySize:h,Environment:{Variables:{S3_BUCKET:c,ORGANIZED_PREFIX:l}},Code:{ZipFile:m.LambdaCode.inboundEmail},Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s},{Key:"Purpose",Value:"InboundEmail"}]}},v={Type:"AWS::Lambda::Permission",Properties:{FunctionName:k.Ref(S),Action:"lambda:InvokeFunction",Principal:"ses.amazonaws.com",SourceAccount:k.Ref("AWS::AccountId")}};return{function:A,permission:v,logicalId:S,permissionLogicalId:b}}static createEmailConversionLambda(n){let{slug:i,environment:s,roleArn:o,s3BucketName:c,convertedPrefix:l="converted/",timeout:u=60,memorySize:h=512}=n,f=r({slug:i,environment:s,resourceType:"email-conversion"}),S=t(f);return{function:{Type:"AWS::Lambda::Function",Properties:{FunctionName:f,Runtime:"nodejs20.x",Handler:"index.handler",Role:o,Timeout:u,MemorySize:h,Environment:{Variables:{S3_BUCKET:c,CONVERTED_PREFIX:l}},Code:{ZipFile:m.LambdaCode.emailConversion},Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s},{Key:"Purpose",Value:"EmailConversion"}]}},logicalId:S}}static createEmailBucketNotification(n){let{lambdaArn:i,prefix:s="inbound/",suffix:o,events:c}=n,l=c??["s3:ObjectCreated:*"],u={};if(s||o){if(u.S3Key={Rules:[]},s)u.S3Key.Rules.push({Name:"prefix",Value:s});if(o)u.S3Key.Rules.push({Name:"suffix",Value:o})}return{notificationConfiguration:{LambdaConfigurations:[{Event:l[0],Function:i,Filter:Object.keys(u).length>0?u:void 0}]}}}static createS3LambdaPermission(n){let{slug:i,environment:s,lambdaLogicalId:o,s3BucketArn:c}=n,l=r({slug:i,environment:s,resourceType:"s3-lambda-permission"}),u=t(l);return{permission:{Type:"AWS::Lambda::Permission",Properties:{FunctionName:k.Ref(o),Action:"lambda:InvokeFunction",Principal:"s3.amazonaws.com",SourceArn:c}},logicalId:u}}static createEmailProcessingStack(n){let{slug:i,environment:s,domain:o,s3BucketName:c,s3BucketArn:l,configurationSetName:u,enableInbound:h=!0,enableConversion:f=!0}=n,S={},{role:b,policy:A,roleLogicalId:v,policyLogicalId:w}=m.createEmailLambdaRole({slug:i,environment:s,s3BucketArn:l,sesIdentityArn:`arn:aws:ses:*:*:identity/${o}`});S[v]=b,S[w]=A;let{function:E,logicalId:P}=m.createOutboundEmailLambda({slug:i,environment:s,roleArn:k.GetAtt(v,"Arn"),domain:o,configurationSetName:u});S[P]=E;let R={roleLogicalId:v,outboundLambdaLogicalId:P};if(h){let{function:D,permission:x,logicalId:I,permissionLogicalId:_}=m.createInboundEmailLambda({slug:i,environment:s,roleArn:k.GetAtt(v,"Arn"),s3BucketName:c});S[I]=D,S[_]=x;let{permission:B,logicalId:W}=m.createS3LambdaPermission({slug:i,environment:s,lambdaLogicalId:I,s3BucketArn:l});S[W]=B,R.inboundLambdaLogicalId=I}if(f){let{function:D,logicalId:x}=m.createEmailConversionLambda({slug:i,environment:s,roleArn:k.GetAtt(v,"Arn"),s3BucketName:c});S[x]=D,R.conversionLambdaLogicalId=x}return{resources:S,outputs:R}}static LambdaCode={outboundEmail:`
|
|
623
|
+
`}class Ke{static createFileSystem(n){let{slug:i,environment:s,encrypted:o=!0,kmsKeyId:c,performanceMode:l="generalPurpose",throughputMode:u="bursting",provisionedThroughput:h,enableBackup:f=!0}=n,S=r({slug:i,environment:s,resourceType:"efs"}),b=t(S),A={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:o,PerformanceMode:l,ThroughputMode:u,FileSystemTags:[{Key:"Name",Value:S},{Key:"Environment",Value:s}]}};if(c)A.Properties.KmsKeyId=c;if(u==="provisioned"&&h)A.Properties.ProvisionedThroughputInMibps=h;if(f)A.Properties.BackupPolicy={Status:"ENABLED"};return{fileSystem:A,logicalId:b}}static createMountTarget(n,i){let{slug:s,environment:o,subnetId:c,securityGroups:l,ipAddress:u}=i,h=r({slug:s,environment:o,resourceType:"efs-mt"}),f=t(`${h}-${c}`),S={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:k.Ref(n),SubnetId:c,SecurityGroups:l}};if(u)S.Properties.IpAddress=u;return{mountTarget:S,logicalId:f}}static createAccessPoint(n,i){let{slug:s,environment:o,path:c="/",uid:l="1000",gid:u="1000",permissions:h="755"}=i,f=r({slug:s,environment:o,resourceType:"efs-ap"}),S=t(`${f}-${c.replace(/\//g,"-")}`);return{accessPoint:{Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:k.Ref(n),PosixUser:{Uid:l,Gid:u},RootDirectory:{Path:c,CreationInfo:{OwnerUid:l,OwnerGid:u,Permissions:h}},AccessPointTags:[{Key:"Name",Value:`${f}-${c}`},{Key:"Environment",Value:o}]}},logicalId:S}}static setLifecyclePolicy(n,i){let{transitionToIA:s,transitionToPrimary:o=!1}=i;if(!n.Properties)n.Properties={};if(n.Properties.LifecyclePolicies=[],s){let c=`AFTER_${s}_DAYS`;n.Properties.LifecyclePolicies.push({TransitionToIA:c})}if(o)n.Properties.LifecyclePolicies.push({TransitionToPrimaryStorageClass:"AFTER_1_ACCESS"});return n}static enableBackup(n){if(!n.Properties)n.Properties={};return n.Properties.BackupPolicy={Status:"ENABLED"},n}static disableBackup(n){if(!n.Properties)n.Properties={};return n.Properties.BackupPolicy={Status:"DISABLED"},n}static setProvisionedThroughput(n,i){if(!n.Properties)n.Properties={};return n.Properties.ThroughputMode="provisioned",n.Properties.ProvisionedThroughputInMibps=i,n}static setElasticThroughput(n){if(!n.Properties)n.Properties={};return n.Properties.ThroughputMode="elastic",n}static enableMaxIO(n){if(!n.Properties)n.Properties={};return n.Properties.PerformanceMode="maxIO",n}static createEfsSecurityGroup(n){let{slug:i,environment:s,vpcId:o,sourceSecurityGroupIds:c=[],sourceCidrBlocks:l=[],description:u}=n,h=r({slug:i,environment:s,resourceType:"efs-sg"}),f=t(h),S=[];for(let b of c)S.push({IpProtocol:"tcp",FromPort:2049,ToPort:2049,SourceSecurityGroupId:b,Description:"NFS from security group"});for(let b of l)S.push({IpProtocol:"tcp",FromPort:2049,ToPort:2049,CidrIp:b,Description:"NFS from CIDR block"});return{securityGroup:{Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:h,GroupDescription:u||`Security group for EFS mount targets - ${i} ${s}`,VpcId:o,SecurityGroupIngress:S,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}},logicalId:f}}static createMultiAzMountTargets(n,i){let{slug:s,environment:o,subnetIds:c,securityGroupId:l}=i,u=[],h=[];for(let f=0;f<c.length;f++){let S=c[f],b=r({slug:s,environment:o,resourceType:"efs-mt"}),A=t(`${b}-az${f+1}`),v={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:k.Ref(n),SubnetId:S,SecurityGroups:[l]}};u.push(v),h.push(A)}return{mountTargets:u,logicalIds:h}}static createCompleteFileSystem(n){let{slug:i,environment:s,vpcId:o,subnetIds:c,sourceSecurityGroupIds:l=[],encrypted:u=!0,performanceMode:h="generalPurpose",throughputMode:f="elastic",enableBackup:S=!0,transitionToIA:b}=n,A={},{fileSystem:v,logicalId:w}=Ke.createFileSystem({slug:i,environment:s,encrypted:u,performanceMode:h,throughputMode:f,enableBackup:S});if(b)Ke.setLifecyclePolicy(v,{transitionToIA:b,transitionToPrimary:!0});A[w]=v;let{securityGroup:E,logicalId:P}=Ke.createEfsSecurityGroup({slug:i,environment:s,vpcId:o,sourceSecurityGroupIds:l});A[P]=E;let{mountTargets:R,logicalIds:D}=Ke.createMultiAzMountTargets(w,{slug:i,environment:s,subnetIds:c,securityGroupId:k.Ref(P)});for(let O=0;O<R.length;O++)A[D[O]]=R[O];return{resources:A,outputs:{fileSystemId:w,securityGroupId:P,mountTargetIds:D}}}}class m{static verifyDomain(n){let{domain:i,slug:s,environment:o,enableDkim:c=!0,dkimKeyLength:l="RSA_2048_BIT"}=n,u=r({slug:s,environment:o,resourceType:"ses-identity"}),h=t(`${u}-${i.replace(/\./g,"")}`),f={Type:"AWS::SES::EmailIdentity",Properties:{EmailIdentity:i,FeedbackAttributes:{EmailForwardingEnabled:!0}}};if(c)f.Properties.DkimSigningAttributes={NextSigningKeyLength:l};return{emailIdentity:f,logicalId:h}}static createDkimRecords(n,i,s){let o=[];for(let c=0;c<i.length;c++){let l=i[c],u=t(`dkim-${n.replace(/\./g,"")}-${c+1}`),h={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:s,Name:`${l}._domainkey.${n}`,Type:"CNAME",TTL:1800,ResourceRecords:[`${l}.dkim.amazonses.com`]}};o.push({record:h,logicalId:u})}return o}static createConfigurationSet(n){let{slug:i,environment:s,name:o,reputationMetrics:c=!0,sendingEnabled:l=!0,suppressBounces:u=!0,suppressComplaints:h=!0}=n,f=o||r({slug:i,environment:s,resourceType:"ses-config"}),S=t(f),b=[];if(u)b.push("BOUNCE");if(h)b.push("COMPLAINT");return{configurationSet:{Type:"AWS::SES::ConfigurationSet",Properties:{Name:f,ReputationOptions:{ReputationMetricsEnabled:c},SendingOptions:{SendingEnabled:l},SuppressionOptions:{SuppressedReasons:b}}},logicalId:S}}static createReceiptRuleSet(n){let{slug:i,environment:s,name:o}=n,c=o||r({slug:i,environment:s,resourceType:"ses-ruleset"}),l=t(c);return{ruleSet:{Type:"AWS::SES::ReceiptRuleSet",Properties:{RuleSetName:c}},logicalId:l}}static createReceiptRule(n,i){let{slug:s,environment:o,ruleSetName:c,recipients:l,enabled:u=!0,scanEnabled:h=!0,tlsPolicy:f="Require",s3Action:S,lambdaAction:b,snsAction:A}=i,v=r({slug:s,environment:o,resourceType:"ses-rule"}),w=t(v),E=[];if(S)E.push({S3Action:{BucketName:S.bucketName,ObjectKeyPrefix:S.prefix,KmsKeyArn:S.kmsKeyArn}});if(b)E.push({LambdaAction:{FunctionArn:b.functionArn,InvocationType:b.invocationType||"Event"}});if(A)E.push({SNSAction:{TopicArn:A.topicArn,Encoding:A.encoding||"UTF-8"}});return{receiptRule:{Type:"AWS::SES::ReceiptRule",Properties:{RuleSetName:c,Rule:{Name:v,Enabled:u,ScanEnabled:h,TlsPolicy:f,Recipients:l,Actions:E.length>0?E:void 0}}},logicalId:w}}static createMxRecord(n,i,s){let o=t(`mx-${n.replace(/\./g,"")}`);return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:n,Type:"MX",TTL:300,ResourceRecords:[`10 inbound-smtp.${s}.amazonaws.com`]}},logicalId:o}}static createVerificationRecord(n,i,s){let o=t(`verification-${n.replace(/\./g,"")}`);return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:s,Name:`_amazonses.${n}`,Type:"TXT",TTL:1800,ResourceRecords:[`"${i}"`]}},logicalId:o}}static getSmtpEndpoint(n){return`email-smtp.${n}.amazonaws.com`}static SmtpPorts={TLS:587,SSL:465,Unencrypted:25};static createSpfRecord(n,i,s){let{includeDomains:o=[],softFail:c=!1}=s||{},l=t(`spf-${n.replace(/\./g,"")}`),u="v=spf1 include:amazonses.com";for(let h of o)u+=` include:${h}`;return u+=c?" ~all":" -all",{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:n,Type:"TXT",TTL:300,ResourceRecords:[`"${u}"`]}},logicalId:l}}static createDmarcRecord(n,i,s){let{policy:o="none",subdomainPolicy:c,percentage:l=100,reportingEmail:u,forensicEmail:h}=s||{},f=t(`dmarc-${n.replace(/\./g,"")}`),S=`v=DMARC1; p=${o}; pct=${l}`;if(c)S+=`; sp=${c}`;if(u)S+=`; rua=mailto:${u}`;if(h)S+=`; ruf=mailto:${h}`;return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:`_dmarc.${n}`,Type:"TXT",TTL:300,ResourceRecords:[`"${S}"`]}},logicalId:f}}static createInboundEmailSetup(n){let{slug:i,environment:s,domain:o,s3BucketName:c,s3KeyPrefix:l="inbound/",region:u,hostedZoneId:h,lambdaFunctionArn:f,snsTopicArn:S}=n,b={},{ruleSet:A,logicalId:v}=m.createReceiptRuleSet({slug:i,environment:s});b[v]=A;let{receiptRule:w,logicalId:E}=m.createReceiptRule(v,{slug:i,environment:s,ruleSetName:A.Properties.RuleSetName||`${i}-${s}-receipt-rule-set`,recipients:[o],s3Action:{bucketName:c,prefix:l},lambdaAction:f?{functionArn:f,invocationType:"Event"}:void 0,snsAction:S?{topicArn:S}:void 0});b[E]=w;let{record:P,logicalId:R}=m.createMxRecord(o,h,u);return b[R]=P,{resources:b,outputs:{ruleSetLogicalId:v,ruleLogicalId:E,mxRecordLogicalId:R}}}static createCompleteDomainSetup(n){let{slug:i,environment:s,domain:o,hostedZoneId:c,region:l,enableInbound:u=!1,inboundS3Bucket:h,dmarcReportingEmail:f}=n,S={},{emailIdentity:b,logicalId:A}=m.verifyDomain({domain:o,slug:i,environment:s});S[A]=b;let{configurationSet:v,logicalId:w}=m.createConfigurationSet({slug:i,environment:s});S[w]=v;let{record:E,logicalId:P}=m.createSpfRecord(o,c);S[P]=E;let{record:R,logicalId:D}=m.createDmarcRecord(o,c,{policy:"none",reportingEmail:f||`dmarc-reports@${o}`});if(S[D]=R,u&&h){let O=m.createInboundEmailSetup({slug:i,environment:s,domain:o,s3BucketName:h,region:l,hostedZoneId:c});Object.assign(S,O.resources)}return{resources:S,outputs:{identityLogicalId:A,configSetLogicalId:w}}}static InboundSmtpEndpoints={"us-east-1":"inbound-smtp.us-east-1.amazonaws.com","us-west-2":"inbound-smtp.us-west-2.amazonaws.com","eu-west-1":"inbound-smtp.eu-west-1.amazonaws.com"};static supportsInboundEmail(n){return n in m.InboundSmtpEndpoints}static createEmailLambdaRole(n){let{slug:i,environment:s,s3BucketArn:o,sesIdentityArn:c}=n,l=r({slug:i,environment:s,resourceType:"email-lambda-role"}),u=t(l),h=t(`${l}-policy`),f={Type:"AWS::IAM::Role",Properties:{RoleName:l,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s}]}},S=[{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[o,`${o}/*`]}];if(c)S.push({Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail"],Resource:c});let b={Type:"AWS::IAM::Policy",Properties:{PolicyName:`${l}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:S},Roles:[k.Ref(u)]}};return{role:f,policy:b,roleLogicalId:u,policyLogicalId:h}}static createOutboundEmailLambda(n){let{slug:i,environment:s,roleArn:o,domain:c,configurationSetName:l,timeout:u=30,memorySize:h=256}=n,f=r({slug:i,environment:s,resourceType:"outbound-email"}),S=t(f);return{function:{Type:"AWS::Lambda::Function",Properties:{FunctionName:f,Runtime:"nodejs20.x",Handler:"index.handler",Role:o,Timeout:u,MemorySize:h,Environment:{Variables:{DOMAIN:c,CONFIGURATION_SET:l||""}},Code:{ZipFile:m.LambdaCode.outboundEmail},Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s},{Key:"Purpose",Value:"OutboundEmail"}]}},logicalId:S}}static createInboundEmailLambda(n){let{slug:i,environment:s,roleArn:o,s3BucketName:c,organizedPrefix:l="organized/",timeout:u=60,memorySize:h=512}=n,f=r({slug:i,environment:s,resourceType:"inbound-email"}),S=t(f),b=t(`${f}-permission`),A={Type:"AWS::Lambda::Function",Properties:{FunctionName:f,Runtime:"nodejs20.x",Handler:"index.handler",Role:o,Timeout:u,MemorySize:h,Environment:{Variables:{S3_BUCKET:c,ORGANIZED_PREFIX:l}},Code:{ZipFile:m.LambdaCode.inboundEmail},Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s},{Key:"Purpose",Value:"InboundEmail"}]}},v={Type:"AWS::Lambda::Permission",Properties:{FunctionName:k.Ref(S),Action:"lambda:InvokeFunction",Principal:"ses.amazonaws.com",SourceAccount:k.Ref("AWS::AccountId")}};return{function:A,permission:v,logicalId:S,permissionLogicalId:b}}static createEmailConversionLambda(n){let{slug:i,environment:s,roleArn:o,s3BucketName:c,convertedPrefix:l="converted/",timeout:u=60,memorySize:h=512}=n,f=r({slug:i,environment:s,resourceType:"email-conversion"}),S=t(f);return{function:{Type:"AWS::Lambda::Function",Properties:{FunctionName:f,Runtime:"nodejs20.x",Handler:"index.handler",Role:o,Timeout:u,MemorySize:h,Environment:{Variables:{S3_BUCKET:c,CONVERTED_PREFIX:l}},Code:{ZipFile:m.LambdaCode.emailConversion},Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s},{Key:"Purpose",Value:"EmailConversion"}]}},logicalId:S}}static createEmailBucketNotification(n){let{lambdaArn:i,prefix:s="inbound/",suffix:o,events:c}=n,l=c??["s3:ObjectCreated:*"],u={};if(s||o){if(u.S3Key={Rules:[]},s)u.S3Key.Rules.push({Name:"prefix",Value:s});if(o)u.S3Key.Rules.push({Name:"suffix",Value:o})}return{notificationConfiguration:{LambdaConfigurations:[{Event:l[0],Function:i,Filter:Object.keys(u).length>0?u:void 0}]}}}static createS3LambdaPermission(n){let{slug:i,environment:s,lambdaLogicalId:o,s3BucketArn:c}=n,l=r({slug:i,environment:s,resourceType:"s3-lambda-permission"}),u=t(l);return{permission:{Type:"AWS::Lambda::Permission",Properties:{FunctionName:k.Ref(o),Action:"lambda:InvokeFunction",Principal:"s3.amazonaws.com",SourceArn:c}},logicalId:u}}static createEmailProcessingStack(n){let{slug:i,environment:s,domain:o,s3BucketName:c,s3BucketArn:l,configurationSetName:u,enableInbound:h=!0,enableConversion:f=!0}=n,S={},{role:b,policy:A,roleLogicalId:v,policyLogicalId:w}=m.createEmailLambdaRole({slug:i,environment:s,s3BucketArn:l,sesIdentityArn:`arn:aws:ses:*:*:identity/${o}`});S[v]=b,S[w]=A;let{function:E,logicalId:P}=m.createOutboundEmailLambda({slug:i,environment:s,roleArn:k.GetAtt(v,"Arn"),domain:o,configurationSetName:u});S[P]=E;let R={roleLogicalId:v,outboundLambdaLogicalId:P};if(h){let{function:D,permission:O,logicalId:I,permissionLogicalId:_}=m.createInboundEmailLambda({slug:i,environment:s,roleArn:k.GetAtt(v,"Arn"),s3BucketName:c});S[I]=D,S[_]=O;let{permission:B,logicalId:W}=m.createS3LambdaPermission({slug:i,environment:s,lambdaLogicalId:I,s3BucketArn:l});S[W]=B,R.inboundLambdaLogicalId=I}if(f){let{function:D,logicalId:O}=m.createEmailConversionLambda({slug:i,environment:s,roleArn:k.GetAtt(v,"Arn"),s3BucketName:c});S[O]=D,R.conversionLambdaLogicalId=O}return{resources:S,outputs:R}}static LambdaCode={outboundEmail:`
|
|
624
624
|
const { SESClient, SendRawEmailCommand } = require('@aws-sdk/client-ses');
|
|
625
625
|
const ses = new SESClient({});
|
|
626
626
|
|
|
@@ -2306,14 +2306,14 @@ function resolveTemplate(template, data) {
|
|
|
2306
2306
|
}
|
|
2307
2307
|
return result;
|
|
2308
2308
|
}
|
|
2309
|
-
`;class Q{static LambdaCode={send:ka,receive:vr,deliveryStatus:Cr};static createPinpointApp(n){return{[`${n.slug}PinpointApp`]:{Type:"AWS::Pinpoint::App",Properties:{Name:n.name||`${n.slug}-sms`}}}}static createSmsChannel(n){let i={ApplicationId:n.applicationId,Enabled:n.enabled!==!1};if(n.senderId)i.SenderId=n.senderId;if(n.shortCode)i.ShortCode=n.shortCode;return{[`${n.slug}SmsChannel`]:{Type:"AWS::Pinpoint::SMSChannel",Properties:i}}}static createSmsLambdaRole(n){return{[`${n.slug}SmsLambdaRole`]:{Type:"AWS::IAM::Role",Properties:{RoleName:`${n.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(n){return{[`${n.slug}SmsSendLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-send`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Q.LambdaCode.send},Environment:{Variables:{PINPOINT_APP_ID:n.pinpointAppId,MESSAGE_LOG_TABLE:n.messageLogTable||"",SMS_SENDER_ID:n.senderId||"",SMS_ORIGINATION_NUMBER:n.originationNumber||""}}}}}}static createReceiveLambda(n){return{[`${n.slug}SmsReceiveLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-receive`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Q.LambdaCode.receive},Environment:{Variables:{OPT_OUT_TABLE:n.optOutTable||"",MESSAGE_LOG_TABLE:n.messageLogTable||"",NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createDeliveryStatusLambda(n){return{[`${n.slug}SmsDeliveryStatusLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-delivery-status`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Q.LambdaCode.deliveryStatus},Environment:{Variables:{MESSAGE_LOG_TABLE:n.messageLogTable||"",NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createMessageLogTable(n){return{[`${n.slug}SmsMessageLogTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-sms-messages`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createOptOutTable(n){return{[`${n.slug}SmsOptOutTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-sms-optouts`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}]}}}}static createNotificationTopic(n){return{[`${n.slug}SmsNotificationTopic`]:{Type:"AWS::SNS::Topic",Properties:{TopicName:`${n.slug}-sms-notifications`}}}}static createCompleteSetup(n){let i={},s={};Object.assign(i,Q.createPinpointApp({slug:n.slug})),Object.assign(i,Q.createSmsChannel({slug:n.slug,applicationId:{Ref:`${n.slug}PinpointApp`},senderId:n.senderId})),Object.assign(i,Q.createSmsLambdaRole({slug:n.slug})),Object.assign(i,Q.createMessageLogTable({slug:n.slug})),Object.assign(i,Q.createOptOutTable({slug:n.slug})),Object.assign(i,Q.createNotificationTopic({slug:n.slug}));let o={"Fn::GetAtt":[`${n.slug}SmsLambdaRole`,"Arn"]},c={Ref:`${n.slug}PinpointApp`},l={Ref:`${n.slug}SmsMessageLogTable`},u={Ref:`${n.slug}SmsOptOutTable`},h={Ref:`${n.slug}SmsNotificationTopic`};if(Object.assign(i,Q.createSendLambda({slug:n.slug,roleArn:o,pinpointAppId:c,messageLogTable:l,senderId:n.senderId,originationNumber:n.originationNumber})),n.twoWayEnabled)Object.assign(i,Q.createReceiveLambda({slug:n.slug,roleArn:o,optOutTable:u,messageLogTable:l,notificationTopicArn:h,webhookUrl:n.webhookUrl}));return Object.assign(i,Q.createDeliveryStatusLambda({slug:n.slug,roleArn:o,messageLogTable:l,notificationTopicArn:h,webhookUrl:n.webhookUrl})),s[`${n.slug}PinpointAppId`]={Description:"Pinpoint application ID",Value:{Ref:`${n.slug}PinpointApp`}},s[`${n.slug}SmsSendLambdaArn`]={Description:"SMS send Lambda ARN",Value:{"Fn::GetAtt":[`${n.slug}SmsSendLambda`,"Arn"]}},s[`${n.slug}SmsNotificationTopicArn`]={Description:"SMS notification topic ARN",Value:{Ref:`${n.slug}SmsNotificationTopic`}},s[`${n.slug}SmsMessageLogTableName`]={Description:"SMS message log table name",Value:{Ref:`${n.slug}SmsMessageLogTable`}},{resources:i,outputs:s}}}function Rt(n){return n.replace(/[^a-zA-Z0-9]/g," ").trim().split(/\s+/).map((i)=>i.charAt(0).toUpperCase()+i.slice(1)).join("")||"User"}function wr(n,i){let s=(n||i).replace(/^\/+|\/+$/g,"");if(!s||s.split("/").includes(".."))throw Error(`sftp: invalid homeDirectory for user ${i}`);return s}function Er(n){let i=n.storage;if(i?.type==="efs"){let o="fileSystemId"in i?i.fileSystemId:void 0;if(!o||typeof o==="string"&&!o.trim())throw Error("sftp: EFS storage requires fileSystemId, or a fileSystem name defined in infrastructure.fileSystem");return{type:"efs",fileSystemId:o,posixProfile:i.posixProfile}}let s=(i?.type==="s3"?i.bucket??n.bucket:n.bucket)?.trim();if(!s)throw Error("sftp: S3 storage requires bucket, or a storageBucket name defined in infrastructure.storage");return{type:"s3",bucket:s}}function Pr(n,i,s){let o=i.posixProfile??s;if(!o)throw Error(`sftp: user ${n} requires a posixProfile (uid/gid) on an EFS-backed server`);for(let c of[o.uid,o.gid,...o.secondaryGids??[]])if(!Number.isInteger(c)||c<0||c>4294967295)throw Error(`sftp: user ${n} has an invalid posixProfile id ${c}`);return{Uid:o.uid,Gid:o.gid,...o.secondaryGids?.length?{SecondaryGids:o.secondaryGids}:{}}}function Ir(n,i){return typeof n==="string"?`/${n}/${i}`:{"Fn::Sub":[`/\${FileSystemId}/${i}`,{FileSystemId:n}]}}function Rr(n){return typeof n==="string"?{"Fn::Sub":"arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}".replace("${FileSystemId}",n)}:{"Fn::Sub":["arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}",{FileSystemId:n}]}}class Ld{static create(n){let i=Er(n),s=i.type==="efs"?"EFS":"S3",o=n.endpointType??"PUBLIC";if(o==="VPC"&&(!n.endpointDetails?.vpcId||!n.endpointDetails.subnetIds.length))throw Error("sftp: VPC endpoints require endpointDetails.vpcId and at least one subnet");let c=`${Rt(n.slug)}${Rt(n.environment)}Sftp`,l=`${c}Server`,u={},h;if(n.logging!==!1){let f=`${c}LoggingRole`;u[f]={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":[f,"Arn"]}}u[l]={Type:"AWS::Transfer::Server",Properties:{Domain:s,EndpointType:o,IdentityProviderType:"SERVICE_MANAGED",Protocols:["SFTP"],...o==="VPC"?{EndpointDetails:{VpcId:n.endpointDetails.vpcId,SubnetIds:n.endpointDetails.subnetIds,...n.endpointDetails.securityGroupIds?.length?{SecurityGroupIds:n.endpointDetails.securityGroupIds}:{},...n.endpointDetails.addressAllocationIds?.length?{AddressAllocationIds:n.endpointDetails.addressAllocationIds}:{}}}:{},...n.securityPolicyName?{SecurityPolicyName:n.securityPolicyName}:{},...h?{LoggingRole:h}:{},Tags:[{Key:"Project",Value:n.slug},{Key:"Environment",Value:n.environment},{Key:"ManagedBy",Value:"ts-cloud"}]}};for(let[f,S]of Object.entries(n.users)){if(!/^[a-zA-Z0-9_.@-]{3,100}$/.test(f))throw Error(`sftp: invalid username ${f}`);if(!S.sshPublicKeys.length)throw Error(`sftp: user ${f} requires at least one SSH public key`);let b=Rt(f),A=wr(S.homeDirectory,f),v=`${c}${b}User`,w=S.roleArn;if(!w){let E=`${c}${b}Role`,P;if(i.type==="efs")P=[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:DescribeMountTargets"],Resource:Rr(i.fileSystemId)}];else{let R=`arn:aws:s3:::${i.bucket}`;P=[{Effect:"Allow",Action:["s3:ListBucket","s3:GetBucketLocation"],Resource:R,Condition:{StringLike:{"s3:prefix":[A,`${A}/*`]}}},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:GetObjectVersion"],Resource:`${R}/${A}/*`}]}u[E]={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:P}}]}},w={"Fn::GetAtt":[E,"Arn"]}}u[v]={Type:"AWS::Transfer::User",DependsOn:[l],Properties:{ServerId:{Ref:l},UserName:f,Role:w,HomeDirectoryType:"PATH",HomeDirectory:i.type==="efs"?Ir(i.fileSystemId,A):`/${i.bucket}/${A}`,...i.type==="efs"?{PosixProfile:Pr(f,S,i.posixProfile)}:{},SshPublicKeys:S.sshPublicKeys}}}return{resources:u,serverLogicalId:l,domain:s}}}class Pe{static createBedrockRole(n,i){let{slug:s,environment:o,name:c,models:l=["*"],allowStreaming:u=!0}=i,h=c||r({slug:s,environment:o,resourceType:"bedrock-role"}),f=t(h),S=["bedrock:InvokeModel"];if(u)S.push("bedrock:InvokeModelWithResponseStream");let b=l.map((A)=>A==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${A}`);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:h,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:n},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:`${h}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:S,Resource:b}]}}],Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:o}]}},logicalId:f}}static createBedrockPolicy(n){let{slug:i,environment:s,name:o,models:c=["*"],allowInvoke:l=!0,allowStreaming:u=!0,allowAsync:h=!1}=n,f=o||r({slug:i,environment:s,resourceType:"bedrock-policy"}),S=t(f),b=[];if(l)b.push("bedrock:InvokeModel");if(u)b.push("bedrock:InvokeModelWithResponseStream");if(h)b.push("bedrock:InvokeModelAsync");let A=c.map((v)=>v==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${v}`);return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:f,PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"BedrockModelInvocation",Effect:"Allow",Action:b,Resource:A}]}}},logicalId:S}}static enableBedrockForLambda(n){return Pe.createBedrockRole("lambda.amazonaws.com",n)}static enableBedrockForEcs(n){return Pe.createBedrockRole("ecs-tasks.amazonaws.com",n)}static enableBedrockForEc2(n){return Pe.createBedrockRole("ec2.amazonaws.com",n)}static addBedrockPermissions(n,i=["*"],s=!0){let o=["bedrock:InvokeModel"];if(s)o.push("bedrock:InvokeModelWithResponseStream");let c=i.map((l)=>l==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${l}`);if(!n.Properties.Policies)n.Properties.Policies=[];return n.Properties.Policies.push({PolicyName:"bedrock-permissions",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:o,Resource:c}]}}),n}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 zt{static createPostgres(n){return zt.createRDSInstance("postgres","16.2",n)}static createMysql(n){return zt.createRDSInstance("mysql","8.0.35",n)}static createRDSInstance(n,i,s){let{slug:o,environment:c,instanceClass:l="db.t3.micro",allocatedStorage:u=20,storageType:h="gp3",masterUsername:f="admin",masterPassword:S,databaseName:b,subnetIds:A,securityGroupIds:v,encrypted:w=!0,kmsKeyId:E,multiAz:P=!1,backupRetentionDays:R=7,publiclyAccessible:D=!1,enableCloudwatchLogs:x=!0,deletionProtection:I=!0}=s,_=r({slug:o,environment:c,resourceType:`${n}-db`}),B=t(_),W,J;if(A&&A.length>0){let Y=r({slug:o,environment:c,resourceType:"db-subnet-group"});J=t(Y),W={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupName:Y,DBSubnetGroupDescription:`Subnet group for ${_}`,SubnetIds:A,Tags:[{Key:"Name",Value:Y},{Key:"Environment",Value:c}]}}}let K={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:_,DBInstanceClass:l,Engine:n,EngineVersion:i,MasterUsername:f,MasterUserPassword:S,AllocatedStorage:u,StorageType:h,StorageEncrypted:w,MultiAZ:P,BackupRetentionPeriod:R,PubliclyAccessible:D,DeletionProtection:I,Tags:[{Key:"Name",Value:_},{Key:"Environment",Value:c}]}};if(b)K.Properties.DBName=b;if(E)K.Properties.KmsKeyId=E;if(J)K.Properties.DBSubnetGroupName=k.Ref(J);if(v&&v.length>0)K.Properties.VPCSecurityGroups=v;if(x)K.Properties.EnableCloudwatchLogsExports=n==="postgres"?["postgresql"]:["error","general","slowquery"];return{dbInstance:K,subnetGroup:W,logicalId:B,subnetGroupId:J}}static createReadReplica(n,i){let{slug:s,environment:o,instanceClass:c="db.t3.micro",securityGroupIds:l,publiclyAccessible:u=!1}=i,h=r({slug:s,environment:o,resourceType:"db-replica"}),f=t(h),S={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:h,DBInstanceClass:c,SourceDBInstanceIdentifier:k.Ref(n),PubliclyAccessible:u,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:o},{Key:"Type",Value:"ReadReplica"}]}};if(l&&l.length>0)S.Properties.VPCSecurityGroups=l;return{replica:S,logicalId:f}}static createParameterGroup(n,i,s){let{slug:o,environment:c,parameters:l={}}=s,u=r({slug:o,environment:c,resourceType:"db-params"}),h=t(u),f=n==="postgres"?`postgres${i.split(".")[0]}`:`mysql${i.split(".")[0]}.${i.split(".")[1]}`;return{parameterGroup:{Type:"AWS::RDS::DBParameterGroup",Properties:{DBParameterGroupName:u,Description:`Parameter group for ${u}`,Family:f,Parameters:l,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:c}]}},logicalId:h}}static enableBackup(n,i=7){return n.Properties.BackupRetentionPeriod=i,n}static createTable(n){let{slug:i,environment:s,tableName:o,partitionKey:c,sortKey:l,billingMode:u="PAY_PER_REQUEST",readCapacity:h=5,writeCapacity:f=5,streamEnabled:S=!1,streamViewType:b="NEW_AND_OLD_IMAGES",encrypted:A=!0,kmsKeyId:v,pointInTimeRecovery:w=!0,ttlAttribute:E}=n,P=o||r({slug:i,environment:s,resourceType:"table"}),R=t(P),D=[{AttributeName:c.name,AttributeType:c.type}];if(l)D.push({AttributeName:l.name,AttributeType:l.type});let x=[{AttributeName:c.name,KeyType:"HASH"}];if(l)x.push({AttributeName:l.name,KeyType:"RANGE"});let I={Type:"AWS::DynamoDB::Table",Properties:{TableName:P,BillingMode:u,AttributeDefinitions:D,KeySchema:x,Tags:[{Key:"Name",Value:P},{Key:"Environment",Value:s}]}};if(u==="PROVISIONED")I.Properties.ProvisionedThroughput={ReadCapacityUnits:h,WriteCapacityUnits:f};if(S)I.Properties.StreamSpecification={StreamViewType:b};if(A)I.Properties.SSESpecification={SSEEnabled:!0,SSEType:v?"KMS":"AES256",KMSMasterKeyId:v};if(w)I.Properties.PointInTimeRecoverySpecification={PointInTimeRecoveryEnabled:!0};if(E)I.Properties.TimeToLiveSpecification={AttributeName:E,Enabled:!0};return{table:I,logicalId:R}}static addGlobalSecondaryIndex(n,i){let{indexName:s,partitionKey:o,sortKey:c,projectionType:l="ALL",nonKeyAttributes:u,readCapacity:h=5,writeCapacity:f=5}=i;if(!n.Properties.AttributeDefinitions.some((A)=>A.AttributeName===o.name))n.Properties.AttributeDefinitions.push({AttributeName:o.name,AttributeType:o.type});if(c&&!n.Properties.AttributeDefinitions.some((A)=>A.AttributeName===c.name))n.Properties.AttributeDefinitions.push({AttributeName:c.name,AttributeType:c.type});let S=[{AttributeName:o.name,KeyType:"HASH"}];if(c)S.push({AttributeName:c.name,KeyType:"RANGE"});let b={IndexName:s,KeySchema:S,Projection:{ProjectionType:l,NonKeyAttributes:l==="INCLUDE"?u:void 0},ProvisionedThroughput:void 0};if(n.Properties.BillingMode==="PROVISIONED")b.ProvisionedThroughput={ReadCapacityUnits:h,WriteCapacityUnits:f};if(!n.Properties.GlobalSecondaryIndexes)n.Properties.GlobalSecondaryIndexes=[];return n.Properties.GlobalSecondaryIndexes.push(b),n}static enableStreams(n,i="NEW_AND_OLD_IMAGES"){return n.Properties.StreamSpecification={StreamViewType:i},n}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 mo{static createRedis(n){let{slug:i,environment:s,nodeType:o="cache.t3.micro",engineVersion:c="7.1",port:l=6379,subnetIds:u,securityGroupIds:h,numCacheClusters:f=2,automaticFailover:S=!0,multiAz:b=!0,clusterMode:A=!1,numNodeGroups:v=1,replicasPerNodeGroup:w=1,atRestEncryption:E=!0,transitEncryption:P=!0,authToken:R,kmsKeyId:D,snapshotRetentionDays:x=7,snapshotWindow:I,maintenanceWindow:_}=n,B=r({slug:i,environment:s,resourceType:"redis"}),W=t(B),J,K;if(u&&u.length>0){let Z=r({slug:i,environment:s,resourceType:"cache-subnet-group"});K=t(Z),J={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:Z,Description:`Subnet group for ${B}`,SubnetIds:u,Tags:[{Key:"Name",Value:Z},{Key:"Environment",Value:s}]}}}let Y={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:B,ReplicationGroupDescription:`Redis cluster for ${i} ${s}`,Engine:"redis",EngineVersion:c,CacheNodeType:o,Port:l,AutomaticFailoverEnabled:S,MultiAZEnabled:b,AtRestEncryptionEnabled:E,TransitEncryptionEnabled:P,SnapshotRetentionLimit:x,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:B},{Key:"Environment",Value:s}]}};if(A)Y.Properties.NumNodeGroups=v,Y.Properties.ReplicasPerNodeGroup=w;else Y.Properties.NumCacheClusters=f;if(R)Y.Properties.AuthToken=R;if(D)Y.Properties.KmsKeyId=D;if(K)Y.Properties.CacheSubnetGroupName=k.Ref(K);if(h&&h.length>0)Y.Properties.SecurityGroupIds=h;if(I)Y.Properties.SnapshotWindow=I;if(_)Y.Properties.PreferredMaintenanceWindow=_;return{replicationGroup:Y,subnetGroup:J,logicalId:W,subnetGroupId:K}}static createMemcached(n){let{slug:i,environment:s,nodeType:o="cache.t3.micro",engineVersion:c="1.6.22",port:l=11211,numCacheNodes:u=2,subnetIds:h,securityGroupIds:f,azMode:S="cross-az",preferredAzs:b,maintenanceWindow:A}=n,v=r({slug:i,environment:s,resourceType:"memcached"}),w=t(v),E,P;if(h&&h.length>0){let D=r({slug:i,environment:s,resourceType:"cache-subnet-group"});P=t(D),E={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:D,Description:`Subnet group for ${v}`,SubnetIds:h,Tags:[{Key:"Name",Value:D},{Key:"Environment",Value:s}]}}}let R={Type:"AWS::ElastiCache::CacheCluster",Properties:{ClusterName:v,CacheNodeType:o,Engine:"memcached",EngineVersion:c,NumCacheNodes:u,Port:l,AZMode:S,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:v},{Key:"Environment",Value:s}]}};if(P)R.Properties.CacheSubnetGroupName=k.Ref(P);if(f&&f.length>0)R.Properties.VpcSecurityGroupIds=f;if(b&&b.length>0)R.Properties.PreferredAvailabilityZones=b;if(A)R.Properties.PreferredMaintenanceWindow=A;return{cluster:R,subnetGroup:E,logicalId:w,subnetGroupId:P}}static enableClusterMode(n,i=3,s=2){return delete n.Properties.NumCacheClusters,n.Properties.NumNodeGroups=i,n.Properties.ReplicasPerNodeGroup=s,n}static createRedisParameterGroup(n,i){let{slug:s,environment:o,parameters:c={}}=i,l=r({slug:s,environment:o,resourceType:"redis-params"}),u=t(l);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`redis${n.split(".")[0]}.x`,Description:`Parameter group for ${l}`,Properties:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:o}]}},logicalId:u}}static createMemcachedParameterGroup(n,i){let{slug:s,environment:o,parameters:c={}}=i,l=r({slug:s,environment:o,resourceType:"memcached-params"}),u=t(l);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`memcached${n.split(".")[0]}.${n.split(".")[1]}`,Description:`Parameter group for ${l}`,Properties:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:o}]}},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 ee{static createUser(n){let{slug:i,environment:s,userName:o,groups:c,managedPolicyArns:l}=n,u=o||r({slug:i,environment:s,resourceType:"user"}),h=t(u),f={Type:"AWS::IAM::User",Properties:{UserName:u,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:s}]}};if(c&&c.length>0)f.Properties.Groups=c;if(l&&l.length>0)f.Properties.ManagedPolicyArns=l;return{user:f,logicalId:h}}static createRole(n){let{slug:i,environment:s,roleName:o,servicePrincipal:c,awsPrincipal:l,managedPolicyArns:u}=n,h=o||r({slug:i,environment:s,resourceType:"role"}),f=t(h),S={};if(c)S.Service=c;if(l)S.AWS=l;let b={Type:"AWS::IAM::Role",Properties:{RoleName:h,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:S,Action:"sts:AssumeRole"}]},Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(u&&u.length>0)b.Properties.ManagedPolicyArns=u;return{role:b,logicalId:f}}static createGroup(n){let{slug:i,environment:s,groupName:o,managedPolicyArns:c}=n,l=o||r({slug:i,environment:s,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(n){let{slug:i,environment:s,policyName:o,description:c,statements:l}=n,u=o||r({slug:i,environment:s,resourceType:"policy"}),h=t(u),f=l.map((S)=>({Sid:S.sid,Effect:S.effect||"Allow",Action:S.actions,Resource:S.resources,Condition:S.conditions}));return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:u,Description:c||`Managed policy for ${u}`,PolicyDocument:{Version:"2012-10-17",Statement:f}}},logicalId:h}}static attachPolicyToRole(n,i){if(!n.Properties.ManagedPolicyArns)n.Properties.ManagedPolicyArns=[];if(!n.Properties.ManagedPolicyArns.includes(i))n.Properties.ManagedPolicyArns.push(i);return n}static attachPolicyToUser(n,i){if(!n.Properties.ManagedPolicyArns)n.Properties.ManagedPolicyArns=[];if(!n.Properties.ManagedPolicyArns.includes(i))n.Properties.ManagedPolicyArns.push(i);return n}static attachPolicyToGroup(n,i){if(!n.Properties.ManagedPolicyArns)n.Properties.ManagedPolicyArns=[];if(!n.Properties.ManagedPolicyArns.includes(i))n.Properties.ManagedPolicyArns.push(i);return n}static addInlinePolicyToRole(n,i,s){if(!n.Properties.Policies)n.Properties.Policies=[];let o=s.map((c)=>({Effect:c.effect||"Allow",Action:c.actions,Resource:c.resources}));return n.Properties.Policies.push({PolicyName:i,PolicyDocument:{Version:"2012-10-17",Statement:o}}),n}static addInlinePolicyToUser(n,i,s){if(!n.Properties.Policies)n.Properties.Policies=[];let o=s.map((c)=>({Effect:c.effect||"Allow",Action:c.actions,Resource:c.resources}));return n.Properties.Policies.push({PolicyName:i,PolicyDocument:{Version:"2012-10-17",Statement:o}}),n}static createAccessKey(n,i){let{slug:s,environment:o,status:c="Active"}=i,l=r({slug:s,environment:o,resourceType:"access-key"}),u=t(l);return{accessKey:{Type:"AWS::IAM::AccessKey",Properties:{UserName:k.Ref(n),Status:c}},logicalId:u}}static createInstanceProfile(n,i){let{slug:s,environment:o,profileName:c}=i,l=c||r({slug:s,environment:o,resourceType:"instance-profile"}),u=t(l);return{instanceProfile:{Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:l,Roles:[k.Ref(n)]}},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(n){let{slug:i,environment:s,permissions:o,createAccessKey:c=!0}=n,l={},u=[];if(o.s3Buckets&&o.s3Buckets.length>0)u.push({sid:"S3Access",actions:["s3:GetBucketLocation","s3:ListBucket","s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucketMultipartUploads","s3:AbortMultipartUpload"],resources:[...o.s3Buckets,...o.s3Buckets.map((w)=>`${w}/*`)]});if(o.cloudFrontDistributions&&o.cloudFrontDistributions.length>0)u.push({sid:"CloudFrontAccess",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations","cloudfront:GetDistribution"],resources:o.cloudFrontDistributions});if(o.ecrRepositories&&o.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:o.ecrRepositories}),u.push({sid:"ECRLogin",actions:["ecr:GetAuthorizationToken"],resources:"*"});if(o.ecsServices&&o.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:o.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(o.cloudFormationStacks&&o.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:o.cloudFormationStacks});if(o.lambdaFunctions&&o.lambdaFunctions.length>0)u.push({sid:"LambdaAccess",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion","lambda:UpdateAlias","lambda:CreateAlias"],resources:o.lambdaFunctions});if(o.secretsManagerSecrets&&o.secretsManagerSecrets.length>0)u.push({sid:"SecretsManagerAccess",actions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],resources:o.secretsManagerSecrets});let{policy:h,logicalId:f}=ee.createPolicy({slug:i,environment:s,policyName:r({slug:i,environment:s,resourceType:"cicd-policy"}),description:`CI/CD deployment policy for ${i} (${s})`,statements:u});l[f]=h;let{user:S,logicalId:b}=ee.createUser({slug:i,environment:s,userName:r({slug:i,environment:s,resourceType:"cicd-user"}),managedPolicyArns:[k.Ref(f)]});l[b]=S;let A,v;if(c){let w=ee.createAccessKey(b,{slug:i,environment:s});A=w.accessKey,v=w.logicalId,l[v]=A}return{user:S,accessKey:A,policy:h,userLogicalId:b,accessKeyLogicalId:v,policyLogicalId:f,resources:l}}static createCrossAccountRole(n){let{slug:i,environment:s,trustedAccountIds:o,externalId:c,permissions:l,maxSessionDuration:u=3600}=n,h={},{policy:f,logicalId:S}=ee.createPolicy({slug:i,environment:s,policyName:r({slug:i,environment:s,resourceType:"cross-account-policy"}),description:`Cross-account access policy for ${i} (${s})`,statements:l});h[S]=f;let b=r({slug:i,environment:s,resourceType:"cross-account-role"}),A=t(b),v={};if(c)v.StringEquals={"sts:ExternalId":c};let w={Type:"AWS::IAM::Role",Properties:{RoleName:b,MaxSessionDuration:u,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:o.map((E)=>`arn:aws:iam::${E}:root`)},Action:"sts:AssumeRole",...Object.keys(v).length>0?{Condition:v}:{}}]},ManagedPolicyArns:[k.Ref(S)],Tags:[{Key:"Name",Value:b},{Key:"Environment",Value:s},{Key:"Purpose",Value:"Cross-Account Access"}]}};return h[A]=w,{role:w,policy:f,roleLogicalId:A,policyLogicalId:S,resources:h}}static createCliUser(n){let{slug:i,environment:s,permissions:o="readonly"}=n,c={},l=[],u=[];switch(o){case"readonly":u=[ee.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=[ee.ManagedPolicies.AdministratorAccess];break}let h,f;if(l.length>0){let w=ee.createPolicy({slug:i,environment:s,policyName:r({slug:i,environment:s,resourceType:"cli-policy"}),description:`CLI access policy for ${i} (${s})`,statements:l});h=w.policy,f=w.logicalId,c[f]=h,u=[k.Ref(f)]}let{user:S,logicalId:b}=ee.createUser({slug:i,environment:s,userName:r({slug:i,environment:s,resourceType:"cli-user"}),managedPolicyArns:u});c[b]=S;let{accessKey:A,logicalId:v}=ee.createAccessKey(b,{slug:i,environment:s});return c[v]=A,{user:S,accessKey:A,policy:h,userLogicalId:b,accessKeyLogicalId:v,policyLogicalId:f,resources:c}}static CiCdPolicies={s3Deployment:(n)=>[{sid:"S3ListBuckets",actions:["s3:ListBucket","s3:GetBucketLocation"],resources:n},{sid:"S3Objects",actions:["s3:GetObject","s3:PutObject","s3:DeleteObject"],resources:n.map((i)=>`${i}/*`)}],cloudFrontInvalidation:(n)=>[{sid:"CloudFrontInvalidation",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations"],resources:n}],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:(n)=>[{sid:"ECRAuth",actions:["ecr:GetAuthorizationToken"],resources:"*"},{sid:"ECRPush",actions:["ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:PutImage"],resources:n}],lambdaDeployment:(n)=>[{sid:"LambdaDeploy",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion"],resources:n}],cloudFormationDeployment:(n)=>[{sid:"CloudFormationDeploy",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate"],resources:n}]}}class $d{static createRestApi(n){let{slug:i,environment:s,name:o,description:c,endpointType:l="REGIONAL",binaryMediaTypes:u,compressionSize:h}=n,f=o||r({slug:i,environment:s,resourceType:"rest-api"}),S=t(f),b={Type:"AWS::ApiGateway::RestApi",Properties:{Name:f,Description:c||`REST API for ${i} ${s}`,EndpointConfiguration:{Types:[l]},Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s}]}};if(u&&u.length>0)b.Properties.BinaryMediaTypes=u;if(h!==void 0)b.Properties.MinimumCompressionSize=h;return{restApi:b,logicalId:S}}static createHttpApi(n){let{slug:i,environment:s,name:o,description:c,corsEnabled:l=!0,corsOrigins:u=["*"],corsMethods:h=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],corsHeaders:f=["*"],corsMaxAge:S=86400,corsAllowCredentials:b=!1}=n,A=o||r({slug:i,environment:s,resourceType:"http-api"}),v=t(A),w={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:A,Description:c||`HTTP API for ${i} ${s}`,ProtocolType:"HTTP",Tags:{Name:A,Environment:s}}};if(l)w.Properties.CorsConfiguration={AllowOrigins:u,AllowMethods:h,AllowHeaders:f,MaxAge:S,AllowCredentials:b};return{httpApi:w,logicalId:v}}static createWebSocketApi(n){let{slug:i,environment:s,name:o,description:c}=n,l=o||r({slug:i,environment:s,resourceType:"ws-api"}),u=t(l);return{webSocketApi:{Type:"AWS::ApiGatewayV2::Api",Properties:{Name:l,Description:c||`WebSocket API for ${i} ${s}`,ProtocolType:"WEBSOCKET",Tags:{Name:l,Environment:s}}},logicalId:u}}static createDeployment(n,i){let{slug:s,environment:o,description:c}=i,l=r({slug:s,environment:o,resourceType:"api-deployment"}),u=t(l);return{deployment:{Type:"AWS::ApiGateway::Deployment",Properties:{RestApiId:k.Ref(n),Description:c||`Deployment for ${l}`}},logicalId:u}}static createStage(n,i,s){let{slug:o,environment:c,stageName:l,description:u,cacheEnabled:h=!1,cacheSize:f="0.5",variables:S,throttling:b}=s,A=r({slug:o,environment:c,resourceType:"api-stage"}),v=t(A),w={Type:"AWS::ApiGateway::Stage",Properties:{StageName:l||c,RestApiId:k.Ref(n),DeploymentId:k.Ref(i),Description:u,CacheClusterEnabled:h,Tags:[{Key:"Name",Value:A},{Key:"Environment",Value:c}]}};if(h)w.Properties.CacheClusterSize=f;if(S)w.Properties.Variables=S;if(b)w.Properties.MethodSettings=[{HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:b.burstLimit,ThrottlingRateLimit:b.rateLimit}];return{stage:w,logicalId:v}}static createAuthorizer(n,i){let{slug:s,environment:o,name:c,type:l,functionArn:u,identitySource:h,userPoolArns:f,ttl:S=300}=i,b=c||r({slug:s,environment:o,resourceType:"api-authorizer"}),A=t(b),v={Type:"AWS::ApiGateway::Authorizer",Properties:{Name:b,Type:l,RestApiId:k.Ref(n),AuthorizerResultTtlInSeconds:S}};if(l==="TOKEN"||l==="REQUEST"){if(!u)throw Error("Lambda authorizer requires functionArn");v.Properties.AuthorizerUri=u,v.Properties.IdentitySource=h||"method.request.header.Authorization"}if(l==="COGNITO_USER_POOLS"){if(!f||f.length===0)throw Error("Cognito authorizer requires userPoolArns");v.Properties.ProviderARNs=f,v.Properties.IdentitySource=h||"method.request.header.Authorization"}return{authorizer:v,logicalId:A}}static setCors(n,i={}){let{origins:s=["*"],methods:o=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],headers:c=["*"],maxAge:l=86400,allowCredentials:u=!1}=i;return n.Properties.CorsConfiguration={AllowOrigins:s,AllowMethods:o,AllowHeaders:c,MaxAge:l,AllowCredentials:u},n}static addThrottling(n,i=5000,s=1e4){if(!n.Properties.MethodSettings)n.Properties.MethodSettings=[];return n.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:i,ThrottlingRateLimit:s}),n}static enableCaching(n,i="0.5",s=300){if(n.Properties.CacheClusterEnabled=!0,n.Properties.CacheClusterSize=i,!n.Properties.MethodSettings)n.Properties.MethodSettings=[];return n.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",CachingEnabled:!0,CacheTtlInSeconds:s}),n}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 te{static createTopic(n){let{slug:i,environment:s,topicName:o,displayName:c,encrypted:l=!1,kmsKeyId:u}=n,h=o||r({slug:i,environment:s,resourceType:"topic"}),f=t(h),S={Type:"AWS::SNS::Topic",Properties:{TopicName:h,DisplayName:c||h,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(l&&u)S.Properties.KmsMasterKeyId=u;return{topic:S,logicalId:f}}static subscribe(n,i){let{slug:s,environment:o,protocol:c,endpoint:l,filterPolicy:u,rawMessageDelivery:h=!1}=i,f=r({slug:s,environment:o,resourceType:"subscription"}),S=l.replace(/[^a-zA-Z0-9]/g,""),b=S.length>12?S.slice(-12):S,A=t(`${f}-${c}-${b}`),v={Type:"AWS::SNS::Subscription",Properties:{TopicArn:k.Ref(n),Protocol:c,Endpoint:l,RawMessageDelivery:h}};if(u)v.Properties.FilterPolicy=u;return{subscription:v,logicalId:A}}static subscribeEmail(n,i,s){return te.subscribe(n,{...s,protocol:"email",endpoint:i})}static subscribeLambda(n,i,s){return te.subscribe(n,{...s,protocol:"lambda",endpoint:i,rawMessageDelivery:!0})}static subscribeSqs(n,i,s){return te.subscribe(n,{...s,protocol:"sqs",endpoint:i})}static subscribeHttp(n,i,s){let o=i.startsWith("https://")?"https":"http";return te.subscribe(n,{...s,protocol:o,endpoint:i})}static subscribeSms(n,i,s){return te.subscribe(n,{...s,protocol:"sms",endpoint:i})}static setTopicPolicy(n,i){let{slug:s,environment:o,allowedPrincipals:c,allowedServices:l,actions:u="SNS:Publish"}=i,h=r({slug:s,environment:o,resourceType:"topic-policy"}),f=t(h),S={};if(c)S.AWS=c;if(l)S.Service=l;return{policy:{Type:"AWS::SNS::TopicPolicy",Properties:{Topics:[k.Ref(n)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:S,Action:u,Resource:k.Ref(n)}]}}},logicalId:f}}static allowCloudWatchAlarms(n,i){return te.setTopicPolicy(n,{...i,allowedServices:"cloudwatch.amazonaws.com",actions:"SNS:Publish"})}static allowEventBridge(n,i){return te.setTopicPolicy(n,{...i,allowedServices:"events.amazonaws.com",actions:"SNS:Publish"})}static allowS3(n,i){return te.setTopicPolicy(n,{...i,allowedServices:"s3.amazonaws.com",actions:"SNS:Publish"})}static enableEncryption(n,i){if(!n.Properties)n.Properties={};return n.Properties.KmsMasterKeyId=i,n}static addInlineSubscription(n,i,s){if(!n.Properties)n.Properties={};if(!n.Properties.Subscription)n.Properties.Subscription=[];return n.Properties.Subscription.push({Protocol:i,Endpoint:s}),n}static FilterPolicies={eventType:(n)=>({eventType:n}),status:(n)=>({status:n}),numericRange:(n,i,s)=>({[n]:[{numeric:[">=",i,"<=",s]}]}),prefix:(n,i)=>({[n]:[{prefix:i}]}),and:(...n)=>Object.assign({},...n),exists:(n,i)=>({[n]:[{exists:i}]})};static UseCases={createAlertTopic:(n)=>te.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-alerts`,displayName:n.displayName||"Alert Notifications"}),createEventFanout:(n)=>te.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-events`,displayName:n.displayName||"Event Fanout"}),createNotificationTopic:(n)=>te.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-notifications`,displayName:n.displayName||"User Notifications"})}}class pA{static createStateMachine(n){let{slug:i,environment:s,stateMachineName:o,type:c="STANDARD",definition:l,roleArn:u,loggingConfiguration:h,tracingConfiguration:f}=n,S=o||r({slug:i,environment:s,resourceType:"state-machine"}),b=t(S),A,v,w;if(u)w=u;else{let P=r({slug:i,environment:s,resourceType:"state-machine-role"});v=t(P),A={Type:"AWS::IAM::Role",Properties:{RoleName:P,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:P},{Key:"Environment",Value:s}]}},w=k.GetAtt(v,"Arn")}let E={Type:"AWS::StepFunctions::StateMachine",Properties:{StateMachineName:S,StateMachineType:c,DefinitionString:JSON.stringify(l),RoleArn:w,Tags:[{Key:"Name",Value:S},{Key:"Environment",Value:s}]}};if(h)E.Properties.LoggingConfiguration={Level:h.level,IncludeExecutionData:h.includeExecutionData,Destinations:h.destinations?.map((P)=>({CloudWatchLogsLogGroup:{LogGroupArn:P}}))};if(f)E.Properties.TracingConfiguration={Enabled:f.enabled};return{stateMachine:E,logicalId:b,role:A,roleLogicalId:v}}static createLambdaTask(n,i){return{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Parameters:{FunctionName:n,Payload:i?.parameters||{"Input.$":"$"}},ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createDynamoDBTask(n,i,s,o){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"}[n],Parameters:{TableName:i,...s},ResultPath:o?.resultPath,Retry:o?.retry,Catch:o?.catch,Next:o?.next,End:o?.end}}static createSNSPublishTask(n,i,s){return{Type:"Task",Resource:"arn:aws:states:::sns:publish",Parameters:{TopicArn:n,Message:i},ResultPath:s?.resultPath,Retry:s?.retry,Catch:s?.catch,Next:s?.next,End:s?.end}}static createSQSSendMessageTask(n,i,s){return{Type:"Task",Resource:"arn:aws:states:::sqs:sendMessage",Parameters:{QueueUrl:n,MessageBody:i},ResultPath:s?.resultPath,Retry:s?.retry,Catch:s?.catch,Next:s?.next,End:s?.end}}static createPassState(n){return{Type:"Pass",Result:n?.result,ResultPath:n?.resultPath,Parameters:n?.parameters,Next:n?.next,End:n?.end}}static createWaitState(n){return{Type:"Wait",Seconds:n.seconds,Timestamp:n.timestamp,SecondsPath:n.secondsPath,TimestampPath:n.timestampPath,Next:n.next,End:n.end}}static createChoiceState(n,i){return{Type:"Choice",Choices:n,Default:i}}static createParallelState(n,i){return{Type:"Parallel",Branches:n,ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createMapState(n,i){return{Type:"Map",ItemsPath:i?.itemsPath||"$.items",Iterator:n,MaxConcurrency:i?.maxConcurrency,ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createSucceedState(){return{Type:"Succeed"}}static createFailState(n,i){return{Type:"Fail",Error:n,Cause:i}}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:(n,i,s,o)=>({ErrorEquals:n,IntervalSeconds:i,MaxAttempts:s,BackoffRate:o})};static CatchPolicies={all:(n,i)=>({ErrorEquals:["States.ALL"],Next:n,ResultPath:i||"$.error"}),specific:(n,i,s)=>({ErrorEquals:n,Next:i,ResultPath:s||"$.error"})};static Patterns={sequential:(n,i,s)=>{let o={};return s.forEach((c,l)=>{let u=l===s.length-1;o[c.name]={...c.state,Next:u?void 0:s[l+1].name,End:u}}),{Comment:"Sequential workflow",StartAt:s[0].name,States:o}},fanout:(n,i,s)=>({Comment:"Fan-out workflow",StartAt:"Parallel",States:{Parallel:{Type:"Parallel",Branches:s.map((o)=>o.definition),End:!0}}}),map:(n,i,s,o)=>({Comment:"Map workflow",StartAt:"Map",States:{Map:{Type:"Map",ItemsPath:"$.items",Iterator:s,MaxConcurrency:o,End:!0}}}),withErrorHandling:(n,i,s,o)=>({Comment:"Workflow with error handling",StartAt:"Main",States:{Main:{...s,Catch:[{ErrorEquals:["States.ALL"],Next:"ErrorHandler"}],Next:"Success"},ErrorHandler:o,Success:{Type:"Succeed"}}})}}class ho{static createAlarm(n){let{slug:i,environment:s,alarmName:o,metricName:c,namespace:l,statistic:u="Average",period:h=300,evaluationPeriods:f=1,threshold:S,comparisonOperator:b,treatMissingData:A="notBreaching",actionsEnabled:v=!0,alarmActions:w,okActions:E,insufficientDataActions:P,dimensions:R,unit:D,datapointsToAlarm:x}=n,I=o||r({slug:i,environment:s,resourceType:"alarm"}),_=t(I),B={Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:I,MetricName:c,Namespace:l,Statistic:u,Period:h,EvaluationPeriods:f,Threshold:S,ComparisonOperator:b,TreatMissingData:A,ActionsEnabled:v}};if(w&&w.length>0)B.Properties.AlarmActions=w;if(E&&E.length>0)B.Properties.OKActions=E;if(P&&P.length>0)B.Properties.InsufficientDataActions=P;if(R)B.Properties.Dimensions=Object.entries(R).map(([W,J])=>({Name:W,Value:J}));if(D)B.Properties.Unit=D;if(x!==void 0)B.Properties.DatapointsToAlarm=x;return{alarm:B,logicalId:_}}static createCompositeAlarm(n){let{slug:i,environment:s,alarmName:o,alarmRule:c,actionsEnabled:l=!0,alarmActions:u,okActions:h,insufficientDataActions:f}=n,S=o||r({slug:i,environment:s,resourceType:"composite-alarm"}),b=t(S),A={Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:S,AlarmRule:c,ActionsEnabled:l}};if(u&&u.length>0)A.Properties.AlarmActions=u;if(h&&h.length>0)A.Properties.OKActions=h;if(f&&f.length>0)A.Properties.InsufficientDataActions=f;return{alarm:A,logicalId:b}}static createDashboard(n){let{slug:i,environment:s,dashboardName:o,widgets:c}=n,l=o||r({slug:i,environment:s,resourceType:"dashboard"}),u=t(l),h={widgets:c.map((f)=>({type:f.type,x:f.x,y:f.y,width:f.width,height:f.height,properties:f.properties}))};return{dashboard:{Type:"AWS::CloudWatch::Dashboard",Properties:{DashboardName:l,DashboardBody:JSON.stringify(h)}},logicalId:u}}static createLogGroup(n){let{slug:i,environment:s,logGroupName:o,retentionInDays:c,kmsKeyId:l}=n,u=o||r({slug:i,environment:s,resourceType:"log-group"}),h=t(u),f={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:u}};if(c!==void 0)f.Properties.RetentionInDays=c;if(l)f.Properties.KmsKeyId=l;return{logGroup:f,logicalId:h}}static createLogStream(n,i){let{slug:s,environment:o,logStreamName:c}=i,l=c||r({slug:s,environment:o,resourceType:"log-stream"}),u=t(l);return{logStream:{Type:"AWS::Logs::LogStream",Properties:{LogGroupName:k.Ref(n),LogStreamName:l}},logicalId:u}}static createMetricFilter(n,i){let{slug:s,environment:o,filterName:c,filterPattern:l,metricTransformations:u}=i,h=c||r({slug:s,environment:o,resourceType:"metric-filter"}),f=t(h);return{metricFilter:{Type:"AWS::Logs::MetricFilter",Properties:{LogGroupName:k.Ref(n),FilterPattern:l,MetricTransformations:u.map((S)=>({MetricName:S.metricName,MetricNamespace:S.metricNamespace,MetricValue:S.metricValue,DefaultValue:S.defaultValue,Unit:S.unit}))}},logicalId:f}}static AlarmTypes={highCpu:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-high-cpu`,metricName:"CPUUtilization",namespace:"AWS/EC2",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s},alarmActions:c?[c]:void 0}),highMemory:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-high-memory`,metricName:"MemoryUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s},alarmActions:c?[c]:void 0}),highDisk:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-high-disk`,metricName:"DiskSpaceUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s,Filesystem:"/dev/xvda1",MountPath:"/"},alarmActions:c?[c]:void 0}),lambdaErrors:(n,i,s,o=5,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-lambda-errors`,metricName:"Errors",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:s},alarmActions:c?[c]:void 0}),lambdaThrottles:(n,i,s,o=10,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-lambda-throttles`,metricName:"Throttles",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:s},alarmActions:c?[c]:void 0}),apiGateway5xxErrors:(n,i,s,o=10,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-api-5xx-errors`,metricName:"5XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:s},alarmActions:c?[c]:void 0}),apiGateway4xxErrors:(n,i,s,o=50,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-api-4xx-errors`,metricName:"4XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:s},alarmActions:c?[c]:void 0}),dynamoDBThrottles:(n,i,s,o=5,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-dynamodb-throttles`,metricName:"UserErrors",namespace:"AWS/DynamoDB",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{TableName:s},alarmActions:c?[c]:void 0}),rdsCpu:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-rds-cpu`,metricName:"CPUUtilization",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{DBInstanceIdentifier:s},alarmActions:c?[c]:void 0}),rdsFreeStorage:(n,i,s,o=5368709120,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-rds-storage`,metricName:"FreeStorageSpace",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"LessThanThreshold",dimensions:{DBInstanceIdentifier:s},alarmActions:c?[c]:void 0,unit:"Bytes"}),sqsQueueDepth:(n,i,s,o=100,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-sqs-depth`,metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{QueueName:s},alarmActions:c?[c]:void 0}),albUnhealthyTargets:(n,i,s,o,c=1,l)=>({slug:n,environment:i,alarmName:`${n}-${i}-alb-unhealthy`,metricName:"UnHealthyHostCount",namespace:"AWS/ApplicationELB",statistic:"Average",period:300,evaluationPeriods:2,threshold:c,comparisonOperator:"GreaterThanThreshold",dimensions:{LoadBalancer:s,TargetGroup:o},alarmActions:l?[l]:void 0}),sesBounceRate:(n,i,s=5,o)=>({slug:n,environment:i,alarmName:`${n}-${i}-ses-bounce-rate`,metricName:"Reputation.BounceRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:s/100,comparisonOperator:"GreaterThanThreshold",alarmActions:o?[o]:void 0}),sesComplaintRate:(n,i,s=0.1,o)=>({slug:n,environment:i,alarmName:`${n}-${i}-ses-complaint-rate`,metricName:"Reputation.ComplaintRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:s/100,comparisonOperator:"GreaterThanThreshold",alarmActions:o?[o]:void 0}),smsDeliveryFailure:(n,i,s,o=10,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-sms-delivery-failure`,metricName:"DirectSendMessagePermanentFailure",namespace:"AWS/Pinpoint",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{ApplicationId:s},alarmActions:c?[c]:void 0}),smsSpendLimit:(n,i,s=100,o)=>({slug:n,environment:i,alarmName:`${n}-${i}-sms-spend-limit`,metricName:"DirectSendMessageSpend",namespace:"AWS/Pinpoint",statistic:"Sum",period:86400,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",alarmActions:o?[o]:void 0}),connectMissedCalls:(n,i,s,o=5,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-connect-missed-calls`,metricName:"MissedCalls",namespace:"AWS/Connect",statistic:"Sum",period:3600,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s},alarmActions:c?[c]:void 0})};static DashboardWidgets={metric:(n,i,s,o,c,l)=>({type:"metric",x:n,y:i,width:s,height:o,properties:{metrics:c,title:l||"Metrics",region:"us-east-1",period:300}}),text:(n,i,s,o,c)=>({type:"text",x:n,y:i,width:s,height:o,properties:{markdown:c}}),log:(n,i,s,o,c,l)=>({type:"log",x:n,y:i,width:s,height:o,properties:{query:`SOURCE '${c.join("' | SOURCE '")}'
|
|
2309
|
+
`;class Q{static LambdaCode={send:ka,receive:vr,deliveryStatus:Cr};static createPinpointApp(n){return{[`${n.slug}PinpointApp`]:{Type:"AWS::Pinpoint::App",Properties:{Name:n.name||`${n.slug}-sms`}}}}static createSmsChannel(n){let i={ApplicationId:n.applicationId,Enabled:n.enabled!==!1};if(n.senderId)i.SenderId=n.senderId;if(n.shortCode)i.ShortCode=n.shortCode;return{[`${n.slug}SmsChannel`]:{Type:"AWS::Pinpoint::SMSChannel",Properties:i}}}static createSmsLambdaRole(n){return{[`${n.slug}SmsLambdaRole`]:{Type:"AWS::IAM::Role",Properties:{RoleName:`${n.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(n){return{[`${n.slug}SmsSendLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-send`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Q.LambdaCode.send},Environment:{Variables:{PINPOINT_APP_ID:n.pinpointAppId,MESSAGE_LOG_TABLE:n.messageLogTable||"",SMS_SENDER_ID:n.senderId||"",SMS_ORIGINATION_NUMBER:n.originationNumber||""}}}}}}static createReceiveLambda(n){return{[`${n.slug}SmsReceiveLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-receive`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Q.LambdaCode.receive},Environment:{Variables:{OPT_OUT_TABLE:n.optOutTable||"",MESSAGE_LOG_TABLE:n.messageLogTable||"",NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createDeliveryStatusLambda(n){return{[`${n.slug}SmsDeliveryStatusLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-delivery-status`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Q.LambdaCode.deliveryStatus},Environment:{Variables:{MESSAGE_LOG_TABLE:n.messageLogTable||"",NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createMessageLogTable(n){return{[`${n.slug}SmsMessageLogTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-sms-messages`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createOptOutTable(n){return{[`${n.slug}SmsOptOutTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-sms-optouts`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}]}}}}static createNotificationTopic(n){return{[`${n.slug}SmsNotificationTopic`]:{Type:"AWS::SNS::Topic",Properties:{TopicName:`${n.slug}-sms-notifications`}}}}static createCompleteSetup(n){let i={},s={};Object.assign(i,Q.createPinpointApp({slug:n.slug})),Object.assign(i,Q.createSmsChannel({slug:n.slug,applicationId:{Ref:`${n.slug}PinpointApp`},senderId:n.senderId})),Object.assign(i,Q.createSmsLambdaRole({slug:n.slug})),Object.assign(i,Q.createMessageLogTable({slug:n.slug})),Object.assign(i,Q.createOptOutTable({slug:n.slug})),Object.assign(i,Q.createNotificationTopic({slug:n.slug}));let o={"Fn::GetAtt":[`${n.slug}SmsLambdaRole`,"Arn"]},c={Ref:`${n.slug}PinpointApp`},l={Ref:`${n.slug}SmsMessageLogTable`},u={Ref:`${n.slug}SmsOptOutTable`},h={Ref:`${n.slug}SmsNotificationTopic`};if(Object.assign(i,Q.createSendLambda({slug:n.slug,roleArn:o,pinpointAppId:c,messageLogTable:l,senderId:n.senderId,originationNumber:n.originationNumber})),n.twoWayEnabled)Object.assign(i,Q.createReceiveLambda({slug:n.slug,roleArn:o,optOutTable:u,messageLogTable:l,notificationTopicArn:h,webhookUrl:n.webhookUrl}));return Object.assign(i,Q.createDeliveryStatusLambda({slug:n.slug,roleArn:o,messageLogTable:l,notificationTopicArn:h,webhookUrl:n.webhookUrl})),s[`${n.slug}PinpointAppId`]={Description:"Pinpoint application ID",Value:{Ref:`${n.slug}PinpointApp`}},s[`${n.slug}SmsSendLambdaArn`]={Description:"SMS send Lambda ARN",Value:{"Fn::GetAtt":[`${n.slug}SmsSendLambda`,"Arn"]}},s[`${n.slug}SmsNotificationTopicArn`]={Description:"SMS notification topic ARN",Value:{Ref:`${n.slug}SmsNotificationTopic`}},s[`${n.slug}SmsMessageLogTableName`]={Description:"SMS message log table name",Value:{Ref:`${n.slug}SmsMessageLogTable`}},{resources:i,outputs:s}}}function Rt(n){return n.replace(/[^a-zA-Z0-9]/g," ").trim().split(/\s+/).map((i)=>i.charAt(0).toUpperCase()+i.slice(1)).join("")||"User"}function wr(n,i){let s=(n||i).replace(/^\/+|\/+$/g,"");if(!s||s.split("/").includes(".."))throw Error(`sftp: invalid homeDirectory for user ${i}`);return s}function Er(n){let i=n.storage;if(i?.type==="efs"){let o="fileSystemId"in i?i.fileSystemId:void 0;if(!o||typeof o==="string"&&!o.trim())throw Error("sftp: EFS storage requires fileSystemId, or a fileSystem name defined in infrastructure.fileSystem");return{type:"efs",fileSystemId:o,posixProfile:i.posixProfile}}let s=(i?.type==="s3"?i.bucket??n.bucket:n.bucket)?.trim();if(!s)throw Error("sftp: S3 storage requires bucket, or a storageBucket name defined in infrastructure.storage");return{type:"s3",bucket:s}}function Pr(n,i,s){let o=i.posixProfile??s;if(!o)throw Error(`sftp: user ${n} requires a posixProfile (uid/gid) on an EFS-backed server`);for(let c of[o.uid,o.gid,...o.secondaryGids??[]])if(!Number.isInteger(c)||c<0||c>4294967295)throw Error(`sftp: user ${n} has an invalid posixProfile id ${c}`);return{Uid:o.uid,Gid:o.gid,...o.secondaryGids?.length?{SecondaryGids:o.secondaryGids}:{}}}function Ir(n,i){return typeof n==="string"?`/${n}/${i}`:{"Fn::Sub":[`/\${FileSystemId}/${i}`,{FileSystemId:n}]}}function Rr(n){return typeof n==="string"?{"Fn::Sub":"arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}".replace("${FileSystemId}",n)}:{"Fn::Sub":["arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}",{FileSystemId:n}]}}class Ld{static create(n){let i=Er(n),s=i.type==="efs"?"EFS":"S3",o=n.endpointType??"PUBLIC";if(o==="VPC"&&(!n.endpointDetails?.vpcId||!n.endpointDetails.subnetIds.length))throw Error("sftp: VPC endpoints require endpointDetails.vpcId and at least one subnet");let c=`${Rt(n.slug)}${Rt(n.environment)}Sftp`,l=`${c}Server`,u={},h;if(n.logging!==!1){let f=`${c}LoggingRole`;u[f]={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":[f,"Arn"]}}u[l]={Type:"AWS::Transfer::Server",Properties:{Domain:s,EndpointType:o,IdentityProviderType:"SERVICE_MANAGED",Protocols:["SFTP"],...o==="VPC"?{EndpointDetails:{VpcId:n.endpointDetails.vpcId,SubnetIds:n.endpointDetails.subnetIds,...n.endpointDetails.securityGroupIds?.length?{SecurityGroupIds:n.endpointDetails.securityGroupIds}:{},...n.endpointDetails.addressAllocationIds?.length?{AddressAllocationIds:n.endpointDetails.addressAllocationIds}:{}}}:{},...n.securityPolicyName?{SecurityPolicyName:n.securityPolicyName}:{},...h?{LoggingRole:h}:{},Tags:[{Key:"Project",Value:n.slug},{Key:"Environment",Value:n.environment},{Key:"ManagedBy",Value:"ts-cloud"}]}};for(let[f,S]of Object.entries(n.users)){if(!/^[a-zA-Z0-9_.@-]{3,100}$/.test(f))throw Error(`sftp: invalid username ${f}`);if(!S.sshPublicKeys.length)throw Error(`sftp: user ${f} requires at least one SSH public key`);let b=Rt(f),A=wr(S.homeDirectory,f),v=`${c}${b}User`,w=S.roleArn;if(!w){let E=`${c}${b}Role`,P;if(i.type==="efs")P=[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:DescribeMountTargets"],Resource:Rr(i.fileSystemId)}];else{let R=`arn:aws:s3:::${i.bucket}`;P=[{Effect:"Allow",Action:["s3:ListBucket","s3:GetBucketLocation"],Resource:R,Condition:{StringLike:{"s3:prefix":[A,`${A}/*`]}}},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:GetObjectVersion"],Resource:`${R}/${A}/*`}]}u[E]={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:P}}]}},w={"Fn::GetAtt":[E,"Arn"]}}u[v]={Type:"AWS::Transfer::User",DependsOn:[l],Properties:{ServerId:{Ref:l},UserName:f,Role:w,HomeDirectoryType:"PATH",HomeDirectory:i.type==="efs"?Ir(i.fileSystemId,A):`/${i.bucket}/${A}`,...i.type==="efs"?{PosixProfile:Pr(f,S,i.posixProfile)}:{},SshPublicKeys:S.sshPublicKeys}}}return{resources:u,serverLogicalId:l,domain:s}}}class Pe{static createBedrockRole(n,i){let{slug:s,environment:o,name:c,models:l=["*"],allowStreaming:u=!0}=i,h=c||r({slug:s,environment:o,resourceType:"bedrock-role"}),f=t(h),S=["bedrock:InvokeModel"];if(u)S.push("bedrock:InvokeModelWithResponseStream");let b=l.map((A)=>A==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${A}`);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:h,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:n},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:`${h}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:S,Resource:b}]}}],Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:o}]}},logicalId:f}}static createBedrockPolicy(n){let{slug:i,environment:s,name:o,models:c=["*"],allowInvoke:l=!0,allowStreaming:u=!0,allowAsync:h=!1}=n,f=o||r({slug:i,environment:s,resourceType:"bedrock-policy"}),S=t(f),b=[];if(l)b.push("bedrock:InvokeModel");if(u)b.push("bedrock:InvokeModelWithResponseStream");if(h)b.push("bedrock:InvokeModelAsync");let A=c.map((v)=>v==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${v}`);return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:f,PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"BedrockModelInvocation",Effect:"Allow",Action:b,Resource:A}]}}},logicalId:S}}static enableBedrockForLambda(n){return Pe.createBedrockRole("lambda.amazonaws.com",n)}static enableBedrockForEcs(n){return Pe.createBedrockRole("ecs-tasks.amazonaws.com",n)}static enableBedrockForEc2(n){return Pe.createBedrockRole("ec2.amazonaws.com",n)}static addBedrockPermissions(n,i=["*"],s=!0){let o=["bedrock:InvokeModel"];if(s)o.push("bedrock:InvokeModelWithResponseStream");let c=i.map((l)=>l==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${l}`);if(!n.Properties.Policies)n.Properties.Policies=[];return n.Properties.Policies.push({PolicyName:"bedrock-permissions",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:o,Resource:c}]}}),n}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 zt{static createPostgres(n){return zt.createRDSInstance("postgres","16.2",n)}static createMysql(n){return zt.createRDSInstance("mysql","8.0.35",n)}static createRDSInstance(n,i,s){let{slug:o,environment:c,instanceClass:l="db.t3.micro",allocatedStorage:u=20,storageType:h="gp3",masterUsername:f="admin",masterPassword:S,databaseName:b,subnetIds:A,securityGroupIds:v,encrypted:w=!0,kmsKeyId:E,multiAz:P=!1,backupRetentionDays:R=7,publiclyAccessible:D=!1,enableCloudwatchLogs:O=!0,deletionProtection:I=!0}=s,_=r({slug:o,environment:c,resourceType:`${n}-db`}),B=t(_),W,J;if(A&&A.length>0){let Y=r({slug:o,environment:c,resourceType:"db-subnet-group"});J=t(Y),W={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupName:Y,DBSubnetGroupDescription:`Subnet group for ${_}`,SubnetIds:A,Tags:[{Key:"Name",Value:Y},{Key:"Environment",Value:c}]}}}let K={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:_,DBInstanceClass:l,Engine:n,EngineVersion:i,MasterUsername:f,MasterUserPassword:S,AllocatedStorage:u,StorageType:h,StorageEncrypted:w,MultiAZ:P,BackupRetentionPeriod:R,PubliclyAccessible:D,DeletionProtection:I,Tags:[{Key:"Name",Value:_},{Key:"Environment",Value:c}]}};if(b)K.Properties.DBName=b;if(E)K.Properties.KmsKeyId=E;if(J)K.Properties.DBSubnetGroupName=k.Ref(J);if(v&&v.length>0)K.Properties.VPCSecurityGroups=v;if(O)K.Properties.EnableCloudwatchLogsExports=n==="postgres"?["postgresql"]:["error","general","slowquery"];return{dbInstance:K,subnetGroup:W,logicalId:B,subnetGroupId:J}}static createReadReplica(n,i){let{slug:s,environment:o,instanceClass:c="db.t3.micro",securityGroupIds:l,publiclyAccessible:u=!1}=i,h=r({slug:s,environment:o,resourceType:"db-replica"}),f=t(h),S={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:h,DBInstanceClass:c,SourceDBInstanceIdentifier:k.Ref(n),PubliclyAccessible:u,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:o},{Key:"Type",Value:"ReadReplica"}]}};if(l&&l.length>0)S.Properties.VPCSecurityGroups=l;return{replica:S,logicalId:f}}static createParameterGroup(n,i,s){let{slug:o,environment:c,parameters:l={}}=s,u=r({slug:o,environment:c,resourceType:"db-params"}),h=t(u),f=n==="postgres"?`postgres${i.split(".")[0]}`:`mysql${i.split(".")[0]}.${i.split(".")[1]}`;return{parameterGroup:{Type:"AWS::RDS::DBParameterGroup",Properties:{DBParameterGroupName:u,Description:`Parameter group for ${u}`,Family:f,Parameters:l,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:c}]}},logicalId:h}}static enableBackup(n,i=7){return n.Properties.BackupRetentionPeriod=i,n}static createTable(n){let{slug:i,environment:s,tableName:o,partitionKey:c,sortKey:l,billingMode:u="PAY_PER_REQUEST",readCapacity:h=5,writeCapacity:f=5,streamEnabled:S=!1,streamViewType:b="NEW_AND_OLD_IMAGES",encrypted:A=!0,kmsKeyId:v,pointInTimeRecovery:w=!0,ttlAttribute:E}=n,P=o||r({slug:i,environment:s,resourceType:"table"}),R=t(P),D=[{AttributeName:c.name,AttributeType:c.type}];if(l)D.push({AttributeName:l.name,AttributeType:l.type});let O=[{AttributeName:c.name,KeyType:"HASH"}];if(l)O.push({AttributeName:l.name,KeyType:"RANGE"});let I={Type:"AWS::DynamoDB::Table",Properties:{TableName:P,BillingMode:u,AttributeDefinitions:D,KeySchema:O,Tags:[{Key:"Name",Value:P},{Key:"Environment",Value:s}]}};if(u==="PROVISIONED")I.Properties.ProvisionedThroughput={ReadCapacityUnits:h,WriteCapacityUnits:f};if(S)I.Properties.StreamSpecification={StreamViewType:b};if(A)I.Properties.SSESpecification={SSEEnabled:!0,SSEType:v?"KMS":"AES256",KMSMasterKeyId:v};if(w)I.Properties.PointInTimeRecoverySpecification={PointInTimeRecoveryEnabled:!0};if(E)I.Properties.TimeToLiveSpecification={AttributeName:E,Enabled:!0};return{table:I,logicalId:R}}static addGlobalSecondaryIndex(n,i){let{indexName:s,partitionKey:o,sortKey:c,projectionType:l="ALL",nonKeyAttributes:u,readCapacity:h=5,writeCapacity:f=5}=i;if(!n.Properties.AttributeDefinitions.some((A)=>A.AttributeName===o.name))n.Properties.AttributeDefinitions.push({AttributeName:o.name,AttributeType:o.type});if(c&&!n.Properties.AttributeDefinitions.some((A)=>A.AttributeName===c.name))n.Properties.AttributeDefinitions.push({AttributeName:c.name,AttributeType:c.type});let S=[{AttributeName:o.name,KeyType:"HASH"}];if(c)S.push({AttributeName:c.name,KeyType:"RANGE"});let b={IndexName:s,KeySchema:S,Projection:{ProjectionType:l,NonKeyAttributes:l==="INCLUDE"?u:void 0},ProvisionedThroughput:void 0};if(n.Properties.BillingMode==="PROVISIONED")b.ProvisionedThroughput={ReadCapacityUnits:h,WriteCapacityUnits:f};if(!n.Properties.GlobalSecondaryIndexes)n.Properties.GlobalSecondaryIndexes=[];return n.Properties.GlobalSecondaryIndexes.push(b),n}static enableStreams(n,i="NEW_AND_OLD_IMAGES"){return n.Properties.StreamSpecification={StreamViewType:i},n}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 mo{static createRedis(n){let{slug:i,environment:s,nodeType:o="cache.t3.micro",engineVersion:c="7.1",port:l=6379,subnetIds:u,securityGroupIds:h,numCacheClusters:f=2,automaticFailover:S=!0,multiAz:b=!0,clusterMode:A=!1,numNodeGroups:v=1,replicasPerNodeGroup:w=1,atRestEncryption:E=!0,transitEncryption:P=!0,authToken:R,kmsKeyId:D,snapshotRetentionDays:O=7,snapshotWindow:I,maintenanceWindow:_}=n,B=r({slug:i,environment:s,resourceType:"redis"}),W=t(B),J,K;if(u&&u.length>0){let Z=r({slug:i,environment:s,resourceType:"cache-subnet-group"});K=t(Z),J={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:Z,Description:`Subnet group for ${B}`,SubnetIds:u,Tags:[{Key:"Name",Value:Z},{Key:"Environment",Value:s}]}}}let Y={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:B,ReplicationGroupDescription:`Redis cluster for ${i} ${s}`,Engine:"redis",EngineVersion:c,CacheNodeType:o,Port:l,AutomaticFailoverEnabled:S,MultiAZEnabled:b,AtRestEncryptionEnabled:E,TransitEncryptionEnabled:P,SnapshotRetentionLimit:O,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:B},{Key:"Environment",Value:s}]}};if(A)Y.Properties.NumNodeGroups=v,Y.Properties.ReplicasPerNodeGroup=w;else Y.Properties.NumCacheClusters=f;if(R)Y.Properties.AuthToken=R;if(D)Y.Properties.KmsKeyId=D;if(K)Y.Properties.CacheSubnetGroupName=k.Ref(K);if(h&&h.length>0)Y.Properties.SecurityGroupIds=h;if(I)Y.Properties.SnapshotWindow=I;if(_)Y.Properties.PreferredMaintenanceWindow=_;return{replicationGroup:Y,subnetGroup:J,logicalId:W,subnetGroupId:K}}static createMemcached(n){let{slug:i,environment:s,nodeType:o="cache.t3.micro",engineVersion:c="1.6.22",port:l=11211,numCacheNodes:u=2,subnetIds:h,securityGroupIds:f,azMode:S="cross-az",preferredAzs:b,maintenanceWindow:A}=n,v=r({slug:i,environment:s,resourceType:"memcached"}),w=t(v),E,P;if(h&&h.length>0){let D=r({slug:i,environment:s,resourceType:"cache-subnet-group"});P=t(D),E={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:D,Description:`Subnet group for ${v}`,SubnetIds:h,Tags:[{Key:"Name",Value:D},{Key:"Environment",Value:s}]}}}let R={Type:"AWS::ElastiCache::CacheCluster",Properties:{ClusterName:v,CacheNodeType:o,Engine:"memcached",EngineVersion:c,NumCacheNodes:u,Port:l,AZMode:S,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:v},{Key:"Environment",Value:s}]}};if(P)R.Properties.CacheSubnetGroupName=k.Ref(P);if(f&&f.length>0)R.Properties.VpcSecurityGroupIds=f;if(b&&b.length>0)R.Properties.PreferredAvailabilityZones=b;if(A)R.Properties.PreferredMaintenanceWindow=A;return{cluster:R,subnetGroup:E,logicalId:w,subnetGroupId:P}}static enableClusterMode(n,i=3,s=2){return delete n.Properties.NumCacheClusters,n.Properties.NumNodeGroups=i,n.Properties.ReplicasPerNodeGroup=s,n}static createRedisParameterGroup(n,i){let{slug:s,environment:o,parameters:c={}}=i,l=r({slug:s,environment:o,resourceType:"redis-params"}),u=t(l);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`redis${n.split(".")[0]}.x`,Description:`Parameter group for ${l}`,Properties:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:o}]}},logicalId:u}}static createMemcachedParameterGroup(n,i){let{slug:s,environment:o,parameters:c={}}=i,l=r({slug:s,environment:o,resourceType:"memcached-params"}),u=t(l);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`memcached${n.split(".")[0]}.${n.split(".")[1]}`,Description:`Parameter group for ${l}`,Properties:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:o}]}},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 ee{static createUser(n){let{slug:i,environment:s,userName:o,groups:c,managedPolicyArns:l}=n,u=o||r({slug:i,environment:s,resourceType:"user"}),h=t(u),f={Type:"AWS::IAM::User",Properties:{UserName:u,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:s}]}};if(c&&c.length>0)f.Properties.Groups=c;if(l&&l.length>0)f.Properties.ManagedPolicyArns=l;return{user:f,logicalId:h}}static createRole(n){let{slug:i,environment:s,roleName:o,servicePrincipal:c,awsPrincipal:l,managedPolicyArns:u}=n,h=o||r({slug:i,environment:s,resourceType:"role"}),f=t(h),S={};if(c)S.Service=c;if(l)S.AWS=l;let b={Type:"AWS::IAM::Role",Properties:{RoleName:h,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:S,Action:"sts:AssumeRole"}]},Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(u&&u.length>0)b.Properties.ManagedPolicyArns=u;return{role:b,logicalId:f}}static createGroup(n){let{slug:i,environment:s,groupName:o,managedPolicyArns:c}=n,l=o||r({slug:i,environment:s,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(n){let{slug:i,environment:s,policyName:o,description:c,statements:l}=n,u=o||r({slug:i,environment:s,resourceType:"policy"}),h=t(u),f=l.map((S)=>({Sid:S.sid,Effect:S.effect||"Allow",Action:S.actions,Resource:S.resources,Condition:S.conditions}));return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:u,Description:c||`Managed policy for ${u}`,PolicyDocument:{Version:"2012-10-17",Statement:f}}},logicalId:h}}static attachPolicyToRole(n,i){if(!n.Properties.ManagedPolicyArns)n.Properties.ManagedPolicyArns=[];if(!n.Properties.ManagedPolicyArns.includes(i))n.Properties.ManagedPolicyArns.push(i);return n}static attachPolicyToUser(n,i){if(!n.Properties.ManagedPolicyArns)n.Properties.ManagedPolicyArns=[];if(!n.Properties.ManagedPolicyArns.includes(i))n.Properties.ManagedPolicyArns.push(i);return n}static attachPolicyToGroup(n,i){if(!n.Properties.ManagedPolicyArns)n.Properties.ManagedPolicyArns=[];if(!n.Properties.ManagedPolicyArns.includes(i))n.Properties.ManagedPolicyArns.push(i);return n}static addInlinePolicyToRole(n,i,s){if(!n.Properties.Policies)n.Properties.Policies=[];let o=s.map((c)=>({Effect:c.effect||"Allow",Action:c.actions,Resource:c.resources}));return n.Properties.Policies.push({PolicyName:i,PolicyDocument:{Version:"2012-10-17",Statement:o}}),n}static addInlinePolicyToUser(n,i,s){if(!n.Properties.Policies)n.Properties.Policies=[];let o=s.map((c)=>({Effect:c.effect||"Allow",Action:c.actions,Resource:c.resources}));return n.Properties.Policies.push({PolicyName:i,PolicyDocument:{Version:"2012-10-17",Statement:o}}),n}static createAccessKey(n,i){let{slug:s,environment:o,status:c="Active"}=i,l=r({slug:s,environment:o,resourceType:"access-key"}),u=t(l);return{accessKey:{Type:"AWS::IAM::AccessKey",Properties:{UserName:k.Ref(n),Status:c}},logicalId:u}}static createInstanceProfile(n,i){let{slug:s,environment:o,profileName:c}=i,l=c||r({slug:s,environment:o,resourceType:"instance-profile"}),u=t(l);return{instanceProfile:{Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:l,Roles:[k.Ref(n)]}},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(n){let{slug:i,environment:s,permissions:o,createAccessKey:c=!0}=n,l={},u=[];if(o.s3Buckets&&o.s3Buckets.length>0)u.push({sid:"S3Access",actions:["s3:GetBucketLocation","s3:ListBucket","s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucketMultipartUploads","s3:AbortMultipartUpload"],resources:[...o.s3Buckets,...o.s3Buckets.map((w)=>`${w}/*`)]});if(o.cloudFrontDistributions&&o.cloudFrontDistributions.length>0)u.push({sid:"CloudFrontAccess",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations","cloudfront:GetDistribution"],resources:o.cloudFrontDistributions});if(o.ecrRepositories&&o.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:o.ecrRepositories}),u.push({sid:"ECRLogin",actions:["ecr:GetAuthorizationToken"],resources:"*"});if(o.ecsServices&&o.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:o.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(o.cloudFormationStacks&&o.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:o.cloudFormationStacks});if(o.lambdaFunctions&&o.lambdaFunctions.length>0)u.push({sid:"LambdaAccess",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion","lambda:UpdateAlias","lambda:CreateAlias"],resources:o.lambdaFunctions});if(o.secretsManagerSecrets&&o.secretsManagerSecrets.length>0)u.push({sid:"SecretsManagerAccess",actions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],resources:o.secretsManagerSecrets});let{policy:h,logicalId:f}=ee.createPolicy({slug:i,environment:s,policyName:r({slug:i,environment:s,resourceType:"cicd-policy"}),description:`CI/CD deployment policy for ${i} (${s})`,statements:u});l[f]=h;let{user:S,logicalId:b}=ee.createUser({slug:i,environment:s,userName:r({slug:i,environment:s,resourceType:"cicd-user"}),managedPolicyArns:[k.Ref(f)]});l[b]=S;let A,v;if(c){let w=ee.createAccessKey(b,{slug:i,environment:s});A=w.accessKey,v=w.logicalId,l[v]=A}return{user:S,accessKey:A,policy:h,userLogicalId:b,accessKeyLogicalId:v,policyLogicalId:f,resources:l}}static createCrossAccountRole(n){let{slug:i,environment:s,trustedAccountIds:o,externalId:c,permissions:l,maxSessionDuration:u=3600}=n,h={},{policy:f,logicalId:S}=ee.createPolicy({slug:i,environment:s,policyName:r({slug:i,environment:s,resourceType:"cross-account-policy"}),description:`Cross-account access policy for ${i} (${s})`,statements:l});h[S]=f;let b=r({slug:i,environment:s,resourceType:"cross-account-role"}),A=t(b),v={};if(c)v.StringEquals={"sts:ExternalId":c};let w={Type:"AWS::IAM::Role",Properties:{RoleName:b,MaxSessionDuration:u,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:o.map((E)=>`arn:aws:iam::${E}:root`)},Action:"sts:AssumeRole",...Object.keys(v).length>0?{Condition:v}:{}}]},ManagedPolicyArns:[k.Ref(S)],Tags:[{Key:"Name",Value:b},{Key:"Environment",Value:s},{Key:"Purpose",Value:"Cross-Account Access"}]}};return h[A]=w,{role:w,policy:f,roleLogicalId:A,policyLogicalId:S,resources:h}}static createCliUser(n){let{slug:i,environment:s,permissions:o="readonly"}=n,c={},l=[],u=[];switch(o){case"readonly":u=[ee.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=[ee.ManagedPolicies.AdministratorAccess];break}let h,f;if(l.length>0){let w=ee.createPolicy({slug:i,environment:s,policyName:r({slug:i,environment:s,resourceType:"cli-policy"}),description:`CLI access policy for ${i} (${s})`,statements:l});h=w.policy,f=w.logicalId,c[f]=h,u=[k.Ref(f)]}let{user:S,logicalId:b}=ee.createUser({slug:i,environment:s,userName:r({slug:i,environment:s,resourceType:"cli-user"}),managedPolicyArns:u});c[b]=S;let{accessKey:A,logicalId:v}=ee.createAccessKey(b,{slug:i,environment:s});return c[v]=A,{user:S,accessKey:A,policy:h,userLogicalId:b,accessKeyLogicalId:v,policyLogicalId:f,resources:c}}static CiCdPolicies={s3Deployment:(n)=>[{sid:"S3ListBuckets",actions:["s3:ListBucket","s3:GetBucketLocation"],resources:n},{sid:"S3Objects",actions:["s3:GetObject","s3:PutObject","s3:DeleteObject"],resources:n.map((i)=>`${i}/*`)}],cloudFrontInvalidation:(n)=>[{sid:"CloudFrontInvalidation",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations"],resources:n}],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:(n)=>[{sid:"ECRAuth",actions:["ecr:GetAuthorizationToken"],resources:"*"},{sid:"ECRPush",actions:["ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:PutImage"],resources:n}],lambdaDeployment:(n)=>[{sid:"LambdaDeploy",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion"],resources:n}],cloudFormationDeployment:(n)=>[{sid:"CloudFormationDeploy",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate"],resources:n}]}}class $d{static createRestApi(n){let{slug:i,environment:s,name:o,description:c,endpointType:l="REGIONAL",binaryMediaTypes:u,compressionSize:h}=n,f=o||r({slug:i,environment:s,resourceType:"rest-api"}),S=t(f),b={Type:"AWS::ApiGateway::RestApi",Properties:{Name:f,Description:c||`REST API for ${i} ${s}`,EndpointConfiguration:{Types:[l]},Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s}]}};if(u&&u.length>0)b.Properties.BinaryMediaTypes=u;if(h!==void 0)b.Properties.MinimumCompressionSize=h;return{restApi:b,logicalId:S}}static createHttpApi(n){let{slug:i,environment:s,name:o,description:c,corsEnabled:l=!0,corsOrigins:u=["*"],corsMethods:h=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],corsHeaders:f=["*"],corsMaxAge:S=86400,corsAllowCredentials:b=!1}=n,A=o||r({slug:i,environment:s,resourceType:"http-api"}),v=t(A),w={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:A,Description:c||`HTTP API for ${i} ${s}`,ProtocolType:"HTTP",Tags:{Name:A,Environment:s}}};if(l)w.Properties.CorsConfiguration={AllowOrigins:u,AllowMethods:h,AllowHeaders:f,MaxAge:S,AllowCredentials:b};return{httpApi:w,logicalId:v}}static createWebSocketApi(n){let{slug:i,environment:s,name:o,description:c}=n,l=o||r({slug:i,environment:s,resourceType:"ws-api"}),u=t(l);return{webSocketApi:{Type:"AWS::ApiGatewayV2::Api",Properties:{Name:l,Description:c||`WebSocket API for ${i} ${s}`,ProtocolType:"WEBSOCKET",Tags:{Name:l,Environment:s}}},logicalId:u}}static createDeployment(n,i){let{slug:s,environment:o,description:c}=i,l=r({slug:s,environment:o,resourceType:"api-deployment"}),u=t(l);return{deployment:{Type:"AWS::ApiGateway::Deployment",Properties:{RestApiId:k.Ref(n),Description:c||`Deployment for ${l}`}},logicalId:u}}static createStage(n,i,s){let{slug:o,environment:c,stageName:l,description:u,cacheEnabled:h=!1,cacheSize:f="0.5",variables:S,throttling:b}=s,A=r({slug:o,environment:c,resourceType:"api-stage"}),v=t(A),w={Type:"AWS::ApiGateway::Stage",Properties:{StageName:l||c,RestApiId:k.Ref(n),DeploymentId:k.Ref(i),Description:u,CacheClusterEnabled:h,Tags:[{Key:"Name",Value:A},{Key:"Environment",Value:c}]}};if(h)w.Properties.CacheClusterSize=f;if(S)w.Properties.Variables=S;if(b)w.Properties.MethodSettings=[{HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:b.burstLimit,ThrottlingRateLimit:b.rateLimit}];return{stage:w,logicalId:v}}static createAuthorizer(n,i){let{slug:s,environment:o,name:c,type:l,functionArn:u,identitySource:h,userPoolArns:f,ttl:S=300}=i,b=c||r({slug:s,environment:o,resourceType:"api-authorizer"}),A=t(b),v={Type:"AWS::ApiGateway::Authorizer",Properties:{Name:b,Type:l,RestApiId:k.Ref(n),AuthorizerResultTtlInSeconds:S}};if(l==="TOKEN"||l==="REQUEST"){if(!u)throw Error("Lambda authorizer requires functionArn");v.Properties.AuthorizerUri=u,v.Properties.IdentitySource=h||"method.request.header.Authorization"}if(l==="COGNITO_USER_POOLS"){if(!f||f.length===0)throw Error("Cognito authorizer requires userPoolArns");v.Properties.ProviderARNs=f,v.Properties.IdentitySource=h||"method.request.header.Authorization"}return{authorizer:v,logicalId:A}}static setCors(n,i={}){let{origins:s=["*"],methods:o=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],headers:c=["*"],maxAge:l=86400,allowCredentials:u=!1}=i;return n.Properties.CorsConfiguration={AllowOrigins:s,AllowMethods:o,AllowHeaders:c,MaxAge:l,AllowCredentials:u},n}static addThrottling(n,i=5000,s=1e4){if(!n.Properties.MethodSettings)n.Properties.MethodSettings=[];return n.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:i,ThrottlingRateLimit:s}),n}static enableCaching(n,i="0.5",s=300){if(n.Properties.CacheClusterEnabled=!0,n.Properties.CacheClusterSize=i,!n.Properties.MethodSettings)n.Properties.MethodSettings=[];return n.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",CachingEnabled:!0,CacheTtlInSeconds:s}),n}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 te{static createTopic(n){let{slug:i,environment:s,topicName:o,displayName:c,encrypted:l=!1,kmsKeyId:u}=n,h=o||r({slug:i,environment:s,resourceType:"topic"}),f=t(h),S={Type:"AWS::SNS::Topic",Properties:{TopicName:h,DisplayName:c||h,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(l&&u)S.Properties.KmsMasterKeyId=u;return{topic:S,logicalId:f}}static subscribe(n,i){let{slug:s,environment:o,protocol:c,endpoint:l,filterPolicy:u,rawMessageDelivery:h=!1}=i,f=r({slug:s,environment:o,resourceType:"subscription"}),S=l.replace(/[^a-zA-Z0-9]/g,""),b=S.length>12?S.slice(-12):S,A=t(`${f}-${c}-${b}`),v={Type:"AWS::SNS::Subscription",Properties:{TopicArn:k.Ref(n),Protocol:c,Endpoint:l,RawMessageDelivery:h}};if(u)v.Properties.FilterPolicy=u;return{subscription:v,logicalId:A}}static subscribeEmail(n,i,s){return te.subscribe(n,{...s,protocol:"email",endpoint:i})}static subscribeLambda(n,i,s){return te.subscribe(n,{...s,protocol:"lambda",endpoint:i,rawMessageDelivery:!0})}static subscribeSqs(n,i,s){return te.subscribe(n,{...s,protocol:"sqs",endpoint:i})}static subscribeHttp(n,i,s){let o=i.startsWith("https://")?"https":"http";return te.subscribe(n,{...s,protocol:o,endpoint:i})}static subscribeSms(n,i,s){return te.subscribe(n,{...s,protocol:"sms",endpoint:i})}static setTopicPolicy(n,i){let{slug:s,environment:o,allowedPrincipals:c,allowedServices:l,actions:u="SNS:Publish"}=i,h=r({slug:s,environment:o,resourceType:"topic-policy"}),f=t(h),S={};if(c)S.AWS=c;if(l)S.Service=l;return{policy:{Type:"AWS::SNS::TopicPolicy",Properties:{Topics:[k.Ref(n)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:S,Action:u,Resource:k.Ref(n)}]}}},logicalId:f}}static allowCloudWatchAlarms(n,i){return te.setTopicPolicy(n,{...i,allowedServices:"cloudwatch.amazonaws.com",actions:"SNS:Publish"})}static allowEventBridge(n,i){return te.setTopicPolicy(n,{...i,allowedServices:"events.amazonaws.com",actions:"SNS:Publish"})}static allowS3(n,i){return te.setTopicPolicy(n,{...i,allowedServices:"s3.amazonaws.com",actions:"SNS:Publish"})}static enableEncryption(n,i){if(!n.Properties)n.Properties={};return n.Properties.KmsMasterKeyId=i,n}static addInlineSubscription(n,i,s){if(!n.Properties)n.Properties={};if(!n.Properties.Subscription)n.Properties.Subscription=[];return n.Properties.Subscription.push({Protocol:i,Endpoint:s}),n}static FilterPolicies={eventType:(n)=>({eventType:n}),status:(n)=>({status:n}),numericRange:(n,i,s)=>({[n]:[{numeric:[">=",i,"<=",s]}]}),prefix:(n,i)=>({[n]:[{prefix:i}]}),and:(...n)=>Object.assign({},...n),exists:(n,i)=>({[n]:[{exists:i}]})};static UseCases={createAlertTopic:(n)=>te.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-alerts`,displayName:n.displayName||"Alert Notifications"}),createEventFanout:(n)=>te.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-events`,displayName:n.displayName||"Event Fanout"}),createNotificationTopic:(n)=>te.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-notifications`,displayName:n.displayName||"User Notifications"})}}class pA{static createStateMachine(n){let{slug:i,environment:s,stateMachineName:o,type:c="STANDARD",definition:l,roleArn:u,loggingConfiguration:h,tracingConfiguration:f}=n,S=o||r({slug:i,environment:s,resourceType:"state-machine"}),b=t(S),A,v,w;if(u)w=u;else{let P=r({slug:i,environment:s,resourceType:"state-machine-role"});v=t(P),A={Type:"AWS::IAM::Role",Properties:{RoleName:P,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:P},{Key:"Environment",Value:s}]}},w=k.GetAtt(v,"Arn")}let E={Type:"AWS::StepFunctions::StateMachine",Properties:{StateMachineName:S,StateMachineType:c,DefinitionString:JSON.stringify(l),RoleArn:w,Tags:[{Key:"Name",Value:S},{Key:"Environment",Value:s}]}};if(h)E.Properties.LoggingConfiguration={Level:h.level,IncludeExecutionData:h.includeExecutionData,Destinations:h.destinations?.map((P)=>({CloudWatchLogsLogGroup:{LogGroupArn:P}}))};if(f)E.Properties.TracingConfiguration={Enabled:f.enabled};return{stateMachine:E,logicalId:b,role:A,roleLogicalId:v}}static createLambdaTask(n,i){return{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Parameters:{FunctionName:n,Payload:i?.parameters||{"Input.$":"$"}},ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createDynamoDBTask(n,i,s,o){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"}[n],Parameters:{TableName:i,...s},ResultPath:o?.resultPath,Retry:o?.retry,Catch:o?.catch,Next:o?.next,End:o?.end}}static createSNSPublishTask(n,i,s){return{Type:"Task",Resource:"arn:aws:states:::sns:publish",Parameters:{TopicArn:n,Message:i},ResultPath:s?.resultPath,Retry:s?.retry,Catch:s?.catch,Next:s?.next,End:s?.end}}static createSQSSendMessageTask(n,i,s){return{Type:"Task",Resource:"arn:aws:states:::sqs:sendMessage",Parameters:{QueueUrl:n,MessageBody:i},ResultPath:s?.resultPath,Retry:s?.retry,Catch:s?.catch,Next:s?.next,End:s?.end}}static createPassState(n){return{Type:"Pass",Result:n?.result,ResultPath:n?.resultPath,Parameters:n?.parameters,Next:n?.next,End:n?.end}}static createWaitState(n){return{Type:"Wait",Seconds:n.seconds,Timestamp:n.timestamp,SecondsPath:n.secondsPath,TimestampPath:n.timestampPath,Next:n.next,End:n.end}}static createChoiceState(n,i){return{Type:"Choice",Choices:n,Default:i}}static createParallelState(n,i){return{Type:"Parallel",Branches:n,ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createMapState(n,i){return{Type:"Map",ItemsPath:i?.itemsPath||"$.items",Iterator:n,MaxConcurrency:i?.maxConcurrency,ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createSucceedState(){return{Type:"Succeed"}}static createFailState(n,i){return{Type:"Fail",Error:n,Cause:i}}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:(n,i,s,o)=>({ErrorEquals:n,IntervalSeconds:i,MaxAttempts:s,BackoffRate:o})};static CatchPolicies={all:(n,i)=>({ErrorEquals:["States.ALL"],Next:n,ResultPath:i||"$.error"}),specific:(n,i,s)=>({ErrorEquals:n,Next:i,ResultPath:s||"$.error"})};static Patterns={sequential:(n,i,s)=>{let o={};return s.forEach((c,l)=>{let u=l===s.length-1;o[c.name]={...c.state,Next:u?void 0:s[l+1].name,End:u}}),{Comment:"Sequential workflow",StartAt:s[0].name,States:o}},fanout:(n,i,s)=>({Comment:"Fan-out workflow",StartAt:"Parallel",States:{Parallel:{Type:"Parallel",Branches:s.map((o)=>o.definition),End:!0}}}),map:(n,i,s,o)=>({Comment:"Map workflow",StartAt:"Map",States:{Map:{Type:"Map",ItemsPath:"$.items",Iterator:s,MaxConcurrency:o,End:!0}}}),withErrorHandling:(n,i,s,o)=>({Comment:"Workflow with error handling",StartAt:"Main",States:{Main:{...s,Catch:[{ErrorEquals:["States.ALL"],Next:"ErrorHandler"}],Next:"Success"},ErrorHandler:o,Success:{Type:"Succeed"}}})}}class ho{static createAlarm(n){let{slug:i,environment:s,alarmName:o,metricName:c,namespace:l,statistic:u="Average",period:h=300,evaluationPeriods:f=1,threshold:S,comparisonOperator:b,treatMissingData:A="notBreaching",actionsEnabled:v=!0,alarmActions:w,okActions:E,insufficientDataActions:P,dimensions:R,unit:D,datapointsToAlarm:O}=n,I=o||r({slug:i,environment:s,resourceType:"alarm"}),_=t(I),B={Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:I,MetricName:c,Namespace:l,Statistic:u,Period:h,EvaluationPeriods:f,Threshold:S,ComparisonOperator:b,TreatMissingData:A,ActionsEnabled:v}};if(w&&w.length>0)B.Properties.AlarmActions=w;if(E&&E.length>0)B.Properties.OKActions=E;if(P&&P.length>0)B.Properties.InsufficientDataActions=P;if(R)B.Properties.Dimensions=Object.entries(R).map(([W,J])=>({Name:W,Value:J}));if(D)B.Properties.Unit=D;if(O!==void 0)B.Properties.DatapointsToAlarm=O;return{alarm:B,logicalId:_}}static createCompositeAlarm(n){let{slug:i,environment:s,alarmName:o,alarmRule:c,actionsEnabled:l=!0,alarmActions:u,okActions:h,insufficientDataActions:f}=n,S=o||r({slug:i,environment:s,resourceType:"composite-alarm"}),b=t(S),A={Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:S,AlarmRule:c,ActionsEnabled:l}};if(u&&u.length>0)A.Properties.AlarmActions=u;if(h&&h.length>0)A.Properties.OKActions=h;if(f&&f.length>0)A.Properties.InsufficientDataActions=f;return{alarm:A,logicalId:b}}static createDashboard(n){let{slug:i,environment:s,dashboardName:o,widgets:c}=n,l=o||r({slug:i,environment:s,resourceType:"dashboard"}),u=t(l),h={widgets:c.map((f)=>({type:f.type,x:f.x,y:f.y,width:f.width,height:f.height,properties:f.properties}))};return{dashboard:{Type:"AWS::CloudWatch::Dashboard",Properties:{DashboardName:l,DashboardBody:JSON.stringify(h)}},logicalId:u}}static createLogGroup(n){let{slug:i,environment:s,logGroupName:o,retentionInDays:c,kmsKeyId:l}=n,u=o||r({slug:i,environment:s,resourceType:"log-group"}),h=t(u),f={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:u}};if(c!==void 0)f.Properties.RetentionInDays=c;if(l)f.Properties.KmsKeyId=l;return{logGroup:f,logicalId:h}}static createLogStream(n,i){let{slug:s,environment:o,logStreamName:c}=i,l=c||r({slug:s,environment:o,resourceType:"log-stream"}),u=t(l);return{logStream:{Type:"AWS::Logs::LogStream",Properties:{LogGroupName:k.Ref(n),LogStreamName:l}},logicalId:u}}static createMetricFilter(n,i){let{slug:s,environment:o,filterName:c,filterPattern:l,metricTransformations:u}=i,h=c||r({slug:s,environment:o,resourceType:"metric-filter"}),f=t(h);return{metricFilter:{Type:"AWS::Logs::MetricFilter",Properties:{LogGroupName:k.Ref(n),FilterPattern:l,MetricTransformations:u.map((S)=>({MetricName:S.metricName,MetricNamespace:S.metricNamespace,MetricValue:S.metricValue,DefaultValue:S.defaultValue,Unit:S.unit}))}},logicalId:f}}static AlarmTypes={highCpu:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-high-cpu`,metricName:"CPUUtilization",namespace:"AWS/EC2",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s},alarmActions:c?[c]:void 0}),highMemory:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-high-memory`,metricName:"MemoryUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s},alarmActions:c?[c]:void 0}),highDisk:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-high-disk`,metricName:"DiskSpaceUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s,Filesystem:"/dev/xvda1",MountPath:"/"},alarmActions:c?[c]:void 0}),lambdaErrors:(n,i,s,o=5,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-lambda-errors`,metricName:"Errors",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:s},alarmActions:c?[c]:void 0}),lambdaThrottles:(n,i,s,o=10,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-lambda-throttles`,metricName:"Throttles",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:s},alarmActions:c?[c]:void 0}),apiGateway5xxErrors:(n,i,s,o=10,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-api-5xx-errors`,metricName:"5XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:s},alarmActions:c?[c]:void 0}),apiGateway4xxErrors:(n,i,s,o=50,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-api-4xx-errors`,metricName:"4XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:s},alarmActions:c?[c]:void 0}),dynamoDBThrottles:(n,i,s,o=5,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-dynamodb-throttles`,metricName:"UserErrors",namespace:"AWS/DynamoDB",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{TableName:s},alarmActions:c?[c]:void 0}),rdsCpu:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-rds-cpu`,metricName:"CPUUtilization",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{DBInstanceIdentifier:s},alarmActions:c?[c]:void 0}),rdsFreeStorage:(n,i,s,o=5368709120,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-rds-storage`,metricName:"FreeStorageSpace",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"LessThanThreshold",dimensions:{DBInstanceIdentifier:s},alarmActions:c?[c]:void 0,unit:"Bytes"}),sqsQueueDepth:(n,i,s,o=100,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-sqs-depth`,metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{QueueName:s},alarmActions:c?[c]:void 0}),albUnhealthyTargets:(n,i,s,o,c=1,l)=>({slug:n,environment:i,alarmName:`${n}-${i}-alb-unhealthy`,metricName:"UnHealthyHostCount",namespace:"AWS/ApplicationELB",statistic:"Average",period:300,evaluationPeriods:2,threshold:c,comparisonOperator:"GreaterThanThreshold",dimensions:{LoadBalancer:s,TargetGroup:o},alarmActions:l?[l]:void 0}),sesBounceRate:(n,i,s=5,o)=>({slug:n,environment:i,alarmName:`${n}-${i}-ses-bounce-rate`,metricName:"Reputation.BounceRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:s/100,comparisonOperator:"GreaterThanThreshold",alarmActions:o?[o]:void 0}),sesComplaintRate:(n,i,s=0.1,o)=>({slug:n,environment:i,alarmName:`${n}-${i}-ses-complaint-rate`,metricName:"Reputation.ComplaintRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:s/100,comparisonOperator:"GreaterThanThreshold",alarmActions:o?[o]:void 0}),smsDeliveryFailure:(n,i,s,o=10,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-sms-delivery-failure`,metricName:"DirectSendMessagePermanentFailure",namespace:"AWS/Pinpoint",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{ApplicationId:s},alarmActions:c?[c]:void 0}),smsSpendLimit:(n,i,s=100,o)=>({slug:n,environment:i,alarmName:`${n}-${i}-sms-spend-limit`,metricName:"DirectSendMessageSpend",namespace:"AWS/Pinpoint",statistic:"Sum",period:86400,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",alarmActions:o?[o]:void 0}),connectMissedCalls:(n,i,s,o=5,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-connect-missed-calls`,metricName:"MissedCalls",namespace:"AWS/Connect",statistic:"Sum",period:3600,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s},alarmActions:c?[c]:void 0})};static DashboardWidgets={metric:(n,i,s,o,c,l)=>({type:"metric",x:n,y:i,width:s,height:o,properties:{metrics:c,title:l||"Metrics",region:"us-east-1",period:300}}),text:(n,i,s,o,c)=>({type:"text",x:n,y:i,width:s,height:o,properties:{markdown:c}}),log:(n,i,s,o,c,l)=>({type:"log",x:n,y:i,width:s,height:o,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:(n,i)=>`{ $.${n} = "${i}" }`,httpStatus:(n)=>`[..., status_code = ${n}, ...]`,http4xx:"[..., status_code = 4*, ...]",http5xx:"[..., status_code = 5*, ...]"};static createApplicationDashboard(n){let{slug:i,environment:s,region:o="us-east-1",components:c={}}=n,l=[],u=0;if(l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:`# ${i.toUpperCase()} Dashboard (${s})`}}),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:o,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:o,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:o,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:o,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:o,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:o,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:o,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:o,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:o,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:o,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:o,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:o,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:o,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:o,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:o,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:o,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:o,metrics:c.sqsQueueNames.map((h)=>["AWS/SQS","ApproximateAgeOfOldestMessage","QueueName",h]),period:60,stat:"Maximum"}}),u+=6;if(c.logGroupNames&&c.logGroupNames.length>0)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## Application Logs"}}),u+=1,l.push({type:"log",x:0,y:u,width:24,height:6,properties:{query:`SOURCE '${c.logGroupNames.join("' | SOURCE '")}'
|
|
2313
2313
|
| fields @timestamp, @message
|
|
2314
2314
|
| filter @message like /ERROR|WARN|Exception/
|
|
2315
2315
|
| sort @timestamp desc
|
|
2316
|
-
| limit 50`,region:o,title:"Recent Errors and Warnings"}}),u+=6;return ho.createDashboard({slug:i,environment:s,widgets:l})}static DashboardTemplates={staticWebsite:(n)=>({slug:n.slug,environment:n.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${n.slug.toUpperCase()} Static Website Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"CloudFront Requests",region:"us-east-1",metrics:[["AWS/CloudFront","Requests","DistributionId",n.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"Error Rate",region:"us-east-1",metrics:[["AWS/CloudFront","4xxErrorRate","DistributionId",n.cloudFrontDistributionId,"Region","Global",{label:"4XX"}],["AWS/CloudFront","5xxErrorRate","DistributionId",n.cloudFrontDistributionId,"Region","Global",{label:"5XX"}]],period:300,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Bytes Downloaded",region:"us-east-1",metrics:[["AWS/CloudFront","BytesDownloaded","DistributionId",n.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:0,y:7,width:12,height:6,properties:{title:"S3 Bucket Size",region:n.region||"us-east-1",metrics:[["AWS/S3","BucketSizeBytes","BucketName",n.s3BucketName,"StorageType","StandardStorage"]],period:86400,stat:"Average"}},{type:"metric",x:12,y:7,width:12,height:6,properties:{title:"S3 Number of Objects",region:n.region||"us-east-1",metrics:[["AWS/S3","NumberOfObjects","BucketName",n.s3BucketName,"StorageType","AllStorageTypes"]],period:86400,stat:"Average"}}]}),serverlessApi:(n)=>({slug:n.slug,environment:n.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${n.slug.toUpperCase()} Serverless API Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"API Requests",region:n.region||"us-east-1",metrics:[["AWS/ApiGateway","Count","ApiName",n.apiGatewayName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"API Latency",region:n.region||"us-east-1",metrics:[["AWS/ApiGateway","Latency","ApiName",n.apiGatewayName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"API Errors",region:n.region||"us-east-1",metrics:[["AWS/ApiGateway","4XXError","ApiName",n.apiGatewayName,{label:"4XX"}],["AWS/ApiGateway","5XXError","ApiName",n.apiGatewayName,{label:"5XX"}]],period:60,stat:"Sum"}},...n.lambdaFunctionNames.map((i,s)=>({type:"metric",x:s%3*8,y:7+Math.floor(s/3)*6,width:8,height:6,properties:{title:`${i} Metrics`,region:n.region||"us-east-1",metrics:[["AWS/Lambda","Invocations","FunctionName",i],["AWS/Lambda","Duration","FunctionName",i],["AWS/Lambda","Errors","FunctionName",i]],period:300,stat:"Sum"}}))]}),containerService:(n)=>({slug:n.slug,environment:n.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${n.slug.toUpperCase()} Container Service Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"ECS CPU",region:n.region||"us-east-1",metrics:[["AWS/ECS","CPUUtilization","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"ECS Memory",region:n.region||"us-east-1",metrics:[["AWS/ECS","MemoryUtilization","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Running Tasks",region:n.region||"us-east-1",metrics:[["ECS/ContainerInsights","RunningTaskCount","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:0,y:7,width:8,height:6,properties:{title:"ALB Requests",region:n.region||"us-east-1",metrics:[["AWS/ApplicationELB","RequestCount","LoadBalancer",n.albName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:7,width:8,height:6,properties:{title:"Response Time",region:n.region||"us-east-1",metrics:[["AWS/ApplicationELB","TargetResponseTime","LoadBalancer",n.albName]],period:60,stat:"Average"}},{type:"metric",x:16,y:7,width:8,height:6,properties:{title:"Healthy Hosts",region:n.region||"us-east-1",metrics:[["AWS/ApplicationELB","HealthyHostCount","LoadBalancer",n.albName]],period:60,stat:"Average"}},...n.rdsInstanceId?[{type:"metric",x:0,y:13,width:12,height:6,properties:{title:"RDS CPU",region:n.region||"us-east-1",metrics:[["AWS/RDS","CPUUtilization","DBInstanceIdentifier",n.rdsInstanceId]],period:300,stat:"Average"}},{type:"metric",x:12,y:13,width:12,height:6,properties:{title:"RDS Connections",region:n.region||"us-east-1",metrics:[["AWS/RDS","DatabaseConnections","DBInstanceIdentifier",n.rdsInstanceId]],period:60,stat:"Sum"}}]:[]]})};static Config={createAlarmConfig:(n)=>{let{metricName:i,namespace:s,threshold:o,comparisonOperator:c="GreaterThanThreshold",evaluationPeriods:l=1,period:u=300,statistic:h="Average",treatMissingData:f="missing"}=n;return{MetricName:i,Namespace:s,Threshold:o,ComparisonOperator:c,EvaluationPeriods:l,Period:u,Statistic:h,TreatMissingData:f}},namespaces:{ec2:"AWS/EC2",ecs:"AWS/ECS",lambda:"AWS/Lambda",rds:"AWS/RDS",sqs:"AWS/SQS",sns:"AWS/SNS",s3:"AWS/S3",cloudfront:"AWS/CloudFront",alb:"AWS/ApplicationELB",nlb:"AWS/NetworkELB",apiGateway:"AWS/ApiGateway",dynamodb:"AWS/DynamoDB",elasticache:"AWS/ElastiCache"},comparisonOperators:{greaterThan:"GreaterThanThreshold",greaterOrEqual:"GreaterThanOrEqualToThreshold",lessThan:"LessThanThreshold",lessOrEqual:"LessThanOrEqualToThreshold"},metrics:{ec2:{cpu:{metricName:"CPUUtilization",namespace:"AWS/EC2"},networkIn:{metricName:"NetworkIn",namespace:"AWS/EC2"},networkOut:{metricName:"NetworkOut",namespace:"AWS/EC2"},statusCheck:{metricName:"StatusCheckFailed",namespace:"AWS/EC2"}},ecs:{cpu:{metricName:"CPUUtilization",namespace:"AWS/ECS"},memory:{metricName:"MemoryUtilization",namespace:"AWS/ECS"}},lambda:{invocations:{metricName:"Invocations",namespace:"AWS/Lambda"},errors:{metricName:"Errors",namespace:"AWS/Lambda"},duration:{metricName:"Duration",namespace:"AWS/Lambda"},throttles:{metricName:"Throttles",namespace:"AWS/Lambda"},concurrentExecutions:{metricName:"ConcurrentExecutions",namespace:"AWS/Lambda"}},rds:{cpu:{metricName:"CPUUtilization",namespace:"AWS/RDS"},connections:{metricName:"DatabaseConnections",namespace:"AWS/RDS"},freeStorage:{metricName:"FreeStorageSpace",namespace:"AWS/RDS"},readLatency:{metricName:"ReadLatency",namespace:"AWS/RDS"},writeLatency:{metricName:"WriteLatency",namespace:"AWS/RDS"}},alb:{requestCount:{metricName:"RequestCount",namespace:"AWS/ApplicationELB"},responseTime:{metricName:"TargetResponseTime",namespace:"AWS/ApplicationELB"},httpCode4xx:{metricName:"HTTPCode_Target_4XX_Count",namespace:"AWS/ApplicationELB"},httpCode5xx:{metricName:"HTTPCode_Target_5XX_Count",namespace:"AWS/ApplicationELB"},healthyHosts:{metricName:"HealthyHostCount",namespace:"AWS/ApplicationELB"}},sqs:{messagesVisible:{metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS"},messagesDelayed:{metricName:"ApproximateNumberOfMessagesDelayed",namespace:"AWS/SQS"},messageAge:{metricName:"ApproximateAgeOfOldestMessage",namespace:"AWS/SQS"}}},presets:{highCpu:(n=80)=>({metricName:"CPUUtilization",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highMemory:(n=80)=>({metricName:"MemoryUtilization",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highErrors:(n=10)=>({metricName:"Errors",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:1,period:60,statistic:"Sum"}),highLatency:(n=5000)=>({metricName:"Duration",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowHealthyHosts:(n=1)=>({metricName:"HealthyHostCount",namespace:"AWS/ApplicationELB",threshold:n,comparisonOperator:"LessThanThreshold",evaluationPeriods:2,period:60,statistic:"Minimum"}),queueDepth:(n=1000)=>({metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowStorage:(n=10737418240)=>({metricName:"FreeStorageSpace",namespace:"AWS/RDS",threshold:n,comparisonOperator:"LessThanThreshold",evaluationPeriods:1,period:300,statistic:"Average"})}}}class H{static createUserPool(n){let{slug:i,environment:s,userPoolName:o,aliasAttributes:c,autoVerifiedAttributes:l,passwordPolicy:u,mfaConfiguration:h,emailConfiguration:f,smsConfiguration:S,lambdaTriggers:b,userPoolAddOns:A,accountRecoverySetting:v}=n,w=o||r({slug:i,environment:s,resourceType:"user-pool"}),E=t(w),P={Type:"AWS::Cognito::UserPool",Properties:{UserPoolName:w,Policies:u?{PasswordPolicy:{MinimumLength:u.minimumLength,RequireLowercase:u.requireLowercase,RequireUppercase:u.requireUppercase,RequireNumbers:u.requireNumbers,RequireSymbols:u.requireSymbols,TemporaryPasswordValidityDays:u.temporaryPasswordValidityDays}}:void 0,MfaConfiguration:h,Schema:[{Name:"email",AttributeDataType:"String",Required:!0,Mutable:!1}]}};if(c&&c.length>0)P.Properties.UsernameAttributes=c;if(l&&l.length>0)P.Properties.AutoVerifiedAttributes=l;if(f)P.Properties.EmailConfiguration={EmailSendingAccount:f.emailSendingAccount,From:f.from,ReplyToEmailAddress:f.replyToEmailAddress,SourceArn:f.sourceArn,ConfigurationSet:f.configurationSet};if(S)P.Properties.SmsConfiguration={ExternalId:S.externalId,SnsCallerArn:S.snsCallerArn};if(b)P.Properties.LambdaConfig={PreSignUp:b.preSignUp,PostConfirmation:b.postConfirmation,PreAuthentication:b.preAuthentication,PostAuthentication:b.postAuthentication,CustomMessage:b.customMessage,DefineAuthChallenge:b.defineAuthChallenge,CreateAuthChallenge:b.createAuthChallenge,VerifyAuthChallengeResponse:b.verifyAuthChallengeResponse,PreTokenGeneration:b.preTokenGeneration,UserMigration:b.userMigration};if(A)P.Properties.UserPoolAddOns={AdvancedSecurityMode:A.advancedSecurityMode};if(v)P.Properties.AccountRecoverySetting={RecoveryMechanisms:v.recoveryMechanisms};return{userPool:P,logicalId:E}}static createUserPoolClient(n,i){let{slug:s,environment:o,clientName:c,generateSecret:l=!1,refreshTokenValidity:u,accessTokenValidity:h,idTokenValidity:f,tokenValidityUnits:S,readAttributes:b,writeAttributes:A,explicitAuthFlows:v,preventUserExistenceErrors:w,enableTokenRevocation:E,callbackURLs:P,logoutURLs:R,allowedOAuthFlows:D,allowedOAuthScopes:x,allowedOAuthFlowsUserPoolClient:I,supportedIdentityProviders:_}=i,B=c||r({slug:s,environment:o,resourceType:"user-pool-client"}),W=t(B);return{client:{Type:"AWS::Cognito::UserPoolClient",Properties:{ClientName:B,UserPoolId:k.Ref(n),GenerateSecret:l,RefreshTokenValidity:u,AccessTokenValidity:h,IdTokenValidity:f,TokenValidityUnits:S,ReadAttributes:b,WriteAttributes:A,ExplicitAuthFlows:v,PreventUserExistenceErrors:w,EnableTokenRevocation:E,CallbackURLs:P,LogoutURLs:R,AllowedOAuthFlows:D,AllowedOAuthScopes:x,AllowedOAuthFlowsUserPoolClient:I,SupportedIdentityProviders:_}},logicalId:W}}static createUserPoolDomain(n,i){let{slug:s,environment:o,domain:c,customDomainConfig:l}=i,u=r({slug:s,environment:o,resourceType:"user-pool-domain"}),h=t(u);return{domain:{Type:"AWS::Cognito::UserPoolDomain",Properties:{Domain:c,UserPoolId:k.Ref(n),CustomDomainConfig:l}},logicalId:h}}static createIdentityPool(n){let{slug:i,environment:s,identityPoolName:o,allowUnauthenticatedIdentities:c=!1,cognitoIdentityProviders:l,supportedLoginProviders:u,samlProviderARNs:h,openIdConnectProviderARNs:f}=n,S=o||r({slug:i,environment:s,resourceType:"identity-pool"}),b=t(S);return{identityPool:{Type:"AWS::Cognito::IdentityPool",Properties:{IdentityPoolName:S,AllowUnauthenticatedIdentities:c,CognitoIdentityProviders:l,SupportedLoginProviders:u,SamlProviderARNs:h,OpenIdConnectProviderARNs:f}},logicalId:b}}static createIdentityPoolRoleAttachment(n,i){let{slug:s,environment:o,authenticatedRole:c,unauthenticatedRole:l,roleMappings:u}=i,h=r({slug:s,environment:o,resourceType:"identity-pool-role-attachment"}),f=t(h),S={authenticated:c};if(l)S.unauthenticated=l;return{attachment:{Type:"AWS::Cognito::IdentityPoolRoleAttachment",Properties:{IdentityPoolId:k.Ref(n),Roles:S,RoleMappings:u}},logicalId:f}}static createAuthenticatedRole(n){let{slug:i,environment:s,identityPoolLogicalId:o}=n,c=r({slug:i,environment:s,resourceType:"cognito-authenticated-role"}),l=t(c);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:c,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":k.Ref(o)},"ForAnyValue:StringLike":{"cognito-identity.amazonaws.com:amr":"authenticated"}}}]},Policies:[{PolicyName:"CognitoAuthenticatedPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["cognito-sync:*","cognito-identity:*"],Resource:"*"}]}}],Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:s}]}},logicalId:l}}static createUnauthenticatedRole(n){let{slug:i,environment:s,identityPoolLogicalId:o}=n,c=r({slug:i,environment:s,resourceType:"cognito-unauthenticated-role"}),l=t(c);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:c,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":k.Ref(o)},"ForAnyValue:StringLike":{"cognito-identity.amazonaws.com:amr":"unauthenticated"}}}]},Policies:[{PolicyName:"CognitoUnauthenticatedPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["cognito-sync:*"],Resource:"*"}]}}],Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:s}]}},logicalId:l}}static PasswordPolicies={relaxed:()=>({minimumLength:8,requireLowercase:!1,requireUppercase:!1,requireNumbers:!1,requireSymbols:!1,temporaryPasswordValidityDays:7}),standard:()=>({minimumLength:8,requireLowercase:!0,requireUppercase:!0,requireNumbers:!0,requireSymbols:!1,temporaryPasswordValidityDays:3}),strict:()=>({minimumLength:12,requireLowercase:!0,requireUppercase:!0,requireNumbers:!0,requireSymbols:!0,temporaryPasswordValidityDays:1})};static AuthFlows={standard:["ALLOW_USER_SRP_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],admin:["ALLOW_ADMIN_USER_PASSWORD_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],custom:["ALLOW_CUSTOM_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],all:["ALLOW_USER_SRP_AUTH","ALLOW_USER_PASSWORD_AUTH","ALLOW_ADMIN_USER_PASSWORD_AUTH","ALLOW_CUSTOM_AUTH","ALLOW_REFRESH_TOKEN_AUTH"]};static OAuthScopes={basic:["openid","email","profile"],all:["openid","email","profile","phone","aws.cognito.signin.user.admin"]};static UseCases={webApp:(n,i,s)=>{let{userPool:o,logicalId:c}=H.createUserPool({slug:n,environment:i,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:H.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:l,logicalId:u}=H.createUserPoolClient(c,{slug:n,environment:i,explicitAuthFlows:[...H.AuthFlows.standard],callbackURLs:[s],allowedOAuthFlows:["code"],allowedOAuthScopes:[...H.OAuthScopes.basic],allowedOAuthFlowsUserPoolClient:!0});return{userPool:o,poolId:c,client:l,clientId:u}},mobileApp:(n,i)=>{let{userPool:s,logicalId:o}=H.createUserPool({slug:n,environment:i,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:H.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:c,logicalId:l}=H.createUserPoolClient(o,{slug:n,environment:i,explicitAuthFlows:[...H.AuthFlows.standard]}),{identityPool:u,logicalId:h}=H.createIdentityPool({slug:n,environment:i,allowUnauthenticatedIdentities:!1,cognitoIdentityProviders:[{ClientId:k.Ref(l),ProviderName:k.GetAtt(o,"ProviderName")}]}),{role:f,logicalId:S}=H.createAuthenticatedRole({slug:n,environment:i,identityPoolLogicalId:h}),{attachment:b,logicalId:A}=H.createIdentityPoolRoleAttachment(h,{slug:n,environment:i,authenticatedRole:k.GetAtt(S,"Arn")});return{userPool:s,poolId:o,client:c,clientId:l,identityPool:u,identityPoolId:h,authRole:f,authRoleId:S,attachment:b,attachmentId:A}}}}class G{static createApplication(n){let{slug:i,environment:s,applicationName:o,computePlatform:c}=n,l=o||r({slug:i,environment:s,resourceType:"deploy-app"}),u=t(l);return{application:{Type:"AWS::CodeDeploy::Application",Properties:{ApplicationName:l,ComputePlatform:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s}]}},logicalId:u}}static createDeploymentGroup(n,i){let{slug:s,environment:o,deploymentGroupName:c,serviceRoleArn:l,autoScalingGroups:u,ec2TagFilters:h,deploymentConfigName:f,autoRollbackConfiguration:S,alarmConfiguration:b,loadBalancerInfo:A,blueGreenDeploymentConfiguration:v}=i,w=c||r({slug:s,environment:o,resourceType:"deploy-group"}),E=t(w);return{deploymentGroup:{Type:"AWS::CodeDeploy::DeploymentGroup",Properties:{ApplicationName:k.Ref(n),DeploymentGroupName:w,ServiceRoleArn:l,AutoScalingGroups:u,Ec2TagFilters:h?.map((P)=>({Key:P.key,Value:P.value,Type:P.type})),DeploymentConfigName:f,AutoRollbackConfiguration:S?{Enabled:S.enabled,Events:S.events}:void 0,AlarmConfiguration:b?{Enabled:b.enabled,Alarms:b.alarms?.map((P)=>({Name:P.name})),IgnorePollAlarmFailure:b.ignorePollAlarmFailure}:void 0,LoadBalancerInfo:A?{TargetGroupInfoList:A.targetGroupInfoList?.map((P)=>({Name:P.name})),ElbInfoList:A.elbInfoList?.map((P)=>({Name:P.name}))}:void 0,BlueGreenDeploymentConfiguration:v?{TerminateBlueInstancesOnDeploymentSuccess:v.terminateBlueInstancesOnDeploymentSuccess?{Action:v.terminateBlueInstancesOnDeploymentSuccess.action,TerminationWaitTimeInMinutes:v.terminateBlueInstancesOnDeploymentSuccess.terminationWaitTimeInMinutes}:void 0,DeploymentReadyOption:v.deploymentReadyOption?{ActionOnTimeout:v.deploymentReadyOption.actionOnTimeout,WaitTimeInMinutes:v.deploymentReadyOption.waitTimeInMinutes}:void 0,GreenFleetProvisioningOption:v.greenFleetProvisioningOption?{Action:v.greenFleetProvisioningOption.action}:void 0}:void 0,Tags:[{Key:"Name",Value:w},{Key:"Environment",Value:o}]}},logicalId:E}}static createDeploymentConfig(n){let{slug:i,environment:s,deploymentConfigName:o,minimumHealthyHosts:c,trafficRoutingConfig:l}=n,u=o||r({slug:i,environment:s,resourceType:"deploy-config"}),h=t(u);return{deploymentConfig:{Type:"AWS::CodeDeploy::DeploymentConfig",Properties:{DeploymentConfigName:u,MinimumHealthyHosts:c?{Type:c.type,Value:c.value}:void 0,TrafficRoutingConfig:l?{Type:l.type,TimeBasedCanary:l.timeBasedCanary?{CanaryPercentage:l.timeBasedCanary.canaryPercentage,CanaryInterval:l.timeBasedCanary.canaryInterval}:void 0,TimeBasedLinear:l.timeBasedLinear?{LinearPercentage:l.timeBasedLinear.linearPercentage,LinearInterval:l.timeBasedLinear.linearInterval}:void 0}:void 0}},logicalId:h}}static DeploymentConfigs={allAtOnce:()=>({type:"FLEET_PERCENT",value:0}),halfAtATime:()=>({type:"FLEET_PERCENT",value:50}),oneAtATime:()=>({type:"HOST_COUNT",value:1}),custom:(n,i)=>({type:n,value:i})};static TrafficRouting={allAtOnce:()=>({type:"AllAtOnce"}),canary:(n,i)=>({type:"TimeBasedCanary",timeBasedCanary:{canaryPercentage:n,canaryInterval:i}}),linear:(n,i)=>({type:"TimeBasedLinear",timeBasedLinear:{linearPercentage:n,linearInterval:i}})};static RollbackConfigs={onFailure:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE"]}),onAlarmOrFailure:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE","DEPLOYMENT_STOP_ON_ALARM"]}),onAllEvents:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE","DEPLOYMENT_STOP_ON_ALARM","DEPLOYMENT_STOP_ON_REQUEST"]}),disabled:()=>({enabled:!1})};static BlueGreenConfigs={standard:()=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withDelay:(n)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:n},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withManualApproval:(n)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"STOP_DEPLOYMENT",waitTimeInMinutes:n},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),keepBlue:()=>({terminateBlueInstancesOnDeploymentSuccess:{action:"KEEP_ALIVE"},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}})};static UseCases={ec2Deployment:(n,i,s,o)=>{let{application:c,logicalId:l}=G.createApplication({slug:n,environment:i,computePlatform:"Server"}),{deploymentGroup:u,logicalId:h}=G.createDeploymentGroup(l,{slug:n,environment:i,serviceRoleArn:s,autoScalingGroups:o,deploymentConfigName:"CodeDeployDefault.OneAtATime",autoRollbackConfiguration:G.RollbackConfigs.onFailure()});return{application:c,appId:l,deploymentGroup:u,groupId:h}},lambdaCanaryDeployment:(n,i,s,o=10,c=5)=>{let{application:l,logicalId:u}=G.createApplication({slug:n,environment:i,computePlatform:"Lambda"}),{deploymentConfig:h,logicalId:f}=G.createDeploymentConfig({slug:n,environment:i,trafficRoutingConfig:G.TrafficRouting.canary(o,c)}),{deploymentGroup:S,logicalId:b}=G.createDeploymentGroup(u,{slug:n,environment:i,serviceRoleArn:s,deploymentConfigName:k.Ref(f),autoRollbackConfiguration:G.RollbackConfigs.onAlarmOrFailure()});return{application:l,appId:u,deploymentConfig:h,configId:f,deploymentGroup:S,groupId:b}},ecsBlueGreenDeployment:(n,i,s,o)=>{let{application:c,logicalId:l}=G.createApplication({slug:n,environment:i,computePlatform:"ECS"}),{deploymentGroup:u,logicalId:h}=G.createDeploymentGroup(l,{slug:n,environment:i,serviceRoleArn:s,loadBalancerInfo:{targetGroupInfoList:[{name:o}]},blueGreenDeploymentConfiguration:G.BlueGreenConfigs.standard(),autoRollbackConfiguration:G.RollbackConfigs.onFailure()});return{application:c,appId:l,deploymentGroup:u,groupId:h}}};static Strategies={rolling:(n=25)=>({type:"rolling",batchPercentage:n}),blueGreen:()=>({type:"blue-green"}),canary:(n=10,i=5)=>({type:"canary",canaryPercentage:n,canaryInterval:i}),allAtOnce:()=>({type:"all-at-once"})}}class N{static ContentTypes={".html":"text/html",".htm":"text/html",".css":"text/css",".js":"application/javascript",".mjs":"application/javascript",".json":"application/json",".xml":"application/xml",".svg":"image/svg+xml",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".avif":"image/avif",".ico":"image/x-icon",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".otf":"font/otf",".eot":"application/vnd.ms-fontobject",".pdf":"application/pdf",".txt":"text/plain",".md":"text/markdown",".map":"application/json"};static NoHashPatterns=[/^index\.html$/,/^favicon\.ico$/,/^robots\.txt$/,/^sitemap\.xml$/,/^manifest\.json$/,/^\.well-known\//,/^_redirects$/,/^_headers$/];static computeFileHash(n,i="md5"){let s=st(n);return Nr(i).update(s).digest("hex")}static computeShortHash(n){return N.computeFileHash(n).slice(0,8)}static getContentType(n){let i=ma(n).toLowerCase();return N.ContentTypes[i]||"application/octet-stream"}static shouldHashFile(n,i){return![...N.NoHashPatterns,...i||[]].some((s)=>s.test(n))}static generateHashedFilename(n,i){let s=ma(n),o=Lr(n,s),c=da(n);if(c===".")return`${o}.${i}${s}`;return Qe(c,`${o}.${i}${s}`)}static collectFiles(n,i){let s=[],o=i||n;if(!Nt(n))return s;let c=kr(n,{withFileTypes:!0});for(let l of c){let u=Qe(n,l.name);if(l.isDirectory())s.push(...N.collectFiles(u,o));else if(l.isFile())s.push(u)}return s}static hashDirectory(n){let{sourceDir:i,outputDir:s,excludePatterns:o=[],hashAlgorithm:c="md5",copyUnhashed:l=!0}=n,u=N.collectFiles(i),h=[],f={};for(let b of u){let A=b.replace(i,"").replace(/^[/\\]/,""),v=N.shouldHashFile(A,o),w=$r(b),E=v?N.computeFileHash(b,c).slice(0,8):"",P=v?N.generateHashedFilename(A,E):A,R={originalPath:A,hashedPath:P,hash:E,size:w.size,contentType:N.getContentType(b)};if(h.push(R),f[A]=P,s){let D=Qe(s,P),x=da(D);if(!Nt(x)){let{mkdirSync:I}=ir("node:fs");I(x,{recursive:!0})}if(v||l)Dr(b,D)}}let S={version:"1.0",timestamp:new Date().toISOString(),assets:h,hashMap:f};if(s){let b=Qe(s,"asset-manifest.json");ot(b,JSON.stringify(S,null,2))}return S}static getInvalidationPaths(n,i){let s=[];if(!n)return["/*"];let o=n.hashMap,c=i.hashMap;for(let[l,u]of Object.entries(c)){let h=o[l];if(!h||h!==u){if(s.push(`/${l}`),h&&h!==u)s.push(`/${h}`)}}for(let[l,u]of Object.entries(o))if(!c[l])s.push(`/${l}`),s.push(`/${u}`);if(s.length>100)return["/*"];return[...new Set(s)]}static updateHtmlReferences(n){let{htmlDir:i,manifest:s,basePath:o=""}=n,c=N.collectFiles(i).filter((l)=>l.endsWith(".html")||l.endsWith(".htm"));for(let l of c){let u=st(l,"utf-8");for(let[h,f]of Object.entries(s.hashMap)){if(h===f)continue;let S=[new RegExp(`(src|href)=["']${o}/?${N.escapeRegExp(h)}["']`,"g"),new RegExp(`url\\(["']?${o}/?${N.escapeRegExp(h)}["']?\\)`,"g")];for(let b of S)u=u.replace(b,(A)=>A.replace(h,f))}ot(l,u)}}static updateCssReferences(n){let{cssDir:i,manifest:s,basePath:o=""}=n,c=N.collectFiles(i).filter((l)=>l.endsWith(".css"));for(let l of c){let u=st(l,"utf-8");for(let[h,f]of Object.entries(s.hashMap)){if(h===f)continue;let S=new RegExp(`url\\(["']?${o}/?${N.escapeRegExp(h)}["']?\\)`,"g");u=u.replace(S,`url(${o}/${f})`)}ot(l,u)}}static escapeRegExp(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}static generateS3DeploymentManifest(n){let{sourceDir:i,keyPrefix:s="",excludePatterns:o=[],cacheControl:c={hashed:"public, max-age=31536000, immutable",unhashed:"public, max-age=3600",html:"public, max-age=0, must-revalidate"}}=n;return N.hashDirectory({sourceDir:i,excludePatterns:o}).assets.map((l)=>{let u=l.hash!=="",h=l.contentType==="text/html",f=c.unhashed||"public, max-age=3600";if(h)f=c.html||"public, max-age=0, must-revalidate";else if(u)f=c.hashed||"public, max-age=31536000, immutable";return{localPath:Qe(i,l.originalPath),s3Key:s?`${s}/${l.hashedPath}`:l.hashedPath,contentType:l.contentType,cacheControl:f,hash:l.hash}})}static compareManifests(n,i){let s={added:[],removed:[],changed:[],unchanged:[]},o=new Set(Object.keys(n.hashMap)),c=new Set(Object.keys(i.hashMap));for(let l of c)if(!o.has(l))s.added.push(l);for(let l of o)if(!c.has(l))s.removed.push(l);for(let l of c)if(o.has(l))if(n.hashMap[l]!==i.hashMap[l])s.changed.push(l);else s.unchanged.push(l);return s}static loadManifest(n){if(!Nt(n))return null;try{let i=st(n,"utf-8");return JSON.parse(i)}catch{return null}}static saveManifest(n,i){ot(i,JSON.stringify(n,null,2))}}class Ni{static createSecret(n){let{slug:i,environment:s,secretName:o,description:c,secretString:l,kmsKeyId:u,tags:h}=n,f=o||r({slug:i,environment:s,resourceType:"secret"}),S=t(f),b={Type:"AWS::SecretsManager::Secret",Properties:{Name:f,Description:c,SecretString:l,Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s},...h?Object.entries(h).map(([A,v])=>({Key:A,Value:v})):[]]}};if(u)b.Properties.KmsKeyId=u;return{secret:b,logicalId:S}}static createGeneratedSecret(n){let{slug:i,environment:s,secretName:o,description:c,excludeCharacters:l,excludeLowercase:u,excludeNumbers:h,excludePunctuation:f,excludeUppercase:S,passwordLength:b,requireEachIncludedType:A,kmsKeyId:v,tags:w}=n,E=o||r({slug:i,environment:s,resourceType:"secret"}),P=t(E),R={Type:"AWS::SecretsManager::Secret",Properties:{Name:E,Description:c,GenerateSecretString:{ExcludeCharacters:l,ExcludeLowercase:u,ExcludeNumbers:h,ExcludePunctuation:f,ExcludeUppercase:S,PasswordLength:b||32,RequireEachIncludedType:A!==!1},Tags:[{Key:"Name",Value:E},{Key:"Environment",Value:s},...w?Object.entries(w).map(([D,x])=>({Key:D,Value:x})):[]]}};if(v)R.Properties.KmsKeyId=v;return{secret:R,logicalId:P}}static createDatabaseSecret(n){let{slug:i,environment:s,secretName:o,username:c,dbname:l,engine:u,host:h,port:f,kmsKeyId:S}=n,b=o||r({slug:i,environment:s,resourceType:"db-secret"}),A=t(b),v={username:c};if(l)v.dbname=l;if(u)v.engine=u;if(h)v.host=h;if(f)v.port=f;let w={Type:"AWS::SecretsManager::Secret",Properties:{Name:b,Description:`Database credentials for ${c}`,GenerateSecretString:{SecretStringTemplate:JSON.stringify(v),GenerateStringKey:"password",PasswordLength:32,ExcludeCharacters:'"@/\\',RequireEachIncludedType:!0},Tags:[{Key:"Name",Value:b},{Key:"Environment",Value:s},{Key:"Type",Value:"database"}]}};if(S)w.Properties.KmsKeyId=S;return{secret:w,logicalId:A}}static attachToDatabase(n){let{slug:i,environment:s,secretId:o,targetId:c,targetType:l}=n,u=r({slug:i,environment:s,resourceType:"secret-attachment"}),h=t(u);return{attachment:{Type:"AWS::SecretsManager::SecretTargetAttachment",Properties:{SecretId:o,TargetId:c,TargetType:l}},logicalId:h}}static enableRotation(n){let{slug:i,environment:s,secretId:o,rotationLambdaArn:c,automaticallyAfterDays:l,rotationType:u,kmsKeyArn:h,vpcSecurityGroupIds:f,vpcSubnetIds:S}=n,b=r({slug:i,environment:s,resourceType:"secret-rotation"}),A=t(b),v={Type:"AWS::SecretsManager::RotationSchedule",Properties:{SecretId:o,RotationRules:{AutomaticallyAfterDays:l||30}}};if(c)v.Properties.RotationLambdaARN=c;else if(u)v.Properties.HostedRotationLambda={RotationType:u,KmsKeyArn:h,VpcSecurityGroupIds:f,VpcSubnetIds:S};return{rotation:v,logicalId:A}}static SecretTypes={apiKey:(n,i,s)=>Ni.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-${s}-api-key`,description:`API key for ${s}`,passwordLength:32,excludePunctuation:!0,excludeLowercase:!1,excludeUppercase:!1,excludeNumbers:!1}),oauthClientSecret:(n,i,s)=>Ni.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-${s}-oauth-secret`,description:`OAuth client secret for ${s}`,passwordLength:64,excludeCharacters:"\"'`\\/@",requireEachIncludedType:!0}),jwtSecret:(n,i)=>Ni.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-jwt-secret`,description:"JWT signing secret",passwordLength:64,excludePunctuation:!0}),encryptionKey:(n,i)=>Ni.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-encryption-key`,description:"Data encryption key",passwordLength:64,excludeCharacters:"+/=",excludePunctuation:!0})};static RotationTypes={MySQLSingleUser:"MySQLSingleUser",MySQLMultiUser:"MySQLMultiUser",PostgreSQLSingleUser:"PostgreSQLSingleUser",PostgreSQLMultiUser:"PostgreSQLMultiUser",OracleSingleUser:"OracleSingleUser",OracleMultiUser:"OracleMultiUser",MariaDBSingleUser:"MariaDBSingleUser",MariaDBMultiUser:"MariaDBMultiUser",SQLServerSingleUser:"SQLServerSingleUser",SQLServerMultiUser:"SQLServerMultiUser",RedshiftSingleUser:"RedshiftSingleUser",RedshiftMultiUser:"RedshiftMultiUser",MongoDBSingleUser:"MongoDBSingleUser",MongoDBMultiUser:"MongoDBMultiUser"}}class T{static createParameter(n){let{slug:i,environment:s,parameterName:o,value:c,type:l="String",description:u,tier:h="Standard",tags:f}=n,S=o||r({slug:i,environment:s,resourceType:"parameter"}),b=t(S);return{parameter:{Type:"AWS::SSM::Parameter",Properties:{Name:`/${i}/${s}/${S}`,Type:l,Value:c,Description:u,Tier:h,Tags:{Name:S,Environment:s,...f}}},logicalId:b}}static createString(n,i,s,o,c){return T.createParameter({slug:n,environment:i,parameterName:s,value:o,type:"String",description:c})}static createSecureString(n,i,s,o,c){return T.createParameter({slug:n,environment:i,parameterName:s,value:o,type:"SecureString",description:c})}static createStringList(n,i,s,o,c){return T.createParameter({slug:n,environment:i,parameterName:s,value:o.join(","),type:"StringList",description:c})}static Parameters={databaseUrl:(n,i,s)=>T.createSecureString(n,i,"database-url",s,"Database connection URL"),apiEndpoint:(n,i,s)=>T.createString(n,i,"api-endpoint",s,"API endpoint URL"),appVersion:(n,i,s)=>T.createString(n,i,"app-version",s,"Application version"),featureFlags:(n,i,s)=>T.createStringList(n,i,"feature-flags",s,"Enabled feature flags"),apiKey:(n,i,s,o)=>T.createSecureString(n,i,`${s}-api-key`,o,`API key for ${s}`),oauthCredentials:(n,i,s,o)=>{let c=T.createString(n,i,"oauth-client-id",s,"OAuth client ID"),l=T.createSecureString(n,i,"oauth-client-secret",o,"OAuth client secret");return{clientId:c,clientSecret:l}},smtpCredentials:(n,i,s,o,c,l)=>{let u=T.createString(n,i,"smtp-username",s,"SMTP username"),h=T.createSecureString(n,i,"smtp-password",o,"SMTP password"),f=T.createString(n,i,"smtp-host",c,"SMTP host"),S=T.createString(n,i,"smtp-port",l.toString(),"SMTP port");return{username:u,password:h,host:f,port:S}},redisUrl:(n,i,s)=>T.createSecureString(n,i,"redis-url",s,"Redis connection URL"),s3Bucket:(n,i,s)=>T.createString(n,i,"s3-bucket",s,"S3 bucket name"),cloudFrontDistribution:(n,i,s)=>T.createString(n,i,"cloudfront-distribution-id",s,"CloudFront distribution ID")}}class Kt{static createDomain(n){let{slug:i,environment:s,domainName:o,engineVersion:c="OpenSearch_2.11",instanceType:l="t3.small.search",instanceCount:u=1,volumeSize:h=10,volumeType:f="gp3",dedicatedMaster:S=!1,dedicatedMasterType:b,dedicatedMasterCount:A=3,multiAz:v=!1,availabilityZoneCount:w=2,vpc:E,encryption:P,enforceHttps:R=!0,tlsSecurityPolicy:D="Policy-Min-TLS-1-2-2019-07",advancedSecurity:x,autoSnapshotHour:I=0,autoTune:_=!0,tags:B={}}=n,W=o||r({slug:i,environment:s,resourceType:"search"}),J=t(W);return{domain:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:W,EngineVersion:c,ClusterConfig:{InstanceType:l,InstanceCount:u,DedicatedMasterEnabled:S,...S&&{DedicatedMasterType:b||l,DedicatedMasterCount:A},ZoneAwarenessEnabled:v,...v&&{ZoneAwarenessConfig:{AvailabilityZoneCount:w}}},EBSOptions:{EBSEnabled:!0,VolumeType:f,VolumeSize:h},DomainEndpointOptions:{EnforceHTTPS:R,TLSSecurityPolicy:D},SnapshotOptions:{AutomatedSnapshotStartHour:I},...E&&{VPCOptions:{SubnetIds:E.subnetIds,SecurityGroupIds:E.securityGroupIds}},...P&&{EncryptionAtRestOptions:{Enabled:P.atRest??!0,...P.kmsKeyId&&{KmsKeyId:P.kmsKeyId}},NodeToNodeEncryptionOptions:{Enabled:P.nodeToNode??!0}},...x&&{AdvancedSecurityOptions:{Enabled:x.enabled,InternalUserDatabaseEnabled:x.internalUserDatabase??!0,...x.masterUserName&&x.masterUserPassword&&{MasterUserOptions:{MasterUserName:x.masterUserName,MasterUserPassword:x.masterUserPassword}},...x.masterUserArn&&{MasterUserOptions:{MasterUserARN:x.masterUserArn}}}},..._&&{AutoTuneOptions:{DesiredState:"ENABLED"}},Tags:[{Key:"Name",Value:W},{Key:"Environment",Value:s},...Object.entries(B).map(([K,Y])=>({Key:K,Value:Y}))]}},logicalId:J}}static createAccessPolicy(n,i){let{ipAddresses:s,iamPrincipalArns:o,allowAll:c,vpcEndpoint:l}=i;if(c)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:n}]};let u=[];if(o&&o.length>0)u.push({Effect:"Allow",Principal:{AWS:o},Action:"es:*",Resource:n});if(s&&s.length>0)u.push({Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:n,Condition:{IpAddress:{"aws:SourceIp":s}}});if(l)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:n}]};return{Version:"2012-10-17",Statement:u}}static DomainPresets={development:(n,i)=>Kt.createDomain({slug:n,environment:i,instanceType:"t3.small.search",instanceCount:1,volumeSize:10,multiAz:!1,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!1}),production:(n,i,s)=>Kt.createDomain({slug:n,environment:i,instanceType:"m6g.large.search",instanceCount:3,volumeSize:100,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"m6g.large.search",dedicatedMasterCount:3,vpc:s,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!0},autoTune:!0}),costOptimized:(n,i)=>Kt.createDomain({slug:n,environment:i,instanceType:"t3.medium.search",instanceCount:2,volumeSize:20,volumeType:"gp3",multiAz:!0,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!0}),highPerformance:(n,i,s)=>Kt.createDomain({slug:n,environment:i,instanceType:"r6g.2xlarge.search",instanceCount:6,volumeSize:500,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"c6g.xlarge.search",dedicatedMasterCount:3,vpc:s,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!1},autoTune:!0})};static InstanceTypes={"t3.small.search":"t3.small.search","t3.medium.search":"t3.medium.search","m6g.large.search":"m6g.large.search","m6g.xlarge.search":"m6g.xlarge.search","m6g.2xlarge.search":"m6g.2xlarge.search","r6g.large.search":"r6g.large.search","r6g.xlarge.search":"r6g.xlarge.search","r6g.2xlarge.search":"r6g.2xlarge.search","r6g.4xlarge.search":"r6g.4xlarge.search","c6g.large.search":"c6g.large.search","c6g.xlarge.search":"c6g.xlarge.search","c6g.2xlarge.search":"c6g.2xlarge.search"};static EngineVersions={"OpenSearch_2.11":"OpenSearch_2.11","OpenSearch_2.9":"OpenSearch_2.9","OpenSearch_2.7":"OpenSearch_2.7","OpenSearch_1.3":"OpenSearch_1.3","Elasticsearch_7.10":"Elasticsearch_7.10"}}class yt{static createDomainRedirectBucket(n){let{slug:i,environment:s,sourceDomain:o,targetDomain:c,protocol:l="https"}=n,u=r({slug:i,environment:s,resourceType:"s3",suffix:"redirect"}),h=t(u),f=t(`${u}-policy`),S={Type:"AWS::S3::Bucket",Properties:{BucketName:o,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:c,Protocol:l}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1},Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:s},{Key:"Purpose",Value:"Domain Redirect"}]}},b={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:k.Ref(h),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[k.Join("",[k.GetAtt(h,"Arn"),"/*"])]}]}}};return{bucket:S,bucketPolicy:b,logicalId:h,policyLogicalId:f}}static createPathRedirectFunction(n){let{slug:i,environment:s,rules:o}=n,c=r({slug:i,environment:s,resourceType:"cf-redirect"}),l=t(c),u=yt.generateRedirectFunctionCode(o);return{function:{Type:"AWS::CloudFront::Function",Properties:{Name:c,AutoPublish:!0,FunctionConfig:{Comment:`Path redirect function for ${i} (${s})`,Runtime:"cloudfront-js-2.0"},FunctionCode:u}},logicalId:l,functionCode:u}}static generateRedirectFunctionCode(n){return`function handler(event) {
|
|
2316
|
+
| limit 50`,region:o,title:"Recent Errors and Warnings"}}),u+=6;return ho.createDashboard({slug:i,environment:s,widgets:l})}static DashboardTemplates={staticWebsite:(n)=>({slug:n.slug,environment:n.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${n.slug.toUpperCase()} Static Website Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"CloudFront Requests",region:"us-east-1",metrics:[["AWS/CloudFront","Requests","DistributionId",n.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"Error Rate",region:"us-east-1",metrics:[["AWS/CloudFront","4xxErrorRate","DistributionId",n.cloudFrontDistributionId,"Region","Global",{label:"4XX"}],["AWS/CloudFront","5xxErrorRate","DistributionId",n.cloudFrontDistributionId,"Region","Global",{label:"5XX"}]],period:300,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Bytes Downloaded",region:"us-east-1",metrics:[["AWS/CloudFront","BytesDownloaded","DistributionId",n.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:0,y:7,width:12,height:6,properties:{title:"S3 Bucket Size",region:n.region||"us-east-1",metrics:[["AWS/S3","BucketSizeBytes","BucketName",n.s3BucketName,"StorageType","StandardStorage"]],period:86400,stat:"Average"}},{type:"metric",x:12,y:7,width:12,height:6,properties:{title:"S3 Number of Objects",region:n.region||"us-east-1",metrics:[["AWS/S3","NumberOfObjects","BucketName",n.s3BucketName,"StorageType","AllStorageTypes"]],period:86400,stat:"Average"}}]}),serverlessApi:(n)=>({slug:n.slug,environment:n.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${n.slug.toUpperCase()} Serverless API Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"API Requests",region:n.region||"us-east-1",metrics:[["AWS/ApiGateway","Count","ApiName",n.apiGatewayName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"API Latency",region:n.region||"us-east-1",metrics:[["AWS/ApiGateway","Latency","ApiName",n.apiGatewayName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"API Errors",region:n.region||"us-east-1",metrics:[["AWS/ApiGateway","4XXError","ApiName",n.apiGatewayName,{label:"4XX"}],["AWS/ApiGateway","5XXError","ApiName",n.apiGatewayName,{label:"5XX"}]],period:60,stat:"Sum"}},...n.lambdaFunctionNames.map((i,s)=>({type:"metric",x:s%3*8,y:7+Math.floor(s/3)*6,width:8,height:6,properties:{title:`${i} Metrics`,region:n.region||"us-east-1",metrics:[["AWS/Lambda","Invocations","FunctionName",i],["AWS/Lambda","Duration","FunctionName",i],["AWS/Lambda","Errors","FunctionName",i]],period:300,stat:"Sum"}}))]}),containerService:(n)=>({slug:n.slug,environment:n.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${n.slug.toUpperCase()} Container Service Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"ECS CPU",region:n.region||"us-east-1",metrics:[["AWS/ECS","CPUUtilization","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"ECS Memory",region:n.region||"us-east-1",metrics:[["AWS/ECS","MemoryUtilization","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Running Tasks",region:n.region||"us-east-1",metrics:[["ECS/ContainerInsights","RunningTaskCount","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:0,y:7,width:8,height:6,properties:{title:"ALB Requests",region:n.region||"us-east-1",metrics:[["AWS/ApplicationELB","RequestCount","LoadBalancer",n.albName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:7,width:8,height:6,properties:{title:"Response Time",region:n.region||"us-east-1",metrics:[["AWS/ApplicationELB","TargetResponseTime","LoadBalancer",n.albName]],period:60,stat:"Average"}},{type:"metric",x:16,y:7,width:8,height:6,properties:{title:"Healthy Hosts",region:n.region||"us-east-1",metrics:[["AWS/ApplicationELB","HealthyHostCount","LoadBalancer",n.albName]],period:60,stat:"Average"}},...n.rdsInstanceId?[{type:"metric",x:0,y:13,width:12,height:6,properties:{title:"RDS CPU",region:n.region||"us-east-1",metrics:[["AWS/RDS","CPUUtilization","DBInstanceIdentifier",n.rdsInstanceId]],period:300,stat:"Average"}},{type:"metric",x:12,y:13,width:12,height:6,properties:{title:"RDS Connections",region:n.region||"us-east-1",metrics:[["AWS/RDS","DatabaseConnections","DBInstanceIdentifier",n.rdsInstanceId]],period:60,stat:"Sum"}}]:[]]})};static Config={createAlarmConfig:(n)=>{let{metricName:i,namespace:s,threshold:o,comparisonOperator:c="GreaterThanThreshold",evaluationPeriods:l=1,period:u=300,statistic:h="Average",treatMissingData:f="missing"}=n;return{MetricName:i,Namespace:s,Threshold:o,ComparisonOperator:c,EvaluationPeriods:l,Period:u,Statistic:h,TreatMissingData:f}},namespaces:{ec2:"AWS/EC2",ecs:"AWS/ECS",lambda:"AWS/Lambda",rds:"AWS/RDS",sqs:"AWS/SQS",sns:"AWS/SNS",s3:"AWS/S3",cloudfront:"AWS/CloudFront",alb:"AWS/ApplicationELB",nlb:"AWS/NetworkELB",apiGateway:"AWS/ApiGateway",dynamodb:"AWS/DynamoDB",elasticache:"AWS/ElastiCache"},comparisonOperators:{greaterThan:"GreaterThanThreshold",greaterOrEqual:"GreaterThanOrEqualToThreshold",lessThan:"LessThanThreshold",lessOrEqual:"LessThanOrEqualToThreshold"},metrics:{ec2:{cpu:{metricName:"CPUUtilization",namespace:"AWS/EC2"},networkIn:{metricName:"NetworkIn",namespace:"AWS/EC2"},networkOut:{metricName:"NetworkOut",namespace:"AWS/EC2"},statusCheck:{metricName:"StatusCheckFailed",namespace:"AWS/EC2"}},ecs:{cpu:{metricName:"CPUUtilization",namespace:"AWS/ECS"},memory:{metricName:"MemoryUtilization",namespace:"AWS/ECS"}},lambda:{invocations:{metricName:"Invocations",namespace:"AWS/Lambda"},errors:{metricName:"Errors",namespace:"AWS/Lambda"},duration:{metricName:"Duration",namespace:"AWS/Lambda"},throttles:{metricName:"Throttles",namespace:"AWS/Lambda"},concurrentExecutions:{metricName:"ConcurrentExecutions",namespace:"AWS/Lambda"}},rds:{cpu:{metricName:"CPUUtilization",namespace:"AWS/RDS"},connections:{metricName:"DatabaseConnections",namespace:"AWS/RDS"},freeStorage:{metricName:"FreeStorageSpace",namespace:"AWS/RDS"},readLatency:{metricName:"ReadLatency",namespace:"AWS/RDS"},writeLatency:{metricName:"WriteLatency",namespace:"AWS/RDS"}},alb:{requestCount:{metricName:"RequestCount",namespace:"AWS/ApplicationELB"},responseTime:{metricName:"TargetResponseTime",namespace:"AWS/ApplicationELB"},httpCode4xx:{metricName:"HTTPCode_Target_4XX_Count",namespace:"AWS/ApplicationELB"},httpCode5xx:{metricName:"HTTPCode_Target_5XX_Count",namespace:"AWS/ApplicationELB"},healthyHosts:{metricName:"HealthyHostCount",namespace:"AWS/ApplicationELB"}},sqs:{messagesVisible:{metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS"},messagesDelayed:{metricName:"ApproximateNumberOfMessagesDelayed",namespace:"AWS/SQS"},messageAge:{metricName:"ApproximateAgeOfOldestMessage",namespace:"AWS/SQS"}}},presets:{highCpu:(n=80)=>({metricName:"CPUUtilization",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highMemory:(n=80)=>({metricName:"MemoryUtilization",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highErrors:(n=10)=>({metricName:"Errors",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:1,period:60,statistic:"Sum"}),highLatency:(n=5000)=>({metricName:"Duration",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowHealthyHosts:(n=1)=>({metricName:"HealthyHostCount",namespace:"AWS/ApplicationELB",threshold:n,comparisonOperator:"LessThanThreshold",evaluationPeriods:2,period:60,statistic:"Minimum"}),queueDepth:(n=1000)=>({metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowStorage:(n=10737418240)=>({metricName:"FreeStorageSpace",namespace:"AWS/RDS",threshold:n,comparisonOperator:"LessThanThreshold",evaluationPeriods:1,period:300,statistic:"Average"})}}}class H{static createUserPool(n){let{slug:i,environment:s,userPoolName:o,aliasAttributes:c,autoVerifiedAttributes:l,passwordPolicy:u,mfaConfiguration:h,emailConfiguration:f,smsConfiguration:S,lambdaTriggers:b,userPoolAddOns:A,accountRecoverySetting:v}=n,w=o||r({slug:i,environment:s,resourceType:"user-pool"}),E=t(w),P={Type:"AWS::Cognito::UserPool",Properties:{UserPoolName:w,Policies:u?{PasswordPolicy:{MinimumLength:u.minimumLength,RequireLowercase:u.requireLowercase,RequireUppercase:u.requireUppercase,RequireNumbers:u.requireNumbers,RequireSymbols:u.requireSymbols,TemporaryPasswordValidityDays:u.temporaryPasswordValidityDays}}:void 0,MfaConfiguration:h,Schema:[{Name:"email",AttributeDataType:"String",Required:!0,Mutable:!1}]}};if(c&&c.length>0)P.Properties.UsernameAttributes=c;if(l&&l.length>0)P.Properties.AutoVerifiedAttributes=l;if(f)P.Properties.EmailConfiguration={EmailSendingAccount:f.emailSendingAccount,From:f.from,ReplyToEmailAddress:f.replyToEmailAddress,SourceArn:f.sourceArn,ConfigurationSet:f.configurationSet};if(S)P.Properties.SmsConfiguration={ExternalId:S.externalId,SnsCallerArn:S.snsCallerArn};if(b)P.Properties.LambdaConfig={PreSignUp:b.preSignUp,PostConfirmation:b.postConfirmation,PreAuthentication:b.preAuthentication,PostAuthentication:b.postAuthentication,CustomMessage:b.customMessage,DefineAuthChallenge:b.defineAuthChallenge,CreateAuthChallenge:b.createAuthChallenge,VerifyAuthChallengeResponse:b.verifyAuthChallengeResponse,PreTokenGeneration:b.preTokenGeneration,UserMigration:b.userMigration};if(A)P.Properties.UserPoolAddOns={AdvancedSecurityMode:A.advancedSecurityMode};if(v)P.Properties.AccountRecoverySetting={RecoveryMechanisms:v.recoveryMechanisms};return{userPool:P,logicalId:E}}static createUserPoolClient(n,i){let{slug:s,environment:o,clientName:c,generateSecret:l=!1,refreshTokenValidity:u,accessTokenValidity:h,idTokenValidity:f,tokenValidityUnits:S,readAttributes:b,writeAttributes:A,explicitAuthFlows:v,preventUserExistenceErrors:w,enableTokenRevocation:E,callbackURLs:P,logoutURLs:R,allowedOAuthFlows:D,allowedOAuthScopes:O,allowedOAuthFlowsUserPoolClient:I,supportedIdentityProviders:_}=i,B=c||r({slug:s,environment:o,resourceType:"user-pool-client"}),W=t(B);return{client:{Type:"AWS::Cognito::UserPoolClient",Properties:{ClientName:B,UserPoolId:k.Ref(n),GenerateSecret:l,RefreshTokenValidity:u,AccessTokenValidity:h,IdTokenValidity:f,TokenValidityUnits:S,ReadAttributes:b,WriteAttributes:A,ExplicitAuthFlows:v,PreventUserExistenceErrors:w,EnableTokenRevocation:E,CallbackURLs:P,LogoutURLs:R,AllowedOAuthFlows:D,AllowedOAuthScopes:O,AllowedOAuthFlowsUserPoolClient:I,SupportedIdentityProviders:_}},logicalId:W}}static createUserPoolDomain(n,i){let{slug:s,environment:o,domain:c,customDomainConfig:l}=i,u=r({slug:s,environment:o,resourceType:"user-pool-domain"}),h=t(u);return{domain:{Type:"AWS::Cognito::UserPoolDomain",Properties:{Domain:c,UserPoolId:k.Ref(n),CustomDomainConfig:l}},logicalId:h}}static createIdentityPool(n){let{slug:i,environment:s,identityPoolName:o,allowUnauthenticatedIdentities:c=!1,cognitoIdentityProviders:l,supportedLoginProviders:u,samlProviderARNs:h,openIdConnectProviderARNs:f}=n,S=o||r({slug:i,environment:s,resourceType:"identity-pool"}),b=t(S);return{identityPool:{Type:"AWS::Cognito::IdentityPool",Properties:{IdentityPoolName:S,AllowUnauthenticatedIdentities:c,CognitoIdentityProviders:l,SupportedLoginProviders:u,SamlProviderARNs:h,OpenIdConnectProviderARNs:f}},logicalId:b}}static createIdentityPoolRoleAttachment(n,i){let{slug:s,environment:o,authenticatedRole:c,unauthenticatedRole:l,roleMappings:u}=i,h=r({slug:s,environment:o,resourceType:"identity-pool-role-attachment"}),f=t(h),S={authenticated:c};if(l)S.unauthenticated=l;return{attachment:{Type:"AWS::Cognito::IdentityPoolRoleAttachment",Properties:{IdentityPoolId:k.Ref(n),Roles:S,RoleMappings:u}},logicalId:f}}static createAuthenticatedRole(n){let{slug:i,environment:s,identityPoolLogicalId:o}=n,c=r({slug:i,environment:s,resourceType:"cognito-authenticated-role"}),l=t(c);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:c,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":k.Ref(o)},"ForAnyValue:StringLike":{"cognito-identity.amazonaws.com:amr":"authenticated"}}}]},Policies:[{PolicyName:"CognitoAuthenticatedPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["cognito-sync:*","cognito-identity:*"],Resource:"*"}]}}],Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:s}]}},logicalId:l}}static createUnauthenticatedRole(n){let{slug:i,environment:s,identityPoolLogicalId:o}=n,c=r({slug:i,environment:s,resourceType:"cognito-unauthenticated-role"}),l=t(c);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:c,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":k.Ref(o)},"ForAnyValue:StringLike":{"cognito-identity.amazonaws.com:amr":"unauthenticated"}}}]},Policies:[{PolicyName:"CognitoUnauthenticatedPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["cognito-sync:*"],Resource:"*"}]}}],Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:s}]}},logicalId:l}}static PasswordPolicies={relaxed:()=>({minimumLength:8,requireLowercase:!1,requireUppercase:!1,requireNumbers:!1,requireSymbols:!1,temporaryPasswordValidityDays:7}),standard:()=>({minimumLength:8,requireLowercase:!0,requireUppercase:!0,requireNumbers:!0,requireSymbols:!1,temporaryPasswordValidityDays:3}),strict:()=>({minimumLength:12,requireLowercase:!0,requireUppercase:!0,requireNumbers:!0,requireSymbols:!0,temporaryPasswordValidityDays:1})};static AuthFlows={standard:["ALLOW_USER_SRP_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],admin:["ALLOW_ADMIN_USER_PASSWORD_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],custom:["ALLOW_CUSTOM_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],all:["ALLOW_USER_SRP_AUTH","ALLOW_USER_PASSWORD_AUTH","ALLOW_ADMIN_USER_PASSWORD_AUTH","ALLOW_CUSTOM_AUTH","ALLOW_REFRESH_TOKEN_AUTH"]};static OAuthScopes={basic:["openid","email","profile"],all:["openid","email","profile","phone","aws.cognito.signin.user.admin"]};static UseCases={webApp:(n,i,s)=>{let{userPool:o,logicalId:c}=H.createUserPool({slug:n,environment:i,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:H.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:l,logicalId:u}=H.createUserPoolClient(c,{slug:n,environment:i,explicitAuthFlows:[...H.AuthFlows.standard],callbackURLs:[s],allowedOAuthFlows:["code"],allowedOAuthScopes:[...H.OAuthScopes.basic],allowedOAuthFlowsUserPoolClient:!0});return{userPool:o,poolId:c,client:l,clientId:u}},mobileApp:(n,i)=>{let{userPool:s,logicalId:o}=H.createUserPool({slug:n,environment:i,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:H.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:c,logicalId:l}=H.createUserPoolClient(o,{slug:n,environment:i,explicitAuthFlows:[...H.AuthFlows.standard]}),{identityPool:u,logicalId:h}=H.createIdentityPool({slug:n,environment:i,allowUnauthenticatedIdentities:!1,cognitoIdentityProviders:[{ClientId:k.Ref(l),ProviderName:k.GetAtt(o,"ProviderName")}]}),{role:f,logicalId:S}=H.createAuthenticatedRole({slug:n,environment:i,identityPoolLogicalId:h}),{attachment:b,logicalId:A}=H.createIdentityPoolRoleAttachment(h,{slug:n,environment:i,authenticatedRole:k.GetAtt(S,"Arn")});return{userPool:s,poolId:o,client:c,clientId:l,identityPool:u,identityPoolId:h,authRole:f,authRoleId:S,attachment:b,attachmentId:A}}}}class G{static createApplication(n){let{slug:i,environment:s,applicationName:o,computePlatform:c}=n,l=o||r({slug:i,environment:s,resourceType:"deploy-app"}),u=t(l);return{application:{Type:"AWS::CodeDeploy::Application",Properties:{ApplicationName:l,ComputePlatform:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s}]}},logicalId:u}}static createDeploymentGroup(n,i){let{slug:s,environment:o,deploymentGroupName:c,serviceRoleArn:l,autoScalingGroups:u,ec2TagFilters:h,deploymentConfigName:f,autoRollbackConfiguration:S,alarmConfiguration:b,loadBalancerInfo:A,blueGreenDeploymentConfiguration:v}=i,w=c||r({slug:s,environment:o,resourceType:"deploy-group"}),E=t(w);return{deploymentGroup:{Type:"AWS::CodeDeploy::DeploymentGroup",Properties:{ApplicationName:k.Ref(n),DeploymentGroupName:w,ServiceRoleArn:l,AutoScalingGroups:u,Ec2TagFilters:h?.map((P)=>({Key:P.key,Value:P.value,Type:P.type})),DeploymentConfigName:f,AutoRollbackConfiguration:S?{Enabled:S.enabled,Events:S.events}:void 0,AlarmConfiguration:b?{Enabled:b.enabled,Alarms:b.alarms?.map((P)=>({Name:P.name})),IgnorePollAlarmFailure:b.ignorePollAlarmFailure}:void 0,LoadBalancerInfo:A?{TargetGroupInfoList:A.targetGroupInfoList?.map((P)=>({Name:P.name})),ElbInfoList:A.elbInfoList?.map((P)=>({Name:P.name}))}:void 0,BlueGreenDeploymentConfiguration:v?{TerminateBlueInstancesOnDeploymentSuccess:v.terminateBlueInstancesOnDeploymentSuccess?{Action:v.terminateBlueInstancesOnDeploymentSuccess.action,TerminationWaitTimeInMinutes:v.terminateBlueInstancesOnDeploymentSuccess.terminationWaitTimeInMinutes}:void 0,DeploymentReadyOption:v.deploymentReadyOption?{ActionOnTimeout:v.deploymentReadyOption.actionOnTimeout,WaitTimeInMinutes:v.deploymentReadyOption.waitTimeInMinutes}:void 0,GreenFleetProvisioningOption:v.greenFleetProvisioningOption?{Action:v.greenFleetProvisioningOption.action}:void 0}:void 0,Tags:[{Key:"Name",Value:w},{Key:"Environment",Value:o}]}},logicalId:E}}static createDeploymentConfig(n){let{slug:i,environment:s,deploymentConfigName:o,minimumHealthyHosts:c,trafficRoutingConfig:l}=n,u=o||r({slug:i,environment:s,resourceType:"deploy-config"}),h=t(u);return{deploymentConfig:{Type:"AWS::CodeDeploy::DeploymentConfig",Properties:{DeploymentConfigName:u,MinimumHealthyHosts:c?{Type:c.type,Value:c.value}:void 0,TrafficRoutingConfig:l?{Type:l.type,TimeBasedCanary:l.timeBasedCanary?{CanaryPercentage:l.timeBasedCanary.canaryPercentage,CanaryInterval:l.timeBasedCanary.canaryInterval}:void 0,TimeBasedLinear:l.timeBasedLinear?{LinearPercentage:l.timeBasedLinear.linearPercentage,LinearInterval:l.timeBasedLinear.linearInterval}:void 0}:void 0}},logicalId:h}}static DeploymentConfigs={allAtOnce:()=>({type:"FLEET_PERCENT",value:0}),halfAtATime:()=>({type:"FLEET_PERCENT",value:50}),oneAtATime:()=>({type:"HOST_COUNT",value:1}),custom:(n,i)=>({type:n,value:i})};static TrafficRouting={allAtOnce:()=>({type:"AllAtOnce"}),canary:(n,i)=>({type:"TimeBasedCanary",timeBasedCanary:{canaryPercentage:n,canaryInterval:i}}),linear:(n,i)=>({type:"TimeBasedLinear",timeBasedLinear:{linearPercentage:n,linearInterval:i}})};static RollbackConfigs={onFailure:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE"]}),onAlarmOrFailure:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE","DEPLOYMENT_STOP_ON_ALARM"]}),onAllEvents:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE","DEPLOYMENT_STOP_ON_ALARM","DEPLOYMENT_STOP_ON_REQUEST"]}),disabled:()=>({enabled:!1})};static BlueGreenConfigs={standard:()=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withDelay:(n)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:n},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withManualApproval:(n)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"STOP_DEPLOYMENT",waitTimeInMinutes:n},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),keepBlue:()=>({terminateBlueInstancesOnDeploymentSuccess:{action:"KEEP_ALIVE"},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}})};static UseCases={ec2Deployment:(n,i,s,o)=>{let{application:c,logicalId:l}=G.createApplication({slug:n,environment:i,computePlatform:"Server"}),{deploymentGroup:u,logicalId:h}=G.createDeploymentGroup(l,{slug:n,environment:i,serviceRoleArn:s,autoScalingGroups:o,deploymentConfigName:"CodeDeployDefault.OneAtATime",autoRollbackConfiguration:G.RollbackConfigs.onFailure()});return{application:c,appId:l,deploymentGroup:u,groupId:h}},lambdaCanaryDeployment:(n,i,s,o=10,c=5)=>{let{application:l,logicalId:u}=G.createApplication({slug:n,environment:i,computePlatform:"Lambda"}),{deploymentConfig:h,logicalId:f}=G.createDeploymentConfig({slug:n,environment:i,trafficRoutingConfig:G.TrafficRouting.canary(o,c)}),{deploymentGroup:S,logicalId:b}=G.createDeploymentGroup(u,{slug:n,environment:i,serviceRoleArn:s,deploymentConfigName:k.Ref(f),autoRollbackConfiguration:G.RollbackConfigs.onAlarmOrFailure()});return{application:l,appId:u,deploymentConfig:h,configId:f,deploymentGroup:S,groupId:b}},ecsBlueGreenDeployment:(n,i,s,o)=>{let{application:c,logicalId:l}=G.createApplication({slug:n,environment:i,computePlatform:"ECS"}),{deploymentGroup:u,logicalId:h}=G.createDeploymentGroup(l,{slug:n,environment:i,serviceRoleArn:s,loadBalancerInfo:{targetGroupInfoList:[{name:o}]},blueGreenDeploymentConfiguration:G.BlueGreenConfigs.standard(),autoRollbackConfiguration:G.RollbackConfigs.onFailure()});return{application:c,appId:l,deploymentGroup:u,groupId:h}}};static Strategies={rolling:(n=25)=>({type:"rolling",batchPercentage:n}),blueGreen:()=>({type:"blue-green"}),canary:(n=10,i=5)=>({type:"canary",canaryPercentage:n,canaryInterval:i}),allAtOnce:()=>({type:"all-at-once"})}}class N{static ContentTypes={".html":"text/html",".htm":"text/html",".css":"text/css",".js":"application/javascript",".mjs":"application/javascript",".json":"application/json",".xml":"application/xml",".svg":"image/svg+xml",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".avif":"image/avif",".ico":"image/x-icon",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".otf":"font/otf",".eot":"application/vnd.ms-fontobject",".pdf":"application/pdf",".txt":"text/plain",".md":"text/markdown",".map":"application/json"};static NoHashPatterns=[/^index\.html$/,/^favicon\.ico$/,/^robots\.txt$/,/^sitemap\.xml$/,/^manifest\.json$/,/^\.well-known\//,/^_redirects$/,/^_headers$/];static computeFileHash(n,i="md5"){let s=st(n);return Nr(i).update(s).digest("hex")}static computeShortHash(n){return N.computeFileHash(n).slice(0,8)}static getContentType(n){let i=ma(n).toLowerCase();return N.ContentTypes[i]||"application/octet-stream"}static shouldHashFile(n,i){return![...N.NoHashPatterns,...i||[]].some((s)=>s.test(n))}static generateHashedFilename(n,i){let s=ma(n),o=Lr(n,s),c=da(n);if(c===".")return`${o}.${i}${s}`;return Qe(c,`${o}.${i}${s}`)}static collectFiles(n,i){let s=[],o=i||n;if(!Nt(n))return s;let c=kr(n,{withFileTypes:!0});for(let l of c){let u=Qe(n,l.name);if(l.isDirectory())s.push(...N.collectFiles(u,o));else if(l.isFile())s.push(u)}return s}static hashDirectory(n){let{sourceDir:i,outputDir:s,excludePatterns:o=[],hashAlgorithm:c="md5",copyUnhashed:l=!0}=n,u=N.collectFiles(i),h=[],f={};for(let b of u){let A=b.replace(i,"").replace(/^[/\\]/,""),v=N.shouldHashFile(A,o),w=$r(b),E=v?N.computeFileHash(b,c).slice(0,8):"",P=v?N.generateHashedFilename(A,E):A,R={originalPath:A,hashedPath:P,hash:E,size:w.size,contentType:N.getContentType(b)};if(h.push(R),f[A]=P,s){let D=Qe(s,P),O=da(D);if(!Nt(O)){let{mkdirSync:I}=ir("node:fs");I(O,{recursive:!0})}if(v||l)Dr(b,D)}}let S={version:"1.0",timestamp:new Date().toISOString(),assets:h,hashMap:f};if(s){let b=Qe(s,"asset-manifest.json");ot(b,JSON.stringify(S,null,2))}return S}static getInvalidationPaths(n,i){let s=[];if(!n)return["/*"];let o=n.hashMap,c=i.hashMap;for(let[l,u]of Object.entries(c)){let h=o[l];if(!h||h!==u){if(s.push(`/${l}`),h&&h!==u)s.push(`/${h}`)}}for(let[l,u]of Object.entries(o))if(!c[l])s.push(`/${l}`),s.push(`/${u}`);if(s.length>100)return["/*"];return[...new Set(s)]}static updateHtmlReferences(n){let{htmlDir:i,manifest:s,basePath:o=""}=n,c=N.collectFiles(i).filter((l)=>l.endsWith(".html")||l.endsWith(".htm"));for(let l of c){let u=st(l,"utf-8");for(let[h,f]of Object.entries(s.hashMap)){if(h===f)continue;let S=[new RegExp(`(src|href)=["']${o}/?${N.escapeRegExp(h)}["']`,"g"),new RegExp(`url\\(["']?${o}/?${N.escapeRegExp(h)}["']?\\)`,"g")];for(let b of S)u=u.replace(b,(A)=>A.replace(h,f))}ot(l,u)}}static updateCssReferences(n){let{cssDir:i,manifest:s,basePath:o=""}=n,c=N.collectFiles(i).filter((l)=>l.endsWith(".css"));for(let l of c){let u=st(l,"utf-8");for(let[h,f]of Object.entries(s.hashMap)){if(h===f)continue;let S=new RegExp(`url\\(["']?${o}/?${N.escapeRegExp(h)}["']?\\)`,"g");u=u.replace(S,`url(${o}/${f})`)}ot(l,u)}}static escapeRegExp(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}static generateS3DeploymentManifest(n){let{sourceDir:i,keyPrefix:s="",excludePatterns:o=[],cacheControl:c={hashed:"public, max-age=31536000, immutable",unhashed:"public, max-age=3600",html:"public, max-age=0, must-revalidate"}}=n;return N.hashDirectory({sourceDir:i,excludePatterns:o}).assets.map((l)=>{let u=l.hash!=="",h=l.contentType==="text/html",f=c.unhashed||"public, max-age=3600";if(h)f=c.html||"public, max-age=0, must-revalidate";else if(u)f=c.hashed||"public, max-age=31536000, immutable";return{localPath:Qe(i,l.originalPath),s3Key:s?`${s}/${l.hashedPath}`:l.hashedPath,contentType:l.contentType,cacheControl:f,hash:l.hash}})}static compareManifests(n,i){let s={added:[],removed:[],changed:[],unchanged:[]},o=new Set(Object.keys(n.hashMap)),c=new Set(Object.keys(i.hashMap));for(let l of c)if(!o.has(l))s.added.push(l);for(let l of o)if(!c.has(l))s.removed.push(l);for(let l of c)if(o.has(l))if(n.hashMap[l]!==i.hashMap[l])s.changed.push(l);else s.unchanged.push(l);return s}static loadManifest(n){if(!Nt(n))return null;try{let i=st(n,"utf-8");return JSON.parse(i)}catch{return null}}static saveManifest(n,i){ot(i,JSON.stringify(n,null,2))}}class Ni{static createSecret(n){let{slug:i,environment:s,secretName:o,description:c,secretString:l,kmsKeyId:u,tags:h}=n,f=o||r({slug:i,environment:s,resourceType:"secret"}),S=t(f),b={Type:"AWS::SecretsManager::Secret",Properties:{Name:f,Description:c,SecretString:l,Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s},...h?Object.entries(h).map(([A,v])=>({Key:A,Value:v})):[]]}};if(u)b.Properties.KmsKeyId=u;return{secret:b,logicalId:S}}static createGeneratedSecret(n){let{slug:i,environment:s,secretName:o,description:c,excludeCharacters:l,excludeLowercase:u,excludeNumbers:h,excludePunctuation:f,excludeUppercase:S,passwordLength:b,requireEachIncludedType:A,kmsKeyId:v,tags:w}=n,E=o||r({slug:i,environment:s,resourceType:"secret"}),P=t(E),R={Type:"AWS::SecretsManager::Secret",Properties:{Name:E,Description:c,GenerateSecretString:{ExcludeCharacters:l,ExcludeLowercase:u,ExcludeNumbers:h,ExcludePunctuation:f,ExcludeUppercase:S,PasswordLength:b||32,RequireEachIncludedType:A!==!1},Tags:[{Key:"Name",Value:E},{Key:"Environment",Value:s},...w?Object.entries(w).map(([D,O])=>({Key:D,Value:O})):[]]}};if(v)R.Properties.KmsKeyId=v;return{secret:R,logicalId:P}}static createDatabaseSecret(n){let{slug:i,environment:s,secretName:o,username:c,dbname:l,engine:u,host:h,port:f,kmsKeyId:S}=n,b=o||r({slug:i,environment:s,resourceType:"db-secret"}),A=t(b),v={username:c};if(l)v.dbname=l;if(u)v.engine=u;if(h)v.host=h;if(f)v.port=f;let w={Type:"AWS::SecretsManager::Secret",Properties:{Name:b,Description:`Database credentials for ${c}`,GenerateSecretString:{SecretStringTemplate:JSON.stringify(v),GenerateStringKey:"password",PasswordLength:32,ExcludeCharacters:'"@/\\',RequireEachIncludedType:!0},Tags:[{Key:"Name",Value:b},{Key:"Environment",Value:s},{Key:"Type",Value:"database"}]}};if(S)w.Properties.KmsKeyId=S;return{secret:w,logicalId:A}}static attachToDatabase(n){let{slug:i,environment:s,secretId:o,targetId:c,targetType:l}=n,u=r({slug:i,environment:s,resourceType:"secret-attachment"}),h=t(u);return{attachment:{Type:"AWS::SecretsManager::SecretTargetAttachment",Properties:{SecretId:o,TargetId:c,TargetType:l}},logicalId:h}}static enableRotation(n){let{slug:i,environment:s,secretId:o,rotationLambdaArn:c,automaticallyAfterDays:l,rotationType:u,kmsKeyArn:h,vpcSecurityGroupIds:f,vpcSubnetIds:S}=n,b=r({slug:i,environment:s,resourceType:"secret-rotation"}),A=t(b),v={Type:"AWS::SecretsManager::RotationSchedule",Properties:{SecretId:o,RotationRules:{AutomaticallyAfterDays:l||30}}};if(c)v.Properties.RotationLambdaARN=c;else if(u)v.Properties.HostedRotationLambda={RotationType:u,KmsKeyArn:h,VpcSecurityGroupIds:f,VpcSubnetIds:S};return{rotation:v,logicalId:A}}static SecretTypes={apiKey:(n,i,s)=>Ni.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-${s}-api-key`,description:`API key for ${s}`,passwordLength:32,excludePunctuation:!0,excludeLowercase:!1,excludeUppercase:!1,excludeNumbers:!1}),oauthClientSecret:(n,i,s)=>Ni.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-${s}-oauth-secret`,description:`OAuth client secret for ${s}`,passwordLength:64,excludeCharacters:"\"'`\\/@",requireEachIncludedType:!0}),jwtSecret:(n,i)=>Ni.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-jwt-secret`,description:"JWT signing secret",passwordLength:64,excludePunctuation:!0}),encryptionKey:(n,i)=>Ni.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-encryption-key`,description:"Data encryption key",passwordLength:64,excludeCharacters:"+/=",excludePunctuation:!0})};static RotationTypes={MySQLSingleUser:"MySQLSingleUser",MySQLMultiUser:"MySQLMultiUser",PostgreSQLSingleUser:"PostgreSQLSingleUser",PostgreSQLMultiUser:"PostgreSQLMultiUser",OracleSingleUser:"OracleSingleUser",OracleMultiUser:"OracleMultiUser",MariaDBSingleUser:"MariaDBSingleUser",MariaDBMultiUser:"MariaDBMultiUser",SQLServerSingleUser:"SQLServerSingleUser",SQLServerMultiUser:"SQLServerMultiUser",RedshiftSingleUser:"RedshiftSingleUser",RedshiftMultiUser:"RedshiftMultiUser",MongoDBSingleUser:"MongoDBSingleUser",MongoDBMultiUser:"MongoDBMultiUser"}}class T{static createParameter(n){let{slug:i,environment:s,parameterName:o,value:c,type:l="String",description:u,tier:h="Standard",tags:f}=n,S=o||r({slug:i,environment:s,resourceType:"parameter"}),b=t(S);return{parameter:{Type:"AWS::SSM::Parameter",Properties:{Name:`/${i}/${s}/${S}`,Type:l,Value:c,Description:u,Tier:h,Tags:{Name:S,Environment:s,...f}}},logicalId:b}}static createString(n,i,s,o,c){return T.createParameter({slug:n,environment:i,parameterName:s,value:o,type:"String",description:c})}static createSecureString(n,i,s,o,c){return T.createParameter({slug:n,environment:i,parameterName:s,value:o,type:"SecureString",description:c})}static createStringList(n,i,s,o,c){return T.createParameter({slug:n,environment:i,parameterName:s,value:o.join(","),type:"StringList",description:c})}static Parameters={databaseUrl:(n,i,s)=>T.createSecureString(n,i,"database-url",s,"Database connection URL"),apiEndpoint:(n,i,s)=>T.createString(n,i,"api-endpoint",s,"API endpoint URL"),appVersion:(n,i,s)=>T.createString(n,i,"app-version",s,"Application version"),featureFlags:(n,i,s)=>T.createStringList(n,i,"feature-flags",s,"Enabled feature flags"),apiKey:(n,i,s,o)=>T.createSecureString(n,i,`${s}-api-key`,o,`API key for ${s}`),oauthCredentials:(n,i,s,o)=>{let c=T.createString(n,i,"oauth-client-id",s,"OAuth client ID"),l=T.createSecureString(n,i,"oauth-client-secret",o,"OAuth client secret");return{clientId:c,clientSecret:l}},smtpCredentials:(n,i,s,o,c,l)=>{let u=T.createString(n,i,"smtp-username",s,"SMTP username"),h=T.createSecureString(n,i,"smtp-password",o,"SMTP password"),f=T.createString(n,i,"smtp-host",c,"SMTP host"),S=T.createString(n,i,"smtp-port",l.toString(),"SMTP port");return{username:u,password:h,host:f,port:S}},redisUrl:(n,i,s)=>T.createSecureString(n,i,"redis-url",s,"Redis connection URL"),s3Bucket:(n,i,s)=>T.createString(n,i,"s3-bucket",s,"S3 bucket name"),cloudFrontDistribution:(n,i,s)=>T.createString(n,i,"cloudfront-distribution-id",s,"CloudFront distribution ID")}}class Kt{static createDomain(n){let{slug:i,environment:s,domainName:o,engineVersion:c="OpenSearch_2.11",instanceType:l="t3.small.search",instanceCount:u=1,volumeSize:h=10,volumeType:f="gp3",dedicatedMaster:S=!1,dedicatedMasterType:b,dedicatedMasterCount:A=3,multiAz:v=!1,availabilityZoneCount:w=2,vpc:E,encryption:P,enforceHttps:R=!0,tlsSecurityPolicy:D="Policy-Min-TLS-1-2-2019-07",advancedSecurity:O,autoSnapshotHour:I=0,autoTune:_=!0,tags:B={}}=n,W=o||r({slug:i,environment:s,resourceType:"search"}),J=t(W);return{domain:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:W,EngineVersion:c,ClusterConfig:{InstanceType:l,InstanceCount:u,DedicatedMasterEnabled:S,...S&&{DedicatedMasterType:b||l,DedicatedMasterCount:A},ZoneAwarenessEnabled:v,...v&&{ZoneAwarenessConfig:{AvailabilityZoneCount:w}}},EBSOptions:{EBSEnabled:!0,VolumeType:f,VolumeSize:h},DomainEndpointOptions:{EnforceHTTPS:R,TLSSecurityPolicy:D},SnapshotOptions:{AutomatedSnapshotStartHour:I},...E&&{VPCOptions:{SubnetIds:E.subnetIds,SecurityGroupIds:E.securityGroupIds}},...P&&{EncryptionAtRestOptions:{Enabled:P.atRest??!0,...P.kmsKeyId&&{KmsKeyId:P.kmsKeyId}},NodeToNodeEncryptionOptions:{Enabled:P.nodeToNode??!0}},...O&&{AdvancedSecurityOptions:{Enabled:O.enabled,InternalUserDatabaseEnabled:O.internalUserDatabase??!0,...O.masterUserName&&O.masterUserPassword&&{MasterUserOptions:{MasterUserName:O.masterUserName,MasterUserPassword:O.masterUserPassword}},...O.masterUserArn&&{MasterUserOptions:{MasterUserARN:O.masterUserArn}}}},..._&&{AutoTuneOptions:{DesiredState:"ENABLED"}},Tags:[{Key:"Name",Value:W},{Key:"Environment",Value:s},...Object.entries(B).map(([K,Y])=>({Key:K,Value:Y}))]}},logicalId:J}}static createAccessPolicy(n,i){let{ipAddresses:s,iamPrincipalArns:o,allowAll:c,vpcEndpoint:l}=i;if(c)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:n}]};let u=[];if(o&&o.length>0)u.push({Effect:"Allow",Principal:{AWS:o},Action:"es:*",Resource:n});if(s&&s.length>0)u.push({Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:n,Condition:{IpAddress:{"aws:SourceIp":s}}});if(l)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:n}]};return{Version:"2012-10-17",Statement:u}}static DomainPresets={development:(n,i)=>Kt.createDomain({slug:n,environment:i,instanceType:"t3.small.search",instanceCount:1,volumeSize:10,multiAz:!1,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!1}),production:(n,i,s)=>Kt.createDomain({slug:n,environment:i,instanceType:"m6g.large.search",instanceCount:3,volumeSize:100,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"m6g.large.search",dedicatedMasterCount:3,vpc:s,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!0},autoTune:!0}),costOptimized:(n,i)=>Kt.createDomain({slug:n,environment:i,instanceType:"t3.medium.search",instanceCount:2,volumeSize:20,volumeType:"gp3",multiAz:!0,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!0}),highPerformance:(n,i,s)=>Kt.createDomain({slug:n,environment:i,instanceType:"r6g.2xlarge.search",instanceCount:6,volumeSize:500,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"c6g.xlarge.search",dedicatedMasterCount:3,vpc:s,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!1},autoTune:!0})};static InstanceTypes={"t3.small.search":"t3.small.search","t3.medium.search":"t3.medium.search","m6g.large.search":"m6g.large.search","m6g.xlarge.search":"m6g.xlarge.search","m6g.2xlarge.search":"m6g.2xlarge.search","r6g.large.search":"r6g.large.search","r6g.xlarge.search":"r6g.xlarge.search","r6g.2xlarge.search":"r6g.2xlarge.search","r6g.4xlarge.search":"r6g.4xlarge.search","c6g.large.search":"c6g.large.search","c6g.xlarge.search":"c6g.xlarge.search","c6g.2xlarge.search":"c6g.2xlarge.search"};static EngineVersions={"OpenSearch_2.11":"OpenSearch_2.11","OpenSearch_2.9":"OpenSearch_2.9","OpenSearch_2.7":"OpenSearch_2.7","OpenSearch_1.3":"OpenSearch_1.3","Elasticsearch_7.10":"Elasticsearch_7.10"}}class yt{static createDomainRedirectBucket(n){let{slug:i,environment:s,sourceDomain:o,targetDomain:c,protocol:l="https"}=n,u=r({slug:i,environment:s,resourceType:"s3",suffix:"redirect"}),h=t(u),f=t(`${u}-policy`),S={Type:"AWS::S3::Bucket",Properties:{BucketName:o,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:c,Protocol:l}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1},Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:s},{Key:"Purpose",Value:"Domain Redirect"}]}},b={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:k.Ref(h),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[k.Join("",[k.GetAtt(h,"Arn"),"/*"])]}]}}};return{bucket:S,bucketPolicy:b,logicalId:h,policyLogicalId:f}}static createPathRedirectFunction(n){let{slug:i,environment:s,rules:o}=n,c=r({slug:i,environment:s,resourceType:"cf-redirect"}),l=t(c),u=yt.generateRedirectFunctionCode(o);return{function:{Type:"AWS::CloudFront::Function",Properties:{Name:c,AutoPublish:!0,FunctionConfig:{Comment:`Path redirect function for ${i} (${s})`,Runtime:"cloudfront-js-2.0"},FunctionCode:u}},logicalId:l,functionCode:u}}static generateRedirectFunctionCode(n){return`function handler(event) {
|
|
2317
2317
|
const request = event.request;
|
|
2318
2318
|
const uri = request.uri;
|
|
2319
2319
|
const querystring = request.querystring;
|
|
@@ -2492,7 +2492,7 @@ rpm -U ./amazon-cloudwatch-agent.rpm || true
|
|
|
2492
2492
|
# Mount EFS for shared file storage
|
|
2493
2493
|
`}},storage:{uploads:{type:"efs",performanceMode:"generalPurpose",throughputMode:"bursting",encrypted:!0,lifecyclePolicy:{transitionToIA:30}},backups:{public:!1,versioning:!0,encryption:!0,lifecycleRules:[{id:"ArchiveOldBackups",enabled:!0,transitions:[{days:90,storageClass:"GLACIER"}]}]},static:{public:!0,versioning:!1,encryption:!1,cors:[{allowedOrigins:[o||"*"],allowedMethods:["GET","HEAD"]}]}},cdn:{enabled:!0,origins:[{originId:"static-assets",domainName:`${s}-static.s3.amazonaws.com`,pathPattern:"/static/*"}],customDomain:o?{domain:o,certificateArn:"TO_BE_GENERATED"}:void 0,cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0},databases:h==="mysql"?{mysql:{engine:"mysql",version:"8.0",instanceClass:"db.t3.medium",allocatedStorage:100,maxAllocatedStorage:500,multiAZ:!0,backupRetentionDays:14,preferredBackupWindow:"03:00-04:00",preferredMaintenanceWindow:"sun:04:00-sun:05:00",enablePerformanceInsights:!0,performanceInsightsRetention:7,deletionProtection:!0,parameters:{max_connections:"500",innodb_buffer_pool_size:"{DBInstanceClassMemory*3/4}",slow_query_log:"1",long_query_time:"2"}}}:{postgres:{engine:"postgres",version:"15",instanceClass:"db.t3.medium",allocatedStorage:100,maxAllocatedStorage:500,multiAZ:!0,backupRetentionDays:14,preferredBackupWindow:"03:00-04:00",preferredMaintenanceWindow:"sun:04:00-sun:05:00",enablePerformanceInsights:!0,performanceInsightsRetention:7,deletionProtection:!0,parameters:{max_connections:"500",shared_buffers:"{DBInstanceClassMemory/4}",log_min_duration_statement:"2000"}}},cache:f==="redis"?{redis:{nodeType:"cache.t3.medium",numCacheNodes:2,engine:"redis",engineVersion:"7.0",port:6379,parameterGroup:{maxmemoryPolicy:"allkeys-lru",timeout:"300"},snapshotRetentionLimit:5,snapshotWindow:"03:00-05:00",automaticFailoverEnabled:!0}}:void 0,queues:{jobs:{fifo:!1,visibilityTimeout:900,messageRetentionPeriod:345600,receiveMessageWaitTime:20,deadLetterQueue:!0,maxReceiveCount:3},emails:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:86400,deadLetterQueue:!0}},functions:{"job-worker":{runtime:"nodejs20.x",handler:"dist/workers/jobs.handler",memory:2048,timeout:900,events:[{type:"sqs",queueName:`${s}-jobs`,batchSize:10}]},"email-sender":{runtime:"nodejs20.x",handler:"dist/workers/email.handler",memory:512,timeout:60,events:[{type:"sqs",queueName:`${s}-emails`,batchSize:10}]},cleanup:{runtime:"nodejs20.x",handler:"dist/tasks/cleanup.handler",memory:512,timeout:300,events:[{type:"schedule",expression:"cron(0 2 * * ? *)"}]}},monitoring:{dashboard:{name:`${s}-web-app`,widgets:[{type:"metric",metrics:["EC2CPUUtilization","ALBRequestCount","ALBTargetResponseTime","RDSCPUUtilization","RDSDatabaseConnections","RDSReadLatency","RDSWriteLatency"]}]},alarms:[{metric:"EC2CPUUtilization",threshold:80,evaluationPeriods:2},{metric:"RDSCPUUtilization",threshold:80,evaluationPeriods:2},{metric:"RDSDatabaseConnections",threshold:400,evaluationPeriods:1},{metric:"ALBTargetResponseTime",threshold:2000,evaluationPeriods:2},{metric:"ALBUnhealthyHostCount",threshold:1,evaluationPeriods:1}],logs:{retention:14,groups:[`${s}-app`,`${s}-nginx`,`${s}-workers`]}},security:{certificate:o?{domain:o,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss","knownBadInputs"]},securityGroups:{alb:{ingress:[{port:80,protocol:"tcp",cidr:"0.0.0.0/0"},{port:443,protocol:"tcp",cidr:"0.0.0.0/0"}]},app:{ingress:[{port:3000,protocol:"tcp",source:"alb-sg"}]},database:{ingress:[{port:h==="mysql"?3306:5432,protocol:"tcp",source:"app-sg"}]},...f==="redis"&&{cache:{ingress:[{port:6379,protocol:"tcp",source:"app-sg"}]}}}}}}}function ZI(n){let{name:i,slug:s,domain:o,repository:c,phpVersion:l="8.3",size:u="small",database:h=s.replace(/-/g,"_"),databasePassword:f,sslEmail:S,deployStrategy:b="push",provider:A="hetzner"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",cloud:{provider:A},environments:{production:{type:"production",domain:o}},infrastructure:{compute:{mode:"server",size:u,runtime:"php",webServer:"nginx",php:{versions:[l],default:l},managedServices:{mysql:!0,redis:!0},firewall:{enabled:!0},autoUpdates:!0,monitoring:!0,backups:{enabled:!0,schedule:"0 2 * * *",retentionCount:7}},appDatabase:{engine:"mysql",name:h,username:h,password:f}},sites:{main:{root:".",type:"laravel",domain:o,phpVersion:l,repository:{...c,strategy:b},scheduler:!0,queues:[{connection:"redis",queue:"default",processes:1}],ssl:{provider:"letsencrypt",email:S}}}}}function eS(n){let{name:i,slug:s,domain:o,layers:c,phpVersion:l="8.3",architecture:u="x86_64",memory:h=1024,build:f,deploy:S=["migrate --force"],cache:b="dynamodb",scheduler:A="on",region:v="us-east-1"}=n;return{project:{name:i,slug:s,region:v},mode:"serverless",environments:{production:{type:"production",domain:o,app:{kind:"php",runtime:"provided.al2023",phpVersion:l,architecture:u,layers:c,memory:h,build:f,deploy:S,assets:"public",queues:!0,scheduler:A,cache:{driver:b},domain:o}}}}}function tS(n){return{root:n.root??"packages/ui/dist",deploy:"server",type:"static",domain:n.domain,build:n.build??"cd packages/ui && bun install && bun run build",ssl:{provider:"letsencrypt"},auth:{username:n.username??"admin",password:n.password}}}var gA=pg,mA="./node_modules/@stacksjs/ts-cloud/dist/bin/dashboard-server.js";function En(n){let i=n.split(".").filter(Boolean);return i.length<=2?n:i.slice(-2).join(".")}function Pn(n){let i=2166136261;for(let s=0;s<n.length;s++)i^=n.charCodeAt(s),i=Math.imul(i,16777619);return i>>>0}var hA=20000,fA=12000;function AA(n){return hA+Pn(n)%fA}function $a(n,i){let s=En(n);if(s===n)return`dashboard.${s}`;for(let o of i)if(o===s)return`dashboard.${s}`;return`dashboard.${n}`}function La(n,i){let s=[],o=n.infrastructure?.dns?.domain;if(o&&!n.cloud?.attachTo)s.push(o);if(i&&n.environments?.[i]?.domain)s.push(n.environments[i].domain);for(let c of Object.values(n.sites??{})){let l=c;if(!l||l.redirect)continue;let u=l.domain;if(typeof u==="string")s.push(u);else if(Array.isArray(u))s.push(...u.filter((h)=>typeof h==="string"))}return s.filter((c)=>c&&!c.startsWith("dashboard."))}function yA(n,i,s){if(s)return s;let o=La(n,i),c=o[0];if(!c)return null;return $a(c,o)}function IA(n,i,s){if(s)return[s];let o=La(n,i),c=[];for(let l of o){let u=$a(l,o);if(!c.includes(u))c.push(u)}return c}function Wt(n){return Object.entries(n.sites??{}).some(([i,s])=>{if(!s)return!1;let o=s.root??"";return Vr(i)||o==="ui/dist"||o.endsWith("/ui/dist")||o.endsWith("/dist/ui")})}var wg="dashboard-";function Rg(n){return wg+n.replace(/^dashboard\./,"").replace(/\./g,"-")}function Vr(n){return n==="dashboard"||n.startsWith(wg)}function ki(n,i,s){if(Wt(n))return[];if(n.cloud?.attachTo)return[];let o=s.password?{auth:{username:s.username||"admin",password:s.password,realm:s.realm}}:{},c=s.build===!1||s.build===void 0?{}:{build:s.build};if(s.live!==!1){let l=yA(n,i,s.domain);if(!l)return[];let u=s.port??AA(l),h=n.infrastructure?.appDatabase??n.infrastructure?.compute?.database,f={root:s.uiRoot,deploy:"server",domain:l,preStart:["bun install --production --no-save"],start:`bun ${mA} --box --host 127.0.0.1 --port ${u}`,port:u,cpuWeight:10,ioWeight:10,tasksMax:128,env:{APP_ENV:"production",NODE_ENV:"production",TS_CLOUD_DASHBOARD_TELEMETRY:"1",...h?.password?{TS_CLOUD_DASHBOARD_DB_PASSWORD:h.password}:{}},zeroDowntime:!1,sharedPaths:[gA],healthCheck:{path:"/login"},ssl:{provider:"letsencrypt"}};return[{name:Rg(l),site:f}]}return IA(n,i,s.domain).map((l)=>({name:Rg(l),site:{root:s.uiRoot,deploy:"server",type:"static",domain:l,ssl:{provider:"letsencrypt"},...c,...o}}))}function rS(n,i,s){return ki(n,i,s)[0]??null}function Ut(n,i){let s={...n};for(let o in i){let c=i[o],l=s[o];if(c===void 0)continue;if(Array.isArray(c)&&Array.isArray(l))s[o]=[...l,...c];else if(typeof c==="object"&&c!==null&&!Array.isArray(c)&&typeof l==="object"&&l!==null&&!Array.isArray(l))s[o]=Ut(l,c);else s[o]=c}return s}function Dg(n,i){return Ut(n,i)}function nS(...n){return n.reduce((i,s)=>Ut(i,s),{})}function iS(n,i){return(s)=>{let o=n(s);if(typeof i==="function")return Dg(o,i(o,s));return Dg(o,i)}}function jr(n){return{infrastructure:n}}function sS(n){return jr({monitoring:n})}function oS(n){return jr({security:n})}function aS(n){return jr({databases:n})}function cS(n){return jr({cache:n})}function dS(n){return jr({cdn:n})}function lS(n){return jr({queues:n})}rt();function SA(){let n=process.env.AWS_ACCESS_KEY_ID,i=process.env.AWS_SECRET_ACCESS_KEY;if(!n||!i)return null;return{accessKeyId:n,secretAccessKey:i,sessionToken:process.env.AWS_SESSION_TOKEN}}function CA(n){let i=n?.profile||process.env.AWS_PROFILE||"default",s=n?.credentialsFile||xa(Oa(),".aws","credentials");if(!Ma(s))return null;try{let o=Ht(s,"utf-8");return In(o,i)}catch{return null}}function In(n,i){let s=n.split(`
|
|
2494
2494
|
`),o=null,c,l,u;for(let h of s){let f=h.trim();if(!f||f.startsWith("#")||f.startsWith(";"))continue;let S=f.match(/^\[([^\]]+)\]$/);if(S){if(o===i&&c&&l)return{accessKeyId:c,secretAccessKey:l,sessionToken:u};o=S[1],c=void 0,l=void 0,u=void 0;continue}if(o===i){let[b,...A]=f.split("="),v=A.join("=").trim();switch(b.trim().toLowerCase()){case"aws_access_key_id":c=v;break;case"aws_secret_access_key":l=v;break;case"aws_session_token":u=v;break}}}if(o===i&&c&&l)return{accessKeyId:c,secretAccessKey:l,sessionToken:u};return null}async function EA(n){let i=n?.timeout??1000,s="http://169.254.169.254";try{let o=await et("http://169.254.169.254/latest/api/token",{method:"PUT",headers:{"X-aws-ec2-metadata-token-ttl-seconds":"21600"}},i);if(!o.ok)return null;let c=await o.text(),l=await et("http://169.254.169.254/latest/meta-data/iam/security-credentials/",{headers:{"X-aws-ec2-metadata-token":c}},i);if(!l.ok)return null;let u=(await l.text()).trim(),h=await et(`http://169.254.169.254/latest/meta-data/iam/security-credentials/${u}`,{headers:{"X-aws-ec2-metadata-token":c}},i);if(!h.ok)return null;let f=await h.json();return{accessKeyId:f.AccessKeyId,secretAccessKey:f.SecretAccessKey,sessionToken:f.Token,expiration:new Date(f.Expiration)}}catch{return null}}async function bA(n){let i=n?.timeout??1000,s=process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI,o=process.env.AWS_CONTAINER_CREDENTIALS_FULL_URI,c=null;if(s)c=`http://169.254.170.2${s}`;else if(o)c=o;if(!c)return null;try{let l={},u=process.env.AWS_CONTAINER_AUTHORIZATION_TOKEN;if(u)l.Authorization=u;let h=await et(c,{headers:l},i);if(!h.ok)return null;let f=await h.json();return{accessKeyId:f.AccessKeyId,secretAccessKey:f.SecretAccessKey,sessionToken:f.Token,expiration:new Date(f.Expiration)}}catch{return null}}async function vA(n){let i=n?.timeout??5000,s=process.env.AWS_WEB_IDENTITY_TOKEN_FILE,o=process.env.AWS_ROLE_ARN,c=process.env.AWS_ROLE_SESSION_NAME||"ts-cloud-session";if(!s||!o)return null;try{let l=Ht(s,"utf-8").trim(),u=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION||"us-east-1",h=u.startsWith("us-gov")?`https://sts.${u}.amazonaws.com`:u==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${u}.amazonaws.com`,f=new URLSearchParams({Action:"AssumeRoleWithWebIdentity",Version:"2011-06-15",RoleArn:o,RoleSessionName:c,WebIdentityToken:l}),S=await et(`${h}/?${f.toString()}`,{method:"POST"},i);if(!S.ok)return null;let b=await S.text(),A=Ze(b,"AccessKeyId"),v=Ze(b,"SecretAccessKey"),w=Ze(b,"SessionToken"),E=Ze(b,"Expiration");if(!A||!v)return null;return{accessKeyId:A,secretAccessKey:v,sessionToken:w??void 0,expiration:E?new Date(E):void 0}}catch{return null}}async function Ao(n){let i=SA();if(i)return i;let s=CA(n);if(s)return s;let o=await vA(n);if(o)return o;let c=await bA(n);if(c)return c;let l=await EA(n);if(l)return l;throw Error("Could not find AWS credentials. Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables, or configure ~/.aws/credentials, or run on an EC2 instance with an IAM role.")}function uS(n){let i=null,s=null;return async()=>{if(i){if(!i.expiration)return i;let o=300000;if(i.expiration.getTime()-Date.now()>o)return i}if(s)return s;return s=Ao(n).then((o)=>(i=o,s=null,o)).catch((o)=>{throw s=null,o}),s}}async function et(n,i,s){let o=new AbortController,c=setTimeout(()=>o.abort(),s);try{let l=await fetch(n,{...i,signal:o.signal});return clearTimeout(c),l}catch(l){throw clearTimeout(c),l}}function Ze(n,i){let s=new RegExp(`<${i}>([^<]+)</${i}>`),o=n.match(s);return o?o[1]:null}async function TA(n){return Ao({profile:n})}function wA(n){let i=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION;if(i)return i;let s=xa(Oa(),".aws","config");if(Ma(s))try{let o=Ht(s,"utf-8"),c=n||process.env.AWS_PROFILE||"default",l=c==="default"?"[default]":`[profile ${c}]`,u=o.split(`
|
|
2495
|
-
`),h=!1;for(let f of u){let S=f.trim();if(S.startsWith("[")){h=S===l;continue}if(h&&S.startsWith("region")){let[,b]=S.split("=");if(b)return b.trim()}}}catch{}return"us-east-1"}async function RA(n){let i=n||await Ao(),s=wA();await rt();let o=s.startsWith("us-gov")?`https://sts.${s}.amazonaws.com`:s==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${s}.amazonaws.com`,c="Action=GetCallerIdentity&Version=2011-06-15",l=O({method:"POST",url:o,body:"Action=GetCallerIdentity&Version=2011-06-15",headers:{"Content-Type":"application/x-www-form-urlencoded"},...i,service:"sts",region:s}),u=await fetch(l.url,{method:l.method,headers:l.headers,body:l.body});if(!u.ok)throw Error(`Failed to get account ID: ${await u.text()}`);let h=await u.text(),f=Ze(h,"Account");if(!f)throw Error("Failed to parse account ID from response");return f}await rt();await rt();var Rn=5242880,Dt=5242880,Nn=5242880;class Ba{region;endpoint;forcePathStyle;credentials;credentialOptions;retryOptions;constructor(n={}){this.region=n.region||process.env.AWS_REGION||"us-east-1",this.endpoint=n.endpoint||`https://s3.${this.region}.amazonaws.com`,this.forcePathStyle=n.forcePathStyle||!1,this.credentials=n.credentials,this.credentialOptions=n.credentialOptions,this.retryOptions=n.retryOptions||{}}async getCredentials(){if(this.credentials)return this.credentials;return Ao(this.credentialOptions)}buildUrl(n,i){let s=i?encodeURIComponent(i).replace(/%2F/g,"/"):"";if(this.forcePathStyle)return i?`${this.endpoint}/${n}/${s}`:`${this.endpoint}/${n}`;let o=new URL(this.endpoint);return o.hostname=`${n}.${o.hostname}`,i?`${o.origin}/${s}`:o.origin}async get(n,i,s={}){let o=await this.getCredentials(),c=this.buildUrl(n,i),l={};if(s.range)l.Range=s.range;if(s.ifModifiedSince)l["If-Modified-Since"]=s.ifModifiedSince.toUTCString();if(s.ifMatch)l["If-Match"]=s.ifMatch;if(s.ifNoneMatch)l["If-None-Match"]=s.ifNoneMatch;let u=new URL(c);if(s.responseContentType)u.searchParams.set("response-content-type",s.responseContentType);if(s.responseContentDisposition)u.searchParams.set("response-content-disposition",s.responseContentDisposition);let h=O({method:"GET",url:u.toString(),headers:l,...o,service:"s3",region:this.region}),f=await fetch(h.url,{method:h.method,headers:h.headers});if(!f.ok&&f.status!==304){let S=await f.text();throw new V(`Failed to get object: ${S}`,f.status,n,i)}return f}async getText(n,i,s={}){return(await this.get(n,i,s)).text()}async getJSON(n,i,s={}){return(await this.get(n,i,s)).json()}async getBuffer(n,i,s={}){return(await this.get(n,i,s)).arrayBuffer()}async put(n,i,s,o={}){let c,l;if(typeof s==="string")c=new TextEncoder().encode(s).length,l=s;else if(s instanceof ArrayBuffer)c=s.byteLength,l=s;else if(s instanceof Uint8Array)c=s.byteLength,l=s;else if(s instanceof Blob)c=s.size,l=s;else return this.uploadMultipart(n,i,s,{...o,partSize:Dt});if(c>Nn){let u=$n(l).stream();return this.uploadMultipart(n,i,u,{...o,partSize:Dt})}return this.putSimple(n,i,l,c,o)}async putSimple(n,i,s,o,c){let l=await this.getCredentials(),u=this.buildUrl(n,i),h={"Content-Length":String(o),"Content-Type":c.contentType||ha(i)};if(c.contentEncoding)h["Content-Encoding"]=c.contentEncoding;if(c.cacheControl)h["Cache-Control"]=c.cacheControl;if(c.contentDisposition)h["Content-Disposition"]=c.contentDisposition;if(c.storageClass)h["x-amz-storage-class"]=c.storageClass;if(c.serverSideEncryption)h["x-amz-server-side-encryption"]=c.serverSideEncryption;if(c.acl)h["x-amz-acl"]=c.acl;if(c.tagging)h["x-amz-tagging"]=c.tagging;if(c.metadata)for(let[A,v]of Object.entries(c.metadata))h[`x-amz-meta-${A.toLowerCase()}`]=v;let f;if(typeof s==="string")f=s;else if(s instanceof Blob)f=await s.text();else f=new TextDecoder().decode(s instanceof ArrayBuffer?new Uint8Array(s):s);let S=O({method:"PUT",url:u,headers:h,body:f,...l,service:"s3",region:this.region}),b=await fetch(S.url,{method:S.method,headers:S.headers,body:s});if(!b.ok){let A=await b.text();throw new V(`Failed to put object: ${A}`,b.status,n,i)}return{etag:(b.headers.get("ETag")||"").replace(/"/g,"")}}async delete(n,i){let s=await this.getCredentials(),o=this.buildUrl(n,i),c=O({method:"DELETE",url:o,...s,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(!l.ok&&l.status!==204){let u=await l.text();throw new V(`Failed to delete object: ${u}`,l.status,n,i)}}async deleteMany(n,i){let s=await this.getCredentials(),o=`${this.buildUrl(n)}?delete`,c=`<?xml version="1.0" encoding="UTF-8"?><Delete><Quiet>false</Quiet>${i.map((w)=>`<Object><Key>${kn(w)}</Key></Object>`).join("")}</Delete>`,l=O({method:"POST",url:o,headers:{"Content-Type":"application/xml"},body:c,...s,service:"s3",region:this.region}),u=await fetch(l.url,{method:l.method,headers:l.headers,body:c});if(!u.ok){let w=await u.text();throw new V(`Failed to delete objects: ${w}`,u.status,n)}let h=await u.text(),f=[],S=[],b=/<Deleted><Key>([^<]+)<\/Key>/g,A;while((A=b.exec(h))!==null)f.push(A[1]);let v=/<Error><Key>([^<]+)<\/Key><Code>([^<]+)<\/Code><Message>([^<]+)<\/Message>/g;while((A=v.exec(h))!==null)S.push({key:A[1],error:`${A[2]}: ${A[3]}`});return{deleted:f,errors:S}}async list(n,i={}){let s=await this.getCredentials(),o=new URL(this.buildUrl(n));if(o.searchParams.set("list-type","2"),i.prefix)o.searchParams.set("prefix",i.prefix);if(i.delimiter)o.searchParams.set("delimiter",i.delimiter);if(i.maxKeys)o.searchParams.set("max-keys",String(i.maxKeys));if(i.continuationToken)o.searchParams.set("continuation-token",i.continuationToken);if(i.startAfter)o.searchParams.set("start-after",i.startAfter);let c=O({method:"GET",url:o.toString(),...s,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(!l.ok){let h=await l.text();throw new V(`Failed to list objects: ${h}`,l.status,n)}let u=await l.text();return Dn(u)}async*listAll(n,i={}){let s;do{let o=await this.list(n,{...i,continuationToken:s});for(let c of o.contents)yield c;s=o.nextContinuationToken}while(s)}async head(n,i){let s=await this.getCredentials(),o=this.buildUrl(n,i),c=O({method:"HEAD",url:o,...s,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(l.status===404)return null;if(!l.ok){let h=await l.text();throw new V(`Failed to head object: ${h}`,l.status,n,i)}let u={};return l.headers.forEach((h,f)=>{if(f.toLowerCase().startsWith("x-amz-meta-"))u[f.slice(11)]=h}),{contentLength:Number(l.headers.get("Content-Length")||0),contentType:l.headers.get("Content-Type")||"application/octet-stream",etag:(l.headers.get("ETag")||"").replace(/"/g,""),lastModified:new Date(l.headers.get("Last-Modified")||0),metadata:u,storageClass:l.headers.get("x-amz-storage-class")||void 0,serverSideEncryption:l.headers.get("x-amz-server-side-encryption")||void 0}}async exists(n,i){return await this.head(n,i)!==null}async copy(n,i,s,o,c={}){let l=await this.getCredentials(),u=this.buildUrl(s,o),h={"x-amz-copy-source":`/${n}/${encodeURIComponent(i)}`};if(c.metadataDirective)h["x-amz-metadata-directive"]=c.metadataDirective;if(c.contentType)h["Content-Type"]=c.contentType;if(c.storageClass)h["x-amz-storage-class"]=c.storageClass;if(c.acl)h["x-amz-acl"]=c.acl;if(c.metadata)for(let[A,v]of Object.entries(c.metadata))h[`x-amz-meta-${A.toLowerCase()}`]=v;let f=O({method:"PUT",url:u,headers:h,...l,service:"s3",region:this.region}),S=await fetch(f.url,{method:f.method,headers:f.headers});if(!S.ok){let A=await S.text();throw new V(`Failed to copy object: ${A}`,S.status,s,o)}let b=(await S.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:b?b[1]:""}}async getPresignedUrl(n,i,s={}){let o=await this.getCredentials(),c=this.buildUrl(n,i);return sA({url:c,method:s.method||"GET",expiresIn:s.expiresIn||3600,...o,service:"s3",region:this.region})}async uploadMultipart(n,i,s,o={}){let c=await this.getCredentials(),l=Math.max(o.partSize||Dt,Rn),u,h;if(s instanceof ReadableStream)u=s;else if(s instanceof Blob)u=s.stream(),h=s.size;else{let b=new Blob([s]);u=b.stream(),h=b.size}let{uploadId:f,baseUrl:S}=await this.initiateMultipartUpload(n,i,o);try{let b=await this.uploadParts(n,i,S,f,u,l,c,h,o.concurrency||4,o.onProgress);return await this.completeMultipartUpload(n,i,S,f,b)}catch(b){throw await this.abortMultipartUpload(n,i,f,S).catch(()=>{}),b}}async initiateMultipartUpload(n,i,s){let o=await this.getCredentials(),c=this.buildUrl(n,i),l=`${c}?uploads`,u={"Content-Type":s.contentType||ha(i)};if(s.storageClass)u["x-amz-storage-class"]=s.storageClass;if(s.serverSideEncryption)u["x-amz-server-side-encryption"]=s.serverSideEncryption;if(s.acl)u["x-amz-acl"]=s.acl;if(s.metadata)for(let[A,v]of Object.entries(s.metadata))u[`x-amz-meta-${A.toLowerCase()}`]=v;let h=O({method:"POST",url:l,headers:u,...o,service:"s3",region:this.region}),f=await fetch(h.url,{method:h.method,headers:h.headers});if(!f.ok){let A=await f.text();throw new V(`Failed to initiate multipart upload: ${A}`,f.status,n,i)}let S=(await f.text()).match(/<UploadId>([^<]+)<\/UploadId>/);if(!S)throw new V("Failed to parse upload ID from response",0,n,i);let b=c;if(f.url)try{let A=new URL(f.url);A.search="",b=A.toString()}catch{}return{uploadId:S[1],baseUrl:b}}async uploadParts(n,i,s,o,c,l,u,h,f,S){let b=[],A=c.getReader(),v=1,w=new Uint8Array(0),E=0,P=h?Math.ceil(h/l):void 0,R=new Map,D=async(I,_)=>{let B=`${s}?partNumber=${_}&uploadId=${encodeURIComponent(o)}`,W={"Content-Length":String(I.byteLength),"x-amz-content-sha256":"UNSIGNED-PAYLOAD"},J=O({method:"PUT",url:B,headers:W,...u,service:"s3",region:this.region}),K=await fetch(J.url,{method:J.method,headers:J.headers,body:I,redirect:"error"});if(!K.ok){let Z=await K.text();throw new V(`Failed to upload part ${_}: ${Z}`,K.status,n,i)}let Y=(K.headers.get("ETag")||"").replace(/"/g,"");if(!Y)throw new V(`Missing ETag for part ${_}`,K.status,n,i);return{partNumber:_,etag:Y}},x=async()=>{let I=await Promise.race(R.values());R.delete(I.partNumber),b.push(I)};while(!0){let{done:I,value:_}=await A.read();if(_){let B=new Uint8Array(w.length+_.length);B.set(w),B.set(_,w.length),w=B}while(w.length>=l||I&&w.length>0){let B=w.slice(0,l);w=w.slice(l);let W=v++;if(R.size>=f)await x();if(R.set(W,D(B,W)),E+=B.byteLength,S)S({loaded:E,total:h||E,part:W,totalParts:P||W})}if(I)break}while(R.size>0)await x();return b.sort((I,_)=>I.partNumber-_.partNumber),b}async completeMultipartUpload(n,i,s,o,c){let l=await this.getCredentials(),u=`${s}?uploadId=${encodeURIComponent(o)}`,h=`<?xml version="1.0" encoding="UTF-8"?><CompleteMultipartUpload>${c.map((A)=>`<Part><PartNumber>${A.partNumber}</PartNumber><ETag>"${A.etag}"</ETag></Part>`).join("")}</CompleteMultipartUpload>`,f=O({method:"POST",url:u,headers:{"Content-Type":"application/xml"},body:h,...l,service:"s3",region:this.region}),S=await fetch(f.url,{method:f.method,headers:f.headers,body:h});if(!S.ok){let A=await S.text();throw new V(`Failed to complete multipart upload: ${A}`,S.status,n,i)}let b=(await S.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:b?b[1]:""}}async abortMultipartUpload(n,i,s,o){let c=await this.getCredentials(),l=`${o??this.buildUrl(n,i)}?uploadId=${encodeURIComponent(s)}`,u=O({method:"DELETE",url:l,...c,service:"s3",region:this.region});await fetch(u.url,{method:u.method,headers:u.headers})}async emptyAndDeleteBucket(n){let i=[];for await(let l of this.listAll(n,{}))if(i.push(l.key),i.length>=1000)await this.deleteMany(n,i),i=[];if(i.length>0)await this.deleteMany(n,i);let s=await this.getCredentials(),o=this.buildUrl(n),c=O({method:"DELETE",url:o,...s,service:"s3",region:this.region});await fetch(c.url,{method:c.method,headers:c.headers})}}class V extends Error{statusCode;bucket;key;constructor(n,i,s,o){super(n);this.statusCode=i,this.bucket=s,this.key=o,this.name="S3Error"}}function Dn(n){let i=[],s=[],o=/<Contents>([\s\S]*?)<\/Contents>/g,c;while((c=o.exec(n))!==null){let u=c[1];i.push({key:ce(u,"Key")||"",lastModified:new Date(ce(u,"LastModified")||0),etag:(ce(u,"ETag")||"").replace(/"/g,""),size:Number(ce(u,"Size")||0),storageClass:ce(u,"StorageClass")||"STANDARD"})}let l=/<CommonPrefixes><Prefix>([^<]+)<\/Prefix><\/CommonPrefixes>/g;while((c=l.exec(n))!==null)s.push(c[1]);return{contents:i,commonPrefixes:s,isTruncated:ce(n,"IsTruncated")==="true",continuationToken:ce(n,"ContinuationToken")||void 0,nextContinuationToken:ce(n,"NextContinuationToken")||void 0,keyCount:Number(ce(n,"KeyCount")||0),maxKeys:Number(ce(n,"MaxKeys")||1000),prefix:ce(n,"Prefix")||void 0,delimiter:ce(n,"Delimiter")||void 0}}function ce(n,i){let s=new RegExp(`<${i}>([^<]*)</${i}>`),o=n.match(s);return o?o[1]:null}function kn(n){return n.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function ha(n){let i=n.split(".").pop()?.toLowerCase();return{html:"text/html",htm:"text/html",css:"text/css",js:"application/javascript",mjs:"application/javascript",json:"application/json",xml:"application/xml",txt:"text/plain",md:"text/markdown",csv:"text/csv",jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",gif:"image/gif",webp:"image/webp",svg:"image/svg+xml",ico:"image/x-icon",avif:"image/avif",mp4:"video/mp4",webm:"video/webm",mov:"video/quicktime",avi:"video/x-msvideo",mp3:"audio/mpeg",wav:"audio/wav",ogg:"audio/ogg",pdf:"application/pdf",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xls:"application/vnd.ms-excel",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",ppt:"application/vnd.ms-powerpoint",pptx:"application/vnd.openxmlformats-officedocument.presentationml.presentation",zip:"application/zip",gz:"application/gzip",tar:"application/x-tar",rar:"application/vnd.rar","7z":"application/x-7z-compressed",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf",otf:"font/otf",eot:"application/vnd.ms-fontobject",wasm:"application/wasm"}[i||""]||"application/octet-stream"}function $n(n){if(n instanceof Blob)return n;if(typeof n==="string")return new Blob([n],{type:"text/plain"});return new Blob([n])}function pS(n){return new Ba(n)}await rt();class Je extends Error{code;solution;details;constructor(n,i,s,o){super(n);this.code=i,this.solution=s,this.details=o,this.name="CloudError",Error.captureStackTrace?.(this,Je)}toString(){let n=`${this.name} [${this.code}]: ${this.message}`;if(this.solution)n+=`
|
|
2495
|
+
`),h=!1;for(let f of u){let S=f.trim();if(S.startsWith("[")){h=S===l;continue}if(h&&S.startsWith("region")){let[,b]=S.split("=");if(b)return b.trim()}}}catch{}return"us-east-1"}async function RA(n){let i=n||await Ao(),s=wA();await rt();let o=s.startsWith("us-gov")?`https://sts.${s}.amazonaws.com`:s==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${s}.amazonaws.com`,c="Action=GetCallerIdentity&Version=2011-06-15",l=x({method:"POST",url:o,body:"Action=GetCallerIdentity&Version=2011-06-15",headers:{"Content-Type":"application/x-www-form-urlencoded"},...i,service:"sts",region:s}),u=await fetch(l.url,{method:l.method,headers:l.headers,body:l.body});if(!u.ok)throw Error(`Failed to get account ID: ${await u.text()}`);let h=await u.text(),f=Ze(h,"Account");if(!f)throw Error("Failed to parse account ID from response");return f}await rt();await rt();var Rn=5242880,Dt=5242880,Nn=5242880;class Ba{region;endpoint;forcePathStyle;credentials;credentialOptions;retryOptions;constructor(n={}){this.region=n.region||process.env.AWS_REGION||"us-east-1",this.endpoint=n.endpoint||`https://s3.${this.region}.amazonaws.com`,this.forcePathStyle=n.forcePathStyle||!1,this.credentials=n.credentials,this.credentialOptions=n.credentialOptions,this.retryOptions=n.retryOptions||{}}async getCredentials(){if(this.credentials)return this.credentials;return Ao(this.credentialOptions)}buildUrl(n,i){let s=i?encodeURIComponent(i).replace(/%2F/g,"/"):"";if(this.forcePathStyle)return i?`${this.endpoint}/${n}/${s}`:`${this.endpoint}/${n}`;let o=new URL(this.endpoint);return o.hostname=`${n}.${o.hostname}`,i?`${o.origin}/${s}`:o.origin}async get(n,i,s={}){let o=await this.getCredentials(),c=this.buildUrl(n,i),l={};if(s.range)l.Range=s.range;if(s.ifModifiedSince)l["If-Modified-Since"]=s.ifModifiedSince.toUTCString();if(s.ifMatch)l["If-Match"]=s.ifMatch;if(s.ifNoneMatch)l["If-None-Match"]=s.ifNoneMatch;let u=new URL(c);if(s.responseContentType)u.searchParams.set("response-content-type",s.responseContentType);if(s.responseContentDisposition)u.searchParams.set("response-content-disposition",s.responseContentDisposition);let h=x({method:"GET",url:u.toString(),headers:l,...o,service:"s3",region:this.region}),f=await fetch(h.url,{method:h.method,headers:h.headers});if(!f.ok&&f.status!==304){let S=await f.text();throw new V(`Failed to get object: ${S}`,f.status,n,i)}return f}async getText(n,i,s={}){return(await this.get(n,i,s)).text()}async getJSON(n,i,s={}){return(await this.get(n,i,s)).json()}async getBuffer(n,i,s={}){return(await this.get(n,i,s)).arrayBuffer()}async put(n,i,s,o={}){let c,l;if(typeof s==="string")c=new TextEncoder().encode(s).length,l=s;else if(s instanceof ArrayBuffer)c=s.byteLength,l=s;else if(s instanceof Uint8Array)c=s.byteLength,l=s;else if(s instanceof Blob)c=s.size,l=s;else return this.uploadMultipart(n,i,s,{...o,partSize:Dt});if(c>Nn){let u=$n(l).stream();return this.uploadMultipart(n,i,u,{...o,partSize:Dt})}return this.putSimple(n,i,l,c,o)}async putSimple(n,i,s,o,c){let l=await this.getCredentials(),u=this.buildUrl(n,i),h={"Content-Length":String(o),"Content-Type":c.contentType||ha(i)};if(c.contentEncoding)h["Content-Encoding"]=c.contentEncoding;if(c.cacheControl)h["Cache-Control"]=c.cacheControl;if(c.contentDisposition)h["Content-Disposition"]=c.contentDisposition;if(c.storageClass)h["x-amz-storage-class"]=c.storageClass;if(c.serverSideEncryption)h["x-amz-server-side-encryption"]=c.serverSideEncryption;if(c.acl)h["x-amz-acl"]=c.acl;if(c.tagging)h["x-amz-tagging"]=c.tagging;if(c.metadata)for(let[A,v]of Object.entries(c.metadata))h[`x-amz-meta-${A.toLowerCase()}`]=v;let f;if(typeof s==="string")f=s;else if(s instanceof Blob)f=await s.text();else f=new TextDecoder().decode(s instanceof ArrayBuffer?new Uint8Array(s):s);let S=x({method:"PUT",url:u,headers:h,body:f,...l,service:"s3",region:this.region}),b=await fetch(S.url,{method:S.method,headers:S.headers,body:s});if(!b.ok){let A=await b.text();throw new V(`Failed to put object: ${A}`,b.status,n,i)}return{etag:(b.headers.get("ETag")||"").replace(/"/g,"")}}async delete(n,i){let s=await this.getCredentials(),o=this.buildUrl(n,i),c=x({method:"DELETE",url:o,...s,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(!l.ok&&l.status!==204){let u=await l.text();throw new V(`Failed to delete object: ${u}`,l.status,n,i)}}async deleteMany(n,i){let s=await this.getCredentials(),o=`${this.buildUrl(n)}?delete`,c=`<?xml version="1.0" encoding="UTF-8"?><Delete><Quiet>false</Quiet>${i.map((w)=>`<Object><Key>${kn(w)}</Key></Object>`).join("")}</Delete>`,l=x({method:"POST",url:o,headers:{"Content-Type":"application/xml"},body:c,...s,service:"s3",region:this.region}),u=await fetch(l.url,{method:l.method,headers:l.headers,body:c});if(!u.ok){let w=await u.text();throw new V(`Failed to delete objects: ${w}`,u.status,n)}let h=await u.text(),f=[],S=[],b=/<Deleted><Key>([^<]+)<\/Key>/g,A;while((A=b.exec(h))!==null)f.push(A[1]);let v=/<Error><Key>([^<]+)<\/Key><Code>([^<]+)<\/Code><Message>([^<]+)<\/Message>/g;while((A=v.exec(h))!==null)S.push({key:A[1],error:`${A[2]}: ${A[3]}`});return{deleted:f,errors:S}}async list(n,i={}){let s=await this.getCredentials(),o=new URL(this.buildUrl(n));if(o.searchParams.set("list-type","2"),i.prefix)o.searchParams.set("prefix",i.prefix);if(i.delimiter)o.searchParams.set("delimiter",i.delimiter);if(i.maxKeys)o.searchParams.set("max-keys",String(i.maxKeys));if(i.continuationToken)o.searchParams.set("continuation-token",i.continuationToken);if(i.startAfter)o.searchParams.set("start-after",i.startAfter);let c=x({method:"GET",url:o.toString(),...s,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(!l.ok){let h=await l.text();throw new V(`Failed to list objects: ${h}`,l.status,n)}let u=await l.text();return Dn(u)}async*listAll(n,i={}){let s;do{let o=await this.list(n,{...i,continuationToken:s});for(let c of o.contents)yield c;s=o.nextContinuationToken}while(s)}async head(n,i){let s=await this.getCredentials(),o=this.buildUrl(n,i),c=x({method:"HEAD",url:o,...s,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(l.status===404)return null;if(!l.ok){let h=await l.text();throw new V(`Failed to head object: ${h}`,l.status,n,i)}let u={};return l.headers.forEach((h,f)=>{if(f.toLowerCase().startsWith("x-amz-meta-"))u[f.slice(11)]=h}),{contentLength:Number(l.headers.get("Content-Length")||0),contentType:l.headers.get("Content-Type")||"application/octet-stream",etag:(l.headers.get("ETag")||"").replace(/"/g,""),lastModified:new Date(l.headers.get("Last-Modified")||0),metadata:u,storageClass:l.headers.get("x-amz-storage-class")||void 0,serverSideEncryption:l.headers.get("x-amz-server-side-encryption")||void 0}}async exists(n,i){return await this.head(n,i)!==null}async copy(n,i,s,o,c={}){let l=await this.getCredentials(),u=this.buildUrl(s,o),h={"x-amz-copy-source":`/${n}/${encodeURIComponent(i)}`};if(c.metadataDirective)h["x-amz-metadata-directive"]=c.metadataDirective;if(c.contentType)h["Content-Type"]=c.contentType;if(c.storageClass)h["x-amz-storage-class"]=c.storageClass;if(c.acl)h["x-amz-acl"]=c.acl;if(c.metadata)for(let[A,v]of Object.entries(c.metadata))h[`x-amz-meta-${A.toLowerCase()}`]=v;let f=x({method:"PUT",url:u,headers:h,...l,service:"s3",region:this.region}),S=await fetch(f.url,{method:f.method,headers:f.headers});if(!S.ok){let A=await S.text();throw new V(`Failed to copy object: ${A}`,S.status,s,o)}let b=(await S.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:b?b[1]:""}}async getPresignedUrl(n,i,s={}){let o=await this.getCredentials(),c=this.buildUrl(n,i);return sA({url:c,method:s.method||"GET",expiresIn:s.expiresIn||3600,...o,service:"s3",region:this.region})}async uploadMultipart(n,i,s,o={}){let c=await this.getCredentials(),l=Math.max(o.partSize||Dt,Rn),u,h;if(s instanceof ReadableStream)u=s;else if(s instanceof Blob)u=s.stream(),h=s.size;else{let b=new Blob([s]);u=b.stream(),h=b.size}let{uploadId:f,baseUrl:S}=await this.initiateMultipartUpload(n,i,o);try{let b=await this.uploadParts(n,i,S,f,u,l,c,h,o.concurrency||4,o.onProgress);return await this.completeMultipartUpload(n,i,S,f,b)}catch(b){throw await this.abortMultipartUpload(n,i,f,S).catch(()=>{}),b}}async initiateMultipartUpload(n,i,s){let o=await this.getCredentials(),c=this.buildUrl(n,i),l=`${c}?uploads`,u={"Content-Type":s.contentType||ha(i)};if(s.storageClass)u["x-amz-storage-class"]=s.storageClass;if(s.serverSideEncryption)u["x-amz-server-side-encryption"]=s.serverSideEncryption;if(s.acl)u["x-amz-acl"]=s.acl;if(s.metadata)for(let[A,v]of Object.entries(s.metadata))u[`x-amz-meta-${A.toLowerCase()}`]=v;let h=x({method:"POST",url:l,headers:u,...o,service:"s3",region:this.region}),f=await fetch(h.url,{method:h.method,headers:h.headers});if(!f.ok){let A=await f.text();throw new V(`Failed to initiate multipart upload: ${A}`,f.status,n,i)}let S=(await f.text()).match(/<UploadId>([^<]+)<\/UploadId>/);if(!S)throw new V("Failed to parse upload ID from response",0,n,i);let b=c;if(f.url)try{let A=new URL(f.url);A.search="",b=A.toString()}catch{}return{uploadId:S[1],baseUrl:b}}async uploadParts(n,i,s,o,c,l,u,h,f,S){let b=[],A=c.getReader(),v=1,w=new Uint8Array(0),E=0,P=h?Math.ceil(h/l):void 0,R=new Map,D=async(I,_)=>{let B=`${s}?partNumber=${_}&uploadId=${encodeURIComponent(o)}`,W={"Content-Length":String(I.byteLength),"x-amz-content-sha256":"UNSIGNED-PAYLOAD"},J=x({method:"PUT",url:B,headers:W,...u,service:"s3",region:this.region}),K=await fetch(J.url,{method:J.method,headers:J.headers,body:I,redirect:"error"});if(!K.ok){let Z=await K.text();throw new V(`Failed to upload part ${_}: ${Z}`,K.status,n,i)}let Y=(K.headers.get("ETag")||"").replace(/"/g,"");if(!Y)throw new V(`Missing ETag for part ${_}`,K.status,n,i);return{partNumber:_,etag:Y}},O=async()=>{let I=await Promise.race(R.values());R.delete(I.partNumber),b.push(I)};while(!0){let{done:I,value:_}=await A.read();if(_){let B=new Uint8Array(w.length+_.length);B.set(w),B.set(_,w.length),w=B}while(w.length>=l||I&&w.length>0){let B=w.slice(0,l);w=w.slice(l);let W=v++;if(R.size>=f)await O();if(R.set(W,D(B,W)),E+=B.byteLength,S)S({loaded:E,total:h||E,part:W,totalParts:P||W})}if(I)break}while(R.size>0)await O();return b.sort((I,_)=>I.partNumber-_.partNumber),b}async completeMultipartUpload(n,i,s,o,c){let l=await this.getCredentials(),u=`${s}?uploadId=${encodeURIComponent(o)}`,h=`<?xml version="1.0" encoding="UTF-8"?><CompleteMultipartUpload>${c.map((A)=>`<Part><PartNumber>${A.partNumber}</PartNumber><ETag>"${A.etag}"</ETag></Part>`).join("")}</CompleteMultipartUpload>`,f=x({method:"POST",url:u,headers:{"Content-Type":"application/xml"},body:h,...l,service:"s3",region:this.region}),S=await fetch(f.url,{method:f.method,headers:f.headers,body:h});if(!S.ok){let A=await S.text();throw new V(`Failed to complete multipart upload: ${A}`,S.status,n,i)}let b=(await S.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:b?b[1]:""}}async abortMultipartUpload(n,i,s,o){let c=await this.getCredentials(),l=`${o??this.buildUrl(n,i)}?uploadId=${encodeURIComponent(s)}`,u=x({method:"DELETE",url:l,...c,service:"s3",region:this.region});await fetch(u.url,{method:u.method,headers:u.headers})}async emptyAndDeleteBucket(n){let i=[];for await(let l of this.listAll(n,{}))if(i.push(l.key),i.length>=1000)await this.deleteMany(n,i),i=[];if(i.length>0)await this.deleteMany(n,i);let s=await this.getCredentials(),o=this.buildUrl(n),c=x({method:"DELETE",url:o,...s,service:"s3",region:this.region});await fetch(c.url,{method:c.method,headers:c.headers})}}class V extends Error{statusCode;bucket;key;constructor(n,i,s,o){super(n);this.statusCode=i,this.bucket=s,this.key=o,this.name="S3Error"}}function Dn(n){let i=[],s=[],o=/<Contents>([\s\S]*?)<\/Contents>/g,c;while((c=o.exec(n))!==null){let u=c[1];i.push({key:ce(u,"Key")||"",lastModified:new Date(ce(u,"LastModified")||0),etag:(ce(u,"ETag")||"").replace(/"/g,""),size:Number(ce(u,"Size")||0),storageClass:ce(u,"StorageClass")||"STANDARD"})}let l=/<CommonPrefixes><Prefix>([^<]+)<\/Prefix><\/CommonPrefixes>/g;while((c=l.exec(n))!==null)s.push(c[1]);return{contents:i,commonPrefixes:s,isTruncated:ce(n,"IsTruncated")==="true",continuationToken:ce(n,"ContinuationToken")||void 0,nextContinuationToken:ce(n,"NextContinuationToken")||void 0,keyCount:Number(ce(n,"KeyCount")||0),maxKeys:Number(ce(n,"MaxKeys")||1000),prefix:ce(n,"Prefix")||void 0,delimiter:ce(n,"Delimiter")||void 0}}function ce(n,i){let s=new RegExp(`<${i}>([^<]*)</${i}>`),o=n.match(s);return o?o[1]:null}function kn(n){return n.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function ha(n){let i=n.split(".").pop()?.toLowerCase();return{html:"text/html",htm:"text/html",css:"text/css",js:"application/javascript",mjs:"application/javascript",json:"application/json",xml:"application/xml",txt:"text/plain",md:"text/markdown",csv:"text/csv",jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",gif:"image/gif",webp:"image/webp",svg:"image/svg+xml",ico:"image/x-icon",avif:"image/avif",mp4:"video/mp4",webm:"video/webm",mov:"video/quicktime",avi:"video/x-msvideo",mp3:"audio/mpeg",wav:"audio/wav",ogg:"audio/ogg",pdf:"application/pdf",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xls:"application/vnd.ms-excel",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",ppt:"application/vnd.ms-powerpoint",pptx:"application/vnd.openxmlformats-officedocument.presentationml.presentation",zip:"application/zip",gz:"application/gzip",tar:"application/x-tar",rar:"application/vnd.rar","7z":"application/x-7z-compressed",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf",otf:"font/otf",eot:"application/vnd.ms-fontobject",wasm:"application/wasm"}[i||""]||"application/octet-stream"}function $n(n){if(n instanceof Blob)return n;if(typeof n==="string")return new Blob([n],{type:"text/plain"});return new Blob([n])}function pS(n){return new Ba(n)}await rt();class Je extends Error{code;solution;details;constructor(n,i,s,o){super(n);this.code=i,this.solution=s,this.details=o,this.name="CloudError",Error.captureStackTrace?.(this,Je)}toString(){let n=`${this.name} [${this.code}]: ${this.message}`;if(this.solution)n+=`
|
|
2496
2496
|
|
|
2497
2497
|
\uD83D\uDCA1 Solution: ${this.solution}`;if(this.details&&Object.keys(this.details).length>0){n+=`
|
|
2498
2498
|
|
|
@@ -2507,9 +2507,9 @@ Stack trace:`),console.error(i.stack)}}static success(n){console.log(`✔ ${n}`)
|
|
|
2507
2507
|
`,s=n.reduce((o,c)=>{if(!o[c.service])o[c.service]=[];return o[c.service].push(c),o},{});for(let[o,c]of Object.entries(s)){i+=`${o}:
|
|
2508
2508
|
`;for(let l of c){let u=l.warning?"⚠":"✓";i+=` ${u} ${l.quotaName}: ${l.currentValue}/${l.limit} (${l.percentage.toFixed(1)}%)
|
|
2509
2509
|
`}i+=`
|
|
2510
|
-
`}return i}function SS(n){let i=[];for(let s of n)if(s.percentage>=100)i.push(`Request quota increase for ${s.service} - ${s.quotaName} (currently ${s.limit})`);else if(s.warning)i.push(`Consider requesting quota increase for ${s.service} - ${s.quotaName} (${s.percentage.toFixed(1)}% used)`);return i}class kg{cacheDir;ttl;constructor(n,i={}){this.cacheDir=n,this.ttl=i.ttl||86400000}ensureCacheDir(){if(!lt(this.cacheDir))Ln(this.cacheDir,{recursive:!0})}getCachePath(n){let i=_a("sha256").update(n).digest("hex");return kt(this.cacheDir,`${i}.json`)}get(n){let i=this.getCachePath(n);if(!lt(i))return;try{let s=fa(i,"utf-8"),o=JSON.parse(s);if(Date.now()-o.timestamp>this.ttl){Ye(i);return}return o.value}catch{Ye(i);return}}set(n,i,s){this.ensureCacheDir();let o=this.getCachePath(n),c={value:i,timestamp:Date.now(),hash:s};Mn(o,JSON.stringify(c),"utf-8")}has(n){return this.get(n)!==void 0}clear(){if(!lt(this.cacheDir))return;let n=ya(this.cacheDir);for(let i of n)Ye(kt(this.cacheDir,i))}prune(){if(!lt(this.cacheDir))return;let n=ya(this.cacheDir),i=Date.now();for(let s of n){let o=kt(this.cacheDir,s);try{let c=fa(o,"utf-8"),l=JSON.parse(c);if(i-l.timestamp>this.ttl)Ye(o)}catch{Ye(o)}}}}class Bg{cache;constructor(n=L("cache","templates")){this.cache=new kg(n,{ttl:86400000})}getTemplate(n){return this.cache.get(`template:${n}`)}setTemplate(n,i){let s=this.hashTemplate(i);this.cache.set(`template:${n}`,i,s)}hasChanged(n,i){let s=this.cache.get(`template:${n}`);if(!s)return!0;let o=this.hashTemplate(s),c=this.hashTemplate(i);return o!==c}hashTemplate(n){return _a("sha256").update(n).digest("hex")}clear(){this.cache.clear()}prune(){this.cache.prune()}}var $t=null;function CS(){if(!$t)$t=new Bg;return $t}async function _g(n,i={}){let s=i.algorithm||"sha256",o=i.chunkSize||65536;return new Promise((c,l)=>{let u=Qt(s),h=On(n,{highWaterMark:o});h.on("data",(f)=>u.update(f)),h.on("end",()=>c(u.digest("hex"))),h.on("error",l)})}function
|
|
2511
|
-
`);return
|
|
2512
|
-
`)}function OS(n,i,s){if(n.deleted.length>0)return!0;for(let o of n.modified){let c=i.Resources[o],l=s.Resources[o];if(c.Type!==l.Type)return!0;let u=Wn(l.Type);for(let h of u){let f=c.Properties?.[h],S=l.Properties?.[h];if(JSON.stringify(f)!==JSON.stringify(S))return!0}}return!1}function Wn(n){return{"AWS::S3::Bucket":["BucketName"],"AWS::EC2::Instance":["ImageId","InstanceType","KeyName"],"AWS::RDS::DBInstance":["DBInstanceIdentifier","Engine"],"AWS::DynamoDB::Table":["TableName","KeySchema"],"AWS::Lambda::Function":["FunctionName"],"AWS::ECS::Service":["ServiceName"],"AWS::ElasticLoadBalancingV2::LoadBalancer":["Name","Type"]}[n]||[]}function LS(n){let i=[],s=[],o=[];i.push(...n.added);for(let c of n.modified)s.push(c);return o.push(...n.deleted),{safe:i,caution:s,dangerous:o}}function $S(n){if(!n.hasChanges)return{strategy:"skip",reason:"No changes detected"};if(n.deleted.length>0)return{strategy:"replace",reason:"Resources will be deleted"};if(n.added.length>0&&n.modified.length===0)return{strategy:"update",reason:"Only new resources added"};return{strategy:"update",reason:"Resources will be updated"}}function MS(n){let i=n.added.length+n.modified.length+n.deleted.length+n.unchanged.length,s=n.added.length+n.modified.length+n.deleted.length,o=i>0?s/i*100:0;return{total:i,added:n.added.length,modified:n.modified.length,deleted:n.deleted.length,unchanged:n.unchanged.length,changePercentage:o}}var FS={$schema:"http://json-schema.org/draft-07/schema#",title:"ts-cloud Configuration",description:"Configuration schema for ts-cloud infrastructure-as-code",type:"object",required:["project"],properties:{project:{type:"object",description:"Project configuration",required:["name","slug"],properties:{name:{type:"string",description:"Human-readable project name",minLength:1},slug:{type:"string",description:"URL-safe project identifier (lowercase, alphanumeric, hyphens only)",pattern:"^[a-z0-9-]+$",minLength:1,maxLength:63},region:{type:"string",description:"Default AWS region",enum:["us-east-1","us-east-2","us-west-1","us-west-2","eu-west-1","eu-west-2","eu-west-3","eu-central-1","ap-southeast-1","ap-southeast-2","ap-northeast-1","ap-northeast-2","sa-east-1","ca-central-1"]}}},mode:{type:"string",description:"Deployment mode (server and serverless are mutually exclusive; auto-detected when omitted)",enum:["server","serverless"]},environments:{type:"object",description:"Environment-specific configurations",properties:{production:{$ref:"#/definitions/environment"},staging:{$ref:"#/definitions/environment"},development:{$ref:"#/definitions/environment"}}},infrastructure:{type:"object",description:"Infrastructure configuration",properties:{network:{$ref:"#/definitions/network"},storage:{type:"object",description:"S3 storage configuration",additionalProperties:{$ref:"#/definitions/storage"}},compute:{$ref:"#/definitions/compute"},database:{$ref:"#/definitions/database"},cache:{$ref:"#/definitions/cache"},cdn:{$ref:"#/definitions/cdn"},sftp:{$ref:"#/definitions/sftp"},functions:{type:"object",description:"Lambda functions configuration",additionalProperties:{type:"array",items:{$ref:"#/definitions/function"}}},monitoring:{$ref:"#/definitions/monitoring"},security:{$ref:"#/definitions/security"},queue:{type:"object",description:"SQS queue configuration",additionalProperties:{$ref:"#/definitions/queue"}}}}},definitions:{environment:{type:"object",properties:{domain:{type:"string",description:"Custom domain for this environment"},region:{type:"string",description:"AWS region override for this environment"},app:{type:"object",description:"Serverless application manifest (Laravel-Vapor-equivalent). Defining this opts the environment into the serverless app deploy pipeline (http/queue/cli Lambda functions, assets, build/deploy hooks).",properties:{runtime:{type:"string",description:"Lambda runtime override (usually derived from kind + runtimeVersion)"},runtimeVersion:{type:"string",description:"Node major (18/20/22 managed, 24+ custom layer) or Bun release for node/bun apps"},kind:{type:"string",enum:["node","bun","php"],description:"Application kind (drives packaging + runtime)"},entry:{type:"string",description:"Entry file exporting the request handler"},memory:{type:"number",description:"HTTP function memory in MB"},timeout:{type:"number",description:"HTTP request timeout in seconds"},gatewayVersion:{type:"number",enum:[1,2],description:"API Gateway version (2 = HTTP API, 1 = REST)"},warm:{type:"number",description:"Keep-warm / provisioned concurrency count"},lambdaInsights:{type:"object",description:"CloudWatch Lambda Insights extension configuration for zip deployments",required:["layerArn"],properties:{layerArn:{type:"string",description:"Region- and architecture-specific Lambda Insights extension layer ARN"}}},queues:{description:"Queue names (true = single default queue, false = disabled)"},scheduler:{type:"string",enum:["off","on","sub-minute"],description:"Task scheduler mode"},build:{type:"array",items:{type:"string"},description:"Commands run locally before packaging"},deploy:{type:"array",items:{type:"string"},description:"Commands run remotely after activation (e.g. migrations)"},octane:{type:"boolean",description:"Persistent application mode (Laravel Octane)"},packaging:{type:"string",enum:["zip","image"],description:"Deployment package format (zip or container image)"},phpVersion:{type:"string",description:"PHP version for the runtime layer (kind: php)"},architecture:{type:"string",enum:["x86_64","arm64"],description:"CPU architecture"}}}}},network:{type:"object",properties:{vpc:{type:"object",properties:{cidr:{type:"string",description:"VPC CIDR block",pattern:"^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]{1,2}$",default:"10.0.0.0/16"},availabilityZones:{type:"number",description:"Number of availability zones",minimum:1,maximum:3,default:2},natGateways:{type:"number",description:"Number of NAT gateways (0 for no NAT, saves cost)",minimum:0,maximum:3,default:1}}}}},storage:{type:"object",properties:{public:{type:"boolean",description:"Allow public access",default:!1},versioning:{type:"boolean",description:"Enable versioning",default:!1},encryption:{type:"boolean",description:"Enable server-side encryption",default:!0},website:{type:"boolean",description:"Enable static website hosting",default:!1},cors:{type:"object",description:"CORS configuration",properties:{allowedOrigins:{type:"array",items:{type:"string"}},allowedMethods:{type:"array",items:{type:"string",enum:["GET","PUT","POST","DELETE","HEAD"]}}}}}},compute:{type:"object",properties:{server:{type:"object",description:"EC2 server configuration",properties:{instanceType:{type:"string",description:"EC2 instance type",enum:["t3.micro","t3.small","t3.medium","t3.large","t3.xlarge","t3.2xlarge"]},autoScaling:{type:"object",properties:{min:{type:"number",minimum:1},max:{type:"number",minimum:1},desired:{type:"number",minimum:1}}}}},fargate:{type:"object",description:"ECS Fargate configuration",properties:{cpu:{type:"number",description:"CPU units (256, 512, 1024, 2048, 4096)",enum:[256,512,1024,2048,4096]},memory:{type:"number",description:"Memory in MB"},desiredCount:{type:"number",description:"Desired number of tasks",minimum:1}}}}},database:{type:"object",properties:{postgres:{type:"object",properties:{instanceClass:{type:"string",description:"RDS instance class",pattern:"^db\\.[a-z0-9]+\\.[a-z0-9]+$"},engine:{type:"string",const:"postgres"},version:{type:"string",description:"PostgreSQL version"},multiAZ:{type:"boolean",description:"Enable Multi-AZ deployment",default:!1},backupRetentionDays:{type:"number",description:"Backup retention period in days",minimum:0,maximum:35,default:7}}},mysql:{type:"object",properties:{instanceClass:{type:"string",pattern:"^db\\.[a-z0-9]+\\.[a-z0-9]+$"},engine:{type:"string",const:"mysql"},version:{type:"string"},multiAZ:{type:"boolean",default:!1},backupRetentionDays:{type:"number",minimum:0,maximum:35,default:7}}},dynamodb:{type:"object",properties:{tables:{type:"array",items:{type:"object",required:["name","partitionKey"],properties:{name:{type:"string"},partitionKey:{type:"string"},sortKey:{type:"string"},billingMode:{type:"string",enum:["PAY_PER_REQUEST","PROVISIONED"],default:"PAY_PER_REQUEST"}}}}}}}},cache:{type:"object",properties:{redis:{type:"object",properties:{nodeType:{type:"string",description:"ElastiCache node type",pattern:"^cache\\.[a-z0-9]+\\.[a-z0-9]+$"},numCacheNodes:{type:"number",minimum:1,default:1},engineVersion:{type:"string",description:"Redis engine version"}}},memcached:{type:"object",properties:{nodeType:{type:"string",pattern:"^cache\\.[a-z0-9]+\\.[a-z0-9]+$"},numCacheNodes:{type:"number",minimum:1,default:1}}}}},cdn:{type:"object",properties:{enabled:{type:"boolean",default:!0},originShield:{type:"boolean",description:"Enable CloudFront Origin Shield",default:!1},originShieldRegion:{type:"string",description:"AWS region used by CloudFront Origin Shield"},compress:{type:"boolean",description:"Enable automatic compression",default:!0},http3:{type:"boolean",description:"Enable HTTP/3 support",default:!0},customDomain:{type:"object",properties:{domain:{type:"string"},certificateArn:{type:"string"}}},cachePolicy:{type:"object",properties:{minTTL:{type:"number",minimum:0},defaultTTL:{type:"number",minimum:0},maxTTL:{type:"number",minimum:0}}}}},sftp:{type:"object",required:["bucket","users"],properties:{bucket:{type:"string",description:"S3 bucket backing the SFTP server"},endpointType:{type:"string",enum:["PUBLIC","VPC"],default:"PUBLIC"},endpointDetails:{type:"object",required:["vpcId","subnetIds"],properties:{vpcId:{type:"string"},subnetIds:{type:"array",items:{type:"string"},minItems:1},securityGroupIds:{type:"array",items:{type:"string"}},addressAllocationIds:{type:"array",items:{type:"string"}}}},securityPolicyName:{type:"string"},logging:{type:"boolean",default:!0},users:{type:"object",additionalProperties:{type:"object",required:["sshPublicKeys"],properties:{sshPublicKeys:{type:"array",items:{type:"string"},minItems:1},homeDirectory:{type:"string"},roleArn:{type:"string"}}}}}},function:{type:"object",required:["name","runtime"],properties:{name:{type:"string"},runtime:{type:"string",enum:["nodejs18.x","nodejs20.x","python3.10","python3.11","python3.12"]},handler:{type:"string",default:"index.handler"},timeout:{type:"number",minimum:1,maximum:900,default:30},memory:{type:"number",minimum:128,maximum:10240,default:1024}}},monitoring:{type:"object",properties:{alarms:{type:"array",items:{type:"object",required:["metric","threshold"],properties:{metric:{type:"string"},threshold:{type:"number"},evaluationPeriods:{type:"number",minimum:1,default:2}}}},dashboard:{type:"object",properties:{name:{type:"string"},widgets:{type:"array"}}}}},security:{type:"object",properties:{waf:{type:"boolean",description:"Enable AWS WAF",default:!1},certificates:{type:"array",items:{type:"object",required:["domain"],properties:{domain:{type:"string"},subdomains:{type:"array",items:{type:"string"}}}}}}},queue:{type:"object",properties:{fifo:{type:"boolean",default:!1},deadLetterQueue:{type:"boolean",default:!0},visibilityTimeout:{type:"number",minimum:0,maximum:43200,default:30},messageRetentionPeriod:{type:"number",minimum:60,maximum:1209600,default:345600}}}}};function US(n){let i=[];if(!n.project)i.push("Missing required field: project");else{if(!n.project.name)i.push("Missing required field: project.name");if(!n.project.slug)i.push("Missing required field: project.slug")}if(n.project?.slug&&!/^[a-z0-9-]+$/.test(n.project.slug))i.push("Invalid project.slug: must contain only lowercase letters, numbers, and hyphens");let s=["us-east-1","us-east-2","us-west-1","us-west-2","eu-west-1","eu-west-2","eu-west-3","eu-central-1","ap-southeast-1","ap-southeast-2","ap-northeast-1","ap-northeast-2","sa-east-1","ca-central-1"];if(n.project?.region&&!s.includes(n.project.region))i.push(`Invalid region: ${n.project.region}. Must be one of: ${s.join(", ")}`);if(n.mode&&!["server","serverless"].includes(n.mode))i.push("Invalid mode: must be one of server or serverless");return{valid:i.length===0,errors:i}}var Og={enabled:process.env.TS_CLOUD_LOCAL==="true"||!0,localstackEndpoint:process.env.LOCALSTACK_ENDPOINT||"http://localhost:4566",postgresUrl:process.env.POSTGRES_URL||"postgresql://tscloud:tscloud@localhost:5432/tscloud",redisUrl:process.env.REDIS_URL||"redis://localhost:6379",dynamodbEndpoint:process.env.DYNAMODB_ENDPOINT||"http://localhost:8000",s3Endpoint:process.env.S3_ENDPOINT||"http://localhost:9000",emailEndpoint:process.env.EMAIL_ENDPOINT||"smtp://localhost:1025",awsRegion:process.env.AWS_REGION||"us-east-1",awsAccessKeyId:process.env.AWS_ACCESS_KEY_ID||"test",awsSecretAccessKey:process.env.AWS_SECRET_ACCESS_KEY||"test"};function Qd(){return Og}function QS(){return Og.enabled}function HS(n){let i=Qd();if(!i.enabled)return"";switch(n.toLowerCase()){case"dynamodb":return i.dynamodbEndpoint;case"s3":return i.s3Endpoint;case"localstack":case"cloudformation":case"lambda":case"apigateway":case"sns":case"sqs":case"cloudwatch":case"iam":case"sts":return i.localstackEndpoint;default:return i.localstackEndpoint}}function GS(){let n=Qd();return{accessKeyId:n.awsAccessKeyId,secretAccessKey:n.awsSecretAccessKey,region:n.awsRegion}}function qS(){let n=Qd();if(!n.enabled)return{};return{AWS_ACCESS_KEY_ID:n.awsAccessKeyId,AWS_SECRET_ACCESS_KEY:n.awsSecretAccessKey,AWS_REGION:n.awsRegion,AWS_ENDPOINT_URL:n.localstackEndpoint,LOCALSTACK_ENDPOINT:n.localstackEndpoint,TS_CLOUD_LOCAL:"true"}}class Lg{stacks=new Map;stackEvents=new Map;async createStack(n){let i=`arn:aws:cloudformation:${n.region||"us-east-1"}:123456789012:stack/${n.StackName}/${Date.now()}`;return this.stacks.set(n.StackName,{StackId:i,StackName:n.StackName,StackStatus:"CREATE_IN_PROGRESS",CreationTime:new Date().toISOString(),TemplateBody:n.TemplateBody,Parameters:n.Parameters||[]}),this.addEvent(n.StackName,{EventId:Date.now().toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_IN_PROGRESS"}),setTimeout(()=>{let s=this.stacks.get(n.StackName);if(s)s.StackStatus="CREATE_COMPLETE",this.addEvent(n.StackName,{EventId:(Date.now()+1).toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_COMPLETE"})},100),{StackId:i}}async updateStack(n){let i=this.stacks.get(n.StackName);if(!i)throw Error(`Stack ${n.StackName} does not exist`);return i.StackStatus="UPDATE_IN_PROGRESS",i.TemplateBody=n.TemplateBody||i.TemplateBody,this.addEvent(n.StackName,{EventId:Date.now().toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_IN_PROGRESS"}),setTimeout(()=>{i.StackStatus="UPDATE_COMPLETE",this.addEvent(n.StackName,{EventId:(Date.now()+1).toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_COMPLETE"})},100),{StackId:i.StackId}}async deleteStack(n){let i=this.stacks.get(n.StackName);if(!i)throw Error(`Stack ${n.StackName} does not exist`);i.StackStatus="DELETE_IN_PROGRESS",this.addEvent(n.StackName,{EventId:Date.now().toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_IN_PROGRESS"}),setTimeout(()=>{this.stacks.delete(n.StackName),this.addEvent(n.StackName,{EventId:(Date.now()+1).toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_COMPLETE"})},100)}async describeStacks(n){if(n.StackName){let i=this.stacks.get(n.StackName);if(!i)throw Error(`Stack ${n.StackName} does not exist`);return{Stacks:[i]}}return{Stacks:Array.from(this.stacks.values())}}async describeStackEvents(n){return{StackEvents:this.stackEvents.get(n.StackName)||[]}}addEvent(n,i){if(!this.stackEvents.has(n))this.stackEvents.set(n,[]);this.stackEvents.get(n).unshift(i)}reset(){this.stacks.clear(),this.stackEvents.clear()}}class $g{buckets=new Map;async createBucket(n){return this.buckets.set(n.Bucket,new Map),{Location:`/${n.Bucket}`}}async deleteBucket(n){this.buckets.delete(n.Bucket)}async putObject(n){let i=this.buckets.get(n.Bucket);if(!i)i=new Map,this.buckets.set(n.Bucket,i);return i.set(n.Key,Buffer.from(n.Body||"")),{ETag:`"${Date.now()}"`}}async getObject(n){let i=this.buckets.get(n.Bucket);if(!i)throw Error(`Bucket ${n.Bucket} does not exist`);let s=i.get(n.Key);if(!s)throw Error(`Object ${n.Key} does not exist`);return{Body:s,ContentLength:s.length}}async deleteObject(n){let i=this.buckets.get(n.Bucket);if(i)i.delete(n.Key)}async listObjects(n){let i=this.buckets.get(n.Bucket);if(!i)throw Error(`Bucket ${n.Bucket} does not exist`);return{Contents:Array.from(i.keys()).map((s)=>({Key:s,Size:i.get(s).length,LastModified:new Date().toISOString()}))}}reset(){this.buckets.clear()}}class Mg{tables=new Map;data=new Map;async createTable(n){return this.tables.set(n.TableName,{TableName:n.TableName,KeySchema:n.KeySchema,AttributeDefinitions:n.AttributeDefinitions,TableStatus:"ACTIVE",CreationDateTime:new Date().toISOString()}),this.data.set(n.TableName,new Map),{TableDescription:this.tables.get(n.TableName)}}async deleteTable(n){this.tables.delete(n.TableName),this.data.delete(n.TableName)}async putItem(n){let i=this.data.get(n.TableName);if(!i)i=new Map,this.data.set(n.TableName,i);let s=JSON.stringify(n.Item);i.set(s,n.Item)}async getItem(n){let i=this.data.get(n.TableName);if(!i)return{};let s=JSON.stringify(n.Key),o=i.get(s);return o?{Item:o}:{}}async deleteItem(n){let i=this.data.get(n.TableName);if(i){let s=JSON.stringify(n.Key);i.delete(s)}}async scan(n){let i=this.data.get(n.TableName);if(!i)return{Items:[]};return{Items:Array.from(i.values())}}reset(){this.tables.clear(),this.data.clear()}}function VS(n){return{cloudformation:new Lg,s3:new $g,dynamodb:new Mg}}class Fg{environments=new Map;async createPreviewEnvironment(n){let{branch:i,pr:s,commitSha:o,ttl:c=24,baseConfig:l,region:u="us-east-1"}=n,h=this.generatePreviewId(i,s,o),f=this.generatePreviewName(i,s),S=`preview-${f}`,b=new Date,A=new Date(b.getTime()+c*60*60*1000),v={id:h,name:f,branch:i,pr:s,commitSha:o,createdAt:b,expiresAt:A,status:"creating",stackName:S,region:u,resources:[]};this.environments.set(h,v);try{let w=this.createPreviewConfig(l,f);return v.status="active",v.url=`https://${f}.preview.example.com`,v}catch(w){throw v.status="failed",w}}async destroyPreviewEnvironment(n){let i=this.environments.get(n);if(!i)throw Error(`Preview environment ${n} not found`);i.status="destroying";try{i.status="destroyed",this.environments.delete(n)}catch(s){throw Error(`Failed to destroy preview environment: ${s}`)}}getPreviewEnvironment(n){return this.environments.get(n)}getPreviewEnvironmentByBranch(n){return Array.from(this.environments.values()).find((i)=>i.branch===n)}getPreviewEnvironmentByPR(n){return Array.from(this.environments.values()).find((i)=>i.pr===n)}listPreviewEnvironments(){return Array.from(this.environments.values())}listActivePreviewEnvironments(){return this.listPreviewEnvironments().filter((n)=>n.status==="active")}async cleanupExpiredEnvironments(n={}){let{maxAge:i,keepCount:s,dryRun:o=!1}=n,c=[],l=[],u=new Date,h=this.listPreviewEnvironments().sort((f,S)=>S.createdAt.getTime()-f.createdAt.getTime());for(let f=0;f<h.length;f++){let S=h[f];if(S.status!=="active")continue;let b=!1;if(S.expiresAt<u)b=!0;if(i){if((u.getTime()-S.createdAt.getTime())/3600000>i)b=!0}if(s&&f>=s)b=!0;if(b)if(o)c.push(S.id);else try{await this.destroyPreviewEnvironment(S.id),c.push(S.id)}catch(A){l.push(S.id)}}return{destroyed:c,failed:l}}async updatePreviewEnvironment(n,i){let s=this.environments.get(n);if(!s)throw Error(`Preview environment ${n} not found`);s.commitSha=i,s.status="creating";try{return s.status="active",s}catch(o){throw s.status="failed",o}}async getPreviewEnvironmentsCost(){let n={},i=0;for(let s of this.environments.values())n[s.id]=0,i+=0;return{total:i,byEnvironment:n}}generatePreviewId(n,i,s){let o=n.replace(/[^a-z0-9-]/gi,"-").toLowerCase(),c=s?.substring(0,7)||Date.now().toString();return i?`pr-${i}-${c}`:`${o}-${c}`}generatePreviewName(n,i){let s=n.replace(/[^a-z0-9-]/gi,"-").toLowerCase();return i?`pr-${i}`:s}createPreviewConfig(n,i){return{...n,project:{...n.project,name:`${n.project.name} Preview (${i})`,slug:`${n.project.slug}-preview-${i}`}}}}var jS=new Fg;function zS(n={}){let{workflowName:i="Preview Environment",trigger:s="pull_request",branches:o=["main","develop"],awsRegion:c="us-east-1",awsRole:l,configFile:u="cloud.config.ts",ttl:h=24}=n;return`name: ${i}
|
|
2510
|
+
`}return i}function SS(n){let i=[];for(let s of n)if(s.percentage>=100)i.push(`Request quota increase for ${s.service} - ${s.quotaName} (currently ${s.limit})`);else if(s.warning)i.push(`Consider requesting quota increase for ${s.service} - ${s.quotaName} (${s.percentage.toFixed(1)}% used)`);return i}class kg{cacheDir;ttl;constructor(n,i={}){this.cacheDir=n,this.ttl=i.ttl||86400000}ensureCacheDir(){if(!lt(this.cacheDir))Ln(this.cacheDir,{recursive:!0})}getCachePath(n){let i=_a("sha256").update(n).digest("hex");return kt(this.cacheDir,`${i}.json`)}get(n){let i=this.getCachePath(n);if(!lt(i))return;try{let s=fa(i,"utf-8"),o=JSON.parse(s);if(Date.now()-o.timestamp>this.ttl){Ye(i);return}return o.value}catch{Ye(i);return}}set(n,i,s){this.ensureCacheDir();let o=this.getCachePath(n),c={value:i,timestamp:Date.now(),hash:s};Mn(o,JSON.stringify(c),"utf-8")}has(n){return this.get(n)!==void 0}clear(){if(!lt(this.cacheDir))return;let n=ya(this.cacheDir);for(let i of n)Ye(kt(this.cacheDir,i))}prune(){if(!lt(this.cacheDir))return;let n=ya(this.cacheDir),i=Date.now();for(let s of n){let o=kt(this.cacheDir,s);try{let c=fa(o,"utf-8"),l=JSON.parse(c);if(i-l.timestamp>this.ttl)Ye(o)}catch{Ye(o)}}}}class Bg{cache;constructor(n=L("cache","templates")){this.cache=new kg(n,{ttl:86400000})}getTemplate(n){return this.cache.get(`template:${n}`)}setTemplate(n,i){let s=this.hashTemplate(i);this.cache.set(`template:${n}`,i,s)}hasChanged(n,i){let s=this.cache.get(`template:${n}`);if(!s)return!0;let o=this.hashTemplate(s),c=this.hashTemplate(i);return o!==c}hashTemplate(n){return _a("sha256").update(n).digest("hex")}clear(){this.cache.clear()}prune(){this.cache.prune()}}var $t=null;function CS(){if(!$t)$t=new Bg;return $t}async function _g(n,i={}){let s=i.algorithm||"sha256",o=i.chunkSize||65536;return new Promise((c,l)=>{let u=Qt(s),h=On(n,{highWaterMark:o});h.on("data",(f)=>u.update(f)),h.on("end",()=>c(u.digest("hex"))),h.on("error",l)})}function Og(n,i="sha256"){return Qt(i).update(n).digest("hex")}function ES(n,i="sha256"){return Qt(i).update(n).digest("hex")}async function bS(n,i={}){let s=i.ignorePatterns||["node_modules",".git","dist","build",uo()],o=[];async function c(l){let u=xn(l,{withFileTypes:!0});for(let h of u){let f=Bn(l,h.name),S=_n(n,f);if(s.some((b)=>S.includes(b)))continue;if(h.isDirectory())await c(f);else if(h.isFile()){let b=St(f),A=await _g(f,i);o.push({path:S,hash:A,size:b.size,mtime:b.mtimeMs})}}}return await c(n),o}function vS(n){let i=[...n].sort((s,o)=>s.path.localeCompare(o.path)).map((s)=>`${s.path}:${s.hash}`).join(`
|
|
2511
|
+
`);return Og(i)}function TS(n){let i=St(n);return Og(`${n}:${i.size}:${i.mtimeMs}`)}function wS(n,i){let s=new Map(n.map((h)=>[h.path,h])),o=new Map(i.map((h)=>[h.path,h])),c=[],l=[],u=[];for(let[h,f]of o){let S=s.get(h);if(!S)c.push(f);else if(S.hash!==f.hash)l.push(f)}for(let[h,f]of s)if(!o.has(h))u.push(f);return{added:c,modified:l,deleted:u}}class _A{cache;constructor(){this.cache=new Map}get(n){let i=St(n),s=this.cache.get(n);if(s&&s.mtime===i.mtimeMs&&s.size===i.size)return s.hash;return}set(n,i){let s=St(n);this.cache.set(n,{hash:i,mtime:s.mtimeMs,size:s.size})}async getOrCompute(n,i={}){let s=this.get(n);if(s)return s;let o=await _g(n,i);return this.set(n,o),o}clear(){this.cache.clear()}}async function Ud(n,i={}){let s=i.concurrency||5,o=i.stopOnError??!0,c=[],l=[],u=Date.now(),h=[...n],f=[];async function S(v,w){try{let E=await v();c[w]=E}catch(E){let P=E instanceof Error?E:Error(String(E));if(l.push(P),o)throw h.length=0,P}}let b=0;while(h.length>0||f.length>0){while(f.length<s&&h.length>0){let v=h.shift(),w=b++,E=S(v,w);f.push(E)}if(f.length>0){await Promise.race(f);for(let v=f.length-1;v>=0;v--)if(await Promise.race([f[v].then(()=>!0),Promise.resolve(!1)]))f.splice(v,1)}if(o&&l.length>0)break}let A=Date.now()-u;return{results:c.filter((v)=>v!==void 0),errors:l,duration:A}}async function RS(n,i,s={}){let o=n.map((c)=>()=>i(c));return Ud(o,s)}async function DS(n,i,s=5){let o=n.map((l,u)=>()=>i(l,u)),c=await Ud(o,{concurrency:s,stopOnError:!1});if(c.errors.length>0)throw AggregateError(c.errors,"Parallel map failed");return c.results}async function PS(n,i={}){let s=i.retries||3,o=i.retryDelay||1000,c=n.map((l)=>async()=>{let u;for(let h=0;h<=s;h++)try{return await l()}catch(f){if(u=f instanceof Error?f:Error(String(f)),h<s)await Wa(o*(h+1))}throw u});return Ud(c,i)}async function NS(n){let i=[];for(let s of n){let o=await s();i.push(o)}return i}function Wa(n){return new Promise((i)=>setTimeout(i,n))}async function kS(n,i,s="Operation timed out"){return Promise.race([n(),new Promise((o,c)=>setTimeout(()=>c(Error(s)),i))])}class OA{maxConcurrent;minInterval;queue=[];running=0;lastExecution=0;constructor(n=5,i=100){this.maxConcurrent=n,this.minInterval=i}async execute(n){await this.waitForSlot(),this.running++,this.lastExecution=Date.now();try{return await n()}finally{this.running--,this.processQueue()}}waitForSlot(){if(this.running<this.maxConcurrent){let n=Date.now()-this.lastExecution;if(n>=this.minInterval)return Promise.resolve();return Wa(this.minInterval-n)}return new Promise((n)=>this.queue.push(n))}processQueue(){if(this.queue.length>0&&this.running<this.maxConcurrent)this.queue.shift()()}stats(){return{running:this.running,queued:this.queue.length}}}function xA(n,i){let s=[];for(let o=0;o<n.length;o+=i)s.push(n.slice(o,o+i));return s}async function BS(n,i,s){let o=xA(n,i),c=[];for(let l of o){let u=await s(l);c.push(...u)}return c}function _S(n,i){let s=[],o=[],c=[],l=[],u=n.Resources||{},h=i.Resources||{},f=new Set(Object.keys(u)),S=new Set(Object.keys(h));for(let v of S)if(!f.has(v))s.push(v);for(let v of f)if(!S.has(v))c.push(v);for(let v of S)if(f.has(v)){let w=u[v],E=h[v];if(JSON.stringify(w)!==JSON.stringify(E))o.push(v);else l.push(v)}let b=JSON.stringify(n.Parameters||{})!==JSON.stringify(i.Parameters||{}),A=JSON.stringify(n.Outputs||{})!==JSON.stringify(i.Outputs||{});return{added:s,modified:o,deleted:c,unchanged:l,parametersChanged:b,outputsChanged:A,hasChanges:s.length>0||o.length>0||c.length>0||b||A}}function OS(n){let i=[];if(!n.hasChanges)return"No changes detected";if(n.added.length>0){i.push(`Added resources (${n.added.length}):`);for(let s of n.added)i.push(` + ${s}`)}if(n.modified.length>0){i.push(`Modified resources (${n.modified.length}):`);for(let s of n.modified)i.push(` ~ ${s}`)}if(n.deleted.length>0){i.push(`Deleted resources (${n.deleted.length}):`);for(let s of n.deleted)i.push(` - ${s}`)}if(n.parametersChanged)i.push("Parameters changed");if(n.outputsChanged)i.push("Outputs changed");return i.join(`
|
|
2512
|
+
`)}function xS(n,i,s){if(n.deleted.length>0)return!0;for(let o of n.modified){let c=i.Resources[o],l=s.Resources[o];if(c.Type!==l.Type)return!0;let u=Wn(l.Type);for(let h of u){let f=c.Properties?.[h],S=l.Properties?.[h];if(JSON.stringify(f)!==JSON.stringify(S))return!0}}return!1}function Wn(n){return{"AWS::S3::Bucket":["BucketName"],"AWS::EC2::Instance":["ImageId","InstanceType","KeyName"],"AWS::RDS::DBInstance":["DBInstanceIdentifier","Engine"],"AWS::DynamoDB::Table":["TableName","KeySchema"],"AWS::Lambda::Function":["FunctionName"],"AWS::ECS::Service":["ServiceName"],"AWS::ElasticLoadBalancingV2::LoadBalancer":["Name","Type"]}[n]||[]}function LS(n){let i=[],s=[],o=[];i.push(...n.added);for(let c of n.modified)s.push(c);return o.push(...n.deleted),{safe:i,caution:s,dangerous:o}}function $S(n){if(!n.hasChanges)return{strategy:"skip",reason:"No changes detected"};if(n.deleted.length>0)return{strategy:"replace",reason:"Resources will be deleted"};if(n.added.length>0&&n.modified.length===0)return{strategy:"update",reason:"Only new resources added"};return{strategy:"update",reason:"Resources will be updated"}}function MS(n){let i=n.added.length+n.modified.length+n.deleted.length+n.unchanged.length,s=n.added.length+n.modified.length+n.deleted.length,o=i>0?s/i*100:0;return{total:i,added:n.added.length,modified:n.modified.length,deleted:n.deleted.length,unchanged:n.unchanged.length,changePercentage:o}}var FS={$schema:"http://json-schema.org/draft-07/schema#",title:"ts-cloud Configuration",description:"Configuration schema for ts-cloud infrastructure-as-code",type:"object",required:["project"],properties:{project:{type:"object",description:"Project configuration",required:["name","slug"],properties:{name:{type:"string",description:"Human-readable project name",minLength:1},slug:{type:"string",description:"URL-safe project identifier (lowercase, alphanumeric, hyphens only)",pattern:"^[a-z0-9-]+$",minLength:1,maxLength:63},region:{type:"string",description:"Default AWS region",enum:["us-east-1","us-east-2","us-west-1","us-west-2","eu-west-1","eu-west-2","eu-west-3","eu-central-1","ap-southeast-1","ap-southeast-2","ap-northeast-1","ap-northeast-2","sa-east-1","ca-central-1"]}}},mode:{type:"string",description:"Deployment mode (server and serverless are mutually exclusive; auto-detected when omitted)",enum:["server","serverless"]},environments:{type:"object",description:"Environment-specific configurations",properties:{production:{$ref:"#/definitions/environment"},staging:{$ref:"#/definitions/environment"},development:{$ref:"#/definitions/environment"}}},infrastructure:{type:"object",description:"Infrastructure configuration",properties:{network:{$ref:"#/definitions/network"},storage:{type:"object",description:"S3 storage configuration",additionalProperties:{$ref:"#/definitions/storage"}},compute:{$ref:"#/definitions/compute"},database:{$ref:"#/definitions/database"},cache:{$ref:"#/definitions/cache"},cdn:{$ref:"#/definitions/cdn"},sftp:{$ref:"#/definitions/sftp"},functions:{type:"object",description:"Lambda functions configuration",additionalProperties:{type:"array",items:{$ref:"#/definitions/function"}}},monitoring:{$ref:"#/definitions/monitoring"},security:{$ref:"#/definitions/security"},queue:{type:"object",description:"SQS queue configuration",additionalProperties:{$ref:"#/definitions/queue"}}}}},definitions:{environment:{type:"object",properties:{domain:{type:"string",description:"Custom domain for this environment"},region:{type:"string",description:"AWS region override for this environment"},app:{type:"object",description:"Serverless application manifest (Laravel-Vapor-equivalent). Defining this opts the environment into the serverless app deploy pipeline (http/queue/cli Lambda functions, assets, build/deploy hooks).",properties:{runtime:{type:"string",description:"Lambda runtime override (usually derived from kind + runtimeVersion)"},runtimeVersion:{type:"string",description:"Node major (18/20/22 managed, 24+ custom layer) or Bun release for node/bun apps"},kind:{type:"string",enum:["node","bun","php"],description:"Application kind (drives packaging + runtime)"},entry:{type:"string",description:"Entry file exporting the request handler"},memory:{type:"number",description:"HTTP function memory in MB"},timeout:{type:"number",description:"HTTP request timeout in seconds"},gatewayVersion:{type:"number",enum:[1,2],description:"API Gateway version (2 = HTTP API, 1 = REST)"},warm:{type:"number",description:"Keep-warm / provisioned concurrency count"},lambdaInsights:{type:"object",description:"CloudWatch Lambda Insights extension configuration for zip deployments",required:["layerArn"],properties:{layerArn:{type:"string",description:"Region- and architecture-specific Lambda Insights extension layer ARN"}}},queues:{description:"Queue names (true = single default queue, false = disabled)"},scheduler:{type:"string",enum:["off","on","sub-minute"],description:"Task scheduler mode"},build:{type:"array",items:{type:"string"},description:"Commands run locally before packaging"},deploy:{type:"array",items:{type:"string"},description:"Commands run remotely after activation (e.g. migrations)"},octane:{type:"boolean",description:"Persistent application mode (Laravel Octane)"},packaging:{type:"string",enum:["zip","image"],description:"Deployment package format (zip or container image)"},phpVersion:{type:"string",description:"PHP version for the runtime layer (kind: php)"},architecture:{type:"string",enum:["x86_64","arm64"],description:"CPU architecture"}}}}},network:{type:"object",properties:{vpc:{type:"object",properties:{cidr:{type:"string",description:"VPC CIDR block",pattern:"^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]{1,2}$",default:"10.0.0.0/16"},availabilityZones:{type:"number",description:"Number of availability zones",minimum:1,maximum:3,default:2},natGateways:{type:"number",description:"Number of NAT gateways (0 for no NAT, saves cost)",minimum:0,maximum:3,default:1}}}}},storage:{type:"object",properties:{public:{type:"boolean",description:"Allow public access",default:!1},versioning:{type:"boolean",description:"Enable versioning",default:!1},encryption:{type:"boolean",description:"Enable server-side encryption",default:!0},website:{type:"boolean",description:"Enable static website hosting",default:!1},cors:{type:"object",description:"CORS configuration",properties:{allowedOrigins:{type:"array",items:{type:"string"}},allowedMethods:{type:"array",items:{type:"string",enum:["GET","PUT","POST","DELETE","HEAD"]}}}}}},compute:{type:"object",properties:{server:{type:"object",description:"EC2 server configuration",properties:{instanceType:{type:"string",description:"EC2 instance type",enum:["t3.micro","t3.small","t3.medium","t3.large","t3.xlarge","t3.2xlarge"]},autoScaling:{type:"object",properties:{min:{type:"number",minimum:1},max:{type:"number",minimum:1},desired:{type:"number",minimum:1}}}}},fargate:{type:"object",description:"ECS Fargate configuration",properties:{cpu:{type:"number",description:"CPU units (256, 512, 1024, 2048, 4096)",enum:[256,512,1024,2048,4096]},memory:{type:"number",description:"Memory in MB"},desiredCount:{type:"number",description:"Desired number of tasks",minimum:1}}}}},database:{type:"object",properties:{postgres:{type:"object",properties:{instanceClass:{type:"string",description:"RDS instance class",pattern:"^db\\.[a-z0-9]+\\.[a-z0-9]+$"},engine:{type:"string",const:"postgres"},version:{type:"string",description:"PostgreSQL version"},multiAZ:{type:"boolean",description:"Enable Multi-AZ deployment",default:!1},backupRetentionDays:{type:"number",description:"Backup retention period in days",minimum:0,maximum:35,default:7}}},mysql:{type:"object",properties:{instanceClass:{type:"string",pattern:"^db\\.[a-z0-9]+\\.[a-z0-9]+$"},engine:{type:"string",const:"mysql"},version:{type:"string"},multiAZ:{type:"boolean",default:!1},backupRetentionDays:{type:"number",minimum:0,maximum:35,default:7}}},dynamodb:{type:"object",properties:{tables:{type:"array",items:{type:"object",required:["name","partitionKey"],properties:{name:{type:"string"},partitionKey:{type:"string"},sortKey:{type:"string"},billingMode:{type:"string",enum:["PAY_PER_REQUEST","PROVISIONED"],default:"PAY_PER_REQUEST"}}}}}}}},cache:{type:"object",properties:{redis:{type:"object",properties:{nodeType:{type:"string",description:"ElastiCache node type",pattern:"^cache\\.[a-z0-9]+\\.[a-z0-9]+$"},numCacheNodes:{type:"number",minimum:1,default:1},engineVersion:{type:"string",description:"Redis engine version"}}},memcached:{type:"object",properties:{nodeType:{type:"string",pattern:"^cache\\.[a-z0-9]+\\.[a-z0-9]+$"},numCacheNodes:{type:"number",minimum:1,default:1}}}}},cdn:{type:"object",properties:{enabled:{type:"boolean",default:!0},originShield:{type:"boolean",description:"Enable CloudFront Origin Shield",default:!1},originShieldRegion:{type:"string",description:"AWS region used by CloudFront Origin Shield"},compress:{type:"boolean",description:"Enable automatic compression",default:!0},http3:{type:"boolean",description:"Enable HTTP/3 support",default:!0},customDomain:{type:"object",properties:{domain:{type:"string"},certificateArn:{type:"string"}}},cachePolicy:{type:"object",properties:{minTTL:{type:"number",minimum:0},defaultTTL:{type:"number",minimum:0},maxTTL:{type:"number",minimum:0}}}}},sftp:{type:"object",required:["bucket","users"],properties:{bucket:{type:"string",description:"S3 bucket backing the SFTP server"},endpointType:{type:"string",enum:["PUBLIC","VPC"],default:"PUBLIC"},endpointDetails:{type:"object",required:["vpcId","subnetIds"],properties:{vpcId:{type:"string"},subnetIds:{type:"array",items:{type:"string"},minItems:1},securityGroupIds:{type:"array",items:{type:"string"}},addressAllocationIds:{type:"array",items:{type:"string"}}}},securityPolicyName:{type:"string"},logging:{type:"boolean",default:!0},users:{type:"object",additionalProperties:{type:"object",required:["sshPublicKeys"],properties:{sshPublicKeys:{type:"array",items:{type:"string"},minItems:1},homeDirectory:{type:"string"},roleArn:{type:"string"}}}}}},function:{type:"object",required:["name","runtime"],properties:{name:{type:"string"},runtime:{type:"string",enum:["nodejs18.x","nodejs20.x","python3.10","python3.11","python3.12"]},handler:{type:"string",default:"index.handler"},timeout:{type:"number",minimum:1,maximum:900,default:30},memory:{type:"number",minimum:128,maximum:10240,default:1024}}},monitoring:{type:"object",properties:{alarms:{type:"array",items:{type:"object",required:["metric","threshold"],properties:{metric:{type:"string"},threshold:{type:"number"},evaluationPeriods:{type:"number",minimum:1,default:2}}}},dashboard:{type:"object",properties:{name:{type:"string"},widgets:{type:"array"}}}}},security:{type:"object",properties:{waf:{type:"boolean",description:"Enable AWS WAF",default:!1},certificates:{type:"array",items:{type:"object",required:["domain"],properties:{domain:{type:"string"},subdomains:{type:"array",items:{type:"string"}}}}}}},queue:{type:"object",properties:{fifo:{type:"boolean",default:!1},deadLetterQueue:{type:"boolean",default:!0},visibilityTimeout:{type:"number",minimum:0,maximum:43200,default:30},messageRetentionPeriod:{type:"number",minimum:60,maximum:1209600,default:345600}}}}};function US(n){let i=[];if(!n.project)i.push("Missing required field: project");else{if(!n.project.name)i.push("Missing required field: project.name");if(!n.project.slug)i.push("Missing required field: project.slug")}if(n.project?.slug&&!/^[a-z0-9-]+$/.test(n.project.slug))i.push("Invalid project.slug: must contain only lowercase letters, numbers, and hyphens");let s=["us-east-1","us-east-2","us-west-1","us-west-2","eu-west-1","eu-west-2","eu-west-3","eu-central-1","ap-southeast-1","ap-southeast-2","ap-northeast-1","ap-northeast-2","sa-east-1","ca-central-1"];if(n.project?.region&&!s.includes(n.project.region))i.push(`Invalid region: ${n.project.region}. Must be one of: ${s.join(", ")}`);if(n.mode&&!["server","serverless"].includes(n.mode))i.push("Invalid mode: must be one of server or serverless");return{valid:i.length===0,errors:i}}var xg={enabled:process.env.TS_CLOUD_LOCAL==="true"||!0,localstackEndpoint:process.env.LOCALSTACK_ENDPOINT||"http://localhost:4566",postgresUrl:process.env.POSTGRES_URL||"postgresql://tscloud:tscloud@localhost:5432/tscloud",redisUrl:process.env.REDIS_URL||"redis://localhost:6379",dynamodbEndpoint:process.env.DYNAMODB_ENDPOINT||"http://localhost:8000",s3Endpoint:process.env.S3_ENDPOINT||"http://localhost:9000",emailEndpoint:process.env.EMAIL_ENDPOINT||"smtp://localhost:1025",awsRegion:process.env.AWS_REGION||"us-east-1",awsAccessKeyId:process.env.AWS_ACCESS_KEY_ID||"test",awsSecretAccessKey:process.env.AWS_SECRET_ACCESS_KEY||"test"};function Qd(){return xg}function QS(){return xg.enabled}function HS(n){let i=Qd();if(!i.enabled)return"";switch(n.toLowerCase()){case"dynamodb":return i.dynamodbEndpoint;case"s3":return i.s3Endpoint;case"localstack":case"cloudformation":case"lambda":case"apigateway":case"sns":case"sqs":case"cloudwatch":case"iam":case"sts":return i.localstackEndpoint;default:return i.localstackEndpoint}}function GS(){let n=Qd();return{accessKeyId:n.awsAccessKeyId,secretAccessKey:n.awsSecretAccessKey,region:n.awsRegion}}function qS(){let n=Qd();if(!n.enabled)return{};return{AWS_ACCESS_KEY_ID:n.awsAccessKeyId,AWS_SECRET_ACCESS_KEY:n.awsSecretAccessKey,AWS_REGION:n.awsRegion,AWS_ENDPOINT_URL:n.localstackEndpoint,LOCALSTACK_ENDPOINT:n.localstackEndpoint,TS_CLOUD_LOCAL:"true"}}class Lg{stacks=new Map;stackEvents=new Map;async createStack(n){let i=`arn:aws:cloudformation:${n.region||"us-east-1"}:123456789012:stack/${n.StackName}/${Date.now()}`;return this.stacks.set(n.StackName,{StackId:i,StackName:n.StackName,StackStatus:"CREATE_IN_PROGRESS",CreationTime:new Date().toISOString(),TemplateBody:n.TemplateBody,Parameters:n.Parameters||[]}),this.addEvent(n.StackName,{EventId:Date.now().toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_IN_PROGRESS"}),setTimeout(()=>{let s=this.stacks.get(n.StackName);if(s)s.StackStatus="CREATE_COMPLETE",this.addEvent(n.StackName,{EventId:(Date.now()+1).toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_COMPLETE"})},100),{StackId:i}}async updateStack(n){let i=this.stacks.get(n.StackName);if(!i)throw Error(`Stack ${n.StackName} does not exist`);return i.StackStatus="UPDATE_IN_PROGRESS",i.TemplateBody=n.TemplateBody||i.TemplateBody,this.addEvent(n.StackName,{EventId:Date.now().toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_IN_PROGRESS"}),setTimeout(()=>{i.StackStatus="UPDATE_COMPLETE",this.addEvent(n.StackName,{EventId:(Date.now()+1).toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_COMPLETE"})},100),{StackId:i.StackId}}async deleteStack(n){let i=this.stacks.get(n.StackName);if(!i)throw Error(`Stack ${n.StackName} does not exist`);i.StackStatus="DELETE_IN_PROGRESS",this.addEvent(n.StackName,{EventId:Date.now().toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_IN_PROGRESS"}),setTimeout(()=>{this.stacks.delete(n.StackName),this.addEvent(n.StackName,{EventId:(Date.now()+1).toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_COMPLETE"})},100)}async describeStacks(n){if(n.StackName){let i=this.stacks.get(n.StackName);if(!i)throw Error(`Stack ${n.StackName} does not exist`);return{Stacks:[i]}}return{Stacks:Array.from(this.stacks.values())}}async describeStackEvents(n){return{StackEvents:this.stackEvents.get(n.StackName)||[]}}addEvent(n,i){if(!this.stackEvents.has(n))this.stackEvents.set(n,[]);this.stackEvents.get(n).unshift(i)}reset(){this.stacks.clear(),this.stackEvents.clear()}}class $g{buckets=new Map;async createBucket(n){return this.buckets.set(n.Bucket,new Map),{Location:`/${n.Bucket}`}}async deleteBucket(n){this.buckets.delete(n.Bucket)}async putObject(n){let i=this.buckets.get(n.Bucket);if(!i)i=new Map,this.buckets.set(n.Bucket,i);return i.set(n.Key,Buffer.from(n.Body||"")),{ETag:`"${Date.now()}"`}}async getObject(n){let i=this.buckets.get(n.Bucket);if(!i)throw Error(`Bucket ${n.Bucket} does not exist`);let s=i.get(n.Key);if(!s)throw Error(`Object ${n.Key} does not exist`);return{Body:s,ContentLength:s.length}}async deleteObject(n){let i=this.buckets.get(n.Bucket);if(i)i.delete(n.Key)}async listObjects(n){let i=this.buckets.get(n.Bucket);if(!i)throw Error(`Bucket ${n.Bucket} does not exist`);return{Contents:Array.from(i.keys()).map((s)=>({Key:s,Size:i.get(s).length,LastModified:new Date().toISOString()}))}}reset(){this.buckets.clear()}}class Mg{tables=new Map;data=new Map;async createTable(n){return this.tables.set(n.TableName,{TableName:n.TableName,KeySchema:n.KeySchema,AttributeDefinitions:n.AttributeDefinitions,TableStatus:"ACTIVE",CreationDateTime:new Date().toISOString()}),this.data.set(n.TableName,new Map),{TableDescription:this.tables.get(n.TableName)}}async deleteTable(n){this.tables.delete(n.TableName),this.data.delete(n.TableName)}async putItem(n){let i=this.data.get(n.TableName);if(!i)i=new Map,this.data.set(n.TableName,i);let s=JSON.stringify(n.Item);i.set(s,n.Item)}async getItem(n){let i=this.data.get(n.TableName);if(!i)return{};let s=JSON.stringify(n.Key),o=i.get(s);return o?{Item:o}:{}}async deleteItem(n){let i=this.data.get(n.TableName);if(i){let s=JSON.stringify(n.Key);i.delete(s)}}async scan(n){let i=this.data.get(n.TableName);if(!i)return{Items:[]};return{Items:Array.from(i.values())}}reset(){this.tables.clear(),this.data.clear()}}function VS(n){return{cloudformation:new Lg,s3:new $g,dynamodb:new Mg}}class Fg{environments=new Map;async createPreviewEnvironment(n){let{branch:i,pr:s,commitSha:o,ttl:c=24,baseConfig:l,region:u="us-east-1"}=n,h=this.generatePreviewId(i,s,o),f=this.generatePreviewName(i,s),S=`preview-${f}`,b=new Date,A=new Date(b.getTime()+c*60*60*1000),v={id:h,name:f,branch:i,pr:s,commitSha:o,createdAt:b,expiresAt:A,status:"creating",stackName:S,region:u,resources:[]};this.environments.set(h,v);try{let w=this.createPreviewConfig(l,f);return v.status="active",v.url=`https://${f}.preview.example.com`,v}catch(w){throw v.status="failed",w}}async destroyPreviewEnvironment(n){let i=this.environments.get(n);if(!i)throw Error(`Preview environment ${n} not found`);i.status="destroying";try{i.status="destroyed",this.environments.delete(n)}catch(s){throw Error(`Failed to destroy preview environment: ${s}`)}}getPreviewEnvironment(n){return this.environments.get(n)}getPreviewEnvironmentByBranch(n){return Array.from(this.environments.values()).find((i)=>i.branch===n)}getPreviewEnvironmentByPR(n){return Array.from(this.environments.values()).find((i)=>i.pr===n)}listPreviewEnvironments(){return Array.from(this.environments.values())}listActivePreviewEnvironments(){return this.listPreviewEnvironments().filter((n)=>n.status==="active")}async cleanupExpiredEnvironments(n={}){let{maxAge:i,keepCount:s,dryRun:o=!1}=n,c=[],l=[],u=new Date,h=this.listPreviewEnvironments().sort((f,S)=>S.createdAt.getTime()-f.createdAt.getTime());for(let f=0;f<h.length;f++){let S=h[f];if(S.status!=="active")continue;let b=!1;if(S.expiresAt<u)b=!0;if(i){if((u.getTime()-S.createdAt.getTime())/3600000>i)b=!0}if(s&&f>=s)b=!0;if(b)if(o)c.push(S.id);else try{await this.destroyPreviewEnvironment(S.id),c.push(S.id)}catch(A){l.push(S.id)}}return{destroyed:c,failed:l}}async updatePreviewEnvironment(n,i){let s=this.environments.get(n);if(!s)throw Error(`Preview environment ${n} not found`);s.commitSha=i,s.status="creating";try{return s.status="active",s}catch(o){throw s.status="failed",o}}async getPreviewEnvironmentsCost(){let n={},i=0;for(let s of this.environments.values())n[s.id]=0,i+=0;return{total:i,byEnvironment:n}}generatePreviewId(n,i,s){let o=n.replace(/[^a-z0-9-]/gi,"-").toLowerCase(),c=s?.substring(0,7)||Date.now().toString();return i?`pr-${i}-${c}`:`${o}-${c}`}generatePreviewName(n,i){let s=n.replace(/[^a-z0-9-]/gi,"-").toLowerCase();return i?`pr-${i}`:s}createPreviewConfig(n,i){return{...n,project:{...n.project,name:`${n.project.name} Preview (${i})`,slug:`${n.project.slug}-preview-${i}`}}}}var jS=new Fg;function zS(n={}){let{workflowName:i="Preview Environment",trigger:s="pull_request",branches:o=["main","develop"],awsRegion:c="us-east-1",awsRole:l,configFile:u="cloud.config.ts",ttl:h=24}=n;return`name: ${i}
|
|
2513
2513
|
|
|
2514
2514
|
on:
|
|
2515
2515
|
${s}:
|
|
@@ -2762,7 +2762,7 @@ ${i.map((s)=>` • ${s}`).join(`
|
|
|
2762
2762
|
`)}importJSON(n){let i=JSON.parse(n).map((s)=>({...s,timestamp:new Date(s.timestamp)}));if(this.entries.push(...i),this.entries.length>this.maxSize)this.entries=this.entries.slice(-this.maxSize)}groupByDate(){let n=new Map;for(let i of this.entries){let s=i.timestamp.toISOString().split("T")[0];if(!n.has(s))n.set(s,[]);n.get(s).push(i)}return n}groupByCommand(){let n=new Map;for(let i of this.entries){let s=i.command.split(" ")[0];if(!n.has(s))n.set(s,[]);n.get(s).push(i)}return n}replay(n){return this.getByIndex(n)?.command}getSuggestions(n,i=5){let s=n.toLowerCase(),o=this.entries.filter((c)=>c.command.toLowerCase().startsWith(s)).map((c)=>c.command);return[...new Set(o)].slice(0,i)}analyzePatterns(){let n=new Map,i=new Map;for(let o of this.entries){let c=o.timestamp.getHours(),l=o.timestamp.getDay();n.set(c,(n.get(c)||0)+1),i.set(l,(i.get(l)||0)+1)}let s=this.entries.length>0?this.getSuccessful().length/this.entries.length:0;return{timeOfDay:n,dayOfWeek:i,successRate:s}}}function gC(n,i={}){let{maxWidth:s=100}=i;if(n.length===0)return"No command history";let o=[];for(let c=0;c<n.length;c++){let l=n[c],u=(c+1).toString().padStart(4),h=l.timestamp.toLocaleString(),f=l.success?"✓":"✗",S=l.command;if(S.length>s-30)S=S.substring(0,s-33)+"...";let b=`${u} ${h} ${f} ${S}`;if(l.duration)b+=` (${l.duration}ms)`;o.push(b)}return o.join(`
|
|
2763
2763
|
`)}function mC(n){let i=[];return i.push("Command History Statistics"),i.push("─".repeat(30)),i.push(`Total commands: ${n.total}`),i.push(`Successful: ${n.successful}`),i.push(`Failed: ${n.failed}`),i.push(`Success rate: ${(n.successful/n.total*100).toFixed(1)}%`),i.push(`Average duration: ${n.averageDuration.toFixed(0)}ms`),i.push(`Most used: ${n.mostUsed}`),i.join(`
|
|
2764
2764
|
`)}class Hg{deployments=new Map;async deploy(n,i){let s=this.generateDeploymentId(),o={id:s,regions:i.regions.map((c)=>({region:c.code,stackName:this.getStackName(n,c.code),status:"pending"})),status:"deploying",startTime:new Date};this.deployments.set(s,o);try{let c=i.regions.find((u)=>u.isPrimary)||i.regions[0];await this.deployToRegion(n,c,o);let l=i.regions.filter((u)=>u.code!==c.code);if(await Promise.all(l.map((u)=>this.deployToRegion(n,u,o))),i.globalResources)await this.deployGlobalResources(o,i);if(i.replication)await this.setupReplication(o,i);if(i.failover?.enabled)await this.setupFailover(o,i);return o.status="deployed",o.endTime=new Date,o}catch(c){throw o.status="failed",o.endTime=new Date,c}}async deployToRegion(n,i,s){let o=s.regions.find((c)=>c.region===i.code);if(!o)throw Error(`Region deployment not found: ${i.code}`);o.status="deploying",o.startTime=new Date;try{let c=this.createRegionConfig(n,i);await this.deployStack(o.stackName,c,i.code),o.status="deployed",o.endTime=new Date,o.outputs={stackId:`arn:aws:cloudformation:${i.code}:123456789012:stack/${o.stackName}/guid`,endpoint:`https://${o.stackName}.${i.code}.example.com`}}catch(c){throw o.status="failed",o.endTime=new Date,o.error=c instanceof Error?c.message:String(c),c}}async deployGlobalResources(n,i){let s={};if(i.globalResources?.route53)s.route53=await this.deployRoute53(n,i);if(i.globalResources?.cloudfront)s.cloudfront=await this.deployCloudFront(n,i);if(i.globalResources?.waf)s.waf=await this.deployWAF(n);n.globalResources=s}async deployRoute53(n,i){let s=[],o=[];for(let c of n.regions){if(c.status!=="deployed")continue;let l={id:`health-${c.region}`,endpoint:c.outputs?.endpoint,path:i.failover?.healthCheckPath||"/health",region:c.region};s.push(l);let u={name:"example.com",type:"A",region:c.region,setIdentifier:c.region,healthCheckId:l.id,resourceRecords:[c.outputs?.endpoint]};o.push(u)}return{healthChecks:s,recordSets:o,hostedZoneId:"Z1234567890ABC"}}async deployCloudFront(n,i){return{distributionId:"E1234567890ABC",domainName:"d1234567890abc.cloudfront.net",origins:n.regions.filter((s)=>s.status==="deployed").map((s,o)=>{let c=i.regions[o];return{id:`origin-${s.region}`,domainName:s.outputs?.endpoint,weight:c?.weight||100}}),status:"Deployed"}}async deployWAF(n){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(n,i){if(i.replication?.s3)await this.setupS3Replication(n);if(i.replication?.dynamodb)await this.setupDynamoDBReplication(n);if(i.replication?.secrets)await this.setupSecretsReplication(n)}async setupS3Replication(n){let i=n.regions.filter((s)=>s.status==="deployed");for(let s=0;s<i.length-1;s++){let o=i[s],c=i[s+1];console.log(`Setting up S3 replication: ${o.region} -> ${c.region}`)}}async setupDynamoDBReplication(n){let i=n.regions.filter((s)=>s.status==="deployed").map((s)=>s.region);console.log(`Setting up DynamoDB global table in regions: ${i.join(", ")}`)}async setupSecretsReplication(n){let i=n.regions.filter((s)=>s.status==="deployed").map((s)=>s.region);console.log(`Setting up Secrets Manager replication in regions: ${i.join(", ")}`)}async setupFailover(n,i){let s=n.regions.find((c,l)=>i.regions[l]?.isPrimary)||n.regions[0],o=n.regions.filter((c)=>c.region!==s.region);console.log(`Setting up failover: primary=${s.region}, secondary=${o.map((c)=>c.region).join(", ")}`)}async destroy(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);i.status="rolling-back";try{if(i.globalResources)await this.destroyGlobalResources(i.globalResources);await Promise.all(i.regions.map((s)=>this.destroyRegionStack(s))),this.deployments.delete(n)}catch(s){throw i.status="failed",s}}async destroyGlobalResources(n){if(n.waf)console.log("Destroying WAF resources");if(n.cloudfront)console.log("Destroying CloudFront distribution");if(n.route53)console.log("Destroying Route53 resources")}async destroyRegionStack(n){if(n.status!=="deployed")return;n.status="rolling-back";try{console.log(`Destroying stack ${n.stackName} in ${n.region}`),n.status="pending"}catch(i){throw n.status="failed",n.error=i instanceof Error?i.message:String(i),i}}getDeployment(n){return this.deployments.get(n)}listDeployments(){return Array.from(this.deployments.values())}getStackName(n,i){return`${n.project.slug}-${i}`}createRegionConfig(n,i){return{...n,infrastructure:{...n.infrastructure}}}async deployStack(n,i,s){console.log(`Deploying stack ${n} to ${s}`)}generateDeploymentId(){return`deploy-${Date.now()}-${Math.random().toString(36).substring(7)}`}}var hC=new Hg;class Gg{references=[];exports=new Map;addExport(n){let i=`${n.region}:${n.exportName}`;if(!this.exports.has(n.region))this.exports.set(n.region,[]);this.exports.get(n.region).push(n)}getExport(n,i){let s=this.exports.get(n);if(!s)return;return s.find((o)=>o.exportName===i)?.value}createReference(n,i,s,o){let c=`/cross-region/${n}/${s}/${o}`;return this.references.push({sourceRegion:n,targetRegion:i,resourceType:s,resourceId:o,value:c}),c}async resolveReference(n,i){let s=this.references.find((o)=>o.targetRegion===n&&o.value===i);if(!s)throw Error(`Reference not found: ${i}`);return`arn:aws:resource:${s.sourceRegion}:123456789012:${s.resourceType}/${s.resourceId}`}getReferencesForRegion(n){return this.references.filter((i)=>i.sourceRegion===n||i.targetRegion===n)}clear(){this.references=[],this.exports.clear()}}class qg{resources=new Map;register(n){this.resources.set(n.id,n)}get(n){return this.resources.get(n)}getByType(n){return Array.from(this.resources.values()).filter((i)=>i.type===n)}getCloudFrontDistributions(){return this.getByType("cloudfront")}getRoute53HostedZones(){return this.getByType("route53")}getWAFWebACLs(){return this.getByType("waf")}remove(n){this.resources.delete(n)}clear(){this.resources.clear()}}class Vg{pairs=[];addPair(n){this.pairs.push(n)}getPairedRegion(n){let i=this.pairs.find((s)=>s.primary===n||s.secondary===n);if(!i)return;return i.primary===n?i.secondary:i.primary}getAllPairs(){return[...this.pairs]}getReplicatedPairs(){return this.pairs.filter((n)=>n.replicationConfig)}getFailoverPairs(){return this.pairs.filter((n)=>n.failoverConfig?.automatic)}arePaired(n,i){return this.pairs.some((s)=>s.primary===n&&s.secondary===i||s.primary===i&&s.secondary===n)}clear(){this.pairs=[]}}class jg{dependencies=[];addDependency(n){this.dependencies.push(n)}getDependencies(n,i){return this.dependencies.filter((s)=>s.dependentStack===n&&s.dependentRegion===i)}getDependents(n,i){return this.dependencies.filter((s)=>s.dependsOnStack===n&&s.dependsOnRegion===i)}hasDependencies(n,i){return this.getDependencies(n,i).length>0}getDeploymentOrder(n){let i=new Set,s=[],o=(c)=>{let l=`${c.name}:${c.region}`;if(i.has(l))return;i.add(l);let u=this.getDependencies(c.name,c.region);for(let h of u)o({name:h.dependsOnStack,region:h.dependsOnRegion});s.push(c)};for(let c of n)o(c);return s}detectCircularDependencies(){let n=new Set,i=new Set,s=(o,c)=>{let l=`${o}:${c}`;if(i.has(l))return!0;if(n.has(l))return!1;n.add(l),i.add(l);let u=this.getDependencies(o,c);for(let h of u)if(s(h.dependsOnStack,h.dependsOnRegion))return!0;return i.delete(l),!1};for(let o of this.dependencies)if(s(o.dependentStack,o.dependentRegion))return!0;return!1}clear(){this.dependencies=[]}}var fC=new Gg,AC=new qg,yC=new Vg,IC=new jg,Ne=[{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 Bi(n){return Ne.find((i)=>i.code===n)}function SC(){return Ne}function CC(n){let i=n.toLowerCase();return Ne.filter((s)=>s.location.toLowerCase().includes(i))}function EC(n){return Ne.filter((i)=>i.compliance.includes(n))}function bC(n){return Ne.filter((i)=>i.pricing.tier===n)}function vC(n){return Ne.some((i)=>i.code===n)}function TC(n){if(n.continent==="North America")return Bi("us-east-1");if(n.continent==="Europe")return Bi("eu-west-1");if(n.continent==="Asia")return Bi("ap-southeast-1");return Bi("us-east-1")}function wC(n){let i=[...Ne];if(n.compliance)i=i.filter((s)=>n.compliance.every((o)=>s.compliance.includes(o)));if(n.requiredServices)i=i.filter((s)=>n.requiredServices.every((o)=>s.services[o]));if(n.pricingSensitive)i.sort((s,o)=>s.pricing.multiplier-o.pricing.multiplier);return i.slice(0,5)}function RC(n){let i=Bi(n);if(!i)throw Error(`Invalid region: ${n}`);let s=[];for(let o of Ne){if(o.code===n)continue;let c=jn(i,o),l=Kn(i,o);s.push({primary:i,secondary:o,distance:c,sameContinent:l})}return s.sort((o,c)=>{if(o.sameContinent!==c.sameContinent)return o.sameContinent?1:-1;return o.distance-c.distance}),s.slice(0,3)}function jn(n,i){let s={"North America":0,"South America":1,Europe:2,Asia:3,Africa:4,Oceania:5},o=at(n.location),c=at(i.location);return Math.abs((s[o]||0)-(s[c]||0))}function Kn(n,i){return at(n.location)===at(i.location)}function at(n){if(n.includes("USA")||n.includes("Canada"))return"North America";if(n.includes("Europe")||n.includes("Ireland")||n.includes("Germany"))return"Europe";if(n.includes("Asia")||n.includes("Singapore")||n.includes("Japan"))return"Asia";if(n.includes("Brazil"))return"South America";if(n.includes("Australia"))return"Oceania";return"Unknown"}function qA(n){return`${n.name} (${n.code})`}function DC(n){return n.map((i)=>qA(i)).join(`
|
|
2765
|
-
`)}function PC(){let n={total:Ne.length,byContinent:{},byPricingTier:{}};for(let i of Ne){let s=at(i.location);n.byContinent[s]=(n.byContinent[s]||0)+1,n.byPricingTier[i.pricing.tier]=(n.byPricingTier[i.pricing.tier]||0)+1}return n}class zg{accounts=new Map;crossAccountRoles=[];accountMappings=[];registerAccount(n){this.accounts.set(n.id,n)}getAccount(n){return this.accounts.get(n)}getAccountByAlias(n){return Array.from(this.accounts.values()).find((i)=>i.alias===n)}listAccounts(){return Array.from(this.accounts.values())}getAccountsByRole(n){return Array.from(this.accounts.values()).filter((i)=>i.role===n)}createCrossAccountRole(n,i,s,o,c){let l={roleArn:`arn:aws:iam::${i}:role/${s}`,roleName:s,sourceAccountId:n,targetAccountId:i,permissions:o,externalId:c?.externalId,sessionDuration:c?.sessionDuration||3600};return this.crossAccountRoles.push(l),l}getAssumeRolePolicyDocument(n,i){let s={Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${n}:root`},Action:"sts:AssumeRole"}]};if(i)s.Statement[0].Condition={StringEquals:{"sts:ExternalId":i}};return s}generateCrossAccountPolicy(n){return{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:n,Resource:"*"}]}}mapEnvironmentToAccount(n,i,s){this.accountMappings.push({environment:n,accountId:i,region:s})}getAccountForEnvironment(n){return this.accountMappings.find((i)=>i.environment===n)}async assumeRole(n,i,s){return console.log(`Assuming role: ${n} with session: ${i}`),{accessKeyId:"AKIAIOSFODNN7EXAMPLE",secretAccessKey:"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",sessionToken:"token",expiration:new Date(Date.now()+3600000)}}async getCredentialsForAccount(n){let i=this.accounts.get(n);if(!i)throw Error(`Account not found: ${n}`);if(i.assumeRoleArn){let s=await this.assumeRole(i.assumeRoleArn,`ts-cloud-${Date.now()}`);return{accessKeyId:s.accessKeyId,secretAccessKey:s.secretAccessKey,sessionToken:s.sessionToken}}throw Error("No credentials available for account")}listCrossAccountRoles(){return[...this.crossAccountRoles]}getCrossAccountRolesForAccount(n){return this.crossAccountRoles.filter((i)=>i.sourceAccountId===n||i.targetAccountId===n)}async validateAccountAccess(n){try{let i=await this.getCredentialsForAccount(n);return console.log(`Validating access to account: ${n}`),!0}catch{return!1}}async getConsolidatedBilling(){let n={};for(let i of this.accounts.values())n[i.id]=Math.random()*1000;return{totalCost:Object.values(n).reduce((i,s)=>i+s,0),byAccount:n}}clear(){this.accounts.clear(),this.crossAccountRoles=[],this.accountMappings=[]}}class Kg{organizationId;organizationalUnits=new Map;getOrganizationId(){return this.organizationId}setOrganizationId(n){this.organizationId=n}createOrganizationalUnit(n,i){let s={id:`ou-${Date.now()}`,name:n,parentId:i,accounts:[]};return this.organizationalUnits.set(s.id,s),s}getOrganizationalUnit(n){return this.organizationalUnits.get(n)}listOrganizationalUnits(){return Array.from(this.organizationalUnits.values())}addAccountToOU(n,i){let s=this.organizationalUnits.get(n);if(!s)throw Error(`Organizational unit not found: ${n}`);if(!s.accounts.includes(i))s.accounts.push(i)}removeAccountFromOU(n,i){let s=this.organizationalUnits.get(n);if(!s)throw Error(`Organizational unit not found: ${n}`);s.accounts=s.accounts.filter((o)=>o!==i)}getAccountsInOU(n){let i=this.organizationalUnits.get(n);if(!i)return[];return[...i.accounts]}applyServiceControlPolicy(n,i){return{id:`scp-${Date.now()}`,name:"Custom SCP",targetId:n,policyDocument:i}}clear(){this.organizationId=void 0,this.organizationalUnits.clear()}}var NC=new zg,kC=new Kg,VA={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"}]}},BC={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"]}}}]}}},_C={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 xC(n){return VA[n]}function OC(n,i){return{Type:"AWS::IAM::Role",Properties:{RoleName:n.roleName,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${n.sourceAccountId}:root`},Action:"sts:AssumeRole",...n.externalId&&{Condition:{StringEquals:{"sts:ExternalId":n.externalId}}}}]},Policies:[{PolicyName:`${n.roleName}Policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:n.permissions,Resource:"*"}]}}],...i&&{ManagedPolicyArns:i},MaxSessionDuration:n.sessionDuration||3600,Tags:[{Key:"ManagedBy",Value:"TS-Cloud"},{Key:"SourceAccount",Value:n.sourceAccountId}]}}}function LC(n){let i=[],s=[],o=n.accounts.filter((f)=>f.role==="management");if(o.length===0)i.push("No management account defined");if(o.length>1)i.push("Multiple management accounts defined");let c=n.accounts.map((f)=>f.email),l=c.filter((f,S)=>c.indexOf(f)!==S);if(l.length>0)i.push(`Duplicate email addresses: ${l.join(", ")}`);let u=n.accounts.map((f)=>f.alias),h=u.filter((f,S)=>u.indexOf(f)!==S);if(h.length>0)i.push(`Duplicate aliases: ${h.join(", ")}`);if(!n.accounts.some((f)=>f.role==="security"))s.push("No dedicated security account - consider adding one for audit logs");if(n.accounts.length<3)s.push("Less than 3 accounts - consider separating environments");if(!n.accounts.some((f)=>f.role==="production"))s.push("No production account defined");return{valid:i.length===0,errors:i,warnings:s}}function $C(n){let i=[];if(i.push(`${n.name}`),i.push("─".repeat(n.name.length)),i.push(n.description),i.push(""),n.organizationalUnits){i.push("Organizational Units:");for(let s of n.organizationalUnits){let o=s.parent?" └─ ":" ";i.push(`${o}${s.name}`)}i.push("")}i.push("Accounts:");for(let s of n.accounts)i.push(` ${s.alias.padEnd(20)} ${s.role.padEnd(15)} ${s.email}`),i.push(` ${"".padEnd(20)} ${s.description}`),i.push("");return i.join(`
|
|
2765
|
+
`)}function PC(){let n={total:Ne.length,byContinent:{},byPricingTier:{}};for(let i of Ne){let s=at(i.location);n.byContinent[s]=(n.byContinent[s]||0)+1,n.byPricingTier[i.pricing.tier]=(n.byPricingTier[i.pricing.tier]||0)+1}return n}class zg{accounts=new Map;crossAccountRoles=[];accountMappings=[];registerAccount(n){this.accounts.set(n.id,n)}getAccount(n){return this.accounts.get(n)}getAccountByAlias(n){return Array.from(this.accounts.values()).find((i)=>i.alias===n)}listAccounts(){return Array.from(this.accounts.values())}getAccountsByRole(n){return Array.from(this.accounts.values()).filter((i)=>i.role===n)}createCrossAccountRole(n,i,s,o,c){let l={roleArn:`arn:aws:iam::${i}:role/${s}`,roleName:s,sourceAccountId:n,targetAccountId:i,permissions:o,externalId:c?.externalId,sessionDuration:c?.sessionDuration||3600};return this.crossAccountRoles.push(l),l}getAssumeRolePolicyDocument(n,i){let s={Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${n}:root`},Action:"sts:AssumeRole"}]};if(i)s.Statement[0].Condition={StringEquals:{"sts:ExternalId":i}};return s}generateCrossAccountPolicy(n){return{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:n,Resource:"*"}]}}mapEnvironmentToAccount(n,i,s){this.accountMappings.push({environment:n,accountId:i,region:s})}getAccountForEnvironment(n){return this.accountMappings.find((i)=>i.environment===n)}async assumeRole(n,i,s){return console.log(`Assuming role: ${n} with session: ${i}`),{accessKeyId:"AKIAIOSFODNN7EXAMPLE",secretAccessKey:"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",sessionToken:"token",expiration:new Date(Date.now()+3600000)}}async getCredentialsForAccount(n){let i=this.accounts.get(n);if(!i)throw Error(`Account not found: ${n}`);if(i.assumeRoleArn){let s=await this.assumeRole(i.assumeRoleArn,`ts-cloud-${Date.now()}`);return{accessKeyId:s.accessKeyId,secretAccessKey:s.secretAccessKey,sessionToken:s.sessionToken}}throw Error("No credentials available for account")}listCrossAccountRoles(){return[...this.crossAccountRoles]}getCrossAccountRolesForAccount(n){return this.crossAccountRoles.filter((i)=>i.sourceAccountId===n||i.targetAccountId===n)}async validateAccountAccess(n){try{let i=await this.getCredentialsForAccount(n);return console.log(`Validating access to account: ${n}`),!0}catch{return!1}}async getConsolidatedBilling(){let n={};for(let i of this.accounts.values())n[i.id]=Math.random()*1000;return{totalCost:Object.values(n).reduce((i,s)=>i+s,0),byAccount:n}}clear(){this.accounts.clear(),this.crossAccountRoles=[],this.accountMappings=[]}}class Kg{organizationId;organizationalUnits=new Map;getOrganizationId(){return this.organizationId}setOrganizationId(n){this.organizationId=n}createOrganizationalUnit(n,i){let s={id:`ou-${Date.now()}`,name:n,parentId:i,accounts:[]};return this.organizationalUnits.set(s.id,s),s}getOrganizationalUnit(n){return this.organizationalUnits.get(n)}listOrganizationalUnits(){return Array.from(this.organizationalUnits.values())}addAccountToOU(n,i){let s=this.organizationalUnits.get(n);if(!s)throw Error(`Organizational unit not found: ${n}`);if(!s.accounts.includes(i))s.accounts.push(i)}removeAccountFromOU(n,i){let s=this.organizationalUnits.get(n);if(!s)throw Error(`Organizational unit not found: ${n}`);s.accounts=s.accounts.filter((o)=>o!==i)}getAccountsInOU(n){let i=this.organizationalUnits.get(n);if(!i)return[];return[...i.accounts]}applyServiceControlPolicy(n,i){return{id:`scp-${Date.now()}`,name:"Custom SCP",targetId:n,policyDocument:i}}clear(){this.organizationId=void 0,this.organizationalUnits.clear()}}var NC=new zg,kC=new Kg,VA={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"}]}},BC={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"]}}}]}}},_C={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 OC(n){return VA[n]}function xC(n,i){return{Type:"AWS::IAM::Role",Properties:{RoleName:n.roleName,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${n.sourceAccountId}:root`},Action:"sts:AssumeRole",...n.externalId&&{Condition:{StringEquals:{"sts:ExternalId":n.externalId}}}}]},Policies:[{PolicyName:`${n.roleName}Policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:n.permissions,Resource:"*"}]}}],...i&&{ManagedPolicyArns:i},MaxSessionDuration:n.sessionDuration||3600,Tags:[{Key:"ManagedBy",Value:"TS-Cloud"},{Key:"SourceAccount",Value:n.sourceAccountId}]}}}function LC(n){let i=[],s=[],o=n.accounts.filter((f)=>f.role==="management");if(o.length===0)i.push("No management account defined");if(o.length>1)i.push("Multiple management accounts defined");let c=n.accounts.map((f)=>f.email),l=c.filter((f,S)=>c.indexOf(f)!==S);if(l.length>0)i.push(`Duplicate email addresses: ${l.join(", ")}`);let u=n.accounts.map((f)=>f.alias),h=u.filter((f,S)=>u.indexOf(f)!==S);if(h.length>0)i.push(`Duplicate aliases: ${h.join(", ")}`);if(!n.accounts.some((f)=>f.role==="security"))s.push("No dedicated security account - consider adding one for audit logs");if(n.accounts.length<3)s.push("Less than 3 accounts - consider separating environments");if(!n.accounts.some((f)=>f.role==="production"))s.push("No production account defined");return{valid:i.length===0,errors:i,warnings:s}}function $C(n){let i=[];if(i.push(`${n.name}`),i.push("─".repeat(n.name.length)),i.push(n.description),i.push(""),n.organizationalUnits){i.push("Organizational Units:");for(let s of n.organizationalUnits){let o=s.parent?" └─ ":" ";i.push(`${o}${s.name}`)}i.push("")}i.push("Accounts:");for(let s of n.accounts)i.push(` ${s.alias.padEnd(20)} ${s.role.padEnd(15)} ${s.email}`),i.push(` ${"".padEnd(20)} ${s.description}`),i.push("");return i.join(`
|
|
2766
2766
|
`)}function MC(n={}){let{workflowName:i="Deploy",trigger:s="push",branches:o=["main"],environments:c=["production"],awsRegion:l="us-east-1",awsRole:u,bunVersion:h="latest",deployCommand:f="bun run cloud deploy",testCommand:S="bun test",buildCommand:b="bun run build"}=n,A=!!u;return`name: ${i}
|
|
2767
2767
|
|
|
2768
2768
|
on:
|
|
@@ -3773,7 +3773,7 @@ Scanning image: ${s}`),console.log(`Scanner: ${i.scanner}`);let o=`scan-result-$
|
|
|
3773
3773
|
Scan Results:`),console.log(` Total vulnerabilities: ${l.total}`),console.log(` Critical: ${l.critical}`),console.log(` High: ${l.high}`),console.log(` Medium: ${l.medium}`),console.log(` Low: ${l.low}`),console.log(` Status: ${u?"✓ PASSED":"✗ FAILED"}`),h}simulateVulnerabilities(n){let i=[];if(n.scanner==="trivy"||n.scanner==="ecr")i.push({id:"vuln-1",cve:"CVE-2024-1234",severity:"HIGH",packageName:"openssl",installedVersion:"1.1.1k",fixedVersion:"1.1.1l",title:"OpenSSL buffer overflow",description:"Buffer overflow vulnerability in OpenSSL",references:["https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-1234"],cvss:7.5}),i.push({id:"vuln-2",cve:"CVE-2024-5678",severity:"MEDIUM",packageName:"curl",installedVersion:"7.68.0",fixedVersion:"7.79.0",title:"curl remote code execution",description:"Remote code execution in curl",references:["https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-5678"],cvss:5.3});return i}evaluateScanResult(n,i){if(!n.failOnSeverity)return!0;switch(n.failOnSeverity){case"CRITICAL":return i.critical===0;case"HIGH":return i.critical===0&&i.high===0;case"MEDIUM":return i.critical===0&&i.high===0&&i.medium===0;case"LOW":return i.total===0;default:return!0}}createPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,...n};return this.policies.set(i,s),s}createStrictPolicy(n){return this.createPolicy({name:n,allowedSeverities:[],maxCritical:0,maxHigh:0,blockOnFailure:!0,exemptions:[]})}createPermissivePolicy(n){return this.createPolicy({name:n,allowedSeverities:["CRITICAL","HIGH","MEDIUM","LOW"],maxCritical:5,maxHigh:10,blockOnFailure:!1,exemptions:[]})}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getResult(n){return this.results.get(n)}listResults(){return Array.from(this.results.values())}generateECRScanCF(n){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:n.repository,ImageScanningConfiguration:{ScanOnPush:n.scanOnPush},ImageTagMutability:"IMMUTABLE",EncryptionConfiguration:{EncryptionType:"AES256"}}}}clear(){this.configs.clear(),this.results.clear(),this.policies.clear(),this.configCounter=0,this.resultCounter=0,this.policyCounter=0}}var CE=new mm;class hm{configs=new Map;multiStageConfigs=new Map;optimizations=new Map;analyses=new Map;configCounter=0;multiStageCounter=0;optimizationCounter=0;analysisCounter=0;createBuildConfig(n){let i=`build-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}createOptimizedBuildConfig(n){let i={type:n.enableCache?"registry":"inline",cacheFrom:n.registry?[`${n.registry}/cache`]:void 0,cacheTo:n.registry?`${n.registry}/cache`:void 0,maxCacheAge:7};return this.createBuildConfig({name:n.name,dockerfile:n.dockerfile,context:".",cacheStrategy:i,buildArgs:{BUILDKIT_INLINE_CACHE:"1"}})}createMultiStageConfig(n){let i=`multi-stage-${Date.now()}-${this.multiStageCounter++}`,s={id:i,...n};return this.multiStageConfigs.set(i,s),s}createNodeMultiStageBuild(n){let i=n.nodeVersion||"18-alpine";return this.createMultiStageConfig({name:n.name,targetStage:n.targetStage||"production",stages:[{name:"dependencies",baseImage:`node:${i}`,workdir:"/app",commands:["COPY package*.json ./","RUN npm ci --only=production"]},{name:"build",baseImage:`node:${i}`,workdir:"/app",commands:["COPY package*.json ./","RUN npm ci","COPY . .","RUN npm run build"]},{name:"production",baseImage:`node:${i}`,workdir:"/app",copyFrom:["dependencies:/app/node_modules","build:/app/dist"],commands:["COPY package*.json ./","ENV NODE_ENV=production",'CMD ["node", "dist/index.js"]']}]})}generateDockerfile(n){let i=this.multiStageConfigs.get(n);if(!i)throw Error(`Multi-stage config not found: ${n}`);let s=[];for(let o of i.stages){if(s.push(`# Stage: ${o.name}`),s.push(`FROM ${o.baseImage} AS ${o.name}`),o.workdir)s.push(`WORKDIR ${o.workdir}`);if(o.env)for(let[c,l]of Object.entries(o.env))s.push(`ENV ${c}=${l}`);for(let c of o.commands)s.push(c);s.push("")}return s.join(`
|
|
3774
3774
|
`)}analyzeImage(n,i){let s=`analysis-${Date.now()}-${this.analysisCounter++}`,o=i.map((h)=>({...h,cacheable:this.isLayerCacheable(h.command)})),c=o.reduce((h,f)=>h+f.size,0),l=o.filter((h)=>!h.cacheable&&h.size>100).length,u={id:s,imageId:n,layers:o,totalSize:c,unnecessaryLayers:l};return this.analyses.set(s,u),u}isLayerCacheable(n){let i=["FROM","RUN","COPY","ADD","WORKDIR","ENV"],s=["CMD","ENTRYPOINT","LABEL"];for(let o of i)if(n.startsWith(o))return!0;for(let o of s)if(n.startsWith(o))return!1;return!1}generateOptimizations(n){let i=this.analyses.get(n);if(!i)throw Error(`Analysis not found: ${n}`);let s=`optimization-${Date.now()}-${this.optimizationCounter++}`,o=[],c=i.layers.filter((S)=>S.command.startsWith("RUN"));if(c.length>5)o.push({type:"layer_reduction",priority:"high",title:"Combine RUN commands",description:`${c.length} RUN commands found. Combine them to reduce layers.`,example:"RUN apt-get update && apt-get install -y package1 package2",impact:"Reduce image size by 20-30% and improve build time"});let l=i.layers[0];if(l.command.includes("ubuntu")||l.command.includes("debian"))o.push({type:"base_image",priority:"medium",title:"Use Alpine base image",description:"Switch to Alpine Linux for smaller image size",example:"FROM node:18-alpine",impact:"Reduce image size by 50-70%"});let u=i.layers.filter((S)=>S.command.startsWith("COPY"));if(u.length>0&&u[0].index>3)o.push({type:"cache_optimization",priority:"high",title:"Copy dependencies first",description:"Copy package files before source code to leverage layer caching",example:`COPY package*.json ./
|
|
3775
3775
|
RUN npm install
|
|
3776
|
-
COPY . .`,impact:"Improve build time by 60-80% on subsequent builds"});let h={sizeBefore:i.totalSize,sizeAfter:i.totalSize*0.6,timeBefore:300,timeAfter:120},f={id:s,name:`Optimization for ${i.imageId}`,recommendations:o,estimatedSavings:h};return this.optimizations.set(s,f),f}getBuildConfig(n){return this.configs.get(n)}listBuildConfigs(){return Array.from(this.configs.values())}getMultiStageConfig(n){return this.multiStageConfigs.get(n)}listMultiStageConfigs(){return Array.from(this.multiStageConfigs.values())}getOptimization(n){return this.optimizations.get(n)}listOptimizations(){return Array.from(this.optimizations.values())}clear(){this.configs.clear(),this.multiStageConfigs.clear(),this.optimizations.clear(),this.analyses.clear(),this.configCounter=0,this.multiStageCounter=0,this.optimizationCounter=0,this.analysisCounter=0}}var EE=new hm;class fm{registries=new Map;credentials=new Map;registryCounter=0;credentialsCounter=0;createRegistry(n){let i=`registry-${Date.now()}-${this.registryCounter++}`,s={id:i,...n};return this.registries.set(i,s),s}createECRRepository(n){return this.createRegistry({name:n.name,registryType:"ecr",repositoryUri:`123456789012.dkr.ecr.${n.region||"us-east-1"}.amazonaws.com/${n.name}`,region:n.region||"us-east-1",encryption:{encryptionType:n.encryption||"AES256",kmsKeyId:n.kmsKeyId},scanning:{scanOnPush:n.scanOnPush??!0}})}createManagedRepository(n){let i=this.createECRRepository({name:n.name,region:n.region,scanOnPush:!0,encryption:"KMS"});return i.lifecycle={id:`lifecycle-${Date.now()}`,rules:[{rulePriority:1,description:"Keep only last N images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:n.maxImageCount||10},action:{type:"expire"}},{rulePriority:2,description:"Remove images older than N days",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:n.maxImageAgeDays||30,countUnit:"days"},action:{type:"expire"}}]},i}enableReplication(n,i){let s=this.registries.get(n);if(!s)throw Error(`Registry not found: ${n}`);return s.replication={enabled:!0,destinations:i},s}createCredentials(n){let i=`creds-${Date.now()}-${this.credentialsCounter++}`,s={id:i,...n};return this.credentials.set(i,s),s}getRegistry(n){return this.registries.get(n)}listRegistries(){return Array.from(this.registries.values())}generateECRRepositoryCF(n){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:n.name,ImageScanningConfiguration:{ScanOnPush:n.scanning?.scanOnPush??!1},EncryptionConfiguration:{EncryptionType:n.encryption?.encryptionType||"AES256",...n.encryption?.kmsKeyId&&{KmsKey:n.encryption.kmsKeyId}},ImageTagMutability:"MUTABLE",...n.lifecycle&&{LifecyclePolicy:{LifecyclePolicyText:JSON.stringify({rules:n.lifecycle.rules})}}}}}generateReplicationConfigCF(n){return{Type:"AWS::ECR::ReplicationConfiguration",Properties:{ReplicationConfiguration:{Rules:n.destinations.map((i)=>({Destinations:[{Region:i.region,...i.registryId&&{RegistryId:i.registryId}}]}))}}}}clear(){this.registries.clear(),this.credentials.clear(),this.registryCounter=0,this.credentialsCounter=0}}var bE=new fm;class Am{meshes=new Map;virtualNodes=new Map;virtualRouters=new Map;virtualGateways=new Map;meshCounter=0;nodeCounter=0;routerCounter=0;gatewayCounter=0;createMesh(n){let i=`mesh-${Date.now()}-${this.meshCounter++}`,s={id:i,...n};return this.meshes.set(i,s),s}createAppMesh(n){return this.createMesh({name:n.name,meshType:"app_mesh",services:n.services,virtualNodes:[],virtualRouters:[],virtualGateways:[]})}createVirtualNode(n){let i=`vnode-${Date.now()}-${this.nodeCounter++}`,s={id:i,...n};return this.virtualNodes.set(i,s),s}createHTTPVirtualNode(n){return this.createVirtualNode({name:n.name,serviceName:n.serviceName,listeners:[{port:n.port,protocol:"http",healthCheck:{protocol:"http",path:"/health",interval:30,timeout:10,healthyThreshold:2,unhealthyThreshold:3},timeout:{perRequest:15000,idle:300000}}],serviceDiscovery:{type:"aws_cloud_map",namespace:n.namespace,serviceName:n.serviceName}})}createVirtualRouter(n){let i=`vrouter-${Date.now()}-${this.routerCounter++}`,s={id:i,...n};return this.virtualRouters.set(i,s),s}createCanaryRoute(n){return this.createVirtualRouter({name:n.name,listeners:[{port:n.port,protocol:n.protocol}],routes:[{name:"canary-route",match:{prefix:"/"},action:{weightedTargets:[{virtualNode:n.stableTarget,weight:100-n.canaryWeight},{virtualNode:n.canaryTarget,weight:n.canaryWeight}]},retryPolicy:{maxRetries:3,perRetryTimeout:5000,httpRetryEvents:["server-error","gateway-error"],tcpRetryEvents:["connection-error"]}}]})}createVirtualGateway(n){let i=`vgateway-${Date.now()}-${this.gatewayCounter++}`,s={id:i,...n};return this.virtualGateways.set(i,s),s}createIngressGateway(n){let i={port:n.port,protocol:"http",healthCheck:{protocol:"http",path:"/health",interval:30,timeout:10,healthyThreshold:2,unhealthyThreshold:3}};if(n.enableTLS&&n.certificateArn)i.tls={mode:"STRICT",certificate:{acm:n.certificateArn}};return this.createVirtualGateway({name:n.name,listeners:[i],logging:{accessLog:{file:{path:"/dev/stdout"}}}})}getMesh(n){return this.meshes.get(n)}listMeshes(){return Array.from(this.meshes.values())}getVirtualNode(n){return this.virtualNodes.get(n)}listVirtualNodes(){return Array.from(this.virtualNodes.values())}generateMeshCF(n){return{Type:"AWS::AppMesh::Mesh",Properties:{MeshName:n.name,Spec:{EgressFilter:{Type:"ALLOW_ALL"}}}}}generateVirtualNodeCF(n,i){return{Type:"AWS::AppMesh::VirtualNode",Properties:{MeshName:i,VirtualNodeName:n.name,Spec:{Listeners:n.listeners.map((s)=>({PortMapping:{Port:s.port,Protocol:s.protocol},...s.healthCheck&&{HealthCheck:{Protocol:s.healthCheck.protocol,...s.healthCheck.path&&{Path:s.healthCheck.path},IntervalMillis:s.healthCheck.interval*1000,TimeoutMillis:s.healthCheck.timeout*1000,HealthyThreshold:s.healthCheck.healthyThreshold,UnhealthyThreshold:s.healthCheck.unhealthyThreshold}}})),ServiceDiscovery:{AWSCloudMap:{NamespaceName:n.serviceDiscovery.namespace,ServiceName:n.serviceDiscovery.serviceName}}}}}}generateVirtualRouterCF(n,i){return{Type:"AWS::AppMesh::VirtualRouter",Properties:{MeshName:i,VirtualRouterName:n.name,Spec:{Listeners:n.listeners.map((s)=>({PortMapping:{Port:s.port,Protocol:s.protocol}}))}}}}clear(){this.meshes.clear(),this.virtualNodes.clear(),this.virtualRouters.clear(),this.virtualGateways.clear(),this.meshCounter=0,this.nodeCounter=0,this.routerCounter=0,this.gatewayCounter=0}}var vE=new Am;class ym{layers=new Map;versions=new Map;permissions=new Map;layerCounter=0;versionCounter=0;permissionCounter=0;createLayer(n){let i=`layer-${Date.now()}-${this.layerCounter++}`,s=1,o={id:i,layerArn:`arn:aws:lambda:us-east-1:123456789012:layer:${n.layerName}:1`,version:1,...n};return this.layers.set(i,o),o}createNodeDependenciesLayer(n){return this.createLayer({layerName:n.layerName,description:"Node.js dependencies layer",compatibleRuntimes:[`nodejs${n.nodeVersion}`],content:{type:"s3",s3Bucket:n.s3Bucket,s3Key:n.s3Key},size:5242880})}createUtilitiesLayer(n){return this.createLayer({layerName:n.layerName,description:"Shared utilities and helpers",compatibleRuntimes:n.runtimes,content:{type:"s3",s3Bucket:n.s3Bucket,s3Key:n.s3Key},size:1048576})}publishVersion(n){let i=this.layers.get(n);if(!i)throw Error(`Layer not found: ${n}`);let s=`version-${Date.now()}-${this.versionCounter++}`,o=i.version+1,c={id:s,layerName:i.layerName,version:o,createdAt:new Date,compatibleRuntimes:i.compatibleRuntimes,size:i.size,codeHash:this.generateHash()};return this.versions.set(s,c),i.version=o,i.layerArn=`arn:aws:lambda:us-east-1:123456789012:layer:${i.layerName}:${o}`,c}addPermission(n){let i=`permission-${Date.now()}-${this.permissionCounter++}`,s={id:i,layerName:n.layerName,version:n.version,principal:n.principal,action:"lambda:GetLayerVersion",organizationId:n.organizationId};return this.permissions.set(i,s),s}generateHash(){return Math.random().toString(36).substring(2,15)}getLayer(n){return this.layers.get(n)}listLayers(){return Array.from(this.layers.values())}getLayerVersions(n){return Array.from(this.versions.values()).filter((i)=>i.layerName===n)}generateLayerCF(n){return{Type:"AWS::Lambda::LayerVersion",Properties:{LayerName:n.layerName,Description:n.description,Content:n.content.type==="s3"?{S3Bucket:n.content.s3Bucket,S3Key:n.content.s3Key,...n.content.s3ObjectVersion&&{S3ObjectVersion:n.content.s3ObjectVersion}}:{ZipFile:n.content.zipFile},CompatibleRuntimes:n.compatibleRuntimes,...n.licenseInfo&&{LicenseInfo:n.licenseInfo}}}}generateLayerPermissionCF(n){return{Type:"AWS::Lambda::LayerVersionPermission",Properties:{LayerVersionArn:`arn:aws:lambda:us-east-1:123456789012:layer:${n.layerName}:${n.version}`,Action:n.action,Principal:n.principal,...n.organizationId&&{OrganizationId:n.organizationId}}}}clear(){this.layers.clear(),this.versions.clear(),this.permissions.clear(),this.layerCounter=0,this.versionCounter=0,this.permissionCounter=0}}var TE=new ym;class Im{versions=new Map;aliases=new Map;deployments=new Map;versionCounter=0;aliasCounter=0;deploymentCounter=0;publishVersion(n){let i=`version-${Date.now()}-${this.versionCounter++}`,s=this.getNextVersionNumber(n.functionName),o={id:i,functionName:n.functionName,version:s.toString(),functionArn:`arn:aws:lambda:us-east-1:123456789012:function:${n.functionName}:${s}`,codeHash:this.generateHash(),description:n.description,runtime:n.runtime,memorySize:n.memorySize,timeout:n.timeout,publishedAt:new Date};return this.versions.set(i,o),o}getNextVersionNumber(n){let i=Array.from(this.versions.values()).filter((s)=>s.functionName===n).map((s)=>parseInt(s.version));return i.length>0?Math.max(...i)+1:1}createAlias(n){let i=`alias-${Date.now()}-${this.aliasCounter++}`,s={id:i,aliasArn:`arn:aws:lambda:us-east-1:123456789012:function:${n.functionName}:${n.aliasName}`,revisionId:this.generateHash(),...n};return this.aliases.set(i,s),s}createProductionAlias(n){return this.createAlias({functionName:n.functionName,aliasName:"production",functionVersion:n.version,description:"Production alias"})}createStagingAlias(n){return this.createAlias({functionName:n.functionName,aliasName:"staging",functionVersion:n.version,description:"Staging alias"})}updateAlias(n,i){let s=this.aliases.get(n);if(!s)throw Error(`Alias not found: ${n}`);return s.functionVersion=i,s.revisionId=this.generateHash(),s}configureWeightedRouting(n,i){let s=this.aliases.get(n);if(!s)throw Error(`Alias not found: ${n}`);return s.routingConfig={additionalVersionWeights:i},s}createCanaryDeployment(n){let i=`deployment-${Date.now()}-${this.deploymentCounter++}`,s=Array.from(this.aliases.values()).find((c)=>c.functionName===n.functionName&&c.aliasName===n.aliasName);if(!s)s=this.createAlias({functionName:n.functionName,aliasName:n.aliasName,functionVersion:n.fromVersion});this.configureWeightedRouting(s.id,{[n.toVersion]:n.canaryWeight});let o={id:i,functionName:n.functionName,fromVersion:n.fromVersion,toVersion:n.toVersion,aliasName:n.aliasName,strategy:"canary",status:"in_progress",startedAt:new Date};return this.deployments.set(i,o),o}completeDeployment(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);let s=Array.from(this.aliases.values()).find((o)=>o.functionName===i.functionName&&o.aliasName===i.aliasName);if(s)s.functionVersion=i.toVersion,s.routingConfig=void 0;return i.status="completed",i.completedAt=new Date,i}rollbackDeployment(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);let s=Array.from(this.aliases.values()).find((o)=>o.functionName===i.functionName&&o.aliasName===i.aliasName);if(s)s.functionVersion=i.fromVersion,s.routingConfig=void 0;return i.status="failed",i.completedAt=new Date,i}generateHash(){return Math.random().toString(36).substring(2,15)}getVersion(n){return this.versions.get(n)}listVersions(n){let i=Array.from(this.versions.values());return n?i.filter((s)=>s.functionName===n):i}getAlias(n){return this.aliases.get(n)}listAliases(n){let i=Array.from(this.aliases.values());return n?i.filter((s)=>s.functionName===n):i}generateVersionCF(n){return{Type:"AWS::Lambda::Version",Properties:{FunctionName:n.functionName,Description:n.description}}}generateAliasCF(n){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:n.functionName,Name:n.aliasName,FunctionVersion:n.functionVersion,Description:n.description,...n.routingConfig&&{RoutingConfig:{AdditionalVersionWeights:Object.entries(n.routingConfig.additionalVersionWeights||{}).map(([i,s])=>({FunctionVersion:i,FunctionWeight:s}))}}}}}clear(){this.versions.clear(),this.aliases.clear(),this.deployments.clear(),this.versionCounter=0,this.aliasCounter=0,this.deploymentCounter=0}}var wE=new Im;class Sm{configs=new Map;provisionedConfigs=new Map;schedules=new Map;autoScalingConfigs=new Map;configCounter=0;provisionedCounter=0;scheduleCounter=0;autoScalingCounter=0;setReservedConcurrency(n){let i=`concurrency-${Date.now()}-${this.configCounter++}`,s={id:i,functionName:n.functionName,reservedConcurrency:n.reservedConcurrency};return this.configs.set(i,s),s}setProvisionedConcurrency(n){let i=`provisioned-${Date.now()}-${this.provisionedCounter++}`,s={id:i,functionName:n.functionName,qualifier:n.qualifier,provisionedConcurrentExecutions:n.provisionedConcurrentExecutions,status:"pending",lastModified:new Date};return this.provisionedConfigs.set(i,s),setTimeout(()=>{s.status="ready",s.allocatedConcurrency=n.provisionedConcurrentExecutions,s.availableConcurrency=n.provisionedConcurrentExecutions},100),s}configureWarmPool(n){return this.setProvisionedConcurrency({functionName:n.functionName,qualifier:n.alias,provisionedConcurrentExecutions:n.minInstances})}createSchedule(n){let i=`schedule-${Date.now()}-${this.scheduleCounter++}`,s={id:i,...n};return this.schedules.set(i,s),s}createBusinessHoursSchedule(n){return this.createSchedule({name:`${n.functionName}-business-hours`,functionName:n.functionName,qualifier:n.qualifier,schedule:[{name:"business-hours",cronExpression:"0 8 * * MON-FRI",targetConcurrency:n.businessHoursConcurrency},{name:"off-hours",cronExpression:"0 18 * * MON-FRI",targetConcurrency:n.offHoursConcurrency},{name:"weekend",cronExpression:"0 0 * * SAT",targetConcurrency:n.offHoursConcurrency}]})}configureAutoScaling(n){let i=`autoscaling-${Date.now()}-${this.autoScalingCounter++}`,s={id:i,...n};return this.autoScalingConfigs.set(i,s),s}configurePredictiveScaling(n){return this.configureAutoScaling({functionName:n.functionName,qualifier:n.qualifier,minCapacity:n.baselineCapacity,maxCapacity:n.peakCapacity,targetUtilization:0.7,scaleInCooldown:300,scaleOutCooldown:60})}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getProvisionedConfig(n){return this.provisionedConfigs.get(n)}listProvisionedConfigs(){return Array.from(this.provisionedConfigs.values())}generateReservedConcurrencyCF(n){return{Type:"AWS::Lambda::Function",Properties:{FunctionName:n.functionName,ReservedConcurrentExecutions:n.reservedConcurrency}}}generateProvisionedConcurrencyCF(n){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:n.functionName,Name:n.qualifier,ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:n.provisionedConcurrentExecutions}}}}generateAutoScalingTargetCF(n){return{Type:"AWS::ApplicationAutoScaling::ScalableTarget",Properties:{ServiceNamespace:"lambda",ResourceId:`function:${n.functionName}:${n.qualifier}`,ScalableDimension:"lambda:function:ProvisionedConcurrentExecutions",MinCapacity:n.minCapacity,MaxCapacity:n.maxCapacity}}}generateAutoScalingPolicyCF(n){return{Type:"AWS::ApplicationAutoScaling::ScalingPolicy",Properties:{PolicyName:`${n.functionName}-autoscaling`,PolicyType:"TargetTrackingScaling",ScalingTargetId:{Ref:`${n.functionName}AutoScalingTarget`},TargetTrackingScalingPolicyConfiguration:{TargetValue:n.targetUtilization*100,PredefinedMetricSpecification:{PredefinedMetricType:"LambdaProvisionedConcurrencyUtilization"},ScaleInCooldown:n.scaleInCooldown||300,ScaleOutCooldown:n.scaleOutCooldown||60}}}}clear(){this.configs.clear(),this.provisionedConfigs.clear(),this.schedules.clear(),this.autoScalingConfigs.clear(),this.configCounter=0,this.provisionedCounter=0,this.scheduleCounter=0,this.autoScalingCounter=0}}var RE=new Sm;class Cm{destinations=new Map;records=new Map;eventBridgeDestinations=new Map;destinationCounter=0;recordCounter=0;eventBridgeCounter=0;configureDestinations(n){let i=`destination-${Date.now()}-${this.destinationCounter++}`,s={id:i,...n};return this.destinations.set(i,s),s}configureSQSDestination(n){let i={type:"sqs",arn:n.queueArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureSNSDestination(n){let i={type:"sns",arn:n.topicArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureEventBridgeDestination(n){let i={type:"eventbridge",arn:n.eventBusArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureLambdaDestination(n){let i={type:"lambda",arn:n.destinationFunctionArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureDLQWithNotification(n){return this.configureDestinations({functionName:n.functionName,failureDestination:{type:"sqs",arn:n.dlqArn},maxEventAge:3600,maxRetries:0})}createEventBridgeIntegration(n){let i=`eventbridge-${Date.now()}-${this.eventBridgeCounter++}`,s={id:i,functionName:n.functionName,eventBusArn:n.eventBusArn,detailType:n.detailType||"Lambda Function Invocation Result",source:n.source||`lambda.${n.functionName}`};return this.eventBridgeDestinations.set(i,s),s}sendToDestination(n){let i=Array.from(this.destinations.values()).find((l)=>l.functionName===n.functionName);if(!i)return null;let s=n.status==="success"?i.successDestination:i.failureDestination;if(!s)return null;let o=`record-${Date.now()}-${this.recordCounter++}`,c={id:o,timestamp:new Date,functionName:n.functionName,requestId:n.requestId,status:n.status,destinationType:s.type,destinationArn:s.arn,payload:n.payload,error:n.error};return this.records.set(o,c),c}getDestination(n){return this.destinations.get(n)}listDestinations(n){let i=Array.from(this.destinations.values());return n?i.filter((s)=>s.functionName===n):i}getDestinationRecords(n){let i=Array.from(this.records.values());return n?i.filter((s)=>s.functionName===n):i}generateEventInvokeConfigCF(n){return{Type:"AWS::Lambda::EventInvokeConfig",Properties:{FunctionName:n.functionName,Qualifier:n.qualifier||"$LATEST",MaximumEventAgeInSeconds:n.maxEventAge||21600,MaximumRetryAttempts:n.maxRetries??2,...n.successDestination&&{DestinationConfig:{OnSuccess:{Destination:n.successDestination.arn}}},...n.failureDestination&&{DestinationConfig:{OnFailure:{Destination:n.failureDestination.arn}}}}}}generateEventBridgeRuleCF(n){return{Type:"AWS::Events::Rule",Properties:{EventBusName:n.eventBusArn.split("/").pop(),EventPattern:{source:[n.source],"detail-type":[n.detailType]},State:"ENABLED",Targets:[{Arn:`arn:aws:lambda:us-east-1:123456789012:function:${n.functionName}`,Id:n.id}]}}}clear(){this.destinations.clear(),this.records.clear(),this.eventBridgeDestinations.clear(),this.destinationCounter=0,this.recordCounter=0,this.eventBridgeCounter=0}}var DE=new Cm;class Em{vpcConfigs=new Map;endpoints=new Map;networkInterfaces=new Map;connectivity=new Map;configCounter=0;endpointCounter=0;eniCounter=0;connectivityCounter=0;configureVPC(n){let i=`vpc-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};this.vpcConfigs.set(i,s);for(let o of n.subnetIds)this.createNetworkInterface({functionName:n.functionName,subnetId:o});return s}configurePrivateVPC(n){return this.configureVPC({functionName:n.functionName,vpcId:n.vpcId,subnetIds:n.privateSubnetIds,securityGroupIds:[n.securityGroupId],ipv6Allowed:!1})}configureMultiAZVPC(n){if(n.subnetIds.length<2)throw Error("Multi-AZ configuration requires at least 2 subnets");return this.configureVPC({functionName:n.functionName,vpcId:n.vpcId,subnetIds:n.subnetIds,securityGroupIds:n.securityGroupIds})}createVPCEndpoint(n){let i=`endpoint-${Date.now()}-${this.endpointCounter++}`,s={id:i,...n};return this.endpoints.set(i,s),s}createS3Endpoint(n){return this.createVPCEndpoint({vpcId:n.vpcId,serviceName:"com.amazonaws.us-east-1.s3",endpointType:"Gateway",privateDnsEnabled:!1})}createDynamoDBEndpoint(n){return this.createVPCEndpoint({vpcId:n.vpcId,serviceName:"com.amazonaws.us-east-1.dynamodb",endpointType:"Gateway",privateDnsEnabled:!1})}createSecretsManagerEndpoint(n){return this.createVPCEndpoint({vpcId:n.vpcId,serviceName:"com.amazonaws.us-east-1.secretsmanager",endpointType:"Interface",subnetIds:n.subnetIds,securityGroupIds:n.securityGroupIds,privateDnsEnabled:!0})}createNetworkInterface(n){let i=`eni-${Date.now()}-${this.eniCounter++}`,s={id:i,functionName:n.functionName,networkInterfaceId:`eni-${Math.random().toString(36).substring(2,15)}`,subnetId:n.subnetId,privateIpAddress:`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`,status:"creating",attachedAt:new Date};return this.networkInterfaces.set(i,s),setTimeout(()=>{s.status="available"},100),s}analyzeConnectivity(n){let i=`connectivity-${Date.now()}-${this.connectivityCounter++}`,s=Array.from(this.vpcConfigs.values()).find((f)=>f.functionName===n.functionName),o=Array.from(this.endpoints.values()).filter((f)=>f.vpcId===s?.vpcId).map((f)=>f.serviceName),c=[],l=n.hasNATGateway??!1,u=n.hasInternetGateway??!1;if(!l&&!u)c.push("Add NAT Gateway for internet access");if(!o.includes("com.amazonaws.us-east-1.s3"))c.push("Add S3 VPC endpoint to reduce NAT costs");if(!o.includes("com.amazonaws.us-east-1.dynamodb"))c.push("Add DynamoDB VPC endpoint for private access");let h={id:i,functionName:n.functionName,hasInternetAccess:l||u,hasNATGateway:l,hasVPCEndpoints:o.length>0,endpoints:o,recommendations:c};return this.connectivity.set(i,h),h}getVPCConfig(n){return this.vpcConfigs.get(n)}listVPCConfigs(n){let i=Array.from(this.vpcConfigs.values());return n?i.filter((s)=>s.functionName===n):i}getNetworkInterfaces(n){return Array.from(this.networkInterfaces.values()).filter((i)=>i.functionName===n)}listVPCEndpoints(n){let i=Array.from(this.endpoints.values());return n?i.filter((s)=>s.vpcId===n):i}generateVPCConfigCF(n){return{VpcConfig:{SubnetIds:n.subnetIds,SecurityGroupIds:n.securityGroupIds,...n.ipv6Allowed&&{Ipv6AllowedForDualStack:!0}}}}generateVPCEndpointCF(n){return{Type:"AWS::EC2::VPCEndpoint",Properties:{VpcId:n.vpcId,ServiceName:n.serviceName,VpcEndpointType:n.endpointType,...n.subnetIds&&{SubnetIds:n.subnetIds},...n.securityGroupIds&&{SecurityGroupIds:n.securityGroupIds},...n.privateDnsEnabled!==void 0&&{PrivateDnsEnabled:n.privateDnsEnabled}}}}generateSecurityGroupCF(n){return{Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:n.groupName,GroupDescription:`Security group for Lambda ${n.groupName}`,VpcId:n.vpcId,...n.ingressRules&&{SecurityGroupIngress:n.ingressRules.map((i)=>({IpProtocol:i.protocol,FromPort:i.fromPort,ToPort:i.toPort,...i.cidrIp&&{CidrIp:i.cidrIp},...i.sourceSecurityGroupId&&{SourceSecurityGroupId:i.sourceSecurityGroupId}}))},...n.egressRules&&{SecurityGroupEgress:n.egressRules.map((i)=>({IpProtocol:i.protocol,FromPort:i.fromPort,ToPort:i.toPort,CidrIp:i.cidrIp||"0.0.0.0/0"}))}}}}clear(){this.vpcConfigs.clear(),this.endpoints.clear(),this.networkInterfaces.clear(),this.connectivity.clear(),this.configCounter=0,this.endpointCounter=0,this.eniCounter=0,this.connectivityCounter=0}}var PE=new Em;class bm{dlqConfigs=new Map;messages=new Map;alarms=new Map;reprocessing=new Map;configCounter=0;messageCounter=0;alarmCounter=0;reprocessCounter=0;configureDLQ(n){let i=`dlq-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.dlqConfigs.set(i,s),s}configureSQSDLQ(n){return this.configureDLQ({functionName:n.functionName,targetArn:n.queueArn,targetType:"sqs",maxReceiveCount:n.maxReceiveCount||3,retentionPeriod:n.retentionPeriod||1209600})}configureSNSDLQ(n){return this.configureDLQ({functionName:n.functionName,targetArn:n.topicArn,targetType:"sns"})}configureDLQWithAlarm(n){let i=this.configureSQSDLQ({functionName:n.functionName,queueArn:n.queueArn});return this.createDLQAlarm({dlqConfigId:i.id,alarmName:`${n.functionName}-dlq-alarm`,threshold:n.alarmThreshold,evaluationPeriods:1,notificationTopicArn:n.notificationTopicArn,enabled:!0}),i}sendToDLQ(n){let i=`message-${Date.now()}-${this.messageCounter++}`,s={id:i,timestamp:new Date,...n};return this.messages.set(i,s),s}createDLQAlarm(n){let i=`alarm-${Date.now()}-${this.alarmCounter++}`,s={id:i,...n};return this.alarms.set(i,s),s}createAgeAlarm(n){let i=this.dlqConfigs.get(n.dlqConfigId);if(!i)throw Error(`DLQ config not found: ${n.dlqConfigId}`);return this.createDLQAlarm({dlqConfigId:n.dlqConfigId,alarmName:`${i.functionName}-dlq-age-alarm`,threshold:n.maxAgeSeconds,evaluationPeriods:1,notificationTopicArn:n.notificationTopicArn,enabled:!0})}async reprocessMessage(n){let i=this.messages.get(n);if(!i)throw Error(`Message not found: ${n}`);let s=Array.from(this.dlqConfigs.values()).find((l)=>l.functionName===i.functionName);if(!s)throw Error(`DLQ config not found for function: ${i.functionName}`);let o=`reprocess-${Date.now()}-${this.reprocessCounter++}`,c={id:o,dlqConfigId:s.id,messageId:n,status:"pending",startedAt:new Date};return this.reprocessing.set(o,c),setTimeout(()=>{c.status="processing",setTimeout(()=>{let l=Math.random()>0.3;if(c.status=l?"success":"failed",c.completedAt=new Date,!l)c.error="Reprocessing failed - same error occurred";else this.messages.delete(n)},100)},50),c}async batchReprocess(n){let i=this.dlqConfigs.get(n.dlqConfigId);if(!i)throw Error(`DLQ config not found: ${n.dlqConfigId}`);let s=Array.from(this.messages.values()).filter((o)=>o.functionName===i.functionName).slice(0,n.maxMessages||10).map((o)=>this.reprocessMessage(o.id));return Promise.all(s)}getDLQStats(n){let i=this.dlqConfigs.get(n);if(!i)throw Error(`DLQ config not found: ${n}`);let s=Array.from(this.messages.values()).filter((u)=>u.functionName===i.functionName),o={},c=0;for(let u of s)o[u.errorType]=(o[u.errorType]||0)+1,c+=u.attemptCount;let l=s.map((u)=>u.timestamp);return{totalMessages:s.length,oldestMessage:l.length>0?new Date(Math.min(...l.map((u)=>u.getTime()))):void 0,newestMessage:l.length>0?new Date(Math.max(...l.map((u)=>u.getTime()))):void 0,averageAttempts:s.length>0?c/s.length:0,errorTypes:o}}getDLQConfig(n){return this.dlqConfigs.get(n)}listDLQConfigs(){return Array.from(this.dlqConfigs.values())}getDLQMessages(n){let i=this.dlqConfigs.get(n);if(!i)return[];return Array.from(this.messages.values()).filter((s)=>s.functionName===i.functionName)}generateDLQCF(n){return{DeadLetterConfig:{TargetArn:n.targetArn}}}generateSQSDLQCF(n){return{Type:"AWS::SQS::Queue",Properties:{QueueName:`${n.functionName}-dlq`,MessageRetentionPeriod:n.retentionPeriod||1209600,...n.maxReceiveCount&&{RedrivePolicy:{deadLetterTargetArn:n.targetArn,maxReceiveCount:n.maxReceiveCount}}}}}generateDLQAlarmCF(n){let i=this.dlqConfigs.get(n.dlqConfigId);if(!i)throw Error(`DLQ config not found: ${n.dlqConfigId}`);return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:n.alarmName,AlarmDescription:`DLQ alarm for ${i.functionName}`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Sum",Period:300,EvaluationPeriods:n.evaluationPeriods,Threshold:n.threshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:i.targetArn.split(":").pop()}],...n.notificationTopicArn&&{AlarmActions:[n.notificationTopicArn]}}}}clear(){this.dlqConfigs.clear(),this.messages.clear(),this.alarms.clear(),this.reprocessing.clear(),this.configCounter=0,this.messageCounter=0,this.alarmCounter=0,this.reprocessCounter=0}}var NE=new bm;class vm{policies=new Map;healthChecks=new Map;trafficPolicies=new Map;policyCounter=0;healthCheckCounter=0;trafficPolicyCounter=0;createWeightedPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"weighted",...n};return this.policies.set(i,s),s}createLatencyPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"latency",...n};return this.policies.set(i,s),s}createFailoverPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"failover",...n};return this.policies.set(i,s),s}createGeolocationPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"geolocation",...n};return this.policies.set(i,s),s}createGeoproximityPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"geoproximity",...n};return this.policies.set(i,s),s}createHTTPHealthCheck(n){let i=`health-check-${Date.now()}-${this.healthCheckCounter++}`,s={id:i,type:n.port===443?"https":"http",requestInterval:n.requestInterval||30,failureThreshold:n.failureThreshold||3,healthCheckStatus:"Unknown",port:n.port||(n.port===443?443:80),...n};return this.healthChecks.set(i,s),setTimeout(()=>{s.healthCheckStatus=Math.random()>0.2?"Healthy":"Unhealthy"},100),s}createTCPHealthCheck(n){let i=`health-check-${Date.now()}-${this.healthCheckCounter++}`,s={id:i,type:"tcp",fullyQualifiedDomainName:n.ipAddress,requestInterval:n.requestInterval||30,failureThreshold:n.failureThreshold||3,healthCheckStatus:"Unknown",...n};return this.healthChecks.set(i,s),setTimeout(()=>{s.healthCheckStatus=Math.random()>0.1?"Healthy":"Unhealthy"},100),s}createCalculatedHealthCheck(n){let i=`health-check-${Date.now()}-${this.healthCheckCounter++}`,s={id:i,type:"calculated",requestInterval:30,failureThreshold:0,healthCheckStatus:"Unknown",...n};return this.healthChecks.set(i,s),setTimeout(()=>{let o=n.childHealthChecks.filter((c)=>this.healthChecks.get(c)?.healthCheckStatus==="Healthy").length;s.healthCheckStatus=o>=n.healthThreshold?"Healthy":"Unhealthy"},150),s}createTrafficPolicy(n){let i=`traffic-policy-${Date.now()}-${this.trafficPolicyCounter++}`,s={id:i,version:1,...n};return this.trafficPolicies.set(i,s),s}createFailoverTrafficPolicy(n){return this.createTrafficPolicy({name:n.name,document:{recordType:n.recordType||"A",startRule:"failover",endpoints:{primary:{type:"value",value:n.primaryEndpoint},secondary:{type:"value",value:n.secondaryEndpoint}},rules:{failover:{ruleType:"failover",primary:"primary",secondary:"secondary"}}}})}createGeoproximityTrafficPolicy(n){let i={},s=[];return n.locations.forEach((o,c)=>{let l=`endpoint${c}`;i[l]={type:"value",value:o.endpoint},s.push({endpointReference:l,region:o.region,latitude:o.latitude,longitude:o.longitude,bias:o.bias})}),this.createTrafficPolicy({name:n.name,document:{recordType:"A",startRule:"geoproximity",endpoints:i,rules:{geoproximity:{ruleType:"geoproximity",locations:s}}}})}getPolicy(n){return this.policies.get(n)}listPolicies(){return Array.from(this.policies.values())}getHealthCheck(n){return this.healthChecks.get(n)}listHealthChecks(){return Array.from(this.healthChecks.values())}getHealthCheckStatus(n){return this.healthChecks.get(n)?.healthCheckStatus||"Unknown"}generateHealthCheckCF(n){let i={Type:"AWS::Route53::HealthCheck",Properties:{HealthCheckConfig:{Type:n.type.toUpperCase(),RequestInterval:n.requestInterval,FailureThreshold:n.failureThreshold,...n.measureLatency&&{MeasureLatency:!0}},HealthCheckTags:[{Key:"Name",Value:n.name}]}};if(n.type==="calculated"){let s=n;i.Properties.HealthCheckConfig.ChildHealthChecks=s.childHealthChecks,i.Properties.HealthCheckConfig.HealthThreshold=s.healthThreshold}else{if(n.ipAddress)i.Properties.HealthCheckConfig.IPAddress=n.ipAddress;if(n.fullyQualifiedDomainName)i.Properties.HealthCheckConfig.FullyQualifiedDomainName=n.fullyQualifiedDomainName;if(n.port)i.Properties.HealthCheckConfig.Port=n.port;if(n.resourcePath)i.Properties.HealthCheckConfig.ResourcePath=n.resourcePath;if(n.enableSNI)i.Properties.HealthCheckConfig.EnableSNI=!0}return i}generateWeightedRecordSetCF(n){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:n.name,Type:n.type,TTL:n.ttl,ResourceRecords:n.resourceRecords,Weight:n.weight,SetIdentifier:n.setIdentifier,...n.healthCheckId&&{HealthCheckId:n.healthCheckId}}}}generateFailoverRecordSetCF(n){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:n.name,Type:n.type,TTL:n.ttl,ResourceRecords:n.resourceRecords,Failover:n.failover,SetIdentifier:n.setIdentifier,...n.healthCheckId&&{HealthCheckId:n.healthCheckId}}}}clear(){this.policies.clear(),this.healthChecks.clear(),this.trafficPolicies.clear(),this.policyCounter=0,this.healthCheckCounter=0,this.trafficPolicyCounter=0}}var kE=new vm;class Tm{configs=new Map;ksks=new Map;validations=new Map;configCounter=0;kskCounter=0;validationCounter=0;enableDNSSEC(n){let i=`dnssec-${Date.now()}-${this.configCounter++}`,s={id:i,hostedZoneId:n.hostedZoneId,status:"SIGNING",signingStatus:"Initializing DNSSEC signing"};if(this.configs.set(i,s),n.kmsKeyArn)this.createKSK({name:`ksk-${n.hostedZoneId}`,hostedZoneId:n.hostedZoneId,kmsKeyArn:n.kmsKeyArn});return setTimeout(()=>{s.status="SIGNED",s.signingStatus="DNSSEC signing complete"},100),s}disableDNSSEC(n){let i=this.configs.get(n);if(!i)throw Error(`DNSSEC config not found: ${n}`);return i.status="DELETING",i.signingStatus="Removing DNSSEC signing",setTimeout(()=>{i.status="NOT_SIGNING",i.signingStatus="DNSSEC signing removed"},100),i}createKSK(n){let i=`ksk-${Date.now()}-${this.kskCounter++}`,s={id:i,status:"ACTIVE",flag:257,keyManagementServiceArn:n.kmsKeyArn,digestAlgorithm:2,keyTag:Math.floor(Math.random()*65535),publicKey:this.generatePublicKey(),...n};s.dnskeyRecord=`${s.flag} 3 8 ${s.publicKey}`;let o=this.generateDigest(s.dnskeyRecord);return s.digestValue=o,s.dsRecord=`${s.keyTag} 8 ${s.digestAlgorithm} ${o}`,this.ksks.set(i,s),s}deactivateKSK(n){let i=this.ksks.get(n);if(!i)throw Error(`KSK not found: ${n}`);return i.status="INACTIVE",i}validateDNSSEC(n){let i=`validation-${Date.now()}-${this.validationCounter++}`,s=n.checkDNSKEY!==!1?Math.random()>0.1:!1,o=n.checkRRSIG!==!1?Math.random()>0.1:!1,c=s&&o,l=[];if(!s)l.push("DNSKEY record not found");if(!o)l.push("RRSIG record not found");let u;if(!s&&!o)u="INSECURE";else if(s&&o&&c)u="VALID";else if(s||o)u="BOGUS",l.push("Invalid signature or incomplete DNSSEC chain");else u="INVALID";let h={id:i,domain:n.domain,validationStatus:u,dnskeyPresent:s,rrsigPresent:o,validSignature:c,errors:l};return this.validations.set(i,h),h}getDNSSECConfig(n){return this.configs.get(n)}listDNSSECConfigs(){return Array.from(this.configs.values())}getKSK(n){return this.ksks.get(n)}listKSKs(n){let i=Array.from(this.ksks.values());return n?i.filter((s)=>s.hostedZoneId===n):i}getDSRecord(n){let i=this.ksks.get(n);if(!i||!i.dsRecord)throw Error("DS record not available");return i.dsRecord}generatePublicKey(){let n="";for(let i=0;i<256;i++)n+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(Math.floor(Math.random()*64));return n}generateDigest(n){let i="";for(let s=0;s<64;s++)i+="0123456789ABCDEF".charAt(Math.floor(Math.random()*16));return i}generateDNSSECCF(n){return{Type:"AWS::Route53::DNSSEC",Properties:{HostedZoneId:n.hostedZoneId}}}generateKSKCF(n){return{Type:"AWS::Route53::KeySigningKey",Properties:{Name:n.name,HostedZoneId:n.hostedZoneId,KeyManagementServiceArn:n.keyManagementServiceArn,Status:n.status}}}clear(){this.configs.clear(),this.ksks.clear(),this.validations.clear(),this.configCounter=0,this.kskCounter=0,this.validationCounter=0}}var BE=new Tm;class wm{endpoints=new Map;rules=new Map;firewalls=new Map;ruleGroups=new Map;domainLists=new Map;endpointCounter=0;ruleCounter=0;firewallCounter=0;ruleGroupCounter=0;domainListCounter=0;createResolverEndpoint(n){let i=`endpoint-${Date.now()}-${this.endpointCounter++}`,s={id:i,status:"CREATING",...n};return this.endpoints.set(i,s),setTimeout(()=>{s.status="OPERATIONAL",s.ipAddresses.forEach((o)=>{if(!o.ip)o.ip=`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`})},100),s}createInboundEndpoint(n){return this.createResolverEndpoint({name:n.name,direction:"INBOUND",ipAddresses:n.subnetIds.map((i)=>({subnetId:i})),securityGroupIds:n.securityGroupIds})}createOutboundEndpoint(n){return this.createResolverEndpoint({name:n.name,direction:"OUTBOUND",ipAddresses:n.subnetIds.map((i)=>({subnetId:i})),securityGroupIds:n.securityGroupIds})}createResolverRule(n){let i=`rule-${Date.now()}-${this.ruleCounter++}`,s={id:i,status:"CREATING",...n};return this.rules.set(i,s),setTimeout(()=>{s.status="COMPLETE"},100),s}createForwardRule(n){return this.createResolverRule({name:n.name,ruleType:"FORWARD",domainName:n.domainName,targetIps:n.targetIps,resolverEndpointId:n.resolverEndpointId})}createSystemRule(n){return this.createResolverRule({name:n.name,ruleType:"SYSTEM",domainName:n.domainName})}createFirewallDomainList(n){let i=`domain-list-${Date.now()}-${this.domainListCounter++}`,s={id:i,status:"CREATING",...n};return this.domainLists.set(i,s),setTimeout(()=>{s.status="COMPLETE"},100),s}createFirewallRuleGroup(n){let i=`rule-group-${Date.now()}-${this.ruleGroupCounter++}`,s={id:i,name:n.name,rules:n.rules.map((o,c)=>({id:`rule-${i}-${c}`,...o})),shareStatus:"NOT_SHARED"};return this.ruleGroups.set(i,s),s}createBlockRule(n){return this.createFirewallRuleGroup({name:n.name,rules:[{name:n.name,priority:n.priority,action:"BLOCK",blockResponse:n.blockResponse||"NODATA",blockOverrideDomain:n.blockOverrideDomain,firewallDomainListId:n.domainListId}]})}createAllowRule(n){return this.createFirewallRuleGroup({name:n.name,rules:[{name:n.name,priority:n.priority,action:"ALLOW",firewallDomainListId:n.domainListId}]})}createDNSFirewall(n){let i=`firewall-${Date.now()}-${this.firewallCounter++}`,s={id:i,name:n.name,firewallRuleGroupAssociations:n.ruleGroupAssociations.map((o,c)=>({id:`assoc-${i}-${c}`,vpcId:n.vpcId,firewallRuleGroupId:o.firewallRuleGroupId,priority:o.priority,mutationProtection:o.mutationProtection||"DISABLED",status:"COMPLETE"}))};return this.firewalls.set(i,s),s}createMalwareProtectionFirewall(n){let i=this.createFirewallDomainList({name:`${n.name}-malware-domains`,domains:n.maliciousDomains}),s=this.createBlockRule({name:`${n.name}-block-malware`,priority:100,domainListId:i.id,blockResponse:"NXDOMAIN"});return this.createDNSFirewall({name:n.name,vpcId:n.vpcId,ruleGroupAssociations:[{firewallRuleGroupId:s.id,priority:100,mutationProtection:"ENABLED"}]})}getEndpoint(n){return this.endpoints.get(n)}listEndpoints(n){let i=Array.from(this.endpoints.values());return n?i.filter((s)=>s.direction===n):i}getRule(n){return this.rules.get(n)}listRules(){return Array.from(this.rules.values())}getFirewall(n){return this.firewalls.get(n)}listFirewalls(){return Array.from(this.firewalls.values())}generateResolverEndpointCF(n){return{Type:"AWS::Route53Resolver::ResolverEndpoint",Properties:{Name:n.name,Direction:n.direction,IpAddresses:n.ipAddresses.map((i)=>({SubnetId:i.subnetId,...i.ip&&{Ip:i.ip}})),SecurityGroupIds:n.securityGroupIds}}}generateResolverRuleCF(n){return{Type:"AWS::Route53Resolver::ResolverRule",Properties:{Name:n.name,RuleType:n.ruleType,DomainName:n.domainName,...n.targetIps&&{TargetIps:n.targetIps.map((i)=>({Ip:i.ip,Port:i.port||53}))},...n.resolverEndpointId&&{ResolverEndpointId:n.resolverEndpointId}}}}generateFirewallRuleGroupCF(n){return{Type:"AWS::Route53Resolver::FirewallRuleGroup",Properties:{Name:n.name,FirewallRules:n.rules.map((i)=>({Name:i.name,Priority:i.priority,Action:i.action,FirewallDomainListId:i.firewallDomainListId,...i.blockResponse&&{BlockResponse:i.blockResponse},...i.blockOverrideDomain&&{BlockOverrideDomain:i.blockOverrideDomain},...i.blockOverrideTTL&&{BlockOverrideTtl:i.blockOverrideTTL}}))}}}clear(){this.endpoints.clear(),this.rules.clear(),this.firewalls.clear(),this.ruleGroups.clear(),this.domainLists.clear(),this.endpointCounter=0,this.ruleCounter=0,this.firewallCounter=0,this.ruleGroupCounter=0,this.domainListCounter=0}}var _E=new wm;class Rm{bounces=new Map;complaints=new Map;handlers=new Map;suppressionList=new Map;metrics=new Map;bounceCounter=0;complaintCounter=0;handlerCounter=0;suppressionCounter=0;metricsCounter=0;recordBounce(n){let i=`bounce-${Date.now()}-${this.bounceCounter++}`,s={id:i,...n};if(this.bounces.set(i,s),n.bounceType==="Permanent")this.addToSuppressionList({emailAddress:n.recipient,reason:"BOUNCE"});return s}recordComplaint(n){let i=`complaint-${Date.now()}-${this.complaintCounter++}`,s={id:i,...n};this.complaints.set(i,s);for(let o of n.recipients)this.addToSuppressionList({emailAddress:o,reason:"COMPLAINT"});return s}createBounceHandler(n){let i=`handler-${Date.now()}-${this.handlerCounter++}`,s={id:i,...n};return this.handlers.set(i,s),s}createAutomaticBounceHandler(n){return this.createBounceHandler({name:n.name,bounceThreshold:5,complaintThreshold:0.1,suppressionDuration:2592000,autoSuppress:!0,notificationTopicArn:n.notificationTopicArn})}addToSuppressionList(n){let i=`suppression-${Date.now()}-${this.suppressionCounter++}`,s=n.expirationDays?new Date(Date.now()+n.expirationDays*24*60*60*1000):void 0,o={id:i,emailAddress:n.emailAddress,reason:n.reason,suppressedAt:new Date,expiresAt:s,bounceCount:n.reason==="BOUNCE"?1:0,complaintCount:n.reason==="COMPLAINT"?1:0};return this.suppressionList.set(n.emailAddress,o),o}removeFromSuppressionList(n){return this.suppressionList.delete(n)}isSuppressed(n){let i=this.suppressionList.get(n);if(!i)return!1;if(i.expiresAt&&i.expiresAt<new Date)return this.suppressionList.delete(n),!1;return!0}getBounceStatistics(n,i){let s=Array.from(this.bounces.values()).filter((b)=>b.timestamp>=n&&b.timestamp<=i),o=s.length,c=s.filter((b)=>b.bounceType==="Permanent").length,l=s.filter((b)=>b.bounceType==="Transient").length,u=o*10,h=o/u*100,f=new Map;for(let b of s)f.set(b.recipient,(f.get(b.recipient)||0)+1);let S=Array.from(f.entries()).map(([b,A])=>({email:b,count:A})).sort((b,A)=>A.count-b.count).slice(0,10);return{totalBounces:o,permanentBounces:c,transientBounces:l,bounceRate:h,topRecipients:S}}getComplaintStatistics(n,i){let s=Array.from(this.complaints.values()).filter((f)=>f.timestamp>=n&&f.timestamp<=i),o=s.length,c=new Set;for(let f of s)for(let S of f.recipients)c.add(S);let l=c.size,u=o*1000,h=o/u*100;return{totalComplaints:o,uniqueComplainters:l,complaintRate:h}}calculateReputationMetrics(){let n=`metrics-${Date.now()}-${this.metricsCounter++}`,i=new Date,s=new Date(i.getTime()-86400000),o=this.getBounceStatistics(s,i),c=this.getComplaintStatistics(s,i),l;if(o.bounceRate>10||c.complaintRate>0.5)l="Shutdown";else if(o.bounceRate>5||c.complaintRate>0.1)l="Probation";else if(o.bounceRate>2||c.complaintRate>0.05)l="Warning";else l="Good";let u={id:n,timestamp:i,bounceRate:o.bounceRate,complaintRate:c.complaintRate,sendingQuota:50000,maxSendRate:14,sentLast24Hours:o.totalBounces*10,reputationStatus:l};return this.metrics.set(n,u),u}getBounces(n){let i=Array.from(this.bounces.values());return n?i.filter((s)=>s.messageId===n):i}getComplaints(n){let i=Array.from(this.complaints.values());return n?i.filter((s)=>s.messageId===n):i}listSuppressionList(n){let i=Array.from(this.suppressionList.values());return n?i.filter((s)=>s.reason===n):i}generateSNSSubscriptionCF(n){return{Type:"AWS::SNS::Subscription",Properties:{TopicArn:n.topicArn,Endpoint:n.endpoint,Protocol:n.protocol}}}generateEventDestinationCF(n){return{Type:"AWS::SES::ConfigurationSetEventDestination",Properties:{ConfigurationSetName:n.configurationSetName,EventDestination:{Name:n.eventDestinationName,Enabled:!0,MatchingEventTypes:n.eventTypes,...n.snsTopicArn&&{SnsDestination:{TopicARN:n.snsTopicArn}},...n.cloudWatchDestination&&{CloudWatchDestination:n.cloudWatchDestination}}}}}clear(){this.bounces.clear(),this.complaints.clear(),this.handlers.clear(),this.suppressionList.clear(),this.metrics.clear(),this.bounceCounter=0,this.complaintCounter=0,this.handlerCounter=0,this.suppressionCounter=0,this.metricsCounter=0}}var xE=new Rm;class Dm{events=new Map;campaigns=new Map;reports=new Map;abTests=new Map;eventCounter=0;campaignCounter=0;reportCounter=0;abTestCounter=0;trackEvent(n){let i=`event-${Date.now()}-${this.eventCounter++}`,s={id:i,...n};if(this.events.set(i,s),n.tags?.campaignId)this.updateCampaignStats(n.tags.campaignId,n.eventType);return s}trackOpen(n){return this.trackEvent({...n,eventType:"open",timestamp:new Date})}trackClick(n){return this.trackEvent({...n,eventType:"click",timestamp:new Date})}createCampaign(n){let i=`campaign-${Date.now()}-${this.campaignCounter++}`,s={id:i,sentCount:0,deliveredCount:0,openCount:0,clickCount:0,bounceCount:0,complaintCount:0,createdAt:new Date,...n};return this.campaigns.set(i,s),s}updateCampaignStats(n,i){let s=this.campaigns.get(n);if(!s)return;switch(i){case"send":s.sentCount++;break;case"delivery":s.deliveredCount++;break;case"open":s.openCount++;break;case"click":s.clickCount++;break;case"bounce":s.bounceCount++;break;case"complaint":s.complaintCount++;break}}generateReport(n){let i=`report-${Date.now()}-${this.reportCounter++}`,s=Array.from(this.events.values()).filter((I)=>{let _=I.timestamp>=n.startDate&&I.timestamp<=n.endDate,B=!n.campaignId||I.tags?.campaignId===n.campaignId;return _&&B}),o=s.filter((I)=>I.eventType==="send").length,c=s.filter((I)=>I.eventType==="delivery").length,l=s.filter((I)=>I.eventType==="open").length,u=s.filter((I)=>I.eventType==="click").length,h=s.filter((I)=>I.eventType==="bounce").length,f=s.filter((I)=>I.eventType==="complaint").length,S=o>0?c/o*100:0,b=c>0?l/c*100:0,A=c>0?u/c*100:0,v=l>0?u/l*100:0,w=o>0?h/o*100:0,E=c>0?f/c*100:0,P=new Map;for(let I of s)if(I.eventType==="click"){let _=I;P.set(_.link,(P.get(_.link)||0)+1)}let R=Array.from(P.entries()).map(([I,_])=>({link:I,clicks:_})).sort((I,_)=>_.clicks-I.clicks).slice(0,10),D={desktop:0,mobile:0,tablet:0,unknown:0};for(let I of s)if(I.eventType==="open"||I.eventType==="click"){let _=I.userAgent.toLowerCase();if(_.includes("mobile"))D.mobile++;else if(_.includes("tablet"))D.tablet++;else if(_.includes("mozilla"))D.desktop++;else D.unknown++}let x={id:i,campaignId:n.campaignId,startDate:n.startDate,endDate:n.endDate,totalSent:o,totalDelivered:c,totalOpened:l,totalClicked:u,totalBounced:h,totalComplaints:f,deliveryRate:S,openRate:b,clickRate:A,clickToOpenRate:v,bounceRate:w,complaintRate:E,topLinks:R,deviceBreakdown:D,locationBreakdown:{}};return this.reports.set(i,x),x}createABTest(n){let i=`abtest-${Date.now()}-${this.abTestCounter++}`,s={id:i,name:n.name,variants:n.variants.map((o,c)=>({id:`variant-${i}-${c}`,sentCount:0,openCount:0,clickCount:0,conversionCount:0,...o})),status:"draft"};return this.abTests.set(i,s),s}startABTest(n){let i=this.abTests.get(n);if(!i)throw Error(`A/B test not found: ${n}`);return i.status="running",i.startedAt=new Date,i}completeABTest(n){let i=this.abTests.get(n);if(!i)throw Error(`A/B test not found: ${n}`);let s=i.variants[0],o=0;for(let c of i.variants){let l=c.sentCount>0?c.openCount/c.sentCount:0;if(l>o)o=l,s=c}return i.status="completed",i.completedAt=new Date,i.winner=s.id,i}getCampaign(n){return this.campaigns.get(n)}listCampaigns(){return Array.from(this.campaigns.values())}getEvents(n){let i=Array.from(this.events.values());if(n?.messageId)i=i.filter((s)=>s.messageId===n.messageId);if(n?.eventType)i=i.filter((s)=>s.eventType===n.eventType);if(n?.startDate)i=i.filter((s)=>s.timestamp>=n.startDate);if(n?.endDate)i=i.filter((s)=>s.timestamp<=n.endDate);return i}generateTrackingConfigurationCF(n){return{Type:"AWS::SES::ConfigurationSet",Properties:{Name:n.configurationSetName,...n.openTracking&&{TrackingOptions:{CustomRedirectDomain:"tracking.example.com"}}}}}clear(){this.events.clear(),this.campaigns.clear(),this.reports.clear(),this.abTests.clear(),this.eventCounter=0,this.campaignCounter=0,this.reportCounter=0,this.abTestCounter=0}}var OE=new Dm;class Pm{dashboards=new Map;warmupPlans=new Map;domainReputations=new Map;dashboardCounter=0;warmupCounter=0;domainCounter=0;getReputationDashboard(){let n=`dashboard-${Date.now()}-${this.dashboardCounter++}`,i=Math.random()*5,s=Math.random()*0.5,o=Math.floor(Math.random()*10),c=Math.max(0,100-i*10-s*100-o*2),l=[];if(i>2)l.push("Reduce bounce rate by cleaning email list");if(s>0.1)l.push("Review email content and unsubscribe process");if(o>5)l.push("Improve email relevance and targeting");let u={id:n,timestamp:new Date,overallScore:c,bounceRate:i,complaintRate:s,spamReports:o,blacklistStatus:this.checkBlacklists(),dkimStatus:"VERIFIED",spfStatus:"PASS",dmarcStatus:"PASS",sendingLimits:{maxSendRate:14,max24HourSend:50000,sentLast24Hours:12000,remainingQuota:38000,quotaResetTime:new Date(Date.now()+86400000)},recommendations:l};return this.dashboards.set(n,u),u}checkBlacklists(){return["Spamhaus ZEN","Spamcop","SORBS","Barracuda","URIBL"].map((n)=>({listName:n,listed:Math.random()>0.95,delistUrl:`https://www.${n.toLowerCase().replace(/\s/g,"")}.org/delist`}))}createWarmupPlan(n){let i=`warmup-${Date.now()}-${this.warmupCounter++}`,s=[],o=(n.targetDailyLimit-n.initialDailyLimit)/n.durationDays;for(let l=0;l<n.durationDays;l++)s.push(Math.floor(n.initialDailyLimit+o*l));let c={id:i,name:n.name,startDate:new Date,currentDay:1,totalDays:n.durationDays,dailyLimits:s,currentLimit:s[0],status:"active"};return this.warmupPlans.set(i,c),c}createAggressiveWarmupPlan(n){return this.createWarmupPlan({name:n.name,initialDailyLimit:500,targetDailyLimit:50000,durationDays:14})}createConservativeWarmupPlan(n){return this.createWarmupPlan({name:n.name,initialDailyLimit:200,targetDailyLimit:50000,durationDays:30})}advanceWarmupPlan(n){let i=this.warmupPlans.get(n);if(!i)throw Error(`Warmup plan not found: ${n}`);if(i.currentDay<i.totalDays)i.currentDay++,i.currentLimit=i.dailyLimits[i.currentDay-1];if(i.currentDay>=i.totalDays)i.status="completed";return i}trackDomainReputation(n){let i=`domain-${Date.now()}-${this.domainCounter++}`,s=n.delivered/n.totalSent*100,o=n.delivered>0?n.opened/n.delivered*100:0,c=n.delivered>0?n.clicked/n.delivered*100:0,l=n.bounced/n.totalSent*100,u=n.delivered>0?n.complained/n.delivered*100:0,h=o*0.4+c*0.6,f=Math.max(0,100-l*10-u*100+h*0.2),S={id:i,domain:n.domain,reputationScore:f,totalSent:n.totalSent,deliveryRate:s,openRate:o,clickRate:c,bounceRate:l,complaintRate:u,engagementScore:h};return this.domainReputations.set(n.domain,S),S}getDomainReputation(n){return this.domainReputations.get(n)}listDomainReputations(){return Array.from(this.domainReputations.values())}getWarmupPlan(n){return this.warmupPlans.get(n)}listWarmupPlans(){return Array.from(this.warmupPlans.values())}clear(){this.dashboards.clear(),this.warmupPlans.clear(),this.domainReputations.clear(),this.dashboardCounter=0,this.warmupCounter=0,this.domainCounter=0}}var LE=new Pm;class Nm{templates=new Map;versions=new Map;tests=new Map;templateCounter=0;testCounter=0;createTemplate(n){let i=`template-${Date.now()}-${this.templateCounter++}`,s=this.extractVariables(n.subject+n.htmlPart+n.textPart),o={id:i,variables:s,createdAt:new Date,updatedAt:new Date,version:1,...n};return this.templates.set(i,o),this.addVersion({templateId:i,version:1,subject:n.subject,htmlPart:n.htmlPart,textPart:n.textPart,createdBy:"system"}),o}createWelcomeTemplate(n){return this.createTemplate({name:n.name,subject:"Welcome to {{companyName}}!",htmlPart:`
|
|
3776
|
+
COPY . .`,impact:"Improve build time by 60-80% on subsequent builds"});let h={sizeBefore:i.totalSize,sizeAfter:i.totalSize*0.6,timeBefore:300,timeAfter:120},f={id:s,name:`Optimization for ${i.imageId}`,recommendations:o,estimatedSavings:h};return this.optimizations.set(s,f),f}getBuildConfig(n){return this.configs.get(n)}listBuildConfigs(){return Array.from(this.configs.values())}getMultiStageConfig(n){return this.multiStageConfigs.get(n)}listMultiStageConfigs(){return Array.from(this.multiStageConfigs.values())}getOptimization(n){return this.optimizations.get(n)}listOptimizations(){return Array.from(this.optimizations.values())}clear(){this.configs.clear(),this.multiStageConfigs.clear(),this.optimizations.clear(),this.analyses.clear(),this.configCounter=0,this.multiStageCounter=0,this.optimizationCounter=0,this.analysisCounter=0}}var EE=new hm;class fm{registries=new Map;credentials=new Map;registryCounter=0;credentialsCounter=0;createRegistry(n){let i=`registry-${Date.now()}-${this.registryCounter++}`,s={id:i,...n};return this.registries.set(i,s),s}createECRRepository(n){return this.createRegistry({name:n.name,registryType:"ecr",repositoryUri:`123456789012.dkr.ecr.${n.region||"us-east-1"}.amazonaws.com/${n.name}`,region:n.region||"us-east-1",encryption:{encryptionType:n.encryption||"AES256",kmsKeyId:n.kmsKeyId},scanning:{scanOnPush:n.scanOnPush??!0}})}createManagedRepository(n){let i=this.createECRRepository({name:n.name,region:n.region,scanOnPush:!0,encryption:"KMS"});return i.lifecycle={id:`lifecycle-${Date.now()}`,rules:[{rulePriority:1,description:"Keep only last N images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:n.maxImageCount||10},action:{type:"expire"}},{rulePriority:2,description:"Remove images older than N days",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:n.maxImageAgeDays||30,countUnit:"days"},action:{type:"expire"}}]},i}enableReplication(n,i){let s=this.registries.get(n);if(!s)throw Error(`Registry not found: ${n}`);return s.replication={enabled:!0,destinations:i},s}createCredentials(n){let i=`creds-${Date.now()}-${this.credentialsCounter++}`,s={id:i,...n};return this.credentials.set(i,s),s}getRegistry(n){return this.registries.get(n)}listRegistries(){return Array.from(this.registries.values())}generateECRRepositoryCF(n){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:n.name,ImageScanningConfiguration:{ScanOnPush:n.scanning?.scanOnPush??!1},EncryptionConfiguration:{EncryptionType:n.encryption?.encryptionType||"AES256",...n.encryption?.kmsKeyId&&{KmsKey:n.encryption.kmsKeyId}},ImageTagMutability:"MUTABLE",...n.lifecycle&&{LifecyclePolicy:{LifecyclePolicyText:JSON.stringify({rules:n.lifecycle.rules})}}}}}generateReplicationConfigCF(n){return{Type:"AWS::ECR::ReplicationConfiguration",Properties:{ReplicationConfiguration:{Rules:n.destinations.map((i)=>({Destinations:[{Region:i.region,...i.registryId&&{RegistryId:i.registryId}}]}))}}}}clear(){this.registries.clear(),this.credentials.clear(),this.registryCounter=0,this.credentialsCounter=0}}var bE=new fm;class Am{meshes=new Map;virtualNodes=new Map;virtualRouters=new Map;virtualGateways=new Map;meshCounter=0;nodeCounter=0;routerCounter=0;gatewayCounter=0;createMesh(n){let i=`mesh-${Date.now()}-${this.meshCounter++}`,s={id:i,...n};return this.meshes.set(i,s),s}createAppMesh(n){return this.createMesh({name:n.name,meshType:"app_mesh",services:n.services,virtualNodes:[],virtualRouters:[],virtualGateways:[]})}createVirtualNode(n){let i=`vnode-${Date.now()}-${this.nodeCounter++}`,s={id:i,...n};return this.virtualNodes.set(i,s),s}createHTTPVirtualNode(n){return this.createVirtualNode({name:n.name,serviceName:n.serviceName,listeners:[{port:n.port,protocol:"http",healthCheck:{protocol:"http",path:"/health",interval:30,timeout:10,healthyThreshold:2,unhealthyThreshold:3},timeout:{perRequest:15000,idle:300000}}],serviceDiscovery:{type:"aws_cloud_map",namespace:n.namespace,serviceName:n.serviceName}})}createVirtualRouter(n){let i=`vrouter-${Date.now()}-${this.routerCounter++}`,s={id:i,...n};return this.virtualRouters.set(i,s),s}createCanaryRoute(n){return this.createVirtualRouter({name:n.name,listeners:[{port:n.port,protocol:n.protocol}],routes:[{name:"canary-route",match:{prefix:"/"},action:{weightedTargets:[{virtualNode:n.stableTarget,weight:100-n.canaryWeight},{virtualNode:n.canaryTarget,weight:n.canaryWeight}]},retryPolicy:{maxRetries:3,perRetryTimeout:5000,httpRetryEvents:["server-error","gateway-error"],tcpRetryEvents:["connection-error"]}}]})}createVirtualGateway(n){let i=`vgateway-${Date.now()}-${this.gatewayCounter++}`,s={id:i,...n};return this.virtualGateways.set(i,s),s}createIngressGateway(n){let i={port:n.port,protocol:"http",healthCheck:{protocol:"http",path:"/health",interval:30,timeout:10,healthyThreshold:2,unhealthyThreshold:3}};if(n.enableTLS&&n.certificateArn)i.tls={mode:"STRICT",certificate:{acm:n.certificateArn}};return this.createVirtualGateway({name:n.name,listeners:[i],logging:{accessLog:{file:{path:"/dev/stdout"}}}})}getMesh(n){return this.meshes.get(n)}listMeshes(){return Array.from(this.meshes.values())}getVirtualNode(n){return this.virtualNodes.get(n)}listVirtualNodes(){return Array.from(this.virtualNodes.values())}generateMeshCF(n){return{Type:"AWS::AppMesh::Mesh",Properties:{MeshName:n.name,Spec:{EgressFilter:{Type:"ALLOW_ALL"}}}}}generateVirtualNodeCF(n,i){return{Type:"AWS::AppMesh::VirtualNode",Properties:{MeshName:i,VirtualNodeName:n.name,Spec:{Listeners:n.listeners.map((s)=>({PortMapping:{Port:s.port,Protocol:s.protocol},...s.healthCheck&&{HealthCheck:{Protocol:s.healthCheck.protocol,...s.healthCheck.path&&{Path:s.healthCheck.path},IntervalMillis:s.healthCheck.interval*1000,TimeoutMillis:s.healthCheck.timeout*1000,HealthyThreshold:s.healthCheck.healthyThreshold,UnhealthyThreshold:s.healthCheck.unhealthyThreshold}}})),ServiceDiscovery:{AWSCloudMap:{NamespaceName:n.serviceDiscovery.namespace,ServiceName:n.serviceDiscovery.serviceName}}}}}}generateVirtualRouterCF(n,i){return{Type:"AWS::AppMesh::VirtualRouter",Properties:{MeshName:i,VirtualRouterName:n.name,Spec:{Listeners:n.listeners.map((s)=>({PortMapping:{Port:s.port,Protocol:s.protocol}}))}}}}clear(){this.meshes.clear(),this.virtualNodes.clear(),this.virtualRouters.clear(),this.virtualGateways.clear(),this.meshCounter=0,this.nodeCounter=0,this.routerCounter=0,this.gatewayCounter=0}}var vE=new Am;class ym{layers=new Map;versions=new Map;permissions=new Map;layerCounter=0;versionCounter=0;permissionCounter=0;createLayer(n){let i=`layer-${Date.now()}-${this.layerCounter++}`,s=1,o={id:i,layerArn:`arn:aws:lambda:us-east-1:123456789012:layer:${n.layerName}:1`,version:1,...n};return this.layers.set(i,o),o}createNodeDependenciesLayer(n){return this.createLayer({layerName:n.layerName,description:"Node.js dependencies layer",compatibleRuntimes:[`nodejs${n.nodeVersion}`],content:{type:"s3",s3Bucket:n.s3Bucket,s3Key:n.s3Key},size:5242880})}createUtilitiesLayer(n){return this.createLayer({layerName:n.layerName,description:"Shared utilities and helpers",compatibleRuntimes:n.runtimes,content:{type:"s3",s3Bucket:n.s3Bucket,s3Key:n.s3Key},size:1048576})}publishVersion(n){let i=this.layers.get(n);if(!i)throw Error(`Layer not found: ${n}`);let s=`version-${Date.now()}-${this.versionCounter++}`,o=i.version+1,c={id:s,layerName:i.layerName,version:o,createdAt:new Date,compatibleRuntimes:i.compatibleRuntimes,size:i.size,codeHash:this.generateHash()};return this.versions.set(s,c),i.version=o,i.layerArn=`arn:aws:lambda:us-east-1:123456789012:layer:${i.layerName}:${o}`,c}addPermission(n){let i=`permission-${Date.now()}-${this.permissionCounter++}`,s={id:i,layerName:n.layerName,version:n.version,principal:n.principal,action:"lambda:GetLayerVersion",organizationId:n.organizationId};return this.permissions.set(i,s),s}generateHash(){return Math.random().toString(36).substring(2,15)}getLayer(n){return this.layers.get(n)}listLayers(){return Array.from(this.layers.values())}getLayerVersions(n){return Array.from(this.versions.values()).filter((i)=>i.layerName===n)}generateLayerCF(n){return{Type:"AWS::Lambda::LayerVersion",Properties:{LayerName:n.layerName,Description:n.description,Content:n.content.type==="s3"?{S3Bucket:n.content.s3Bucket,S3Key:n.content.s3Key,...n.content.s3ObjectVersion&&{S3ObjectVersion:n.content.s3ObjectVersion}}:{ZipFile:n.content.zipFile},CompatibleRuntimes:n.compatibleRuntimes,...n.licenseInfo&&{LicenseInfo:n.licenseInfo}}}}generateLayerPermissionCF(n){return{Type:"AWS::Lambda::LayerVersionPermission",Properties:{LayerVersionArn:`arn:aws:lambda:us-east-1:123456789012:layer:${n.layerName}:${n.version}`,Action:n.action,Principal:n.principal,...n.organizationId&&{OrganizationId:n.organizationId}}}}clear(){this.layers.clear(),this.versions.clear(),this.permissions.clear(),this.layerCounter=0,this.versionCounter=0,this.permissionCounter=0}}var TE=new ym;class Im{versions=new Map;aliases=new Map;deployments=new Map;versionCounter=0;aliasCounter=0;deploymentCounter=0;publishVersion(n){let i=`version-${Date.now()}-${this.versionCounter++}`,s=this.getNextVersionNumber(n.functionName),o={id:i,functionName:n.functionName,version:s.toString(),functionArn:`arn:aws:lambda:us-east-1:123456789012:function:${n.functionName}:${s}`,codeHash:this.generateHash(),description:n.description,runtime:n.runtime,memorySize:n.memorySize,timeout:n.timeout,publishedAt:new Date};return this.versions.set(i,o),o}getNextVersionNumber(n){let i=Array.from(this.versions.values()).filter((s)=>s.functionName===n).map((s)=>parseInt(s.version));return i.length>0?Math.max(...i)+1:1}createAlias(n){let i=`alias-${Date.now()}-${this.aliasCounter++}`,s={id:i,aliasArn:`arn:aws:lambda:us-east-1:123456789012:function:${n.functionName}:${n.aliasName}`,revisionId:this.generateHash(),...n};return this.aliases.set(i,s),s}createProductionAlias(n){return this.createAlias({functionName:n.functionName,aliasName:"production",functionVersion:n.version,description:"Production alias"})}createStagingAlias(n){return this.createAlias({functionName:n.functionName,aliasName:"staging",functionVersion:n.version,description:"Staging alias"})}updateAlias(n,i){let s=this.aliases.get(n);if(!s)throw Error(`Alias not found: ${n}`);return s.functionVersion=i,s.revisionId=this.generateHash(),s}configureWeightedRouting(n,i){let s=this.aliases.get(n);if(!s)throw Error(`Alias not found: ${n}`);return s.routingConfig={additionalVersionWeights:i},s}createCanaryDeployment(n){let i=`deployment-${Date.now()}-${this.deploymentCounter++}`,s=Array.from(this.aliases.values()).find((c)=>c.functionName===n.functionName&&c.aliasName===n.aliasName);if(!s)s=this.createAlias({functionName:n.functionName,aliasName:n.aliasName,functionVersion:n.fromVersion});this.configureWeightedRouting(s.id,{[n.toVersion]:n.canaryWeight});let o={id:i,functionName:n.functionName,fromVersion:n.fromVersion,toVersion:n.toVersion,aliasName:n.aliasName,strategy:"canary",status:"in_progress",startedAt:new Date};return this.deployments.set(i,o),o}completeDeployment(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);let s=Array.from(this.aliases.values()).find((o)=>o.functionName===i.functionName&&o.aliasName===i.aliasName);if(s)s.functionVersion=i.toVersion,s.routingConfig=void 0;return i.status="completed",i.completedAt=new Date,i}rollbackDeployment(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);let s=Array.from(this.aliases.values()).find((o)=>o.functionName===i.functionName&&o.aliasName===i.aliasName);if(s)s.functionVersion=i.fromVersion,s.routingConfig=void 0;return i.status="failed",i.completedAt=new Date,i}generateHash(){return Math.random().toString(36).substring(2,15)}getVersion(n){return this.versions.get(n)}listVersions(n){let i=Array.from(this.versions.values());return n?i.filter((s)=>s.functionName===n):i}getAlias(n){return this.aliases.get(n)}listAliases(n){let i=Array.from(this.aliases.values());return n?i.filter((s)=>s.functionName===n):i}generateVersionCF(n){return{Type:"AWS::Lambda::Version",Properties:{FunctionName:n.functionName,Description:n.description}}}generateAliasCF(n){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:n.functionName,Name:n.aliasName,FunctionVersion:n.functionVersion,Description:n.description,...n.routingConfig&&{RoutingConfig:{AdditionalVersionWeights:Object.entries(n.routingConfig.additionalVersionWeights||{}).map(([i,s])=>({FunctionVersion:i,FunctionWeight:s}))}}}}}clear(){this.versions.clear(),this.aliases.clear(),this.deployments.clear(),this.versionCounter=0,this.aliasCounter=0,this.deploymentCounter=0}}var wE=new Im;class Sm{configs=new Map;provisionedConfigs=new Map;schedules=new Map;autoScalingConfigs=new Map;configCounter=0;provisionedCounter=0;scheduleCounter=0;autoScalingCounter=0;setReservedConcurrency(n){let i=`concurrency-${Date.now()}-${this.configCounter++}`,s={id:i,functionName:n.functionName,reservedConcurrency:n.reservedConcurrency};return this.configs.set(i,s),s}setProvisionedConcurrency(n){let i=`provisioned-${Date.now()}-${this.provisionedCounter++}`,s={id:i,functionName:n.functionName,qualifier:n.qualifier,provisionedConcurrentExecutions:n.provisionedConcurrentExecutions,status:"pending",lastModified:new Date};return this.provisionedConfigs.set(i,s),setTimeout(()=>{s.status="ready",s.allocatedConcurrency=n.provisionedConcurrentExecutions,s.availableConcurrency=n.provisionedConcurrentExecutions},100),s}configureWarmPool(n){return this.setProvisionedConcurrency({functionName:n.functionName,qualifier:n.alias,provisionedConcurrentExecutions:n.minInstances})}createSchedule(n){let i=`schedule-${Date.now()}-${this.scheduleCounter++}`,s={id:i,...n};return this.schedules.set(i,s),s}createBusinessHoursSchedule(n){return this.createSchedule({name:`${n.functionName}-business-hours`,functionName:n.functionName,qualifier:n.qualifier,schedule:[{name:"business-hours",cronExpression:"0 8 * * MON-FRI",targetConcurrency:n.businessHoursConcurrency},{name:"off-hours",cronExpression:"0 18 * * MON-FRI",targetConcurrency:n.offHoursConcurrency},{name:"weekend",cronExpression:"0 0 * * SAT",targetConcurrency:n.offHoursConcurrency}]})}configureAutoScaling(n){let i=`autoscaling-${Date.now()}-${this.autoScalingCounter++}`,s={id:i,...n};return this.autoScalingConfigs.set(i,s),s}configurePredictiveScaling(n){return this.configureAutoScaling({functionName:n.functionName,qualifier:n.qualifier,minCapacity:n.baselineCapacity,maxCapacity:n.peakCapacity,targetUtilization:0.7,scaleInCooldown:300,scaleOutCooldown:60})}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getProvisionedConfig(n){return this.provisionedConfigs.get(n)}listProvisionedConfigs(){return Array.from(this.provisionedConfigs.values())}generateReservedConcurrencyCF(n){return{Type:"AWS::Lambda::Function",Properties:{FunctionName:n.functionName,ReservedConcurrentExecutions:n.reservedConcurrency}}}generateProvisionedConcurrencyCF(n){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:n.functionName,Name:n.qualifier,ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:n.provisionedConcurrentExecutions}}}}generateAutoScalingTargetCF(n){return{Type:"AWS::ApplicationAutoScaling::ScalableTarget",Properties:{ServiceNamespace:"lambda",ResourceId:`function:${n.functionName}:${n.qualifier}`,ScalableDimension:"lambda:function:ProvisionedConcurrentExecutions",MinCapacity:n.minCapacity,MaxCapacity:n.maxCapacity}}}generateAutoScalingPolicyCF(n){return{Type:"AWS::ApplicationAutoScaling::ScalingPolicy",Properties:{PolicyName:`${n.functionName}-autoscaling`,PolicyType:"TargetTrackingScaling",ScalingTargetId:{Ref:`${n.functionName}AutoScalingTarget`},TargetTrackingScalingPolicyConfiguration:{TargetValue:n.targetUtilization*100,PredefinedMetricSpecification:{PredefinedMetricType:"LambdaProvisionedConcurrencyUtilization"},ScaleInCooldown:n.scaleInCooldown||300,ScaleOutCooldown:n.scaleOutCooldown||60}}}}clear(){this.configs.clear(),this.provisionedConfigs.clear(),this.schedules.clear(),this.autoScalingConfigs.clear(),this.configCounter=0,this.provisionedCounter=0,this.scheduleCounter=0,this.autoScalingCounter=0}}var RE=new Sm;class Cm{destinations=new Map;records=new Map;eventBridgeDestinations=new Map;destinationCounter=0;recordCounter=0;eventBridgeCounter=0;configureDestinations(n){let i=`destination-${Date.now()}-${this.destinationCounter++}`,s={id:i,...n};return this.destinations.set(i,s),s}configureSQSDestination(n){let i={type:"sqs",arn:n.queueArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureSNSDestination(n){let i={type:"sns",arn:n.topicArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureEventBridgeDestination(n){let i={type:"eventbridge",arn:n.eventBusArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureLambdaDestination(n){let i={type:"lambda",arn:n.destinationFunctionArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureDLQWithNotification(n){return this.configureDestinations({functionName:n.functionName,failureDestination:{type:"sqs",arn:n.dlqArn},maxEventAge:3600,maxRetries:0})}createEventBridgeIntegration(n){let i=`eventbridge-${Date.now()}-${this.eventBridgeCounter++}`,s={id:i,functionName:n.functionName,eventBusArn:n.eventBusArn,detailType:n.detailType||"Lambda Function Invocation Result",source:n.source||`lambda.${n.functionName}`};return this.eventBridgeDestinations.set(i,s),s}sendToDestination(n){let i=Array.from(this.destinations.values()).find((l)=>l.functionName===n.functionName);if(!i)return null;let s=n.status==="success"?i.successDestination:i.failureDestination;if(!s)return null;let o=`record-${Date.now()}-${this.recordCounter++}`,c={id:o,timestamp:new Date,functionName:n.functionName,requestId:n.requestId,status:n.status,destinationType:s.type,destinationArn:s.arn,payload:n.payload,error:n.error};return this.records.set(o,c),c}getDestination(n){return this.destinations.get(n)}listDestinations(n){let i=Array.from(this.destinations.values());return n?i.filter((s)=>s.functionName===n):i}getDestinationRecords(n){let i=Array.from(this.records.values());return n?i.filter((s)=>s.functionName===n):i}generateEventInvokeConfigCF(n){return{Type:"AWS::Lambda::EventInvokeConfig",Properties:{FunctionName:n.functionName,Qualifier:n.qualifier||"$LATEST",MaximumEventAgeInSeconds:n.maxEventAge||21600,MaximumRetryAttempts:n.maxRetries??2,...n.successDestination&&{DestinationConfig:{OnSuccess:{Destination:n.successDestination.arn}}},...n.failureDestination&&{DestinationConfig:{OnFailure:{Destination:n.failureDestination.arn}}}}}}generateEventBridgeRuleCF(n){return{Type:"AWS::Events::Rule",Properties:{EventBusName:n.eventBusArn.split("/").pop(),EventPattern:{source:[n.source],"detail-type":[n.detailType]},State:"ENABLED",Targets:[{Arn:`arn:aws:lambda:us-east-1:123456789012:function:${n.functionName}`,Id:n.id}]}}}clear(){this.destinations.clear(),this.records.clear(),this.eventBridgeDestinations.clear(),this.destinationCounter=0,this.recordCounter=0,this.eventBridgeCounter=0}}var DE=new Cm;class Em{vpcConfigs=new Map;endpoints=new Map;networkInterfaces=new Map;connectivity=new Map;configCounter=0;endpointCounter=0;eniCounter=0;connectivityCounter=0;configureVPC(n){let i=`vpc-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};this.vpcConfigs.set(i,s);for(let o of n.subnetIds)this.createNetworkInterface({functionName:n.functionName,subnetId:o});return s}configurePrivateVPC(n){return this.configureVPC({functionName:n.functionName,vpcId:n.vpcId,subnetIds:n.privateSubnetIds,securityGroupIds:[n.securityGroupId],ipv6Allowed:!1})}configureMultiAZVPC(n){if(n.subnetIds.length<2)throw Error("Multi-AZ configuration requires at least 2 subnets");return this.configureVPC({functionName:n.functionName,vpcId:n.vpcId,subnetIds:n.subnetIds,securityGroupIds:n.securityGroupIds})}createVPCEndpoint(n){let i=`endpoint-${Date.now()}-${this.endpointCounter++}`,s={id:i,...n};return this.endpoints.set(i,s),s}createS3Endpoint(n){return this.createVPCEndpoint({vpcId:n.vpcId,serviceName:"com.amazonaws.us-east-1.s3",endpointType:"Gateway",privateDnsEnabled:!1})}createDynamoDBEndpoint(n){return this.createVPCEndpoint({vpcId:n.vpcId,serviceName:"com.amazonaws.us-east-1.dynamodb",endpointType:"Gateway",privateDnsEnabled:!1})}createSecretsManagerEndpoint(n){return this.createVPCEndpoint({vpcId:n.vpcId,serviceName:"com.amazonaws.us-east-1.secretsmanager",endpointType:"Interface",subnetIds:n.subnetIds,securityGroupIds:n.securityGroupIds,privateDnsEnabled:!0})}createNetworkInterface(n){let i=`eni-${Date.now()}-${this.eniCounter++}`,s={id:i,functionName:n.functionName,networkInterfaceId:`eni-${Math.random().toString(36).substring(2,15)}`,subnetId:n.subnetId,privateIpAddress:`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`,status:"creating",attachedAt:new Date};return this.networkInterfaces.set(i,s),setTimeout(()=>{s.status="available"},100),s}analyzeConnectivity(n){let i=`connectivity-${Date.now()}-${this.connectivityCounter++}`,s=Array.from(this.vpcConfigs.values()).find((f)=>f.functionName===n.functionName),o=Array.from(this.endpoints.values()).filter((f)=>f.vpcId===s?.vpcId).map((f)=>f.serviceName),c=[],l=n.hasNATGateway??!1,u=n.hasInternetGateway??!1;if(!l&&!u)c.push("Add NAT Gateway for internet access");if(!o.includes("com.amazonaws.us-east-1.s3"))c.push("Add S3 VPC endpoint to reduce NAT costs");if(!o.includes("com.amazonaws.us-east-1.dynamodb"))c.push("Add DynamoDB VPC endpoint for private access");let h={id:i,functionName:n.functionName,hasInternetAccess:l||u,hasNATGateway:l,hasVPCEndpoints:o.length>0,endpoints:o,recommendations:c};return this.connectivity.set(i,h),h}getVPCConfig(n){return this.vpcConfigs.get(n)}listVPCConfigs(n){let i=Array.from(this.vpcConfigs.values());return n?i.filter((s)=>s.functionName===n):i}getNetworkInterfaces(n){return Array.from(this.networkInterfaces.values()).filter((i)=>i.functionName===n)}listVPCEndpoints(n){let i=Array.from(this.endpoints.values());return n?i.filter((s)=>s.vpcId===n):i}generateVPCConfigCF(n){return{VpcConfig:{SubnetIds:n.subnetIds,SecurityGroupIds:n.securityGroupIds,...n.ipv6Allowed&&{Ipv6AllowedForDualStack:!0}}}}generateVPCEndpointCF(n){return{Type:"AWS::EC2::VPCEndpoint",Properties:{VpcId:n.vpcId,ServiceName:n.serviceName,VpcEndpointType:n.endpointType,...n.subnetIds&&{SubnetIds:n.subnetIds},...n.securityGroupIds&&{SecurityGroupIds:n.securityGroupIds},...n.privateDnsEnabled!==void 0&&{PrivateDnsEnabled:n.privateDnsEnabled}}}}generateSecurityGroupCF(n){return{Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:n.groupName,GroupDescription:`Security group for Lambda ${n.groupName}`,VpcId:n.vpcId,...n.ingressRules&&{SecurityGroupIngress:n.ingressRules.map((i)=>({IpProtocol:i.protocol,FromPort:i.fromPort,ToPort:i.toPort,...i.cidrIp&&{CidrIp:i.cidrIp},...i.sourceSecurityGroupId&&{SourceSecurityGroupId:i.sourceSecurityGroupId}}))},...n.egressRules&&{SecurityGroupEgress:n.egressRules.map((i)=>({IpProtocol:i.protocol,FromPort:i.fromPort,ToPort:i.toPort,CidrIp:i.cidrIp||"0.0.0.0/0"}))}}}}clear(){this.vpcConfigs.clear(),this.endpoints.clear(),this.networkInterfaces.clear(),this.connectivity.clear(),this.configCounter=0,this.endpointCounter=0,this.eniCounter=0,this.connectivityCounter=0}}var PE=new Em;class bm{dlqConfigs=new Map;messages=new Map;alarms=new Map;reprocessing=new Map;configCounter=0;messageCounter=0;alarmCounter=0;reprocessCounter=0;configureDLQ(n){let i=`dlq-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.dlqConfigs.set(i,s),s}configureSQSDLQ(n){return this.configureDLQ({functionName:n.functionName,targetArn:n.queueArn,targetType:"sqs",maxReceiveCount:n.maxReceiveCount||3,retentionPeriod:n.retentionPeriod||1209600})}configureSNSDLQ(n){return this.configureDLQ({functionName:n.functionName,targetArn:n.topicArn,targetType:"sns"})}configureDLQWithAlarm(n){let i=this.configureSQSDLQ({functionName:n.functionName,queueArn:n.queueArn});return this.createDLQAlarm({dlqConfigId:i.id,alarmName:`${n.functionName}-dlq-alarm`,threshold:n.alarmThreshold,evaluationPeriods:1,notificationTopicArn:n.notificationTopicArn,enabled:!0}),i}sendToDLQ(n){let i=`message-${Date.now()}-${this.messageCounter++}`,s={id:i,timestamp:new Date,...n};return this.messages.set(i,s),s}createDLQAlarm(n){let i=`alarm-${Date.now()}-${this.alarmCounter++}`,s={id:i,...n};return this.alarms.set(i,s),s}createAgeAlarm(n){let i=this.dlqConfigs.get(n.dlqConfigId);if(!i)throw Error(`DLQ config not found: ${n.dlqConfigId}`);return this.createDLQAlarm({dlqConfigId:n.dlqConfigId,alarmName:`${i.functionName}-dlq-age-alarm`,threshold:n.maxAgeSeconds,evaluationPeriods:1,notificationTopicArn:n.notificationTopicArn,enabled:!0})}async reprocessMessage(n){let i=this.messages.get(n);if(!i)throw Error(`Message not found: ${n}`);let s=Array.from(this.dlqConfigs.values()).find((l)=>l.functionName===i.functionName);if(!s)throw Error(`DLQ config not found for function: ${i.functionName}`);let o=`reprocess-${Date.now()}-${this.reprocessCounter++}`,c={id:o,dlqConfigId:s.id,messageId:n,status:"pending",startedAt:new Date};return this.reprocessing.set(o,c),setTimeout(()=>{c.status="processing",setTimeout(()=>{let l=Math.random()>0.3;if(c.status=l?"success":"failed",c.completedAt=new Date,!l)c.error="Reprocessing failed - same error occurred";else this.messages.delete(n)},100)},50),c}async batchReprocess(n){let i=this.dlqConfigs.get(n.dlqConfigId);if(!i)throw Error(`DLQ config not found: ${n.dlqConfigId}`);let s=Array.from(this.messages.values()).filter((o)=>o.functionName===i.functionName).slice(0,n.maxMessages||10).map((o)=>this.reprocessMessage(o.id));return Promise.all(s)}getDLQStats(n){let i=this.dlqConfigs.get(n);if(!i)throw Error(`DLQ config not found: ${n}`);let s=Array.from(this.messages.values()).filter((u)=>u.functionName===i.functionName),o={},c=0;for(let u of s)o[u.errorType]=(o[u.errorType]||0)+1,c+=u.attemptCount;let l=s.map((u)=>u.timestamp);return{totalMessages:s.length,oldestMessage:l.length>0?new Date(Math.min(...l.map((u)=>u.getTime()))):void 0,newestMessage:l.length>0?new Date(Math.max(...l.map((u)=>u.getTime()))):void 0,averageAttempts:s.length>0?c/s.length:0,errorTypes:o}}getDLQConfig(n){return this.dlqConfigs.get(n)}listDLQConfigs(){return Array.from(this.dlqConfigs.values())}getDLQMessages(n){let i=this.dlqConfigs.get(n);if(!i)return[];return Array.from(this.messages.values()).filter((s)=>s.functionName===i.functionName)}generateDLQCF(n){return{DeadLetterConfig:{TargetArn:n.targetArn}}}generateSQSDLQCF(n){return{Type:"AWS::SQS::Queue",Properties:{QueueName:`${n.functionName}-dlq`,MessageRetentionPeriod:n.retentionPeriod||1209600,...n.maxReceiveCount&&{RedrivePolicy:{deadLetterTargetArn:n.targetArn,maxReceiveCount:n.maxReceiveCount}}}}}generateDLQAlarmCF(n){let i=this.dlqConfigs.get(n.dlqConfigId);if(!i)throw Error(`DLQ config not found: ${n.dlqConfigId}`);return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:n.alarmName,AlarmDescription:`DLQ alarm for ${i.functionName}`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Sum",Period:300,EvaluationPeriods:n.evaluationPeriods,Threshold:n.threshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:i.targetArn.split(":").pop()}],...n.notificationTopicArn&&{AlarmActions:[n.notificationTopicArn]}}}}clear(){this.dlqConfigs.clear(),this.messages.clear(),this.alarms.clear(),this.reprocessing.clear(),this.configCounter=0,this.messageCounter=0,this.alarmCounter=0,this.reprocessCounter=0}}var NE=new bm;class vm{policies=new Map;healthChecks=new Map;trafficPolicies=new Map;policyCounter=0;healthCheckCounter=0;trafficPolicyCounter=0;createWeightedPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"weighted",...n};return this.policies.set(i,s),s}createLatencyPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"latency",...n};return this.policies.set(i,s),s}createFailoverPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"failover",...n};return this.policies.set(i,s),s}createGeolocationPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"geolocation",...n};return this.policies.set(i,s),s}createGeoproximityPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"geoproximity",...n};return this.policies.set(i,s),s}createHTTPHealthCheck(n){let i=`health-check-${Date.now()}-${this.healthCheckCounter++}`,s={id:i,type:n.port===443?"https":"http",requestInterval:n.requestInterval||30,failureThreshold:n.failureThreshold||3,healthCheckStatus:"Unknown",port:n.port||(n.port===443?443:80),...n};return this.healthChecks.set(i,s),setTimeout(()=>{s.healthCheckStatus=Math.random()>0.2?"Healthy":"Unhealthy"},100),s}createTCPHealthCheck(n){let i=`health-check-${Date.now()}-${this.healthCheckCounter++}`,s={id:i,type:"tcp",fullyQualifiedDomainName:n.ipAddress,requestInterval:n.requestInterval||30,failureThreshold:n.failureThreshold||3,healthCheckStatus:"Unknown",...n};return this.healthChecks.set(i,s),setTimeout(()=>{s.healthCheckStatus=Math.random()>0.1?"Healthy":"Unhealthy"},100),s}createCalculatedHealthCheck(n){let i=`health-check-${Date.now()}-${this.healthCheckCounter++}`,s={id:i,type:"calculated",requestInterval:30,failureThreshold:0,healthCheckStatus:"Unknown",...n};return this.healthChecks.set(i,s),setTimeout(()=>{let o=n.childHealthChecks.filter((c)=>this.healthChecks.get(c)?.healthCheckStatus==="Healthy").length;s.healthCheckStatus=o>=n.healthThreshold?"Healthy":"Unhealthy"},150),s}createTrafficPolicy(n){let i=`traffic-policy-${Date.now()}-${this.trafficPolicyCounter++}`,s={id:i,version:1,...n};return this.trafficPolicies.set(i,s),s}createFailoverTrafficPolicy(n){return this.createTrafficPolicy({name:n.name,document:{recordType:n.recordType||"A",startRule:"failover",endpoints:{primary:{type:"value",value:n.primaryEndpoint},secondary:{type:"value",value:n.secondaryEndpoint}},rules:{failover:{ruleType:"failover",primary:"primary",secondary:"secondary"}}}})}createGeoproximityTrafficPolicy(n){let i={},s=[];return n.locations.forEach((o,c)=>{let l=`endpoint${c}`;i[l]={type:"value",value:o.endpoint},s.push({endpointReference:l,region:o.region,latitude:o.latitude,longitude:o.longitude,bias:o.bias})}),this.createTrafficPolicy({name:n.name,document:{recordType:"A",startRule:"geoproximity",endpoints:i,rules:{geoproximity:{ruleType:"geoproximity",locations:s}}}})}getPolicy(n){return this.policies.get(n)}listPolicies(){return Array.from(this.policies.values())}getHealthCheck(n){return this.healthChecks.get(n)}listHealthChecks(){return Array.from(this.healthChecks.values())}getHealthCheckStatus(n){return this.healthChecks.get(n)?.healthCheckStatus||"Unknown"}generateHealthCheckCF(n){let i={Type:"AWS::Route53::HealthCheck",Properties:{HealthCheckConfig:{Type:n.type.toUpperCase(),RequestInterval:n.requestInterval,FailureThreshold:n.failureThreshold,...n.measureLatency&&{MeasureLatency:!0}},HealthCheckTags:[{Key:"Name",Value:n.name}]}};if(n.type==="calculated"){let s=n;i.Properties.HealthCheckConfig.ChildHealthChecks=s.childHealthChecks,i.Properties.HealthCheckConfig.HealthThreshold=s.healthThreshold}else{if(n.ipAddress)i.Properties.HealthCheckConfig.IPAddress=n.ipAddress;if(n.fullyQualifiedDomainName)i.Properties.HealthCheckConfig.FullyQualifiedDomainName=n.fullyQualifiedDomainName;if(n.port)i.Properties.HealthCheckConfig.Port=n.port;if(n.resourcePath)i.Properties.HealthCheckConfig.ResourcePath=n.resourcePath;if(n.enableSNI)i.Properties.HealthCheckConfig.EnableSNI=!0}return i}generateWeightedRecordSetCF(n){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:n.name,Type:n.type,TTL:n.ttl,ResourceRecords:n.resourceRecords,Weight:n.weight,SetIdentifier:n.setIdentifier,...n.healthCheckId&&{HealthCheckId:n.healthCheckId}}}}generateFailoverRecordSetCF(n){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:n.name,Type:n.type,TTL:n.ttl,ResourceRecords:n.resourceRecords,Failover:n.failover,SetIdentifier:n.setIdentifier,...n.healthCheckId&&{HealthCheckId:n.healthCheckId}}}}clear(){this.policies.clear(),this.healthChecks.clear(),this.trafficPolicies.clear(),this.policyCounter=0,this.healthCheckCounter=0,this.trafficPolicyCounter=0}}var kE=new vm;class Tm{configs=new Map;ksks=new Map;validations=new Map;configCounter=0;kskCounter=0;validationCounter=0;enableDNSSEC(n){let i=`dnssec-${Date.now()}-${this.configCounter++}`,s={id:i,hostedZoneId:n.hostedZoneId,status:"SIGNING",signingStatus:"Initializing DNSSEC signing"};if(this.configs.set(i,s),n.kmsKeyArn)this.createKSK({name:`ksk-${n.hostedZoneId}`,hostedZoneId:n.hostedZoneId,kmsKeyArn:n.kmsKeyArn});return setTimeout(()=>{s.status="SIGNED",s.signingStatus="DNSSEC signing complete"},100),s}disableDNSSEC(n){let i=this.configs.get(n);if(!i)throw Error(`DNSSEC config not found: ${n}`);return i.status="DELETING",i.signingStatus="Removing DNSSEC signing",setTimeout(()=>{i.status="NOT_SIGNING",i.signingStatus="DNSSEC signing removed"},100),i}createKSK(n){let i=`ksk-${Date.now()}-${this.kskCounter++}`,s={id:i,status:"ACTIVE",flag:257,keyManagementServiceArn:n.kmsKeyArn,digestAlgorithm:2,keyTag:Math.floor(Math.random()*65535),publicKey:this.generatePublicKey(),...n};s.dnskeyRecord=`${s.flag} 3 8 ${s.publicKey}`;let o=this.generateDigest(s.dnskeyRecord);return s.digestValue=o,s.dsRecord=`${s.keyTag} 8 ${s.digestAlgorithm} ${o}`,this.ksks.set(i,s),s}deactivateKSK(n){let i=this.ksks.get(n);if(!i)throw Error(`KSK not found: ${n}`);return i.status="INACTIVE",i}validateDNSSEC(n){let i=`validation-${Date.now()}-${this.validationCounter++}`,s=n.checkDNSKEY!==!1?Math.random()>0.1:!1,o=n.checkRRSIG!==!1?Math.random()>0.1:!1,c=s&&o,l=[];if(!s)l.push("DNSKEY record not found");if(!o)l.push("RRSIG record not found");let u;if(!s&&!o)u="INSECURE";else if(s&&o&&c)u="VALID";else if(s||o)u="BOGUS",l.push("Invalid signature or incomplete DNSSEC chain");else u="INVALID";let h={id:i,domain:n.domain,validationStatus:u,dnskeyPresent:s,rrsigPresent:o,validSignature:c,errors:l};return this.validations.set(i,h),h}getDNSSECConfig(n){return this.configs.get(n)}listDNSSECConfigs(){return Array.from(this.configs.values())}getKSK(n){return this.ksks.get(n)}listKSKs(n){let i=Array.from(this.ksks.values());return n?i.filter((s)=>s.hostedZoneId===n):i}getDSRecord(n){let i=this.ksks.get(n);if(!i||!i.dsRecord)throw Error("DS record not available");return i.dsRecord}generatePublicKey(){let n="";for(let i=0;i<256;i++)n+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(Math.floor(Math.random()*64));return n}generateDigest(n){let i="";for(let s=0;s<64;s++)i+="0123456789ABCDEF".charAt(Math.floor(Math.random()*16));return i}generateDNSSECCF(n){return{Type:"AWS::Route53::DNSSEC",Properties:{HostedZoneId:n.hostedZoneId}}}generateKSKCF(n){return{Type:"AWS::Route53::KeySigningKey",Properties:{Name:n.name,HostedZoneId:n.hostedZoneId,KeyManagementServiceArn:n.keyManagementServiceArn,Status:n.status}}}clear(){this.configs.clear(),this.ksks.clear(),this.validations.clear(),this.configCounter=0,this.kskCounter=0,this.validationCounter=0}}var BE=new Tm;class wm{endpoints=new Map;rules=new Map;firewalls=new Map;ruleGroups=new Map;domainLists=new Map;endpointCounter=0;ruleCounter=0;firewallCounter=0;ruleGroupCounter=0;domainListCounter=0;createResolverEndpoint(n){let i=`endpoint-${Date.now()}-${this.endpointCounter++}`,s={id:i,status:"CREATING",...n};return this.endpoints.set(i,s),setTimeout(()=>{s.status="OPERATIONAL",s.ipAddresses.forEach((o)=>{if(!o.ip)o.ip=`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`})},100),s}createInboundEndpoint(n){return this.createResolverEndpoint({name:n.name,direction:"INBOUND",ipAddresses:n.subnetIds.map((i)=>({subnetId:i})),securityGroupIds:n.securityGroupIds})}createOutboundEndpoint(n){return this.createResolverEndpoint({name:n.name,direction:"OUTBOUND",ipAddresses:n.subnetIds.map((i)=>({subnetId:i})),securityGroupIds:n.securityGroupIds})}createResolverRule(n){let i=`rule-${Date.now()}-${this.ruleCounter++}`,s={id:i,status:"CREATING",...n};return this.rules.set(i,s),setTimeout(()=>{s.status="COMPLETE"},100),s}createForwardRule(n){return this.createResolverRule({name:n.name,ruleType:"FORWARD",domainName:n.domainName,targetIps:n.targetIps,resolverEndpointId:n.resolverEndpointId})}createSystemRule(n){return this.createResolverRule({name:n.name,ruleType:"SYSTEM",domainName:n.domainName})}createFirewallDomainList(n){let i=`domain-list-${Date.now()}-${this.domainListCounter++}`,s={id:i,status:"CREATING",...n};return this.domainLists.set(i,s),setTimeout(()=>{s.status="COMPLETE"},100),s}createFirewallRuleGroup(n){let i=`rule-group-${Date.now()}-${this.ruleGroupCounter++}`,s={id:i,name:n.name,rules:n.rules.map((o,c)=>({id:`rule-${i}-${c}`,...o})),shareStatus:"NOT_SHARED"};return this.ruleGroups.set(i,s),s}createBlockRule(n){return this.createFirewallRuleGroup({name:n.name,rules:[{name:n.name,priority:n.priority,action:"BLOCK",blockResponse:n.blockResponse||"NODATA",blockOverrideDomain:n.blockOverrideDomain,firewallDomainListId:n.domainListId}]})}createAllowRule(n){return this.createFirewallRuleGroup({name:n.name,rules:[{name:n.name,priority:n.priority,action:"ALLOW",firewallDomainListId:n.domainListId}]})}createDNSFirewall(n){let i=`firewall-${Date.now()}-${this.firewallCounter++}`,s={id:i,name:n.name,firewallRuleGroupAssociations:n.ruleGroupAssociations.map((o,c)=>({id:`assoc-${i}-${c}`,vpcId:n.vpcId,firewallRuleGroupId:o.firewallRuleGroupId,priority:o.priority,mutationProtection:o.mutationProtection||"DISABLED",status:"COMPLETE"}))};return this.firewalls.set(i,s),s}createMalwareProtectionFirewall(n){let i=this.createFirewallDomainList({name:`${n.name}-malware-domains`,domains:n.maliciousDomains}),s=this.createBlockRule({name:`${n.name}-block-malware`,priority:100,domainListId:i.id,blockResponse:"NXDOMAIN"});return this.createDNSFirewall({name:n.name,vpcId:n.vpcId,ruleGroupAssociations:[{firewallRuleGroupId:s.id,priority:100,mutationProtection:"ENABLED"}]})}getEndpoint(n){return this.endpoints.get(n)}listEndpoints(n){let i=Array.from(this.endpoints.values());return n?i.filter((s)=>s.direction===n):i}getRule(n){return this.rules.get(n)}listRules(){return Array.from(this.rules.values())}getFirewall(n){return this.firewalls.get(n)}listFirewalls(){return Array.from(this.firewalls.values())}generateResolverEndpointCF(n){return{Type:"AWS::Route53Resolver::ResolverEndpoint",Properties:{Name:n.name,Direction:n.direction,IpAddresses:n.ipAddresses.map((i)=>({SubnetId:i.subnetId,...i.ip&&{Ip:i.ip}})),SecurityGroupIds:n.securityGroupIds}}}generateResolverRuleCF(n){return{Type:"AWS::Route53Resolver::ResolverRule",Properties:{Name:n.name,RuleType:n.ruleType,DomainName:n.domainName,...n.targetIps&&{TargetIps:n.targetIps.map((i)=>({Ip:i.ip,Port:i.port||53}))},...n.resolverEndpointId&&{ResolverEndpointId:n.resolverEndpointId}}}}generateFirewallRuleGroupCF(n){return{Type:"AWS::Route53Resolver::FirewallRuleGroup",Properties:{Name:n.name,FirewallRules:n.rules.map((i)=>({Name:i.name,Priority:i.priority,Action:i.action,FirewallDomainListId:i.firewallDomainListId,...i.blockResponse&&{BlockResponse:i.blockResponse},...i.blockOverrideDomain&&{BlockOverrideDomain:i.blockOverrideDomain},...i.blockOverrideTTL&&{BlockOverrideTtl:i.blockOverrideTTL}}))}}}clear(){this.endpoints.clear(),this.rules.clear(),this.firewalls.clear(),this.ruleGroups.clear(),this.domainLists.clear(),this.endpointCounter=0,this.ruleCounter=0,this.firewallCounter=0,this.ruleGroupCounter=0,this.domainListCounter=0}}var _E=new wm;class Rm{bounces=new Map;complaints=new Map;handlers=new Map;suppressionList=new Map;metrics=new Map;bounceCounter=0;complaintCounter=0;handlerCounter=0;suppressionCounter=0;metricsCounter=0;recordBounce(n){let i=`bounce-${Date.now()}-${this.bounceCounter++}`,s={id:i,...n};if(this.bounces.set(i,s),n.bounceType==="Permanent")this.addToSuppressionList({emailAddress:n.recipient,reason:"BOUNCE"});return s}recordComplaint(n){let i=`complaint-${Date.now()}-${this.complaintCounter++}`,s={id:i,...n};this.complaints.set(i,s);for(let o of n.recipients)this.addToSuppressionList({emailAddress:o,reason:"COMPLAINT"});return s}createBounceHandler(n){let i=`handler-${Date.now()}-${this.handlerCounter++}`,s={id:i,...n};return this.handlers.set(i,s),s}createAutomaticBounceHandler(n){return this.createBounceHandler({name:n.name,bounceThreshold:5,complaintThreshold:0.1,suppressionDuration:2592000,autoSuppress:!0,notificationTopicArn:n.notificationTopicArn})}addToSuppressionList(n){let i=`suppression-${Date.now()}-${this.suppressionCounter++}`,s=n.expirationDays?new Date(Date.now()+n.expirationDays*24*60*60*1000):void 0,o={id:i,emailAddress:n.emailAddress,reason:n.reason,suppressedAt:new Date,expiresAt:s,bounceCount:n.reason==="BOUNCE"?1:0,complaintCount:n.reason==="COMPLAINT"?1:0};return this.suppressionList.set(n.emailAddress,o),o}removeFromSuppressionList(n){return this.suppressionList.delete(n)}isSuppressed(n){let i=this.suppressionList.get(n);if(!i)return!1;if(i.expiresAt&&i.expiresAt<new Date)return this.suppressionList.delete(n),!1;return!0}getBounceStatistics(n,i){let s=Array.from(this.bounces.values()).filter((b)=>b.timestamp>=n&&b.timestamp<=i),o=s.length,c=s.filter((b)=>b.bounceType==="Permanent").length,l=s.filter((b)=>b.bounceType==="Transient").length,u=o*10,h=o/u*100,f=new Map;for(let b of s)f.set(b.recipient,(f.get(b.recipient)||0)+1);let S=Array.from(f.entries()).map(([b,A])=>({email:b,count:A})).sort((b,A)=>A.count-b.count).slice(0,10);return{totalBounces:o,permanentBounces:c,transientBounces:l,bounceRate:h,topRecipients:S}}getComplaintStatistics(n,i){let s=Array.from(this.complaints.values()).filter((f)=>f.timestamp>=n&&f.timestamp<=i),o=s.length,c=new Set;for(let f of s)for(let S of f.recipients)c.add(S);let l=c.size,u=o*1000,h=o/u*100;return{totalComplaints:o,uniqueComplainters:l,complaintRate:h}}calculateReputationMetrics(){let n=`metrics-${Date.now()}-${this.metricsCounter++}`,i=new Date,s=new Date(i.getTime()-86400000),o=this.getBounceStatistics(s,i),c=this.getComplaintStatistics(s,i),l;if(o.bounceRate>10||c.complaintRate>0.5)l="Shutdown";else if(o.bounceRate>5||c.complaintRate>0.1)l="Probation";else if(o.bounceRate>2||c.complaintRate>0.05)l="Warning";else l="Good";let u={id:n,timestamp:i,bounceRate:o.bounceRate,complaintRate:c.complaintRate,sendingQuota:50000,maxSendRate:14,sentLast24Hours:o.totalBounces*10,reputationStatus:l};return this.metrics.set(n,u),u}getBounces(n){let i=Array.from(this.bounces.values());return n?i.filter((s)=>s.messageId===n):i}getComplaints(n){let i=Array.from(this.complaints.values());return n?i.filter((s)=>s.messageId===n):i}listSuppressionList(n){let i=Array.from(this.suppressionList.values());return n?i.filter((s)=>s.reason===n):i}generateSNSSubscriptionCF(n){return{Type:"AWS::SNS::Subscription",Properties:{TopicArn:n.topicArn,Endpoint:n.endpoint,Protocol:n.protocol}}}generateEventDestinationCF(n){return{Type:"AWS::SES::ConfigurationSetEventDestination",Properties:{ConfigurationSetName:n.configurationSetName,EventDestination:{Name:n.eventDestinationName,Enabled:!0,MatchingEventTypes:n.eventTypes,...n.snsTopicArn&&{SnsDestination:{TopicARN:n.snsTopicArn}},...n.cloudWatchDestination&&{CloudWatchDestination:n.cloudWatchDestination}}}}}clear(){this.bounces.clear(),this.complaints.clear(),this.handlers.clear(),this.suppressionList.clear(),this.metrics.clear(),this.bounceCounter=0,this.complaintCounter=0,this.handlerCounter=0,this.suppressionCounter=0,this.metricsCounter=0}}var OE=new Rm;class Dm{events=new Map;campaigns=new Map;reports=new Map;abTests=new Map;eventCounter=0;campaignCounter=0;reportCounter=0;abTestCounter=0;trackEvent(n){let i=`event-${Date.now()}-${this.eventCounter++}`,s={id:i,...n};if(this.events.set(i,s),n.tags?.campaignId)this.updateCampaignStats(n.tags.campaignId,n.eventType);return s}trackOpen(n){return this.trackEvent({...n,eventType:"open",timestamp:new Date})}trackClick(n){return this.trackEvent({...n,eventType:"click",timestamp:new Date})}createCampaign(n){let i=`campaign-${Date.now()}-${this.campaignCounter++}`,s={id:i,sentCount:0,deliveredCount:0,openCount:0,clickCount:0,bounceCount:0,complaintCount:0,createdAt:new Date,...n};return this.campaigns.set(i,s),s}updateCampaignStats(n,i){let s=this.campaigns.get(n);if(!s)return;switch(i){case"send":s.sentCount++;break;case"delivery":s.deliveredCount++;break;case"open":s.openCount++;break;case"click":s.clickCount++;break;case"bounce":s.bounceCount++;break;case"complaint":s.complaintCount++;break}}generateReport(n){let i=`report-${Date.now()}-${this.reportCounter++}`,s=Array.from(this.events.values()).filter((I)=>{let _=I.timestamp>=n.startDate&&I.timestamp<=n.endDate,B=!n.campaignId||I.tags?.campaignId===n.campaignId;return _&&B}),o=s.filter((I)=>I.eventType==="send").length,c=s.filter((I)=>I.eventType==="delivery").length,l=s.filter((I)=>I.eventType==="open").length,u=s.filter((I)=>I.eventType==="click").length,h=s.filter((I)=>I.eventType==="bounce").length,f=s.filter((I)=>I.eventType==="complaint").length,S=o>0?c/o*100:0,b=c>0?l/c*100:0,A=c>0?u/c*100:0,v=l>0?u/l*100:0,w=o>0?h/o*100:0,E=c>0?f/c*100:0,P=new Map;for(let I of s)if(I.eventType==="click"){let _=I;P.set(_.link,(P.get(_.link)||0)+1)}let R=Array.from(P.entries()).map(([I,_])=>({link:I,clicks:_})).sort((I,_)=>_.clicks-I.clicks).slice(0,10),D={desktop:0,mobile:0,tablet:0,unknown:0};for(let I of s)if(I.eventType==="open"||I.eventType==="click"){let _=I.userAgent.toLowerCase();if(_.includes("mobile"))D.mobile++;else if(_.includes("tablet"))D.tablet++;else if(_.includes("mozilla"))D.desktop++;else D.unknown++}let O={id:i,campaignId:n.campaignId,startDate:n.startDate,endDate:n.endDate,totalSent:o,totalDelivered:c,totalOpened:l,totalClicked:u,totalBounced:h,totalComplaints:f,deliveryRate:S,openRate:b,clickRate:A,clickToOpenRate:v,bounceRate:w,complaintRate:E,topLinks:R,deviceBreakdown:D,locationBreakdown:{}};return this.reports.set(i,O),O}createABTest(n){let i=`abtest-${Date.now()}-${this.abTestCounter++}`,s={id:i,name:n.name,variants:n.variants.map((o,c)=>({id:`variant-${i}-${c}`,sentCount:0,openCount:0,clickCount:0,conversionCount:0,...o})),status:"draft"};return this.abTests.set(i,s),s}startABTest(n){let i=this.abTests.get(n);if(!i)throw Error(`A/B test not found: ${n}`);return i.status="running",i.startedAt=new Date,i}completeABTest(n){let i=this.abTests.get(n);if(!i)throw Error(`A/B test not found: ${n}`);let s=i.variants[0],o=0;for(let c of i.variants){let l=c.sentCount>0?c.openCount/c.sentCount:0;if(l>o)o=l,s=c}return i.status="completed",i.completedAt=new Date,i.winner=s.id,i}getCampaign(n){return this.campaigns.get(n)}listCampaigns(){return Array.from(this.campaigns.values())}getEvents(n){let i=Array.from(this.events.values());if(n?.messageId)i=i.filter((s)=>s.messageId===n.messageId);if(n?.eventType)i=i.filter((s)=>s.eventType===n.eventType);if(n?.startDate)i=i.filter((s)=>s.timestamp>=n.startDate);if(n?.endDate)i=i.filter((s)=>s.timestamp<=n.endDate);return i}generateTrackingConfigurationCF(n){return{Type:"AWS::SES::ConfigurationSet",Properties:{Name:n.configurationSetName,...n.openTracking&&{TrackingOptions:{CustomRedirectDomain:"tracking.example.com"}}}}}clear(){this.events.clear(),this.campaigns.clear(),this.reports.clear(),this.abTests.clear(),this.eventCounter=0,this.campaignCounter=0,this.reportCounter=0,this.abTestCounter=0}}var xE=new Dm;class Pm{dashboards=new Map;warmupPlans=new Map;domainReputations=new Map;dashboardCounter=0;warmupCounter=0;domainCounter=0;getReputationDashboard(){let n=`dashboard-${Date.now()}-${this.dashboardCounter++}`,i=Math.random()*5,s=Math.random()*0.5,o=Math.floor(Math.random()*10),c=Math.max(0,100-i*10-s*100-o*2),l=[];if(i>2)l.push("Reduce bounce rate by cleaning email list");if(s>0.1)l.push("Review email content and unsubscribe process");if(o>5)l.push("Improve email relevance and targeting");let u={id:n,timestamp:new Date,overallScore:c,bounceRate:i,complaintRate:s,spamReports:o,blacklistStatus:this.checkBlacklists(),dkimStatus:"VERIFIED",spfStatus:"PASS",dmarcStatus:"PASS",sendingLimits:{maxSendRate:14,max24HourSend:50000,sentLast24Hours:12000,remainingQuota:38000,quotaResetTime:new Date(Date.now()+86400000)},recommendations:l};return this.dashboards.set(n,u),u}checkBlacklists(){return["Spamhaus ZEN","Spamcop","SORBS","Barracuda","URIBL"].map((n)=>({listName:n,listed:Math.random()>0.95,delistUrl:`https://www.${n.toLowerCase().replace(/\s/g,"")}.org/delist`}))}createWarmupPlan(n){let i=`warmup-${Date.now()}-${this.warmupCounter++}`,s=[],o=(n.targetDailyLimit-n.initialDailyLimit)/n.durationDays;for(let l=0;l<n.durationDays;l++)s.push(Math.floor(n.initialDailyLimit+o*l));let c={id:i,name:n.name,startDate:new Date,currentDay:1,totalDays:n.durationDays,dailyLimits:s,currentLimit:s[0],status:"active"};return this.warmupPlans.set(i,c),c}createAggressiveWarmupPlan(n){return this.createWarmupPlan({name:n.name,initialDailyLimit:500,targetDailyLimit:50000,durationDays:14})}createConservativeWarmupPlan(n){return this.createWarmupPlan({name:n.name,initialDailyLimit:200,targetDailyLimit:50000,durationDays:30})}advanceWarmupPlan(n){let i=this.warmupPlans.get(n);if(!i)throw Error(`Warmup plan not found: ${n}`);if(i.currentDay<i.totalDays)i.currentDay++,i.currentLimit=i.dailyLimits[i.currentDay-1];if(i.currentDay>=i.totalDays)i.status="completed";return i}trackDomainReputation(n){let i=`domain-${Date.now()}-${this.domainCounter++}`,s=n.delivered/n.totalSent*100,o=n.delivered>0?n.opened/n.delivered*100:0,c=n.delivered>0?n.clicked/n.delivered*100:0,l=n.bounced/n.totalSent*100,u=n.delivered>0?n.complained/n.delivered*100:0,h=o*0.4+c*0.6,f=Math.max(0,100-l*10-u*100+h*0.2),S={id:i,domain:n.domain,reputationScore:f,totalSent:n.totalSent,deliveryRate:s,openRate:o,clickRate:c,bounceRate:l,complaintRate:u,engagementScore:h};return this.domainReputations.set(n.domain,S),S}getDomainReputation(n){return this.domainReputations.get(n)}listDomainReputations(){return Array.from(this.domainReputations.values())}getWarmupPlan(n){return this.warmupPlans.get(n)}listWarmupPlans(){return Array.from(this.warmupPlans.values())}clear(){this.dashboards.clear(),this.warmupPlans.clear(),this.domainReputations.clear(),this.dashboardCounter=0,this.warmupCounter=0,this.domainCounter=0}}var LE=new Pm;class Nm{templates=new Map;versions=new Map;tests=new Map;templateCounter=0;testCounter=0;createTemplate(n){let i=`template-${Date.now()}-${this.templateCounter++}`,s=this.extractVariables(n.subject+n.htmlPart+n.textPart),o={id:i,variables:s,createdAt:new Date,updatedAt:new Date,version:1,...n};return this.templates.set(i,o),this.addVersion({templateId:i,version:1,subject:n.subject,htmlPart:n.htmlPart,textPart:n.textPart,createdBy:"system"}),o}createWelcomeTemplate(n){return this.createTemplate({name:n.name,subject:"Welcome to {{companyName}}!",htmlPart:`
|
|
3777
3777
|
<html>
|
|
3778
3778
|
<body>
|
|
3779
3779
|
<h1>Welcome, {{userName}}!</h1>
|
|
@@ -7261,7 +7261,7 @@ function unmarshallTest(item) {
|
|
|
7261
7261
|
|
|
7262
7262
|
return test;
|
|
7263
7263
|
}
|
|
7264
|
-
`;static createAbTestsTable(n){return{[`${n.slug}AbTestsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-ab-tests`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}}static createAbTestManagerLambda(n){return{[`${n.slug}AbTestManagerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-ab-test-manager`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Te.AbTestManagerCode},Environment:{Variables:{AB_TESTS_TABLE:n.abTestsTable}}}}}}static selectVariant(n,i){let s=Te.hashString(i+n.id)%100,o=0;for(let c=0;c<n.variants.length;c++)if(o+=n.trafficSplit[c],s<o)return n.variants[c];return n.variants[n.variants.length-1]}static determineWinner(n){if(n.variants.length===0)return null;let i=n.winningCriteria,s=n.variants[0],o=Te.getMetricValue(s,i);for(let c of n.variants.slice(1)){let l=Te.getMetricValue(c,i);if(l>o)o=l,s=c}return s}static calculateSignificance(n,i,s){let o=n.stats.sent,c=i.stats.sent;if(o<30||c<30)return 0;let l=Te.getMetricValue(n,s)/100,u=Te.getMetricValue(i,s)/100,h=(l*o+u*c)/(o+c),f=Math.sqrt(h*(1-h)*(1/o+1/c));if(f===0)return 0;let S=Math.abs(l-u)/f;if(S>=2.576)return 99;if(S>=1.96)return 95;if(S>=1.645)return 90;if(S>=1.28)return 80;return Math.round(S*30)}static getMetricValue(n,i){switch(i){case"delivery_rate":return n.stats.deliveryRate;case"click_rate":return n.stats.clickRate;case"reply_rate":return n.stats.replyRate;case"conversion_rate":return n.stats.conversionRate;default:return n.stats.deliveryRate}}static hashString(n){let i=0;for(let s=0;s<n.length;s++){let o=n.charCodeAt(s);i=(i<<5)-i+o,i=i&i}return Math.abs(i)}}class km{queues=new Map;messageGroups=new Map;deduplicationConfigs=new Map;messages=new Map;queueCounter=0;groupCounter=0;deduplicationCounter=0;messageCounter=0;sequenceCounter=0;createFIFOQueue(n){let i=`fifo-queue-${Date.now()}-${this.queueCounter++}`,s=n.name.endsWith(".fifo")?n.name:`${n.name}.fifo`,{name:o,...c}=n,l={id:i,name:s,queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${s}`,...c};return this.queues.set(i,l),this.createDeduplicationConfig({queueId:i,contentBasedDeduplication:n.contentBasedDeduplication,deduplicationInterval:300}),l}createHighThroughputFIFO(n){return this.createFIFOQueue({name:n.name,contentBasedDeduplication:n.contentBasedDeduplication??!0,deduplicationScope:"messageGroup",fifoThroughputLimit:"perMessageGroupId",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createStandardFIFO(n){return this.createFIFOQueue({name:n.name,contentBasedDeduplication:n.contentBasedDeduplication??!1,deduplicationScope:"queue",fifoThroughputLimit:"perQueue",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createDeduplicationConfig(n){let i={id:`dedup-${Date.now()}-${this.deduplicationCounter++}`,deduplicationHashes:new Map,...n};return this.deduplicationConfigs.set(n.queueId,i),i}sendMessage(n){let i=this.queues.get(n.queueId);if(!i)throw Error(`Queue not found: ${n.queueId}`);let s=this.deduplicationConfigs.get(n.queueId);if(s){let u=n.messageDeduplicationId||(i.contentBasedDeduplication?this.generateHash(n.messageBody):void 0);if(u&&this.isDuplicate(s,u))return null;if(u)s.deduplicationHashes.set(u,new Date)}let o=`msg-${Date.now()}-${this.messageCounter++}`,c=this.generateSequenceNumber(),l={id:o,messageId:o,messageGroupId:n.messageGroupId,messageDeduplicationId:n.messageDeduplicationId,body:n.messageBody,attributes:n.messageAttributes||{},sentTimestamp:new Date,sequenceNumber:c};return this.messages.set(o,l),this.updateMessageGroup(n.queueId,n.messageGroupId),l}isDuplicate(n,i){let s=n.deduplicationHashes.get(i);if(!s)return!1;if((Date.now()-s.getTime())/1000>n.deduplicationInterval)return n.deduplicationHashes.delete(i),!1;return!0}generateHash(n){let i=0;for(let s=0;s<n.length;s++){let o=n.charCodeAt(s);i=(i<<5)-i+o,i=i&i}return Math.abs(i).toString(36)}generateSequenceNumber(){return`${Date.now()}${this.sequenceCounter++}`.padStart(20,"0")}updateMessageGroup(n,i){let s=`${n}-${i}`,o=this.messageGroups.get(s);if(!o)o={id:`group-${Date.now()}-${this.groupCounter++}`,messageGroupId:i,queueId:n,messagesInFlight:0},this.messageGroups.set(s,o);o.messagesInFlight++,o.lastMessageTimestamp=new Date}getMessageGroups(n){return Array.from(this.messageGroups.values()).filter((i)=>i.queueId===n)}getQueue(n){return this.queues.get(n)}listQueues(){return Array.from(this.queues.values())}getMessages(n,i){let s=Array.from(this.messages.values());if(i)s=s.filter((o)=>o.messageGroupId===i);return s.sort((o,c)=>o.sequenceNumber.localeCompare(c.sequenceNumber))}generateFIFOQueueCF(n){return{Type:"AWS::SQS::Queue",Properties:{QueueName:n.name,FifoQueue:!0,ContentBasedDeduplication:n.contentBasedDeduplication,DeduplicationScope:n.deduplicationScope,FifoThroughputLimit:n.fifoThroughputLimit,MessageRetentionPeriod:n.messageRetentionPeriod,VisibilityTimeout:n.visibilityTimeout,ReceiveMessageWaitTimeSeconds:n.receiveMessageWaitTime,...n.deadLetterTargetArn&&{RedrivePolicy:{deadLetterTargetArn:n.deadLetterTargetArn,maxReceiveCount:n.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 ME=new km;class Bm{monitors=new Map;metrics=new Map;alerts=new Map;reprocessJobs=new Map;monitorCounter=0;metricsCounter=0;alertCounter=0;jobCounter=0;createDLQMonitor(n){let i=`dlq-monitor-${Date.now()}-${this.monitorCounter++}`,s={id:i,...n};return this.monitors.set(i,s),s}createAutomatedMonitor(n){return this.createDLQMonitor({name:n.name,queueUrl:n.queueUrl,sourceQueues:n.sourceQueues,maxReceiveCount:3,alarmThreshold:10,autoReprocess:!0,reprocessStrategy:"scheduled",notificationTopicArn:n.notificationTopicArn})}collectMetrics(n){let i={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:n,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)},s=this.metrics.get(n)||[];return s.push(i),this.metrics.set(n,s),this.checkForAlerts(n,i),i}checkForAlerts(n,i){let s=Array.from(this.monitors.values()).find((c)=>c.queueUrl===n);if(!s)return;if(i.approximateNumberOfMessages>=s.alarmThreshold)this.createAlert({monitorId:s.id,alertType:"threshold_exceeded",severity:"high",message:`DLQ ${s.name} has ${i.approximateNumberOfMessages} messages (threshold: ${s.alarmThreshold})`});let o=3600;if(i.approximateAgeOfOldestMessage>o)this.createAlert({monitorId:s.id,alertType:"old_message",severity:"medium",message:`DLQ ${s.name} has messages older than ${o} seconds`})}createAlert(n){let i=`alert-${Date.now()}-${this.alertCounter++}`,s={id:i,timestamp:new Date,acknowledged:!1,...n};return this.alerts.set(i,s),s}acknowledgeAlert(n){let i=this.alerts.get(n);if(!i)throw Error(`Alert not found: ${n}`);return i.acknowledged=!0,i}createReprocessJob(n){let i=`reprocess-${Date.now()}-${this.jobCounter++}`,s={id:i,queueUrl:n.queueUrl,messageId:n.messageId,attempts:0,status:"pending"};return this.reprocessJobs.set(i,s),s}async executeReprocessJob(n){let i=this.reprocessJobs.get(n);if(!i)throw Error(`Reprocess job not found: ${n}`);i.status="processing",i.startedAt=new Date,i.attempts++,await new Promise((o)=>setTimeout(o,100));let s=Math.random()>0.3;if(i.status=s?"success":"failed",i.completedAt=new Date,!s)i.error="Reprocessing failed - original error still present";return i}async batchReprocess(n){let i=[];for(let s=0;s<n.maxMessages;s++){let o=this.createReprocessJob({queueUrl:n.queueUrl,messageId:`msg-${s}`});await this.executeReprocessJob(o.id),i.push(o)}return i}getDLQStatistics(n,i=24){let s=new Date(Date.now()-i*60*60*1000),o=(this.metrics.get(n)||[]).filter((b)=>b.timestamp>=s);if(o.length===0)return{totalMessages:0,avgAge:0,messagesReceived:0,messagesDeleted:0,messagesReprocessed:0,successRate:0};let c=o[o.length-1],l=o.reduce((b,A)=>b+A.messagesReceived,0),u=o.reduce((b,A)=>b+A.messagesDeleted,0),h=o.reduce((b,A)=>b+A.messagesReprocessed,0),f=o.reduce((b,A)=>b+A.approximateAgeOfOldestMessage,0)/o.length,S=h>0?u/h*100:0;return{totalMessages:c.approximateNumberOfMessages,avgAge:f,messagesReceived:l,messagesDeleted:u,messagesReprocessed:h,successRate:S}}getMonitor(n){return this.monitors.get(n)}listMonitors(){return Array.from(this.monitors.values())}getAlerts(n,i){let s=Array.from(this.alerts.values());if(n)s=s.filter((o)=>o.monitorId===n);if(i!==void 0)s=s.filter((o)=>o.acknowledged===i);return s.sort((o,c)=>c.timestamp.getTime()-o.timestamp.getTime())}getReprocessJobs(n){let i=Array.from(this.reprocessJobs.values());if(n)i=i.filter((s)=>s.queueUrl===n);return i}generateDLQAlarmCF(n){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${n.name}-messages-alarm`,AlarmDescription:`Alert when DLQ ${n.name} exceeds threshold`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Average",Period:300,EvaluationPeriods:1,Threshold:n.alarmThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:n.queueUrl.split("/").pop()}],...n.notificationTopicArn&&{AlarmActions:[n.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 FE=new Bm;class _m{configs=new Map;jobs=new Map;metrics=new Map;configCounter=0;jobCounter=0;metricsCounter=0;createBatchConfig(n){let i=`batch-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}createHighThroughputConfig(n){return this.createBatchConfig({queueUrl:n.queueUrl,batchSize:10,maxWaitTime:100,parallelProcessors:10,retryAttempts:3,visibilityTimeout:30})}createLowLatencyConfig(n){return this.createBatchConfig({queueUrl:n.queueUrl,batchSize:1,maxWaitTime:0,parallelProcessors:5,retryAttempts:2,visibilityTimeout:10})}createBatchJob(n){let i=`batch-job-${Date.now()}-${this.jobCounter++}`;if(!this.configs.get(n.configId))throw Error(`Batch config not found: ${n.configId}`);let s=[];for(let c=0;c<n.messageCount;c++)s.push({id:`msg-${i}-${c}`,messageId:`${i}-${c}`,body:`Message ${c}`,receiptHandle:`receipt-${i}-${c}`,attributes:{},status:"pending"});let o={id:i,configId:n.configId,messages:s,status:"pending",processedCount:0,failedCount:0};return this.jobs.set(i,o),o}async processBatchJob(n){let i=this.jobs.get(n);if(!i)throw Error(`Batch job not found: ${n}`);let s=this.configs.get(i.configId);if(!s)throw Error(`Batch config not found: ${i.configId}`);i.status="processing",i.startedAt=new Date;let o=this.chunkArray(i.messages,s.batchSize);for(let c of o)await this.processBatch(c,s);return i.processedCount=i.messages.filter((c)=>c.status==="success").length,i.failedCount=i.messages.filter((c)=>c.status==="failed").length,i.status=i.failedCount===0?"completed":"failed",i.completedAt=new Date,this.collectProcessorMetrics(s.id,i),i}async processBatch(n,i){let s=n.map((o)=>this.processMessage(o,i));await Promise.all(s)}async processMessage(n,i){n.status="processing";let s=Date.now();await new Promise((c)=>setTimeout(c,Math.random()*100));let o=Date.now()-s;if(n.processingTime=o,Math.random()>0.1)n.status="success";else n.status="failed",n.error="Processing error"}chunkArray(n,i){let s=[];for(let o=0;o<n.length;o+=i)s.push(n.slice(o,o+i));return s}collectProcessorMetrics(n,i){let s=`metrics-${Date.now()}-${this.metricsCounter++}`,o=i.messages.filter((b)=>b.status==="success").map((b)=>b.processingTime||0).filter((b)=>b>0),c=o.length>0?o.reduce((b,A)=>b+A,0)/o.length:0,l=i.completedAt&&i.startedAt?(i.completedAt.getTime()-i.startedAt.getTime())/1000:1,u=i.processedCount/l,h=i.messages.length>0?i.failedCount/i.messages.length*100:0,f={id:s,configId:n,timestamp:new Date,messagesProcessed:i.processedCount,averageProcessingTime:c,throughput:u,errorRate:h},S=this.metrics.get(n)||[];S.push(f),this.metrics.set(n,S)}getBatchStatistics(n){let i=this.metrics.get(n)||[];if(i.length===0)return{totalJobsProcessed:0,totalMessagesProcessed:0,averageThroughput:0,averageErrorRate:0,averageProcessingTime:0};let s=i.reduce((u,h)=>u+h.messagesProcessed,0),o=i.reduce((u,h)=>u+h.throughput,0)/i.length,c=i.reduce((u,h)=>u+h.errorRate,0)/i.length,l=i.reduce((u,h)=>u+h.averageProcessingTime,0)/i.length;return{totalJobsProcessed:i.length,totalMessagesProcessed:s,averageThroughput:o,averageErrorRate:c,averageProcessingTime:l}}optimizeBatchConfig(n){let i=this.configs.get(n);if(!i)throw Error(`Batch config not found: ${n}`);let s=this.getBatchStatistics(n);if(s.averageErrorRate<5&&i.batchSize<10)i.batchSize=Math.min(10,i.batchSize+1);if(s.averageErrorRate>20&&i.batchSize>1)i.batchSize=Math.max(1,i.batchSize-1);if(s.averageThroughput<5&&i.parallelProcessors<20)i.parallelProcessors++;return i}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getJob(n){return this.jobs.get(n)}listJobs(n){let i=Array.from(this.jobs.values());if(n)i=i.filter((s)=>s.configId===n);return i}generateBatchProcessorCF(n){return{Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:`arn:aws:sqs:us-east-1:123456789012:${n.queueUrl.split("/").pop()}`,FunctionName:"batch-processor-function",BatchSize:n.batchSize,MaximumBatchingWindowInSeconds:n.maxWaitTime/1000,FunctionResponseTypes:["ReportBatchItemFailures"]}}}clear(){this.configs.clear(),this.jobs.clear(),this.metrics.clear(),this.configCounter=0,this.jobCounter=0,this.metricsCounter=0}}var UE=new _m;class xm{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(n){let i=`queue-${Date.now()}-${this.queueCounter++}`,s={id:i,purgeInProgress:!1,...n};return this.queues.set(i,s),s}createStandardQueue(n){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${n.queueName}`,queueName:n.queueName,messageRetentionPeriod:(n.messageRetentionDays||4)*24*60*60,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:0})}createLongPollingQueue(n){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${n.queueName}`,queueName:n.queueName,messageRetentionPeriod:345600,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:n.waitTimeSeconds||20})}createRetentionPolicy(n){let i=`retention-${Date.now()}-${this.retentionCounter++}`,s={id:i,...n};this.retentionPolicies.set(i,s);let o=this.queues.get(n.queueId);if(o)o.messageRetentionPeriod=n.retentionPeriod;return s}createShortRetentionPolicy(n){return this.createRetentionPolicy({queueId:n.queueId,retentionPeriod:n.retentionHours*60*60,autoCleanup:!0,archiveExpiredMessages:!1})}createArchivalRetentionPolicy(n){return this.createRetentionPolicy({queueId:n.queueId,retentionPeriod:n.retentionDays*24*60*60,autoCleanup:!0,cleanupSchedule:"cron(0 0 * * ? *)",archiveExpiredMessages:!0,archiveS3Bucket:n.s3Bucket})}createDelayQueue(n){let i=`delay-${Date.now()}-${this.delayCounter++}`,s={id:i,...n};this.delayQueues.set(i,s);let o=Array.from(this.queues.values()).find((c)=>c.queueUrl===n.queueUrl);if(o)o.delaySeconds=n.defaultDelay;return s}createScheduledDelayQueue(n){return this.createDelayQueue({queueUrl:n.queueUrl,defaultDelay:n.delayMinutes*60,perMessageDelay:!1,maxDelay:900})}async purgeQueue(n){let i=this.queues.get(n);if(!i)throw Error(`Queue not found: ${n}`);if(i.purgeInProgress)throw Error("Purge already in progress for this queue");let s=`purge-${Date.now()}-${this.purgeCounter++}`,o={id:s,queueUrl:i.queueUrl,status:"in_progress",startedAt:new Date};return this.purgeOperations.set(s,o),i.purgeInProgress=!0,setTimeout(()=>{o.status="completed",o.completedAt=new Date,o.messagesPurged=Math.floor(Math.random()*1000),i.purgeInProgress=!1},100),o}collectQueueMetrics(n){let i={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:n,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)},s=this.metrics.get(n)||[];return s.push(i),this.metrics.set(n,s),i}getQueueHealth(n){let i=this.metrics.get(n)||[];if(i.length===0)return{status:"healthy",issues:[],recommendations:[]};let s=i[i.length-1],o=[],c=[],l="healthy";if(s.approximateNumberOfMessages>1e4)l="critical",o.push("Large message backlog detected"),c.push("Increase consumer capacity");else if(s.approximateNumberOfMessages>1000)l="warning",o.push("Growing message backlog"),c.push("Monitor consumer performance");if(s.oldestMessageAge&&s.oldestMessageAge>3600){if(l!=="critical")l="warning";o.push("Old messages in queue"),c.push("Review message processing")}if(s.approximateNumberOfMessagesDelayed>100){if(l!=="critical")l="warning";o.push("High number of delayed messages")}return{status:l,issues:o,recommendations:c}}getQueue(n){return this.queues.get(n)}listQueues(){return Array.from(this.queues.values())}getRetentionPolicy(n){return this.retentionPolicies.get(n)}listRetentionPolicies(){return Array.from(this.retentionPolicies.values())}getPurgeOperations(n){let i=Array.from(this.purgeOperations.values());if(n)i=i.filter((s)=>s.queueUrl===n);return i}generateQueueCF(n){return{Type:"AWS::SQS::Queue",Properties:{QueueName:n.queueName,MessageRetentionPeriod:n.messageRetentionPeriod,DelaySeconds:n.delaySeconds,MaximumMessageSize:n.maximumMessageSize,ReceiveMessageWaitTimeSeconds:n.receiveMessageWaitTime}}}generateCleanupRuleCF(n){return{Type:"AWS::Events::Rule",Properties:{Name:`${n.id}-cleanup`,Description:"Automated queue cleanup",ScheduleExpression:n.cleanupSchedule||"cron(0 0 * * ? *)",State:"ENABLED",Targets:[{Arn:"arn:aws:lambda:us-east-1:123456789012:function:queue-cleanup",Id:n.id,Input:JSON.stringify({queueId:n.queueId,archiveBucket:n.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 QE=new xm,Qn=(()=>{let n=[];for(let i=0;i<256;i++){let s=i;for(let o=0;o<8;o++)s=s&1?3988292384^s>>>1:s>>>1;n[i]=s>>>0}return n})();function Jn(n){let i=4294967295;for(let s=0;s<n.length;s++)i=Qn[(i^n[s])&255]^i>>>8;return(i^4294967295)>>>0}function Yn(n){if(typeof n==="string")return Buffer.from(n,"utf-8");if(Buffer.isBuffer(n))return n;return Buffer.from(n)}function Zn(n){let i=Math.max(1980,n.getFullYear()),s=(n.getHours()<<11|n.getMinutes()<<5|n.getSeconds()>>1)&65535,o=(i-1980<<9|n.getMonth()+1<<5|n.getDate())&65535;return{time:s,date:o}}function _i(n){let i=[],s=[],o=0;for(let u of n){let h=Yn(u.data),f=zn(h),S=Jn(h),b=Buffer.from(u.name.replace(/\\/g,"/"),"utf-8"),{time:A,date:v}=Zn(u.date??new Date(0)),w=u.mode??420,E=Buffer.alloc(30+b.length);E.writeUInt32LE(67324752,0),E.writeUInt16LE(20,4),E.writeUInt16LE(0,6),E.writeUInt16LE(8,8),E.writeUInt16LE(A,10),E.writeUInt16LE(v,12),E.writeUInt32LE(S,14),E.writeUInt32LE(f.length,18),E.writeUInt32LE(h.length,22),E.writeUInt16LE(b.length,26),E.writeUInt16LE(0,28),b.copy(E,30);let P=Buffer.alloc(46+b.length);P.writeUInt32LE(33639248,0),P.writeUInt16LE(798,4),P.writeUInt16LE(20,6),P.writeUInt16LE(0,8),P.writeUInt16LE(8,10),P.writeUInt16LE(A,12),P.writeUInt16LE(v,14),P.writeUInt32LE(S,16),P.writeUInt32LE(f.length,20),P.writeUInt32LE(h.length,24),P.writeUInt16LE(b.length,28),P.writeUInt16LE(0,30),P.writeUInt16LE(0,32),P.writeUInt16LE(0,34),P.writeUInt16LE(0,36),P.writeUInt32LE((w&65535)<<16,38),P.writeUInt32LE(o,42),b.copy(P,46),i.push(E,f),s.push(P),o+=E.length+f.length}let c=Buffer.concat(s),l=Buffer.alloc(22);return l.writeUInt32LE(101010256,0),l.writeUInt16LE(0,4),l.writeUInt16LE(0,6),l.writeUInt16LE(n.length,8),l.writeUInt16LE(n.length,10),l.writeUInt32LE(c.length,12),l.writeUInt32LE(o,16),l.writeUInt16LE(0,20),Buffer.concat([...i,c,l])}function JA(n){let i=n.adapterImport??"./adapter",s=n.entryImport.replace(/\\/g,"/");return`// Generated by ts-cloud — serverless app bootstrap. Do not edit.
|
|
7264
|
+
`;static createAbTestsTable(n){return{[`${n.slug}AbTestsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-ab-tests`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}}static createAbTestManagerLambda(n){return{[`${n.slug}AbTestManagerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-ab-test-manager`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Te.AbTestManagerCode},Environment:{Variables:{AB_TESTS_TABLE:n.abTestsTable}}}}}}static selectVariant(n,i){let s=Te.hashString(i+n.id)%100,o=0;for(let c=0;c<n.variants.length;c++)if(o+=n.trafficSplit[c],s<o)return n.variants[c];return n.variants[n.variants.length-1]}static determineWinner(n){if(n.variants.length===0)return null;let i=n.winningCriteria,s=n.variants[0],o=Te.getMetricValue(s,i);for(let c of n.variants.slice(1)){let l=Te.getMetricValue(c,i);if(l>o)o=l,s=c}return s}static calculateSignificance(n,i,s){let o=n.stats.sent,c=i.stats.sent;if(o<30||c<30)return 0;let l=Te.getMetricValue(n,s)/100,u=Te.getMetricValue(i,s)/100,h=(l*o+u*c)/(o+c),f=Math.sqrt(h*(1-h)*(1/o+1/c));if(f===0)return 0;let S=Math.abs(l-u)/f;if(S>=2.576)return 99;if(S>=1.96)return 95;if(S>=1.645)return 90;if(S>=1.28)return 80;return Math.round(S*30)}static getMetricValue(n,i){switch(i){case"delivery_rate":return n.stats.deliveryRate;case"click_rate":return n.stats.clickRate;case"reply_rate":return n.stats.replyRate;case"conversion_rate":return n.stats.conversionRate;default:return n.stats.deliveryRate}}static hashString(n){let i=0;for(let s=0;s<n.length;s++){let o=n.charCodeAt(s);i=(i<<5)-i+o,i=i&i}return Math.abs(i)}}class km{queues=new Map;messageGroups=new Map;deduplicationConfigs=new Map;messages=new Map;queueCounter=0;groupCounter=0;deduplicationCounter=0;messageCounter=0;sequenceCounter=0;createFIFOQueue(n){let i=`fifo-queue-${Date.now()}-${this.queueCounter++}`,s=n.name.endsWith(".fifo")?n.name:`${n.name}.fifo`,{name:o,...c}=n,l={id:i,name:s,queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${s}`,...c};return this.queues.set(i,l),this.createDeduplicationConfig({queueId:i,contentBasedDeduplication:n.contentBasedDeduplication,deduplicationInterval:300}),l}createHighThroughputFIFO(n){return this.createFIFOQueue({name:n.name,contentBasedDeduplication:n.contentBasedDeduplication??!0,deduplicationScope:"messageGroup",fifoThroughputLimit:"perMessageGroupId",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createStandardFIFO(n){return this.createFIFOQueue({name:n.name,contentBasedDeduplication:n.contentBasedDeduplication??!1,deduplicationScope:"queue",fifoThroughputLimit:"perQueue",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createDeduplicationConfig(n){let i={id:`dedup-${Date.now()}-${this.deduplicationCounter++}`,deduplicationHashes:new Map,...n};return this.deduplicationConfigs.set(n.queueId,i),i}sendMessage(n){let i=this.queues.get(n.queueId);if(!i)throw Error(`Queue not found: ${n.queueId}`);let s=this.deduplicationConfigs.get(n.queueId);if(s){let u=n.messageDeduplicationId||(i.contentBasedDeduplication?this.generateHash(n.messageBody):void 0);if(u&&this.isDuplicate(s,u))return null;if(u)s.deduplicationHashes.set(u,new Date)}let o=`msg-${Date.now()}-${this.messageCounter++}`,c=this.generateSequenceNumber(),l={id:o,messageId:o,messageGroupId:n.messageGroupId,messageDeduplicationId:n.messageDeduplicationId,body:n.messageBody,attributes:n.messageAttributes||{},sentTimestamp:new Date,sequenceNumber:c};return this.messages.set(o,l),this.updateMessageGroup(n.queueId,n.messageGroupId),l}isDuplicate(n,i){let s=n.deduplicationHashes.get(i);if(!s)return!1;if((Date.now()-s.getTime())/1000>n.deduplicationInterval)return n.deduplicationHashes.delete(i),!1;return!0}generateHash(n){let i=0;for(let s=0;s<n.length;s++){let o=n.charCodeAt(s);i=(i<<5)-i+o,i=i&i}return Math.abs(i).toString(36)}generateSequenceNumber(){return`${Date.now()}${this.sequenceCounter++}`.padStart(20,"0")}updateMessageGroup(n,i){let s=`${n}-${i}`,o=this.messageGroups.get(s);if(!o)o={id:`group-${Date.now()}-${this.groupCounter++}`,messageGroupId:i,queueId:n,messagesInFlight:0},this.messageGroups.set(s,o);o.messagesInFlight++,o.lastMessageTimestamp=new Date}getMessageGroups(n){return Array.from(this.messageGroups.values()).filter((i)=>i.queueId===n)}getQueue(n){return this.queues.get(n)}listQueues(){return Array.from(this.queues.values())}getMessages(n,i){let s=Array.from(this.messages.values());if(i)s=s.filter((o)=>o.messageGroupId===i);return s.sort((o,c)=>o.sequenceNumber.localeCompare(c.sequenceNumber))}generateFIFOQueueCF(n){return{Type:"AWS::SQS::Queue",Properties:{QueueName:n.name,FifoQueue:!0,ContentBasedDeduplication:n.contentBasedDeduplication,DeduplicationScope:n.deduplicationScope,FifoThroughputLimit:n.fifoThroughputLimit,MessageRetentionPeriod:n.messageRetentionPeriod,VisibilityTimeout:n.visibilityTimeout,ReceiveMessageWaitTimeSeconds:n.receiveMessageWaitTime,...n.deadLetterTargetArn&&{RedrivePolicy:{deadLetterTargetArn:n.deadLetterTargetArn,maxReceiveCount:n.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 ME=new km;class Bm{monitors=new Map;metrics=new Map;alerts=new Map;reprocessJobs=new Map;monitorCounter=0;metricsCounter=0;alertCounter=0;jobCounter=0;createDLQMonitor(n){let i=`dlq-monitor-${Date.now()}-${this.monitorCounter++}`,s={id:i,...n};return this.monitors.set(i,s),s}createAutomatedMonitor(n){return this.createDLQMonitor({name:n.name,queueUrl:n.queueUrl,sourceQueues:n.sourceQueues,maxReceiveCount:3,alarmThreshold:10,autoReprocess:!0,reprocessStrategy:"scheduled",notificationTopicArn:n.notificationTopicArn})}collectMetrics(n){let i={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:n,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)},s=this.metrics.get(n)||[];return s.push(i),this.metrics.set(n,s),this.checkForAlerts(n,i),i}checkForAlerts(n,i){let s=Array.from(this.monitors.values()).find((c)=>c.queueUrl===n);if(!s)return;if(i.approximateNumberOfMessages>=s.alarmThreshold)this.createAlert({monitorId:s.id,alertType:"threshold_exceeded",severity:"high",message:`DLQ ${s.name} has ${i.approximateNumberOfMessages} messages (threshold: ${s.alarmThreshold})`});let o=3600;if(i.approximateAgeOfOldestMessage>o)this.createAlert({monitorId:s.id,alertType:"old_message",severity:"medium",message:`DLQ ${s.name} has messages older than ${o} seconds`})}createAlert(n){let i=`alert-${Date.now()}-${this.alertCounter++}`,s={id:i,timestamp:new Date,acknowledged:!1,...n};return this.alerts.set(i,s),s}acknowledgeAlert(n){let i=this.alerts.get(n);if(!i)throw Error(`Alert not found: ${n}`);return i.acknowledged=!0,i}createReprocessJob(n){let i=`reprocess-${Date.now()}-${this.jobCounter++}`,s={id:i,queueUrl:n.queueUrl,messageId:n.messageId,attempts:0,status:"pending"};return this.reprocessJobs.set(i,s),s}async executeReprocessJob(n){let i=this.reprocessJobs.get(n);if(!i)throw Error(`Reprocess job not found: ${n}`);i.status="processing",i.startedAt=new Date,i.attempts++,await new Promise((o)=>setTimeout(o,100));let s=Math.random()>0.3;if(i.status=s?"success":"failed",i.completedAt=new Date,!s)i.error="Reprocessing failed - original error still present";return i}async batchReprocess(n){let i=[];for(let s=0;s<n.maxMessages;s++){let o=this.createReprocessJob({queueUrl:n.queueUrl,messageId:`msg-${s}`});await this.executeReprocessJob(o.id),i.push(o)}return i}getDLQStatistics(n,i=24){let s=new Date(Date.now()-i*60*60*1000),o=(this.metrics.get(n)||[]).filter((b)=>b.timestamp>=s);if(o.length===0)return{totalMessages:0,avgAge:0,messagesReceived:0,messagesDeleted:0,messagesReprocessed:0,successRate:0};let c=o[o.length-1],l=o.reduce((b,A)=>b+A.messagesReceived,0),u=o.reduce((b,A)=>b+A.messagesDeleted,0),h=o.reduce((b,A)=>b+A.messagesReprocessed,0),f=o.reduce((b,A)=>b+A.approximateAgeOfOldestMessage,0)/o.length,S=h>0?u/h*100:0;return{totalMessages:c.approximateNumberOfMessages,avgAge:f,messagesReceived:l,messagesDeleted:u,messagesReprocessed:h,successRate:S}}getMonitor(n){return this.monitors.get(n)}listMonitors(){return Array.from(this.monitors.values())}getAlerts(n,i){let s=Array.from(this.alerts.values());if(n)s=s.filter((o)=>o.monitorId===n);if(i!==void 0)s=s.filter((o)=>o.acknowledged===i);return s.sort((o,c)=>c.timestamp.getTime()-o.timestamp.getTime())}getReprocessJobs(n){let i=Array.from(this.reprocessJobs.values());if(n)i=i.filter((s)=>s.queueUrl===n);return i}generateDLQAlarmCF(n){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${n.name}-messages-alarm`,AlarmDescription:`Alert when DLQ ${n.name} exceeds threshold`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Average",Period:300,EvaluationPeriods:1,Threshold:n.alarmThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:n.queueUrl.split("/").pop()}],...n.notificationTopicArn&&{AlarmActions:[n.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 FE=new Bm;class _m{configs=new Map;jobs=new Map;metrics=new Map;configCounter=0;jobCounter=0;metricsCounter=0;createBatchConfig(n){let i=`batch-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}createHighThroughputConfig(n){return this.createBatchConfig({queueUrl:n.queueUrl,batchSize:10,maxWaitTime:100,parallelProcessors:10,retryAttempts:3,visibilityTimeout:30})}createLowLatencyConfig(n){return this.createBatchConfig({queueUrl:n.queueUrl,batchSize:1,maxWaitTime:0,parallelProcessors:5,retryAttempts:2,visibilityTimeout:10})}createBatchJob(n){let i=`batch-job-${Date.now()}-${this.jobCounter++}`;if(!this.configs.get(n.configId))throw Error(`Batch config not found: ${n.configId}`);let s=[];for(let c=0;c<n.messageCount;c++)s.push({id:`msg-${i}-${c}`,messageId:`${i}-${c}`,body:`Message ${c}`,receiptHandle:`receipt-${i}-${c}`,attributes:{},status:"pending"});let o={id:i,configId:n.configId,messages:s,status:"pending",processedCount:0,failedCount:0};return this.jobs.set(i,o),o}async processBatchJob(n){let i=this.jobs.get(n);if(!i)throw Error(`Batch job not found: ${n}`);let s=this.configs.get(i.configId);if(!s)throw Error(`Batch config not found: ${i.configId}`);i.status="processing",i.startedAt=new Date;let o=this.chunkArray(i.messages,s.batchSize);for(let c of o)await this.processBatch(c,s);return i.processedCount=i.messages.filter((c)=>c.status==="success").length,i.failedCount=i.messages.filter((c)=>c.status==="failed").length,i.status=i.failedCount===0?"completed":"failed",i.completedAt=new Date,this.collectProcessorMetrics(s.id,i),i}async processBatch(n,i){let s=n.map((o)=>this.processMessage(o,i));await Promise.all(s)}async processMessage(n,i){n.status="processing";let s=Date.now();await new Promise((c)=>setTimeout(c,Math.random()*100));let o=Date.now()-s;if(n.processingTime=o,Math.random()>0.1)n.status="success";else n.status="failed",n.error="Processing error"}chunkArray(n,i){let s=[];for(let o=0;o<n.length;o+=i)s.push(n.slice(o,o+i));return s}collectProcessorMetrics(n,i){let s=`metrics-${Date.now()}-${this.metricsCounter++}`,o=i.messages.filter((b)=>b.status==="success").map((b)=>b.processingTime||0).filter((b)=>b>0),c=o.length>0?o.reduce((b,A)=>b+A,0)/o.length:0,l=i.completedAt&&i.startedAt?(i.completedAt.getTime()-i.startedAt.getTime())/1000:1,u=i.processedCount/l,h=i.messages.length>0?i.failedCount/i.messages.length*100:0,f={id:s,configId:n,timestamp:new Date,messagesProcessed:i.processedCount,averageProcessingTime:c,throughput:u,errorRate:h},S=this.metrics.get(n)||[];S.push(f),this.metrics.set(n,S)}getBatchStatistics(n){let i=this.metrics.get(n)||[];if(i.length===0)return{totalJobsProcessed:0,totalMessagesProcessed:0,averageThroughput:0,averageErrorRate:0,averageProcessingTime:0};let s=i.reduce((u,h)=>u+h.messagesProcessed,0),o=i.reduce((u,h)=>u+h.throughput,0)/i.length,c=i.reduce((u,h)=>u+h.errorRate,0)/i.length,l=i.reduce((u,h)=>u+h.averageProcessingTime,0)/i.length;return{totalJobsProcessed:i.length,totalMessagesProcessed:s,averageThroughput:o,averageErrorRate:c,averageProcessingTime:l}}optimizeBatchConfig(n){let i=this.configs.get(n);if(!i)throw Error(`Batch config not found: ${n}`);let s=this.getBatchStatistics(n);if(s.averageErrorRate<5&&i.batchSize<10)i.batchSize=Math.min(10,i.batchSize+1);if(s.averageErrorRate>20&&i.batchSize>1)i.batchSize=Math.max(1,i.batchSize-1);if(s.averageThroughput<5&&i.parallelProcessors<20)i.parallelProcessors++;return i}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getJob(n){return this.jobs.get(n)}listJobs(n){let i=Array.from(this.jobs.values());if(n)i=i.filter((s)=>s.configId===n);return i}generateBatchProcessorCF(n){return{Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:`arn:aws:sqs:us-east-1:123456789012:${n.queueUrl.split("/").pop()}`,FunctionName:"batch-processor-function",BatchSize:n.batchSize,MaximumBatchingWindowInSeconds:n.maxWaitTime/1000,FunctionResponseTypes:["ReportBatchItemFailures"]}}}clear(){this.configs.clear(),this.jobs.clear(),this.metrics.clear(),this.configCounter=0,this.jobCounter=0,this.metricsCounter=0}}var UE=new _m;class Om{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(n){let i=`queue-${Date.now()}-${this.queueCounter++}`,s={id:i,purgeInProgress:!1,...n};return this.queues.set(i,s),s}createStandardQueue(n){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${n.queueName}`,queueName:n.queueName,messageRetentionPeriod:(n.messageRetentionDays||4)*24*60*60,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:0})}createLongPollingQueue(n){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${n.queueName}`,queueName:n.queueName,messageRetentionPeriod:345600,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:n.waitTimeSeconds||20})}createRetentionPolicy(n){let i=`retention-${Date.now()}-${this.retentionCounter++}`,s={id:i,...n};this.retentionPolicies.set(i,s);let o=this.queues.get(n.queueId);if(o)o.messageRetentionPeriod=n.retentionPeriod;return s}createShortRetentionPolicy(n){return this.createRetentionPolicy({queueId:n.queueId,retentionPeriod:n.retentionHours*60*60,autoCleanup:!0,archiveExpiredMessages:!1})}createArchivalRetentionPolicy(n){return this.createRetentionPolicy({queueId:n.queueId,retentionPeriod:n.retentionDays*24*60*60,autoCleanup:!0,cleanupSchedule:"cron(0 0 * * ? *)",archiveExpiredMessages:!0,archiveS3Bucket:n.s3Bucket})}createDelayQueue(n){let i=`delay-${Date.now()}-${this.delayCounter++}`,s={id:i,...n};this.delayQueues.set(i,s);let o=Array.from(this.queues.values()).find((c)=>c.queueUrl===n.queueUrl);if(o)o.delaySeconds=n.defaultDelay;return s}createScheduledDelayQueue(n){return this.createDelayQueue({queueUrl:n.queueUrl,defaultDelay:n.delayMinutes*60,perMessageDelay:!1,maxDelay:900})}async purgeQueue(n){let i=this.queues.get(n);if(!i)throw Error(`Queue not found: ${n}`);if(i.purgeInProgress)throw Error("Purge already in progress for this queue");let s=`purge-${Date.now()}-${this.purgeCounter++}`,o={id:s,queueUrl:i.queueUrl,status:"in_progress",startedAt:new Date};return this.purgeOperations.set(s,o),i.purgeInProgress=!0,setTimeout(()=>{o.status="completed",o.completedAt=new Date,o.messagesPurged=Math.floor(Math.random()*1000),i.purgeInProgress=!1},100),o}collectQueueMetrics(n){let i={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:n,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)},s=this.metrics.get(n)||[];return s.push(i),this.metrics.set(n,s),i}getQueueHealth(n){let i=this.metrics.get(n)||[];if(i.length===0)return{status:"healthy",issues:[],recommendations:[]};let s=i[i.length-1],o=[],c=[],l="healthy";if(s.approximateNumberOfMessages>1e4)l="critical",o.push("Large message backlog detected"),c.push("Increase consumer capacity");else if(s.approximateNumberOfMessages>1000)l="warning",o.push("Growing message backlog"),c.push("Monitor consumer performance");if(s.oldestMessageAge&&s.oldestMessageAge>3600){if(l!=="critical")l="warning";o.push("Old messages in queue"),c.push("Review message processing")}if(s.approximateNumberOfMessagesDelayed>100){if(l!=="critical")l="warning";o.push("High number of delayed messages")}return{status:l,issues:o,recommendations:c}}getQueue(n){return this.queues.get(n)}listQueues(){return Array.from(this.queues.values())}getRetentionPolicy(n){return this.retentionPolicies.get(n)}listRetentionPolicies(){return Array.from(this.retentionPolicies.values())}getPurgeOperations(n){let i=Array.from(this.purgeOperations.values());if(n)i=i.filter((s)=>s.queueUrl===n);return i}generateQueueCF(n){return{Type:"AWS::SQS::Queue",Properties:{QueueName:n.queueName,MessageRetentionPeriod:n.messageRetentionPeriod,DelaySeconds:n.delaySeconds,MaximumMessageSize:n.maximumMessageSize,ReceiveMessageWaitTimeSeconds:n.receiveMessageWaitTime}}}generateCleanupRuleCF(n){return{Type:"AWS::Events::Rule",Properties:{Name:`${n.id}-cleanup`,Description:"Automated queue cleanup",ScheduleExpression:n.cleanupSchedule||"cron(0 0 * * ? *)",State:"ENABLED",Targets:[{Arn:"arn:aws:lambda:us-east-1:123456789012:function:queue-cleanup",Id:n.id,Input:JSON.stringify({queueId:n.queueId,archiveBucket:n.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 QE=new Om,Qn=(()=>{let n=[];for(let i=0;i<256;i++){let s=i;for(let o=0;o<8;o++)s=s&1?3988292384^s>>>1:s>>>1;n[i]=s>>>0}return n})();function Jn(n){let i=4294967295;for(let s=0;s<n.length;s++)i=Qn[(i^n[s])&255]^i>>>8;return(i^4294967295)>>>0}function Yn(n){if(typeof n==="string")return Buffer.from(n,"utf-8");if(Buffer.isBuffer(n))return n;return Buffer.from(n)}function Zn(n){let i=Math.max(1980,n.getFullYear()),s=(n.getHours()<<11|n.getMinutes()<<5|n.getSeconds()>>1)&65535,o=(i-1980<<9|n.getMonth()+1<<5|n.getDate())&65535;return{time:s,date:o}}function _i(n){let i=[],s=[],o=0;for(let u of n){let h=Yn(u.data),f=zn(h),S=Jn(h),b=Buffer.from(u.name.replace(/\\/g,"/"),"utf-8"),{time:A,date:v}=Zn(u.date??new Date(0)),w=u.mode??420,E=Buffer.alloc(30+b.length);E.writeUInt32LE(67324752,0),E.writeUInt16LE(20,4),E.writeUInt16LE(0,6),E.writeUInt16LE(8,8),E.writeUInt16LE(A,10),E.writeUInt16LE(v,12),E.writeUInt32LE(S,14),E.writeUInt32LE(f.length,18),E.writeUInt32LE(h.length,22),E.writeUInt16LE(b.length,26),E.writeUInt16LE(0,28),b.copy(E,30);let P=Buffer.alloc(46+b.length);P.writeUInt32LE(33639248,0),P.writeUInt16LE(798,4),P.writeUInt16LE(20,6),P.writeUInt16LE(0,8),P.writeUInt16LE(8,10),P.writeUInt16LE(A,12),P.writeUInt16LE(v,14),P.writeUInt32LE(S,16),P.writeUInt32LE(f.length,20),P.writeUInt32LE(h.length,24),P.writeUInt16LE(b.length,28),P.writeUInt16LE(0,30),P.writeUInt16LE(0,32),P.writeUInt16LE(0,34),P.writeUInt16LE(0,36),P.writeUInt32LE((w&65535)<<16,38),P.writeUInt32LE(o,42),b.copy(P,46),i.push(E,f),s.push(P),o+=E.length+f.length}let c=Buffer.concat(s),l=Buffer.alloc(22);return l.writeUInt32LE(101010256,0),l.writeUInt16LE(0,4),l.writeUInt16LE(0,6),l.writeUInt16LE(n.length,8),l.writeUInt16LE(n.length,10),l.writeUInt32LE(c.length,12),l.writeUInt32LE(o,16),l.writeUInt16LE(0,20),Buffer.concat([...i,c,l])}function JA(n){let i=n.adapterImport??"./adapter",s=n.entryImport.replace(/\\/g,"/");return`// Generated by ts-cloud — serverless app bootstrap. Do not edit.
|
|
7265
7265
|
import * as __userModule from ${JSON.stringify(s)}
|
|
7266
7266
|
import { resolveApp, createHandlers } from ${JSON.stringify(i)}
|
|
7267
7267
|
|
|
@@ -7273,7 +7273,7 @@ export const queue = __handlers.queue
|
|
|
7273
7273
|
export const cli = __handlers.cli
|
|
7274
7274
|
`}var ui=["adapter.ts","recursion.ts","auto-recursion.ts"];function di(){return Oe(si(li(import.meta.url)),"runtime")}function XA(n,i,s){for(let o of n??[])s?.(`build: ${o}`),Xn(o,{stdio:"inherit",cwd:i})}function So(n){return ei("sha256").update(n).digest("hex")}function Hd(n,i,s){return`deployments/${n}/${i}/${s}.zip`}async function Wr(n){let i=ci(n.projectRoot??process.cwd()),{app:s}=n;if(!n.skipBuild)XA(s.build,i,n.onStep);let o=s.entry;if(!o)throw Error("serverless app: `entry` is required to package a Node/Bun application");let c=oi(o)?o:Oe(i,o),l=ai(Oe(ii(),"tscloud-pkg-"));try{for(let v of ui)ti(Oe(di(),v),Oe(l,v));let u=Oe(l,"bootstrap.ts");ni(u,JA({entryImport:c,adapterImport:"./adapter"})),n.onStep?.("bundling application");let h=await Bun.build({entrypoints:[u],target:s.kind==="bun"?"bun":"node",format:"esm",minify:!1,sourcemap:"none"});if(!h.success){let v=h.logs.map((w)=>String(w)).join(`
|
|
7275
7275
|
`);throw Error(`serverless app bundle failed:
|
|
7276
|
-
${v}`)}let f=h.outputs[0],S=Buffer.from(await f.arrayBuffer()),b="index",A=_i([{name:`${b}.mjs`,data:S}]);return{zip:A,bundle:S,sha256:So(A),handlerFile:b,handlers:{http:s.handlers?.http??`${b}.http`,queue:s.handlers?.queue??`${b}.queue`,cli:s.handlers?.cli??`${b}.cli`},bundleBytes:S.length}}finally{ri(l,{recursive:!0,force:!0})}}var YA=["18","20","22"];function mi(n){if(!n)return"22";let i=String(n).match(/(\d+)/);return i?i[1]:"22"}function Co(n){let i=n.kind??"node";if(i==="php")return{lambdaRuntime:"provided.al2023",kind:"php",version:n.phpVersion??"8.3",usesLayer:!0,layerKind:"php",layerEnvVar:"TSCLOUD_PHP_LAYER_ARN"};if(i==="bun")return{lambdaRuntime:"provided.al2023",kind:"bun",version:n.runtimeVersion??"latest",usesLayer:!0,layerKind:"bun",layerEnvVar:"TSCLOUD_BUN_LAYER_ARN"};let s=mi(n.runtimeVersion);if(n.runtime!=="provided.al2023"&&YA.includes(s))return{lambdaRuntime:n.runtime&&n.runtime.startsWith("nodejs")?n.runtime:`nodejs${s}.x`,kind:"node",version:s,usesLayer:!1};return{lambdaRuntime:"provided.al2023",kind:"node",version:s,usesLayer:!0,layerKind:"node",layerEnvVar:"TSCLOUD_NODE_LAYER_ARN"}}function Xt(n,i,s){if(n.queues===!1)return[];if(n.queues===void 0||n.queues===!0)return[{name:`${i}-${s}-default`}];return n.queues.map((o)=>{if(typeof o==="string")return{name:`${i}-${s}-${o}`};let[c,l]=Object.entries(o)[0];return{name:`${i}-${s}-${c}`,concurrency:l}})}function Gd(n,i,s){return Xt(n,i,s).map((o)=>o.name)}function qd(n){let{app:i,environment:s,handlers:o}=n,c=n.config.project.slug,l=Co(i).lambdaRuntime,u=i.architecture??"x86_64",h=n.config.project.region,f={http:`${c}-${s}-http`,queue:`${c}-${s}-queue`,cli:`${c}-${s}-cli`};if(i.gatewayVersion===1)throw Error("serverless app: `gatewayVersion: 1` (REST API) is not supported — ts-cloud uses API Gateway HTTP API (v2). Remove `gatewayVersion` or set it to 2.");let S=Xt(i,c,s),b=S.map((z)=>z.name),A=b.length>0,v=i.logRetention??14,w=i.packaging==="image";if(w&&i.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 E=(i.scheduler??"on")!=="off",P=(i.cache?.driver??"dynamodb")==="dynamodb",R=Boolean(i.assets),D=po(c,s),x=i.tmpStorage??512,I={},_={},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}-${s}-*`)},{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameter","ssm:GetParameters","ssm:GetParametersByPath"],Resource:[e.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${c}/${s}/*`),e.sub(`arn:aws:ssm:\${AWS::Region}:\${AWS::AccountId}:parameter/${c}/${s}/*`)]},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[e.sub(`arn:aws:s3:::${D}`),e.sub(`arn:aws:s3:::${D}/*`),...i.storage?.bucket?[e.sub(`arn:aws:s3:::${i.storage.bucket}`),e.sub(`arn:aws:s3:::${i.storage.bucket}/*`)]:[]]}]}}];if(A)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["sqs:SendMessage","sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes","sqs:GetQueueUrl"],Resource:e.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${c}-${s}-*`)});if(P)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}-${s}-cache*`)});let W=["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"];if(i.vpc?.subnets?.length)W.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");if(i.lambdaInsights)W.push("arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy");I.AppRole={Type:"AWS::IAM::Role",Properties:{RoleName:`${c}-${s}-app-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:W,Policies:B}};let J=(z)=>({TSCLOUD_LAMBDA_MODE:z,TSCLOUD_ENV:s,...i.octane?{TSCLOUD_OCTANE:"1"}:{},...i.scheduler==="sub-minute"?{TSCLOUD_SCHEDULER:"sub-minute"}:{},...P?{TSCLOUD_CACHE_TABLE:`${c}-${s}-cache`}:{},...A?{TSCLOUD_QUEUE:b[0]}:{},...i.env??{}}),K=Boolean(i.efs),Y=typeof i.efs==="object"?i.efs:{},Z=Y.mountPath??"/mnt/local",ne=K&&!Y.accessPointArn,de=Y.accessPointArn??(ne?e.getAtt("EfsAccessPoint","Arn"):void 0),oe=i.vpc?.subnets??[],le=oe.length>0,ie=i.cache?.driver==="elasticache"||i.database?.connection==="aurora-serverless"||Boolean(i.rdsProxy)||K;if(ie&&!le)throw Error("serverless app: elasticache / aurora-serverless / rdsProxy / efs require app.vpc.subnets (private subnets) to be set.");let Ee=le?{VpcConfig:{SubnetIds:oe,SecurityGroupIds:[...i.vpc?.securityGroups??[],...ie?[e.getAtt("DataSecurityGroup","GroupId")]:[]]}}:{},Fe=ne?oe.map((z,ae)=>`EfsMountTarget${ae}`):[],Et=K?{FileSystemConfigs:[{Arn:de,LocalMountPath:Z}]}:{};if(K)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess","elasticfilesystem:DescribeMountTargets"],Resource:"*"});function pe(z,ae,X,se,fe,nt,Ce,it=x){I[`${z}LogGroup`]={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:`/aws/lambda/${ae}`,RetentionInDays:v}};let Pt=[...n.runtimeLayers??[],...i.lambdaInsights?[i.lambdaInsights.layerArn]:[]],It=w?{PackageType:"Image",Code:{ImageUri:e.ref("ImageUri")},...i.kind==="php"?{}:{ImageConfig:{Command:[X]}}}:{Runtime:l,Handler:X,Code:{S3Bucket:e.ref("ArtifactBucket"),S3Key:e.ref("ArtifactKey")},...Pt.length?{Layers:[...new Set(Pt)]}:{}};I[z]={Type:"AWS::Lambda::Function",DependsOn:[`${z}LogGroup`,...Fe],Properties:{FunctionName:ae,Architectures:[u],MemorySize:fe,Timeout:nt,Role:e.getAtt("AppRole","Arn"),Environment:{Variables:J(se)},EphemeralStorage:{Size:it},...It,...Ce!==void 0?{ReservedConcurrentExecutions:Ce}:{},...Ee,...Et}}}if(pe("HttpFunction",f.http,o.http,"http",i.memory??1024,i.timeout??28,i.concurrency,x),pe("CliFunction",f.cli,o.cli,"cli",i.cliMemory??1024,i.cliTimeout??900,void 0,i.cliTmpStorage??x),A)pe("QueueFunction",f.queue,o.queue,"queue",i.queueMemory??1024,i.queueTimeout??120,void 0,i.queueTmpStorage??x);let ue=(i.provisionedConcurrency??0)>0?i.provisionedConcurrency:0,he=["HttpFunction","CliFunction",...A?["QueueFunction"]:[]];if(ue)for(let z of he)I[`${z}Version`]={Type:"AWS::Lambda::Version",DeletionPolicy:"Retain",Properties:{FunctionName:e.ref(z)}},I[`${z}Alias`]={Type:"AWS::Lambda::Alias",Properties:{FunctionName:e.ref(z),Name:"live",FunctionVersion:e.getAtt(`${z}Version`,"Version"),ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:ue}}};let Ie=(z)=>ue?e.ref(`${z}Alias`):e.getAtt(z,"Arn"),ye=(z)=>ue?e.ref(`${z}Alias`):e.ref(z);I.HttpApi={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:`${c}-${s}`,ProtocolType:"HTTP"}},I.HttpIntegration={Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:e.ref("HttpApi"),IntegrationType:"AWS_PROXY",IntegrationUri:Ie("HttpFunction"),PayloadFormatVersion:"2.0"}},I.HttpRoute={Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:e.ref("HttpApi"),RouteKey:"$default",Target:e.join("/",["integrations",e.ref("HttpIntegration")])}},I.HttpStage={Type:"AWS::ApiGatewayV2::Stage",Properties:{ApiId:e.ref("HttpApi"),StageName:"$default",AutoDeploy:!0}},I.HttpPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:ye("HttpFunction"),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:e.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${HttpApi}/*/*")}},_.HttpApiEndpoint={Description:"HTTP API endpoint",Value:e.getAtt("HttpApi","ApiEndpoint")},_.HttpApiId={Description:"HTTP API id",Value:e.ref("HttpApi")};let Ae=(Array.isArray(i.domain)?i.domain:i.domain?[i.domain]:[]).filter(Boolean);if(Ae.length){if(!i.certificateArn&&!i.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=i.certificateArn;if(!z)I.HttpCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:Ae[0],...Ae.length>1?{SubjectAlternativeNames:Ae.slice(1)}:{},ValidationMethod:"DNS",DomainValidationOptions:Ae.map((ae)=>({DomainName:ae,HostedZoneId:i.hostedZoneId}))}},z=e.ref("HttpCertificate");Ae.forEach((ae,X)=>{let se=`HttpDomain${X}`;if(I[se]={Type:"AWS::ApiGatewayV2::DomainName",Properties:{DomainName:ae,DomainNameConfigurations:[{CertificateArn:z,EndpointType:"REGIONAL"}]}},I[`HttpApiMapping${X}`]={Type:"AWS::ApiGatewayV2::ApiMapping",DependsOn:["HttpStage"],Properties:{ApiId:e.ref("HttpApi"),DomainName:e.ref(se),Stage:"$default"}},i.hostedZoneId)I[`HttpDomainRecord${X}`]={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i.hostedZoneId,Name:ae,Type:"A",AliasTarget:{DNSName:e.getAtt(se,"RegionalDomainName"),HostedZoneId:e.getAtt(se,"RegionalHostedZoneId")}}};_[`CustomDomain${X}`]={Description:`Custom domain ${ae}`,Value:ae},_[`CustomDomainTarget${X}`]={Description:`Point ${ae} (CNAME/alias) at this APIGW regional domain`,Value:e.getAtt(se,"RegionalDomainName")}})}if(A)I.AppQueueDlq={Type:"AWS::SQS::Queue",Properties:{QueueName:`${c}-${s}-dlq`,MessageRetentionPeriod:1209600}},S.forEach((z,ae)=>{let X=`AppQueue${ae}`,se=i.queueTimeout??120;I[X]={Type:"AWS::SQS::Queue",Properties:{QueueName:z.name,VisibilityTimeout:Math.min(43200,se*6),RedrivePolicy:{deadLetterTargetArn:e.getAtt("AppQueueDlq","Arn"),maxReceiveCount:i.queueTries??3}}};let fe=z.concurrency??i.queueConcurrency;I[`${X}Mapping`]={Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:e.getAtt(X,"Arn"),FunctionName:ye("QueueFunction"),BatchSize:1,FunctionResponseTypes:["ReportBatchItemFailures"],...fe?{ScalingConfig:{MaximumConcurrency:Math.max(2,fe)}}:{}}},_[`QueueUrl${ae}`]={Description:`Queue URL: ${z.name}`,Value:e.ref(X)}});if(E)I.SchedulerRule={Type:"AWS::Events::Rule",Properties:{Name:`${c}-${s}-scheduler`,ScheduleExpression:"rate(1 minute)",State:"ENABLED",Targets:[{Id:"cli",Arn:Ie("CliFunction"),Input:JSON.stringify({command:"schedule:run"})}]}},I.SchedulerPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:ye("CliFunction"),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.getAtt("SchedulerRule","Arn")}};if(i.warm&&i.warm>0){let z={http:"HttpFunction",queue:"QueueFunction",cli:"CliFunction"},ae=(i.warmFunctions??["http"]).filter((X)=>X!=="queue"||A);for(let X of ae){let se=X.charAt(0).toUpperCase()+X.slice(1),fe=Math.ceil(i.warm/5),nt=0;for(let Ce=0;Ce<fe;Ce++){let it=Math.min(5,i.warm-nt);I[`Warmer${se}Rule${Ce}`]={Type:"AWS::Events::Rule",Properties:{Name:`${c}-${s}-warmer-${X}-${Ce}`,ScheduleExpression:"rate(5 minutes)",State:"ENABLED",Targets:Array.from({length:it},(Pt,It)=>({Id:`warm-${X}-${Ce}-${It}`,Arn:e.getAtt(z[X],"Arn"),Input:JSON.stringify({warmer:!0})}))}},nt+=it}I[`Warmer${se}Permission`]={Type:"AWS::Lambda::Permission",Properties:{FunctionName:e.ref(z[X]),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.sub(`arn:aws:events:\${AWS::Region}:\${AWS::AccountId}:rule/${c}-${s}-warmer-${X}-*`)}}}}if(P)I.CacheTable={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${c}-${s}-cache`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"key",AttributeType:"S"}],KeySchema:[{AttributeName:"key",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"expires_at",Enabled:!0}}},_.CacheTableName={Description:"DynamoDB cache table",Value:e.ref("CacheTable")};if(R){if(I.AssetsBucket={Type:"AWS::S3::Bucket",Properties:{BucketName:D,PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}}},I.AssetsOAC={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${c}-${s}-assets-oac`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},I.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:""}}],...i.assetDomain?{Aliases:[i.assetDomain],ViewerCertificate:{AcmCertificateArn:i.assetCertificateArn??e.ref("AssetsCertificate"),SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}}:{}}}},i.assetDomain){if(!i.assetCertificateArn){if(!i.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.`);I.AssetsCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:i.assetDomain,ValidationMethod:"DNS",DomainValidationOptions:[{DomainName:i.assetDomain,HostedZoneId:i.hostedZoneId}]}}}if(i.hostedZoneId)I.AssetsDomainRecord={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i.hostedZoneId,Name:i.assetDomain,Type:"A",AliasTarget:{DNSName:e.getAtt("AssetsDistribution","DomainName"),HostedZoneId:"Z2FDTNDATAQYW2"}}};_.AssetDomain={Description:"Custom asset CDN host",Value:i.assetDomain}}I.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:::${D}/*`),Condition:{StringEquals:{"AWS:SourceArn":e.sub("arn:aws:cloudfront::${AWS::AccountId}:distribution/${AssetsDistribution}")}}}]}}},_.AssetsBucketName={Description:"Assets bucket",Value:e.ref("AssetsBucket")},_.AssetsCdnDomain={Description:"Assets CloudFront domain",Value:e.getAtt("AssetsDistribution","DomainName")}}if(i.firewall?.enabled){let z=[],ae=0;if(i.firewall.rateLimit)z.push({Name:"rate-limit",Priority:ae++,Action:{Block:{}},Statement:{RateBasedStatement:{Limit:i.firewall.rateLimit,AggregateKeyType:"IP"}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${s}-rate`}});let X={sqlInjection:"AWSManagedRulesSQLiRuleSet",xss:"AWSManagedRulesCommonRuleSet",common:"AWSManagedRulesCommonRuleSet",botControl:"AWSManagedRulesBotControlRuleSet",ipReputation:"AWSManagedRulesAmazonIpReputationList"};for(let se of i.firewall.rules??[]){let fe=X[se];if(!fe)continue;z.push({Name:`managed-${se}`,Priority:ae++,OverrideAction:{None:{}},Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:fe}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${s}-${se}`}})}I.WebAcl={Type:"AWS::WAFv2::WebACL",Properties:{Name:`${c}-${s}-waf`,Scope:"REGIONAL",DefaultAction:{Allow:{}},Rules:z,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${s}-waf`}}},_.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(!i.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.");I.DataSecurityGroup={Type:"AWS::EC2::SecurityGroup",Properties:{VpcId:i.vpc.id,GroupDescription:`${c}-${s} serverless data access`,SecurityGroupIngress:[{IpProtocol:"-1",CidrIp:"10.0.0.0/8"}]}}}if(ne)I.EfsFileSystem={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:!0,FileSystemTags:[{Key:"Name",Value:`${c}-${s}-efs`}]}},oe.forEach((z,ae)=>{I[`EfsMountTarget${ae}`]={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:e.ref("EfsFileSystem"),SubnetId:z,SecurityGroups:[e.getAtt("DataSecurityGroup","GroupId")]}}}),I.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"}}}},_.EfsFileSystemId={Description:"EFS file system id",Value:e.ref("EfsFileSystem")};if(i.cache?.driver==="elasticache")I.CacheSubnetGroup={Type:"AWS::ElastiCache::SubnetGroup",Properties:{Description:`${c}-${s} cache subnets`,SubnetIds:oe}},I.CacheCluster={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:`${c}-${s}-cache`,ReplicationGroupDescription:`${c}-${s} redis`,Engine:"redis",CacheNodeType:"cache.t4g.micro",NumCacheClusters:1,AutomaticFailoverEnabled:!1,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),SecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")],TransitEncryptionEnabled:!1}},_.CacheEndpoint={Description:"Redis primary endpoint",Value:e.getAtt("CacheCluster","PrimaryEndPoint.Address")};if(i.database?.connection==="aurora-serverless")I.DbSubnetGroup={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupDescription:`${c}-${s} db subnets`,SubnetIds:oe}},I.DbSecret={Type:"AWS::SecretsManager::Secret",Properties:{Name:`${c}/${s}/db`,GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"app"}),GenerateStringKey:"password",PasswordLength:32,ExcludePunctuation:!0}}},I.DbCluster={Type:"AWS::RDS::DBCluster",Properties:{Engine:"aurora-mysql",EngineMode:"provisioned",DBClusterIdentifier:`${c}-${s}-db`,DatabaseName:"app",MasterUsername:e.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:username}}"),MasterUserPassword:e.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:password}}"),ServerlessV2ScalingConfiguration:{MinCapacity:i.database?.minCapacity??0.5,MaxCapacity:i.database?.maxCapacity??4},DBSubnetGroupName:e.ref("DbSubnetGroup"),VpcSecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")]}},I.DbInstance={Type:"AWS::RDS::DBInstance",Properties:{Engine:"aurora-mysql",DBInstanceClass:"db.serverless",DBClusterIdentifier:e.ref("DbCluster")}},_.DbEndpoint={Description:"Aurora cluster endpoint",Value:e.getAtt("DbCluster","Endpoint.Address")};if(i.rdsProxy&&i.database?.connection==="aurora-serverless")I.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")}]}}]}},I.DbProxy={Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:typeof i.rdsProxy==="object"&&i.rdsProxy.name?i.rdsProxy.name:`${c}-${s}-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}},I.DbProxyTargetGroup={Type:"AWS::RDS::DBProxyTargetGroup",DependsOn:["DbInstance"],Properties:{DBProxyName:e.ref("DbProxy"),TargetGroupName:"default",DBClusterIdentifiers:[e.ref("DbCluster")]}},_.DbProxyEndpoint={Description:"RDS Proxy endpoint",Value:e.getAtt("DbProxy","Endpoint")};if(_.HttpFunctionName={Description:"HTTP function name",Value:e.ref("HttpFunction")},_.CliFunctionName={Description:"CLI function name",Value:e.ref("CliFunction")},A)_.QueueFunctionName={Description:"Queue function name",Value:e.ref("QueueFunction")};let Me={AWSTemplateFormatVersion:"2010-09-09",Description:`Serverless application for ${n.config.project.name} (${c}-${s})`,Parameters:w?{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:I,Outputs:_},Ue={};for(let z of Object.values(I))Ue[z.Type]=(Ue[z.Type]??0)+1;return{template:Me,functionNames:f,queueNames:b,resourceSummary:Ue}}var ZA=["cli","fpm","curl","mbstring","xml","pdo","mysqlnd","gd","bcmath","intl","opcache","sodium","process","pecl-redis6","pecl-apcu","pgsql"];function ey(n){let i=`php${n.replace(".","")}`;return ZA.map((s)=>`${i}-php-${s}`)}function Om(n,i){let s=`php${n.replace(".","")}`,o=ey(n).join(" \\\n "),c=`/opt/remi/${s}/root`,l=`/etc/opt/remi/${s}`;return`${i?`FROM almalinux:9 AS ${i}`:"FROM almalinux:9"}
|
|
7276
|
+
${v}`)}let f=h.outputs[0],S=Buffer.from(await f.arrayBuffer()),b="index",A=_i([{name:`${b}.mjs`,data:S}]);return{zip:A,bundle:S,sha256:So(A),handlerFile:b,handlers:{http:s.handlers?.http??`${b}.http`,queue:s.handlers?.queue??`${b}.queue`,cli:s.handlers?.cli??`${b}.cli`},bundleBytes:S.length}}finally{ri(l,{recursive:!0,force:!0})}}var YA=["18","20","22"];function mi(n){if(!n)return"22";let i=String(n).match(/(\d+)/);return i?i[1]:"22"}function Co(n){let i=n.kind??"node";if(i==="php")return{lambdaRuntime:"provided.al2023",kind:"php",version:n.phpVersion??"8.3",usesLayer:!0,layerKind:"php",layerEnvVar:"TSCLOUD_PHP_LAYER_ARN"};if(i==="bun")return{lambdaRuntime:"provided.al2023",kind:"bun",version:n.runtimeVersion??"latest",usesLayer:!0,layerKind:"bun",layerEnvVar:"TSCLOUD_BUN_LAYER_ARN"};let s=mi(n.runtimeVersion);if(n.runtime!=="provided.al2023"&&YA.includes(s))return{lambdaRuntime:n.runtime&&n.runtime.startsWith("nodejs")?n.runtime:`nodejs${s}.x`,kind:"node",version:s,usesLayer:!1};return{lambdaRuntime:"provided.al2023",kind:"node",version:s,usesLayer:!0,layerKind:"node",layerEnvVar:"TSCLOUD_NODE_LAYER_ARN"}}function Xt(n,i,s){if(n.queues===!1)return[];if(n.queues===void 0||n.queues===!0)return[{name:`${i}-${s}-default`}];return n.queues.map((o)=>{if(typeof o==="string")return{name:`${i}-${s}-${o}`};let[c,l]=Object.entries(o)[0];return{name:`${i}-${s}-${c}`,concurrency:l}})}function Gd(n,i,s){return Xt(n,i,s).map((o)=>o.name)}function qd(n){let{app:i,environment:s,handlers:o}=n,c=n.config.project.slug,l=Co(i).lambdaRuntime,u=i.architecture??"x86_64",h=n.config.project.region,f={http:`${c}-${s}-http`,queue:`${c}-${s}-queue`,cli:`${c}-${s}-cli`};if(i.gatewayVersion===1)throw Error("serverless app: `gatewayVersion: 1` (REST API) is not supported — ts-cloud uses API Gateway HTTP API (v2). Remove `gatewayVersion` or set it to 2.");let S=Xt(i,c,s),b=S.map((z)=>z.name),A=b.length>0,v=i.logRetention??14,w=i.packaging==="image";if(w&&i.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 E=(i.scheduler??"on")!=="off",P=(i.cache?.driver??"dynamodb")==="dynamodb",R=Boolean(i.assets),D=po(c,s),O=i.tmpStorage??512,I={},_={},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}-${s}-*`)},{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameter","ssm:GetParameters","ssm:GetParametersByPath"],Resource:[e.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${c}/${s}/*`),e.sub(`arn:aws:ssm:\${AWS::Region}:\${AWS::AccountId}:parameter/${c}/${s}/*`)]},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[e.sub(`arn:aws:s3:::${D}`),e.sub(`arn:aws:s3:::${D}/*`),...i.storage?.bucket?[e.sub(`arn:aws:s3:::${i.storage.bucket}`),e.sub(`arn:aws:s3:::${i.storage.bucket}/*`)]:[]]}]}}];if(A)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["sqs:SendMessage","sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes","sqs:GetQueueUrl"],Resource:e.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${c}-${s}-*`)});if(P)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}-${s}-cache*`)});let W=["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"];if(i.vpc?.subnets?.length)W.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");if(i.lambdaInsights)W.push("arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy");I.AppRole={Type:"AWS::IAM::Role",Properties:{RoleName:`${c}-${s}-app-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:W,Policies:B}};let J=(z)=>({TSCLOUD_LAMBDA_MODE:z,TSCLOUD_ENV:s,...i.octane?{TSCLOUD_OCTANE:"1"}:{},...i.scheduler==="sub-minute"?{TSCLOUD_SCHEDULER:"sub-minute"}:{},...P?{TSCLOUD_CACHE_TABLE:`${c}-${s}-cache`}:{},...A?{TSCLOUD_QUEUE:b[0]}:{},...i.env??{}}),K=Boolean(i.efs),Y=typeof i.efs==="object"?i.efs:{},Z=Y.mountPath??"/mnt/local",ne=K&&!Y.accessPointArn,de=Y.accessPointArn??(ne?e.getAtt("EfsAccessPoint","Arn"):void 0),oe=i.vpc?.subnets??[],le=oe.length>0,ie=i.cache?.driver==="elasticache"||i.database?.connection==="aurora-serverless"||Boolean(i.rdsProxy)||K;if(ie&&!le)throw Error("serverless app: elasticache / aurora-serverless / rdsProxy / efs require app.vpc.subnets (private subnets) to be set.");let Ee=le?{VpcConfig:{SubnetIds:oe,SecurityGroupIds:[...i.vpc?.securityGroups??[],...ie?[e.getAtt("DataSecurityGroup","GroupId")]:[]]}}:{},Fe=ne?oe.map((z,ae)=>`EfsMountTarget${ae}`):[],Et=K?{FileSystemConfigs:[{Arn:de,LocalMountPath:Z}]}:{};if(K)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess","elasticfilesystem:DescribeMountTargets"],Resource:"*"});function pe(z,ae,X,se,fe,nt,Ce,it=O){I[`${z}LogGroup`]={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:`/aws/lambda/${ae}`,RetentionInDays:v}};let Pt=[...n.runtimeLayers??[],...i.lambdaInsights?[i.lambdaInsights.layerArn]:[]],It=w?{PackageType:"Image",Code:{ImageUri:e.ref("ImageUri")},...i.kind==="php"?{}:{ImageConfig:{Command:[X]}}}:{Runtime:l,Handler:X,Code:{S3Bucket:e.ref("ArtifactBucket"),S3Key:e.ref("ArtifactKey")},...Pt.length?{Layers:[...new Set(Pt)]}:{}};I[z]={Type:"AWS::Lambda::Function",DependsOn:[`${z}LogGroup`,...Fe],Properties:{FunctionName:ae,Architectures:[u],MemorySize:fe,Timeout:nt,Role:e.getAtt("AppRole","Arn"),Environment:{Variables:J(se)},EphemeralStorage:{Size:it},...It,...Ce!==void 0?{ReservedConcurrentExecutions:Ce}:{},...Ee,...Et}}}if(pe("HttpFunction",f.http,o.http,"http",i.memory??1024,i.timeout??28,i.concurrency,O),pe("CliFunction",f.cli,o.cli,"cli",i.cliMemory??1024,i.cliTimeout??900,void 0,i.cliTmpStorage??O),A)pe("QueueFunction",f.queue,o.queue,"queue",i.queueMemory??1024,i.queueTimeout??120,void 0,i.queueTmpStorage??O);let ue=(i.provisionedConcurrency??0)>0?i.provisionedConcurrency:0,he=["HttpFunction","CliFunction",...A?["QueueFunction"]:[]];if(ue)for(let z of he)I[`${z}Version`]={Type:"AWS::Lambda::Version",DeletionPolicy:"Retain",Properties:{FunctionName:e.ref(z)}},I[`${z}Alias`]={Type:"AWS::Lambda::Alias",Properties:{FunctionName:e.ref(z),Name:"live",FunctionVersion:e.getAtt(`${z}Version`,"Version"),ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:ue}}};let Ie=(z)=>ue?e.ref(`${z}Alias`):e.getAtt(z,"Arn"),ye=(z)=>ue?e.ref(`${z}Alias`):e.ref(z);I.HttpApi={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:`${c}-${s}`,ProtocolType:"HTTP"}},I.HttpIntegration={Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:e.ref("HttpApi"),IntegrationType:"AWS_PROXY",IntegrationUri:Ie("HttpFunction"),PayloadFormatVersion:"2.0"}},I.HttpRoute={Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:e.ref("HttpApi"),RouteKey:"$default",Target:e.join("/",["integrations",e.ref("HttpIntegration")])}},I.HttpStage={Type:"AWS::ApiGatewayV2::Stage",Properties:{ApiId:e.ref("HttpApi"),StageName:"$default",AutoDeploy:!0}},I.HttpPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:ye("HttpFunction"),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:e.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${HttpApi}/*/*")}},_.HttpApiEndpoint={Description:"HTTP API endpoint",Value:e.getAtt("HttpApi","ApiEndpoint")},_.HttpApiId={Description:"HTTP API id",Value:e.ref("HttpApi")};let Ae=(Array.isArray(i.domain)?i.domain:i.domain?[i.domain]:[]).filter(Boolean);if(Ae.length){if(!i.certificateArn&&!i.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=i.certificateArn;if(!z)I.HttpCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:Ae[0],...Ae.length>1?{SubjectAlternativeNames:Ae.slice(1)}:{},ValidationMethod:"DNS",DomainValidationOptions:Ae.map((ae)=>({DomainName:ae,HostedZoneId:i.hostedZoneId}))}},z=e.ref("HttpCertificate");Ae.forEach((ae,X)=>{let se=`HttpDomain${X}`;if(I[se]={Type:"AWS::ApiGatewayV2::DomainName",Properties:{DomainName:ae,DomainNameConfigurations:[{CertificateArn:z,EndpointType:"REGIONAL"}]}},I[`HttpApiMapping${X}`]={Type:"AWS::ApiGatewayV2::ApiMapping",DependsOn:["HttpStage"],Properties:{ApiId:e.ref("HttpApi"),DomainName:e.ref(se),Stage:"$default"}},i.hostedZoneId)I[`HttpDomainRecord${X}`]={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i.hostedZoneId,Name:ae,Type:"A",AliasTarget:{DNSName:e.getAtt(se,"RegionalDomainName"),HostedZoneId:e.getAtt(se,"RegionalHostedZoneId")}}};_[`CustomDomain${X}`]={Description:`Custom domain ${ae}`,Value:ae},_[`CustomDomainTarget${X}`]={Description:`Point ${ae} (CNAME/alias) at this APIGW regional domain`,Value:e.getAtt(se,"RegionalDomainName")}})}if(A)I.AppQueueDlq={Type:"AWS::SQS::Queue",Properties:{QueueName:`${c}-${s}-dlq`,MessageRetentionPeriod:1209600}},S.forEach((z,ae)=>{let X=`AppQueue${ae}`,se=i.queueTimeout??120;I[X]={Type:"AWS::SQS::Queue",Properties:{QueueName:z.name,VisibilityTimeout:Math.min(43200,se*6),RedrivePolicy:{deadLetterTargetArn:e.getAtt("AppQueueDlq","Arn"),maxReceiveCount:i.queueTries??3}}};let fe=z.concurrency??i.queueConcurrency;I[`${X}Mapping`]={Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:e.getAtt(X,"Arn"),FunctionName:ye("QueueFunction"),BatchSize:1,FunctionResponseTypes:["ReportBatchItemFailures"],...fe?{ScalingConfig:{MaximumConcurrency:Math.max(2,fe)}}:{}}},_[`QueueUrl${ae}`]={Description:`Queue URL: ${z.name}`,Value:e.ref(X)}});if(E)I.SchedulerRule={Type:"AWS::Events::Rule",Properties:{Name:`${c}-${s}-scheduler`,ScheduleExpression:"rate(1 minute)",State:"ENABLED",Targets:[{Id:"cli",Arn:Ie("CliFunction"),Input:JSON.stringify({command:"schedule:run"})}]}},I.SchedulerPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:ye("CliFunction"),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.getAtt("SchedulerRule","Arn")}};if(i.warm&&i.warm>0){let z={http:"HttpFunction",queue:"QueueFunction",cli:"CliFunction"},ae=(i.warmFunctions??["http"]).filter((X)=>X!=="queue"||A);for(let X of ae){let se=X.charAt(0).toUpperCase()+X.slice(1),fe=Math.ceil(i.warm/5),nt=0;for(let Ce=0;Ce<fe;Ce++){let it=Math.min(5,i.warm-nt);I[`Warmer${se}Rule${Ce}`]={Type:"AWS::Events::Rule",Properties:{Name:`${c}-${s}-warmer-${X}-${Ce}`,ScheduleExpression:"rate(5 minutes)",State:"ENABLED",Targets:Array.from({length:it},(Pt,It)=>({Id:`warm-${X}-${Ce}-${It}`,Arn:e.getAtt(z[X],"Arn"),Input:JSON.stringify({warmer:!0})}))}},nt+=it}I[`Warmer${se}Permission`]={Type:"AWS::Lambda::Permission",Properties:{FunctionName:e.ref(z[X]),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.sub(`arn:aws:events:\${AWS::Region}:\${AWS::AccountId}:rule/${c}-${s}-warmer-${X}-*`)}}}}if(P)I.CacheTable={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${c}-${s}-cache`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"key",AttributeType:"S"}],KeySchema:[{AttributeName:"key",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"expires_at",Enabled:!0}}},_.CacheTableName={Description:"DynamoDB cache table",Value:e.ref("CacheTable")};if(R){if(I.AssetsBucket={Type:"AWS::S3::Bucket",Properties:{BucketName:D,PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}}},I.AssetsOAC={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${c}-${s}-assets-oac`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},I.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:""}}],...i.assetDomain?{Aliases:[i.assetDomain],ViewerCertificate:{AcmCertificateArn:i.assetCertificateArn??e.ref("AssetsCertificate"),SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}}:{}}}},i.assetDomain){if(!i.assetCertificateArn){if(!i.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.`);I.AssetsCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:i.assetDomain,ValidationMethod:"DNS",DomainValidationOptions:[{DomainName:i.assetDomain,HostedZoneId:i.hostedZoneId}]}}}if(i.hostedZoneId)I.AssetsDomainRecord={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i.hostedZoneId,Name:i.assetDomain,Type:"A",AliasTarget:{DNSName:e.getAtt("AssetsDistribution","DomainName"),HostedZoneId:"Z2FDTNDATAQYW2"}}};_.AssetDomain={Description:"Custom asset CDN host",Value:i.assetDomain}}I.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:::${D}/*`),Condition:{StringEquals:{"AWS:SourceArn":e.sub("arn:aws:cloudfront::${AWS::AccountId}:distribution/${AssetsDistribution}")}}}]}}},_.AssetsBucketName={Description:"Assets bucket",Value:e.ref("AssetsBucket")},_.AssetsCdnDomain={Description:"Assets CloudFront domain",Value:e.getAtt("AssetsDistribution","DomainName")}}if(i.firewall?.enabled){let z=[],ae=0;if(i.firewall.rateLimit)z.push({Name:"rate-limit",Priority:ae++,Action:{Block:{}},Statement:{RateBasedStatement:{Limit:i.firewall.rateLimit,AggregateKeyType:"IP"}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${s}-rate`}});let X={sqlInjection:"AWSManagedRulesSQLiRuleSet",xss:"AWSManagedRulesCommonRuleSet",common:"AWSManagedRulesCommonRuleSet",botControl:"AWSManagedRulesBotControlRuleSet",ipReputation:"AWSManagedRulesAmazonIpReputationList"};for(let se of i.firewall.rules??[]){let fe=X[se];if(!fe)continue;z.push({Name:`managed-${se}`,Priority:ae++,OverrideAction:{None:{}},Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:fe}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${s}-${se}`}})}I.WebAcl={Type:"AWS::WAFv2::WebACL",Properties:{Name:`${c}-${s}-waf`,Scope:"REGIONAL",DefaultAction:{Allow:{}},Rules:z,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${s}-waf`}}},_.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(!i.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.");I.DataSecurityGroup={Type:"AWS::EC2::SecurityGroup",Properties:{VpcId:i.vpc.id,GroupDescription:`${c}-${s} serverless data access`,SecurityGroupIngress:[{IpProtocol:"-1",CidrIp:"10.0.0.0/8"}]}}}if(ne)I.EfsFileSystem={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:!0,FileSystemTags:[{Key:"Name",Value:`${c}-${s}-efs`}]}},oe.forEach((z,ae)=>{I[`EfsMountTarget${ae}`]={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:e.ref("EfsFileSystem"),SubnetId:z,SecurityGroups:[e.getAtt("DataSecurityGroup","GroupId")]}}}),I.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"}}}},_.EfsFileSystemId={Description:"EFS file system id",Value:e.ref("EfsFileSystem")};if(i.cache?.driver==="elasticache")I.CacheSubnetGroup={Type:"AWS::ElastiCache::SubnetGroup",Properties:{Description:`${c}-${s} cache subnets`,SubnetIds:oe}},I.CacheCluster={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:`${c}-${s}-cache`,ReplicationGroupDescription:`${c}-${s} redis`,Engine:"redis",CacheNodeType:"cache.t4g.micro",NumCacheClusters:1,AutomaticFailoverEnabled:!1,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),SecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")],TransitEncryptionEnabled:!1}},_.CacheEndpoint={Description:"Redis primary endpoint",Value:e.getAtt("CacheCluster","PrimaryEndPoint.Address")};if(i.database?.connection==="aurora-serverless")I.DbSubnetGroup={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupDescription:`${c}-${s} db subnets`,SubnetIds:oe}},I.DbSecret={Type:"AWS::SecretsManager::Secret",Properties:{Name:`${c}/${s}/db`,GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"app"}),GenerateStringKey:"password",PasswordLength:32,ExcludePunctuation:!0}}},I.DbCluster={Type:"AWS::RDS::DBCluster",Properties:{Engine:"aurora-mysql",EngineMode:"provisioned",DBClusterIdentifier:`${c}-${s}-db`,DatabaseName:"app",MasterUsername:e.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:username}}"),MasterUserPassword:e.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:password}}"),ServerlessV2ScalingConfiguration:{MinCapacity:i.database?.minCapacity??0.5,MaxCapacity:i.database?.maxCapacity??4},DBSubnetGroupName:e.ref("DbSubnetGroup"),VpcSecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")]}},I.DbInstance={Type:"AWS::RDS::DBInstance",Properties:{Engine:"aurora-mysql",DBInstanceClass:"db.serverless",DBClusterIdentifier:e.ref("DbCluster")}},_.DbEndpoint={Description:"Aurora cluster endpoint",Value:e.getAtt("DbCluster","Endpoint.Address")};if(i.rdsProxy&&i.database?.connection==="aurora-serverless")I.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")}]}}]}},I.DbProxy={Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:typeof i.rdsProxy==="object"&&i.rdsProxy.name?i.rdsProxy.name:`${c}-${s}-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}},I.DbProxyTargetGroup={Type:"AWS::RDS::DBProxyTargetGroup",DependsOn:["DbInstance"],Properties:{DBProxyName:e.ref("DbProxy"),TargetGroupName:"default",DBClusterIdentifiers:[e.ref("DbCluster")]}},_.DbProxyEndpoint={Description:"RDS Proxy endpoint",Value:e.getAtt("DbProxy","Endpoint")};if(_.HttpFunctionName={Description:"HTTP function name",Value:e.ref("HttpFunction")},_.CliFunctionName={Description:"CLI function name",Value:e.ref("CliFunction")},A)_.QueueFunctionName={Description:"Queue function name",Value:e.ref("QueueFunction")};let Me={AWSTemplateFormatVersion:"2010-09-09",Description:`Serverless application for ${n.config.project.name} (${c}-${s})`,Parameters:w?{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:I,Outputs:_},Ue={};for(let z of Object.values(I))Ue[z.Type]=(Ue[z.Type]??0)+1;return{template:Me,functionNames:f,queueNames:b,resourceSummary:Ue}}var ZA=["cli","fpm","curl","mbstring","xml","pdo","mysqlnd","gd","bcmath","intl","opcache","sodium","process","pecl-redis6","pecl-apcu","pgsql"];function ey(n){let i=`php${n.replace(".","")}`;return ZA.map((s)=>`${i}-php-${s}`)}function xm(n,i){let s=`php${n.replace(".","")}`,o=ey(n).join(" \\\n "),c=`/opt/remi/${s}/root`,l=`/etc/opt/remi/${s}`;return`${i?`FROM almalinux:9 AS ${i}`:"FROM almalinux:9"}
|
|
7277
7277
|
|
|
7278
7278
|
# Build PHP on AlmaLinux 9 (where Remi's version-isolated SCL packages install
|
|
7279
7279
|
# cleanly — Remi's release RPM rejects Amazon Linux 2023). AlmaLinux 9 shares
|
|
@@ -7314,8 +7314,8 @@ RUN printf 'extension_dir=/opt/php/lib/php/modules\\n' > /opt/php/etc/php.ini &&
|
|
|
7314
7314
|
# orchestrator after the image is produced. Export /opt as the layer payload.
|
|
7315
7315
|
CMD ["true"]
|
|
7316
7316
|
`}function ty(n={}){let i=n.phpVersion??"8.3";return`# ts-cloud PHP ${i} runtime layer (generated) — AWS Lambda provided.al2023.
|
|
7317
|
-
${
|
|
7318
|
-
${
|
|
7317
|
+
${xm(i)}`}function Vd(n){if(n.kind==="php"){let i=n.phpVersion??"8.3";return`# ts-cloud serverless PHP app image (generated, multi-stage).
|
|
7318
|
+
${xm(i,"phpbuild")}
|
|
7319
7319
|
|
|
7320
7320
|
FROM public.ecr.aws/lambda/provided:al2023
|
|
7321
7321
|
# Bake the relocated PHP runtime from the build stage.
|
|
@@ -7334,7 +7334,7 @@ COPY app/ \${LAMBDA_TASK_ROOT}/
|
|
|
7334
7334
|
|
|
7335
7335
|
# Per-function CMD (e.g. index.http) is supplied via ImageConfig.Command.
|
|
7336
7336
|
CMD [ "index.http" ]
|
|
7337
|
-
`}function ja(){return pi(gi(import.meta.url))}function Lm(){return wt(we(ja(),"runtime.mjs"),"utf-8")}function Ka(n){return wt(we(ja(),`${n}-bootstrap`),"utf-8")}function HE(n){let i=n.architecture??"x86_64",s=i==="arm64"?"arm64":"x64",o=n.version.replace(/^v/,""),c=n.onStep??(()=>{}),l=Fa(we(Va(),"tscloud-node-layer-"));try{let u=o.includes(".")?o:hi(o),h=`node-v${u}-linux-${s}`,f=`https://nodejs.org/dist/v${u}/${h}.tar.xz`;c(`downloading Node ${u} (${i})`);let S=we(l,"node.tar.xz");qa(f,S),c("extracting node binary"),Tt("tar",["-xf",S,"-C",l,`${h}/bin/node`],{stdio:"inherit"});let b=wt(we(l,h,"bin","node"));c("packaging layer");let A=[{name:"bootstrap",data:Ka("node"),mode:493},{name:"runtime.mjs",data:Lm(),mode:420},{name:"bin/node",data:b,mode:493}];return{zip:_i(A),architecture:i,version:u,fileCount:A.length}}finally{Ua(l,{recursive:!0,force:!0})}}function GE(n){let i=n.architecture??"x86_64",s=i==="arm64"?"bun-linux-aarch64":"bun-linux-x64",o=n.version==="latest"?"":n.version.replace(/^v/,""),c=n.onStep??(()=>{}),l=Fa(we(Va(),"tscloud-bun-layer-"));try{let u=o?`https://github.com/oven-sh/bun/releases/download/bun-v${o}/${s}.zip`:`https://github.com/oven-sh/bun/releases/latest/download/${s}.zip`;c(`downloading Bun ${o||"latest"} (${i})`);let h=we(l,"bun.zip");qa(u,h),c("extracting bun binary"),Tt("unzip",["-o","-q",h,"-d",l],{stdio:"inherit"});let f=wt(we(l,s,"bun"));c("packaging layer");let S=[{name:"bootstrap",data:Ka("bun"),mode:493},{name:"runtime.mjs",data:Lm(),mode:420},{name:"bin/bun",data:f,mode:493}];return{zip:_i(S),architecture:i,version:o||"latest",fileCount:S.length}}finally{Ua(l,{recursive:!0,force:!0})}}function qa(n,i){Tt("curl",["-fsSL","-o",i,n],{stdio:["ignore","ignore","inherit"]})}function hi(n){let i=Tt("curl",["-fsSL","https://nodejs.org/dist/index.json"],{encoding:"utf-8"}),s=JSON.parse(i).find((o)=>o.version.startsWith(`v${n}.`));if(!s)throw Error(`No Node release found for major version ${n}`);return s.version.replace(/^v/,"")}var Eo="x-ts-cloud-invoke-depth",bo="x-ts-cloud-invoke-chain",vo="x-ts-cloud-trace-id";function jd(n){return fi("sha256").update(n).digest("hex").slice(0,8)}var
|
|
7337
|
+
`}function ja(){return pi(gi(import.meta.url))}function Lm(){return wt(we(ja(),"runtime.mjs"),"utf-8")}function Ka(n){return wt(we(ja(),`${n}-bootstrap`),"utf-8")}function HE(n){let i=n.architecture??"x86_64",s=i==="arm64"?"arm64":"x64",o=n.version.replace(/^v/,""),c=n.onStep??(()=>{}),l=Fa(we(Va(),"tscloud-node-layer-"));try{let u=o.includes(".")?o:hi(o),h=`node-v${u}-linux-${s}`,f=`https://nodejs.org/dist/v${u}/${h}.tar.xz`;c(`downloading Node ${u} (${i})`);let S=we(l,"node.tar.xz");qa(f,S),c("extracting node binary"),Tt("tar",["-xf",S,"-C",l,`${h}/bin/node`],{stdio:"inherit"});let b=wt(we(l,h,"bin","node"));c("packaging layer");let A=[{name:"bootstrap",data:Ka("node"),mode:493},{name:"runtime.mjs",data:Lm(),mode:420},{name:"bin/node",data:b,mode:493}];return{zip:_i(A),architecture:i,version:u,fileCount:A.length}}finally{Ua(l,{recursive:!0,force:!0})}}function GE(n){let i=n.architecture??"x86_64",s=i==="arm64"?"bun-linux-aarch64":"bun-linux-x64",o=n.version==="latest"?"":n.version.replace(/^v/,""),c=n.onStep??(()=>{}),l=Fa(we(Va(),"tscloud-bun-layer-"));try{let u=o?`https://github.com/oven-sh/bun/releases/download/bun-v${o}/${s}.zip`:`https://github.com/oven-sh/bun/releases/latest/download/${s}.zip`;c(`downloading Bun ${o||"latest"} (${i})`);let h=we(l,"bun.zip");qa(u,h),c("extracting bun binary"),Tt("unzip",["-o","-q",h,"-d",l],{stdio:"inherit"});let f=wt(we(l,s,"bun"));c("packaging layer");let S=[{name:"bootstrap",data:Ka("bun"),mode:493},{name:"runtime.mjs",data:Lm(),mode:420},{name:"bin/bun",data:f,mode:493}];return{zip:_i(S),architecture:i,version:o||"latest",fileCount:S.length}}finally{Ua(l,{recursive:!0,force:!0})}}function qa(n,i){Tt("curl",["-fsSL","-o",i,n],{stdio:["ignore","ignore","inherit"]})}function hi(n){let i=Tt("curl",["-fsSL","https://nodejs.org/dist/index.json"],{encoding:"utf-8"}),s=JSON.parse(i).find((o)=>o.version.startsWith(`v${n}.`));if(!s)throw Error(`No Node release found for major version ${n}`);return s.version.replace(/^v/,"")}var Eo="x-ts-cloud-invoke-depth",bo="x-ts-cloud-invoke-chain",vo="x-ts-cloud-trace-id";function jd(n){return fi("sha256").update(n).digest("hex").slice(0,8)}var Oi={maxDepth:10,maxRepeats:3,maxInvocationsPerTrace:100,traceWindowMs:60000,breakerThreshold:5,breakerCooldownMs:60000};function Mt(n,i){if(typeof n.get==="function")return n.get(i)??void 0;let s=n;return s[i]??s[i.toLowerCase()]??s[i.toUpperCase()]}function zd(n,i=64){if(!n)return[];return n.split(".").map((s)=>s.trim()).filter((s)=>/^[0-9a-f]{8}$/.test(s)).slice(-i)}function Kd(n,i=Oi){let s=jd(n.functionId),o=zd(Mt(n.headers,bo)),c=n.traceId??Mt(n.headers,vo)??crypto.randomUUID(),l=[...o,s],u=o.filter((A)=>A===s).length,h=o[o.length-1]===s,f=Number.parseInt(Mt(n.headers,Eo)??"",10),S=Math.max(l.length,Number.isFinite(f)?f+1:0),b="ok";if(S>i.maxDepth)b="depth_exceeded";else if(u>=i.maxRepeats)b="cycle_detected";else if(h&&i.maxRepeats<=1)b="self_invocation";return{reason:b,depth:S,chain:l,traceId:c,selfInvocation:h,repeats:u,propagate:{[Eo]:String(S),[bo]:l.join("."),[vo]:c}}}var Ha={ok:"",depth_exceeded:"Invocation chain is deeper than the configured limit; the call was refused to stop a runaway loop.",cycle_detected:"This function already appears in the invocation chain; the call was refused as a recursion loop.",self_invocation:"This function invoked itself directly; the call was refused.",trace_budget_exceeded:"This request has already made more invocations than its budget allows.",breaker_open:"Recursion protection is open for this function after repeated loop detections."};class To{limits;clock;traces=new Map;breakers=new Map;constructor(n=Oi,i=()=>Date.now()){this.limits=n,this.clock=i}check(n){let i=this.clock();this.expireTraces(i);let s=Kd(n,this.limits),o=this.breakers.get(n.functionId);if(o?.openUntil!=null&&o.openUntil>i)return this.deny(n.functionId,s,"breaker_open",i,!1);if(s.reason!=="ok")return this.deny(n.functionId,s,s.reason,i,!0);let c=this.traces.get(s.traceId)??{count:0,firstAt:i};if(c.count>=this.limits.maxInvocationsPerTrace)return this.traces.set(s.traceId,c),this.deny(n.functionId,s,"trace_budget_exceeded",i,!0);if(this.traces.set(s.traceId,{count:c.count+1,firstAt:c.firstAt}),o)this.breakers.set(n.functionId,{consecutiveBlocks:0});return{...s,allowed:!0,reason:"ok",propagate:s.propagate}}deny(n,i,s,o,c){if(c){let l=this.breakers.get(n)??{consecutiveBlocks:0},u=l.consecutiveBlocks+1;this.breakers.set(n,{consecutiveBlocks:u,openUntil:u>=this.limits.breakerThreshold?o+this.limits.breakerCooldownMs:l.openUntil})}return{...i,allowed:!1,reason:s,message:Ha[s]}}breakerOpen(n){let i=this.breakers.get(n);return i?.openUntil!=null&&i.openUntil>this.clock()}reset(n){if(n){this.breakers.delete(n);return}this.breakers.clear(),this.traces.clear()}expireTraces(n){if(this.traces.size===0)return;for(let[i,s]of this.traces)if(n-s.firstAt>this.limits.traceWindowMs)this.traces.delete(i)}get trackedTraces(){return this.traces.size}}function Wd(n){return{...n.propagate}}function Jd(n){return{status:508,headers:{"content-type":"application/json","x-ts-cloud-recursion-blocked":n.reason},body:{error:"recursion_blocked",reason:n.reason,message:n.message??Ha[n.reason],depth:n.depth,traceId:n.traceId}}}var $m=new yi;function ba(n){let i=globalThis.process?.env?.[n];if(i==null||i==="")return;return i!=="0"&&i.toLowerCase()!=="false"}function Si(){let n=globalThis.process?.env??{};return n.TS_CLOUD_FUNCTION_ID||n.AWS_LAMBDA_FUNCTION_NAME||n.FUNCTION_NAME||"function"}function ry(n){let i=n===!1?{enabled:!1}:n??{},s=ba("TS_CLOUD_RECURSION_PROTECTION"),o=ba("TS_CLOUD_RECURSION_DETECTION_ONLY");return{enabled:s??i.enabled??!0,detectionOnly:o??i.detectionOnly??!1,limits:{...Oi,...i.limits},functionId:i.functionId??Si()}}var $e,be;function ny(){let n=globalThis.fetch;if(!n||$e===n)return()=>{};be=n;let i=async(s,o)=>{let c=$m.getStore();if(!c)return be(s,o);let l=new Headers(o?.headers??(s instanceof Request?s.headers:void 0));for(let[u,h]of Object.entries(Wd(c)))l.set(u,h);if(s instanceof Request)return be(new Request(s,{headers:l}),o);return be(s,{...o,headers:l})};return Object.assign(i,n),globalThis.fetch=i,$e=i,()=>{if(globalThis.fetch===$e&&be)globalThis.fetch=be;$e=void 0}}var dt,_t;function iy(n){if(!dt||JSON.stringify(_t)!==JSON.stringify(n))dt=new To(n),_t=n;return dt}function qE(){if(dt=void 0,_t=void 0,$e&&be&&globalThis.fetch===$e)globalThis.fetch=be;$e=void 0,be=void 0}function sy(n,i){let s=ry(i);if(!s.enabled)return;let o=iy(s.limits),c={functionId:s.functionId,headers:n},l=o.check(c);return{verdict:l,blocked:!l.allowed&&!s.detectionOnly,observed:!l.allowed&&s.detectionOnly}}function oy(n,i){return ny(),$m.run(n,i)}function VE(n){let i=n,s=i?.default??i;if(typeof s==="function")return{fetch:s};return{fetch:s?.fetch??i?.fetch,queue:s?.queue??i?.queue,cli:s?.cli??i?.cli}}var bi=/^(?:text\/|application\/(?:json|xml|javascript|graphql|x-www-form-urlencoded|.*\+json|.*\+xml)|image\/svg)/i;function Ai(n){if(!n)return!0;return bi.test(n)}function Ci(n){if(n?.maintenance)return n.maintenance;let i=globalThis.process?.env??{};return{enabled:i.MAINTENANCE_MODE==="1"||i.MAINTENANCE_MODE==="true",bypassSecret:i.MAINTENANCE_BYPASS_SECRET}}function ay(n){let i=n.requestContext?.domainName??"localhost",s=n.rawQueryString?`?${n.rawQueryString}`:"",o=`https://${i}${n.rawPath||"/"}${s}`,c=new Headers;for(let[h,f]of Object.entries(n.headers??{}))if(f!==void 0)c.set(h,f);if(n.cookies?.length)c.set("cookie",n.cookies.join("; "));let l=n.requestContext.http.method,u;if(n.body!==void 0&&l!=="GET"&&l!=="HEAD")u=n.isBase64Encoded?new Uint8Array(Buffer.from(n.body,"base64")):new TextEncoder().encode(n.body);return new Request(o,{method:l,headers:c,body:u})}async function Mm(n){let i={},s=[],o=typeof n.headers.getSetCookie==="function"?n.headers.getSetCookie():[];for(let u of o)s.push(u);n.headers.forEach((u,h)=>{if(h.toLowerCase()==="set-cookie")return;i[h]=u});let c=Buffer.from(await n.arrayBuffer()),l=Ai(n.headers.get("content-type"));return{statusCode:n.status,headers:i,...s.length?{cookies:s}:{},body:l?c.toString("utf-8"):c.toString("base64"),isBase64Encoded:!l}}function cy(n,i){return async(s)=>{if(s.warmer)return{statusCode:200,headers:{"content-type":"text/plain"},body:"warm",isBase64Encoded:!1};if(!n)return{statusCode:501,headers:{"content-type":"text/plain"},body:"No HTTP handler configured",isBase64Encoded:!1};let o=Ci(i);if(o.enabled){let u=s.headers?.["x-maintenance-bypass"]??s.cookies?.find((h)=>h.startsWith("tscloud_bypass="))?.split("=")[1];if(!o.bypassSecret||u!==o.bypassSecret)return{statusCode:503,headers:{"content-type":"text/plain","retry-after":"120"},body:"Service temporarily unavailable (maintenance mode)",isBase64Encoded:!1}}let c=sy(s.headers??{},i?.recursionProtection);if(c?.blocked){let u=Jd(c.verdict);return{statusCode:u.status,headers:{...u.headers,"retry-after":"60"},body:JSON.stringify(u.body),isBase64Encoded:!1}}let l=ay(s);if(!c){let u=await n(l);return Mm(u)}if(c.observed)console.warn(`[ts-cloud] recursion detected (${c.verdict.reason}) at depth ${c.verdict.depth}; detection-only mode let it run`);return oy(c.verdict,async()=>Mm(await n(l)))}}function vi(n){try{return JSON.parse(n)}catch{return n}}function dy(n){return async(i)=>{let s=[];if(i.warmer)return{batchItemFailures:s};if(!n)return{batchItemFailures:s};for(let o of i.Records??[])try{await n(vi(o.body),o)}catch{s.push({itemIdentifier:o.messageId})}return{batchItemFailures:s}}}function ly(n){return async(i)=>{if(i.warmer)return{statusCode:0,output:"warm"};if(!n)return{statusCode:501,output:"No CLI handler configured"};return n(i)}}function jE(n,i){return{http:cy(n.fetch,i),queue:dy(n.queue),cli:ly(n.cli)}}function uy(n={}){let i=n.socketPath??"/tmp/.tscloud-fpm.sock",s=n.maxChildren??1;return`; ts-cloud php-fpm configuration (generated) — AWS Lambda custom runtime.
|
|
7338
7338
|
[global]
|
|
7339
7339
|
daemonize = no
|
|
7340
7340
|
error_log = ${n.errorLog??"/tmp/storage/logs/php-fpm.log"}
|
|
@@ -7351,5 +7351,5 @@ decorate_workers_output = no
|
|
|
7351
7351
|
php_admin_value[error_log] = /dev/stderr
|
|
7352
7352
|
php_admin_flag[log_errors] = on
|
|
7353
7353
|
clear_env = no
|
|
7354
|
-
`}function Ii(){return za(wi(Ei(import.meta.url)),"runtime-assets")}function Oi(){let n=Ii(),i=(s)=>Ti(za(n,s),"utf-8");return[{path:"bootstrap",contents:i("bootstrap"),mode:493},{path:"tscloud/runtime.php",contents:i("runtime.php"),mode:420},{path:"tscloud/octane-runtime.php",contents:i("octane-runtime.php"),mode:420},{path:"tscloud/cli-runtime.php",contents:i("cli-runtime.php"),mode:420},{path:"tscloud/fastcgi-client.php",contents:i("fastcgi-client.php"),mode:420},{path:"tscloud/php-fpm.conf",contents:uy(),mode:420}]}function Xd(n={}){let i=n.cacheDriver??"dynamodb";return{APP_ENV:"production",LOG_CHANNEL:"stderr",CACHE_STORE:i,CACHE_DRIVER:i,SESSION_DRIVER:i,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 py=["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*Ja(n){for(let i of Li(n)){let s=xe(n,i);if(Qa(s).isDirectory())yield*Ja(s);else yield s}}function zE(n={}){let i=n.architecture??"x86_64",s=n.platform??(i==="arm64"?"linux/arm64":"linux/amd64"),o=n.onStep??(()=>{}),c=$i(xe(Fi(),"tscloud-php-layer-")),l="tscloud-php-layer:build";try{Gi(xe(c,"Dockerfile"),ty(n)),o("Building PHP runtime image (docker)"),ut("docker",["build","--platform",s,"-t","tscloud-php-layer:build",c],{stdio:"inherit"}),o("Extracting /opt/php from image");let u=ut("docker",["create","--platform",s,"tscloud-php-layer:build"],{encoding:"utf-8"}).trim(),h=xe(c,"opt");Di(h,{recursive:!0});try{ut("docker",["cp",`${u}:/opt/php`,xe(h,"php")],{stdio:"inherit"})}finally{ut("docker",["rm",u],{stdio:"ignore"})}if(!Ri(xe(h,"php","bin","php")))throw Error("layer build produced no /opt/php/bin/php");let f=[];for(let A of Ja(h)){let v=Ui(h,A).replace(/\\/g,"/"),w=Qa(A).mode&73?493:420;f.push({name:v,data:Mi(A),mode:w})}o("Injecting runtime assets");let S=new Set(Oi().map((A)=>A.path)),b=f.filter((A)=>!S.has(A.name));for(let A of Oi())b.push({name:A.path,data:A.contents,mode:A.mode});return o("Packaging layer ZIP"),{zip:_i(b),architecture:i,fileCount:b.length}}finally{Wi(c,{recursive:!0,force:!0})}}var gy=[".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 zi(n,i){return i.some((s)=>n===s||n.startsWith(`${s}/`))}function*Xa(n,i,s){for(let o of Ki(n)){let c=Hi(n,o),l=Za(i,c).replace(/\\/g,"/");if(zi(l,s))continue;if(Ya(c).isDirectory())yield*Xa(c,i,s);else yield c}}function wo(n){if(n.skipBuild)return;let i=ua(n.projectRoot??process.cwd()),s=n.app.build??py;for(let o of s)n.onStep?.(`build: ${o}`),Vi(o,{stdio:"inherit",cwd:i})}function Ro(n,i=[]){let s=ua(n),o=[...gy,uo(),...i],c=[];for(let l of Xa(s,s,o)){let u=Za(s,l).replace(/\\/g,"/"),h=(Ya(l).mode&73)!==0;c.push({name:u,data:qi(l),mode:h?493:420})}return c}function Yd(n){let i=ua(n.projectRoot??process.cwd());wo(n),n.onStep?.("packaging application tree");let s=Ro(i,n.exclude);if(!s.length)throw Error(`No files to package under ${i}`);let o=_i(s),c=n.app.handlers?.http??"public/index.php";return{zip:o,sha256:ji("sha256").update(o).digest("hex"),handlers:{http:c,queue:n.app.handlers?.queue??c,cli:n.app.handlers?.cli??c},fileCount:s.length}}class Fm{optimizations=new Map;imageConfigs=new Map;ssgConfigs=new Map;prerenderConfigs=new Map;counter=0;createAssetOptimization(n){let i=`asset-opt-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.optimizations.set(i,s),s}createImageOptimization(n){let i=`image-opt-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.imageConfigs.set(i,s),s}createSSGConfig(n){let i=`ssg-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.ssgConfigs.set(i,s),s}createPrerenderConfig(n){let i=`prerender-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.prerenderConfigs.set(i,s),s}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 KE=new Fm;class Um{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(n,i){let s=`lifecycle-${Date.now()}-${this.counter++}`,o={id:s,transitions:n,expiration:i};return this.policies.set(s,o),o}enableVersioning(n=!1){let i=`versioning-${Date.now()}-${this.counter++}`,s={id:i,enabled:!0,mfaDelete:n};return this.versioningConfigs.set(i,s),s}createReplicationRule(n,i,s){let o=`replication-${Date.now()}-${this.counter++}`,c={id:o,sourceRegion:n,destRegion:i,destBucket:s};return this.replicationRules.set(o,c),c}createIntelligentTiering(n,i){let s=`tiering-${Date.now()}-${this.counter++}`,o={id:s,archiveDays:n,deepArchiveDays:i};return this.tieringConfigs.set(s,o),o}enableObjectLock(n){let i=`object-lock-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,mode:n.mode||"COMPLIANCE",retentionDays:n.retentionDays,retentionYears:n.retentionYears,legalHoldEnabled:n.legalHoldEnabled||!1};return this.objectLocks.set(i,s),s}enableTransferAcceleration(n){let i=`transfer-accel-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n,enabled:!0,endpoint:`${n}.s3-accelerate.amazonaws.com`};return this.transferAcceleration.set(i,s),s}createAccessPoint(n){let i=`access-point-${Date.now()}-${this.counter++}`,s={id:i,name:n.name,bucketName:n.bucketName,vpcId:n.vpcId,publicAccessBlock:n.publicAccessBlock!==!1,policy:n.policy};return this.accessPoints.set(i,s),s}createGlacierArchive(n){let i=`glacier-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,archiveType:n.archiveType,transitionDays:n.transitionDays,restoreConfig:n.restoreTier?{tier:n.restoreTier,days:n.restoreDays||7}:void 0};return this.glacierConfigs.set(i,s),s}createInventory(n){let i=`inventory-${Date.now()}-${this.counter++}`,s={id:i,sourceBucket:n.sourceBucket,destinationBucket:n.destinationBucket,schedule:n.schedule||"Daily",format:n.format||"CSV",includedFields:n.includedFields||["Size","LastModifiedDate","StorageClass","ETag"],prefix:n.prefix};return this.inventories.set(i,s),s}createBatchOperation(n){let i=`batch-op-${Date.now()}-${this.counter++}`,s={id:i,operation:n.operation,manifestBucket:n.manifestBucket,manifestKey:n.manifestKey,priority:n.priority||10,status:"pending"};return this.batchOps.set(i,s),s}executeBatchOperation(n){let i=this.batchOps.get(n);if(!i)throw Error(`Batch operation not found: ${n}`);return i.status="in_progress",i.totalObjects=1000,i.processedObjects=0,i}getBatchOperationStatus(n){return this.batchOps.get(n)}createLambdaNotification(n){let i=`event-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,events:n.events,destination:{type:"Lambda",arn:n.lambdaArn},filter:n.prefix||n.suffix?{prefix:n.prefix,suffix:n.suffix}:void 0};return this.eventNotifications.set(i,s),s}createSQSNotification(n){let i=`event-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,events:n.events,destination:{type:"SQS",arn:n.queueArn},filter:n.prefix||n.suffix?{prefix:n.prefix,suffix:n.suffix}:void 0};return this.eventNotifications.set(i,s),s}createSNSNotification(n){let i=`event-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,events:n.events,destination:{type:"SNS",arn:n.topicArn},filter:n.prefix||n.suffix?{prefix:n.prefix,suffix:n.suffix}:void 0};return this.eventNotifications.set(i,s),s}generateObjectLockCF(n){let i={ObjectLockEnabled:"Enabled",ObjectLockConfiguration:{ObjectLockEnabled:"Enabled",Rule:{DefaultRetention:{Mode:n.mode}}}};if(n.retentionDays)i.ObjectLockConfiguration.Rule.DefaultRetention.Days=n.retentionDays;if(n.retentionYears)i.ObjectLockConfiguration.Rule.DefaultRetention.Years=n.retentionYears;return i}generateTransferAccelerationCF(n){return{AccelerateConfiguration:{AccelerationStatus:n.enabled?"Enabled":"Suspended"}}}generateAccessPointCF(n){return{Type:"AWS::S3::AccessPoint",Properties:{Name:n.name,Bucket:n.bucketName,...n.vpcId&&{VpcConfiguration:{VpcId:n.vpcId}},PublicAccessBlockConfiguration:n.publicAccessBlock?{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}:void 0,...n.policy&&{Policy:n.policy}}}}generateInventoryCF(n){return{Type:"AWS::S3::Bucket",Properties:{InventoryConfigurations:[{Id:n.id,Destination:{BucketArn:`arn:aws:s3:::${n.destinationBucket}`,Format:n.format},Enabled:!0,IncludedObjectVersions:"Current",OptionalFields:n.includedFields,ScheduleFrequency:n.schedule,...n.prefix&&{Prefix:n.prefix}}]}}}generateEventNotificationCF(n){let i=n.destination.type==="Lambda"?"LambdaConfigurations":n.destination.type==="SQS"?"QueueConfigurations":"TopicConfigurations",s=n.destination.type==="Lambda"?"Function":n.destination.type==="SQS"?"Queue":"Topic",o={Event:n.events[0],[s]:n.destination.arn};if(n.filter)o.Filter={S3Key:{Rules:[...n.filter.prefix?[{Name:"prefix",Value:n.filter.prefix}]:[],...n.filter.suffix?[{Name:"suffix",Value:n.filter.suffix}]:[]]}};return{NotificationConfiguration:{[i]:[o]}}}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 WE=new Um;class Qm{checks=new Map;synthetics=new Map;uptimeTrackers=new Map;counter=0;createHealthCheck(n,i=30,s=10){let o=`health-${Date.now()}-${this.counter++}`,c={id:o,url:n,interval:i,timeout:s,status:"healthy"};return this.checks.set(o,c),c}createSyntheticMonitor(n,i,s,o){let c=`synthetic-${Date.now()}-${this.counter++}`,l={id:c,name:n,script:i,frequency:s,locations:o};return this.synthetics.set(c,l),l}trackUptime(n,i,s){let o=`uptime-${Date.now()}-${this.counter++}`,c=i/(i+s)*100,l={id:o,resource:n,uptime:i,downtime:s,availability:c};return this.uptimeTrackers.set(o,l),l}clear(){this.checks.clear(),this.synthetics.clear(),this.uptimeTrackers.clear()}}var JE=new Qm;class Hm{wafRules=new Map;shieldProtections=new Map;securityGroups=new Map;nacls=new Map;counter=0;createWAFRule(n,i,s,o){let c=`waf-${Date.now()}-${this.counter++}`,l={id:c,name:n,priority:i,action:s,conditions:o};return this.wafRules.set(c,l),l}enableShield(n,i="standard"){let s=`shield-${Date.now()}-${this.counter++}`,o={id:s,resourceArn:n,protectionType:i};return this.shieldProtections.set(s,o),o}createSecurityGroup(n,i,s){let o=`sg-${Date.now()}-${this.counter++}`,c={id:o,name:n,vpcId:i,rules:s};return this.securityGroups.set(o,c),c}createNACL(n,i){let s=`nacl-${Date.now()}-${this.counter++}`,o={id:s,vpcId:n,rules:i};return this.nacls.set(s,o),o}clear(){this.wafRules.clear(),this.shieldProtections.clear(),this.securityGroups.clear(),this.nacls.clear()}}var XE=new Hm;class Gm{strategies=new Map;allocations=new Map;groups=new Map;counter=0;createTaggingStrategy(n,i){let s=`tagging-${Date.now()}-${this.counter++}`,o={id:s,tags:n,resources:i};return this.strategies.set(s,o),o}createCostAllocation(n,i){let s=`cost-${Date.now()}-${this.counter++}`,o={id:s,tagKey:n,allocations:i};return this.allocations.set(s,o),o}createResourceGroup(n,i,s){let o=`group-${Date.now()}-${this.counter++}`,c={id:o,name:n,query:{resourceTypeFilters:i,tagFilters:s}};return this.groups.set(o,c),c}clear(){this.strategies.clear(),this.allocations.clear(),this.groups.clear()}}var YE=new Gm;
|
|
7355
|
-
export{lg,
|
|
7354
|
+
`}function Ii(){return za(wi(Ei(import.meta.url)),"runtime-assets")}function xi(){let n=Ii(),i=(s)=>Ti(za(n,s),"utf-8");return[{path:"bootstrap",contents:i("bootstrap"),mode:493},{path:"tscloud/runtime.php",contents:i("runtime.php"),mode:420},{path:"tscloud/octane-runtime.php",contents:i("octane-runtime.php"),mode:420},{path:"tscloud/cli-runtime.php",contents:i("cli-runtime.php"),mode:420},{path:"tscloud/fastcgi-client.php",contents:i("fastcgi-client.php"),mode:420},{path:"tscloud/php-fpm.conf",contents:uy(),mode:420}]}function Xd(n={}){let i=n.cacheDriver??"dynamodb";return{APP_ENV:"production",LOG_CHANNEL:"stderr",CACHE_STORE:i,CACHE_DRIVER:i,SESSION_DRIVER:i,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 py=["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*Ja(n){for(let i of Li(n)){let s=xe(n,i);if(Qa(s).isDirectory())yield*Ja(s);else yield s}}function zE(n={}){let i=n.architecture??"x86_64",s=n.platform??(i==="arm64"?"linux/arm64":"linux/amd64"),o=n.onStep??(()=>{}),c=$i(xe(Fi(),"tscloud-php-layer-")),l="tscloud-php-layer:build";try{Gi(xe(c,"Dockerfile"),ty(n)),o("Building PHP runtime image (docker)"),ut("docker",["build","--platform",s,"-t","tscloud-php-layer:build",c],{stdio:"inherit"}),o("Extracting /opt/php from image");let u=ut("docker",["create","--platform",s,"tscloud-php-layer:build"],{encoding:"utf-8"}).trim(),h=xe(c,"opt");Di(h,{recursive:!0});try{ut("docker",["cp",`${u}:/opt/php`,xe(h,"php")],{stdio:"inherit"})}finally{ut("docker",["rm",u],{stdio:"ignore"})}if(!Ri(xe(h,"php","bin","php")))throw Error("layer build produced no /opt/php/bin/php");let f=[];for(let A of Ja(h)){let v=Ui(h,A).replace(/\\/g,"/"),w=Qa(A).mode&73?493:420;f.push({name:v,data:Mi(A),mode:w})}o("Injecting runtime assets");let S=new Set(xi().map((A)=>A.path)),b=f.filter((A)=>!S.has(A.name));for(let A of xi())b.push({name:A.path,data:A.contents,mode:A.mode});return o("Packaging layer ZIP"),{zip:_i(b),architecture:i,fileCount:b.length}}finally{Wi(c,{recursive:!0,force:!0})}}var gy=[".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 zi(n,i){return i.some((s)=>n===s||n.startsWith(`${s}/`))}function*Xa(n,i,s){for(let o of Ki(n)){let c=Hi(n,o),l=Za(i,c).replace(/\\/g,"/");if(zi(l,s))continue;if(Ya(c).isDirectory())yield*Xa(c,i,s);else yield c}}function wo(n){if(n.skipBuild)return;let i=ua(n.projectRoot??process.cwd()),s=n.app.build??py;for(let o of s)n.onStep?.(`build: ${o}`),Vi(o,{stdio:"inherit",cwd:i})}function Ro(n,i=[]){let s=ua(n),o=[...gy,uo(),...i],c=[];for(let l of Xa(s,s,o)){let u=Za(s,l).replace(/\\/g,"/"),h=(Ya(l).mode&73)!==0;c.push({name:u,data:qi(l),mode:h?493:420})}return c}function Yd(n){let i=ua(n.projectRoot??process.cwd());wo(n),n.onStep?.("packaging application tree");let s=Ro(i,n.exclude);if(!s.length)throw Error(`No files to package under ${i}`);let o=_i(s),c=n.app.handlers?.http??"public/index.php";return{zip:o,sha256:ji("sha256").update(o).digest("hex"),handlers:{http:c,queue:n.app.handlers?.queue??c,cli:n.app.handlers?.cli??c},fileCount:s.length}}class Fm{optimizations=new Map;imageConfigs=new Map;ssgConfigs=new Map;prerenderConfigs=new Map;counter=0;createAssetOptimization(n){let i=`asset-opt-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.optimizations.set(i,s),s}createImageOptimization(n){let i=`image-opt-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.imageConfigs.set(i,s),s}createSSGConfig(n){let i=`ssg-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.ssgConfigs.set(i,s),s}createPrerenderConfig(n){let i=`prerender-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.prerenderConfigs.set(i,s),s}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 KE=new Fm;class Um{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(n,i){let s=`lifecycle-${Date.now()}-${this.counter++}`,o={id:s,transitions:n,expiration:i};return this.policies.set(s,o),o}enableVersioning(n=!1){let i=`versioning-${Date.now()}-${this.counter++}`,s={id:i,enabled:!0,mfaDelete:n};return this.versioningConfigs.set(i,s),s}createReplicationRule(n,i,s){let o=`replication-${Date.now()}-${this.counter++}`,c={id:o,sourceRegion:n,destRegion:i,destBucket:s};return this.replicationRules.set(o,c),c}createIntelligentTiering(n,i){let s=`tiering-${Date.now()}-${this.counter++}`,o={id:s,archiveDays:n,deepArchiveDays:i};return this.tieringConfigs.set(s,o),o}enableObjectLock(n){let i=`object-lock-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,mode:n.mode||"COMPLIANCE",retentionDays:n.retentionDays,retentionYears:n.retentionYears,legalHoldEnabled:n.legalHoldEnabled||!1};return this.objectLocks.set(i,s),s}enableTransferAcceleration(n){let i=`transfer-accel-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n,enabled:!0,endpoint:`${n}.s3-accelerate.amazonaws.com`};return this.transferAcceleration.set(i,s),s}createAccessPoint(n){let i=`access-point-${Date.now()}-${this.counter++}`,s={id:i,name:n.name,bucketName:n.bucketName,vpcId:n.vpcId,publicAccessBlock:n.publicAccessBlock!==!1,policy:n.policy};return this.accessPoints.set(i,s),s}createGlacierArchive(n){let i=`glacier-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,archiveType:n.archiveType,transitionDays:n.transitionDays,restoreConfig:n.restoreTier?{tier:n.restoreTier,days:n.restoreDays||7}:void 0};return this.glacierConfigs.set(i,s),s}createInventory(n){let i=`inventory-${Date.now()}-${this.counter++}`,s={id:i,sourceBucket:n.sourceBucket,destinationBucket:n.destinationBucket,schedule:n.schedule||"Daily",format:n.format||"CSV",includedFields:n.includedFields||["Size","LastModifiedDate","StorageClass","ETag"],prefix:n.prefix};return this.inventories.set(i,s),s}createBatchOperation(n){let i=`batch-op-${Date.now()}-${this.counter++}`,s={id:i,operation:n.operation,manifestBucket:n.manifestBucket,manifestKey:n.manifestKey,priority:n.priority||10,status:"pending"};return this.batchOps.set(i,s),s}executeBatchOperation(n){let i=this.batchOps.get(n);if(!i)throw Error(`Batch operation not found: ${n}`);return i.status="in_progress",i.totalObjects=1000,i.processedObjects=0,i}getBatchOperationStatus(n){return this.batchOps.get(n)}createLambdaNotification(n){let i=`event-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,events:n.events,destination:{type:"Lambda",arn:n.lambdaArn},filter:n.prefix||n.suffix?{prefix:n.prefix,suffix:n.suffix}:void 0};return this.eventNotifications.set(i,s),s}createSQSNotification(n){let i=`event-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,events:n.events,destination:{type:"SQS",arn:n.queueArn},filter:n.prefix||n.suffix?{prefix:n.prefix,suffix:n.suffix}:void 0};return this.eventNotifications.set(i,s),s}createSNSNotification(n){let i=`event-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,events:n.events,destination:{type:"SNS",arn:n.topicArn},filter:n.prefix||n.suffix?{prefix:n.prefix,suffix:n.suffix}:void 0};return this.eventNotifications.set(i,s),s}generateObjectLockCF(n){let i={ObjectLockEnabled:"Enabled",ObjectLockConfiguration:{ObjectLockEnabled:"Enabled",Rule:{DefaultRetention:{Mode:n.mode}}}};if(n.retentionDays)i.ObjectLockConfiguration.Rule.DefaultRetention.Days=n.retentionDays;if(n.retentionYears)i.ObjectLockConfiguration.Rule.DefaultRetention.Years=n.retentionYears;return i}generateTransferAccelerationCF(n){return{AccelerateConfiguration:{AccelerationStatus:n.enabled?"Enabled":"Suspended"}}}generateAccessPointCF(n){return{Type:"AWS::S3::AccessPoint",Properties:{Name:n.name,Bucket:n.bucketName,...n.vpcId&&{VpcConfiguration:{VpcId:n.vpcId}},PublicAccessBlockConfiguration:n.publicAccessBlock?{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}:void 0,...n.policy&&{Policy:n.policy}}}}generateInventoryCF(n){return{Type:"AWS::S3::Bucket",Properties:{InventoryConfigurations:[{Id:n.id,Destination:{BucketArn:`arn:aws:s3:::${n.destinationBucket}`,Format:n.format},Enabled:!0,IncludedObjectVersions:"Current",OptionalFields:n.includedFields,ScheduleFrequency:n.schedule,...n.prefix&&{Prefix:n.prefix}}]}}}generateEventNotificationCF(n){let i=n.destination.type==="Lambda"?"LambdaConfigurations":n.destination.type==="SQS"?"QueueConfigurations":"TopicConfigurations",s=n.destination.type==="Lambda"?"Function":n.destination.type==="SQS"?"Queue":"Topic",o={Event:n.events[0],[s]:n.destination.arn};if(n.filter)o.Filter={S3Key:{Rules:[...n.filter.prefix?[{Name:"prefix",Value:n.filter.prefix}]:[],...n.filter.suffix?[{Name:"suffix",Value:n.filter.suffix}]:[]]}};return{NotificationConfiguration:{[i]:[o]}}}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 WE=new Um;class Qm{checks=new Map;synthetics=new Map;uptimeTrackers=new Map;counter=0;createHealthCheck(n,i=30,s=10){let o=`health-${Date.now()}-${this.counter++}`,c={id:o,url:n,interval:i,timeout:s,status:"healthy"};return this.checks.set(o,c),c}createSyntheticMonitor(n,i,s,o){let c=`synthetic-${Date.now()}-${this.counter++}`,l={id:c,name:n,script:i,frequency:s,locations:o};return this.synthetics.set(c,l),l}trackUptime(n,i,s){let o=`uptime-${Date.now()}-${this.counter++}`,c=i/(i+s)*100,l={id:o,resource:n,uptime:i,downtime:s,availability:c};return this.uptimeTrackers.set(o,l),l}clear(){this.checks.clear(),this.synthetics.clear(),this.uptimeTrackers.clear()}}var JE=new Qm;class Hm{wafRules=new Map;shieldProtections=new Map;securityGroups=new Map;nacls=new Map;counter=0;createWAFRule(n,i,s,o){let c=`waf-${Date.now()}-${this.counter++}`,l={id:c,name:n,priority:i,action:s,conditions:o};return this.wafRules.set(c,l),l}enableShield(n,i="standard"){let s=`shield-${Date.now()}-${this.counter++}`,o={id:s,resourceArn:n,protectionType:i};return this.shieldProtections.set(s,o),o}createSecurityGroup(n,i,s){let o=`sg-${Date.now()}-${this.counter++}`,c={id:o,name:n,vpcId:i,rules:s};return this.securityGroups.set(o,c),c}createNACL(n,i){let s=`nacl-${Date.now()}-${this.counter++}`,o={id:s,vpcId:n,rules:i};return this.nacls.set(s,o),o}clear(){this.wafRules.clear(),this.shieldProtections.clear(),this.securityGroups.clear(),this.nacls.clear()}}var XE=new Hm;class Gm{strategies=new Map;allocations=new Map;groups=new Map;counter=0;createTaggingStrategy(n,i){let s=`tagging-${Date.now()}-${this.counter++}`,o={id:s,tags:n,resources:i};return this.strategies.set(s,o),o}createCostAllocation(n,i){let s=`cost-${Date.now()}-${this.counter++}`,o={id:s,tagKey:n,allocations:i};return this.allocations.set(s,o),o}createResourceGroup(n,i,s){let o=`group-${Date.now()}-${this.counter++}`,c={id:o,name:n,query:{resourceTypeFilters:i,tagFilters:s}};return this.groups.set(o,c),c}clear(){this.strategies.clear(),this.allocations.clear(),this.groups.clear()}}var YE=new Gm;
|
|
7355
|
+
export{lg,x,ug,sA,mI,oA,hI,fI,yI,II,SI,CI,EI,bI,vI,TI,pg,gg,bd,vd,uo,L,d,Td,mg,M,wd,p,aA,Pi,Rd,Dd,ge,Pd,wI,r,t,RI,DI,g,PI,NI,kI,BI,_I,qt,Nd,po,cA,OI,xI,Re,ze,kd,hg,fg,LI,Ag,yg,Ig,Bd,Sg,De,qr,Vt,_d,jt,me,dA,Od,go,Cg,Eg,bg,vg,xd,$I,F,C,a,y,Ke,m,lA,We,U,At,MI,uA,Q,Ld,Pe,zt,mo,ee,$d,te,pA,ho,H,G,N,Ni,T,Kt,yt,q,e,fo,FI,Tg,Md,UI,QI,HI,GI,Fd,qI,VI,jI,zI,KI,WI,JI,XI,YI,ZI,eS,tS,gA,mA,hA,fA,AA,yA,IA,Wt,wg,Rg,Vr,ki,rS,Dg,nS,iS,jr,sS,oS,aS,cS,dS,lS,SA,CA,EA,bA,vA,Ao,uS,TA,wA,RA,V,pS,Je,yo,Jt,DA,Pg,PA,NA,kA,Ng,re,gS,mS,hS,fS,BA,AS,j,yS,IS,SS,kg,Bg,CS,_g,Og,ES,bS,vS,TS,wS,_A,Ud,RS,DS,PS,NS,kS,OA,xA,BS,_S,OS,xS,LS,$S,MS,FS,US,xg,Qd,QS,HS,GS,qS,Lg,$g,Mg,VS,Fg,jS,zS,KS,WS,Ug,JS,XS,YS,ZS,eC,tC,rC,nC,LA,$A,MA,FA,Qg,iC,sC,oC,aC,cC,dC,lC,uC,pC,UA,QA,HA,GA,gC,mC,Hg,hC,Gg,qg,Vg,jg,fC,AC,yC,IC,Ne,Bi,SC,CC,EC,bC,vC,TC,wC,RC,qA,DC,PC,zg,Kg,NC,kC,VA,BC,_C,OC,xC,LC,$C,MC,FC,UC,QC,HC,GC,qC,VC,jC,zC,KC,WC,JC,XC,YC,Wg,ZC,Jg,eE,Xg,tE,Yg,rE,Zg,nE,zr,iE,em,sE,Io,oE,tm,aE,rm,cE,nm,dE,im,lE,sm,uE,Kr,pE,om,gE,am,mE,cm,hE,dm,fE,lm,AE,um,yE,pm,IE,gm,SE,mm,CE,hm,EE,fm,bE,Am,vE,ym,TE,Im,wE,Sm,RE,Cm,DE,Em,PE,bm,NE,vm,kE,Tm,BE,wm,_E,Rm,OE,Dm,xE,Pm,LE,Nm,$E,jA,zA,KA,WA,km,ME,Bm,FE,_m,UE,Om,QE,_i,JA,XA,So,Hd,Wr,YA,Co,Xt,Gd,qd,ZA,ey,xm,ty,Vd,Lm,HE,GE,Eo,bo,vo,jd,Oi,zd,Kd,To,Wd,Jd,$m,ry,ny,iy,qE,sy,oy,VE,ay,Mm,cy,dy,ly,jE,uy,xi,Xd,py,zE,gy,wo,Ro,Yd,Fm,KE,Um,WE,Qm,JE,Hm,XE,Gm,YE};
|