@stacksjs/ts-cloud 0.12.13 → 0.12.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aws/index.js +1 -1
- package/dist/bin/{chunk-bnv8yd9w.js → chunk-16rs9egs.js} +1 -1
- package/dist/bin/{chunk-w7k5rvmw.js → chunk-1rcsm0px.js} +1 -1
- package/dist/bin/{chunk-nnkhrm4n.js → chunk-1wvrtg42.js} +2 -2
- package/dist/bin/{chunk-96xtj5j6.js → chunk-1x7mm26k.js} +1 -1
- package/dist/bin/{chunk-7h6h8yxm.js → chunk-2paqksap.js} +3 -3
- package/dist/bin/{chunk-2hpnd4g4.js → chunk-3gwmejhk.js} +1 -1
- package/dist/bin/{chunk-jcyrm5q0.js → chunk-4201mvaj.js} +1 -1
- package/dist/bin/chunk-61ysn56t.js +1 -0
- package/dist/bin/{chunk-d5qhwtkg.js → chunk-6vay4ggv.js} +4 -4
- package/dist/bin/{chunk-xgepx8yx.js → chunk-92nng29y.js} +1 -1
- package/dist/bin/{chunk-1fj5gk6r.js → chunk-9q8zjavc.js} +52 -52
- package/dist/bin/{chunk-5gehfky4.js → chunk-a929za72.js} +2 -2
- package/dist/bin/{chunk-6xw0r4gn.js → chunk-bj5nq0kn.js} +11 -11
- package/dist/bin/{chunk-13dhcjjb.js → chunk-dbmk60r7.js} +2 -2
- package/dist/bin/chunk-f1ke4ygp.js +1 -0
- package/dist/bin/{chunk-p9hd27k4.js → chunk-f8mbjwme.js} +1 -1
- package/dist/bin/{chunk-ymbwekjm.js → chunk-fnr6k11h.js} +1 -1
- package/dist/bin/chunk-mzfct5en.js +1 -0
- package/dist/bin/{chunk-6zk2n3wk.js → chunk-n6qqa2fr.js} +29 -29
- package/dist/bin/{chunk-wvhqjr80.js → chunk-ngav845g.js} +2 -2
- package/dist/bin/{chunk-jh1593zx.js → chunk-nrnq9adz.js} +1 -1
- package/dist/bin/{chunk-84tvv3x1.js → chunk-pega3x2x.js} +1 -1
- package/dist/bin/{chunk-55kmbzr5.js → chunk-pt2bz3kr.js} +1 -1
- package/dist/bin/chunk-q5aj280b.js +1 -0
- package/dist/bin/{chunk-0vsxpmfj.js → chunk-rpg5k3wt.js} +2 -2
- package/dist/bin/{chunk-dh2qmxw9.js → chunk-vwyq2s2k.js} +1 -1
- package/dist/bin/{chunk-x5x9dzk7.js → chunk-w637s5q0.js} +1 -1
- package/dist/bin/{chunk-gj5jkhfr.js → chunk-wr6a423y.js} +3 -3
- package/dist/bin/{chunk-9jfjzycs.js → chunk-y7ece16e.js} +10 -10
- package/dist/bin/{chunk-12e9v1dw.js → chunk-ydpnsp4x.js} +1 -1
- package/dist/bin/cli.js +76 -76
- package/dist/bin/dashboard-server.js +1 -1
- package/dist/{chunk-edqhhcg9.js → chunk-5g1hsrab.js} +3 -3
- package/dist/chunk-5qqb671d.js +1 -0
- package/dist/{chunk-zmyv76f0.js → chunk-5ww7kc5z.js} +4 -4
- package/dist/{chunk-sct6mdgc.js → chunk-6j8f4ahv.js} +16 -16
- package/dist/{chunk-3qp10j0j.js → chunk-7hy9p6xr.js} +3 -3
- package/dist/{chunk-tnjae324.js → chunk-7kwha0fw.js} +61 -61
- package/dist/{chunk-g8fpsdyq.js → chunk-9mhcjht7.js} +4 -4
- package/dist/{chunk-wpqj98h8.js → chunk-bqaqkmtr.js} +2 -2
- package/dist/{chunk-7ww65b66.js → chunk-djd9xgkz.js} +70 -70
- package/dist/{chunk-1kp3y2s7.js → chunk-hw3p6pth.js} +1 -1
- package/dist/{chunk-emg3shmb.js → chunk-pkan6evc.js} +2 -2
- package/dist/{chunk-13d54txj.js → chunk-qzwack6w.js} +2 -2
- package/dist/{chunk-9c29rnk3.js → chunk-ttq6dvft.js} +7 -7
- package/dist/chunk-vpy3zjqv.js +1 -0
- package/dist/{chunk-ej4sm2tw.js → chunk-vva43vnp.js} +5 -5
- package/dist/{chunk-1n3ckctd.js → chunk-xxbvjq8g.js} +22 -22
- package/dist/deploy/index.js +1 -1
- package/dist/dns/index.js +1 -1
- package/dist/drivers/index.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +19 -19
- 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 +6 -6
- package/dist/ui/account/security.html +2 -2
- package/dist/ui/applications/compose.html +6 -6
- package/dist/ui/applications/new.html +1 -1
- 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 +6 -6
- package/dist/ui/operations/observability.html +6 -6
- package/dist/ui/operations/previews.html +5 -5
- package/dist/ui/operations/queue.html +6 -6
- package/dist/ui/operations/regions.html +6 -6
- 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 +2 -2
- package/dist/ui/server/actions.html +5 -5
- package/dist/ui/server/activity.html +2 -2
- package/dist/ui/server/capacity.html +5 -5
- package/dist/ui/server/database.html +5 -5
- package/dist/ui/server/deployments.html +6 -6
- package/dist/ui/server/diagnostics.html +1 -1
- 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 +5 -5
- package/dist/ui/server/ssh-keys.html +6 -6
- package/dist/ui/server/team.html +5 -5
- 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 +5 -5
- package/dist/ui/serverless/secrets.html +6 -6
- package/dist/ui/serverless/traces.html +6 -6
- package/dist/ui/serverless.html +5 -5
- package/package.json +3 -3
- package/dist/bin/chunk-de88yqwy.js +0 -1
- package/dist/bin/chunk-qz3za76g.js +0 -1
- package/dist/bin/chunk-rxwecjgc.js +0 -1
- package/dist/bin/chunk-xaafj6kf.js +0 -1
- package/dist/chunk-7by4rm7y.js +0 -1
- package/dist/chunk-n688m5fp.js +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{createRequire as qa}from"node:module";import{isAbsolute as $t,join as gt,relative as tr}from"node:path";import{existsSync as Ke,readdirSync as or}from"node:fs";import{join as ve}from"node:path";import{createHash as br}from"node:crypto";import{copyFileSync as Ar,existsSync as Et,readdirSync as Cr,readFileSync as nt,statSync as Tr,writeFileSync as it}from"node:fs";import{basename as vr,dirname as ia,extname as sa,join as He}from"node:path";import{existsSync as Ia,readFileSync as Wt}from"node:fs";import{homedir as Ra}from"node:os";import{join as Na}from"node:path";import{createHash as ka}from"node:crypto";import{existsSync as ot,mkdirSync as Tn,readdirSync as ua,readFileSync as da,unlinkSync as qe,writeFileSync as vn}from"node:fs";import{join as It}from"node:path";import{createHash as Vt}from"node:crypto";import{createReadStream as wn,readdirSync as En,statSync as ht}from"node:fs";import{join as Pn,relative as In}from"node:path";import{deflateRawSync as Bn}from"node:zlib";import{execSync as Fn}from"node:child_process";import{createHash as Vn}from"node:crypto";import{cpSync as jn,mkdtempSync as Kn,rmSync as Hn,writeFileSync as qn}from"node:fs";import{tmpdir as zn}from"node:os";import{dirname as Qn,isAbsolute as Jn,join as Le,resolve as Yn}from"node:path";import{fileURLToPath as Zn}from"node:url";import{execFileSync as bt}from"node:child_process";import{mkdtempSync as Ma,readFileSync as At,rmSync as xa}from"node:fs";import{tmpdir as Oa}from"node:os";import{dirname as ai,join as Pe}from"node:path";import{fileURLToPath as ri}from"node:url";import{AsyncLocalStorage as ii}from"node:async_hooks";import{createHash as si}from"node:crypto";import{readFileSync as
|
|
1
|
+
import{createRequire as qa}from"node:module";import{isAbsolute as $t,join as gt,relative as tr}from"node:path";import{existsSync as Ke,readdirSync as or}from"node:fs";import{join as ve}from"node:path";import{createHash as br}from"node:crypto";import{copyFileSync as Ar,existsSync as Et,readdirSync as Cr,readFileSync as nt,statSync as Tr,writeFileSync as it}from"node:fs";import{basename as vr,dirname as ia,extname as sa,join as He}from"node:path";import{existsSync as Ia,readFileSync as Wt}from"node:fs";import{homedir as Ra}from"node:os";import{join as Na}from"node:path";import{createHash as ka}from"node:crypto";import{existsSync as ot,mkdirSync as Tn,readdirSync as ua,readFileSync as da,unlinkSync as qe,writeFileSync as vn}from"node:fs";import{join as It}from"node:path";import{createHash as Vt}from"node:crypto";import{createReadStream as wn,readdirSync as En,statSync as ht}from"node:fs";import{join as Pn,relative as In}from"node:path";import{deflateRawSync as Bn}from"node:zlib";import{execSync as Fn}from"node:child_process";import{createHash as Vn}from"node:crypto";import{cpSync as jn,mkdtempSync as Kn,rmSync as Hn,writeFileSync as qn}from"node:fs";import{tmpdir as zn}from"node:os";import{dirname as Qn,isAbsolute as Jn,join as Le,resolve as Yn}from"node:path";import{fileURLToPath as Zn}from"node:url";import{execFileSync as bt}from"node:child_process";import{mkdtempSync as Ma,readFileSync as At,rmSync as xa}from"node:fs";import{tmpdir as Oa}from"node:os";import{dirname as ai,join as Pe}from"node:path";import{fileURLToPath as ri}from"node:url";import{AsyncLocalStorage as ii}from"node:async_hooks";import{createHash as si}from"node:crypto";import{readFileSync as Si}from"node:fs";import{dirname as bi,join as Ua}from"node:path";import{fileURLToPath as Ci}from"node:url";import{execFileSync as lt}from"node:child_process";import{existsSync as vi,mkdirSync as wi,mkdtempSync as Ei,readdirSync as Pi,readFileSync as Ii,rmSync as Ri,statSync as Fa,writeFileSync as Ni}from"node:fs";import{tmpdir as Di}from"node:os";import{join as xe,relative as ki}from"node:path";import{execSync as $i}from"node:child_process";import{createHash as Li}from"node:crypto";import{readdirSync as Mi,readFileSync as xi,statSync as ja}from"node:fs";import{join as Oi,relative as Ka,resolve as na}from"node:path";var za=Object.defineProperty,Qa=(a)=>a;function Ja(a,n){this[a]=Qa.bind(null,n)}var _e=(a,n)=>{for(var i in n)za(a,i,{get:n[i],enumerable:!0,configurable:!0,set:Ja.bind(n,i)})},Ya=(a,n,i)=>()=>{if(a)try{n=a(a=0)}catch(s){i=[s]}if(i)throw i[0];return n},Za=qa(import.meta.url);function Sp(a){let n=typeof a==="string"?new URL(a):a,{hostname:i,pathname:s}=n;if(i.endsWith(".on.aws")){let h=i.match(/^[^.]+\.lambda-url\.([^.]+)\.on\.aws$/);if(h)return{service:"lambda",region:h[1]};return{service:"",region:""}}if(i.endsWith(".r2.cloudflarestorage.com"))return{service:"s3",region:"auto"};if(i.endsWith(".backblazeb2.com")){let h=i.match(/^(?:[^.]+\.)?s3\.([^.]+)\.backblazeb2\.com$/);if(h)return{service:"s3",region:h[1]};return{service:"",region:""}}let c=i.replace("dualstack.","").match(/([^.]+)\.(?:([^.]+)\.)?amazonaws\.com(?:\.cn)?$/);if(!c)return{service:"",region:""};let l=c[1],u=c[2]||"";if(u==="us-gov")u="us-gov-west-1";else if(u==="s3"||u==="s3-accelerate")u="us-east-1",l="s3";else if(l==="iot")if(i.startsWith("iot."))l="execute-api";else if(i.startsWith("data.jobs.iot."))l="iot-jobs-data";else l=s==="/mqtt"?"iotdevicegateway":"iotdata";else if(l==="autoscaling");else if(!u&&l.startsWith("s3-"))u=l.slice(3).replace(/^fips-|^external-1/,""),l="s3";else if(l.endsWith("-fips"))l=l.slice(0,-5);else if(u&&/-\d$/.test(l)&&!/-\d$/.test(u))[l,u]=[u,l];return l=Ca[l]||l,{service:l,region:u||"us-east-1"}}function x(a){let{method:n,url:i,body:s="",accessKeyId:c,secretAccessKey:l,sessionToken:u,signQuery:h=!1,expiresIn:y=86400,datetime:f}=a,S=new URL(i),b=S.hostname,C=Sp(S),T=a.service||C.service,v=a.region||C.region;if(!T)throw Error("Could not detect service from URL. Please provide service explicitly.");if(!v)throw Error("Could not detect region from URL. Please provide region explicitly.");let w=f||new Date().toISOString().replace(/[:-]|\.\d{3}/g,""),R=w.substring(0,8),k=[R,v,T,"aws4_request"].join("/"),W="AWS4-HMAC-SHA256";if(h)return Xa({urlObj:S,method:n,body:s,accessKeyId:c,secretAccessKey:l,sessionToken:u,service:T,region:v,timestamp:w,date:R,credentialScope:k,algorithm:W,expiresIn:y,cache:a.cache});let P=S.pathname||"/",V=ft(S.searchParams),B={host:b,"x-amz-date":w,...a.headers};if(u)B["x-amz-security-token"]=u;let j=Object.keys(B).some((Ie)=>Ie.toLowerCase()==="content-type");if(s&&!j)B["content-type"]="application/x-amz-json-1.0";if(T==="s3"&&!B["x-amz-content-sha256"])B["x-amz-content-sha256"]=Je(s);let Z=ga(B),K=ha(B),ee=B["x-amz-content-sha256"]||Je(s),te=[n,St(P),V,Z,K,ee].join(`
|
|
2
2
|
`),ie=Je(te),me=[W,w,k,ie].join(`
|
|
3
3
|
`),ce=a.cache??ke,ue=fa(l,R,v,T,me,ce),se=[`${W} Credential=${c}/${k}`,`SignedHeaders=${K}`,`Signature=${ue}`].join(", ");return B.authorization=se,{url:i,method:n,headers:B,body:s||void 0}}async function Cp(a){let{method:n,url:i,body:s="",accessKeyId:c,secretAccessKey:l,sessionToken:u,signQuery:h=!1,expiresIn:y=86400,datetime:f}=a,S=new URL(i),b=S.hostname,C=Sp(S),T=a.service||C.service,v=a.region||C.region;if(!T)throw Error("Could not detect service from URL. Please provide service explicitly.");if(!v)throw Error("Could not detect region from URL. Please provide region explicitly.");let w=f||new Date().toISOString().replace(/[:-]|\.\d{3}/g,""),R=w.substring(0,8),k=[R,v,T,"aws4_request"].join("/"),W="AWS4-HMAC-SHA256";if(h)return er({urlObj:S,method:n,body:s,accessKeyId:c,secretAccessKey:l,sessionToken:u,service:T,region:v,timestamp:w,date:R,credentialScope:k,algorithm:W,expiresIn:y,cache:a.cache});let P=S.pathname||"/",V=ft(S.searchParams),B={host:b,"x-amz-date":w,...a.headers};if(u)B["x-amz-security-token"]=u;let j=Object.keys(B).some((We)=>We.toLowerCase()==="content-type");if(s&&!j)B["content-type"]="application/x-amz-json-1.0";let Z=await dt(s);if(T==="s3"&&!B["x-amz-content-sha256"])B["x-amz-content-sha256"]=Z;let K=ga(B),ee=ha(B),te=B["x-amz-content-sha256"]||Z,ie=[n,St(P),V,K,ee,te].join(`
|
|
4
4
|
`),me=await dt(ie),ce=[W,w,k,me].join(`
|
|
@@ -10,12 +10,12 @@ import{createRequire as qa}from"node:module";import{isAbsolute as $t,join as gt,
|
|
|
10
10
|
`),j=[C,f,b,await dt(B)].join(`
|
|
11
11
|
`),Z=await Sa(l,S,y,h,j,v??ke);return w.searchParams.set("X-Amz-Signature",Z),{url:w.toString(),method:i,headers:{},body:s||void 0}}function rf(a){let{url:n,method:i="GET",expiresIn:s=3600,...c}=a,l=Math.min(s,604800);return x({...c,url:n,method:i,signQuery:!0,expiresIn:l}).url}async function uy(a){let{url:n,method:i="GET",expiresIn:s=3600,...c}=a,l=Math.min(s,604800);return(await Cp({...c,url:n,method:i,signQuery:!0,expiresIn:l})).url}function ga(a){return Object.keys(a).sort().map((n)=>`${n.toLowerCase()}:${a[n].trim().replace(/\s+/g," ")}`).join(`
|
|
12
12
|
`)+`
|
|
13
|
-
`}function ha(a){return Object.keys(a).sort().map((n)=>n.toLowerCase()).join(";")}function ft(a){let n=[];return a.forEach((i,s)=>{n.push([kt(s),kt(i)])}),n.sort((i,s)=>{if(i[0]<s[0])return-1;if(i[0]>s[0])return 1;if(i[1]<s[1])return-1;if(i[1]>s[1])return 1;return 0}),n.map(([i,s])=>`${i}=${s}`).join("&")}function St(a){return a.split("/").map((n)=>kt(n)).join("/")}function kt(a){return encodeURIComponent(a).replace(/[!'()*]/g,(n)=>`%${n.charCodeAt(0).toString(16).toUpperCase()}`)}function Je(a){if(!Be)throw Error("Synchronous hash not available in browser. Use signRequestAsync() instead.");return Be.createHash("sha256").update(a,"utf8").digest("hex")}function Ve(a,n){if(!Be)throw Error("Synchronous hmac not available in browser. Use signRequestAsync() instead.");return Be.createHmac("sha256",a).update(n,"utf8").digest()}async function dt(a){let n=new TextEncoder().encode(a),i=await crypto.subtle.digest("SHA-256",n);return ya(new Uint8Array(i))}async function je(a,n){let i=new TextEncoder,s=typeof a==="string"?i.encode(a):a,c=i.encode(n),l=await crypto.subtle.importKey("raw",s.buffer,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),u=await crypto.subtle.sign("HMAC",l,c.buffer);return new Uint8Array(u)}function ya(a){return Array.from(a).map((n)=>n.toString(16).padStart(2,"0")).join("")}function fa(a,n,i,s,c,l){let u=`${a}:${n}:${i}:${s}`,h=l.get(u);if(!h){let y=Ve(`AWS4${a}`,n),f=Ve(y,i),S=Ve(f,s);if(h=Ve(S,"aws4_request"),l.size>=Aa){let b=l.keys().next().value;if(b)l.delete(b)}l.set(u,h)}return Ve(h,c).toString("hex")}async function Sa(a,n,i,s,c,l){let u=`${a}:${n}:${i}:${s}`,h=l.get(u);if(!h){let f=await je(`AWS4${a}`,n),S=await je(f,i),b=await je(S,s);if(h=await je(b,"aws4_request"),l.size>=Aa){let C=l.keys().next().value;if(C)l.delete(C)}l.set(u,h)}let y=await je(h,c);return ya(y)}function ba(a,n){return n.includes(a)}function mt(a,n,i){let s=n*Math.pow(2,a),c=Math.random()*0.3*s;return Math.min(s+c,i)}function pt(a){return new Promise((n)=>setTimeout(n,a))}async function nf(a,n){let{maxRetries:i=3,initialDelayMs:s=100,maxDelayMs:c=5000,retryableStatusCodes:l=[429,500,502,503,504],timeoutMs:u=30000}=n??{},h,y;for(let f=0;f<=i;f++){let S=x(a),b={method:S.method,headers:S.headers};if(S.body)b.body=S.body;let C=new AbortController,T=setTimeout(()=>C.abort(),u);b.signal=C.signal;try{let v=await fetch(S.url,b);if(clearTimeout(T),y=v,v.ok)return v;if(f<i&&ba(v.status,l)){let R=mt(f,s,c);await pt(R);continue}let w=await v.text();throw Error(`AWS API request failed (${v.status}): ${w}`)}catch(v){if(clearTimeout(T),h=v,v instanceof Error&&v.name==="AbortError")h=Error(`Request timed out after ${u}ms`);if(f<i&&!(v instanceof Error&&v.message.includes("AWS API request failed"))){let w=mt(f,s,c);await pt(w);continue}throw h}}throw h??Error("Request failed after retries")}async function py(a){return nf(a,{maxRetries:0})}async function gy(a,n){let{maxRetries:i=3,initialDelayMs:s=100,maxDelayMs:c=5000,retryableStatusCodes:l=[429,500,502,503,504],timeoutMs:u=30000}=n??{},h;for(let y=0;y<=i;y++){let f=await Cp(a),S={method:f.method,headers:f.headers};if(f.body)S.body=f.body;let b=new AbortController,C=setTimeout(()=>b.abort(),u);S.signal=b.signal;try{let T=await fetch(f.url,S);if(clearTimeout(C),T.ok)return T;if(y<i&&ba(T.status,l)){let w=mt(y,s,c);await pt(w);continue}let v=await T.text();throw Error(`AWS API request failed (${T.status}): ${v}`)}catch(T){if(clearTimeout(C),h=T,T instanceof Error&&T.name==="AbortError")h=Error(`Request timed out after ${u}ms`);if(y<i&&!(T instanceof Error&&T.message.includes("AWS API request failed"))){let v=mt(y,s,c);await pt(v);continue}throw h}}throw h??Error("Request failed after retries")}async function my(a){let n=await a.text(),i={},s=/<(\w+)>([^<]+)<\/\1>/g,c;while((c=s.exec(n))!==null){let[,l,u]=c;i[l]=u}return i}async function hy(a){return await a.json()}function fy(){ke.clear()}function Ay(){return ke.size}function yy(){return Be!==void 0}function Iy(){return typeof crypto<"u"&&typeof crypto.subtle<"u"}var Be,ke,Aa=100,Ca,et=Ya(async()=>{try{Be=await import("node:crypto")}catch{}ke=new Map,Ca={appstream2:"appstream",cloudhsmv2:"cloudhsm",email:"ses",marketplace:"aws-marketplace",mobile:"AWSMobileHubService",pinpoint:"mobiletargeting",queue:"sqs","git-codecommit":"codecommit","mturk-requester-sandbox":"mturk-requester","personalize-runtime":"personalize"}}),Sy={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}},Cy={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}}}},bp=".ts-cloud",Ep="TS_CLOUD_STATE_DIR",Ot=null;function Wc(a){Ot=a?.trim()||null}function Jc(){return Boolean(process.env[Ep]?.trim()||Ot)}function Us(){return process.env[Ep]?.trim()||Ot||bp}function _(...a){return gt(Us(),...a)}function d(a,...n){let i=Us();return $t(i)?gt(i,...n):gt(a,i,...n)}function Xc(a,n=process.cwd()){let i=(c,l)=>{let u=tr(c,l);return u===""||!u.startsWith("..")&&!$t(u)},s=$t(a)?a:gt(n,a);return i(d(n),s)}function vp(a){let n=a.infrastructure?.compute!=null,i=Object.values(a.environments??{}).some((s)=>s?.app!=null);return{server:n,serverless:i}}function O(a){if(a.mode==="server"||a.mode==="serverless")return a.mode;let{serverless:n}=vp(a);return n?"serverless":"server"}function Yc(a){let{server:n,serverless:i}=vp(a);if(n&&i)return"A project cannot be both a server and a serverless deployment. Found `infrastructure.compute` (server) AND `environments.<env>.app` (serverless Lambda). Keep one: remove `infrastructure.compute` for a serverless app, or remove `environments.<env>.app` for a server.";if(a.mode==="server"&&i&&!n)return"Config sets `mode: 'server'` but declares a serverless app (`environments.<env>.app`). Remove the app or change the mode.";if(a.mode==="serverless"&&n&&!i)return"Config sets `mode: 'serverless'` but declares a server (`infrastructure.compute`). Remove the compute block or change the mode.";return null}function p(a){return a.infrastructure?.appDatabase??a.infrastructure?.compute?.database}function ar(a){return typeof a==="object"&&a!==null?a:{}}function sf(a){return a===!0||typeof a==="object"&&a!==null}function rr(a,n){let i=n?a.environments?.[n]:void 0;if(i?.domain)return i.domain;let s=Object.values(a.sites??{}),c=a.sites?.main?.domain??s.find((l)=>l.domain)?.domain;if(c)return c;return`${a.project?.slug??"app"}.local`}function nr(a){let n=a.indexOf(".");return n>0?a.slice(n+1):void 0}function li(a,n={}){let i=a.infrastructure?.compute?.managedServices?.mail,s=ar(i),c=n.environmentType??(n.environment?a.environments?.[n.environment]?.type:void 0),l=s.mode??(c==="production"?"server":"catcher"),u=l==="server",h=rr(a,n.environment),y=s.hostname??(u?`mail.${h}`:"localhost"),f=s.ports??{},S=u?{smtp:f.smtp??25,submission:f.submission??587,submissions:f.submissions??465,imap:f.imap??143,imaps:f.imaps??993,webmail:f.webmail??8080,managesieve:f.managesieve}:{smtp:f.smtp??1025,submission:f.submission,submissions:f.submissions,imap:f.imap,imaps:f.imaps,webmail:f.webmail??8025,managesieve:f.managesieve},b=s.tls??{},C=b.enabled??u,T=!!(b.certPath&&b.keyPath),v=(s.accounts??[]).map((K)=>({address:K.address,password:K.password})),w=typeof s.dkim==="object"&&s.dkim!==null?s.dkim:{},R=s.dkim===!1?!1:s.dkim===!0||u,k=typeof s.webmail==="object"&&s.webmail!==null?s.webmail:{},W=s.webmail===!1?!1:k.enabled??!0,P=s.spam??{},V=s.delivery??(u?"direct":"none"),B=s.expose??u,j=nr(y),Z=[...new Set([y,...j?[j]:[],...s.domains??[]])];return{enabled:sf(i),mode:l,version:s.version,hostname:y,domains:Z,ports:S,tls:{enabled:C,acme:C&&!T&&(b.acme??!0),certPath:b.certPath,keyPath:b.keyPath,requireForAuth:b.requireForAuth??(C&&u),acmeEmail:b.acmeEmail??v[0]?.address},dkim:{enabled:R,selector:w.selector??"default",rotate:w.rotate??!1,rotateIntervalDays:w.rotateIntervalDays??90},webmail:{enabled:W,port:k.port??S.webmail,domain:k.domain},delivery:V,sesRegion:s.sesRegion??"us-east-1",accounts:v,storagePath:s.storagePath??"/var/lib/mail",maxMessageSize:s.maxMessageSize??26214400,spam:{enabled:P.enabled??u,enforce:P.enforce??!1,junkScore:P.junkScore??5,rejectScore:P.rejectScore??12,dnsbl:P.dnsbl??u,greylist:P.greylist??!1},webhookUrl:s.webhookUrl,expose:B,bindAddress:B?"0.0.0.0":"127.0.0.1"}}function Zc(a){if(!a.enabled||!a.expose)return[];let n=[a.ports.smtp,a.ports.submission,a.ports.submissions,a.ports.imap,a.ports.imaps,a.ports.managesieve].filter((i)=>typeof i==="number");if(a.webmail.enabled&&!a.webmail.domain)n.push(a.webmail.port);return[...new Set(n)].sort((i,s)=>i-s)}function ed(a){if(!a.enabled)return{};let n=a.ports.submission??a.ports.smtp,i={MAIL_MAILER:"smtp",MAIL_HOST:"127.0.0.1",MAIL_PORT:String(n)};if(a.mode==="server"){i.MAIL_ENCRYPTION=a.tls.enabled?"tls":"null";let s=a.accounts[0];if(s)i.MAIL_USERNAME=s.address,i.MAIL_PASSWORD=s.password}else i.MAIL_ENCRYPTION="null",i.MAIL_USERNAME="null",i.MAIL_PASSWORD="null";return i}function ae(a){if(a.cloud?.provider)return a.cloud.provider;if(a.ssh?.hosts?.length)return"ssh";if(a.hetzner?.apiToken)return"hetzner";return"aws"}class td{template;constructor(a){this.template={AWSTemplateFormatVersion:"2010-09-09",Description:a,Resources:{}}}addResource(a,n){return this.template.Resources[a]=n,this}addResources(a){return Object.assign(this.template.Resources,a),this}addParameter(a,n){if(!this.template.Parameters)this.template.Parameters={};return this.template.Parameters[a]=n,this}addOutput(a,n){if(!this.template.Outputs)this.template.Outputs={};return this.template.Outputs[a]=n,this}hasResource(a){return a in this.template.Resources}getResources(){return this.template.Resources}build(){return this.template}toJSON(a=!0){return JSON.stringify(this.template,null,a?2:0)}toYAML(){return this.convertToYAML(this.template)}convertToYAML(a,n=0){let i=" ".repeat(n),s="";for(let[c,l]of Object.entries(a)){if(l===null||l===void 0)continue;if(typeof l==="object"&&!Array.isArray(l))s+=`${i}${c}:
|
|
13
|
+
`}function ha(a){return Object.keys(a).sort().map((n)=>n.toLowerCase()).join(";")}function ft(a){let n=[];return a.forEach((i,s)=>{n.push([kt(s),kt(i)])}),n.sort((i,s)=>{if(i[0]<s[0])return-1;if(i[0]>s[0])return 1;if(i[1]<s[1])return-1;if(i[1]>s[1])return 1;return 0}),n.map(([i,s])=>`${i}=${s}`).join("&")}function St(a){return a.split("/").map((n)=>kt(n)).join("/")}function kt(a){return encodeURIComponent(a).replace(/[!'()*]/g,(n)=>`%${n.charCodeAt(0).toString(16).toUpperCase()}`)}function Je(a){if(!Be)throw Error("Synchronous hash not available in browser. Use signRequestAsync() instead.");return Be.createHash("sha256").update(a,"utf8").digest("hex")}function Ve(a,n){if(!Be)throw Error("Synchronous hmac not available in browser. Use signRequestAsync() instead.");return Be.createHmac("sha256",a).update(n,"utf8").digest()}async function dt(a){let n=new TextEncoder().encode(a),i=await crypto.subtle.digest("SHA-256",n);return ya(new Uint8Array(i))}async function je(a,n){let i=new TextEncoder,s=typeof a==="string"?i.encode(a):a,c=i.encode(n),l=await crypto.subtle.importKey("raw",s.buffer,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),u=await crypto.subtle.sign("HMAC",l,c.buffer);return new Uint8Array(u)}function ya(a){return Array.from(a).map((n)=>n.toString(16).padStart(2,"0")).join("")}function fa(a,n,i,s,c,l){let u=`${a}:${n}:${i}:${s}`,h=l.get(u);if(!h){let y=Ve(`AWS4${a}`,n),f=Ve(y,i),S=Ve(f,s);if(h=Ve(S,"aws4_request"),l.size>=Aa){let b=l.keys().next().value;if(b)l.delete(b)}l.set(u,h)}return Ve(h,c).toString("hex")}async function Sa(a,n,i,s,c,l){let u=`${a}:${n}:${i}:${s}`,h=l.get(u);if(!h){let f=await je(`AWS4${a}`,n),S=await je(f,i),b=await je(S,s);if(h=await je(b,"aws4_request"),l.size>=Aa){let C=l.keys().next().value;if(C)l.delete(C)}l.set(u,h)}let y=await je(h,c);return ya(y)}function ba(a,n){return n.includes(a)}function mt(a,n,i){let s=n*Math.pow(2,a),c=Math.random()*0.3*s;return Math.min(s+c,i)}function pt(a){return new Promise((n)=>setTimeout(n,a))}async function nf(a,n){let{maxRetries:i=3,initialDelayMs:s=100,maxDelayMs:c=5000,retryableStatusCodes:l=[429,500,502,503,504],timeoutMs:u=30000}=n??{},h,y;for(let f=0;f<=i;f++){let S=x(a),b={method:S.method,headers:S.headers};if(S.body)b.body=S.body;let C=new AbortController,T=setTimeout(()=>C.abort(),u);b.signal=C.signal;try{let v=await fetch(S.url,b);if(clearTimeout(T),y=v,v.ok)return v;if(f<i&&ba(v.status,l)){let R=mt(f,s,c);await pt(R);continue}let w=await v.text();throw Error(`AWS API request failed (${v.status}): ${w}`)}catch(v){if(clearTimeout(T),h=v,v instanceof Error&&v.name==="AbortError")h=Error(`Request timed out after ${u}ms`);if(f<i&&!(v instanceof Error&&v.message.includes("AWS API request failed"))){let w=mt(f,s,c);await pt(w);continue}throw h}}throw h??Error("Request failed after retries")}async function py(a){return nf(a,{maxRetries:0})}async function gy(a,n){let{maxRetries:i=3,initialDelayMs:s=100,maxDelayMs:c=5000,retryableStatusCodes:l=[429,500,502,503,504],timeoutMs:u=30000}=n??{},h;for(let y=0;y<=i;y++){let f=await Cp(a),S={method:f.method,headers:f.headers};if(f.body)S.body=f.body;let b=new AbortController,C=setTimeout(()=>b.abort(),u);S.signal=b.signal;try{let T=await fetch(f.url,S);if(clearTimeout(C),T.ok)return T;if(y<i&&ba(T.status,l)){let w=mt(y,s,c);await pt(w);continue}let v=await T.text();throw Error(`AWS API request failed (${T.status}): ${v}`)}catch(T){if(clearTimeout(C),h=T,T instanceof Error&&T.name==="AbortError")h=Error(`Request timed out after ${u}ms`);if(y<i&&!(T instanceof Error&&T.message.includes("AWS API request failed"))){let v=mt(y,s,c);await pt(v);continue}throw h}}throw h??Error("Request failed after retries")}async function my(a){let n=await a.text(),i={},s=/<(\w+)>([^<]+)<\/\1>/g,c;while((c=s.exec(n))!==null){let[,l,u]=c;i[l]=u}return i}async function hy(a){return await a.json()}function fy(){ke.clear()}function Ay(){return ke.size}function yy(){return Be!==void 0}function Iy(){return typeof crypto<"u"&&typeof crypto.subtle<"u"}var Be,ke,Aa=100,Ca,et=Ya(async()=>{try{Be=await import("node:crypto")}catch{}ke=new Map,Ca={appstream2:"appstream",cloudhsmv2:"cloudhsm",email:"ses",marketplace:"aws-marketplace",mobile:"AWSMobileHubService",pinpoint:"mobiletargeting",queue:"sqs","git-codecommit":"codecommit","mturk-requester-sandbox":"mturk-requester","personalize-runtime":"personalize"}}),Sy={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}},Cy={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}}}},bp=".ts-cloud",Ep="TS_CLOUD_STATE_DIR",Ot=null;function Wc(a){Ot=a?.trim()||null}function Jc(){return Boolean(process.env[Ep]?.trim()||Ot)}function Qs(){return process.env[Ep]?.trim()||Ot||bp}function _(...a){return gt(Qs(),...a)}function d(a,...n){let i=Qs();return $t(i)?gt(i,...n):gt(a,i,...n)}function Xc(a,n=process.cwd()){let i=(c,l)=>{let u=tr(c,l);return u===""||!u.startsWith("..")&&!$t(u)},s=$t(a)?a:gt(n,a);return i(d(n),s)}function vp(a){let n=a.infrastructure?.compute!=null,i=Object.values(a.environments??{}).some((s)=>s?.app!=null);return{server:n,serverless:i}}function O(a){if(a.mode==="server"||a.mode==="serverless")return a.mode;let{serverless:n}=vp(a);return n?"serverless":"server"}function Yc(a){let{server:n,serverless:i}=vp(a);if(n&&i)return"A project cannot be both a server and a serverless deployment. Found `infrastructure.compute` (server) AND `environments.<env>.app` (serverless Lambda). Keep one: remove `infrastructure.compute` for a serverless app, or remove `environments.<env>.app` for a server.";if(a.mode==="server"&&i&&!n)return"Config sets `mode: 'server'` but declares a serverless app (`environments.<env>.app`). Remove the app or change the mode.";if(a.mode==="serverless"&&n&&!i)return"Config sets `mode: 'serverless'` but declares a server (`infrastructure.compute`). Remove the compute block or change the mode.";return null}function p(a){return a.infrastructure?.appDatabase??a.infrastructure?.compute?.database}function ar(a){return typeof a==="object"&&a!==null?a:{}}function sf(a){return a===!0||typeof a==="object"&&a!==null}function rr(a,n){let i=n?a.environments?.[n]:void 0;if(i?.domain)return i.domain;let s=Object.values(a.sites??{}),c=a.sites?.main?.domain??s.find((l)=>l.domain)?.domain;if(c)return c;return`${a.project?.slug??"app"}.local`}function nr(a){let n=a.indexOf(".");return n>0?a.slice(n+1):void 0}function ui(a,n={}){let i=a.infrastructure?.compute?.managedServices?.mail,s=ar(i),c=n.environmentType??(n.environment?a.environments?.[n.environment]?.type:void 0),l=s.mode??(c==="production"?"server":"catcher"),u=l==="server",h=rr(a,n.environment),y=s.hostname??(u?`mail.${h}`:"localhost"),f=s.ports??{},S=u?{smtp:f.smtp??25,submission:f.submission??587,submissions:f.submissions??465,imap:f.imap??143,imaps:f.imaps??993,webmail:f.webmail??8080,managesieve:f.managesieve}:{smtp:f.smtp??1025,submission:f.submission,submissions:f.submissions,imap:f.imap,imaps:f.imaps,webmail:f.webmail??8025,managesieve:f.managesieve},b=s.tls??{},C=b.enabled??u,T=!!(b.certPath&&b.keyPath),v=(s.accounts??[]).map((K)=>({address:K.address,password:K.password})),w=typeof s.dkim==="object"&&s.dkim!==null?s.dkim:{},R=s.dkim===!1?!1:s.dkim===!0||u,k=typeof s.webmail==="object"&&s.webmail!==null?s.webmail:{},W=s.webmail===!1?!1:k.enabled??!0,P=s.spam??{},V=s.delivery??(u?"direct":"none"),B=s.expose??u,j=nr(y),Z=[...new Set([y,...j?[j]:[],...s.domains??[]])];return{enabled:sf(i),mode:l,version:s.version,hostname:y,domains:Z,ports:S,tls:{enabled:C,acme:C&&!T&&(b.acme??!0),certPath:b.certPath,keyPath:b.keyPath,requireForAuth:b.requireForAuth??(C&&u),acmeEmail:b.acmeEmail??v[0]?.address},dkim:{enabled:R,selector:w.selector??"default",rotate:w.rotate??!1,rotateIntervalDays:w.rotateIntervalDays??90},webmail:{enabled:W,port:k.port??S.webmail,domain:k.domain},delivery:V,sesRegion:s.sesRegion??"us-east-1",accounts:v,storagePath:s.storagePath??"/var/lib/mail",maxMessageSize:s.maxMessageSize??26214400,spam:{enabled:P.enabled??u,enforce:P.enforce??!1,junkScore:P.junkScore??5,rejectScore:P.rejectScore??12,dnsbl:P.dnsbl??u,greylist:P.greylist??!1},webhookUrl:s.webhookUrl,expose:B,bindAddress:B?"0.0.0.0":"127.0.0.1"}}function Zc(a){if(!a.enabled||!a.expose)return[];let n=[a.ports.smtp,a.ports.submission,a.ports.submissions,a.ports.imap,a.ports.imaps,a.ports.managesieve].filter((i)=>typeof i==="number");if(a.webmail.enabled&&!a.webmail.domain)n.push(a.webmail.port);return[...new Set(n)].sort((i,s)=>i-s)}function ed(a){if(!a.enabled)return{};let n=a.ports.submission??a.ports.smtp,i={MAIL_MAILER:"smtp",MAIL_HOST:"127.0.0.1",MAIL_PORT:String(n)};if(a.mode==="server"){i.MAIL_ENCRYPTION=a.tls.enabled?"tls":"null";let s=a.accounts[0];if(s)i.MAIL_USERNAME=s.address,i.MAIL_PASSWORD=s.password}else i.MAIL_ENCRYPTION="null",i.MAIL_USERNAME="null",i.MAIL_PASSWORD="null";return i}function ae(a){if(a.cloud?.provider)return a.cloud.provider;if(a.ssh?.hosts?.length)return"ssh";if(a.hetzner?.apiToken)return"hetzner";return"aws"}class td{template;constructor(a){this.template={AWSTemplateFormatVersion:"2010-09-09",Description:a,Resources:{}}}addResource(a,n){return this.template.Resources[a]=n,this}addResources(a){return Object.assign(this.template.Resources,a),this}addParameter(a,n){if(!this.template.Parameters)this.template.Parameters={};return this.template.Parameters[a]=n,this}addOutput(a,n){if(!this.template.Outputs)this.template.Outputs={};return this.template.Outputs[a]=n,this}hasResource(a){return a in this.template.Resources}getResources(){return this.template.Resources}build(){return this.template}toJSON(a=!0){return JSON.stringify(this.template,null,a?2:0)}toYAML(){return this.convertToYAML(this.template)}convertToYAML(a,n=0){let i=" ".repeat(n),s="";for(let[c,l]of Object.entries(a)){if(l===null||l===void 0)continue;if(typeof l==="object"&&!Array.isArray(l))s+=`${i}${c}:
|
|
14
14
|
${this.convertToYAML(l,n+1)}`;else if(Array.isArray(l)){s+=`${i}${c}:
|
|
15
15
|
`;for(let u of l)if(typeof u==="object")s+=`${i} -
|
|
16
16
|
${this.convertToYAML(u,n+2)}`;else s+=`${i} - ${u}
|
|
17
17
|
`}else s+=`${i}${c}: ${l}
|
|
18
|
-
`}return s}}var N={Ref:(a)=>({Ref:a}),GetAtt:(a,n)=>({"Fn::GetAtt":[a,n]}),Sub:(a,n)=>{if(n)return{"Fn::Sub":[a,n]};return{"Fn::Sub":a}},Join:(a,n)=>({"Fn::Join":[a,n]}),Select:(a,n)=>({"Fn::Select":[a,n]}),Split:(a,n)=>({"Fn::Split":[a,n]}),GetAZs:(a="")=>({"Fn::GetAZs":a}),ImportValue:(a)=>({"Fn::ImportValue":a}),If:(a,n,i)=>({"Fn::If":[a,n,i]}),Equals:(a,n)=>({"Fn::Equals":[a,n]}),And:(...a)=>({"Fn::And":a}),Or:(...a)=>({"Fn::Or":a}),Not:(a)=>({"Fn::Not":[a]}),Base64:(a)=>({"Fn::Base64":a})},by={AccountId:{Ref:"AWS::AccountId"},Region:{Ref:"AWS::Region"},StackId:{Ref:"AWS::StackId"},StackName:{Ref:"AWS::StackName"},NotificationARNs:{Ref:"AWS::NotificationARNs"},Partition:{Ref:"AWS::Partition"},URLSuffix:{Ref:"AWS::URLSuffix"},NoValue:{Ref:"AWS::NoValue"}};function r(a){let{slug:n,environment:i,resourceType:s,timestamp:c,suffix:l}=a,u=[n,i,s];if(c)u.push(c);if(l)u.push(l);return u.join("-")}function t(a){return a.split("-").map((n)=>n.charAt(0).toUpperCase()+n.slice(1)).join("")}function Ey(){return Date.now().toString()}function vy(a){return a.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/^-+|-+$/g,"").replace(/-+/g,"-")}function g(a,n){return a.project.stackName??`${a.project.slug}-${n}`}function Ty(a,n,i,s){return i.stackName??`${a.project.slug}-${s}-${n}-site`}function wy(a,n){return`${a.project.slug}-${n}`}function Ry(a,n,i,s){if(s)return s;if(i==="main")return`${a}-${n}-site`;return`${a}-${n}-${i}`}function Dy(a,n,i,s){return s??`${a}-${n}-${i}`}function Py(a,n){return`${a}-${n}-deploy`}function Mt(a,n){return`${a.project.slug}-${n}-app`}function rd(a,n){return`${a}-${n}-deployments`}function
|
|
18
|
+
`}return s}}var N={Ref:(a)=>({Ref:a}),GetAtt:(a,n)=>({"Fn::GetAtt":[a,n]}),Sub:(a,n)=>{if(n)return{"Fn::Sub":[a,n]};return{"Fn::Sub":a}},Join:(a,n)=>({"Fn::Join":[a,n]}),Select:(a,n)=>({"Fn::Select":[a,n]}),Split:(a,n)=>({"Fn::Split":[a,n]}),GetAZs:(a="")=>({"Fn::GetAZs":a}),ImportValue:(a)=>({"Fn::ImportValue":a}),If:(a,n,i)=>({"Fn::If":[a,n,i]}),Equals:(a,n)=>({"Fn::Equals":[a,n]}),And:(...a)=>({"Fn::And":a}),Or:(...a)=>({"Fn::Or":a}),Not:(a)=>({"Fn::Not":[a]}),Base64:(a)=>({"Fn::Base64":a})},by={AccountId:{Ref:"AWS::AccountId"},Region:{Ref:"AWS::Region"},StackId:{Ref:"AWS::StackId"},StackName:{Ref:"AWS::StackName"},NotificationARNs:{Ref:"AWS::NotificationARNs"},Partition:{Ref:"AWS::Partition"},URLSuffix:{Ref:"AWS::URLSuffix"},NoValue:{Ref:"AWS::NoValue"}};function r(a){let{slug:n,environment:i,resourceType:s,timestamp:c,suffix:l}=a,u=[n,i,s];if(c)u.push(c);if(l)u.push(l);return u.join("-")}function t(a){return a.split("-").map((n)=>n.charAt(0).toUpperCase()+n.slice(1)).join("")}function Ey(){return Date.now().toString()}function vy(a){return a.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/^-+|-+$/g,"").replace(/-+/g,"-")}function g(a,n){return a.project.stackName??`${a.project.slug}-${n}`}function Ty(a,n,i,s){return i.stackName??`${a.project.slug}-${s}-${n}-site`}function wy(a,n){return`${a.project.slug}-${n}`}function Ry(a,n,i,s){if(s)return s;if(i==="main")return`${a}-${n}-site`;return`${a}-${n}-${i}`}function Dy(a,n,i,s){return s??`${a}-${n}-${i}`}function Py(a,n){return`${a}-${n}-deploy`}function Mt(a,n){return`${a.project.slug}-${n}-app`}function rd(a,n){return`${a}-${n}-deployments`}function Hs(a,n){return`${a}-${n}-assets`}class of{nodes=new Map;addResource(a,n){let i=this.extractDependencies(n);this.nodes.set(a,{logicalId:a,resource:n,dependencies:i})}extractDependencies(a){let n=new Set;if(a.DependsOn)if(Array.isArray(a.DependsOn))a.DependsOn.forEach((i)=>n.add(i));else n.add(a.DependsOn);return this.findReferences(a.Properties||{},n),n}findReferences(a,n){if(!a||typeof a!=="object")return;if("Ref"in a&&typeof a.Ref==="string"){if(!a.Ref.startsWith("AWS::"))n.add(a.Ref)}if("Fn::GetAtt"in a&&Array.isArray(a["Fn::GetAtt"]))n.add(a["Fn::GetAtt"][0]);for(let i of Object.values(a))if(typeof i==="object")this.findReferences(i,n)}topologicalSort(){let a=[],n=new Set,i=new Set,s=(c)=>{if(n.has(c))return;if(i.has(c))throw Error(`Circular dependency detected: ${c}`);i.add(c);let l=this.nodes.get(c);if(l)for(let u of l.dependencies)s(u);i.delete(c),n.add(c),a.push(c)};for(let c of this.nodes.keys())s(c);return a}validate(){for(let[a,n]of this.nodes.entries())for(let i of n.dependencies)if(!this.nodes.has(i))throw Error(`Resource "${a}" depends on "${i}" which does not exist`)}getDependents(a){let n=[];for(let[i,s]of this.nodes.entries())if(s.dependencies.has(a))n.push(i);return n}}function Ny(a,n){let i=[],s=[],c=[],l=[],u=[],h=a.Resources||{},y=n.Resources||{},f=new Set([...Object.keys(h),...Object.keys(y)]);for(let b of f){let C=h[b],T=y[b];if(!C&&T)i.push({logicalId:b,action:"add",resourceType:T.Type});else if(C&&!T)s.push({logicalId:b,action:"remove",resourceType:C.Type});else if(C&&T)if(C.Type!==T.Type)l.push({logicalId:b,action:"replace",resourceType:T.Type,reason:`Type changed from ${C.Type} to ${T.Type}`});else{let v=Ta(C.Properties||{},T.Properties||{});if(v.length>0)if(ir(C.Type,v))l.push({logicalId:b,action:"replace",resourceType:T.Type,changes:v,reason:"Property changes require replacement"});else c.push({logicalId:b,action:"update",resourceType:T.Type,changes:v});else u.push(b)}}let S=sr([...s,...l,...c]);return{added:i,removed:s,updated:c,replaced:l,unchanged:u,summary:{totalChanges:i.length+s.length+c.length+l.length,requiresReplacement:l.length>0,dangerousChanges:S}}}function Ta(a,n,i=""){let s=[],c=new Set([...Object.keys(a),...Object.keys(n)]);for(let l of c){let u=i?`${i}.${l}`:l,h=a[l],y=n[l];if(h===void 0&&y!==void 0)s.push({path:u,oldValue:void 0,newValue:y});else if(h!==void 0&&y===void 0)s.push({path:u,oldValue:h,newValue:void 0});else if(typeof h!==typeof y)s.push({path:u,oldValue:h,newValue:y});else if(typeof h==="object"&&h!==null)if(Array.isArray(h)&&Array.isArray(y)){if(JSON.stringify(h)!==JSON.stringify(y))s.push({path:u,oldValue:h,newValue:y})}else if(!Array.isArray(h)&&!Array.isArray(y)){let f=Ta(h,y,u);s.push(...f)}else s.push({path:u,oldValue:h,newValue:y});else if(h!==y)s.push({path:u,oldValue:h,newValue:y})}return s}function ir(a,n){let i={"AWS::S3::Bucket":new Set(["BucketName"]),"AWS::DynamoDB::Table":new Set(["TableName","KeySchema"]),"AWS::RDS::DBInstance":new Set(["DBInstanceIdentifier","DBName","Engine"]),"AWS::Lambda::Function":new Set(["FunctionName"]),"AWS::EC2::Instance":new Set(["ImageId","InstanceType","KeyName"]),"AWS::ECS::TaskDefinition":new Set(["Family","ContainerDefinitions"]),"AWS::ElastiCache::CacheCluster":new Set(["CacheNodeType","Engine"]),"AWS::CloudFront::Distribution":new Set([]),"AWS::Route53::HostedZone":new Set(["Name"]),"AWS::IAM::Role":new Set(["RoleName","Path"]),"AWS::KMS::Key":new Set(["KeyPolicy"]),"AWS::Cognito::UserPool":new Set(["UserPoolName"]),"AWS::OpenSearchService::Domain":new Set(["DomainName"])}[a];if(!i)return!1;for(let s of n){let c=s.path.split(".")[0];if(i.has(c))return!0}return!1}function sr(a){let n=[];for(let i of a){if(i.action==="remove"&&(i.resourceType==="AWS::RDS::DBInstance"||i.resourceType==="AWS::DynamoDB::Table"||i.resourceType==="AWS::ElastiCache::CacheCluster"))n.push(`Removing ${i.resourceType} ${i.logicalId} - data loss risk!`);if(i.action==="replace"&&(i.resourceType==="AWS::RDS::DBInstance"||i.resourceType==="AWS::DynamoDB::Table"))n.push(`Replacing ${i.resourceType} ${i.logicalId} - data loss risk!`);if((i.action==="remove"||i.action==="replace")&&i.resourceType==="AWS::S3::Bucket")n.push(`${i.action==="remove"?"Removing":"Replacing"} S3 bucket ${i.logicalId} - data loss risk!`);if(i.action==="replace"&&i.resourceType==="AWS::EC2::Instance")n.push(`Replacing EC2 instance ${i.logicalId} - downtime expected`);if(i.action==="update"&&i.resourceType==="AWS::EC2::SecurityGroup")n.push(`Updating security group ${i.logicalId} - may affect connectivity`);if((i.action==="update"||i.action==="replace")&&(i.resourceType==="AWS::IAM::Role"||i.resourceType==="AWS::IAM::Policy"))n.push(`Modifying IAM ${i.resourceType.split("::")[2]} ${i.logicalId} - may affect permissions`)}return n}function ky(a){let n=[];if(n.push(`=== Stack Update Analysis ===
|
|
19
19
|
`),a.summary.totalChanges===0)return n.push(`No changes detected.
|
|
20
20
|
`),n.join(`
|
|
21
21
|
`);if(n.push(`Total changes: ${a.summary.totalChanges}`),n.push(`Requires replacement: ${a.summary.requiresReplacement?"Yes":"No"}
|
|
@@ -2306,14 +2306,14 @@ function resolveTemplate(template, data) {
|
|
|
2306
2306
|
}
|
|
2307
2307
|
return result;
|
|
2308
2308
|
}
|
|
2309
|
-
`;class F{static LambdaCode={send:wa,receive:mr,deliveryStatus:dr};static createPinpointApp(a){return{[`${a.slug}PinpointApp`]:{Type:"AWS::Pinpoint::App",Properties:{Name:a.name||`${a.slug}-sms`}}}}static createSmsChannel(a){let n={ApplicationId:a.applicationId,Enabled:a.enabled!==!1};if(a.senderId)n.SenderId=a.senderId;if(a.shortCode)n.ShortCode=a.shortCode;return{[`${a.slug}SmsChannel`]:{Type:"AWS::Pinpoint::SMSChannel",Properties:n}}}static createSmsLambdaRole(a){return{[`${a.slug}SmsLambdaRole`]:{Type:"AWS::IAM::Role",Properties:{RoleName:`${a.slug}-sms-lambda-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],Policies:[{PolicyName:"SmsLambdaPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["mobiletargeting:SendMessages","mobiletargeting:GetSmsChannel"],Resource:"*"},{Effect:"Allow",Action:["sns:Publish"],Resource:"*"},{Effect:"Allow",Action:["dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:GetItem","dynamodb:DeleteItem"],Resource:"*"}]}}]}}}}static createSendLambda(a){return{[`${a.slug}SmsSendLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-sms-send`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:F.LambdaCode.send},Environment:{Variables:{PINPOINT_APP_ID:a.pinpointAppId,MESSAGE_LOG_TABLE:a.messageLogTable||"",SMS_SENDER_ID:a.senderId||"",SMS_ORIGINATION_NUMBER:a.originationNumber||""}}}}}}static createReceiveLambda(a){return{[`${a.slug}SmsReceiveLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-sms-receive`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:F.LambdaCode.receive},Environment:{Variables:{OPT_OUT_TABLE:a.optOutTable||"",MESSAGE_LOG_TABLE:a.messageLogTable||"",NOTIFICATION_TOPIC_ARN:a.notificationTopicArn||"",WEBHOOK_URL:a.webhookUrl||""}}}}}}static createDeliveryStatusLambda(a){return{[`${a.slug}SmsDeliveryStatusLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-sms-delivery-status`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:F.LambdaCode.deliveryStatus},Environment:{Variables:{MESSAGE_LOG_TABLE:a.messageLogTable||"",NOTIFICATION_TOPIC_ARN:a.notificationTopicArn||"",WEBHOOK_URL:a.webhookUrl||""}}}}}}static createMessageLogTable(a){return{[`${a.slug}SmsMessageLogTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${a.slug}-sms-messages`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createOptOutTable(a){return{[`${a.slug}SmsOptOutTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${a.slug}-sms-optouts`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}]}}}}static createNotificationTopic(a){return{[`${a.slug}SmsNotificationTopic`]:{Type:"AWS::SNS::Topic",Properties:{TopicName:`${a.slug}-sms-notifications`}}}}static createCompleteSetup(a){let n={},i={};Object.assign(n,F.createPinpointApp({slug:a.slug})),Object.assign(n,F.createSmsChannel({slug:a.slug,applicationId:{Ref:`${a.slug}PinpointApp`},senderId:a.senderId})),Object.assign(n,F.createSmsLambdaRole({slug:a.slug})),Object.assign(n,F.createMessageLogTable({slug:a.slug})),Object.assign(n,F.createOptOutTable({slug:a.slug})),Object.assign(n,F.createNotificationTopic({slug:a.slug}));let s={"Fn::GetAtt":[`${a.slug}SmsLambdaRole`,"Arn"]},c={Ref:`${a.slug}PinpointApp`},l={Ref:`${a.slug}SmsMessageLogTable`},u={Ref:`${a.slug}SmsOptOutTable`},h={Ref:`${a.slug}SmsNotificationTopic`};if(Object.assign(n,F.createSendLambda({slug:a.slug,roleArn:s,pinpointAppId:c,messageLogTable:l,senderId:a.senderId,originationNumber:a.originationNumber})),a.twoWayEnabled)Object.assign(n,F.createReceiveLambda({slug:a.slug,roleArn:s,optOutTable:u,messageLogTable:l,notificationTopicArn:h,webhookUrl:a.webhookUrl}));return Object.assign(n,F.createDeliveryStatusLambda({slug:a.slug,roleArn:s,messageLogTable:l,notificationTopicArn:h,webhookUrl:a.webhookUrl})),i[`${a.slug}PinpointAppId`]={Description:"Pinpoint application ID",Value:{Ref:`${a.slug}PinpointApp`}},i[`${a.slug}SmsSendLambdaArn`]={Description:"SMS send Lambda ARN",Value:{"Fn::GetAtt":[`${a.slug}SmsSendLambda`,"Arn"]}},i[`${a.slug}SmsNotificationTopicArn`]={Description:"SMS notification topic ARN",Value:{Ref:`${a.slug}SmsNotificationTopic`}},i[`${a.slug}SmsMessageLogTableName`]={Description:"SMS message log table name",Value:{Ref:`${a.slug}SmsMessageLogTable`}},{resources:n,outputs:i}}}function wt(a){return a.replace(/[^a-zA-Z0-9]/g," ").trim().split(/\s+/).map((n)=>n.charAt(0).toUpperCase()+n.slice(1)).join("")||"User"}function gr(a,n){let i=(a||n).replace(/^\/+|\/+$/g,"");if(!i||i.split("/").includes(".."))throw Error(`sftp: invalid homeDirectory for user ${n}`);return i}function hr(a){let n=a.storage;if(n?.type==="efs"){let s="fileSystemId"in n?n.fileSystemId:void 0;if(!s||typeof s==="string"&&!s.trim())throw Error("sftp: EFS storage requires fileSystemId, or a fileSystem name defined in infrastructure.fileSystem");return{type:"efs",fileSystemId:s,posixProfile:n.posixProfile}}let i=(n?.type==="s3"?n.bucket??a.bucket:a.bucket)?.trim();if(!i)throw Error("sftp: S3 storage requires bucket, or a storageBucket name defined in infrastructure.storage");return{type:"s3",bucket:i}}function yr(a,n,i){let s=n.posixProfile??i;if(!s)throw Error(`sftp: user ${a} requires a posixProfile (uid/gid) on an EFS-backed server`);for(let c of[s.uid,s.gid,...s.secondaryGids??[]])if(!Number.isInteger(c)||c<0||c>4294967295)throw Error(`sftp: user ${a} has an invalid posixProfile id ${c}`);return{Uid:s.uid,Gid:s.gid,...s.secondaryGids?.length?{SecondaryGids:s.secondaryGids}:{}}}function fr(a,n){return typeof a==="string"?`/${a}/${n}`:{"Fn::Sub":[`/\${FileSystemId}/${n}`,{FileSystemId:a}]}}function Sr(a){return typeof a==="string"?{"Fn::Sub":"arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}".replace("${FileSystemId}",a)}:{"Fn::Sub":["arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}",{FileSystemId:a}]}}class nd{static create(a){let n=hr(a),i=n.type==="efs"?"EFS":"S3",s=a.endpointType??"PUBLIC";if(s==="VPC"&&(!a.endpointDetails?.vpcId||!a.endpointDetails.subnetIds.length))throw Error("sftp: VPC endpoints require endpointDetails.vpcId and at least one subnet");let c=`${wt(a.slug)}${wt(a.environment)}Sftp`,l=`${c}Server`,u={},h;if(a.logging!==!1){let y=`${c}LoggingRole`;u[y]={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"transfer.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"TransferLogging",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:DescribeLogStreams","logs:PutLogEvents"],Resource:"arn:aws:logs:*:*:log-group:/aws/transfer/*"}]}}]}},h={"Fn::GetAtt":[y,"Arn"]}}u[l]={Type:"AWS::Transfer::Server",Properties:{Domain:i,EndpointType:s,IdentityProviderType:"SERVICE_MANAGED",Protocols:["SFTP"],...s==="VPC"?{EndpointDetails:{VpcId:a.endpointDetails.vpcId,SubnetIds:a.endpointDetails.subnetIds,...a.endpointDetails.securityGroupIds?.length?{SecurityGroupIds:a.endpointDetails.securityGroupIds}:{},...a.endpointDetails.addressAllocationIds?.length?{AddressAllocationIds:a.endpointDetails.addressAllocationIds}:{}}}:{},...a.securityPolicyName?{SecurityPolicyName:a.securityPolicyName}:{},...h?{LoggingRole:h}:{},Tags:[{Key:"Project",Value:a.slug},{Key:"Environment",Value:a.environment},{Key:"ManagedBy",Value:"ts-cloud"}]}};for(let[y,f]of Object.entries(a.users)){if(!/^[a-zA-Z0-9_.@-]{3,100}$/.test(y))throw Error(`sftp: invalid username ${y}`);if(!f.sshPublicKeys.length)throw Error(`sftp: user ${y} requires at least one SSH public key`);let S=wt(y),b=gr(f.homeDirectory,y),C=`${c}${S}User`,T=f.roleArn;if(!T){let v=`${c}${S}Role`,w;if(n.type==="efs")w=[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:DescribeMountTargets"],Resource:Sr(n.fileSystemId)}];else{let R=`arn:aws:s3:::${n.bucket}`;w=[{Effect:"Allow",Action:["s3:ListBucket","s3:GetBucketLocation"],Resource:R,Condition:{StringLike:{"s3:prefix":[b,`${b}/*`]}}},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:GetObjectVersion"],Resource:`${R}/${b}/*`}]}u[v]={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"transfer.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"SftpHomeDirectory",PolicyDocument:{Version:"2012-10-17",Statement:w}}]}},T={"Fn::GetAtt":[v,"Arn"]}}u[C]={Type:"AWS::Transfer::User",DependsOn:[l],Properties:{ServerId:{Ref:l},UserName:y,Role:T,HomeDirectoryType:"PATH",HomeDirectory:n.type==="efs"?fr(n.fileSystemId,b):`/${n.bucket}/${b}`,...n.type==="efs"?{PosixProfile:yr(y,f,n.posixProfile)}:{},SshPublicKeys:f.sshPublicKeys}}}return{resources:u,serverLogicalId:l,domain:i}}}class be{static createBedrockRole(a,n){let{slug:i,environment:s,name:c,models:l=["*"],allowStreaming:u=!0}=n,h=c||r({slug:i,environment:s,resourceType:"bedrock-role"}),y=t(h),f=["bedrock:InvokeModel"];if(u)f.push("bedrock:InvokeModelWithResponseStream");let S=l.map((b)=>b==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${b}`);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:h,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:a},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:`${h}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:f,Resource:S}]}}],Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}},logicalId:y}}static createBedrockPolicy(a){let{slug:n,environment:i,name:s,models:c=["*"],allowInvoke:l=!0,allowStreaming:u=!0,allowAsync:h=!1}=a,y=s||r({slug:n,environment:i,resourceType:"bedrock-policy"}),f=t(y),S=[];if(l)S.push("bedrock:InvokeModel");if(u)S.push("bedrock:InvokeModelWithResponseStream");if(h)S.push("bedrock:InvokeModelAsync");let b=c.map((C)=>C==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${C}`);return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:y,PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"BedrockModelInvocation",Effect:"Allow",Action:S,Resource:b}]}}},logicalId:f}}static enableBedrockForLambda(a){return be.createBedrockRole("lambda.amazonaws.com",a)}static enableBedrockForEcs(a){return be.createBedrockRole("ecs-tasks.amazonaws.com",a)}static enableBedrockForEc2(a){return be.createBedrockRole("ec2.amazonaws.com",a)}static addBedrockPermissions(a,n=["*"],i=!0){let s=["bedrock:InvokeModel"];if(i)s.push("bedrock:InvokeModelWithResponseStream");let c=n.map((l)=>l==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${l}`);if(!a.Properties.Policies)a.Properties.Policies=[];return a.Properties.Policies.push({PolicyName:"bedrock-permissions",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:s,Resource:c}]}}),a}static Models={Claude3_5_Sonnet:"anthropic.claude-3-5-sonnet-20241022-v2:0",Claude3_5_Haiku:"anthropic.claude-3-5-haiku-20241022-v1:0",Claude3_Opus:"anthropic.claude-3-opus-20240229-v1:0",Claude3_Sonnet:"anthropic.claude-3-sonnet-20240229-v1:0",Claude3_Haiku:"anthropic.claude-3-haiku-20240307-v1:0",TitanTextG1Express:"amazon.titan-text-express-v1",TitanTextG1Lite:"amazon.titan-text-lite-v1",TitanEmbedG1Text:"amazon.titan-embed-text-v1",TitanImageG1:"amazon.titan-image-generator-v1",JurassicUltra:"ai21.j2-ultra-v1",JurassicMid:"ai21.j2-mid-v1",CommandText:"cohere.command-text-v14",CommandLight:"cohere.command-light-text-v14",EmbedEnglish:"cohere.embed-english-v3",EmbedMultilingual:"cohere.embed-multilingual-v3",Llama3_2_1B:"meta.llama3-2-1b-instruct-v1:0",Llama3_2_3B:"meta.llama3-2-3b-instruct-v1:0",Llama3_2_11B:"meta.llama3-2-11b-instruct-v1:0",Llama3_2_90B:"meta.llama3-2-90b-instruct-v1:0",Llama3_1_8B:"meta.llama3-1-8b-instruct-v1:0",Llama3_1_70B:"meta.llama3-1-70b-instruct-v1:0",Llama3_1_405B:"meta.llama3-1-405b-instruct-v1:0",Mistral7B:"mistral.mistral-7b-instruct-v0:2",Mixtral8x7B:"mistral.mixtral-8x7b-instruct-v0:1",MistralLarge:"mistral.mistral-large-2402-v1:0",StableDiffusionXL:"stability.stable-diffusion-xl-v1"};static ModelGroups={AllClaude:["anthropic.claude-3-5-sonnet-20241022-v2:0","anthropic.claude-3-5-haiku-20241022-v1:0","anthropic.claude-3-opus-20240229-v1:0","anthropic.claude-3-sonnet-20240229-v1:0","anthropic.claude-3-haiku-20240307-v1:0"],AllTitan:["amazon.titan-text-express-v1","amazon.titan-text-lite-v1","amazon.titan-embed-text-v1","amazon.titan-image-generator-v1"],AllLlama:["meta.llama3-2-1b-instruct-v1:0","meta.llama3-2-3b-instruct-v1:0","meta.llama3-2-11b-instruct-v1:0","meta.llama3-2-90b-instruct-v1:0","meta.llama3-1-8b-instruct-v1:0","meta.llama3-1-70b-instruct-v1:0","meta.llama3-1-405b-instruct-v1:0"],TextModels:["anthropic.claude-3-5-sonnet-20241022-v2:0","anthropic.claude-3-5-haiku-20241022-v1:0","amazon.titan-text-express-v1","meta.llama3-2-11b-instruct-v1:0","mistral.mistral-7b-instruct-v0:2"],EmbeddingModels:["amazon.titan-embed-text-v1","cohere.embed-english-v3","cohere.embed-multilingual-v3"],ImageModels:["amazon.titan-image-generator-v1","stability.stable-diffusion-xl-v1"]}}class Ft{static createPostgres(a){return Ft.createRDSInstance("postgres","16.2",a)}static createMysql(a){return Ft.createRDSInstance("mysql","8.0.35",a)}static createRDSInstance(a,n,i){let{slug:s,environment:c,instanceClass:l="db.t3.micro",allocatedStorage:u=20,storageType:h="gp3",masterUsername:y="admin",masterPassword:f,databaseName:S,subnetIds:b,securityGroupIds:C,encrypted:T=!0,kmsKeyId:v,multiAz:w=!1,backupRetentionDays:R=7,publiclyAccessible:k=!1,enableCloudwatchLogs:W=!0,deletionProtection:P=!0}=i,V=r({slug:s,environment:c,resourceType:`${a}-db`}),B=t(V),j,Z;if(b&&b.length>0){let ee=r({slug:s,environment:c,resourceType:"db-subnet-group"});Z=t(ee),j={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupName:ee,DBSubnetGroupDescription:`Subnet group for ${V}`,SubnetIds:b,Tags:[{Key:"Name",Value:ee},{Key:"Environment",Value:c}]}}}let K={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:V,DBInstanceClass:l,Engine:a,EngineVersion:n,MasterUsername:y,MasterUserPassword:f,AllocatedStorage:u,StorageType:h,StorageEncrypted:T,MultiAZ:w,BackupRetentionPeriod:R,PubliclyAccessible:k,DeletionProtection:P,Tags:[{Key:"Name",Value:V},{Key:"Environment",Value:c}]}};if(S)K.Properties.DBName=S;if(v)K.Properties.KmsKeyId=v;if(Z)K.Properties.DBSubnetGroupName=N.Ref(Z);if(C&&C.length>0)K.Properties.VPCSecurityGroups=C;if(W)K.Properties.EnableCloudwatchLogsExports=a==="postgres"?["postgresql"]:["error","general","slowquery"];return{dbInstance:K,subnetGroup:j,logicalId:B,subnetGroupId:Z}}static createReadReplica(a,n){let{slug:i,environment:s,instanceClass:c="db.t3.micro",securityGroupIds:l,publiclyAccessible:u=!1}=n,h=r({slug:i,environment:s,resourceType:"db-replica"}),y=t(h),f={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:h,DBInstanceClass:c,SourceDBInstanceIdentifier:N.Ref(a),PubliclyAccessible:u,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s},{Key:"Type",Value:"ReadReplica"}]}};if(l&&l.length>0)f.Properties.VPCSecurityGroups=l;return{replica:f,logicalId:y}}static createParameterGroup(a,n,i){let{slug:s,environment:c,parameters:l={}}=i,u=r({slug:s,environment:c,resourceType:"db-params"}),h=t(u),y=a==="postgres"?`postgres${n.split(".")[0]}`:`mysql${n.split(".")[0]}.${n.split(".")[1]}`;return{parameterGroup:{Type:"AWS::RDS::DBParameterGroup",Properties:{DBParameterGroupName:u,Description:`Parameter group for ${u}`,Family:y,Parameters:l,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:c}]}},logicalId:h}}static enableBackup(a,n=7){return a.Properties.BackupRetentionPeriod=n,a}static createTable(a){let{slug:n,environment:i,tableName:s,partitionKey:c,sortKey:l,billingMode:u="PAY_PER_REQUEST",readCapacity:h=5,writeCapacity:y=5,streamEnabled:f=!1,streamViewType:S="NEW_AND_OLD_IMAGES",encrypted:b=!0,kmsKeyId:C,pointInTimeRecovery:T=!0,ttlAttribute:v}=a,w=s||r({slug:n,environment:i,resourceType:"table"}),R=t(w),k=[{AttributeName:c.name,AttributeType:c.type}];if(l)k.push({AttributeName:l.name,AttributeType:l.type});let W=[{AttributeName:c.name,KeyType:"HASH"}];if(l)W.push({AttributeName:l.name,KeyType:"RANGE"});let P={Type:"AWS::DynamoDB::Table",Properties:{TableName:w,BillingMode:u,AttributeDefinitions:k,KeySchema:W,Tags:[{Key:"Name",Value:w},{Key:"Environment",Value:i}]}};if(u==="PROVISIONED")P.Properties.ProvisionedThroughput={ReadCapacityUnits:h,WriteCapacityUnits:y};if(f)P.Properties.StreamSpecification={StreamViewType:S};if(b)P.Properties.SSESpecification={SSEEnabled:!0,SSEType:C?"KMS":"AES256",KMSMasterKeyId:C};if(T)P.Properties.PointInTimeRecoverySpecification={PointInTimeRecoveryEnabled:!0};if(v)P.Properties.TimeToLiveSpecification={AttributeName:v,Enabled:!0};return{table:P,logicalId:R}}static addGlobalSecondaryIndex(a,n){let{indexName:i,partitionKey:s,sortKey:c,projectionType:l="ALL",nonKeyAttributes:u,readCapacity:h=5,writeCapacity:y=5}=n;if(!a.Properties.AttributeDefinitions.some((b)=>b.AttributeName===s.name))a.Properties.AttributeDefinitions.push({AttributeName:s.name,AttributeType:s.type});if(c&&!a.Properties.AttributeDefinitions.some((b)=>b.AttributeName===c.name))a.Properties.AttributeDefinitions.push({AttributeName:c.name,AttributeType:c.type});let f=[{AttributeName:s.name,KeyType:"HASH"}];if(c)f.push({AttributeName:c.name,KeyType:"RANGE"});let S={IndexName:i,KeySchema:f,Projection:{ProjectionType:l,NonKeyAttributes:l==="INCLUDE"?u:void 0},ProvisionedThroughput:void 0};if(a.Properties.BillingMode==="PROVISIONED")S.ProvisionedThroughput={ReadCapacityUnits:h,WriteCapacityUnits:y};if(!a.Properties.GlobalSecondaryIndexes)a.Properties.GlobalSecondaryIndexes=[];return a.Properties.GlobalSecondaryIndexes.push(S),a}static enableStreams(a,n="NEW_AND_OLD_IMAGES"){return a.Properties.StreamSpecification={StreamViewType:n},a}static InstanceClasses={T3_Micro:"db.t3.micro",T3_Small:"db.t3.small",T3_Medium:"db.t3.medium",T3_Large:"db.t3.large",T4g_Micro:"db.t4g.micro",T4g_Small:"db.t4g.small",T4g_Medium:"db.t4g.medium",M5_Large:"db.m5.large",M5_XLarge:"db.m5.xlarge",M5_2XLarge:"db.m5.2xlarge",R5_Large:"db.r5.large",R5_XLarge:"db.r5.xlarge",R5_2XLarge:"db.r5.2xlarge"}}class Hs{static createRedis(a){let{slug:n,environment:i,nodeType:s="cache.t3.micro",engineVersion:c="7.1",port:l=6379,subnetIds:u,securityGroupIds:h,numCacheClusters:y=2,automaticFailover:f=!0,multiAz:S=!0,clusterMode:b=!1,numNodeGroups:C=1,replicasPerNodeGroup:T=1,atRestEncryption:v=!0,transitEncryption:w=!0,authToken:R,kmsKeyId:k,snapshotRetentionDays:W=7,snapshotWindow:P,maintenanceWindow:V}=a,B=r({slug:n,environment:i,resourceType:"redis"}),j=t(B),Z,K;if(u&&u.length>0){let te=r({slug:n,environment:i,resourceType:"cache-subnet-group"});K=t(te),Z={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:te,Description:`Subnet group for ${B}`,SubnetIds:u,Tags:[{Key:"Name",Value:te},{Key:"Environment",Value:i}]}}}let ee={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:B,ReplicationGroupDescription:`Redis cluster for ${n} ${i}`,Engine:"redis",EngineVersion:c,CacheNodeType:s,Port:l,AutomaticFailoverEnabled:f,MultiAZEnabled:S,AtRestEncryptionEnabled:v,TransitEncryptionEnabled:w,SnapshotRetentionLimit:W,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:B},{Key:"Environment",Value:i}]}};if(b)ee.Properties.NumNodeGroups=C,ee.Properties.ReplicasPerNodeGroup=T;else ee.Properties.NumCacheClusters=y;if(R)ee.Properties.AuthToken=R;if(k)ee.Properties.KmsKeyId=k;if(K)ee.Properties.CacheSubnetGroupName=N.Ref(K);if(h&&h.length>0)ee.Properties.SecurityGroupIds=h;if(P)ee.Properties.SnapshotWindow=P;if(V)ee.Properties.PreferredMaintenanceWindow=V;return{replicationGroup:ee,subnetGroup:Z,logicalId:j,subnetGroupId:K}}static createMemcached(a){let{slug:n,environment:i,nodeType:s="cache.t3.micro",engineVersion:c="1.6.22",port:l=11211,numCacheNodes:u=2,subnetIds:h,securityGroupIds:y,azMode:f="cross-az",preferredAzs:S,maintenanceWindow:b}=a,C=r({slug:n,environment:i,resourceType:"memcached"}),T=t(C),v,w;if(h&&h.length>0){let k=r({slug:n,environment:i,resourceType:"cache-subnet-group"});w=t(k),v={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:k,Description:`Subnet group for ${C}`,SubnetIds:h,Tags:[{Key:"Name",Value:k},{Key:"Environment",Value:i}]}}}let R={Type:"AWS::ElastiCache::CacheCluster",Properties:{ClusterName:C,CacheNodeType:s,Engine:"memcached",EngineVersion:c,NumCacheNodes:u,Port:l,AZMode:f,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:C},{Key:"Environment",Value:i}]}};if(w)R.Properties.CacheSubnetGroupName=N.Ref(w);if(y&&y.length>0)R.Properties.VpcSecurityGroupIds=y;if(S&&S.length>0)R.Properties.PreferredAvailabilityZones=S;if(b)R.Properties.PreferredMaintenanceWindow=b;return{cluster:R,subnetGroup:v,logicalId:T,subnetGroupId:w}}static enableClusterMode(a,n=3,i=2){return delete a.Properties.NumCacheClusters,a.Properties.NumNodeGroups=n,a.Properties.ReplicasPerNodeGroup=i,a}static createRedisParameterGroup(a,n){let{slug:i,environment:s,parameters:c={}}=n,l=r({slug:i,environment:s,resourceType:"redis-params"}),u=t(l);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`redis${a.split(".")[0]}.x`,Description:`Parameter group for ${l}`,Properties:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s}]}},logicalId:u}}static createMemcachedParameterGroup(a,n){let{slug:i,environment:s,parameters:c={}}=n,l=r({slug:i,environment:s,resourceType:"memcached-params"}),u=t(l);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`memcached${a.split(".")[0]}.${a.split(".")[1]}`,Description:`Parameter group for ${l}`,Properties:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s}]}},logicalId:u}}static NodeTypes={T3_Micro:"cache.t3.micro",T3_Small:"cache.t3.small",T3_Medium:"cache.t3.medium",T4g_Micro:"cache.t4g.micro",T4g_Small:"cache.t4g.small",T4g_Medium:"cache.t4g.medium",M5_Large:"cache.m5.large",M5_XLarge:"cache.m5.xlarge",M5_2XLarge:"cache.m5.2xlarge",R5_Large:"cache.r5.large",R5_XLarge:"cache.r5.xlarge",R5_2XLarge:"cache.r5.2xlarge",R5_4XLarge:"cache.r5.4xlarge",R6g_Large:"cache.r6g.large",R6g_XLarge:"cache.r6g.xlarge",R6g_2XLarge:"cache.r6g.2xlarge"}}class J{static createUser(a){let{slug:n,environment:i,userName:s,groups:c,managedPolicyArns:l}=a,u=s||r({slug:n,environment:i,resourceType:"user"}),h=t(u),y={Type:"AWS::IAM::User",Properties:{UserName:u,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:i}]}};if(c&&c.length>0)y.Properties.Groups=c;if(l&&l.length>0)y.Properties.ManagedPolicyArns=l;return{user:y,logicalId:h}}static createRole(a){let{slug:n,environment:i,roleName:s,servicePrincipal:c,awsPrincipal:l,managedPolicyArns:u}=a,h=s||r({slug:n,environment:i,resourceType:"role"}),y=t(h),f={};if(c)f.Service=c;if(l)f.AWS=l;let S={Type:"AWS::IAM::Role",Properties:{RoleName:h,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:f,Action:"sts:AssumeRole"}]},Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:i}]}};if(u&&u.length>0)S.Properties.ManagedPolicyArns=u;return{role:S,logicalId:y}}static createGroup(a){let{slug:n,environment:i,groupName:s,managedPolicyArns:c}=a,l=s||r({slug:n,environment:i,resourceType:"group"}),u=t(l),h={Type:"AWS::IAM::Group",Properties:{GroupName:l}};if(c&&c.length>0)h.Properties.ManagedPolicyArns=c;return{group:h,logicalId:u}}static createPolicy(a){let{slug:n,environment:i,policyName:s,description:c,statements:l}=a,u=s||r({slug:n,environment:i,resourceType:"policy"}),h=t(u),y=l.map((f)=>({Sid:f.sid,Effect:f.effect||"Allow",Action:f.actions,Resource:f.resources,Condition:f.conditions}));return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:u,Description:c||`Managed policy for ${u}`,PolicyDocument:{Version:"2012-10-17",Statement:y}}},logicalId:h}}static attachPolicyToRole(a,n){if(!a.Properties.ManagedPolicyArns)a.Properties.ManagedPolicyArns=[];if(!a.Properties.ManagedPolicyArns.includes(n))a.Properties.ManagedPolicyArns.push(n);return a}static attachPolicyToUser(a,n){if(!a.Properties.ManagedPolicyArns)a.Properties.ManagedPolicyArns=[];if(!a.Properties.ManagedPolicyArns.includes(n))a.Properties.ManagedPolicyArns.push(n);return a}static attachPolicyToGroup(a,n){if(!a.Properties.ManagedPolicyArns)a.Properties.ManagedPolicyArns=[];if(!a.Properties.ManagedPolicyArns.includes(n))a.Properties.ManagedPolicyArns.push(n);return a}static addInlinePolicyToRole(a,n,i){if(!a.Properties.Policies)a.Properties.Policies=[];let s=i.map((c)=>({Effect:c.effect||"Allow",Action:c.actions,Resource:c.resources}));return a.Properties.Policies.push({PolicyName:n,PolicyDocument:{Version:"2012-10-17",Statement:s}}),a}static addInlinePolicyToUser(a,n,i){if(!a.Properties.Policies)a.Properties.Policies=[];let s=i.map((c)=>({Effect:c.effect||"Allow",Action:c.actions,Resource:c.resources}));return a.Properties.Policies.push({PolicyName:n,PolicyDocument:{Version:"2012-10-17",Statement:s}}),a}static createAccessKey(a,n){let{slug:i,environment:s,status:c="Active"}=n,l=r({slug:i,environment:s,resourceType:"access-key"}),u=t(l);return{accessKey:{Type:"AWS::IAM::AccessKey",Properties:{UserName:N.Ref(a),Status:c}},logicalId:u}}static createInstanceProfile(a,n){let{slug:i,environment:s,profileName:c}=n,l=c||r({slug:i,environment:s,resourceType:"instance-profile"}),u=t(l);return{instanceProfile:{Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:l,Roles:[N.Ref(a)]}},logicalId:u}}static ManagedPolicies={AdministratorAccess:"arn:aws:iam::aws:policy/AdministratorAccess",PowerUserAccess:"arn:aws:iam::aws:policy/PowerUserAccess",ReadOnlyAccess:"arn:aws:iam::aws:policy/ReadOnlyAccess",S3FullAccess:"arn:aws:iam::aws:policy/AmazonS3FullAccess",S3ReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess",DynamoDBFullAccess:"arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess",DynamoDBReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonDynamoDBReadOnlyAccess",RDSFullAccess:"arn:aws:iam::aws:policy/AmazonRDSFullAccess",RDSReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonRDSReadOnlyAccess",LambdaFullAccess:"arn:aws:iam::aws:policy/AWSLambda_FullAccess",LambdaReadOnlyAccess:"arn:aws:iam::aws:policy/AWSLambda_ReadOnlyAccess",LambdaBasicExecutionRole:"arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",LambdaVPCAccessExecutionRole:"arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole",EC2FullAccess:"arn:aws:iam::aws:policy/AmazonEC2FullAccess",EC2ReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess",EC2ContainerRegistryReadOnly:"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly",EC2ContainerRegistryPowerUser:"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPowerUser",ECSTaskExecutionRole:"arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy",ECSFullAccess:"arn:aws:iam::aws:policy/AmazonECS_FullAccess",CloudWatchFullAccess:"arn:aws:iam::aws:policy/CloudWatchFullAccess",CloudWatchLogsFullAccess:"arn:aws:iam::aws:policy/CloudWatchLogsFullAccess",SESFullAccess:"arn:aws:iam::aws:policy/AmazonSESFullAccess",SNSFullAccess:"arn:aws:iam::aws:policy/AmazonSNSFullAccess",SQSFullAccess:"arn:aws:iam::aws:policy/AmazonSQSFullAccess",SecretsManagerReadWrite:"arn:aws:iam::aws:policy/SecretsManagerReadWrite"};static ServicePrincipals={Lambda:"lambda.amazonaws.com",EC2:"ec2.amazonaws.com",ECS:"ecs.amazonaws.com",ECSTaskExecution:"ecs-tasks.amazonaws.com",APIGateway:"apigateway.amazonaws.com",Events:"events.amazonaws.com",States:"states.amazonaws.com",CodeBuild:"codebuild.amazonaws.com",CodeDeploy:"codedeploy.amazonaws.com",CloudFormation:"cloudformation.amazonaws.com"};static createCiCdUser(a){let{slug:n,environment:i,permissions:s,createAccessKey:c=!0}=a,l={},u=[];if(s.s3Buckets&&s.s3Buckets.length>0)u.push({sid:"S3Access",actions:["s3:GetBucketLocation","s3:ListBucket","s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucketMultipartUploads","s3:AbortMultipartUpload"],resources:[...s.s3Buckets,...s.s3Buckets.map((T)=>`${T}/*`)]});if(s.cloudFrontDistributions&&s.cloudFrontDistributions.length>0)u.push({sid:"CloudFrontAccess",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations","cloudfront:GetDistribution"],resources:s.cloudFrontDistributions});if(s.ecrRepositories&&s.ecrRepositories.length>0)u.push({sid:"ECRAccess",actions:["ecr:GetAuthorizationToken","ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:GetRepositoryPolicy","ecr:DescribeRepositories","ecr:ListImages","ecr:DescribeImages","ecr:BatchGetImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:PutImage"],resources:s.ecrRepositories}),u.push({sid:"ECRLogin",actions:["ecr:GetAuthorizationToken"],resources:"*"});if(s.ecsServices&&s.ecsServices.length>0)u.push({sid:"ECSAccess",actions:["ecs:DescribeServices","ecs:DescribeTaskDefinition","ecs:DescribeTasks","ecs:ListTasks","ecs:RegisterTaskDefinition","ecs:UpdateService","ecs:RunTask","ecs:StopTask"],resources:s.ecsServices}),u.push({sid:"ECSTaskDefinitions",actions:["ecs:RegisterTaskDefinition","ecs:DeregisterTaskDefinition"],resources:"*"}),u.push({sid:"ECSPassRole",actions:["iam:PassRole"],resources:"*",conditions:{StringLike:{"iam:PassedToService":"ecs-tasks.amazonaws.com"}}});if(s.cloudFormationStacks&&s.cloudFormationStacks.length>0)u.push({sid:"CloudFormationAccess",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:DescribeStackResources","cloudformation:GetTemplate","cloudformation:ListStackResources","cloudformation:ValidateTemplate"],resources:s.cloudFormationStacks});if(s.lambdaFunctions&&s.lambdaFunctions.length>0)u.push({sid:"LambdaAccess",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion","lambda:UpdateAlias","lambda:CreateAlias"],resources:s.lambdaFunctions});if(s.secretsManagerSecrets&&s.secretsManagerSecrets.length>0)u.push({sid:"SecretsManagerAccess",actions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],resources:s.secretsManagerSecrets});let{policy:h,logicalId:y}=J.createPolicy({slug:n,environment:i,policyName:r({slug:n,environment:i,resourceType:"cicd-policy"}),description:`CI/CD deployment policy for ${n} (${i})`,statements:u});l[y]=h;let{user:f,logicalId:S}=J.createUser({slug:n,environment:i,userName:r({slug:n,environment:i,resourceType:"cicd-user"}),managedPolicyArns:[N.Ref(y)]});l[S]=f;let b,C;if(c){let T=J.createAccessKey(S,{slug:n,environment:i});b=T.accessKey,C=T.logicalId,l[C]=b}return{user:f,accessKey:b,policy:h,userLogicalId:S,accessKeyLogicalId:C,policyLogicalId:y,resources:l}}static createCrossAccountRole(a){let{slug:n,environment:i,trustedAccountIds:s,externalId:c,permissions:l,maxSessionDuration:u=3600}=a,h={},{policy:y,logicalId:f}=J.createPolicy({slug:n,environment:i,policyName:r({slug:n,environment:i,resourceType:"cross-account-policy"}),description:`Cross-account access policy for ${n} (${i})`,statements:l});h[f]=y;let S=r({slug:n,environment:i,resourceType:"cross-account-role"}),b=t(S),C={};if(c)C.StringEquals={"sts:ExternalId":c};let T={Type:"AWS::IAM::Role",Properties:{RoleName:S,MaxSessionDuration:u,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:s.map((v)=>`arn:aws:iam::${v}:root`)},Action:"sts:AssumeRole",...Object.keys(C).length>0?{Condition:C}:{}}]},ManagedPolicyArns:[N.Ref(f)],Tags:[{Key:"Name",Value:S},{Key:"Environment",Value:i},{Key:"Purpose",Value:"Cross-Account Access"}]}};return h[b]=T,{role:T,policy:y,roleLogicalId:b,policyLogicalId:f,resources:h}}static createCliUser(a){let{slug:n,environment:i,permissions:s="readonly"}=a,c={},l=[],u=[];switch(s){case"readonly":u=[J.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=[J.ManagedPolicies.AdministratorAccess];break}let h,y;if(l.length>0){let T=J.createPolicy({slug:n,environment:i,policyName:r({slug:n,environment:i,resourceType:"cli-policy"}),description:`CLI access policy for ${n} (${i})`,statements:l});h=T.policy,y=T.logicalId,c[y]=h,u=[N.Ref(y)]}let{user:f,logicalId:S}=J.createUser({slug:n,environment:i,userName:r({slug:n,environment:i,resourceType:"cli-user"}),managedPolicyArns:u});c[S]=f;let{accessKey:b,logicalId:C}=J.createAccessKey(S,{slug:n,environment:i});return c[C]=b,{user:f,accessKey:b,policy:h,userLogicalId:S,accessKeyLogicalId:C,policyLogicalId:y,resources:c}}static CiCdPolicies={s3Deployment:(a)=>[{sid:"S3ListBuckets",actions:["s3:ListBucket","s3:GetBucketLocation"],resources:a},{sid:"S3Objects",actions:["s3:GetObject","s3:PutObject","s3:DeleteObject"],resources:a.map((n)=>`${n}/*`)}],cloudFrontInvalidation:(a)=>[{sid:"CloudFrontInvalidation",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations"],resources:a}],ecsDeployment:()=>[{sid:"ECSServices",actions:["ecs:DescribeServices","ecs:UpdateService","ecs:DescribeTaskDefinition","ecs:RegisterTaskDefinition"],resources:"*"},{sid:"ECSPassRole",actions:["iam:PassRole"],resources:"*",conditions:{StringLike:{"iam:PassedToService":"ecs-tasks.amazonaws.com"}}}],ecrPush:(a)=>[{sid:"ECRAuth",actions:["ecr:GetAuthorizationToken"],resources:"*"},{sid:"ECRPush",actions:["ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:PutImage"],resources:a}],lambdaDeployment:(a)=>[{sid:"LambdaDeploy",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion"],resources:a}],cloudFormationDeployment:(a)=>[{sid:"CloudFormationDeploy",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate"],resources:a}]}}class id{static createRestApi(a){let{slug:n,environment:i,name:s,description:c,endpointType:l="REGIONAL",binaryMediaTypes:u,compressionSize:h}=a,y=s||r({slug:n,environment:i,resourceType:"rest-api"}),f=t(y),S={Type:"AWS::ApiGateway::RestApi",Properties:{Name:y,Description:c||`REST API for ${n} ${i}`,EndpointConfiguration:{Types:[l]},Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:i}]}};if(u&&u.length>0)S.Properties.BinaryMediaTypes=u;if(h!==void 0)S.Properties.MinimumCompressionSize=h;return{restApi:S,logicalId:f}}static createHttpApi(a){let{slug:n,environment:i,name:s,description:c,corsEnabled:l=!0,corsOrigins:u=["*"],corsMethods:h=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],corsHeaders:y=["*"],corsMaxAge:f=86400,corsAllowCredentials:S=!1}=a,b=s||r({slug:n,environment:i,resourceType:"http-api"}),C=t(b),T={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:b,Description:c||`HTTP API for ${n} ${i}`,ProtocolType:"HTTP",Tags:{Name:b,Environment:i}}};if(l)T.Properties.CorsConfiguration={AllowOrigins:u,AllowMethods:h,AllowHeaders:y,MaxAge:f,AllowCredentials:S};return{httpApi:T,logicalId:C}}static createWebSocketApi(a){let{slug:n,environment:i,name:s,description:c}=a,l=s||r({slug:n,environment:i,resourceType:"ws-api"}),u=t(l);return{webSocketApi:{Type:"AWS::ApiGatewayV2::Api",Properties:{Name:l,Description:c||`WebSocket API for ${n} ${i}`,ProtocolType:"WEBSOCKET",Tags:{Name:l,Environment:i}}},logicalId:u}}static createDeployment(a,n){let{slug:i,environment:s,description:c}=n,l=r({slug:i,environment:s,resourceType:"api-deployment"}),u=t(l);return{deployment:{Type:"AWS::ApiGateway::Deployment",Properties:{RestApiId:N.Ref(a),Description:c||`Deployment for ${l}`}},logicalId:u}}static createStage(a,n,i){let{slug:s,environment:c,stageName:l,description:u,cacheEnabled:h=!1,cacheSize:y="0.5",variables:f,throttling:S}=i,b=r({slug:s,environment:c,resourceType:"api-stage"}),C=t(b),T={Type:"AWS::ApiGateway::Stage",Properties:{StageName:l||c,RestApiId:N.Ref(a),DeploymentId:N.Ref(n),Description:u,CacheClusterEnabled:h,Tags:[{Key:"Name",Value:b},{Key:"Environment",Value:c}]}};if(h)T.Properties.CacheClusterSize=y;if(f)T.Properties.Variables=f;if(S)T.Properties.MethodSettings=[{HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:S.burstLimit,ThrottlingRateLimit:S.rateLimit}];return{stage:T,logicalId:C}}static createAuthorizer(a,n){let{slug:i,environment:s,name:c,type:l,functionArn:u,identitySource:h,userPoolArns:y,ttl:f=300}=n,S=c||r({slug:i,environment:s,resourceType:"api-authorizer"}),b=t(S),C={Type:"AWS::ApiGateway::Authorizer",Properties:{Name:S,Type:l,RestApiId:N.Ref(a),AuthorizerResultTtlInSeconds:f}};if(l==="TOKEN"||l==="REQUEST"){if(!u)throw Error("Lambda authorizer requires functionArn");C.Properties.AuthorizerUri=u,C.Properties.IdentitySource=h||"method.request.header.Authorization"}if(l==="COGNITO_USER_POOLS"){if(!y||y.length===0)throw Error("Cognito authorizer requires userPoolArns");C.Properties.ProviderARNs=y,C.Properties.IdentitySource=h||"method.request.header.Authorization"}return{authorizer:C,logicalId:b}}static setCors(a,n={}){let{origins:i=["*"],methods:s=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],headers:c=["*"],maxAge:l=86400,allowCredentials:u=!1}=n;return a.Properties.CorsConfiguration={AllowOrigins:i,AllowMethods:s,AllowHeaders:c,MaxAge:l,AllowCredentials:u},a}static addThrottling(a,n=5000,i=1e4){if(!a.Properties.MethodSettings)a.Properties.MethodSettings=[];return a.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:n,ThrottlingRateLimit:i}),a}static enableCaching(a,n="0.5",i=300){if(a.Properties.CacheClusterEnabled=!0,a.Properties.CacheClusterSize=n,!a.Properties.MethodSettings)a.Properties.MethodSettings=[];return a.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",CachingEnabled:!0,CacheTtlInSeconds:i}),a}static CacheSizes={Small:"0.5",Medium:"1.6",Large:"6.1",XLarge:"13.5",XXLarge:"28.4",XXXLarge:"58.2",Huge:"118",Massive:"237"};static ThrottlingPresets={Light:{burstLimit:100,rateLimit:50},Medium:{burstLimit:500,rateLimit:250},Heavy:{burstLimit:2000,rateLimit:1000},Default:{burstLimit:5000,rateLimit:1e4}}}class X{static createTopic(a){let{slug:n,environment:i,topicName:s,displayName:c,encrypted:l=!1,kmsKeyId:u}=a,h=s||r({slug:n,environment:i,resourceType:"topic"}),y=t(h),f={Type:"AWS::SNS::Topic",Properties:{TopicName:h,DisplayName:c||h,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:i}]}};if(l&&u)f.Properties.KmsMasterKeyId=u;return{topic:f,logicalId:y}}static subscribe(a,n){let{slug:i,environment:s,protocol:c,endpoint:l,filterPolicy:u,rawMessageDelivery:h=!1}=n,y=r({slug:i,environment:s,resourceType:"subscription"}),f=l.replace(/[^a-zA-Z0-9]/g,""),S=f.length>12?f.slice(-12):f,b=t(`${y}-${c}-${S}`),C={Type:"AWS::SNS::Subscription",Properties:{TopicArn:N.Ref(a),Protocol:c,Endpoint:l,RawMessageDelivery:h}};if(u)C.Properties.FilterPolicy=u;return{subscription:C,logicalId:b}}static subscribeEmail(a,n,i){return X.subscribe(a,{...i,protocol:"email",endpoint:n})}static subscribeLambda(a,n,i){return X.subscribe(a,{...i,protocol:"lambda",endpoint:n,rawMessageDelivery:!0})}static subscribeSqs(a,n,i){return X.subscribe(a,{...i,protocol:"sqs",endpoint:n})}static subscribeHttp(a,n,i){let s=n.startsWith("https://")?"https":"http";return X.subscribe(a,{...i,protocol:s,endpoint:n})}static subscribeSms(a,n,i){return X.subscribe(a,{...i,protocol:"sms",endpoint:n})}static setTopicPolicy(a,n){let{slug:i,environment:s,allowedPrincipals:c,allowedServices:l,actions:u="SNS:Publish"}=n,h=r({slug:i,environment:s,resourceType:"topic-policy"}),y=t(h),f={};if(c)f.AWS=c;if(l)f.Service=l;return{policy:{Type:"AWS::SNS::TopicPolicy",Properties:{Topics:[N.Ref(a)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:f,Action:u,Resource:N.Ref(a)}]}}},logicalId:y}}static allowCloudWatchAlarms(a,n){return X.setTopicPolicy(a,{...n,allowedServices:"cloudwatch.amazonaws.com",actions:"SNS:Publish"})}static allowEventBridge(a,n){return X.setTopicPolicy(a,{...n,allowedServices:"events.amazonaws.com",actions:"SNS:Publish"})}static allowS3(a,n){return X.setTopicPolicy(a,{...n,allowedServices:"s3.amazonaws.com",actions:"SNS:Publish"})}static enableEncryption(a,n){if(!a.Properties)a.Properties={};return a.Properties.KmsMasterKeyId=n,a}static addInlineSubscription(a,n,i){if(!a.Properties)a.Properties={};if(!a.Properties.Subscription)a.Properties.Subscription=[];return a.Properties.Subscription.push({Protocol:n,Endpoint:i}),a}static FilterPolicies={eventType:(a)=>({eventType:a}),status:(a)=>({status:a}),numericRange:(a,n,i)=>({[a]:[{numeric:[">=",n,"<=",i]}]}),prefix:(a,n)=>({[a]:[{prefix:n}]}),and:(...a)=>Object.assign({},...a),exists:(a,n)=>({[a]:[{exists:n}]})};static UseCases={createAlertTopic:(a)=>X.createTopic({...a,topicName:a.topicName||`${a.slug}-${a.environment}-alerts`,displayName:a.displayName||"Alert Notifications"}),createEventFanout:(a)=>X.createTopic({...a,topicName:a.topicName||`${a.slug}-${a.environment}-events`,displayName:a.displayName||"Event Fanout"}),createNotificationTopic:(a)=>X.createTopic({...a,topicName:a.topicName||`${a.slug}-${a.environment}-notifications`,displayName:a.displayName||"User Notifications"})}}class df{static createStateMachine(a){let{slug:n,environment:i,stateMachineName:s,type:c="STANDARD",definition:l,roleArn:u,loggingConfiguration:h,tracingConfiguration:y}=a,f=s||r({slug:n,environment:i,resourceType:"state-machine"}),S=t(f),b,C,T;if(u)T=u;else{let w=r({slug:n,environment:i,resourceType:"state-machine-role"});C=t(w),b={Type:"AWS::IAM::Role",Properties:{RoleName:w,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"states.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/CloudWatchLogsFullAccess"],Tags:[{Key:"Name",Value:w},{Key:"Environment",Value:i}]}},T=N.GetAtt(C,"Arn")}let v={Type:"AWS::StepFunctions::StateMachine",Properties:{StateMachineName:f,StateMachineType:c,DefinitionString:JSON.stringify(l),RoleArn:T,Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:i}]}};if(h)v.Properties.LoggingConfiguration={Level:h.level,IncludeExecutionData:h.includeExecutionData,Destinations:h.destinations?.map((w)=>({CloudWatchLogsLogGroup:{LogGroupArn:w}}))};if(y)v.Properties.TracingConfiguration={Enabled:y.enabled};return{stateMachine:v,logicalId:S,role:b,roleLogicalId:C}}static createLambdaTask(a,n){return{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Parameters:{FunctionName:a,Payload:n?.parameters||{"Input.$":"$"}},ResultPath:n?.resultPath,Retry:n?.retry,Catch:n?.catch,Next:n?.next,End:n?.end}}static createDynamoDBTask(a,n,i,s){return{Type:"Task",Resource:{GetItem:"arn:aws:states:::dynamodb:getItem",PutItem:"arn:aws:states:::dynamodb:putItem",UpdateItem:"arn:aws:states:::dynamodb:updateItem",DeleteItem:"arn:aws:states:::dynamodb:deleteItem"}[a],Parameters:{TableName:n,...i},ResultPath:s?.resultPath,Retry:s?.retry,Catch:s?.catch,Next:s?.next,End:s?.end}}static createSNSPublishTask(a,n,i){return{Type:"Task",Resource:"arn:aws:states:::sns:publish",Parameters:{TopicArn:a,Message:n},ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createSQSSendMessageTask(a,n,i){return{Type:"Task",Resource:"arn:aws:states:::sqs:sendMessage",Parameters:{QueueUrl:a,MessageBody:n},ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createPassState(a){return{Type:"Pass",Result:a?.result,ResultPath:a?.resultPath,Parameters:a?.parameters,Next:a?.next,End:a?.end}}static createWaitState(a){return{Type:"Wait",Seconds:a.seconds,Timestamp:a.timestamp,SecondsPath:a.secondsPath,TimestampPath:a.timestampPath,Next:a.next,End:a.end}}static createChoiceState(a,n){return{Type:"Choice",Choices:a,Default:n}}static createParallelState(a,n){return{Type:"Parallel",Branches:a,ResultPath:n?.resultPath,Retry:n?.retry,Catch:n?.catch,Next:n?.next,End:n?.end}}static createMapState(a,n){return{Type:"Map",ItemsPath:n?.itemsPath||"$.items",Iterator:a,MaxConcurrency:n?.maxConcurrency,ResultPath:n?.resultPath,Retry:n?.retry,Catch:n?.catch,Next:n?.next,End:n?.end}}static createSucceedState(){return{Type:"Succeed"}}static createFailState(a,n){return{Type:"Fail",Error:a,Cause:n}}static RetryPolicies={standard:()=>({ErrorEquals:["States.ALL"],IntervalSeconds:2,MaxAttempts:3,BackoffRate:2}),aggressive:()=>({ErrorEquals:["States.TaskFailed","States.Timeout"],IntervalSeconds:1,MaxAttempts:5,BackoffRate:1.5}),custom:(a,n,i,s)=>({ErrorEquals:a,IntervalSeconds:n,MaxAttempts:i,BackoffRate:s})};static CatchPolicies={all:(a,n)=>({ErrorEquals:["States.ALL"],Next:a,ResultPath:n||"$.error"}),specific:(a,n,i)=>({ErrorEquals:a,Next:n,ResultPath:i||"$.error"})};static Patterns={sequential:(a,n,i)=>{let s={};return i.forEach((c,l)=>{let u=l===i.length-1;s[c.name]={...c.state,Next:u?void 0:i[l+1].name,End:u}}),{Comment:"Sequential workflow",StartAt:i[0].name,States:s}},fanout:(a,n,i)=>({Comment:"Fan-out workflow",StartAt:"Parallel",States:{Parallel:{Type:"Parallel",Branches:i.map((s)=>s.definition),End:!0}}}),map:(a,n,i,s)=>({Comment:"Map workflow",StartAt:"Map",States:{Map:{Type:"Map",ItemsPath:"$.items",Iterator:i,MaxConcurrency:s,End:!0}}}),withErrorHandling:(a,n,i,s)=>({Comment:"Workflow with error handling",StartAt:"Main",States:{Main:{...i,Catch:[{ErrorEquals:["States.ALL"],Next:"ErrorHandler"}],Next:"Success"},ErrorHandler:s,Success:{Type:"Succeed"}}})}}class Gs{static createAlarm(a){let{slug:n,environment:i,alarmName:s,metricName:c,namespace:l,statistic:u="Average",period:h=300,evaluationPeriods:y=1,threshold:f,comparisonOperator:S,treatMissingData:b="notBreaching",actionsEnabled:C=!0,alarmActions:T,okActions:v,insufficientDataActions:w,dimensions:R,unit:k,datapointsToAlarm:W}=a,P=s||r({slug:n,environment:i,resourceType:"alarm"}),V=t(P),B={Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:P,MetricName:c,Namespace:l,Statistic:u,Period:h,EvaluationPeriods:y,Threshold:f,ComparisonOperator:S,TreatMissingData:b,ActionsEnabled:C}};if(T&&T.length>0)B.Properties.AlarmActions=T;if(v&&v.length>0)B.Properties.OKActions=v;if(w&&w.length>0)B.Properties.InsufficientDataActions=w;if(R)B.Properties.Dimensions=Object.entries(R).map(([j,Z])=>({Name:j,Value:Z}));if(k)B.Properties.Unit=k;if(W!==void 0)B.Properties.DatapointsToAlarm=W;return{alarm:B,logicalId:V}}static createCompositeAlarm(a){let{slug:n,environment:i,alarmName:s,alarmRule:c,actionsEnabled:l=!0,alarmActions:u,okActions:h,insufficientDataActions:y}=a,f=s||r({slug:n,environment:i,resourceType:"composite-alarm"}),S=t(f),b={Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:f,AlarmRule:c,ActionsEnabled:l}};if(u&&u.length>0)b.Properties.AlarmActions=u;if(h&&h.length>0)b.Properties.OKActions=h;if(y&&y.length>0)b.Properties.InsufficientDataActions=y;return{alarm:b,logicalId:S}}static createDashboard(a){let{slug:n,environment:i,dashboardName:s,widgets:c}=a,l=s||r({slug:n,environment:i,resourceType:"dashboard"}),u=t(l),h={widgets:c.map((y)=>({type:y.type,x:y.x,y:y.y,width:y.width,height:y.height,properties:y.properties}))};return{dashboard:{Type:"AWS::CloudWatch::Dashboard",Properties:{DashboardName:l,DashboardBody:JSON.stringify(h)}},logicalId:u}}static createLogGroup(a){let{slug:n,environment:i,logGroupName:s,retentionInDays:c,kmsKeyId:l}=a,u=s||r({slug:n,environment:i,resourceType:"log-group"}),h=t(u),y={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:u}};if(c!==void 0)y.Properties.RetentionInDays=c;if(l)y.Properties.KmsKeyId=l;return{logGroup:y,logicalId:h}}static createLogStream(a,n){let{slug:i,environment:s,logStreamName:c}=n,l=c||r({slug:i,environment:s,resourceType:"log-stream"}),u=t(l);return{logStream:{Type:"AWS::Logs::LogStream",Properties:{LogGroupName:N.Ref(a),LogStreamName:l}},logicalId:u}}static createMetricFilter(a,n){let{slug:i,environment:s,filterName:c,filterPattern:l,metricTransformations:u}=n,h=c||r({slug:i,environment:s,resourceType:"metric-filter"}),y=t(h);return{metricFilter:{Type:"AWS::Logs::MetricFilter",Properties:{LogGroupName:N.Ref(a),FilterPattern:l,MetricTransformations:u.map((f)=>({MetricName:f.metricName,MetricNamespace:f.metricNamespace,MetricValue:f.metricValue,DefaultValue:f.defaultValue,Unit:f.unit}))}},logicalId:y}}static AlarmTypes={highCpu:(a,n,i,s=80,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-high-cpu`,metricName:"CPUUtilization",namespace:"AWS/EC2",statistic:"Average",period:300,evaluationPeriods:2,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:i},alarmActions:c?[c]:void 0}),highMemory:(a,n,i,s=80,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-high-memory`,metricName:"MemoryUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:i},alarmActions:c?[c]:void 0}),highDisk:(a,n,i,s=80,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-high-disk`,metricName:"DiskSpaceUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:i,Filesystem:"/dev/xvda1",MountPath:"/"},alarmActions:c?[c]:void 0}),lambdaErrors:(a,n,i,s=5,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-lambda-errors`,metricName:"Errors",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:i},alarmActions:c?[c]:void 0}),lambdaThrottles:(a,n,i,s=10,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-lambda-throttles`,metricName:"Throttles",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:i},alarmActions:c?[c]:void 0}),apiGateway5xxErrors:(a,n,i,s=10,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-api-5xx-errors`,metricName:"5XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:i},alarmActions:c?[c]:void 0}),apiGateway4xxErrors:(a,n,i,s=50,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-api-4xx-errors`,metricName:"4XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:2,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:i},alarmActions:c?[c]:void 0}),dynamoDBThrottles:(a,n,i,s=5,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-dynamodb-throttles`,metricName:"UserErrors",namespace:"AWS/DynamoDB",statistic:"Sum",period:300,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{TableName:i},alarmActions:c?[c]:void 0}),rdsCpu:(a,n,i,s=80,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-rds-cpu`,metricName:"CPUUtilization",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:2,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{DBInstanceIdentifier:i},alarmActions:c?[c]:void 0}),rdsFreeStorage:(a,n,i,s=5368709120,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-rds-storage`,metricName:"FreeStorageSpace",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:1,threshold:s,comparisonOperator:"LessThanThreshold",dimensions:{DBInstanceIdentifier:i},alarmActions:c?[c]:void 0,unit:"Bytes"}),sqsQueueDepth:(a,n,i,s=100,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-sqs-depth`,metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",statistic:"Average",period:300,evaluationPeriods:2,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{QueueName:i},alarmActions:c?[c]:void 0}),albUnhealthyTargets:(a,n,i,s,c=1,l)=>({slug:a,environment:n,alarmName:`${a}-${n}-alb-unhealthy`,metricName:"UnHealthyHostCount",namespace:"AWS/ApplicationELB",statistic:"Average",period:300,evaluationPeriods:2,threshold:c,comparisonOperator:"GreaterThanThreshold",dimensions:{LoadBalancer:i,TargetGroup:s},alarmActions:l?[l]:void 0}),sesBounceRate:(a,n,i=5,s)=>({slug:a,environment:n,alarmName:`${a}-${n}-ses-bounce-rate`,metricName:"Reputation.BounceRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:i/100,comparisonOperator:"GreaterThanThreshold",alarmActions:s?[s]:void 0}),sesComplaintRate:(a,n,i=0.1,s)=>({slug:a,environment:n,alarmName:`${a}-${n}-ses-complaint-rate`,metricName:"Reputation.ComplaintRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:i/100,comparisonOperator:"GreaterThanThreshold",alarmActions:s?[s]:void 0}),smsDeliveryFailure:(a,n,i,s=10,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-sms-delivery-failure`,metricName:"DirectSendMessagePermanentFailure",namespace:"AWS/Pinpoint",statistic:"Sum",period:300,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{ApplicationId:i},alarmActions:c?[c]:void 0}),smsSpendLimit:(a,n,i=100,s)=>({slug:a,environment:n,alarmName:`${a}-${n}-sms-spend-limit`,metricName:"DirectSendMessageSpend",namespace:"AWS/Pinpoint",statistic:"Sum",period:86400,evaluationPeriods:1,threshold:i,comparisonOperator:"GreaterThanThreshold",alarmActions:s?[s]:void 0}),connectMissedCalls:(a,n,i,s=5,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-connect-missed-calls`,metricName:"MissedCalls",namespace:"AWS/Connect",statistic:"Sum",period:3600,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:i},alarmActions:c?[c]:void 0})};static DashboardWidgets={metric:(a,n,i,s,c,l)=>({type:"metric",x:a,y:n,width:i,height:s,properties:{metrics:c,title:l||"Metrics",region:"us-east-1",period:300}}),text:(a,n,i,s,c)=>({type:"text",x:a,y:n,width:i,height:s,properties:{markdown:c}}),log:(a,n,i,s,c,l)=>({type:"log",x:a,y:n,width:i,height:s,properties:{query:`SOURCE '${c.join("' | SOURCE '")}'
|
|
2309
|
+
`;class F{static LambdaCode={send:wa,receive:mr,deliveryStatus:dr};static createPinpointApp(a){return{[`${a.slug}PinpointApp`]:{Type:"AWS::Pinpoint::App",Properties:{Name:a.name||`${a.slug}-sms`}}}}static createSmsChannel(a){let n={ApplicationId:a.applicationId,Enabled:a.enabled!==!1};if(a.senderId)n.SenderId=a.senderId;if(a.shortCode)n.ShortCode=a.shortCode;return{[`${a.slug}SmsChannel`]:{Type:"AWS::Pinpoint::SMSChannel",Properties:n}}}static createSmsLambdaRole(a){return{[`${a.slug}SmsLambdaRole`]:{Type:"AWS::IAM::Role",Properties:{RoleName:`${a.slug}-sms-lambda-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],Policies:[{PolicyName:"SmsLambdaPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["mobiletargeting:SendMessages","mobiletargeting:GetSmsChannel"],Resource:"*"},{Effect:"Allow",Action:["sns:Publish"],Resource:"*"},{Effect:"Allow",Action:["dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:GetItem","dynamodb:DeleteItem"],Resource:"*"}]}}]}}}}static createSendLambda(a){return{[`${a.slug}SmsSendLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-sms-send`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:F.LambdaCode.send},Environment:{Variables:{PINPOINT_APP_ID:a.pinpointAppId,MESSAGE_LOG_TABLE:a.messageLogTable||"",SMS_SENDER_ID:a.senderId||"",SMS_ORIGINATION_NUMBER:a.originationNumber||""}}}}}}static createReceiveLambda(a){return{[`${a.slug}SmsReceiveLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-sms-receive`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:F.LambdaCode.receive},Environment:{Variables:{OPT_OUT_TABLE:a.optOutTable||"",MESSAGE_LOG_TABLE:a.messageLogTable||"",NOTIFICATION_TOPIC_ARN:a.notificationTopicArn||"",WEBHOOK_URL:a.webhookUrl||""}}}}}}static createDeliveryStatusLambda(a){return{[`${a.slug}SmsDeliveryStatusLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-sms-delivery-status`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:F.LambdaCode.deliveryStatus},Environment:{Variables:{MESSAGE_LOG_TABLE:a.messageLogTable||"",NOTIFICATION_TOPIC_ARN:a.notificationTopicArn||"",WEBHOOK_URL:a.webhookUrl||""}}}}}}static createMessageLogTable(a){return{[`${a.slug}SmsMessageLogTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${a.slug}-sms-messages`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createOptOutTable(a){return{[`${a.slug}SmsOptOutTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${a.slug}-sms-optouts`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}]}}}}static createNotificationTopic(a){return{[`${a.slug}SmsNotificationTopic`]:{Type:"AWS::SNS::Topic",Properties:{TopicName:`${a.slug}-sms-notifications`}}}}static createCompleteSetup(a){let n={},i={};Object.assign(n,F.createPinpointApp({slug:a.slug})),Object.assign(n,F.createSmsChannel({slug:a.slug,applicationId:{Ref:`${a.slug}PinpointApp`},senderId:a.senderId})),Object.assign(n,F.createSmsLambdaRole({slug:a.slug})),Object.assign(n,F.createMessageLogTable({slug:a.slug})),Object.assign(n,F.createOptOutTable({slug:a.slug})),Object.assign(n,F.createNotificationTopic({slug:a.slug}));let s={"Fn::GetAtt":[`${a.slug}SmsLambdaRole`,"Arn"]},c={Ref:`${a.slug}PinpointApp`},l={Ref:`${a.slug}SmsMessageLogTable`},u={Ref:`${a.slug}SmsOptOutTable`},h={Ref:`${a.slug}SmsNotificationTopic`};if(Object.assign(n,F.createSendLambda({slug:a.slug,roleArn:s,pinpointAppId:c,messageLogTable:l,senderId:a.senderId,originationNumber:a.originationNumber})),a.twoWayEnabled)Object.assign(n,F.createReceiveLambda({slug:a.slug,roleArn:s,optOutTable:u,messageLogTable:l,notificationTopicArn:h,webhookUrl:a.webhookUrl}));return Object.assign(n,F.createDeliveryStatusLambda({slug:a.slug,roleArn:s,messageLogTable:l,notificationTopicArn:h,webhookUrl:a.webhookUrl})),i[`${a.slug}PinpointAppId`]={Description:"Pinpoint application ID",Value:{Ref:`${a.slug}PinpointApp`}},i[`${a.slug}SmsSendLambdaArn`]={Description:"SMS send Lambda ARN",Value:{"Fn::GetAtt":[`${a.slug}SmsSendLambda`,"Arn"]}},i[`${a.slug}SmsNotificationTopicArn`]={Description:"SMS notification topic ARN",Value:{Ref:`${a.slug}SmsNotificationTopic`}},i[`${a.slug}SmsMessageLogTableName`]={Description:"SMS message log table name",Value:{Ref:`${a.slug}SmsMessageLogTable`}},{resources:n,outputs:i}}}function wt(a){return a.replace(/[^a-zA-Z0-9]/g," ").trim().split(/\s+/).map((n)=>n.charAt(0).toUpperCase()+n.slice(1)).join("")||"User"}function gr(a,n){let i=(a||n).replace(/^\/+|\/+$/g,"");if(!i||i.split("/").includes(".."))throw Error(`sftp: invalid homeDirectory for user ${n}`);return i}function hr(a){let n=a.storage;if(n?.type==="efs"){let s="fileSystemId"in n?n.fileSystemId:void 0;if(!s||typeof s==="string"&&!s.trim())throw Error("sftp: EFS storage requires fileSystemId, or a fileSystem name defined in infrastructure.fileSystem");return{type:"efs",fileSystemId:s,posixProfile:n.posixProfile}}let i=(n?.type==="s3"?n.bucket??a.bucket:a.bucket)?.trim();if(!i)throw Error("sftp: S3 storage requires bucket, or a storageBucket name defined in infrastructure.storage");return{type:"s3",bucket:i}}function yr(a,n,i){let s=n.posixProfile??i;if(!s)throw Error(`sftp: user ${a} requires a posixProfile (uid/gid) on an EFS-backed server`);for(let c of[s.uid,s.gid,...s.secondaryGids??[]])if(!Number.isInteger(c)||c<0||c>4294967295)throw Error(`sftp: user ${a} has an invalid posixProfile id ${c}`);return{Uid:s.uid,Gid:s.gid,...s.secondaryGids?.length?{SecondaryGids:s.secondaryGids}:{}}}function fr(a,n){return typeof a==="string"?`/${a}/${n}`:{"Fn::Sub":[`/\${FileSystemId}/${n}`,{FileSystemId:a}]}}function Sr(a){return typeof a==="string"?{"Fn::Sub":"arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}".replace("${FileSystemId}",a)}:{"Fn::Sub":["arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}",{FileSystemId:a}]}}class nd{static create(a){let n=hr(a),i=n.type==="efs"?"EFS":"S3",s=a.endpointType??"PUBLIC";if(s==="VPC"&&(!a.endpointDetails?.vpcId||!a.endpointDetails.subnetIds.length))throw Error("sftp: VPC endpoints require endpointDetails.vpcId and at least one subnet");let c=`${wt(a.slug)}${wt(a.environment)}Sftp`,l=`${c}Server`,u={},h;if(a.logging!==!1){let y=`${c}LoggingRole`;u[y]={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"transfer.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"TransferLogging",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:DescribeLogStreams","logs:PutLogEvents"],Resource:"arn:aws:logs:*:*:log-group:/aws/transfer/*"}]}}]}},h={"Fn::GetAtt":[y,"Arn"]}}u[l]={Type:"AWS::Transfer::Server",Properties:{Domain:i,EndpointType:s,IdentityProviderType:"SERVICE_MANAGED",Protocols:["SFTP"],...s==="VPC"?{EndpointDetails:{VpcId:a.endpointDetails.vpcId,SubnetIds:a.endpointDetails.subnetIds,...a.endpointDetails.securityGroupIds?.length?{SecurityGroupIds:a.endpointDetails.securityGroupIds}:{},...a.endpointDetails.addressAllocationIds?.length?{AddressAllocationIds:a.endpointDetails.addressAllocationIds}:{}}}:{},...a.securityPolicyName?{SecurityPolicyName:a.securityPolicyName}:{},...h?{LoggingRole:h}:{},Tags:[{Key:"Project",Value:a.slug},{Key:"Environment",Value:a.environment},{Key:"ManagedBy",Value:"ts-cloud"}]}};for(let[y,f]of Object.entries(a.users)){if(!/^[a-zA-Z0-9_.@-]{3,100}$/.test(y))throw Error(`sftp: invalid username ${y}`);if(!f.sshPublicKeys.length)throw Error(`sftp: user ${y} requires at least one SSH public key`);let S=wt(y),b=gr(f.homeDirectory,y),C=`${c}${S}User`,T=f.roleArn;if(!T){let v=`${c}${S}Role`,w;if(n.type==="efs")w=[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:DescribeMountTargets"],Resource:Sr(n.fileSystemId)}];else{let R=`arn:aws:s3:::${n.bucket}`;w=[{Effect:"Allow",Action:["s3:ListBucket","s3:GetBucketLocation"],Resource:R,Condition:{StringLike:{"s3:prefix":[b,`${b}/*`]}}},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:GetObjectVersion"],Resource:`${R}/${b}/*`}]}u[v]={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"transfer.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"SftpHomeDirectory",PolicyDocument:{Version:"2012-10-17",Statement:w}}]}},T={"Fn::GetAtt":[v,"Arn"]}}u[C]={Type:"AWS::Transfer::User",DependsOn:[l],Properties:{ServerId:{Ref:l},UserName:y,Role:T,HomeDirectoryType:"PATH",HomeDirectory:n.type==="efs"?fr(n.fileSystemId,b):`/${n.bucket}/${b}`,...n.type==="efs"?{PosixProfile:yr(y,f,n.posixProfile)}:{},SshPublicKeys:f.sshPublicKeys}}}return{resources:u,serverLogicalId:l,domain:i}}}class be{static createBedrockRole(a,n){let{slug:i,environment:s,name:c,models:l=["*"],allowStreaming:u=!0}=n,h=c||r({slug:i,environment:s,resourceType:"bedrock-role"}),y=t(h),f=["bedrock:InvokeModel"];if(u)f.push("bedrock:InvokeModelWithResponseStream");let S=l.map((b)=>b==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${b}`);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:h,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:a},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:`${h}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:f,Resource:S}]}}],Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}},logicalId:y}}static createBedrockPolicy(a){let{slug:n,environment:i,name:s,models:c=["*"],allowInvoke:l=!0,allowStreaming:u=!0,allowAsync:h=!1}=a,y=s||r({slug:n,environment:i,resourceType:"bedrock-policy"}),f=t(y),S=[];if(l)S.push("bedrock:InvokeModel");if(u)S.push("bedrock:InvokeModelWithResponseStream");if(h)S.push("bedrock:InvokeModelAsync");let b=c.map((C)=>C==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${C}`);return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:y,PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"BedrockModelInvocation",Effect:"Allow",Action:S,Resource:b}]}}},logicalId:f}}static enableBedrockForLambda(a){return be.createBedrockRole("lambda.amazonaws.com",a)}static enableBedrockForEcs(a){return be.createBedrockRole("ecs-tasks.amazonaws.com",a)}static enableBedrockForEc2(a){return be.createBedrockRole("ec2.amazonaws.com",a)}static addBedrockPermissions(a,n=["*"],i=!0){let s=["bedrock:InvokeModel"];if(i)s.push("bedrock:InvokeModelWithResponseStream");let c=n.map((l)=>l==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${l}`);if(!a.Properties.Policies)a.Properties.Policies=[];return a.Properties.Policies.push({PolicyName:"bedrock-permissions",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:s,Resource:c}]}}),a}static Models={Claude3_5_Sonnet:"anthropic.claude-3-5-sonnet-20241022-v2:0",Claude3_5_Haiku:"anthropic.claude-3-5-haiku-20241022-v1:0",Claude3_Opus:"anthropic.claude-3-opus-20240229-v1:0",Claude3_Sonnet:"anthropic.claude-3-sonnet-20240229-v1:0",Claude3_Haiku:"anthropic.claude-3-haiku-20240307-v1:0",TitanTextG1Express:"amazon.titan-text-express-v1",TitanTextG1Lite:"amazon.titan-text-lite-v1",TitanEmbedG1Text:"amazon.titan-embed-text-v1",TitanImageG1:"amazon.titan-image-generator-v1",JurassicUltra:"ai21.j2-ultra-v1",JurassicMid:"ai21.j2-mid-v1",CommandText:"cohere.command-text-v14",CommandLight:"cohere.command-light-text-v14",EmbedEnglish:"cohere.embed-english-v3",EmbedMultilingual:"cohere.embed-multilingual-v3",Llama3_2_1B:"meta.llama3-2-1b-instruct-v1:0",Llama3_2_3B:"meta.llama3-2-3b-instruct-v1:0",Llama3_2_11B:"meta.llama3-2-11b-instruct-v1:0",Llama3_2_90B:"meta.llama3-2-90b-instruct-v1:0",Llama3_1_8B:"meta.llama3-1-8b-instruct-v1:0",Llama3_1_70B:"meta.llama3-1-70b-instruct-v1:0",Llama3_1_405B:"meta.llama3-1-405b-instruct-v1:0",Mistral7B:"mistral.mistral-7b-instruct-v0:2",Mixtral8x7B:"mistral.mixtral-8x7b-instruct-v0:1",MistralLarge:"mistral.mistral-large-2402-v1:0",StableDiffusionXL:"stability.stable-diffusion-xl-v1"};static ModelGroups={AllClaude:["anthropic.claude-3-5-sonnet-20241022-v2:0","anthropic.claude-3-5-haiku-20241022-v1:0","anthropic.claude-3-opus-20240229-v1:0","anthropic.claude-3-sonnet-20240229-v1:0","anthropic.claude-3-haiku-20240307-v1:0"],AllTitan:["amazon.titan-text-express-v1","amazon.titan-text-lite-v1","amazon.titan-embed-text-v1","amazon.titan-image-generator-v1"],AllLlama:["meta.llama3-2-1b-instruct-v1:0","meta.llama3-2-3b-instruct-v1:0","meta.llama3-2-11b-instruct-v1:0","meta.llama3-2-90b-instruct-v1:0","meta.llama3-1-8b-instruct-v1:0","meta.llama3-1-70b-instruct-v1:0","meta.llama3-1-405b-instruct-v1:0"],TextModels:["anthropic.claude-3-5-sonnet-20241022-v2:0","anthropic.claude-3-5-haiku-20241022-v1:0","amazon.titan-text-express-v1","meta.llama3-2-11b-instruct-v1:0","mistral.mistral-7b-instruct-v0:2"],EmbeddingModels:["amazon.titan-embed-text-v1","cohere.embed-english-v3","cohere.embed-multilingual-v3"],ImageModels:["amazon.titan-image-generator-v1","stability.stable-diffusion-xl-v1"]}}class Ft{static createPostgres(a){return Ft.createRDSInstance("postgres","16.2",a)}static createMysql(a){return Ft.createRDSInstance("mysql","8.0.35",a)}static createRDSInstance(a,n,i){let{slug:s,environment:c,instanceClass:l="db.t3.micro",allocatedStorage:u=20,storageType:h="gp3",masterUsername:y="admin",masterPassword:f,databaseName:S,subnetIds:b,securityGroupIds:C,encrypted:T=!0,kmsKeyId:v,multiAz:w=!1,backupRetentionDays:R=7,publiclyAccessible:k=!1,enableCloudwatchLogs:W=!0,deletionProtection:P=!0}=i,V=r({slug:s,environment:c,resourceType:`${a}-db`}),B=t(V),j,Z;if(b&&b.length>0){let ee=r({slug:s,environment:c,resourceType:"db-subnet-group"});Z=t(ee),j={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupName:ee,DBSubnetGroupDescription:`Subnet group for ${V}`,SubnetIds:b,Tags:[{Key:"Name",Value:ee},{Key:"Environment",Value:c}]}}}let K={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:V,DBInstanceClass:l,Engine:a,EngineVersion:n,MasterUsername:y,MasterUserPassword:f,AllocatedStorage:u,StorageType:h,StorageEncrypted:T,MultiAZ:w,BackupRetentionPeriod:R,PubliclyAccessible:k,DeletionProtection:P,Tags:[{Key:"Name",Value:V},{Key:"Environment",Value:c}]}};if(S)K.Properties.DBName=S;if(v)K.Properties.KmsKeyId=v;if(Z)K.Properties.DBSubnetGroupName=N.Ref(Z);if(C&&C.length>0)K.Properties.VPCSecurityGroups=C;if(W)K.Properties.EnableCloudwatchLogsExports=a==="postgres"?["postgresql"]:["error","general","slowquery"];return{dbInstance:K,subnetGroup:j,logicalId:B,subnetGroupId:Z}}static createReadReplica(a,n){let{slug:i,environment:s,instanceClass:c="db.t3.micro",securityGroupIds:l,publiclyAccessible:u=!1}=n,h=r({slug:i,environment:s,resourceType:"db-replica"}),y=t(h),f={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:h,DBInstanceClass:c,SourceDBInstanceIdentifier:N.Ref(a),PubliclyAccessible:u,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s},{Key:"Type",Value:"ReadReplica"}]}};if(l&&l.length>0)f.Properties.VPCSecurityGroups=l;return{replica:f,logicalId:y}}static createParameterGroup(a,n,i){let{slug:s,environment:c,parameters:l={}}=i,u=r({slug:s,environment:c,resourceType:"db-params"}),h=t(u),y=a==="postgres"?`postgres${n.split(".")[0]}`:`mysql${n.split(".")[0]}.${n.split(".")[1]}`;return{parameterGroup:{Type:"AWS::RDS::DBParameterGroup",Properties:{DBParameterGroupName:u,Description:`Parameter group for ${u}`,Family:y,Parameters:l,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:c}]}},logicalId:h}}static enableBackup(a,n=7){return a.Properties.BackupRetentionPeriod=n,a}static createTable(a){let{slug:n,environment:i,tableName:s,partitionKey:c,sortKey:l,billingMode:u="PAY_PER_REQUEST",readCapacity:h=5,writeCapacity:y=5,streamEnabled:f=!1,streamViewType:S="NEW_AND_OLD_IMAGES",encrypted:b=!0,kmsKeyId:C,pointInTimeRecovery:T=!0,ttlAttribute:v}=a,w=s||r({slug:n,environment:i,resourceType:"table"}),R=t(w),k=[{AttributeName:c.name,AttributeType:c.type}];if(l)k.push({AttributeName:l.name,AttributeType:l.type});let W=[{AttributeName:c.name,KeyType:"HASH"}];if(l)W.push({AttributeName:l.name,KeyType:"RANGE"});let P={Type:"AWS::DynamoDB::Table",Properties:{TableName:w,BillingMode:u,AttributeDefinitions:k,KeySchema:W,Tags:[{Key:"Name",Value:w},{Key:"Environment",Value:i}]}};if(u==="PROVISIONED")P.Properties.ProvisionedThroughput={ReadCapacityUnits:h,WriteCapacityUnits:y};if(f)P.Properties.StreamSpecification={StreamViewType:S};if(b)P.Properties.SSESpecification={SSEEnabled:!0,SSEType:C?"KMS":"AES256",KMSMasterKeyId:C};if(T)P.Properties.PointInTimeRecoverySpecification={PointInTimeRecoveryEnabled:!0};if(v)P.Properties.TimeToLiveSpecification={AttributeName:v,Enabled:!0};return{table:P,logicalId:R}}static addGlobalSecondaryIndex(a,n){let{indexName:i,partitionKey:s,sortKey:c,projectionType:l="ALL",nonKeyAttributes:u,readCapacity:h=5,writeCapacity:y=5}=n;if(!a.Properties.AttributeDefinitions.some((b)=>b.AttributeName===s.name))a.Properties.AttributeDefinitions.push({AttributeName:s.name,AttributeType:s.type});if(c&&!a.Properties.AttributeDefinitions.some((b)=>b.AttributeName===c.name))a.Properties.AttributeDefinitions.push({AttributeName:c.name,AttributeType:c.type});let f=[{AttributeName:s.name,KeyType:"HASH"}];if(c)f.push({AttributeName:c.name,KeyType:"RANGE"});let S={IndexName:i,KeySchema:f,Projection:{ProjectionType:l,NonKeyAttributes:l==="INCLUDE"?u:void 0},ProvisionedThroughput:void 0};if(a.Properties.BillingMode==="PROVISIONED")S.ProvisionedThroughput={ReadCapacityUnits:h,WriteCapacityUnits:y};if(!a.Properties.GlobalSecondaryIndexes)a.Properties.GlobalSecondaryIndexes=[];return a.Properties.GlobalSecondaryIndexes.push(S),a}static enableStreams(a,n="NEW_AND_OLD_IMAGES"){return a.Properties.StreamSpecification={StreamViewType:n},a}static InstanceClasses={T3_Micro:"db.t3.micro",T3_Small:"db.t3.small",T3_Medium:"db.t3.medium",T3_Large:"db.t3.large",T4g_Micro:"db.t4g.micro",T4g_Small:"db.t4g.small",T4g_Medium:"db.t4g.medium",M5_Large:"db.m5.large",M5_XLarge:"db.m5.xlarge",M5_2XLarge:"db.m5.2xlarge",R5_Large:"db.r5.large",R5_XLarge:"db.r5.xlarge",R5_2XLarge:"db.r5.2xlarge"}}class Gs{static createRedis(a){let{slug:n,environment:i,nodeType:s="cache.t3.micro",engineVersion:c="7.1",port:l=6379,subnetIds:u,securityGroupIds:h,numCacheClusters:y=2,automaticFailover:f=!0,multiAz:S=!0,clusterMode:b=!1,numNodeGroups:C=1,replicasPerNodeGroup:T=1,atRestEncryption:v=!0,transitEncryption:w=!0,authToken:R,kmsKeyId:k,snapshotRetentionDays:W=7,snapshotWindow:P,maintenanceWindow:V}=a,B=r({slug:n,environment:i,resourceType:"redis"}),j=t(B),Z,K;if(u&&u.length>0){let te=r({slug:n,environment:i,resourceType:"cache-subnet-group"});K=t(te),Z={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:te,Description:`Subnet group for ${B}`,SubnetIds:u,Tags:[{Key:"Name",Value:te},{Key:"Environment",Value:i}]}}}let ee={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:B,ReplicationGroupDescription:`Redis cluster for ${n} ${i}`,Engine:"redis",EngineVersion:c,CacheNodeType:s,Port:l,AutomaticFailoverEnabled:f,MultiAZEnabled:S,AtRestEncryptionEnabled:v,TransitEncryptionEnabled:w,SnapshotRetentionLimit:W,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:B},{Key:"Environment",Value:i}]}};if(b)ee.Properties.NumNodeGroups=C,ee.Properties.ReplicasPerNodeGroup=T;else ee.Properties.NumCacheClusters=y;if(R)ee.Properties.AuthToken=R;if(k)ee.Properties.KmsKeyId=k;if(K)ee.Properties.CacheSubnetGroupName=N.Ref(K);if(h&&h.length>0)ee.Properties.SecurityGroupIds=h;if(P)ee.Properties.SnapshotWindow=P;if(V)ee.Properties.PreferredMaintenanceWindow=V;return{replicationGroup:ee,subnetGroup:Z,logicalId:j,subnetGroupId:K}}static createMemcached(a){let{slug:n,environment:i,nodeType:s="cache.t3.micro",engineVersion:c="1.6.22",port:l=11211,numCacheNodes:u=2,subnetIds:h,securityGroupIds:y,azMode:f="cross-az",preferredAzs:S,maintenanceWindow:b}=a,C=r({slug:n,environment:i,resourceType:"memcached"}),T=t(C),v,w;if(h&&h.length>0){let k=r({slug:n,environment:i,resourceType:"cache-subnet-group"});w=t(k),v={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:k,Description:`Subnet group for ${C}`,SubnetIds:h,Tags:[{Key:"Name",Value:k},{Key:"Environment",Value:i}]}}}let R={Type:"AWS::ElastiCache::CacheCluster",Properties:{ClusterName:C,CacheNodeType:s,Engine:"memcached",EngineVersion:c,NumCacheNodes:u,Port:l,AZMode:f,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:C},{Key:"Environment",Value:i}]}};if(w)R.Properties.CacheSubnetGroupName=N.Ref(w);if(y&&y.length>0)R.Properties.VpcSecurityGroupIds=y;if(S&&S.length>0)R.Properties.PreferredAvailabilityZones=S;if(b)R.Properties.PreferredMaintenanceWindow=b;return{cluster:R,subnetGroup:v,logicalId:T,subnetGroupId:w}}static enableClusterMode(a,n=3,i=2){return delete a.Properties.NumCacheClusters,a.Properties.NumNodeGroups=n,a.Properties.ReplicasPerNodeGroup=i,a}static createRedisParameterGroup(a,n){let{slug:i,environment:s,parameters:c={}}=n,l=r({slug:i,environment:s,resourceType:"redis-params"}),u=t(l);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`redis${a.split(".")[0]}.x`,Description:`Parameter group for ${l}`,Properties:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s}]}},logicalId:u}}static createMemcachedParameterGroup(a,n){let{slug:i,environment:s,parameters:c={}}=n,l=r({slug:i,environment:s,resourceType:"memcached-params"}),u=t(l);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`memcached${a.split(".")[0]}.${a.split(".")[1]}`,Description:`Parameter group for ${l}`,Properties:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s}]}},logicalId:u}}static NodeTypes={T3_Micro:"cache.t3.micro",T3_Small:"cache.t3.small",T3_Medium:"cache.t3.medium",T4g_Micro:"cache.t4g.micro",T4g_Small:"cache.t4g.small",T4g_Medium:"cache.t4g.medium",M5_Large:"cache.m5.large",M5_XLarge:"cache.m5.xlarge",M5_2XLarge:"cache.m5.2xlarge",R5_Large:"cache.r5.large",R5_XLarge:"cache.r5.xlarge",R5_2XLarge:"cache.r5.2xlarge",R5_4XLarge:"cache.r5.4xlarge",R6g_Large:"cache.r6g.large",R6g_XLarge:"cache.r6g.xlarge",R6g_2XLarge:"cache.r6g.2xlarge"}}class J{static createUser(a){let{slug:n,environment:i,userName:s,groups:c,managedPolicyArns:l}=a,u=s||r({slug:n,environment:i,resourceType:"user"}),h=t(u),y={Type:"AWS::IAM::User",Properties:{UserName:u,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:i}]}};if(c&&c.length>0)y.Properties.Groups=c;if(l&&l.length>0)y.Properties.ManagedPolicyArns=l;return{user:y,logicalId:h}}static createRole(a){let{slug:n,environment:i,roleName:s,servicePrincipal:c,awsPrincipal:l,managedPolicyArns:u}=a,h=s||r({slug:n,environment:i,resourceType:"role"}),y=t(h),f={};if(c)f.Service=c;if(l)f.AWS=l;let S={Type:"AWS::IAM::Role",Properties:{RoleName:h,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:f,Action:"sts:AssumeRole"}]},Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:i}]}};if(u&&u.length>0)S.Properties.ManagedPolicyArns=u;return{role:S,logicalId:y}}static createGroup(a){let{slug:n,environment:i,groupName:s,managedPolicyArns:c}=a,l=s||r({slug:n,environment:i,resourceType:"group"}),u=t(l),h={Type:"AWS::IAM::Group",Properties:{GroupName:l}};if(c&&c.length>0)h.Properties.ManagedPolicyArns=c;return{group:h,logicalId:u}}static createPolicy(a){let{slug:n,environment:i,policyName:s,description:c,statements:l}=a,u=s||r({slug:n,environment:i,resourceType:"policy"}),h=t(u),y=l.map((f)=>({Sid:f.sid,Effect:f.effect||"Allow",Action:f.actions,Resource:f.resources,Condition:f.conditions}));return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:u,Description:c||`Managed policy for ${u}`,PolicyDocument:{Version:"2012-10-17",Statement:y}}},logicalId:h}}static attachPolicyToRole(a,n){if(!a.Properties.ManagedPolicyArns)a.Properties.ManagedPolicyArns=[];if(!a.Properties.ManagedPolicyArns.includes(n))a.Properties.ManagedPolicyArns.push(n);return a}static attachPolicyToUser(a,n){if(!a.Properties.ManagedPolicyArns)a.Properties.ManagedPolicyArns=[];if(!a.Properties.ManagedPolicyArns.includes(n))a.Properties.ManagedPolicyArns.push(n);return a}static attachPolicyToGroup(a,n){if(!a.Properties.ManagedPolicyArns)a.Properties.ManagedPolicyArns=[];if(!a.Properties.ManagedPolicyArns.includes(n))a.Properties.ManagedPolicyArns.push(n);return a}static addInlinePolicyToRole(a,n,i){if(!a.Properties.Policies)a.Properties.Policies=[];let s=i.map((c)=>({Effect:c.effect||"Allow",Action:c.actions,Resource:c.resources}));return a.Properties.Policies.push({PolicyName:n,PolicyDocument:{Version:"2012-10-17",Statement:s}}),a}static addInlinePolicyToUser(a,n,i){if(!a.Properties.Policies)a.Properties.Policies=[];let s=i.map((c)=>({Effect:c.effect||"Allow",Action:c.actions,Resource:c.resources}));return a.Properties.Policies.push({PolicyName:n,PolicyDocument:{Version:"2012-10-17",Statement:s}}),a}static createAccessKey(a,n){let{slug:i,environment:s,status:c="Active"}=n,l=r({slug:i,environment:s,resourceType:"access-key"}),u=t(l);return{accessKey:{Type:"AWS::IAM::AccessKey",Properties:{UserName:N.Ref(a),Status:c}},logicalId:u}}static createInstanceProfile(a,n){let{slug:i,environment:s,profileName:c}=n,l=c||r({slug:i,environment:s,resourceType:"instance-profile"}),u=t(l);return{instanceProfile:{Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:l,Roles:[N.Ref(a)]}},logicalId:u}}static ManagedPolicies={AdministratorAccess:"arn:aws:iam::aws:policy/AdministratorAccess",PowerUserAccess:"arn:aws:iam::aws:policy/PowerUserAccess",ReadOnlyAccess:"arn:aws:iam::aws:policy/ReadOnlyAccess",S3FullAccess:"arn:aws:iam::aws:policy/AmazonS3FullAccess",S3ReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess",DynamoDBFullAccess:"arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess",DynamoDBReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonDynamoDBReadOnlyAccess",RDSFullAccess:"arn:aws:iam::aws:policy/AmazonRDSFullAccess",RDSReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonRDSReadOnlyAccess",LambdaFullAccess:"arn:aws:iam::aws:policy/AWSLambda_FullAccess",LambdaReadOnlyAccess:"arn:aws:iam::aws:policy/AWSLambda_ReadOnlyAccess",LambdaBasicExecutionRole:"arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",LambdaVPCAccessExecutionRole:"arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole",EC2FullAccess:"arn:aws:iam::aws:policy/AmazonEC2FullAccess",EC2ReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess",EC2ContainerRegistryReadOnly:"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly",EC2ContainerRegistryPowerUser:"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPowerUser",ECSTaskExecutionRole:"arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy",ECSFullAccess:"arn:aws:iam::aws:policy/AmazonECS_FullAccess",CloudWatchFullAccess:"arn:aws:iam::aws:policy/CloudWatchFullAccess",CloudWatchLogsFullAccess:"arn:aws:iam::aws:policy/CloudWatchLogsFullAccess",SESFullAccess:"arn:aws:iam::aws:policy/AmazonSESFullAccess",SNSFullAccess:"arn:aws:iam::aws:policy/AmazonSNSFullAccess",SQSFullAccess:"arn:aws:iam::aws:policy/AmazonSQSFullAccess",SecretsManagerReadWrite:"arn:aws:iam::aws:policy/SecretsManagerReadWrite"};static ServicePrincipals={Lambda:"lambda.amazonaws.com",EC2:"ec2.amazonaws.com",ECS:"ecs.amazonaws.com",ECSTaskExecution:"ecs-tasks.amazonaws.com",APIGateway:"apigateway.amazonaws.com",Events:"events.amazonaws.com",States:"states.amazonaws.com",CodeBuild:"codebuild.amazonaws.com",CodeDeploy:"codedeploy.amazonaws.com",CloudFormation:"cloudformation.amazonaws.com"};static createCiCdUser(a){let{slug:n,environment:i,permissions:s,createAccessKey:c=!0}=a,l={},u=[];if(s.s3Buckets&&s.s3Buckets.length>0)u.push({sid:"S3Access",actions:["s3:GetBucketLocation","s3:ListBucket","s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucketMultipartUploads","s3:AbortMultipartUpload"],resources:[...s.s3Buckets,...s.s3Buckets.map((T)=>`${T}/*`)]});if(s.cloudFrontDistributions&&s.cloudFrontDistributions.length>0)u.push({sid:"CloudFrontAccess",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations","cloudfront:GetDistribution"],resources:s.cloudFrontDistributions});if(s.ecrRepositories&&s.ecrRepositories.length>0)u.push({sid:"ECRAccess",actions:["ecr:GetAuthorizationToken","ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:GetRepositoryPolicy","ecr:DescribeRepositories","ecr:ListImages","ecr:DescribeImages","ecr:BatchGetImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:PutImage"],resources:s.ecrRepositories}),u.push({sid:"ECRLogin",actions:["ecr:GetAuthorizationToken"],resources:"*"});if(s.ecsServices&&s.ecsServices.length>0)u.push({sid:"ECSAccess",actions:["ecs:DescribeServices","ecs:DescribeTaskDefinition","ecs:DescribeTasks","ecs:ListTasks","ecs:RegisterTaskDefinition","ecs:UpdateService","ecs:RunTask","ecs:StopTask"],resources:s.ecsServices}),u.push({sid:"ECSTaskDefinitions",actions:["ecs:RegisterTaskDefinition","ecs:DeregisterTaskDefinition"],resources:"*"}),u.push({sid:"ECSPassRole",actions:["iam:PassRole"],resources:"*",conditions:{StringLike:{"iam:PassedToService":"ecs-tasks.amazonaws.com"}}});if(s.cloudFormationStacks&&s.cloudFormationStacks.length>0)u.push({sid:"CloudFormationAccess",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:DescribeStackResources","cloudformation:GetTemplate","cloudformation:ListStackResources","cloudformation:ValidateTemplate"],resources:s.cloudFormationStacks});if(s.lambdaFunctions&&s.lambdaFunctions.length>0)u.push({sid:"LambdaAccess",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion","lambda:UpdateAlias","lambda:CreateAlias"],resources:s.lambdaFunctions});if(s.secretsManagerSecrets&&s.secretsManagerSecrets.length>0)u.push({sid:"SecretsManagerAccess",actions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],resources:s.secretsManagerSecrets});let{policy:h,logicalId:y}=J.createPolicy({slug:n,environment:i,policyName:r({slug:n,environment:i,resourceType:"cicd-policy"}),description:`CI/CD deployment policy for ${n} (${i})`,statements:u});l[y]=h;let{user:f,logicalId:S}=J.createUser({slug:n,environment:i,userName:r({slug:n,environment:i,resourceType:"cicd-user"}),managedPolicyArns:[N.Ref(y)]});l[S]=f;let b,C;if(c){let T=J.createAccessKey(S,{slug:n,environment:i});b=T.accessKey,C=T.logicalId,l[C]=b}return{user:f,accessKey:b,policy:h,userLogicalId:S,accessKeyLogicalId:C,policyLogicalId:y,resources:l}}static createCrossAccountRole(a){let{slug:n,environment:i,trustedAccountIds:s,externalId:c,permissions:l,maxSessionDuration:u=3600}=a,h={},{policy:y,logicalId:f}=J.createPolicy({slug:n,environment:i,policyName:r({slug:n,environment:i,resourceType:"cross-account-policy"}),description:`Cross-account access policy for ${n} (${i})`,statements:l});h[f]=y;let S=r({slug:n,environment:i,resourceType:"cross-account-role"}),b=t(S),C={};if(c)C.StringEquals={"sts:ExternalId":c};let T={Type:"AWS::IAM::Role",Properties:{RoleName:S,MaxSessionDuration:u,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:s.map((v)=>`arn:aws:iam::${v}:root`)},Action:"sts:AssumeRole",...Object.keys(C).length>0?{Condition:C}:{}}]},ManagedPolicyArns:[N.Ref(f)],Tags:[{Key:"Name",Value:S},{Key:"Environment",Value:i},{Key:"Purpose",Value:"Cross-Account Access"}]}};return h[b]=T,{role:T,policy:y,roleLogicalId:b,policyLogicalId:f,resources:h}}static createCliUser(a){let{slug:n,environment:i,permissions:s="readonly"}=a,c={},l=[],u=[];switch(s){case"readonly":u=[J.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=[J.ManagedPolicies.AdministratorAccess];break}let h,y;if(l.length>0){let T=J.createPolicy({slug:n,environment:i,policyName:r({slug:n,environment:i,resourceType:"cli-policy"}),description:`CLI access policy for ${n} (${i})`,statements:l});h=T.policy,y=T.logicalId,c[y]=h,u=[N.Ref(y)]}let{user:f,logicalId:S}=J.createUser({slug:n,environment:i,userName:r({slug:n,environment:i,resourceType:"cli-user"}),managedPolicyArns:u});c[S]=f;let{accessKey:b,logicalId:C}=J.createAccessKey(S,{slug:n,environment:i});return c[C]=b,{user:f,accessKey:b,policy:h,userLogicalId:S,accessKeyLogicalId:C,policyLogicalId:y,resources:c}}static CiCdPolicies={s3Deployment:(a)=>[{sid:"S3ListBuckets",actions:["s3:ListBucket","s3:GetBucketLocation"],resources:a},{sid:"S3Objects",actions:["s3:GetObject","s3:PutObject","s3:DeleteObject"],resources:a.map((n)=>`${n}/*`)}],cloudFrontInvalidation:(a)=>[{sid:"CloudFrontInvalidation",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations"],resources:a}],ecsDeployment:()=>[{sid:"ECSServices",actions:["ecs:DescribeServices","ecs:UpdateService","ecs:DescribeTaskDefinition","ecs:RegisterTaskDefinition"],resources:"*"},{sid:"ECSPassRole",actions:["iam:PassRole"],resources:"*",conditions:{StringLike:{"iam:PassedToService":"ecs-tasks.amazonaws.com"}}}],ecrPush:(a)=>[{sid:"ECRAuth",actions:["ecr:GetAuthorizationToken"],resources:"*"},{sid:"ECRPush",actions:["ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:PutImage"],resources:a}],lambdaDeployment:(a)=>[{sid:"LambdaDeploy",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion"],resources:a}],cloudFormationDeployment:(a)=>[{sid:"CloudFormationDeploy",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate"],resources:a}]}}class id{static createRestApi(a){let{slug:n,environment:i,name:s,description:c,endpointType:l="REGIONAL",binaryMediaTypes:u,compressionSize:h}=a,y=s||r({slug:n,environment:i,resourceType:"rest-api"}),f=t(y),S={Type:"AWS::ApiGateway::RestApi",Properties:{Name:y,Description:c||`REST API for ${n} ${i}`,EndpointConfiguration:{Types:[l]},Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:i}]}};if(u&&u.length>0)S.Properties.BinaryMediaTypes=u;if(h!==void 0)S.Properties.MinimumCompressionSize=h;return{restApi:S,logicalId:f}}static createHttpApi(a){let{slug:n,environment:i,name:s,description:c,corsEnabled:l=!0,corsOrigins:u=["*"],corsMethods:h=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],corsHeaders:y=["*"],corsMaxAge:f=86400,corsAllowCredentials:S=!1}=a,b=s||r({slug:n,environment:i,resourceType:"http-api"}),C=t(b),T={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:b,Description:c||`HTTP API for ${n} ${i}`,ProtocolType:"HTTP",Tags:{Name:b,Environment:i}}};if(l)T.Properties.CorsConfiguration={AllowOrigins:u,AllowMethods:h,AllowHeaders:y,MaxAge:f,AllowCredentials:S};return{httpApi:T,logicalId:C}}static createWebSocketApi(a){let{slug:n,environment:i,name:s,description:c}=a,l=s||r({slug:n,environment:i,resourceType:"ws-api"}),u=t(l);return{webSocketApi:{Type:"AWS::ApiGatewayV2::Api",Properties:{Name:l,Description:c||`WebSocket API for ${n} ${i}`,ProtocolType:"WEBSOCKET",Tags:{Name:l,Environment:i}}},logicalId:u}}static createDeployment(a,n){let{slug:i,environment:s,description:c}=n,l=r({slug:i,environment:s,resourceType:"api-deployment"}),u=t(l);return{deployment:{Type:"AWS::ApiGateway::Deployment",Properties:{RestApiId:N.Ref(a),Description:c||`Deployment for ${l}`}},logicalId:u}}static createStage(a,n,i){let{slug:s,environment:c,stageName:l,description:u,cacheEnabled:h=!1,cacheSize:y="0.5",variables:f,throttling:S}=i,b=r({slug:s,environment:c,resourceType:"api-stage"}),C=t(b),T={Type:"AWS::ApiGateway::Stage",Properties:{StageName:l||c,RestApiId:N.Ref(a),DeploymentId:N.Ref(n),Description:u,CacheClusterEnabled:h,Tags:[{Key:"Name",Value:b},{Key:"Environment",Value:c}]}};if(h)T.Properties.CacheClusterSize=y;if(f)T.Properties.Variables=f;if(S)T.Properties.MethodSettings=[{HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:S.burstLimit,ThrottlingRateLimit:S.rateLimit}];return{stage:T,logicalId:C}}static createAuthorizer(a,n){let{slug:i,environment:s,name:c,type:l,functionArn:u,identitySource:h,userPoolArns:y,ttl:f=300}=n,S=c||r({slug:i,environment:s,resourceType:"api-authorizer"}),b=t(S),C={Type:"AWS::ApiGateway::Authorizer",Properties:{Name:S,Type:l,RestApiId:N.Ref(a),AuthorizerResultTtlInSeconds:f}};if(l==="TOKEN"||l==="REQUEST"){if(!u)throw Error("Lambda authorizer requires functionArn");C.Properties.AuthorizerUri=u,C.Properties.IdentitySource=h||"method.request.header.Authorization"}if(l==="COGNITO_USER_POOLS"){if(!y||y.length===0)throw Error("Cognito authorizer requires userPoolArns");C.Properties.ProviderARNs=y,C.Properties.IdentitySource=h||"method.request.header.Authorization"}return{authorizer:C,logicalId:b}}static setCors(a,n={}){let{origins:i=["*"],methods:s=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],headers:c=["*"],maxAge:l=86400,allowCredentials:u=!1}=n;return a.Properties.CorsConfiguration={AllowOrigins:i,AllowMethods:s,AllowHeaders:c,MaxAge:l,AllowCredentials:u},a}static addThrottling(a,n=5000,i=1e4){if(!a.Properties.MethodSettings)a.Properties.MethodSettings=[];return a.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:n,ThrottlingRateLimit:i}),a}static enableCaching(a,n="0.5",i=300){if(a.Properties.CacheClusterEnabled=!0,a.Properties.CacheClusterSize=n,!a.Properties.MethodSettings)a.Properties.MethodSettings=[];return a.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",CachingEnabled:!0,CacheTtlInSeconds:i}),a}static CacheSizes={Small:"0.5",Medium:"1.6",Large:"6.1",XLarge:"13.5",XXLarge:"28.4",XXXLarge:"58.2",Huge:"118",Massive:"237"};static ThrottlingPresets={Light:{burstLimit:100,rateLimit:50},Medium:{burstLimit:500,rateLimit:250},Heavy:{burstLimit:2000,rateLimit:1000},Default:{burstLimit:5000,rateLimit:1e4}}}class X{static createTopic(a){let{slug:n,environment:i,topicName:s,displayName:c,encrypted:l=!1,kmsKeyId:u}=a,h=s||r({slug:n,environment:i,resourceType:"topic"}),y=t(h),f={Type:"AWS::SNS::Topic",Properties:{TopicName:h,DisplayName:c||h,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:i}]}};if(l&&u)f.Properties.KmsMasterKeyId=u;return{topic:f,logicalId:y}}static subscribe(a,n){let{slug:i,environment:s,protocol:c,endpoint:l,filterPolicy:u,rawMessageDelivery:h=!1}=n,y=r({slug:i,environment:s,resourceType:"subscription"}),f=l.replace(/[^a-zA-Z0-9]/g,""),S=f.length>12?f.slice(-12):f,b=t(`${y}-${c}-${S}`),C={Type:"AWS::SNS::Subscription",Properties:{TopicArn:N.Ref(a),Protocol:c,Endpoint:l,RawMessageDelivery:h}};if(u)C.Properties.FilterPolicy=u;return{subscription:C,logicalId:b}}static subscribeEmail(a,n,i){return X.subscribe(a,{...i,protocol:"email",endpoint:n})}static subscribeLambda(a,n,i){return X.subscribe(a,{...i,protocol:"lambda",endpoint:n,rawMessageDelivery:!0})}static subscribeSqs(a,n,i){return X.subscribe(a,{...i,protocol:"sqs",endpoint:n})}static subscribeHttp(a,n,i){let s=n.startsWith("https://")?"https":"http";return X.subscribe(a,{...i,protocol:s,endpoint:n})}static subscribeSms(a,n,i){return X.subscribe(a,{...i,protocol:"sms",endpoint:n})}static setTopicPolicy(a,n){let{slug:i,environment:s,allowedPrincipals:c,allowedServices:l,actions:u="SNS:Publish"}=n,h=r({slug:i,environment:s,resourceType:"topic-policy"}),y=t(h),f={};if(c)f.AWS=c;if(l)f.Service=l;return{policy:{Type:"AWS::SNS::TopicPolicy",Properties:{Topics:[N.Ref(a)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:f,Action:u,Resource:N.Ref(a)}]}}},logicalId:y}}static allowCloudWatchAlarms(a,n){return X.setTopicPolicy(a,{...n,allowedServices:"cloudwatch.amazonaws.com",actions:"SNS:Publish"})}static allowEventBridge(a,n){return X.setTopicPolicy(a,{...n,allowedServices:"events.amazonaws.com",actions:"SNS:Publish"})}static allowS3(a,n){return X.setTopicPolicy(a,{...n,allowedServices:"s3.amazonaws.com",actions:"SNS:Publish"})}static enableEncryption(a,n){if(!a.Properties)a.Properties={};return a.Properties.KmsMasterKeyId=n,a}static addInlineSubscription(a,n,i){if(!a.Properties)a.Properties={};if(!a.Properties.Subscription)a.Properties.Subscription=[];return a.Properties.Subscription.push({Protocol:n,Endpoint:i}),a}static FilterPolicies={eventType:(a)=>({eventType:a}),status:(a)=>({status:a}),numericRange:(a,n,i)=>({[a]:[{numeric:[">=",n,"<=",i]}]}),prefix:(a,n)=>({[a]:[{prefix:n}]}),and:(...a)=>Object.assign({},...a),exists:(a,n)=>({[a]:[{exists:n}]})};static UseCases={createAlertTopic:(a)=>X.createTopic({...a,topicName:a.topicName||`${a.slug}-${a.environment}-alerts`,displayName:a.displayName||"Alert Notifications"}),createEventFanout:(a)=>X.createTopic({...a,topicName:a.topicName||`${a.slug}-${a.environment}-events`,displayName:a.displayName||"Event Fanout"}),createNotificationTopic:(a)=>X.createTopic({...a,topicName:a.topicName||`${a.slug}-${a.environment}-notifications`,displayName:a.displayName||"User Notifications"})}}class df{static createStateMachine(a){let{slug:n,environment:i,stateMachineName:s,type:c="STANDARD",definition:l,roleArn:u,loggingConfiguration:h,tracingConfiguration:y}=a,f=s||r({slug:n,environment:i,resourceType:"state-machine"}),S=t(f),b,C,T;if(u)T=u;else{let w=r({slug:n,environment:i,resourceType:"state-machine-role"});C=t(w),b={Type:"AWS::IAM::Role",Properties:{RoleName:w,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"states.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/CloudWatchLogsFullAccess"],Tags:[{Key:"Name",Value:w},{Key:"Environment",Value:i}]}},T=N.GetAtt(C,"Arn")}let v={Type:"AWS::StepFunctions::StateMachine",Properties:{StateMachineName:f,StateMachineType:c,DefinitionString:JSON.stringify(l),RoleArn:T,Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:i}]}};if(h)v.Properties.LoggingConfiguration={Level:h.level,IncludeExecutionData:h.includeExecutionData,Destinations:h.destinations?.map((w)=>({CloudWatchLogsLogGroup:{LogGroupArn:w}}))};if(y)v.Properties.TracingConfiguration={Enabled:y.enabled};return{stateMachine:v,logicalId:S,role:b,roleLogicalId:C}}static createLambdaTask(a,n){return{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Parameters:{FunctionName:a,Payload:n?.parameters||{"Input.$":"$"}},ResultPath:n?.resultPath,Retry:n?.retry,Catch:n?.catch,Next:n?.next,End:n?.end}}static createDynamoDBTask(a,n,i,s){return{Type:"Task",Resource:{GetItem:"arn:aws:states:::dynamodb:getItem",PutItem:"arn:aws:states:::dynamodb:putItem",UpdateItem:"arn:aws:states:::dynamodb:updateItem",DeleteItem:"arn:aws:states:::dynamodb:deleteItem"}[a],Parameters:{TableName:n,...i},ResultPath:s?.resultPath,Retry:s?.retry,Catch:s?.catch,Next:s?.next,End:s?.end}}static createSNSPublishTask(a,n,i){return{Type:"Task",Resource:"arn:aws:states:::sns:publish",Parameters:{TopicArn:a,Message:n},ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createSQSSendMessageTask(a,n,i){return{Type:"Task",Resource:"arn:aws:states:::sqs:sendMessage",Parameters:{QueueUrl:a,MessageBody:n},ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createPassState(a){return{Type:"Pass",Result:a?.result,ResultPath:a?.resultPath,Parameters:a?.parameters,Next:a?.next,End:a?.end}}static createWaitState(a){return{Type:"Wait",Seconds:a.seconds,Timestamp:a.timestamp,SecondsPath:a.secondsPath,TimestampPath:a.timestampPath,Next:a.next,End:a.end}}static createChoiceState(a,n){return{Type:"Choice",Choices:a,Default:n}}static createParallelState(a,n){return{Type:"Parallel",Branches:a,ResultPath:n?.resultPath,Retry:n?.retry,Catch:n?.catch,Next:n?.next,End:n?.end}}static createMapState(a,n){return{Type:"Map",ItemsPath:n?.itemsPath||"$.items",Iterator:a,MaxConcurrency:n?.maxConcurrency,ResultPath:n?.resultPath,Retry:n?.retry,Catch:n?.catch,Next:n?.next,End:n?.end}}static createSucceedState(){return{Type:"Succeed"}}static createFailState(a,n){return{Type:"Fail",Error:a,Cause:n}}static RetryPolicies={standard:()=>({ErrorEquals:["States.ALL"],IntervalSeconds:2,MaxAttempts:3,BackoffRate:2}),aggressive:()=>({ErrorEquals:["States.TaskFailed","States.Timeout"],IntervalSeconds:1,MaxAttempts:5,BackoffRate:1.5}),custom:(a,n,i,s)=>({ErrorEquals:a,IntervalSeconds:n,MaxAttempts:i,BackoffRate:s})};static CatchPolicies={all:(a,n)=>({ErrorEquals:["States.ALL"],Next:a,ResultPath:n||"$.error"}),specific:(a,n,i)=>({ErrorEquals:a,Next:n,ResultPath:i||"$.error"})};static Patterns={sequential:(a,n,i)=>{let s={};return i.forEach((c,l)=>{let u=l===i.length-1;s[c.name]={...c.state,Next:u?void 0:i[l+1].name,End:u}}),{Comment:"Sequential workflow",StartAt:i[0].name,States:s}},fanout:(a,n,i)=>({Comment:"Fan-out workflow",StartAt:"Parallel",States:{Parallel:{Type:"Parallel",Branches:i.map((s)=>s.definition),End:!0}}}),map:(a,n,i,s)=>({Comment:"Map workflow",StartAt:"Map",States:{Map:{Type:"Map",ItemsPath:"$.items",Iterator:i,MaxConcurrency:s,End:!0}}}),withErrorHandling:(a,n,i,s)=>({Comment:"Workflow with error handling",StartAt:"Main",States:{Main:{...i,Catch:[{ErrorEquals:["States.ALL"],Next:"ErrorHandler"}],Next:"Success"},ErrorHandler:s,Success:{Type:"Succeed"}}})}}class qs{static createAlarm(a){let{slug:n,environment:i,alarmName:s,metricName:c,namespace:l,statistic:u="Average",period:h=300,evaluationPeriods:y=1,threshold:f,comparisonOperator:S,treatMissingData:b="notBreaching",actionsEnabled:C=!0,alarmActions:T,okActions:v,insufficientDataActions:w,dimensions:R,unit:k,datapointsToAlarm:W}=a,P=s||r({slug:n,environment:i,resourceType:"alarm"}),V=t(P),B={Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:P,MetricName:c,Namespace:l,Statistic:u,Period:h,EvaluationPeriods:y,Threshold:f,ComparisonOperator:S,TreatMissingData:b,ActionsEnabled:C}};if(T&&T.length>0)B.Properties.AlarmActions=T;if(v&&v.length>0)B.Properties.OKActions=v;if(w&&w.length>0)B.Properties.InsufficientDataActions=w;if(R)B.Properties.Dimensions=Object.entries(R).map(([j,Z])=>({Name:j,Value:Z}));if(k)B.Properties.Unit=k;if(W!==void 0)B.Properties.DatapointsToAlarm=W;return{alarm:B,logicalId:V}}static createCompositeAlarm(a){let{slug:n,environment:i,alarmName:s,alarmRule:c,actionsEnabled:l=!0,alarmActions:u,okActions:h,insufficientDataActions:y}=a,f=s||r({slug:n,environment:i,resourceType:"composite-alarm"}),S=t(f),b={Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:f,AlarmRule:c,ActionsEnabled:l}};if(u&&u.length>0)b.Properties.AlarmActions=u;if(h&&h.length>0)b.Properties.OKActions=h;if(y&&y.length>0)b.Properties.InsufficientDataActions=y;return{alarm:b,logicalId:S}}static createDashboard(a){let{slug:n,environment:i,dashboardName:s,widgets:c}=a,l=s||r({slug:n,environment:i,resourceType:"dashboard"}),u=t(l),h={widgets:c.map((y)=>({type:y.type,x:y.x,y:y.y,width:y.width,height:y.height,properties:y.properties}))};return{dashboard:{Type:"AWS::CloudWatch::Dashboard",Properties:{DashboardName:l,DashboardBody:JSON.stringify(h)}},logicalId:u}}static createLogGroup(a){let{slug:n,environment:i,logGroupName:s,retentionInDays:c,kmsKeyId:l}=a,u=s||r({slug:n,environment:i,resourceType:"log-group"}),h=t(u),y={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:u}};if(c!==void 0)y.Properties.RetentionInDays=c;if(l)y.Properties.KmsKeyId=l;return{logGroup:y,logicalId:h}}static createLogStream(a,n){let{slug:i,environment:s,logStreamName:c}=n,l=c||r({slug:i,environment:s,resourceType:"log-stream"}),u=t(l);return{logStream:{Type:"AWS::Logs::LogStream",Properties:{LogGroupName:N.Ref(a),LogStreamName:l}},logicalId:u}}static createMetricFilter(a,n){let{slug:i,environment:s,filterName:c,filterPattern:l,metricTransformations:u}=n,h=c||r({slug:i,environment:s,resourceType:"metric-filter"}),y=t(h);return{metricFilter:{Type:"AWS::Logs::MetricFilter",Properties:{LogGroupName:N.Ref(a),FilterPattern:l,MetricTransformations:u.map((f)=>({MetricName:f.metricName,MetricNamespace:f.metricNamespace,MetricValue:f.metricValue,DefaultValue:f.defaultValue,Unit:f.unit}))}},logicalId:y}}static AlarmTypes={highCpu:(a,n,i,s=80,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-high-cpu`,metricName:"CPUUtilization",namespace:"AWS/EC2",statistic:"Average",period:300,evaluationPeriods:2,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:i},alarmActions:c?[c]:void 0}),highMemory:(a,n,i,s=80,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-high-memory`,metricName:"MemoryUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:i},alarmActions:c?[c]:void 0}),highDisk:(a,n,i,s=80,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-high-disk`,metricName:"DiskSpaceUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:i,Filesystem:"/dev/xvda1",MountPath:"/"},alarmActions:c?[c]:void 0}),lambdaErrors:(a,n,i,s=5,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-lambda-errors`,metricName:"Errors",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:i},alarmActions:c?[c]:void 0}),lambdaThrottles:(a,n,i,s=10,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-lambda-throttles`,metricName:"Throttles",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:i},alarmActions:c?[c]:void 0}),apiGateway5xxErrors:(a,n,i,s=10,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-api-5xx-errors`,metricName:"5XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:i},alarmActions:c?[c]:void 0}),apiGateway4xxErrors:(a,n,i,s=50,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-api-4xx-errors`,metricName:"4XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:2,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:i},alarmActions:c?[c]:void 0}),dynamoDBThrottles:(a,n,i,s=5,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-dynamodb-throttles`,metricName:"UserErrors",namespace:"AWS/DynamoDB",statistic:"Sum",period:300,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{TableName:i},alarmActions:c?[c]:void 0}),rdsCpu:(a,n,i,s=80,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-rds-cpu`,metricName:"CPUUtilization",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:2,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{DBInstanceIdentifier:i},alarmActions:c?[c]:void 0}),rdsFreeStorage:(a,n,i,s=5368709120,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-rds-storage`,metricName:"FreeStorageSpace",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:1,threshold:s,comparisonOperator:"LessThanThreshold",dimensions:{DBInstanceIdentifier:i},alarmActions:c?[c]:void 0,unit:"Bytes"}),sqsQueueDepth:(a,n,i,s=100,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-sqs-depth`,metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",statistic:"Average",period:300,evaluationPeriods:2,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{QueueName:i},alarmActions:c?[c]:void 0}),albUnhealthyTargets:(a,n,i,s,c=1,l)=>({slug:a,environment:n,alarmName:`${a}-${n}-alb-unhealthy`,metricName:"UnHealthyHostCount",namespace:"AWS/ApplicationELB",statistic:"Average",period:300,evaluationPeriods:2,threshold:c,comparisonOperator:"GreaterThanThreshold",dimensions:{LoadBalancer:i,TargetGroup:s},alarmActions:l?[l]:void 0}),sesBounceRate:(a,n,i=5,s)=>({slug:a,environment:n,alarmName:`${a}-${n}-ses-bounce-rate`,metricName:"Reputation.BounceRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:i/100,comparisonOperator:"GreaterThanThreshold",alarmActions:s?[s]:void 0}),sesComplaintRate:(a,n,i=0.1,s)=>({slug:a,environment:n,alarmName:`${a}-${n}-ses-complaint-rate`,metricName:"Reputation.ComplaintRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:i/100,comparisonOperator:"GreaterThanThreshold",alarmActions:s?[s]:void 0}),smsDeliveryFailure:(a,n,i,s=10,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-sms-delivery-failure`,metricName:"DirectSendMessagePermanentFailure",namespace:"AWS/Pinpoint",statistic:"Sum",period:300,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{ApplicationId:i},alarmActions:c?[c]:void 0}),smsSpendLimit:(a,n,i=100,s)=>({slug:a,environment:n,alarmName:`${a}-${n}-sms-spend-limit`,metricName:"DirectSendMessageSpend",namespace:"AWS/Pinpoint",statistic:"Sum",period:86400,evaluationPeriods:1,threshold:i,comparisonOperator:"GreaterThanThreshold",alarmActions:s?[s]:void 0}),connectMissedCalls:(a,n,i,s=5,c)=>({slug:a,environment:n,alarmName:`${a}-${n}-connect-missed-calls`,metricName:"MissedCalls",namespace:"AWS/Connect",statistic:"Sum",period:3600,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:i},alarmActions:c?[c]:void 0})};static DashboardWidgets={metric:(a,n,i,s,c,l)=>({type:"metric",x:a,y:n,width:i,height:s,properties:{metrics:c,title:l||"Metrics",region:"us-east-1",period:300}}),text:(a,n,i,s,c)=>({type:"text",x:a,y:n,width:i,height:s,properties:{markdown:c}}),log:(a,n,i,s,c,l)=>({type:"log",x:a,y:n,width:i,height:s,properties:{query:`SOURCE '${c.join("' | SOURCE '")}'
|
|
2310
2310
|
| fields @timestamp, @message
|
|
2311
2311
|
| sort @timestamp desc
|
|
2312
2312
|
| limit 20`,region:"us-east-1",title:l||"Logs"}})};static RetentionPeriods={ONE_DAY:1,THREE_DAYS:3,FIVE_DAYS:5,ONE_WEEK:7,TWO_WEEKS:14,ONE_MONTH:30,TWO_MONTHS:60,THREE_MONTHS:90,FOUR_MONTHS:120,FIVE_MONTHS:150,SIX_MONTHS:180,ONE_YEAR:365,THIRTEEN_MONTHS:400,EIGHTEEN_MONTHS:545,TWO_YEARS:731,FIVE_YEARS:1827,TEN_YEARS:3653,NEVER_EXPIRE:void 0};static FilterPatterns={errors:"[time, request_id, event_type = ERROR*, ...]",all:"",jsonField:(a,n)=>`{ $.${a} = "${n}" }`,httpStatus:(a)=>`[..., status_code = ${a}, ...]`,http4xx:"[..., status_code = 4*, ...]",http5xx:"[..., status_code = 5*, ...]"};static createApplicationDashboard(a){let{slug:n,environment:i,region:s="us-east-1",components:c={}}=a,l=[],u=0;if(l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:`# ${n.toUpperCase()} Dashboard (${i})`}}),u+=1,c.ec2InstanceIds&&c.ec2InstanceIds.length>0)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## EC2 Instances"}}),u+=1,l.push({type:"metric",x:0,y:u,width:8,height:6,properties:{title:"CPU Utilization",region:s,metrics:c.ec2InstanceIds.map((h)=>["AWS/EC2","CPUUtilization","InstanceId",h]),period:300,stat:"Average"}}),l.push({type:"metric",x:8,y:u,width:8,height:6,properties:{title:"Network Traffic",region:s,metrics:[...c.ec2InstanceIds.flatMap((h)=>[["AWS/EC2","NetworkIn","InstanceId",h,{label:`${h} In`}],["AWS/EC2","NetworkOut","InstanceId",h,{label:`${h} Out`}]])],period:300,stat:"Sum"}}),l.push({type:"metric",x:16,y:u,width:8,height:6,properties:{title:"Status Checks",region:s,metrics:c.ec2InstanceIds.map((h)=>["AWS/EC2","StatusCheckFailed","InstanceId",h]),period:60,stat:"Maximum"}}),u+=6;if(c.lambdaFunctionNames&&c.lambdaFunctionNames.length>0)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## Lambda Functions"}}),u+=1,l.push({type:"metric",x:0,y:u,width:8,height:6,properties:{title:"Invocations",region:s,metrics:c.lambdaFunctionNames.map((h)=>["AWS/Lambda","Invocations","FunctionName",h]),period:300,stat:"Sum"}}),l.push({type:"metric",x:8,y:u,width:8,height:6,properties:{title:"Duration",region:s,metrics:c.lambdaFunctionNames.map((h)=>["AWS/Lambda","Duration","FunctionName",h]),period:300,stat:"Average"}}),l.push({type:"metric",x:16,y:u,width:8,height:6,properties:{title:"Errors",region:s,metrics:c.lambdaFunctionNames.map((h)=>["AWS/Lambda","Errors","FunctionName",h]),period:300,stat:"Sum"}}),u+=6;if(c.ecsClusterName&&c.ecsServiceName)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## ECS Service"}}),u+=1,l.push({type:"metric",x:0,y:u,width:8,height:6,properties:{title:"CPU Utilization",region:s,metrics:[["AWS/ECS","CPUUtilization","ClusterName",c.ecsClusterName,"ServiceName",c.ecsServiceName]],period:300,stat:"Average"}}),l.push({type:"metric",x:8,y:u,width:8,height:6,properties:{title:"Memory Utilization",region:s,metrics:[["AWS/ECS","MemoryUtilization","ClusterName",c.ecsClusterName,"ServiceName",c.ecsServiceName]],period:300,stat:"Average"}}),l.push({type:"metric",x:16,y:u,width:8,height:6,properties:{title:"Running Tasks",region:s,metrics:[["ECS/ContainerInsights","RunningTaskCount","ClusterName",c.ecsClusterName,"ServiceName",c.ecsServiceName]],period:60,stat:"Average"}}),u+=6;if(c.albName)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## Application Load Balancer"}}),u+=1,l.push({type:"metric",x:0,y:u,width:8,height:6,properties:{title:"Request Count",region:s,metrics:[["AWS/ApplicationELB","RequestCount","LoadBalancer",c.albName]],period:60,stat:"Sum"}}),l.push({type:"metric",x:8,y:u,width:8,height:6,properties:{title:"Response Time",region:s,metrics:[["AWS/ApplicationELB","TargetResponseTime","LoadBalancer",c.albName]],period:60,stat:"Average"}}),l.push({type:"metric",x:16,y:u,width:8,height:6,properties:{title:"HTTP Errors",region:s,metrics:[["AWS/ApplicationELB","HTTPCode_Target_4XX_Count","LoadBalancer",c.albName,{label:"4XX"}],["AWS/ApplicationELB","HTTPCode_Target_5XX_Count","LoadBalancer",c.albName,{label:"5XX"}]],period:60,stat:"Sum"}}),u+=6;if(c.rdsInstanceId)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## RDS Database"}}),u+=1,l.push({type:"metric",x:0,y:u,width:8,height:6,properties:{title:"CPU Utilization",region:s,metrics:[["AWS/RDS","CPUUtilization","DBInstanceIdentifier",c.rdsInstanceId]],period:300,stat:"Average"}}),l.push({type:"metric",x:8,y:u,width:8,height:6,properties:{title:"Database Connections",region:s,metrics:[["AWS/RDS","DatabaseConnections","DBInstanceIdentifier",c.rdsInstanceId]],period:60,stat:"Sum"}}),l.push({type:"metric",x:16,y:u,width:8,height:6,properties:{title:"Free Storage Space",region:s,metrics:[["AWS/RDS","FreeStorageSpace","DBInstanceIdentifier",c.rdsInstanceId]],period:300,stat:"Average"}}),u+=6;if(c.sqsQueueNames&&c.sqsQueueNames.length>0)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## SQS Queues"}}),u+=1,l.push({type:"metric",x:0,y:u,width:12,height:6,properties:{title:"Messages Visible",region:s,metrics:c.sqsQueueNames.map((h)=>["AWS/SQS","ApproximateNumberOfMessagesVisible","QueueName",h]),period:60,stat:"Sum"}}),l.push({type:"metric",x:12,y:u,width:12,height:6,properties:{title:"Message Age",region:s,metrics:c.sqsQueueNames.map((h)=>["AWS/SQS","ApproximateAgeOfOldestMessage","QueueName",h]),period:60,stat:"Maximum"}}),u+=6;if(c.logGroupNames&&c.logGroupNames.length>0)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## Application Logs"}}),u+=1,l.push({type:"log",x:0,y:u,width:24,height:6,properties:{query:`SOURCE '${c.logGroupNames.join("' | SOURCE '")}'
|
|
2313
2313
|
| fields @timestamp, @message
|
|
2314
2314
|
| filter @message like /ERROR|WARN|Exception/
|
|
2315
2315
|
| sort @timestamp desc
|
|
2316
|
-
| limit 50`,region:s,title:"Recent Errors and Warnings"}}),u+=6;return Gs.createDashboard({slug:n,environment:i,widgets:l})}static DashboardTemplates={staticWebsite:(a)=>({slug:a.slug,environment:a.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${a.slug.toUpperCase()} Static Website Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"CloudFront Requests",region:"us-east-1",metrics:[["AWS/CloudFront","Requests","DistributionId",a.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"Error Rate",region:"us-east-1",metrics:[["AWS/CloudFront","4xxErrorRate","DistributionId",a.cloudFrontDistributionId,"Region","Global",{label:"4XX"}],["AWS/CloudFront","5xxErrorRate","DistributionId",a.cloudFrontDistributionId,"Region","Global",{label:"5XX"}]],period:300,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Bytes Downloaded",region:"us-east-1",metrics:[["AWS/CloudFront","BytesDownloaded","DistributionId",a.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:0,y:7,width:12,height:6,properties:{title:"S3 Bucket Size",region:a.region||"us-east-1",metrics:[["AWS/S3","BucketSizeBytes","BucketName",a.s3BucketName,"StorageType","StandardStorage"]],period:86400,stat:"Average"}},{type:"metric",x:12,y:7,width:12,height:6,properties:{title:"S3 Number of Objects",region:a.region||"us-east-1",metrics:[["AWS/S3","NumberOfObjects","BucketName",a.s3BucketName,"StorageType","AllStorageTypes"]],period:86400,stat:"Average"}}]}),serverlessApi:(a)=>({slug:a.slug,environment:a.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${a.slug.toUpperCase()} Serverless API Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"API Requests",region:a.region||"us-east-1",metrics:[["AWS/ApiGateway","Count","ApiName",a.apiGatewayName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"API Latency",region:a.region||"us-east-1",metrics:[["AWS/ApiGateway","Latency","ApiName",a.apiGatewayName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"API Errors",region:a.region||"us-east-1",metrics:[["AWS/ApiGateway","4XXError","ApiName",a.apiGatewayName,{label:"4XX"}],["AWS/ApiGateway","5XXError","ApiName",a.apiGatewayName,{label:"5XX"}]],period:60,stat:"Sum"}},...a.lambdaFunctionNames.map((n,i)=>({type:"metric",x:i%3*8,y:7+Math.floor(i/3)*6,width:8,height:6,properties:{title:`${n} Metrics`,region:a.region||"us-east-1",metrics:[["AWS/Lambda","Invocations","FunctionName",n],["AWS/Lambda","Duration","FunctionName",n],["AWS/Lambda","Errors","FunctionName",n]],period:300,stat:"Sum"}}))]}),containerService:(a)=>({slug:a.slug,environment:a.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${a.slug.toUpperCase()} Container Service Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"ECS CPU",region:a.region||"us-east-1",metrics:[["AWS/ECS","CPUUtilization","ClusterName",a.ecsClusterName,"ServiceName",a.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"ECS Memory",region:a.region||"us-east-1",metrics:[["AWS/ECS","MemoryUtilization","ClusterName",a.ecsClusterName,"ServiceName",a.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Running Tasks",region:a.region||"us-east-1",metrics:[["ECS/ContainerInsights","RunningTaskCount","ClusterName",a.ecsClusterName,"ServiceName",a.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:0,y:7,width:8,height:6,properties:{title:"ALB Requests",region:a.region||"us-east-1",metrics:[["AWS/ApplicationELB","RequestCount","LoadBalancer",a.albName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:7,width:8,height:6,properties:{title:"Response Time",region:a.region||"us-east-1",metrics:[["AWS/ApplicationELB","TargetResponseTime","LoadBalancer",a.albName]],period:60,stat:"Average"}},{type:"metric",x:16,y:7,width:8,height:6,properties:{title:"Healthy Hosts",region:a.region||"us-east-1",metrics:[["AWS/ApplicationELB","HealthyHostCount","LoadBalancer",a.albName]],period:60,stat:"Average"}},...a.rdsInstanceId?[{type:"metric",x:0,y:13,width:12,height:6,properties:{title:"RDS CPU",region:a.region||"us-east-1",metrics:[["AWS/RDS","CPUUtilization","DBInstanceIdentifier",a.rdsInstanceId]],period:300,stat:"Average"}},{type:"metric",x:12,y:13,width:12,height:6,properties:{title:"RDS Connections",region:a.region||"us-east-1",metrics:[["AWS/RDS","DatabaseConnections","DBInstanceIdentifier",a.rdsInstanceId]],period:60,stat:"Sum"}}]:[]]})};static Config={createAlarmConfig:(a)=>{let{metricName:n,namespace:i,threshold:s,comparisonOperator:c="GreaterThanThreshold",evaluationPeriods:l=1,period:u=300,statistic:h="Average",treatMissingData:y="missing"}=a;return{MetricName:n,Namespace:i,Threshold:s,ComparisonOperator:c,EvaluationPeriods:l,Period:u,Statistic:h,TreatMissingData:y}},namespaces:{ec2:"AWS/EC2",ecs:"AWS/ECS",lambda:"AWS/Lambda",rds:"AWS/RDS",sqs:"AWS/SQS",sns:"AWS/SNS",s3:"AWS/S3",cloudfront:"AWS/CloudFront",alb:"AWS/ApplicationELB",nlb:"AWS/NetworkELB",apiGateway:"AWS/ApiGateway",dynamodb:"AWS/DynamoDB",elasticache:"AWS/ElastiCache"},comparisonOperators:{greaterThan:"GreaterThanThreshold",greaterOrEqual:"GreaterThanOrEqualToThreshold",lessThan:"LessThanThreshold",lessOrEqual:"LessThanOrEqualToThreshold"},metrics:{ec2:{cpu:{metricName:"CPUUtilization",namespace:"AWS/EC2"},networkIn:{metricName:"NetworkIn",namespace:"AWS/EC2"},networkOut:{metricName:"NetworkOut",namespace:"AWS/EC2"},statusCheck:{metricName:"StatusCheckFailed",namespace:"AWS/EC2"}},ecs:{cpu:{metricName:"CPUUtilization",namespace:"AWS/ECS"},memory:{metricName:"MemoryUtilization",namespace:"AWS/ECS"}},lambda:{invocations:{metricName:"Invocations",namespace:"AWS/Lambda"},errors:{metricName:"Errors",namespace:"AWS/Lambda"},duration:{metricName:"Duration",namespace:"AWS/Lambda"},throttles:{metricName:"Throttles",namespace:"AWS/Lambda"},concurrentExecutions:{metricName:"ConcurrentExecutions",namespace:"AWS/Lambda"}},rds:{cpu:{metricName:"CPUUtilization",namespace:"AWS/RDS"},connections:{metricName:"DatabaseConnections",namespace:"AWS/RDS"},freeStorage:{metricName:"FreeStorageSpace",namespace:"AWS/RDS"},readLatency:{metricName:"ReadLatency",namespace:"AWS/RDS"},writeLatency:{metricName:"WriteLatency",namespace:"AWS/RDS"}},alb:{requestCount:{metricName:"RequestCount",namespace:"AWS/ApplicationELB"},responseTime:{metricName:"TargetResponseTime",namespace:"AWS/ApplicationELB"},httpCode4xx:{metricName:"HTTPCode_Target_4XX_Count",namespace:"AWS/ApplicationELB"},httpCode5xx:{metricName:"HTTPCode_Target_5XX_Count",namespace:"AWS/ApplicationELB"},healthyHosts:{metricName:"HealthyHostCount",namespace:"AWS/ApplicationELB"}},sqs:{messagesVisible:{metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS"},messagesDelayed:{metricName:"ApproximateNumberOfMessagesDelayed",namespace:"AWS/SQS"},messageAge:{metricName:"ApproximateAgeOfOldestMessage",namespace:"AWS/SQS"}}},presets:{highCpu:(a=80)=>({metricName:"CPUUtilization",threshold:a,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highMemory:(a=80)=>({metricName:"MemoryUtilization",threshold:a,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highErrors:(a=10)=>({metricName:"Errors",threshold:a,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:1,period:60,statistic:"Sum"}),highLatency:(a=5000)=>({metricName:"Duration",threshold:a,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowHealthyHosts:(a=1)=>({metricName:"HealthyHostCount",namespace:"AWS/ApplicationELB",threshold:a,comparisonOperator:"LessThanThreshold",evaluationPeriods:2,period:60,statistic:"Minimum"}),queueDepth:(a=1000)=>({metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",threshold:a,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowStorage:(a=10737418240)=>({metricName:"FreeStorageSpace",namespace:"AWS/RDS",threshold:a,comparisonOperator:"LessThanThreshold",evaluationPeriods:1,period:300,statistic:"Average"})}}}class U{static createUserPool(a){let{slug:n,environment:i,userPoolName:s,aliasAttributes:c,autoVerifiedAttributes:l,passwordPolicy:u,mfaConfiguration:h,emailConfiguration:y,smsConfiguration:f,lambdaTriggers:S,userPoolAddOns:b,accountRecoverySetting:C}=a,T=s||r({slug:n,environment:i,resourceType:"user-pool"}),v=t(T),w={Type:"AWS::Cognito::UserPool",Properties:{UserPoolName:T,Policies:u?{PasswordPolicy:{MinimumLength:u.minimumLength,RequireLowercase:u.requireLowercase,RequireUppercase:u.requireUppercase,RequireNumbers:u.requireNumbers,RequireSymbols:u.requireSymbols,TemporaryPasswordValidityDays:u.temporaryPasswordValidityDays}}:void 0,MfaConfiguration:h,Schema:[{Name:"email",AttributeDataType:"String",Required:!0,Mutable:!1}]}};if(c&&c.length>0)w.Properties.UsernameAttributes=c;if(l&&l.length>0)w.Properties.AutoVerifiedAttributes=l;if(y)w.Properties.EmailConfiguration={EmailSendingAccount:y.emailSendingAccount,From:y.from,ReplyToEmailAddress:y.replyToEmailAddress,SourceArn:y.sourceArn,ConfigurationSet:y.configurationSet};if(f)w.Properties.SmsConfiguration={ExternalId:f.externalId,SnsCallerArn:f.snsCallerArn};if(S)w.Properties.LambdaConfig={PreSignUp:S.preSignUp,PostConfirmation:S.postConfirmation,PreAuthentication:S.preAuthentication,PostAuthentication:S.postAuthentication,CustomMessage:S.customMessage,DefineAuthChallenge:S.defineAuthChallenge,CreateAuthChallenge:S.createAuthChallenge,VerifyAuthChallengeResponse:S.verifyAuthChallengeResponse,PreTokenGeneration:S.preTokenGeneration,UserMigration:S.userMigration};if(b)w.Properties.UserPoolAddOns={AdvancedSecurityMode:b.advancedSecurityMode};if(C)w.Properties.AccountRecoverySetting={RecoveryMechanisms:C.recoveryMechanisms};return{userPool:w,logicalId:v}}static createUserPoolClient(a,n){let{slug:i,environment:s,clientName:c,generateSecret:l=!1,refreshTokenValidity:u,accessTokenValidity:h,idTokenValidity:y,tokenValidityUnits:f,readAttributes:S,writeAttributes:b,explicitAuthFlows:C,preventUserExistenceErrors:T,enableTokenRevocation:v,callbackURLs:w,logoutURLs:R,allowedOAuthFlows:k,allowedOAuthScopes:W,allowedOAuthFlowsUserPoolClient:P,supportedIdentityProviders:V}=n,B=c||r({slug:i,environment:s,resourceType:"user-pool-client"}),j=t(B);return{client:{Type:"AWS::Cognito::UserPoolClient",Properties:{ClientName:B,UserPoolId:N.Ref(a),GenerateSecret:l,RefreshTokenValidity:u,AccessTokenValidity:h,IdTokenValidity:y,TokenValidityUnits:f,ReadAttributes:S,WriteAttributes:b,ExplicitAuthFlows:C,PreventUserExistenceErrors:T,EnableTokenRevocation:v,CallbackURLs:w,LogoutURLs:R,AllowedOAuthFlows:k,AllowedOAuthScopes:W,AllowedOAuthFlowsUserPoolClient:P,SupportedIdentityProviders:V}},logicalId:j}}static createUserPoolDomain(a,n){let{slug:i,environment:s,domain:c,customDomainConfig:l}=n,u=r({slug:i,environment:s,resourceType:"user-pool-domain"}),h=t(u);return{domain:{Type:"AWS::Cognito::UserPoolDomain",Properties:{Domain:c,UserPoolId:N.Ref(a),CustomDomainConfig:l}},logicalId:h}}static createIdentityPool(a){let{slug:n,environment:i,identityPoolName:s,allowUnauthenticatedIdentities:c=!1,cognitoIdentityProviders:l,supportedLoginProviders:u,samlProviderARNs:h,openIdConnectProviderARNs:y}=a,f=s||r({slug:n,environment:i,resourceType:"identity-pool"}),S=t(f);return{identityPool:{Type:"AWS::Cognito::IdentityPool",Properties:{IdentityPoolName:f,AllowUnauthenticatedIdentities:c,CognitoIdentityProviders:l,SupportedLoginProviders:u,SamlProviderARNs:h,OpenIdConnectProviderARNs:y}},logicalId:S}}static createIdentityPoolRoleAttachment(a,n){let{slug:i,environment:s,authenticatedRole:c,unauthenticatedRole:l,roleMappings:u}=n,h=r({slug:i,environment:s,resourceType:"identity-pool-role-attachment"}),y=t(h),f={authenticated:c};if(l)f.unauthenticated=l;return{attachment:{Type:"AWS::Cognito::IdentityPoolRoleAttachment",Properties:{IdentityPoolId:N.Ref(a),Roles:f,RoleMappings:u}},logicalId:y}}static createAuthenticatedRole(a){let{slug:n,environment:i,identityPoolLogicalId:s}=a,c=r({slug:n,environment:i,resourceType:"cognito-authenticated-role"}),l=t(c);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:c,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":N.Ref(s)},"ForAnyValue:StringLike":{"cognito-identity.amazonaws.com:amr":"authenticated"}}}]},Policies:[{PolicyName:"CognitoAuthenticatedPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["cognito-sync:*","cognito-identity:*"],Resource:"*"}]}}],Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:i}]}},logicalId:l}}static createUnauthenticatedRole(a){let{slug:n,environment:i,identityPoolLogicalId:s}=a,c=r({slug:n,environment:i,resourceType:"cognito-unauthenticated-role"}),l=t(c);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:c,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":N.Ref(s)},"ForAnyValue:StringLike":{"cognito-identity.amazonaws.com:amr":"unauthenticated"}}}]},Policies:[{PolicyName:"CognitoUnauthenticatedPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["cognito-sync:*"],Resource:"*"}]}}],Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:i}]}},logicalId:l}}static PasswordPolicies={relaxed:()=>({minimumLength:8,requireLowercase:!1,requireUppercase:!1,requireNumbers:!1,requireSymbols:!1,temporaryPasswordValidityDays:7}),standard:()=>({minimumLength:8,requireLowercase:!0,requireUppercase:!0,requireNumbers:!0,requireSymbols:!1,temporaryPasswordValidityDays:3}),strict:()=>({minimumLength:12,requireLowercase:!0,requireUppercase:!0,requireNumbers:!0,requireSymbols:!0,temporaryPasswordValidityDays:1})};static AuthFlows={standard:["ALLOW_USER_SRP_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],admin:["ALLOW_ADMIN_USER_PASSWORD_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],custom:["ALLOW_CUSTOM_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],all:["ALLOW_USER_SRP_AUTH","ALLOW_USER_PASSWORD_AUTH","ALLOW_ADMIN_USER_PASSWORD_AUTH","ALLOW_CUSTOM_AUTH","ALLOW_REFRESH_TOKEN_AUTH"]};static OAuthScopes={basic:["openid","email","profile"],all:["openid","email","profile","phone","aws.cognito.signin.user.admin"]};static UseCases={webApp:(a,n,i)=>{let{userPool:s,logicalId:c}=U.createUserPool({slug:a,environment:n,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:U.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:l,logicalId:u}=U.createUserPoolClient(c,{slug:a,environment:n,explicitAuthFlows:[...U.AuthFlows.standard],callbackURLs:[i],allowedOAuthFlows:["code"],allowedOAuthScopes:[...U.OAuthScopes.basic],allowedOAuthFlowsUserPoolClient:!0});return{userPool:s,poolId:c,client:l,clientId:u}},mobileApp:(a,n)=>{let{userPool:i,logicalId:s}=U.createUserPool({slug:a,environment:n,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:U.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:c,logicalId:l}=U.createUserPoolClient(s,{slug:a,environment:n,explicitAuthFlows:[...U.AuthFlows.standard]}),{identityPool:u,logicalId:h}=U.createIdentityPool({slug:a,environment:n,allowUnauthenticatedIdentities:!1,cognitoIdentityProviders:[{ClientId:N.Ref(l),ProviderName:N.GetAtt(s,"ProviderName")}]}),{role:y,logicalId:f}=U.createAuthenticatedRole({slug:a,environment:n,identityPoolLogicalId:h}),{attachment:S,logicalId:b}=U.createIdentityPoolRoleAttachment(h,{slug:a,environment:n,authenticatedRole:N.GetAtt(f,"Arn")});return{userPool:i,poolId:s,client:c,clientId:l,identityPool:u,identityPoolId:h,authRole:y,authRoleId:f,attachment:S,attachmentId:b}}}}class Q{static createApplication(a){let{slug:n,environment:i,applicationName:s,computePlatform:c}=a,l=s||r({slug:n,environment:i,resourceType:"deploy-app"}),u=t(l);return{application:{Type:"AWS::CodeDeploy::Application",Properties:{ApplicationName:l,ComputePlatform:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:i}]}},logicalId:u}}static createDeploymentGroup(a,n){let{slug:i,environment:s,deploymentGroupName:c,serviceRoleArn:l,autoScalingGroups:u,ec2TagFilters:h,deploymentConfigName:y,autoRollbackConfiguration:f,alarmConfiguration:S,loadBalancerInfo:b,blueGreenDeploymentConfiguration:C}=n,T=c||r({slug:i,environment:s,resourceType:"deploy-group"}),v=t(T);return{deploymentGroup:{Type:"AWS::CodeDeploy::DeploymentGroup",Properties:{ApplicationName:N.Ref(a),DeploymentGroupName:T,ServiceRoleArn:l,AutoScalingGroups:u,Ec2TagFilters:h?.map((w)=>({Key:w.key,Value:w.value,Type:w.type})),DeploymentConfigName:y,AutoRollbackConfiguration:f?{Enabled:f.enabled,Events:f.events}:void 0,AlarmConfiguration:S?{Enabled:S.enabled,Alarms:S.alarms?.map((w)=>({Name:w.name})),IgnorePollAlarmFailure:S.ignorePollAlarmFailure}:void 0,LoadBalancerInfo:b?{TargetGroupInfoList:b.targetGroupInfoList?.map((w)=>({Name:w.name})),ElbInfoList:b.elbInfoList?.map((w)=>({Name:w.name}))}:void 0,BlueGreenDeploymentConfiguration:C?{TerminateBlueInstancesOnDeploymentSuccess:C.terminateBlueInstancesOnDeploymentSuccess?{Action:C.terminateBlueInstancesOnDeploymentSuccess.action,TerminationWaitTimeInMinutes:C.terminateBlueInstancesOnDeploymentSuccess.terminationWaitTimeInMinutes}:void 0,DeploymentReadyOption:C.deploymentReadyOption?{ActionOnTimeout:C.deploymentReadyOption.actionOnTimeout,WaitTimeInMinutes:C.deploymentReadyOption.waitTimeInMinutes}:void 0,GreenFleetProvisioningOption:C.greenFleetProvisioningOption?{Action:C.greenFleetProvisioningOption.action}:void 0}:void 0,Tags:[{Key:"Name",Value:T},{Key:"Environment",Value:s}]}},logicalId:v}}static createDeploymentConfig(a){let{slug:n,environment:i,deploymentConfigName:s,minimumHealthyHosts:c,trafficRoutingConfig:l}=a,u=s||r({slug:n,environment:i,resourceType:"deploy-config"}),h=t(u);return{deploymentConfig:{Type:"AWS::CodeDeploy::DeploymentConfig",Properties:{DeploymentConfigName:u,MinimumHealthyHosts:c?{Type:c.type,Value:c.value}:void 0,TrafficRoutingConfig:l?{Type:l.type,TimeBasedCanary:l.timeBasedCanary?{CanaryPercentage:l.timeBasedCanary.canaryPercentage,CanaryInterval:l.timeBasedCanary.canaryInterval}:void 0,TimeBasedLinear:l.timeBasedLinear?{LinearPercentage:l.timeBasedLinear.linearPercentage,LinearInterval:l.timeBasedLinear.linearInterval}:void 0}:void 0}},logicalId:h}}static DeploymentConfigs={allAtOnce:()=>({type:"FLEET_PERCENT",value:0}),halfAtATime:()=>({type:"FLEET_PERCENT",value:50}),oneAtATime:()=>({type:"HOST_COUNT",value:1}),custom:(a,n)=>({type:a,value:n})};static TrafficRouting={allAtOnce:()=>({type:"AllAtOnce"}),canary:(a,n)=>({type:"TimeBasedCanary",timeBasedCanary:{canaryPercentage:a,canaryInterval:n}}),linear:(a,n)=>({type:"TimeBasedLinear",timeBasedLinear:{linearPercentage:a,linearInterval:n}})};static RollbackConfigs={onFailure:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE"]}),onAlarmOrFailure:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE","DEPLOYMENT_STOP_ON_ALARM"]}),onAllEvents:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE","DEPLOYMENT_STOP_ON_ALARM","DEPLOYMENT_STOP_ON_REQUEST"]}),disabled:()=>({enabled:!1})};static BlueGreenConfigs={standard:()=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withDelay:(a)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:a},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withManualApproval:(a)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"STOP_DEPLOYMENT",waitTimeInMinutes:a},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),keepBlue:()=>({terminateBlueInstancesOnDeploymentSuccess:{action:"KEEP_ALIVE"},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}})};static UseCases={ec2Deployment:(a,n,i,s)=>{let{application:c,logicalId:l}=Q.createApplication({slug:a,environment:n,computePlatform:"Server"}),{deploymentGroup:u,logicalId:h}=Q.createDeploymentGroup(l,{slug:a,environment:n,serviceRoleArn:i,autoScalingGroups:s,deploymentConfigName:"CodeDeployDefault.OneAtATime",autoRollbackConfiguration:Q.RollbackConfigs.onFailure()});return{application:c,appId:l,deploymentGroup:u,groupId:h}},lambdaCanaryDeployment:(a,n,i,s=10,c=5)=>{let{application:l,logicalId:u}=Q.createApplication({slug:a,environment:n,computePlatform:"Lambda"}),{deploymentConfig:h,logicalId:y}=Q.createDeploymentConfig({slug:a,environment:n,trafficRoutingConfig:Q.TrafficRouting.canary(s,c)}),{deploymentGroup:f,logicalId:S}=Q.createDeploymentGroup(u,{slug:a,environment:n,serviceRoleArn:i,deploymentConfigName:N.Ref(y),autoRollbackConfiguration:Q.RollbackConfigs.onAlarmOrFailure()});return{application:l,appId:u,deploymentConfig:h,configId:y,deploymentGroup:f,groupId:S}},ecsBlueGreenDeployment:(a,n,i,s)=>{let{application:c,logicalId:l}=Q.createApplication({slug:a,environment:n,computePlatform:"ECS"}),{deploymentGroup:u,logicalId:h}=Q.createDeploymentGroup(l,{slug:a,environment:n,serviceRoleArn:i,loadBalancerInfo:{targetGroupInfoList:[{name:s}]},blueGreenDeploymentConfiguration:Q.BlueGreenConfigs.standard(),autoRollbackConfiguration:Q.RollbackConfigs.onFailure()});return{application:c,appId:l,deploymentGroup:u,groupId:h}}};static Strategies={rolling:(a=25)=>({type:"rolling",batchPercentage:a}),blueGreen:()=>({type:"blue-green"}),canary:(a=10,n=5)=>({type:"canary",canaryPercentage:a,canaryInterval:n}),allAtOnce:()=>({type:"all-at-once"})}}class D{static ContentTypes={".html":"text/html",".htm":"text/html",".css":"text/css",".js":"application/javascript",".mjs":"application/javascript",".json":"application/json",".xml":"application/xml",".svg":"image/svg+xml",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".avif":"image/avif",".ico":"image/x-icon",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".otf":"font/otf",".eot":"application/vnd.ms-fontobject",".pdf":"application/pdf",".txt":"text/plain",".md":"text/markdown",".map":"application/json"};static NoHashPatterns=[/^index\.html$/,/^favicon\.ico$/,/^robots\.txt$/,/^sitemap\.xml$/,/^manifest\.json$/,/^\.well-known\//,/^_redirects$/,/^_headers$/];static computeFileHash(a,n="md5"){let i=nt(a);return br(n).update(i).digest("hex")}static computeShortHash(a){return D.computeFileHash(a).slice(0,8)}static getContentType(a){let n=sa(a).toLowerCase();return D.ContentTypes[n]||"application/octet-stream"}static shouldHashFile(a,n){return![...D.NoHashPatterns,...n||[]].some((i)=>i.test(a))}static generateHashedFilename(a,n){let i=sa(a),s=vr(a,i),c=ia(a);if(c===".")return`${s}.${n}${i}`;return He(c,`${s}.${n}${i}`)}static collectFiles(a,n){let i=[],s=n||a;if(!Et(a))return i;let c=Cr(a,{withFileTypes:!0});for(let l of c){let u=He(a,l.name);if(l.isDirectory())i.push(...D.collectFiles(u,s));else if(l.isFile())i.push(u)}return i}static hashDirectory(a){let{sourceDir:n,outputDir:i,excludePatterns:s=[],hashAlgorithm:c="md5",copyUnhashed:l=!0}=a,u=D.collectFiles(n),h=[],y={};for(let S of u){let b=S.replace(n,"").replace(/^[/\\]/,""),C=D.shouldHashFile(b,s),T=Tr(S),v=C?D.computeFileHash(S,c).slice(0,8):"",w=C?D.generateHashedFilename(b,v):b,R={originalPath:b,hashedPath:w,hash:v,size:T.size,contentType:D.getContentType(S)};if(h.push(R),y[b]=w,i){let k=He(i,w),W=ia(k);if(!Et(W)){let{mkdirSync:P}=Za("node:fs");P(W,{recursive:!0})}if(C||l)Ar(S,k)}}let f={version:"1.0",timestamp:new Date().toISOString(),assets:h,hashMap:y};if(i){let S=He(i,"asset-manifest.json");it(S,JSON.stringify(f,null,2))}return f}static getInvalidationPaths(a,n){let i=[];if(!a)return["/*"];let s=a.hashMap,c=n.hashMap;for(let[l,u]of Object.entries(c)){let h=s[l];if(!h||h!==u){if(i.push(`/${l}`),h&&h!==u)i.push(`/${h}`)}}for(let[l,u]of Object.entries(s))if(!c[l])i.push(`/${l}`),i.push(`/${u}`);if(i.length>100)return["/*"];return[...new Set(i)]}static updateHtmlReferences(a){let{htmlDir:n,manifest:i,basePath:s=""}=a,c=D.collectFiles(n).filter((l)=>l.endsWith(".html")||l.endsWith(".htm"));for(let l of c){let u=nt(l,"utf-8");for(let[h,y]of Object.entries(i.hashMap)){if(h===y)continue;let f=[new RegExp(`(src|href)=["']${s}/?${D.escapeRegExp(h)}["']`,"g"),new RegExp(`url\\(["']?${s}/?${D.escapeRegExp(h)}["']?\\)`,"g")];for(let S of f)u=u.replace(S,(b)=>b.replace(h,y))}it(l,u)}}static updateCssReferences(a){let{cssDir:n,manifest:i,basePath:s=""}=a,c=D.collectFiles(n).filter((l)=>l.endsWith(".css"));for(let l of c){let u=nt(l,"utf-8");for(let[h,y]of Object.entries(i.hashMap)){if(h===y)continue;let f=new RegExp(`url\\(["']?${s}/?${D.escapeRegExp(h)}["']?\\)`,"g");u=u.replace(f,`url(${s}/${y})`)}it(l,u)}}static escapeRegExp(a){return a.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}static generateS3DeploymentManifest(a){let{sourceDir:n,keyPrefix:i="",excludePatterns:s=[],cacheControl:c={hashed:"public, max-age=31536000, immutable",unhashed:"public, max-age=3600",html:"public, max-age=0, must-revalidate"}}=a;return D.hashDirectory({sourceDir:n,excludePatterns:s}).assets.map((l)=>{let u=l.hash!=="",h=l.contentType==="text/html",y=c.unhashed||"public, max-age=3600";if(h)y=c.html||"public, max-age=0, must-revalidate";else if(u)y=c.hashed||"public, max-age=31536000, immutable";return{localPath:He(n,l.originalPath),s3Key:i?`${i}/${l.hashedPath}`:l.hashedPath,contentType:l.contentType,cacheControl:y,hash:l.hash}})}static compareManifests(a,n){let i={added:[],removed:[],changed:[],unchanged:[]},s=new Set(Object.keys(a.hashMap)),c=new Set(Object.keys(n.hashMap));for(let l of c)if(!s.has(l))i.added.push(l);for(let l of s)if(!c.has(l))i.removed.push(l);for(let l of c)if(s.has(l))if(a.hashMap[l]!==n.hashMap[l])i.changed.push(l);else i.unchanged.push(l);return i}static loadManifest(a){if(!Et(a))return null;try{let n=nt(a,"utf-8");return JSON.parse(n)}catch{return null}}static saveManifest(a,n){it(n,JSON.stringify(a,null,2))}}class ui{static createSecret(a){let{slug:n,environment:i,secretName:s,description:c,secretString:l,kmsKeyId:u,tags:h}=a,y=s||r({slug:n,environment:i,resourceType:"secret"}),f=t(y),S={Type:"AWS::SecretsManager::Secret",Properties:{Name:y,Description:c,SecretString:l,Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:i},...h?Object.entries(h).map(([b,C])=>({Key:b,Value:C})):[]]}};if(u)S.Properties.KmsKeyId=u;return{secret:S,logicalId:f}}static createGeneratedSecret(a){let{slug:n,environment:i,secretName:s,description:c,excludeCharacters:l,excludeLowercase:u,excludeNumbers:h,excludePunctuation:y,excludeUppercase:f,passwordLength:S,requireEachIncludedType:b,kmsKeyId:C,tags:T}=a,v=s||r({slug:n,environment:i,resourceType:"secret"}),w=t(v),R={Type:"AWS::SecretsManager::Secret",Properties:{Name:v,Description:c,GenerateSecretString:{ExcludeCharacters:l,ExcludeLowercase:u,ExcludeNumbers:h,ExcludePunctuation:y,ExcludeUppercase:f,PasswordLength:S||32,RequireEachIncludedType:b!==!1},Tags:[{Key:"Name",Value:v},{Key:"Environment",Value:i},...T?Object.entries(T).map(([k,W])=>({Key:k,Value:W})):[]]}};if(C)R.Properties.KmsKeyId=C;return{secret:R,logicalId:w}}static createDatabaseSecret(a){let{slug:n,environment:i,secretName:s,username:c,dbname:l,engine:u,host:h,port:y,kmsKeyId:f}=a,S=s||r({slug:n,environment:i,resourceType:"db-secret"}),b=t(S),C={username:c};if(l)C.dbname=l;if(u)C.engine=u;if(h)C.host=h;if(y)C.port=y;let T={Type:"AWS::SecretsManager::Secret",Properties:{Name:S,Description:`Database credentials for ${c}`,GenerateSecretString:{SecretStringTemplate:JSON.stringify(C),GenerateStringKey:"password",PasswordLength:32,ExcludeCharacters:'"@/\\',RequireEachIncludedType:!0},Tags:[{Key:"Name",Value:S},{Key:"Environment",Value:i},{Key:"Type",Value:"database"}]}};if(f)T.Properties.KmsKeyId=f;return{secret:T,logicalId:b}}static attachToDatabase(a){let{slug:n,environment:i,secretId:s,targetId:c,targetType:l}=a,u=r({slug:n,environment:i,resourceType:"secret-attachment"}),h=t(u);return{attachment:{Type:"AWS::SecretsManager::SecretTargetAttachment",Properties:{SecretId:s,TargetId:c,TargetType:l}},logicalId:h}}static enableRotation(a){let{slug:n,environment:i,secretId:s,rotationLambdaArn:c,automaticallyAfterDays:l,rotationType:u,kmsKeyArn:h,vpcSecurityGroupIds:y,vpcSubnetIds:f}=a,S=r({slug:n,environment:i,resourceType:"secret-rotation"}),b=t(S),C={Type:"AWS::SecretsManager::RotationSchedule",Properties:{SecretId:s,RotationRules:{AutomaticallyAfterDays:l||30}}};if(c)C.Properties.RotationLambdaARN=c;else if(u)C.Properties.HostedRotationLambda={RotationType:u,KmsKeyArn:h,VpcSecurityGroupIds:y,VpcSubnetIds:f};return{rotation:C,logicalId:b}}static SecretTypes={apiKey:(a,n,i)=>ui.createGeneratedSecret({slug:a,environment:n,secretName:`${a}-${n}-${i}-api-key`,description:`API key for ${i}`,passwordLength:32,excludePunctuation:!0,excludeLowercase:!1,excludeUppercase:!1,excludeNumbers:!1}),oauthClientSecret:(a,n,i)=>ui.createGeneratedSecret({slug:a,environment:n,secretName:`${a}-${n}-${i}-oauth-secret`,description:`OAuth client secret for ${i}`,passwordLength:64,excludeCharacters:"\"'`\\/@",requireEachIncludedType:!0}),jwtSecret:(a,n)=>ui.createGeneratedSecret({slug:a,environment:n,secretName:`${a}-${n}-jwt-secret`,description:"JWT signing secret",passwordLength:64,excludePunctuation:!0}),encryptionKey:(a,n)=>ui.createGeneratedSecret({slug:a,environment:n,secretName:`${a}-${n}-encryption-key`,description:"Data encryption key",passwordLength:64,excludeCharacters:"+/=",excludePunctuation:!0})};static RotationTypes={MySQLSingleUser:"MySQLSingleUser",MySQLMultiUser:"MySQLMultiUser",PostgreSQLSingleUser:"PostgreSQLSingleUser",PostgreSQLMultiUser:"PostgreSQLMultiUser",OracleSingleUser:"OracleSingleUser",OracleMultiUser:"OracleMultiUser",MariaDBSingleUser:"MariaDBSingleUser",MariaDBMultiUser:"MariaDBMultiUser",SQLServerSingleUser:"SQLServerSingleUser",SQLServerMultiUser:"SQLServerMultiUser",RedshiftSingleUser:"RedshiftSingleUser",RedshiftMultiUser:"RedshiftMultiUser",MongoDBSingleUser:"MongoDBSingleUser",MongoDBMultiUser:"MongoDBMultiUser"}}class E{static createParameter(a){let{slug:n,environment:i,parameterName:s,value:c,type:l="String",description:u,tier:h="Standard",tags:y}=a,f=s||r({slug:n,environment:i,resourceType:"parameter"}),S=t(f);return{parameter:{Type:"AWS::SSM::Parameter",Properties:{Name:`/${n}/${i}/${f}`,Type:l,Value:c,Description:u,Tier:h,Tags:{Name:f,Environment:i,...y}}},logicalId:S}}static createString(a,n,i,s,c){return E.createParameter({slug:a,environment:n,parameterName:i,value:s,type:"String",description:c})}static createSecureString(a,n,i,s,c){return E.createParameter({slug:a,environment:n,parameterName:i,value:s,type:"SecureString",description:c})}static createStringList(a,n,i,s,c){return E.createParameter({slug:a,environment:n,parameterName:i,value:s.join(","),type:"StringList",description:c})}static Parameters={databaseUrl:(a,n,i)=>E.createSecureString(a,n,"database-url",i,"Database connection URL"),apiEndpoint:(a,n,i)=>E.createString(a,n,"api-endpoint",i,"API endpoint URL"),appVersion:(a,n,i)=>E.createString(a,n,"app-version",i,"Application version"),featureFlags:(a,n,i)=>E.createStringList(a,n,"feature-flags",i,"Enabled feature flags"),apiKey:(a,n,i,s)=>E.createSecureString(a,n,`${i}-api-key`,s,`API key for ${i}`),oauthCredentials:(a,n,i,s)=>{let c=E.createString(a,n,"oauth-client-id",i,"OAuth client ID"),l=E.createSecureString(a,n,"oauth-client-secret",s,"OAuth client secret");return{clientId:c,clientSecret:l}},smtpCredentials:(a,n,i,s,c,l)=>{let u=E.createString(a,n,"smtp-username",i,"SMTP username"),h=E.createSecureString(a,n,"smtp-password",s,"SMTP password"),y=E.createString(a,n,"smtp-host",c,"SMTP host"),f=E.createString(a,n,"smtp-port",l.toString(),"SMTP port");return{username:u,password:h,host:y,port:f}},redisUrl:(a,n,i)=>E.createSecureString(a,n,"redis-url",i,"Redis connection URL"),s3Bucket:(a,n,i)=>E.createString(a,n,"s3-bucket",i,"S3 bucket name"),cloudFrontDistribution:(a,n,i)=>E.createString(a,n,"cloudfront-distribution-id",i,"CloudFront distribution ID")}}class Ut{static createDomain(a){let{slug:n,environment:i,domainName:s,engineVersion:c="OpenSearch_2.11",instanceType:l="t3.small.search",instanceCount:u=1,volumeSize:h=10,volumeType:y="gp3",dedicatedMaster:f=!1,dedicatedMasterType:S,dedicatedMasterCount:b=3,multiAz:C=!1,availabilityZoneCount:T=2,vpc:v,encryption:w,enforceHttps:R=!0,tlsSecurityPolicy:k="Policy-Min-TLS-1-2-2019-07",advancedSecurity:W,autoSnapshotHour:P=0,autoTune:V=!0,tags:B={}}=a,j=s||r({slug:n,environment:i,resourceType:"search"}),Z=t(j);return{domain:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:j,EngineVersion:c,ClusterConfig:{InstanceType:l,InstanceCount:u,DedicatedMasterEnabled:f,...f&&{DedicatedMasterType:S||l,DedicatedMasterCount:b},ZoneAwarenessEnabled:C,...C&&{ZoneAwarenessConfig:{AvailabilityZoneCount:T}}},EBSOptions:{EBSEnabled:!0,VolumeType:y,VolumeSize:h},DomainEndpointOptions:{EnforceHTTPS:R,TLSSecurityPolicy:k},SnapshotOptions:{AutomatedSnapshotStartHour:P},...v&&{VPCOptions:{SubnetIds:v.subnetIds,SecurityGroupIds:v.securityGroupIds}},...w&&{EncryptionAtRestOptions:{Enabled:w.atRest??!0,...w.kmsKeyId&&{KmsKeyId:w.kmsKeyId}},NodeToNodeEncryptionOptions:{Enabled:w.nodeToNode??!0}},...W&&{AdvancedSecurityOptions:{Enabled:W.enabled,InternalUserDatabaseEnabled:W.internalUserDatabase??!0,...W.masterUserName&&W.masterUserPassword&&{MasterUserOptions:{MasterUserName:W.masterUserName,MasterUserPassword:W.masterUserPassword}},...W.masterUserArn&&{MasterUserOptions:{MasterUserARN:W.masterUserArn}}}},...V&&{AutoTuneOptions:{DesiredState:"ENABLED"}},Tags:[{Key:"Name",Value:j},{Key:"Environment",Value:i},...Object.entries(B).map(([K,ee])=>({Key:K,Value:ee}))]}},logicalId:Z}}static createAccessPolicy(a,n){let{ipAddresses:i,iamPrincipalArns:s,allowAll:c,vpcEndpoint:l}=n;if(c)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:a}]};let u=[];if(s&&s.length>0)u.push({Effect:"Allow",Principal:{AWS:s},Action:"es:*",Resource:a});if(i&&i.length>0)u.push({Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:a,Condition:{IpAddress:{"aws:SourceIp":i}}});if(l)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:a}]};return{Version:"2012-10-17",Statement:u}}static DomainPresets={development:(a,n)=>Ut.createDomain({slug:a,environment:n,instanceType:"t3.small.search",instanceCount:1,volumeSize:10,multiAz:!1,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!1}),production:(a,n,i)=>Ut.createDomain({slug:a,environment:n,instanceType:"m6g.large.search",instanceCount:3,volumeSize:100,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"m6g.large.search",dedicatedMasterCount:3,vpc:i,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!0},autoTune:!0}),costOptimized:(a,n)=>Ut.createDomain({slug:a,environment:n,instanceType:"t3.medium.search",instanceCount:2,volumeSize:20,volumeType:"gp3",multiAz:!0,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!0}),highPerformance:(a,n,i)=>Ut.createDomain({slug:a,environment:n,instanceType:"r6g.2xlarge.search",instanceCount:6,volumeSize:500,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"c6g.xlarge.search",dedicatedMasterCount:3,vpc:i,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!1},autoTune:!0})};static InstanceTypes={"t3.small.search":"t3.small.search","t3.medium.search":"t3.medium.search","m6g.large.search":"m6g.large.search","m6g.xlarge.search":"m6g.xlarge.search","m6g.2xlarge.search":"m6g.2xlarge.search","r6g.large.search":"r6g.large.search","r6g.xlarge.search":"r6g.xlarge.search","r6g.2xlarge.search":"r6g.2xlarge.search","r6g.4xlarge.search":"r6g.4xlarge.search","c6g.large.search":"c6g.large.search","c6g.xlarge.search":"c6g.xlarge.search","c6g.2xlarge.search":"c6g.2xlarge.search"};static EngineVersions={"OpenSearch_2.11":"OpenSearch_2.11","OpenSearch_2.9":"OpenSearch_2.9","OpenSearch_2.7":"OpenSearch_2.7","OpenSearch_1.3":"OpenSearch_1.3","Elasticsearch_7.10":"Elasticsearch_7.10"}}class ct{static createDomainRedirectBucket(a){let{slug:n,environment:i,sourceDomain:s,targetDomain:c,protocol:l="https"}=a,u=r({slug:n,environment:i,resourceType:"s3",suffix:"redirect"}),h=t(u),y=t(`${u}-policy`),f={Type:"AWS::S3::Bucket",Properties:{BucketName:s,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:c,Protocol:l}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1},Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:i},{Key:"Purpose",Value:"Domain Redirect"}]}},S={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:N.Ref(h),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[N.Join("",[N.GetAtt(h,"Arn"),"/*"])]}]}}};return{bucket:f,bucketPolicy:S,logicalId:h,policyLogicalId:y}}static createPathRedirectFunction(a){let{slug:n,environment:i,rules:s}=a,c=r({slug:n,environment:i,resourceType:"cf-redirect"}),l=t(c),u=ct.generateRedirectFunctionCode(s);return{function:{Type:"AWS::CloudFront::Function",Properties:{Name:c,AutoPublish:!0,FunctionConfig:{Comment:`Path redirect function for ${n} (${i})`,Runtime:"cloudfront-js-2.0"},FunctionCode:u}},logicalId:l,functionCode:u}}static generateRedirectFunctionCode(a){return`function handler(event) {
|
|
2316
|
+
| limit 50`,region:s,title:"Recent Errors and Warnings"}}),u+=6;return qs.createDashboard({slug:n,environment:i,widgets:l})}static DashboardTemplates={staticWebsite:(a)=>({slug:a.slug,environment:a.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${a.slug.toUpperCase()} Static Website Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"CloudFront Requests",region:"us-east-1",metrics:[["AWS/CloudFront","Requests","DistributionId",a.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"Error Rate",region:"us-east-1",metrics:[["AWS/CloudFront","4xxErrorRate","DistributionId",a.cloudFrontDistributionId,"Region","Global",{label:"4XX"}],["AWS/CloudFront","5xxErrorRate","DistributionId",a.cloudFrontDistributionId,"Region","Global",{label:"5XX"}]],period:300,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Bytes Downloaded",region:"us-east-1",metrics:[["AWS/CloudFront","BytesDownloaded","DistributionId",a.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:0,y:7,width:12,height:6,properties:{title:"S3 Bucket Size",region:a.region||"us-east-1",metrics:[["AWS/S3","BucketSizeBytes","BucketName",a.s3BucketName,"StorageType","StandardStorage"]],period:86400,stat:"Average"}},{type:"metric",x:12,y:7,width:12,height:6,properties:{title:"S3 Number of Objects",region:a.region||"us-east-1",metrics:[["AWS/S3","NumberOfObjects","BucketName",a.s3BucketName,"StorageType","AllStorageTypes"]],period:86400,stat:"Average"}}]}),serverlessApi:(a)=>({slug:a.slug,environment:a.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${a.slug.toUpperCase()} Serverless API Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"API Requests",region:a.region||"us-east-1",metrics:[["AWS/ApiGateway","Count","ApiName",a.apiGatewayName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"API Latency",region:a.region||"us-east-1",metrics:[["AWS/ApiGateway","Latency","ApiName",a.apiGatewayName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"API Errors",region:a.region||"us-east-1",metrics:[["AWS/ApiGateway","4XXError","ApiName",a.apiGatewayName,{label:"4XX"}],["AWS/ApiGateway","5XXError","ApiName",a.apiGatewayName,{label:"5XX"}]],period:60,stat:"Sum"}},...a.lambdaFunctionNames.map((n,i)=>({type:"metric",x:i%3*8,y:7+Math.floor(i/3)*6,width:8,height:6,properties:{title:`${n} Metrics`,region:a.region||"us-east-1",metrics:[["AWS/Lambda","Invocations","FunctionName",n],["AWS/Lambda","Duration","FunctionName",n],["AWS/Lambda","Errors","FunctionName",n]],period:300,stat:"Sum"}}))]}),containerService:(a)=>({slug:a.slug,environment:a.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${a.slug.toUpperCase()} Container Service Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"ECS CPU",region:a.region||"us-east-1",metrics:[["AWS/ECS","CPUUtilization","ClusterName",a.ecsClusterName,"ServiceName",a.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"ECS Memory",region:a.region||"us-east-1",metrics:[["AWS/ECS","MemoryUtilization","ClusterName",a.ecsClusterName,"ServiceName",a.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Running Tasks",region:a.region||"us-east-1",metrics:[["ECS/ContainerInsights","RunningTaskCount","ClusterName",a.ecsClusterName,"ServiceName",a.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:0,y:7,width:8,height:6,properties:{title:"ALB Requests",region:a.region||"us-east-1",metrics:[["AWS/ApplicationELB","RequestCount","LoadBalancer",a.albName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:7,width:8,height:6,properties:{title:"Response Time",region:a.region||"us-east-1",metrics:[["AWS/ApplicationELB","TargetResponseTime","LoadBalancer",a.albName]],period:60,stat:"Average"}},{type:"metric",x:16,y:7,width:8,height:6,properties:{title:"Healthy Hosts",region:a.region||"us-east-1",metrics:[["AWS/ApplicationELB","HealthyHostCount","LoadBalancer",a.albName]],period:60,stat:"Average"}},...a.rdsInstanceId?[{type:"metric",x:0,y:13,width:12,height:6,properties:{title:"RDS CPU",region:a.region||"us-east-1",metrics:[["AWS/RDS","CPUUtilization","DBInstanceIdentifier",a.rdsInstanceId]],period:300,stat:"Average"}},{type:"metric",x:12,y:13,width:12,height:6,properties:{title:"RDS Connections",region:a.region||"us-east-1",metrics:[["AWS/RDS","DatabaseConnections","DBInstanceIdentifier",a.rdsInstanceId]],period:60,stat:"Sum"}}]:[]]})};static Config={createAlarmConfig:(a)=>{let{metricName:n,namespace:i,threshold:s,comparisonOperator:c="GreaterThanThreshold",evaluationPeriods:l=1,period:u=300,statistic:h="Average",treatMissingData:y="missing"}=a;return{MetricName:n,Namespace:i,Threshold:s,ComparisonOperator:c,EvaluationPeriods:l,Period:u,Statistic:h,TreatMissingData:y}},namespaces:{ec2:"AWS/EC2",ecs:"AWS/ECS",lambda:"AWS/Lambda",rds:"AWS/RDS",sqs:"AWS/SQS",sns:"AWS/SNS",s3:"AWS/S3",cloudfront:"AWS/CloudFront",alb:"AWS/ApplicationELB",nlb:"AWS/NetworkELB",apiGateway:"AWS/ApiGateway",dynamodb:"AWS/DynamoDB",elasticache:"AWS/ElastiCache"},comparisonOperators:{greaterThan:"GreaterThanThreshold",greaterOrEqual:"GreaterThanOrEqualToThreshold",lessThan:"LessThanThreshold",lessOrEqual:"LessThanOrEqualToThreshold"},metrics:{ec2:{cpu:{metricName:"CPUUtilization",namespace:"AWS/EC2"},networkIn:{metricName:"NetworkIn",namespace:"AWS/EC2"},networkOut:{metricName:"NetworkOut",namespace:"AWS/EC2"},statusCheck:{metricName:"StatusCheckFailed",namespace:"AWS/EC2"}},ecs:{cpu:{metricName:"CPUUtilization",namespace:"AWS/ECS"},memory:{metricName:"MemoryUtilization",namespace:"AWS/ECS"}},lambda:{invocations:{metricName:"Invocations",namespace:"AWS/Lambda"},errors:{metricName:"Errors",namespace:"AWS/Lambda"},duration:{metricName:"Duration",namespace:"AWS/Lambda"},throttles:{metricName:"Throttles",namespace:"AWS/Lambda"},concurrentExecutions:{metricName:"ConcurrentExecutions",namespace:"AWS/Lambda"}},rds:{cpu:{metricName:"CPUUtilization",namespace:"AWS/RDS"},connections:{metricName:"DatabaseConnections",namespace:"AWS/RDS"},freeStorage:{metricName:"FreeStorageSpace",namespace:"AWS/RDS"},readLatency:{metricName:"ReadLatency",namespace:"AWS/RDS"},writeLatency:{metricName:"WriteLatency",namespace:"AWS/RDS"}},alb:{requestCount:{metricName:"RequestCount",namespace:"AWS/ApplicationELB"},responseTime:{metricName:"TargetResponseTime",namespace:"AWS/ApplicationELB"},httpCode4xx:{metricName:"HTTPCode_Target_4XX_Count",namespace:"AWS/ApplicationELB"},httpCode5xx:{metricName:"HTTPCode_Target_5XX_Count",namespace:"AWS/ApplicationELB"},healthyHosts:{metricName:"HealthyHostCount",namespace:"AWS/ApplicationELB"}},sqs:{messagesVisible:{metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS"},messagesDelayed:{metricName:"ApproximateNumberOfMessagesDelayed",namespace:"AWS/SQS"},messageAge:{metricName:"ApproximateAgeOfOldestMessage",namespace:"AWS/SQS"}}},presets:{highCpu:(a=80)=>({metricName:"CPUUtilization",threshold:a,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highMemory:(a=80)=>({metricName:"MemoryUtilization",threshold:a,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highErrors:(a=10)=>({metricName:"Errors",threshold:a,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:1,period:60,statistic:"Sum"}),highLatency:(a=5000)=>({metricName:"Duration",threshold:a,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowHealthyHosts:(a=1)=>({metricName:"HealthyHostCount",namespace:"AWS/ApplicationELB",threshold:a,comparisonOperator:"LessThanThreshold",evaluationPeriods:2,period:60,statistic:"Minimum"}),queueDepth:(a=1000)=>({metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",threshold:a,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowStorage:(a=10737418240)=>({metricName:"FreeStorageSpace",namespace:"AWS/RDS",threshold:a,comparisonOperator:"LessThanThreshold",evaluationPeriods:1,period:300,statistic:"Average"})}}}class U{static createUserPool(a){let{slug:n,environment:i,userPoolName:s,aliasAttributes:c,autoVerifiedAttributes:l,passwordPolicy:u,mfaConfiguration:h,emailConfiguration:y,smsConfiguration:f,lambdaTriggers:S,userPoolAddOns:b,accountRecoverySetting:C}=a,T=s||r({slug:n,environment:i,resourceType:"user-pool"}),v=t(T),w={Type:"AWS::Cognito::UserPool",Properties:{UserPoolName:T,Policies:u?{PasswordPolicy:{MinimumLength:u.minimumLength,RequireLowercase:u.requireLowercase,RequireUppercase:u.requireUppercase,RequireNumbers:u.requireNumbers,RequireSymbols:u.requireSymbols,TemporaryPasswordValidityDays:u.temporaryPasswordValidityDays}}:void 0,MfaConfiguration:h,Schema:[{Name:"email",AttributeDataType:"String",Required:!0,Mutable:!1}]}};if(c&&c.length>0)w.Properties.UsernameAttributes=c;if(l&&l.length>0)w.Properties.AutoVerifiedAttributes=l;if(y)w.Properties.EmailConfiguration={EmailSendingAccount:y.emailSendingAccount,From:y.from,ReplyToEmailAddress:y.replyToEmailAddress,SourceArn:y.sourceArn,ConfigurationSet:y.configurationSet};if(f)w.Properties.SmsConfiguration={ExternalId:f.externalId,SnsCallerArn:f.snsCallerArn};if(S)w.Properties.LambdaConfig={PreSignUp:S.preSignUp,PostConfirmation:S.postConfirmation,PreAuthentication:S.preAuthentication,PostAuthentication:S.postAuthentication,CustomMessage:S.customMessage,DefineAuthChallenge:S.defineAuthChallenge,CreateAuthChallenge:S.createAuthChallenge,VerifyAuthChallengeResponse:S.verifyAuthChallengeResponse,PreTokenGeneration:S.preTokenGeneration,UserMigration:S.userMigration};if(b)w.Properties.UserPoolAddOns={AdvancedSecurityMode:b.advancedSecurityMode};if(C)w.Properties.AccountRecoverySetting={RecoveryMechanisms:C.recoveryMechanisms};return{userPool:w,logicalId:v}}static createUserPoolClient(a,n){let{slug:i,environment:s,clientName:c,generateSecret:l=!1,refreshTokenValidity:u,accessTokenValidity:h,idTokenValidity:y,tokenValidityUnits:f,readAttributes:S,writeAttributes:b,explicitAuthFlows:C,preventUserExistenceErrors:T,enableTokenRevocation:v,callbackURLs:w,logoutURLs:R,allowedOAuthFlows:k,allowedOAuthScopes:W,allowedOAuthFlowsUserPoolClient:P,supportedIdentityProviders:V}=n,B=c||r({slug:i,environment:s,resourceType:"user-pool-client"}),j=t(B);return{client:{Type:"AWS::Cognito::UserPoolClient",Properties:{ClientName:B,UserPoolId:N.Ref(a),GenerateSecret:l,RefreshTokenValidity:u,AccessTokenValidity:h,IdTokenValidity:y,TokenValidityUnits:f,ReadAttributes:S,WriteAttributes:b,ExplicitAuthFlows:C,PreventUserExistenceErrors:T,EnableTokenRevocation:v,CallbackURLs:w,LogoutURLs:R,AllowedOAuthFlows:k,AllowedOAuthScopes:W,AllowedOAuthFlowsUserPoolClient:P,SupportedIdentityProviders:V}},logicalId:j}}static createUserPoolDomain(a,n){let{slug:i,environment:s,domain:c,customDomainConfig:l}=n,u=r({slug:i,environment:s,resourceType:"user-pool-domain"}),h=t(u);return{domain:{Type:"AWS::Cognito::UserPoolDomain",Properties:{Domain:c,UserPoolId:N.Ref(a),CustomDomainConfig:l}},logicalId:h}}static createIdentityPool(a){let{slug:n,environment:i,identityPoolName:s,allowUnauthenticatedIdentities:c=!1,cognitoIdentityProviders:l,supportedLoginProviders:u,samlProviderARNs:h,openIdConnectProviderARNs:y}=a,f=s||r({slug:n,environment:i,resourceType:"identity-pool"}),S=t(f);return{identityPool:{Type:"AWS::Cognito::IdentityPool",Properties:{IdentityPoolName:f,AllowUnauthenticatedIdentities:c,CognitoIdentityProviders:l,SupportedLoginProviders:u,SamlProviderARNs:h,OpenIdConnectProviderARNs:y}},logicalId:S}}static createIdentityPoolRoleAttachment(a,n){let{slug:i,environment:s,authenticatedRole:c,unauthenticatedRole:l,roleMappings:u}=n,h=r({slug:i,environment:s,resourceType:"identity-pool-role-attachment"}),y=t(h),f={authenticated:c};if(l)f.unauthenticated=l;return{attachment:{Type:"AWS::Cognito::IdentityPoolRoleAttachment",Properties:{IdentityPoolId:N.Ref(a),Roles:f,RoleMappings:u}},logicalId:y}}static createAuthenticatedRole(a){let{slug:n,environment:i,identityPoolLogicalId:s}=a,c=r({slug:n,environment:i,resourceType:"cognito-authenticated-role"}),l=t(c);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:c,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":N.Ref(s)},"ForAnyValue:StringLike":{"cognito-identity.amazonaws.com:amr":"authenticated"}}}]},Policies:[{PolicyName:"CognitoAuthenticatedPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["cognito-sync:*","cognito-identity:*"],Resource:"*"}]}}],Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:i}]}},logicalId:l}}static createUnauthenticatedRole(a){let{slug:n,environment:i,identityPoolLogicalId:s}=a,c=r({slug:n,environment:i,resourceType:"cognito-unauthenticated-role"}),l=t(c);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:c,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":N.Ref(s)},"ForAnyValue:StringLike":{"cognito-identity.amazonaws.com:amr":"unauthenticated"}}}]},Policies:[{PolicyName:"CognitoUnauthenticatedPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["cognito-sync:*"],Resource:"*"}]}}],Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:i}]}},logicalId:l}}static PasswordPolicies={relaxed:()=>({minimumLength:8,requireLowercase:!1,requireUppercase:!1,requireNumbers:!1,requireSymbols:!1,temporaryPasswordValidityDays:7}),standard:()=>({minimumLength:8,requireLowercase:!0,requireUppercase:!0,requireNumbers:!0,requireSymbols:!1,temporaryPasswordValidityDays:3}),strict:()=>({minimumLength:12,requireLowercase:!0,requireUppercase:!0,requireNumbers:!0,requireSymbols:!0,temporaryPasswordValidityDays:1})};static AuthFlows={standard:["ALLOW_USER_SRP_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],admin:["ALLOW_ADMIN_USER_PASSWORD_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],custom:["ALLOW_CUSTOM_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],all:["ALLOW_USER_SRP_AUTH","ALLOW_USER_PASSWORD_AUTH","ALLOW_ADMIN_USER_PASSWORD_AUTH","ALLOW_CUSTOM_AUTH","ALLOW_REFRESH_TOKEN_AUTH"]};static OAuthScopes={basic:["openid","email","profile"],all:["openid","email","profile","phone","aws.cognito.signin.user.admin"]};static UseCases={webApp:(a,n,i)=>{let{userPool:s,logicalId:c}=U.createUserPool({slug:a,environment:n,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:U.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:l,logicalId:u}=U.createUserPoolClient(c,{slug:a,environment:n,explicitAuthFlows:[...U.AuthFlows.standard],callbackURLs:[i],allowedOAuthFlows:["code"],allowedOAuthScopes:[...U.OAuthScopes.basic],allowedOAuthFlowsUserPoolClient:!0});return{userPool:s,poolId:c,client:l,clientId:u}},mobileApp:(a,n)=>{let{userPool:i,logicalId:s}=U.createUserPool({slug:a,environment:n,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:U.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:c,logicalId:l}=U.createUserPoolClient(s,{slug:a,environment:n,explicitAuthFlows:[...U.AuthFlows.standard]}),{identityPool:u,logicalId:h}=U.createIdentityPool({slug:a,environment:n,allowUnauthenticatedIdentities:!1,cognitoIdentityProviders:[{ClientId:N.Ref(l),ProviderName:N.GetAtt(s,"ProviderName")}]}),{role:y,logicalId:f}=U.createAuthenticatedRole({slug:a,environment:n,identityPoolLogicalId:h}),{attachment:S,logicalId:b}=U.createIdentityPoolRoleAttachment(h,{slug:a,environment:n,authenticatedRole:N.GetAtt(f,"Arn")});return{userPool:i,poolId:s,client:c,clientId:l,identityPool:u,identityPoolId:h,authRole:y,authRoleId:f,attachment:S,attachmentId:b}}}}class Q{static createApplication(a){let{slug:n,environment:i,applicationName:s,computePlatform:c}=a,l=s||r({slug:n,environment:i,resourceType:"deploy-app"}),u=t(l);return{application:{Type:"AWS::CodeDeploy::Application",Properties:{ApplicationName:l,ComputePlatform:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:i}]}},logicalId:u}}static createDeploymentGroup(a,n){let{slug:i,environment:s,deploymentGroupName:c,serviceRoleArn:l,autoScalingGroups:u,ec2TagFilters:h,deploymentConfigName:y,autoRollbackConfiguration:f,alarmConfiguration:S,loadBalancerInfo:b,blueGreenDeploymentConfiguration:C}=n,T=c||r({slug:i,environment:s,resourceType:"deploy-group"}),v=t(T);return{deploymentGroup:{Type:"AWS::CodeDeploy::DeploymentGroup",Properties:{ApplicationName:N.Ref(a),DeploymentGroupName:T,ServiceRoleArn:l,AutoScalingGroups:u,Ec2TagFilters:h?.map((w)=>({Key:w.key,Value:w.value,Type:w.type})),DeploymentConfigName:y,AutoRollbackConfiguration:f?{Enabled:f.enabled,Events:f.events}:void 0,AlarmConfiguration:S?{Enabled:S.enabled,Alarms:S.alarms?.map((w)=>({Name:w.name})),IgnorePollAlarmFailure:S.ignorePollAlarmFailure}:void 0,LoadBalancerInfo:b?{TargetGroupInfoList:b.targetGroupInfoList?.map((w)=>({Name:w.name})),ElbInfoList:b.elbInfoList?.map((w)=>({Name:w.name}))}:void 0,BlueGreenDeploymentConfiguration:C?{TerminateBlueInstancesOnDeploymentSuccess:C.terminateBlueInstancesOnDeploymentSuccess?{Action:C.terminateBlueInstancesOnDeploymentSuccess.action,TerminationWaitTimeInMinutes:C.terminateBlueInstancesOnDeploymentSuccess.terminationWaitTimeInMinutes}:void 0,DeploymentReadyOption:C.deploymentReadyOption?{ActionOnTimeout:C.deploymentReadyOption.actionOnTimeout,WaitTimeInMinutes:C.deploymentReadyOption.waitTimeInMinutes}:void 0,GreenFleetProvisioningOption:C.greenFleetProvisioningOption?{Action:C.greenFleetProvisioningOption.action}:void 0}:void 0,Tags:[{Key:"Name",Value:T},{Key:"Environment",Value:s}]}},logicalId:v}}static createDeploymentConfig(a){let{slug:n,environment:i,deploymentConfigName:s,minimumHealthyHosts:c,trafficRoutingConfig:l}=a,u=s||r({slug:n,environment:i,resourceType:"deploy-config"}),h=t(u);return{deploymentConfig:{Type:"AWS::CodeDeploy::DeploymentConfig",Properties:{DeploymentConfigName:u,MinimumHealthyHosts:c?{Type:c.type,Value:c.value}:void 0,TrafficRoutingConfig:l?{Type:l.type,TimeBasedCanary:l.timeBasedCanary?{CanaryPercentage:l.timeBasedCanary.canaryPercentage,CanaryInterval:l.timeBasedCanary.canaryInterval}:void 0,TimeBasedLinear:l.timeBasedLinear?{LinearPercentage:l.timeBasedLinear.linearPercentage,LinearInterval:l.timeBasedLinear.linearInterval}:void 0}:void 0}},logicalId:h}}static DeploymentConfigs={allAtOnce:()=>({type:"FLEET_PERCENT",value:0}),halfAtATime:()=>({type:"FLEET_PERCENT",value:50}),oneAtATime:()=>({type:"HOST_COUNT",value:1}),custom:(a,n)=>({type:a,value:n})};static TrafficRouting={allAtOnce:()=>({type:"AllAtOnce"}),canary:(a,n)=>({type:"TimeBasedCanary",timeBasedCanary:{canaryPercentage:a,canaryInterval:n}}),linear:(a,n)=>({type:"TimeBasedLinear",timeBasedLinear:{linearPercentage:a,linearInterval:n}})};static RollbackConfigs={onFailure:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE"]}),onAlarmOrFailure:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE","DEPLOYMENT_STOP_ON_ALARM"]}),onAllEvents:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE","DEPLOYMENT_STOP_ON_ALARM","DEPLOYMENT_STOP_ON_REQUEST"]}),disabled:()=>({enabled:!1})};static BlueGreenConfigs={standard:()=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withDelay:(a)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:a},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withManualApproval:(a)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"STOP_DEPLOYMENT",waitTimeInMinutes:a},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),keepBlue:()=>({terminateBlueInstancesOnDeploymentSuccess:{action:"KEEP_ALIVE"},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}})};static UseCases={ec2Deployment:(a,n,i,s)=>{let{application:c,logicalId:l}=Q.createApplication({slug:a,environment:n,computePlatform:"Server"}),{deploymentGroup:u,logicalId:h}=Q.createDeploymentGroup(l,{slug:a,environment:n,serviceRoleArn:i,autoScalingGroups:s,deploymentConfigName:"CodeDeployDefault.OneAtATime",autoRollbackConfiguration:Q.RollbackConfigs.onFailure()});return{application:c,appId:l,deploymentGroup:u,groupId:h}},lambdaCanaryDeployment:(a,n,i,s=10,c=5)=>{let{application:l,logicalId:u}=Q.createApplication({slug:a,environment:n,computePlatform:"Lambda"}),{deploymentConfig:h,logicalId:y}=Q.createDeploymentConfig({slug:a,environment:n,trafficRoutingConfig:Q.TrafficRouting.canary(s,c)}),{deploymentGroup:f,logicalId:S}=Q.createDeploymentGroup(u,{slug:a,environment:n,serviceRoleArn:i,deploymentConfigName:N.Ref(y),autoRollbackConfiguration:Q.RollbackConfigs.onAlarmOrFailure()});return{application:l,appId:u,deploymentConfig:h,configId:y,deploymentGroup:f,groupId:S}},ecsBlueGreenDeployment:(a,n,i,s)=>{let{application:c,logicalId:l}=Q.createApplication({slug:a,environment:n,computePlatform:"ECS"}),{deploymentGroup:u,logicalId:h}=Q.createDeploymentGroup(l,{slug:a,environment:n,serviceRoleArn:i,loadBalancerInfo:{targetGroupInfoList:[{name:s}]},blueGreenDeploymentConfiguration:Q.BlueGreenConfigs.standard(),autoRollbackConfiguration:Q.RollbackConfigs.onFailure()});return{application:c,appId:l,deploymentGroup:u,groupId:h}}};static Strategies={rolling:(a=25)=>({type:"rolling",batchPercentage:a}),blueGreen:()=>({type:"blue-green"}),canary:(a=10,n=5)=>({type:"canary",canaryPercentage:a,canaryInterval:n}),allAtOnce:()=>({type:"all-at-once"})}}class D{static ContentTypes={".html":"text/html",".htm":"text/html",".css":"text/css",".js":"application/javascript",".mjs":"application/javascript",".json":"application/json",".xml":"application/xml",".svg":"image/svg+xml",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".avif":"image/avif",".ico":"image/x-icon",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".otf":"font/otf",".eot":"application/vnd.ms-fontobject",".pdf":"application/pdf",".txt":"text/plain",".md":"text/markdown",".map":"application/json"};static NoHashPatterns=[/^index\.html$/,/^favicon\.ico$/,/^robots\.txt$/,/^sitemap\.xml$/,/^manifest\.json$/,/^\.well-known\//,/^_redirects$/,/^_headers$/];static computeFileHash(a,n="md5"){let i=nt(a);return br(n).update(i).digest("hex")}static computeShortHash(a){return D.computeFileHash(a).slice(0,8)}static getContentType(a){let n=sa(a).toLowerCase();return D.ContentTypes[n]||"application/octet-stream"}static shouldHashFile(a,n){return![...D.NoHashPatterns,...n||[]].some((i)=>i.test(a))}static generateHashedFilename(a,n){let i=sa(a),s=vr(a,i),c=ia(a);if(c===".")return`${s}.${n}${i}`;return He(c,`${s}.${n}${i}`)}static collectFiles(a,n){let i=[],s=n||a;if(!Et(a))return i;let c=Cr(a,{withFileTypes:!0});for(let l of c){let u=He(a,l.name);if(l.isDirectory())i.push(...D.collectFiles(u,s));else if(l.isFile())i.push(u)}return i}static hashDirectory(a){let{sourceDir:n,outputDir:i,excludePatterns:s=[],hashAlgorithm:c="md5",copyUnhashed:l=!0}=a,u=D.collectFiles(n),h=[],y={};for(let S of u){let b=S.replace(n,"").replace(/^[/\\]/,""),C=D.shouldHashFile(b,s),T=Tr(S),v=C?D.computeFileHash(S,c).slice(0,8):"",w=C?D.generateHashedFilename(b,v):b,R={originalPath:b,hashedPath:w,hash:v,size:T.size,contentType:D.getContentType(S)};if(h.push(R),y[b]=w,i){let k=He(i,w),W=ia(k);if(!Et(W)){let{mkdirSync:P}=Za("node:fs");P(W,{recursive:!0})}if(C||l)Ar(S,k)}}let f={version:"1.0",timestamp:new Date().toISOString(),assets:h,hashMap:y};if(i){let S=He(i,"asset-manifest.json");it(S,JSON.stringify(f,null,2))}return f}static getInvalidationPaths(a,n){let i=[];if(!a)return["/*"];let s=a.hashMap,c=n.hashMap;for(let[l,u]of Object.entries(c)){let h=s[l];if(!h||h!==u){if(i.push(`/${l}`),h&&h!==u)i.push(`/${h}`)}}for(let[l,u]of Object.entries(s))if(!c[l])i.push(`/${l}`),i.push(`/${u}`);if(i.length>100)return["/*"];return[...new Set(i)]}static updateHtmlReferences(a){let{htmlDir:n,manifest:i,basePath:s=""}=a,c=D.collectFiles(n).filter((l)=>l.endsWith(".html")||l.endsWith(".htm"));for(let l of c){let u=nt(l,"utf-8");for(let[h,y]of Object.entries(i.hashMap)){if(h===y)continue;let f=[new RegExp(`(src|href)=["']${s}/?${D.escapeRegExp(h)}["']`,"g"),new RegExp(`url\\(["']?${s}/?${D.escapeRegExp(h)}["']?\\)`,"g")];for(let S of f)u=u.replace(S,(b)=>b.replace(h,y))}it(l,u)}}static updateCssReferences(a){let{cssDir:n,manifest:i,basePath:s=""}=a,c=D.collectFiles(n).filter((l)=>l.endsWith(".css"));for(let l of c){let u=nt(l,"utf-8");for(let[h,y]of Object.entries(i.hashMap)){if(h===y)continue;let f=new RegExp(`url\\(["']?${s}/?${D.escapeRegExp(h)}["']?\\)`,"g");u=u.replace(f,`url(${s}/${y})`)}it(l,u)}}static escapeRegExp(a){return a.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}static generateS3DeploymentManifest(a){let{sourceDir:n,keyPrefix:i="",excludePatterns:s=[],cacheControl:c={hashed:"public, max-age=31536000, immutable",unhashed:"public, max-age=3600",html:"public, max-age=0, must-revalidate"}}=a;return D.hashDirectory({sourceDir:n,excludePatterns:s}).assets.map((l)=>{let u=l.hash!=="",h=l.contentType==="text/html",y=c.unhashed||"public, max-age=3600";if(h)y=c.html||"public, max-age=0, must-revalidate";else if(u)y=c.hashed||"public, max-age=31536000, immutable";return{localPath:He(n,l.originalPath),s3Key:i?`${i}/${l.hashedPath}`:l.hashedPath,contentType:l.contentType,cacheControl:y,hash:l.hash}})}static compareManifests(a,n){let i={added:[],removed:[],changed:[],unchanged:[]},s=new Set(Object.keys(a.hashMap)),c=new Set(Object.keys(n.hashMap));for(let l of c)if(!s.has(l))i.added.push(l);for(let l of s)if(!c.has(l))i.removed.push(l);for(let l of c)if(s.has(l))if(a.hashMap[l]!==n.hashMap[l])i.changed.push(l);else i.unchanged.push(l);return i}static loadManifest(a){if(!Et(a))return null;try{let n=nt(a,"utf-8");return JSON.parse(n)}catch{return null}}static saveManifest(a,n){it(n,JSON.stringify(a,null,2))}}class pi{static createSecret(a){let{slug:n,environment:i,secretName:s,description:c,secretString:l,kmsKeyId:u,tags:h}=a,y=s||r({slug:n,environment:i,resourceType:"secret"}),f=t(y),S={Type:"AWS::SecretsManager::Secret",Properties:{Name:y,Description:c,SecretString:l,Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:i},...h?Object.entries(h).map(([b,C])=>({Key:b,Value:C})):[]]}};if(u)S.Properties.KmsKeyId=u;return{secret:S,logicalId:f}}static createGeneratedSecret(a){let{slug:n,environment:i,secretName:s,description:c,excludeCharacters:l,excludeLowercase:u,excludeNumbers:h,excludePunctuation:y,excludeUppercase:f,passwordLength:S,requireEachIncludedType:b,kmsKeyId:C,tags:T}=a,v=s||r({slug:n,environment:i,resourceType:"secret"}),w=t(v),R={Type:"AWS::SecretsManager::Secret",Properties:{Name:v,Description:c,GenerateSecretString:{ExcludeCharacters:l,ExcludeLowercase:u,ExcludeNumbers:h,ExcludePunctuation:y,ExcludeUppercase:f,PasswordLength:S||32,RequireEachIncludedType:b!==!1},Tags:[{Key:"Name",Value:v},{Key:"Environment",Value:i},...T?Object.entries(T).map(([k,W])=>({Key:k,Value:W})):[]]}};if(C)R.Properties.KmsKeyId=C;return{secret:R,logicalId:w}}static createDatabaseSecret(a){let{slug:n,environment:i,secretName:s,username:c,dbname:l,engine:u,host:h,port:y,kmsKeyId:f}=a,S=s||r({slug:n,environment:i,resourceType:"db-secret"}),b=t(S),C={username:c};if(l)C.dbname=l;if(u)C.engine=u;if(h)C.host=h;if(y)C.port=y;let T={Type:"AWS::SecretsManager::Secret",Properties:{Name:S,Description:`Database credentials for ${c}`,GenerateSecretString:{SecretStringTemplate:JSON.stringify(C),GenerateStringKey:"password",PasswordLength:32,ExcludeCharacters:'"@/\\',RequireEachIncludedType:!0},Tags:[{Key:"Name",Value:S},{Key:"Environment",Value:i},{Key:"Type",Value:"database"}]}};if(f)T.Properties.KmsKeyId=f;return{secret:T,logicalId:b}}static attachToDatabase(a){let{slug:n,environment:i,secretId:s,targetId:c,targetType:l}=a,u=r({slug:n,environment:i,resourceType:"secret-attachment"}),h=t(u);return{attachment:{Type:"AWS::SecretsManager::SecretTargetAttachment",Properties:{SecretId:s,TargetId:c,TargetType:l}},logicalId:h}}static enableRotation(a){let{slug:n,environment:i,secretId:s,rotationLambdaArn:c,automaticallyAfterDays:l,rotationType:u,kmsKeyArn:h,vpcSecurityGroupIds:y,vpcSubnetIds:f}=a,S=r({slug:n,environment:i,resourceType:"secret-rotation"}),b=t(S),C={Type:"AWS::SecretsManager::RotationSchedule",Properties:{SecretId:s,RotationRules:{AutomaticallyAfterDays:l||30}}};if(c)C.Properties.RotationLambdaARN=c;else if(u)C.Properties.HostedRotationLambda={RotationType:u,KmsKeyArn:h,VpcSecurityGroupIds:y,VpcSubnetIds:f};return{rotation:C,logicalId:b}}static SecretTypes={apiKey:(a,n,i)=>pi.createGeneratedSecret({slug:a,environment:n,secretName:`${a}-${n}-${i}-api-key`,description:`API key for ${i}`,passwordLength:32,excludePunctuation:!0,excludeLowercase:!1,excludeUppercase:!1,excludeNumbers:!1}),oauthClientSecret:(a,n,i)=>pi.createGeneratedSecret({slug:a,environment:n,secretName:`${a}-${n}-${i}-oauth-secret`,description:`OAuth client secret for ${i}`,passwordLength:64,excludeCharacters:"\"'`\\/@",requireEachIncludedType:!0}),jwtSecret:(a,n)=>pi.createGeneratedSecret({slug:a,environment:n,secretName:`${a}-${n}-jwt-secret`,description:"JWT signing secret",passwordLength:64,excludePunctuation:!0}),encryptionKey:(a,n)=>pi.createGeneratedSecret({slug:a,environment:n,secretName:`${a}-${n}-encryption-key`,description:"Data encryption key",passwordLength:64,excludeCharacters:"+/=",excludePunctuation:!0})};static RotationTypes={MySQLSingleUser:"MySQLSingleUser",MySQLMultiUser:"MySQLMultiUser",PostgreSQLSingleUser:"PostgreSQLSingleUser",PostgreSQLMultiUser:"PostgreSQLMultiUser",OracleSingleUser:"OracleSingleUser",OracleMultiUser:"OracleMultiUser",MariaDBSingleUser:"MariaDBSingleUser",MariaDBMultiUser:"MariaDBMultiUser",SQLServerSingleUser:"SQLServerSingleUser",SQLServerMultiUser:"SQLServerMultiUser",RedshiftSingleUser:"RedshiftSingleUser",RedshiftMultiUser:"RedshiftMultiUser",MongoDBSingleUser:"MongoDBSingleUser",MongoDBMultiUser:"MongoDBMultiUser"}}class E{static createParameter(a){let{slug:n,environment:i,parameterName:s,value:c,type:l="String",description:u,tier:h="Standard",tags:y}=a,f=s||r({slug:n,environment:i,resourceType:"parameter"}),S=t(f);return{parameter:{Type:"AWS::SSM::Parameter",Properties:{Name:`/${n}/${i}/${f}`,Type:l,Value:c,Description:u,Tier:h,Tags:{Name:f,Environment:i,...y}}},logicalId:S}}static createString(a,n,i,s,c){return E.createParameter({slug:a,environment:n,parameterName:i,value:s,type:"String",description:c})}static createSecureString(a,n,i,s,c){return E.createParameter({slug:a,environment:n,parameterName:i,value:s,type:"SecureString",description:c})}static createStringList(a,n,i,s,c){return E.createParameter({slug:a,environment:n,parameterName:i,value:s.join(","),type:"StringList",description:c})}static Parameters={databaseUrl:(a,n,i)=>E.createSecureString(a,n,"database-url",i,"Database connection URL"),apiEndpoint:(a,n,i)=>E.createString(a,n,"api-endpoint",i,"API endpoint URL"),appVersion:(a,n,i)=>E.createString(a,n,"app-version",i,"Application version"),featureFlags:(a,n,i)=>E.createStringList(a,n,"feature-flags",i,"Enabled feature flags"),apiKey:(a,n,i,s)=>E.createSecureString(a,n,`${i}-api-key`,s,`API key for ${i}`),oauthCredentials:(a,n,i,s)=>{let c=E.createString(a,n,"oauth-client-id",i,"OAuth client ID"),l=E.createSecureString(a,n,"oauth-client-secret",s,"OAuth client secret");return{clientId:c,clientSecret:l}},smtpCredentials:(a,n,i,s,c,l)=>{let u=E.createString(a,n,"smtp-username",i,"SMTP username"),h=E.createSecureString(a,n,"smtp-password",s,"SMTP password"),y=E.createString(a,n,"smtp-host",c,"SMTP host"),f=E.createString(a,n,"smtp-port",l.toString(),"SMTP port");return{username:u,password:h,host:y,port:f}},redisUrl:(a,n,i)=>E.createSecureString(a,n,"redis-url",i,"Redis connection URL"),s3Bucket:(a,n,i)=>E.createString(a,n,"s3-bucket",i,"S3 bucket name"),cloudFrontDistribution:(a,n,i)=>E.createString(a,n,"cloudfront-distribution-id",i,"CloudFront distribution ID")}}class Ut{static createDomain(a){let{slug:n,environment:i,domainName:s,engineVersion:c="OpenSearch_2.11",instanceType:l="t3.small.search",instanceCount:u=1,volumeSize:h=10,volumeType:y="gp3",dedicatedMaster:f=!1,dedicatedMasterType:S,dedicatedMasterCount:b=3,multiAz:C=!1,availabilityZoneCount:T=2,vpc:v,encryption:w,enforceHttps:R=!0,tlsSecurityPolicy:k="Policy-Min-TLS-1-2-2019-07",advancedSecurity:W,autoSnapshotHour:P=0,autoTune:V=!0,tags:B={}}=a,j=s||r({slug:n,environment:i,resourceType:"search"}),Z=t(j);return{domain:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:j,EngineVersion:c,ClusterConfig:{InstanceType:l,InstanceCount:u,DedicatedMasterEnabled:f,...f&&{DedicatedMasterType:S||l,DedicatedMasterCount:b},ZoneAwarenessEnabled:C,...C&&{ZoneAwarenessConfig:{AvailabilityZoneCount:T}}},EBSOptions:{EBSEnabled:!0,VolumeType:y,VolumeSize:h},DomainEndpointOptions:{EnforceHTTPS:R,TLSSecurityPolicy:k},SnapshotOptions:{AutomatedSnapshotStartHour:P},...v&&{VPCOptions:{SubnetIds:v.subnetIds,SecurityGroupIds:v.securityGroupIds}},...w&&{EncryptionAtRestOptions:{Enabled:w.atRest??!0,...w.kmsKeyId&&{KmsKeyId:w.kmsKeyId}},NodeToNodeEncryptionOptions:{Enabled:w.nodeToNode??!0}},...W&&{AdvancedSecurityOptions:{Enabled:W.enabled,InternalUserDatabaseEnabled:W.internalUserDatabase??!0,...W.masterUserName&&W.masterUserPassword&&{MasterUserOptions:{MasterUserName:W.masterUserName,MasterUserPassword:W.masterUserPassword}},...W.masterUserArn&&{MasterUserOptions:{MasterUserARN:W.masterUserArn}}}},...V&&{AutoTuneOptions:{DesiredState:"ENABLED"}},Tags:[{Key:"Name",Value:j},{Key:"Environment",Value:i},...Object.entries(B).map(([K,ee])=>({Key:K,Value:ee}))]}},logicalId:Z}}static createAccessPolicy(a,n){let{ipAddresses:i,iamPrincipalArns:s,allowAll:c,vpcEndpoint:l}=n;if(c)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:a}]};let u=[];if(s&&s.length>0)u.push({Effect:"Allow",Principal:{AWS:s},Action:"es:*",Resource:a});if(i&&i.length>0)u.push({Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:a,Condition:{IpAddress:{"aws:SourceIp":i}}});if(l)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:a}]};return{Version:"2012-10-17",Statement:u}}static DomainPresets={development:(a,n)=>Ut.createDomain({slug:a,environment:n,instanceType:"t3.small.search",instanceCount:1,volumeSize:10,multiAz:!1,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!1}),production:(a,n,i)=>Ut.createDomain({slug:a,environment:n,instanceType:"m6g.large.search",instanceCount:3,volumeSize:100,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"m6g.large.search",dedicatedMasterCount:3,vpc:i,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!0},autoTune:!0}),costOptimized:(a,n)=>Ut.createDomain({slug:a,environment:n,instanceType:"t3.medium.search",instanceCount:2,volumeSize:20,volumeType:"gp3",multiAz:!0,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!0}),highPerformance:(a,n,i)=>Ut.createDomain({slug:a,environment:n,instanceType:"r6g.2xlarge.search",instanceCount:6,volumeSize:500,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"c6g.xlarge.search",dedicatedMasterCount:3,vpc:i,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!1},autoTune:!0})};static InstanceTypes={"t3.small.search":"t3.small.search","t3.medium.search":"t3.medium.search","m6g.large.search":"m6g.large.search","m6g.xlarge.search":"m6g.xlarge.search","m6g.2xlarge.search":"m6g.2xlarge.search","r6g.large.search":"r6g.large.search","r6g.xlarge.search":"r6g.xlarge.search","r6g.2xlarge.search":"r6g.2xlarge.search","r6g.4xlarge.search":"r6g.4xlarge.search","c6g.large.search":"c6g.large.search","c6g.xlarge.search":"c6g.xlarge.search","c6g.2xlarge.search":"c6g.2xlarge.search"};static EngineVersions={"OpenSearch_2.11":"OpenSearch_2.11","OpenSearch_2.9":"OpenSearch_2.9","OpenSearch_2.7":"OpenSearch_2.7","OpenSearch_1.3":"OpenSearch_1.3","Elasticsearch_7.10":"Elasticsearch_7.10"}}class ct{static createDomainRedirectBucket(a){let{slug:n,environment:i,sourceDomain:s,targetDomain:c,protocol:l="https"}=a,u=r({slug:n,environment:i,resourceType:"s3",suffix:"redirect"}),h=t(u),y=t(`${u}-policy`),f={Type:"AWS::S3::Bucket",Properties:{BucketName:s,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:c,Protocol:l}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1},Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:i},{Key:"Purpose",Value:"Domain Redirect"}]}},S={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:N.Ref(h),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[N.Join("",[N.GetAtt(h,"Arn"),"/*"])]}]}}};return{bucket:f,bucketPolicy:S,logicalId:h,policyLogicalId:y}}static createPathRedirectFunction(a){let{slug:n,environment:i,rules:s}=a,c=r({slug:n,environment:i,resourceType:"cf-redirect"}),l=t(c),u=ct.generateRedirectFunctionCode(s);return{function:{Type:"AWS::CloudFront::Function",Properties:{Name:c,AutoPublish:!0,FunctionConfig:{Comment:`Path redirect function for ${n} (${i})`,Runtime:"cloudfront-js-2.0"},FunctionCode:u}},logicalId:l,functionCode:u}}static generateRedirectFunctionCode(a){return`function handler(event) {
|
|
2317
2317
|
const request = event.request;
|
|
2318
2318
|
const uri = request.uri;
|
|
2319
2319
|
const querystring = request.querystring;
|
|
@@ -2465,7 +2465,7 @@ exports.handler = async (event) => {
|
|
|
2465
2465
|
console.log('Receive SMS:', JSON.stringify(event, null, 2));
|
|
2466
2466
|
// Process inbound SMS, handle opt-out keywords
|
|
2467
2467
|
return { statusCode: 200 };
|
|
2468
|
-
};`}var e={ref:(a)=>({Ref:a}),getAtt:(a,n)=>({"Fn::GetAtt":[a,n]}),join:(a,n)=>({"Fn::Join":[a,n]}),sub:(a,n)=>n?{"Fn::Sub":[a,n]}:{"Fn::Sub":a},select:(a,n)=>({"Fn::Select":[a,n]}),split:(a,n)=>({"Fn::Split":[a,n]}),getAZs:(a="")=>({"Fn::GetAZs":a}),importValue:(a)=>({"Fn::ImportValue":a}),findInMap:(a,n,i)=>({"Fn::FindInMap":[a,n,i]}),base64:(a)=>({"Fn::Base64":a}),cidr:(a,n,i)=>({"Fn::Cidr":[a,n,i]}),equals:(a,n)=>({"Fn::Equals":[a,n]}),if:(a,n,i)=>({"Fn::If":[a,n,i]}),not:(a)=>({"Fn::Not":[a]}),and:(...a)=>({"Fn::And":a}),or:(...a)=>({"Fn::Or":a})},qs={s3Bucket:(a)=>e.sub(`arn:aws:s3:::${a}`),s3Object:(a,n="*")=>e.sub(`arn:aws:s3:::${a}/${n}`),lambda:(a,n,i)=>e.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${a}`,n&&i?{"AWS::Region":n,"AWS::AccountId":i}:void 0),dynamodb:(a)=>e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${a}`),sqs:(a)=>e.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${a}`),sns:(a)=>e.sub(`arn:aws:sns:\${AWS::Region}:\${AWS::AccountId}:${a}`),kinesis:(a)=>e.sub(`arn:aws:kinesis:\${AWS::Region}:\${AWS::AccountId}:stream/${a}`),iam:(a,n)=>e.sub(`arn:aws:iam::\${AWS::AccountId}:${a}/${n}`),secretsManager:(a)=>e.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${a}`),cloudwatch:(a)=>e.sub(`arn:aws:logs:\${AWS::Region}:\${AWS::AccountId}:log-group:${a}`)},xy={ACCOUNT_ID:{Ref:"AWS::AccountId"},NOTIFICATION_ARNS:{Ref:"AWS::NotificationARNs"},NO_VALUE:{Ref:"AWS::NoValue"},PARTITION:{Ref:"AWS::Partition"},REGION:{Ref:"AWS::Region"},STACK_ID:{Ref:"AWS::StackId"},STACK_NAME:{Ref:"AWS::StackName"},URL_SUFFIX:{Ref:"AWS::URLSuffix"}};function wr(a,n){if(n.type==="http")Er(a,n);else if(n.type==="rest")Pr(a,n);else if(n.type==="websocket")Ir(a,n)}function Er(a,n){let i={Name:e.sub("${AWS::StackName}-http-api"),ProtocolType:"HTTP"};if(n.cors)i.CorsConfiguration={AllowOrigins:n.cors.allowOrigins,AllowMethods:n.cors.allowMethods,AllowHeaders:n.cors.allowHeaders||["*"],MaxAge:n.cors.maxAge||300};if(a.addResource("HttpApi","AWS::ApiGatewayV2::Api",i),a.addResource("HttpApiStage","AWS::ApiGatewayV2::Stage",{ApiId:e.ref("HttpApi"),StageName:"$default",AutoDeploy:!0,DefaultRouteSettings:n.throttling?{ThrottlingBurstLimit:n.throttling.burstLimit,ThrottlingRateLimit:n.throttling.rateLimit}:void 0,AccessLogSettings:{DestinationArn:e.getAtt("ApiLogGroup","Arn"),Format:"$context.requestId $context.error.message $context.error.messageString"}},{dependsOn:["HttpApi","ApiLogGroup"]}),a.addResource("ApiLogGroup","AWS::Logs::LogGroup",{LogGroupName:e.sub("/aws/apigateway/${AWS::StackName}-http-api"),RetentionInDays:14}),n.authorizer)Rr(a,"HttpApi",n.authorizer);if(n.customDomain)Bt(a,"HttpApi",n.customDomain,"HTTP");a.addOutputs({HttpApiId:{Description:"HTTP API ID",Value:e.ref("HttpApi"),Export:{Name:e.sub("${AWS::StackName}-http-api-id")}},HttpApiEndpoint:{Description:"HTTP API endpoint",Value:e.getAtt("HttpApi","ApiEndpoint"),Export:{Name:e.sub("${AWS::StackName}-http-api-endpoint")}}})}function Pr(a,n){a.addResource("RestApi","AWS::ApiGateway::RestApi",{Name:e.sub("${AWS::StackName}-rest-api"),Description:e.sub("REST API for ${AWS::StackName}"),EndpointConfiguration:{Types:["REGIONAL"]}}),a.addResource("ApiGatewayAccount","AWS::ApiGateway::Account",{CloudWatchRoleArn:e.getAtt("ApiGatewayCloudWatchRole","Arn")},{dependsOn:"ApiGatewayCloudWatchRole"}),a.addResource("ApiGatewayCloudWatchRole","AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"apigateway.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs"]}),a.addResource("RestApiDeployment","AWS::ApiGateway::Deployment",{RestApiId:e.ref("RestApi"),Description:"Initial deployment"},{dependsOn:"RestApi"});let i={RestApiId:e.ref("RestApi"),DeploymentId:e.ref("RestApiDeployment"),StageName:"prod",Description:"Production stage",MethodSettings:[{ResourcePath:"/*",HttpMethod:"*",LoggingLevel:"INFO",DataTraceEnabled:!0,MetricsEnabled:!0}]};if(n.throttling)i.MethodSettings[0].ThrottlingBurstLimit=n.throttling.burstLimit,i.MethodSettings[0].ThrottlingRateLimit=n.throttling.rateLimit;if(a.addResource("RestApiStage","AWS::ApiGateway::Stage",i,{dependsOn:["RestApi","RestApiDeployment"]}),n.customDomain)Bt(a,"RestApi",n.customDomain,"REST");a.addOutputs({RestApiId:{Description:"REST API ID",Value:e.ref("RestApi"),Export:{Name:e.sub("${AWS::StackName}-rest-api-id")}},RestApiEndpoint:{Description:"REST API endpoint",Value:e.sub("https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/prod"),Export:{Name:e.sub("${AWS::StackName}-rest-api-endpoint")}}})}function Ir(a,n){if(a.addResource("WebSocketApi","AWS::ApiGatewayV2::Api",{Name:e.sub("${AWS::StackName}-websocket-api"),ProtocolType:"WEBSOCKET",RouteSelectionExpression:"$request.body.action"}),n.routes){if(n.routes.connect)st(a,"$connect",n.routes.connect.functionName);if(n.routes.disconnect)st(a,"$disconnect",n.routes.disconnect.functionName);if(n.routes.default)st(a,"$default",n.routes.default.functionName);if(n.routes.custom)n.routes.custom.forEach((i)=>{st(a,i.routeKey,i.functionName)})}if(a.addResource("WebSocketApiStage","AWS::ApiGatewayV2::Stage",{ApiId:e.ref("WebSocketApi"),StageName:"prod",AutoDeploy:!0,DefaultRouteSettings:n.throttling?{ThrottlingBurstLimit:n.throttling.burstLimit,ThrottlingRateLimit:n.throttling.rateLimit}:void 0},{dependsOn:"WebSocketApi"}),n.customDomain)Bt(a,"WebSocketApi",n.customDomain,"WEBSOCKET");a.addOutputs({WebSocketApiId:{Description:"WebSocket API ID",Value:e.ref("WebSocketApi"),Export:{Name:e.sub("${AWS::StackName}-websocket-api-id")}},WebSocketApiEndpoint:{Description:"WebSocket API endpoint",Value:e.getAtt("WebSocketApi","ApiEndpoint"),Export:{Name:e.sub("${AWS::StackName}-websocket-api-endpoint")}}})}function st(a,n,i){let s=a.toLogicalId(`websocket-route-${n}`),c=a.toLogicalId(`websocket-integration-${n}`),l=a.toLogicalId(`${i}-function`);a.addResource(c,"AWS::ApiGatewayV2::Integration",{ApiId:e.ref("WebSocketApi"),IntegrationType:"AWS_PROXY",IntegrationUri:e.sub(`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${l}.Arn}/invocations`)},{dependsOn:["WebSocketApi",l]}),a.addResource(s,"AWS::ApiGatewayV2::Route",{ApiId:e.ref("WebSocketApi"),RouteKey:n,Target:e.join("/",["integrations",e.ref(c)])},{dependsOn:["WebSocketApi",c]}),a.addResource(`${s}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(l),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:e.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${WebSocketApi}/*")},{dependsOn:[l,"WebSocketApi"]})}function Bt(a,n,i,s){let c={DomainName:i.domain};if(s==="REST")c.CertificateArn=i.certificateArn,c.EndpointConfiguration={Types:["REGIONAL"]},a.addResource("ApiCustomDomain","AWS::ApiGateway::DomainName",c),a.addResource("ApiBasePathMapping","AWS::ApiGateway::BasePathMapping",{DomainName:e.ref("ApiCustomDomain"),RestApiId:e.ref(n),Stage:e.ref("RestApiStage")},{dependsOn:["ApiCustomDomain",n,"RestApiStage"]});else c.DomainNameConfigurations=[{CertificateArn:i.certificateArn,EndpointType:"REGIONAL"}],a.addResource("ApiCustomDomain","AWS::ApiGatewayV2::DomainName",c),a.addResource("ApiMapping","AWS::ApiGatewayV2::ApiMapping",{ApiId:e.ref(n),DomainName:e.ref("ApiCustomDomain"),Stage:s==="HTTP"?e.ref("HttpApiStage"):e.ref("WebSocketApiStage")},{dependsOn:["ApiCustomDomain",n]});if(i.dnsProvider!=="external")a.addResource("ApiDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:e.sub(`${Dr(i.domain)}.`),Name:i.domain,Type:"A",AliasTarget:{HostedZoneId:e.getAtt("ApiCustomDomain","RegionalHostedZoneId"),DNSName:e.getAtt("ApiCustomDomain","RegionalDomainName"),EvaluateTargetHealth:!1}},{dependsOn:"ApiCustomDomain"});a.addOutputs({ApiCustomDomainName:{Description:"Configured API custom domain",Value:i.domain},ApiCustomDomainTarget:{Description:"DNS target for Route53 or an external DNS provider",Value:e.getAtt("ApiCustomDomain","RegionalDomainName")},ApiCustomDomainHostedZoneId:{Description:"Regional API Gateway hosted zone ID",Value:e.getAtt("ApiCustomDomain","RegionalHostedZoneId")}})}function Rr(a,n,i){if(!i)return;if(i.type==="jwt")a.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:e.ref(n),AuthorizerType:"JWT",IdentitySource:[i.identitySource||"$request.header.Authorization"],JwtConfiguration:{Issuer:i.issuer,Audience:i.audience},Name:"JWTAuthorizer"},{dependsOn:n});else if(i.type==="lambda")a.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:e.ref(n),AuthorizerType:"REQUEST",AuthorizerUri:i.authorizerUri,IdentitySource:[i.identitySource||"$request.header.Authorization"],Name:"LambdaAuthorizer"},{dependsOn:n})}function Dr(a){let n=a.split(".");if(n.length>=2)return n.slice(-2).join(".");return a}function $r(a,n){if(n.redis)Lr(a,n.redis);if(n.memcached)Mr(a,n.memcached);if(n.elasticache)Or(a,n.elasticache)}function Lr(a,n){if(!n)return;if(a.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache Redis cluster",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-subnet-group")}]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]}),a.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Redis",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:n.port||6379,ToPort:n.port||6379,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]}),n.parameterGroup&&Object.keys(n.parameterGroup).length>0)a.addResource("CacheParameterGroup","AWS::ElastiCache::ParameterGroup",{Description:"Parameter group for Redis",CacheParameterGroupFamily:`redis${n.engineVersion.split(".")[0]}`,Properties:n.parameterGroup});if(n.numCacheNodes>1||n.automaticFailoverEnabled)a.addResource("RedisReplicationGroup","AWS::ElastiCache::ReplicationGroup",{ReplicationGroupDescription:"Redis replication group",ReplicationGroupId:e.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:n.engineVersion,CacheNodeType:n.nodeType,NumCacheClusters:n.numCacheNodes,AutomaticFailoverEnabled:n.automaticFailoverEnabled||!1,MultiAZEnabled:n.automaticFailoverEnabled||!1,Port:n.port||6379,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),SecurityGroupIds:[e.ref("CacheSecurityGroup")],CacheParameterGroupName:n.parameterGroup?e.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:n.snapshotRetentionLimit||5,SnapshotWindow:n.snapshotWindow||"03:00-05:00",PreferredMaintenanceWindow:"sun:05:00-sun:06:00",AtRestEncryptionEnabled:!0,TransitEncryptionEnabled:!0,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-redis")}]},{dependsOn:n.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),a.addOutputs({RedisEndpoint:{Description:"Redis primary endpoint",Value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Address"),Export:{Name:e.sub("${AWS::StackName}-redis-endpoint")}},RedisPort:{Description:"Redis port",Value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Port"),Export:{Name:e.sub("${AWS::StackName}-redis-port")}}});else a.addResource("RedisCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:n.engineVersion,CacheNodeType:n.nodeType,NumCacheNodes:1,Port:n.port||6379,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],CacheParameterGroupName:n.parameterGroup?e.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:n.snapshotRetentionLimit||5,SnapshotWindow:n.snapshotWindow||"03:00-05:00",PreferredMaintenanceWindow:"sun:05:00-sun:06:00",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-redis")}]},{dependsOn:n.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),a.addOutputs({RedisEndpoint:{Description:"Redis endpoint",Value:e.getAtt("RedisCacheCluster","RedisEndpoint.Address"),Export:{Name:e.sub("${AWS::StackName}-redis-endpoint")}},RedisPort:{Description:"Redis port",Value:e.getAtt("RedisCacheCluster","RedisEndpoint.Port"),Export:{Name:e.sub("${AWS::StackName}-redis-port")}}})}function Mr(a,n){if(!n)return;if(!a.hasResource("CacheSubnetGroup"))a.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!a.hasResource("CacheSecurityGroup"))a.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Memcached",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:n.port||11211,ToPort:n.port||11211,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});a.addResource("MemcachedCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub("${AWS::StackName}-memcached"),Engine:"memcached",EngineVersion:n.engineVersion,CacheNodeType:n.nodeType,NumCacheNodes:n.numCacheNodes,Port:n.port||11211,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],PreferredMaintenanceWindow:"sun:05:00-sun:06:00",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-memcached")}]},{dependsOn:["CacheSubnetGroup","CacheSecurityGroup"]}),a.addOutputs({MemcachedEndpoint:{Description:"Memcached configuration endpoint",Value:e.getAtt("MemcachedCacheCluster","ConfigurationEndpoint.Address"),Export:{Name:e.sub("${AWS::StackName}-memcached-endpoint")}},MemcachedPort:{Description:"Memcached port",Value:e.getAtt("MemcachedCacheCluster","ConfigurationEndpoint.Port"),Export:{Name:e.sub("${AWS::StackName}-memcached-port")}}})}function Or(a,n){if(!n)return;let i=n.engine==="redis";if(!a.hasResource("CacheSubnetGroup"))a.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!a.hasResource("CacheSecurityGroup"))a.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:i?6379:11211,ToPort:i?6379:11211,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});a.addResource("CacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub(`\${AWS::StackName}-${n.engine}`),Engine:n.engine,EngineVersion:n.engineVersion,CacheNodeType:n.nodeType,NumCacheNodes:n.numCacheNodes,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n.engine}`)}]},{dependsOn:["CacheSubnetGroup","CacheSecurityGroup"]})}function Wr(a,n){if(!n.enabled)return;a.addResource("CloudFrontOriginAccessIdentity","AWS::CloudFront::CloudFrontOriginAccessIdentity",{CloudFrontOriginAccessIdentityConfig:{Comment:e.sub("${AWS::StackName} CloudFront OAI")}});let i=[],s=[];if(!n.origins||n.origins.length===0)i.push({Id:"S3Origin",DomainName:e.getAtt("StaticBucket","DomainName"),S3OriginConfig:{OriginAccessIdentity:e.sub("origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}")}});else n.origins.forEach((u,h)=>{let y={Id:u.id,DomainName:u.domainName};if(u.originPath)y.OriginPath=u.originPath;if(u.domainName.includes("s3"))y.S3OriginConfig={OriginAccessIdentity:e.sub("origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}")};else y.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"]};if(i.push(y),h>0||u.pathPattern)s.push({PathPattern:u.pathPattern||`/${u.id}/*`,TargetOriginId:u.id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:n.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:n.cachePolicy?.minTTL||0,DefaultTTL:n.cachePolicy?.defaultTTL||86400,MaxTTL:n.cachePolicy?.maxTTL||31536000})});let c={TargetOriginId:i[0].Id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:n.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:n.cachePolicy?.minTTL||0,DefaultTTL:n.cachePolicy?.defaultTTL||86400,MaxTTL:n.cachePolicy?.maxTTL||31536000};if(n.edgeFunctions&&n.edgeFunctions.length>0)c.LambdaFunctionAssociations=n.edgeFunctions.map((u)=>({EventType:u.eventType,LambdaFunctionARN:u.functionArn}));let l={Enabled:!0,HttpVersion:n.http3?"http3":"http2",IPV6Enabled:!0,Origins:i,DefaultCacheBehavior:c,PriceClass:n.priceClass||"PriceClass_100",ViewerCertificate:{}};if(s.length>0)l.CacheBehaviors=s;if(n.customDomain)l.Aliases=[n.customDomain.domain],l.ViewerCertificate={AcmCertificateArn:n.customDomain.certificateArn,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};else l.ViewerCertificate={CloudFrontDefaultCertificate:!0};if(n.errorPages)l.CustomErrorResponses=Object.entries(n.errorPages).map(([u,h])=>({ErrorCode:Number.parseInt(u),ResponseCode:200,ResponsePagePath:h,ErrorCachingMinTTL:300}));if(l.DefaultRootObject="index.html",l.Comment=e.sub("${AWS::StackName} CloudFront Distribution"),a.addResource("CloudFrontDistribution","AWS::CloudFront::Distribution",{DistributionConfig:l},{dependsOn:"CloudFrontOriginAccessIdentity"}),!n.origins||n.origins.length===0)a.addResource("StaticBucketPolicyForCloudFront","AWS::S3::BucketPolicy",{Bucket:e.ref("StaticBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowCloudFrontAccess",Effect:"Allow",Principal:{CanonicalUser:e.getAtt("CloudFrontOriginAccessIdentity","S3CanonicalUserId")},Action:"s3:GetObject",Resource:e.join("",[e.getAtt("StaticBucket","Arn"),"/*"])}]}},{dependsOn:["StaticBucket","CloudFrontOriginAccessIdentity"]});if(n.customDomain)a.addResource("CloudFrontDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:e.sub(`${Gr(n.customDomain.domain)}.`),Name:n.customDomain.domain,Type:"A",AliasTarget:{HostedZoneId:"Z2FDTNDATAQYW2",DNSName:e.getAtt("CloudFrontDistribution","DomainName"),EvaluateTargetHealth:!1}},{dependsOn:"CloudFrontDistribution"});if(a.addOutputs({CloudFrontDistributionId:{Description:"CloudFront distribution ID",Value:e.ref("CloudFrontDistribution"),Export:{Name:e.sub("${AWS::StackName}-cloudfront-id")}},CloudFrontDomainName:{Description:"CloudFront distribution domain name",Value:e.getAtt("CloudFrontDistribution","DomainName"),Export:{Name:e.sub("${AWS::StackName}-cloudfront-domain")}}}),n.customDomain)a.addOutputs({CloudFrontURL:{Description:"CloudFront custom domain URL",Value:e.sub(`https://${n.customDomain.domain}`)}})}function Gr(a){let n=a.split(".");if(n.length>=2)return n.slice(-2).join(".");return a}function Ur(a,n){if(n.server)Fr(a,n.server);if(n.fargate)oa(a,"app",n.fargate);if(n.services)n.services.forEach((i)=>{if(i.type==="fargate")oa(a,i.name,{taskDefinition:i.taskDefinition,service:i.service})})}function Fr(a,n){if(!n)return;a.addResource("AppSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for application instances",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:3000,ToPort:3000,SourceSecurityGroupId:e.ref("ALBSecurityGroup")},{IpProtocol:"tcp",FromPort:22,ToPort:22,CidrIp:"0.0.0.0/0"}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-app-sg")}]},{dependsOn:"VPC"}),a.addResource("EC2InstanceRole","AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ec2.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore","arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-ec2-role")}]}),a.addResource("EC2InstanceProfile","AWS::IAM::InstanceProfile",{Roles:[e.ref("EC2InstanceRole")]},{dependsOn:"EC2InstanceRole"});let i=n.userData||`#!/bin/bash
|
|
2468
|
+
};`}var e={ref:(a)=>({Ref:a}),getAtt:(a,n)=>({"Fn::GetAtt":[a,n]}),join:(a,n)=>({"Fn::Join":[a,n]}),sub:(a,n)=>n?{"Fn::Sub":[a,n]}:{"Fn::Sub":a},select:(a,n)=>({"Fn::Select":[a,n]}),split:(a,n)=>({"Fn::Split":[a,n]}),getAZs:(a="")=>({"Fn::GetAZs":a}),importValue:(a)=>({"Fn::ImportValue":a}),findInMap:(a,n,i)=>({"Fn::FindInMap":[a,n,i]}),base64:(a)=>({"Fn::Base64":a}),cidr:(a,n,i)=>({"Fn::Cidr":[a,n,i]}),equals:(a,n)=>({"Fn::Equals":[a,n]}),if:(a,n,i)=>({"Fn::If":[a,n,i]}),not:(a)=>({"Fn::Not":[a]}),and:(...a)=>({"Fn::And":a}),or:(...a)=>({"Fn::Or":a})},Vs={s3Bucket:(a)=>e.sub(`arn:aws:s3:::${a}`),s3Object:(a,n="*")=>e.sub(`arn:aws:s3:::${a}/${n}`),lambda:(a,n,i)=>e.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${a}`,n&&i?{"AWS::Region":n,"AWS::AccountId":i}:void 0),dynamodb:(a)=>e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${a}`),sqs:(a)=>e.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${a}`),sns:(a)=>e.sub(`arn:aws:sns:\${AWS::Region}:\${AWS::AccountId}:${a}`),kinesis:(a)=>e.sub(`arn:aws:kinesis:\${AWS::Region}:\${AWS::AccountId}:stream/${a}`),iam:(a,n)=>e.sub(`arn:aws:iam::\${AWS::AccountId}:${a}/${n}`),secretsManager:(a)=>e.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${a}`),cloudwatch:(a)=>e.sub(`arn:aws:logs:\${AWS::Region}:\${AWS::AccountId}:log-group:${a}`)},xy={ACCOUNT_ID:{Ref:"AWS::AccountId"},NOTIFICATION_ARNS:{Ref:"AWS::NotificationARNs"},NO_VALUE:{Ref:"AWS::NoValue"},PARTITION:{Ref:"AWS::Partition"},REGION:{Ref:"AWS::Region"},STACK_ID:{Ref:"AWS::StackId"},STACK_NAME:{Ref:"AWS::StackName"},URL_SUFFIX:{Ref:"AWS::URLSuffix"}};function wr(a,n){if(n.type==="http")Er(a,n);else if(n.type==="rest")Pr(a,n);else if(n.type==="websocket")Ir(a,n)}function Er(a,n){let i={Name:e.sub("${AWS::StackName}-http-api"),ProtocolType:"HTTP"};if(n.cors)i.CorsConfiguration={AllowOrigins:n.cors.allowOrigins,AllowMethods:n.cors.allowMethods,AllowHeaders:n.cors.allowHeaders||["*"],MaxAge:n.cors.maxAge||300};if(a.addResource("HttpApi","AWS::ApiGatewayV2::Api",i),a.addResource("HttpApiStage","AWS::ApiGatewayV2::Stage",{ApiId:e.ref("HttpApi"),StageName:"$default",AutoDeploy:!0,DefaultRouteSettings:n.throttling?{ThrottlingBurstLimit:n.throttling.burstLimit,ThrottlingRateLimit:n.throttling.rateLimit}:void 0,AccessLogSettings:{DestinationArn:e.getAtt("ApiLogGroup","Arn"),Format:"$context.requestId $context.error.message $context.error.messageString"}},{dependsOn:["HttpApi","ApiLogGroup"]}),a.addResource("ApiLogGroup","AWS::Logs::LogGroup",{LogGroupName:e.sub("/aws/apigateway/${AWS::StackName}-http-api"),RetentionInDays:14}),n.authorizer)Rr(a,"HttpApi",n.authorizer);if(n.customDomain)Bt(a,"HttpApi",n.customDomain,"HTTP");a.addOutputs({HttpApiId:{Description:"HTTP API ID",Value:e.ref("HttpApi"),Export:{Name:e.sub("${AWS::StackName}-http-api-id")}},HttpApiEndpoint:{Description:"HTTP API endpoint",Value:e.getAtt("HttpApi","ApiEndpoint"),Export:{Name:e.sub("${AWS::StackName}-http-api-endpoint")}}})}function Pr(a,n){a.addResource("RestApi","AWS::ApiGateway::RestApi",{Name:e.sub("${AWS::StackName}-rest-api"),Description:e.sub("REST API for ${AWS::StackName}"),EndpointConfiguration:{Types:["REGIONAL"]}}),a.addResource("ApiGatewayAccount","AWS::ApiGateway::Account",{CloudWatchRoleArn:e.getAtt("ApiGatewayCloudWatchRole","Arn")},{dependsOn:"ApiGatewayCloudWatchRole"}),a.addResource("ApiGatewayCloudWatchRole","AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"apigateway.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs"]}),a.addResource("RestApiDeployment","AWS::ApiGateway::Deployment",{RestApiId:e.ref("RestApi"),Description:"Initial deployment"},{dependsOn:"RestApi"});let i={RestApiId:e.ref("RestApi"),DeploymentId:e.ref("RestApiDeployment"),StageName:"prod",Description:"Production stage",MethodSettings:[{ResourcePath:"/*",HttpMethod:"*",LoggingLevel:"INFO",DataTraceEnabled:!0,MetricsEnabled:!0}]};if(n.throttling)i.MethodSettings[0].ThrottlingBurstLimit=n.throttling.burstLimit,i.MethodSettings[0].ThrottlingRateLimit=n.throttling.rateLimit;if(a.addResource("RestApiStage","AWS::ApiGateway::Stage",i,{dependsOn:["RestApi","RestApiDeployment"]}),n.customDomain)Bt(a,"RestApi",n.customDomain,"REST");a.addOutputs({RestApiId:{Description:"REST API ID",Value:e.ref("RestApi"),Export:{Name:e.sub("${AWS::StackName}-rest-api-id")}},RestApiEndpoint:{Description:"REST API endpoint",Value:e.sub("https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/prod"),Export:{Name:e.sub("${AWS::StackName}-rest-api-endpoint")}}})}function Ir(a,n){if(a.addResource("WebSocketApi","AWS::ApiGatewayV2::Api",{Name:e.sub("${AWS::StackName}-websocket-api"),ProtocolType:"WEBSOCKET",RouteSelectionExpression:"$request.body.action"}),n.routes){if(n.routes.connect)st(a,"$connect",n.routes.connect.functionName);if(n.routes.disconnect)st(a,"$disconnect",n.routes.disconnect.functionName);if(n.routes.default)st(a,"$default",n.routes.default.functionName);if(n.routes.custom)n.routes.custom.forEach((i)=>{st(a,i.routeKey,i.functionName)})}if(a.addResource("WebSocketApiStage","AWS::ApiGatewayV2::Stage",{ApiId:e.ref("WebSocketApi"),StageName:"prod",AutoDeploy:!0,DefaultRouteSettings:n.throttling?{ThrottlingBurstLimit:n.throttling.burstLimit,ThrottlingRateLimit:n.throttling.rateLimit}:void 0},{dependsOn:"WebSocketApi"}),n.customDomain)Bt(a,"WebSocketApi",n.customDomain,"WEBSOCKET");a.addOutputs({WebSocketApiId:{Description:"WebSocket API ID",Value:e.ref("WebSocketApi"),Export:{Name:e.sub("${AWS::StackName}-websocket-api-id")}},WebSocketApiEndpoint:{Description:"WebSocket API endpoint",Value:e.getAtt("WebSocketApi","ApiEndpoint"),Export:{Name:e.sub("${AWS::StackName}-websocket-api-endpoint")}}})}function st(a,n,i){let s=a.toLogicalId(`websocket-route-${n}`),c=a.toLogicalId(`websocket-integration-${n}`),l=a.toLogicalId(`${i}-function`);a.addResource(c,"AWS::ApiGatewayV2::Integration",{ApiId:e.ref("WebSocketApi"),IntegrationType:"AWS_PROXY",IntegrationUri:e.sub(`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${l}.Arn}/invocations`)},{dependsOn:["WebSocketApi",l]}),a.addResource(s,"AWS::ApiGatewayV2::Route",{ApiId:e.ref("WebSocketApi"),RouteKey:n,Target:e.join("/",["integrations",e.ref(c)])},{dependsOn:["WebSocketApi",c]}),a.addResource(`${s}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(l),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:e.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${WebSocketApi}/*")},{dependsOn:[l,"WebSocketApi"]})}function Bt(a,n,i,s){let c={DomainName:i.domain};if(s==="REST")c.CertificateArn=i.certificateArn,c.EndpointConfiguration={Types:["REGIONAL"]},a.addResource("ApiCustomDomain","AWS::ApiGateway::DomainName",c),a.addResource("ApiBasePathMapping","AWS::ApiGateway::BasePathMapping",{DomainName:e.ref("ApiCustomDomain"),RestApiId:e.ref(n),Stage:e.ref("RestApiStage")},{dependsOn:["ApiCustomDomain",n,"RestApiStage"]});else c.DomainNameConfigurations=[{CertificateArn:i.certificateArn,EndpointType:"REGIONAL"}],a.addResource("ApiCustomDomain","AWS::ApiGatewayV2::DomainName",c),a.addResource("ApiMapping","AWS::ApiGatewayV2::ApiMapping",{ApiId:e.ref(n),DomainName:e.ref("ApiCustomDomain"),Stage:s==="HTTP"?e.ref("HttpApiStage"):e.ref("WebSocketApiStage")},{dependsOn:["ApiCustomDomain",n]});if(i.dnsProvider!=="external")a.addResource("ApiDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:e.sub(`${Dr(i.domain)}.`),Name:i.domain,Type:"A",AliasTarget:{HostedZoneId:e.getAtt("ApiCustomDomain","RegionalHostedZoneId"),DNSName:e.getAtt("ApiCustomDomain","RegionalDomainName"),EvaluateTargetHealth:!1}},{dependsOn:"ApiCustomDomain"});a.addOutputs({ApiCustomDomainName:{Description:"Configured API custom domain",Value:i.domain},ApiCustomDomainTarget:{Description:"DNS target for Route53 or an external DNS provider",Value:e.getAtt("ApiCustomDomain","RegionalDomainName")},ApiCustomDomainHostedZoneId:{Description:"Regional API Gateway hosted zone ID",Value:e.getAtt("ApiCustomDomain","RegionalHostedZoneId")}})}function Rr(a,n,i){if(!i)return;if(i.type==="jwt")a.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:e.ref(n),AuthorizerType:"JWT",IdentitySource:[i.identitySource||"$request.header.Authorization"],JwtConfiguration:{Issuer:i.issuer,Audience:i.audience},Name:"JWTAuthorizer"},{dependsOn:n});else if(i.type==="lambda")a.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:e.ref(n),AuthorizerType:"REQUEST",AuthorizerUri:i.authorizerUri,IdentitySource:[i.identitySource||"$request.header.Authorization"],Name:"LambdaAuthorizer"},{dependsOn:n})}function Dr(a){let n=a.split(".");if(n.length>=2)return n.slice(-2).join(".");return a}function $r(a,n){if(n.redis)Lr(a,n.redis);if(n.memcached)Mr(a,n.memcached);if(n.elasticache)Or(a,n.elasticache)}function Lr(a,n){if(!n)return;if(a.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache Redis cluster",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-subnet-group")}]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]}),a.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Redis",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:n.port||6379,ToPort:n.port||6379,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]}),n.parameterGroup&&Object.keys(n.parameterGroup).length>0)a.addResource("CacheParameterGroup","AWS::ElastiCache::ParameterGroup",{Description:"Parameter group for Redis",CacheParameterGroupFamily:`redis${n.engineVersion.split(".")[0]}`,Properties:n.parameterGroup});if(n.numCacheNodes>1||n.automaticFailoverEnabled)a.addResource("RedisReplicationGroup","AWS::ElastiCache::ReplicationGroup",{ReplicationGroupDescription:"Redis replication group",ReplicationGroupId:e.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:n.engineVersion,CacheNodeType:n.nodeType,NumCacheClusters:n.numCacheNodes,AutomaticFailoverEnabled:n.automaticFailoverEnabled||!1,MultiAZEnabled:n.automaticFailoverEnabled||!1,Port:n.port||6379,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),SecurityGroupIds:[e.ref("CacheSecurityGroup")],CacheParameterGroupName:n.parameterGroup?e.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:n.snapshotRetentionLimit||5,SnapshotWindow:n.snapshotWindow||"03:00-05:00",PreferredMaintenanceWindow:"sun:05:00-sun:06:00",AtRestEncryptionEnabled:!0,TransitEncryptionEnabled:!0,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-redis")}]},{dependsOn:n.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),a.addOutputs({RedisEndpoint:{Description:"Redis primary endpoint",Value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Address"),Export:{Name:e.sub("${AWS::StackName}-redis-endpoint")}},RedisPort:{Description:"Redis port",Value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Port"),Export:{Name:e.sub("${AWS::StackName}-redis-port")}}});else a.addResource("RedisCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:n.engineVersion,CacheNodeType:n.nodeType,NumCacheNodes:1,Port:n.port||6379,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],CacheParameterGroupName:n.parameterGroup?e.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:n.snapshotRetentionLimit||5,SnapshotWindow:n.snapshotWindow||"03:00-05:00",PreferredMaintenanceWindow:"sun:05:00-sun:06:00",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-redis")}]},{dependsOn:n.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),a.addOutputs({RedisEndpoint:{Description:"Redis endpoint",Value:e.getAtt("RedisCacheCluster","RedisEndpoint.Address"),Export:{Name:e.sub("${AWS::StackName}-redis-endpoint")}},RedisPort:{Description:"Redis port",Value:e.getAtt("RedisCacheCluster","RedisEndpoint.Port"),Export:{Name:e.sub("${AWS::StackName}-redis-port")}}})}function Mr(a,n){if(!n)return;if(!a.hasResource("CacheSubnetGroup"))a.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!a.hasResource("CacheSecurityGroup"))a.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Memcached",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:n.port||11211,ToPort:n.port||11211,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});a.addResource("MemcachedCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub("${AWS::StackName}-memcached"),Engine:"memcached",EngineVersion:n.engineVersion,CacheNodeType:n.nodeType,NumCacheNodes:n.numCacheNodes,Port:n.port||11211,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],PreferredMaintenanceWindow:"sun:05:00-sun:06:00",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-memcached")}]},{dependsOn:["CacheSubnetGroup","CacheSecurityGroup"]}),a.addOutputs({MemcachedEndpoint:{Description:"Memcached configuration endpoint",Value:e.getAtt("MemcachedCacheCluster","ConfigurationEndpoint.Address"),Export:{Name:e.sub("${AWS::StackName}-memcached-endpoint")}},MemcachedPort:{Description:"Memcached port",Value:e.getAtt("MemcachedCacheCluster","ConfigurationEndpoint.Port"),Export:{Name:e.sub("${AWS::StackName}-memcached-port")}}})}function Or(a,n){if(!n)return;let i=n.engine==="redis";if(!a.hasResource("CacheSubnetGroup"))a.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!a.hasResource("CacheSecurityGroup"))a.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:i?6379:11211,ToPort:i?6379:11211,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});a.addResource("CacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub(`\${AWS::StackName}-${n.engine}`),Engine:n.engine,EngineVersion:n.engineVersion,CacheNodeType:n.nodeType,NumCacheNodes:n.numCacheNodes,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n.engine}`)}]},{dependsOn:["CacheSubnetGroup","CacheSecurityGroup"]})}function Wr(a,n){if(!n.enabled)return;a.addResource("CloudFrontOriginAccessIdentity","AWS::CloudFront::CloudFrontOriginAccessIdentity",{CloudFrontOriginAccessIdentityConfig:{Comment:e.sub("${AWS::StackName} CloudFront OAI")}});let i=[],s=[];if(!n.origins||n.origins.length===0)i.push({Id:"S3Origin",DomainName:e.getAtt("StaticBucket","DomainName"),S3OriginConfig:{OriginAccessIdentity:e.sub("origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}")}});else n.origins.forEach((u,h)=>{let y={Id:u.id,DomainName:u.domainName};if(u.originPath)y.OriginPath=u.originPath;if(u.domainName.includes("s3"))y.S3OriginConfig={OriginAccessIdentity:e.sub("origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}")};else y.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"]};if(i.push(y),h>0||u.pathPattern)s.push({PathPattern:u.pathPattern||`/${u.id}/*`,TargetOriginId:u.id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:n.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:n.cachePolicy?.minTTL||0,DefaultTTL:n.cachePolicy?.defaultTTL||86400,MaxTTL:n.cachePolicy?.maxTTL||31536000})});let c={TargetOriginId:i[0].Id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:n.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:n.cachePolicy?.minTTL||0,DefaultTTL:n.cachePolicy?.defaultTTL||86400,MaxTTL:n.cachePolicy?.maxTTL||31536000};if(n.edgeFunctions&&n.edgeFunctions.length>0)c.LambdaFunctionAssociations=n.edgeFunctions.map((u)=>({EventType:u.eventType,LambdaFunctionARN:u.functionArn}));let l={Enabled:!0,HttpVersion:n.http3?"http3":"http2",IPV6Enabled:!0,Origins:i,DefaultCacheBehavior:c,PriceClass:n.priceClass||"PriceClass_100",ViewerCertificate:{}};if(s.length>0)l.CacheBehaviors=s;if(n.customDomain)l.Aliases=[n.customDomain.domain],l.ViewerCertificate={AcmCertificateArn:n.customDomain.certificateArn,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};else l.ViewerCertificate={CloudFrontDefaultCertificate:!0};if(n.errorPages)l.CustomErrorResponses=Object.entries(n.errorPages).map(([u,h])=>({ErrorCode:Number.parseInt(u),ResponseCode:200,ResponsePagePath:h,ErrorCachingMinTTL:300}));if(l.DefaultRootObject="index.html",l.Comment=e.sub("${AWS::StackName} CloudFront Distribution"),a.addResource("CloudFrontDistribution","AWS::CloudFront::Distribution",{DistributionConfig:l},{dependsOn:"CloudFrontOriginAccessIdentity"}),!n.origins||n.origins.length===0)a.addResource("StaticBucketPolicyForCloudFront","AWS::S3::BucketPolicy",{Bucket:e.ref("StaticBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowCloudFrontAccess",Effect:"Allow",Principal:{CanonicalUser:e.getAtt("CloudFrontOriginAccessIdentity","S3CanonicalUserId")},Action:"s3:GetObject",Resource:e.join("",[e.getAtt("StaticBucket","Arn"),"/*"])}]}},{dependsOn:["StaticBucket","CloudFrontOriginAccessIdentity"]});if(n.customDomain)a.addResource("CloudFrontDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:e.sub(`${Gr(n.customDomain.domain)}.`),Name:n.customDomain.domain,Type:"A",AliasTarget:{HostedZoneId:"Z2FDTNDATAQYW2",DNSName:e.getAtt("CloudFrontDistribution","DomainName"),EvaluateTargetHealth:!1}},{dependsOn:"CloudFrontDistribution"});if(a.addOutputs({CloudFrontDistributionId:{Description:"CloudFront distribution ID",Value:e.ref("CloudFrontDistribution"),Export:{Name:e.sub("${AWS::StackName}-cloudfront-id")}},CloudFrontDomainName:{Description:"CloudFront distribution domain name",Value:e.getAtt("CloudFrontDistribution","DomainName"),Export:{Name:e.sub("${AWS::StackName}-cloudfront-domain")}}}),n.customDomain)a.addOutputs({CloudFrontURL:{Description:"CloudFront custom domain URL",Value:e.sub(`https://${n.customDomain.domain}`)}})}function Gr(a){let n=a.split(".");if(n.length>=2)return n.slice(-2).join(".");return a}function Ur(a,n){if(n.server)Fr(a,n.server);if(n.fargate)oa(a,"app",n.fargate);if(n.services)n.services.forEach((i)=>{if(i.type==="fargate")oa(a,i.name,{taskDefinition:i.taskDefinition,service:i.service})})}function Fr(a,n){if(!n)return;a.addResource("AppSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for application instances",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:3000,ToPort:3000,SourceSecurityGroupId:e.ref("ALBSecurityGroup")},{IpProtocol:"tcp",FromPort:22,ToPort:22,CidrIp:"0.0.0.0/0"}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-app-sg")}]},{dependsOn:"VPC"}),a.addResource("EC2InstanceRole","AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ec2.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore","arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-ec2-role")}]}),a.addResource("EC2InstanceProfile","AWS::IAM::InstanceProfile",{Roles:[e.ref("EC2InstanceRole")]},{dependsOn:"EC2InstanceRole"});let i=n.userData||`#!/bin/bash
|
|
2469
2469
|
set -e
|
|
2470
2470
|
# Update system
|
|
2471
2471
|
yum update -y || apt-get update -y
|
|
@@ -2483,31 +2483,31 @@ rpm -U ./amazon-cloudwatch-agent.rpm || true
|
|
|
2483
2483
|
`;if(a.addResource("LaunchTemplate","AWS::EC2::LaunchTemplate",{LaunchTemplateName:e.sub("${AWS::StackName}-template"),LaunchTemplateData:{ImageId:n.ami||e.findInMap("RegionMap",e.ref("AWS::Region"),"AMI"),InstanceType:n.instanceType,IamInstanceProfile:{Arn:e.getAtt("EC2InstanceProfile","Arn")},SecurityGroupIds:[e.ref("AppSecurityGroup")],UserData:e.base64(e.sub(i)),TagSpecifications:[{ResourceType:"instance",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-instance")}]}],MetadataOptions:{HttpTokens:"required",HttpPutResponseHopLimit:1}}},{dependsOn:["AppSecurityGroup","EC2InstanceProfile"]}),n.loadBalancer){Vr(a,n.loadBalancer);let s={LaunchTemplate:{LaunchTemplateId:e.ref("LaunchTemplate"),Version:e.getAtt("LaunchTemplate","LatestVersionNumber")},MinSize:n.autoScaling?.min.toString()||"1",MaxSize:n.autoScaling?.max.toString()||"3",DesiredCapacity:n.autoScaling?.min.toString()||"2",VPCZoneIdentifier:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],TargetGroupARNs:[e.ref("TargetGroup")],HealthCheckType:"ELB",HealthCheckGracePeriod:300,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-asg"),PropagateAtLaunch:!0}]};if(a.addResource("AutoScalingGroup","AWS::AutoScaling::AutoScalingGroup",s,{dependsOn:["LaunchTemplate","TargetGroup"]}),n.autoScaling)a.addResource("ScaleUpPolicy","AWS::AutoScaling::ScalingPolicy",{AdjustmentType:"ChangeInCapacity",AutoScalingGroupName:e.ref("AutoScalingGroup"),Cooldown:n.autoScaling.scaleUpCooldown?.toString()||"300",ScalingAdjustment:"1"},{dependsOn:"AutoScalingGroup"}),a.addResource("ScaleDownPolicy","AWS::AutoScaling::ScalingPolicy",{AdjustmentType:"ChangeInCapacity",AutoScalingGroupName:e.ref("AutoScalingGroup"),Cooldown:n.autoScaling.scaleDownCooldown?.toString()||"300",ScalingAdjustment:"-1"},{dependsOn:"AutoScalingGroup"}),a.addResource("HighCPUAlarm","AWS::CloudWatch::Alarm",{AlarmDescription:"Scale up when CPU exceeds target",MetricName:"CPUUtilization",Namespace:"AWS/EC2",Statistic:"Average",Period:"300",EvaluationPeriods:"2",Threshold:(n.autoScaling.targetCPU||70).toString(),AlarmActions:[e.ref("ScaleUpPolicy")],Dimensions:[{Name:"AutoScalingGroupName",Value:e.ref("AutoScalingGroup")}],ComparisonOperator:"GreaterThanThreshold"},{dependsOn:["AutoScalingGroup","ScaleUpPolicy"]}),a.addResource("LowCPUAlarm","AWS::CloudWatch::Alarm",{AlarmDescription:"Scale down when CPU is below threshold",MetricName:"CPUUtilization",Namespace:"AWS/EC2",Statistic:"Average",Period:"300",EvaluationPeriods:"2",Threshold:((n.autoScaling.targetCPU||70)-20).toString(),AlarmActions:[e.ref("ScaleDownPolicy")],Dimensions:[{Name:"AutoScalingGroupName",Value:e.ref("AutoScalingGroup")}],ComparisonOperator:"LessThanThreshold"},{dependsOn:["AutoScalingGroup","ScaleDownPolicy"]})}}function Vr(a,n){if(!n)return;a.addResource("ALBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for Application Load Balancer",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:80,ToPort:80,CidrIp:"0.0.0.0/0"},{IpProtocol:"tcp",FromPort:443,ToPort:443,CidrIp:"0.0.0.0/0"}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-alb-sg")}]},{dependsOn:"VPC"}),a.addResource("LoadBalancer","AWS::ElasticLoadBalancingV2::LoadBalancer",{Name:e.sub("${AWS::StackName}-alb"),Type:n.type||"application",Scheme:"internet-facing",IpAddressType:"ipv4",Subnets:[e.ref("PublicSubnet1"),e.ref("PublicSubnet2")],SecurityGroups:[e.ref("ALBSecurityGroup")],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-alb")}]},{dependsOn:["PublicSubnet1","PublicSubnet2","ALBSecurityGroup"]}),a.addResource("TargetGroup","AWS::ElasticLoadBalancingV2::TargetGroup",{Name:e.sub("${AWS::StackName}-tg"),Port:3000,Protocol:"HTTP",VpcId:e.ref("VPC"),HealthCheckEnabled:!0,HealthCheckPath:n.healthCheck?.path||"/health",HealthCheckProtocol:"HTTP",HealthCheckIntervalSeconds:n.healthCheck?.interval||30,HealthCheckTimeoutSeconds:n.healthCheck?.timeout||5,HealthyThresholdCount:n.healthCheck?.healthyThreshold||2,UnhealthyThresholdCount:n.healthCheck?.unhealthyThreshold||3,TargetType:"instance",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-tg")}]},{dependsOn:"VPC"}),a.addResource("LoadBalancerListener","AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:e.ref("LoadBalancer"),Port:80,Protocol:"HTTP",DefaultActions:[{Type:"forward",TargetGroupArn:e.ref("TargetGroup")}]},{dependsOn:["LoadBalancer","TargetGroup"]}),a.addOutputs({LoadBalancerDNS:{Description:"Load Balancer DNS Name",Value:e.getAtt("LoadBalancer","DNSName"),Export:{Name:e.sub("${AWS::StackName}-alb-dns")}}})}function oa(a,n,i){let s=a.toLogicalId(n),c=i.taskDefinition.containerDefinitions?.[0],l=c?.name||c?.Name||n,u=c?.portMappings?.[0]?.containerPort||c?.PortMappings?.[0]?.ContainerPort||3000,h=(i.taskDefinition.containerDefinitions||[]).flatMap((C)=>(C.secrets||C.Secrets||[]).map((T)=>T.valueFrom||T.ValueFrom)).filter(Boolean);if(!a.hasResource("ECSCluster"))a.addResource("ECSCluster","AWS::ECS::Cluster",{ClusterName:e.sub("${AWS::StackName}-cluster"),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cluster")}]});if(a.addResource(`${s}TaskExecutionRole`,"AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"],...h.length?{Policies:[{PolicyName:"read-task-secrets",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameters"],Resource:h},{Effect:"Allow",Action:"kms:Decrypt",Resource:"*"}]}}]}:{}}),a.addResource(`${s}TaskRole`,"AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"application-services",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes","sqs:SendMessage"],Resource:e.sub("arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:${AWS::StackName}-*")},{Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail"],Resource:"*"}]}}]}),!a.hasResource("ALBSecurityGroup"))a.addResource("ALBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Public ingress for the application load balancer",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:80,ToPort:80,CidrIp:"0.0.0.0/0"},...i.loadBalancer?.customDomain?.certificateArn?[{IpProtocol:"tcp",FromPort:443,ToPort:443,CidrIp:"0.0.0.0/0"}]:[]],SecurityGroupEgress:[{IpProtocol:"tcp",FromPort:u,ToPort:u,CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-alb-sg")}]},{dependsOn:"VPC"});if(!a.hasResource("AppSecurityGroup"))a.addResource("AppSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Only the application load balancer may reach Fargate tasks",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:u,ToPort:u,SourceSecurityGroupId:e.ref("ALBSecurityGroup")}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-app-sg")}]},{dependsOn:["VPC","ALBSecurityGroup"]});let y=(i.taskDefinition.containerDefinitions||[{name:n,image:e.sub(`\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.amazonaws.com/${n}:latest`),portMappings:[{containerPort:3000}]}]).map((C)=>({Name:C.Name||C.name,Image:C.Image||C.image,Essential:C.Essential??C.essential??!0,PortMappings:(C.PortMappings||C.portMappings||[]).map((T)=>({ContainerPort:T.ContainerPort??T.containerPort,Protocol:T.Protocol||T.protocol||"tcp"})),Environment:Array.isArray(C.Environment||C.environment)?(C.Environment||C.environment).map((T)=>({Name:T.Name||T.name,Value:T.Value??T.value})):Object.entries(C.Environment||C.environment||{}).map(([T,v])=>({Name:T,Value:v})),Secrets:(C.Secrets||C.secrets||[]).map((T)=>({Name:T.Name||T.name,ValueFrom:T.ValueFrom||T.valueFrom})),HealthCheck:C.HealthCheck||C.healthCheck,Command:C.Command||C.command,EntryPoint:C.EntryPoint||C.entryPoint,LogConfiguration:C.LogConfiguration||C.logConfiguration||{LogDriver:"awslogs",Options:{"awslogs-group":e.ref(`${s}LogGroup`),"awslogs-region":e.ref("AWS::Region"),"awslogs-stream-prefix":n}}}));a.addResource(`${s}TaskDefinition`,"AWS::ECS::TaskDefinition",{Family:e.sub(`\${AWS::StackName}-${n}`),NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:i.taskDefinition.cpu,Memory:i.taskDefinition.memory,ExecutionRoleArn:e.getAtt(`${s}TaskExecutionRole`,"Arn"),TaskRoleArn:e.getAtt(`${s}TaskRole`,"Arn"),ContainerDefinitions:y},{dependsOn:[`${s}TaskExecutionRole`,`${s}TaskRole`,`${s}LogGroup`]}),a.addResource(`${s}LogGroup`,"AWS::Logs::LogGroup",{LogGroupName:e.sub(`/ecs/\${AWS::StackName}/${n}`),RetentionInDays:14});let f=i.service.healthCheck||{};a.addResource(`${s}TargetGroup`,"AWS::ElasticLoadBalancingV2::TargetGroup",{VpcId:e.ref("VPC"),Port:u,Protocol:"HTTP",TargetType:"ip",HealthCheckEnabled:!0,HealthCheckPath:f.path||"/health",HealthCheckProtocol:"HTTP",HealthCheckIntervalSeconds:f.interval||30,HealthCheckTimeoutSeconds:f.timeout||5,HealthyThresholdCount:f.healthyThreshold||2,UnhealthyThresholdCount:f.unhealthyThreshold||3,Matcher:{HttpCode:"200-399"},TargetGroupAttributes:[{Key:"deregistration_delay.timeout_seconds",Value:"30"}]},{dependsOn:"VPC"}),a.addResource(`${s}LoadBalancer`,"AWS::ElasticLoadBalancingV2::LoadBalancer",{Type:"application",Scheme:"internet-facing",IpAddressType:"ipv4",Subnets:[e.ref("PublicSubnet1"),e.ref("PublicSubnet2")],SecurityGroups:[e.ref("ALBSecurityGroup")],LoadBalancerAttributes:[{Key:"routing.http.drop_invalid_header_fields.enabled",Value:"true"},{Key:"deletion_protection.enabled",Value:String(i.loadBalancer?.deletionProtection===!0)}],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}-alb`)}]},{dependsOn:["PublicSubnet1","PublicSubnet2","ALBSecurityGroup"]});let S=i.loadBalancer?.customDomain?.certificateArn,b=i.loadBalancer?.originVerifyHeader;if(a.addResource(`${s}HttpListener`,"AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:e.ref(`${s}LoadBalancer`),Port:80,Protocol:"HTTP",DefaultActions:S?[{Type:"redirect",RedirectConfig:{Protocol:"HTTPS",Port:"443",StatusCode:"HTTP_301"}}]:b?[{Type:"fixed-response",FixedResponseConfig:{StatusCode:"403",ContentType:"text/plain",MessageBody:"Forbidden"}}]:[{Type:"forward",TargetGroupArn:e.ref(`${s}TargetGroup`)}]},{dependsOn:[`${s}LoadBalancer`,`${s}TargetGroup`]}),S)a.addResource(`${s}HttpsListener`,"AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:e.ref(`${s}LoadBalancer`),Port:443,Protocol:"HTTPS",Certificates:[{CertificateArn:S}],SslPolicy:"ELBSecurityPolicy-TLS13-1-2-2021-06",DefaultActions:b?[{Type:"fixed-response",FixedResponseConfig:{StatusCode:"403",ContentType:"text/plain",MessageBody:"Forbidden"}}]:[{Type:"forward",TargetGroupArn:e.ref(`${s}TargetGroup`)}]},{dependsOn:[`${s}LoadBalancer`,`${s}TargetGroup`]});if(b){let C=S?`${s}HttpsListener`:`${s}HttpListener`;a.addResource(`${s}OriginVerifyRule`,"AWS::ElasticLoadBalancingV2::ListenerRule",{ListenerArn:e.ref(C),Priority:1,Conditions:[{Field:"http-header",HttpHeaderConfig:{HttpHeaderName:b.name,Values:[b.value]}}],Actions:[{Type:"forward",TargetGroupArn:e.ref(`${s}TargetGroup`)}]},{dependsOn:[C,`${s}TargetGroup`]})}if(a.addResource(`${s}Service`,"AWS::ECS::Service",{ServiceName:e.sub(`\${AWS::StackName}-${n}`),Cluster:e.ref("ECSCluster"),TaskDefinition:e.ref(`${s}TaskDefinition`),DesiredCount:i.service.desiredCount,LaunchType:"FARGATE",PlatformVersion:"LATEST",HealthCheckGracePeriodSeconds:60,DeploymentConfiguration:{MinimumHealthyPercent:100,MaximumPercent:200,DeploymentCircuitBreaker:{Enable:!0,Rollback:!0}},LoadBalancers:[{ContainerName:l,ContainerPort:u,TargetGroupArn:e.ref(`${s}TargetGroup`)}],NetworkConfiguration:{AwsvpcConfiguration:{AssignPublicIp:"DISABLED",Subnets:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],SecurityGroups:[e.ref("AppSecurityGroup")]}}},{dependsOn:["ECSCluster",`${s}TaskDefinition`,b?`${s}OriginVerifyRule`:S?`${s}HttpsListener`:`${s}HttpListener`]}),i.service.autoScaling){let C=i.service.autoScaling;a.addResource(`${s}ScalableTarget`,"AWS::ApplicationAutoScaling::ScalableTarget",{MinCapacity:C.min,MaxCapacity:C.max,ResourceId:e.join("/",["service",e.ref("ECSCluster"),e.getAtt(`${s}Service`,"Name")]),RoleARN:e.sub("arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService"),ScalableDimension:"ecs:service:DesiredCount",ServiceNamespace:"ecs"},{dependsOn:`${s}Service`}),a.addResource(`${s}ScalingPolicy`,"AWS::ApplicationAutoScaling::ScalingPolicy",{PolicyType:"TargetTrackingScaling",ScalingTargetId:e.ref(`${s}ScalableTarget`),TargetTrackingScalingPolicyConfiguration:{TargetValue:C.targetCPU||70,PredefinedMetricSpecification:{PredefinedMetricType:"ECSServiceAverageCPUUtilization"},ScaleInCooldown:60,ScaleOutCooldown:30}},{dependsOn:`${s}ScalableTarget`})}a.addOutputs({[`${s}ClusterName`]:{Description:"ECS cluster name",Value:e.ref("ECSCluster")},[`${s}ServiceName`]:{Description:"ECS service name",Value:e.getAtt(`${s}Service`,"Name")},[`${s}LoadBalancerDnsName`]:{Description:"ALB origin hostname",Value:e.getAtt(`${s}LoadBalancer`,"DNSName")},[`${s}LoadBalancerHostedZoneId`]:{Description:"ALB canonical hosted zone ID",Value:e.getAtt(`${s}LoadBalancer`,"CanonicalHostedZoneID")},[`${s}TargetGroupArn`]:{Description:"ECS target group ARN",Value:e.ref(`${s}TargetGroup`)}})}function jr(a,n){if(n.postgres)ca(a,"postgres",n.postgres);if(n.mysql)ca(a,"mysql",n.mysql);if(n.dynamodb?.tables)n.dynamodb.tables.forEach((i)=>{Kr(a,i)})}function ca(a,n,i){if(!i)return;let s=n==="postgres"?"postgres":"mysql",c=a.toLogicalId(`${s}-db`);a.addResource("DBSubnetGroup","AWS::RDS::DBSubnetGroup",{DBSubnetGroupDescription:"Subnet group for RDS instance",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-db-subnet-group")}]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]}),a.addResource("DBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for RDS instance",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:n==="postgres"?5432:3306,ToPort:n==="postgres"?5432:3306,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-db-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});let l=n==="postgres"?`postgres${i.version.split(".")[0]}`:`mysql${i.version.split(".")[0]}.${i.version.split(".")[1]||"0"}`;if(i.parameters&&Object.keys(i.parameters).length>0)a.addResource("DBParameterGroup","AWS::RDS::DBParameterGroup",{Description:`Parameter group for ${s}`,Family:l,Parameters:i.parameters,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-db-params")}]});a.addResource("DBSecret","AWS::SecretsManager::Secret",{Description:"Database credentials",GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"admin"}),GenerateStringKey:"password",PasswordLength:32,ExcludeCharacters:'"@/\\'},Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-db-secret")}]},{deletionPolicy:"Retain",updateReplacePolicy:"Retain"});let u={Engine:s,EngineVersion:i.version,DBInstanceClass:i.instanceClass,AllocatedStorage:i.allocatedStorage.toString(),MaxAllocatedStorage:i.maxAllocatedStorage?.toString(),StorageType:"gp3",StorageEncrypted:!0,MultiAZ:i.multiAZ!==!1,DBSubnetGroupName:e.ref("DBSubnetGroup"),VPCSecurityGroups:[e.ref("DBSecurityGroup")],MasterUsername:e.sub("{{resolve:secretsmanager:${DBSecret}:SecretString:username}}"),MasterUserPassword:e.sub("{{resolve:secretsmanager:${DBSecret}:SecretString:password}}"),BackupRetentionPeriod:i.backupRetentionDays||7,PreferredBackupWindow:i.preferredBackupWindow||"03:00-04:00",PreferredMaintenanceWindow:i.preferredMaintenanceWindow||"sun:04:00-sun:05:00",EnablePerformanceInsights:i.enablePerformanceInsights!==!1,PerformanceInsightsRetentionPeriod:i.performanceInsightsRetention||7,DeletionProtection:i.deletionProtection!==!1,CopyTagsToSnapshot:!0,EnableCloudwatchLogsExports:n==="postgres"?["postgresql"]:["error","general","slowquery"],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${s}-db`)}]};if(i.parameters&&Object.keys(i.parameters).length>0)u.DBParameterGroupName=e.ref("DBParameterGroup");a.addResource(c,"AWS::RDS::DBInstance",u,{dependsOn:["DBSubnetGroup","DBSecurityGroup","DBSecret"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),a.addResource("DBSecretAttachment","AWS::SecretsManager::SecretTargetAttachment",{SecretId:e.ref("DBSecret"),TargetId:e.ref(c),TargetType:"AWS::RDS::DBInstance"},{dependsOn:[c,"DBSecret"]}),a.addOutputs({DBEndpoint:{Description:"Database endpoint",Value:e.getAtt(c,"Endpoint.Address"),Export:{Name:e.sub("${AWS::StackName}-db-endpoint")}},DBPort:{Description:"Database port",Value:e.getAtt(c,"Endpoint.Port"),Export:{Name:e.sub("${AWS::StackName}-db-port")}},DBSecretArn:{Description:"ARN of the database credentials secret",Value:e.ref("DBSecret"),Export:{Name:e.sub("${AWS::StackName}-db-secret-arn")}}})}function Kr(a,n){let i=a.toLogicalId(`${n.name}-table`),s={TableName:e.sub(`\${AWS::StackName}-${n.name}`),BillingMode:n.billingMode||"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:n.partitionKey,AttributeType:"S"}],KeySchema:[{AttributeName:n.partitionKey,KeyType:"HASH"}],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n.name}`)}]};if(n.sortKey)s.AttributeDefinitions.push({AttributeName:n.sortKey,AttributeType:"S"}),s.KeySchema.push({AttributeName:n.sortKey,KeyType:"RANGE"});if(n.billingMode==="PROVISIONED")s.ProvisionedThroughput={ReadCapacityUnits:n.readCapacity||5,WriteCapacityUnits:n.writeCapacity||5};if(n.streamEnabled)s.StreamSpecification={StreamViewType:"NEW_AND_OLD_IMAGES"};if(n.pointInTimeRecovery)s.PointInTimeRecoverySpecification={PointInTimeRecoveryEnabled:!0};if(n.ttl?.enabled)s.TimeToLiveSpecification={Enabled:!0,AttributeName:n.ttl.attributeName};if(n.globalSecondaryIndexes&&n.globalSecondaryIndexes.length>0)s.GlobalSecondaryIndexes=n.globalSecondaryIndexes.map((c)=>{let l=new Set(s.AttributeDefinitions.map((h)=>h.AttributeName));if(!l.has(c.partitionKey))s.AttributeDefinitions.push({AttributeName:c.partitionKey,AttributeType:"S"});if(c.sortKey&&!l.has(c.sortKey))s.AttributeDefinitions.push({AttributeName:c.sortKey,AttributeType:"S"});let u={IndexName:c.name,KeySchema:[{AttributeName:c.partitionKey,KeyType:"HASH"}],Projection:{ProjectionType:c.projectionType||"ALL"}};if(c.sortKey)u.KeySchema.push({AttributeName:c.sortKey,KeyType:"RANGE"});if(c.projectionType==="INCLUDE"&&c.nonKeyAttributes)u.Projection.NonKeyAttributes=c.nonKeyAttributes;if(n.billingMode==="PROVISIONED")u.ProvisionedThroughput={ReadCapacityUnits:n.readCapacity||5,WriteCapacityUnits:n.writeCapacity||5};return u});if(a.addResource(i,"AWS::DynamoDB::Table",s,{deletionPolicy:"Retain"}),a.addOutputs({[`${i}Name`]:{Description:`${n.name} table name`,Value:e.ref(i),Export:{Name:e.sub(`\${AWS::StackName}-${n.name}-table`)}},[`${i}Arn`]:{Description:`${n.name} table ARN`,Value:e.getAtt(i,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${n.name}-table-arn`)}}}),n.streamEnabled)a.addOutputs({[`${i}StreamArn`]:{Description:`${n.name} stream ARN`,Value:e.getAtt(i,"StreamArn"),Export:{Name:e.sub(`\${AWS::StackName}-${n.name}-stream-arn`)}}})}function Hr(a,n){for(let[i,s]of Object.entries(n))s.forEach((c)=>{qr(a,c,i)})}function qr(a,n,i){let s=a.toLogicalId(`${i}-${n.name}-function`),c=`${s}Role`;a.addResource(c,"AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole","arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"],Policies:[{PolicyName:"LambdaExecutionPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[...Qr(n.events||[])]}}],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n.name}-role`)}]});let l={FunctionName:e.sub(`\${AWS::StackName}-${n.name}`),Runtime:n.runtime,Handler:n.handler,Role:e.getAtt(c,"Arn"),MemorySize:n.memory,Timeout:n.timeout,Code:{ZipFile:`exports.handler = async (event) => {
|
|
2484
2484
|
console.log('Event:', JSON.stringify(event, null, 2));
|
|
2485
2485
|
return { statusCode: 200, body: 'Function not yet implemented' };
|
|
2486
|
-
};`},Environment:n.environment?{Variables:n.environment}:void 0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n.name}`)}]};if(i!=="edge")l.VpcConfig={SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],SecurityGroupIds:[e.ref("AppSecurityGroup")]};if(a.addResource(s,"AWS::Lambda::Function",l,{dependsOn:c}),a.addResource(`${s}LogGroup`,"AWS::Logs::LogGroup",{LogGroupName:e.sub(`/aws/lambda/\${AWS::StackName}-${n.name}`),RetentionInDays:14}),n.events)n.events.forEach((u,h)=>{zr(a,s,u,h)});a.addOutputs({[`${s}Arn`]:{Description:`${n.name} function ARN`,Value:e.getAtt(s,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${n.name}-function-arn`)}}})}function zr(a,n,i,s){let c=`${n}EventSource${s}`;switch(i.type){case"http":break;case"s3":if(i.bucket){let l=a.toLogicalId(`${i.bucket}-bucket`);a.addResource(`${c}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(n),Action:"lambda:InvokeFunction",Principal:"s3.amazonaws.com",SourceArn:
|
|
2486
|
+
};`},Environment:n.environment?{Variables:n.environment}:void 0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n.name}`)}]};if(i!=="edge")l.VpcConfig={SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],SecurityGroupIds:[e.ref("AppSecurityGroup")]};if(a.addResource(s,"AWS::Lambda::Function",l,{dependsOn:c}),a.addResource(`${s}LogGroup`,"AWS::Logs::LogGroup",{LogGroupName:e.sub(`/aws/lambda/\${AWS::StackName}-${n.name}`),RetentionInDays:14}),n.events)n.events.forEach((u,h)=>{zr(a,s,u,h)});a.addOutputs({[`${s}Arn`]:{Description:`${n.name} function ARN`,Value:e.getAtt(s,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${n.name}-function-arn`)}}})}function zr(a,n,i,s){let c=`${n}EventSource${s}`;switch(i.type){case"http":break;case"s3":if(i.bucket){let l=a.toLogicalId(`${i.bucket}-bucket`);a.addResource(`${c}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(n),Action:"lambda:InvokeFunction",Principal:"s3.amazonaws.com",SourceArn:Vs.s3Bucket(e.ref(l))},{dependsOn:[n,l]})}break;case"sqs":if(i.queueName){let l=a.toLogicalId(`${i.queueName}-queue`);a.addResource(c,"AWS::Lambda::EventSourceMapping",{EventSourceArn:e.getAtt(l,"Arn"),FunctionName:e.ref(n),BatchSize:i.batchSize||10},{dependsOn:[n,l]})}break;case"kinesis":if(i.streamName){let l=a.toLogicalId(`${i.streamName}-stream`);a.addResource(c,"AWS::Lambda::EventSourceMapping",{EventSourceArn:e.getAtt(l,"Arn"),FunctionName:e.ref(n),BatchSize:i.batchSize||100,StartingPosition:i.startingPosition||"LATEST",ParallelizationFactor:i.parallelizationFactor||1},{dependsOn:[n,l]})}break;case"dynamodb-stream":if(i.tableName){let l=a.toLogicalId(`${i.tableName}-table`);a.addResource(c,"AWS::Lambda::EventSourceMapping",{EventSourceArn:e.getAtt(l,"StreamArn"),FunctionName:e.ref(n),BatchSize:i.batchSize||100,StartingPosition:i.startingPosition||"LATEST"},{dependsOn:[n,l]})}break;case"schedule":if(i.expression)a.addResource(`${c}Rule`,"AWS::Events::Rule",{ScheduleExpression:i.expression,State:"ENABLED",Targets:[{Arn:e.getAtt(n,"Arn"),Id:`${n}Target`}]},{dependsOn:n}),a.addResource(`${c}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(n),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.getAtt(`${c}Rule`,"Arn")},{dependsOn:[n,`${c}Rule`]});break}}function Qr(a){let n=[];if(!a)return n;if(a.forEach((i)=>{switch(i.type){case"s3":n.push({Effect:"Allow",Action:["s3:GetObject","s3:GetObjectVersion"],Resource:i.bucket?`arn:aws:s3:::${i.bucket}/*`:"arn:aws:s3:::*/*"});break;case"sqs":n.push({Effect:"Allow",Action:["sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes"],Resource:i.queueName?Vs.sqs(i.queueName):"arn:aws:sqs:*:*:*"});break;case"kinesis":n.push({Effect:"Allow",Action:["kinesis:GetRecords","kinesis:GetShardIterator","kinesis:DescribeStream","kinesis:ListStreams"],Resource:i.streamName?Vs.kinesis(i.streamName):"arn:aws:kinesis:*:*:stream/*"});break;case"dynamodb-stream":n.push({Effect:"Allow",Action:["dynamodb:GetRecords","dynamodb:GetShardIterator","dynamodb:DescribeStream","dynamodb:ListStreams"],Resource:i.tableName?e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${i.tableName}/stream/*`):"arn:aws:dynamodb:*:*:table/*/stream/*"});break}}),n.length===0)n.push({Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:"arn:aws:logs:*:*:*"});return n}function Jr(a,n){if(n.topics)n.topics.forEach((i)=>{Yr(a,i)})}function Yr(a,n){let i=a.toLogicalId(`${n.name}-topic`);if(a.addResource(i,"AWS::SNS::Topic",{TopicName:e.sub(`\${AWS::StackName}-${n.name}`),DisplayName:n.displayName||n.name,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n.name}`)}]}),a.addResource(`${i}Policy`,"AWS::SNS::TopicPolicy",{Topics:[e.ref(i)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["events.amazonaws.com","cloudwatch.amazonaws.com","s3.amazonaws.com"]},Action:"sns:Publish",Resource:e.ref(i)},{Effect:"Allow",Principal:{AWS:e.sub("arn:aws:iam::${AWS::AccountId}:root")},Action:["sns:Subscribe","sns:Publish","sns:Receive"],Resource:e.ref(i)}]}},{dependsOn:i}),n.subscriptions)n.subscriptions.forEach((s,c)=>{let l=`${i}Subscription${c+1}`,u={Protocol:s.protocol,TopicArn:e.ref(i),Endpoint:s.endpoint};if(s.filterPolicy)u.FilterPolicy=s.filterPolicy;if(s.protocol==="sqs"){let h=a.toLogicalId(`${s.endpoint}-queue`);u.Endpoint=e.getAtt(h,"Arn")}if(s.protocol==="lambda"){let h=a.toLogicalId(s.endpoint);u.Endpoint=e.getAtt(h,"Arn"),a.addResource(`${l}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(h),Action:"lambda:InvokeFunction",Principal:"sns.amazonaws.com",SourceArn:e.ref(i)},{dependsOn:[h,i]})}a.addResource(l,"AWS::SNS::Subscription",u,{dependsOn:i})});a.addOutputs({[`${i}Arn`]:{Description:`${n.name} topic ARN`,Value:e.ref(i),Export:{Name:e.sub(`\${AWS::StackName}-${n.name}-topic-arn`)}}})}function Zr(a,n){if(n.alarms&&n.alarms.length>0)a.addResource("AlarmTopic","AWS::SNS::Topic",{TopicName:e.sub("${AWS::StackName}-alarms"),DisplayName:"CloudWatch Alarms",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-alarms")}]}),n.alarms.forEach((i,s)=>{Xr(a,i,s)});if(n.dashboard)en(a,n.dashboard);if(n.logs?.groups)n.logs.groups.forEach((i)=>{tn(a,i,n.logs?.retention)})}function Xr(a,n,i){let s=a.toLogicalId(`alarm-${n.name||n.metric}-${i}`),c={AlarmName:n.name||e.sub(`\${AWS::StackName}-${n.metric}`),AlarmDescription:`Alarm for ${n.metric}`,MetricName:n.metric,Namespace:n.namespace||Lt(n.metric,n.service),Statistic:n.statistic||"Average",Period:n.period||300,EvaluationPeriods:n.evaluationPeriods||1,Threshold:n.threshold,ComparisonOperator:n.comparisonOperator||"GreaterThanThreshold",TreatMissingData:n.treatMissingData||"notBreaching",AlarmActions:[e.ref("AlarmTopic")],OKActions:[e.ref("AlarmTopic")]};if(n.dimensions)c.Dimensions=Object.entries(n.dimensions).map(([l,u])=>({Name:l,Value:u}));else if(n.service)c.Dimensions=an(n.service);a.addResource(s,"AWS::CloudWatch::Alarm",c,{dependsOn:"AlarmTopic"})}function en(a,n){if(!n)return;let i=[],s=0,c=0;n.widgets?.forEach((l)=>{let u=l.width||12,h=l.height||6;if(l.type==="metric"&&l.metrics){let y=l.metrics.map((f)=>{if(typeof f==="string")return[Lt(f),f];else return[Lt(f.metric,f.service),f.metric]});i.push({type:"metric",x:s,y:c,width:u,height:h,properties:{metrics:y,period:300,stat:"Average",region:e.ref("AWS::Region"),title:l.metrics.length>1?"Multiple Metrics":typeof l.metrics[0]==="string"?l.metrics[0]:l.metrics[0].metric}})}else if(l.type==="log"&&l.logGroup)i.push({type:"log",x:s,y:c,width:u,height:h,properties:{query:`SOURCE '${l.logGroup}'
|
|
2487
2487
|
| fields @timestamp, @message
|
|
2488
2488
|
| sort @timestamp desc
|
|
2489
|
-
| limit 20`,region:e.ref("AWS::Region"),title:`Logs: ${l.logGroup}`}});else if(l.type==="text"&&l.text)i.push({type:"text",x:s,y:c,width:u,height:h,properties:{markdown:l.text}});if(s+=u,s>=24)s=0,c+=h}),a.addResource("CloudWatchDashboard","AWS::CloudWatch::Dashboard",{DashboardName:e.sub(`\${AWS::StackName}-${n.name}`),DashboardBody:JSON.stringify({widgets:i})}),a.addOutputs({DashboardURL:{Description:"CloudWatch Dashboard URL",Value:e.sub("https://console.aws.amazon.com/cloudwatch/home?region=${AWS::Region}#dashboards:name=${CloudWatchDashboard}")}})}function tn(a,n,i){let s=a.toLogicalId(`${n}-log-group`);a.addResource(s,"AWS::Logs::LogGroup",{LogGroupName:e.sub(`/aws/\${AWS::StackName}/${n}`),RetentionInDays:i||14,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}`)}]})}function Lt(a,n){if(n)return{ec2:"AWS/EC2",ecs:"AWS/ECS",lambda:"AWS/Lambda",rds:"AWS/RDS",dynamodb:"AWS/DynamoDB",s3:"AWS/S3",cloudfront:"AWS/CloudFront",alb:"AWS/ApplicationELB",nlb:"AWS/NetworkELB",apigateway:"AWS/ApiGateway",sqs:"AWS/SQS",sns:"AWS/SNS",kinesis:"AWS/Kinesis",elasticache:"AWS/ElastiCache"}[n.toLowerCase()]||"AWS/CloudWatch";let i=a.toLowerCase();if(i.includes("cpu")||i.includes("memory")||i.includes("network"))return"AWS/EC2";if(i.includes("lambda")||i.includes("invocation")||i.includes("duration"))return"AWS/Lambda";if(i.includes("request")||i.includes("latency")||i.includes("target"))return"AWS/ApplicationELB";if(i.includes("database")||i.includes("connection"))return"AWS/RDS";if(i.includes("read")||i.includes("write")||i.includes("consumed"))return"AWS/DynamoDB";return"AWS/CloudWatch"}function an(a){return{ec2:[{Name:"InstanceId",Value:e.ref("EC2Instance")}],ecs:[{Name:"ClusterName",Value:e.ref("ECSCluster")},{Name:"ServiceName",Value:e.getAtt("ECSService","Name")}],lambda:[{Name:"FunctionName",Value:e.ref("LambdaFunction")}],rds:[{Name:"DBInstanceIdentifier",Value:e.ref("Database")}],dynamodb:[{Name:"TableName",Value:e.ref("DynamoDBTable")}],alb:[{Name:"LoadBalancer",Value:e.getAtt("LoadBalancer","LoadBalancerFullName")}],apigateway:[{Name:"ApiName",Value:e.ref("HttpApi")}]}[a.toLowerCase()]||[]}function rn(a,n){if(!n.vpc)return;let{cidr:i="10.0.0.0/16",availabilityZones:s=2,natGateways:c=1,enableDnsHostnames:l=!0,enableDnsSupport:u=!0}=n.vpc;a.addResource("VPC","AWS::EC2::VPC",{CidrBlock:i,EnableDnsHostnames:l,EnableDnsSupport:u,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-vpc")}]}),a.addResource("InternetGateway","AWS::EC2::InternetGateway",{Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-igw")}]}),a.addResource("VPCGatewayAttachment","AWS::EC2::VPCGatewayAttachment",{VpcId:e.ref("VPC"),InternetGatewayId:e.ref("InternetGateway")},{dependsOn:["VPC","InternetGateway"]});let h=[];for(let b=0;b<s;b++){let C=`PublicSubnet${b+1}`;h.push(C),a.addResource(C,"AWS::EC2::Subnet",{VpcId:e.ref("VPC"),CidrBlock:e.select(b,e.cidr(e.getAtt("VPC","CidrBlock"),s*2,8)),AvailabilityZone:e.select(b,e.getAZs()),MapPublicIpOnLaunch:!0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-public-${b+1}`)},{Key:"Type",Value:"public"}]},{dependsOn:"VPC"})}let y=[];for(let b=0;b<s;b++){let C=`PrivateSubnet${b+1}`;y.push(C),a.addResource(C,"AWS::EC2::Subnet",{VpcId:e.ref("VPC"),CidrBlock:e.select(b+s,e.cidr(e.getAtt("VPC","CidrBlock"),s*2,8)),AvailabilityZone:e.select(b,e.getAZs()),MapPublicIpOnLaunch:!1,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-private-${b+1}`)},{Key:"Type",Value:"private"}]},{dependsOn:"VPC"})}let f=[];for(let b=0;b<c;b++){let C=`NatEIP${b+1}`;f.push(C),a.addResource(C,"AWS::EC2::EIP",{Domain:"vpc",Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-nat-eip-${b+1}`)}]},{dependsOn:"VPCGatewayAttachment"})}let S=[];for(let b=0;b<c;b++){let C=`NatGateway${b+1}`;S.push(C);let T=b%s;a.addResource(C,"AWS::EC2::NatGateway",{AllocationId:e.getAtt(f[b],"AllocationId"),SubnetId:e.ref(h[T]),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-nat-${b+1}`)}]},{dependsOn:[f[b],h[T]]})}a.addResource("PublicRouteTable","AWS::EC2::RouteTable",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-public-rt")}]},{dependsOn:"VPC"}),a.addResource("PublicRoute","AWS::EC2::Route",{RouteTableId:e.ref("PublicRouteTable"),DestinationCidrBlock:"0.0.0.0/0",GatewayId:e.ref("InternetGateway")},{dependsOn:["PublicRouteTable","VPCGatewayAttachment"]}),h.forEach((b,C)=>{a.addResource(`PublicSubnetRouteTableAssociation${C+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:e.ref(b),RouteTableId:e.ref("PublicRouteTable")},{dependsOn:[b,"PublicRouteTable"]})}),y.forEach((b,C)=>{let T=`PrivateRouteTable${C+1}`,v=C%c;a.addResource(T,"AWS::EC2::RouteTable",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-private-rt-${C+1}`)}]},{dependsOn:"VPC"}),a.addResource(`PrivateRoute${C+1}`,"AWS::EC2::Route",{RouteTableId:e.ref(T),DestinationCidrBlock:"0.0.0.0/0",NatGatewayId:e.ref(S[v])},{dependsOn:[T,S[v]]}),a.addResource(`PrivateSubnetRouteTableAssociation${C+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:e.ref(b),RouteTableId:e.ref(T)},{dependsOn:[b,T]})}),a.addResource("S3VPCEndpoint","AWS::EC2::VPCEndpoint",{VpcId:e.ref("VPC"),ServiceName:e.sub("com.amazonaws.${AWS::Region}.s3"),VpcEndpointType:"Gateway",RouteTableIds:[e.ref("PublicRouteTable"),...Array.from({length:s},(b,C)=>e.ref(`PrivateRouteTable${C+1}`))]},{dependsOn:"VPC"}),a.addResource("NetworkAcl","AWS::EC2::NetworkAcl",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-nacl")}]},{dependsOn:"VPC"}),a.addResource("NetworkAclEntryInbound","AWS::EC2::NetworkAclEntry",{NetworkAclId:e.ref("NetworkAcl"),RuleNumber:100,Protocol:-1,RuleAction:"allow",CidrBlock:"0.0.0.0/0"},{dependsOn:"NetworkAcl"}),a.addResource("NetworkAclEntryOutbound","AWS::EC2::NetworkAclEntry",{NetworkAclId:e.ref("NetworkAcl"),RuleNumber:100,Protocol:-1,Egress:!0,RuleAction:"allow",CidrBlock:"0.0.0.0/0"},{dependsOn:"NetworkAcl"}),a.addOutputs({VPCId:{Description:"VPC ID",Value:e.ref("VPC"),Export:{Name:e.sub("${AWS::StackName}-VPC")}},PublicSubnets:{Description:"Public subnet IDs",Value:e.join(",",h.map((b)=>e.ref(b))),Export:{Name:e.sub("${AWS::StackName}-PublicSubnets")}},PrivateSubnets:{Description:"Private subnet IDs",Value:e.join(",",y.map((b)=>e.ref(b))),Export:{Name:e.sub("${AWS::StackName}-PrivateSubnets")}}})}function nn(a,n){for(let[i,s]of Object.entries(n))sn(a,i,s)}function sn(a,n,i){let s=a.toLogicalId(`${n}-queue`),c=i.fifo||!1,l;if(i.deadLetterQueue){let h=`${s}DLQ`;a.addResource(h,"AWS::SQS::Queue",{QueueName:c?e.sub(`\${AWS::StackName}-${n}-dlq.fifo`):e.sub(`\${AWS::StackName}-${n}-dlq`),FifoQueue:c,MessageRetentionPeriod:1209600,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}-dlq`)}]},{deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),l=e.getAtt(h,"Arn")}let u={QueueName:c?e.sub(`\${AWS::StackName}-${n}.fifo`):e.sub(`\${AWS::StackName}-${n}`),FifoQueue:c,VisibilityTimeout:i.visibilityTimeout||30,MessageRetentionPeriod:i.messageRetentionPeriod||345600,ReceiveMessageWaitTimeSeconds:i.receiveMessageWaitTime||0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}`)}]};if(c&&i.contentBasedDeduplication)u.ContentBasedDeduplication=!0;if(i.deadLetterQueue&&l)u.RedrivePolicy={deadLetterTargetArn:l,maxReceiveCount:i.maxReceiveCount||3};if(a.addResource(s,"AWS::SQS::Queue",u,{dependsOn:i.deadLetterQueue?`${s}DLQ`:void 0,deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),a.addResource(`${s}Policy`,"AWS::SQS::QueuePolicy",{Queues:[e.ref(s)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["lambda.amazonaws.com","events.amazonaws.com","sns.amazonaws.com"]},Action:"sqs:SendMessage",Resource:e.getAtt(s,"Arn"),Condition:{ArnEquals:{"aws:SourceArn":e.sub("arn:aws:*:${AWS::Region}:${AWS::AccountId}:*")}}}]}},{dependsOn:s}),a.addOutputs({[`${s}Url`]:{Description:`${n} queue URL`,Value:e.ref(s),Export:{Name:e.sub(`\${AWS::StackName}-${n}-queue-url`)}},[`${s}Arn`]:{Description:`${n} queue ARN`,Value:e.getAtt(s,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${n}-queue-arn`)}}}),i.deadLetterQueue)a.addOutputs({[`${s}DLQUrl`]:{Description:`${n} dead letter queue URL`,Value:e.ref(`${s}DLQ`),Export:{Name:e.sub(`\${AWS::StackName}-${n}-dlq-url`)}}})}function on(a,n){if(n.certificate)cn(a,n.certificate);if(n.waf?.enabled)ln(a,n.waf);if(n.securityGroups)for(let[i,s]of Object.entries(n.securityGroups))un(a,i,s)}function cn(a,n){if(!n)return;let i=[n.domain];if(n.subdomains)i.push(...n.subdomains);a.addResource("Certificate","AWS::CertificateManager::Certificate",{DomainName:n.domain,SubjectAlternativeNames:n.subdomains,ValidationMethod:n.validationMethod||"DNS",DomainValidationOptions:i.map((s)=>({DomainName:s,HostedZoneId:e.ref("HostedZone")})),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-certificate")}]}),a.addOutputs({CertificateArn:{Description:"ACM Certificate ARN",Value:e.ref("Certificate"),Export:{Name:e.sub("${AWS::StackName}-certificate-arn")}}})}function ln(a,n){if(!n)return;let i=[],s=n.rules||["rateLimit","sqlInjection","xss"];if(s.includes("rateLimit"))i.push({Name:"RateLimitRule",Priority:1,Statement:{RateBasedStatement:{Limit:n.rateLimit||2000,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"RateLimitRule"}});let c=i.length+1;if(s.includes("sqlInjection"))i.push({Name:"AWSManagedRulesSQLi",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesSQLiRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesSQLi"}});if(s.includes("xss"))i.push({Name:"AWSManagedRulesXSS",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesXSS"}});if(s.includes("knownBadInputs"))i.push({Name:"AWSManagedRulesKnownBadInputs",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesKnownBadInputs"}});if(s.includes("coreRuleSet"))i.push({Name:"AWSManagedRulesCoreRuleSet",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesCommonRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesCoreRuleSet"}});if(s.includes("linuxRuleSet"))i.push({Name:"AWSManagedRulesLinuxRuleSet",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesLinuxRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesLinuxRuleSet"}});if(s.includes("apiProtection"))i.push({Name:"AWSManagedRulesAPIProtection",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesAmazonIpReputationList"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesAPIProtection"}});if(s.includes("geoBlock"))i.push({Name:"GeoBlockRule",Priority:c++,Statement:{GeoMatchStatement:{CountryCodes:["CN","RU"]}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"GeoBlockRule"}});if(s.includes("connectionLimit"))i.push({Name:"ConnectionLimitRule",Priority:c++,Statement:{RateBasedStatement:{Limit:100,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"ConnectionLimitRule"}});if(a.addResource("WebACL","AWS::WAFv2::WebACL",{Name:e.sub("${AWS::StackName}-waf"),Scope:n.scope||"REGIONAL",DefaultAction:{Allow:{}},Rules:i,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:e.sub("${AWS::StackName}-waf")},Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-waf")}]}),a.hasResource("LoadBalancer"))a.addResource("WebACLAssociation","AWS::WAFv2::WebACLAssociation",{ResourceArn:e.ref("LoadBalancer"),WebACLArn:e.getAtt("WebACL","Arn")},{dependsOn:["WebACL","LoadBalancer"]});a.addOutputs({WebACLId:{Description:"WAF Web ACL ID",Value:e.ref("WebACL"),Export:{Name:e.sub("${AWS::StackName}-waf-id")}},WebACLArn:{Description:"WAF Web ACL ARN",Value:e.getAtt("WebACL","Arn"),Export:{Name:e.sub("${AWS::StackName}-waf-arn")}}})}function un(a,n,i){if(!i)return;let s=a.toLogicalId(`${n}-security-group`),c=i.ingress?.map((u)=>({IpProtocol:u.protocol,FromPort:u.port,ToPort:u.port,CidrIp:u.cidr,SourceSecurityGroupId:u.source?e.ref(u.source):void 0}))||[],l=i.egress?.map((u)=>({IpProtocol:u.protocol,FromPort:u.port,ToPort:u.port,CidrIp:u.cidr||"0.0.0.0/0"}))||[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}];a.addResource(s,"AWS::EC2::SecurityGroup",{GroupDescription:`Security group for ${n}`,VpcId:e.ref("VPC"),SecurityGroupIngress:c,SecurityGroupEgress:l,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}-sg`)}]},{dependsOn:"VPC"}),a.addOutputs({[`${s}Id`]:{Description:`${n} security group ID`,Value:e.ref(s),Export:{Name:e.sub(`\${AWS::StackName}-${n}-sg-id`)}}})}function dn(a,n){for(let[i,s]of Object.entries(n)){if(s.type==="efs"){pn(a,i,s);continue}mn(a,i,s)}}function mn(a,n,i){let s=a.toLogicalId(`${n}-bucket`),c={BucketName:e.sub(`\${AWS::StackName}-${n}`),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}`)}]};if(i.versioning)c.VersioningConfiguration={Status:"Enabled"};if(i.encryption)c.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(!i.public)c.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(i.website)c.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"index.html"};if(i.cors&&i.cors.length>0)c.CorsConfiguration={CorsRules:i.cors.map((l)=>({AllowedOrigins:l.allowedOrigins,AllowedMethods:l.allowedMethods,AllowedHeaders:l.allowedHeaders||["*"],MaxAge:l.maxAge||3600}))};if(i.lifecycleRules&&i.lifecycleRules.length>0)c.LifecycleConfiguration={Rules:i.lifecycleRules.map((l)=>({Id:l.id,Status:l.enabled?"Enabled":"Disabled",ExpirationInDays:l.expirationDays,Transitions:l.transitions?.map((u)=>({TransitionInDays:u.days,StorageClass:u.storageClass}))}))};if(i.intelligentTiering)c.IntelligentTieringConfigurations=[{Id:"EntireBucket",Status:"Enabled",Tierings:[{AccessTier:"ARCHIVE_ACCESS",Days:90},{AccessTier:"DEEP_ARCHIVE_ACCESS",Days:180}]}];if(a.addResource(s,"AWS::S3::Bucket",c,{deletionPolicy:i.versioning?"Retain":"Delete"}),i.public)a.addResource(`${s}Policy`,"AWS::S3::BucketPolicy",{Bucket:e.ref(s),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:"s3:GetObject",Resource:e.join("",[qs.s3Bucket(e.ref(s)),"/*"])}]}},{dependsOn:s});if(a.addOutputs({[`${s}Name`]:{Description:`${n} bucket name`,Value:e.ref(s),Export:{Name:e.sub(`\${AWS::StackName}-${n}-bucket`)}},[`${s}Arn`]:{Description:`${n} bucket ARN`,Value:e.getAtt(s,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${n}-bucket-arn`)}}}),i.website)a.addOutputs({[`${s}WebsiteURL`]:{Description:`${n} website URL`,Value:e.getAtt(s,"WebsiteURL")}})}function pn(a,n,i){let s=a.toLogicalId(`${n}-efs`),c={Encrypted:i.encryption!==!1,PerformanceMode:i.performanceMode||"generalPurpose",ThroughputMode:i.throughputMode||"bursting",FileSystemTags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}`)}]};if(i.lifecyclePolicy){if(c.LifecyclePolicies=[],i.lifecyclePolicy.transitionToIA)c.LifecyclePolicies.push({TransitionToIA:`AFTER_${i.lifecyclePolicy.transitionToIA}_DAYS`});if(i.lifecyclePolicy.transitionToPrimaryStorageClass)c.LifecyclePolicies.push({TransitionToPrimaryStorageClass:"AFTER_1_ACCESS"})}a.addResource(s,"AWS::EFS::FileSystem",c,{deletionPolicy:"Retain"});let l=2;for(let u=0;u<l;u++)a.addResource(`${s}MountTarget${u+1}`,"AWS::EFS::MountTarget",{FileSystemId:e.ref(s),SubnetId:e.ref(`PrivateSubnet${u+1}`),SecurityGroups:[e.ref("EFSSecurityGroup")]},{dependsOn:[s,`PrivateSubnet${u+1}`]});a.addResource("EFSSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for EFS mount targets",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:2049,ToPort:2049,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-efs-sg")}]},{dependsOn:"VPC"}),a.addOutputs({[`${s}Id`]:{Description:`${n} EFS file system ID`,Value:e.ref(s),Export:{Name:e.sub(`\${AWS::StackName}-${n}-efs`)}}})}class Tp{template;config;resourceDependencies;constructor(a){this.config=a,this.resourceDependencies=new Map,this.template={AWSTemplateFormatVersion:"2010-09-09",Description:`Infrastructure for ${a.project.name} (${a.project.slug})`,Resources:{}}}build(){return this.addParameters(),this.addMappings(),this.addConditions(),this.addResources(),this.initializeOutputs(),this.resolveDependencies(),this.template}addParameters(){this.template.Parameters={Environment:{Type:"String",Default:"production",AllowedValues:["development","staging","production"],Description:"Environment name"}}}addMappings(){this.template.Mappings={RegionMap:{"us-east-1":{AMI:"ami-0f3caa1cf4417e51b"},"us-west-2":{AMI:"ami-0d1cd67c26f5fca19"},"eu-west-1":{AMI:"ami-0bbc25e23a7640b9b"}}}}addConditions(){this.template.Conditions={IsProduction:e.equals(e.ref("Environment"),"production"),HasDomain:e.not([e.equals(this.config.environments?.production?.domain||"","")])}}addResources(){let{infrastructure:a}=this.config;if(!a)return;if(a.network)this.addNetworkResources(a.network);if(a.storage)this.addStorageResources(a.storage);if(a.compute)this.addComputeResources(a.compute);if(a.databases)this.addDatabaseResources(a.databases);if(a.cache)this.addCacheResources(a.cache);if(a.cdn)this.addCDNResources(a.cdn);if(a.apiGateway)this.addApiGatewayResources(a.apiGateway);if(a.functions)this.addFunctionResources(a.functions);if(a.queues)this.addQueueResources(a.queues);if(a.messaging)this.addMessagingResources(a.messaging);if(a.monitoring)this.addMonitoringResources(a.monitoring);if(a.security)this.addSecurityResources(a.security)}initializeOutputs(){let a=this.template.Outputs||{};if(this.template.Outputs={StackName:{Description:"Stack name",Value:e.ref("AWS::StackName"),Export:{Name:e.sub("${AWS::StackName}-Name")}},Region:{Description:"AWS Region",Value:e.ref("AWS::Region"),Export:{Name:e.sub("${AWS::StackName}-Region")}},...a},this.config.environments?.production?.domain)this.template.Outputs.Domain={Description:"Production domain",Value:this.config.environments.production.domain,Condition:"HasDomain"}}addResource(a,n,i,s){let c={Type:n,Properties:i};if(s?.dependsOn)c.DependsOn=s.dependsOn,this.trackDependency(a,s.dependsOn);if(s?.condition)c.Condition=s.condition;if(s?.deletionPolicy)c.DeletionPolicy=s.deletionPolicy;if(s?.updateReplacePolicy)c.UpdateReplacePolicy=s.updateReplacePolicy;this.template.Resources[a]=c}addOutputs(a){this.template.Outputs={...this.template.Outputs,...a}}getOutputs(){return this.template.Outputs||{}}hasResource(a){return a in this.template.Resources}getResource(a){return this.template.Resources[a]}trackDependency(a,n){if(!this.resourceDependencies.has(a))this.resourceDependencies.set(a,new Set);(Array.isArray(n)?n:[n]).forEach((i)=>this.resourceDependencies.get(a).add(i))}resolveDependencies(){let a=new Set,n=new Set,i=(s)=>{if(n.has(s))throw Error(`Circular dependency detected involving resource: ${s}`);if(a.has(s))return!0;a.add(s),n.add(s);let c=this.resourceDependencies.get(s);if(c)for(let l of c)i(l);return n.delete(s),!0};for(let s of this.resourceDependencies.keys())i(s)}toLogicalId(a){return a.split(/[-_\s]/).map((n)=>n.charAt(0).toUpperCase()+n.slice(1).toLowerCase()).join("")}addNetworkResources(a){rn(this,a)}addStorageResources(a){dn(this,a)}addComputeResources(a){Ur(this,a)}addDatabaseResources(a){jr(this,a)}addFunctionResources(a){Hr(this,a)}addCacheResources(a){$r(this,a)}addQueueResources(a){nn(this,a)}addMessagingResources(a){Jr(this,a)}addCDNResources(a){Wr(this,a)}addApiGatewayResources(a){wr(this,a)}addMonitoringResources(a){Zr(this,a)}addSecurityResources(a){on(this,a)}}function sd(a){return new Tp(a).build()}function _y(a){let{name:n,slug:i,domain:s,subdomain:c}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:c&&s?`${c}.${s}`:s}},infrastructure:{storage:{assets:{public:!0,versioning:!1,website:!0,encryption:!1,cors:[{allowedOrigins:["*"],allowedMethods:["GET","HEAD"],allowedHeaders:["*"],maxAge:3600}]}},cdn:{enabled:!0,customDomain:s?{domain:c&&s?`${c}.${s}`:s,certificateArn:"TO_BE_GENERATED"}:void 0,cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0,errorPages:{404:"/index.html",403:"/index.html"}}}}}function Oy(a){let{name:n,slug:i,domain:s,instanceType:c="t3.small",minInstances:l=2,maxInstances:u=10}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:s}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",keyPair:`${i}-key`,autoScaling:{min:l,max:u,desired:l,targetCPU:70},loadBalancer:{type:"application",healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3}},userData:{packages:["nodejs","npm","nginx"],commands:["curl -fsSL https://bun.sh/install | bash","npm install -g pm2"]}}},databases:{postgres:{engine:"postgres",version:"15",instanceClass:"db.t3.micro",allocatedStorage:20,multiAZ:!0,backupRetentionDays:7,deletionProtection:!0}},cache:{redis:{nodeType:"cache.t3.micro",numCacheNodes:1,engine:"redis",engineVersion:"7.0"}},security:{certificate:s?{domain:s,subdomains:[`*.${s}`],validationMethod:"DNS"}:void 0}}}}function Ly(a){let{name:n,slug:i,domain:s,taskCpu:c="256",taskMemory:l="512",desiredCount:u=2}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:s}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:0}},compute:{fargate:{taskDefinition:{cpu:c,memory:l,containerDefinitions:[{name:"app",image:`${i}-app:latest`,portMappings:[{containerPort:3000}],environment:[],secrets:[]}]},service:{desiredCount:u,healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3},autoScaling:{min:u,max:u*5,targetCPU:70,targetMemory:80}},loadBalancer:{type:"application"}}},databases:{dynamodb:{tables:{[`${i}-main`]:{partitionKey:{name:"id",type:"S"},sortKey:{name:"createdAt",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0}}}},functions:{"process-queue":{runtime:"nodejs20.x",handler:"dist/workers/queue.handler",memory:512,timeout:60,events:[{type:"sqs",queueName:`${i}-queue`}]}},security:{certificate:s?{domain:s,subdomains:[`*.${s}`],validationMethod:"DNS"}:void 0}}}}function $y(a){let{name:n,slug:i,entry:s,domain:c,runtime:l="nodejs20.x",memory:u=1024,build:h,deploy:y,assets:f,queues:S=!0,scheduler:b="on",region:C="us-east-1"}=a;return{project:{name:n,slug:i,region:C},mode:"serverless",environments:{production:{type:"production",domain:c,app:{kind:"node",runtime:l,entry:s,memory:u,build:h,deploy:y,assets:f,queues:S,scheduler:b,domain:c}}}}}function od(a){let n=a.database!==!1,i=a.cache!==!1,s=a.queue!==!1;return{project:{name:a.name,slug:a.slug,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:a.domain}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{fargate:{taskDefinition:{cpu:"256",memory:"512",containerDefinitions:[{name:"api",image:a.imageUri,portMappings:[{containerPort:3000}],environment:[{name:"NODE_ENV",value:"production"},{name:"PORT",value:"3000"},{name:"AWS_REGION",value:e.ref("AWS::Region")},...n?[{name:"DB_HOST",value:e.getAtt("PostgresDb","Endpoint.Address")},{name:"DB_PORT",value:e.getAtt("PostgresDb","Endpoint.Port")}]:[],...i?[{name:"REDIS_HOST",value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Address")},{name:"REDIS_PORT",value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Port")},{name:"REDIS_TLS",value:"true"}]:[],...s?[{name:"QUEUE_URL",value:e.ref("JobsQueue")}]:[],{name:"MAIL_TRANSPORT",value:"ses"}],secrets:n?[{name:"DB_USERNAME",valueFrom:e.sub("${DBSecret}:username::")},{name:"DB_PASSWORD",valueFrom:e.sub("${DBSecret}:password::")}]:[]}]},service:{desiredCount:a.desiredCount||1,healthCheck:{path:"/api/health",interval:30,timeout:5},autoScaling:{min:a.desiredCount||1,max:6,targetCPU:70}},loadBalancer:{type:"application",...a.certificateArn?{customDomain:{domain:a.domain,certificateArn:a.certificateArn}}:{},...a.originVerifySecret?{originVerifyHeader:{name:"X-Origin-Verify",value:a.originVerifySecret}}:{}}}},...n?{databases:{postgres:{engine:"postgres",version:"16",instanceClass:"db.t4g.micro",allocatedStorage:20,maxAllocatedStorage:100,multiAZ:!1,backupRetentionDays:7,deletionProtection:!0}}}:{},...i?{cache:{redis:{nodeType:"cache.t4g.micro",numCacheNodes:2,engine:"redis",engineVersion:"7.1",automaticFailoverEnabled:!0,snapshotRetentionLimit:5}}}:{},...s?{queues:{jobs:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0,maxReceiveCount:3,receiveMessageWaitTime:20}}}:{}}}}function My(a){let{name:n,slug:i,domain:s,apiSubdomain:c="api"}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:s}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},storage:{frontend:{public:!0,versioning:!0,website:!0,encryption:!1}},cdn:{enabled:!0,customDomain:{domain:s,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0,errorPages:{404:"/index.html"}},compute:{fargate:{taskDefinition:{cpu:"512",memory:"1024",containerDefinitions:[{name:"api",image:`${i}-api:latest`,portMappings:[{containerPort:3000}]}]},service:{desiredCount:2,healthCheck:{path:"/api/health",interval:30},autoScaling:{min:2,max:10,targetCPU:70}},loadBalancer:{type:"application",customDomain:{domain:`${c}.${s}`,certificateArn:"TO_BE_GENERATED"}}}},databases:{postgres:{engine:"postgres",version:"15",instanceClass:"db.t3.small",allocatedStorage:50,multiAZ:!0,backupRetentionDays:14,deletionProtection:!0}},cache:{redis:{nodeType:"cache.t3.small",numCacheNodes:2,engine:"redis",engineVersion:"7.0"}},queues:{jobs:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0}},security:{certificate:{domain:s,subdomains:[`*.${s}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss"]}}}}}function Fy(a){let{name:n,slug:i,domain:s}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:s}},infrastructure:{apiGateway:{type:"HTTP",cors:{allowOrigins:["*"],allowMethods:["GET","POST","PUT","DELETE","PATCH"],allowHeaders:["Content-Type","Authorization"],maxAge:3600},customDomain:s?{domain:s,certificateArn:"TO_BE_GENERATED"}:void 0,throttling:{rateLimit:1e4,burstLimit:5000},authorizer:{type:"JWT",identitySource:"$request.header.Authorization"}},functions:{users:{runtime:"nodejs20.x",handler:"dist/api/users.handler",memory:512,timeout:30,events:[{type:"http",path:"/users",method:"GET"},{type:"http",path:"/users",method:"POST"}]},products:{runtime:"nodejs20.x",handler:"dist/api/products.handler",memory:512,timeout:30,events:[{type:"http",path:"/products",method:"GET"}]}},databases:{dynamodb:{tables:{[`${i}-users`]:{partitionKey:{name:"userId",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0,globalSecondaryIndexes:[{name:"EmailIndex",partitionKey:{name:"email",type:"S"},projection:"ALL"}]},[`${i}-products`]:{partitionKey:{name:"productId",type:"S"},sortKey:{name:"category",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!1}}}},cache:{elasticache:{nodeType:"cache.t3.micro",numCacheNodes:1,engine:"redis",engineVersion:"7.0"}},security:{certificate:s?{domain:s,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","sqlInjection"]}},monitoring:{alarms:[{metric:"Errors",threshold:10,period:300,evaluationPeriods:1},{metric:"Duration",threshold:3000,period:300,evaluationPeriods:2}]}}}}function Uy(a){let{name:n,slug:i,domain:s,instanceType:c="t3.small"}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:s}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",keyPair:`${i}-key`,autoScaling:{min:2,max:6,desired:2,targetCPU:75},loadBalancer:{type:"application",healthCheck:{path:"/wp-admin/install.php",interval:30}},userData:{packages:["nginx","php8.1-fpm","php8.1-mysql","php8.1-curl","php8.1-gd","php8.1-mbstring","php8.1-xml","php8.1-zip"],commands:["cd /var/www","wget https://wordpress.org/latest.tar.gz","tar -xzf latest.tar.gz","chown -R www-data:www-data wordpress","rm /etc/nginx/sites-enabled/default","systemctl restart nginx","systemctl restart php8.1-fpm"]}}},fileSystem:{uploads:{performanceMode:"generalPurpose",throughputMode:"bursting",encrypted:!0,lifecyclePolicy:{transitionToIA:30},mountPath:"/var/www/wordpress/wp-content/uploads"}},databases:{mysql:{engine:"mysql",version:"8.0",instanceClass:"db.t3.small",allocatedStorage:50,multiAZ:!0,backupRetentionDays:7,deletionProtection:!0,databaseName:"wordpress"}},cache:{redis:{nodeType:"cache.t3.micro",numCacheNodes:1,engine:"redis",engineVersion:"7.0"}},cdn:{enabled:!0,customDomain:{domain:s,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,origins:[{type:"alb",pathPattern:"/wp-content/*"}]},security:{certificate:{domain:s,subdomains:[`www.${s}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss","wordpressRules"]}}}}}function Qy(a){let{name:n,slug:i,domain:s,apiDomain:c}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:s}},infrastructure:{storage:{static:{public:!0,versioning:!0,website:!0,encryption:!1,cors:[{allowedOrigins:["*"],allowedMethods:["GET","HEAD"]}],lifecycleRules:[{id:"DeleteOldVersions",enabled:!0,expirationDays:90}]}},cdn:{enabled:!0,customDomain:{domain:s,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:0,maxTTL:31536000},compress:!0,http3:!0,errorPages:{404:"/404.html",500:"/500.html"},edgeFunctions:[{eventType:"origin-request",functionArn:"TO_BE_CREATED",name:"ssr-handler"}]},functions:{ssr:{runtime:"nodejs20.x",handler:"dist/edge/ssr.handler",memory:512,timeout:5},...c?{api:{runtime:"nodejs20.x",handler:"dist/api/index.handler",memory:1024,timeout:30,events:[{type:"http",path:"/{proxy+}",method:"ANY"}]}}:{}},apiGateway:c?{type:"HTTP",customDomain:{domain:c,certificateArn:"TO_BE_GENERATED"},cors:{allowOrigins:[s],allowMethods:["GET","POST","PUT","DELETE"],allowHeaders:["Content-Type","Authorization"]}}:void 0,databases:{dynamodb:{tables:{content:{partitionKey:{name:"id",type:"S"},sortKey:{name:"type",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!1}}}},security:{certificate:{domain:s,subdomains:c?[c]:[],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","geoBlock"]}}}}}function Hy(a){let{name:n,slug:i,domain:s,services:c}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:s}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:3,natGateways:2}},compute:{services:c.map((l)=>({name:l.name,type:"fargate",taskDefinition:{cpu:l.cpu||"256",memory:l.memory||"512",containerDefinitions:[{name:l.name,image:`${i}-${l.name}:latest`,portMappings:[{containerPort:l.port}],healthCheck:{command:["CMD-SHELL",`curl -f http://localhost:${l.port}/health || exit 1`],interval:30,timeout:5,retries:3}}]},service:{desiredCount:l.desiredCount||2,serviceDiscovery:{enabled:!0,namespace:`${i}.local`},autoScaling:{min:2,max:10,targetCPU:70}}}))},apiGateway:{type:"HTTP",customDomain:{domain:s,certificateArn:"TO_BE_GENERATED"},cors:{allowOrigins:["*"],allowMethods:["GET","POST","PUT","DELETE","PATCH"]},routes:c.map((l)=>({path:`/${l.name}/{proxy+}`,integration:{type:"vpc-link",service:l.name}}))},databases:{dynamodb:{tables:Object.fromEntries(c.map((l)=>[`${i}-${l.name}`,{partitionKey:{name:"id",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0}]))}},queues:{events:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0}},messaging:{topics:{events:{name:`${i}-events`,subscriptions:c.map((l)=>({protocol:"sqs",endpoint:`${i}-${l.name}-queue`,filterPolicy:{service:[l.name]}}))}}},monitoring:{dashboard:{name:`${i}-microservices`,widgets:c.map((l)=>({type:"metric",metrics:[{service:l.name,metric:"CPUUtilization"},{service:l.name,metric:"MemoryUtilization"},{service:l.name,metric:"RequestCount"}]}))},alarms:c.flatMap((l)=>[{name:`${l.name}-high-cpu`,metric:"CPUUtilization",threshold:80,service:l.name},{name:`${l.name}-errors`,metric:"Errors",threshold:10,service:l.name}])},security:{certificate:{domain:s,validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection"]}}}}}function Gy(a){let{name:n,slug:i,domain:s}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:s}},infrastructure:{apiGateway:{type:"websocket",customDomain:s?{domain:s,certificateArn:"TO_BE_GENERATED"}:void 0,routes:[{path:"$connect",method:"WEBSOCKET",integration:"websocket-connect"},{path:"$disconnect",method:"WEBSOCKET",integration:"websocket-disconnect"},{path:"$default",method:"WEBSOCKET",integration:"websocket-default"},{path:"sendMessage",method:"WEBSOCKET",integration:"websocket-send-message"},{path:"joinRoom",method:"WEBSOCKET",integration:"websocket-join-room"}]},functions:{connect:{runtime:"nodejs20.x",handler:"dist/websocket/connect.handler",memory:512,timeout:30},disconnect:{runtime:"nodejs20.x",handler:"dist/websocket/disconnect.handler",memory:512,timeout:30},default:{runtime:"nodejs20.x",handler:"dist/websocket/default.handler",memory:512,timeout:30},"send-message":{runtime:"nodejs20.x",handler:"dist/websocket/sendMessage.handler",memory:512,timeout:30},"join-room":{runtime:"nodejs20.x",handler:"dist/websocket/joinRoom.handler",memory:512,timeout:30},broadcast:{runtime:"nodejs20.x",handler:"dist/streams/broadcast.handler",memory:1024,timeout:60,events:[{type:"dynamodb-stream",tableName:`${i}-messages`,startingPosition:"LATEST",batchSize:100}]}},databases:{dynamodb:{tables:{[`${i}-connections`]:{partitionKey:{name:"connectionId",type:"S"},billingMode:"PAY_PER_REQUEST",globalSecondaryIndexes:[{name:"RoomIndex",partitionKey:{name:"roomId",type:"S"},sortKey:{name:"connectionId",type:"S"},projection:"ALL"}]},[`${i}-messages`]:{partitionKey:{name:"roomId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0,globalSecondaryIndexes:[{name:"UserIndex",partitionKey:{name:"userId",type:"S"},sortKey:{name:"timestamp",type:"S"},projection:"ALL"}]},[`${i}-rooms`]:{partitionKey:{name:"roomId",type:"S"},billingMode:"PAY_PER_REQUEST"}}}},cache:{elasticache:{nodeType:"cache.t3.small",numCacheNodes:2,engine:"redis",engineVersion:"7.0"}},monitoring:{alarms:[{metric:"WebSocketConnections",threshold:1e4,evaluationPeriods:1},{metric:"IntegrationLatency",threshold:1000,evaluationPeriods:2}],dashboard:{name:`${i}-realtime`,widgets:[{type:"metric",metrics:["WebSocketConnections","MessagesSent","IntegrationLatency"]}]}},security:{certificate:s?{domain:s,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","connectionLimit"]}}}}}function qy(a){let{name:n,slug:i,retentionDays:s=7}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",infrastructure:{streaming:{dataStream:{name:`${i}-stream`,shardCount:2,retentionPeriod:s*24,encryption:!0}},storage:{raw:{public:!1,versioning:!0,encryption:!0,intelligentTiering:!0,lifecycleRules:[{id:"ArchiveOldData",enabled:!0,transitions:[{days:30,storageClass:"GLACIER"},{days:90,storageClass:"DEEP_ARCHIVE"}]}]},processed:{public:!1,versioning:!0,encryption:!0,intelligentTiering:!0}},functions:{"stream-processor":{runtime:"nodejs20.x",handler:"dist/processors/stream.handler",memory:2048,timeout:300,events:[{type:"kinesis",streamName:`${i}-stream`,batchSize:1000,startingPosition:"LATEST",parallelizationFactor:10}]},transformer:{runtime:"nodejs20.x",handler:"dist/processors/transform.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${i}-raw`,prefix:"incoming/"}]},aggregator:{runtime:"nodejs20.x",handler:"dist/processors/aggregate.handler",memory:2048,timeout:600,events:[{type:"schedule",expression:"cron(0 * * * ? *)"}]}},analytics:{athena:{database:`${i}_analytics`,workgroup:`${i}-workgroup`,outputBucket:`${i}-query-results`,tables:[{name:"raw_events",location:`s3://${i}-raw/events/`,format:"parquet",partitionKeys:["year","month","day"]},{name:"processed_events",location:`s3://${i}-processed/events/`,format:"parquet",partitionKeys:["year","month","day"]}]},glue:{crawlers:[{name:`${i}-crawler`,databaseName:`${i}_analytics`,s3Targets:[`s3://${i}-raw/`,`s3://${i}-processed/`],schedule:"cron(0 2 * * ? *)"}],jobs:[{name:`${i}-etl-job`,scriptLocation:`s3://${i}-scripts/etl.py`,role:`${i}-glue-role`,maxCapacity:10,timeout:120}]}},databases:{dynamodb:{tables:{[`${i}-metadata`]:{partitionKey:{name:"pipelineId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST"}}}},queues:{failedJobs:{fifo:!1,visibilityTimeout:900,messageRetentionPeriod:1209600,deadLetterQueue:!0,maxReceiveCount:3}},workflow:{pipelines:[{name:`${i}-daily-pipeline`,type:"stepFunctions",definition:{StartAt:"ExtractData",States:{ExtractData:{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Next:"TransformData"},TransformData:{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Next:"LoadData"},LoadData:{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",End:!0}}},schedule:"cron(0 0 * * ? *)"}]},monitoring:{dashboard:{name:`${i}-pipeline`,widgets:[{type:"metric",metrics:["KinesisIncomingRecords","LambdaInvocations","S3ObjectsCreated","GlueJobsSucceeded"]}]},alarms:[{metric:"LambdaErrors",threshold:10,evaluationPeriods:1},{metric:"KinesisIteratorAge",threshold:60000,evaluationPeriods:2}]}}}}function Vy(a){let{name:n,slug:i,domain:s,modelS3Path:c=`s3://${i}-models/`,instanceType:l="ml.t3.medium"}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:s}},infrastructure:{storage:{models:{public:!1,versioning:!0,encryption:!0,intelligentTiering:!0},datasets:{public:!1,versioning:!0,encryption:!0,lifecycleRules:[{id:"ArchiveOldDatasets",enabled:!0,transitions:[{days:90,storageClass:"GLACIER"}]}]},predictions:{public:!1,versioning:!1,encryption:!0,lifecycleRules:[{id:"DeleteOldPredictions",enabled:!0,expirationDays:30}]}},machineLearning:{sagemaker:{endpoints:[{name:`${i}-inference`,modelS3Path:c,instanceType:l,initialInstanceCount:1,autoScaling:{minInstances:1,maxInstances:5,targetInvocationsPerInstance:1000}}],trainingJobs:[{name:`${i}-training`,algorithmSpecification:{trainingImage:"TO_BE_SPECIFIED",trainingInputMode:"File"},instanceType:"ml.p3.2xlarge",instanceCount:1,volumeSizeInGB:50,maxRuntimeInSeconds:86400}]}},apiGateway:{type:"HTTP",customDomain:s?{domain:s,certificateArn:"TO_BE_GENERATED"}:void 0,cors:{allowOrigins:["*"],allowMethods:["POST"],allowHeaders:["Content-Type","Authorization"]},throttling:{rateLimit:1000,burstLimit:500}},functions:{predict:{runtime:"python3.11",handler:"handlers/predict.handler",memory:2048,timeout:60,events:[{type:"http",path:"/predict",method:"POST"}],environment:{SAGEMAKER_ENDPOINT:`${i}-inference`,MODEL_BUCKET:`${i}-models`}},"batch-predict":{runtime:"python3.11",handler:"handlers/batchPredict.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${i}-datasets`,suffix:".csv"}]},"trigger-training":{runtime:"python3.11",handler:"handlers/training.handler",memory:1024,timeout:300,events:[{type:"schedule",expression:"cron(0 2 * * ? *)"}]}},databases:{dynamodb:{tables:{[`${i}-predictions`]:{partitionKey:{name:"requestId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0},[`${i}-models`]:{partitionKey:{name:"modelId",type:"S"},sortKey:{name:"version",type:"S"},billingMode:"PAY_PER_REQUEST"}}}},queues:{predictions:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:86400,deadLetterQueue:!0}},monitoring:{dashboard:{name:`${i}-ml`,widgets:[{type:"metric",metrics:["SageMakerInvocations","SageMakerModelLatency","APIGatewayRequests","LambdaErrors"]}]},alarms:[{metric:"SageMakerModelLatency",threshold:1000,evaluationPeriods:2},{metric:"SageMakerInvocationErrors",threshold:10,evaluationPeriods:1}]},security:{certificate:s?{domain:s,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","apiProtection"]}}}}}function jy(a){let{name:n,slug:i,domain:s,instanceType:c="t3.medium",minInstances:l=2,maxInstances:u=10,databaseEngine:h="mysql",sessionStore:y="redis"}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:s}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:2}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",autoScaling:{min:l,max:u,targetCPU:70,scaleUpCooldown:300,scaleDownCooldown:300},loadBalancer:{type:"application",healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3},stickySession:{enabled:!0,duration:86400}},userData:`#!/bin/bash
|
|
2489
|
+
| limit 20`,region:e.ref("AWS::Region"),title:`Logs: ${l.logGroup}`}});else if(l.type==="text"&&l.text)i.push({type:"text",x:s,y:c,width:u,height:h,properties:{markdown:l.text}});if(s+=u,s>=24)s=0,c+=h}),a.addResource("CloudWatchDashboard","AWS::CloudWatch::Dashboard",{DashboardName:e.sub(`\${AWS::StackName}-${n.name}`),DashboardBody:JSON.stringify({widgets:i})}),a.addOutputs({DashboardURL:{Description:"CloudWatch Dashboard URL",Value:e.sub("https://console.aws.amazon.com/cloudwatch/home?region=${AWS::Region}#dashboards:name=${CloudWatchDashboard}")}})}function tn(a,n,i){let s=a.toLogicalId(`${n}-log-group`);a.addResource(s,"AWS::Logs::LogGroup",{LogGroupName:e.sub(`/aws/\${AWS::StackName}/${n}`),RetentionInDays:i||14,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}`)}]})}function Lt(a,n){if(n)return{ec2:"AWS/EC2",ecs:"AWS/ECS",lambda:"AWS/Lambda",rds:"AWS/RDS",dynamodb:"AWS/DynamoDB",s3:"AWS/S3",cloudfront:"AWS/CloudFront",alb:"AWS/ApplicationELB",nlb:"AWS/NetworkELB",apigateway:"AWS/ApiGateway",sqs:"AWS/SQS",sns:"AWS/SNS",kinesis:"AWS/Kinesis",elasticache:"AWS/ElastiCache"}[n.toLowerCase()]||"AWS/CloudWatch";let i=a.toLowerCase();if(i.includes("cpu")||i.includes("memory")||i.includes("network"))return"AWS/EC2";if(i.includes("lambda")||i.includes("invocation")||i.includes("duration"))return"AWS/Lambda";if(i.includes("request")||i.includes("latency")||i.includes("target"))return"AWS/ApplicationELB";if(i.includes("database")||i.includes("connection"))return"AWS/RDS";if(i.includes("read")||i.includes("write")||i.includes("consumed"))return"AWS/DynamoDB";return"AWS/CloudWatch"}function an(a){return{ec2:[{Name:"InstanceId",Value:e.ref("EC2Instance")}],ecs:[{Name:"ClusterName",Value:e.ref("ECSCluster")},{Name:"ServiceName",Value:e.getAtt("ECSService","Name")}],lambda:[{Name:"FunctionName",Value:e.ref("LambdaFunction")}],rds:[{Name:"DBInstanceIdentifier",Value:e.ref("Database")}],dynamodb:[{Name:"TableName",Value:e.ref("DynamoDBTable")}],alb:[{Name:"LoadBalancer",Value:e.getAtt("LoadBalancer","LoadBalancerFullName")}],apigateway:[{Name:"ApiName",Value:e.ref("HttpApi")}]}[a.toLowerCase()]||[]}function rn(a,n){if(!n.vpc)return;let{cidr:i="10.0.0.0/16",availabilityZones:s=2,natGateways:c=1,enableDnsHostnames:l=!0,enableDnsSupport:u=!0}=n.vpc;a.addResource("VPC","AWS::EC2::VPC",{CidrBlock:i,EnableDnsHostnames:l,EnableDnsSupport:u,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-vpc")}]}),a.addResource("InternetGateway","AWS::EC2::InternetGateway",{Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-igw")}]}),a.addResource("VPCGatewayAttachment","AWS::EC2::VPCGatewayAttachment",{VpcId:e.ref("VPC"),InternetGatewayId:e.ref("InternetGateway")},{dependsOn:["VPC","InternetGateway"]});let h=[];for(let b=0;b<s;b++){let C=`PublicSubnet${b+1}`;h.push(C),a.addResource(C,"AWS::EC2::Subnet",{VpcId:e.ref("VPC"),CidrBlock:e.select(b,e.cidr(e.getAtt("VPC","CidrBlock"),s*2,8)),AvailabilityZone:e.select(b,e.getAZs()),MapPublicIpOnLaunch:!0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-public-${b+1}`)},{Key:"Type",Value:"public"}]},{dependsOn:"VPC"})}let y=[];for(let b=0;b<s;b++){let C=`PrivateSubnet${b+1}`;y.push(C),a.addResource(C,"AWS::EC2::Subnet",{VpcId:e.ref("VPC"),CidrBlock:e.select(b+s,e.cidr(e.getAtt("VPC","CidrBlock"),s*2,8)),AvailabilityZone:e.select(b,e.getAZs()),MapPublicIpOnLaunch:!1,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-private-${b+1}`)},{Key:"Type",Value:"private"}]},{dependsOn:"VPC"})}let f=[];for(let b=0;b<c;b++){let C=`NatEIP${b+1}`;f.push(C),a.addResource(C,"AWS::EC2::EIP",{Domain:"vpc",Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-nat-eip-${b+1}`)}]},{dependsOn:"VPCGatewayAttachment"})}let S=[];for(let b=0;b<c;b++){let C=`NatGateway${b+1}`;S.push(C);let T=b%s;a.addResource(C,"AWS::EC2::NatGateway",{AllocationId:e.getAtt(f[b],"AllocationId"),SubnetId:e.ref(h[T]),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-nat-${b+1}`)}]},{dependsOn:[f[b],h[T]]})}a.addResource("PublicRouteTable","AWS::EC2::RouteTable",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-public-rt")}]},{dependsOn:"VPC"}),a.addResource("PublicRoute","AWS::EC2::Route",{RouteTableId:e.ref("PublicRouteTable"),DestinationCidrBlock:"0.0.0.0/0",GatewayId:e.ref("InternetGateway")},{dependsOn:["PublicRouteTable","VPCGatewayAttachment"]}),h.forEach((b,C)=>{a.addResource(`PublicSubnetRouteTableAssociation${C+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:e.ref(b),RouteTableId:e.ref("PublicRouteTable")},{dependsOn:[b,"PublicRouteTable"]})}),y.forEach((b,C)=>{let T=`PrivateRouteTable${C+1}`,v=C%c;a.addResource(T,"AWS::EC2::RouteTable",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-private-rt-${C+1}`)}]},{dependsOn:"VPC"}),a.addResource(`PrivateRoute${C+1}`,"AWS::EC2::Route",{RouteTableId:e.ref(T),DestinationCidrBlock:"0.0.0.0/0",NatGatewayId:e.ref(S[v])},{dependsOn:[T,S[v]]}),a.addResource(`PrivateSubnetRouteTableAssociation${C+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:e.ref(b),RouteTableId:e.ref(T)},{dependsOn:[b,T]})}),a.addResource("S3VPCEndpoint","AWS::EC2::VPCEndpoint",{VpcId:e.ref("VPC"),ServiceName:e.sub("com.amazonaws.${AWS::Region}.s3"),VpcEndpointType:"Gateway",RouteTableIds:[e.ref("PublicRouteTable"),...Array.from({length:s},(b,C)=>e.ref(`PrivateRouteTable${C+1}`))]},{dependsOn:"VPC"}),a.addResource("NetworkAcl","AWS::EC2::NetworkAcl",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-nacl")}]},{dependsOn:"VPC"}),a.addResource("NetworkAclEntryInbound","AWS::EC2::NetworkAclEntry",{NetworkAclId:e.ref("NetworkAcl"),RuleNumber:100,Protocol:-1,RuleAction:"allow",CidrBlock:"0.0.0.0/0"},{dependsOn:"NetworkAcl"}),a.addResource("NetworkAclEntryOutbound","AWS::EC2::NetworkAclEntry",{NetworkAclId:e.ref("NetworkAcl"),RuleNumber:100,Protocol:-1,Egress:!0,RuleAction:"allow",CidrBlock:"0.0.0.0/0"},{dependsOn:"NetworkAcl"}),a.addOutputs({VPCId:{Description:"VPC ID",Value:e.ref("VPC"),Export:{Name:e.sub("${AWS::StackName}-VPC")}},PublicSubnets:{Description:"Public subnet IDs",Value:e.join(",",h.map((b)=>e.ref(b))),Export:{Name:e.sub("${AWS::StackName}-PublicSubnets")}},PrivateSubnets:{Description:"Private subnet IDs",Value:e.join(",",y.map((b)=>e.ref(b))),Export:{Name:e.sub("${AWS::StackName}-PrivateSubnets")}}})}function nn(a,n){for(let[i,s]of Object.entries(n))sn(a,i,s)}function sn(a,n,i){let s=a.toLogicalId(`${n}-queue`),c=i.fifo||!1,l;if(i.deadLetterQueue){let h=`${s}DLQ`;a.addResource(h,"AWS::SQS::Queue",{QueueName:c?e.sub(`\${AWS::StackName}-${n}-dlq.fifo`):e.sub(`\${AWS::StackName}-${n}-dlq`),FifoQueue:c,MessageRetentionPeriod:1209600,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}-dlq`)}]},{deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),l=e.getAtt(h,"Arn")}let u={QueueName:c?e.sub(`\${AWS::StackName}-${n}.fifo`):e.sub(`\${AWS::StackName}-${n}`),FifoQueue:c,VisibilityTimeout:i.visibilityTimeout||30,MessageRetentionPeriod:i.messageRetentionPeriod||345600,ReceiveMessageWaitTimeSeconds:i.receiveMessageWaitTime||0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}`)}]};if(c&&i.contentBasedDeduplication)u.ContentBasedDeduplication=!0;if(i.deadLetterQueue&&l)u.RedrivePolicy={deadLetterTargetArn:l,maxReceiveCount:i.maxReceiveCount||3};if(a.addResource(s,"AWS::SQS::Queue",u,{dependsOn:i.deadLetterQueue?`${s}DLQ`:void 0,deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),a.addResource(`${s}Policy`,"AWS::SQS::QueuePolicy",{Queues:[e.ref(s)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["lambda.amazonaws.com","events.amazonaws.com","sns.amazonaws.com"]},Action:"sqs:SendMessage",Resource:e.getAtt(s,"Arn"),Condition:{ArnEquals:{"aws:SourceArn":e.sub("arn:aws:*:${AWS::Region}:${AWS::AccountId}:*")}}}]}},{dependsOn:s}),a.addOutputs({[`${s}Url`]:{Description:`${n} queue URL`,Value:e.ref(s),Export:{Name:e.sub(`\${AWS::StackName}-${n}-queue-url`)}},[`${s}Arn`]:{Description:`${n} queue ARN`,Value:e.getAtt(s,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${n}-queue-arn`)}}}),i.deadLetterQueue)a.addOutputs({[`${s}DLQUrl`]:{Description:`${n} dead letter queue URL`,Value:e.ref(`${s}DLQ`),Export:{Name:e.sub(`\${AWS::StackName}-${n}-dlq-url`)}}})}function on(a,n){if(n.certificate)cn(a,n.certificate);if(n.waf?.enabled)ln(a,n.waf);if(n.securityGroups)for(let[i,s]of Object.entries(n.securityGroups))un(a,i,s)}function cn(a,n){if(!n)return;let i=[n.domain];if(n.subdomains)i.push(...n.subdomains);a.addResource("Certificate","AWS::CertificateManager::Certificate",{DomainName:n.domain,SubjectAlternativeNames:n.subdomains,ValidationMethod:n.validationMethod||"DNS",DomainValidationOptions:i.map((s)=>({DomainName:s,HostedZoneId:e.ref("HostedZone")})),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-certificate")}]}),a.addOutputs({CertificateArn:{Description:"ACM Certificate ARN",Value:e.ref("Certificate"),Export:{Name:e.sub("${AWS::StackName}-certificate-arn")}}})}function ln(a,n){if(!n)return;let i=[],s=n.rules||["rateLimit","sqlInjection","xss"];if(s.includes("rateLimit"))i.push({Name:"RateLimitRule",Priority:1,Statement:{RateBasedStatement:{Limit:n.rateLimit||2000,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"RateLimitRule"}});let c=i.length+1;if(s.includes("sqlInjection"))i.push({Name:"AWSManagedRulesSQLi",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesSQLiRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesSQLi"}});if(s.includes("xss"))i.push({Name:"AWSManagedRulesXSS",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesXSS"}});if(s.includes("knownBadInputs"))i.push({Name:"AWSManagedRulesKnownBadInputs",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesKnownBadInputs"}});if(s.includes("coreRuleSet"))i.push({Name:"AWSManagedRulesCoreRuleSet",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesCommonRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesCoreRuleSet"}});if(s.includes("linuxRuleSet"))i.push({Name:"AWSManagedRulesLinuxRuleSet",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesLinuxRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesLinuxRuleSet"}});if(s.includes("apiProtection"))i.push({Name:"AWSManagedRulesAPIProtection",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesAmazonIpReputationList"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesAPIProtection"}});if(s.includes("geoBlock"))i.push({Name:"GeoBlockRule",Priority:c++,Statement:{GeoMatchStatement:{CountryCodes:["CN","RU"]}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"GeoBlockRule"}});if(s.includes("connectionLimit"))i.push({Name:"ConnectionLimitRule",Priority:c++,Statement:{RateBasedStatement:{Limit:100,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"ConnectionLimitRule"}});if(a.addResource("WebACL","AWS::WAFv2::WebACL",{Name:e.sub("${AWS::StackName}-waf"),Scope:n.scope||"REGIONAL",DefaultAction:{Allow:{}},Rules:i,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:e.sub("${AWS::StackName}-waf")},Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-waf")}]}),a.hasResource("LoadBalancer"))a.addResource("WebACLAssociation","AWS::WAFv2::WebACLAssociation",{ResourceArn:e.ref("LoadBalancer"),WebACLArn:e.getAtt("WebACL","Arn")},{dependsOn:["WebACL","LoadBalancer"]});a.addOutputs({WebACLId:{Description:"WAF Web ACL ID",Value:e.ref("WebACL"),Export:{Name:e.sub("${AWS::StackName}-waf-id")}},WebACLArn:{Description:"WAF Web ACL ARN",Value:e.getAtt("WebACL","Arn"),Export:{Name:e.sub("${AWS::StackName}-waf-arn")}}})}function un(a,n,i){if(!i)return;let s=a.toLogicalId(`${n}-security-group`),c=i.ingress?.map((u)=>({IpProtocol:u.protocol,FromPort:u.port,ToPort:u.port,CidrIp:u.cidr,SourceSecurityGroupId:u.source?e.ref(u.source):void 0}))||[],l=i.egress?.map((u)=>({IpProtocol:u.protocol,FromPort:u.port,ToPort:u.port,CidrIp:u.cidr||"0.0.0.0/0"}))||[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}];a.addResource(s,"AWS::EC2::SecurityGroup",{GroupDescription:`Security group for ${n}`,VpcId:e.ref("VPC"),SecurityGroupIngress:c,SecurityGroupEgress:l,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}-sg`)}]},{dependsOn:"VPC"}),a.addOutputs({[`${s}Id`]:{Description:`${n} security group ID`,Value:e.ref(s),Export:{Name:e.sub(`\${AWS::StackName}-${n}-sg-id`)}}})}function dn(a,n){for(let[i,s]of Object.entries(n)){if(s.type==="efs"){pn(a,i,s);continue}mn(a,i,s)}}function mn(a,n,i){let s=a.toLogicalId(`${n}-bucket`),c={BucketName:e.sub(`\${AWS::StackName}-${n}`),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}`)}]};if(i.versioning)c.VersioningConfiguration={Status:"Enabled"};if(i.encryption)c.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(!i.public)c.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(i.website)c.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"index.html"};if(i.cors&&i.cors.length>0)c.CorsConfiguration={CorsRules:i.cors.map((l)=>({AllowedOrigins:l.allowedOrigins,AllowedMethods:l.allowedMethods,AllowedHeaders:l.allowedHeaders||["*"],MaxAge:l.maxAge||3600}))};if(i.lifecycleRules&&i.lifecycleRules.length>0)c.LifecycleConfiguration={Rules:i.lifecycleRules.map((l)=>({Id:l.id,Status:l.enabled?"Enabled":"Disabled",ExpirationInDays:l.expirationDays,Transitions:l.transitions?.map((u)=>({TransitionInDays:u.days,StorageClass:u.storageClass}))}))};if(i.intelligentTiering)c.IntelligentTieringConfigurations=[{Id:"EntireBucket",Status:"Enabled",Tierings:[{AccessTier:"ARCHIVE_ACCESS",Days:90},{AccessTier:"DEEP_ARCHIVE_ACCESS",Days:180}]}];if(a.addResource(s,"AWS::S3::Bucket",c,{deletionPolicy:i.versioning?"Retain":"Delete"}),i.public)a.addResource(`${s}Policy`,"AWS::S3::BucketPolicy",{Bucket:e.ref(s),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:"s3:GetObject",Resource:e.join("",[Vs.s3Bucket(e.ref(s)),"/*"])}]}},{dependsOn:s});if(a.addOutputs({[`${s}Name`]:{Description:`${n} bucket name`,Value:e.ref(s),Export:{Name:e.sub(`\${AWS::StackName}-${n}-bucket`)}},[`${s}Arn`]:{Description:`${n} bucket ARN`,Value:e.getAtt(s,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${n}-bucket-arn`)}}}),i.website)a.addOutputs({[`${s}WebsiteURL`]:{Description:`${n} website URL`,Value:e.getAtt(s,"WebsiteURL")}})}function pn(a,n,i){let s=a.toLogicalId(`${n}-efs`),c={Encrypted:i.encryption!==!1,PerformanceMode:i.performanceMode||"generalPurpose",ThroughputMode:i.throughputMode||"bursting",FileSystemTags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${n}`)}]};if(i.lifecyclePolicy){if(c.LifecyclePolicies=[],i.lifecyclePolicy.transitionToIA)c.LifecyclePolicies.push({TransitionToIA:`AFTER_${i.lifecyclePolicy.transitionToIA}_DAYS`});if(i.lifecyclePolicy.transitionToPrimaryStorageClass)c.LifecyclePolicies.push({TransitionToPrimaryStorageClass:"AFTER_1_ACCESS"})}a.addResource(s,"AWS::EFS::FileSystem",c,{deletionPolicy:"Retain"});let l=2;for(let u=0;u<l;u++)a.addResource(`${s}MountTarget${u+1}`,"AWS::EFS::MountTarget",{FileSystemId:e.ref(s),SubnetId:e.ref(`PrivateSubnet${u+1}`),SecurityGroups:[e.ref("EFSSecurityGroup")]},{dependsOn:[s,`PrivateSubnet${u+1}`]});a.addResource("EFSSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for EFS mount targets",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:2049,ToPort:2049,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-efs-sg")}]},{dependsOn:"VPC"}),a.addOutputs({[`${s}Id`]:{Description:`${n} EFS file system ID`,Value:e.ref(s),Export:{Name:e.sub(`\${AWS::StackName}-${n}-efs`)}}})}class Tp{template;config;resourceDependencies;constructor(a){this.config=a,this.resourceDependencies=new Map,this.template={AWSTemplateFormatVersion:"2010-09-09",Description:`Infrastructure for ${a.project.name} (${a.project.slug})`,Resources:{}}}build(){return this.addParameters(),this.addMappings(),this.addConditions(),this.addResources(),this.initializeOutputs(),this.resolveDependencies(),this.template}addParameters(){this.template.Parameters={Environment:{Type:"String",Default:"production",AllowedValues:["development","staging","production"],Description:"Environment name"}}}addMappings(){this.template.Mappings={RegionMap:{"us-east-1":{AMI:"ami-0f3caa1cf4417e51b"},"us-west-2":{AMI:"ami-0d1cd67c26f5fca19"},"eu-west-1":{AMI:"ami-0bbc25e23a7640b9b"}}}}addConditions(){this.template.Conditions={IsProduction:e.equals(e.ref("Environment"),"production"),HasDomain:e.not([e.equals(this.config.environments?.production?.domain||"","")])}}addResources(){let{infrastructure:a}=this.config;if(!a)return;if(a.network)this.addNetworkResources(a.network);if(a.storage)this.addStorageResources(a.storage);if(a.compute)this.addComputeResources(a.compute);if(a.databases)this.addDatabaseResources(a.databases);if(a.cache)this.addCacheResources(a.cache);if(a.cdn)this.addCDNResources(a.cdn);if(a.apiGateway)this.addApiGatewayResources(a.apiGateway);if(a.functions)this.addFunctionResources(a.functions);if(a.queues)this.addQueueResources(a.queues);if(a.messaging)this.addMessagingResources(a.messaging);if(a.monitoring)this.addMonitoringResources(a.monitoring);if(a.security)this.addSecurityResources(a.security)}initializeOutputs(){let a=this.template.Outputs||{};if(this.template.Outputs={StackName:{Description:"Stack name",Value:e.ref("AWS::StackName"),Export:{Name:e.sub("${AWS::StackName}-Name")}},Region:{Description:"AWS Region",Value:e.ref("AWS::Region"),Export:{Name:e.sub("${AWS::StackName}-Region")}},...a},this.config.environments?.production?.domain)this.template.Outputs.Domain={Description:"Production domain",Value:this.config.environments.production.domain,Condition:"HasDomain"}}addResource(a,n,i,s){let c={Type:n,Properties:i};if(s?.dependsOn)c.DependsOn=s.dependsOn,this.trackDependency(a,s.dependsOn);if(s?.condition)c.Condition=s.condition;if(s?.deletionPolicy)c.DeletionPolicy=s.deletionPolicy;if(s?.updateReplacePolicy)c.UpdateReplacePolicy=s.updateReplacePolicy;this.template.Resources[a]=c}addOutputs(a){this.template.Outputs={...this.template.Outputs,...a}}getOutputs(){return this.template.Outputs||{}}hasResource(a){return a in this.template.Resources}getResource(a){return this.template.Resources[a]}trackDependency(a,n){if(!this.resourceDependencies.has(a))this.resourceDependencies.set(a,new Set);(Array.isArray(n)?n:[n]).forEach((i)=>this.resourceDependencies.get(a).add(i))}resolveDependencies(){let a=new Set,n=new Set,i=(s)=>{if(n.has(s))throw Error(`Circular dependency detected involving resource: ${s}`);if(a.has(s))return!0;a.add(s),n.add(s);let c=this.resourceDependencies.get(s);if(c)for(let l of c)i(l);return n.delete(s),!0};for(let s of this.resourceDependencies.keys())i(s)}toLogicalId(a){return a.split(/[-_\s]/).map((n)=>n.charAt(0).toUpperCase()+n.slice(1).toLowerCase()).join("")}addNetworkResources(a){rn(this,a)}addStorageResources(a){dn(this,a)}addComputeResources(a){Ur(this,a)}addDatabaseResources(a){jr(this,a)}addFunctionResources(a){Hr(this,a)}addCacheResources(a){$r(this,a)}addQueueResources(a){nn(this,a)}addMessagingResources(a){Jr(this,a)}addCDNResources(a){Wr(this,a)}addApiGatewayResources(a){wr(this,a)}addMonitoringResources(a){Zr(this,a)}addSecurityResources(a){on(this,a)}}function sd(a){return new Tp(a).build()}function _y(a){let{name:n,slug:i,domain:s,subdomain:c}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:c&&s?`${c}.${s}`:s}},infrastructure:{storage:{assets:{public:!0,versioning:!1,website:!0,encryption:!1,cors:[{allowedOrigins:["*"],allowedMethods:["GET","HEAD"],allowedHeaders:["*"],maxAge:3600}]}},cdn:{enabled:!0,customDomain:s?{domain:c&&s?`${c}.${s}`:s,certificateArn:"TO_BE_GENERATED"}:void 0,cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0,errorPages:{404:"/index.html",403:"/index.html"}}}}}function Oy(a){let{name:n,slug:i,domain:s,instanceType:c="t3.small",minInstances:l=2,maxInstances:u=10}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:s}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",keyPair:`${i}-key`,autoScaling:{min:l,max:u,desired:l,targetCPU:70},loadBalancer:{type:"application",healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3}},userData:{packages:["nodejs","npm","nginx"],commands:["curl -fsSL https://bun.sh/install | bash","npm install -g pm2"]}}},databases:{postgres:{engine:"postgres",version:"15",instanceClass:"db.t3.micro",allocatedStorage:20,multiAZ:!0,backupRetentionDays:7,deletionProtection:!0}},cache:{redis:{nodeType:"cache.t3.micro",numCacheNodes:1,engine:"redis",engineVersion:"7.0"}},security:{certificate:s?{domain:s,subdomains:[`*.${s}`],validationMethod:"DNS"}:void 0}}}}function Ly(a){let{name:n,slug:i,domain:s,taskCpu:c="256",taskMemory:l="512",desiredCount:u=2}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:s}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:0}},compute:{fargate:{taskDefinition:{cpu:c,memory:l,containerDefinitions:[{name:"app",image:`${i}-app:latest`,portMappings:[{containerPort:3000}],environment:[],secrets:[]}]},service:{desiredCount:u,healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3},autoScaling:{min:u,max:u*5,targetCPU:70,targetMemory:80}},loadBalancer:{type:"application"}}},databases:{dynamodb:{tables:{[`${i}-main`]:{partitionKey:{name:"id",type:"S"},sortKey:{name:"createdAt",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0}}}},functions:{"process-queue":{runtime:"nodejs20.x",handler:"dist/workers/queue.handler",memory:512,timeout:60,events:[{type:"sqs",queueName:`${i}-queue`}]}},security:{certificate:s?{domain:s,subdomains:[`*.${s}`],validationMethod:"DNS"}:void 0}}}}function $y(a){let{name:n,slug:i,entry:s,domain:c,runtime:l="nodejs20.x",memory:u=1024,build:h,deploy:y,assets:f,queues:S=!0,scheduler:b="on",region:C="us-east-1"}=a;return{project:{name:n,slug:i,region:C},mode:"serverless",environments:{production:{type:"production",domain:c,app:{kind:"node",runtime:l,entry:s,memory:u,build:h,deploy:y,assets:f,queues:S,scheduler:b,domain:c}}}}}function od(a){let n=a.database!==!1,i=a.cache!==!1,s=a.queue!==!1;return{project:{name:a.name,slug:a.slug,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:a.domain}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{fargate:{taskDefinition:{cpu:"256",memory:"512",containerDefinitions:[{name:"api",image:a.imageUri,portMappings:[{containerPort:3000}],environment:[{name:"NODE_ENV",value:"production"},{name:"PORT",value:"3000"},{name:"AWS_REGION",value:e.ref("AWS::Region")},...n?[{name:"DB_HOST",value:e.getAtt("PostgresDb","Endpoint.Address")},{name:"DB_PORT",value:e.getAtt("PostgresDb","Endpoint.Port")}]:[],...i?[{name:"REDIS_HOST",value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Address")},{name:"REDIS_PORT",value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Port")},{name:"REDIS_TLS",value:"true"}]:[],...s?[{name:"QUEUE_URL",value:e.ref("JobsQueue")}]:[],{name:"MAIL_TRANSPORT",value:"ses"}],secrets:n?[{name:"DB_USERNAME",valueFrom:e.sub("${DBSecret}:username::")},{name:"DB_PASSWORD",valueFrom:e.sub("${DBSecret}:password::")}]:[]}]},service:{desiredCount:a.desiredCount||1,healthCheck:{path:"/api/health",interval:30,timeout:5},autoScaling:{min:a.desiredCount||1,max:6,targetCPU:70}},loadBalancer:{type:"application",...a.certificateArn?{customDomain:{domain:a.domain,certificateArn:a.certificateArn}}:{},...a.originVerifySecret?{originVerifyHeader:{name:"X-Origin-Verify",value:a.originVerifySecret}}:{}}}},...n?{databases:{postgres:{engine:"postgres",version:"16",instanceClass:"db.t4g.micro",allocatedStorage:20,maxAllocatedStorage:100,multiAZ:!1,backupRetentionDays:7,deletionProtection:!0}}}:{},...i?{cache:{redis:{nodeType:"cache.t4g.micro",numCacheNodes:2,engine:"redis",engineVersion:"7.1",automaticFailoverEnabled:!0,snapshotRetentionLimit:5}}}:{},...s?{queues:{jobs:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0,maxReceiveCount:3,receiveMessageWaitTime:20}}}:{}}}}function My(a){let{name:n,slug:i,domain:s,apiSubdomain:c="api"}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:s}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},storage:{frontend:{public:!0,versioning:!0,website:!0,encryption:!1}},cdn:{enabled:!0,customDomain:{domain:s,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0,errorPages:{404:"/index.html"}},compute:{fargate:{taskDefinition:{cpu:"512",memory:"1024",containerDefinitions:[{name:"api",image:`${i}-api:latest`,portMappings:[{containerPort:3000}]}]},service:{desiredCount:2,healthCheck:{path:"/api/health",interval:30},autoScaling:{min:2,max:10,targetCPU:70}},loadBalancer:{type:"application",customDomain:{domain:`${c}.${s}`,certificateArn:"TO_BE_GENERATED"}}}},databases:{postgres:{engine:"postgres",version:"15",instanceClass:"db.t3.small",allocatedStorage:50,multiAZ:!0,backupRetentionDays:14,deletionProtection:!0}},cache:{redis:{nodeType:"cache.t3.small",numCacheNodes:2,engine:"redis",engineVersion:"7.0"}},queues:{jobs:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0}},security:{certificate:{domain:s,subdomains:[`*.${s}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss"]}}}}}function Fy(a){let{name:n,slug:i,domain:s}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:s}},infrastructure:{apiGateway:{type:"HTTP",cors:{allowOrigins:["*"],allowMethods:["GET","POST","PUT","DELETE","PATCH"],allowHeaders:["Content-Type","Authorization"],maxAge:3600},customDomain:s?{domain:s,certificateArn:"TO_BE_GENERATED"}:void 0,throttling:{rateLimit:1e4,burstLimit:5000},authorizer:{type:"JWT",identitySource:"$request.header.Authorization"}},functions:{users:{runtime:"nodejs20.x",handler:"dist/api/users.handler",memory:512,timeout:30,events:[{type:"http",path:"/users",method:"GET"},{type:"http",path:"/users",method:"POST"}]},products:{runtime:"nodejs20.x",handler:"dist/api/products.handler",memory:512,timeout:30,events:[{type:"http",path:"/products",method:"GET"}]}},databases:{dynamodb:{tables:{[`${i}-users`]:{partitionKey:{name:"userId",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0,globalSecondaryIndexes:[{name:"EmailIndex",partitionKey:{name:"email",type:"S"},projection:"ALL"}]},[`${i}-products`]:{partitionKey:{name:"productId",type:"S"},sortKey:{name:"category",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!1}}}},cache:{elasticache:{nodeType:"cache.t3.micro",numCacheNodes:1,engine:"redis",engineVersion:"7.0"}},security:{certificate:s?{domain:s,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","sqlInjection"]}},monitoring:{alarms:[{metric:"Errors",threshold:10,period:300,evaluationPeriods:1},{metric:"Duration",threshold:3000,period:300,evaluationPeriods:2}]}}}}function Uy(a){let{name:n,slug:i,domain:s,instanceType:c="t3.small"}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:s}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",keyPair:`${i}-key`,autoScaling:{min:2,max:6,desired:2,targetCPU:75},loadBalancer:{type:"application",healthCheck:{path:"/wp-admin/install.php",interval:30}},userData:{packages:["nginx","php8.1-fpm","php8.1-mysql","php8.1-curl","php8.1-gd","php8.1-mbstring","php8.1-xml","php8.1-zip"],commands:["cd /var/www","wget https://wordpress.org/latest.tar.gz","tar -xzf latest.tar.gz","chown -R www-data:www-data wordpress","rm /etc/nginx/sites-enabled/default","systemctl restart nginx","systemctl restart php8.1-fpm"]}}},fileSystem:{uploads:{performanceMode:"generalPurpose",throughputMode:"bursting",encrypted:!0,lifecyclePolicy:{transitionToIA:30},mountPath:"/var/www/wordpress/wp-content/uploads"}},databases:{mysql:{engine:"mysql",version:"8.0",instanceClass:"db.t3.small",allocatedStorage:50,multiAZ:!0,backupRetentionDays:7,deletionProtection:!0,databaseName:"wordpress"}},cache:{redis:{nodeType:"cache.t3.micro",numCacheNodes:1,engine:"redis",engineVersion:"7.0"}},cdn:{enabled:!0,customDomain:{domain:s,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,origins:[{type:"alb",pathPattern:"/wp-content/*"}]},security:{certificate:{domain:s,subdomains:[`www.${s}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss","wordpressRules"]}}}}}function Qy(a){let{name:n,slug:i,domain:s,apiDomain:c}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:s}},infrastructure:{storage:{static:{public:!0,versioning:!0,website:!0,encryption:!1,cors:[{allowedOrigins:["*"],allowedMethods:["GET","HEAD"]}],lifecycleRules:[{id:"DeleteOldVersions",enabled:!0,expirationDays:90}]}},cdn:{enabled:!0,customDomain:{domain:s,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:0,maxTTL:31536000},compress:!0,http3:!0,errorPages:{404:"/404.html",500:"/500.html"},edgeFunctions:[{eventType:"origin-request",functionArn:"TO_BE_CREATED",name:"ssr-handler"}]},functions:{ssr:{runtime:"nodejs20.x",handler:"dist/edge/ssr.handler",memory:512,timeout:5},...c?{api:{runtime:"nodejs20.x",handler:"dist/api/index.handler",memory:1024,timeout:30,events:[{type:"http",path:"/{proxy+}",method:"ANY"}]}}:{}},apiGateway:c?{type:"HTTP",customDomain:{domain:c,certificateArn:"TO_BE_GENERATED"},cors:{allowOrigins:[s],allowMethods:["GET","POST","PUT","DELETE"],allowHeaders:["Content-Type","Authorization"]}}:void 0,databases:{dynamodb:{tables:{content:{partitionKey:{name:"id",type:"S"},sortKey:{name:"type",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!1}}}},security:{certificate:{domain:s,subdomains:c?[c]:[],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","geoBlock"]}}}}}function Hy(a){let{name:n,slug:i,domain:s,services:c}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:s}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:3,natGateways:2}},compute:{services:c.map((l)=>({name:l.name,type:"fargate",taskDefinition:{cpu:l.cpu||"256",memory:l.memory||"512",containerDefinitions:[{name:l.name,image:`${i}-${l.name}:latest`,portMappings:[{containerPort:l.port}],healthCheck:{command:["CMD-SHELL",`curl -f http://localhost:${l.port}/health || exit 1`],interval:30,timeout:5,retries:3}}]},service:{desiredCount:l.desiredCount||2,serviceDiscovery:{enabled:!0,namespace:`${i}.local`},autoScaling:{min:2,max:10,targetCPU:70}}}))},apiGateway:{type:"HTTP",customDomain:{domain:s,certificateArn:"TO_BE_GENERATED"},cors:{allowOrigins:["*"],allowMethods:["GET","POST","PUT","DELETE","PATCH"]},routes:c.map((l)=>({path:`/${l.name}/{proxy+}`,integration:{type:"vpc-link",service:l.name}}))},databases:{dynamodb:{tables:Object.fromEntries(c.map((l)=>[`${i}-${l.name}`,{partitionKey:{name:"id",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0}]))}},queues:{events:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0}},messaging:{topics:{events:{name:`${i}-events`,subscriptions:c.map((l)=>({protocol:"sqs",endpoint:`${i}-${l.name}-queue`,filterPolicy:{service:[l.name]}}))}}},monitoring:{dashboard:{name:`${i}-microservices`,widgets:c.map((l)=>({type:"metric",metrics:[{service:l.name,metric:"CPUUtilization"},{service:l.name,metric:"MemoryUtilization"},{service:l.name,metric:"RequestCount"}]}))},alarms:c.flatMap((l)=>[{name:`${l.name}-high-cpu`,metric:"CPUUtilization",threshold:80,service:l.name},{name:`${l.name}-errors`,metric:"Errors",threshold:10,service:l.name}])},security:{certificate:{domain:s,validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection"]}}}}}function Gy(a){let{name:n,slug:i,domain:s}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:s}},infrastructure:{apiGateway:{type:"websocket",customDomain:s?{domain:s,certificateArn:"TO_BE_GENERATED"}:void 0,routes:[{path:"$connect",method:"WEBSOCKET",integration:"websocket-connect"},{path:"$disconnect",method:"WEBSOCKET",integration:"websocket-disconnect"},{path:"$default",method:"WEBSOCKET",integration:"websocket-default"},{path:"sendMessage",method:"WEBSOCKET",integration:"websocket-send-message"},{path:"joinRoom",method:"WEBSOCKET",integration:"websocket-join-room"}]},functions:{connect:{runtime:"nodejs20.x",handler:"dist/websocket/connect.handler",memory:512,timeout:30},disconnect:{runtime:"nodejs20.x",handler:"dist/websocket/disconnect.handler",memory:512,timeout:30},default:{runtime:"nodejs20.x",handler:"dist/websocket/default.handler",memory:512,timeout:30},"send-message":{runtime:"nodejs20.x",handler:"dist/websocket/sendMessage.handler",memory:512,timeout:30},"join-room":{runtime:"nodejs20.x",handler:"dist/websocket/joinRoom.handler",memory:512,timeout:30},broadcast:{runtime:"nodejs20.x",handler:"dist/streams/broadcast.handler",memory:1024,timeout:60,events:[{type:"dynamodb-stream",tableName:`${i}-messages`,startingPosition:"LATEST",batchSize:100}]}},databases:{dynamodb:{tables:{[`${i}-connections`]:{partitionKey:{name:"connectionId",type:"S"},billingMode:"PAY_PER_REQUEST",globalSecondaryIndexes:[{name:"RoomIndex",partitionKey:{name:"roomId",type:"S"},sortKey:{name:"connectionId",type:"S"},projection:"ALL"}]},[`${i}-messages`]:{partitionKey:{name:"roomId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0,globalSecondaryIndexes:[{name:"UserIndex",partitionKey:{name:"userId",type:"S"},sortKey:{name:"timestamp",type:"S"},projection:"ALL"}]},[`${i}-rooms`]:{partitionKey:{name:"roomId",type:"S"},billingMode:"PAY_PER_REQUEST"}}}},cache:{elasticache:{nodeType:"cache.t3.small",numCacheNodes:2,engine:"redis",engineVersion:"7.0"}},monitoring:{alarms:[{metric:"WebSocketConnections",threshold:1e4,evaluationPeriods:1},{metric:"IntegrationLatency",threshold:1000,evaluationPeriods:2}],dashboard:{name:`${i}-realtime`,widgets:[{type:"metric",metrics:["WebSocketConnections","MessagesSent","IntegrationLatency"]}]}},security:{certificate:s?{domain:s,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","connectionLimit"]}}}}}function qy(a){let{name:n,slug:i,retentionDays:s=7}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",infrastructure:{streaming:{dataStream:{name:`${i}-stream`,shardCount:2,retentionPeriod:s*24,encryption:!0}},storage:{raw:{public:!1,versioning:!0,encryption:!0,intelligentTiering:!0,lifecycleRules:[{id:"ArchiveOldData",enabled:!0,transitions:[{days:30,storageClass:"GLACIER"},{days:90,storageClass:"DEEP_ARCHIVE"}]}]},processed:{public:!1,versioning:!0,encryption:!0,intelligentTiering:!0}},functions:{"stream-processor":{runtime:"nodejs20.x",handler:"dist/processors/stream.handler",memory:2048,timeout:300,events:[{type:"kinesis",streamName:`${i}-stream`,batchSize:1000,startingPosition:"LATEST",parallelizationFactor:10}]},transformer:{runtime:"nodejs20.x",handler:"dist/processors/transform.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${i}-raw`,prefix:"incoming/"}]},aggregator:{runtime:"nodejs20.x",handler:"dist/processors/aggregate.handler",memory:2048,timeout:600,events:[{type:"schedule",expression:"cron(0 * * * ? *)"}]}},analytics:{athena:{database:`${i}_analytics`,workgroup:`${i}-workgroup`,outputBucket:`${i}-query-results`,tables:[{name:"raw_events",location:`s3://${i}-raw/events/`,format:"parquet",partitionKeys:["year","month","day"]},{name:"processed_events",location:`s3://${i}-processed/events/`,format:"parquet",partitionKeys:["year","month","day"]}]},glue:{crawlers:[{name:`${i}-crawler`,databaseName:`${i}_analytics`,s3Targets:[`s3://${i}-raw/`,`s3://${i}-processed/`],schedule:"cron(0 2 * * ? *)"}],jobs:[{name:`${i}-etl-job`,scriptLocation:`s3://${i}-scripts/etl.py`,role:`${i}-glue-role`,maxCapacity:10,timeout:120}]}},databases:{dynamodb:{tables:{[`${i}-metadata`]:{partitionKey:{name:"pipelineId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST"}}}},queues:{failedJobs:{fifo:!1,visibilityTimeout:900,messageRetentionPeriod:1209600,deadLetterQueue:!0,maxReceiveCount:3}},workflow:{pipelines:[{name:`${i}-daily-pipeline`,type:"stepFunctions",definition:{StartAt:"ExtractData",States:{ExtractData:{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Next:"TransformData"},TransformData:{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Next:"LoadData"},LoadData:{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",End:!0}}},schedule:"cron(0 0 * * ? *)"}]},monitoring:{dashboard:{name:`${i}-pipeline`,widgets:[{type:"metric",metrics:["KinesisIncomingRecords","LambdaInvocations","S3ObjectsCreated","GlueJobsSucceeded"]}]},alarms:[{metric:"LambdaErrors",threshold:10,evaluationPeriods:1},{metric:"KinesisIteratorAge",threshold:60000,evaluationPeriods:2}]}}}}function Vy(a){let{name:n,slug:i,domain:s,modelS3Path:c=`s3://${i}-models/`,instanceType:l="ml.t3.medium"}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:s}},infrastructure:{storage:{models:{public:!1,versioning:!0,encryption:!0,intelligentTiering:!0},datasets:{public:!1,versioning:!0,encryption:!0,lifecycleRules:[{id:"ArchiveOldDatasets",enabled:!0,transitions:[{days:90,storageClass:"GLACIER"}]}]},predictions:{public:!1,versioning:!1,encryption:!0,lifecycleRules:[{id:"DeleteOldPredictions",enabled:!0,expirationDays:30}]}},machineLearning:{sagemaker:{endpoints:[{name:`${i}-inference`,modelS3Path:c,instanceType:l,initialInstanceCount:1,autoScaling:{minInstances:1,maxInstances:5,targetInvocationsPerInstance:1000}}],trainingJobs:[{name:`${i}-training`,algorithmSpecification:{trainingImage:"TO_BE_SPECIFIED",trainingInputMode:"File"},instanceType:"ml.p3.2xlarge",instanceCount:1,volumeSizeInGB:50,maxRuntimeInSeconds:86400}]}},apiGateway:{type:"HTTP",customDomain:s?{domain:s,certificateArn:"TO_BE_GENERATED"}:void 0,cors:{allowOrigins:["*"],allowMethods:["POST"],allowHeaders:["Content-Type","Authorization"]},throttling:{rateLimit:1000,burstLimit:500}},functions:{predict:{runtime:"python3.11",handler:"handlers/predict.handler",memory:2048,timeout:60,events:[{type:"http",path:"/predict",method:"POST"}],environment:{SAGEMAKER_ENDPOINT:`${i}-inference`,MODEL_BUCKET:`${i}-models`}},"batch-predict":{runtime:"python3.11",handler:"handlers/batchPredict.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${i}-datasets`,suffix:".csv"}]},"trigger-training":{runtime:"python3.11",handler:"handlers/training.handler",memory:1024,timeout:300,events:[{type:"schedule",expression:"cron(0 2 * * ? *)"}]}},databases:{dynamodb:{tables:{[`${i}-predictions`]:{partitionKey:{name:"requestId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0},[`${i}-models`]:{partitionKey:{name:"modelId",type:"S"},sortKey:{name:"version",type:"S"},billingMode:"PAY_PER_REQUEST"}}}},queues:{predictions:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:86400,deadLetterQueue:!0}},monitoring:{dashboard:{name:`${i}-ml`,widgets:[{type:"metric",metrics:["SageMakerInvocations","SageMakerModelLatency","APIGatewayRequests","LambdaErrors"]}]},alarms:[{metric:"SageMakerModelLatency",threshold:1000,evaluationPeriods:2},{metric:"SageMakerInvocationErrors",threshold:10,evaluationPeriods:1}]},security:{certificate:s?{domain:s,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","apiProtection"]}}}}}function jy(a){let{name:n,slug:i,domain:s,instanceType:c="t3.medium",minInstances:l=2,maxInstances:u=10,databaseEngine:h="mysql",sessionStore:y="redis"}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:s}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:2}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",autoScaling:{min:l,max:u,targetCPU:70,scaleUpCooldown:300,scaleDownCooldown:300},loadBalancer:{type:"application",healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3},stickySession:{enabled:!0,duration:86400}},userData:`#!/bin/bash
|
|
2490
2490
|
# Install Node.js or PHP/Python based on app needs
|
|
2491
2491
|
# Configure application server (PM2, Nginx, Apache)
|
|
2492
2492
|
# Mount EFS for shared file storage
|
|
2493
|
-
`}},storage:{uploads:{type:"efs",performanceMode:"generalPurpose",throughputMode:"bursting",encrypted:!0,lifecyclePolicy:{transitionToIA:30}},backups:{public:!1,versioning:!0,encryption:!0,lifecycleRules:[{id:"ArchiveOldBackups",enabled:!0,transitions:[{days:90,storageClass:"GLACIER"}]}]},static:{public:!0,versioning:!1,encryption:!1,cors:[{allowedOrigins:[s||"*"],allowedMethods:["GET","HEAD"]}]}},cdn:{enabled:!0,origins:[{originId:"static-assets",domainName:`${i}-static.s3.amazonaws.com`,pathPattern:"/static/*"}],customDomain:s?{domain:s,certificateArn:"TO_BE_GENERATED"}:void 0,cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0},databases:h==="mysql"?{mysql:{engine:"mysql",version:"8.0",instanceClass:"db.t3.medium",allocatedStorage:100,maxAllocatedStorage:500,multiAZ:!0,backupRetentionDays:14,preferredBackupWindow:"03:00-04:00",preferredMaintenanceWindow:"sun:04:00-sun:05:00",enablePerformanceInsights:!0,performanceInsightsRetention:7,deletionProtection:!0,parameters:{max_connections:"500",innodb_buffer_pool_size:"{DBInstanceClassMemory*3/4}",slow_query_log:"1",long_query_time:"2"}}}:{postgres:{engine:"postgres",version:"15",instanceClass:"db.t3.medium",allocatedStorage:100,maxAllocatedStorage:500,multiAZ:!0,backupRetentionDays:14,preferredBackupWindow:"03:00-04:00",preferredMaintenanceWindow:"sun:04:00-sun:05:00",enablePerformanceInsights:!0,performanceInsightsRetention:7,deletionProtection:!0,parameters:{max_connections:"500",shared_buffers:"{DBInstanceClassMemory/4}",log_min_duration_statement:"2000"}}},cache:y==="redis"?{redis:{nodeType:"cache.t3.medium",numCacheNodes:2,engine:"redis",engineVersion:"7.0",port:6379,parameterGroup:{maxmemoryPolicy:"allkeys-lru",timeout:"300"},snapshotRetentionLimit:5,snapshotWindow:"03:00-05:00",automaticFailoverEnabled:!0}}:void 0,queues:{jobs:{fifo:!1,visibilityTimeout:900,messageRetentionPeriod:345600,receiveMessageWaitTime:20,deadLetterQueue:!0,maxReceiveCount:3},emails:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:86400,deadLetterQueue:!0}},functions:{"job-worker":{runtime:"nodejs20.x",handler:"dist/workers/jobs.handler",memory:2048,timeout:900,events:[{type:"sqs",queueName:`${i}-jobs`,batchSize:10}]},"email-sender":{runtime:"nodejs20.x",handler:"dist/workers/email.handler",memory:512,timeout:60,events:[{type:"sqs",queueName:`${i}-emails`,batchSize:10}]},cleanup:{runtime:"nodejs20.x",handler:"dist/tasks/cleanup.handler",memory:512,timeout:300,events:[{type:"schedule",expression:"cron(0 2 * * ? *)"}]}},monitoring:{dashboard:{name:`${i}-web-app`,widgets:[{type:"metric",metrics:["EC2CPUUtilization","ALBRequestCount","ALBTargetResponseTime","RDSCPUUtilization","RDSDatabaseConnections","RDSReadLatency","RDSWriteLatency"]}]},alarms:[{metric:"EC2CPUUtilization",threshold:80,evaluationPeriods:2},{metric:"RDSCPUUtilization",threshold:80,evaluationPeriods:2},{metric:"RDSDatabaseConnections",threshold:400,evaluationPeriods:1},{metric:"ALBTargetResponseTime",threshold:2000,evaluationPeriods:2},{metric:"ALBUnhealthyHostCount",threshold:1,evaluationPeriods:1}],logs:{retention:14,groups:[`${i}-app`,`${i}-nginx`,`${i}-workers`]}},security:{certificate:s?{domain:s,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss","knownBadInputs"]},securityGroups:{alb:{ingress:[{port:80,protocol:"tcp",cidr:"0.0.0.0/0"},{port:443,protocol:"tcp",cidr:"0.0.0.0/0"}]},app:{ingress:[{port:3000,protocol:"tcp",source:"alb-sg"}]},database:{ingress:[{port:h==="mysql"?3306:5432,protocol:"tcp",source:"app-sg"}]},...y==="redis"&&{cache:{ingress:[{port:6379,protocol:"tcp",source:"app-sg"}]}}}}}}}function zy(a){let{name:n,slug:i,domain:s,repository:c,phpVersion:l="8.3",size:u="small",database:h=i.replace(/-/g,"_"),databasePassword:y,sslEmail:f,deployStrategy:S="push",provider:b="hetzner"}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"server",cloud:{provider:b},environments:{production:{type:"production",domain:s}},infrastructure:{compute:{mode:"server",size:u,runtime:"php",webServer:"nginx",php:{versions:[l],default:l},managedServices:{mysql:!0,redis:!0},firewall:{enabled:!0},autoUpdates:!0,monitoring:!0,backups:{enabled:!0,schedule:"0 2 * * *",retentionCount:7}},appDatabase:{engine:"mysql",name:h,username:h,password:y}},sites:{main:{root:".",type:"laravel",domain:s,phpVersion:l,repository:{...c,strategy:S},scheduler:!0,queues:[{connection:"redis",queue:"default",processes:1}],ssl:{provider:"letsencrypt",email:f}}}}}function Ky(a){let{name:n,slug:i,domain:s,layers:c,phpVersion:l="8.3",architecture:u="x86_64",memory:h=1024,build:y,deploy:f=["migrate --force"],cache:S="dynamodb",scheduler:b="on",region:C="us-east-1"}=a;return{project:{name:n,slug:i,region:C},mode:"serverless",environments:{production:{type:"production",domain:s,app:{kind:"php",runtime:"provided.al2023",phpVersion:l,architecture:u,layers:c,memory:h,build:y,deploy:f,assets:"public",queues:!0,scheduler:b,cache:{driver:S},domain:s}}}}}function Wy(a){return{root:a.root??"packages/ui/dist",deploy:"server",type:"static",domain:a.domain,build:a.build??"cd packages/ui && bun install && bun run build",ssl:{provider:"letsencrypt"},auth:{username:a.username??"admin",password:a.password}}}var lf=bp,uf="./node_modules/@stacksjs/ts-cloud/dist/bin/dashboard-server.js";function gn(a){let n=a.split(".").filter(Boolean);return n.length<=2?a:n.slice(-2).join(".")}function hn(a){let n=2166136261;for(let i=0;i<a.length;i++)n^=a.charCodeAt(i),n=Math.imul(n,16777619);return n>>>0}var pf=20000,gf=12000;function mf(a){return pf+hn(a)%gf}function Ea(a,n){let i=gn(a);if(i===a)return`dashboard.${i}`;for(let s of n)if(s===i)return`dashboard.${i}`;return`dashboard.${a}`}function Pa(a,n){let i=[],s=a.infrastructure?.dns?.domain;if(s&&!a.cloud?.attachTo)i.push(s);if(n&&a.environments?.[n]?.domain)i.push(a.environments[n].domain);for(let c of Object.values(a.sites??{})){let l=c;if(!l||l.redirect)continue;let u=l.domain;if(typeof u==="string")i.push(u);else if(Array.isArray(u))i.push(...u.filter((h)=>typeof h==="string"))}return i.filter((c)=>c&&!c.startsWith("dashboard."))}function hf(a,n,i){if(i)return i;let s=Pa(a,n),c=s[0];if(!c)return null;return Ea(c,s)}function ff(a,n,i){if(i)return[i];let s=Pa(a,n),c=[];for(let l of s){let u=Ea(l,s);if(!c.includes(u))c.push(u)}return c}function Qt(a){return Object.entries(a.sites??{}).some(([n,i])=>{if(!i)return!1;let s=i.root??"";return Nr(n)||s==="ui/dist"||s.endsWith("/ui/dist")||s.endsWith("/dist/ui")})}var wp="dashboard-";function Rp(a){return wp+a.replace(/^dashboard\./,"").replace(/\./g,"-")}function Nr(a){return a==="dashboard"||a.startsWith(wp)}function
|
|
2494
|
-
`),s=null,c,l,u;for(let h of i){let y=h.trim();if(!y||y.startsWith("#")||y.startsWith(";"))continue;let f=y.match(/^\[([^\]]+)\]$/);if(f){if(s===n&&c&&l)return{accessKeyId:c,secretAccessKey:l,sessionToken:u};s=f[1],c=void 0,l=void 0,u=void 0;continue}if(s===n){let[S,...b]=y.split("="),C=b.join("=").trim();switch(S.trim().toLowerCase()){case"aws_access_key_id":c=C;break;case"aws_secret_access_key":l=C;break;case"aws_session_token":u=C;break}}}if(s===n&&c&&l)return{accessKeyId:c,secretAccessKey:l,sessionToken:u};return null}async function If(a){let n=a?.timeout??1000,i="http://169.254.169.254";try{let s=await Ye("http://169.254.169.254/latest/api/token",{method:"PUT",headers:{"X-aws-ec2-metadata-token-ttl-seconds":"21600"}},n);if(!s.ok)return null;let c=await s.text(),l=await Ye("http://169.254.169.254/latest/meta-data/iam/security-credentials/",{headers:{"X-aws-ec2-metadata-token":c}},n);if(!l.ok)return null;let u=(await l.text()).trim(),h=await Ye(`http://169.254.169.254/latest/meta-data/iam/security-credentials/${u}`,{headers:{"X-aws-ec2-metadata-token":c}},n);if(!h.ok)return null;let y=await h.json();return{accessKeyId:y.AccessKeyId,secretAccessKey:y.SecretAccessKey,sessionToken:y.Token,expiration:new Date(y.Expiration)}}catch{return null}}async function Sf(a){let n=a?.timeout??1000,i=process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI,s=process.env.AWS_CONTAINER_CREDENTIALS_FULL_URI,c=null;if(i)c=`http://169.254.170.2${i}`;else if(s)c=s;if(!c)return null;try{let l={},u=process.env.AWS_CONTAINER_AUTHORIZATION_TOKEN;if(u)l.Authorization=u;let h=await Ye(c,{headers:l},n);if(!h.ok)return null;let y=await h.json();return{accessKeyId:y.AccessKeyId,secretAccessKey:y.SecretAccessKey,sessionToken:y.Token,expiration:new Date(y.Expiration)}}catch{return null}}async function Cf(a){let n=a?.timeout??5000,i=process.env.AWS_WEB_IDENTITY_TOKEN_FILE,s=process.env.AWS_ROLE_ARN,c=process.env.AWS_ROLE_SESSION_NAME||"ts-cloud-session";if(!i||!s)return null;try{let l=Wt(i,"utf-8").trim(),u=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION||"us-east-1",h=u.startsWith("us-gov")?`https://sts.${u}.amazonaws.com`:u==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${u}.amazonaws.com`,y=new URLSearchParams({Action:"AssumeRoleWithWebIdentity",Version:"2011-06-15",RoleArn:s,RoleSessionName:c,WebIdentityToken:l}),f=await Ye(`${h}/?${y.toString()}`,{method:"POST"},n);if(!f.ok)return null;let S=await f.text(),b=ze(S,"AccessKeyId"),C=ze(S,"SecretAccessKey"),T=ze(S,"SessionToken"),v=ze(S,"Expiration");if(!b||!C)return null;return{accessKeyId:b,secretAccessKey:C,sessionToken:T??void 0,expiration:v?new Date(v):void 0}}catch{return null}}async function
|
|
2495
|
-
`),h=!1;for(let y of u){let f=y.trim();if(f.startsWith("[")){h=f===l;continue}if(h&&f.startsWith("region")){let[,S]=f.split("=");if(S)return S.trim()}}}catch{}return"us-east-1"}async function vf(a){let n=a||await Vs(),i=Ef();await et();let s=i.startsWith("us-gov")?`https://sts.${i}.amazonaws.com`:i==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${i}.amazonaws.com`,c="Action=GetCallerIdentity&Version=2011-06-15",l=x({method:"POST",url:s,body:"Action=GetCallerIdentity&Version=2011-06-15",headers:{"Content-Type":"application/x-www-form-urlencoded"},...n,service:"sts",region:i}),u=await fetch(l.url,{method:l.method,headers:l.headers,body:l.body});if(!u.ok)throw Error(`Failed to get account ID: ${await u.text()}`);let h=await u.text(),y=ze(h,"Account");if(!y)throw Error("Failed to parse account ID from response");return y}await et();await et();var fn=5242880,Pt=5242880,Sn=5242880;class Da{region;endpoint;forcePathStyle;credentials;credentialOptions;retryOptions;constructor(a={}){this.region=a.region||process.env.AWS_REGION||"us-east-1",this.endpoint=a.endpoint||`https://s3.${this.region}.amazonaws.com`,this.forcePathStyle=a.forcePathStyle||!1,this.credentials=a.credentials,this.credentialOptions=a.credentialOptions,this.retryOptions=a.retryOptions||{}}async getCredentials(){if(this.credentials)return this.credentials;return Vs(this.credentialOptions)}buildUrl(a,n){let i=n?encodeURIComponent(n).replace(/%2F/g,"/"):"";if(this.forcePathStyle)return n?`${this.endpoint}/${a}/${i}`:`${this.endpoint}/${a}`;let s=new URL(this.endpoint);return s.hostname=`${a}.${s.hostname}`,n?`${s.origin}/${i}`:s.origin}async get(a,n,i={}){let s=await this.getCredentials(),c=this.buildUrl(a,n),l={};if(i.range)l.Range=i.range;if(i.ifModifiedSince)l["If-Modified-Since"]=i.ifModifiedSince.toUTCString();if(i.ifMatch)l["If-Match"]=i.ifMatch;if(i.ifNoneMatch)l["If-None-Match"]=i.ifNoneMatch;let u=new URL(c);if(i.responseContentType)u.searchParams.set("response-content-type",i.responseContentType);if(i.responseContentDisposition)u.searchParams.set("response-content-disposition",i.responseContentDisposition);let h=x({method:"GET",url:u.toString(),headers:l,...s,service:"s3",region:this.region}),y=await fetch(h.url,{method:h.method,headers:h.headers});if(!y.ok&&y.status!==304){let f=await y.text();throw new G(`Failed to get object: ${f}`,y.status,a,n)}return y}async getText(a,n,i={}){return(await this.get(a,n,i)).text()}async getJSON(a,n,i={}){return(await this.get(a,n,i)).json()}async getBuffer(a,n,i={}){return(await this.get(a,n,i)).arrayBuffer()}async put(a,n,i,s={}){let c,l;if(typeof i==="string")c=new TextEncoder().encode(i).length,l=i;else if(i instanceof ArrayBuffer)c=i.byteLength,l=i;else if(i instanceof Uint8Array)c=i.byteLength,l=i;else if(i instanceof Blob)c=i.size,l=i;else return this.uploadMultipart(a,n,i,{...s,partSize:Pt});if(c>Sn){let u=Cn(l).stream();return this.uploadMultipart(a,n,u,{...s,partSize:Pt})}return this.putSimple(a,n,l,c,s)}async putSimple(a,n,i,s,c){let l=await this.getCredentials(),u=this.buildUrl(a,n),h={"Content-Length":String(s),"Content-Type":c.contentType||la(n)};if(c.contentEncoding)h["Content-Encoding"]=c.contentEncoding;if(c.cacheControl)h["Cache-Control"]=c.cacheControl;if(c.contentDisposition)h["Content-Disposition"]=c.contentDisposition;if(c.storageClass)h["x-amz-storage-class"]=c.storageClass;if(c.serverSideEncryption)h["x-amz-server-side-encryption"]=c.serverSideEncryption;if(c.acl)h["x-amz-acl"]=c.acl;if(c.tagging)h["x-amz-tagging"]=c.tagging;if(c.metadata)for(let[b,C]of Object.entries(c.metadata))h[`x-amz-meta-${b.toLowerCase()}`]=C;let y;if(typeof i==="string")y=i;else if(i instanceof Blob)y=await i.text();else y=new TextDecoder().decode(i instanceof ArrayBuffer?new Uint8Array(i):i);let f=x({method:"PUT",url:u,headers:h,body:y,...l,service:"s3",region:this.region}),S=await fetch(f.url,{method:f.method,headers:f.headers,body:i});if(!S.ok){let b=await S.text();throw new G(`Failed to put object: ${b}`,S.status,a,n)}return{etag:(S.headers.get("ETag")||"").replace(/"/g,"")}}async delete(a,n){let i=await this.getCredentials(),s=this.buildUrl(a,n),c=x({method:"DELETE",url:s,...i,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(!l.ok&&l.status!==204){let u=await l.text();throw new G(`Failed to delete object: ${u}`,l.status,a,n)}}async deleteMany(a,n){let i=await this.getCredentials(),s=`${this.buildUrl(a)}?delete`,c=`<?xml version="1.0" encoding="UTF-8"?><Delete><Quiet>false</Quiet>${n.map((T)=>`<Object><Key>${An(T)}</Key></Object>`).join("")}</Delete>`,l=x({method:"POST",url:s,headers:{"Content-Type":"application/xml"},body:c,...i,service:"s3",region:this.region}),u=await fetch(l.url,{method:l.method,headers:l.headers,body:c});if(!u.ok){let T=await u.text();throw new G(`Failed to delete objects: ${T}`,u.status,a)}let h=await u.text(),y=[],f=[],S=/<Deleted><Key>([^<]+)<\/Key>/g,b;while((b=S.exec(h))!==null)y.push(b[1]);let C=/<Error><Key>([^<]+)<\/Key><Code>([^<]+)<\/Code><Message>([^<]+)<\/Message>/g;while((b=C.exec(h))!==null)f.push({key:b[1],error:`${b[2]}: ${b[3]}`});return{deleted:y,errors:f}}async list(a,n={}){let i=await this.getCredentials(),s=new URL(this.buildUrl(a));if(s.searchParams.set("list-type","2"),n.prefix)s.searchParams.set("prefix",n.prefix);if(n.delimiter)s.searchParams.set("delimiter",n.delimiter);if(n.maxKeys)s.searchParams.set("max-keys",String(n.maxKeys));if(n.continuationToken)s.searchParams.set("continuation-token",n.continuationToken);if(n.startAfter)s.searchParams.set("start-after",n.startAfter);let c=x({method:"GET",url:s.toString(),...i,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(!l.ok){let h=await l.text();throw new G(`Failed to list objects: ${h}`,l.status,a)}let u=await l.text();return bn(u)}async*listAll(a,n={}){let i;do{let s=await this.list(a,{...n,continuationToken:i});for(let c of s.contents)yield c;i=s.nextContinuationToken}while(i)}async head(a,n){let i=await this.getCredentials(),s=this.buildUrl(a,n),c=x({method:"HEAD",url:s,...i,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(l.status===404)return null;if(!l.ok){let h=await l.text();throw new G(`Failed to head object: ${h}`,l.status,a,n)}let u={};return l.headers.forEach((h,y)=>{if(y.toLowerCase().startsWith("x-amz-meta-"))u[y.slice(11)]=h}),{contentLength:Number(l.headers.get("Content-Length")||0),contentType:l.headers.get("Content-Type")||"application/octet-stream",etag:(l.headers.get("ETag")||"").replace(/"/g,""),lastModified:new Date(l.headers.get("Last-Modified")||0),metadata:u,storageClass:l.headers.get("x-amz-storage-class")||void 0,serverSideEncryption:l.headers.get("x-amz-server-side-encryption")||void 0}}async exists(a,n){return await this.head(a,n)!==null}async copy(a,n,i,s,c={}){let l=await this.getCredentials(),u=this.buildUrl(i,s),h={"x-amz-copy-source":`/${a}/${encodeURIComponent(n)}`};if(c.metadataDirective)h["x-amz-metadata-directive"]=c.metadataDirective;if(c.contentType)h["Content-Type"]=c.contentType;if(c.storageClass)h["x-amz-storage-class"]=c.storageClass;if(c.acl)h["x-amz-acl"]=c.acl;if(c.metadata)for(let[b,C]of Object.entries(c.metadata))h[`x-amz-meta-${b.toLowerCase()}`]=C;let y=x({method:"PUT",url:u,headers:h,...l,service:"s3",region:this.region}),f=await fetch(y.url,{method:y.method,headers:y.headers});if(!f.ok){let b=await f.text();throw new G(`Failed to copy object: ${b}`,f.status,i,s)}let S=(await f.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:S?S[1]:""}}async getPresignedUrl(a,n,i={}){let s=await this.getCredentials(),c=this.buildUrl(a,n);return rf({url:c,method:i.method||"GET",expiresIn:i.expiresIn||3600,...s,service:"s3",region:this.region})}async uploadMultipart(a,n,i,s={}){let c=await this.getCredentials(),l=Math.max(s.partSize||Pt,fn),u,h;if(i instanceof ReadableStream)u=i;else if(i instanceof Blob)u=i.stream(),h=i.size;else{let S=new Blob([i]);u=S.stream(),h=S.size}let{uploadId:y,baseUrl:f}=await this.initiateMultipartUpload(a,n,s);try{let S=await this.uploadParts(a,n,f,y,u,l,c,h,s.concurrency||4,s.onProgress);return await this.completeMultipartUpload(a,n,f,y,S)}catch(S){throw await this.abortMultipartUpload(a,n,y,f).catch(()=>{}),S}}async initiateMultipartUpload(a,n,i){let s=await this.getCredentials(),c=this.buildUrl(a,n),l=`${c}?uploads`,u={"Content-Type":i.contentType||la(n)};if(i.storageClass)u["x-amz-storage-class"]=i.storageClass;if(i.serverSideEncryption)u["x-amz-server-side-encryption"]=i.serverSideEncryption;if(i.acl)u["x-amz-acl"]=i.acl;if(i.metadata)for(let[b,C]of Object.entries(i.metadata))u[`x-amz-meta-${b.toLowerCase()}`]=C;let h=x({method:"POST",url:l,headers:u,...s,service:"s3",region:this.region}),y=await fetch(h.url,{method:h.method,headers:h.headers});if(!y.ok){let b=await y.text();throw new G(`Failed to initiate multipart upload: ${b}`,y.status,a,n)}let f=(await y.text()).match(/<UploadId>([^<]+)<\/UploadId>/);if(!f)throw new G("Failed to parse upload ID from response",0,a,n);let S=c;if(y.url)try{let b=new URL(y.url);b.search="",S=b.toString()}catch{}return{uploadId:f[1],baseUrl:S}}async uploadParts(a,n,i,s,c,l,u,h,y,f){let S=[],b=c.getReader(),C=1,T=new Uint8Array(0),v=0,w=h?Math.ceil(h/l):void 0,R=new Map,k=async(P,V)=>{let B=`${i}?partNumber=${V}&uploadId=${encodeURIComponent(s)}`,j={"Content-Length":String(P.byteLength),"x-amz-content-sha256":"UNSIGNED-PAYLOAD"},Z=x({method:"PUT",url:B,headers:j,...u,service:"s3",region:this.region}),K=await fetch(Z.url,{method:Z.method,headers:Z.headers,body:P,redirect:"error"});if(!K.ok){let te=await K.text();throw new G(`Failed to upload part ${V}: ${te}`,K.status,a,n)}let ee=(K.headers.get("ETag")||"").replace(/"/g,"");if(!ee)throw new G(`Missing ETag for part ${V}`,K.status,a,n);return{partNumber:V,etag:ee}},W=async()=>{let P=await Promise.race(R.values());R.delete(P.partNumber),S.push(P)};while(!0){let{done:P,value:V}=await b.read();if(V){let B=new Uint8Array(T.length+V.length);B.set(T),B.set(V,T.length),T=B}while(T.length>=l||P&&T.length>0){let B=T.slice(0,l);T=T.slice(l);let j=C++;if(R.size>=y)await W();if(R.set(j,k(B,j)),v+=B.byteLength,f)f({loaded:v,total:h||v,part:j,totalParts:w||j})}if(P)break}while(R.size>0)await W();return S.sort((P,V)=>P.partNumber-V.partNumber),S}async completeMultipartUpload(a,n,i,s,c){let l=await this.getCredentials(),u=`${i}?uploadId=${encodeURIComponent(s)}`,h=`<?xml version="1.0" encoding="UTF-8"?><CompleteMultipartUpload>${c.map((b)=>`<Part><PartNumber>${b.partNumber}</PartNumber><ETag>"${b.etag}"</ETag></Part>`).join("")}</CompleteMultipartUpload>`,y=x({method:"POST",url:u,headers:{"Content-Type":"application/xml"},body:h,...l,service:"s3",region:this.region}),f=await fetch(y.url,{method:y.method,headers:y.headers,body:h});if(!f.ok){let b=await f.text();throw new G(`Failed to complete multipart upload: ${b}`,f.status,a,n)}let S=(await f.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:S?S[1]:""}}async abortMultipartUpload(a,n,i,s){let c=await this.getCredentials(),l=`${s??this.buildUrl(a,n)}?uploadId=${encodeURIComponent(i)}`,u=x({method:"DELETE",url:l,...c,service:"s3",region:this.region});await fetch(u.url,{method:u.method,headers:u.headers})}async emptyAndDeleteBucket(a){let n=[];for await(let l of this.listAll(a,{}))if(n.push(l.key),n.length>=1000)await this.deleteMany(a,n),n=[];if(n.length>0)await this.deleteMany(a,n);let i=await this.getCredentials(),s=this.buildUrl(a),c=x({method:"DELETE",url:s,...i,service:"s3",region:this.region});await fetch(c.url,{method:c.method,headers:c.headers})}}class G extends Error{statusCode;bucket;key;constructor(a,n,i,s){super(a);this.statusCode=n,this.bucket=i,this.key=s,this.name="S3Error"}}function bn(a){let n=[],i=[],s=/<Contents>([\s\S]*?)<\/Contents>/g,c;while((c=s.exec(a))!==null){let u=c[1];n.push({key:le(u,"Key")||"",lastModified:new Date(le(u,"LastModified")||0),etag:(le(u,"ETag")||"").replace(/"/g,""),size:Number(le(u,"Size")||0),storageClass:le(u,"StorageClass")||"STANDARD"})}let l=/<CommonPrefixes><Prefix>([^<]+)<\/Prefix><\/CommonPrefixes>/g;while((c=l.exec(a))!==null)i.push(c[1]);return{contents:n,commonPrefixes:i,isTruncated:le(a,"IsTruncated")==="true",continuationToken:le(a,"ContinuationToken")||void 0,nextContinuationToken:le(a,"NextContinuationToken")||void 0,keyCount:Number(le(a,"KeyCount")||0),maxKeys:Number(le(a,"MaxKeys")||1000),prefix:le(a,"Prefix")||void 0,delimiter:le(a,"Delimiter")||void 0}}function le(a,n){let i=new RegExp(`<${n}>([^<]*)</${n}>`),s=a.match(i);return s?s[1]:null}function An(a){return a.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function la(a){let n=a.split(".").pop()?.toLowerCase();return{html:"text/html",htm:"text/html",css:"text/css",js:"application/javascript",mjs:"application/javascript",json:"application/json",xml:"application/xml",txt:"text/plain",md:"text/markdown",csv:"text/csv",jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",gif:"image/gif",webp:"image/webp",svg:"image/svg+xml",ico:"image/x-icon",avif:"image/avif",mp4:"video/mp4",webm:"video/webm",mov:"video/quicktime",avi:"video/x-msvideo",mp3:"audio/mpeg",wav:"audio/wav",ogg:"audio/ogg",pdf:"application/pdf",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xls:"application/vnd.ms-excel",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",ppt:"application/vnd.ms-powerpoint",pptx:"application/vnd.openxmlformats-officedocument.presentationml.presentation",zip:"application/zip",gz:"application/gzip",tar:"application/x-tar",rar:"application/vnd.rar","7z":"application/x-7z-compressed",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf",otf:"font/otf",eot:"application/vnd.ms-fontobject",wasm:"application/wasm"}[n||""]||"application/octet-stream"}function Cn(a){if(a instanceof Blob)return a;if(typeof a==="string")return new Blob([a],{type:"text/plain"});return new Blob([a])}function oI(a){return new Da(a)}await et();class Qe extends Error{code;solution;details;constructor(a,n,i,s){super(a);this.code=n,this.solution=i,this.details=s,this.name="CloudError",Error.captureStackTrace?.(this,Qe)}toString(){let a=`${this.name} [${this.code}]: ${this.message}`;if(this.solution)a+=`
|
|
2493
|
+
`}},storage:{uploads:{type:"efs",performanceMode:"generalPurpose",throughputMode:"bursting",encrypted:!0,lifecyclePolicy:{transitionToIA:30}},backups:{public:!1,versioning:!0,encryption:!0,lifecycleRules:[{id:"ArchiveOldBackups",enabled:!0,transitions:[{days:90,storageClass:"GLACIER"}]}]},static:{public:!0,versioning:!1,encryption:!1,cors:[{allowedOrigins:[s||"*"],allowedMethods:["GET","HEAD"]}]}},cdn:{enabled:!0,origins:[{originId:"static-assets",domainName:`${i}-static.s3.amazonaws.com`,pathPattern:"/static/*"}],customDomain:s?{domain:s,certificateArn:"TO_BE_GENERATED"}:void 0,cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0},databases:h==="mysql"?{mysql:{engine:"mysql",version:"8.0",instanceClass:"db.t3.medium",allocatedStorage:100,maxAllocatedStorage:500,multiAZ:!0,backupRetentionDays:14,preferredBackupWindow:"03:00-04:00",preferredMaintenanceWindow:"sun:04:00-sun:05:00",enablePerformanceInsights:!0,performanceInsightsRetention:7,deletionProtection:!0,parameters:{max_connections:"500",innodb_buffer_pool_size:"{DBInstanceClassMemory*3/4}",slow_query_log:"1",long_query_time:"2"}}}:{postgres:{engine:"postgres",version:"15",instanceClass:"db.t3.medium",allocatedStorage:100,maxAllocatedStorage:500,multiAZ:!0,backupRetentionDays:14,preferredBackupWindow:"03:00-04:00",preferredMaintenanceWindow:"sun:04:00-sun:05:00",enablePerformanceInsights:!0,performanceInsightsRetention:7,deletionProtection:!0,parameters:{max_connections:"500",shared_buffers:"{DBInstanceClassMemory/4}",log_min_duration_statement:"2000"}}},cache:y==="redis"?{redis:{nodeType:"cache.t3.medium",numCacheNodes:2,engine:"redis",engineVersion:"7.0",port:6379,parameterGroup:{maxmemoryPolicy:"allkeys-lru",timeout:"300"},snapshotRetentionLimit:5,snapshotWindow:"03:00-05:00",automaticFailoverEnabled:!0}}:void 0,queues:{jobs:{fifo:!1,visibilityTimeout:900,messageRetentionPeriod:345600,receiveMessageWaitTime:20,deadLetterQueue:!0,maxReceiveCount:3},emails:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:86400,deadLetterQueue:!0}},functions:{"job-worker":{runtime:"nodejs20.x",handler:"dist/workers/jobs.handler",memory:2048,timeout:900,events:[{type:"sqs",queueName:`${i}-jobs`,batchSize:10}]},"email-sender":{runtime:"nodejs20.x",handler:"dist/workers/email.handler",memory:512,timeout:60,events:[{type:"sqs",queueName:`${i}-emails`,batchSize:10}]},cleanup:{runtime:"nodejs20.x",handler:"dist/tasks/cleanup.handler",memory:512,timeout:300,events:[{type:"schedule",expression:"cron(0 2 * * ? *)"}]}},monitoring:{dashboard:{name:`${i}-web-app`,widgets:[{type:"metric",metrics:["EC2CPUUtilization","ALBRequestCount","ALBTargetResponseTime","RDSCPUUtilization","RDSDatabaseConnections","RDSReadLatency","RDSWriteLatency"]}]},alarms:[{metric:"EC2CPUUtilization",threshold:80,evaluationPeriods:2},{metric:"RDSCPUUtilization",threshold:80,evaluationPeriods:2},{metric:"RDSDatabaseConnections",threshold:400,evaluationPeriods:1},{metric:"ALBTargetResponseTime",threshold:2000,evaluationPeriods:2},{metric:"ALBUnhealthyHostCount",threshold:1,evaluationPeriods:1}],logs:{retention:14,groups:[`${i}-app`,`${i}-nginx`,`${i}-workers`]}},security:{certificate:s?{domain:s,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss","knownBadInputs"]},securityGroups:{alb:{ingress:[{port:80,protocol:"tcp",cidr:"0.0.0.0/0"},{port:443,protocol:"tcp",cidr:"0.0.0.0/0"}]},app:{ingress:[{port:3000,protocol:"tcp",source:"alb-sg"}]},database:{ingress:[{port:h==="mysql"?3306:5432,protocol:"tcp",source:"app-sg"}]},...y==="redis"&&{cache:{ingress:[{port:6379,protocol:"tcp",source:"app-sg"}]}}}}}}}function zy(a){let{name:n,slug:i,domain:s,repository:c,phpVersion:l="8.3",size:u="small",database:h=i.replace(/-/g,"_"),databasePassword:y,sslEmail:f,deployStrategy:S="push",provider:b="hetzner"}=a;return{project:{name:n,slug:i,region:"us-east-1"},mode:"server",cloud:{provider:b},environments:{production:{type:"production",domain:s}},infrastructure:{compute:{mode:"server",size:u,runtime:"php",webServer:"nginx",php:{versions:[l],default:l},managedServices:{mysql:!0,redis:!0},firewall:{enabled:!0},autoUpdates:!0,monitoring:!0,backups:{enabled:!0,schedule:"0 2 * * *",retentionCount:7}},appDatabase:{engine:"mysql",name:h,username:h,password:y}},sites:{main:{root:".",type:"laravel",domain:s,phpVersion:l,repository:{...c,strategy:S},scheduler:!0,queues:[{connection:"redis",queue:"default",processes:1}],ssl:{provider:"letsencrypt",email:f}}}}}function Ky(a){let{name:n,slug:i,domain:s,layers:c,phpVersion:l="8.3",architecture:u="x86_64",memory:h=1024,build:y,deploy:f=["migrate --force"],cache:S="dynamodb",scheduler:b="on",region:C="us-east-1"}=a;return{project:{name:n,slug:i,region:C},mode:"serverless",environments:{production:{type:"production",domain:s,app:{kind:"php",runtime:"provided.al2023",phpVersion:l,architecture:u,layers:c,memory:h,build:y,deploy:f,assets:"public",queues:!0,scheduler:b,cache:{driver:S},domain:s}}}}}function Wy(a){return{root:a.root??"packages/ui/dist",deploy:"server",type:"static",domain:a.domain,build:a.build??"cd packages/ui && bun install && bun run build",ssl:{provider:"letsencrypt"},auth:{username:a.username??"admin",password:a.password}}}var lf=bp,uf="./node_modules/@stacksjs/ts-cloud/dist/bin/dashboard-server.js";function gn(a){let n=a.split(".").filter(Boolean);return n.length<=2?a:n.slice(-2).join(".")}function hn(a){let n=2166136261;for(let i=0;i<a.length;i++)n^=a.charCodeAt(i),n=Math.imul(n,16777619);return n>>>0}var pf=20000,gf=12000;function mf(a){return pf+hn(a)%gf}function Ea(a,n){let i=gn(a);if(i===a)return`dashboard.${i}`;for(let s of n)if(s===i)return`dashboard.${i}`;return`dashboard.${a}`}function Pa(a,n){let i=[],s=a.infrastructure?.dns?.domain;if(s&&!a.cloud?.attachTo)i.push(s);if(n&&a.environments?.[n]?.domain)i.push(a.environments[n].domain);for(let c of Object.values(a.sites??{})){let l=c;if(!l||l.redirect)continue;let u=l.domain;if(typeof u==="string")i.push(u);else if(Array.isArray(u))i.push(...u.filter((h)=>typeof h==="string"))}return i.filter((c)=>c&&!c.startsWith("dashboard."))}function hf(a,n,i){if(i)return i;let s=Pa(a,n),c=s[0];if(!c)return null;return Ea(c,s)}function ff(a,n,i){if(i)return[i];let s=Pa(a,n),c=[];for(let l of s){let u=Ea(l,s);if(!c.includes(u))c.push(u)}return c}function Qt(a){return Object.entries(a.sites??{}).some(([n,i])=>{if(!i)return!1;let s=i.root??"";return Nr(n)||s==="ui/dist"||s.endsWith("/ui/dist")||s.endsWith("/dist/ui")})}var wp="dashboard-";function Rp(a){return wp+a.replace(/^dashboard\./,"").replace(/\./g,"-")}function Nr(a){return a==="dashboard"||a.startsWith(wp)}function gi(a,n,i){if(Qt(a))return[];if(a.cloud?.attachTo)return[];let s=i.password?{auth:{username:i.username||"admin",password:i.password,realm:i.realm}}:{},c=i.build===!1||i.build===void 0?{}:{build:i.build};if(i.live!==!1){let l=hf(a,n,i.domain);if(!l)return[];let u=i.port??mf(l),h=a.infrastructure?.appDatabase??a.infrastructure?.compute?.database,y={root:i.uiRoot,deploy:"server",domain:l,preStart:["bun install --production --no-save"],start:`bun ${uf} --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:[lf],healthCheck:{path:"/login"},ssl:{provider:"letsencrypt"}};return[{name:Rp(l),site:y}]}return ff(a,n,i.domain).map((l)=>({name:Rp(l),site:{root:i.uiRoot,deploy:"server",type:"static",domain:l,ssl:{provider:"letsencrypt"},...c,...s}}))}function Jy(a,n,i){return gi(a,n,i)[0]??null}function _t(a,n){let i={...a};for(let s in n){let c=n[s],l=i[s];if(c===void 0)continue;if(Array.isArray(c)&&Array.isArray(l))i[s]=[...l,...c];else if(typeof c==="object"&&c!==null&&!Array.isArray(c)&&typeof l==="object"&&l!==null&&!Array.isArray(l))i[s]=_t(l,c);else i[s]=c}return i}function Dp(a,n){return _t(a,n)}function Xy(...a){return a.reduce((n,i)=>_t(n,i),{})}function Yy(a,n){return(i)=>{let s=a(i);if(typeof n==="function")return Dp(s,n(s,i));return Dp(s,n)}}function kr(a){return{infrastructure:a}}function Zy(a){return kr({monitoring:a})}function eI(a){return kr({security:a})}function tI(a){return kr({databases:a})}function rI(a){return kr({cache:a})}function nI(a){return kr({cdn:a})}function iI(a){return kr({queues:a})}et();function Af(){let a=process.env.AWS_ACCESS_KEY_ID,n=process.env.AWS_SECRET_ACCESS_KEY;if(!a||!n)return null;return{accessKeyId:a,secretAccessKey:n,sessionToken:process.env.AWS_SESSION_TOKEN}}function yf(a){let n=a?.profile||process.env.AWS_PROFILE||"default",i=a?.credentialsFile||Na(Ra(),".aws","credentials");if(!Ia(i))return null;try{let s=Wt(i,"utf-8");return yn(s,n)}catch{return null}}function yn(a,n){let i=a.split(`
|
|
2494
|
+
`),s=null,c,l,u;for(let h of i){let y=h.trim();if(!y||y.startsWith("#")||y.startsWith(";"))continue;let f=y.match(/^\[([^\]]+)\]$/);if(f){if(s===n&&c&&l)return{accessKeyId:c,secretAccessKey:l,sessionToken:u};s=f[1],c=void 0,l=void 0,u=void 0;continue}if(s===n){let[S,...b]=y.split("="),C=b.join("=").trim();switch(S.trim().toLowerCase()){case"aws_access_key_id":c=C;break;case"aws_secret_access_key":l=C;break;case"aws_session_token":u=C;break}}}if(s===n&&c&&l)return{accessKeyId:c,secretAccessKey:l,sessionToken:u};return null}async function If(a){let n=a?.timeout??1000,i="http://169.254.169.254";try{let s=await Ye("http://169.254.169.254/latest/api/token",{method:"PUT",headers:{"X-aws-ec2-metadata-token-ttl-seconds":"21600"}},n);if(!s.ok)return null;let c=await s.text(),l=await Ye("http://169.254.169.254/latest/meta-data/iam/security-credentials/",{headers:{"X-aws-ec2-metadata-token":c}},n);if(!l.ok)return null;let u=(await l.text()).trim(),h=await Ye(`http://169.254.169.254/latest/meta-data/iam/security-credentials/${u}`,{headers:{"X-aws-ec2-metadata-token":c}},n);if(!h.ok)return null;let y=await h.json();return{accessKeyId:y.AccessKeyId,secretAccessKey:y.SecretAccessKey,sessionToken:y.Token,expiration:new Date(y.Expiration)}}catch{return null}}async function Sf(a){let n=a?.timeout??1000,i=process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI,s=process.env.AWS_CONTAINER_CREDENTIALS_FULL_URI,c=null;if(i)c=`http://169.254.170.2${i}`;else if(s)c=s;if(!c)return null;try{let l={},u=process.env.AWS_CONTAINER_AUTHORIZATION_TOKEN;if(u)l.Authorization=u;let h=await Ye(c,{headers:l},n);if(!h.ok)return null;let y=await h.json();return{accessKeyId:y.AccessKeyId,secretAccessKey:y.SecretAccessKey,sessionToken:y.Token,expiration:new Date(y.Expiration)}}catch{return null}}async function Cf(a){let n=a?.timeout??5000,i=process.env.AWS_WEB_IDENTITY_TOKEN_FILE,s=process.env.AWS_ROLE_ARN,c=process.env.AWS_ROLE_SESSION_NAME||"ts-cloud-session";if(!i||!s)return null;try{let l=Wt(i,"utf-8").trim(),u=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION||"us-east-1",h=u.startsWith("us-gov")?`https://sts.${u}.amazonaws.com`:u==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${u}.amazonaws.com`,y=new URLSearchParams({Action:"AssumeRoleWithWebIdentity",Version:"2011-06-15",RoleArn:s,RoleSessionName:c,WebIdentityToken:l}),f=await Ye(`${h}/?${y.toString()}`,{method:"POST"},n);if(!f.ok)return null;let S=await f.text(),b=ze(S,"AccessKeyId"),C=ze(S,"SecretAccessKey"),T=ze(S,"SessionToken"),v=ze(S,"Expiration");if(!b||!C)return null;return{accessKeyId:b,secretAccessKey:C,sessionToken:T??void 0,expiration:v?new Date(v):void 0}}catch{return null}}async function js(a){let n=Af();if(n)return n;let i=yf(a);if(i)return i;let s=await Cf(a);if(s)return s;let c=await Sf(a);if(c)return c;let l=await If(a);if(l)return l;throw Error("Could not find AWS credentials. Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables, or configure ~/.aws/credentials, or run on an EC2 instance with an IAM role.")}function sI(a){let n=null,i=null;return async()=>{if(n){if(!n.expiration)return n;let s=300000;if(n.expiration.getTime()-Date.now()>s)return n}if(i)return i;return i=js(a).then((s)=>(n=s,i=null,s)).catch((s)=>{throw i=null,s}),i}}async function Ye(a,n,i){let s=new AbortController,c=setTimeout(()=>s.abort(),i);try{let l=await fetch(a,{...n,signal:s.signal});return clearTimeout(c),l}catch(l){throw clearTimeout(c),l}}function ze(a,n){let i=new RegExp(`<${n}>([^<]+)</${n}>`),s=a.match(i);return s?s[1]:null}async function bf(a){return js({profile:a})}function Ef(a){let n=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION;if(n)return n;let i=Na(Ra(),".aws","config");if(Ia(i))try{let s=Wt(i,"utf-8"),c=a||process.env.AWS_PROFILE||"default",l=c==="default"?"[default]":`[profile ${c}]`,u=s.split(`
|
|
2495
|
+
`),h=!1;for(let y of u){let f=y.trim();if(f.startsWith("[")){h=f===l;continue}if(h&&f.startsWith("region")){let[,S]=f.split("=");if(S)return S.trim()}}}catch{}return"us-east-1"}async function vf(a){let n=a||await js(),i=Ef();await et();let s=i.startsWith("us-gov")?`https://sts.${i}.amazonaws.com`:i==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${i}.amazonaws.com`,c="Action=GetCallerIdentity&Version=2011-06-15",l=x({method:"POST",url:s,body:"Action=GetCallerIdentity&Version=2011-06-15",headers:{"Content-Type":"application/x-www-form-urlencoded"},...n,service:"sts",region:i}),u=await fetch(l.url,{method:l.method,headers:l.headers,body:l.body});if(!u.ok)throw Error(`Failed to get account ID: ${await u.text()}`);let h=await u.text(),y=ze(h,"Account");if(!y)throw Error("Failed to parse account ID from response");return y}await et();await et();var fn=5242880,Pt=5242880,Sn=5242880;class Da{region;endpoint;forcePathStyle;credentials;credentialOptions;retryOptions;constructor(a={}){this.region=a.region||process.env.AWS_REGION||"us-east-1",this.endpoint=a.endpoint||`https://s3.${this.region}.amazonaws.com`,this.forcePathStyle=a.forcePathStyle||!1,this.credentials=a.credentials,this.credentialOptions=a.credentialOptions,this.retryOptions=a.retryOptions||{}}async getCredentials(){if(this.credentials)return this.credentials;return js(this.credentialOptions)}buildUrl(a,n){let i=n?encodeURIComponent(n).replace(/%2F/g,"/"):"";if(this.forcePathStyle)return n?`${this.endpoint}/${a}/${i}`:`${this.endpoint}/${a}`;let s=new URL(this.endpoint);return s.hostname=`${a}.${s.hostname}`,n?`${s.origin}/${i}`:s.origin}async get(a,n,i={}){let s=await this.getCredentials(),c=this.buildUrl(a,n),l={};if(i.range)l.Range=i.range;if(i.ifModifiedSince)l["If-Modified-Since"]=i.ifModifiedSince.toUTCString();if(i.ifMatch)l["If-Match"]=i.ifMatch;if(i.ifNoneMatch)l["If-None-Match"]=i.ifNoneMatch;let u=new URL(c);if(i.responseContentType)u.searchParams.set("response-content-type",i.responseContentType);if(i.responseContentDisposition)u.searchParams.set("response-content-disposition",i.responseContentDisposition);let h=x({method:"GET",url:u.toString(),headers:l,...s,service:"s3",region:this.region}),y=await fetch(h.url,{method:h.method,headers:h.headers});if(!y.ok&&y.status!==304){let f=await y.text();throw new G(`Failed to get object: ${f}`,y.status,a,n)}return y}async getText(a,n,i={}){return(await this.get(a,n,i)).text()}async getJSON(a,n,i={}){return(await this.get(a,n,i)).json()}async getBuffer(a,n,i={}){return(await this.get(a,n,i)).arrayBuffer()}async put(a,n,i,s={}){let c,l;if(typeof i==="string")c=new TextEncoder().encode(i).length,l=i;else if(i instanceof ArrayBuffer)c=i.byteLength,l=i;else if(i instanceof Uint8Array)c=i.byteLength,l=i;else if(i instanceof Blob)c=i.size,l=i;else return this.uploadMultipart(a,n,i,{...s,partSize:Pt});if(c>Sn){let u=Cn(l).stream();return this.uploadMultipart(a,n,u,{...s,partSize:Pt})}return this.putSimple(a,n,l,c,s)}async putSimple(a,n,i,s,c){let l=await this.getCredentials(),u=this.buildUrl(a,n),h={"Content-Length":String(s),"Content-Type":c.contentType||la(n)};if(c.contentEncoding)h["Content-Encoding"]=c.contentEncoding;if(c.cacheControl)h["Cache-Control"]=c.cacheControl;if(c.contentDisposition)h["Content-Disposition"]=c.contentDisposition;if(c.storageClass)h["x-amz-storage-class"]=c.storageClass;if(c.serverSideEncryption)h["x-amz-server-side-encryption"]=c.serverSideEncryption;if(c.acl)h["x-amz-acl"]=c.acl;if(c.tagging)h["x-amz-tagging"]=c.tagging;if(c.metadata)for(let[b,C]of Object.entries(c.metadata))h[`x-amz-meta-${b.toLowerCase()}`]=C;let y;if(typeof i==="string")y=i;else if(i instanceof Blob)y=await i.text();else y=new TextDecoder().decode(i instanceof ArrayBuffer?new Uint8Array(i):i);let f=x({method:"PUT",url:u,headers:h,body:y,...l,service:"s3",region:this.region}),S=await fetch(f.url,{method:f.method,headers:f.headers,body:i});if(!S.ok){let b=await S.text();throw new G(`Failed to put object: ${b}`,S.status,a,n)}return{etag:(S.headers.get("ETag")||"").replace(/"/g,"")}}async delete(a,n){let i=await this.getCredentials(),s=this.buildUrl(a,n),c=x({method:"DELETE",url:s,...i,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(!l.ok&&l.status!==204){let u=await l.text();throw new G(`Failed to delete object: ${u}`,l.status,a,n)}}async deleteMany(a,n){let i=await this.getCredentials(),s=`${this.buildUrl(a)}?delete`,c=`<?xml version="1.0" encoding="UTF-8"?><Delete><Quiet>false</Quiet>${n.map((T)=>`<Object><Key>${An(T)}</Key></Object>`).join("")}</Delete>`,l=x({method:"POST",url:s,headers:{"Content-Type":"application/xml"},body:c,...i,service:"s3",region:this.region}),u=await fetch(l.url,{method:l.method,headers:l.headers,body:c});if(!u.ok){let T=await u.text();throw new G(`Failed to delete objects: ${T}`,u.status,a)}let h=await u.text(),y=[],f=[],S=/<Deleted><Key>([^<]+)<\/Key>/g,b;while((b=S.exec(h))!==null)y.push(b[1]);let C=/<Error><Key>([^<]+)<\/Key><Code>([^<]+)<\/Code><Message>([^<]+)<\/Message>/g;while((b=C.exec(h))!==null)f.push({key:b[1],error:`${b[2]}: ${b[3]}`});return{deleted:y,errors:f}}async list(a,n={}){let i=await this.getCredentials(),s=new URL(this.buildUrl(a));if(s.searchParams.set("list-type","2"),n.prefix)s.searchParams.set("prefix",n.prefix);if(n.delimiter)s.searchParams.set("delimiter",n.delimiter);if(n.maxKeys)s.searchParams.set("max-keys",String(n.maxKeys));if(n.continuationToken)s.searchParams.set("continuation-token",n.continuationToken);if(n.startAfter)s.searchParams.set("start-after",n.startAfter);let c=x({method:"GET",url:s.toString(),...i,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(!l.ok){let h=await l.text();throw new G(`Failed to list objects: ${h}`,l.status,a)}let u=await l.text();return bn(u)}async*listAll(a,n={}){let i;do{let s=await this.list(a,{...n,continuationToken:i});for(let c of s.contents)yield c;i=s.nextContinuationToken}while(i)}async head(a,n){let i=await this.getCredentials(),s=this.buildUrl(a,n),c=x({method:"HEAD",url:s,...i,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(l.status===404)return null;if(!l.ok){let h=await l.text();throw new G(`Failed to head object: ${h}`,l.status,a,n)}let u={};return l.headers.forEach((h,y)=>{if(y.toLowerCase().startsWith("x-amz-meta-"))u[y.slice(11)]=h}),{contentLength:Number(l.headers.get("Content-Length")||0),contentType:l.headers.get("Content-Type")||"application/octet-stream",etag:(l.headers.get("ETag")||"").replace(/"/g,""),lastModified:new Date(l.headers.get("Last-Modified")||0),metadata:u,storageClass:l.headers.get("x-amz-storage-class")||void 0,serverSideEncryption:l.headers.get("x-amz-server-side-encryption")||void 0}}async exists(a,n){return await this.head(a,n)!==null}async copy(a,n,i,s,c={}){let l=await this.getCredentials(),u=this.buildUrl(i,s),h={"x-amz-copy-source":`/${a}/${encodeURIComponent(n)}`};if(c.metadataDirective)h["x-amz-metadata-directive"]=c.metadataDirective;if(c.contentType)h["Content-Type"]=c.contentType;if(c.storageClass)h["x-amz-storage-class"]=c.storageClass;if(c.acl)h["x-amz-acl"]=c.acl;if(c.metadata)for(let[b,C]of Object.entries(c.metadata))h[`x-amz-meta-${b.toLowerCase()}`]=C;let y=x({method:"PUT",url:u,headers:h,...l,service:"s3",region:this.region}),f=await fetch(y.url,{method:y.method,headers:y.headers});if(!f.ok){let b=await f.text();throw new G(`Failed to copy object: ${b}`,f.status,i,s)}let S=(await f.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:S?S[1]:""}}async getPresignedUrl(a,n,i={}){let s=await this.getCredentials(),c=this.buildUrl(a,n);return rf({url:c,method:i.method||"GET",expiresIn:i.expiresIn||3600,...s,service:"s3",region:this.region})}async uploadMultipart(a,n,i,s={}){let c=await this.getCredentials(),l=Math.max(s.partSize||Pt,fn),u,h;if(i instanceof ReadableStream)u=i;else if(i instanceof Blob)u=i.stream(),h=i.size;else{let S=new Blob([i]);u=S.stream(),h=S.size}let{uploadId:y,baseUrl:f}=await this.initiateMultipartUpload(a,n,s);try{let S=await this.uploadParts(a,n,f,y,u,l,c,h,s.concurrency||4,s.onProgress);return await this.completeMultipartUpload(a,n,f,y,S)}catch(S){throw await this.abortMultipartUpload(a,n,y,f).catch(()=>{}),S}}async initiateMultipartUpload(a,n,i){let s=await this.getCredentials(),c=this.buildUrl(a,n),l=`${c}?uploads`,u={"Content-Type":i.contentType||la(n)};if(i.storageClass)u["x-amz-storage-class"]=i.storageClass;if(i.serverSideEncryption)u["x-amz-server-side-encryption"]=i.serverSideEncryption;if(i.acl)u["x-amz-acl"]=i.acl;if(i.metadata)for(let[b,C]of Object.entries(i.metadata))u[`x-amz-meta-${b.toLowerCase()}`]=C;let h=x({method:"POST",url:l,headers:u,...s,service:"s3",region:this.region}),y=await fetch(h.url,{method:h.method,headers:h.headers});if(!y.ok){let b=await y.text();throw new G(`Failed to initiate multipart upload: ${b}`,y.status,a,n)}let f=(await y.text()).match(/<UploadId>([^<]+)<\/UploadId>/);if(!f)throw new G("Failed to parse upload ID from response",0,a,n);let S=c;if(y.url)try{let b=new URL(y.url);b.search="",S=b.toString()}catch{}return{uploadId:f[1],baseUrl:S}}async uploadParts(a,n,i,s,c,l,u,h,y,f){let S=[],b=c.getReader(),C=1,T=new Uint8Array(0),v=0,w=h?Math.ceil(h/l):void 0,R=new Map,k=async(P,V)=>{let B=`${i}?partNumber=${V}&uploadId=${encodeURIComponent(s)}`,j={"Content-Length":String(P.byteLength),"x-amz-content-sha256":"UNSIGNED-PAYLOAD"},Z=x({method:"PUT",url:B,headers:j,...u,service:"s3",region:this.region}),K=await fetch(Z.url,{method:Z.method,headers:Z.headers,body:P,redirect:"error"});if(!K.ok){let te=await K.text();throw new G(`Failed to upload part ${V}: ${te}`,K.status,a,n)}let ee=(K.headers.get("ETag")||"").replace(/"/g,"");if(!ee)throw new G(`Missing ETag for part ${V}`,K.status,a,n);return{partNumber:V,etag:ee}},W=async()=>{let P=await Promise.race(R.values());R.delete(P.partNumber),S.push(P)};while(!0){let{done:P,value:V}=await b.read();if(V){let B=new Uint8Array(T.length+V.length);B.set(T),B.set(V,T.length),T=B}while(T.length>=l||P&&T.length>0){let B=T.slice(0,l);T=T.slice(l);let j=C++;if(R.size>=y)await W();if(R.set(j,k(B,j)),v+=B.byteLength,f)f({loaded:v,total:h||v,part:j,totalParts:w||j})}if(P)break}while(R.size>0)await W();return S.sort((P,V)=>P.partNumber-V.partNumber),S}async completeMultipartUpload(a,n,i,s,c){let l=await this.getCredentials(),u=`${i}?uploadId=${encodeURIComponent(s)}`,h=`<?xml version="1.0" encoding="UTF-8"?><CompleteMultipartUpload>${c.map((b)=>`<Part><PartNumber>${b.partNumber}</PartNumber><ETag>"${b.etag}"</ETag></Part>`).join("")}</CompleteMultipartUpload>`,y=x({method:"POST",url:u,headers:{"Content-Type":"application/xml"},body:h,...l,service:"s3",region:this.region}),f=await fetch(y.url,{method:y.method,headers:y.headers,body:h});if(!f.ok){let b=await f.text();throw new G(`Failed to complete multipart upload: ${b}`,f.status,a,n)}let S=(await f.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:S?S[1]:""}}async abortMultipartUpload(a,n,i,s){let c=await this.getCredentials(),l=`${s??this.buildUrl(a,n)}?uploadId=${encodeURIComponent(i)}`,u=x({method:"DELETE",url:l,...c,service:"s3",region:this.region});await fetch(u.url,{method:u.method,headers:u.headers})}async emptyAndDeleteBucket(a){let n=[];for await(let l of this.listAll(a,{}))if(n.push(l.key),n.length>=1000)await this.deleteMany(a,n),n=[];if(n.length>0)await this.deleteMany(a,n);let i=await this.getCredentials(),s=this.buildUrl(a),c=x({method:"DELETE",url:s,...i,service:"s3",region:this.region});await fetch(c.url,{method:c.method,headers:c.headers})}}class G extends Error{statusCode;bucket;key;constructor(a,n,i,s){super(a);this.statusCode=n,this.bucket=i,this.key=s,this.name="S3Error"}}function bn(a){let n=[],i=[],s=/<Contents>([\s\S]*?)<\/Contents>/g,c;while((c=s.exec(a))!==null){let u=c[1];n.push({key:le(u,"Key")||"",lastModified:new Date(le(u,"LastModified")||0),etag:(le(u,"ETag")||"").replace(/"/g,""),size:Number(le(u,"Size")||0),storageClass:le(u,"StorageClass")||"STANDARD"})}let l=/<CommonPrefixes><Prefix>([^<]+)<\/Prefix><\/CommonPrefixes>/g;while((c=l.exec(a))!==null)i.push(c[1]);return{contents:n,commonPrefixes:i,isTruncated:le(a,"IsTruncated")==="true",continuationToken:le(a,"ContinuationToken")||void 0,nextContinuationToken:le(a,"NextContinuationToken")||void 0,keyCount:Number(le(a,"KeyCount")||0),maxKeys:Number(le(a,"MaxKeys")||1000),prefix:le(a,"Prefix")||void 0,delimiter:le(a,"Delimiter")||void 0}}function le(a,n){let i=new RegExp(`<${n}>([^<]*)</${n}>`),s=a.match(i);return s?s[1]:null}function An(a){return a.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function la(a){let n=a.split(".").pop()?.toLowerCase();return{html:"text/html",htm:"text/html",css:"text/css",js:"application/javascript",mjs:"application/javascript",json:"application/json",xml:"application/xml",txt:"text/plain",md:"text/markdown",csv:"text/csv",jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",gif:"image/gif",webp:"image/webp",svg:"image/svg+xml",ico:"image/x-icon",avif:"image/avif",mp4:"video/mp4",webm:"video/webm",mov:"video/quicktime",avi:"video/x-msvideo",mp3:"audio/mpeg",wav:"audio/wav",ogg:"audio/ogg",pdf:"application/pdf",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xls:"application/vnd.ms-excel",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",ppt:"application/vnd.ms-powerpoint",pptx:"application/vnd.openxmlformats-officedocument.presentationml.presentation",zip:"application/zip",gz:"application/gzip",tar:"application/x-tar",rar:"application/vnd.rar","7z":"application/x-7z-compressed",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf",otf:"font/otf",eot:"application/vnd.ms-fontobject",wasm:"application/wasm"}[n||""]||"application/octet-stream"}function Cn(a){if(a instanceof Blob)return a;if(typeof a==="string")return new Blob([a],{type:"text/plain"});return new Blob([a])}function oI(a){return new Da(a)}await et();class Qe extends Error{code;solution;details;constructor(a,n,i,s){super(a);this.code=n,this.solution=i,this.details=s,this.name="CloudError",Error.captureStackTrace?.(this,Qe)}toString(){let a=`${this.name} [${this.code}]: ${this.message}`;if(this.solution)a+=`
|
|
2496
2496
|
|
|
2497
2497
|
\uD83D\uDCA1 Solution: ${this.solution}`;if(this.details&&Object.keys(this.details).length>0){a+=`
|
|
2498
2498
|
|
|
2499
2499
|
Details:`;for(let[n,i]of Object.entries(this.details))a+=`
|
|
2500
|
-
${n}: ${JSON.stringify(i)}`}return a}}class
|
|
2500
|
+
${n}: ${JSON.stringify(i)}`}return a}}class zs extends Qe{constructor(a,n,i){super(a,"CONFIG_ERROR",n,i);this.name="ConfigurationError"}}class Ht extends Qe{constructor(a,n,i){super(a,"CREDENTIAL_ERROR",n,i);this.name="CredentialError"}}class Tf extends Qe{constructor(a,n,i){super(a,"DEPLOYMENT_ERROR",n,i);this.name="DeploymentError"}}class Pp extends Qe{constructor(a,n,i){super(a,"VALIDATION_ERROR",n,i);this.name="ValidationError"}}class wf extends Qe{statusCode;constructor(a,n,i,s){super(a,"AWS_API_ERROR",i,s);this.statusCode=n,this.name="AWSAPIError"}}var Rf={NO_CREDENTIALS:{message:"AWS credentials not found",solution:`Configure AWS credentials using one of these methods:
|
|
2501
2501
|
1. Set environment variables: AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
|
|
2502
2502
|
2. Create ~/.aws/credentials file with your credentials
|
|
2503
2503
|
3. Use an IAM role (for EC2 instances)
|
|
2504
2504
|
4. Run 'aws configure' if you have AWS CLI installed`},INVALID_CREDENTIALS:{message:"AWS credentials are invalid",solution:"Verify your AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are correct. Run: aws sts get-caller-identity"},EXPIRED_CREDENTIALS:{message:"AWS credentials have expired",solution:"Refresh your AWS credentials. If using temporary credentials, generate new ones."},MISSING_CONFIG:{message:"Configuration file not found",solution:"Create a cloud.config.ts file in your project root. Use: cloud init"},INVALID_CONFIG:{message:"Configuration is invalid",solution:"Check your cloud.config.ts file for syntax errors. Use: cloud config:validate"},MISSING_REQUIRED_FIELD:{message:"Required configuration field is missing",solution:"Add the missing field to your cloud.config.ts file"},INVALID_REGION:{message:"AWS region is invalid",solution:"Use a valid AWS region like us-east-1, us-west-2, eu-west-1, etc."},STACK_ALREADY_EXISTS:{message:"CloudFormation stack already exists",solution:"Use: cloud deploy --update to update the existing stack, or cloud destroy to delete it first"},STACK_IN_PROGRESS:{message:"Stack operation already in progress",solution:"Wait for the current operation to complete, or cancel it in the AWS Console"},INSUFFICIENT_PERMISSIONS:{message:"Insufficient IAM permissions",solution:"Ensure your IAM user/role has the necessary permissions for CloudFormation and the resources you're deploying"},RESOURCE_LIMIT_EXCEEDED:{message:"AWS service limit exceeded",solution:"Request a service limit increase in the AWS Console, or clean up unused resources"},ROLLBACK_COMPLETE:{message:"Stack creation failed and rolled back",solution:"Check the CloudFormation events to see which resource failed. Fix the issue and try again."},CIRCULAR_DEPENDENCY:{message:"Circular dependency detected in resources",solution:"Review your resource dependencies and remove the circular reference"},INVALID_RESOURCE_NAME:{message:"Resource name contains invalid characters",solution:"Use only alphanumeric characters and hyphens in resource names"},DUPLICATE_RESOURCE:{message:"Duplicate resource name detected",solution:"Ensure all resource names are unique in your configuration"},VPC_CIDR_CONFLICT:{message:"VPC CIDR block conflicts with existing VPC",solution:"Use a different CIDR block that doesn't overlap with existing VPCs"},SUBNET_CIDR_INVALID:{message:"Subnet CIDR block is invalid or outside VPC range",solution:"Ensure subnet CIDR is within the VPC CIDR range and properly sized"},DB_INSTANCE_LIMIT:{message:"RDS instance limit reached",solution:"Delete unused RDS instances or request a limit increase"},INVALID_DB_NAME:{message:"Database name contains invalid characters",solution:"Use only alphanumeric characters and underscores, starting with a letter"},BUCKET_ALREADY_EXISTS:{message:"S3 bucket name already exists globally",solution:"S3 bucket names must be globally unique. Try a different name with your organization prefix"},INVALID_BUCKET_NAME:{message:"S3 bucket name is invalid",solution:"Use lowercase letters, numbers, and hyphens. Must start/end with letter/number. 3-63 characters."},TEMPLATE_TOO_LARGE:{message:"CloudFormation template exceeds size limit",solution:"Split your infrastructure into multiple stacks or use nested stacks"},INVALID_TEMPLATE:{message:"CloudFormation template is invalid",solution:"Validate your template with: cloud config:validate"},PARAMETER_NOT_FOUND:{message:"CloudFormation parameter not found",solution:"Check that all referenced parameters are defined in your template"}};function Df(a){return Rf[a]}function Np(a,n){let i=Df(a);return new Qe(i.message,a,i.solution,n)}class Y{static verboseMode=!1;static debugMode=!1;static setVerbose(a){this.verboseMode=a}static setDebug(a){this.debugMode=a}static verbose(a,...n){if(this.verboseMode)console.log(`[VERBOSE] ${a}`,...n)}static debug(a,...n){if(this.debugMode)console.log(`[DEBUG] ${a}`,...n)}static info(a,...n){console.log(`ℹ ${a}`,...n)}static warn(a,...n){console.warn(`⚠ ${a}`,...n)}static error(a,n){if(console.error(`✖ ${a}`),n){if(n instanceof Qe)console.error(n.toString());else console.error(n.message);if(this.debugMode&&n.stack)console.error(`
|
|
2505
|
-
Stack trace:`),console.error(n.stack)}}static success(a){console.log(`✔ ${a}`)}}function aI(a){if(!a)throw Np("MISSING_CONFIG");if(!a.project)throw new
|
|
2505
|
+
Stack trace:`),console.error(n.stack)}}static success(a){console.log(`✔ ${a}`)}}function aI(a){if(!a)throw Np("MISSING_CONFIG");if(!a.project)throw new zs("Missing required field: project","Add a project configuration with name, slug, and region",{field:"project"});if(!a.project.name)throw new zs("Missing required field: project.name","Add a project name to your configuration",{field:"project.name"});if(!a.project.slug)throw new zs("Missing required field: project.slug","Add a project slug (lowercase, alphanumeric with hyphens)",{field:"project.slug"});if(!/^[a-z0-9-]+$/.test(a.project.slug))throw new Pp("Invalid project slug format","Use only lowercase letters, numbers, and hyphens",{slug:a.project.slug});if(a.project.region){if(!["us-east-1","us-east-2","us-west-1","us-west-2","eu-west-1","eu-west-2","eu-west-3","eu-central-1","ap-southeast-1","ap-southeast-2","ap-northeast-1","ap-northeast-2","sa-east-1","ca-central-1"].includes(a.project.region))throw Np("INVALID_REGION",{region:a.project.region})}Y.success("Configuration validation passed")}function cI(a){let n=[];if(a.environments?.production&&a.infrastructure?.database){let i=a.infrastructure.database;if((i.postgres||i.mysql)&&!i.postgres?.multiAZ&&!i.mysql?.multiAZ)n.push("Production database should use Multi-AZ for high availability")}if(a.infrastructure?.storage){for(let[i,s]of Object.entries(a.infrastructure.storage))if(s.encryption===!1)n.push(`Storage "${i}" is not encrypted - consider enabling encryption for security`)}if(a.infrastructure?.storage){for(let[i,s]of Object.entries(a.infrastructure.storage))if(s.public===!0)n.push(`Storage "${i}" is publicly accessible - ensure this is intentional`)}if(a.infrastructure?.database){let i=a.infrastructure.database;if(i.postgres||i.mysql){let s=i.postgres?.backupRetentionDays||i.mysql?.backupRetentionDays;if(!s||s<7)n.push("Database backup retention is less than 7 days - consider increasing for production")}}if(!a.infrastructure?.monitoring)n.push("No monitoring configured - consider adding CloudWatch alarms");return n}async function dI(a="default"){try{Y.verbose("Resolving AWS credentials...");let n=await bf(a);if(!n.accessKeyId||!n.secretAccessKey)throw new Ht("AWS credentials are incomplete","Ensure both AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are set");Y.verbose("Credentials resolved successfully"),Y.debug("Access Key ID:",n.accessKeyId.substring(0,8)+"..."),Y.verbose("Testing credentials with GetCallerIdentity...");let i;try{i=await vf(n),Y.verbose("Credentials are valid"),Y.debug("Account ID:",i)}catch(s){if(s instanceof Error)if(s.message.includes("InvalidClientTokenId"))throw new Ht("Invalid AWS access key ID","Check that your AWS_ACCESS_KEY_ID is correct");else if(s.message.includes("SignatureDoesNotMatch"))throw new Ht("Invalid AWS secret access key","Check that your AWS_SECRET_ACCESS_KEY is correct");else if(s.message.includes("ExpiredToken"))throw new Ht("AWS credentials have expired","Refresh your temporary credentials or use long-term credentials");else throw new Ht(`Failed to validate credentials: ${s.message}`,"Verify your AWS credentials are correct and have the necessary permissions");throw s}return{valid:!0,accountId:i,region:n.region}}catch(n){if(n instanceof Ht)throw n;return{valid:!1,error:n instanceof Error?n.message:"Unknown error"}}}async function lI(a,n){return{allowed:n,denied:[]}}function Pf(a){let n=new Set(["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate","cloudformation:ListStacks"]);if(a.infrastructure){if(a.infrastructure.storage)n.add("s3:CreateBucket"),n.add("s3:DeleteBucket"),n.add("s3:PutBucketPolicy"),n.add("s3:PutBucketVersioning"),n.add("s3:PutBucketEncryption"),n.add("s3:PutObject"),n.add("s3:GetObject");if(a.infrastructure.compute){if(a.infrastructure.compute.server)n.add("ec2:RunInstances"),n.add("ec2:TerminateInstances"),n.add("ec2:DescribeInstances"),n.add("autoscaling:CreateAutoScalingGroup"),n.add("autoscaling:UpdateAutoScalingGroup"),n.add("autoscaling:DeleteAutoScalingGroup"),n.add("elasticloadbalancing:CreateLoadBalancer"),n.add("elasticloadbalancing:DeleteLoadBalancer");if(a.infrastructure.compute.fargate)n.add("ecs:CreateCluster"),n.add("ecs:DeleteCluster"),n.add("ecs:CreateService"),n.add("ecs:UpdateService"),n.add("ecs:DeleteService"),n.add("ecs:RegisterTaskDefinition")}if(a.infrastructure.database){if(a.infrastructure.database.postgres||a.infrastructure.database.mysql)n.add("rds:CreateDBInstance"),n.add("rds:DeleteDBInstance"),n.add("rds:ModifyDBInstance"),n.add("rds:DescribeDBInstances");if(a.infrastructure.database.dynamodb)n.add("dynamodb:CreateTable"),n.add("dynamodb:DeleteTable"),n.add("dynamodb:UpdateTable"),n.add("dynamodb:DescribeTable")}if(a.infrastructure.functions)n.add("lambda:CreateFunction"),n.add("lambda:DeleteFunction"),n.add("lambda:UpdateFunctionCode"),n.add("lambda:UpdateFunctionConfiguration"),n.add("lambda:AddPermission");if(a.infrastructure.cdn)n.add("cloudfront:CreateDistribution"),n.add("cloudfront:UpdateDistribution"),n.add("cloudfront:DeleteDistribution"),n.add("cloudfront:GetDistribution");if(a.infrastructure.network)n.add("ec2:CreateVpc"),n.add("ec2:DeleteVpc"),n.add("ec2:CreateSubnet"),n.add("ec2:DeleteSubnet"),n.add("ec2:CreateInternetGateway"),n.add("ec2:DeleteInternetGateway"),n.add("ec2:CreateNatGateway"),n.add("ec2:DeleteNatGateway"),n.add("ec2:CreateRouteTable"),n.add("ec2:DeleteRouteTable"),n.add("ec2:CreateSecurityGroup"),n.add("ec2:DeleteSecurityGroup")}return n.add("iam:CreateRole"),n.add("iam:DeleteRole"),n.add("iam:AttachRolePolicy"),n.add("iam:DetachRolePolicy"),n.add("iam:PutRolePolicy"),n.add("iam:GetRole"),n.add("iam:PassRole"),Array.from(n).sort()}function uI(a){let n=Pf(a);return JSON.stringify({Version:"2012-10-17",Statement:[{Effect:"Allow",Action:n,Resource:"*"}]},null,2)}var q={ec2:{"Running On-Demand Instances":20,"Elastic IPs":5,VPCs:5,"Internet Gateways":5,"NAT Gateways":5,"Security Groups":500},rds:{"DB Instances":40,"DB Snapshots":100,"DB Parameter Groups":50},lambda:{"Concurrent Executions":1000,"Function Storage":80530636800},s3:{Buckets:100},cloudformation:{Stacks:200,StackSets:100},elasticache:{Nodes:100,Clusters:100},dynamodb:{Tables:256},ecs:{Clusters:1e4,"Services per Cluster":2000}};async function pI(a){let n=[];if(Y.verbose("Checking AWS service quotas..."),a.infrastructure?.compute?.server){let s=a.infrastructure.compute.server.autoScaling?.max||1;n.push({service:"EC2",quotaName:"Running On-Demand Instances",currentValue:s,limit:q.ec2["Running On-Demand Instances"],percentage:s/q.ec2["Running On-Demand Instances"]*100,warning:s>q.ec2["Running On-Demand Instances"]*0.8})}if(a.infrastructure?.network?.vpc)n.push({service:"EC2",quotaName:"VPCs",currentValue:1,limit:q.ec2.VPCs,percentage:1/q.ec2.VPCs*100,warning:!1});if(a.infrastructure?.database?.postgres||a.infrastructure?.database?.mysql)n.push({service:"RDS",quotaName:"DB Instances",currentValue:1,limit:q.rds["DB Instances"],percentage:1/q.rds["DB Instances"]*100,warning:!1});if(a.infrastructure?.storage){let s=Object.keys(a.infrastructure.storage).length;n.push({service:"S3",quotaName:"Buckets",currentValue:s,limit:q.s3.Buckets,percentage:s/q.s3.Buckets*100,warning:s>q.s3.Buckets*0.8})}if(a.infrastructure?.functions){let s=0;for(let c of Object.values(a.infrastructure.functions))if(Array.isArray(c))s+=c.length;n.push({service:"Lambda",quotaName:"Functions (estimated)",currentValue:s,limit:1000,percentage:s/1000*100,warning:s>800})}if(a.infrastructure?.database?.dynamodb){let s=a.infrastructure.database.dynamodb.tables?.length||0;n.push({service:"DynamoDB",quotaName:"Tables",currentValue:s,limit:q.dynamodb.Tables,percentage:s/q.dynamodb.Tables*100,warning:s>q.dynamodb.Tables*0.8})}let i=n.filter((s)=>s.warning);if(i.length>0){Y.warn("Service quota warnings detected:");for(let s of i)Y.warn(` ${s.service} - ${s.quotaName}: ${s.currentValue}/${s.limit} (${s.percentage.toFixed(1)}%)`)}else Y.verbose("All service quotas are within limits");return n}function gI(a){if(a.length===0)return"No quotas to check";let n=`Service Quota Usage:
|
|
2506
2506
|
|
|
2507
2507
|
`,i=a.reduce((s,c)=>{if(!s[c.service])s[c.service]=[];return s[c.service].push(c),s},{});for(let[s,c]of Object.entries(i)){n+=`${s}:
|
|
2508
2508
|
`;for(let l of c){let u=l.warning?"⚠":"✓";n+=` ${u} ${l.quotaName}: ${l.currentValue}/${l.limit} (${l.percentage.toFixed(1)}%)
|
|
2509
2509
|
`}n+=`
|
|
2510
|
-
`}return n}function mI(a){let n=[];for(let i of a)if(i.percentage>=100)n.push(`Request quota increase for ${i.service} - ${i.quotaName} (currently ${i.limit})`);else if(i.warning)n.push(`Consider requesting quota increase for ${i.service} - ${i.quotaName} (${i.percentage.toFixed(1)}% used)`);return n}class kp{cacheDir;ttl;constructor(a,n={}){this.cacheDir=a,this.ttl=n.ttl||86400000}ensureCacheDir(){if(!ot(this.cacheDir))Tn(this.cacheDir,{recursive:!0})}getCachePath(a){let n=ka("sha256").update(a).digest("hex");return It(this.cacheDir,`${n}.json`)}get(a){let n=this.getCachePath(a);if(!ot(n))return;try{let i=da(n,"utf-8"),s=JSON.parse(i);if(Date.now()-s.timestamp>this.ttl){qe(n);return}return s.value}catch{qe(n);return}}set(a,n,i){this.ensureCacheDir();let s=this.getCachePath(a),c={value:n,timestamp:Date.now(),hash:i};vn(s,JSON.stringify(c),"utf-8")}has(a){return this.get(a)!==void 0}clear(){if(!ot(this.cacheDir))return;let a=ua(this.cacheDir);for(let n of a)qe(It(this.cacheDir,n))}prune(){if(!ot(this.cacheDir))return;let a=ua(this.cacheDir),n=Date.now();for(let i of a){let s=It(this.cacheDir,i);try{let c=da(s,"utf-8"),l=JSON.parse(c);if(n-l.timestamp>this.ttl)qe(s)}catch{qe(s)}}}}class Bp{cache;constructor(a=_("cache","templates")){this.cache=new kp(a,{ttl:86400000})}getTemplate(a){return this.cache.get(`template:${a}`)}setTemplate(a,n){let i=this.hashTemplate(n);this.cache.set(`template:${a}`,n,i)}hasChanged(a,n){let i=this.cache.get(`template:${a}`);if(!i)return!0;let s=this.hashTemplate(i),c=this.hashTemplate(n);return s!==c}hashTemplate(a){return ka("sha256").update(a).digest("hex")}clear(){this.cache.clear()}prune(){this.cache.prune()}}var Rt=null;function hI(){if(!Rt)Rt=new Bp;return Rt}async function xp(a,n={}){let i=n.algorithm||"sha256",s=n.chunkSize||65536;return new Promise((c,l)=>{let u=Vt(i),h=wn(a,{highWaterMark:s});h.on("data",(y)=>u.update(y)),h.on("end",()=>c(u.digest("hex"))),h.on("error",l)})}function _p(a,n="sha256"){return Vt(n).update(a).digest("hex")}function fI(a,n="sha256"){return Vt(n).update(a).digest("hex")}async function yI(a,n={}){let i=n.ignorePatterns||["node_modules",".git","dist","build",
|
|
2510
|
+
`}return n}function mI(a){let n=[];for(let i of a)if(i.percentage>=100)n.push(`Request quota increase for ${i.service} - ${i.quotaName} (currently ${i.limit})`);else if(i.warning)n.push(`Consider requesting quota increase for ${i.service} - ${i.quotaName} (${i.percentage.toFixed(1)}% used)`);return n}class kp{cacheDir;ttl;constructor(a,n={}){this.cacheDir=a,this.ttl=n.ttl||86400000}ensureCacheDir(){if(!ot(this.cacheDir))Tn(this.cacheDir,{recursive:!0})}getCachePath(a){let n=ka("sha256").update(a).digest("hex");return It(this.cacheDir,`${n}.json`)}get(a){let n=this.getCachePath(a);if(!ot(n))return;try{let i=da(n,"utf-8"),s=JSON.parse(i);if(Date.now()-s.timestamp>this.ttl){qe(n);return}return s.value}catch{qe(n);return}}set(a,n,i){this.ensureCacheDir();let s=this.getCachePath(a),c={value:n,timestamp:Date.now(),hash:i};vn(s,JSON.stringify(c),"utf-8")}has(a){return this.get(a)!==void 0}clear(){if(!ot(this.cacheDir))return;let a=ua(this.cacheDir);for(let n of a)qe(It(this.cacheDir,n))}prune(){if(!ot(this.cacheDir))return;let a=ua(this.cacheDir),n=Date.now();for(let i of a){let s=It(this.cacheDir,i);try{let c=da(s,"utf-8"),l=JSON.parse(c);if(n-l.timestamp>this.ttl)qe(s)}catch{qe(s)}}}}class Bp{cache;constructor(a=_("cache","templates")){this.cache=new kp(a,{ttl:86400000})}getTemplate(a){return this.cache.get(`template:${a}`)}setTemplate(a,n){let i=this.hashTemplate(n);this.cache.set(`template:${a}`,n,i)}hasChanged(a,n){let i=this.cache.get(`template:${a}`);if(!i)return!0;let s=this.hashTemplate(i),c=this.hashTemplate(n);return s!==c}hashTemplate(a){return ka("sha256").update(a).digest("hex")}clear(){this.cache.clear()}prune(){this.cache.prune()}}var Rt=null;function hI(){if(!Rt)Rt=new Bp;return Rt}async function xp(a,n={}){let i=n.algorithm||"sha256",s=n.chunkSize||65536;return new Promise((c,l)=>{let u=Vt(i),h=wn(a,{highWaterMark:s});h.on("data",(y)=>u.update(y)),h.on("end",()=>c(u.digest("hex"))),h.on("error",l)})}function _p(a,n="sha256"){return Vt(n).update(a).digest("hex")}function fI(a,n="sha256"){return Vt(n).update(a).digest("hex")}async function yI(a,n={}){let i=n.ignorePatterns||["node_modules",".git","dist","build",Qs()],s=[];async function c(l){let u=En(l,{withFileTypes:!0});for(let h of u){let y=Pn(l,h.name),f=In(a,y);if(i.some((S)=>f.includes(S)))continue;if(h.isDirectory())await c(y);else if(h.isFile()){let S=ht(y),b=await xp(y,n);s.push({path:f,hash:b,size:S.size,mtime:S.mtimeMs})}}}return await c(a),s}function II(a){let n=[...a].sort((i,s)=>i.path.localeCompare(s.path)).map((i)=>`${i.path}:${i.hash}`).join(`
|
|
2511
2511
|
`);return _p(n)}function SI(a){let n=ht(a);return _p(`${a}:${n.size}:${n.mtimeMs}`)}function CI(a,n){let i=new Map(a.map((h)=>[h.path,h])),s=new Map(n.map((h)=>[h.path,h])),c=[],l=[],u=[];for(let[h,y]of s){let f=i.get(h);if(!f)c.push(y);else if(f.hash!==y.hash)l.push(y)}for(let[h,y]of i)if(!s.has(h))u.push(y);return{added:c,modified:l,deleted:u}}class Nf{cache;constructor(){this.cache=new Map}get(a){let n=ht(a),i=this.cache.get(a);if(i&&i.mtime===n.mtimeMs&&i.size===n.size)return i.hash;return}set(a,n){let i=ht(a);this.cache.set(a,{hash:n,mtime:i.mtimeMs,size:i.size})}async getOrCompute(a,n={}){let i=this.get(a);if(i)return i;let s=await xp(a,n);return this.set(a,s),s}clear(){this.cache.clear()}}async function ad(a,n={}){let i=n.concurrency||5,s=n.stopOnError??!0,c=[],l=[],u=Date.now(),h=[...a],y=[];async function f(C,T){try{let v=await C();c[T]=v}catch(v){let w=v instanceof Error?v:Error(String(v));if(l.push(w),s)throw h.length=0,w}}let S=0;while(h.length>0||y.length>0){while(y.length<i&&h.length>0){let C=h.shift(),T=S++,v=f(C,T);y.push(v)}if(y.length>0){await Promise.race(y);for(let C=y.length-1;C>=0;C--)if(await Promise.race([y[C].then(()=>!0),Promise.resolve(!1)]))y.splice(C,1)}if(s&&l.length>0)break}let b=Date.now()-u;return{results:c.filter((C)=>C!==void 0),errors:l,duration:b}}async function bI(a,n,i={}){let s=a.map((c)=>()=>n(c));return ad(s,i)}async function EI(a,n,i=5){let s=a.map((l,u)=>()=>n(l,u)),c=await ad(s,{concurrency:i,stopOnError:!1});if(c.errors.length>0)throw AggregateError(c.errors,"Parallel map failed");return c.results}async function vI(a,n={}){let i=n.retries||3,s=n.retryDelay||1000,c=a.map((l)=>async()=>{let u;for(let h=0;h<=i;h++)try{return await l()}catch(y){if(u=y instanceof Error?y:Error(String(y)),h<i)await $a(s*(h+1))}throw u});return ad(c,n)}async function TI(a){let n=[];for(let i of a){let s=await i();n.push(s)}return n}function $a(a){return new Promise((n)=>setTimeout(n,a))}async function wI(a,n,i="Operation timed out"){return Promise.race([a(),new Promise((s,c)=>setTimeout(()=>c(Error(i)),n))])}class kf{maxConcurrent;minInterval;queue=[];running=0;lastExecution=0;constructor(a=5,n=100){this.maxConcurrent=a,this.minInterval=n}async execute(a){await this.waitForSlot(),this.running++,this.lastExecution=Date.now();try{return await a()}finally{this.running--,this.processQueue()}}waitForSlot(){if(this.running<this.maxConcurrent){let a=Date.now()-this.lastExecution;if(a>=this.minInterval)return Promise.resolve();return $a(this.minInterval-a)}return new Promise((a)=>this.queue.push(a))}processQueue(){if(this.queue.length>0&&this.running<this.maxConcurrent)this.queue.shift()()}stats(){return{running:this.running,queued:this.queue.length}}}function Bf(a,n){let i=[];for(let s=0;s<a.length;s+=n)i.push(a.slice(s,s+n));return i}async function RI(a,n,i){let s=Bf(a,n),c=[];for(let l of s){let u=await i(l);c.push(...u)}return c}function DI(a,n){let i=[],s=[],c=[],l=[],u=a.Resources||{},h=n.Resources||{},y=new Set(Object.keys(u)),f=new Set(Object.keys(h));for(let C of f)if(!y.has(C))i.push(C);for(let C of y)if(!f.has(C))c.push(C);for(let C of f)if(y.has(C)){let T=u[C],v=h[C];if(JSON.stringify(T)!==JSON.stringify(v))s.push(C);else l.push(C)}let S=JSON.stringify(a.Parameters||{})!==JSON.stringify(n.Parameters||{}),b=JSON.stringify(a.Outputs||{})!==JSON.stringify(n.Outputs||{});return{added:i,modified:s,deleted:c,unchanged:l,parametersChanged:S,outputsChanged:b,hasChanges:i.length>0||s.length>0||c.length>0||S||b}}function PI(a){let n=[];if(!a.hasChanges)return"No changes detected";if(a.added.length>0){n.push(`Added resources (${a.added.length}):`);for(let i of a.added)n.push(` + ${i}`)}if(a.modified.length>0){n.push(`Modified resources (${a.modified.length}):`);for(let i of a.modified)n.push(` ~ ${i}`)}if(a.deleted.length>0){n.push(`Deleted resources (${a.deleted.length}):`);for(let i of a.deleted)n.push(` - ${i}`)}if(a.parametersChanged)n.push("Parameters changed");if(a.outputsChanged)n.push("Outputs changed");return n.join(`
|
|
2512
2512
|
`)}function NI(a,n,i){if(a.deleted.length>0)return!0;for(let s of a.modified){let c=n.Resources[s],l=i.Resources[s];if(c.Type!==l.Type)return!0;let u=Rn(l.Type);for(let h of u){let y=c.Properties?.[h],f=l.Properties?.[h];if(JSON.stringify(y)!==JSON.stringify(f))return!0}}return!1}function Rn(a){return{"AWS::S3::Bucket":["BucketName"],"AWS::EC2::Instance":["ImageId","InstanceType","KeyName"],"AWS::RDS::DBInstance":["DBInstanceIdentifier","Engine"],"AWS::DynamoDB::Table":["TableName","KeySchema"],"AWS::Lambda::Function":["FunctionName"],"AWS::ECS::Service":["ServiceName"],"AWS::ElasticLoadBalancingV2::LoadBalancer":["Name","Type"]}[a]||[]}function kI(a){let n=[],i=[],s=[];n.push(...a.added);for(let c of a.modified)i.push(c);return s.push(...a.deleted),{safe:n,caution:i,dangerous:s}}function BI(a){if(!a.hasChanges)return{strategy:"skip",reason:"No changes detected"};if(a.deleted.length>0)return{strategy:"replace",reason:"Resources will be deleted"};if(a.added.length>0&&a.modified.length===0)return{strategy:"update",reason:"Only new resources added"};return{strategy:"update",reason:"Resources will be updated"}}function xI(a){let n=a.added.length+a.modified.length+a.deleted.length+a.unchanged.length,i=a.added.length+a.modified.length+a.deleted.length,s=n>0?i/n*100:0;return{total:n,added:a.added.length,modified:a.modified.length,deleted:a.deleted.length,unchanged:a.unchanged.length,changePercentage:s}}var _I={$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 OI(a){let n=[];if(!a.project)n.push("Missing required field: project");else{if(!a.project.name)n.push("Missing required field: project.name");if(!a.project.slug)n.push("Missing required field: project.slug")}if(a.project?.slug&&!/^[a-z0-9-]+$/.test(a.project.slug))n.push("Invalid project.slug: must contain only lowercase letters, numbers, and hyphens");let i=["us-east-1","us-east-2","us-west-1","us-west-2","eu-west-1","eu-west-2","eu-west-3","eu-central-1","ap-southeast-1","ap-southeast-2","ap-northeast-1","ap-northeast-2","sa-east-1","ca-central-1"];if(a.project?.region&&!i.includes(a.project.region))n.push(`Invalid region: ${a.project.region}. Must be one of: ${i.join(", ")}`);if(a.mode&&!["server","serverless"].includes(a.mode))n.push("Invalid mode: must be one of server or serverless");return{valid:n.length===0,errors:n}}var Op={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 cd(){return Op}function LI(){return Op.enabled}function $I(a){let n=cd();if(!n.enabled)return"";switch(a.toLowerCase()){case"dynamodb":return n.dynamodbEndpoint;case"s3":return n.s3Endpoint;case"localstack":case"cloudformation":case"lambda":case"apigateway":case"sns":case"sqs":case"cloudwatch":case"iam":case"sts":return n.localstackEndpoint;default:return n.localstackEndpoint}}function MI(){let a=cd();return{accessKeyId:a.awsAccessKeyId,secretAccessKey:a.awsSecretAccessKey,region:a.awsRegion}}function FI(){let a=cd();if(!a.enabled)return{};return{AWS_ACCESS_KEY_ID:a.awsAccessKeyId,AWS_SECRET_ACCESS_KEY:a.awsSecretAccessKey,AWS_REGION:a.awsRegion,AWS_ENDPOINT_URL:a.localstackEndpoint,LOCALSTACK_ENDPOINT:a.localstackEndpoint,TS_CLOUD_LOCAL:"true"}}class Lp{stacks=new Map;stackEvents=new Map;async createStack(a){let n=`arn:aws:cloudformation:${a.region||"us-east-1"}:123456789012:stack/${a.StackName}/${Date.now()}`;return this.stacks.set(a.StackName,{StackId:n,StackName:a.StackName,StackStatus:"CREATE_IN_PROGRESS",CreationTime:new Date().toISOString(),TemplateBody:a.TemplateBody,Parameters:a.Parameters||[]}),this.addEvent(a.StackName,{EventId:Date.now().toString(),StackName:a.StackName,LogicalResourceId:a.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_IN_PROGRESS"}),setTimeout(()=>{let i=this.stacks.get(a.StackName);if(i)i.StackStatus="CREATE_COMPLETE",this.addEvent(a.StackName,{EventId:(Date.now()+1).toString(),StackName:a.StackName,LogicalResourceId:a.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_COMPLETE"})},100),{StackId:n}}async updateStack(a){let n=this.stacks.get(a.StackName);if(!n)throw Error(`Stack ${a.StackName} does not exist`);return n.StackStatus="UPDATE_IN_PROGRESS",n.TemplateBody=a.TemplateBody||n.TemplateBody,this.addEvent(a.StackName,{EventId:Date.now().toString(),StackName:a.StackName,LogicalResourceId:a.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_IN_PROGRESS"}),setTimeout(()=>{n.StackStatus="UPDATE_COMPLETE",this.addEvent(a.StackName,{EventId:(Date.now()+1).toString(),StackName:a.StackName,LogicalResourceId:a.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_COMPLETE"})},100),{StackId:n.StackId}}async deleteStack(a){let n=this.stacks.get(a.StackName);if(!n)throw Error(`Stack ${a.StackName} does not exist`);n.StackStatus="DELETE_IN_PROGRESS",this.addEvent(a.StackName,{EventId:Date.now().toString(),StackName:a.StackName,LogicalResourceId:a.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_IN_PROGRESS"}),setTimeout(()=>{this.stacks.delete(a.StackName),this.addEvent(a.StackName,{EventId:(Date.now()+1).toString(),StackName:a.StackName,LogicalResourceId:a.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_COMPLETE"})},100)}async describeStacks(a){if(a.StackName){let n=this.stacks.get(a.StackName);if(!n)throw Error(`Stack ${a.StackName} does not exist`);return{Stacks:[n]}}return{Stacks:Array.from(this.stacks.values())}}async describeStackEvents(a){return{StackEvents:this.stackEvents.get(a.StackName)||[]}}addEvent(a,n){if(!this.stackEvents.has(a))this.stackEvents.set(a,[]);this.stackEvents.get(a).unshift(n)}reset(){this.stacks.clear(),this.stackEvents.clear()}}class $p{buckets=new Map;async createBucket(a){return this.buckets.set(a.Bucket,new Map),{Location:`/${a.Bucket}`}}async deleteBucket(a){this.buckets.delete(a.Bucket)}async putObject(a){let n=this.buckets.get(a.Bucket);if(!n)n=new Map,this.buckets.set(a.Bucket,n);return n.set(a.Key,Buffer.from(a.Body||"")),{ETag:`"${Date.now()}"`}}async getObject(a){let n=this.buckets.get(a.Bucket);if(!n)throw Error(`Bucket ${a.Bucket} does not exist`);let i=n.get(a.Key);if(!i)throw Error(`Object ${a.Key} does not exist`);return{Body:i,ContentLength:i.length}}async deleteObject(a){let n=this.buckets.get(a.Bucket);if(n)n.delete(a.Key)}async listObjects(a){let n=this.buckets.get(a.Bucket);if(!n)throw Error(`Bucket ${a.Bucket} does not exist`);return{Contents:Array.from(n.keys()).map((i)=>({Key:i,Size:n.get(i).length,LastModified:new Date().toISOString()}))}}reset(){this.buckets.clear()}}class Mp{tables=new Map;data=new Map;async createTable(a){return this.tables.set(a.TableName,{TableName:a.TableName,KeySchema:a.KeySchema,AttributeDefinitions:a.AttributeDefinitions,TableStatus:"ACTIVE",CreationDateTime:new Date().toISOString()}),this.data.set(a.TableName,new Map),{TableDescription:this.tables.get(a.TableName)}}async deleteTable(a){this.tables.delete(a.TableName),this.data.delete(a.TableName)}async putItem(a){let n=this.data.get(a.TableName);if(!n)n=new Map,this.data.set(a.TableName,n);let i=JSON.stringify(a.Item);n.set(i,a.Item)}async getItem(a){let n=this.data.get(a.TableName);if(!n)return{};let i=JSON.stringify(a.Key),s=n.get(i);return s?{Item:s}:{}}async deleteItem(a){let n=this.data.get(a.TableName);if(n){let i=JSON.stringify(a.Key);n.delete(i)}}async scan(a){let n=this.data.get(a.TableName);if(!n)return{Items:[]};return{Items:Array.from(n.values())}}reset(){this.tables.clear(),this.data.clear()}}function UI(a){return{cloudformation:new Lp,s3:new $p,dynamodb:new Mp}}class Fp{environments=new Map;async createPreviewEnvironment(a){let{branch:n,pr:i,commitSha:s,ttl:c=24,baseConfig:l,region:u="us-east-1"}=a,h=this.generatePreviewId(n,i,s),y=this.generatePreviewName(n,i),f=`preview-${y}`,S=new Date,b=new Date(S.getTime()+c*60*60*1000),C={id:h,name:y,branch:n,pr:i,commitSha:s,createdAt:S,expiresAt:b,status:"creating",stackName:f,region:u,resources:[]};this.environments.set(h,C);try{let T=this.createPreviewConfig(l,y);return C.status="active",C.url=`https://${y}.preview.example.com`,C}catch(T){throw C.status="failed",T}}async destroyPreviewEnvironment(a){let n=this.environments.get(a);if(!n)throw Error(`Preview environment ${a} not found`);n.status="destroying";try{n.status="destroyed",this.environments.delete(a)}catch(i){throw Error(`Failed to destroy preview environment: ${i}`)}}getPreviewEnvironment(a){return this.environments.get(a)}getPreviewEnvironmentByBranch(a){return Array.from(this.environments.values()).find((n)=>n.branch===a)}getPreviewEnvironmentByPR(a){return Array.from(this.environments.values()).find((n)=>n.pr===a)}listPreviewEnvironments(){return Array.from(this.environments.values())}listActivePreviewEnvironments(){return this.listPreviewEnvironments().filter((a)=>a.status==="active")}async cleanupExpiredEnvironments(a={}){let{maxAge:n,keepCount:i,dryRun:s=!1}=a,c=[],l=[],u=new Date,h=this.listPreviewEnvironments().sort((y,f)=>f.createdAt.getTime()-y.createdAt.getTime());for(let y=0;y<h.length;y++){let f=h[y];if(f.status!=="active")continue;let S=!1;if(f.expiresAt<u)S=!0;if(n){if((u.getTime()-f.createdAt.getTime())/3600000>n)S=!0}if(i&&y>=i)S=!0;if(S)if(s)c.push(f.id);else try{await this.destroyPreviewEnvironment(f.id),c.push(f.id)}catch(b){l.push(f.id)}}return{destroyed:c,failed:l}}async updatePreviewEnvironment(a,n){let i=this.environments.get(a);if(!i)throw Error(`Preview environment ${a} not found`);i.commitSha=n,i.status="creating";try{return i.status="active",i}catch(s){throw i.status="failed",s}}async getPreviewEnvironmentsCost(){let a={},n=0;for(let i of this.environments.values())a[i.id]=0,n+=0;return{total:n,byEnvironment:a}}generatePreviewId(a,n,i){let s=a.replace(/[^a-z0-9-]/gi,"-").toLowerCase(),c=i?.substring(0,7)||Date.now().toString();return n?`pr-${n}-${c}`:`${s}-${c}`}generatePreviewName(a,n){let i=a.replace(/[^a-z0-9-]/gi,"-").toLowerCase();return n?`pr-${n}`:i}createPreviewConfig(a,n){return{...a,project:{...a.project,name:`${a.project.name} Preview (${n})`,slug:`${a.project.slug}-preview-${n}`}}}}var QI=new Fp;function HI(a={}){let{workflowName:n="Preview Environment",trigger:i="pull_request",branches:s=["main","develop"],awsRegion:c="us-east-1",awsRole:l,configFile:u="cloud.config.ts",ttl:h=24}=a;return`name: ${n}
|
|
2513
2513
|
|
|
@@ -2761,7 +2761,7 @@ ${n.map((i)=>` • ${i}`).join(`
|
|
|
2761
2761
|
`))}catch(a){console.error(`Failed to save history: ${a}`)}}searchHistory(a){return this.history.commands.filter((n)=>n.includes(a))}clearHistory(){this.history.commands=[],this.historyIndex=0}}class Mf{variables=new Map;workingDirectory=process.cwd();set(a,n){this.variables.set(a,n)}get(a){return this.variables.get(a)}has(a){return this.variables.has(a)}delete(a){this.variables.delete(a)}getAll(){return Object.fromEntries(this.variables)}clear(){this.variables.clear()}setWorkingDirectory(a){this.workingDirectory=a}getWorkingDirectory(){return this.workingDirectory}}class Ff{command={};name(a){return this.command.name=a,this}description(a){return this.command.description=a,this}aliases(...a){return this.command.aliases=a,this}handler(a){return this.command.handler=a,this}autocomplete(a){return this.command.autocomplete=a,this}build(){if(!this.command.name||!this.command.description||!this.command.handler)throw Error("Command must have name, description, and handler");return this.command}}class Uf{entries=[];maxSize;persistFile;trackOutput;constructor(a={}){this.maxSize=a.maxSize||1000,this.persistFile=a.persistFile,this.trackOutput=a.trackOutput||!1}add(a){if(this.entries.push({...a,timestamp:new Date}),this.entries.length>this.maxSize)this.entries=this.entries.slice(-this.maxSize)}getAll(){return[...this.entries]}getRecent(a=10){return this.entries.slice(-a)}search(a){let n=a.toLowerCase();return this.entries.filter((i)=>i.command.toLowerCase().includes(n))}searchByDate(a,n){return this.entries.filter((i)=>i.timestamp>=a&&i.timestamp<=n)}getSuccessful(){return this.entries.filter((a)=>a.success)}getFailed(){return this.entries.filter((a)=>!a.success)}getMostUsed(a=10){let n=new Map;for(let i of this.entries){let s=i.command.split(" ")[0];n.set(s,(n.get(s)||0)+1)}return Array.from(n.entries()).map(([i,s])=>({command:i,count:s})).sort((i,s)=>s.count-i.count).slice(0,a)}getStats(){let a=this.entries.length,n=this.entries.filter((h)=>h.success).length,i=this.entries.filter((h)=>!h.success).length,s=this.entries.filter((h)=>h.duration!==void 0),c=s.length>0?s.reduce((h,y)=>h+(y.duration||0),0)/s.length:0,l=this.getMostUsed(1),u=l.length>0?l[0].command:"N/A";return{total:a,successful:n,failed:i,averageDuration:c,mostUsed:u}}clear(){this.entries=[]}getByIndex(a){if(a<0||a>=this.entries.length)return;return this.entries[a]}removeByIndex(a){if(a>=0&&a<this.entries.length)this.entries.splice(a,1)}async save(){if(!this.persistFile)return;try{let a=await import("node:fs/promises"),n=JSON.stringify(this.entries,null,2);await a.writeFile(this.persistFile,n,"utf-8")}catch(a){throw Error(`Failed to save history: ${a}`)}}async load(){if(!this.persistFile)return;try{let a=await import("node:fs/promises"),n=await a.readFile(this.persistFile,"utf-8"),i=JSON.parse(n);this.entries=i.map((s)=>({...s,timestamp:new Date(s.timestamp)}))}catch{this.entries=[]}}exportJSON(){return JSON.stringify(this.entries,null,2)}exportCSV(){return["Timestamp,Command,Success,Duration",...this.entries.map((a)=>[a.timestamp.toISOString(),`"${a.command.replace(/"/g,'""')}"`,a.success,a.duration||""].join(","))].join(`
|
|
2762
2762
|
`)}importJSON(a){let n=JSON.parse(a).map((i)=>({...i,timestamp:new Date(i.timestamp)}));if(this.entries.push(...n),this.entries.length>this.maxSize)this.entries=this.entries.slice(-this.maxSize)}groupByDate(){let a=new Map;for(let n of this.entries){let i=n.timestamp.toISOString().split("T")[0];if(!a.has(i))a.set(i,[]);a.get(i).push(n)}return a}groupByCommand(){let a=new Map;for(let n of this.entries){let i=n.command.split(" ")[0];if(!a.has(i))a.set(i,[]);a.get(i).push(n)}return a}replay(a){return this.getByIndex(a)?.command}getSuggestions(a,n=5){let i=a.toLowerCase(),s=this.entries.filter((c)=>c.command.toLowerCase().startsWith(i)).map((c)=>c.command);return[...new Set(s)].slice(0,n)}analyzePatterns(){let a=new Map,n=new Map;for(let s of this.entries){let c=s.timestamp.getHours(),l=s.timestamp.getDay();a.set(c,(a.get(c)||0)+1),n.set(l,(n.get(l)||0)+1)}let i=this.entries.length>0?this.getSuccessful().length/this.entries.length:0;return{timeOfDay:a,dayOfWeek:n,successRate:i}}}function cS(a,n={}){let{maxWidth:i=100}=n;if(a.length===0)return"No command history";let s=[];for(let c=0;c<a.length;c++){let l=a[c],u=(c+1).toString().padStart(4),h=l.timestamp.toLocaleString(),y=l.success?"✓":"✗",f=l.command;if(f.length>i-30)f=f.substring(0,i-33)+"...";let S=`${u} ${h} ${y} ${f}`;if(l.duration)S+=` (${l.duration}ms)`;s.push(S)}return s.join(`
|
|
2763
2763
|
`)}function dS(a){let n=[];return n.push("Command History Statistics"),n.push("─".repeat(30)),n.push(`Total commands: ${a.total}`),n.push(`Successful: ${a.successful}`),n.push(`Failed: ${a.failed}`),n.push(`Success rate: ${(a.successful/a.total*100).toFixed(1)}%`),n.push(`Average duration: ${a.averageDuration.toFixed(0)}ms`),n.push(`Most used: ${a.mostUsed}`),n.join(`
|
|
2764
|
-
`)}class Hp{deployments=new Map;async deploy(a,n){let i=this.generateDeploymentId(),s={id:i,regions:n.regions.map((c)=>({region:c.code,stackName:this.getStackName(a,c.code),status:"pending"})),status:"deploying",startTime:new Date};this.deployments.set(i,s);try{let c=n.regions.find((u)=>u.isPrimary)||n.regions[0];await this.deployToRegion(a,c,s);let l=n.regions.filter((u)=>u.code!==c.code);if(await Promise.all(l.map((u)=>this.deployToRegion(a,u,s))),n.globalResources)await this.deployGlobalResources(s,n);if(n.replication)await this.setupReplication(s,n);if(n.failover?.enabled)await this.setupFailover(s,n);return s.status="deployed",s.endTime=new Date,s}catch(c){throw s.status="failed",s.endTime=new Date,c}}async deployToRegion(a,n,i){let s=i.regions.find((c)=>c.region===n.code);if(!s)throw Error(`Region deployment not found: ${n.code}`);s.status="deploying",s.startTime=new Date;try{let c=this.createRegionConfig(a,n);await this.deployStack(s.stackName,c,n.code),s.status="deployed",s.endTime=new Date,s.outputs={stackId:`arn:aws:cloudformation:${n.code}:123456789012:stack/${s.stackName}/guid`,endpoint:`https://${s.stackName}.${n.code}.example.com`}}catch(c){throw s.status="failed",s.endTime=new Date,s.error=c instanceof Error?c.message:String(c),c}}async deployGlobalResources(a,n){let i={};if(n.globalResources?.route53)i.route53=await this.deployRoute53(a,n);if(n.globalResources?.cloudfront)i.cloudfront=await this.deployCloudFront(a,n);if(n.globalResources?.waf)i.waf=await this.deployWAF(a);a.globalResources=i}async deployRoute53(a,n){let i=[],s=[];for(let c of a.regions){if(c.status!=="deployed")continue;let l={id:`health-${c.region}`,endpoint:c.outputs?.endpoint,path:n.failover?.healthCheckPath||"/health",region:c.region};i.push(l);let u={name:"example.com",type:"A",region:c.region,setIdentifier:c.region,healthCheckId:l.id,resourceRecords:[c.outputs?.endpoint]};s.push(u)}return{healthChecks:i,recordSets:s,hostedZoneId:"Z1234567890ABC"}}async deployCloudFront(a,n){return{distributionId:"E1234567890ABC",domainName:"d1234567890abc.cloudfront.net",origins:a.regions.filter((i)=>i.status==="deployed").map((i,s)=>{let c=n.regions[s];return{id:`origin-${i.region}`,domainName:i.outputs?.endpoint,weight:c?.weight||100}}),status:"Deployed"}}async deployWAF(a){return{webAclId:"arn:aws:wafv2:us-east-1:123456789012:global/webacl/test/a1234567-b890-c123-d456-e789012345f6",webAclArn:"arn:aws:wafv2:us-east-1:123456789012:global/webacl/test/a1234567-b890-c123-d456-e789012345f6"}}async setupReplication(a,n){if(n.replication?.s3)await this.setupS3Replication(a);if(n.replication?.dynamodb)await this.setupDynamoDBReplication(a);if(n.replication?.secrets)await this.setupSecretsReplication(a)}async setupS3Replication(a){let n=a.regions.filter((i)=>i.status==="deployed");for(let i=0;i<n.length-1;i++){let s=n[i],c=n[i+1];console.log(`Setting up S3 replication: ${s.region} -> ${c.region}`)}}async setupDynamoDBReplication(a){let n=a.regions.filter((i)=>i.status==="deployed").map((i)=>i.region);console.log(`Setting up DynamoDB global table in regions: ${n.join(", ")}`)}async setupSecretsReplication(a){let n=a.regions.filter((i)=>i.status==="deployed").map((i)=>i.region);console.log(`Setting up Secrets Manager replication in regions: ${n.join(", ")}`)}async setupFailover(a,n){let i=a.regions.find((c,l)=>n.regions[l]?.isPrimary)||a.regions[0],s=a.regions.filter((c)=>c.region!==i.region);console.log(`Setting up failover: primary=${i.region}, secondary=${s.map((c)=>c.region).join(", ")}`)}async destroy(a){let n=this.deployments.get(a);if(!n)throw Error(`Deployment not found: ${a}`);n.status="rolling-back";try{if(n.globalResources)await this.destroyGlobalResources(n.globalResources);await Promise.all(n.regions.map((i)=>this.destroyRegionStack(i))),this.deployments.delete(a)}catch(i){throw n.status="failed",i}}async destroyGlobalResources(a){if(a.waf)console.log("Destroying WAF resources");if(a.cloudfront)console.log("Destroying CloudFront distribution");if(a.route53)console.log("Destroying Route53 resources")}async destroyRegionStack(a){if(a.status!=="deployed")return;a.status="rolling-back";try{console.log(`Destroying stack ${a.stackName} in ${a.region}`),a.status="pending"}catch(n){throw a.status="failed",a.error=n instanceof Error?n.message:String(n),n}}getDeployment(a){return this.deployments.get(a)}listDeployments(){return Array.from(this.deployments.values())}getStackName(a,n){return`${a.project.slug}-${n}`}createRegionConfig(a,n){return{...a,infrastructure:{...a.infrastructure}}}async deployStack(a,n,i){console.log(`Deploying stack ${a} to ${i}`)}generateDeploymentId(){return`deploy-${Date.now()}-${Math.random().toString(36).substring(7)}`}}var lS=new Hp;class Gp{references=[];exports=new Map;addExport(a){let n=`${a.region}:${a.exportName}`;if(!this.exports.has(a.region))this.exports.set(a.region,[]);this.exports.get(a.region).push(a)}getExport(a,n){let i=this.exports.get(a);if(!i)return;return i.find((s)=>s.exportName===n)?.value}createReference(a,n,i,s){let c=`/cross-region/${a}/${i}/${s}`;return this.references.push({sourceRegion:a,targetRegion:n,resourceType:i,resourceId:s,value:c}),c}async resolveReference(a,n){let i=this.references.find((s)=>s.targetRegion===a&&s.value===n);if(!i)throw Error(`Reference not found: ${n}`);return`arn:aws:resource:${i.sourceRegion}:123456789012:${i.resourceType}/${i.resourceId}`}getReferencesForRegion(a){return this.references.filter((n)=>n.sourceRegion===a||n.targetRegion===a)}clear(){this.references=[],this.exports.clear()}}class qp{resources=new Map;register(a){this.resources.set(a.id,a)}get(a){return this.resources.get(a)}getByType(a){return Array.from(this.resources.values()).filter((n)=>n.type===a)}getCloudFrontDistributions(){return this.getByType("cloudfront")}getRoute53HostedZones(){return this.getByType("route53")}getWAFWebACLs(){return this.getByType("waf")}remove(a){this.resources.delete(a)}clear(){this.resources.clear()}}class Vp{pairs=[];addPair(a){this.pairs.push(a)}getPairedRegion(a){let n=this.pairs.find((i)=>i.primary===a||i.secondary===a);if(!n)return;return n.primary===a?n.secondary:n.primary}getAllPairs(){return[...this.pairs]}getReplicatedPairs(){return this.pairs.filter((a)=>a.replicationConfig)}getFailoverPairs(){return this.pairs.filter((a)=>a.failoverConfig?.automatic)}arePaired(a,n){return this.pairs.some((i)=>i.primary===a&&i.secondary===n||i.primary===n&&i.secondary===a)}clear(){this.pairs=[]}}class jp{dependencies=[];addDependency(a){this.dependencies.push(a)}getDependencies(a,n){return this.dependencies.filter((i)=>i.dependentStack===a&&i.dependentRegion===n)}getDependents(a,n){return this.dependencies.filter((i)=>i.dependsOnStack===a&&i.dependsOnRegion===n)}hasDependencies(a,n){return this.getDependencies(a,n).length>0}getDeploymentOrder(a){let n=new Set,i=[],s=(c)=>{let l=`${c.name}:${c.region}`;if(n.has(l))return;n.add(l);let u=this.getDependencies(c.name,c.region);for(let h of u)s({name:h.dependsOnStack,region:h.dependsOnRegion});i.push(c)};for(let c of a)s(c);return i}detectCircularDependencies(){let a=new Set,n=new Set,i=(s,c)=>{let l=`${s}:${c}`;if(n.has(l))return!0;if(a.has(l))return!1;a.add(l),n.add(l);let u=this.getDependencies(s,c);for(let h of u)if(i(h.dependsOnStack,h.dependsOnRegion))return!0;return n.delete(l),!1};for(let s of this.dependencies)if(i(s.dependentStack,s.dependentRegion))return!0;return!1}clear(){this.dependencies=[]}}var uS=new Gp,pS=new qp,gS=new Vp,mS=new jp,Ee=[{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 gi(a){return Ee.find((n)=>n.code===a)}function hS(){return Ee}function fS(a){let n=a.toLowerCase();return Ee.filter((i)=>i.location.toLowerCase().includes(n))}function AS(a){return Ee.filter((n)=>n.compliance.includes(a))}function yS(a){return Ee.filter((n)=>n.pricing.tier===a)}function IS(a){return Ee.some((n)=>n.code===a)}function SS(a){if(a.continent==="North America")return gi("us-east-1");if(a.continent==="Europe")return gi("eu-west-1");if(a.continent==="Asia")return gi("ap-southeast-1");return gi("us-east-1")}function CS(a){let n=[...Ee];if(a.compliance)n=n.filter((i)=>a.compliance.every((s)=>i.compliance.includes(s)));if(a.requiredServices)n=n.filter((i)=>a.requiredServices.every((s)=>i.services[s]));if(a.pricingSensitive)n.sort((i,s)=>i.pricing.multiplier-s.pricing.multiplier);return n.slice(0,5)}function bS(a){let n=gi(a);if(!n)throw Error(`Invalid region: ${a}`);let i=[];for(let s of Ee){if(s.code===a)continue;let c=Ln(n,s),l=Mn(n,s);i.push({primary:n,secondary:s,distance:c,sameContinent:l})}return i.sort((s,c)=>{if(s.sameContinent!==c.sameContinent)return s.sameContinent?1:-1;return s.distance-c.distance}),i.slice(0,3)}function Ln(a,n){let i={"North America":0,"South America":1,Europe:2,Asia:3,Africa:4,Oceania:5},s=Xe(a.location),c=Xe(n.location);return Math.abs((i[s]||0)-(i[c]||0))}function Mn(a,n){return Xe(a.location)===Xe(n.location)}function Xe(a){if(a.includes("USA")||a.includes("Canada"))return"North America";if(a.includes("Europe")||a.includes("Ireland")||a.includes("Germany"))return"Europe";if(a.includes("Asia")||a.includes("Singapore")||a.includes("Japan"))return"Asia";if(a.includes("Brazil"))return"South America";if(a.includes("Australia"))return"Oceania";return"Unknown"}function Qf(a){return`${a.name} (${a.code})`}function ES(a){return a.map((n)=>Qf(n)).join(`
|
|
2764
|
+
`)}class Hp{deployments=new Map;async deploy(a,n){let i=this.generateDeploymentId(),s={id:i,regions:n.regions.map((c)=>({region:c.code,stackName:this.getStackName(a,c.code),status:"pending"})),status:"deploying",startTime:new Date};this.deployments.set(i,s);try{let c=n.regions.find((u)=>u.isPrimary)||n.regions[0];await this.deployToRegion(a,c,s);let l=n.regions.filter((u)=>u.code!==c.code);if(await Promise.all(l.map((u)=>this.deployToRegion(a,u,s))),n.globalResources)await this.deployGlobalResources(s,n);if(n.replication)await this.setupReplication(s,n);if(n.failover?.enabled)await this.setupFailover(s,n);return s.status="deployed",s.endTime=new Date,s}catch(c){throw s.status="failed",s.endTime=new Date,c}}async deployToRegion(a,n,i){let s=i.regions.find((c)=>c.region===n.code);if(!s)throw Error(`Region deployment not found: ${n.code}`);s.status="deploying",s.startTime=new Date;try{let c=this.createRegionConfig(a,n);await this.deployStack(s.stackName,c,n.code),s.status="deployed",s.endTime=new Date,s.outputs={stackId:`arn:aws:cloudformation:${n.code}:123456789012:stack/${s.stackName}/guid`,endpoint:`https://${s.stackName}.${n.code}.example.com`}}catch(c){throw s.status="failed",s.endTime=new Date,s.error=c instanceof Error?c.message:String(c),c}}async deployGlobalResources(a,n){let i={};if(n.globalResources?.route53)i.route53=await this.deployRoute53(a,n);if(n.globalResources?.cloudfront)i.cloudfront=await this.deployCloudFront(a,n);if(n.globalResources?.waf)i.waf=await this.deployWAF(a);a.globalResources=i}async deployRoute53(a,n){let i=[],s=[];for(let c of a.regions){if(c.status!=="deployed")continue;let l={id:`health-${c.region}`,endpoint:c.outputs?.endpoint,path:n.failover?.healthCheckPath||"/health",region:c.region};i.push(l);let u={name:"example.com",type:"A",region:c.region,setIdentifier:c.region,healthCheckId:l.id,resourceRecords:[c.outputs?.endpoint]};s.push(u)}return{healthChecks:i,recordSets:s,hostedZoneId:"Z1234567890ABC"}}async deployCloudFront(a,n){return{distributionId:"E1234567890ABC",domainName:"d1234567890abc.cloudfront.net",origins:a.regions.filter((i)=>i.status==="deployed").map((i,s)=>{let c=n.regions[s];return{id:`origin-${i.region}`,domainName:i.outputs?.endpoint,weight:c?.weight||100}}),status:"Deployed"}}async deployWAF(a){return{webAclId:"arn:aws:wafv2:us-east-1:123456789012:global/webacl/test/a1234567-b890-c123-d456-e789012345f6",webAclArn:"arn:aws:wafv2:us-east-1:123456789012:global/webacl/test/a1234567-b890-c123-d456-e789012345f6"}}async setupReplication(a,n){if(n.replication?.s3)await this.setupS3Replication(a);if(n.replication?.dynamodb)await this.setupDynamoDBReplication(a);if(n.replication?.secrets)await this.setupSecretsReplication(a)}async setupS3Replication(a){let n=a.regions.filter((i)=>i.status==="deployed");for(let i=0;i<n.length-1;i++){let s=n[i],c=n[i+1];console.log(`Setting up S3 replication: ${s.region} -> ${c.region}`)}}async setupDynamoDBReplication(a){let n=a.regions.filter((i)=>i.status==="deployed").map((i)=>i.region);console.log(`Setting up DynamoDB global table in regions: ${n.join(", ")}`)}async setupSecretsReplication(a){let n=a.regions.filter((i)=>i.status==="deployed").map((i)=>i.region);console.log(`Setting up Secrets Manager replication in regions: ${n.join(", ")}`)}async setupFailover(a,n){let i=a.regions.find((c,l)=>n.regions[l]?.isPrimary)||a.regions[0],s=a.regions.filter((c)=>c.region!==i.region);console.log(`Setting up failover: primary=${i.region}, secondary=${s.map((c)=>c.region).join(", ")}`)}async destroy(a){let n=this.deployments.get(a);if(!n)throw Error(`Deployment not found: ${a}`);n.status="rolling-back";try{if(n.globalResources)await this.destroyGlobalResources(n.globalResources);await Promise.all(n.regions.map((i)=>this.destroyRegionStack(i))),this.deployments.delete(a)}catch(i){throw n.status="failed",i}}async destroyGlobalResources(a){if(a.waf)console.log("Destroying WAF resources");if(a.cloudfront)console.log("Destroying CloudFront distribution");if(a.route53)console.log("Destroying Route53 resources")}async destroyRegionStack(a){if(a.status!=="deployed")return;a.status="rolling-back";try{console.log(`Destroying stack ${a.stackName} in ${a.region}`),a.status="pending"}catch(n){throw a.status="failed",a.error=n instanceof Error?n.message:String(n),n}}getDeployment(a){return this.deployments.get(a)}listDeployments(){return Array.from(this.deployments.values())}getStackName(a,n){return`${a.project.slug}-${n}`}createRegionConfig(a,n){return{...a,infrastructure:{...a.infrastructure}}}async deployStack(a,n,i){console.log(`Deploying stack ${a} to ${i}`)}generateDeploymentId(){return`deploy-${Date.now()}-${Math.random().toString(36).substring(7)}`}}var lS=new Hp;class Gp{references=[];exports=new Map;addExport(a){let n=`${a.region}:${a.exportName}`;if(!this.exports.has(a.region))this.exports.set(a.region,[]);this.exports.get(a.region).push(a)}getExport(a,n){let i=this.exports.get(a);if(!i)return;return i.find((s)=>s.exportName===n)?.value}createReference(a,n,i,s){let c=`/cross-region/${a}/${i}/${s}`;return this.references.push({sourceRegion:a,targetRegion:n,resourceType:i,resourceId:s,value:c}),c}async resolveReference(a,n){let i=this.references.find((s)=>s.targetRegion===a&&s.value===n);if(!i)throw Error(`Reference not found: ${n}`);return`arn:aws:resource:${i.sourceRegion}:123456789012:${i.resourceType}/${i.resourceId}`}getReferencesForRegion(a){return this.references.filter((n)=>n.sourceRegion===a||n.targetRegion===a)}clear(){this.references=[],this.exports.clear()}}class qp{resources=new Map;register(a){this.resources.set(a.id,a)}get(a){return this.resources.get(a)}getByType(a){return Array.from(this.resources.values()).filter((n)=>n.type===a)}getCloudFrontDistributions(){return this.getByType("cloudfront")}getRoute53HostedZones(){return this.getByType("route53")}getWAFWebACLs(){return this.getByType("waf")}remove(a){this.resources.delete(a)}clear(){this.resources.clear()}}class Vp{pairs=[];addPair(a){this.pairs.push(a)}getPairedRegion(a){let n=this.pairs.find((i)=>i.primary===a||i.secondary===a);if(!n)return;return n.primary===a?n.secondary:n.primary}getAllPairs(){return[...this.pairs]}getReplicatedPairs(){return this.pairs.filter((a)=>a.replicationConfig)}getFailoverPairs(){return this.pairs.filter((a)=>a.failoverConfig?.automatic)}arePaired(a,n){return this.pairs.some((i)=>i.primary===a&&i.secondary===n||i.primary===n&&i.secondary===a)}clear(){this.pairs=[]}}class jp{dependencies=[];addDependency(a){this.dependencies.push(a)}getDependencies(a,n){return this.dependencies.filter((i)=>i.dependentStack===a&&i.dependentRegion===n)}getDependents(a,n){return this.dependencies.filter((i)=>i.dependsOnStack===a&&i.dependsOnRegion===n)}hasDependencies(a,n){return this.getDependencies(a,n).length>0}getDeploymentOrder(a){let n=new Set,i=[],s=(c)=>{let l=`${c.name}:${c.region}`;if(n.has(l))return;n.add(l);let u=this.getDependencies(c.name,c.region);for(let h of u)s({name:h.dependsOnStack,region:h.dependsOnRegion});i.push(c)};for(let c of a)s(c);return i}detectCircularDependencies(){let a=new Set,n=new Set,i=(s,c)=>{let l=`${s}:${c}`;if(n.has(l))return!0;if(a.has(l))return!1;a.add(l),n.add(l);let u=this.getDependencies(s,c);for(let h of u)if(i(h.dependsOnStack,h.dependsOnRegion))return!0;return n.delete(l),!1};for(let s of this.dependencies)if(i(s.dependentStack,s.dependentRegion))return!0;return!1}clear(){this.dependencies=[]}}var uS=new Gp,pS=new qp,gS=new Vp,mS=new jp,Ee=[{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 mi(a){return Ee.find((n)=>n.code===a)}function hS(){return Ee}function fS(a){let n=a.toLowerCase();return Ee.filter((i)=>i.location.toLowerCase().includes(n))}function AS(a){return Ee.filter((n)=>n.compliance.includes(a))}function yS(a){return Ee.filter((n)=>n.pricing.tier===a)}function IS(a){return Ee.some((n)=>n.code===a)}function SS(a){if(a.continent==="North America")return mi("us-east-1");if(a.continent==="Europe")return mi("eu-west-1");if(a.continent==="Asia")return mi("ap-southeast-1");return mi("us-east-1")}function CS(a){let n=[...Ee];if(a.compliance)n=n.filter((i)=>a.compliance.every((s)=>i.compliance.includes(s)));if(a.requiredServices)n=n.filter((i)=>a.requiredServices.every((s)=>i.services[s]));if(a.pricingSensitive)n.sort((i,s)=>i.pricing.multiplier-s.pricing.multiplier);return n.slice(0,5)}function bS(a){let n=mi(a);if(!n)throw Error(`Invalid region: ${a}`);let i=[];for(let s of Ee){if(s.code===a)continue;let c=Ln(n,s),l=Mn(n,s);i.push({primary:n,secondary:s,distance:c,sameContinent:l})}return i.sort((s,c)=>{if(s.sameContinent!==c.sameContinent)return s.sameContinent?1:-1;return s.distance-c.distance}),i.slice(0,3)}function Ln(a,n){let i={"North America":0,"South America":1,Europe:2,Asia:3,Africa:4,Oceania:5},s=Xe(a.location),c=Xe(n.location);return Math.abs((i[s]||0)-(i[c]||0))}function Mn(a,n){return Xe(a.location)===Xe(n.location)}function Xe(a){if(a.includes("USA")||a.includes("Canada"))return"North America";if(a.includes("Europe")||a.includes("Ireland")||a.includes("Germany"))return"Europe";if(a.includes("Asia")||a.includes("Singapore")||a.includes("Japan"))return"Asia";if(a.includes("Brazil"))return"South America";if(a.includes("Australia"))return"Oceania";return"Unknown"}function Qf(a){return`${a.name} (${a.code})`}function ES(a){return a.map((n)=>Qf(n)).join(`
|
|
2765
2765
|
`)}function vS(){let a={total:Ee.length,byContinent:{},byPricingTier:{}};for(let n of Ee){let i=Xe(n.location);a.byContinent[i]=(a.byContinent[i]||0)+1,a.byPricingTier[n.pricing.tier]=(a.byPricingTier[n.pricing.tier]||0)+1}return a}class zp{accounts=new Map;crossAccountRoles=[];accountMappings=[];registerAccount(a){this.accounts.set(a.id,a)}getAccount(a){return this.accounts.get(a)}getAccountByAlias(a){return Array.from(this.accounts.values()).find((n)=>n.alias===a)}listAccounts(){return Array.from(this.accounts.values())}getAccountsByRole(a){return Array.from(this.accounts.values()).filter((n)=>n.role===a)}createCrossAccountRole(a,n,i,s,c){let l={roleArn:`arn:aws:iam::${n}:role/${i}`,roleName:i,sourceAccountId:a,targetAccountId:n,permissions:s,externalId:c?.externalId,sessionDuration:c?.sessionDuration||3600};return this.crossAccountRoles.push(l),l}getAssumeRolePolicyDocument(a,n){let i={Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${a}:root`},Action:"sts:AssumeRole"}]};if(n)i.Statement[0].Condition={StringEquals:{"sts:ExternalId":n}};return i}generateCrossAccountPolicy(a){return{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:a,Resource:"*"}]}}mapEnvironmentToAccount(a,n,i){this.accountMappings.push({environment:a,accountId:n,region:i})}getAccountForEnvironment(a){return this.accountMappings.find((n)=>n.environment===a)}async assumeRole(a,n,i){return console.log(`Assuming role: ${a} with session: ${n}`),{accessKeyId:"AKIAIOSFODNN7EXAMPLE",secretAccessKey:"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",sessionToken:"token",expiration:new Date(Date.now()+3600000)}}async getCredentialsForAccount(a){let n=this.accounts.get(a);if(!n)throw Error(`Account not found: ${a}`);if(n.assumeRoleArn){let i=await this.assumeRole(n.assumeRoleArn,`ts-cloud-${Date.now()}`);return{accessKeyId:i.accessKeyId,secretAccessKey:i.secretAccessKey,sessionToken:i.sessionToken}}throw Error("No credentials available for account")}listCrossAccountRoles(){return[...this.crossAccountRoles]}getCrossAccountRolesForAccount(a){return this.crossAccountRoles.filter((n)=>n.sourceAccountId===a||n.targetAccountId===a)}async validateAccountAccess(a){try{let n=await this.getCredentialsForAccount(a);return console.log(`Validating access to account: ${a}`),!0}catch{return!1}}async getConsolidatedBilling(){let a={};for(let n of this.accounts.values())a[n.id]=Math.random()*1000;return{totalCost:Object.values(a).reduce((n,i)=>n+i,0),byAccount:a}}clear(){this.accounts.clear(),this.crossAccountRoles=[],this.accountMappings=[]}}class Kp{organizationId;organizationalUnits=new Map;getOrganizationId(){return this.organizationId}setOrganizationId(a){this.organizationId=a}createOrganizationalUnit(a,n){let i={id:`ou-${Date.now()}`,name:a,parentId:n,accounts:[]};return this.organizationalUnits.set(i.id,i),i}getOrganizationalUnit(a){return this.organizationalUnits.get(a)}listOrganizationalUnits(){return Array.from(this.organizationalUnits.values())}addAccountToOU(a,n){let i=this.organizationalUnits.get(a);if(!i)throw Error(`Organizational unit not found: ${a}`);if(!i.accounts.includes(n))i.accounts.push(n)}removeAccountFromOU(a,n){let i=this.organizationalUnits.get(a);if(!i)throw Error(`Organizational unit not found: ${a}`);i.accounts=i.accounts.filter((s)=>s!==n)}getAccountsInOU(a){let n=this.organizationalUnits.get(a);if(!n)return[];return[...n.accounts]}applyServiceControlPolicy(a,n){return{id:`scp-${Date.now()}`,name:"Custom SCP",targetId:a,policyDocument:n}}clear(){this.organizationId=void 0,this.organizationalUnits.clear()}}var TS=new zp,wS=new Kp,Hf={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"}]}},RS={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"]}}}]}}},DS={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 PS(a){return Hf[a]}function NS(a,n){return{Type:"AWS::IAM::Role",Properties:{RoleName:a.roleName,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${a.sourceAccountId}:root`},Action:"sts:AssumeRole",...a.externalId&&{Condition:{StringEquals:{"sts:ExternalId":a.externalId}}}}]},Policies:[{PolicyName:`${a.roleName}Policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:a.permissions,Resource:"*"}]}}],...n&&{ManagedPolicyArns:n},MaxSessionDuration:a.sessionDuration||3600,Tags:[{Key:"ManagedBy",Value:"TS-Cloud"},{Key:"SourceAccount",Value:a.sourceAccountId}]}}}function kS(a){let n=[],i=[],s=a.accounts.filter((y)=>y.role==="management");if(s.length===0)n.push("No management account defined");if(s.length>1)n.push("Multiple management accounts defined");let c=a.accounts.map((y)=>y.email),l=c.filter((y,f)=>c.indexOf(y)!==f);if(l.length>0)n.push(`Duplicate email addresses: ${l.join(", ")}`);let u=a.accounts.map((y)=>y.alias),h=u.filter((y,f)=>u.indexOf(y)!==f);if(h.length>0)n.push(`Duplicate aliases: ${h.join(", ")}`);if(!a.accounts.some((y)=>y.role==="security"))i.push("No dedicated security account - consider adding one for audit logs");if(a.accounts.length<3)i.push("Less than 3 accounts - consider separating environments");if(!a.accounts.some((y)=>y.role==="production"))i.push("No production account defined");return{valid:n.length===0,errors:n,warnings:i}}function BS(a){let n=[];if(n.push(`${a.name}`),n.push("─".repeat(a.name.length)),n.push(a.description),n.push(""),a.organizationalUnits){n.push("Organizational Units:");for(let i of a.organizationalUnits){let s=i.parent?" └─ ":" ";n.push(`${s}${i.name}`)}n.push("")}n.push("Accounts:");for(let i of a.accounts)n.push(` ${i.alias.padEnd(20)} ${i.role.padEnd(15)} ${i.email}`),n.push(` ${"".padEnd(20)} ${i.description}`),n.push("");return n.join(`
|
|
2766
2766
|
`)}function xS(a={}){let{workflowName:n="Deploy",trigger:i="push",branches:s=["main"],environments:c=["production"],awsRegion:l="us-east-1",awsRole:u,bunVersion:h="latest",deployCommand:y="bun run cloud deploy",testCommand:f="bun test",buildCommand:S="bun run build"}=a,b=!!u;return`name: ${n}
|
|
2767
2767
|
|
|
@@ -3597,7 +3597,7 @@ workflows:
|
|
|
3597
3597
|
requires:
|
|
3598
3598
|
- test
|
|
3599
3599
|
${c}
|
|
3600
|
-
`}class Wp{backupPlans=new Map;backupVaults=new Map;restoreJobs=new Map;continuousBackups=new Map;planCounter=0;restoreCounter=0;continuousBackupCounter=0;createVault(a){this.backupVaults.set(a.name,a)}getVault(a){return this.backupVaults.get(a)}createBackupPlan(a){let n=`backup-plan-${Date.now()}-${this.planCounter++}`,i={id:n,...a};return this.backupPlans.set(n,i),i}getBackupPlan(a){return this.backupPlans.get(a)}listBackupPlans(){return Array.from(this.backupPlans.values())}createRDSBackupPlan(a){let{dbInstanceArn:n,schedule:i="0 2 * * *",retentionDays:s=7,vaultName:c="default-vault"}=a;return this.createBackupPlan({name:"RDS Daily Backup",schedule:i,retentionDays:s,vaultName:c,resources:[{resourceArn:n,resourceType:"rds",region:"us-east-1"}],lifecycle:{moveTocoldStorageAfterDays:30,deleteAfterDays:s}})}createDynamoDBBackupPlan(a){let{tableArn:n,schedule:i="0 3 * * *",retentionDays:s=35,crossRegionCopy:c}=a;return this.createBackupPlan({name:"DynamoDB Daily Backup",schedule:i,retentionDays:s,vaultName:"dynamodb-vault",resources:[{resourceArn:n,resourceType:"dynamodb",region:"us-east-1"}],lifecycle:{deleteAfterDays:s},tags:c?{CrossRegionCopy:c.join(",")}:void 0})}createEFSBackupPlan(a){let{fileSystemArn:n,schedule:i="0 1 * * *",retentionDays:s=30}=a;return this.createBackupPlan({name:"EFS Daily Backup",schedule:i,retentionDays:s,vaultName:"efs-vault",resources:[{resourceArn:n,resourceType:"efs",region:"us-east-1"}],lifecycle:{deleteAfterDays:s}})}enableContinuousBackup(a,n=35){let i=`continuous-backup-${Date.now()}-${this.continuousBackupCounter++}`,s={id:i,resourceId:a,enabled:!0,retentionDays:n};return this.continuousBackups.set(i,s),s}getContinuousBackup(a){return this.continuousBackups.get(a)}enablePointInTimeRecovery(a,n){return{enabled:!0,earliestRestorableTime:new Date(Date.now()-604800000),latestRestorableTime:new Date}}async restoreFromBackup(a){let{backupId:n,resourceType:i,targetRegion:s}=a,c={id:`restore-${Date.now()}-${this.restoreCounter++}`,backupId:n,resourceType:i,status:"pending",startTime:new Date,targetRegion:s};return this.restoreJobs.set(c.id,c),setTimeout(()=>{c.status="running"},100),setTimeout(()=>{c.status="completed",c.endTime=new Date},1000),c}async restoreToPointInTime(a){let{sourceResourceArn:n,targetResourceName:i,restoreTime:s,resourceType:c}=a,l={id:`pitr-${Date.now()}-${this.restoreCounter++}`,backupId:`pitr-${s.getTime()}`,resourceType:c,status:"pending",startTime:new Date};return this.restoreJobs.set(l.id,l),console.log(`Restoring ${c} from ${n} to ${i} at ${s.toISOString()}`),setTimeout(()=>{l.status="completed",l.endTime=new Date},2000),l}getRestoreJob(a){return this.restoreJobs.get(a)}listRestoreJobs(){return Array.from(this.restoreJobs.values())}setupCrossRegionReplication(a){let{sourceVault:n,sourceRegion:i,targetRegions:s}=a;console.log("Setting up cross-region replication:"),console.log(` Source: ${n} in ${i}`),console.log(` Targets: ${s.join(", ")}`)}generateBackupVaultCF(a){return{Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:a.name,...a.encryptionKeyArn&&{EncryptionKeyArn:a.encryptionKeyArn},...a.accessPolicy&&{AccessPolicy:a.accessPolicy}}}}generateBackupPlanCF(a){return{Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:a.name,BackupPlanRule:[{RuleName:"DailyBackup",TargetBackupVault:a.vaultName,ScheduleExpression:`cron(${a.schedule})`,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:a.lifecycle?{...a.lifecycle.moveTocoldStorageAfterDays&&{MoveToColdStorageAfterDays:a.lifecycle.moveTocoldStorageAfterDays},...a.lifecycle.deleteAfterDays&&{DeleteAfterDays:a.lifecycle.deleteAfterDays}}:void 0}]},...a.tags&&{BackupPlanTags:a.tags}}}}generateBackupSelectionCF(a){return{Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:{Ref:`BackupPlan${a.id}`},BackupSelection:{SelectionName:`${a.name}Selection`,IamRoleArn:"arn:aws:iam::123456789012:role/service-role/AWSBackupDefaultServiceRole",Resources:a.resources.map((n)=>n.resourceArn)}}}}clear(){this.backupPlans.clear(),this.backupVaults.clear(),this.restoreJobs.clear(),this.continuousBackups.clear(),this.planCounter=0,this.restoreCounter=0,this.continuousBackupCounter=0}}var KS=new Wp;class Jp{drPlans=new Map;failoverTests=new Map;planCounter=0;testCounter=0;createDRPlan(a){let n=`dr-plan-${Date.now()}-${this.planCounter++}`,i={id:n,...a};return this.drPlans.set(n,i),i}createRDSDRPlan(a){let{primaryDbArn:n,secondaryDbArn:i,primaryRegion:s,secondaryRegion:c,rto:l=60,rpo:u=5}=a;return this.createDRPlan({name:"RDS Multi-Region DR",primaryRegion:s,secondaryRegion:c,rto:l,rpo:u,resources:[{resourceId:"primary-db",resourceType:"rds",primaryArn:n,secondaryArn:i,replicationEnabled:!0}],runbook:this.generateRDSRunbook(s,c),testSchedule:"0 0 1 * *"})}createDynamoDBDRPlan(a){let{tableArn:n,regions:i,rto:s=15,rpo:c=1}=a;return this.createDRPlan({name:"DynamoDB Global Tables DR",primaryRegion:i[0],secondaryRegion:i[1],rto:s,rpo:c,resources:[{resourceId:"dynamodb-table",resourceType:"dynamodb",primaryArn:n,replicationEnabled:!0}],runbook:this.generateDynamoDBRunbook(i)})}generateRDSRunbook(a,n){return{estimatedDuration:60,requiredApprovals:["cto","engineering-lead"],steps:[{order:1,name:"Verify Primary Database Failure",description:"Confirm that the primary database is truly unavailable and not experiencing temporary issues",action:"aws rds describe-db-instances --region "+a,automatable:!0,estimatedDuration:2,rollbackable:!1},{order:2,name:"Check Replication Lag",description:"Verify that the read replica is up to date",action:"Check ReplicaLag metric in CloudWatch",automatable:!0,estimatedDuration:1,rollbackable:!1},{order:3,name:"Promote Read Replica",description:"Promote the read replica in the secondary region to be the new primary",action:"aws rds promote-read-replica --db-instance-identifier replica --region "+n,automatable:!0,estimatedDuration:10,rollbackable:!1},{order:4,name:"Update DNS Records",description:"Update Route53 records to point to the new primary database",action:"Update Route53 failover record set",automatable:!0,estimatedDuration:5,rollbackable:!0},{order:5,name:"Update Application Configuration",description:"Update application connection strings if needed",action:"Deploy configuration update to ECS/Lambda",automatable:!0,estimatedDuration:10,rollbackable:!0},{order:6,name:"Verify Application Connectivity",description:"Test that applications can connect to the new primary",action:"Run smoke tests",automatable:!0,estimatedDuration:5,rollbackable:!1},{order:7,name:"Monitor for Issues",description:"Monitor CloudWatch metrics and application logs",action:"Monitor for 30 minutes",automatable:!1,estimatedDuration:30,rollbackable:!1}]}}generateDynamoDBRunbook(a){return{estimatedDuration:15,steps:[{order:1,name:"Verify Primary Region Failure",description:"Confirm that the primary region is experiencing an outage",action:"Check AWS Health Dashboard",automatable:!0,estimatedDuration:2,rollbackable:!1},{order:2,name:"Update Route53 Failover",description:"Update Route53 to direct traffic to secondary region",action:"Update Route53 health check and failover records",automatable:!0,estimatedDuration:5,rollbackable:!0},{order:3,name:"Update Application Endpoints",description:"Update Lambda/ECS to use secondary region DynamoDB endpoint",action:"Deploy configuration update",automatable:!0,estimatedDuration:5,rollbackable:!0},{order:4,name:"Verify Data Consistency",description:"Verify that data is consistent in secondary region",action:"Run data validation queries",automatable:!0,estimatedDuration:3,rollbackable:!1}]}}async executeFailover(a,n=!1){let i=this.drPlans.get(a);if(!i)throw Error(`DR plan not found: ${a}`);let s=Date.now(),c=0;console.log(`${n?"[DRY RUN] ":""}Executing failover for plan: ${i.name}`),console.log(`Primary: ${i.primaryRegion} -> Secondary: ${i.secondaryRegion}`),console.log(`RTO: ${i.rto} minutes, RPO: ${i.rpo} minutes`),console.log("");for(let l of i.runbook.steps){if(console.log(`Step ${l.order}: ${l.name}`),console.log(` ${l.description}`),console.log(` Action: ${l.action}`),console.log(` Estimated: ${l.estimatedDuration} minutes`),n)console.log(" [SKIPPED - DRY RUN]");else if(l.automatable)console.log(" [AUTOMATED]");else console.log(" [MANUAL - WAITING]");c++,console.log("")}return{success:!0,duration:(Date.now()-s)/1000/60,completedSteps:c}}scheduleFailoverTest(a,n){let i={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:a,status:"scheduled",startTime:n};return this.failoverTests.set(i.id,i),i}async runFailoverTest(a){let n=this.drPlans.get(a);if(!n)throw Error(`DR plan not found: ${a}`);let i={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:a,status:"running",startTime:new Date,results:[]};this.failoverTests.set(i.id,i),console.log(`Running failover test for plan: ${n.name}`),console.log("This is a non-destructive test using test resources"),console.log("");for(let s of n.runbook.steps){let c=Date.now();console.log(`Testing step ${s.order}: ${s.name}`);let l={step:s.name,status:"success",duration:(Date.now()-c)/1000,message:`Successfully validated step ${s.order}`};i.results.push(l)}return i.status="completed",i.endTime=new Date,i}getDRPlan(a){return this.drPlans.get(a)}listDRPlans(){return Array.from(this.drPlans.values())}getFailoverTest(a){return this.failoverTests.get(a)}listFailoverTests(){return Array.from(this.failoverTests.values())}validateDRPlan(a){let n=[],i=[];if(a.rto<a.rpo)i.push("RTO cannot be less than RPO");if(a.rto>240)n.push("RTO exceeds 4 hours - consider improving recovery time");if(a.rpo>60)n.push("RPO exceeds 1 hour - consider more frequent backups");if(a.resources.length===0)i.push("No resources defined in DR plan");for(let l of a.resources){if(!l.replicationEnabled)n.push(`Resource ${l.resourceId} does not have replication enabled`);if(!l.secondaryArn&&l.resourceType!=="dynamodb")n.push(`Resource ${l.resourceId} does not have secondary resource defined`)}if(a.runbook.steps.length===0)i.push("No recovery steps defined in runbook");let s=a.runbook.steps.reduce((l,u)=>l+u.estimatedDuration,0);if(s>a.rto)n.push(`Estimated recovery duration (${s}m) exceeds RTO (${a.rto}m)`);let c=a.runbook.steps.filter((l)=>!l.automatable);if(c.length>0)n.push(`${c.length} manual steps in runbook - consider automation`);return{valid:i.length===0,warnings:n,errors:i}}clear(){this.drPlans.clear(),this.failoverTests.clear(),this.planCounter=0,this.testCounter=0}}var WS=new Jp;class Xp{configRules=new Map;configRecorders=new Map;deliveryChannels=new Map;ruleCounter=0;createConfigRecorder(a){return this.configRecorders.set(a.name,a),a}createDeliveryChannel(a){return this.deliveryChannels.set(a.name,a),a}createConfigRule(a){let n=`config-rule-${Date.now()}-${this.ruleCounter++}`,i={id:n,...a};return this.configRules.set(n,i),i}createS3EncryptionRule(){return this.createConfigRule({name:"s3-bucket-server-side-encryption-enabled",description:"Checks that S3 buckets have server-side encryption enabled",source:"AWS_MANAGED",identifier:"S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED",scope:{complianceResourceTypes:["AWS::S3::Bucket"]}})}createS3PublicAccessBlockRule(){return this.createConfigRule({name:"s3-bucket-public-read-prohibited",description:"Checks that S3 buckets do not allow public read access",source:"AWS_MANAGED",identifier:"S3_BUCKET_PUBLIC_READ_PROHIBITED",scope:{complianceResourceTypes:["AWS::S3::Bucket"]}})}createS3VersioningRule(){return this.createConfigRule({name:"s3-bucket-versioning-enabled",description:"Checks whether versioning is enabled for S3 buckets",source:"AWS_MANAGED",identifier:"S3_BUCKET_VERSIONING_ENABLED",scope:{complianceResourceTypes:["AWS::S3::Bucket"]}})}createRdsEncryptionRule(){return this.createConfigRule({name:"rds-storage-encrypted",description:"Checks whether storage encryption is enabled for RDS DB instances",source:"AWS_MANAGED",identifier:"RDS_STORAGE_ENCRYPTED",scope:{complianceResourceTypes:["AWS::RDS::DBInstance"]}})}createRdsSnapshotEncryptionRule(){return this.createConfigRule({name:"rds-snapshots-public-prohibited",description:"Checks if RDS snapshots are public",source:"AWS_MANAGED",identifier:"RDS_SNAPSHOTS_PUBLIC_PROHIBITED",scope:{complianceResourceTypes:["AWS::RDS::DBSnapshot","AWS::RDS::DBClusterSnapshot"]}})}createRdsBackupRule(a=7){return this.createConfigRule({name:"db-backup-enabled",description:"Checks whether RDS DB instances have backups enabled",source:"AWS_MANAGED",identifier:"DB_BACKUP_ENABLED",inputParameters:{backupRetentionPeriod:a},scope:{complianceResourceTypes:["AWS::RDS::DBInstance"]}})}createEc2InstanceProfileRule(){return this.createConfigRule({name:"ec2-instance-managed-by-systems-manager",description:"Checks if EC2 instances are managed by Systems Manager",source:"AWS_MANAGED",identifier:"EC2_INSTANCE_MANAGED_BY_SSM",scope:{complianceResourceTypes:["AWS::EC2::Instance"]}})}createEbsEncryptionRule(){return this.createConfigRule({name:"encrypted-volumes",description:"Checks whether EBS volumes are encrypted",source:"AWS_MANAGED",identifier:"ENCRYPTED_VOLUMES",scope:{complianceResourceTypes:["AWS::EC2::Volume"]}})}createIamPasswordPolicyRule(){return this.createConfigRule({name:"iam-password-policy",description:"Checks whether the IAM password policy meets specified requirements",source:"AWS_MANAGED",identifier:"IAM_PASSWORD_POLICY",inputParameters:{RequireUppercaseCharacters:!0,RequireLowercaseCharacters:!0,RequireSymbols:!0,RequireNumbers:!0,MinimumPasswordLength:14,PasswordReusePrevention:24,MaxPasswordAge:90}})}createIamMfaRule(){return this.createConfigRule({name:"iam-user-mfa-enabled",description:"Checks whether IAM users have MFA enabled",source:"AWS_MANAGED",identifier:"IAM_USER_MFA_ENABLED"})}createRootAccountMfaRule(){return this.createConfigRule({name:"root-account-mfa-enabled",description:"Checks whether the root account has MFA enabled",source:"AWS_MANAGED",identifier:"ROOT_ACCOUNT_MFA_ENABLED"})}createVpcFlowLogsRule(){return this.createConfigRule({name:"vpc-flow-logs-enabled",description:"Checks whether VPC Flow Logs is enabled",source:"AWS_MANAGED",identifier:"VPC_FLOW_LOGS_ENABLED",scope:{complianceResourceTypes:["AWS::EC2::VPC"]}})}createCloudTrailEnabledRule(){return this.createConfigRule({name:"cloudtrail-enabled",description:"Checks whether CloudTrail is enabled",source:"AWS_MANAGED",identifier:"CLOUD_TRAIL_ENABLED",maxExecutionFrequency:"TwentyFour_Hours"})}createCloudWatchAlarmRule(){return this.createConfigRule({name:"cloudwatch-alarm-action-check",description:"Checks whether CloudWatch alarms have actions configured",source:"AWS_MANAGED",identifier:"CLOUDWATCH_ALARM_ACTION_CHECK",inputParameters:{alarmActionRequired:!0,insufficientDataActionRequired:!1,okActionRequired:!1},scope:{complianceResourceTypes:["AWS::CloudWatch::Alarm"]}})}createCustomLambdaRule(a){return this.createConfigRule({name:a.name,description:a.description,source:"CUSTOM_LAMBDA",lambdaFunctionArn:a.lambdaFunctionArn,scope:a.resourceTypes?{complianceResourceTypes:a.resourceTypes}:void 0,maxExecutionFrequency:a.maxExecutionFrequency,inputParameters:a.inputParameters})}createCompliancePreset(a){let n=[];switch(a){case"hipaa":n.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createRdsBackupRule(7),this.createVpcFlowLogsRule());break;case"pci-dss":n.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createIamMfaRule(),this.createRootAccountMfaRule(),this.createVpcFlowLogsRule());break;case"sox":n.push(this.createS3VersioningRule(),this.createCloudTrailEnabledRule(),this.createRdsBackupRule(30),this.createIamPasswordPolicyRule());break;case"gdpr":n.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createRdsSnapshotEncryptionRule());break;case"basic":n.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamMfaRule(),this.createRootAccountMfaRule());break}return n}getConfigRule(a){return this.configRules.get(a)}listConfigRules(){return Array.from(this.configRules.values())}getConfigRecorder(a){return this.configRecorders.get(a)}listConfigRecorders(){return Array.from(this.configRecorders.values())}getDeliveryChannel(a){return this.deliveryChannels.get(a)}listDeliveryChannels(){return Array.from(this.deliveryChannels.values())}generateConfigRuleCF(a){let n={Type:"AWS::Config::ConfigRule",Properties:{ConfigRuleName:a.name,Description:a.description,Source:{Owner:a.source==="AWS_MANAGED"?"AWS":"CUSTOM_LAMBDA"}}};if(a.source==="AWS_MANAGED"&&a.identifier)n.Properties.Source.SourceIdentifier=a.identifier;if(a.source==="CUSTOM_LAMBDA"&&a.lambdaFunctionArn)n.Properties.Source.SourceIdentifier=a.lambdaFunctionArn,n.Properties.Source.SourceDetails=[{EventSource:"aws.config",MessageType:"ConfigurationItemChangeNotification"}];if(a.inputParameters)n.Properties.InputParameters=JSON.stringify(a.inputParameters);if(a.scope){if(n.Properties.Scope={},a.scope.complianceResourceTypes)n.Properties.Scope.ComplianceResourceTypes=a.scope.complianceResourceTypes;if(a.scope.tagKey)n.Properties.Scope.TagKey=a.scope.tagKey;if(a.scope.tagValue)n.Properties.Scope.TagValue=a.scope.tagValue}if(a.maxExecutionFrequency)n.Properties.MaximumExecutionFrequency=a.maxExecutionFrequency;return n}generateConfigRecorderCF(a){return{Type:"AWS::Config::ConfigurationRecorder",Properties:{Name:a.name,RoleArn:a.roleArn,RecordingGroup:a.recordingGroup||{AllSupported:!0,IncludeGlobalResourceTypes:!0}}}}generateDeliveryChannelCF(a){return{Type:"AWS::Config::DeliveryChannel",Properties:{Name:a.name,S3BucketName:a.s3BucketName,...a.s3KeyPrefix&&{S3KeyPrefix:a.s3KeyPrefix},...a.snsTopicArn&&{SnsTopicARN:a.snsTopicArn},...a.configSnapshotDeliveryProperties&&{ConfigSnapshotDeliveryProperties:a.configSnapshotDeliveryProperties}}}}clear(){this.configRules.clear(),this.configRecorders.clear(),this.deliveryChannels.clear(),this.ruleCounter=0}}var JS=new Xp;class Yp{trails=new Map;trailCounter=0;createTrail(a){let n=`trail-${Date.now()}-${this.trailCounter++}`,i={id:n,...a};return this.trails.set(n,i),i}createOrganizationTrail(a){return this.createTrail({name:a.name,s3BucketName:a.s3BucketName,s3KeyPrefix:"organization-trail",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:a.kmsKeyId,cloudWatchLogsLogGroupArn:a.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:a.cloudWatchLogsRoleArn})}createSecurityAuditTrail(a){return this.createTrail({name:a.name,s3BucketName:a.s3BucketName,s3KeyPrefix:"security-audit",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:a.kmsKeyId,cloudWatchLogsLogGroupArn:a.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:a.cloudWatchLogsRoleArn,eventSelectors:[{readWriteType:"All",includeManagementEvents:!0,excludeManagementEventSources:[]}],insightSelectors:[{insightType:"ApiCallRateInsight"},{insightType:"ApiErrorRateInsight"}]})}createDataEventsTrail(a){let n=[];if(a.s3DataBuckets&&a.s3DataBuckets.length>0)n.push({type:"AWS::S3::Object",values:a.s3DataBuckets.map((i)=>`arn:aws:s3:::${i}/*`)});if(a.lambdaFunctions&&a.lambdaFunctions.length>0)n.push({type:"AWS::Lambda::Function",values:a.lambdaFunctions});return this.createTrail({name:a.name,s3BucketName:a.s3BucketName,s3KeyPrefix:"data-events",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"All",includeManagementEvents:!1,dataResources:n}]})}createAdvancedTrail(a){return this.createTrail({name:a.name,s3BucketName:a.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,advancedEventSelectors:a.selectors})}createReadOnlyTrail(a){return this.createTrail({name:a.name,s3BucketName:a.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"ReadOnly",includeManagementEvents:!0}]})}createWriteOnlyTrail(a){return this.createTrail({name:a.name,s3BucketName:a.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"WriteOnly",includeManagementEvents:!0}]})}getTrail(a){return this.trails.get(a)}listTrails(){return Array.from(this.trails.values())}generateTrailCF(a){let n={Type:"AWS::CloudTrail::Trail",Properties:{TrailName:a.name,S3BucketName:a.s3BucketName,IsLogging:!0,IncludeGlobalServiceEvents:a.includeGlobalServiceEvents??!0,IsMultiRegionTrail:a.isMultiRegionTrail??!0,EnableLogFileValidation:a.enableLogFileValidation??!0}};if(a.s3KeyPrefix)n.Properties.S3KeyPrefix=a.s3KeyPrefix;if(a.cloudWatchLogsLogGroupArn)n.Properties.CloudWatchLogsLogGroupArn=a.cloudWatchLogsLogGroupArn;if(a.cloudWatchLogsRoleArn)n.Properties.CloudWatchLogsRoleArn=a.cloudWatchLogsRoleArn;if(a.snsTopicName)n.Properties.SnsTopicName=a.snsTopicName;if(a.kmsKeyId)n.Properties.KMSKeyId=a.kmsKeyId;if(a.eventSelectors)n.Properties.EventSelectors=a.eventSelectors.map((i)=>({ReadWriteType:i.readWriteType,IncludeManagementEvents:i.includeManagementEvents??!0,...i.dataResources&&{DataResources:i.dataResources.map((s)=>({Type:s.type,Values:s.values}))},...i.excludeManagementEventSources&&{ExcludeManagementEventSources:i.excludeManagementEventSources}}));if(a.insightSelectors)n.Properties.InsightSelectors=a.insightSelectors.map((i)=>({InsightType:i.insightType}));if(a.advancedEventSelectors)n.Properties.AdvancedEventSelectors=a.advancedEventSelectors.map((i)=>({Name:i.name,FieldSelectors:i.fieldSelectors.map((s)=>({Field:s.field,...s.equals&&{Equals:s.equals},...s.startsWith&&{StartsWith:s.startsWith},...s.endsWith&&{EndsWith:s.endsWith},...s.notEquals&&{NotEquals:s.notEquals},...s.notStartsWith&&{NotStartsWith:s.notStartsWith},...s.notEndsWith&&{NotEndsWith:s.notEndsWith}}))}));return n}generateBucketPolicy(a,n){return{Version:"2012-10-17",Statement:[{Sid:"AWSCloudTrailAclCheck",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:GetBucketAcl",Resource:`arn:aws:s3:::${a}`},{Sid:"AWSCloudTrailWrite",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:PutObject",Resource:n.map((i)=>`arn:aws:s3:::${a}/AWSLogs/${i}/*`),Condition:{StringEquals:{"s3:x-amz-acl":"bucket-owner-full-control"}}}]}}clear(){this.trails.clear(),this.trailCounter=0}}var XS=new Yp;class Zp{detectors=new Map;threatIntelSets=new Map;ipSets=new Map;filters=new Map;detectorCounter=0;threatIntelCounter=0;ipSetCounter=0;filterCounter=0;createDetector(a){let n=`detector-${Date.now()}-${this.detectorCounter++}`,i={id:n,...a};return this.detectors.set(n,i),i}createComprehensiveDetector(){return this.createDetector({enable:!0,findingPublishingFrequency:"FIFTEEN_MINUTES",dataSources:{s3Logs:{enable:!0},kubernetes:{auditLogs:{enable:!0}},malwareProtection:{scanEc2InstanceWithFindings:{ebsVolumes:{enable:!0}}}},features:[{name:"S3_DATA_EVENTS",status:"ENABLED"},{name:"EKS_AUDIT_LOGS",status:"ENABLED"},{name:"EBS_MALWARE_PROTECTION",status:"ENABLED"},{name:"RDS_LOGIN_EVENTS",status:"ENABLED"},{name:"LAMBDA_NETWORK_LOGS",status:"ENABLED"}]})}createBasicDetector(){return this.createDetector({enable:!0,findingPublishingFrequency:"SIX_HOURS"})}createThreatIntelSet(a){let n=`threat-intel-${Date.now()}-${this.threatIntelCounter++}`,i={id:n,...a};return this.threatIntelSets.set(n,i),i}createIPSet(a){let n=`ip-set-${Date.now()}-${this.ipSetCounter++}`,i={id:n,...a};return this.ipSets.set(n,i),i}createFindingFilter(a){let n=`filter-${Date.now()}-${this.filterCounter++}`,i={id:n,...a};return this.filters.set(n,i),i}createLowSeverityArchiveFilter(a){return this.createFindingFilter({detectorId:a,name:"archive-low-severity",description:"Automatically archive low severity findings",action:"ARCHIVE",rank:1,findingCriteria:{criterion:{severity:{lt:4}}}})}createFindingTypeFilter(a,n,i){return this.createFindingFilter({detectorId:a,name:`filter-finding-types-${i.toLowerCase()}`,description:`${i==="ARCHIVE"?"Archive":"Keep"} specific finding types`,action:i,rank:2,findingCriteria:{criterion:{type:{eq:n}}}})}createTrustedIPFilter(a,n){return this.createFindingFilter({detectorId:a,name:"trusted-ip-addresses",description:"Archive findings from trusted IP addresses",action:"ARCHIVE",rank:3,findingCriteria:{criterion:{"resource.instanceDetails.networkInterfaces.privateIpAddress":{eq:n}}}})}getDetector(a){return this.detectors.get(a)}listDetectors(){return Array.from(this.detectors.values())}getThreatIntelSet(a){return this.threatIntelSets.get(a)}listThreatIntelSets(){return Array.from(this.threatIntelSets.values())}getIPSet(a){return this.ipSets.get(a)}listIPSets(){return Array.from(this.ipSets.values())}getFindingFilter(a){return this.filters.get(a)}listFindingFilters(){return Array.from(this.filters.values())}generateDetectorCF(a){let n={Type:"AWS::GuardDuty::Detector",Properties:{Enable:a.enable}};if(a.findingPublishingFrequency)n.Properties.FindingPublishingFrequency=a.findingPublishingFrequency;if(a.dataSources){if(n.Properties.DataSources={},a.dataSources.s3Logs)n.Properties.DataSources.S3Logs={Enable:a.dataSources.s3Logs.enable};if(a.dataSources.kubernetes)n.Properties.DataSources.Kubernetes={AuditLogs:{Enable:a.dataSources.kubernetes.auditLogs.enable}};if(a.dataSources.malwareProtection)n.Properties.DataSources.MalwareProtection={ScanEc2InstanceWithFindings:{EbsVolumes:{Enable:a.dataSources.malwareProtection.scanEc2InstanceWithFindings.ebsVolumes.enable}}}}if(a.features)n.Properties.Features=a.features.map((i)=>({Name:i.name,Status:i.status,...i.additionalConfiguration&&{AdditionalConfiguration:i.additionalConfiguration}}));return n}generateThreatIntelSetCF(a){return{Type:"AWS::GuardDuty::ThreatIntelSet",Properties:{DetectorId:a.detectorId,Name:a.name,Format:a.format,Location:a.location,Activate:a.activate}}}generateIPSetCF(a){return{Type:"AWS::GuardDuty::IPSet",Properties:{DetectorId:a.detectorId,Name:a.name,Format:a.format,Location:a.location,Activate:a.activate}}}generateFilterCF(a){return{Type:"AWS::GuardDuty::Filter",Properties:{DetectorId:a.detectorId,Name:a.name,Description:a.description,Action:a.action,Rank:a.rank,FindingCriteria:{Criterion:a.findingCriteria.criterion}}}}clear(){this.detectors.clear(),this.threatIntelSets.clear(),this.ipSets.clear(),this.filters.clear(),this.detectorCounter=0,this.threatIntelCounter=0,this.ipSetCounter=0,this.filterCounter=0}}var YS=new Zp;class Br{hubs=new Map;hubCounter=0;ruleCounter=0;static Standards={AWS_FOUNDATIONAL_SECURITY:{arn:"arn:aws:securityhub:::ruleset/aws-foundational-security-best-practices/v/1.0.0",name:"AWS Foundational Security Best Practices",description:"AWS recommended security best practices"},CIS_AWS_FOUNDATIONS_1_2:{arn:"arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0",name:"CIS AWS Foundations Benchmark v1.2.0",description:"CIS AWS Foundations Benchmark v1.2.0"},CIS_AWS_FOUNDATIONS_1_4:{arn:"arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.4.0",name:"CIS AWS Foundations Benchmark v1.4.0",description:"CIS AWS Foundations Benchmark v1.4.0"},PCI_DSS:{arn:"arn:aws:securityhub:us-east-1::standards/pci-dss/v/3.2.1",name:"PCI DSS v3.2.1",description:"Payment Card Industry Data Security Standard"},NIST_800_53:{arn:"arn:aws:securityhub:us-east-1::standards/nist-800-53/v/5.0.0",name:"NIST SP 800-53 Rev. 5",description:"NIST Special Publication 800-53 Revision 5"}};createHub(a){let n=`hub-${Date.now()}-${this.hubCounter++}`,i={id:n,...a};return this.hubs.set(n,i),i}createComprehensiveHub(){return this.createHub({enable:!0,controlFindingGenerator:"SECURITY_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...Br.Standards.AWS_FOUNDATIONAL_SECURITY,enabled:!0},{id:"cis-1-4",...Br.Standards.CIS_AWS_FOUNDATIONS_1_4,enabled:!0},{id:"pci-dss",...Br.Standards.PCI_DSS,enabled:!0}]})}createBasicHub(){return this.createHub({enable:!0,controlFindingGenerator:"STANDARD_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...Br.Standards.AWS_FOUNDATIONAL_SECURITY,enabled:!0}]})}createLowSeveritySuppressionRule(){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:"Suppress Low Severity Informational Findings",description:"Automatically suppress informational findings",actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"SUPPRESSED"},note:{text:"Automatically suppressed low severity finding",updatedBy:"SecurityHub Automation"}}}],criteria:{severityLabel:[{value:"INFORMATIONAL",comparison:"EQUALS"}],recordState:[{value:"ACTIVE",comparison:"EQUALS"}]},ruleStatus:"ENABLED",ruleOrder:1}}createResourceTypeNotificationRule(a){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:"Notify on Critical Resource Findings",description:"Set findings for critical resources to NOTIFIED status",actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"NOTIFIED"},note:{text:"Critical resource finding requires attention",updatedBy:"SecurityHub Automation"}}}],criteria:{resourceType:a.map((n)=>({value:n,comparison:"EQUALS"})),severityLabel:[{value:"HIGH",comparison:"EQUALS"},{value:"CRITICAL",comparison:"EQUALS"}],workflowStatus:[{value:"NEW",comparison:"EQUALS"}]},ruleStatus:"ENABLED",ruleOrder:2}}createComplianceFailureRule(){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:"Flag Compliance Failures",description:"Increase severity for compliance failures",actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{severity:{label:"HIGH"},workflow:{status:"NOTIFIED"},note:{text:"Compliance failure detected - requires immediate attention",updatedBy:"SecurityHub Automation"}}}],criteria:{complianceStatus:[{value:"FAILED",comparison:"EQUALS"}],recordState:[{value:"ACTIVE",comparison:"EQUALS"}]},ruleStatus:"ENABLED",ruleOrder:3}}createFalsePositiveSuppressionRule(a,n){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:`Suppress False Positives - ${a}`,description:`Automatically suppress known false positives from ${a}`,actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"SUPPRESSED"},note:{text:"Known false positive - automatically suppressed",updatedBy:"SecurityHub Automation"}}}],criteria:{productName:[{value:a,comparison:"EQUALS"}],title:n.map((i)=>({value:i,comparison:"PREFIX"}))},ruleStatus:"ENABLED",ruleOrder:10}}getHub(a){return this.hubs.get(a)}listHubs(){return Array.from(this.hubs.values())}generateHubCF(a){let n={Type:"AWS::SecurityHub::Hub",Properties:{}};if(a.controlFindingGenerator)n.Properties.ControlFindingGenerator=a.controlFindingGenerator;if(a.enableDefaultStandards!==void 0)n.Properties.EnableDefaultStandards=a.enableDefaultStandards;return n}generateStandardCF(a){let n={Type:"AWS::SecurityHub::Standard",Properties:{StandardsArn:a.arn}};if(a.disabledControls&&a.disabledControls.length>0)n.Properties.DisabledStandardsControls=a.disabledControls.map((i)=>({StandardsControlArn:i,Reason:"Disabled by configuration"}));return n}generateAutomationRuleCF(a){return{Type:"AWS::SecurityHub::AutomationRule",Properties:{RuleName:a.ruleName,Description:a.description,Actions:a.actions.map((n)=>({Type:n.type,FindingFieldsUpdate:n.findingFieldsUpdate})),Criteria:a.criteria,RuleStatus:a.ruleStatus,RuleOrder:a.ruleOrder}}}clear(){this.hubs.clear(),this.hubCounter=0,this.ruleCounter=0}}var ZS=new Br;class eg{deployments=new Map;deploymentHistory=new Map;deploymentCounter=0;resultCounter=0;createDeployment(a){let n=`bg-deployment-${Date.now()}-${this.deploymentCounter++}`,i={id:n,...a};return this.deployments.set(n,i),i}createALBDeployment(a){return this.createDeployment({name:a.name,blueEnvironment:{name:"blue",targetGroupArn:a.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:a.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:a.listenerArn,switchoverTimeSeconds:0},autoPromote:a.autoPromote,healthCheckConfig:a.healthCheckConfig})}createRoute53Deployment(a){return this.createDeployment({name:a.name,blueEnvironment:{name:"blue",targetGroupArn:a.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:a.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"route53",hostedZoneId:a.hostedZoneId,switchoverTimeSeconds:a.switchoverTimeSeconds||60}})}createECSDeployment(a){return this.createDeployment({name:a.name,blueEnvironment:{name:"blue",targetGroupArn:a.blueTargetGroupArn,taskDefinitionArn:a.blueTaskDefinitionArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:a.greenTargetGroupArn,taskDefinitionArn:a.greenTaskDefinitionArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:a.listenerArn},autoRollback:a.autoRollback??!0})}async executeDeployment(a,n=!1){let i=this.deployments.get(a);if(!i)throw Error(`Deployment not found: ${a}`);let s={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!1,errors:[]};console.log(`${n?"[DRY RUN] ":""}Starting blue/green deployment: ${i.name}`),console.log(` Active environment: ${i.activeEnvironment}`),console.log(` Routing type: ${i.routingConfig.type}`);let c=i.activeEnvironment==="blue"?"green":"blue";if(console.log(` Switching to: ${c}`),console.log(`\\n1. Deploying to ${c} environment`),!n)await new Promise((l)=>setTimeout(l,100));if(console.log(`\\n2. Running health checks on ${c} environment`),i.healthCheckConfig){let l=await this.runHealthChecks(i,c,n);if(s.healthChecksPassed=l,!l){if(s.errors?.push("Health checks failed"),s.endTime=new Date,i.autoRollback)console.log(" Auto-rollback enabled - keeping current environment active"),s.rolledBackAt=new Date;return this.recordDeployment(a,s),s}}else s.healthChecksPassed=!0;if(console.log(`\\n3. Switching traffic to ${c} environment`),!n)i.activeEnvironment=c,s.switchedAt=new Date;if(console.log(`\\n4. Monitoring ${c} environment`),!n)await new Promise((l)=>setTimeout(l,100));return s.success=!0,s.endTime=new Date,console.log("\\n✓ Deployment completed successfully"),this.recordDeployment(a,s),s}async rollback(a){let n=this.deployments.get(a);if(!n)throw Error(`Deployment not found: ${a}`);let i={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!0,errors:[]};console.log(`Rolling back deployment: ${n.name}`);let s=n.activeEnvironment==="blue"?"green":"blue";return n.activeEnvironment=s,i.success=!0,i.rolledBackAt=new Date,i.endTime=new Date,console.log(` Switched back to: ${s}`),this.recordDeployment(a,i),i}async runHealthChecks(a,n,i){let s=a.healthCheckConfig;if(console.log(` Health check path: ${s.path||"/"}`),console.log(` Healthy threshold: ${s.healthyThreshold}`),console.log(` Interval: ${s.interval}s`),i)return console.log(" [SKIPPED - DRY RUN]"),!0;let c=0,l=s.healthyThreshold+2;for(let u=0;u<l;u++)if(await new Promise((h)=>setTimeout(h,50)),Math.random()>0.1){if(c++,console.log(` Check ${u+1}: ✓ Healthy (${c}/${s.healthyThreshold})`),c>=s.healthyThreshold)return!0}else c=0,console.log(` Check ${u+1}: ✗ Unhealthy`);return!1}recordDeployment(a,n){if(!this.deploymentHistory.has(a))this.deploymentHistory.set(a,[]);this.deploymentHistory.get(a).push(n)}getDeployment(a){return this.deployments.get(a)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(a){return this.deploymentHistory.get(a)||[]}generateALBListenerCF(a){let n=a.activeEnvironment==="blue"?a.blueEnvironment:a.greenEnvironment;return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:a.routingConfig.listenerArn,Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",TargetGroupArn:n.targetGroupArn}]}}}generateRoute53RecordSetCF(a,n){return[{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:a.routingConfig.hostedZoneId,Name:n,Type:"A",SetIdentifier:"blue",Weight:a.activeEnvironment==="blue"?100:0,AliasTarget:{HostedZoneId:a.routingConfig.hostedZoneId,DNSName:a.blueEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}},{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:a.routingConfig.hostedZoneId,Name:n,Type:"A",SetIdentifier:"green",Weight:a.activeEnvironment==="green"?100:0,AliasTarget:{HostedZoneId:a.routingConfig.hostedZoneId,DNSName:a.greenEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}}]}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var eC=new eg;class zs{deployments=new Map;deploymentHistory=new Map;deploymentCounter=0;resultCounter=0;static Strategies={CONSERVATIVE:[{name:"Initial Canary",trafficPercentage:10,durationMinutes:10},{name:"Quarter Traffic",trafficPercentage:25,durationMinutes:10},{name:"Half Traffic",trafficPercentage:50,durationMinutes:15},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}],BALANCED:[{name:"Initial Canary",trafficPercentage:20,durationMinutes:5},{name:"Half Traffic",trafficPercentage:50,durationMinutes:10},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}],AGGRESSIVE:[{name:"Half Traffic",trafficPercentage:50,durationMinutes:5},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}],LINEAR_10:[{name:"Canary 10%",trafficPercentage:10,durationMinutes:5},{name:"Canary 20%",trafficPercentage:20,durationMinutes:5},{name:"Canary 30%",trafficPercentage:30,durationMinutes:5},{name:"Canary 40%",trafficPercentage:40,durationMinutes:5},{name:"Canary 50%",trafficPercentage:50,durationMinutes:5},{name:"Canary 60%",trafficPercentage:60,durationMinutes:5},{name:"Canary 70%",trafficPercentage:70,durationMinutes:5},{name:"Canary 80%",trafficPercentage:80,durationMinutes:5},{name:"Canary 90%",trafficPercentage:90,durationMinutes:5},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}]};createDeployment(a){let n=`canary-${Date.now()}-${this.deploymentCounter++}`,i={id:n,...a};return this.deployments.set(n,i),i}createLambdaCanaryDeployment(a){let n=a.strategy||"BALANCED",i=zs.Strategies[n].map((s)=>({...s,alarmThresholds:{errorRate:a.errorRateThreshold||1,latencyP99:a.latencyThreshold||1000}}));return this.createDeployment({name:a.name,baselineVersion:{version:"baseline",functionVersionArn:a.baselineVersionArn,weight:100},canaryVersion:{version:"canary",functionVersionArn:a.canaryVersionArn,weight:0},stages:i,currentStage:0,status:"pending",autoPromote:a.autoPromote??!0,autoRollback:!0})}createECSCanaryDeployment(a){let n=a.strategy||"CONSERVATIVE",i=zs.Strategies[n];return this.createDeployment({name:a.name,baselineVersion:{version:"baseline",taskDefinitionArn:a.baselineTaskDefinitionArn,targetGroupArn:a.baselineTargetGroupArn,weight:100},canaryVersion:{version:"canary",taskDefinitionArn:a.canaryTaskDefinitionArn,targetGroupArn:a.canaryTargetGroupArn,weight:0},stages:i,currentStage:0,status:"pending",autoRollback:!0})}async executeDeployment(a,n=!1){let i=this.deployments.get(a);if(!i)throw Error(`Deployment not found: ${a}`);let s={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,completedStages:0,rolledBack:!1};console.log(`${n?"[DRY RUN] ":""}Starting canary deployment: ${i.name}`),console.log(` Strategy: ${i.stages.length} stages`),console.log(` Auto-promote: ${i.autoPromote}`),console.log(` Auto-rollback: ${i.autoRollback}`),console.log(""),i.status="in_progress";for(let c=0;c<i.stages.length;c++){let l=i.stages[c];if(i.currentStage=c,console.log(`Stage ${c+1}/${i.stages.length}: ${l.name}`),console.log(` Traffic: ${l.trafficPercentage}% canary, ${100-l.trafficPercentage}% baseline`),console.log(` Duration: ${l.durationMinutes} minutes`),!n)i.baselineVersion.weight=100-l.trafficPercentage,i.canaryVersion.weight=l.trafficPercentage;if(!await this.monitorStage(i,l,n)){if(console.log(" ✗ Stage failed - metrics exceeded thresholds"),i.autoRollback)console.log("\\n Rolling back deployment..."),await this.rollback(a,n),s.rolledBack=!0,s.reason="Metrics exceeded thresholds";return s.endTime=new Date,i.status="rolled_back",this.recordDeployment(a,s),s}console.log(" ✓ Stage completed successfully"),s.completedStages++,console.log("")}return i.status="completed",s.success=!0,s.endTime=new Date,console.log("✓ Canary deployment completed successfully"),this.recordDeployment(a,s),s}async monitorStage(a,n,i){if(console.log(" Monitoring metrics..."),i)return console.log(" [SKIPPED - DRY RUN]"),!0;await new Promise((c)=>setTimeout(c,100));let s={baselineErrorRate:Math.random()*0.5,canaryErrorRate:Math.random()*0.8,baselineLatencyP99:200+Math.random()*100,canaryLatencyP99:180+Math.random()*150,baselineRequestCount:Math.floor(Math.random()*1000)+500,canaryRequestCount:Math.floor((Math.random()*1000+500)*n.trafficPercentage/100)};if(a.metrics=s,console.log(` Baseline: ${s.baselineErrorRate.toFixed(2)}% errors, ${s.baselineLatencyP99.toFixed(0)}ms P99`),console.log(` Canary: ${s.canaryErrorRate.toFixed(2)}% errors, ${s.canaryLatencyP99.toFixed(0)}ms P99`),n.alarmThresholds){let{errorRate:c,latencyP99:l}=n.alarmThresholds;if(c&&s.canaryErrorRate>c)return console.log(` ⚠ Error rate exceeded threshold: ${s.canaryErrorRate.toFixed(2)}% > ${c}%`),!1;if(l&&s.canaryLatencyP99>l)return console.log(` ⚠ Latency P99 exceeded threshold: ${s.canaryLatencyP99.toFixed(0)}ms > ${l}ms`),!1}return!0}async rollback(a,n=!1){let i=this.deployments.get(a);if(!i)throw Error(`Deployment not found: ${a}`);if(console.log(`${n?"[DRY RUN] ":""}Rolling back canary deployment: ${i.name}`),!n)i.baselineVersion.weight=100,i.canaryVersion.weight=0,i.status="rolled_back";console.log(" Traffic restored to baseline: 100%")}promoteCanary(a){let n=this.deployments.get(a);if(!n)throw Error(`Deployment not found: ${a}`);console.log(`Promoting canary to baseline: ${n.name}`);let i=n.baselineVersion;n.baselineVersion=n.canaryVersion,n.canaryVersion=i,n.baselineVersion.weight=100,n.canaryVersion.weight=0,n.status="completed",console.log(" Canary promoted successfully")}recordDeployment(a,n){if(!this.deploymentHistory.has(a))this.deploymentHistory.set(a,[]);this.deploymentHistory.get(a).push(n)}getDeployment(a){return this.deployments.get(a)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(a){return this.deploymentHistory.get(a)||[]}generateLambdaAliasCF(a,n){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:{Ref:"LambdaFunction"},Name:n,FunctionVersion:a.canaryVersion.version,RoutingConfig:{AdditionalVersionWeights:[{FunctionVersion:a.baselineVersion.version,FunctionWeight:a.baselineVersion.weight/100}]}}}}generateALBListenerRuleCF(a){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:[{TargetGroupArn:a.baselineVersion.targetGroupArn,Weight:a.baselineVersion.weight},{TargetGroupArn:a.canaryVersion.targetGroupArn,Weight:a.canaryVersion.weight}],TargetGroupStickinessConfig:{Enabled:!1}}}]}}}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var tC=new zs;class tg{tests=new Map;testCounter=0;createTest(a){let n=`abtest-${Date.now()}-${this.testCounter++}`,i={id:n,...a};return this.tests.set(n,i),i}createSimpleABTest(a){let n=a.variantTrafficPercentage||50;return this.createTest({name:a.name,description:a.description,variants:[{id:"control",name:"Control",description:"Original version",trafficPercentage:100-n,targetGroupArn:a.controlTargetGroupArn,weight:100-n},{id:"variant-a",name:"Variant A",description:"Test version",trafficPercentage:n,targetGroupArn:a.variantTargetGroupArn,weight:n}],routingStrategy:{type:a.stickySession?"cookie":"random",cookieName:a.stickySession?"ab_variant":void 0,stickySession:a.stickySession??!1,sessionDuration:1440},startTime:new Date,status:"draft"})}createMultivariateTest(a){let n=a.variants.reduce((i,s)=>i+s.trafficPercentage,0);if(n!==100)throw Error(`Traffic percentages must sum to 100, got ${n}`);return this.createTest({name:a.name,description:a.description,variants:a.variants.map((i,s)=>({id:`variant-${s}`,name:i.name,description:i.description,trafficPercentage:i.trafficPercentage,targetGroupArn:i.targetGroupArn,weight:i.trafficPercentage})),routingStrategy:a.routingStrategy||{type:"random",stickySession:!1},startTime:new Date,status:"draft"})}createHeaderBasedTest(a){return this.createTest({name:a.name,description:`Route based on ${a.headerName} header`,variants:[{id:"control",name:"Control",trafficPercentage:50,targetGroupArn:a.controlTargetGroupArn,weight:50},{id:"variant-a",name:"Variant A",trafficPercentage:50,targetGroupArn:a.variantTargetGroupArn,weight:50}],routingStrategy:{type:"header",headerName:a.headerName,stickySession:!1},startTime:new Date,status:"draft"})}createGeoBasedTest(a){return this.createTest({name:a.name,description:"Route based on geographic location",variants:[{id:"control",name:"Control (Rest of World)",trafficPercentage:50,targetGroupArn:a.controlTargetGroupArn,weight:50},{id:"variant-a",name:`Variant A (${a.regions.join(", ")})`,trafficPercentage:50,targetGroupArn:a.variantTargetGroupArn,weight:50}],routingStrategy:{type:"geo",stickySession:!0,sessionDuration:1440},startTime:new Date,status:"draft"})}startTest(a){let n=this.tests.get(a);if(!n)throw Error(`Test not found: ${a}`);if(n.status!=="draft"&&n.status!=="paused")throw Error(`Cannot start test in ${n.status} status`);n.status="active",n.startTime=new Date,console.log(`Started A/B test: ${n.name}`),console.log(` Variants: ${n.variants.length}`),n.variants.forEach((i)=>{console.log(` - ${i.name}: ${i.trafficPercentage}%`)})}pauseTest(a){let n=this.tests.get(a);if(!n)throw Error(`Test not found: ${a}`);n.status="paused",console.log(`Paused A/B test: ${n.name}`)}updateTrafficSplit(a,n,i){let s=this.tests.get(a);if(!s)throw Error(`Test not found: ${a}`);let c=s.variants.find((u)=>u.id===n);if(!c)throw Error(`Variant not found: ${n}`);let l=c.trafficPercentage;c.trafficPercentage=i,c.weight=i,console.log(`Updated ${c.name} traffic: ${l}% → ${i}%`)}analyzeResults(a){let n=this.tests.get(a);if(!n)throw Error(`Test not found: ${a}`);if(!n.metrics)n.metrics=this.collectMetrics(n);let i=n.variants[0],s=0;for(let f of n.variants){let S=n.metrics.variants[f.id];if(S&&S.conversionRate>s)s=S.conversionRate,i=f}let c=n.metrics.variants.control||n.metrics.variants[n.variants[0].id],l=n.metrics.variants[i.id],u=(l.conversionRate-c.conversionRate)/c.conversionRate*100,h=100,y=l.requests>h&&c.requests>h&&Math.abs(u)>10;return{testId:a,winningVariant:i.name,confidence:y?95:75,improvement:u,statisticalSignificance:y,metrics:n.metrics,recommendation:this.generateRecommendation(u,y,i.name)}}declareWinner(a,n){let i=this.tests.get(a);if(!i)throw Error(`Test not found: ${a}`);let s=i.variants.find((c)=>c.id===n);if(!s)throw Error(`Variant not found: ${n}`);i.variants.forEach((c)=>{if(c.id===n)c.trafficPercentage=100,c.weight=100;else c.trafficPercentage=0,c.weight=0}),i.status="completed",i.endTime=new Date,i.winner=n,console.log(`Declared winner: ${s.name}`),console.log(` All traffic now routed to ${s.name}`)}collectMetrics(a){let n={},i=0;for(let s of a.variants){let c=Math.floor(Math.random()*1000)+500,l=Math.floor(c*(Math.random()*0.1+0.05)),u=l/c*100;n[s.id]={requests:c,conversions:l,conversionRate:u,averageLatency:150+Math.random()*100,errorRate:Math.random()*0.5,revenue:l*(Math.random()*50+100)},i+=c}return{variants:n,totalRequests:i,startTime:a.startTime,lastUpdated:new Date}}generateRecommendation(a,n,i){if(!n)return"Continue test - sample size too small or no significant difference detected";if(a>20)return`Strong winner detected - ${i} shows ${a.toFixed(1)}% improvement. Recommend deploying to all traffic.`;if(a>10)return`Moderate improvement - ${i} shows ${a.toFixed(1)}% improvement. Consider deploying.`;if(a>0)return`Minor improvement - ${i} shows ${a.toFixed(1)}% improvement. May not be worth the complexity.`;return"No improvement detected - consider reverting to control variant"}getTest(a){return this.tests.get(a)}listTests(){return Array.from(this.tests.values())}generateALBListenerRuleCF(a){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:a.variants.map((n)=>({TargetGroupArn:n.targetGroupArn,Weight:n.weight})),TargetGroupStickinessConfig:{Enabled:a.routingStrategy.stickySession||!1,DurationSeconds:a.routingStrategy.sessionDuration?a.routingStrategy.sessionDuration*60:void 0}}}]}}}generateLambdaEdgeFunction(a){return`'use strict';
|
|
3600
|
+
`}class Wp{backupPlans=new Map;backupVaults=new Map;restoreJobs=new Map;continuousBackups=new Map;planCounter=0;restoreCounter=0;continuousBackupCounter=0;createVault(a){this.backupVaults.set(a.name,a)}getVault(a){return this.backupVaults.get(a)}createBackupPlan(a){let n=`backup-plan-${Date.now()}-${this.planCounter++}`,i={id:n,...a};return this.backupPlans.set(n,i),i}getBackupPlan(a){return this.backupPlans.get(a)}listBackupPlans(){return Array.from(this.backupPlans.values())}createRDSBackupPlan(a){let{dbInstanceArn:n,schedule:i="0 2 * * *",retentionDays:s=7,vaultName:c="default-vault"}=a;return this.createBackupPlan({name:"RDS Daily Backup",schedule:i,retentionDays:s,vaultName:c,resources:[{resourceArn:n,resourceType:"rds",region:"us-east-1"}],lifecycle:{moveTocoldStorageAfterDays:30,deleteAfterDays:s}})}createDynamoDBBackupPlan(a){let{tableArn:n,schedule:i="0 3 * * *",retentionDays:s=35,crossRegionCopy:c}=a;return this.createBackupPlan({name:"DynamoDB Daily Backup",schedule:i,retentionDays:s,vaultName:"dynamodb-vault",resources:[{resourceArn:n,resourceType:"dynamodb",region:"us-east-1"}],lifecycle:{deleteAfterDays:s},tags:c?{CrossRegionCopy:c.join(",")}:void 0})}createEFSBackupPlan(a){let{fileSystemArn:n,schedule:i="0 1 * * *",retentionDays:s=30}=a;return this.createBackupPlan({name:"EFS Daily Backup",schedule:i,retentionDays:s,vaultName:"efs-vault",resources:[{resourceArn:n,resourceType:"efs",region:"us-east-1"}],lifecycle:{deleteAfterDays:s}})}enableContinuousBackup(a,n=35){let i=`continuous-backup-${Date.now()}-${this.continuousBackupCounter++}`,s={id:i,resourceId:a,enabled:!0,retentionDays:n};return this.continuousBackups.set(i,s),s}getContinuousBackup(a){return this.continuousBackups.get(a)}enablePointInTimeRecovery(a,n){return{enabled:!0,earliestRestorableTime:new Date(Date.now()-604800000),latestRestorableTime:new Date}}async restoreFromBackup(a){let{backupId:n,resourceType:i,targetRegion:s}=a,c={id:`restore-${Date.now()}-${this.restoreCounter++}`,backupId:n,resourceType:i,status:"pending",startTime:new Date,targetRegion:s};return this.restoreJobs.set(c.id,c),setTimeout(()=>{c.status="running"},100),setTimeout(()=>{c.status="completed",c.endTime=new Date},1000),c}async restoreToPointInTime(a){let{sourceResourceArn:n,targetResourceName:i,restoreTime:s,resourceType:c}=a,l={id:`pitr-${Date.now()}-${this.restoreCounter++}`,backupId:`pitr-${s.getTime()}`,resourceType:c,status:"pending",startTime:new Date};return this.restoreJobs.set(l.id,l),console.log(`Restoring ${c} from ${n} to ${i} at ${s.toISOString()}`),setTimeout(()=>{l.status="completed",l.endTime=new Date},2000),l}getRestoreJob(a){return this.restoreJobs.get(a)}listRestoreJobs(){return Array.from(this.restoreJobs.values())}setupCrossRegionReplication(a){let{sourceVault:n,sourceRegion:i,targetRegions:s}=a;console.log("Setting up cross-region replication:"),console.log(` Source: ${n} in ${i}`),console.log(` Targets: ${s.join(", ")}`)}generateBackupVaultCF(a){return{Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:a.name,...a.encryptionKeyArn&&{EncryptionKeyArn:a.encryptionKeyArn},...a.accessPolicy&&{AccessPolicy:a.accessPolicy}}}}generateBackupPlanCF(a){return{Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:a.name,BackupPlanRule:[{RuleName:"DailyBackup",TargetBackupVault:a.vaultName,ScheduleExpression:`cron(${a.schedule})`,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:a.lifecycle?{...a.lifecycle.moveTocoldStorageAfterDays&&{MoveToColdStorageAfterDays:a.lifecycle.moveTocoldStorageAfterDays},...a.lifecycle.deleteAfterDays&&{DeleteAfterDays:a.lifecycle.deleteAfterDays}}:void 0}]},...a.tags&&{BackupPlanTags:a.tags}}}}generateBackupSelectionCF(a){return{Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:{Ref:`BackupPlan${a.id}`},BackupSelection:{SelectionName:`${a.name}Selection`,IamRoleArn:"arn:aws:iam::123456789012:role/service-role/AWSBackupDefaultServiceRole",Resources:a.resources.map((n)=>n.resourceArn)}}}}clear(){this.backupPlans.clear(),this.backupVaults.clear(),this.restoreJobs.clear(),this.continuousBackups.clear(),this.planCounter=0,this.restoreCounter=0,this.continuousBackupCounter=0}}var KS=new Wp;class Jp{drPlans=new Map;failoverTests=new Map;planCounter=0;testCounter=0;createDRPlan(a){let n=`dr-plan-${Date.now()}-${this.planCounter++}`,i={id:n,...a};return this.drPlans.set(n,i),i}createRDSDRPlan(a){let{primaryDbArn:n,secondaryDbArn:i,primaryRegion:s,secondaryRegion:c,rto:l=60,rpo:u=5}=a;return this.createDRPlan({name:"RDS Multi-Region DR",primaryRegion:s,secondaryRegion:c,rto:l,rpo:u,resources:[{resourceId:"primary-db",resourceType:"rds",primaryArn:n,secondaryArn:i,replicationEnabled:!0}],runbook:this.generateRDSRunbook(s,c),testSchedule:"0 0 1 * *"})}createDynamoDBDRPlan(a){let{tableArn:n,regions:i,rto:s=15,rpo:c=1}=a;return this.createDRPlan({name:"DynamoDB Global Tables DR",primaryRegion:i[0],secondaryRegion:i[1],rto:s,rpo:c,resources:[{resourceId:"dynamodb-table",resourceType:"dynamodb",primaryArn:n,replicationEnabled:!0}],runbook:this.generateDynamoDBRunbook(i)})}generateRDSRunbook(a,n){return{estimatedDuration:60,requiredApprovals:["cto","engineering-lead"],steps:[{order:1,name:"Verify Primary Database Failure",description:"Confirm that the primary database is truly unavailable and not experiencing temporary issues",action:"aws rds describe-db-instances --region "+a,automatable:!0,estimatedDuration:2,rollbackable:!1},{order:2,name:"Check Replication Lag",description:"Verify that the read replica is up to date",action:"Check ReplicaLag metric in CloudWatch",automatable:!0,estimatedDuration:1,rollbackable:!1},{order:3,name:"Promote Read Replica",description:"Promote the read replica in the secondary region to be the new primary",action:"aws rds promote-read-replica --db-instance-identifier replica --region "+n,automatable:!0,estimatedDuration:10,rollbackable:!1},{order:4,name:"Update DNS Records",description:"Update Route53 records to point to the new primary database",action:"Update Route53 failover record set",automatable:!0,estimatedDuration:5,rollbackable:!0},{order:5,name:"Update Application Configuration",description:"Update application connection strings if needed",action:"Deploy configuration update to ECS/Lambda",automatable:!0,estimatedDuration:10,rollbackable:!0},{order:6,name:"Verify Application Connectivity",description:"Test that applications can connect to the new primary",action:"Run smoke tests",automatable:!0,estimatedDuration:5,rollbackable:!1},{order:7,name:"Monitor for Issues",description:"Monitor CloudWatch metrics and application logs",action:"Monitor for 30 minutes",automatable:!1,estimatedDuration:30,rollbackable:!1}]}}generateDynamoDBRunbook(a){return{estimatedDuration:15,steps:[{order:1,name:"Verify Primary Region Failure",description:"Confirm that the primary region is experiencing an outage",action:"Check AWS Health Dashboard",automatable:!0,estimatedDuration:2,rollbackable:!1},{order:2,name:"Update Route53 Failover",description:"Update Route53 to direct traffic to secondary region",action:"Update Route53 health check and failover records",automatable:!0,estimatedDuration:5,rollbackable:!0},{order:3,name:"Update Application Endpoints",description:"Update Lambda/ECS to use secondary region DynamoDB endpoint",action:"Deploy configuration update",automatable:!0,estimatedDuration:5,rollbackable:!0},{order:4,name:"Verify Data Consistency",description:"Verify that data is consistent in secondary region",action:"Run data validation queries",automatable:!0,estimatedDuration:3,rollbackable:!1}]}}async executeFailover(a,n=!1){let i=this.drPlans.get(a);if(!i)throw Error(`DR plan not found: ${a}`);let s=Date.now(),c=0;console.log(`${n?"[DRY RUN] ":""}Executing failover for plan: ${i.name}`),console.log(`Primary: ${i.primaryRegion} -> Secondary: ${i.secondaryRegion}`),console.log(`RTO: ${i.rto} minutes, RPO: ${i.rpo} minutes`),console.log("");for(let l of i.runbook.steps){if(console.log(`Step ${l.order}: ${l.name}`),console.log(` ${l.description}`),console.log(` Action: ${l.action}`),console.log(` Estimated: ${l.estimatedDuration} minutes`),n)console.log(" [SKIPPED - DRY RUN]");else if(l.automatable)console.log(" [AUTOMATED]");else console.log(" [MANUAL - WAITING]");c++,console.log("")}return{success:!0,duration:(Date.now()-s)/1000/60,completedSteps:c}}scheduleFailoverTest(a,n){let i={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:a,status:"scheduled",startTime:n};return this.failoverTests.set(i.id,i),i}async runFailoverTest(a){let n=this.drPlans.get(a);if(!n)throw Error(`DR plan not found: ${a}`);let i={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:a,status:"running",startTime:new Date,results:[]};this.failoverTests.set(i.id,i),console.log(`Running failover test for plan: ${n.name}`),console.log("This is a non-destructive test using test resources"),console.log("");for(let s of n.runbook.steps){let c=Date.now();console.log(`Testing step ${s.order}: ${s.name}`);let l={step:s.name,status:"success",duration:(Date.now()-c)/1000,message:`Successfully validated step ${s.order}`};i.results.push(l)}return i.status="completed",i.endTime=new Date,i}getDRPlan(a){return this.drPlans.get(a)}listDRPlans(){return Array.from(this.drPlans.values())}getFailoverTest(a){return this.failoverTests.get(a)}listFailoverTests(){return Array.from(this.failoverTests.values())}validateDRPlan(a){let n=[],i=[];if(a.rto<a.rpo)i.push("RTO cannot be less than RPO");if(a.rto>240)n.push("RTO exceeds 4 hours - consider improving recovery time");if(a.rpo>60)n.push("RPO exceeds 1 hour - consider more frequent backups");if(a.resources.length===0)i.push("No resources defined in DR plan");for(let l of a.resources){if(!l.replicationEnabled)n.push(`Resource ${l.resourceId} does not have replication enabled`);if(!l.secondaryArn&&l.resourceType!=="dynamodb")n.push(`Resource ${l.resourceId} does not have secondary resource defined`)}if(a.runbook.steps.length===0)i.push("No recovery steps defined in runbook");let s=a.runbook.steps.reduce((l,u)=>l+u.estimatedDuration,0);if(s>a.rto)n.push(`Estimated recovery duration (${s}m) exceeds RTO (${a.rto}m)`);let c=a.runbook.steps.filter((l)=>!l.automatable);if(c.length>0)n.push(`${c.length} manual steps in runbook - consider automation`);return{valid:i.length===0,warnings:n,errors:i}}clear(){this.drPlans.clear(),this.failoverTests.clear(),this.planCounter=0,this.testCounter=0}}var WS=new Jp;class Xp{configRules=new Map;configRecorders=new Map;deliveryChannels=new Map;ruleCounter=0;createConfigRecorder(a){return this.configRecorders.set(a.name,a),a}createDeliveryChannel(a){return this.deliveryChannels.set(a.name,a),a}createConfigRule(a){let n=`config-rule-${Date.now()}-${this.ruleCounter++}`,i={id:n,...a};return this.configRules.set(n,i),i}createS3EncryptionRule(){return this.createConfigRule({name:"s3-bucket-server-side-encryption-enabled",description:"Checks that S3 buckets have server-side encryption enabled",source:"AWS_MANAGED",identifier:"S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED",scope:{complianceResourceTypes:["AWS::S3::Bucket"]}})}createS3PublicAccessBlockRule(){return this.createConfigRule({name:"s3-bucket-public-read-prohibited",description:"Checks that S3 buckets do not allow public read access",source:"AWS_MANAGED",identifier:"S3_BUCKET_PUBLIC_READ_PROHIBITED",scope:{complianceResourceTypes:["AWS::S3::Bucket"]}})}createS3VersioningRule(){return this.createConfigRule({name:"s3-bucket-versioning-enabled",description:"Checks whether versioning is enabled for S3 buckets",source:"AWS_MANAGED",identifier:"S3_BUCKET_VERSIONING_ENABLED",scope:{complianceResourceTypes:["AWS::S3::Bucket"]}})}createRdsEncryptionRule(){return this.createConfigRule({name:"rds-storage-encrypted",description:"Checks whether storage encryption is enabled for RDS DB instances",source:"AWS_MANAGED",identifier:"RDS_STORAGE_ENCRYPTED",scope:{complianceResourceTypes:["AWS::RDS::DBInstance"]}})}createRdsSnapshotEncryptionRule(){return this.createConfigRule({name:"rds-snapshots-public-prohibited",description:"Checks if RDS snapshots are public",source:"AWS_MANAGED",identifier:"RDS_SNAPSHOTS_PUBLIC_PROHIBITED",scope:{complianceResourceTypes:["AWS::RDS::DBSnapshot","AWS::RDS::DBClusterSnapshot"]}})}createRdsBackupRule(a=7){return this.createConfigRule({name:"db-backup-enabled",description:"Checks whether RDS DB instances have backups enabled",source:"AWS_MANAGED",identifier:"DB_BACKUP_ENABLED",inputParameters:{backupRetentionPeriod:a},scope:{complianceResourceTypes:["AWS::RDS::DBInstance"]}})}createEc2InstanceProfileRule(){return this.createConfigRule({name:"ec2-instance-managed-by-systems-manager",description:"Checks if EC2 instances are managed by Systems Manager",source:"AWS_MANAGED",identifier:"EC2_INSTANCE_MANAGED_BY_SSM",scope:{complianceResourceTypes:["AWS::EC2::Instance"]}})}createEbsEncryptionRule(){return this.createConfigRule({name:"encrypted-volumes",description:"Checks whether EBS volumes are encrypted",source:"AWS_MANAGED",identifier:"ENCRYPTED_VOLUMES",scope:{complianceResourceTypes:["AWS::EC2::Volume"]}})}createIamPasswordPolicyRule(){return this.createConfigRule({name:"iam-password-policy",description:"Checks whether the IAM password policy meets specified requirements",source:"AWS_MANAGED",identifier:"IAM_PASSWORD_POLICY",inputParameters:{RequireUppercaseCharacters:!0,RequireLowercaseCharacters:!0,RequireSymbols:!0,RequireNumbers:!0,MinimumPasswordLength:14,PasswordReusePrevention:24,MaxPasswordAge:90}})}createIamMfaRule(){return this.createConfigRule({name:"iam-user-mfa-enabled",description:"Checks whether IAM users have MFA enabled",source:"AWS_MANAGED",identifier:"IAM_USER_MFA_ENABLED"})}createRootAccountMfaRule(){return this.createConfigRule({name:"root-account-mfa-enabled",description:"Checks whether the root account has MFA enabled",source:"AWS_MANAGED",identifier:"ROOT_ACCOUNT_MFA_ENABLED"})}createVpcFlowLogsRule(){return this.createConfigRule({name:"vpc-flow-logs-enabled",description:"Checks whether VPC Flow Logs is enabled",source:"AWS_MANAGED",identifier:"VPC_FLOW_LOGS_ENABLED",scope:{complianceResourceTypes:["AWS::EC2::VPC"]}})}createCloudTrailEnabledRule(){return this.createConfigRule({name:"cloudtrail-enabled",description:"Checks whether CloudTrail is enabled",source:"AWS_MANAGED",identifier:"CLOUD_TRAIL_ENABLED",maxExecutionFrequency:"TwentyFour_Hours"})}createCloudWatchAlarmRule(){return this.createConfigRule({name:"cloudwatch-alarm-action-check",description:"Checks whether CloudWatch alarms have actions configured",source:"AWS_MANAGED",identifier:"CLOUDWATCH_ALARM_ACTION_CHECK",inputParameters:{alarmActionRequired:!0,insufficientDataActionRequired:!1,okActionRequired:!1},scope:{complianceResourceTypes:["AWS::CloudWatch::Alarm"]}})}createCustomLambdaRule(a){return this.createConfigRule({name:a.name,description:a.description,source:"CUSTOM_LAMBDA",lambdaFunctionArn:a.lambdaFunctionArn,scope:a.resourceTypes?{complianceResourceTypes:a.resourceTypes}:void 0,maxExecutionFrequency:a.maxExecutionFrequency,inputParameters:a.inputParameters})}createCompliancePreset(a){let n=[];switch(a){case"hipaa":n.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createRdsBackupRule(7),this.createVpcFlowLogsRule());break;case"pci-dss":n.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createIamMfaRule(),this.createRootAccountMfaRule(),this.createVpcFlowLogsRule());break;case"sox":n.push(this.createS3VersioningRule(),this.createCloudTrailEnabledRule(),this.createRdsBackupRule(30),this.createIamPasswordPolicyRule());break;case"gdpr":n.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createRdsSnapshotEncryptionRule());break;case"basic":n.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamMfaRule(),this.createRootAccountMfaRule());break}return n}getConfigRule(a){return this.configRules.get(a)}listConfigRules(){return Array.from(this.configRules.values())}getConfigRecorder(a){return this.configRecorders.get(a)}listConfigRecorders(){return Array.from(this.configRecorders.values())}getDeliveryChannel(a){return this.deliveryChannels.get(a)}listDeliveryChannels(){return Array.from(this.deliveryChannels.values())}generateConfigRuleCF(a){let n={Type:"AWS::Config::ConfigRule",Properties:{ConfigRuleName:a.name,Description:a.description,Source:{Owner:a.source==="AWS_MANAGED"?"AWS":"CUSTOM_LAMBDA"}}};if(a.source==="AWS_MANAGED"&&a.identifier)n.Properties.Source.SourceIdentifier=a.identifier;if(a.source==="CUSTOM_LAMBDA"&&a.lambdaFunctionArn)n.Properties.Source.SourceIdentifier=a.lambdaFunctionArn,n.Properties.Source.SourceDetails=[{EventSource:"aws.config",MessageType:"ConfigurationItemChangeNotification"}];if(a.inputParameters)n.Properties.InputParameters=JSON.stringify(a.inputParameters);if(a.scope){if(n.Properties.Scope={},a.scope.complianceResourceTypes)n.Properties.Scope.ComplianceResourceTypes=a.scope.complianceResourceTypes;if(a.scope.tagKey)n.Properties.Scope.TagKey=a.scope.tagKey;if(a.scope.tagValue)n.Properties.Scope.TagValue=a.scope.tagValue}if(a.maxExecutionFrequency)n.Properties.MaximumExecutionFrequency=a.maxExecutionFrequency;return n}generateConfigRecorderCF(a){return{Type:"AWS::Config::ConfigurationRecorder",Properties:{Name:a.name,RoleArn:a.roleArn,RecordingGroup:a.recordingGroup||{AllSupported:!0,IncludeGlobalResourceTypes:!0}}}}generateDeliveryChannelCF(a){return{Type:"AWS::Config::DeliveryChannel",Properties:{Name:a.name,S3BucketName:a.s3BucketName,...a.s3KeyPrefix&&{S3KeyPrefix:a.s3KeyPrefix},...a.snsTopicArn&&{SnsTopicARN:a.snsTopicArn},...a.configSnapshotDeliveryProperties&&{ConfigSnapshotDeliveryProperties:a.configSnapshotDeliveryProperties}}}}clear(){this.configRules.clear(),this.configRecorders.clear(),this.deliveryChannels.clear(),this.ruleCounter=0}}var JS=new Xp;class Yp{trails=new Map;trailCounter=0;createTrail(a){let n=`trail-${Date.now()}-${this.trailCounter++}`,i={id:n,...a};return this.trails.set(n,i),i}createOrganizationTrail(a){return this.createTrail({name:a.name,s3BucketName:a.s3BucketName,s3KeyPrefix:"organization-trail",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:a.kmsKeyId,cloudWatchLogsLogGroupArn:a.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:a.cloudWatchLogsRoleArn})}createSecurityAuditTrail(a){return this.createTrail({name:a.name,s3BucketName:a.s3BucketName,s3KeyPrefix:"security-audit",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:a.kmsKeyId,cloudWatchLogsLogGroupArn:a.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:a.cloudWatchLogsRoleArn,eventSelectors:[{readWriteType:"All",includeManagementEvents:!0,excludeManagementEventSources:[]}],insightSelectors:[{insightType:"ApiCallRateInsight"},{insightType:"ApiErrorRateInsight"}]})}createDataEventsTrail(a){let n=[];if(a.s3DataBuckets&&a.s3DataBuckets.length>0)n.push({type:"AWS::S3::Object",values:a.s3DataBuckets.map((i)=>`arn:aws:s3:::${i}/*`)});if(a.lambdaFunctions&&a.lambdaFunctions.length>0)n.push({type:"AWS::Lambda::Function",values:a.lambdaFunctions});return this.createTrail({name:a.name,s3BucketName:a.s3BucketName,s3KeyPrefix:"data-events",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"All",includeManagementEvents:!1,dataResources:n}]})}createAdvancedTrail(a){return this.createTrail({name:a.name,s3BucketName:a.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,advancedEventSelectors:a.selectors})}createReadOnlyTrail(a){return this.createTrail({name:a.name,s3BucketName:a.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"ReadOnly",includeManagementEvents:!0}]})}createWriteOnlyTrail(a){return this.createTrail({name:a.name,s3BucketName:a.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"WriteOnly",includeManagementEvents:!0}]})}getTrail(a){return this.trails.get(a)}listTrails(){return Array.from(this.trails.values())}generateTrailCF(a){let n={Type:"AWS::CloudTrail::Trail",Properties:{TrailName:a.name,S3BucketName:a.s3BucketName,IsLogging:!0,IncludeGlobalServiceEvents:a.includeGlobalServiceEvents??!0,IsMultiRegionTrail:a.isMultiRegionTrail??!0,EnableLogFileValidation:a.enableLogFileValidation??!0}};if(a.s3KeyPrefix)n.Properties.S3KeyPrefix=a.s3KeyPrefix;if(a.cloudWatchLogsLogGroupArn)n.Properties.CloudWatchLogsLogGroupArn=a.cloudWatchLogsLogGroupArn;if(a.cloudWatchLogsRoleArn)n.Properties.CloudWatchLogsRoleArn=a.cloudWatchLogsRoleArn;if(a.snsTopicName)n.Properties.SnsTopicName=a.snsTopicName;if(a.kmsKeyId)n.Properties.KMSKeyId=a.kmsKeyId;if(a.eventSelectors)n.Properties.EventSelectors=a.eventSelectors.map((i)=>({ReadWriteType:i.readWriteType,IncludeManagementEvents:i.includeManagementEvents??!0,...i.dataResources&&{DataResources:i.dataResources.map((s)=>({Type:s.type,Values:s.values}))},...i.excludeManagementEventSources&&{ExcludeManagementEventSources:i.excludeManagementEventSources}}));if(a.insightSelectors)n.Properties.InsightSelectors=a.insightSelectors.map((i)=>({InsightType:i.insightType}));if(a.advancedEventSelectors)n.Properties.AdvancedEventSelectors=a.advancedEventSelectors.map((i)=>({Name:i.name,FieldSelectors:i.fieldSelectors.map((s)=>({Field:s.field,...s.equals&&{Equals:s.equals},...s.startsWith&&{StartsWith:s.startsWith},...s.endsWith&&{EndsWith:s.endsWith},...s.notEquals&&{NotEquals:s.notEquals},...s.notStartsWith&&{NotStartsWith:s.notStartsWith},...s.notEndsWith&&{NotEndsWith:s.notEndsWith}}))}));return n}generateBucketPolicy(a,n){return{Version:"2012-10-17",Statement:[{Sid:"AWSCloudTrailAclCheck",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:GetBucketAcl",Resource:`arn:aws:s3:::${a}`},{Sid:"AWSCloudTrailWrite",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:PutObject",Resource:n.map((i)=>`arn:aws:s3:::${a}/AWSLogs/${i}/*`),Condition:{StringEquals:{"s3:x-amz-acl":"bucket-owner-full-control"}}}]}}clear(){this.trails.clear(),this.trailCounter=0}}var XS=new Yp;class Zp{detectors=new Map;threatIntelSets=new Map;ipSets=new Map;filters=new Map;detectorCounter=0;threatIntelCounter=0;ipSetCounter=0;filterCounter=0;createDetector(a){let n=`detector-${Date.now()}-${this.detectorCounter++}`,i={id:n,...a};return this.detectors.set(n,i),i}createComprehensiveDetector(){return this.createDetector({enable:!0,findingPublishingFrequency:"FIFTEEN_MINUTES",dataSources:{s3Logs:{enable:!0},kubernetes:{auditLogs:{enable:!0}},malwareProtection:{scanEc2InstanceWithFindings:{ebsVolumes:{enable:!0}}}},features:[{name:"S3_DATA_EVENTS",status:"ENABLED"},{name:"EKS_AUDIT_LOGS",status:"ENABLED"},{name:"EBS_MALWARE_PROTECTION",status:"ENABLED"},{name:"RDS_LOGIN_EVENTS",status:"ENABLED"},{name:"LAMBDA_NETWORK_LOGS",status:"ENABLED"}]})}createBasicDetector(){return this.createDetector({enable:!0,findingPublishingFrequency:"SIX_HOURS"})}createThreatIntelSet(a){let n=`threat-intel-${Date.now()}-${this.threatIntelCounter++}`,i={id:n,...a};return this.threatIntelSets.set(n,i),i}createIPSet(a){let n=`ip-set-${Date.now()}-${this.ipSetCounter++}`,i={id:n,...a};return this.ipSets.set(n,i),i}createFindingFilter(a){let n=`filter-${Date.now()}-${this.filterCounter++}`,i={id:n,...a};return this.filters.set(n,i),i}createLowSeverityArchiveFilter(a){return this.createFindingFilter({detectorId:a,name:"archive-low-severity",description:"Automatically archive low severity findings",action:"ARCHIVE",rank:1,findingCriteria:{criterion:{severity:{lt:4}}}})}createFindingTypeFilter(a,n,i){return this.createFindingFilter({detectorId:a,name:`filter-finding-types-${i.toLowerCase()}`,description:`${i==="ARCHIVE"?"Archive":"Keep"} specific finding types`,action:i,rank:2,findingCriteria:{criterion:{type:{eq:n}}}})}createTrustedIPFilter(a,n){return this.createFindingFilter({detectorId:a,name:"trusted-ip-addresses",description:"Archive findings from trusted IP addresses",action:"ARCHIVE",rank:3,findingCriteria:{criterion:{"resource.instanceDetails.networkInterfaces.privateIpAddress":{eq:n}}}})}getDetector(a){return this.detectors.get(a)}listDetectors(){return Array.from(this.detectors.values())}getThreatIntelSet(a){return this.threatIntelSets.get(a)}listThreatIntelSets(){return Array.from(this.threatIntelSets.values())}getIPSet(a){return this.ipSets.get(a)}listIPSets(){return Array.from(this.ipSets.values())}getFindingFilter(a){return this.filters.get(a)}listFindingFilters(){return Array.from(this.filters.values())}generateDetectorCF(a){let n={Type:"AWS::GuardDuty::Detector",Properties:{Enable:a.enable}};if(a.findingPublishingFrequency)n.Properties.FindingPublishingFrequency=a.findingPublishingFrequency;if(a.dataSources){if(n.Properties.DataSources={},a.dataSources.s3Logs)n.Properties.DataSources.S3Logs={Enable:a.dataSources.s3Logs.enable};if(a.dataSources.kubernetes)n.Properties.DataSources.Kubernetes={AuditLogs:{Enable:a.dataSources.kubernetes.auditLogs.enable}};if(a.dataSources.malwareProtection)n.Properties.DataSources.MalwareProtection={ScanEc2InstanceWithFindings:{EbsVolumes:{Enable:a.dataSources.malwareProtection.scanEc2InstanceWithFindings.ebsVolumes.enable}}}}if(a.features)n.Properties.Features=a.features.map((i)=>({Name:i.name,Status:i.status,...i.additionalConfiguration&&{AdditionalConfiguration:i.additionalConfiguration}}));return n}generateThreatIntelSetCF(a){return{Type:"AWS::GuardDuty::ThreatIntelSet",Properties:{DetectorId:a.detectorId,Name:a.name,Format:a.format,Location:a.location,Activate:a.activate}}}generateIPSetCF(a){return{Type:"AWS::GuardDuty::IPSet",Properties:{DetectorId:a.detectorId,Name:a.name,Format:a.format,Location:a.location,Activate:a.activate}}}generateFilterCF(a){return{Type:"AWS::GuardDuty::Filter",Properties:{DetectorId:a.detectorId,Name:a.name,Description:a.description,Action:a.action,Rank:a.rank,FindingCriteria:{Criterion:a.findingCriteria.criterion}}}}clear(){this.detectors.clear(),this.threatIntelSets.clear(),this.ipSets.clear(),this.filters.clear(),this.detectorCounter=0,this.threatIntelCounter=0,this.ipSetCounter=0,this.filterCounter=0}}var YS=new Zp;class Br{hubs=new Map;hubCounter=0;ruleCounter=0;static Standards={AWS_FOUNDATIONAL_SECURITY:{arn:"arn:aws:securityhub:::ruleset/aws-foundational-security-best-practices/v/1.0.0",name:"AWS Foundational Security Best Practices",description:"AWS recommended security best practices"},CIS_AWS_FOUNDATIONS_1_2:{arn:"arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0",name:"CIS AWS Foundations Benchmark v1.2.0",description:"CIS AWS Foundations Benchmark v1.2.0"},CIS_AWS_FOUNDATIONS_1_4:{arn:"arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.4.0",name:"CIS AWS Foundations Benchmark v1.4.0",description:"CIS AWS Foundations Benchmark v1.4.0"},PCI_DSS:{arn:"arn:aws:securityhub:us-east-1::standards/pci-dss/v/3.2.1",name:"PCI DSS v3.2.1",description:"Payment Card Industry Data Security Standard"},NIST_800_53:{arn:"arn:aws:securityhub:us-east-1::standards/nist-800-53/v/5.0.0",name:"NIST SP 800-53 Rev. 5",description:"NIST Special Publication 800-53 Revision 5"}};createHub(a){let n=`hub-${Date.now()}-${this.hubCounter++}`,i={id:n,...a};return this.hubs.set(n,i),i}createComprehensiveHub(){return this.createHub({enable:!0,controlFindingGenerator:"SECURITY_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...Br.Standards.AWS_FOUNDATIONAL_SECURITY,enabled:!0},{id:"cis-1-4",...Br.Standards.CIS_AWS_FOUNDATIONS_1_4,enabled:!0},{id:"pci-dss",...Br.Standards.PCI_DSS,enabled:!0}]})}createBasicHub(){return this.createHub({enable:!0,controlFindingGenerator:"STANDARD_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...Br.Standards.AWS_FOUNDATIONAL_SECURITY,enabled:!0}]})}createLowSeveritySuppressionRule(){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:"Suppress Low Severity Informational Findings",description:"Automatically suppress informational findings",actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"SUPPRESSED"},note:{text:"Automatically suppressed low severity finding",updatedBy:"SecurityHub Automation"}}}],criteria:{severityLabel:[{value:"INFORMATIONAL",comparison:"EQUALS"}],recordState:[{value:"ACTIVE",comparison:"EQUALS"}]},ruleStatus:"ENABLED",ruleOrder:1}}createResourceTypeNotificationRule(a){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:"Notify on Critical Resource Findings",description:"Set findings for critical resources to NOTIFIED status",actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"NOTIFIED"},note:{text:"Critical resource finding requires attention",updatedBy:"SecurityHub Automation"}}}],criteria:{resourceType:a.map((n)=>({value:n,comparison:"EQUALS"})),severityLabel:[{value:"HIGH",comparison:"EQUALS"},{value:"CRITICAL",comparison:"EQUALS"}],workflowStatus:[{value:"NEW",comparison:"EQUALS"}]},ruleStatus:"ENABLED",ruleOrder:2}}createComplianceFailureRule(){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:"Flag Compliance Failures",description:"Increase severity for compliance failures",actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{severity:{label:"HIGH"},workflow:{status:"NOTIFIED"},note:{text:"Compliance failure detected - requires immediate attention",updatedBy:"SecurityHub Automation"}}}],criteria:{complianceStatus:[{value:"FAILED",comparison:"EQUALS"}],recordState:[{value:"ACTIVE",comparison:"EQUALS"}]},ruleStatus:"ENABLED",ruleOrder:3}}createFalsePositiveSuppressionRule(a,n){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:`Suppress False Positives - ${a}`,description:`Automatically suppress known false positives from ${a}`,actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"SUPPRESSED"},note:{text:"Known false positive - automatically suppressed",updatedBy:"SecurityHub Automation"}}}],criteria:{productName:[{value:a,comparison:"EQUALS"}],title:n.map((i)=>({value:i,comparison:"PREFIX"}))},ruleStatus:"ENABLED",ruleOrder:10}}getHub(a){return this.hubs.get(a)}listHubs(){return Array.from(this.hubs.values())}generateHubCF(a){let n={Type:"AWS::SecurityHub::Hub",Properties:{}};if(a.controlFindingGenerator)n.Properties.ControlFindingGenerator=a.controlFindingGenerator;if(a.enableDefaultStandards!==void 0)n.Properties.EnableDefaultStandards=a.enableDefaultStandards;return n}generateStandardCF(a){let n={Type:"AWS::SecurityHub::Standard",Properties:{StandardsArn:a.arn}};if(a.disabledControls&&a.disabledControls.length>0)n.Properties.DisabledStandardsControls=a.disabledControls.map((i)=>({StandardsControlArn:i,Reason:"Disabled by configuration"}));return n}generateAutomationRuleCF(a){return{Type:"AWS::SecurityHub::AutomationRule",Properties:{RuleName:a.ruleName,Description:a.description,Actions:a.actions.map((n)=>({Type:n.type,FindingFieldsUpdate:n.findingFieldsUpdate})),Criteria:a.criteria,RuleStatus:a.ruleStatus,RuleOrder:a.ruleOrder}}}clear(){this.hubs.clear(),this.hubCounter=0,this.ruleCounter=0}}var ZS=new Br;class eg{deployments=new Map;deploymentHistory=new Map;deploymentCounter=0;resultCounter=0;createDeployment(a){let n=`bg-deployment-${Date.now()}-${this.deploymentCounter++}`,i={id:n,...a};return this.deployments.set(n,i),i}createALBDeployment(a){return this.createDeployment({name:a.name,blueEnvironment:{name:"blue",targetGroupArn:a.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:a.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:a.listenerArn,switchoverTimeSeconds:0},autoPromote:a.autoPromote,healthCheckConfig:a.healthCheckConfig})}createRoute53Deployment(a){return this.createDeployment({name:a.name,blueEnvironment:{name:"blue",targetGroupArn:a.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:a.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"route53",hostedZoneId:a.hostedZoneId,switchoverTimeSeconds:a.switchoverTimeSeconds||60}})}createECSDeployment(a){return this.createDeployment({name:a.name,blueEnvironment:{name:"blue",targetGroupArn:a.blueTargetGroupArn,taskDefinitionArn:a.blueTaskDefinitionArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:a.greenTargetGroupArn,taskDefinitionArn:a.greenTaskDefinitionArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:a.listenerArn},autoRollback:a.autoRollback??!0})}async executeDeployment(a,n=!1){let i=this.deployments.get(a);if(!i)throw Error(`Deployment not found: ${a}`);let s={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!1,errors:[]};console.log(`${n?"[DRY RUN] ":""}Starting blue/green deployment: ${i.name}`),console.log(` Active environment: ${i.activeEnvironment}`),console.log(` Routing type: ${i.routingConfig.type}`);let c=i.activeEnvironment==="blue"?"green":"blue";if(console.log(` Switching to: ${c}`),console.log(`\\n1. Deploying to ${c} environment`),!n)await new Promise((l)=>setTimeout(l,100));if(console.log(`\\n2. Running health checks on ${c} environment`),i.healthCheckConfig){let l=await this.runHealthChecks(i,c,n);if(s.healthChecksPassed=l,!l){if(s.errors?.push("Health checks failed"),s.endTime=new Date,i.autoRollback)console.log(" Auto-rollback enabled - keeping current environment active"),s.rolledBackAt=new Date;return this.recordDeployment(a,s),s}}else s.healthChecksPassed=!0;if(console.log(`\\n3. Switching traffic to ${c} environment`),!n)i.activeEnvironment=c,s.switchedAt=new Date;if(console.log(`\\n4. Monitoring ${c} environment`),!n)await new Promise((l)=>setTimeout(l,100));return s.success=!0,s.endTime=new Date,console.log("\\n✓ Deployment completed successfully"),this.recordDeployment(a,s),s}async rollback(a){let n=this.deployments.get(a);if(!n)throw Error(`Deployment not found: ${a}`);let i={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!0,errors:[]};console.log(`Rolling back deployment: ${n.name}`);let s=n.activeEnvironment==="blue"?"green":"blue";return n.activeEnvironment=s,i.success=!0,i.rolledBackAt=new Date,i.endTime=new Date,console.log(` Switched back to: ${s}`),this.recordDeployment(a,i),i}async runHealthChecks(a,n,i){let s=a.healthCheckConfig;if(console.log(` Health check path: ${s.path||"/"}`),console.log(` Healthy threshold: ${s.healthyThreshold}`),console.log(` Interval: ${s.interval}s`),i)return console.log(" [SKIPPED - DRY RUN]"),!0;let c=0,l=s.healthyThreshold+2;for(let u=0;u<l;u++)if(await new Promise((h)=>setTimeout(h,50)),Math.random()>0.1){if(c++,console.log(` Check ${u+1}: ✓ Healthy (${c}/${s.healthyThreshold})`),c>=s.healthyThreshold)return!0}else c=0,console.log(` Check ${u+1}: ✗ Unhealthy`);return!1}recordDeployment(a,n){if(!this.deploymentHistory.has(a))this.deploymentHistory.set(a,[]);this.deploymentHistory.get(a).push(n)}getDeployment(a){return this.deployments.get(a)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(a){return this.deploymentHistory.get(a)||[]}generateALBListenerCF(a){let n=a.activeEnvironment==="blue"?a.blueEnvironment:a.greenEnvironment;return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:a.routingConfig.listenerArn,Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",TargetGroupArn:n.targetGroupArn}]}}}generateRoute53RecordSetCF(a,n){return[{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:a.routingConfig.hostedZoneId,Name:n,Type:"A",SetIdentifier:"blue",Weight:a.activeEnvironment==="blue"?100:0,AliasTarget:{HostedZoneId:a.routingConfig.hostedZoneId,DNSName:a.blueEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}},{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:a.routingConfig.hostedZoneId,Name:n,Type:"A",SetIdentifier:"green",Weight:a.activeEnvironment==="green"?100:0,AliasTarget:{HostedZoneId:a.routingConfig.hostedZoneId,DNSName:a.greenEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}}]}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var eC=new eg;class Ks{deployments=new Map;deploymentHistory=new Map;deploymentCounter=0;resultCounter=0;static Strategies={CONSERVATIVE:[{name:"Initial Canary",trafficPercentage:10,durationMinutes:10},{name:"Quarter Traffic",trafficPercentage:25,durationMinutes:10},{name:"Half Traffic",trafficPercentage:50,durationMinutes:15},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}],BALANCED:[{name:"Initial Canary",trafficPercentage:20,durationMinutes:5},{name:"Half Traffic",trafficPercentage:50,durationMinutes:10},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}],AGGRESSIVE:[{name:"Half Traffic",trafficPercentage:50,durationMinutes:5},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}],LINEAR_10:[{name:"Canary 10%",trafficPercentage:10,durationMinutes:5},{name:"Canary 20%",trafficPercentage:20,durationMinutes:5},{name:"Canary 30%",trafficPercentage:30,durationMinutes:5},{name:"Canary 40%",trafficPercentage:40,durationMinutes:5},{name:"Canary 50%",trafficPercentage:50,durationMinutes:5},{name:"Canary 60%",trafficPercentage:60,durationMinutes:5},{name:"Canary 70%",trafficPercentage:70,durationMinutes:5},{name:"Canary 80%",trafficPercentage:80,durationMinutes:5},{name:"Canary 90%",trafficPercentage:90,durationMinutes:5},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}]};createDeployment(a){let n=`canary-${Date.now()}-${this.deploymentCounter++}`,i={id:n,...a};return this.deployments.set(n,i),i}createLambdaCanaryDeployment(a){let n=a.strategy||"BALANCED",i=Ks.Strategies[n].map((s)=>({...s,alarmThresholds:{errorRate:a.errorRateThreshold||1,latencyP99:a.latencyThreshold||1000}}));return this.createDeployment({name:a.name,baselineVersion:{version:"baseline",functionVersionArn:a.baselineVersionArn,weight:100},canaryVersion:{version:"canary",functionVersionArn:a.canaryVersionArn,weight:0},stages:i,currentStage:0,status:"pending",autoPromote:a.autoPromote??!0,autoRollback:!0})}createECSCanaryDeployment(a){let n=a.strategy||"CONSERVATIVE",i=Ks.Strategies[n];return this.createDeployment({name:a.name,baselineVersion:{version:"baseline",taskDefinitionArn:a.baselineTaskDefinitionArn,targetGroupArn:a.baselineTargetGroupArn,weight:100},canaryVersion:{version:"canary",taskDefinitionArn:a.canaryTaskDefinitionArn,targetGroupArn:a.canaryTargetGroupArn,weight:0},stages:i,currentStage:0,status:"pending",autoRollback:!0})}async executeDeployment(a,n=!1){let i=this.deployments.get(a);if(!i)throw Error(`Deployment not found: ${a}`);let s={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,completedStages:0,rolledBack:!1};console.log(`${n?"[DRY RUN] ":""}Starting canary deployment: ${i.name}`),console.log(` Strategy: ${i.stages.length} stages`),console.log(` Auto-promote: ${i.autoPromote}`),console.log(` Auto-rollback: ${i.autoRollback}`),console.log(""),i.status="in_progress";for(let c=0;c<i.stages.length;c++){let l=i.stages[c];if(i.currentStage=c,console.log(`Stage ${c+1}/${i.stages.length}: ${l.name}`),console.log(` Traffic: ${l.trafficPercentage}% canary, ${100-l.trafficPercentage}% baseline`),console.log(` Duration: ${l.durationMinutes} minutes`),!n)i.baselineVersion.weight=100-l.trafficPercentage,i.canaryVersion.weight=l.trafficPercentage;if(!await this.monitorStage(i,l,n)){if(console.log(" ✗ Stage failed - metrics exceeded thresholds"),i.autoRollback)console.log("\\n Rolling back deployment..."),await this.rollback(a,n),s.rolledBack=!0,s.reason="Metrics exceeded thresholds";return s.endTime=new Date,i.status="rolled_back",this.recordDeployment(a,s),s}console.log(" ✓ Stage completed successfully"),s.completedStages++,console.log("")}return i.status="completed",s.success=!0,s.endTime=new Date,console.log("✓ Canary deployment completed successfully"),this.recordDeployment(a,s),s}async monitorStage(a,n,i){if(console.log(" Monitoring metrics..."),i)return console.log(" [SKIPPED - DRY RUN]"),!0;await new Promise((c)=>setTimeout(c,100));let s={baselineErrorRate:Math.random()*0.5,canaryErrorRate:Math.random()*0.8,baselineLatencyP99:200+Math.random()*100,canaryLatencyP99:180+Math.random()*150,baselineRequestCount:Math.floor(Math.random()*1000)+500,canaryRequestCount:Math.floor((Math.random()*1000+500)*n.trafficPercentage/100)};if(a.metrics=s,console.log(` Baseline: ${s.baselineErrorRate.toFixed(2)}% errors, ${s.baselineLatencyP99.toFixed(0)}ms P99`),console.log(` Canary: ${s.canaryErrorRate.toFixed(2)}% errors, ${s.canaryLatencyP99.toFixed(0)}ms P99`),n.alarmThresholds){let{errorRate:c,latencyP99:l}=n.alarmThresholds;if(c&&s.canaryErrorRate>c)return console.log(` ⚠ Error rate exceeded threshold: ${s.canaryErrorRate.toFixed(2)}% > ${c}%`),!1;if(l&&s.canaryLatencyP99>l)return console.log(` ⚠ Latency P99 exceeded threshold: ${s.canaryLatencyP99.toFixed(0)}ms > ${l}ms`),!1}return!0}async rollback(a,n=!1){let i=this.deployments.get(a);if(!i)throw Error(`Deployment not found: ${a}`);if(console.log(`${n?"[DRY RUN] ":""}Rolling back canary deployment: ${i.name}`),!n)i.baselineVersion.weight=100,i.canaryVersion.weight=0,i.status="rolled_back";console.log(" Traffic restored to baseline: 100%")}promoteCanary(a){let n=this.deployments.get(a);if(!n)throw Error(`Deployment not found: ${a}`);console.log(`Promoting canary to baseline: ${n.name}`);let i=n.baselineVersion;n.baselineVersion=n.canaryVersion,n.canaryVersion=i,n.baselineVersion.weight=100,n.canaryVersion.weight=0,n.status="completed",console.log(" Canary promoted successfully")}recordDeployment(a,n){if(!this.deploymentHistory.has(a))this.deploymentHistory.set(a,[]);this.deploymentHistory.get(a).push(n)}getDeployment(a){return this.deployments.get(a)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(a){return this.deploymentHistory.get(a)||[]}generateLambdaAliasCF(a,n){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:{Ref:"LambdaFunction"},Name:n,FunctionVersion:a.canaryVersion.version,RoutingConfig:{AdditionalVersionWeights:[{FunctionVersion:a.baselineVersion.version,FunctionWeight:a.baselineVersion.weight/100}]}}}}generateALBListenerRuleCF(a){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:[{TargetGroupArn:a.baselineVersion.targetGroupArn,Weight:a.baselineVersion.weight},{TargetGroupArn:a.canaryVersion.targetGroupArn,Weight:a.canaryVersion.weight}],TargetGroupStickinessConfig:{Enabled:!1}}}]}}}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var tC=new Ks;class tg{tests=new Map;testCounter=0;createTest(a){let n=`abtest-${Date.now()}-${this.testCounter++}`,i={id:n,...a};return this.tests.set(n,i),i}createSimpleABTest(a){let n=a.variantTrafficPercentage||50;return this.createTest({name:a.name,description:a.description,variants:[{id:"control",name:"Control",description:"Original version",trafficPercentage:100-n,targetGroupArn:a.controlTargetGroupArn,weight:100-n},{id:"variant-a",name:"Variant A",description:"Test version",trafficPercentage:n,targetGroupArn:a.variantTargetGroupArn,weight:n}],routingStrategy:{type:a.stickySession?"cookie":"random",cookieName:a.stickySession?"ab_variant":void 0,stickySession:a.stickySession??!1,sessionDuration:1440},startTime:new Date,status:"draft"})}createMultivariateTest(a){let n=a.variants.reduce((i,s)=>i+s.trafficPercentage,0);if(n!==100)throw Error(`Traffic percentages must sum to 100, got ${n}`);return this.createTest({name:a.name,description:a.description,variants:a.variants.map((i,s)=>({id:`variant-${s}`,name:i.name,description:i.description,trafficPercentage:i.trafficPercentage,targetGroupArn:i.targetGroupArn,weight:i.trafficPercentage})),routingStrategy:a.routingStrategy||{type:"random",stickySession:!1},startTime:new Date,status:"draft"})}createHeaderBasedTest(a){return this.createTest({name:a.name,description:`Route based on ${a.headerName} header`,variants:[{id:"control",name:"Control",trafficPercentage:50,targetGroupArn:a.controlTargetGroupArn,weight:50},{id:"variant-a",name:"Variant A",trafficPercentage:50,targetGroupArn:a.variantTargetGroupArn,weight:50}],routingStrategy:{type:"header",headerName:a.headerName,stickySession:!1},startTime:new Date,status:"draft"})}createGeoBasedTest(a){return this.createTest({name:a.name,description:"Route based on geographic location",variants:[{id:"control",name:"Control (Rest of World)",trafficPercentage:50,targetGroupArn:a.controlTargetGroupArn,weight:50},{id:"variant-a",name:`Variant A (${a.regions.join(", ")})`,trafficPercentage:50,targetGroupArn:a.variantTargetGroupArn,weight:50}],routingStrategy:{type:"geo",stickySession:!0,sessionDuration:1440},startTime:new Date,status:"draft"})}startTest(a){let n=this.tests.get(a);if(!n)throw Error(`Test not found: ${a}`);if(n.status!=="draft"&&n.status!=="paused")throw Error(`Cannot start test in ${n.status} status`);n.status="active",n.startTime=new Date,console.log(`Started A/B test: ${n.name}`),console.log(` Variants: ${n.variants.length}`),n.variants.forEach((i)=>{console.log(` - ${i.name}: ${i.trafficPercentage}%`)})}pauseTest(a){let n=this.tests.get(a);if(!n)throw Error(`Test not found: ${a}`);n.status="paused",console.log(`Paused A/B test: ${n.name}`)}updateTrafficSplit(a,n,i){let s=this.tests.get(a);if(!s)throw Error(`Test not found: ${a}`);let c=s.variants.find((u)=>u.id===n);if(!c)throw Error(`Variant not found: ${n}`);let l=c.trafficPercentage;c.trafficPercentage=i,c.weight=i,console.log(`Updated ${c.name} traffic: ${l}% → ${i}%`)}analyzeResults(a){let n=this.tests.get(a);if(!n)throw Error(`Test not found: ${a}`);if(!n.metrics)n.metrics=this.collectMetrics(n);let i=n.variants[0],s=0;for(let f of n.variants){let S=n.metrics.variants[f.id];if(S&&S.conversionRate>s)s=S.conversionRate,i=f}let c=n.metrics.variants.control||n.metrics.variants[n.variants[0].id],l=n.metrics.variants[i.id],u=(l.conversionRate-c.conversionRate)/c.conversionRate*100,h=100,y=l.requests>h&&c.requests>h&&Math.abs(u)>10;return{testId:a,winningVariant:i.name,confidence:y?95:75,improvement:u,statisticalSignificance:y,metrics:n.metrics,recommendation:this.generateRecommendation(u,y,i.name)}}declareWinner(a,n){let i=this.tests.get(a);if(!i)throw Error(`Test not found: ${a}`);let s=i.variants.find((c)=>c.id===n);if(!s)throw Error(`Variant not found: ${n}`);i.variants.forEach((c)=>{if(c.id===n)c.trafficPercentage=100,c.weight=100;else c.trafficPercentage=0,c.weight=0}),i.status="completed",i.endTime=new Date,i.winner=n,console.log(`Declared winner: ${s.name}`),console.log(` All traffic now routed to ${s.name}`)}collectMetrics(a){let n={},i=0;for(let s of a.variants){let c=Math.floor(Math.random()*1000)+500,l=Math.floor(c*(Math.random()*0.1+0.05)),u=l/c*100;n[s.id]={requests:c,conversions:l,conversionRate:u,averageLatency:150+Math.random()*100,errorRate:Math.random()*0.5,revenue:l*(Math.random()*50+100)},i+=c}return{variants:n,totalRequests:i,startTime:a.startTime,lastUpdated:new Date}}generateRecommendation(a,n,i){if(!n)return"Continue test - sample size too small or no significant difference detected";if(a>20)return`Strong winner detected - ${i} shows ${a.toFixed(1)}% improvement. Recommend deploying to all traffic.`;if(a>10)return`Moderate improvement - ${i} shows ${a.toFixed(1)}% improvement. Consider deploying.`;if(a>0)return`Minor improvement - ${i} shows ${a.toFixed(1)}% improvement. May not be worth the complexity.`;return"No improvement detected - consider reverting to control variant"}getTest(a){return this.tests.get(a)}listTests(){return Array.from(this.tests.values())}generateALBListenerRuleCF(a){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:a.variants.map((n)=>({TargetGroupArn:n.targetGroupArn,Weight:n.weight})),TargetGroupStickinessConfig:{Enabled:a.routingStrategy.stickySession||!1,DurationSeconds:a.routingStrategy.sessionDuration?a.routingStrategy.sessionDuration*60:void 0}}}]}}}generateLambdaEdgeFunction(a){return`'use strict';
|
|
3601
3601
|
|
|
3602
3602
|
exports.handler = (event, _context, _callback) => {
|
|
3603
3603
|
const request = event.Records[0].cf.request;
|
|
@@ -7261,7 +7261,7 @@ function unmarshallTest(item) {
|
|
|
7261
7261
|
|
|
7262
7262
|
return test;
|
|
7263
7263
|
}
|
|
7264
|
-
`;static createAbTestsTable(a){return{[`${a.slug}AbTestsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${a.slug}-ab-tests`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}}static createAbTestManagerLambda(a){return{[`${a.slug}AbTestManagerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-ab-test-manager`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:we.AbTestManagerCode},Environment:{Variables:{AB_TESTS_TABLE:a.abTestsTable}}}}}}static selectVariant(a,n){let i=we.hashString(n+a.id)%100,s=0;for(let c=0;c<a.variants.length;c++)if(s+=a.trafficSplit[c],i<s)return a.variants[c];return a.variants[a.variants.length-1]}static determineWinner(a){if(a.variants.length===0)return null;let n=a.winningCriteria,i=a.variants[0],s=we.getMetricValue(i,n);for(let c of a.variants.slice(1)){let l=we.getMetricValue(c,n);if(l>s)s=l,i=c}return i}static calculateSignificance(a,n,i){let s=a.stats.sent,c=n.stats.sent;if(s<30||c<30)return 0;let l=we.getMetricValue(a,i)/100,u=we.getMetricValue(n,i)/100,h=(l*s+u*c)/(s+c),y=Math.sqrt(h*(1-h)*(1/s+1/c));if(y===0)return 0;let f=Math.abs(l-u)/y;if(f>=2.576)return 99;if(f>=1.96)return 95;if(f>=1.645)return 90;if(f>=1.28)return 80;return Math.round(f*30)}static getMetricValue(a,n){switch(n){case"delivery_rate":return a.stats.deliveryRate;case"click_rate":return a.stats.clickRate;case"reply_rate":return a.stats.replyRate;case"conversion_rate":return a.stats.conversionRate;default:return a.stats.deliveryRate}}static hashString(a){let n=0;for(let i=0;i<a.length;i++){let s=a.charCodeAt(i);n=(n<<5)-n+s,n=n&n}return Math.abs(n)}}class kg{queues=new Map;messageGroups=new Map;deduplicationConfigs=new Map;messages=new Map;queueCounter=0;groupCounter=0;deduplicationCounter=0;messageCounter=0;sequenceCounter=0;createFIFOQueue(a){let n=`fifo-queue-${Date.now()}-${this.queueCounter++}`,i=a.name.endsWith(".fifo")?a.name:`${a.name}.fifo`,{name:s,...c}=a,l={id:n,name:i,queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${i}`,...c};return this.queues.set(n,l),this.createDeduplicationConfig({queueId:n,contentBasedDeduplication:a.contentBasedDeduplication,deduplicationInterval:300}),l}createHighThroughputFIFO(a){return this.createFIFOQueue({name:a.name,contentBasedDeduplication:a.contentBasedDeduplication??!0,deduplicationScope:"messageGroup",fifoThroughputLimit:"perMessageGroupId",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createStandardFIFO(a){return this.createFIFOQueue({name:a.name,contentBasedDeduplication:a.contentBasedDeduplication??!1,deduplicationScope:"queue",fifoThroughputLimit:"perQueue",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createDeduplicationConfig(a){let n={id:`dedup-${Date.now()}-${this.deduplicationCounter++}`,deduplicationHashes:new Map,...a};return this.deduplicationConfigs.set(a.queueId,n),n}sendMessage(a){let n=this.queues.get(a.queueId);if(!n)throw Error(`Queue not found: ${a.queueId}`);let i=this.deduplicationConfigs.get(a.queueId);if(i){let u=a.messageDeduplicationId||(n.contentBasedDeduplication?this.generateHash(a.messageBody):void 0);if(u&&this.isDuplicate(i,u))return null;if(u)i.deduplicationHashes.set(u,new Date)}let s=`msg-${Date.now()}-${this.messageCounter++}`,c=this.generateSequenceNumber(),l={id:s,messageId:s,messageGroupId:a.messageGroupId,messageDeduplicationId:a.messageDeduplicationId,body:a.messageBody,attributes:a.messageAttributes||{},sentTimestamp:new Date,sequenceNumber:c};return this.messages.set(s,l),this.updateMessageGroup(a.queueId,a.messageGroupId),l}isDuplicate(a,n){let i=a.deduplicationHashes.get(n);if(!i)return!1;if((Date.now()-i.getTime())/1000>a.deduplicationInterval)return a.deduplicationHashes.delete(n),!1;return!0}generateHash(a){let n=0;for(let i=0;i<a.length;i++){let s=a.charCodeAt(i);n=(n<<5)-n+s,n=n&n}return Math.abs(n).toString(36)}generateSequenceNumber(){return`${Date.now()}${this.sequenceCounter++}`.padStart(20,"0")}updateMessageGroup(a,n){let i=`${a}-${n}`,s=this.messageGroups.get(i);if(!s)s={id:`group-${Date.now()}-${this.groupCounter++}`,messageGroupId:n,queueId:a,messagesInFlight:0},this.messageGroups.set(i,s);s.messagesInFlight++,s.lastMessageTimestamp=new Date}getMessageGroups(a){return Array.from(this.messageGroups.values()).filter((n)=>n.queueId===a)}getQueue(a){return this.queues.get(a)}listQueues(){return Array.from(this.queues.values())}getMessages(a,n){let i=Array.from(this.messages.values());if(n)i=i.filter((s)=>s.messageGroupId===n);return i.sort((s,c)=>s.sequenceNumber.localeCompare(c.sequenceNumber))}generateFIFOQueueCF(a){return{Type:"AWS::SQS::Queue",Properties:{QueueName:a.name,FifoQueue:!0,ContentBasedDeduplication:a.contentBasedDeduplication,DeduplicationScope:a.deduplicationScope,FifoThroughputLimit:a.fifoThroughputLimit,MessageRetentionPeriod:a.messageRetentionPeriod,VisibilityTimeout:a.visibilityTimeout,ReceiveMessageWaitTimeSeconds:a.receiveMessageWaitTime,...a.deadLetterTargetArn&&{RedrivePolicy:{deadLetterTargetArn:a.deadLetterTargetArn,maxReceiveCount:a.maxReceiveCount||3}}}}}clear(){this.queues.clear(),this.messageGroups.clear(),this.deduplicationConfigs.clear(),this.messages.clear(),this.queueCounter=0,this.groupCounter=0,this.deduplicationCounter=0,this.messageCounter=0,this.sequenceCounter=0}}var xC=new kg;class Bg{monitors=new Map;metrics=new Map;alerts=new Map;reprocessJobs=new Map;monitorCounter=0;metricsCounter=0;alertCounter=0;jobCounter=0;createDLQMonitor(a){let n=`dlq-monitor-${Date.now()}-${this.monitorCounter++}`,i={id:n,...a};return this.monitors.set(n,i),i}createAutomatedMonitor(a){return this.createDLQMonitor({name:a.name,queueUrl:a.queueUrl,sourceQueues:a.sourceQueues,maxReceiveCount:3,alarmThreshold:10,autoReprocess:!0,reprocessStrategy:"scheduled",notificationTopicArn:a.notificationTopicArn})}collectMetrics(a){let n={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:a,timestamp:new Date,approximateNumberOfMessages:Math.floor(Math.random()*100),approximateAgeOfOldestMessage:Math.floor(Math.random()*86400),messagesReceived:Math.floor(Math.random()*50),messagesDeleted:Math.floor(Math.random()*30),messagesReprocessed:Math.floor(Math.random()*20)},i=this.metrics.get(a)||[];return i.push(n),this.metrics.set(a,i),this.checkForAlerts(a,n),n}checkForAlerts(a,n){let i=Array.from(this.monitors.values()).find((c)=>c.queueUrl===a);if(!i)return;if(n.approximateNumberOfMessages>=i.alarmThreshold)this.createAlert({monitorId:i.id,alertType:"threshold_exceeded",severity:"high",message:`DLQ ${i.name} has ${n.approximateNumberOfMessages} messages (threshold: ${i.alarmThreshold})`});let s=3600;if(n.approximateAgeOfOldestMessage>s)this.createAlert({monitorId:i.id,alertType:"old_message",severity:"medium",message:`DLQ ${i.name} has messages older than ${s} seconds`})}createAlert(a){let n=`alert-${Date.now()}-${this.alertCounter++}`,i={id:n,timestamp:new Date,acknowledged:!1,...a};return this.alerts.set(n,i),i}acknowledgeAlert(a){let n=this.alerts.get(a);if(!n)throw Error(`Alert not found: ${a}`);return n.acknowledged=!0,n}createReprocessJob(a){let n=`reprocess-${Date.now()}-${this.jobCounter++}`,i={id:n,queueUrl:a.queueUrl,messageId:a.messageId,attempts:0,status:"pending"};return this.reprocessJobs.set(n,i),i}async executeReprocessJob(a){let n=this.reprocessJobs.get(a);if(!n)throw Error(`Reprocess job not found: ${a}`);n.status="processing",n.startedAt=new Date,n.attempts++,await new Promise((s)=>setTimeout(s,100));let i=Math.random()>0.3;if(n.status=i?"success":"failed",n.completedAt=new Date,!i)n.error="Reprocessing failed - original error still present";return n}async batchReprocess(a){let n=[];for(let i=0;i<a.maxMessages;i++){let s=this.createReprocessJob({queueUrl:a.queueUrl,messageId:`msg-${i}`});await this.executeReprocessJob(s.id),n.push(s)}return n}getDLQStatistics(a,n=24){let i=new Date(Date.now()-n*60*60*1000),s=(this.metrics.get(a)||[]).filter((S)=>S.timestamp>=i);if(s.length===0)return{totalMessages:0,avgAge:0,messagesReceived:0,messagesDeleted:0,messagesReprocessed:0,successRate:0};let c=s[s.length-1],l=s.reduce((S,b)=>S+b.messagesReceived,0),u=s.reduce((S,b)=>S+b.messagesDeleted,0),h=s.reduce((S,b)=>S+b.messagesReprocessed,0),y=s.reduce((S,b)=>S+b.approximateAgeOfOldestMessage,0)/s.length,f=h>0?u/h*100:0;return{totalMessages:c.approximateNumberOfMessages,avgAge:y,messagesReceived:l,messagesDeleted:u,messagesReprocessed:h,successRate:f}}getMonitor(a){return this.monitors.get(a)}listMonitors(){return Array.from(this.monitors.values())}getAlerts(a,n){let i=Array.from(this.alerts.values());if(a)i=i.filter((s)=>s.monitorId===a);if(n!==void 0)i=i.filter((s)=>s.acknowledged===n);return i.sort((s,c)=>c.timestamp.getTime()-s.timestamp.getTime())}getReprocessJobs(a){let n=Array.from(this.reprocessJobs.values());if(a)n=n.filter((i)=>i.queueUrl===a);return n}generateDLQAlarmCF(a){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${a.name}-messages-alarm`,AlarmDescription:`Alert when DLQ ${a.name} exceeds threshold`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Average",Period:300,EvaluationPeriods:1,Threshold:a.alarmThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:a.queueUrl.split("/").pop()}],...a.notificationTopicArn&&{AlarmActions:[a.notificationTopicArn]}}}}clear(){this.monitors.clear(),this.metrics.clear(),this.alerts.clear(),this.reprocessJobs.clear(),this.monitorCounter=0,this.metricsCounter=0,this.alertCounter=0,this.jobCounter=0}}var _C=new Bg;class xg{configs=new Map;jobs=new Map;metrics=new Map;configCounter=0;jobCounter=0;metricsCounter=0;createBatchConfig(a){let n=`batch-config-${Date.now()}-${this.configCounter++}`,i={id:n,...a};return this.configs.set(n,i),i}createHighThroughputConfig(a){return this.createBatchConfig({queueUrl:a.queueUrl,batchSize:10,maxWaitTime:100,parallelProcessors:10,retryAttempts:3,visibilityTimeout:30})}createLowLatencyConfig(a){return this.createBatchConfig({queueUrl:a.queueUrl,batchSize:1,maxWaitTime:0,parallelProcessors:5,retryAttempts:2,visibilityTimeout:10})}createBatchJob(a){let n=`batch-job-${Date.now()}-${this.jobCounter++}`;if(!this.configs.get(a.configId))throw Error(`Batch config not found: ${a.configId}`);let i=[];for(let c=0;c<a.messageCount;c++)i.push({id:`msg-${n}-${c}`,messageId:`${n}-${c}`,body:`Message ${c}`,receiptHandle:`receipt-${n}-${c}`,attributes:{},status:"pending"});let s={id:n,configId:a.configId,messages:i,status:"pending",processedCount:0,failedCount:0};return this.jobs.set(n,s),s}async processBatchJob(a){let n=this.jobs.get(a);if(!n)throw Error(`Batch job not found: ${a}`);let i=this.configs.get(n.configId);if(!i)throw Error(`Batch config not found: ${n.configId}`);n.status="processing",n.startedAt=new Date;let s=this.chunkArray(n.messages,i.batchSize);for(let c of s)await this.processBatch(c,i);return n.processedCount=n.messages.filter((c)=>c.status==="success").length,n.failedCount=n.messages.filter((c)=>c.status==="failed").length,n.status=n.failedCount===0?"completed":"failed",n.completedAt=new Date,this.collectProcessorMetrics(i.id,n),n}async processBatch(a,n){let i=a.map((s)=>this.processMessage(s,n));await Promise.all(i)}async processMessage(a,n){a.status="processing";let i=Date.now();await new Promise((c)=>setTimeout(c,Math.random()*100));let s=Date.now()-i;if(a.processingTime=s,Math.random()>0.1)a.status="success";else a.status="failed",a.error="Processing error"}chunkArray(a,n){let i=[];for(let s=0;s<a.length;s+=n)i.push(a.slice(s,s+n));return i}collectProcessorMetrics(a,n){let i=`metrics-${Date.now()}-${this.metricsCounter++}`,s=n.messages.filter((S)=>S.status==="success").map((S)=>S.processingTime||0).filter((S)=>S>0),c=s.length>0?s.reduce((S,b)=>S+b,0)/s.length:0,l=n.completedAt&&n.startedAt?(n.completedAt.getTime()-n.startedAt.getTime())/1000:1,u=n.processedCount/l,h=n.messages.length>0?n.failedCount/n.messages.length*100:0,y={id:i,configId:a,timestamp:new Date,messagesProcessed:n.processedCount,averageProcessingTime:c,throughput:u,errorRate:h},f=this.metrics.get(a)||[];f.push(y),this.metrics.set(a,f)}getBatchStatistics(a){let n=this.metrics.get(a)||[];if(n.length===0)return{totalJobsProcessed:0,totalMessagesProcessed:0,averageThroughput:0,averageErrorRate:0,averageProcessingTime:0};let i=n.reduce((u,h)=>u+h.messagesProcessed,0),s=n.reduce((u,h)=>u+h.throughput,0)/n.length,c=n.reduce((u,h)=>u+h.errorRate,0)/n.length,l=n.reduce((u,h)=>u+h.averageProcessingTime,0)/n.length;return{totalJobsProcessed:n.length,totalMessagesProcessed:i,averageThroughput:s,averageErrorRate:c,averageProcessingTime:l}}optimizeBatchConfig(a){let n=this.configs.get(a);if(!n)throw Error(`Batch config not found: ${a}`);let i=this.getBatchStatistics(a);if(i.averageErrorRate<5&&n.batchSize<10)n.batchSize=Math.min(10,n.batchSize+1);if(i.averageErrorRate>20&&n.batchSize>1)n.batchSize=Math.max(1,n.batchSize-1);if(i.averageThroughput<5&&n.parallelProcessors<20)n.parallelProcessors++;return n}getConfig(a){return this.configs.get(a)}listConfigs(){return Array.from(this.configs.values())}getJob(a){return this.jobs.get(a)}listJobs(a){let n=Array.from(this.jobs.values());if(a)n=n.filter((i)=>i.configId===a);return n}generateBatchProcessorCF(a){return{Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:`arn:aws:sqs:us-east-1:123456789012:${a.queueUrl.split("/").pop()}`,FunctionName:"batch-processor-function",BatchSize:a.batchSize,MaximumBatchingWindowInSeconds:a.maxWaitTime/1000,FunctionResponseTypes:["ReportBatchItemFailures"]}}}clear(){this.configs.clear(),this.jobs.clear(),this.metrics.clear(),this.configCounter=0,this.jobCounter=0,this.metricsCounter=0}}var OC=new xg;class _g{queues=new Map;retentionPolicies=new Map;delayQueues=new Map;purgeOperations=new Map;metrics=new Map;queueCounter=0;retentionCounter=0;delayCounter=0;purgeCounter=0;metricsCounter=0;createQueue(a){let n=`queue-${Date.now()}-${this.queueCounter++}`,i={id:n,purgeInProgress:!1,...a};return this.queues.set(n,i),i}createStandardQueue(a){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${a.queueName}`,queueName:a.queueName,messageRetentionPeriod:(a.messageRetentionDays||4)*24*60*60,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:0})}createLongPollingQueue(a){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${a.queueName}`,queueName:a.queueName,messageRetentionPeriod:345600,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:a.waitTimeSeconds||20})}createRetentionPolicy(a){let n=`retention-${Date.now()}-${this.retentionCounter++}`,i={id:n,...a};this.retentionPolicies.set(n,i);let s=this.queues.get(a.queueId);if(s)s.messageRetentionPeriod=a.retentionPeriod;return i}createShortRetentionPolicy(a){return this.createRetentionPolicy({queueId:a.queueId,retentionPeriod:a.retentionHours*60*60,autoCleanup:!0,archiveExpiredMessages:!1})}createArchivalRetentionPolicy(a){return this.createRetentionPolicy({queueId:a.queueId,retentionPeriod:a.retentionDays*24*60*60,autoCleanup:!0,cleanupSchedule:"cron(0 0 * * ? *)",archiveExpiredMessages:!0,archiveS3Bucket:a.s3Bucket})}createDelayQueue(a){let n=`delay-${Date.now()}-${this.delayCounter++}`,i={id:n,...a};this.delayQueues.set(n,i);let s=Array.from(this.queues.values()).find((c)=>c.queueUrl===a.queueUrl);if(s)s.delaySeconds=a.defaultDelay;return i}createScheduledDelayQueue(a){return this.createDelayQueue({queueUrl:a.queueUrl,defaultDelay:a.delayMinutes*60,perMessageDelay:!1,maxDelay:900})}async purgeQueue(a){let n=this.queues.get(a);if(!n)throw Error(`Queue not found: ${a}`);if(n.purgeInProgress)throw Error("Purge already in progress for this queue");let i=`purge-${Date.now()}-${this.purgeCounter++}`,s={id:i,queueUrl:n.queueUrl,status:"in_progress",startedAt:new Date};return this.purgeOperations.set(i,s),n.purgeInProgress=!0,setTimeout(()=>{s.status="completed",s.completedAt=new Date,s.messagesPurged=Math.floor(Math.random()*1000),n.purgeInProgress=!1},100),s}collectQueueMetrics(a){let n={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:a,timestamp:new Date,approximateNumberOfMessages:Math.floor(Math.random()*1000),approximateNumberOfMessagesNotVisible:Math.floor(Math.random()*100),approximateNumberOfMessagesDelayed:Math.floor(Math.random()*50),oldestMessageAge:Math.floor(Math.random()*86400)},i=this.metrics.get(a)||[];return i.push(n),this.metrics.set(a,i),n}getQueueHealth(a){let n=this.metrics.get(a)||[];if(n.length===0)return{status:"healthy",issues:[],recommendations:[]};let i=n[n.length-1],s=[],c=[],l="healthy";if(i.approximateNumberOfMessages>1e4)l="critical",s.push("Large message backlog detected"),c.push("Increase consumer capacity");else if(i.approximateNumberOfMessages>1000)l="warning",s.push("Growing message backlog"),c.push("Monitor consumer performance");if(i.oldestMessageAge&&i.oldestMessageAge>3600){if(l!=="critical")l="warning";s.push("Old messages in queue"),c.push("Review message processing")}if(i.approximateNumberOfMessagesDelayed>100){if(l!=="critical")l="warning";s.push("High number of delayed messages")}return{status:l,issues:s,recommendations:c}}getQueue(a){return this.queues.get(a)}listQueues(){return Array.from(this.queues.values())}getRetentionPolicy(a){return this.retentionPolicies.get(a)}listRetentionPolicies(){return Array.from(this.retentionPolicies.values())}getPurgeOperations(a){let n=Array.from(this.purgeOperations.values());if(a)n=n.filter((i)=>i.queueUrl===a);return n}generateQueueCF(a){return{Type:"AWS::SQS::Queue",Properties:{QueueName:a.queueName,MessageRetentionPeriod:a.messageRetentionPeriod,DelaySeconds:a.delaySeconds,MaximumMessageSize:a.maximumMessageSize,ReceiveMessageWaitTimeSeconds:a.receiveMessageWaitTime}}}generateCleanupRuleCF(a){return{Type:"AWS::Events::Rule",Properties:{Name:`${a.id}-cleanup`,Description:"Automated queue cleanup",ScheduleExpression:a.cleanupSchedule||"cron(0 0 * * ? *)",State:"ENABLED",Targets:[{Arn:"arn:aws:lambda:us-east-1:123456789012:function:queue-cleanup",Id:a.id,Input:JSON.stringify({queueId:a.queueId,archiveBucket:a.archiveS3Bucket})}]}}}clear(){this.queues.clear(),this.retentionPolicies.clear(),this.delayQueues.clear(),this.purgeOperations.clear(),this.metrics.clear(),this.queueCounter=0,this.retentionCounter=0,this.delayCounter=0,this.purgeCounter=0,this.metricsCounter=0}}var LC=new _g,_n=(()=>{let a=[];for(let n=0;n<256;n++){let i=n;for(let s=0;s<8;s++)i=i&1?3988292384^i>>>1:i>>>1;a[n]=i>>>0}return a})();function Wn(a){let n=4294967295;for(let i=0;i<a.length;i++)n=_n[(n^a[i])&255]^n>>>8;return(n^4294967295)>>>0}function Gn(a){if(typeof a==="string")return Buffer.from(a,"utf-8");if(Buffer.isBuffer(a))return a;return Buffer.from(a)}function Un(a){let n=Math.max(1980,a.getFullYear()),i=(a.getHours()<<11|a.getMinutes()<<5|a.getSeconds()>>1)&65535,s=(n-1980<<9|a.getMonth()+1<<5|a.getDate())&65535;return{time:i,date:s}}function mi(a){let n=[],i=[],s=0;for(let u of a){let h=Gn(u.data),y=Bn(h),f=Wn(h),S=Buffer.from(u.name.replace(/\\/g,"/"),"utf-8"),{time:b,date:C}=Un(u.date??new Date(0)),T=u.mode??420,v=Buffer.alloc(30+S.length);v.writeUInt32LE(67324752,0),v.writeUInt16LE(20,4),v.writeUInt16LE(0,6),v.writeUInt16LE(8,8),v.writeUInt16LE(b,10),v.writeUInt16LE(C,12),v.writeUInt32LE(f,14),v.writeUInt32LE(y.length,18),v.writeUInt32LE(h.length,22),v.writeUInt16LE(S.length,26),v.writeUInt16LE(0,28),S.copy(v,30);let w=Buffer.alloc(46+S.length);w.writeUInt32LE(33639248,0),w.writeUInt16LE(798,4),w.writeUInt16LE(20,6),w.writeUInt16LE(0,8),w.writeUInt16LE(8,10),w.writeUInt16LE(b,12),w.writeUInt16LE(C,14),w.writeUInt32LE(f,16),w.writeUInt32LE(y.length,20),w.writeUInt32LE(h.length,24),w.writeUInt16LE(S.length,28),w.writeUInt16LE(0,30),w.writeUInt16LE(0,32),w.writeUInt16LE(0,34),w.writeUInt16LE(0,36),w.writeUInt32LE((T&65535)<<16,38),w.writeUInt32LE(s,42),S.copy(w,46),n.push(v,y),i.push(w),s+=v.length+y.length}let c=Buffer.concat(i),l=Buffer.alloc(22);return l.writeUInt32LE(101010256,0),l.writeUInt16LE(0,4),l.writeUInt16LE(0,6),l.writeUInt16LE(a.length,8),l.writeUInt16LE(a.length,10),l.writeUInt32LE(c.length,12),l.writeUInt32LE(s,16),l.writeUInt16LE(0,20),Buffer.concat([...n,c,l])}function zf(a){let n=a.adapterImport??"./adapter",i=a.entryImport.replace(/\\/g,"/");return`// Generated by ts-cloud — serverless app bootstrap. Do not edit.
|
|
7264
|
+
`;static createAbTestsTable(a){return{[`${a.slug}AbTestsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${a.slug}-ab-tests`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}}static createAbTestManagerLambda(a){return{[`${a.slug}AbTestManagerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${a.slug}-ab-test-manager`,Runtime:"nodejs20.x",Handler:"index.handler",Role:a.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:we.AbTestManagerCode},Environment:{Variables:{AB_TESTS_TABLE:a.abTestsTable}}}}}}static selectVariant(a,n){let i=we.hashString(n+a.id)%100,s=0;for(let c=0;c<a.variants.length;c++)if(s+=a.trafficSplit[c],i<s)return a.variants[c];return a.variants[a.variants.length-1]}static determineWinner(a){if(a.variants.length===0)return null;let n=a.winningCriteria,i=a.variants[0],s=we.getMetricValue(i,n);for(let c of a.variants.slice(1)){let l=we.getMetricValue(c,n);if(l>s)s=l,i=c}return i}static calculateSignificance(a,n,i){let s=a.stats.sent,c=n.stats.sent;if(s<30||c<30)return 0;let l=we.getMetricValue(a,i)/100,u=we.getMetricValue(n,i)/100,h=(l*s+u*c)/(s+c),y=Math.sqrt(h*(1-h)*(1/s+1/c));if(y===0)return 0;let f=Math.abs(l-u)/y;if(f>=2.576)return 99;if(f>=1.96)return 95;if(f>=1.645)return 90;if(f>=1.28)return 80;return Math.round(f*30)}static getMetricValue(a,n){switch(n){case"delivery_rate":return a.stats.deliveryRate;case"click_rate":return a.stats.clickRate;case"reply_rate":return a.stats.replyRate;case"conversion_rate":return a.stats.conversionRate;default:return a.stats.deliveryRate}}static hashString(a){let n=0;for(let i=0;i<a.length;i++){let s=a.charCodeAt(i);n=(n<<5)-n+s,n=n&n}return Math.abs(n)}}class kg{queues=new Map;messageGroups=new Map;deduplicationConfigs=new Map;messages=new Map;queueCounter=0;groupCounter=0;deduplicationCounter=0;messageCounter=0;sequenceCounter=0;createFIFOQueue(a){let n=`fifo-queue-${Date.now()}-${this.queueCounter++}`,i=a.name.endsWith(".fifo")?a.name:`${a.name}.fifo`,{name:s,...c}=a,l={id:n,name:i,queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${i}`,...c};return this.queues.set(n,l),this.createDeduplicationConfig({queueId:n,contentBasedDeduplication:a.contentBasedDeduplication,deduplicationInterval:300}),l}createHighThroughputFIFO(a){return this.createFIFOQueue({name:a.name,contentBasedDeduplication:a.contentBasedDeduplication??!0,deduplicationScope:"messageGroup",fifoThroughputLimit:"perMessageGroupId",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createStandardFIFO(a){return this.createFIFOQueue({name:a.name,contentBasedDeduplication:a.contentBasedDeduplication??!1,deduplicationScope:"queue",fifoThroughputLimit:"perQueue",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createDeduplicationConfig(a){let n={id:`dedup-${Date.now()}-${this.deduplicationCounter++}`,deduplicationHashes:new Map,...a};return this.deduplicationConfigs.set(a.queueId,n),n}sendMessage(a){let n=this.queues.get(a.queueId);if(!n)throw Error(`Queue not found: ${a.queueId}`);let i=this.deduplicationConfigs.get(a.queueId);if(i){let u=a.messageDeduplicationId||(n.contentBasedDeduplication?this.generateHash(a.messageBody):void 0);if(u&&this.isDuplicate(i,u))return null;if(u)i.deduplicationHashes.set(u,new Date)}let s=`msg-${Date.now()}-${this.messageCounter++}`,c=this.generateSequenceNumber(),l={id:s,messageId:s,messageGroupId:a.messageGroupId,messageDeduplicationId:a.messageDeduplicationId,body:a.messageBody,attributes:a.messageAttributes||{},sentTimestamp:new Date,sequenceNumber:c};return this.messages.set(s,l),this.updateMessageGroup(a.queueId,a.messageGroupId),l}isDuplicate(a,n){let i=a.deduplicationHashes.get(n);if(!i)return!1;if((Date.now()-i.getTime())/1000>a.deduplicationInterval)return a.deduplicationHashes.delete(n),!1;return!0}generateHash(a){let n=0;for(let i=0;i<a.length;i++){let s=a.charCodeAt(i);n=(n<<5)-n+s,n=n&n}return Math.abs(n).toString(36)}generateSequenceNumber(){return`${Date.now()}${this.sequenceCounter++}`.padStart(20,"0")}updateMessageGroup(a,n){let i=`${a}-${n}`,s=this.messageGroups.get(i);if(!s)s={id:`group-${Date.now()}-${this.groupCounter++}`,messageGroupId:n,queueId:a,messagesInFlight:0},this.messageGroups.set(i,s);s.messagesInFlight++,s.lastMessageTimestamp=new Date}getMessageGroups(a){return Array.from(this.messageGroups.values()).filter((n)=>n.queueId===a)}getQueue(a){return this.queues.get(a)}listQueues(){return Array.from(this.queues.values())}getMessages(a,n){let i=Array.from(this.messages.values());if(n)i=i.filter((s)=>s.messageGroupId===n);return i.sort((s,c)=>s.sequenceNumber.localeCompare(c.sequenceNumber))}generateFIFOQueueCF(a){return{Type:"AWS::SQS::Queue",Properties:{QueueName:a.name,FifoQueue:!0,ContentBasedDeduplication:a.contentBasedDeduplication,DeduplicationScope:a.deduplicationScope,FifoThroughputLimit:a.fifoThroughputLimit,MessageRetentionPeriod:a.messageRetentionPeriod,VisibilityTimeout:a.visibilityTimeout,ReceiveMessageWaitTimeSeconds:a.receiveMessageWaitTime,...a.deadLetterTargetArn&&{RedrivePolicy:{deadLetterTargetArn:a.deadLetterTargetArn,maxReceiveCount:a.maxReceiveCount||3}}}}}clear(){this.queues.clear(),this.messageGroups.clear(),this.deduplicationConfigs.clear(),this.messages.clear(),this.queueCounter=0,this.groupCounter=0,this.deduplicationCounter=0,this.messageCounter=0,this.sequenceCounter=0}}var xC=new kg;class Bg{monitors=new Map;metrics=new Map;alerts=new Map;reprocessJobs=new Map;monitorCounter=0;metricsCounter=0;alertCounter=0;jobCounter=0;createDLQMonitor(a){let n=`dlq-monitor-${Date.now()}-${this.monitorCounter++}`,i={id:n,...a};return this.monitors.set(n,i),i}createAutomatedMonitor(a){return this.createDLQMonitor({name:a.name,queueUrl:a.queueUrl,sourceQueues:a.sourceQueues,maxReceiveCount:3,alarmThreshold:10,autoReprocess:!0,reprocessStrategy:"scheduled",notificationTopicArn:a.notificationTopicArn})}collectMetrics(a){let n={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:a,timestamp:new Date,approximateNumberOfMessages:Math.floor(Math.random()*100),approximateAgeOfOldestMessage:Math.floor(Math.random()*86400),messagesReceived:Math.floor(Math.random()*50),messagesDeleted:Math.floor(Math.random()*30),messagesReprocessed:Math.floor(Math.random()*20)},i=this.metrics.get(a)||[];return i.push(n),this.metrics.set(a,i),this.checkForAlerts(a,n),n}checkForAlerts(a,n){let i=Array.from(this.monitors.values()).find((c)=>c.queueUrl===a);if(!i)return;if(n.approximateNumberOfMessages>=i.alarmThreshold)this.createAlert({monitorId:i.id,alertType:"threshold_exceeded",severity:"high",message:`DLQ ${i.name} has ${n.approximateNumberOfMessages} messages (threshold: ${i.alarmThreshold})`});let s=3600;if(n.approximateAgeOfOldestMessage>s)this.createAlert({monitorId:i.id,alertType:"old_message",severity:"medium",message:`DLQ ${i.name} has messages older than ${s} seconds`})}createAlert(a){let n=`alert-${Date.now()}-${this.alertCounter++}`,i={id:n,timestamp:new Date,acknowledged:!1,...a};return this.alerts.set(n,i),i}acknowledgeAlert(a){let n=this.alerts.get(a);if(!n)throw Error(`Alert not found: ${a}`);return n.acknowledged=!0,n}createReprocessJob(a){let n=`reprocess-${Date.now()}-${this.jobCounter++}`,i={id:n,queueUrl:a.queueUrl,messageId:a.messageId,attempts:0,status:"pending"};return this.reprocessJobs.set(n,i),i}async executeReprocessJob(a){let n=this.reprocessJobs.get(a);if(!n)throw Error(`Reprocess job not found: ${a}`);n.status="processing",n.startedAt=new Date,n.attempts++,await new Promise((s)=>setTimeout(s,100));let i=Math.random()>0.3;if(n.status=i?"success":"failed",n.completedAt=new Date,!i)n.error="Reprocessing failed - original error still present";return n}async batchReprocess(a){let n=[];for(let i=0;i<a.maxMessages;i++){let s=this.createReprocessJob({queueUrl:a.queueUrl,messageId:`msg-${i}`});await this.executeReprocessJob(s.id),n.push(s)}return n}getDLQStatistics(a,n=24){let i=new Date(Date.now()-n*60*60*1000),s=(this.metrics.get(a)||[]).filter((S)=>S.timestamp>=i);if(s.length===0)return{totalMessages:0,avgAge:0,messagesReceived:0,messagesDeleted:0,messagesReprocessed:0,successRate:0};let c=s[s.length-1],l=s.reduce((S,b)=>S+b.messagesReceived,0),u=s.reduce((S,b)=>S+b.messagesDeleted,0),h=s.reduce((S,b)=>S+b.messagesReprocessed,0),y=s.reduce((S,b)=>S+b.approximateAgeOfOldestMessage,0)/s.length,f=h>0?u/h*100:0;return{totalMessages:c.approximateNumberOfMessages,avgAge:y,messagesReceived:l,messagesDeleted:u,messagesReprocessed:h,successRate:f}}getMonitor(a){return this.monitors.get(a)}listMonitors(){return Array.from(this.monitors.values())}getAlerts(a,n){let i=Array.from(this.alerts.values());if(a)i=i.filter((s)=>s.monitorId===a);if(n!==void 0)i=i.filter((s)=>s.acknowledged===n);return i.sort((s,c)=>c.timestamp.getTime()-s.timestamp.getTime())}getReprocessJobs(a){let n=Array.from(this.reprocessJobs.values());if(a)n=n.filter((i)=>i.queueUrl===a);return n}generateDLQAlarmCF(a){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${a.name}-messages-alarm`,AlarmDescription:`Alert when DLQ ${a.name} exceeds threshold`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Average",Period:300,EvaluationPeriods:1,Threshold:a.alarmThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:a.queueUrl.split("/").pop()}],...a.notificationTopicArn&&{AlarmActions:[a.notificationTopicArn]}}}}clear(){this.monitors.clear(),this.metrics.clear(),this.alerts.clear(),this.reprocessJobs.clear(),this.monitorCounter=0,this.metricsCounter=0,this.alertCounter=0,this.jobCounter=0}}var _C=new Bg;class xg{configs=new Map;jobs=new Map;metrics=new Map;configCounter=0;jobCounter=0;metricsCounter=0;createBatchConfig(a){let n=`batch-config-${Date.now()}-${this.configCounter++}`,i={id:n,...a};return this.configs.set(n,i),i}createHighThroughputConfig(a){return this.createBatchConfig({queueUrl:a.queueUrl,batchSize:10,maxWaitTime:100,parallelProcessors:10,retryAttempts:3,visibilityTimeout:30})}createLowLatencyConfig(a){return this.createBatchConfig({queueUrl:a.queueUrl,batchSize:1,maxWaitTime:0,parallelProcessors:5,retryAttempts:2,visibilityTimeout:10})}createBatchJob(a){let n=`batch-job-${Date.now()}-${this.jobCounter++}`;if(!this.configs.get(a.configId))throw Error(`Batch config not found: ${a.configId}`);let i=[];for(let c=0;c<a.messageCount;c++)i.push({id:`msg-${n}-${c}`,messageId:`${n}-${c}`,body:`Message ${c}`,receiptHandle:`receipt-${n}-${c}`,attributes:{},status:"pending"});let s={id:n,configId:a.configId,messages:i,status:"pending",processedCount:0,failedCount:0};return this.jobs.set(n,s),s}async processBatchJob(a){let n=this.jobs.get(a);if(!n)throw Error(`Batch job not found: ${a}`);let i=this.configs.get(n.configId);if(!i)throw Error(`Batch config not found: ${n.configId}`);n.status="processing",n.startedAt=new Date;let s=this.chunkArray(n.messages,i.batchSize);for(let c of s)await this.processBatch(c,i);return n.processedCount=n.messages.filter((c)=>c.status==="success").length,n.failedCount=n.messages.filter((c)=>c.status==="failed").length,n.status=n.failedCount===0?"completed":"failed",n.completedAt=new Date,this.collectProcessorMetrics(i.id,n),n}async processBatch(a,n){let i=a.map((s)=>this.processMessage(s,n));await Promise.all(i)}async processMessage(a,n){a.status="processing";let i=Date.now();await new Promise((c)=>setTimeout(c,Math.random()*100));let s=Date.now()-i;if(a.processingTime=s,Math.random()>0.1)a.status="success";else a.status="failed",a.error="Processing error"}chunkArray(a,n){let i=[];for(let s=0;s<a.length;s+=n)i.push(a.slice(s,s+n));return i}collectProcessorMetrics(a,n){let i=`metrics-${Date.now()}-${this.metricsCounter++}`,s=n.messages.filter((S)=>S.status==="success").map((S)=>S.processingTime||0).filter((S)=>S>0),c=s.length>0?s.reduce((S,b)=>S+b,0)/s.length:0,l=n.completedAt&&n.startedAt?(n.completedAt.getTime()-n.startedAt.getTime())/1000:1,u=n.processedCount/l,h=n.messages.length>0?n.failedCount/n.messages.length*100:0,y={id:i,configId:a,timestamp:new Date,messagesProcessed:n.processedCount,averageProcessingTime:c,throughput:u,errorRate:h},f=this.metrics.get(a)||[];f.push(y),this.metrics.set(a,f)}getBatchStatistics(a){let n=this.metrics.get(a)||[];if(n.length===0)return{totalJobsProcessed:0,totalMessagesProcessed:0,averageThroughput:0,averageErrorRate:0,averageProcessingTime:0};let i=n.reduce((u,h)=>u+h.messagesProcessed,0),s=n.reduce((u,h)=>u+h.throughput,0)/n.length,c=n.reduce((u,h)=>u+h.errorRate,0)/n.length,l=n.reduce((u,h)=>u+h.averageProcessingTime,0)/n.length;return{totalJobsProcessed:n.length,totalMessagesProcessed:i,averageThroughput:s,averageErrorRate:c,averageProcessingTime:l}}optimizeBatchConfig(a){let n=this.configs.get(a);if(!n)throw Error(`Batch config not found: ${a}`);let i=this.getBatchStatistics(a);if(i.averageErrorRate<5&&n.batchSize<10)n.batchSize=Math.min(10,n.batchSize+1);if(i.averageErrorRate>20&&n.batchSize>1)n.batchSize=Math.max(1,n.batchSize-1);if(i.averageThroughput<5&&n.parallelProcessors<20)n.parallelProcessors++;return n}getConfig(a){return this.configs.get(a)}listConfigs(){return Array.from(this.configs.values())}getJob(a){return this.jobs.get(a)}listJobs(a){let n=Array.from(this.jobs.values());if(a)n=n.filter((i)=>i.configId===a);return n}generateBatchProcessorCF(a){return{Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:`arn:aws:sqs:us-east-1:123456789012:${a.queueUrl.split("/").pop()}`,FunctionName:"batch-processor-function",BatchSize:a.batchSize,MaximumBatchingWindowInSeconds:a.maxWaitTime/1000,FunctionResponseTypes:["ReportBatchItemFailures"]}}}clear(){this.configs.clear(),this.jobs.clear(),this.metrics.clear(),this.configCounter=0,this.jobCounter=0,this.metricsCounter=0}}var OC=new xg;class _g{queues=new Map;retentionPolicies=new Map;delayQueues=new Map;purgeOperations=new Map;metrics=new Map;queueCounter=0;retentionCounter=0;delayCounter=0;purgeCounter=0;metricsCounter=0;createQueue(a){let n=`queue-${Date.now()}-${this.queueCounter++}`,i={id:n,purgeInProgress:!1,...a};return this.queues.set(n,i),i}createStandardQueue(a){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${a.queueName}`,queueName:a.queueName,messageRetentionPeriod:(a.messageRetentionDays||4)*24*60*60,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:0})}createLongPollingQueue(a){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${a.queueName}`,queueName:a.queueName,messageRetentionPeriod:345600,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:a.waitTimeSeconds||20})}createRetentionPolicy(a){let n=`retention-${Date.now()}-${this.retentionCounter++}`,i={id:n,...a};this.retentionPolicies.set(n,i);let s=this.queues.get(a.queueId);if(s)s.messageRetentionPeriod=a.retentionPeriod;return i}createShortRetentionPolicy(a){return this.createRetentionPolicy({queueId:a.queueId,retentionPeriod:a.retentionHours*60*60,autoCleanup:!0,archiveExpiredMessages:!1})}createArchivalRetentionPolicy(a){return this.createRetentionPolicy({queueId:a.queueId,retentionPeriod:a.retentionDays*24*60*60,autoCleanup:!0,cleanupSchedule:"cron(0 0 * * ? *)",archiveExpiredMessages:!0,archiveS3Bucket:a.s3Bucket})}createDelayQueue(a){let n=`delay-${Date.now()}-${this.delayCounter++}`,i={id:n,...a};this.delayQueues.set(n,i);let s=Array.from(this.queues.values()).find((c)=>c.queueUrl===a.queueUrl);if(s)s.delaySeconds=a.defaultDelay;return i}createScheduledDelayQueue(a){return this.createDelayQueue({queueUrl:a.queueUrl,defaultDelay:a.delayMinutes*60,perMessageDelay:!1,maxDelay:900})}async purgeQueue(a){let n=this.queues.get(a);if(!n)throw Error(`Queue not found: ${a}`);if(n.purgeInProgress)throw Error("Purge already in progress for this queue");let i=`purge-${Date.now()}-${this.purgeCounter++}`,s={id:i,queueUrl:n.queueUrl,status:"in_progress",startedAt:new Date};return this.purgeOperations.set(i,s),n.purgeInProgress=!0,setTimeout(()=>{s.status="completed",s.completedAt=new Date,s.messagesPurged=Math.floor(Math.random()*1000),n.purgeInProgress=!1},100),s}collectQueueMetrics(a){let n={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:a,timestamp:new Date,approximateNumberOfMessages:Math.floor(Math.random()*1000),approximateNumberOfMessagesNotVisible:Math.floor(Math.random()*100),approximateNumberOfMessagesDelayed:Math.floor(Math.random()*50),oldestMessageAge:Math.floor(Math.random()*86400)},i=this.metrics.get(a)||[];return i.push(n),this.metrics.set(a,i),n}getQueueHealth(a){let n=this.metrics.get(a)||[];if(n.length===0)return{status:"healthy",issues:[],recommendations:[]};let i=n[n.length-1],s=[],c=[],l="healthy";if(i.approximateNumberOfMessages>1e4)l="critical",s.push("Large message backlog detected"),c.push("Increase consumer capacity");else if(i.approximateNumberOfMessages>1000)l="warning",s.push("Growing message backlog"),c.push("Monitor consumer performance");if(i.oldestMessageAge&&i.oldestMessageAge>3600){if(l!=="critical")l="warning";s.push("Old messages in queue"),c.push("Review message processing")}if(i.approximateNumberOfMessagesDelayed>100){if(l!=="critical")l="warning";s.push("High number of delayed messages")}return{status:l,issues:s,recommendations:c}}getQueue(a){return this.queues.get(a)}listQueues(){return Array.from(this.queues.values())}getRetentionPolicy(a){return this.retentionPolicies.get(a)}listRetentionPolicies(){return Array.from(this.retentionPolicies.values())}getPurgeOperations(a){let n=Array.from(this.purgeOperations.values());if(a)n=n.filter((i)=>i.queueUrl===a);return n}generateQueueCF(a){return{Type:"AWS::SQS::Queue",Properties:{QueueName:a.queueName,MessageRetentionPeriod:a.messageRetentionPeriod,DelaySeconds:a.delaySeconds,MaximumMessageSize:a.maximumMessageSize,ReceiveMessageWaitTimeSeconds:a.receiveMessageWaitTime}}}generateCleanupRuleCF(a){return{Type:"AWS::Events::Rule",Properties:{Name:`${a.id}-cleanup`,Description:"Automated queue cleanup",ScheduleExpression:a.cleanupSchedule||"cron(0 0 * * ? *)",State:"ENABLED",Targets:[{Arn:"arn:aws:lambda:us-east-1:123456789012:function:queue-cleanup",Id:a.id,Input:JSON.stringify({queueId:a.queueId,archiveBucket:a.archiveS3Bucket})}]}}}clear(){this.queues.clear(),this.retentionPolicies.clear(),this.delayQueues.clear(),this.purgeOperations.clear(),this.metrics.clear(),this.queueCounter=0,this.retentionCounter=0,this.delayCounter=0,this.purgeCounter=0,this.metricsCounter=0}}var LC=new _g,_n=(()=>{let a=[];for(let n=0;n<256;n++){let i=n;for(let s=0;s<8;s++)i=i&1?3988292384^i>>>1:i>>>1;a[n]=i>>>0}return a})();function Wn(a){let n=4294967295;for(let i=0;i<a.length;i++)n=_n[(n^a[i])&255]^n>>>8;return(n^4294967295)>>>0}function Gn(a){if(typeof a==="string")return Buffer.from(a,"utf-8");if(Buffer.isBuffer(a))return a;return Buffer.from(a)}function Un(a){let n=Math.max(1980,a.getFullYear()),i=(a.getHours()<<11|a.getMinutes()<<5|a.getSeconds()>>1)&65535,s=(n-1980<<9|a.getMonth()+1<<5|a.getDate())&65535;return{time:i,date:s}}function hi(a){let n=[],i=[],s=0;for(let u of a){let h=Gn(u.data),y=Bn(h),f=Wn(h),S=Buffer.from(u.name.replace(/\\/g,"/"),"utf-8"),{time:b,date:C}=Un(u.date??new Date(0)),T=u.mode??420,v=Buffer.alloc(30+S.length);v.writeUInt32LE(67324752,0),v.writeUInt16LE(20,4),v.writeUInt16LE(0,6),v.writeUInt16LE(8,8),v.writeUInt16LE(b,10),v.writeUInt16LE(C,12),v.writeUInt32LE(f,14),v.writeUInt32LE(y.length,18),v.writeUInt32LE(h.length,22),v.writeUInt16LE(S.length,26),v.writeUInt16LE(0,28),S.copy(v,30);let w=Buffer.alloc(46+S.length);w.writeUInt32LE(33639248,0),w.writeUInt16LE(798,4),w.writeUInt16LE(20,6),w.writeUInt16LE(0,8),w.writeUInt16LE(8,10),w.writeUInt16LE(b,12),w.writeUInt16LE(C,14),w.writeUInt32LE(f,16),w.writeUInt32LE(y.length,20),w.writeUInt32LE(h.length,24),w.writeUInt16LE(S.length,28),w.writeUInt16LE(0,30),w.writeUInt16LE(0,32),w.writeUInt16LE(0,34),w.writeUInt16LE(0,36),w.writeUInt32LE((T&65535)<<16,38),w.writeUInt32LE(s,42),S.copy(w,46),n.push(v,y),i.push(w),s+=v.length+y.length}let c=Buffer.concat(i),l=Buffer.alloc(22);return l.writeUInt32LE(101010256,0),l.writeUInt16LE(0,4),l.writeUInt16LE(0,6),l.writeUInt16LE(a.length,8),l.writeUInt16LE(a.length,10),l.writeUInt32LE(c.length,12),l.writeUInt32LE(s,16),l.writeUInt16LE(0,20),Buffer.concat([...n,c,l])}function zf(a){let n=a.adapterImport??"./adapter",i=a.entryImport.replace(/\\/g,"/");return`// Generated by ts-cloud — serverless app bootstrap. Do not edit.
|
|
7265
7265
|
import * as __userModule from ${JSON.stringify(i)}
|
|
7266
7266
|
import { resolveApp, createHandlers } from ${JSON.stringify(n)}
|
|
7267
7267
|
|
|
@@ -7271,9 +7271,9 @@ const __handlers = createHandlers(__app)
|
|
|
7271
7271
|
export const http = __handlers.http
|
|
7272
7272
|
export const queue = __handlers.queue
|
|
7273
7273
|
export const cli = __handlers.cli
|
|
7274
|
-
`}var Xn=["adapter.ts","recursion.ts","auto-recursion.ts"];function ei(){return Le(Qn(Zn(import.meta.url)),"runtime")}function Kf(a,n,i){for(let s of a??[])i?.(`build: ${s}`),Fn(s,{stdio:"inherit",cwd:n})}function
|
|
7274
|
+
`}var Xn=["adapter.ts","recursion.ts","auto-recursion.ts"];function ei(){return Le(Qn(Zn(import.meta.url)),"runtime")}function Kf(a,n,i){for(let s of a??[])i?.(`build: ${s}`),Fn(s,{stdio:"inherit",cwd:n})}function Ws(a){return Vn("sha256").update(a).digest("hex")}function dd(a,n,i){return`deployments/${a}/${n}/${i}.zip`}async function _r(a){let n=Yn(a.projectRoot??process.cwd()),{app:i}=a;if(!a.skipBuild)Kf(i.build,n,a.onStep);let s=i.entry;if(!s)throw Error("serverless app: `entry` is required to package a Node/Bun application");let c=Jn(s)?s:Le(n,s),l=Kn(Le(zn(),"tscloud-pkg-"));try{for(let C of Xn)jn(Le(ei(),C),Le(l,C));let u=Le(l,"bootstrap.ts");qn(u,zf({entryImport:c,adapterImport:"./adapter"})),a.onStep?.("bundling application");let h=await Bun.build({entrypoints:[u],target:i.kind==="bun"?"bun":"node",format:"esm",minify:!1,sourcemap:"none"});if(!h.success){let C=h.logs.map((T)=>String(T)).join(`
|
|
7275
7275
|
`);throw Error(`serverless app bundle failed:
|
|
7276
|
-
${C}`)}let y=h.outputs[0],f=Buffer.from(await y.arrayBuffer()),S="index",b=mi([{name:`${S}.mjs`,data:f}]);return{zip:b,bundle:f,sha256:Ks(b),handlerFile:S,handlers:{http:i.handlers?.http??`${S}.http`,queue:i.handlers?.queue??`${S}.queue`,cli:i.handlers?.cli??`${S}.cli`},bundleBytes:f.length}}finally{Hn(l,{recursive:!0,force:!0})}}var Wf=["18","20","22"];function ti(a){if(!a)return"22";let n=String(a).match(/(\d+)/);return n?n[1]:"22"}function Ws(a){let n=a.kind??"node";if(n==="php")return{lambdaRuntime:"provided.al2023",kind:"php",version:a.phpVersion??"8.3",usesLayer:!0,layerKind:"php",layerEnvVar:"TSCLOUD_PHP_LAYER_ARN"};if(n==="bun")return{lambdaRuntime:"provided.al2023",kind:"bun",version:a.runtimeVersion??"latest",usesLayer:!0,layerKind:"bun",layerEnvVar:"TSCLOUD_BUN_LAYER_ARN"};let i=ti(a.runtimeVersion);if(a.runtime!=="provided.al2023"&&Wf.includes(i))return{lambdaRuntime:a.runtime&&a.runtime.startsWith("nodejs")?a.runtime:`nodejs${i}.x`,kind:"node",version:i,usesLayer:!1};return{lambdaRuntime:"provided.al2023",kind:"node",version:i,usesLayer:!0,layerKind:"node",layerEnvVar:"TSCLOUD_NODE_LAYER_ARN"}}function Gt(a,n,i){if(a.queues===!1)return[];if(a.queues===void 0||a.queues===!0)return[{name:`${n}-${i}-default`}];return a.queues.map((s)=>{if(typeof s==="string")return{name:`${n}-${i}-${s}`};let[c,l]=Object.entries(s)[0];return{name:`${n}-${i}-${c}`,concurrency:l}})}function ld(a,n,i){return Gt(a,n,i).map((s)=>s.name)}function ud(a){let{app:n,environment:i,handlers:s}=a,c=a.config.project.slug,l=Ws(n).lambdaRuntime,u=n.architecture??"x86_64",h=a.config.project.region,y={http:`${c}-${i}-http`,queue:`${c}-${i}-queue`,cli:`${c}-${i}-cli`};if(n.gatewayVersion===1)throw Error("serverless app: `gatewayVersion: 1` (REST API) is not supported — ts-cloud uses API Gateway HTTP API (v2). Remove `gatewayVersion` or set it to 2.");let f=Gt(n,c,i),S=f.map((z)=>z.name),b=S.length>0,C=n.logRetention??14,T=n.packaging==="image";if(T&&n.lambdaInsights)throw Error("serverless app: `lambdaInsights` layer attachment is only supported for zip packaging. Container images must install the Lambda Insights extension in the image.");let v=(n.scheduler??"on")!=="off",w=(n.cache?.driver??"dynamodb")==="dynamodb",R=Boolean(n.assets),k=Qs(c,i),W=n.tmpStorage??512,P={},V={},B=[{PolicyName:"tscloud-serverless-app",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:e.sub("arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*")},{Effect:"Allow",Action:["lambda:InvokeFunction"],Resource:e.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${c}-${i}-*`)},{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameter","ssm:GetParameters","ssm:GetParametersByPath"],Resource:[e.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${c}/${i}/*`),e.sub(`arn:aws:ssm:\${AWS::Region}:\${AWS::AccountId}:parameter/${c}/${i}/*`)]},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[e.sub(`arn:aws:s3:::${k}`),e.sub(`arn:aws:s3:::${k}/*`),...n.storage?.bucket?[e.sub(`arn:aws:s3:::${n.storage.bucket}`),e.sub(`arn:aws:s3:::${n.storage.bucket}/*`)]:[]]}]}}];if(b)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["sqs:SendMessage","sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes","sqs:GetQueueUrl"],Resource:e.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${c}-${i}-*`)});if(w)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:BatchGetItem","dynamodb:BatchWriteItem"],Resource:e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${c}-${i}-cache*`)});let j=["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"];if(n.vpc?.subnets?.length)j.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");if(n.lambdaInsights)j.push("arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy");P.AppRole={Type:"AWS::IAM::Role",Properties:{RoleName:`${c}-${i}-app-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:j,Policies:B}};let Z=(z)=>({TSCLOUD_LAMBDA_MODE:z,TSCLOUD_ENV:i,...n.octane?{TSCLOUD_OCTANE:"1"}:{},...n.scheduler==="sub-minute"?{TSCLOUD_SCHEDULER:"sub-minute"}:{},...w?{TSCLOUD_CACHE_TABLE:`${c}-${i}-cache`}:{},...b?{TSCLOUD_QUEUE:S[0]}:{},...n.env??{}}),K=Boolean(n.efs),ee=typeof n.efs==="object"?n.efs:{},te=ee.mountPath??"/mnt/local",ie=K&&!ee.accessPointArn,me=ee.accessPointArn??(ie?e.getAtt("EfsAccessPoint","Arn"):void 0),ce=n.vpc?.subnets??[],ue=ce.length>0,se=n.cache?.driver==="elasticache"||n.database?.connection==="aurora-serverless"||Boolean(n.rdsProxy)||K;if(se&&!ue)throw Error("serverless app: elasticache / aurora-serverless / rdsProxy / efs require app.vpc.subnets (private subnets) to be set.");let Ie=ue?{VpcConfig:{SubnetIds:ce,SecurityGroupIds:[...n.vpc?.securityGroups??[],...se?[e.getAtt("DataSecurityGroup","GroupId")]:[]]}}:{},We=ie?ce.map((z,ne)=>`EfsMountTarget${ne}`):[],Ct=K?{FileSystemConfigs:[{Arn:me,LocalMountPath:te}]}:{};if(K)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess","elasticfilesystem:DescribeMountTargets"],Resource:"*"});function pe(z,ne,re,oe,ye,tt,Te,rt=W){P[`${z}LogGroup`]={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:`/aws/lambda/${ne}`,RetentionInDays:C}};let Tt=[...a.runtimeLayers??[],...n.lambdaInsights?[n.lambdaInsights.layerArn]:[]],vt=T?{PackageType:"Image",Code:{ImageUri:e.ref("ImageUri")},...n.kind==="php"?{}:{ImageConfig:{Command:[re]}}}:{Runtime:l,Handler:re,Code:{S3Bucket:e.ref("ArtifactBucket"),S3Key:e.ref("ArtifactKey")},...Tt.length?{Layers:[...new Set(Tt)]}:{}};P[z]={Type:"AWS::Lambda::Function",DependsOn:[`${z}LogGroup`,...We],Properties:{FunctionName:ne,Architectures:[u],MemorySize:ye,Timeout:tt,Role:e.getAtt("AppRole","Arn"),Environment:{Variables:Z(oe)},EphemeralStorage:{Size:rt},...vt,...Te!==void 0?{ReservedConcurrentExecutions:Te}:{},...Ie,...Ct}}}if(pe("HttpFunction",y.http,s.http,"http",n.memory??1024,n.timeout??28,n.concurrency,W),pe("CliFunction",y.cli,s.cli,"cli",n.cliMemory??1024,n.cliTimeout??900,void 0,n.cliTmpStorage??W),b)pe("QueueFunction",y.queue,s.queue,"queue",n.queueMemory??1024,n.queueTimeout??120,void 0,n.queueTmpStorage??W);let de=(n.provisionedConcurrency??0)>0?n.provisionedConcurrency:0,ge=["HttpFunction","CliFunction",...b?["QueueFunction"]:[]];if(de)for(let z of ge)P[`${z}Version`]={Type:"AWS::Lambda::Version",DeletionPolicy:"Retain",Properties:{FunctionName:e.ref(z)}},P[`${z}Alias`]={Type:"AWS::Lambda::Alias",Properties:{FunctionName:e.ref(z),Name:"live",FunctionVersion:e.getAtt(`${z}Version`,"Version"),ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:de}}};let Re=(z)=>de?e.ref(`${z}Alias`):e.getAtt(z,"Arn"),he=(z)=>de?e.ref(`${z}Alias`):e.ref(z);P.HttpApi={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:`${c}-${i}`,ProtocolType:"HTTP"}},P.HttpIntegration={Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:e.ref("HttpApi"),IntegrationType:"AWS_PROXY",IntegrationUri:Re("HttpFunction"),PayloadFormatVersion:"2.0"}},P.HttpRoute={Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:e.ref("HttpApi"),RouteKey:"$default",Target:e.join("/",["integrations",e.ref("HttpIntegration")])}},P.HttpStage={Type:"AWS::ApiGatewayV2::Stage",Properties:{ApiId:e.ref("HttpApi"),StageName:"$default",AutoDeploy:!0}},P.HttpPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:he("HttpFunction"),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:e.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${HttpApi}/*/*")}},V.HttpApiEndpoint={Description:"HTTP API endpoint",Value:e.getAtt("HttpApi","ApiEndpoint")},V.HttpApiId={Description:"HTTP API id",Value:e.ref("HttpApi")};let Ae=(Array.isArray(n.domain)?n.domain:n.domain?[n.domain]:[]).filter(Boolean);if(Ae.length){if(!n.certificateArn&&!n.hostedZoneId)throw Error("serverless app: a custom `domain` needs either `certificateArn` (pre-issued, regional) or `hostedZoneId` (to auto-issue + validate an ACM cert).");let z=n.certificateArn;if(!z)P.HttpCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:Ae[0],...Ae.length>1?{SubjectAlternativeNames:Ae.slice(1)}:{},ValidationMethod:"DNS",DomainValidationOptions:Ae.map((ne)=>({DomainName:ne,HostedZoneId:n.hostedZoneId}))}},z=e.ref("HttpCertificate");Ae.forEach((ne,re)=>{let oe=`HttpDomain${re}`;if(P[oe]={Type:"AWS::ApiGatewayV2::DomainName",Properties:{DomainName:ne,DomainNameConfigurations:[{CertificateArn:z,EndpointType:"REGIONAL"}]}},P[`HttpApiMapping${re}`]={Type:"AWS::ApiGatewayV2::ApiMapping",DependsOn:["HttpStage"],Properties:{ApiId:e.ref("HttpApi"),DomainName:e.ref(oe),Stage:"$default"}},n.hostedZoneId)P[`HttpDomainRecord${re}`]={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:ne,Type:"A",AliasTarget:{DNSName:e.getAtt(oe,"RegionalDomainName"),HostedZoneId:e.getAtt(oe,"RegionalHostedZoneId")}}};V[`CustomDomain${re}`]={Description:`Custom domain ${ne}`,Value:ne},V[`CustomDomainTarget${re}`]={Description:`Point ${ne} (CNAME/alias) at this APIGW regional domain`,Value:e.getAtt(oe,"RegionalDomainName")}})}if(b)P.AppQueueDlq={Type:"AWS::SQS::Queue",Properties:{QueueName:`${c}-${i}-dlq`,MessageRetentionPeriod:1209600}},f.forEach((z,ne)=>{let re=`AppQueue${ne}`,oe=n.queueTimeout??120;P[re]={Type:"AWS::SQS::Queue",Properties:{QueueName:z.name,VisibilityTimeout:Math.min(43200,oe*6),RedrivePolicy:{deadLetterTargetArn:e.getAtt("AppQueueDlq","Arn"),maxReceiveCount:n.queueTries??3}}};let ye=z.concurrency??n.queueConcurrency;P[`${re}Mapping`]={Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:e.getAtt(re,"Arn"),FunctionName:he("QueueFunction"),BatchSize:1,FunctionResponseTypes:["ReportBatchItemFailures"],...ye?{ScalingConfig:{MaximumConcurrency:Math.max(2,ye)}}:{}}},V[`QueueUrl${ne}`]={Description:`Queue URL: ${z.name}`,Value:e.ref(re)}});if(v)P.SchedulerRule={Type:"AWS::Events::Rule",Properties:{Name:`${c}-${i}-scheduler`,ScheduleExpression:"rate(1 minute)",State:"ENABLED",Targets:[{Id:"cli",Arn:Re("CliFunction"),Input:JSON.stringify({command:"schedule:run"})}]}},P.SchedulerPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:he("CliFunction"),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.getAtt("SchedulerRule","Arn")}};if(n.warm&&n.warm>0){let z={http:"HttpFunction",queue:"QueueFunction",cli:"CliFunction"},ne=(n.warmFunctions??["http"]).filter((re)=>re!=="queue"||b);for(let re of ne){let oe=re.charAt(0).toUpperCase()+re.slice(1),ye=Math.ceil(n.warm/5),tt=0;for(let Te=0;Te<ye;Te++){let rt=Math.min(5,n.warm-tt);P[`Warmer${oe}Rule${Te}`]={Type:"AWS::Events::Rule",Properties:{Name:`${c}-${i}-warmer-${re}-${Te}`,ScheduleExpression:"rate(5 minutes)",State:"ENABLED",Targets:Array.from({length:rt},(Tt,vt)=>({Id:`warm-${re}-${Te}-${vt}`,Arn:e.getAtt(z[re],"Arn"),Input:JSON.stringify({warmer:!0})}))}},tt+=rt}P[`Warmer${oe}Permission`]={Type:"AWS::Lambda::Permission",Properties:{FunctionName:e.ref(z[re]),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.sub(`arn:aws:events:\${AWS::Region}:\${AWS::AccountId}:rule/${c}-${i}-warmer-${re}-*`)}}}}if(w)P.CacheTable={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${c}-${i}-cache`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"key",AttributeType:"S"}],KeySchema:[{AttributeName:"key",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"expires_at",Enabled:!0}}},V.CacheTableName={Description:"DynamoDB cache table",Value:e.ref("CacheTable")};if(R){if(P.AssetsBucket={Type:"AWS::S3::Bucket",Properties:{BucketName:k,PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}}},P.AssetsOAC={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${c}-${i}-assets-oac`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},P.AssetsDistribution={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,DefaultCacheBehavior:{TargetOriginId:"assets",ViewerProtocolPolicy:"redirect-to-https",Compress:!0,CachePolicyId:"658327ea-f89d-4fab-a63d-7e88639e58f6"},Origins:[{Id:"assets",DomainName:e.getAtt("AssetsBucket","RegionalDomainName"),OriginAccessControlId:e.ref("AssetsOAC"),S3OriginConfig:{OriginAccessIdentity:""}}],...n.assetDomain?{Aliases:[n.assetDomain],ViewerCertificate:{AcmCertificateArn:n.assetCertificateArn??e.ref("AssetsCertificate"),SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}}:{}}}},n.assetDomain){if(!n.assetCertificateArn){if(!n.hostedZoneId)throw Error("serverless app: `assetDomain` requires either `assetCertificateArn` (a us-east-1 ACM cert) or `hostedZoneId` (to auto-issue + validate one). CloudFront only accepts certs from us-east-1.");if(h!=="us-east-1")throw Error(`serverless app: auto-issuing an asset-domain cert needs a us-east-1 app (CloudFront certs must be us-east-1); this app is in ${h}. Supply a pre-issued us-east-1 \`assetCertificateArn\` instead.`);P.AssetsCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:n.assetDomain,ValidationMethod:"DNS",DomainValidationOptions:[{DomainName:n.assetDomain,HostedZoneId:n.hostedZoneId}]}}}if(n.hostedZoneId)P.AssetsDomainRecord={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:n.assetDomain,Type:"A",AliasTarget:{DNSName:e.getAtt("AssetsDistribution","DomainName"),HostedZoneId:"Z2FDTNDATAQYW2"}}};V.AssetDomain={Description:"Custom asset CDN host",Value:n.assetDomain}}P.AssetsBucketPolicy={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:e.ref("AssetsBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:e.sub(`arn:aws:s3:::${k}/*`),Condition:{StringEquals:{"AWS:SourceArn":e.sub("arn:aws:cloudfront::${AWS::AccountId}:distribution/${AssetsDistribution}")}}}]}}},V.AssetsBucketName={Description:"Assets bucket",Value:e.ref("AssetsBucket")},V.AssetsCdnDomain={Description:"Assets CloudFront domain",Value:e.getAtt("AssetsDistribution","DomainName")}}if(n.firewall?.enabled){let z=[],ne=0;if(n.firewall.rateLimit)z.push({Name:"rate-limit",Priority:ne++,Action:{Block:{}},Statement:{RateBasedStatement:{Limit:n.firewall.rateLimit,AggregateKeyType:"IP"}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${i}-rate`}});let re={sqlInjection:"AWSManagedRulesSQLiRuleSet",xss:"AWSManagedRulesCommonRuleSet",common:"AWSManagedRulesCommonRuleSet",botControl:"AWSManagedRulesBotControlRuleSet",ipReputation:"AWSManagedRulesAmazonIpReputationList"};for(let oe of n.firewall.rules??[]){let ye=re[oe];if(!ye)continue;z.push({Name:`managed-${oe}`,Priority:ne++,OverrideAction:{None:{}},Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:ye}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${i}-${oe}`}})}P.WebAcl={Type:"AWS::WAFv2::WebACL",Properties:{Name:`${c}-${i}-waf`,Scope:"REGIONAL",DefaultAction:{Allow:{}},Rules:z,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${i}-waf`}}},V.WafAclArn={Description:"WAF web ACL ARN. Attach to a CloudFront distribution fronting the API to enforce (HTTP API v2 stages do not support direct WAF association).",Value:e.getAtt("WebAcl","Arn")}}if(ue&&se){if(!n.vpc?.id)throw Error("serverless app: data services (elasticache / aurora-serverless / rdsProxy / efs) need app.vpc.id (the VPC id) so the managed security group is created in the right VPC.");P.DataSecurityGroup={Type:"AWS::EC2::SecurityGroup",Properties:{VpcId:n.vpc.id,GroupDescription:`${c}-${i} serverless data access`,SecurityGroupIngress:[{IpProtocol:"-1",CidrIp:"10.0.0.0/8"}]}}}if(ie)P.EfsFileSystem={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:!0,FileSystemTags:[{Key:"Name",Value:`${c}-${i}-efs`}]}},ce.forEach((z,ne)=>{P[`EfsMountTarget${ne}`]={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:e.ref("EfsFileSystem"),SubnetId:z,SecurityGroups:[e.getAtt("DataSecurityGroup","GroupId")]}}}),P.EfsAccessPoint={Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:e.ref("EfsFileSystem"),PosixUser:{Uid:1001,Gid:1001},RootDirectory:{Path:"/lambda",CreationInfo:{OwnerUid:1001,OwnerGid:1001,Permissions:"0755"}}}},V.EfsFileSystemId={Description:"EFS file system id",Value:e.ref("EfsFileSystem")};if(n.cache?.driver==="elasticache")P.CacheSubnetGroup={Type:"AWS::ElastiCache::SubnetGroup",Properties:{Description:`${c}-${i} cache subnets`,SubnetIds:ce}},P.CacheCluster={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:`${c}-${i}-cache`,ReplicationGroupDescription:`${c}-${i} redis`,Engine:"redis",CacheNodeType:"cache.t4g.micro",NumCacheClusters:1,AutomaticFailoverEnabled:!1,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),SecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")],TransitEncryptionEnabled:!1}},V.CacheEndpoint={Description:"Redis primary endpoint",Value:e.getAtt("CacheCluster","PrimaryEndPoint.Address")};if(n.database?.connection==="aurora-serverless")P.DbSubnetGroup={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupDescription:`${c}-${i} db subnets`,SubnetIds:ce}},P.DbSecret={Type:"AWS::SecretsManager::Secret",Properties:{Name:`${c}/${i}/db`,GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"app"}),GenerateStringKey:"password",PasswordLength:32,ExcludePunctuation:!0}}},P.DbCluster={Type:"AWS::RDS::DBCluster",Properties:{Engine:"aurora-mysql",EngineMode:"provisioned",DBClusterIdentifier:`${c}-${i}-db`,DatabaseName:"app",MasterUsername:e.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:username}}"),MasterUserPassword:e.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:password}}"),ServerlessV2ScalingConfiguration:{MinCapacity:n.database?.minCapacity??0.5,MaxCapacity:n.database?.maxCapacity??4},DBSubnetGroupName:e.ref("DbSubnetGroup"),VpcSecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")]}},P.DbInstance={Type:"AWS::RDS::DBInstance",Properties:{Engine:"aurora-mysql",DBInstanceClass:"db.serverless",DBClusterIdentifier:e.ref("DbCluster")}},V.DbEndpoint={Description:"Aurora cluster endpoint",Value:e.getAtt("DbCluster","Endpoint.Address")};if(n.rdsProxy&&n.database?.connection==="aurora-serverless")P.DbProxyRole={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"rds.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"read-db-secret",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue"],Resource:e.ref("DbSecret")}]}}]}},P.DbProxy={Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:typeof n.rdsProxy==="object"&&n.rdsProxy.name?n.rdsProxy.name:`${c}-${i}-proxy`,EngineFamily:"MYSQL",RoleArn:e.getAtt("DbProxyRole","Arn"),Auth:[{AuthScheme:"SECRETS",SecretArn:e.ref("DbSecret"),IAMAuth:"DISABLED"}],VpcSubnetIds:ce,VpcSecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")],RequireTLS:!1}},P.DbProxyTargetGroup={Type:"AWS::RDS::DBProxyTargetGroup",DependsOn:["DbInstance"],Properties:{DBProxyName:e.ref("DbProxy"),TargetGroupName:"default",DBClusterIdentifiers:[e.ref("DbCluster")]}},V.DbProxyEndpoint={Description:"RDS Proxy endpoint",Value:e.getAtt("DbProxy","Endpoint")};if(V.HttpFunctionName={Description:"HTTP function name",Value:e.ref("HttpFunction")},V.CliFunctionName={Description:"CLI function name",Value:e.ref("CliFunction")},b)V.QueueFunctionName={Description:"Queue function name",Value:e.ref("QueueFunction")};let $e={AWSTemplateFormatVersion:"2010-09-09",Description:`Serverless application for ${a.config.project.name} (${c}-${i})`,Parameters:T?{ImageUri:{Type:"String",Description:"ECR image URI of the deployment artifact"}}:{ArtifactBucket:{Type:"String",Description:"S3 bucket holding the deployment artifact"},ArtifactKey:{Type:"String",Description:"S3 key of the deployment artifact (zip)"}},Resources:P,Outputs:V},Ge={};for(let z of Object.values(P))Ge[z.Type]=(Ge[z.Type]??0)+1;return{template:$e,functionNames:y,queueNames:S,resourceSummary:Ge}}var Jf=["cli","fpm","curl","mbstring","xml","pdo","mysqlnd","gd","bcmath","intl","opcache","sodium","process","pecl-redis6","pecl-apcu","pgsql"];function Xf(a){let n=`php${a.replace(".","")}`;return Jf.map((i)=>`${n}-php-${i}`)}function Og(a,n){let i=`php${a.replace(".","")}`,s=Xf(a).join(" \\\n "),c=`/opt/remi/${i}/root`,l=`/etc/opt/remi/${i}`;return`${n?`FROM almalinux:9 AS ${n}`:"FROM almalinux:9"}
|
|
7276
|
+
${C}`)}let y=h.outputs[0],f=Buffer.from(await y.arrayBuffer()),S="index",b=hi([{name:`${S}.mjs`,data:f}]);return{zip:b,bundle:f,sha256:Ws(b),handlerFile:S,handlers:{http:i.handlers?.http??`${S}.http`,queue:i.handlers?.queue??`${S}.queue`,cli:i.handlers?.cli??`${S}.cli`},bundleBytes:f.length}}finally{Hn(l,{recursive:!0,force:!0})}}var Wf=["18","20","22"];function ti(a){if(!a)return"22";let n=String(a).match(/(\d+)/);return n?n[1]:"22"}function Js(a){let n=a.kind??"node";if(n==="php")return{lambdaRuntime:"provided.al2023",kind:"php",version:a.phpVersion??"8.3",usesLayer:!0,layerKind:"php",layerEnvVar:"TSCLOUD_PHP_LAYER_ARN"};if(n==="bun")return{lambdaRuntime:"provided.al2023",kind:"bun",version:a.runtimeVersion??"latest",usesLayer:!0,layerKind:"bun",layerEnvVar:"TSCLOUD_BUN_LAYER_ARN"};let i=ti(a.runtimeVersion);if(a.runtime!=="provided.al2023"&&Wf.includes(i))return{lambdaRuntime:a.runtime&&a.runtime.startsWith("nodejs")?a.runtime:`nodejs${i}.x`,kind:"node",version:i,usesLayer:!1};return{lambdaRuntime:"provided.al2023",kind:"node",version:i,usesLayer:!0,layerKind:"node",layerEnvVar:"TSCLOUD_NODE_LAYER_ARN"}}function Gt(a,n,i){if(a.queues===!1)return[];if(a.queues===void 0||a.queues===!0)return[{name:`${n}-${i}-default`}];return a.queues.map((s)=>{if(typeof s==="string")return{name:`${n}-${i}-${s}`};let[c,l]=Object.entries(s)[0];return{name:`${n}-${i}-${c}`,concurrency:l}})}function ld(a,n,i){return Gt(a,n,i).map((s)=>s.name)}function ud(a){let{app:n,environment:i,handlers:s}=a,c=a.config.project.slug,l=Js(n).lambdaRuntime,u=n.architecture??"x86_64",h=a.config.project.region,y={http:`${c}-${i}-http`,queue:`${c}-${i}-queue`,cli:`${c}-${i}-cli`};if(n.gatewayVersion===1)throw Error("serverless app: `gatewayVersion: 1` (REST API) is not supported — ts-cloud uses API Gateway HTTP API (v2). Remove `gatewayVersion` or set it to 2.");let f=Gt(n,c,i),S=f.map((z)=>z.name),b=S.length>0,C=n.logRetention??14,T=n.packaging==="image";if(T&&n.lambdaInsights)throw Error("serverless app: `lambdaInsights` layer attachment is only supported for zip packaging. Container images must install the Lambda Insights extension in the image.");let v=(n.scheduler??"on")!=="off",w=(n.cache?.driver??"dynamodb")==="dynamodb",R=Boolean(n.assets),k=Hs(c,i),W=n.tmpStorage??512,P={},V={},B=[{PolicyName:"tscloud-serverless-app",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:e.sub("arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*")},{Effect:"Allow",Action:["lambda:InvokeFunction"],Resource:e.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${c}-${i}-*`)},{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameter","ssm:GetParameters","ssm:GetParametersByPath"],Resource:[e.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${c}/${i}/*`),e.sub(`arn:aws:ssm:\${AWS::Region}:\${AWS::AccountId}:parameter/${c}/${i}/*`)]},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[e.sub(`arn:aws:s3:::${k}`),e.sub(`arn:aws:s3:::${k}/*`),...n.storage?.bucket?[e.sub(`arn:aws:s3:::${n.storage.bucket}`),e.sub(`arn:aws:s3:::${n.storage.bucket}/*`)]:[]]}]}}];if(b)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["sqs:SendMessage","sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes","sqs:GetQueueUrl"],Resource:e.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${c}-${i}-*`)});if(w)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:BatchGetItem","dynamodb:BatchWriteItem"],Resource:e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${c}-${i}-cache*`)});let j=["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"];if(n.vpc?.subnets?.length)j.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");if(n.lambdaInsights)j.push("arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy");P.AppRole={Type:"AWS::IAM::Role",Properties:{RoleName:`${c}-${i}-app-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:j,Policies:B}};let Z=(z)=>({TSCLOUD_LAMBDA_MODE:z,TSCLOUD_ENV:i,...n.octane?{TSCLOUD_OCTANE:"1"}:{},...n.scheduler==="sub-minute"?{TSCLOUD_SCHEDULER:"sub-minute"}:{},...w?{TSCLOUD_CACHE_TABLE:`${c}-${i}-cache`}:{},...b?{TSCLOUD_QUEUE:S[0]}:{},...n.env??{}}),K=Boolean(n.efs),ee=typeof n.efs==="object"?n.efs:{},te=ee.mountPath??"/mnt/local",ie=K&&!ee.accessPointArn,me=ee.accessPointArn??(ie?e.getAtt("EfsAccessPoint","Arn"):void 0),ce=n.vpc?.subnets??[],ue=ce.length>0,se=n.cache?.driver==="elasticache"||n.database?.connection==="aurora-serverless"||Boolean(n.rdsProxy)||K;if(se&&!ue)throw Error("serverless app: elasticache / aurora-serverless / rdsProxy / efs require app.vpc.subnets (private subnets) to be set.");let Ie=ue?{VpcConfig:{SubnetIds:ce,SecurityGroupIds:[...n.vpc?.securityGroups??[],...se?[e.getAtt("DataSecurityGroup","GroupId")]:[]]}}:{},We=ie?ce.map((z,ne)=>`EfsMountTarget${ne}`):[],Ct=K?{FileSystemConfigs:[{Arn:me,LocalMountPath:te}]}:{};if(K)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess","elasticfilesystem:DescribeMountTargets"],Resource:"*"});function pe(z,ne,re,oe,ye,tt,Te,rt=W){P[`${z}LogGroup`]={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:`/aws/lambda/${ne}`,RetentionInDays:C}};let Tt=[...a.runtimeLayers??[],...n.lambdaInsights?[n.lambdaInsights.layerArn]:[]],vt=T?{PackageType:"Image",Code:{ImageUri:e.ref("ImageUri")},...n.kind==="php"?{}:{ImageConfig:{Command:[re]}}}:{Runtime:l,Handler:re,Code:{S3Bucket:e.ref("ArtifactBucket"),S3Key:e.ref("ArtifactKey")},...Tt.length?{Layers:[...new Set(Tt)]}:{}};P[z]={Type:"AWS::Lambda::Function",DependsOn:[`${z}LogGroup`,...We],Properties:{FunctionName:ne,Architectures:[u],MemorySize:ye,Timeout:tt,Role:e.getAtt("AppRole","Arn"),Environment:{Variables:Z(oe)},EphemeralStorage:{Size:rt},...vt,...Te!==void 0?{ReservedConcurrentExecutions:Te}:{},...Ie,...Ct}}}if(pe("HttpFunction",y.http,s.http,"http",n.memory??1024,n.timeout??28,n.concurrency,W),pe("CliFunction",y.cli,s.cli,"cli",n.cliMemory??1024,n.cliTimeout??900,void 0,n.cliTmpStorage??W),b)pe("QueueFunction",y.queue,s.queue,"queue",n.queueMemory??1024,n.queueTimeout??120,void 0,n.queueTmpStorage??W);let de=(n.provisionedConcurrency??0)>0?n.provisionedConcurrency:0,ge=["HttpFunction","CliFunction",...b?["QueueFunction"]:[]];if(de)for(let z of ge)P[`${z}Version`]={Type:"AWS::Lambda::Version",DeletionPolicy:"Retain",Properties:{FunctionName:e.ref(z)}},P[`${z}Alias`]={Type:"AWS::Lambda::Alias",Properties:{FunctionName:e.ref(z),Name:"live",FunctionVersion:e.getAtt(`${z}Version`,"Version"),ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:de}}};let Re=(z)=>de?e.ref(`${z}Alias`):e.getAtt(z,"Arn"),he=(z)=>de?e.ref(`${z}Alias`):e.ref(z);P.HttpApi={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:`${c}-${i}`,ProtocolType:"HTTP"}},P.HttpIntegration={Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:e.ref("HttpApi"),IntegrationType:"AWS_PROXY",IntegrationUri:Re("HttpFunction"),PayloadFormatVersion:"2.0"}},P.HttpRoute={Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:e.ref("HttpApi"),RouteKey:"$default",Target:e.join("/",["integrations",e.ref("HttpIntegration")])}},P.HttpStage={Type:"AWS::ApiGatewayV2::Stage",Properties:{ApiId:e.ref("HttpApi"),StageName:"$default",AutoDeploy:!0}},P.HttpPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:he("HttpFunction"),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:e.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${HttpApi}/*/*")}},V.HttpApiEndpoint={Description:"HTTP API endpoint",Value:e.getAtt("HttpApi","ApiEndpoint")},V.HttpApiId={Description:"HTTP API id",Value:e.ref("HttpApi")};let Ae=(Array.isArray(n.domain)?n.domain:n.domain?[n.domain]:[]).filter(Boolean);if(Ae.length){if(!n.certificateArn&&!n.hostedZoneId)throw Error("serverless app: a custom `domain` needs either `certificateArn` (pre-issued, regional) or `hostedZoneId` (to auto-issue + validate an ACM cert).");let z=n.certificateArn;if(!z)P.HttpCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:Ae[0],...Ae.length>1?{SubjectAlternativeNames:Ae.slice(1)}:{},ValidationMethod:"DNS",DomainValidationOptions:Ae.map((ne)=>({DomainName:ne,HostedZoneId:n.hostedZoneId}))}},z=e.ref("HttpCertificate");Ae.forEach((ne,re)=>{let oe=`HttpDomain${re}`;if(P[oe]={Type:"AWS::ApiGatewayV2::DomainName",Properties:{DomainName:ne,DomainNameConfigurations:[{CertificateArn:z,EndpointType:"REGIONAL"}]}},P[`HttpApiMapping${re}`]={Type:"AWS::ApiGatewayV2::ApiMapping",DependsOn:["HttpStage"],Properties:{ApiId:e.ref("HttpApi"),DomainName:e.ref(oe),Stage:"$default"}},n.hostedZoneId)P[`HttpDomainRecord${re}`]={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:ne,Type:"A",AliasTarget:{DNSName:e.getAtt(oe,"RegionalDomainName"),HostedZoneId:e.getAtt(oe,"RegionalHostedZoneId")}}};V[`CustomDomain${re}`]={Description:`Custom domain ${ne}`,Value:ne},V[`CustomDomainTarget${re}`]={Description:`Point ${ne} (CNAME/alias) at this APIGW regional domain`,Value:e.getAtt(oe,"RegionalDomainName")}})}if(b)P.AppQueueDlq={Type:"AWS::SQS::Queue",Properties:{QueueName:`${c}-${i}-dlq`,MessageRetentionPeriod:1209600}},f.forEach((z,ne)=>{let re=`AppQueue${ne}`,oe=n.queueTimeout??120;P[re]={Type:"AWS::SQS::Queue",Properties:{QueueName:z.name,VisibilityTimeout:Math.min(43200,oe*6),RedrivePolicy:{deadLetterTargetArn:e.getAtt("AppQueueDlq","Arn"),maxReceiveCount:n.queueTries??3}}};let ye=z.concurrency??n.queueConcurrency;P[`${re}Mapping`]={Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:e.getAtt(re,"Arn"),FunctionName:he("QueueFunction"),BatchSize:1,FunctionResponseTypes:["ReportBatchItemFailures"],...ye?{ScalingConfig:{MaximumConcurrency:Math.max(2,ye)}}:{}}},V[`QueueUrl${ne}`]={Description:`Queue URL: ${z.name}`,Value:e.ref(re)}});if(v)P.SchedulerRule={Type:"AWS::Events::Rule",Properties:{Name:`${c}-${i}-scheduler`,ScheduleExpression:"rate(1 minute)",State:"ENABLED",Targets:[{Id:"cli",Arn:Re("CliFunction"),Input:JSON.stringify({command:"schedule:run"})}]}},P.SchedulerPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:he("CliFunction"),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.getAtt("SchedulerRule","Arn")}};if(n.warm&&n.warm>0){let z={http:"HttpFunction",queue:"QueueFunction",cli:"CliFunction"},ne=(n.warmFunctions??["http"]).filter((re)=>re!=="queue"||b);for(let re of ne){let oe=re.charAt(0).toUpperCase()+re.slice(1),ye=Math.ceil(n.warm/5),tt=0;for(let Te=0;Te<ye;Te++){let rt=Math.min(5,n.warm-tt);P[`Warmer${oe}Rule${Te}`]={Type:"AWS::Events::Rule",Properties:{Name:`${c}-${i}-warmer-${re}-${Te}`,ScheduleExpression:"rate(5 minutes)",State:"ENABLED",Targets:Array.from({length:rt},(Tt,vt)=>({Id:`warm-${re}-${Te}-${vt}`,Arn:e.getAtt(z[re],"Arn"),Input:JSON.stringify({warmer:!0})}))}},tt+=rt}P[`Warmer${oe}Permission`]={Type:"AWS::Lambda::Permission",Properties:{FunctionName:e.ref(z[re]),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.sub(`arn:aws:events:\${AWS::Region}:\${AWS::AccountId}:rule/${c}-${i}-warmer-${re}-*`)}}}}if(w)P.CacheTable={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${c}-${i}-cache`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"key",AttributeType:"S"}],KeySchema:[{AttributeName:"key",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"expires_at",Enabled:!0}}},V.CacheTableName={Description:"DynamoDB cache table",Value:e.ref("CacheTable")};if(R){if(P.AssetsBucket={Type:"AWS::S3::Bucket",Properties:{BucketName:k,PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}}},P.AssetsOAC={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${c}-${i}-assets-oac`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},P.AssetsDistribution={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,DefaultCacheBehavior:{TargetOriginId:"assets",ViewerProtocolPolicy:"redirect-to-https",Compress:!0,CachePolicyId:"658327ea-f89d-4fab-a63d-7e88639e58f6"},Origins:[{Id:"assets",DomainName:e.getAtt("AssetsBucket","RegionalDomainName"),OriginAccessControlId:e.ref("AssetsOAC"),S3OriginConfig:{OriginAccessIdentity:""}}],...n.assetDomain?{Aliases:[n.assetDomain],ViewerCertificate:{AcmCertificateArn:n.assetCertificateArn??e.ref("AssetsCertificate"),SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}}:{}}}},n.assetDomain){if(!n.assetCertificateArn){if(!n.hostedZoneId)throw Error("serverless app: `assetDomain` requires either `assetCertificateArn` (a us-east-1 ACM cert) or `hostedZoneId` (to auto-issue + validate one). CloudFront only accepts certs from us-east-1.");if(h!=="us-east-1")throw Error(`serverless app: auto-issuing an asset-domain cert needs a us-east-1 app (CloudFront certs must be us-east-1); this app is in ${h}. Supply a pre-issued us-east-1 \`assetCertificateArn\` instead.`);P.AssetsCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:n.assetDomain,ValidationMethod:"DNS",DomainValidationOptions:[{DomainName:n.assetDomain,HostedZoneId:n.hostedZoneId}]}}}if(n.hostedZoneId)P.AssetsDomainRecord={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:n.assetDomain,Type:"A",AliasTarget:{DNSName:e.getAtt("AssetsDistribution","DomainName"),HostedZoneId:"Z2FDTNDATAQYW2"}}};V.AssetDomain={Description:"Custom asset CDN host",Value:n.assetDomain}}P.AssetsBucketPolicy={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:e.ref("AssetsBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:e.sub(`arn:aws:s3:::${k}/*`),Condition:{StringEquals:{"AWS:SourceArn":e.sub("arn:aws:cloudfront::${AWS::AccountId}:distribution/${AssetsDistribution}")}}}]}}},V.AssetsBucketName={Description:"Assets bucket",Value:e.ref("AssetsBucket")},V.AssetsCdnDomain={Description:"Assets CloudFront domain",Value:e.getAtt("AssetsDistribution","DomainName")}}if(n.firewall?.enabled){let z=[],ne=0;if(n.firewall.rateLimit)z.push({Name:"rate-limit",Priority:ne++,Action:{Block:{}},Statement:{RateBasedStatement:{Limit:n.firewall.rateLimit,AggregateKeyType:"IP"}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${i}-rate`}});let re={sqlInjection:"AWSManagedRulesSQLiRuleSet",xss:"AWSManagedRulesCommonRuleSet",common:"AWSManagedRulesCommonRuleSet",botControl:"AWSManagedRulesBotControlRuleSet",ipReputation:"AWSManagedRulesAmazonIpReputationList"};for(let oe of n.firewall.rules??[]){let ye=re[oe];if(!ye)continue;z.push({Name:`managed-${oe}`,Priority:ne++,OverrideAction:{None:{}},Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:ye}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${i}-${oe}`}})}P.WebAcl={Type:"AWS::WAFv2::WebACL",Properties:{Name:`${c}-${i}-waf`,Scope:"REGIONAL",DefaultAction:{Allow:{}},Rules:z,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${i}-waf`}}},V.WafAclArn={Description:"WAF web ACL ARN. Attach to a CloudFront distribution fronting the API to enforce (HTTP API v2 stages do not support direct WAF association).",Value:e.getAtt("WebAcl","Arn")}}if(ue&&se){if(!n.vpc?.id)throw Error("serverless app: data services (elasticache / aurora-serverless / rdsProxy / efs) need app.vpc.id (the VPC id) so the managed security group is created in the right VPC.");P.DataSecurityGroup={Type:"AWS::EC2::SecurityGroup",Properties:{VpcId:n.vpc.id,GroupDescription:`${c}-${i} serverless data access`,SecurityGroupIngress:[{IpProtocol:"-1",CidrIp:"10.0.0.0/8"}]}}}if(ie)P.EfsFileSystem={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:!0,FileSystemTags:[{Key:"Name",Value:`${c}-${i}-efs`}]}},ce.forEach((z,ne)=>{P[`EfsMountTarget${ne}`]={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:e.ref("EfsFileSystem"),SubnetId:z,SecurityGroups:[e.getAtt("DataSecurityGroup","GroupId")]}}}),P.EfsAccessPoint={Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:e.ref("EfsFileSystem"),PosixUser:{Uid:1001,Gid:1001},RootDirectory:{Path:"/lambda",CreationInfo:{OwnerUid:1001,OwnerGid:1001,Permissions:"0755"}}}},V.EfsFileSystemId={Description:"EFS file system id",Value:e.ref("EfsFileSystem")};if(n.cache?.driver==="elasticache")P.CacheSubnetGroup={Type:"AWS::ElastiCache::SubnetGroup",Properties:{Description:`${c}-${i} cache subnets`,SubnetIds:ce}},P.CacheCluster={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:`${c}-${i}-cache`,ReplicationGroupDescription:`${c}-${i} redis`,Engine:"redis",CacheNodeType:"cache.t4g.micro",NumCacheClusters:1,AutomaticFailoverEnabled:!1,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),SecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")],TransitEncryptionEnabled:!1}},V.CacheEndpoint={Description:"Redis primary endpoint",Value:e.getAtt("CacheCluster","PrimaryEndPoint.Address")};if(n.database?.connection==="aurora-serverless")P.DbSubnetGroup={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupDescription:`${c}-${i} db subnets`,SubnetIds:ce}},P.DbSecret={Type:"AWS::SecretsManager::Secret",Properties:{Name:`${c}/${i}/db`,GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"app"}),GenerateStringKey:"password",PasswordLength:32,ExcludePunctuation:!0}}},P.DbCluster={Type:"AWS::RDS::DBCluster",Properties:{Engine:"aurora-mysql",EngineMode:"provisioned",DBClusterIdentifier:`${c}-${i}-db`,DatabaseName:"app",MasterUsername:e.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:username}}"),MasterUserPassword:e.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:password}}"),ServerlessV2ScalingConfiguration:{MinCapacity:n.database?.minCapacity??0.5,MaxCapacity:n.database?.maxCapacity??4},DBSubnetGroupName:e.ref("DbSubnetGroup"),VpcSecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")]}},P.DbInstance={Type:"AWS::RDS::DBInstance",Properties:{Engine:"aurora-mysql",DBInstanceClass:"db.serverless",DBClusterIdentifier:e.ref("DbCluster")}},V.DbEndpoint={Description:"Aurora cluster endpoint",Value:e.getAtt("DbCluster","Endpoint.Address")};if(n.rdsProxy&&n.database?.connection==="aurora-serverless")P.DbProxyRole={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"rds.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"read-db-secret",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue"],Resource:e.ref("DbSecret")}]}}]}},P.DbProxy={Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:typeof n.rdsProxy==="object"&&n.rdsProxy.name?n.rdsProxy.name:`${c}-${i}-proxy`,EngineFamily:"MYSQL",RoleArn:e.getAtt("DbProxyRole","Arn"),Auth:[{AuthScheme:"SECRETS",SecretArn:e.ref("DbSecret"),IAMAuth:"DISABLED"}],VpcSubnetIds:ce,VpcSecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")],RequireTLS:!1}},P.DbProxyTargetGroup={Type:"AWS::RDS::DBProxyTargetGroup",DependsOn:["DbInstance"],Properties:{DBProxyName:e.ref("DbProxy"),TargetGroupName:"default",DBClusterIdentifiers:[e.ref("DbCluster")]}},V.DbProxyEndpoint={Description:"RDS Proxy endpoint",Value:e.getAtt("DbProxy","Endpoint")};if(V.HttpFunctionName={Description:"HTTP function name",Value:e.ref("HttpFunction")},V.CliFunctionName={Description:"CLI function name",Value:e.ref("CliFunction")},b)V.QueueFunctionName={Description:"Queue function name",Value:e.ref("QueueFunction")};let $e={AWSTemplateFormatVersion:"2010-09-09",Description:`Serverless application for ${a.config.project.name} (${c}-${i})`,Parameters:T?{ImageUri:{Type:"String",Description:"ECR image URI of the deployment artifact"}}:{ArtifactBucket:{Type:"String",Description:"S3 bucket holding the deployment artifact"},ArtifactKey:{Type:"String",Description:"S3 key of the deployment artifact (zip)"}},Resources:P,Outputs:V},Ge={};for(let z of Object.values(P))Ge[z.Type]=(Ge[z.Type]??0)+1;return{template:$e,functionNames:y,queueNames:S,resourceSummary:Ge}}var Jf=["cli","fpm","curl","mbstring","xml","pdo","mysqlnd","gd","bcmath","intl","opcache","sodium","process","pecl-redis6","pecl-apcu","pgsql"];function Xf(a){let n=`php${a.replace(".","")}`;return Jf.map((i)=>`${n}-php-${i}`)}function Og(a,n){let i=`php${a.replace(".","")}`,s=Xf(a).join(" \\\n "),c=`/opt/remi/${i}/root`,l=`/etc/opt/remi/${i}`;return`${n?`FROM almalinux:9 AS ${n}`:"FROM almalinux:9"}
|
|
7277
7277
|
|
|
7278
7278
|
# Build PHP on AlmaLinux 9 (where Remi's version-isolated SCL packages install
|
|
7279
7279
|
# cleanly — Remi's release RPM rejects Amazon Linux 2023). AlmaLinux 9 shares
|
|
@@ -7334,7 +7334,7 @@ COPY app/ \${LAMBDA_TASK_ROOT}/
|
|
|
7334
7334
|
|
|
7335
7335
|
# Per-function CMD (e.g. index.http) is supplied via ImageConfig.Command.
|
|
7336
7336
|
CMD [ "index.http" ]
|
|
7337
|
-
`}function Ba(){return ai(ri(import.meta.url))}function Lg(){return At(Pe(Ba(),"runtime.mjs"),"utf-8")}function _a(a){return At(Pe(Ba(),`${a}-bootstrap`),"utf-8")}function $C(a){let n=a.architecture??"x86_64",i=n==="arm64"?"arm64":"x64",s=a.version.replace(/^v/,""),c=a.onStep??(()=>{}),l=Ma(Pe(Oa(),"tscloud-node-layer-"));try{let u=s.includes(".")?s:ni(s),h=`node-v${u}-linux-${i}`,y=`https://nodejs.org/dist/v${u}/${h}.tar.xz`;c(`downloading Node ${u} (${n})`);let f=Pe(l,"node.tar.xz");Wa(y,f),c("extracting node binary"),bt("tar",["-xf",f,"-C",l,`${h}/bin/node`],{stdio:"inherit"});let S=At(Pe(l,h,"bin","node"));c("packaging layer");let b=[{name:"bootstrap",data:_a("node"),mode:493},{name:"runtime.mjs",data:Lg(),mode:420},{name:"bin/node",data:S,mode:493}];return{zip:
|
|
7337
|
+
`}function Ba(){return ai(ri(import.meta.url))}function Lg(){return At(Pe(Ba(),"runtime.mjs"),"utf-8")}function _a(a){return At(Pe(Ba(),`${a}-bootstrap`),"utf-8")}function $C(a){let n=a.architecture??"x86_64",i=n==="arm64"?"arm64":"x64",s=a.version.replace(/^v/,""),c=a.onStep??(()=>{}),l=Ma(Pe(Oa(),"tscloud-node-layer-"));try{let u=s.includes(".")?s:ni(s),h=`node-v${u}-linux-${i}`,y=`https://nodejs.org/dist/v${u}/${h}.tar.xz`;c(`downloading Node ${u} (${n})`);let f=Pe(l,"node.tar.xz");Wa(y,f),c("extracting node binary"),bt("tar",["-xf",f,"-C",l,`${h}/bin/node`],{stdio:"inherit"});let S=At(Pe(l,h,"bin","node"));c("packaging layer");let b=[{name:"bootstrap",data:_a("node"),mode:493},{name:"runtime.mjs",data:Lg(),mode:420},{name:"bin/node",data:S,mode:493}];return{zip:hi(b),architecture:n,version:u,fileCount:b.length}}finally{xa(l,{recursive:!0,force:!0})}}function MC(a){let n=a.architecture??"x86_64",i=n==="arm64"?"bun-linux-aarch64":"bun-linux-x64",s=a.version==="latest"?"":a.version.replace(/^v/,""),c=a.onStep??(()=>{}),l=Ma(Pe(Oa(),"tscloud-bun-layer-"));try{let u=s?`https://github.com/oven-sh/bun/releases/download/bun-v${s}/${i}.zip`:`https://github.com/oven-sh/bun/releases/latest/download/${i}.zip`;c(`downloading Bun ${s||"latest"} (${n})`);let h=Pe(l,"bun.zip");Wa(u,h),c("extracting bun binary"),bt("unzip",["-o","-q",h,"-d",l],{stdio:"inherit"});let y=At(Pe(l,i,"bun"));c("packaging layer");let f=[{name:"bootstrap",data:_a("bun"),mode:493},{name:"runtime.mjs",data:Lg(),mode:420},{name:"bin/bun",data:y,mode:493}];return{zip:hi(f),architecture:n,version:s||"latest",fileCount:f.length}}finally{xa(l,{recursive:!0,force:!0})}}function Wa(a,n){bt("curl",["-fsSL","-o",n,a],{stdio:["ignore","ignore","inherit"]})}function ni(a){let n=bt("curl",["-fsSL","https://nodejs.org/dist/index.json"],{encoding:"utf-8"}),i=JSON.parse(n).find((s)=>s.version.startsWith(`v${a}.`));if(!i)throw Error(`No Node release found for major version ${a}`);return i.version.replace(/^v/,"")}var Xs="x-ts-cloud-invoke-depth",Ys="x-ts-cloud-invoke-chain",Zs="x-ts-cloud-trace-id";function gd(a){return si("sha256").update(a).digest("hex").slice(0,8)}var fi={maxDepth:10,maxRepeats:3,maxInvocationsPerTrace:100,traceWindowMs:60000,breakerThreshold:5,breakerCooldownMs:60000};function Dt(a,n){if(typeof a.get==="function")return a.get(n)??void 0;let i=a;return i[n]??i[n.toLowerCase()]??i[n.toUpperCase()]}function md(a,n=64){if(!a)return[];return a.split(".").map((i)=>i.trim()).filter((i)=>/^[0-9a-f]{8}$/.test(i)).slice(-n)}function hd(a,n=fi){let i=gd(a.functionId),s=md(Dt(a.headers,Ys)),c=a.traceId??Dt(a.headers,Zs)??crypto.randomUUID(),l=[...s,i],u=s.filter((b)=>b===i).length,h=s[s.length-1]===i,y=Number.parseInt(Dt(a.headers,Xs)??"",10),f=Math.max(l.length,Number.isFinite(y)?y+1:0),S="ok";if(f>n.maxDepth)S="depth_exceeded";else if(u>=n.maxRepeats)S="cycle_detected";else if(h&&n.maxRepeats<=1)S="self_invocation";return{reason:S,depth:f,chain:l,traceId:c,selfInvocation:h,repeats:u,propagate:{[Xs]:String(f),[Ys]:l.join("."),[Zs]:c}}}var Ga={ok:"",depth_exceeded:"Invocation chain is deeper than the configured limit; the call was refused to stop a runaway loop.",cycle_detected:"This function already appears in the invocation chain; the call was refused as a recursion loop.",self_invocation:"This function invoked itself directly; the call was refused.",trace_budget_exceeded:"This request has already made more invocations than its budget allows.",breaker_open:"Recursion protection is open for this function after repeated loop detections."};class eo{limits;clock;traces=new Map;breakers=new Map;constructor(a=fi,n=()=>Date.now()){this.limits=a,this.clock=n}check(a){let n=this.clock();this.expireTraces(n);let i=hd(a,this.limits),s=this.breakers.get(a.functionId);if(s?.openUntil!=null&&s.openUntil>n)return this.deny(a.functionId,i,"breaker_open",n,!1);if(i.reason!=="ok")return this.deny(a.functionId,i,i.reason,n,!0);let c=this.traces.get(i.traceId)??{count:0,firstAt:n};if(c.count>=this.limits.maxInvocationsPerTrace)return this.traces.set(i.traceId,c),this.deny(a.functionId,i,"trace_budget_exceeded",n,!0);if(this.traces.set(i.traceId,{count:c.count+1,firstAt:c.firstAt}),s)this.breakers.set(a.functionId,{consecutiveBlocks:0});return{...i,allowed:!0,reason:"ok",propagate:i.propagate}}deny(a,n,i,s,c){if(c){let l=this.breakers.get(a)??{consecutiveBlocks:0},u=l.consecutiveBlocks+1;this.breakers.set(a,{consecutiveBlocks:u,openUntil:u>=this.limits.breakerThreshold?s+this.limits.breakerCooldownMs:l.openUntil})}return{...n,allowed:!1,reason:i,message:Ga[i]}}breakerOpen(a){let n=this.breakers.get(a);return n?.openUntil!=null&&n.openUntil>this.clock()}reset(a){if(a){this.breakers.delete(a);return}this.breakers.clear(),this.traces.clear()}expireTraces(a){if(this.traces.size===0)return;for(let[n,i]of this.traces)if(a-i.firstAt>this.limits.traceWindowMs)this.traces.delete(n)}get trackedTraces(){return this.traces.size}}function fd(a){return{...a.propagate}}function Ad(a){return{status:508,headers:{"content-type":"application/json","x-ts-cloud-recursion-blocked":a.reason},body:{error:"recursion_blocked",reason:a.reason,message:a.message??Ga[a.reason],depth:a.depth,traceId:a.traceId}}}var $g=new ii;function pa(a){let n=globalThis.process?.env?.[a];if(n==null||n==="")return;return n!=="0"&&n.toLowerCase()!=="false"}function oi(){let a=globalThis.process?.env??{};return a.TS_CLOUD_FUNCTION_ID||a.AWS_LAMBDA_FUNCTION_NAME||a.FUNCTION_NAME||"function"}function Zf(a){let n=a===!1?{enabled:!1}:a??{},i=pa("TS_CLOUD_RECURSION_PROTECTION"),s=pa("TS_CLOUD_RECURSION_DETECTION_ONLY");return{enabled:i??n.enabled??!0,detectionOnly:s??n.detectionOnly??!1,limits:{...fi,...n.limits},functionId:n.functionId??oi()}}var De,fe;function eA(){let a=globalThis.fetch;if(!a||De===a)return()=>{};fe=a;let n=async(i,s)=>{let c=$g.getStore();if(!c)return fe(i,s);let l=new Headers(s?.headers??(i instanceof Request?i.headers:void 0));for(let[u,h]of Object.entries(fd(c)))l.set(u,h);if(i instanceof Request)return fe(new Request(i,{headers:l}),s);return fe(i,{...s,headers:l})};return Object.assign(n,a),globalThis.fetch=n,De=n,()=>{if(globalThis.fetch===De&&fe)globalThis.fetch=fe;De=void 0}}var ut,xt;function tA(a){if(!ut||JSON.stringify(xt)!==JSON.stringify(a))ut=new eo(a),xt=a;return ut}function FC(){if(ut=void 0,xt=void 0,De&&fe&&globalThis.fetch===De)globalThis.fetch=fe;De=void 0,fe=void 0}function rA(a,n){let i=Zf(n);if(!i.enabled)return;let s=tA(i.limits),c={functionId:i.functionId,headers:a},l=s.check(c);return{verdict:l,blocked:!l.allowed&&!i.detectionOnly,observed:!l.allowed&&i.detectionOnly}}function nA(a,n){return eA(),$g.run(a,n)}function UC(a){let n=a,i=n?.default??n;if(typeof i==="function")return{fetch:i};return{fetch:i?.fetch??n?.fetch,queue:i?.queue??n?.queue,cli:i?.cli??n?.cli}}var ci=/^(?:text\/|application\/(?:json|xml|javascript|graphql|x-www-form-urlencoded|.*\+json|.*\+xml)|image\/svg)/i;function li(a){if(!a)return!0;return ci.test(a)}function di(a){if(a?.maintenance)return a.maintenance;let n=globalThis.process?.env??{};return{enabled:n.MAINTENANCE_MODE==="1"||n.MAINTENANCE_MODE==="true",bypassSecret:n.MAINTENANCE_BYPASS_SECRET}}function iA(a){let n=a.requestContext?.domainName??"localhost",i=a.rawQueryString?`?${a.rawQueryString}`:"",s=`https://${n}${a.rawPath||"/"}${i}`,c=new Headers;for(let[h,y]of Object.entries(a.headers??{}))if(y!==void 0)c.set(h,y);if(a.cookies?.length)c.set("cookie",a.cookies.join("; "));let l=a.requestContext.http.method,u;if(a.body!==void 0&&l!=="GET"&&l!=="HEAD")u=a.isBase64Encoded?new Uint8Array(Buffer.from(a.body,"base64")):new TextEncoder().encode(a.body);return new Request(s,{method:l,headers:c,body:u})}async function Mg(a){let n={},i=[],s=typeof a.headers.getSetCookie==="function"?a.headers.getSetCookie():[];for(let u of s)i.push(u);a.headers.forEach((u,h)=>{if(h.toLowerCase()==="set-cookie")return;n[h]=u});let c=Buffer.from(await a.arrayBuffer()),l=li(a.headers.get("content-type"));return{statusCode:a.status,headers:n,...i.length?{cookies:i}:{},body:l?c.toString("utf-8"):c.toString("base64"),isBase64Encoded:!l}}function sA(a,n){return async(i)=>{if(i.warmer)return{statusCode:200,headers:{"content-type":"text/plain"},body:"warm",isBase64Encoded:!1};if(!a)return{statusCode:501,headers:{"content-type":"text/plain"},body:"No HTTP handler configured",isBase64Encoded:!1};let s=di(n);if(s.enabled){let u=i.headers?.["x-maintenance-bypass"]??i.cookies?.find((h)=>h.startsWith("tscloud_bypass="))?.split("=")[1];if(!s.bypassSecret||u!==s.bypassSecret)return{statusCode:503,headers:{"content-type":"text/plain","retry-after":"120"},body:"Service temporarily unavailable (maintenance mode)",isBase64Encoded:!1}}let c=rA(i.headers??{},n?.recursionProtection);if(c?.blocked){let u=Ad(c.verdict);return{statusCode:u.status,headers:{...u.headers,"retry-after":"60"},body:JSON.stringify(u.body),isBase64Encoded:!1}}let l=iA(i);if(!c){let u=await a(l);return Mg(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 nA(c.verdict,async()=>Mg(await a(l)))}}function yi(a){try{return JSON.parse(a)}catch{return a}}function oA(a){return async(n)=>{let i=[];if(n.warmer)return{batchItemFailures:i};if(!a)return{batchItemFailures:i};for(let s of n.Records??[])try{await a(yi(s.body),s)}catch{i.push({itemIdentifier:s.messageId})}return{batchItemFailures:i}}}function aA(a){return async(n)=>{if(n.warmer)return{statusCode:0,output:"warm"};if(!a)return{statusCode:501,output:"No CLI handler configured"};return a(n)}}function QC(a,n){return{http:sA(a.fetch,n),queue:oA(a.queue),cli:aA(a.cli)}}function cA(a={}){let n=a.socketPath??"/tmp/.tscloud-fpm.sock",i=a.maxChildren??1;return`; ts-cloud php-fpm configuration (generated) — AWS Lambda custom runtime.
|
|
7338
7338
|
[global]
|
|
7339
7339
|
daemonize = no
|
|
7340
7340
|
error_log = ${a.errorLog??"/tmp/storage/logs/php-fpm.log"}
|
|
@@ -7351,5 +7351,5 @@ decorate_workers_output = no
|
|
|
7351
7351
|
php_admin_value[error_log] = /dev/stderr
|
|
7352
7352
|
php_admin_flag[log_errors] = on
|
|
7353
7353
|
clear_env = no
|
|
7354
|
-
`}function Ti(){return Ua(Ai(Ci(import.meta.url)),"runtime-assets")}function fi(){let a=Ti(),n=(i)=>bi(Ua(a,i),"utf-8");return[{path:"bootstrap",contents:n("bootstrap"),mode:493},{path:"tscloud/runtime.php",contents:n("runtime.php"),mode:420},{path:"tscloud/octane-runtime.php",contents:n("octane-runtime.php"),mode:420},{path:"tscloud/cli-runtime.php",contents:n("cli-runtime.php"),mode:420},{path:"tscloud/fastcgi-client.php",contents:n("fastcgi-client.php"),mode:420},{path:"tscloud/php-fpm.conf",contents:cA(),mode:420}]}function yd(a={}){let n=a.cacheDriver??"dynamodb";return{APP_ENV:"production",LOG_CHANNEL:"stderr",CACHE_STORE:n,CACHE_DRIVER:n,SESSION_DRIVER:n,QUEUE_CONNECTION:"sqs",FILESYSTEM_DISK:"s3",VIEW_COMPILED_PATH:"/tmp/storage/framework/views",APP_SERVICES_CACHE:"/tmp/bootstrap/cache/services.php",APP_PACKAGES_CACHE:"/tmp/bootstrap/cache/packages.php",APP_CONFIG_CACHE:"/tmp/bootstrap/cache/config.php",APP_ROUTES_CACHE:"/tmp/bootstrap/cache/routes.php",APP_EVENTS_CACHE:"/tmp/bootstrap/cache/events.php"}}var dA=["composer install --no-dev --optimize-autoloader --no-interaction","php artisan config:cache","php artisan route:cache","php artisan event:cache","php artisan view:cache"];function*Va(a){for(let n of Pi(a)){let i=xe(a,n);if(Fa(i).isDirectory())yield*Va(i);else yield i}}function HC(a={}){let n=a.architecture??"x86_64",i=a.platform??(n==="arm64"?"linux/arm64":"linux/amd64"),s=a.onStep??(()=>{}),c=Ei(xe(Di(),"tscloud-php-layer-")),l="tscloud-php-layer:build";try{Ni(xe(c,"Dockerfile"),Yf(a)),s("Building PHP runtime image (docker)"),lt("docker",["build","--platform",i,"-t","tscloud-php-layer:build",c],{stdio:"inherit"}),s("Extracting /opt/php from image");let u=lt("docker",["create","--platform",i,"tscloud-php-layer:build"],{encoding:"utf-8"}).trim(),h=xe(c,"opt");wi(h,{recursive:!0});try{lt("docker",["cp",`${u}:/opt/php`,xe(h,"php")],{stdio:"inherit"})}finally{lt("docker",["rm",u],{stdio:"ignore"})}if(!vi(xe(h,"php","bin","php")))throw Error("layer build produced no /opt/php/bin/php");let y=[];for(let b of Va(h)){let C=ki(h,b).replace(/\\/g,"/"),T=Fa(b).mode&73?493:420;y.push({name:C,data:Ii(b),mode:T})}s("Injecting runtime assets");let f=new Set(fi().map((b)=>b.path)),S=y.filter((b)=>!f.has(b.name));for(let b of fi())S.push({name:b.path,data:b.contents,mode:b.mode});return s("Packaging layer ZIP"),{zip:mi(S),architecture:n,fileCount:S.length}}finally{Ri(c,{recursive:!0,force:!0})}}var lA=[".git",".github","node_modules","tests","storage/logs","storage/framework/cache","storage/framework/sessions","storage/framework/views",".env",".env.local",".vapor",".ts-cloud","dist-lambda"];function Bi(a,n){return n.some((i)=>a===i||a.startsWith(`${i}/`))}function*Ha(a,n,i){for(let s of Mi(a)){let c=Oi(a,s),l=Ka(n,c).replace(/\\/g,"/");if(Bi(l,i))continue;if(ja(c).isDirectory())yield*Ha(c,n,i);else yield c}}function eo(a){if(a.skipBuild)return;let n=na(a.projectRoot??process.cwd()),i=a.app.build??dA;for(let s of i)a.onStep?.(`build: ${s}`),$i(s,{stdio:"inherit",cwd:n})}function to(a,n=[]){let i=na(a),s=[...lA,Us(),...n],c=[];for(let l of Ha(i,i,s)){let u=Ka(i,l).replace(/\\/g,"/"),h=(ja(l).mode&73)!==0;c.push({name:u,data:xi(l),mode:h?493:420})}return c}function Id(a){let n=na(a.projectRoot??process.cwd());eo(a),a.onStep?.("packaging application tree");let i=to(n,a.exclude);if(!i.length)throw Error(`No files to package under ${n}`);let s=mi(i),c=a.app.handlers?.http??"public/index.php";return{zip:s,sha256:Li("sha256").update(s).digest("hex"),handlers:{http:c,queue:a.app.handlers?.queue??c,cli:a.app.handlers?.cli??c},fileCount:i.length}}class Fg{optimizations=new Map;imageConfigs=new Map;ssgConfigs=new Map;prerenderConfigs=new Map;counter=0;createAssetOptimization(a){let n=`asset-opt-${Date.now()}-${this.counter++}`,i={id:n,...a};return this.optimizations.set(n,i),i}createImageOptimization(a){let n=`image-opt-${Date.now()}-${this.counter++}`,i={id:n,...a};return this.imageConfigs.set(n,i),i}createSSGConfig(a){let n=`ssg-${Date.now()}-${this.counter++}`,i={id:n,...a};return this.ssgConfigs.set(n,i),i}createPrerenderConfig(a){let n=`prerender-${Date.now()}-${this.counter++}`,i={id:n,...a};return this.prerenderConfigs.set(n,i),i}listOptimizations(){return Array.from(this.optimizations.values())}listImageConfigs(){return Array.from(this.imageConfigs.values())}clear(){this.optimizations.clear(),this.imageConfigs.clear(),this.ssgConfigs.clear(),this.prerenderConfigs.clear()}}var GC=new Fg;class Ug{policies=new Map;versioningConfigs=new Map;replicationRules=new Map;tieringConfigs=new Map;objectLocks=new Map;transferAcceleration=new Map;accessPoints=new Map;glacierConfigs=new Map;inventories=new Map;batchOps=new Map;eventNotifications=new Map;counter=0;createLifecyclePolicy(a,n){let i=`lifecycle-${Date.now()}-${this.counter++}`,s={id:i,transitions:a,expiration:n};return this.policies.set(i,s),s}enableVersioning(a=!1){let n=`versioning-${Date.now()}-${this.counter++}`,i={id:n,enabled:!0,mfaDelete:a};return this.versioningConfigs.set(n,i),i}createReplicationRule(a,n,i){let s=`replication-${Date.now()}-${this.counter++}`,c={id:s,sourceRegion:a,destRegion:n,destBucket:i};return this.replicationRules.set(s,c),c}createIntelligentTiering(a,n){let i=`tiering-${Date.now()}-${this.counter++}`,s={id:i,archiveDays:a,deepArchiveDays:n};return this.tieringConfigs.set(i,s),s}enableObjectLock(a){let n=`object-lock-${Date.now()}-${this.counter++}`,i={id:n,bucketName:a.bucketName,mode:a.mode||"COMPLIANCE",retentionDays:a.retentionDays,retentionYears:a.retentionYears,legalHoldEnabled:a.legalHoldEnabled||!1};return this.objectLocks.set(n,i),i}enableTransferAcceleration(a){let n=`transfer-accel-${Date.now()}-${this.counter++}`,i={id:n,bucketName:a,enabled:!0,endpoint:`${a}.s3-accelerate.amazonaws.com`};return this.transferAcceleration.set(n,i),i}createAccessPoint(a){let n=`access-point-${Date.now()}-${this.counter++}`,i={id:n,name:a.name,bucketName:a.bucketName,vpcId:a.vpcId,publicAccessBlock:a.publicAccessBlock!==!1,policy:a.policy};return this.accessPoints.set(n,i),i}createGlacierArchive(a){let n=`glacier-${Date.now()}-${this.counter++}`,i={id:n,bucketName:a.bucketName,archiveType:a.archiveType,transitionDays:a.transitionDays,restoreConfig:a.restoreTier?{tier:a.restoreTier,days:a.restoreDays||7}:void 0};return this.glacierConfigs.set(n,i),i}createInventory(a){let n=`inventory-${Date.now()}-${this.counter++}`,i={id:n,sourceBucket:a.sourceBucket,destinationBucket:a.destinationBucket,schedule:a.schedule||"Daily",format:a.format||"CSV",includedFields:a.includedFields||["Size","LastModifiedDate","StorageClass","ETag"],prefix:a.prefix};return this.inventories.set(n,i),i}createBatchOperation(a){let n=`batch-op-${Date.now()}-${this.counter++}`,i={id:n,operation:a.operation,manifestBucket:a.manifestBucket,manifestKey:a.manifestKey,priority:a.priority||10,status:"pending"};return this.batchOps.set(n,i),i}executeBatchOperation(a){let n=this.batchOps.get(a);if(!n)throw Error(`Batch operation not found: ${a}`);return n.status="in_progress",n.totalObjects=1000,n.processedObjects=0,n}getBatchOperationStatus(a){return this.batchOps.get(a)}createLambdaNotification(a){let n=`event-${Date.now()}-${this.counter++}`,i={id:n,bucketName:a.bucketName,events:a.events,destination:{type:"Lambda",arn:a.lambdaArn},filter:a.prefix||a.suffix?{prefix:a.prefix,suffix:a.suffix}:void 0};return this.eventNotifications.set(n,i),i}createSQSNotification(a){let n=`event-${Date.now()}-${this.counter++}`,i={id:n,bucketName:a.bucketName,events:a.events,destination:{type:"SQS",arn:a.queueArn},filter:a.prefix||a.suffix?{prefix:a.prefix,suffix:a.suffix}:void 0};return this.eventNotifications.set(n,i),i}createSNSNotification(a){let n=`event-${Date.now()}-${this.counter++}`,i={id:n,bucketName:a.bucketName,events:a.events,destination:{type:"SNS",arn:a.topicArn},filter:a.prefix||a.suffix?{prefix:a.prefix,suffix:a.suffix}:void 0};return this.eventNotifications.set(n,i),i}generateObjectLockCF(a){let n={ObjectLockEnabled:"Enabled",ObjectLockConfiguration:{ObjectLockEnabled:"Enabled",Rule:{DefaultRetention:{Mode:a.mode}}}};if(a.retentionDays)n.ObjectLockConfiguration.Rule.DefaultRetention.Days=a.retentionDays;if(a.retentionYears)n.ObjectLockConfiguration.Rule.DefaultRetention.Years=a.retentionYears;return n}generateTransferAccelerationCF(a){return{AccelerateConfiguration:{AccelerationStatus:a.enabled?"Enabled":"Suspended"}}}generateAccessPointCF(a){return{Type:"AWS::S3::AccessPoint",Properties:{Name:a.name,Bucket:a.bucketName,...a.vpcId&&{VpcConfiguration:{VpcId:a.vpcId}},PublicAccessBlockConfiguration:a.publicAccessBlock?{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}:void 0,...a.policy&&{Policy:a.policy}}}}generateInventoryCF(a){return{Type:"AWS::S3::Bucket",Properties:{InventoryConfigurations:[{Id:a.id,Destination:{BucketArn:`arn:aws:s3:::${a.destinationBucket}`,Format:a.format},Enabled:!0,IncludedObjectVersions:"Current",OptionalFields:a.includedFields,ScheduleFrequency:a.schedule,...a.prefix&&{Prefix:a.prefix}}]}}}generateEventNotificationCF(a){let n=a.destination.type==="Lambda"?"LambdaConfigurations":a.destination.type==="SQS"?"QueueConfigurations":"TopicConfigurations",i=a.destination.type==="Lambda"?"Function":a.destination.type==="SQS"?"Queue":"Topic",s={Event:a.events[0],[i]:a.destination.arn};if(a.filter)s.Filter={S3Key:{Rules:[...a.filter.prefix?[{Name:"prefix",Value:a.filter.prefix}]:[],...a.filter.suffix?[{Name:"suffix",Value:a.filter.suffix}]:[]]}};return{NotificationConfiguration:{[n]:[s]}}}clear(){this.policies.clear(),this.versioningConfigs.clear(),this.replicationRules.clear(),this.tieringConfigs.clear(),this.objectLocks.clear(),this.transferAcceleration.clear(),this.accessPoints.clear(),this.glacierConfigs.clear(),this.inventories.clear(),this.batchOps.clear(),this.eventNotifications.clear()}}var qC=new Ug;class Qg{checks=new Map;synthetics=new Map;uptimeTrackers=new Map;counter=0;createHealthCheck(a,n=30,i=10){let s=`health-${Date.now()}-${this.counter++}`,c={id:s,url:a,interval:n,timeout:i,status:"healthy"};return this.checks.set(s,c),c}createSyntheticMonitor(a,n,i,s){let c=`synthetic-${Date.now()}-${this.counter++}`,l={id:c,name:a,script:n,frequency:i,locations:s};return this.synthetics.set(c,l),l}trackUptime(a,n,i){let s=`uptime-${Date.now()}-${this.counter++}`,c=n/(n+i)*100,l={id:s,resource:a,uptime:n,downtime:i,availability:c};return this.uptimeTrackers.set(s,l),l}clear(){this.checks.clear(),this.synthetics.clear(),this.uptimeTrackers.clear()}}var VC=new Qg;class Hg{wafRules=new Map;shieldProtections=new Map;securityGroups=new Map;nacls=new Map;counter=0;createWAFRule(a,n,i,s){let c=`waf-${Date.now()}-${this.counter++}`,l={id:c,name:a,priority:n,action:i,conditions:s};return this.wafRules.set(c,l),l}enableShield(a,n="standard"){let i=`shield-${Date.now()}-${this.counter++}`,s={id:i,resourceArn:a,protectionType:n};return this.shieldProtections.set(i,s),s}createSecurityGroup(a,n,i){let s=`sg-${Date.now()}-${this.counter++}`,c={id:s,name:a,vpcId:n,rules:i};return this.securityGroups.set(s,c),c}createNACL(a,n){let i=`nacl-${Date.now()}-${this.counter++}`,s={id:i,vpcId:a,rules:n};return this.nacls.set(i,s),s}clear(){this.wafRules.clear(),this.shieldProtections.clear(),this.securityGroups.clear(),this.nacls.clear()}}var jC=new Hg;class Gg{strategies=new Map;allocations=new Map;groups=new Map;counter=0;createTaggingStrategy(a,n){let i=`tagging-${Date.now()}-${this.counter++}`,s={id:i,tags:a,resources:n};return this.strategies.set(i,s),s}createCostAllocation(a,n){let i=`cost-${Date.now()}-${this.counter++}`,s={id:i,tagKey:a,allocations:n};return this.allocations.set(i,s),s}createResourceGroup(a,n,i){let s=`group-${Date.now()}-${this.counter++}`,c={id:s,name:a,query:{resourceTypeFilters:n,tagFilters:i}};return this.groups.set(s,c),c}clear(){this.strategies.clear(),this.allocations.clear(),this.groups.clear()}}var zC=new Gg;
|
|
7355
|
-
export{Sp,x,Cp,rf,uy,nf,py,gy,my,hy,fy,Ay,yy,Iy,Sy,Cy,bp,Ep,Wc,Jc,
|
|
7354
|
+
`}function Ti(){return Ua(bi(Ci(import.meta.url)),"runtime-assets")}function Ai(){let a=Ti(),n=(i)=>Si(Ua(a,i),"utf-8");return[{path:"bootstrap",contents:n("bootstrap"),mode:493},{path:"tscloud/runtime.php",contents:n("runtime.php"),mode:420},{path:"tscloud/octane-runtime.php",contents:n("octane-runtime.php"),mode:420},{path:"tscloud/cli-runtime.php",contents:n("cli-runtime.php"),mode:420},{path:"tscloud/fastcgi-client.php",contents:n("fastcgi-client.php"),mode:420},{path:"tscloud/php-fpm.conf",contents:cA(),mode:420}]}function yd(a={}){let n=a.cacheDriver??"dynamodb";return{APP_ENV:"production",LOG_CHANNEL:"stderr",CACHE_STORE:n,CACHE_DRIVER:n,SESSION_DRIVER:n,QUEUE_CONNECTION:"sqs",FILESYSTEM_DISK:"s3",VIEW_COMPILED_PATH:"/tmp/storage/framework/views",APP_SERVICES_CACHE:"/tmp/bootstrap/cache/services.php",APP_PACKAGES_CACHE:"/tmp/bootstrap/cache/packages.php",APP_CONFIG_CACHE:"/tmp/bootstrap/cache/config.php",APP_ROUTES_CACHE:"/tmp/bootstrap/cache/routes.php",APP_EVENTS_CACHE:"/tmp/bootstrap/cache/events.php"}}var dA=["composer install --no-dev --optimize-autoloader --no-interaction","php artisan config:cache","php artisan route:cache","php artisan event:cache","php artisan view:cache"];function*Va(a){for(let n of Pi(a)){let i=xe(a,n);if(Fa(i).isDirectory())yield*Va(i);else yield i}}function HC(a={}){let n=a.architecture??"x86_64",i=a.platform??(n==="arm64"?"linux/arm64":"linux/amd64"),s=a.onStep??(()=>{}),c=Ei(xe(Di(),"tscloud-php-layer-")),l="tscloud-php-layer:build";try{Ni(xe(c,"Dockerfile"),Yf(a)),s("Building PHP runtime image (docker)"),lt("docker",["build","--platform",i,"-t","tscloud-php-layer:build",c],{stdio:"inherit"}),s("Extracting /opt/php from image");let u=lt("docker",["create","--platform",i,"tscloud-php-layer:build"],{encoding:"utf-8"}).trim(),h=xe(c,"opt");wi(h,{recursive:!0});try{lt("docker",["cp",`${u}:/opt/php`,xe(h,"php")],{stdio:"inherit"})}finally{lt("docker",["rm",u],{stdio:"ignore"})}if(!vi(xe(h,"php","bin","php")))throw Error("layer build produced no /opt/php/bin/php");let y=[];for(let b of Va(h)){let C=ki(h,b).replace(/\\/g,"/"),T=Fa(b).mode&73?493:420;y.push({name:C,data:Ii(b),mode:T})}s("Injecting runtime assets");let f=new Set(Ai().map((b)=>b.path)),S=y.filter((b)=>!f.has(b.name));for(let b of Ai())S.push({name:b.path,data:b.contents,mode:b.mode});return s("Packaging layer ZIP"),{zip:hi(S),architecture:n,fileCount:S.length}}finally{Ri(c,{recursive:!0,force:!0})}}var lA=[".git",".github","node_modules","tests","storage/logs","storage/framework/cache","storage/framework/sessions","storage/framework/views",".env",".env.local",".vapor",".ts-cloud","dist-lambda"];function Bi(a,n){return n.some((i)=>a===i||a.startsWith(`${i}/`))}function*Ha(a,n,i){for(let s of Mi(a)){let c=Oi(a,s),l=Ka(n,c).replace(/\\/g,"/");if(Bi(l,i))continue;if(ja(c).isDirectory())yield*Ha(c,n,i);else yield c}}function to(a){if(a.skipBuild)return;let n=na(a.projectRoot??process.cwd()),i=a.app.build??dA;for(let s of i)a.onStep?.(`build: ${s}`),$i(s,{stdio:"inherit",cwd:n})}function ro(a,n=[]){let i=na(a),s=[...lA,Qs(),...n],c=[];for(let l of Ha(i,i,s)){let u=Ka(i,l).replace(/\\/g,"/"),h=(ja(l).mode&73)!==0;c.push({name:u,data:xi(l),mode:h?493:420})}return c}function Id(a){let n=na(a.projectRoot??process.cwd());to(a),a.onStep?.("packaging application tree");let i=ro(n,a.exclude);if(!i.length)throw Error(`No files to package under ${n}`);let s=hi(i),c=a.app.handlers?.http??"public/index.php";return{zip:s,sha256:Li("sha256").update(s).digest("hex"),handlers:{http:c,queue:a.app.handlers?.queue??c,cli:a.app.handlers?.cli??c},fileCount:i.length}}class Fg{optimizations=new Map;imageConfigs=new Map;ssgConfigs=new Map;prerenderConfigs=new Map;counter=0;createAssetOptimization(a){let n=`asset-opt-${Date.now()}-${this.counter++}`,i={id:n,...a};return this.optimizations.set(n,i),i}createImageOptimization(a){let n=`image-opt-${Date.now()}-${this.counter++}`,i={id:n,...a};return this.imageConfigs.set(n,i),i}createSSGConfig(a){let n=`ssg-${Date.now()}-${this.counter++}`,i={id:n,...a};return this.ssgConfigs.set(n,i),i}createPrerenderConfig(a){let n=`prerender-${Date.now()}-${this.counter++}`,i={id:n,...a};return this.prerenderConfigs.set(n,i),i}listOptimizations(){return Array.from(this.optimizations.values())}listImageConfigs(){return Array.from(this.imageConfigs.values())}clear(){this.optimizations.clear(),this.imageConfigs.clear(),this.ssgConfigs.clear(),this.prerenderConfigs.clear()}}var GC=new Fg;class Ug{policies=new Map;versioningConfigs=new Map;replicationRules=new Map;tieringConfigs=new Map;objectLocks=new Map;transferAcceleration=new Map;accessPoints=new Map;glacierConfigs=new Map;inventories=new Map;batchOps=new Map;eventNotifications=new Map;counter=0;createLifecyclePolicy(a,n){let i=`lifecycle-${Date.now()}-${this.counter++}`,s={id:i,transitions:a,expiration:n};return this.policies.set(i,s),s}enableVersioning(a=!1){let n=`versioning-${Date.now()}-${this.counter++}`,i={id:n,enabled:!0,mfaDelete:a};return this.versioningConfigs.set(n,i),i}createReplicationRule(a,n,i){let s=`replication-${Date.now()}-${this.counter++}`,c={id:s,sourceRegion:a,destRegion:n,destBucket:i};return this.replicationRules.set(s,c),c}createIntelligentTiering(a,n){let i=`tiering-${Date.now()}-${this.counter++}`,s={id:i,archiveDays:a,deepArchiveDays:n};return this.tieringConfigs.set(i,s),s}enableObjectLock(a){let n=`object-lock-${Date.now()}-${this.counter++}`,i={id:n,bucketName:a.bucketName,mode:a.mode||"COMPLIANCE",retentionDays:a.retentionDays,retentionYears:a.retentionYears,legalHoldEnabled:a.legalHoldEnabled||!1};return this.objectLocks.set(n,i),i}enableTransferAcceleration(a){let n=`transfer-accel-${Date.now()}-${this.counter++}`,i={id:n,bucketName:a,enabled:!0,endpoint:`${a}.s3-accelerate.amazonaws.com`};return this.transferAcceleration.set(n,i),i}createAccessPoint(a){let n=`access-point-${Date.now()}-${this.counter++}`,i={id:n,name:a.name,bucketName:a.bucketName,vpcId:a.vpcId,publicAccessBlock:a.publicAccessBlock!==!1,policy:a.policy};return this.accessPoints.set(n,i),i}createGlacierArchive(a){let n=`glacier-${Date.now()}-${this.counter++}`,i={id:n,bucketName:a.bucketName,archiveType:a.archiveType,transitionDays:a.transitionDays,restoreConfig:a.restoreTier?{tier:a.restoreTier,days:a.restoreDays||7}:void 0};return this.glacierConfigs.set(n,i),i}createInventory(a){let n=`inventory-${Date.now()}-${this.counter++}`,i={id:n,sourceBucket:a.sourceBucket,destinationBucket:a.destinationBucket,schedule:a.schedule||"Daily",format:a.format||"CSV",includedFields:a.includedFields||["Size","LastModifiedDate","StorageClass","ETag"],prefix:a.prefix};return this.inventories.set(n,i),i}createBatchOperation(a){let n=`batch-op-${Date.now()}-${this.counter++}`,i={id:n,operation:a.operation,manifestBucket:a.manifestBucket,manifestKey:a.manifestKey,priority:a.priority||10,status:"pending"};return this.batchOps.set(n,i),i}executeBatchOperation(a){let n=this.batchOps.get(a);if(!n)throw Error(`Batch operation not found: ${a}`);return n.status="in_progress",n.totalObjects=1000,n.processedObjects=0,n}getBatchOperationStatus(a){return this.batchOps.get(a)}createLambdaNotification(a){let n=`event-${Date.now()}-${this.counter++}`,i={id:n,bucketName:a.bucketName,events:a.events,destination:{type:"Lambda",arn:a.lambdaArn},filter:a.prefix||a.suffix?{prefix:a.prefix,suffix:a.suffix}:void 0};return this.eventNotifications.set(n,i),i}createSQSNotification(a){let n=`event-${Date.now()}-${this.counter++}`,i={id:n,bucketName:a.bucketName,events:a.events,destination:{type:"SQS",arn:a.queueArn},filter:a.prefix||a.suffix?{prefix:a.prefix,suffix:a.suffix}:void 0};return this.eventNotifications.set(n,i),i}createSNSNotification(a){let n=`event-${Date.now()}-${this.counter++}`,i={id:n,bucketName:a.bucketName,events:a.events,destination:{type:"SNS",arn:a.topicArn},filter:a.prefix||a.suffix?{prefix:a.prefix,suffix:a.suffix}:void 0};return this.eventNotifications.set(n,i),i}generateObjectLockCF(a){let n={ObjectLockEnabled:"Enabled",ObjectLockConfiguration:{ObjectLockEnabled:"Enabled",Rule:{DefaultRetention:{Mode:a.mode}}}};if(a.retentionDays)n.ObjectLockConfiguration.Rule.DefaultRetention.Days=a.retentionDays;if(a.retentionYears)n.ObjectLockConfiguration.Rule.DefaultRetention.Years=a.retentionYears;return n}generateTransferAccelerationCF(a){return{AccelerateConfiguration:{AccelerationStatus:a.enabled?"Enabled":"Suspended"}}}generateAccessPointCF(a){return{Type:"AWS::S3::AccessPoint",Properties:{Name:a.name,Bucket:a.bucketName,...a.vpcId&&{VpcConfiguration:{VpcId:a.vpcId}},PublicAccessBlockConfiguration:a.publicAccessBlock?{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}:void 0,...a.policy&&{Policy:a.policy}}}}generateInventoryCF(a){return{Type:"AWS::S3::Bucket",Properties:{InventoryConfigurations:[{Id:a.id,Destination:{BucketArn:`arn:aws:s3:::${a.destinationBucket}`,Format:a.format},Enabled:!0,IncludedObjectVersions:"Current",OptionalFields:a.includedFields,ScheduleFrequency:a.schedule,...a.prefix&&{Prefix:a.prefix}}]}}}generateEventNotificationCF(a){let n=a.destination.type==="Lambda"?"LambdaConfigurations":a.destination.type==="SQS"?"QueueConfigurations":"TopicConfigurations",i=a.destination.type==="Lambda"?"Function":a.destination.type==="SQS"?"Queue":"Topic",s={Event:a.events[0],[i]:a.destination.arn};if(a.filter)s.Filter={S3Key:{Rules:[...a.filter.prefix?[{Name:"prefix",Value:a.filter.prefix}]:[],...a.filter.suffix?[{Name:"suffix",Value:a.filter.suffix}]:[]]}};return{NotificationConfiguration:{[n]:[s]}}}clear(){this.policies.clear(),this.versioningConfigs.clear(),this.replicationRules.clear(),this.tieringConfigs.clear(),this.objectLocks.clear(),this.transferAcceleration.clear(),this.accessPoints.clear(),this.glacierConfigs.clear(),this.inventories.clear(),this.batchOps.clear(),this.eventNotifications.clear()}}var qC=new Ug;class Qg{checks=new Map;synthetics=new Map;uptimeTrackers=new Map;counter=0;createHealthCheck(a,n=30,i=10){let s=`health-${Date.now()}-${this.counter++}`,c={id:s,url:a,interval:n,timeout:i,status:"healthy"};return this.checks.set(s,c),c}createSyntheticMonitor(a,n,i,s){let c=`synthetic-${Date.now()}-${this.counter++}`,l={id:c,name:a,script:n,frequency:i,locations:s};return this.synthetics.set(c,l),l}trackUptime(a,n,i){let s=`uptime-${Date.now()}-${this.counter++}`,c=n/(n+i)*100,l={id:s,resource:a,uptime:n,downtime:i,availability:c};return this.uptimeTrackers.set(s,l),l}clear(){this.checks.clear(),this.synthetics.clear(),this.uptimeTrackers.clear()}}var VC=new Qg;class Hg{wafRules=new Map;shieldProtections=new Map;securityGroups=new Map;nacls=new Map;counter=0;createWAFRule(a,n,i,s){let c=`waf-${Date.now()}-${this.counter++}`,l={id:c,name:a,priority:n,action:i,conditions:s};return this.wafRules.set(c,l),l}enableShield(a,n="standard"){let i=`shield-${Date.now()}-${this.counter++}`,s={id:i,resourceArn:a,protectionType:n};return this.shieldProtections.set(i,s),s}createSecurityGroup(a,n,i){let s=`sg-${Date.now()}-${this.counter++}`,c={id:s,name:a,vpcId:n,rules:i};return this.securityGroups.set(s,c),c}createNACL(a,n){let i=`nacl-${Date.now()}-${this.counter++}`,s={id:i,vpcId:a,rules:n};return this.nacls.set(i,s),s}clear(){this.wafRules.clear(),this.shieldProtections.clear(),this.securityGroups.clear(),this.nacls.clear()}}var jC=new Hg;class Gg{strategies=new Map;allocations=new Map;groups=new Map;counter=0;createTaggingStrategy(a,n){let i=`tagging-${Date.now()}-${this.counter++}`,s={id:i,tags:a,resources:n};return this.strategies.set(i,s),s}createCostAllocation(a,n){let i=`cost-${Date.now()}-${this.counter++}`,s={id:i,tagKey:a,allocations:n};return this.allocations.set(i,s),s}createResourceGroup(a,n,i){let s=`group-${Date.now()}-${this.counter++}`,c={id:s,name:a,query:{resourceTypeFilters:n,tagFilters:i}};return this.groups.set(s,c),c}clear(){this.strategies.clear(),this.allocations.clear(),this.groups.clear()}}var zC=new Gg;
|
|
7355
|
+
export{Sp,x,Cp,rf,uy,nf,py,gy,my,hy,fy,Ay,yy,Iy,Sy,Cy,bp,Ep,Wc,Jc,Qs,_,d,Xc,vp,O,Yc,p,sf,ui,Zc,ed,ae,td,by,r,t,Ey,vy,g,Ty,wy,Ry,Dy,Py,Mt,rd,Hs,of,Ny,ky,Se,Me,Ce,L,I,o,A,Fe,m,af,Ue,M,at,By,cf,F,nd,be,Ft,Gs,J,id,X,df,qs,U,Q,D,pi,E,Ut,ct,H,e,Vs,xy,Tp,sd,_y,Oy,Ly,$y,od,My,Fy,Uy,Qy,Hy,Gy,qy,Vy,jy,zy,Ky,Wy,lf,uf,pf,gf,mf,hf,ff,Qt,wp,Rp,Nr,gi,Jy,Dp,Xy,Yy,kr,Zy,eI,tI,rI,nI,iI,Af,yf,If,Sf,Cf,js,sI,bf,Ef,vf,G,oI,Qe,zs,Ht,Tf,Pp,wf,Rf,Df,Np,Y,aI,cI,dI,lI,Pf,uI,q,pI,gI,mI,kp,Bp,hI,xp,_p,fI,yI,II,SI,CI,Nf,ad,bI,EI,vI,TI,wI,kf,Bf,RI,DI,PI,NI,kI,BI,xI,_I,OI,Op,cd,LI,$I,MI,FI,Lp,$p,Mp,UI,Fp,QI,HI,GI,qI,Up,VI,jI,zI,KI,WI,JI,XI,YI,xf,_f,Of,Lf,Qp,ZI,eS,tS,rS,nS,iS,sS,oS,aS,$f,Mf,Ff,Uf,cS,dS,Hp,lS,Gp,qp,Vp,jp,uS,pS,gS,mS,Ee,mi,hS,fS,AS,yS,IS,SS,CS,bS,Qf,ES,vS,zp,Kp,TS,wS,Hf,RS,DS,PS,NS,kS,BS,xS,_S,OS,LS,$S,MS,FS,US,QS,HS,GS,qS,VS,jS,zS,Wp,KS,Jp,WS,Xp,JS,Yp,XS,Zp,YS,Br,ZS,eg,eC,Ks,tC,tg,rC,rg,nC,ng,iC,ig,sC,sg,oC,xr,aC,og,cC,ag,dC,cg,lC,dg,uC,lg,pC,ug,gC,pg,mC,gg,hC,mg,fC,hg,AC,fg,yC,Ag,IC,yg,SC,Ig,CC,Sg,bC,Cg,EC,bg,vC,Eg,TC,vg,wC,Tg,RC,wg,DC,Rg,PC,Dg,NC,Pg,kC,Ng,BC,Gf,qf,Vf,jf,kg,xC,Bg,_C,xg,OC,_g,LC,hi,zf,Kf,Ws,dd,_r,Wf,Js,Gt,ld,ud,Jf,Xf,Og,Yf,pd,Lg,$C,MC,Xs,Ys,Zs,gd,fi,md,hd,eo,fd,Ad,$g,Zf,eA,tA,FC,rA,nA,UC,iA,Mg,sA,oA,aA,QC,cA,Ai,yd,dA,HC,lA,to,ro,Id,Fg,GC,Ug,qC,Qg,VC,Hg,jC,Gg,zC};
|