@stacksjs/ts-cloud 0.16.22 → 0.16.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. package/dist/aws/elasticache.d.ts +11 -9
  2. package/dist/aws/index.js +1 -1
  3. package/dist/bin/{chunk-qqqx70g6.js → chunk-0d98bem8.js} +2 -2
  4. package/dist/bin/{chunk-87f5d9qj.js → chunk-0r45d0s3.js} +1 -1
  5. package/dist/bin/{chunk-09d5qe73.js → chunk-21zhm1mk.js} +7 -7
  6. package/dist/bin/chunk-2g1j00yc.js +1 -0
  7. package/dist/bin/{chunk-5bsknbr7.js → chunk-2tk8egg8.js} +1 -1
  8. package/dist/bin/{chunk-v980gs11.js → chunk-33e0t7e5.js} +2 -2
  9. package/dist/bin/{chunk-2gd8kqzq.js → chunk-34kwhmbt.js} +5 -5
  10. package/dist/bin/chunk-4xmhrvfa.js +1 -0
  11. package/dist/bin/{chunk-rm59bcnw.js → chunk-65rndjtr.js} +61 -61
  12. package/dist/bin/{chunk-636jsmnz.js → chunk-6cfpdb35.js} +6 -6
  13. package/dist/bin/chunk-6crapvp1.js +1 -0
  14. package/dist/bin/chunk-7b4gf64x.js +1 -0
  15. package/dist/bin/chunk-818tj49e.js +1 -0
  16. package/dist/bin/{chunk-hmnaen1z.js → chunk-8vm7tpyv.js} +1 -1
  17. package/dist/bin/{chunk-wqydambz.js → chunk-90kpnjdm.js} +16 -16
  18. package/dist/bin/chunk-92qsww97.js +1 -0
  19. package/dist/bin/chunk-9947rscj.js +1 -0
  20. package/dist/bin/{chunk-k97ms0bs.js → chunk-9h7yjtz2.js} +5 -5
  21. package/dist/bin/{chunk-8agf66wn.js → chunk-btr6zq53.js} +3 -3
  22. package/dist/bin/chunk-cas0bp91.js +2 -0
  23. package/dist/bin/{chunk-ardzx4dw.js → chunk-cpwk0pbg.js} +128 -128
  24. package/dist/bin/chunk-cyap08qg.js +1 -0
  25. package/dist/bin/chunk-dk92s260.js +1 -0
  26. package/dist/bin/chunk-ejxp74ks.js +1 -0
  27. package/dist/bin/{chunk-n7hmjzgd.js → chunk-en7sf83z.js} +1 -1
  28. package/dist/bin/{chunk-330kytpm.js → chunk-f2yhthd1.js} +2 -2
  29. package/dist/bin/{chunk-95v6ry1x.js → chunk-f3sd1hpa.js} +5 -5
  30. package/dist/bin/chunk-gfwkmttt.js +1 -0
  31. package/dist/bin/chunk-gx98tkpf.js +1 -0
  32. package/dist/bin/{chunk-8wnkx3jf.js → chunk-gzpwf3n4.js} +2 -2
  33. package/dist/bin/{chunk-n8dsby4k.js → chunk-h90azajz.js} +1 -1
  34. package/dist/bin/chunk-hcdbw9j1.js +1 -0
  35. package/dist/bin/chunk-hdsgfgnz.js +34 -0
  36. package/dist/bin/{chunk-vskhr9qy.js → chunk-hqmkfh4a.js} +2 -2
  37. package/dist/bin/{chunk-jp23ed1q.js → chunk-ht318ydv.js} +1 -1
  38. package/dist/bin/{chunk-3425j97b.js → chunk-ht6tpmqw.js} +2 -2
  39. package/dist/bin/{chunk-7xr71hnt.js → chunk-j0zg3mbm.js} +2 -2
  40. package/dist/bin/{chunk-k6apknm8.js → chunk-jbpkwxht.js} +5 -5
  41. package/dist/bin/{chunk-a0me5fed.js → chunk-jtnv8nwz.js} +2 -2
  42. package/dist/bin/{chunk-12q8xrct.js → chunk-k052rtd5.js} +5 -5
  43. package/dist/bin/{chunk-and7khsv.js → chunk-k1eezsj1.js} +2 -2
  44. package/dist/bin/chunk-kay11qc7.js +1 -0
  45. package/dist/bin/chunk-n28a9a9c.js +1 -0
  46. package/dist/bin/{chunk-7kj8f72p.js → chunk-n298azax.js} +1 -1
  47. package/dist/bin/chunk-q8w7fa56.js +1 -0
  48. package/dist/bin/chunk-qdnx952p.js +1 -0
  49. package/dist/bin/chunk-t1jpqn4x.js +6 -0
  50. package/dist/bin/chunk-tr0pkm4p.js +1 -0
  51. package/dist/bin/{chunk-24njmb7d.js → chunk-tyqxz92e.js} +109 -109
  52. package/dist/bin/chunk-tytvrehe.js +1 -0
  53. package/dist/bin/{chunk-v5bjbyve.js → chunk-v002yxaf.js} +2 -2
  54. package/dist/bin/chunk-wpp0fa94.js +1 -0
  55. package/dist/bin/{chunk-c04dygzg.js → chunk-wyanqf91.js} +5 -5
  56. package/dist/bin/{chunk-mz2jbtcs.js → chunk-xs6afjat.js} +3 -3
  57. package/dist/bin/chunk-xzgxwnb7.js +1 -0
  58. package/dist/bin/chunk-y21yk6zv.js +1 -0
  59. package/dist/bin/chunk-yt1t5ct8.js +1 -0
  60. package/dist/bin/chunk-yxyvhqhr.js +2 -0
  61. package/dist/bin/{chunk-m51vpvr6.js → chunk-zcabmq4p.js} +3 -3
  62. package/dist/bin/chunk-zs8ddeaz.js +1 -0
  63. package/dist/bin/cli.js +335 -335
  64. package/dist/bin/dashboard-server.js +1 -1
  65. package/dist/{chunk-2dextjqf.js → chunk-01rbgche.js} +2 -2
  66. package/dist/{chunk-mgg0psgc.js → chunk-14zcywnp.js} +2 -2
  67. package/dist/{chunk-2ap78e1s.js → chunk-2hy7ny4k.js} +4 -4
  68. package/dist/{chunk-khatwx29.js → chunk-4apkvhsc.js} +98 -98
  69. package/dist/{chunk-3zzm5f28.js → chunk-4rb7stp5.js} +26 -26
  70. package/dist/chunk-5vxpgw8q.js +6 -0
  71. package/dist/{chunk-x60w04y3.js → chunk-60fn008g.js} +2 -2
  72. package/dist/{chunk-3jkc3s8c.js → chunk-92gn9ght.js} +19 -19
  73. package/dist/{chunk-9p89msvs.js → chunk-b5xjjz3y.js} +5 -5
  74. package/dist/{chunk-ezgpamw6.js → chunk-bz1hp7es.js} +1 -1
  75. package/dist/{chunk-pffebjr8.js → chunk-c836kdrx.js} +36 -36
  76. package/dist/{chunk-pcns0kz4.js → chunk-ckwdjb5q.js} +5 -5
  77. package/dist/chunk-cpyrhh52.js +709 -0
  78. package/dist/chunk-cwgy9pvc.js +34 -0
  79. package/dist/{chunk-kpyhx96m.js → chunk-ds2v2xpb.js} +110 -110
  80. package/dist/chunk-e4qh4c2n.js +1 -0
  81. package/dist/{chunk-pwywwdq2.js → chunk-g6aev693.js} +1 -1
  82. package/dist/chunk-gm0qysea.js +114 -0
  83. package/dist/{chunk-jt49qs0f.js → chunk-hpq0rrve.js} +2 -2
  84. package/dist/{chunk-w4s3rswa.js → chunk-j2w0cvnr.js} +2 -2
  85. package/dist/{chunk-9s24pbbc.js → chunk-nfkdgsgh.js} +1 -1
  86. package/dist/{chunk-np8vgbv0.js → chunk-pdmfmsm9.js} +3 -3
  87. package/dist/chunk-pj9z4fjv.js +1 -0
  88. package/dist/{chunk-cfrv8110.js → chunk-rq0wrpz6.js} +4 -4
  89. package/dist/{chunk-ms4dnha2.js → chunk-t7q4awss.js} +1 -1
  90. package/dist/chunk-twhbns31.js +1 -0
  91. package/dist/chunk-wkg22nj5.js +1 -0
  92. package/dist/{chunk-dv1jkay7.js → chunk-xassxhvq.js} +7 -7
  93. package/dist/{chunk-5dz6bzdj.js → chunk-xkqx98bx.js} +2 -2
  94. package/dist/chunk-xtd0s5ep.js +1 -0
  95. package/dist/deploy/index.js +1 -1
  96. package/dist/dns/index.js +1 -1
  97. package/dist/drivers/index.js +1 -1
  98. package/dist/index.js +78 -78
  99. package/dist/operations/index.js +1 -1
  100. package/dist/protection/index.js +1 -1
  101. package/dist/spend/index.js +1 -1
  102. package/dist/ui/404.html +1 -1
  103. package/dist/ui/accept-invitation.html +1 -1
  104. package/dist/ui/access-denied.html +1 -1
  105. package/dist/ui/account/automation.html +6 -6
  106. package/dist/ui/account/security.html +2 -2
  107. package/dist/ui/applications/compose.html +6 -6
  108. package/dist/ui/applications/new.html +2 -2
  109. package/dist/ui/data/backups.html +5 -5
  110. package/dist/ui/data/services.html +6 -6
  111. package/dist/ui/data/volumes.html +6 -6
  112. package/dist/ui/index.html +6 -6
  113. package/dist/ui/infrastructure/topology.html +6 -6
  114. package/dist/ui/integrations.html +2 -2
  115. package/dist/ui/operations/alerts.html +6 -6
  116. package/dist/ui/operations/configuration.html +6 -6
  117. package/dist/ui/operations/jobs.html +6 -6
  118. package/dist/ui/operations/maintenance.html +6 -6
  119. package/dist/ui/operations/observability.html +6 -6
  120. package/dist/ui/operations/previews.html +6 -6
  121. package/dist/ui/operations/queue.html +6 -6
  122. package/dist/ui/operations/regions.html +6 -6
  123. package/dist/ui/operations/releases.html +6 -6
  124. package/dist/ui/operations/spend.html +6 -6
  125. package/dist/ui/operations/workloads.html +6 -6
  126. package/dist/ui/security.html +1 -1
  127. package/dist/ui/server/actions.html +6 -6
  128. package/dist/ui/server/activity.html +1 -1
  129. package/dist/ui/server/capacity.html +6 -6
  130. package/dist/ui/server/database.html +6 -6
  131. package/dist/ui/server/deployments.html +6 -6
  132. package/dist/ui/server/diagnostics.html +2 -2
  133. package/dist/ui/server/firewall.html +5 -5
  134. package/dist/ui/server/fleet.html +6 -6
  135. package/dist/ui/server/logs.html +6 -6
  136. package/dist/ui/server/metrics.html +6 -6
  137. package/dist/ui/server/security.html +2 -2
  138. package/dist/ui/server/services.html +2 -2
  139. package/dist/ui/server/sites.html +6 -6
  140. package/dist/ui/server/ssh-keys.html +5 -5
  141. package/dist/ui/server/team.html +6 -6
  142. package/dist/ui/server/terminal.html +2 -2
  143. package/dist/ui/serverless/alarms.html +6 -6
  144. package/dist/ui/serverless/assets.html +2 -2
  145. package/dist/ui/serverless/cost.html +2 -2
  146. package/dist/ui/serverless/data.html +6 -6
  147. package/dist/ui/serverless/deployments.html +2 -2
  148. package/dist/ui/serverless/firewall.html +1 -1
  149. package/dist/ui/serverless/functions.html +6 -6
  150. package/dist/ui/serverless/logs.html +6 -6
  151. package/dist/ui/serverless/metrics.html +2 -2
  152. package/dist/ui/serverless/queues.html +6 -6
  153. package/dist/ui/serverless/secrets.html +5 -5
  154. package/dist/ui/serverless/traces.html +6 -6
  155. package/dist/ui/serverless.html +6 -6
  156. package/package.json +3 -3
  157. package/dist/bin/chunk-0cefbrxg.js +0 -1
  158. package/dist/bin/chunk-1srmd473.js +0 -1
  159. package/dist/bin/chunk-27ka240w.js +0 -1
  160. package/dist/bin/chunk-3bq69jqk.js +0 -1
  161. package/dist/bin/chunk-4pysr1ky.js +0 -1
  162. package/dist/bin/chunk-56zfvf7e.js +0 -1
  163. package/dist/bin/chunk-59nav625.js +0 -1
  164. package/dist/bin/chunk-8fjzcr2w.js +0 -1
  165. package/dist/bin/chunk-9fq0bezb.js +0 -1
  166. package/dist/bin/chunk-9wpy7r9f.js +0 -1
  167. package/dist/bin/chunk-eetz9jgy.js +0 -1
  168. package/dist/bin/chunk-eg6156wp.js +0 -1
  169. package/dist/bin/chunk-ezpz96kp.js +0 -1
  170. package/dist/bin/chunk-f2qpsrrj.js +0 -1
  171. package/dist/bin/chunk-f3sbq7pw.js +0 -2
  172. package/dist/bin/chunk-gmabk4qn.js +0 -1
  173. package/dist/bin/chunk-kr51h4gk.js +0 -1
  174. package/dist/bin/chunk-mbqwrs7a.js +0 -6
  175. package/dist/bin/chunk-nx8gpr90.js +0 -34
  176. package/dist/bin/chunk-q62ggp3g.js +0 -1
  177. package/dist/bin/chunk-q957s44c.js +0 -1
  178. package/dist/bin/chunk-rm6qnyce.js +0 -2
  179. package/dist/bin/chunk-rxehseyz.js +0 -1
  180. package/dist/bin/chunk-tfz7djw9.js +0 -1
  181. package/dist/bin/chunk-tr8901hb.js +0 -1
  182. package/dist/bin/chunk-vqb80dyg.js +0 -1
  183. package/dist/bin/chunk-wysyyysg.js +0 -1
  184. package/dist/bin/chunk-xfs7rscr.js +0 -1
  185. package/dist/chunk-2fa9cdyf.js +0 -1
  186. package/dist/chunk-6d5e10md.js +0 -1
  187. package/dist/chunk-9gypn8w9.js +0 -1
  188. package/dist/chunk-badb5mf3.js +0 -34
  189. package/dist/chunk-j6a577hr.js +0 -1
  190. package/dist/chunk-kw852q5m.js +0 -709
  191. package/dist/chunk-p0b08g9f.js +0 -114
  192. package/dist/chunk-whdbz3h8.js +0 -1
  193. package/dist/chunk-y6k0vwfn.js +0 -6
@@ -1,26 +1,26 @@
1
- import{createRequire as er}from"node:module";import{isAbsolute as xt,join as ft,relative as cr}from"node:path";import{existsSync as He,readdirSync as gr}from"node:fs";import{join as ve}from"node:path";import{createHash as Nr}from"node:crypto";import{copyFileSync as Dr,existsSync as Nt,readdirSync as kr,readFileSync as st,statSync as $r,writeFileSync as ot}from"node:fs";import{basename as Lr,dirname as da,extname as ma,join as Je}from"node:path";import{existsSync as Ma,readFileSync as Jt}from"node:fs";import{homedir as Oa}from"node:os";import{join as xa}from"node:path";import{createHash as _a}from"node:crypto";import{existsSync as lt,mkdirSync as Ln,readdirSync as ya,readFileSync as fa,unlinkSync as Ye,writeFileSync as Mn}from"node:fs";import{join as kt}from"node:path";import{createHash as Yt}from"node:crypto";import{createReadStream as On,readdirSync as xn,statSync as bt}from"node:fs";import{join as Bn,relative as _n}from"node:path";import{deflateRawSync as zn}from"node:zlib";import{execSync as Xn}from"node:child_process";import{createHash as ei}from"node:crypto";import{cpSync as ti,mkdtempSync as ai,rmSync as ri,writeFileSync as ni}from"node:fs";import{tmpdir as ii}from"node:os";import{dirname as si,isAbsolute as oi,join as Oe,resolve as ci}from"node:path";import{fileURLToPath as li}from"node:url";import{execFileSync as Tt}from"node:child_process";import{mkdtempSync as Fa,readFileSync as wt,rmSync as Ua}from"node:fs";import{tmpdir as Va}from"node:os";import{dirname as pi,join as Pe}from"node:path";import{fileURLToPath as gi}from"node:url";import{AsyncLocalStorage as yi}from"node:async_hooks";import{createHash as fi}from"node:crypto";import{readFileSync as Ei}from"node:fs";import{dirname as Ii,join as za}from"node:path";import{fileURLToPath as $i}from"node:url";import{execFileSync as ut}from"node:child_process";import{existsSync as Mi,mkdirSync as Oi,mkdtempSync as xi,readdirSync as Bi,readFileSync as _i,rmSync as Wi,statSync as Qa,writeFileSync as Gi}from"node:fs";import{tmpdir as Fi}from"node:os";import{join as xe,relative as Ui}from"node:path";import{execSync as Vi}from"node:child_process";import{createHash as ji}from"node:crypto";import{readdirSync as Ki,readFileSync as qi,statSync as Ya}from"node:fs";import{join as Hi,relative as Za,resolve as ua}from"node:path";var tr=Object.defineProperty,ar=(n)=>n;function rr(n,i){this[n]=ar.bind(null,i)}var We=(n,i)=>{for(var s in i)tr(n,s,{get:i[s],enumerable:!0,configurable:!0,set:rr.bind(i,s)})},nr=(n,i,s)=>()=>{if(n)try{i=n(n=0)}catch(o){s=[o]}if(s)throw s[0];return i},ir=er(import.meta.url);function sg(n){let i=typeof n==="string"?new URL(n):n,{hostname:s,pathname:o}=i;if(s.endsWith(".on.aws")){let h=s.match(/^[^.]+\.lambda-url\.([^.]+)\.on\.aws$/);if(h)return{service:"lambda",region:h[1]};return{service:"",region:""}}if(s.endsWith(".r2.cloudflarestorage.com"))return{service:"s3",region:"auto"};if(s.endsWith(".backblazeb2.com")){let h=s.match(/^(?:[^.]+\.)?s3\.([^.]+)\.backblazeb2\.com$/);if(h)return{service:"s3",region:h[1]};return{service:"",region:""}}let c=s.replace("dualstack.","").match(/([^.]+)\.(?:([^.]+)\.)?amazonaws\.com(?:\.cn)?$/);if(!c)return{service:"",region:""};let l=c[1],u=c[2]||"";if(u==="us-gov")u="us-gov-west-1";else if(u==="s3"||u==="s3-accelerate")u="us-east-1",l="s3";else if(l==="iot")if(s.startsWith("iot."))l="execute-api";else if(s.startsWith("data.jobs.iot."))l="iot-jobs-data";else l=o==="/mqtt"?"iotdevicegateway":"iotdata";else if(l==="autoscaling");else if(!u&&l.startsWith("s3-"))u=l.slice(3).replace(/^fips-|^external-1/,""),l="s3";else if(l.endsWith("-fips"))l=l.slice(0,-5);else if(u&&/-\d$/.test(l)&&!/-\d$/.test(u))[l,u]=[u,l];return l=Ia[l]||l,{service:l,region:u||"us-east-1"}}function x(n){let{method:i,url:s,body:o="",accessKeyId:c,secretAccessKey:l,sessionToken:u,signQuery:h=!1,expiresIn:y=86400,datetime:f}=n,b=new URL(s),C=b.hostname,T=sg(b),w=n.service||T.service,E=n.region||T.region;if(!w)throw Error("Could not detect service from URL. Please provide service explicitly.");if(!E)throw Error("Could not detect region from URL. Please provide region explicitly.");let I=f||new Date().toISOString().replace(/[:-]|\.\d{3}/g,""),N=I.substring(0,8),D=[N,E,w,"aws4_request"].join("/"),B="AWS4-HMAC-SHA256";if(h)return sr({urlObj:b,method:i,body:o,accessKeyId:c,secretAccessKey:l,sessionToken:u,service:w,region:E,timestamp:I,date:N,credentialScope:D,algorithm:B,expiresIn:y,cache:n.cache});let R=b.pathname||"/",W=Ct(b.searchParams),_={host:C,"x-amz-date":I,...n.headers};if(u)_["x-amz-security-token"]=u;let j=Object.keys(_).some((Ie)=>Ie.toLowerCase()==="content-type");if(o&&!j)_["content-type"]="application/x-amz-json-1.0";if(w==="s3"&&!_["x-amz-content-sha256"])_["x-amz-content-sha256"]=Xe(o);let J=Aa(_),K=Ca(_),Y=_["x-amz-content-sha256"]||Xe(o),X=[i,vt(R),W,J,K,Y].join(`
2
- `),ne=Xe(X),me=[B,I,D,ne].join(`
3
- `),oe=n.cache??Le,le=Ta(l,N,E,w,me,oe),ie=[`${B} Credential=${c}/${D}`,`SignedHeaders=${K}`,`Signature=${le}`].join(", ");return _.authorization=ie,{url:s,method:i,headers:_,body:o||void 0}}async function og(n){let{method:i,url:s,body:o="",accessKeyId:c,secretAccessKey:l,sessionToken:u,signQuery:h=!1,expiresIn:y=86400,datetime:f}=n,b=new URL(s),C=b.hostname,T=sg(b),w=n.service||T.service,E=n.region||T.region;if(!w)throw Error("Could not detect service from URL. Please provide service explicitly.");if(!E)throw Error("Could not detect region from URL. Please provide region explicitly.");let I=f||new Date().toISOString().replace(/[:-]|\.\d{3}/g,""),N=I.substring(0,8),D=[N,E,w,"aws4_request"].join("/"),B="AWS4-HMAC-SHA256";if(h)return or({urlObj:b,method:i,body:o,accessKeyId:c,secretAccessKey:l,sessionToken:u,service:w,region:E,timestamp:I,date:N,credentialScope:D,algorithm:B,expiresIn:y,cache:n.cache});let R=b.pathname||"/",W=Ct(b.searchParams),_={host:C,"x-amz-date":I,...n.headers};if(u)_["x-amz-security-token"]=u;let j=Object.keys(_).some((Ge)=>Ge.toLowerCase()==="content-type");if(o&&!j)_["content-type"]="application/x-amz-json-1.0";let J=await pt(o);if(w==="s3"&&!_["x-amz-content-sha256"])_["x-amz-content-sha256"]=J;let K=Aa(_),Y=Ca(_),X=_["x-amz-content-sha256"]||J,ne=[i,vt(R),W,K,Y,X].join(`
4
- `),me=await pt(ne),oe=[B,I,D,me].join(`
5
- `),le=n.cache??Le,ie=await wa(l,N,E,w,oe,le),Ie=[`${B} Credential=${c}/${D}`,`SignedHeaders=${Y}`,`Signature=${ie}`].join(", ");return _.authorization=Ie,{url:s,method:i,headers:_,body:o||void 0}}function sr(n){let{urlObj:i,method:s,body:o,accessKeyId:c,secretAccessKey:l,sessionToken:u,service:h,region:y,timestamp:f,date:b,credentialScope:C,algorithm:T,expiresIn:w,cache:E}=n,I=new URL(i.toString());I.searchParams.set("X-Amz-Algorithm",T),I.searchParams.set("X-Amz-Credential",`${c}/${C}`),I.searchParams.set("X-Amz-Date",f),I.searchParams.set("X-Amz-Expires",String(w));let N=h==="s3"?"UNSIGNED-PAYLOAD":Xe(o);if(h==="s3")I.searchParams.set("X-Amz-Content-Sha256",N);let D="host";if(I.searchParams.set("X-Amz-SignedHeaders",D),u)I.searchParams.set("X-Amz-Security-Token",u);let B=vt(I.pathname||"/"),R=`host:${I.hostname}
6
- `,W=Ct(I.searchParams),_=[s,B,W,R,D,N].join(`
7
- `),j=[T,f,C,Xe(_)].join(`
8
- `),J=Ta(l,b,y,h,j,E??Le);return I.searchParams.set("X-Amz-Signature",J),{url:I.toString(),method:s,headers:{},body:o||void 0}}async function or(n){let{urlObj:i,method:s,body:o,accessKeyId:c,secretAccessKey:l,sessionToken:u,service:h,region:y,timestamp:f,date:b,credentialScope:C,algorithm:T,expiresIn:w,cache:E}=n,I=new URL(i.toString());I.searchParams.set("X-Amz-Algorithm",T),I.searchParams.set("X-Amz-Credential",`${c}/${C}`),I.searchParams.set("X-Amz-Date",f),I.searchParams.set("X-Amz-Expires",String(w));let N=h==="s3"?"UNSIGNED-PAYLOAD":await pt(o);if(h==="s3")I.searchParams.set("X-Amz-Content-Sha256",N);let D="host";if(I.searchParams.set("X-Amz-SignedHeaders",D),u)I.searchParams.set("X-Amz-Security-Token",u);let B=vt(I.pathname||"/"),R=`host:${I.hostname}
9
- `,W=Ct(I.searchParams),_=[s,B,W,R,D,N].join(`
10
- `),j=[T,f,C,await pt(_)].join(`
11
- `),J=await wa(l,b,y,h,j,E??Le);return I.searchParams.set("X-Amz-Signature",J),{url:I.toString(),method:s,headers:{},body:o||void 0}}function eA(n){let{url:i,method:s="GET",expiresIn:o=3600,...c}=n,l=Math.min(o,604800);return x({...c,url:i,method:s,signQuery:!0,expiresIn:l}).url}async function dI(n){let{url:i,method:s="GET",expiresIn:o=3600,...c}=n,l=Math.min(o,604800);return(await og({...c,url:i,method:s,signQuery:!0,expiresIn:l})).url}function Aa(n){return Object.keys(n).sort().map((i)=>`${i.toLowerCase()}:${n[i].trim().replace(/\s+/g," ")}`).join(`
1
+ import{createRequire as er}from"node:module";import{isAbsolute as xt,join as ht,relative as cr}from"node:path";import{existsSync as He,readdirSync as gr}from"node:fs";import{join as ve}from"node:path";import{createHash as Nr}from"node:crypto";import{copyFileSync as Dr,existsSync as Nt,readdirSync as kr,readFileSync as st,statSync as $r,writeFileSync as ot}from"node:fs";import{basename as Lr,dirname as da,extname as ma,join as Je}from"node:path";import{existsSync as Ma,readFileSync as Qt}from"node:fs";import{homedir as Oa}from"node:os";import{join as xa}from"node:path";import{createHash as _a}from"node:crypto";import{existsSync as lt,mkdirSync as Ln,readdirSync as ya,readFileSync as fa,unlinkSync as Ye,writeFileSync as Mn}from"node:fs";import{join as kt}from"node:path";import{createHash as Yt}from"node:crypto";import{createReadStream as On,readdirSync as xn,statSync as St}from"node:fs";import{join as Bn,relative as _n}from"node:path";import{deflateRawSync as zn}from"node:zlib";import{execSync as Xn}from"node:child_process";import{createHash as ei}from"node:crypto";import{cpSync as ti,mkdtempSync as ai,rmSync as ri,writeFileSync as ni}from"node:fs";import{tmpdir as ii}from"node:os";import{dirname as si,isAbsolute as oi,join as Oe,resolve as ci}from"node:path";import{fileURLToPath as li}from"node:url";import{execFileSync as Tt}from"node:child_process";import{mkdtempSync as Fa,readFileSync as wt,rmSync as Ua}from"node:fs";import{tmpdir as Va}from"node:os";import{dirname as pi,join as we}from"node:path";import{fileURLToPath as gi}from"node:url";import{AsyncLocalStorage as yi}from"node:async_hooks";import{createHash as fi}from"node:crypto";import{readFileSync as Ti}from"node:fs";import{dirname as wi,join as za}from"node:path";import{fileURLToPath as Ei}from"node:url";import{execFileSync as ut}from"node:child_process";import{existsSync as $i,mkdirSync as Li,mkdtempSync as Mi,readdirSync as Oi,readFileSync as xi,rmSync as Wi,statSync as Qa,writeFileSync as Gi}from"node:fs";import{tmpdir as Fi}from"node:os";import{join as xe,relative as Ui}from"node:path";import{execSync as Vi}from"node:child_process";import{createHash as ji}from"node:crypto";import{readdirSync as Ki,readFileSync as qi,statSync as Ya}from"node:fs";import{join as Hi,relative as Za,resolve as ua}from"node:path";var tr=Object.defineProperty,ar=(n)=>n;function rr(n,i){this[n]=ar.bind(null,i)}var Ge=(n,i)=>{for(var s in i)tr(n,s,{get:i[s],enumerable:!0,configurable:!0,set:rr.bind(i,s)})},nr=(n,i,s)=>()=>{if(n)try{i=n(n=0)}catch(o){s=[o]}if(s)throw s[0];return i},ir=er(import.meta.url);function ag(n){let i=typeof n==="string"?new URL(n):n,{hostname:s,pathname:o}=i;if(s.endsWith(".on.aws")){let h=s.match(/^[^.]+\.lambda-url\.([^.]+)\.on\.aws$/);if(h)return{service:"lambda",region:h[1]};return{service:"",region:""}}if(s.endsWith(".r2.cloudflarestorage.com"))return{service:"s3",region:"auto"};if(s.endsWith(".backblazeb2.com")){let h=s.match(/^(?:[^.]+\.)?s3\.([^.]+)\.backblazeb2\.com$/);if(h)return{service:"s3",region:h[1]};return{service:"",region:""}}let c=s.replace("dualstack.","").match(/([^.]+)\.(?:([^.]+)\.)?amazonaws\.com(?:\.cn)?$/);if(!c)return{service:"",region:""};let l=c[1],u=c[2]||"";if(u==="us-gov")u="us-gov-west-1";else if(u==="s3"||u==="s3-accelerate")u="us-east-1",l="s3";else if(l==="iot")if(s.startsWith("iot."))l="execute-api";else if(s.startsWith("data.jobs.iot."))l="iot-jobs-data";else l=o==="/mqtt"?"iotdevicegateway":"iotdata";else if(l==="autoscaling");else if(!u&&l.startsWith("s3-"))u=l.slice(3).replace(/^fips-|^external-1/,""),l="s3";else if(l.endsWith("-fips"))l=l.slice(0,-5);else if(u&&/-\d$/.test(l)&&!/-\d$/.test(u))[l,u]=[u,l];return l=Ia[l]||l,{service:l,region:u||"us-east-1"}}function O(n){let{method:i,url:s,body:o="",accessKeyId:c,secretAccessKey:l,sessionToken:u,signQuery:h=!1,expiresIn:y=86400,datetime:f}=n,b=new URL(s),C=b.hostname,T=ag(b),w=n.service||T.service,E=n.region||T.region;if(!w)throw Error("Could not detect service from URL. Please provide service explicitly.");if(!E)throw Error("Could not detect region from URL. Please provide region explicitly.");let I=f||new Date().toISOString().replace(/[:-]|\.\d{3}/g,""),N=I.substring(0,8),D=[N,E,w,"aws4_request"].join("/"),x="AWS4-HMAC-SHA256";if(h)return sr({urlObj:b,method:i,body:o,accessKeyId:c,secretAccessKey:l,sessionToken:u,service:w,region:E,timestamp:I,date:N,credentialScope:D,algorithm:x,expiresIn:y,cache:n.cache});let R=b.pathname||"/",_=Ct(b.searchParams),B={host:C,"x-amz-date":I,...n.headers};if(u)B["x-amz-security-token"]=u;let W=Object.keys(B).some((Ee)=>Ee.toLowerCase()==="content-type");if(o&&!W)B["content-type"]="application/x-amz-json-1.0";if(w==="s3"&&!B["x-amz-content-sha256"])B["x-amz-content-sha256"]=Xe(o);let J=Aa(B),K=Ca(B),Y=B["x-amz-content-sha256"]||Xe(o),Z=[i,vt(R),_,J,K,Y].join(`
2
+ `),ne=Xe(Z),de=[x,I,D,ne].join(`
3
+ `),oe=n.cache??Le,le=Ta(l,N,E,w,de,oe),ie=[`${x} Credential=${c}/${D}`,`SignedHeaders=${K}`,`Signature=${le}`].join(", ");return B.authorization=ie,{url:s,method:i,headers:B,body:o||void 0}}async function cg(n){let{method:i,url:s,body:o="",accessKeyId:c,secretAccessKey:l,sessionToken:u,signQuery:h=!1,expiresIn:y=86400,datetime:f}=n,b=new URL(s),C=b.hostname,T=ag(b),w=n.service||T.service,E=n.region||T.region;if(!w)throw Error("Could not detect service from URL. Please provide service explicitly.");if(!E)throw Error("Could not detect region from URL. Please provide region explicitly.");let I=f||new Date().toISOString().replace(/[:-]|\.\d{3}/g,""),N=I.substring(0,8),D=[N,E,w,"aws4_request"].join("/"),x="AWS4-HMAC-SHA256";if(h)return or({urlObj:b,method:i,body:o,accessKeyId:c,secretAccessKey:l,sessionToken:u,service:w,region:E,timestamp:I,date:N,credentialScope:D,algorithm:x,expiresIn:y,cache:n.cache});let R=b.pathname||"/",_=Ct(b.searchParams),B={host:C,"x-amz-date":I,...n.headers};if(u)B["x-amz-security-token"]=u;let W=Object.keys(B).some((Fe)=>Fe.toLowerCase()==="content-type");if(o&&!W)B["content-type"]="application/x-amz-json-1.0";let J=await mt(o);if(w==="s3"&&!B["x-amz-content-sha256"])B["x-amz-content-sha256"]=J;let K=Aa(B),Y=Ca(B),Z=B["x-amz-content-sha256"]||J,ne=[i,vt(R),_,K,Y,Z].join(`
4
+ `),de=await mt(ne),oe=[x,I,D,de].join(`
5
+ `),le=n.cache??Le,ie=await wa(l,N,E,w,oe,le),Ee=[`${x} Credential=${c}/${D}`,`SignedHeaders=${Y}`,`Signature=${ie}`].join(", ");return B.authorization=Ee,{url:s,method:i,headers:B,body:o||void 0}}function sr(n){let{urlObj:i,method:s,body:o,accessKeyId:c,secretAccessKey:l,sessionToken:u,service:h,region:y,timestamp:f,date:b,credentialScope:C,algorithm:T,expiresIn:w,cache:E}=n,I=new URL(i.toString());I.searchParams.set("X-Amz-Algorithm",T),I.searchParams.set("X-Amz-Credential",`${c}/${C}`),I.searchParams.set("X-Amz-Date",f),I.searchParams.set("X-Amz-Expires",String(w));let N=h==="s3"?"UNSIGNED-PAYLOAD":Xe(o);if(h==="s3")I.searchParams.set("X-Amz-Content-Sha256",N);let D="host";if(I.searchParams.set("X-Amz-SignedHeaders",D),u)I.searchParams.set("X-Amz-Security-Token",u);let x=vt(I.pathname||"/"),R=`host:${I.hostname}
6
+ `,_=Ct(I.searchParams),B=[s,x,_,R,D,N].join(`
7
+ `),W=[T,f,C,Xe(B)].join(`
8
+ `),J=Ta(l,b,y,h,W,E??Le);return I.searchParams.set("X-Amz-Signature",J),{url:I.toString(),method:s,headers:{},body:o||void 0}}async function or(n){let{urlObj:i,method:s,body:o,accessKeyId:c,secretAccessKey:l,sessionToken:u,service:h,region:y,timestamp:f,date:b,credentialScope:C,algorithm:T,expiresIn:w,cache:E}=n,I=new URL(i.toString());I.searchParams.set("X-Amz-Algorithm",T),I.searchParams.set("X-Amz-Credential",`${c}/${C}`),I.searchParams.set("X-Amz-Date",f),I.searchParams.set("X-Amz-Expires",String(w));let N=h==="s3"?"UNSIGNED-PAYLOAD":await mt(o);if(h==="s3")I.searchParams.set("X-Amz-Content-Sha256",N);let D="host";if(I.searchParams.set("X-Amz-SignedHeaders",D),u)I.searchParams.set("X-Amz-Security-Token",u);let x=vt(I.pathname||"/"),R=`host:${I.hostname}
9
+ `,_=Ct(I.searchParams),B=[s,x,_,R,D,N].join(`
10
+ `),W=[T,f,C,await mt(B)].join(`
11
+ `),J=await wa(l,b,y,h,W,E??Le);return I.searchParams.set("X-Amz-Signature",J),{url:I.toString(),method:s,headers:{},body:o||void 0}}function rA(n){let{url:i,method:s="GET",expiresIn:o=3600,...c}=n,l=Math.min(o,604800);return O({...c,url:i,method:s,signQuery:!0,expiresIn:l}).url}async function uI(n){let{url:i,method:s="GET",expiresIn:o=3600,...c}=n,l=Math.min(o,604800);return(await cg({...c,url:i,method:s,signQuery:!0,expiresIn:l})).url}function Aa(n){return Object.keys(n).sort().map((i)=>`${i.toLowerCase()}:${n[i].trim().replace(/\s+/g," ")}`).join(`
12
12
  `)+`
13
- `}function Ca(n){return Object.keys(n).sort().map((i)=>i.toLowerCase()).join(";")}function Ct(n){let i=[];return n.forEach((s,o)=>{i.push([Ot(o),Ot(s)])}),i.sort((s,o)=>{if(s[0]<o[0])return-1;if(s[0]>o[0])return 1;if(s[1]<o[1])return-1;if(s[1]>o[1])return 1;return 0}),i.map(([s,o])=>`${s}=${o}`).join("&")}function vt(n){return n.split("/").map((i)=>Ot(i)).join("/")}function Ot(n){return encodeURIComponent(n).replace(/[!'()*]/g,(i)=>`%${i.charCodeAt(0).toString(16).toUpperCase()}`)}function Xe(n){if(!_e)throw Error("Synchronous hash not available in browser. Use signRequestAsync() instead.");return _e.createHash("sha256").update(n,"utf8").digest("hex")}function Ue(n,i){if(!_e)throw Error("Synchronous hmac not available in browser. Use signRequestAsync() instead.");return _e.createHmac("sha256",n).update(i,"utf8").digest()}async function pt(n){let i=new TextEncoder().encode(n),s=await crypto.subtle.digest("SHA-256",i);return va(new Uint8Array(s))}async function Ke(n,i){let s=new TextEncoder,o=typeof n==="string"?s.encode(n):n,c=s.encode(i),l=await crypto.subtle.importKey("raw",o.buffer,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),u=await crypto.subtle.sign("HMAC",l,c.buffer);return new Uint8Array(u)}function va(n){return Array.from(n).map((i)=>i.toString(16).padStart(2,"0")).join("")}function Ta(n,i,s,o,c,l){let u=`${n}:${i}:${s}:${o}`,h=l.get(u);if(!h){let y=Ue(`AWS4${n}`,i),f=Ue(y,s),b=Ue(f,o);if(h=Ue(b,"aws4_request"),l.size>=Pa){let C=l.keys().next().value;if(C)l.delete(C)}l.set(u,h)}return Ue(h,c).toString("hex")}async function wa(n,i,s,o,c,l){let u=`${n}:${i}:${s}:${o}`,h=l.get(u);if(!h){let f=await Ke(`AWS4${n}`,i),b=await Ke(f,s),C=await Ke(b,o);if(h=await Ke(C,"aws4_request"),l.size>=Pa){let T=l.keys().next().value;if(T)l.delete(T)}l.set(u,h)}let y=await Ke(h,c);return va(y)}function Ea(n,i){return i.includes(n)}function gt(n,i,s){let o=i*Math.pow(2,n),c=Math.random()*0.3*o;return Math.min(o+c,s)}function yt(n){return new Promise((i)=>setTimeout(i,n))}async function tA(n,i){let{maxRetries:s=3,initialDelayMs:o=100,maxDelayMs:c=5000,retryableStatusCodes:l=[429,500,502,503,504],timeoutMs:u=30000}=i??{},h,y;for(let f=0;f<=s;f++){let b=x(n),C={method:b.method,headers:b.headers};if(b.body)C.body=b.body;let T=new AbortController,w=setTimeout(()=>T.abort(),u);C.signal=T.signal;try{let E=await fetch(b.url,C);if(clearTimeout(w),y=E,E.ok)return E;if(f<s&&Ea(E.status,l)){let N=gt(f,o,c);await yt(N);continue}let I=await E.text();throw Error(`AWS API request failed (${E.status}): ${I}`)}catch(E){if(clearTimeout(w),h=E,E instanceof Error&&E.name==="AbortError")h=Error(`Request timed out after ${u}ms`);if(f<s&&!(E instanceof Error&&E.message.includes("AWS API request failed"))){let I=gt(f,o,c);await yt(I);continue}throw h}}throw h??Error("Request failed after retries")}async function lI(n){return tA(n,{maxRetries:0})}async function uI(n,i){let{maxRetries:s=3,initialDelayMs:o=100,maxDelayMs:c=5000,retryableStatusCodes:l=[429,500,502,503,504],timeoutMs:u=30000}=i??{},h;for(let y=0;y<=s;y++){let f=await og(n),b={method:f.method,headers:f.headers};if(f.body)b.body=f.body;let C=new AbortController,T=setTimeout(()=>C.abort(),u);b.signal=C.signal;try{let w=await fetch(f.url,b);if(clearTimeout(T),w.ok)return w;if(y<s&&Ea(w.status,l)){let I=gt(y,o,c);await yt(I);continue}let E=await w.text();throw Error(`AWS API request failed (${w.status}): ${E}`)}catch(w){if(clearTimeout(T),h=w,w instanceof Error&&w.name==="AbortError")h=Error(`Request timed out after ${u}ms`);if(y<s&&!(w instanceof Error&&w.message.includes("AWS API request failed"))){let E=gt(y,o,c);await yt(E);continue}throw h}}throw h??Error("Request failed after retries")}async function pI(n){let i=await n.text(),s={},o=/<(\w+)>([^<]+)<\/\1>/g,c;while((c=o.exec(i))!==null){let[,l,u]=c;s[l]=u}return s}async function gI(n){return await n.json()}function mI(){Le.clear()}function hI(){return Le.size}function fI(){return _e!==void 0}function yI(){return typeof crypto<"u"&&typeof crypto.subtle<"u"}var _e,Le,Pa=100,Ia,rt=nr(async()=>{try{_e=await import("node:crypto")}catch{}Le=new Map,Ia={appstream2:"appstream",cloudhsmv2:"cloudhsm",email:"ses",marketplace:"aws-marketplace",mobile:"AWSMobileHubService",pinpoint:"mobiletargeting",queue:"sqs","git-codecommit":"codecommit","mturk-requester-sandbox":"mturk-requester","personalize-runtime":"personalize"}}),II={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}},SI={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}}}},ag=".ts-cloud",cg="TS_CLOUD_STATE_DIR",Ft=null;function yd(n){Ft=n?.trim()||null}function Id(){return Boolean(process.env[cg]?.trim()||Ft)}function oo(){return process.env[cg]?.trim()||Ft||ag}function O(...n){return ft(oo(),...n)}function d(n,...i){let s=oo();return xt(s)?ft(s,...i):ft(n,s,...i)}function Sd(n,i=process.cwd()){let s=(c,l)=>{let u=cr(c,l);return u===""||!u.startsWith("..")&&!xt(u)},o=xt(n)?n:ft(i,n);return s(d(i),o)}function dg(n){let i=n.infrastructure?.compute!=null,s=Object.values(n.environments??{}).some((o)=>o?.app!=null);return{server:i,serverless:s}}function L(n){if(n.mode==="server"||n.mode==="serverless")return n.mode;let{serverless:i}=dg(n);return i?"serverless":"server"}function Cd(n){let{server:i,serverless:s}=dg(n);if(i&&s)return"A project cannot be both a server and a serverless deployment. Found `infrastructure.compute` (server) AND `environments.<env>.app` (serverless Lambda). Keep one: remove `infrastructure.compute` for a serverless app, or remove `environments.<env>.app` for a server.";if(n.mode==="server"&&s&&!i)return"Config sets `mode: 'server'` but declares a serverless app (`environments.<env>.app`). Remove the app or change the mode.";if(n.mode==="serverless"&&i&&!s)return"Config sets `mode: 'serverless'` but declares a server (`infrastructure.compute`). Remove the compute block or change the mode.";return null}function p(n){return n.infrastructure?.appDatabase??n.infrastructure?.compute?.database}function lr(n){return typeof n==="object"&&n!==null?n:{}}function rA(n){return n===!0||typeof n==="object"&&n!==null}function ur(n,i){let s=i?n.environments?.[i]:void 0;if(s?.domain)return s.domain;let o=Object.values(n.sites??{}),c=n.sites?.main?.domain??o.find((l)=>l.domain)?.domain;if(c)return c;return`${n.project?.slug??"app"}.local`}function dr(n){let i=n.indexOf(".");return i>0?n.slice(i+1):void 0}function Ti(n,i={}){let s=n.infrastructure?.compute?.managedServices?.mail,o=lr(s),c=i.environmentType??(i.environment?n.environments?.[i.environment]?.type:void 0),l=o.mode??(c==="production"?"server":"catcher"),u=l==="server",h=ur(n,i.environment),y=o.hostname??(u?`mail.${h}`:"localhost"),f=o.ports??{},b=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},C=o.tls??{},T=C.enabled??u,w=!!(C.certPath&&C.keyPath),E=(o.accounts??[]).map((K)=>({address:K.address,password:K.password})),I=typeof o.dkim==="object"&&o.dkim!==null?o.dkim:{},N=o.dkim===!1?!1:o.dkim===!0||u,D=typeof o.webmail==="object"&&o.webmail!==null?o.webmail:{},B=o.webmail===!1?!1:D.enabled??!0,R=o.spam??{},W=o.delivery??(u?"direct":"none"),_=o.expose??u,j=dr(y),J=[...new Set([y,...j?[j]:[],...o.domains??[]])];return{enabled:rA(s),mode:l,version:o.version,hostname:y,domains:J,ports:b,tls:{enabled:T,acme:T&&!w&&(C.acme??!0),certPath:C.certPath,keyPath:C.keyPath,requireForAuth:C.requireForAuth??(T&&u),acmeEmail:C.acmeEmail??E[0]?.address},dkim:{enabled:N,selector:I.selector??"default",rotate:I.rotate??!1,rotateIntervalDays:I.rotateIntervalDays??90},webmail:{enabled:B,port:D.port??b.webmail,domain:D.domain},delivery:W,sesRegion:o.sesRegion??"us-east-1",accounts:E,storagePath:o.storagePath??"/var/lib/mail",maxMessageSize:o.maxMessageSize??26214400,spam:{enabled:R.enabled??u,enforce:R.enforce??!1,junkScore:R.junkScore??5,rejectScore:R.rejectScore??12,dnsbl:R.dnsbl??u,greylist:R.greylist??!1},webhookUrl:o.webhookUrl,expose:_,bindAddress:_?"0.0.0.0":"127.0.0.1"}}function Ed(n){if(!n.enabled||!n.expose)return[];let i=[n.ports.smtp,n.ports.submission,n.ports.submissions,n.ports.imap,n.ports.imaps,n.ports.managesieve].filter((s)=>typeof s==="number");if(n.webmail.enabled&&!n.webmail.domain)i.push(n.webmail.port);return[...new Set(i)].sort((s,o)=>s-o)}function bd(n){if(!n.enabled)return{};let i=n.ports.submission??n.ports.smtp,s={MAIL_MAILER:"smtp",MAIL_HOST:"127.0.0.1",MAIL_PORT:String(i)};if(n.mode==="server"){s.MAIL_ENCRYPTION=n.tls.enabled?"tls":"null";let o=n.accounts[0];if(o)s.MAIL_USERNAME=o.address,s.MAIL_PASSWORD=o.password}else s.MAIL_ENCRYPTION="null",s.MAIL_USERNAME="null",s.MAIL_PASSWORD="null";return s}function ue(n){if(n.cloud?.provider)return n.cloud.provider;if(n.ssh?.hosts?.length)return"ssh";if(n.hetzner?.apiToken)return"hetzner";return"aws"}class vd{template;constructor(n){this.template={AWSTemplateFormatVersion:"2010-09-09",Description:n,Resources:{}}}addResource(n,i){return this.template.Resources[n]=i,this}addResources(n){return Object.assign(this.template.Resources,n),this}addParameter(n,i){if(!this.template.Parameters)this.template.Parameters={};return this.template.Parameters[n]=i,this}addOutput(n,i){if(!this.template.Outputs)this.template.Outputs={};return this.template.Outputs[n]=i,this}addMetadata(n,i){if(!this.template.Metadata)this.template.Metadata={};return this.template.Metadata[n]=i,this}hasResource(n){return n in this.template.Resources}getResources(){return this.template.Resources}build(){return this.template}toJSON(n=!0){return JSON.stringify(this.template,null,n?2:0)}toYAML(){return this.convertToYAML(this.template)}convertToYAML(n,i=0){let s=" ".repeat(i),o="";for(let[c,l]of Object.entries(n)){if(l===null||l===void 0)continue;if(typeof l==="object"&&!Array.isArray(l))o+=`${s}${c}:
13
+ `}function Ca(n){return Object.keys(n).sort().map((i)=>i.toLowerCase()).join(";")}function Ct(n){let i=[];return n.forEach((s,o)=>{i.push([Ot(o),Ot(s)])}),i.sort((s,o)=>{if(s[0]<o[0])return-1;if(s[0]>o[0])return 1;if(s[1]<o[1])return-1;if(s[1]>o[1])return 1;return 0}),i.map(([s,o])=>`${s}=${o}`).join("&")}function vt(n){return n.split("/").map((i)=>Ot(i)).join("/")}function Ot(n){return encodeURIComponent(n).replace(/[!'()*]/g,(i)=>`%${i.charCodeAt(0).toString(16).toUpperCase()}`)}function Xe(n){if(!_e)throw Error("Synchronous hash not available in browser. Use signRequestAsync() instead.");return _e.createHash("sha256").update(n,"utf8").digest("hex")}function Ve(n,i){if(!_e)throw Error("Synchronous hmac not available in browser. Use signRequestAsync() instead.");return _e.createHmac("sha256",n).update(i,"utf8").digest()}async function mt(n){let i=new TextEncoder().encode(n),s=await crypto.subtle.digest("SHA-256",i);return va(new Uint8Array(s))}async function qe(n,i){let s=new TextEncoder,o=typeof n==="string"?s.encode(n):n,c=s.encode(i),l=await crypto.subtle.importKey("raw",o.buffer,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),u=await crypto.subtle.sign("HMAC",l,c.buffer);return new Uint8Array(u)}function va(n){return Array.from(n).map((i)=>i.toString(16).padStart(2,"0")).join("")}function Ta(n,i,s,o,c,l){let u=`${n}:${i}:${s}:${o}`,h=l.get(u);if(!h){let y=Ve(`AWS4${n}`,i),f=Ve(y,s),b=Ve(f,o);if(h=Ve(b,"aws4_request"),l.size>=Pa){let C=l.keys().next().value;if(C)l.delete(C)}l.set(u,h)}return Ve(h,c).toString("hex")}async function wa(n,i,s,o,c,l){let u=`${n}:${i}:${s}:${o}`,h=l.get(u);if(!h){let f=await qe(`AWS4${n}`,i),b=await qe(f,s),C=await qe(b,o);if(h=await qe(C,"aws4_request"),l.size>=Pa){let T=l.keys().next().value;if(T)l.delete(T)}l.set(u,h)}let y=await qe(h,c);return va(y)}function Ea(n,i){return i.includes(n)}function pt(n,i,s){let o=i*Math.pow(2,n),c=Math.random()*0.3*o;return Math.min(o+c,s)}function gt(n){return new Promise((i)=>setTimeout(i,n))}async function nA(n,i){let{maxRetries:s=3,initialDelayMs:o=100,maxDelayMs:c=5000,retryableStatusCodes:l=[429,500,502,503,504],timeoutMs:u=30000}=i??{},h,y;for(let f=0;f<=s;f++){let b=O(n),C={method:b.method,headers:b.headers};if(b.body)C.body=b.body;let T=new AbortController,w=setTimeout(()=>T.abort(),u);C.signal=T.signal;try{let E=await fetch(b.url,C);if(clearTimeout(w),y=E,E.ok)return E;if(f<s&&Ea(E.status,l)){let N=pt(f,o,c);await gt(N);continue}let I=await E.text();throw Error(`AWS API request failed (${E.status}): ${I}`)}catch(E){if(clearTimeout(w),h=E,E instanceof Error&&E.name==="AbortError")h=Error(`Request timed out after ${u}ms`);if(f<s&&!(E instanceof Error&&E.message.includes("AWS API request failed"))){let I=pt(f,o,c);await gt(I);continue}throw h}}throw h??Error("Request failed after retries")}async function pI(n){return nA(n,{maxRetries:0})}async function gI(n,i){let{maxRetries:s=3,initialDelayMs:o=100,maxDelayMs:c=5000,retryableStatusCodes:l=[429,500,502,503,504],timeoutMs:u=30000}=i??{},h;for(let y=0;y<=s;y++){let f=await cg(n),b={method:f.method,headers:f.headers};if(f.body)b.body=f.body;let C=new AbortController,T=setTimeout(()=>C.abort(),u);b.signal=C.signal;try{let w=await fetch(f.url,b);if(clearTimeout(T),w.ok)return w;if(y<s&&Ea(w.status,l)){let I=pt(y,o,c);await gt(I);continue}let E=await w.text();throw Error(`AWS API request failed (${w.status}): ${E}`)}catch(w){if(clearTimeout(T),h=w,w instanceof Error&&w.name==="AbortError")h=Error(`Request timed out after ${u}ms`);if(y<s&&!(w instanceof Error&&w.message.includes("AWS API request failed"))){let E=pt(y,o,c);await gt(E);continue}throw h}}throw h??Error("Request failed after retries")}async function mI(n){let i=await n.text(),s={},o=/<(\w+)>([^<]+)<\/\1>/g,c;while((c=o.exec(i))!==null){let[,l,u]=c;s[l]=u}return s}async function hI(n){return await n.json()}function fI(){Le.clear()}function yI(){return Le.size}function II(){return _e!==void 0}function SI(){return typeof crypto<"u"&&typeof crypto.subtle<"u"}var _e,Le,Pa=100,Ia,rt=nr(async()=>{try{_e=await import("node:crypto")}catch{}Le=new Map,Ia={appstream2:"appstream",cloudhsmv2:"cloudhsm",email:"ses",marketplace:"aws-marketplace",mobile:"AWSMobileHubService",pinpoint:"mobiletargeting",queue:"sqs","git-codecommit":"codecommit","mturk-requester-sandbox":"mturk-requester","personalize-runtime":"personalize"}}),CI={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}},EI={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}}}},dg=".ts-cloud",lg="TS_CLOUD_STATE_DIR",Ft=null;function Sd(n){Ft=n?.trim()||null}function Cd(){return Boolean(process.env[lg]?.trim()||Ft)}function co(){return process.env[lg]?.trim()||Ft||dg}function L(...n){return ht(co(),...n)}function d(n,...i){let s=co();return xt(s)?ht(s,...i):ht(n,s,...i)}function Ed(n,i=process.cwd()){let s=(c,l)=>{let u=cr(c,l);return u===""||!u.startsWith("..")&&!xt(u)},o=xt(n)?n:ht(i,n);return s(d(i),o)}function ug(n){let i=n.infrastructure?.compute!=null,s=Object.values(n.environments??{}).some((o)=>o?.app!=null);return{server:i,serverless:s}}function M(n){if(n.mode==="server"||n.mode==="serverless")return n.mode;let{serverless:i}=ug(n);return i?"serverless":"server"}function bd(n){let{server:i,serverless:s}=ug(n);if(i&&s)return"A project cannot be both a server and a serverless deployment. Found `infrastructure.compute` (server) AND `environments.<env>.app` (serverless Lambda). Keep one: remove `infrastructure.compute` for a serverless app, or remove `environments.<env>.app` for a server.";if(n.mode==="server"&&s&&!i)return"Config sets `mode: 'server'` but declares a serverless app (`environments.<env>.app`). Remove the app or change the mode.";if(n.mode==="serverless"&&i&&!s)return"Config sets `mode: 'serverless'` but declares a server (`infrastructure.compute`). Remove the compute block or change the mode.";return null}function p(n){return n.infrastructure?.appDatabase??n.infrastructure?.compute?.database}function lr(n){return typeof n==="object"&&n!==null?n:{}}function iA(n){return n===!0||typeof n==="object"&&n!==null}function ur(n,i){let s=i?n.environments?.[i]:void 0;if(s?.domain)return s.domain;let o=Object.values(n.sites??{}),c=n.sites?.main?.domain??o.find((l)=>l.domain)?.domain;if(c)return c;return`${n.project?.slug??"app"}.local`}function dr(n){let i=n.indexOf(".");return i>0?n.slice(i+1):void 0}function Ri(n,i={}){let s=n.infrastructure?.compute?.managedServices?.mail,o=lr(s),c=i.environmentType??(i.environment?n.environments?.[i.environment]?.type:void 0),l=o.mode??(c==="production"?"server":"catcher"),u=l==="server",h=ur(n,i.environment),y=o.hostname??(u?`mail.${h}`:"localhost"),f=o.ports??{},b=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},C=o.tls??{},T=C.enabled??u,w=!!(C.certPath&&C.keyPath),E=(o.accounts??[]).map((K)=>({address:K.address,password:K.password})),I=typeof o.dkim==="object"&&o.dkim!==null?o.dkim:{},N=o.dkim===!1?!1:o.dkim===!0||u,D=typeof o.webmail==="object"&&o.webmail!==null?o.webmail:{},x=o.webmail===!1?!1:D.enabled??!0,R=o.spam??{},_=o.delivery??(u?"direct":"none"),B=o.expose??u,W=dr(y),J=[...new Set([y,...W?[W]:[],...o.domains??[]])];return{enabled:iA(s),mode:l,version:o.version,hostname:y,domains:J,ports:b,tls:{enabled:T,acme:T&&!w&&(C.acme??!0),certPath:C.certPath,keyPath:C.keyPath,requireForAuth:C.requireForAuth??(T&&u),acmeEmail:C.acmeEmail??E[0]?.address},dkim:{enabled:N,selector:I.selector??"default",rotate:I.rotate??!1,rotateIntervalDays:I.rotateIntervalDays??90},webmail:{enabled:x,port:D.port??b.webmail,domain:D.domain},delivery:_,sesRegion:o.sesRegion??"us-east-1",accounts:E,storagePath:o.storagePath??"/var/lib/mail",maxMessageSize:o.maxMessageSize??26214400,spam:{enabled:R.enabled??u,enforce:R.enforce??!1,junkScore:R.junkScore??5,rejectScore:R.rejectScore??12,dnsbl:R.dnsbl??u,greylist:R.greylist??!1},webhookUrl:o.webhookUrl,expose:B,bindAddress:B?"0.0.0.0":"127.0.0.1"}}function vd(n){if(!n.enabled||!n.expose)return[];let i=[n.ports.smtp,n.ports.submission,n.ports.submissions,n.ports.imap,n.ports.imaps,n.ports.managesieve].filter((s)=>typeof s==="number");if(n.webmail.enabled&&!n.webmail.domain)i.push(n.webmail.port);return[...new Set(i)].sort((s,o)=>s-o)}function Td(n){if(!n.enabled)return{};let i=n.ports.submission??n.ports.smtp,s={MAIL_MAILER:"smtp",MAIL_HOST:"127.0.0.1",MAIL_PORT:String(i)};if(n.mode==="server"){s.MAIL_ENCRYPTION=n.tls.enabled?"tls":"null";let o=n.accounts[0];if(o)s.MAIL_USERNAME=o.address,s.MAIL_PASSWORD=o.password}else s.MAIL_ENCRYPTION="null",s.MAIL_USERNAME="null",s.MAIL_PASSWORD="null";return s}function ge(n){if(n.cloud?.provider)return n.cloud.provider;if(n.ssh?.hosts?.length)return"ssh";if(n.hetzner?.apiToken)return"hetzner";return"aws"}class wd{template;constructor(n){this.template={AWSTemplateFormatVersion:"2010-09-09",Description:n,Resources:{}}}addResource(n,i){return this.template.Resources[n]=i,this}addResources(n){return Object.assign(this.template.Resources,n),this}addParameter(n,i){if(!this.template.Parameters)this.template.Parameters={};return this.template.Parameters[n]=i,this}addOutput(n,i){if(!this.template.Outputs)this.template.Outputs={};return this.template.Outputs[n]=i,this}addMetadata(n,i){if(!this.template.Metadata)this.template.Metadata={};return this.template.Metadata[n]=i,this}hasResource(n){return n in this.template.Resources}getResources(){return this.template.Resources}build(){return this.template}toJSON(n=!0){return JSON.stringify(this.template,null,n?2:0)}toYAML(){return this.convertToYAML(this.template)}convertToYAML(n,i=0){let s=" ".repeat(i),o="";for(let[c,l]of Object.entries(n)){if(l===null||l===void 0)continue;if(typeof l==="object"&&!Array.isArray(l))o+=`${s}${c}:
14
14
  ${this.convertToYAML(l,i+1)}`;else if(Array.isArray(l)){o+=`${s}${c}:
15
15
  `;for(let u of l)if(typeof u==="object")o+=`${s} -
16
16
  ${this.convertToYAML(u,i+2)}`;else o+=`${s} - ${u}
17
17
  `}else o+=`${s}${c}: ${l}
18
- `}return o}}var k={Ref:(n)=>({Ref:n}),GetAtt:(n,i)=>({"Fn::GetAtt":[n,i]}),Sub:(n,i)=>{if(i)return{"Fn::Sub":[n,i]};return{"Fn::Sub":n}},Join:(n,i)=>({"Fn::Join":[n,i]}),Select:(n,i)=>({"Fn::Select":[n,i]}),Split:(n,i)=>({"Fn::Split":[n,i]}),GetAZs:(n="")=>({"Fn::GetAZs":n}),ImportValue:(n)=>({"Fn::ImportValue":n}),If:(n,i,s)=>({"Fn::If":[n,i,s]}),Equals:(n,i)=>({"Fn::Equals":[n,i]}),And:(...n)=>({"Fn::And":n}),Or:(...n)=>({"Fn::Or":n}),Not:(n)=>({"Fn::Not":[n]}),Base64:(n)=>({"Fn::Base64":n})},CI={AccountId:{Ref:"AWS::AccountId"},Region:{Ref:"AWS::Region"},StackId:{Ref:"AWS::StackId"},StackName:{Ref:"AWS::StackName"},NotificationARNs:{Ref:"AWS::NotificationARNs"},Partition:{Ref:"AWS::Partition"},URLSuffix:{Ref:"AWS::URLSuffix"},NoValue:{Ref:"AWS::NoValue"}};function r(n){let{slug:i,environment:s,resourceType:o,timestamp:c,suffix:l}=n,u=[i,s,o];if(c)u.push(c);if(l)u.push(l);return u.join("-")}function t(n){return n.split("-").map((i)=>i.charAt(0).toUpperCase()+i.slice(1)).join("")}function EI(){return Date.now().toString()}function bI(n){return n.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/^-+|-+$/g,"").replace(/-+/g,"-")}function g(n,i){return n.project.stackName??`${n.project.slug}-${i}`}function vI(n,i,s,o){return s.stackName??`${n.project.slug}-${o}-${i}-site`}function TI(n,i){return`${n.project.slug}-${i}`}function wI(n,i,s,o){if(o)return o;if(s==="main")return`${n}-${i}-site`;return`${n}-${i}-${s}`}function RI(n,i,s,o){return o??`${n}-${i}-${s}`}function DI(n,i){return`${n}-${i}-deploy`}function Ht(n,i){return`${n.project.slug}-${i}-app`}function Td(n,i){return`${n}-${i}-deployments`}function ao(n,i){return`${n}-${i}-assets`}class nA{nodes=new Map;addResource(n,i){let s=this.extractDependencies(i);this.nodes.set(n,{logicalId:n,resource:i,dependencies:s})}extractDependencies(n){let i=new Set;if(n.DependsOn)if(Array.isArray(n.DependsOn))n.DependsOn.forEach((s)=>i.add(s));else i.add(n.DependsOn);return this.findReferences(n.Properties||{},i),i}findReferences(n,i){if(!n||typeof n!=="object")return;if("Ref"in n&&typeof n.Ref==="string"){if(!n.Ref.startsWith("AWS::"))i.add(n.Ref)}if("Fn::GetAtt"in n&&Array.isArray(n["Fn::GetAtt"]))i.add(n["Fn::GetAtt"][0]);for(let s of Object.values(n))if(typeof s==="object")this.findReferences(s,i)}topologicalSort(){let n=[],i=new Set,s=new Set,o=(c)=>{if(i.has(c))return;if(s.has(c))throw Error(`Circular dependency detected: ${c}`);s.add(c);let l=this.nodes.get(c);if(l)for(let u of l.dependencies)o(u);s.delete(c),i.add(c),n.push(c)};for(let c of this.nodes.keys())o(c);return n}validate(){for(let[n,i]of this.nodes.entries())for(let s of i.dependencies)if(!this.nodes.has(s))throw Error(`Resource "${n}" depends on "${s}" which does not exist`)}getDependents(n){let i=[];for(let[s,o]of this.nodes.entries())if(o.dependencies.has(n))i.push(s);return i}}function PI(n,i){let s=[],o=[],c=[],l=[],u=[],h=n.Resources||{},y=i.Resources||{},f=new Set([...Object.keys(h),...Object.keys(y)]);for(let C of f){let T=h[C],w=y[C];if(!T&&w)s.push({logicalId:C,action:"add",resourceType:w.Type});else if(T&&!w)o.push({logicalId:C,action:"remove",resourceType:T.Type});else if(T&&w)if(T.Type!==w.Type)l.push({logicalId:C,action:"replace",resourceType:w.Type,reason:`Type changed from ${T.Type} to ${w.Type}`});else{let E=Ra(T.Properties||{},w.Properties||{});if(E.length>0)if(mr(T.Type,E))l.push({logicalId:C,action:"replace",resourceType:w.Type,changes:E,reason:"Property changes require replacement"});else c.push({logicalId:C,action:"update",resourceType:w.Type,changes:E});else u.push(C)}}let b=pr([...o,...l,...c]);return{added:s,removed:o,updated:c,replaced:l,unchanged:u,summary:{totalChanges:s.length+o.length+c.length+l.length,requiresReplacement:l.length>0,dangerousChanges:b}}}function Ra(n,i,s=""){let o=[],c=new Set([...Object.keys(n),...Object.keys(i)]);for(let l of c){let u=s?`${s}.${l}`:l,h=n[l],y=i[l];if(h===void 0&&y!==void 0)o.push({path:u,oldValue:void 0,newValue:y});else if(h!==void 0&&y===void 0)o.push({path:u,oldValue:h,newValue:void 0});else if(typeof h!==typeof y)o.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))o.push({path:u,oldValue:h,newValue:y})}else if(!Array.isArray(h)&&!Array.isArray(y)){let f=Ra(h,y,u);o.push(...f)}else o.push({path:u,oldValue:h,newValue:y});else if(h!==y)o.push({path:u,oldValue:h,newValue:y})}return o}function mr(n,i){let s={"AWS::S3::Bucket":new Set(["BucketName"]),"AWS::DynamoDB::Table":new Set(["TableName","KeySchema"]),"AWS::RDS::DBInstance":new Set(["DBInstanceIdentifier","DBName","Engine"]),"AWS::Lambda::Function":new Set(["FunctionName"]),"AWS::EC2::Instance":new Set(["ImageId","InstanceType","KeyName"]),"AWS::ECS::TaskDefinition":new Set(["Family","ContainerDefinitions"]),"AWS::ElastiCache::CacheCluster":new Set(["CacheNodeType","Engine"]),"AWS::CloudFront::Distribution":new Set([]),"AWS::Route53::HostedZone":new Set(["Name"]),"AWS::IAM::Role":new Set(["RoleName","Path"]),"AWS::KMS::Key":new Set(["KeyPolicy"]),"AWS::Cognito::UserPool":new Set(["UserPoolName"]),"AWS::OpenSearchService::Domain":new Set(["DomainName"])}[n];if(!s)return!1;for(let o of i){let c=o.path.split(".")[0];if(s.has(c))return!0}return!1}function pr(n){let i=[];for(let s of n){if(s.action==="remove"&&(s.resourceType==="AWS::RDS::DBInstance"||s.resourceType==="AWS::DynamoDB::Table"||s.resourceType==="AWS::ElastiCache::CacheCluster"))i.push(`Removing ${s.resourceType} ${s.logicalId} - data loss risk!`);if(s.action==="replace"&&(s.resourceType==="AWS::RDS::DBInstance"||s.resourceType==="AWS::DynamoDB::Table"))i.push(`Replacing ${s.resourceType} ${s.logicalId} - data loss risk!`);if((s.action==="remove"||s.action==="replace")&&s.resourceType==="AWS::S3::Bucket")i.push(`${s.action==="remove"?"Removing":"Replacing"} S3 bucket ${s.logicalId} - data loss risk!`);if(s.action==="replace"&&s.resourceType==="AWS::EC2::Instance")i.push(`Replacing EC2 instance ${s.logicalId} - downtime expected`);if(s.action==="update"&&s.resourceType==="AWS::EC2::SecurityGroup")i.push(`Updating security group ${s.logicalId} - may affect connectivity`);if((s.action==="update"||s.action==="replace")&&(s.resourceType==="AWS::IAM::Role"||s.resourceType==="AWS::IAM::Policy"))i.push(`Modifying IAM ${s.resourceType.split("::")[2]} ${s.logicalId} - may affect permissions`)}return i}function NI(n){let i=[];if(i.push(`=== Stack Update Analysis ===
18
+ `}return o}}var k={Ref:(n)=>({Ref:n}),GetAtt:(n,i)=>({"Fn::GetAtt":[n,i]}),Sub:(n,i)=>{if(i)return{"Fn::Sub":[n,i]};return{"Fn::Sub":n}},Join:(n,i)=>({"Fn::Join":[n,i]}),Select:(n,i)=>({"Fn::Select":[n,i]}),Split:(n,i)=>({"Fn::Split":[n,i]}),GetAZs:(n="")=>({"Fn::GetAZs":n}),ImportValue:(n)=>({"Fn::ImportValue":n}),If:(n,i,s)=>({"Fn::If":[n,i,s]}),Equals:(n,i)=>({"Fn::Equals":[n,i]}),And:(...n)=>({"Fn::And":n}),Or:(...n)=>({"Fn::Or":n}),Not:(n)=>({"Fn::Not":[n]}),Base64:(n)=>({"Fn::Base64":n})},bI={AccountId:{Ref:"AWS::AccountId"},Region:{Ref:"AWS::Region"},StackId:{Ref:"AWS::StackId"},StackName:{Ref:"AWS::StackName"},NotificationARNs:{Ref:"AWS::NotificationARNs"},Partition:{Ref:"AWS::Partition"},URLSuffix:{Ref:"AWS::URLSuffix"},NoValue:{Ref:"AWS::NoValue"}};function r(n){let{slug:i,environment:s,resourceType:o,timestamp:c,suffix:l}=n,u=[i,s,o];if(c)u.push(c);if(l)u.push(l);return u.join("-")}function t(n){return n.split("-").map((i)=>i.charAt(0).toUpperCase()+i.slice(1)).join("")}function vI(){return Date.now().toString()}function TI(n){return n.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/^-+|-+$/g,"").replace(/-+/g,"-")}function g(n,i){return n.project.stackName??`${n.project.slug}-${i}`}function wI(n,i,s,o){return s.stackName??`${n.project.slug}-${o}-${i}-site`}function RI(n,i){return`${n.project.slug}-${i}`}function DI(n,i,s,o){if(o)return o;if(s==="main")return`${n}-${i}-site`;return`${n}-${i}-${s}`}function PI(n,i,s,o){return o??`${n}-${i}-${s}`}function NI(n,i){return`${n}-${i}-deploy`}function Gt(n,i){return`${n.project.slug}-${i}-app`}function Rd(n,i){return`${n}-${i}-deployments`}function lo(n,i){return`${n}-${i}-assets`}class sA{nodes=new Map;addResource(n,i){let s=this.extractDependencies(i);this.nodes.set(n,{logicalId:n,resource:i,dependencies:s})}extractDependencies(n){let i=new Set;if(n.DependsOn)if(Array.isArray(n.DependsOn))n.DependsOn.forEach((s)=>i.add(s));else i.add(n.DependsOn);return this.findReferences(n.Properties||{},i),i}findReferences(n,i){if(!n||typeof n!=="object")return;if("Ref"in n&&typeof n.Ref==="string"){if(!n.Ref.startsWith("AWS::"))i.add(n.Ref)}if("Fn::GetAtt"in n&&Array.isArray(n["Fn::GetAtt"]))i.add(n["Fn::GetAtt"][0]);for(let s of Object.values(n))if(typeof s==="object")this.findReferences(s,i)}topologicalSort(){let n=[],i=new Set,s=new Set,o=(c)=>{if(i.has(c))return;if(s.has(c))throw Error(`Circular dependency detected: ${c}`);s.add(c);let l=this.nodes.get(c);if(l)for(let u of l.dependencies)o(u);s.delete(c),i.add(c),n.push(c)};for(let c of this.nodes.keys())o(c);return n}validate(){for(let[n,i]of this.nodes.entries())for(let s of i.dependencies)if(!this.nodes.has(s))throw Error(`Resource "${n}" depends on "${s}" which does not exist`)}getDependents(n){let i=[];for(let[s,o]of this.nodes.entries())if(o.dependencies.has(n))i.push(s);return i}}function kI(n,i){let s=[],o=[],c=[],l=[],u=[],h=n.Resources||{},y=i.Resources||{},f=new Set([...Object.keys(h),...Object.keys(y)]);for(let C of f){let T=h[C],w=y[C];if(!T&&w)s.push({logicalId:C,action:"add",resourceType:w.Type});else if(T&&!w)o.push({logicalId:C,action:"remove",resourceType:T.Type});else if(T&&w)if(T.Type!==w.Type)l.push({logicalId:C,action:"replace",resourceType:w.Type,reason:`Type changed from ${T.Type} to ${w.Type}`});else{let E=Ra(T.Properties||{},w.Properties||{});if(E.length>0)if(mr(T.Type,E))l.push({logicalId:C,action:"replace",resourceType:w.Type,changes:E,reason:"Property changes require replacement"});else c.push({logicalId:C,action:"update",resourceType:w.Type,changes:E});else u.push(C)}}let b=pr([...o,...l,...c]);return{added:s,removed:o,updated:c,replaced:l,unchanged:u,summary:{totalChanges:s.length+o.length+c.length+l.length,requiresReplacement:l.length>0,dangerousChanges:b}}}function Ra(n,i,s=""){let o=[],c=new Set([...Object.keys(n),...Object.keys(i)]);for(let l of c){let u=s?`${s}.${l}`:l,h=n[l],y=i[l];if(h===void 0&&y!==void 0)o.push({path:u,oldValue:void 0,newValue:y});else if(h!==void 0&&y===void 0)o.push({path:u,oldValue:h,newValue:void 0});else if(typeof h!==typeof y)o.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))o.push({path:u,oldValue:h,newValue:y})}else if(!Array.isArray(h)&&!Array.isArray(y)){let f=Ra(h,y,u);o.push(...f)}else o.push({path:u,oldValue:h,newValue:y});else if(h!==y)o.push({path:u,oldValue:h,newValue:y})}return o}function mr(n,i){let s={"AWS::S3::Bucket":new Set(["BucketName"]),"AWS::DynamoDB::Table":new Set(["TableName","KeySchema"]),"AWS::RDS::DBInstance":new Set(["DBInstanceIdentifier","DBName","Engine"]),"AWS::Lambda::Function":new Set(["FunctionName"]),"AWS::EC2::Instance":new Set(["ImageId","InstanceType","KeyName"]),"AWS::ECS::TaskDefinition":new Set(["Family","ContainerDefinitions"]),"AWS::ElastiCache::CacheCluster":new Set(["CacheNodeType","Engine"]),"AWS::CloudFront::Distribution":new Set([]),"AWS::Route53::HostedZone":new Set(["Name"]),"AWS::IAM::Role":new Set(["RoleName","Path"]),"AWS::KMS::Key":new Set(["KeyPolicy"]),"AWS::Cognito::UserPool":new Set(["UserPoolName"]),"AWS::OpenSearchService::Domain":new Set(["DomainName"])}[n];if(!s)return!1;for(let o of i){let c=o.path.split(".")[0];if(s.has(c))return!0}return!1}function pr(n){let i=[];for(let s of n){if(s.action==="remove"&&(s.resourceType==="AWS::RDS::DBInstance"||s.resourceType==="AWS::DynamoDB::Table"||s.resourceType==="AWS::ElastiCache::CacheCluster"))i.push(`Removing ${s.resourceType} ${s.logicalId} - data loss risk!`);if(s.action==="replace"&&(s.resourceType==="AWS::RDS::DBInstance"||s.resourceType==="AWS::DynamoDB::Table"))i.push(`Replacing ${s.resourceType} ${s.logicalId} - data loss risk!`);if((s.action==="remove"||s.action==="replace")&&s.resourceType==="AWS::S3::Bucket")i.push(`${s.action==="remove"?"Removing":"Replacing"} S3 bucket ${s.logicalId} - data loss risk!`);if(s.action==="replace"&&s.resourceType==="AWS::EC2::Instance")i.push(`Replacing EC2 instance ${s.logicalId} - downtime expected`);if(s.action==="update"&&s.resourceType==="AWS::EC2::SecurityGroup")i.push(`Updating security group ${s.logicalId} - may affect connectivity`);if((s.action==="update"||s.action==="replace")&&(s.resourceType==="AWS::IAM::Role"||s.resourceType==="AWS::IAM::Policy"))i.push(`Modifying IAM ${s.resourceType.split("::")[2]} ${s.logicalId} - may affect permissions`)}return i}function BI(n){let i=[];if(i.push(`=== Stack Update Analysis ===
19
19
  `),n.summary.totalChanges===0)return i.push(`No changes detected.
20
20
  `),i.join(`
21
21
  `);if(i.push(`Total changes: ${n.summary.totalChanges}`),i.push(`Requires replacement: ${n.summary.requiresReplacement?"Yes":"No"}
22
22
  `),n.summary.dangerousChanges.length>0){i.push("⚠️ DANGEROUS CHANGES DETECTED:");for(let s of n.summary.dangerousChanges)i.push(` • ${s}`);i.push("")}if(n.added.length>0){i.push(`✅ Resources to Add (${n.added.length}):`);for(let s of n.added)i.push(` + ${s.logicalId} (${s.resourceType})`);i.push("")}if(n.removed.length>0){i.push(`❌ Resources to Remove (${n.removed.length}):`);for(let s of n.removed)i.push(` - ${s.logicalId} (${s.resourceType})`);i.push("")}if(n.replaced.length>0){i.push(`\uD83D\uDD04 Resources to Replace (${n.replaced.length}):`);for(let s of n.replaced){if(i.push(` ~ ${s.logicalId} (${s.resourceType})`),s.reason)i.push(` Reason: ${s.reason}`);if(s.changes){for(let o of s.changes.slice(0,3))i.push(` • ${o.path}: ${JSON.stringify(o.oldValue)} → ${JSON.stringify(o.newValue)}`);if(s.changes.length>3)i.push(` ... and ${s.changes.length-3} more changes`)}}i.push("")}if(n.updated.length>0){i.push(`\uD83D\uDCDD Resources to Update (${n.updated.length}):`);for(let s of n.updated)if(i.push(` ~ ${s.logicalId} (${s.resourceType})`),s.changes){for(let o of s.changes.slice(0,3))i.push(` • ${o.path}: ${JSON.stringify(o.oldValue)} → ${JSON.stringify(o.newValue)}`);if(s.changes.length>3)i.push(` ... and ${s.changes.length-3} more changes`)}i.push("")}if(n.unchanged.length>0)i.push(`⚪ Unchanged Resources (${n.unchanged.length})`);return i.join(`
23
- `)}class Te{static createBucket(n){let{name:i,bucketName:s,slug:o,environment:c,public:l=!1,versioning:u=!1,website:h=!1,encryption:y=!0,intelligentTiering:f=!1,cors:b,lifecycleRules:C}=n,T=s??r({slug:o,environment:c,resourceType:"s3",suffix:i}),w=t(T),E={Type:"AWS::S3::Bucket",Properties:{BucketName:T}};if(y)E.Properties.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(u)E.Properties.VersioningConfiguration={Status:"Enabled"};if(h)E.Properties.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"error.html"};if(!l)E.Properties.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(b&&b.length>0)E.Properties.CorsConfiguration={CorsRules:b.map((N)=>({AllowedOrigins:N.allowedOrigins,AllowedMethods:N.allowedMethods,AllowedHeaders:N.allowedHeaders,MaxAge:N.maxAge}))};if(C&&C.length>0)E.Properties.LifecycleConfiguration={Rules:C.map((N)=>({Id:N.id,Status:N.enabled?"Enabled":"Disabled",ExpirationInDays:N.expirationDays,Transitions:N.transitions?.map((D)=>({TransitionInDays:D.days,StorageClass:D.storageClass}))}))};if(f&&C){let N={id:"IntelligentTieringRule",enabled:!0,transitions:[{days:0,storageClass:"INTELLIGENT_TIERING"}]};if(!E.Properties.LifecycleConfiguration)E.Properties.LifecycleConfiguration={Rules:[]};E.Properties.LifecycleConfiguration.Rules.push({Id:N.id,Status:"Enabled",Transitions:N.transitions?.map((D)=>({TransitionInDays:D.days,StorageClass:D.storageClass}))})}let I;if(l)I={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:k.Ref(w),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[k.Join("",[k.GetAtt(w,"Arn"),"/*"])]}]}}};return{bucket:E,bucketPolicy:I,logicalId:w}}static enableVersioning(n){if(!n.Properties)n.Properties={};return n.Properties.VersioningConfiguration={Status:"Enabled"},n}static enableWebsiteHosting(n,i="index.html",s="error.html"){if(!n.Properties)n.Properties={};return n.Properties.WebsiteConfiguration={IndexDocument:i,ErrorDocument:s},n}static setLifecycleRules(n,i){if(!n.Properties)n.Properties={};return n.Properties.LifecycleConfiguration={Rules:i.map((s)=>({Id:s.id,Status:s.enabled?"Enabled":"Disabled",ExpirationInDays:s.expirationDays,Transitions:s.transitions?.map((o)=>({TransitionInDays:o.days,StorageClass:o.storageClass}))}))},n}static enableIntelligentTiering(n){if(!n.Properties)n.Properties={};if(!n.Properties.LifecycleConfiguration)n.Properties.LifecycleConfiguration={Rules:[]};return n.Properties.LifecycleConfiguration.Rules.push({Id:"IntelligentTieringRule",Status:"Enabled",Transitions:[{TransitionInDays:0,StorageClass:"INTELLIGENT_TIERING"}]}),n}static addLambdaNotification(n,i){if(!n.Properties)n.Properties={};if(!n.Properties.NotificationConfiguration)n.Properties.NotificationConfiguration={};if(!n.Properties.NotificationConfiguration.LambdaConfigurations)n.Properties.NotificationConfiguration.LambdaConfigurations=[];let s={Event:i.events[0],Function:i.functionArn};if(i.filter)s.Filter={S3Key:{Rules:[...i.filter.prefix?[{Name:"prefix",Value:i.filter.prefix}]:[],...i.filter.suffix?[{Name:"suffix",Value:i.filter.suffix}]:[]]}};for(let o of i.events){let c={...s,Event:o};n.Properties.NotificationConfiguration.LambdaConfigurations.push(c)}return n}static Notifications={onObjectCreated:(n)=>({functionArn:n,events:["s3:ObjectCreated:*"]}),onObjectRemoved:(n)=>({functionArn:n,events:["s3:ObjectRemoved:*"]}),onImageUpload:(n,i)=>({functionArn:n,events:["s3:ObjectCreated:*"],filter:{prefix:i,suffix:".jpg"}}),onFileType:(n,i,s)=>({functionArn:n,events:["s3:ObjectCreated:*"],filter:{prefix:s,suffix:i}}),onFolderUpload:(n,i)=>({functionArn:n,events:["s3:ObjectCreated:*"],filter:{prefix:i.endsWith("/")?i:`${i}/`}})};static createBackupPlan(n){let{name:i,slug:s,environment:o,bucketLogicalIds:c,retentionDays:l,schedule:u="cron(0 5 * * ? *)",vaultName:h,enableContinuousBackup:y=!1,moveToColdStorageAfterDays:f}=n,b=h||r({slug:s,environment:o,resourceType:"backup-vault",suffix:i}),C=t(b),T={Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:b}},w=r({slug:s,environment:o,resourceType:"backup-role",suffix:i}),E=t(w),I={Type:"AWS::IAM::Role",Properties:{RoleName:w,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"backup.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup","arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForRestores"]}},N=r({slug:s,environment:o,resourceType:"backup-plan",suffix:i}),D=t(N),B={DeleteAfterDays:l};if(f&&f<l)B.MoveToColdStorageAfterDays=f;let R={Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:N,BackupPlanRule:[{RuleName:`${i}-daily-backup`,TargetBackupVault:k.Ref(C),ScheduleExpression:u,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:B,EnableContinuousBackup:y}]}}},W=r({slug:s,environment:o,resourceType:"backup-selection",suffix:i}),_=t(W),j=c.map((K)=>k.GetAtt(K,"Arn")),J={Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:k.Ref(D),BackupSelection:{SelectionName:W,IamRoleArn:k.GetAtt(E,"Arn"),Resources:j}}};return{vault:T,plan:R,selection:J,role:I,vaultLogicalId:C,planLogicalId:D,selectionLogicalId:_,roleLogicalId:E}}static BackupSchedules={HOURLY:"cron(0 * * * ? *)",DAILY_5AM:"cron(0 5 * * ? *)",DAILY_MIDNIGHT:"cron(0 0 * * ? *)",WEEKLY_SUNDAY:"cron(0 5 ? * SUN *)",WEEKLY_SATURDAY:"cron(0 5 ? * SAT *)",MONTHLY_FIRST:"cron(0 5 1 * ? *)",EVERY_12_HOURS:"cron(0 */12 * * ? *)",EVERY_6_HOURS:"cron(0 */6 * * ? *)"};static BackupRetention={ONE_DAY:1,ONE_WEEK:7,TWO_WEEKS:14,ONE_MONTH:30,THREE_MONTHS:90,SIX_MONTHS:180,ONE_YEAR:365,TWO_YEARS:730,FIVE_YEARS:1825,SEVEN_YEARS:2555};static createWwwRedirectBucket(n){let{slug:i,environment:s,sourceDomain:o,targetDomain:c,protocol:l="https"}=n,u=r({slug:i,environment:s,resourceType:"s3",suffix:"www-redirect"}),h=t(u),y={Type:"AWS::S3::Bucket",Properties:{BucketName:o,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:c,Protocol:l}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1}}},f={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:k.Ref(h),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[k.Join("",[k.GetAtt(h,"Arn"),"/*"])]}]}}};return{bucket:y,bucketPolicy:f,logicalId:h}}static createDocsBucket(n){let{slug:i,environment:s,domain:o}=n,c=o||r({slug:i,environment:s,resourceType:"s3",suffix:"docs"}),l=t(c);return{bucket:{Type:"AWS::S3::Bucket",Properties:{BucketName:c,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},Tags:[{Key:"backup",Value:"weekly"}]}},logicalId:l}}static createEmailBucket(n){let{slug:i,environment:s}=n,o=r({slug:i,environment:s,resourceType:"s3",suffix:"email"}),c=t(o),l={Type:"AWS::S3::Bucket",Properties:{BucketName:o,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},LifecycleConfiguration:{Rules:[{Id:"EmailRetention",Status:"Enabled",ExpirationInDays:90,Transitions:[{TransitionInDays:30,StorageClass:"STANDARD_IA"}]}]}}},u={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:k.Ref(c),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowSESPuts",Effect:"Allow",Principal:{Service:"ses.amazonaws.com"},Action:"s3:PutObject",Resource:k.Join("",[k.GetAtt(c,"Arn"),"/*"]),Condition:{StringEquals:{"AWS:SourceAccount":k.Ref("AWS::AccountId")}}}]}}};return{bucket:l,bucketPolicy:u,logicalId:c}}static docsExist(n={}){let{projectRoot:i=process.cwd(),docsPaths:s=["docs","documentation","doc"]}=n;for(let o of s){let c=ve(i,o);if(He(c)){let l=["dist","build",".bunpress/dist","_site","out","public"];for(let u of l){let h=ve(c,u);if(He(h))try{if(gr(h).length>0)return{exists:!0,path:c,hasDistFolder:!0,distPath:h}}catch{}}return{exists:!0,path:c,hasDistFolder:!1,distPath:null}}}return{exists:!1,path:null,hasDistFolder:!1,distPath:null}}static createDocsBucketIfExists(n){let i=Te.docsExist({projectRoot:n.projectRoot,docsPaths:n.docsPaths});if(!i.exists)return{bucket:null,logicalId:null,docsInfo:i};let s=Te.createDocsBucket({slug:n.slug,environment:n.environment,domain:n.domain});return{bucket:s.bucket,bucketPolicy:s.bucketPolicy,logicalId:s.logicalId,docsInfo:i}}static createPrivateBucket(n){let{slug:i,environment:s,enableVersioning:o=!0,retentionDays:c,encryptionKeyArn:l}=n,u=r({slug:i,environment:s,resourceType:"s3",suffix:"private"}),h=t(u);return{bucket:{Type:"AWS::S3::Bucket",Properties:{BucketName:u,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:l?{SSEAlgorithm:"aws:kms",KMSMasterKeyID:l}:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},VersioningConfiguration:o?{Status:"Enabled"}:void 0,LifecycleConfiguration:c?{Rules:[{Id:"RetentionPolicy",Status:"Enabled",ExpirationInDays:c}]}:void 0,Tags:[{Key:"backup",Value:"daily"}]}},logicalId:h}}static checkSourcePaths(n={}){let{projectRoot:i=process.cwd(),paths:s={}}=n,o=s.web||"views/web/dist",c=s.docs||"docs/dist",l=s.private||"private";return{web:{exists:He(ve(i,o)),path:ve(i,o)},docs:{exists:He(ve(i,c)),path:ve(i,c)},private:{exists:He(ve(i,l)),path:ve(i,l)}}}static createDeploymentBuckets(n){let{slug:i,environment:s,domain:o,projectRoot:c,paths:l}=n,u=Te.checkSourcePaths({projectRoot:c,paths:l}),h={},y={web:!1,docs:!1,private:!1},f=Te.createBucket({name:"web",slug:i,environment:s,public:!1,versioning:!1,encryption:!0});if(h[f.logicalId]=f.bucket,y.web=!0,u.docs.exists){let b=Te.createDocsBucket({slug:i,environment:s,domain:o?`docs.${o}`:void 0});if(h[b.logicalId]=b.bucket,b.bucketPolicy)h[`${b.logicalId}Policy`]=b.bucketPolicy;y.docs=!0}if(u.private.exists){let b=Te.createPrivateBucket({slug:i,environment:s,enableVersioning:!0});h[b.logicalId]=b.bucket,y.private=!0}return{resources:h,created:y,sourcePaths:u}}}class qe{static createRepository(n){let{name:i,slug:s,environment:o,scanOnPush:c=!0,imageMutability:l="MUTABLE",encryption:u="AES256",kmsKey:h,lifecyclePolicy:y,tags:f}=n,b=r({slug:s,environment:o,resourceType:"ecr",suffix:i}),C=t(b),T={Type:"AWS::ECR::Repository",Properties:{RepositoryName:b,ImageTagMutability:l,ImageScanningConfiguration:{ScanOnPush:c},EncryptionConfiguration:{EncryptionType:u,...h&&u==="KMS"?{KmsKey:h}:{}}}};if(y)T.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(qe.generateLifecyclePolicy(y))};if(f)T.Properties.Tags=Object.entries(f).map(([w,E])=>({Key:w,Value:E}));return{repository:T,logicalId:C}}static generateLifecyclePolicy(n){let i=[];if(n.untaggedImageExpireDays!==void 0)i.push({rulePriority:1,description:"Delete untagged images",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:n.untaggedImageExpireDays,countUnit:"days"},action:{type:"expire"}});if(n.maxImageCount!==void 0)i.push({rulePriority:i.length+1,description:"Keep only most recent images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:n.maxImageCount},action:{type:"expire"}});if(n.maxImageAgeDays!==void 0)i.push({rulePriority:i.length+1,description:"Delete images older than specified days",selection:{tagStatus:"any",countType:"sinceImagePushed",countNumber:n.maxImageAgeDays,countUnit:"days"},action:{type:"expire"}});return{rules:i}}static LifecyclePolicies={production:{maxImageCount:10,untaggedImageExpireDays:7},development:{maxImageCount:5,untaggedImageExpireDays:3},minimal:{maxImageCount:3,untaggedImageExpireDays:1},archive:{maxImageCount:50,untaggedImageExpireDays:30}};static enableImmutableTags(n){if(!n.Properties)n.Properties={};return n.Properties.ImageTagMutability="IMMUTABLE",n}static enableScanOnPush(n){if(!n.Properties)n.Properties={};return n.Properties.ImageScanningConfiguration={ScanOnPush:!0},n}static setLifecyclePolicy(n,i){if(!n.Properties)n.Properties={};return n.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(qe.generateLifecyclePolicy(i))},n}static addCrossAccountAccess(n,i){if(!n.Properties)n.Properties={};return n.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"CrossAccountPull",Effect:"Allow",Principal:{AWS:i.map((s)=>`arn:aws:iam::${s}:root`)},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:BatchCheckLayerAvailability"]}]},n}static addLambdaAccess(n){if(!n.Properties)n.Properties={};return n.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"LambdaECRImageRetrievalPolicy",Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage"]}]},n}static generateBunDockerfile(n){let{baseImage:i="oven/bun:1-debian",serverPath:s,port:o=3000,additionalDirs:c=[],healthCheckEndpoint:l="/health",nodeCompatible:u=!1,envVars:h={},buildCommands:y=[],runCommand:f}=n,b=["app","config",...c],C=f||`bun run ${s}`,T=`# Multi-stage build for Bun application
23
+ `)}class Re{static createBucket(n){let{name:i,bucketName:s,slug:o,environment:c,public:l=!1,versioning:u=!1,website:h=!1,encryption:y=!0,intelligentTiering:f=!1,cors:b,lifecycleRules:C}=n,T=s??r({slug:o,environment:c,resourceType:"s3",suffix:i}),w=t(T),E={Type:"AWS::S3::Bucket",Properties:{BucketName:T}};if(y)E.Properties.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(u)E.Properties.VersioningConfiguration={Status:"Enabled"};if(h)E.Properties.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"error.html"};if(!l)E.Properties.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(b&&b.length>0)E.Properties.CorsConfiguration={CorsRules:b.map((N)=>({AllowedOrigins:N.allowedOrigins,AllowedMethods:N.allowedMethods,AllowedHeaders:N.allowedHeaders,MaxAge:N.maxAge}))};if(C&&C.length>0)E.Properties.LifecycleConfiguration={Rules:C.map((N)=>({Id:N.id,Status:N.enabled?"Enabled":"Disabled",ExpirationInDays:N.expirationDays,Transitions:N.transitions?.map((D)=>({TransitionInDays:D.days,StorageClass:D.storageClass}))}))};if(f&&C){let N={id:"IntelligentTieringRule",enabled:!0,transitions:[{days:0,storageClass:"INTELLIGENT_TIERING"}]};if(!E.Properties.LifecycleConfiguration)E.Properties.LifecycleConfiguration={Rules:[]};E.Properties.LifecycleConfiguration.Rules.push({Id:N.id,Status:"Enabled",Transitions:N.transitions?.map((D)=>({TransitionInDays:D.days,StorageClass:D.storageClass}))})}let I;if(l)I={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:k.Ref(w),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[k.Join("",[k.GetAtt(w,"Arn"),"/*"])]}]}}};return{bucket:E,bucketPolicy:I,logicalId:w}}static enableVersioning(n){if(!n.Properties)n.Properties={};return n.Properties.VersioningConfiguration={Status:"Enabled"},n}static enableWebsiteHosting(n,i="index.html",s="error.html"){if(!n.Properties)n.Properties={};return n.Properties.WebsiteConfiguration={IndexDocument:i,ErrorDocument:s},n}static setLifecycleRules(n,i){if(!n.Properties)n.Properties={};return n.Properties.LifecycleConfiguration={Rules:i.map((s)=>({Id:s.id,Status:s.enabled?"Enabled":"Disabled",ExpirationInDays:s.expirationDays,Transitions:s.transitions?.map((o)=>({TransitionInDays:o.days,StorageClass:o.storageClass}))}))},n}static enableIntelligentTiering(n){if(!n.Properties)n.Properties={};if(!n.Properties.LifecycleConfiguration)n.Properties.LifecycleConfiguration={Rules:[]};return n.Properties.LifecycleConfiguration.Rules.push({Id:"IntelligentTieringRule",Status:"Enabled",Transitions:[{TransitionInDays:0,StorageClass:"INTELLIGENT_TIERING"}]}),n}static addLambdaNotification(n,i){if(!n.Properties)n.Properties={};if(!n.Properties.NotificationConfiguration)n.Properties.NotificationConfiguration={};if(!n.Properties.NotificationConfiguration.LambdaConfigurations)n.Properties.NotificationConfiguration.LambdaConfigurations=[];let s={Event:i.events[0],Function:i.functionArn};if(i.filter)s.Filter={S3Key:{Rules:[...i.filter.prefix?[{Name:"prefix",Value:i.filter.prefix}]:[],...i.filter.suffix?[{Name:"suffix",Value:i.filter.suffix}]:[]]}};for(let o of i.events){let c={...s,Event:o};n.Properties.NotificationConfiguration.LambdaConfigurations.push(c)}return n}static Notifications={onObjectCreated:(n)=>({functionArn:n,events:["s3:ObjectCreated:*"]}),onObjectRemoved:(n)=>({functionArn:n,events:["s3:ObjectRemoved:*"]}),onImageUpload:(n,i)=>({functionArn:n,events:["s3:ObjectCreated:*"],filter:{prefix:i,suffix:".jpg"}}),onFileType:(n,i,s)=>({functionArn:n,events:["s3:ObjectCreated:*"],filter:{prefix:s,suffix:i}}),onFolderUpload:(n,i)=>({functionArn:n,events:["s3:ObjectCreated:*"],filter:{prefix:i.endsWith("/")?i:`${i}/`}})};static createBackupPlan(n){let{name:i,slug:s,environment:o,bucketLogicalIds:c,retentionDays:l,schedule:u="cron(0 5 * * ? *)",vaultName:h,enableContinuousBackup:y=!1,moveToColdStorageAfterDays:f}=n,b=h||r({slug:s,environment:o,resourceType:"backup-vault",suffix:i}),C=t(b),T={Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:b}},w=r({slug:s,environment:o,resourceType:"backup-role",suffix:i}),E=t(w),I={Type:"AWS::IAM::Role",Properties:{RoleName:w,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"backup.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup","arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForRestores"]}},N=r({slug:s,environment:o,resourceType:"backup-plan",suffix:i}),D=t(N),x={DeleteAfterDays:l};if(f&&f<l)x.MoveToColdStorageAfterDays=f;let R={Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:N,BackupPlanRule:[{RuleName:`${i}-daily-backup`,TargetBackupVault:k.Ref(C),ScheduleExpression:u,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:x,EnableContinuousBackup:y}]}}},_=r({slug:s,environment:o,resourceType:"backup-selection",suffix:i}),B=t(_),W=c.map((K)=>k.GetAtt(K,"Arn")),J={Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:k.Ref(D),BackupSelection:{SelectionName:_,IamRoleArn:k.GetAtt(E,"Arn"),Resources:W}}};return{vault:T,plan:R,selection:J,role:I,vaultLogicalId:C,planLogicalId:D,selectionLogicalId:B,roleLogicalId:E}}static BackupSchedules={HOURLY:"cron(0 * * * ? *)",DAILY_5AM:"cron(0 5 * * ? *)",DAILY_MIDNIGHT:"cron(0 0 * * ? *)",WEEKLY_SUNDAY:"cron(0 5 ? * SUN *)",WEEKLY_SATURDAY:"cron(0 5 ? * SAT *)",MONTHLY_FIRST:"cron(0 5 1 * ? *)",EVERY_12_HOURS:"cron(0 */12 * * ? *)",EVERY_6_HOURS:"cron(0 */6 * * ? *)"};static BackupRetention={ONE_DAY:1,ONE_WEEK:7,TWO_WEEKS:14,ONE_MONTH:30,THREE_MONTHS:90,SIX_MONTHS:180,ONE_YEAR:365,TWO_YEARS:730,FIVE_YEARS:1825,SEVEN_YEARS:2555};static createWwwRedirectBucket(n){let{slug:i,environment:s,sourceDomain:o,targetDomain:c,protocol:l="https"}=n,u=r({slug:i,environment:s,resourceType:"s3",suffix:"www-redirect"}),h=t(u),y={Type:"AWS::S3::Bucket",Properties:{BucketName:o,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:c,Protocol:l}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1}}},f={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:k.Ref(h),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[k.Join("",[k.GetAtt(h,"Arn"),"/*"])]}]}}};return{bucket:y,bucketPolicy:f,logicalId:h}}static createDocsBucket(n){let{slug:i,environment:s,domain:o}=n,c=o||r({slug:i,environment:s,resourceType:"s3",suffix:"docs"}),l=t(c);return{bucket:{Type:"AWS::S3::Bucket",Properties:{BucketName:c,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},Tags:[{Key:"backup",Value:"weekly"}]}},logicalId:l}}static createEmailBucket(n){let{slug:i,environment:s}=n,o=r({slug:i,environment:s,resourceType:"s3",suffix:"email"}),c=t(o),l={Type:"AWS::S3::Bucket",Properties:{BucketName:o,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},LifecycleConfiguration:{Rules:[{Id:"EmailRetention",Status:"Enabled",ExpirationInDays:90,Transitions:[{TransitionInDays:30,StorageClass:"STANDARD_IA"}]}]}}},u={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:k.Ref(c),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowSESPuts",Effect:"Allow",Principal:{Service:"ses.amazonaws.com"},Action:"s3:PutObject",Resource:k.Join("",[k.GetAtt(c,"Arn"),"/*"]),Condition:{StringEquals:{"AWS:SourceAccount":k.Ref("AWS::AccountId")}}}]}}};return{bucket:l,bucketPolicy:u,logicalId:c}}static docsExist(n={}){let{projectRoot:i=process.cwd(),docsPaths:s=["docs","documentation","doc"]}=n;for(let o of s){let c=ve(i,o);if(He(c)){let l=["dist","build",".bunpress/dist","_site","out","public"];for(let u of l){let h=ve(c,u);if(He(h))try{if(gr(h).length>0)return{exists:!0,path:c,hasDistFolder:!0,distPath:h}}catch{}}return{exists:!0,path:c,hasDistFolder:!1,distPath:null}}}return{exists:!1,path:null,hasDistFolder:!1,distPath:null}}static createDocsBucketIfExists(n){let i=Re.docsExist({projectRoot:n.projectRoot,docsPaths:n.docsPaths});if(!i.exists)return{bucket:null,logicalId:null,docsInfo:i};let s=Re.createDocsBucket({slug:n.slug,environment:n.environment,domain:n.domain});return{bucket:s.bucket,bucketPolicy:s.bucketPolicy,logicalId:s.logicalId,docsInfo:i}}static createPrivateBucket(n){let{slug:i,environment:s,enableVersioning:o=!0,retentionDays:c,encryptionKeyArn:l}=n,u=r({slug:i,environment:s,resourceType:"s3",suffix:"private"}),h=t(u);return{bucket:{Type:"AWS::S3::Bucket",Properties:{BucketName:u,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:l?{SSEAlgorithm:"aws:kms",KMSMasterKeyID:l}:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},VersioningConfiguration:o?{Status:"Enabled"}:void 0,LifecycleConfiguration:c?{Rules:[{Id:"RetentionPolicy",Status:"Enabled",ExpirationInDays:c}]}:void 0,Tags:[{Key:"backup",Value:"daily"}]}},logicalId:h}}static checkSourcePaths(n={}){let{projectRoot:i=process.cwd(),paths:s={}}=n,o=s.web||"views/web/dist",c=s.docs||"docs/dist",l=s.private||"private";return{web:{exists:He(ve(i,o)),path:ve(i,o)},docs:{exists:He(ve(i,c)),path:ve(i,c)},private:{exists:He(ve(i,l)),path:ve(i,l)}}}static createDeploymentBuckets(n){let{slug:i,environment:s,domain:o,projectRoot:c,paths:l}=n,u=Re.checkSourcePaths({projectRoot:c,paths:l}),h={},y={web:!1,docs:!1,private:!1},f=Re.createBucket({name:"web",slug:i,environment:s,public:!1,versioning:!1,encryption:!0});if(h[f.logicalId]=f.bucket,y.web=!0,u.docs.exists){let b=Re.createDocsBucket({slug:i,environment:s,domain:o?`docs.${o}`:void 0});if(h[b.logicalId]=b.bucket,b.bucketPolicy)h[`${b.logicalId}Policy`]=b.bucketPolicy;y.docs=!0}if(u.private.exists){let b=Re.createPrivateBucket({slug:i,environment:s,enableVersioning:!0});h[b.logicalId]=b.bucket,y.private=!0}return{resources:h,created:y,sourcePaths:u}}}class je{static createRepository(n){let{name:i,slug:s,environment:o,scanOnPush:c=!0,imageMutability:l="MUTABLE",encryption:u="AES256",kmsKey:h,lifecyclePolicy:y,tags:f}=n,b=r({slug:s,environment:o,resourceType:"ecr",suffix:i}),C=t(b),T={Type:"AWS::ECR::Repository",Properties:{RepositoryName:b,ImageTagMutability:l,ImageScanningConfiguration:{ScanOnPush:c},EncryptionConfiguration:{EncryptionType:u,...h&&u==="KMS"?{KmsKey:h}:{}}}};if(y)T.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(je.generateLifecyclePolicy(y))};if(f)T.Properties.Tags=Object.entries(f).map(([w,E])=>({Key:w,Value:E}));return{repository:T,logicalId:C}}static generateLifecyclePolicy(n){let i=[];if(n.untaggedImageExpireDays!==void 0)i.push({rulePriority:1,description:"Delete untagged images",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:n.untaggedImageExpireDays,countUnit:"days"},action:{type:"expire"}});if(n.maxImageCount!==void 0)i.push({rulePriority:i.length+1,description:"Keep only most recent images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:n.maxImageCount},action:{type:"expire"}});if(n.maxImageAgeDays!==void 0)i.push({rulePriority:i.length+1,description:"Delete images older than specified days",selection:{tagStatus:"any",countType:"sinceImagePushed",countNumber:n.maxImageAgeDays,countUnit:"days"},action:{type:"expire"}});return{rules:i}}static LifecyclePolicies={production:{maxImageCount:10,untaggedImageExpireDays:7},development:{maxImageCount:5,untaggedImageExpireDays:3},minimal:{maxImageCount:3,untaggedImageExpireDays:1},archive:{maxImageCount:50,untaggedImageExpireDays:30}};static enableImmutableTags(n){if(!n.Properties)n.Properties={};return n.Properties.ImageTagMutability="IMMUTABLE",n}static enableScanOnPush(n){if(!n.Properties)n.Properties={};return n.Properties.ImageScanningConfiguration={ScanOnPush:!0},n}static setLifecyclePolicy(n,i){if(!n.Properties)n.Properties={};return n.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(je.generateLifecyclePolicy(i))},n}static addCrossAccountAccess(n,i){if(!n.Properties)n.Properties={};return n.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"CrossAccountPull",Effect:"Allow",Principal:{AWS:i.map((s)=>`arn:aws:iam::${s}:root`)},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:BatchCheckLayerAvailability"]}]},n}static addLambdaAccess(n){if(!n.Properties)n.Properties={};return n.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"LambdaECRImageRetrievalPolicy",Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage"]}]},n}static generateBunDockerfile(n){let{baseImage:i="oven/bun:1-debian",serverPath:s,port:o=3000,additionalDirs:c=[],healthCheckEndpoint:l="/health",nodeCompatible:u=!1,envVars:h={},buildCommands:y=[],runCommand:f}=n,b=["app","config",...c],C=f||`bun run ${s}`,T=`# Multi-stage build for Bun application
24
24
  # Generated by ts-cloud
25
25
 
26
26
  # Builder stage
@@ -74,7 +74,7 @@ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \\
74
74
 
75
75
  # Start application
76
76
  CMD ["bun", "run", "${s}"]
77
- `,T}static generateDockerBuildCommands(n){let{repositoryUri:i,tag:s="latest",dockerfilePath:o="Dockerfile",context:c=".",additionalTags:l=[],buildArgs:u={},platform:h="linux/amd64",noCache:y=!1}=n,f=`${i}:${s}`,b=[s,...l],C=`docker build -f ${o} -t ${f}`;if(h)C+=` --platform ${h}`;if(y)C+=" --no-cache";for(let[E,I]of Object.entries(u))C+=` --build-arg ${E}=${I}`;C+=` ${c}`;let T=b.slice(1).map((E)=>`docker tag ${f} ${i}:${E}`),w=b.map((E)=>`docker push ${i}:${E}`);return{build:C,tag:T,push:w,all:[C,...T,...w]}}static generateEcrLoginCommand(n,i){return`aws ecr get-login-password --region ${n} | docker login --username AWS --password-stdin ${i}.dkr.ecr.${n}.amazonaws.com`}static buildRepositoryUri(n){return`${n.accountId}.dkr.ecr.${n.region}.amazonaws.com/${n.repositoryName}`}static generateImageTags(n){let i=["latest"];if(n.version){i.push(n.version);let s=n.version.split(".");if(s.length>=2)i.push(`${s[0]}.${s[1]}`);if(s.length>=1)i.push(s[0])}if(n.gitSha)i.push(n.gitSha.substring(0,7)),i.push(n.gitSha);if(n.gitBranch){let s=n.gitBranch.replace(/[^a-zA-Z0-9.-]/g,"-").replace(/^-+|-+$/g,"");i.push(s)}if(n.environment)i.push(n.environment);if(n.timestamp){let s=new Date().toISOString().replace(/[:.]/g,"-").substring(0,19);i.push(s)}return[...new Set(i)]}static DeploymentWorkflow={generateDeployScript:(n)=>{let i=qe.buildRepositoryUri({accountId:n.accountId,region:n.region,repositoryName:n.repositoryName}),s=n.tags||["latest"],o=s[0];return`#!/bin/bash
77
+ `,T}static generateDockerBuildCommands(n){let{repositoryUri:i,tag:s="latest",dockerfilePath:o="Dockerfile",context:c=".",additionalTags:l=[],buildArgs:u={},platform:h="linux/amd64",noCache:y=!1}=n,f=`${i}:${s}`,b=[s,...l],C=`docker build -f ${o} -t ${f}`;if(h)C+=` --platform ${h}`;if(y)C+=" --no-cache";for(let[E,I]of Object.entries(u))C+=` --build-arg ${E}=${I}`;C+=` ${c}`;let T=b.slice(1).map((E)=>`docker tag ${f} ${i}:${E}`),w=b.map((E)=>`docker push ${i}:${E}`);return{build:C,tag:T,push:w,all:[C,...T,...w]}}static generateEcrLoginCommand(n,i){return`aws ecr get-login-password --region ${n} | docker login --username AWS --password-stdin ${i}.dkr.ecr.${n}.amazonaws.com`}static buildRepositoryUri(n){return`${n.accountId}.dkr.ecr.${n.region}.amazonaws.com/${n.repositoryName}`}static generateImageTags(n){let i=["latest"];if(n.version){i.push(n.version);let s=n.version.split(".");if(s.length>=2)i.push(`${s[0]}.${s[1]}`);if(s.length>=1)i.push(s[0])}if(n.gitSha)i.push(n.gitSha.substring(0,7)),i.push(n.gitSha);if(n.gitBranch){let s=n.gitBranch.replace(/[^a-zA-Z0-9.-]/g,"-").replace(/^-+|-+$/g,"");i.push(s)}if(n.environment)i.push(n.environment);if(n.timestamp){let s=new Date().toISOString().replace(/[:.]/g,"-").substring(0,19);i.push(s)}return[...new Set(i)]}static DeploymentWorkflow={generateDeployScript:(n)=>{let i=je.buildRepositoryUri({accountId:n.accountId,region:n.region,repositoryName:n.repositoryName}),s=n.tags||["latest"],o=s[0];return`#!/bin/bash
78
78
  set -e
79
79
 
80
80
  # Configuration
@@ -85,7 +85,7 @@ IMAGE_URI="${i}"
85
85
  DOCKERFILE="${n.dockerfilePath||"Dockerfile"}"
86
86
 
87
87
  echo "=== ECR Login ==="
88
- ${qe.generateEcrLoginCommand(n.region,n.accountId)}
88
+ ${je.generateEcrLoginCommand(n.region,n.accountId)}
89
89
 
90
90
  echo "=== Building Image ==="
91
91
  docker build -f $DOCKERFILE -t $IMAGE_URI:${o} --platform linux/amd64 .
@@ -103,7 +103,7 @@ echo "Image: $IMAGE_URI:${o}"
103
103
  docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
104
104
  docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest`},...n.ecsCluster&&n.ecsService?[{name:"Deploy to ECS",run:`aws ecs update-service --cluster ${n.ecsCluster} --service ${n.ecsService} --force-new-deployment`}]:[]]}}};return`# Generated by ts-cloud
105
105
  ${JSON.stringify(i,null,2).replace(/"/g,"").replace(/,\n/g,`
106
- `)}`}};static DockerfileTemplates={bunServer:(n,i=3000)=>qe.generateBunDockerfile({serverPath:n,port:i}),bunWithBuild:(n,i,s=3000)=>qe.generateBunDockerfile({serverPath:n,port:s,buildCommands:[i]}),bunFullStack:(n,i=3000)=>qe.generateBunDockerfile({serverPath:n,port:i,additionalDirs:["public","views","dist"],buildCommands:["bun run build"]}),bunApi:(n,i=3000)=>qe.generateBunDockerfile({serverPath:n,port:i,healthCheckEndpoint:"/api/health"})}}var wd=[400,403,404,416,429,500,502,503,504],lg=[500,502,503,504],ug=["GET","HEAD","OPTIONS"],kI="-failover-group",pg=["default","media-quality-based"],gg={min:1,max:3},mg={min:1,max:10};function Rd(n){if(n===void 0)return[...lg];if(n.length===0)throw Error(`CloudFront origin failover: statusCodes must list at least one code (allowed: ${wd.join(", ")}). Omit it to use the default ${lg.join(", ")}.`);let i=n.filter((s)=>!wd.includes(s));if(i.length>0)throw Error(`CloudFront origin failover: ${i.join(", ")} ${i.length===1?"is not a status code":"are not status codes"} CloudFront can fail over on. Allowed: ${wd.join(", ")}.`);return[...new Set(n)].sort((s,o)=>s-o)}function hg(n){let{primaryOriginId:i,secondaryOriginId:s}=n;if(!i||!s)throw Error("CloudFront origin failover: both a primary and a secondary origin id are required");if(i===s)throw Error(`CloudFront origin failover: the secondary origin must differ from the primary (both are "${i}")`);let o=Rd(n.statusCodes);return Na(n.selectionCriteria),{Id:n.groupId??`${i}-failover-group`,FailoverCriteria:{StatusCodes:{Quantity:o.length,Items:o}},Members:{Quantity:2,Items:[{OriginId:i},{OriginId:s}]},...n.selectionCriteria?{SelectionCriteria:n.selectionCriteria}:{}}}function Na(n,i="the origin group"){if(n===void 0)return;if(!pg.includes(n))throw Error(`CloudFront origin failover: ${i} has selection criteria ${JSON.stringify(n)}. Allowed: ${pg.join(", ")}.`)}function St(n,i,s){if(typeof n!=="number"||!Number.isInteger(n)||n<i.min||n>i.max)throw Error(`CloudFront origin: ${s} must be a whole number from ${i.min} to ${i.max}, got ${JSON.stringify(n)}.`)}function we(n,i="the origin"){let s={};if(n?.connectionAttempts!==void 0)St(n.connectionAttempts,gg,`${i} connectionAttempts`),s.ConnectionAttempts=n.connectionAttempts;if(n?.connectionTimeout!==void 0)St(n.connectionTimeout,mg,`${i} connectionTimeout (seconds)`),s.ConnectionTimeout=n.connectionTimeout;return s}function Qr(n){return{Quantity:1,Items:[hg(n)]}}function Gt(n,i="the cache behavior"){let s=(Array.isArray(n)?n:n?.Items??[]).filter((o)=>!ug.includes(o.toUpperCase()));if(s.length>0)throw Error(`CloudFront origin failover: ${i} allows ${s.join(", ")}, but a cache behavior that targets an origin group may only allow ${ug.join(", ")}. CloudFront never fails over a write, so point the write paths at a single origin in their own cache behavior.`)}function Dd(n){return/\.s3[.-](?:[a-z0-9-]+\.)?amazonaws\.com(?:\.cn)?$/i.test(n)&&!/s3-website/i.test(n)}function Qe(n){if(!n)return[];if(Array.isArray(n))return n;return n.Items??[]}function Se(n){return typeof n==="string"?n:void 0}var hr=/\.mediapackagev2\.[a-z0-9-]+\.amazonaws\.com$/i;function qt(n,i="the distribution"){let s=Qe(n.Origins),o=new Set(s.map((b)=>Se(b.Id)).filter((b)=>!!b)),c=new Map(s.map((b)=>[Se(b.Id)??"",b.DomainName])),l=s.some((b)=>Se(b.Id)===void 0);for(let b of s){let C=Se(b.Id)??"(unnamed origin)";if(b.ConnectionAttempts!==void 0)St(b.ConnectionAttempts,gg,`${i} origin "${C}" ConnectionAttempts`);if(b.ConnectionTimeout!==void 0)St(b.ConnectionTimeout,mg,`${i} origin "${C}" ConnectionTimeout (seconds)`)}let u=n.OriginGroups,h=Qe(u);if(u&&!Array.isArray(u)&&u.Quantity!==void 0&&u.Quantity!==h.length)throw Error(`CloudFront origin failover: ${i} OriginGroups.Quantity is ${u.Quantity} but it lists ${h.length} group(s).`);let y=new Set;for(let b of h){let C=Se(b.Id);if(b.Id===void 0||b.Id==="")throw Error(`CloudFront origin failover: ${i} has an origin group without an Id.`);let T=`${i} origin group "${C??"(intrinsic id)"}"`;if(C){if(y.has(C))throw Error(`CloudFront origin failover: ${i} declares origin group "${C}" twice.`);if(o.has(C))throw Error(`CloudFront origin failover: ${T} has the same id as an origin. Cache behaviors target groups and origins by id, so the two must differ.`);y.add(C)}let w=b.Members,E=Qe(w);if(E.length!==2||w?.Quantity!==void 0&&w.Quantity!==E.length)throw Error(`CloudFront origin failover: ${T} must have exactly 2 members (a primary and a secondary), it has ${E.length}${w?.Quantity!==void 0&&w.Quantity!==E.length?` with Quantity ${w.Quantity}`:""}.`);let I=E.map((B)=>Se(B.OriginId));for(let B of I)if(B&&!o.has(B)&&!l)throw Error(`CloudFront origin failover: ${T} lists member "${B}", which is not an origin of this distribution. Origins: ${[...o].join(", ")||"(none)"}.`);if(I[0]&&I[0]===I[1])throw Error(`CloudFront origin failover: ${T} lists "${I[0]}" as both primary and secondary.`);let N=b.FailoverCriteria?.StatusCodes,D=Qe(N);if(Rd(D),N?.Quantity!==void 0&&N.Quantity!==D.length)throw Error(`CloudFront origin failover: ${T} FailoverCriteria.StatusCodes.Quantity is ${N.Quantity} but it lists ${D.length} code(s).`);if(Na(b.SelectionCriteria,T),b.SelectionCriteria==="media-quality-based")for(let B of I){let R=B?Se(c.get(B)):void 0;if(R&&!hr.test(R))throw Error(`CloudFront origin failover: ${T} uses media-quality-based selection, which only works between AWS Elemental MediaPackage v2 origins, but member "${B}" is ${R}. Use 'default'.`)}}let f=[];if(n.DefaultCacheBehavior)f.push({behavior:n.DefaultCacheBehavior,name:"the default cache behavior"});for(let b of Qe(n.CacheBehaviors))f.push({behavior:b,name:`the cache behavior for ${JSON.stringify(b.PathPattern)}`});for(let{behavior:b,name:C}of f){let T=Se(b.TargetOriginId);if(!T)continue;if(y.has(T))Gt(b.AllowedMethods??["GET","HEAD"],`${C} of ${i} (origin group "${T}")`);else if(!o.has(T)&&!l&&h.every((w)=>Se(w.Id)!==void 0))throw Error(`CloudFront: ${C} of ${i} targets "${T}", which is neither an origin nor an origin group of this distribution.`)}}class pe{static createDistribution(n){let{slug:i,environment:s,origin:o,customDomain:c,certificateArn:l,errorPages:u,cachePolicy:h,edgeFunctions:y,http3:f=!1,comment:b,failoverOrigin:C}=n,T=r({slug:i,environment:s,resourceType:"cdn"}),w=t(T),E={Id:"DefaultOrigin",DomainName:o.domainName,OriginPath:o.originPath||"",...we(o,"the CDN origin")},I;if(o.type==="s3"){let D=`${w}OAC`;I={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${T}-oac`,Description:`Origin Access Control for ${T}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},E.OriginAccessControlId=k.Ref(D)}else if(o.type==="alb"||o.type==="custom")E.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only"};let N={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:b||`CDN for ${T}`,DefaultRootObject:"index.html",Origins:[E],DefaultCacheBehavior:{TargetOriginId:"DefaultOrigin",ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0},PriceClass:"PriceClass_100",HttpVersion:f?"http2and3":"http2"}}};if(c&&l)N.Properties.DistributionConfig.Aliases=[c],N.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:l,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};if(u&&u.length>0)N.Properties.DistributionConfig.CustomErrorResponses=u.map((D)=>({ErrorCode:D.errorCode,ResponseCode:D.responseCode,ResponsePagePath:D.responsePagePath}));if(y&&y.length>0)N.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=y.map((D)=>({EventType:D.event,LambdaFunctionARN:D.functionArn}));if(C)pe.addOriginFailover(N,C);return{distribution:N,originAccessControl:I,logicalId:w}}static addOriginFailover(n,i){let s=n.Properties.DistributionConfig,o=s.DefaultCacheBehavior,c=o.TargetOriginId,l=i.id??"FailoverOrigin";if(s.OriginGroups&&s.OriginGroups.Quantity>0)throw Error("CloudFront origin failover: this distribution already has an origin group");if(Gt(o.AllowedMethods??["GET","HEAD"],"the default cache behavior"),s.Origins.some((b)=>b.Id===l))throw Error(`CloudFront origin failover: an origin with id "${l}" already exists`);let u=hg({primaryOriginId:c,secondaryOriginId:l,statusCodes:i.statusCodes,selectionCriteria:i.selectionCriteria}),h=i.type??(Dd(i.domainName)?"s3":"custom"),y={Id:l,DomainName:i.domainName,OriginPath:i.originPath||"",...we(i,"the failover origin")},f=we(i.primary,"the primary origin");if(Object.keys(f).length>0){let b=s.Origins.find((C)=>C.Id===c);if(b)Object.assign(b,f)}if(h==="s3"){let b=s.Origins.find((C)=>C.Id===c);if(y.S3OriginConfig={OriginAccessIdentity:""},b?.OriginAccessControlId)y.OriginAccessControlId=b.OriginAccessControlId}else y.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only"};return s.Origins.push(y),s.OriginGroups={Quantity:1,Items:[u]},o.TargetOriginId=u.Id,qt(s),n}static setCustomDomain(n,i,s){return n.Properties.DistributionConfig.Aliases=[i],n.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:s,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"},n}static setErrorPages(n,i){return n.Properties.DistributionConfig.CustomErrorResponses=i.map((s)=>({ErrorCode:s.errorCode,ResponseCode:s.responseCode,ResponsePagePath:s.responsePagePath})),n}static enableHttp3(n){return n.Properties.DistributionConfig.HttpVersion="http2and3",n}static addEdgeFunction(n,i,s){if(!n.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations)n.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=[];return n.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations.push({EventType:i,LambdaFunctionARN:s}),n}static setCachePolicy(n,i){return n.Properties.DistributionConfig.Comment=`${n.Properties.DistributionConfig.Comment||""} (TTL: ${i.default||86400}s)`,n}static createSpaDistribution(n){return pe.createDistribution({...n,errorPages:[{errorCode:404,responseCode:200,responsePagePath:"/index.html"},{errorCode:403,responseCode:200,responsePagePath:"/index.html"}]})}static createDocsOriginRequestFunction(n){let{slug:i,environment:s}=n,o=r({slug:i,environment:s,resourceType:"edge-docs"}),c=t(o),l=t(`${o}-role`),u=t(`${o}-version`),h={Type:"AWS::IAM::Role",Properties:{RoleName:`${o}-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["lambda.amazonaws.com","edgelambda.amazonaws.com"]},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]}},y=`
106
+ `)}`}};static DockerfileTemplates={bunServer:(n,i=3000)=>je.generateBunDockerfile({serverPath:n,port:i}),bunWithBuild:(n,i,s=3000)=>je.generateBunDockerfile({serverPath:n,port:s,buildCommands:[i]}),bunFullStack:(n,i=3000)=>je.generateBunDockerfile({serverPath:n,port:i,additionalDirs:["public","views","dist"],buildCommands:["bun run build"]}),bunApi:(n,i=3000)=>je.generateBunDockerfile({serverPath:n,port:i,healthCheckEndpoint:"/api/health"})}}var Dd=[400,403,404,416,429,500,502,503,504],pg=[500,502,503,504],gg=["GET","HEAD","OPTIONS"],_I="-failover-group",mg=["default","media-quality-based"],hg={min:1,max:3},fg={min:1,max:10};function Pd(n){if(n===void 0)return[...pg];if(n.length===0)throw Error(`CloudFront origin failover: statusCodes must list at least one code (allowed: ${Dd.join(", ")}). Omit it to use the default ${pg.join(", ")}.`);let i=n.filter((s)=>!Dd.includes(s));if(i.length>0)throw Error(`CloudFront origin failover: ${i.join(", ")} ${i.length===1?"is not a status code":"are not status codes"} CloudFront can fail over on. Allowed: ${Dd.join(", ")}.`);return[...new Set(n)].sort((s,o)=>s-o)}function Ag(n){let{primaryOriginId:i,secondaryOriginId:s}=n;if(!i||!s)throw Error("CloudFront origin failover: both a primary and a secondary origin id are required");if(i===s)throw Error(`CloudFront origin failover: the secondary origin must differ from the primary (both are "${i}")`);let o=Pd(n.statusCodes);return Na(n.selectionCriteria),{Id:n.groupId??`${i}-failover-group`,FailoverCriteria:{StatusCodes:{Quantity:o.length,Items:o}},Members:{Quantity:2,Items:[{OriginId:i},{OriginId:s}]},...n.selectionCriteria?{SelectionCriteria:n.selectionCriteria}:{}}}function Na(n,i="the origin group"){if(n===void 0)return;if(!mg.includes(n))throw Error(`CloudFront origin failover: ${i} has selection criteria ${JSON.stringify(n)}. Allowed: ${mg.join(", ")}.`)}function yt(n,i,s){if(typeof n!=="number"||!Number.isInteger(n)||n<i.min||n>i.max)throw Error(`CloudFront origin: ${s} must be a whole number from ${i.min} to ${i.max}, got ${JSON.stringify(n)}.`)}function De(n,i="the origin"){let s={};if(n?.connectionAttempts!==void 0)yt(n.connectionAttempts,hg,`${i} connectionAttempts`),s.ConnectionAttempts=n.connectionAttempts;if(n?.connectionTimeout!==void 0)yt(n.connectionTimeout,fg,`${i} connectionTimeout (seconds)`),s.ConnectionTimeout=n.connectionTimeout;return s}function Gr(n){return{Quantity:1,Items:[Ag(n)]}}function qt(n,i="the cache behavior"){let s=(Array.isArray(n)?n:n?.Items??[]).filter((o)=>!gg.includes(o.toUpperCase()));if(s.length>0)throw Error(`CloudFront origin failover: ${i} allows ${s.join(", ")}, but a cache behavior that targets an origin group may only allow ${gg.join(", ")}. CloudFront never fails over a write, so point the write paths at a single origin in their own cache behavior.`)}function Nd(n){return/\.s3[.-](?:[a-z0-9-]+\.)?amazonaws\.com(?:\.cn)?$/i.test(n)&&!/s3-website/i.test(n)}function Qe(n){if(!n)return[];if(Array.isArray(n))return n;return n.Items??[]}function Se(n){return typeof n==="string"?n:void 0}var hr=/\.mediapackagev2\.[a-z0-9-]+\.amazonaws\.com$/i;function Vt(n,i="the distribution"){let s=Qe(n.Origins),o=new Set(s.map((b)=>Se(b.Id)).filter((b)=>!!b)),c=new Map(s.map((b)=>[Se(b.Id)??"",b.DomainName])),l=s.some((b)=>Se(b.Id)===void 0);for(let b of s){let C=Se(b.Id)??"(unnamed origin)";if(b.ConnectionAttempts!==void 0)yt(b.ConnectionAttempts,hg,`${i} origin "${C}" ConnectionAttempts`);if(b.ConnectionTimeout!==void 0)yt(b.ConnectionTimeout,fg,`${i} origin "${C}" ConnectionTimeout (seconds)`)}let u=n.OriginGroups,h=Qe(u);if(u&&!Array.isArray(u)&&u.Quantity!==void 0&&u.Quantity!==h.length)throw Error(`CloudFront origin failover: ${i} OriginGroups.Quantity is ${u.Quantity} but it lists ${h.length} group(s).`);let y=new Set;for(let b of h){let C=Se(b.Id);if(b.Id===void 0||b.Id==="")throw Error(`CloudFront origin failover: ${i} has an origin group without an Id.`);let T=`${i} origin group "${C??"(intrinsic id)"}"`;if(C){if(y.has(C))throw Error(`CloudFront origin failover: ${i} declares origin group "${C}" twice.`);if(o.has(C))throw Error(`CloudFront origin failover: ${T} has the same id as an origin. Cache behaviors target groups and origins by id, so the two must differ.`);y.add(C)}let w=b.Members,E=Qe(w);if(E.length!==2||w?.Quantity!==void 0&&w.Quantity!==E.length)throw Error(`CloudFront origin failover: ${T} must have exactly 2 members (a primary and a secondary), it has ${E.length}${w?.Quantity!==void 0&&w.Quantity!==E.length?` with Quantity ${w.Quantity}`:""}.`);let I=E.map((x)=>Se(x.OriginId));for(let x of I)if(x&&!o.has(x)&&!l)throw Error(`CloudFront origin failover: ${T} lists member "${x}", which is not an origin of this distribution. Origins: ${[...o].join(", ")||"(none)"}.`);if(I[0]&&I[0]===I[1])throw Error(`CloudFront origin failover: ${T} lists "${I[0]}" as both primary and secondary.`);let N=b.FailoverCriteria?.StatusCodes,D=Qe(N);if(Pd(D),N?.Quantity!==void 0&&N.Quantity!==D.length)throw Error(`CloudFront origin failover: ${T} FailoverCriteria.StatusCodes.Quantity is ${N.Quantity} but it lists ${D.length} code(s).`);if(Na(b.SelectionCriteria,T),b.SelectionCriteria==="media-quality-based")for(let x of I){let R=x?Se(c.get(x)):void 0;if(R&&!hr.test(R))throw Error(`CloudFront origin failover: ${T} uses media-quality-based selection, which only works between AWS Elemental MediaPackage v2 origins, but member "${x}" is ${R}. Use 'default'.`)}}let f=[];if(n.DefaultCacheBehavior)f.push({behavior:n.DefaultCacheBehavior,name:"the default cache behavior"});for(let b of Qe(n.CacheBehaviors))f.push({behavior:b,name:`the cache behavior for ${JSON.stringify(b.PathPattern)}`});for(let{behavior:b,name:C}of f){let T=Se(b.TargetOriginId);if(!T)continue;if(y.has(T))qt(b.AllowedMethods??["GET","HEAD"],`${C} of ${i} (origin group "${T}")`);else if(!o.has(T)&&!l&&h.every((w)=>Se(w.Id)!==void 0))throw Error(`CloudFront: ${C} of ${i} targets "${T}", which is neither an origin nor an origin group of this distribution.`)}}class me{static createDistribution(n){let{slug:i,environment:s,origin:o,customDomain:c,certificateArn:l,errorPages:u,cachePolicy:h,edgeFunctions:y,http3:f=!1,comment:b,failoverOrigin:C}=n,T=r({slug:i,environment:s,resourceType:"cdn"}),w=t(T),E={Id:"DefaultOrigin",DomainName:o.domainName,OriginPath:o.originPath||"",...De(o,"the CDN origin")},I;if(o.type==="s3"){let D=`${w}OAC`;I={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${T}-oac`,Description:`Origin Access Control for ${T}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},E.OriginAccessControlId=k.Ref(D)}else if(o.type==="alb"||o.type==="custom")E.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only"};let N={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:b||`CDN for ${T}`,DefaultRootObject:"index.html",Origins:[E],DefaultCacheBehavior:{TargetOriginId:"DefaultOrigin",ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0},PriceClass:"PriceClass_100",HttpVersion:f?"http2and3":"http2"}}};if(c&&l)N.Properties.DistributionConfig.Aliases=[c],N.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:l,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};if(u&&u.length>0)N.Properties.DistributionConfig.CustomErrorResponses=u.map((D)=>({ErrorCode:D.errorCode,ResponseCode:D.responseCode,ResponsePagePath:D.responsePagePath}));if(y&&y.length>0)N.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=y.map((D)=>({EventType:D.event,LambdaFunctionARN:D.functionArn}));if(C)me.addOriginFailover(N,C);return{distribution:N,originAccessControl:I,logicalId:w}}static addOriginFailover(n,i){let s=n.Properties.DistributionConfig,o=s.DefaultCacheBehavior,c=o.TargetOriginId,l=i.id??"FailoverOrigin";if(s.OriginGroups&&s.OriginGroups.Quantity>0)throw Error("CloudFront origin failover: this distribution already has an origin group");if(qt(o.AllowedMethods??["GET","HEAD"],"the default cache behavior"),s.Origins.some((b)=>b.Id===l))throw Error(`CloudFront origin failover: an origin with id "${l}" already exists`);let u=Ag({primaryOriginId:c,secondaryOriginId:l,statusCodes:i.statusCodes,selectionCriteria:i.selectionCriteria}),h=i.type??(Nd(i.domainName)?"s3":"custom"),y={Id:l,DomainName:i.domainName,OriginPath:i.originPath||"",...De(i,"the failover origin")},f=De(i.primary,"the primary origin");if(Object.keys(f).length>0){let b=s.Origins.find((C)=>C.Id===c);if(b)Object.assign(b,f)}if(h==="s3"){let b=s.Origins.find((C)=>C.Id===c);if(y.S3OriginConfig={OriginAccessIdentity:""},b?.OriginAccessControlId)y.OriginAccessControlId=b.OriginAccessControlId}else y.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only"};return s.Origins.push(y),s.OriginGroups={Quantity:1,Items:[u]},o.TargetOriginId=u.Id,Vt(s),n}static setCustomDomain(n,i,s){return n.Properties.DistributionConfig.Aliases=[i],n.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:s,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"},n}static setErrorPages(n,i){return n.Properties.DistributionConfig.CustomErrorResponses=i.map((s)=>({ErrorCode:s.errorCode,ResponseCode:s.responseCode,ResponsePagePath:s.responsePagePath})),n}static enableHttp3(n){return n.Properties.DistributionConfig.HttpVersion="http2and3",n}static addEdgeFunction(n,i,s){if(!n.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations)n.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=[];return n.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations.push({EventType:i,LambdaFunctionARN:s}),n}static setCachePolicy(n,i){return n.Properties.DistributionConfig.Comment=`${n.Properties.DistributionConfig.Comment||""} (TTL: ${i.default||86400}s)`,n}static createSpaDistribution(n){return me.createDistribution({...n,errorPages:[{errorCode:404,responseCode:200,responsePagePath:"/index.html"},{errorCode:403,responseCode:200,responsePagePath:"/index.html"}]})}static createDocsOriginRequestFunction(n){let{slug:i,environment:s}=n,o=r({slug:i,environment:s,resourceType:"edge-docs"}),c=t(o),l=t(`${o}-role`),u=t(`${o}-version`),h={Type:"AWS::IAM::Role",Properties:{RoleName:`${o}-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["lambda.amazonaws.com","edgelambda.amazonaws.com"]},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]}},y=`
107
107
  'use strict';
108
108
 
109
109
  exports.handler = async (event) => {
@@ -136,7 +136,7 @@ exports.handler = async (event) => {
136
136
 
137
137
  return request;
138
138
  };
139
- `.trim();return{lambdaFunction:{Type:"AWS::Lambda::Function",Properties:{FunctionName:o,Description:"Lambda@Edge origin request handler for docs routing",Runtime:"nodejs20.x",Handler:"index.handler",Role:k.GetAtt(l,"Arn"),Code:{ZipFile:y},MemorySize:128,Timeout:5}},role:h,functionLogicalId:c,roleLogicalId:l,versionLogicalId:u}}static createDocsDistribution(n){let{slug:i,environment:s,origin:o,customDomain:c,certificateArn:l,lambdaEdgeFunctionArn:u}=n,h=pe.createDistribution({slug:i,environment:s,origin:o,customDomain:c,certificateArn:l,comment:`Docs CDN for ${i}`,errorPages:[{errorCode:404,responseCode:404,responsePagePath:"/404.html"},{errorCode:403,responseCode:403,responsePagePath:"/404.html"}]});if(u)pe.addEdgeFunction(h.distribution,"origin-request",u);return h.distribution.Properties.DistributionConfig.DefaultCacheBehavior.DefaultTTL=86400,h.distribution.Properties.DistributionConfig.DefaultCacheBehavior.MaxTTL=604800,h.distribution.Properties.DistributionConfig.DefaultCacheBehavior.MinTTL=0,h}static createApiDistribution(n){let{slug:i,environment:s,albDomainName:o,customDomain:c,certificateArn:l,pathPattern:u="/api/*",forwardHeaders:h=["Host","Origin","Authorization","Content-Type","Accept"],forwardCookies:y="all",whitelistedCookies:f,customOriginHeaders:b={}}=n,C=r({slug:i,environment:s,resourceType:"cdn-api"}),T=t(C),w=Object.entries(b).map(([D,B])=>({HeaderName:D,HeaderValue:B})),E={Id:"ALBOrigin",DomainName:o,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(w.length>0)E.OriginCustomHeaders=w;let I={Forward:y};if(y==="whitelist"&&f)I.WhitelistedNames=f;let N={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:`API CDN for ${C}`,Origins:[E],DefaultCacheBehavior:{TargetOriginId:"ALBOrigin",ViewerProtocolPolicy:"https-only",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,DefaultTTL:0,MaxTTL:0,MinTTL:0,ForwardedValues:{QueryString:!0,Headers:h,Cookies:I}},PriceClass:"PriceClass_100",HttpVersion:"http2"}}};if(c&&l)N.Properties.DistributionConfig.Aliases=[c],N.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:l,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};return{distribution:N,logicalId:T}}static createMultiOriginDistribution(n){let{slug:i,environment:s,s3BucketDomainName:o,albDomainName:c,apiPathPattern:l="/api/*",customDomain:u,certificateArn:h,customOriginHeaders:y={}}=n,f=r({slug:i,environment:s,resourceType:"cdn"}),b=t(f),C=`${b}OAC`,T={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${f}-oac`,Description:`Origin Access Control for ${f}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},w=Object.entries(y).map(([D,B])=>({HeaderName:D,HeaderValue:B})),E={Id:"S3Origin",DomainName:o,OriginAccessControlId:k.Ref(C)},I={Id:"ALBOrigin",DomainName:c,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(w.length>0)I.OriginCustomHeaders=w;let N={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:`Multi-origin CDN for ${f}`,DefaultRootObject:"index.html",Origins:[E,I],DefaultCacheBehavior:{TargetOriginId:"S3Origin",ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0},CacheBehaviors:[{PathPattern:l,TargetOriginId:"ALBOrigin",ViewerProtocolPolicy:"https-only",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,DefaultTTL:0,MaxTTL:0,MinTTL:0,ForwardedValues:{QueryString:!0,Headers:["Host","Origin","Authorization","Content-Type","Accept"],Cookies:{Forward:"all"}}}],PriceClass:"PriceClass_100",HttpVersion:"http2",CustomErrorResponses:[{ErrorCode:404,ResponseCode:200,ResponsePagePath:"/index.html"},{ErrorCode:403,ResponseCode:200,ResponsePagePath:"/index.html"}]}}};if(u&&h)N.Properties.DistributionConfig.Aliases=[u],N.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:h,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};return{distribution:N,originAccessControl:T,logicalId:b,oacLogicalId:C}}static addAlbOrigin(n,i){let{originId:s,domainName:o,pathPattern:c,customHeaders:l={},forwardHeaders:u=["Host","Origin","Authorization","Content-Type","Accept"],cacheTtl:h={default:0,max:0,min:0}}=i,y=Object.entries(l).map(([b,C])=>({HeaderName:b,HeaderValue:C})),f={Id:s,DomainName:o,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(y.length>0)f.OriginCustomHeaders=y;if(!n.Properties.DistributionConfig.Origins)n.Properties.DistributionConfig.Origins=[];if(n.Properties.DistributionConfig.Origins.push(f),!n.Properties.DistributionConfig.CacheBehaviors)n.Properties.DistributionConfig.CacheBehaviors=[];return n.Properties.DistributionConfig.CacheBehaviors.push({PathPattern:c,TargetOriginId:s,ViewerProtocolPolicy:"https-only",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,DefaultTTL:h.default,MaxTTL:h.max,MinTTL:h.min,ForwardedValues:{QueryString:!0,Headers:u,Cookies:{Forward:"all"}}}),n}static addOriginHeader(n,i,s,o){let c=n.Properties.DistributionConfig.Origins?.find((l)=>l.Id===i);if(c){if(!c.OriginCustomHeaders)c.OriginCustomHeaders=[];c.OriginCustomHeaders.push({HeaderName:s,HeaderValue:o})}return n}static EdgeFunctionTemplates={docsOriginRequest:`
139
+ `.trim();return{lambdaFunction:{Type:"AWS::Lambda::Function",Properties:{FunctionName:o,Description:"Lambda@Edge origin request handler for docs routing",Runtime:"nodejs20.x",Handler:"index.handler",Role:k.GetAtt(l,"Arn"),Code:{ZipFile:y},MemorySize:128,Timeout:5}},role:h,functionLogicalId:c,roleLogicalId:l,versionLogicalId:u}}static createDocsDistribution(n){let{slug:i,environment:s,origin:o,customDomain:c,certificateArn:l,lambdaEdgeFunctionArn:u}=n,h=me.createDistribution({slug:i,environment:s,origin:o,customDomain:c,certificateArn:l,comment:`Docs CDN for ${i}`,errorPages:[{errorCode:404,responseCode:404,responsePagePath:"/404.html"},{errorCode:403,responseCode:403,responsePagePath:"/404.html"}]});if(u)me.addEdgeFunction(h.distribution,"origin-request",u);return h.distribution.Properties.DistributionConfig.DefaultCacheBehavior.DefaultTTL=86400,h.distribution.Properties.DistributionConfig.DefaultCacheBehavior.MaxTTL=604800,h.distribution.Properties.DistributionConfig.DefaultCacheBehavior.MinTTL=0,h}static createApiDistribution(n){let{slug:i,environment:s,albDomainName:o,customDomain:c,certificateArn:l,pathPattern:u="/api/*",forwardHeaders:h=["Host","Origin","Authorization","Content-Type","Accept"],forwardCookies:y="all",whitelistedCookies:f,customOriginHeaders:b={}}=n,C=r({slug:i,environment:s,resourceType:"cdn-api"}),T=t(C),w=Object.entries(b).map(([D,x])=>({HeaderName:D,HeaderValue:x})),E={Id:"ALBOrigin",DomainName:o,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(w.length>0)E.OriginCustomHeaders=w;let I={Forward:y};if(y==="whitelist"&&f)I.WhitelistedNames=f;let N={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:`API CDN for ${C}`,Origins:[E],DefaultCacheBehavior:{TargetOriginId:"ALBOrigin",ViewerProtocolPolicy:"https-only",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,DefaultTTL:0,MaxTTL:0,MinTTL:0,ForwardedValues:{QueryString:!0,Headers:h,Cookies:I}},PriceClass:"PriceClass_100",HttpVersion:"http2"}}};if(c&&l)N.Properties.DistributionConfig.Aliases=[c],N.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:l,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};return{distribution:N,logicalId:T}}static createMultiOriginDistribution(n){let{slug:i,environment:s,s3BucketDomainName:o,albDomainName:c,apiPathPattern:l="/api/*",customDomain:u,certificateArn:h,customOriginHeaders:y={}}=n,f=r({slug:i,environment:s,resourceType:"cdn"}),b=t(f),C=`${b}OAC`,T={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${f}-oac`,Description:`Origin Access Control for ${f}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},w=Object.entries(y).map(([D,x])=>({HeaderName:D,HeaderValue:x})),E={Id:"S3Origin",DomainName:o,OriginAccessControlId:k.Ref(C)},I={Id:"ALBOrigin",DomainName:c,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(w.length>0)I.OriginCustomHeaders=w;let N={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:`Multi-origin CDN for ${f}`,DefaultRootObject:"index.html",Origins:[E,I],DefaultCacheBehavior:{TargetOriginId:"S3Origin",ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0},CacheBehaviors:[{PathPattern:l,TargetOriginId:"ALBOrigin",ViewerProtocolPolicy:"https-only",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,DefaultTTL:0,MaxTTL:0,MinTTL:0,ForwardedValues:{QueryString:!0,Headers:["Host","Origin","Authorization","Content-Type","Accept"],Cookies:{Forward:"all"}}}],PriceClass:"PriceClass_100",HttpVersion:"http2",CustomErrorResponses:[{ErrorCode:404,ResponseCode:200,ResponsePagePath:"/index.html"},{ErrorCode:403,ResponseCode:200,ResponsePagePath:"/index.html"}]}}};if(u&&h)N.Properties.DistributionConfig.Aliases=[u],N.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:h,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};return{distribution:N,originAccessControl:T,logicalId:b,oacLogicalId:C}}static addAlbOrigin(n,i){let{originId:s,domainName:o,pathPattern:c,customHeaders:l={},forwardHeaders:u=["Host","Origin","Authorization","Content-Type","Accept"],cacheTtl:h={default:0,max:0,min:0}}=i,y=Object.entries(l).map(([b,C])=>({HeaderName:b,HeaderValue:C})),f={Id:s,DomainName:o,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(y.length>0)f.OriginCustomHeaders=y;if(!n.Properties.DistributionConfig.Origins)n.Properties.DistributionConfig.Origins=[];if(n.Properties.DistributionConfig.Origins.push(f),!n.Properties.DistributionConfig.CacheBehaviors)n.Properties.DistributionConfig.CacheBehaviors=[];return n.Properties.DistributionConfig.CacheBehaviors.push({PathPattern:c,TargetOriginId:s,ViewerProtocolPolicy:"https-only",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,DefaultTTL:h.default,MaxTTL:h.max,MinTTL:h.min,ForwardedValues:{QueryString:!0,Headers:u,Cookies:{Forward:"all"}}}),n}static addOriginHeader(n,i,s,o){let c=n.Properties.DistributionConfig.Origins?.find((l)=>l.Id===i);if(c){if(!c.OriginCustomHeaders)c.OriginCustomHeaders=[];c.OriginCustomHeaders.push({HeaderName:s,HeaderValue:o})}return n}static EdgeFunctionTemplates={docsOriginRequest:`
140
140
  'use strict';
141
141
  exports.handler = async (event) => {
142
142
  const request = event.Records[0].cf.request;
@@ -209,7 +209,7 @@ exports.handler = async (event) => {
209
209
 
210
210
  return request;
211
211
  };
212
- `.trim()};static Config={ttl:(n)=>{let{min:i=0,max:s=86400,default:o=86400}=n;return{MinTTL:i,MaxTTL:s,DefaultTTL:o}},cookies:(n,i)=>{let s={Forward:n==="allowList"?"whitelist":n};if(n==="allowList"&&i)s.WhitelistedNames=i;return s},allowedMethods:(n)=>{let i={ALL:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return i[n]||i.GET_HEAD},cachedMethods:(n)=>{let i={GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return i[n]||i.GET_HEAD},ttlPresets:{static:{min:0,max:31536000,default:31536000},dynamic:{min:0,max:0,default:0},api:{min:0,max:3600,default:60},html:{min:0,max:86400,default:86400},images:{min:0,max:604800,default:604800}},cacheBehavior:(n)=>{let{ttl:i={min:0,max:86400,default:86400},cookies:s="none",allowedCookies:o,allowedMethods:c="GET_HEAD",cachedMethods:l="GET_HEAD",compress:u=!0,forwardQueryString:h=!0,forwardHeaders:y=[]}=n;return{MinTTL:i.min,MaxTTL:i.max,DefaultTTL:i.default,Compress:u,AllowedMethods:pe.Config.allowedMethods(c),CachedMethods:pe.Config.cachedMethods(l),ForwardedValues:{QueryString:h,Headers:y,Cookies:pe.Config.cookies(s,o)}}}};static applyConfig(n,i){let s=n.Properties.DistributionConfig.DefaultCacheBehavior;if(i.ttl)s.MinTTL=i.ttl.min,s.MaxTTL=i.ttl.max,s.DefaultTTL=i.ttl.default;if(i.compress!==void 0)s.Compress=i.compress;if(i.allowedMethods)s.AllowedMethods=pe.Config.allowedMethods(i.allowedMethods);if(i.cachedMethods)s.CachedMethods=pe.Config.cachedMethods(i.cachedMethods);if(i.cookies){if(!s.ForwardedValues)s.ForwardedValues={QueryString:!0};s.ForwardedValues.Cookies=pe.Config.cookies(i.cookies,i.allowedCookies)}return n}}var iA=[403,404,500,502,503,504],Pd="TsCloud::StorageFailover",co="AllowCloudFrontFailoverRead",yr=/^[a-z]{2}(?:-gov)?-[a-z]+-\d$/,fr=/^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/;function fg(n){let{failover:i,primaryBucket:s,primaryRegion:o}=n,c=n.where??"storage failover";if(!i||typeof i!=="object")throw Error(`${c}.failover must be an object such as { region: 'us-west-2' }.`);if(!i.region||!yr.test(i.region))throw Error(`${c}.failover.region must be an AWS region such as 'us-west-2', got ${JSON.stringify(i.region)}.`);if(i.region===o)throw Error(`${c}.failover.region is ${i.region}, the same region as the primary bucket. Failover only helps when the replica is in another region.`);let l=i.bucket??`${s}-${i.region}`;if(!fr.test(l)||l.includes("..")){let u=i.bucket===void 0&&l.length>63?` The default name (<primary bucket>-<region>) is ${l.length} characters; S3 allows 63. Set ${c}.failover.bucket.`:"";throw Error(`${c}.failover: "${l}" is not a valid S3 bucket name.${u}`)}if(l===s)throw Error(`${c}.failover.bucket must differ from the primary bucket "${s}".`);return{replicaBucket:l,replicaRegion:i.region,replicate:i.replicate!==!1,statusCodes:Rd(i.statusCodes??iA),primaryConnection:we(i,`${c}.failover`)}}function Ag(n,i){return`${n}.s3.${i}.amazonaws.com`}function yg(n){let i=`arn:aws:s3:::${n.primaryBucket}`,s=`arn:aws:s3:::${n.replicaBucket}`;return{Type:"AWS::IAM::Role",Properties:{...n.roleName?{RoleName:n.roleName}:{},AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"s3.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"failover-replication",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["s3:GetReplicationConfiguration","s3:ListBucket"],Resource:i},{Effect:"Allow",Action:["s3:GetObjectVersionForReplication","s3:GetObjectVersionAcl","s3:GetObjectVersionTagging"],Resource:`${i}/*`},{Effect:"Allow",Action:["s3:ReplicateObject","s3:ReplicateDelete","s3:ReplicateTags"],Resource:`${s}/*`}]}}]}}}function Ig(n){return{Role:n.roleArn,Rules:[{Id:"cloudfront-failover-replica",Status:"Enabled",Priority:1,Filter:{Prefix:""},DeleteMarkerReplication:{Status:"Enabled"},Destination:{Bucket:`arn:aws:s3:::${n.replicaBucket}`}}]}}function Nd(n){return{Sid:co,Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:`arn:aws:s3:::${n.replicaBucket}/*`,Condition:{StringEquals:{"AWS:SourceArn":n.distributionArn}}}}function BI(n){let i=(typeof n==="string"?JSON.parse(n):n)?.Metadata?.[Pd];return Array.isArray(i)?i:[]}class M{static createHostedZone(n){let{domain:i,slug:s,environment:o,comment:c}=n,l=r({slug:s,environment:o,resourceType:"hostedzone"}),u=t(`${l}-${i.replace(/\./g,"")}`);return{zone:{Type:"AWS::Route53::HostedZone",Properties:{Name:i,HostedZoneConfig:{Comment:c||`Hosted zone for ${i}`}}},logicalId:u}}static createRecord(n){let{hostedZoneId:i,hostedZoneName:s,name:o,type:c,ttl:l,values:u,aliasTarget:h}=n,y=t(`record-${o.replace(/\./g,"")}-${c}`),f={Type:"AWS::Route53::RecordSet",Properties:{Name:o,Type:c}};if(i)f.Properties.HostedZoneId=i;else if(s)f.Properties.HostedZoneName=s;if(h)f.Properties.AliasTarget={DNSName:h.dnsName,HostedZoneId:h.hostedZoneId,EvaluateTargetHealth:h.evaluateTargetHealth??!1};else f.Properties.TTL=l||300,f.Properties.ResourceRecords=u||[];return{record:f,logicalId:y}}static createCloudFrontAlias(n,i,s){return M.createRecord({hostedZoneId:s,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:"Z2FDTNDATAQYW2",evaluateTargetHealth:!1}})}static createAlbAlias(n,i,s,o){return M.createRecord({hostedZoneId:o,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:s,evaluateTargetHealth:!0}})}static createCname(n,i,s,o=300){return M.createRecord({hostedZoneId:s,name:n,type:"CNAME",ttl:o,values:[i]})}static createWwwRedirect(n,i){return M.createRecord({hostedZoneId:i,name:`www.${n}`,type:"CNAME",ttl:300,values:[n]})}static createMxRecords(n,i,s,o=300){return M.createRecord({hostedZoneId:s,name:n,type:"MX",ttl:o,values:i.map((c)=>`${c.priority} ${c.server}`)})}static createTxtRecord(n,i,s,o=300){return M.createRecord({hostedZoneId:s,name:n,type:"TXT",ttl:o,values:[`"${i}"`]})}static createSpfRecord(n,i,s){return M.createTxtRecord(n,i,s)}static createDmarcRecord(n,i,s,o){let c=`v=DMARC1; p=${i}; rua=mailto:${s}`;return M.createTxtRecord(`_dmarc.${n}`,c,o)}static createS3WebsiteAlias(n,i,s,o){return M.createRecord({hostedZoneId:o,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:s,evaluateTargetHealth:!1}})}static S3WebsiteHostedZoneIds={"us-east-1":"Z3AQBSTGFYJSTF","us-east-2":"Z2O1EMRO9K5GLX","us-west-1":"Z2F56UZL2M1ACD","us-west-2":"Z3BJ6K6RIION7M","af-south-1":"Z83WF9RJE8B12","ap-east-1":"ZNB98KWMFR0R6","ap-south-1":"Z11RGJOFQNVJUP","ap-south-2":"Z02976202B4EZMXIPMXF7","ap-northeast-1":"Z2M4EHUR26P7ZW","ap-northeast-2":"Z3W03O7B5YMIYP","ap-northeast-3":"Z2YQB5RD63NC85","ap-southeast-1":"Z3O0J2DXBE1FTB","ap-southeast-2":"Z1WCIBER6CPFUU","ap-southeast-3":"Z01613992JD795ZI93075","ca-central-1":"Z1QDHH18159H29","eu-central-1":"Z21DNDUVLTQW6Q","eu-central-2":"Z030506016YDQGETNASS","eu-west-1":"Z1BKCTXD74EZPE","eu-west-2":"Z3GKZC51ZF0DB4","eu-west-3":"Z3R1K369G5AVDG","eu-north-1":"Z3BAZG2TWCNX0D","eu-south-1":"Z30OZKI7KPW7MI","eu-south-2":"Z0081959F7139GRJC19J","me-south-1":"Z1MPMWCPA7YB62","me-central-1":"Z06143092I8HRBER9VXCO","sa-east-1":"Z7KQH4QJS55SO"};static getS3WebsiteEndpoint(n,i){return`${n}.s3-website-${i}.amazonaws.com`}static createStoreRecord(n,i,s){return M.createCname(`store.${n}`,i,s)}static createApiRecord(n,i,s){return M.createCname(`api.${n}`,i,s)}static createDocsRecord(n,i,s){return M.createCname(`docs.${n}`,i,s)}static CloudFrontHostedZoneId="Z2FDTNDATAQYW2"}class S{static createCertificate(n){let{domain:i,subdomains:s=[],slug:o,environment:c,validationMethod:l="DNS",hostedZoneId:u}=n,h=r({slug:o,environment:c,resourceType:"acm"}),y=t(`${h}-${i.replace(/\./g,"")}`),f=[i];for(let C of s)if(C==="*")f.push(`*.${i}`);else f.push(`${C}.${i}`);let b={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:i,SubjectAlternativeNames:f,ValidationMethod:l}};if(l==="DNS"&&u)b.Properties.DomainValidationOptions=f.map((C)=>({DomainName:C,HostedZoneId:u}));return{certificate:b,logicalId:y}}static createKmsKey(n){let{description:i,slug:s,environment:o,enableRotation:c=!0,multiRegion:l=!1}=n,u=r({slug:s,environment:o,resourceType:"kms"}),h=t(u),y={Version:"2012-10-17",Statement:[{Sid:"Enable IAM User Permissions",Effect:"Allow",Principal:{AWS:k.Sub("arn:aws:iam::${AWS::AccountId}:root")},Action:"kms:*",Resource:"*"},{Sid:"Allow services to use the key",Effect:"Allow",Principal:{Service:["s3.amazonaws.com","cloudfront.amazonaws.com","logs.amazonaws.com","secretsmanager.amazonaws.com"]},Action:["kms:Decrypt","kms:GenerateDataKey"],Resource:"*"}]},f={Type:"AWS::KMS::Key",Properties:{Description:i,Enabled:!0,EnableKeyRotation:c,KeyPolicy:y,KeySpec:"SYMMETRIC_DEFAULT",KeyUsage:"ENCRYPT_DECRYPT",MultiRegion:l}},b=t(`${u}-alias`),C={Type:"AWS::KMS::Alias",Properties:{AliasName:`alias/${s}-${o}`,TargetKeyId:k.Ref(h)}};return{key:f,alias:C,logicalId:h,aliasId:b}}static createFirewall(n){let{slug:i,environment:s,scope:o="CLOUDFRONT",defaultAction:c="allow"}=n,l=r({slug:i,environment:s,resourceType:"waf"}),u=t(l);return{webAcl:{Type:"AWS::WAFv2::WebACL",Properties:{Name:l,Scope:o,DefaultAction:c==="allow"?{Allow:{}}:{Block:{}},Description:`WAF for ${i} ${s}`,Rules:[],VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${l}-metric`}}},logicalId:u}}static setRateLimit(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{RateBasedStatement:{Limit:i.requestsPerWindow,AggregateKeyType:i.aggregateKeyType||"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static blockCountries(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{GeoMatchStatement:{CountryCodes:i.countryCodes}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static blockIpAddresses(n,i,s,o){let c=r({slug:s,environment:o,resourceType:"ipset"}),l=t(`${c}-${i.name}`),u={Type:"AWS::WAFv2::IPSet",Properties:{Name:`${c}-${i.name}`,Scope:n.Properties.Scope,IPAddressVersion:i.ipVersion||"IPV4",Addresses:i.ipAddresses,Description:`Blocked IPs for ${i.name}`}};if(!n.Properties.Rules)n.Properties.Rules=[];return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{IPSetReferenceStatement:{Arn:k.GetAtt(l,"Arn")}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),{webAcl:n,ipSet:u,ipSetLogicalId:l}}static addManagedRules(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];let s={ManagedRuleGroupStatement:{VendorName:i.vendorName,Name:i.ruleName}};if(i.excludedRules&&i.excludedRules.length>0)s.ManagedRuleGroupStatement.ExcludedRules=i.excludedRules.map((o)=>({Name:o}));return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:s,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static ManagedRuleGroups={CoreRuleSet:{vendorName:"AWS",ruleName:"AWSManagedRulesCommonRuleSet"},KnownBadInputs:{vendorName:"AWS",ruleName:"AWSManagedRulesKnownBadInputsRuleSet"},SqlDatabase:{vendorName:"AWS",ruleName:"AWSManagedRulesSQLiRuleSet"},LinuxOS:{vendorName:"AWS",ruleName:"AWSManagedRulesLinuxRuleSet"},PosixOS:{vendorName:"AWS",ruleName:"AWSManagedRulesUnixRuleSet"},AmazonIpReputation:{vendorName:"AWS",ruleName:"AWSManagedRulesAmazonIpReputationList"},AnonymousIpList:{vendorName:"AWS",ruleName:"AWSManagedRulesAnonymousIpList"},BotControl:{vendorName:"AWS",ruleName:"AWSManagedRulesBotControlRuleSet"}};static setPathRateLimit(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];let s=i.paths.map((o)=>({SearchString:o,FieldToMatch:{UriPath:{}},TextTransformation:[{Priority:0,Type:"LOWERCASE"}],PositionalConstraint:"STARTS_WITH"}));return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{RateBasedStatement:{Limit:i.requestsPerWindow,AggregateKeyType:i.aggregateKeyType||"IP",ScopeDownStatement:{OrStatement:{Statements:s.map((o)=>({ByteMatchStatement:o}))}}}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static setHeaderRateLimit(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];let s={RateBasedStatement:{Limit:i.requestsPerWindow,AggregateKeyType:"CUSTOM_KEYS",CustomKeys:[{Header:{Name:i.headerName,TextTransformations:[{Priority:0,Type:"NONE"}]}}]}};if(i.headerValue)s.RateBasedStatement.ScopeDownStatement={ByteMatchStatement:{SearchString:i.headerValue,FieldToMatch:{SingleHeader:{Name:i.headerName}},TextTransformation:[{Priority:0,Type:"NONE"}],PositionalConstraint:"EXACTLY"}};return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:s,Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static protectLoginEndpoint(n,i){let{loginPaths:s,priority:o,requestsPerMinute:c=10}=i;return S.setPathRateLimit(n,{name:"LoginRateLimit",priority:o,requestsPerWindow:c*5,paths:s}),n}static protectApiEndpoints(n,i){let{apiPaths:s,priority:o,requestsPerMinute:c=100}=i;return S.setPathRateLimit(n,{name:"ApiRateLimit",priority:o,requestsPerWindow:c*5,paths:s}),n}static createProtectedFirewall(n){let{slug:i,environment:s,scope:o="CLOUDFRONT",enableBotControl:c=!1,enableRateLimiting:l=!0,rateLimitPerMinute:u=2000}=n,{webAcl:h,logicalId:y}=S.createFirewall({slug:i,environment:s,scope:o,defaultAction:"allow"}),f=0;if(h=S.addManagedRules(h,{name:"AWSIPReputationList",priority:f++,...S.ManagedRuleGroups.AmazonIpReputation}),h=S.addManagedRules(h,{name:"AWSAnonymousIPList",priority:f++,...S.ManagedRuleGroups.AnonymousIpList}),h=S.addManagedRules(h,{name:"AWSCoreRuleSet",priority:f++,...S.ManagedRuleGroups.CoreRuleSet}),h=S.addManagedRules(h,{name:"AWSKnownBadInputs",priority:f++,...S.ManagedRuleGroups.KnownBadInputs}),h=S.addManagedRules(h,{name:"AWSSQLi",priority:f++,...S.ManagedRuleGroups.SqlDatabase}),c)h=S.addManagedRules(h,{name:"AWSBotControl",priority:f++,...S.ManagedRuleGroups.BotControl});if(l)h=S.setRateLimit(h,{name:"GlobalRateLimit",priority:f++,requestsPerWindow:u*5});return{webAcl:h,logicalId:y}}static RateLimitPresets={STANDARD:2000,HIGH_TRAFFIC:1e4,STRICT:100,LOGIN:10,API:100}}class a{static createServer(n){let{slug:i,environment:s,instanceType:o="t3.micro",imageId:c="ami-0f3caa1cf4417e51b",keyName:l,securityGroupIds:u,subnetId:h,userData:y,volumeSize:f=20,volumeType:b="gp3",encrypted:C=!0}=n,T=r({slug:i,environment:s,resourceType:"ec2"}),w=t(T),E={Type:"AWS::EC2::Instance",Properties:{ImageId:c,InstanceType:o,Tags:[{Key:"Name",Value:T},{Key:"Environment",Value:s}]}};if(l)E.Properties.KeyName=l;if(u)E.Properties.SecurityGroupIds=u;if(h)E.Properties.SubnetId=h;if(y)E.Properties.UserData=k.Base64(y);return E.Properties.BlockDeviceMappings=[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:f,VolumeType:b,Encrypted:C,DeleteOnTermination:!0}}],{instance:E,logicalId:w}}static createSecurityGroup(n){let{slug:i,environment:s,vpcId:o,description:c,ingress:l=[],egress:u=[]}=n,h=r({slug:i,environment:s,resourceType:"sg"}),y=t(h),f={Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:c||`Security group for ${i} ${s}`,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(o)f.Properties.VpcId=o;if(l.length>0)f.Properties.SecurityGroupIngress=l.map((b)=>({IpProtocol:b.protocol,FromPort:b.fromPort,ToPort:b.toPort,CidrIp:b.cidr,SourceSecurityGroupId:b.sourceSecurityGroupId}));if(u.length>0)f.Properties.SecurityGroupEgress=u.map((b)=>({IpProtocol:b.protocol,FromPort:b.fromPort,ToPort:b.toPort,CidrIp:b.cidr,DestinationSecurityGroupId:b.sourceSecurityGroupId}));return{securityGroup:f,logicalId:y}}static createWebServerSecurityGroup(n,i,s){return a.createSecurityGroup({slug:n,environment:i,vpcId:s,description:"Security group for web servers - HTTP, HTTPS, SSH",ingress:[{protocol:"tcp",fromPort:80,toPort:80,cidr:"0.0.0.0/0"},{protocol:"tcp",fromPort:443,toPort:443,cidr:"0.0.0.0/0"},{protocol:"tcp",fromPort:22,toPort:22,cidr:"0.0.0.0/0"}],egress:[{protocol:"-1",fromPort:0,toPort:0,cidr:"0.0.0.0/0"}]})}static createLoadBalancer(n){let{slug:i,environment:s,scheme:o="internet-facing",subnets:c,securityGroups:l,type:u="application"}=n,h=r({slug:i,environment:s,resourceType:"alb"}),y=t(h),f={Type:"AWS::ElasticLoadBalancingV2::LoadBalancer",Properties:{Name:h,Scheme:o,Type:u,Subnets:c,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(l)f.Properties.SecurityGroups=l;return{loadBalancer:f,logicalId:y}}static createTargetGroup(n){let{slug:i,environment:s,port:o,protocol:c="HTTP",vpcId:l,targetType:u="ip",healthCheckPath:h="/",healthCheckInterval:y=30,healthCheckTimeout:f=5,healthyThreshold:b=2,unhealthyThreshold:C=3}=n,T=r({slug:i,environment:s,resourceType:"tg"}),w=t(T);return{targetGroup:{Type:"AWS::ElasticLoadBalancingV2::TargetGroup",Properties:{Name:T,Port:o,Protocol:c,VpcId:l,TargetType:u,HealthCheckEnabled:!0,HealthCheckProtocol:c,HealthCheckPath:h,HealthCheckIntervalSeconds:y,HealthCheckTimeoutSeconds:f,HealthyThresholdCount:b,UnhealthyThresholdCount:C,Tags:[{Key:"Name",Value:T},{Key:"Environment",Value:s}]}},logicalId:w}}static createListener(n,i){let{port:s,protocol:o="HTTP",certificateArn:c,defaultTargetGroupArn:l}=i,u=t(`listener-${n}-${s}`),h={Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:k.Ref(n),Port:s,Protocol:o,DefaultActions:[{Type:"forward",TargetGroupArn:l}]}};if(o==="HTTPS"&&c)h.Properties.Certificates=[{CertificateArn:c}],h.Properties.SslPolicy="ELBSecurityPolicy-TLS13-1-2-2021-06";return{listener:h,logicalId:u}}static createEcsCluster(n,i){let s=r({slug:n,environment:i,resourceType:"ecs-cluster"}),o=t(s);return{cluster:{Type:"AWS::ECS::Cluster",Properties:{ClusterName:s,Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:i}]}},logicalId:o}}static createFargateService(n){let{slug:i,environment:s,image:o,cpu:c="256",memory:l="512",desiredCount:u=1,containerPort:h=8080,environmentVariables:y={},secrets:f=[],healthCheck:b,logGroup:C,subnets:T,securityGroups:w,targetGroupArn:E}=n,{cluster:I,logicalId:N}=a.createEcsCluster(i,s),D=r({slug:i,environment:s,resourceType:"fargate"}),B=t(`${D}-execution-role`),R={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"]}},W=t(`${D}-task-role`),_={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]}}},j=t(`${D}-task`),J={Type:"AWS::ECS::TaskDefinition",Properties:{Family:D,TaskRoleArn:k.GetAtt(W,"Arn"),ExecutionRoleArn:k.GetAtt(B,"Arn"),NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:c,Memory:l,ContainerDefinitions:[{Name:i,Image:o,Essential:!0,PortMappings:[{ContainerPort:h,Protocol:"tcp"}],Environment:Object.entries(y).map(([X,ne])=>({Name:X,Value:ne})),Secrets:f.map((X)=>({Name:X.name,ValueFrom:X.valueFrom}))}],Tags:[{Key:"Name",Value:D},{Key:"Environment",Value:s}]}};if(b)J.Properties.ContainerDefinitions[0].HealthCheck={Command:b.command,Interval:b.interval||30,Timeout:b.timeout||5,Retries:b.retries||3,StartPeriod:60};if(C)J.Properties.ContainerDefinitions[0].LogConfiguration={LogDriver:"awslogs",Options:{"awslogs-group":C,"awslogs-region":k.Ref("AWS::Region"),"awslogs-stream-prefix":i}};let K=t(`${D}-service`),Y={Type:"AWS::ECS::Service",Properties:{ServiceName:D,Cluster:k.Ref(N),TaskDefinition:k.Ref(j),DesiredCount:u,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{Subnets:T,SecurityGroups:w,AssignPublicIp:"ENABLED"}},Tags:[{Key:"Name",Value:D},{Key:"Environment",Value:s}]}};if(E)Y.Properties.LoadBalancers=[{TargetGroupArn:E,ContainerName:i,ContainerPort:h}];return{cluster:I,taskDefinition:J,service:Y,taskRole:_,executionRole:R,clusterLogicalId:N,taskDefinitionLogicalId:j,serviceLogicalId:K,taskRoleLogicalId:W,executionRoleLogicalId:B}}static createLambdaFunction(n){let{slug:i,environment:s,runtime:o,handler:c,code:l,timeout:u=30,memorySize:h=128,environmentVariables:y={},vpcConfig:f}=n,b=r({slug:i,environment:s,resourceType:"lambda"}),C=t(b),T=t(`${b}-role`),w={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]}};if(f)w.Properties.ManagedPolicyArns.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");let E={Type:"AWS::Lambda::Function",Properties:{FunctionName:b,Runtime:o,Role:k.GetAtt(T,"Arn"),Handler:c,Code:{...l.s3Bucket&&{S3Bucket:l.s3Bucket},...l.s3Key&&{S3Key:l.s3Key},...l.zipFile&&{ZipFile:l.zipFile}},Timeout:u,MemorySize:h,Tags:[{Key:"Name",Value:b},{Key:"Environment",Value:s}]}};if(Object.keys(y).length>0)E.Properties.Environment={Variables:y};if(f)E.Properties.VpcConfig={SecurityGroupIds:f.securityGroupIds,SubnetIds:f.subnetIds};return{lambdaFunction:E,role:w,logicalId:C,roleLogicalId:T}}static generateNodeServerUserData(n={}){let{nodeVersion:i="20",appRepo:s,environment:o={}}=n,c=Object.entries(o).map(([l,u])=>`echo "export ${l}='${u}'" >> /etc/environment`).join(`
212
+ `.trim()};static Config={ttl:(n)=>{let{min:i=0,max:s=86400,default:o=86400}=n;return{MinTTL:i,MaxTTL:s,DefaultTTL:o}},cookies:(n,i)=>{let s={Forward:n==="allowList"?"whitelist":n};if(n==="allowList"&&i)s.WhitelistedNames=i;return s},allowedMethods:(n)=>{let i={ALL:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return i[n]||i.GET_HEAD},cachedMethods:(n)=>{let i={GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return i[n]||i.GET_HEAD},ttlPresets:{static:{min:0,max:31536000,default:31536000},dynamic:{min:0,max:0,default:0},api:{min:0,max:3600,default:60},html:{min:0,max:86400,default:86400},images:{min:0,max:604800,default:604800}},cacheBehavior:(n)=>{let{ttl:i={min:0,max:86400,default:86400},cookies:s="none",allowedCookies:o,allowedMethods:c="GET_HEAD",cachedMethods:l="GET_HEAD",compress:u=!0,forwardQueryString:h=!0,forwardHeaders:y=[]}=n;return{MinTTL:i.min,MaxTTL:i.max,DefaultTTL:i.default,Compress:u,AllowedMethods:me.Config.allowedMethods(c),CachedMethods:me.Config.cachedMethods(l),ForwardedValues:{QueryString:h,Headers:y,Cookies:me.Config.cookies(s,o)}}}};static applyConfig(n,i){let s=n.Properties.DistributionConfig.DefaultCacheBehavior;if(i.ttl)s.MinTTL=i.ttl.min,s.MaxTTL=i.ttl.max,s.DefaultTTL=i.ttl.default;if(i.compress!==void 0)s.Compress=i.compress;if(i.allowedMethods)s.AllowedMethods=me.Config.allowedMethods(i.allowedMethods);if(i.cachedMethods)s.CachedMethods=me.Config.cachedMethods(i.cachedMethods);if(i.cookies){if(!s.ForwardedValues)s.ForwardedValues={QueryString:!0};s.ForwardedValues.Cookies=me.Config.cookies(i.cookies,i.allowedCookies)}return n}}var oA=[403,404,500,502,503,504],kd="TsCloud::StorageFailover",uo="AllowCloudFrontFailoverRead",yr=/^[a-z]{2}(?:-gov)?-[a-z]+-\d$/,fr=/^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/;function yg(n){let{failover:i,primaryBucket:s,primaryRegion:o}=n,c=n.where??"storage failover";if(!i||typeof i!=="object")throw Error(`${c}.failover must be an object such as { region: 'us-west-2' }.`);if(!i.region||!yr.test(i.region))throw Error(`${c}.failover.region must be an AWS region such as 'us-west-2', got ${JSON.stringify(i.region)}.`);if(i.region===o)throw Error(`${c}.failover.region is ${i.region}, the same region as the primary bucket. Failover only helps when the replica is in another region.`);let l=i.bucket??`${s}-${i.region}`;if(!fr.test(l)||l.includes("..")){let u=i.bucket===void 0&&l.length>63?` The default name (<primary bucket>-<region>) is ${l.length} characters; S3 allows 63. Set ${c}.failover.bucket.`:"";throw Error(`${c}.failover: "${l}" is not a valid S3 bucket name.${u}`)}if(l===s)throw Error(`${c}.failover.bucket must differ from the primary bucket "${s}".`);return{replicaBucket:l,replicaRegion:i.region,replicate:i.replicate!==!1,statusCodes:Pd(i.statusCodes??oA),primaryConnection:De(i,`${c}.failover`)}}function Ig(n,i){return`${n}.s3.${i}.amazonaws.com`}function Sg(n){let i=`arn:aws:s3:::${n.primaryBucket}`,s=`arn:aws:s3:::${n.replicaBucket}`;return{Type:"AWS::IAM::Role",Properties:{...n.roleName?{RoleName:n.roleName}:{},AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"s3.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"failover-replication",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["s3:GetReplicationConfiguration","s3:ListBucket"],Resource:i},{Effect:"Allow",Action:["s3:GetObjectVersionForReplication","s3:GetObjectVersionAcl","s3:GetObjectVersionTagging"],Resource:`${i}/*`},{Effect:"Allow",Action:["s3:ReplicateObject","s3:ReplicateDelete","s3:ReplicateTags"],Resource:`${s}/*`}]}}]}}}function Cg(n){return{Role:n.roleArn,Rules:[{Id:"cloudfront-failover-replica",Status:"Enabled",Priority:1,Filter:{Prefix:""},DeleteMarkerReplication:{Status:"Enabled"},Destination:{Bucket:`arn:aws:s3:::${n.replicaBucket}`}}]}}function Bd(n){return{Sid:uo,Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:`arn:aws:s3:::${n.replicaBucket}/*`,Condition:{StringEquals:{"AWS:SourceArn":n.distributionArn}}}}function xI(n){let i=(typeof n==="string"?JSON.parse(n):n)?.Metadata?.[kd];return Array.isArray(i)?i:[]}class F{static createHostedZone(n){let{domain:i,slug:s,environment:o,comment:c}=n,l=r({slug:s,environment:o,resourceType:"hostedzone"}),u=t(`${l}-${i.replace(/\./g,"")}`);return{zone:{Type:"AWS::Route53::HostedZone",Properties:{Name:i,HostedZoneConfig:{Comment:c||`Hosted zone for ${i}`}}},logicalId:u}}static createRecord(n){let{hostedZoneId:i,hostedZoneName:s,name:o,type:c,ttl:l,values:u,aliasTarget:h}=n,y=t(`record-${o.replace(/\./g,"")}-${c}`),f={Type:"AWS::Route53::RecordSet",Properties:{Name:o,Type:c}};if(i)f.Properties.HostedZoneId=i;else if(s)f.Properties.HostedZoneName=s;if(h)f.Properties.AliasTarget={DNSName:h.dnsName,HostedZoneId:h.hostedZoneId,EvaluateTargetHealth:h.evaluateTargetHealth??!1};else f.Properties.TTL=l||300,f.Properties.ResourceRecords=u||[];return{record:f,logicalId:y}}static createCloudFrontAlias(n,i,s){return F.createRecord({hostedZoneId:s,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:"Z2FDTNDATAQYW2",evaluateTargetHealth:!1}})}static createAlbAlias(n,i,s,o){return F.createRecord({hostedZoneId:o,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:s,evaluateTargetHealth:!0}})}static createCname(n,i,s,o=300){return F.createRecord({hostedZoneId:s,name:n,type:"CNAME",ttl:o,values:[i]})}static createWwwRedirect(n,i){return F.createRecord({hostedZoneId:i,name:`www.${n}`,type:"CNAME",ttl:300,values:[n]})}static createMxRecords(n,i,s,o=300){return F.createRecord({hostedZoneId:s,name:n,type:"MX",ttl:o,values:i.map((c)=>`${c.priority} ${c.server}`)})}static createTxtRecord(n,i,s,o=300){return F.createRecord({hostedZoneId:s,name:n,type:"TXT",ttl:o,values:[`"${i}"`]})}static createSpfRecord(n,i,s){return F.createTxtRecord(n,i,s)}static createDmarcRecord(n,i,s,o){let c=`v=DMARC1; p=${i}; rua=mailto:${s}`;return F.createTxtRecord(`_dmarc.${n}`,c,o)}static createS3WebsiteAlias(n,i,s,o){return F.createRecord({hostedZoneId:o,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:s,evaluateTargetHealth:!1}})}static S3WebsiteHostedZoneIds={"us-east-1":"Z3AQBSTGFYJSTF","us-east-2":"Z2O1EMRO9K5GLX","us-west-1":"Z2F56UZL2M1ACD","us-west-2":"Z3BJ6K6RIION7M","af-south-1":"Z83WF9RJE8B12","ap-east-1":"ZNB98KWMFR0R6","ap-south-1":"Z11RGJOFQNVJUP","ap-south-2":"Z02976202B4EZMXIPMXF7","ap-northeast-1":"Z2M4EHUR26P7ZW","ap-northeast-2":"Z3W03O7B5YMIYP","ap-northeast-3":"Z2YQB5RD63NC85","ap-southeast-1":"Z3O0J2DXBE1FTB","ap-southeast-2":"Z1WCIBER6CPFUU","ap-southeast-3":"Z01613992JD795ZI93075","ca-central-1":"Z1QDHH18159H29","eu-central-1":"Z21DNDUVLTQW6Q","eu-central-2":"Z030506016YDQGETNASS","eu-west-1":"Z1BKCTXD74EZPE","eu-west-2":"Z3GKZC51ZF0DB4","eu-west-3":"Z3R1K369G5AVDG","eu-north-1":"Z3BAZG2TWCNX0D","eu-south-1":"Z30OZKI7KPW7MI","eu-south-2":"Z0081959F7139GRJC19J","me-south-1":"Z1MPMWCPA7YB62","me-central-1":"Z06143092I8HRBER9VXCO","sa-east-1":"Z7KQH4QJS55SO"};static getS3WebsiteEndpoint(n,i){return`${n}.s3-website-${i}.amazonaws.com`}static createStoreRecord(n,i,s){return F.createCname(`store.${n}`,i,s)}static createApiRecord(n,i,s){return F.createCname(`api.${n}`,i,s)}static createDocsRecord(n,i,s){return F.createCname(`docs.${n}`,i,s)}static CloudFrontHostedZoneId="Z2FDTNDATAQYW2"}class S{static createCertificate(n){let{domain:i,subdomains:s=[],slug:o,environment:c,validationMethod:l="DNS",hostedZoneId:u}=n,h=r({slug:o,environment:c,resourceType:"acm"}),y=t(`${h}-${i.replace(/\./g,"")}`),f=[i];for(let C of s)if(C==="*")f.push(`*.${i}`);else f.push(`${C}.${i}`);let b={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:i,SubjectAlternativeNames:f,ValidationMethod:l}};if(l==="DNS"&&u)b.Properties.DomainValidationOptions=f.map((C)=>({DomainName:C,HostedZoneId:u}));return{certificate:b,logicalId:y}}static createKmsKey(n){let{description:i,slug:s,environment:o,enableRotation:c=!0,multiRegion:l=!1}=n,u=r({slug:s,environment:o,resourceType:"kms"}),h=t(u),y={Version:"2012-10-17",Statement:[{Sid:"Enable IAM User Permissions",Effect:"Allow",Principal:{AWS:k.Sub("arn:aws:iam::${AWS::AccountId}:root")},Action:"kms:*",Resource:"*"},{Sid:"Allow services to use the key",Effect:"Allow",Principal:{Service:["s3.amazonaws.com","cloudfront.amazonaws.com","logs.amazonaws.com","secretsmanager.amazonaws.com"]},Action:["kms:Decrypt","kms:GenerateDataKey"],Resource:"*"}]},f={Type:"AWS::KMS::Key",Properties:{Description:i,Enabled:!0,EnableKeyRotation:c,KeyPolicy:y,KeySpec:"SYMMETRIC_DEFAULT",KeyUsage:"ENCRYPT_DECRYPT",MultiRegion:l}},b=t(`${u}-alias`),C={Type:"AWS::KMS::Alias",Properties:{AliasName:`alias/${s}-${o}`,TargetKeyId:k.Ref(h)}};return{key:f,alias:C,logicalId:h,aliasId:b}}static createFirewall(n){let{slug:i,environment:s,scope:o="CLOUDFRONT",defaultAction:c="allow"}=n,l=r({slug:i,environment:s,resourceType:"waf"}),u=t(l);return{webAcl:{Type:"AWS::WAFv2::WebACL",Properties:{Name:l,Scope:o,DefaultAction:c==="allow"?{Allow:{}}:{Block:{}},Description:`WAF for ${i} ${s}`,Rules:[],VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${l}-metric`}}},logicalId:u}}static setRateLimit(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{RateBasedStatement:{Limit:i.requestsPerWindow,AggregateKeyType:i.aggregateKeyType||"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static blockCountries(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{GeoMatchStatement:{CountryCodes:i.countryCodes}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static blockIpAddresses(n,i,s,o){let c=r({slug:s,environment:o,resourceType:"ipset"}),l=t(`${c}-${i.name}`),u={Type:"AWS::WAFv2::IPSet",Properties:{Name:`${c}-${i.name}`,Scope:n.Properties.Scope,IPAddressVersion:i.ipVersion||"IPV4",Addresses:i.ipAddresses,Description:`Blocked IPs for ${i.name}`}};if(!n.Properties.Rules)n.Properties.Rules=[];return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{IPSetReferenceStatement:{Arn:k.GetAtt(l,"Arn")}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),{webAcl:n,ipSet:u,ipSetLogicalId:l}}static addManagedRules(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];let s={ManagedRuleGroupStatement:{VendorName:i.vendorName,Name:i.ruleName}};if(i.excludedRules&&i.excludedRules.length>0)s.ManagedRuleGroupStatement.ExcludedRules=i.excludedRules.map((o)=>({Name:o}));return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:s,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static ManagedRuleGroups={CoreRuleSet:{vendorName:"AWS",ruleName:"AWSManagedRulesCommonRuleSet"},KnownBadInputs:{vendorName:"AWS",ruleName:"AWSManagedRulesKnownBadInputsRuleSet"},SqlDatabase:{vendorName:"AWS",ruleName:"AWSManagedRulesSQLiRuleSet"},LinuxOS:{vendorName:"AWS",ruleName:"AWSManagedRulesLinuxRuleSet"},PosixOS:{vendorName:"AWS",ruleName:"AWSManagedRulesUnixRuleSet"},AmazonIpReputation:{vendorName:"AWS",ruleName:"AWSManagedRulesAmazonIpReputationList"},AnonymousIpList:{vendorName:"AWS",ruleName:"AWSManagedRulesAnonymousIpList"},BotControl:{vendorName:"AWS",ruleName:"AWSManagedRulesBotControlRuleSet"}};static setPathRateLimit(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];let s=i.paths.map((o)=>({SearchString:o,FieldToMatch:{UriPath:{}},TextTransformation:[{Priority:0,Type:"LOWERCASE"}],PositionalConstraint:"STARTS_WITH"}));return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{RateBasedStatement:{Limit:i.requestsPerWindow,AggregateKeyType:i.aggregateKeyType||"IP",ScopeDownStatement:{OrStatement:{Statements:s.map((o)=>({ByteMatchStatement:o}))}}}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static setHeaderRateLimit(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];let s={RateBasedStatement:{Limit:i.requestsPerWindow,AggregateKeyType:"CUSTOM_KEYS",CustomKeys:[{Header:{Name:i.headerName,TextTransformations:[{Priority:0,Type:"NONE"}]}}]}};if(i.headerValue)s.RateBasedStatement.ScopeDownStatement={ByteMatchStatement:{SearchString:i.headerValue,FieldToMatch:{SingleHeader:{Name:i.headerName}},TextTransformation:[{Priority:0,Type:"NONE"}],PositionalConstraint:"EXACTLY"}};return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:s,Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static protectLoginEndpoint(n,i){let{loginPaths:s,priority:o,requestsPerMinute:c=10}=i;return S.setPathRateLimit(n,{name:"LoginRateLimit",priority:o,requestsPerWindow:c*5,paths:s}),n}static protectApiEndpoints(n,i){let{apiPaths:s,priority:o,requestsPerMinute:c=100}=i;return S.setPathRateLimit(n,{name:"ApiRateLimit",priority:o,requestsPerWindow:c*5,paths:s}),n}static createProtectedFirewall(n){let{slug:i,environment:s,scope:o="CLOUDFRONT",enableBotControl:c=!1,enableRateLimiting:l=!0,rateLimitPerMinute:u=2000}=n,{webAcl:h,logicalId:y}=S.createFirewall({slug:i,environment:s,scope:o,defaultAction:"allow"}),f=0;if(h=S.addManagedRules(h,{name:"AWSIPReputationList",priority:f++,...S.ManagedRuleGroups.AmazonIpReputation}),h=S.addManagedRules(h,{name:"AWSAnonymousIPList",priority:f++,...S.ManagedRuleGroups.AnonymousIpList}),h=S.addManagedRules(h,{name:"AWSCoreRuleSet",priority:f++,...S.ManagedRuleGroups.CoreRuleSet}),h=S.addManagedRules(h,{name:"AWSKnownBadInputs",priority:f++,...S.ManagedRuleGroups.KnownBadInputs}),h=S.addManagedRules(h,{name:"AWSSQLi",priority:f++,...S.ManagedRuleGroups.SqlDatabase}),c)h=S.addManagedRules(h,{name:"AWSBotControl",priority:f++,...S.ManagedRuleGroups.BotControl});if(l)h=S.setRateLimit(h,{name:"GlobalRateLimit",priority:f++,requestsPerWindow:u*5});return{webAcl:h,logicalId:y}}static RateLimitPresets={STANDARD:2000,HIGH_TRAFFIC:1e4,STRICT:100,LOGIN:10,API:100}}class a{static createServer(n){let{slug:i,environment:s,instanceType:o="t3.micro",imageId:c="ami-0f3caa1cf4417e51b",keyName:l,securityGroupIds:u,subnetId:h,userData:y,volumeSize:f=20,volumeType:b="gp3",encrypted:C=!0}=n,T=r({slug:i,environment:s,resourceType:"ec2"}),w=t(T),E={Type:"AWS::EC2::Instance",Properties:{ImageId:c,InstanceType:o,Tags:[{Key:"Name",Value:T},{Key:"Environment",Value:s}]}};if(l)E.Properties.KeyName=l;if(u)E.Properties.SecurityGroupIds=u;if(h)E.Properties.SubnetId=h;if(y)E.Properties.UserData=k.Base64(y);return E.Properties.BlockDeviceMappings=[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:f,VolumeType:b,Encrypted:C,DeleteOnTermination:!0}}],{instance:E,logicalId:w}}static createSecurityGroup(n){let{slug:i,environment:s,vpcId:o,description:c,ingress:l=[],egress:u=[]}=n,h=r({slug:i,environment:s,resourceType:"sg"}),y=t(h),f={Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:c||`Security group for ${i} ${s}`,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(o)f.Properties.VpcId=o;if(l.length>0)f.Properties.SecurityGroupIngress=l.map((b)=>({IpProtocol:b.protocol,FromPort:b.fromPort,ToPort:b.toPort,CidrIp:b.cidr,SourceSecurityGroupId:b.sourceSecurityGroupId}));if(u.length>0)f.Properties.SecurityGroupEgress=u.map((b)=>({IpProtocol:b.protocol,FromPort:b.fromPort,ToPort:b.toPort,CidrIp:b.cidr,DestinationSecurityGroupId:b.sourceSecurityGroupId}));return{securityGroup:f,logicalId:y}}static createWebServerSecurityGroup(n,i,s){return a.createSecurityGroup({slug:n,environment:i,vpcId:s,description:"Security group for web servers - HTTP, HTTPS, SSH",ingress:[{protocol:"tcp",fromPort:80,toPort:80,cidr:"0.0.0.0/0"},{protocol:"tcp",fromPort:443,toPort:443,cidr:"0.0.0.0/0"},{protocol:"tcp",fromPort:22,toPort:22,cidr:"0.0.0.0/0"}],egress:[{protocol:"-1",fromPort:0,toPort:0,cidr:"0.0.0.0/0"}]})}static createLoadBalancer(n){let{slug:i,environment:s,scheme:o="internet-facing",subnets:c,securityGroups:l,type:u="application"}=n,h=r({slug:i,environment:s,resourceType:"alb"}),y=t(h),f={Type:"AWS::ElasticLoadBalancingV2::LoadBalancer",Properties:{Name:h,Scheme:o,Type:u,Subnets:c,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(l)f.Properties.SecurityGroups=l;return{loadBalancer:f,logicalId:y}}static createTargetGroup(n){let{slug:i,environment:s,port:o,protocol:c="HTTP",vpcId:l,targetType:u="ip",healthCheckPath:h="/",healthCheckInterval:y=30,healthCheckTimeout:f=5,healthyThreshold:b=2,unhealthyThreshold:C=3}=n,T=r({slug:i,environment:s,resourceType:"tg"}),w=t(T);return{targetGroup:{Type:"AWS::ElasticLoadBalancingV2::TargetGroup",Properties:{Name:T,Port:o,Protocol:c,VpcId:l,TargetType:u,HealthCheckEnabled:!0,HealthCheckProtocol:c,HealthCheckPath:h,HealthCheckIntervalSeconds:y,HealthCheckTimeoutSeconds:f,HealthyThresholdCount:b,UnhealthyThresholdCount:C,Tags:[{Key:"Name",Value:T},{Key:"Environment",Value:s}]}},logicalId:w}}static createListener(n,i){let{port:s,protocol:o="HTTP",certificateArn:c,defaultTargetGroupArn:l}=i,u=t(`listener-${n}-${s}`),h={Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:k.Ref(n),Port:s,Protocol:o,DefaultActions:[{Type:"forward",TargetGroupArn:l}]}};if(o==="HTTPS"&&c)h.Properties.Certificates=[{CertificateArn:c}],h.Properties.SslPolicy="ELBSecurityPolicy-TLS13-1-2-2021-06";return{listener:h,logicalId:u}}static createEcsCluster(n,i){let s=r({slug:n,environment:i,resourceType:"ecs-cluster"}),o=t(s);return{cluster:{Type:"AWS::ECS::Cluster",Properties:{ClusterName:s,Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:i}]}},logicalId:o}}static createFargateService(n){let{slug:i,environment:s,image:o,cpu:c="256",memory:l="512",desiredCount:u=1,containerPort:h=8080,environmentVariables:y={},secrets:f=[],healthCheck:b,logGroup:C,subnets:T,securityGroups:w,targetGroupArn:E}=n,{cluster:I,logicalId:N}=a.createEcsCluster(i,s),D=r({slug:i,environment:s,resourceType:"fargate"}),x=t(`${D}-execution-role`),R={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"]}},_=t(`${D}-task-role`),B={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]}}},W=t(`${D}-task`),J={Type:"AWS::ECS::TaskDefinition",Properties:{Family:D,TaskRoleArn:k.GetAtt(_,"Arn"),ExecutionRoleArn:k.GetAtt(x,"Arn"),NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:c,Memory:l,ContainerDefinitions:[{Name:i,Image:o,Essential:!0,PortMappings:[{ContainerPort:h,Protocol:"tcp"}],Environment:Object.entries(y).map(([Z,ne])=>({Name:Z,Value:ne})),Secrets:f.map((Z)=>({Name:Z.name,ValueFrom:Z.valueFrom}))}],Tags:[{Key:"Name",Value:D},{Key:"Environment",Value:s}]}};if(b)J.Properties.ContainerDefinitions[0].HealthCheck={Command:b.command,Interval:b.interval||30,Timeout:b.timeout||5,Retries:b.retries||3,StartPeriod:60};if(C)J.Properties.ContainerDefinitions[0].LogConfiguration={LogDriver:"awslogs",Options:{"awslogs-group":C,"awslogs-region":k.Ref("AWS::Region"),"awslogs-stream-prefix":i}};let K=t(`${D}-service`),Y={Type:"AWS::ECS::Service",Properties:{ServiceName:D,Cluster:k.Ref(N),TaskDefinition:k.Ref(W),DesiredCount:u,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{Subnets:T,SecurityGroups:w,AssignPublicIp:"ENABLED"}},Tags:[{Key:"Name",Value:D},{Key:"Environment",Value:s}]}};if(E)Y.Properties.LoadBalancers=[{TargetGroupArn:E,ContainerName:i,ContainerPort:h}];return{cluster:I,taskDefinition:J,service:Y,taskRole:B,executionRole:R,clusterLogicalId:N,taskDefinitionLogicalId:W,serviceLogicalId:K,taskRoleLogicalId:_,executionRoleLogicalId:x}}static createLambdaFunction(n){let{slug:i,environment:s,runtime:o,handler:c,code:l,timeout:u=30,memorySize:h=128,environmentVariables:y={},vpcConfig:f}=n,b=r({slug:i,environment:s,resourceType:"lambda"}),C=t(b),T=t(`${b}-role`),w={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]}};if(f)w.Properties.ManagedPolicyArns.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");let E={Type:"AWS::Lambda::Function",Properties:{FunctionName:b,Runtime:o,Role:k.GetAtt(T,"Arn"),Handler:c,Code:{...l.s3Bucket&&{S3Bucket:l.s3Bucket},...l.s3Key&&{S3Key:l.s3Key},...l.zipFile&&{ZipFile:l.zipFile}},Timeout:u,MemorySize:h,Tags:[{Key:"Name",Value:b},{Key:"Environment",Value:s}]}};if(Object.keys(y).length>0)E.Properties.Environment={Variables:y};if(f)E.Properties.VpcConfig={SecurityGroupIds:f.securityGroupIds,SubnetIds:f.subnetIds};return{lambdaFunction:E,role:w,logicalId:C,roleLogicalId:T}}static generateNodeServerUserData(n={}){let{nodeVersion:i="20",appRepo:s,environment:o={}}=n,c=Object.entries(o).map(([l,u])=>`echo "export ${l}='${u}'" >> /etc/environment`).join(`
213
213
  `);return`#!/bin/bash
214
214
  # Update system
215
215
  yum update -y
@@ -310,15 +310,15 @@ systemctl enable caddy
310
310
  systemctl start caddy
311
311
 
312
312
  echo "Bun server setup complete!"
313
- `}static createLaunchConfiguration(n){let{slug:i,environment:s,imageId:o,instanceType:c,keyName:l,securityGroups:u,userData:h,volumeSize:y=20,volumeType:f="gp3",encrypted:b=!0,iamInstanceProfile:C}=n,T=r({slug:i,environment:s,resourceType:"launch-config"}),w=t(T),E={Type:"AWS::AutoScaling::LaunchConfiguration",Properties:{ImageId:o,InstanceType:c,BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:y,VolumeType:f,Encrypted:b,DeleteOnTermination:!0}}]}};if(l)E.Properties.KeyName=l;if(u)E.Properties.SecurityGroups=u;if(h)E.Properties.UserData=k.Base64(h);if(C)E.Properties.IamInstanceProfile=C;return{launchConfiguration:E,logicalId:w}}static createAutoScalingGroup(n){let{slug:i,environment:s,launchConfigurationName:o,minSize:c,maxSize:l,desiredCapacity:u,vpcZoneIdentifier:h,targetGroupArns:y,healthCheckType:f="EC2",healthCheckGracePeriod:b=300,cooldown:C=300,tags:T={}}=n,w=r({slug:i,environment:s,resourceType:"asg"}),E=t(w),I={Type:"AWS::AutoScaling::AutoScalingGroup",Properties:{AutoScalingGroupName:w,LaunchConfigurationName:o,MinSize:c,MaxSize:l,HealthCheckType:f,HealthCheckGracePeriod:b,Cooldown:C,Tags:[{Key:"Name",Value:w,PropagateAtLaunch:!0},{Key:"Environment",Value:s,PropagateAtLaunch:!0},...Object.entries(T).map(([N,D])=>({Key:N,Value:D,PropagateAtLaunch:!0}))]}};if(u!==void 0)I.Properties.DesiredCapacity=u;if(h)I.Properties.VPCZoneIdentifier=h;if(y)I.Properties.TargetGroupARNs=y;return I.UpdatePolicy={AutoScalingRollingUpdate:{MaxBatchSize:1,MinInstancesInService:Math.max(0,c-1),PauseTime:"PT5M",WaitOnResourceSignals:!1}},{autoScalingGroup:I,logicalId:E}}static createScalingPolicy(n){let{slug:i,environment:s,autoScalingGroupName:o,policyType:c="TargetTrackingScaling",targetValue:l=70,predefinedMetricType:u="ASGAverageCPUUtilization"}=n,h=r({slug:i,environment:s,resourceType:"scaling-policy"}),y=t(h),f={Type:"AWS::AutoScaling::ScalingPolicy",Properties:{AutoScalingGroupName:o,PolicyType:c}};if(c==="TargetTrackingScaling")f.Properties.TargetTrackingConfiguration={PredefinedMetricSpecification:{PredefinedMetricType:u},TargetValue:l};return{scalingPolicy:f,logicalId:y}}static AutoScaling={smallWebServer:(n,i,s,o,c)=>a.createAutoScalingGroup({slug:n,environment:i,launchConfigurationName:s,minSize:2,maxSize:4,desiredCapacity:2,vpcZoneIdentifier:o,targetGroupArns:c,healthCheckType:c?"ELB":"EC2",healthCheckGracePeriod:300}),mediumWebServer:(n,i,s,o,c)=>a.createAutoScalingGroup({slug:n,environment:i,launchConfigurationName:s,minSize:3,maxSize:10,desiredCapacity:3,vpcZoneIdentifier:o,targetGroupArns:c,healthCheckType:c?"ELB":"EC2",healthCheckGracePeriod:300}),largeWebServer:(n,i,s,o,c)=>a.createAutoScalingGroup({slug:n,environment:i,launchConfigurationName:s,minSize:5,maxSize:20,desiredCapacity:5,vpcZoneIdentifier:o,targetGroupArns:c,healthCheckType:c?"ELB":"EC2",healthCheckGracePeriod:300}),cpuScaling:(n,i,s,o=70)=>a.createScalingPolicy({slug:n,environment:i,autoScalingGroupName:s,policyType:"TargetTrackingScaling",predefinedMetricType:"ASGAverageCPUUtilization",targetValue:o}),requestCountScaling:(n,i,s,o=1000)=>a.createScalingPolicy({slug:n,environment:i,autoScalingGroupName:s,policyType:"TargetTrackingScaling",predefinedMetricType:"ALBRequestCountPerTarget",targetValue:o})};static Secrets={fromSecretsManager:(n)=>Object.entries(n).map(([i,s])=>({name:i,valueFrom:s})),fromJsonSecret:(n,i)=>`${n}:${i}::`,fromSecretVersion:(n,i)=>`${n}::${i}:`,fromSecretVersionStage:(n,i)=>`${n}:::${i}`,createAccessPolicy:(n)=>({PolicyName:"SecretsManagerAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],Resource:n}]}}),createKmsPolicy:(n)=>({PolicyName:"KMSDecryptAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["kms:Decrypt"],Resource:n}]}}),buildSecretArn:(n)=>`arn:aws:secretsmanager:${n.region}:${n.accountId}:secret:${n.secretName}`,buildSecretArnPattern:(n)=>{let i=n.region||"*",s=n.accountId||"*";return`arn:aws:secretsmanager:${i}:${s}:secret:${n.secretNamePrefix}*`},commonAppSecrets:(n)=>({DATABASE_URL:`${n}/database-url`,DATABASE_PASSWORD:`${n}/database-password`,REDIS_URL:`${n}/redis-url`,REDIS_PASSWORD:`${n}/redis-password`,API_KEY:`${n}/api-key`,JWT_SECRET:`${n}/jwt-secret`,ENCRYPTION_KEY:`${n}/encryption-key`,AWS_ACCESS_KEY_ID:`${n}/aws-access-key-id`,AWS_SECRET_ACCESS_KEY:`${n}/aws-secret-access-key`,MAIL_PASSWORD:`${n}/mail-password`,STRIPE_SECRET_KEY:`${n}/stripe-secret-key`,STRIPE_WEBHOOK_SECRET:`${n}/stripe-webhook-secret`})};static createFargateServiceWithSecrets(n){let{secretArns:i=[],kmsKeyArns:s=[],...o}=n,c=a.createFargateService(o);if(i.length>0){if(!c.executionRole.Properties.Policies)c.executionRole.Properties.Policies=[];if(c.executionRole.Properties.Policies.push(a.Secrets.createAccessPolicy(i)),s.length>0)c.executionRole.Properties.Policies.push(a.Secrets.createKmsPolicy(s))}return c}static generateSecretReferences(n){return n.secrets.map((i)=>{let s=`arn:aws:secretsmanager:${n.region}:${n.accountId}:secret:${n.secretPrefix}/${i}`;return{name:i.toUpperCase().replace(/-/g,"_"),valueFrom:s}})}static EnvSecrets={database:(n)=>[{name:"DB_HOST",valueFrom:`${n}:host::`},{name:"DB_PORT",valueFrom:`${n}:port::`},{name:"DB_USERNAME",valueFrom:`${n}:username::`},{name:"DB_PASSWORD",valueFrom:`${n}:password::`},{name:"DB_NAME",valueFrom:`${n}:dbname::`}],redis:(n)=>[{name:"REDIS_HOST",valueFrom:`${n}:host::`},{name:"REDIS_PORT",valueFrom:`${n}:port::`},{name:"REDIS_PASSWORD",valueFrom:`${n}:password::`}],apiCredentials:(n)=>[{name:"API_KEY",valueFrom:`${n}:apiKey::`},{name:"API_SECRET",valueFrom:`${n}:apiSecret::`}],mail:(n)=>[{name:"MAIL_HOST",valueFrom:`${n}:host::`},{name:"MAIL_PORT",valueFrom:`${n}:port::`},{name:"MAIL_USERNAME",valueFrom:`${n}:username::`},{name:"MAIL_PASSWORD",valueFrom:`${n}:password::`}],awsCredentials:(n)=>[{name:"AWS_ACCESS_KEY_ID",valueFrom:`${n}:accessKeyId::`},{name:"AWS_SECRET_ACCESS_KEY",valueFrom:`${n}:secretAccessKey::`}]};static createJumpBox(n){let{slug:i,environment:s,vpcId:o,subnetId:c,keyName:l,instanceType:u="t3.micro",imageId:h="ami-0f3caa1cf4417e51b",allowedCidrs:y=["0.0.0.0/0"],mountEfs:f}=n,b=r({slug:i,environment:s,resourceType:"jumpbox"}),C=t(`${b}-sg`),T={Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:`${b}-sg`,GroupDescription:`Security group for ${b} JumpBox SSH access`,VpcId:o,SecurityGroupIngress:y.map((_)=>({IpProtocol:"tcp",FromPort:22,ToPort:22,CidrIp:_,Description:`SSH access from ${_}`})),SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound traffic"}],Tags:[{Key:"Name",Value:`${b}-sg`},{Key:"Environment",Value:s}]}},w=t(`${b}-role`),E={Type:"AWS::IAM::Role",Properties:{RoleName:`${b}-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ec2.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"],Policies:f?[{PolicyName:"EFSAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess"],Resource:"*"}]}}]:void 0}},I=t(`${b}-profile`),N={Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:`${b}-profile`,Roles:[k.Ref(w)]}},D=`#!/bin/bash
313
+ `}static createLaunchConfiguration(n){let{slug:i,environment:s,imageId:o,instanceType:c,keyName:l,securityGroups:u,userData:h,volumeSize:y=20,volumeType:f="gp3",encrypted:b=!0,iamInstanceProfile:C}=n,T=r({slug:i,environment:s,resourceType:"launch-config"}),w=t(T),E={Type:"AWS::AutoScaling::LaunchConfiguration",Properties:{ImageId:o,InstanceType:c,BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:y,VolumeType:f,Encrypted:b,DeleteOnTermination:!0}}]}};if(l)E.Properties.KeyName=l;if(u)E.Properties.SecurityGroups=u;if(h)E.Properties.UserData=k.Base64(h);if(C)E.Properties.IamInstanceProfile=C;return{launchConfiguration:E,logicalId:w}}static createAutoScalingGroup(n){let{slug:i,environment:s,launchConfigurationName:o,minSize:c,maxSize:l,desiredCapacity:u,vpcZoneIdentifier:h,targetGroupArns:y,healthCheckType:f="EC2",healthCheckGracePeriod:b=300,cooldown:C=300,tags:T={}}=n,w=r({slug:i,environment:s,resourceType:"asg"}),E=t(w),I={Type:"AWS::AutoScaling::AutoScalingGroup",Properties:{AutoScalingGroupName:w,LaunchConfigurationName:o,MinSize:c,MaxSize:l,HealthCheckType:f,HealthCheckGracePeriod:b,Cooldown:C,Tags:[{Key:"Name",Value:w,PropagateAtLaunch:!0},{Key:"Environment",Value:s,PropagateAtLaunch:!0},...Object.entries(T).map(([N,D])=>({Key:N,Value:D,PropagateAtLaunch:!0}))]}};if(u!==void 0)I.Properties.DesiredCapacity=u;if(h)I.Properties.VPCZoneIdentifier=h;if(y)I.Properties.TargetGroupARNs=y;return I.UpdatePolicy={AutoScalingRollingUpdate:{MaxBatchSize:1,MinInstancesInService:Math.max(0,c-1),PauseTime:"PT5M",WaitOnResourceSignals:!1}},{autoScalingGroup:I,logicalId:E}}static createScalingPolicy(n){let{slug:i,environment:s,autoScalingGroupName:o,policyType:c="TargetTrackingScaling",targetValue:l=70,predefinedMetricType:u="ASGAverageCPUUtilization"}=n,h=r({slug:i,environment:s,resourceType:"scaling-policy"}),y=t(h),f={Type:"AWS::AutoScaling::ScalingPolicy",Properties:{AutoScalingGroupName:o,PolicyType:c}};if(c==="TargetTrackingScaling")f.Properties.TargetTrackingConfiguration={PredefinedMetricSpecification:{PredefinedMetricType:u},TargetValue:l};return{scalingPolicy:f,logicalId:y}}static AutoScaling={smallWebServer:(n,i,s,o,c)=>a.createAutoScalingGroup({slug:n,environment:i,launchConfigurationName:s,minSize:2,maxSize:4,desiredCapacity:2,vpcZoneIdentifier:o,targetGroupArns:c,healthCheckType:c?"ELB":"EC2",healthCheckGracePeriod:300}),mediumWebServer:(n,i,s,o,c)=>a.createAutoScalingGroup({slug:n,environment:i,launchConfigurationName:s,minSize:3,maxSize:10,desiredCapacity:3,vpcZoneIdentifier:o,targetGroupArns:c,healthCheckType:c?"ELB":"EC2",healthCheckGracePeriod:300}),largeWebServer:(n,i,s,o,c)=>a.createAutoScalingGroup({slug:n,environment:i,launchConfigurationName:s,minSize:5,maxSize:20,desiredCapacity:5,vpcZoneIdentifier:o,targetGroupArns:c,healthCheckType:c?"ELB":"EC2",healthCheckGracePeriod:300}),cpuScaling:(n,i,s,o=70)=>a.createScalingPolicy({slug:n,environment:i,autoScalingGroupName:s,policyType:"TargetTrackingScaling",predefinedMetricType:"ASGAverageCPUUtilization",targetValue:o}),requestCountScaling:(n,i,s,o=1000)=>a.createScalingPolicy({slug:n,environment:i,autoScalingGroupName:s,policyType:"TargetTrackingScaling",predefinedMetricType:"ALBRequestCountPerTarget",targetValue:o})};static Secrets={fromSecretsManager:(n)=>Object.entries(n).map(([i,s])=>({name:i,valueFrom:s})),fromJsonSecret:(n,i)=>`${n}:${i}::`,fromSecretVersion:(n,i)=>`${n}::${i}:`,fromSecretVersionStage:(n,i)=>`${n}:::${i}`,createAccessPolicy:(n)=>({PolicyName:"SecretsManagerAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],Resource:n}]}}),createKmsPolicy:(n)=>({PolicyName:"KMSDecryptAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["kms:Decrypt"],Resource:n}]}}),buildSecretArn:(n)=>`arn:aws:secretsmanager:${n.region}:${n.accountId}:secret:${n.secretName}`,buildSecretArnPattern:(n)=>{let i=n.region||"*",s=n.accountId||"*";return`arn:aws:secretsmanager:${i}:${s}:secret:${n.secretNamePrefix}*`},commonAppSecrets:(n)=>({DATABASE_URL:`${n}/database-url`,DATABASE_PASSWORD:`${n}/database-password`,REDIS_URL:`${n}/redis-url`,REDIS_PASSWORD:`${n}/redis-password`,API_KEY:`${n}/api-key`,JWT_SECRET:`${n}/jwt-secret`,ENCRYPTION_KEY:`${n}/encryption-key`,AWS_ACCESS_KEY_ID:`${n}/aws-access-key-id`,AWS_SECRET_ACCESS_KEY:`${n}/aws-secret-access-key`,MAIL_PASSWORD:`${n}/mail-password`,STRIPE_SECRET_KEY:`${n}/stripe-secret-key`,STRIPE_WEBHOOK_SECRET:`${n}/stripe-webhook-secret`})};static createFargateServiceWithSecrets(n){let{secretArns:i=[],kmsKeyArns:s=[],...o}=n,c=a.createFargateService(o);if(i.length>0){if(!c.executionRole.Properties.Policies)c.executionRole.Properties.Policies=[];if(c.executionRole.Properties.Policies.push(a.Secrets.createAccessPolicy(i)),s.length>0)c.executionRole.Properties.Policies.push(a.Secrets.createKmsPolicy(s))}return c}static generateSecretReferences(n){return n.secrets.map((i)=>{let s=`arn:aws:secretsmanager:${n.region}:${n.accountId}:secret:${n.secretPrefix}/${i}`;return{name:i.toUpperCase().replace(/-/g,"_"),valueFrom:s}})}static EnvSecrets={database:(n)=>[{name:"DB_HOST",valueFrom:`${n}:host::`},{name:"DB_PORT",valueFrom:`${n}:port::`},{name:"DB_USERNAME",valueFrom:`${n}:username::`},{name:"DB_PASSWORD",valueFrom:`${n}:password::`},{name:"DB_NAME",valueFrom:`${n}:dbname::`}],redis:(n)=>[{name:"REDIS_HOST",valueFrom:`${n}:host::`},{name:"REDIS_PORT",valueFrom:`${n}:port::`},{name:"REDIS_PASSWORD",valueFrom:`${n}:password::`}],apiCredentials:(n)=>[{name:"API_KEY",valueFrom:`${n}:apiKey::`},{name:"API_SECRET",valueFrom:`${n}:apiSecret::`}],mail:(n)=>[{name:"MAIL_HOST",valueFrom:`${n}:host::`},{name:"MAIL_PORT",valueFrom:`${n}:port::`},{name:"MAIL_USERNAME",valueFrom:`${n}:username::`},{name:"MAIL_PASSWORD",valueFrom:`${n}:password::`}],awsCredentials:(n)=>[{name:"AWS_ACCESS_KEY_ID",valueFrom:`${n}:accessKeyId::`},{name:"AWS_SECRET_ACCESS_KEY",valueFrom:`${n}:secretAccessKey::`}]};static createJumpBox(n){let{slug:i,environment:s,vpcId:o,subnetId:c,keyName:l,instanceType:u="t3.micro",imageId:h="ami-0f3caa1cf4417e51b",allowedCidrs:y=["0.0.0.0/0"],mountEfs:f}=n,b=r({slug:i,environment:s,resourceType:"jumpbox"}),C=t(`${b}-sg`),T={Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:`${b}-sg`,GroupDescription:`Security group for ${b} JumpBox SSH access`,VpcId:o,SecurityGroupIngress:y.map((B)=>({IpProtocol:"tcp",FromPort:22,ToPort:22,CidrIp:B,Description:`SSH access from ${B}`})),SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound traffic"}],Tags:[{Key:"Name",Value:`${b}-sg`},{Key:"Environment",Value:s}]}},w=t(`${b}-role`),E={Type:"AWS::IAM::Role",Properties:{RoleName:`${b}-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ec2.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"],Policies:f?[{PolicyName:"EFSAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess"],Resource:"*"}]}}]:void 0}},I=t(`${b}-profile`),N={Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:`${b}-profile`,Roles:[k.Ref(w)]}},D=`#!/bin/bash
314
314
  yum update -y
315
315
  yum install -y amazon-efs-utils nfs-utils jq curl wget htop
316
- `;if(f){let _=f.mountPath||"/mnt/efs";D+=`
316
+ `;if(f){let B=f.mountPath||"/mnt/efs";D+=`
317
317
  # Mount EFS
318
- mkdir -p ${_}
319
- mount -t efs ${f.fileSystemId}:/ ${_}
320
- echo "${f.fileSystemId}:/ ${_} efs defaults,_netdev 0 0" >> /etc/fstab
321
- `}let B=t(b),R={Type:"AWS::EC2::Instance",DependsOn:[I],Properties:{ImageId:h,InstanceType:u,KeyName:l,SubnetId:c,SecurityGroupIds:[k.Ref(C)],IamInstanceProfile:k.Ref(I),UserData:k.Base64(D),BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:20,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0}}],Tags:[{Key:"Name",Value:b},{Key:"Environment",Value:s},{Key:"Purpose",Value:"JumpBox/Bastion"}]}},W={[C]:T,[w]:E,[I]:N,[B]:R};return{instance:R,securityGroup:T,instanceProfile:N,instanceRole:E,instanceLogicalId:B,securityGroupLogicalId:C,instanceProfileLogicalId:I,instanceRoleLogicalId:w,resources:W}}static JumpBox={withEfsMount:(n)=>a.createJumpBox({slug:n.slug,environment:n.environment,vpcId:n.vpcId,subnetId:n.subnetId,keyName:n.keyName,allowedCidrs:n.allowedCidrs,mountEfs:{fileSystemId:n.fileSystemId,mountPath:n.mountPath||"/mnt/efs"}}),minimal:(n)=>a.createJumpBox({slug:n.slug,environment:n.environment,vpcId:n.vpcId,subnetId:n.subnetId,keyName:n.keyName,instanceType:"t3.nano",allowedCidrs:n.allowedCidrs}),withDatabaseTools:(n)=>{let i=a.createJumpBox({slug:n.slug,environment:n.environment,vpcId:n.vpcId,subnetId:n.subnetId,keyName:n.keyName,allowedCidrs:n.allowedCidrs}),s=`#!/bin/bash
318
+ mkdir -p ${B}
319
+ mount -t efs ${f.fileSystemId}:/ ${B}
320
+ echo "${f.fileSystemId}:/ ${B} efs defaults,_netdev 0 0" >> /etc/fstab
321
+ `}let x=t(b),R={Type:"AWS::EC2::Instance",DependsOn:[I],Properties:{ImageId:h,InstanceType:u,KeyName:l,SubnetId:c,SecurityGroupIds:[k.Ref(C)],IamInstanceProfile:k.Ref(I),UserData:k.Base64(D),BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:20,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0}}],Tags:[{Key:"Name",Value:b},{Key:"Environment",Value:s},{Key:"Purpose",Value:"JumpBox/Bastion"}]}},_={[C]:T,[w]:E,[I]:N,[x]:R};return{instance:R,securityGroup:T,instanceProfile:N,instanceRole:E,instanceLogicalId:x,securityGroupLogicalId:C,instanceProfileLogicalId:I,instanceRoleLogicalId:w,resources:_}}static JumpBox={withEfsMount:(n)=>a.createJumpBox({slug:n.slug,environment:n.environment,vpcId:n.vpcId,subnetId:n.subnetId,keyName:n.keyName,allowedCidrs:n.allowedCidrs,mountEfs:{fileSystemId:n.fileSystemId,mountPath:n.mountPath||"/mnt/efs"}}),minimal:(n)=>a.createJumpBox({slug:n.slug,environment:n.environment,vpcId:n.vpcId,subnetId:n.subnetId,keyName:n.keyName,instanceType:"t3.nano",allowedCidrs:n.allowedCidrs}),withDatabaseTools:(n)=>{let i=a.createJumpBox({slug:n.slug,environment:n.environment,vpcId:n.vpcId,subnetId:n.subnetId,keyName:n.keyName,allowedCidrs:n.allowedCidrs}),s=`#!/bin/bash
322
322
  yum update -y
323
323
  yum install -y amazon-efs-utils nfs-utils jq curl wget htop
324
324
 
@@ -604,7 +604,7 @@ ufw default allow outgoing
604
604
  ${n.map((i)=>`ufw allow ${i}`).join(`
605
605
  `)}
606
606
  ufw --force enable
607
- `},Presets:{bunWithNginx:(n,i=3000)=>a.UserData.generateAppServerScript({runtime:"bun",webServer:"nginx",processManager:"systemd",domain:n,appPort:i,enableSsl:!0}),bunWithCaddy:(n,i=3000)=>a.UserData.generateAppServerScript({runtime:"bun",webServer:"caddy",processManager:"systemd",domain:n,appPort:i,enableSsl:!1}),nodeWithPm2:(n,i=3000)=>a.UserData.generateAppServerScript({runtime:"node",webServer:"nginx",processManager:"pm2",domain:n,appPort:i,enableSsl:!0}),worker:(n="bun")=>a.UserData.generateAppServerScript({runtime:n,webServer:"none",processManager:"systemd",enableSsl:!1})}};static createElasticIp(n){let{slug:i,environment:s,domain:o,instanceLogicalId:c}=n,l=r({slug:i,environment:s,resourceType:"eip"}),u=t(l),h={Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s},...o?[{Key:"Domain",Value:o}]:[]]}},y={[u]:h},f,b;if(c)b=t(`${l}-assoc`),f={Type:"AWS::EC2::EIPAssociation",Properties:{AllocationId:k.GetAtt(u,"AllocationId"),InstanceId:k.Ref(c)}},y[b]=f;return{eip:h,eipAssociation:f,eipLogicalId:u,associationLogicalId:b,resources:y}}static createServerModeStack(n){let{slug:i,environment:s,vpcId:o,subnetId:c,instanceType:l="t3.small",imageId:u="ami-0f3caa1cf4417e51b",keyName:h,domain:y,userData:f,allowedPorts:b=[22,80,443],volumeSize:C=20,volumeType:T="gp3"}=n,w={},E=r({slug:i,environment:s,resourceType:"server-sg"}),I=t(E),N={Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:E,GroupDescription:`Security group for ${i} server`,VpcId:o,SecurityGroupIngress:b.map((ie)=>({IpProtocol:"tcp",FromPort:ie,ToPort:ie,CidrIp:"0.0.0.0/0",Description:`Port ${ie}`})),SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound"}],Tags:[{Key:"Name",Value:E},{Key:"Environment",Value:s}]}};w[I]=N;let D=r({slug:i,environment:s,resourceType:"server-role"}),B=t(D),R={Type:"AWS::IAM::Role",Properties:{RoleName:D,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ec2.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore","arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"],Policies:[{PolicyName:"StacksServerPermissions",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail","ses:SendBulkEmail","ses:VerifyDomainIdentity","ses:VerifyDomainDkim","ses:GetIdentityDkimAttributes","ses:GetIdentityVerificationAttributes"],Resource:"*"},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:ListBucket"],Resource:"*"},{Effect:"Allow",Action:["route53:ChangeResourceRecordSets","route53:ListResourceRecordSets","route53:GetHostedZone"],Resource:"*"},{Effect:"Allow",Action:["ssm:GetParameter","ssm:GetParameters"],Resource:"*"}]}}]}};w[B]=R;let W=r({slug:i,environment:s,resourceType:"server-profile"}),_=t(W),j={Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:W,Roles:[k.Ref(B)]}};w[_]=j;let J=r({slug:i,environment:s,resourceType:"server"}),K=t(J),Y={Type:"AWS::EC2::Instance",DependsOn:[_],Properties:{ImageId:u,InstanceType:l,KeyName:h,SubnetId:c,SecurityGroupIds:[k.Ref(I)],IamInstanceProfile:k.Ref(_),BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:C,VolumeType:T,Encrypted:!0,DeleteOnTermination:!0}}],Tags:[{Key:"Name",Value:J},{Key:"Environment",Value:s},...y?[{Key:"Domain",Value:y}]:[]]}};if(f)Y.Properties.UserData=k.Base64(f);w[K]=Y;let{eip:X,eipAssociation:ne,eipLogicalId:me,associationLogicalId:oe,resources:le}=a.createElasticIp({slug:i,environment:s,domain:y,instanceLogicalId:K});return Object.assign(w,le),{instance:Y,securityGroup:N,eip:X,eipAssociation:ne,instanceRole:R,instanceProfile:j,resources:w,outputs:{instanceLogicalId:K,securityGroupLogicalId:I,eipLogicalId:me,associationLogicalId:oe,roleLogicalId:B,profileLogicalId:_}}}static ServerMode={webServer:(n)=>{let i=a.UserData.generateAppServerScript({runtime:n.runtime||"bun",webServer:n.webServer||"nginx",domain:n.domain,enableSsl:!0});return a.createServerModeStack({...n,userData:i,instanceType:"t3.small",allowedPorts:[22,80,443]})},workerServer:(n)=>{let i=a.UserData.generateAppServerScript({runtime:n.runtime||"bun",webServer:"none",installRedis:n.installRedis});return a.createServerModeStack({...n,userData:i,instanceType:"t3.medium",allowedPorts:[22]})},cacheServer:(n)=>a.createServerModeStack({...n,userData:`#!/bin/bash
607
+ `},Presets:{bunWithNginx:(n,i=3000)=>a.UserData.generateAppServerScript({runtime:"bun",webServer:"nginx",processManager:"systemd",domain:n,appPort:i,enableSsl:!0}),bunWithCaddy:(n,i=3000)=>a.UserData.generateAppServerScript({runtime:"bun",webServer:"caddy",processManager:"systemd",domain:n,appPort:i,enableSsl:!1}),nodeWithPm2:(n,i=3000)=>a.UserData.generateAppServerScript({runtime:"node",webServer:"nginx",processManager:"pm2",domain:n,appPort:i,enableSsl:!0}),worker:(n="bun")=>a.UserData.generateAppServerScript({runtime:n,webServer:"none",processManager:"systemd",enableSsl:!1})}};static createElasticIp(n){let{slug:i,environment:s,domain:o,instanceLogicalId:c}=n,l=r({slug:i,environment:s,resourceType:"eip"}),u=t(l),h={Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s},...o?[{Key:"Domain",Value:o}]:[]]}},y={[u]:h},f,b;if(c)b=t(`${l}-assoc`),f={Type:"AWS::EC2::EIPAssociation",Properties:{AllocationId:k.GetAtt(u,"AllocationId"),InstanceId:k.Ref(c)}},y[b]=f;return{eip:h,eipAssociation:f,eipLogicalId:u,associationLogicalId:b,resources:y}}static createServerModeStack(n){let{slug:i,environment:s,vpcId:o,subnetId:c,instanceType:l="t3.small",imageId:u="ami-0f3caa1cf4417e51b",keyName:h,domain:y,userData:f,allowedPorts:b=[22,80,443],volumeSize:C=20,volumeType:T="gp3"}=n,w={},E=r({slug:i,environment:s,resourceType:"server-sg"}),I=t(E),N={Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:E,GroupDescription:`Security group for ${i} server`,VpcId:o,SecurityGroupIngress:b.map((ie)=>({IpProtocol:"tcp",FromPort:ie,ToPort:ie,CidrIp:"0.0.0.0/0",Description:`Port ${ie}`})),SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound"}],Tags:[{Key:"Name",Value:E},{Key:"Environment",Value:s}]}};w[I]=N;let D=r({slug:i,environment:s,resourceType:"server-role"}),x=t(D),R={Type:"AWS::IAM::Role",Properties:{RoleName:D,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ec2.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore","arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"],Policies:[{PolicyName:"StacksServerPermissions",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail","ses:SendBulkEmail","ses:VerifyDomainIdentity","ses:VerifyDomainDkim","ses:GetIdentityDkimAttributes","ses:GetIdentityVerificationAttributes"],Resource:"*"},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:ListBucket"],Resource:"*"},{Effect:"Allow",Action:["route53:ChangeResourceRecordSets","route53:ListResourceRecordSets","route53:GetHostedZone"],Resource:"*"},{Effect:"Allow",Action:["ssm:GetParameter","ssm:GetParameters"],Resource:"*"}]}}]}};w[x]=R;let _=r({slug:i,environment:s,resourceType:"server-profile"}),B=t(_),W={Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:_,Roles:[k.Ref(x)]}};w[B]=W;let J=r({slug:i,environment:s,resourceType:"server"}),K=t(J),Y={Type:"AWS::EC2::Instance",DependsOn:[B],Properties:{ImageId:u,InstanceType:l,KeyName:h,SubnetId:c,SecurityGroupIds:[k.Ref(I)],IamInstanceProfile:k.Ref(B),BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:C,VolumeType:T,Encrypted:!0,DeleteOnTermination:!0}}],Tags:[{Key:"Name",Value:J},{Key:"Environment",Value:s},...y?[{Key:"Domain",Value:y}]:[]]}};if(f)Y.Properties.UserData=k.Base64(f);w[K]=Y;let{eip:Z,eipAssociation:ne,eipLogicalId:de,associationLogicalId:oe,resources:le}=a.createElasticIp({slug:i,environment:s,domain:y,instanceLogicalId:K});return Object.assign(w,le),{instance:Y,securityGroup:N,eip:Z,eipAssociation:ne,instanceRole:R,instanceProfile:W,resources:w,outputs:{instanceLogicalId:K,securityGroupLogicalId:I,eipLogicalId:de,associationLogicalId:oe,roleLogicalId:x,profileLogicalId:B}}}static ServerMode={webServer:(n)=>{let i=a.UserData.generateAppServerScript({runtime:n.runtime||"bun",webServer:n.webServer||"nginx",domain:n.domain,enableSsl:!0});return a.createServerModeStack({...n,userData:i,instanceType:"t3.small",allowedPorts:[22,80,443]})},workerServer:(n)=>{let i=a.UserData.generateAppServerScript({runtime:n.runtime||"bun",webServer:"none",installRedis:n.installRedis});return a.createServerModeStack({...n,userData:i,instanceType:"t3.medium",allowedPorts:[22]})},cacheServer:(n)=>a.createServerModeStack({...n,userData:`#!/bin/bash
608
608
  set -e
609
609
  apt-get update && apt-get upgrade -y
610
610
  apt-get install -y redis-server
@@ -612,7 +612,7 @@ sed -i 's/bind 127.0.0.1/bind 0.0.0.0/' /etc/redis/redis.conf
612
612
  systemctl enable redis-server
613
613
  systemctl restart redis-server
614
614
  echo "Redis server setup complete!"
615
- `,instanceType:"t3.medium",allowedPorts:[22,6379]})}}class A{static createVpc(n){let{slug:i,environment:s,cidr:o="10.0.0.0/16",enableDnsHostnames:c=!0,enableDnsSupport:l=!0}=n,u=r({slug:i,environment:s,resourceType:"vpc"}),h=t(u);return{vpc:{Type:"AWS::EC2::VPC",Properties:{CidrBlock:o,EnableDnsHostnames:c,EnableDnsSupport:l,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:s}]}},logicalId:h}}static createSubnet(n){let{slug:i,environment:s,vpcId:o,type:c,cidr:l,availabilityZone:u,mapPublicIp:h=c==="public"}=n,y=r({slug:i,environment:s,resourceType:`subnet-${c}`}),f=t(`${y}-${u}`);return{subnet:{Type:"AWS::EC2::Subnet",Properties:{VpcId:o,CidrBlock:l,AvailabilityZone:u,MapPublicIpOnLaunch:h,Tags:[{Key:"Name",Value:`${y}-${u}`},{Key:"Environment",Value:s},{Key:"Type",Value:c}]}},logicalId:f}}static createInternetGateway(n,i){let s=r({slug:n,environment:i,resourceType:"igw"}),o=t(s);return{internetGateway:{Type:"AWS::EC2::InternetGateway",Properties:{Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:i}]}},logicalId:o}}static attachInternetGateway(n,i){let s=t(`${n}-igw-attachment`);return{attachment:{Type:"AWS::EC2::VPCGatewayAttachment",Properties:{VpcId:k.Ref(n),InternetGatewayId:k.Ref(i)}},logicalId:s}}static createEip(n,i){let s=r({slug:n,environment:i,resourceType:"eip"}),o=t(s);return{eip:{Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:i}]}},logicalId:o}}static createNatGateway(n,i){let{slug:s,environment:o,subnetId:c}=n,l=r({slug:s,environment:o,resourceType:"nat"}),u=t(l);return{natGateway:{Type:"AWS::EC2::NatGateway",Properties:{AllocationId:k.GetAtt(i,"AllocationId"),SubnetId:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:o},{Key:"Warning",Value:"NAT Gateway incurs hourly charges"}]}},logicalId:u}}static createRouteTable(n,i,s,o){let c=r({slug:n,environment:i,resourceType:`rt-${o}`}),l=t(c);return{routeTable:{Type:"AWS::EC2::RouteTable",Properties:{VpcId:k.Ref(s),Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:i},{Key:"Type",Value:o}]}},logicalId:l}}static createRoute(n,i,s){let o=t(`${n}-route-${s.type}`),c={Type:"AWS::EC2::Route",Properties:{RouteTableId:k.Ref(n),DestinationCidrBlock:i}};if(s.type==="igw")c.Properties.GatewayId=k.Ref(s.logicalId);else if(s.type==="nat")c.Properties.NatGatewayId=k.Ref(s.logicalId);else if(s.type==="instance")c.Properties.InstanceId=k.Ref(s.logicalId);return{route:c,logicalId:o}}static associateSubnetWithRouteTable(n,i){let s=t(`${n}-rt-assoc`);return{association:{Type:"AWS::EC2::SubnetRouteTableAssociation",Properties:{SubnetId:k.Ref(n),RouteTableId:k.Ref(i)}},logicalId:s}}static enableFlowLogs(n){let{slug:i,environment:s,resourceId:o,resourceType:c,trafficType:l="ALL",logGroupName:u}=n,h=r({slug:i,environment:s,resourceType:"flowlog"}),y=t(h);return{flowLog:{Type:"AWS::EC2::FlowLog",Properties:{ResourceType:c,ResourceIds:[o],TrafficType:l,LogDestinationType:"cloud-watch-logs",LogGroupName:u||`/aws/vpc/${i}-${s}`,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}},logicalId:y}}static calculateSubnetCidrs(n,i,s=3){let[o,c]=n.split("/"),l=Number.parseInt(c,10),u=Math.ceil(Math.log2(i*s)),h=l+u;if(h>28)throw Error("VPC CIDR is too small to accommodate requested subnets");let[y,f,b,C]=o.split(".").map(Number),T=(y<<24)+(f<<16)+(b<<8)+C,w=2**(32-h),E=[];for(let I=0;I<i*s;I++){let N=T+I*w,D=[N>>>24&255,N>>>16&255,N>>>8&255,N&255].join(".");E.push(`${D}/${h}`)}return E}static getAvailabilityZones(n,i){return["a","b","c","d","e","f"].slice(0,i).map((s)=>`${n}${s}`)}static createMultiAzNetwork(n){let{slug:i,environment:s,region:o,cidr:c="10.0.0.0/16",zones:l=3,enableNatGateway:u=!1,singleNatGateway:h=!1,enableFlowLogs:y=!1}=n,f={},b=[],C=[],T=[],{vpc:w,logicalId:E}=A.createVpc({slug:i,environment:s,cidr:c});f[E]=w;let{internetGateway:I,logicalId:N}=A.createInternetGateway(i,s);f[N]=I;let{attachment:D,logicalId:B}=A.attachInternetGateway(E,N);f[B]=D;let{routeTable:R,logicalId:W}=A.createRouteTable(i,s,E,"public");f[W]=R;let{route:_,logicalId:j}=A.createRoute(W,"0.0.0.0/0",{type:"igw",logicalId:N});_.DependsOn=B,f[j]=_;let J=A.calculateSubnetCidrs(c,l,2),K=A.getAvailabilityZones(o,l),Y=[];for(let X=0;X<l;X++){let ne=K[X],me=J[X*2],oe=J[X*2+1],{subnet:le,logicalId:ie}=A.createSubnet({slug:i,environment:s,vpcId:k.Ref(E),type:"public",cidr:me,availabilityZone:ne});f[ie]=le,b.push(ie);let{association:Ie,logicalId:Ge}=A.associateSubnetWithRouteTable(ie,W);f[Ge]=Ie;let{subnet:Et,logicalId:ge}=A.createSubnet({slug:i,environment:s,vpcId:k.Ref(E),type:"private",cidr:oe,availabilityZone:ne});if(f[ge]=Et,C.push(ge),u&&(!h||X===0)){let{eip:de,logicalId:he}=A.createEip(`${i}-${ne}`,s);f[he]=de;let{natGateway:Ne,logicalId:ye}=A.createNatGateway({slug:`${i}-${ne}`,environment:s,subnetId:k.Ref(ie)},he);Ne.DependsOn=B,f[ye]=Ne,T.push(ye);let{routeTable:Ae,logicalId:Me}=A.createRouteTable(`${i}-${ne}`,s,E,"private");f[Me]=Ae,Y.push(Me);let{route:Fe,logicalId:z}=A.createRoute(Me,"0.0.0.0/0",{type:"nat",logicalId:ye});f[z]=Fe;let{association:re,logicalId:ae}=A.associateSubnetWithRouteTable(ge,Me);f[ae]=re}else if(u&&h&&X>0){let{association:de,logicalId:he}=A.associateSubnetWithRouteTable(ge,Y[0]);f[he]=de}else{let{routeTable:de,logicalId:he}=A.createRouteTable(`${i}-${ne}-isolated`,s,E,"private");f[he]=de;let{association:Ne,logicalId:ye}=A.associateSubnetWithRouteTable(ge,he);f[ye]=Ne}}if(y){let{flowLog:X,logicalId:ne}=A.enableFlowLogs({slug:i,environment:s,resourceId:k.Ref(E),resourceType:"VPC"});f[ne]=X}return{resources:f,outputs:{vpcId:E,publicSubnetIds:b,privateSubnetIds:C,natGatewayIds:T.length>0?T:void 0}}}static NatGatewayCostWarning=`
615
+ `,instanceType:"t3.medium",allowedPorts:[22,6379]})}}class A{static createVpc(n){let{slug:i,environment:s,cidr:o="10.0.0.0/16",enableDnsHostnames:c=!0,enableDnsSupport:l=!0}=n,u=r({slug:i,environment:s,resourceType:"vpc"}),h=t(u);return{vpc:{Type:"AWS::EC2::VPC",Properties:{CidrBlock:o,EnableDnsHostnames:c,EnableDnsSupport:l,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:s}]}},logicalId:h}}static createSubnet(n){let{slug:i,environment:s,vpcId:o,type:c,cidr:l,availabilityZone:u,mapPublicIp:h=c==="public"}=n,y=r({slug:i,environment:s,resourceType:`subnet-${c}`}),f=t(`${y}-${u}`);return{subnet:{Type:"AWS::EC2::Subnet",Properties:{VpcId:o,CidrBlock:l,AvailabilityZone:u,MapPublicIpOnLaunch:h,Tags:[{Key:"Name",Value:`${y}-${u}`},{Key:"Environment",Value:s},{Key:"Type",Value:c}]}},logicalId:f}}static createInternetGateway(n,i){let s=r({slug:n,environment:i,resourceType:"igw"}),o=t(s);return{internetGateway:{Type:"AWS::EC2::InternetGateway",Properties:{Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:i}]}},logicalId:o}}static attachInternetGateway(n,i){let s=t(`${n}-igw-attachment`);return{attachment:{Type:"AWS::EC2::VPCGatewayAttachment",Properties:{VpcId:k.Ref(n),InternetGatewayId:k.Ref(i)}},logicalId:s}}static createEip(n,i){let s=r({slug:n,environment:i,resourceType:"eip"}),o=t(s);return{eip:{Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:i}]}},logicalId:o}}static createNatGateway(n,i){let{slug:s,environment:o,subnetId:c}=n,l=r({slug:s,environment:o,resourceType:"nat"}),u=t(l);return{natGateway:{Type:"AWS::EC2::NatGateway",Properties:{AllocationId:k.GetAtt(i,"AllocationId"),SubnetId:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:o},{Key:"Warning",Value:"NAT Gateway incurs hourly charges"}]}},logicalId:u}}static createRouteTable(n,i,s,o){let c=r({slug:n,environment:i,resourceType:`rt-${o}`}),l=t(c);return{routeTable:{Type:"AWS::EC2::RouteTable",Properties:{VpcId:k.Ref(s),Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:i},{Key:"Type",Value:o}]}},logicalId:l}}static createRoute(n,i,s){let o=t(`${n}-route-${s.type}`),c={Type:"AWS::EC2::Route",Properties:{RouteTableId:k.Ref(n),DestinationCidrBlock:i}};if(s.type==="igw")c.Properties.GatewayId=k.Ref(s.logicalId);else if(s.type==="nat")c.Properties.NatGatewayId=k.Ref(s.logicalId);else if(s.type==="instance")c.Properties.InstanceId=k.Ref(s.logicalId);return{route:c,logicalId:o}}static associateSubnetWithRouteTable(n,i){let s=t(`${n}-rt-assoc`);return{association:{Type:"AWS::EC2::SubnetRouteTableAssociation",Properties:{SubnetId:k.Ref(n),RouteTableId:k.Ref(i)}},logicalId:s}}static enableFlowLogs(n){let{slug:i,environment:s,resourceId:o,resourceType:c,trafficType:l="ALL",logGroupName:u}=n,h=r({slug:i,environment:s,resourceType:"flowlog"}),y=t(h);return{flowLog:{Type:"AWS::EC2::FlowLog",Properties:{ResourceType:c,ResourceIds:[o],TrafficType:l,LogDestinationType:"cloud-watch-logs",LogGroupName:u||`/aws/vpc/${i}-${s}`,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}},logicalId:y}}static calculateSubnetCidrs(n,i,s=3){let[o,c]=n.split("/"),l=Number.parseInt(c,10),u=Math.ceil(Math.log2(i*s)),h=l+u;if(h>28)throw Error("VPC CIDR is too small to accommodate requested subnets");let[y,f,b,C]=o.split(".").map(Number),T=(y<<24)+(f<<16)+(b<<8)+C,w=2**(32-h),E=[];for(let I=0;I<i*s;I++){let N=T+I*w,D=[N>>>24&255,N>>>16&255,N>>>8&255,N&255].join(".");E.push(`${D}/${h}`)}return E}static getAvailabilityZones(n,i){return["a","b","c","d","e","f"].slice(0,i).map((s)=>`${n}${s}`)}static createMultiAzNetwork(n){let{slug:i,environment:s,region:o,cidr:c="10.0.0.0/16",zones:l=3,enableNatGateway:u=!1,singleNatGateway:h=!1,enableFlowLogs:y=!1}=n,f={},b=[],C=[],T=[],{vpc:w,logicalId:E}=A.createVpc({slug:i,environment:s,cidr:c});f[E]=w;let{internetGateway:I,logicalId:N}=A.createInternetGateway(i,s);f[N]=I;let{attachment:D,logicalId:x}=A.attachInternetGateway(E,N);f[x]=D;let{routeTable:R,logicalId:_}=A.createRouteTable(i,s,E,"public");f[_]=R;let{route:B,logicalId:W}=A.createRoute(_,"0.0.0.0/0",{type:"igw",logicalId:N});B.DependsOn=x,f[W]=B;let J=A.calculateSubnetCidrs(c,l,2),K=A.getAvailabilityZones(o,l),Y=[];for(let Z=0;Z<l;Z++){let ne=K[Z],de=J[Z*2],oe=J[Z*2+1],{subnet:le,logicalId:ie}=A.createSubnet({slug:i,environment:s,vpcId:k.Ref(E),type:"public",cidr:de,availabilityZone:ne});f[ie]=le,b.push(ie);let{association:Ee,logicalId:Fe}=A.associateSubnetWithRouteTable(ie,_);f[Fe]=Ee;let{subnet:Et,logicalId:pe}=A.createSubnet({slug:i,environment:s,vpcId:k.Ref(E),type:"private",cidr:oe,availabilityZone:ne});if(f[pe]=Et,C.push(pe),u&&(!h||Z===0)){let{eip:ue,logicalId:he}=A.createEip(`${i}-${ne}`,s);f[he]=ue;let{natGateway:Ie,logicalId:ye}=A.createNatGateway({slug:`${i}-${ne}`,environment:s,subnetId:k.Ref(ie)},he);Ie.DependsOn=x,f[ye]=Ie,T.push(ye);let{routeTable:Ae,logicalId:Me}=A.createRouteTable(`${i}-${ne}`,s,E,"private");f[Me]=Ae,Y.push(Me);let{route:Ue,logicalId:z}=A.createRoute(Me,"0.0.0.0/0",{type:"nat",logicalId:ye});f[z]=Ue;let{association:ae,logicalId:X}=A.associateSubnetWithRouteTable(pe,Me);f[X]=ae}else if(u&&h&&Z>0){let{association:ue,logicalId:he}=A.associateSubnetWithRouteTable(pe,Y[0]);f[he]=ue}else{let{routeTable:ue,logicalId:he}=A.createRouteTable(`${i}-${ne}-isolated`,s,E,"private");f[he]=ue;let{association:Ie,logicalId:ye}=A.associateSubnetWithRouteTable(pe,he);f[ye]=Ie}}if(y){let{flowLog:Z,logicalId:ne}=A.enableFlowLogs({slug:i,environment:s,resourceId:k.Ref(E),resourceType:"VPC"});f[ne]=Z}return{resources:f,outputs:{vpcId:E,publicSubnetIds:b,privateSubnetIds:C,natGatewayIds:T.length>0?T:void 0}}}static NatGatewayCostWarning=`
616
616
  ⚠️ NAT Gateway Cost Warning:
617
617
  - Each NAT Gateway costs approximately $32-45/month (hourly charges)
618
618
  - Data processing charges: $0.045/GB processed
@@ -620,7 +620,7 @@ echo "Redis server setup complete!"
620
620
  - Using a single NAT Gateway (singleNatGateway: true)
621
621
  - Using NAT Instances instead (cheaper but requires management)
622
622
  - Disabling NAT entirely for isolated private subnets
623
- `}class Ve{static createFileSystem(n){let{slug:i,environment:s,encrypted:o=!0,kmsKeyId:c,performanceMode:l="generalPurpose",throughputMode:u="bursting",provisionedThroughput:h,enableBackup:y=!0}=n,f=r({slug:i,environment:s,resourceType:"efs"}),b=t(f),C={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:o,PerformanceMode:l,ThroughputMode:u,FileSystemTags:[{Key:"Name",Value:f},{Key:"Environment",Value:s}]}};if(c)C.Properties.KmsKeyId=c;if(u==="provisioned"&&h)C.Properties.ProvisionedThroughputInMibps=h;if(y)C.Properties.BackupPolicy={Status:"ENABLED"};return{fileSystem:C,logicalId:b}}static createMountTarget(n,i){let{slug:s,environment:o,subnetId:c,securityGroups:l,ipAddress:u}=i,h=r({slug:s,environment:o,resourceType:"efs-mt"}),y=t(`${h}-${c}`),f={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:k.Ref(n),SubnetId:c,SecurityGroups:l}};if(u)f.Properties.IpAddress=u;return{mountTarget:f,logicalId:y}}static createAccessPoint(n,i){let{slug:s,environment:o,path:c="/",uid:l="1000",gid:u="1000",permissions:h="755"}=i,y=r({slug:s,environment:o,resourceType:"efs-ap"}),f=t(`${y}-${c.replace(/\//g,"-")}`);return{accessPoint:{Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:k.Ref(n),PosixUser:{Uid:l,Gid:u},RootDirectory:{Path:c,CreationInfo:{OwnerUid:l,OwnerGid:u,Permissions:h}},AccessPointTags:[{Key:"Name",Value:`${y}-${c}`},{Key:"Environment",Value:o}]}},logicalId:f}}static setLifecyclePolicy(n,i){let{transitionToIA:s,transitionToPrimary:o=!1}=i;if(!n.Properties)n.Properties={};if(n.Properties.LifecyclePolicies=[],s){let c=`AFTER_${s}_DAYS`;n.Properties.LifecyclePolicies.push({TransitionToIA:c})}if(o)n.Properties.LifecyclePolicies.push({TransitionToPrimaryStorageClass:"AFTER_1_ACCESS"});return n}static enableBackup(n){if(!n.Properties)n.Properties={};return n.Properties.BackupPolicy={Status:"ENABLED"},n}static disableBackup(n){if(!n.Properties)n.Properties={};return n.Properties.BackupPolicy={Status:"DISABLED"},n}static setProvisionedThroughput(n,i){if(!n.Properties)n.Properties={};return n.Properties.ThroughputMode="provisioned",n.Properties.ProvisionedThroughputInMibps=i,n}static setElasticThroughput(n){if(!n.Properties)n.Properties={};return n.Properties.ThroughputMode="elastic",n}static enableMaxIO(n){if(!n.Properties)n.Properties={};return n.Properties.PerformanceMode="maxIO",n}static createEfsSecurityGroup(n){let{slug:i,environment:s,vpcId:o,sourceSecurityGroupIds:c=[],sourceCidrBlocks:l=[],description:u}=n,h=r({slug:i,environment:s,resourceType:"efs-sg"}),y=t(h),f=[];for(let b of c)f.push({IpProtocol:"tcp",FromPort:2049,ToPort:2049,SourceSecurityGroupId:b,Description:"NFS from security group"});for(let b of l)f.push({IpProtocol:"tcp",FromPort:2049,ToPort:2049,CidrIp:b,Description:"NFS from CIDR block"});return{securityGroup:{Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:h,GroupDescription:u||`Security group for EFS mount targets - ${i} ${s}`,VpcId:o,SecurityGroupIngress:f,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}},logicalId:y}}static createMultiAzMountTargets(n,i){let{slug:s,environment:o,subnetIds:c,securityGroupId:l}=i,u=[],h=[];for(let y=0;y<c.length;y++){let f=c[y],b=r({slug:s,environment:o,resourceType:"efs-mt"}),C=t(`${b}-az${y+1}`),T={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:k.Ref(n),SubnetId:f,SecurityGroups:[l]}};u.push(T),h.push(C)}return{mountTargets:u,logicalIds:h}}static createCompleteFileSystem(n){let{slug:i,environment:s,vpcId:o,subnetIds:c,sourceSecurityGroupIds:l=[],encrypted:u=!0,performanceMode:h="generalPurpose",throughputMode:y="elastic",enableBackup:f=!0,transitionToIA:b}=n,C={},{fileSystem:T,logicalId:w}=Ve.createFileSystem({slug:i,environment:s,encrypted:u,performanceMode:h,throughputMode:y,enableBackup:f});if(b)Ve.setLifecyclePolicy(T,{transitionToIA:b,transitionToPrimary:!0});C[w]=T;let{securityGroup:E,logicalId:I}=Ve.createEfsSecurityGroup({slug:i,environment:s,vpcId:o,sourceSecurityGroupIds:l});C[I]=E;let{mountTargets:N,logicalIds:D}=Ve.createMultiAzMountTargets(w,{slug:i,environment:s,subnetIds:c,securityGroupId:k.Ref(I)});for(let B=0;B<N.length;B++)C[D[B]]=N[B];return{resources:C,outputs:{fileSystemId:w,securityGroupId:I,mountTargetIds:D}}}}class m{static verifyDomain(n){let{domain:i,slug:s,environment:o,enableDkim:c=!0,dkimKeyLength:l="RSA_2048_BIT"}=n,u=r({slug:s,environment:o,resourceType:"ses-identity"}),h=t(`${u}-${i.replace(/\./g,"")}`),y={Type:"AWS::SES::EmailIdentity",Properties:{EmailIdentity:i,FeedbackAttributes:{EmailForwardingEnabled:!0}}};if(c)y.Properties.DkimSigningAttributes={NextSigningKeyLength:l};return{emailIdentity:y,logicalId:h}}static createDkimRecords(n,i,s){let o=[];for(let c=0;c<i.length;c++){let l=i[c],u=t(`dkim-${n.replace(/\./g,"")}-${c+1}`),h={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:s,Name:`${l}._domainkey.${n}`,Type:"CNAME",TTL:1800,ResourceRecords:[`${l}.dkim.amazonses.com`]}};o.push({record:h,logicalId:u})}return o}static createConfigurationSet(n){let{slug:i,environment:s,name:o,reputationMetrics:c=!0,sendingEnabled:l=!0,suppressBounces:u=!0,suppressComplaints:h=!0}=n,y=o||r({slug:i,environment:s,resourceType:"ses-config"}),f=t(y),b=[];if(u)b.push("BOUNCE");if(h)b.push("COMPLAINT");return{configurationSet:{Type:"AWS::SES::ConfigurationSet",Properties:{Name:y,ReputationOptions:{ReputationMetricsEnabled:c},SendingOptions:{SendingEnabled:l},SuppressionOptions:{SuppressedReasons:b}}},logicalId:f}}static createReceiptRuleSet(n){let{slug:i,environment:s,name:o}=n,c=o||r({slug:i,environment:s,resourceType:"ses-ruleset"}),l=t(c);return{ruleSet:{Type:"AWS::SES::ReceiptRuleSet",Properties:{RuleSetName:c}},logicalId:l}}static createReceiptRule(n,i){let{slug:s,environment:o,ruleSetName:c,recipients:l,enabled:u=!0,scanEnabled:h=!0,tlsPolicy:y="Require",s3Action:f,lambdaAction:b,snsAction:C}=i,T=r({slug:s,environment:o,resourceType:"ses-rule"}),w=t(T),E=[];if(f)E.push({S3Action:{BucketName:f.bucketName,ObjectKeyPrefix:f.prefix,KmsKeyArn:f.kmsKeyArn}});if(b)E.push({LambdaAction:{FunctionArn:b.functionArn,InvocationType:b.invocationType||"Event"}});if(C)E.push({SNSAction:{TopicArn:C.topicArn,Encoding:C.encoding||"UTF-8"}});return{receiptRule:{Type:"AWS::SES::ReceiptRule",Properties:{RuleSetName:c,Rule:{Name:T,Enabled:u,ScanEnabled:h,TlsPolicy:y,Recipients:l,Actions:E.length>0?E:void 0}}},logicalId:w}}static createMxRecord(n,i,s){let o=t(`mx-${n.replace(/\./g,"")}`);return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:n,Type:"MX",TTL:300,ResourceRecords:[`10 inbound-smtp.${s}.amazonaws.com`]}},logicalId:o}}static createVerificationRecord(n,i,s){let o=t(`verification-${n.replace(/\./g,"")}`);return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:s,Name:`_amazonses.${n}`,Type:"TXT",TTL:1800,ResourceRecords:[`"${i}"`]}},logicalId:o}}static getSmtpEndpoint(n){return`email-smtp.${n}.amazonaws.com`}static SmtpPorts={TLS:587,SSL:465,Unencrypted:25};static createSpfRecord(n,i,s){let{includeDomains:o=[],softFail:c=!1}=s||{},l=t(`spf-${n.replace(/\./g,"")}`),u="v=spf1 include:amazonses.com";for(let h of o)u+=` include:${h}`;return u+=c?" ~all":" -all",{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:n,Type:"TXT",TTL:300,ResourceRecords:[`"${u}"`]}},logicalId:l}}static createDmarcRecord(n,i,s){let{policy:o="none",subdomainPolicy:c,percentage:l=100,reportingEmail:u,forensicEmail:h}=s||{},y=t(`dmarc-${n.replace(/\./g,"")}`),f=`v=DMARC1; p=${o}; pct=${l}`;if(c)f+=`; sp=${c}`;if(u)f+=`; rua=mailto:${u}`;if(h)f+=`; ruf=mailto:${h}`;return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:`_dmarc.${n}`,Type:"TXT",TTL:300,ResourceRecords:[`"${f}"`]}},logicalId:y}}static createInboundEmailSetup(n){let{slug:i,environment:s,domain:o,s3BucketName:c,s3KeyPrefix:l="inbound/",region:u,hostedZoneId:h,lambdaFunctionArn:y,snsTopicArn:f}=n,b={},{ruleSet:C,logicalId:T}=m.createReceiptRuleSet({slug:i,environment:s});b[T]=C;let{receiptRule:w,logicalId:E}=m.createReceiptRule(T,{slug:i,environment:s,ruleSetName:C.Properties.RuleSetName||`${i}-${s}-receipt-rule-set`,recipients:[o],s3Action:{bucketName:c,prefix:l},lambdaAction:y?{functionArn:y,invocationType:"Event"}:void 0,snsAction:f?{topicArn:f}:void 0});b[E]=w;let{record:I,logicalId:N}=m.createMxRecord(o,h,u);return b[N]=I,{resources:b,outputs:{ruleSetLogicalId:T,ruleLogicalId:E,mxRecordLogicalId:N}}}static createCompleteDomainSetup(n){let{slug:i,environment:s,domain:o,hostedZoneId:c,region:l,enableInbound:u=!1,inboundS3Bucket:h,dmarcReportingEmail:y}=n,f={},{emailIdentity:b,logicalId:C}=m.verifyDomain({domain:o,slug:i,environment:s});f[C]=b;let{configurationSet:T,logicalId:w}=m.createConfigurationSet({slug:i,environment:s});f[w]=T;let{record:E,logicalId:I}=m.createSpfRecord(o,c);f[I]=E;let{record:N,logicalId:D}=m.createDmarcRecord(o,c,{policy:"none",reportingEmail:y||`dmarc-reports@${o}`});if(f[D]=N,u&&h){let B=m.createInboundEmailSetup({slug:i,environment:s,domain:o,s3BucketName:h,region:l,hostedZoneId:c});Object.assign(f,B.resources)}return{resources:f,outputs:{identityLogicalId:C,configSetLogicalId:w}}}static InboundSmtpEndpoints={"us-east-1":"inbound-smtp.us-east-1.amazonaws.com","us-west-2":"inbound-smtp.us-west-2.amazonaws.com","eu-west-1":"inbound-smtp.eu-west-1.amazonaws.com"};static supportsInboundEmail(n){return n in m.InboundSmtpEndpoints}static createEmailLambdaRole(n){let{slug:i,environment:s,s3BucketArn:o,sesIdentityArn:c}=n,l=r({slug:i,environment:s,resourceType:"email-lambda-role"}),u=t(l),h=t(`${l}-policy`),y={Type:"AWS::IAM::Role",Properties:{RoleName:l,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s}]}},f=[{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[o,`${o}/*`]}];if(c)f.push({Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail"],Resource:c});let b={Type:"AWS::IAM::Policy",Properties:{PolicyName:`${l}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:f},Roles:[k.Ref(u)]}};return{role:y,policy:b,roleLogicalId:u,policyLogicalId:h}}static createOutboundEmailLambda(n){let{slug:i,environment:s,roleArn:o,domain:c,configurationSetName:l,timeout:u=30,memorySize:h=256}=n,y=r({slug:i,environment:s,resourceType:"outbound-email"}),f=t(y);return{function:{Type:"AWS::Lambda::Function",Properties:{FunctionName:y,Runtime:"nodejs20.x",Handler:"index.handler",Role:o,Timeout:u,MemorySize:h,Environment:{Variables:{DOMAIN:c,CONFIGURATION_SET:l||""}},Code:{ZipFile:m.LambdaCode.outboundEmail},Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:s},{Key:"Purpose",Value:"OutboundEmail"}]}},logicalId:f}}static createInboundEmailLambda(n){let{slug:i,environment:s,roleArn:o,s3BucketName:c,organizedPrefix:l="organized/",timeout:u=60,memorySize:h=512}=n,y=r({slug:i,environment:s,resourceType:"inbound-email"}),f=t(y),b=t(`${y}-permission`),C={Type:"AWS::Lambda::Function",Properties:{FunctionName:y,Runtime:"nodejs20.x",Handler:"index.handler",Role:o,Timeout:u,MemorySize:h,Environment:{Variables:{S3_BUCKET:c,ORGANIZED_PREFIX:l}},Code:{ZipFile:m.LambdaCode.inboundEmail},Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:s},{Key:"Purpose",Value:"InboundEmail"}]}},T={Type:"AWS::Lambda::Permission",Properties:{FunctionName:k.Ref(f),Action:"lambda:InvokeFunction",Principal:"ses.amazonaws.com",SourceAccount:k.Ref("AWS::AccountId")}};return{function:C,permission:T,logicalId:f,permissionLogicalId:b}}static createEmailConversionLambda(n){let{slug:i,environment:s,roleArn:o,s3BucketName:c,convertedPrefix:l="converted/",timeout:u=60,memorySize:h=512}=n,y=r({slug:i,environment:s,resourceType:"email-conversion"}),f=t(y);return{function:{Type:"AWS::Lambda::Function",Properties:{FunctionName:y,Runtime:"nodejs20.x",Handler:"index.handler",Role:o,Timeout:u,MemorySize:h,Environment:{Variables:{S3_BUCKET:c,CONVERTED_PREFIX:l}},Code:{ZipFile:m.LambdaCode.emailConversion},Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:s},{Key:"Purpose",Value:"EmailConversion"}]}},logicalId:f}}static createEmailBucketNotification(n){let{lambdaArn:i,prefix:s="inbound/",suffix:o,events:c}=n,l=c??["s3:ObjectCreated:*"],u={};if(s||o){if(u.S3Key={Rules:[]},s)u.S3Key.Rules.push({Name:"prefix",Value:s});if(o)u.S3Key.Rules.push({Name:"suffix",Value:o})}return{notificationConfiguration:{LambdaConfigurations:[{Event:l[0],Function:i,Filter:Object.keys(u).length>0?u:void 0}]}}}static createS3LambdaPermission(n){let{slug:i,environment:s,lambdaLogicalId:o,s3BucketArn:c}=n,l=r({slug:i,environment:s,resourceType:"s3-lambda-permission"}),u=t(l);return{permission:{Type:"AWS::Lambda::Permission",Properties:{FunctionName:k.Ref(o),Action:"lambda:InvokeFunction",Principal:"s3.amazonaws.com",SourceArn:c}},logicalId:u}}static createEmailProcessingStack(n){let{slug:i,environment:s,domain:o,s3BucketName:c,s3BucketArn:l,configurationSetName:u,enableInbound:h=!0,enableConversion:y=!0}=n,f={},{role:b,policy:C,roleLogicalId:T,policyLogicalId:w}=m.createEmailLambdaRole({slug:i,environment:s,s3BucketArn:l,sesIdentityArn:`arn:aws:ses:*:*:identity/${o}`});f[T]=b,f[w]=C;let{function:E,logicalId:I}=m.createOutboundEmailLambda({slug:i,environment:s,roleArn:k.GetAtt(T,"Arn"),domain:o,configurationSetName:u});f[I]=E;let N={roleLogicalId:T,outboundLambdaLogicalId:I};if(h){let{function:D,permission:B,logicalId:R,permissionLogicalId:W}=m.createInboundEmailLambda({slug:i,environment:s,roleArn:k.GetAtt(T,"Arn"),s3BucketName:c});f[R]=D,f[W]=B;let{permission:_,logicalId:j}=m.createS3LambdaPermission({slug:i,environment:s,lambdaLogicalId:R,s3BucketArn:l});f[j]=_,N.inboundLambdaLogicalId=R}if(y){let{function:D,logicalId:B}=m.createEmailConversionLambda({slug:i,environment:s,roleArn:k.GetAtt(T,"Arn"),s3BucketName:c});f[B]=D,N.conversionLambdaLogicalId=B}return{resources:f,outputs:N}}static LambdaCode={outboundEmail:`
623
+ `}class ze{static createFileSystem(n){let{slug:i,environment:s,encrypted:o=!0,kmsKeyId:c,performanceMode:l="generalPurpose",throughputMode:u="bursting",provisionedThroughput:h,enableBackup:y=!0}=n,f=r({slug:i,environment:s,resourceType:"efs"}),b=t(f),C={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:o,PerformanceMode:l,ThroughputMode:u,FileSystemTags:[{Key:"Name",Value:f},{Key:"Environment",Value:s}]}};if(c)C.Properties.KmsKeyId=c;if(u==="provisioned"&&h)C.Properties.ProvisionedThroughputInMibps=h;if(y)C.Properties.BackupPolicy={Status:"ENABLED"};return{fileSystem:C,logicalId:b}}static createMountTarget(n,i){let{slug:s,environment:o,subnetId:c,securityGroups:l,ipAddress:u}=i,h=r({slug:s,environment:o,resourceType:"efs-mt"}),y=t(`${h}-${c}`),f={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:k.Ref(n),SubnetId:c,SecurityGroups:l}};if(u)f.Properties.IpAddress=u;return{mountTarget:f,logicalId:y}}static createAccessPoint(n,i){let{slug:s,environment:o,path:c="/",uid:l="1000",gid:u="1000",permissions:h="755"}=i,y=r({slug:s,environment:o,resourceType:"efs-ap"}),f=t(`${y}-${c.replace(/\//g,"-")}`);return{accessPoint:{Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:k.Ref(n),PosixUser:{Uid:l,Gid:u},RootDirectory:{Path:c,CreationInfo:{OwnerUid:l,OwnerGid:u,Permissions:h}},AccessPointTags:[{Key:"Name",Value:`${y}-${c}`},{Key:"Environment",Value:o}]}},logicalId:f}}static setLifecyclePolicy(n,i){let{transitionToIA:s,transitionToPrimary:o=!1}=i;if(!n.Properties)n.Properties={};if(n.Properties.LifecyclePolicies=[],s){let c=`AFTER_${s}_DAYS`;n.Properties.LifecyclePolicies.push({TransitionToIA:c})}if(o)n.Properties.LifecyclePolicies.push({TransitionToPrimaryStorageClass:"AFTER_1_ACCESS"});return n}static enableBackup(n){if(!n.Properties)n.Properties={};return n.Properties.BackupPolicy={Status:"ENABLED"},n}static disableBackup(n){if(!n.Properties)n.Properties={};return n.Properties.BackupPolicy={Status:"DISABLED"},n}static setProvisionedThroughput(n,i){if(!n.Properties)n.Properties={};return n.Properties.ThroughputMode="provisioned",n.Properties.ProvisionedThroughputInMibps=i,n}static setElasticThroughput(n){if(!n.Properties)n.Properties={};return n.Properties.ThroughputMode="elastic",n}static enableMaxIO(n){if(!n.Properties)n.Properties={};return n.Properties.PerformanceMode="maxIO",n}static createEfsSecurityGroup(n){let{slug:i,environment:s,vpcId:o,sourceSecurityGroupIds:c=[],sourceCidrBlocks:l=[],description:u}=n,h=r({slug:i,environment:s,resourceType:"efs-sg"}),y=t(h),f=[];for(let b of c)f.push({IpProtocol:"tcp",FromPort:2049,ToPort:2049,SourceSecurityGroupId:b,Description:"NFS from security group"});for(let b of l)f.push({IpProtocol:"tcp",FromPort:2049,ToPort:2049,CidrIp:b,Description:"NFS from CIDR block"});return{securityGroup:{Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:h,GroupDescription:u||`Security group for EFS mount targets - ${i} ${s}`,VpcId:o,SecurityGroupIngress:f,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}},logicalId:y}}static createMultiAzMountTargets(n,i){let{slug:s,environment:o,subnetIds:c,securityGroupId:l}=i,u=[],h=[];for(let y=0;y<c.length;y++){let f=c[y],b=r({slug:s,environment:o,resourceType:"efs-mt"}),C=t(`${b}-az${y+1}`),T={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:k.Ref(n),SubnetId:f,SecurityGroups:[l]}};u.push(T),h.push(C)}return{mountTargets:u,logicalIds:h}}static createCompleteFileSystem(n){let{slug:i,environment:s,vpcId:o,subnetIds:c,sourceSecurityGroupIds:l=[],encrypted:u=!0,performanceMode:h="generalPurpose",throughputMode:y="elastic",enableBackup:f=!0,transitionToIA:b}=n,C={},{fileSystem:T,logicalId:w}=ze.createFileSystem({slug:i,environment:s,encrypted:u,performanceMode:h,throughputMode:y,enableBackup:f});if(b)ze.setLifecyclePolicy(T,{transitionToIA:b,transitionToPrimary:!0});C[w]=T;let{securityGroup:E,logicalId:I}=ze.createEfsSecurityGroup({slug:i,environment:s,vpcId:o,sourceSecurityGroupIds:l});C[I]=E;let{mountTargets:N,logicalIds:D}=ze.createMultiAzMountTargets(w,{slug:i,environment:s,subnetIds:c,securityGroupId:k.Ref(I)});for(let x=0;x<N.length;x++)C[D[x]]=N[x];return{resources:C,outputs:{fileSystemId:w,securityGroupId:I,mountTargetIds:D}}}}class m{static verifyDomain(n){let{domain:i,slug:s,environment:o,enableDkim:c=!0,dkimKeyLength:l="RSA_2048_BIT"}=n,u=r({slug:s,environment:o,resourceType:"ses-identity"}),h=t(`${u}-${i.replace(/\./g,"")}`),y={Type:"AWS::SES::EmailIdentity",Properties:{EmailIdentity:i,FeedbackAttributes:{EmailForwardingEnabled:!0}}};if(c)y.Properties.DkimSigningAttributes={NextSigningKeyLength:l};return{emailIdentity:y,logicalId:h}}static createDkimRecords(n,i,s){let o=[];for(let c=0;c<i.length;c++){let l=i[c],u=t(`dkim-${n.replace(/\./g,"")}-${c+1}`),h={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:s,Name:`${l}._domainkey.${n}`,Type:"CNAME",TTL:1800,ResourceRecords:[`${l}.dkim.amazonses.com`]}};o.push({record:h,logicalId:u})}return o}static createConfigurationSet(n){let{slug:i,environment:s,name:o,reputationMetrics:c=!0,sendingEnabled:l=!0,suppressBounces:u=!0,suppressComplaints:h=!0}=n,y=o||r({slug:i,environment:s,resourceType:"ses-config"}),f=t(y),b=[];if(u)b.push("BOUNCE");if(h)b.push("COMPLAINT");return{configurationSet:{Type:"AWS::SES::ConfigurationSet",Properties:{Name:y,ReputationOptions:{ReputationMetricsEnabled:c},SendingOptions:{SendingEnabled:l},SuppressionOptions:{SuppressedReasons:b}}},logicalId:f}}static createReceiptRuleSet(n){let{slug:i,environment:s,name:o}=n,c=o||r({slug:i,environment:s,resourceType:"ses-ruleset"}),l=t(c);return{ruleSet:{Type:"AWS::SES::ReceiptRuleSet",Properties:{RuleSetName:c}},logicalId:l}}static createReceiptRule(n,i){let{slug:s,environment:o,ruleSetName:c,recipients:l,enabled:u=!0,scanEnabled:h=!0,tlsPolicy:y="Require",s3Action:f,lambdaAction:b,snsAction:C}=i,T=r({slug:s,environment:o,resourceType:"ses-rule"}),w=t(T),E=[];if(f)E.push({S3Action:{BucketName:f.bucketName,ObjectKeyPrefix:f.prefix,KmsKeyArn:f.kmsKeyArn}});if(b)E.push({LambdaAction:{FunctionArn:b.functionArn,InvocationType:b.invocationType||"Event"}});if(C)E.push({SNSAction:{TopicArn:C.topicArn,Encoding:C.encoding||"UTF-8"}});return{receiptRule:{Type:"AWS::SES::ReceiptRule",Properties:{RuleSetName:c,Rule:{Name:T,Enabled:u,ScanEnabled:h,TlsPolicy:y,Recipients:l,Actions:E.length>0?E:void 0}}},logicalId:w}}static createMxRecord(n,i,s){let o=t(`mx-${n.replace(/\./g,"")}`);return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:n,Type:"MX",TTL:300,ResourceRecords:[`10 inbound-smtp.${s}.amazonaws.com`]}},logicalId:o}}static createVerificationRecord(n,i,s){let o=t(`verification-${n.replace(/\./g,"")}`);return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:s,Name:`_amazonses.${n}`,Type:"TXT",TTL:1800,ResourceRecords:[`"${i}"`]}},logicalId:o}}static getSmtpEndpoint(n){return`email-smtp.${n}.amazonaws.com`}static SmtpPorts={TLS:587,SSL:465,Unencrypted:25};static createSpfRecord(n,i,s){let{includeDomains:o=[],softFail:c=!1}=s||{},l=t(`spf-${n.replace(/\./g,"")}`),u="v=spf1 include:amazonses.com";for(let h of o)u+=` include:${h}`;return u+=c?" ~all":" -all",{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:n,Type:"TXT",TTL:300,ResourceRecords:[`"${u}"`]}},logicalId:l}}static createDmarcRecord(n,i,s){let{policy:o="none",subdomainPolicy:c,percentage:l=100,reportingEmail:u,forensicEmail:h}=s||{},y=t(`dmarc-${n.replace(/\./g,"")}`),f=`v=DMARC1; p=${o}; pct=${l}`;if(c)f+=`; sp=${c}`;if(u)f+=`; rua=mailto:${u}`;if(h)f+=`; ruf=mailto:${h}`;return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:`_dmarc.${n}`,Type:"TXT",TTL:300,ResourceRecords:[`"${f}"`]}},logicalId:y}}static createInboundEmailSetup(n){let{slug:i,environment:s,domain:o,s3BucketName:c,s3KeyPrefix:l="inbound/",region:u,hostedZoneId:h,lambdaFunctionArn:y,snsTopicArn:f}=n,b={},{ruleSet:C,logicalId:T}=m.createReceiptRuleSet({slug:i,environment:s});b[T]=C;let{receiptRule:w,logicalId:E}=m.createReceiptRule(T,{slug:i,environment:s,ruleSetName:C.Properties.RuleSetName||`${i}-${s}-receipt-rule-set`,recipients:[o],s3Action:{bucketName:c,prefix:l},lambdaAction:y?{functionArn:y,invocationType:"Event"}:void 0,snsAction:f?{topicArn:f}:void 0});b[E]=w;let{record:I,logicalId:N}=m.createMxRecord(o,h,u);return b[N]=I,{resources:b,outputs:{ruleSetLogicalId:T,ruleLogicalId:E,mxRecordLogicalId:N}}}static createCompleteDomainSetup(n){let{slug:i,environment:s,domain:o,hostedZoneId:c,region:l,enableInbound:u=!1,inboundS3Bucket:h,dmarcReportingEmail:y}=n,f={},{emailIdentity:b,logicalId:C}=m.verifyDomain({domain:o,slug:i,environment:s});f[C]=b;let{configurationSet:T,logicalId:w}=m.createConfigurationSet({slug:i,environment:s});f[w]=T;let{record:E,logicalId:I}=m.createSpfRecord(o,c);f[I]=E;let{record:N,logicalId:D}=m.createDmarcRecord(o,c,{policy:"none",reportingEmail:y||`dmarc-reports@${o}`});if(f[D]=N,u&&h){let x=m.createInboundEmailSetup({slug:i,environment:s,domain:o,s3BucketName:h,region:l,hostedZoneId:c});Object.assign(f,x.resources)}return{resources:f,outputs:{identityLogicalId:C,configSetLogicalId:w}}}static InboundSmtpEndpoints={"us-east-1":"inbound-smtp.us-east-1.amazonaws.com","us-west-2":"inbound-smtp.us-west-2.amazonaws.com","eu-west-1":"inbound-smtp.eu-west-1.amazonaws.com"};static supportsInboundEmail(n){return n in m.InboundSmtpEndpoints}static createEmailLambdaRole(n){let{slug:i,environment:s,s3BucketArn:o,sesIdentityArn:c}=n,l=r({slug:i,environment:s,resourceType:"email-lambda-role"}),u=t(l),h=t(`${l}-policy`),y={Type:"AWS::IAM::Role",Properties:{RoleName:l,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s}]}},f=[{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[o,`${o}/*`]}];if(c)f.push({Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail"],Resource:c});let b={Type:"AWS::IAM::Policy",Properties:{PolicyName:`${l}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:f},Roles:[k.Ref(u)]}};return{role:y,policy:b,roleLogicalId:u,policyLogicalId:h}}static createOutboundEmailLambda(n){let{slug:i,environment:s,roleArn:o,domain:c,configurationSetName:l,timeout:u=30,memorySize:h=256}=n,y=r({slug:i,environment:s,resourceType:"outbound-email"}),f=t(y);return{function:{Type:"AWS::Lambda::Function",Properties:{FunctionName:y,Runtime:"nodejs20.x",Handler:"index.handler",Role:o,Timeout:u,MemorySize:h,Environment:{Variables:{DOMAIN:c,CONFIGURATION_SET:l||""}},Code:{ZipFile:m.LambdaCode.outboundEmail},Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:s},{Key:"Purpose",Value:"OutboundEmail"}]}},logicalId:f}}static createInboundEmailLambda(n){let{slug:i,environment:s,roleArn:o,s3BucketName:c,organizedPrefix:l="organized/",timeout:u=60,memorySize:h=512}=n,y=r({slug:i,environment:s,resourceType:"inbound-email"}),f=t(y),b=t(`${y}-permission`),C={Type:"AWS::Lambda::Function",Properties:{FunctionName:y,Runtime:"nodejs20.x",Handler:"index.handler",Role:o,Timeout:u,MemorySize:h,Environment:{Variables:{S3_BUCKET:c,ORGANIZED_PREFIX:l}},Code:{ZipFile:m.LambdaCode.inboundEmail},Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:s},{Key:"Purpose",Value:"InboundEmail"}]}},T={Type:"AWS::Lambda::Permission",Properties:{FunctionName:k.Ref(f),Action:"lambda:InvokeFunction",Principal:"ses.amazonaws.com",SourceAccount:k.Ref("AWS::AccountId")}};return{function:C,permission:T,logicalId:f,permissionLogicalId:b}}static createEmailConversionLambda(n){let{slug:i,environment:s,roleArn:o,s3BucketName:c,convertedPrefix:l="converted/",timeout:u=60,memorySize:h=512}=n,y=r({slug:i,environment:s,resourceType:"email-conversion"}),f=t(y);return{function:{Type:"AWS::Lambda::Function",Properties:{FunctionName:y,Runtime:"nodejs20.x",Handler:"index.handler",Role:o,Timeout:u,MemorySize:h,Environment:{Variables:{S3_BUCKET:c,CONVERTED_PREFIX:l}},Code:{ZipFile:m.LambdaCode.emailConversion},Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:s},{Key:"Purpose",Value:"EmailConversion"}]}},logicalId:f}}static createEmailBucketNotification(n){let{lambdaArn:i,prefix:s="inbound/",suffix:o,events:c}=n,l=c??["s3:ObjectCreated:*"],u={};if(s||o){if(u.S3Key={Rules:[]},s)u.S3Key.Rules.push({Name:"prefix",Value:s});if(o)u.S3Key.Rules.push({Name:"suffix",Value:o})}return{notificationConfiguration:{LambdaConfigurations:[{Event:l[0],Function:i,Filter:Object.keys(u).length>0?u:void 0}]}}}static createS3LambdaPermission(n){let{slug:i,environment:s,lambdaLogicalId:o,s3BucketArn:c}=n,l=r({slug:i,environment:s,resourceType:"s3-lambda-permission"}),u=t(l);return{permission:{Type:"AWS::Lambda::Permission",Properties:{FunctionName:k.Ref(o),Action:"lambda:InvokeFunction",Principal:"s3.amazonaws.com",SourceArn:c}},logicalId:u}}static createEmailProcessingStack(n){let{slug:i,environment:s,domain:o,s3BucketName:c,s3BucketArn:l,configurationSetName:u,enableInbound:h=!0,enableConversion:y=!0}=n,f={},{role:b,policy:C,roleLogicalId:T,policyLogicalId:w}=m.createEmailLambdaRole({slug:i,environment:s,s3BucketArn:l,sesIdentityArn:`arn:aws:ses:*:*:identity/${o}`});f[T]=b,f[w]=C;let{function:E,logicalId:I}=m.createOutboundEmailLambda({slug:i,environment:s,roleArn:k.GetAtt(T,"Arn"),domain:o,configurationSetName:u});f[I]=E;let N={roleLogicalId:T,outboundLambdaLogicalId:I};if(h){let{function:D,permission:x,logicalId:R,permissionLogicalId:_}=m.createInboundEmailLambda({slug:i,environment:s,roleArn:k.GetAtt(T,"Arn"),s3BucketName:c});f[R]=D,f[_]=x;let{permission:B,logicalId:W}=m.createS3LambdaPermission({slug:i,environment:s,lambdaLogicalId:R,s3BucketArn:l});f[W]=B,N.inboundLambdaLogicalId=R}if(y){let{function:D,logicalId:x}=m.createEmailConversionLambda({slug:i,environment:s,roleArn:k.GetAtt(T,"Arn"),s3BucketName:c});f[x]=D,N.conversionLambdaLogicalId=x}return{resources:f,outputs:N}}static LambdaCode={outboundEmail:`
624
624
  const { SESClient, SendRawEmailCommand } = require('@aws-sdk/client-ses');
625
625
  const ses = new SESClient({});
626
626
 
@@ -1166,7 +1166,7 @@ else if (encoding === 'quoted-printable') {
1166
1166
 
1167
1167
  return content;
1168
1168
  }
1169
- `}}var sA={};We(sA,{default:()=>Sr,handler:()=>Da});var Da=`
1169
+ `}}var aA={};Ge(aA,{default:()=>Sr,handler:()=>Da});var Da=`
1170
1170
  const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');
1171
1171
  const { DynamoDBClient, PutItemCommand } = require('@aws-sdk/client-dynamodb');
1172
1172
 
@@ -1658,7 +1658,7 @@ catch (error) {
1658
1658
 
1659
1659
  return { statusCode: 200, body: 'OK' };
1660
1660
  };
1661
- `;class je{static LambdaCode={incomingCall:Da,voicemail:Ar,missedCall:br};static createConnectInstance(n){let{slug:i,environment:s,instanceAlias:o,inboundCallsEnabled:c=!0,outboundCallsEnabled:l=!0}=n;return{[`${i}ConnectInstance`]:{Type:"AWS::Connect::Instance",Properties:{InstanceAlias:o,IdentityManagementType:"CONNECT_MANAGED",Attributes:{InboundCalls:c,OutboundCalls:l,ContactflowLogs:!0,ContactLens:!0,AutoResolveBestVoices:!0,UseCustomTTSVoices:!1,EarlyMedia:!0}}}}}static createHoursOfOperation(n){return{[`${n.slug}HoursOfOperation`]:{Type:"AWS::Connect::HoursOfOperation",Properties:{InstanceArn:n.instanceArn,Name:n.name,TimeZone:n.timezone,Config:n.schedule.map((i)=>({Day:i.day,StartTime:{Hours:i.startHour,Minutes:i.startMinute},EndTime:{Hours:i.endHour,Minutes:i.endMinute}}))}}}}static createQueue(n){return{[`${n.slug}Queue`]:{Type:"AWS::Connect::Queue",Properties:{InstanceArn:n.instanceArn,Name:n.name,HoursOfOperationArn:n.hoursOfOperationArn,MaxContacts:n.maxContacts||10}}}}static createContactFlow(n){return{[`${n.slug}ContactFlow`]:{Type:"AWS::Connect::ContactFlow",Properties:{InstanceArn:n.instanceArn,Name:n.name,Type:n.type,Content:n.content}}}}static createBasicIvrFlow(n){let i={Version:"2019-10-30",StartAction:"greeting",Actions:[{Identifier:"greeting",Type:"MessageParticipant",Parameters:{Text:n.greeting},Transitions:{NextAction:"transfer_to_queue",Errors:[{NextAction:"disconnect"}]}},{Identifier:"transfer_to_queue",Type:"TransferToQueue",Parameters:{QueueId:n.queueArn},Transitions:{NextAction:n.voicemailLambdaArn?"voicemail":"disconnect",Errors:[{NextAction:"disconnect"}]}},...n.voicemailLambdaArn?[{Identifier:"voicemail",Type:"InvokeLambdaFunction",Parameters:{LambdaFunctionARN:n.voicemailLambdaArn},Transitions:{NextAction:"disconnect",Errors:[{NextAction:"disconnect"}]}}]:[],{Identifier:"disconnect",Type:"DisconnectParticipant",Parameters:{},Transitions:{}}]};return JSON.stringify(i)}static createPhoneLambdaRole(n){return{[`${n.slug}PhoneLambdaRole`]:{Type:"AWS::IAM::Role",Properties:{RoleName:`${n.slug}-phone-lambda-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],Policies:[{PolicyName:"PhoneLambdaPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:GetItem"],Resource:"*"},{Effect:"Allow",Action:["sns:Publish"],Resource:"*"},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject"],Resource:"*"},{Effect:"Allow",Action:["transcribe:StartTranscriptionJob","transcribe:GetTranscriptionJob"],Resource:"*"},{Effect:"Allow",Action:["connect:*"],Resource:"*"}]}}]}}}}static createIncomingCallLambda(n){return{[`${n.slug}IncomingCallLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-incoming-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:je.LambdaCode.incomingCall},Environment:{Variables:{NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",CALL_LOG_TABLE:n.callLogTable||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createVoicemailLambda(n){return{[`${n.slug}VoicemailLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-voicemail`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:300,MemorySize:512,Code:{ZipFile:je.LambdaCode.voicemail},Environment:{Variables:{VOICEMAIL_BUCKET:n.voicemailBucket,NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",CALL_LOG_TABLE:n.callLogTable||"",TRANSCRIPTION_ENABLED:n.transcriptionEnabled?"true":"false"}}}}}}static createMissedCallLambda(n){return{[`${n.slug}MissedCallLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-missed-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:je.LambdaCode.missedCall},Environment:{Variables:{NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",CALL_LOG_TABLE:n.callLogTable||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createCallLogTable(n){return{[`${n.slug}CallLogTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-call-log`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"contactId",AttributeType:"S"}],KeySchema:[{AttributeName:"contactId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createCompleteSetup(n){let i={},s={};Object.assign(i,je.createPhoneLambdaRole({slug:n.slug})),Object.assign(i,je.createCallLogTable({slug:n.slug})),i[`${n.slug}PhoneNotificationTopic`]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${n.slug}-phone-notifications`}},i[`${n.slug}VoicemailBucket`]={Type:"AWS::S3::Bucket",Properties:{BucketName:`${n.slug}-voicemails`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldVoicemails",Status:"Enabled",ExpirationInDays:90}]}}};let o={"Fn::GetAtt":[`${n.slug}PhoneLambdaRole`,"Arn"]},c={Ref:`${n.slug}PhoneNotificationTopic`},l={Ref:`${n.slug}CallLogTable`},u={Ref:`${n.slug}VoicemailBucket`};if(Object.assign(i,je.createIncomingCallLambda({slug:n.slug,roleArn:o,notificationTopicArn:c,callLogTable:l,webhookUrl:n.webhookUrl})),n.voicemailEnabled!==!1)Object.assign(i,je.createVoicemailLambda({slug:n.slug,roleArn:o,voicemailBucket:u,notificationTopicArn:c,callLogTable:l,transcriptionEnabled:n.transcriptionEnabled}));return Object.assign(i,je.createMissedCallLambda({slug:n.slug,roleArn:o,notificationTopicArn:c,callLogTable:l,webhookUrl:n.webhookUrl})),s[`${n.slug}PhoneNotificationTopicArn`]={Description:"Phone notification topic ARN",Value:{Ref:`${n.slug}PhoneNotificationTopic`}},s[`${n.slug}CallLogTableName`]={Description:"Call log table name",Value:{Ref:`${n.slug}CallLogTable`}},s[`${n.slug}VoicemailBucketName`]={Description:"Voicemail bucket name",Value:{Ref:`${n.slug}VoicemailBucket`}},{resources:i,outputs:s}}}class F{static createQueue(n){let{slug:i,environment:s,name:o,delaySeconds:c=0,visibilityTimeout:l=30,messageRetentionPeriod:u=345600,maxMessageSize:h=262144,receiveMessageWaitTime:y=0,fifo:f=!1,contentBasedDeduplication:b=!1,encrypted:C=!0,kmsKeyId:T}=n,w=o||r({slug:i,environment:s,resourceType:"queue"}),E=f?`${w}.fifo`:w,I=t(w),N={Type:"AWS::SQS::Queue",Properties:{QueueName:E,DelaySeconds:c,MaximumMessageSize:h,MessageRetentionPeriod:u,ReceiveMessageWaitTimeSeconds:y,VisibilityTimeout:l,Tags:[{Key:"Name",Value:E},{Key:"Environment",Value:s}]}};if(f)N.Properties.FifoQueue=!0,N.Properties.ContentBasedDeduplication=b;if(C)if(T)N.Properties.KmsMasterKeyId=T;else N.Properties.SqsManagedSseEnabled=!0;return{queue:N,logicalId:I}}static createDeadLetterQueue(n,i){let{slug:s,environment:o,maxReceiveCount:c=3}=i,l=r({slug:s,environment:o,resourceType:"dlq"}),u=t(l),h={Type:"AWS::SQS::Queue",Properties:{QueueName:l,MessageRetentionPeriod:1209600,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:o},{Key:"Type",Value:"DeadLetterQueue"}]}},y={Type:"AWS::SQS::Queue",Properties:{RedrivePolicy:{deadLetterTargetArn:k.GetAtt(u,"Arn"),maxReceiveCount:c}}};return{deadLetterQueue:h,updatedSourceQueue:y,deadLetterLogicalId:u}}static createSchedule(n,i){let{slug:s,environment:o,name:c,description:l,enabled:u=!0}=i,h=c||r({slug:s,environment:o,resourceType:"schedule"}),y=t(h);return{rule:{Type:"AWS::Events::Rule",Properties:{Name:h,Description:l,ScheduleExpression:n,State:u?"ENABLED":"DISABLED",Targets:[]}},logicalId:y}}static scheduleEcsTask(n,i,s){let{slug:o,environment:c,name:l,description:u,enabled:h=!0,taskDefinitionArn:y,clusterArn:f,subnets:b,securityGroups:C=[],assignPublicIp:T=!1,taskCount:w=1,containerOverrides:E}=s,I=l||r({slug:o,environment:c,resourceType:"ecs-schedule"}),N=t(I),D={Id:"1",Arn:f,RoleArn:i,EcsParameters:{TaskDefinitionArn:y,TaskCount:w,LaunchType:"FARGATE",NetworkConfiguration:{awsvpcConfiguration:{Subnets:b,SecurityGroups:C,AssignPublicIp:T?"ENABLED":"DISABLED"}},PlatformVersion:"LATEST"}};if(E&&E.length>0)D.Input=JSON.stringify({containerOverrides:E});return{rule:{Type:"AWS::Events::Rule",Properties:{Name:I,Description:u||`Scheduled ECS task: ${y}`,ScheduleExpression:n,State:h?"ENABLED":"DISABLED",Targets:[D]}},logicalId:N}}static scheduleLambda(n,i){let{slug:s,environment:o,name:c,description:l,enabled:u=!0,functionArn:h,input:y}=i,f=c||r({slug:s,environment:o,resourceType:"lambda-schedule"}),b=t(f),C={Id:"1",Arn:h};if(y)C.Input=JSON.stringify(y);return{rule:{Type:"AWS::Events::Rule",Properties:{Name:f,Description:l||`Scheduled Lambda: ${h}`,ScheduleExpression:n,State:u?"ENABLED":"DISABLED",Targets:[C]}},logicalId:b}}static scheduleSqsMessage(n,i){let{slug:s,environment:o,name:c,description:l,enabled:u=!0,queueArn:h,messageGroupId:y}=i,f=c||r({slug:s,environment:o,resourceType:"sqs-schedule"}),b=t(f),C={Id:"1",Arn:h};if(y)C.SqsParameters={MessageGroupId:y};return{rule:{Type:"AWS::Events::Rule",Properties:{Name:f,Description:l||`Scheduled SQS message: ${h}`,ScheduleExpression:n,State:u?"ENABLED":"DISABLED",Targets:[C]}},logicalId:b}}static addTarget(n,i){if(!n.Properties.Targets)n.Properties.Targets=[];let s={Id:i.id,Arn:i.arn};if(i.roleArn)s.RoleArn=i.roleArn;if(i.input)s.Input=JSON.stringify(i.input);return n.Properties.Targets.push(s),n}static toCronExpression(n){if(n.startsWith("cron(")||n.startsWith("rate("))return n;return`cron(${n})`}static rateExpression(n,i){return`rate(${n} ${i})`}static CronExpressions={EveryMinute:"cron(* * * * ? *)",Every5Minutes:"cron(*/5 * * * ? *)",Every15Minutes:"cron(*/15 * * * ? *)",Every30Minutes:"cron(*/30 * * * ? *)",Hourly:"cron(0 * * * ? *)",Daily:"cron(0 0 * * ? *)",DailyAt9AM:"cron(0 9 * * ? *)",DailyAtMidnight:"cron(0 0 * * ? *)",Weekly:"cron(0 0 ? * SUN *)",Monthly:"cron(0 0 1 * ? *)"};static RateExpressions={Every1Minute:"rate(1 minute)",Every5Minutes:"rate(5 minutes)",Every10Minutes:"rate(10 minutes)",Every15Minutes:"rate(15 minutes)",Every30Minutes:"rate(30 minutes)",Every1Hour:"rate(1 hour)",Every6Hours:"rate(6 hours)",Every12Hours:"rate(12 hours)",Every1Day:"rate(1 day)"};static rateStringToExpression(n){let i=n.toLowerCase().trim(),s=i.match(/^every\s+(\d+)\s+(minute|minutes|hour|hours|day|days)$/i);if(s){let f=parseInt(s[1],10),b=s[2].toLowerCase(),C=b.endsWith("s")&&f===1?b.slice(0,-1):b,T=!b.endsWith("s")&&f>1?`${b}s`:b;return`rate(${f} ${f===1?C:T})`}let o=i.match(/^every\s+(minute|hour|day)$/i);if(o)return`rate(1 ${o[1]})`;let c={"every minute":"rate(1 minute)","every hour":"rate(1 hour)","every day":"rate(1 day)",hourly:"cron(0 * * * ? *)",daily:"cron(0 0 * * ? *)","daily at midnight":"cron(0 0 * * ? *)",weekly:"cron(0 0 ? * SUN *)",monthly:"cron(0 0 1 * ? *)",yearly:"cron(0 0 1 1 ? *)"};if(c[i])return c[i];let l=i.match(/^daily\s+at\s+(\d{1,2})\s*(am|pm)?$/i);if(l){let f=parseInt(l[1],10),b=l[2]?.toLowerCase();if(b==="pm"&&f!==12)f+=12;else if(b==="am"&&f===12)f=0;return`cron(0 ${f} * * ? *)`}let u=i.match(/^at\s+(\d{1,2}):(\d{2})$/i);if(u){let f=parseInt(u[1],10);return`cron(${parseInt(u[2],10)} ${f} * * ? *)`}let h={monday:"MON",tuesday:"TUE",wednesday:"WED",thursday:"THU",friday:"FRI",saturday:"SAT",sunday:"SUN"},y=i.match(/^every\s+(monday|tuesday|wednesday|thursday|friday|saturday|sunday)$/i);if(y)return`cron(0 0 ? * ${h[y[1].toLowerCase()]} *)`;return F.toCronExpression(n)}static JobConfig={create:(n)=>{let{name:i,handler:s,retries:o=3,backoff:c="exponential",backoffDelay:l=1000,maxDelay:u=30000,timeout:h=60000,jitter:y=!0}=n;return{name:i,handler:s,retries:o,backoff:c,backoffDelay:l,maxDelay:u,timeout:h,jitter:y}},calculateDelay:(n,i)=>{let{backoff:s,backoffDelay:o,maxDelay:c,jitter:l}=i,u;switch(s){case"linear":u=o*n;break;case"exponential":u=o*2**(n-1);break;case"fixed":default:u=o}if(u=Math.min(u,c||Number.MAX_SAFE_INTEGER),l){let h=u*0.25*Math.random();u+=h}return Math.floor(u)},presets:{fastRetry:{retries:5,backoff:"exponential",backoffDelay:100,maxDelay:5000,jitter:!0},standard:{retries:3,backoff:"exponential",backoffDelay:1000,maxDelay:30000,jitter:!0},longRunning:{retries:2,backoff:"exponential",backoffDelay:5000,maxDelay:60000,timeout:300000,jitter:!0},critical:{retries:10,backoff:"exponential",backoffDelay:500,maxDelay:60000,jitter:!0},noRetry:{retries:0,backoff:"fixed",backoffDelay:0,maxDelay:0,jitter:!1}}};static createJobContainerOverride(n){let{containerName:i,jobClass:s,jobData:o,environment:c={}}=n,l=[{name:"JOB_CLASS",value:s}];if(o)l.push({name:"JOB_DATA",value:JSON.stringify(o)});for(let[u,h]of Object.entries(c))l.push({name:u,value:h});return{name:i,command:["bun","run","app/Jobs/runner.ts"],environment:l}}static createScheduledJob(n){let{slug:i,environment:s,schedule:o,jobClass:c,jobData:l,taskDefinitionArn:u,clusterArn:h,subnets:y,securityGroups:f=[],roleArn:b,containerName:C="app"}=n,T=F.rateStringToExpression(o),w=F.createJobContainerOverride({containerName:C,jobClass:c,jobData:l});return F.scheduleEcsTask(T,b,{slug:i,environment:s,name:`${i}-${c.toLowerCase().replace(/[^a-z0-9]/g,"-")}`,description:`Scheduled job: ${c}`,taskDefinitionArn:u,clusterArn:h,subnets:y,securityGroups:f,containerOverrides:[w]})}static QueuePresets={highThroughput:(n,i)=>F.createQueue({slug:n,environment:i,visibilityTimeout:30,receiveMessageWaitTime:0,delaySeconds:0}),longRunning:(n,i)=>F.createQueue({slug:n,environment:i,visibilityTimeout:300,messageRetentionPeriod:1209600}),fifo:(n,i)=>F.createQueue({slug:n,environment:i,fifo:!0,contentBasedDeduplication:!0}),delayed:(n,i,s=60)=>F.createQueue({slug:n,environment:i,delaySeconds:s})}}class mt{static async discoverJobs(n){let{projectRoot:i,jobsPath:s="app/Jobs"}=n,o=`${i}/${s}`,c=[];try{let l=await import("node:fs"),u=await import("node:path");if(!l.existsSync(o))return[];let h=l.readdirSync(o).filter((y)=>y.endsWith(".ts")&&!y.startsWith("_")&&y!=="runner.ts");for(let y of h){let f=u.join(o,y),b=y.replace(".ts",""),C=l.readFileSync(f,"utf-8"),T=mt.parseJobMetadata(C,b,f);if(T)c.push(T)}}catch{return[]}return c}static parseJobMetadata(n,i,s){let o=n.match(/export\s + const\s + schedule\s*=\s*['"`]([^'"`]+)['"`]/)||n.match(/schedule:\s*['"`]([^'"`]+)['"`]/),c=n.match(/export\s+const\s+enabled\s*=\s*(true|false)/)||n.match(/enabled:\s*(true|false)/),l=n.match(/export\s+const\s+retries\s*=\s*(\d+)/)||n.match(/retries:\s*(\d+)/),u=n.match(/export\s+const\s+timeout\s*=\s*(\d+)/)||n.match(/timeout:\s*(\d+)/),h=n.match(/export\s+const\s+backoff\s*=\s*['"`](linear|exponential|fixed)['"`]/)||n.match(/backoff:\s*['"`](linear|exponential|fixed)['"`]/),y=n.match(/export\s + const\s + description\s*=\s*['"`]([^'"`]+)['"`]/)||n.match(/description:\s*['"`]([^'"`]+)['"`]/);if(!(n.includes("export async function handle")||n.includes("export function handle")||n.includes("export default")))return null;return{name:i,path:s,schedule:o?.[1],handler:`${i}.handle`,enabled:c?.[1]!=="false",retries:l?parseInt(l[1],10):void 0,backoff:h?.[1],timeout:u?parseInt(u[1],10):void 0,description:y?.[1]}}static async discoverActions(n){let{projectRoot:i,actionsPath:s="app/Actions"}=n,o=`${i}/${s}`,c=[];try{let l=await import("node:fs"),u=await import("node:path");if(!l.existsSync(o))return[];let h=l.readdirSync(o).filter((y)=>y.endsWith(".ts")&&!y.startsWith("_"));for(let y of h){let f=u.join(o,y),b=y.replace(".ts",""),C=l.readFileSync(f,"utf-8"),T=mt.parseActionMetadata(C,b,f);if(T)c.push(T)}}catch{return[]}return c}static parseActionMetadata(n,i,s){if(!(n.includes("export async function handle")||n.includes("export function handle")||n.includes("export default")))return null;let o=n.match(/export\s + const\s + description\s*=\s*['"`]([^'"`]+)['"`]/)||n.match(/description:\s*['"`]([^'"`]+)['"`]/);return{name:i,path:s,handler:`${i}.handle`,description:o?.[1]}}static generateScheduledJobResources(n){let{slug:i,environment:s,jobs:o,taskDefinitionArn:c,clusterArn:l,subnets:u,securityGroups:h=[],roleArn:y,containerName:f="app"}=n,b={},C=0;for(let T of o){if(!T.schedule||!T.enabled)continue;let{rule:w,logicalId:E}=F.createScheduledJob({slug:i,environment:s,schedule:T.schedule,jobClass:T.name,taskDefinitionArn:c,clusterArn:l,subnets:u,securityGroups:h,roleArn:y,containerName:f});b[E]=w,C++}return{rules:b,count:C}}static generateJobRunnerScript(){return`#!/usr/bin/env bun
1661
+ `;class Ke{static LambdaCode={incomingCall:Da,voicemail:Ar,missedCall:br};static createConnectInstance(n){let{slug:i,environment:s,instanceAlias:o,inboundCallsEnabled:c=!0,outboundCallsEnabled:l=!0}=n;return{[`${i}ConnectInstance`]:{Type:"AWS::Connect::Instance",Properties:{InstanceAlias:o,IdentityManagementType:"CONNECT_MANAGED",Attributes:{InboundCalls:c,OutboundCalls:l,ContactflowLogs:!0,ContactLens:!0,AutoResolveBestVoices:!0,UseCustomTTSVoices:!1,EarlyMedia:!0}}}}}static createHoursOfOperation(n){return{[`${n.slug}HoursOfOperation`]:{Type:"AWS::Connect::HoursOfOperation",Properties:{InstanceArn:n.instanceArn,Name:n.name,TimeZone:n.timezone,Config:n.schedule.map((i)=>({Day:i.day,StartTime:{Hours:i.startHour,Minutes:i.startMinute},EndTime:{Hours:i.endHour,Minutes:i.endMinute}}))}}}}static createQueue(n){return{[`${n.slug}Queue`]:{Type:"AWS::Connect::Queue",Properties:{InstanceArn:n.instanceArn,Name:n.name,HoursOfOperationArn:n.hoursOfOperationArn,MaxContacts:n.maxContacts||10}}}}static createContactFlow(n){return{[`${n.slug}ContactFlow`]:{Type:"AWS::Connect::ContactFlow",Properties:{InstanceArn:n.instanceArn,Name:n.name,Type:n.type,Content:n.content}}}}static createBasicIvrFlow(n){let i={Version:"2019-10-30",StartAction:"greeting",Actions:[{Identifier:"greeting",Type:"MessageParticipant",Parameters:{Text:n.greeting},Transitions:{NextAction:"transfer_to_queue",Errors:[{NextAction:"disconnect"}]}},{Identifier:"transfer_to_queue",Type:"TransferToQueue",Parameters:{QueueId:n.queueArn},Transitions:{NextAction:n.voicemailLambdaArn?"voicemail":"disconnect",Errors:[{NextAction:"disconnect"}]}},...n.voicemailLambdaArn?[{Identifier:"voicemail",Type:"InvokeLambdaFunction",Parameters:{LambdaFunctionARN:n.voicemailLambdaArn},Transitions:{NextAction:"disconnect",Errors:[{NextAction:"disconnect"}]}}]:[],{Identifier:"disconnect",Type:"DisconnectParticipant",Parameters:{},Transitions:{}}]};return JSON.stringify(i)}static createPhoneLambdaRole(n){return{[`${n.slug}PhoneLambdaRole`]:{Type:"AWS::IAM::Role",Properties:{RoleName:`${n.slug}-phone-lambda-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],Policies:[{PolicyName:"PhoneLambdaPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:GetItem"],Resource:"*"},{Effect:"Allow",Action:["sns:Publish"],Resource:"*"},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject"],Resource:"*"},{Effect:"Allow",Action:["transcribe:StartTranscriptionJob","transcribe:GetTranscriptionJob"],Resource:"*"},{Effect:"Allow",Action:["connect:*"],Resource:"*"}]}}]}}}}static createIncomingCallLambda(n){return{[`${n.slug}IncomingCallLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-incoming-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Ke.LambdaCode.incomingCall},Environment:{Variables:{NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",CALL_LOG_TABLE:n.callLogTable||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createVoicemailLambda(n){return{[`${n.slug}VoicemailLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-voicemail`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:300,MemorySize:512,Code:{ZipFile:Ke.LambdaCode.voicemail},Environment:{Variables:{VOICEMAIL_BUCKET:n.voicemailBucket,NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",CALL_LOG_TABLE:n.callLogTable||"",TRANSCRIPTION_ENABLED:n.transcriptionEnabled?"true":"false"}}}}}}static createMissedCallLambda(n){return{[`${n.slug}MissedCallLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-missed-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Ke.LambdaCode.missedCall},Environment:{Variables:{NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",CALL_LOG_TABLE:n.callLogTable||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createCallLogTable(n){return{[`${n.slug}CallLogTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-call-log`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"contactId",AttributeType:"S"}],KeySchema:[{AttributeName:"contactId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createCompleteSetup(n){let i={},s={};Object.assign(i,Ke.createPhoneLambdaRole({slug:n.slug})),Object.assign(i,Ke.createCallLogTable({slug:n.slug})),i[`${n.slug}PhoneNotificationTopic`]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${n.slug}-phone-notifications`}},i[`${n.slug}VoicemailBucket`]={Type:"AWS::S3::Bucket",Properties:{BucketName:`${n.slug}-voicemails`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldVoicemails",Status:"Enabled",ExpirationInDays:90}]}}};let o={"Fn::GetAtt":[`${n.slug}PhoneLambdaRole`,"Arn"]},c={Ref:`${n.slug}PhoneNotificationTopic`},l={Ref:`${n.slug}CallLogTable`},u={Ref:`${n.slug}VoicemailBucket`};if(Object.assign(i,Ke.createIncomingCallLambda({slug:n.slug,roleArn:o,notificationTopicArn:c,callLogTable:l,webhookUrl:n.webhookUrl})),n.voicemailEnabled!==!1)Object.assign(i,Ke.createVoicemailLambda({slug:n.slug,roleArn:o,voicemailBucket:u,notificationTopicArn:c,callLogTable:l,transcriptionEnabled:n.transcriptionEnabled}));return Object.assign(i,Ke.createMissedCallLambda({slug:n.slug,roleArn:o,notificationTopicArn:c,callLogTable:l,webhookUrl:n.webhookUrl})),s[`${n.slug}PhoneNotificationTopicArn`]={Description:"Phone notification topic ARN",Value:{Ref:`${n.slug}PhoneNotificationTopic`}},s[`${n.slug}CallLogTableName`]={Description:"Call log table name",Value:{Ref:`${n.slug}CallLogTable`}},s[`${n.slug}VoicemailBucketName`]={Description:"Voicemail bucket name",Value:{Ref:`${n.slug}VoicemailBucket`}},{resources:i,outputs:s}}}class U{static createQueue(n){let{slug:i,environment:s,name:o,delaySeconds:c=0,visibilityTimeout:l=30,messageRetentionPeriod:u=345600,maxMessageSize:h=262144,receiveMessageWaitTime:y=0,fifo:f=!1,contentBasedDeduplication:b=!1,encrypted:C=!0,kmsKeyId:T}=n,w=o||r({slug:i,environment:s,resourceType:"queue"}),E=f?`${w}.fifo`:w,I=t(w),N={Type:"AWS::SQS::Queue",Properties:{QueueName:E,DelaySeconds:c,MaximumMessageSize:h,MessageRetentionPeriod:u,ReceiveMessageWaitTimeSeconds:y,VisibilityTimeout:l,Tags:[{Key:"Name",Value:E},{Key:"Environment",Value:s}]}};if(f)N.Properties.FifoQueue=!0,N.Properties.ContentBasedDeduplication=b;if(C)if(T)N.Properties.KmsMasterKeyId=T;else N.Properties.SqsManagedSseEnabled=!0;return{queue:N,logicalId:I}}static createDeadLetterQueue(n,i){let{slug:s,environment:o,maxReceiveCount:c=3}=i,l=r({slug:s,environment:o,resourceType:"dlq"}),u=t(l),h={Type:"AWS::SQS::Queue",Properties:{QueueName:l,MessageRetentionPeriod:1209600,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:o},{Key:"Type",Value:"DeadLetterQueue"}]}},y={Type:"AWS::SQS::Queue",Properties:{RedrivePolicy:{deadLetterTargetArn:k.GetAtt(u,"Arn"),maxReceiveCount:c}}};return{deadLetterQueue:h,updatedSourceQueue:y,deadLetterLogicalId:u}}static createSchedule(n,i){let{slug:s,environment:o,name:c,description:l,enabled:u=!0}=i,h=c||r({slug:s,environment:o,resourceType:"schedule"}),y=t(h);return{rule:{Type:"AWS::Events::Rule",Properties:{Name:h,Description:l,ScheduleExpression:n,State:u?"ENABLED":"DISABLED",Targets:[]}},logicalId:y}}static scheduleEcsTask(n,i,s){let{slug:o,environment:c,name:l,description:u,enabled:h=!0,taskDefinitionArn:y,clusterArn:f,subnets:b,securityGroups:C=[],assignPublicIp:T=!1,taskCount:w=1,containerOverrides:E}=s,I=l||r({slug:o,environment:c,resourceType:"ecs-schedule"}),N=t(I),D={Id:"1",Arn:f,RoleArn:i,EcsParameters:{TaskDefinitionArn:y,TaskCount:w,LaunchType:"FARGATE",NetworkConfiguration:{awsvpcConfiguration:{Subnets:b,SecurityGroups:C,AssignPublicIp:T?"ENABLED":"DISABLED"}},PlatformVersion:"LATEST"}};if(E&&E.length>0)D.Input=JSON.stringify({containerOverrides:E});return{rule:{Type:"AWS::Events::Rule",Properties:{Name:I,Description:u||`Scheduled ECS task: ${y}`,ScheduleExpression:n,State:h?"ENABLED":"DISABLED",Targets:[D]}},logicalId:N}}static scheduleLambda(n,i){let{slug:s,environment:o,name:c,description:l,enabled:u=!0,functionArn:h,input:y}=i,f=c||r({slug:s,environment:o,resourceType:"lambda-schedule"}),b=t(f),C={Id:"1",Arn:h};if(y)C.Input=JSON.stringify(y);return{rule:{Type:"AWS::Events::Rule",Properties:{Name:f,Description:l||`Scheduled Lambda: ${h}`,ScheduleExpression:n,State:u?"ENABLED":"DISABLED",Targets:[C]}},logicalId:b}}static scheduleSqsMessage(n,i){let{slug:s,environment:o,name:c,description:l,enabled:u=!0,queueArn:h,messageGroupId:y}=i,f=c||r({slug:s,environment:o,resourceType:"sqs-schedule"}),b=t(f),C={Id:"1",Arn:h};if(y)C.SqsParameters={MessageGroupId:y};return{rule:{Type:"AWS::Events::Rule",Properties:{Name:f,Description:l||`Scheduled SQS message: ${h}`,ScheduleExpression:n,State:u?"ENABLED":"DISABLED",Targets:[C]}},logicalId:b}}static addTarget(n,i){if(!n.Properties.Targets)n.Properties.Targets=[];let s={Id:i.id,Arn:i.arn};if(i.roleArn)s.RoleArn=i.roleArn;if(i.input)s.Input=JSON.stringify(i.input);return n.Properties.Targets.push(s),n}static toCronExpression(n){if(n.startsWith("cron(")||n.startsWith("rate("))return n;return`cron(${n})`}static rateExpression(n,i){return`rate(${n} ${i})`}static CronExpressions={EveryMinute:"cron(* * * * ? *)",Every5Minutes:"cron(*/5 * * * ? *)",Every15Minutes:"cron(*/15 * * * ? *)",Every30Minutes:"cron(*/30 * * * ? *)",Hourly:"cron(0 * * * ? *)",Daily:"cron(0 0 * * ? *)",DailyAt9AM:"cron(0 9 * * ? *)",DailyAtMidnight:"cron(0 0 * * ? *)",Weekly:"cron(0 0 ? * SUN *)",Monthly:"cron(0 0 1 * ? *)"};static RateExpressions={Every1Minute:"rate(1 minute)",Every5Minutes:"rate(5 minutes)",Every10Minutes:"rate(10 minutes)",Every15Minutes:"rate(15 minutes)",Every30Minutes:"rate(30 minutes)",Every1Hour:"rate(1 hour)",Every6Hours:"rate(6 hours)",Every12Hours:"rate(12 hours)",Every1Day:"rate(1 day)"};static rateStringToExpression(n){let i=n.toLowerCase().trim(),s=i.match(/^every\s+(\d+)\s+(minute|minutes|hour|hours|day|days)$/i);if(s){let f=parseInt(s[1],10),b=s[2].toLowerCase(),C=b.endsWith("s")&&f===1?b.slice(0,-1):b,T=!b.endsWith("s")&&f>1?`${b}s`:b;return`rate(${f} ${f===1?C:T})`}let o=i.match(/^every\s+(minute|hour|day)$/i);if(o)return`rate(1 ${o[1]})`;let c={"every minute":"rate(1 minute)","every hour":"rate(1 hour)","every day":"rate(1 day)",hourly:"cron(0 * * * ? *)",daily:"cron(0 0 * * ? *)","daily at midnight":"cron(0 0 * * ? *)",weekly:"cron(0 0 ? * SUN *)",monthly:"cron(0 0 1 * ? *)",yearly:"cron(0 0 1 1 ? *)"};if(c[i])return c[i];let l=i.match(/^daily\s+at\s+(\d{1,2})\s*(am|pm)?$/i);if(l){let f=parseInt(l[1],10),b=l[2]?.toLowerCase();if(b==="pm"&&f!==12)f+=12;else if(b==="am"&&f===12)f=0;return`cron(0 ${f} * * ? *)`}let u=i.match(/^at\s+(\d{1,2}):(\d{2})$/i);if(u){let f=parseInt(u[1],10);return`cron(${parseInt(u[2],10)} ${f} * * ? *)`}let h={monday:"MON",tuesday:"TUE",wednesday:"WED",thursday:"THU",friday:"FRI",saturday:"SAT",sunday:"SUN"},y=i.match(/^every\s+(monday|tuesday|wednesday|thursday|friday|saturday|sunday)$/i);if(y)return`cron(0 0 ? * ${h[y[1].toLowerCase()]} *)`;return U.toCronExpression(n)}static JobConfig={create:(n)=>{let{name:i,handler:s,retries:o=3,backoff:c="exponential",backoffDelay:l=1000,maxDelay:u=30000,timeout:h=60000,jitter:y=!0}=n;return{name:i,handler:s,retries:o,backoff:c,backoffDelay:l,maxDelay:u,timeout:h,jitter:y}},calculateDelay:(n,i)=>{let{backoff:s,backoffDelay:o,maxDelay:c,jitter:l}=i,u;switch(s){case"linear":u=o*n;break;case"exponential":u=o*2**(n-1);break;case"fixed":default:u=o}if(u=Math.min(u,c||Number.MAX_SAFE_INTEGER),l){let h=u*0.25*Math.random();u+=h}return Math.floor(u)},presets:{fastRetry:{retries:5,backoff:"exponential",backoffDelay:100,maxDelay:5000,jitter:!0},standard:{retries:3,backoff:"exponential",backoffDelay:1000,maxDelay:30000,jitter:!0},longRunning:{retries:2,backoff:"exponential",backoffDelay:5000,maxDelay:60000,timeout:300000,jitter:!0},critical:{retries:10,backoff:"exponential",backoffDelay:500,maxDelay:60000,jitter:!0},noRetry:{retries:0,backoff:"fixed",backoffDelay:0,maxDelay:0,jitter:!1}}};static createJobContainerOverride(n){let{containerName:i,jobClass:s,jobData:o,environment:c={}}=n,l=[{name:"JOB_CLASS",value:s}];if(o)l.push({name:"JOB_DATA",value:JSON.stringify(o)});for(let[u,h]of Object.entries(c))l.push({name:u,value:h});return{name:i,command:["bun","run","app/Jobs/runner.ts"],environment:l}}static createScheduledJob(n){let{slug:i,environment:s,schedule:o,jobClass:c,jobData:l,taskDefinitionArn:u,clusterArn:h,subnets:y,securityGroups:f=[],roleArn:b,containerName:C="app"}=n,T=U.rateStringToExpression(o),w=U.createJobContainerOverride({containerName:C,jobClass:c,jobData:l});return U.scheduleEcsTask(T,b,{slug:i,environment:s,name:`${i}-${c.toLowerCase().replace(/[^a-z0-9]/g,"-")}`,description:`Scheduled job: ${c}`,taskDefinitionArn:u,clusterArn:h,subnets:y,securityGroups:f,containerOverrides:[w]})}static QueuePresets={highThroughput:(n,i)=>U.createQueue({slug:n,environment:i,visibilityTimeout:30,receiveMessageWaitTime:0,delaySeconds:0}),longRunning:(n,i)=>U.createQueue({slug:n,environment:i,visibilityTimeout:300,messageRetentionPeriod:1209600}),fifo:(n,i)=>U.createQueue({slug:n,environment:i,fifo:!0,contentBasedDeduplication:!0}),delayed:(n,i,s=60)=>U.createQueue({slug:n,environment:i,delaySeconds:s})}}class ft{static async discoverJobs(n){let{projectRoot:i,jobsPath:s="app/Jobs"}=n,o=`${i}/${s}`,c=[];try{let l=await import("node:fs"),u=await import("node:path");if(!l.existsSync(o))return[];let h=l.readdirSync(o).filter((y)=>y.endsWith(".ts")&&!y.startsWith("_")&&y!=="runner.ts");for(let y of h){let f=u.join(o,y),b=y.replace(".ts",""),C=l.readFileSync(f,"utf-8"),T=ft.parseJobMetadata(C,b,f);if(T)c.push(T)}}catch{return[]}return c}static parseJobMetadata(n,i,s){let o=n.match(/export\s + const\s + schedule\s*=\s*['"`]([^'"`]+)['"`]/)||n.match(/schedule:\s*['"`]([^'"`]+)['"`]/),c=n.match(/export\s+const\s+enabled\s*=\s*(true|false)/)||n.match(/enabled:\s*(true|false)/),l=n.match(/export\s+const\s+retries\s*=\s*(\d+)/)||n.match(/retries:\s*(\d+)/),u=n.match(/export\s+const\s+timeout\s*=\s*(\d+)/)||n.match(/timeout:\s*(\d+)/),h=n.match(/export\s+const\s+backoff\s*=\s*['"`](linear|exponential|fixed)['"`]/)||n.match(/backoff:\s*['"`](linear|exponential|fixed)['"`]/),y=n.match(/export\s + const\s + description\s*=\s*['"`]([^'"`]+)['"`]/)||n.match(/description:\s*['"`]([^'"`]+)['"`]/);if(!(n.includes("export async function handle")||n.includes("export function handle")||n.includes("export default")))return null;return{name:i,path:s,schedule:o?.[1],handler:`${i}.handle`,enabled:c?.[1]!=="false",retries:l?parseInt(l[1],10):void 0,backoff:h?.[1],timeout:u?parseInt(u[1],10):void 0,description:y?.[1]}}static async discoverActions(n){let{projectRoot:i,actionsPath:s="app/Actions"}=n,o=`${i}/${s}`,c=[];try{let l=await import("node:fs"),u=await import("node:path");if(!l.existsSync(o))return[];let h=l.readdirSync(o).filter((y)=>y.endsWith(".ts")&&!y.startsWith("_"));for(let y of h){let f=u.join(o,y),b=y.replace(".ts",""),C=l.readFileSync(f,"utf-8"),T=ft.parseActionMetadata(C,b,f);if(T)c.push(T)}}catch{return[]}return c}static parseActionMetadata(n,i,s){if(!(n.includes("export async function handle")||n.includes("export function handle")||n.includes("export default")))return null;let o=n.match(/export\s + const\s + description\s*=\s*['"`]([^'"`]+)['"`]/)||n.match(/description:\s*['"`]([^'"`]+)['"`]/);return{name:i,path:s,handler:`${i}.handle`,description:o?.[1]}}static generateScheduledJobResources(n){let{slug:i,environment:s,jobs:o,taskDefinitionArn:c,clusterArn:l,subnets:u,securityGroups:h=[],roleArn:y,containerName:f="app"}=n,b={},C=0;for(let T of o){if(!T.schedule||!T.enabled)continue;let{rule:w,logicalId:E}=U.createScheduledJob({slug:i,environment:s,schedule:T.schedule,jobClass:T.name,taskDefinitionArn:c,clusterArn:l,subnets:u,securityGroups:h,roleArn:y,containerName:f});b[E]=w,C++}return{rules:b,count:C}}static generateJobRunnerScript(){return`#!/usr/bin/env bun
1662
1662
  /**
1663
1663
  * Job Runner Script
1664
1664
  * This script is invoked by ECS scheduled tasks to run jobs
@@ -1703,7 +1703,7 @@ catch (error) {
1703
1703
  }
1704
1704
 
1705
1705
  run()
1706
- `}static async generateJobManifest(n){let i=await mt.discoverJobs(n),s=i.filter((o)=>o.schedule&&o.enabled);return{jobs:i,scheduledCount:s.length,totalCount:i.length}}}var _I={loadJobs:mt.discoverJobs,loadActions:mt.discoverActions,generateScheduledJobs:mt.generateScheduledJobResources,generateRunner:mt.generateJobRunnerScript,paths:{jobs:"app/Jobs",actions:"app/Actions",runner:"app/Jobs/runner.ts"}},Cr=`
1706
+ `}static async generateJobManifest(n){let i=await ft.discoverJobs(n),s=i.filter((o)=>o.schedule&&o.enabled);return{jobs:i,scheduledCount:s.length,totalCount:i.length}}}var OI={loadJobs:ft.discoverJobs,loadActions:ft.discoverActions,generateScheduledJobs:ft.generateScheduledJobResources,generateRunner:ft.generateJobRunnerScript,paths:{jobs:"app/Jobs",actions:"app/Actions",runner:"app/Jobs/runner.ts"}},Cr=`
1707
1707
  const { DynamoDBClient, UpdateItemCommand } = require('@aws-sdk/client-dynamodb');
1708
1708
  const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');
1709
1709
 
@@ -1978,7 +1978,7 @@ catch (error) {
1978
1978
 
1979
1979
  return { statusCode: 200, body: 'OK' };
1980
1980
  };
1981
- `,oA={};We(oA,{default:()=>Tr,handler:()=>ka});var ka=`
1981
+ `,cA={};Ge(cA,{default:()=>Tr,handler:()=>ka});var ka=`
1982
1982
  const { PinpointClient, SendMessagesCommand } = require('@aws-sdk/client-pinpoint');
1983
1983
  const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');
1984
1984
  const { DynamoDBClient, PutItemCommand } = require('@aws-sdk/client-dynamodb');
@@ -2306,14 +2306,14 @@ function resolveTemplate(template, data) {
2306
2306
  }
2307
2307
  return result;
2308
2308
  }
2309
- `;class U{static LambdaCode={send:ka,receive:vr,deliveryStatus:Cr};static createPinpointApp(n){return{[`${n.slug}PinpointApp`]:{Type:"AWS::Pinpoint::App",Properties:{Name:n.name||`${n.slug}-sms`}}}}static createSmsChannel(n){let i={ApplicationId:n.applicationId,Enabled:n.enabled!==!1};if(n.senderId)i.SenderId=n.senderId;if(n.shortCode)i.ShortCode=n.shortCode;return{[`${n.slug}SmsChannel`]:{Type:"AWS::Pinpoint::SMSChannel",Properties:i}}}static createSmsLambdaRole(n){return{[`${n.slug}SmsLambdaRole`]:{Type:"AWS::IAM::Role",Properties:{RoleName:`${n.slug}-sms-lambda-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],Policies:[{PolicyName:"SmsLambdaPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["mobiletargeting:SendMessages","mobiletargeting:GetSmsChannel"],Resource:"*"},{Effect:"Allow",Action:["sns:Publish"],Resource:"*"},{Effect:"Allow",Action:["dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:GetItem","dynamodb:DeleteItem"],Resource:"*"}]}}]}}}}static createSendLambda(n){return{[`${n.slug}SmsSendLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-send`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:U.LambdaCode.send},Environment:{Variables:{PINPOINT_APP_ID:n.pinpointAppId,MESSAGE_LOG_TABLE:n.messageLogTable||"",SMS_SENDER_ID:n.senderId||"",SMS_ORIGINATION_NUMBER:n.originationNumber||""}}}}}}static createReceiveLambda(n){return{[`${n.slug}SmsReceiveLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-receive`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:U.LambdaCode.receive},Environment:{Variables:{OPT_OUT_TABLE:n.optOutTable||"",MESSAGE_LOG_TABLE:n.messageLogTable||"",NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createDeliveryStatusLambda(n){return{[`${n.slug}SmsDeliveryStatusLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-delivery-status`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:U.LambdaCode.deliveryStatus},Environment:{Variables:{MESSAGE_LOG_TABLE:n.messageLogTable||"",NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createMessageLogTable(n){return{[`${n.slug}SmsMessageLogTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-sms-messages`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createOptOutTable(n){return{[`${n.slug}SmsOptOutTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-sms-optouts`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}]}}}}static createNotificationTopic(n){return{[`${n.slug}SmsNotificationTopic`]:{Type:"AWS::SNS::Topic",Properties:{TopicName:`${n.slug}-sms-notifications`}}}}static createCompleteSetup(n){let i={},s={};Object.assign(i,U.createPinpointApp({slug:n.slug})),Object.assign(i,U.createSmsChannel({slug:n.slug,applicationId:{Ref:`${n.slug}PinpointApp`},senderId:n.senderId})),Object.assign(i,U.createSmsLambdaRole({slug:n.slug})),Object.assign(i,U.createMessageLogTable({slug:n.slug})),Object.assign(i,U.createOptOutTable({slug:n.slug})),Object.assign(i,U.createNotificationTopic({slug:n.slug}));let o={"Fn::GetAtt":[`${n.slug}SmsLambdaRole`,"Arn"]},c={Ref:`${n.slug}PinpointApp`},l={Ref:`${n.slug}SmsMessageLogTable`},u={Ref:`${n.slug}SmsOptOutTable`},h={Ref:`${n.slug}SmsNotificationTopic`};if(Object.assign(i,U.createSendLambda({slug:n.slug,roleArn:o,pinpointAppId:c,messageLogTable:l,senderId:n.senderId,originationNumber:n.originationNumber})),n.twoWayEnabled)Object.assign(i,U.createReceiveLambda({slug:n.slug,roleArn:o,optOutTable:u,messageLogTable:l,notificationTopicArn:h,webhookUrl:n.webhookUrl}));return Object.assign(i,U.createDeliveryStatusLambda({slug:n.slug,roleArn:o,messageLogTable:l,notificationTopicArn:h,webhookUrl:n.webhookUrl})),s[`${n.slug}PinpointAppId`]={Description:"Pinpoint application ID",Value:{Ref:`${n.slug}PinpointApp`}},s[`${n.slug}SmsSendLambdaArn`]={Description:"SMS send Lambda ARN",Value:{"Fn::GetAtt":[`${n.slug}SmsSendLambda`,"Arn"]}},s[`${n.slug}SmsNotificationTopicArn`]={Description:"SMS notification topic ARN",Value:{Ref:`${n.slug}SmsNotificationTopic`}},s[`${n.slug}SmsMessageLogTableName`]={Description:"SMS message log table name",Value:{Ref:`${n.slug}SmsMessageLogTable`}},{resources:i,outputs:s}}}function Rt(n){return n.replace(/[^a-zA-Z0-9]/g," ").trim().split(/\s+/).map((i)=>i.charAt(0).toUpperCase()+i.slice(1)).join("")||"User"}function wr(n,i){let s=(n||i).replace(/^\/+|\/+$/g,"");if(!s||s.split("/").includes(".."))throw Error(`sftp: invalid homeDirectory for user ${i}`);return s}function Er(n){let i=n.storage;if(i?.type==="efs"){let o="fileSystemId"in i?i.fileSystemId:void 0;if(!o||typeof o==="string"&&!o.trim())throw Error("sftp: EFS storage requires fileSystemId, or a fileSystem name defined in infrastructure.fileSystem");return{type:"efs",fileSystemId:o,posixProfile:i.posixProfile}}let s=(i?.type==="s3"?i.bucket??n.bucket:n.bucket)?.trim();if(!s)throw Error("sftp: S3 storage requires bucket, or a storageBucket name defined in infrastructure.storage");return{type:"s3",bucket:s}}function Pr(n,i,s){let o=i.posixProfile??s;if(!o)throw Error(`sftp: user ${n} requires a posixProfile (uid/gid) on an EFS-backed server`);for(let c of[o.uid,o.gid,...o.secondaryGids??[]])if(!Number.isInteger(c)||c<0||c>4294967295)throw Error(`sftp: user ${n} has an invalid posixProfile id ${c}`);return{Uid:o.uid,Gid:o.gid,...o.secondaryGids?.length?{SecondaryGids:o.secondaryGids}:{}}}function Ir(n,i){return typeof n==="string"?`/${n}/${i}`:{"Fn::Sub":[`/\${FileSystemId}/${i}`,{FileSystemId:n}]}}function Rr(n){return typeof n==="string"?{"Fn::Sub":"arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}".replace("${FileSystemId}",n)}:{"Fn::Sub":["arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}",{FileSystemId:n}]}}class kd{static create(n){let i=Er(n),s=i.type==="efs"?"EFS":"S3",o=n.endpointType??"PUBLIC";if(o==="VPC"&&(!n.endpointDetails?.vpcId||!n.endpointDetails.subnetIds.length))throw Error("sftp: VPC endpoints require endpointDetails.vpcId and at least one subnet");let c=`${Rt(n.slug)}${Rt(n.environment)}Sftp`,l=`${c}Server`,u={},h;if(n.logging!==!1){let 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:s,EndpointType:o,IdentityProviderType:"SERVICE_MANAGED",Protocols:["SFTP"],...o==="VPC"?{EndpointDetails:{VpcId:n.endpointDetails.vpcId,SubnetIds:n.endpointDetails.subnetIds,...n.endpointDetails.securityGroupIds?.length?{SecurityGroupIds:n.endpointDetails.securityGroupIds}:{},...n.endpointDetails.addressAllocationIds?.length?{AddressAllocationIds:n.endpointDetails.addressAllocationIds}:{}}}:{},...n.securityPolicyName?{SecurityPolicyName:n.securityPolicyName}:{},...h?{LoggingRole:h}:{},Tags:[{Key:"Project",Value:n.slug},{Key:"Environment",Value:n.environment},{Key:"ManagedBy",Value:"ts-cloud"}]}};for(let[y,f]of Object.entries(n.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 b=Rt(y),C=wr(f.homeDirectory,y),T=`${c}${b}User`,w=f.roleArn;if(!w){let E=`${c}${b}Role`,I;if(i.type==="efs")I=[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:DescribeMountTargets"],Resource:Rr(i.fileSystemId)}];else{let N=`arn:aws:s3:::${i.bucket}`;I=[{Effect:"Allow",Action:["s3:ListBucket","s3:GetBucketLocation"],Resource:N,Condition:{StringLike:{"s3:prefix":[C,`${C}/*`]}}},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:GetObjectVersion"],Resource:`${N}/${C}/*`}]}u[E]={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"transfer.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"SftpHomeDirectory",PolicyDocument:{Version:"2012-10-17",Statement:I}}]}},w={"Fn::GetAtt":[E,"Arn"]}}u[T]={Type:"AWS::Transfer::User",DependsOn:[l],Properties:{ServerId:{Ref:l},UserName:y,Role:w,HomeDirectoryType:"PATH",HomeDirectory:i.type==="efs"?Ir(i.fileSystemId,C):`/${i.bucket}/${C}`,...i.type==="efs"?{PosixProfile:Pr(y,f,i.posixProfile)}:{},SshPublicKeys:f.sshPublicKeys}}}return{resources:u,serverLogicalId:l,domain:s}}}class Re{static createBedrockRole(n,i){let{slug:s,environment:o,name:c,models:l=["*"],allowStreaming:u=!0}=i,h=c||r({slug:s,environment:o,resourceType:"bedrock-role"}),y=t(h),f=["bedrock:InvokeModel"];if(u)f.push("bedrock:InvokeModelWithResponseStream");let b=l.map((C)=>C==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${C}`);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:h,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:n},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:`${h}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:f,Resource:b}]}}],Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:o}]}},logicalId:y}}static createBedrockPolicy(n){let{slug:i,environment:s,name:o,models:c=["*"],allowInvoke:l=!0,allowStreaming:u=!0,allowAsync:h=!1}=n,y=o||r({slug:i,environment:s,resourceType:"bedrock-policy"}),f=t(y),b=[];if(l)b.push("bedrock:InvokeModel");if(u)b.push("bedrock:InvokeModelWithResponseStream");if(h)b.push("bedrock:InvokeModelAsync");let C=c.map((T)=>T==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${T}`);return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:y,PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"BedrockModelInvocation",Effect:"Allow",Action:b,Resource:C}]}}},logicalId:f}}static enableBedrockForLambda(n){return Re.createBedrockRole("lambda.amazonaws.com",n)}static enableBedrockForEcs(n){return Re.createBedrockRole("ecs-tasks.amazonaws.com",n)}static enableBedrockForEc2(n){return Re.createBedrockRole("ec2.amazonaws.com",n)}static addBedrockPermissions(n,i=["*"],s=!0){let o=["bedrock:InvokeModel"];if(s)o.push("bedrock:InvokeModelWithResponseStream");let c=i.map((l)=>l==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${l}`);if(!n.Properties.Policies)n.Properties.Policies=[];return n.Properties.Policies.push({PolicyName:"bedrock-permissions",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:o,Resource:c}]}}),n}static Models={Claude3_5_Sonnet:"anthropic.claude-3-5-sonnet-20241022-v2:0",Claude3_5_Haiku:"anthropic.claude-3-5-haiku-20241022-v1:0",Claude3_Opus:"anthropic.claude-3-opus-20240229-v1:0",Claude3_Sonnet:"anthropic.claude-3-sonnet-20240229-v1:0",Claude3_Haiku:"anthropic.claude-3-haiku-20240307-v1:0",TitanTextG1Express:"amazon.titan-text-express-v1",TitanTextG1Lite:"amazon.titan-text-lite-v1",TitanEmbedG1Text:"amazon.titan-embed-text-v1",TitanImageG1:"amazon.titan-image-generator-v1",JurassicUltra:"ai21.j2-ultra-v1",JurassicMid:"ai21.j2-mid-v1",CommandText:"cohere.command-text-v14",CommandLight:"cohere.command-light-text-v14",EmbedEnglish:"cohere.embed-english-v3",EmbedMultilingual:"cohere.embed-multilingual-v3",Llama3_2_1B:"meta.llama3-2-1b-instruct-v1:0",Llama3_2_3B:"meta.llama3-2-3b-instruct-v1:0",Llama3_2_11B:"meta.llama3-2-11b-instruct-v1:0",Llama3_2_90B:"meta.llama3-2-90b-instruct-v1:0",Llama3_1_8B:"meta.llama3-1-8b-instruct-v1:0",Llama3_1_70B:"meta.llama3-1-70b-instruct-v1:0",Llama3_1_405B:"meta.llama3-1-405b-instruct-v1:0",Mistral7B:"mistral.mistral-7b-instruct-v0:2",Mixtral8x7B:"mistral.mixtral-8x7b-instruct-v0:1",MistralLarge:"mistral.mistral-large-2402-v1:0",StableDiffusionXL:"stability.stable-diffusion-xl-v1"};static ModelGroups={AllClaude:["anthropic.claude-3-5-sonnet-20241022-v2:0","anthropic.claude-3-5-haiku-20241022-v1:0","anthropic.claude-3-opus-20240229-v1:0","anthropic.claude-3-sonnet-20240229-v1:0","anthropic.claude-3-haiku-20240307-v1:0"],AllTitan:["amazon.titan-text-express-v1","amazon.titan-text-lite-v1","amazon.titan-embed-text-v1","amazon.titan-image-generator-v1"],AllLlama:["meta.llama3-2-1b-instruct-v1:0","meta.llama3-2-3b-instruct-v1:0","meta.llama3-2-11b-instruct-v1:0","meta.llama3-2-90b-instruct-v1:0","meta.llama3-1-8b-instruct-v1:0","meta.llama3-1-70b-instruct-v1:0","meta.llama3-1-405b-instruct-v1:0"],TextModels:["anthropic.claude-3-5-sonnet-20241022-v2:0","anthropic.claude-3-5-haiku-20241022-v1:0","amazon.titan-text-express-v1","meta.llama3-2-11b-instruct-v1:0","mistral.mistral-7b-instruct-v0:2"],EmbeddingModels:["amazon.titan-embed-text-v1","cohere.embed-english-v3","cohere.embed-multilingual-v3"],ImageModels:["amazon.titan-image-generator-v1","stability.stable-diffusion-xl-v1"]}}class Vt{static createPostgres(n){return Vt.createRDSInstance("postgres","16.2",n)}static createMysql(n){return Vt.createRDSInstance("mysql","8.0.35",n)}static createRDSInstance(n,i,s){let{slug:o,environment:c,instanceClass:l="db.t3.micro",allocatedStorage:u=20,storageType:h="gp3",masterUsername:y="admin",masterPassword:f,databaseName:b,subnetIds:C,securityGroupIds:T,encrypted:w=!0,kmsKeyId:E,multiAz:I=!1,backupRetentionDays:N=7,publiclyAccessible:D=!1,enableCloudwatchLogs:B=!0,deletionProtection:R=!0}=s,W=r({slug:o,environment:c,resourceType:`${n}-db`}),_=t(W),j,J;if(C&&C.length>0){let Y=r({slug:o,environment:c,resourceType:"db-subnet-group"});J=t(Y),j={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupName:Y,DBSubnetGroupDescription:`Subnet group for ${W}`,SubnetIds:C,Tags:[{Key:"Name",Value:Y},{Key:"Environment",Value:c}]}}}let K={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:W,DBInstanceClass:l,Engine:n,EngineVersion:i,MasterUsername:y,MasterUserPassword:f,AllocatedStorage:u,StorageType:h,StorageEncrypted:w,MultiAZ:I,BackupRetentionPeriod:N,PubliclyAccessible:D,DeletionProtection:R,Tags:[{Key:"Name",Value:W},{Key:"Environment",Value:c}]}};if(b)K.Properties.DBName=b;if(E)K.Properties.KmsKeyId=E;if(J)K.Properties.DBSubnetGroupName=k.Ref(J);if(T&&T.length>0)K.Properties.VPCSecurityGroups=T;if(B)K.Properties.EnableCloudwatchLogsExports=n==="postgres"?["postgresql"]:["error","general","slowquery"];return{dbInstance:K,subnetGroup:j,logicalId:_,subnetGroupId:J}}static createReadReplica(n,i){let{slug:s,environment:o,instanceClass:c="db.t3.micro",securityGroupIds:l,publiclyAccessible:u=!1}=i,h=r({slug:s,environment:o,resourceType:"db-replica"}),y=t(h),f={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:h,DBInstanceClass:c,SourceDBInstanceIdentifier:k.Ref(n),PubliclyAccessible:u,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:o},{Key:"Type",Value:"ReadReplica"}]}};if(l&&l.length>0)f.Properties.VPCSecurityGroups=l;return{replica:f,logicalId:y}}static createParameterGroup(n,i,s){let{slug:o,environment:c,parameters:l={}}=s,u=r({slug:o,environment:c,resourceType:"db-params"}),h=t(u),y=n==="postgres"?`postgres${i.split(".")[0]}`:`mysql${i.split(".")[0]}.${i.split(".")[1]}`;return{parameterGroup:{Type:"AWS::RDS::DBParameterGroup",Properties:{DBParameterGroupName:u,Description:`Parameter group for ${u}`,Family:y,Parameters:l,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:c}]}},logicalId:h}}static enableBackup(n,i=7){return n.Properties.BackupRetentionPeriod=i,n}static createTable(n){let{slug:i,environment:s,tableName:o,partitionKey:c,sortKey:l,billingMode:u="PAY_PER_REQUEST",readCapacity:h=5,writeCapacity:y=5,streamEnabled:f=!1,streamViewType:b="NEW_AND_OLD_IMAGES",encrypted:C=!0,kmsKeyId:T,pointInTimeRecovery:w=!0,ttlAttribute:E}=n,I=o||r({slug:i,environment:s,resourceType:"table"}),N=t(I),D=[{AttributeName:c.name,AttributeType:c.type}];if(l)D.push({AttributeName:l.name,AttributeType:l.type});let B=[{AttributeName:c.name,KeyType:"HASH"}];if(l)B.push({AttributeName:l.name,KeyType:"RANGE"});let R={Type:"AWS::DynamoDB::Table",Properties:{TableName:I,BillingMode:u,AttributeDefinitions:D,KeySchema:B,Tags:[{Key:"Name",Value:I},{Key:"Environment",Value:s}]}};if(u==="PROVISIONED")R.Properties.ProvisionedThroughput={ReadCapacityUnits:h,WriteCapacityUnits:y};if(f)R.Properties.StreamSpecification={StreamViewType:b};if(C)R.Properties.SSESpecification={SSEEnabled:!0,SSEType:T?"KMS":"AES256",KMSMasterKeyId:T};if(w)R.Properties.PointInTimeRecoverySpecification={PointInTimeRecoveryEnabled:!0};if(E)R.Properties.TimeToLiveSpecification={AttributeName:E,Enabled:!0};return{table:R,logicalId:N}}static addGlobalSecondaryIndex(n,i){let{indexName:s,partitionKey:o,sortKey:c,projectionType:l="ALL",nonKeyAttributes:u,readCapacity:h=5,writeCapacity:y=5}=i;if(!n.Properties.AttributeDefinitions.some((C)=>C.AttributeName===o.name))n.Properties.AttributeDefinitions.push({AttributeName:o.name,AttributeType:o.type});if(c&&!n.Properties.AttributeDefinitions.some((C)=>C.AttributeName===c.name))n.Properties.AttributeDefinitions.push({AttributeName:c.name,AttributeType:c.type});let f=[{AttributeName:o.name,KeyType:"HASH"}];if(c)f.push({AttributeName:c.name,KeyType:"RANGE"});let b={IndexName:s,KeySchema:f,Projection:{ProjectionType:l,NonKeyAttributes:l==="INCLUDE"?u:void 0},ProvisionedThroughput:void 0};if(n.Properties.BillingMode==="PROVISIONED")b.ProvisionedThroughput={ReadCapacityUnits:h,WriteCapacityUnits:y};if(!n.Properties.GlobalSecondaryIndexes)n.Properties.GlobalSecondaryIndexes=[];return n.Properties.GlobalSecondaryIndexes.push(b),n}static enableStreams(n,i="NEW_AND_OLD_IMAGES"){return n.Properties.StreamSpecification={StreamViewType:i},n}static InstanceClasses={T3_Micro:"db.t3.micro",T3_Small:"db.t3.small",T3_Medium:"db.t3.medium",T3_Large:"db.t3.large",T4g_Micro:"db.t4g.micro",T4g_Small:"db.t4g.small",T4g_Medium:"db.t4g.medium",M5_Large:"db.m5.large",M5_XLarge:"db.m5.xlarge",M5_2XLarge:"db.m5.2xlarge",R5_Large:"db.r5.large",R5_XLarge:"db.r5.xlarge",R5_2XLarge:"db.r5.2xlarge"}}class lo{static createRedis(n){let{slug:i,environment:s,nodeType:o="cache.t3.micro",engineVersion:c="7.1",port:l=6379,subnetIds:u,securityGroupIds:h,numCacheClusters:y=2,automaticFailover:f=!0,multiAz:b=!0,clusterMode:C=!1,numNodeGroups:T=1,replicasPerNodeGroup:w=1,atRestEncryption:E=!0,transitEncryption:I=!0,authToken:N,kmsKeyId:D,snapshotRetentionDays:B=7,snapshotWindow:R,maintenanceWindow:W}=n,_=r({slug:i,environment:s,resourceType:"redis"}),j=t(_),J,K;if(u&&u.length>0){let X=r({slug:i,environment:s,resourceType:"cache-subnet-group"});K=t(X),J={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:X,Description:`Subnet group for ${_}`,SubnetIds:u,Tags:[{Key:"Name",Value:X},{Key:"Environment",Value:s}]}}}let Y={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:_,ReplicationGroupDescription:`Redis cluster for ${i} ${s}`,Engine:"redis",EngineVersion:c,CacheNodeType:o,Port:l,AutomaticFailoverEnabled:f,MultiAZEnabled:b,AtRestEncryptionEnabled:E,TransitEncryptionEnabled:I,SnapshotRetentionLimit:B,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:_},{Key:"Environment",Value:s}]}};if(C)Y.Properties.NumNodeGroups=T,Y.Properties.ReplicasPerNodeGroup=w;else Y.Properties.NumCacheClusters=y;if(N)Y.Properties.AuthToken=N;if(D)Y.Properties.KmsKeyId=D;if(K)Y.Properties.CacheSubnetGroupName=k.Ref(K);if(h&&h.length>0)Y.Properties.SecurityGroupIds=h;if(R)Y.Properties.SnapshotWindow=R;if(W)Y.Properties.PreferredMaintenanceWindow=W;return{replicationGroup:Y,subnetGroup:J,logicalId:j,subnetGroupId:K}}static createMemcached(n){let{slug:i,environment:s,nodeType:o="cache.t3.micro",engineVersion:c="1.6.22",port:l=11211,numCacheNodes:u=2,subnetIds:h,securityGroupIds:y,azMode:f="cross-az",preferredAzs:b,maintenanceWindow:C}=n,T=r({slug:i,environment:s,resourceType:"memcached"}),w=t(T),E,I;if(h&&h.length>0){let D=r({slug:i,environment:s,resourceType:"cache-subnet-group"});I=t(D),E={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:D,Description:`Subnet group for ${T}`,SubnetIds:h,Tags:[{Key:"Name",Value:D},{Key:"Environment",Value:s}]}}}let N={Type:"AWS::ElastiCache::CacheCluster",Properties:{ClusterName:T,CacheNodeType:o,Engine:"memcached",EngineVersion:c,NumCacheNodes:u,Port:l,AZMode:f,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:T},{Key:"Environment",Value:s}]}};if(I)N.Properties.CacheSubnetGroupName=k.Ref(I);if(y&&y.length>0)N.Properties.VpcSecurityGroupIds=y;if(b&&b.length>0)N.Properties.PreferredAvailabilityZones=b;if(C)N.Properties.PreferredMaintenanceWindow=C;return{cluster:N,subnetGroup:E,logicalId:w,subnetGroupId:I}}static enableClusterMode(n,i=3,s=2){return delete n.Properties.NumCacheClusters,n.Properties.NumNodeGroups=i,n.Properties.ReplicasPerNodeGroup=s,n}static createRedisParameterGroup(n,i){let{slug:s,environment:o,parameters:c={}}=i,l=r({slug:s,environment:o,resourceType:"redis-params"}),u=t(l);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`redis${n.split(".")[0]}.x`,Description:`Parameter group for ${l}`,Properties:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:o}]}},logicalId:u}}static createMemcachedParameterGroup(n,i){let{slug:s,environment:o,parameters:c={}}=i,l=r({slug:s,environment:o,resourceType:"memcached-params"}),u=t(l);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`memcached${n.split(".")[0]}.${n.split(".")[1]}`,Description:`Parameter group for ${l}`,Properties:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:o}]}},logicalId:u}}static NodeTypes={T3_Micro:"cache.t3.micro",T3_Small:"cache.t3.small",T3_Medium:"cache.t3.medium",T4g_Micro:"cache.t4g.micro",T4g_Small:"cache.t4g.small",T4g_Medium:"cache.t4g.medium",M5_Large:"cache.m5.large",M5_XLarge:"cache.m5.xlarge",M5_2XLarge:"cache.m5.2xlarge",R5_Large:"cache.r5.large",R5_XLarge:"cache.r5.xlarge",R5_2XLarge:"cache.r5.2xlarge",R5_4XLarge:"cache.r5.4xlarge",R6g_Large:"cache.r6g.large",R6g_XLarge:"cache.r6g.xlarge",R6g_2XLarge:"cache.r6g.2xlarge"}}class Z{static createUser(n){let{slug:i,environment:s,userName:o,groups:c,managedPolicyArns:l}=n,u=o||r({slug:i,environment:s,resourceType:"user"}),h=t(u),y={Type:"AWS::IAM::User",Properties:{UserName:u,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:s}]}};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(n){let{slug:i,environment:s,roleName:o,servicePrincipal:c,awsPrincipal:l,managedPolicyArns:u}=n,h=o||r({slug:i,environment:s,resourceType:"role"}),y=t(h),f={};if(c)f.Service=c;if(l)f.AWS=l;let b={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:s}]}};if(u&&u.length>0)b.Properties.ManagedPolicyArns=u;return{role:b,logicalId:y}}static createGroup(n){let{slug:i,environment:s,groupName:o,managedPolicyArns:c}=n,l=o||r({slug:i,environment:s,resourceType:"group"}),u=t(l),h={Type:"AWS::IAM::Group",Properties:{GroupName:l}};if(c&&c.length>0)h.Properties.ManagedPolicyArns=c;return{group:h,logicalId:u}}static createPolicy(n){let{slug:i,environment:s,policyName:o,description:c,statements:l}=n,u=o||r({slug:i,environment:s,resourceType:"policy"}),h=t(u),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(n,i){if(!n.Properties.ManagedPolicyArns)n.Properties.ManagedPolicyArns=[];if(!n.Properties.ManagedPolicyArns.includes(i))n.Properties.ManagedPolicyArns.push(i);return n}static attachPolicyToUser(n,i){if(!n.Properties.ManagedPolicyArns)n.Properties.ManagedPolicyArns=[];if(!n.Properties.ManagedPolicyArns.includes(i))n.Properties.ManagedPolicyArns.push(i);return n}static attachPolicyToGroup(n,i){if(!n.Properties.ManagedPolicyArns)n.Properties.ManagedPolicyArns=[];if(!n.Properties.ManagedPolicyArns.includes(i))n.Properties.ManagedPolicyArns.push(i);return n}static addInlinePolicyToRole(n,i,s){if(!n.Properties.Policies)n.Properties.Policies=[];let o=s.map((c)=>({Effect:c.effect||"Allow",Action:c.actions,Resource:c.resources}));return n.Properties.Policies.push({PolicyName:i,PolicyDocument:{Version:"2012-10-17",Statement:o}}),n}static addInlinePolicyToUser(n,i,s){if(!n.Properties.Policies)n.Properties.Policies=[];let o=s.map((c)=>({Effect:c.effect||"Allow",Action:c.actions,Resource:c.resources}));return n.Properties.Policies.push({PolicyName:i,PolicyDocument:{Version:"2012-10-17",Statement:o}}),n}static createAccessKey(n,i){let{slug:s,environment:o,status:c="Active"}=i,l=r({slug:s,environment:o,resourceType:"access-key"}),u=t(l);return{accessKey:{Type:"AWS::IAM::AccessKey",Properties:{UserName:k.Ref(n),Status:c}},logicalId:u}}static createInstanceProfile(n,i){let{slug:s,environment:o,profileName:c}=i,l=c||r({slug:s,environment:o,resourceType:"instance-profile"}),u=t(l);return{instanceProfile:{Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:l,Roles:[k.Ref(n)]}},logicalId:u}}static ManagedPolicies={AdministratorAccess:"arn:aws:iam::aws:policy/AdministratorAccess",PowerUserAccess:"arn:aws:iam::aws:policy/PowerUserAccess",ReadOnlyAccess:"arn:aws:iam::aws:policy/ReadOnlyAccess",S3FullAccess:"arn:aws:iam::aws:policy/AmazonS3FullAccess",S3ReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess",DynamoDBFullAccess:"arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess",DynamoDBReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonDynamoDBReadOnlyAccess",RDSFullAccess:"arn:aws:iam::aws:policy/AmazonRDSFullAccess",RDSReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonRDSReadOnlyAccess",LambdaFullAccess:"arn:aws:iam::aws:policy/AWSLambda_FullAccess",LambdaReadOnlyAccess:"arn:aws:iam::aws:policy/AWSLambda_ReadOnlyAccess",LambdaBasicExecutionRole:"arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",LambdaVPCAccessExecutionRole:"arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole",EC2FullAccess:"arn:aws:iam::aws:policy/AmazonEC2FullAccess",EC2ReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess",EC2ContainerRegistryReadOnly:"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly",EC2ContainerRegistryPowerUser:"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPowerUser",ECSTaskExecutionRole:"arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy",ECSFullAccess:"arn:aws:iam::aws:policy/AmazonECS_FullAccess",CloudWatchFullAccess:"arn:aws:iam::aws:policy/CloudWatchFullAccess",CloudWatchLogsFullAccess:"arn:aws:iam::aws:policy/CloudWatchLogsFullAccess",SESFullAccess:"arn:aws:iam::aws:policy/AmazonSESFullAccess",SNSFullAccess:"arn:aws:iam::aws:policy/AmazonSNSFullAccess",SQSFullAccess:"arn:aws:iam::aws:policy/AmazonSQSFullAccess",SecretsManagerReadWrite:"arn:aws:iam::aws:policy/SecretsManagerReadWrite"};static ServicePrincipals={Lambda:"lambda.amazonaws.com",EC2:"ec2.amazonaws.com",ECS:"ecs.amazonaws.com",ECSTaskExecution:"ecs-tasks.amazonaws.com",APIGateway:"apigateway.amazonaws.com",Events:"events.amazonaws.com",States:"states.amazonaws.com",CodeBuild:"codebuild.amazonaws.com",CodeDeploy:"codedeploy.amazonaws.com",CloudFormation:"cloudformation.amazonaws.com"};static createCiCdUser(n){let{slug:i,environment:s,permissions:o,createAccessKey:c=!0}=n,l={},u=[];if(o.s3Buckets&&o.s3Buckets.length>0)u.push({sid:"S3Access",actions:["s3:GetBucketLocation","s3:ListBucket","s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucketMultipartUploads","s3:AbortMultipartUpload"],resources:[...o.s3Buckets,...o.s3Buckets.map((w)=>`${w}/*`)]});if(o.cloudFrontDistributions&&o.cloudFrontDistributions.length>0)u.push({sid:"CloudFrontAccess",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations","cloudfront:GetDistribution"],resources:o.cloudFrontDistributions});if(o.ecrRepositories&&o.ecrRepositories.length>0)u.push({sid:"ECRAccess",actions:["ecr:GetAuthorizationToken","ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:GetRepositoryPolicy","ecr:DescribeRepositories","ecr:ListImages","ecr:DescribeImages","ecr:BatchGetImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:PutImage"],resources:o.ecrRepositories}),u.push({sid:"ECRLogin",actions:["ecr:GetAuthorizationToken"],resources:"*"});if(o.ecsServices&&o.ecsServices.length>0)u.push({sid:"ECSAccess",actions:["ecs:DescribeServices","ecs:DescribeTaskDefinition","ecs:DescribeTasks","ecs:ListTasks","ecs:RegisterTaskDefinition","ecs:UpdateService","ecs:RunTask","ecs:StopTask"],resources:o.ecsServices}),u.push({sid:"ECSTaskDefinitions",actions:["ecs:RegisterTaskDefinition","ecs:DeregisterTaskDefinition"],resources:"*"}),u.push({sid:"ECSPassRole",actions:["iam:PassRole"],resources:"*",conditions:{StringLike:{"iam:PassedToService":"ecs-tasks.amazonaws.com"}}});if(o.cloudFormationStacks&&o.cloudFormationStacks.length>0)u.push({sid:"CloudFormationAccess",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:DescribeStackResources","cloudformation:GetTemplate","cloudformation:ListStackResources","cloudformation:ValidateTemplate"],resources:o.cloudFormationStacks});if(o.lambdaFunctions&&o.lambdaFunctions.length>0)u.push({sid:"LambdaAccess",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion","lambda:UpdateAlias","lambda:CreateAlias"],resources:o.lambdaFunctions});if(o.secretsManagerSecrets&&o.secretsManagerSecrets.length>0)u.push({sid:"SecretsManagerAccess",actions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],resources:o.secretsManagerSecrets});let{policy:h,logicalId:y}=Z.createPolicy({slug:i,environment:s,policyName:r({slug:i,environment:s,resourceType:"cicd-policy"}),description:`CI/CD deployment policy for ${i} (${s})`,statements:u});l[y]=h;let{user:f,logicalId:b}=Z.createUser({slug:i,environment:s,userName:r({slug:i,environment:s,resourceType:"cicd-user"}),managedPolicyArns:[k.Ref(y)]});l[b]=f;let C,T;if(c){let w=Z.createAccessKey(b,{slug:i,environment:s});C=w.accessKey,T=w.logicalId,l[T]=C}return{user:f,accessKey:C,policy:h,userLogicalId:b,accessKeyLogicalId:T,policyLogicalId:y,resources:l}}static createCrossAccountRole(n){let{slug:i,environment:s,trustedAccountIds:o,externalId:c,permissions:l,maxSessionDuration:u=3600}=n,h={},{policy:y,logicalId:f}=Z.createPolicy({slug:i,environment:s,policyName:r({slug:i,environment:s,resourceType:"cross-account-policy"}),description:`Cross-account access policy for ${i} (${s})`,statements:l});h[f]=y;let b=r({slug:i,environment:s,resourceType:"cross-account-role"}),C=t(b),T={};if(c)T.StringEquals={"sts:ExternalId":c};let w={Type:"AWS::IAM::Role",Properties:{RoleName:b,MaxSessionDuration:u,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:o.map((E)=>`arn:aws:iam::${E}:root`)},Action:"sts:AssumeRole",...Object.keys(T).length>0?{Condition:T}:{}}]},ManagedPolicyArns:[k.Ref(f)],Tags:[{Key:"Name",Value:b},{Key:"Environment",Value:s},{Key:"Purpose",Value:"Cross-Account Access"}]}};return h[C]=w,{role:w,policy:y,roleLogicalId:C,policyLogicalId:f,resources:h}}static createCliUser(n){let{slug:i,environment:s,permissions:o="readonly"}=n,c={},l=[],u=[];switch(o){case"readonly":u=[Z.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=[Z.ManagedPolicies.AdministratorAccess];break}let h,y;if(l.length>0){let w=Z.createPolicy({slug:i,environment:s,policyName:r({slug:i,environment:s,resourceType:"cli-policy"}),description:`CLI access policy for ${i} (${s})`,statements:l});h=w.policy,y=w.logicalId,c[y]=h,u=[k.Ref(y)]}let{user:f,logicalId:b}=Z.createUser({slug:i,environment:s,userName:r({slug:i,environment:s,resourceType:"cli-user"}),managedPolicyArns:u});c[b]=f;let{accessKey:C,logicalId:T}=Z.createAccessKey(b,{slug:i,environment:s});return c[T]=C,{user:f,accessKey:C,policy:h,userLogicalId:b,accessKeyLogicalId:T,policyLogicalId:y,resources:c}}static CiCdPolicies={s3Deployment:(n)=>[{sid:"S3ListBuckets",actions:["s3:ListBucket","s3:GetBucketLocation"],resources:n},{sid:"S3Objects",actions:["s3:GetObject","s3:PutObject","s3:DeleteObject"],resources:n.map((i)=>`${i}/*`)}],cloudFrontInvalidation:(n)=>[{sid:"CloudFrontInvalidation",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations"],resources:n}],ecsDeployment:()=>[{sid:"ECSServices",actions:["ecs:DescribeServices","ecs:UpdateService","ecs:DescribeTaskDefinition","ecs:RegisterTaskDefinition"],resources:"*"},{sid:"ECSPassRole",actions:["iam:PassRole"],resources:"*",conditions:{StringLike:{"iam:PassedToService":"ecs-tasks.amazonaws.com"}}}],ecrPush:(n)=>[{sid:"ECRAuth",actions:["ecr:GetAuthorizationToken"],resources:"*"},{sid:"ECRPush",actions:["ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:PutImage"],resources:n}],lambdaDeployment:(n)=>[{sid:"LambdaDeploy",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion"],resources:n}],cloudFormationDeployment:(n)=>[{sid:"CloudFormationDeploy",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate"],resources:n}]}}class Bd{static createRestApi(n){let{slug:i,environment:s,name:o,description:c,endpointType:l="REGIONAL",binaryMediaTypes:u,compressionSize:h}=n,y=o||r({slug:i,environment:s,resourceType:"rest-api"}),f=t(y),b={Type:"AWS::ApiGateway::RestApi",Properties:{Name:y,Description:c||`REST API for ${i} ${s}`,EndpointConfiguration:{Types:[l]},Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:s}]}};if(u&&u.length>0)b.Properties.BinaryMediaTypes=u;if(h!==void 0)b.Properties.MinimumCompressionSize=h;return{restApi:b,logicalId:f}}static createHttpApi(n){let{slug:i,environment:s,name:o,description:c,corsEnabled:l=!0,corsOrigins:u=["*"],corsMethods:h=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],corsHeaders:y=["*"],corsMaxAge:f=86400,corsAllowCredentials:b=!1}=n,C=o||r({slug:i,environment:s,resourceType:"http-api"}),T=t(C),w={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:C,Description:c||`HTTP API for ${i} ${s}`,ProtocolType:"HTTP",Tags:{Name:C,Environment:s}}};if(l)w.Properties.CorsConfiguration={AllowOrigins:u,AllowMethods:h,AllowHeaders:y,MaxAge:f,AllowCredentials:b};return{httpApi:w,logicalId:T}}static createWebSocketApi(n){let{slug:i,environment:s,name:o,description:c}=n,l=o||r({slug:i,environment:s,resourceType:"ws-api"}),u=t(l);return{webSocketApi:{Type:"AWS::ApiGatewayV2::Api",Properties:{Name:l,Description:c||`WebSocket API for ${i} ${s}`,ProtocolType:"WEBSOCKET",Tags:{Name:l,Environment:s}}},logicalId:u}}static createDeployment(n,i){let{slug:s,environment:o,description:c}=i,l=r({slug:s,environment:o,resourceType:"api-deployment"}),u=t(l);return{deployment:{Type:"AWS::ApiGateway::Deployment",Properties:{RestApiId:k.Ref(n),Description:c||`Deployment for ${l}`}},logicalId:u}}static createStage(n,i,s){let{slug:o,environment:c,stageName:l,description:u,cacheEnabled:h=!1,cacheSize:y="0.5",variables:f,throttling:b}=s,C=r({slug:o,environment:c,resourceType:"api-stage"}),T=t(C),w={Type:"AWS::ApiGateway::Stage",Properties:{StageName:l||c,RestApiId:k.Ref(n),DeploymentId:k.Ref(i),Description:u,CacheClusterEnabled:h,Tags:[{Key:"Name",Value:C},{Key:"Environment",Value:c}]}};if(h)w.Properties.CacheClusterSize=y;if(f)w.Properties.Variables=f;if(b)w.Properties.MethodSettings=[{HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:b.burstLimit,ThrottlingRateLimit:b.rateLimit}];return{stage:w,logicalId:T}}static createAuthorizer(n,i){let{slug:s,environment:o,name:c,type:l,functionArn:u,identitySource:h,userPoolArns:y,ttl:f=300}=i,b=c||r({slug:s,environment:o,resourceType:"api-authorizer"}),C=t(b),T={Type:"AWS::ApiGateway::Authorizer",Properties:{Name:b,Type:l,RestApiId:k.Ref(n),AuthorizerResultTtlInSeconds:f}};if(l==="TOKEN"||l==="REQUEST"){if(!u)throw Error("Lambda authorizer requires functionArn");T.Properties.AuthorizerUri=u,T.Properties.IdentitySource=h||"method.request.header.Authorization"}if(l==="COGNITO_USER_POOLS"){if(!y||y.length===0)throw Error("Cognito authorizer requires userPoolArns");T.Properties.ProviderARNs=y,T.Properties.IdentitySource=h||"method.request.header.Authorization"}return{authorizer:T,logicalId:C}}static setCors(n,i={}){let{origins:s=["*"],methods:o=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],headers:c=["*"],maxAge:l=86400,allowCredentials:u=!1}=i;return n.Properties.CorsConfiguration={AllowOrigins:s,AllowMethods:o,AllowHeaders:c,MaxAge:l,AllowCredentials:u},n}static addThrottling(n,i=5000,s=1e4){if(!n.Properties.MethodSettings)n.Properties.MethodSettings=[];return n.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:i,ThrottlingRateLimit:s}),n}static enableCaching(n,i="0.5",s=300){if(n.Properties.CacheClusterEnabled=!0,n.Properties.CacheClusterSize=i,!n.Properties.MethodSettings)n.Properties.MethodSettings=[];return n.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",CachingEnabled:!0,CacheTtlInSeconds:s}),n}static CacheSizes={Small:"0.5",Medium:"1.6",Large:"6.1",XLarge:"13.5",XXLarge:"28.4",XXXLarge:"58.2",Huge:"118",Massive:"237"};static ThrottlingPresets={Light:{burstLimit:100,rateLimit:50},Medium:{burstLimit:500,rateLimit:250},Heavy:{burstLimit:2000,rateLimit:1000},Default:{burstLimit:5000,rateLimit:1e4}}}class ee{static createTopic(n){let{slug:i,environment:s,topicName:o,displayName:c,encrypted:l=!1,kmsKeyId:u}=n,h=o||r({slug:i,environment:s,resourceType:"topic"}),y=t(h),f={Type:"AWS::SNS::Topic",Properties:{TopicName:h,DisplayName:c||h,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(l&&u)f.Properties.KmsMasterKeyId=u;return{topic:f,logicalId:y}}static subscribe(n,i){let{slug:s,environment:o,protocol:c,endpoint:l,filterPolicy:u,rawMessageDelivery:h=!1}=i,y=r({slug:s,environment:o,resourceType:"subscription"}),f=l.replace(/[^a-zA-Z0-9]/g,""),b=f.length>12?f.slice(-12):f,C=t(`${y}-${c}-${b}`),T={Type:"AWS::SNS::Subscription",Properties:{TopicArn:k.Ref(n),Protocol:c,Endpoint:l,RawMessageDelivery:h}};if(u)T.Properties.FilterPolicy=u;return{subscription:T,logicalId:C}}static subscribeEmail(n,i,s){return ee.subscribe(n,{...s,protocol:"email",endpoint:i})}static subscribeLambda(n,i,s){return ee.subscribe(n,{...s,protocol:"lambda",endpoint:i,rawMessageDelivery:!0})}static subscribeSqs(n,i,s){return ee.subscribe(n,{...s,protocol:"sqs",endpoint:i})}static subscribeHttp(n,i,s){let o=i.startsWith("https://")?"https":"http";return ee.subscribe(n,{...s,protocol:o,endpoint:i})}static subscribeSms(n,i,s){return ee.subscribe(n,{...s,protocol:"sms",endpoint:i})}static setTopicPolicy(n,i){let{slug:s,environment:o,allowedPrincipals:c,allowedServices:l,actions:u="SNS:Publish"}=i,h=r({slug:s,environment:o,resourceType:"topic-policy"}),y=t(h),f={};if(c)f.AWS=c;if(l)f.Service=l;return{policy:{Type:"AWS::SNS::TopicPolicy",Properties:{Topics:[k.Ref(n)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:f,Action:u,Resource:k.Ref(n)}]}}},logicalId:y}}static allowCloudWatchAlarms(n,i){return ee.setTopicPolicy(n,{...i,allowedServices:"cloudwatch.amazonaws.com",actions:"SNS:Publish"})}static allowEventBridge(n,i){return ee.setTopicPolicy(n,{...i,allowedServices:"events.amazonaws.com",actions:"SNS:Publish"})}static allowS3(n,i){return ee.setTopicPolicy(n,{...i,allowedServices:"s3.amazonaws.com",actions:"SNS:Publish"})}static enableEncryption(n,i){if(!n.Properties)n.Properties={};return n.Properties.KmsMasterKeyId=i,n}static addInlineSubscription(n,i,s){if(!n.Properties)n.Properties={};if(!n.Properties.Subscription)n.Properties.Subscription=[];return n.Properties.Subscription.push({Protocol:i,Endpoint:s}),n}static FilterPolicies={eventType:(n)=>({eventType:n}),status:(n)=>({status:n}),numericRange:(n,i,s)=>({[n]:[{numeric:[">=",i,"<=",s]}]}),prefix:(n,i)=>({[n]:[{prefix:i}]}),and:(...n)=>Object.assign({},...n),exists:(n,i)=>({[n]:[{exists:i}]})};static UseCases={createAlertTopic:(n)=>ee.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-alerts`,displayName:n.displayName||"Alert Notifications"}),createEventFanout:(n)=>ee.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-events`,displayName:n.displayName||"Event Fanout"}),createNotificationTopic:(n)=>ee.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-notifications`,displayName:n.displayName||"User Notifications"})}}class aA{static createStateMachine(n){let{slug:i,environment:s,stateMachineName:o,type:c="STANDARD",definition:l,roleArn:u,loggingConfiguration:h,tracingConfiguration:y}=n,f=o||r({slug:i,environment:s,resourceType:"state-machine"}),b=t(f),C,T,w;if(u)w=u;else{let I=r({slug:i,environment:s,resourceType:"state-machine-role"});T=t(I),C={Type:"AWS::IAM::Role",Properties:{RoleName:I,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:I},{Key:"Environment",Value:s}]}},w=k.GetAtt(T,"Arn")}let E={Type:"AWS::StepFunctions::StateMachine",Properties:{StateMachineName:f,StateMachineType:c,DefinitionString:JSON.stringify(l),RoleArn:w,Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s}]}};if(h)E.Properties.LoggingConfiguration={Level:h.level,IncludeExecutionData:h.includeExecutionData,Destinations:h.destinations?.map((I)=>({CloudWatchLogsLogGroup:{LogGroupArn:I}}))};if(y)E.Properties.TracingConfiguration={Enabled:y.enabled};return{stateMachine:E,logicalId:b,role:C,roleLogicalId:T}}static createLambdaTask(n,i){return{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Parameters:{FunctionName:n,Payload:i?.parameters||{"Input.$":"$"}},ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createDynamoDBTask(n,i,s,o){return{Type:"Task",Resource:{GetItem:"arn:aws:states:::dynamodb:getItem",PutItem:"arn:aws:states:::dynamodb:putItem",UpdateItem:"arn:aws:states:::dynamodb:updateItem",DeleteItem:"arn:aws:states:::dynamodb:deleteItem"}[n],Parameters:{TableName:i,...s},ResultPath:o?.resultPath,Retry:o?.retry,Catch:o?.catch,Next:o?.next,End:o?.end}}static createSNSPublishTask(n,i,s){return{Type:"Task",Resource:"arn:aws:states:::sns:publish",Parameters:{TopicArn:n,Message:i},ResultPath:s?.resultPath,Retry:s?.retry,Catch:s?.catch,Next:s?.next,End:s?.end}}static createSQSSendMessageTask(n,i,s){return{Type:"Task",Resource:"arn:aws:states:::sqs:sendMessage",Parameters:{QueueUrl:n,MessageBody:i},ResultPath:s?.resultPath,Retry:s?.retry,Catch:s?.catch,Next:s?.next,End:s?.end}}static createPassState(n){return{Type:"Pass",Result:n?.result,ResultPath:n?.resultPath,Parameters:n?.parameters,Next:n?.next,End:n?.end}}static createWaitState(n){return{Type:"Wait",Seconds:n.seconds,Timestamp:n.timestamp,SecondsPath:n.secondsPath,TimestampPath:n.timestampPath,Next:n.next,End:n.end}}static createChoiceState(n,i){return{Type:"Choice",Choices:n,Default:i}}static createParallelState(n,i){return{Type:"Parallel",Branches:n,ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createMapState(n,i){return{Type:"Map",ItemsPath:i?.itemsPath||"$.items",Iterator:n,MaxConcurrency:i?.maxConcurrency,ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createSucceedState(){return{Type:"Succeed"}}static createFailState(n,i){return{Type:"Fail",Error:n,Cause:i}}static RetryPolicies={standard:()=>({ErrorEquals:["States.ALL"],IntervalSeconds:2,MaxAttempts:3,BackoffRate:2}),aggressive:()=>({ErrorEquals:["States.TaskFailed","States.Timeout"],IntervalSeconds:1,MaxAttempts:5,BackoffRate:1.5}),custom:(n,i,s,o)=>({ErrorEquals:n,IntervalSeconds:i,MaxAttempts:s,BackoffRate:o})};static CatchPolicies={all:(n,i)=>({ErrorEquals:["States.ALL"],Next:n,ResultPath:i||"$.error"}),specific:(n,i,s)=>({ErrorEquals:n,Next:i,ResultPath:s||"$.error"})};static Patterns={sequential:(n,i,s)=>{let o={};return s.forEach((c,l)=>{let u=l===s.length-1;o[c.name]={...c.state,Next:u?void 0:s[l+1].name,End:u}}),{Comment:"Sequential workflow",StartAt:s[0].name,States:o}},fanout:(n,i,s)=>({Comment:"Fan-out workflow",StartAt:"Parallel",States:{Parallel:{Type:"Parallel",Branches:s.map((o)=>o.definition),End:!0}}}),map:(n,i,s,o)=>({Comment:"Map workflow",StartAt:"Map",States:{Map:{Type:"Map",ItemsPath:"$.items",Iterator:s,MaxConcurrency:o,End:!0}}}),withErrorHandling:(n,i,s,o)=>({Comment:"Workflow with error handling",StartAt:"Main",States:{Main:{...s,Catch:[{ErrorEquals:["States.ALL"],Next:"ErrorHandler"}],Next:"Success"},ErrorHandler:o,Success:{Type:"Succeed"}}})}}class uo{static createAlarm(n){let{slug:i,environment:s,alarmName:o,metricName:c,namespace:l,statistic:u="Average",period:h=300,evaluationPeriods:y=1,threshold:f,comparisonOperator:b,treatMissingData:C="notBreaching",actionsEnabled:T=!0,alarmActions:w,okActions:E,insufficientDataActions:I,dimensions:N,unit:D,datapointsToAlarm:B}=n,R=o||r({slug:i,environment:s,resourceType:"alarm"}),W=t(R),_={Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:R,MetricName:c,Namespace:l,Statistic:u,Period:h,EvaluationPeriods:y,Threshold:f,ComparisonOperator:b,TreatMissingData:C,ActionsEnabled:T}};if(w&&w.length>0)_.Properties.AlarmActions=w;if(E&&E.length>0)_.Properties.OKActions=E;if(I&&I.length>0)_.Properties.InsufficientDataActions=I;if(N)_.Properties.Dimensions=Object.entries(N).map(([j,J])=>({Name:j,Value:J}));if(D)_.Properties.Unit=D;if(B!==void 0)_.Properties.DatapointsToAlarm=B;return{alarm:_,logicalId:W}}static createCompositeAlarm(n){let{slug:i,environment:s,alarmName:o,alarmRule:c,actionsEnabled:l=!0,alarmActions:u,okActions:h,insufficientDataActions:y}=n,f=o||r({slug:i,environment:s,resourceType:"composite-alarm"}),b=t(f),C={Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:f,AlarmRule:c,ActionsEnabled:l}};if(u&&u.length>0)C.Properties.AlarmActions=u;if(h&&h.length>0)C.Properties.OKActions=h;if(y&&y.length>0)C.Properties.InsufficientDataActions=y;return{alarm:C,logicalId:b}}static createDashboard(n){let{slug:i,environment:s,dashboardName:o,widgets:c}=n,l=o||r({slug:i,environment:s,resourceType:"dashboard"}),u=t(l),h={widgets:c.map((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(n){let{slug:i,environment:s,logGroupName:o,retentionInDays:c,kmsKeyId:l}=n,u=o||r({slug:i,environment:s,resourceType:"log-group"}),h=t(u),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(n,i){let{slug:s,environment:o,logStreamName:c}=i,l=c||r({slug:s,environment:o,resourceType:"log-stream"}),u=t(l);return{logStream:{Type:"AWS::Logs::LogStream",Properties:{LogGroupName:k.Ref(n),LogStreamName:l}},logicalId:u}}static createMetricFilter(n,i){let{slug:s,environment:o,filterName:c,filterPattern:l,metricTransformations:u}=i,h=c||r({slug:s,environment:o,resourceType:"metric-filter"}),y=t(h);return{metricFilter:{Type:"AWS::Logs::MetricFilter",Properties:{LogGroupName:k.Ref(n),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:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-high-cpu`,metricName:"CPUUtilization",namespace:"AWS/EC2",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s},alarmActions:c?[c]:void 0}),highMemory:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-high-memory`,metricName:"MemoryUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s},alarmActions:c?[c]:void 0}),highDisk:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-high-disk`,metricName:"DiskSpaceUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s,Filesystem:"/dev/xvda1",MountPath:"/"},alarmActions:c?[c]:void 0}),lambdaErrors:(n,i,s,o=5,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-lambda-errors`,metricName:"Errors",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:s},alarmActions:c?[c]:void 0}),lambdaThrottles:(n,i,s,o=10,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-lambda-throttles`,metricName:"Throttles",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:s},alarmActions:c?[c]:void 0}),apiGateway5xxErrors:(n,i,s,o=10,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-api-5xx-errors`,metricName:"5XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:s},alarmActions:c?[c]:void 0}),apiGateway4xxErrors:(n,i,s,o=50,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-api-4xx-errors`,metricName:"4XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:s},alarmActions:c?[c]:void 0}),dynamoDBThrottles:(n,i,s,o=5,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-dynamodb-throttles`,metricName:"UserErrors",namespace:"AWS/DynamoDB",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{TableName:s},alarmActions:c?[c]:void 0}),rdsCpu:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-rds-cpu`,metricName:"CPUUtilization",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{DBInstanceIdentifier:s},alarmActions:c?[c]:void 0}),rdsFreeStorage:(n,i,s,o=5368709120,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-rds-storage`,metricName:"FreeStorageSpace",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"LessThanThreshold",dimensions:{DBInstanceIdentifier:s},alarmActions:c?[c]:void 0,unit:"Bytes"}),sqsQueueDepth:(n,i,s,o=100,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-sqs-depth`,metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{QueueName:s},alarmActions:c?[c]:void 0}),albUnhealthyTargets:(n,i,s,o,c=1,l)=>({slug:n,environment:i,alarmName:`${n}-${i}-alb-unhealthy`,metricName:"UnHealthyHostCount",namespace:"AWS/ApplicationELB",statistic:"Average",period:300,evaluationPeriods:2,threshold:c,comparisonOperator:"GreaterThanThreshold",dimensions:{LoadBalancer:s,TargetGroup:o},alarmActions:l?[l]:void 0}),sesBounceRate:(n,i,s=5,o)=>({slug:n,environment:i,alarmName:`${n}-${i}-ses-bounce-rate`,metricName:"Reputation.BounceRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:s/100,comparisonOperator:"GreaterThanThreshold",alarmActions:o?[o]:void 0}),sesComplaintRate:(n,i,s=0.1,o)=>({slug:n,environment:i,alarmName:`${n}-${i}-ses-complaint-rate`,metricName:"Reputation.ComplaintRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:s/100,comparisonOperator:"GreaterThanThreshold",alarmActions:o?[o]:void 0}),smsDeliveryFailure:(n,i,s,o=10,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-sms-delivery-failure`,metricName:"DirectSendMessagePermanentFailure",namespace:"AWS/Pinpoint",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{ApplicationId:s},alarmActions:c?[c]:void 0}),smsSpendLimit:(n,i,s=100,o)=>({slug:n,environment:i,alarmName:`${n}-${i}-sms-spend-limit`,metricName:"DirectSendMessageSpend",namespace:"AWS/Pinpoint",statistic:"Sum",period:86400,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",alarmActions:o?[o]:void 0}),connectMissedCalls:(n,i,s,o=5,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-connect-missed-calls`,metricName:"MissedCalls",namespace:"AWS/Connect",statistic:"Sum",period:3600,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s},alarmActions:c?[c]:void 0})};static DashboardWidgets={metric:(n,i,s,o,c,l)=>({type:"metric",x:n,y:i,width:s,height:o,properties:{metrics:c,title:l||"Metrics",region:"us-east-1",period:300}}),text:(n,i,s,o,c)=>({type:"text",x:n,y:i,width:s,height:o,properties:{markdown:c}}),log:(n,i,s,o,c,l)=>({type:"log",x:n,y:i,width:s,height:o,properties:{query:`SOURCE '${c.join("' | SOURCE '")}'
2309
+ `;class Q{static LambdaCode={send:ka,receive:vr,deliveryStatus:Cr};static createPinpointApp(n){return{[`${n.slug}PinpointApp`]:{Type:"AWS::Pinpoint::App",Properties:{Name:n.name||`${n.slug}-sms`}}}}static createSmsChannel(n){let i={ApplicationId:n.applicationId,Enabled:n.enabled!==!1};if(n.senderId)i.SenderId=n.senderId;if(n.shortCode)i.ShortCode=n.shortCode;return{[`${n.slug}SmsChannel`]:{Type:"AWS::Pinpoint::SMSChannel",Properties:i}}}static createSmsLambdaRole(n){return{[`${n.slug}SmsLambdaRole`]:{Type:"AWS::IAM::Role",Properties:{RoleName:`${n.slug}-sms-lambda-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],Policies:[{PolicyName:"SmsLambdaPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["mobiletargeting:SendMessages","mobiletargeting:GetSmsChannel"],Resource:"*"},{Effect:"Allow",Action:["sns:Publish"],Resource:"*"},{Effect:"Allow",Action:["dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:GetItem","dynamodb:DeleteItem"],Resource:"*"}]}}]}}}}static createSendLambda(n){return{[`${n.slug}SmsSendLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-send`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Q.LambdaCode.send},Environment:{Variables:{PINPOINT_APP_ID:n.pinpointAppId,MESSAGE_LOG_TABLE:n.messageLogTable||"",SMS_SENDER_ID:n.senderId||"",SMS_ORIGINATION_NUMBER:n.originationNumber||""}}}}}}static createReceiveLambda(n){return{[`${n.slug}SmsReceiveLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-receive`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Q.LambdaCode.receive},Environment:{Variables:{OPT_OUT_TABLE:n.optOutTable||"",MESSAGE_LOG_TABLE:n.messageLogTable||"",NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createDeliveryStatusLambda(n){return{[`${n.slug}SmsDeliveryStatusLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-delivery-status`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Q.LambdaCode.deliveryStatus},Environment:{Variables:{MESSAGE_LOG_TABLE:n.messageLogTable||"",NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createMessageLogTable(n){return{[`${n.slug}SmsMessageLogTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-sms-messages`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createOptOutTable(n){return{[`${n.slug}SmsOptOutTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-sms-optouts`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}]}}}}static createNotificationTopic(n){return{[`${n.slug}SmsNotificationTopic`]:{Type:"AWS::SNS::Topic",Properties:{TopicName:`${n.slug}-sms-notifications`}}}}static createCompleteSetup(n){let i={},s={};Object.assign(i,Q.createPinpointApp({slug:n.slug})),Object.assign(i,Q.createSmsChannel({slug:n.slug,applicationId:{Ref:`${n.slug}PinpointApp`},senderId:n.senderId})),Object.assign(i,Q.createSmsLambdaRole({slug:n.slug})),Object.assign(i,Q.createMessageLogTable({slug:n.slug})),Object.assign(i,Q.createOptOutTable({slug:n.slug})),Object.assign(i,Q.createNotificationTopic({slug:n.slug}));let o={"Fn::GetAtt":[`${n.slug}SmsLambdaRole`,"Arn"]},c={Ref:`${n.slug}PinpointApp`},l={Ref:`${n.slug}SmsMessageLogTable`},u={Ref:`${n.slug}SmsOptOutTable`},h={Ref:`${n.slug}SmsNotificationTopic`};if(Object.assign(i,Q.createSendLambda({slug:n.slug,roleArn:o,pinpointAppId:c,messageLogTable:l,senderId:n.senderId,originationNumber:n.originationNumber})),n.twoWayEnabled)Object.assign(i,Q.createReceiveLambda({slug:n.slug,roleArn:o,optOutTable:u,messageLogTable:l,notificationTopicArn:h,webhookUrl:n.webhookUrl}));return Object.assign(i,Q.createDeliveryStatusLambda({slug:n.slug,roleArn:o,messageLogTable:l,notificationTopicArn:h,webhookUrl:n.webhookUrl})),s[`${n.slug}PinpointAppId`]={Description:"Pinpoint application ID",Value:{Ref:`${n.slug}PinpointApp`}},s[`${n.slug}SmsSendLambdaArn`]={Description:"SMS send Lambda ARN",Value:{"Fn::GetAtt":[`${n.slug}SmsSendLambda`,"Arn"]}},s[`${n.slug}SmsNotificationTopicArn`]={Description:"SMS notification topic ARN",Value:{Ref:`${n.slug}SmsNotificationTopic`}},s[`${n.slug}SmsMessageLogTableName`]={Description:"SMS message log table name",Value:{Ref:`${n.slug}SmsMessageLogTable`}},{resources:i,outputs:s}}}function Rt(n){return n.replace(/[^a-zA-Z0-9]/g," ").trim().split(/\s+/).map((i)=>i.charAt(0).toUpperCase()+i.slice(1)).join("")||"User"}function wr(n,i){let s=(n||i).replace(/^\/+|\/+$/g,"");if(!s||s.split("/").includes(".."))throw Error(`sftp: invalid homeDirectory for user ${i}`);return s}function Er(n){let i=n.storage;if(i?.type==="efs"){let o="fileSystemId"in i?i.fileSystemId:void 0;if(!o||typeof o==="string"&&!o.trim())throw Error("sftp: EFS storage requires fileSystemId, or a fileSystem name defined in infrastructure.fileSystem");return{type:"efs",fileSystemId:o,posixProfile:i.posixProfile}}let s=(i?.type==="s3"?i.bucket??n.bucket:n.bucket)?.trim();if(!s)throw Error("sftp: S3 storage requires bucket, or a storageBucket name defined in infrastructure.storage");return{type:"s3",bucket:s}}function Pr(n,i,s){let o=i.posixProfile??s;if(!o)throw Error(`sftp: user ${n} requires a posixProfile (uid/gid) on an EFS-backed server`);for(let c of[o.uid,o.gid,...o.secondaryGids??[]])if(!Number.isInteger(c)||c<0||c>4294967295)throw Error(`sftp: user ${n} has an invalid posixProfile id ${c}`);return{Uid:o.uid,Gid:o.gid,...o.secondaryGids?.length?{SecondaryGids:o.secondaryGids}:{}}}function Ir(n,i){return typeof n==="string"?`/${n}/${i}`:{"Fn::Sub":[`/\${FileSystemId}/${i}`,{FileSystemId:n}]}}function Rr(n){return typeof n==="string"?{"Fn::Sub":"arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}".replace("${FileSystemId}",n)}:{"Fn::Sub":["arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}",{FileSystemId:n}]}}class _d{static create(n){let i=Er(n),s=i.type==="efs"?"EFS":"S3",o=n.endpointType??"PUBLIC";if(o==="VPC"&&(!n.endpointDetails?.vpcId||!n.endpointDetails.subnetIds.length))throw Error("sftp: VPC endpoints require endpointDetails.vpcId and at least one subnet");let c=`${Rt(n.slug)}${Rt(n.environment)}Sftp`,l=`${c}Server`,u={},h;if(n.logging!==!1){let 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:s,EndpointType:o,IdentityProviderType:"SERVICE_MANAGED",Protocols:["SFTP"],...o==="VPC"?{EndpointDetails:{VpcId:n.endpointDetails.vpcId,SubnetIds:n.endpointDetails.subnetIds,...n.endpointDetails.securityGroupIds?.length?{SecurityGroupIds:n.endpointDetails.securityGroupIds}:{},...n.endpointDetails.addressAllocationIds?.length?{AddressAllocationIds:n.endpointDetails.addressAllocationIds}:{}}}:{},...n.securityPolicyName?{SecurityPolicyName:n.securityPolicyName}:{},...h?{LoggingRole:h}:{},Tags:[{Key:"Project",Value:n.slug},{Key:"Environment",Value:n.environment},{Key:"ManagedBy",Value:"ts-cloud"}]}};for(let[y,f]of Object.entries(n.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 b=Rt(y),C=wr(f.homeDirectory,y),T=`${c}${b}User`,w=f.roleArn;if(!w){let E=`${c}${b}Role`,I;if(i.type==="efs")I=[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:DescribeMountTargets"],Resource:Rr(i.fileSystemId)}];else{let N=`arn:aws:s3:::${i.bucket}`;I=[{Effect:"Allow",Action:["s3:ListBucket","s3:GetBucketLocation"],Resource:N,Condition:{StringLike:{"s3:prefix":[C,`${C}/*`]}}},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:GetObjectVersion"],Resource:`${N}/${C}/*`}]}u[E]={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"transfer.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"SftpHomeDirectory",PolicyDocument:{Version:"2012-10-17",Statement:I}}]}},w={"Fn::GetAtt":[E,"Arn"]}}u[T]={Type:"AWS::Transfer::User",DependsOn:[l],Properties:{ServerId:{Ref:l},UserName:y,Role:w,HomeDirectoryType:"PATH",HomeDirectory:i.type==="efs"?Ir(i.fileSystemId,C):`/${i.bucket}/${C}`,...i.type==="efs"?{PosixProfile:Pr(y,f,i.posixProfile)}:{},SshPublicKeys:f.sshPublicKeys}}}return{resources:u,serverLogicalId:l,domain:s}}}class Pe{static createBedrockRole(n,i){let{slug:s,environment:o,name:c,models:l=["*"],allowStreaming:u=!0}=i,h=c||r({slug:s,environment:o,resourceType:"bedrock-role"}),y=t(h),f=["bedrock:InvokeModel"];if(u)f.push("bedrock:InvokeModelWithResponseStream");let b=l.map((C)=>C==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${C}`);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:h,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:n},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:`${h}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:f,Resource:b}]}}],Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:o}]}},logicalId:y}}static createBedrockPolicy(n){let{slug:i,environment:s,name:o,models:c=["*"],allowInvoke:l=!0,allowStreaming:u=!0,allowAsync:h=!1}=n,y=o||r({slug:i,environment:s,resourceType:"bedrock-policy"}),f=t(y),b=[];if(l)b.push("bedrock:InvokeModel");if(u)b.push("bedrock:InvokeModelWithResponseStream");if(h)b.push("bedrock:InvokeModelAsync");let C=c.map((T)=>T==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${T}`);return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:y,PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"BedrockModelInvocation",Effect:"Allow",Action:b,Resource:C}]}}},logicalId:f}}static enableBedrockForLambda(n){return Pe.createBedrockRole("lambda.amazonaws.com",n)}static enableBedrockForEcs(n){return Pe.createBedrockRole("ecs-tasks.amazonaws.com",n)}static enableBedrockForEc2(n){return Pe.createBedrockRole("ec2.amazonaws.com",n)}static addBedrockPermissions(n,i=["*"],s=!0){let o=["bedrock:InvokeModel"];if(s)o.push("bedrock:InvokeModelWithResponseStream");let c=i.map((l)=>l==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${l}`);if(!n.Properties.Policies)n.Properties.Policies=[];return n.Properties.Policies.push({PolicyName:"bedrock-permissions",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:o,Resource:c}]}}),n}static Models={Claude3_5_Sonnet:"anthropic.claude-3-5-sonnet-20241022-v2:0",Claude3_5_Haiku:"anthropic.claude-3-5-haiku-20241022-v1:0",Claude3_Opus:"anthropic.claude-3-opus-20240229-v1:0",Claude3_Sonnet:"anthropic.claude-3-sonnet-20240229-v1:0",Claude3_Haiku:"anthropic.claude-3-haiku-20240307-v1:0",TitanTextG1Express:"amazon.titan-text-express-v1",TitanTextG1Lite:"amazon.titan-text-lite-v1",TitanEmbedG1Text:"amazon.titan-embed-text-v1",TitanImageG1:"amazon.titan-image-generator-v1",JurassicUltra:"ai21.j2-ultra-v1",JurassicMid:"ai21.j2-mid-v1",CommandText:"cohere.command-text-v14",CommandLight:"cohere.command-light-text-v14",EmbedEnglish:"cohere.embed-english-v3",EmbedMultilingual:"cohere.embed-multilingual-v3",Llama3_2_1B:"meta.llama3-2-1b-instruct-v1:0",Llama3_2_3B:"meta.llama3-2-3b-instruct-v1:0",Llama3_2_11B:"meta.llama3-2-11b-instruct-v1:0",Llama3_2_90B:"meta.llama3-2-90b-instruct-v1:0",Llama3_1_8B:"meta.llama3-1-8b-instruct-v1:0",Llama3_1_70B:"meta.llama3-1-70b-instruct-v1:0",Llama3_1_405B:"meta.llama3-1-405b-instruct-v1:0",Mistral7B:"mistral.mistral-7b-instruct-v0:2",Mixtral8x7B:"mistral.mixtral-8x7b-instruct-v0:1",MistralLarge:"mistral.mistral-large-2402-v1:0",StableDiffusionXL:"stability.stable-diffusion-xl-v1"};static ModelGroups={AllClaude:["anthropic.claude-3-5-sonnet-20241022-v2:0","anthropic.claude-3-5-haiku-20241022-v1:0","anthropic.claude-3-opus-20240229-v1:0","anthropic.claude-3-sonnet-20240229-v1:0","anthropic.claude-3-haiku-20240307-v1:0"],AllTitan:["amazon.titan-text-express-v1","amazon.titan-text-lite-v1","amazon.titan-embed-text-v1","amazon.titan-image-generator-v1"],AllLlama:["meta.llama3-2-1b-instruct-v1:0","meta.llama3-2-3b-instruct-v1:0","meta.llama3-2-11b-instruct-v1:0","meta.llama3-2-90b-instruct-v1:0","meta.llama3-1-8b-instruct-v1:0","meta.llama3-1-70b-instruct-v1:0","meta.llama3-1-405b-instruct-v1:0"],TextModels:["anthropic.claude-3-5-sonnet-20241022-v2:0","anthropic.claude-3-5-haiku-20241022-v1:0","amazon.titan-text-express-v1","meta.llama3-2-11b-instruct-v1:0","mistral.mistral-7b-instruct-v0:2"],EmbeddingModels:["amazon.titan-embed-text-v1","cohere.embed-english-v3","cohere.embed-multilingual-v3"],ImageModels:["amazon.titan-image-generator-v1","stability.stable-diffusion-xl-v1"]}}class jt{static createPostgres(n){return jt.createRDSInstance("postgres","16.2",n)}static createMysql(n){return jt.createRDSInstance("mysql","8.0.35",n)}static createRDSInstance(n,i,s){let{slug:o,environment:c,instanceClass:l="db.t3.micro",allocatedStorage:u=20,storageType:h="gp3",masterUsername:y="admin",masterPassword:f,databaseName:b,subnetIds:C,securityGroupIds:T,encrypted:w=!0,kmsKeyId:E,multiAz:I=!1,backupRetentionDays:N=7,publiclyAccessible:D=!1,enableCloudwatchLogs:x=!0,deletionProtection:R=!0}=s,_=r({slug:o,environment:c,resourceType:`${n}-db`}),B=t(_),W,J;if(C&&C.length>0){let Y=r({slug:o,environment:c,resourceType:"db-subnet-group"});J=t(Y),W={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupName:Y,DBSubnetGroupDescription:`Subnet group for ${_}`,SubnetIds:C,Tags:[{Key:"Name",Value:Y},{Key:"Environment",Value:c}]}}}let K={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:_,DBInstanceClass:l,Engine:n,EngineVersion:i,MasterUsername:y,MasterUserPassword:f,AllocatedStorage:u,StorageType:h,StorageEncrypted:w,MultiAZ:I,BackupRetentionPeriod:N,PubliclyAccessible:D,DeletionProtection:R,Tags:[{Key:"Name",Value:_},{Key:"Environment",Value:c}]}};if(b)K.Properties.DBName=b;if(E)K.Properties.KmsKeyId=E;if(J)K.Properties.DBSubnetGroupName=k.Ref(J);if(T&&T.length>0)K.Properties.VPCSecurityGroups=T;if(x)K.Properties.EnableCloudwatchLogsExports=n==="postgres"?["postgresql"]:["error","general","slowquery"];return{dbInstance:K,subnetGroup:W,logicalId:B,subnetGroupId:J}}static createReadReplica(n,i){let{slug:s,environment:o,instanceClass:c="db.t3.micro",securityGroupIds:l,publiclyAccessible:u=!1}=i,h=r({slug:s,environment:o,resourceType:"db-replica"}),y=t(h),f={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:h,DBInstanceClass:c,SourceDBInstanceIdentifier:k.Ref(n),PubliclyAccessible:u,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:o},{Key:"Type",Value:"ReadReplica"}]}};if(l&&l.length>0)f.Properties.VPCSecurityGroups=l;return{replica:f,logicalId:y}}static createParameterGroup(n,i,s){let{slug:o,environment:c,parameters:l={}}=s,u=r({slug:o,environment:c,resourceType:"db-params"}),h=t(u),y=n==="postgres"?`postgres${i.split(".")[0]}`:`mysql${i.split(".")[0]}.${i.split(".")[1]}`;return{parameterGroup:{Type:"AWS::RDS::DBParameterGroup",Properties:{DBParameterGroupName:u,Description:`Parameter group for ${u}`,Family:y,Parameters:l,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:c}]}},logicalId:h}}static enableBackup(n,i=7){return n.Properties.BackupRetentionPeriod=i,n}static createTable(n){let{slug:i,environment:s,tableName:o,partitionKey:c,sortKey:l,billingMode:u="PAY_PER_REQUEST",readCapacity:h=5,writeCapacity:y=5,streamEnabled:f=!1,streamViewType:b="NEW_AND_OLD_IMAGES",encrypted:C=!0,kmsKeyId:T,pointInTimeRecovery:w=!0,ttlAttribute:E}=n,I=o||r({slug:i,environment:s,resourceType:"table"}),N=t(I),D=[{AttributeName:c.name,AttributeType:c.type}];if(l)D.push({AttributeName:l.name,AttributeType:l.type});let x=[{AttributeName:c.name,KeyType:"HASH"}];if(l)x.push({AttributeName:l.name,KeyType:"RANGE"});let R={Type:"AWS::DynamoDB::Table",Properties:{TableName:I,BillingMode:u,AttributeDefinitions:D,KeySchema:x,Tags:[{Key:"Name",Value:I},{Key:"Environment",Value:s}]}};if(u==="PROVISIONED")R.Properties.ProvisionedThroughput={ReadCapacityUnits:h,WriteCapacityUnits:y};if(f)R.Properties.StreamSpecification={StreamViewType:b};if(C)R.Properties.SSESpecification={SSEEnabled:!0,SSEType:T?"KMS":"AES256",KMSMasterKeyId:T};if(w)R.Properties.PointInTimeRecoverySpecification={PointInTimeRecoveryEnabled:!0};if(E)R.Properties.TimeToLiveSpecification={AttributeName:E,Enabled:!0};return{table:R,logicalId:N}}static addGlobalSecondaryIndex(n,i){let{indexName:s,partitionKey:o,sortKey:c,projectionType:l="ALL",nonKeyAttributes:u,readCapacity:h=5,writeCapacity:y=5}=i;if(!n.Properties.AttributeDefinitions.some((C)=>C.AttributeName===o.name))n.Properties.AttributeDefinitions.push({AttributeName:o.name,AttributeType:o.type});if(c&&!n.Properties.AttributeDefinitions.some((C)=>C.AttributeName===c.name))n.Properties.AttributeDefinitions.push({AttributeName:c.name,AttributeType:c.type});let f=[{AttributeName:o.name,KeyType:"HASH"}];if(c)f.push({AttributeName:c.name,KeyType:"RANGE"});let b={IndexName:s,KeySchema:f,Projection:{ProjectionType:l,NonKeyAttributes:l==="INCLUDE"?u:void 0},ProvisionedThroughput:void 0};if(n.Properties.BillingMode==="PROVISIONED")b.ProvisionedThroughput={ReadCapacityUnits:h,WriteCapacityUnits:y};if(!n.Properties.GlobalSecondaryIndexes)n.Properties.GlobalSecondaryIndexes=[];return n.Properties.GlobalSecondaryIndexes.push(b),n}static enableStreams(n,i="NEW_AND_OLD_IMAGES"){return n.Properties.StreamSpecification={StreamViewType:i},n}static InstanceClasses={T3_Micro:"db.t3.micro",T3_Small:"db.t3.small",T3_Medium:"db.t3.medium",T3_Large:"db.t3.large",T4g_Micro:"db.t4g.micro",T4g_Small:"db.t4g.small",T4g_Medium:"db.t4g.medium",M5_Large:"db.m5.large",M5_XLarge:"db.m5.xlarge",M5_2XLarge:"db.m5.2xlarge",R5_Large:"db.r5.large",R5_XLarge:"db.r5.xlarge",R5_2XLarge:"db.r5.2xlarge"}}class po{static createRedis(n){let{slug:i,environment:s,nodeType:o="cache.t3.micro",engineVersion:c="7.1",port:l=6379,subnetIds:u,securityGroupIds:h,numCacheClusters:y=2,automaticFailover:f=!0,multiAz:b=!0,clusterMode:C=!1,numNodeGroups:T=1,replicasPerNodeGroup:w=1,atRestEncryption:E=!0,transitEncryption:I=!0,authToken:N,kmsKeyId:D,snapshotRetentionDays:x=7,snapshotWindow:R,maintenanceWindow:_}=n,B=r({slug:i,environment:s,resourceType:"redis"}),W=t(B),J,K;if(u&&u.length>0){let Z=r({slug:i,environment:s,resourceType:"cache-subnet-group"});K=t(Z),J={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:Z,Description:`Subnet group for ${B}`,SubnetIds:u,Tags:[{Key:"Name",Value:Z},{Key:"Environment",Value:s}]}}}let Y={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:B,ReplicationGroupDescription:`Redis cluster for ${i} ${s}`,Engine:"redis",EngineVersion:c,CacheNodeType:o,Port:l,AutomaticFailoverEnabled:f,MultiAZEnabled:b,AtRestEncryptionEnabled:E,TransitEncryptionEnabled:I,SnapshotRetentionLimit:x,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:B},{Key:"Environment",Value:s}]}};if(C)Y.Properties.NumNodeGroups=T,Y.Properties.ReplicasPerNodeGroup=w;else Y.Properties.NumCacheClusters=y;if(N)Y.Properties.AuthToken=N;if(D)Y.Properties.KmsKeyId=D;if(K)Y.Properties.CacheSubnetGroupName=k.Ref(K);if(h&&h.length>0)Y.Properties.SecurityGroupIds=h;if(R)Y.Properties.SnapshotWindow=R;if(_)Y.Properties.PreferredMaintenanceWindow=_;return{replicationGroup:Y,subnetGroup:J,logicalId:W,subnetGroupId:K}}static createMemcached(n){let{slug:i,environment:s,nodeType:o="cache.t3.micro",engineVersion:c="1.6.22",port:l=11211,numCacheNodes:u=2,subnetIds:h,securityGroupIds:y,azMode:f="cross-az",preferredAzs:b,maintenanceWindow:C}=n,T=r({slug:i,environment:s,resourceType:"memcached"}),w=t(T),E,I;if(h&&h.length>0){let D=r({slug:i,environment:s,resourceType:"cache-subnet-group"});I=t(D),E={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:D,Description:`Subnet group for ${T}`,SubnetIds:h,Tags:[{Key:"Name",Value:D},{Key:"Environment",Value:s}]}}}let N={Type:"AWS::ElastiCache::CacheCluster",Properties:{ClusterName:T,CacheNodeType:o,Engine:"memcached",EngineVersion:c,NumCacheNodes:u,Port:l,AZMode:f,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:T},{Key:"Environment",Value:s}]}};if(I)N.Properties.CacheSubnetGroupName=k.Ref(I);if(y&&y.length>0)N.Properties.VpcSecurityGroupIds=y;if(b&&b.length>0)N.Properties.PreferredAvailabilityZones=b;if(C)N.Properties.PreferredMaintenanceWindow=C;return{cluster:N,subnetGroup:E,logicalId:w,subnetGroupId:I}}static enableClusterMode(n,i=3,s=2){return delete n.Properties.NumCacheClusters,n.Properties.NumNodeGroups=i,n.Properties.ReplicasPerNodeGroup=s,n}static createRedisParameterGroup(n,i){let{slug:s,environment:o,parameters:c={}}=i,l=r({slug:s,environment:o,resourceType:"redis-params"}),u=t(l);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`redis${n.split(".")[0]}.x`,Description:`Parameter group for ${l}`,Properties:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:o}]}},logicalId:u}}static createMemcachedParameterGroup(n,i){let{slug:s,environment:o,parameters:c={}}=i,l=r({slug:s,environment:o,resourceType:"memcached-params"}),u=t(l);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`memcached${n.split(".")[0]}.${n.split(".")[1]}`,Description:`Parameter group for ${l}`,Properties:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:o}]}},logicalId:u}}static NodeTypes={T3_Micro:"cache.t3.micro",T3_Small:"cache.t3.small",T3_Medium:"cache.t3.medium",T4g_Micro:"cache.t4g.micro",T4g_Small:"cache.t4g.small",T4g_Medium:"cache.t4g.medium",M5_Large:"cache.m5.large",M5_XLarge:"cache.m5.xlarge",M5_2XLarge:"cache.m5.2xlarge",R5_Large:"cache.r5.large",R5_XLarge:"cache.r5.xlarge",R5_2XLarge:"cache.r5.2xlarge",R5_4XLarge:"cache.r5.4xlarge",R6g_Large:"cache.r6g.large",R6g_XLarge:"cache.r6g.xlarge",R6g_2XLarge:"cache.r6g.2xlarge"}}class ee{static createUser(n){let{slug:i,environment:s,userName:o,groups:c,managedPolicyArns:l}=n,u=o||r({slug:i,environment:s,resourceType:"user"}),h=t(u),y={Type:"AWS::IAM::User",Properties:{UserName:u,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:s}]}};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(n){let{slug:i,environment:s,roleName:o,servicePrincipal:c,awsPrincipal:l,managedPolicyArns:u}=n,h=o||r({slug:i,environment:s,resourceType:"role"}),y=t(h),f={};if(c)f.Service=c;if(l)f.AWS=l;let b={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:s}]}};if(u&&u.length>0)b.Properties.ManagedPolicyArns=u;return{role:b,logicalId:y}}static createGroup(n){let{slug:i,environment:s,groupName:o,managedPolicyArns:c}=n,l=o||r({slug:i,environment:s,resourceType:"group"}),u=t(l),h={Type:"AWS::IAM::Group",Properties:{GroupName:l}};if(c&&c.length>0)h.Properties.ManagedPolicyArns=c;return{group:h,logicalId:u}}static createPolicy(n){let{slug:i,environment:s,policyName:o,description:c,statements:l}=n,u=o||r({slug:i,environment:s,resourceType:"policy"}),h=t(u),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(n,i){if(!n.Properties.ManagedPolicyArns)n.Properties.ManagedPolicyArns=[];if(!n.Properties.ManagedPolicyArns.includes(i))n.Properties.ManagedPolicyArns.push(i);return n}static attachPolicyToUser(n,i){if(!n.Properties.ManagedPolicyArns)n.Properties.ManagedPolicyArns=[];if(!n.Properties.ManagedPolicyArns.includes(i))n.Properties.ManagedPolicyArns.push(i);return n}static attachPolicyToGroup(n,i){if(!n.Properties.ManagedPolicyArns)n.Properties.ManagedPolicyArns=[];if(!n.Properties.ManagedPolicyArns.includes(i))n.Properties.ManagedPolicyArns.push(i);return n}static addInlinePolicyToRole(n,i,s){if(!n.Properties.Policies)n.Properties.Policies=[];let o=s.map((c)=>({Effect:c.effect||"Allow",Action:c.actions,Resource:c.resources}));return n.Properties.Policies.push({PolicyName:i,PolicyDocument:{Version:"2012-10-17",Statement:o}}),n}static addInlinePolicyToUser(n,i,s){if(!n.Properties.Policies)n.Properties.Policies=[];let o=s.map((c)=>({Effect:c.effect||"Allow",Action:c.actions,Resource:c.resources}));return n.Properties.Policies.push({PolicyName:i,PolicyDocument:{Version:"2012-10-17",Statement:o}}),n}static createAccessKey(n,i){let{slug:s,environment:o,status:c="Active"}=i,l=r({slug:s,environment:o,resourceType:"access-key"}),u=t(l);return{accessKey:{Type:"AWS::IAM::AccessKey",Properties:{UserName:k.Ref(n),Status:c}},logicalId:u}}static createInstanceProfile(n,i){let{slug:s,environment:o,profileName:c}=i,l=c||r({slug:s,environment:o,resourceType:"instance-profile"}),u=t(l);return{instanceProfile:{Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:l,Roles:[k.Ref(n)]}},logicalId:u}}static ManagedPolicies={AdministratorAccess:"arn:aws:iam::aws:policy/AdministratorAccess",PowerUserAccess:"arn:aws:iam::aws:policy/PowerUserAccess",ReadOnlyAccess:"arn:aws:iam::aws:policy/ReadOnlyAccess",S3FullAccess:"arn:aws:iam::aws:policy/AmazonS3FullAccess",S3ReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess",DynamoDBFullAccess:"arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess",DynamoDBReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonDynamoDBReadOnlyAccess",RDSFullAccess:"arn:aws:iam::aws:policy/AmazonRDSFullAccess",RDSReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonRDSReadOnlyAccess",LambdaFullAccess:"arn:aws:iam::aws:policy/AWSLambda_FullAccess",LambdaReadOnlyAccess:"arn:aws:iam::aws:policy/AWSLambda_ReadOnlyAccess",LambdaBasicExecutionRole:"arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",LambdaVPCAccessExecutionRole:"arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole",EC2FullAccess:"arn:aws:iam::aws:policy/AmazonEC2FullAccess",EC2ReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess",EC2ContainerRegistryReadOnly:"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly",EC2ContainerRegistryPowerUser:"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPowerUser",ECSTaskExecutionRole:"arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy",ECSFullAccess:"arn:aws:iam::aws:policy/AmazonECS_FullAccess",CloudWatchFullAccess:"arn:aws:iam::aws:policy/CloudWatchFullAccess",CloudWatchLogsFullAccess:"arn:aws:iam::aws:policy/CloudWatchLogsFullAccess",SESFullAccess:"arn:aws:iam::aws:policy/AmazonSESFullAccess",SNSFullAccess:"arn:aws:iam::aws:policy/AmazonSNSFullAccess",SQSFullAccess:"arn:aws:iam::aws:policy/AmazonSQSFullAccess",SecretsManagerReadWrite:"arn:aws:iam::aws:policy/SecretsManagerReadWrite"};static ServicePrincipals={Lambda:"lambda.amazonaws.com",EC2:"ec2.amazonaws.com",ECS:"ecs.amazonaws.com",ECSTaskExecution:"ecs-tasks.amazonaws.com",APIGateway:"apigateway.amazonaws.com",Events:"events.amazonaws.com",States:"states.amazonaws.com",CodeBuild:"codebuild.amazonaws.com",CodeDeploy:"codedeploy.amazonaws.com",CloudFormation:"cloudformation.amazonaws.com"};static createCiCdUser(n){let{slug:i,environment:s,permissions:o,createAccessKey:c=!0}=n,l={},u=[];if(o.s3Buckets&&o.s3Buckets.length>0)u.push({sid:"S3Access",actions:["s3:GetBucketLocation","s3:ListBucket","s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucketMultipartUploads","s3:AbortMultipartUpload"],resources:[...o.s3Buckets,...o.s3Buckets.map((w)=>`${w}/*`)]});if(o.cloudFrontDistributions&&o.cloudFrontDistributions.length>0)u.push({sid:"CloudFrontAccess",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations","cloudfront:GetDistribution"],resources:o.cloudFrontDistributions});if(o.ecrRepositories&&o.ecrRepositories.length>0)u.push({sid:"ECRAccess",actions:["ecr:GetAuthorizationToken","ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:GetRepositoryPolicy","ecr:DescribeRepositories","ecr:ListImages","ecr:DescribeImages","ecr:BatchGetImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:PutImage"],resources:o.ecrRepositories}),u.push({sid:"ECRLogin",actions:["ecr:GetAuthorizationToken"],resources:"*"});if(o.ecsServices&&o.ecsServices.length>0)u.push({sid:"ECSAccess",actions:["ecs:DescribeServices","ecs:DescribeTaskDefinition","ecs:DescribeTasks","ecs:ListTasks","ecs:RegisterTaskDefinition","ecs:UpdateService","ecs:RunTask","ecs:StopTask"],resources:o.ecsServices}),u.push({sid:"ECSTaskDefinitions",actions:["ecs:RegisterTaskDefinition","ecs:DeregisterTaskDefinition"],resources:"*"}),u.push({sid:"ECSPassRole",actions:["iam:PassRole"],resources:"*",conditions:{StringLike:{"iam:PassedToService":"ecs-tasks.amazonaws.com"}}});if(o.cloudFormationStacks&&o.cloudFormationStacks.length>0)u.push({sid:"CloudFormationAccess",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:DescribeStackResources","cloudformation:GetTemplate","cloudformation:ListStackResources","cloudformation:ValidateTemplate"],resources:o.cloudFormationStacks});if(o.lambdaFunctions&&o.lambdaFunctions.length>0)u.push({sid:"LambdaAccess",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion","lambda:UpdateAlias","lambda:CreateAlias"],resources:o.lambdaFunctions});if(o.secretsManagerSecrets&&o.secretsManagerSecrets.length>0)u.push({sid:"SecretsManagerAccess",actions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],resources:o.secretsManagerSecrets});let{policy:h,logicalId:y}=ee.createPolicy({slug:i,environment:s,policyName:r({slug:i,environment:s,resourceType:"cicd-policy"}),description:`CI/CD deployment policy for ${i} (${s})`,statements:u});l[y]=h;let{user:f,logicalId:b}=ee.createUser({slug:i,environment:s,userName:r({slug:i,environment:s,resourceType:"cicd-user"}),managedPolicyArns:[k.Ref(y)]});l[b]=f;let C,T;if(c){let w=ee.createAccessKey(b,{slug:i,environment:s});C=w.accessKey,T=w.logicalId,l[T]=C}return{user:f,accessKey:C,policy:h,userLogicalId:b,accessKeyLogicalId:T,policyLogicalId:y,resources:l}}static createCrossAccountRole(n){let{slug:i,environment:s,trustedAccountIds:o,externalId:c,permissions:l,maxSessionDuration:u=3600}=n,h={},{policy:y,logicalId:f}=ee.createPolicy({slug:i,environment:s,policyName:r({slug:i,environment:s,resourceType:"cross-account-policy"}),description:`Cross-account access policy for ${i} (${s})`,statements:l});h[f]=y;let b=r({slug:i,environment:s,resourceType:"cross-account-role"}),C=t(b),T={};if(c)T.StringEquals={"sts:ExternalId":c};let w={Type:"AWS::IAM::Role",Properties:{RoleName:b,MaxSessionDuration:u,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:o.map((E)=>`arn:aws:iam::${E}:root`)},Action:"sts:AssumeRole",...Object.keys(T).length>0?{Condition:T}:{}}]},ManagedPolicyArns:[k.Ref(f)],Tags:[{Key:"Name",Value:b},{Key:"Environment",Value:s},{Key:"Purpose",Value:"Cross-Account Access"}]}};return h[C]=w,{role:w,policy:y,roleLogicalId:C,policyLogicalId:f,resources:h}}static createCliUser(n){let{slug:i,environment:s,permissions:o="readonly"}=n,c={},l=[],u=[];switch(o){case"readonly":u=[ee.ManagedPolicies.ReadOnlyAccess];break;case"deploy":l=[{sid:"S3Deploy",actions:["s3:*"],resources:"*"},{sid:"CloudFrontDeploy",actions:["cloudfront:*"],resources:"*"},{sid:"ECSDeploy",actions:["ecs:*"],resources:"*"},{sid:"ECRDeploy",actions:["ecr:*"],resources:"*"},{sid:"LambdaDeploy",actions:["lambda:*"],resources:"*"},{sid:"CloudFormationDeploy",actions:["cloudformation:*"],resources:"*"},{sid:"IAMPassRole",actions:["iam:PassRole"],resources:"*"}];break;case"admin":u=[ee.ManagedPolicies.AdministratorAccess];break}let h,y;if(l.length>0){let w=ee.createPolicy({slug:i,environment:s,policyName:r({slug:i,environment:s,resourceType:"cli-policy"}),description:`CLI access policy for ${i} (${s})`,statements:l});h=w.policy,y=w.logicalId,c[y]=h,u=[k.Ref(y)]}let{user:f,logicalId:b}=ee.createUser({slug:i,environment:s,userName:r({slug:i,environment:s,resourceType:"cli-user"}),managedPolicyArns:u});c[b]=f;let{accessKey:C,logicalId:T}=ee.createAccessKey(b,{slug:i,environment:s});return c[T]=C,{user:f,accessKey:C,policy:h,userLogicalId:b,accessKeyLogicalId:T,policyLogicalId:y,resources:c}}static CiCdPolicies={s3Deployment:(n)=>[{sid:"S3ListBuckets",actions:["s3:ListBucket","s3:GetBucketLocation"],resources:n},{sid:"S3Objects",actions:["s3:GetObject","s3:PutObject","s3:DeleteObject"],resources:n.map((i)=>`${i}/*`)}],cloudFrontInvalidation:(n)=>[{sid:"CloudFrontInvalidation",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations"],resources:n}],ecsDeployment:()=>[{sid:"ECSServices",actions:["ecs:DescribeServices","ecs:UpdateService","ecs:DescribeTaskDefinition","ecs:RegisterTaskDefinition"],resources:"*"},{sid:"ECSPassRole",actions:["iam:PassRole"],resources:"*",conditions:{StringLike:{"iam:PassedToService":"ecs-tasks.amazonaws.com"}}}],ecrPush:(n)=>[{sid:"ECRAuth",actions:["ecr:GetAuthorizationToken"],resources:"*"},{sid:"ECRPush",actions:["ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:PutImage"],resources:n}],lambdaDeployment:(n)=>[{sid:"LambdaDeploy",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion"],resources:n}],cloudFormationDeployment:(n)=>[{sid:"CloudFormationDeploy",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate"],resources:n}]}}class xd{static createRestApi(n){let{slug:i,environment:s,name:o,description:c,endpointType:l="REGIONAL",binaryMediaTypes:u,compressionSize:h}=n,y=o||r({slug:i,environment:s,resourceType:"rest-api"}),f=t(y),b={Type:"AWS::ApiGateway::RestApi",Properties:{Name:y,Description:c||`REST API for ${i} ${s}`,EndpointConfiguration:{Types:[l]},Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:s}]}};if(u&&u.length>0)b.Properties.BinaryMediaTypes=u;if(h!==void 0)b.Properties.MinimumCompressionSize=h;return{restApi:b,logicalId:f}}static createHttpApi(n){let{slug:i,environment:s,name:o,description:c,corsEnabled:l=!0,corsOrigins:u=["*"],corsMethods:h=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],corsHeaders:y=["*"],corsMaxAge:f=86400,corsAllowCredentials:b=!1}=n,C=o||r({slug:i,environment:s,resourceType:"http-api"}),T=t(C),w={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:C,Description:c||`HTTP API for ${i} ${s}`,ProtocolType:"HTTP",Tags:{Name:C,Environment:s}}};if(l)w.Properties.CorsConfiguration={AllowOrigins:u,AllowMethods:h,AllowHeaders:y,MaxAge:f,AllowCredentials:b};return{httpApi:w,logicalId:T}}static createWebSocketApi(n){let{slug:i,environment:s,name:o,description:c}=n,l=o||r({slug:i,environment:s,resourceType:"ws-api"}),u=t(l);return{webSocketApi:{Type:"AWS::ApiGatewayV2::Api",Properties:{Name:l,Description:c||`WebSocket API for ${i} ${s}`,ProtocolType:"WEBSOCKET",Tags:{Name:l,Environment:s}}},logicalId:u}}static createDeployment(n,i){let{slug:s,environment:o,description:c}=i,l=r({slug:s,environment:o,resourceType:"api-deployment"}),u=t(l);return{deployment:{Type:"AWS::ApiGateway::Deployment",Properties:{RestApiId:k.Ref(n),Description:c||`Deployment for ${l}`}},logicalId:u}}static createStage(n,i,s){let{slug:o,environment:c,stageName:l,description:u,cacheEnabled:h=!1,cacheSize:y="0.5",variables:f,throttling:b}=s,C=r({slug:o,environment:c,resourceType:"api-stage"}),T=t(C),w={Type:"AWS::ApiGateway::Stage",Properties:{StageName:l||c,RestApiId:k.Ref(n),DeploymentId:k.Ref(i),Description:u,CacheClusterEnabled:h,Tags:[{Key:"Name",Value:C},{Key:"Environment",Value:c}]}};if(h)w.Properties.CacheClusterSize=y;if(f)w.Properties.Variables=f;if(b)w.Properties.MethodSettings=[{HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:b.burstLimit,ThrottlingRateLimit:b.rateLimit}];return{stage:w,logicalId:T}}static createAuthorizer(n,i){let{slug:s,environment:o,name:c,type:l,functionArn:u,identitySource:h,userPoolArns:y,ttl:f=300}=i,b=c||r({slug:s,environment:o,resourceType:"api-authorizer"}),C=t(b),T={Type:"AWS::ApiGateway::Authorizer",Properties:{Name:b,Type:l,RestApiId:k.Ref(n),AuthorizerResultTtlInSeconds:f}};if(l==="TOKEN"||l==="REQUEST"){if(!u)throw Error("Lambda authorizer requires functionArn");T.Properties.AuthorizerUri=u,T.Properties.IdentitySource=h||"method.request.header.Authorization"}if(l==="COGNITO_USER_POOLS"){if(!y||y.length===0)throw Error("Cognito authorizer requires userPoolArns");T.Properties.ProviderARNs=y,T.Properties.IdentitySource=h||"method.request.header.Authorization"}return{authorizer:T,logicalId:C}}static setCors(n,i={}){let{origins:s=["*"],methods:o=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],headers:c=["*"],maxAge:l=86400,allowCredentials:u=!1}=i;return n.Properties.CorsConfiguration={AllowOrigins:s,AllowMethods:o,AllowHeaders:c,MaxAge:l,AllowCredentials:u},n}static addThrottling(n,i=5000,s=1e4){if(!n.Properties.MethodSettings)n.Properties.MethodSettings=[];return n.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:i,ThrottlingRateLimit:s}),n}static enableCaching(n,i="0.5",s=300){if(n.Properties.CacheClusterEnabled=!0,n.Properties.CacheClusterSize=i,!n.Properties.MethodSettings)n.Properties.MethodSettings=[];return n.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",CachingEnabled:!0,CacheTtlInSeconds:s}),n}static CacheSizes={Small:"0.5",Medium:"1.6",Large:"6.1",XLarge:"13.5",XXLarge:"28.4",XXXLarge:"58.2",Huge:"118",Massive:"237"};static ThrottlingPresets={Light:{burstLimit:100,rateLimit:50},Medium:{burstLimit:500,rateLimit:250},Heavy:{burstLimit:2000,rateLimit:1000},Default:{burstLimit:5000,rateLimit:1e4}}}class te{static createTopic(n){let{slug:i,environment:s,topicName:o,displayName:c,encrypted:l=!1,kmsKeyId:u}=n,h=o||r({slug:i,environment:s,resourceType:"topic"}),y=t(h),f={Type:"AWS::SNS::Topic",Properties:{TopicName:h,DisplayName:c||h,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(l&&u)f.Properties.KmsMasterKeyId=u;return{topic:f,logicalId:y}}static subscribe(n,i){let{slug:s,environment:o,protocol:c,endpoint:l,filterPolicy:u,rawMessageDelivery:h=!1}=i,y=r({slug:s,environment:o,resourceType:"subscription"}),f=l.replace(/[^a-zA-Z0-9]/g,""),b=f.length>12?f.slice(-12):f,C=t(`${y}-${c}-${b}`),T={Type:"AWS::SNS::Subscription",Properties:{TopicArn:k.Ref(n),Protocol:c,Endpoint:l,RawMessageDelivery:h}};if(u)T.Properties.FilterPolicy=u;return{subscription:T,logicalId:C}}static subscribeEmail(n,i,s){return te.subscribe(n,{...s,protocol:"email",endpoint:i})}static subscribeLambda(n,i,s){return te.subscribe(n,{...s,protocol:"lambda",endpoint:i,rawMessageDelivery:!0})}static subscribeSqs(n,i,s){return te.subscribe(n,{...s,protocol:"sqs",endpoint:i})}static subscribeHttp(n,i,s){let o=i.startsWith("https://")?"https":"http";return te.subscribe(n,{...s,protocol:o,endpoint:i})}static subscribeSms(n,i,s){return te.subscribe(n,{...s,protocol:"sms",endpoint:i})}static setTopicPolicy(n,i){let{slug:s,environment:o,allowedPrincipals:c,allowedServices:l,actions:u="SNS:Publish"}=i,h=r({slug:s,environment:o,resourceType:"topic-policy"}),y=t(h),f={};if(c)f.AWS=c;if(l)f.Service=l;return{policy:{Type:"AWS::SNS::TopicPolicy",Properties:{Topics:[k.Ref(n)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:f,Action:u,Resource:k.Ref(n)}]}}},logicalId:y}}static allowCloudWatchAlarms(n,i){return te.setTopicPolicy(n,{...i,allowedServices:"cloudwatch.amazonaws.com",actions:"SNS:Publish"})}static allowEventBridge(n,i){return te.setTopicPolicy(n,{...i,allowedServices:"events.amazonaws.com",actions:"SNS:Publish"})}static allowS3(n,i){return te.setTopicPolicy(n,{...i,allowedServices:"s3.amazonaws.com",actions:"SNS:Publish"})}static enableEncryption(n,i){if(!n.Properties)n.Properties={};return n.Properties.KmsMasterKeyId=i,n}static addInlineSubscription(n,i,s){if(!n.Properties)n.Properties={};if(!n.Properties.Subscription)n.Properties.Subscription=[];return n.Properties.Subscription.push({Protocol:i,Endpoint:s}),n}static FilterPolicies={eventType:(n)=>({eventType:n}),status:(n)=>({status:n}),numericRange:(n,i,s)=>({[n]:[{numeric:[">=",i,"<=",s]}]}),prefix:(n,i)=>({[n]:[{prefix:i}]}),and:(...n)=>Object.assign({},...n),exists:(n,i)=>({[n]:[{exists:i}]})};static UseCases={createAlertTopic:(n)=>te.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-alerts`,displayName:n.displayName||"Alert Notifications"}),createEventFanout:(n)=>te.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-events`,displayName:n.displayName||"Event Fanout"}),createNotificationTopic:(n)=>te.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-notifications`,displayName:n.displayName||"User Notifications"})}}class dA{static createStateMachine(n){let{slug:i,environment:s,stateMachineName:o,type:c="STANDARD",definition:l,roleArn:u,loggingConfiguration:h,tracingConfiguration:y}=n,f=o||r({slug:i,environment:s,resourceType:"state-machine"}),b=t(f),C,T,w;if(u)w=u;else{let I=r({slug:i,environment:s,resourceType:"state-machine-role"});T=t(I),C={Type:"AWS::IAM::Role",Properties:{RoleName:I,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:I},{Key:"Environment",Value:s}]}},w=k.GetAtt(T,"Arn")}let E={Type:"AWS::StepFunctions::StateMachine",Properties:{StateMachineName:f,StateMachineType:c,DefinitionString:JSON.stringify(l),RoleArn:w,Tags:[{Key:"Name",Value:f},{Key:"Environment",Value:s}]}};if(h)E.Properties.LoggingConfiguration={Level:h.level,IncludeExecutionData:h.includeExecutionData,Destinations:h.destinations?.map((I)=>({CloudWatchLogsLogGroup:{LogGroupArn:I}}))};if(y)E.Properties.TracingConfiguration={Enabled:y.enabled};return{stateMachine:E,logicalId:b,role:C,roleLogicalId:T}}static createLambdaTask(n,i){return{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Parameters:{FunctionName:n,Payload:i?.parameters||{"Input.$":"$"}},ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createDynamoDBTask(n,i,s,o){return{Type:"Task",Resource:{GetItem:"arn:aws:states:::dynamodb:getItem",PutItem:"arn:aws:states:::dynamodb:putItem",UpdateItem:"arn:aws:states:::dynamodb:updateItem",DeleteItem:"arn:aws:states:::dynamodb:deleteItem"}[n],Parameters:{TableName:i,...s},ResultPath:o?.resultPath,Retry:o?.retry,Catch:o?.catch,Next:o?.next,End:o?.end}}static createSNSPublishTask(n,i,s){return{Type:"Task",Resource:"arn:aws:states:::sns:publish",Parameters:{TopicArn:n,Message:i},ResultPath:s?.resultPath,Retry:s?.retry,Catch:s?.catch,Next:s?.next,End:s?.end}}static createSQSSendMessageTask(n,i,s){return{Type:"Task",Resource:"arn:aws:states:::sqs:sendMessage",Parameters:{QueueUrl:n,MessageBody:i},ResultPath:s?.resultPath,Retry:s?.retry,Catch:s?.catch,Next:s?.next,End:s?.end}}static createPassState(n){return{Type:"Pass",Result:n?.result,ResultPath:n?.resultPath,Parameters:n?.parameters,Next:n?.next,End:n?.end}}static createWaitState(n){return{Type:"Wait",Seconds:n.seconds,Timestamp:n.timestamp,SecondsPath:n.secondsPath,TimestampPath:n.timestampPath,Next:n.next,End:n.end}}static createChoiceState(n,i){return{Type:"Choice",Choices:n,Default:i}}static createParallelState(n,i){return{Type:"Parallel",Branches:n,ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createMapState(n,i){return{Type:"Map",ItemsPath:i?.itemsPath||"$.items",Iterator:n,MaxConcurrency:i?.maxConcurrency,ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createSucceedState(){return{Type:"Succeed"}}static createFailState(n,i){return{Type:"Fail",Error:n,Cause:i}}static RetryPolicies={standard:()=>({ErrorEquals:["States.ALL"],IntervalSeconds:2,MaxAttempts:3,BackoffRate:2}),aggressive:()=>({ErrorEquals:["States.TaskFailed","States.Timeout"],IntervalSeconds:1,MaxAttempts:5,BackoffRate:1.5}),custom:(n,i,s,o)=>({ErrorEquals:n,IntervalSeconds:i,MaxAttempts:s,BackoffRate:o})};static CatchPolicies={all:(n,i)=>({ErrorEquals:["States.ALL"],Next:n,ResultPath:i||"$.error"}),specific:(n,i,s)=>({ErrorEquals:n,Next:i,ResultPath:s||"$.error"})};static Patterns={sequential:(n,i,s)=>{let o={};return s.forEach((c,l)=>{let u=l===s.length-1;o[c.name]={...c.state,Next:u?void 0:s[l+1].name,End:u}}),{Comment:"Sequential workflow",StartAt:s[0].name,States:o}},fanout:(n,i,s)=>({Comment:"Fan-out workflow",StartAt:"Parallel",States:{Parallel:{Type:"Parallel",Branches:s.map((o)=>o.definition),End:!0}}}),map:(n,i,s,o)=>({Comment:"Map workflow",StartAt:"Map",States:{Map:{Type:"Map",ItemsPath:"$.items",Iterator:s,MaxConcurrency:o,End:!0}}}),withErrorHandling:(n,i,s,o)=>({Comment:"Workflow with error handling",StartAt:"Main",States:{Main:{...s,Catch:[{ErrorEquals:["States.ALL"],Next:"ErrorHandler"}],Next:"Success"},ErrorHandler:o,Success:{Type:"Succeed"}}})}}class go{static createAlarm(n){let{slug:i,environment:s,alarmName:o,metricName:c,namespace:l,statistic:u="Average",period:h=300,evaluationPeriods:y=1,threshold:f,comparisonOperator:b,treatMissingData:C="notBreaching",actionsEnabled:T=!0,alarmActions:w,okActions:E,insufficientDataActions:I,dimensions:N,unit:D,datapointsToAlarm:x}=n,R=o||r({slug:i,environment:s,resourceType:"alarm"}),_=t(R),B={Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:R,MetricName:c,Namespace:l,Statistic:u,Period:h,EvaluationPeriods:y,Threshold:f,ComparisonOperator:b,TreatMissingData:C,ActionsEnabled:T}};if(w&&w.length>0)B.Properties.AlarmActions=w;if(E&&E.length>0)B.Properties.OKActions=E;if(I&&I.length>0)B.Properties.InsufficientDataActions=I;if(N)B.Properties.Dimensions=Object.entries(N).map(([W,J])=>({Name:W,Value:J}));if(D)B.Properties.Unit=D;if(x!==void 0)B.Properties.DatapointsToAlarm=x;return{alarm:B,logicalId:_}}static createCompositeAlarm(n){let{slug:i,environment:s,alarmName:o,alarmRule:c,actionsEnabled:l=!0,alarmActions:u,okActions:h,insufficientDataActions:y}=n,f=o||r({slug:i,environment:s,resourceType:"composite-alarm"}),b=t(f),C={Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:f,AlarmRule:c,ActionsEnabled:l}};if(u&&u.length>0)C.Properties.AlarmActions=u;if(h&&h.length>0)C.Properties.OKActions=h;if(y&&y.length>0)C.Properties.InsufficientDataActions=y;return{alarm:C,logicalId:b}}static createDashboard(n){let{slug:i,environment:s,dashboardName:o,widgets:c}=n,l=o||r({slug:i,environment:s,resourceType:"dashboard"}),u=t(l),h={widgets:c.map((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(n){let{slug:i,environment:s,logGroupName:o,retentionInDays:c,kmsKeyId:l}=n,u=o||r({slug:i,environment:s,resourceType:"log-group"}),h=t(u),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(n,i){let{slug:s,environment:o,logStreamName:c}=i,l=c||r({slug:s,environment:o,resourceType:"log-stream"}),u=t(l);return{logStream:{Type:"AWS::Logs::LogStream",Properties:{LogGroupName:k.Ref(n),LogStreamName:l}},logicalId:u}}static createMetricFilter(n,i){let{slug:s,environment:o,filterName:c,filterPattern:l,metricTransformations:u}=i,h=c||r({slug:s,environment:o,resourceType:"metric-filter"}),y=t(h);return{metricFilter:{Type:"AWS::Logs::MetricFilter",Properties:{LogGroupName:k.Ref(n),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:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-high-cpu`,metricName:"CPUUtilization",namespace:"AWS/EC2",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s},alarmActions:c?[c]:void 0}),highMemory:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-high-memory`,metricName:"MemoryUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s},alarmActions:c?[c]:void 0}),highDisk:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-high-disk`,metricName:"DiskSpaceUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s,Filesystem:"/dev/xvda1",MountPath:"/"},alarmActions:c?[c]:void 0}),lambdaErrors:(n,i,s,o=5,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-lambda-errors`,metricName:"Errors",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:s},alarmActions:c?[c]:void 0}),lambdaThrottles:(n,i,s,o=10,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-lambda-throttles`,metricName:"Throttles",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:s},alarmActions:c?[c]:void 0}),apiGateway5xxErrors:(n,i,s,o=10,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-api-5xx-errors`,metricName:"5XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:s},alarmActions:c?[c]:void 0}),apiGateway4xxErrors:(n,i,s,o=50,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-api-4xx-errors`,metricName:"4XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:s},alarmActions:c?[c]:void 0}),dynamoDBThrottles:(n,i,s,o=5,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-dynamodb-throttles`,metricName:"UserErrors",namespace:"AWS/DynamoDB",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{TableName:s},alarmActions:c?[c]:void 0}),rdsCpu:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-rds-cpu`,metricName:"CPUUtilization",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{DBInstanceIdentifier:s},alarmActions:c?[c]:void 0}),rdsFreeStorage:(n,i,s,o=5368709120,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-rds-storage`,metricName:"FreeStorageSpace",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"LessThanThreshold",dimensions:{DBInstanceIdentifier:s},alarmActions:c?[c]:void 0,unit:"Bytes"}),sqsQueueDepth:(n,i,s,o=100,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-sqs-depth`,metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{QueueName:s},alarmActions:c?[c]:void 0}),albUnhealthyTargets:(n,i,s,o,c=1,l)=>({slug:n,environment:i,alarmName:`${n}-${i}-alb-unhealthy`,metricName:"UnHealthyHostCount",namespace:"AWS/ApplicationELB",statistic:"Average",period:300,evaluationPeriods:2,threshold:c,comparisonOperator:"GreaterThanThreshold",dimensions:{LoadBalancer:s,TargetGroup:o},alarmActions:l?[l]:void 0}),sesBounceRate:(n,i,s=5,o)=>({slug:n,environment:i,alarmName:`${n}-${i}-ses-bounce-rate`,metricName:"Reputation.BounceRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:s/100,comparisonOperator:"GreaterThanThreshold",alarmActions:o?[o]:void 0}),sesComplaintRate:(n,i,s=0.1,o)=>({slug:n,environment:i,alarmName:`${n}-${i}-ses-complaint-rate`,metricName:"Reputation.ComplaintRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:s/100,comparisonOperator:"GreaterThanThreshold",alarmActions:o?[o]:void 0}),smsDeliveryFailure:(n,i,s,o=10,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-sms-delivery-failure`,metricName:"DirectSendMessagePermanentFailure",namespace:"AWS/Pinpoint",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{ApplicationId:s},alarmActions:c?[c]:void 0}),smsSpendLimit:(n,i,s=100,o)=>({slug:n,environment:i,alarmName:`${n}-${i}-sms-spend-limit`,metricName:"DirectSendMessageSpend",namespace:"AWS/Pinpoint",statistic:"Sum",period:86400,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",alarmActions:o?[o]:void 0}),connectMissedCalls:(n,i,s,o=5,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-connect-missed-calls`,metricName:"MissedCalls",namespace:"AWS/Connect",statistic:"Sum",period:3600,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s},alarmActions:c?[c]:void 0})};static DashboardWidgets={metric:(n,i,s,o,c,l)=>({type:"metric",x:n,y:i,width:s,height:o,properties:{metrics:c,title:l||"Metrics",region:"us-east-1",period:300}}),text:(n,i,s,o,c)=>({type:"text",x:n,y:i,width:s,height:o,properties:{markdown:c}}),log:(n,i,s,o,c,l)=>({type:"log",x:n,y:i,width:s,height:o,properties:{query:`SOURCE '${c.join("' | SOURCE '")}'
2310
2310
  | fields @timestamp, @message
2311
2311
  | sort @timestamp desc
2312
2312
  | limit 20`,region:"us-east-1",title:l||"Logs"}})};static RetentionPeriods={ONE_DAY:1,THREE_DAYS:3,FIVE_DAYS:5,ONE_WEEK:7,TWO_WEEKS:14,ONE_MONTH:30,TWO_MONTHS:60,THREE_MONTHS:90,FOUR_MONTHS:120,FIVE_MONTHS:150,SIX_MONTHS:180,ONE_YEAR:365,THIRTEEN_MONTHS:400,EIGHTEEN_MONTHS:545,TWO_YEARS:731,FIVE_YEARS:1827,TEN_YEARS:3653,NEVER_EXPIRE:void 0};static FilterPatterns={errors:"[time, request_id, event_type = ERROR*, ...]",all:"",jsonField:(n,i)=>`{ $.${n} = "${i}" }`,httpStatus:(n)=>`[..., status_code = ${n}, ...]`,http4xx:"[..., status_code = 4*, ...]",http5xx:"[..., status_code = 5*, ...]"};static createApplicationDashboard(n){let{slug:i,environment:s,region:o="us-east-1",components:c={}}=n,l=[],u=0;if(l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:`# ${i.toUpperCase()} Dashboard (${s})`}}),u+=1,c.ec2InstanceIds&&c.ec2InstanceIds.length>0)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## EC2 Instances"}}),u+=1,l.push({type:"metric",x:0,y:u,width:8,height:6,properties:{title:"CPU Utilization",region:o,metrics:c.ec2InstanceIds.map((h)=>["AWS/EC2","CPUUtilization","InstanceId",h]),period:300,stat:"Average"}}),l.push({type:"metric",x:8,y:u,width:8,height:6,properties:{title:"Network Traffic",region:o,metrics:[...c.ec2InstanceIds.flatMap((h)=>[["AWS/EC2","NetworkIn","InstanceId",h,{label:`${h} In`}],["AWS/EC2","NetworkOut","InstanceId",h,{label:`${h} Out`}]])],period:300,stat:"Sum"}}),l.push({type:"metric",x:16,y:u,width:8,height:6,properties:{title:"Status Checks",region:o,metrics:c.ec2InstanceIds.map((h)=>["AWS/EC2","StatusCheckFailed","InstanceId",h]),period:60,stat:"Maximum"}}),u+=6;if(c.lambdaFunctionNames&&c.lambdaFunctionNames.length>0)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## Lambda Functions"}}),u+=1,l.push({type:"metric",x:0,y:u,width:8,height:6,properties:{title:"Invocations",region:o,metrics:c.lambdaFunctionNames.map((h)=>["AWS/Lambda","Invocations","FunctionName",h]),period:300,stat:"Sum"}}),l.push({type:"metric",x:8,y:u,width:8,height:6,properties:{title:"Duration",region:o,metrics:c.lambdaFunctionNames.map((h)=>["AWS/Lambda","Duration","FunctionName",h]),period:300,stat:"Average"}}),l.push({type:"metric",x:16,y:u,width:8,height:6,properties:{title:"Errors",region:o,metrics:c.lambdaFunctionNames.map((h)=>["AWS/Lambda","Errors","FunctionName",h]),period:300,stat:"Sum"}}),u+=6;if(c.ecsClusterName&&c.ecsServiceName)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## ECS Service"}}),u+=1,l.push({type:"metric",x:0,y:u,width:8,height:6,properties:{title:"CPU Utilization",region:o,metrics:[["AWS/ECS","CPUUtilization","ClusterName",c.ecsClusterName,"ServiceName",c.ecsServiceName]],period:300,stat:"Average"}}),l.push({type:"metric",x:8,y:u,width:8,height:6,properties:{title:"Memory Utilization",region:o,metrics:[["AWS/ECS","MemoryUtilization","ClusterName",c.ecsClusterName,"ServiceName",c.ecsServiceName]],period:300,stat:"Average"}}),l.push({type:"metric",x:16,y:u,width:8,height:6,properties:{title:"Running Tasks",region:o,metrics:[["ECS/ContainerInsights","RunningTaskCount","ClusterName",c.ecsClusterName,"ServiceName",c.ecsServiceName]],period:60,stat:"Average"}}),u+=6;if(c.albName)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## Application Load Balancer"}}),u+=1,l.push({type:"metric",x:0,y:u,width:8,height:6,properties:{title:"Request Count",region:o,metrics:[["AWS/ApplicationELB","RequestCount","LoadBalancer",c.albName]],period:60,stat:"Sum"}}),l.push({type:"metric",x:8,y:u,width:8,height:6,properties:{title:"Response Time",region:o,metrics:[["AWS/ApplicationELB","TargetResponseTime","LoadBalancer",c.albName]],period:60,stat:"Average"}}),l.push({type:"metric",x:16,y:u,width:8,height:6,properties:{title:"HTTP Errors",region:o,metrics:[["AWS/ApplicationELB","HTTPCode_Target_4XX_Count","LoadBalancer",c.albName,{label:"4XX"}],["AWS/ApplicationELB","HTTPCode_Target_5XX_Count","LoadBalancer",c.albName,{label:"5XX"}]],period:60,stat:"Sum"}}),u+=6;if(c.rdsInstanceId)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## RDS Database"}}),u+=1,l.push({type:"metric",x:0,y:u,width:8,height:6,properties:{title:"CPU Utilization",region:o,metrics:[["AWS/RDS","CPUUtilization","DBInstanceIdentifier",c.rdsInstanceId]],period:300,stat:"Average"}}),l.push({type:"metric",x:8,y:u,width:8,height:6,properties:{title:"Database Connections",region:o,metrics:[["AWS/RDS","DatabaseConnections","DBInstanceIdentifier",c.rdsInstanceId]],period:60,stat:"Sum"}}),l.push({type:"metric",x:16,y:u,width:8,height:6,properties:{title:"Free Storage Space",region:o,metrics:[["AWS/RDS","FreeStorageSpace","DBInstanceIdentifier",c.rdsInstanceId]],period:300,stat:"Average"}}),u+=6;if(c.sqsQueueNames&&c.sqsQueueNames.length>0)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## SQS Queues"}}),u+=1,l.push({type:"metric",x:0,y:u,width:12,height:6,properties:{title:"Messages Visible",region:o,metrics:c.sqsQueueNames.map((h)=>["AWS/SQS","ApproximateNumberOfMessagesVisible","QueueName",h]),period:60,stat:"Sum"}}),l.push({type:"metric",x:12,y:u,width:12,height:6,properties:{title:"Message Age",region:o,metrics:c.sqsQueueNames.map((h)=>["AWS/SQS","ApproximateAgeOfOldestMessage","QueueName",h]),period:60,stat:"Maximum"}}),u+=6;if(c.logGroupNames&&c.logGroupNames.length>0)l.push({type:"text",x:0,y:u,width:24,height:1,properties:{markdown:"## Application Logs"}}),u+=1,l.push({type:"log",x:0,y:u,width:24,height:6,properties:{query:`SOURCE '${c.logGroupNames.join("' | SOURCE '")}'
2313
2313
  | fields @timestamp, @message
2314
2314
  | filter @message like /ERROR|WARN|Exception/
2315
2315
  | sort @timestamp desc
2316
- | limit 50`,region:o,title:"Recent Errors and Warnings"}}),u+=6;return uo.createDashboard({slug:i,environment:s,widgets:l})}static DashboardTemplates={staticWebsite:(n)=>({slug:n.slug,environment:n.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${n.slug.toUpperCase()} Static Website Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"CloudFront Requests",region:"us-east-1",metrics:[["AWS/CloudFront","Requests","DistributionId",n.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"Error Rate",region:"us-east-1",metrics:[["AWS/CloudFront","4xxErrorRate","DistributionId",n.cloudFrontDistributionId,"Region","Global",{label:"4XX"}],["AWS/CloudFront","5xxErrorRate","DistributionId",n.cloudFrontDistributionId,"Region","Global",{label:"5XX"}]],period:300,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Bytes Downloaded",region:"us-east-1",metrics:[["AWS/CloudFront","BytesDownloaded","DistributionId",n.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:0,y:7,width:12,height:6,properties:{title:"S3 Bucket Size",region:n.region||"us-east-1",metrics:[["AWS/S3","BucketSizeBytes","BucketName",n.s3BucketName,"StorageType","StandardStorage"]],period:86400,stat:"Average"}},{type:"metric",x:12,y:7,width:12,height:6,properties:{title:"S3 Number of Objects",region:n.region||"us-east-1",metrics:[["AWS/S3","NumberOfObjects","BucketName",n.s3BucketName,"StorageType","AllStorageTypes"]],period:86400,stat:"Average"}}]}),serverlessApi:(n)=>({slug:n.slug,environment:n.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${n.slug.toUpperCase()} Serverless API Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"API Requests",region:n.region||"us-east-1",metrics:[["AWS/ApiGateway","Count","ApiName",n.apiGatewayName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"API Latency",region:n.region||"us-east-1",metrics:[["AWS/ApiGateway","Latency","ApiName",n.apiGatewayName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"API Errors",region:n.region||"us-east-1",metrics:[["AWS/ApiGateway","4XXError","ApiName",n.apiGatewayName,{label:"4XX"}],["AWS/ApiGateway","5XXError","ApiName",n.apiGatewayName,{label:"5XX"}]],period:60,stat:"Sum"}},...n.lambdaFunctionNames.map((i,s)=>({type:"metric",x:s%3*8,y:7+Math.floor(s/3)*6,width:8,height:6,properties:{title:`${i} Metrics`,region:n.region||"us-east-1",metrics:[["AWS/Lambda","Invocations","FunctionName",i],["AWS/Lambda","Duration","FunctionName",i],["AWS/Lambda","Errors","FunctionName",i]],period:300,stat:"Sum"}}))]}),containerService:(n)=>({slug:n.slug,environment:n.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${n.slug.toUpperCase()} Container Service Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"ECS CPU",region:n.region||"us-east-1",metrics:[["AWS/ECS","CPUUtilization","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"ECS Memory",region:n.region||"us-east-1",metrics:[["AWS/ECS","MemoryUtilization","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Running Tasks",region:n.region||"us-east-1",metrics:[["ECS/ContainerInsights","RunningTaskCount","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:0,y:7,width:8,height:6,properties:{title:"ALB Requests",region:n.region||"us-east-1",metrics:[["AWS/ApplicationELB","RequestCount","LoadBalancer",n.albName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:7,width:8,height:6,properties:{title:"Response Time",region:n.region||"us-east-1",metrics:[["AWS/ApplicationELB","TargetResponseTime","LoadBalancer",n.albName]],period:60,stat:"Average"}},{type:"metric",x:16,y:7,width:8,height:6,properties:{title:"Healthy Hosts",region:n.region||"us-east-1",metrics:[["AWS/ApplicationELB","HealthyHostCount","LoadBalancer",n.albName]],period:60,stat:"Average"}},...n.rdsInstanceId?[{type:"metric",x:0,y:13,width:12,height:6,properties:{title:"RDS CPU",region:n.region||"us-east-1",metrics:[["AWS/RDS","CPUUtilization","DBInstanceIdentifier",n.rdsInstanceId]],period:300,stat:"Average"}},{type:"metric",x:12,y:13,width:12,height:6,properties:{title:"RDS Connections",region:n.region||"us-east-1",metrics:[["AWS/RDS","DatabaseConnections","DBInstanceIdentifier",n.rdsInstanceId]],period:60,stat:"Sum"}}]:[]]})};static Config={createAlarmConfig:(n)=>{let{metricName:i,namespace:s,threshold:o,comparisonOperator:c="GreaterThanThreshold",evaluationPeriods:l=1,period:u=300,statistic:h="Average",treatMissingData:y="missing"}=n;return{MetricName:i,Namespace:s,Threshold:o,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:(n=80)=>({metricName:"CPUUtilization",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highMemory:(n=80)=>({metricName:"MemoryUtilization",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highErrors:(n=10)=>({metricName:"Errors",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:1,period:60,statistic:"Sum"}),highLatency:(n=5000)=>({metricName:"Duration",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowHealthyHosts:(n=1)=>({metricName:"HealthyHostCount",namespace:"AWS/ApplicationELB",threshold:n,comparisonOperator:"LessThanThreshold",evaluationPeriods:2,period:60,statistic:"Minimum"}),queueDepth:(n=1000)=>({metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowStorage:(n=10737418240)=>({metricName:"FreeStorageSpace",namespace:"AWS/RDS",threshold:n,comparisonOperator:"LessThanThreshold",evaluationPeriods:1,period:300,statistic:"Average"})}}}class Q{static createUserPool(n){let{slug:i,environment:s,userPoolName:o,aliasAttributes:c,autoVerifiedAttributes:l,passwordPolicy:u,mfaConfiguration:h,emailConfiguration:y,smsConfiguration:f,lambdaTriggers:b,userPoolAddOns:C,accountRecoverySetting:T}=n,w=o||r({slug:i,environment:s,resourceType:"user-pool"}),E=t(w),I={Type:"AWS::Cognito::UserPool",Properties:{UserPoolName:w,Policies:u?{PasswordPolicy:{MinimumLength:u.minimumLength,RequireLowercase:u.requireLowercase,RequireUppercase:u.requireUppercase,RequireNumbers:u.requireNumbers,RequireSymbols:u.requireSymbols,TemporaryPasswordValidityDays:u.temporaryPasswordValidityDays}}:void 0,MfaConfiguration:h,Schema:[{Name:"email",AttributeDataType:"String",Required:!0,Mutable:!1}]}};if(c&&c.length>0)I.Properties.UsernameAttributes=c;if(l&&l.length>0)I.Properties.AutoVerifiedAttributes=l;if(y)I.Properties.EmailConfiguration={EmailSendingAccount:y.emailSendingAccount,From:y.from,ReplyToEmailAddress:y.replyToEmailAddress,SourceArn:y.sourceArn,ConfigurationSet:y.configurationSet};if(f)I.Properties.SmsConfiguration={ExternalId:f.externalId,SnsCallerArn:f.snsCallerArn};if(b)I.Properties.LambdaConfig={PreSignUp:b.preSignUp,PostConfirmation:b.postConfirmation,PreAuthentication:b.preAuthentication,PostAuthentication:b.postAuthentication,CustomMessage:b.customMessage,DefineAuthChallenge:b.defineAuthChallenge,CreateAuthChallenge:b.createAuthChallenge,VerifyAuthChallengeResponse:b.verifyAuthChallengeResponse,PreTokenGeneration:b.preTokenGeneration,UserMigration:b.userMigration};if(C)I.Properties.UserPoolAddOns={AdvancedSecurityMode:C.advancedSecurityMode};if(T)I.Properties.AccountRecoverySetting={RecoveryMechanisms:T.recoveryMechanisms};return{userPool:I,logicalId:E}}static createUserPoolClient(n,i){let{slug:s,environment:o,clientName:c,generateSecret:l=!1,refreshTokenValidity:u,accessTokenValidity:h,idTokenValidity:y,tokenValidityUnits:f,readAttributes:b,writeAttributes:C,explicitAuthFlows:T,preventUserExistenceErrors:w,enableTokenRevocation:E,callbackURLs:I,logoutURLs:N,allowedOAuthFlows:D,allowedOAuthScopes:B,allowedOAuthFlowsUserPoolClient:R,supportedIdentityProviders:W}=i,_=c||r({slug:s,environment:o,resourceType:"user-pool-client"}),j=t(_);return{client:{Type:"AWS::Cognito::UserPoolClient",Properties:{ClientName:_,UserPoolId:k.Ref(n),GenerateSecret:l,RefreshTokenValidity:u,AccessTokenValidity:h,IdTokenValidity:y,TokenValidityUnits:f,ReadAttributes:b,WriteAttributes:C,ExplicitAuthFlows:T,PreventUserExistenceErrors:w,EnableTokenRevocation:E,CallbackURLs:I,LogoutURLs:N,AllowedOAuthFlows:D,AllowedOAuthScopes:B,AllowedOAuthFlowsUserPoolClient:R,SupportedIdentityProviders:W}},logicalId:j}}static createUserPoolDomain(n,i){let{slug:s,environment:o,domain:c,customDomainConfig:l}=i,u=r({slug:s,environment:o,resourceType:"user-pool-domain"}),h=t(u);return{domain:{Type:"AWS::Cognito::UserPoolDomain",Properties:{Domain:c,UserPoolId:k.Ref(n),CustomDomainConfig:l}},logicalId:h}}static createIdentityPool(n){let{slug:i,environment:s,identityPoolName:o,allowUnauthenticatedIdentities:c=!1,cognitoIdentityProviders:l,supportedLoginProviders:u,samlProviderARNs:h,openIdConnectProviderARNs:y}=n,f=o||r({slug:i,environment:s,resourceType:"identity-pool"}),b=t(f);return{identityPool:{Type:"AWS::Cognito::IdentityPool",Properties:{IdentityPoolName:f,AllowUnauthenticatedIdentities:c,CognitoIdentityProviders:l,SupportedLoginProviders:u,SamlProviderARNs:h,OpenIdConnectProviderARNs:y}},logicalId:b}}static createIdentityPoolRoleAttachment(n,i){let{slug:s,environment:o,authenticatedRole:c,unauthenticatedRole:l,roleMappings:u}=i,h=r({slug:s,environment:o,resourceType:"identity-pool-role-attachment"}),y=t(h),f={authenticated:c};if(l)f.unauthenticated=l;return{attachment:{Type:"AWS::Cognito::IdentityPoolRoleAttachment",Properties:{IdentityPoolId:k.Ref(n),Roles:f,RoleMappings:u}},logicalId:y}}static createAuthenticatedRole(n){let{slug:i,environment:s,identityPoolLogicalId:o}=n,c=r({slug:i,environment:s,resourceType:"cognito-authenticated-role"}),l=t(c);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:c,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":k.Ref(o)},"ForAnyValue:StringLike":{"cognito-identity.amazonaws.com:amr":"authenticated"}}}]},Policies:[{PolicyName:"CognitoAuthenticatedPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["cognito-sync:*","cognito-identity:*"],Resource:"*"}]}}],Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:s}]}},logicalId:l}}static createUnauthenticatedRole(n){let{slug:i,environment:s,identityPoolLogicalId:o}=n,c=r({slug:i,environment:s,resourceType:"cognito-unauthenticated-role"}),l=t(c);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:c,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":k.Ref(o)},"ForAnyValue:StringLike":{"cognito-identity.amazonaws.com:amr":"unauthenticated"}}}]},Policies:[{PolicyName:"CognitoUnauthenticatedPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["cognito-sync:*"],Resource:"*"}]}}],Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:s}]}},logicalId:l}}static PasswordPolicies={relaxed:()=>({minimumLength:8,requireLowercase:!1,requireUppercase:!1,requireNumbers:!1,requireSymbols:!1,temporaryPasswordValidityDays:7}),standard:()=>({minimumLength:8,requireLowercase:!0,requireUppercase:!0,requireNumbers:!0,requireSymbols:!1,temporaryPasswordValidityDays:3}),strict:()=>({minimumLength:12,requireLowercase:!0,requireUppercase:!0,requireNumbers:!0,requireSymbols:!0,temporaryPasswordValidityDays:1})};static AuthFlows={standard:["ALLOW_USER_SRP_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],admin:["ALLOW_ADMIN_USER_PASSWORD_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],custom:["ALLOW_CUSTOM_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],all:["ALLOW_USER_SRP_AUTH","ALLOW_USER_PASSWORD_AUTH","ALLOW_ADMIN_USER_PASSWORD_AUTH","ALLOW_CUSTOM_AUTH","ALLOW_REFRESH_TOKEN_AUTH"]};static OAuthScopes={basic:["openid","email","profile"],all:["openid","email","profile","phone","aws.cognito.signin.user.admin"]};static UseCases={webApp:(n,i,s)=>{let{userPool:o,logicalId:c}=Q.createUserPool({slug:n,environment:i,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:Q.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:l,logicalId:u}=Q.createUserPoolClient(c,{slug:n,environment:i,explicitAuthFlows:[...Q.AuthFlows.standard],callbackURLs:[s],allowedOAuthFlows:["code"],allowedOAuthScopes:[...Q.OAuthScopes.basic],allowedOAuthFlowsUserPoolClient:!0});return{userPool:o,poolId:c,client:l,clientId:u}},mobileApp:(n,i)=>{let{userPool:s,logicalId:o}=Q.createUserPool({slug:n,environment:i,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:Q.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:c,logicalId:l}=Q.createUserPoolClient(o,{slug:n,environment:i,explicitAuthFlows:[...Q.AuthFlows.standard]}),{identityPool:u,logicalId:h}=Q.createIdentityPool({slug:n,environment:i,allowUnauthenticatedIdentities:!1,cognitoIdentityProviders:[{ClientId:k.Ref(l),ProviderName:k.GetAtt(o,"ProviderName")}]}),{role:y,logicalId:f}=Q.createAuthenticatedRole({slug:n,environment:i,identityPoolLogicalId:h}),{attachment:b,logicalId:C}=Q.createIdentityPoolRoleAttachment(h,{slug:n,environment:i,authenticatedRole:k.GetAtt(f,"Arn")});return{userPool:s,poolId:o,client:c,clientId:l,identityPool:u,identityPoolId:h,authRole:y,authRoleId:f,attachment:b,attachmentId:C}}}}class H{static createApplication(n){let{slug:i,environment:s,applicationName:o,computePlatform:c}=n,l=o||r({slug:i,environment:s,resourceType:"deploy-app"}),u=t(l);return{application:{Type:"AWS::CodeDeploy::Application",Properties:{ApplicationName:l,ComputePlatform:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s}]}},logicalId:u}}static createDeploymentGroup(n,i){let{slug:s,environment:o,deploymentGroupName:c,serviceRoleArn:l,autoScalingGroups:u,ec2TagFilters:h,deploymentConfigName:y,autoRollbackConfiguration:f,alarmConfiguration:b,loadBalancerInfo:C,blueGreenDeploymentConfiguration:T}=i,w=c||r({slug:s,environment:o,resourceType:"deploy-group"}),E=t(w);return{deploymentGroup:{Type:"AWS::CodeDeploy::DeploymentGroup",Properties:{ApplicationName:k.Ref(n),DeploymentGroupName:w,ServiceRoleArn:l,AutoScalingGroups:u,Ec2TagFilters:h?.map((I)=>({Key:I.key,Value:I.value,Type:I.type})),DeploymentConfigName:y,AutoRollbackConfiguration:f?{Enabled:f.enabled,Events:f.events}:void 0,AlarmConfiguration:b?{Enabled:b.enabled,Alarms:b.alarms?.map((I)=>({Name:I.name})),IgnorePollAlarmFailure:b.ignorePollAlarmFailure}:void 0,LoadBalancerInfo:C?{TargetGroupInfoList:C.targetGroupInfoList?.map((I)=>({Name:I.name})),ElbInfoList:C.elbInfoList?.map((I)=>({Name:I.name}))}:void 0,BlueGreenDeploymentConfiguration:T?{TerminateBlueInstancesOnDeploymentSuccess:T.terminateBlueInstancesOnDeploymentSuccess?{Action:T.terminateBlueInstancesOnDeploymentSuccess.action,TerminationWaitTimeInMinutes:T.terminateBlueInstancesOnDeploymentSuccess.terminationWaitTimeInMinutes}:void 0,DeploymentReadyOption:T.deploymentReadyOption?{ActionOnTimeout:T.deploymentReadyOption.actionOnTimeout,WaitTimeInMinutes:T.deploymentReadyOption.waitTimeInMinutes}:void 0,GreenFleetProvisioningOption:T.greenFleetProvisioningOption?{Action:T.greenFleetProvisioningOption.action}:void 0}:void 0,Tags:[{Key:"Name",Value:w},{Key:"Environment",Value:o}]}},logicalId:E}}static createDeploymentConfig(n){let{slug:i,environment:s,deploymentConfigName:o,minimumHealthyHosts:c,trafficRoutingConfig:l}=n,u=o||r({slug:i,environment:s,resourceType:"deploy-config"}),h=t(u);return{deploymentConfig:{Type:"AWS::CodeDeploy::DeploymentConfig",Properties:{DeploymentConfigName:u,MinimumHealthyHosts:c?{Type:c.type,Value:c.value}:void 0,TrafficRoutingConfig:l?{Type:l.type,TimeBasedCanary:l.timeBasedCanary?{CanaryPercentage:l.timeBasedCanary.canaryPercentage,CanaryInterval:l.timeBasedCanary.canaryInterval}:void 0,TimeBasedLinear:l.timeBasedLinear?{LinearPercentage:l.timeBasedLinear.linearPercentage,LinearInterval:l.timeBasedLinear.linearInterval}:void 0}:void 0}},logicalId:h}}static DeploymentConfigs={allAtOnce:()=>({type:"FLEET_PERCENT",value:0}),halfAtATime:()=>({type:"FLEET_PERCENT",value:50}),oneAtATime:()=>({type:"HOST_COUNT",value:1}),custom:(n,i)=>({type:n,value:i})};static TrafficRouting={allAtOnce:()=>({type:"AllAtOnce"}),canary:(n,i)=>({type:"TimeBasedCanary",timeBasedCanary:{canaryPercentage:n,canaryInterval:i}}),linear:(n,i)=>({type:"TimeBasedLinear",timeBasedLinear:{linearPercentage:n,linearInterval:i}})};static RollbackConfigs={onFailure:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE"]}),onAlarmOrFailure:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE","DEPLOYMENT_STOP_ON_ALARM"]}),onAllEvents:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE","DEPLOYMENT_STOP_ON_ALARM","DEPLOYMENT_STOP_ON_REQUEST"]}),disabled:()=>({enabled:!1})};static BlueGreenConfigs={standard:()=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withDelay:(n)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:n},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withManualApproval:(n)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"STOP_DEPLOYMENT",waitTimeInMinutes:n},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),keepBlue:()=>({terminateBlueInstancesOnDeploymentSuccess:{action:"KEEP_ALIVE"},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}})};static UseCases={ec2Deployment:(n,i,s,o)=>{let{application:c,logicalId:l}=H.createApplication({slug:n,environment:i,computePlatform:"Server"}),{deploymentGroup:u,logicalId:h}=H.createDeploymentGroup(l,{slug:n,environment:i,serviceRoleArn:s,autoScalingGroups:o,deploymentConfigName:"CodeDeployDefault.OneAtATime",autoRollbackConfiguration:H.RollbackConfigs.onFailure()});return{application:c,appId:l,deploymentGroup:u,groupId:h}},lambdaCanaryDeployment:(n,i,s,o=10,c=5)=>{let{application:l,logicalId:u}=H.createApplication({slug:n,environment:i,computePlatform:"Lambda"}),{deploymentConfig:h,logicalId:y}=H.createDeploymentConfig({slug:n,environment:i,trafficRoutingConfig:H.TrafficRouting.canary(o,c)}),{deploymentGroup:f,logicalId:b}=H.createDeploymentGroup(u,{slug:n,environment:i,serviceRoleArn:s,deploymentConfigName:k.Ref(y),autoRollbackConfiguration:H.RollbackConfigs.onAlarmOrFailure()});return{application:l,appId:u,deploymentConfig:h,configId:y,deploymentGroup:f,groupId:b}},ecsBlueGreenDeployment:(n,i,s,o)=>{let{application:c,logicalId:l}=H.createApplication({slug:n,environment:i,computePlatform:"ECS"}),{deploymentGroup:u,logicalId:h}=H.createDeploymentGroup(l,{slug:n,environment:i,serviceRoleArn:s,loadBalancerInfo:{targetGroupInfoList:[{name:o}]},blueGreenDeploymentConfiguration:H.BlueGreenConfigs.standard(),autoRollbackConfiguration:H.RollbackConfigs.onFailure()});return{application:c,appId:l,deploymentGroup:u,groupId:h}}};static Strategies={rolling:(n=25)=>({type:"rolling",batchPercentage:n}),blueGreen:()=>({type:"blue-green"}),canary:(n=10,i=5)=>({type:"canary",canaryPercentage:n,canaryInterval:i}),allAtOnce:()=>({type:"all-at-once"})}}class P{static ContentTypes={".html":"text/html",".htm":"text/html",".css":"text/css",".js":"application/javascript",".mjs":"application/javascript",".json":"application/json",".xml":"application/xml",".svg":"image/svg+xml",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".avif":"image/avif",".ico":"image/x-icon",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".otf":"font/otf",".eot":"application/vnd.ms-fontobject",".pdf":"application/pdf",".txt":"text/plain",".md":"text/markdown",".map":"application/json"};static NoHashPatterns=[/^index\.html$/,/^favicon\.ico$/,/^robots\.txt$/,/^sitemap\.xml$/,/^manifest\.json$/,/^\.well-known\//,/^_redirects$/,/^_headers$/];static computeFileHash(n,i="md5"){let s=st(n);return Nr(i).update(s).digest("hex")}static computeShortHash(n){return P.computeFileHash(n).slice(0,8)}static getContentType(n){let i=ma(n).toLowerCase();return P.ContentTypes[i]||"application/octet-stream"}static shouldHashFile(n,i){return![...P.NoHashPatterns,...i||[]].some((s)=>s.test(n))}static generateHashedFilename(n,i){let s=ma(n),o=Lr(n,s),c=da(n);if(c===".")return`${o}.${i}${s}`;return Je(c,`${o}.${i}${s}`)}static collectFiles(n,i){let s=[],o=i||n;if(!Nt(n))return s;let c=kr(n,{withFileTypes:!0});for(let l of c){let u=Je(n,l.name);if(l.isDirectory())s.push(...P.collectFiles(u,o));else if(l.isFile())s.push(u)}return s}static hashDirectory(n){let{sourceDir:i,outputDir:s,excludePatterns:o=[],hashAlgorithm:c="md5",copyUnhashed:l=!0}=n,u=P.collectFiles(i),h=[],y={};for(let b of u){let C=b.replace(i,"").replace(/^[/\\]/,""),T=P.shouldHashFile(C,o),w=$r(b),E=T?P.computeFileHash(b,c).slice(0,8):"",I=T?P.generateHashedFilename(C,E):C,N={originalPath:C,hashedPath:I,hash:E,size:w.size,contentType:P.getContentType(b)};if(h.push(N),y[C]=I,s){let D=Je(s,I),B=da(D);if(!Nt(B)){let{mkdirSync:R}=ir("node:fs");R(B,{recursive:!0})}if(T||l)Dr(b,D)}}let f={version:"1.0",timestamp:new Date().toISOString(),assets:h,hashMap:y};if(s){let b=Je(s,"asset-manifest.json");ot(b,JSON.stringify(f,null,2))}return f}static getInvalidationPaths(n,i){let s=[];if(!n)return["/*"];let o=n.hashMap,c=i.hashMap;for(let[l,u]of Object.entries(c)){let h=o[l];if(!h||h!==u){if(s.push(`/${l}`),h&&h!==u)s.push(`/${h}`)}}for(let[l,u]of Object.entries(o))if(!c[l])s.push(`/${l}`),s.push(`/${u}`);if(s.length>100)return["/*"];return[...new Set(s)]}static updateHtmlReferences(n){let{htmlDir:i,manifest:s,basePath:o=""}=n,c=P.collectFiles(i).filter((l)=>l.endsWith(".html")||l.endsWith(".htm"));for(let l of c){let u=st(l,"utf-8");for(let[h,y]of Object.entries(s.hashMap)){if(h===y)continue;let f=[new RegExp(`(src|href)=["']${o}/?${P.escapeRegExp(h)}["']`,"g"),new RegExp(`url\\(["']?${o}/?${P.escapeRegExp(h)}["']?\\)`,"g")];for(let b of f)u=u.replace(b,(C)=>C.replace(h,y))}ot(l,u)}}static updateCssReferences(n){let{cssDir:i,manifest:s,basePath:o=""}=n,c=P.collectFiles(i).filter((l)=>l.endsWith(".css"));for(let l of c){let u=st(l,"utf-8");for(let[h,y]of Object.entries(s.hashMap)){if(h===y)continue;let f=new RegExp(`url\\(["']?${o}/?${P.escapeRegExp(h)}["']?\\)`,"g");u=u.replace(f,`url(${o}/${y})`)}ot(l,u)}}static escapeRegExp(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}static generateS3DeploymentManifest(n){let{sourceDir:i,keyPrefix:s="",excludePatterns:o=[],cacheControl:c={hashed:"public, max-age=31536000, immutable",unhashed:"public, max-age=3600",html:"public, max-age=0, must-revalidate"}}=n;return P.hashDirectory({sourceDir:i,excludePatterns:o}).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:Je(i,l.originalPath),s3Key:s?`${s}/${l.hashedPath}`:l.hashedPath,contentType:l.contentType,cacheControl:y,hash:l.hash}})}static compareManifests(n,i){let s={added:[],removed:[],changed:[],unchanged:[]},o=new Set(Object.keys(n.hashMap)),c=new Set(Object.keys(i.hashMap));for(let l of c)if(!o.has(l))s.added.push(l);for(let l of o)if(!c.has(l))s.removed.push(l);for(let l of c)if(o.has(l))if(n.hashMap[l]!==i.hashMap[l])s.changed.push(l);else s.unchanged.push(l);return s}static loadManifest(n){if(!Nt(n))return null;try{let i=st(n,"utf-8");return JSON.parse(i)}catch{return null}}static saveManifest(n,i){ot(i,JSON.stringify(n,null,2))}}class wi{static createSecret(n){let{slug:i,environment:s,secretName:o,description:c,secretString:l,kmsKeyId:u,tags:h}=n,y=o||r({slug:i,environment:s,resourceType:"secret"}),f=t(y),b={Type:"AWS::SecretsManager::Secret",Properties:{Name:y,Description:c,SecretString:l,Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:s},...h?Object.entries(h).map(([C,T])=>({Key:C,Value:T})):[]]}};if(u)b.Properties.KmsKeyId=u;return{secret:b,logicalId:f}}static createGeneratedSecret(n){let{slug:i,environment:s,secretName:o,description:c,excludeCharacters:l,excludeLowercase:u,excludeNumbers:h,excludePunctuation:y,excludeUppercase:f,passwordLength:b,requireEachIncludedType:C,kmsKeyId:T,tags:w}=n,E=o||r({slug:i,environment:s,resourceType:"secret"}),I=t(E),N={Type:"AWS::SecretsManager::Secret",Properties:{Name:E,Description:c,GenerateSecretString:{ExcludeCharacters:l,ExcludeLowercase:u,ExcludeNumbers:h,ExcludePunctuation:y,ExcludeUppercase:f,PasswordLength:b||32,RequireEachIncludedType:C!==!1},Tags:[{Key:"Name",Value:E},{Key:"Environment",Value:s},...w?Object.entries(w).map(([D,B])=>({Key:D,Value:B})):[]]}};if(T)N.Properties.KmsKeyId=T;return{secret:N,logicalId:I}}static createDatabaseSecret(n){let{slug:i,environment:s,secretName:o,username:c,dbname:l,engine:u,host:h,port:y,kmsKeyId:f}=n,b=o||r({slug:i,environment:s,resourceType:"db-secret"}),C=t(b),T={username:c};if(l)T.dbname=l;if(u)T.engine=u;if(h)T.host=h;if(y)T.port=y;let w={Type:"AWS::SecretsManager::Secret",Properties:{Name:b,Description:`Database credentials for ${c}`,GenerateSecretString:{SecretStringTemplate:JSON.stringify(T),GenerateStringKey:"password",PasswordLength:32,ExcludeCharacters:'"@/\\',RequireEachIncludedType:!0},Tags:[{Key:"Name",Value:b},{Key:"Environment",Value:s},{Key:"Type",Value:"database"}]}};if(f)w.Properties.KmsKeyId=f;return{secret:w,logicalId:C}}static attachToDatabase(n){let{slug:i,environment:s,secretId:o,targetId:c,targetType:l}=n,u=r({slug:i,environment:s,resourceType:"secret-attachment"}),h=t(u);return{attachment:{Type:"AWS::SecretsManager::SecretTargetAttachment",Properties:{SecretId:o,TargetId:c,TargetType:l}},logicalId:h}}static enableRotation(n){let{slug:i,environment:s,secretId:o,rotationLambdaArn:c,automaticallyAfterDays:l,rotationType:u,kmsKeyArn:h,vpcSecurityGroupIds:y,vpcSubnetIds:f}=n,b=r({slug:i,environment:s,resourceType:"secret-rotation"}),C=t(b),T={Type:"AWS::SecretsManager::RotationSchedule",Properties:{SecretId:o,RotationRules:{AutomaticallyAfterDays:l||30}}};if(c)T.Properties.RotationLambdaARN=c;else if(u)T.Properties.HostedRotationLambda={RotationType:u,KmsKeyArn:h,VpcSecurityGroupIds:y,VpcSubnetIds:f};return{rotation:T,logicalId:C}}static SecretTypes={apiKey:(n,i,s)=>wi.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-${s}-api-key`,description:`API key for ${s}`,passwordLength:32,excludePunctuation:!0,excludeLowercase:!1,excludeUppercase:!1,excludeNumbers:!1}),oauthClientSecret:(n,i,s)=>wi.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-${s}-oauth-secret`,description:`OAuth client secret for ${s}`,passwordLength:64,excludeCharacters:"\"'`\\/@",requireEachIncludedType:!0}),jwtSecret:(n,i)=>wi.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-jwt-secret`,description:"JWT signing secret",passwordLength:64,excludePunctuation:!0}),encryptionKey:(n,i)=>wi.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-encryption-key`,description:"Data encryption key",passwordLength:64,excludeCharacters:"+/=",excludePunctuation:!0})};static RotationTypes={MySQLSingleUser:"MySQLSingleUser",MySQLMultiUser:"MySQLMultiUser",PostgreSQLSingleUser:"PostgreSQLSingleUser",PostgreSQLMultiUser:"PostgreSQLMultiUser",OracleSingleUser:"OracleSingleUser",OracleMultiUser:"OracleMultiUser",MariaDBSingleUser:"MariaDBSingleUser",MariaDBMultiUser:"MariaDBMultiUser",SQLServerSingleUser:"SQLServerSingleUser",SQLServerMultiUser:"SQLServerMultiUser",RedshiftSingleUser:"RedshiftSingleUser",RedshiftMultiUser:"RedshiftMultiUser",MongoDBSingleUser:"MongoDBSingleUser",MongoDBMultiUser:"MongoDBMultiUser"}}class v{static createParameter(n){let{slug:i,environment:s,parameterName:o,value:c,type:l="String",description:u,tier:h="Standard",tags:y}=n,f=o||r({slug:i,environment:s,resourceType:"parameter"}),b=t(f);return{parameter:{Type:"AWS::SSM::Parameter",Properties:{Name:`/${i}/${s}/${f}`,Type:l,Value:c,Description:u,Tier:h,Tags:{Name:f,Environment:s,...y}}},logicalId:b}}static createString(n,i,s,o,c){return v.createParameter({slug:n,environment:i,parameterName:s,value:o,type:"String",description:c})}static createSecureString(n,i,s,o,c){return v.createParameter({slug:n,environment:i,parameterName:s,value:o,type:"SecureString",description:c})}static createStringList(n,i,s,o,c){return v.createParameter({slug:n,environment:i,parameterName:s,value:o.join(","),type:"StringList",description:c})}static Parameters={databaseUrl:(n,i,s)=>v.createSecureString(n,i,"database-url",s,"Database connection URL"),apiEndpoint:(n,i,s)=>v.createString(n,i,"api-endpoint",s,"API endpoint URL"),appVersion:(n,i,s)=>v.createString(n,i,"app-version",s,"Application version"),featureFlags:(n,i,s)=>v.createStringList(n,i,"feature-flags",s,"Enabled feature flags"),apiKey:(n,i,s,o)=>v.createSecureString(n,i,`${s}-api-key`,o,`API key for ${s}`),oauthCredentials:(n,i,s,o)=>{let c=v.createString(n,i,"oauth-client-id",s,"OAuth client ID"),l=v.createSecureString(n,i,"oauth-client-secret",o,"OAuth client secret");return{clientId:c,clientSecret:l}},smtpCredentials:(n,i,s,o,c,l)=>{let u=v.createString(n,i,"smtp-username",s,"SMTP username"),h=v.createSecureString(n,i,"smtp-password",o,"SMTP password"),y=v.createString(n,i,"smtp-host",c,"SMTP host"),f=v.createString(n,i,"smtp-port",l.toString(),"SMTP port");return{username:u,password:h,host:y,port:f}},redisUrl:(n,i,s)=>v.createSecureString(n,i,"redis-url",s,"Redis connection URL"),s3Bucket:(n,i,s)=>v.createString(n,i,"s3-bucket",s,"S3 bucket name"),cloudFrontDistribution:(n,i,s)=>v.createString(n,i,"cloudfront-distribution-id",s,"CloudFront distribution ID")}}class jt{static createDomain(n){let{slug:i,environment:s,domainName:o,engineVersion:c="OpenSearch_2.11",instanceType:l="t3.small.search",instanceCount:u=1,volumeSize:h=10,volumeType:y="gp3",dedicatedMaster:f=!1,dedicatedMasterType:b,dedicatedMasterCount:C=3,multiAz:T=!1,availabilityZoneCount:w=2,vpc:E,encryption:I,enforceHttps:N=!0,tlsSecurityPolicy:D="Policy-Min-TLS-1-2-2019-07",advancedSecurity:B,autoSnapshotHour:R=0,autoTune:W=!0,tags:_={}}=n,j=o||r({slug:i,environment:s,resourceType:"search"}),J=t(j);return{domain:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:j,EngineVersion:c,ClusterConfig:{InstanceType:l,InstanceCount:u,DedicatedMasterEnabled:f,...f&&{DedicatedMasterType:b||l,DedicatedMasterCount:C},ZoneAwarenessEnabled:T,...T&&{ZoneAwarenessConfig:{AvailabilityZoneCount:w}}},EBSOptions:{EBSEnabled:!0,VolumeType:y,VolumeSize:h},DomainEndpointOptions:{EnforceHTTPS:N,TLSSecurityPolicy:D},SnapshotOptions:{AutomatedSnapshotStartHour:R},...E&&{VPCOptions:{SubnetIds:E.subnetIds,SecurityGroupIds:E.securityGroupIds}},...I&&{EncryptionAtRestOptions:{Enabled:I.atRest??!0,...I.kmsKeyId&&{KmsKeyId:I.kmsKeyId}},NodeToNodeEncryptionOptions:{Enabled:I.nodeToNode??!0}},...B&&{AdvancedSecurityOptions:{Enabled:B.enabled,InternalUserDatabaseEnabled:B.internalUserDatabase??!0,...B.masterUserName&&B.masterUserPassword&&{MasterUserOptions:{MasterUserName:B.masterUserName,MasterUserPassword:B.masterUserPassword}},...B.masterUserArn&&{MasterUserOptions:{MasterUserARN:B.masterUserArn}}}},...W&&{AutoTuneOptions:{DesiredState:"ENABLED"}},Tags:[{Key:"Name",Value:j},{Key:"Environment",Value:s},...Object.entries(_).map(([K,Y])=>({Key:K,Value:Y}))]}},logicalId:J}}static createAccessPolicy(n,i){let{ipAddresses:s,iamPrincipalArns:o,allowAll:c,vpcEndpoint:l}=i;if(c)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:n}]};let u=[];if(o&&o.length>0)u.push({Effect:"Allow",Principal:{AWS:o},Action:"es:*",Resource:n});if(s&&s.length>0)u.push({Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:n,Condition:{IpAddress:{"aws:SourceIp":s}}});if(l)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:n}]};return{Version:"2012-10-17",Statement:u}}static DomainPresets={development:(n,i)=>jt.createDomain({slug:n,environment:i,instanceType:"t3.small.search",instanceCount:1,volumeSize:10,multiAz:!1,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!1}),production:(n,i,s)=>jt.createDomain({slug:n,environment:i,instanceType:"m6g.large.search",instanceCount:3,volumeSize:100,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"m6g.large.search",dedicatedMasterCount:3,vpc:s,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!0},autoTune:!0}),costOptimized:(n,i)=>jt.createDomain({slug:n,environment:i,instanceType:"t3.medium.search",instanceCount:2,volumeSize:20,volumeType:"gp3",multiAz:!0,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!0}),highPerformance:(n,i,s)=>jt.createDomain({slug:n,environment:i,instanceType:"r6g.2xlarge.search",instanceCount:6,volumeSize:500,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"c6g.xlarge.search",dedicatedMasterCount:3,vpc:s,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!1},autoTune:!0})};static InstanceTypes={"t3.small.search":"t3.small.search","t3.medium.search":"t3.medium.search","m6g.large.search":"m6g.large.search","m6g.xlarge.search":"m6g.xlarge.search","m6g.2xlarge.search":"m6g.2xlarge.search","r6g.large.search":"r6g.large.search","r6g.xlarge.search":"r6g.xlarge.search","r6g.2xlarge.search":"r6g.2xlarge.search","r6g.4xlarge.search":"r6g.4xlarge.search","c6g.large.search":"c6g.large.search","c6g.xlarge.search":"c6g.xlarge.search","c6g.2xlarge.search":"c6g.2xlarge.search"};static EngineVersions={"OpenSearch_2.11":"OpenSearch_2.11","OpenSearch_2.9":"OpenSearch_2.9","OpenSearch_2.7":"OpenSearch_2.7","OpenSearch_1.3":"OpenSearch_1.3","Elasticsearch_7.10":"Elasticsearch_7.10"}}class ht{static createDomainRedirectBucket(n){let{slug:i,environment:s,sourceDomain:o,targetDomain:c,protocol:l="https"}=n,u=r({slug:i,environment:s,resourceType:"s3",suffix:"redirect"}),h=t(u),y=t(`${u}-policy`),f={Type:"AWS::S3::Bucket",Properties:{BucketName:o,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:c,Protocol:l}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1},Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:s},{Key:"Purpose",Value:"Domain Redirect"}]}},b={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:k.Ref(h),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[k.Join("",[k.GetAtt(h,"Arn"),"/*"])]}]}}};return{bucket:f,bucketPolicy:b,logicalId:h,policyLogicalId:y}}static createPathRedirectFunction(n){let{slug:i,environment:s,rules:o}=n,c=r({slug:i,environment:s,resourceType:"cf-redirect"}),l=t(c),u=ht.generateRedirectFunctionCode(o);return{function:{Type:"AWS::CloudFront::Function",Properties:{Name:c,AutoPublish:!0,FunctionConfig:{Comment:`Path redirect function for ${i} (${s})`,Runtime:"cloudfront-js-2.0"},FunctionCode:u}},logicalId:l,functionCode:u}}static generateRedirectFunctionCode(n){return`function handler(event) {
2316
+ | limit 50`,region:o,title:"Recent Errors and Warnings"}}),u+=6;return go.createDashboard({slug:i,environment:s,widgets:l})}static DashboardTemplates={staticWebsite:(n)=>({slug:n.slug,environment:n.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${n.slug.toUpperCase()} Static Website Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"CloudFront Requests",region:"us-east-1",metrics:[["AWS/CloudFront","Requests","DistributionId",n.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"Error Rate",region:"us-east-1",metrics:[["AWS/CloudFront","4xxErrorRate","DistributionId",n.cloudFrontDistributionId,"Region","Global",{label:"4XX"}],["AWS/CloudFront","5xxErrorRate","DistributionId",n.cloudFrontDistributionId,"Region","Global",{label:"5XX"}]],period:300,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Bytes Downloaded",region:"us-east-1",metrics:[["AWS/CloudFront","BytesDownloaded","DistributionId",n.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:0,y:7,width:12,height:6,properties:{title:"S3 Bucket Size",region:n.region||"us-east-1",metrics:[["AWS/S3","BucketSizeBytes","BucketName",n.s3BucketName,"StorageType","StandardStorage"]],period:86400,stat:"Average"}},{type:"metric",x:12,y:7,width:12,height:6,properties:{title:"S3 Number of Objects",region:n.region||"us-east-1",metrics:[["AWS/S3","NumberOfObjects","BucketName",n.s3BucketName,"StorageType","AllStorageTypes"]],period:86400,stat:"Average"}}]}),serverlessApi:(n)=>({slug:n.slug,environment:n.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${n.slug.toUpperCase()} Serverless API Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"API Requests",region:n.region||"us-east-1",metrics:[["AWS/ApiGateway","Count","ApiName",n.apiGatewayName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"API Latency",region:n.region||"us-east-1",metrics:[["AWS/ApiGateway","Latency","ApiName",n.apiGatewayName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"API Errors",region:n.region||"us-east-1",metrics:[["AWS/ApiGateway","4XXError","ApiName",n.apiGatewayName,{label:"4XX"}],["AWS/ApiGateway","5XXError","ApiName",n.apiGatewayName,{label:"5XX"}]],period:60,stat:"Sum"}},...n.lambdaFunctionNames.map((i,s)=>({type:"metric",x:s%3*8,y:7+Math.floor(s/3)*6,width:8,height:6,properties:{title:`${i} Metrics`,region:n.region||"us-east-1",metrics:[["AWS/Lambda","Invocations","FunctionName",i],["AWS/Lambda","Duration","FunctionName",i],["AWS/Lambda","Errors","FunctionName",i]],period:300,stat:"Sum"}}))]}),containerService:(n)=>({slug:n.slug,environment:n.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${n.slug.toUpperCase()} Container Service Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"ECS CPU",region:n.region||"us-east-1",metrics:[["AWS/ECS","CPUUtilization","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"ECS Memory",region:n.region||"us-east-1",metrics:[["AWS/ECS","MemoryUtilization","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Running Tasks",region:n.region||"us-east-1",metrics:[["ECS/ContainerInsights","RunningTaskCount","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:0,y:7,width:8,height:6,properties:{title:"ALB Requests",region:n.region||"us-east-1",metrics:[["AWS/ApplicationELB","RequestCount","LoadBalancer",n.albName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:7,width:8,height:6,properties:{title:"Response Time",region:n.region||"us-east-1",metrics:[["AWS/ApplicationELB","TargetResponseTime","LoadBalancer",n.albName]],period:60,stat:"Average"}},{type:"metric",x:16,y:7,width:8,height:6,properties:{title:"Healthy Hosts",region:n.region||"us-east-1",metrics:[["AWS/ApplicationELB","HealthyHostCount","LoadBalancer",n.albName]],period:60,stat:"Average"}},...n.rdsInstanceId?[{type:"metric",x:0,y:13,width:12,height:6,properties:{title:"RDS CPU",region:n.region||"us-east-1",metrics:[["AWS/RDS","CPUUtilization","DBInstanceIdentifier",n.rdsInstanceId]],period:300,stat:"Average"}},{type:"metric",x:12,y:13,width:12,height:6,properties:{title:"RDS Connections",region:n.region||"us-east-1",metrics:[["AWS/RDS","DatabaseConnections","DBInstanceIdentifier",n.rdsInstanceId]],period:60,stat:"Sum"}}]:[]]})};static Config={createAlarmConfig:(n)=>{let{metricName:i,namespace:s,threshold:o,comparisonOperator:c="GreaterThanThreshold",evaluationPeriods:l=1,period:u=300,statistic:h="Average",treatMissingData:y="missing"}=n;return{MetricName:i,Namespace:s,Threshold:o,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:(n=80)=>({metricName:"CPUUtilization",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highMemory:(n=80)=>({metricName:"MemoryUtilization",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highErrors:(n=10)=>({metricName:"Errors",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:1,period:60,statistic:"Sum"}),highLatency:(n=5000)=>({metricName:"Duration",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowHealthyHosts:(n=1)=>({metricName:"HealthyHostCount",namespace:"AWS/ApplicationELB",threshold:n,comparisonOperator:"LessThanThreshold",evaluationPeriods:2,period:60,statistic:"Minimum"}),queueDepth:(n=1000)=>({metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowStorage:(n=10737418240)=>({metricName:"FreeStorageSpace",namespace:"AWS/RDS",threshold:n,comparisonOperator:"LessThanThreshold",evaluationPeriods:1,period:300,statistic:"Average"})}}}class H{static createUserPool(n){let{slug:i,environment:s,userPoolName:o,aliasAttributes:c,autoVerifiedAttributes:l,passwordPolicy:u,mfaConfiguration:h,emailConfiguration:y,smsConfiguration:f,lambdaTriggers:b,userPoolAddOns:C,accountRecoverySetting:T}=n,w=o||r({slug:i,environment:s,resourceType:"user-pool"}),E=t(w),I={Type:"AWS::Cognito::UserPool",Properties:{UserPoolName:w,Policies:u?{PasswordPolicy:{MinimumLength:u.minimumLength,RequireLowercase:u.requireLowercase,RequireUppercase:u.requireUppercase,RequireNumbers:u.requireNumbers,RequireSymbols:u.requireSymbols,TemporaryPasswordValidityDays:u.temporaryPasswordValidityDays}}:void 0,MfaConfiguration:h,Schema:[{Name:"email",AttributeDataType:"String",Required:!0,Mutable:!1}]}};if(c&&c.length>0)I.Properties.UsernameAttributes=c;if(l&&l.length>0)I.Properties.AutoVerifiedAttributes=l;if(y)I.Properties.EmailConfiguration={EmailSendingAccount:y.emailSendingAccount,From:y.from,ReplyToEmailAddress:y.replyToEmailAddress,SourceArn:y.sourceArn,ConfigurationSet:y.configurationSet};if(f)I.Properties.SmsConfiguration={ExternalId:f.externalId,SnsCallerArn:f.snsCallerArn};if(b)I.Properties.LambdaConfig={PreSignUp:b.preSignUp,PostConfirmation:b.postConfirmation,PreAuthentication:b.preAuthentication,PostAuthentication:b.postAuthentication,CustomMessage:b.customMessage,DefineAuthChallenge:b.defineAuthChallenge,CreateAuthChallenge:b.createAuthChallenge,VerifyAuthChallengeResponse:b.verifyAuthChallengeResponse,PreTokenGeneration:b.preTokenGeneration,UserMigration:b.userMigration};if(C)I.Properties.UserPoolAddOns={AdvancedSecurityMode:C.advancedSecurityMode};if(T)I.Properties.AccountRecoverySetting={RecoveryMechanisms:T.recoveryMechanisms};return{userPool:I,logicalId:E}}static createUserPoolClient(n,i){let{slug:s,environment:o,clientName:c,generateSecret:l=!1,refreshTokenValidity:u,accessTokenValidity:h,idTokenValidity:y,tokenValidityUnits:f,readAttributes:b,writeAttributes:C,explicitAuthFlows:T,preventUserExistenceErrors:w,enableTokenRevocation:E,callbackURLs:I,logoutURLs:N,allowedOAuthFlows:D,allowedOAuthScopes:x,allowedOAuthFlowsUserPoolClient:R,supportedIdentityProviders:_}=i,B=c||r({slug:s,environment:o,resourceType:"user-pool-client"}),W=t(B);return{client:{Type:"AWS::Cognito::UserPoolClient",Properties:{ClientName:B,UserPoolId:k.Ref(n),GenerateSecret:l,RefreshTokenValidity:u,AccessTokenValidity:h,IdTokenValidity:y,TokenValidityUnits:f,ReadAttributes:b,WriteAttributes:C,ExplicitAuthFlows:T,PreventUserExistenceErrors:w,EnableTokenRevocation:E,CallbackURLs:I,LogoutURLs:N,AllowedOAuthFlows:D,AllowedOAuthScopes:x,AllowedOAuthFlowsUserPoolClient:R,SupportedIdentityProviders:_}},logicalId:W}}static createUserPoolDomain(n,i){let{slug:s,environment:o,domain:c,customDomainConfig:l}=i,u=r({slug:s,environment:o,resourceType:"user-pool-domain"}),h=t(u);return{domain:{Type:"AWS::Cognito::UserPoolDomain",Properties:{Domain:c,UserPoolId:k.Ref(n),CustomDomainConfig:l}},logicalId:h}}static createIdentityPool(n){let{slug:i,environment:s,identityPoolName:o,allowUnauthenticatedIdentities:c=!1,cognitoIdentityProviders:l,supportedLoginProviders:u,samlProviderARNs:h,openIdConnectProviderARNs:y}=n,f=o||r({slug:i,environment:s,resourceType:"identity-pool"}),b=t(f);return{identityPool:{Type:"AWS::Cognito::IdentityPool",Properties:{IdentityPoolName:f,AllowUnauthenticatedIdentities:c,CognitoIdentityProviders:l,SupportedLoginProviders:u,SamlProviderARNs:h,OpenIdConnectProviderARNs:y}},logicalId:b}}static createIdentityPoolRoleAttachment(n,i){let{slug:s,environment:o,authenticatedRole:c,unauthenticatedRole:l,roleMappings:u}=i,h=r({slug:s,environment:o,resourceType:"identity-pool-role-attachment"}),y=t(h),f={authenticated:c};if(l)f.unauthenticated=l;return{attachment:{Type:"AWS::Cognito::IdentityPoolRoleAttachment",Properties:{IdentityPoolId:k.Ref(n),Roles:f,RoleMappings:u}},logicalId:y}}static createAuthenticatedRole(n){let{slug:i,environment:s,identityPoolLogicalId:o}=n,c=r({slug:i,environment:s,resourceType:"cognito-authenticated-role"}),l=t(c);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:c,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":k.Ref(o)},"ForAnyValue:StringLike":{"cognito-identity.amazonaws.com:amr":"authenticated"}}}]},Policies:[{PolicyName:"CognitoAuthenticatedPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["cognito-sync:*","cognito-identity:*"],Resource:"*"}]}}],Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:s}]}},logicalId:l}}static createUnauthenticatedRole(n){let{slug:i,environment:s,identityPoolLogicalId:o}=n,c=r({slug:i,environment:s,resourceType:"cognito-unauthenticated-role"}),l=t(c);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:c,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":k.Ref(o)},"ForAnyValue:StringLike":{"cognito-identity.amazonaws.com:amr":"unauthenticated"}}}]},Policies:[{PolicyName:"CognitoUnauthenticatedPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["cognito-sync:*"],Resource:"*"}]}}],Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:s}]}},logicalId:l}}static PasswordPolicies={relaxed:()=>({minimumLength:8,requireLowercase:!1,requireUppercase:!1,requireNumbers:!1,requireSymbols:!1,temporaryPasswordValidityDays:7}),standard:()=>({minimumLength:8,requireLowercase:!0,requireUppercase:!0,requireNumbers:!0,requireSymbols:!1,temporaryPasswordValidityDays:3}),strict:()=>({minimumLength:12,requireLowercase:!0,requireUppercase:!0,requireNumbers:!0,requireSymbols:!0,temporaryPasswordValidityDays:1})};static AuthFlows={standard:["ALLOW_USER_SRP_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],admin:["ALLOW_ADMIN_USER_PASSWORD_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],custom:["ALLOW_CUSTOM_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],all:["ALLOW_USER_SRP_AUTH","ALLOW_USER_PASSWORD_AUTH","ALLOW_ADMIN_USER_PASSWORD_AUTH","ALLOW_CUSTOM_AUTH","ALLOW_REFRESH_TOKEN_AUTH"]};static OAuthScopes={basic:["openid","email","profile"],all:["openid","email","profile","phone","aws.cognito.signin.user.admin"]};static UseCases={webApp:(n,i,s)=>{let{userPool:o,logicalId:c}=H.createUserPool({slug:n,environment:i,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:H.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:l,logicalId:u}=H.createUserPoolClient(c,{slug:n,environment:i,explicitAuthFlows:[...H.AuthFlows.standard],callbackURLs:[s],allowedOAuthFlows:["code"],allowedOAuthScopes:[...H.OAuthScopes.basic],allowedOAuthFlowsUserPoolClient:!0});return{userPool:o,poolId:c,client:l,clientId:u}},mobileApp:(n,i)=>{let{userPool:s,logicalId:o}=H.createUserPool({slug:n,environment:i,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:H.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:c,logicalId:l}=H.createUserPoolClient(o,{slug:n,environment:i,explicitAuthFlows:[...H.AuthFlows.standard]}),{identityPool:u,logicalId:h}=H.createIdentityPool({slug:n,environment:i,allowUnauthenticatedIdentities:!1,cognitoIdentityProviders:[{ClientId:k.Ref(l),ProviderName:k.GetAtt(o,"ProviderName")}]}),{role:y,logicalId:f}=H.createAuthenticatedRole({slug:n,environment:i,identityPoolLogicalId:h}),{attachment:b,logicalId:C}=H.createIdentityPoolRoleAttachment(h,{slug:n,environment:i,authenticatedRole:k.GetAtt(f,"Arn")});return{userPool:s,poolId:o,client:c,clientId:l,identityPool:u,identityPoolId:h,authRole:y,authRoleId:f,attachment:b,attachmentId:C}}}}class G{static createApplication(n){let{slug:i,environment:s,applicationName:o,computePlatform:c}=n,l=o||r({slug:i,environment:s,resourceType:"deploy-app"}),u=t(l);return{application:{Type:"AWS::CodeDeploy::Application",Properties:{ApplicationName:l,ComputePlatform:c,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:s}]}},logicalId:u}}static createDeploymentGroup(n,i){let{slug:s,environment:o,deploymentGroupName:c,serviceRoleArn:l,autoScalingGroups:u,ec2TagFilters:h,deploymentConfigName:y,autoRollbackConfiguration:f,alarmConfiguration:b,loadBalancerInfo:C,blueGreenDeploymentConfiguration:T}=i,w=c||r({slug:s,environment:o,resourceType:"deploy-group"}),E=t(w);return{deploymentGroup:{Type:"AWS::CodeDeploy::DeploymentGroup",Properties:{ApplicationName:k.Ref(n),DeploymentGroupName:w,ServiceRoleArn:l,AutoScalingGroups:u,Ec2TagFilters:h?.map((I)=>({Key:I.key,Value:I.value,Type:I.type})),DeploymentConfigName:y,AutoRollbackConfiguration:f?{Enabled:f.enabled,Events:f.events}:void 0,AlarmConfiguration:b?{Enabled:b.enabled,Alarms:b.alarms?.map((I)=>({Name:I.name})),IgnorePollAlarmFailure:b.ignorePollAlarmFailure}:void 0,LoadBalancerInfo:C?{TargetGroupInfoList:C.targetGroupInfoList?.map((I)=>({Name:I.name})),ElbInfoList:C.elbInfoList?.map((I)=>({Name:I.name}))}:void 0,BlueGreenDeploymentConfiguration:T?{TerminateBlueInstancesOnDeploymentSuccess:T.terminateBlueInstancesOnDeploymentSuccess?{Action:T.terminateBlueInstancesOnDeploymentSuccess.action,TerminationWaitTimeInMinutes:T.terminateBlueInstancesOnDeploymentSuccess.terminationWaitTimeInMinutes}:void 0,DeploymentReadyOption:T.deploymentReadyOption?{ActionOnTimeout:T.deploymentReadyOption.actionOnTimeout,WaitTimeInMinutes:T.deploymentReadyOption.waitTimeInMinutes}:void 0,GreenFleetProvisioningOption:T.greenFleetProvisioningOption?{Action:T.greenFleetProvisioningOption.action}:void 0}:void 0,Tags:[{Key:"Name",Value:w},{Key:"Environment",Value:o}]}},logicalId:E}}static createDeploymentConfig(n){let{slug:i,environment:s,deploymentConfigName:o,minimumHealthyHosts:c,trafficRoutingConfig:l}=n,u=o||r({slug:i,environment:s,resourceType:"deploy-config"}),h=t(u);return{deploymentConfig:{Type:"AWS::CodeDeploy::DeploymentConfig",Properties:{DeploymentConfigName:u,MinimumHealthyHosts:c?{Type:c.type,Value:c.value}:void 0,TrafficRoutingConfig:l?{Type:l.type,TimeBasedCanary:l.timeBasedCanary?{CanaryPercentage:l.timeBasedCanary.canaryPercentage,CanaryInterval:l.timeBasedCanary.canaryInterval}:void 0,TimeBasedLinear:l.timeBasedLinear?{LinearPercentage:l.timeBasedLinear.linearPercentage,LinearInterval:l.timeBasedLinear.linearInterval}:void 0}:void 0}},logicalId:h}}static DeploymentConfigs={allAtOnce:()=>({type:"FLEET_PERCENT",value:0}),halfAtATime:()=>({type:"FLEET_PERCENT",value:50}),oneAtATime:()=>({type:"HOST_COUNT",value:1}),custom:(n,i)=>({type:n,value:i})};static TrafficRouting={allAtOnce:()=>({type:"AllAtOnce"}),canary:(n,i)=>({type:"TimeBasedCanary",timeBasedCanary:{canaryPercentage:n,canaryInterval:i}}),linear:(n,i)=>({type:"TimeBasedLinear",timeBasedLinear:{linearPercentage:n,linearInterval:i}})};static RollbackConfigs={onFailure:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE"]}),onAlarmOrFailure:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE","DEPLOYMENT_STOP_ON_ALARM"]}),onAllEvents:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE","DEPLOYMENT_STOP_ON_ALARM","DEPLOYMENT_STOP_ON_REQUEST"]}),disabled:()=>({enabled:!1})};static BlueGreenConfigs={standard:()=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withDelay:(n)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:n},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withManualApproval:(n)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"STOP_DEPLOYMENT",waitTimeInMinutes:n},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),keepBlue:()=>({terminateBlueInstancesOnDeploymentSuccess:{action:"KEEP_ALIVE"},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}})};static UseCases={ec2Deployment:(n,i,s,o)=>{let{application:c,logicalId:l}=G.createApplication({slug:n,environment:i,computePlatform:"Server"}),{deploymentGroup:u,logicalId:h}=G.createDeploymentGroup(l,{slug:n,environment:i,serviceRoleArn:s,autoScalingGroups:o,deploymentConfigName:"CodeDeployDefault.OneAtATime",autoRollbackConfiguration:G.RollbackConfigs.onFailure()});return{application:c,appId:l,deploymentGroup:u,groupId:h}},lambdaCanaryDeployment:(n,i,s,o=10,c=5)=>{let{application:l,logicalId:u}=G.createApplication({slug:n,environment:i,computePlatform:"Lambda"}),{deploymentConfig:h,logicalId:y}=G.createDeploymentConfig({slug:n,environment:i,trafficRoutingConfig:G.TrafficRouting.canary(o,c)}),{deploymentGroup:f,logicalId:b}=G.createDeploymentGroup(u,{slug:n,environment:i,serviceRoleArn:s,deploymentConfigName:k.Ref(y),autoRollbackConfiguration:G.RollbackConfigs.onAlarmOrFailure()});return{application:l,appId:u,deploymentConfig:h,configId:y,deploymentGroup:f,groupId:b}},ecsBlueGreenDeployment:(n,i,s,o)=>{let{application:c,logicalId:l}=G.createApplication({slug:n,environment:i,computePlatform:"ECS"}),{deploymentGroup:u,logicalId:h}=G.createDeploymentGroup(l,{slug:n,environment:i,serviceRoleArn:s,loadBalancerInfo:{targetGroupInfoList:[{name:o}]},blueGreenDeploymentConfiguration:G.BlueGreenConfigs.standard(),autoRollbackConfiguration:G.RollbackConfigs.onFailure()});return{application:c,appId:l,deploymentGroup:u,groupId:h}}};static Strategies={rolling:(n=25)=>({type:"rolling",batchPercentage:n}),blueGreen:()=>({type:"blue-green"}),canary:(n=10,i=5)=>({type:"canary",canaryPercentage:n,canaryInterval:i}),allAtOnce:()=>({type:"all-at-once"})}}class P{static ContentTypes={".html":"text/html",".htm":"text/html",".css":"text/css",".js":"application/javascript",".mjs":"application/javascript",".json":"application/json",".xml":"application/xml",".svg":"image/svg+xml",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".avif":"image/avif",".ico":"image/x-icon",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".otf":"font/otf",".eot":"application/vnd.ms-fontobject",".pdf":"application/pdf",".txt":"text/plain",".md":"text/markdown",".map":"application/json"};static NoHashPatterns=[/^index\.html$/,/^favicon\.ico$/,/^robots\.txt$/,/^sitemap\.xml$/,/^manifest\.json$/,/^\.well-known\//,/^_redirects$/,/^_headers$/];static computeFileHash(n,i="md5"){let s=st(n);return Nr(i).update(s).digest("hex")}static computeShortHash(n){return P.computeFileHash(n).slice(0,8)}static getContentType(n){let i=ma(n).toLowerCase();return P.ContentTypes[i]||"application/octet-stream"}static shouldHashFile(n,i){return![...P.NoHashPatterns,...i||[]].some((s)=>s.test(n))}static generateHashedFilename(n,i){let s=ma(n),o=Lr(n,s),c=da(n);if(c===".")return`${o}.${i}${s}`;return Je(c,`${o}.${i}${s}`)}static collectFiles(n,i){let s=[],o=i||n;if(!Nt(n))return s;let c=kr(n,{withFileTypes:!0});for(let l of c){let u=Je(n,l.name);if(l.isDirectory())s.push(...P.collectFiles(u,o));else if(l.isFile())s.push(u)}return s}static hashDirectory(n){let{sourceDir:i,outputDir:s,excludePatterns:o=[],hashAlgorithm:c="md5",copyUnhashed:l=!0}=n,u=P.collectFiles(i),h=[],y={};for(let b of u){let C=b.replace(i,"").replace(/^[/\\]/,""),T=P.shouldHashFile(C,o),w=$r(b),E=T?P.computeFileHash(b,c).slice(0,8):"",I=T?P.generateHashedFilename(C,E):C,N={originalPath:C,hashedPath:I,hash:E,size:w.size,contentType:P.getContentType(b)};if(h.push(N),y[C]=I,s){let D=Je(s,I),x=da(D);if(!Nt(x)){let{mkdirSync:R}=ir("node:fs");R(x,{recursive:!0})}if(T||l)Dr(b,D)}}let f={version:"1.0",timestamp:new Date().toISOString(),assets:h,hashMap:y};if(s){let b=Je(s,"asset-manifest.json");ot(b,JSON.stringify(f,null,2))}return f}static getInvalidationPaths(n,i){let s=[];if(!n)return["/*"];let o=n.hashMap,c=i.hashMap;for(let[l,u]of Object.entries(c)){let h=o[l];if(!h||h!==u){if(s.push(`/${l}`),h&&h!==u)s.push(`/${h}`)}}for(let[l,u]of Object.entries(o))if(!c[l])s.push(`/${l}`),s.push(`/${u}`);if(s.length>100)return["/*"];return[...new Set(s)]}static updateHtmlReferences(n){let{htmlDir:i,manifest:s,basePath:o=""}=n,c=P.collectFiles(i).filter((l)=>l.endsWith(".html")||l.endsWith(".htm"));for(let l of c){let u=st(l,"utf-8");for(let[h,y]of Object.entries(s.hashMap)){if(h===y)continue;let f=[new RegExp(`(src|href)=["']${o}/?${P.escapeRegExp(h)}["']`,"g"),new RegExp(`url\\(["']?${o}/?${P.escapeRegExp(h)}["']?\\)`,"g")];for(let b of f)u=u.replace(b,(C)=>C.replace(h,y))}ot(l,u)}}static updateCssReferences(n){let{cssDir:i,manifest:s,basePath:o=""}=n,c=P.collectFiles(i).filter((l)=>l.endsWith(".css"));for(let l of c){let u=st(l,"utf-8");for(let[h,y]of Object.entries(s.hashMap)){if(h===y)continue;let f=new RegExp(`url\\(["']?${o}/?${P.escapeRegExp(h)}["']?\\)`,"g");u=u.replace(f,`url(${o}/${y})`)}ot(l,u)}}static escapeRegExp(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}static generateS3DeploymentManifest(n){let{sourceDir:i,keyPrefix:s="",excludePatterns:o=[],cacheControl:c={hashed:"public, max-age=31536000, immutable",unhashed:"public, max-age=3600",html:"public, max-age=0, must-revalidate"}}=n;return P.hashDirectory({sourceDir:i,excludePatterns:o}).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:Je(i,l.originalPath),s3Key:s?`${s}/${l.hashedPath}`:l.hashedPath,contentType:l.contentType,cacheControl:y,hash:l.hash}})}static compareManifests(n,i){let s={added:[],removed:[],changed:[],unchanged:[]},o=new Set(Object.keys(n.hashMap)),c=new Set(Object.keys(i.hashMap));for(let l of c)if(!o.has(l))s.added.push(l);for(let l of o)if(!c.has(l))s.removed.push(l);for(let l of c)if(o.has(l))if(n.hashMap[l]!==i.hashMap[l])s.changed.push(l);else s.unchanged.push(l);return s}static loadManifest(n){if(!Nt(n))return null;try{let i=st(n,"utf-8");return JSON.parse(i)}catch{return null}}static saveManifest(n,i){ot(i,JSON.stringify(n,null,2))}}class Di{static createSecret(n){let{slug:i,environment:s,secretName:o,description:c,secretString:l,kmsKeyId:u,tags:h}=n,y=o||r({slug:i,environment:s,resourceType:"secret"}),f=t(y),b={Type:"AWS::SecretsManager::Secret",Properties:{Name:y,Description:c,SecretString:l,Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:s},...h?Object.entries(h).map(([C,T])=>({Key:C,Value:T})):[]]}};if(u)b.Properties.KmsKeyId=u;return{secret:b,logicalId:f}}static createGeneratedSecret(n){let{slug:i,environment:s,secretName:o,description:c,excludeCharacters:l,excludeLowercase:u,excludeNumbers:h,excludePunctuation:y,excludeUppercase:f,passwordLength:b,requireEachIncludedType:C,kmsKeyId:T,tags:w}=n,E=o||r({slug:i,environment:s,resourceType:"secret"}),I=t(E),N={Type:"AWS::SecretsManager::Secret",Properties:{Name:E,Description:c,GenerateSecretString:{ExcludeCharacters:l,ExcludeLowercase:u,ExcludeNumbers:h,ExcludePunctuation:y,ExcludeUppercase:f,PasswordLength:b||32,RequireEachIncludedType:C!==!1},Tags:[{Key:"Name",Value:E},{Key:"Environment",Value:s},...w?Object.entries(w).map(([D,x])=>({Key:D,Value:x})):[]]}};if(T)N.Properties.KmsKeyId=T;return{secret:N,logicalId:I}}static createDatabaseSecret(n){let{slug:i,environment:s,secretName:o,username:c,dbname:l,engine:u,host:h,port:y,kmsKeyId:f}=n,b=o||r({slug:i,environment:s,resourceType:"db-secret"}),C=t(b),T={username:c};if(l)T.dbname=l;if(u)T.engine=u;if(h)T.host=h;if(y)T.port=y;let w={Type:"AWS::SecretsManager::Secret",Properties:{Name:b,Description:`Database credentials for ${c}`,GenerateSecretString:{SecretStringTemplate:JSON.stringify(T),GenerateStringKey:"password",PasswordLength:32,ExcludeCharacters:'"@/\\',RequireEachIncludedType:!0},Tags:[{Key:"Name",Value:b},{Key:"Environment",Value:s},{Key:"Type",Value:"database"}]}};if(f)w.Properties.KmsKeyId=f;return{secret:w,logicalId:C}}static attachToDatabase(n){let{slug:i,environment:s,secretId:o,targetId:c,targetType:l}=n,u=r({slug:i,environment:s,resourceType:"secret-attachment"}),h=t(u);return{attachment:{Type:"AWS::SecretsManager::SecretTargetAttachment",Properties:{SecretId:o,TargetId:c,TargetType:l}},logicalId:h}}static enableRotation(n){let{slug:i,environment:s,secretId:o,rotationLambdaArn:c,automaticallyAfterDays:l,rotationType:u,kmsKeyArn:h,vpcSecurityGroupIds:y,vpcSubnetIds:f}=n,b=r({slug:i,environment:s,resourceType:"secret-rotation"}),C=t(b),T={Type:"AWS::SecretsManager::RotationSchedule",Properties:{SecretId:o,RotationRules:{AutomaticallyAfterDays:l||30}}};if(c)T.Properties.RotationLambdaARN=c;else if(u)T.Properties.HostedRotationLambda={RotationType:u,KmsKeyArn:h,VpcSecurityGroupIds:y,VpcSubnetIds:f};return{rotation:T,logicalId:C}}static SecretTypes={apiKey:(n,i,s)=>Di.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-${s}-api-key`,description:`API key for ${s}`,passwordLength:32,excludePunctuation:!0,excludeLowercase:!1,excludeUppercase:!1,excludeNumbers:!1}),oauthClientSecret:(n,i,s)=>Di.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-${s}-oauth-secret`,description:`OAuth client secret for ${s}`,passwordLength:64,excludeCharacters:"\"'`\\/@",requireEachIncludedType:!0}),jwtSecret:(n,i)=>Di.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-jwt-secret`,description:"JWT signing secret",passwordLength:64,excludePunctuation:!0}),encryptionKey:(n,i)=>Di.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-encryption-key`,description:"Data encryption key",passwordLength:64,excludeCharacters:"+/=",excludePunctuation:!0})};static RotationTypes={MySQLSingleUser:"MySQLSingleUser",MySQLMultiUser:"MySQLMultiUser",PostgreSQLSingleUser:"PostgreSQLSingleUser",PostgreSQLMultiUser:"PostgreSQLMultiUser",OracleSingleUser:"OracleSingleUser",OracleMultiUser:"OracleMultiUser",MariaDBSingleUser:"MariaDBSingleUser",MariaDBMultiUser:"MariaDBMultiUser",SQLServerSingleUser:"SQLServerSingleUser",SQLServerMultiUser:"SQLServerMultiUser",RedshiftSingleUser:"RedshiftSingleUser",RedshiftMultiUser:"RedshiftMultiUser",MongoDBSingleUser:"MongoDBSingleUser",MongoDBMultiUser:"MongoDBMultiUser"}}class v{static createParameter(n){let{slug:i,environment:s,parameterName:o,value:c,type:l="String",description:u,tier:h="Standard",tags:y}=n,f=o||r({slug:i,environment:s,resourceType:"parameter"}),b=t(f);return{parameter:{Type:"AWS::SSM::Parameter",Properties:{Name:`/${i}/${s}/${f}`,Type:l,Value:c,Description:u,Tier:h,Tags:{Name:f,Environment:s,...y}}},logicalId:b}}static createString(n,i,s,o,c){return v.createParameter({slug:n,environment:i,parameterName:s,value:o,type:"String",description:c})}static createSecureString(n,i,s,o,c){return v.createParameter({slug:n,environment:i,parameterName:s,value:o,type:"SecureString",description:c})}static createStringList(n,i,s,o,c){return v.createParameter({slug:n,environment:i,parameterName:s,value:o.join(","),type:"StringList",description:c})}static Parameters={databaseUrl:(n,i,s)=>v.createSecureString(n,i,"database-url",s,"Database connection URL"),apiEndpoint:(n,i,s)=>v.createString(n,i,"api-endpoint",s,"API endpoint URL"),appVersion:(n,i,s)=>v.createString(n,i,"app-version",s,"Application version"),featureFlags:(n,i,s)=>v.createStringList(n,i,"feature-flags",s,"Enabled feature flags"),apiKey:(n,i,s,o)=>v.createSecureString(n,i,`${s}-api-key`,o,`API key for ${s}`),oauthCredentials:(n,i,s,o)=>{let c=v.createString(n,i,"oauth-client-id",s,"OAuth client ID"),l=v.createSecureString(n,i,"oauth-client-secret",o,"OAuth client secret");return{clientId:c,clientSecret:l}},smtpCredentials:(n,i,s,o,c,l)=>{let u=v.createString(n,i,"smtp-username",s,"SMTP username"),h=v.createSecureString(n,i,"smtp-password",o,"SMTP password"),y=v.createString(n,i,"smtp-host",c,"SMTP host"),f=v.createString(n,i,"smtp-port",l.toString(),"SMTP port");return{username:u,password:h,host:y,port:f}},redisUrl:(n,i,s)=>v.createSecureString(n,i,"redis-url",s,"Redis connection URL"),s3Bucket:(n,i,s)=>v.createString(n,i,"s3-bucket",s,"S3 bucket name"),cloudFrontDistribution:(n,i,s)=>v.createString(n,i,"cloudfront-distribution-id",s,"CloudFront distribution ID")}}class zt{static createDomain(n){let{slug:i,environment:s,domainName:o,engineVersion:c="OpenSearch_2.11",instanceType:l="t3.small.search",instanceCount:u=1,volumeSize:h=10,volumeType:y="gp3",dedicatedMaster:f=!1,dedicatedMasterType:b,dedicatedMasterCount:C=3,multiAz:T=!1,availabilityZoneCount:w=2,vpc:E,encryption:I,enforceHttps:N=!0,tlsSecurityPolicy:D="Policy-Min-TLS-1-2-2019-07",advancedSecurity:x,autoSnapshotHour:R=0,autoTune:_=!0,tags:B={}}=n,W=o||r({slug:i,environment:s,resourceType:"search"}),J=t(W);return{domain:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:W,EngineVersion:c,ClusterConfig:{InstanceType:l,InstanceCount:u,DedicatedMasterEnabled:f,...f&&{DedicatedMasterType:b||l,DedicatedMasterCount:C},ZoneAwarenessEnabled:T,...T&&{ZoneAwarenessConfig:{AvailabilityZoneCount:w}}},EBSOptions:{EBSEnabled:!0,VolumeType:y,VolumeSize:h},DomainEndpointOptions:{EnforceHTTPS:N,TLSSecurityPolicy:D},SnapshotOptions:{AutomatedSnapshotStartHour:R},...E&&{VPCOptions:{SubnetIds:E.subnetIds,SecurityGroupIds:E.securityGroupIds}},...I&&{EncryptionAtRestOptions:{Enabled:I.atRest??!0,...I.kmsKeyId&&{KmsKeyId:I.kmsKeyId}},NodeToNodeEncryptionOptions:{Enabled:I.nodeToNode??!0}},...x&&{AdvancedSecurityOptions:{Enabled:x.enabled,InternalUserDatabaseEnabled:x.internalUserDatabase??!0,...x.masterUserName&&x.masterUserPassword&&{MasterUserOptions:{MasterUserName:x.masterUserName,MasterUserPassword:x.masterUserPassword}},...x.masterUserArn&&{MasterUserOptions:{MasterUserARN:x.masterUserArn}}}},..._&&{AutoTuneOptions:{DesiredState:"ENABLED"}},Tags:[{Key:"Name",Value:W},{Key:"Environment",Value:s},...Object.entries(B).map(([K,Y])=>({Key:K,Value:Y}))]}},logicalId:J}}static createAccessPolicy(n,i){let{ipAddresses:s,iamPrincipalArns:o,allowAll:c,vpcEndpoint:l}=i;if(c)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:n}]};let u=[];if(o&&o.length>0)u.push({Effect:"Allow",Principal:{AWS:o},Action:"es:*",Resource:n});if(s&&s.length>0)u.push({Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:n,Condition:{IpAddress:{"aws:SourceIp":s}}});if(l)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:n}]};return{Version:"2012-10-17",Statement:u}}static DomainPresets={development:(n,i)=>zt.createDomain({slug:n,environment:i,instanceType:"t3.small.search",instanceCount:1,volumeSize:10,multiAz:!1,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!1}),production:(n,i,s)=>zt.createDomain({slug:n,environment:i,instanceType:"m6g.large.search",instanceCount:3,volumeSize:100,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"m6g.large.search",dedicatedMasterCount:3,vpc:s,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!0},autoTune:!0}),costOptimized:(n,i)=>zt.createDomain({slug:n,environment:i,instanceType:"t3.medium.search",instanceCount:2,volumeSize:20,volumeType:"gp3",multiAz:!0,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!0}),highPerformance:(n,i,s)=>zt.createDomain({slug:n,environment:i,instanceType:"r6g.2xlarge.search",instanceCount:6,volumeSize:500,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"c6g.xlarge.search",dedicatedMasterCount:3,vpc:s,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!1},autoTune:!0})};static InstanceTypes={"t3.small.search":"t3.small.search","t3.medium.search":"t3.medium.search","m6g.large.search":"m6g.large.search","m6g.xlarge.search":"m6g.xlarge.search","m6g.2xlarge.search":"m6g.2xlarge.search","r6g.large.search":"r6g.large.search","r6g.xlarge.search":"r6g.xlarge.search","r6g.2xlarge.search":"r6g.2xlarge.search","r6g.4xlarge.search":"r6g.4xlarge.search","c6g.large.search":"c6g.large.search","c6g.xlarge.search":"c6g.xlarge.search","c6g.2xlarge.search":"c6g.2xlarge.search"};static EngineVersions={"OpenSearch_2.11":"OpenSearch_2.11","OpenSearch_2.9":"OpenSearch_2.9","OpenSearch_2.7":"OpenSearch_2.7","OpenSearch_1.3":"OpenSearch_1.3","Elasticsearch_7.10":"Elasticsearch_7.10"}}class At{static createDomainRedirectBucket(n){let{slug:i,environment:s,sourceDomain:o,targetDomain:c,protocol:l="https"}=n,u=r({slug:i,environment:s,resourceType:"s3",suffix:"redirect"}),h=t(u),y=t(`${u}-policy`),f={Type:"AWS::S3::Bucket",Properties:{BucketName:o,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:c,Protocol:l}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1},Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:s},{Key:"Purpose",Value:"Domain Redirect"}]}},b={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:k.Ref(h),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[k.Join("",[k.GetAtt(h,"Arn"),"/*"])]}]}}};return{bucket:f,bucketPolicy:b,logicalId:h,policyLogicalId:y}}static createPathRedirectFunction(n){let{slug:i,environment:s,rules:o}=n,c=r({slug:i,environment:s,resourceType:"cf-redirect"}),l=t(c),u=At.generateRedirectFunctionCode(o);return{function:{Type:"AWS::CloudFront::Function",Properties:{Name:c,AutoPublish:!0,FunctionConfig:{Comment:`Path redirect function for ${i} (${s})`,Runtime:"cloudfront-js-2.0"},FunctionCode:u}},logicalId:l,functionCode:u}}static generateRedirectFunctionCode(n){return`function handler(event) {
2317
2317
  const request = event.request;
2318
2318
  const uri = request.uri;
2319
2319
  const querystring = request.querystring;
@@ -2367,7 +2367,7 @@ ${n.map((i)=>{let s=i.preserveQueryString!==!1,o=i.statusCode||301;return` '${i
2367
2367
  }
2368
2368
 
2369
2369
  return request;
2370
- }`}static CommonRedirects={wwwToApex:(n,i="https")=>({slug:n.replace(/\./g,"-"),environment:"production",sourceDomain:`www.${n}`,targetDomain:n,protocol:i,preservePath:!0}),apexToWww:(n,i="https")=>({slug:n.replace(/\./g,"-"),environment:"production",sourceDomain:n,targetDomain:`www.${n}`,protocol:i,preservePath:!0}),httpToHttps:(n="/")=>({source:n,target:n,statusCode:301}),addTrailingSlash:(n)=>n.map((i)=>({source:i.endsWith("/")?i.slice(0,-1):i,target:i.endsWith("/")?i:`${i}/`,statusCode:301})),removeTrailingSlash:(n)=>n.map((i)=>({source:i.endsWith("/")&&i!=="/"?i:`${i}/`,target:i.endsWith("/")&&i!=="/"?i.slice(0,-1):i,statusCode:301}))};static Patterns={flattenBlogUrls:(n)=>n.map(({oldPath:i,newPath:s})=>({source:i,target:s,statusCode:301,preserveQueryString:!0})),categoryRename:(n,i)=>[{source:`/${n}`,target:`/${i}`,statusCode:301},{source:`/${n}/`,target:`/${i}/`,statusCode:301}],productSlugChange:(n)=>n.map(({oldSlug:i,newSlug:s})=>({source:`/products/${i}`,target:`/products/${s}`,statusCode:301})),apiVersionRedirect:(n,i,s)=>s.map((o)=>({source:`/api/${n}/${o}`,target:`/api/${i}/${o}`,statusCode:307,preserveQueryString:!0})),gonePages:(n)=>n.map((i)=>({source:i,target:"/410",statusCode:301}))};static createRedirectSetup(n){let{slug:i,environment:s,domainRedirects:o=[],pathRedirects:c=[]}=n,l={},u=[];for(let y of o){let{bucket:f,bucketPolicy:b,logicalId:C,policyLogicalId:T}=ht.createDomainRedirectBucket({...y,slug:i,environment:s});l[C]=f,l[T]=b,u.push(C)}let h=null;if(c.length>0){let{function:y,logicalId:f}=ht.createPathRedirectFunction({slug:i,environment:s,rules:c});l[f]=y,h=f}return{resources:l,outputs:{domainRedirectBuckets:u,pathRedirectFunctionLogicalId:h}}}static fromMapping(n,i){return Object.entries(n).map(([s,o])=>({source:s,target:o,statusCode:i?.statusCode||301,preserveQueryString:i?.preserveQueryString??!0}))}static validateRules(n){let i=[],s=[],o=new Set;for(let c of n){if(o.has(c.source))i.push(`Duplicate source path: ${c.source}`);if(o.add(c.source),c.source===c.target)i.push(`Redirect loop detected: ${c.source} -> ${c.target}`);if(!c.target.startsWith("/")&&!c.target.startsWith("http"))s.push(`Target URL should start with / or http: ${c.target}`);if(!c.source||c.source.trim()==="")i.push("Source path cannot be empty");if(!c.target||c.target.trim()==="")i.push("Target path cannot be empty")}for(let c of n){let l=n.find((u)=>u.source===c.target);if(l)s.push(`Potential redirect chain: ${c.source} -> ${c.target} -> ${l.target}`)}return{valid:i.length===0,errors:i,warnings:s}}}class G{static generate(n){let i={},{slug:s,environment:o,region:c="us-east-1"}=n,l=G.createLambdaExecutionRole(s,o);if(Object.assign(i,l.resources),n.email?.enabled){let u=G.generateEmailResources(n,l.roleArn);Object.assign(i,u)}if(n.phone?.enabled){let u=G.generatePhoneResources(n,l.roleArn);Object.assign(i,u)}if(n.sms?.enabled){let u=G.generateSmsResources(n,l.roleArn);Object.assign(i,u)}return i}static createLambdaExecutionRole(n,i){let s=`${n}-${i}-communication-role`,o=t(s);return{resources:{[o]:{Type:"AWS::IAM::Role",Properties:{RoleName:s,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],Policies:[{PolicyName:"CommunicationPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:"*"},{Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail","ses:GetIdentityVerificationAttributes"],Resource:"*"},{Effect:"Allow",Action:["sns:Publish","sns:Subscribe"],Resource:"*"},{Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:BatchWriteItem","dynamodb:BatchGetItem"],Resource:"*"},{Effect:"Allow",Action:["connect:*"],Resource:"*"},{Effect:"Allow",Action:["mobiletargeting:SendMessages","mobiletargeting:GetEndpoint","mobiletargeting:UpdateEndpoint"],Resource:"*"},{Effect:"Allow",Action:["transcribe:StartTranscriptionJob","transcribe:GetTranscriptionJob"],Resource:"*"},{Effect:"Allow",Action:["bedrock:InvokeModel"],Resource:"*"},{Effect:"Allow",Action:["es:ESHttpGet","es:ESHttpPost","es:ESHttpPut","es:ESHttpDelete"],Resource:"*"}]}}]}}},roleArn:k.GetAtt(o,"Arn"),roleName:s}}static generateEmailResources(n,i){let{slug:s,environment:o,email:c}=n;if(!c)return{};let l={},u=`${s}-${o}`,h=`${u}-email-storage`,y=t(h);l[y]={Type:"AWS::S3::Bucket",Properties:{BucketName:h,LifecycleConfiguration:{Rules:[{Id:"ArchiveOldEmails",Status:"Enabled",Transitions:c.server?.storage?.archiveAfterDays?[{StorageClass:"GLACIER",TransitionInDays:c.server.storage.archiveAfterDays}]:[],ExpirationInDays:c.server?.storage?.retentionDays||365}]},NotificationConfiguration:{LambdaConfigurations:[]}}};let f=t(`${u}-ses-identity`);if(l[f]={Type:"AWS::SES::EmailIdentity",Properties:{EmailIdentity:c.domain,DkimSigningAttributes:{NextSigningKeyLength:"RSA_2048_BIT"},FeedbackAttributes:{EmailForwardingEnabled:!0}}},c.notifications?.bounces||c.notifications?.complaints){let b=t(`${u}-bounce-topic`);l[b]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${u}-email-bounces`}};let C=t(`${u}-complaint-topic`);l[C]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${u}-email-complaints`}}}if(c.server?.enabled){let b=t(`${u}-inbound-email`);l[b]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-inbound-email`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:60,MemorySize:256,Code:{ZipFile:G.InboundEmailCode},Environment:{Variables:{EMAIL_BUCKET:h,DOMAIN:c.domain}}}};let C=t(`${u}-outbound-email`);l[C]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-outbound-email`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:30,MemorySize:256,Code:{ZipFile:G.OutboundEmailCode},Environment:{Variables:{EMAIL_BUCKET:h,DOMAIN:c.domain}}}}}if(c.advanced?.analytics){let b=t(`${u}-email-analytics`);l[b]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-email-analytics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.scheduling){let b=t(`${u}-email-scheduler`);l[b]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-email-scheduler`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:300,MemorySize:256,Code:{ZipFile:G.EmailSchedulerCode},Environment:{Variables:{EMAIL_BUCKET:h}}}};let C=t(`${u}-email-scheduler-rule`);l[C]={Type:"AWS::Events::Rule",Properties:{Name:`${u}-email-scheduler`,ScheduleExpression:"rate(1 minute)",State:"ENABLED",Targets:[{Id:"EmailSchedulerTarget",Arn:k.GetAtt(b,"Arn")}]}}}if(c.advanced?.threading){let b=t(`${u}-email-threading`);l[b]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-email-threading`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:60,MemorySize:256,Code:{ZipFile:G.EmailThreadingCode},Environment:{Variables:{EMAIL_BUCKET:h}}}}}if(c.advanced?.rules){let b=t(`${u}-email-rules`);l[b]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-email-rules`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"mailbox",AttributeType:"S"},{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"mailbox",KeyType:"HASH"},{AttributeName:"id",KeyType:"RANGE"}]}}}if(c.advanced?.sharedMailboxes){let b=t(`${u}-shared-mailboxes`);l[b]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-shared-mailboxes`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"},{AttributeName:"type",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],GlobalSecondaryIndexes:[{IndexName:"type-index",KeySchema:[{AttributeName:"type",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"}}]}}}if(c.advanced?.search){let b=t(`${u}-email-search`);l[b]={Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:`${u}-email-search`.toLowerCase().replace(/[^a-z0-9-]/g,"-").substring(0,28),EngineVersion:"OpenSearch_2.11",ClusterConfig:{InstanceType:"t3.small.search",InstanceCount:1},EBSOptions:{EBSEnabled:!0,VolumeType:"gp3",VolumeSize:10},NodeToNodeEncryptionOptions:{Enabled:!0},EncryptionAtRestOptions:{Enabled:!0},DomainEndpointOptions:{EnforceHTTPS:!0}}}}return l}static generatePhoneResources(n,i){let{slug:s,environment:o,phone:c}=n;if(!c)return{};let l={},u=`${s}-${o}`,h=t(`${u}-call-log`);if(l[h]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-call-log`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"contactId",AttributeType:"S"}],KeySchema:[{AttributeName:"contactId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}},c.voicemail?.enabled){let b=t(`${u}-voicemail`);l[b]={Type:"AWS::S3::Bucket",Properties:{BucketName:`${u}-voicemail`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldVoicemails",Status:"Enabled",ExpirationInDays:90}]}}}}let y=t(`${u}-phone-notifications`);l[y]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${u}-phone-notifications`}};let f=t(`${u}-incoming-call`);if(l[f]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-incoming-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:30,MemorySize:256,Code:{ZipFile:G.IncomingCallCode},Environment:{Variables:{CALL_LOG_TABLE:`${u}-call-log`,NOTIFICATION_TOPIC_ARN:k.Ref(y)}}}},c.voicemail?.enabled){let b=t(`${u}-voicemail-handler`);l[b]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-voicemail-handler`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:c.voicemail.transcription?300:60,MemorySize:256,Code:{ZipFile:G.VoicemailCode},Environment:{Variables:{VOICEMAIL_BUCKET:`${u}-voicemail`,TRANSCRIPTION_ENABLED:String(c.voicemail.transcription||!1),NOTIFICATION_TOPIC_ARN:k.Ref(y)}}}}}if(c.advanced?.recording){let b=t(`${u}-call-recordings`);l[b]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-call-recordings`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"recordingId",AttributeType:"S"}],KeySchema:[{AttributeName:"recordingId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.callbacks){let b=t(`${u}-callbacks`);l[b]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-callbacks`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.analytics){let b=t(`${u}-call-metrics`);l[b]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-call-metrics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"period",AttributeType:"S"}],KeySchema:[{AttributeName:"period",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}return l}static generateSmsResources(n,i){let{slug:s,environment:o,sms:c}=n;if(!c)return{};let l={},u=`${s}-${o}`,h=t(`${u}-pinpoint-app`);l[h]={Type:"AWS::Pinpoint::App",Properties:{Name:`${u}-sms`}};let y=t(`${u}-sms-channel`);l[y]={Type:"AWS::Pinpoint::SMSChannel",Properties:{ApplicationId:k.Ref(h),Enabled:!0,SenderId:c.senderId}};let f=t(`${u}-sms-log`);if(l[f]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-sms-log`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}},c.optOut?.enabled){let w=t(`${u}-sms-optout`);l[w]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-sms-optout`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}]}}}let b=t(`${u}-sms-notifications`);l[b]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${u}-sms-notifications`}};let C=t(`${u}-send-sms`);l[C]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-send-sms`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:30,MemorySize:256,Code:{ZipFile:G.SendSmsCode},Environment:{Variables:{PINPOINT_APP_ID:k.Ref(h),MESSAGE_LOG_TABLE:`${u}-sms-log`,OPT_OUT_TABLE:c.optOut?.enabled?`${u}-sms-optout`:"",MESSAGE_TYPE:c.messageType||"TRANSACTIONAL"}}}};let T=t(`${u}-receive-sms`);if(l[T]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-receive-sms`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:30,MemorySize:256,Code:{ZipFile:G.ReceiveSmsCode},Environment:{Variables:{MESSAGE_LOG_TABLE:`${u}-sms-log`,OPT_OUT_TABLE:c.optOut?.enabled?`${u}-sms-optout`:"",NOTIFICATION_TOPIC_ARN:k.Ref(b)}}}},c.advanced?.campaigns){let w=t(`${u}-sms-campaigns`);l[w]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-sms-campaigns`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}if(c.advanced?.analytics){let w=t(`${u}-sms-analytics`);l[w]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-sms-analytics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"period",AttributeType:"S"}],KeySchema:[{AttributeName:"period",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.linkTracking){let w=t(`${u}-short-links`);l[w]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-short-links`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.chatbot){let w=t(`${u}-chatbot-sessions`);l[w]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-chatbot-sessions`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}};let E=t(`${u}-chatbot-rules`);l[E]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-chatbot-rules`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}if(c.advanced?.abTesting){let w=t(`${u}-ab-tests`);l[w]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-ab-tests`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}if(c.advanced?.mms){let w=t(`${u}-mms-media`);l[w]={Type:"AWS::S3::Bucket",Properties:{BucketName:`${u}-mms-media`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldMedia",Status:"Enabled",ExpirationInDays:30}]}}}}return l}static InboundEmailCode=`
2370
+ }`}static CommonRedirects={wwwToApex:(n,i="https")=>({slug:n.replace(/\./g,"-"),environment:"production",sourceDomain:`www.${n}`,targetDomain:n,protocol:i,preservePath:!0}),apexToWww:(n,i="https")=>({slug:n.replace(/\./g,"-"),environment:"production",sourceDomain:n,targetDomain:`www.${n}`,protocol:i,preservePath:!0}),httpToHttps:(n="/")=>({source:n,target:n,statusCode:301}),addTrailingSlash:(n)=>n.map((i)=>({source:i.endsWith("/")?i.slice(0,-1):i,target:i.endsWith("/")?i:`${i}/`,statusCode:301})),removeTrailingSlash:(n)=>n.map((i)=>({source:i.endsWith("/")&&i!=="/"?i:`${i}/`,target:i.endsWith("/")&&i!=="/"?i.slice(0,-1):i,statusCode:301}))};static Patterns={flattenBlogUrls:(n)=>n.map(({oldPath:i,newPath:s})=>({source:i,target:s,statusCode:301,preserveQueryString:!0})),categoryRename:(n,i)=>[{source:`/${n}`,target:`/${i}`,statusCode:301},{source:`/${n}/`,target:`/${i}/`,statusCode:301}],productSlugChange:(n)=>n.map(({oldSlug:i,newSlug:s})=>({source:`/products/${i}`,target:`/products/${s}`,statusCode:301})),apiVersionRedirect:(n,i,s)=>s.map((o)=>({source:`/api/${n}/${o}`,target:`/api/${i}/${o}`,statusCode:307,preserveQueryString:!0})),gonePages:(n)=>n.map((i)=>({source:i,target:"/410",statusCode:301}))};static createRedirectSetup(n){let{slug:i,environment:s,domainRedirects:o=[],pathRedirects:c=[]}=n,l={},u=[];for(let y of o){let{bucket:f,bucketPolicy:b,logicalId:C,policyLogicalId:T}=At.createDomainRedirectBucket({...y,slug:i,environment:s});l[C]=f,l[T]=b,u.push(C)}let h=null;if(c.length>0){let{function:y,logicalId:f}=At.createPathRedirectFunction({slug:i,environment:s,rules:c});l[f]=y,h=f}return{resources:l,outputs:{domainRedirectBuckets:u,pathRedirectFunctionLogicalId:h}}}static fromMapping(n,i){return Object.entries(n).map(([s,o])=>({source:s,target:o,statusCode:i?.statusCode||301,preserveQueryString:i?.preserveQueryString??!0}))}static validateRules(n){let i=[],s=[],o=new Set;for(let c of n){if(o.has(c.source))i.push(`Duplicate source path: ${c.source}`);if(o.add(c.source),c.source===c.target)i.push(`Redirect loop detected: ${c.source} -> ${c.target}`);if(!c.target.startsWith("/")&&!c.target.startsWith("http"))s.push(`Target URL should start with / or http: ${c.target}`);if(!c.source||c.source.trim()==="")i.push("Source path cannot be empty");if(!c.target||c.target.trim()==="")i.push("Target path cannot be empty")}for(let c of n){let l=n.find((u)=>u.source===c.target);if(l)s.push(`Potential redirect chain: ${c.source} -> ${c.target} -> ${l.target}`)}return{valid:i.length===0,errors:i,warnings:s}}}class q{static generate(n){let i={},{slug:s,environment:o,region:c="us-east-1"}=n,l=q.createLambdaExecutionRole(s,o);if(Object.assign(i,l.resources),n.email?.enabled){let u=q.generateEmailResources(n,l.roleArn);Object.assign(i,u)}if(n.phone?.enabled){let u=q.generatePhoneResources(n,l.roleArn);Object.assign(i,u)}if(n.sms?.enabled){let u=q.generateSmsResources(n,l.roleArn);Object.assign(i,u)}return i}static createLambdaExecutionRole(n,i){let s=`${n}-${i}-communication-role`,o=t(s);return{resources:{[o]:{Type:"AWS::IAM::Role",Properties:{RoleName:s,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],Policies:[{PolicyName:"CommunicationPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:"*"},{Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail","ses:GetIdentityVerificationAttributes"],Resource:"*"},{Effect:"Allow",Action:["sns:Publish","sns:Subscribe"],Resource:"*"},{Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:BatchWriteItem","dynamodb:BatchGetItem"],Resource:"*"},{Effect:"Allow",Action:["connect:*"],Resource:"*"},{Effect:"Allow",Action:["mobiletargeting:SendMessages","mobiletargeting:GetEndpoint","mobiletargeting:UpdateEndpoint"],Resource:"*"},{Effect:"Allow",Action:["transcribe:StartTranscriptionJob","transcribe:GetTranscriptionJob"],Resource:"*"},{Effect:"Allow",Action:["bedrock:InvokeModel"],Resource:"*"},{Effect:"Allow",Action:["es:ESHttpGet","es:ESHttpPost","es:ESHttpPut","es:ESHttpDelete"],Resource:"*"}]}}]}}},roleArn:k.GetAtt(o,"Arn"),roleName:s}}static generateEmailResources(n,i){let{slug:s,environment:o,email:c}=n;if(!c)return{};let l={},u=`${s}-${o}`,h=`${u}-email-storage`,y=t(h);l[y]={Type:"AWS::S3::Bucket",Properties:{BucketName:h,LifecycleConfiguration:{Rules:[{Id:"ArchiveOldEmails",Status:"Enabled",Transitions:c.server?.storage?.archiveAfterDays?[{StorageClass:"GLACIER",TransitionInDays:c.server.storage.archiveAfterDays}]:[],ExpirationInDays:c.server?.storage?.retentionDays||365}]},NotificationConfiguration:{LambdaConfigurations:[]}}};let f=t(`${u}-ses-identity`);if(l[f]={Type:"AWS::SES::EmailIdentity",Properties:{EmailIdentity:c.domain,DkimSigningAttributes:{NextSigningKeyLength:"RSA_2048_BIT"},FeedbackAttributes:{EmailForwardingEnabled:!0}}},c.notifications?.bounces||c.notifications?.complaints){let b=t(`${u}-bounce-topic`);l[b]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${u}-email-bounces`}};let C=t(`${u}-complaint-topic`);l[C]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${u}-email-complaints`}}}if(c.server?.enabled){let b=t(`${u}-inbound-email`);l[b]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-inbound-email`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:60,MemorySize:256,Code:{ZipFile:q.InboundEmailCode},Environment:{Variables:{EMAIL_BUCKET:h,DOMAIN:c.domain}}}};let C=t(`${u}-outbound-email`);l[C]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-outbound-email`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:30,MemorySize:256,Code:{ZipFile:q.OutboundEmailCode},Environment:{Variables:{EMAIL_BUCKET:h,DOMAIN:c.domain}}}}}if(c.advanced?.analytics){let b=t(`${u}-email-analytics`);l[b]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-email-analytics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.scheduling){let b=t(`${u}-email-scheduler`);l[b]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-email-scheduler`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:300,MemorySize:256,Code:{ZipFile:q.EmailSchedulerCode},Environment:{Variables:{EMAIL_BUCKET:h}}}};let C=t(`${u}-email-scheduler-rule`);l[C]={Type:"AWS::Events::Rule",Properties:{Name:`${u}-email-scheduler`,ScheduleExpression:"rate(1 minute)",State:"ENABLED",Targets:[{Id:"EmailSchedulerTarget",Arn:k.GetAtt(b,"Arn")}]}}}if(c.advanced?.threading){let b=t(`${u}-email-threading`);l[b]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-email-threading`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:60,MemorySize:256,Code:{ZipFile:q.EmailThreadingCode},Environment:{Variables:{EMAIL_BUCKET:h}}}}}if(c.advanced?.rules){let b=t(`${u}-email-rules`);l[b]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-email-rules`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"mailbox",AttributeType:"S"},{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"mailbox",KeyType:"HASH"},{AttributeName:"id",KeyType:"RANGE"}]}}}if(c.advanced?.sharedMailboxes){let b=t(`${u}-shared-mailboxes`);l[b]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-shared-mailboxes`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"},{AttributeName:"type",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],GlobalSecondaryIndexes:[{IndexName:"type-index",KeySchema:[{AttributeName:"type",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"}}]}}}if(c.advanced?.search){let b=t(`${u}-email-search`);l[b]={Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:`${u}-email-search`.toLowerCase().replace(/[^a-z0-9-]/g,"-").substring(0,28),EngineVersion:"OpenSearch_2.11",ClusterConfig:{InstanceType:"t3.small.search",InstanceCount:1},EBSOptions:{EBSEnabled:!0,VolumeType:"gp3",VolumeSize:10},NodeToNodeEncryptionOptions:{Enabled:!0},EncryptionAtRestOptions:{Enabled:!0},DomainEndpointOptions:{EnforceHTTPS:!0}}}}return l}static generatePhoneResources(n,i){let{slug:s,environment:o,phone:c}=n;if(!c)return{};let l={},u=`${s}-${o}`,h=t(`${u}-call-log`);if(l[h]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-call-log`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"contactId",AttributeType:"S"}],KeySchema:[{AttributeName:"contactId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}},c.voicemail?.enabled){let b=t(`${u}-voicemail`);l[b]={Type:"AWS::S3::Bucket",Properties:{BucketName:`${u}-voicemail`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldVoicemails",Status:"Enabled",ExpirationInDays:90}]}}}}let y=t(`${u}-phone-notifications`);l[y]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${u}-phone-notifications`}};let f=t(`${u}-incoming-call`);if(l[f]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-incoming-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:30,MemorySize:256,Code:{ZipFile:q.IncomingCallCode},Environment:{Variables:{CALL_LOG_TABLE:`${u}-call-log`,NOTIFICATION_TOPIC_ARN:k.Ref(y)}}}},c.voicemail?.enabled){let b=t(`${u}-voicemail-handler`);l[b]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-voicemail-handler`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:c.voicemail.transcription?300:60,MemorySize:256,Code:{ZipFile:q.VoicemailCode},Environment:{Variables:{VOICEMAIL_BUCKET:`${u}-voicemail`,TRANSCRIPTION_ENABLED:String(c.voicemail.transcription||!1),NOTIFICATION_TOPIC_ARN:k.Ref(y)}}}}}if(c.advanced?.recording){let b=t(`${u}-call-recordings`);l[b]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-call-recordings`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"recordingId",AttributeType:"S"}],KeySchema:[{AttributeName:"recordingId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.callbacks){let b=t(`${u}-callbacks`);l[b]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-callbacks`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.analytics){let b=t(`${u}-call-metrics`);l[b]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-call-metrics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"period",AttributeType:"S"}],KeySchema:[{AttributeName:"period",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}return l}static generateSmsResources(n,i){let{slug:s,environment:o,sms:c}=n;if(!c)return{};let l={},u=`${s}-${o}`,h=t(`${u}-pinpoint-app`);l[h]={Type:"AWS::Pinpoint::App",Properties:{Name:`${u}-sms`}};let y=t(`${u}-sms-channel`);l[y]={Type:"AWS::Pinpoint::SMSChannel",Properties:{ApplicationId:k.Ref(h),Enabled:!0,SenderId:c.senderId}};let f=t(`${u}-sms-log`);if(l[f]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-sms-log`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}},c.optOut?.enabled){let w=t(`${u}-sms-optout`);l[w]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-sms-optout`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}]}}}let b=t(`${u}-sms-notifications`);l[b]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${u}-sms-notifications`}};let C=t(`${u}-send-sms`);l[C]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-send-sms`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:30,MemorySize:256,Code:{ZipFile:q.SendSmsCode},Environment:{Variables:{PINPOINT_APP_ID:k.Ref(h),MESSAGE_LOG_TABLE:`${u}-sms-log`,OPT_OUT_TABLE:c.optOut?.enabled?`${u}-sms-optout`:"",MESSAGE_TYPE:c.messageType||"TRANSACTIONAL"}}}};let T=t(`${u}-receive-sms`);if(l[T]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${u}-receive-sms`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:30,MemorySize:256,Code:{ZipFile:q.ReceiveSmsCode},Environment:{Variables:{MESSAGE_LOG_TABLE:`${u}-sms-log`,OPT_OUT_TABLE:c.optOut?.enabled?`${u}-sms-optout`:"",NOTIFICATION_TOPIC_ARN:k.Ref(b)}}}},c.advanced?.campaigns){let w=t(`${u}-sms-campaigns`);l[w]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-sms-campaigns`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}if(c.advanced?.analytics){let w=t(`${u}-sms-analytics`);l[w]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-sms-analytics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"period",AttributeType:"S"}],KeySchema:[{AttributeName:"period",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.linkTracking){let w=t(`${u}-short-links`);l[w]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-short-links`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.chatbot){let w=t(`${u}-chatbot-sessions`);l[w]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-chatbot-sessions`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}};let E=t(`${u}-chatbot-rules`);l[E]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-chatbot-rules`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}if(c.advanced?.abTesting){let w=t(`${u}-ab-tests`);l[w]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${u}-ab-tests`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}if(c.advanced?.mms){let w=t(`${u}-mms-media`);l[w]={Type:"AWS::S3::Bucket",Properties:{BucketName:`${u}-mms-media`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldMedia",Status:"Enabled",ExpirationInDays:30}]}}}}return l}static InboundEmailCode=`
2371
2371
  const { S3Client, GetObjectCommand, PutObjectCommand } = require('@aws-sdk/client-s3');
2372
2372
  const s3 = new S3Client({});
2373
2373
  exports.handler = async (event) => {
@@ -2465,7 +2465,7 @@ exports.handler = async (event) => {
2465
2465
  console.log('Receive SMS:', JSON.stringify(event, null, 2));
2466
2466
  // Process inbound SMS, handle opt-out keywords
2467
2467
  return { statusCode: 200 };
2468
- };`}var e={ref:(n)=>({Ref:n}),getAtt:(n,i)=>({"Fn::GetAtt":[n,i]}),join:(n,i)=>({"Fn::Join":[n,i]}),sub:(n,i)=>i?{"Fn::Sub":[n,i]}:{"Fn::Sub":n},select:(n,i)=>({"Fn::Select":[n,i]}),split:(n,i)=>({"Fn::Split":[n,i]}),getAZs:(n="")=>({"Fn::GetAZs":n}),importValue:(n)=>({"Fn::ImportValue":n}),findInMap:(n,i,s)=>({"Fn::FindInMap":[n,i,s]}),base64:(n)=>({"Fn::Base64":n}),cidr:(n,i,s)=>({"Fn::Cidr":[n,i,s]}),equals:(n,i)=>({"Fn::Equals":[n,i]}),if:(n,i,s)=>({"Fn::If":[n,i,s]}),not:(n)=>({"Fn::Not":[n]}),and:(...n)=>({"Fn::And":n}),or:(...n)=>({"Fn::Or":n})},po={s3Bucket:(n)=>e.sub(`arn:aws:s3:::${n}`),s3Object:(n,i="*")=>e.sub(`arn:aws:s3:::${n}/${i}`),lambda:(n,i,s)=>e.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${n}`,i&&s?{"AWS::Region":i,"AWS::AccountId":s}:void 0),dynamodb:(n)=>e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${n}`),sqs:(n)=>e.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${n}`),sns:(n)=>e.sub(`arn:aws:sns:\${AWS::Region}:\${AWS::AccountId}:${n}`),kinesis:(n)=>e.sub(`arn:aws:kinesis:\${AWS::Region}:\${AWS::AccountId}:stream/${n}`),iam:(n,i)=>e.sub(`arn:aws:iam::\${AWS::AccountId}:${n}/${i}`),secretsManager:(n)=>e.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${n}`),cloudwatch:(n)=>e.sub(`arn:aws:logs:\${AWS::Region}:\${AWS::AccountId}:log-group:${n}`)},xI={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 Mr(n,i){if(i.type==="http")Or(n,i);else if(i.type==="rest")xr(n,i);else if(i.type==="websocket")Br(n,i)}function Or(n,i){let s={Name:e.sub("${AWS::StackName}-http-api"),ProtocolType:"HTTP"};if(i.cors)s.CorsConfiguration={AllowOrigins:i.cors.allowOrigins,AllowMethods:i.cors.allowMethods,AllowHeaders:i.cors.allowHeaders||["*"],MaxAge:i.cors.maxAge||300};if(n.addResource("HttpApi","AWS::ApiGatewayV2::Api",s),n.addResource("HttpApiStage","AWS::ApiGatewayV2::Stage",{ApiId:e.ref("HttpApi"),StageName:"$default",AutoDeploy:!0,DefaultRouteSettings:i.throttling?{ThrottlingBurstLimit:i.throttling.burstLimit,ThrottlingRateLimit:i.throttling.rateLimit}:void 0,AccessLogSettings:{DestinationArn:e.getAtt("ApiLogGroup","Arn"),Format:"$context.requestId $context.error.message $context.error.messageString"}},{dependsOn:["HttpApi","ApiLogGroup"]}),n.addResource("ApiLogGroup","AWS::Logs::LogGroup",{LogGroupName:e.sub("/aws/apigateway/${AWS::StackName}-http-api"),RetentionInDays:14}),i.authorizer)_r(n,"HttpApi",i.authorizer);if(i.customDomain)Ut(n,"HttpApi",i.customDomain,"HTTP");n.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 xr(n,i){n.addResource("RestApi","AWS::ApiGateway::RestApi",{Name:e.sub("${AWS::StackName}-rest-api"),Description:e.sub("REST API for ${AWS::StackName}"),EndpointConfiguration:{Types:["REGIONAL"]}}),n.addResource("ApiGatewayAccount","AWS::ApiGateway::Account",{CloudWatchRoleArn:e.getAtt("ApiGatewayCloudWatchRole","Arn")},{dependsOn:"ApiGatewayCloudWatchRole"}),n.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"]}),n.addResource("RestApiDeployment","AWS::ApiGateway::Deployment",{RestApiId:e.ref("RestApi"),Description:"Initial deployment"},{dependsOn:"RestApi"});let s={RestApiId:e.ref("RestApi"),DeploymentId:e.ref("RestApiDeployment"),StageName:"prod",Description:"Production stage",MethodSettings:[{ResourcePath:"/*",HttpMethod:"*",LoggingLevel:"INFO",DataTraceEnabled:!0,MetricsEnabled:!0}]};if(i.throttling)s.MethodSettings[0].ThrottlingBurstLimit=i.throttling.burstLimit,s.MethodSettings[0].ThrottlingRateLimit=i.throttling.rateLimit;if(n.addResource("RestApiStage","AWS::ApiGateway::Stage",s,{dependsOn:["RestApi","RestApiDeployment"]}),i.customDomain)Ut(n,"RestApi",i.customDomain,"REST");n.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 Br(n,i){if(n.addResource("WebSocketApi","AWS::ApiGatewayV2::Api",{Name:e.sub("${AWS::StackName}-websocket-api"),ProtocolType:"WEBSOCKET",RouteSelectionExpression:"$request.body.action"}),i.routes){if(i.routes.connect)ct(n,"$connect",i.routes.connect.functionName);if(i.routes.disconnect)ct(n,"$disconnect",i.routes.disconnect.functionName);if(i.routes.default)ct(n,"$default",i.routes.default.functionName);if(i.routes.custom)i.routes.custom.forEach((s)=>{ct(n,s.routeKey,s.functionName)})}if(n.addResource("WebSocketApiStage","AWS::ApiGatewayV2::Stage",{ApiId:e.ref("WebSocketApi"),StageName:"prod",AutoDeploy:!0,DefaultRouteSettings:i.throttling?{ThrottlingBurstLimit:i.throttling.burstLimit,ThrottlingRateLimit:i.throttling.rateLimit}:void 0},{dependsOn:"WebSocketApi"}),i.customDomain)Ut(n,"WebSocketApi",i.customDomain,"WEBSOCKET");n.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 ct(n,i,s){let o=n.toLogicalId(`websocket-route-${i}`),c=n.toLogicalId(`websocket-integration-${i}`),l=n.toLogicalId(`${s}-function`);n.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]}),n.addResource(o,"AWS::ApiGatewayV2::Route",{ApiId:e.ref("WebSocketApi"),RouteKey:i,Target:e.join("/",["integrations",e.ref(c)])},{dependsOn:["WebSocketApi",c]}),n.addResource(`${o}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 Ut(n,i,s,o){let c={DomainName:s.domain};if(o==="REST")c.CertificateArn=s.certificateArn,c.EndpointConfiguration={Types:["REGIONAL"]},n.addResource("ApiCustomDomain","AWS::ApiGateway::DomainName",c),n.addResource("ApiBasePathMapping","AWS::ApiGateway::BasePathMapping",{DomainName:e.ref("ApiCustomDomain"),RestApiId:e.ref(i),Stage:e.ref("RestApiStage")},{dependsOn:["ApiCustomDomain",i,"RestApiStage"]});else c.DomainNameConfigurations=[{CertificateArn:s.certificateArn,EndpointType:"REGIONAL"}],n.addResource("ApiCustomDomain","AWS::ApiGatewayV2::DomainName",c),n.addResource("ApiMapping","AWS::ApiGatewayV2::ApiMapping",{ApiId:e.ref(i),DomainName:e.ref("ApiCustomDomain"),Stage:o==="HTTP"?e.ref("HttpApiStage"):e.ref("WebSocketApiStage")},{dependsOn:["ApiCustomDomain",i]});if(s.dnsProvider!=="external")n.addResource("ApiDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:e.sub(`${Wr(s.domain)}.`),Name:s.domain,Type:"A",AliasTarget:{HostedZoneId:e.getAtt("ApiCustomDomain","RegionalHostedZoneId"),DNSName:e.getAtt("ApiCustomDomain","RegionalDomainName"),EvaluateTargetHealth:!1}},{dependsOn:"ApiCustomDomain"});n.addOutputs({ApiCustomDomainName:{Description:"Configured API custom domain",Value:s.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 _r(n,i,s){if(!s)return;if(s.type==="jwt")n.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:e.ref(i),AuthorizerType:"JWT",IdentitySource:[s.identitySource||"$request.header.Authorization"],JwtConfiguration:{Issuer:s.issuer,Audience:s.audience},Name:"JWTAuthorizer"},{dependsOn:i});else if(s.type==="lambda")n.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:e.ref(i),AuthorizerType:"REQUEST",AuthorizerUri:s.authorizerUri,IdentitySource:[s.identitySource||"$request.header.Authorization"],Name:"LambdaAuthorizer"},{dependsOn:i})}function Wr(n){let i=n.split(".");if(i.length>=2)return i.slice(-2).join(".");return n}function Fr(n,i){if(i.redis)Ur(n,i.redis);if(i.memcached)Kr(n,i.memcached);if(i.elasticache)zr(n,i.elasticache)}function Ur(n,i){if(!i)return;if(n.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"]}),n.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Redis",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:i.port||6379,ToPort:i.port||6379,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]}),i.parameterGroup&&Object.keys(i.parameterGroup).length>0)n.addResource("CacheParameterGroup","AWS::ElastiCache::ParameterGroup",{Description:"Parameter group for Redis",CacheParameterGroupFamily:`redis${i.engineVersion.split(".")[0]}`,Properties:i.parameterGroup});if(i.numCacheNodes>1||i.automaticFailoverEnabled)n.addResource("RedisReplicationGroup","AWS::ElastiCache::ReplicationGroup",{ReplicationGroupDescription:"Redis replication group",ReplicationGroupId:e.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:i.engineVersion,CacheNodeType:i.nodeType,NumCacheClusters:i.numCacheNodes,AutomaticFailoverEnabled:i.automaticFailoverEnabled||!1,MultiAZEnabled:i.automaticFailoverEnabled||!1,Port:i.port||6379,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),SecurityGroupIds:[e.ref("CacheSecurityGroup")],CacheParameterGroupName:i.parameterGroup?e.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:i.snapshotRetentionLimit||5,SnapshotWindow:i.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:i.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),n.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 n.addResource("RedisCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:i.engineVersion,CacheNodeType:i.nodeType,NumCacheNodes:1,Port:i.port||6379,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],CacheParameterGroupName:i.parameterGroup?e.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:i.snapshotRetentionLimit||5,SnapshotWindow:i.snapshotWindow||"03:00-05:00",PreferredMaintenanceWindow:"sun:05:00-sun:06:00",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-redis")}]},{dependsOn:i.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),n.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 Kr(n,i){if(!i)return;if(!n.hasResource("CacheSubnetGroup"))n.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!n.hasResource("CacheSecurityGroup"))n.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Memcached",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:i.port||11211,ToPort:i.port||11211,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});n.addResource("MemcachedCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub("${AWS::StackName}-memcached"),Engine:"memcached",EngineVersion:i.engineVersion,CacheNodeType:i.nodeType,NumCacheNodes:i.numCacheNodes,Port:i.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"]}),n.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 zr(n,i){if(!i)return;let s=i.engine==="redis";if(!n.hasResource("CacheSubnetGroup"))n.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!n.hasResource("CacheSecurityGroup"))n.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:s?6379:11211,ToPort:s?6379:11211,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});n.addResource("CacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub(`\${AWS::StackName}-${i.engine}`),Engine:i.engine,EngineVersion:i.engineVersion,CacheNodeType:i.nodeType,NumCacheNodes:i.numCacheNodes,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i.engine}`)}]},{dependsOn:["CacheSubnetGroup","CacheSecurityGroup"]})}function Jr(n,i){if(!i.enabled)return;n.addResource("CloudFrontOriginAccessIdentity","AWS::CloudFront::CloudFrontOriginAccessIdentity",{CloudFrontOriginAccessIdentityConfig:{Comment:e.sub("${AWS::StackName} CloudFront OAI")}});let s=[],o=[];if(!i.origins||i.origins.length===0)s.push({Id:"S3Origin",DomainName:e.getAtt("StaticBucket","DomainName"),S3OriginConfig:{OriginAccessIdentity:e.sub("origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}")}});else i.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(s.push(y),h>0||u.pathPattern)o.push({PathPattern:u.pathPattern||`/${u.id}/*`,TargetOriginId:u.id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:i.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:i.cachePolicy?.minTTL||0,DefaultTTL:i.cachePolicy?.defaultTTL||86400,MaxTTL:i.cachePolicy?.maxTTL||31536000})});let c={TargetOriginId:s[0].Id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:i.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:i.cachePolicy?.minTTL||0,DefaultTTL:i.cachePolicy?.defaultTTL||86400,MaxTTL:i.cachePolicy?.maxTTL||31536000};if(i.edgeFunctions&&i.edgeFunctions.length>0)c.LambdaFunctionAssociations=i.edgeFunctions.map((u)=>({EventType:u.eventType,LambdaFunctionARN:u.functionArn}));let l={Enabled:!0,HttpVersion:i.http3?"http3":"http2",IPV6Enabled:!0,Origins:s,DefaultCacheBehavior:c,PriceClass:i.priceClass||"PriceClass_100",ViewerCertificate:{}};if(o.length>0)l.CacheBehaviors=o;if(i.customDomain)l.Aliases=[i.customDomain.domain],l.ViewerCertificate={AcmCertificateArn:i.customDomain.certificateArn,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};else l.ViewerCertificate={CloudFrontDefaultCertificate:!0};if(i.errorPages)l.CustomErrorResponses=Object.entries(i.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"),n.addResource("CloudFrontDistribution","AWS::CloudFront::Distribution",{DistributionConfig:l},{dependsOn:"CloudFrontOriginAccessIdentity"}),!i.origins||i.origins.length===0)n.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(i.customDomain)n.addResource("CloudFrontDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:e.sub(`${Yr(i.customDomain.domain)}.`),Name:i.customDomain.domain,Type:"A",AliasTarget:{HostedZoneId:"Z2FDTNDATAQYW2",DNSName:e.getAtt("CloudFrontDistribution","DomainName"),EvaluateTargetHealth:!1}},{dependsOn:"CloudFrontDistribution"});if(n.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")}}}),i.customDomain)n.addOutputs({CloudFrontURL:{Description:"CloudFront custom domain URL",Value:e.sub(`https://${i.customDomain.domain}`)}})}function Yr(n){let i=n.split(".");if(i.length>=2)return i.slice(-2).join(".");return n}function Zr(n,i){if(i.server)Xr(n,i.server);if(i.fargate)pa(n,"app",i.fargate);if(i.services)i.services.forEach((s)=>{if(s.type==="fargate")pa(n,s.name,{taskDefinition:s.taskDefinition,service:s.service})})}function Xr(n,i){if(!i)return;n.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"}),n.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")}]}),n.addResource("EC2InstanceProfile","AWS::IAM::InstanceProfile",{Roles:[e.ref("EC2InstanceRole")]},{dependsOn:"EC2InstanceRole"});let s=i.userData||`#!/bin/bash
2468
+ };`}var e={ref:(n)=>({Ref:n}),getAtt:(n,i)=>({"Fn::GetAtt":[n,i]}),join:(n,i)=>({"Fn::Join":[n,i]}),sub:(n,i)=>i?{"Fn::Sub":[n,i]}:{"Fn::Sub":n},select:(n,i)=>({"Fn::Select":[n,i]}),split:(n,i)=>({"Fn::Split":[n,i]}),getAZs:(n="")=>({"Fn::GetAZs":n}),importValue:(n)=>({"Fn::ImportValue":n}),findInMap:(n,i,s)=>({"Fn::FindInMap":[n,i,s]}),base64:(n)=>({"Fn::Base64":n}),cidr:(n,i,s)=>({"Fn::Cidr":[n,i,s]}),equals:(n,i)=>({"Fn::Equals":[n,i]}),if:(n,i,s)=>({"Fn::If":[n,i,s]}),not:(n)=>({"Fn::Not":[n]}),and:(...n)=>({"Fn::And":n}),or:(...n)=>({"Fn::Or":n})},mo={s3Bucket:(n)=>e.sub(`arn:aws:s3:::${n}`),s3Object:(n,i="*")=>e.sub(`arn:aws:s3:::${n}/${i}`),lambda:(n,i,s)=>e.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${n}`,i&&s?{"AWS::Region":i,"AWS::AccountId":s}:void 0),dynamodb:(n)=>e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${n}`),sqs:(n)=>e.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${n}`),sns:(n)=>e.sub(`arn:aws:sns:\${AWS::Region}:\${AWS::AccountId}:${n}`),kinesis:(n)=>e.sub(`arn:aws:kinesis:\${AWS::Region}:\${AWS::AccountId}:stream/${n}`),iam:(n,i)=>e.sub(`arn:aws:iam::\${AWS::AccountId}:${n}/${i}`),secretsManager:(n)=>e.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${n}`),cloudwatch:(n)=>e.sub(`arn:aws:logs:\${AWS::Region}:\${AWS::AccountId}:log-group:${n}`)},LI={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 Mr(n,i){if(i.type==="http")Or(n,i);else if(i.type==="rest")xr(n,i);else if(i.type==="websocket")Br(n,i)}function Or(n,i){let s={Name:e.sub("${AWS::StackName}-http-api"),ProtocolType:"HTTP"};if(i.cors)s.CorsConfiguration={AllowOrigins:i.cors.allowOrigins,AllowMethods:i.cors.allowMethods,AllowHeaders:i.cors.allowHeaders||["*"],MaxAge:i.cors.maxAge||300};if(n.addResource("HttpApi","AWS::ApiGatewayV2::Api",s),n.addResource("HttpApiStage","AWS::ApiGatewayV2::Stage",{ApiId:e.ref("HttpApi"),StageName:"$default",AutoDeploy:!0,DefaultRouteSettings:i.throttling?{ThrottlingBurstLimit:i.throttling.burstLimit,ThrottlingRateLimit:i.throttling.rateLimit}:void 0,AccessLogSettings:{DestinationArn:e.getAtt("ApiLogGroup","Arn"),Format:"$context.requestId $context.error.message $context.error.messageString"}},{dependsOn:["HttpApi","ApiLogGroup"]}),n.addResource("ApiLogGroup","AWS::Logs::LogGroup",{LogGroupName:e.sub("/aws/apigateway/${AWS::StackName}-http-api"),RetentionInDays:14}),i.authorizer)_r(n,"HttpApi",i.authorizer);if(i.customDomain)Ut(n,"HttpApi",i.customDomain,"HTTP");n.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 xr(n,i){n.addResource("RestApi","AWS::ApiGateway::RestApi",{Name:e.sub("${AWS::StackName}-rest-api"),Description:e.sub("REST API for ${AWS::StackName}"),EndpointConfiguration:{Types:["REGIONAL"]}}),n.addResource("ApiGatewayAccount","AWS::ApiGateway::Account",{CloudWatchRoleArn:e.getAtt("ApiGatewayCloudWatchRole","Arn")},{dependsOn:"ApiGatewayCloudWatchRole"}),n.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"]}),n.addResource("RestApiDeployment","AWS::ApiGateway::Deployment",{RestApiId:e.ref("RestApi"),Description:"Initial deployment"},{dependsOn:"RestApi"});let s={RestApiId:e.ref("RestApi"),DeploymentId:e.ref("RestApiDeployment"),StageName:"prod",Description:"Production stage",MethodSettings:[{ResourcePath:"/*",HttpMethod:"*",LoggingLevel:"INFO",DataTraceEnabled:!0,MetricsEnabled:!0}]};if(i.throttling)s.MethodSettings[0].ThrottlingBurstLimit=i.throttling.burstLimit,s.MethodSettings[0].ThrottlingRateLimit=i.throttling.rateLimit;if(n.addResource("RestApiStage","AWS::ApiGateway::Stage",s,{dependsOn:["RestApi","RestApiDeployment"]}),i.customDomain)Ut(n,"RestApi",i.customDomain,"REST");n.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 Br(n,i){if(n.addResource("WebSocketApi","AWS::ApiGatewayV2::Api",{Name:e.sub("${AWS::StackName}-websocket-api"),ProtocolType:"WEBSOCKET",RouteSelectionExpression:"$request.body.action"}),i.routes){if(i.routes.connect)ct(n,"$connect",i.routes.connect.functionName);if(i.routes.disconnect)ct(n,"$disconnect",i.routes.disconnect.functionName);if(i.routes.default)ct(n,"$default",i.routes.default.functionName);if(i.routes.custom)i.routes.custom.forEach((s)=>{ct(n,s.routeKey,s.functionName)})}if(n.addResource("WebSocketApiStage","AWS::ApiGatewayV2::Stage",{ApiId:e.ref("WebSocketApi"),StageName:"prod",AutoDeploy:!0,DefaultRouteSettings:i.throttling?{ThrottlingBurstLimit:i.throttling.burstLimit,ThrottlingRateLimit:i.throttling.rateLimit}:void 0},{dependsOn:"WebSocketApi"}),i.customDomain)Ut(n,"WebSocketApi",i.customDomain,"WEBSOCKET");n.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 ct(n,i,s){let o=n.toLogicalId(`websocket-route-${i}`),c=n.toLogicalId(`websocket-integration-${i}`),l=n.toLogicalId(`${s}-function`);n.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]}),n.addResource(o,"AWS::ApiGatewayV2::Route",{ApiId:e.ref("WebSocketApi"),RouteKey:i,Target:e.join("/",["integrations",e.ref(c)])},{dependsOn:["WebSocketApi",c]}),n.addResource(`${o}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 Ut(n,i,s,o){let c={DomainName:s.domain};if(o==="REST")c.CertificateArn=s.certificateArn,c.EndpointConfiguration={Types:["REGIONAL"]},n.addResource("ApiCustomDomain","AWS::ApiGateway::DomainName",c),n.addResource("ApiBasePathMapping","AWS::ApiGateway::BasePathMapping",{DomainName:e.ref("ApiCustomDomain"),RestApiId:e.ref(i),Stage:e.ref("RestApiStage")},{dependsOn:["ApiCustomDomain",i,"RestApiStage"]});else c.DomainNameConfigurations=[{CertificateArn:s.certificateArn,EndpointType:"REGIONAL"}],n.addResource("ApiCustomDomain","AWS::ApiGatewayV2::DomainName",c),n.addResource("ApiMapping","AWS::ApiGatewayV2::ApiMapping",{ApiId:e.ref(i),DomainName:e.ref("ApiCustomDomain"),Stage:o==="HTTP"?e.ref("HttpApiStage"):e.ref("WebSocketApiStage")},{dependsOn:["ApiCustomDomain",i]});if(s.dnsProvider!=="external")n.addResource("ApiDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:e.sub(`${Wr(s.domain)}.`),Name:s.domain,Type:"A",AliasTarget:{HostedZoneId:e.getAtt("ApiCustomDomain","RegionalHostedZoneId"),DNSName:e.getAtt("ApiCustomDomain","RegionalDomainName"),EvaluateTargetHealth:!1}},{dependsOn:"ApiCustomDomain"});n.addOutputs({ApiCustomDomainName:{Description:"Configured API custom domain",Value:s.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 _r(n,i,s){if(!s)return;if(s.type==="jwt")n.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:e.ref(i),AuthorizerType:"JWT",IdentitySource:[s.identitySource||"$request.header.Authorization"],JwtConfiguration:{Issuer:s.issuer,Audience:s.audience},Name:"JWTAuthorizer"},{dependsOn:i});else if(s.type==="lambda")n.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:e.ref(i),AuthorizerType:"REQUEST",AuthorizerUri:s.authorizerUri,IdentitySource:[s.identitySource||"$request.header.Authorization"],Name:"LambdaAuthorizer"},{dependsOn:i})}function Wr(n){let i=n.split(".");if(i.length>=2)return i.slice(-2).join(".");return n}function Fr(n,i){if(i.redis)Ur(n,i.redis);if(i.memcached)Hr(n,i.memcached);if(i.elasticache)Qr(n,i.elasticache)}function Ur(n,i){if(!i)return;if(n.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"]}),n.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Redis",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:i.port||6379,ToPort:i.port||6379,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]}),i.parameterGroup&&Object.keys(i.parameterGroup).length>0)n.addResource("CacheParameterGroup","AWS::ElastiCache::ParameterGroup",{Description:"Parameter group for Redis",CacheParameterGroupFamily:`redis${i.engineVersion.split(".")[0]}`,Properties:i.parameterGroup});if(i.numCacheNodes>1||i.automaticFailoverEnabled)n.addResource("RedisReplicationGroup","AWS::ElastiCache::ReplicationGroup",{ReplicationGroupDescription:"Redis replication group",ReplicationGroupId:e.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:i.engineVersion,CacheNodeType:i.nodeType,NumCacheClusters:i.numCacheNodes,AutomaticFailoverEnabled:i.automaticFailoverEnabled||!1,MultiAZEnabled:i.automaticFailoverEnabled||!1,Port:i.port||6379,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),SecurityGroupIds:[e.ref("CacheSecurityGroup")],CacheParameterGroupName:i.parameterGroup?e.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:i.snapshotRetentionLimit||5,SnapshotWindow:i.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:i.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),n.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 n.addResource("RedisCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:i.engineVersion,CacheNodeType:i.nodeType,NumCacheNodes:1,Port:i.port||6379,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],CacheParameterGroupName:i.parameterGroup?e.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:i.snapshotRetentionLimit||5,SnapshotWindow:i.snapshotWindow||"03:00-05:00",PreferredMaintenanceWindow:"sun:05:00-sun:06:00",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-redis")}]},{dependsOn:i.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),n.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 Hr(n,i){if(!i)return;if(!n.hasResource("CacheSubnetGroup"))n.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!n.hasResource("CacheSecurityGroup"))n.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Memcached",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:i.port||11211,ToPort:i.port||11211,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});n.addResource("MemcachedCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub("${AWS::StackName}-memcached"),Engine:"memcached",EngineVersion:i.engineVersion,CacheNodeType:i.nodeType,NumCacheNodes:i.numCacheNodes,Port:i.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"]}),n.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 Qr(n,i){if(!i)return;let s=i.engine==="redis";if(!n.hasResource("CacheSubnetGroup"))n.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!n.hasResource("CacheSecurityGroup"))n.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:s?6379:11211,ToPort:s?6379:11211,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});n.addResource("CacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub(`\${AWS::StackName}-${i.engine}`),Engine:i.engine,EngineVersion:i.engineVersion,CacheNodeType:i.nodeType,NumCacheNodes:i.numCacheNodes,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i.engine}`)}]},{dependsOn:["CacheSubnetGroup","CacheSecurityGroup"]})}function Jr(n,i){if(!i.enabled)return;n.addResource("CloudFrontOriginAccessIdentity","AWS::CloudFront::CloudFrontOriginAccessIdentity",{CloudFrontOriginAccessIdentityConfig:{Comment:e.sub("${AWS::StackName} CloudFront OAI")}});let s=[],o=[];if(!i.origins||i.origins.length===0)s.push({Id:"S3Origin",DomainName:e.getAtt("StaticBucket","DomainName"),S3OriginConfig:{OriginAccessIdentity:e.sub("origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}")}});else i.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(s.push(y),h>0||u.pathPattern)o.push({PathPattern:u.pathPattern||`/${u.id}/*`,TargetOriginId:u.id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:i.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:i.cachePolicy?.minTTL||0,DefaultTTL:i.cachePolicy?.defaultTTL||86400,MaxTTL:i.cachePolicy?.maxTTL||31536000})});let c={TargetOriginId:s[0].Id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:i.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:i.cachePolicy?.minTTL||0,DefaultTTL:i.cachePolicy?.defaultTTL||86400,MaxTTL:i.cachePolicy?.maxTTL||31536000};if(i.edgeFunctions&&i.edgeFunctions.length>0)c.LambdaFunctionAssociations=i.edgeFunctions.map((u)=>({EventType:u.eventType,LambdaFunctionARN:u.functionArn}));let l={Enabled:!0,HttpVersion:i.http3?"http3":"http2",IPV6Enabled:!0,Origins:s,DefaultCacheBehavior:c,PriceClass:i.priceClass||"PriceClass_100",ViewerCertificate:{}};if(o.length>0)l.CacheBehaviors=o;if(i.customDomain)l.Aliases=[i.customDomain.domain],l.ViewerCertificate={AcmCertificateArn:i.customDomain.certificateArn,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};else l.ViewerCertificate={CloudFrontDefaultCertificate:!0};if(i.errorPages)l.CustomErrorResponses=Object.entries(i.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"),n.addResource("CloudFrontDistribution","AWS::CloudFront::Distribution",{DistributionConfig:l},{dependsOn:"CloudFrontOriginAccessIdentity"}),!i.origins||i.origins.length===0)n.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(i.customDomain)n.addResource("CloudFrontDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:e.sub(`${Yr(i.customDomain.domain)}.`),Name:i.customDomain.domain,Type:"A",AliasTarget:{HostedZoneId:"Z2FDTNDATAQYW2",DNSName:e.getAtt("CloudFrontDistribution","DomainName"),EvaluateTargetHealth:!1}},{dependsOn:"CloudFrontDistribution"});if(n.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")}}}),i.customDomain)n.addOutputs({CloudFrontURL:{Description:"CloudFront custom domain URL",Value:e.sub(`https://${i.customDomain.domain}`)}})}function Yr(n){let i=n.split(".");if(i.length>=2)return i.slice(-2).join(".");return n}function Zr(n,i){if(i.server)Xr(n,i.server);if(i.fargate)pa(n,"app",i.fargate);if(i.services)i.services.forEach((s)=>{if(s.type==="fargate")pa(n,s.name,{taskDefinition:s.taskDefinition,service:s.service})})}function Xr(n,i){if(!i)return;n.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"}),n.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")}]}),n.addResource("EC2InstanceProfile","AWS::IAM::InstanceProfile",{Roles:[e.ref("EC2InstanceRole")]},{dependsOn:"EC2InstanceRole"});let s=i.userData||`#!/bin/bash
2469
2469
  set -e
2470
2470
  # Update system
2471
2471
  yum update -y || apt-get update -y
@@ -2483,33 +2483,33 @@ rpm -U ./amazon-cloudwatch-agent.rpm || true
2483
2483
  `;if(n.addResource("LaunchTemplate","AWS::EC2::LaunchTemplate",{LaunchTemplateName:e.sub("${AWS::StackName}-template"),LaunchTemplateData:{ImageId:i.ami||e.findInMap("RegionMap",e.ref("AWS::Region"),"AMI"),InstanceType:i.instanceType,IamInstanceProfile:{Arn:e.getAtt("EC2InstanceProfile","Arn")},SecurityGroupIds:[e.ref("AppSecurityGroup")],UserData:e.base64(e.sub(s)),TagSpecifications:[{ResourceType:"instance",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-instance")}]}],MetadataOptions:{HttpTokens:"required",HttpPutResponseHopLimit:1}}},{dependsOn:["AppSecurityGroup","EC2InstanceProfile"]}),i.loadBalancer){en(n,i.loadBalancer);let o={LaunchTemplate:{LaunchTemplateId:e.ref("LaunchTemplate"),Version:e.getAtt("LaunchTemplate","LatestVersionNumber")},MinSize:i.autoScaling?.min.toString()||"1",MaxSize:i.autoScaling?.max.toString()||"3",DesiredCapacity:i.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(n.addResource("AutoScalingGroup","AWS::AutoScaling::AutoScalingGroup",o,{dependsOn:["LaunchTemplate","TargetGroup"]}),i.autoScaling)n.addResource("ScaleUpPolicy","AWS::AutoScaling::ScalingPolicy",{AdjustmentType:"ChangeInCapacity",AutoScalingGroupName:e.ref("AutoScalingGroup"),Cooldown:i.autoScaling.scaleUpCooldown?.toString()||"300",ScalingAdjustment:"1"},{dependsOn:"AutoScalingGroup"}),n.addResource("ScaleDownPolicy","AWS::AutoScaling::ScalingPolicy",{AdjustmentType:"ChangeInCapacity",AutoScalingGroupName:e.ref("AutoScalingGroup"),Cooldown:i.autoScaling.scaleDownCooldown?.toString()||"300",ScalingAdjustment:"-1"},{dependsOn:"AutoScalingGroup"}),n.addResource("HighCPUAlarm","AWS::CloudWatch::Alarm",{AlarmDescription:"Scale up when CPU exceeds target",MetricName:"CPUUtilization",Namespace:"AWS/EC2",Statistic:"Average",Period:"300",EvaluationPeriods:"2",Threshold:(i.autoScaling.targetCPU||70).toString(),AlarmActions:[e.ref("ScaleUpPolicy")],Dimensions:[{Name:"AutoScalingGroupName",Value:e.ref("AutoScalingGroup")}],ComparisonOperator:"GreaterThanThreshold"},{dependsOn:["AutoScalingGroup","ScaleUpPolicy"]}),n.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:((i.autoScaling.targetCPU||70)-20).toString(),AlarmActions:[e.ref("ScaleDownPolicy")],Dimensions:[{Name:"AutoScalingGroupName",Value:e.ref("AutoScalingGroup")}],ComparisonOperator:"LessThanThreshold"},{dependsOn:["AutoScalingGroup","ScaleDownPolicy"]})}}function en(n,i){if(!i)return;n.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"}),n.addResource("LoadBalancer","AWS::ElasticLoadBalancingV2::LoadBalancer",{Name:e.sub("${AWS::StackName}-alb"),Type:i.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"]}),n.addResource("TargetGroup","AWS::ElasticLoadBalancingV2::TargetGroup",{Name:e.sub("${AWS::StackName}-tg"),Port:3000,Protocol:"HTTP",VpcId:e.ref("VPC"),HealthCheckEnabled:!0,HealthCheckPath:i.healthCheck?.path||"/health",HealthCheckProtocol:"HTTP",HealthCheckIntervalSeconds:i.healthCheck?.interval||30,HealthCheckTimeoutSeconds:i.healthCheck?.timeout||5,HealthyThresholdCount:i.healthCheck?.healthyThreshold||2,UnhealthyThresholdCount:i.healthCheck?.unhealthyThreshold||3,TargetType:"instance",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-tg")}]},{dependsOn:"VPC"}),n.addResource("LoadBalancerListener","AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:e.ref("LoadBalancer"),Port:80,Protocol:"HTTP",DefaultActions:[{Type:"forward",TargetGroupArn:e.ref("TargetGroup")}]},{dependsOn:["LoadBalancer","TargetGroup"]}),n.addOutputs({LoadBalancerDNS:{Description:"Load Balancer DNS Name",Value:e.getAtt("LoadBalancer","DNSName"),Export:{Name:e.sub("${AWS::StackName}-alb-dns")}}})}function pa(n,i,s){let o=n.toLogicalId(i),c=s.taskDefinition.containerDefinitions?.[0],l=c?.name||c?.Name||i,u=c?.portMappings?.[0]?.containerPort||c?.PortMappings?.[0]?.ContainerPort||3000,h=(s.taskDefinition.containerDefinitions||[]).flatMap((T)=>(T.secrets||T.Secrets||[]).map((w)=>w.valueFrom||w.ValueFrom)).filter(Boolean);if(!n.hasResource("ECSCluster"))n.addResource("ECSCluster","AWS::ECS::Cluster",{ClusterName:e.sub("${AWS::StackName}-cluster"),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cluster")}]});if(n.addResource(`${o}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:"*"}]}}]}:{}}),n.addResource(`${o}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:"*"}]}}]}),!n.hasResource("ALBSecurityGroup"))n.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"},...s.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(!n.hasResource("AppSecurityGroup"))n.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=(s.taskDefinition.containerDefinitions||[{name:i,image:e.sub(`\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.amazonaws.com/${i}:latest`),portMappings:[{containerPort:3000}]}]).map((T)=>({Name:T.Name||T.name,Image:T.Image||T.image,Essential:T.Essential??T.essential??!0,PortMappings:(T.PortMappings||T.portMappings||[]).map((w)=>({ContainerPort:w.ContainerPort??w.containerPort,Protocol:w.Protocol||w.protocol||"tcp"})),Environment:Array.isArray(T.Environment||T.environment)?(T.Environment||T.environment).map((w)=>({Name:w.Name||w.name,Value:w.Value??w.value})):Object.entries(T.Environment||T.environment||{}).map(([w,E])=>({Name:w,Value:E})),Secrets:(T.Secrets||T.secrets||[]).map((w)=>({Name:w.Name||w.name,ValueFrom:w.ValueFrom||w.valueFrom})),HealthCheck:T.HealthCheck||T.healthCheck,Command:T.Command||T.command,EntryPoint:T.EntryPoint||T.entryPoint,LogConfiguration:T.LogConfiguration||T.logConfiguration||{LogDriver:"awslogs",Options:{"awslogs-group":e.ref(`${o}LogGroup`),"awslogs-region":e.ref("AWS::Region"),"awslogs-stream-prefix":i}}}));n.addResource(`${o}TaskDefinition`,"AWS::ECS::TaskDefinition",{Family:e.sub(`\${AWS::StackName}-${i}`),NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:s.taskDefinition.cpu,Memory:s.taskDefinition.memory,ExecutionRoleArn:e.getAtt(`${o}TaskExecutionRole`,"Arn"),TaskRoleArn:e.getAtt(`${o}TaskRole`,"Arn"),ContainerDefinitions:y},{dependsOn:[`${o}TaskExecutionRole`,`${o}TaskRole`,`${o}LogGroup`]}),n.addResource(`${o}LogGroup`,"AWS::Logs::LogGroup",{LogGroupName:e.sub(`/ecs/\${AWS::StackName}/${i}`),RetentionInDays:14});let f=s.service.healthCheck||{};n.addResource(`${o}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"}),n.addResource(`${o}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(s.loadBalancer?.deletionProtection===!0)}],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}-alb`)}]},{dependsOn:["PublicSubnet1","PublicSubnet2","ALBSecurityGroup"]});let b=s.loadBalancer?.customDomain?.certificateArn,C=s.loadBalancer?.originVerifyHeader;if(n.addResource(`${o}HttpListener`,"AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:e.ref(`${o}LoadBalancer`),Port:80,Protocol:"HTTP",DefaultActions:b?[{Type:"redirect",RedirectConfig:{Protocol:"HTTPS",Port:"443",StatusCode:"HTTP_301"}}]:C?[{Type:"fixed-response",FixedResponseConfig:{StatusCode:"403",ContentType:"text/plain",MessageBody:"Forbidden"}}]:[{Type:"forward",TargetGroupArn:e.ref(`${o}TargetGroup`)}]},{dependsOn:[`${o}LoadBalancer`,`${o}TargetGroup`]}),b)n.addResource(`${o}HttpsListener`,"AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:e.ref(`${o}LoadBalancer`),Port:443,Protocol:"HTTPS",Certificates:[{CertificateArn:b}],SslPolicy:"ELBSecurityPolicy-TLS13-1-2-2021-06",DefaultActions:C?[{Type:"fixed-response",FixedResponseConfig:{StatusCode:"403",ContentType:"text/plain",MessageBody:"Forbidden"}}]:[{Type:"forward",TargetGroupArn:e.ref(`${o}TargetGroup`)}]},{dependsOn:[`${o}LoadBalancer`,`${o}TargetGroup`]});if(C){let T=b?`${o}HttpsListener`:`${o}HttpListener`;n.addResource(`${o}OriginVerifyRule`,"AWS::ElasticLoadBalancingV2::ListenerRule",{ListenerArn:e.ref(T),Priority:1,Conditions:[{Field:"http-header",HttpHeaderConfig:{HttpHeaderName:C.name,Values:[C.value]}}],Actions:[{Type:"forward",TargetGroupArn:e.ref(`${o}TargetGroup`)}]},{dependsOn:[T,`${o}TargetGroup`]})}if(n.addResource(`${o}Service`,"AWS::ECS::Service",{ServiceName:e.sub(`\${AWS::StackName}-${i}`),Cluster:e.ref("ECSCluster"),TaskDefinition:e.ref(`${o}TaskDefinition`),DesiredCount:s.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(`${o}TargetGroup`)}],NetworkConfiguration:{AwsvpcConfiguration:{AssignPublicIp:"DISABLED",Subnets:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],SecurityGroups:[e.ref("AppSecurityGroup")]}}},{dependsOn:["ECSCluster",`${o}TaskDefinition`,C?`${o}OriginVerifyRule`:b?`${o}HttpsListener`:`${o}HttpListener`]}),s.service.autoScaling){let T=s.service.autoScaling;n.addResource(`${o}ScalableTarget`,"AWS::ApplicationAutoScaling::ScalableTarget",{MinCapacity:T.min,MaxCapacity:T.max,ResourceId:e.join("/",["service",e.ref("ECSCluster"),e.getAtt(`${o}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:`${o}Service`}),n.addResource(`${o}ScalingPolicy`,"AWS::ApplicationAutoScaling::ScalingPolicy",{PolicyType:"TargetTrackingScaling",ScalingTargetId:e.ref(`${o}ScalableTarget`),TargetTrackingScalingPolicyConfiguration:{TargetValue:T.targetCPU||70,PredefinedMetricSpecification:{PredefinedMetricType:"ECSServiceAverageCPUUtilization"},ScaleInCooldown:60,ScaleOutCooldown:30}},{dependsOn:`${o}ScalableTarget`})}n.addOutputs({[`${o}ClusterName`]:{Description:"ECS cluster name",Value:e.ref("ECSCluster")},[`${o}ServiceName`]:{Description:"ECS service name",Value:e.getAtt(`${o}Service`,"Name")},[`${o}LoadBalancerDnsName`]:{Description:"ALB origin hostname",Value:e.getAtt(`${o}LoadBalancer`,"DNSName")},[`${o}LoadBalancerHostedZoneId`]:{Description:"ALB canonical hosted zone ID",Value:e.getAtt(`${o}LoadBalancer`,"CanonicalHostedZoneID")},[`${o}TargetGroupArn`]:{Description:"ECS target group ARN",Value:e.ref(`${o}TargetGroup`)}})}function tn(n,i){if(i.postgres)ga(n,"postgres",i.postgres);if(i.mysql)ga(n,"mysql",i.mysql);if(i.dynamodb?.tables)i.dynamodb.tables.forEach((s)=>{an(n,s)})}function ga(n,i,s){if(!s)return;let o=i==="postgres"?"postgres":"mysql",c=n.toLogicalId(`${o}-db`);n.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"]}),n.addResource("DBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for RDS instance",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:i==="postgres"?5432:3306,ToPort:i==="postgres"?5432:3306,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-db-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});let l=i==="postgres"?`postgres${s.version.split(".")[0]}`:`mysql${s.version.split(".")[0]}.${s.version.split(".")[1]||"0"}`;if(s.parameters&&Object.keys(s.parameters).length>0)n.addResource("DBParameterGroup","AWS::RDS::DBParameterGroup",{Description:`Parameter group for ${o}`,Family:l,Parameters:s.parameters,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-db-params")}]});n.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:o,EngineVersion:s.version,DBInstanceClass:s.instanceClass,AllocatedStorage:s.allocatedStorage.toString(),MaxAllocatedStorage:s.maxAllocatedStorage?.toString(),StorageType:"gp3",StorageEncrypted:!0,MultiAZ:s.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:s.backupRetentionDays||7,PreferredBackupWindow:s.preferredBackupWindow||"03:00-04:00",PreferredMaintenanceWindow:s.preferredMaintenanceWindow||"sun:04:00-sun:05:00",EnablePerformanceInsights:s.enablePerformanceInsights!==!1,PerformanceInsightsRetentionPeriod:s.performanceInsightsRetention||7,DeletionProtection:s.deletionProtection!==!1,CopyTagsToSnapshot:!0,EnableCloudwatchLogsExports:i==="postgres"?["postgresql"]:["error","general","slowquery"],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${o}-db`)}]};if(s.parameters&&Object.keys(s.parameters).length>0)u.DBParameterGroupName=e.ref("DBParameterGroup");n.addResource(c,"AWS::RDS::DBInstance",u,{dependsOn:["DBSubnetGroup","DBSecurityGroup","DBSecret"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),n.addResource("DBSecretAttachment","AWS::SecretsManager::SecretTargetAttachment",{SecretId:e.ref("DBSecret"),TargetId:e.ref(c),TargetType:"AWS::RDS::DBInstance"},{dependsOn:[c,"DBSecret"]}),n.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 an(n,i){let s=n.toLogicalId(`${i.name}-table`),o={TableName:e.sub(`\${AWS::StackName}-${i.name}`),BillingMode:i.billingMode||"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:i.partitionKey,AttributeType:"S"}],KeySchema:[{AttributeName:i.partitionKey,KeyType:"HASH"}],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i.name}`)}]};if(i.sortKey)o.AttributeDefinitions.push({AttributeName:i.sortKey,AttributeType:"S"}),o.KeySchema.push({AttributeName:i.sortKey,KeyType:"RANGE"});if(i.billingMode==="PROVISIONED")o.ProvisionedThroughput={ReadCapacityUnits:i.readCapacity||5,WriteCapacityUnits:i.writeCapacity||5};if(i.streamEnabled)o.StreamSpecification={StreamViewType:"NEW_AND_OLD_IMAGES"};if(i.pointInTimeRecovery)o.PointInTimeRecoverySpecification={PointInTimeRecoveryEnabled:!0};if(i.ttl?.enabled)o.TimeToLiveSpecification={Enabled:!0,AttributeName:i.ttl.attributeName};if(i.globalSecondaryIndexes&&i.globalSecondaryIndexes.length>0)o.GlobalSecondaryIndexes=i.globalSecondaryIndexes.map((c)=>{let l=new Set(o.AttributeDefinitions.map((h)=>h.AttributeName));if(!l.has(c.partitionKey))o.AttributeDefinitions.push({AttributeName:c.partitionKey,AttributeType:"S"});if(c.sortKey&&!l.has(c.sortKey))o.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(i.billingMode==="PROVISIONED")u.ProvisionedThroughput={ReadCapacityUnits:i.readCapacity||5,WriteCapacityUnits:i.writeCapacity||5};return u});if(n.addResource(s,"AWS::DynamoDB::Table",o,{deletionPolicy:"Retain"}),n.addOutputs({[`${s}Name`]:{Description:`${i.name} table name`,Value:e.ref(s),Export:{Name:e.sub(`\${AWS::StackName}-${i.name}-table`)}},[`${s}Arn`]:{Description:`${i.name} table ARN`,Value:e.getAtt(s,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${i.name}-table-arn`)}}}),i.streamEnabled)n.addOutputs({[`${s}StreamArn`]:{Description:`${i.name} stream ARN`,Value:e.getAtt(s,"StreamArn"),Export:{Name:e.sub(`\${AWS::StackName}-${i.name}-stream-arn`)}}})}function rn(n,i){for(let[s,o]of Object.entries(i))o.forEach((c)=>{nn(n,c,s)})}function nn(n,i,s){let o=n.toLogicalId(`${s}-${i.name}-function`),c=`${o}Role`;n.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:[...on(i.events||[])]}}],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i.name}-role`)}]});let l={FunctionName:e.sub(`\${AWS::StackName}-${i.name}`),Runtime:i.runtime,Handler:i.handler,Role:e.getAtt(c,"Arn"),MemorySize:i.memory,Timeout:i.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:i.environment?{Variables:i.environment}:void 0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i.name}`)}]};if(s!=="edge")l.VpcConfig={SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],SecurityGroupIds:[e.ref("AppSecurityGroup")]};if(n.addResource(o,"AWS::Lambda::Function",l,{dependsOn:c}),n.addResource(`${o}LogGroup`,"AWS::Logs::LogGroup",{LogGroupName:e.sub(`/aws/lambda/\${AWS::StackName}-${i.name}`),RetentionInDays:14}),i.events)i.events.forEach((u,h)=>{sn(n,o,u,h)});n.addOutputs({[`${o}Arn`]:{Description:`${i.name} function ARN`,Value:e.getAtt(o,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${i.name}-function-arn`)}}})}function sn(n,i,s,o){let c=`${i}EventSource${o}`;switch(s.type){case"http":break;case"s3":if(s.bucket){let l=n.toLogicalId(`${s.bucket}-bucket`);n.addResource(`${c}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(i),Action:"lambda:InvokeFunction",Principal:"s3.amazonaws.com",SourceArn:po.s3Bucket(e.ref(l))},{dependsOn:[i,l]})}break;case"sqs":if(s.queueName){let l=n.toLogicalId(`${s.queueName}-queue`);n.addResource(c,"AWS::Lambda::EventSourceMapping",{EventSourceArn:e.getAtt(l,"Arn"),FunctionName:e.ref(i),BatchSize:s.batchSize||10},{dependsOn:[i,l]})}break;case"kinesis":if(s.streamName){let l=n.toLogicalId(`${s.streamName}-stream`);n.addResource(c,"AWS::Lambda::EventSourceMapping",{EventSourceArn:e.getAtt(l,"Arn"),FunctionName:e.ref(i),BatchSize:s.batchSize||100,StartingPosition:s.startingPosition||"LATEST",ParallelizationFactor:s.parallelizationFactor||1},{dependsOn:[i,l]})}break;case"dynamodb-stream":if(s.tableName){let l=n.toLogicalId(`${s.tableName}-table`);n.addResource(c,"AWS::Lambda::EventSourceMapping",{EventSourceArn:e.getAtt(l,"StreamArn"),FunctionName:e.ref(i),BatchSize:s.batchSize||100,StartingPosition:s.startingPosition||"LATEST"},{dependsOn:[i,l]})}break;case"schedule":if(s.expression)n.addResource(`${c}Rule`,"AWS::Events::Rule",{ScheduleExpression:s.expression,State:"ENABLED",Targets:[{Arn:e.getAtt(i,"Arn"),Id:`${i}Target`}]},{dependsOn:i}),n.addResource(`${c}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(i),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.getAtt(`${c}Rule`,"Arn")},{dependsOn:[i,`${c}Rule`]});break}}function on(n){let i=[];if(!n)return i;if(n.forEach((s)=>{switch(s.type){case"s3":i.push({Effect:"Allow",Action:["s3:GetObject","s3:GetObjectVersion"],Resource:s.bucket?`arn:aws:s3:::${s.bucket}/*`:"arn:aws:s3:::*/*"});break;case"sqs":i.push({Effect:"Allow",Action:["sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes"],Resource:s.queueName?po.sqs(s.queueName):"arn:aws:sqs:*:*:*"});break;case"kinesis":i.push({Effect:"Allow",Action:["kinesis:GetRecords","kinesis:GetShardIterator","kinesis:DescribeStream","kinesis:ListStreams"],Resource:s.streamName?po.kinesis(s.streamName):"arn:aws:kinesis:*:*:stream/*"});break;case"dynamodb-stream":i.push({Effect:"Allow",Action:["dynamodb:GetRecords","dynamodb:GetShardIterator","dynamodb:DescribeStream","dynamodb:ListStreams"],Resource:s.tableName?e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${s.tableName}/stream/*`):"arn:aws:dynamodb:*:*:table/*/stream/*"});break}}),i.length===0)i.push({Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:"arn:aws:logs:*:*:*"});return i}function cn(n,i){if(i.topics)i.topics.forEach((s)=>{ln(n,s)})}function ln(n,i){let s=n.toLogicalId(`${i.name}-topic`);if(n.addResource(s,"AWS::SNS::Topic",{TopicName:e.sub(`\${AWS::StackName}-${i.name}`),DisplayName:i.displayName||i.name,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i.name}`)}]}),n.addResource(`${s}Policy`,"AWS::SNS::TopicPolicy",{Topics:[e.ref(s)],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(s)},{Effect:"Allow",Principal:{AWS:e.sub("arn:aws:iam::${AWS::AccountId}:root")},Action:["sns:Subscribe","sns:Publish","sns:Receive"],Resource:e.ref(s)}]}},{dependsOn:s}),i.subscriptions)i.subscriptions.forEach((o,c)=>{let l=`${s}Subscription${c+1}`,u={Protocol:o.protocol,TopicArn:e.ref(s),Endpoint:o.endpoint};if(o.filterPolicy)u.FilterPolicy=o.filterPolicy;if(o.protocol==="sqs"){let h=n.toLogicalId(`${o.endpoint}-queue`);u.Endpoint=e.getAtt(h,"Arn")}if(o.protocol==="lambda"){let h=n.toLogicalId(o.endpoint);u.Endpoint=e.getAtt(h,"Arn"),n.addResource(`${l}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(h),Action:"lambda:InvokeFunction",Principal:"sns.amazonaws.com",SourceArn:e.ref(s)},{dependsOn:[h,s]})}n.addResource(l,"AWS::SNS::Subscription",u,{dependsOn:s})});n.addOutputs({[`${s}Arn`]:{Description:`${i.name} topic ARN`,Value:e.ref(s),Export:{Name:e.sub(`\${AWS::StackName}-${i.name}-topic-arn`)}}})}function un(n,i){if(i.alarms&&i.alarms.length>0)n.addResource("AlarmTopic","AWS::SNS::Topic",{TopicName:e.sub("${AWS::StackName}-alarms"),DisplayName:"CloudWatch Alarms",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-alarms")}]}),i.alarms.forEach((s,o)=>{dn(n,s,o)});if(i.dashboard)mn(n,i.dashboard);if(i.logs?.groups)i.logs.groups.forEach((s)=>{pn(n,s,i.logs?.retention)})}function dn(n,i,s){let o=n.toLogicalId(`alarm-${i.name||i.metric}-${s}`),c={AlarmName:i.name||e.sub(`\${AWS::StackName}-${i.metric}`),AlarmDescription:`Alarm for ${i.metric}`,MetricName:i.metric,Namespace:i.namespace||Bt(i.metric,i.service),Statistic:i.statistic||"Average",Period:i.period||300,EvaluationPeriods:i.evaluationPeriods||1,Threshold:i.threshold,ComparisonOperator:i.comparisonOperator||"GreaterThanThreshold",TreatMissingData:i.treatMissingData||"notBreaching",AlarmActions:[e.ref("AlarmTopic")],OKActions:[e.ref("AlarmTopic")]};if(i.dimensions)c.Dimensions=Object.entries(i.dimensions).map(([l,u])=>({Name:l,Value:u}));else if(i.service)c.Dimensions=gn(i.service);n.addResource(o,"AWS::CloudWatch::Alarm",c,{dependsOn:"AlarmTopic"})}function mn(n,i){if(!i)return;let s=[],o=0,c=0;i.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[Bt(f),f];else return[Bt(f.metric,f.service),f.metric]});s.push({type:"metric",x:o,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)s.push({type:"log",x:o,y:c,width:u,height:h,properties:{query:`SOURCE '${l.logGroup}'
2486
+ };`},Environment:i.environment?{Variables:i.environment}:void 0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i.name}`)}]};if(s!=="edge")l.VpcConfig={SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],SecurityGroupIds:[e.ref("AppSecurityGroup")]};if(n.addResource(o,"AWS::Lambda::Function",l,{dependsOn:c}),n.addResource(`${o}LogGroup`,"AWS::Logs::LogGroup",{LogGroupName:e.sub(`/aws/lambda/\${AWS::StackName}-${i.name}`),RetentionInDays:14}),i.events)i.events.forEach((u,h)=>{sn(n,o,u,h)});n.addOutputs({[`${o}Arn`]:{Description:`${i.name} function ARN`,Value:e.getAtt(o,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${i.name}-function-arn`)}}})}function sn(n,i,s,o){let c=`${i}EventSource${o}`;switch(s.type){case"http":break;case"s3":if(s.bucket){let l=n.toLogicalId(`${s.bucket}-bucket`);n.addResource(`${c}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(i),Action:"lambda:InvokeFunction",Principal:"s3.amazonaws.com",SourceArn:mo.s3Bucket(e.ref(l))},{dependsOn:[i,l]})}break;case"sqs":if(s.queueName){let l=n.toLogicalId(`${s.queueName}-queue`);n.addResource(c,"AWS::Lambda::EventSourceMapping",{EventSourceArn:e.getAtt(l,"Arn"),FunctionName:e.ref(i),BatchSize:s.batchSize||10},{dependsOn:[i,l]})}break;case"kinesis":if(s.streamName){let l=n.toLogicalId(`${s.streamName}-stream`);n.addResource(c,"AWS::Lambda::EventSourceMapping",{EventSourceArn:e.getAtt(l,"Arn"),FunctionName:e.ref(i),BatchSize:s.batchSize||100,StartingPosition:s.startingPosition||"LATEST",ParallelizationFactor:s.parallelizationFactor||1},{dependsOn:[i,l]})}break;case"dynamodb-stream":if(s.tableName){let l=n.toLogicalId(`${s.tableName}-table`);n.addResource(c,"AWS::Lambda::EventSourceMapping",{EventSourceArn:e.getAtt(l,"StreamArn"),FunctionName:e.ref(i),BatchSize:s.batchSize||100,StartingPosition:s.startingPosition||"LATEST"},{dependsOn:[i,l]})}break;case"schedule":if(s.expression)n.addResource(`${c}Rule`,"AWS::Events::Rule",{ScheduleExpression:s.expression,State:"ENABLED",Targets:[{Arn:e.getAtt(i,"Arn"),Id:`${i}Target`}]},{dependsOn:i}),n.addResource(`${c}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(i),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.getAtt(`${c}Rule`,"Arn")},{dependsOn:[i,`${c}Rule`]});break}}function on(n){let i=[];if(!n)return i;if(n.forEach((s)=>{switch(s.type){case"s3":i.push({Effect:"Allow",Action:["s3:GetObject","s3:GetObjectVersion"],Resource:s.bucket?`arn:aws:s3:::${s.bucket}/*`:"arn:aws:s3:::*/*"});break;case"sqs":i.push({Effect:"Allow",Action:["sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes"],Resource:s.queueName?mo.sqs(s.queueName):"arn:aws:sqs:*:*:*"});break;case"kinesis":i.push({Effect:"Allow",Action:["kinesis:GetRecords","kinesis:GetShardIterator","kinesis:DescribeStream","kinesis:ListStreams"],Resource:s.streamName?mo.kinesis(s.streamName):"arn:aws:kinesis:*:*:stream/*"});break;case"dynamodb-stream":i.push({Effect:"Allow",Action:["dynamodb:GetRecords","dynamodb:GetShardIterator","dynamodb:DescribeStream","dynamodb:ListStreams"],Resource:s.tableName?e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${s.tableName}/stream/*`):"arn:aws:dynamodb:*:*:table/*/stream/*"});break}}),i.length===0)i.push({Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:"arn:aws:logs:*:*:*"});return i}function cn(n,i){if(i.topics)i.topics.forEach((s)=>{ln(n,s)})}function ln(n,i){let s=n.toLogicalId(`${i.name}-topic`);if(n.addResource(s,"AWS::SNS::Topic",{TopicName:e.sub(`\${AWS::StackName}-${i.name}`),DisplayName:i.displayName||i.name,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i.name}`)}]}),n.addResource(`${s}Policy`,"AWS::SNS::TopicPolicy",{Topics:[e.ref(s)],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(s)},{Effect:"Allow",Principal:{AWS:e.sub("arn:aws:iam::${AWS::AccountId}:root")},Action:["sns:Subscribe","sns:Publish","sns:Receive"],Resource:e.ref(s)}]}},{dependsOn:s}),i.subscriptions)i.subscriptions.forEach((o,c)=>{let l=`${s}Subscription${c+1}`,u={Protocol:o.protocol,TopicArn:e.ref(s),Endpoint:o.endpoint};if(o.filterPolicy)u.FilterPolicy=o.filterPolicy;if(o.protocol==="sqs"){let h=n.toLogicalId(`${o.endpoint}-queue`);u.Endpoint=e.getAtt(h,"Arn")}if(o.protocol==="lambda"){let h=n.toLogicalId(o.endpoint);u.Endpoint=e.getAtt(h,"Arn"),n.addResource(`${l}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(h),Action:"lambda:InvokeFunction",Principal:"sns.amazonaws.com",SourceArn:e.ref(s)},{dependsOn:[h,s]})}n.addResource(l,"AWS::SNS::Subscription",u,{dependsOn:s})});n.addOutputs({[`${s}Arn`]:{Description:`${i.name} topic ARN`,Value:e.ref(s),Export:{Name:e.sub(`\${AWS::StackName}-${i.name}-topic-arn`)}}})}function un(n,i){if(i.alarms&&i.alarms.length>0)n.addResource("AlarmTopic","AWS::SNS::Topic",{TopicName:e.sub("${AWS::StackName}-alarms"),DisplayName:"CloudWatch Alarms",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-alarms")}]}),i.alarms.forEach((s,o)=>{dn(n,s,o)});if(i.dashboard)mn(n,i.dashboard);if(i.logs?.groups)i.logs.groups.forEach((s)=>{pn(n,s,i.logs?.retention)})}function dn(n,i,s){let o=n.toLogicalId(`alarm-${i.name||i.metric}-${s}`),c={AlarmName:i.name||e.sub(`\${AWS::StackName}-${i.metric}`),AlarmDescription:`Alarm for ${i.metric}`,MetricName:i.metric,Namespace:i.namespace||Bt(i.metric,i.service),Statistic:i.statistic||"Average",Period:i.period||300,EvaluationPeriods:i.evaluationPeriods||1,Threshold:i.threshold,ComparisonOperator:i.comparisonOperator||"GreaterThanThreshold",TreatMissingData:i.treatMissingData||"notBreaching",AlarmActions:[e.ref("AlarmTopic")],OKActions:[e.ref("AlarmTopic")]};if(i.dimensions)c.Dimensions=Object.entries(i.dimensions).map(([l,u])=>({Name:l,Value:u}));else if(i.service)c.Dimensions=gn(i.service);n.addResource(o,"AWS::CloudWatch::Alarm",c,{dependsOn:"AlarmTopic"})}function mn(n,i){if(!i)return;let s=[],o=0,c=0;i.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[Bt(f),f];else return[Bt(f.metric,f.service),f.metric]});s.push({type:"metric",x:o,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)s.push({type:"log",x:o,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)s.push({type:"text",x:o,y:c,width:u,height:h,properties:{markdown:l.text}});if(o+=u,o>=24)o=0,c+=h}),n.addResource("CloudWatchDashboard","AWS::CloudWatch::Dashboard",{DashboardName:e.sub(`\${AWS::StackName}-${i.name}`),DashboardBody:JSON.stringify({widgets:s})}),n.addOutputs({DashboardURL:{Description:"CloudWatch Dashboard URL",Value:e.sub("https://console.aws.amazon.com/cloudwatch/home?region=${AWS::Region}#dashboards:name=${CloudWatchDashboard}")}})}function pn(n,i,s){let o=n.toLogicalId(`${i}-log-group`);n.addResource(o,"AWS::Logs::LogGroup",{LogGroupName:e.sub(`/aws/\${AWS::StackName}/${i}`),RetentionInDays:s||14,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}`)}]})}function Bt(n,i){if(i)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"}[i.toLowerCase()]||"AWS/CloudWatch";let s=n.toLowerCase();if(s.includes("cpu")||s.includes("memory")||s.includes("network"))return"AWS/EC2";if(s.includes("lambda")||s.includes("invocation")||s.includes("duration"))return"AWS/Lambda";if(s.includes("request")||s.includes("latency")||s.includes("target"))return"AWS/ApplicationELB";if(s.includes("database")||s.includes("connection"))return"AWS/RDS";if(s.includes("read")||s.includes("write")||s.includes("consumed"))return"AWS/DynamoDB";return"AWS/CloudWatch"}function gn(n){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")}]}[n.toLowerCase()]||[]}function hn(n,i){if(!i.vpc)return;let{cidr:s="10.0.0.0/16",availabilityZones:o=2,natGateways:c=1,enableDnsHostnames:l=!0,enableDnsSupport:u=!0}=i.vpc;n.addResource("VPC","AWS::EC2::VPC",{CidrBlock:s,EnableDnsHostnames:l,EnableDnsSupport:u,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-vpc")}]}),n.addResource("InternetGateway","AWS::EC2::InternetGateway",{Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-igw")}]}),n.addResource("VPCGatewayAttachment","AWS::EC2::VPCGatewayAttachment",{VpcId:e.ref("VPC"),InternetGatewayId:e.ref("InternetGateway")},{dependsOn:["VPC","InternetGateway"]});let h=[];for(let C=0;C<o;C++){let T=`PublicSubnet${C+1}`;h.push(T),n.addResource(T,"AWS::EC2::Subnet",{VpcId:e.ref("VPC"),CidrBlock:e.select(C,e.cidr(e.getAtt("VPC","CidrBlock"),o*2,8)),AvailabilityZone:e.select(C,e.getAZs()),MapPublicIpOnLaunch:!0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-public-${C+1}`)},{Key:"Type",Value:"public"}]},{dependsOn:"VPC"})}let y=[];for(let C=0;C<o;C++){let T=`PrivateSubnet${C+1}`;y.push(T),n.addResource(T,"AWS::EC2::Subnet",{VpcId:e.ref("VPC"),CidrBlock:e.select(C+o,e.cidr(e.getAtt("VPC","CidrBlock"),o*2,8)),AvailabilityZone:e.select(C,e.getAZs()),MapPublicIpOnLaunch:!1,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-private-${C+1}`)},{Key:"Type",Value:"private"}]},{dependsOn:"VPC"})}let f=[];for(let C=0;C<c;C++){let T=`NatEIP${C+1}`;f.push(T),n.addResource(T,"AWS::EC2::EIP",{Domain:"vpc",Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-nat-eip-${C+1}`)}]},{dependsOn:"VPCGatewayAttachment"})}let b=[];for(let C=0;C<c;C++){let T=`NatGateway${C+1}`;b.push(T);let w=C%o;n.addResource(T,"AWS::EC2::NatGateway",{AllocationId:e.getAtt(f[C],"AllocationId"),SubnetId:e.ref(h[w]),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-nat-${C+1}`)}]},{dependsOn:[f[C],h[w]]})}n.addResource("PublicRouteTable","AWS::EC2::RouteTable",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-public-rt")}]},{dependsOn:"VPC"}),n.addResource("PublicRoute","AWS::EC2::Route",{RouteTableId:e.ref("PublicRouteTable"),DestinationCidrBlock:"0.0.0.0/0",GatewayId:e.ref("InternetGateway")},{dependsOn:["PublicRouteTable","VPCGatewayAttachment"]}),h.forEach((C,T)=>{n.addResource(`PublicSubnetRouteTableAssociation${T+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:e.ref(C),RouteTableId:e.ref("PublicRouteTable")},{dependsOn:[C,"PublicRouteTable"]})}),y.forEach((C,T)=>{let w=`PrivateRouteTable${T+1}`,E=T%c;n.addResource(w,"AWS::EC2::RouteTable",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-private-rt-${T+1}`)}]},{dependsOn:"VPC"}),n.addResource(`PrivateRoute${T+1}`,"AWS::EC2::Route",{RouteTableId:e.ref(w),DestinationCidrBlock:"0.0.0.0/0",NatGatewayId:e.ref(b[E])},{dependsOn:[w,b[E]]}),n.addResource(`PrivateSubnetRouteTableAssociation${T+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:e.ref(C),RouteTableId:e.ref(w)},{dependsOn:[C,w]})}),n.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:o},(C,T)=>e.ref(`PrivateRouteTable${T+1}`))]},{dependsOn:"VPC"}),n.addResource("NetworkAcl","AWS::EC2::NetworkAcl",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-nacl")}]},{dependsOn:"VPC"}),n.addResource("NetworkAclEntryInbound","AWS::EC2::NetworkAclEntry",{NetworkAclId:e.ref("NetworkAcl"),RuleNumber:100,Protocol:-1,RuleAction:"allow",CidrBlock:"0.0.0.0/0"},{dependsOn:"NetworkAcl"}),n.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"}),n.addOutputs({VPCId:{Description:"VPC ID",Value:e.ref("VPC"),Export:{Name:e.sub("${AWS::StackName}-VPC")}},PublicSubnets:{Description:"Public subnet IDs",Value:e.join(",",h.map((C)=>e.ref(C))),Export:{Name:e.sub("${AWS::StackName}-PublicSubnets")}},PrivateSubnets:{Description:"Private subnet IDs",Value:e.join(",",y.map((C)=>e.ref(C))),Export:{Name:e.sub("${AWS::StackName}-PrivateSubnets")}}})}function yn(n,i){for(let[s,o]of Object.entries(i))fn(n,s,o)}function fn(n,i,s){let o=n.toLogicalId(`${i}-queue`),c=s.fifo||!1,l;if(s.deadLetterQueue){let h=`${o}DLQ`;n.addResource(h,"AWS::SQS::Queue",{QueueName:c?e.sub(`\${AWS::StackName}-${i}-dlq.fifo`):e.sub(`\${AWS::StackName}-${i}-dlq`),FifoQueue:c,MessageRetentionPeriod:1209600,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}-dlq`)}]},{deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),l=e.getAtt(h,"Arn")}let u={QueueName:c?e.sub(`\${AWS::StackName}-${i}.fifo`):e.sub(`\${AWS::StackName}-${i}`),FifoQueue:c,VisibilityTimeout:s.visibilityTimeout||30,MessageRetentionPeriod:s.messageRetentionPeriod||345600,ReceiveMessageWaitTimeSeconds:s.receiveMessageWaitTime||0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}`)}]};if(c&&s.contentBasedDeduplication)u.ContentBasedDeduplication=!0;if(s.deadLetterQueue&&l)u.RedrivePolicy={deadLetterTargetArn:l,maxReceiveCount:s.maxReceiveCount||3};if(n.addResource(o,"AWS::SQS::Queue",u,{dependsOn:s.deadLetterQueue?`${o}DLQ`:void 0,deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),n.addResource(`${o}Policy`,"AWS::SQS::QueuePolicy",{Queues:[e.ref(o)],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(o,"Arn"),Condition:{ArnEquals:{"aws:SourceArn":e.sub("arn:aws:*:${AWS::Region}:${AWS::AccountId}:*")}}}]}},{dependsOn:o}),n.addOutputs({[`${o}Url`]:{Description:`${i} queue URL`,Value:e.ref(o),Export:{Name:e.sub(`\${AWS::StackName}-${i}-queue-url`)}},[`${o}Arn`]:{Description:`${i} queue ARN`,Value:e.getAtt(o,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${i}-queue-arn`)}}}),s.deadLetterQueue)n.addOutputs({[`${o}DLQUrl`]:{Description:`${i} dead letter queue URL`,Value:e.ref(`${o}DLQ`),Export:{Name:e.sub(`\${AWS::StackName}-${i}-dlq-url`)}}})}function Sn(n,i){if(i.certificate)bn(n,i.certificate);if(i.waf?.enabled)An(n,i.waf);if(i.securityGroups)for(let[s,o]of Object.entries(i.securityGroups))Cn(n,s,o)}function bn(n,i){if(!i)return;let s=[i.domain];if(i.subdomains)s.push(...i.subdomains);n.addResource("Certificate","AWS::CertificateManager::Certificate",{DomainName:i.domain,SubjectAlternativeNames:i.subdomains,ValidationMethod:i.validationMethod||"DNS",DomainValidationOptions:s.map((o)=>({DomainName:o,HostedZoneId:e.ref("HostedZone")})),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-certificate")}]}),n.addOutputs({CertificateArn:{Description:"ACM Certificate ARN",Value:e.ref("Certificate"),Export:{Name:e.sub("${AWS::StackName}-certificate-arn")}}})}function An(n,i){if(!i)return;let s=[],o=i.rules||["rateLimit","sqlInjection","xss"];if(o.includes("rateLimit"))s.push({Name:"RateLimitRule",Priority:1,Statement:{RateBasedStatement:{Limit:i.rateLimit||2000,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"RateLimitRule"}});let c=s.length+1;if(o.includes("sqlInjection"))s.push({Name:"AWSManagedRulesSQLi",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesSQLiRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesSQLi"}});if(o.includes("xss"))s.push({Name:"AWSManagedRulesXSS",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesXSS"}});if(o.includes("knownBadInputs"))s.push({Name:"AWSManagedRulesKnownBadInputs",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesKnownBadInputs"}});if(o.includes("coreRuleSet"))s.push({Name:"AWSManagedRulesCoreRuleSet",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesCommonRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesCoreRuleSet"}});if(o.includes("linuxRuleSet"))s.push({Name:"AWSManagedRulesLinuxRuleSet",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesLinuxRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesLinuxRuleSet"}});if(o.includes("apiProtection"))s.push({Name:"AWSManagedRulesAPIProtection",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesAmazonIpReputationList"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesAPIProtection"}});if(o.includes("geoBlock"))s.push({Name:"GeoBlockRule",Priority:c++,Statement:{GeoMatchStatement:{CountryCodes:["CN","RU"]}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"GeoBlockRule"}});if(o.includes("connectionLimit"))s.push({Name:"ConnectionLimitRule",Priority:c++,Statement:{RateBasedStatement:{Limit:100,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"ConnectionLimitRule"}});if(n.addResource("WebACL","AWS::WAFv2::WebACL",{Name:e.sub("${AWS::StackName}-waf"),Scope:i.scope||"REGIONAL",DefaultAction:{Allow:{}},Rules:s,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:e.sub("${AWS::StackName}-waf")},Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-waf")}]}),n.hasResource("LoadBalancer"))n.addResource("WebACLAssociation","AWS::WAFv2::WebACLAssociation",{ResourceArn:e.ref("LoadBalancer"),WebACLArn:e.getAtt("WebACL","Arn")},{dependsOn:["WebACL","LoadBalancer"]});n.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 Cn(n,i,s){if(!s)return;let o=n.toLogicalId(`${i}-security-group`),c=s.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=s.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"}];n.addResource(o,"AWS::EC2::SecurityGroup",{GroupDescription:`Security group for ${i}`,VpcId:e.ref("VPC"),SecurityGroupIngress:c,SecurityGroupEgress:l,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}-sg`)}]},{dependsOn:"VPC"}),n.addOutputs({[`${o}Id`]:{Description:`${i} security group ID`,Value:e.ref(o),Export:{Name:e.sub(`\${AWS::StackName}-${i}-sg-id`)}}})}function vn(n,i){for(let[s,o]of Object.entries(i)){if(o.type==="efs"){wn(n,s,o);continue}Tn(n,s,o)}}function Tn(n,i,s){let o=n.toLogicalId(`${i}-bucket`),c={BucketName:e.sub(`\${AWS::StackName}-${i}`),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}`)}]};if(s.versioning)c.VersioningConfiguration={Status:"Enabled"};if(s.encryption)c.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(!s.public)c.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(s.website)c.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"index.html"};if(s.cors&&s.cors.length>0)c.CorsConfiguration={CorsRules:s.cors.map((l)=>({AllowedOrigins:l.allowedOrigins,AllowedMethods:l.allowedMethods,AllowedHeaders:l.allowedHeaders||["*"],MaxAge:l.maxAge||3600}))};if(s.lifecycleRules&&s.lifecycleRules.length>0)c.LifecycleConfiguration={Rules:s.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(s.intelligentTiering)c.IntelligentTieringConfigurations=[{Id:"EntireBucket",Status:"Enabled",Tierings:[{AccessTier:"ARCHIVE_ACCESS",Days:90},{AccessTier:"DEEP_ARCHIVE_ACCESS",Days:180}]}];if(n.addResource(o,"AWS::S3::Bucket",c,{deletionPolicy:s.versioning?"Retain":"Delete"}),s.public)n.addResource(`${o}Policy`,"AWS::S3::BucketPolicy",{Bucket:e.ref(o),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:"s3:GetObject",Resource:e.join("",[po.s3Bucket(e.ref(o)),"/*"])}]}},{dependsOn:o});if(n.addOutputs({[`${o}Name`]:{Description:`${i} bucket name`,Value:e.ref(o),Export:{Name:e.sub(`\${AWS::StackName}-${i}-bucket`)}},[`${o}Arn`]:{Description:`${i} bucket ARN`,Value:e.getAtt(o,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${i}-bucket-arn`)}}}),s.website)n.addOutputs({[`${o}WebsiteURL`]:{Description:`${i} website URL`,Value:e.getAtt(o,"WebsiteURL")}})}function wn(n,i,s){let o=n.toLogicalId(`${i}-efs`),c={Encrypted:s.encryption!==!1,PerformanceMode:s.performanceMode||"generalPurpose",ThroughputMode:s.throughputMode||"bursting",FileSystemTags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}`)}]};if(s.lifecyclePolicy){if(c.LifecyclePolicies=[],s.lifecyclePolicy.transitionToIA)c.LifecyclePolicies.push({TransitionToIA:`AFTER_${s.lifecyclePolicy.transitionToIA}_DAYS`});if(s.lifecyclePolicy.transitionToPrimaryStorageClass)c.LifecyclePolicies.push({TransitionToPrimaryStorageClass:"AFTER_1_ACCESS"})}n.addResource(o,"AWS::EFS::FileSystem",c,{deletionPolicy:"Retain"});let l=2;for(let u=0;u<l;u++)n.addResource(`${o}MountTarget${u+1}`,"AWS::EFS::MountTarget",{FileSystemId:e.ref(o),SubnetId:e.ref(`PrivateSubnet${u+1}`),SecurityGroups:[e.ref("EFSSecurityGroup")]},{dependsOn:[o,`PrivateSubnet${u+1}`]});n.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"}),n.addOutputs({[`${o}Id`]:{Description:`${i} EFS file system ID`,Value:e.ref(o),Export:{Name:e.sub(`\${AWS::StackName}-${i}-efs`)}}})}class Sg{template;config;resourceDependencies;constructor(n){this.config=n,this.resourceDependencies=new Map,this.template={AWSTemplateFormatVersion:"2010-09-09",Description:`Infrastructure for ${n.project.name} (${n.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:n}=this.config;if(!n)return;if(n.network)this.addNetworkResources(n.network);if(n.storage)this.addStorageResources(n.storage);if(n.compute)this.addComputeResources(n.compute);if(n.databases)this.addDatabaseResources(n.databases);if(n.cache)this.addCacheResources(n.cache);if(n.cdn)this.addCDNResources(n.cdn);if(n.apiGateway)this.addApiGatewayResources(n.apiGateway);if(n.functions)this.addFunctionResources(n.functions);if(n.queues)this.addQueueResources(n.queues);if(n.messaging)this.addMessagingResources(n.messaging);if(n.monitoring)this.addMonitoringResources(n.monitoring);if(n.security)this.addSecurityResources(n.security)}initializeOutputs(){let n=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")}},...n},this.config.environments?.production?.domain)this.template.Outputs.Domain={Description:"Production domain",Value:this.config.environments.production.domain,Condition:"HasDomain"}}addResource(n,i,s,o){let c={Type:i,Properties:s};if(o?.dependsOn)c.DependsOn=o.dependsOn,this.trackDependency(n,o.dependsOn);if(o?.condition)c.Condition=o.condition;if(o?.deletionPolicy)c.DeletionPolicy=o.deletionPolicy;if(o?.updateReplacePolicy)c.UpdateReplacePolicy=o.updateReplacePolicy;this.template.Resources[n]=c}addOutputs(n){this.template.Outputs={...this.template.Outputs,...n}}getOutputs(){return this.template.Outputs||{}}hasResource(n){return n in this.template.Resources}getResource(n){return this.template.Resources[n]}trackDependency(n,i){if(!this.resourceDependencies.has(n))this.resourceDependencies.set(n,new Set);(Array.isArray(i)?i:[i]).forEach((s)=>this.resourceDependencies.get(n).add(s))}resolveDependencies(){let n=new Set,i=new Set,s=(o)=>{if(i.has(o))throw Error(`Circular dependency detected involving resource: ${o}`);if(n.has(o))return!0;n.add(o),i.add(o);let c=this.resourceDependencies.get(o);if(c)for(let l of c)s(l);return i.delete(o),!0};for(let o of this.resourceDependencies.keys())s(o)}toLogicalId(n){return n.split(/[-_\s]/).map((i)=>i.charAt(0).toUpperCase()+i.slice(1).toLowerCase()).join("")}addNetworkResources(n){hn(this,n)}addStorageResources(n){vn(this,n)}addComputeResources(n){Zr(this,n)}addDatabaseResources(n){tn(this,n)}addFunctionResources(n){rn(this,n)}addCacheResources(n){Fr(this,n)}addQueueResources(n){yn(this,n)}addMessagingResources(n){cn(this,n)}addCDNResources(n){Jr(this,n)}addApiGatewayResources(n){Mr(this,n)}addMonitoringResources(n){un(this,n)}addSecurityResources(n){Sn(this,n)}}function _d(n){return new Sg(n).build()}function OI(n){let{name:i,slug:s,domain:o,subdomain:c}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:c&&o?`${c}.${o}`:o}},infrastructure:{storage:{assets:{public:!0,versioning:!1,website:!0,encryption:!1,cors:[{allowedOrigins:["*"],allowedMethods:["GET","HEAD"],allowedHeaders:["*"],maxAge:3600}]}},cdn:{enabled:!0,customDomain:o?{domain:c&&o?`${c}.${o}`:o,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 LI(n){let{name:i,slug:s,domain:o,instanceType:c="t3.small",minInstances:l=2,maxInstances:u=10}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",keyPair:`${s}-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:o?{domain:o,subdomains:[`*.${o}`],validationMethod:"DNS"}:void 0}}}}function $I(n){let{name:i,slug:s,domain:o,taskCpu:c="256",taskMemory:l="512",desiredCount:u=2}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:0}},compute:{fargate:{taskDefinition:{cpu:c,memory:l,containerDefinitions:[{name:"app",image:`${s}-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:{[`${s}-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:`${s}-queue`}]}},security:{certificate:o?{domain:o,subdomains:[`*.${o}`],validationMethod:"DNS"}:void 0}}}}function MI(n){let{name:i,slug:s,entry:o,domain:c,runtime:l="nodejs20.x",memory:u=1024,build:h,deploy:y,assets:f,queues:b=!0,scheduler:C="on",region:T="us-east-1"}=n;return{project:{name:i,slug:s,region:T},mode:"serverless",environments:{production:{type:"production",domain:c,app:{kind:"node",runtime:l,entry:o,memory:u,build:h,deploy:y,assets:f,queues:b,scheduler:C,domain:c}}}}}function xd(n){let i=n.database!==!1,s=n.cache!==!1,o=n.queue!==!1;return{project:{name:n.name,slug:n.slug,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:n.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:n.imageUri,portMappings:[{containerPort:3000}],environment:[{name:"NODE_ENV",value:"production"},{name:"PORT",value:"3000"},{name:"AWS_REGION",value:e.ref("AWS::Region")},...i?[{name:"DB_HOST",value:e.getAtt("PostgresDb","Endpoint.Address")},{name:"DB_PORT",value:e.getAtt("PostgresDb","Endpoint.Port")}]:[],...s?[{name:"REDIS_HOST",value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Address")},{name:"REDIS_PORT",value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Port")},{name:"REDIS_TLS",value:"true"}]:[],...o?[{name:"QUEUE_URL",value:e.ref("JobsQueue")}]:[],{name:"MAIL_TRANSPORT",value:"ses"}],secrets:i?[{name:"DB_USERNAME",valueFrom:e.sub("${DBSecret}:username::")},{name:"DB_PASSWORD",valueFrom:e.sub("${DBSecret}:password::")}]:[]}]},service:{desiredCount:n.desiredCount||1,healthCheck:{path:"/api/health",interval:30,timeout:5},autoScaling:{min:n.desiredCount||1,max:6,targetCPU:70}},loadBalancer:{type:"application",...n.certificateArn?{customDomain:{domain:n.domain,certificateArn:n.certificateArn}}:{},...n.originVerifySecret?{originVerifyHeader:{name:"X-Origin-Verify",value:n.originVerifySecret}}:{}}}},...i?{databases:{postgres:{engine:"postgres",version:"16",instanceClass:"db.t4g.micro",allocatedStorage:20,maxAllocatedStorage:100,multiAZ:!1,backupRetentionDays:7,deletionProtection:!0}}}:{},...s?{cache:{redis:{nodeType:"cache.t4g.micro",numCacheNodes:2,engine:"redis",engineVersion:"7.1",automaticFailoverEnabled:!0,snapshotRetentionLimit:5}}}:{},...o?{queues:{jobs:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0,maxReceiveCount:3,receiveMessageWaitTime:20}}}:{}}}}function FI(n){let{name:i,slug:s,domain:o,apiSubdomain:c="api"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:o}},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:o,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:`${s}-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}.${o}`,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:o,subdomains:[`*.${o}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss"]}}}}}function UI(n){let{name:i,slug:s,domain:o}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{apiGateway:{type:"HTTP",cors:{allowOrigins:["*"],allowMethods:["GET","POST","PUT","DELETE","PATCH"],allowHeaders:["Content-Type","Authorization"],maxAge:3600},customDomain:o?{domain:o,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:{[`${s}-users`]:{partitionKey:{name:"userId",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0,globalSecondaryIndexes:[{name:"EmailIndex",partitionKey:{name:"email",type:"S"},projection:"ALL"}]},[`${s}-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:o?{domain:o,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 QI(n){let{name:i,slug:s,domain:o,instanceType:c="t3.small"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",keyPair:`${s}-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:o,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,origins:[{type:"alb",pathPattern:"/wp-content/*"}]},security:{certificate:{domain:o,subdomains:[`www.${o}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss","wordpressRules"]}}}}}function HI(n){let{name:i,slug:s,domain:o,apiDomain:c}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},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:o,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:[o],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:o,subdomains:c?[c]:[],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","geoBlock"]}}}}}function GI(n){let{name:i,slug:s,domain:o,services:c}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},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:`${s}-${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:`${s}.local`},autoScaling:{min:2,max:10,targetCPU:70}}}))},apiGateway:{type:"HTTP",customDomain:{domain:o,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)=>[`${s}-${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:`${s}-events`,subscriptions:c.map((l)=>({protocol:"sqs",endpoint:`${s}-${l.name}-queue`,filterPolicy:{service:[l.name]}}))}}},monitoring:{dashboard:{name:`${s}-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:o,validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection"]}}}}}function qI(n){let{name:i,slug:s,domain:o}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{apiGateway:{type:"websocket",customDomain:o?{domain:o,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:`${s}-messages`,startingPosition:"LATEST",batchSize:100}]}},databases:{dynamodb:{tables:{[`${s}-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"}]},[`${s}-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"}]},[`${s}-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:`${s}-realtime`,widgets:[{type:"metric",metrics:["WebSocketConnections","MessagesSent","IntegrationLatency"]}]}},security:{certificate:o?{domain:o,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","connectionLimit"]}}}}}function VI(n){let{name:i,slug:s,retentionDays:o=7}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",infrastructure:{streaming:{dataStream:{name:`${s}-stream`,shardCount:2,retentionPeriod:o*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:`${s}-stream`,batchSize:1000,startingPosition:"LATEST",parallelizationFactor:10}]},transformer:{runtime:"nodejs20.x",handler:"dist/processors/transform.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${s}-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:`${s}_analytics`,workgroup:`${s}-workgroup`,outputBucket:`${s}-query-results`,tables:[{name:"raw_events",location:`s3://${s}-raw/events/`,format:"parquet",partitionKeys:["year","month","day"]},{name:"processed_events",location:`s3://${s}-processed/events/`,format:"parquet",partitionKeys:["year","month","day"]}]},glue:{crawlers:[{name:`${s}-crawler`,databaseName:`${s}_analytics`,s3Targets:[`s3://${s}-raw/`,`s3://${s}-processed/`],schedule:"cron(0 2 * * ? *)"}],jobs:[{name:`${s}-etl-job`,scriptLocation:`s3://${s}-scripts/etl.py`,role:`${s}-glue-role`,maxCapacity:10,timeout:120}]}},databases:{dynamodb:{tables:{[`${s}-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:`${s}-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:`${s}-pipeline`,widgets:[{type:"metric",metrics:["KinesisIncomingRecords","LambdaInvocations","S3ObjectsCreated","GlueJobsSucceeded"]}]},alarms:[{metric:"LambdaErrors",threshold:10,evaluationPeriods:1},{metric:"KinesisIteratorAge",threshold:60000,evaluationPeriods:2}]}}}}function jI(n){let{name:i,slug:s,domain:o,modelS3Path:c=`s3://${s}-models/`,instanceType:l="ml.t3.medium"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},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:`${s}-inference`,modelS3Path:c,instanceType:l,initialInstanceCount:1,autoScaling:{minInstances:1,maxInstances:5,targetInvocationsPerInstance:1000}}],trainingJobs:[{name:`${s}-training`,algorithmSpecification:{trainingImage:"TO_BE_SPECIFIED",trainingInputMode:"File"},instanceType:"ml.p3.2xlarge",instanceCount:1,volumeSizeInGB:50,maxRuntimeInSeconds:86400}]}},apiGateway:{type:"HTTP",customDomain:o?{domain:o,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:`${s}-inference`,MODEL_BUCKET:`${s}-models`}},"batch-predict":{runtime:"python3.11",handler:"handlers/batchPredict.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${s}-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:{[`${s}-predictions`]:{partitionKey:{name:"requestId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0},[`${s}-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:`${s}-ml`,widgets:[{type:"metric",metrics:["SageMakerInvocations","SageMakerModelLatency","APIGatewayRequests","LambdaErrors"]}]},alarms:[{metric:"SageMakerModelLatency",threshold:1000,evaluationPeriods:2},{metric:"SageMakerInvocationErrors",threshold:10,evaluationPeriods:1}]},security:{certificate:o?{domain:o,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","apiProtection"]}}}}}function zI(n){let{name:i,slug:s,domain:o,instanceType:c="t3.medium",minInstances:l=2,maxInstances:u=10,databaseEngine:h="mysql",sessionStore:y="redis"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:o}},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)s.push({type:"text",x:o,y:c,width:u,height:h,properties:{markdown:l.text}});if(o+=u,o>=24)o=0,c+=h}),n.addResource("CloudWatchDashboard","AWS::CloudWatch::Dashboard",{DashboardName:e.sub(`\${AWS::StackName}-${i.name}`),DashboardBody:JSON.stringify({widgets:s})}),n.addOutputs({DashboardURL:{Description:"CloudWatch Dashboard URL",Value:e.sub("https://console.aws.amazon.com/cloudwatch/home?region=${AWS::Region}#dashboards:name=${CloudWatchDashboard}")}})}function pn(n,i,s){let o=n.toLogicalId(`${i}-log-group`);n.addResource(o,"AWS::Logs::LogGroup",{LogGroupName:e.sub(`/aws/\${AWS::StackName}/${i}`),RetentionInDays:s||14,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}`)}]})}function Bt(n,i){if(i)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"}[i.toLowerCase()]||"AWS/CloudWatch";let s=n.toLowerCase();if(s.includes("cpu")||s.includes("memory")||s.includes("network"))return"AWS/EC2";if(s.includes("lambda")||s.includes("invocation")||s.includes("duration"))return"AWS/Lambda";if(s.includes("request")||s.includes("latency")||s.includes("target"))return"AWS/ApplicationELB";if(s.includes("database")||s.includes("connection"))return"AWS/RDS";if(s.includes("read")||s.includes("write")||s.includes("consumed"))return"AWS/DynamoDB";return"AWS/CloudWatch"}function gn(n){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")}]}[n.toLowerCase()]||[]}function hn(n,i){if(!i.vpc)return;let{cidr:s="10.0.0.0/16",availabilityZones:o=2,natGateways:c=1,enableDnsHostnames:l=!0,enableDnsSupport:u=!0}=i.vpc;n.addResource("VPC","AWS::EC2::VPC",{CidrBlock:s,EnableDnsHostnames:l,EnableDnsSupport:u,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-vpc")}]}),n.addResource("InternetGateway","AWS::EC2::InternetGateway",{Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-igw")}]}),n.addResource("VPCGatewayAttachment","AWS::EC2::VPCGatewayAttachment",{VpcId:e.ref("VPC"),InternetGatewayId:e.ref("InternetGateway")},{dependsOn:["VPC","InternetGateway"]});let h=[];for(let C=0;C<o;C++){let T=`PublicSubnet${C+1}`;h.push(T),n.addResource(T,"AWS::EC2::Subnet",{VpcId:e.ref("VPC"),CidrBlock:e.select(C,e.cidr(e.getAtt("VPC","CidrBlock"),o*2,8)),AvailabilityZone:e.select(C,e.getAZs()),MapPublicIpOnLaunch:!0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-public-${C+1}`)},{Key:"Type",Value:"public"}]},{dependsOn:"VPC"})}let y=[];for(let C=0;C<o;C++){let T=`PrivateSubnet${C+1}`;y.push(T),n.addResource(T,"AWS::EC2::Subnet",{VpcId:e.ref("VPC"),CidrBlock:e.select(C+o,e.cidr(e.getAtt("VPC","CidrBlock"),o*2,8)),AvailabilityZone:e.select(C,e.getAZs()),MapPublicIpOnLaunch:!1,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-private-${C+1}`)},{Key:"Type",Value:"private"}]},{dependsOn:"VPC"})}let f=[];for(let C=0;C<c;C++){let T=`NatEIP${C+1}`;f.push(T),n.addResource(T,"AWS::EC2::EIP",{Domain:"vpc",Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-nat-eip-${C+1}`)}]},{dependsOn:"VPCGatewayAttachment"})}let b=[];for(let C=0;C<c;C++){let T=`NatGateway${C+1}`;b.push(T);let w=C%o;n.addResource(T,"AWS::EC2::NatGateway",{AllocationId:e.getAtt(f[C],"AllocationId"),SubnetId:e.ref(h[w]),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-nat-${C+1}`)}]},{dependsOn:[f[C],h[w]]})}n.addResource("PublicRouteTable","AWS::EC2::RouteTable",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-public-rt")}]},{dependsOn:"VPC"}),n.addResource("PublicRoute","AWS::EC2::Route",{RouteTableId:e.ref("PublicRouteTable"),DestinationCidrBlock:"0.0.0.0/0",GatewayId:e.ref("InternetGateway")},{dependsOn:["PublicRouteTable","VPCGatewayAttachment"]}),h.forEach((C,T)=>{n.addResource(`PublicSubnetRouteTableAssociation${T+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:e.ref(C),RouteTableId:e.ref("PublicRouteTable")},{dependsOn:[C,"PublicRouteTable"]})}),y.forEach((C,T)=>{let w=`PrivateRouteTable${T+1}`,E=T%c;n.addResource(w,"AWS::EC2::RouteTable",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-private-rt-${T+1}`)}]},{dependsOn:"VPC"}),n.addResource(`PrivateRoute${T+1}`,"AWS::EC2::Route",{RouteTableId:e.ref(w),DestinationCidrBlock:"0.0.0.0/0",NatGatewayId:e.ref(b[E])},{dependsOn:[w,b[E]]}),n.addResource(`PrivateSubnetRouteTableAssociation${T+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:e.ref(C),RouteTableId:e.ref(w)},{dependsOn:[C,w]})}),n.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:o},(C,T)=>e.ref(`PrivateRouteTable${T+1}`))]},{dependsOn:"VPC"}),n.addResource("NetworkAcl","AWS::EC2::NetworkAcl",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-nacl")}]},{dependsOn:"VPC"}),n.addResource("NetworkAclEntryInbound","AWS::EC2::NetworkAclEntry",{NetworkAclId:e.ref("NetworkAcl"),RuleNumber:100,Protocol:-1,RuleAction:"allow",CidrBlock:"0.0.0.0/0"},{dependsOn:"NetworkAcl"}),n.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"}),n.addOutputs({VPCId:{Description:"VPC ID",Value:e.ref("VPC"),Export:{Name:e.sub("${AWS::StackName}-VPC")}},PublicSubnets:{Description:"Public subnet IDs",Value:e.join(",",h.map((C)=>e.ref(C))),Export:{Name:e.sub("${AWS::StackName}-PublicSubnets")}},PrivateSubnets:{Description:"Private subnet IDs",Value:e.join(",",y.map((C)=>e.ref(C))),Export:{Name:e.sub("${AWS::StackName}-PrivateSubnets")}}})}function yn(n,i){for(let[s,o]of Object.entries(i))fn(n,s,o)}function fn(n,i,s){let o=n.toLogicalId(`${i}-queue`),c=s.fifo||!1,l;if(s.deadLetterQueue){let h=`${o}DLQ`;n.addResource(h,"AWS::SQS::Queue",{QueueName:c?e.sub(`\${AWS::StackName}-${i}-dlq.fifo`):e.sub(`\${AWS::StackName}-${i}-dlq`),FifoQueue:c,MessageRetentionPeriod:1209600,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}-dlq`)}]},{deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),l=e.getAtt(h,"Arn")}let u={QueueName:c?e.sub(`\${AWS::StackName}-${i}.fifo`):e.sub(`\${AWS::StackName}-${i}`),FifoQueue:c,VisibilityTimeout:s.visibilityTimeout||30,MessageRetentionPeriod:s.messageRetentionPeriod||345600,ReceiveMessageWaitTimeSeconds:s.receiveMessageWaitTime||0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}`)}]};if(c&&s.contentBasedDeduplication)u.ContentBasedDeduplication=!0;if(s.deadLetterQueue&&l)u.RedrivePolicy={deadLetterTargetArn:l,maxReceiveCount:s.maxReceiveCount||3};if(n.addResource(o,"AWS::SQS::Queue",u,{dependsOn:s.deadLetterQueue?`${o}DLQ`:void 0,deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),n.addResource(`${o}Policy`,"AWS::SQS::QueuePolicy",{Queues:[e.ref(o)],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(o,"Arn"),Condition:{ArnEquals:{"aws:SourceArn":e.sub("arn:aws:*:${AWS::Region}:${AWS::AccountId}:*")}}}]}},{dependsOn:o}),n.addOutputs({[`${o}Url`]:{Description:`${i} queue URL`,Value:e.ref(o),Export:{Name:e.sub(`\${AWS::StackName}-${i}-queue-url`)}},[`${o}Arn`]:{Description:`${i} queue ARN`,Value:e.getAtt(o,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${i}-queue-arn`)}}}),s.deadLetterQueue)n.addOutputs({[`${o}DLQUrl`]:{Description:`${i} dead letter queue URL`,Value:e.ref(`${o}DLQ`),Export:{Name:e.sub(`\${AWS::StackName}-${i}-dlq-url`)}}})}function Sn(n,i){if(i.certificate)bn(n,i.certificate);if(i.waf?.enabled)An(n,i.waf);if(i.securityGroups)for(let[s,o]of Object.entries(i.securityGroups))Cn(n,s,o)}function bn(n,i){if(!i)return;let s=[i.domain];if(i.subdomains)s.push(...i.subdomains);n.addResource("Certificate","AWS::CertificateManager::Certificate",{DomainName:i.domain,SubjectAlternativeNames:i.subdomains,ValidationMethod:i.validationMethod||"DNS",DomainValidationOptions:s.map((o)=>({DomainName:o,HostedZoneId:e.ref("HostedZone")})),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-certificate")}]}),n.addOutputs({CertificateArn:{Description:"ACM Certificate ARN",Value:e.ref("Certificate"),Export:{Name:e.sub("${AWS::StackName}-certificate-arn")}}})}function An(n,i){if(!i)return;let s=[],o=i.rules||["rateLimit","sqlInjection","xss"];if(o.includes("rateLimit"))s.push({Name:"RateLimitRule",Priority:1,Statement:{RateBasedStatement:{Limit:i.rateLimit||2000,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"RateLimitRule"}});let c=s.length+1;if(o.includes("sqlInjection"))s.push({Name:"AWSManagedRulesSQLi",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesSQLiRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesSQLi"}});if(o.includes("xss"))s.push({Name:"AWSManagedRulesXSS",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesXSS"}});if(o.includes("knownBadInputs"))s.push({Name:"AWSManagedRulesKnownBadInputs",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesKnownBadInputs"}});if(o.includes("coreRuleSet"))s.push({Name:"AWSManagedRulesCoreRuleSet",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesCommonRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesCoreRuleSet"}});if(o.includes("linuxRuleSet"))s.push({Name:"AWSManagedRulesLinuxRuleSet",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesLinuxRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesLinuxRuleSet"}});if(o.includes("apiProtection"))s.push({Name:"AWSManagedRulesAPIProtection",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesAmazonIpReputationList"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesAPIProtection"}});if(o.includes("geoBlock"))s.push({Name:"GeoBlockRule",Priority:c++,Statement:{GeoMatchStatement:{CountryCodes:["CN","RU"]}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"GeoBlockRule"}});if(o.includes("connectionLimit"))s.push({Name:"ConnectionLimitRule",Priority:c++,Statement:{RateBasedStatement:{Limit:100,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"ConnectionLimitRule"}});if(n.addResource("WebACL","AWS::WAFv2::WebACL",{Name:e.sub("${AWS::StackName}-waf"),Scope:i.scope||"REGIONAL",DefaultAction:{Allow:{}},Rules:s,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:e.sub("${AWS::StackName}-waf")},Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-waf")}]}),n.hasResource("LoadBalancer"))n.addResource("WebACLAssociation","AWS::WAFv2::WebACLAssociation",{ResourceArn:e.ref("LoadBalancer"),WebACLArn:e.getAtt("WebACL","Arn")},{dependsOn:["WebACL","LoadBalancer"]});n.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 Cn(n,i,s){if(!s)return;let o=n.toLogicalId(`${i}-security-group`),c=s.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=s.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"}];n.addResource(o,"AWS::EC2::SecurityGroup",{GroupDescription:`Security group for ${i}`,VpcId:e.ref("VPC"),SecurityGroupIngress:c,SecurityGroupEgress:l,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}-sg`)}]},{dependsOn:"VPC"}),n.addOutputs({[`${o}Id`]:{Description:`${i} security group ID`,Value:e.ref(o),Export:{Name:e.sub(`\${AWS::StackName}-${i}-sg-id`)}}})}function vn(n,i){for(let[s,o]of Object.entries(i)){if(o.type==="efs"){wn(n,s,o);continue}Tn(n,s,o)}}function Tn(n,i,s){let o=n.toLogicalId(`${i}-bucket`),c={BucketName:e.sub(`\${AWS::StackName}-${i}`),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}`)}]};if(s.versioning)c.VersioningConfiguration={Status:"Enabled"};if(s.encryption)c.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(!s.public)c.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(s.website)c.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"index.html"};if(s.cors&&s.cors.length>0)c.CorsConfiguration={CorsRules:s.cors.map((l)=>({AllowedOrigins:l.allowedOrigins,AllowedMethods:l.allowedMethods,AllowedHeaders:l.allowedHeaders||["*"],MaxAge:l.maxAge||3600}))};if(s.lifecycleRules&&s.lifecycleRules.length>0)c.LifecycleConfiguration={Rules:s.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(s.intelligentTiering)c.IntelligentTieringConfigurations=[{Id:"EntireBucket",Status:"Enabled",Tierings:[{AccessTier:"ARCHIVE_ACCESS",Days:90},{AccessTier:"DEEP_ARCHIVE_ACCESS",Days:180}]}];if(n.addResource(o,"AWS::S3::Bucket",c,{deletionPolicy:s.versioning?"Retain":"Delete"}),s.public)n.addResource(`${o}Policy`,"AWS::S3::BucketPolicy",{Bucket:e.ref(o),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:"s3:GetObject",Resource:e.join("",[mo.s3Bucket(e.ref(o)),"/*"])}]}},{dependsOn:o});if(n.addOutputs({[`${o}Name`]:{Description:`${i} bucket name`,Value:e.ref(o),Export:{Name:e.sub(`\${AWS::StackName}-${i}-bucket`)}},[`${o}Arn`]:{Description:`${i} bucket ARN`,Value:e.getAtt(o,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${i}-bucket-arn`)}}}),s.website)n.addOutputs({[`${o}WebsiteURL`]:{Description:`${i} website URL`,Value:e.getAtt(o,"WebsiteURL")}})}function wn(n,i,s){let o=n.toLogicalId(`${i}-efs`),c={Encrypted:s.encryption!==!1,PerformanceMode:s.performanceMode||"generalPurpose",ThroughputMode:s.throughputMode||"bursting",FileSystemTags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}`)}]};if(s.lifecyclePolicy){if(c.LifecyclePolicies=[],s.lifecyclePolicy.transitionToIA)c.LifecyclePolicies.push({TransitionToIA:`AFTER_${s.lifecyclePolicy.transitionToIA}_DAYS`});if(s.lifecyclePolicy.transitionToPrimaryStorageClass)c.LifecyclePolicies.push({TransitionToPrimaryStorageClass:"AFTER_1_ACCESS"})}n.addResource(o,"AWS::EFS::FileSystem",c,{deletionPolicy:"Retain"});let l=2;for(let u=0;u<l;u++)n.addResource(`${o}MountTarget${u+1}`,"AWS::EFS::MountTarget",{FileSystemId:e.ref(o),SubnetId:e.ref(`PrivateSubnet${u+1}`),SecurityGroups:[e.ref("EFSSecurityGroup")]},{dependsOn:[o,`PrivateSubnet${u+1}`]});n.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"}),n.addOutputs({[`${o}Id`]:{Description:`${i} EFS file system ID`,Value:e.ref(o),Export:{Name:e.sub(`\${AWS::StackName}-${i}-efs`)}}})}class Eg{template;config;resourceDependencies;constructor(n){this.config=n,this.resourceDependencies=new Map,this.template={AWSTemplateFormatVersion:"2010-09-09",Description:`Infrastructure for ${n.project.name} (${n.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:n}=this.config;if(!n)return;if(n.network)this.addNetworkResources(n.network);if(n.storage)this.addStorageResources(n.storage);if(n.compute)this.addComputeResources(n.compute);if(n.databases)this.addDatabaseResources(n.databases);if(n.cache)this.addCacheResources(n.cache);if(n.cdn)this.addCDNResources(n.cdn);if(n.apiGateway)this.addApiGatewayResources(n.apiGateway);if(n.functions)this.addFunctionResources(n.functions);if(n.queues)this.addQueueResources(n.queues);if(n.messaging)this.addMessagingResources(n.messaging);if(n.monitoring)this.addMonitoringResources(n.monitoring);if(n.security)this.addSecurityResources(n.security)}initializeOutputs(){let n=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")}},...n},this.config.environments?.production?.domain)this.template.Outputs.Domain={Description:"Production domain",Value:this.config.environments.production.domain,Condition:"HasDomain"}}addResource(n,i,s,o){let c={Type:i,Properties:s};if(o?.dependsOn)c.DependsOn=o.dependsOn,this.trackDependency(n,o.dependsOn);if(o?.condition)c.Condition=o.condition;if(o?.deletionPolicy)c.DeletionPolicy=o.deletionPolicy;if(o?.updateReplacePolicy)c.UpdateReplacePolicy=o.updateReplacePolicy;this.template.Resources[n]=c}addOutputs(n){this.template.Outputs={...this.template.Outputs,...n}}getOutputs(){return this.template.Outputs||{}}hasResource(n){return n in this.template.Resources}getResource(n){return this.template.Resources[n]}trackDependency(n,i){if(!this.resourceDependencies.has(n))this.resourceDependencies.set(n,new Set);(Array.isArray(i)?i:[i]).forEach((s)=>this.resourceDependencies.get(n).add(s))}resolveDependencies(){let n=new Set,i=new Set,s=(o)=>{if(i.has(o))throw Error(`Circular dependency detected involving resource: ${o}`);if(n.has(o))return!0;n.add(o),i.add(o);let c=this.resourceDependencies.get(o);if(c)for(let l of c)s(l);return i.delete(o),!0};for(let o of this.resourceDependencies.keys())s(o)}toLogicalId(n){return n.split(/[-_\s]/).map((i)=>i.charAt(0).toUpperCase()+i.slice(1).toLowerCase()).join("")}addNetworkResources(n){hn(this,n)}addStorageResources(n){vn(this,n)}addComputeResources(n){Zr(this,n)}addDatabaseResources(n){tn(this,n)}addFunctionResources(n){rn(this,n)}addCacheResources(n){Fr(this,n)}addQueueResources(n){yn(this,n)}addMessagingResources(n){cn(this,n)}addCDNResources(n){Jr(this,n)}addApiGatewayResources(n){Mr(this,n)}addMonitoringResources(n){un(this,n)}addSecurityResources(n){Sn(this,n)}}function Od(n){return new Eg(n).build()}function $I(n){let{name:i,slug:s,domain:o,subdomain:c}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:c&&o?`${c}.${o}`:o}},infrastructure:{storage:{assets:{public:!0,versioning:!1,website:!0,encryption:!1,cors:[{allowedOrigins:["*"],allowedMethods:["GET","HEAD"],allowedHeaders:["*"],maxAge:3600}]}},cdn:{enabled:!0,customDomain:o?{domain:c&&o?`${c}.${o}`:o,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 MI(n){let{name:i,slug:s,domain:o,instanceType:c="t3.small",minInstances:l=2,maxInstances:u=10}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",keyPair:`${s}-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:o?{domain:o,subdomains:[`*.${o}`],validationMethod:"DNS"}:void 0}}}}function FI(n){let{name:i,slug:s,domain:o,taskCpu:c="256",taskMemory:l="512",desiredCount:u=2}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:0}},compute:{fargate:{taskDefinition:{cpu:c,memory:l,containerDefinitions:[{name:"app",image:`${s}-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:{[`${s}-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:`${s}-queue`}]}},security:{certificate:o?{domain:o,subdomains:[`*.${o}`],validationMethod:"DNS"}:void 0}}}}function UI(n){let{name:i,slug:s,entry:o,domain:c,runtime:l="nodejs20.x",memory:u=1024,build:h,deploy:y,assets:f,queues:b=!0,scheduler:C="on",region:T="us-east-1"}=n;return{project:{name:i,slug:s,region:T},mode:"serverless",environments:{production:{type:"production",domain:c,app:{kind:"node",runtime:l,entry:o,memory:u,build:h,deploy:y,assets:f,queues:b,scheduler:C,domain:c}}}}}function Ld(n){let i=n.database!==!1,s=n.cache!==!1,o=n.queue!==!1;return{project:{name:n.name,slug:n.slug,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:n.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:n.imageUri,portMappings:[{containerPort:3000}],environment:[{name:"NODE_ENV",value:"production"},{name:"PORT",value:"3000"},{name:"AWS_REGION",value:e.ref("AWS::Region")},...i?[{name:"DB_HOST",value:e.getAtt("PostgresDb","Endpoint.Address")},{name:"DB_PORT",value:e.getAtt("PostgresDb","Endpoint.Port")}]:[],...s?[{name:"REDIS_HOST",value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Address")},{name:"REDIS_PORT",value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Port")},{name:"REDIS_TLS",value:"true"}]:[],...o?[{name:"QUEUE_URL",value:e.ref("JobsQueue")}]:[],{name:"MAIL_TRANSPORT",value:"ses"}],secrets:i?[{name:"DB_USERNAME",valueFrom:e.sub("${DBSecret}:username::")},{name:"DB_PASSWORD",valueFrom:e.sub("${DBSecret}:password::")}]:[]}]},service:{desiredCount:n.desiredCount||1,healthCheck:{path:"/api/health",interval:30,timeout:5},autoScaling:{min:n.desiredCount||1,max:6,targetCPU:70}},loadBalancer:{type:"application",...n.certificateArn?{customDomain:{domain:n.domain,certificateArn:n.certificateArn}}:{},...n.originVerifySecret?{originVerifyHeader:{name:"X-Origin-Verify",value:n.originVerifySecret}}:{}}}},...i?{databases:{postgres:{engine:"postgres",version:"16",instanceClass:"db.t4g.micro",allocatedStorage:20,maxAllocatedStorage:100,multiAZ:!1,backupRetentionDays:7,deletionProtection:!0}}}:{},...s?{cache:{redis:{nodeType:"cache.t4g.micro",numCacheNodes:2,engine:"redis",engineVersion:"7.1",automaticFailoverEnabled:!0,snapshotRetentionLimit:5}}}:{},...o?{queues:{jobs:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0,maxReceiveCount:3,receiveMessageWaitTime:20}}}:{}}}}function QI(n){let{name:i,slug:s,domain:o,apiSubdomain:c="api"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:o}},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:o,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:`${s}-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}.${o}`,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:o,subdomains:[`*.${o}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss"]}}}}}function HI(n){let{name:i,slug:s,domain:o}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{apiGateway:{type:"HTTP",cors:{allowOrigins:["*"],allowMethods:["GET","POST","PUT","DELETE","PATCH"],allowHeaders:["Content-Type","Authorization"],maxAge:3600},customDomain:o?{domain:o,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:{[`${s}-users`]:{partitionKey:{name:"userId",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0,globalSecondaryIndexes:[{name:"EmailIndex",partitionKey:{name:"email",type:"S"},projection:"ALL"}]},[`${s}-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:o?{domain:o,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 GI(n){let{name:i,slug:s,domain:o,instanceType:c="t3.small"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",keyPair:`${s}-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:o,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,origins:[{type:"alb",pathPattern:"/wp-content/*"}]},security:{certificate:{domain:o,subdomains:[`www.${o}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss","wordpressRules"]}}}}}function qI(n){let{name:i,slug:s,domain:o,apiDomain:c}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},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:o,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:[o],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:o,subdomains:c?[c]:[],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","geoBlock"]}}}}}function VI(n){let{name:i,slug:s,domain:o,services:c}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},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:`${s}-${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:`${s}.local`},autoScaling:{min:2,max:10,targetCPU:70}}}))},apiGateway:{type:"HTTP",customDomain:{domain:o,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)=>[`${s}-${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:`${s}-events`,subscriptions:c.map((l)=>({protocol:"sqs",endpoint:`${s}-${l.name}-queue`,filterPolicy:{service:[l.name]}}))}}},monitoring:{dashboard:{name:`${s}-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:o,validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection"]}}}}}function jI(n){let{name:i,slug:s,domain:o}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{apiGateway:{type:"websocket",customDomain:o?{domain:o,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:`${s}-messages`,startingPosition:"LATEST",batchSize:100}]}},databases:{dynamodb:{tables:{[`${s}-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"}]},[`${s}-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"}]},[`${s}-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:`${s}-realtime`,widgets:[{type:"metric",metrics:["WebSocketConnections","MessagesSent","IntegrationLatency"]}]}},security:{certificate:o?{domain:o,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","connectionLimit"]}}}}}function zI(n){let{name:i,slug:s,retentionDays:o=7}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",infrastructure:{streaming:{dataStream:{name:`${s}-stream`,shardCount:2,retentionPeriod:o*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:`${s}-stream`,batchSize:1000,startingPosition:"LATEST",parallelizationFactor:10}]},transformer:{runtime:"nodejs20.x",handler:"dist/processors/transform.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${s}-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:`${s}_analytics`,workgroup:`${s}-workgroup`,outputBucket:`${s}-query-results`,tables:[{name:"raw_events",location:`s3://${s}-raw/events/`,format:"parquet",partitionKeys:["year","month","day"]},{name:"processed_events",location:`s3://${s}-processed/events/`,format:"parquet",partitionKeys:["year","month","day"]}]},glue:{crawlers:[{name:`${s}-crawler`,databaseName:`${s}_analytics`,s3Targets:[`s3://${s}-raw/`,`s3://${s}-processed/`],schedule:"cron(0 2 * * ? *)"}],jobs:[{name:`${s}-etl-job`,scriptLocation:`s3://${s}-scripts/etl.py`,role:`${s}-glue-role`,maxCapacity:10,timeout:120}]}},databases:{dynamodb:{tables:{[`${s}-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:`${s}-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:`${s}-pipeline`,widgets:[{type:"metric",metrics:["KinesisIncomingRecords","LambdaInvocations","S3ObjectsCreated","GlueJobsSucceeded"]}]},alarms:[{metric:"LambdaErrors",threshold:10,evaluationPeriods:1},{metric:"KinesisIteratorAge",threshold:60000,evaluationPeriods:2}]}}}}function KI(n){let{name:i,slug:s,domain:o,modelS3Path:c=`s3://${s}-models/`,instanceType:l="ml.t3.medium"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},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:`${s}-inference`,modelS3Path:c,instanceType:l,initialInstanceCount:1,autoScaling:{minInstances:1,maxInstances:5,targetInvocationsPerInstance:1000}}],trainingJobs:[{name:`${s}-training`,algorithmSpecification:{trainingImage:"TO_BE_SPECIFIED",trainingInputMode:"File"},instanceType:"ml.p3.2xlarge",instanceCount:1,volumeSizeInGB:50,maxRuntimeInSeconds:86400}]}},apiGateway:{type:"HTTP",customDomain:o?{domain:o,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:`${s}-inference`,MODEL_BUCKET:`${s}-models`}},"batch-predict":{runtime:"python3.11",handler:"handlers/batchPredict.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${s}-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:{[`${s}-predictions`]:{partitionKey:{name:"requestId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0},[`${s}-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:`${s}-ml`,widgets:[{type:"metric",metrics:["SageMakerInvocations","SageMakerModelLatency","APIGatewayRequests","LambdaErrors"]}]},alarms:[{metric:"SageMakerModelLatency",threshold:1000,evaluationPeriods:2},{metric:"SageMakerInvocationErrors",threshold:10,evaluationPeriods:1}]},security:{certificate:o?{domain:o,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","apiProtection"]}}}}}function WI(n){let{name:i,slug:s,domain:o,instanceType:c="t3.medium",minInstances:l=2,maxInstances:u=10,databaseEngine:h="mysql",sessionStore:y="redis"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:o}},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:[o||"*"],allowedMethods:["GET","HEAD"]}]}},cdn:{enabled:!0,origins:[{originId:"static-assets",domainName:`${s}-static.s3.amazonaws.com`,pathPattern:"/static/*"}],customDomain:o?{domain:o,certificateArn:"TO_BE_GENERATED"}:void 0,cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0},databases:h==="mysql"?{mysql:{engine:"mysql",version:"8.0",instanceClass:"db.t3.medium",allocatedStorage:100,maxAllocatedStorage:500,multiAZ:!0,backupRetentionDays:14,preferredBackupWindow:"03:00-04:00",preferredMaintenanceWindow:"sun:04:00-sun:05:00",enablePerformanceInsights:!0,performanceInsightsRetention:7,deletionProtection:!0,parameters:{max_connections:"500",innodb_buffer_pool_size:"{DBInstanceClassMemory*3/4}",slow_query_log:"1",long_query_time:"2"}}}:{postgres:{engine:"postgres",version:"15",instanceClass:"db.t3.medium",allocatedStorage:100,maxAllocatedStorage:500,multiAZ:!0,backupRetentionDays:14,preferredBackupWindow:"03:00-04:00",preferredMaintenanceWindow:"sun:04:00-sun:05:00",enablePerformanceInsights:!0,performanceInsightsRetention:7,deletionProtection:!0,parameters:{max_connections:"500",shared_buffers:"{DBInstanceClassMemory/4}",log_min_duration_statement:"2000"}}},cache: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:`${s}-jobs`,batchSize:10}]},"email-sender":{runtime:"nodejs20.x",handler:"dist/workers/email.handler",memory:512,timeout:60,events:[{type:"sqs",queueName:`${s}-emails`,batchSize:10}]},cleanup:{runtime:"nodejs20.x",handler:"dist/tasks/cleanup.handler",memory:512,timeout:300,events:[{type:"schedule",expression:"cron(0 2 * * ? *)"}]}},monitoring:{dashboard:{name:`${s}-web-app`,widgets:[{type:"metric",metrics:["EC2CPUUtilization","ALBRequestCount","ALBTargetResponseTime","RDSCPUUtilization","RDSDatabaseConnections","RDSReadLatency","RDSWriteLatency"]}]},alarms:[{metric:"EC2CPUUtilization",threshold:80,evaluationPeriods:2},{metric:"RDSCPUUtilization",threshold:80,evaluationPeriods:2},{metric:"RDSDatabaseConnections",threshold:400,evaluationPeriods:1},{metric:"ALBTargetResponseTime",threshold:2000,evaluationPeriods:2},{metric:"ALBUnhealthyHostCount",threshold:1,evaluationPeriods:1}],logs:{retention:14,groups:[`${s}-app`,`${s}-nginx`,`${s}-workers`]}},security:{certificate:o?{domain:o,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss","knownBadInputs"]},securityGroups:{alb:{ingress:[{port:80,protocol:"tcp",cidr:"0.0.0.0/0"},{port:443,protocol:"tcp",cidr:"0.0.0.0/0"}]},app:{ingress:[{port:3000,protocol:"tcp",source:"alb-sg"}]},database:{ingress:[{port:h==="mysql"?3306:5432,protocol:"tcp",source:"app-sg"}]},...y==="redis"&&{cache:{ingress:[{port:6379,protocol:"tcp",source:"app-sg"}]}}}}}}}function KI(n){let{name:i,slug:s,domain:o,repository:c,phpVersion:l="8.3",size:u="small",database:h=s.replace(/-/g,"_"),databasePassword:y,sslEmail:f,deployStrategy:b="push",provider:C="hetzner"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",cloud:{provider:C},environments:{production:{type:"production",domain:o}},infrastructure:{compute:{mode:"server",size:u,runtime:"php",webServer:"nginx",php:{versions:[l],default:l},managedServices:{mysql:!0,redis:!0},firewall:{enabled:!0},autoUpdates:!0,monitoring:!0,backups:{enabled:!0,schedule:"0 2 * * *",retentionCount:7}},appDatabase:{engine:"mysql",name:h,username:h,password:y}},sites:{main:{root:".",type:"laravel",domain:o,phpVersion:l,repository:{...c,strategy:b},scheduler:!0,queues:[{connection:"redis",queue:"default",processes:1}],ssl:{provider:"letsencrypt",email:f}}}}}function WI(n){let{name:i,slug:s,domain:o,layers:c,phpVersion:l="8.3",architecture:u="x86_64",memory:h=1024,build:y,deploy:f=["migrate --force"],cache:b="dynamodb",scheduler:C="on",region:T="us-east-1"}=n;return{project:{name:i,slug:s,region:T},mode:"serverless",environments:{production:{type:"production",domain:o,app:{kind:"php",runtime:"provided.al2023",phpVersion:l,architecture:u,layers:c,memory:h,build:y,deploy:f,assets:"public",queues:!0,scheduler:C,cache:{driver:b},domain:o}}}}}function JI(n){return{root:n.root??"packages/ui/dist",deploy:"server",type:"static",domain:n.domain,build:n.build??"cd packages/ui && bun install && bun run build",ssl:{provider:"letsencrypt"},auth:{username:n.username??"admin",password:n.password}}}var cA=ag,dA="./node_modules/@stacksjs/ts-cloud/dist/bin/dashboard-server.js";function En(n){let i=n.split(".").filter(Boolean);return i.length<=2?n:i.slice(-2).join(".")}function Pn(n){let i=2166136261;for(let s=0;s<n.length;s++)i^=n.charCodeAt(s),i=Math.imul(i,16777619);return i>>>0}var lA=20000,uA=12000;function pA(n){return lA+Pn(n)%uA}function $a(n,i){let s=En(n);if(s===n)return`dashboard.${s}`;for(let o of i)if(o===s)return`dashboard.${s}`;return`dashboard.${n}`}function La(n,i){let s=[],o=n.infrastructure?.dns?.domain;if(o&&!n.cloud?.attachTo)s.push(o);if(i&&n.environments?.[i]?.domain)s.push(n.environments[i].domain);for(let c of Object.values(n.sites??{})){let l=c;if(!l||l.redirect)continue;let u=l.domain;if(typeof u==="string")s.push(u);else if(Array.isArray(u))s.push(...u.filter((h)=>typeof h==="string"))}return s.filter((c)=>c&&!c.startsWith("dashboard."))}function gA(n,i,s){if(s)return s;let o=La(n,i),c=o[0];if(!c)return null;return $a(c,o)}function mA(n,i,s){if(s)return[s];let o=La(n,i),c=[];for(let l of o){let u=$a(l,o);if(!c.includes(u))c.push(u)}return c}function zt(n){return Object.entries(n.sites??{}).some(([i,s])=>{if(!s)return!1;let o=s.root??"";return Hr(i)||o==="ui/dist"||o.endsWith("/ui/dist")||o.endsWith("/dist/ui")})}var Cg="dashboard-";function Eg(n){return Cg+n.replace(/^dashboard\./,"").replace(/\./g,"-")}function Hr(n){return n==="dashboard"||n.startsWith(Cg)}function Ri(n,i,s){if(zt(n))return[];if(n.cloud?.attachTo)return[];let o=s.password?{auth:{username:s.username||"admin",password:s.password,realm:s.realm}}:{},c=s.build===!1||s.build===void 0?{}:{build:s.build};if(s.live!==!1){let l=gA(n,i,s.domain);if(!l)return[];let u=s.port??pA(l),h=n.infrastructure?.appDatabase??n.infrastructure?.compute?.database,y={root:s.uiRoot,deploy:"server",domain:l,preStart:["bun install --production --no-save"],start:`bun ${dA} --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:[cA],healthCheck:{path:"/login"},ssl:{provider:"letsencrypt"}};return[{name:Eg(l),site:y}]}return mA(n,i,s.domain).map((l)=>({name:Eg(l),site:{root:s.uiRoot,deploy:"server",type:"static",domain:l,ssl:{provider:"letsencrypt"},...c,...o}}))}function XI(n,i,s){return Ri(n,i,s)[0]??null}function Qt(n,i){let s={...n};for(let o in i){let c=i[o],l=s[o];if(c===void 0)continue;if(Array.isArray(c)&&Array.isArray(l))s[o]=[...l,...c];else if(typeof c==="object"&&c!==null&&!Array.isArray(c)&&typeof l==="object"&&l!==null&&!Array.isArray(l))s[o]=Qt(l,c);else s[o]=c}return s}function bg(n,i){return Qt(n,i)}function YI(...n){return n.reduce((i,s)=>Qt(i,s),{})}function ZI(n,i){return(s)=>{let o=n(s);if(typeof i==="function")return bg(o,i(o,s));return bg(o,i)}}function Gr(n){return{infrastructure:n}}function eS(n){return Gr({monitoring:n})}function tS(n){return Gr({security:n})}function rS(n){return Gr({databases:n})}function nS(n){return Gr({cache:n})}function iS(n){return Gr({cdn:n})}function sS(n){return Gr({queues:n})}rt();function hA(){let n=process.env.AWS_ACCESS_KEY_ID,i=process.env.AWS_SECRET_ACCESS_KEY;if(!n||!i)return null;return{accessKeyId:n,secretAccessKey:i,sessionToken:process.env.AWS_SESSION_TOKEN}}function fA(n){let i=n?.profile||process.env.AWS_PROFILE||"default",s=n?.credentialsFile||xa(Oa(),".aws","credentials");if(!Ma(s))return null;try{let o=Jt(s,"utf-8");return In(o,i)}catch{return null}}function In(n,i){let s=n.split(`
2494
- `),o=null,c,l,u;for(let h of s){let y=h.trim();if(!y||y.startsWith("#")||y.startsWith(";"))continue;let f=y.match(/^\[([^\]]+)\]$/);if(f){if(o===i&&c&&l)return{accessKeyId:c,secretAccessKey:l,sessionToken:u};o=f[1],c=void 0,l=void 0,u=void 0;continue}if(o===i){let[b,...C]=y.split("="),T=C.join("=").trim();switch(b.trim().toLowerCase()){case"aws_access_key_id":c=T;break;case"aws_secret_access_key":l=T;break;case"aws_session_token":u=T;break}}}if(o===i&&c&&l)return{accessKeyId:c,secretAccessKey:l,sessionToken:u};return null}async function AA(n){let i=n?.timeout??1000,s="http://169.254.169.254";try{let o=await et("http://169.254.169.254/latest/api/token",{method:"PUT",headers:{"X-aws-ec2-metadata-token-ttl-seconds":"21600"}},i);if(!o.ok)return null;let c=await o.text(),l=await et("http://169.254.169.254/latest/meta-data/iam/security-credentials/",{headers:{"X-aws-ec2-metadata-token":c}},i);if(!l.ok)return null;let u=(await l.text()).trim(),h=await et(`http://169.254.169.254/latest/meta-data/iam/security-credentials/${u}`,{headers:{"X-aws-ec2-metadata-token":c}},i);if(!h.ok)return null;let y=await h.json();return{accessKeyId:y.AccessKeyId,secretAccessKey:y.SecretAccessKey,sessionToken:y.Token,expiration:new Date(y.Expiration)}}catch{return null}}async function yA(n){let i=n?.timeout??1000,s=process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI,o=process.env.AWS_CONTAINER_CREDENTIALS_FULL_URI,c=null;if(s)c=`http://169.254.170.2${s}`;else if(o)c=o;if(!c)return null;try{let l={},u=process.env.AWS_CONTAINER_AUTHORIZATION_TOKEN;if(u)l.Authorization=u;let h=await et(c,{headers:l},i);if(!h.ok)return null;let y=await h.json();return{accessKeyId:y.AccessKeyId,secretAccessKey:y.SecretAccessKey,sessionToken:y.Token,expiration:new Date(y.Expiration)}}catch{return null}}async function IA(n){let i=n?.timeout??5000,s=process.env.AWS_WEB_IDENTITY_TOKEN_FILE,o=process.env.AWS_ROLE_ARN,c=process.env.AWS_ROLE_SESSION_NAME||"ts-cloud-session";if(!s||!o)return null;try{let l=Jt(s,"utf-8").trim(),u=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION||"us-east-1",h=u.startsWith("us-gov")?`https://sts.${u}.amazonaws.com`:u==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${u}.amazonaws.com`,y=new URLSearchParams({Action:"AssumeRoleWithWebIdentity",Version:"2011-06-15",RoleArn:o,RoleSessionName:c,WebIdentityToken:l}),f=await et(`${h}/?${y.toString()}`,{method:"POST"},i);if(!f.ok)return null;let b=await f.text(),C=Ze(b,"AccessKeyId"),T=Ze(b,"SecretAccessKey"),w=Ze(b,"SessionToken"),E=Ze(b,"Expiration");if(!C||!T)return null;return{accessKeyId:C,secretAccessKey:T,sessionToken:w??void 0,expiration:E?new Date(E):void 0}}catch{return null}}async function go(n){let i=hA();if(i)return i;let s=fA(n);if(s)return s;let o=await IA(n);if(o)return o;let c=await yA(n);if(c)return c;let l=await AA(n);if(l)return l;throw Error("Could not find AWS credentials. Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables, or configure ~/.aws/credentials, or run on an EC2 instance with an IAM role.")}function oS(n){let i=null,s=null;return async()=>{if(i){if(!i.expiration)return i;let o=300000;if(i.expiration.getTime()-Date.now()>o)return i}if(s)return s;return s=go(n).then((o)=>(i=o,s=null,o)).catch((o)=>{throw s=null,o}),s}}async function et(n,i,s){let o=new AbortController,c=setTimeout(()=>o.abort(),s);try{let l=await fetch(n,{...i,signal:o.signal});return clearTimeout(c),l}catch(l){throw clearTimeout(c),l}}function Ze(n,i){let s=new RegExp(`<${i}>([^<]+)</${i}>`),o=n.match(s);return o?o[1]:null}async function SA(n){return go({profile:n})}function CA(n){let i=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION;if(i)return i;let s=xa(Oa(),".aws","config");if(Ma(s))try{let o=Jt(s,"utf-8"),c=n||process.env.AWS_PROFILE||"default",l=c==="default"?"[default]":`[profile ${c}]`,u=o.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[,b]=f.split("=");if(b)return b.trim()}}}catch{}return"us-east-1"}async function EA(n){let i=n||await go(),s=CA();await rt();let o=s.startsWith("us-gov")?`https://sts.${s}.amazonaws.com`:s==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${s}.amazonaws.com`,c="Action=GetCallerIdentity&Version=2011-06-15",l=x({method:"POST",url:o,body:"Action=GetCallerIdentity&Version=2011-06-15",headers:{"Content-Type":"application/x-www-form-urlencoded"},...i,service:"sts",region:s}),u=await fetch(l.url,{method:l.method,headers:l.headers,body:l.body});if(!u.ok)throw Error(`Failed to get account ID: ${await u.text()}`);let h=await u.text(),y=Ze(h,"Account");if(!y)throw Error("Failed to parse account ID from response");return y}await rt();await rt();var Rn=5242880,Dt=5242880,Nn=5242880;class Ba{region;endpoint;forcePathStyle;credentials;credentialOptions;retryOptions;constructor(n={}){this.region=n.region||process.env.AWS_REGION||"us-east-1",this.endpoint=n.endpoint||`https://s3.${this.region}.amazonaws.com`,this.forcePathStyle=n.forcePathStyle||!1,this.credentials=n.credentials,this.credentialOptions=n.credentialOptions,this.retryOptions=n.retryOptions||{}}async getCredentials(){if(this.credentials)return this.credentials;return go(this.credentialOptions)}buildUrl(n,i){let s=i?encodeURIComponent(i).replace(/%2F/g,"/"):"";if(this.forcePathStyle)return i?`${this.endpoint}/${n}/${s}`:`${this.endpoint}/${n}`;let o=new URL(this.endpoint);return o.hostname=`${n}.${o.hostname}`,i?`${o.origin}/${s}`:o.origin}async get(n,i,s={}){let o=await this.getCredentials(),c=this.buildUrl(n,i),l={};if(s.range)l.Range=s.range;if(s.ifModifiedSince)l["If-Modified-Since"]=s.ifModifiedSince.toUTCString();if(s.ifMatch)l["If-Match"]=s.ifMatch;if(s.ifNoneMatch)l["If-None-Match"]=s.ifNoneMatch;let u=new URL(c);if(s.responseContentType)u.searchParams.set("response-content-type",s.responseContentType);if(s.responseContentDisposition)u.searchParams.set("response-content-disposition",s.responseContentDisposition);let h=x({method:"GET",url:u.toString(),headers:l,...o,service:"s3",region:this.region}),y=await fetch(h.url,{method:h.method,headers:h.headers});if(!y.ok&&y.status!==304){let f=await y.text();throw new q(`Failed to get object: ${f}`,y.status,n,i)}return y}async getText(n,i,s={}){return(await this.get(n,i,s)).text()}async getJSON(n,i,s={}){return(await this.get(n,i,s)).json()}async getBuffer(n,i,s={}){return(await this.get(n,i,s)).arrayBuffer()}async put(n,i,s,o={}){let c,l;if(typeof s==="string")c=new TextEncoder().encode(s).length,l=s;else if(s instanceof ArrayBuffer)c=s.byteLength,l=s;else if(s instanceof Uint8Array)c=s.byteLength,l=s;else if(s instanceof Blob)c=s.size,l=s;else return this.uploadMultipart(n,i,s,{...o,partSize:Dt});if(c>Nn){let u=$n(l).stream();return this.uploadMultipart(n,i,u,{...o,partSize:Dt})}return this.putSimple(n,i,l,c,o)}async putSimple(n,i,s,o,c){let l=await this.getCredentials(),u=this.buildUrl(n,i),h={"Content-Length":String(o),"Content-Type":c.contentType||ha(i)};if(c.contentEncoding)h["Content-Encoding"]=c.contentEncoding;if(c.cacheControl)h["Cache-Control"]=c.cacheControl;if(c.contentDisposition)h["Content-Disposition"]=c.contentDisposition;if(c.storageClass)h["x-amz-storage-class"]=c.storageClass;if(c.serverSideEncryption)h["x-amz-server-side-encryption"]=c.serverSideEncryption;if(c.acl)h["x-amz-acl"]=c.acl;if(c.tagging)h["x-amz-tagging"]=c.tagging;if(c.metadata)for(let[C,T]of Object.entries(c.metadata))h[`x-amz-meta-${C.toLowerCase()}`]=T;let y;if(typeof s==="string")y=s;else if(s instanceof Blob)y=await s.text();else y=new TextDecoder().decode(s instanceof ArrayBuffer?new Uint8Array(s):s);let f=x({method:"PUT",url:u,headers:h,body:y,...l,service:"s3",region:this.region}),b=await fetch(f.url,{method:f.method,headers:f.headers,body:s});if(!b.ok){let C=await b.text();throw new q(`Failed to put object: ${C}`,b.status,n,i)}return{etag:(b.headers.get("ETag")||"").replace(/"/g,"")}}async delete(n,i){let s=await this.getCredentials(),o=this.buildUrl(n,i),c=x({method:"DELETE",url:o,...s,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(!l.ok&&l.status!==204){let u=await l.text();throw new q(`Failed to delete object: ${u}`,l.status,n,i)}}async deleteMany(n,i){let s=await this.getCredentials(),o=`${this.buildUrl(n)}?delete`,c=`<?xml version="1.0" encoding="UTF-8"?><Delete><Quiet>false</Quiet>${i.map((w)=>`<Object><Key>${kn(w)}</Key></Object>`).join("")}</Delete>`,l=x({method:"POST",url:o,headers:{"Content-Type":"application/xml"},body:c,...s,service:"s3",region:this.region}),u=await fetch(l.url,{method:l.method,headers:l.headers,body:c});if(!u.ok){let w=await u.text();throw new q(`Failed to delete objects: ${w}`,u.status,n)}let h=await u.text(),y=[],f=[],b=/<Deleted><Key>([^<]+)<\/Key>/g,C;while((C=b.exec(h))!==null)y.push(C[1]);let T=/<Error><Key>([^<]+)<\/Key><Code>([^<]+)<\/Code><Message>([^<]+)<\/Message>/g;while((C=T.exec(h))!==null)f.push({key:C[1],error:`${C[2]}: ${C[3]}`});return{deleted:y,errors:f}}async list(n,i={}){let s=await this.getCredentials(),o=new URL(this.buildUrl(n));if(o.searchParams.set("list-type","2"),i.prefix)o.searchParams.set("prefix",i.prefix);if(i.delimiter)o.searchParams.set("delimiter",i.delimiter);if(i.maxKeys)o.searchParams.set("max-keys",String(i.maxKeys));if(i.continuationToken)o.searchParams.set("continuation-token",i.continuationToken);if(i.startAfter)o.searchParams.set("start-after",i.startAfter);let c=x({method:"GET",url:o.toString(),...s,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(!l.ok){let h=await l.text();throw new q(`Failed to list objects: ${h}`,l.status,n)}let u=await l.text();return Dn(u)}async*listAll(n,i={}){let s;do{let o=await this.list(n,{...i,continuationToken:s});for(let c of o.contents)yield c;s=o.nextContinuationToken}while(s)}async head(n,i){let s=await this.getCredentials(),o=this.buildUrl(n,i),c=x({method:"HEAD",url:o,...s,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(l.status===404)return null;if(!l.ok){let h=await l.text();throw new q(`Failed to head object: ${h}`,l.status,n,i)}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(n,i){return await this.head(n,i)!==null}async copy(n,i,s,o,c={}){let l=await this.getCredentials(),u=this.buildUrl(s,o),h={"x-amz-copy-source":`/${n}/${encodeURIComponent(i)}`};if(c.metadataDirective)h["x-amz-metadata-directive"]=c.metadataDirective;if(c.contentType)h["Content-Type"]=c.contentType;if(c.storageClass)h["x-amz-storage-class"]=c.storageClass;if(c.acl)h["x-amz-acl"]=c.acl;if(c.metadata)for(let[C,T]of Object.entries(c.metadata))h[`x-amz-meta-${C.toLowerCase()}`]=T;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 C=await f.text();throw new q(`Failed to copy object: ${C}`,f.status,s,o)}let b=(await f.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:b?b[1]:""}}async getPresignedUrl(n,i,s={}){let o=await this.getCredentials(),c=this.buildUrl(n,i);return eA({url:c,method:s.method||"GET",expiresIn:s.expiresIn||3600,...o,service:"s3",region:this.region})}async uploadMultipart(n,i,s,o={}){let c=await this.getCredentials(),l=Math.max(o.partSize||Dt,Rn),u,h;if(s instanceof ReadableStream)u=s;else if(s instanceof Blob)u=s.stream(),h=s.size;else{let b=new Blob([s]);u=b.stream(),h=b.size}let{uploadId:y,baseUrl:f}=await this.initiateMultipartUpload(n,i,o);try{let b=await this.uploadParts(n,i,f,y,u,l,c,h,o.concurrency||4,o.onProgress);return await this.completeMultipartUpload(n,i,f,y,b)}catch(b){throw await this.abortMultipartUpload(n,i,y,f).catch(()=>{}),b}}async initiateMultipartUpload(n,i,s){let o=await this.getCredentials(),c=this.buildUrl(n,i),l=`${c}?uploads`,u={"Content-Type":s.contentType||ha(i)};if(s.storageClass)u["x-amz-storage-class"]=s.storageClass;if(s.serverSideEncryption)u["x-amz-server-side-encryption"]=s.serverSideEncryption;if(s.acl)u["x-amz-acl"]=s.acl;if(s.metadata)for(let[C,T]of Object.entries(s.metadata))u[`x-amz-meta-${C.toLowerCase()}`]=T;let h=x({method:"POST",url:l,headers:u,...o,service:"s3",region:this.region}),y=await fetch(h.url,{method:h.method,headers:h.headers});if(!y.ok){let C=await y.text();throw new q(`Failed to initiate multipart upload: ${C}`,y.status,n,i)}let f=(await y.text()).match(/<UploadId>([^<]+)<\/UploadId>/);if(!f)throw new q("Failed to parse upload ID from response",0,n,i);let b=c;if(y.url)try{let C=new URL(y.url);C.search="",b=C.toString()}catch{}return{uploadId:f[1],baseUrl:b}}async uploadParts(n,i,s,o,c,l,u,h,y,f){let b=[],C=c.getReader(),T=1,w=new Uint8Array(0),E=0,I=h?Math.ceil(h/l):void 0,N=new Map,D=async(R,W)=>{let _=`${s}?partNumber=${W}&uploadId=${encodeURIComponent(o)}`,j={"Content-Length":String(R.byteLength),"x-amz-content-sha256":"UNSIGNED-PAYLOAD"},J=x({method:"PUT",url:_,headers:j,...u,service:"s3",region:this.region}),K=await fetch(J.url,{method:J.method,headers:J.headers,body:R,redirect:"error"});if(!K.ok){let X=await K.text();throw new q(`Failed to upload part ${W}: ${X}`,K.status,n,i)}let Y=(K.headers.get("ETag")||"").replace(/"/g,"");if(!Y)throw new q(`Missing ETag for part ${W}`,K.status,n,i);return{partNumber:W,etag:Y}},B=async()=>{let R=await Promise.race(N.values());N.delete(R.partNumber),b.push(R)};while(!0){let{done:R,value:W}=await C.read();if(W){let _=new Uint8Array(w.length+W.length);_.set(w),_.set(W,w.length),w=_}while(w.length>=l||R&&w.length>0){let _=w.slice(0,l);w=w.slice(l);let j=T++;if(N.size>=y)await B();if(N.set(j,D(_,j)),E+=_.byteLength,f)f({loaded:E,total:h||E,part:j,totalParts:I||j})}if(R)break}while(N.size>0)await B();return b.sort((R,W)=>R.partNumber-W.partNumber),b}async completeMultipartUpload(n,i,s,o,c){let l=await this.getCredentials(),u=`${s}?uploadId=${encodeURIComponent(o)}`,h=`<?xml version="1.0" encoding="UTF-8"?><CompleteMultipartUpload>${c.map((C)=>`<Part><PartNumber>${C.partNumber}</PartNumber><ETag>"${C.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 C=await f.text();throw new q(`Failed to complete multipart upload: ${C}`,f.status,n,i)}let b=(await f.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:b?b[1]:""}}async abortMultipartUpload(n,i,s,o){let c=await this.getCredentials(),l=`${o??this.buildUrl(n,i)}?uploadId=${encodeURIComponent(s)}`,u=x({method:"DELETE",url:l,...c,service:"s3",region:this.region});await fetch(u.url,{method:u.method,headers:u.headers})}async emptyAndDeleteBucket(n){let i=[];for await(let l of this.listAll(n,{}))if(i.push(l.key),i.length>=1000)await this.deleteMany(n,i),i=[];if(i.length>0)await this.deleteMany(n,i);let s=await this.getCredentials(),o=this.buildUrl(n),c=x({method:"DELETE",url:o,...s,service:"s3",region:this.region});await fetch(c.url,{method:c.method,headers:c.headers})}}class q extends Error{statusCode;bucket;key;constructor(n,i,s,o){super(n);this.statusCode=i,this.bucket=s,this.key=o,this.name="S3Error"}}function Dn(n){let i=[],s=[],o=/<Contents>([\s\S]*?)<\/Contents>/g,c;while((c=o.exec(n))!==null){let u=c[1];i.push({key:ce(u,"Key")||"",lastModified:new Date(ce(u,"LastModified")||0),etag:(ce(u,"ETag")||"").replace(/"/g,""),size:Number(ce(u,"Size")||0),storageClass:ce(u,"StorageClass")||"STANDARD"})}let l=/<CommonPrefixes><Prefix>([^<]+)<\/Prefix><\/CommonPrefixes>/g;while((c=l.exec(n))!==null)s.push(c[1]);return{contents:i,commonPrefixes:s,isTruncated:ce(n,"IsTruncated")==="true",continuationToken:ce(n,"ContinuationToken")||void 0,nextContinuationToken:ce(n,"NextContinuationToken")||void 0,keyCount:Number(ce(n,"KeyCount")||0),maxKeys:Number(ce(n,"MaxKeys")||1000),prefix:ce(n,"Prefix")||void 0,delimiter:ce(n,"Delimiter")||void 0}}function ce(n,i){let s=new RegExp(`<${i}>([^<]*)</${i}>`),o=n.match(s);return o?o[1]:null}function kn(n){return n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function ha(n){let i=n.split(".").pop()?.toLowerCase();return{html:"text/html",htm:"text/html",css:"text/css",js:"application/javascript",mjs:"application/javascript",json:"application/json",xml:"application/xml",txt:"text/plain",md:"text/markdown",csv:"text/csv",jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",gif:"image/gif",webp:"image/webp",svg:"image/svg+xml",ico:"image/x-icon",avif:"image/avif",mp4:"video/mp4",webm:"video/webm",mov:"video/quicktime",avi:"video/x-msvideo",mp3:"audio/mpeg",wav:"audio/wav",ogg:"audio/ogg",pdf:"application/pdf",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xls:"application/vnd.ms-excel",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",ppt:"application/vnd.ms-powerpoint",pptx:"application/vnd.openxmlformats-officedocument.presentationml.presentation",zip:"application/zip",gz:"application/gzip",tar:"application/x-tar",rar:"application/vnd.rar","7z":"application/x-7z-compressed",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf",otf:"font/otf",eot:"application/vnd.ms-fontobject",wasm:"application/wasm"}[i||""]||"application/octet-stream"}function $n(n){if(n instanceof Blob)return n;if(typeof n==="string")return new Blob([n],{type:"text/plain"});return new Blob([n])}function aS(n){return new Ba(n)}await rt();class ze extends Error{code;solution;details;constructor(n,i,s,o){super(n);this.code=i,this.solution=s,this.details=o,this.name="CloudError",Error.captureStackTrace?.(this,ze)}toString(){let n=`${this.name} [${this.code}]: ${this.message}`;if(this.solution)n+=`
2493
+ `}},storage:{uploads:{type:"efs",performanceMode:"generalPurpose",throughputMode:"bursting",encrypted:!0,lifecyclePolicy:{transitionToIA:30}},backups:{public:!1,versioning:!0,encryption:!0,lifecycleRules:[{id:"ArchiveOldBackups",enabled:!0,transitions:[{days:90,storageClass:"GLACIER"}]}]},static:{public:!0,versioning:!1,encryption:!1,cors:[{allowedOrigins:[o||"*"],allowedMethods:["GET","HEAD"]}]}},cdn:{enabled:!0,origins:[{originId:"static-assets",domainName:`${s}-static.s3.amazonaws.com`,pathPattern:"/static/*"}],customDomain:o?{domain:o,certificateArn:"TO_BE_GENERATED"}:void 0,cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0},databases:h==="mysql"?{mysql:{engine:"mysql",version:"8.0",instanceClass:"db.t3.medium",allocatedStorage:100,maxAllocatedStorage:500,multiAZ:!0,backupRetentionDays:14,preferredBackupWindow:"03:00-04:00",preferredMaintenanceWindow:"sun:04:00-sun:05:00",enablePerformanceInsights:!0,performanceInsightsRetention:7,deletionProtection:!0,parameters:{max_connections:"500",innodb_buffer_pool_size:"{DBInstanceClassMemory*3/4}",slow_query_log:"1",long_query_time:"2"}}}:{postgres:{engine:"postgres",version:"15",instanceClass:"db.t3.medium",allocatedStorage:100,maxAllocatedStorage:500,multiAZ:!0,backupRetentionDays:14,preferredBackupWindow:"03:00-04:00",preferredMaintenanceWindow:"sun:04:00-sun:05:00",enablePerformanceInsights:!0,performanceInsightsRetention:7,deletionProtection:!0,parameters:{max_connections:"500",shared_buffers:"{DBInstanceClassMemory/4}",log_min_duration_statement:"2000"}}},cache: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:`${s}-jobs`,batchSize:10}]},"email-sender":{runtime:"nodejs20.x",handler:"dist/workers/email.handler",memory:512,timeout:60,events:[{type:"sqs",queueName:`${s}-emails`,batchSize:10}]},cleanup:{runtime:"nodejs20.x",handler:"dist/tasks/cleanup.handler",memory:512,timeout:300,events:[{type:"schedule",expression:"cron(0 2 * * ? *)"}]}},monitoring:{dashboard:{name:`${s}-web-app`,widgets:[{type:"metric",metrics:["EC2CPUUtilization","ALBRequestCount","ALBTargetResponseTime","RDSCPUUtilization","RDSDatabaseConnections","RDSReadLatency","RDSWriteLatency"]}]},alarms:[{metric:"EC2CPUUtilization",threshold:80,evaluationPeriods:2},{metric:"RDSCPUUtilization",threshold:80,evaluationPeriods:2},{metric:"RDSDatabaseConnections",threshold:400,evaluationPeriods:1},{metric:"ALBTargetResponseTime",threshold:2000,evaluationPeriods:2},{metric:"ALBUnhealthyHostCount",threshold:1,evaluationPeriods:1}],logs:{retention:14,groups:[`${s}-app`,`${s}-nginx`,`${s}-workers`]}},security:{certificate:o?{domain:o,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss","knownBadInputs"]},securityGroups:{alb:{ingress:[{port:80,protocol:"tcp",cidr:"0.0.0.0/0"},{port:443,protocol:"tcp",cidr:"0.0.0.0/0"}]},app:{ingress:[{port:3000,protocol:"tcp",source:"alb-sg"}]},database:{ingress:[{port:h==="mysql"?3306:5432,protocol:"tcp",source:"app-sg"}]},...y==="redis"&&{cache:{ingress:[{port:6379,protocol:"tcp",source:"app-sg"}]}}}}}}}function JI(n){let{name:i,slug:s,domain:o,repository:c,phpVersion:l="8.3",size:u="small",database:h=s.replace(/-/g,"_"),databasePassword:y,sslEmail:f,deployStrategy:b="push",provider:C="hetzner"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",cloud:{provider:C},environments:{production:{type:"production",domain:o}},infrastructure:{compute:{mode:"server",size:u,runtime:"php",webServer:"nginx",php:{versions:[l],default:l},managedServices:{mysql:!0,redis:!0},firewall:{enabled:!0},autoUpdates:!0,monitoring:!0,backups:{enabled:!0,schedule:"0 2 * * *",retentionCount:7}},appDatabase:{engine:"mysql",name:h,username:h,password:y}},sites:{main:{root:".",type:"laravel",domain:o,phpVersion:l,repository:{...c,strategy:b},scheduler:!0,queues:[{connection:"redis",queue:"default",processes:1}],ssl:{provider:"letsencrypt",email:f}}}}}function XI(n){let{name:i,slug:s,domain:o,layers:c,phpVersion:l="8.3",architecture:u="x86_64",memory:h=1024,build:y,deploy:f=["migrate --force"],cache:b="dynamodb",scheduler:C="on",region:T="us-east-1"}=n;return{project:{name:i,slug:s,region:T},mode:"serverless",environments:{production:{type:"production",domain:o,app:{kind:"php",runtime:"provided.al2023",phpVersion:l,architecture:u,layers:c,memory:h,build:y,deploy:f,assets:"public",queues:!0,scheduler:C,cache:{driver:b},domain:o}}}}}function YI(n){return{root:n.root??"packages/ui/dist",deploy:"server",type:"static",domain:n.domain,build:n.build??"cd packages/ui && bun install && bun run build",ssl:{provider:"letsencrypt"},auth:{username:n.username??"admin",password:n.password}}}var lA=dg,uA="./node_modules/@stacksjs/ts-cloud/dist/bin/dashboard-server.js";function En(n){let i=n.split(".").filter(Boolean);return i.length<=2?n:i.slice(-2).join(".")}function Pn(n){let i=2166136261;for(let s=0;s<n.length;s++)i^=n.charCodeAt(s),i=Math.imul(i,16777619);return i>>>0}var pA=20000,gA=12000;function mA(n){return pA+Pn(n)%gA}function $a(n,i){let s=En(n);if(s===n)return`dashboard.${s}`;for(let o of i)if(o===s)return`dashboard.${s}`;return`dashboard.${n}`}function La(n,i){let s=[],o=n.infrastructure?.dns?.domain;if(o&&!n.cloud?.attachTo)s.push(o);if(i&&n.environments?.[i]?.domain)s.push(n.environments[i].domain);for(let c of Object.values(n.sites??{})){let l=c;if(!l||l.redirect)continue;let u=l.domain;if(typeof u==="string")s.push(u);else if(Array.isArray(u))s.push(...u.filter((h)=>typeof h==="string"))}return s.filter((c)=>c&&!c.startsWith("dashboard."))}function hA(n,i,s){if(s)return s;let o=La(n,i),c=o[0];if(!c)return null;return $a(c,o)}function fA(n,i,s){if(s)return[s];let o=La(n,i),c=[];for(let l of o){let u=$a(l,o);if(!c.includes(u))c.push(u)}return c}function Kt(n){return Object.entries(n.sites??{}).some(([i,s])=>{if(!s)return!1;let o=s.root??"";return qr(i)||o==="ui/dist"||o.endsWith("/ui/dist")||o.endsWith("/dist/ui")})}var bg="dashboard-";function vg(n){return bg+n.replace(/^dashboard\./,"").replace(/\./g,"-")}function qr(n){return n==="dashboard"||n.startsWith(bg)}function Pi(n,i,s){if(Kt(n))return[];if(n.cloud?.attachTo)return[];let o=s.password?{auth:{username:s.username||"admin",password:s.password,realm:s.realm}}:{},c=s.build===!1||s.build===void 0?{}:{build:s.build};if(s.live!==!1){let l=hA(n,i,s.domain);if(!l)return[];let u=s.port??mA(l),h=n.infrastructure?.appDatabase??n.infrastructure?.compute?.database,y={root:s.uiRoot,deploy:"server",domain:l,preStart:["bun install --production --no-save"],start:`bun ${uA} --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:[lA],healthCheck:{path:"/login"},ssl:{provider:"letsencrypt"}};return[{name:vg(l),site:y}]}return fA(n,i,s.domain).map((l)=>({name:vg(l),site:{root:s.uiRoot,deploy:"server",type:"static",domain:l,ssl:{provider:"letsencrypt"},...c,...o}}))}function ZI(n,i,s){return Pi(n,i,s)[0]??null}function Ht(n,i){let s={...n};for(let o in i){let c=i[o],l=s[o];if(c===void 0)continue;if(Array.isArray(c)&&Array.isArray(l))s[o]=[...l,...c];else if(typeof c==="object"&&c!==null&&!Array.isArray(c)&&typeof l==="object"&&l!==null&&!Array.isArray(l))s[o]=Ht(l,c);else s[o]=c}return s}function Tg(n,i){return Ht(n,i)}function eS(...n){return n.reduce((i,s)=>Ht(i,s),{})}function tS(n,i){return(s)=>{let o=n(s);if(typeof i==="function")return Tg(o,i(o,s));return Tg(o,i)}}function Vr(n){return{infrastructure:n}}function rS(n){return Vr({monitoring:n})}function nS(n){return Vr({security:n})}function iS(n){return Vr({databases:n})}function sS(n){return Vr({cache:n})}function oS(n){return Vr({cdn:n})}function aS(n){return Vr({queues:n})}rt();function AA(){let n=process.env.AWS_ACCESS_KEY_ID,i=process.env.AWS_SECRET_ACCESS_KEY;if(!n||!i)return null;return{accessKeyId:n,secretAccessKey:i,sessionToken:process.env.AWS_SESSION_TOKEN}}function yA(n){let i=n?.profile||process.env.AWS_PROFILE||"default",s=n?.credentialsFile||xa(Oa(),".aws","credentials");if(!Ma(s))return null;try{let o=Qt(s,"utf-8");return In(o,i)}catch{return null}}function In(n,i){let s=n.split(`
2494
+ `),o=null,c,l,u;for(let h of s){let y=h.trim();if(!y||y.startsWith("#")||y.startsWith(";"))continue;let f=y.match(/^\[([^\]]+)\]$/);if(f){if(o===i&&c&&l)return{accessKeyId:c,secretAccessKey:l,sessionToken:u};o=f[1],c=void 0,l=void 0,u=void 0;continue}if(o===i){let[b,...C]=y.split("="),T=C.join("=").trim();switch(b.trim().toLowerCase()){case"aws_access_key_id":c=T;break;case"aws_secret_access_key":l=T;break;case"aws_session_token":u=T;break}}}if(o===i&&c&&l)return{accessKeyId:c,secretAccessKey:l,sessionToken:u};return null}async function IA(n){let i=n?.timeout??1000,s="http://169.254.169.254";try{let o=await et("http://169.254.169.254/latest/api/token",{method:"PUT",headers:{"X-aws-ec2-metadata-token-ttl-seconds":"21600"}},i);if(!o.ok)return null;let c=await o.text(),l=await et("http://169.254.169.254/latest/meta-data/iam/security-credentials/",{headers:{"X-aws-ec2-metadata-token":c}},i);if(!l.ok)return null;let u=(await l.text()).trim(),h=await et(`http://169.254.169.254/latest/meta-data/iam/security-credentials/${u}`,{headers:{"X-aws-ec2-metadata-token":c}},i);if(!h.ok)return null;let y=await h.json();return{accessKeyId:y.AccessKeyId,secretAccessKey:y.SecretAccessKey,sessionToken:y.Token,expiration:new Date(y.Expiration)}}catch{return null}}async function SA(n){let i=n?.timeout??1000,s=process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI,o=process.env.AWS_CONTAINER_CREDENTIALS_FULL_URI,c=null;if(s)c=`http://169.254.170.2${s}`;else if(o)c=o;if(!c)return null;try{let l={},u=process.env.AWS_CONTAINER_AUTHORIZATION_TOKEN;if(u)l.Authorization=u;let h=await et(c,{headers:l},i);if(!h.ok)return null;let y=await h.json();return{accessKeyId:y.AccessKeyId,secretAccessKey:y.SecretAccessKey,sessionToken:y.Token,expiration:new Date(y.Expiration)}}catch{return null}}async function CA(n){let i=n?.timeout??5000,s=process.env.AWS_WEB_IDENTITY_TOKEN_FILE,o=process.env.AWS_ROLE_ARN,c=process.env.AWS_ROLE_SESSION_NAME||"ts-cloud-session";if(!s||!o)return null;try{let l=Qt(s,"utf-8").trim(),u=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION||"us-east-1",h=u.startsWith("us-gov")?`https://sts.${u}.amazonaws.com`:u==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${u}.amazonaws.com`,y=new URLSearchParams({Action:"AssumeRoleWithWebIdentity",Version:"2011-06-15",RoleArn:o,RoleSessionName:c,WebIdentityToken:l}),f=await et(`${h}/?${y.toString()}`,{method:"POST"},i);if(!f.ok)return null;let b=await f.text(),C=Ze(b,"AccessKeyId"),T=Ze(b,"SecretAccessKey"),w=Ze(b,"SessionToken"),E=Ze(b,"Expiration");if(!C||!T)return null;return{accessKeyId:C,secretAccessKey:T,sessionToken:w??void 0,expiration:E?new Date(E):void 0}}catch{return null}}async function ho(n){let i=AA();if(i)return i;let s=yA(n);if(s)return s;let o=await CA(n);if(o)return o;let c=await SA(n);if(c)return c;let l=await IA(n);if(l)return l;throw Error("Could not find AWS credentials. Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables, or configure ~/.aws/credentials, or run on an EC2 instance with an IAM role.")}function cS(n){let i=null,s=null;return async()=>{if(i){if(!i.expiration)return i;let o=300000;if(i.expiration.getTime()-Date.now()>o)return i}if(s)return s;return s=ho(n).then((o)=>(i=o,s=null,o)).catch((o)=>{throw s=null,o}),s}}async function et(n,i,s){let o=new AbortController,c=setTimeout(()=>o.abort(),s);try{let l=await fetch(n,{...i,signal:o.signal});return clearTimeout(c),l}catch(l){throw clearTimeout(c),l}}function Ze(n,i){let s=new RegExp(`<${i}>([^<]+)</${i}>`),o=n.match(s);return o?o[1]:null}async function EA(n){return ho({profile:n})}function bA(n){let i=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION;if(i)return i;let s=xa(Oa(),".aws","config");if(Ma(s))try{let o=Qt(s,"utf-8"),c=n||process.env.AWS_PROFILE||"default",l=c==="default"?"[default]":`[profile ${c}]`,u=o.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[,b]=f.split("=");if(b)return b.trim()}}}catch{}return"us-east-1"}async function vA(n){let i=n||await ho(),s=bA();await rt();let o=s.startsWith("us-gov")?`https://sts.${s}.amazonaws.com`:s==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${s}.amazonaws.com`,c="Action=GetCallerIdentity&Version=2011-06-15",l=O({method:"POST",url:o,body:"Action=GetCallerIdentity&Version=2011-06-15",headers:{"Content-Type":"application/x-www-form-urlencoded"},...i,service:"sts",region:s}),u=await fetch(l.url,{method:l.method,headers:l.headers,body:l.body});if(!u.ok)throw Error(`Failed to get account ID: ${await u.text()}`);let h=await u.text(),y=Ze(h,"Account");if(!y)throw Error("Failed to parse account ID from response");return y}await rt();await rt();var Rn=5242880,Dt=5242880,Nn=5242880;class Ba{region;endpoint;forcePathStyle;credentials;credentialOptions;retryOptions;constructor(n={}){this.region=n.region||process.env.AWS_REGION||"us-east-1",this.endpoint=n.endpoint||`https://s3.${this.region}.amazonaws.com`,this.forcePathStyle=n.forcePathStyle||!1,this.credentials=n.credentials,this.credentialOptions=n.credentialOptions,this.retryOptions=n.retryOptions||{}}async getCredentials(){if(this.credentials)return this.credentials;return ho(this.credentialOptions)}buildUrl(n,i){let s=i?encodeURIComponent(i).replace(/%2F/g,"/"):"";if(this.forcePathStyle)return i?`${this.endpoint}/${n}/${s}`:`${this.endpoint}/${n}`;let o=new URL(this.endpoint);return o.hostname=`${n}.${o.hostname}`,i?`${o.origin}/${s}`:o.origin}async get(n,i,s={}){let o=await this.getCredentials(),c=this.buildUrl(n,i),l={};if(s.range)l.Range=s.range;if(s.ifModifiedSince)l["If-Modified-Since"]=s.ifModifiedSince.toUTCString();if(s.ifMatch)l["If-Match"]=s.ifMatch;if(s.ifNoneMatch)l["If-None-Match"]=s.ifNoneMatch;let u=new URL(c);if(s.responseContentType)u.searchParams.set("response-content-type",s.responseContentType);if(s.responseContentDisposition)u.searchParams.set("response-content-disposition",s.responseContentDisposition);let h=O({method:"GET",url:u.toString(),headers:l,...o,service:"s3",region:this.region}),y=await fetch(h.url,{method:h.method,headers:h.headers});if(!y.ok&&y.status!==304){let f=await y.text();throw new V(`Failed to get object: ${f}`,y.status,n,i)}return y}async getText(n,i,s={}){return(await this.get(n,i,s)).text()}async getJSON(n,i,s={}){return(await this.get(n,i,s)).json()}async getBuffer(n,i,s={}){return(await this.get(n,i,s)).arrayBuffer()}async put(n,i,s,o={}){let c,l;if(typeof s==="string")c=new TextEncoder().encode(s).length,l=s;else if(s instanceof ArrayBuffer)c=s.byteLength,l=s;else if(s instanceof Uint8Array)c=s.byteLength,l=s;else if(s instanceof Blob)c=s.size,l=s;else return this.uploadMultipart(n,i,s,{...o,partSize:Dt});if(c>Nn){let u=$n(l).stream();return this.uploadMultipart(n,i,u,{...o,partSize:Dt})}return this.putSimple(n,i,l,c,o)}async putSimple(n,i,s,o,c){let l=await this.getCredentials(),u=this.buildUrl(n,i),h={"Content-Length":String(o),"Content-Type":c.contentType||ha(i)};if(c.contentEncoding)h["Content-Encoding"]=c.contentEncoding;if(c.cacheControl)h["Cache-Control"]=c.cacheControl;if(c.contentDisposition)h["Content-Disposition"]=c.contentDisposition;if(c.storageClass)h["x-amz-storage-class"]=c.storageClass;if(c.serverSideEncryption)h["x-amz-server-side-encryption"]=c.serverSideEncryption;if(c.acl)h["x-amz-acl"]=c.acl;if(c.tagging)h["x-amz-tagging"]=c.tagging;if(c.metadata)for(let[C,T]of Object.entries(c.metadata))h[`x-amz-meta-${C.toLowerCase()}`]=T;let y;if(typeof s==="string")y=s;else if(s instanceof Blob)y=await s.text();else y=new TextDecoder().decode(s instanceof ArrayBuffer?new Uint8Array(s):s);let f=O({method:"PUT",url:u,headers:h,body:y,...l,service:"s3",region:this.region}),b=await fetch(f.url,{method:f.method,headers:f.headers,body:s});if(!b.ok){let C=await b.text();throw new V(`Failed to put object: ${C}`,b.status,n,i)}return{etag:(b.headers.get("ETag")||"").replace(/"/g,"")}}async delete(n,i){let s=await this.getCredentials(),o=this.buildUrl(n,i),c=O({method:"DELETE",url:o,...s,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(!l.ok&&l.status!==204){let u=await l.text();throw new V(`Failed to delete object: ${u}`,l.status,n,i)}}async deleteMany(n,i){let s=await this.getCredentials(),o=`${this.buildUrl(n)}?delete`,c=`<?xml version="1.0" encoding="UTF-8"?><Delete><Quiet>false</Quiet>${i.map((w)=>`<Object><Key>${kn(w)}</Key></Object>`).join("")}</Delete>`,l=O({method:"POST",url:o,headers:{"Content-Type":"application/xml"},body:c,...s,service:"s3",region:this.region}),u=await fetch(l.url,{method:l.method,headers:l.headers,body:c});if(!u.ok){let w=await u.text();throw new V(`Failed to delete objects: ${w}`,u.status,n)}let h=await u.text(),y=[],f=[],b=/<Deleted><Key>([^<]+)<\/Key>/g,C;while((C=b.exec(h))!==null)y.push(C[1]);let T=/<Error><Key>([^<]+)<\/Key><Code>([^<]+)<\/Code><Message>([^<]+)<\/Message>/g;while((C=T.exec(h))!==null)f.push({key:C[1],error:`${C[2]}: ${C[3]}`});return{deleted:y,errors:f}}async list(n,i={}){let s=await this.getCredentials(),o=new URL(this.buildUrl(n));if(o.searchParams.set("list-type","2"),i.prefix)o.searchParams.set("prefix",i.prefix);if(i.delimiter)o.searchParams.set("delimiter",i.delimiter);if(i.maxKeys)o.searchParams.set("max-keys",String(i.maxKeys));if(i.continuationToken)o.searchParams.set("continuation-token",i.continuationToken);if(i.startAfter)o.searchParams.set("start-after",i.startAfter);let c=O({method:"GET",url:o.toString(),...s,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(!l.ok){let h=await l.text();throw new V(`Failed to list objects: ${h}`,l.status,n)}let u=await l.text();return Dn(u)}async*listAll(n,i={}){let s;do{let o=await this.list(n,{...i,continuationToken:s});for(let c of o.contents)yield c;s=o.nextContinuationToken}while(s)}async head(n,i){let s=await this.getCredentials(),o=this.buildUrl(n,i),c=O({method:"HEAD",url:o,...s,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(l.status===404)return null;if(!l.ok){let h=await l.text();throw new V(`Failed to head object: ${h}`,l.status,n,i)}let u={};return l.headers.forEach((h,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(n,i){return await this.head(n,i)!==null}async copy(n,i,s,o,c={}){let l=await this.getCredentials(),u=this.buildUrl(s,o),h={"x-amz-copy-source":`/${n}/${encodeURIComponent(i)}`};if(c.metadataDirective)h["x-amz-metadata-directive"]=c.metadataDirective;if(c.contentType)h["Content-Type"]=c.contentType;if(c.storageClass)h["x-amz-storage-class"]=c.storageClass;if(c.acl)h["x-amz-acl"]=c.acl;if(c.metadata)for(let[C,T]of Object.entries(c.metadata))h[`x-amz-meta-${C.toLowerCase()}`]=T;let y=O({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 C=await f.text();throw new V(`Failed to copy object: ${C}`,f.status,s,o)}let b=(await f.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:b?b[1]:""}}async getPresignedUrl(n,i,s={}){let o=await this.getCredentials(),c=this.buildUrl(n,i);return rA({url:c,method:s.method||"GET",expiresIn:s.expiresIn||3600,...o,service:"s3",region:this.region})}async uploadMultipart(n,i,s,o={}){let c=await this.getCredentials(),l=Math.max(o.partSize||Dt,Rn),u,h;if(s instanceof ReadableStream)u=s;else if(s instanceof Blob)u=s.stream(),h=s.size;else{let b=new Blob([s]);u=b.stream(),h=b.size}let{uploadId:y,baseUrl:f}=await this.initiateMultipartUpload(n,i,o);try{let b=await this.uploadParts(n,i,f,y,u,l,c,h,o.concurrency||4,o.onProgress);return await this.completeMultipartUpload(n,i,f,y,b)}catch(b){throw await this.abortMultipartUpload(n,i,y,f).catch(()=>{}),b}}async initiateMultipartUpload(n,i,s){let o=await this.getCredentials(),c=this.buildUrl(n,i),l=`${c}?uploads`,u={"Content-Type":s.contentType||ha(i)};if(s.storageClass)u["x-amz-storage-class"]=s.storageClass;if(s.serverSideEncryption)u["x-amz-server-side-encryption"]=s.serverSideEncryption;if(s.acl)u["x-amz-acl"]=s.acl;if(s.metadata)for(let[C,T]of Object.entries(s.metadata))u[`x-amz-meta-${C.toLowerCase()}`]=T;let h=O({method:"POST",url:l,headers:u,...o,service:"s3",region:this.region}),y=await fetch(h.url,{method:h.method,headers:h.headers});if(!y.ok){let C=await y.text();throw new V(`Failed to initiate multipart upload: ${C}`,y.status,n,i)}let f=(await y.text()).match(/<UploadId>([^<]+)<\/UploadId>/);if(!f)throw new V("Failed to parse upload ID from response",0,n,i);let b=c;if(y.url)try{let C=new URL(y.url);C.search="",b=C.toString()}catch{}return{uploadId:f[1],baseUrl:b}}async uploadParts(n,i,s,o,c,l,u,h,y,f){let b=[],C=c.getReader(),T=1,w=new Uint8Array(0),E=0,I=h?Math.ceil(h/l):void 0,N=new Map,D=async(R,_)=>{let B=`${s}?partNumber=${_}&uploadId=${encodeURIComponent(o)}`,W={"Content-Length":String(R.byteLength),"x-amz-content-sha256":"UNSIGNED-PAYLOAD"},J=O({method:"PUT",url:B,headers:W,...u,service:"s3",region:this.region}),K=await fetch(J.url,{method:J.method,headers:J.headers,body:R,redirect:"error"});if(!K.ok){let Z=await K.text();throw new V(`Failed to upload part ${_}: ${Z}`,K.status,n,i)}let Y=(K.headers.get("ETag")||"").replace(/"/g,"");if(!Y)throw new V(`Missing ETag for part ${_}`,K.status,n,i);return{partNumber:_,etag:Y}},x=async()=>{let R=await Promise.race(N.values());N.delete(R.partNumber),b.push(R)};while(!0){let{done:R,value:_}=await C.read();if(_){let B=new Uint8Array(w.length+_.length);B.set(w),B.set(_,w.length),w=B}while(w.length>=l||R&&w.length>0){let B=w.slice(0,l);w=w.slice(l);let W=T++;if(N.size>=y)await x();if(N.set(W,D(B,W)),E+=B.byteLength,f)f({loaded:E,total:h||E,part:W,totalParts:I||W})}if(R)break}while(N.size>0)await x();return b.sort((R,_)=>R.partNumber-_.partNumber),b}async completeMultipartUpload(n,i,s,o,c){let l=await this.getCredentials(),u=`${s}?uploadId=${encodeURIComponent(o)}`,h=`<?xml version="1.0" encoding="UTF-8"?><CompleteMultipartUpload>${c.map((C)=>`<Part><PartNumber>${C.partNumber}</PartNumber><ETag>"${C.etag}"</ETag></Part>`).join("")}</CompleteMultipartUpload>`,y=O({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 C=await f.text();throw new V(`Failed to complete multipart upload: ${C}`,f.status,n,i)}let b=(await f.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:b?b[1]:""}}async abortMultipartUpload(n,i,s,o){let c=await this.getCredentials(),l=`${o??this.buildUrl(n,i)}?uploadId=${encodeURIComponent(s)}`,u=O({method:"DELETE",url:l,...c,service:"s3",region:this.region});await fetch(u.url,{method:u.method,headers:u.headers})}async emptyAndDeleteBucket(n){let i=[];for await(let l of this.listAll(n,{}))if(i.push(l.key),i.length>=1000)await this.deleteMany(n,i),i=[];if(i.length>0)await this.deleteMany(n,i);let s=await this.getCredentials(),o=this.buildUrl(n),c=O({method:"DELETE",url:o,...s,service:"s3",region:this.region});await fetch(c.url,{method:c.method,headers:c.headers})}}class V extends Error{statusCode;bucket;key;constructor(n,i,s,o){super(n);this.statusCode=i,this.bucket=s,this.key=o,this.name="S3Error"}}function Dn(n){let i=[],s=[],o=/<Contents>([\s\S]*?)<\/Contents>/g,c;while((c=o.exec(n))!==null){let u=c[1];i.push({key:ce(u,"Key")||"",lastModified:new Date(ce(u,"LastModified")||0),etag:(ce(u,"ETag")||"").replace(/"/g,""),size:Number(ce(u,"Size")||0),storageClass:ce(u,"StorageClass")||"STANDARD"})}let l=/<CommonPrefixes><Prefix>([^<]+)<\/Prefix><\/CommonPrefixes>/g;while((c=l.exec(n))!==null)s.push(c[1]);return{contents:i,commonPrefixes:s,isTruncated:ce(n,"IsTruncated")==="true",continuationToken:ce(n,"ContinuationToken")||void 0,nextContinuationToken:ce(n,"NextContinuationToken")||void 0,keyCount:Number(ce(n,"KeyCount")||0),maxKeys:Number(ce(n,"MaxKeys")||1000),prefix:ce(n,"Prefix")||void 0,delimiter:ce(n,"Delimiter")||void 0}}function ce(n,i){let s=new RegExp(`<${i}>([^<]*)</${i}>`),o=n.match(s);return o?o[1]:null}function kn(n){return n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function ha(n){let i=n.split(".").pop()?.toLowerCase();return{html:"text/html",htm:"text/html",css:"text/css",js:"application/javascript",mjs:"application/javascript",json:"application/json",xml:"application/xml",txt:"text/plain",md:"text/markdown",csv:"text/csv",jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",gif:"image/gif",webp:"image/webp",svg:"image/svg+xml",ico:"image/x-icon",avif:"image/avif",mp4:"video/mp4",webm:"video/webm",mov:"video/quicktime",avi:"video/x-msvideo",mp3:"audio/mpeg",wav:"audio/wav",ogg:"audio/ogg",pdf:"application/pdf",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xls:"application/vnd.ms-excel",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",ppt:"application/vnd.ms-powerpoint",pptx:"application/vnd.openxmlformats-officedocument.presentationml.presentation",zip:"application/zip",gz:"application/gzip",tar:"application/x-tar",rar:"application/vnd.rar","7z":"application/x-7z-compressed",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf",otf:"font/otf",eot:"application/vnd.ms-fontobject",wasm:"application/wasm"}[i||""]||"application/octet-stream"}function $n(n){if(n instanceof Blob)return n;if(typeof n==="string")return new Blob([n],{type:"text/plain"});return new Blob([n])}function dS(n){return new Ba(n)}await rt();class We extends Error{code;solution;details;constructor(n,i,s,o){super(n);this.code=i,this.solution=s,this.details=o,this.name="CloudError",Error.captureStackTrace?.(this,We)}toString(){let n=`${this.name} [${this.code}]: ${this.message}`;if(this.solution)n+=`
2496
2496
 
2497
2497
  \uD83D\uDCA1 Solution: ${this.solution}`;if(this.details&&Object.keys(this.details).length>0){n+=`
2498
2498
 
2499
2499
  Details:`;for(let[i,s]of Object.entries(this.details))n+=`
2500
- ${i}: ${JSON.stringify(s)}`}return n}}class mo extends ze{constructor(n,i,s){super(n,"CONFIG_ERROR",i,s);this.name="ConfigurationError"}}class Kt extends ze{constructor(n,i,s){super(n,"CREDENTIAL_ERROR",i,s);this.name="CredentialError"}}class bA extends ze{constructor(n,i,s){super(n,"DEPLOYMENT_ERROR",i,s);this.name="DeploymentError"}}class vg extends ze{constructor(n,i,s){super(n,"VALIDATION_ERROR",i,s);this.name="ValidationError"}}class vA extends ze{statusCode;constructor(n,i,s,o){super(n,"AWS_API_ERROR",s,o);this.statusCode=i,this.name="AWSAPIError"}}var TA={NO_CREDENTIALS:{message:"AWS credentials not found",solution:`Configure AWS credentials using one of these methods:
2500
+ ${i}: ${JSON.stringify(s)}`}return n}}class fo extends We{constructor(n,i,s){super(n,"CONFIG_ERROR",i,s);this.name="ConfigurationError"}}class Wt extends We{constructor(n,i,s){super(n,"CREDENTIAL_ERROR",i,s);this.name="CredentialError"}}class TA extends We{constructor(n,i,s){super(n,"DEPLOYMENT_ERROR",i,s);this.name="DeploymentError"}}class wg extends We{constructor(n,i,s){super(n,"VALIDATION_ERROR",i,s);this.name="ValidationError"}}class wA extends We{statusCode;constructor(n,i,s,o){super(n,"AWS_API_ERROR",s,o);this.statusCode=i,this.name="AWSAPIError"}}var RA={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
- 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 wA(n){return TA[n]}function Tg(n,i){let s=wA(n);return new ze(s.message,n,s.solution,i)}class te{static verboseMode=!1;static debugMode=!1;static setVerbose(n){this.verboseMode=n}static setDebug(n){this.debugMode=n}static verbose(n,...i){if(this.verboseMode)console.log(`[VERBOSE] ${n}`,...i)}static debug(n,...i){if(this.debugMode)console.log(`[DEBUG] ${n}`,...i)}static info(n,...i){console.log(`ℹ ${n}`,...i)}static warn(n,...i){console.warn(`⚠ ${n}`,...i)}static error(n,i){if(console.error(`✖ ${n}`),i){if(i instanceof ze)console.error(i.toString());else console.error(i.message);if(this.debugMode&&i.stack)console.error(`
2505
- Stack trace:`),console.error(i.stack)}}static success(n){console.log(`✔ ${n}`)}}function cS(n){if(!n)throw Tg("MISSING_CONFIG");if(!n.project)throw new mo("Missing required field: project","Add a project configuration with name, slug, and region",{field:"project"});if(!n.project.name)throw new mo("Missing required field: project.name","Add a project name to your configuration",{field:"project.name"});if(!n.project.slug)throw new mo("Missing required field: project.slug","Add a project slug (lowercase, alphanumeric with hyphens)",{field:"project.slug"});if(!/^[a-z0-9-]+$/.test(n.project.slug))throw new vg("Invalid project slug format","Use only lowercase letters, numbers, and hyphens",{slug:n.project.slug});if(n.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(n.project.region))throw Tg("INVALID_REGION",{region:n.project.region})}te.success("Configuration validation passed")}function dS(n){let i=[];if(n.environments?.production&&n.infrastructure?.database){let s=n.infrastructure.database;if((s.postgres||s.mysql)&&!s.postgres?.multiAZ&&!s.mysql?.multiAZ)i.push("Production database should use Multi-AZ for high availability")}if(n.infrastructure?.storage){for(let[s,o]of Object.entries(n.infrastructure.storage))if(o.encryption===!1)i.push(`Storage "${s}" is not encrypted - consider enabling encryption for security`)}if(n.infrastructure?.storage){for(let[s,o]of Object.entries(n.infrastructure.storage))if(o.public===!0)i.push(`Storage "${s}" is publicly accessible - ensure this is intentional`)}if(n.infrastructure?.database){let s=n.infrastructure.database;if(s.postgres||s.mysql){let o=s.postgres?.backupRetentionDays||s.mysql?.backupRetentionDays;if(!o||o<7)i.push("Database backup retention is less than 7 days - consider increasing for production")}}if(!n.infrastructure?.monitoring)i.push("No monitoring configured - consider adding CloudWatch alarms");return i}async function lS(n="default"){try{te.verbose("Resolving AWS credentials...");let i=await SA(n);if(!i.accessKeyId||!i.secretAccessKey)throw new Kt("AWS credentials are incomplete","Ensure both AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are set");te.verbose("Credentials resolved successfully"),te.debug("Access Key ID:",i.accessKeyId.substring(0,8)+"..."),te.verbose("Testing credentials with GetCallerIdentity...");let s;try{s=await EA(i),te.verbose("Credentials are valid"),te.debug("Account ID:",s)}catch(o){if(o instanceof Error)if(o.message.includes("InvalidClientTokenId"))throw new Kt("Invalid AWS access key ID","Check that your AWS_ACCESS_KEY_ID is correct");else if(o.message.includes("SignatureDoesNotMatch"))throw new Kt("Invalid AWS secret access key","Check that your AWS_SECRET_ACCESS_KEY is correct");else if(o.message.includes("ExpiredToken"))throw new Kt("AWS credentials have expired","Refresh your temporary credentials or use long-term credentials");else throw new Kt(`Failed to validate credentials: ${o.message}`,"Verify your AWS credentials are correct and have the necessary permissions");throw o}return{valid:!0,accountId:s,region:i.region}}catch(i){if(i instanceof Kt)throw i;return{valid:!1,error:i instanceof Error?i.message:"Unknown error"}}}async function uS(n,i){return{allowed:i,denied:[]}}function RA(n){let i=new Set(["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate","cloudformation:ListStacks"]);if(n.infrastructure){if(n.infrastructure.storage)i.add("s3:CreateBucket"),i.add("s3:DeleteBucket"),i.add("s3:PutBucketPolicy"),i.add("s3:PutBucketVersioning"),i.add("s3:PutBucketEncryption"),i.add("s3:PutObject"),i.add("s3:GetObject");if(n.infrastructure.compute){if(n.infrastructure.compute.server)i.add("ec2:RunInstances"),i.add("ec2:TerminateInstances"),i.add("ec2:DescribeInstances"),i.add("autoscaling:CreateAutoScalingGroup"),i.add("autoscaling:UpdateAutoScalingGroup"),i.add("autoscaling:DeleteAutoScalingGroup"),i.add("elasticloadbalancing:CreateLoadBalancer"),i.add("elasticloadbalancing:DeleteLoadBalancer");if(n.infrastructure.compute.fargate)i.add("ecs:CreateCluster"),i.add("ecs:DeleteCluster"),i.add("ecs:CreateService"),i.add("ecs:UpdateService"),i.add("ecs:DeleteService"),i.add("ecs:RegisterTaskDefinition")}if(n.infrastructure.database){if(n.infrastructure.database.postgres||n.infrastructure.database.mysql)i.add("rds:CreateDBInstance"),i.add("rds:DeleteDBInstance"),i.add("rds:ModifyDBInstance"),i.add("rds:DescribeDBInstances");if(n.infrastructure.database.dynamodb)i.add("dynamodb:CreateTable"),i.add("dynamodb:DeleteTable"),i.add("dynamodb:UpdateTable"),i.add("dynamodb:DescribeTable")}if(n.infrastructure.functions)i.add("lambda:CreateFunction"),i.add("lambda:DeleteFunction"),i.add("lambda:UpdateFunctionCode"),i.add("lambda:UpdateFunctionConfiguration"),i.add("lambda:AddPermission");if(n.infrastructure.cdn)i.add("cloudfront:CreateDistribution"),i.add("cloudfront:UpdateDistribution"),i.add("cloudfront:DeleteDistribution"),i.add("cloudfront:GetDistribution");if(n.infrastructure.network)i.add("ec2:CreateVpc"),i.add("ec2:DeleteVpc"),i.add("ec2:CreateSubnet"),i.add("ec2:DeleteSubnet"),i.add("ec2:CreateInternetGateway"),i.add("ec2:DeleteInternetGateway"),i.add("ec2:CreateNatGateway"),i.add("ec2:DeleteNatGateway"),i.add("ec2:CreateRouteTable"),i.add("ec2:DeleteRouteTable"),i.add("ec2:CreateSecurityGroup"),i.add("ec2:DeleteSecurityGroup")}return i.add("iam:CreateRole"),i.add("iam:DeleteRole"),i.add("iam:AttachRolePolicy"),i.add("iam:DetachRolePolicy"),i.add("iam:PutRolePolicy"),i.add("iam:GetRole"),i.add("iam:PassRole"),Array.from(i).sort()}function pS(n){let i=RA(n);return JSON.stringify({Version:"2012-10-17",Statement:[{Effect:"Allow",Action:i,Resource:"*"}]},null,2)}var V={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 gS(n){let i=[];if(te.verbose("Checking AWS service quotas..."),n.infrastructure?.compute?.server){let o=n.infrastructure.compute.server.autoScaling?.max||1;i.push({service:"EC2",quotaName:"Running On-Demand Instances",currentValue:o,limit:V.ec2["Running On-Demand Instances"],percentage:o/V.ec2["Running On-Demand Instances"]*100,warning:o>V.ec2["Running On-Demand Instances"]*0.8})}if(n.infrastructure?.network?.vpc)i.push({service:"EC2",quotaName:"VPCs",currentValue:1,limit:V.ec2.VPCs,percentage:1/V.ec2.VPCs*100,warning:!1});if(n.infrastructure?.database?.postgres||n.infrastructure?.database?.mysql)i.push({service:"RDS",quotaName:"DB Instances",currentValue:1,limit:V.rds["DB Instances"],percentage:1/V.rds["DB Instances"]*100,warning:!1});if(n.infrastructure?.storage){let o=Object.keys(n.infrastructure.storage).length;i.push({service:"S3",quotaName:"Buckets",currentValue:o,limit:V.s3.Buckets,percentage:o/V.s3.Buckets*100,warning:o>V.s3.Buckets*0.8})}if(n.infrastructure?.functions){let o=0;for(let c of Object.values(n.infrastructure.functions))if(Array.isArray(c))o+=c.length;i.push({service:"Lambda",quotaName:"Functions (estimated)",currentValue:o,limit:1000,percentage:o/1000*100,warning:o>800})}if(n.infrastructure?.database?.dynamodb){let o=n.infrastructure.database.dynamodb.tables?.length||0;i.push({service:"DynamoDB",quotaName:"Tables",currentValue:o,limit:V.dynamodb.Tables,percentage:o/V.dynamodb.Tables*100,warning:o>V.dynamodb.Tables*0.8})}let s=i.filter((o)=>o.warning);if(s.length>0){te.warn("Service quota warnings detected:");for(let o of s)te.warn(` ${o.service} - ${o.quotaName}: ${o.currentValue}/${o.limit} (${o.percentage.toFixed(1)}%)`)}else te.verbose("All service quotas are within limits");return i}function mS(n){if(n.length===0)return"No quotas to check";let i=`Service Quota Usage:
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 DA(n){return RA[n]}function Rg(n,i){let s=DA(n);return new We(s.message,n,s.solution,i)}class re{static verboseMode=!1;static debugMode=!1;static setVerbose(n){this.verboseMode=n}static setDebug(n){this.debugMode=n}static verbose(n,...i){if(this.verboseMode)console.log(`[VERBOSE] ${n}`,...i)}static debug(n,...i){if(this.debugMode)console.log(`[DEBUG] ${n}`,...i)}static info(n,...i){console.log(`ℹ ${n}`,...i)}static warn(n,...i){console.warn(`⚠ ${n}`,...i)}static error(n,i){if(console.error(`✖ ${n}`),i){if(i instanceof We)console.error(i.toString());else console.error(i.message);if(this.debugMode&&i.stack)console.error(`
2505
+ Stack trace:`),console.error(i.stack)}}static success(n){console.log(`✔ ${n}`)}}function lS(n){if(!n)throw Rg("MISSING_CONFIG");if(!n.project)throw new fo("Missing required field: project","Add a project configuration with name, slug, and region",{field:"project"});if(!n.project.name)throw new fo("Missing required field: project.name","Add a project name to your configuration",{field:"project.name"});if(!n.project.slug)throw new fo("Missing required field: project.slug","Add a project slug (lowercase, alphanumeric with hyphens)",{field:"project.slug"});if(!/^[a-z0-9-]+$/.test(n.project.slug))throw new wg("Invalid project slug format","Use only lowercase letters, numbers, and hyphens",{slug:n.project.slug});if(n.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(n.project.region))throw Rg("INVALID_REGION",{region:n.project.region})}re.success("Configuration validation passed")}function uS(n){let i=[];if(n.environments?.production&&n.infrastructure?.database){let s=n.infrastructure.database;if((s.postgres||s.mysql)&&!s.postgres?.multiAZ&&!s.mysql?.multiAZ)i.push("Production database should use Multi-AZ for high availability")}if(n.infrastructure?.storage){for(let[s,o]of Object.entries(n.infrastructure.storage))if(o.encryption===!1)i.push(`Storage "${s}" is not encrypted - consider enabling encryption for security`)}if(n.infrastructure?.storage){for(let[s,o]of Object.entries(n.infrastructure.storage))if(o.public===!0)i.push(`Storage "${s}" is publicly accessible - ensure this is intentional`)}if(n.infrastructure?.database){let s=n.infrastructure.database;if(s.postgres||s.mysql){let o=s.postgres?.backupRetentionDays||s.mysql?.backupRetentionDays;if(!o||o<7)i.push("Database backup retention is less than 7 days - consider increasing for production")}}if(!n.infrastructure?.monitoring)i.push("No monitoring configured - consider adding CloudWatch alarms");return i}async function pS(n="default"){try{re.verbose("Resolving AWS credentials...");let i=await EA(n);if(!i.accessKeyId||!i.secretAccessKey)throw new Wt("AWS credentials are incomplete","Ensure both AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are set");re.verbose("Credentials resolved successfully"),re.debug("Access Key ID:",i.accessKeyId.substring(0,8)+"..."),re.verbose("Testing credentials with GetCallerIdentity...");let s;try{s=await vA(i),re.verbose("Credentials are valid"),re.debug("Account ID:",s)}catch(o){if(o instanceof Error)if(o.message.includes("InvalidClientTokenId"))throw new Wt("Invalid AWS access key ID","Check that your AWS_ACCESS_KEY_ID is correct");else if(o.message.includes("SignatureDoesNotMatch"))throw new Wt("Invalid AWS secret access key","Check that your AWS_SECRET_ACCESS_KEY is correct");else if(o.message.includes("ExpiredToken"))throw new Wt("AWS credentials have expired","Refresh your temporary credentials or use long-term credentials");else throw new Wt(`Failed to validate credentials: ${o.message}`,"Verify your AWS credentials are correct and have the necessary permissions");throw o}return{valid:!0,accountId:s,region:i.region}}catch(i){if(i instanceof Wt)throw i;return{valid:!1,error:i instanceof Error?i.message:"Unknown error"}}}async function gS(n,i){return{allowed:i,denied:[]}}function PA(n){let i=new Set(["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate","cloudformation:ListStacks"]);if(n.infrastructure){if(n.infrastructure.storage)i.add("s3:CreateBucket"),i.add("s3:DeleteBucket"),i.add("s3:PutBucketPolicy"),i.add("s3:PutBucketVersioning"),i.add("s3:PutBucketEncryption"),i.add("s3:PutObject"),i.add("s3:GetObject");if(n.infrastructure.compute){if(n.infrastructure.compute.server)i.add("ec2:RunInstances"),i.add("ec2:TerminateInstances"),i.add("ec2:DescribeInstances"),i.add("autoscaling:CreateAutoScalingGroup"),i.add("autoscaling:UpdateAutoScalingGroup"),i.add("autoscaling:DeleteAutoScalingGroup"),i.add("elasticloadbalancing:CreateLoadBalancer"),i.add("elasticloadbalancing:DeleteLoadBalancer");if(n.infrastructure.compute.fargate)i.add("ecs:CreateCluster"),i.add("ecs:DeleteCluster"),i.add("ecs:CreateService"),i.add("ecs:UpdateService"),i.add("ecs:DeleteService"),i.add("ecs:RegisterTaskDefinition")}if(n.infrastructure.database){if(n.infrastructure.database.postgres||n.infrastructure.database.mysql)i.add("rds:CreateDBInstance"),i.add("rds:DeleteDBInstance"),i.add("rds:ModifyDBInstance"),i.add("rds:DescribeDBInstances");if(n.infrastructure.database.dynamodb)i.add("dynamodb:CreateTable"),i.add("dynamodb:DeleteTable"),i.add("dynamodb:UpdateTable"),i.add("dynamodb:DescribeTable")}if(n.infrastructure.functions)i.add("lambda:CreateFunction"),i.add("lambda:DeleteFunction"),i.add("lambda:UpdateFunctionCode"),i.add("lambda:UpdateFunctionConfiguration"),i.add("lambda:AddPermission");if(n.infrastructure.cdn)i.add("cloudfront:CreateDistribution"),i.add("cloudfront:UpdateDistribution"),i.add("cloudfront:DeleteDistribution"),i.add("cloudfront:GetDistribution");if(n.infrastructure.network)i.add("ec2:CreateVpc"),i.add("ec2:DeleteVpc"),i.add("ec2:CreateSubnet"),i.add("ec2:DeleteSubnet"),i.add("ec2:CreateInternetGateway"),i.add("ec2:DeleteInternetGateway"),i.add("ec2:CreateNatGateway"),i.add("ec2:DeleteNatGateway"),i.add("ec2:CreateRouteTable"),i.add("ec2:DeleteRouteTable"),i.add("ec2:CreateSecurityGroup"),i.add("ec2:DeleteSecurityGroup")}return i.add("iam:CreateRole"),i.add("iam:DeleteRole"),i.add("iam:AttachRolePolicy"),i.add("iam:DetachRolePolicy"),i.add("iam:PutRolePolicy"),i.add("iam:GetRole"),i.add("iam:PassRole"),Array.from(i).sort()}function mS(n){let i=PA(n);return JSON.stringify({Version:"2012-10-17",Statement:[{Effect:"Allow",Action:i,Resource:"*"}]},null,2)}var j={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 hS(n){let i=[];if(re.verbose("Checking AWS service quotas..."),n.infrastructure?.compute?.server){let o=n.infrastructure.compute.server.autoScaling?.max||1;i.push({service:"EC2",quotaName:"Running On-Demand Instances",currentValue:o,limit:j.ec2["Running On-Demand Instances"],percentage:o/j.ec2["Running On-Demand Instances"]*100,warning:o>j.ec2["Running On-Demand Instances"]*0.8})}if(n.infrastructure?.network?.vpc)i.push({service:"EC2",quotaName:"VPCs",currentValue:1,limit:j.ec2.VPCs,percentage:1/j.ec2.VPCs*100,warning:!1});if(n.infrastructure?.database?.postgres||n.infrastructure?.database?.mysql)i.push({service:"RDS",quotaName:"DB Instances",currentValue:1,limit:j.rds["DB Instances"],percentage:1/j.rds["DB Instances"]*100,warning:!1});if(n.infrastructure?.storage){let o=Object.keys(n.infrastructure.storage).length;i.push({service:"S3",quotaName:"Buckets",currentValue:o,limit:j.s3.Buckets,percentage:o/j.s3.Buckets*100,warning:o>j.s3.Buckets*0.8})}if(n.infrastructure?.functions){let o=0;for(let c of Object.values(n.infrastructure.functions))if(Array.isArray(c))o+=c.length;i.push({service:"Lambda",quotaName:"Functions (estimated)",currentValue:o,limit:1000,percentage:o/1000*100,warning:o>800})}if(n.infrastructure?.database?.dynamodb){let o=n.infrastructure.database.dynamodb.tables?.length||0;i.push({service:"DynamoDB",quotaName:"Tables",currentValue:o,limit:j.dynamodb.Tables,percentage:o/j.dynamodb.Tables*100,warning:o>j.dynamodb.Tables*0.8})}let s=i.filter((o)=>o.warning);if(s.length>0){re.warn("Service quota warnings detected:");for(let o of s)re.warn(` ${o.service} - ${o.quotaName}: ${o.currentValue}/${o.limit} (${o.percentage.toFixed(1)}%)`)}else re.verbose("All service quotas are within limits");return i}function fS(n){if(n.length===0)return"No quotas to check";let i=`Service Quota Usage:
2506
2506
 
2507
2507
  `,s=n.reduce((o,c)=>{if(!o[c.service])o[c.service]=[];return o[c.service].push(c),o},{});for(let[o,c]of Object.entries(s)){i+=`${o}:
2508
2508
  `;for(let l of c){let u=l.warning?"⚠":"✓";i+=` ${u} ${l.quotaName}: ${l.currentValue}/${l.limit} (${l.percentage.toFixed(1)}%)
2509
2509
  `}i+=`
2510
- `}return i}function hS(n){let i=[];for(let s of n)if(s.percentage>=100)i.push(`Request quota increase for ${s.service} - ${s.quotaName} (currently ${s.limit})`);else if(s.warning)i.push(`Consider requesting quota increase for ${s.service} - ${s.quotaName} (${s.percentage.toFixed(1)}% used)`);return i}class wg{cacheDir;ttl;constructor(n,i={}){this.cacheDir=n,this.ttl=i.ttl||86400000}ensureCacheDir(){if(!lt(this.cacheDir))Ln(this.cacheDir,{recursive:!0})}getCachePath(n){let i=_a("sha256").update(n).digest("hex");return kt(this.cacheDir,`${i}.json`)}get(n){let i=this.getCachePath(n);if(!lt(i))return;try{let s=fa(i,"utf-8"),o=JSON.parse(s);if(Date.now()-o.timestamp>this.ttl){Ye(i);return}return o.value}catch{Ye(i);return}}set(n,i,s){this.ensureCacheDir();let o=this.getCachePath(n),c={value:i,timestamp:Date.now(),hash:s};Mn(o,JSON.stringify(c),"utf-8")}has(n){return this.get(n)!==void 0}clear(){if(!lt(this.cacheDir))return;let n=ya(this.cacheDir);for(let i of n)Ye(kt(this.cacheDir,i))}prune(){if(!lt(this.cacheDir))return;let n=ya(this.cacheDir),i=Date.now();for(let s of n){let o=kt(this.cacheDir,s);try{let c=fa(o,"utf-8"),l=JSON.parse(c);if(i-l.timestamp>this.ttl)Ye(o)}catch{Ye(o)}}}}class Rg{cache;constructor(n=O("cache","templates")){this.cache=new wg(n,{ttl:86400000})}getTemplate(n){return this.cache.get(`template:${n}`)}setTemplate(n,i){let s=this.hashTemplate(i);this.cache.set(`template:${n}`,i,s)}hasChanged(n,i){let s=this.cache.get(`template:${n}`);if(!s)return!0;let o=this.hashTemplate(s),c=this.hashTemplate(i);return o!==c}hashTemplate(n){return _a("sha256").update(n).digest("hex")}clear(){this.cache.clear()}prune(){this.cache.prune()}}var $t=null;function fS(){if(!$t)$t=new Rg;return $t}async function Dg(n,i={}){let s=i.algorithm||"sha256",o=i.chunkSize||65536;return new Promise((c,l)=>{let u=Yt(s),h=On(n,{highWaterMark:o});h.on("data",(y)=>u.update(y)),h.on("end",()=>c(u.digest("hex"))),h.on("error",l)})}function Pg(n,i="sha256"){return Yt(i).update(n).digest("hex")}function AS(n,i="sha256"){return Yt(i).update(n).digest("hex")}async function yS(n,i={}){let s=i.ignorePatterns||["node_modules",".git","dist","build",oo()],o=[];async function c(l){let u=xn(l,{withFileTypes:!0});for(let h of u){let y=Bn(l,h.name),f=_n(n,y);if(s.some((b)=>f.includes(b)))continue;if(h.isDirectory())await c(y);else if(h.isFile()){let b=bt(y),C=await Dg(y,i);o.push({path:f,hash:C,size:b.size,mtime:b.mtimeMs})}}}return await c(n),o}function IS(n){let i=[...n].sort((s,o)=>s.path.localeCompare(o.path)).map((s)=>`${s.path}:${s.hash}`).join(`
2511
- `);return Pg(i)}function SS(n){let i=bt(n);return Pg(`${n}:${i.size}:${i.mtimeMs}`)}function CS(n,i){let s=new Map(n.map((h)=>[h.path,h])),o=new Map(i.map((h)=>[h.path,h])),c=[],l=[],u=[];for(let[h,y]of o){let f=s.get(h);if(!f)c.push(y);else if(f.hash!==y.hash)l.push(y)}for(let[h,y]of s)if(!o.has(h))u.push(y);return{added:c,modified:l,deleted:u}}class DA{cache;constructor(){this.cache=new Map}get(n){let i=bt(n),s=this.cache.get(n);if(s&&s.mtime===i.mtimeMs&&s.size===i.size)return s.hash;return}set(n,i){let s=bt(n);this.cache.set(n,{hash:i,mtime:s.mtimeMs,size:s.size})}async getOrCompute(n,i={}){let s=this.get(n);if(s)return s;let o=await Dg(n,i);return this.set(n,o),o}clear(){this.cache.clear()}}async function Od(n,i={}){let s=i.concurrency||5,o=i.stopOnError??!0,c=[],l=[],u=Date.now(),h=[...n],y=[];async function f(T,w){try{let E=await T();c[w]=E}catch(E){let I=E instanceof Error?E:Error(String(E));if(l.push(I),o)throw h.length=0,I}}let b=0;while(h.length>0||y.length>0){while(y.length<s&&h.length>0){let T=h.shift(),w=b++,E=f(T,w);y.push(E)}if(y.length>0){await Promise.race(y);for(let T=y.length-1;T>=0;T--)if(await Promise.race([y[T].then(()=>!0),Promise.resolve(!1)]))y.splice(T,1)}if(o&&l.length>0)break}let C=Date.now()-u;return{results:c.filter((T)=>T!==void 0),errors:l,duration:C}}async function ES(n,i,s={}){let o=n.map((c)=>()=>i(c));return Od(o,s)}async function bS(n,i,s=5){let o=n.map((l,u)=>()=>i(l,u)),c=await Od(o,{concurrency:s,stopOnError:!1});if(c.errors.length>0)throw AggregateError(c.errors,"Parallel map failed");return c.results}async function vS(n,i={}){let s=i.retries||3,o=i.retryDelay||1000,c=n.map((l)=>async()=>{let u;for(let h=0;h<=s;h++)try{return await l()}catch(y){if(u=y instanceof Error?y:Error(String(y)),h<s)await Wa(o*(h+1))}throw u});return Od(c,i)}async function TS(n){let i=[];for(let s of n){let o=await s();i.push(o)}return i}function Wa(n){return new Promise((i)=>setTimeout(i,n))}async function wS(n,i,s="Operation timed out"){return Promise.race([n(),new Promise((o,c)=>setTimeout(()=>c(Error(s)),i))])}class PA{maxConcurrent;minInterval;queue=[];running=0;lastExecution=0;constructor(n=5,i=100){this.maxConcurrent=n,this.minInterval=i}async execute(n){await this.waitForSlot(),this.running++,this.lastExecution=Date.now();try{return await n()}finally{this.running--,this.processQueue()}}waitForSlot(){if(this.running<this.maxConcurrent){let n=Date.now()-this.lastExecution;if(n>=this.minInterval)return Promise.resolve();return Wa(this.minInterval-n)}return new Promise((n)=>this.queue.push(n))}processQueue(){if(this.queue.length>0&&this.running<this.maxConcurrent)this.queue.shift()()}stats(){return{running:this.running,queued:this.queue.length}}}function NA(n,i){let s=[];for(let o=0;o<n.length;o+=i)s.push(n.slice(o,o+i));return s}async function RS(n,i,s){let o=NA(n,i),c=[];for(let l of o){let u=await s(l);c.push(...u)}return c}function DS(n,i){let s=[],o=[],c=[],l=[],u=n.Resources||{},h=i.Resources||{},y=new Set(Object.keys(u)),f=new Set(Object.keys(h));for(let T of f)if(!y.has(T))s.push(T);for(let T of y)if(!f.has(T))c.push(T);for(let T of f)if(y.has(T)){let w=u[T],E=h[T];if(JSON.stringify(w)!==JSON.stringify(E))o.push(T);else l.push(T)}let b=JSON.stringify(n.Parameters||{})!==JSON.stringify(i.Parameters||{}),C=JSON.stringify(n.Outputs||{})!==JSON.stringify(i.Outputs||{});return{added:s,modified:o,deleted:c,unchanged:l,parametersChanged:b,outputsChanged:C,hasChanges:s.length>0||o.length>0||c.length>0||b||C}}function PS(n){let i=[];if(!n.hasChanges)return"No changes detected";if(n.added.length>0){i.push(`Added resources (${n.added.length}):`);for(let s of n.added)i.push(` + ${s}`)}if(n.modified.length>0){i.push(`Modified resources (${n.modified.length}):`);for(let s of n.modified)i.push(` ~ ${s}`)}if(n.deleted.length>0){i.push(`Deleted resources (${n.deleted.length}):`);for(let s of n.deleted)i.push(` - ${s}`)}if(n.parametersChanged)i.push("Parameters changed");if(n.outputsChanged)i.push("Outputs changed");return i.join(`
2512
- `)}function NS(n,i,s){if(n.deleted.length>0)return!0;for(let o of n.modified){let c=i.Resources[o],l=s.Resources[o];if(c.Type!==l.Type)return!0;let u=Wn(l.Type);for(let h of u){let y=c.Properties?.[h],f=l.Properties?.[h];if(JSON.stringify(y)!==JSON.stringify(f))return!0}}return!1}function Wn(n){return{"AWS::S3::Bucket":["BucketName"],"AWS::EC2::Instance":["ImageId","InstanceType","KeyName"],"AWS::RDS::DBInstance":["DBInstanceIdentifier","Engine"],"AWS::DynamoDB::Table":["TableName","KeySchema"],"AWS::Lambda::Function":["FunctionName"],"AWS::ECS::Service":["ServiceName"],"AWS::ElasticLoadBalancingV2::LoadBalancer":["Name","Type"]}[n]||[]}function kS(n){let i=[],s=[],o=[];i.push(...n.added);for(let c of n.modified)s.push(c);return o.push(...n.deleted),{safe:i,caution:s,dangerous:o}}function BS(n){if(!n.hasChanges)return{strategy:"skip",reason:"No changes detected"};if(n.deleted.length>0)return{strategy:"replace",reason:"Resources will be deleted"};if(n.added.length>0&&n.modified.length===0)return{strategy:"update",reason:"Only new resources added"};return{strategy:"update",reason:"Resources will be updated"}}function _S(n){let i=n.added.length+n.modified.length+n.deleted.length+n.unchanged.length,s=n.added.length+n.modified.length+n.deleted.length,o=i>0?s/i*100:0;return{total:i,added:n.added.length,modified:n.modified.length,deleted:n.deleted.length,unchanged:n.unchanged.length,changePercentage:o}}var xS={$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 OS(n){let i=[];if(!n.project)i.push("Missing required field: project");else{if(!n.project.name)i.push("Missing required field: project.name");if(!n.project.slug)i.push("Missing required field: project.slug")}if(n.project?.slug&&!/^[a-z0-9-]+$/.test(n.project.slug))i.push("Invalid project.slug: must contain only lowercase letters, numbers, and hyphens");let s=["us-east-1","us-east-2","us-west-1","us-west-2","eu-west-1","eu-west-2","eu-west-3","eu-central-1","ap-southeast-1","ap-southeast-2","ap-northeast-1","ap-northeast-2","sa-east-1","ca-central-1"];if(n.project?.region&&!s.includes(n.project.region))i.push(`Invalid region: ${n.project.region}. Must be one of: ${s.join(", ")}`);if(n.mode&&!["server","serverless"].includes(n.mode))i.push("Invalid mode: must be one of server or serverless");return{valid:i.length===0,errors:i}}var Ng={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 Ld(){return Ng}function LS(){return Ng.enabled}function $S(n){let i=Ld();if(!i.enabled)return"";switch(n.toLowerCase()){case"dynamodb":return i.dynamodbEndpoint;case"s3":return i.s3Endpoint;case"localstack":case"cloudformation":case"lambda":case"apigateway":case"sns":case"sqs":case"cloudwatch":case"iam":case"sts":return i.localstackEndpoint;default:return i.localstackEndpoint}}function MS(){let n=Ld();return{accessKeyId:n.awsAccessKeyId,secretAccessKey:n.awsSecretAccessKey,region:n.awsRegion}}function FS(){let n=Ld();if(!n.enabled)return{};return{AWS_ACCESS_KEY_ID:n.awsAccessKeyId,AWS_SECRET_ACCESS_KEY:n.awsSecretAccessKey,AWS_REGION:n.awsRegion,AWS_ENDPOINT_URL:n.localstackEndpoint,LOCALSTACK_ENDPOINT:n.localstackEndpoint,TS_CLOUD_LOCAL:"true"}}class kg{stacks=new Map;stackEvents=new Map;async createStack(n){let i=`arn:aws:cloudformation:${n.region||"us-east-1"}:123456789012:stack/${n.StackName}/${Date.now()}`;return this.stacks.set(n.StackName,{StackId:i,StackName:n.StackName,StackStatus:"CREATE_IN_PROGRESS",CreationTime:new Date().toISOString(),TemplateBody:n.TemplateBody,Parameters:n.Parameters||[]}),this.addEvent(n.StackName,{EventId:Date.now().toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_IN_PROGRESS"}),setTimeout(()=>{let s=this.stacks.get(n.StackName);if(s)s.StackStatus="CREATE_COMPLETE",this.addEvent(n.StackName,{EventId:(Date.now()+1).toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_COMPLETE"})},100),{StackId:i}}async updateStack(n){let i=this.stacks.get(n.StackName);if(!i)throw Error(`Stack ${n.StackName} does not exist`);return i.StackStatus="UPDATE_IN_PROGRESS",i.TemplateBody=n.TemplateBody||i.TemplateBody,this.addEvent(n.StackName,{EventId:Date.now().toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_IN_PROGRESS"}),setTimeout(()=>{i.StackStatus="UPDATE_COMPLETE",this.addEvent(n.StackName,{EventId:(Date.now()+1).toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_COMPLETE"})},100),{StackId:i.StackId}}async deleteStack(n){let i=this.stacks.get(n.StackName);if(!i)throw Error(`Stack ${n.StackName} does not exist`);i.StackStatus="DELETE_IN_PROGRESS",this.addEvent(n.StackName,{EventId:Date.now().toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_IN_PROGRESS"}),setTimeout(()=>{this.stacks.delete(n.StackName),this.addEvent(n.StackName,{EventId:(Date.now()+1).toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_COMPLETE"})},100)}async describeStacks(n){if(n.StackName){let i=this.stacks.get(n.StackName);if(!i)throw Error(`Stack ${n.StackName} does not exist`);return{Stacks:[i]}}return{Stacks:Array.from(this.stacks.values())}}async describeStackEvents(n){return{StackEvents:this.stackEvents.get(n.StackName)||[]}}addEvent(n,i){if(!this.stackEvents.has(n))this.stackEvents.set(n,[]);this.stackEvents.get(n).unshift(i)}reset(){this.stacks.clear(),this.stackEvents.clear()}}class Bg{buckets=new Map;async createBucket(n){return this.buckets.set(n.Bucket,new Map),{Location:`/${n.Bucket}`}}async deleteBucket(n){this.buckets.delete(n.Bucket)}async putObject(n){let i=this.buckets.get(n.Bucket);if(!i)i=new Map,this.buckets.set(n.Bucket,i);return i.set(n.Key,Buffer.from(n.Body||"")),{ETag:`"${Date.now()}"`}}async getObject(n){let i=this.buckets.get(n.Bucket);if(!i)throw Error(`Bucket ${n.Bucket} does not exist`);let s=i.get(n.Key);if(!s)throw Error(`Object ${n.Key} does not exist`);return{Body:s,ContentLength:s.length}}async deleteObject(n){let i=this.buckets.get(n.Bucket);if(i)i.delete(n.Key)}async listObjects(n){let i=this.buckets.get(n.Bucket);if(!i)throw Error(`Bucket ${n.Bucket} does not exist`);return{Contents:Array.from(i.keys()).map((s)=>({Key:s,Size:i.get(s).length,LastModified:new Date().toISOString()}))}}reset(){this.buckets.clear()}}class _g{tables=new Map;data=new Map;async createTable(n){return this.tables.set(n.TableName,{TableName:n.TableName,KeySchema:n.KeySchema,AttributeDefinitions:n.AttributeDefinitions,TableStatus:"ACTIVE",CreationDateTime:new Date().toISOString()}),this.data.set(n.TableName,new Map),{TableDescription:this.tables.get(n.TableName)}}async deleteTable(n){this.tables.delete(n.TableName),this.data.delete(n.TableName)}async putItem(n){let i=this.data.get(n.TableName);if(!i)i=new Map,this.data.set(n.TableName,i);let s=JSON.stringify(n.Item);i.set(s,n.Item)}async getItem(n){let i=this.data.get(n.TableName);if(!i)return{};let s=JSON.stringify(n.Key),o=i.get(s);return o?{Item:o}:{}}async deleteItem(n){let i=this.data.get(n.TableName);if(i){let s=JSON.stringify(n.Key);i.delete(s)}}async scan(n){let i=this.data.get(n.TableName);if(!i)return{Items:[]};return{Items:Array.from(i.values())}}reset(){this.tables.clear(),this.data.clear()}}function US(n){return{cloudformation:new kg,s3:new Bg,dynamodb:new _g}}class xg{environments=new Map;async createPreviewEnvironment(n){let{branch:i,pr:s,commitSha:o,ttl:c=24,baseConfig:l,region:u="us-east-1"}=n,h=this.generatePreviewId(i,s,o),y=this.generatePreviewName(i,s),f=`preview-${y}`,b=new Date,C=new Date(b.getTime()+c*60*60*1000),T={id:h,name:y,branch:i,pr:s,commitSha:o,createdAt:b,expiresAt:C,status:"creating",stackName:f,region:u,resources:[]};this.environments.set(h,T);try{let w=this.createPreviewConfig(l,y);return T.status="active",T.url=`https://${y}.preview.example.com`,T}catch(w){throw T.status="failed",w}}async destroyPreviewEnvironment(n){let i=this.environments.get(n);if(!i)throw Error(`Preview environment ${n} not found`);i.status="destroying";try{i.status="destroyed",this.environments.delete(n)}catch(s){throw Error(`Failed to destroy preview environment: ${s}`)}}getPreviewEnvironment(n){return this.environments.get(n)}getPreviewEnvironmentByBranch(n){return Array.from(this.environments.values()).find((i)=>i.branch===n)}getPreviewEnvironmentByPR(n){return Array.from(this.environments.values()).find((i)=>i.pr===n)}listPreviewEnvironments(){return Array.from(this.environments.values())}listActivePreviewEnvironments(){return this.listPreviewEnvironments().filter((n)=>n.status==="active")}async cleanupExpiredEnvironments(n={}){let{maxAge:i,keepCount:s,dryRun:o=!1}=n,c=[],l=[],u=new Date,h=this.listPreviewEnvironments().sort((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 b=!1;if(f.expiresAt<u)b=!0;if(i){if((u.getTime()-f.createdAt.getTime())/3600000>i)b=!0}if(s&&y>=s)b=!0;if(b)if(o)c.push(f.id);else try{await this.destroyPreviewEnvironment(f.id),c.push(f.id)}catch(C){l.push(f.id)}}return{destroyed:c,failed:l}}async updatePreviewEnvironment(n,i){let s=this.environments.get(n);if(!s)throw Error(`Preview environment ${n} not found`);s.commitSha=i,s.status="creating";try{return s.status="active",s}catch(o){throw s.status="failed",o}}async getPreviewEnvironmentsCost(){let n={},i=0;for(let s of this.environments.values())n[s.id]=0,i+=0;return{total:i,byEnvironment:n}}generatePreviewId(n,i,s){let o=n.replace(/[^a-z0-9-]/gi,"-").toLowerCase(),c=s?.substring(0,7)||Date.now().toString();return i?`pr-${i}-${c}`:`${o}-${c}`}generatePreviewName(n,i){let s=n.replace(/[^a-z0-9-]/gi,"-").toLowerCase();return i?`pr-${i}`:s}createPreviewConfig(n,i){return{...n,project:{...n.project,name:`${n.project.name} Preview (${i})`,slug:`${n.project.slug}-preview-${i}`}}}}var QS=new xg;function HS(n={}){let{workflowName:i="Preview Environment",trigger:s="pull_request",branches:o=["main","develop"],awsRegion:c="us-east-1",awsRole:l,configFile:u="cloud.config.ts",ttl:h=24}=n;return`name: ${i}
2510
+ `}return i}function AS(n){let i=[];for(let s of n)if(s.percentage>=100)i.push(`Request quota increase for ${s.service} - ${s.quotaName} (currently ${s.limit})`);else if(s.warning)i.push(`Consider requesting quota increase for ${s.service} - ${s.quotaName} (${s.percentage.toFixed(1)}% used)`);return i}class Dg{cacheDir;ttl;constructor(n,i={}){this.cacheDir=n,this.ttl=i.ttl||86400000}ensureCacheDir(){if(!lt(this.cacheDir))Ln(this.cacheDir,{recursive:!0})}getCachePath(n){let i=_a("sha256").update(n).digest("hex");return kt(this.cacheDir,`${i}.json`)}get(n){let i=this.getCachePath(n);if(!lt(i))return;try{let s=fa(i,"utf-8"),o=JSON.parse(s);if(Date.now()-o.timestamp>this.ttl){Ye(i);return}return o.value}catch{Ye(i);return}}set(n,i,s){this.ensureCacheDir();let o=this.getCachePath(n),c={value:i,timestamp:Date.now(),hash:s};Mn(o,JSON.stringify(c),"utf-8")}has(n){return this.get(n)!==void 0}clear(){if(!lt(this.cacheDir))return;let n=ya(this.cacheDir);for(let i of n)Ye(kt(this.cacheDir,i))}prune(){if(!lt(this.cacheDir))return;let n=ya(this.cacheDir),i=Date.now();for(let s of n){let o=kt(this.cacheDir,s);try{let c=fa(o,"utf-8"),l=JSON.parse(c);if(i-l.timestamp>this.ttl)Ye(o)}catch{Ye(o)}}}}class Pg{cache;constructor(n=L("cache","templates")){this.cache=new Dg(n,{ttl:86400000})}getTemplate(n){return this.cache.get(`template:${n}`)}setTemplate(n,i){let s=this.hashTemplate(i);this.cache.set(`template:${n}`,i,s)}hasChanged(n,i){let s=this.cache.get(`template:${n}`);if(!s)return!0;let o=this.hashTemplate(s),c=this.hashTemplate(i);return o!==c}hashTemplate(n){return _a("sha256").update(n).digest("hex")}clear(){this.cache.clear()}prune(){this.cache.prune()}}var $t=null;function yS(){if(!$t)$t=new Pg;return $t}async function Ng(n,i={}){let s=i.algorithm||"sha256",o=i.chunkSize||65536;return new Promise((c,l)=>{let u=Yt(s),h=On(n,{highWaterMark:o});h.on("data",(y)=>u.update(y)),h.on("end",()=>c(u.digest("hex"))),h.on("error",l)})}function kg(n,i="sha256"){return Yt(i).update(n).digest("hex")}function IS(n,i="sha256"){return Yt(i).update(n).digest("hex")}async function SS(n,i={}){let s=i.ignorePatterns||["node_modules",".git","dist","build",co()],o=[];async function c(l){let u=xn(l,{withFileTypes:!0});for(let h of u){let y=Bn(l,h.name),f=_n(n,y);if(s.some((b)=>f.includes(b)))continue;if(h.isDirectory())await c(y);else if(h.isFile()){let b=St(y),C=await Ng(y,i);o.push({path:f,hash:C,size:b.size,mtime:b.mtimeMs})}}}return await c(n),o}function CS(n){let i=[...n].sort((s,o)=>s.path.localeCompare(o.path)).map((s)=>`${s.path}:${s.hash}`).join(`
2511
+ `);return kg(i)}function ES(n){let i=St(n);return kg(`${n}:${i.size}:${i.mtimeMs}`)}function bS(n,i){let s=new Map(n.map((h)=>[h.path,h])),o=new Map(i.map((h)=>[h.path,h])),c=[],l=[],u=[];for(let[h,y]of o){let f=s.get(h);if(!f)c.push(y);else if(f.hash!==y.hash)l.push(y)}for(let[h,y]of s)if(!o.has(h))u.push(y);return{added:c,modified:l,deleted:u}}class NA{cache;constructor(){this.cache=new Map}get(n){let i=St(n),s=this.cache.get(n);if(s&&s.mtime===i.mtimeMs&&s.size===i.size)return s.hash;return}set(n,i){let s=St(n);this.cache.set(n,{hash:i,mtime:s.mtimeMs,size:s.size})}async getOrCompute(n,i={}){let s=this.get(n);if(s)return s;let o=await Ng(n,i);return this.set(n,o),o}clear(){this.cache.clear()}}async function $d(n,i={}){let s=i.concurrency||5,o=i.stopOnError??!0,c=[],l=[],u=Date.now(),h=[...n],y=[];async function f(T,w){try{let E=await T();c[w]=E}catch(E){let I=E instanceof Error?E:Error(String(E));if(l.push(I),o)throw h.length=0,I}}let b=0;while(h.length>0||y.length>0){while(y.length<s&&h.length>0){let T=h.shift(),w=b++,E=f(T,w);y.push(E)}if(y.length>0){await Promise.race(y);for(let T=y.length-1;T>=0;T--)if(await Promise.race([y[T].then(()=>!0),Promise.resolve(!1)]))y.splice(T,1)}if(o&&l.length>0)break}let C=Date.now()-u;return{results:c.filter((T)=>T!==void 0),errors:l,duration:C}}async function vS(n,i,s={}){let o=n.map((c)=>()=>i(c));return $d(o,s)}async function TS(n,i,s=5){let o=n.map((l,u)=>()=>i(l,u)),c=await $d(o,{concurrency:s,stopOnError:!1});if(c.errors.length>0)throw AggregateError(c.errors,"Parallel map failed");return c.results}async function wS(n,i={}){let s=i.retries||3,o=i.retryDelay||1000,c=n.map((l)=>async()=>{let u;for(let h=0;h<=s;h++)try{return await l()}catch(y){if(u=y instanceof Error?y:Error(String(y)),h<s)await Wa(o*(h+1))}throw u});return $d(c,i)}async function RS(n){let i=[];for(let s of n){let o=await s();i.push(o)}return i}function Wa(n){return new Promise((i)=>setTimeout(i,n))}async function DS(n,i,s="Operation timed out"){return Promise.race([n(),new Promise((o,c)=>setTimeout(()=>c(Error(s)),i))])}class kA{maxConcurrent;minInterval;queue=[];running=0;lastExecution=0;constructor(n=5,i=100){this.maxConcurrent=n,this.minInterval=i}async execute(n){await this.waitForSlot(),this.running++,this.lastExecution=Date.now();try{return await n()}finally{this.running--,this.processQueue()}}waitForSlot(){if(this.running<this.maxConcurrent){let n=Date.now()-this.lastExecution;if(n>=this.minInterval)return Promise.resolve();return Wa(this.minInterval-n)}return new Promise((n)=>this.queue.push(n))}processQueue(){if(this.queue.length>0&&this.running<this.maxConcurrent)this.queue.shift()()}stats(){return{running:this.running,queued:this.queue.length}}}function BA(n,i){let s=[];for(let o=0;o<n.length;o+=i)s.push(n.slice(o,o+i));return s}async function PS(n,i,s){let o=BA(n,i),c=[];for(let l of o){let u=await s(l);c.push(...u)}return c}function NS(n,i){let s=[],o=[],c=[],l=[],u=n.Resources||{},h=i.Resources||{},y=new Set(Object.keys(u)),f=new Set(Object.keys(h));for(let T of f)if(!y.has(T))s.push(T);for(let T of y)if(!f.has(T))c.push(T);for(let T of f)if(y.has(T)){let w=u[T],E=h[T];if(JSON.stringify(w)!==JSON.stringify(E))o.push(T);else l.push(T)}let b=JSON.stringify(n.Parameters||{})!==JSON.stringify(i.Parameters||{}),C=JSON.stringify(n.Outputs||{})!==JSON.stringify(i.Outputs||{});return{added:s,modified:o,deleted:c,unchanged:l,parametersChanged:b,outputsChanged:C,hasChanges:s.length>0||o.length>0||c.length>0||b||C}}function kS(n){let i=[];if(!n.hasChanges)return"No changes detected";if(n.added.length>0){i.push(`Added resources (${n.added.length}):`);for(let s of n.added)i.push(` + ${s}`)}if(n.modified.length>0){i.push(`Modified resources (${n.modified.length}):`);for(let s of n.modified)i.push(` ~ ${s}`)}if(n.deleted.length>0){i.push(`Deleted resources (${n.deleted.length}):`);for(let s of n.deleted)i.push(` - ${s}`)}if(n.parametersChanged)i.push("Parameters changed");if(n.outputsChanged)i.push("Outputs changed");return i.join(`
2512
+ `)}function BS(n,i,s){if(n.deleted.length>0)return!0;for(let o of n.modified){let c=i.Resources[o],l=s.Resources[o];if(c.Type!==l.Type)return!0;let u=Wn(l.Type);for(let h of u){let y=c.Properties?.[h],f=l.Properties?.[h];if(JSON.stringify(y)!==JSON.stringify(f))return!0}}return!1}function Wn(n){return{"AWS::S3::Bucket":["BucketName"],"AWS::EC2::Instance":["ImageId","InstanceType","KeyName"],"AWS::RDS::DBInstance":["DBInstanceIdentifier","Engine"],"AWS::DynamoDB::Table":["TableName","KeySchema"],"AWS::Lambda::Function":["FunctionName"],"AWS::ECS::Service":["ServiceName"],"AWS::ElasticLoadBalancingV2::LoadBalancer":["Name","Type"]}[n]||[]}function _S(n){let i=[],s=[],o=[];i.push(...n.added);for(let c of n.modified)s.push(c);return o.push(...n.deleted),{safe:i,caution:s,dangerous:o}}function xS(n){if(!n.hasChanges)return{strategy:"skip",reason:"No changes detected"};if(n.deleted.length>0)return{strategy:"replace",reason:"Resources will be deleted"};if(n.added.length>0&&n.modified.length===0)return{strategy:"update",reason:"Only new resources added"};return{strategy:"update",reason:"Resources will be updated"}}function OS(n){let i=n.added.length+n.modified.length+n.deleted.length+n.unchanged.length,s=n.added.length+n.modified.length+n.deleted.length,o=i>0?s/i*100:0;return{total:i,added:n.added.length,modified:n.modified.length,deleted:n.deleted.length,unchanged:n.unchanged.length,changePercentage:o}}var LS={$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 $S(n){let i=[];if(!n.project)i.push("Missing required field: project");else{if(!n.project.name)i.push("Missing required field: project.name");if(!n.project.slug)i.push("Missing required field: project.slug")}if(n.project?.slug&&!/^[a-z0-9-]+$/.test(n.project.slug))i.push("Invalid project.slug: must contain only lowercase letters, numbers, and hyphens");let s=["us-east-1","us-east-2","us-west-1","us-west-2","eu-west-1","eu-west-2","eu-west-3","eu-central-1","ap-southeast-1","ap-southeast-2","ap-northeast-1","ap-northeast-2","sa-east-1","ca-central-1"];if(n.project?.region&&!s.includes(n.project.region))i.push(`Invalid region: ${n.project.region}. Must be one of: ${s.join(", ")}`);if(n.mode&&!["server","serverless"].includes(n.mode))i.push("Invalid mode: must be one of server or serverless");return{valid:i.length===0,errors:i}}var Bg={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 Md(){return Bg}function MS(){return Bg.enabled}function FS(n){let i=Md();if(!i.enabled)return"";switch(n.toLowerCase()){case"dynamodb":return i.dynamodbEndpoint;case"s3":return i.s3Endpoint;case"localstack":case"cloudformation":case"lambda":case"apigateway":case"sns":case"sqs":case"cloudwatch":case"iam":case"sts":return i.localstackEndpoint;default:return i.localstackEndpoint}}function US(){let n=Md();return{accessKeyId:n.awsAccessKeyId,secretAccessKey:n.awsSecretAccessKey,region:n.awsRegion}}function QS(){let n=Md();if(!n.enabled)return{};return{AWS_ACCESS_KEY_ID:n.awsAccessKeyId,AWS_SECRET_ACCESS_KEY:n.awsSecretAccessKey,AWS_REGION:n.awsRegion,AWS_ENDPOINT_URL:n.localstackEndpoint,LOCALSTACK_ENDPOINT:n.localstackEndpoint,TS_CLOUD_LOCAL:"true"}}class _g{stacks=new Map;stackEvents=new Map;async createStack(n){let i=`arn:aws:cloudformation:${n.region||"us-east-1"}:123456789012:stack/${n.StackName}/${Date.now()}`;return this.stacks.set(n.StackName,{StackId:i,StackName:n.StackName,StackStatus:"CREATE_IN_PROGRESS",CreationTime:new Date().toISOString(),TemplateBody:n.TemplateBody,Parameters:n.Parameters||[]}),this.addEvent(n.StackName,{EventId:Date.now().toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_IN_PROGRESS"}),setTimeout(()=>{let s=this.stacks.get(n.StackName);if(s)s.StackStatus="CREATE_COMPLETE",this.addEvent(n.StackName,{EventId:(Date.now()+1).toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_COMPLETE"})},100),{StackId:i}}async updateStack(n){let i=this.stacks.get(n.StackName);if(!i)throw Error(`Stack ${n.StackName} does not exist`);return i.StackStatus="UPDATE_IN_PROGRESS",i.TemplateBody=n.TemplateBody||i.TemplateBody,this.addEvent(n.StackName,{EventId:Date.now().toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_IN_PROGRESS"}),setTimeout(()=>{i.StackStatus="UPDATE_COMPLETE",this.addEvent(n.StackName,{EventId:(Date.now()+1).toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_COMPLETE"})},100),{StackId:i.StackId}}async deleteStack(n){let i=this.stacks.get(n.StackName);if(!i)throw Error(`Stack ${n.StackName} does not exist`);i.StackStatus="DELETE_IN_PROGRESS",this.addEvent(n.StackName,{EventId:Date.now().toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_IN_PROGRESS"}),setTimeout(()=>{this.stacks.delete(n.StackName),this.addEvent(n.StackName,{EventId:(Date.now()+1).toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_COMPLETE"})},100)}async describeStacks(n){if(n.StackName){let i=this.stacks.get(n.StackName);if(!i)throw Error(`Stack ${n.StackName} does not exist`);return{Stacks:[i]}}return{Stacks:Array.from(this.stacks.values())}}async describeStackEvents(n){return{StackEvents:this.stackEvents.get(n.StackName)||[]}}addEvent(n,i){if(!this.stackEvents.has(n))this.stackEvents.set(n,[]);this.stackEvents.get(n).unshift(i)}reset(){this.stacks.clear(),this.stackEvents.clear()}}class xg{buckets=new Map;async createBucket(n){return this.buckets.set(n.Bucket,new Map),{Location:`/${n.Bucket}`}}async deleteBucket(n){this.buckets.delete(n.Bucket)}async putObject(n){let i=this.buckets.get(n.Bucket);if(!i)i=new Map,this.buckets.set(n.Bucket,i);return i.set(n.Key,Buffer.from(n.Body||"")),{ETag:`"${Date.now()}"`}}async getObject(n){let i=this.buckets.get(n.Bucket);if(!i)throw Error(`Bucket ${n.Bucket} does not exist`);let s=i.get(n.Key);if(!s)throw Error(`Object ${n.Key} does not exist`);return{Body:s,ContentLength:s.length}}async deleteObject(n){let i=this.buckets.get(n.Bucket);if(i)i.delete(n.Key)}async listObjects(n){let i=this.buckets.get(n.Bucket);if(!i)throw Error(`Bucket ${n.Bucket} does not exist`);return{Contents:Array.from(i.keys()).map((s)=>({Key:s,Size:i.get(s).length,LastModified:new Date().toISOString()}))}}reset(){this.buckets.clear()}}class Og{tables=new Map;data=new Map;async createTable(n){return this.tables.set(n.TableName,{TableName:n.TableName,KeySchema:n.KeySchema,AttributeDefinitions:n.AttributeDefinitions,TableStatus:"ACTIVE",CreationDateTime:new Date().toISOString()}),this.data.set(n.TableName,new Map),{TableDescription:this.tables.get(n.TableName)}}async deleteTable(n){this.tables.delete(n.TableName),this.data.delete(n.TableName)}async putItem(n){let i=this.data.get(n.TableName);if(!i)i=new Map,this.data.set(n.TableName,i);let s=JSON.stringify(n.Item);i.set(s,n.Item)}async getItem(n){let i=this.data.get(n.TableName);if(!i)return{};let s=JSON.stringify(n.Key),o=i.get(s);return o?{Item:o}:{}}async deleteItem(n){let i=this.data.get(n.TableName);if(i){let s=JSON.stringify(n.Key);i.delete(s)}}async scan(n){let i=this.data.get(n.TableName);if(!i)return{Items:[]};return{Items:Array.from(i.values())}}reset(){this.tables.clear(),this.data.clear()}}function HS(n){return{cloudformation:new _g,s3:new xg,dynamodb:new Og}}class Lg{environments=new Map;async createPreviewEnvironment(n){let{branch:i,pr:s,commitSha:o,ttl:c=24,baseConfig:l,region:u="us-east-1"}=n,h=this.generatePreviewId(i,s,o),y=this.generatePreviewName(i,s),f=`preview-${y}`,b=new Date,C=new Date(b.getTime()+c*60*60*1000),T={id:h,name:y,branch:i,pr:s,commitSha:o,createdAt:b,expiresAt:C,status:"creating",stackName:f,region:u,resources:[]};this.environments.set(h,T);try{let w=this.createPreviewConfig(l,y);return T.status="active",T.url=`https://${y}.preview.example.com`,T}catch(w){throw T.status="failed",w}}async destroyPreviewEnvironment(n){let i=this.environments.get(n);if(!i)throw Error(`Preview environment ${n} not found`);i.status="destroying";try{i.status="destroyed",this.environments.delete(n)}catch(s){throw Error(`Failed to destroy preview environment: ${s}`)}}getPreviewEnvironment(n){return this.environments.get(n)}getPreviewEnvironmentByBranch(n){return Array.from(this.environments.values()).find((i)=>i.branch===n)}getPreviewEnvironmentByPR(n){return Array.from(this.environments.values()).find((i)=>i.pr===n)}listPreviewEnvironments(){return Array.from(this.environments.values())}listActivePreviewEnvironments(){return this.listPreviewEnvironments().filter((n)=>n.status==="active")}async cleanupExpiredEnvironments(n={}){let{maxAge:i,keepCount:s,dryRun:o=!1}=n,c=[],l=[],u=new Date,h=this.listPreviewEnvironments().sort((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 b=!1;if(f.expiresAt<u)b=!0;if(i){if((u.getTime()-f.createdAt.getTime())/3600000>i)b=!0}if(s&&y>=s)b=!0;if(b)if(o)c.push(f.id);else try{await this.destroyPreviewEnvironment(f.id),c.push(f.id)}catch(C){l.push(f.id)}}return{destroyed:c,failed:l}}async updatePreviewEnvironment(n,i){let s=this.environments.get(n);if(!s)throw Error(`Preview environment ${n} not found`);s.commitSha=i,s.status="creating";try{return s.status="active",s}catch(o){throw s.status="failed",o}}async getPreviewEnvironmentsCost(){let n={},i=0;for(let s of this.environments.values())n[s.id]=0,i+=0;return{total:i,byEnvironment:n}}generatePreviewId(n,i,s){let o=n.replace(/[^a-z0-9-]/gi,"-").toLowerCase(),c=s?.substring(0,7)||Date.now().toString();return i?`pr-${i}-${c}`:`${o}-${c}`}generatePreviewName(n,i){let s=n.replace(/[^a-z0-9-]/gi,"-").toLowerCase();return i?`pr-${i}`:s}createPreviewConfig(n,i){return{...n,project:{...n.project,name:`${n.project.name} Preview (${i})`,slug:`${n.project.slug}-preview-${i}`}}}}var GS=new Lg;function qS(n={}){let{workflowName:i="Preview Environment",trigger:s="pull_request",branches:o=["main","develop"],awsRegion:c="us-east-1",awsRole:l,configFile:u="cloud.config.ts",ttl:h=24}=n;return`name: ${i}
2513
2513
 
2514
2514
  on:
2515
2515
  ${s}:
@@ -2643,7 +2643,7 @@ jobs:
2643
2643
  run: |
2644
2644
  # Clean up environments older than TTL
2645
2645
  bun run cloud env:cleanup --max-age=\${{ env.TTL_HOURS }}
2646
- `}function GS(n={}){let{schedule:i="0 0 * * *",maxAge:s=48,keepCount:o=10}=n;return`name: Cleanup Stale Preview Environments
2646
+ `}function VS(n={}){let{schedule:i="0 0 * * *",maxAge:s=48,keepCount:o=10}=n;return`name: Cleanup Stale Preview Environments
2647
2647
 
2648
2648
  on:
2649
2649
  schedule:
@@ -2688,7 +2688,7 @@ jobs:
2688
2688
  - name: Report cleanup results
2689
2689
  run: |
2690
2690
  bun run cloud env:list --status=destroyed
2691
- `}function qS(n={}){let{schedule:i="0 8 * * 1",webhookUrl:s}=n;return`name: Preview Environment Cost Report
2691
+ `}function jS(n={}){let{schedule:i="0 8 * * 1",webhookUrl:s}=n;return`name: Preview Environment Cost Report
2692
2692
 
2693
2693
  on:
2694
2694
  schedule:
@@ -2737,15 +2737,15 @@ jobs:
2737
2737
  curl -X POST -H 'Content-type: application/json' \\
2738
2738
  --data '{"text":"Preview Environment Cost Report\\n\${{ steps.cost.outputs.cost_json }}"}' \\
2739
2739
  $SLACK_WEBHOOK_URL`:'run: |\n echo "${{ steps.cost.outputs.cost_json }}"'}
2740
- `}class Og{channels=[];addChannel(n){this.channels.push(n)}removeChannel(n){this.channels=this.channels.filter((i)=>i.type!==n)}async notify(n){let i=this.channels.map((s)=>this.sendToChannel(s,n));await Promise.allSettled(i)}async sendToChannel(n,i){switch(n.type){case"slack":await this.sendToSlack(n.config,i);break;case"discord":await this.sendToDiscord(n.config,i);break;case"email":await this.sendToEmail(n.config,i);break;case"webhook":await this.sendToWebhook(n.config,i);break}}async sendToSlack(n,i){let s=this.formatSlackMessage(i,n),o=await fetch(n.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!o.ok)throw Error(`Failed to send Slack notification: ${o.statusText}`)}formatSlackMessage(n,i){let{environment:s,type:o}=n,c={created:":rocket:",updated:":arrows_counterclockwise:",destroyed:":wastebasket:",failed:":x:",expired:":hourglass_flowing_sand:"}[o],l={created:"#36a64f",updated:"#2196F3",destroyed:"#808080",failed:"#f44336",expired:"#ff9800"}[o],u={created:"Preview Environment Created",updated:"Preview Environment Updated",destroyed:"Preview Environment Destroyed",failed:"Preview Environment Failed",expired:"Preview Environment Expired"}[o];return{username:i.username||"ts-cloud",icon_emoji:i.iconEmoji||":cloud:",channel:i.channel,attachments:[{color:l,title:`${c} ${u}`,fields:[{title:"Environment",value:s.name,short:!0},{title:"Branch",value:s.branch,short:!0},...s.pr?[{title:"PR",value:`#${s.pr}`,short:!0}]:[],{title:"Commit",value:s.commitSha.substring(0,7),short:!0},...s.url?[{title:"URL",value:s.url,short:!1}]:[],...o==="created"?[{title:"Expires",value:s.expiresAt.toLocaleString(),short:!0}]:[]],footer:"ts-cloud Preview Environments",ts:Math.floor(n.timestamp.getTime()/1000)}]}}async sendToDiscord(n,i){let s=this.formatDiscordMessage(i,n),o=await fetch(n.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!o.ok)throw Error(`Failed to send Discord notification: ${o.statusText}`)}formatDiscordMessage(n,i){let{environment:s,type:o}=n,c={created:":rocket:",updated:":arrows_counterclockwise:",destroyed:":wastebasket:",failed:":x:",expired:":hourglass:"}[o],l={created:3581519,updated:2201331,destroyed:8421504,failed:16007990,expired:16750592}[o],u={created:"Preview Environment Created",updated:"Preview Environment Updated",destroyed:"Preview Environment Destroyed",failed:"Preview Environment Failed",expired:"Preview Environment Expired"}[o];return{username:i.username||"ts-cloud",avatar_url:i.avatarUrl,embeds:[{title:`${c} ${u}`,color:l,fields:[{name:"Environment",value:s.name,inline:!0},{name:"Branch",value:s.branch,inline:!0},...s.pr?[{name:"PR",value:`#${s.pr}`,inline:!0}]:[],{name:"Commit",value:`\`${s.commitSha.substring(0,7)}\``,inline:!0},...s.url?[{name:"URL",value:s.url,inline:!1}]:[]],timestamp:n.timestamp.toISOString(),footer:{text:"ts-cloud Preview Environments"}}]}}async sendToEmail(n,i){console.log(`Email notification would be sent to ${n.to.join(", ")}`)}async sendToWebhook(n,i){let s=await fetch(n.url,{method:n.method||"POST",headers:{"Content-Type":"application/json",...n.headers},body:JSON.stringify({event:i.type,environment:i.environment,timestamp:i.timestamp.toISOString(),metadata:i.metadata})});if(!s.ok)throw Error(`Failed to send webhook notification: ${s.statusText}`)}}var VS=new Og;function jS(n){let{columns:i,data:s,border:o=!0,header:c=!0,compact:l=!1,maxWidth:u}=n;if(s.length===0)return"No data to display";let h=i.map((f)=>{let b=f.label.length,C=Math.max(...s.map((w)=>(f.formatter?f.formatter(w[f.key]):String(w[f.key]||"")).length)),T=f.width||Math.max(b,C);if(u&&T>u)T=u;return T}),y=[];if(o)y.push(Lt(h,"top",l));if(c){if(y.push(Sa(i.map((f)=>f.label),h,i.map((f)=>f.align||"left"),o)),o)y.push(Lt(h,"middle",l))}for(let f of s){let b=i.map((C)=>{let T=C.formatter?C.formatter(f[C.key]):String(f[C.key]||"");return Fn(T,h[i.indexOf(C)])});y.push(Sa(b,h,i.map((C)=>C.align||"left"),o))}if(o)y.push(Lt(h,"bottom",l));return y.join(`
2741
- `)}function Sa(n,i,s,o){let c=n.map((l,u)=>{let h=i[u],y=s[u];return Gn(l,h,y)});if(o)return`│ ${c.join(" │ ")} │`;return c.join(" ")}function Lt(n,i,s){let o=i==="top"?"┌":i==="middle"?"├":"└",c=i==="top"?"┐":i==="middle"?"┤":"┘",l=i==="top"?"┬":i==="middle"?"┼":"┴",u="─";if(s)return o+n.map((h)=>"─".repeat(h+2)).join(l)+c;return o+n.map((h)=>"─".repeat(h+2)).join(l)+c}function Gn(n,i,s){let o=Ga(n).length;if(o>=i)return n;let c=i-o;switch(s){case"right":return" ".repeat(c)+n;case"center":{let l=Math.floor(c/2),u=c-l;return" ".repeat(l)+n+" ".repeat(u)}default:return n+" ".repeat(c)}}function Fn(n,i){if(Ga(n).length<=i)return n;return n.substring(0,i-1)+"…"}function Ga(n){return n.replace(/\x1B\[[0-9;]*m/g,"")}function zS(n,i={}){let{indent:s=" ",showMetadata:o=!1}=i,c=[];function l(u,h,y){let f=h+(y?"└─ ":"├─ ")+u.label;if(c.push(f),o&&u.metadata){let b=h+(y?" ":"│ ");for(let[C,T]of Object.entries(u.metadata))c.push(`${b}${C}: ${T}`)}if(u.children&&u.children.length>0){let b=h+(y?" ":"│ ");u.children.forEach((C,T)=>{l(C,b,T===u.children.length-1)})}}return n.forEach((u,h)=>{l(u,"",h===n.length-1)}),c.join(`
2742
- `)}function KS(n){let{total:i,current:s,width:o=40,format:c=":bar :percent :current/:total",complete:l="█",incomplete:u="░"}=n,h=Math.min(100,Math.max(0,s/i*100)),y=Math.floor(o*s/i),f=o-y,b=l.repeat(y)+u.repeat(f);return c.replace(":bar",b).replace(":percent",`${h.toFixed(0)}%`).replace(":current",String(s)).replace(":total",String(i))}function WS(n,i=2){if(n===0)return"0 Bytes";let s=1024,o=i<0?0:i,c=["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"],l=Math.floor(Math.log(n)/Math.log(s));return`${Number.parseFloat((n/Math.pow(s,l)).toFixed(o))} ${c[l]}`}function JS(n){if(n<1000)return`${n}ms`;let i=Math.floor(n/1000);if(i<60)return`${i}s`;let s=Math.floor(i/60),o=i%60;if(s<60)return o>0?`${s}m ${o}s`:`${s}m`;let c=Math.floor(s/60),l=s%60;if(c<24)return l>0?`${c}h ${l}m`:`${c}h`;let u=Math.floor(c/24),h=c%24;return h>0?`${u}d ${h}h`:`${u}d`}function XS(n,i="•"){return n.map((s)=>`${i} ${s}`).join(`
2743
- `)}function YS(n,i={}){let{indent:s="",separator:o=": "}=i,c=Math.max(...Object.keys(n).map((l)=>l.length));return Object.entries(n).map(([l,u])=>{let h=l.padEnd(c);return`${s}${h}${o}${u}`}).join(`
2744
- `)}class kA{total;current=0;width;format;message;showETA;showPercentage;showCounter;startTime=Date.now();lastUpdate=0;constructor(n){this.total=n.total,this.current=n.current||0,this.width=n.width||40,this.format=n.format||":message :bar :percent :eta",this.message=n.message||"Progress",this.showETA=n.showETA!==!1,this.showPercentage=n.showPercentage!==!1,this.showCounter=n.showCounter!==!1}tick(n=1){this.current=Math.min(this.total,this.current+n),this.lastUpdate=Date.now()}update(n){this.current=Math.min(this.total,Math.max(0,n)),this.lastUpdate=Date.now()}setMessage(n){this.message=n}getPercentage(){return Math.min(100,this.current/this.total*100)}getETA(){if(this.current===0)return 0;let n=Date.now()-this.startTime,i=this.current/n,s=this.total-this.current;return Math.round(s/i)}getETAFormatted(){if(this.current===0)return"calculating...";if(this.current===this.total)return"complete";let n=this.getETA();if(n<1000)return"< 1s";if(n<60000)return`${Math.round(n/1000)}s`;let i=Math.floor(n/60000);if(i<60)return`${i}m`;let s=Math.floor(i/60),o=i%60;if(s<24)return o>0?`${s}h ${o}m`:`${s}h`;let c=Math.floor(s/24),l=s%24;return l>0?`${c}d ${l}h`:`${c}d`}render(){let n=this.getPercentage(),i=Math.floor(this.width*this.current/this.total),s=this.width-i,o="█".repeat(i)+"░".repeat(s),c=`${n.toFixed(1)}%`,l=`${this.current}/${this.total}`,u=this.showETA?`ETA: ${this.getETAFormatted()}`:"",h=this.format.replace(":message",this.message).replace(":bar",o).replace(":percent",this.showPercentage?c:"").replace(":counter",this.showCounter?l:"").replace(":eta",u).replace(":current",String(this.current)).replace(":total",String(this.total));return h=h.replace(/\s+/g," ").trim(),h}isComplete(){return this.current>=this.total}}class BA{steps;currentStepIndex=0;constructor(n){this.steps=n.map((i)=>({name:i,status:"pending"}))}startStep(n,i){if(n>=0&&n<this.steps.length)this.steps[n].status="active",this.steps[n].message=i,this.currentStepIndex=n}completeStep(n){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="completed",this.steps[this.currentStepIndex].message=n,this.currentStepIndex++}failStep(n){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="failed",this.steps[this.currentStepIndex].error=n}skipStep(n){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="skipped",this.steps[this.currentStepIndex].message=n,this.currentStepIndex++}getStep(n){return this.steps[n]}getSteps(){return this.steps}render(){let n=[];for(let i of this.steps){let s=`${this.getStatusIcon(i.status)} ${i.name}`;if(i.message)s+=` - ${i.message}`;if(i.error)s+=`
2740
+ `}class $g{channels=[];addChannel(n){this.channels.push(n)}removeChannel(n){this.channels=this.channels.filter((i)=>i.type!==n)}async notify(n){let i=this.channels.map((s)=>this.sendToChannel(s,n));await Promise.allSettled(i)}async sendToChannel(n,i){switch(n.type){case"slack":await this.sendToSlack(n.config,i);break;case"discord":await this.sendToDiscord(n.config,i);break;case"email":await this.sendToEmail(n.config,i);break;case"webhook":await this.sendToWebhook(n.config,i);break}}async sendToSlack(n,i){let s=this.formatSlackMessage(i,n),o=await fetch(n.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!o.ok)throw Error(`Failed to send Slack notification: ${o.statusText}`)}formatSlackMessage(n,i){let{environment:s,type:o}=n,c={created:":rocket:",updated:":arrows_counterclockwise:",destroyed:":wastebasket:",failed:":x:",expired:":hourglass_flowing_sand:"}[o],l={created:"#36a64f",updated:"#2196F3",destroyed:"#808080",failed:"#f44336",expired:"#ff9800"}[o],u={created:"Preview Environment Created",updated:"Preview Environment Updated",destroyed:"Preview Environment Destroyed",failed:"Preview Environment Failed",expired:"Preview Environment Expired"}[o];return{username:i.username||"ts-cloud",icon_emoji:i.iconEmoji||":cloud:",channel:i.channel,attachments:[{color:l,title:`${c} ${u}`,fields:[{title:"Environment",value:s.name,short:!0},{title:"Branch",value:s.branch,short:!0},...s.pr?[{title:"PR",value:`#${s.pr}`,short:!0}]:[],{title:"Commit",value:s.commitSha.substring(0,7),short:!0},...s.url?[{title:"URL",value:s.url,short:!1}]:[],...o==="created"?[{title:"Expires",value:s.expiresAt.toLocaleString(),short:!0}]:[]],footer:"ts-cloud Preview Environments",ts:Math.floor(n.timestamp.getTime()/1000)}]}}async sendToDiscord(n,i){let s=this.formatDiscordMessage(i,n),o=await fetch(n.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!o.ok)throw Error(`Failed to send Discord notification: ${o.statusText}`)}formatDiscordMessage(n,i){let{environment:s,type:o}=n,c={created:":rocket:",updated:":arrows_counterclockwise:",destroyed:":wastebasket:",failed:":x:",expired:":hourglass:"}[o],l={created:3581519,updated:2201331,destroyed:8421504,failed:16007990,expired:16750592}[o],u={created:"Preview Environment Created",updated:"Preview Environment Updated",destroyed:"Preview Environment Destroyed",failed:"Preview Environment Failed",expired:"Preview Environment Expired"}[o];return{username:i.username||"ts-cloud",avatar_url:i.avatarUrl,embeds:[{title:`${c} ${u}`,color:l,fields:[{name:"Environment",value:s.name,inline:!0},{name:"Branch",value:s.branch,inline:!0},...s.pr?[{name:"PR",value:`#${s.pr}`,inline:!0}]:[],{name:"Commit",value:`\`${s.commitSha.substring(0,7)}\``,inline:!0},...s.url?[{name:"URL",value:s.url,inline:!1}]:[]],timestamp:n.timestamp.toISOString(),footer:{text:"ts-cloud Preview Environments"}}]}}async sendToEmail(n,i){console.log(`Email notification would be sent to ${n.to.join(", ")}`)}async sendToWebhook(n,i){let s=await fetch(n.url,{method:n.method||"POST",headers:{"Content-Type":"application/json",...n.headers},body:JSON.stringify({event:i.type,environment:i.environment,timestamp:i.timestamp.toISOString(),metadata:i.metadata})});if(!s.ok)throw Error(`Failed to send webhook notification: ${s.statusText}`)}}var zS=new $g;function KS(n){let{columns:i,data:s,border:o=!0,header:c=!0,compact:l=!1,maxWidth:u}=n;if(s.length===0)return"No data to display";let h=i.map((f)=>{let b=f.label.length,C=Math.max(...s.map((w)=>(f.formatter?f.formatter(w[f.key]):String(w[f.key]||"")).length)),T=f.width||Math.max(b,C);if(u&&T>u)T=u;return T}),y=[];if(o)y.push(Lt(h,"top",l));if(c){if(y.push(Sa(i.map((f)=>f.label),h,i.map((f)=>f.align||"left"),o)),o)y.push(Lt(h,"middle",l))}for(let f of s){let b=i.map((C)=>{let T=C.formatter?C.formatter(f[C.key]):String(f[C.key]||"");return Fn(T,h[i.indexOf(C)])});y.push(Sa(b,h,i.map((C)=>C.align||"left"),o))}if(o)y.push(Lt(h,"bottom",l));return y.join(`
2741
+ `)}function Sa(n,i,s,o){let c=n.map((l,u)=>{let h=i[u],y=s[u];return Gn(l,h,y)});if(o)return`│ ${c.join(" │ ")} │`;return c.join(" ")}function Lt(n,i,s){let o=i==="top"?"┌":i==="middle"?"├":"└",c=i==="top"?"┐":i==="middle"?"┤":"┘",l=i==="top"?"┬":i==="middle"?"┼":"┴",u="─";if(s)return o+n.map((h)=>"─".repeat(h+2)).join(l)+c;return o+n.map((h)=>"─".repeat(h+2)).join(l)+c}function Gn(n,i,s){let o=Ga(n).length;if(o>=i)return n;let c=i-o;switch(s){case"right":return" ".repeat(c)+n;case"center":{let l=Math.floor(c/2),u=c-l;return" ".repeat(l)+n+" ".repeat(u)}default:return n+" ".repeat(c)}}function Fn(n,i){if(Ga(n).length<=i)return n;return n.substring(0,i-1)+"…"}function Ga(n){return n.replace(/\x1B\[[0-9;]*m/g,"")}function WS(n,i={}){let{indent:s=" ",showMetadata:o=!1}=i,c=[];function l(u,h,y){let f=h+(y?"└─ ":"├─ ")+u.label;if(c.push(f),o&&u.metadata){let b=h+(y?" ":"│ ");for(let[C,T]of Object.entries(u.metadata))c.push(`${b}${C}: ${T}`)}if(u.children&&u.children.length>0){let b=h+(y?" ":"│ ");u.children.forEach((C,T)=>{l(C,b,T===u.children.length-1)})}}return n.forEach((u,h)=>{l(u,"",h===n.length-1)}),c.join(`
2742
+ `)}function JS(n){let{total:i,current:s,width:o=40,format:c=":bar :percent :current/:total",complete:l="█",incomplete:u="░"}=n,h=Math.min(100,Math.max(0,s/i*100)),y=Math.floor(o*s/i),f=o-y,b=l.repeat(y)+u.repeat(f);return c.replace(":bar",b).replace(":percent",`${h.toFixed(0)}%`).replace(":current",String(s)).replace(":total",String(i))}function XS(n,i=2){if(n===0)return"0 Bytes";let s=1024,o=i<0?0:i,c=["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"],l=Math.floor(Math.log(n)/Math.log(s));return`${Number.parseFloat((n/Math.pow(s,l)).toFixed(o))} ${c[l]}`}function YS(n){if(n<1000)return`${n}ms`;let i=Math.floor(n/1000);if(i<60)return`${i}s`;let s=Math.floor(i/60),o=i%60;if(s<60)return o>0?`${s}m ${o}s`:`${s}m`;let c=Math.floor(s/60),l=s%60;if(c<24)return l>0?`${c}h ${l}m`:`${c}h`;let u=Math.floor(c/24),h=c%24;return h>0?`${u}d ${h}h`:`${u}d`}function ZS(n,i="•"){return n.map((s)=>`${i} ${s}`).join(`
2743
+ `)}function eC(n,i={}){let{indent:s="",separator:o=": "}=i,c=Math.max(...Object.keys(n).map((l)=>l.length));return Object.entries(n).map(([l,u])=>{let h=l.padEnd(c);return`${s}${h}${o}${u}`}).join(`
2744
+ `)}class _A{total;current=0;width;format;message;showETA;showPercentage;showCounter;startTime=Date.now();lastUpdate=0;constructor(n){this.total=n.total,this.current=n.current||0,this.width=n.width||40,this.format=n.format||":message :bar :percent :eta",this.message=n.message||"Progress",this.showETA=n.showETA!==!1,this.showPercentage=n.showPercentage!==!1,this.showCounter=n.showCounter!==!1}tick(n=1){this.current=Math.min(this.total,this.current+n),this.lastUpdate=Date.now()}update(n){this.current=Math.min(this.total,Math.max(0,n)),this.lastUpdate=Date.now()}setMessage(n){this.message=n}getPercentage(){return Math.min(100,this.current/this.total*100)}getETA(){if(this.current===0)return 0;let n=Date.now()-this.startTime,i=this.current/n,s=this.total-this.current;return Math.round(s/i)}getETAFormatted(){if(this.current===0)return"calculating...";if(this.current===this.total)return"complete";let n=this.getETA();if(n<1000)return"< 1s";if(n<60000)return`${Math.round(n/1000)}s`;let i=Math.floor(n/60000);if(i<60)return`${i}m`;let s=Math.floor(i/60),o=i%60;if(s<24)return o>0?`${s}h ${o}m`:`${s}h`;let c=Math.floor(s/24),l=s%24;return l>0?`${c}d ${l}h`:`${c}d`}render(){let n=this.getPercentage(),i=Math.floor(this.width*this.current/this.total),s=this.width-i,o="█".repeat(i)+"░".repeat(s),c=`${n.toFixed(1)}%`,l=`${this.current}/${this.total}`,u=this.showETA?`ETA: ${this.getETAFormatted()}`:"",h=this.format.replace(":message",this.message).replace(":bar",o).replace(":percent",this.showPercentage?c:"").replace(":counter",this.showCounter?l:"").replace(":eta",u).replace(":current",String(this.current)).replace(":total",String(this.total));return h=h.replace(/\s+/g," ").trim(),h}isComplete(){return this.current>=this.total}}class xA{steps;currentStepIndex=0;constructor(n){this.steps=n.map((i)=>({name:i,status:"pending"}))}startStep(n,i){if(n>=0&&n<this.steps.length)this.steps[n].status="active",this.steps[n].message=i,this.currentStepIndex=n}completeStep(n){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="completed",this.steps[this.currentStepIndex].message=n,this.currentStepIndex++}failStep(n){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="failed",this.steps[this.currentStepIndex].error=n}skipStep(n){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="skipped",this.steps[this.currentStepIndex].message=n,this.currentStepIndex++}getStep(n){return this.steps[n]}getSteps(){return this.steps}render(){let n=[];for(let i of this.steps){let s=`${this.getStatusIcon(i.status)} ${i.name}`;if(i.message)s+=` - ${i.message}`;if(i.error)s+=`
2745
2745
  Error: ${i.error}`;n.push(s)}return n.join(`
2746
- `)}getStatusIcon(n){switch(n){case"pending":return"○";case"active":return"◐";case"completed":return"✓";case"failed":return"✗";case"skipped":return"⊘";default:return"○"}}isComplete(){return this.steps.every((n)=>n.status==="completed"||n.status==="skipped")}hasFailed(){return this.steps.some((n)=>n.status==="failed")}}class _A{frames=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];currentFrame=0;message;interval=null;constructor(n="Loading..."){this.message=n}start(){if(this.interval)return;this.interval=setInterval(()=>{this.currentFrame=(this.currentFrame+1)%this.frames.length},80)}stop(){if(this.interval)clearInterval(this.interval),this.interval=null}setMessage(n){this.message=n}render(){return`${this.frames[this.currentFrame]} ${this.message}`}succeed(n){return this.stop(),`✓ ${n||this.message}`}fail(n){return this.stop(),`✗ ${n||this.message}`}warn(n){return this.stop(),`⚠ ${n||this.message}`}info(n){return this.stop(),`ℹ ${n||this.message}`}}class xA{tasks=[];add(n){return this.tasks.push({title:n,status:"pending"}),this.tasks.length-1}start(n){if(n>=0&&n<this.tasks.length)this.tasks[n].status="running"}complete(n,i){if(n>=0&&n<this.tasks.length)this.tasks[n].status="completed",this.tasks[n].output=i}fail(n,i){if(n>=0&&n<this.tasks.length)this.tasks[n].status="failed",this.tasks[n].output=i}render(){let n=[];for(let i of this.tasks){let s=`${this.getStatusIcon(i.status)} ${i.title}`;if(i.output)s+=`
2746
+ `)}getStatusIcon(n){switch(n){case"pending":return"○";case"active":return"◐";case"completed":return"✓";case"failed":return"✗";case"skipped":return"⊘";default:return"○"}}isComplete(){return this.steps.every((n)=>n.status==="completed"||n.status==="skipped")}hasFailed(){return this.steps.some((n)=>n.status==="failed")}}class OA{frames=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];currentFrame=0;message;interval=null;constructor(n="Loading..."){this.message=n}start(){if(this.interval)return;this.interval=setInterval(()=>{this.currentFrame=(this.currentFrame+1)%this.frames.length},80)}stop(){if(this.interval)clearInterval(this.interval),this.interval=null}setMessage(n){this.message=n}render(){return`${this.frames[this.currentFrame]} ${this.message}`}succeed(n){return this.stop(),`✓ ${n||this.message}`}fail(n){return this.stop(),`✗ ${n||this.message}`}warn(n){return this.stop(),`⚠ ${n||this.message}`}info(n){return this.stop(),`ℹ ${n||this.message}`}}class LA{tasks=[];add(n){return this.tasks.push({title:n,status:"pending"}),this.tasks.length-1}start(n){if(n>=0&&n<this.tasks.length)this.tasks[n].status="running"}complete(n,i){if(n>=0&&n<this.tasks.length)this.tasks[n].status="completed",this.tasks[n].output=i}fail(n,i){if(n>=0&&n<this.tasks.length)this.tasks[n].status="failed",this.tasks[n].output=i}render(){let n=[];for(let i of this.tasks){let s=`${this.getStatusIcon(i.status)} ${i.title}`;if(i.output)s+=`
2747
2747
  ${i.output}`;n.push(s)}return n.join(`
2748
- `)}getStatusIcon(n){switch(n){case"pending":return"○";case"running":return"◐";case"completed":return"✓";case"failed":return"✗";default:return"○"}}}function Un(n,i){let s=[];for(let o=0;o<=i.length;o++)s[o]=[o];for(let o=0;o<=n.length;o++)s[0][o]=o;for(let o=1;o<=i.length;o++)for(let c=1;c<=n.length;c++)if(i.charAt(o-1)===n.charAt(c-1))s[o][c]=s[o-1][c-1];else s[o][c]=Math.min(s[o-1][c-1]+1,s[o][c-1]+1,s[o-1][c]+1);return s[i.length][n.length]}function Vn(n,i){let s=Un(n.toLowerCase(),i.toLowerCase()),o=Math.max(n.length,i.length);if(o===0)return 1;return 1-s/o}function Lg(n,i,s=0.5){return i.map((o)=>({command:o,score:Vn(n,o)})).filter((o)=>o.score>=s).sort((o,c)=>c.score-o.score).map((o)=>o.command).slice(0,5)}function ZS(n,i){if(i.length===0)return`Unknown command: '${n}'
2748
+ `)}getStatusIcon(n){switch(n){case"pending":return"○";case"running":return"◐";case"completed":return"✓";case"failed":return"✗";default:return"○"}}}function Un(n,i){let s=[];for(let o=0;o<=i.length;o++)s[o]=[o];for(let o=0;o<=n.length;o++)s[0][o]=o;for(let o=1;o<=i.length;o++)for(let c=1;c<=n.length;c++)if(i.charAt(o-1)===n.charAt(c-1))s[o][c]=s[o-1][c-1];else s[o][c]=Math.min(s[o-1][c-1]+1,s[o][c-1]+1,s[o-1][c]+1);return s[i.length][n.length]}function Vn(n,i){let s=Un(n.toLowerCase(),i.toLowerCase()),o=Math.max(n.length,i.length);if(o===0)return 1;return 1-s/o}function Mg(n,i,s=0.5){return i.map((o)=>({command:o,score:Vn(n,o)})).filter((o)=>o.score>=s).sort((o,c)=>c.score-o.score).map((o)=>o.command).slice(0,5)}function tC(n,i){if(i.length===0)return`Unknown command: '${n}'
2749
2749
 
2750
2750
  Run 'ts-cloud --help' to see available commands.`;if(i.length===1)return`Unknown command: '${n}'
2751
2751
 
@@ -2753,17 +2753,17 @@ Did you mean: ${i[0]}?`;return`Unknown command: '${n}'
2753
2753
 
2754
2754
  Did you mean one of these?
2755
2755
  ${i.map((s)=>` • ${s}`).join(`
2756
- `)}`}function eC(n,i){return Lg(n,i,0.7).length>0}function tC(n,i){let s=i.find((l)=>l.commands.some((u)=>u.name===n||u.aliases?.includes(n)));if(!s)return"No contextual help available.";let o=[];o.push(`${s.name}`),o.push("─".repeat(s.name.length)),o.push(s.description),o.push(""),o.push("Related commands:");for(let l of s.commands)if(o.push(` ${l.name.padEnd(20)} ${l.description}`),l.aliases&&l.aliases.length>0)o.push(` Aliases: ${l.aliases.join(", ")}`);let c=s.commands.find((l)=>l.name===n||l.aliases?.includes(n));if(c?.examples&&c.examples.length>0){o.push(""),o.push("Examples:");for(let l of c.examples)o.push(` ${l}`)}return o.join(`
2757
- `)}function rC(n,i){let s=[],o=n.toLowerCase();for(let c of i)for(let l of c.commands){let u=l.name.toLowerCase().includes(o),h=l.description.toLowerCase().includes(o),y=l.aliases?.some((f)=>f.toLowerCase().includes(o));if(u||h||y)s.push({command:l,category:c.name})}return s}function nC(n,i,s=10){let o=n.toLowerCase(),c=i.filter((u)=>u.toLowerCase().startsWith(o)),l=i.filter((u)=>u.toLowerCase().includes(o)&&!u.toLowerCase().startsWith(o));return[...c,...l].slice(0,s)}function iC(n,i){let s=n.toLowerCase();return i.filter((o)=>{let c=o.name.toLowerCase().includes(s),l=o.alias?.toLowerCase().includes(s);return c||l})}function sC(n){if(n.length===0)return"No matching flags found.";let i=[];for(let s of n){let o=` --${s.name}`;if(s.alias)o+=`, -${s.alias}`;if(o=o.padEnd(30),o+=s.description,s.required)o+=" (required)";i.push(o)}return i.join(`
2758
- `)}function oC(n){let i=[];if(i.push(`Usage: ts-cloud ${n.name}`),i.push(""),i.push(n.description),n.aliases&&n.aliases.length>0)i.push(""),i.push(`Aliases: ${n.aliases.join(", ")}`);if(n.examples&&n.examples.length>0){i.push(""),i.push("Examples:");for(let s of n.examples)i.push(` ${s}`)}return i.join(`
2759
- `)}function aC(n,i,s=[]){let o={valid:!0,errors:[],warnings:[],suggestions:[]},[c,...l]=n.split(" ");if(!i.includes(c)){o.valid=!1,o.errors.push(`Unknown command: ${c}`);let u=Lg(c,i);if(u.length>0)o.suggestions.push(...u)}for(let u of s)if(!l.some((h)=>h===`--${u}`||h.startsWith(`--${u}=`)))o.valid=!1,o.errors.push(`Missing required flag: --${u}`);return o}class OA{options;running=!1;history={commands:[],maxSize:1000};historyIndex=-1;constructor(n){this.options={prompt:n.prompt||"> ",welcome:n.welcome||'Welcome to ts-cloud interactive mode. Type "help" for available commands.',...n}}async start(){if(this.running=!0,this.options.welcome)console.log(this.options.welcome),console.log("");if(this.options.historyFile)await this.loadHistory();while(this.running)try{let n=await this.readInput();if(!n.trim())continue;this.addToHistory(n),await this.executeCommand(n)}catch(n){if(n instanceof Error)console.error(`Error: ${n.message}`)}if(this.options.historyFile)await this.saveHistory()}stop(){this.running=!1}async readInput(){return new Promise((n)=>{process.stdout.write(this.options.prompt||"> "),n("")})}async executeCommand(n){let[i,...s]=this.parseCommand(n);if(i==="exit"||i==="quit"){this.stop();return}if(i==="help"){this.showHelp();return}if(i==="history"){this.showHistory();return}if(i==="clear"){console.clear();return}let o=this.findCommand(i);if(!o){console.error(`Unknown command: ${i}`),console.log('Type "help" to see available commands.');return}try{await o.handler(s)}catch(c){if(c instanceof Error)console.error(`Command failed: ${c.message}`)}}parseCommand(n){return n.trim().split(/\s+/)}findCommand(n){for(let[i,s]of this.options.commands)if(s.name===n||s.aliases?.includes(n))return s;return}showHelp(){console.log("Available commands:"),console.log("");let n=Array.from(this.options.commands.values());console.log(" help Show this help message"),console.log(" history Show command history"),console.log(" clear Clear screen"),console.log(" exit, quit Exit interactive mode"),console.log("");for(let i of n){let s=` ${i.name.padEnd(20)} ${i.description}`;if(i.aliases&&i.aliases.length>0)s+=` (aliases: ${i.aliases.join(", ")})`;console.log(s)}}showHistory(){if(this.history.commands.length===0){console.log("No command history");return}console.log("Command history:"),this.history.commands.forEach((n,i)=>{console.log(` ${(i+1).toString().padStart(4)} ${n}`)})}addToHistory(n){if(this.history.commands[this.history.commands.length-1]===n)return;if(this.history.commands.push(n),this.history.commands.length>this.history.maxSize)this.history.commands=this.history.commands.slice(-this.history.maxSize);this.historyIndex=this.history.commands.length}historyBack(){if(this.historyIndex>0)return this.historyIndex--,this.history.commands[this.historyIndex];return}historyForward(){if(this.historyIndex<this.history.commands.length-1)return this.historyIndex++,this.history.commands[this.historyIndex];return this.historyIndex=this.history.commands.length,""}autocomplete(n){let i=[],s=["help","history","clear","exit","quit"];for(let o of s)if(o.startsWith(n))i.push(o);for(let[o,c]of this.options.commands){if(c.name.startsWith(n))i.push(c.name);if(c.aliases){for(let l of c.aliases)if(l.startsWith(n))i.push(l)}}return i}async loadHistory(){if(!this.options.historyFile)return;try{let n=await import("node:fs/promises"),i=await n.readFile(this.options.historyFile,"utf-8");this.history.commands=i.split(`
2756
+ `)}`}function rC(n,i){return Mg(n,i,0.7).length>0}function nC(n,i){let s=i.find((l)=>l.commands.some((u)=>u.name===n||u.aliases?.includes(n)));if(!s)return"No contextual help available.";let o=[];o.push(`${s.name}`),o.push("─".repeat(s.name.length)),o.push(s.description),o.push(""),o.push("Related commands:");for(let l of s.commands)if(o.push(` ${l.name.padEnd(20)} ${l.description}`),l.aliases&&l.aliases.length>0)o.push(` Aliases: ${l.aliases.join(", ")}`);let c=s.commands.find((l)=>l.name===n||l.aliases?.includes(n));if(c?.examples&&c.examples.length>0){o.push(""),o.push("Examples:");for(let l of c.examples)o.push(` ${l}`)}return o.join(`
2757
+ `)}function iC(n,i){let s=[],o=n.toLowerCase();for(let c of i)for(let l of c.commands){let u=l.name.toLowerCase().includes(o),h=l.description.toLowerCase().includes(o),y=l.aliases?.some((f)=>f.toLowerCase().includes(o));if(u||h||y)s.push({command:l,category:c.name})}return s}function sC(n,i,s=10){let o=n.toLowerCase(),c=i.filter((u)=>u.toLowerCase().startsWith(o)),l=i.filter((u)=>u.toLowerCase().includes(o)&&!u.toLowerCase().startsWith(o));return[...c,...l].slice(0,s)}function oC(n,i){let s=n.toLowerCase();return i.filter((o)=>{let c=o.name.toLowerCase().includes(s),l=o.alias?.toLowerCase().includes(s);return c||l})}function aC(n){if(n.length===0)return"No matching flags found.";let i=[];for(let s of n){let o=` --${s.name}`;if(s.alias)o+=`, -${s.alias}`;if(o=o.padEnd(30),o+=s.description,s.required)o+=" (required)";i.push(o)}return i.join(`
2758
+ `)}function cC(n){let i=[];if(i.push(`Usage: ts-cloud ${n.name}`),i.push(""),i.push(n.description),n.aliases&&n.aliases.length>0)i.push(""),i.push(`Aliases: ${n.aliases.join(", ")}`);if(n.examples&&n.examples.length>0){i.push(""),i.push("Examples:");for(let s of n.examples)i.push(` ${s}`)}return i.join(`
2759
+ `)}function dC(n,i,s=[]){let o={valid:!0,errors:[],warnings:[],suggestions:[]},[c,...l]=n.split(" ");if(!i.includes(c)){o.valid=!1,o.errors.push(`Unknown command: ${c}`);let u=Mg(c,i);if(u.length>0)o.suggestions.push(...u)}for(let u of s)if(!l.some((h)=>h===`--${u}`||h.startsWith(`--${u}=`)))o.valid=!1,o.errors.push(`Missing required flag: --${u}`);return o}class $A{options;running=!1;history={commands:[],maxSize:1000};historyIndex=-1;constructor(n){this.options={prompt:n.prompt||"> ",welcome:n.welcome||'Welcome to ts-cloud interactive mode. Type "help" for available commands.',...n}}async start(){if(this.running=!0,this.options.welcome)console.log(this.options.welcome),console.log("");if(this.options.historyFile)await this.loadHistory();while(this.running)try{let n=await this.readInput();if(!n.trim())continue;this.addToHistory(n),await this.executeCommand(n)}catch(n){if(n instanceof Error)console.error(`Error: ${n.message}`)}if(this.options.historyFile)await this.saveHistory()}stop(){this.running=!1}async readInput(){return new Promise((n)=>{process.stdout.write(this.options.prompt||"> "),n("")})}async executeCommand(n){let[i,...s]=this.parseCommand(n);if(i==="exit"||i==="quit"){this.stop();return}if(i==="help"){this.showHelp();return}if(i==="history"){this.showHistory();return}if(i==="clear"){console.clear();return}let o=this.findCommand(i);if(!o){console.error(`Unknown command: ${i}`),console.log('Type "help" to see available commands.');return}try{await o.handler(s)}catch(c){if(c instanceof Error)console.error(`Command failed: ${c.message}`)}}parseCommand(n){return n.trim().split(/\s+/)}findCommand(n){for(let[i,s]of this.options.commands)if(s.name===n||s.aliases?.includes(n))return s;return}showHelp(){console.log("Available commands:"),console.log("");let n=Array.from(this.options.commands.values());console.log(" help Show this help message"),console.log(" history Show command history"),console.log(" clear Clear screen"),console.log(" exit, quit Exit interactive mode"),console.log("");for(let i of n){let s=` ${i.name.padEnd(20)} ${i.description}`;if(i.aliases&&i.aliases.length>0)s+=` (aliases: ${i.aliases.join(", ")})`;console.log(s)}}showHistory(){if(this.history.commands.length===0){console.log("No command history");return}console.log("Command history:"),this.history.commands.forEach((n,i)=>{console.log(` ${(i+1).toString().padStart(4)} ${n}`)})}addToHistory(n){if(this.history.commands[this.history.commands.length-1]===n)return;if(this.history.commands.push(n),this.history.commands.length>this.history.maxSize)this.history.commands=this.history.commands.slice(-this.history.maxSize);this.historyIndex=this.history.commands.length}historyBack(){if(this.historyIndex>0)return this.historyIndex--,this.history.commands[this.historyIndex];return}historyForward(){if(this.historyIndex<this.history.commands.length-1)return this.historyIndex++,this.history.commands[this.historyIndex];return this.historyIndex=this.history.commands.length,""}autocomplete(n){let i=[],s=["help","history","clear","exit","quit"];for(let o of s)if(o.startsWith(n))i.push(o);for(let[o,c]of this.options.commands){if(c.name.startsWith(n))i.push(c.name);if(c.aliases){for(let l of c.aliases)if(l.startsWith(n))i.push(l)}}return i}async loadHistory(){if(!this.options.historyFile)return;try{let n=await import("node:fs/promises"),i=await n.readFile(this.options.historyFile,"utf-8");this.history.commands=i.split(`
2760
2760
  `).filter((s)=>s.trim()),this.historyIndex=this.history.commands.length}catch{}}async saveHistory(){if(!this.options.historyFile)return;try{let n=await import("node:fs/promises");await n.writeFile(this.options.historyFile,this.history.commands.join(`
2761
- `))}catch(n){console.error(`Failed to save history: ${n}`)}}searchHistory(n){return this.history.commands.filter((i)=>i.includes(n))}clearHistory(){this.history.commands=[],this.historyIndex=0}}class LA{variables=new Map;workingDirectory=process.cwd();set(n,i){this.variables.set(n,i)}get(n){return this.variables.get(n)}has(n){return this.variables.has(n)}delete(n){this.variables.delete(n)}getAll(){return Object.fromEntries(this.variables)}clear(){this.variables.clear()}setWorkingDirectory(n){this.workingDirectory=n}getWorkingDirectory(){return this.workingDirectory}}class $A{command={};name(n){return this.command.name=n,this}description(n){return this.command.description=n,this}aliases(...n){return this.command.aliases=n,this}handler(n){return this.command.handler=n,this}autocomplete(n){return this.command.autocomplete=n,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 MA{entries=[];maxSize;persistFile;trackOutput;constructor(n={}){this.maxSize=n.maxSize||1000,this.persistFile=n.persistFile,this.trackOutput=n.trackOutput||!1}add(n){if(this.entries.push({...n,timestamp:new Date}),this.entries.length>this.maxSize)this.entries=this.entries.slice(-this.maxSize)}getAll(){return[...this.entries]}getRecent(n=10){return this.entries.slice(-n)}search(n){let i=n.toLowerCase();return this.entries.filter((s)=>s.command.toLowerCase().includes(i))}searchByDate(n,i){return this.entries.filter((s)=>s.timestamp>=n&&s.timestamp<=i)}getSuccessful(){return this.entries.filter((n)=>n.success)}getFailed(){return this.entries.filter((n)=>!n.success)}getMostUsed(n=10){let i=new Map;for(let s of this.entries){let o=s.command.split(" ")[0];i.set(o,(i.get(o)||0)+1)}return Array.from(i.entries()).map(([s,o])=>({command:s,count:o})).sort((s,o)=>o.count-s.count).slice(0,n)}getStats(){let n=this.entries.length,i=this.entries.filter((h)=>h.success).length,s=this.entries.filter((h)=>!h.success).length,o=this.entries.filter((h)=>h.duration!==void 0),c=o.length>0?o.reduce((h,y)=>h+(y.duration||0),0)/o.length:0,l=this.getMostUsed(1),u=l.length>0?l[0].command:"N/A";return{total:n,successful:i,failed:s,averageDuration:c,mostUsed:u}}clear(){this.entries=[]}getByIndex(n){if(n<0||n>=this.entries.length)return;return this.entries[n]}removeByIndex(n){if(n>=0&&n<this.entries.length)this.entries.splice(n,1)}async save(){if(!this.persistFile)return;try{let n=await import("node:fs/promises"),i=JSON.stringify(this.entries,null,2);await n.writeFile(this.persistFile,i,"utf-8")}catch(n){throw Error(`Failed to save history: ${n}`)}}async load(){if(!this.persistFile)return;try{let n=await import("node:fs/promises"),i=await n.readFile(this.persistFile,"utf-8"),s=JSON.parse(i);this.entries=s.map((o)=>({...o,timestamp:new Date(o.timestamp)}))}catch{this.entries=[]}}exportJSON(){return JSON.stringify(this.entries,null,2)}exportCSV(){return["Timestamp,Command,Success,Duration",...this.entries.map((n)=>[n.timestamp.toISOString(),`"${n.command.replace(/"/g,'""')}"`,n.success,n.duration||""].join(","))].join(`
2762
- `)}importJSON(n){let i=JSON.parse(n).map((s)=>({...s,timestamp:new Date(s.timestamp)}));if(this.entries.push(...i),this.entries.length>this.maxSize)this.entries=this.entries.slice(-this.maxSize)}groupByDate(){let n=new Map;for(let i of this.entries){let s=i.timestamp.toISOString().split("T")[0];if(!n.has(s))n.set(s,[]);n.get(s).push(i)}return n}groupByCommand(){let n=new Map;for(let i of this.entries){let s=i.command.split(" ")[0];if(!n.has(s))n.set(s,[]);n.get(s).push(i)}return n}replay(n){return this.getByIndex(n)?.command}getSuggestions(n,i=5){let s=n.toLowerCase(),o=this.entries.filter((c)=>c.command.toLowerCase().startsWith(s)).map((c)=>c.command);return[...new Set(o)].slice(0,i)}analyzePatterns(){let n=new Map,i=new Map;for(let o of this.entries){let c=o.timestamp.getHours(),l=o.timestamp.getDay();n.set(c,(n.get(c)||0)+1),i.set(l,(i.get(l)||0)+1)}let s=this.entries.length>0?this.getSuccessful().length/this.entries.length:0;return{timeOfDay:n,dayOfWeek:i,successRate:s}}}function cC(n,i={}){let{maxWidth:s=100}=i;if(n.length===0)return"No command history";let o=[];for(let c=0;c<n.length;c++){let l=n[c],u=(c+1).toString().padStart(4),h=l.timestamp.toLocaleString(),y=l.success?"✓":"✗",f=l.command;if(f.length>s-30)f=f.substring(0,s-33)+"...";let b=`${u} ${h} ${y} ${f}`;if(l.duration)b+=` (${l.duration}ms)`;o.push(b)}return o.join(`
2763
- `)}function dC(n){let i=[];return i.push("Command History Statistics"),i.push("─".repeat(30)),i.push(`Total commands: ${n.total}`),i.push(`Successful: ${n.successful}`),i.push(`Failed: ${n.failed}`),i.push(`Success rate: ${(n.successful/n.total*100).toFixed(1)}%`),i.push(`Average duration: ${n.averageDuration.toFixed(0)}ms`),i.push(`Most used: ${n.mostUsed}`),i.join(`
2764
- `)}class $g{deployments=new Map;async deploy(n,i){let s=this.generateDeploymentId(),o={id:s,regions:i.regions.map((c)=>({region:c.code,stackName:this.getStackName(n,c.code),status:"pending"})),status:"deploying",startTime:new Date};this.deployments.set(s,o);try{let c=i.regions.find((u)=>u.isPrimary)||i.regions[0];await this.deployToRegion(n,c,o);let l=i.regions.filter((u)=>u.code!==c.code);if(await Promise.all(l.map((u)=>this.deployToRegion(n,u,o))),i.globalResources)await this.deployGlobalResources(o,i);if(i.replication)await this.setupReplication(o,i);if(i.failover?.enabled)await this.setupFailover(o,i);return o.status="deployed",o.endTime=new Date,o}catch(c){throw o.status="failed",o.endTime=new Date,c}}async deployToRegion(n,i,s){let o=s.regions.find((c)=>c.region===i.code);if(!o)throw Error(`Region deployment not found: ${i.code}`);o.status="deploying",o.startTime=new Date;try{let c=this.createRegionConfig(n,i);await this.deployStack(o.stackName,c,i.code),o.status="deployed",o.endTime=new Date,o.outputs={stackId:`arn:aws:cloudformation:${i.code}:123456789012:stack/${o.stackName}/guid`,endpoint:`https://${o.stackName}.${i.code}.example.com`}}catch(c){throw o.status="failed",o.endTime=new Date,o.error=c instanceof Error?c.message:String(c),c}}async deployGlobalResources(n,i){let s={};if(i.globalResources?.route53)s.route53=await this.deployRoute53(n,i);if(i.globalResources?.cloudfront)s.cloudfront=await this.deployCloudFront(n,i);if(i.globalResources?.waf)s.waf=await this.deployWAF(n);n.globalResources=s}async deployRoute53(n,i){let s=[],o=[];for(let c of n.regions){if(c.status!=="deployed")continue;let l={id:`health-${c.region}`,endpoint:c.outputs?.endpoint,path:i.failover?.healthCheckPath||"/health",region:c.region};s.push(l);let u={name:"example.com",type:"A",region:c.region,setIdentifier:c.region,healthCheckId:l.id,resourceRecords:[c.outputs?.endpoint]};o.push(u)}return{healthChecks:s,recordSets:o,hostedZoneId:"Z1234567890ABC"}}async deployCloudFront(n,i){return{distributionId:"E1234567890ABC",domainName:"d1234567890abc.cloudfront.net",origins:n.regions.filter((s)=>s.status==="deployed").map((s,o)=>{let c=i.regions[o];return{id:`origin-${s.region}`,domainName:s.outputs?.endpoint,weight:c?.weight||100}}),status:"Deployed"}}async deployWAF(n){return{webAclId:"arn:aws:wafv2:us-east-1:123456789012:global/webacl/test/a1234567-b890-c123-d456-e789012345f6",webAclArn:"arn:aws:wafv2:us-east-1:123456789012:global/webacl/test/a1234567-b890-c123-d456-e789012345f6"}}async setupReplication(n,i){if(i.replication?.s3)await this.setupS3Replication(n);if(i.replication?.dynamodb)await this.setupDynamoDBReplication(n);if(i.replication?.secrets)await this.setupSecretsReplication(n)}async setupS3Replication(n){let i=n.regions.filter((s)=>s.status==="deployed");for(let s=0;s<i.length-1;s++){let o=i[s],c=i[s+1];console.log(`Setting up S3 replication: ${o.region} -> ${c.region}`)}}async setupDynamoDBReplication(n){let i=n.regions.filter((s)=>s.status==="deployed").map((s)=>s.region);console.log(`Setting up DynamoDB global table in regions: ${i.join(", ")}`)}async setupSecretsReplication(n){let i=n.regions.filter((s)=>s.status==="deployed").map((s)=>s.region);console.log(`Setting up Secrets Manager replication in regions: ${i.join(", ")}`)}async setupFailover(n,i){let s=n.regions.find((c,l)=>i.regions[l]?.isPrimary)||n.regions[0],o=n.regions.filter((c)=>c.region!==s.region);console.log(`Setting up failover: primary=${s.region}, secondary=${o.map((c)=>c.region).join(", ")}`)}async destroy(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);i.status="rolling-back";try{if(i.globalResources)await this.destroyGlobalResources(i.globalResources);await Promise.all(i.regions.map((s)=>this.destroyRegionStack(s))),this.deployments.delete(n)}catch(s){throw i.status="failed",s}}async destroyGlobalResources(n){if(n.waf)console.log("Destroying WAF resources");if(n.cloudfront)console.log("Destroying CloudFront distribution");if(n.route53)console.log("Destroying Route53 resources")}async destroyRegionStack(n){if(n.status!=="deployed")return;n.status="rolling-back";try{console.log(`Destroying stack ${n.stackName} in ${n.region}`),n.status="pending"}catch(i){throw n.status="failed",n.error=i instanceof Error?i.message:String(i),i}}getDeployment(n){return this.deployments.get(n)}listDeployments(){return Array.from(this.deployments.values())}getStackName(n,i){return`${n.project.slug}-${i}`}createRegionConfig(n,i){return{...n,infrastructure:{...n.infrastructure}}}async deployStack(n,i,s){console.log(`Deploying stack ${n} to ${s}`)}generateDeploymentId(){return`deploy-${Date.now()}-${Math.random().toString(36).substring(7)}`}}var lC=new $g;class Mg{references=[];exports=new Map;addExport(n){let i=`${n.region}:${n.exportName}`;if(!this.exports.has(n.region))this.exports.set(n.region,[]);this.exports.get(n.region).push(n)}getExport(n,i){let s=this.exports.get(n);if(!s)return;return s.find((o)=>o.exportName===i)?.value}createReference(n,i,s,o){let c=`/cross-region/${n}/${s}/${o}`;return this.references.push({sourceRegion:n,targetRegion:i,resourceType:s,resourceId:o,value:c}),c}async resolveReference(n,i){let s=this.references.find((o)=>o.targetRegion===n&&o.value===i);if(!s)throw Error(`Reference not found: ${i}`);return`arn:aws:resource:${s.sourceRegion}:123456789012:${s.resourceType}/${s.resourceId}`}getReferencesForRegion(n){return this.references.filter((i)=>i.sourceRegion===n||i.targetRegion===n)}clear(){this.references=[],this.exports.clear()}}class Fg{resources=new Map;register(n){this.resources.set(n.id,n)}get(n){return this.resources.get(n)}getByType(n){return Array.from(this.resources.values()).filter((i)=>i.type===n)}getCloudFrontDistributions(){return this.getByType("cloudfront")}getRoute53HostedZones(){return this.getByType("route53")}getWAFWebACLs(){return this.getByType("waf")}remove(n){this.resources.delete(n)}clear(){this.resources.clear()}}class Ug{pairs=[];addPair(n){this.pairs.push(n)}getPairedRegion(n){let i=this.pairs.find((s)=>s.primary===n||s.secondary===n);if(!i)return;return i.primary===n?i.secondary:i.primary}getAllPairs(){return[...this.pairs]}getReplicatedPairs(){return this.pairs.filter((n)=>n.replicationConfig)}getFailoverPairs(){return this.pairs.filter((n)=>n.failoverConfig?.automatic)}arePaired(n,i){return this.pairs.some((s)=>s.primary===n&&s.secondary===i||s.primary===i&&s.secondary===n)}clear(){this.pairs=[]}}class Qg{dependencies=[];addDependency(n){this.dependencies.push(n)}getDependencies(n,i){return this.dependencies.filter((s)=>s.dependentStack===n&&s.dependentRegion===i)}getDependents(n,i){return this.dependencies.filter((s)=>s.dependsOnStack===n&&s.dependsOnRegion===i)}hasDependencies(n,i){return this.getDependencies(n,i).length>0}getDeploymentOrder(n){let i=new Set,s=[],o=(c)=>{let l=`${c.name}:${c.region}`;if(i.has(l))return;i.add(l);let u=this.getDependencies(c.name,c.region);for(let h of u)o({name:h.dependsOnStack,region:h.dependsOnRegion});s.push(c)};for(let c of n)o(c);return s}detectCircularDependencies(){let n=new Set,i=new Set,s=(o,c)=>{let l=`${o}:${c}`;if(i.has(l))return!0;if(n.has(l))return!1;n.add(l),i.add(l);let u=this.getDependencies(o,c);for(let h of u)if(s(h.dependsOnStack,h.dependsOnRegion))return!0;return i.delete(l),!1};for(let o of this.dependencies)if(s(o.dependentStack,o.dependentRegion))return!0;return!1}clear(){this.dependencies=[]}}var uC=new Mg,pC=new Fg,gC=new Ug,mC=new Qg,De=[{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 Di(n){return De.find((i)=>i.code===n)}function hC(){return De}function fC(n){let i=n.toLowerCase();return De.filter((s)=>s.location.toLowerCase().includes(i))}function AC(n){return De.filter((i)=>i.compliance.includes(n))}function yC(n){return De.filter((i)=>i.pricing.tier===n)}function IC(n){return De.some((i)=>i.code===n)}function SC(n){if(n.continent==="North America")return Di("us-east-1");if(n.continent==="Europe")return Di("eu-west-1");if(n.continent==="Asia")return Di("ap-southeast-1");return Di("us-east-1")}function CC(n){let i=[...De];if(n.compliance)i=i.filter((s)=>n.compliance.every((o)=>s.compliance.includes(o)));if(n.requiredServices)i=i.filter((s)=>n.requiredServices.every((o)=>s.services[o]));if(n.pricingSensitive)i.sort((s,o)=>s.pricing.multiplier-o.pricing.multiplier);return i.slice(0,5)}function EC(n){let i=Di(n);if(!i)throw Error(`Invalid region: ${n}`);let s=[];for(let o of De){if(o.code===n)continue;let c=jn(i,o),l=Kn(i,o);s.push({primary:i,secondary:o,distance:c,sameContinent:l})}return s.sort((o,c)=>{if(o.sameContinent!==c.sameContinent)return o.sameContinent?1:-1;return o.distance-c.distance}),s.slice(0,3)}function jn(n,i){let s={"North America":0,"South America":1,Europe:2,Asia:3,Africa:4,Oceania:5},o=at(n.location),c=at(i.location);return Math.abs((s[o]||0)-(s[c]||0))}function Kn(n,i){return at(n.location)===at(i.location)}function at(n){if(n.includes("USA")||n.includes("Canada"))return"North America";if(n.includes("Europe")||n.includes("Ireland")||n.includes("Germany"))return"Europe";if(n.includes("Asia")||n.includes("Singapore")||n.includes("Japan"))return"Asia";if(n.includes("Brazil"))return"South America";if(n.includes("Australia"))return"Oceania";return"Unknown"}function FA(n){return`${n.name} (${n.code})`}function bC(n){return n.map((i)=>FA(i)).join(`
2765
- `)}function vC(){let n={total:De.length,byContinent:{},byPricingTier:{}};for(let i of De){let s=at(i.location);n.byContinent[s]=(n.byContinent[s]||0)+1,n.byPricingTier[i.pricing.tier]=(n.byPricingTier[i.pricing.tier]||0)+1}return n}class Hg{accounts=new Map;crossAccountRoles=[];accountMappings=[];registerAccount(n){this.accounts.set(n.id,n)}getAccount(n){return this.accounts.get(n)}getAccountByAlias(n){return Array.from(this.accounts.values()).find((i)=>i.alias===n)}listAccounts(){return Array.from(this.accounts.values())}getAccountsByRole(n){return Array.from(this.accounts.values()).filter((i)=>i.role===n)}createCrossAccountRole(n,i,s,o,c){let l={roleArn:`arn:aws:iam::${i}:role/${s}`,roleName:s,sourceAccountId:n,targetAccountId:i,permissions:o,externalId:c?.externalId,sessionDuration:c?.sessionDuration||3600};return this.crossAccountRoles.push(l),l}getAssumeRolePolicyDocument(n,i){let s={Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${n}:root`},Action:"sts:AssumeRole"}]};if(i)s.Statement[0].Condition={StringEquals:{"sts:ExternalId":i}};return s}generateCrossAccountPolicy(n){return{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:n,Resource:"*"}]}}mapEnvironmentToAccount(n,i,s){this.accountMappings.push({environment:n,accountId:i,region:s})}getAccountForEnvironment(n){return this.accountMappings.find((i)=>i.environment===n)}async assumeRole(n,i,s){return console.log(`Assuming role: ${n} with session: ${i}`),{accessKeyId:"AKIAIOSFODNN7EXAMPLE",secretAccessKey:"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",sessionToken:"token",expiration:new Date(Date.now()+3600000)}}async getCredentialsForAccount(n){let i=this.accounts.get(n);if(!i)throw Error(`Account not found: ${n}`);if(i.assumeRoleArn){let s=await this.assumeRole(i.assumeRoleArn,`ts-cloud-${Date.now()}`);return{accessKeyId:s.accessKeyId,secretAccessKey:s.secretAccessKey,sessionToken:s.sessionToken}}throw Error("No credentials available for account")}listCrossAccountRoles(){return[...this.crossAccountRoles]}getCrossAccountRolesForAccount(n){return this.crossAccountRoles.filter((i)=>i.sourceAccountId===n||i.targetAccountId===n)}async validateAccountAccess(n){try{let i=await this.getCredentialsForAccount(n);return console.log(`Validating access to account: ${n}`),!0}catch{return!1}}async getConsolidatedBilling(){let n={};for(let i of this.accounts.values())n[i.id]=Math.random()*1000;return{totalCost:Object.values(n).reduce((i,s)=>i+s,0),byAccount:n}}clear(){this.accounts.clear(),this.crossAccountRoles=[],this.accountMappings=[]}}class Gg{organizationId;organizationalUnits=new Map;getOrganizationId(){return this.organizationId}setOrganizationId(n){this.organizationId=n}createOrganizationalUnit(n,i){let s={id:`ou-${Date.now()}`,name:n,parentId:i,accounts:[]};return this.organizationalUnits.set(s.id,s),s}getOrganizationalUnit(n){return this.organizationalUnits.get(n)}listOrganizationalUnits(){return Array.from(this.organizationalUnits.values())}addAccountToOU(n,i){let s=this.organizationalUnits.get(n);if(!s)throw Error(`Organizational unit not found: ${n}`);if(!s.accounts.includes(i))s.accounts.push(i)}removeAccountFromOU(n,i){let s=this.organizationalUnits.get(n);if(!s)throw Error(`Organizational unit not found: ${n}`);s.accounts=s.accounts.filter((o)=>o!==i)}getAccountsInOU(n){let i=this.organizationalUnits.get(n);if(!i)return[];return[...i.accounts]}applyServiceControlPolicy(n,i){return{id:`scp-${Date.now()}`,name:"Custom SCP",targetId:n,policyDocument:i}}clear(){this.organizationId=void 0,this.organizationalUnits.clear()}}var TC=new Hg,wC=new Gg,UA={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"}]}},RC={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"]}}}]}}},DC={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 PC(n){return UA[n]}function NC(n,i){return{Type:"AWS::IAM::Role",Properties:{RoleName:n.roleName,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${n.sourceAccountId}:root`},Action:"sts:AssumeRole",...n.externalId&&{Condition:{StringEquals:{"sts:ExternalId":n.externalId}}}}]},Policies:[{PolicyName:`${n.roleName}Policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:n.permissions,Resource:"*"}]}}],...i&&{ManagedPolicyArns:i},MaxSessionDuration:n.sessionDuration||3600,Tags:[{Key:"ManagedBy",Value:"TS-Cloud"},{Key:"SourceAccount",Value:n.sourceAccountId}]}}}function kC(n){let i=[],s=[],o=n.accounts.filter((y)=>y.role==="management");if(o.length===0)i.push("No management account defined");if(o.length>1)i.push("Multiple management accounts defined");let c=n.accounts.map((y)=>y.email),l=c.filter((y,f)=>c.indexOf(y)!==f);if(l.length>0)i.push(`Duplicate email addresses: ${l.join(", ")}`);let u=n.accounts.map((y)=>y.alias),h=u.filter((y,f)=>u.indexOf(y)!==f);if(h.length>0)i.push(`Duplicate aliases: ${h.join(", ")}`);if(!n.accounts.some((y)=>y.role==="security"))s.push("No dedicated security account - consider adding one for audit logs");if(n.accounts.length<3)s.push("Less than 3 accounts - consider separating environments");if(!n.accounts.some((y)=>y.role==="production"))s.push("No production account defined");return{valid:i.length===0,errors:i,warnings:s}}function BC(n){let i=[];if(i.push(`${n.name}`),i.push("─".repeat(n.name.length)),i.push(n.description),i.push(""),n.organizationalUnits){i.push("Organizational Units:");for(let s of n.organizationalUnits){let o=s.parent?" └─ ":" ";i.push(`${o}${s.name}`)}i.push("")}i.push("Accounts:");for(let s of n.accounts)i.push(` ${s.alias.padEnd(20)} ${s.role.padEnd(15)} ${s.email}`),i.push(` ${"".padEnd(20)} ${s.description}`),i.push("");return i.join(`
2766
- `)}function _C(n={}){let{workflowName:i="Deploy",trigger:s="push",branches:o=["main"],environments:c=["production"],awsRegion:l="us-east-1",awsRole:u,bunVersion:h="latest",deployCommand:y="bun run cloud deploy",testCommand:f="bun test",buildCommand:b="bun run build"}=n,C=!!u;return`name: ${i}
2761
+ `))}catch(n){console.error(`Failed to save history: ${n}`)}}searchHistory(n){return this.history.commands.filter((i)=>i.includes(n))}clearHistory(){this.history.commands=[],this.historyIndex=0}}class MA{variables=new Map;workingDirectory=process.cwd();set(n,i){this.variables.set(n,i)}get(n){return this.variables.get(n)}has(n){return this.variables.has(n)}delete(n){this.variables.delete(n)}getAll(){return Object.fromEntries(this.variables)}clear(){this.variables.clear()}setWorkingDirectory(n){this.workingDirectory=n}getWorkingDirectory(){return this.workingDirectory}}class FA{command={};name(n){return this.command.name=n,this}description(n){return this.command.description=n,this}aliases(...n){return this.command.aliases=n,this}handler(n){return this.command.handler=n,this}autocomplete(n){return this.command.autocomplete=n,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 UA{entries=[];maxSize;persistFile;trackOutput;constructor(n={}){this.maxSize=n.maxSize||1000,this.persistFile=n.persistFile,this.trackOutput=n.trackOutput||!1}add(n){if(this.entries.push({...n,timestamp:new Date}),this.entries.length>this.maxSize)this.entries=this.entries.slice(-this.maxSize)}getAll(){return[...this.entries]}getRecent(n=10){return this.entries.slice(-n)}search(n){let i=n.toLowerCase();return this.entries.filter((s)=>s.command.toLowerCase().includes(i))}searchByDate(n,i){return this.entries.filter((s)=>s.timestamp>=n&&s.timestamp<=i)}getSuccessful(){return this.entries.filter((n)=>n.success)}getFailed(){return this.entries.filter((n)=>!n.success)}getMostUsed(n=10){let i=new Map;for(let s of this.entries){let o=s.command.split(" ")[0];i.set(o,(i.get(o)||0)+1)}return Array.from(i.entries()).map(([s,o])=>({command:s,count:o})).sort((s,o)=>o.count-s.count).slice(0,n)}getStats(){let n=this.entries.length,i=this.entries.filter((h)=>h.success).length,s=this.entries.filter((h)=>!h.success).length,o=this.entries.filter((h)=>h.duration!==void 0),c=o.length>0?o.reduce((h,y)=>h+(y.duration||0),0)/o.length:0,l=this.getMostUsed(1),u=l.length>0?l[0].command:"N/A";return{total:n,successful:i,failed:s,averageDuration:c,mostUsed:u}}clear(){this.entries=[]}getByIndex(n){if(n<0||n>=this.entries.length)return;return this.entries[n]}removeByIndex(n){if(n>=0&&n<this.entries.length)this.entries.splice(n,1)}async save(){if(!this.persistFile)return;try{let n=await import("node:fs/promises"),i=JSON.stringify(this.entries,null,2);await n.writeFile(this.persistFile,i,"utf-8")}catch(n){throw Error(`Failed to save history: ${n}`)}}async load(){if(!this.persistFile)return;try{let n=await import("node:fs/promises"),i=await n.readFile(this.persistFile,"utf-8"),s=JSON.parse(i);this.entries=s.map((o)=>({...o,timestamp:new Date(o.timestamp)}))}catch{this.entries=[]}}exportJSON(){return JSON.stringify(this.entries,null,2)}exportCSV(){return["Timestamp,Command,Success,Duration",...this.entries.map((n)=>[n.timestamp.toISOString(),`"${n.command.replace(/"/g,'""')}"`,n.success,n.duration||""].join(","))].join(`
2762
+ `)}importJSON(n){let i=JSON.parse(n).map((s)=>({...s,timestamp:new Date(s.timestamp)}));if(this.entries.push(...i),this.entries.length>this.maxSize)this.entries=this.entries.slice(-this.maxSize)}groupByDate(){let n=new Map;for(let i of this.entries){let s=i.timestamp.toISOString().split("T")[0];if(!n.has(s))n.set(s,[]);n.get(s).push(i)}return n}groupByCommand(){let n=new Map;for(let i of this.entries){let s=i.command.split(" ")[0];if(!n.has(s))n.set(s,[]);n.get(s).push(i)}return n}replay(n){return this.getByIndex(n)?.command}getSuggestions(n,i=5){let s=n.toLowerCase(),o=this.entries.filter((c)=>c.command.toLowerCase().startsWith(s)).map((c)=>c.command);return[...new Set(o)].slice(0,i)}analyzePatterns(){let n=new Map,i=new Map;for(let o of this.entries){let c=o.timestamp.getHours(),l=o.timestamp.getDay();n.set(c,(n.get(c)||0)+1),i.set(l,(i.get(l)||0)+1)}let s=this.entries.length>0?this.getSuccessful().length/this.entries.length:0;return{timeOfDay:n,dayOfWeek:i,successRate:s}}}function lC(n,i={}){let{maxWidth:s=100}=i;if(n.length===0)return"No command history";let o=[];for(let c=0;c<n.length;c++){let l=n[c],u=(c+1).toString().padStart(4),h=l.timestamp.toLocaleString(),y=l.success?"✓":"✗",f=l.command;if(f.length>s-30)f=f.substring(0,s-33)+"...";let b=`${u} ${h} ${y} ${f}`;if(l.duration)b+=` (${l.duration}ms)`;o.push(b)}return o.join(`
2763
+ `)}function uC(n){let i=[];return i.push("Command History Statistics"),i.push("─".repeat(30)),i.push(`Total commands: ${n.total}`),i.push(`Successful: ${n.successful}`),i.push(`Failed: ${n.failed}`),i.push(`Success rate: ${(n.successful/n.total*100).toFixed(1)}%`),i.push(`Average duration: ${n.averageDuration.toFixed(0)}ms`),i.push(`Most used: ${n.mostUsed}`),i.join(`
2764
+ `)}class Fg{deployments=new Map;async deploy(n,i){let s=this.generateDeploymentId(),o={id:s,regions:i.regions.map((c)=>({region:c.code,stackName:this.getStackName(n,c.code),status:"pending"})),status:"deploying",startTime:new Date};this.deployments.set(s,o);try{let c=i.regions.find((u)=>u.isPrimary)||i.regions[0];await this.deployToRegion(n,c,o);let l=i.regions.filter((u)=>u.code!==c.code);if(await Promise.all(l.map((u)=>this.deployToRegion(n,u,o))),i.globalResources)await this.deployGlobalResources(o,i);if(i.replication)await this.setupReplication(o,i);if(i.failover?.enabled)await this.setupFailover(o,i);return o.status="deployed",o.endTime=new Date,o}catch(c){throw o.status="failed",o.endTime=new Date,c}}async deployToRegion(n,i,s){let o=s.regions.find((c)=>c.region===i.code);if(!o)throw Error(`Region deployment not found: ${i.code}`);o.status="deploying",o.startTime=new Date;try{let c=this.createRegionConfig(n,i);await this.deployStack(o.stackName,c,i.code),o.status="deployed",o.endTime=new Date,o.outputs={stackId:`arn:aws:cloudformation:${i.code}:123456789012:stack/${o.stackName}/guid`,endpoint:`https://${o.stackName}.${i.code}.example.com`}}catch(c){throw o.status="failed",o.endTime=new Date,o.error=c instanceof Error?c.message:String(c),c}}async deployGlobalResources(n,i){let s={};if(i.globalResources?.route53)s.route53=await this.deployRoute53(n,i);if(i.globalResources?.cloudfront)s.cloudfront=await this.deployCloudFront(n,i);if(i.globalResources?.waf)s.waf=await this.deployWAF(n);n.globalResources=s}async deployRoute53(n,i){let s=[],o=[];for(let c of n.regions){if(c.status!=="deployed")continue;let l={id:`health-${c.region}`,endpoint:c.outputs?.endpoint,path:i.failover?.healthCheckPath||"/health",region:c.region};s.push(l);let u={name:"example.com",type:"A",region:c.region,setIdentifier:c.region,healthCheckId:l.id,resourceRecords:[c.outputs?.endpoint]};o.push(u)}return{healthChecks:s,recordSets:o,hostedZoneId:"Z1234567890ABC"}}async deployCloudFront(n,i){return{distributionId:"E1234567890ABC",domainName:"d1234567890abc.cloudfront.net",origins:n.regions.filter((s)=>s.status==="deployed").map((s,o)=>{let c=i.regions[o];return{id:`origin-${s.region}`,domainName:s.outputs?.endpoint,weight:c?.weight||100}}),status:"Deployed"}}async deployWAF(n){return{webAclId:"arn:aws:wafv2:us-east-1:123456789012:global/webacl/test/a1234567-b890-c123-d456-e789012345f6",webAclArn:"arn:aws:wafv2:us-east-1:123456789012:global/webacl/test/a1234567-b890-c123-d456-e789012345f6"}}async setupReplication(n,i){if(i.replication?.s3)await this.setupS3Replication(n);if(i.replication?.dynamodb)await this.setupDynamoDBReplication(n);if(i.replication?.secrets)await this.setupSecretsReplication(n)}async setupS3Replication(n){let i=n.regions.filter((s)=>s.status==="deployed");for(let s=0;s<i.length-1;s++){let o=i[s],c=i[s+1];console.log(`Setting up S3 replication: ${o.region} -> ${c.region}`)}}async setupDynamoDBReplication(n){let i=n.regions.filter((s)=>s.status==="deployed").map((s)=>s.region);console.log(`Setting up DynamoDB global table in regions: ${i.join(", ")}`)}async setupSecretsReplication(n){let i=n.regions.filter((s)=>s.status==="deployed").map((s)=>s.region);console.log(`Setting up Secrets Manager replication in regions: ${i.join(", ")}`)}async setupFailover(n,i){let s=n.regions.find((c,l)=>i.regions[l]?.isPrimary)||n.regions[0],o=n.regions.filter((c)=>c.region!==s.region);console.log(`Setting up failover: primary=${s.region}, secondary=${o.map((c)=>c.region).join(", ")}`)}async destroy(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);i.status="rolling-back";try{if(i.globalResources)await this.destroyGlobalResources(i.globalResources);await Promise.all(i.regions.map((s)=>this.destroyRegionStack(s))),this.deployments.delete(n)}catch(s){throw i.status="failed",s}}async destroyGlobalResources(n){if(n.waf)console.log("Destroying WAF resources");if(n.cloudfront)console.log("Destroying CloudFront distribution");if(n.route53)console.log("Destroying Route53 resources")}async destroyRegionStack(n){if(n.status!=="deployed")return;n.status="rolling-back";try{console.log(`Destroying stack ${n.stackName} in ${n.region}`),n.status="pending"}catch(i){throw n.status="failed",n.error=i instanceof Error?i.message:String(i),i}}getDeployment(n){return this.deployments.get(n)}listDeployments(){return Array.from(this.deployments.values())}getStackName(n,i){return`${n.project.slug}-${i}`}createRegionConfig(n,i){return{...n,infrastructure:{...n.infrastructure}}}async deployStack(n,i,s){console.log(`Deploying stack ${n} to ${s}`)}generateDeploymentId(){return`deploy-${Date.now()}-${Math.random().toString(36).substring(7)}`}}var pC=new Fg;class Ug{references=[];exports=new Map;addExport(n){let i=`${n.region}:${n.exportName}`;if(!this.exports.has(n.region))this.exports.set(n.region,[]);this.exports.get(n.region).push(n)}getExport(n,i){let s=this.exports.get(n);if(!s)return;return s.find((o)=>o.exportName===i)?.value}createReference(n,i,s,o){let c=`/cross-region/${n}/${s}/${o}`;return this.references.push({sourceRegion:n,targetRegion:i,resourceType:s,resourceId:o,value:c}),c}async resolveReference(n,i){let s=this.references.find((o)=>o.targetRegion===n&&o.value===i);if(!s)throw Error(`Reference not found: ${i}`);return`arn:aws:resource:${s.sourceRegion}:123456789012:${s.resourceType}/${s.resourceId}`}getReferencesForRegion(n){return this.references.filter((i)=>i.sourceRegion===n||i.targetRegion===n)}clear(){this.references=[],this.exports.clear()}}class Qg{resources=new Map;register(n){this.resources.set(n.id,n)}get(n){return this.resources.get(n)}getByType(n){return Array.from(this.resources.values()).filter((i)=>i.type===n)}getCloudFrontDistributions(){return this.getByType("cloudfront")}getRoute53HostedZones(){return this.getByType("route53")}getWAFWebACLs(){return this.getByType("waf")}remove(n){this.resources.delete(n)}clear(){this.resources.clear()}}class Hg{pairs=[];addPair(n){this.pairs.push(n)}getPairedRegion(n){let i=this.pairs.find((s)=>s.primary===n||s.secondary===n);if(!i)return;return i.primary===n?i.secondary:i.primary}getAllPairs(){return[...this.pairs]}getReplicatedPairs(){return this.pairs.filter((n)=>n.replicationConfig)}getFailoverPairs(){return this.pairs.filter((n)=>n.failoverConfig?.automatic)}arePaired(n,i){return this.pairs.some((s)=>s.primary===n&&s.secondary===i||s.primary===i&&s.secondary===n)}clear(){this.pairs=[]}}class Gg{dependencies=[];addDependency(n){this.dependencies.push(n)}getDependencies(n,i){return this.dependencies.filter((s)=>s.dependentStack===n&&s.dependentRegion===i)}getDependents(n,i){return this.dependencies.filter((s)=>s.dependsOnStack===n&&s.dependsOnRegion===i)}hasDependencies(n,i){return this.getDependencies(n,i).length>0}getDeploymentOrder(n){let i=new Set,s=[],o=(c)=>{let l=`${c.name}:${c.region}`;if(i.has(l))return;i.add(l);let u=this.getDependencies(c.name,c.region);for(let h of u)o({name:h.dependsOnStack,region:h.dependsOnRegion});s.push(c)};for(let c of n)o(c);return s}detectCircularDependencies(){let n=new Set,i=new Set,s=(o,c)=>{let l=`${o}:${c}`;if(i.has(l))return!0;if(n.has(l))return!1;n.add(l),i.add(l);let u=this.getDependencies(o,c);for(let h of u)if(s(h.dependsOnStack,h.dependsOnRegion))return!0;return i.delete(l),!1};for(let o of this.dependencies)if(s(o.dependentStack,o.dependentRegion))return!0;return!1}clear(){this.dependencies=[]}}var gC=new Ug,mC=new Qg,hC=new Hg,fC=new Gg,Ne=[{code:"us-east-1",name:"US East (N. Virginia)",location:"Virginia, USA",launchYear:2006,availabilityZones:6,localZones:16,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"standard",multiplier:1},compliance:["PCI-DSS","HIPAA","SOC","ISO","FedRAMP"]},{code:"us-east-2",name:"US East (Ohio)",location:"Ohio, USA",launchYear:2016,availabilityZones:3,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"standard",multiplier:1},compliance:["PCI-DSS","HIPAA","SOC","ISO"]},{code:"us-west-1",name:"US West (N. California)",location:"California, USA",launchYear:2009,availabilityZones:3,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"premium",multiplier:1.1},compliance:["PCI-DSS","HIPAA","SOC","ISO"]},{code:"us-west-2",name:"US West (Oregon)",location:"Oregon, USA",launchYear:2011,availabilityZones:4,localZones:2,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"standard",multiplier:1},compliance:["PCI-DSS","HIPAA","SOC","ISO"]},{code:"eu-west-1",name:"Europe (Ireland)",location:"Dublin, Ireland",launchYear:2007,availabilityZones:3,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"standard",multiplier:1.05},compliance:["PCI-DSS","GDPR","SOC","ISO"]},{code:"eu-central-1",name:"Europe (Frankfurt)",location:"Frankfurt, Germany",launchYear:2014,availabilityZones:3,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"premium",multiplier:1.1},compliance:["PCI-DSS","GDPR","SOC","ISO"]},{code:"ap-southeast-1",name:"Asia Pacific (Singapore)",location:"Singapore",launchYear:2010,availabilityZones:3,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"premium",multiplier:1.12},compliance:["PCI-DSS","SOC","ISO","MTCS"]},{code:"ap-northeast-1",name:"Asia Pacific (Tokyo)",location:"Tokyo, Japan",launchYear:2011,availabilityZones:4,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"premium",multiplier:1.15},compliance:["PCI-DSS","SOC","ISO"]}];function Ni(n){return Ne.find((i)=>i.code===n)}function AC(){return Ne}function yC(n){let i=n.toLowerCase();return Ne.filter((s)=>s.location.toLowerCase().includes(i))}function IC(n){return Ne.filter((i)=>i.compliance.includes(n))}function SC(n){return Ne.filter((i)=>i.pricing.tier===n)}function CC(n){return Ne.some((i)=>i.code===n)}function EC(n){if(n.continent==="North America")return Ni("us-east-1");if(n.continent==="Europe")return Ni("eu-west-1");if(n.continent==="Asia")return Ni("ap-southeast-1");return Ni("us-east-1")}function bC(n){let i=[...Ne];if(n.compliance)i=i.filter((s)=>n.compliance.every((o)=>s.compliance.includes(o)));if(n.requiredServices)i=i.filter((s)=>n.requiredServices.every((o)=>s.services[o]));if(n.pricingSensitive)i.sort((s,o)=>s.pricing.multiplier-o.pricing.multiplier);return i.slice(0,5)}function vC(n){let i=Ni(n);if(!i)throw Error(`Invalid region: ${n}`);let s=[];for(let o of Ne){if(o.code===n)continue;let c=jn(i,o),l=Kn(i,o);s.push({primary:i,secondary:o,distance:c,sameContinent:l})}return s.sort((o,c)=>{if(o.sameContinent!==c.sameContinent)return o.sameContinent?1:-1;return o.distance-c.distance}),s.slice(0,3)}function jn(n,i){let s={"North America":0,"South America":1,Europe:2,Asia:3,Africa:4,Oceania:5},o=at(n.location),c=at(i.location);return Math.abs((s[o]||0)-(s[c]||0))}function Kn(n,i){return at(n.location)===at(i.location)}function at(n){if(n.includes("USA")||n.includes("Canada"))return"North America";if(n.includes("Europe")||n.includes("Ireland")||n.includes("Germany"))return"Europe";if(n.includes("Asia")||n.includes("Singapore")||n.includes("Japan"))return"Asia";if(n.includes("Brazil"))return"South America";if(n.includes("Australia"))return"Oceania";return"Unknown"}function QA(n){return`${n.name} (${n.code})`}function TC(n){return n.map((i)=>QA(i)).join(`
2765
+ `)}function wC(){let n={total:Ne.length,byContinent:{},byPricingTier:{}};for(let i of Ne){let s=at(i.location);n.byContinent[s]=(n.byContinent[s]||0)+1,n.byPricingTier[i.pricing.tier]=(n.byPricingTier[i.pricing.tier]||0)+1}return n}class qg{accounts=new Map;crossAccountRoles=[];accountMappings=[];registerAccount(n){this.accounts.set(n.id,n)}getAccount(n){return this.accounts.get(n)}getAccountByAlias(n){return Array.from(this.accounts.values()).find((i)=>i.alias===n)}listAccounts(){return Array.from(this.accounts.values())}getAccountsByRole(n){return Array.from(this.accounts.values()).filter((i)=>i.role===n)}createCrossAccountRole(n,i,s,o,c){let l={roleArn:`arn:aws:iam::${i}:role/${s}`,roleName:s,sourceAccountId:n,targetAccountId:i,permissions:o,externalId:c?.externalId,sessionDuration:c?.sessionDuration||3600};return this.crossAccountRoles.push(l),l}getAssumeRolePolicyDocument(n,i){let s={Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${n}:root`},Action:"sts:AssumeRole"}]};if(i)s.Statement[0].Condition={StringEquals:{"sts:ExternalId":i}};return s}generateCrossAccountPolicy(n){return{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:n,Resource:"*"}]}}mapEnvironmentToAccount(n,i,s){this.accountMappings.push({environment:n,accountId:i,region:s})}getAccountForEnvironment(n){return this.accountMappings.find((i)=>i.environment===n)}async assumeRole(n,i,s){return console.log(`Assuming role: ${n} with session: ${i}`),{accessKeyId:"AKIAIOSFODNN7EXAMPLE",secretAccessKey:"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",sessionToken:"token",expiration:new Date(Date.now()+3600000)}}async getCredentialsForAccount(n){let i=this.accounts.get(n);if(!i)throw Error(`Account not found: ${n}`);if(i.assumeRoleArn){let s=await this.assumeRole(i.assumeRoleArn,`ts-cloud-${Date.now()}`);return{accessKeyId:s.accessKeyId,secretAccessKey:s.secretAccessKey,sessionToken:s.sessionToken}}throw Error("No credentials available for account")}listCrossAccountRoles(){return[...this.crossAccountRoles]}getCrossAccountRolesForAccount(n){return this.crossAccountRoles.filter((i)=>i.sourceAccountId===n||i.targetAccountId===n)}async validateAccountAccess(n){try{let i=await this.getCredentialsForAccount(n);return console.log(`Validating access to account: ${n}`),!0}catch{return!1}}async getConsolidatedBilling(){let n={};for(let i of this.accounts.values())n[i.id]=Math.random()*1000;return{totalCost:Object.values(n).reduce((i,s)=>i+s,0),byAccount:n}}clear(){this.accounts.clear(),this.crossAccountRoles=[],this.accountMappings=[]}}class Vg{organizationId;organizationalUnits=new Map;getOrganizationId(){return this.organizationId}setOrganizationId(n){this.organizationId=n}createOrganizationalUnit(n,i){let s={id:`ou-${Date.now()}`,name:n,parentId:i,accounts:[]};return this.organizationalUnits.set(s.id,s),s}getOrganizationalUnit(n){return this.organizationalUnits.get(n)}listOrganizationalUnits(){return Array.from(this.organizationalUnits.values())}addAccountToOU(n,i){let s=this.organizationalUnits.get(n);if(!s)throw Error(`Organizational unit not found: ${n}`);if(!s.accounts.includes(i))s.accounts.push(i)}removeAccountFromOU(n,i){let s=this.organizationalUnits.get(n);if(!s)throw Error(`Organizational unit not found: ${n}`);s.accounts=s.accounts.filter((o)=>o!==i)}getAccountsInOU(n){let i=this.organizationalUnits.get(n);if(!i)return[];return[...i.accounts]}applyServiceControlPolicy(n,i){return{id:`scp-${Date.now()}`,name:"Custom SCP",targetId:n,policyDocument:i}}clear(){this.organizationId=void 0,this.organizationalUnits.clear()}}var RC=new qg,DC=new Vg,HA={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"}]}},PC={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"]}}}]}}},NC={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 kC(n){return HA[n]}function BC(n,i){return{Type:"AWS::IAM::Role",Properties:{RoleName:n.roleName,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${n.sourceAccountId}:root`},Action:"sts:AssumeRole",...n.externalId&&{Condition:{StringEquals:{"sts:ExternalId":n.externalId}}}}]},Policies:[{PolicyName:`${n.roleName}Policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:n.permissions,Resource:"*"}]}}],...i&&{ManagedPolicyArns:i},MaxSessionDuration:n.sessionDuration||3600,Tags:[{Key:"ManagedBy",Value:"TS-Cloud"},{Key:"SourceAccount",Value:n.sourceAccountId}]}}}function _C(n){let i=[],s=[],o=n.accounts.filter((y)=>y.role==="management");if(o.length===0)i.push("No management account defined");if(o.length>1)i.push("Multiple management accounts defined");let c=n.accounts.map((y)=>y.email),l=c.filter((y,f)=>c.indexOf(y)!==f);if(l.length>0)i.push(`Duplicate email addresses: ${l.join(", ")}`);let u=n.accounts.map((y)=>y.alias),h=u.filter((y,f)=>u.indexOf(y)!==f);if(h.length>0)i.push(`Duplicate aliases: ${h.join(", ")}`);if(!n.accounts.some((y)=>y.role==="security"))s.push("No dedicated security account - consider adding one for audit logs");if(n.accounts.length<3)s.push("Less than 3 accounts - consider separating environments");if(!n.accounts.some((y)=>y.role==="production"))s.push("No production account defined");return{valid:i.length===0,errors:i,warnings:s}}function xC(n){let i=[];if(i.push(`${n.name}`),i.push("─".repeat(n.name.length)),i.push(n.description),i.push(""),n.organizationalUnits){i.push("Organizational Units:");for(let s of n.organizationalUnits){let o=s.parent?" └─ ":" ";i.push(`${o}${s.name}`)}i.push("")}i.push("Accounts:");for(let s of n.accounts)i.push(` ${s.alias.padEnd(20)} ${s.role.padEnd(15)} ${s.email}`),i.push(` ${"".padEnd(20)} ${s.description}`),i.push("");return i.join(`
2766
+ `)}function OC(n={}){let{workflowName:i="Deploy",trigger:s="push",branches:o=["main"],environments:c=["production"],awsRegion:l="us-east-1",awsRole:u,bunVersion:h="latest",deployCommand:y="bun run cloud deploy",testCommand:f="bun test",buildCommand:b="bun run build"}=n,C=!!u;return`name: ${i}
2767
2767
 
2768
2768
  on:
2769
2769
  ${s}:
@@ -2832,7 +2832,7 @@ jobs:
2832
2832
 
2833
2833
  - name: Post-deployment tests
2834
2834
  run: bun run cloud test:smoke
2835
- `}function xC(n){let{environments:i,awsRegion:s="us-east-1",awsRole:o}=n,c=!!o;return`name: Multi-Environment Deploy
2835
+ `}function LC(n){let{environments:i,awsRegion:s="us-east-1",awsRole:o}=n,c=!!o;return`name: Multi-Environment Deploy
2836
2836
 
2837
2837
  on:
2838
2838
  push:
@@ -2888,7 +2888,7 @@ ${i.map((l,u)=>` ${u>0?"elif":"if"} [[ "\${{ github.ref }}" == "refs/he
2888
2888
 
2889
2889
  - name: Deploy
2890
2890
  run: bun run cloud deploy --env=\${{ needs.determine-environment.outputs.environment }}
2891
- `}function OC(n={}){let{awsRegion:i="us-east-1",awsRole:s,ttl:o=24}=n,c=!!s;return`name: PR Preview Environment
2891
+ `}function $C(n={}){let{awsRegion:i="us-east-1",awsRole:s,ttl:o=24}=n,c=!!s;return`name: PR Preview Environment
2892
2892
 
2893
2893
  on:
2894
2894
  pull_request:
@@ -2993,7 +2993,7 @@ jobs:
2993
2993
  bun run cloud env:preview --destroy \\
2994
2994
  --branch=\${{ github.head_ref }} \\
2995
2995
  --pr=\${{ github.event.pull_request.number }}
2996
- `}function LC(n){let{schedule:i,environment:s,awsRegion:o="us-east-1",awsRole:c}=n;return`name: Scheduled Deployment
2996
+ `}function MC(n){let{schedule:i,environment:s,awsRegion:o="us-east-1",awsRole:c}=n;return`name: Scheduled Deployment
2997
2997
 
2998
2998
  on:
2999
2999
  schedule:
@@ -3035,7 +3035,7 @@ jobs:
3035
3035
 
3036
3036
  - name: Deploy
3037
3037
  run: bun run cloud deploy --env=\${{ env.ENVIRONMENT }}
3038
- `}function $C(n){let{matrix:i,awsRole:s}=n,o=!!s;return`name: Matrix Deployment
3038
+ `}function FC(n){let{matrix:i,awsRole:s}=n,o=!!s;return`name: Matrix Deployment
3039
3039
 
3040
3040
  on:
3041
3041
  workflow_dispatch:
@@ -3082,7 +3082,7 @@ ${i.map((c)=>` - environment: ${c.environment}
3082
3082
 
3083
3083
  - name: Deploy to \${{ matrix.environment }} (\${{ matrix.region }})
3084
3084
  run: bun run cloud deploy --env=\${{ matrix.environment }} --region=\${{ matrix.region }}
3085
- `}function MC(n={}){let{stages:i=["test","build","deploy"],environments:s=["production"],awsRegion:o="us-east-1",dockerImage:c="oven/bun:latest",deployCommand:l="bun run cloud deploy",testCommand:u="bun test",buildCommand:h="bun run build"}=n;return`stages:
3085
+ `}function UC(n={}){let{stages:i=["test","build","deploy"],environments:s=["production"],awsRegion:o="us-east-1",dockerImage:c="oven/bun:latest",deployCommand:l="bun run cloud deploy",testCommand:u="bun test",buildCommand:h="bun run build"}=n;return`stages:
3086
3086
  ${i.map((y)=>` - ${y}`).join(`
3087
3087
  `)}
3088
3088
 
@@ -3130,7 +3130,7 @@ deploy:
3130
3130
  only:
3131
3131
  - main
3132
3132
  when: manual
3133
- `}function FC(n){let{environments:i,awsRegion:s="us-east-1"}=n,o=i.map((c)=>`
3133
+ `}function QC(n){let{environments:i,awsRegion:s="us-east-1"}=n,o=i.map((c)=>`
3134
3134
  deploy:${c.name}:
3135
3135
  stage: deploy
3136
3136
  script:
@@ -3171,7 +3171,7 @@ build:
3171
3171
  paths:
3172
3172
  - dist/
3173
3173
  ${o}
3174
- `}function UC(n={}){let{awsRegion:i="us-east-1",ttl:s=24}=n;return`stages:
3174
+ `}function HC(n={}){let{awsRegion:i="us-east-1",ttl:s=24}=n;return`stages:
3175
3175
  - build
3176
3176
  - deploy
3177
3177
  - cleanup
@@ -3216,7 +3216,7 @@ cleanup:preview:
3216
3216
  when: manual
3217
3217
  only:
3218
3218
  - merge_requests
3219
- `}function QC(n){let{environment:i,awsRegion:s="us-east-1"}=n;return`stages:
3219
+ `}function GC(n){let{environment:i,awsRegion:s="us-east-1"}=n;return`stages:
3220
3220
  - deploy
3221
3221
 
3222
3222
  variables:
@@ -3235,7 +3235,7 @@ deploy:scheduled:
3235
3235
  name: \${ENVIRONMENT}
3236
3236
  only:
3237
3237
  - schedules
3238
- `}function HC(n){let{environments:i,awsRegion:s="us-east-1"}=n,o=i.map((c)=>`
3238
+ `}function qC(n){let{environments:i,awsRegion:s="us-east-1"}=n,o=i.map((c)=>`
3239
3239
  deploy:${c}:
3240
3240
  stage: deploy
3241
3241
  script:
@@ -3256,7 +3256,7 @@ variables:
3256
3256
  default:
3257
3257
  image: oven/bun:latest
3258
3258
  ${o}
3259
- `}function GC(n={}){let{awsRegion:i="us-east-1",dockerImage:s="oven/bun:latest",deployCommand:o="bun run cloud deploy",testCommand:c="bun test",buildCommand:l="bun run build",workflows:u=!0}=n;return`version: 2.1
3259
+ `}function VC(n={}){let{awsRegion:i="us-east-1",dockerImage:s="oven/bun:latest",deployCommand:o="bun run cloud deploy",testCommand:c="bun test",buildCommand:l="bun run build",workflows:u=!0}=n;return`version: 2.1
3260
3260
 
3261
3261
  orbs:
3262
3262
  aws-cli: circleci/aws-cli@4.0
@@ -3339,7 +3339,7 @@ ${u?`workflows:
3339
3339
  branches:
3340
3340
  only: main
3341
3341
  `:""}
3342
- `}function qC(n){let{environments:i,awsRegion:s="us-east-1"}=n,o=i.map((l)=>`
3342
+ `}function jC(n){let{environments:i,awsRegion:s="us-east-1"}=n,o=i.map((l)=>`
3343
3343
  deploy-${l.name}:
3344
3344
  executor: bun-executor
3345
3345
  steps:
@@ -3415,7 +3415,7 @@ workflows:
3415
3415
  requires:
3416
3416
  - test
3417
3417
  ${c}
3418
- `}function VC(n){let{schedule:i,environment:s,awsRegion:o="us-east-1"}=n;return`version: 2.1
3418
+ `}function zC(n){let{schedule:i,environment:s,awsRegion:o="us-east-1"}=n;return`version: 2.1
3419
3419
 
3420
3420
  orbs:
3421
3421
  aws-cli: circleci/aws-cli@4.0
@@ -3452,7 +3452,7 @@ workflows:
3452
3452
  only: main
3453
3453
  jobs:
3454
3454
  - deploy
3455
- `}function jC(n){let{environments:i,awsRegion:s="us-east-1"}=n,o=i.map((l)=>`
3455
+ `}function KC(n){let{environments:i,awsRegion:s="us-east-1"}=n,o=i.map((l)=>`
3456
3456
  deploy-${l}:
3457
3457
  executor: bun-executor
3458
3458
  steps:
@@ -3528,7 +3528,7 @@ workflows:
3528
3528
  requires:
3529
3529
  - test
3530
3530
  ${c}
3531
- `}function zC(n){let{regions:i,environment:s}=n,o=i.map((l)=>`
3531
+ `}function WC(n){let{regions:i,environment:s}=n,o=i.map((l)=>`
3532
3532
  deploy-${l.replace(/-/g,"_")}:
3533
3533
  executor: bun-executor
3534
3534
  environment:
@@ -3597,7 +3597,7 @@ workflows:
3597
3597
  requires:
3598
3598
  - test
3599
3599
  ${c}
3600
- `}class qg{backupPlans=new Map;backupVaults=new Map;restoreJobs=new Map;continuousBackups=new Map;planCounter=0;restoreCounter=0;continuousBackupCounter=0;createVault(n){this.backupVaults.set(n.name,n)}getVault(n){return this.backupVaults.get(n)}createBackupPlan(n){let i=`backup-plan-${Date.now()}-${this.planCounter++}`,s={id:i,...n};return this.backupPlans.set(i,s),s}getBackupPlan(n){return this.backupPlans.get(n)}listBackupPlans(){return Array.from(this.backupPlans.values())}createRDSBackupPlan(n){let{dbInstanceArn:i,schedule:s="0 2 * * *",retentionDays:o=7,vaultName:c="default-vault"}=n;return this.createBackupPlan({name:"RDS Daily Backup",schedule:s,retentionDays:o,vaultName:c,resources:[{resourceArn:i,resourceType:"rds",region:"us-east-1"}],lifecycle:{moveTocoldStorageAfterDays:30,deleteAfterDays:o}})}createDynamoDBBackupPlan(n){let{tableArn:i,schedule:s="0 3 * * *",retentionDays:o=35,crossRegionCopy:c}=n;return this.createBackupPlan({name:"DynamoDB Daily Backup",schedule:s,retentionDays:o,vaultName:"dynamodb-vault",resources:[{resourceArn:i,resourceType:"dynamodb",region:"us-east-1"}],lifecycle:{deleteAfterDays:o},tags:c?{CrossRegionCopy:c.join(",")}:void 0})}createEFSBackupPlan(n){let{fileSystemArn:i,schedule:s="0 1 * * *",retentionDays:o=30}=n;return this.createBackupPlan({name:"EFS Daily Backup",schedule:s,retentionDays:o,vaultName:"efs-vault",resources:[{resourceArn:i,resourceType:"efs",region:"us-east-1"}],lifecycle:{deleteAfterDays:o}})}enableContinuousBackup(n,i=35){let s=`continuous-backup-${Date.now()}-${this.continuousBackupCounter++}`,o={id:s,resourceId:n,enabled:!0,retentionDays:i};return this.continuousBackups.set(s,o),o}getContinuousBackup(n){return this.continuousBackups.get(n)}enablePointInTimeRecovery(n,i){return{enabled:!0,earliestRestorableTime:new Date(Date.now()-604800000),latestRestorableTime:new Date}}async restoreFromBackup(n){let{backupId:i,resourceType:s,targetRegion:o}=n,c={id:`restore-${Date.now()}-${this.restoreCounter++}`,backupId:i,resourceType:s,status:"pending",startTime:new Date,targetRegion:o};return this.restoreJobs.set(c.id,c),setTimeout(()=>{c.status="running"},100),setTimeout(()=>{c.status="completed",c.endTime=new Date},1000),c}async restoreToPointInTime(n){let{sourceResourceArn:i,targetResourceName:s,restoreTime:o,resourceType:c}=n,l={id:`pitr-${Date.now()}-${this.restoreCounter++}`,backupId:`pitr-${o.getTime()}`,resourceType:c,status:"pending",startTime:new Date};return this.restoreJobs.set(l.id,l),console.log(`Restoring ${c} from ${i} to ${s} at ${o.toISOString()}`),setTimeout(()=>{l.status="completed",l.endTime=new Date},2000),l}getRestoreJob(n){return this.restoreJobs.get(n)}listRestoreJobs(){return Array.from(this.restoreJobs.values())}setupCrossRegionReplication(n){let{sourceVault:i,sourceRegion:s,targetRegions:o}=n;console.log("Setting up cross-region replication:"),console.log(` Source: ${i} in ${s}`),console.log(` Targets: ${o.join(", ")}`)}generateBackupVaultCF(n){return{Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:n.name,...n.encryptionKeyArn&&{EncryptionKeyArn:n.encryptionKeyArn},...n.accessPolicy&&{AccessPolicy:n.accessPolicy}}}}generateBackupPlanCF(n){return{Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:n.name,BackupPlanRule:[{RuleName:"DailyBackup",TargetBackupVault:n.vaultName,ScheduleExpression:`cron(${n.schedule})`,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:n.lifecycle?{...n.lifecycle.moveTocoldStorageAfterDays&&{MoveToColdStorageAfterDays:n.lifecycle.moveTocoldStorageAfterDays},...n.lifecycle.deleteAfterDays&&{DeleteAfterDays:n.lifecycle.deleteAfterDays}}:void 0}]},...n.tags&&{BackupPlanTags:n.tags}}}}generateBackupSelectionCF(n){return{Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:{Ref:`BackupPlan${n.id}`},BackupSelection:{SelectionName:`${n.name}Selection`,IamRoleArn:"arn:aws:iam::123456789012:role/service-role/AWSBackupDefaultServiceRole",Resources:n.resources.map((i)=>i.resourceArn)}}}}clear(){this.backupPlans.clear(),this.backupVaults.clear(),this.restoreJobs.clear(),this.continuousBackups.clear(),this.planCounter=0,this.restoreCounter=0,this.continuousBackupCounter=0}}var KC=new qg;class Vg{drPlans=new Map;failoverTests=new Map;planCounter=0;testCounter=0;createDRPlan(n){let i=`dr-plan-${Date.now()}-${this.planCounter++}`,s={id:i,...n};return this.drPlans.set(i,s),s}createRDSDRPlan(n){let{primaryDbArn:i,secondaryDbArn:s,primaryRegion:o,secondaryRegion:c,rto:l=60,rpo:u=5}=n;return this.createDRPlan({name:"RDS Multi-Region DR",primaryRegion:o,secondaryRegion:c,rto:l,rpo:u,resources:[{resourceId:"primary-db",resourceType:"rds",primaryArn:i,secondaryArn:s,replicationEnabled:!0}],runbook:this.generateRDSRunbook(o,c),testSchedule:"0 0 1 * *"})}createDynamoDBDRPlan(n){let{tableArn:i,regions:s,rto:o=15,rpo:c=1}=n;return this.createDRPlan({name:"DynamoDB Global Tables DR",primaryRegion:s[0],secondaryRegion:s[1],rto:o,rpo:c,resources:[{resourceId:"dynamodb-table",resourceType:"dynamodb",primaryArn:i,replicationEnabled:!0}],runbook:this.generateDynamoDBRunbook(s)})}generateRDSRunbook(n,i){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 "+n,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 "+i,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(n){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(n,i=!1){let s=this.drPlans.get(n);if(!s)throw Error(`DR plan not found: ${n}`);let o=Date.now(),c=0;console.log(`${i?"[DRY RUN] ":""}Executing failover for plan: ${s.name}`),console.log(`Primary: ${s.primaryRegion} -> Secondary: ${s.secondaryRegion}`),console.log(`RTO: ${s.rto} minutes, RPO: ${s.rpo} minutes`),console.log("");for(let l of s.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`),i)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()-o)/1000/60,completedSteps:c}}scheduleFailoverTest(n,i){let s={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:n,status:"scheduled",startTime:i};return this.failoverTests.set(s.id,s),s}async runFailoverTest(n){let i=this.drPlans.get(n);if(!i)throw Error(`DR plan not found: ${n}`);let s={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:n,status:"running",startTime:new Date,results:[]};this.failoverTests.set(s.id,s),console.log(`Running failover test for plan: ${i.name}`),console.log("This is a non-destructive test using test resources"),console.log("");for(let o of i.runbook.steps){let c=Date.now();console.log(`Testing step ${o.order}: ${o.name}`);let l={step:o.name,status:"success",duration:(Date.now()-c)/1000,message:`Successfully validated step ${o.order}`};s.results.push(l)}return s.status="completed",s.endTime=new Date,s}getDRPlan(n){return this.drPlans.get(n)}listDRPlans(){return Array.from(this.drPlans.values())}getFailoverTest(n){return this.failoverTests.get(n)}listFailoverTests(){return Array.from(this.failoverTests.values())}validateDRPlan(n){let i=[],s=[];if(n.rto<n.rpo)s.push("RTO cannot be less than RPO");if(n.rto>240)i.push("RTO exceeds 4 hours - consider improving recovery time");if(n.rpo>60)i.push("RPO exceeds 1 hour - consider more frequent backups");if(n.resources.length===0)s.push("No resources defined in DR plan");for(let l of n.resources){if(!l.replicationEnabled)i.push(`Resource ${l.resourceId} does not have replication enabled`);if(!l.secondaryArn&&l.resourceType!=="dynamodb")i.push(`Resource ${l.resourceId} does not have secondary resource defined`)}if(n.runbook.steps.length===0)s.push("No recovery steps defined in runbook");let o=n.runbook.steps.reduce((l,u)=>l+u.estimatedDuration,0);if(o>n.rto)i.push(`Estimated recovery duration (${o}m) exceeds RTO (${n.rto}m)`);let c=n.runbook.steps.filter((l)=>!l.automatable);if(c.length>0)i.push(`${c.length} manual steps in runbook - consider automation`);return{valid:s.length===0,warnings:i,errors:s}}clear(){this.drPlans.clear(),this.failoverTests.clear(),this.planCounter=0,this.testCounter=0}}var WC=new Vg;class jg{configRules=new Map;configRecorders=new Map;deliveryChannels=new Map;ruleCounter=0;createConfigRecorder(n){return this.configRecorders.set(n.name,n),n}createDeliveryChannel(n){return this.deliveryChannels.set(n.name,n),n}createConfigRule(n){let i=`config-rule-${Date.now()}-${this.ruleCounter++}`,s={id:i,...n};return this.configRules.set(i,s),s}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(n=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:n},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(n){return this.createConfigRule({name:n.name,description:n.description,source:"CUSTOM_LAMBDA",lambdaFunctionArn:n.lambdaFunctionArn,scope:n.resourceTypes?{complianceResourceTypes:n.resourceTypes}:void 0,maxExecutionFrequency:n.maxExecutionFrequency,inputParameters:n.inputParameters})}createCompliancePreset(n){let i=[];switch(n){case"hipaa":i.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createRdsBackupRule(7),this.createVpcFlowLogsRule());break;case"pci-dss":i.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createIamMfaRule(),this.createRootAccountMfaRule(),this.createVpcFlowLogsRule());break;case"sox":i.push(this.createS3VersioningRule(),this.createCloudTrailEnabledRule(),this.createRdsBackupRule(30),this.createIamPasswordPolicyRule());break;case"gdpr":i.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createRdsSnapshotEncryptionRule());break;case"basic":i.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamMfaRule(),this.createRootAccountMfaRule());break}return i}getConfigRule(n){return this.configRules.get(n)}listConfigRules(){return Array.from(this.configRules.values())}getConfigRecorder(n){return this.configRecorders.get(n)}listConfigRecorders(){return Array.from(this.configRecorders.values())}getDeliveryChannel(n){return this.deliveryChannels.get(n)}listDeliveryChannels(){return Array.from(this.deliveryChannels.values())}generateConfigRuleCF(n){let i={Type:"AWS::Config::ConfigRule",Properties:{ConfigRuleName:n.name,Description:n.description,Source:{Owner:n.source==="AWS_MANAGED"?"AWS":"CUSTOM_LAMBDA"}}};if(n.source==="AWS_MANAGED"&&n.identifier)i.Properties.Source.SourceIdentifier=n.identifier;if(n.source==="CUSTOM_LAMBDA"&&n.lambdaFunctionArn)i.Properties.Source.SourceIdentifier=n.lambdaFunctionArn,i.Properties.Source.SourceDetails=[{EventSource:"aws.config",MessageType:"ConfigurationItemChangeNotification"}];if(n.inputParameters)i.Properties.InputParameters=JSON.stringify(n.inputParameters);if(n.scope){if(i.Properties.Scope={},n.scope.complianceResourceTypes)i.Properties.Scope.ComplianceResourceTypes=n.scope.complianceResourceTypes;if(n.scope.tagKey)i.Properties.Scope.TagKey=n.scope.tagKey;if(n.scope.tagValue)i.Properties.Scope.TagValue=n.scope.tagValue}if(n.maxExecutionFrequency)i.Properties.MaximumExecutionFrequency=n.maxExecutionFrequency;return i}generateConfigRecorderCF(n){return{Type:"AWS::Config::ConfigurationRecorder",Properties:{Name:n.name,RoleArn:n.roleArn,RecordingGroup:n.recordingGroup||{AllSupported:!0,IncludeGlobalResourceTypes:!0}}}}generateDeliveryChannelCF(n){return{Type:"AWS::Config::DeliveryChannel",Properties:{Name:n.name,S3BucketName:n.s3BucketName,...n.s3KeyPrefix&&{S3KeyPrefix:n.s3KeyPrefix},...n.snsTopicArn&&{SnsTopicARN:n.snsTopicArn},...n.configSnapshotDeliveryProperties&&{ConfigSnapshotDeliveryProperties:n.configSnapshotDeliveryProperties}}}}clear(){this.configRules.clear(),this.configRecorders.clear(),this.deliveryChannels.clear(),this.ruleCounter=0}}var JC=new jg;class zg{trails=new Map;trailCounter=0;createTrail(n){let i=`trail-${Date.now()}-${this.trailCounter++}`,s={id:i,...n};return this.trails.set(i,s),s}createOrganizationTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,s3KeyPrefix:"organization-trail",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:n.kmsKeyId,cloudWatchLogsLogGroupArn:n.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:n.cloudWatchLogsRoleArn})}createSecurityAuditTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,s3KeyPrefix:"security-audit",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:n.kmsKeyId,cloudWatchLogsLogGroupArn:n.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:n.cloudWatchLogsRoleArn,eventSelectors:[{readWriteType:"All",includeManagementEvents:!0,excludeManagementEventSources:[]}],insightSelectors:[{insightType:"ApiCallRateInsight"},{insightType:"ApiErrorRateInsight"}]})}createDataEventsTrail(n){let i=[];if(n.s3DataBuckets&&n.s3DataBuckets.length>0)i.push({type:"AWS::S3::Object",values:n.s3DataBuckets.map((s)=>`arn:aws:s3:::${s}/*`)});if(n.lambdaFunctions&&n.lambdaFunctions.length>0)i.push({type:"AWS::Lambda::Function",values:n.lambdaFunctions});return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,s3KeyPrefix:"data-events",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"All",includeManagementEvents:!1,dataResources:i}]})}createAdvancedTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,advancedEventSelectors:n.selectors})}createReadOnlyTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"ReadOnly",includeManagementEvents:!0}]})}createWriteOnlyTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"WriteOnly",includeManagementEvents:!0}]})}getTrail(n){return this.trails.get(n)}listTrails(){return Array.from(this.trails.values())}generateTrailCF(n){let i={Type:"AWS::CloudTrail::Trail",Properties:{TrailName:n.name,S3BucketName:n.s3BucketName,IsLogging:!0,IncludeGlobalServiceEvents:n.includeGlobalServiceEvents??!0,IsMultiRegionTrail:n.isMultiRegionTrail??!0,EnableLogFileValidation:n.enableLogFileValidation??!0}};if(n.s3KeyPrefix)i.Properties.S3KeyPrefix=n.s3KeyPrefix;if(n.cloudWatchLogsLogGroupArn)i.Properties.CloudWatchLogsLogGroupArn=n.cloudWatchLogsLogGroupArn;if(n.cloudWatchLogsRoleArn)i.Properties.CloudWatchLogsRoleArn=n.cloudWatchLogsRoleArn;if(n.snsTopicName)i.Properties.SnsTopicName=n.snsTopicName;if(n.kmsKeyId)i.Properties.KMSKeyId=n.kmsKeyId;if(n.eventSelectors)i.Properties.EventSelectors=n.eventSelectors.map((s)=>({ReadWriteType:s.readWriteType,IncludeManagementEvents:s.includeManagementEvents??!0,...s.dataResources&&{DataResources:s.dataResources.map((o)=>({Type:o.type,Values:o.values}))},...s.excludeManagementEventSources&&{ExcludeManagementEventSources:s.excludeManagementEventSources}}));if(n.insightSelectors)i.Properties.InsightSelectors=n.insightSelectors.map((s)=>({InsightType:s.insightType}));if(n.advancedEventSelectors)i.Properties.AdvancedEventSelectors=n.advancedEventSelectors.map((s)=>({Name:s.name,FieldSelectors:s.fieldSelectors.map((o)=>({Field:o.field,...o.equals&&{Equals:o.equals},...o.startsWith&&{StartsWith:o.startsWith},...o.endsWith&&{EndsWith:o.endsWith},...o.notEquals&&{NotEquals:o.notEquals},...o.notStartsWith&&{NotStartsWith:o.notStartsWith},...o.notEndsWith&&{NotEndsWith:o.notEndsWith}}))}));return i}generateBucketPolicy(n,i){return{Version:"2012-10-17",Statement:[{Sid:"AWSCloudTrailAclCheck",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:GetBucketAcl",Resource:`arn:aws:s3:::${n}`},{Sid:"AWSCloudTrailWrite",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:PutObject",Resource:i.map((s)=>`arn:aws:s3:::${n}/AWSLogs/${s}/*`),Condition:{StringEquals:{"s3:x-amz-acl":"bucket-owner-full-control"}}}]}}clear(){this.trails.clear(),this.trailCounter=0}}var XC=new zg;class Kg{detectors=new Map;threatIntelSets=new Map;ipSets=new Map;filters=new Map;detectorCounter=0;threatIntelCounter=0;ipSetCounter=0;filterCounter=0;createDetector(n){let i=`detector-${Date.now()}-${this.detectorCounter++}`,s={id:i,...n};return this.detectors.set(i,s),s}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(n){let i=`threat-intel-${Date.now()}-${this.threatIntelCounter++}`,s={id:i,...n};return this.threatIntelSets.set(i,s),s}createIPSet(n){let i=`ip-set-${Date.now()}-${this.ipSetCounter++}`,s={id:i,...n};return this.ipSets.set(i,s),s}createFindingFilter(n){let i=`filter-${Date.now()}-${this.filterCounter++}`,s={id:i,...n};return this.filters.set(i,s),s}createLowSeverityArchiveFilter(n){return this.createFindingFilter({detectorId:n,name:"archive-low-severity",description:"Automatically archive low severity findings",action:"ARCHIVE",rank:1,findingCriteria:{criterion:{severity:{lt:4}}}})}createFindingTypeFilter(n,i,s){return this.createFindingFilter({detectorId:n,name:`filter-finding-types-${s.toLowerCase()}`,description:`${s==="ARCHIVE"?"Archive":"Keep"} specific finding types`,action:s,rank:2,findingCriteria:{criterion:{type:{eq:i}}}})}createTrustedIPFilter(n,i){return this.createFindingFilter({detectorId:n,name:"trusted-ip-addresses",description:"Archive findings from trusted IP addresses",action:"ARCHIVE",rank:3,findingCriteria:{criterion:{"resource.instanceDetails.networkInterfaces.privateIpAddress":{eq:i}}}})}getDetector(n){return this.detectors.get(n)}listDetectors(){return Array.from(this.detectors.values())}getThreatIntelSet(n){return this.threatIntelSets.get(n)}listThreatIntelSets(){return Array.from(this.threatIntelSets.values())}getIPSet(n){return this.ipSets.get(n)}listIPSets(){return Array.from(this.ipSets.values())}getFindingFilter(n){return this.filters.get(n)}listFindingFilters(){return Array.from(this.filters.values())}generateDetectorCF(n){let i={Type:"AWS::GuardDuty::Detector",Properties:{Enable:n.enable}};if(n.findingPublishingFrequency)i.Properties.FindingPublishingFrequency=n.findingPublishingFrequency;if(n.dataSources){if(i.Properties.DataSources={},n.dataSources.s3Logs)i.Properties.DataSources.S3Logs={Enable:n.dataSources.s3Logs.enable};if(n.dataSources.kubernetes)i.Properties.DataSources.Kubernetes={AuditLogs:{Enable:n.dataSources.kubernetes.auditLogs.enable}};if(n.dataSources.malwareProtection)i.Properties.DataSources.MalwareProtection={ScanEc2InstanceWithFindings:{EbsVolumes:{Enable:n.dataSources.malwareProtection.scanEc2InstanceWithFindings.ebsVolumes.enable}}}}if(n.features)i.Properties.Features=n.features.map((s)=>({Name:s.name,Status:s.status,...s.additionalConfiguration&&{AdditionalConfiguration:s.additionalConfiguration}}));return i}generateThreatIntelSetCF(n){return{Type:"AWS::GuardDuty::ThreatIntelSet",Properties:{DetectorId:n.detectorId,Name:n.name,Format:n.format,Location:n.location,Activate:n.activate}}}generateIPSetCF(n){return{Type:"AWS::GuardDuty::IPSet",Properties:{DetectorId:n.detectorId,Name:n.name,Format:n.format,Location:n.location,Activate:n.activate}}}generateFilterCF(n){return{Type:"AWS::GuardDuty::Filter",Properties:{DetectorId:n.detectorId,Name:n.name,Description:n.description,Action:n.action,Rank:n.rank,FindingCriteria:{Criterion:n.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 YC=new Kg;class qr{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(n){let i=`hub-${Date.now()}-${this.hubCounter++}`,s={id:i,...n};return this.hubs.set(i,s),s}createComprehensiveHub(){return this.createHub({enable:!0,controlFindingGenerator:"SECURITY_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...qr.Standards.AWS_FOUNDATIONAL_SECURITY,enabled:!0},{id:"cis-1-4",...qr.Standards.CIS_AWS_FOUNDATIONS_1_4,enabled:!0},{id:"pci-dss",...qr.Standards.PCI_DSS,enabled:!0}]})}createBasicHub(){return this.createHub({enable:!0,controlFindingGenerator:"STANDARD_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...qr.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(n){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:n.map((i)=>({value:i,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(n,i){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:`Suppress False Positives - ${n}`,description:`Automatically suppress known false positives from ${n}`,actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"SUPPRESSED"},note:{text:"Known false positive - automatically suppressed",updatedBy:"SecurityHub Automation"}}}],criteria:{productName:[{value:n,comparison:"EQUALS"}],title:i.map((s)=>({value:s,comparison:"PREFIX"}))},ruleStatus:"ENABLED",ruleOrder:10}}getHub(n){return this.hubs.get(n)}listHubs(){return Array.from(this.hubs.values())}generateHubCF(n){let i={Type:"AWS::SecurityHub::Hub",Properties:{}};if(n.controlFindingGenerator)i.Properties.ControlFindingGenerator=n.controlFindingGenerator;if(n.enableDefaultStandards!==void 0)i.Properties.EnableDefaultStandards=n.enableDefaultStandards;return i}generateStandardCF(n){let i={Type:"AWS::SecurityHub::Standard",Properties:{StandardsArn:n.arn}};if(n.disabledControls&&n.disabledControls.length>0)i.Properties.DisabledStandardsControls=n.disabledControls.map((s)=>({StandardsControlArn:s,Reason:"Disabled by configuration"}));return i}generateAutomationRuleCF(n){return{Type:"AWS::SecurityHub::AutomationRule",Properties:{RuleName:n.ruleName,Description:n.description,Actions:n.actions.map((i)=>({Type:i.type,FindingFieldsUpdate:i.findingFieldsUpdate})),Criteria:n.criteria,RuleStatus:n.ruleStatus,RuleOrder:n.ruleOrder}}}clear(){this.hubs.clear(),this.hubCounter=0,this.ruleCounter=0}}var ZC=new qr;class Wg{deployments=new Map;deploymentHistory=new Map;deploymentCounter=0;resultCounter=0;createDeployment(n){let i=`bg-deployment-${Date.now()}-${this.deploymentCounter++}`,s={id:i,...n};return this.deployments.set(i,s),s}createALBDeployment(n){return this.createDeployment({name:n.name,blueEnvironment:{name:"blue",targetGroupArn:n.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:n.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:n.listenerArn,switchoverTimeSeconds:0},autoPromote:n.autoPromote,healthCheckConfig:n.healthCheckConfig})}createRoute53Deployment(n){return this.createDeployment({name:n.name,blueEnvironment:{name:"blue",targetGroupArn:n.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:n.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"route53",hostedZoneId:n.hostedZoneId,switchoverTimeSeconds:n.switchoverTimeSeconds||60}})}createECSDeployment(n){return this.createDeployment({name:n.name,blueEnvironment:{name:"blue",targetGroupArn:n.blueTargetGroupArn,taskDefinitionArn:n.blueTaskDefinitionArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:n.greenTargetGroupArn,taskDefinitionArn:n.greenTaskDefinitionArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:n.listenerArn},autoRollback:n.autoRollback??!0})}async executeDeployment(n,i=!1){let s=this.deployments.get(n);if(!s)throw Error(`Deployment not found: ${n}`);let o={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!1,errors:[]};console.log(`${i?"[DRY RUN] ":""}Starting blue/green deployment: ${s.name}`),console.log(` Active environment: ${s.activeEnvironment}`),console.log(` Routing type: ${s.routingConfig.type}`);let c=s.activeEnvironment==="blue"?"green":"blue";if(console.log(` Switching to: ${c}`),console.log(`\\n1. Deploying to ${c} environment`),!i)await new Promise((l)=>setTimeout(l,100));if(console.log(`\\n2. Running health checks on ${c} environment`),s.healthCheckConfig){let l=await this.runHealthChecks(s,c,i);if(o.healthChecksPassed=l,!l){if(o.errors?.push("Health checks failed"),o.endTime=new Date,s.autoRollback)console.log(" Auto-rollback enabled - keeping current environment active"),o.rolledBackAt=new Date;return this.recordDeployment(n,o),o}}else o.healthChecksPassed=!0;if(console.log(`\\n3. Switching traffic to ${c} environment`),!i)s.activeEnvironment=c,o.switchedAt=new Date;if(console.log(`\\n4. Monitoring ${c} environment`),!i)await new Promise((l)=>setTimeout(l,100));return o.success=!0,o.endTime=new Date,console.log("\\n✓ Deployment completed successfully"),this.recordDeployment(n,o),o}async rollback(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);let s={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!0,errors:[]};console.log(`Rolling back deployment: ${i.name}`);let o=i.activeEnvironment==="blue"?"green":"blue";return i.activeEnvironment=o,s.success=!0,s.rolledBackAt=new Date,s.endTime=new Date,console.log(` Switched back to: ${o}`),this.recordDeployment(n,s),s}async runHealthChecks(n,i,s){let o=n.healthCheckConfig;if(console.log(` Health check path: ${o.path||"/"}`),console.log(` Healthy threshold: ${o.healthyThreshold}`),console.log(` Interval: ${o.interval}s`),s)return console.log(" [SKIPPED - DRY RUN]"),!0;let c=0,l=o.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}/${o.healthyThreshold})`),c>=o.healthyThreshold)return!0}else c=0,console.log(` Check ${u+1}: ✗ Unhealthy`);return!1}recordDeployment(n,i){if(!this.deploymentHistory.has(n))this.deploymentHistory.set(n,[]);this.deploymentHistory.get(n).push(i)}getDeployment(n){return this.deployments.get(n)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(n){return this.deploymentHistory.get(n)||[]}generateALBListenerCF(n){let i=n.activeEnvironment==="blue"?n.blueEnvironment:n.greenEnvironment;return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:n.routingConfig.listenerArn,Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",TargetGroupArn:i.targetGroupArn}]}}}generateRoute53RecordSetCF(n,i){return[{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.routingConfig.hostedZoneId,Name:i,Type:"A",SetIdentifier:"blue",Weight:n.activeEnvironment==="blue"?100:0,AliasTarget:{HostedZoneId:n.routingConfig.hostedZoneId,DNSName:n.blueEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}},{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.routingConfig.hostedZoneId,Name:i,Type:"A",SetIdentifier:"green",Weight:n.activeEnvironment==="green"?100:0,AliasTarget:{HostedZoneId:n.routingConfig.hostedZoneId,DNSName:n.greenEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}}]}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var eE=new Wg;class ho{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(n){let i=`canary-${Date.now()}-${this.deploymentCounter++}`,s={id:i,...n};return this.deployments.set(i,s),s}createLambdaCanaryDeployment(n){let i=n.strategy||"BALANCED",s=ho.Strategies[i].map((o)=>({...o,alarmThresholds:{errorRate:n.errorRateThreshold||1,latencyP99:n.latencyThreshold||1000}}));return this.createDeployment({name:n.name,baselineVersion:{version:"baseline",functionVersionArn:n.baselineVersionArn,weight:100},canaryVersion:{version:"canary",functionVersionArn:n.canaryVersionArn,weight:0},stages:s,currentStage:0,status:"pending",autoPromote:n.autoPromote??!0,autoRollback:!0})}createECSCanaryDeployment(n){let i=n.strategy||"CONSERVATIVE",s=ho.Strategies[i];return this.createDeployment({name:n.name,baselineVersion:{version:"baseline",taskDefinitionArn:n.baselineTaskDefinitionArn,targetGroupArn:n.baselineTargetGroupArn,weight:100},canaryVersion:{version:"canary",taskDefinitionArn:n.canaryTaskDefinitionArn,targetGroupArn:n.canaryTargetGroupArn,weight:0},stages:s,currentStage:0,status:"pending",autoRollback:!0})}async executeDeployment(n,i=!1){let s=this.deployments.get(n);if(!s)throw Error(`Deployment not found: ${n}`);let o={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,completedStages:0,rolledBack:!1};console.log(`${i?"[DRY RUN] ":""}Starting canary deployment: ${s.name}`),console.log(` Strategy: ${s.stages.length} stages`),console.log(` Auto-promote: ${s.autoPromote}`),console.log(` Auto-rollback: ${s.autoRollback}`),console.log(""),s.status="in_progress";for(let c=0;c<s.stages.length;c++){let l=s.stages[c];if(s.currentStage=c,console.log(`Stage ${c+1}/${s.stages.length}: ${l.name}`),console.log(` Traffic: ${l.trafficPercentage}% canary, ${100-l.trafficPercentage}% baseline`),console.log(` Duration: ${l.durationMinutes} minutes`),!i)s.baselineVersion.weight=100-l.trafficPercentage,s.canaryVersion.weight=l.trafficPercentage;if(!await this.monitorStage(s,l,i)){if(console.log(" ✗ Stage failed - metrics exceeded thresholds"),s.autoRollback)console.log("\\n Rolling back deployment..."),await this.rollback(n,i),o.rolledBack=!0,o.reason="Metrics exceeded thresholds";return o.endTime=new Date,s.status="rolled_back",this.recordDeployment(n,o),o}console.log(" ✓ Stage completed successfully"),o.completedStages++,console.log("")}return s.status="completed",o.success=!0,o.endTime=new Date,console.log("✓ Canary deployment completed successfully"),this.recordDeployment(n,o),o}async monitorStage(n,i,s){if(console.log(" Monitoring metrics..."),s)return console.log(" [SKIPPED - DRY RUN]"),!0;await new Promise((c)=>setTimeout(c,100));let o={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)*i.trafficPercentage/100)};if(n.metrics=o,console.log(` Baseline: ${o.baselineErrorRate.toFixed(2)}% errors, ${o.baselineLatencyP99.toFixed(0)}ms P99`),console.log(` Canary: ${o.canaryErrorRate.toFixed(2)}% errors, ${o.canaryLatencyP99.toFixed(0)}ms P99`),i.alarmThresholds){let{errorRate:c,latencyP99:l}=i.alarmThresholds;if(c&&o.canaryErrorRate>c)return console.log(` ⚠ Error rate exceeded threshold: ${o.canaryErrorRate.toFixed(2)}% > ${c}%`),!1;if(l&&o.canaryLatencyP99>l)return console.log(` ⚠ Latency P99 exceeded threshold: ${o.canaryLatencyP99.toFixed(0)}ms > ${l}ms`),!1}return!0}async rollback(n,i=!1){let s=this.deployments.get(n);if(!s)throw Error(`Deployment not found: ${n}`);if(console.log(`${i?"[DRY RUN] ":""}Rolling back canary deployment: ${s.name}`),!i)s.baselineVersion.weight=100,s.canaryVersion.weight=0,s.status="rolled_back";console.log(" Traffic restored to baseline: 100%")}promoteCanary(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);console.log(`Promoting canary to baseline: ${i.name}`);let s=i.baselineVersion;i.baselineVersion=i.canaryVersion,i.canaryVersion=s,i.baselineVersion.weight=100,i.canaryVersion.weight=0,i.status="completed",console.log(" Canary promoted successfully")}recordDeployment(n,i){if(!this.deploymentHistory.has(n))this.deploymentHistory.set(n,[]);this.deploymentHistory.get(n).push(i)}getDeployment(n){return this.deployments.get(n)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(n){return this.deploymentHistory.get(n)||[]}generateLambdaAliasCF(n,i){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:{Ref:"LambdaFunction"},Name:i,FunctionVersion:n.canaryVersion.version,RoutingConfig:{AdditionalVersionWeights:[{FunctionVersion:n.baselineVersion.version,FunctionWeight:n.baselineVersion.weight/100}]}}}}generateALBListenerRuleCF(n){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:[{TargetGroupArn:n.baselineVersion.targetGroupArn,Weight:n.baselineVersion.weight},{TargetGroupArn:n.canaryVersion.targetGroupArn,Weight:n.canaryVersion.weight}],TargetGroupStickinessConfig:{Enabled:!1}}}]}}}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var tE=new ho;class Jg{tests=new Map;testCounter=0;createTest(n){let i=`abtest-${Date.now()}-${this.testCounter++}`,s={id:i,...n};return this.tests.set(i,s),s}createSimpleABTest(n){let i=n.variantTrafficPercentage||50;return this.createTest({name:n.name,description:n.description,variants:[{id:"control",name:"Control",description:"Original version",trafficPercentage:100-i,targetGroupArn:n.controlTargetGroupArn,weight:100-i},{id:"variant-a",name:"Variant A",description:"Test version",trafficPercentage:i,targetGroupArn:n.variantTargetGroupArn,weight:i}],routingStrategy:{type:n.stickySession?"cookie":"random",cookieName:n.stickySession?"ab_variant":void 0,stickySession:n.stickySession??!1,sessionDuration:1440},startTime:new Date,status:"draft"})}createMultivariateTest(n){let i=n.variants.reduce((s,o)=>s+o.trafficPercentage,0);if(i!==100)throw Error(`Traffic percentages must sum to 100, got ${i}`);return this.createTest({name:n.name,description:n.description,variants:n.variants.map((s,o)=>({id:`variant-${o}`,name:s.name,description:s.description,trafficPercentage:s.trafficPercentage,targetGroupArn:s.targetGroupArn,weight:s.trafficPercentage})),routingStrategy:n.routingStrategy||{type:"random",stickySession:!1},startTime:new Date,status:"draft"})}createHeaderBasedTest(n){return this.createTest({name:n.name,description:`Route based on ${n.headerName} header`,variants:[{id:"control",name:"Control",trafficPercentage:50,targetGroupArn:n.controlTargetGroupArn,weight:50},{id:"variant-a",name:"Variant A",trafficPercentage:50,targetGroupArn:n.variantTargetGroupArn,weight:50}],routingStrategy:{type:"header",headerName:n.headerName,stickySession:!1},startTime:new Date,status:"draft"})}createGeoBasedTest(n){return this.createTest({name:n.name,description:"Route based on geographic location",variants:[{id:"control",name:"Control (Rest of World)",trafficPercentage:50,targetGroupArn:n.controlTargetGroupArn,weight:50},{id:"variant-a",name:`Variant A (${n.regions.join(", ")})`,trafficPercentage:50,targetGroupArn:n.variantTargetGroupArn,weight:50}],routingStrategy:{type:"geo",stickySession:!0,sessionDuration:1440},startTime:new Date,status:"draft"})}startTest(n){let i=this.tests.get(n);if(!i)throw Error(`Test not found: ${n}`);if(i.status!=="draft"&&i.status!=="paused")throw Error(`Cannot start test in ${i.status} status`);i.status="active",i.startTime=new Date,console.log(`Started A/B test: ${i.name}`),console.log(` Variants: ${i.variants.length}`),i.variants.forEach((s)=>{console.log(` - ${s.name}: ${s.trafficPercentage}%`)})}pauseTest(n){let i=this.tests.get(n);if(!i)throw Error(`Test not found: ${n}`);i.status="paused",console.log(`Paused A/B test: ${i.name}`)}updateTrafficSplit(n,i,s){let o=this.tests.get(n);if(!o)throw Error(`Test not found: ${n}`);let c=o.variants.find((u)=>u.id===i);if(!c)throw Error(`Variant not found: ${i}`);let l=c.trafficPercentage;c.trafficPercentage=s,c.weight=s,console.log(`Updated ${c.name} traffic: ${l}% → ${s}%`)}analyzeResults(n){let i=this.tests.get(n);if(!i)throw Error(`Test not found: ${n}`);if(!i.metrics)i.metrics=this.collectMetrics(i);let s=i.variants[0],o=0;for(let f of i.variants){let b=i.metrics.variants[f.id];if(b&&b.conversionRate>o)o=b.conversionRate,s=f}let c=i.metrics.variants.control||i.metrics.variants[i.variants[0].id],l=i.metrics.variants[s.id],u=(l.conversionRate-c.conversionRate)/c.conversionRate*100,h=100,y=l.requests>h&&c.requests>h&&Math.abs(u)>10;return{testId:n,winningVariant:s.name,confidence:y?95:75,improvement:u,statisticalSignificance:y,metrics:i.metrics,recommendation:this.generateRecommendation(u,y,s.name)}}declareWinner(n,i){let s=this.tests.get(n);if(!s)throw Error(`Test not found: ${n}`);let o=s.variants.find((c)=>c.id===i);if(!o)throw Error(`Variant not found: ${i}`);s.variants.forEach((c)=>{if(c.id===i)c.trafficPercentage=100,c.weight=100;else c.trafficPercentage=0,c.weight=0}),s.status="completed",s.endTime=new Date,s.winner=i,console.log(`Declared winner: ${o.name}`),console.log(` All traffic now routed to ${o.name}`)}collectMetrics(n){let i={},s=0;for(let o of n.variants){let c=Math.floor(Math.random()*1000)+500,l=Math.floor(c*(Math.random()*0.1+0.05)),u=l/c*100;i[o.id]={requests:c,conversions:l,conversionRate:u,averageLatency:150+Math.random()*100,errorRate:Math.random()*0.5,revenue:l*(Math.random()*50+100)},s+=c}return{variants:i,totalRequests:s,startTime:n.startTime,lastUpdated:new Date}}generateRecommendation(n,i,s){if(!i)return"Continue test - sample size too small or no significant difference detected";if(n>20)return`Strong winner detected - ${s} shows ${n.toFixed(1)}% improvement. Recommend deploying to all traffic.`;if(n>10)return`Moderate improvement - ${s} shows ${n.toFixed(1)}% improvement. Consider deploying.`;if(n>0)return`Minor improvement - ${s} shows ${n.toFixed(1)}% improvement. May not be worth the complexity.`;return"No improvement detected - consider reverting to control variant"}getTest(n){return this.tests.get(n)}listTests(){return Array.from(this.tests.values())}generateALBListenerRuleCF(n){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:n.variants.map((i)=>({TargetGroupArn:i.targetGroupArn,Weight:i.weight})),TargetGroupStickinessConfig:{Enabled:n.routingStrategy.stickySession||!1,DurationSeconds:n.routingStrategy.sessionDuration?n.routingStrategy.sessionDuration*60:void 0}}}]}}}generateLambdaEdgeFunction(n){return`'use strict';
3600
+ `}class jg{backupPlans=new Map;backupVaults=new Map;restoreJobs=new Map;continuousBackups=new Map;planCounter=0;restoreCounter=0;continuousBackupCounter=0;createVault(n){this.backupVaults.set(n.name,n)}getVault(n){return this.backupVaults.get(n)}createBackupPlan(n){let i=`backup-plan-${Date.now()}-${this.planCounter++}`,s={id:i,...n};return this.backupPlans.set(i,s),s}getBackupPlan(n){return this.backupPlans.get(n)}listBackupPlans(){return Array.from(this.backupPlans.values())}createRDSBackupPlan(n){let{dbInstanceArn:i,schedule:s="0 2 * * *",retentionDays:o=7,vaultName:c="default-vault"}=n;return this.createBackupPlan({name:"RDS Daily Backup",schedule:s,retentionDays:o,vaultName:c,resources:[{resourceArn:i,resourceType:"rds",region:"us-east-1"}],lifecycle:{moveTocoldStorageAfterDays:30,deleteAfterDays:o}})}createDynamoDBBackupPlan(n){let{tableArn:i,schedule:s="0 3 * * *",retentionDays:o=35,crossRegionCopy:c}=n;return this.createBackupPlan({name:"DynamoDB Daily Backup",schedule:s,retentionDays:o,vaultName:"dynamodb-vault",resources:[{resourceArn:i,resourceType:"dynamodb",region:"us-east-1"}],lifecycle:{deleteAfterDays:o},tags:c?{CrossRegionCopy:c.join(",")}:void 0})}createEFSBackupPlan(n){let{fileSystemArn:i,schedule:s="0 1 * * *",retentionDays:o=30}=n;return this.createBackupPlan({name:"EFS Daily Backup",schedule:s,retentionDays:o,vaultName:"efs-vault",resources:[{resourceArn:i,resourceType:"efs",region:"us-east-1"}],lifecycle:{deleteAfterDays:o}})}enableContinuousBackup(n,i=35){let s=`continuous-backup-${Date.now()}-${this.continuousBackupCounter++}`,o={id:s,resourceId:n,enabled:!0,retentionDays:i};return this.continuousBackups.set(s,o),o}getContinuousBackup(n){return this.continuousBackups.get(n)}enablePointInTimeRecovery(n,i){return{enabled:!0,earliestRestorableTime:new Date(Date.now()-604800000),latestRestorableTime:new Date}}async restoreFromBackup(n){let{backupId:i,resourceType:s,targetRegion:o}=n,c={id:`restore-${Date.now()}-${this.restoreCounter++}`,backupId:i,resourceType:s,status:"pending",startTime:new Date,targetRegion:o};return this.restoreJobs.set(c.id,c),setTimeout(()=>{c.status="running"},100),setTimeout(()=>{c.status="completed",c.endTime=new Date},1000),c}async restoreToPointInTime(n){let{sourceResourceArn:i,targetResourceName:s,restoreTime:o,resourceType:c}=n,l={id:`pitr-${Date.now()}-${this.restoreCounter++}`,backupId:`pitr-${o.getTime()}`,resourceType:c,status:"pending",startTime:new Date};return this.restoreJobs.set(l.id,l),console.log(`Restoring ${c} from ${i} to ${s} at ${o.toISOString()}`),setTimeout(()=>{l.status="completed",l.endTime=new Date},2000),l}getRestoreJob(n){return this.restoreJobs.get(n)}listRestoreJobs(){return Array.from(this.restoreJobs.values())}setupCrossRegionReplication(n){let{sourceVault:i,sourceRegion:s,targetRegions:o}=n;console.log("Setting up cross-region replication:"),console.log(` Source: ${i} in ${s}`),console.log(` Targets: ${o.join(", ")}`)}generateBackupVaultCF(n){return{Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:n.name,...n.encryptionKeyArn&&{EncryptionKeyArn:n.encryptionKeyArn},...n.accessPolicy&&{AccessPolicy:n.accessPolicy}}}}generateBackupPlanCF(n){return{Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:n.name,BackupPlanRule:[{RuleName:"DailyBackup",TargetBackupVault:n.vaultName,ScheduleExpression:`cron(${n.schedule})`,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:n.lifecycle?{...n.lifecycle.moveTocoldStorageAfterDays&&{MoveToColdStorageAfterDays:n.lifecycle.moveTocoldStorageAfterDays},...n.lifecycle.deleteAfterDays&&{DeleteAfterDays:n.lifecycle.deleteAfterDays}}:void 0}]},...n.tags&&{BackupPlanTags:n.tags}}}}generateBackupSelectionCF(n){return{Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:{Ref:`BackupPlan${n.id}`},BackupSelection:{SelectionName:`${n.name}Selection`,IamRoleArn:"arn:aws:iam::123456789012:role/service-role/AWSBackupDefaultServiceRole",Resources:n.resources.map((i)=>i.resourceArn)}}}}clear(){this.backupPlans.clear(),this.backupVaults.clear(),this.restoreJobs.clear(),this.continuousBackups.clear(),this.planCounter=0,this.restoreCounter=0,this.continuousBackupCounter=0}}var JC=new jg;class zg{drPlans=new Map;failoverTests=new Map;planCounter=0;testCounter=0;createDRPlan(n){let i=`dr-plan-${Date.now()}-${this.planCounter++}`,s={id:i,...n};return this.drPlans.set(i,s),s}createRDSDRPlan(n){let{primaryDbArn:i,secondaryDbArn:s,primaryRegion:o,secondaryRegion:c,rto:l=60,rpo:u=5}=n;return this.createDRPlan({name:"RDS Multi-Region DR",primaryRegion:o,secondaryRegion:c,rto:l,rpo:u,resources:[{resourceId:"primary-db",resourceType:"rds",primaryArn:i,secondaryArn:s,replicationEnabled:!0}],runbook:this.generateRDSRunbook(o,c),testSchedule:"0 0 1 * *"})}createDynamoDBDRPlan(n){let{tableArn:i,regions:s,rto:o=15,rpo:c=1}=n;return this.createDRPlan({name:"DynamoDB Global Tables DR",primaryRegion:s[0],secondaryRegion:s[1],rto:o,rpo:c,resources:[{resourceId:"dynamodb-table",resourceType:"dynamodb",primaryArn:i,replicationEnabled:!0}],runbook:this.generateDynamoDBRunbook(s)})}generateRDSRunbook(n,i){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 "+n,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 "+i,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(n){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(n,i=!1){let s=this.drPlans.get(n);if(!s)throw Error(`DR plan not found: ${n}`);let o=Date.now(),c=0;console.log(`${i?"[DRY RUN] ":""}Executing failover for plan: ${s.name}`),console.log(`Primary: ${s.primaryRegion} -> Secondary: ${s.secondaryRegion}`),console.log(`RTO: ${s.rto} minutes, RPO: ${s.rpo} minutes`),console.log("");for(let l of s.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`),i)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()-o)/1000/60,completedSteps:c}}scheduleFailoverTest(n,i){let s={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:n,status:"scheduled",startTime:i};return this.failoverTests.set(s.id,s),s}async runFailoverTest(n){let i=this.drPlans.get(n);if(!i)throw Error(`DR plan not found: ${n}`);let s={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:n,status:"running",startTime:new Date,results:[]};this.failoverTests.set(s.id,s),console.log(`Running failover test for plan: ${i.name}`),console.log("This is a non-destructive test using test resources"),console.log("");for(let o of i.runbook.steps){let c=Date.now();console.log(`Testing step ${o.order}: ${o.name}`);let l={step:o.name,status:"success",duration:(Date.now()-c)/1000,message:`Successfully validated step ${o.order}`};s.results.push(l)}return s.status="completed",s.endTime=new Date,s}getDRPlan(n){return this.drPlans.get(n)}listDRPlans(){return Array.from(this.drPlans.values())}getFailoverTest(n){return this.failoverTests.get(n)}listFailoverTests(){return Array.from(this.failoverTests.values())}validateDRPlan(n){let i=[],s=[];if(n.rto<n.rpo)s.push("RTO cannot be less than RPO");if(n.rto>240)i.push("RTO exceeds 4 hours - consider improving recovery time");if(n.rpo>60)i.push("RPO exceeds 1 hour - consider more frequent backups");if(n.resources.length===0)s.push("No resources defined in DR plan");for(let l of n.resources){if(!l.replicationEnabled)i.push(`Resource ${l.resourceId} does not have replication enabled`);if(!l.secondaryArn&&l.resourceType!=="dynamodb")i.push(`Resource ${l.resourceId} does not have secondary resource defined`)}if(n.runbook.steps.length===0)s.push("No recovery steps defined in runbook");let o=n.runbook.steps.reduce((l,u)=>l+u.estimatedDuration,0);if(o>n.rto)i.push(`Estimated recovery duration (${o}m) exceeds RTO (${n.rto}m)`);let c=n.runbook.steps.filter((l)=>!l.automatable);if(c.length>0)i.push(`${c.length} manual steps in runbook - consider automation`);return{valid:s.length===0,warnings:i,errors:s}}clear(){this.drPlans.clear(),this.failoverTests.clear(),this.planCounter=0,this.testCounter=0}}var XC=new zg;class Kg{configRules=new Map;configRecorders=new Map;deliveryChannels=new Map;ruleCounter=0;createConfigRecorder(n){return this.configRecorders.set(n.name,n),n}createDeliveryChannel(n){return this.deliveryChannels.set(n.name,n),n}createConfigRule(n){let i=`config-rule-${Date.now()}-${this.ruleCounter++}`,s={id:i,...n};return this.configRules.set(i,s),s}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(n=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:n},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(n){return this.createConfigRule({name:n.name,description:n.description,source:"CUSTOM_LAMBDA",lambdaFunctionArn:n.lambdaFunctionArn,scope:n.resourceTypes?{complianceResourceTypes:n.resourceTypes}:void 0,maxExecutionFrequency:n.maxExecutionFrequency,inputParameters:n.inputParameters})}createCompliancePreset(n){let i=[];switch(n){case"hipaa":i.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createRdsBackupRule(7),this.createVpcFlowLogsRule());break;case"pci-dss":i.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createIamMfaRule(),this.createRootAccountMfaRule(),this.createVpcFlowLogsRule());break;case"sox":i.push(this.createS3VersioningRule(),this.createCloudTrailEnabledRule(),this.createRdsBackupRule(30),this.createIamPasswordPolicyRule());break;case"gdpr":i.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createRdsSnapshotEncryptionRule());break;case"basic":i.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamMfaRule(),this.createRootAccountMfaRule());break}return i}getConfigRule(n){return this.configRules.get(n)}listConfigRules(){return Array.from(this.configRules.values())}getConfigRecorder(n){return this.configRecorders.get(n)}listConfigRecorders(){return Array.from(this.configRecorders.values())}getDeliveryChannel(n){return this.deliveryChannels.get(n)}listDeliveryChannels(){return Array.from(this.deliveryChannels.values())}generateConfigRuleCF(n){let i={Type:"AWS::Config::ConfigRule",Properties:{ConfigRuleName:n.name,Description:n.description,Source:{Owner:n.source==="AWS_MANAGED"?"AWS":"CUSTOM_LAMBDA"}}};if(n.source==="AWS_MANAGED"&&n.identifier)i.Properties.Source.SourceIdentifier=n.identifier;if(n.source==="CUSTOM_LAMBDA"&&n.lambdaFunctionArn)i.Properties.Source.SourceIdentifier=n.lambdaFunctionArn,i.Properties.Source.SourceDetails=[{EventSource:"aws.config",MessageType:"ConfigurationItemChangeNotification"}];if(n.inputParameters)i.Properties.InputParameters=JSON.stringify(n.inputParameters);if(n.scope){if(i.Properties.Scope={},n.scope.complianceResourceTypes)i.Properties.Scope.ComplianceResourceTypes=n.scope.complianceResourceTypes;if(n.scope.tagKey)i.Properties.Scope.TagKey=n.scope.tagKey;if(n.scope.tagValue)i.Properties.Scope.TagValue=n.scope.tagValue}if(n.maxExecutionFrequency)i.Properties.MaximumExecutionFrequency=n.maxExecutionFrequency;return i}generateConfigRecorderCF(n){return{Type:"AWS::Config::ConfigurationRecorder",Properties:{Name:n.name,RoleArn:n.roleArn,RecordingGroup:n.recordingGroup||{AllSupported:!0,IncludeGlobalResourceTypes:!0}}}}generateDeliveryChannelCF(n){return{Type:"AWS::Config::DeliveryChannel",Properties:{Name:n.name,S3BucketName:n.s3BucketName,...n.s3KeyPrefix&&{S3KeyPrefix:n.s3KeyPrefix},...n.snsTopicArn&&{SnsTopicARN:n.snsTopicArn},...n.configSnapshotDeliveryProperties&&{ConfigSnapshotDeliveryProperties:n.configSnapshotDeliveryProperties}}}}clear(){this.configRules.clear(),this.configRecorders.clear(),this.deliveryChannels.clear(),this.ruleCounter=0}}var YC=new Kg;class Wg{trails=new Map;trailCounter=0;createTrail(n){let i=`trail-${Date.now()}-${this.trailCounter++}`,s={id:i,...n};return this.trails.set(i,s),s}createOrganizationTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,s3KeyPrefix:"organization-trail",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:n.kmsKeyId,cloudWatchLogsLogGroupArn:n.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:n.cloudWatchLogsRoleArn})}createSecurityAuditTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,s3KeyPrefix:"security-audit",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:n.kmsKeyId,cloudWatchLogsLogGroupArn:n.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:n.cloudWatchLogsRoleArn,eventSelectors:[{readWriteType:"All",includeManagementEvents:!0,excludeManagementEventSources:[]}],insightSelectors:[{insightType:"ApiCallRateInsight"},{insightType:"ApiErrorRateInsight"}]})}createDataEventsTrail(n){let i=[];if(n.s3DataBuckets&&n.s3DataBuckets.length>0)i.push({type:"AWS::S3::Object",values:n.s3DataBuckets.map((s)=>`arn:aws:s3:::${s}/*`)});if(n.lambdaFunctions&&n.lambdaFunctions.length>0)i.push({type:"AWS::Lambda::Function",values:n.lambdaFunctions});return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,s3KeyPrefix:"data-events",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"All",includeManagementEvents:!1,dataResources:i}]})}createAdvancedTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,advancedEventSelectors:n.selectors})}createReadOnlyTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"ReadOnly",includeManagementEvents:!0}]})}createWriteOnlyTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"WriteOnly",includeManagementEvents:!0}]})}getTrail(n){return this.trails.get(n)}listTrails(){return Array.from(this.trails.values())}generateTrailCF(n){let i={Type:"AWS::CloudTrail::Trail",Properties:{TrailName:n.name,S3BucketName:n.s3BucketName,IsLogging:!0,IncludeGlobalServiceEvents:n.includeGlobalServiceEvents??!0,IsMultiRegionTrail:n.isMultiRegionTrail??!0,EnableLogFileValidation:n.enableLogFileValidation??!0}};if(n.s3KeyPrefix)i.Properties.S3KeyPrefix=n.s3KeyPrefix;if(n.cloudWatchLogsLogGroupArn)i.Properties.CloudWatchLogsLogGroupArn=n.cloudWatchLogsLogGroupArn;if(n.cloudWatchLogsRoleArn)i.Properties.CloudWatchLogsRoleArn=n.cloudWatchLogsRoleArn;if(n.snsTopicName)i.Properties.SnsTopicName=n.snsTopicName;if(n.kmsKeyId)i.Properties.KMSKeyId=n.kmsKeyId;if(n.eventSelectors)i.Properties.EventSelectors=n.eventSelectors.map((s)=>({ReadWriteType:s.readWriteType,IncludeManagementEvents:s.includeManagementEvents??!0,...s.dataResources&&{DataResources:s.dataResources.map((o)=>({Type:o.type,Values:o.values}))},...s.excludeManagementEventSources&&{ExcludeManagementEventSources:s.excludeManagementEventSources}}));if(n.insightSelectors)i.Properties.InsightSelectors=n.insightSelectors.map((s)=>({InsightType:s.insightType}));if(n.advancedEventSelectors)i.Properties.AdvancedEventSelectors=n.advancedEventSelectors.map((s)=>({Name:s.name,FieldSelectors:s.fieldSelectors.map((o)=>({Field:o.field,...o.equals&&{Equals:o.equals},...o.startsWith&&{StartsWith:o.startsWith},...o.endsWith&&{EndsWith:o.endsWith},...o.notEquals&&{NotEquals:o.notEquals},...o.notStartsWith&&{NotStartsWith:o.notStartsWith},...o.notEndsWith&&{NotEndsWith:o.notEndsWith}}))}));return i}generateBucketPolicy(n,i){return{Version:"2012-10-17",Statement:[{Sid:"AWSCloudTrailAclCheck",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:GetBucketAcl",Resource:`arn:aws:s3:::${n}`},{Sid:"AWSCloudTrailWrite",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:PutObject",Resource:i.map((s)=>`arn:aws:s3:::${n}/AWSLogs/${s}/*`),Condition:{StringEquals:{"s3:x-amz-acl":"bucket-owner-full-control"}}}]}}clear(){this.trails.clear(),this.trailCounter=0}}var ZC=new Wg;class Jg{detectors=new Map;threatIntelSets=new Map;ipSets=new Map;filters=new Map;detectorCounter=0;threatIntelCounter=0;ipSetCounter=0;filterCounter=0;createDetector(n){let i=`detector-${Date.now()}-${this.detectorCounter++}`,s={id:i,...n};return this.detectors.set(i,s),s}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(n){let i=`threat-intel-${Date.now()}-${this.threatIntelCounter++}`,s={id:i,...n};return this.threatIntelSets.set(i,s),s}createIPSet(n){let i=`ip-set-${Date.now()}-${this.ipSetCounter++}`,s={id:i,...n};return this.ipSets.set(i,s),s}createFindingFilter(n){let i=`filter-${Date.now()}-${this.filterCounter++}`,s={id:i,...n};return this.filters.set(i,s),s}createLowSeverityArchiveFilter(n){return this.createFindingFilter({detectorId:n,name:"archive-low-severity",description:"Automatically archive low severity findings",action:"ARCHIVE",rank:1,findingCriteria:{criterion:{severity:{lt:4}}}})}createFindingTypeFilter(n,i,s){return this.createFindingFilter({detectorId:n,name:`filter-finding-types-${s.toLowerCase()}`,description:`${s==="ARCHIVE"?"Archive":"Keep"} specific finding types`,action:s,rank:2,findingCriteria:{criterion:{type:{eq:i}}}})}createTrustedIPFilter(n,i){return this.createFindingFilter({detectorId:n,name:"trusted-ip-addresses",description:"Archive findings from trusted IP addresses",action:"ARCHIVE",rank:3,findingCriteria:{criterion:{"resource.instanceDetails.networkInterfaces.privateIpAddress":{eq:i}}}})}getDetector(n){return this.detectors.get(n)}listDetectors(){return Array.from(this.detectors.values())}getThreatIntelSet(n){return this.threatIntelSets.get(n)}listThreatIntelSets(){return Array.from(this.threatIntelSets.values())}getIPSet(n){return this.ipSets.get(n)}listIPSets(){return Array.from(this.ipSets.values())}getFindingFilter(n){return this.filters.get(n)}listFindingFilters(){return Array.from(this.filters.values())}generateDetectorCF(n){let i={Type:"AWS::GuardDuty::Detector",Properties:{Enable:n.enable}};if(n.findingPublishingFrequency)i.Properties.FindingPublishingFrequency=n.findingPublishingFrequency;if(n.dataSources){if(i.Properties.DataSources={},n.dataSources.s3Logs)i.Properties.DataSources.S3Logs={Enable:n.dataSources.s3Logs.enable};if(n.dataSources.kubernetes)i.Properties.DataSources.Kubernetes={AuditLogs:{Enable:n.dataSources.kubernetes.auditLogs.enable}};if(n.dataSources.malwareProtection)i.Properties.DataSources.MalwareProtection={ScanEc2InstanceWithFindings:{EbsVolumes:{Enable:n.dataSources.malwareProtection.scanEc2InstanceWithFindings.ebsVolumes.enable}}}}if(n.features)i.Properties.Features=n.features.map((s)=>({Name:s.name,Status:s.status,...s.additionalConfiguration&&{AdditionalConfiguration:s.additionalConfiguration}}));return i}generateThreatIntelSetCF(n){return{Type:"AWS::GuardDuty::ThreatIntelSet",Properties:{DetectorId:n.detectorId,Name:n.name,Format:n.format,Location:n.location,Activate:n.activate}}}generateIPSetCF(n){return{Type:"AWS::GuardDuty::IPSet",Properties:{DetectorId:n.detectorId,Name:n.name,Format:n.format,Location:n.location,Activate:n.activate}}}generateFilterCF(n){return{Type:"AWS::GuardDuty::Filter",Properties:{DetectorId:n.detectorId,Name:n.name,Description:n.description,Action:n.action,Rank:n.rank,FindingCriteria:{Criterion:n.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 eE=new Jg;class jr{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(n){let i=`hub-${Date.now()}-${this.hubCounter++}`,s={id:i,...n};return this.hubs.set(i,s),s}createComprehensiveHub(){return this.createHub({enable:!0,controlFindingGenerator:"SECURITY_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...jr.Standards.AWS_FOUNDATIONAL_SECURITY,enabled:!0},{id:"cis-1-4",...jr.Standards.CIS_AWS_FOUNDATIONS_1_4,enabled:!0},{id:"pci-dss",...jr.Standards.PCI_DSS,enabled:!0}]})}createBasicHub(){return this.createHub({enable:!0,controlFindingGenerator:"STANDARD_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...jr.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(n){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:n.map((i)=>({value:i,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(n,i){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:`Suppress False Positives - ${n}`,description:`Automatically suppress known false positives from ${n}`,actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"SUPPRESSED"},note:{text:"Known false positive - automatically suppressed",updatedBy:"SecurityHub Automation"}}}],criteria:{productName:[{value:n,comparison:"EQUALS"}],title:i.map((s)=>({value:s,comparison:"PREFIX"}))},ruleStatus:"ENABLED",ruleOrder:10}}getHub(n){return this.hubs.get(n)}listHubs(){return Array.from(this.hubs.values())}generateHubCF(n){let i={Type:"AWS::SecurityHub::Hub",Properties:{}};if(n.controlFindingGenerator)i.Properties.ControlFindingGenerator=n.controlFindingGenerator;if(n.enableDefaultStandards!==void 0)i.Properties.EnableDefaultStandards=n.enableDefaultStandards;return i}generateStandardCF(n){let i={Type:"AWS::SecurityHub::Standard",Properties:{StandardsArn:n.arn}};if(n.disabledControls&&n.disabledControls.length>0)i.Properties.DisabledStandardsControls=n.disabledControls.map((s)=>({StandardsControlArn:s,Reason:"Disabled by configuration"}));return i}generateAutomationRuleCF(n){return{Type:"AWS::SecurityHub::AutomationRule",Properties:{RuleName:n.ruleName,Description:n.description,Actions:n.actions.map((i)=>({Type:i.type,FindingFieldsUpdate:i.findingFieldsUpdate})),Criteria:n.criteria,RuleStatus:n.ruleStatus,RuleOrder:n.ruleOrder}}}clear(){this.hubs.clear(),this.hubCounter=0,this.ruleCounter=0}}var tE=new jr;class Xg{deployments=new Map;deploymentHistory=new Map;deploymentCounter=0;resultCounter=0;createDeployment(n){let i=`bg-deployment-${Date.now()}-${this.deploymentCounter++}`,s={id:i,...n};return this.deployments.set(i,s),s}createALBDeployment(n){return this.createDeployment({name:n.name,blueEnvironment:{name:"blue",targetGroupArn:n.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:n.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:n.listenerArn,switchoverTimeSeconds:0},autoPromote:n.autoPromote,healthCheckConfig:n.healthCheckConfig})}createRoute53Deployment(n){return this.createDeployment({name:n.name,blueEnvironment:{name:"blue",targetGroupArn:n.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:n.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"route53",hostedZoneId:n.hostedZoneId,switchoverTimeSeconds:n.switchoverTimeSeconds||60}})}createECSDeployment(n){return this.createDeployment({name:n.name,blueEnvironment:{name:"blue",targetGroupArn:n.blueTargetGroupArn,taskDefinitionArn:n.blueTaskDefinitionArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:n.greenTargetGroupArn,taskDefinitionArn:n.greenTaskDefinitionArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:n.listenerArn},autoRollback:n.autoRollback??!0})}async executeDeployment(n,i=!1){let s=this.deployments.get(n);if(!s)throw Error(`Deployment not found: ${n}`);let o={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!1,errors:[]};console.log(`${i?"[DRY RUN] ":""}Starting blue/green deployment: ${s.name}`),console.log(` Active environment: ${s.activeEnvironment}`),console.log(` Routing type: ${s.routingConfig.type}`);let c=s.activeEnvironment==="blue"?"green":"blue";if(console.log(` Switching to: ${c}`),console.log(`\\n1. Deploying to ${c} environment`),!i)await new Promise((l)=>setTimeout(l,100));if(console.log(`\\n2. Running health checks on ${c} environment`),s.healthCheckConfig){let l=await this.runHealthChecks(s,c,i);if(o.healthChecksPassed=l,!l){if(o.errors?.push("Health checks failed"),o.endTime=new Date,s.autoRollback)console.log(" Auto-rollback enabled - keeping current environment active"),o.rolledBackAt=new Date;return this.recordDeployment(n,o),o}}else o.healthChecksPassed=!0;if(console.log(`\\n3. Switching traffic to ${c} environment`),!i)s.activeEnvironment=c,o.switchedAt=new Date;if(console.log(`\\n4. Monitoring ${c} environment`),!i)await new Promise((l)=>setTimeout(l,100));return o.success=!0,o.endTime=new Date,console.log("\\n✓ Deployment completed successfully"),this.recordDeployment(n,o),o}async rollback(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);let s={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!0,errors:[]};console.log(`Rolling back deployment: ${i.name}`);let o=i.activeEnvironment==="blue"?"green":"blue";return i.activeEnvironment=o,s.success=!0,s.rolledBackAt=new Date,s.endTime=new Date,console.log(` Switched back to: ${o}`),this.recordDeployment(n,s),s}async runHealthChecks(n,i,s){let o=n.healthCheckConfig;if(console.log(` Health check path: ${o.path||"/"}`),console.log(` Healthy threshold: ${o.healthyThreshold}`),console.log(` Interval: ${o.interval}s`),s)return console.log(" [SKIPPED - DRY RUN]"),!0;let c=0,l=o.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}/${o.healthyThreshold})`),c>=o.healthyThreshold)return!0}else c=0,console.log(` Check ${u+1}: ✗ Unhealthy`);return!1}recordDeployment(n,i){if(!this.deploymentHistory.has(n))this.deploymentHistory.set(n,[]);this.deploymentHistory.get(n).push(i)}getDeployment(n){return this.deployments.get(n)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(n){return this.deploymentHistory.get(n)||[]}generateALBListenerCF(n){let i=n.activeEnvironment==="blue"?n.blueEnvironment:n.greenEnvironment;return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:n.routingConfig.listenerArn,Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",TargetGroupArn:i.targetGroupArn}]}}}generateRoute53RecordSetCF(n,i){return[{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.routingConfig.hostedZoneId,Name:i,Type:"A",SetIdentifier:"blue",Weight:n.activeEnvironment==="blue"?100:0,AliasTarget:{HostedZoneId:n.routingConfig.hostedZoneId,DNSName:n.blueEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}},{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.routingConfig.hostedZoneId,Name:i,Type:"A",SetIdentifier:"green",Weight:n.activeEnvironment==="green"?100:0,AliasTarget:{HostedZoneId:n.routingConfig.hostedZoneId,DNSName:n.greenEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}}]}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var rE=new Xg;class Ao{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(n){let i=`canary-${Date.now()}-${this.deploymentCounter++}`,s={id:i,...n};return this.deployments.set(i,s),s}createLambdaCanaryDeployment(n){let i=n.strategy||"BALANCED",s=Ao.Strategies[i].map((o)=>({...o,alarmThresholds:{errorRate:n.errorRateThreshold||1,latencyP99:n.latencyThreshold||1000}}));return this.createDeployment({name:n.name,baselineVersion:{version:"baseline",functionVersionArn:n.baselineVersionArn,weight:100},canaryVersion:{version:"canary",functionVersionArn:n.canaryVersionArn,weight:0},stages:s,currentStage:0,status:"pending",autoPromote:n.autoPromote??!0,autoRollback:!0})}createECSCanaryDeployment(n){let i=n.strategy||"CONSERVATIVE",s=Ao.Strategies[i];return this.createDeployment({name:n.name,baselineVersion:{version:"baseline",taskDefinitionArn:n.baselineTaskDefinitionArn,targetGroupArn:n.baselineTargetGroupArn,weight:100},canaryVersion:{version:"canary",taskDefinitionArn:n.canaryTaskDefinitionArn,targetGroupArn:n.canaryTargetGroupArn,weight:0},stages:s,currentStage:0,status:"pending",autoRollback:!0})}async executeDeployment(n,i=!1){let s=this.deployments.get(n);if(!s)throw Error(`Deployment not found: ${n}`);let o={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,completedStages:0,rolledBack:!1};console.log(`${i?"[DRY RUN] ":""}Starting canary deployment: ${s.name}`),console.log(` Strategy: ${s.stages.length} stages`),console.log(` Auto-promote: ${s.autoPromote}`),console.log(` Auto-rollback: ${s.autoRollback}`),console.log(""),s.status="in_progress";for(let c=0;c<s.stages.length;c++){let l=s.stages[c];if(s.currentStage=c,console.log(`Stage ${c+1}/${s.stages.length}: ${l.name}`),console.log(` Traffic: ${l.trafficPercentage}% canary, ${100-l.trafficPercentage}% baseline`),console.log(` Duration: ${l.durationMinutes} minutes`),!i)s.baselineVersion.weight=100-l.trafficPercentage,s.canaryVersion.weight=l.trafficPercentage;if(!await this.monitorStage(s,l,i)){if(console.log(" ✗ Stage failed - metrics exceeded thresholds"),s.autoRollback)console.log("\\n Rolling back deployment..."),await this.rollback(n,i),o.rolledBack=!0,o.reason="Metrics exceeded thresholds";return o.endTime=new Date,s.status="rolled_back",this.recordDeployment(n,o),o}console.log(" ✓ Stage completed successfully"),o.completedStages++,console.log("")}return s.status="completed",o.success=!0,o.endTime=new Date,console.log("✓ Canary deployment completed successfully"),this.recordDeployment(n,o),o}async monitorStage(n,i,s){if(console.log(" Monitoring metrics..."),s)return console.log(" [SKIPPED - DRY RUN]"),!0;await new Promise((c)=>setTimeout(c,100));let o={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)*i.trafficPercentage/100)};if(n.metrics=o,console.log(` Baseline: ${o.baselineErrorRate.toFixed(2)}% errors, ${o.baselineLatencyP99.toFixed(0)}ms P99`),console.log(` Canary: ${o.canaryErrorRate.toFixed(2)}% errors, ${o.canaryLatencyP99.toFixed(0)}ms P99`),i.alarmThresholds){let{errorRate:c,latencyP99:l}=i.alarmThresholds;if(c&&o.canaryErrorRate>c)return console.log(` ⚠ Error rate exceeded threshold: ${o.canaryErrorRate.toFixed(2)}% > ${c}%`),!1;if(l&&o.canaryLatencyP99>l)return console.log(` ⚠ Latency P99 exceeded threshold: ${o.canaryLatencyP99.toFixed(0)}ms > ${l}ms`),!1}return!0}async rollback(n,i=!1){let s=this.deployments.get(n);if(!s)throw Error(`Deployment not found: ${n}`);if(console.log(`${i?"[DRY RUN] ":""}Rolling back canary deployment: ${s.name}`),!i)s.baselineVersion.weight=100,s.canaryVersion.weight=0,s.status="rolled_back";console.log(" Traffic restored to baseline: 100%")}promoteCanary(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);console.log(`Promoting canary to baseline: ${i.name}`);let s=i.baselineVersion;i.baselineVersion=i.canaryVersion,i.canaryVersion=s,i.baselineVersion.weight=100,i.canaryVersion.weight=0,i.status="completed",console.log(" Canary promoted successfully")}recordDeployment(n,i){if(!this.deploymentHistory.has(n))this.deploymentHistory.set(n,[]);this.deploymentHistory.get(n).push(i)}getDeployment(n){return this.deployments.get(n)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(n){return this.deploymentHistory.get(n)||[]}generateLambdaAliasCF(n,i){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:{Ref:"LambdaFunction"},Name:i,FunctionVersion:n.canaryVersion.version,RoutingConfig:{AdditionalVersionWeights:[{FunctionVersion:n.baselineVersion.version,FunctionWeight:n.baselineVersion.weight/100}]}}}}generateALBListenerRuleCF(n){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:[{TargetGroupArn:n.baselineVersion.targetGroupArn,Weight:n.baselineVersion.weight},{TargetGroupArn:n.canaryVersion.targetGroupArn,Weight:n.canaryVersion.weight}],TargetGroupStickinessConfig:{Enabled:!1}}}]}}}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var nE=new Ao;class Yg{tests=new Map;testCounter=0;createTest(n){let i=`abtest-${Date.now()}-${this.testCounter++}`,s={id:i,...n};return this.tests.set(i,s),s}createSimpleABTest(n){let i=n.variantTrafficPercentage||50;return this.createTest({name:n.name,description:n.description,variants:[{id:"control",name:"Control",description:"Original version",trafficPercentage:100-i,targetGroupArn:n.controlTargetGroupArn,weight:100-i},{id:"variant-a",name:"Variant A",description:"Test version",trafficPercentage:i,targetGroupArn:n.variantTargetGroupArn,weight:i}],routingStrategy:{type:n.stickySession?"cookie":"random",cookieName:n.stickySession?"ab_variant":void 0,stickySession:n.stickySession??!1,sessionDuration:1440},startTime:new Date,status:"draft"})}createMultivariateTest(n){let i=n.variants.reduce((s,o)=>s+o.trafficPercentage,0);if(i!==100)throw Error(`Traffic percentages must sum to 100, got ${i}`);return this.createTest({name:n.name,description:n.description,variants:n.variants.map((s,o)=>({id:`variant-${o}`,name:s.name,description:s.description,trafficPercentage:s.trafficPercentage,targetGroupArn:s.targetGroupArn,weight:s.trafficPercentage})),routingStrategy:n.routingStrategy||{type:"random",stickySession:!1},startTime:new Date,status:"draft"})}createHeaderBasedTest(n){return this.createTest({name:n.name,description:`Route based on ${n.headerName} header`,variants:[{id:"control",name:"Control",trafficPercentage:50,targetGroupArn:n.controlTargetGroupArn,weight:50},{id:"variant-a",name:"Variant A",trafficPercentage:50,targetGroupArn:n.variantTargetGroupArn,weight:50}],routingStrategy:{type:"header",headerName:n.headerName,stickySession:!1},startTime:new Date,status:"draft"})}createGeoBasedTest(n){return this.createTest({name:n.name,description:"Route based on geographic location",variants:[{id:"control",name:"Control (Rest of World)",trafficPercentage:50,targetGroupArn:n.controlTargetGroupArn,weight:50},{id:"variant-a",name:`Variant A (${n.regions.join(", ")})`,trafficPercentage:50,targetGroupArn:n.variantTargetGroupArn,weight:50}],routingStrategy:{type:"geo",stickySession:!0,sessionDuration:1440},startTime:new Date,status:"draft"})}startTest(n){let i=this.tests.get(n);if(!i)throw Error(`Test not found: ${n}`);if(i.status!=="draft"&&i.status!=="paused")throw Error(`Cannot start test in ${i.status} status`);i.status="active",i.startTime=new Date,console.log(`Started A/B test: ${i.name}`),console.log(` Variants: ${i.variants.length}`),i.variants.forEach((s)=>{console.log(` - ${s.name}: ${s.trafficPercentage}%`)})}pauseTest(n){let i=this.tests.get(n);if(!i)throw Error(`Test not found: ${n}`);i.status="paused",console.log(`Paused A/B test: ${i.name}`)}updateTrafficSplit(n,i,s){let o=this.tests.get(n);if(!o)throw Error(`Test not found: ${n}`);let c=o.variants.find((u)=>u.id===i);if(!c)throw Error(`Variant not found: ${i}`);let l=c.trafficPercentage;c.trafficPercentage=s,c.weight=s,console.log(`Updated ${c.name} traffic: ${l}% → ${s}%`)}analyzeResults(n){let i=this.tests.get(n);if(!i)throw Error(`Test not found: ${n}`);if(!i.metrics)i.metrics=this.collectMetrics(i);let s=i.variants[0],o=0;for(let f of i.variants){let b=i.metrics.variants[f.id];if(b&&b.conversionRate>o)o=b.conversionRate,s=f}let c=i.metrics.variants.control||i.metrics.variants[i.variants[0].id],l=i.metrics.variants[s.id],u=(l.conversionRate-c.conversionRate)/c.conversionRate*100,h=100,y=l.requests>h&&c.requests>h&&Math.abs(u)>10;return{testId:n,winningVariant:s.name,confidence:y?95:75,improvement:u,statisticalSignificance:y,metrics:i.metrics,recommendation:this.generateRecommendation(u,y,s.name)}}declareWinner(n,i){let s=this.tests.get(n);if(!s)throw Error(`Test not found: ${n}`);let o=s.variants.find((c)=>c.id===i);if(!o)throw Error(`Variant not found: ${i}`);s.variants.forEach((c)=>{if(c.id===i)c.trafficPercentage=100,c.weight=100;else c.trafficPercentage=0,c.weight=0}),s.status="completed",s.endTime=new Date,s.winner=i,console.log(`Declared winner: ${o.name}`),console.log(` All traffic now routed to ${o.name}`)}collectMetrics(n){let i={},s=0;for(let o of n.variants){let c=Math.floor(Math.random()*1000)+500,l=Math.floor(c*(Math.random()*0.1+0.05)),u=l/c*100;i[o.id]={requests:c,conversions:l,conversionRate:u,averageLatency:150+Math.random()*100,errorRate:Math.random()*0.5,revenue:l*(Math.random()*50+100)},s+=c}return{variants:i,totalRequests:s,startTime:n.startTime,lastUpdated:new Date}}generateRecommendation(n,i,s){if(!i)return"Continue test - sample size too small or no significant difference detected";if(n>20)return`Strong winner detected - ${s} shows ${n.toFixed(1)}% improvement. Recommend deploying to all traffic.`;if(n>10)return`Moderate improvement - ${s} shows ${n.toFixed(1)}% improvement. Consider deploying.`;if(n>0)return`Minor improvement - ${s} shows ${n.toFixed(1)}% improvement. May not be worth the complexity.`;return"No improvement detected - consider reverting to control variant"}getTest(n){return this.tests.get(n)}listTests(){return Array.from(this.tests.values())}generateALBListenerRuleCF(n){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:n.variants.map((i)=>({TargetGroupArn:i.targetGroupArn,Weight:i.weight})),TargetGroupStickinessConfig:{Enabled:n.routingStrategy.stickySession||!1,DurationSeconds:n.routingStrategy.sessionDuration?n.routingStrategy.sessionDuration*60:void 0}}}]}}}generateLambdaEdgeFunction(n){return`'use strict';
3601
3601
 
3602
3602
  exports.handler = (event, _context, _callback) => {
3603
3603
  const request = event.Records[0].cf.request;
@@ -3644,7 +3644,7 @@ exports.handler = (event, _context, _callback) => {
3644
3644
  }`).join(" else ")}
3645
3645
 
3646
3646
  callback(null, request);
3647
- };`}clear(){this.tests.clear(),this.testCounter=0}}var rE=new Jg;class Xg{rollouts=new Map;flags=new Map;gates=new Map;counter=0;createProgressiveRollout(n,i){let s=`rollout-${Date.now()}-${this.counter++}`,o={id:s,name:n,stages:i,currentStage:0};return this.rollouts.set(s,o),o}createFeatureFlag(n,i=0){let s=`flag-${Date.now()}-${this.counter++}`,o={id:s,name:n,enabled:!1,rolloutPercentage:i,targetingRules:[]};return this.flags.set(s,o),o}createDeploymentGate(n,i,s,o){let c=`gate-${Date.now()}-${this.counter++}`,l={id:c,name:n,type:i,approvers:s,conditions:o};return this.gates.set(c,l),l}clear(){this.rollouts.clear(),this.flags.clear(),this.gates.clear()}}var nE=new Xg;class Yg{configs=new Map;samplingRules=new Map;configCounter=0;ruleCounter=0;createConfig(n){let i=`xray-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}createLambdaConfig(n){return this.createConfig({name:`${n.functionName}-xray`,serviceName:n.functionName,samplingRate:n.samplingRate||0.1,enableActiveTracing:!0})}createECSConfig(n){return this.createConfig({name:`${n.serviceName}-xray`,serviceName:`${n.clusterName}/${n.serviceName}`,samplingRate:n.samplingRate||0.05,enableActiveTracing:!0})}createAPIGatewayConfig(n){return this.createConfig({name:`${n.apiName}-${n.stage}-xray`,serviceName:`${n.apiName}/${n.stage}`,samplingRate:n.samplingRate||0.05,enableActiveTracing:!0})}createSamplingRule(n){let i=`sampling-rule-${Date.now()}-${this.ruleCounter++}`,s={id:i,...n};return this.samplingRules.set(i,s),s}createHighPrioritySamplingRule(n){return this.createSamplingRule({ruleName:n.ruleName,priority:100,fixedRate:1,reservoirSize:100,serviceName:n.serviceName,serviceType:"*",host:"*",httpMethod:"*",urlPath:n.urlPath,version:1})}createErrorSamplingRule(n){return this.createSamplingRule({ruleName:`${n}-errors`,priority:200,fixedRate:1,reservoirSize:50,serviceName:n,serviceType:"*",host:"*",httpMethod:"*",urlPath:"/error/*",version:1})}createDefaultSamplingRule(n,i=0.05){return this.createSamplingRule({ruleName:`${n}-default`,priority:1000,fixedRate:i,reservoirSize:10,serviceName:n,serviceType:"*",host:"*",httpMethod:"*",urlPath:"*",version:1})}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getSamplingRule(n){return this.samplingRules.get(n)}listSamplingRules(){return Array.from(this.samplingRules.values())}generateLambdaXRayCF(n){return{TracingConfig:{Mode:n.enableActiveTracing?"Active":"PassThrough"}}}generateAPIGatewayXRayCF(n){return{TracingEnabled:n.enableActiveTracing}}generateECSXRaySidecarCF(){return{Name:"xray-daemon",Image:"public.ecr.aws/xray/aws-xray-daemon:latest",Cpu:32,MemoryReservation:256,PortMappings:[{ContainerPort:2000,Protocol:"udp"}]}}generateSamplingRuleCF(n){return{Type:"AWS::XRay::SamplingRule",Properties:{SamplingRule:{RuleName:n.ruleName,Priority:n.priority,FixedRate:n.fixedRate,ReservoirSize:n.reservoirSize,ServiceName:n.serviceName,ServiceType:n.serviceType,Host:n.host,HTTPMethod:n.httpMethod,URLPath:n.urlPath,Version:n.version,ResourceARN:"*"}}}}createTrace(n,i){return{id:`trace-${Date.now()}-${this.configCounter++}`,traceId:n,spans:i}}clear(){this.configs.clear(),this.samplingRules.clear(),this.configCounter=0,this.ruleCounter=0}}var iE=new Yg;class Zg{namespaces=new Map;metrics=new Map;namespaceCounter=0;metricCounter=0;alarmCounter=0;createNamespace(n){let i=`namespace-${Date.now()}-${this.namespaceCounter++}`,s={id:i,...n};return this.namespaces.set(i,s),s}createMetric(n){let i=`metric-${Date.now()}-${this.metricCounter++}`,s={id:i,...n};return this.metrics.set(i,s),s}createBusinessMetric(n){return this.createMetric({name:n.name,namespace:n.namespace,unit:n.unit,dimensions:[{name:"Environment",value:"production"},{name:"Type",value:"Business"}]})}createApplicationMetric(n){return this.createMetric({name:n.name,namespace:n.namespace,unit:n.unit,dimensions:[{name:"Service",value:n.serviceName},{name:"Type",value:"Application"}]})}createPerformanceMetric(n){return this.createMetric({name:n.name,namespace:n.namespace,unit:"Milliseconds",dimensions:[{name:"Operation",value:n.operation},{name:"Type",value:"Performance"}]})}createErrorMetric(n){return this.createMetric({name:n.name,namespace:n.namespace,unit:"Count",dimensions:[{name:"ErrorType",value:n.errorType},{name:"Type",value:"Error"}]})}createAlarm(n,i){let s=this.metrics.get(n);if(!s)throw Error(`Metric not found: ${n}`);let o={id:`alarm-${Date.now()}-${this.alarmCounter++}`,...i};if(!s.alarms)s.alarms=[];return s.alarms.push(o),o}createErrorRateAlarm(n){return this.createAlarm(n.metricId,{name:n.name,description:`Alert when error rate exceeds ${n.threshold} errors/min`,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:2,threshold:n.threshold,period:60,statistic:"Sum",treatMissingData:"notBreaching",actionsEnabled:!0,alarmActions:n.snsTopicArn?[n.snsTopicArn]:void 0})}createLatencyAlarm(n){return this.createAlarm(n.metricId,{name:n.name,description:`Alert when latency exceeds ${n.thresholdMs}ms`,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,threshold:n.thresholdMs,period:300,statistic:"Average",treatMissingData:"notBreaching",actionsEnabled:!0,alarmActions:n.snsTopicArn?[n.snsTopicArn]:void 0})}createThroughputAlarm(n){return this.createAlarm(n.metricId,{name:n.name,description:`Alert when throughput drops below ${n.minimumThreshold}`,comparisonOperator:"LessThanThreshold",evaluationPeriods:2,threshold:n.minimumThreshold,period:300,statistic:"Sum",treatMissingData:"breaching",actionsEnabled:!0,alarmActions:n.snsTopicArn?[n.snsTopicArn]:void 0})}createCompositeAlarm(n){return{name:n.name,description:n.description,alarmRule:n.alarmRule,actionsEnabled:n.actionsEnabled??!0,alarmActions:n.alarmActions}}getNamespace(n){return this.namespaces.get(n)}listNamespaces(){return Array.from(this.namespaces.values())}getMetric(n){return this.metrics.get(n)}listMetrics(){return Array.from(this.metrics.values())}generateAlarmCF(n,i){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:i.name,AlarmDescription:i.description,ComparisonOperator:i.comparisonOperator,EvaluationPeriods:i.evaluationPeriods,MetricName:n.name,Namespace:n.namespace,Period:i.period,Statistic:i.statistic,Threshold:i.threshold,TreatMissingData:i.treatMissingData||"notBreaching",ActionsEnabled:i.actionsEnabled??!0,...i.alarmActions&&{AlarmActions:i.alarmActions},...i.okActions&&{OKActions:i.okActions},...i.insufficientDataActions&&{InsufficientDataActions:i.insufficientDataActions},...n.dimensions&&{Dimensions:n.dimensions.map((s)=>({Name:s.name,Value:s.value}))}}}}generateCompositeAlarmCF(n){return{Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:n.name,AlarmDescription:n.description,AlarmRule:n.alarmRule,ActionsEnabled:n.actionsEnabled,...n.alarmActions&&{AlarmActions:n.alarmActions}}}}generateDashboardWidget(n){return{type:"metric",properties:{metrics:[[n.namespace,n.name,...n.dimensions?.flatMap((i)=>[i.name,i.value])||[]]],period:300,stat:"Average",region:"us-east-1",title:n.name}}}publishCustomMetric(n,i,s,o={},c="Count"){return{id:`metric-${Date.now()}-${this.metricCounter++}`,namespace:n,name:i,dimensions:o,value:s,unit:c,timestamp:new Date}}clear(){this.namespaces.clear(),this.metrics.clear(),this.namespaceCounter=0,this.metricCounter=0,this.alarmCounter=0}}var sE=new Zg;class em{logGroups=new Map;queries=new Map;insightsQueries=new Map;logGroupCounter=0;filterCounter=0;queryCounter=0;createLogGroup(n){let i=`log-group-${Date.now()}-${this.logGroupCounter++}`,s={id:i,...n};return this.logGroups.set(i,s),s}createLambdaLogGroup(n,i=7){return this.createLogGroup({name:`/aws/lambda/${n}`,retentionDays:i})}createECSLogGroup(n){return this.createLogGroup({name:`/ecs/${n.clusterName}/${n.serviceName}`,retentionDays:n.retentionDays||14})}createAPIGatewayLogGroup(n,i,s=30){return this.createLogGroup({name:`/aws/apigateway/${n}/${i}`,retentionDays:s})}createApplicationLogGroup(n){return this.createLogGroup({name:`/application/${n.appName}/${n.environment}`,retentionDays:n.retentionDays||30,kmsKeyId:n.kmsKeyId})}createMetricFilter(n,i){let s=this.logGroups.get(n);if(!s)throw Error(`Log group not found: ${n}`);let o={id:`filter-${Date.now()}-${this.filterCounter++}`,...i};if(!s.metricFilters)s.metricFilters=[];return s.metricFilters.push(o),o}createErrorCountFilter(n,i){return this.createMetricFilter(n,{name:"ErrorCount",filterPattern:"[timestamp, request_id, level = ERROR*, ...]",metricTransformations:[{metricName:"ErrorCount",metricNamespace:i,metricValue:"1",defaultValue:0,unit:"Count"}]})}createLatencyFilter(n,i){return this.createMetricFilter(n,{name:"Latency",filterPattern:"[timestamp, request_id, level, duration, ...]",metricTransformations:[{metricName:"ResponseTime",metricNamespace:i,metricValue:"$duration",unit:"Milliseconds"}]})}createCustomPatternFilter(n){return this.createMetricFilter(n.logGroupId,{name:n.name,filterPattern:n.pattern,metricTransformations:[{metricName:n.metricName,metricNamespace:n.namespace,metricValue:"1",defaultValue:0,unit:"Count"}]})}createSubscriptionFilter(n,i){let s=this.logGroups.get(n);if(!s)throw Error(`Log group not found: ${n}`);let o={id:`subscription-${Date.now()}-${this.filterCounter++}`,...i};if(!s.subscriptionFilters)s.subscriptionFilters=[];return s.subscriptionFilters.push(o),o}createKinesisSubscription(n){let i=this.logGroups.get(n.logGroupId);if(!i)throw Error(`Log group not found: ${n.logGroupId}`);return this.createSubscriptionFilter(n.logGroupId,{name:"KinesisSubscription",logGroupName:i.name,filterPattern:n.filterPattern||"",destinationArn:n.kinesisStreamArn,roleArn:n.roleArn,distribution:"Random"})}createLambdaSubscription(n){let i=this.logGroups.get(n.logGroupId);if(!i)throw Error(`Log group not found: ${n.logGroupId}`);return this.createSubscriptionFilter(n.logGroupId,{name:"LambdaSubscription",logGroupName:i.name,filterPattern:n.filterPattern||"",destinationArn:n.lambdaFunctionArn,distribution:"ByLogStream"})}createInsightsQuery(n){let i=`query-${Date.now()}-${this.queryCounter++}`,s={id:i,...n};return this.insightsQueries.set(i,s),s}createErrorAnalysisQuery(n){return this.createInsightsQuery({name:"Error Analysis",description:"Analyze error patterns and frequencies",query:`fields @timestamp, @message
3647
+ };`}clear(){this.tests.clear(),this.testCounter=0}}var iE=new Yg;class Zg{rollouts=new Map;flags=new Map;gates=new Map;counter=0;createProgressiveRollout(n,i){let s=`rollout-${Date.now()}-${this.counter++}`,o={id:s,name:n,stages:i,currentStage:0};return this.rollouts.set(s,o),o}createFeatureFlag(n,i=0){let s=`flag-${Date.now()}-${this.counter++}`,o={id:s,name:n,enabled:!1,rolloutPercentage:i,targetingRules:[]};return this.flags.set(s,o),o}createDeploymentGate(n,i,s,o){let c=`gate-${Date.now()}-${this.counter++}`,l={id:c,name:n,type:i,approvers:s,conditions:o};return this.gates.set(c,l),l}clear(){this.rollouts.clear(),this.flags.clear(),this.gates.clear()}}var sE=new Zg;class em{configs=new Map;samplingRules=new Map;configCounter=0;ruleCounter=0;createConfig(n){let i=`xray-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}createLambdaConfig(n){return this.createConfig({name:`${n.functionName}-xray`,serviceName:n.functionName,samplingRate:n.samplingRate||0.1,enableActiveTracing:!0})}createECSConfig(n){return this.createConfig({name:`${n.serviceName}-xray`,serviceName:`${n.clusterName}/${n.serviceName}`,samplingRate:n.samplingRate||0.05,enableActiveTracing:!0})}createAPIGatewayConfig(n){return this.createConfig({name:`${n.apiName}-${n.stage}-xray`,serviceName:`${n.apiName}/${n.stage}`,samplingRate:n.samplingRate||0.05,enableActiveTracing:!0})}createSamplingRule(n){let i=`sampling-rule-${Date.now()}-${this.ruleCounter++}`,s={id:i,...n};return this.samplingRules.set(i,s),s}createHighPrioritySamplingRule(n){return this.createSamplingRule({ruleName:n.ruleName,priority:100,fixedRate:1,reservoirSize:100,serviceName:n.serviceName,serviceType:"*",host:"*",httpMethod:"*",urlPath:n.urlPath,version:1})}createErrorSamplingRule(n){return this.createSamplingRule({ruleName:`${n}-errors`,priority:200,fixedRate:1,reservoirSize:50,serviceName:n,serviceType:"*",host:"*",httpMethod:"*",urlPath:"/error/*",version:1})}createDefaultSamplingRule(n,i=0.05){return this.createSamplingRule({ruleName:`${n}-default`,priority:1000,fixedRate:i,reservoirSize:10,serviceName:n,serviceType:"*",host:"*",httpMethod:"*",urlPath:"*",version:1})}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getSamplingRule(n){return this.samplingRules.get(n)}listSamplingRules(){return Array.from(this.samplingRules.values())}generateLambdaXRayCF(n){return{TracingConfig:{Mode:n.enableActiveTracing?"Active":"PassThrough"}}}generateAPIGatewayXRayCF(n){return{TracingEnabled:n.enableActiveTracing}}generateECSXRaySidecarCF(){return{Name:"xray-daemon",Image:"public.ecr.aws/xray/aws-xray-daemon:latest",Cpu:32,MemoryReservation:256,PortMappings:[{ContainerPort:2000,Protocol:"udp"}]}}generateSamplingRuleCF(n){return{Type:"AWS::XRay::SamplingRule",Properties:{SamplingRule:{RuleName:n.ruleName,Priority:n.priority,FixedRate:n.fixedRate,ReservoirSize:n.reservoirSize,ServiceName:n.serviceName,ServiceType:n.serviceType,Host:n.host,HTTPMethod:n.httpMethod,URLPath:n.urlPath,Version:n.version,ResourceARN:"*"}}}}createTrace(n,i){return{id:`trace-${Date.now()}-${this.configCounter++}`,traceId:n,spans:i}}clear(){this.configs.clear(),this.samplingRules.clear(),this.configCounter=0,this.ruleCounter=0}}var oE=new em;class tm{namespaces=new Map;metrics=new Map;namespaceCounter=0;metricCounter=0;alarmCounter=0;createNamespace(n){let i=`namespace-${Date.now()}-${this.namespaceCounter++}`,s={id:i,...n};return this.namespaces.set(i,s),s}createMetric(n){let i=`metric-${Date.now()}-${this.metricCounter++}`,s={id:i,...n};return this.metrics.set(i,s),s}createBusinessMetric(n){return this.createMetric({name:n.name,namespace:n.namespace,unit:n.unit,dimensions:[{name:"Environment",value:"production"},{name:"Type",value:"Business"}]})}createApplicationMetric(n){return this.createMetric({name:n.name,namespace:n.namespace,unit:n.unit,dimensions:[{name:"Service",value:n.serviceName},{name:"Type",value:"Application"}]})}createPerformanceMetric(n){return this.createMetric({name:n.name,namespace:n.namespace,unit:"Milliseconds",dimensions:[{name:"Operation",value:n.operation},{name:"Type",value:"Performance"}]})}createErrorMetric(n){return this.createMetric({name:n.name,namespace:n.namespace,unit:"Count",dimensions:[{name:"ErrorType",value:n.errorType},{name:"Type",value:"Error"}]})}createAlarm(n,i){let s=this.metrics.get(n);if(!s)throw Error(`Metric not found: ${n}`);let o={id:`alarm-${Date.now()}-${this.alarmCounter++}`,...i};if(!s.alarms)s.alarms=[];return s.alarms.push(o),o}createErrorRateAlarm(n){return this.createAlarm(n.metricId,{name:n.name,description:`Alert when error rate exceeds ${n.threshold} errors/min`,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:2,threshold:n.threshold,period:60,statistic:"Sum",treatMissingData:"notBreaching",actionsEnabled:!0,alarmActions:n.snsTopicArn?[n.snsTopicArn]:void 0})}createLatencyAlarm(n){return this.createAlarm(n.metricId,{name:n.name,description:`Alert when latency exceeds ${n.thresholdMs}ms`,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,threshold:n.thresholdMs,period:300,statistic:"Average",treatMissingData:"notBreaching",actionsEnabled:!0,alarmActions:n.snsTopicArn?[n.snsTopicArn]:void 0})}createThroughputAlarm(n){return this.createAlarm(n.metricId,{name:n.name,description:`Alert when throughput drops below ${n.minimumThreshold}`,comparisonOperator:"LessThanThreshold",evaluationPeriods:2,threshold:n.minimumThreshold,period:300,statistic:"Sum",treatMissingData:"breaching",actionsEnabled:!0,alarmActions:n.snsTopicArn?[n.snsTopicArn]:void 0})}createCompositeAlarm(n){return{name:n.name,description:n.description,alarmRule:n.alarmRule,actionsEnabled:n.actionsEnabled??!0,alarmActions:n.alarmActions}}getNamespace(n){return this.namespaces.get(n)}listNamespaces(){return Array.from(this.namespaces.values())}getMetric(n){return this.metrics.get(n)}listMetrics(){return Array.from(this.metrics.values())}generateAlarmCF(n,i){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:i.name,AlarmDescription:i.description,ComparisonOperator:i.comparisonOperator,EvaluationPeriods:i.evaluationPeriods,MetricName:n.name,Namespace:n.namespace,Period:i.period,Statistic:i.statistic,Threshold:i.threshold,TreatMissingData:i.treatMissingData||"notBreaching",ActionsEnabled:i.actionsEnabled??!0,...i.alarmActions&&{AlarmActions:i.alarmActions},...i.okActions&&{OKActions:i.okActions},...i.insufficientDataActions&&{InsufficientDataActions:i.insufficientDataActions},...n.dimensions&&{Dimensions:n.dimensions.map((s)=>({Name:s.name,Value:s.value}))}}}}generateCompositeAlarmCF(n){return{Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:n.name,AlarmDescription:n.description,AlarmRule:n.alarmRule,ActionsEnabled:n.actionsEnabled,...n.alarmActions&&{AlarmActions:n.alarmActions}}}}generateDashboardWidget(n){return{type:"metric",properties:{metrics:[[n.namespace,n.name,...n.dimensions?.flatMap((i)=>[i.name,i.value])||[]]],period:300,stat:"Average",region:"us-east-1",title:n.name}}}publishCustomMetric(n,i,s,o={},c="Count"){return{id:`metric-${Date.now()}-${this.metricCounter++}`,namespace:n,name:i,dimensions:o,value:s,unit:c,timestamp:new Date}}clear(){this.namespaces.clear(),this.metrics.clear(),this.namespaceCounter=0,this.metricCounter=0,this.alarmCounter=0}}var aE=new tm;class rm{logGroups=new Map;queries=new Map;insightsQueries=new Map;logGroupCounter=0;filterCounter=0;queryCounter=0;createLogGroup(n){let i=`log-group-${Date.now()}-${this.logGroupCounter++}`,s={id:i,...n};return this.logGroups.set(i,s),s}createLambdaLogGroup(n,i=7){return this.createLogGroup({name:`/aws/lambda/${n}`,retentionDays:i})}createECSLogGroup(n){return this.createLogGroup({name:`/ecs/${n.clusterName}/${n.serviceName}`,retentionDays:n.retentionDays||14})}createAPIGatewayLogGroup(n,i,s=30){return this.createLogGroup({name:`/aws/apigateway/${n}/${i}`,retentionDays:s})}createApplicationLogGroup(n){return this.createLogGroup({name:`/application/${n.appName}/${n.environment}`,retentionDays:n.retentionDays||30,kmsKeyId:n.kmsKeyId})}createMetricFilter(n,i){let s=this.logGroups.get(n);if(!s)throw Error(`Log group not found: ${n}`);let o={id:`filter-${Date.now()}-${this.filterCounter++}`,...i};if(!s.metricFilters)s.metricFilters=[];return s.metricFilters.push(o),o}createErrorCountFilter(n,i){return this.createMetricFilter(n,{name:"ErrorCount",filterPattern:"[timestamp, request_id, level = ERROR*, ...]",metricTransformations:[{metricName:"ErrorCount",metricNamespace:i,metricValue:"1",defaultValue:0,unit:"Count"}]})}createLatencyFilter(n,i){return this.createMetricFilter(n,{name:"Latency",filterPattern:"[timestamp, request_id, level, duration, ...]",metricTransformations:[{metricName:"ResponseTime",metricNamespace:i,metricValue:"$duration",unit:"Milliseconds"}]})}createCustomPatternFilter(n){return this.createMetricFilter(n.logGroupId,{name:n.name,filterPattern:n.pattern,metricTransformations:[{metricName:n.metricName,metricNamespace:n.namespace,metricValue:"1",defaultValue:0,unit:"Count"}]})}createSubscriptionFilter(n,i){let s=this.logGroups.get(n);if(!s)throw Error(`Log group not found: ${n}`);let o={id:`subscription-${Date.now()}-${this.filterCounter++}`,...i};if(!s.subscriptionFilters)s.subscriptionFilters=[];return s.subscriptionFilters.push(o),o}createKinesisSubscription(n){let i=this.logGroups.get(n.logGroupId);if(!i)throw Error(`Log group not found: ${n.logGroupId}`);return this.createSubscriptionFilter(n.logGroupId,{name:"KinesisSubscription",logGroupName:i.name,filterPattern:n.filterPattern||"",destinationArn:n.kinesisStreamArn,roleArn:n.roleArn,distribution:"Random"})}createLambdaSubscription(n){let i=this.logGroups.get(n.logGroupId);if(!i)throw Error(`Log group not found: ${n.logGroupId}`);return this.createSubscriptionFilter(n.logGroupId,{name:"LambdaSubscription",logGroupName:i.name,filterPattern:n.filterPattern||"",destinationArn:n.lambdaFunctionArn,distribution:"ByLogStream"})}createInsightsQuery(n){let i=`query-${Date.now()}-${this.queryCounter++}`,s={id:i,...n};return this.insightsQueries.set(i,s),s}createErrorAnalysisQuery(n){return this.createInsightsQuery({name:"Error Analysis",description:"Analyze error patterns and frequencies",query:`fields @timestamp, @message
3648
3648
  | filter @message like /ERROR/
3649
3649
  | stats count() by bin(5m)
3650
3650
  | sort @timestamp desc`,logGroupNames:n})}createLatencyAnalysisQuery(n){return this.createInsightsQuery({name:"Latency Analysis",description:"Analyze request latency patterns",query:`fields @timestamp, @duration
@@ -3654,7 +3654,7 @@ exports.handler = (event, _context, _callback) => {
3654
3654
  | filter @message like /ERROR/
3655
3655
  | stats count() as error_count by @message
3656
3656
  | sort error_count desc
3657
- | limit 20`,logGroupNames:n})}getLogGroup(n){return this.logGroups.get(n)}listLogGroups(){return Array.from(this.logGroups.values())}getInsightsQuery(n){return this.insightsQueries.get(n)}listInsightsQueries(){return Array.from(this.insightsQueries.values())}generateLogGroupCF(n){return{Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:n.name,...n.retentionDays&&{RetentionInDays:n.retentionDays},...n.kmsKeyId&&{KmsKeyId:n.kmsKeyId}}}}generateMetricFilterCF(n,i){return{Type:"AWS::Logs::MetricFilter",Properties:{FilterName:i.name,FilterPattern:i.filterPattern,LogGroupName:n.name,MetricTransformations:i.metricTransformations.map((s)=>({MetricName:s.metricName,MetricNamespace:s.metricNamespace,MetricValue:s.metricValue,...s.defaultValue!==void 0&&{DefaultValue:s.defaultValue},...s.unit&&{Unit:s.unit},...s.dimensions&&{Dimensions:s.dimensions}}))}}}generateSubscriptionFilterCF(n){return{Type:"AWS::Logs::SubscriptionFilter",Properties:{FilterName:n.name,FilterPattern:n.filterPattern,LogGroupName:n.logGroupName,DestinationArn:n.destinationArn,...n.roleArn&&{RoleArn:n.roleArn},...n.distribution&&{Distribution:n.distribution}}}}generateQueryDefinitionCF(n){return{Type:"AWS::Logs::QueryDefinition",Properties:{Name:n.name,QueryString:n.query,LogGroupNames:n.logGroupNames}}}createLogAggregation(n,i,s=7){let o=`aggregation-${Date.now()}-${this.logGroupCounter++}`,c=this.createLogGroup({name:n,retentionDays:s});return i.forEach((l)=>{this.createMetricFilter(c.id,{name:l.metric,filterPattern:l.pattern,metricTransformations:[{metricName:l.metric,metricNamespace:"CustomMetrics",metricValue:"1",defaultValue:0,unit:"Count"}]})}),{id:o,logGroup:n,filters:i,retention:s}}clear(){this.logGroups.clear(),this.queries.clear(),this.insightsQueries.clear(),this.logGroupCounter=0,this.filterCounter=0,this.queryCounter=0}}var oE=new em;class Vr{canaries=new Map;heartbeats=new Map;apiMonitors=new Map;canaryCounter=0;heartbeatCounter=0;apiMonitorCounter=0;alarmCounter=0;static RuntimeVersions={NODEJS_PUPPETEER_3_9:"syn-nodejs-puppeteer-3.9",NODEJS_PUPPETEER_4_0:"syn-nodejs-puppeteer-4.0",PYTHON_SELENIUM_1_3:"syn-python-selenium-1.3"};createCanary(n){let i=`canary-${Date.now()}-${this.canaryCounter++}`,s={id:i,...n};return this.canaries.set(i,s),s}createHeartbeatCanary(n){let i=`
3657
+ | limit 20`,logGroupNames:n})}getLogGroup(n){return this.logGroups.get(n)}listLogGroups(){return Array.from(this.logGroups.values())}getInsightsQuery(n){return this.insightsQueries.get(n)}listInsightsQueries(){return Array.from(this.insightsQueries.values())}generateLogGroupCF(n){return{Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:n.name,...n.retentionDays&&{RetentionInDays:n.retentionDays},...n.kmsKeyId&&{KmsKeyId:n.kmsKeyId}}}}generateMetricFilterCF(n,i){return{Type:"AWS::Logs::MetricFilter",Properties:{FilterName:i.name,FilterPattern:i.filterPattern,LogGroupName:n.name,MetricTransformations:i.metricTransformations.map((s)=>({MetricName:s.metricName,MetricNamespace:s.metricNamespace,MetricValue:s.metricValue,...s.defaultValue!==void 0&&{DefaultValue:s.defaultValue},...s.unit&&{Unit:s.unit},...s.dimensions&&{Dimensions:s.dimensions}}))}}}generateSubscriptionFilterCF(n){return{Type:"AWS::Logs::SubscriptionFilter",Properties:{FilterName:n.name,FilterPattern:n.filterPattern,LogGroupName:n.logGroupName,DestinationArn:n.destinationArn,...n.roleArn&&{RoleArn:n.roleArn},...n.distribution&&{Distribution:n.distribution}}}}generateQueryDefinitionCF(n){return{Type:"AWS::Logs::QueryDefinition",Properties:{Name:n.name,QueryString:n.query,LogGroupNames:n.logGroupNames}}}createLogAggregation(n,i,s=7){let o=`aggregation-${Date.now()}-${this.logGroupCounter++}`,c=this.createLogGroup({name:n,retentionDays:s});return i.forEach((l)=>{this.createMetricFilter(c.id,{name:l.metric,filterPattern:l.pattern,metricTransformations:[{metricName:l.metric,metricNamespace:"CustomMetrics",metricValue:"1",defaultValue:0,unit:"Count"}]})}),{id:o,logGroup:n,filters:i,retention:s}}clear(){this.logGroups.clear(),this.queries.clear(),this.insightsQueries.clear(),this.logGroupCounter=0,this.filterCounter=0,this.queryCounter=0}}var cE=new rm;class zr{canaries=new Map;heartbeats=new Map;apiMonitors=new Map;canaryCounter=0;heartbeatCounter=0;apiMonitorCounter=0;alarmCounter=0;static RuntimeVersions={NODEJS_PUPPETEER_3_9:"syn-nodejs-puppeteer-3.9",NODEJS_PUPPETEER_4_0:"syn-nodejs-puppeteer-4.0",PYTHON_SELENIUM_1_3:"syn-python-selenium-1.3"};createCanary(n){let i=`canary-${Date.now()}-${this.canaryCounter++}`,s={id:i,...n};return this.canaries.set(i,s),s}createHeartbeatCanary(n){let i=`
3658
3658
  const synthetics = require('Synthetics');
3659
3659
  const log = require('SyntheticsLogger');
3660
3660
 
@@ -3674,7 +3674,7 @@ const heartbeat = async function () {
3674
3674
  exports.handler = async () => {
3675
3675
  return await heartbeat();
3676
3676
  };
3677
- `;return this.createCanary({name:n.name,description:`Heartbeat monitor for ${n.url}`,runtimeVersion:Vr.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:i},schedule:{expression:`rate(${n.interval} minutes)`},runConfig:{timeoutInSeconds:60,memoryInMB:960,activeTracing:!0},artifactS3Location:`s3://${n.s3Bucket}/canary-artifacts/${n.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}createAPICanary(n){let i=`
3677
+ `;return this.createCanary({name:n.name,description:`Heartbeat monitor for ${n.url}`,runtimeVersion:zr.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:i},schedule:{expression:`rate(${n.interval} minutes)`},runConfig:{timeoutInSeconds:60,memoryInMB:960,activeTracing:!0},artifactS3Location:`s3://${n.s3Bucket}/canary-artifacts/${n.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}createAPICanary(n){let i=`
3678
3678
  const synthetics = require('Synthetics');
3679
3679
  const log = require('SyntheticsLogger');
3680
3680
 
@@ -3703,7 +3703,7 @@ const apiCheck = async function () {
3703
3703
  exports.handler = async () => {
3704
3704
  return await apiCheck();
3705
3705
  };
3706
- `;return this.createCanary({name:n.name,description:`API monitor for ${n.baseUrl}`,runtimeVersion:Vr.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:i},schedule:{expression:`rate(${n.interval} minutes)`},runConfig:{timeoutInSeconds:120,memoryInMB:960,activeTracing:!0},artifactS3Location:`s3://${n.s3Bucket}/canary-artifacts/${n.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}createVisualRegressionCanary(n){let i=`
3706
+ `;return this.createCanary({name:n.name,description:`API monitor for ${n.baseUrl}`,runtimeVersion:zr.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:i},schedule:{expression:`rate(${n.interval} minutes)`},runConfig:{timeoutInSeconds:120,memoryInMB:960,activeTracing:!0},artifactS3Location:`s3://${n.s3Bucket}/canary-artifacts/${n.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}createVisualRegressionCanary(n){let i=`
3707
3707
  const synthetics = require('Synthetics');
3708
3708
  const log = require('SyntheticsLogger');
3709
3709
 
@@ -3723,7 +3723,7 @@ const visualCheck = async function () {
3723
3723
  exports.handler = async () => {
3724
3724
  return await visualCheck();
3725
3725
  };
3726
- `;return this.createCanary({name:n.name,description:`Visual regression monitor for ${n.url}`,runtimeVersion:Vr.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:i},schedule:{expression:`rate(${n.interval} minutes)`},runConfig:{timeoutInSeconds:120,memoryInMB:1024,activeTracing:!0},artifactS3Location:`s3://${n.s3Bucket}/canary-artifacts/${n.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}createWorkflowCanary(n){let i=`
3726
+ `;return this.createCanary({name:n.name,description:`Visual regression monitor for ${n.url}`,runtimeVersion:zr.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:i},schedule:{expression:`rate(${n.interval} minutes)`},runConfig:{timeoutInSeconds:120,memoryInMB:1024,activeTracing:!0},artifactS3Location:`s3://${n.s3Bucket}/canary-artifacts/${n.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}createWorkflowCanary(n){let i=`
3727
3727
  const synthetics = require('Synthetics');
3728
3728
  const log = require('SyntheticsLogger');
3729
3729
 
@@ -3745,35 +3745,35 @@ const workflowCheck = async function () {
3745
3745
  exports.handler = async () => {
3746
3746
  return await workflowCheck();
3747
3747
  };
3748
- `;return this.createCanary({name:n.name,description:n.description,runtimeVersion:Vr.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:i},schedule:{expression:`rate(${n.interval} minutes)`},runConfig:{timeoutInSeconds:180,memoryInMB:1024,activeTracing:!0},artifactS3Location:`s3://${n.s3Bucket}/canary-artifacts/${n.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}generateActionScript(n){switch(n.type){case"click":return`await page.click('${n.selector}');`;case"type":return`await page.type('${n.selector}', '${n.value}');`;case"wait":return`await page.waitForTimeout(${n.duration});`;case"waitForSelector":return`await page.waitForSelector('${n.selector}');`;default:return""}}createAlarm(n,i){let s=this.canaries.get(n);if(!s)throw Error(`Canary not found: ${n}`);let o={id:`alarm-${Date.now()}-${this.alarmCounter++}`,...i};if(!s.alarms)s.alarms=[];return s.alarms.push(o),o}getCanary(n){return this.canaries.get(n)}listCanaries(){return Array.from(this.canaries.values())}generateCanaryCF(n){let i={Type:"AWS::Synthetics::Canary",Properties:{Name:n.name,RuntimeVersion:n.runtimeVersion,ExecutionRoleArn:{"Fn::GetAtt":["CanaryExecutionRole","Arn"]},Schedule:{Expression:n.schedule.expression,...n.schedule.durationInSeconds&&{DurationInSeconds:n.schedule.durationInSeconds}},ArtifactS3Location:n.artifactS3Location,StartCanaryAfterCreation:!0}};if(n.code.type==="script")i.Properties.Code={Handler:n.handler,Script:n.code.script};else i.Properties.Code={Handler:n.handler,S3Bucket:n.code.s3Bucket,S3Key:n.code.s3Key,...n.code.s3Version&&{S3ObjectVersion:n.code.s3Version}};if(n.runConfig)i.Properties.RunConfig={TimeoutInSeconds:n.runConfig.timeoutInSeconds,MemoryInMB:n.runConfig.memoryInMB,...n.runConfig.environmentVariables&&{EnvironmentVariables:n.runConfig.environmentVariables},...n.runConfig.activeTracing!==void 0&&{ActiveTracing:n.runConfig.activeTracing}};if(n.vpcConfig)i.Properties.VPCConfig={SubnetIds:n.vpcConfig.subnetIds,SecurityGroupIds:n.vpcConfig.securityGroupIds};if(n.successRetentionPeriod)i.Properties.SuccessRetentionPeriod=n.successRetentionPeriod;if(n.failureRetentionPeriod)i.Properties.FailureRetentionPeriod=n.failureRetentionPeriod;return i}generateCanaryRoleCF(){return{Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole","arn:aws:iam::aws:policy/CloudWatchSyntheticsFullAccess"],Policies:[{PolicyName:"CanaryS3Policy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["s3:PutObject","s3:GetBucketLocation"],Resource:["arn:aws:s3:::*/*"]}]}}]}}}clear(){this.canaries.clear(),this.heartbeats.clear(),this.apiMonitors.clear(),this.canaryCounter=0,this.heartbeatCounter=0,this.apiMonitorCounter=0,this.alarmCounter=0}}var aE=new Vr;class tm{plans=new Map;migrations=new Map;planCounter=0;migrationCounter=0;createPlan(n){let i=`migration-plan-${Date.now()}-${this.planCounter++}`,s={id:i,...n};return this.plans.set(i,s),s}createMigration(n){let i=`migration-${Date.now()}-${this.migrationCounter++}`,s=this.generateChecksum(n.up+n.down),o={id:i,checksum:s,...n};return this.migrations.set(i,o),o}createSchemaMigration(n){let{up:i,down:s}=this.generateSchemaSQL(n.changes,n.tableName,n.engine);return this.createMigration({version:n.version,name:n.name,description:`Schema changes for ${n.tableName}`,up:i,down:s})}createDataMigration(n){return this.createMigration({version:n.version,name:n.name,description:n.description,up:n.upSQL,down:n.downSQL})}addMigrationToPlan(n,i){let s=this.plans.get(n);if(!s)throw Error(`Migration plan not found: ${n}`);s.migrations.push(i)}async executePlan(n,i=!1){let s=this.plans.get(n);if(!s)throw Error(`Migration plan not found: ${n}`);let o=Date.now(),c=[],l=[];if(console.log(`${i?"[DRY RUN] ":""}Executing migration plan: ${s.name}`),console.log(`Database: ${s.database.type} - ${s.database.identifier}`),console.log(`Migrations to apply: ${s.migrations.length}
3748
+ `;return this.createCanary({name:n.name,description:n.description,runtimeVersion:zr.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:i},schedule:{expression:`rate(${n.interval} minutes)`},runConfig:{timeoutInSeconds:180,memoryInMB:1024,activeTracing:!0},artifactS3Location:`s3://${n.s3Bucket}/canary-artifacts/${n.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}generateActionScript(n){switch(n.type){case"click":return`await page.click('${n.selector}');`;case"type":return`await page.type('${n.selector}', '${n.value}');`;case"wait":return`await page.waitForTimeout(${n.duration});`;case"waitForSelector":return`await page.waitForSelector('${n.selector}');`;default:return""}}createAlarm(n,i){let s=this.canaries.get(n);if(!s)throw Error(`Canary not found: ${n}`);let o={id:`alarm-${Date.now()}-${this.alarmCounter++}`,...i};if(!s.alarms)s.alarms=[];return s.alarms.push(o),o}getCanary(n){return this.canaries.get(n)}listCanaries(){return Array.from(this.canaries.values())}generateCanaryCF(n){let i={Type:"AWS::Synthetics::Canary",Properties:{Name:n.name,RuntimeVersion:n.runtimeVersion,ExecutionRoleArn:{"Fn::GetAtt":["CanaryExecutionRole","Arn"]},Schedule:{Expression:n.schedule.expression,...n.schedule.durationInSeconds&&{DurationInSeconds:n.schedule.durationInSeconds}},ArtifactS3Location:n.artifactS3Location,StartCanaryAfterCreation:!0}};if(n.code.type==="script")i.Properties.Code={Handler:n.handler,Script:n.code.script};else i.Properties.Code={Handler:n.handler,S3Bucket:n.code.s3Bucket,S3Key:n.code.s3Key,...n.code.s3Version&&{S3ObjectVersion:n.code.s3Version}};if(n.runConfig)i.Properties.RunConfig={TimeoutInSeconds:n.runConfig.timeoutInSeconds,MemoryInMB:n.runConfig.memoryInMB,...n.runConfig.environmentVariables&&{EnvironmentVariables:n.runConfig.environmentVariables},...n.runConfig.activeTracing!==void 0&&{ActiveTracing:n.runConfig.activeTracing}};if(n.vpcConfig)i.Properties.VPCConfig={SubnetIds:n.vpcConfig.subnetIds,SecurityGroupIds:n.vpcConfig.securityGroupIds};if(n.successRetentionPeriod)i.Properties.SuccessRetentionPeriod=n.successRetentionPeriod;if(n.failureRetentionPeriod)i.Properties.FailureRetentionPeriod=n.failureRetentionPeriod;return i}generateCanaryRoleCF(){return{Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole","arn:aws:iam::aws:policy/CloudWatchSyntheticsFullAccess"],Policies:[{PolicyName:"CanaryS3Policy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["s3:PutObject","s3:GetBucketLocation"],Resource:["arn:aws:s3:::*/*"]}]}}]}}}clear(){this.canaries.clear(),this.heartbeats.clear(),this.apiMonitors.clear(),this.canaryCounter=0,this.heartbeatCounter=0,this.apiMonitorCounter=0,this.alarmCounter=0}}var dE=new zr;class nm{plans=new Map;migrations=new Map;planCounter=0;migrationCounter=0;createPlan(n){let i=`migration-plan-${Date.now()}-${this.planCounter++}`,s={id:i,...n};return this.plans.set(i,s),s}createMigration(n){let i=`migration-${Date.now()}-${this.migrationCounter++}`,s=this.generateChecksum(n.up+n.down),o={id:i,checksum:s,...n};return this.migrations.set(i,o),o}createSchemaMigration(n){let{up:i,down:s}=this.generateSchemaSQL(n.changes,n.tableName,n.engine);return this.createMigration({version:n.version,name:n.name,description:`Schema changes for ${n.tableName}`,up:i,down:s})}createDataMigration(n){return this.createMigration({version:n.version,name:n.name,description:n.description,up:n.upSQL,down:n.downSQL})}addMigrationToPlan(n,i){let s=this.plans.get(n);if(!s)throw Error(`Migration plan not found: ${n}`);s.migrations.push(i)}async executePlan(n,i=!1){let s=this.plans.get(n);if(!s)throw Error(`Migration plan not found: ${n}`);let o=Date.now(),c=[],l=[];if(console.log(`${i?"[DRY RUN] ":""}Executing migration plan: ${s.name}`),console.log(`Database: ${s.database.type} - ${s.database.identifier}`),console.log(`Migrations to apply: ${s.migrations.length}
3749
3749
  `),s.backupBeforeMigration&&!i)console.log("Creating database backup before migration...");for(let h of s.migrations)try{if(console.log(`Applying migration: ${h.version} - ${h.name}`),!i){if(this.generateChecksum(h.up+h.down)!==h.checksum)throw Error("Migration checksum mismatch - migration has been modified");let y=Date.now();h.appliedAt=new Date,h.executionTimeMs=Date.now()-y,console.log(`✓ Applied in ${h.executionTimeMs}ms
3750
3750
  `)}else console.log(`[SKIPPED - DRY RUN]
3751
3751
  `);c.push(h.version)}catch(y){if(console.error(`✗ Failed: ${y instanceof Error?y.message:String(y)}
3752
3752
  `),l.push(h.version),!i)return console.log("Rolling back previously applied migrations..."),await this.rollbackMigrations(c.reverse(),s),{success:!1,version:h.version,appliedMigrations:[],failedMigrations:l,executionTimeMs:Date.now()-o,error:y instanceof Error?y.message:String(y),rollbackPerformed:!0}}let u=Date.now()-o;return console.log(`${i?"[DRY RUN] ":""}Migration plan completed successfully`),console.log(`Total time: ${u}ms`),{success:!0,version:s.migrations[s.migrations.length-1]?.version||"unknown",appliedMigrations:c,failedMigrations:l,executionTimeMs:u}}async rollbackMigrations(n,i){for(let s of n){let o=i.migrations.find((c)=>c.version===s);if(o)console.log(`Rolling back: ${o.version} - ${o.name}`),o.rolledBackAt=new Date,console.log(`✓ Rolled back
3753
3753
  `)}}getMigrationStatus(n){let i=this.plans.get(n);if(!i)throw Error(`Migration plan not found: ${n}`);let s=i.migrations.filter((c)=>c.appliedAt&&!c.rolledBackAt),o=i.migrations.filter((c)=>!c.appliedAt);return{currentVersion:s[s.length-1]?.version||"0.0.0",pendingMigrations:o,appliedMigrations:s,lastMigration:s[s.length-1]}}generateSchemaSQL(n,i,s="postgres"){let o=[],c=[];for(let l of n)switch(l.type){case"add_column":o.push(`ALTER TABLE ${i} ADD COLUMN ${l.columnName} ${l.columnType}${l.nullable===!1?" NOT NULL":""}${l.defaultValue?` DEFAULT ${l.defaultValue}`:""}; `),c.push(`ALTER TABLE ${i} DROP COLUMN ${l.columnName};`);break;case"drop_column":o.push(`ALTER TABLE ${i} DROP COLUMN ${l.columnName};`),c.push(`-- Cannot restore dropped column ${l.columnName}`);break;case"modify_column":if(s==="postgres")o.push(`ALTER TABLE ${i} ALTER COLUMN ${l.columnName} TYPE ${l.newType};`);else o.push(`ALTER TABLE ${i} MODIFY COLUMN ${l.columnName} ${l.newType};`);c.push(`-- Reverting ${l.columnName} type change requires manual intervention`);break;case"add_index":o.push(`CREATE INDEX ${l.indexName} ON ${i} (${(l.columns??[]).join(", ")});`),c.push(`DROP INDEX ${l.indexName};`);break;case"drop_index":o.push(`DROP INDEX ${l.indexName};`),c.push(`-- Cannot restore index ${l.indexName} without schema details`);break}return{up:o.join(`
3754
3754
  `),down:c.reverse().join(`
3755
- `)}}generateChecksum(n){let i=0;for(let s=0;s<n.length;s++){let o=n.charCodeAt(s);i=(i<<5)-i+o,i=i&i}return i.toString(16)}validatePlan(n){let i=this.plans.get(n);if(!i)return{valid:!1,errors:["Migration plan not found"]};let s=[],o=new Set;for(let c of i.migrations){if(o.has(c.version))s.push(`Duplicate migration version: ${c.version}`);o.add(c.version)}for(let c of i.migrations)if(!c.down||c.down.trim()==="")s.push(`Migration ${c.version} is missing rollback SQL`);for(let c of i.migrations)if(this.generateChecksum(c.up+c.down)!==c.checksum)s.push(`Migration ${c.version} has invalid checksum`);return{valid:s.length===0,errors:s}}getPlan(n){return this.plans.get(n)}listPlans(){return Array.from(this.plans.values())}getMigration(n){return this.migrations.get(n)}listMigrations(){return Array.from(this.migrations.values())}clear(){this.plans.clear(),this.migrations.clear(),this.planCounter=0,this.migrationCounter=0}}var cE=new tm;class rm{replicas=new Map;replicationGroups=new Map;proxies=new Map;proxyTargets=new Map;replicaCounter=0;groupCounter=0;proxyCounter=0;targetCounter=0;createReplica(n){let i=`replica-${Date.now()}-${this.replicaCounter++}`,s={id:i,status:"creating",...n};return this.replicas.set(i,s),s}createRDSReplica(n){return this.createReplica({name:n.name,sourceDatabase:n.sourceDatabase,region:n.region||"us-east-1",instanceClass:n.instanceClass||"db.t3.medium",multiAZ:n.multiAZ||!1,autoMinorVersionUpgrade:!0,backupRetentionPeriod:7})}createCrossRegionReplica(n){return this.createReplica({name:n.name,sourceDatabase:n.sourceDatabase,region:n.targetRegion,instanceClass:n.instanceClass||"db.t3.medium",multiAZ:!0,autoMinorVersionUpgrade:!0,backupRetentionPeriod:7})}createReplicationGroup(n){let i=`replication-group-${Date.now()}-${this.groupCounter++}`,s={id:i,...n};return this.replicationGroups.set(i,s),s}createAutoScalingReplicationGroup(n){return this.createReplicationGroup({name:n.name,primaryDatabase:n.primaryDatabase,replicas:[],loadBalancing:n.loadBalancing||{type:"round-robin"},failoverEnabled:!0,autoScaling:{enabled:!0,minReplicas:n.minReplicas,maxReplicas:n.maxReplicas,targetCPU:n.targetCPU||70,scaleUpCooldown:300,scaleDownCooldown:600}})}addReplicaToGroup(n,i){let s=this.replicationGroups.get(n);if(!s)throw Error(`Replication group not found: ${n}`);s.replicas.push(i)}createProxy(n){let i=`rds-proxy-${Date.now()}-${this.proxyCounter++}`,s={id:i,...n};return this.proxies.set(i,s),s}createConnectionPoolProxy(n){return this.createProxy({name:n.name,engineFamily:n.engineFamily,targetDatabase:n.targetDatabase,maxConnectionsPercent:n.maxConnections||100,maxIdleConnectionsPercent:50,connectionBorrowTimeout:120,sessionPinningFilters:["EXCLUDE_VARIABLE_SETS"],requireTLS:!0,idleClientTimeout:1800,vpcSubnetIds:n.vpcSubnetIds,securityGroupIds:n.securityGroupIds,secretArn:n.secretArn})}createServerlessProxy(n){return this.createProxy({name:n.name,engineFamily:n.engineFamily,targetDatabase:n.targetDatabase,maxConnectionsPercent:100,maxIdleConnectionsPercent:10,connectionBorrowTimeout:60,sessionPinningFilters:["EXCLUDE_VARIABLE_SETS"],requireTLS:!0,idleClientTimeout:300,vpcSubnetIds:n.vpcSubnetIds,securityGroupIds:n.securityGroupIds,secretArn:n.secretArn})}addProxyTarget(n){let i=`proxy-target-${Date.now()}-${this.targetCounter++}`,s={id:i,...n};return this.proxyTargets.set(i,s),s}promoteReplica(n){let i=this.replicas.get(n);if(!i)return{success:!1,message:"Replica not found"};if(console.log(`Promoting replica to primary: ${i.name}`),console.log(`Region: ${i.region}`),console.log(`
3755
+ `)}}generateChecksum(n){let i=0;for(let s=0;s<n.length;s++){let o=n.charCodeAt(s);i=(i<<5)-i+o,i=i&i}return i.toString(16)}validatePlan(n){let i=this.plans.get(n);if(!i)return{valid:!1,errors:["Migration plan not found"]};let s=[],o=new Set;for(let c of i.migrations){if(o.has(c.version))s.push(`Duplicate migration version: ${c.version}`);o.add(c.version)}for(let c of i.migrations)if(!c.down||c.down.trim()==="")s.push(`Migration ${c.version} is missing rollback SQL`);for(let c of i.migrations)if(this.generateChecksum(c.up+c.down)!==c.checksum)s.push(`Migration ${c.version} has invalid checksum`);return{valid:s.length===0,errors:s}}getPlan(n){return this.plans.get(n)}listPlans(){return Array.from(this.plans.values())}getMigration(n){return this.migrations.get(n)}listMigrations(){return Array.from(this.migrations.values())}clear(){this.plans.clear(),this.migrations.clear(),this.planCounter=0,this.migrationCounter=0}}var lE=new nm;class im{replicas=new Map;replicationGroups=new Map;proxies=new Map;proxyTargets=new Map;replicaCounter=0;groupCounter=0;proxyCounter=0;targetCounter=0;createReplica(n){let i=`replica-${Date.now()}-${this.replicaCounter++}`,s={id:i,status:"creating",...n};return this.replicas.set(i,s),s}createRDSReplica(n){return this.createReplica({name:n.name,sourceDatabase:n.sourceDatabase,region:n.region||"us-east-1",instanceClass:n.instanceClass||"db.t3.medium",multiAZ:n.multiAZ||!1,autoMinorVersionUpgrade:!0,backupRetentionPeriod:7})}createCrossRegionReplica(n){return this.createReplica({name:n.name,sourceDatabase:n.sourceDatabase,region:n.targetRegion,instanceClass:n.instanceClass||"db.t3.medium",multiAZ:!0,autoMinorVersionUpgrade:!0,backupRetentionPeriod:7})}createReplicationGroup(n){let i=`replication-group-${Date.now()}-${this.groupCounter++}`,s={id:i,...n};return this.replicationGroups.set(i,s),s}createAutoScalingReplicationGroup(n){return this.createReplicationGroup({name:n.name,primaryDatabase:n.primaryDatabase,replicas:[],loadBalancing:n.loadBalancing||{type:"round-robin"},failoverEnabled:!0,autoScaling:{enabled:!0,minReplicas:n.minReplicas,maxReplicas:n.maxReplicas,targetCPU:n.targetCPU||70,scaleUpCooldown:300,scaleDownCooldown:600}})}addReplicaToGroup(n,i){let s=this.replicationGroups.get(n);if(!s)throw Error(`Replication group not found: ${n}`);s.replicas.push(i)}createProxy(n){let i=`rds-proxy-${Date.now()}-${this.proxyCounter++}`,s={id:i,...n};return this.proxies.set(i,s),s}createConnectionPoolProxy(n){return this.createProxy({name:n.name,engineFamily:n.engineFamily,targetDatabase:n.targetDatabase,maxConnectionsPercent:n.maxConnections||100,maxIdleConnectionsPercent:50,connectionBorrowTimeout:120,sessionPinningFilters:["EXCLUDE_VARIABLE_SETS"],requireTLS:!0,idleClientTimeout:1800,vpcSubnetIds:n.vpcSubnetIds,securityGroupIds:n.securityGroupIds,secretArn:n.secretArn})}createServerlessProxy(n){return this.createProxy({name:n.name,engineFamily:n.engineFamily,targetDatabase:n.targetDatabase,maxConnectionsPercent:100,maxIdleConnectionsPercent:10,connectionBorrowTimeout:60,sessionPinningFilters:["EXCLUDE_VARIABLE_SETS"],requireTLS:!0,idleClientTimeout:300,vpcSubnetIds:n.vpcSubnetIds,securityGroupIds:n.securityGroupIds,secretArn:n.secretArn})}addProxyTarget(n){let i=`proxy-target-${Date.now()}-${this.targetCounter++}`,s={id:i,...n};return this.proxyTargets.set(i,s),s}promoteReplica(n){let i=this.replicas.get(n);if(!i)return{success:!1,message:"Replica not found"};if(console.log(`Promoting replica to primary: ${i.name}`),console.log(`Region: ${i.region}`),console.log(`
3756
3756
  1. Checking replication lag...`),i.replicationLag&&i.replicationLag>5000)return{success:!1,message:`Replication lag too high: ${i.replicationLag}ms`};return console.log(` Replication lag: ${i.replicationLag||0}ms (acceptable)`),console.log(`
3757
3757
  2. Promoting replica to standalone instance...`),console.log(`
3758
3758
  3. Updating DNS records...`),console.log(`
3759
3759
  4. Updating application configuration...`),console.log(`
3760
- ✓ Promotion completed successfully`),i.status="available",{success:!0,message:"Replica promoted successfully"}}getReplicationLag(n){if(!this.replicas.get(n))throw Error(`Replica not found: ${n}`);return Math.floor(Math.random()*1000)}getReplica(n){return this.replicas.get(n)}listReplicas(){return Array.from(this.replicas.values())}getReplicationGroup(n){return this.replicationGroups.get(n)}listReplicationGroups(){return Array.from(this.replicationGroups.values())}getProxy(n){return this.proxies.get(n)}listProxies(){return Array.from(this.proxies.values())}generateReplicaCF(n){return{Type:"AWS::RDS::DBInstance",Properties:{SourceDBInstanceIdentifier:n.sourceDatabase,DBInstanceIdentifier:n.name,DBInstanceClass:n.instanceClass,MultiAZ:n.multiAZ||!1,AutoMinorVersionUpgrade:n.autoMinorVersionUpgrade??!0,...n.backupRetentionPeriod&&{BackupRetentionPeriod:n.backupRetentionPeriod},...n.preferredBackupWindow&&{PreferredBackupWindow:n.preferredBackupWindow},...n.preferredMaintenanceWindow&&{PreferredMaintenanceWindow:n.preferredMaintenanceWindow}}}}generateProxyCF(n){return{Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:n.name,EngineFamily:n.engineFamily,Auth:[{AuthScheme:"SECRETS",SecretArn:n.secretArn,IAMAuth:"DISABLED"}],RoleArn:{"Fn::GetAtt":["RDSProxyRole","Arn"]},VpcSubnetIds:n.vpcSubnetIds,VpcSecurityGroupIds:n.securityGroupIds,RequireTLS:n.requireTLS??!0,IdleClientTimeout:n.idleClientTimeout||1800,...n.maxConnectionsPercent&&{MaxConnectionsPercent:n.maxConnectionsPercent},...n.maxIdleConnectionsPercent&&{MaxIdleConnectionsPercent:n.maxIdleConnectionsPercent},...n.connectionBorrowTimeout&&{ConnectionBorrowTimeout:n.connectionBorrowTimeout}}}}generateProxyTargetCF(n,i){return{Type:"AWS::RDS::DBProxyTargetGroup",Properties:{DBProxyName:i.name,TargetGroupName:"default",DBInstanceIdentifiers:[n.targetArn],ConnectionPoolConfig:{MaxConnectionsPercent:100,MaxIdleConnectionsPercent:50,ConnectionBorrowTimeout:120}}}}generateProxyRoleCF(){return{Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"rds.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"RDSProxySecretsPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],Resource:"arn:aws:secretsmanager:*:*:secret:*"},{Effect:"Allow",Action:["kms:Decrypt"],Resource:"arn:aws:kms:*:*:key/*",Condition:{StringEquals:{"kms:ViaService":"secretsmanager.*.amazonaws.com"}}}]}}]}}}clear(){this.replicas.clear(),this.replicationGroups.clear(),this.proxies.clear(),this.proxyTargets.clear(),this.replicaCounter=0,this.groupCounter=0,this.proxyCounter=0,this.targetCounter=0}}var dE=new rm;class nm{insights=new Map;slowQueryLogs=new Map;queryMetrics=new Map;reports=new Map;indexRecommendations=new Map;insightsCounter=0;logCounter=0;metricCounter=0;reportCounter=0;recommendationCounter=0;enablePerformanceInsights(n){let i=`pi-${Date.now()}-${this.insightsCounter++}`,s={id:i,name:n.name,databaseIdentifier:n.databaseIdentifier,enabled:!0,retentionPeriod:n.retentionPeriod||7,kmsKeyId:n.kmsKeyId};return this.insights.set(i,s),s}enableSlowQueryLog(n){let i=`slow-query-${Date.now()}-${this.logCounter++}`,s={id:i,name:n.name,databaseIdentifier:n.databaseIdentifier,enabled:!0,logDestination:n.logDestination,cloudwatchLogGroup:n.cloudwatchLogGroup,s3Bucket:n.s3Bucket,s3Prefix:n.s3Bucket?"slow-queries/":void 0,minExecutionTime:n.minExecutionTime||1000};return this.slowQueryLogs.set(i,s),s}recordQueryMetric(n){let i=`metric-${Date.now()}-${this.metricCounter++}`,s={id:i,timestamp:new Date,...n};return this.queryMetrics.set(i,s),s}generatePerformanceReport(n){let i=`report-${Date.now()}-${this.reportCounter++}`,s={avgCPU:Math.random()*60+20,maxCPU:Math.random()*30+70,avgConnections:Math.floor(Math.random()*50+10),maxConnections:Math.floor(Math.random()*50+100),avgReadIOPS:Math.floor(Math.random()*1000+500),avgWriteIOPS:Math.floor(Math.random()*500+200),avgReadThroughput:Math.random()*50+10,avgWriteThroughput:Math.random()*20+5,avgReadLatency:Math.random()*5+1,avgWriteLatency:Math.random()*8+2,cacheHitRatio:Math.random()*10+90,deadlocks:Math.floor(Math.random()*5),longRunningTransactions:Math.floor(Math.random()*10)},o=Array.from(this.queryMetrics.values()),c=o.sort((y,f)=>f.executionCount-y.executionCount).slice(0,10),l=o.filter((y)=>y.avgExecutionTime>1000).sort((y,f)=>f.avgExecutionTime-y.avgExecutionTime).slice(0,10),u=this.generateRecommendations(s,l),h={id:i,name:n.name,databaseIdentifier:n.databaseIdentifier,reportType:n.reportType,metrics:s,topQueries:c,slowQueries:l,recommendations:u,generatedAt:new Date};return this.reports.set(i,h),h}generateRecommendations(n,i){let s=[];if(n.avgCPU>70)s.push({type:"scaling",severity:"high",title:"High CPU Usage",description:`Average CPU usage is ${n.avgCPU.toFixed(1)}%, which is above the recommended threshold of 70%.`,impact:"Performance degradation, increased latency, potential timeouts",effort:"medium"});if(n.cacheHitRatio<95)s.push({type:"configuration",severity:"medium",title:"Low Cache Hit Ratio",description:`Cache hit ratio is ${n.cacheHitRatio.toFixed(1)}%. Consider increasing buffer pool size.`,impact:"Increased disk I/O, slower query performance",effort:"low"});if(n.deadlocks>0)s.push({type:"query",severity:"medium",title:"Deadlocks Detected",description:`${n.deadlocks} deadlock(s) detected. Review transaction isolation levels and query patterns.`,impact:"Transaction failures, application errors",effort:"high"});if(i.length>0)s.push({type:"index",severity:"high",title:"Slow Queries Detected",description:`${i.length} slow queries detected. Consider adding indexes or optimizing queries.`,impact:"High latency, poor user experience",effort:"medium"});if(n.avgReadLatency>10||n.avgWriteLatency>10)s.push({type:"scaling",severity:"high",title:"High I/O Latency",description:"Read or write latency is high. Consider upgrading to Provisioned IOPS or moving to a larger instance.",impact:"Slow query execution, application timeouts",effort:"medium"});return s}analyzeQuery(n){let i=`analysis-${Date.now()}-${Math.random().toString(36).slice(2,9)}`,s=[{id:1,operation:"Seq Scan",table:"users",rows:1e4,cost:850.5,children:[]}],o=[];if(n.toLowerCase().includes("select *"))o.push({type:"full_table_scan",severity:"warning",description:"Query selects all columns. Consider selecting only required columns."});if(!n.toLowerCase().includes("where")&&n.toLowerCase().includes("select"))o.push({type:"full_table_scan",severity:"critical",description:"Query has no WHERE clause and may scan entire table."});return{id:i,queryId:i,sql:n,executionPlan:s,bottlenecks:o,recommendations:["Add appropriate indexes on WHERE clause columns","Consider using EXPLAIN ANALYZE to get actual execution statistics","Review and optimize JOIN conditions"],estimatedCost:s[0].cost}}recommendIndex(n){let i=`index-rec-${Date.now()}-${this.recommendationCounter++}`,s=`idx_${n.tableName}_${n.columns.join("_")}`,o={id:i,tableName:n.tableName,columns:n.columns,reason:n.reason,estimatedImprovement:n.estimatedImprovement||50,estimatedSize:n.columns.length*10,createSQL:`CREATE INDEX ${s} ON ${n.tableName} (${n.columns.join(", ")});`};return this.indexRecommendations.set(i,o),o}getInsights(n){return this.insights.get(n)}listInsights(){return Array.from(this.insights.values())}getSlowQueryLog(n){return this.slowQueryLogs.get(n)}listSlowQueryLogs(){return Array.from(this.slowQueryLogs.values())}getReport(n){return this.reports.get(n)}listReports(){return Array.from(this.reports.values())}listIndexRecommendations(){return Array.from(this.indexRecommendations.values())}generatePerformanceInsightsCF(n){return{EnablePerformanceInsights:n.enabled,PerformanceInsightsRetentionPeriod:n.retentionPeriod,...n.kmsKeyId&&{PerformanceInsightsKMSKeyId:n.kmsKeyId}}}generateSlowQueryAlarmCF(n){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:n.alarmName,AlarmDescription:"Alert when slow queries exceed threshold",MetricName:"SlowQueryCount",Namespace:"AWS/RDS",Statistic:"Sum",Period:300,EvaluationPeriods:1,Threshold:n.threshold,ComparisonOperator:"GreaterThanThreshold",...n.snsTopicArn&&{AlarmActions:[n.snsTopicArn]}}}}clear(){this.insights.clear(),this.slowQueryLogs.clear(),this.queryMetrics.clear(),this.reports.clear(),this.indexRecommendations.clear(),this.insightsCounter=0,this.logCounter=0,this.metricCounter=0,this.reportCounter=0,this.recommendationCounter=0}}var lE=new nm;class im{users=new Map;roles=new Map;audits=new Map;userCounter=0;roleCounter=0;auditCounter=0;createUser(n){let i=`db-user-${Date.now()}-${this.userCounter++}`,s={id:i,createdAt:new Date,...n};return this.users.set(i,s),s}createReadOnlyUser(n){let i=n.tables?n.tables.map((s)=>({database:n.database,table:s,privileges:["SELECT"]})):[{database:n.database,privileges:["SELECT"]}];return this.createUser({username:n.username,database:n.database,privileges:i,passwordSecretArn:n.passwordSecretArn,rotationEnabled:!0,rotationDays:90})}createReadWriteUser(n){let i=n.tables?n.tables.map((s)=>({database:n.database,table:s,privileges:["SELECT","INSERT","UPDATE","DELETE"]})):[{database:n.database,privileges:["SELECT","INSERT","UPDATE","DELETE"]}];return this.createUser({username:n.username,database:n.database,privileges:i,passwordSecretArn:n.passwordSecretArn,rotationEnabled:!0,rotationDays:60})}createAdminUser(n){return this.createUser({username:n.username,database:n.database,privileges:[{database:n.database,privileges:["ALL"]}],passwordSecretArn:n.passwordSecretArn,rotationEnabled:!0,rotationDays:30})}createApplicationUser(n){let i=n.tables.map((s)=>({database:n.database,table:s.name,privileges:s.privileges}));return this.createUser({username:n.username,database:n.database,privileges:i,passwordSecretArn:n.passwordSecretArn,rotationEnabled:!0,rotationDays:90})}createRole(n){let i=`role-${Date.now()}-${this.roleCounter++}`,s={id:i,users:[],...n};return this.roles.set(i,s),s}assignUserToRole(n,i){let s=this.users.get(n),o=this.roles.get(i);if(!s)throw Error(`User not found: ${n}`);if(!o)throw Error(`Role not found: ${i}`);o.users.push(n);for(let c of o.privileges){let l=s.privileges.find((u)=>u.database===c.database&&u.table===c.table);if(l)l.privileges=Array.from(new Set([...l.privileges,...c.privileges]));else s.privileges.push({...c})}}grantPrivileges(n,i){let s=this.users.get(n);if(!s)return{success:!1,message:"User not found"};for(let o of i){let c=s.privileges.find((l)=>l.database===o.database&&l.table===o.table);if(c)c.privileges=Array.from(new Set([...c.privileges,...o.privileges]));else s.privileges.push(o)}return this.auditAccess({username:s.username,action:"GRANT",database:i[0]?.database,table:i[0]?.table,success:!0}),{success:!0,message:"Privileges granted successfully"}}revokePrivileges(n,i){let s=this.users.get(n);if(!s)return{success:!1,message:"User not found"};for(let o of i){let c=s.privileges.findIndex((l)=>l.database===o.database&&l.table===o.table);if(c!==-1){let l=s.privileges[c];if(l.privileges=l.privileges.filter((u)=>!o.privileges.includes(u)),l.privileges.length===0)s.privileges.splice(c,1)}}return this.auditAccess({username:s.username,action:"REVOKE",database:i[0]?.database,table:i[0]?.table,success:!0}),{success:!0,message:"Privileges revoked successfully"}}rotatePassword(n){let i=this.users.get(n);if(!i)return{success:!1};let s=`arn:aws:secretsmanager:us-east-1:123456789012:secret:db-${i.username}-${Date.now()}`;return i.passwordSecretArn=s,i.lastRotated=new Date,console.log(`Password rotated for user: ${i.username}`),{success:!0,newSecretArn:s}}needsPasswordRotation(n){let i=this.users.get(n);if(!i||!i.rotationEnabled||!i.lastRotated||!i.rotationDays)return!1;return(Date.now()-i.lastRotated.getTime())/86400000>=i.rotationDays}auditAccess(n){let i=`audit-${Date.now()}-${this.auditCounter++}`,s={id:i,timestamp:new Date,...n};return this.audits.set(i,s),s}getUserAccessHistory(n,i=100){return Array.from(this.audits.values()).filter((s)=>s.username===n).sort((s,o)=>o.timestamp.getTime()-s.timestamp.getTime()).slice(0,i)}getFailedLoginAttempts(n,i=24){let s=Date.now()-i*60*60*1000;return Array.from(this.audits.values()).filter((o)=>o.username===n&&o.action==="LOGIN"&&!o.success&&o.timestamp.getTime()>s)}generateCreateUserSQL(n,i="postgres"){let s=[];if(i==="postgres"){s.push(`CREATE USER ${n.username} WITH PASSWORD '${n.passwordSecretArn}';`);for(let o of n.privileges)if(o.privileges.includes("ALL"))s.push(`GRANT ALL PRIVILEGES ON DATABASE ${o.database} TO ${n.username};`);else{let c=o.privileges.join(", ");if(o.table)s.push(`GRANT ${c} ON ${o.database}.${o.table} TO ${n.username};`);else s.push(`GRANT ${c} ON DATABASE ${o.database} TO ${n.username};`)}}else{s.push(`CREATE USER '${n.username}'@'%' IDENTIFIED BY '${n.passwordSecretArn}';`);for(let o of n.privileges){let c=o.privileges.includes("ALL")?"ALL PRIVILEGES":o.privileges.join(", "),l=o.table?`${o.database}.${o.table}`:`${o.database}.*`;s.push(`GRANT ${c} ON ${l} TO '${n.username}'@'%';`)}s.push("FLUSH PRIVILEGES;")}return s.join(`
3761
- `)}getUser(n){return this.users.get(n)}listUsers(){return Array.from(this.users.values())}getRole(n){return this.roles.get(n)}listRoles(){return Array.from(this.roles.values())}clear(){this.users.clear(),this.roles.clear(),this.audits.clear(),this.userCounter=0,this.roleCounter=0,this.auditCounter=0}}var uE=new im;class sm{rotations=new Map;schedules=new Map;rotationCounter=0;scheduleCounter=0;createRotation(n){let i=`rotation-${Date.now()}-${this.rotationCounter++}`,s={id:i,...n};return this.rotations.set(i,s),s}enableRDSRotation(n){let i=this.createRotation({secretId:n.secretId,secretType:"rds_credentials",rotationEnabled:!0,rotationDays:n.rotationDays||30,rotationLambdaArn:this.generateRDSRotationLambdaArn(n.engine)});return i.nextRotation=new Date(Date.now()+i.rotationDays*24*60*60*1000),i}enableAPIKeyRotation(n){return this.createRotation({secretId:n.secretId,secretType:"api_key",rotationEnabled:!0,rotationDays:n.rotationDays||90,rotationLambdaArn:n.rotationLambdaArn})}enableOAuthRotation(n){return this.createRotation({secretId:n.secretId,secretType:"oauth_token",rotationEnabled:!0,rotationDays:n.rotationDays||60,rotationLambdaArn:n.rotationLambdaArn})}enableSSHKeyRotation(n){return this.createRotation({secretId:n.secretId,secretType:"ssh_key",rotationEnabled:!0,rotationDays:n.rotationDays||180,rotationLambdaArn:n.rotationLambdaArn})}createSchedule(n){let i=`schedule-${Date.now()}-${this.scheduleCounter++}`,s={id:i,...n};return this.schedules.set(i,s),s}async executeRotation(n){let i=this.rotations.get(n);if(!i)throw Error(`Rotation not found: ${n}`);console.log(`
3760
+ ✓ Promotion completed successfully`),i.status="available",{success:!0,message:"Replica promoted successfully"}}getReplicationLag(n){if(!this.replicas.get(n))throw Error(`Replica not found: ${n}`);return Math.floor(Math.random()*1000)}getReplica(n){return this.replicas.get(n)}listReplicas(){return Array.from(this.replicas.values())}getReplicationGroup(n){return this.replicationGroups.get(n)}listReplicationGroups(){return Array.from(this.replicationGroups.values())}getProxy(n){return this.proxies.get(n)}listProxies(){return Array.from(this.proxies.values())}generateReplicaCF(n){return{Type:"AWS::RDS::DBInstance",Properties:{SourceDBInstanceIdentifier:n.sourceDatabase,DBInstanceIdentifier:n.name,DBInstanceClass:n.instanceClass,MultiAZ:n.multiAZ||!1,AutoMinorVersionUpgrade:n.autoMinorVersionUpgrade??!0,...n.backupRetentionPeriod&&{BackupRetentionPeriod:n.backupRetentionPeriod},...n.preferredBackupWindow&&{PreferredBackupWindow:n.preferredBackupWindow},...n.preferredMaintenanceWindow&&{PreferredMaintenanceWindow:n.preferredMaintenanceWindow}}}}generateProxyCF(n){return{Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:n.name,EngineFamily:n.engineFamily,Auth:[{AuthScheme:"SECRETS",SecretArn:n.secretArn,IAMAuth:"DISABLED"}],RoleArn:{"Fn::GetAtt":["RDSProxyRole","Arn"]},VpcSubnetIds:n.vpcSubnetIds,VpcSecurityGroupIds:n.securityGroupIds,RequireTLS:n.requireTLS??!0,IdleClientTimeout:n.idleClientTimeout||1800,...n.maxConnectionsPercent&&{MaxConnectionsPercent:n.maxConnectionsPercent},...n.maxIdleConnectionsPercent&&{MaxIdleConnectionsPercent:n.maxIdleConnectionsPercent},...n.connectionBorrowTimeout&&{ConnectionBorrowTimeout:n.connectionBorrowTimeout}}}}generateProxyTargetCF(n,i){return{Type:"AWS::RDS::DBProxyTargetGroup",Properties:{DBProxyName:i.name,TargetGroupName:"default",DBInstanceIdentifiers:[n.targetArn],ConnectionPoolConfig:{MaxConnectionsPercent:100,MaxIdleConnectionsPercent:50,ConnectionBorrowTimeout:120}}}}generateProxyRoleCF(){return{Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"rds.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"RDSProxySecretsPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],Resource:"arn:aws:secretsmanager:*:*:secret:*"},{Effect:"Allow",Action:["kms:Decrypt"],Resource:"arn:aws:kms:*:*:key/*",Condition:{StringEquals:{"kms:ViaService":"secretsmanager.*.amazonaws.com"}}}]}}]}}}clear(){this.replicas.clear(),this.replicationGroups.clear(),this.proxies.clear(),this.proxyTargets.clear(),this.replicaCounter=0,this.groupCounter=0,this.proxyCounter=0,this.targetCounter=0}}var uE=new im;class sm{insights=new Map;slowQueryLogs=new Map;queryMetrics=new Map;reports=new Map;indexRecommendations=new Map;insightsCounter=0;logCounter=0;metricCounter=0;reportCounter=0;recommendationCounter=0;enablePerformanceInsights(n){let i=`pi-${Date.now()}-${this.insightsCounter++}`,s={id:i,name:n.name,databaseIdentifier:n.databaseIdentifier,enabled:!0,retentionPeriod:n.retentionPeriod||7,kmsKeyId:n.kmsKeyId};return this.insights.set(i,s),s}enableSlowQueryLog(n){let i=`slow-query-${Date.now()}-${this.logCounter++}`,s={id:i,name:n.name,databaseIdentifier:n.databaseIdentifier,enabled:!0,logDestination:n.logDestination,cloudwatchLogGroup:n.cloudwatchLogGroup,s3Bucket:n.s3Bucket,s3Prefix:n.s3Bucket?"slow-queries/":void 0,minExecutionTime:n.minExecutionTime||1000};return this.slowQueryLogs.set(i,s),s}recordQueryMetric(n){let i=`metric-${Date.now()}-${this.metricCounter++}`,s={id:i,timestamp:new Date,...n};return this.queryMetrics.set(i,s),s}generatePerformanceReport(n){let i=`report-${Date.now()}-${this.reportCounter++}`,s={avgCPU:Math.random()*60+20,maxCPU:Math.random()*30+70,avgConnections:Math.floor(Math.random()*50+10),maxConnections:Math.floor(Math.random()*50+100),avgReadIOPS:Math.floor(Math.random()*1000+500),avgWriteIOPS:Math.floor(Math.random()*500+200),avgReadThroughput:Math.random()*50+10,avgWriteThroughput:Math.random()*20+5,avgReadLatency:Math.random()*5+1,avgWriteLatency:Math.random()*8+2,cacheHitRatio:Math.random()*10+90,deadlocks:Math.floor(Math.random()*5),longRunningTransactions:Math.floor(Math.random()*10)},o=Array.from(this.queryMetrics.values()),c=o.sort((y,f)=>f.executionCount-y.executionCount).slice(0,10),l=o.filter((y)=>y.avgExecutionTime>1000).sort((y,f)=>f.avgExecutionTime-y.avgExecutionTime).slice(0,10),u=this.generateRecommendations(s,l),h={id:i,name:n.name,databaseIdentifier:n.databaseIdentifier,reportType:n.reportType,metrics:s,topQueries:c,slowQueries:l,recommendations:u,generatedAt:new Date};return this.reports.set(i,h),h}generateRecommendations(n,i){let s=[];if(n.avgCPU>70)s.push({type:"scaling",severity:"high",title:"High CPU Usage",description:`Average CPU usage is ${n.avgCPU.toFixed(1)}%, which is above the recommended threshold of 70%.`,impact:"Performance degradation, increased latency, potential timeouts",effort:"medium"});if(n.cacheHitRatio<95)s.push({type:"configuration",severity:"medium",title:"Low Cache Hit Ratio",description:`Cache hit ratio is ${n.cacheHitRatio.toFixed(1)}%. Consider increasing buffer pool size.`,impact:"Increased disk I/O, slower query performance",effort:"low"});if(n.deadlocks>0)s.push({type:"query",severity:"medium",title:"Deadlocks Detected",description:`${n.deadlocks} deadlock(s) detected. Review transaction isolation levels and query patterns.`,impact:"Transaction failures, application errors",effort:"high"});if(i.length>0)s.push({type:"index",severity:"high",title:"Slow Queries Detected",description:`${i.length} slow queries detected. Consider adding indexes or optimizing queries.`,impact:"High latency, poor user experience",effort:"medium"});if(n.avgReadLatency>10||n.avgWriteLatency>10)s.push({type:"scaling",severity:"high",title:"High I/O Latency",description:"Read or write latency is high. Consider upgrading to Provisioned IOPS or moving to a larger instance.",impact:"Slow query execution, application timeouts",effort:"medium"});return s}analyzeQuery(n){let i=`analysis-${Date.now()}-${Math.random().toString(36).slice(2,9)}`,s=[{id:1,operation:"Seq Scan",table:"users",rows:1e4,cost:850.5,children:[]}],o=[];if(n.toLowerCase().includes("select *"))o.push({type:"full_table_scan",severity:"warning",description:"Query selects all columns. Consider selecting only required columns."});if(!n.toLowerCase().includes("where")&&n.toLowerCase().includes("select"))o.push({type:"full_table_scan",severity:"critical",description:"Query has no WHERE clause and may scan entire table."});return{id:i,queryId:i,sql:n,executionPlan:s,bottlenecks:o,recommendations:["Add appropriate indexes on WHERE clause columns","Consider using EXPLAIN ANALYZE to get actual execution statistics","Review and optimize JOIN conditions"],estimatedCost:s[0].cost}}recommendIndex(n){let i=`index-rec-${Date.now()}-${this.recommendationCounter++}`,s=`idx_${n.tableName}_${n.columns.join("_")}`,o={id:i,tableName:n.tableName,columns:n.columns,reason:n.reason,estimatedImprovement:n.estimatedImprovement||50,estimatedSize:n.columns.length*10,createSQL:`CREATE INDEX ${s} ON ${n.tableName} (${n.columns.join(", ")});`};return this.indexRecommendations.set(i,o),o}getInsights(n){return this.insights.get(n)}listInsights(){return Array.from(this.insights.values())}getSlowQueryLog(n){return this.slowQueryLogs.get(n)}listSlowQueryLogs(){return Array.from(this.slowQueryLogs.values())}getReport(n){return this.reports.get(n)}listReports(){return Array.from(this.reports.values())}listIndexRecommendations(){return Array.from(this.indexRecommendations.values())}generatePerformanceInsightsCF(n){return{EnablePerformanceInsights:n.enabled,PerformanceInsightsRetentionPeriod:n.retentionPeriod,...n.kmsKeyId&&{PerformanceInsightsKMSKeyId:n.kmsKeyId}}}generateSlowQueryAlarmCF(n){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:n.alarmName,AlarmDescription:"Alert when slow queries exceed threshold",MetricName:"SlowQueryCount",Namespace:"AWS/RDS",Statistic:"Sum",Period:300,EvaluationPeriods:1,Threshold:n.threshold,ComparisonOperator:"GreaterThanThreshold",...n.snsTopicArn&&{AlarmActions:[n.snsTopicArn]}}}}clear(){this.insights.clear(),this.slowQueryLogs.clear(),this.queryMetrics.clear(),this.reports.clear(),this.indexRecommendations.clear(),this.insightsCounter=0,this.logCounter=0,this.metricCounter=0,this.reportCounter=0,this.recommendationCounter=0}}var pE=new sm;class om{users=new Map;roles=new Map;audits=new Map;userCounter=0;roleCounter=0;auditCounter=0;createUser(n){let i=`db-user-${Date.now()}-${this.userCounter++}`,s={id:i,createdAt:new Date,...n};return this.users.set(i,s),s}createReadOnlyUser(n){let i=n.tables?n.tables.map((s)=>({database:n.database,table:s,privileges:["SELECT"]})):[{database:n.database,privileges:["SELECT"]}];return this.createUser({username:n.username,database:n.database,privileges:i,passwordSecretArn:n.passwordSecretArn,rotationEnabled:!0,rotationDays:90})}createReadWriteUser(n){let i=n.tables?n.tables.map((s)=>({database:n.database,table:s,privileges:["SELECT","INSERT","UPDATE","DELETE"]})):[{database:n.database,privileges:["SELECT","INSERT","UPDATE","DELETE"]}];return this.createUser({username:n.username,database:n.database,privileges:i,passwordSecretArn:n.passwordSecretArn,rotationEnabled:!0,rotationDays:60})}createAdminUser(n){return this.createUser({username:n.username,database:n.database,privileges:[{database:n.database,privileges:["ALL"]}],passwordSecretArn:n.passwordSecretArn,rotationEnabled:!0,rotationDays:30})}createApplicationUser(n){let i=n.tables.map((s)=>({database:n.database,table:s.name,privileges:s.privileges}));return this.createUser({username:n.username,database:n.database,privileges:i,passwordSecretArn:n.passwordSecretArn,rotationEnabled:!0,rotationDays:90})}createRole(n){let i=`role-${Date.now()}-${this.roleCounter++}`,s={id:i,users:[],...n};return this.roles.set(i,s),s}assignUserToRole(n,i){let s=this.users.get(n),o=this.roles.get(i);if(!s)throw Error(`User not found: ${n}`);if(!o)throw Error(`Role not found: ${i}`);o.users.push(n);for(let c of o.privileges){let l=s.privileges.find((u)=>u.database===c.database&&u.table===c.table);if(l)l.privileges=Array.from(new Set([...l.privileges,...c.privileges]));else s.privileges.push({...c})}}grantPrivileges(n,i){let s=this.users.get(n);if(!s)return{success:!1,message:"User not found"};for(let o of i){let c=s.privileges.find((l)=>l.database===o.database&&l.table===o.table);if(c)c.privileges=Array.from(new Set([...c.privileges,...o.privileges]));else s.privileges.push(o)}return this.auditAccess({username:s.username,action:"GRANT",database:i[0]?.database,table:i[0]?.table,success:!0}),{success:!0,message:"Privileges granted successfully"}}revokePrivileges(n,i){let s=this.users.get(n);if(!s)return{success:!1,message:"User not found"};for(let o of i){let c=s.privileges.findIndex((l)=>l.database===o.database&&l.table===o.table);if(c!==-1){let l=s.privileges[c];if(l.privileges=l.privileges.filter((u)=>!o.privileges.includes(u)),l.privileges.length===0)s.privileges.splice(c,1)}}return this.auditAccess({username:s.username,action:"REVOKE",database:i[0]?.database,table:i[0]?.table,success:!0}),{success:!0,message:"Privileges revoked successfully"}}rotatePassword(n){let i=this.users.get(n);if(!i)return{success:!1};let s=`arn:aws:secretsmanager:us-east-1:123456789012:secret:db-${i.username}-${Date.now()}`;return i.passwordSecretArn=s,i.lastRotated=new Date,console.log(`Password rotated for user: ${i.username}`),{success:!0,newSecretArn:s}}needsPasswordRotation(n){let i=this.users.get(n);if(!i||!i.rotationEnabled||!i.lastRotated||!i.rotationDays)return!1;return(Date.now()-i.lastRotated.getTime())/86400000>=i.rotationDays}auditAccess(n){let i=`audit-${Date.now()}-${this.auditCounter++}`,s={id:i,timestamp:new Date,...n};return this.audits.set(i,s),s}getUserAccessHistory(n,i=100){return Array.from(this.audits.values()).filter((s)=>s.username===n).sort((s,o)=>o.timestamp.getTime()-s.timestamp.getTime()).slice(0,i)}getFailedLoginAttempts(n,i=24){let s=Date.now()-i*60*60*1000;return Array.from(this.audits.values()).filter((o)=>o.username===n&&o.action==="LOGIN"&&!o.success&&o.timestamp.getTime()>s)}generateCreateUserSQL(n,i="postgres"){let s=[];if(i==="postgres"){s.push(`CREATE USER ${n.username} WITH PASSWORD '${n.passwordSecretArn}';`);for(let o of n.privileges)if(o.privileges.includes("ALL"))s.push(`GRANT ALL PRIVILEGES ON DATABASE ${o.database} TO ${n.username};`);else{let c=o.privileges.join(", ");if(o.table)s.push(`GRANT ${c} ON ${o.database}.${o.table} TO ${n.username};`);else s.push(`GRANT ${c} ON DATABASE ${o.database} TO ${n.username};`)}}else{s.push(`CREATE USER '${n.username}'@'%' IDENTIFIED BY '${n.passwordSecretArn}';`);for(let o of n.privileges){let c=o.privileges.includes("ALL")?"ALL PRIVILEGES":o.privileges.join(", "),l=o.table?`${o.database}.${o.table}`:`${o.database}.*`;s.push(`GRANT ${c} ON ${l} TO '${n.username}'@'%';`)}s.push("FLUSH PRIVILEGES;")}return s.join(`
3761
+ `)}getUser(n){return this.users.get(n)}listUsers(){return Array.from(this.users.values())}getRole(n){return this.roles.get(n)}listRoles(){return Array.from(this.roles.values())}clear(){this.users.clear(),this.roles.clear(),this.audits.clear(),this.userCounter=0,this.roleCounter=0,this.auditCounter=0}}var gE=new om;class am{rotations=new Map;schedules=new Map;rotationCounter=0;scheduleCounter=0;createRotation(n){let i=`rotation-${Date.now()}-${this.rotationCounter++}`,s={id:i,...n};return this.rotations.set(i,s),s}enableRDSRotation(n){let i=this.createRotation({secretId:n.secretId,secretType:"rds_credentials",rotationEnabled:!0,rotationDays:n.rotationDays||30,rotationLambdaArn:this.generateRDSRotationLambdaArn(n.engine)});return i.nextRotation=new Date(Date.now()+i.rotationDays*24*60*60*1000),i}enableAPIKeyRotation(n){return this.createRotation({secretId:n.secretId,secretType:"api_key",rotationEnabled:!0,rotationDays:n.rotationDays||90,rotationLambdaArn:n.rotationLambdaArn})}enableOAuthRotation(n){return this.createRotation({secretId:n.secretId,secretType:"oauth_token",rotationEnabled:!0,rotationDays:n.rotationDays||60,rotationLambdaArn:n.rotationLambdaArn})}enableSSHKeyRotation(n){return this.createRotation({secretId:n.secretId,secretType:"ssh_key",rotationEnabled:!0,rotationDays:n.rotationDays||180,rotationLambdaArn:n.rotationLambdaArn})}createSchedule(n){let i=`schedule-${Date.now()}-${this.scheduleCounter++}`,s={id:i,...n};return this.schedules.set(i,s),s}async executeRotation(n){let i=this.rotations.get(n);if(!i)throw Error(`Rotation not found: ${n}`);console.log(`
3762
3762
  Executing rotation for secret: ${i.secretId}`),console.log(`Secret type: ${i.secretType}`),console.log(`Rotation interval: ${i.rotationDays} days`);try{console.log(`
3763
3763
  Rotation steps:`),console.log("1. Creating new secret version...");let s=`v${Date.now()}`;console.log("2. Testing new credentials..."),console.log("3. Updating application references..."),console.log("4. Marking previous version as deprecated...");let o=i.versionStages?.[0]||"v1";return console.log("5. Finalizing rotation..."),i.lastRotated=new Date,i.nextRotation=new Date(Date.now()+i.rotationDays*24*60*60*1000),console.log(`
3764
3764
  ✓ Rotation completed successfully`),console.log(` New version: ${s}`),console.log(` Next rotation: ${i.nextRotation.toISOString()}`),{success:!0,secretId:i.secretId,oldVersion:o,newVersion:s,rotatedAt:new Date}}catch(s){return console.error(`
3765
- ✗ Rotation failed:`,s),{success:!1,secretId:i.secretId,oldVersion:"unknown",newVersion:"unknown",rotatedAt:new Date,error:s instanceof Error?s.message:String(s)}}}needsRotation(n){let i=this.rotations.get(n);if(!i||!i.rotationEnabled)return!1;if(!i.lastRotated)return!0;return(Date.now()-i.lastRotated.getTime())/86400000>=i.rotationDays}getSecretsNeedingRotation(){return Array.from(this.rotations.values()).filter((n)=>this.needsRotation(n.id))}generateRDSRotationLambdaArn(n){let i={postgres:"SecretsManagerRDSPostgreSQLRotationSingleUser",mysql:"SecretsManagerRDSMySQLRotationSingleUser",sqlserver:"SecretsManagerRDSSQLServerRotationSingleUser",oracle:"SecretsManagerRDSOracleRotationSingleUser"};return`arn:aws:lambda:us-east-1:123456789012:function:${i[n]||i.postgres}`}getRotation(n){return this.rotations.get(n)}listRotations(){return Array.from(this.rotations.values())}getSchedule(n){return this.schedules.get(n)}listSchedules(){return Array.from(this.schedules.values())}generateRotationCF(n){return{RotationEnabled:n.rotationEnabled,RotationRules:{AutomaticallyAfterDays:n.rotationDays},...n.rotationLambdaArn&&{RotationLambdaARN:n.rotationLambdaArn}}}generateRotationLambdaCF(n){return{Type:"AWS::Lambda::Function",Properties:{FunctionName:n.functionName,Runtime:"python3.11",Handler:"lambda_function.lambda_handler",Role:{"Fn::GetAtt":["RotationLambdaRole","Arn"]},Timeout:30,Environment:{Variables:{SECRETS_MANAGER_ENDPOINT:"https://secretsmanager.us-east-1.amazonaws.com"}},...n.vpcConfig&&{VpcConfig:{SubnetIds:n.vpcConfig.subnetIds,SecurityGroupIds:n.vpcConfig.securityGroupIds}}}}}generateRotationLambdaRoleCF(){return{Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole","arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"],Policies:[{PolicyName:"SecretsRotationPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:DescribeSecret","secretsmanager:GetSecretValue","secretsmanager:PutSecretValue","secretsmanager:UpdateSecretVersionStage"],Resource:"*"},{Effect:"Allow",Action:["secretsmanager:GetRandomPassword"],Resource:"*"}]}}]}}}generateRotationScheduleCF(n){return{Type:"AWS::Events::Rule",Properties:{Name:n.name,Description:`Rotation schedule for ${n.secrets.length} secrets`,ScheduleExpression:n.schedule,State:n.enabled?"ENABLED":"DISABLED",Targets:[{Arn:{"Fn::GetAtt":["RotationStateMachine","Arn"]},RoleArn:{"Fn::GetAtt":["EventBridgeRotationRole","Arn"]},Input:JSON.stringify({secrets:n.secrets})}]}}}clear(){this.rotations.clear(),this.schedules.clear(),this.rotationCounter=0,this.scheduleCounter=0}}var pE=new sm;class om{versions=new Map;audits=new Map;externalManagers=new Map;replications=new Map;policies=new Map;versionCounter=0;auditCounter=0;managerCounter=0;replicationCounter=0;policyCounter=0;createVersion(n){let i=`version-${Date.now()}-${this.versionCounter++}`,s={id:i,...n};return this.versions.set(i,s),this.auditAction({secretId:n.secretId,action:"CREATE",actor:"system",versionId:n.versionId,success:!0}),s}getVersionByStage(n,i){return Array.from(this.versions.values()).find((s)=>s.secretId===n&&s.versionStages.includes(i))}listVersions(n){return Array.from(this.versions.values()).filter((i)=>i.secretId===n).sort((i,s)=>s.createdAt.getTime()-i.createdAt.getTime())}deprecateVersion(n){let i=Array.from(this.versions.values()).find((s)=>s.versionId===n);if(i)i.deprecatedAt=new Date,i.versionStages=i.versionStages.filter((s)=>s!=="AWSCURRENT"),this.auditAction({secretId:i.secretId,action:"UPDATE",actor:"system",versionId:n,success:!0})}restoreVersion(n){let i=Array.from(this.versions.values()).find((s)=>s.versionId===n);if(i)Array.from(this.versions.values()).filter((s)=>s.secretId===i.secretId&&s.versionId!==n).forEach((s)=>{s.versionStages=s.versionStages.filter((o)=>o!=="AWSCURRENT")}),i.versionStages.push("AWSCURRENT"),i.deprecatedAt=void 0,this.auditAction({secretId:i.secretId,action:"RESTORE",actor:"system",versionId:n,success:!0})}auditAction(n){let i=`audit-${Date.now()}-${this.auditCounter++}`,s={id:i,timestamp:new Date,...n};return this.audits.set(i,s),s}getAuditTrail(n,i=100){return Array.from(this.audits.values()).filter((s)=>s.secretId===n).sort((s,o)=>o.timestamp.getTime()-s.timestamp.getTime()).slice(0,i)}getFailedAccesses(n,i=24){let s=Date.now()-i*60*60*1000;return Array.from(this.audits.values()).filter((o)=>o.secretId===n&&!o.success&&o.timestamp.getTime()>s)}registerExternalManager(n){let i=`ext-manager-${Date.now()}-${this.managerCounter++}`,s={id:i,...n};return this.externalManagers.set(i,s),s}registerVault(n){return this.registerExternalManager({type:"vault",name:n.name,endpoint:n.endpoint,authentication:{type:n.token?"token":"iam",credentials:n.token?{token:n.token}:void 0,roleArn:n.roleArn},syncEnabled:n.syncEnabled||!1,syncInterval:60})}registerOnePassword(n){return this.registerExternalManager({type:"onepassword",name:n.name,endpoint:n.endpoint||"https://my.1password.com",authentication:{type:"apikey",credentials:{apiKey:n.apiKey}},syncEnabled:n.syncEnabled||!1,syncInterval:30})}enableReplication(n){let i=`replication-${Date.now()}-${this.replicationCounter++}`,s={id:i,secretId:n.secretId,sourceRegion:n.sourceRegion,replicaRegions:n.replicaRegions,kmsKeyIds:n.kmsKeyIds,status:"replicating"};return this.replications.set(i,s),this.auditAction({secretId:n.secretId,action:"REPLICATE",actor:"system",success:!0}),setTimeout(()=>{s.status="completed"},100),s}createPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,secretId:n.secretId,policy:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:n.allowedPrincipals},Action:n.allowedActions,Resource:"*"}]}};return this.policies.set(i,s),s}createCrossAccountPolicy(n){let i=n.roleNames.map((s)=>`arn:aws:iam::${n.accountId}:role/${s}`);return this.createPolicy({secretId:n.secretId,allowedPrincipals:i,allowedActions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"]})}getVersion(n){return this.versions.get(n)}getExternalManager(n){return this.externalManagers.get(n)}listExternalManagers(){return Array.from(this.externalManagers.values())}getReplication(n){return this.replications.get(n)}listReplications(){return Array.from(this.replications.values())}generateSecretCF(n){return{Type:"AWS::SecretsManager::Secret",Properties:{Name:n.name,Description:n.description,...n.kmsKeyId&&{KmsKeyId:n.kmsKeyId},...n.replicaRegions&&{ReplicaRegions:n.replicaRegions.map((i)=>({Region:i}))}}}}generateSecretPolicyCF(n){return{Type:"AWS::SecretsManager::ResourcePolicy",Properties:{SecretId:n.secretId,ResourcePolicy:n.policy}}}clear(){this.versions.clear(),this.audits.clear(),this.externalManagers.clear(),this.replications.clear(),this.policies.clear(),this.versionCounter=0,this.auditCounter=0,this.managerCounter=0,this.replicationCounter=0,this.policyCounter=0}}var gE=new om;class am{certificates=new Map;renewals=new Map;validations=new Map;monitors=new Map;alerts=new Map;certificateCounter=0;renewalCounter=0;validationCounter=0;monitorCounter=0;alertCounter=0;requestCertificate(n){let i=`cert-${Date.now()}-${this.certificateCounter++}`,s=`arn:aws:acm:us-east-1:123456789012:certificate/${i}`,o={id:i,arn:s,domainName:n.domainName,subjectAlternativeNames:n.subjectAlternativeNames,validationMethod:n.validationMethod||"DNS",status:"PENDING_VALIDATION"};return this.certificates.set(i,o),this.createValidation(o),o}requestWildcardCertificate(n){let i=[];if(n.includeApex)i.push(n.domainName.replace("*.",""));return this.requestCertificate({domainName:n.domainName,subjectAlternativeNames:i.length>0?i:void 0,validationMethod:"DNS"})}requestMultiDomainCertificate(n){return this.requestCertificate({domainName:n.primaryDomain,subjectAlternativeNames:n.additionalDomains,validationMethod:n.validationMethod||"DNS"})}createValidation(n){let i={domainName:n.domainName,validationMethod:n.validationMethod,validationStatus:"PENDING"};if(n.validationMethod==="DNS")i.resourceRecords=[{name:`_${Math.random().toString(36).slice(2)}.${n.domainName}`,type:"CNAME",value:`_${Math.random().toString(36).slice(2)}.acm-validations.aws.`}];else i.validationEmails=[`admin@${n.domainName}`,`administrator@${n.domainName}`,`hostmaster@${n.domainName}`];return this.validations.set(n.id,i),i}validateCertificate(n){let i=this.certificates.get(n),s=this.validations.get(n);if(!i||!s)return{success:!1,message:"Certificate or validation not found"};return s.validationStatus="SUCCESS",i.status="ISSUED",i.issuedAt=new Date,i.expiresAt=new Date(Date.now()+31536000000),i.renewalEligibility=!0,i.issuer="Amazon",{success:!0,message:"Certificate validated and issued successfully"}}enableAutoRenewal(n){let i=`renewal-${Date.now()}-${this.renewalCounter++}`,s={id:i,certificateArn:n.certificateArn,autoRenew:!0,renewBeforeDays:n.renewBeforeDays||30};return this.renewals.set(i,s),s}async renewCertificate(n){let i=this.renewals.get(n);if(!i)return{success:!1,message:"Renewal configuration not found"};let s=Array.from(this.certificates.values()).find((o)=>o.arn===i.certificateArn);if(!s)return{success:!1,message:"Certificate not found"};console.log(`
3765
+ ✗ Rotation failed:`,s),{success:!1,secretId:i.secretId,oldVersion:"unknown",newVersion:"unknown",rotatedAt:new Date,error:s instanceof Error?s.message:String(s)}}}needsRotation(n){let i=this.rotations.get(n);if(!i||!i.rotationEnabled)return!1;if(!i.lastRotated)return!0;return(Date.now()-i.lastRotated.getTime())/86400000>=i.rotationDays}getSecretsNeedingRotation(){return Array.from(this.rotations.values()).filter((n)=>this.needsRotation(n.id))}generateRDSRotationLambdaArn(n){let i={postgres:"SecretsManagerRDSPostgreSQLRotationSingleUser",mysql:"SecretsManagerRDSMySQLRotationSingleUser",sqlserver:"SecretsManagerRDSSQLServerRotationSingleUser",oracle:"SecretsManagerRDSOracleRotationSingleUser"};return`arn:aws:lambda:us-east-1:123456789012:function:${i[n]||i.postgres}`}getRotation(n){return this.rotations.get(n)}listRotations(){return Array.from(this.rotations.values())}getSchedule(n){return this.schedules.get(n)}listSchedules(){return Array.from(this.schedules.values())}generateRotationCF(n){return{RotationEnabled:n.rotationEnabled,RotationRules:{AutomaticallyAfterDays:n.rotationDays},...n.rotationLambdaArn&&{RotationLambdaARN:n.rotationLambdaArn}}}generateRotationLambdaCF(n){return{Type:"AWS::Lambda::Function",Properties:{FunctionName:n.functionName,Runtime:"python3.11",Handler:"lambda_function.lambda_handler",Role:{"Fn::GetAtt":["RotationLambdaRole","Arn"]},Timeout:30,Environment:{Variables:{SECRETS_MANAGER_ENDPOINT:"https://secretsmanager.us-east-1.amazonaws.com"}},...n.vpcConfig&&{VpcConfig:{SubnetIds:n.vpcConfig.subnetIds,SecurityGroupIds:n.vpcConfig.securityGroupIds}}}}}generateRotationLambdaRoleCF(){return{Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole","arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"],Policies:[{PolicyName:"SecretsRotationPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:DescribeSecret","secretsmanager:GetSecretValue","secretsmanager:PutSecretValue","secretsmanager:UpdateSecretVersionStage"],Resource:"*"},{Effect:"Allow",Action:["secretsmanager:GetRandomPassword"],Resource:"*"}]}}]}}}generateRotationScheduleCF(n){return{Type:"AWS::Events::Rule",Properties:{Name:n.name,Description:`Rotation schedule for ${n.secrets.length} secrets`,ScheduleExpression:n.schedule,State:n.enabled?"ENABLED":"DISABLED",Targets:[{Arn:{"Fn::GetAtt":["RotationStateMachine","Arn"]},RoleArn:{"Fn::GetAtt":["EventBridgeRotationRole","Arn"]},Input:JSON.stringify({secrets:n.secrets})}]}}}clear(){this.rotations.clear(),this.schedules.clear(),this.rotationCounter=0,this.scheduleCounter=0}}var mE=new am;class cm{versions=new Map;audits=new Map;externalManagers=new Map;replications=new Map;policies=new Map;versionCounter=0;auditCounter=0;managerCounter=0;replicationCounter=0;policyCounter=0;createVersion(n){let i=`version-${Date.now()}-${this.versionCounter++}`,s={id:i,...n};return this.versions.set(i,s),this.auditAction({secretId:n.secretId,action:"CREATE",actor:"system",versionId:n.versionId,success:!0}),s}getVersionByStage(n,i){return Array.from(this.versions.values()).find((s)=>s.secretId===n&&s.versionStages.includes(i))}listVersions(n){return Array.from(this.versions.values()).filter((i)=>i.secretId===n).sort((i,s)=>s.createdAt.getTime()-i.createdAt.getTime())}deprecateVersion(n){let i=Array.from(this.versions.values()).find((s)=>s.versionId===n);if(i)i.deprecatedAt=new Date,i.versionStages=i.versionStages.filter((s)=>s!=="AWSCURRENT"),this.auditAction({secretId:i.secretId,action:"UPDATE",actor:"system",versionId:n,success:!0})}restoreVersion(n){let i=Array.from(this.versions.values()).find((s)=>s.versionId===n);if(i)Array.from(this.versions.values()).filter((s)=>s.secretId===i.secretId&&s.versionId!==n).forEach((s)=>{s.versionStages=s.versionStages.filter((o)=>o!=="AWSCURRENT")}),i.versionStages.push("AWSCURRENT"),i.deprecatedAt=void 0,this.auditAction({secretId:i.secretId,action:"RESTORE",actor:"system",versionId:n,success:!0})}auditAction(n){let i=`audit-${Date.now()}-${this.auditCounter++}`,s={id:i,timestamp:new Date,...n};return this.audits.set(i,s),s}getAuditTrail(n,i=100){return Array.from(this.audits.values()).filter((s)=>s.secretId===n).sort((s,o)=>o.timestamp.getTime()-s.timestamp.getTime()).slice(0,i)}getFailedAccesses(n,i=24){let s=Date.now()-i*60*60*1000;return Array.from(this.audits.values()).filter((o)=>o.secretId===n&&!o.success&&o.timestamp.getTime()>s)}registerExternalManager(n){let i=`ext-manager-${Date.now()}-${this.managerCounter++}`,s={id:i,...n};return this.externalManagers.set(i,s),s}registerVault(n){return this.registerExternalManager({type:"vault",name:n.name,endpoint:n.endpoint,authentication:{type:n.token?"token":"iam",credentials:n.token?{token:n.token}:void 0,roleArn:n.roleArn},syncEnabled:n.syncEnabled||!1,syncInterval:60})}registerOnePassword(n){return this.registerExternalManager({type:"onepassword",name:n.name,endpoint:n.endpoint||"https://my.1password.com",authentication:{type:"apikey",credentials:{apiKey:n.apiKey}},syncEnabled:n.syncEnabled||!1,syncInterval:30})}enableReplication(n){let i=`replication-${Date.now()}-${this.replicationCounter++}`,s={id:i,secretId:n.secretId,sourceRegion:n.sourceRegion,replicaRegions:n.replicaRegions,kmsKeyIds:n.kmsKeyIds,status:"replicating"};return this.replications.set(i,s),this.auditAction({secretId:n.secretId,action:"REPLICATE",actor:"system",success:!0}),setTimeout(()=>{s.status="completed"},100),s}createPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,secretId:n.secretId,policy:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:n.allowedPrincipals},Action:n.allowedActions,Resource:"*"}]}};return this.policies.set(i,s),s}createCrossAccountPolicy(n){let i=n.roleNames.map((s)=>`arn:aws:iam::${n.accountId}:role/${s}`);return this.createPolicy({secretId:n.secretId,allowedPrincipals:i,allowedActions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"]})}getVersion(n){return this.versions.get(n)}getExternalManager(n){return this.externalManagers.get(n)}listExternalManagers(){return Array.from(this.externalManagers.values())}getReplication(n){return this.replications.get(n)}listReplications(){return Array.from(this.replications.values())}generateSecretCF(n){return{Type:"AWS::SecretsManager::Secret",Properties:{Name:n.name,Description:n.description,...n.kmsKeyId&&{KmsKeyId:n.kmsKeyId},...n.replicaRegions&&{ReplicaRegions:n.replicaRegions.map((i)=>({Region:i}))}}}}generateSecretPolicyCF(n){return{Type:"AWS::SecretsManager::ResourcePolicy",Properties:{SecretId:n.secretId,ResourcePolicy:n.policy}}}clear(){this.versions.clear(),this.audits.clear(),this.externalManagers.clear(),this.replications.clear(),this.policies.clear(),this.versionCounter=0,this.auditCounter=0,this.managerCounter=0,this.replicationCounter=0,this.policyCounter=0}}var hE=new cm;class dm{certificates=new Map;renewals=new Map;validations=new Map;monitors=new Map;alerts=new Map;certificateCounter=0;renewalCounter=0;validationCounter=0;monitorCounter=0;alertCounter=0;requestCertificate(n){let i=`cert-${Date.now()}-${this.certificateCounter++}`,s=`arn:aws:acm:us-east-1:123456789012:certificate/${i}`,o={id:i,arn:s,domainName:n.domainName,subjectAlternativeNames:n.subjectAlternativeNames,validationMethod:n.validationMethod||"DNS",status:"PENDING_VALIDATION"};return this.certificates.set(i,o),this.createValidation(o),o}requestWildcardCertificate(n){let i=[];if(n.includeApex)i.push(n.domainName.replace("*.",""));return this.requestCertificate({domainName:n.domainName,subjectAlternativeNames:i.length>0?i:void 0,validationMethod:"DNS"})}requestMultiDomainCertificate(n){return this.requestCertificate({domainName:n.primaryDomain,subjectAlternativeNames:n.additionalDomains,validationMethod:n.validationMethod||"DNS"})}createValidation(n){let i={domainName:n.domainName,validationMethod:n.validationMethod,validationStatus:"PENDING"};if(n.validationMethod==="DNS")i.resourceRecords=[{name:`_${Math.random().toString(36).slice(2)}.${n.domainName}`,type:"CNAME",value:`_${Math.random().toString(36).slice(2)}.acm-validations.aws.`}];else i.validationEmails=[`admin@${n.domainName}`,`administrator@${n.domainName}`,`hostmaster@${n.domainName}`];return this.validations.set(n.id,i),i}validateCertificate(n){let i=this.certificates.get(n),s=this.validations.get(n);if(!i||!s)return{success:!1,message:"Certificate or validation not found"};return s.validationStatus="SUCCESS",i.status="ISSUED",i.issuedAt=new Date,i.expiresAt=new Date(Date.now()+31536000000),i.renewalEligibility=!0,i.issuer="Amazon",{success:!0,message:"Certificate validated and issued successfully"}}enableAutoRenewal(n){let i=`renewal-${Date.now()}-${this.renewalCounter++}`,s={id:i,certificateArn:n.certificateArn,autoRenew:!0,renewBeforeDays:n.renewBeforeDays||30};return this.renewals.set(i,s),s}async renewCertificate(n){let i=this.renewals.get(n);if(!i)return{success:!1,message:"Renewal configuration not found"};let s=Array.from(this.certificates.values()).find((o)=>o.arn===i.certificateArn);if(!s)return{success:!1,message:"Certificate not found"};console.log(`
3766
3766
  Renewing certificate: ${s.domainName}`),console.log(`Certificate ARN: ${s.arn}`);try{return console.log(`
3767
3767
  1. Requesting new certificate...`),console.log("2. Validating domain ownership..."),console.log("3. Issuing renewed certificate..."),console.log("4. Updating resource associations..."),s.issuedAt=new Date,s.expiresAt=new Date(Date.now()+31536000000),i.lastRenewal=new Date,i.renewalStatus="success",i.nextRenewal=new Date(s.expiresAt.getTime()-i.renewBeforeDays*24*60*60*1000),console.log(`
3768
- ✓ Certificate renewed successfully`),console.log(` New expiration: ${s.expiresAt.toISOString()}`),console.log(` Next renewal: ${i.nextRenewal.toISOString()}`),{success:!0,message:"Certificate renewed successfully"}}catch(o){return i.renewalStatus="failed",this.createAlert({certificateArn:s.arn,alertType:"renewal_failed",severity:"critical",message:`Certificate renewal failed: ${o}`}),{success:!1,message:o instanceof Error?o.message:String(o)}}}createMonitor(n){let i=`monitor-${Date.now()}-${this.monitorCounter++}`,s={id:i,...n};return this.monitors.set(i,s),s}checkExpiration(){let n=[],i=Date.now();for(let s of this.certificates.values()){if(!s.expiresAt)continue;let o=(s.expiresAt.getTime()-i)/86400000;if(o<0)n.push(this.createAlert({certificateArn:s.arn,alertType:"expired",severity:"critical",message:`Certificate has expired for ${s.domainName}`}));else if(o<30)n.push(this.createAlert({certificateArn:s.arn,alertType:"expiring_soon",severity:o<7?"critical":"warning",message:`Certificate expiring in ${Math.floor(o)} days for ${s.domainName}`}))}return n}createAlert(n){let i=`alert-${Date.now()}-${this.alertCounter++}`,s={id:i,timestamp:new Date,acknowledged:!1,...n};return this.alerts.set(i,s),s}acknowledgeAlert(n){let i=this.alerts.get(n);if(i)i.acknowledged=!0}getCertificate(n){return this.certificates.get(n)}listCertificates(){return Array.from(this.certificates.values())}getExpiringCertificates(n=30){let i=Date.now()+n*24*60*60*1000;return Array.from(this.certificates.values()).filter((s)=>s.expiresAt&&s.expiresAt.getTime()<i)}getValidation(n){return this.validations.get(n)}getRenewal(n){return this.renewals.get(n)}listRenewals(){return Array.from(this.renewals.values())}listAlerts(n=!1){return Array.from(this.alerts.values()).filter((i)=>i.acknowledged===n)}generateCertificateCF(n){return{Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:n.domainName,...n.subjectAlternativeNames&&{SubjectAlternativeNames:n.subjectAlternativeNames},ValidationMethod:n.validationMethod}}}generateExpirationAlarmCF(n){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:n.alarmName,AlarmDescription:`Certificate expiring in ${n.daysBeforeExpiration} days`,MetricName:"DaysToExpiry",Namespace:"AWS/CertificateManager",Statistic:"Minimum",Period:86400,EvaluationPeriods:1,Threshold:n.daysBeforeExpiration,ComparisonOperator:"LessThanThreshold",Dimensions:[{Name:"CertificateArn",Value:n.certificateArn}],...n.snsTopicArn&&{AlarmActions:[n.snsTopicArn]}}}}clear(){this.certificates.clear(),this.renewals.clear(),this.validations.clear(),this.monitors.clear(),this.alerts.clear(),this.certificateCounter=0,this.renewalCounter=0,this.validationCounter=0,this.monitorCounter=0,this.alertCounter=0}}var mE=new am;class cm{scans=new Map;findings=new Map;reports=new Map;complianceChecks=new Map;postures=new Map;scanCounter=0;findingCounter=0;reportCounter=0;checkCounter=0;postureCounter=0;createScan(n){let i=`scan-${Date.now()}-${this.scanCounter++}`,s={id:i,status:"queued",findings:[],...n};return this.scans.set(i,s),s}createContainerScan(n){return this.createScan({name:n.name,scanType:"container_image",target:{type:"ecr_image",identifier:n.imageUri,region:n.region||"us-east-1"}})}createLambdaScan(n){return this.createScan({name:n.name,scanType:"vulnerability",target:{type:"lambda",identifier:n.functionName,region:n.region||"us-east-1"}})}createSecretsDetectionScan(n){return this.createScan({name:n.name,scanType:"secrets_detection",target:{type:"repository",identifier:n.repositoryUrl}})}async executeScan(n){let i=this.scans.get(n);if(!i)throw Error(`Scan not found: ${n}`);console.log(`
3768
+ ✓ Certificate renewed successfully`),console.log(` New expiration: ${s.expiresAt.toISOString()}`),console.log(` Next renewal: ${i.nextRenewal.toISOString()}`),{success:!0,message:"Certificate renewed successfully"}}catch(o){return i.renewalStatus="failed",this.createAlert({certificateArn:s.arn,alertType:"renewal_failed",severity:"critical",message:`Certificate renewal failed: ${o}`}),{success:!1,message:o instanceof Error?o.message:String(o)}}}createMonitor(n){let i=`monitor-${Date.now()}-${this.monitorCounter++}`,s={id:i,...n};return this.monitors.set(i,s),s}checkExpiration(){let n=[],i=Date.now();for(let s of this.certificates.values()){if(!s.expiresAt)continue;let o=(s.expiresAt.getTime()-i)/86400000;if(o<0)n.push(this.createAlert({certificateArn:s.arn,alertType:"expired",severity:"critical",message:`Certificate has expired for ${s.domainName}`}));else if(o<30)n.push(this.createAlert({certificateArn:s.arn,alertType:"expiring_soon",severity:o<7?"critical":"warning",message:`Certificate expiring in ${Math.floor(o)} days for ${s.domainName}`}))}return n}createAlert(n){let i=`alert-${Date.now()}-${this.alertCounter++}`,s={id:i,timestamp:new Date,acknowledged:!1,...n};return this.alerts.set(i,s),s}acknowledgeAlert(n){let i=this.alerts.get(n);if(i)i.acknowledged=!0}getCertificate(n){return this.certificates.get(n)}listCertificates(){return Array.from(this.certificates.values())}getExpiringCertificates(n=30){let i=Date.now()+n*24*60*60*1000;return Array.from(this.certificates.values()).filter((s)=>s.expiresAt&&s.expiresAt.getTime()<i)}getValidation(n){return this.validations.get(n)}getRenewal(n){return this.renewals.get(n)}listRenewals(){return Array.from(this.renewals.values())}listAlerts(n=!1){return Array.from(this.alerts.values()).filter((i)=>i.acknowledged===n)}generateCertificateCF(n){return{Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:n.domainName,...n.subjectAlternativeNames&&{SubjectAlternativeNames:n.subjectAlternativeNames},ValidationMethod:n.validationMethod}}}generateExpirationAlarmCF(n){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:n.alarmName,AlarmDescription:`Certificate expiring in ${n.daysBeforeExpiration} days`,MetricName:"DaysToExpiry",Namespace:"AWS/CertificateManager",Statistic:"Minimum",Period:86400,EvaluationPeriods:1,Threshold:n.daysBeforeExpiration,ComparisonOperator:"LessThanThreshold",Dimensions:[{Name:"CertificateArn",Value:n.certificateArn}],...n.snsTopicArn&&{AlarmActions:[n.snsTopicArn]}}}}clear(){this.certificates.clear(),this.renewals.clear(),this.validations.clear(),this.monitors.clear(),this.alerts.clear(),this.certificateCounter=0,this.renewalCounter=0,this.validationCounter=0,this.monitorCounter=0,this.alertCounter=0}}var fE=new dm;class lm{scans=new Map;findings=new Map;reports=new Map;complianceChecks=new Map;postures=new Map;scanCounter=0;findingCounter=0;reportCounter=0;checkCounter=0;postureCounter=0;createScan(n){let i=`scan-${Date.now()}-${this.scanCounter++}`,s={id:i,status:"queued",findings:[],...n};return this.scans.set(i,s),s}createContainerScan(n){return this.createScan({name:n.name,scanType:"container_image",target:{type:"ecr_image",identifier:n.imageUri,region:n.region||"us-east-1"}})}createLambdaScan(n){return this.createScan({name:n.name,scanType:"vulnerability",target:{type:"lambda",identifier:n.functionName,region:n.region||"us-east-1"}})}createSecretsDetectionScan(n){return this.createScan({name:n.name,scanType:"secrets_detection",target:{type:"repository",identifier:n.repositoryUrl}})}async executeScan(n){let i=this.scans.get(n);if(!i)throw Error(`Scan not found: ${n}`);console.log(`
3769
3769
  Executing security scan: ${i.name}`),console.log(`Scan type: ${i.scanType}`),console.log(`Target: ${i.target.type} - ${i.target.identifier}`),i.status="running",i.startedAt=new Date;try{console.log(`
3770
3770
  Scanning...`);let s=this.simulateFindings(i);return i.findings=s,i.status="completed",i.completedAt=new Date,i.summary={totalFindings:s.length,criticalCount:s.filter((o)=>o.severity==="CRITICAL").length,highCount:s.filter((o)=>o.severity==="HIGH").length,mediumCount:s.filter((o)=>o.severity==="MEDIUM").length,lowCount:s.filter((o)=>o.severity==="LOW").length,infoCount:s.filter((o)=>o.severity==="INFO").length,executionTime:i.completedAt.getTime()-i.startedAt.getTime()},console.log(`
3771
- ✓ Scan completed`),console.log(` Findings: ${i.summary.totalFindings}`),console.log(` Critical: ${i.summary.criticalCount}`),console.log(` High: ${i.summary.highCount}`),console.log(` Medium: ${i.summary.mediumCount}`),console.log(` Low: ${i.summary.lowCount}`),i}catch(s){throw i.status="failed",i.completedAt=new Date,s}}simulateFindings(n){let i=[],s=new Date;if(n.scanType==="container_image")i.push(this.createFinding({severity:"HIGH",title:"Vulnerable OpenSSL version detected",description:"OpenSSL 1.1.1k contains known vulnerabilities",cve:"CVE-2021-3711",cvss:7.5,affectedResource:n.target.identifier,remediation:"Update OpenSSL to version 1.1.1l or later",status:"OPEN",firstDetected:s,lastSeen:s})),i.push(this.createFinding({severity:"MEDIUM",title:"Outdated npm package: lodash",description:"lodash 4.17.19 has known security issues",cve:"CVE-2020-8203",cvss:5.3,affectedResource:n.target.identifier,remediation:"Update lodash to version 4.17.21 or later",status:"OPEN",firstDetected:s,lastSeen:s}));else if(n.scanType==="secrets_detection")i.push(this.createFinding({severity:"CRITICAL",title:"AWS Access Key exposed in code",description:"Hardcoded AWS access key found in source code",affectedResource:`${n.target.identifier}/src/config.ts:12`,remediation:"Remove hardcoded credentials and use AWS Secrets Manager",status:"OPEN",firstDetected:s,lastSeen:s}));return i}createFinding(n){let i=`finding-${Date.now()}-${this.findingCounter++}`,s={id:i,...n};return this.findings.set(i,s),s}suppressFinding(n,i){let s=this.findings.get(n);if(s){if(s.status="SUPPRESSED",console.log(`Finding suppressed: ${s.title}`),i)console.log(`Reason: ${i}`)}}resolveFinding(n){let i=this.findings.get(n);if(i)i.status="RESOLVED",console.log(`Finding resolved: ${i.title}`)}generateReport(n){let i=`report-${Date.now()}-${this.reportCounter++}`,s={id:i,scanId:n.scanId,reportType:n.reportType,format:n.format,generatedAt:new Date,s3Location:`s3://security-reports/${i}.${n.format}`};return this.reports.set(i,s),s}runComplianceCheck(n){let i=[];if(n.framework.includes("CIS"))i.push(this.createComplianceCheck({framework:n.framework,checkId:"1.1",title:"Avoid the use of root account",description:"Root account should not be used for everyday tasks",status:"PASS",severity:"CRITICAL",resourceType:n.resourceType,resourceId:n.resourceId})),i.push(this.createComplianceCheck({framework:n.framework,checkId:"2.1",title:"Ensure CloudTrail is enabled",description:"CloudTrail should be enabled in all regions",status:"FAIL",severity:"HIGH",resourceType:n.resourceType,resourceId:n.resourceId,remediation:"Enable CloudTrail in all regions"}));return i}createComplianceCheck(n){let i=`check-${Date.now()}-${this.checkCounter++}`,s={id:i,...n};return this.complianceChecks.set(i,s),s}assessSecurityPosture(n){let i=`posture-${Date.now()}-${this.postureCounter++}`,s=Array.from(this.complianceChecks.values()),o=s.filter((y)=>y.status==="PASS").length,c=s.length,l=c>0?Math.round(o/c*100):0,u;if(l>=90)u="A";else if(l>=80)u="B";else if(l>=70)u="C";else if(l>=60)u="D";else u="F";let h={id:i,accountId:n.accountId,region:n.region,score:l,grade:u,assessedAt:new Date,strengths:["IAM password policy enforced","Multi-factor authentication enabled","CloudTrail logging enabled"],weaknesses:["Some S3 buckets are publicly accessible","Security groups allow unrestricted ingress","Outdated dependencies in Lambda functions"],recommendations:["Review and update S3 bucket policies","Implement least-privilege security group rules","Update Lambda runtime versions and dependencies","Enable GuardDuty for threat detection"]};return this.postures.set(i,h),h}getScan(n){return this.scans.get(n)}listScans(){return Array.from(this.scans.values())}getOpenFindings(n){return Array.from(this.findings.values()).filter((i)=>i.status==="OPEN"&&(!n||i.severity===n))}getComplianceChecksByStatus(n){return Array.from(this.complianceChecks.values()).filter((i)=>i.status===n)}listPostures(){return Array.from(this.postures.values())}generateECRScanCF(n){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:n,ImageScanningConfiguration:{ScanOnPush:!0},ImageTagMutability:"IMMUTABLE"}}}clear(){this.scans.clear(),this.findings.clear(),this.reports.clear(),this.complianceChecks.clear(),this.postures.clear(),this.scanCounter=0,this.findingCounter=0,this.reportCounter=0,this.checkCounter=0,this.postureCounter=0}}var hE=new cm;class dm{configs=new Map;results=new Map;policies=new Map;configCounter=0;resultCounter=0;policyCounter=0;configureScan(n){let i=`scan-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}configureTrivyScan(n){return this.configureScan({repository:n.repository,imageTag:n.imageTag,scanner:"trivy",scanOnPush:n.scanOnPush??!0,ignoreUnfixed:n.ignoreUnfixed??!1,failOnSeverity:"HIGH"})}configureSnykScan(n){return this.configureScan({repository:n.repository,imageTag:n.imageTag,scanner:"snyk",scanOnPush:n.scanOnPush??!0,failOnSeverity:"HIGH"})}configureECRScan(n){return this.configureScan({repository:n.repository,imageTag:"latest",scanner:"ecr",scanOnPush:n.scanOnPush??!0,failOnSeverity:"CRITICAL"})}async scanImage(n){let i=this.configs.get(n);if(!i)throw Error(`Scan config not found: ${n}`);let s=`${i.repository}:${i.imageTag}`;console.log(`
3771
+ ✓ Scan completed`),console.log(` Findings: ${i.summary.totalFindings}`),console.log(` Critical: ${i.summary.criticalCount}`),console.log(` High: ${i.summary.highCount}`),console.log(` Medium: ${i.summary.mediumCount}`),console.log(` Low: ${i.summary.lowCount}`),i}catch(s){throw i.status="failed",i.completedAt=new Date,s}}simulateFindings(n){let i=[],s=new Date;if(n.scanType==="container_image")i.push(this.createFinding({severity:"HIGH",title:"Vulnerable OpenSSL version detected",description:"OpenSSL 1.1.1k contains known vulnerabilities",cve:"CVE-2021-3711",cvss:7.5,affectedResource:n.target.identifier,remediation:"Update OpenSSL to version 1.1.1l or later",status:"OPEN",firstDetected:s,lastSeen:s})),i.push(this.createFinding({severity:"MEDIUM",title:"Outdated npm package: lodash",description:"lodash 4.17.19 has known security issues",cve:"CVE-2020-8203",cvss:5.3,affectedResource:n.target.identifier,remediation:"Update lodash to version 4.17.21 or later",status:"OPEN",firstDetected:s,lastSeen:s}));else if(n.scanType==="secrets_detection")i.push(this.createFinding({severity:"CRITICAL",title:"AWS Access Key exposed in code",description:"Hardcoded AWS access key found in source code",affectedResource:`${n.target.identifier}/src/config.ts:12`,remediation:"Remove hardcoded credentials and use AWS Secrets Manager",status:"OPEN",firstDetected:s,lastSeen:s}));return i}createFinding(n){let i=`finding-${Date.now()}-${this.findingCounter++}`,s={id:i,...n};return this.findings.set(i,s),s}suppressFinding(n,i){let s=this.findings.get(n);if(s){if(s.status="SUPPRESSED",console.log(`Finding suppressed: ${s.title}`),i)console.log(`Reason: ${i}`)}}resolveFinding(n){let i=this.findings.get(n);if(i)i.status="RESOLVED",console.log(`Finding resolved: ${i.title}`)}generateReport(n){let i=`report-${Date.now()}-${this.reportCounter++}`,s={id:i,scanId:n.scanId,reportType:n.reportType,format:n.format,generatedAt:new Date,s3Location:`s3://security-reports/${i}.${n.format}`};return this.reports.set(i,s),s}runComplianceCheck(n){let i=[];if(n.framework.includes("CIS"))i.push(this.createComplianceCheck({framework:n.framework,checkId:"1.1",title:"Avoid the use of root account",description:"Root account should not be used for everyday tasks",status:"PASS",severity:"CRITICAL",resourceType:n.resourceType,resourceId:n.resourceId})),i.push(this.createComplianceCheck({framework:n.framework,checkId:"2.1",title:"Ensure CloudTrail is enabled",description:"CloudTrail should be enabled in all regions",status:"FAIL",severity:"HIGH",resourceType:n.resourceType,resourceId:n.resourceId,remediation:"Enable CloudTrail in all regions"}));return i}createComplianceCheck(n){let i=`check-${Date.now()}-${this.checkCounter++}`,s={id:i,...n};return this.complianceChecks.set(i,s),s}assessSecurityPosture(n){let i=`posture-${Date.now()}-${this.postureCounter++}`,s=Array.from(this.complianceChecks.values()),o=s.filter((y)=>y.status==="PASS").length,c=s.length,l=c>0?Math.round(o/c*100):0,u;if(l>=90)u="A";else if(l>=80)u="B";else if(l>=70)u="C";else if(l>=60)u="D";else u="F";let h={id:i,accountId:n.accountId,region:n.region,score:l,grade:u,assessedAt:new Date,strengths:["IAM password policy enforced","Multi-factor authentication enabled","CloudTrail logging enabled"],weaknesses:["Some S3 buckets are publicly accessible","Security groups allow unrestricted ingress","Outdated dependencies in Lambda functions"],recommendations:["Review and update S3 bucket policies","Implement least-privilege security group rules","Update Lambda runtime versions and dependencies","Enable GuardDuty for threat detection"]};return this.postures.set(i,h),h}getScan(n){return this.scans.get(n)}listScans(){return Array.from(this.scans.values())}getOpenFindings(n){return Array.from(this.findings.values()).filter((i)=>i.status==="OPEN"&&(!n||i.severity===n))}getComplianceChecksByStatus(n){return Array.from(this.complianceChecks.values()).filter((i)=>i.status===n)}listPostures(){return Array.from(this.postures.values())}generateECRScanCF(n){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:n,ImageScanningConfiguration:{ScanOnPush:!0},ImageTagMutability:"IMMUTABLE"}}}clear(){this.scans.clear(),this.findings.clear(),this.reports.clear(),this.complianceChecks.clear(),this.postures.clear(),this.scanCounter=0,this.findingCounter=0,this.reportCounter=0,this.checkCounter=0,this.postureCounter=0}}var AE=new lm;class um{configs=new Map;results=new Map;policies=new Map;configCounter=0;resultCounter=0;policyCounter=0;configureScan(n){let i=`scan-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}configureTrivyScan(n){return this.configureScan({repository:n.repository,imageTag:n.imageTag,scanner:"trivy",scanOnPush:n.scanOnPush??!0,ignoreUnfixed:n.ignoreUnfixed??!1,failOnSeverity:"HIGH"})}configureSnykScan(n){return this.configureScan({repository:n.repository,imageTag:n.imageTag,scanner:"snyk",scanOnPush:n.scanOnPush??!0,failOnSeverity:"HIGH"})}configureECRScan(n){return this.configureScan({repository:n.repository,imageTag:"latest",scanner:"ecr",scanOnPush:n.scanOnPush??!0,failOnSeverity:"CRITICAL"})}async scanImage(n){let i=this.configs.get(n);if(!i)throw Error(`Scan config not found: ${n}`);let s=`${i.repository}:${i.imageTag}`;console.log(`
3772
3772
  Scanning image: ${s}`),console.log(`Scanner: ${i.scanner}`);let o=`scan-result-${Date.now()}-${this.resultCounter++}`,c=this.simulateVulnerabilities(i),l={total:c.length,critical:c.filter((y)=>y.severity==="CRITICAL").length,high:c.filter((y)=>y.severity==="HIGH").length,medium:c.filter((y)=>y.severity==="MEDIUM").length,low:c.filter((y)=>y.severity==="LOW").length,unknown:c.filter((y)=>y.severity==="UNKNOWN").length},u=this.evaluateScanResult(i,l),h={id:o,imageUri:s,scannerType:i.scanner,scanDate:new Date,vulnerabilities:c,summary:l,passed:u};return this.results.set(o,h),console.log(`
3773
- Scan Results:`),console.log(` Total vulnerabilities: ${l.total}`),console.log(` Critical: ${l.critical}`),console.log(` High: ${l.high}`),console.log(` Medium: ${l.medium}`),console.log(` Low: ${l.low}`),console.log(` Status: ${u?"✓ PASSED":"✗ FAILED"}`),h}simulateVulnerabilities(n){let i=[];if(n.scanner==="trivy"||n.scanner==="ecr")i.push({id:"vuln-1",cve:"CVE-2024-1234",severity:"HIGH",packageName:"openssl",installedVersion:"1.1.1k",fixedVersion:"1.1.1l",title:"OpenSSL buffer overflow",description:"Buffer overflow vulnerability in OpenSSL",references:["https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-1234"],cvss:7.5}),i.push({id:"vuln-2",cve:"CVE-2024-5678",severity:"MEDIUM",packageName:"curl",installedVersion:"7.68.0",fixedVersion:"7.79.0",title:"curl remote code execution",description:"Remote code execution in curl",references:["https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-5678"],cvss:5.3});return i}evaluateScanResult(n,i){if(!n.failOnSeverity)return!0;switch(n.failOnSeverity){case"CRITICAL":return i.critical===0;case"HIGH":return i.critical===0&&i.high===0;case"MEDIUM":return i.critical===0&&i.high===0&&i.medium===0;case"LOW":return i.total===0;default:return!0}}createPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,...n};return this.policies.set(i,s),s}createStrictPolicy(n){return this.createPolicy({name:n,allowedSeverities:[],maxCritical:0,maxHigh:0,blockOnFailure:!0,exemptions:[]})}createPermissivePolicy(n){return this.createPolicy({name:n,allowedSeverities:["CRITICAL","HIGH","MEDIUM","LOW"],maxCritical:5,maxHigh:10,blockOnFailure:!1,exemptions:[]})}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getResult(n){return this.results.get(n)}listResults(){return Array.from(this.results.values())}generateECRScanCF(n){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:n.repository,ImageScanningConfiguration:{ScanOnPush:n.scanOnPush},ImageTagMutability:"IMMUTABLE",EncryptionConfiguration:{EncryptionType:"AES256"}}}}clear(){this.configs.clear(),this.results.clear(),this.policies.clear(),this.configCounter=0,this.resultCounter=0,this.policyCounter=0}}var fE=new dm;class lm{configs=new Map;multiStageConfigs=new Map;optimizations=new Map;analyses=new Map;configCounter=0;multiStageCounter=0;optimizationCounter=0;analysisCounter=0;createBuildConfig(n){let i=`build-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}createOptimizedBuildConfig(n){let i={type:n.enableCache?"registry":"inline",cacheFrom:n.registry?[`${n.registry}/cache`]:void 0,cacheTo:n.registry?`${n.registry}/cache`:void 0,maxCacheAge:7};return this.createBuildConfig({name:n.name,dockerfile:n.dockerfile,context:".",cacheStrategy:i,buildArgs:{BUILDKIT_INLINE_CACHE:"1"}})}createMultiStageConfig(n){let i=`multi-stage-${Date.now()}-${this.multiStageCounter++}`,s={id:i,...n};return this.multiStageConfigs.set(i,s),s}createNodeMultiStageBuild(n){let i=n.nodeVersion||"18-alpine";return this.createMultiStageConfig({name:n.name,targetStage:n.targetStage||"production",stages:[{name:"dependencies",baseImage:`node:${i}`,workdir:"/app",commands:["COPY package*.json ./","RUN npm ci --only=production"]},{name:"build",baseImage:`node:${i}`,workdir:"/app",commands:["COPY package*.json ./","RUN npm ci","COPY . .","RUN npm run build"]},{name:"production",baseImage:`node:${i}`,workdir:"/app",copyFrom:["dependencies:/app/node_modules","build:/app/dist"],commands:["COPY package*.json ./","ENV NODE_ENV=production",'CMD ["node", "dist/index.js"]']}]})}generateDockerfile(n){let i=this.multiStageConfigs.get(n);if(!i)throw Error(`Multi-stage config not found: ${n}`);let s=[];for(let o of i.stages){if(s.push(`# Stage: ${o.name}`),s.push(`FROM ${o.baseImage} AS ${o.name}`),o.workdir)s.push(`WORKDIR ${o.workdir}`);if(o.env)for(let[c,l]of Object.entries(o.env))s.push(`ENV ${c}=${l}`);for(let c of o.commands)s.push(c);s.push("")}return s.join(`
3773
+ Scan Results:`),console.log(` Total vulnerabilities: ${l.total}`),console.log(` Critical: ${l.critical}`),console.log(` High: ${l.high}`),console.log(` Medium: ${l.medium}`),console.log(` Low: ${l.low}`),console.log(` Status: ${u?"✓ PASSED":"✗ FAILED"}`),h}simulateVulnerabilities(n){let i=[];if(n.scanner==="trivy"||n.scanner==="ecr")i.push({id:"vuln-1",cve:"CVE-2024-1234",severity:"HIGH",packageName:"openssl",installedVersion:"1.1.1k",fixedVersion:"1.1.1l",title:"OpenSSL buffer overflow",description:"Buffer overflow vulnerability in OpenSSL",references:["https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-1234"],cvss:7.5}),i.push({id:"vuln-2",cve:"CVE-2024-5678",severity:"MEDIUM",packageName:"curl",installedVersion:"7.68.0",fixedVersion:"7.79.0",title:"curl remote code execution",description:"Remote code execution in curl",references:["https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-5678"],cvss:5.3});return i}evaluateScanResult(n,i){if(!n.failOnSeverity)return!0;switch(n.failOnSeverity){case"CRITICAL":return i.critical===0;case"HIGH":return i.critical===0&&i.high===0;case"MEDIUM":return i.critical===0&&i.high===0&&i.medium===0;case"LOW":return i.total===0;default:return!0}}createPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,...n};return this.policies.set(i,s),s}createStrictPolicy(n){return this.createPolicy({name:n,allowedSeverities:[],maxCritical:0,maxHigh:0,blockOnFailure:!0,exemptions:[]})}createPermissivePolicy(n){return this.createPolicy({name:n,allowedSeverities:["CRITICAL","HIGH","MEDIUM","LOW"],maxCritical:5,maxHigh:10,blockOnFailure:!1,exemptions:[]})}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getResult(n){return this.results.get(n)}listResults(){return Array.from(this.results.values())}generateECRScanCF(n){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:n.repository,ImageScanningConfiguration:{ScanOnPush:n.scanOnPush},ImageTagMutability:"IMMUTABLE",EncryptionConfiguration:{EncryptionType:"AES256"}}}}clear(){this.configs.clear(),this.results.clear(),this.policies.clear(),this.configCounter=0,this.resultCounter=0,this.policyCounter=0}}var yE=new um;class pm{configs=new Map;multiStageConfigs=new Map;optimizations=new Map;analyses=new Map;configCounter=0;multiStageCounter=0;optimizationCounter=0;analysisCounter=0;createBuildConfig(n){let i=`build-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}createOptimizedBuildConfig(n){let i={type:n.enableCache?"registry":"inline",cacheFrom:n.registry?[`${n.registry}/cache`]:void 0,cacheTo:n.registry?`${n.registry}/cache`:void 0,maxCacheAge:7};return this.createBuildConfig({name:n.name,dockerfile:n.dockerfile,context:".",cacheStrategy:i,buildArgs:{BUILDKIT_INLINE_CACHE:"1"}})}createMultiStageConfig(n){let i=`multi-stage-${Date.now()}-${this.multiStageCounter++}`,s={id:i,...n};return this.multiStageConfigs.set(i,s),s}createNodeMultiStageBuild(n){let i=n.nodeVersion||"18-alpine";return this.createMultiStageConfig({name:n.name,targetStage:n.targetStage||"production",stages:[{name:"dependencies",baseImage:`node:${i}`,workdir:"/app",commands:["COPY package*.json ./","RUN npm ci --only=production"]},{name:"build",baseImage:`node:${i}`,workdir:"/app",commands:["COPY package*.json ./","RUN npm ci","COPY . .","RUN npm run build"]},{name:"production",baseImage:`node:${i}`,workdir:"/app",copyFrom:["dependencies:/app/node_modules","build:/app/dist"],commands:["COPY package*.json ./","ENV NODE_ENV=production",'CMD ["node", "dist/index.js"]']}]})}generateDockerfile(n){let i=this.multiStageConfigs.get(n);if(!i)throw Error(`Multi-stage config not found: ${n}`);let s=[];for(let o of i.stages){if(s.push(`# Stage: ${o.name}`),s.push(`FROM ${o.baseImage} AS ${o.name}`),o.workdir)s.push(`WORKDIR ${o.workdir}`);if(o.env)for(let[c,l]of Object.entries(o.env))s.push(`ENV ${c}=${l}`);for(let c of o.commands)s.push(c);s.push("")}return s.join(`
3774
3774
  `)}analyzeImage(n,i){let s=`analysis-${Date.now()}-${this.analysisCounter++}`,o=i.map((h)=>({...h,cacheable:this.isLayerCacheable(h.command)})),c=o.reduce((h,y)=>h+y.size,0),l=o.filter((h)=>!h.cacheable&&h.size>100).length,u={id:s,imageId:n,layers:o,totalSize:c,unnecessaryLayers:l};return this.analyses.set(s,u),u}isLayerCacheable(n){let i=["FROM","RUN","COPY","ADD","WORKDIR","ENV"],s=["CMD","ENTRYPOINT","LABEL"];for(let o of i)if(n.startsWith(o))return!0;for(let o of s)if(n.startsWith(o))return!1;return!1}generateOptimizations(n){let i=this.analyses.get(n);if(!i)throw Error(`Analysis not found: ${n}`);let s=`optimization-${Date.now()}-${this.optimizationCounter++}`,o=[],c=i.layers.filter((f)=>f.command.startsWith("RUN"));if(c.length>5)o.push({type:"layer_reduction",priority:"high",title:"Combine RUN commands",description:`${c.length} RUN commands found. Combine them to reduce layers.`,example:"RUN apt-get update && apt-get install -y package1 package2",impact:"Reduce image size by 20-30% and improve build time"});let l=i.layers[0];if(l.command.includes("ubuntu")||l.command.includes("debian"))o.push({type:"base_image",priority:"medium",title:"Use Alpine base image",description:"Switch to Alpine Linux for smaller image size",example:"FROM node:18-alpine",impact:"Reduce image size by 50-70%"});let u=i.layers.filter((f)=>f.command.startsWith("COPY"));if(u.length>0&&u[0].index>3)o.push({type:"cache_optimization",priority:"high",title:"Copy dependencies first",description:"Copy package files before source code to leverage layer caching",example:`COPY package*.json ./
3775
3775
  RUN npm install
3776
- COPY . .`,impact:"Improve build time by 60-80% on subsequent builds"});let h={sizeBefore:i.totalSize,sizeAfter:i.totalSize*0.6,timeBefore:300,timeAfter:120},y={id:s,name:`Optimization for ${i.imageId}`,recommendations:o,estimatedSavings:h};return this.optimizations.set(s,y),y}getBuildConfig(n){return this.configs.get(n)}listBuildConfigs(){return Array.from(this.configs.values())}getMultiStageConfig(n){return this.multiStageConfigs.get(n)}listMultiStageConfigs(){return Array.from(this.multiStageConfigs.values())}getOptimization(n){return this.optimizations.get(n)}listOptimizations(){return Array.from(this.optimizations.values())}clear(){this.configs.clear(),this.multiStageConfigs.clear(),this.optimizations.clear(),this.analyses.clear(),this.configCounter=0,this.multiStageCounter=0,this.optimizationCounter=0,this.analysisCounter=0}}var AE=new lm;class um{registries=new Map;credentials=new Map;registryCounter=0;credentialsCounter=0;createRegistry(n){let i=`registry-${Date.now()}-${this.registryCounter++}`,s={id:i,...n};return this.registries.set(i,s),s}createECRRepository(n){return this.createRegistry({name:n.name,registryType:"ecr",repositoryUri:`123456789012.dkr.ecr.${n.region||"us-east-1"}.amazonaws.com/${n.name}`,region:n.region||"us-east-1",encryption:{encryptionType:n.encryption||"AES256",kmsKeyId:n.kmsKeyId},scanning:{scanOnPush:n.scanOnPush??!0}})}createManagedRepository(n){let i=this.createECRRepository({name:n.name,region:n.region,scanOnPush:!0,encryption:"KMS"});return i.lifecycle={id:`lifecycle-${Date.now()}`,rules:[{rulePriority:1,description:"Keep only last N images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:n.maxImageCount||10},action:{type:"expire"}},{rulePriority:2,description:"Remove images older than N days",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:n.maxImageAgeDays||30,countUnit:"days"},action:{type:"expire"}}]},i}enableReplication(n,i){let s=this.registries.get(n);if(!s)throw Error(`Registry not found: ${n}`);return s.replication={enabled:!0,destinations:i},s}createCredentials(n){let i=`creds-${Date.now()}-${this.credentialsCounter++}`,s={id:i,...n};return this.credentials.set(i,s),s}getRegistry(n){return this.registries.get(n)}listRegistries(){return Array.from(this.registries.values())}generateECRRepositoryCF(n){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:n.name,ImageScanningConfiguration:{ScanOnPush:n.scanning?.scanOnPush??!1},EncryptionConfiguration:{EncryptionType:n.encryption?.encryptionType||"AES256",...n.encryption?.kmsKeyId&&{KmsKey:n.encryption.kmsKeyId}},ImageTagMutability:"MUTABLE",...n.lifecycle&&{LifecyclePolicy:{LifecyclePolicyText:JSON.stringify({rules:n.lifecycle.rules})}}}}}generateReplicationConfigCF(n){return{Type:"AWS::ECR::ReplicationConfiguration",Properties:{ReplicationConfiguration:{Rules:n.destinations.map((i)=>({Destinations:[{Region:i.region,...i.registryId&&{RegistryId:i.registryId}}]}))}}}}clear(){this.registries.clear(),this.credentials.clear(),this.registryCounter=0,this.credentialsCounter=0}}var yE=new um;class pm{meshes=new Map;virtualNodes=new Map;virtualRouters=new Map;virtualGateways=new Map;meshCounter=0;nodeCounter=0;routerCounter=0;gatewayCounter=0;createMesh(n){let i=`mesh-${Date.now()}-${this.meshCounter++}`,s={id:i,...n};return this.meshes.set(i,s),s}createAppMesh(n){return this.createMesh({name:n.name,meshType:"app_mesh",services:n.services,virtualNodes:[],virtualRouters:[],virtualGateways:[]})}createVirtualNode(n){let i=`vnode-${Date.now()}-${this.nodeCounter++}`,s={id:i,...n};return this.virtualNodes.set(i,s),s}createHTTPVirtualNode(n){return this.createVirtualNode({name:n.name,serviceName:n.serviceName,listeners:[{port:n.port,protocol:"http",healthCheck:{protocol:"http",path:"/health",interval:30,timeout:10,healthyThreshold:2,unhealthyThreshold:3},timeout:{perRequest:15000,idle:300000}}],serviceDiscovery:{type:"aws_cloud_map",namespace:n.namespace,serviceName:n.serviceName}})}createVirtualRouter(n){let i=`vrouter-${Date.now()}-${this.routerCounter++}`,s={id:i,...n};return this.virtualRouters.set(i,s),s}createCanaryRoute(n){return this.createVirtualRouter({name:n.name,listeners:[{port:n.port,protocol:n.protocol}],routes:[{name:"canary-route",match:{prefix:"/"},action:{weightedTargets:[{virtualNode:n.stableTarget,weight:100-n.canaryWeight},{virtualNode:n.canaryTarget,weight:n.canaryWeight}]},retryPolicy:{maxRetries:3,perRetryTimeout:5000,httpRetryEvents:["server-error","gateway-error"],tcpRetryEvents:["connection-error"]}}]})}createVirtualGateway(n){let i=`vgateway-${Date.now()}-${this.gatewayCounter++}`,s={id:i,...n};return this.virtualGateways.set(i,s),s}createIngressGateway(n){let i={port:n.port,protocol:"http",healthCheck:{protocol:"http",path:"/health",interval:30,timeout:10,healthyThreshold:2,unhealthyThreshold:3}};if(n.enableTLS&&n.certificateArn)i.tls={mode:"STRICT",certificate:{acm:n.certificateArn}};return this.createVirtualGateway({name:n.name,listeners:[i],logging:{accessLog:{file:{path:"/dev/stdout"}}}})}getMesh(n){return this.meshes.get(n)}listMeshes(){return Array.from(this.meshes.values())}getVirtualNode(n){return this.virtualNodes.get(n)}listVirtualNodes(){return Array.from(this.virtualNodes.values())}generateMeshCF(n){return{Type:"AWS::AppMesh::Mesh",Properties:{MeshName:n.name,Spec:{EgressFilter:{Type:"ALLOW_ALL"}}}}}generateVirtualNodeCF(n,i){return{Type:"AWS::AppMesh::VirtualNode",Properties:{MeshName:i,VirtualNodeName:n.name,Spec:{Listeners:n.listeners.map((s)=>({PortMapping:{Port:s.port,Protocol:s.protocol},...s.healthCheck&&{HealthCheck:{Protocol:s.healthCheck.protocol,...s.healthCheck.path&&{Path:s.healthCheck.path},IntervalMillis:s.healthCheck.interval*1000,TimeoutMillis:s.healthCheck.timeout*1000,HealthyThreshold:s.healthCheck.healthyThreshold,UnhealthyThreshold:s.healthCheck.unhealthyThreshold}}})),ServiceDiscovery:{AWSCloudMap:{NamespaceName:n.serviceDiscovery.namespace,ServiceName:n.serviceDiscovery.serviceName}}}}}}generateVirtualRouterCF(n,i){return{Type:"AWS::AppMesh::VirtualRouter",Properties:{MeshName:i,VirtualRouterName:n.name,Spec:{Listeners:n.listeners.map((s)=>({PortMapping:{Port:s.port,Protocol:s.protocol}}))}}}}clear(){this.meshes.clear(),this.virtualNodes.clear(),this.virtualRouters.clear(),this.virtualGateways.clear(),this.meshCounter=0,this.nodeCounter=0,this.routerCounter=0,this.gatewayCounter=0}}var IE=new pm;class gm{layers=new Map;versions=new Map;permissions=new Map;layerCounter=0;versionCounter=0;permissionCounter=0;createLayer(n){let i=`layer-${Date.now()}-${this.layerCounter++}`,s=1,o={id:i,layerArn:`arn:aws:lambda:us-east-1:123456789012:layer:${n.layerName}:1`,version:1,...n};return this.layers.set(i,o),o}createNodeDependenciesLayer(n){return this.createLayer({layerName:n.layerName,description:"Node.js dependencies layer",compatibleRuntimes:[`nodejs${n.nodeVersion}`],content:{type:"s3",s3Bucket:n.s3Bucket,s3Key:n.s3Key},size:5242880})}createUtilitiesLayer(n){return this.createLayer({layerName:n.layerName,description:"Shared utilities and helpers",compatibleRuntimes:n.runtimes,content:{type:"s3",s3Bucket:n.s3Bucket,s3Key:n.s3Key},size:1048576})}publishVersion(n){let i=this.layers.get(n);if(!i)throw Error(`Layer not found: ${n}`);let s=`version-${Date.now()}-${this.versionCounter++}`,o=i.version+1,c={id:s,layerName:i.layerName,version:o,createdAt:new Date,compatibleRuntimes:i.compatibleRuntimes,size:i.size,codeHash:this.generateHash()};return this.versions.set(s,c),i.version=o,i.layerArn=`arn:aws:lambda:us-east-1:123456789012:layer:${i.layerName}:${o}`,c}addPermission(n){let i=`permission-${Date.now()}-${this.permissionCounter++}`,s={id:i,layerName:n.layerName,version:n.version,principal:n.principal,action:"lambda:GetLayerVersion",organizationId:n.organizationId};return this.permissions.set(i,s),s}generateHash(){return Math.random().toString(36).substring(2,15)}getLayer(n){return this.layers.get(n)}listLayers(){return Array.from(this.layers.values())}getLayerVersions(n){return Array.from(this.versions.values()).filter((i)=>i.layerName===n)}generateLayerCF(n){return{Type:"AWS::Lambda::LayerVersion",Properties:{LayerName:n.layerName,Description:n.description,Content:n.content.type==="s3"?{S3Bucket:n.content.s3Bucket,S3Key:n.content.s3Key,...n.content.s3ObjectVersion&&{S3ObjectVersion:n.content.s3ObjectVersion}}:{ZipFile:n.content.zipFile},CompatibleRuntimes:n.compatibleRuntimes,...n.licenseInfo&&{LicenseInfo:n.licenseInfo}}}}generateLayerPermissionCF(n){return{Type:"AWS::Lambda::LayerVersionPermission",Properties:{LayerVersionArn:`arn:aws:lambda:us-east-1:123456789012:layer:${n.layerName}:${n.version}`,Action:n.action,Principal:n.principal,...n.organizationId&&{OrganizationId:n.organizationId}}}}clear(){this.layers.clear(),this.versions.clear(),this.permissions.clear(),this.layerCounter=0,this.versionCounter=0,this.permissionCounter=0}}var SE=new gm;class mm{versions=new Map;aliases=new Map;deployments=new Map;versionCounter=0;aliasCounter=0;deploymentCounter=0;publishVersion(n){let i=`version-${Date.now()}-${this.versionCounter++}`,s=this.getNextVersionNumber(n.functionName),o={id:i,functionName:n.functionName,version:s.toString(),functionArn:`arn:aws:lambda:us-east-1:123456789012:function:${n.functionName}:${s}`,codeHash:this.generateHash(),description:n.description,runtime:n.runtime,memorySize:n.memorySize,timeout:n.timeout,publishedAt:new Date};return this.versions.set(i,o),o}getNextVersionNumber(n){let i=Array.from(this.versions.values()).filter((s)=>s.functionName===n).map((s)=>parseInt(s.version));return i.length>0?Math.max(...i)+1:1}createAlias(n){let i=`alias-${Date.now()}-${this.aliasCounter++}`,s={id:i,aliasArn:`arn:aws:lambda:us-east-1:123456789012:function:${n.functionName}:${n.aliasName}`,revisionId:this.generateHash(),...n};return this.aliases.set(i,s),s}createProductionAlias(n){return this.createAlias({functionName:n.functionName,aliasName:"production",functionVersion:n.version,description:"Production alias"})}createStagingAlias(n){return this.createAlias({functionName:n.functionName,aliasName:"staging",functionVersion:n.version,description:"Staging alias"})}updateAlias(n,i){let s=this.aliases.get(n);if(!s)throw Error(`Alias not found: ${n}`);return s.functionVersion=i,s.revisionId=this.generateHash(),s}configureWeightedRouting(n,i){let s=this.aliases.get(n);if(!s)throw Error(`Alias not found: ${n}`);return s.routingConfig={additionalVersionWeights:i},s}createCanaryDeployment(n){let i=`deployment-${Date.now()}-${this.deploymentCounter++}`,s=Array.from(this.aliases.values()).find((c)=>c.functionName===n.functionName&&c.aliasName===n.aliasName);if(!s)s=this.createAlias({functionName:n.functionName,aliasName:n.aliasName,functionVersion:n.fromVersion});this.configureWeightedRouting(s.id,{[n.toVersion]:n.canaryWeight});let o={id:i,functionName:n.functionName,fromVersion:n.fromVersion,toVersion:n.toVersion,aliasName:n.aliasName,strategy:"canary",status:"in_progress",startedAt:new Date};return this.deployments.set(i,o),o}completeDeployment(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);let s=Array.from(this.aliases.values()).find((o)=>o.functionName===i.functionName&&o.aliasName===i.aliasName);if(s)s.functionVersion=i.toVersion,s.routingConfig=void 0;return i.status="completed",i.completedAt=new Date,i}rollbackDeployment(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);let s=Array.from(this.aliases.values()).find((o)=>o.functionName===i.functionName&&o.aliasName===i.aliasName);if(s)s.functionVersion=i.fromVersion,s.routingConfig=void 0;return i.status="failed",i.completedAt=new Date,i}generateHash(){return Math.random().toString(36).substring(2,15)}getVersion(n){return this.versions.get(n)}listVersions(n){let i=Array.from(this.versions.values());return n?i.filter((s)=>s.functionName===n):i}getAlias(n){return this.aliases.get(n)}listAliases(n){let i=Array.from(this.aliases.values());return n?i.filter((s)=>s.functionName===n):i}generateVersionCF(n){return{Type:"AWS::Lambda::Version",Properties:{FunctionName:n.functionName,Description:n.description}}}generateAliasCF(n){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:n.functionName,Name:n.aliasName,FunctionVersion:n.functionVersion,Description:n.description,...n.routingConfig&&{RoutingConfig:{AdditionalVersionWeights:Object.entries(n.routingConfig.additionalVersionWeights||{}).map(([i,s])=>({FunctionVersion:i,FunctionWeight:s}))}}}}}clear(){this.versions.clear(),this.aliases.clear(),this.deployments.clear(),this.versionCounter=0,this.aliasCounter=0,this.deploymentCounter=0}}var CE=new mm;class hm{configs=new Map;provisionedConfigs=new Map;schedules=new Map;autoScalingConfigs=new Map;configCounter=0;provisionedCounter=0;scheduleCounter=0;autoScalingCounter=0;setReservedConcurrency(n){let i=`concurrency-${Date.now()}-${this.configCounter++}`,s={id:i,functionName:n.functionName,reservedConcurrency:n.reservedConcurrency};return this.configs.set(i,s),s}setProvisionedConcurrency(n){let i=`provisioned-${Date.now()}-${this.provisionedCounter++}`,s={id:i,functionName:n.functionName,qualifier:n.qualifier,provisionedConcurrentExecutions:n.provisionedConcurrentExecutions,status:"pending",lastModified:new Date};return this.provisionedConfigs.set(i,s),setTimeout(()=>{s.status="ready",s.allocatedConcurrency=n.provisionedConcurrentExecutions,s.availableConcurrency=n.provisionedConcurrentExecutions},100),s}configureWarmPool(n){return this.setProvisionedConcurrency({functionName:n.functionName,qualifier:n.alias,provisionedConcurrentExecutions:n.minInstances})}createSchedule(n){let i=`schedule-${Date.now()}-${this.scheduleCounter++}`,s={id:i,...n};return this.schedules.set(i,s),s}createBusinessHoursSchedule(n){return this.createSchedule({name:`${n.functionName}-business-hours`,functionName:n.functionName,qualifier:n.qualifier,schedule:[{name:"business-hours",cronExpression:"0 8 * * MON-FRI",targetConcurrency:n.businessHoursConcurrency},{name:"off-hours",cronExpression:"0 18 * * MON-FRI",targetConcurrency:n.offHoursConcurrency},{name:"weekend",cronExpression:"0 0 * * SAT",targetConcurrency:n.offHoursConcurrency}]})}configureAutoScaling(n){let i=`autoscaling-${Date.now()}-${this.autoScalingCounter++}`,s={id:i,...n};return this.autoScalingConfigs.set(i,s),s}configurePredictiveScaling(n){return this.configureAutoScaling({functionName:n.functionName,qualifier:n.qualifier,minCapacity:n.baselineCapacity,maxCapacity:n.peakCapacity,targetUtilization:0.7,scaleInCooldown:300,scaleOutCooldown:60})}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getProvisionedConfig(n){return this.provisionedConfigs.get(n)}listProvisionedConfigs(){return Array.from(this.provisionedConfigs.values())}generateReservedConcurrencyCF(n){return{Type:"AWS::Lambda::Function",Properties:{FunctionName:n.functionName,ReservedConcurrentExecutions:n.reservedConcurrency}}}generateProvisionedConcurrencyCF(n){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:n.functionName,Name:n.qualifier,ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:n.provisionedConcurrentExecutions}}}}generateAutoScalingTargetCF(n){return{Type:"AWS::ApplicationAutoScaling::ScalableTarget",Properties:{ServiceNamespace:"lambda",ResourceId:`function:${n.functionName}:${n.qualifier}`,ScalableDimension:"lambda:function:ProvisionedConcurrentExecutions",MinCapacity:n.minCapacity,MaxCapacity:n.maxCapacity}}}generateAutoScalingPolicyCF(n){return{Type:"AWS::ApplicationAutoScaling::ScalingPolicy",Properties:{PolicyName:`${n.functionName}-autoscaling`,PolicyType:"TargetTrackingScaling",ScalingTargetId:{Ref:`${n.functionName}AutoScalingTarget`},TargetTrackingScalingPolicyConfiguration:{TargetValue:n.targetUtilization*100,PredefinedMetricSpecification:{PredefinedMetricType:"LambdaProvisionedConcurrencyUtilization"},ScaleInCooldown:n.scaleInCooldown||300,ScaleOutCooldown:n.scaleOutCooldown||60}}}}clear(){this.configs.clear(),this.provisionedConfigs.clear(),this.schedules.clear(),this.autoScalingConfigs.clear(),this.configCounter=0,this.provisionedCounter=0,this.scheduleCounter=0,this.autoScalingCounter=0}}var EE=new hm;class fm{destinations=new Map;records=new Map;eventBridgeDestinations=new Map;destinationCounter=0;recordCounter=0;eventBridgeCounter=0;configureDestinations(n){let i=`destination-${Date.now()}-${this.destinationCounter++}`,s={id:i,...n};return this.destinations.set(i,s),s}configureSQSDestination(n){let i={type:"sqs",arn:n.queueArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureSNSDestination(n){let i={type:"sns",arn:n.topicArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureEventBridgeDestination(n){let i={type:"eventbridge",arn:n.eventBusArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureLambdaDestination(n){let i={type:"lambda",arn:n.destinationFunctionArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureDLQWithNotification(n){return this.configureDestinations({functionName:n.functionName,failureDestination:{type:"sqs",arn:n.dlqArn},maxEventAge:3600,maxRetries:0})}createEventBridgeIntegration(n){let i=`eventbridge-${Date.now()}-${this.eventBridgeCounter++}`,s={id:i,functionName:n.functionName,eventBusArn:n.eventBusArn,detailType:n.detailType||"Lambda Function Invocation Result",source:n.source||`lambda.${n.functionName}`};return this.eventBridgeDestinations.set(i,s),s}sendToDestination(n){let i=Array.from(this.destinations.values()).find((l)=>l.functionName===n.functionName);if(!i)return null;let s=n.status==="success"?i.successDestination:i.failureDestination;if(!s)return null;let o=`record-${Date.now()}-${this.recordCounter++}`,c={id:o,timestamp:new Date,functionName:n.functionName,requestId:n.requestId,status:n.status,destinationType:s.type,destinationArn:s.arn,payload:n.payload,error:n.error};return this.records.set(o,c),c}getDestination(n){return this.destinations.get(n)}listDestinations(n){let i=Array.from(this.destinations.values());return n?i.filter((s)=>s.functionName===n):i}getDestinationRecords(n){let i=Array.from(this.records.values());return n?i.filter((s)=>s.functionName===n):i}generateEventInvokeConfigCF(n){return{Type:"AWS::Lambda::EventInvokeConfig",Properties:{FunctionName:n.functionName,Qualifier:n.qualifier||"$LATEST",MaximumEventAgeInSeconds:n.maxEventAge||21600,MaximumRetryAttempts:n.maxRetries??2,...n.successDestination&&{DestinationConfig:{OnSuccess:{Destination:n.successDestination.arn}}},...n.failureDestination&&{DestinationConfig:{OnFailure:{Destination:n.failureDestination.arn}}}}}}generateEventBridgeRuleCF(n){return{Type:"AWS::Events::Rule",Properties:{EventBusName:n.eventBusArn.split("/").pop(),EventPattern:{source:[n.source],"detail-type":[n.detailType]},State:"ENABLED",Targets:[{Arn:`arn:aws:lambda:us-east-1:123456789012:function:${n.functionName}`,Id:n.id}]}}}clear(){this.destinations.clear(),this.records.clear(),this.eventBridgeDestinations.clear(),this.destinationCounter=0,this.recordCounter=0,this.eventBridgeCounter=0}}var bE=new fm;class Am{vpcConfigs=new Map;endpoints=new Map;networkInterfaces=new Map;connectivity=new Map;configCounter=0;endpointCounter=0;eniCounter=0;connectivityCounter=0;configureVPC(n){let i=`vpc-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};this.vpcConfigs.set(i,s);for(let o of n.subnetIds)this.createNetworkInterface({functionName:n.functionName,subnetId:o});return s}configurePrivateVPC(n){return this.configureVPC({functionName:n.functionName,vpcId:n.vpcId,subnetIds:n.privateSubnetIds,securityGroupIds:[n.securityGroupId],ipv6Allowed:!1})}configureMultiAZVPC(n){if(n.subnetIds.length<2)throw Error("Multi-AZ configuration requires at least 2 subnets");return this.configureVPC({functionName:n.functionName,vpcId:n.vpcId,subnetIds:n.subnetIds,securityGroupIds:n.securityGroupIds})}createVPCEndpoint(n){let i=`endpoint-${Date.now()}-${this.endpointCounter++}`,s={id:i,...n};return this.endpoints.set(i,s),s}createS3Endpoint(n){return this.createVPCEndpoint({vpcId:n.vpcId,serviceName:"com.amazonaws.us-east-1.s3",endpointType:"Gateway",privateDnsEnabled:!1})}createDynamoDBEndpoint(n){return this.createVPCEndpoint({vpcId:n.vpcId,serviceName:"com.amazonaws.us-east-1.dynamodb",endpointType:"Gateway",privateDnsEnabled:!1})}createSecretsManagerEndpoint(n){return this.createVPCEndpoint({vpcId:n.vpcId,serviceName:"com.amazonaws.us-east-1.secretsmanager",endpointType:"Interface",subnetIds:n.subnetIds,securityGroupIds:n.securityGroupIds,privateDnsEnabled:!0})}createNetworkInterface(n){let i=`eni-${Date.now()}-${this.eniCounter++}`,s={id:i,functionName:n.functionName,networkInterfaceId:`eni-${Math.random().toString(36).substring(2,15)}`,subnetId:n.subnetId,privateIpAddress:`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`,status:"creating",attachedAt:new Date};return this.networkInterfaces.set(i,s),setTimeout(()=>{s.status="available"},100),s}analyzeConnectivity(n){let i=`connectivity-${Date.now()}-${this.connectivityCounter++}`,s=Array.from(this.vpcConfigs.values()).find((y)=>y.functionName===n.functionName),o=Array.from(this.endpoints.values()).filter((y)=>y.vpcId===s?.vpcId).map((y)=>y.serviceName),c=[],l=n.hasNATGateway??!1,u=n.hasInternetGateway??!1;if(!l&&!u)c.push("Add NAT Gateway for internet access");if(!o.includes("com.amazonaws.us-east-1.s3"))c.push("Add S3 VPC endpoint to reduce NAT costs");if(!o.includes("com.amazonaws.us-east-1.dynamodb"))c.push("Add DynamoDB VPC endpoint for private access");let h={id:i,functionName:n.functionName,hasInternetAccess:l||u,hasNATGateway:l,hasVPCEndpoints:o.length>0,endpoints:o,recommendations:c};return this.connectivity.set(i,h),h}getVPCConfig(n){return this.vpcConfigs.get(n)}listVPCConfigs(n){let i=Array.from(this.vpcConfigs.values());return n?i.filter((s)=>s.functionName===n):i}getNetworkInterfaces(n){return Array.from(this.networkInterfaces.values()).filter((i)=>i.functionName===n)}listVPCEndpoints(n){let i=Array.from(this.endpoints.values());return n?i.filter((s)=>s.vpcId===n):i}generateVPCConfigCF(n){return{VpcConfig:{SubnetIds:n.subnetIds,SecurityGroupIds:n.securityGroupIds,...n.ipv6Allowed&&{Ipv6AllowedForDualStack:!0}}}}generateVPCEndpointCF(n){return{Type:"AWS::EC2::VPCEndpoint",Properties:{VpcId:n.vpcId,ServiceName:n.serviceName,VpcEndpointType:n.endpointType,...n.subnetIds&&{SubnetIds:n.subnetIds},...n.securityGroupIds&&{SecurityGroupIds:n.securityGroupIds},...n.privateDnsEnabled!==void 0&&{PrivateDnsEnabled:n.privateDnsEnabled}}}}generateSecurityGroupCF(n){return{Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:n.groupName,GroupDescription:`Security group for Lambda ${n.groupName}`,VpcId:n.vpcId,...n.ingressRules&&{SecurityGroupIngress:n.ingressRules.map((i)=>({IpProtocol:i.protocol,FromPort:i.fromPort,ToPort:i.toPort,...i.cidrIp&&{CidrIp:i.cidrIp},...i.sourceSecurityGroupId&&{SourceSecurityGroupId:i.sourceSecurityGroupId}}))},...n.egressRules&&{SecurityGroupEgress:n.egressRules.map((i)=>({IpProtocol:i.protocol,FromPort:i.fromPort,ToPort:i.toPort,CidrIp:i.cidrIp||"0.0.0.0/0"}))}}}}clear(){this.vpcConfigs.clear(),this.endpoints.clear(),this.networkInterfaces.clear(),this.connectivity.clear(),this.configCounter=0,this.endpointCounter=0,this.eniCounter=0,this.connectivityCounter=0}}var vE=new Am;class ym{dlqConfigs=new Map;messages=new Map;alarms=new Map;reprocessing=new Map;configCounter=0;messageCounter=0;alarmCounter=0;reprocessCounter=0;configureDLQ(n){let i=`dlq-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.dlqConfigs.set(i,s),s}configureSQSDLQ(n){return this.configureDLQ({functionName:n.functionName,targetArn:n.queueArn,targetType:"sqs",maxReceiveCount:n.maxReceiveCount||3,retentionPeriod:n.retentionPeriod||1209600})}configureSNSDLQ(n){return this.configureDLQ({functionName:n.functionName,targetArn:n.topicArn,targetType:"sns"})}configureDLQWithAlarm(n){let i=this.configureSQSDLQ({functionName:n.functionName,queueArn:n.queueArn});return this.createDLQAlarm({dlqConfigId:i.id,alarmName:`${n.functionName}-dlq-alarm`,threshold:n.alarmThreshold,evaluationPeriods:1,notificationTopicArn:n.notificationTopicArn,enabled:!0}),i}sendToDLQ(n){let i=`message-${Date.now()}-${this.messageCounter++}`,s={id:i,timestamp:new Date,...n};return this.messages.set(i,s),s}createDLQAlarm(n){let i=`alarm-${Date.now()}-${this.alarmCounter++}`,s={id:i,...n};return this.alarms.set(i,s),s}createAgeAlarm(n){let i=this.dlqConfigs.get(n.dlqConfigId);if(!i)throw Error(`DLQ config not found: ${n.dlqConfigId}`);return this.createDLQAlarm({dlqConfigId:n.dlqConfigId,alarmName:`${i.functionName}-dlq-age-alarm`,threshold:n.maxAgeSeconds,evaluationPeriods:1,notificationTopicArn:n.notificationTopicArn,enabled:!0})}async reprocessMessage(n){let i=this.messages.get(n);if(!i)throw Error(`Message not found: ${n}`);let s=Array.from(this.dlqConfigs.values()).find((l)=>l.functionName===i.functionName);if(!s)throw Error(`DLQ config not found for function: ${i.functionName}`);let o=`reprocess-${Date.now()}-${this.reprocessCounter++}`,c={id:o,dlqConfigId:s.id,messageId:n,status:"pending",startedAt:new Date};return this.reprocessing.set(o,c),setTimeout(()=>{c.status="processing",setTimeout(()=>{let l=Math.random()>0.3;if(c.status=l?"success":"failed",c.completedAt=new Date,!l)c.error="Reprocessing failed - same error occurred";else this.messages.delete(n)},100)},50),c}async batchReprocess(n){let i=this.dlqConfigs.get(n.dlqConfigId);if(!i)throw Error(`DLQ config not found: ${n.dlqConfigId}`);let s=Array.from(this.messages.values()).filter((o)=>o.functionName===i.functionName).slice(0,n.maxMessages||10).map((o)=>this.reprocessMessage(o.id));return Promise.all(s)}getDLQStats(n){let i=this.dlqConfigs.get(n);if(!i)throw Error(`DLQ config not found: ${n}`);let s=Array.from(this.messages.values()).filter((u)=>u.functionName===i.functionName),o={},c=0;for(let u of s)o[u.errorType]=(o[u.errorType]||0)+1,c+=u.attemptCount;let l=s.map((u)=>u.timestamp);return{totalMessages:s.length,oldestMessage:l.length>0?new Date(Math.min(...l.map((u)=>u.getTime()))):void 0,newestMessage:l.length>0?new Date(Math.max(...l.map((u)=>u.getTime()))):void 0,averageAttempts:s.length>0?c/s.length:0,errorTypes:o}}getDLQConfig(n){return this.dlqConfigs.get(n)}listDLQConfigs(){return Array.from(this.dlqConfigs.values())}getDLQMessages(n){let i=this.dlqConfigs.get(n);if(!i)return[];return Array.from(this.messages.values()).filter((s)=>s.functionName===i.functionName)}generateDLQCF(n){return{DeadLetterConfig:{TargetArn:n.targetArn}}}generateSQSDLQCF(n){return{Type:"AWS::SQS::Queue",Properties:{QueueName:`${n.functionName}-dlq`,MessageRetentionPeriod:n.retentionPeriod||1209600,...n.maxReceiveCount&&{RedrivePolicy:{deadLetterTargetArn:n.targetArn,maxReceiveCount:n.maxReceiveCount}}}}}generateDLQAlarmCF(n){let i=this.dlqConfigs.get(n.dlqConfigId);if(!i)throw Error(`DLQ config not found: ${n.dlqConfigId}`);return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:n.alarmName,AlarmDescription:`DLQ alarm for ${i.functionName}`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Sum",Period:300,EvaluationPeriods:n.evaluationPeriods,Threshold:n.threshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:i.targetArn.split(":").pop()}],...n.notificationTopicArn&&{AlarmActions:[n.notificationTopicArn]}}}}clear(){this.dlqConfigs.clear(),this.messages.clear(),this.alarms.clear(),this.reprocessing.clear(),this.configCounter=0,this.messageCounter=0,this.alarmCounter=0,this.reprocessCounter=0}}var TE=new ym;class Im{policies=new Map;healthChecks=new Map;trafficPolicies=new Map;policyCounter=0;healthCheckCounter=0;trafficPolicyCounter=0;createWeightedPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"weighted",...n};return this.policies.set(i,s),s}createLatencyPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"latency",...n};return this.policies.set(i,s),s}createFailoverPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"failover",...n};return this.policies.set(i,s),s}createGeolocationPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"geolocation",...n};return this.policies.set(i,s),s}createGeoproximityPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"geoproximity",...n};return this.policies.set(i,s),s}createHTTPHealthCheck(n){let i=`health-check-${Date.now()}-${this.healthCheckCounter++}`,s={id:i,type:n.port===443?"https":"http",requestInterval:n.requestInterval||30,failureThreshold:n.failureThreshold||3,healthCheckStatus:"Unknown",port:n.port||(n.port===443?443:80),...n};return this.healthChecks.set(i,s),setTimeout(()=>{s.healthCheckStatus=Math.random()>0.2?"Healthy":"Unhealthy"},100),s}createTCPHealthCheck(n){let i=`health-check-${Date.now()}-${this.healthCheckCounter++}`,s={id:i,type:"tcp",fullyQualifiedDomainName:n.ipAddress,requestInterval:n.requestInterval||30,failureThreshold:n.failureThreshold||3,healthCheckStatus:"Unknown",...n};return this.healthChecks.set(i,s),setTimeout(()=>{s.healthCheckStatus=Math.random()>0.1?"Healthy":"Unhealthy"},100),s}createCalculatedHealthCheck(n){let i=`health-check-${Date.now()}-${this.healthCheckCounter++}`,s={id:i,type:"calculated",requestInterval:30,failureThreshold:0,healthCheckStatus:"Unknown",...n};return this.healthChecks.set(i,s),setTimeout(()=>{let o=n.childHealthChecks.filter((c)=>this.healthChecks.get(c)?.healthCheckStatus==="Healthy").length;s.healthCheckStatus=o>=n.healthThreshold?"Healthy":"Unhealthy"},150),s}createTrafficPolicy(n){let i=`traffic-policy-${Date.now()}-${this.trafficPolicyCounter++}`,s={id:i,version:1,...n};return this.trafficPolicies.set(i,s),s}createFailoverTrafficPolicy(n){return this.createTrafficPolicy({name:n.name,document:{recordType:n.recordType||"A",startRule:"failover",endpoints:{primary:{type:"value",value:n.primaryEndpoint},secondary:{type:"value",value:n.secondaryEndpoint}},rules:{failover:{ruleType:"failover",primary:"primary",secondary:"secondary"}}}})}createGeoproximityTrafficPolicy(n){let i={},s=[];return n.locations.forEach((o,c)=>{let l=`endpoint${c}`;i[l]={type:"value",value:o.endpoint},s.push({endpointReference:l,region:o.region,latitude:o.latitude,longitude:o.longitude,bias:o.bias})}),this.createTrafficPolicy({name:n.name,document:{recordType:"A",startRule:"geoproximity",endpoints:i,rules:{geoproximity:{ruleType:"geoproximity",locations:s}}}})}getPolicy(n){return this.policies.get(n)}listPolicies(){return Array.from(this.policies.values())}getHealthCheck(n){return this.healthChecks.get(n)}listHealthChecks(){return Array.from(this.healthChecks.values())}getHealthCheckStatus(n){return this.healthChecks.get(n)?.healthCheckStatus||"Unknown"}generateHealthCheckCF(n){let i={Type:"AWS::Route53::HealthCheck",Properties:{HealthCheckConfig:{Type:n.type.toUpperCase(),RequestInterval:n.requestInterval,FailureThreshold:n.failureThreshold,...n.measureLatency&&{MeasureLatency:!0}},HealthCheckTags:[{Key:"Name",Value:n.name}]}};if(n.type==="calculated"){let s=n;i.Properties.HealthCheckConfig.ChildHealthChecks=s.childHealthChecks,i.Properties.HealthCheckConfig.HealthThreshold=s.healthThreshold}else{if(n.ipAddress)i.Properties.HealthCheckConfig.IPAddress=n.ipAddress;if(n.fullyQualifiedDomainName)i.Properties.HealthCheckConfig.FullyQualifiedDomainName=n.fullyQualifiedDomainName;if(n.port)i.Properties.HealthCheckConfig.Port=n.port;if(n.resourcePath)i.Properties.HealthCheckConfig.ResourcePath=n.resourcePath;if(n.enableSNI)i.Properties.HealthCheckConfig.EnableSNI=!0}return i}generateWeightedRecordSetCF(n){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:n.name,Type:n.type,TTL:n.ttl,ResourceRecords:n.resourceRecords,Weight:n.weight,SetIdentifier:n.setIdentifier,...n.healthCheckId&&{HealthCheckId:n.healthCheckId}}}}generateFailoverRecordSetCF(n){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:n.name,Type:n.type,TTL:n.ttl,ResourceRecords:n.resourceRecords,Failover:n.failover,SetIdentifier:n.setIdentifier,...n.healthCheckId&&{HealthCheckId:n.healthCheckId}}}}clear(){this.policies.clear(),this.healthChecks.clear(),this.trafficPolicies.clear(),this.policyCounter=0,this.healthCheckCounter=0,this.trafficPolicyCounter=0}}var wE=new Im;class Sm{configs=new Map;ksks=new Map;validations=new Map;configCounter=0;kskCounter=0;validationCounter=0;enableDNSSEC(n){let i=`dnssec-${Date.now()}-${this.configCounter++}`,s={id:i,hostedZoneId:n.hostedZoneId,status:"SIGNING",signingStatus:"Initializing DNSSEC signing"};if(this.configs.set(i,s),n.kmsKeyArn)this.createKSK({name:`ksk-${n.hostedZoneId}`,hostedZoneId:n.hostedZoneId,kmsKeyArn:n.kmsKeyArn});return setTimeout(()=>{s.status="SIGNED",s.signingStatus="DNSSEC signing complete"},100),s}disableDNSSEC(n){let i=this.configs.get(n);if(!i)throw Error(`DNSSEC config not found: ${n}`);return i.status="DELETING",i.signingStatus="Removing DNSSEC signing",setTimeout(()=>{i.status="NOT_SIGNING",i.signingStatus="DNSSEC signing removed"},100),i}createKSK(n){let i=`ksk-${Date.now()}-${this.kskCounter++}`,s={id:i,status:"ACTIVE",flag:257,keyManagementServiceArn:n.kmsKeyArn,digestAlgorithm:2,keyTag:Math.floor(Math.random()*65535),publicKey:this.generatePublicKey(),...n};s.dnskeyRecord=`${s.flag} 3 8 ${s.publicKey}`;let o=this.generateDigest(s.dnskeyRecord);return s.digestValue=o,s.dsRecord=`${s.keyTag} 8 ${s.digestAlgorithm} ${o}`,this.ksks.set(i,s),s}deactivateKSK(n){let i=this.ksks.get(n);if(!i)throw Error(`KSK not found: ${n}`);return i.status="INACTIVE",i}validateDNSSEC(n){let i=`validation-${Date.now()}-${this.validationCounter++}`,s=n.checkDNSKEY!==!1?Math.random()>0.1:!1,o=n.checkRRSIG!==!1?Math.random()>0.1:!1,c=s&&o,l=[];if(!s)l.push("DNSKEY record not found");if(!o)l.push("RRSIG record not found");let u;if(!s&&!o)u="INSECURE";else if(s&&o&&c)u="VALID";else if(s||o)u="BOGUS",l.push("Invalid signature or incomplete DNSSEC chain");else u="INVALID";let h={id:i,domain:n.domain,validationStatus:u,dnskeyPresent:s,rrsigPresent:o,validSignature:c,errors:l};return this.validations.set(i,h),h}getDNSSECConfig(n){return this.configs.get(n)}listDNSSECConfigs(){return Array.from(this.configs.values())}getKSK(n){return this.ksks.get(n)}listKSKs(n){let i=Array.from(this.ksks.values());return n?i.filter((s)=>s.hostedZoneId===n):i}getDSRecord(n){let i=this.ksks.get(n);if(!i||!i.dsRecord)throw Error("DS record not available");return i.dsRecord}generatePublicKey(){let n="";for(let i=0;i<256;i++)n+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(Math.floor(Math.random()*64));return n}generateDigest(n){let i="";for(let s=0;s<64;s++)i+="0123456789ABCDEF".charAt(Math.floor(Math.random()*16));return i}generateDNSSECCF(n){return{Type:"AWS::Route53::DNSSEC",Properties:{HostedZoneId:n.hostedZoneId}}}generateKSKCF(n){return{Type:"AWS::Route53::KeySigningKey",Properties:{Name:n.name,HostedZoneId:n.hostedZoneId,KeyManagementServiceArn:n.keyManagementServiceArn,Status:n.status}}}clear(){this.configs.clear(),this.ksks.clear(),this.validations.clear(),this.configCounter=0,this.kskCounter=0,this.validationCounter=0}}var RE=new Sm;class Cm{endpoints=new Map;rules=new Map;firewalls=new Map;ruleGroups=new Map;domainLists=new Map;endpointCounter=0;ruleCounter=0;firewallCounter=0;ruleGroupCounter=0;domainListCounter=0;createResolverEndpoint(n){let i=`endpoint-${Date.now()}-${this.endpointCounter++}`,s={id:i,status:"CREATING",...n};return this.endpoints.set(i,s),setTimeout(()=>{s.status="OPERATIONAL",s.ipAddresses.forEach((o)=>{if(!o.ip)o.ip=`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`})},100),s}createInboundEndpoint(n){return this.createResolverEndpoint({name:n.name,direction:"INBOUND",ipAddresses:n.subnetIds.map((i)=>({subnetId:i})),securityGroupIds:n.securityGroupIds})}createOutboundEndpoint(n){return this.createResolverEndpoint({name:n.name,direction:"OUTBOUND",ipAddresses:n.subnetIds.map((i)=>({subnetId:i})),securityGroupIds:n.securityGroupIds})}createResolverRule(n){let i=`rule-${Date.now()}-${this.ruleCounter++}`,s={id:i,status:"CREATING",...n};return this.rules.set(i,s),setTimeout(()=>{s.status="COMPLETE"},100),s}createForwardRule(n){return this.createResolverRule({name:n.name,ruleType:"FORWARD",domainName:n.domainName,targetIps:n.targetIps,resolverEndpointId:n.resolverEndpointId})}createSystemRule(n){return this.createResolverRule({name:n.name,ruleType:"SYSTEM",domainName:n.domainName})}createFirewallDomainList(n){let i=`domain-list-${Date.now()}-${this.domainListCounter++}`,s={id:i,status:"CREATING",...n};return this.domainLists.set(i,s),setTimeout(()=>{s.status="COMPLETE"},100),s}createFirewallRuleGroup(n){let i=`rule-group-${Date.now()}-${this.ruleGroupCounter++}`,s={id:i,name:n.name,rules:n.rules.map((o,c)=>({id:`rule-${i}-${c}`,...o})),shareStatus:"NOT_SHARED"};return this.ruleGroups.set(i,s),s}createBlockRule(n){return this.createFirewallRuleGroup({name:n.name,rules:[{name:n.name,priority:n.priority,action:"BLOCK",blockResponse:n.blockResponse||"NODATA",blockOverrideDomain:n.blockOverrideDomain,firewallDomainListId:n.domainListId}]})}createAllowRule(n){return this.createFirewallRuleGroup({name:n.name,rules:[{name:n.name,priority:n.priority,action:"ALLOW",firewallDomainListId:n.domainListId}]})}createDNSFirewall(n){let i=`firewall-${Date.now()}-${this.firewallCounter++}`,s={id:i,name:n.name,firewallRuleGroupAssociations:n.ruleGroupAssociations.map((o,c)=>({id:`assoc-${i}-${c}`,vpcId:n.vpcId,firewallRuleGroupId:o.firewallRuleGroupId,priority:o.priority,mutationProtection:o.mutationProtection||"DISABLED",status:"COMPLETE"}))};return this.firewalls.set(i,s),s}createMalwareProtectionFirewall(n){let i=this.createFirewallDomainList({name:`${n.name}-malware-domains`,domains:n.maliciousDomains}),s=this.createBlockRule({name:`${n.name}-block-malware`,priority:100,domainListId:i.id,blockResponse:"NXDOMAIN"});return this.createDNSFirewall({name:n.name,vpcId:n.vpcId,ruleGroupAssociations:[{firewallRuleGroupId:s.id,priority:100,mutationProtection:"ENABLED"}]})}getEndpoint(n){return this.endpoints.get(n)}listEndpoints(n){let i=Array.from(this.endpoints.values());return n?i.filter((s)=>s.direction===n):i}getRule(n){return this.rules.get(n)}listRules(){return Array.from(this.rules.values())}getFirewall(n){return this.firewalls.get(n)}listFirewalls(){return Array.from(this.firewalls.values())}generateResolverEndpointCF(n){return{Type:"AWS::Route53Resolver::ResolverEndpoint",Properties:{Name:n.name,Direction:n.direction,IpAddresses:n.ipAddresses.map((i)=>({SubnetId:i.subnetId,...i.ip&&{Ip:i.ip}})),SecurityGroupIds:n.securityGroupIds}}}generateResolverRuleCF(n){return{Type:"AWS::Route53Resolver::ResolverRule",Properties:{Name:n.name,RuleType:n.ruleType,DomainName:n.domainName,...n.targetIps&&{TargetIps:n.targetIps.map((i)=>({Ip:i.ip,Port:i.port||53}))},...n.resolverEndpointId&&{ResolverEndpointId:n.resolverEndpointId}}}}generateFirewallRuleGroupCF(n){return{Type:"AWS::Route53Resolver::FirewallRuleGroup",Properties:{Name:n.name,FirewallRules:n.rules.map((i)=>({Name:i.name,Priority:i.priority,Action:i.action,FirewallDomainListId:i.firewallDomainListId,...i.blockResponse&&{BlockResponse:i.blockResponse},...i.blockOverrideDomain&&{BlockOverrideDomain:i.blockOverrideDomain},...i.blockOverrideTTL&&{BlockOverrideTtl:i.blockOverrideTTL}}))}}}clear(){this.endpoints.clear(),this.rules.clear(),this.firewalls.clear(),this.ruleGroups.clear(),this.domainLists.clear(),this.endpointCounter=0,this.ruleCounter=0,this.firewallCounter=0,this.ruleGroupCounter=0,this.domainListCounter=0}}var DE=new Cm;class Em{bounces=new Map;complaints=new Map;handlers=new Map;suppressionList=new Map;metrics=new Map;bounceCounter=0;complaintCounter=0;handlerCounter=0;suppressionCounter=0;metricsCounter=0;recordBounce(n){let i=`bounce-${Date.now()}-${this.bounceCounter++}`,s={id:i,...n};if(this.bounces.set(i,s),n.bounceType==="Permanent")this.addToSuppressionList({emailAddress:n.recipient,reason:"BOUNCE"});return s}recordComplaint(n){let i=`complaint-${Date.now()}-${this.complaintCounter++}`,s={id:i,...n};this.complaints.set(i,s);for(let o of n.recipients)this.addToSuppressionList({emailAddress:o,reason:"COMPLAINT"});return s}createBounceHandler(n){let i=`handler-${Date.now()}-${this.handlerCounter++}`,s={id:i,...n};return this.handlers.set(i,s),s}createAutomaticBounceHandler(n){return this.createBounceHandler({name:n.name,bounceThreshold:5,complaintThreshold:0.1,suppressionDuration:2592000,autoSuppress:!0,notificationTopicArn:n.notificationTopicArn})}addToSuppressionList(n){let i=`suppression-${Date.now()}-${this.suppressionCounter++}`,s=n.expirationDays?new Date(Date.now()+n.expirationDays*24*60*60*1000):void 0,o={id:i,emailAddress:n.emailAddress,reason:n.reason,suppressedAt:new Date,expiresAt:s,bounceCount:n.reason==="BOUNCE"?1:0,complaintCount:n.reason==="COMPLAINT"?1:0};return this.suppressionList.set(n.emailAddress,o),o}removeFromSuppressionList(n){return this.suppressionList.delete(n)}isSuppressed(n){let i=this.suppressionList.get(n);if(!i)return!1;if(i.expiresAt&&i.expiresAt<new Date)return this.suppressionList.delete(n),!1;return!0}getBounceStatistics(n,i){let s=Array.from(this.bounces.values()).filter((b)=>b.timestamp>=n&&b.timestamp<=i),o=s.length,c=s.filter((b)=>b.bounceType==="Permanent").length,l=s.filter((b)=>b.bounceType==="Transient").length,u=o*10,h=o/u*100,y=new Map;for(let b of s)y.set(b.recipient,(y.get(b.recipient)||0)+1);let f=Array.from(y.entries()).map(([b,C])=>({email:b,count:C})).sort((b,C)=>C.count-b.count).slice(0,10);return{totalBounces:o,permanentBounces:c,transientBounces:l,bounceRate:h,topRecipients:f}}getComplaintStatistics(n,i){let s=Array.from(this.complaints.values()).filter((y)=>y.timestamp>=n&&y.timestamp<=i),o=s.length,c=new Set;for(let y of s)for(let f of y.recipients)c.add(f);let l=c.size,u=o*1000,h=o/u*100;return{totalComplaints:o,uniqueComplainters:l,complaintRate:h}}calculateReputationMetrics(){let n=`metrics-${Date.now()}-${this.metricsCounter++}`,i=new Date,s=new Date(i.getTime()-86400000),o=this.getBounceStatistics(s,i),c=this.getComplaintStatistics(s,i),l;if(o.bounceRate>10||c.complaintRate>0.5)l="Shutdown";else if(o.bounceRate>5||c.complaintRate>0.1)l="Probation";else if(o.bounceRate>2||c.complaintRate>0.05)l="Warning";else l="Good";let u={id:n,timestamp:i,bounceRate:o.bounceRate,complaintRate:c.complaintRate,sendingQuota:50000,maxSendRate:14,sentLast24Hours:o.totalBounces*10,reputationStatus:l};return this.metrics.set(n,u),u}getBounces(n){let i=Array.from(this.bounces.values());return n?i.filter((s)=>s.messageId===n):i}getComplaints(n){let i=Array.from(this.complaints.values());return n?i.filter((s)=>s.messageId===n):i}listSuppressionList(n){let i=Array.from(this.suppressionList.values());return n?i.filter((s)=>s.reason===n):i}generateSNSSubscriptionCF(n){return{Type:"AWS::SNS::Subscription",Properties:{TopicArn:n.topicArn,Endpoint:n.endpoint,Protocol:n.protocol}}}generateEventDestinationCF(n){return{Type:"AWS::SES::ConfigurationSetEventDestination",Properties:{ConfigurationSetName:n.configurationSetName,EventDestination:{Name:n.eventDestinationName,Enabled:!0,MatchingEventTypes:n.eventTypes,...n.snsTopicArn&&{SnsDestination:{TopicARN:n.snsTopicArn}},...n.cloudWatchDestination&&{CloudWatchDestination:n.cloudWatchDestination}}}}}clear(){this.bounces.clear(),this.complaints.clear(),this.handlers.clear(),this.suppressionList.clear(),this.metrics.clear(),this.bounceCounter=0,this.complaintCounter=0,this.handlerCounter=0,this.suppressionCounter=0,this.metricsCounter=0}}var PE=new Em;class bm{events=new Map;campaigns=new Map;reports=new Map;abTests=new Map;eventCounter=0;campaignCounter=0;reportCounter=0;abTestCounter=0;trackEvent(n){let i=`event-${Date.now()}-${this.eventCounter++}`,s={id:i,...n};if(this.events.set(i,s),n.tags?.campaignId)this.updateCampaignStats(n.tags.campaignId,n.eventType);return s}trackOpen(n){return this.trackEvent({...n,eventType:"open",timestamp:new Date})}trackClick(n){return this.trackEvent({...n,eventType:"click",timestamp:new Date})}createCampaign(n){let i=`campaign-${Date.now()}-${this.campaignCounter++}`,s={id:i,sentCount:0,deliveredCount:0,openCount:0,clickCount:0,bounceCount:0,complaintCount:0,createdAt:new Date,...n};return this.campaigns.set(i,s),s}updateCampaignStats(n,i){let s=this.campaigns.get(n);if(!s)return;switch(i){case"send":s.sentCount++;break;case"delivery":s.deliveredCount++;break;case"open":s.openCount++;break;case"click":s.clickCount++;break;case"bounce":s.bounceCount++;break;case"complaint":s.complaintCount++;break}}generateReport(n){let i=`report-${Date.now()}-${this.reportCounter++}`,s=Array.from(this.events.values()).filter((R)=>{let W=R.timestamp>=n.startDate&&R.timestamp<=n.endDate,_=!n.campaignId||R.tags?.campaignId===n.campaignId;return W&&_}),o=s.filter((R)=>R.eventType==="send").length,c=s.filter((R)=>R.eventType==="delivery").length,l=s.filter((R)=>R.eventType==="open").length,u=s.filter((R)=>R.eventType==="click").length,h=s.filter((R)=>R.eventType==="bounce").length,y=s.filter((R)=>R.eventType==="complaint").length,f=o>0?c/o*100:0,b=c>0?l/c*100:0,C=c>0?u/c*100:0,T=l>0?u/l*100:0,w=o>0?h/o*100:0,E=c>0?y/c*100:0,I=new Map;for(let R of s)if(R.eventType==="click"){let W=R;I.set(W.link,(I.get(W.link)||0)+1)}let N=Array.from(I.entries()).map(([R,W])=>({link:R,clicks:W})).sort((R,W)=>W.clicks-R.clicks).slice(0,10),D={desktop:0,mobile:0,tablet:0,unknown:0};for(let R of s)if(R.eventType==="open"||R.eventType==="click"){let W=R.userAgent.toLowerCase();if(W.includes("mobile"))D.mobile++;else if(W.includes("tablet"))D.tablet++;else if(W.includes("mozilla"))D.desktop++;else D.unknown++}let B={id:i,campaignId:n.campaignId,startDate:n.startDate,endDate:n.endDate,totalSent:o,totalDelivered:c,totalOpened:l,totalClicked:u,totalBounced:h,totalComplaints:y,deliveryRate:f,openRate:b,clickRate:C,clickToOpenRate:T,bounceRate:w,complaintRate:E,topLinks:N,deviceBreakdown:D,locationBreakdown:{}};return this.reports.set(i,B),B}createABTest(n){let i=`abtest-${Date.now()}-${this.abTestCounter++}`,s={id:i,name:n.name,variants:n.variants.map((o,c)=>({id:`variant-${i}-${c}`,sentCount:0,openCount:0,clickCount:0,conversionCount:0,...o})),status:"draft"};return this.abTests.set(i,s),s}startABTest(n){let i=this.abTests.get(n);if(!i)throw Error(`A/B test not found: ${n}`);return i.status="running",i.startedAt=new Date,i}completeABTest(n){let i=this.abTests.get(n);if(!i)throw Error(`A/B test not found: ${n}`);let s=i.variants[0],o=0;for(let c of i.variants){let l=c.sentCount>0?c.openCount/c.sentCount:0;if(l>o)o=l,s=c}return i.status="completed",i.completedAt=new Date,i.winner=s.id,i}getCampaign(n){return this.campaigns.get(n)}listCampaigns(){return Array.from(this.campaigns.values())}getEvents(n){let i=Array.from(this.events.values());if(n?.messageId)i=i.filter((s)=>s.messageId===n.messageId);if(n?.eventType)i=i.filter((s)=>s.eventType===n.eventType);if(n?.startDate)i=i.filter((s)=>s.timestamp>=n.startDate);if(n?.endDate)i=i.filter((s)=>s.timestamp<=n.endDate);return i}generateTrackingConfigurationCF(n){return{Type:"AWS::SES::ConfigurationSet",Properties:{Name:n.configurationSetName,...n.openTracking&&{TrackingOptions:{CustomRedirectDomain:"tracking.example.com"}}}}}clear(){this.events.clear(),this.campaigns.clear(),this.reports.clear(),this.abTests.clear(),this.eventCounter=0,this.campaignCounter=0,this.reportCounter=0,this.abTestCounter=0}}var NE=new bm;class vm{dashboards=new Map;warmupPlans=new Map;domainReputations=new Map;dashboardCounter=0;warmupCounter=0;domainCounter=0;getReputationDashboard(){let n=`dashboard-${Date.now()}-${this.dashboardCounter++}`,i=Math.random()*5,s=Math.random()*0.5,o=Math.floor(Math.random()*10),c=Math.max(0,100-i*10-s*100-o*2),l=[];if(i>2)l.push("Reduce bounce rate by cleaning email list");if(s>0.1)l.push("Review email content and unsubscribe process");if(o>5)l.push("Improve email relevance and targeting");let u={id:n,timestamp:new Date,overallScore:c,bounceRate:i,complaintRate:s,spamReports:o,blacklistStatus:this.checkBlacklists(),dkimStatus:"VERIFIED",spfStatus:"PASS",dmarcStatus:"PASS",sendingLimits:{maxSendRate:14,max24HourSend:50000,sentLast24Hours:12000,remainingQuota:38000,quotaResetTime:new Date(Date.now()+86400000)},recommendations:l};return this.dashboards.set(n,u),u}checkBlacklists(){return["Spamhaus ZEN","Spamcop","SORBS","Barracuda","URIBL"].map((n)=>({listName:n,listed:Math.random()>0.95,delistUrl:`https://www.${n.toLowerCase().replace(/\s/g,"")}.org/delist`}))}createWarmupPlan(n){let i=`warmup-${Date.now()}-${this.warmupCounter++}`,s=[],o=(n.targetDailyLimit-n.initialDailyLimit)/n.durationDays;for(let l=0;l<n.durationDays;l++)s.push(Math.floor(n.initialDailyLimit+o*l));let c={id:i,name:n.name,startDate:new Date,currentDay:1,totalDays:n.durationDays,dailyLimits:s,currentLimit:s[0],status:"active"};return this.warmupPlans.set(i,c),c}createAggressiveWarmupPlan(n){return this.createWarmupPlan({name:n.name,initialDailyLimit:500,targetDailyLimit:50000,durationDays:14})}createConservativeWarmupPlan(n){return this.createWarmupPlan({name:n.name,initialDailyLimit:200,targetDailyLimit:50000,durationDays:30})}advanceWarmupPlan(n){let i=this.warmupPlans.get(n);if(!i)throw Error(`Warmup plan not found: ${n}`);if(i.currentDay<i.totalDays)i.currentDay++,i.currentLimit=i.dailyLimits[i.currentDay-1];if(i.currentDay>=i.totalDays)i.status="completed";return i}trackDomainReputation(n){let i=`domain-${Date.now()}-${this.domainCounter++}`,s=n.delivered/n.totalSent*100,o=n.delivered>0?n.opened/n.delivered*100:0,c=n.delivered>0?n.clicked/n.delivered*100:0,l=n.bounced/n.totalSent*100,u=n.delivered>0?n.complained/n.delivered*100:0,h=o*0.4+c*0.6,y=Math.max(0,100-l*10-u*100+h*0.2),f={id:i,domain:n.domain,reputationScore:y,totalSent:n.totalSent,deliveryRate:s,openRate:o,clickRate:c,bounceRate:l,complaintRate:u,engagementScore:h};return this.domainReputations.set(n.domain,f),f}getDomainReputation(n){return this.domainReputations.get(n)}listDomainReputations(){return Array.from(this.domainReputations.values())}getWarmupPlan(n){return this.warmupPlans.get(n)}listWarmupPlans(){return Array.from(this.warmupPlans.values())}clear(){this.dashboards.clear(),this.warmupPlans.clear(),this.domainReputations.clear(),this.dashboardCounter=0,this.warmupCounter=0,this.domainCounter=0}}var kE=new vm;class Tm{templates=new Map;versions=new Map;tests=new Map;templateCounter=0;testCounter=0;createTemplate(n){let i=`template-${Date.now()}-${this.templateCounter++}`,s=this.extractVariables(n.subject+n.htmlPart+n.textPart),o={id:i,variables:s,createdAt:new Date,updatedAt:new Date,version:1,...n};return this.templates.set(i,o),this.addVersion({templateId:i,version:1,subject:n.subject,htmlPart:n.htmlPart,textPart:n.textPart,createdBy:"system"}),o}createWelcomeTemplate(n){return this.createTemplate({name:n.name,subject:"Welcome to {{companyName}}!",htmlPart:`
3776
+ COPY . .`,impact:"Improve build time by 60-80% on subsequent builds"});let h={sizeBefore:i.totalSize,sizeAfter:i.totalSize*0.6,timeBefore:300,timeAfter:120},y={id:s,name:`Optimization for ${i.imageId}`,recommendations:o,estimatedSavings:h};return this.optimizations.set(s,y),y}getBuildConfig(n){return this.configs.get(n)}listBuildConfigs(){return Array.from(this.configs.values())}getMultiStageConfig(n){return this.multiStageConfigs.get(n)}listMultiStageConfigs(){return Array.from(this.multiStageConfigs.values())}getOptimization(n){return this.optimizations.get(n)}listOptimizations(){return Array.from(this.optimizations.values())}clear(){this.configs.clear(),this.multiStageConfigs.clear(),this.optimizations.clear(),this.analyses.clear(),this.configCounter=0,this.multiStageCounter=0,this.optimizationCounter=0,this.analysisCounter=0}}var IE=new pm;class gm{registries=new Map;credentials=new Map;registryCounter=0;credentialsCounter=0;createRegistry(n){let i=`registry-${Date.now()}-${this.registryCounter++}`,s={id:i,...n};return this.registries.set(i,s),s}createECRRepository(n){return this.createRegistry({name:n.name,registryType:"ecr",repositoryUri:`123456789012.dkr.ecr.${n.region||"us-east-1"}.amazonaws.com/${n.name}`,region:n.region||"us-east-1",encryption:{encryptionType:n.encryption||"AES256",kmsKeyId:n.kmsKeyId},scanning:{scanOnPush:n.scanOnPush??!0}})}createManagedRepository(n){let i=this.createECRRepository({name:n.name,region:n.region,scanOnPush:!0,encryption:"KMS"});return i.lifecycle={id:`lifecycle-${Date.now()}`,rules:[{rulePriority:1,description:"Keep only last N images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:n.maxImageCount||10},action:{type:"expire"}},{rulePriority:2,description:"Remove images older than N days",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:n.maxImageAgeDays||30,countUnit:"days"},action:{type:"expire"}}]},i}enableReplication(n,i){let s=this.registries.get(n);if(!s)throw Error(`Registry not found: ${n}`);return s.replication={enabled:!0,destinations:i},s}createCredentials(n){let i=`creds-${Date.now()}-${this.credentialsCounter++}`,s={id:i,...n};return this.credentials.set(i,s),s}getRegistry(n){return this.registries.get(n)}listRegistries(){return Array.from(this.registries.values())}generateECRRepositoryCF(n){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:n.name,ImageScanningConfiguration:{ScanOnPush:n.scanning?.scanOnPush??!1},EncryptionConfiguration:{EncryptionType:n.encryption?.encryptionType||"AES256",...n.encryption?.kmsKeyId&&{KmsKey:n.encryption.kmsKeyId}},ImageTagMutability:"MUTABLE",...n.lifecycle&&{LifecyclePolicy:{LifecyclePolicyText:JSON.stringify({rules:n.lifecycle.rules})}}}}}generateReplicationConfigCF(n){return{Type:"AWS::ECR::ReplicationConfiguration",Properties:{ReplicationConfiguration:{Rules:n.destinations.map((i)=>({Destinations:[{Region:i.region,...i.registryId&&{RegistryId:i.registryId}}]}))}}}}clear(){this.registries.clear(),this.credentials.clear(),this.registryCounter=0,this.credentialsCounter=0}}var SE=new gm;class mm{meshes=new Map;virtualNodes=new Map;virtualRouters=new Map;virtualGateways=new Map;meshCounter=0;nodeCounter=0;routerCounter=0;gatewayCounter=0;createMesh(n){let i=`mesh-${Date.now()}-${this.meshCounter++}`,s={id:i,...n};return this.meshes.set(i,s),s}createAppMesh(n){return this.createMesh({name:n.name,meshType:"app_mesh",services:n.services,virtualNodes:[],virtualRouters:[],virtualGateways:[]})}createVirtualNode(n){let i=`vnode-${Date.now()}-${this.nodeCounter++}`,s={id:i,...n};return this.virtualNodes.set(i,s),s}createHTTPVirtualNode(n){return this.createVirtualNode({name:n.name,serviceName:n.serviceName,listeners:[{port:n.port,protocol:"http",healthCheck:{protocol:"http",path:"/health",interval:30,timeout:10,healthyThreshold:2,unhealthyThreshold:3},timeout:{perRequest:15000,idle:300000}}],serviceDiscovery:{type:"aws_cloud_map",namespace:n.namespace,serviceName:n.serviceName}})}createVirtualRouter(n){let i=`vrouter-${Date.now()}-${this.routerCounter++}`,s={id:i,...n};return this.virtualRouters.set(i,s),s}createCanaryRoute(n){return this.createVirtualRouter({name:n.name,listeners:[{port:n.port,protocol:n.protocol}],routes:[{name:"canary-route",match:{prefix:"/"},action:{weightedTargets:[{virtualNode:n.stableTarget,weight:100-n.canaryWeight},{virtualNode:n.canaryTarget,weight:n.canaryWeight}]},retryPolicy:{maxRetries:3,perRetryTimeout:5000,httpRetryEvents:["server-error","gateway-error"],tcpRetryEvents:["connection-error"]}}]})}createVirtualGateway(n){let i=`vgateway-${Date.now()}-${this.gatewayCounter++}`,s={id:i,...n};return this.virtualGateways.set(i,s),s}createIngressGateway(n){let i={port:n.port,protocol:"http",healthCheck:{protocol:"http",path:"/health",interval:30,timeout:10,healthyThreshold:2,unhealthyThreshold:3}};if(n.enableTLS&&n.certificateArn)i.tls={mode:"STRICT",certificate:{acm:n.certificateArn}};return this.createVirtualGateway({name:n.name,listeners:[i],logging:{accessLog:{file:{path:"/dev/stdout"}}}})}getMesh(n){return this.meshes.get(n)}listMeshes(){return Array.from(this.meshes.values())}getVirtualNode(n){return this.virtualNodes.get(n)}listVirtualNodes(){return Array.from(this.virtualNodes.values())}generateMeshCF(n){return{Type:"AWS::AppMesh::Mesh",Properties:{MeshName:n.name,Spec:{EgressFilter:{Type:"ALLOW_ALL"}}}}}generateVirtualNodeCF(n,i){return{Type:"AWS::AppMesh::VirtualNode",Properties:{MeshName:i,VirtualNodeName:n.name,Spec:{Listeners:n.listeners.map((s)=>({PortMapping:{Port:s.port,Protocol:s.protocol},...s.healthCheck&&{HealthCheck:{Protocol:s.healthCheck.protocol,...s.healthCheck.path&&{Path:s.healthCheck.path},IntervalMillis:s.healthCheck.interval*1000,TimeoutMillis:s.healthCheck.timeout*1000,HealthyThreshold:s.healthCheck.healthyThreshold,UnhealthyThreshold:s.healthCheck.unhealthyThreshold}}})),ServiceDiscovery:{AWSCloudMap:{NamespaceName:n.serviceDiscovery.namespace,ServiceName:n.serviceDiscovery.serviceName}}}}}}generateVirtualRouterCF(n,i){return{Type:"AWS::AppMesh::VirtualRouter",Properties:{MeshName:i,VirtualRouterName:n.name,Spec:{Listeners:n.listeners.map((s)=>({PortMapping:{Port:s.port,Protocol:s.protocol}}))}}}}clear(){this.meshes.clear(),this.virtualNodes.clear(),this.virtualRouters.clear(),this.virtualGateways.clear(),this.meshCounter=0,this.nodeCounter=0,this.routerCounter=0,this.gatewayCounter=0}}var CE=new mm;class hm{layers=new Map;versions=new Map;permissions=new Map;layerCounter=0;versionCounter=0;permissionCounter=0;createLayer(n){let i=`layer-${Date.now()}-${this.layerCounter++}`,s=1,o={id:i,layerArn:`arn:aws:lambda:us-east-1:123456789012:layer:${n.layerName}:1`,version:1,...n};return this.layers.set(i,o),o}createNodeDependenciesLayer(n){return this.createLayer({layerName:n.layerName,description:"Node.js dependencies layer",compatibleRuntimes:[`nodejs${n.nodeVersion}`],content:{type:"s3",s3Bucket:n.s3Bucket,s3Key:n.s3Key},size:5242880})}createUtilitiesLayer(n){return this.createLayer({layerName:n.layerName,description:"Shared utilities and helpers",compatibleRuntimes:n.runtimes,content:{type:"s3",s3Bucket:n.s3Bucket,s3Key:n.s3Key},size:1048576})}publishVersion(n){let i=this.layers.get(n);if(!i)throw Error(`Layer not found: ${n}`);let s=`version-${Date.now()}-${this.versionCounter++}`,o=i.version+1,c={id:s,layerName:i.layerName,version:o,createdAt:new Date,compatibleRuntimes:i.compatibleRuntimes,size:i.size,codeHash:this.generateHash()};return this.versions.set(s,c),i.version=o,i.layerArn=`arn:aws:lambda:us-east-1:123456789012:layer:${i.layerName}:${o}`,c}addPermission(n){let i=`permission-${Date.now()}-${this.permissionCounter++}`,s={id:i,layerName:n.layerName,version:n.version,principal:n.principal,action:"lambda:GetLayerVersion",organizationId:n.organizationId};return this.permissions.set(i,s),s}generateHash(){return Math.random().toString(36).substring(2,15)}getLayer(n){return this.layers.get(n)}listLayers(){return Array.from(this.layers.values())}getLayerVersions(n){return Array.from(this.versions.values()).filter((i)=>i.layerName===n)}generateLayerCF(n){return{Type:"AWS::Lambda::LayerVersion",Properties:{LayerName:n.layerName,Description:n.description,Content:n.content.type==="s3"?{S3Bucket:n.content.s3Bucket,S3Key:n.content.s3Key,...n.content.s3ObjectVersion&&{S3ObjectVersion:n.content.s3ObjectVersion}}:{ZipFile:n.content.zipFile},CompatibleRuntimes:n.compatibleRuntimes,...n.licenseInfo&&{LicenseInfo:n.licenseInfo}}}}generateLayerPermissionCF(n){return{Type:"AWS::Lambda::LayerVersionPermission",Properties:{LayerVersionArn:`arn:aws:lambda:us-east-1:123456789012:layer:${n.layerName}:${n.version}`,Action:n.action,Principal:n.principal,...n.organizationId&&{OrganizationId:n.organizationId}}}}clear(){this.layers.clear(),this.versions.clear(),this.permissions.clear(),this.layerCounter=0,this.versionCounter=0,this.permissionCounter=0}}var EE=new hm;class fm{versions=new Map;aliases=new Map;deployments=new Map;versionCounter=0;aliasCounter=0;deploymentCounter=0;publishVersion(n){let i=`version-${Date.now()}-${this.versionCounter++}`,s=this.getNextVersionNumber(n.functionName),o={id:i,functionName:n.functionName,version:s.toString(),functionArn:`arn:aws:lambda:us-east-1:123456789012:function:${n.functionName}:${s}`,codeHash:this.generateHash(),description:n.description,runtime:n.runtime,memorySize:n.memorySize,timeout:n.timeout,publishedAt:new Date};return this.versions.set(i,o),o}getNextVersionNumber(n){let i=Array.from(this.versions.values()).filter((s)=>s.functionName===n).map((s)=>parseInt(s.version));return i.length>0?Math.max(...i)+1:1}createAlias(n){let i=`alias-${Date.now()}-${this.aliasCounter++}`,s={id:i,aliasArn:`arn:aws:lambda:us-east-1:123456789012:function:${n.functionName}:${n.aliasName}`,revisionId:this.generateHash(),...n};return this.aliases.set(i,s),s}createProductionAlias(n){return this.createAlias({functionName:n.functionName,aliasName:"production",functionVersion:n.version,description:"Production alias"})}createStagingAlias(n){return this.createAlias({functionName:n.functionName,aliasName:"staging",functionVersion:n.version,description:"Staging alias"})}updateAlias(n,i){let s=this.aliases.get(n);if(!s)throw Error(`Alias not found: ${n}`);return s.functionVersion=i,s.revisionId=this.generateHash(),s}configureWeightedRouting(n,i){let s=this.aliases.get(n);if(!s)throw Error(`Alias not found: ${n}`);return s.routingConfig={additionalVersionWeights:i},s}createCanaryDeployment(n){let i=`deployment-${Date.now()}-${this.deploymentCounter++}`,s=Array.from(this.aliases.values()).find((c)=>c.functionName===n.functionName&&c.aliasName===n.aliasName);if(!s)s=this.createAlias({functionName:n.functionName,aliasName:n.aliasName,functionVersion:n.fromVersion});this.configureWeightedRouting(s.id,{[n.toVersion]:n.canaryWeight});let o={id:i,functionName:n.functionName,fromVersion:n.fromVersion,toVersion:n.toVersion,aliasName:n.aliasName,strategy:"canary",status:"in_progress",startedAt:new Date};return this.deployments.set(i,o),o}completeDeployment(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);let s=Array.from(this.aliases.values()).find((o)=>o.functionName===i.functionName&&o.aliasName===i.aliasName);if(s)s.functionVersion=i.toVersion,s.routingConfig=void 0;return i.status="completed",i.completedAt=new Date,i}rollbackDeployment(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);let s=Array.from(this.aliases.values()).find((o)=>o.functionName===i.functionName&&o.aliasName===i.aliasName);if(s)s.functionVersion=i.fromVersion,s.routingConfig=void 0;return i.status="failed",i.completedAt=new Date,i}generateHash(){return Math.random().toString(36).substring(2,15)}getVersion(n){return this.versions.get(n)}listVersions(n){let i=Array.from(this.versions.values());return n?i.filter((s)=>s.functionName===n):i}getAlias(n){return this.aliases.get(n)}listAliases(n){let i=Array.from(this.aliases.values());return n?i.filter((s)=>s.functionName===n):i}generateVersionCF(n){return{Type:"AWS::Lambda::Version",Properties:{FunctionName:n.functionName,Description:n.description}}}generateAliasCF(n){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:n.functionName,Name:n.aliasName,FunctionVersion:n.functionVersion,Description:n.description,...n.routingConfig&&{RoutingConfig:{AdditionalVersionWeights:Object.entries(n.routingConfig.additionalVersionWeights||{}).map(([i,s])=>({FunctionVersion:i,FunctionWeight:s}))}}}}}clear(){this.versions.clear(),this.aliases.clear(),this.deployments.clear(),this.versionCounter=0,this.aliasCounter=0,this.deploymentCounter=0}}var bE=new fm;class Am{configs=new Map;provisionedConfigs=new Map;schedules=new Map;autoScalingConfigs=new Map;configCounter=0;provisionedCounter=0;scheduleCounter=0;autoScalingCounter=0;setReservedConcurrency(n){let i=`concurrency-${Date.now()}-${this.configCounter++}`,s={id:i,functionName:n.functionName,reservedConcurrency:n.reservedConcurrency};return this.configs.set(i,s),s}setProvisionedConcurrency(n){let i=`provisioned-${Date.now()}-${this.provisionedCounter++}`,s={id:i,functionName:n.functionName,qualifier:n.qualifier,provisionedConcurrentExecutions:n.provisionedConcurrentExecutions,status:"pending",lastModified:new Date};return this.provisionedConfigs.set(i,s),setTimeout(()=>{s.status="ready",s.allocatedConcurrency=n.provisionedConcurrentExecutions,s.availableConcurrency=n.provisionedConcurrentExecutions},100),s}configureWarmPool(n){return this.setProvisionedConcurrency({functionName:n.functionName,qualifier:n.alias,provisionedConcurrentExecutions:n.minInstances})}createSchedule(n){let i=`schedule-${Date.now()}-${this.scheduleCounter++}`,s={id:i,...n};return this.schedules.set(i,s),s}createBusinessHoursSchedule(n){return this.createSchedule({name:`${n.functionName}-business-hours`,functionName:n.functionName,qualifier:n.qualifier,schedule:[{name:"business-hours",cronExpression:"0 8 * * MON-FRI",targetConcurrency:n.businessHoursConcurrency},{name:"off-hours",cronExpression:"0 18 * * MON-FRI",targetConcurrency:n.offHoursConcurrency},{name:"weekend",cronExpression:"0 0 * * SAT",targetConcurrency:n.offHoursConcurrency}]})}configureAutoScaling(n){let i=`autoscaling-${Date.now()}-${this.autoScalingCounter++}`,s={id:i,...n};return this.autoScalingConfigs.set(i,s),s}configurePredictiveScaling(n){return this.configureAutoScaling({functionName:n.functionName,qualifier:n.qualifier,minCapacity:n.baselineCapacity,maxCapacity:n.peakCapacity,targetUtilization:0.7,scaleInCooldown:300,scaleOutCooldown:60})}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getProvisionedConfig(n){return this.provisionedConfigs.get(n)}listProvisionedConfigs(){return Array.from(this.provisionedConfigs.values())}generateReservedConcurrencyCF(n){return{Type:"AWS::Lambda::Function",Properties:{FunctionName:n.functionName,ReservedConcurrentExecutions:n.reservedConcurrency}}}generateProvisionedConcurrencyCF(n){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:n.functionName,Name:n.qualifier,ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:n.provisionedConcurrentExecutions}}}}generateAutoScalingTargetCF(n){return{Type:"AWS::ApplicationAutoScaling::ScalableTarget",Properties:{ServiceNamespace:"lambda",ResourceId:`function:${n.functionName}:${n.qualifier}`,ScalableDimension:"lambda:function:ProvisionedConcurrentExecutions",MinCapacity:n.minCapacity,MaxCapacity:n.maxCapacity}}}generateAutoScalingPolicyCF(n){return{Type:"AWS::ApplicationAutoScaling::ScalingPolicy",Properties:{PolicyName:`${n.functionName}-autoscaling`,PolicyType:"TargetTrackingScaling",ScalingTargetId:{Ref:`${n.functionName}AutoScalingTarget`},TargetTrackingScalingPolicyConfiguration:{TargetValue:n.targetUtilization*100,PredefinedMetricSpecification:{PredefinedMetricType:"LambdaProvisionedConcurrencyUtilization"},ScaleInCooldown:n.scaleInCooldown||300,ScaleOutCooldown:n.scaleOutCooldown||60}}}}clear(){this.configs.clear(),this.provisionedConfigs.clear(),this.schedules.clear(),this.autoScalingConfigs.clear(),this.configCounter=0,this.provisionedCounter=0,this.scheduleCounter=0,this.autoScalingCounter=0}}var vE=new Am;class ym{destinations=new Map;records=new Map;eventBridgeDestinations=new Map;destinationCounter=0;recordCounter=0;eventBridgeCounter=0;configureDestinations(n){let i=`destination-${Date.now()}-${this.destinationCounter++}`,s={id:i,...n};return this.destinations.set(i,s),s}configureSQSDestination(n){let i={type:"sqs",arn:n.queueArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureSNSDestination(n){let i={type:"sns",arn:n.topicArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureEventBridgeDestination(n){let i={type:"eventbridge",arn:n.eventBusArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureLambdaDestination(n){let i={type:"lambda",arn:n.destinationFunctionArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureDLQWithNotification(n){return this.configureDestinations({functionName:n.functionName,failureDestination:{type:"sqs",arn:n.dlqArn},maxEventAge:3600,maxRetries:0})}createEventBridgeIntegration(n){let i=`eventbridge-${Date.now()}-${this.eventBridgeCounter++}`,s={id:i,functionName:n.functionName,eventBusArn:n.eventBusArn,detailType:n.detailType||"Lambda Function Invocation Result",source:n.source||`lambda.${n.functionName}`};return this.eventBridgeDestinations.set(i,s),s}sendToDestination(n){let i=Array.from(this.destinations.values()).find((l)=>l.functionName===n.functionName);if(!i)return null;let s=n.status==="success"?i.successDestination:i.failureDestination;if(!s)return null;let o=`record-${Date.now()}-${this.recordCounter++}`,c={id:o,timestamp:new Date,functionName:n.functionName,requestId:n.requestId,status:n.status,destinationType:s.type,destinationArn:s.arn,payload:n.payload,error:n.error};return this.records.set(o,c),c}getDestination(n){return this.destinations.get(n)}listDestinations(n){let i=Array.from(this.destinations.values());return n?i.filter((s)=>s.functionName===n):i}getDestinationRecords(n){let i=Array.from(this.records.values());return n?i.filter((s)=>s.functionName===n):i}generateEventInvokeConfigCF(n){return{Type:"AWS::Lambda::EventInvokeConfig",Properties:{FunctionName:n.functionName,Qualifier:n.qualifier||"$LATEST",MaximumEventAgeInSeconds:n.maxEventAge||21600,MaximumRetryAttempts:n.maxRetries??2,...n.successDestination&&{DestinationConfig:{OnSuccess:{Destination:n.successDestination.arn}}},...n.failureDestination&&{DestinationConfig:{OnFailure:{Destination:n.failureDestination.arn}}}}}}generateEventBridgeRuleCF(n){return{Type:"AWS::Events::Rule",Properties:{EventBusName:n.eventBusArn.split("/").pop(),EventPattern:{source:[n.source],"detail-type":[n.detailType]},State:"ENABLED",Targets:[{Arn:`arn:aws:lambda:us-east-1:123456789012:function:${n.functionName}`,Id:n.id}]}}}clear(){this.destinations.clear(),this.records.clear(),this.eventBridgeDestinations.clear(),this.destinationCounter=0,this.recordCounter=0,this.eventBridgeCounter=0}}var TE=new ym;class Im{vpcConfigs=new Map;endpoints=new Map;networkInterfaces=new Map;connectivity=new Map;configCounter=0;endpointCounter=0;eniCounter=0;connectivityCounter=0;configureVPC(n){let i=`vpc-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};this.vpcConfigs.set(i,s);for(let o of n.subnetIds)this.createNetworkInterface({functionName:n.functionName,subnetId:o});return s}configurePrivateVPC(n){return this.configureVPC({functionName:n.functionName,vpcId:n.vpcId,subnetIds:n.privateSubnetIds,securityGroupIds:[n.securityGroupId],ipv6Allowed:!1})}configureMultiAZVPC(n){if(n.subnetIds.length<2)throw Error("Multi-AZ configuration requires at least 2 subnets");return this.configureVPC({functionName:n.functionName,vpcId:n.vpcId,subnetIds:n.subnetIds,securityGroupIds:n.securityGroupIds})}createVPCEndpoint(n){let i=`endpoint-${Date.now()}-${this.endpointCounter++}`,s={id:i,...n};return this.endpoints.set(i,s),s}createS3Endpoint(n){return this.createVPCEndpoint({vpcId:n.vpcId,serviceName:"com.amazonaws.us-east-1.s3",endpointType:"Gateway",privateDnsEnabled:!1})}createDynamoDBEndpoint(n){return this.createVPCEndpoint({vpcId:n.vpcId,serviceName:"com.amazonaws.us-east-1.dynamodb",endpointType:"Gateway",privateDnsEnabled:!1})}createSecretsManagerEndpoint(n){return this.createVPCEndpoint({vpcId:n.vpcId,serviceName:"com.amazonaws.us-east-1.secretsmanager",endpointType:"Interface",subnetIds:n.subnetIds,securityGroupIds:n.securityGroupIds,privateDnsEnabled:!0})}createNetworkInterface(n){let i=`eni-${Date.now()}-${this.eniCounter++}`,s={id:i,functionName:n.functionName,networkInterfaceId:`eni-${Math.random().toString(36).substring(2,15)}`,subnetId:n.subnetId,privateIpAddress:`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`,status:"creating",attachedAt:new Date};return this.networkInterfaces.set(i,s),setTimeout(()=>{s.status="available"},100),s}analyzeConnectivity(n){let i=`connectivity-${Date.now()}-${this.connectivityCounter++}`,s=Array.from(this.vpcConfigs.values()).find((y)=>y.functionName===n.functionName),o=Array.from(this.endpoints.values()).filter((y)=>y.vpcId===s?.vpcId).map((y)=>y.serviceName),c=[],l=n.hasNATGateway??!1,u=n.hasInternetGateway??!1;if(!l&&!u)c.push("Add NAT Gateway for internet access");if(!o.includes("com.amazonaws.us-east-1.s3"))c.push("Add S3 VPC endpoint to reduce NAT costs");if(!o.includes("com.amazonaws.us-east-1.dynamodb"))c.push("Add DynamoDB VPC endpoint for private access");let h={id:i,functionName:n.functionName,hasInternetAccess:l||u,hasNATGateway:l,hasVPCEndpoints:o.length>0,endpoints:o,recommendations:c};return this.connectivity.set(i,h),h}getVPCConfig(n){return this.vpcConfigs.get(n)}listVPCConfigs(n){let i=Array.from(this.vpcConfigs.values());return n?i.filter((s)=>s.functionName===n):i}getNetworkInterfaces(n){return Array.from(this.networkInterfaces.values()).filter((i)=>i.functionName===n)}listVPCEndpoints(n){let i=Array.from(this.endpoints.values());return n?i.filter((s)=>s.vpcId===n):i}generateVPCConfigCF(n){return{VpcConfig:{SubnetIds:n.subnetIds,SecurityGroupIds:n.securityGroupIds,...n.ipv6Allowed&&{Ipv6AllowedForDualStack:!0}}}}generateVPCEndpointCF(n){return{Type:"AWS::EC2::VPCEndpoint",Properties:{VpcId:n.vpcId,ServiceName:n.serviceName,VpcEndpointType:n.endpointType,...n.subnetIds&&{SubnetIds:n.subnetIds},...n.securityGroupIds&&{SecurityGroupIds:n.securityGroupIds},...n.privateDnsEnabled!==void 0&&{PrivateDnsEnabled:n.privateDnsEnabled}}}}generateSecurityGroupCF(n){return{Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:n.groupName,GroupDescription:`Security group for Lambda ${n.groupName}`,VpcId:n.vpcId,...n.ingressRules&&{SecurityGroupIngress:n.ingressRules.map((i)=>({IpProtocol:i.protocol,FromPort:i.fromPort,ToPort:i.toPort,...i.cidrIp&&{CidrIp:i.cidrIp},...i.sourceSecurityGroupId&&{SourceSecurityGroupId:i.sourceSecurityGroupId}}))},...n.egressRules&&{SecurityGroupEgress:n.egressRules.map((i)=>({IpProtocol:i.protocol,FromPort:i.fromPort,ToPort:i.toPort,CidrIp:i.cidrIp||"0.0.0.0/0"}))}}}}clear(){this.vpcConfigs.clear(),this.endpoints.clear(),this.networkInterfaces.clear(),this.connectivity.clear(),this.configCounter=0,this.endpointCounter=0,this.eniCounter=0,this.connectivityCounter=0}}var wE=new Im;class Sm{dlqConfigs=new Map;messages=new Map;alarms=new Map;reprocessing=new Map;configCounter=0;messageCounter=0;alarmCounter=0;reprocessCounter=0;configureDLQ(n){let i=`dlq-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.dlqConfigs.set(i,s),s}configureSQSDLQ(n){return this.configureDLQ({functionName:n.functionName,targetArn:n.queueArn,targetType:"sqs",maxReceiveCount:n.maxReceiveCount||3,retentionPeriod:n.retentionPeriod||1209600})}configureSNSDLQ(n){return this.configureDLQ({functionName:n.functionName,targetArn:n.topicArn,targetType:"sns"})}configureDLQWithAlarm(n){let i=this.configureSQSDLQ({functionName:n.functionName,queueArn:n.queueArn});return this.createDLQAlarm({dlqConfigId:i.id,alarmName:`${n.functionName}-dlq-alarm`,threshold:n.alarmThreshold,evaluationPeriods:1,notificationTopicArn:n.notificationTopicArn,enabled:!0}),i}sendToDLQ(n){let i=`message-${Date.now()}-${this.messageCounter++}`,s={id:i,timestamp:new Date,...n};return this.messages.set(i,s),s}createDLQAlarm(n){let i=`alarm-${Date.now()}-${this.alarmCounter++}`,s={id:i,...n};return this.alarms.set(i,s),s}createAgeAlarm(n){let i=this.dlqConfigs.get(n.dlqConfigId);if(!i)throw Error(`DLQ config not found: ${n.dlqConfigId}`);return this.createDLQAlarm({dlqConfigId:n.dlqConfigId,alarmName:`${i.functionName}-dlq-age-alarm`,threshold:n.maxAgeSeconds,evaluationPeriods:1,notificationTopicArn:n.notificationTopicArn,enabled:!0})}async reprocessMessage(n){let i=this.messages.get(n);if(!i)throw Error(`Message not found: ${n}`);let s=Array.from(this.dlqConfigs.values()).find((l)=>l.functionName===i.functionName);if(!s)throw Error(`DLQ config not found for function: ${i.functionName}`);let o=`reprocess-${Date.now()}-${this.reprocessCounter++}`,c={id:o,dlqConfigId:s.id,messageId:n,status:"pending",startedAt:new Date};return this.reprocessing.set(o,c),setTimeout(()=>{c.status="processing",setTimeout(()=>{let l=Math.random()>0.3;if(c.status=l?"success":"failed",c.completedAt=new Date,!l)c.error="Reprocessing failed - same error occurred";else this.messages.delete(n)},100)},50),c}async batchReprocess(n){let i=this.dlqConfigs.get(n.dlqConfigId);if(!i)throw Error(`DLQ config not found: ${n.dlqConfigId}`);let s=Array.from(this.messages.values()).filter((o)=>o.functionName===i.functionName).slice(0,n.maxMessages||10).map((o)=>this.reprocessMessage(o.id));return Promise.all(s)}getDLQStats(n){let i=this.dlqConfigs.get(n);if(!i)throw Error(`DLQ config not found: ${n}`);let s=Array.from(this.messages.values()).filter((u)=>u.functionName===i.functionName),o={},c=0;for(let u of s)o[u.errorType]=(o[u.errorType]||0)+1,c+=u.attemptCount;let l=s.map((u)=>u.timestamp);return{totalMessages:s.length,oldestMessage:l.length>0?new Date(Math.min(...l.map((u)=>u.getTime()))):void 0,newestMessage:l.length>0?new Date(Math.max(...l.map((u)=>u.getTime()))):void 0,averageAttempts:s.length>0?c/s.length:0,errorTypes:o}}getDLQConfig(n){return this.dlqConfigs.get(n)}listDLQConfigs(){return Array.from(this.dlqConfigs.values())}getDLQMessages(n){let i=this.dlqConfigs.get(n);if(!i)return[];return Array.from(this.messages.values()).filter((s)=>s.functionName===i.functionName)}generateDLQCF(n){return{DeadLetterConfig:{TargetArn:n.targetArn}}}generateSQSDLQCF(n){return{Type:"AWS::SQS::Queue",Properties:{QueueName:`${n.functionName}-dlq`,MessageRetentionPeriod:n.retentionPeriod||1209600,...n.maxReceiveCount&&{RedrivePolicy:{deadLetterTargetArn:n.targetArn,maxReceiveCount:n.maxReceiveCount}}}}}generateDLQAlarmCF(n){let i=this.dlqConfigs.get(n.dlqConfigId);if(!i)throw Error(`DLQ config not found: ${n.dlqConfigId}`);return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:n.alarmName,AlarmDescription:`DLQ alarm for ${i.functionName}`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Sum",Period:300,EvaluationPeriods:n.evaluationPeriods,Threshold:n.threshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:i.targetArn.split(":").pop()}],...n.notificationTopicArn&&{AlarmActions:[n.notificationTopicArn]}}}}clear(){this.dlqConfigs.clear(),this.messages.clear(),this.alarms.clear(),this.reprocessing.clear(),this.configCounter=0,this.messageCounter=0,this.alarmCounter=0,this.reprocessCounter=0}}var RE=new Sm;class Cm{policies=new Map;healthChecks=new Map;trafficPolicies=new Map;policyCounter=0;healthCheckCounter=0;trafficPolicyCounter=0;createWeightedPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"weighted",...n};return this.policies.set(i,s),s}createLatencyPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"latency",...n};return this.policies.set(i,s),s}createFailoverPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"failover",...n};return this.policies.set(i,s),s}createGeolocationPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"geolocation",...n};return this.policies.set(i,s),s}createGeoproximityPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"geoproximity",...n};return this.policies.set(i,s),s}createHTTPHealthCheck(n){let i=`health-check-${Date.now()}-${this.healthCheckCounter++}`,s={id:i,type:n.port===443?"https":"http",requestInterval:n.requestInterval||30,failureThreshold:n.failureThreshold||3,healthCheckStatus:"Unknown",port:n.port||(n.port===443?443:80),...n};return this.healthChecks.set(i,s),setTimeout(()=>{s.healthCheckStatus=Math.random()>0.2?"Healthy":"Unhealthy"},100),s}createTCPHealthCheck(n){let i=`health-check-${Date.now()}-${this.healthCheckCounter++}`,s={id:i,type:"tcp",fullyQualifiedDomainName:n.ipAddress,requestInterval:n.requestInterval||30,failureThreshold:n.failureThreshold||3,healthCheckStatus:"Unknown",...n};return this.healthChecks.set(i,s),setTimeout(()=>{s.healthCheckStatus=Math.random()>0.1?"Healthy":"Unhealthy"},100),s}createCalculatedHealthCheck(n){let i=`health-check-${Date.now()}-${this.healthCheckCounter++}`,s={id:i,type:"calculated",requestInterval:30,failureThreshold:0,healthCheckStatus:"Unknown",...n};return this.healthChecks.set(i,s),setTimeout(()=>{let o=n.childHealthChecks.filter((c)=>this.healthChecks.get(c)?.healthCheckStatus==="Healthy").length;s.healthCheckStatus=o>=n.healthThreshold?"Healthy":"Unhealthy"},150),s}createTrafficPolicy(n){let i=`traffic-policy-${Date.now()}-${this.trafficPolicyCounter++}`,s={id:i,version:1,...n};return this.trafficPolicies.set(i,s),s}createFailoverTrafficPolicy(n){return this.createTrafficPolicy({name:n.name,document:{recordType:n.recordType||"A",startRule:"failover",endpoints:{primary:{type:"value",value:n.primaryEndpoint},secondary:{type:"value",value:n.secondaryEndpoint}},rules:{failover:{ruleType:"failover",primary:"primary",secondary:"secondary"}}}})}createGeoproximityTrafficPolicy(n){let i={},s=[];return n.locations.forEach((o,c)=>{let l=`endpoint${c}`;i[l]={type:"value",value:o.endpoint},s.push({endpointReference:l,region:o.region,latitude:o.latitude,longitude:o.longitude,bias:o.bias})}),this.createTrafficPolicy({name:n.name,document:{recordType:"A",startRule:"geoproximity",endpoints:i,rules:{geoproximity:{ruleType:"geoproximity",locations:s}}}})}getPolicy(n){return this.policies.get(n)}listPolicies(){return Array.from(this.policies.values())}getHealthCheck(n){return this.healthChecks.get(n)}listHealthChecks(){return Array.from(this.healthChecks.values())}getHealthCheckStatus(n){return this.healthChecks.get(n)?.healthCheckStatus||"Unknown"}generateHealthCheckCF(n){let i={Type:"AWS::Route53::HealthCheck",Properties:{HealthCheckConfig:{Type:n.type.toUpperCase(),RequestInterval:n.requestInterval,FailureThreshold:n.failureThreshold,...n.measureLatency&&{MeasureLatency:!0}},HealthCheckTags:[{Key:"Name",Value:n.name}]}};if(n.type==="calculated"){let s=n;i.Properties.HealthCheckConfig.ChildHealthChecks=s.childHealthChecks,i.Properties.HealthCheckConfig.HealthThreshold=s.healthThreshold}else{if(n.ipAddress)i.Properties.HealthCheckConfig.IPAddress=n.ipAddress;if(n.fullyQualifiedDomainName)i.Properties.HealthCheckConfig.FullyQualifiedDomainName=n.fullyQualifiedDomainName;if(n.port)i.Properties.HealthCheckConfig.Port=n.port;if(n.resourcePath)i.Properties.HealthCheckConfig.ResourcePath=n.resourcePath;if(n.enableSNI)i.Properties.HealthCheckConfig.EnableSNI=!0}return i}generateWeightedRecordSetCF(n){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:n.name,Type:n.type,TTL:n.ttl,ResourceRecords:n.resourceRecords,Weight:n.weight,SetIdentifier:n.setIdentifier,...n.healthCheckId&&{HealthCheckId:n.healthCheckId}}}}generateFailoverRecordSetCF(n){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:n.name,Type:n.type,TTL:n.ttl,ResourceRecords:n.resourceRecords,Failover:n.failover,SetIdentifier:n.setIdentifier,...n.healthCheckId&&{HealthCheckId:n.healthCheckId}}}}clear(){this.policies.clear(),this.healthChecks.clear(),this.trafficPolicies.clear(),this.policyCounter=0,this.healthCheckCounter=0,this.trafficPolicyCounter=0}}var DE=new Cm;class Em{configs=new Map;ksks=new Map;validations=new Map;configCounter=0;kskCounter=0;validationCounter=0;enableDNSSEC(n){let i=`dnssec-${Date.now()}-${this.configCounter++}`,s={id:i,hostedZoneId:n.hostedZoneId,status:"SIGNING",signingStatus:"Initializing DNSSEC signing"};if(this.configs.set(i,s),n.kmsKeyArn)this.createKSK({name:`ksk-${n.hostedZoneId}`,hostedZoneId:n.hostedZoneId,kmsKeyArn:n.kmsKeyArn});return setTimeout(()=>{s.status="SIGNED",s.signingStatus="DNSSEC signing complete"},100),s}disableDNSSEC(n){let i=this.configs.get(n);if(!i)throw Error(`DNSSEC config not found: ${n}`);return i.status="DELETING",i.signingStatus="Removing DNSSEC signing",setTimeout(()=>{i.status="NOT_SIGNING",i.signingStatus="DNSSEC signing removed"},100),i}createKSK(n){let i=`ksk-${Date.now()}-${this.kskCounter++}`,s={id:i,status:"ACTIVE",flag:257,keyManagementServiceArn:n.kmsKeyArn,digestAlgorithm:2,keyTag:Math.floor(Math.random()*65535),publicKey:this.generatePublicKey(),...n};s.dnskeyRecord=`${s.flag} 3 8 ${s.publicKey}`;let o=this.generateDigest(s.dnskeyRecord);return s.digestValue=o,s.dsRecord=`${s.keyTag} 8 ${s.digestAlgorithm} ${o}`,this.ksks.set(i,s),s}deactivateKSK(n){let i=this.ksks.get(n);if(!i)throw Error(`KSK not found: ${n}`);return i.status="INACTIVE",i}validateDNSSEC(n){let i=`validation-${Date.now()}-${this.validationCounter++}`,s=n.checkDNSKEY!==!1?Math.random()>0.1:!1,o=n.checkRRSIG!==!1?Math.random()>0.1:!1,c=s&&o,l=[];if(!s)l.push("DNSKEY record not found");if(!o)l.push("RRSIG record not found");let u;if(!s&&!o)u="INSECURE";else if(s&&o&&c)u="VALID";else if(s||o)u="BOGUS",l.push("Invalid signature or incomplete DNSSEC chain");else u="INVALID";let h={id:i,domain:n.domain,validationStatus:u,dnskeyPresent:s,rrsigPresent:o,validSignature:c,errors:l};return this.validations.set(i,h),h}getDNSSECConfig(n){return this.configs.get(n)}listDNSSECConfigs(){return Array.from(this.configs.values())}getKSK(n){return this.ksks.get(n)}listKSKs(n){let i=Array.from(this.ksks.values());return n?i.filter((s)=>s.hostedZoneId===n):i}getDSRecord(n){let i=this.ksks.get(n);if(!i||!i.dsRecord)throw Error("DS record not available");return i.dsRecord}generatePublicKey(){let n="";for(let i=0;i<256;i++)n+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(Math.floor(Math.random()*64));return n}generateDigest(n){let i="";for(let s=0;s<64;s++)i+="0123456789ABCDEF".charAt(Math.floor(Math.random()*16));return i}generateDNSSECCF(n){return{Type:"AWS::Route53::DNSSEC",Properties:{HostedZoneId:n.hostedZoneId}}}generateKSKCF(n){return{Type:"AWS::Route53::KeySigningKey",Properties:{Name:n.name,HostedZoneId:n.hostedZoneId,KeyManagementServiceArn:n.keyManagementServiceArn,Status:n.status}}}clear(){this.configs.clear(),this.ksks.clear(),this.validations.clear(),this.configCounter=0,this.kskCounter=0,this.validationCounter=0}}var PE=new Em;class bm{endpoints=new Map;rules=new Map;firewalls=new Map;ruleGroups=new Map;domainLists=new Map;endpointCounter=0;ruleCounter=0;firewallCounter=0;ruleGroupCounter=0;domainListCounter=0;createResolverEndpoint(n){let i=`endpoint-${Date.now()}-${this.endpointCounter++}`,s={id:i,status:"CREATING",...n};return this.endpoints.set(i,s),setTimeout(()=>{s.status="OPERATIONAL",s.ipAddresses.forEach((o)=>{if(!o.ip)o.ip=`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`})},100),s}createInboundEndpoint(n){return this.createResolverEndpoint({name:n.name,direction:"INBOUND",ipAddresses:n.subnetIds.map((i)=>({subnetId:i})),securityGroupIds:n.securityGroupIds})}createOutboundEndpoint(n){return this.createResolverEndpoint({name:n.name,direction:"OUTBOUND",ipAddresses:n.subnetIds.map((i)=>({subnetId:i})),securityGroupIds:n.securityGroupIds})}createResolverRule(n){let i=`rule-${Date.now()}-${this.ruleCounter++}`,s={id:i,status:"CREATING",...n};return this.rules.set(i,s),setTimeout(()=>{s.status="COMPLETE"},100),s}createForwardRule(n){return this.createResolverRule({name:n.name,ruleType:"FORWARD",domainName:n.domainName,targetIps:n.targetIps,resolverEndpointId:n.resolverEndpointId})}createSystemRule(n){return this.createResolverRule({name:n.name,ruleType:"SYSTEM",domainName:n.domainName})}createFirewallDomainList(n){let i=`domain-list-${Date.now()}-${this.domainListCounter++}`,s={id:i,status:"CREATING",...n};return this.domainLists.set(i,s),setTimeout(()=>{s.status="COMPLETE"},100),s}createFirewallRuleGroup(n){let i=`rule-group-${Date.now()}-${this.ruleGroupCounter++}`,s={id:i,name:n.name,rules:n.rules.map((o,c)=>({id:`rule-${i}-${c}`,...o})),shareStatus:"NOT_SHARED"};return this.ruleGroups.set(i,s),s}createBlockRule(n){return this.createFirewallRuleGroup({name:n.name,rules:[{name:n.name,priority:n.priority,action:"BLOCK",blockResponse:n.blockResponse||"NODATA",blockOverrideDomain:n.blockOverrideDomain,firewallDomainListId:n.domainListId}]})}createAllowRule(n){return this.createFirewallRuleGroup({name:n.name,rules:[{name:n.name,priority:n.priority,action:"ALLOW",firewallDomainListId:n.domainListId}]})}createDNSFirewall(n){let i=`firewall-${Date.now()}-${this.firewallCounter++}`,s={id:i,name:n.name,firewallRuleGroupAssociations:n.ruleGroupAssociations.map((o,c)=>({id:`assoc-${i}-${c}`,vpcId:n.vpcId,firewallRuleGroupId:o.firewallRuleGroupId,priority:o.priority,mutationProtection:o.mutationProtection||"DISABLED",status:"COMPLETE"}))};return this.firewalls.set(i,s),s}createMalwareProtectionFirewall(n){let i=this.createFirewallDomainList({name:`${n.name}-malware-domains`,domains:n.maliciousDomains}),s=this.createBlockRule({name:`${n.name}-block-malware`,priority:100,domainListId:i.id,blockResponse:"NXDOMAIN"});return this.createDNSFirewall({name:n.name,vpcId:n.vpcId,ruleGroupAssociations:[{firewallRuleGroupId:s.id,priority:100,mutationProtection:"ENABLED"}]})}getEndpoint(n){return this.endpoints.get(n)}listEndpoints(n){let i=Array.from(this.endpoints.values());return n?i.filter((s)=>s.direction===n):i}getRule(n){return this.rules.get(n)}listRules(){return Array.from(this.rules.values())}getFirewall(n){return this.firewalls.get(n)}listFirewalls(){return Array.from(this.firewalls.values())}generateResolverEndpointCF(n){return{Type:"AWS::Route53Resolver::ResolverEndpoint",Properties:{Name:n.name,Direction:n.direction,IpAddresses:n.ipAddresses.map((i)=>({SubnetId:i.subnetId,...i.ip&&{Ip:i.ip}})),SecurityGroupIds:n.securityGroupIds}}}generateResolverRuleCF(n){return{Type:"AWS::Route53Resolver::ResolverRule",Properties:{Name:n.name,RuleType:n.ruleType,DomainName:n.domainName,...n.targetIps&&{TargetIps:n.targetIps.map((i)=>({Ip:i.ip,Port:i.port||53}))},...n.resolverEndpointId&&{ResolverEndpointId:n.resolverEndpointId}}}}generateFirewallRuleGroupCF(n){return{Type:"AWS::Route53Resolver::FirewallRuleGroup",Properties:{Name:n.name,FirewallRules:n.rules.map((i)=>({Name:i.name,Priority:i.priority,Action:i.action,FirewallDomainListId:i.firewallDomainListId,...i.blockResponse&&{BlockResponse:i.blockResponse},...i.blockOverrideDomain&&{BlockOverrideDomain:i.blockOverrideDomain},...i.blockOverrideTTL&&{BlockOverrideTtl:i.blockOverrideTTL}}))}}}clear(){this.endpoints.clear(),this.rules.clear(),this.firewalls.clear(),this.ruleGroups.clear(),this.domainLists.clear(),this.endpointCounter=0,this.ruleCounter=0,this.firewallCounter=0,this.ruleGroupCounter=0,this.domainListCounter=0}}var NE=new bm;class vm{bounces=new Map;complaints=new Map;handlers=new Map;suppressionList=new Map;metrics=new Map;bounceCounter=0;complaintCounter=0;handlerCounter=0;suppressionCounter=0;metricsCounter=0;recordBounce(n){let i=`bounce-${Date.now()}-${this.bounceCounter++}`,s={id:i,...n};if(this.bounces.set(i,s),n.bounceType==="Permanent")this.addToSuppressionList({emailAddress:n.recipient,reason:"BOUNCE"});return s}recordComplaint(n){let i=`complaint-${Date.now()}-${this.complaintCounter++}`,s={id:i,...n};this.complaints.set(i,s);for(let o of n.recipients)this.addToSuppressionList({emailAddress:o,reason:"COMPLAINT"});return s}createBounceHandler(n){let i=`handler-${Date.now()}-${this.handlerCounter++}`,s={id:i,...n};return this.handlers.set(i,s),s}createAutomaticBounceHandler(n){return this.createBounceHandler({name:n.name,bounceThreshold:5,complaintThreshold:0.1,suppressionDuration:2592000,autoSuppress:!0,notificationTopicArn:n.notificationTopicArn})}addToSuppressionList(n){let i=`suppression-${Date.now()}-${this.suppressionCounter++}`,s=n.expirationDays?new Date(Date.now()+n.expirationDays*24*60*60*1000):void 0,o={id:i,emailAddress:n.emailAddress,reason:n.reason,suppressedAt:new Date,expiresAt:s,bounceCount:n.reason==="BOUNCE"?1:0,complaintCount:n.reason==="COMPLAINT"?1:0};return this.suppressionList.set(n.emailAddress,o),o}removeFromSuppressionList(n){return this.suppressionList.delete(n)}isSuppressed(n){let i=this.suppressionList.get(n);if(!i)return!1;if(i.expiresAt&&i.expiresAt<new Date)return this.suppressionList.delete(n),!1;return!0}getBounceStatistics(n,i){let s=Array.from(this.bounces.values()).filter((b)=>b.timestamp>=n&&b.timestamp<=i),o=s.length,c=s.filter((b)=>b.bounceType==="Permanent").length,l=s.filter((b)=>b.bounceType==="Transient").length,u=o*10,h=o/u*100,y=new Map;for(let b of s)y.set(b.recipient,(y.get(b.recipient)||0)+1);let f=Array.from(y.entries()).map(([b,C])=>({email:b,count:C})).sort((b,C)=>C.count-b.count).slice(0,10);return{totalBounces:o,permanentBounces:c,transientBounces:l,bounceRate:h,topRecipients:f}}getComplaintStatistics(n,i){let s=Array.from(this.complaints.values()).filter((y)=>y.timestamp>=n&&y.timestamp<=i),o=s.length,c=new Set;for(let y of s)for(let f of y.recipients)c.add(f);let l=c.size,u=o*1000,h=o/u*100;return{totalComplaints:o,uniqueComplainters:l,complaintRate:h}}calculateReputationMetrics(){let n=`metrics-${Date.now()}-${this.metricsCounter++}`,i=new Date,s=new Date(i.getTime()-86400000),o=this.getBounceStatistics(s,i),c=this.getComplaintStatistics(s,i),l;if(o.bounceRate>10||c.complaintRate>0.5)l="Shutdown";else if(o.bounceRate>5||c.complaintRate>0.1)l="Probation";else if(o.bounceRate>2||c.complaintRate>0.05)l="Warning";else l="Good";let u={id:n,timestamp:i,bounceRate:o.bounceRate,complaintRate:c.complaintRate,sendingQuota:50000,maxSendRate:14,sentLast24Hours:o.totalBounces*10,reputationStatus:l};return this.metrics.set(n,u),u}getBounces(n){let i=Array.from(this.bounces.values());return n?i.filter((s)=>s.messageId===n):i}getComplaints(n){let i=Array.from(this.complaints.values());return n?i.filter((s)=>s.messageId===n):i}listSuppressionList(n){let i=Array.from(this.suppressionList.values());return n?i.filter((s)=>s.reason===n):i}generateSNSSubscriptionCF(n){return{Type:"AWS::SNS::Subscription",Properties:{TopicArn:n.topicArn,Endpoint:n.endpoint,Protocol:n.protocol}}}generateEventDestinationCF(n){return{Type:"AWS::SES::ConfigurationSetEventDestination",Properties:{ConfigurationSetName:n.configurationSetName,EventDestination:{Name:n.eventDestinationName,Enabled:!0,MatchingEventTypes:n.eventTypes,...n.snsTopicArn&&{SnsDestination:{TopicARN:n.snsTopicArn}},...n.cloudWatchDestination&&{CloudWatchDestination:n.cloudWatchDestination}}}}}clear(){this.bounces.clear(),this.complaints.clear(),this.handlers.clear(),this.suppressionList.clear(),this.metrics.clear(),this.bounceCounter=0,this.complaintCounter=0,this.handlerCounter=0,this.suppressionCounter=0,this.metricsCounter=0}}var kE=new vm;class Tm{events=new Map;campaigns=new Map;reports=new Map;abTests=new Map;eventCounter=0;campaignCounter=0;reportCounter=0;abTestCounter=0;trackEvent(n){let i=`event-${Date.now()}-${this.eventCounter++}`,s={id:i,...n};if(this.events.set(i,s),n.tags?.campaignId)this.updateCampaignStats(n.tags.campaignId,n.eventType);return s}trackOpen(n){return this.trackEvent({...n,eventType:"open",timestamp:new Date})}trackClick(n){return this.trackEvent({...n,eventType:"click",timestamp:new Date})}createCampaign(n){let i=`campaign-${Date.now()}-${this.campaignCounter++}`,s={id:i,sentCount:0,deliveredCount:0,openCount:0,clickCount:0,bounceCount:0,complaintCount:0,createdAt:new Date,...n};return this.campaigns.set(i,s),s}updateCampaignStats(n,i){let s=this.campaigns.get(n);if(!s)return;switch(i){case"send":s.sentCount++;break;case"delivery":s.deliveredCount++;break;case"open":s.openCount++;break;case"click":s.clickCount++;break;case"bounce":s.bounceCount++;break;case"complaint":s.complaintCount++;break}}generateReport(n){let i=`report-${Date.now()}-${this.reportCounter++}`,s=Array.from(this.events.values()).filter((R)=>{let _=R.timestamp>=n.startDate&&R.timestamp<=n.endDate,B=!n.campaignId||R.tags?.campaignId===n.campaignId;return _&&B}),o=s.filter((R)=>R.eventType==="send").length,c=s.filter((R)=>R.eventType==="delivery").length,l=s.filter((R)=>R.eventType==="open").length,u=s.filter((R)=>R.eventType==="click").length,h=s.filter((R)=>R.eventType==="bounce").length,y=s.filter((R)=>R.eventType==="complaint").length,f=o>0?c/o*100:0,b=c>0?l/c*100:0,C=c>0?u/c*100:0,T=l>0?u/l*100:0,w=o>0?h/o*100:0,E=c>0?y/c*100:0,I=new Map;for(let R of s)if(R.eventType==="click"){let _=R;I.set(_.link,(I.get(_.link)||0)+1)}let N=Array.from(I.entries()).map(([R,_])=>({link:R,clicks:_})).sort((R,_)=>_.clicks-R.clicks).slice(0,10),D={desktop:0,mobile:0,tablet:0,unknown:0};for(let R of s)if(R.eventType==="open"||R.eventType==="click"){let _=R.userAgent.toLowerCase();if(_.includes("mobile"))D.mobile++;else if(_.includes("tablet"))D.tablet++;else if(_.includes("mozilla"))D.desktop++;else D.unknown++}let x={id:i,campaignId:n.campaignId,startDate:n.startDate,endDate:n.endDate,totalSent:o,totalDelivered:c,totalOpened:l,totalClicked:u,totalBounced:h,totalComplaints:y,deliveryRate:f,openRate:b,clickRate:C,clickToOpenRate:T,bounceRate:w,complaintRate:E,topLinks:N,deviceBreakdown:D,locationBreakdown:{}};return this.reports.set(i,x),x}createABTest(n){let i=`abtest-${Date.now()}-${this.abTestCounter++}`,s={id:i,name:n.name,variants:n.variants.map((o,c)=>({id:`variant-${i}-${c}`,sentCount:0,openCount:0,clickCount:0,conversionCount:0,...o})),status:"draft"};return this.abTests.set(i,s),s}startABTest(n){let i=this.abTests.get(n);if(!i)throw Error(`A/B test not found: ${n}`);return i.status="running",i.startedAt=new Date,i}completeABTest(n){let i=this.abTests.get(n);if(!i)throw Error(`A/B test not found: ${n}`);let s=i.variants[0],o=0;for(let c of i.variants){let l=c.sentCount>0?c.openCount/c.sentCount:0;if(l>o)o=l,s=c}return i.status="completed",i.completedAt=new Date,i.winner=s.id,i}getCampaign(n){return this.campaigns.get(n)}listCampaigns(){return Array.from(this.campaigns.values())}getEvents(n){let i=Array.from(this.events.values());if(n?.messageId)i=i.filter((s)=>s.messageId===n.messageId);if(n?.eventType)i=i.filter((s)=>s.eventType===n.eventType);if(n?.startDate)i=i.filter((s)=>s.timestamp>=n.startDate);if(n?.endDate)i=i.filter((s)=>s.timestamp<=n.endDate);return i}generateTrackingConfigurationCF(n){return{Type:"AWS::SES::ConfigurationSet",Properties:{Name:n.configurationSetName,...n.openTracking&&{TrackingOptions:{CustomRedirectDomain:"tracking.example.com"}}}}}clear(){this.events.clear(),this.campaigns.clear(),this.reports.clear(),this.abTests.clear(),this.eventCounter=0,this.campaignCounter=0,this.reportCounter=0,this.abTestCounter=0}}var BE=new Tm;class wm{dashboards=new Map;warmupPlans=new Map;domainReputations=new Map;dashboardCounter=0;warmupCounter=0;domainCounter=0;getReputationDashboard(){let n=`dashboard-${Date.now()}-${this.dashboardCounter++}`,i=Math.random()*5,s=Math.random()*0.5,o=Math.floor(Math.random()*10),c=Math.max(0,100-i*10-s*100-o*2),l=[];if(i>2)l.push("Reduce bounce rate by cleaning email list");if(s>0.1)l.push("Review email content and unsubscribe process");if(o>5)l.push("Improve email relevance and targeting");let u={id:n,timestamp:new Date,overallScore:c,bounceRate:i,complaintRate:s,spamReports:o,blacklistStatus:this.checkBlacklists(),dkimStatus:"VERIFIED",spfStatus:"PASS",dmarcStatus:"PASS",sendingLimits:{maxSendRate:14,max24HourSend:50000,sentLast24Hours:12000,remainingQuota:38000,quotaResetTime:new Date(Date.now()+86400000)},recommendations:l};return this.dashboards.set(n,u),u}checkBlacklists(){return["Spamhaus ZEN","Spamcop","SORBS","Barracuda","URIBL"].map((n)=>({listName:n,listed:Math.random()>0.95,delistUrl:`https://www.${n.toLowerCase().replace(/\s/g,"")}.org/delist`}))}createWarmupPlan(n){let i=`warmup-${Date.now()}-${this.warmupCounter++}`,s=[],o=(n.targetDailyLimit-n.initialDailyLimit)/n.durationDays;for(let l=0;l<n.durationDays;l++)s.push(Math.floor(n.initialDailyLimit+o*l));let c={id:i,name:n.name,startDate:new Date,currentDay:1,totalDays:n.durationDays,dailyLimits:s,currentLimit:s[0],status:"active"};return this.warmupPlans.set(i,c),c}createAggressiveWarmupPlan(n){return this.createWarmupPlan({name:n.name,initialDailyLimit:500,targetDailyLimit:50000,durationDays:14})}createConservativeWarmupPlan(n){return this.createWarmupPlan({name:n.name,initialDailyLimit:200,targetDailyLimit:50000,durationDays:30})}advanceWarmupPlan(n){let i=this.warmupPlans.get(n);if(!i)throw Error(`Warmup plan not found: ${n}`);if(i.currentDay<i.totalDays)i.currentDay++,i.currentLimit=i.dailyLimits[i.currentDay-1];if(i.currentDay>=i.totalDays)i.status="completed";return i}trackDomainReputation(n){let i=`domain-${Date.now()}-${this.domainCounter++}`,s=n.delivered/n.totalSent*100,o=n.delivered>0?n.opened/n.delivered*100:0,c=n.delivered>0?n.clicked/n.delivered*100:0,l=n.bounced/n.totalSent*100,u=n.delivered>0?n.complained/n.delivered*100:0,h=o*0.4+c*0.6,y=Math.max(0,100-l*10-u*100+h*0.2),f={id:i,domain:n.domain,reputationScore:y,totalSent:n.totalSent,deliveryRate:s,openRate:o,clickRate:c,bounceRate:l,complaintRate:u,engagementScore:h};return this.domainReputations.set(n.domain,f),f}getDomainReputation(n){return this.domainReputations.get(n)}listDomainReputations(){return Array.from(this.domainReputations.values())}getWarmupPlan(n){return this.warmupPlans.get(n)}listWarmupPlans(){return Array.from(this.warmupPlans.values())}clear(){this.dashboards.clear(),this.warmupPlans.clear(),this.domainReputations.clear(),this.dashboardCounter=0,this.warmupCounter=0,this.domainCounter=0}}var _E=new wm;class Rm{templates=new Map;versions=new Map;tests=new Map;templateCounter=0;testCounter=0;createTemplate(n){let i=`template-${Date.now()}-${this.templateCounter++}`,s=this.extractVariables(n.subject+n.htmlPart+n.textPart),o={id:i,variables:s,createdAt:new Date,updatedAt:new Date,version:1,...n};return this.templates.set(i,o),this.addVersion({templateId:i,version:1,subject:n.subject,htmlPart:n.htmlPart,textPart:n.textPart,createdBy:"system"}),o}createWelcomeTemplate(n){return this.createTemplate({name:n.name,subject:"Welcome to {{companyName}}!",htmlPart:`
3777
3777
  <html>
3778
3778
  <body>
3779
3779
  <h1>Welcome, {{userName}}!</h1>
@@ -3793,7 +3793,7 @@ COPY . .`,impact:"Improve build time by 60-80% on subsequent builds"});let h={si
3793
3793
  <p>If you didn't request this, please ignore this email.</p>
3794
3794
  </body>
3795
3795
  </html>
3796
- `,textPart:"Hi {{userName}}, reset your password at: {{resetUrl}}. This link expires in {{expirationHours}} hours."})}updateTemplate(n,i,s){let o=this.templates.get(n);if(!o)throw Error(`Template not found: ${n}`);if(i.subject)o.subject=i.subject;if(i.htmlPart)o.htmlPart=i.htmlPart;if(i.textPart)o.textPart=i.textPart;return o.version++,o.updatedAt=new Date,o.variables=this.extractVariables(o.subject+o.htmlPart+o.textPart),this.addVersion({templateId:n,version:o.version,subject:o.subject,htmlPart:o.htmlPart,textPart:o.textPart,createdBy:"system",changelog:s}),o}addVersion(n){let i={id:`version-${n.templateId}-${n.version}`,createdAt:new Date,...n},s=this.versions.get(n.templateId)||[];return s.push(i),this.versions.set(n.templateId,s),i}extractVariables(n){let i=/\{\{([^}]+)\}\}/g,s=new Set,o;while((o=i.exec(n))!==null)s.add(o[1].trim());return Array.from(s)}renderTemplate(n,i){let s=this.templates.get(n);if(!s)throw Error(`Template not found: ${n}`);let o=(c)=>c.replace(/\{\{([^}]+)\}\}/g,(l,u)=>{let h=u.trim();return i[h]!==void 0?String(i[h]):l});return{subject:o(s.subject),html:o(s.htmlPart),text:o(s.textPart)}}testTemplate(n,i){let s=`test-${Date.now()}-${this.testCounter++}`,o=this.renderTemplate(n,i),c={id:s,templateId:n,testData:i,renderedSubject:o.subject,renderedHtml:o.html,renderedText:o.text,timestamp:new Date};return this.tests.set(s,c),c}getTemplate(n){return this.templates.get(n)}listTemplates(){return Array.from(this.templates.values())}getTemplateVersions(n){return this.versions.get(n)||[]}revertToVersion(n,i){let s=this.templates.get(n);if(!s)throw Error(`Template not found: ${n}`);let o=(this.versions.get(n)||[]).find((c)=>c.version===i);if(!o)throw Error(`Version ${i} not found for template ${n}`);return s.subject=o.subject,s.htmlPart=o.htmlPart,s.textPart=o.textPart,s.version++,s.updatedAt=new Date,this.addVersion({templateId:n,version:s.version,subject:s.subject,htmlPart:s.htmlPart,textPart:s.textPart,createdBy:"system",changelog:`Reverted to version ${i}`}),s}generateTemplateCF(n){return{Type:"AWS::SES::Template",Properties:{Template:{TemplateName:n.name,SubjectPart:n.subject,HtmlPart:n.htmlPart,TextPart:n.textPart}}}}clear(){this.templates.clear(),this.versions.clear(),this.tests.clear(),this.templateCounter=0,this.testCounter=0}}var BE=new Tm,QA={};We(QA,{EmailAnalyticsModule:()=>tt,EmailRules:()=>aa,EmailScheduling:()=>ea,EmailSearch:()=>Zt,EmailTemplates:()=>ke,EmailThreading:()=>Xt,SharedMailboxes:()=>ta});class Zt{static createSearchDomain(n){let{slug:i,environment:s,domainName:o,instanceType:c="t3.small.search",instanceCount:l=1,ebsVolumeSize:u=10,masterUserName:h="admin",masterUserPassword:y}=n,f=o||`${i}-${s}-email-search`;return{[`${i}EmailSearchDomain`]:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:f,EngineVersion:"OpenSearch_2.11",ClusterConfig:{InstanceType:c,InstanceCount:l,DedicatedMasterEnabled:!1,ZoneAwarenessEnabled:!1},EBSOptions:{EBSEnabled:!0,VolumeType:"gp3",VolumeSize:u},NodeToNodeEncryptionOptions:{Enabled:!0},EncryptionAtRestOptions:{Enabled:!0},DomainEndpointOptions:{EnforceHTTPS:!0},AdvancedSecurityOptions:{Enabled:!0,InternalUserDatabaseEnabled:!0,MasterUserOptions:{MasterUserName:h,MasterUserPassword:y||`${i}-search-${Date.now()}`}},AccessPolicies:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:`arn:aws:es:*:*:domain/${f}/*`}]}}}}}static createIndexerLambda(n){return{[`${n.slug}EmailIndexerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-email-indexer`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:60,MemorySize:512,Code:{ZipFile:Zt.IndexerLambdaCode},Environment:{Variables:{OPENSEARCH_ENDPOINT:n.searchDomainEndpoint,EMAIL_BUCKET:n.emailBucket}}}}}}static IndexerLambdaCode=`
3796
+ `,textPart:"Hi {{userName}}, reset your password at: {{resetUrl}}. This link expires in {{expirationHours}} hours."})}updateTemplate(n,i,s){let o=this.templates.get(n);if(!o)throw Error(`Template not found: ${n}`);if(i.subject)o.subject=i.subject;if(i.htmlPart)o.htmlPart=i.htmlPart;if(i.textPart)o.textPart=i.textPart;return o.version++,o.updatedAt=new Date,o.variables=this.extractVariables(o.subject+o.htmlPart+o.textPart),this.addVersion({templateId:n,version:o.version,subject:o.subject,htmlPart:o.htmlPart,textPart:o.textPart,createdBy:"system",changelog:s}),o}addVersion(n){let i={id:`version-${n.templateId}-${n.version}`,createdAt:new Date,...n},s=this.versions.get(n.templateId)||[];return s.push(i),this.versions.set(n.templateId,s),i}extractVariables(n){let i=/\{\{([^}]+)\}\}/g,s=new Set,o;while((o=i.exec(n))!==null)s.add(o[1].trim());return Array.from(s)}renderTemplate(n,i){let s=this.templates.get(n);if(!s)throw Error(`Template not found: ${n}`);let o=(c)=>c.replace(/\{\{([^}]+)\}\}/g,(l,u)=>{let h=u.trim();return i[h]!==void 0?String(i[h]):l});return{subject:o(s.subject),html:o(s.htmlPart),text:o(s.textPart)}}testTemplate(n,i){let s=`test-${Date.now()}-${this.testCounter++}`,o=this.renderTemplate(n,i),c={id:s,templateId:n,testData:i,renderedSubject:o.subject,renderedHtml:o.html,renderedText:o.text,timestamp:new Date};return this.tests.set(s,c),c}getTemplate(n){return this.templates.get(n)}listTemplates(){return Array.from(this.templates.values())}getTemplateVersions(n){return this.versions.get(n)||[]}revertToVersion(n,i){let s=this.templates.get(n);if(!s)throw Error(`Template not found: ${n}`);let o=(this.versions.get(n)||[]).find((c)=>c.version===i);if(!o)throw Error(`Version ${i} not found for template ${n}`);return s.subject=o.subject,s.htmlPart=o.htmlPart,s.textPart=o.textPart,s.version++,s.updatedAt=new Date,this.addVersion({templateId:n,version:s.version,subject:s.subject,htmlPart:s.htmlPart,textPart:s.textPart,createdBy:"system",changelog:`Reverted to version ${i}`}),s}generateTemplateCF(n){return{Type:"AWS::SES::Template",Properties:{Template:{TemplateName:n.name,SubjectPart:n.subject,HtmlPart:n.htmlPart,TextPart:n.textPart}}}}clear(){this.templates.clear(),this.versions.clear(),this.tests.clear(),this.templateCounter=0,this.testCounter=0}}var xE=new Rm,GA={};Ge(GA,{EmailAnalyticsModule:()=>tt,EmailRules:()=>aa,EmailScheduling:()=>ea,EmailSearch:()=>Zt,EmailTemplates:()=>ke,EmailThreading:()=>Xt,SharedMailboxes:()=>ta});class Zt{static createSearchDomain(n){let{slug:i,environment:s,domainName:o,instanceType:c="t3.small.search",instanceCount:l=1,ebsVolumeSize:u=10,masterUserName:h="admin",masterUserPassword:y}=n,f=o||`${i}-${s}-email-search`;return{[`${i}EmailSearchDomain`]:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:f,EngineVersion:"OpenSearch_2.11",ClusterConfig:{InstanceType:c,InstanceCount:l,DedicatedMasterEnabled:!1,ZoneAwarenessEnabled:!1},EBSOptions:{EBSEnabled:!0,VolumeType:"gp3",VolumeSize:u},NodeToNodeEncryptionOptions:{Enabled:!0},EncryptionAtRestOptions:{Enabled:!0},DomainEndpointOptions:{EnforceHTTPS:!0},AdvancedSecurityOptions:{Enabled:!0,InternalUserDatabaseEnabled:!0,MasterUserOptions:{MasterUserName:h,MasterUserPassword:y||`${i}-search-${Date.now()}`}},AccessPolicies:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:`arn:aws:es:*:*:domain/${f}/*`}]}}}}}static createIndexerLambda(n){return{[`${n.slug}EmailIndexerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-email-indexer`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:60,MemorySize:512,Code:{ZipFile:Zt.IndexerLambdaCode},Environment:{Variables:{OPENSEARCH_ENDPOINT:n.searchDomainEndpoint,EMAIL_BUCKET:n.emailBucket}}}}}}static IndexerLambdaCode=`
3797
3797
  const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
3798
3798
  const https = require('https');
3799
3799
 
@@ -5164,7 +5164,7 @@ async function invokeLambda(functionName, metadata) {
5164
5164
  Payload: JSON.stringify(metadata),
5165
5165
  }));
5166
5166
  }
5167
- `;static createRulesTable(n){return{[`${n.slug}EmailRulesTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-email-rules`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"mailbox",AttributeType:"S"},{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"mailbox",KeyType:"HASH"},{AttributeName:"id",KeyType:"RANGE"}]}}}}static createRuleProcessorLambda(n){return{[`${n.slug}EmailRuleProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-email-rule-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:aa.RuleProcessorCode},Environment:{Variables:{EMAIL_BUCKET:n.emailBucket,RULES_TABLE:n.rulesTable}}}}}}static RuleTemplates={spamFilter:{name:"Spam Filter",conditions:[{field:"subject",operator:"regex",value:"(viagra|lottery|winner|prince|inheritance)",caseSensitive:!1}],conditionOperator:"or",actions:[{type:"move",params:{folder:"spam"}},{type:"mark-read",params:{}}]},autoLabel:{name:"Auto Label Invoices",conditions:[{field:"subject",operator:"contains",value:"invoice",caseSensitive:!1}],conditionOperator:"and",actions:[{type:"label",params:{label:"invoices"}}]},forwardUrgent:{name:"Forward Urgent",conditions:[{field:"subject",operator:"contains",value:"urgent",caseSensitive:!1}],conditionOperator:"and",actions:[{type:"forward",params:{to:"admin@example.com"}},{type:"label",params:{label:"urgent"}}]}}}var HA={};We(HA,{default:()=>Hn,handler:()=>qn});var qn=`
5167
+ `;static createRulesTable(n){return{[`${n.slug}EmailRulesTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-email-rules`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"mailbox",AttributeType:"S"},{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"mailbox",KeyType:"HASH"},{AttributeName:"id",KeyType:"RANGE"}]}}}}static createRuleProcessorLambda(n){return{[`${n.slug}EmailRuleProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-email-rule-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:aa.RuleProcessorCode},Environment:{Variables:{EMAIL_BUCKET:n.emailBucket,RULES_TABLE:n.rulesTable}}}}}}static RuleTemplates={spamFilter:{name:"Spam Filter",conditions:[{field:"subject",operator:"regex",value:"(viagra|lottery|winner|prince|inheritance)",caseSensitive:!1}],conditionOperator:"or",actions:[{type:"move",params:{folder:"spam"}},{type:"mark-read",params:{}}]},autoLabel:{name:"Auto Label Invoices",conditions:[{field:"subject",operator:"contains",value:"invoice",caseSensitive:!1}],conditionOperator:"and",actions:[{type:"label",params:{label:"invoices"}}]},forwardUrgent:{name:"Forward Urgent",conditions:[{field:"subject",operator:"contains",value:"urgent",caseSensitive:!1}],conditionOperator:"and",actions:[{type:"forward",params:{to:"admin@example.com"}},{type:"label",params:{label:"urgent"}}]}}}var qA={};Ge(qA,{default:()=>Hn,handler:()=>qn});var qn=`
5168
5168
  const { S3Client, GetObjectCommand, PutObjectCommand, CopyObjectCommand } = require('@aws-sdk/client-s3');
5169
5169
  const s3 = new S3Client({});
5170
5170
 
@@ -5480,7 +5480,7 @@ catch (error) {
5480
5480
 
5481
5481
  return { statusCode: 200, body: 'OK' };
5482
5482
  };
5483
- `,GA={};We(GA,{CallAnalytics:()=>na,CallRecording:()=>ra,Callbacks:()=>At,IVRBuilder:()=>Be});class ra{static RecordingProcessorCode=`
5483
+ `,VA={};Ge(VA,{CallAnalytics:()=>na,CallRecording:()=>ra,Callbacks:()=>bt,IVRBuilder:()=>Be});class ra{static RecordingProcessorCode=`
5484
5484
  const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
5485
5485
  const { TranscribeClient, StartTranscriptionJobCommand } = require('@aws-sdk/client-transcribe');
5486
5486
  const { DynamoDBClient, PutItemCommand, UpdateItemCommand } = require('@aws-sdk/client-dynamodb');
@@ -5871,7 +5871,7 @@ catch (error) {
5871
5871
  };
5872
5872
  }
5873
5873
  };
5874
- `;static createMetricsTable(n){return{[`${n.slug}CallMetricsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-call-metrics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"period",AttributeType:"S"}],KeySchema:[{AttributeName:"period",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createMetricsAggregatorLambda(n){return{[`${n.slug}CallMetricsAggregatorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-call-metrics-aggregator`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:na.MetricsAggregatorCode},Environment:{Variables:{CALL_LOG_TABLE:n.callLogTable,METRICS_TABLE:n.metricsTable}}}}}}static createMetricsSchedule(n){return{[`${n.slug}CallMetricsSchedule`]:{Type:"AWS::Events::Rule",Properties:{Name:`${n.slug}-call-metrics-schedule`,Description:"Aggregate call metrics hourly",ScheduleExpression:"rate(1 hour)",State:"ENABLED",Targets:[{Id:"MetricsAggregatorTarget",Arn:n.lambdaArn}]}}}}}class At{static CallbackRequestCode=`
5874
+ `;static createMetricsTable(n){return{[`${n.slug}CallMetricsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-call-metrics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"period",AttributeType:"S"}],KeySchema:[{AttributeName:"period",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createMetricsAggregatorLambda(n){return{[`${n.slug}CallMetricsAggregatorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-call-metrics-aggregator`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:na.MetricsAggregatorCode},Environment:{Variables:{CALL_LOG_TABLE:n.callLogTable,METRICS_TABLE:n.metricsTable}}}}}}static createMetricsSchedule(n){return{[`${n.slug}CallMetricsSchedule`]:{Type:"AWS::Events::Rule",Properties:{Name:`${n.slug}-call-metrics-schedule`,Description:"Aggregate call metrics hourly",ScheduleExpression:"rate(1 hour)",State:"ENABLED",Targets:[{Id:"MetricsAggregatorTarget",Arn:n.lambdaArn}]}}}}}class bt{static CallbackRequestCode=`
5875
5875
  const { DynamoDBClient, PutItemCommand, UpdateItemCommand } = require('@aws-sdk/client-dynamodb');
5876
5876
  const { ConnectClient, StartOutboundVoiceContactCommand } = require('@aws-sdk/client-connect');
5877
5877
  const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');
@@ -6161,7 +6161,7 @@ catch (error) {
6161
6161
  return { statusCode: 500, error: error.message };
6162
6162
  }
6163
6163
  };
6164
- `;static createCallbacksTable(n){return{[`${n.slug}CallbacksTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-callbacks`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createCallbackRequestLambda(n){return{[`${n.slug}CallbackRequestLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-callback-request`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:At.CallbackRequestCode},Environment:{Variables:{CALLBACKS_TABLE:n.callbacksTable,NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||""}}}}}}static createCallbackProcessorLambda(n){return{[`${n.slug}CallbackProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-callback-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:300,MemorySize:256,Code:{ZipFile:At.CallbackProcessorCode},Environment:{Variables:{CALLBACKS_TABLE:n.callbacksTable,CONNECT_INSTANCE_ID:n.connectInstanceId,CONTACT_FLOW_ID:n.contactFlowId,SOURCE_PHONE_NUMBER:n.sourcePhoneNumber,QUEUE_ID:n.queueId||""}}}}}}}var qA={};We(qA,{AbTesting:()=>Ee,LinkTracking:()=>la,MmsSupport:()=>oa,SmsAnalytics:()=>sa,SmsCampaigns:()=>ia,SmsChatbot:()=>ca});class ia{static CampaignManagerCode=`
6164
+ `;static createCallbacksTable(n){return{[`${n.slug}CallbacksTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-callbacks`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createCallbackRequestLambda(n){return{[`${n.slug}CallbackRequestLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-callback-request`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:bt.CallbackRequestCode},Environment:{Variables:{CALLBACKS_TABLE:n.callbacksTable,NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||""}}}}}}static createCallbackProcessorLambda(n){return{[`${n.slug}CallbackProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-callback-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:300,MemorySize:256,Code:{ZipFile:bt.CallbackProcessorCode},Environment:{Variables:{CALLBACKS_TABLE:n.callbacksTable,CONNECT_INSTANCE_ID:n.connectInstanceId,CONTACT_FLOW_ID:n.contactFlowId,SOURCE_PHONE_NUMBER:n.sourcePhoneNumber,QUEUE_ID:n.queueId||""}}}}}}}var jA={};Ge(jA,{AbTesting:()=>Te,LinkTracking:()=>la,MmsSupport:()=>oa,SmsAnalytics:()=>sa,SmsCampaigns:()=>ia,SmsChatbot:()=>ca});class ia{static CampaignManagerCode=`
6165
6165
  const { DynamoDBClient, PutItemCommand, GetItemCommand, UpdateItemCommand, ScanCommand } = require('@aws-sdk/client-dynamodb');
6166
6166
 
6167
6167
  const dynamodb = new DynamoDBClient({});
@@ -7067,7 +7067,7 @@ function generateShortId() {
7067
7067
  }
7068
7068
  return id;
7069
7069
  }
7070
- `;static createLinksTable(n){return{[`${n.slug}ShortLinksTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-short-links`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createLinkShortenerLambda(n){return{[`${n.slug}LinkShortenerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-link-shortener`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:10,MemorySize:128,Code:{ZipFile:la.LinkShortenerCode},Environment:{Variables:{LINKS_TABLE:n.linksTable,SHORT_DOMAIN:n.shortDomain||""}}}}}}static shortenUrlsInMessage(n,i,s){let o=/(https?:\/\/[^\s]+)/g,c=[],l=0;return{message:n.replace(o,(u)=>{let h=`${s}-${l++}`,y=`https://${i}/l/${h}`;return c.push({original:u,short:y,id:h}),y}),links:c}}}class Ee{static AbTestManagerCode=`
7070
+ `;static createLinksTable(n){return{[`${n.slug}ShortLinksTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-short-links`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createLinkShortenerLambda(n){return{[`${n.slug}LinkShortenerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-link-shortener`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:10,MemorySize:128,Code:{ZipFile:la.LinkShortenerCode},Environment:{Variables:{LINKS_TABLE:n.linksTable,SHORT_DOMAIN:n.shortDomain||""}}}}}}static shortenUrlsInMessage(n,i,s){let o=/(https?:\/\/[^\s]+)/g,c=[],l=0;return{message:n.replace(o,(u)=>{let h=`${s}-${l++}`,y=`https://${i}/l/${h}`;return c.push({original:u,short:y,id:h}),y}),links:c}}}class Te{static AbTestManagerCode=`
7071
7071
  const { DynamoDBClient, PutItemCommand, GetItemCommand, UpdateItemCommand, ScanCommand } = require('@aws-sdk/client-dynamodb');
7072
7072
 
7073
7073
  const dynamodb = new DynamoDBClient({});
@@ -7261,7 +7261,7 @@ function unmarshallTest(item) {
7261
7261
 
7262
7262
  return test;
7263
7263
  }
7264
- `;static createAbTestsTable(n){return{[`${n.slug}AbTestsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-ab-tests`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}}static createAbTestManagerLambda(n){return{[`${n.slug}AbTestManagerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-ab-test-manager`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Ee.AbTestManagerCode},Environment:{Variables:{AB_TESTS_TABLE:n.abTestsTable}}}}}}static selectVariant(n,i){let s=Ee.hashString(i+n.id)%100,o=0;for(let c=0;c<n.variants.length;c++)if(o+=n.trafficSplit[c],s<o)return n.variants[c];return n.variants[n.variants.length-1]}static determineWinner(n){if(n.variants.length===0)return null;let i=n.winningCriteria,s=n.variants[0],o=Ee.getMetricValue(s,i);for(let c of n.variants.slice(1)){let l=Ee.getMetricValue(c,i);if(l>o)o=l,s=c}return s}static calculateSignificance(n,i,s){let o=n.stats.sent,c=i.stats.sent;if(o<30||c<30)return 0;let l=Ee.getMetricValue(n,s)/100,u=Ee.getMetricValue(i,s)/100,h=(l*o+u*c)/(o+c),y=Math.sqrt(h*(1-h)*(1/o+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(n,i){switch(i){case"delivery_rate":return n.stats.deliveryRate;case"click_rate":return n.stats.clickRate;case"reply_rate":return n.stats.replyRate;case"conversion_rate":return n.stats.conversionRate;default:return n.stats.deliveryRate}}static hashString(n){let i=0;for(let s=0;s<n.length;s++){let o=n.charCodeAt(s);i=(i<<5)-i+o,i=i&i}return Math.abs(i)}}class wm{queues=new Map;messageGroups=new Map;deduplicationConfigs=new Map;messages=new Map;queueCounter=0;groupCounter=0;deduplicationCounter=0;messageCounter=0;sequenceCounter=0;createFIFOQueue(n){let i=`fifo-queue-${Date.now()}-${this.queueCounter++}`,s=n.name.endsWith(".fifo")?n.name:`${n.name}.fifo`,{name:o,...c}=n,l={id:i,name:s,queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${s}`,...c};return this.queues.set(i,l),this.createDeduplicationConfig({queueId:i,contentBasedDeduplication:n.contentBasedDeduplication,deduplicationInterval:300}),l}createHighThroughputFIFO(n){return this.createFIFOQueue({name:n.name,contentBasedDeduplication:n.contentBasedDeduplication??!0,deduplicationScope:"messageGroup",fifoThroughputLimit:"perMessageGroupId",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createStandardFIFO(n){return this.createFIFOQueue({name:n.name,contentBasedDeduplication:n.contentBasedDeduplication??!1,deduplicationScope:"queue",fifoThroughputLimit:"perQueue",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createDeduplicationConfig(n){let i={id:`dedup-${Date.now()}-${this.deduplicationCounter++}`,deduplicationHashes:new Map,...n};return this.deduplicationConfigs.set(n.queueId,i),i}sendMessage(n){let i=this.queues.get(n.queueId);if(!i)throw Error(`Queue not found: ${n.queueId}`);let s=this.deduplicationConfigs.get(n.queueId);if(s){let u=n.messageDeduplicationId||(i.contentBasedDeduplication?this.generateHash(n.messageBody):void 0);if(u&&this.isDuplicate(s,u))return null;if(u)s.deduplicationHashes.set(u,new Date)}let o=`msg-${Date.now()}-${this.messageCounter++}`,c=this.generateSequenceNumber(),l={id:o,messageId:o,messageGroupId:n.messageGroupId,messageDeduplicationId:n.messageDeduplicationId,body:n.messageBody,attributes:n.messageAttributes||{},sentTimestamp:new Date,sequenceNumber:c};return this.messages.set(o,l),this.updateMessageGroup(n.queueId,n.messageGroupId),l}isDuplicate(n,i){let s=n.deduplicationHashes.get(i);if(!s)return!1;if((Date.now()-s.getTime())/1000>n.deduplicationInterval)return n.deduplicationHashes.delete(i),!1;return!0}generateHash(n){let i=0;for(let s=0;s<n.length;s++){let o=n.charCodeAt(s);i=(i<<5)-i+o,i=i&i}return Math.abs(i).toString(36)}generateSequenceNumber(){return`${Date.now()}${this.sequenceCounter++}`.padStart(20,"0")}updateMessageGroup(n,i){let s=`${n}-${i}`,o=this.messageGroups.get(s);if(!o)o={id:`group-${Date.now()}-${this.groupCounter++}`,messageGroupId:i,queueId:n,messagesInFlight:0},this.messageGroups.set(s,o);o.messagesInFlight++,o.lastMessageTimestamp=new Date}getMessageGroups(n){return Array.from(this.messageGroups.values()).filter((i)=>i.queueId===n)}getQueue(n){return this.queues.get(n)}listQueues(){return Array.from(this.queues.values())}getMessages(n,i){let s=Array.from(this.messages.values());if(i)s=s.filter((o)=>o.messageGroupId===i);return s.sort((o,c)=>o.sequenceNumber.localeCompare(c.sequenceNumber))}generateFIFOQueueCF(n){return{Type:"AWS::SQS::Queue",Properties:{QueueName:n.name,FifoQueue:!0,ContentBasedDeduplication:n.contentBasedDeduplication,DeduplicationScope:n.deduplicationScope,FifoThroughputLimit:n.fifoThroughputLimit,MessageRetentionPeriod:n.messageRetentionPeriod,VisibilityTimeout:n.visibilityTimeout,ReceiveMessageWaitTimeSeconds:n.receiveMessageWaitTime,...n.deadLetterTargetArn&&{RedrivePolicy:{deadLetterTargetArn:n.deadLetterTargetArn,maxReceiveCount:n.maxReceiveCount||3}}}}}clear(){this.queues.clear(),this.messageGroups.clear(),this.deduplicationConfigs.clear(),this.messages.clear(),this.queueCounter=0,this.groupCounter=0,this.deduplicationCounter=0,this.messageCounter=0,this.sequenceCounter=0}}var _E=new wm;class Rm{monitors=new Map;metrics=new Map;alerts=new Map;reprocessJobs=new Map;monitorCounter=0;metricsCounter=0;alertCounter=0;jobCounter=0;createDLQMonitor(n){let i=`dlq-monitor-${Date.now()}-${this.monitorCounter++}`,s={id:i,...n};return this.monitors.set(i,s),s}createAutomatedMonitor(n){return this.createDLQMonitor({name:n.name,queueUrl:n.queueUrl,sourceQueues:n.sourceQueues,maxReceiveCount:3,alarmThreshold:10,autoReprocess:!0,reprocessStrategy:"scheduled",notificationTopicArn:n.notificationTopicArn})}collectMetrics(n){let i={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:n,timestamp:new Date,approximateNumberOfMessages:Math.floor(Math.random()*100),approximateAgeOfOldestMessage:Math.floor(Math.random()*86400),messagesReceived:Math.floor(Math.random()*50),messagesDeleted:Math.floor(Math.random()*30),messagesReprocessed:Math.floor(Math.random()*20)},s=this.metrics.get(n)||[];return s.push(i),this.metrics.set(n,s),this.checkForAlerts(n,i),i}checkForAlerts(n,i){let s=Array.from(this.monitors.values()).find((c)=>c.queueUrl===n);if(!s)return;if(i.approximateNumberOfMessages>=s.alarmThreshold)this.createAlert({monitorId:s.id,alertType:"threshold_exceeded",severity:"high",message:`DLQ ${s.name} has ${i.approximateNumberOfMessages} messages (threshold: ${s.alarmThreshold})`});let o=3600;if(i.approximateAgeOfOldestMessage>o)this.createAlert({monitorId:s.id,alertType:"old_message",severity:"medium",message:`DLQ ${s.name} has messages older than ${o} seconds`})}createAlert(n){let i=`alert-${Date.now()}-${this.alertCounter++}`,s={id:i,timestamp:new Date,acknowledged:!1,...n};return this.alerts.set(i,s),s}acknowledgeAlert(n){let i=this.alerts.get(n);if(!i)throw Error(`Alert not found: ${n}`);return i.acknowledged=!0,i}createReprocessJob(n){let i=`reprocess-${Date.now()}-${this.jobCounter++}`,s={id:i,queueUrl:n.queueUrl,messageId:n.messageId,attempts:0,status:"pending"};return this.reprocessJobs.set(i,s),s}async executeReprocessJob(n){let i=this.reprocessJobs.get(n);if(!i)throw Error(`Reprocess job not found: ${n}`);i.status="processing",i.startedAt=new Date,i.attempts++,await new Promise((o)=>setTimeout(o,100));let s=Math.random()>0.3;if(i.status=s?"success":"failed",i.completedAt=new Date,!s)i.error="Reprocessing failed - original error still present";return i}async batchReprocess(n){let i=[];for(let s=0;s<n.maxMessages;s++){let o=this.createReprocessJob({queueUrl:n.queueUrl,messageId:`msg-${s}`});await this.executeReprocessJob(o.id),i.push(o)}return i}getDLQStatistics(n,i=24){let s=new Date(Date.now()-i*60*60*1000),o=(this.metrics.get(n)||[]).filter((b)=>b.timestamp>=s);if(o.length===0)return{totalMessages:0,avgAge:0,messagesReceived:0,messagesDeleted:0,messagesReprocessed:0,successRate:0};let c=o[o.length-1],l=o.reduce((b,C)=>b+C.messagesReceived,0),u=o.reduce((b,C)=>b+C.messagesDeleted,0),h=o.reduce((b,C)=>b+C.messagesReprocessed,0),y=o.reduce((b,C)=>b+C.approximateAgeOfOldestMessage,0)/o.length,f=h>0?u/h*100:0;return{totalMessages:c.approximateNumberOfMessages,avgAge:y,messagesReceived:l,messagesDeleted:u,messagesReprocessed:h,successRate:f}}getMonitor(n){return this.monitors.get(n)}listMonitors(){return Array.from(this.monitors.values())}getAlerts(n,i){let s=Array.from(this.alerts.values());if(n)s=s.filter((o)=>o.monitorId===n);if(i!==void 0)s=s.filter((o)=>o.acknowledged===i);return s.sort((o,c)=>c.timestamp.getTime()-o.timestamp.getTime())}getReprocessJobs(n){let i=Array.from(this.reprocessJobs.values());if(n)i=i.filter((s)=>s.queueUrl===n);return i}generateDLQAlarmCF(n){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${n.name}-messages-alarm`,AlarmDescription:`Alert when DLQ ${n.name} exceeds threshold`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Average",Period:300,EvaluationPeriods:1,Threshold:n.alarmThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:n.queueUrl.split("/").pop()}],...n.notificationTopicArn&&{AlarmActions:[n.notificationTopicArn]}}}}clear(){this.monitors.clear(),this.metrics.clear(),this.alerts.clear(),this.reprocessJobs.clear(),this.monitorCounter=0,this.metricsCounter=0,this.alertCounter=0,this.jobCounter=0}}var xE=new Rm;class Dm{configs=new Map;jobs=new Map;metrics=new Map;configCounter=0;jobCounter=0;metricsCounter=0;createBatchConfig(n){let i=`batch-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}createHighThroughputConfig(n){return this.createBatchConfig({queueUrl:n.queueUrl,batchSize:10,maxWaitTime:100,parallelProcessors:10,retryAttempts:3,visibilityTimeout:30})}createLowLatencyConfig(n){return this.createBatchConfig({queueUrl:n.queueUrl,batchSize:1,maxWaitTime:0,parallelProcessors:5,retryAttempts:2,visibilityTimeout:10})}createBatchJob(n){let i=`batch-job-${Date.now()}-${this.jobCounter++}`;if(!this.configs.get(n.configId))throw Error(`Batch config not found: ${n.configId}`);let s=[];for(let c=0;c<n.messageCount;c++)s.push({id:`msg-${i}-${c}`,messageId:`${i}-${c}`,body:`Message ${c}`,receiptHandle:`receipt-${i}-${c}`,attributes:{},status:"pending"});let o={id:i,configId:n.configId,messages:s,status:"pending",processedCount:0,failedCount:0};return this.jobs.set(i,o),o}async processBatchJob(n){let i=this.jobs.get(n);if(!i)throw Error(`Batch job not found: ${n}`);let s=this.configs.get(i.configId);if(!s)throw Error(`Batch config not found: ${i.configId}`);i.status="processing",i.startedAt=new Date;let o=this.chunkArray(i.messages,s.batchSize);for(let c of o)await this.processBatch(c,s);return i.processedCount=i.messages.filter((c)=>c.status==="success").length,i.failedCount=i.messages.filter((c)=>c.status==="failed").length,i.status=i.failedCount===0?"completed":"failed",i.completedAt=new Date,this.collectProcessorMetrics(s.id,i),i}async processBatch(n,i){let s=n.map((o)=>this.processMessage(o,i));await Promise.all(s)}async processMessage(n,i){n.status="processing";let s=Date.now();await new Promise((c)=>setTimeout(c,Math.random()*100));let o=Date.now()-s;if(n.processingTime=o,Math.random()>0.1)n.status="success";else n.status="failed",n.error="Processing error"}chunkArray(n,i){let s=[];for(let o=0;o<n.length;o+=i)s.push(n.slice(o,o+i));return s}collectProcessorMetrics(n,i){let s=`metrics-${Date.now()}-${this.metricsCounter++}`,o=i.messages.filter((b)=>b.status==="success").map((b)=>b.processingTime||0).filter((b)=>b>0),c=o.length>0?o.reduce((b,C)=>b+C,0)/o.length:0,l=i.completedAt&&i.startedAt?(i.completedAt.getTime()-i.startedAt.getTime())/1000:1,u=i.processedCount/l,h=i.messages.length>0?i.failedCount/i.messages.length*100:0,y={id:s,configId:n,timestamp:new Date,messagesProcessed:i.processedCount,averageProcessingTime:c,throughput:u,errorRate:h},f=this.metrics.get(n)||[];f.push(y),this.metrics.set(n,f)}getBatchStatistics(n){let i=this.metrics.get(n)||[];if(i.length===0)return{totalJobsProcessed:0,totalMessagesProcessed:0,averageThroughput:0,averageErrorRate:0,averageProcessingTime:0};let s=i.reduce((u,h)=>u+h.messagesProcessed,0),o=i.reduce((u,h)=>u+h.throughput,0)/i.length,c=i.reduce((u,h)=>u+h.errorRate,0)/i.length,l=i.reduce((u,h)=>u+h.averageProcessingTime,0)/i.length;return{totalJobsProcessed:i.length,totalMessagesProcessed:s,averageThroughput:o,averageErrorRate:c,averageProcessingTime:l}}optimizeBatchConfig(n){let i=this.configs.get(n);if(!i)throw Error(`Batch config not found: ${n}`);let s=this.getBatchStatistics(n);if(s.averageErrorRate<5&&i.batchSize<10)i.batchSize=Math.min(10,i.batchSize+1);if(s.averageErrorRate>20&&i.batchSize>1)i.batchSize=Math.max(1,i.batchSize-1);if(s.averageThroughput<5&&i.parallelProcessors<20)i.parallelProcessors++;return i}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getJob(n){return this.jobs.get(n)}listJobs(n){let i=Array.from(this.jobs.values());if(n)i=i.filter((s)=>s.configId===n);return i}generateBatchProcessorCF(n){return{Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:`arn:aws:sqs:us-east-1:123456789012:${n.queueUrl.split("/").pop()}`,FunctionName:"batch-processor-function",BatchSize:n.batchSize,MaximumBatchingWindowInSeconds:n.maxWaitTime/1000,FunctionResponseTypes:["ReportBatchItemFailures"]}}}clear(){this.configs.clear(),this.jobs.clear(),this.metrics.clear(),this.configCounter=0,this.jobCounter=0,this.metricsCounter=0}}var OE=new Dm;class Pm{queues=new Map;retentionPolicies=new Map;delayQueues=new Map;purgeOperations=new Map;metrics=new Map;queueCounter=0;retentionCounter=0;delayCounter=0;purgeCounter=0;metricsCounter=0;createQueue(n){let i=`queue-${Date.now()}-${this.queueCounter++}`,s={id:i,purgeInProgress:!1,...n};return this.queues.set(i,s),s}createStandardQueue(n){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${n.queueName}`,queueName:n.queueName,messageRetentionPeriod:(n.messageRetentionDays||4)*24*60*60,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:0})}createLongPollingQueue(n){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${n.queueName}`,queueName:n.queueName,messageRetentionPeriod:345600,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:n.waitTimeSeconds||20})}createRetentionPolicy(n){let i=`retention-${Date.now()}-${this.retentionCounter++}`,s={id:i,...n};this.retentionPolicies.set(i,s);let o=this.queues.get(n.queueId);if(o)o.messageRetentionPeriod=n.retentionPeriod;return s}createShortRetentionPolicy(n){return this.createRetentionPolicy({queueId:n.queueId,retentionPeriod:n.retentionHours*60*60,autoCleanup:!0,archiveExpiredMessages:!1})}createArchivalRetentionPolicy(n){return this.createRetentionPolicy({queueId:n.queueId,retentionPeriod:n.retentionDays*24*60*60,autoCleanup:!0,cleanupSchedule:"cron(0 0 * * ? *)",archiveExpiredMessages:!0,archiveS3Bucket:n.s3Bucket})}createDelayQueue(n){let i=`delay-${Date.now()}-${this.delayCounter++}`,s={id:i,...n};this.delayQueues.set(i,s);let o=Array.from(this.queues.values()).find((c)=>c.queueUrl===n.queueUrl);if(o)o.delaySeconds=n.defaultDelay;return s}createScheduledDelayQueue(n){return this.createDelayQueue({queueUrl:n.queueUrl,defaultDelay:n.delayMinutes*60,perMessageDelay:!1,maxDelay:900})}async purgeQueue(n){let i=this.queues.get(n);if(!i)throw Error(`Queue not found: ${n}`);if(i.purgeInProgress)throw Error("Purge already in progress for this queue");let s=`purge-${Date.now()}-${this.purgeCounter++}`,o={id:s,queueUrl:i.queueUrl,status:"in_progress",startedAt:new Date};return this.purgeOperations.set(s,o),i.purgeInProgress=!0,setTimeout(()=>{o.status="completed",o.completedAt=new Date,o.messagesPurged=Math.floor(Math.random()*1000),i.purgeInProgress=!1},100),o}collectQueueMetrics(n){let i={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:n,timestamp:new Date,approximateNumberOfMessages:Math.floor(Math.random()*1000),approximateNumberOfMessagesNotVisible:Math.floor(Math.random()*100),approximateNumberOfMessagesDelayed:Math.floor(Math.random()*50),oldestMessageAge:Math.floor(Math.random()*86400)},s=this.metrics.get(n)||[];return s.push(i),this.metrics.set(n,s),i}getQueueHealth(n){let i=this.metrics.get(n)||[];if(i.length===0)return{status:"healthy",issues:[],recommendations:[]};let s=i[i.length-1],o=[],c=[],l="healthy";if(s.approximateNumberOfMessages>1e4)l="critical",o.push("Large message backlog detected"),c.push("Increase consumer capacity");else if(s.approximateNumberOfMessages>1000)l="warning",o.push("Growing message backlog"),c.push("Monitor consumer performance");if(s.oldestMessageAge&&s.oldestMessageAge>3600){if(l!=="critical")l="warning";o.push("Old messages in queue"),c.push("Review message processing")}if(s.approximateNumberOfMessagesDelayed>100){if(l!=="critical")l="warning";o.push("High number of delayed messages")}return{status:l,issues:o,recommendations:c}}getQueue(n){return this.queues.get(n)}listQueues(){return Array.from(this.queues.values())}getRetentionPolicy(n){return this.retentionPolicies.get(n)}listRetentionPolicies(){return Array.from(this.retentionPolicies.values())}getPurgeOperations(n){let i=Array.from(this.purgeOperations.values());if(n)i=i.filter((s)=>s.queueUrl===n);return i}generateQueueCF(n){return{Type:"AWS::SQS::Queue",Properties:{QueueName:n.queueName,MessageRetentionPeriod:n.messageRetentionPeriod,DelaySeconds:n.delaySeconds,MaximumMessageSize:n.maximumMessageSize,ReceiveMessageWaitTimeSeconds:n.receiveMessageWaitTime}}}generateCleanupRuleCF(n){return{Type:"AWS::Events::Rule",Properties:{Name:`${n.id}-cleanup`,Description:"Automated queue cleanup",ScheduleExpression:n.cleanupSchedule||"cron(0 0 * * ? *)",State:"ENABLED",Targets:[{Arn:"arn:aws:lambda:us-east-1:123456789012:function:queue-cleanup",Id:n.id,Input:JSON.stringify({queueId:n.queueId,archiveBucket:n.archiveS3Bucket})}]}}}clear(){this.queues.clear(),this.retentionPolicies.clear(),this.delayQueues.clear(),this.purgeOperations.clear(),this.metrics.clear(),this.queueCounter=0,this.retentionCounter=0,this.delayCounter=0,this.purgeCounter=0,this.metricsCounter=0}}var LE=new Pm,Qn=(()=>{let n=[];for(let i=0;i<256;i++){let s=i;for(let o=0;o<8;o++)s=s&1?3988292384^s>>>1:s>>>1;n[i]=s>>>0}return n})();function Jn(n){let i=4294967295;for(let s=0;s<n.length;s++)i=Qn[(i^n[s])&255]^i>>>8;return(i^4294967295)>>>0}function Yn(n){if(typeof n==="string")return Buffer.from(n,"utf-8");if(Buffer.isBuffer(n))return n;return Buffer.from(n)}function Zn(n){let i=Math.max(1980,n.getFullYear()),s=(n.getHours()<<11|n.getMinutes()<<5|n.getSeconds()>>1)&65535,o=(i-1980<<9|n.getMonth()+1<<5|n.getDate())&65535;return{time:s,date:o}}function Pi(n){let i=[],s=[],o=0;for(let u of n){let h=Yn(u.data),y=zn(h),f=Jn(h),b=Buffer.from(u.name.replace(/\\/g,"/"),"utf-8"),{time:C,date:T}=Zn(u.date??new Date(0)),w=u.mode??420,E=Buffer.alloc(30+b.length);E.writeUInt32LE(67324752,0),E.writeUInt16LE(20,4),E.writeUInt16LE(0,6),E.writeUInt16LE(8,8),E.writeUInt16LE(C,10),E.writeUInt16LE(T,12),E.writeUInt32LE(f,14),E.writeUInt32LE(y.length,18),E.writeUInt32LE(h.length,22),E.writeUInt16LE(b.length,26),E.writeUInt16LE(0,28),b.copy(E,30);let I=Buffer.alloc(46+b.length);I.writeUInt32LE(33639248,0),I.writeUInt16LE(798,4),I.writeUInt16LE(20,6),I.writeUInt16LE(0,8),I.writeUInt16LE(8,10),I.writeUInt16LE(C,12),I.writeUInt16LE(T,14),I.writeUInt32LE(f,16),I.writeUInt32LE(y.length,20),I.writeUInt32LE(h.length,24),I.writeUInt16LE(b.length,28),I.writeUInt16LE(0,30),I.writeUInt16LE(0,32),I.writeUInt16LE(0,34),I.writeUInt16LE(0,36),I.writeUInt32LE((w&65535)<<16,38),I.writeUInt32LE(o,42),b.copy(I,46),i.push(E,y),s.push(I),o+=E.length+y.length}let c=Buffer.concat(s),l=Buffer.alloc(22);return l.writeUInt32LE(101010256,0),l.writeUInt16LE(0,4),l.writeUInt16LE(0,6),l.writeUInt16LE(n.length,8),l.writeUInt16LE(n.length,10),l.writeUInt32LE(c.length,12),l.writeUInt32LE(o,16),l.writeUInt16LE(0,20),Buffer.concat([...i,c,l])}function VA(n){let i=n.adapterImport??"./adapter",s=n.entryImport.replace(/\\/g,"/");return`// Generated by ts-cloud — serverless app bootstrap. Do not edit.
7264
+ `;static createAbTestsTable(n){return{[`${n.slug}AbTestsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-ab-tests`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}}static createAbTestManagerLambda(n){return{[`${n.slug}AbTestManagerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-ab-test-manager`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Te.AbTestManagerCode},Environment:{Variables:{AB_TESTS_TABLE:n.abTestsTable}}}}}}static selectVariant(n,i){let s=Te.hashString(i+n.id)%100,o=0;for(let c=0;c<n.variants.length;c++)if(o+=n.trafficSplit[c],s<o)return n.variants[c];return n.variants[n.variants.length-1]}static determineWinner(n){if(n.variants.length===0)return null;let i=n.winningCriteria,s=n.variants[0],o=Te.getMetricValue(s,i);for(let c of n.variants.slice(1)){let l=Te.getMetricValue(c,i);if(l>o)o=l,s=c}return s}static calculateSignificance(n,i,s){let o=n.stats.sent,c=i.stats.sent;if(o<30||c<30)return 0;let l=Te.getMetricValue(n,s)/100,u=Te.getMetricValue(i,s)/100,h=(l*o+u*c)/(o+c),y=Math.sqrt(h*(1-h)*(1/o+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(n,i){switch(i){case"delivery_rate":return n.stats.deliveryRate;case"click_rate":return n.stats.clickRate;case"reply_rate":return n.stats.replyRate;case"conversion_rate":return n.stats.conversionRate;default:return n.stats.deliveryRate}}static hashString(n){let i=0;for(let s=0;s<n.length;s++){let o=n.charCodeAt(s);i=(i<<5)-i+o,i=i&i}return Math.abs(i)}}class Dm{queues=new Map;messageGroups=new Map;deduplicationConfigs=new Map;messages=new Map;queueCounter=0;groupCounter=0;deduplicationCounter=0;messageCounter=0;sequenceCounter=0;createFIFOQueue(n){let i=`fifo-queue-${Date.now()}-${this.queueCounter++}`,s=n.name.endsWith(".fifo")?n.name:`${n.name}.fifo`,{name:o,...c}=n,l={id:i,name:s,queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${s}`,...c};return this.queues.set(i,l),this.createDeduplicationConfig({queueId:i,contentBasedDeduplication:n.contentBasedDeduplication,deduplicationInterval:300}),l}createHighThroughputFIFO(n){return this.createFIFOQueue({name:n.name,contentBasedDeduplication:n.contentBasedDeduplication??!0,deduplicationScope:"messageGroup",fifoThroughputLimit:"perMessageGroupId",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createStandardFIFO(n){return this.createFIFOQueue({name:n.name,contentBasedDeduplication:n.contentBasedDeduplication??!1,deduplicationScope:"queue",fifoThroughputLimit:"perQueue",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createDeduplicationConfig(n){let i={id:`dedup-${Date.now()}-${this.deduplicationCounter++}`,deduplicationHashes:new Map,...n};return this.deduplicationConfigs.set(n.queueId,i),i}sendMessage(n){let i=this.queues.get(n.queueId);if(!i)throw Error(`Queue not found: ${n.queueId}`);let s=this.deduplicationConfigs.get(n.queueId);if(s){let u=n.messageDeduplicationId||(i.contentBasedDeduplication?this.generateHash(n.messageBody):void 0);if(u&&this.isDuplicate(s,u))return null;if(u)s.deduplicationHashes.set(u,new Date)}let o=`msg-${Date.now()}-${this.messageCounter++}`,c=this.generateSequenceNumber(),l={id:o,messageId:o,messageGroupId:n.messageGroupId,messageDeduplicationId:n.messageDeduplicationId,body:n.messageBody,attributes:n.messageAttributes||{},sentTimestamp:new Date,sequenceNumber:c};return this.messages.set(o,l),this.updateMessageGroup(n.queueId,n.messageGroupId),l}isDuplicate(n,i){let s=n.deduplicationHashes.get(i);if(!s)return!1;if((Date.now()-s.getTime())/1000>n.deduplicationInterval)return n.deduplicationHashes.delete(i),!1;return!0}generateHash(n){let i=0;for(let s=0;s<n.length;s++){let o=n.charCodeAt(s);i=(i<<5)-i+o,i=i&i}return Math.abs(i).toString(36)}generateSequenceNumber(){return`${Date.now()}${this.sequenceCounter++}`.padStart(20,"0")}updateMessageGroup(n,i){let s=`${n}-${i}`,o=this.messageGroups.get(s);if(!o)o={id:`group-${Date.now()}-${this.groupCounter++}`,messageGroupId:i,queueId:n,messagesInFlight:0},this.messageGroups.set(s,o);o.messagesInFlight++,o.lastMessageTimestamp=new Date}getMessageGroups(n){return Array.from(this.messageGroups.values()).filter((i)=>i.queueId===n)}getQueue(n){return this.queues.get(n)}listQueues(){return Array.from(this.queues.values())}getMessages(n,i){let s=Array.from(this.messages.values());if(i)s=s.filter((o)=>o.messageGroupId===i);return s.sort((o,c)=>o.sequenceNumber.localeCompare(c.sequenceNumber))}generateFIFOQueueCF(n){return{Type:"AWS::SQS::Queue",Properties:{QueueName:n.name,FifoQueue:!0,ContentBasedDeduplication:n.contentBasedDeduplication,DeduplicationScope:n.deduplicationScope,FifoThroughputLimit:n.fifoThroughputLimit,MessageRetentionPeriod:n.messageRetentionPeriod,VisibilityTimeout:n.visibilityTimeout,ReceiveMessageWaitTimeSeconds:n.receiveMessageWaitTime,...n.deadLetterTargetArn&&{RedrivePolicy:{deadLetterTargetArn:n.deadLetterTargetArn,maxReceiveCount:n.maxReceiveCount||3}}}}}clear(){this.queues.clear(),this.messageGroups.clear(),this.deduplicationConfigs.clear(),this.messages.clear(),this.queueCounter=0,this.groupCounter=0,this.deduplicationCounter=0,this.messageCounter=0,this.sequenceCounter=0}}var OE=new Dm;class Pm{monitors=new Map;metrics=new Map;alerts=new Map;reprocessJobs=new Map;monitorCounter=0;metricsCounter=0;alertCounter=0;jobCounter=0;createDLQMonitor(n){let i=`dlq-monitor-${Date.now()}-${this.monitorCounter++}`,s={id:i,...n};return this.monitors.set(i,s),s}createAutomatedMonitor(n){return this.createDLQMonitor({name:n.name,queueUrl:n.queueUrl,sourceQueues:n.sourceQueues,maxReceiveCount:3,alarmThreshold:10,autoReprocess:!0,reprocessStrategy:"scheduled",notificationTopicArn:n.notificationTopicArn})}collectMetrics(n){let i={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:n,timestamp:new Date,approximateNumberOfMessages:Math.floor(Math.random()*100),approximateAgeOfOldestMessage:Math.floor(Math.random()*86400),messagesReceived:Math.floor(Math.random()*50),messagesDeleted:Math.floor(Math.random()*30),messagesReprocessed:Math.floor(Math.random()*20)},s=this.metrics.get(n)||[];return s.push(i),this.metrics.set(n,s),this.checkForAlerts(n,i),i}checkForAlerts(n,i){let s=Array.from(this.monitors.values()).find((c)=>c.queueUrl===n);if(!s)return;if(i.approximateNumberOfMessages>=s.alarmThreshold)this.createAlert({monitorId:s.id,alertType:"threshold_exceeded",severity:"high",message:`DLQ ${s.name} has ${i.approximateNumberOfMessages} messages (threshold: ${s.alarmThreshold})`});let o=3600;if(i.approximateAgeOfOldestMessage>o)this.createAlert({monitorId:s.id,alertType:"old_message",severity:"medium",message:`DLQ ${s.name} has messages older than ${o} seconds`})}createAlert(n){let i=`alert-${Date.now()}-${this.alertCounter++}`,s={id:i,timestamp:new Date,acknowledged:!1,...n};return this.alerts.set(i,s),s}acknowledgeAlert(n){let i=this.alerts.get(n);if(!i)throw Error(`Alert not found: ${n}`);return i.acknowledged=!0,i}createReprocessJob(n){let i=`reprocess-${Date.now()}-${this.jobCounter++}`,s={id:i,queueUrl:n.queueUrl,messageId:n.messageId,attempts:0,status:"pending"};return this.reprocessJobs.set(i,s),s}async executeReprocessJob(n){let i=this.reprocessJobs.get(n);if(!i)throw Error(`Reprocess job not found: ${n}`);i.status="processing",i.startedAt=new Date,i.attempts++,await new Promise((o)=>setTimeout(o,100));let s=Math.random()>0.3;if(i.status=s?"success":"failed",i.completedAt=new Date,!s)i.error="Reprocessing failed - original error still present";return i}async batchReprocess(n){let i=[];for(let s=0;s<n.maxMessages;s++){let o=this.createReprocessJob({queueUrl:n.queueUrl,messageId:`msg-${s}`});await this.executeReprocessJob(o.id),i.push(o)}return i}getDLQStatistics(n,i=24){let s=new Date(Date.now()-i*60*60*1000),o=(this.metrics.get(n)||[]).filter((b)=>b.timestamp>=s);if(o.length===0)return{totalMessages:0,avgAge:0,messagesReceived:0,messagesDeleted:0,messagesReprocessed:0,successRate:0};let c=o[o.length-1],l=o.reduce((b,C)=>b+C.messagesReceived,0),u=o.reduce((b,C)=>b+C.messagesDeleted,0),h=o.reduce((b,C)=>b+C.messagesReprocessed,0),y=o.reduce((b,C)=>b+C.approximateAgeOfOldestMessage,0)/o.length,f=h>0?u/h*100:0;return{totalMessages:c.approximateNumberOfMessages,avgAge:y,messagesReceived:l,messagesDeleted:u,messagesReprocessed:h,successRate:f}}getMonitor(n){return this.monitors.get(n)}listMonitors(){return Array.from(this.monitors.values())}getAlerts(n,i){let s=Array.from(this.alerts.values());if(n)s=s.filter((o)=>o.monitorId===n);if(i!==void 0)s=s.filter((o)=>o.acknowledged===i);return s.sort((o,c)=>c.timestamp.getTime()-o.timestamp.getTime())}getReprocessJobs(n){let i=Array.from(this.reprocessJobs.values());if(n)i=i.filter((s)=>s.queueUrl===n);return i}generateDLQAlarmCF(n){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${n.name}-messages-alarm`,AlarmDescription:`Alert when DLQ ${n.name} exceeds threshold`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Average",Period:300,EvaluationPeriods:1,Threshold:n.alarmThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:n.queueUrl.split("/").pop()}],...n.notificationTopicArn&&{AlarmActions:[n.notificationTopicArn]}}}}clear(){this.monitors.clear(),this.metrics.clear(),this.alerts.clear(),this.reprocessJobs.clear(),this.monitorCounter=0,this.metricsCounter=0,this.alertCounter=0,this.jobCounter=0}}var LE=new Pm;class Nm{configs=new Map;jobs=new Map;metrics=new Map;configCounter=0;jobCounter=0;metricsCounter=0;createBatchConfig(n){let i=`batch-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}createHighThroughputConfig(n){return this.createBatchConfig({queueUrl:n.queueUrl,batchSize:10,maxWaitTime:100,parallelProcessors:10,retryAttempts:3,visibilityTimeout:30})}createLowLatencyConfig(n){return this.createBatchConfig({queueUrl:n.queueUrl,batchSize:1,maxWaitTime:0,parallelProcessors:5,retryAttempts:2,visibilityTimeout:10})}createBatchJob(n){let i=`batch-job-${Date.now()}-${this.jobCounter++}`;if(!this.configs.get(n.configId))throw Error(`Batch config not found: ${n.configId}`);let s=[];for(let c=0;c<n.messageCount;c++)s.push({id:`msg-${i}-${c}`,messageId:`${i}-${c}`,body:`Message ${c}`,receiptHandle:`receipt-${i}-${c}`,attributes:{},status:"pending"});let o={id:i,configId:n.configId,messages:s,status:"pending",processedCount:0,failedCount:0};return this.jobs.set(i,o),o}async processBatchJob(n){let i=this.jobs.get(n);if(!i)throw Error(`Batch job not found: ${n}`);let s=this.configs.get(i.configId);if(!s)throw Error(`Batch config not found: ${i.configId}`);i.status="processing",i.startedAt=new Date;let o=this.chunkArray(i.messages,s.batchSize);for(let c of o)await this.processBatch(c,s);return i.processedCount=i.messages.filter((c)=>c.status==="success").length,i.failedCount=i.messages.filter((c)=>c.status==="failed").length,i.status=i.failedCount===0?"completed":"failed",i.completedAt=new Date,this.collectProcessorMetrics(s.id,i),i}async processBatch(n,i){let s=n.map((o)=>this.processMessage(o,i));await Promise.all(s)}async processMessage(n,i){n.status="processing";let s=Date.now();await new Promise((c)=>setTimeout(c,Math.random()*100));let o=Date.now()-s;if(n.processingTime=o,Math.random()>0.1)n.status="success";else n.status="failed",n.error="Processing error"}chunkArray(n,i){let s=[];for(let o=0;o<n.length;o+=i)s.push(n.slice(o,o+i));return s}collectProcessorMetrics(n,i){let s=`metrics-${Date.now()}-${this.metricsCounter++}`,o=i.messages.filter((b)=>b.status==="success").map((b)=>b.processingTime||0).filter((b)=>b>0),c=o.length>0?o.reduce((b,C)=>b+C,0)/o.length:0,l=i.completedAt&&i.startedAt?(i.completedAt.getTime()-i.startedAt.getTime())/1000:1,u=i.processedCount/l,h=i.messages.length>0?i.failedCount/i.messages.length*100:0,y={id:s,configId:n,timestamp:new Date,messagesProcessed:i.processedCount,averageProcessingTime:c,throughput:u,errorRate:h},f=this.metrics.get(n)||[];f.push(y),this.metrics.set(n,f)}getBatchStatistics(n){let i=this.metrics.get(n)||[];if(i.length===0)return{totalJobsProcessed:0,totalMessagesProcessed:0,averageThroughput:0,averageErrorRate:0,averageProcessingTime:0};let s=i.reduce((u,h)=>u+h.messagesProcessed,0),o=i.reduce((u,h)=>u+h.throughput,0)/i.length,c=i.reduce((u,h)=>u+h.errorRate,0)/i.length,l=i.reduce((u,h)=>u+h.averageProcessingTime,0)/i.length;return{totalJobsProcessed:i.length,totalMessagesProcessed:s,averageThroughput:o,averageErrorRate:c,averageProcessingTime:l}}optimizeBatchConfig(n){let i=this.configs.get(n);if(!i)throw Error(`Batch config not found: ${n}`);let s=this.getBatchStatistics(n);if(s.averageErrorRate<5&&i.batchSize<10)i.batchSize=Math.min(10,i.batchSize+1);if(s.averageErrorRate>20&&i.batchSize>1)i.batchSize=Math.max(1,i.batchSize-1);if(s.averageThroughput<5&&i.parallelProcessors<20)i.parallelProcessors++;return i}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getJob(n){return this.jobs.get(n)}listJobs(n){let i=Array.from(this.jobs.values());if(n)i=i.filter((s)=>s.configId===n);return i}generateBatchProcessorCF(n){return{Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:`arn:aws:sqs:us-east-1:123456789012:${n.queueUrl.split("/").pop()}`,FunctionName:"batch-processor-function",BatchSize:n.batchSize,MaximumBatchingWindowInSeconds:n.maxWaitTime/1000,FunctionResponseTypes:["ReportBatchItemFailures"]}}}clear(){this.configs.clear(),this.jobs.clear(),this.metrics.clear(),this.configCounter=0,this.jobCounter=0,this.metricsCounter=0}}var $E=new Nm;class km{queues=new Map;retentionPolicies=new Map;delayQueues=new Map;purgeOperations=new Map;metrics=new Map;queueCounter=0;retentionCounter=0;delayCounter=0;purgeCounter=0;metricsCounter=0;createQueue(n){let i=`queue-${Date.now()}-${this.queueCounter++}`,s={id:i,purgeInProgress:!1,...n};return this.queues.set(i,s),s}createStandardQueue(n){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${n.queueName}`,queueName:n.queueName,messageRetentionPeriod:(n.messageRetentionDays||4)*24*60*60,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:0})}createLongPollingQueue(n){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${n.queueName}`,queueName:n.queueName,messageRetentionPeriod:345600,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:n.waitTimeSeconds||20})}createRetentionPolicy(n){let i=`retention-${Date.now()}-${this.retentionCounter++}`,s={id:i,...n};this.retentionPolicies.set(i,s);let o=this.queues.get(n.queueId);if(o)o.messageRetentionPeriod=n.retentionPeriod;return s}createShortRetentionPolicy(n){return this.createRetentionPolicy({queueId:n.queueId,retentionPeriod:n.retentionHours*60*60,autoCleanup:!0,archiveExpiredMessages:!1})}createArchivalRetentionPolicy(n){return this.createRetentionPolicy({queueId:n.queueId,retentionPeriod:n.retentionDays*24*60*60,autoCleanup:!0,cleanupSchedule:"cron(0 0 * * ? *)",archiveExpiredMessages:!0,archiveS3Bucket:n.s3Bucket})}createDelayQueue(n){let i=`delay-${Date.now()}-${this.delayCounter++}`,s={id:i,...n};this.delayQueues.set(i,s);let o=Array.from(this.queues.values()).find((c)=>c.queueUrl===n.queueUrl);if(o)o.delaySeconds=n.defaultDelay;return s}createScheduledDelayQueue(n){return this.createDelayQueue({queueUrl:n.queueUrl,defaultDelay:n.delayMinutes*60,perMessageDelay:!1,maxDelay:900})}async purgeQueue(n){let i=this.queues.get(n);if(!i)throw Error(`Queue not found: ${n}`);if(i.purgeInProgress)throw Error("Purge already in progress for this queue");let s=`purge-${Date.now()}-${this.purgeCounter++}`,o={id:s,queueUrl:i.queueUrl,status:"in_progress",startedAt:new Date};return this.purgeOperations.set(s,o),i.purgeInProgress=!0,setTimeout(()=>{o.status="completed",o.completedAt=new Date,o.messagesPurged=Math.floor(Math.random()*1000),i.purgeInProgress=!1},100),o}collectQueueMetrics(n){let i={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:n,timestamp:new Date,approximateNumberOfMessages:Math.floor(Math.random()*1000),approximateNumberOfMessagesNotVisible:Math.floor(Math.random()*100),approximateNumberOfMessagesDelayed:Math.floor(Math.random()*50),oldestMessageAge:Math.floor(Math.random()*86400)},s=this.metrics.get(n)||[];return s.push(i),this.metrics.set(n,s),i}getQueueHealth(n){let i=this.metrics.get(n)||[];if(i.length===0)return{status:"healthy",issues:[],recommendations:[]};let s=i[i.length-1],o=[],c=[],l="healthy";if(s.approximateNumberOfMessages>1e4)l="critical",o.push("Large message backlog detected"),c.push("Increase consumer capacity");else if(s.approximateNumberOfMessages>1000)l="warning",o.push("Growing message backlog"),c.push("Monitor consumer performance");if(s.oldestMessageAge&&s.oldestMessageAge>3600){if(l!=="critical")l="warning";o.push("Old messages in queue"),c.push("Review message processing")}if(s.approximateNumberOfMessagesDelayed>100){if(l!=="critical")l="warning";o.push("High number of delayed messages")}return{status:l,issues:o,recommendations:c}}getQueue(n){return this.queues.get(n)}listQueues(){return Array.from(this.queues.values())}getRetentionPolicy(n){return this.retentionPolicies.get(n)}listRetentionPolicies(){return Array.from(this.retentionPolicies.values())}getPurgeOperations(n){let i=Array.from(this.purgeOperations.values());if(n)i=i.filter((s)=>s.queueUrl===n);return i}generateQueueCF(n){return{Type:"AWS::SQS::Queue",Properties:{QueueName:n.queueName,MessageRetentionPeriod:n.messageRetentionPeriod,DelaySeconds:n.delaySeconds,MaximumMessageSize:n.maximumMessageSize,ReceiveMessageWaitTimeSeconds:n.receiveMessageWaitTime}}}generateCleanupRuleCF(n){return{Type:"AWS::Events::Rule",Properties:{Name:`${n.id}-cleanup`,Description:"Automated queue cleanup",ScheduleExpression:n.cleanupSchedule||"cron(0 0 * * ? *)",State:"ENABLED",Targets:[{Arn:"arn:aws:lambda:us-east-1:123456789012:function:queue-cleanup",Id:n.id,Input:JSON.stringify({queueId:n.queueId,archiveBucket:n.archiveS3Bucket})}]}}}clear(){this.queues.clear(),this.retentionPolicies.clear(),this.delayQueues.clear(),this.purgeOperations.clear(),this.metrics.clear(),this.queueCounter=0,this.retentionCounter=0,this.delayCounter=0,this.purgeCounter=0,this.metricsCounter=0}}var ME=new km,Qn=(()=>{let n=[];for(let i=0;i<256;i++){let s=i;for(let o=0;o<8;o++)s=s&1?3988292384^s>>>1:s>>>1;n[i]=s>>>0}return n})();function Jn(n){let i=4294967295;for(let s=0;s<n.length;s++)i=Qn[(i^n[s])&255]^i>>>8;return(i^4294967295)>>>0}function Yn(n){if(typeof n==="string")return Buffer.from(n,"utf-8");if(Buffer.isBuffer(n))return n;return Buffer.from(n)}function Zn(n){let i=Math.max(1980,n.getFullYear()),s=(n.getHours()<<11|n.getMinutes()<<5|n.getSeconds()>>1)&65535,o=(i-1980<<9|n.getMonth()+1<<5|n.getDate())&65535;return{time:s,date:o}}function ki(n){let i=[],s=[],o=0;for(let u of n){let h=Yn(u.data),y=zn(h),f=Jn(h),b=Buffer.from(u.name.replace(/\\/g,"/"),"utf-8"),{time:C,date:T}=Zn(u.date??new Date(0)),w=u.mode??420,E=Buffer.alloc(30+b.length);E.writeUInt32LE(67324752,0),E.writeUInt16LE(20,4),E.writeUInt16LE(0,6),E.writeUInt16LE(8,8),E.writeUInt16LE(C,10),E.writeUInt16LE(T,12),E.writeUInt32LE(f,14),E.writeUInt32LE(y.length,18),E.writeUInt32LE(h.length,22),E.writeUInt16LE(b.length,26),E.writeUInt16LE(0,28),b.copy(E,30);let I=Buffer.alloc(46+b.length);I.writeUInt32LE(33639248,0),I.writeUInt16LE(798,4),I.writeUInt16LE(20,6),I.writeUInt16LE(0,8),I.writeUInt16LE(8,10),I.writeUInt16LE(C,12),I.writeUInt16LE(T,14),I.writeUInt32LE(f,16),I.writeUInt32LE(y.length,20),I.writeUInt32LE(h.length,24),I.writeUInt16LE(b.length,28),I.writeUInt16LE(0,30),I.writeUInt16LE(0,32),I.writeUInt16LE(0,34),I.writeUInt16LE(0,36),I.writeUInt32LE((w&65535)<<16,38),I.writeUInt32LE(o,42),b.copy(I,46),i.push(E,y),s.push(I),o+=E.length+y.length}let c=Buffer.concat(s),l=Buffer.alloc(22);return l.writeUInt32LE(101010256,0),l.writeUInt16LE(0,4),l.writeUInt16LE(0,6),l.writeUInt16LE(n.length,8),l.writeUInt16LE(n.length,10),l.writeUInt32LE(c.length,12),l.writeUInt32LE(o,16),l.writeUInt16LE(0,20),Buffer.concat([...i,c,l])}function zA(n){let i=n.adapterImport??"./adapter",s=n.entryImport.replace(/\\/g,"/");return`// Generated by ts-cloud — serverless app bootstrap. Do not edit.
7265
7265
  import * as __userModule from ${JSON.stringify(s)}
7266
7266
  import { resolveApp, createHandlers } from ${JSON.stringify(i)}
7267
7267
 
@@ -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 ui=["adapter.ts","recursion.ts","auto-recursion.ts"];function di(){return Oe(si(li(import.meta.url)),"runtime")}function jA(n,i,s){for(let o of n??[])s?.(`build: ${o}`),Xn(o,{stdio:"inherit",cwd:i})}function fo(n){return ei("sha256").update(n).digest("hex")}function $d(n,i,s){return`deployments/${n}/${i}/${s}.zip`}async function jr(n){let i=ci(n.projectRoot??process.cwd()),{app:s}=n;if(!n.skipBuild)jA(s.build,i,n.onStep);let o=s.entry;if(!o)throw Error("serverless app: `entry` is required to package a Node/Bun application");let c=oi(o)?o:Oe(i,o),l=ai(Oe(ii(),"tscloud-pkg-"));try{for(let T of ui)ti(Oe(di(),T),Oe(l,T));let u=Oe(l,"bootstrap.ts");ni(u,VA({entryImport:c,adapterImport:"./adapter"})),n.onStep?.("bundling application");let h=await Bun.build({entrypoints:[u],target:s.kind==="bun"?"bun":"node",format:"esm",minify:!1,sourcemap:"none"});if(!h.success){let T=h.logs.map((w)=>String(w)).join(`
7274
+ `}var ui=["adapter.ts","recursion.ts","auto-recursion.ts"];function di(){return Oe(si(li(import.meta.url)),"runtime")}function KA(n,i,s){for(let o of n??[])s?.(`build: ${o}`),Xn(o,{stdio:"inherit",cwd:i})}function yo(n){return ei("sha256").update(n).digest("hex")}function Fd(n,i,s){return`deployments/${n}/${i}/${s}.zip`}async function Kr(n){let i=ci(n.projectRoot??process.cwd()),{app:s}=n;if(!n.skipBuild)KA(s.build,i,n.onStep);let o=s.entry;if(!o)throw Error("serverless app: `entry` is required to package a Node/Bun application");let c=oi(o)?o:Oe(i,o),l=ai(Oe(ii(),"tscloud-pkg-"));try{for(let T of ui)ti(Oe(di(),T),Oe(l,T));let u=Oe(l,"bootstrap.ts");ni(u,zA({entryImport:c,adapterImport:"./adapter"})),n.onStep?.("bundling application");let h=await Bun.build({entrypoints:[u],target:s.kind==="bun"?"bun":"node",format:"esm",minify:!1,sourcemap:"none"});if(!h.success){let T=h.logs.map((w)=>String(w)).join(`
7275
7275
  `);throw Error(`serverless app bundle failed:
7276
- ${T}`)}let y=h.outputs[0],f=Buffer.from(await y.arrayBuffer()),b="index",C=Pi([{name:`${b}.mjs`,data:f}]);return{zip:C,bundle:f,sha256:fo(C),handlerFile:b,handlers:{http:s.handlers?.http??`${b}.http`,queue:s.handlers?.queue??`${b}.queue`,cli:s.handlers?.cli??`${b}.cli`},bundleBytes:f.length}}finally{ri(l,{recursive:!0,force:!0})}}var zA=["18","20","22"];function mi(n){if(!n)return"22";let i=String(n).match(/(\d+)/);return i?i[1]:"22"}function Ao(n){let i=n.kind??"node";if(i==="php")return{lambdaRuntime:"provided.al2023",kind:"php",version:n.phpVersion??"8.3",usesLayer:!0,layerKind:"php",layerEnvVar:"TSCLOUD_PHP_LAYER_ARN"};if(i==="bun")return{lambdaRuntime:"provided.al2023",kind:"bun",version:n.runtimeVersion??"latest",usesLayer:!0,layerKind:"bun",layerEnvVar:"TSCLOUD_BUN_LAYER_ARN"};let s=mi(n.runtimeVersion);if(n.runtime!=="provided.al2023"&&zA.includes(s))return{lambdaRuntime:n.runtime&&n.runtime.startsWith("nodejs")?n.runtime:`nodejs${s}.x`,kind:"node",version:s,usesLayer:!1};return{lambdaRuntime:"provided.al2023",kind:"node",version:s,usesLayer:!0,layerKind:"node",layerEnvVar:"TSCLOUD_NODE_LAYER_ARN"}}function Wt(n,i,s){if(n.queues===!1)return[];if(n.queues===void 0||n.queues===!0)return[{name:`${i}-${s}-default`}];return n.queues.map((o)=>{if(typeof o==="string")return{name:`${i}-${s}-${o}`};let[c,l]=Object.entries(o)[0];return{name:`${i}-${s}-${c}`,concurrency:l}})}function Md(n,i,s){return Wt(n,i,s).map((o)=>o.name)}function Fd(n){let{app:i,environment:s,handlers:o}=n,c=n.config.project.slug,l=Ao(i).lambdaRuntime,u=i.architecture??"x86_64",h=n.config.project.region,y={http:`${c}-${s}-http`,queue:`${c}-${s}-queue`,cli:`${c}-${s}-cli`};if(i.gatewayVersion===1)throw Error("serverless app: `gatewayVersion: 1` (REST API) is not supported — ts-cloud uses API Gateway HTTP API (v2). Remove `gatewayVersion` or set it to 2.");let f=Wt(i,c,s),b=f.map((z)=>z.name),C=b.length>0,T=i.logRetention??14,w=i.packaging==="image";if(w&&i.lambdaInsights)throw Error("serverless app: `lambdaInsights` layer attachment is only supported for zip packaging. Container images must install the Lambda Insights extension in the image.");let E=(i.scheduler??"on")!=="off",I=(i.cache?.driver??"dynamodb")==="dynamodb",N=Boolean(i.assets),D=ao(c,s),B=i.tmpStorage??512,R={},W={},_=[{PolicyName:"tscloud-serverless-app",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:e.sub("arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*")},{Effect:"Allow",Action:["lambda:InvokeFunction"],Resource:e.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${c}-${s}-*`)},{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameter","ssm:GetParameters","ssm:GetParametersByPath"],Resource:[e.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${c}/${s}/*`),e.sub(`arn:aws:ssm:\${AWS::Region}:\${AWS::AccountId}:parameter/${c}/${s}/*`)]},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[e.sub(`arn:aws:s3:::${D}`),e.sub(`arn:aws:s3:::${D}/*`),...i.storage?.bucket?[e.sub(`arn:aws:s3:::${i.storage.bucket}`),e.sub(`arn:aws:s3:::${i.storage.bucket}/*`)]:[]]}]}}];if(C)_[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["sqs:SendMessage","sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes","sqs:GetQueueUrl"],Resource:e.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${c}-${s}-*`)});if(I)_[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:BatchGetItem","dynamodb:BatchWriteItem"],Resource:e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${c}-${s}-cache*`)});let j=["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"];if(i.vpc?.subnets?.length)j.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");if(i.lambdaInsights)j.push("arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy");R.AppRole={Type:"AWS::IAM::Role",Properties:{RoleName:`${c}-${s}-app-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:j,Policies:_}};let J=(z)=>({TSCLOUD_LAMBDA_MODE:z,TSCLOUD_ENV:s,...i.octane?{TSCLOUD_OCTANE:"1"}:{},...i.scheduler==="sub-minute"?{TSCLOUD_SCHEDULER:"sub-minute"}:{},...I?{TSCLOUD_CACHE_TABLE:`${c}-${s}-cache`}:{},...C?{TSCLOUD_QUEUE:b[0]}:{},...i.env??{}}),K=Boolean(i.efs),Y=typeof i.efs==="object"?i.efs:{},X=Y.mountPath??"/mnt/local",ne=K&&!Y.accessPointArn,me=Y.accessPointArn??(ne?e.getAtt("EfsAccessPoint","Arn"):void 0),oe=i.vpc?.subnets??[],le=oe.length>0,ie=i.cache?.driver==="elasticache"||i.database?.connection==="aurora-serverless"||Boolean(i.rdsProxy)||K;if(ie&&!le)throw Error("serverless app: elasticache / aurora-serverless / rdsProxy / efs require app.vpc.subnets (private subnets) to be set.");let Ie=le?{VpcConfig:{SubnetIds:oe,SecurityGroupIds:[...i.vpc?.securityGroups??[],...ie?[e.getAtt("DataSecurityGroup","GroupId")]:[]]}}:{},Ge=ne?oe.map((z,re)=>`EfsMountTarget${re}`):[],Et=K?{FileSystemConfigs:[{Arn:me,LocalMountPath:X}]}:{};if(K)_[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess","elasticfilesystem:DescribeMountTargets"],Resource:"*"});function ge(z,re,ae,se,fe,nt,Ce,it=B){R[`${z}LogGroup`]={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:`/aws/lambda/${re}`,RetentionInDays:T}};let Pt=[...n.runtimeLayers??[],...i.lambdaInsights?[i.lambdaInsights.layerArn]:[]],It=w?{PackageType:"Image",Code:{ImageUri:e.ref("ImageUri")},...i.kind==="php"?{}:{ImageConfig:{Command:[ae]}}}:{Runtime:l,Handler:ae,Code:{S3Bucket:e.ref("ArtifactBucket"),S3Key:e.ref("ArtifactKey")},...Pt.length?{Layers:[...new Set(Pt)]}:{}};R[z]={Type:"AWS::Lambda::Function",DependsOn:[`${z}LogGroup`,...Ge],Properties:{FunctionName:re,Architectures:[u],MemorySize:fe,Timeout:nt,Role:e.getAtt("AppRole","Arn"),Environment:{Variables:J(se)},EphemeralStorage:{Size:it},...It,...Ce!==void 0?{ReservedConcurrentExecutions:Ce}:{},...Ie,...Et}}}if(ge("HttpFunction",y.http,o.http,"http",i.memory??1024,i.timeout??28,i.concurrency,B),ge("CliFunction",y.cli,o.cli,"cli",i.cliMemory??1024,i.cliTimeout??900,void 0,i.cliTmpStorage??B),C)ge("QueueFunction",y.queue,o.queue,"queue",i.queueMemory??1024,i.queueTimeout??120,void 0,i.queueTmpStorage??B);let de=(i.provisionedConcurrency??0)>0?i.provisionedConcurrency:0,he=["HttpFunction","CliFunction",...C?["QueueFunction"]:[]];if(de)for(let z of he)R[`${z}Version`]={Type:"AWS::Lambda::Version",DeletionPolicy:"Retain",Properties:{FunctionName:e.ref(z)}},R[`${z}Alias`]={Type:"AWS::Lambda::Alias",Properties:{FunctionName:e.ref(z),Name:"live",FunctionVersion:e.getAtt(`${z}Version`,"Version"),ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:de}}};let Ne=(z)=>de?e.ref(`${z}Alias`):e.getAtt(z,"Arn"),ye=(z)=>de?e.ref(`${z}Alias`):e.ref(z);R.HttpApi={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:`${c}-${s}`,ProtocolType:"HTTP"}},R.HttpIntegration={Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:e.ref("HttpApi"),IntegrationType:"AWS_PROXY",IntegrationUri:Ne("HttpFunction"),PayloadFormatVersion:"2.0"}},R.HttpRoute={Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:e.ref("HttpApi"),RouteKey:"$default",Target:e.join("/",["integrations",e.ref("HttpIntegration")])}},R.HttpStage={Type:"AWS::ApiGatewayV2::Stage",Properties:{ApiId:e.ref("HttpApi"),StageName:"$default",AutoDeploy:!0}},R.HttpPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:ye("HttpFunction"),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:e.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${HttpApi}/*/*")}},W.HttpApiEndpoint={Description:"HTTP API endpoint",Value:e.getAtt("HttpApi","ApiEndpoint")},W.HttpApiId={Description:"HTTP API id",Value:e.ref("HttpApi")};let Ae=(Array.isArray(i.domain)?i.domain:i.domain?[i.domain]:[]).filter(Boolean);if(Ae.length){if(!i.certificateArn&&!i.hostedZoneId)throw Error("serverless app: a custom `domain` needs either `certificateArn` (pre-issued, regional) or `hostedZoneId` (to auto-issue + validate an ACM cert).");let z=i.certificateArn;if(!z)R.HttpCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:Ae[0],...Ae.length>1?{SubjectAlternativeNames:Ae.slice(1)}:{},ValidationMethod:"DNS",DomainValidationOptions:Ae.map((re)=>({DomainName:re,HostedZoneId:i.hostedZoneId}))}},z=e.ref("HttpCertificate");Ae.forEach((re,ae)=>{let se=`HttpDomain${ae}`;if(R[se]={Type:"AWS::ApiGatewayV2::DomainName",Properties:{DomainName:re,DomainNameConfigurations:[{CertificateArn:z,EndpointType:"REGIONAL"}]}},R[`HttpApiMapping${ae}`]={Type:"AWS::ApiGatewayV2::ApiMapping",DependsOn:["HttpStage"],Properties:{ApiId:e.ref("HttpApi"),DomainName:e.ref(se),Stage:"$default"}},i.hostedZoneId)R[`HttpDomainRecord${ae}`]={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i.hostedZoneId,Name:re,Type:"A",AliasTarget:{DNSName:e.getAtt(se,"RegionalDomainName"),HostedZoneId:e.getAtt(se,"RegionalHostedZoneId")}}};W[`CustomDomain${ae}`]={Description:`Custom domain ${re}`,Value:re},W[`CustomDomainTarget${ae}`]={Description:`Point ${re} (CNAME/alias) at this APIGW regional domain`,Value:e.getAtt(se,"RegionalDomainName")}})}if(C)R.AppQueueDlq={Type:"AWS::SQS::Queue",Properties:{QueueName:`${c}-${s}-dlq`,MessageRetentionPeriod:1209600}},f.forEach((z,re)=>{let ae=`AppQueue${re}`,se=i.queueTimeout??120;R[ae]={Type:"AWS::SQS::Queue",Properties:{QueueName:z.name,VisibilityTimeout:Math.min(43200,se*6),RedrivePolicy:{deadLetterTargetArn:e.getAtt("AppQueueDlq","Arn"),maxReceiveCount:i.queueTries??3}}};let fe=z.concurrency??i.queueConcurrency;R[`${ae}Mapping`]={Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:e.getAtt(ae,"Arn"),FunctionName:ye("QueueFunction"),BatchSize:1,FunctionResponseTypes:["ReportBatchItemFailures"],...fe?{ScalingConfig:{MaximumConcurrency:Math.max(2,fe)}}:{}}},W[`QueueUrl${re}`]={Description:`Queue URL: ${z.name}`,Value:e.ref(ae)}});if(E)R.SchedulerRule={Type:"AWS::Events::Rule",Properties:{Name:`${c}-${s}-scheduler`,ScheduleExpression:"rate(1 minute)",State:"ENABLED",Targets:[{Id:"cli",Arn:Ne("CliFunction"),Input:JSON.stringify({command:"schedule:run"})}]}},R.SchedulerPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:ye("CliFunction"),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.getAtt("SchedulerRule","Arn")}};if(i.warm&&i.warm>0){let z={http:"HttpFunction",queue:"QueueFunction",cli:"CliFunction"},re=(i.warmFunctions??["http"]).filter((ae)=>ae!=="queue"||C);for(let ae of re){let se=ae.charAt(0).toUpperCase()+ae.slice(1),fe=Math.ceil(i.warm/5),nt=0;for(let Ce=0;Ce<fe;Ce++){let it=Math.min(5,i.warm-nt);R[`Warmer${se}Rule${Ce}`]={Type:"AWS::Events::Rule",Properties:{Name:`${c}-${s}-warmer-${ae}-${Ce}`,ScheduleExpression:"rate(5 minutes)",State:"ENABLED",Targets:Array.from({length:it},(Pt,It)=>({Id:`warm-${ae}-${Ce}-${It}`,Arn:e.getAtt(z[ae],"Arn"),Input:JSON.stringify({warmer:!0})}))}},nt+=it}R[`Warmer${se}Permission`]={Type:"AWS::Lambda::Permission",Properties:{FunctionName:e.ref(z[ae]),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.sub(`arn:aws:events:\${AWS::Region}:\${AWS::AccountId}:rule/${c}-${s}-warmer-${ae}-*`)}}}}if(I)R.CacheTable={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${c}-${s}-cache`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"key",AttributeType:"S"}],KeySchema:[{AttributeName:"key",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"expires_at",Enabled:!0}}},W.CacheTableName={Description:"DynamoDB cache table",Value:e.ref("CacheTable")};if(N){if(R.AssetsBucket={Type:"AWS::S3::Bucket",Properties:{BucketName:D,PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}}},R.AssetsOAC={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${c}-${s}-assets-oac`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},R.AssetsDistribution={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,DefaultCacheBehavior:{TargetOriginId:"assets",ViewerProtocolPolicy:"redirect-to-https",Compress:!0,CachePolicyId:"658327ea-f89d-4fab-a63d-7e88639e58f6"},Origins:[{Id:"assets",DomainName:e.getAtt("AssetsBucket","RegionalDomainName"),OriginAccessControlId:e.ref("AssetsOAC"),S3OriginConfig:{OriginAccessIdentity:""}}],...i.assetDomain?{Aliases:[i.assetDomain],ViewerCertificate:{AcmCertificateArn:i.assetCertificateArn??e.ref("AssetsCertificate"),SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}}:{}}}},i.assetDomain){if(!i.assetCertificateArn){if(!i.hostedZoneId)throw Error("serverless app: `assetDomain` requires either `assetCertificateArn` (a us-east-1 ACM cert) or `hostedZoneId` (to auto-issue + validate one). CloudFront only accepts certs from us-east-1.");if(h!=="us-east-1")throw Error(`serverless app: auto-issuing an asset-domain cert needs a us-east-1 app (CloudFront certs must be us-east-1); this app is in ${h}. Supply a pre-issued us-east-1 \`assetCertificateArn\` instead.`);R.AssetsCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:i.assetDomain,ValidationMethod:"DNS",DomainValidationOptions:[{DomainName:i.assetDomain,HostedZoneId:i.hostedZoneId}]}}}if(i.hostedZoneId)R.AssetsDomainRecord={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i.hostedZoneId,Name:i.assetDomain,Type:"A",AliasTarget:{DNSName:e.getAtt("AssetsDistribution","DomainName"),HostedZoneId:"Z2FDTNDATAQYW2"}}};W.AssetDomain={Description:"Custom asset CDN host",Value:i.assetDomain}}R.AssetsBucketPolicy={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:e.ref("AssetsBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:e.sub(`arn:aws:s3:::${D}/*`),Condition:{StringEquals:{"AWS:SourceArn":e.sub("arn:aws:cloudfront::${AWS::AccountId}:distribution/${AssetsDistribution}")}}}]}}},W.AssetsBucketName={Description:"Assets bucket",Value:e.ref("AssetsBucket")},W.AssetsCdnDomain={Description:"Assets CloudFront domain",Value:e.getAtt("AssetsDistribution","DomainName")}}if(i.firewall?.enabled){let z=[],re=0;if(i.firewall.rateLimit)z.push({Name:"rate-limit",Priority:re++,Action:{Block:{}},Statement:{RateBasedStatement:{Limit:i.firewall.rateLimit,AggregateKeyType:"IP"}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${s}-rate`}});let ae={sqlInjection:"AWSManagedRulesSQLiRuleSet",xss:"AWSManagedRulesCommonRuleSet",common:"AWSManagedRulesCommonRuleSet",botControl:"AWSManagedRulesBotControlRuleSet",ipReputation:"AWSManagedRulesAmazonIpReputationList"};for(let se of i.firewall.rules??[]){let fe=ae[se];if(!fe)continue;z.push({Name:`managed-${se}`,Priority:re++,OverrideAction:{None:{}},Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:fe}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${s}-${se}`}})}R.WebAcl={Type:"AWS::WAFv2::WebACL",Properties:{Name:`${c}-${s}-waf`,Scope:"REGIONAL",DefaultAction:{Allow:{}},Rules:z,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${s}-waf`}}},W.WafAclArn={Description:"WAF web ACL ARN. Attach to a CloudFront distribution fronting the API to enforce (HTTP API v2 stages do not support direct WAF association).",Value:e.getAtt("WebAcl","Arn")}}if(le&&ie){if(!i.vpc?.id)throw Error("serverless app: data services (elasticache / aurora-serverless / rdsProxy / efs) need app.vpc.id (the VPC id) so the managed security group is created in the right VPC.");R.DataSecurityGroup={Type:"AWS::EC2::SecurityGroup",Properties:{VpcId:i.vpc.id,GroupDescription:`${c}-${s} serverless data access`,SecurityGroupIngress:[{IpProtocol:"-1",CidrIp:"10.0.0.0/8"}]}}}if(ne)R.EfsFileSystem={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:!0,FileSystemTags:[{Key:"Name",Value:`${c}-${s}-efs`}]}},oe.forEach((z,re)=>{R[`EfsMountTarget${re}`]={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:e.ref("EfsFileSystem"),SubnetId:z,SecurityGroups:[e.getAtt("DataSecurityGroup","GroupId")]}}}),R.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"}}}},W.EfsFileSystemId={Description:"EFS file system id",Value:e.ref("EfsFileSystem")};if(i.cache?.driver==="elasticache")R.CacheSubnetGroup={Type:"AWS::ElastiCache::SubnetGroup",Properties:{Description:`${c}-${s} cache subnets`,SubnetIds:oe}},R.CacheCluster={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:`${c}-${s}-cache`,ReplicationGroupDescription:`${c}-${s} redis`,Engine:"redis",CacheNodeType:"cache.t4g.micro",NumCacheClusters:1,AutomaticFailoverEnabled:!1,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),SecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")],TransitEncryptionEnabled:!1}},W.CacheEndpoint={Description:"Redis primary endpoint",Value:e.getAtt("CacheCluster","PrimaryEndPoint.Address")};if(i.database?.connection==="aurora-serverless")R.DbSubnetGroup={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupDescription:`${c}-${s} db subnets`,SubnetIds:oe}},R.DbSecret={Type:"AWS::SecretsManager::Secret",Properties:{Name:`${c}/${s}/db`,GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"app"}),GenerateStringKey:"password",PasswordLength:32,ExcludePunctuation:!0}}},R.DbCluster={Type:"AWS::RDS::DBCluster",Properties:{Engine:"aurora-mysql",EngineMode:"provisioned",DBClusterIdentifier:`${c}-${s}-db`,DatabaseName:"app",MasterUsername:e.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:username}}"),MasterUserPassword:e.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:password}}"),ServerlessV2ScalingConfiguration:{MinCapacity:i.database?.minCapacity??0.5,MaxCapacity:i.database?.maxCapacity??4},DBSubnetGroupName:e.ref("DbSubnetGroup"),VpcSecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")]}},R.DbInstance={Type:"AWS::RDS::DBInstance",Properties:{Engine:"aurora-mysql",DBInstanceClass:"db.serverless",DBClusterIdentifier:e.ref("DbCluster")}},W.DbEndpoint={Description:"Aurora cluster endpoint",Value:e.getAtt("DbCluster","Endpoint.Address")};if(i.rdsProxy&&i.database?.connection==="aurora-serverless")R.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")}]}}]}},R.DbProxy={Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:typeof i.rdsProxy==="object"&&i.rdsProxy.name?i.rdsProxy.name:`${c}-${s}-proxy`,EngineFamily:"MYSQL",RoleArn:e.getAtt("DbProxyRole","Arn"),Auth:[{AuthScheme:"SECRETS",SecretArn:e.ref("DbSecret"),IAMAuth:"DISABLED"}],VpcSubnetIds:oe,VpcSecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")],RequireTLS:!1}},R.DbProxyTargetGroup={Type:"AWS::RDS::DBProxyTargetGroup",DependsOn:["DbInstance"],Properties:{DBProxyName:e.ref("DbProxy"),TargetGroupName:"default",DBClusterIdentifiers:[e.ref("DbCluster")]}},W.DbProxyEndpoint={Description:"RDS Proxy endpoint",Value:e.getAtt("DbProxy","Endpoint")};if(W.HttpFunctionName={Description:"HTTP function name",Value:e.ref("HttpFunction")},W.CliFunctionName={Description:"CLI function name",Value:e.ref("CliFunction")},C)W.QueueFunctionName={Description:"Queue function name",Value:e.ref("QueueFunction")};let Me={AWSTemplateFormatVersion:"2010-09-09",Description:`Serverless application for ${n.config.project.name} (${c}-${s})`,Parameters:w?{ImageUri:{Type:"String",Description:"ECR image URI of the deployment artifact"}}:{ArtifactBucket:{Type:"String",Description:"S3 bucket holding the deployment artifact"},ArtifactKey:{Type:"String",Description:"S3 key of the deployment artifact (zip)"}},Resources:R,Outputs:W},Fe={};for(let z of Object.values(R))Fe[z.Type]=(Fe[z.Type]??0)+1;return{template:Me,functionNames:y,queueNames:b,resourceSummary:Fe}}var KA=["cli","fpm","curl","mbstring","xml","pdo","mysqlnd","gd","bcmath","intl","opcache","sodium","process","pecl-redis6","pecl-apcu","pgsql"];function WA(n){let i=`php${n.replace(".","")}`;return KA.map((s)=>`${i}-php-${s}`)}function Nm(n,i){let s=`php${n.replace(".","")}`,o=WA(n).join(" \\\n "),c=`/opt/remi/${s}/root`,l=`/etc/opt/remi/${s}`;return`${i?`FROM almalinux:9 AS ${i}`:"FROM almalinux:9"}
7276
+ ${T}`)}let y=h.outputs[0],f=Buffer.from(await y.arrayBuffer()),b="index",C=ki([{name:`${b}.mjs`,data:f}]);return{zip:C,bundle:f,sha256:yo(C),handlerFile:b,handlers:{http:s.handlers?.http??`${b}.http`,queue:s.handlers?.queue??`${b}.queue`,cli:s.handlers?.cli??`${b}.cli`},bundleBytes:f.length}}finally{ri(l,{recursive:!0,force:!0})}}var WA=["18","20","22"];function mi(n){if(!n)return"22";let i=String(n).match(/(\d+)/);return i?i[1]:"22"}function Io(n){let i=n.kind??"node";if(i==="php")return{lambdaRuntime:"provided.al2023",kind:"php",version:n.phpVersion??"8.3",usesLayer:!0,layerKind:"php",layerEnvVar:"TSCLOUD_PHP_LAYER_ARN"};if(i==="bun")return{lambdaRuntime:"provided.al2023",kind:"bun",version:n.runtimeVersion??"latest",usesLayer:!0,layerKind:"bun",layerEnvVar:"TSCLOUD_BUN_LAYER_ARN"};let s=mi(n.runtimeVersion);if(n.runtime!=="provided.al2023"&&WA.includes(s))return{lambdaRuntime:n.runtime&&n.runtime.startsWith("nodejs")?n.runtime:`nodejs${s}.x`,kind:"node",version:s,usesLayer:!1};return{lambdaRuntime:"provided.al2023",kind:"node",version:s,usesLayer:!0,layerKind:"node",layerEnvVar:"TSCLOUD_NODE_LAYER_ARN"}}function Jt(n,i,s){if(n.queues===!1)return[];if(n.queues===void 0||n.queues===!0)return[{name:`${i}-${s}-default`}];return n.queues.map((o)=>{if(typeof o==="string")return{name:`${i}-${s}-${o}`};let[c,l]=Object.entries(o)[0];return{name:`${i}-${s}-${c}`,concurrency:l}})}function Ud(n,i,s){return Jt(n,i,s).map((o)=>o.name)}function Qd(n){let{app:i,environment:s,handlers:o}=n,c=n.config.project.slug,l=Io(i).lambdaRuntime,u=i.architecture??"x86_64",h=n.config.project.region,y={http:`${c}-${s}-http`,queue:`${c}-${s}-queue`,cli:`${c}-${s}-cli`};if(i.gatewayVersion===1)throw Error("serverless app: `gatewayVersion: 1` (REST API) is not supported — ts-cloud uses API Gateway HTTP API (v2). Remove `gatewayVersion` or set it to 2.");let f=Jt(i,c,s),b=f.map((z)=>z.name),C=b.length>0,T=i.logRetention??14,w=i.packaging==="image";if(w&&i.lambdaInsights)throw Error("serverless app: `lambdaInsights` layer attachment is only supported for zip packaging. Container images must install the Lambda Insights extension in the image.");let E=(i.scheduler??"on")!=="off",I=(i.cache?.driver??"dynamodb")==="dynamodb",N=Boolean(i.assets),D=lo(c,s),x=i.tmpStorage??512,R={},_={},B=[{PolicyName:"tscloud-serverless-app",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:e.sub("arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*")},{Effect:"Allow",Action:["lambda:InvokeFunction"],Resource:e.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${c}-${s}-*`)},{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameter","ssm:GetParameters","ssm:GetParametersByPath"],Resource:[e.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${c}/${s}/*`),e.sub(`arn:aws:ssm:\${AWS::Region}:\${AWS::AccountId}:parameter/${c}/${s}/*`)]},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[e.sub(`arn:aws:s3:::${D}`),e.sub(`arn:aws:s3:::${D}/*`),...i.storage?.bucket?[e.sub(`arn:aws:s3:::${i.storage.bucket}`),e.sub(`arn:aws:s3:::${i.storage.bucket}/*`)]:[]]}]}}];if(C)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["sqs:SendMessage","sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes","sqs:GetQueueUrl"],Resource:e.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${c}-${s}-*`)});if(I)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:BatchGetItem","dynamodb:BatchWriteItem"],Resource:e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${c}-${s}-cache*`)});let W=["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"];if(i.vpc?.subnets?.length)W.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");if(i.lambdaInsights)W.push("arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy");R.AppRole={Type:"AWS::IAM::Role",Properties:{RoleName:`${c}-${s}-app-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:W,Policies:B}};let J=(z)=>({TSCLOUD_LAMBDA_MODE:z,TSCLOUD_ENV:s,...i.octane?{TSCLOUD_OCTANE:"1"}:{},...i.scheduler==="sub-minute"?{TSCLOUD_SCHEDULER:"sub-minute"}:{},...I?{TSCLOUD_CACHE_TABLE:`${c}-${s}-cache`}:{},...C?{TSCLOUD_QUEUE:b[0]}:{},...i.env??{}}),K=Boolean(i.efs),Y=typeof i.efs==="object"?i.efs:{},Z=Y.mountPath??"/mnt/local",ne=K&&!Y.accessPointArn,de=Y.accessPointArn??(ne?e.getAtt("EfsAccessPoint","Arn"):void 0),oe=i.vpc?.subnets??[],le=oe.length>0,ie=i.cache?.driver==="elasticache"||i.database?.connection==="aurora-serverless"||Boolean(i.rdsProxy)||K;if(ie&&!le)throw Error("serverless app: elasticache / aurora-serverless / rdsProxy / efs require app.vpc.subnets (private subnets) to be set.");let Ee=le?{VpcConfig:{SubnetIds:oe,SecurityGroupIds:[...i.vpc?.securityGroups??[],...ie?[e.getAtt("DataSecurityGroup","GroupId")]:[]]}}:{},Fe=ne?oe.map((z,ae)=>`EfsMountTarget${ae}`):[],Et=K?{FileSystemConfigs:[{Arn:de,LocalMountPath:Z}]}:{};if(K)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess","elasticfilesystem:DescribeMountTargets"],Resource:"*"});function pe(z,ae,X,se,fe,nt,Ce,it=x){R[`${z}LogGroup`]={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:`/aws/lambda/${ae}`,RetentionInDays:T}};let Pt=[...n.runtimeLayers??[],...i.lambdaInsights?[i.lambdaInsights.layerArn]:[]],It=w?{PackageType:"Image",Code:{ImageUri:e.ref("ImageUri")},...i.kind==="php"?{}:{ImageConfig:{Command:[X]}}}:{Runtime:l,Handler:X,Code:{S3Bucket:e.ref("ArtifactBucket"),S3Key:e.ref("ArtifactKey")},...Pt.length?{Layers:[...new Set(Pt)]}:{}};R[z]={Type:"AWS::Lambda::Function",DependsOn:[`${z}LogGroup`,...Fe],Properties:{FunctionName:ae,Architectures:[u],MemorySize:fe,Timeout:nt,Role:e.getAtt("AppRole","Arn"),Environment:{Variables:J(se)},EphemeralStorage:{Size:it},...It,...Ce!==void 0?{ReservedConcurrentExecutions:Ce}:{},...Ee,...Et}}}if(pe("HttpFunction",y.http,o.http,"http",i.memory??1024,i.timeout??28,i.concurrency,x),pe("CliFunction",y.cli,o.cli,"cli",i.cliMemory??1024,i.cliTimeout??900,void 0,i.cliTmpStorage??x),C)pe("QueueFunction",y.queue,o.queue,"queue",i.queueMemory??1024,i.queueTimeout??120,void 0,i.queueTmpStorage??x);let ue=(i.provisionedConcurrency??0)>0?i.provisionedConcurrency:0,he=["HttpFunction","CliFunction",...C?["QueueFunction"]:[]];if(ue)for(let z of he)R[`${z}Version`]={Type:"AWS::Lambda::Version",DeletionPolicy:"Retain",Properties:{FunctionName:e.ref(z)}},R[`${z}Alias`]={Type:"AWS::Lambda::Alias",Properties:{FunctionName:e.ref(z),Name:"live",FunctionVersion:e.getAtt(`${z}Version`,"Version"),ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:ue}}};let Ie=(z)=>ue?e.ref(`${z}Alias`):e.getAtt(z,"Arn"),ye=(z)=>ue?e.ref(`${z}Alias`):e.ref(z);R.HttpApi={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:`${c}-${s}`,ProtocolType:"HTTP"}},R.HttpIntegration={Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:e.ref("HttpApi"),IntegrationType:"AWS_PROXY",IntegrationUri:Ie("HttpFunction"),PayloadFormatVersion:"2.0"}},R.HttpRoute={Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:e.ref("HttpApi"),RouteKey:"$default",Target:e.join("/",["integrations",e.ref("HttpIntegration")])}},R.HttpStage={Type:"AWS::ApiGatewayV2::Stage",Properties:{ApiId:e.ref("HttpApi"),StageName:"$default",AutoDeploy:!0}},R.HttpPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:ye("HttpFunction"),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:e.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${HttpApi}/*/*")}},_.HttpApiEndpoint={Description:"HTTP API endpoint",Value:e.getAtt("HttpApi","ApiEndpoint")},_.HttpApiId={Description:"HTTP API id",Value:e.ref("HttpApi")};let Ae=(Array.isArray(i.domain)?i.domain:i.domain?[i.domain]:[]).filter(Boolean);if(Ae.length){if(!i.certificateArn&&!i.hostedZoneId)throw Error("serverless app: a custom `domain` needs either `certificateArn` (pre-issued, regional) or `hostedZoneId` (to auto-issue + validate an ACM cert).");let z=i.certificateArn;if(!z)R.HttpCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:Ae[0],...Ae.length>1?{SubjectAlternativeNames:Ae.slice(1)}:{},ValidationMethod:"DNS",DomainValidationOptions:Ae.map((ae)=>({DomainName:ae,HostedZoneId:i.hostedZoneId}))}},z=e.ref("HttpCertificate");Ae.forEach((ae,X)=>{let se=`HttpDomain${X}`;if(R[se]={Type:"AWS::ApiGatewayV2::DomainName",Properties:{DomainName:ae,DomainNameConfigurations:[{CertificateArn:z,EndpointType:"REGIONAL"}]}},R[`HttpApiMapping${X}`]={Type:"AWS::ApiGatewayV2::ApiMapping",DependsOn:["HttpStage"],Properties:{ApiId:e.ref("HttpApi"),DomainName:e.ref(se),Stage:"$default"}},i.hostedZoneId)R[`HttpDomainRecord${X}`]={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i.hostedZoneId,Name:ae,Type:"A",AliasTarget:{DNSName:e.getAtt(se,"RegionalDomainName"),HostedZoneId:e.getAtt(se,"RegionalHostedZoneId")}}};_[`CustomDomain${X}`]={Description:`Custom domain ${ae}`,Value:ae},_[`CustomDomainTarget${X}`]={Description:`Point ${ae} (CNAME/alias) at this APIGW regional domain`,Value:e.getAtt(se,"RegionalDomainName")}})}if(C)R.AppQueueDlq={Type:"AWS::SQS::Queue",Properties:{QueueName:`${c}-${s}-dlq`,MessageRetentionPeriod:1209600}},f.forEach((z,ae)=>{let X=`AppQueue${ae}`,se=i.queueTimeout??120;R[X]={Type:"AWS::SQS::Queue",Properties:{QueueName:z.name,VisibilityTimeout:Math.min(43200,se*6),RedrivePolicy:{deadLetterTargetArn:e.getAtt("AppQueueDlq","Arn"),maxReceiveCount:i.queueTries??3}}};let fe=z.concurrency??i.queueConcurrency;R[`${X}Mapping`]={Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:e.getAtt(X,"Arn"),FunctionName:ye("QueueFunction"),BatchSize:1,FunctionResponseTypes:["ReportBatchItemFailures"],...fe?{ScalingConfig:{MaximumConcurrency:Math.max(2,fe)}}:{}}},_[`QueueUrl${ae}`]={Description:`Queue URL: ${z.name}`,Value:e.ref(X)}});if(E)R.SchedulerRule={Type:"AWS::Events::Rule",Properties:{Name:`${c}-${s}-scheduler`,ScheduleExpression:"rate(1 minute)",State:"ENABLED",Targets:[{Id:"cli",Arn:Ie("CliFunction"),Input:JSON.stringify({command:"schedule:run"})}]}},R.SchedulerPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:ye("CliFunction"),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.getAtt("SchedulerRule","Arn")}};if(i.warm&&i.warm>0){let z={http:"HttpFunction",queue:"QueueFunction",cli:"CliFunction"},ae=(i.warmFunctions??["http"]).filter((X)=>X!=="queue"||C);for(let X of ae){let se=X.charAt(0).toUpperCase()+X.slice(1),fe=Math.ceil(i.warm/5),nt=0;for(let Ce=0;Ce<fe;Ce++){let it=Math.min(5,i.warm-nt);R[`Warmer${se}Rule${Ce}`]={Type:"AWS::Events::Rule",Properties:{Name:`${c}-${s}-warmer-${X}-${Ce}`,ScheduleExpression:"rate(5 minutes)",State:"ENABLED",Targets:Array.from({length:it},(Pt,It)=>({Id:`warm-${X}-${Ce}-${It}`,Arn:e.getAtt(z[X],"Arn"),Input:JSON.stringify({warmer:!0})}))}},nt+=it}R[`Warmer${se}Permission`]={Type:"AWS::Lambda::Permission",Properties:{FunctionName:e.ref(z[X]),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.sub(`arn:aws:events:\${AWS::Region}:\${AWS::AccountId}:rule/${c}-${s}-warmer-${X}-*`)}}}}if(I)R.CacheTable={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${c}-${s}-cache`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"key",AttributeType:"S"}],KeySchema:[{AttributeName:"key",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"expires_at",Enabled:!0}}},_.CacheTableName={Description:"DynamoDB cache table",Value:e.ref("CacheTable")};if(N){if(R.AssetsBucket={Type:"AWS::S3::Bucket",Properties:{BucketName:D,PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}}},R.AssetsOAC={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${c}-${s}-assets-oac`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},R.AssetsDistribution={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,DefaultCacheBehavior:{TargetOriginId:"assets",ViewerProtocolPolicy:"redirect-to-https",Compress:!0,CachePolicyId:"658327ea-f89d-4fab-a63d-7e88639e58f6"},Origins:[{Id:"assets",DomainName:e.getAtt("AssetsBucket","RegionalDomainName"),OriginAccessControlId:e.ref("AssetsOAC"),S3OriginConfig:{OriginAccessIdentity:""}}],...i.assetDomain?{Aliases:[i.assetDomain],ViewerCertificate:{AcmCertificateArn:i.assetCertificateArn??e.ref("AssetsCertificate"),SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}}:{}}}},i.assetDomain){if(!i.assetCertificateArn){if(!i.hostedZoneId)throw Error("serverless app: `assetDomain` requires either `assetCertificateArn` (a us-east-1 ACM cert) or `hostedZoneId` (to auto-issue + validate one). CloudFront only accepts certs from us-east-1.");if(h!=="us-east-1")throw Error(`serverless app: auto-issuing an asset-domain cert needs a us-east-1 app (CloudFront certs must be us-east-1); this app is in ${h}. Supply a pre-issued us-east-1 \`assetCertificateArn\` instead.`);R.AssetsCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:i.assetDomain,ValidationMethod:"DNS",DomainValidationOptions:[{DomainName:i.assetDomain,HostedZoneId:i.hostedZoneId}]}}}if(i.hostedZoneId)R.AssetsDomainRecord={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i.hostedZoneId,Name:i.assetDomain,Type:"A",AliasTarget:{DNSName:e.getAtt("AssetsDistribution","DomainName"),HostedZoneId:"Z2FDTNDATAQYW2"}}};_.AssetDomain={Description:"Custom asset CDN host",Value:i.assetDomain}}R.AssetsBucketPolicy={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:e.ref("AssetsBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:e.sub(`arn:aws:s3:::${D}/*`),Condition:{StringEquals:{"AWS:SourceArn":e.sub("arn:aws:cloudfront::${AWS::AccountId}:distribution/${AssetsDistribution}")}}}]}}},_.AssetsBucketName={Description:"Assets bucket",Value:e.ref("AssetsBucket")},_.AssetsCdnDomain={Description:"Assets CloudFront domain",Value:e.getAtt("AssetsDistribution","DomainName")}}if(i.firewall?.enabled){let z=[],ae=0;if(i.firewall.rateLimit)z.push({Name:"rate-limit",Priority:ae++,Action:{Block:{}},Statement:{RateBasedStatement:{Limit:i.firewall.rateLimit,AggregateKeyType:"IP"}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${s}-rate`}});let X={sqlInjection:"AWSManagedRulesSQLiRuleSet",xss:"AWSManagedRulesCommonRuleSet",common:"AWSManagedRulesCommonRuleSet",botControl:"AWSManagedRulesBotControlRuleSet",ipReputation:"AWSManagedRulesAmazonIpReputationList"};for(let se of i.firewall.rules??[]){let fe=X[se];if(!fe)continue;z.push({Name:`managed-${se}`,Priority:ae++,OverrideAction:{None:{}},Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:fe}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${s}-${se}`}})}R.WebAcl={Type:"AWS::WAFv2::WebACL",Properties:{Name:`${c}-${s}-waf`,Scope:"REGIONAL",DefaultAction:{Allow:{}},Rules:z,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${s}-waf`}}},_.WafAclArn={Description:"WAF web ACL ARN. Attach to a CloudFront distribution fronting the API to enforce (HTTP API v2 stages do not support direct WAF association).",Value:e.getAtt("WebAcl","Arn")}}if(le&&ie){if(!i.vpc?.id)throw Error("serverless app: data services (elasticache / aurora-serverless / rdsProxy / efs) need app.vpc.id (the VPC id) so the managed security group is created in the right VPC.");R.DataSecurityGroup={Type:"AWS::EC2::SecurityGroup",Properties:{VpcId:i.vpc.id,GroupDescription:`${c}-${s} serverless data access`,SecurityGroupIngress:[{IpProtocol:"-1",CidrIp:"10.0.0.0/8"}]}}}if(ne)R.EfsFileSystem={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:!0,FileSystemTags:[{Key:"Name",Value:`${c}-${s}-efs`}]}},oe.forEach((z,ae)=>{R[`EfsMountTarget${ae}`]={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:e.ref("EfsFileSystem"),SubnetId:z,SecurityGroups:[e.getAtt("DataSecurityGroup","GroupId")]}}}),R.EfsAccessPoint={Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:e.ref("EfsFileSystem"),PosixUser:{Uid:1001,Gid:1001},RootDirectory:{Path:"/lambda",CreationInfo:{OwnerUid:1001,OwnerGid:1001,Permissions:"0755"}}}},_.EfsFileSystemId={Description:"EFS file system id",Value:e.ref("EfsFileSystem")};if(i.cache?.driver==="elasticache")R.CacheSubnetGroup={Type:"AWS::ElastiCache::SubnetGroup",Properties:{Description:`${c}-${s} cache subnets`,SubnetIds:oe}},R.CacheCluster={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:`${c}-${s}-cache`,ReplicationGroupDescription:`${c}-${s} redis`,Engine:"redis",CacheNodeType:"cache.t4g.micro",NumCacheClusters:1,AutomaticFailoverEnabled:!1,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),SecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")],TransitEncryptionEnabled:!1}},_.CacheEndpoint={Description:"Redis primary endpoint",Value:e.getAtt("CacheCluster","PrimaryEndPoint.Address")};if(i.database?.connection==="aurora-serverless")R.DbSubnetGroup={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupDescription:`${c}-${s} db subnets`,SubnetIds:oe}},R.DbSecret={Type:"AWS::SecretsManager::Secret",Properties:{Name:`${c}/${s}/db`,GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"app"}),GenerateStringKey:"password",PasswordLength:32,ExcludePunctuation:!0}}},R.DbCluster={Type:"AWS::RDS::DBCluster",Properties:{Engine:"aurora-mysql",EngineMode:"provisioned",DBClusterIdentifier:`${c}-${s}-db`,DatabaseName:"app",MasterUsername:e.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:username}}"),MasterUserPassword:e.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:password}}"),ServerlessV2ScalingConfiguration:{MinCapacity:i.database?.minCapacity??0.5,MaxCapacity:i.database?.maxCapacity??4},DBSubnetGroupName:e.ref("DbSubnetGroup"),VpcSecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")]}},R.DbInstance={Type:"AWS::RDS::DBInstance",Properties:{Engine:"aurora-mysql",DBInstanceClass:"db.serverless",DBClusterIdentifier:e.ref("DbCluster")}},_.DbEndpoint={Description:"Aurora cluster endpoint",Value:e.getAtt("DbCluster","Endpoint.Address")};if(i.rdsProxy&&i.database?.connection==="aurora-serverless")R.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")}]}}]}},R.DbProxy={Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:typeof i.rdsProxy==="object"&&i.rdsProxy.name?i.rdsProxy.name:`${c}-${s}-proxy`,EngineFamily:"MYSQL",RoleArn:e.getAtt("DbProxyRole","Arn"),Auth:[{AuthScheme:"SECRETS",SecretArn:e.ref("DbSecret"),IAMAuth:"DISABLED"}],VpcSubnetIds:oe,VpcSecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")],RequireTLS:!1}},R.DbProxyTargetGroup={Type:"AWS::RDS::DBProxyTargetGroup",DependsOn:["DbInstance"],Properties:{DBProxyName:e.ref("DbProxy"),TargetGroupName:"default",DBClusterIdentifiers:[e.ref("DbCluster")]}},_.DbProxyEndpoint={Description:"RDS Proxy endpoint",Value:e.getAtt("DbProxy","Endpoint")};if(_.HttpFunctionName={Description:"HTTP function name",Value:e.ref("HttpFunction")},_.CliFunctionName={Description:"CLI function name",Value:e.ref("CliFunction")},C)_.QueueFunctionName={Description:"Queue function name",Value:e.ref("QueueFunction")};let Me={AWSTemplateFormatVersion:"2010-09-09",Description:`Serverless application for ${n.config.project.name} (${c}-${s})`,Parameters:w?{ImageUri:{Type:"String",Description:"ECR image URI of the deployment artifact"}}:{ArtifactBucket:{Type:"String",Description:"S3 bucket holding the deployment artifact"},ArtifactKey:{Type:"String",Description:"S3 key of the deployment artifact (zip)"}},Resources:R,Outputs:_},Ue={};for(let z of Object.values(R))Ue[z.Type]=(Ue[z.Type]??0)+1;return{template:Me,functionNames:y,queueNames:b,resourceSummary:Ue}}var JA=["cli","fpm","curl","mbstring","xml","pdo","mysqlnd","gd","bcmath","intl","opcache","sodium","process","pecl-redis6","pecl-apcu","pgsql"];function XA(n){let i=`php${n.replace(".","")}`;return JA.map((s)=>`${i}-php-${s}`)}function Bm(n,i){let s=`php${n.replace(".","")}`,o=XA(n).join(" \\\n "),c=`/opt/remi/${s}/root`,l=`/etc/opt/remi/${s}`;return`${i?`FROM almalinux:9 AS ${i}`:"FROM almalinux:9"}
7277
7277
 
7278
7278
  # Build PHP on AlmaLinux 9 (where Remi's version-isolated SCL packages install
7279
7279
  # cleanly — Remi's release RPM rejects Amazon Linux 2023). AlmaLinux 9 shares
@@ -7313,9 +7313,9 @@ RUN printf 'extension_dir=/opt/php/lib/php/modules\\n' > /opt/php/etc/php.ini &&
7313
7313
  # Runtime assets (bootstrap, runtime loops, fpm config) are added by the build
7314
7314
  # orchestrator after the image is produced. Export /opt as the layer payload.
7315
7315
  CMD ["true"]
7316
- `}function JA(n={}){let i=n.phpVersion??"8.3";return`# ts-cloud PHP ${i} runtime layer (generated) — AWS Lambda provided.al2023.
7317
- ${Nm(i)}`}function Ud(n){if(n.kind==="php"){let i=n.phpVersion??"8.3";return`# ts-cloud serverless PHP app image (generated, multi-stage).
7318
- ${Nm(i,"phpbuild")}
7316
+ `}function YA(n={}){let i=n.phpVersion??"8.3";return`# ts-cloud PHP ${i} runtime layer (generated) — AWS Lambda provided.al2023.
7317
+ ${Bm(i)}`}function Hd(n){if(n.kind==="php"){let i=n.phpVersion??"8.3";return`# ts-cloud serverless PHP app image (generated, multi-stage).
7318
+ ${Bm(i,"phpbuild")}
7319
7319
 
7320
7320
  FROM public.ecr.aws/lambda/provided:al2023
7321
7321
  # Bake the relocated PHP runtime from the build stage.
@@ -7334,7 +7334,7 @@ COPY app/ \${LAMBDA_TASK_ROOT}/
7334
7334
 
7335
7335
  # Per-function CMD (e.g. index.http) is supplied via ImageConfig.Command.
7336
7336
  CMD [ "index.http" ]
7337
- `}function ja(){return pi(gi(import.meta.url))}function km(){return wt(Pe(ja(),"runtime.mjs"),"utf-8")}function Ka(n){return wt(Pe(ja(),`${n}-bootstrap`),"utf-8")}function $E(n){let i=n.architecture??"x86_64",s=i==="arm64"?"arm64":"x64",o=n.version.replace(/^v/,""),c=n.onStep??(()=>{}),l=Fa(Pe(Va(),"tscloud-node-layer-"));try{let u=o.includes(".")?o:hi(o),h=`node-v${u}-linux-${s}`,y=`https://nodejs.org/dist/v${u}/${h}.tar.xz`;c(`downloading Node ${u} (${i})`);let f=Pe(l,"node.tar.xz");qa(y,f),c("extracting node binary"),Tt("tar",["-xf",f,"-C",l,`${h}/bin/node`],{stdio:"inherit"});let b=wt(Pe(l,h,"bin","node"));c("packaging layer");let C=[{name:"bootstrap",data:Ka("node"),mode:493},{name:"runtime.mjs",data:km(),mode:420},{name:"bin/node",data:b,mode:493}];return{zip:Pi(C),architecture:i,version:u,fileCount:C.length}}finally{Ua(l,{recursive:!0,force:!0})}}function ME(n){let i=n.architecture??"x86_64",s=i==="arm64"?"bun-linux-aarch64":"bun-linux-x64",o=n.version==="latest"?"":n.version.replace(/^v/,""),c=n.onStep??(()=>{}),l=Fa(Pe(Va(),"tscloud-bun-layer-"));try{let u=o?`https://github.com/oven-sh/bun/releases/download/bun-v${o}/${s}.zip`:`https://github.com/oven-sh/bun/releases/latest/download/${s}.zip`;c(`downloading Bun ${o||"latest"} (${i})`);let h=Pe(l,"bun.zip");qa(u,h),c("extracting bun binary"),Tt("unzip",["-o","-q",h,"-d",l],{stdio:"inherit"});let y=wt(Pe(l,s,"bun"));c("packaging layer");let f=[{name:"bootstrap",data:Ka("bun"),mode:493},{name:"runtime.mjs",data:km(),mode:420},{name:"bin/bun",data:y,mode:493}];return{zip:Pi(f),architecture:i,version:o||"latest",fileCount:f.length}}finally{Ua(l,{recursive:!0,force:!0})}}function qa(n,i){Tt("curl",["-fsSL","-o",i,n],{stdio:["ignore","ignore","inherit"]})}function hi(n){let i=Tt("curl",["-fsSL","https://nodejs.org/dist/index.json"],{encoding:"utf-8"}),s=JSON.parse(i).find((o)=>o.version.startsWith(`v${n}.`));if(!s)throw Error(`No Node release found for major version ${n}`);return s.version.replace(/^v/,"")}var yo="x-ts-cloud-invoke-depth",Io="x-ts-cloud-invoke-chain",So="x-ts-cloud-trace-id";function Qd(n){return fi("sha256").update(n).digest("hex").slice(0,8)}var Ni={maxDepth:10,maxRepeats:3,maxInvocationsPerTrace:100,traceWindowMs:60000,breakerThreshold:5,breakerCooldownMs:60000};function Mt(n,i){if(typeof n.get==="function")return n.get(i)??void 0;let s=n;return s[i]??s[i.toLowerCase()]??s[i.toUpperCase()]}function Hd(n,i=64){if(!n)return[];return n.split(".").map((s)=>s.trim()).filter((s)=>/^[0-9a-f]{8}$/.test(s)).slice(-i)}function Gd(n,i=Ni){let s=Qd(n.functionId),o=Hd(Mt(n.headers,Io)),c=n.traceId??Mt(n.headers,So)??crypto.randomUUID(),l=[...o,s],u=o.filter((C)=>C===s).length,h=o[o.length-1]===s,y=Number.parseInt(Mt(n.headers,yo)??"",10),f=Math.max(l.length,Number.isFinite(y)?y+1:0),b="ok";if(f>i.maxDepth)b="depth_exceeded";else if(u>=i.maxRepeats)b="cycle_detected";else if(h&&i.maxRepeats<=1)b="self_invocation";return{reason:b,depth:f,chain:l,traceId:c,selfInvocation:h,repeats:u,propagate:{[yo]:String(f),[Io]:l.join("."),[So]:c}}}var Ha={ok:"",depth_exceeded:"Invocation chain is deeper than the configured limit; the call was refused to stop a runaway loop.",cycle_detected:"This function already appears in the invocation chain; the call was refused as a recursion loop.",self_invocation:"This function invoked itself directly; the call was refused.",trace_budget_exceeded:"This request has already made more invocations than its budget allows.",breaker_open:"Recursion protection is open for this function after repeated loop detections."};class Co{limits;clock;traces=new Map;breakers=new Map;constructor(n=Ni,i=()=>Date.now()){this.limits=n,this.clock=i}check(n){let i=this.clock();this.expireTraces(i);let s=Gd(n,this.limits),o=this.breakers.get(n.functionId);if(o?.openUntil!=null&&o.openUntil>i)return this.deny(n.functionId,s,"breaker_open",i,!1);if(s.reason!=="ok")return this.deny(n.functionId,s,s.reason,i,!0);let c=this.traces.get(s.traceId)??{count:0,firstAt:i};if(c.count>=this.limits.maxInvocationsPerTrace)return this.traces.set(s.traceId,c),this.deny(n.functionId,s,"trace_budget_exceeded",i,!0);if(this.traces.set(s.traceId,{count:c.count+1,firstAt:c.firstAt}),o)this.breakers.set(n.functionId,{consecutiveBlocks:0});return{...s,allowed:!0,reason:"ok",propagate:s.propagate}}deny(n,i,s,o,c){if(c){let l=this.breakers.get(n)??{consecutiveBlocks:0},u=l.consecutiveBlocks+1;this.breakers.set(n,{consecutiveBlocks:u,openUntil:u>=this.limits.breakerThreshold?o+this.limits.breakerCooldownMs:l.openUntil})}return{...i,allowed:!1,reason:s,message:Ha[s]}}breakerOpen(n){let i=this.breakers.get(n);return i?.openUntil!=null&&i.openUntil>this.clock()}reset(n){if(n){this.breakers.delete(n);return}this.breakers.clear(),this.traces.clear()}expireTraces(n){if(this.traces.size===0)return;for(let[i,s]of this.traces)if(n-s.firstAt>this.limits.traceWindowMs)this.traces.delete(i)}get trackedTraces(){return this.traces.size}}function qd(n){return{...n.propagate}}function Vd(n){return{status:508,headers:{"content-type":"application/json","x-ts-cloud-recursion-blocked":n.reason},body:{error:"recursion_blocked",reason:n.reason,message:n.message??Ha[n.reason],depth:n.depth,traceId:n.traceId}}}var Bm=new yi;function ba(n){let i=globalThis.process?.env?.[n];if(i==null||i==="")return;return i!=="0"&&i.toLowerCase()!=="false"}function Si(){let n=globalThis.process?.env??{};return n.TS_CLOUD_FUNCTION_ID||n.AWS_LAMBDA_FUNCTION_NAME||n.FUNCTION_NAME||"function"}function XA(n){let i=n===!1?{enabled:!1}:n??{},s=ba("TS_CLOUD_RECURSION_PROTECTION"),o=ba("TS_CLOUD_RECURSION_DETECTION_ONLY");return{enabled:s??i.enabled??!0,detectionOnly:o??i.detectionOnly??!1,limits:{...Ni,...i.limits},functionId:i.functionId??Si()}}var $e,be;function YA(){let n=globalThis.fetch;if(!n||$e===n)return()=>{};be=n;let i=async(s,o)=>{let c=Bm.getStore();if(!c)return be(s,o);let l=new Headers(o?.headers??(s instanceof Request?s.headers:void 0));for(let[u,h]of Object.entries(qd(c)))l.set(u,h);if(s instanceof Request)return be(new Request(s,{headers:l}),o);return be(s,{...o,headers:l})};return Object.assign(i,n),globalThis.fetch=i,$e=i,()=>{if(globalThis.fetch===$e&&be)globalThis.fetch=be;$e=void 0}}var dt,_t;function ZA(n){if(!dt||JSON.stringify(_t)!==JSON.stringify(n))dt=new Co(n),_t=n;return dt}function FE(){if(dt=void 0,_t=void 0,$e&&be&&globalThis.fetch===$e)globalThis.fetch=be;$e=void 0,be=void 0}function ey(n,i){let s=XA(i);if(!s.enabled)return;let o=ZA(s.limits),c={functionId:s.functionId,headers:n},l=o.check(c);return{verdict:l,blocked:!l.allowed&&!s.detectionOnly,observed:!l.allowed&&s.detectionOnly}}function ty(n,i){return YA(),Bm.run(n,i)}function UE(n){let i=n,s=i?.default??i;if(typeof s==="function")return{fetch:s};return{fetch:s?.fetch??i?.fetch,queue:s?.queue??i?.queue,cli:s?.cli??i?.cli}}var bi=/^(?:text\/|application\/(?:json|xml|javascript|graphql|x-www-form-urlencoded|.*\+json|.*\+xml)|image\/svg)/i;function Ai(n){if(!n)return!0;return bi.test(n)}function Ci(n){if(n?.maintenance)return n.maintenance;let i=globalThis.process?.env??{};return{enabled:i.MAINTENANCE_MODE==="1"||i.MAINTENANCE_MODE==="true",bypassSecret:i.MAINTENANCE_BYPASS_SECRET}}function ry(n){let i=n.requestContext?.domainName??"localhost",s=n.rawQueryString?`?${n.rawQueryString}`:"",o=`https://${i}${n.rawPath||"/"}${s}`,c=new Headers;for(let[h,y]of Object.entries(n.headers??{}))if(y!==void 0)c.set(h,y);if(n.cookies?.length)c.set("cookie",n.cookies.join("; "));let l=n.requestContext.http.method,u;if(n.body!==void 0&&l!=="GET"&&l!=="HEAD")u=n.isBase64Encoded?new Uint8Array(Buffer.from(n.body,"base64")):new TextEncoder().encode(n.body);return new Request(o,{method:l,headers:c,body:u})}async function _m(n){let i={},s=[],o=typeof n.headers.getSetCookie==="function"?n.headers.getSetCookie():[];for(let u of o)s.push(u);n.headers.forEach((u,h)=>{if(h.toLowerCase()==="set-cookie")return;i[h]=u});let c=Buffer.from(await n.arrayBuffer()),l=Ai(n.headers.get("content-type"));return{statusCode:n.status,headers:i,...s.length?{cookies:s}:{},body:l?c.toString("utf-8"):c.toString("base64"),isBase64Encoded:!l}}function ny(n,i){return async(s)=>{if(s.warmer)return{statusCode:200,headers:{"content-type":"text/plain"},body:"warm",isBase64Encoded:!1};if(!n)return{statusCode:501,headers:{"content-type":"text/plain"},body:"No HTTP handler configured",isBase64Encoded:!1};let o=Ci(i);if(o.enabled){let u=s.headers?.["x-maintenance-bypass"]??s.cookies?.find((h)=>h.startsWith("tscloud_bypass="))?.split("=")[1];if(!o.bypassSecret||u!==o.bypassSecret)return{statusCode:503,headers:{"content-type":"text/plain","retry-after":"120"},body:"Service temporarily unavailable (maintenance mode)",isBase64Encoded:!1}}let c=ey(s.headers??{},i?.recursionProtection);if(c?.blocked){let u=Vd(c.verdict);return{statusCode:u.status,headers:{...u.headers,"retry-after":"60"},body:JSON.stringify(u.body),isBase64Encoded:!1}}let l=ry(s);if(!c){let u=await n(l);return _m(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 ty(c.verdict,async()=>_m(await n(l)))}}function vi(n){try{return JSON.parse(n)}catch{return n}}function iy(n){return async(i)=>{let s=[];if(i.warmer)return{batchItemFailures:s};if(!n)return{batchItemFailures:s};for(let o of i.Records??[])try{await n(vi(o.body),o)}catch{s.push({itemIdentifier:o.messageId})}return{batchItemFailures:s}}}function sy(n){return async(i)=>{if(i.warmer)return{statusCode:0,output:"warm"};if(!n)return{statusCode:501,output:"No CLI handler configured"};return n(i)}}function QE(n,i){return{http:ny(n.fetch,i),queue:iy(n.queue),cli:sy(n.cli)}}function oy(n={}){let i=n.socketPath??"/tmp/.tscloud-fpm.sock",s=n.maxChildren??1;return`; ts-cloud php-fpm configuration (generated) — AWS Lambda custom runtime.
7337
+ `}function ja(){return pi(gi(import.meta.url))}function _m(){return wt(we(ja(),"runtime.mjs"),"utf-8")}function Ka(n){return wt(we(ja(),`${n}-bootstrap`),"utf-8")}function FE(n){let i=n.architecture??"x86_64",s=i==="arm64"?"arm64":"x64",o=n.version.replace(/^v/,""),c=n.onStep??(()=>{}),l=Fa(we(Va(),"tscloud-node-layer-"));try{let u=o.includes(".")?o:hi(o),h=`node-v${u}-linux-${s}`,y=`https://nodejs.org/dist/v${u}/${h}.tar.xz`;c(`downloading Node ${u} (${i})`);let f=we(l,"node.tar.xz");qa(y,f),c("extracting node binary"),Tt("tar",["-xf",f,"-C",l,`${h}/bin/node`],{stdio:"inherit"});let b=wt(we(l,h,"bin","node"));c("packaging layer");let C=[{name:"bootstrap",data:Ka("node"),mode:493},{name:"runtime.mjs",data:_m(),mode:420},{name:"bin/node",data:b,mode:493}];return{zip:ki(C),architecture:i,version:u,fileCount:C.length}}finally{Ua(l,{recursive:!0,force:!0})}}function UE(n){let i=n.architecture??"x86_64",s=i==="arm64"?"bun-linux-aarch64":"bun-linux-x64",o=n.version==="latest"?"":n.version.replace(/^v/,""),c=n.onStep??(()=>{}),l=Fa(we(Va(),"tscloud-bun-layer-"));try{let u=o?`https://github.com/oven-sh/bun/releases/download/bun-v${o}/${s}.zip`:`https://github.com/oven-sh/bun/releases/latest/download/${s}.zip`;c(`downloading Bun ${o||"latest"} (${i})`);let h=we(l,"bun.zip");qa(u,h),c("extracting bun binary"),Tt("unzip",["-o","-q",h,"-d",l],{stdio:"inherit"});let y=wt(we(l,s,"bun"));c("packaging layer");let f=[{name:"bootstrap",data:Ka("bun"),mode:493},{name:"runtime.mjs",data:_m(),mode:420},{name:"bin/bun",data:y,mode:493}];return{zip:ki(f),architecture:i,version:o||"latest",fileCount:f.length}}finally{Ua(l,{recursive:!0,force:!0})}}function qa(n,i){Tt("curl",["-fsSL","-o",i,n],{stdio:["ignore","ignore","inherit"]})}function hi(n){let i=Tt("curl",["-fsSL","https://nodejs.org/dist/index.json"],{encoding:"utf-8"}),s=JSON.parse(i).find((o)=>o.version.startsWith(`v${n}.`));if(!s)throw Error(`No Node release found for major version ${n}`);return s.version.replace(/^v/,"")}var So="x-ts-cloud-invoke-depth",Co="x-ts-cloud-invoke-chain",Eo="x-ts-cloud-trace-id";function Gd(n){return fi("sha256").update(n).digest("hex").slice(0,8)}var Bi={maxDepth:10,maxRepeats:3,maxInvocationsPerTrace:100,traceWindowMs:60000,breakerThreshold:5,breakerCooldownMs:60000};function Mt(n,i){if(typeof n.get==="function")return n.get(i)??void 0;let s=n;return s[i]??s[i.toLowerCase()]??s[i.toUpperCase()]}function qd(n,i=64){if(!n)return[];return n.split(".").map((s)=>s.trim()).filter((s)=>/^[0-9a-f]{8}$/.test(s)).slice(-i)}function Vd(n,i=Bi){let s=Gd(n.functionId),o=qd(Mt(n.headers,Co)),c=n.traceId??Mt(n.headers,Eo)??crypto.randomUUID(),l=[...o,s],u=o.filter((C)=>C===s).length,h=o[o.length-1]===s,y=Number.parseInt(Mt(n.headers,So)??"",10),f=Math.max(l.length,Number.isFinite(y)?y+1:0),b="ok";if(f>i.maxDepth)b="depth_exceeded";else if(u>=i.maxRepeats)b="cycle_detected";else if(h&&i.maxRepeats<=1)b="self_invocation";return{reason:b,depth:f,chain:l,traceId:c,selfInvocation:h,repeats:u,propagate:{[So]:String(f),[Co]:l.join("."),[Eo]:c}}}var Ha={ok:"",depth_exceeded:"Invocation chain is deeper than the configured limit; the call was refused to stop a runaway loop.",cycle_detected:"This function already appears in the invocation chain; the call was refused as a recursion loop.",self_invocation:"This function invoked itself directly; the call was refused.",trace_budget_exceeded:"This request has already made more invocations than its budget allows.",breaker_open:"Recursion protection is open for this function after repeated loop detections."};class bo{limits;clock;traces=new Map;breakers=new Map;constructor(n=Bi,i=()=>Date.now()){this.limits=n,this.clock=i}check(n){let i=this.clock();this.expireTraces(i);let s=Vd(n,this.limits),o=this.breakers.get(n.functionId);if(o?.openUntil!=null&&o.openUntil>i)return this.deny(n.functionId,s,"breaker_open",i,!1);if(s.reason!=="ok")return this.deny(n.functionId,s,s.reason,i,!0);let c=this.traces.get(s.traceId)??{count:0,firstAt:i};if(c.count>=this.limits.maxInvocationsPerTrace)return this.traces.set(s.traceId,c),this.deny(n.functionId,s,"trace_budget_exceeded",i,!0);if(this.traces.set(s.traceId,{count:c.count+1,firstAt:c.firstAt}),o)this.breakers.set(n.functionId,{consecutiveBlocks:0});return{...s,allowed:!0,reason:"ok",propagate:s.propagate}}deny(n,i,s,o,c){if(c){let l=this.breakers.get(n)??{consecutiveBlocks:0},u=l.consecutiveBlocks+1;this.breakers.set(n,{consecutiveBlocks:u,openUntil:u>=this.limits.breakerThreshold?o+this.limits.breakerCooldownMs:l.openUntil})}return{...i,allowed:!1,reason:s,message:Ha[s]}}breakerOpen(n){let i=this.breakers.get(n);return i?.openUntil!=null&&i.openUntil>this.clock()}reset(n){if(n){this.breakers.delete(n);return}this.breakers.clear(),this.traces.clear()}expireTraces(n){if(this.traces.size===0)return;for(let[i,s]of this.traces)if(n-s.firstAt>this.limits.traceWindowMs)this.traces.delete(i)}get trackedTraces(){return this.traces.size}}function jd(n){return{...n.propagate}}function zd(n){return{status:508,headers:{"content-type":"application/json","x-ts-cloud-recursion-blocked":n.reason},body:{error:"recursion_blocked",reason:n.reason,message:n.message??Ha[n.reason],depth:n.depth,traceId:n.traceId}}}var xm=new yi;function ba(n){let i=globalThis.process?.env?.[n];if(i==null||i==="")return;return i!=="0"&&i.toLowerCase()!=="false"}function Si(){let n=globalThis.process?.env??{};return n.TS_CLOUD_FUNCTION_ID||n.AWS_LAMBDA_FUNCTION_NAME||n.FUNCTION_NAME||"function"}function ZA(n){let i=n===!1?{enabled:!1}:n??{},s=ba("TS_CLOUD_RECURSION_PROTECTION"),o=ba("TS_CLOUD_RECURSION_DETECTION_ONLY");return{enabled:s??i.enabled??!0,detectionOnly:o??i.detectionOnly??!1,limits:{...Bi,...i.limits},functionId:i.functionId??Si()}}var $e,be;function ey(){let n=globalThis.fetch;if(!n||$e===n)return()=>{};be=n;let i=async(s,o)=>{let c=xm.getStore();if(!c)return be(s,o);let l=new Headers(o?.headers??(s instanceof Request?s.headers:void 0));for(let[u,h]of Object.entries(jd(c)))l.set(u,h);if(s instanceof Request)return be(new Request(s,{headers:l}),o);return be(s,{...o,headers:l})};return Object.assign(i,n),globalThis.fetch=i,$e=i,()=>{if(globalThis.fetch===$e&&be)globalThis.fetch=be;$e=void 0}}var dt,_t;function ty(n){if(!dt||JSON.stringify(_t)!==JSON.stringify(n))dt=new bo(n),_t=n;return dt}function QE(){if(dt=void 0,_t=void 0,$e&&be&&globalThis.fetch===$e)globalThis.fetch=be;$e=void 0,be=void 0}function ry(n,i){let s=ZA(i);if(!s.enabled)return;let o=ty(s.limits),c={functionId:s.functionId,headers:n},l=o.check(c);return{verdict:l,blocked:!l.allowed&&!s.detectionOnly,observed:!l.allowed&&s.detectionOnly}}function ny(n,i){return ey(),xm.run(n,i)}function HE(n){let i=n,s=i?.default??i;if(typeof s==="function")return{fetch:s};return{fetch:s?.fetch??i?.fetch,queue:s?.queue??i?.queue,cli:s?.cli??i?.cli}}var bi=/^(?:text\/|application\/(?:json|xml|javascript|graphql|x-www-form-urlencoded|.*\+json|.*\+xml)|image\/svg)/i;function Ai(n){if(!n)return!0;return bi.test(n)}function Ci(n){if(n?.maintenance)return n.maintenance;let i=globalThis.process?.env??{};return{enabled:i.MAINTENANCE_MODE==="1"||i.MAINTENANCE_MODE==="true",bypassSecret:i.MAINTENANCE_BYPASS_SECRET}}function iy(n){let i=n.requestContext?.domainName??"localhost",s=n.rawQueryString?`?${n.rawQueryString}`:"",o=`https://${i}${n.rawPath||"/"}${s}`,c=new Headers;for(let[h,y]of Object.entries(n.headers??{}))if(y!==void 0)c.set(h,y);if(n.cookies?.length)c.set("cookie",n.cookies.join("; "));let l=n.requestContext.http.method,u;if(n.body!==void 0&&l!=="GET"&&l!=="HEAD")u=n.isBase64Encoded?new Uint8Array(Buffer.from(n.body,"base64")):new TextEncoder().encode(n.body);return new Request(o,{method:l,headers:c,body:u})}async function Om(n){let i={},s=[],o=typeof n.headers.getSetCookie==="function"?n.headers.getSetCookie():[];for(let u of o)s.push(u);n.headers.forEach((u,h)=>{if(h.toLowerCase()==="set-cookie")return;i[h]=u});let c=Buffer.from(await n.arrayBuffer()),l=Ai(n.headers.get("content-type"));return{statusCode:n.status,headers:i,...s.length?{cookies:s}:{},body:l?c.toString("utf-8"):c.toString("base64"),isBase64Encoded:!l}}function sy(n,i){return async(s)=>{if(s.warmer)return{statusCode:200,headers:{"content-type":"text/plain"},body:"warm",isBase64Encoded:!1};if(!n)return{statusCode:501,headers:{"content-type":"text/plain"},body:"No HTTP handler configured",isBase64Encoded:!1};let o=Ci(i);if(o.enabled){let u=s.headers?.["x-maintenance-bypass"]??s.cookies?.find((h)=>h.startsWith("tscloud_bypass="))?.split("=")[1];if(!o.bypassSecret||u!==o.bypassSecret)return{statusCode:503,headers:{"content-type":"text/plain","retry-after":"120"},body:"Service temporarily unavailable (maintenance mode)",isBase64Encoded:!1}}let c=ry(s.headers??{},i?.recursionProtection);if(c?.blocked){let u=zd(c.verdict);return{statusCode:u.status,headers:{...u.headers,"retry-after":"60"},body:JSON.stringify(u.body),isBase64Encoded:!1}}let l=iy(s);if(!c){let u=await n(l);return Om(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 ny(c.verdict,async()=>Om(await n(l)))}}function vi(n){try{return JSON.parse(n)}catch{return n}}function oy(n){return async(i)=>{let s=[];if(i.warmer)return{batchItemFailures:s};if(!n)return{batchItemFailures:s};for(let o of i.Records??[])try{await n(vi(o.body),o)}catch{s.push({itemIdentifier:o.messageId})}return{batchItemFailures:s}}}function ay(n){return async(i)=>{if(i.warmer)return{statusCode:0,output:"warm"};if(!n)return{statusCode:501,output:"No CLI handler configured"};return n(i)}}function GE(n,i){return{http:sy(n.fetch,i),queue:oy(n.queue),cli:ay(n.cli)}}function cy(n={}){let i=n.socketPath??"/tmp/.tscloud-fpm.sock",s=n.maxChildren??1;return`; ts-cloud php-fpm configuration (generated) — AWS Lambda custom runtime.
7338
7338
  [global]
7339
7339
  daemonize = no
7340
7340
  error_log = ${n.errorLog??"/tmp/storage/logs/php-fpm.log"}
@@ -7351,5 +7351,5 @@ decorate_workers_output = no
7351
7351
  php_admin_value[error_log] = /dev/stderr
7352
7352
  php_admin_flag[log_errors] = on
7353
7353
  clear_env = no
7354
- `}function Li(){return za(Ii($i(import.meta.url)),"runtime-assets")}function ki(){let n=Li(),i=(s)=>Ei(za(n,s),"utf-8");return[{path:"bootstrap",contents:i("bootstrap"),mode:493},{path:"tscloud/runtime.php",contents:i("runtime.php"),mode:420},{path:"tscloud/octane-runtime.php",contents:i("octane-runtime.php"),mode:420},{path:"tscloud/cli-runtime.php",contents:i("cli-runtime.php"),mode:420},{path:"tscloud/fastcgi-client.php",contents:i("fastcgi-client.php"),mode:420},{path:"tscloud/php-fpm.conf",contents:oy(),mode:420}]}function jd(n={}){let i=n.cacheDriver??"dynamodb";return{APP_ENV:"production",LOG_CHANNEL:"stderr",CACHE_STORE:i,CACHE_DRIVER:i,SESSION_DRIVER:i,QUEUE_CONNECTION:"sqs",FILESYSTEM_DISK:"s3",VIEW_COMPILED_PATH:"/tmp/storage/framework/views",APP_SERVICES_CACHE:"/tmp/bootstrap/cache/services.php",APP_PACKAGES_CACHE:"/tmp/bootstrap/cache/packages.php",APP_CONFIG_CACHE:"/tmp/bootstrap/cache/config.php",APP_ROUTES_CACHE:"/tmp/bootstrap/cache/routes.php",APP_EVENTS_CACHE:"/tmp/bootstrap/cache/events.php"}}var ay=["composer install --no-dev --optimize-autoloader --no-interaction","php artisan config:cache","php artisan route:cache","php artisan event:cache","php artisan view:cache"];function*Ja(n){for(let i of Bi(n)){let s=xe(n,i);if(Qa(s).isDirectory())yield*Ja(s);else yield s}}function HE(n={}){let i=n.architecture??"x86_64",s=n.platform??(i==="arm64"?"linux/arm64":"linux/amd64"),o=n.onStep??(()=>{}),c=xi(xe(Fi(),"tscloud-php-layer-")),l="tscloud-php-layer:build";try{Gi(xe(c,"Dockerfile"),JA(n)),o("Building PHP runtime image (docker)"),ut("docker",["build","--platform",s,"-t","tscloud-php-layer:build",c],{stdio:"inherit"}),o("Extracting /opt/php from image");let u=ut("docker",["create","--platform",s,"tscloud-php-layer:build"],{encoding:"utf-8"}).trim(),h=xe(c,"opt");Oi(h,{recursive:!0});try{ut("docker",["cp",`${u}:/opt/php`,xe(h,"php")],{stdio:"inherit"})}finally{ut("docker",["rm",u],{stdio:"ignore"})}if(!Mi(xe(h,"php","bin","php")))throw Error("layer build produced no /opt/php/bin/php");let y=[];for(let C of Ja(h)){let T=Ui(h,C).replace(/\\/g,"/"),w=Qa(C).mode&73?493:420;y.push({name:T,data:_i(C),mode:w})}o("Injecting runtime assets");let f=new Set(ki().map((C)=>C.path)),b=y.filter((C)=>!f.has(C.name));for(let C of ki())b.push({name:C.path,data:C.contents,mode:C.mode});return o("Packaging layer ZIP"),{zip:Pi(b),architecture:i,fileCount:b.length}}finally{Wi(c,{recursive:!0,force:!0})}}var cy=[".git",".github","node_modules","tests","storage/logs","storage/framework/cache","storage/framework/sessions","storage/framework/views",".env",".env.local",".vapor",".ts-cloud","dist-lambda"];function zi(n,i){return i.some((s)=>n===s||n.startsWith(`${s}/`))}function*Xa(n,i,s){for(let o of Ki(n)){let c=Hi(n,o),l=Za(i,c).replace(/\\/g,"/");if(zi(l,s))continue;if(Ya(c).isDirectory())yield*Xa(c,i,s);else yield c}}function Eo(n){if(n.skipBuild)return;let i=ua(n.projectRoot??process.cwd()),s=n.app.build??ay;for(let o of s)n.onStep?.(`build: ${o}`),Vi(o,{stdio:"inherit",cwd:i})}function bo(n,i=[]){let s=ua(n),o=[...cy,oo(),...i],c=[];for(let l of Xa(s,s,o)){let u=Za(s,l).replace(/\\/g,"/"),h=(Ya(l).mode&73)!==0;c.push({name:u,data:qi(l),mode:h?493:420})}return c}function zd(n){let i=ua(n.projectRoot??process.cwd());Eo(n),n.onStep?.("packaging application tree");let s=bo(i,n.exclude);if(!s.length)throw Error(`No files to package under ${i}`);let o=Pi(s),c=n.app.handlers?.http??"public/index.php";return{zip:o,sha256:ji("sha256").update(o).digest("hex"),handlers:{http:c,queue:n.app.handlers?.queue??c,cli:n.app.handlers?.cli??c},fileCount:s.length}}class xm{optimizations=new Map;imageConfigs=new Map;ssgConfigs=new Map;prerenderConfigs=new Map;counter=0;createAssetOptimization(n){let i=`asset-opt-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.optimizations.set(i,s),s}createImageOptimization(n){let i=`image-opt-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.imageConfigs.set(i,s),s}createSSGConfig(n){let i=`ssg-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.ssgConfigs.set(i,s),s}createPrerenderConfig(n){let i=`prerender-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.prerenderConfigs.set(i,s),s}listOptimizations(){return Array.from(this.optimizations.values())}listImageConfigs(){return Array.from(this.imageConfigs.values())}clear(){this.optimizations.clear(),this.imageConfigs.clear(),this.ssgConfigs.clear(),this.prerenderConfigs.clear()}}var GE=new xm;class Om{policies=new Map;versioningConfigs=new Map;replicationRules=new Map;tieringConfigs=new Map;objectLocks=new Map;transferAcceleration=new Map;accessPoints=new Map;glacierConfigs=new Map;inventories=new Map;batchOps=new Map;eventNotifications=new Map;counter=0;createLifecyclePolicy(n,i){let s=`lifecycle-${Date.now()}-${this.counter++}`,o={id:s,transitions:n,expiration:i};return this.policies.set(s,o),o}enableVersioning(n=!1){let i=`versioning-${Date.now()}-${this.counter++}`,s={id:i,enabled:!0,mfaDelete:n};return this.versioningConfigs.set(i,s),s}createReplicationRule(n,i,s){let o=`replication-${Date.now()}-${this.counter++}`,c={id:o,sourceRegion:n,destRegion:i,destBucket:s};return this.replicationRules.set(o,c),c}createIntelligentTiering(n,i){let s=`tiering-${Date.now()}-${this.counter++}`,o={id:s,archiveDays:n,deepArchiveDays:i};return this.tieringConfigs.set(s,o),o}enableObjectLock(n){let i=`object-lock-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,mode:n.mode||"COMPLIANCE",retentionDays:n.retentionDays,retentionYears:n.retentionYears,legalHoldEnabled:n.legalHoldEnabled||!1};return this.objectLocks.set(i,s),s}enableTransferAcceleration(n){let i=`transfer-accel-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n,enabled:!0,endpoint:`${n}.s3-accelerate.amazonaws.com`};return this.transferAcceleration.set(i,s),s}createAccessPoint(n){let i=`access-point-${Date.now()}-${this.counter++}`,s={id:i,name:n.name,bucketName:n.bucketName,vpcId:n.vpcId,publicAccessBlock:n.publicAccessBlock!==!1,policy:n.policy};return this.accessPoints.set(i,s),s}createGlacierArchive(n){let i=`glacier-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,archiveType:n.archiveType,transitionDays:n.transitionDays,restoreConfig:n.restoreTier?{tier:n.restoreTier,days:n.restoreDays||7}:void 0};return this.glacierConfigs.set(i,s),s}createInventory(n){let i=`inventory-${Date.now()}-${this.counter++}`,s={id:i,sourceBucket:n.sourceBucket,destinationBucket:n.destinationBucket,schedule:n.schedule||"Daily",format:n.format||"CSV",includedFields:n.includedFields||["Size","LastModifiedDate","StorageClass","ETag"],prefix:n.prefix};return this.inventories.set(i,s),s}createBatchOperation(n){let i=`batch-op-${Date.now()}-${this.counter++}`,s={id:i,operation:n.operation,manifestBucket:n.manifestBucket,manifestKey:n.manifestKey,priority:n.priority||10,status:"pending"};return this.batchOps.set(i,s),s}executeBatchOperation(n){let i=this.batchOps.get(n);if(!i)throw Error(`Batch operation not found: ${n}`);return i.status="in_progress",i.totalObjects=1000,i.processedObjects=0,i}getBatchOperationStatus(n){return this.batchOps.get(n)}createLambdaNotification(n){let i=`event-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,events:n.events,destination:{type:"Lambda",arn:n.lambdaArn},filter:n.prefix||n.suffix?{prefix:n.prefix,suffix:n.suffix}:void 0};return this.eventNotifications.set(i,s),s}createSQSNotification(n){let i=`event-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,events:n.events,destination:{type:"SQS",arn:n.queueArn},filter:n.prefix||n.suffix?{prefix:n.prefix,suffix:n.suffix}:void 0};return this.eventNotifications.set(i,s),s}createSNSNotification(n){let i=`event-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,events:n.events,destination:{type:"SNS",arn:n.topicArn},filter:n.prefix||n.suffix?{prefix:n.prefix,suffix:n.suffix}:void 0};return this.eventNotifications.set(i,s),s}generateObjectLockCF(n){let i={ObjectLockEnabled:"Enabled",ObjectLockConfiguration:{ObjectLockEnabled:"Enabled",Rule:{DefaultRetention:{Mode:n.mode}}}};if(n.retentionDays)i.ObjectLockConfiguration.Rule.DefaultRetention.Days=n.retentionDays;if(n.retentionYears)i.ObjectLockConfiguration.Rule.DefaultRetention.Years=n.retentionYears;return i}generateTransferAccelerationCF(n){return{AccelerateConfiguration:{AccelerationStatus:n.enabled?"Enabled":"Suspended"}}}generateAccessPointCF(n){return{Type:"AWS::S3::AccessPoint",Properties:{Name:n.name,Bucket:n.bucketName,...n.vpcId&&{VpcConfiguration:{VpcId:n.vpcId}},PublicAccessBlockConfiguration:n.publicAccessBlock?{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}:void 0,...n.policy&&{Policy:n.policy}}}}generateInventoryCF(n){return{Type:"AWS::S3::Bucket",Properties:{InventoryConfigurations:[{Id:n.id,Destination:{BucketArn:`arn:aws:s3:::${n.destinationBucket}`,Format:n.format},Enabled:!0,IncludedObjectVersions:"Current",OptionalFields:n.includedFields,ScheduleFrequency:n.schedule,...n.prefix&&{Prefix:n.prefix}}]}}}generateEventNotificationCF(n){let i=n.destination.type==="Lambda"?"LambdaConfigurations":n.destination.type==="SQS"?"QueueConfigurations":"TopicConfigurations",s=n.destination.type==="Lambda"?"Function":n.destination.type==="SQS"?"Queue":"Topic",o={Event:n.events[0],[s]:n.destination.arn};if(n.filter)o.Filter={S3Key:{Rules:[...n.filter.prefix?[{Name:"prefix",Value:n.filter.prefix}]:[],...n.filter.suffix?[{Name:"suffix",Value:n.filter.suffix}]:[]]}};return{NotificationConfiguration:{[i]:[o]}}}clear(){this.policies.clear(),this.versioningConfigs.clear(),this.replicationRules.clear(),this.tieringConfigs.clear(),this.objectLocks.clear(),this.transferAcceleration.clear(),this.accessPoints.clear(),this.glacierConfigs.clear(),this.inventories.clear(),this.batchOps.clear(),this.eventNotifications.clear()}}var qE=new Om;class Lm{checks=new Map;synthetics=new Map;uptimeTrackers=new Map;counter=0;createHealthCheck(n,i=30,s=10){let o=`health-${Date.now()}-${this.counter++}`,c={id:o,url:n,interval:i,timeout:s,status:"healthy"};return this.checks.set(o,c),c}createSyntheticMonitor(n,i,s,o){let c=`synthetic-${Date.now()}-${this.counter++}`,l={id:c,name:n,script:i,frequency:s,locations:o};return this.synthetics.set(c,l),l}trackUptime(n,i,s){let o=`uptime-${Date.now()}-${this.counter++}`,c=i/(i+s)*100,l={id:o,resource:n,uptime:i,downtime:s,availability:c};return this.uptimeTrackers.set(o,l),l}clear(){this.checks.clear(),this.synthetics.clear(),this.uptimeTrackers.clear()}}var VE=new Lm;class $m{wafRules=new Map;shieldProtections=new Map;securityGroups=new Map;nacls=new Map;counter=0;createWAFRule(n,i,s,o){let c=`waf-${Date.now()}-${this.counter++}`,l={id:c,name:n,priority:i,action:s,conditions:o};return this.wafRules.set(c,l),l}enableShield(n,i="standard"){let s=`shield-${Date.now()}-${this.counter++}`,o={id:s,resourceArn:n,protectionType:i};return this.shieldProtections.set(s,o),o}createSecurityGroup(n,i,s){let o=`sg-${Date.now()}-${this.counter++}`,c={id:o,name:n,vpcId:i,rules:s};return this.securityGroups.set(o,c),c}createNACL(n,i){let s=`nacl-${Date.now()}-${this.counter++}`,o={id:s,vpcId:n,rules:i};return this.nacls.set(s,o),o}clear(){this.wafRules.clear(),this.shieldProtections.clear(),this.securityGroups.clear(),this.nacls.clear()}}var jE=new $m;class Mm{strategies=new Map;allocations=new Map;groups=new Map;counter=0;createTaggingStrategy(n,i){let s=`tagging-${Date.now()}-${this.counter++}`,o={id:s,tags:n,resources:i};return this.strategies.set(s,o),o}createCostAllocation(n,i){let s=`cost-${Date.now()}-${this.counter++}`,o={id:s,tagKey:n,allocations:i};return this.allocations.set(s,o),o}createResourceGroup(n,i,s){let o=`group-${Date.now()}-${this.counter++}`,c={id:o,name:n,query:{resourceTypeFilters:i,tagFilters:s}};return this.groups.set(o,c),c}clear(){this.strategies.clear(),this.allocations.clear(),this.groups.clear()}}var zE=new Mm;
7355
- export{sg,x,og,eA,dI,tA,lI,uI,pI,gI,mI,hI,fI,yI,II,SI,ag,cg,yd,Id,oo,O,d,Sd,dg,L,Cd,p,rA,Ti,Ed,bd,ue,vd,CI,r,t,EI,bI,g,vI,TI,wI,RI,DI,Ht,Td,ao,nA,PI,NI,Te,qe,wd,lg,ug,kI,pg,gg,mg,Rd,hg,we,Qr,Gt,Dd,qt,pe,iA,Pd,co,fg,Ag,yg,Ig,Nd,BI,M,S,a,A,Ve,m,sA,je,F,mt,_I,oA,U,kd,Re,Vt,lo,Z,Bd,ee,aA,uo,Q,H,P,wi,v,jt,ht,G,e,po,xI,Sg,_d,OI,LI,$I,MI,xd,FI,UI,QI,HI,GI,qI,VI,jI,zI,KI,WI,JI,cA,dA,lA,uA,pA,gA,mA,zt,Cg,Eg,Hr,Ri,XI,bg,YI,ZI,Gr,eS,tS,rS,nS,iS,sS,hA,fA,AA,yA,IA,go,oS,SA,CA,EA,q,aS,ze,mo,Kt,bA,vg,vA,TA,wA,Tg,te,cS,dS,lS,uS,RA,pS,V,gS,mS,hS,wg,Rg,fS,Dg,Pg,AS,yS,IS,SS,CS,DA,Od,ES,bS,vS,TS,wS,PA,NA,RS,DS,PS,NS,kS,BS,_S,xS,OS,Ng,Ld,LS,$S,MS,FS,kg,Bg,_g,US,xg,QS,HS,GS,qS,Og,VS,jS,zS,KS,WS,JS,XS,YS,kA,BA,_A,xA,Lg,ZS,eC,tC,rC,nC,iC,sC,oC,aC,OA,LA,$A,MA,cC,dC,$g,lC,Mg,Fg,Ug,Qg,uC,pC,gC,mC,De,Di,hC,fC,AC,yC,IC,SC,CC,EC,FA,bC,vC,Hg,Gg,TC,wC,UA,RC,DC,PC,NC,kC,BC,_C,xC,OC,LC,$C,MC,FC,UC,QC,HC,GC,qC,VC,jC,zC,qg,KC,Vg,WC,jg,JC,zg,XC,Kg,YC,qr,ZC,Wg,eE,ho,tE,Jg,rE,Xg,nE,Yg,iE,Zg,sE,em,oE,Vr,aE,tm,cE,rm,dE,nm,lE,im,uE,sm,pE,om,gE,am,mE,cm,hE,dm,fE,lm,AE,um,yE,pm,IE,gm,SE,mm,CE,hm,EE,fm,bE,Am,vE,ym,TE,Im,wE,Sm,RE,Cm,DE,Em,PE,bm,NE,vm,kE,Tm,BE,QA,HA,GA,qA,wm,_E,Rm,xE,Dm,OE,Pm,LE,Pi,VA,jA,fo,$d,jr,zA,Ao,Wt,Md,Fd,KA,WA,Nm,JA,Ud,km,$E,ME,yo,Io,So,Qd,Ni,Hd,Gd,Co,qd,Vd,Bm,XA,YA,ZA,FE,ey,ty,UE,ry,_m,ny,iy,sy,QE,oy,ki,jd,ay,HE,cy,Eo,bo,zd,xm,GE,Om,qE,Lm,VE,$m,jE,Mm,zE};
7354
+ `}function Ii(){return za(wi(Ei(import.meta.url)),"runtime-assets")}function _i(){let n=Ii(),i=(s)=>Ti(za(n,s),"utf-8");return[{path:"bootstrap",contents:i("bootstrap"),mode:493},{path:"tscloud/runtime.php",contents:i("runtime.php"),mode:420},{path:"tscloud/octane-runtime.php",contents:i("octane-runtime.php"),mode:420},{path:"tscloud/cli-runtime.php",contents:i("cli-runtime.php"),mode:420},{path:"tscloud/fastcgi-client.php",contents:i("fastcgi-client.php"),mode:420},{path:"tscloud/php-fpm.conf",contents:cy(),mode:420}]}function Kd(n={}){let i=n.cacheDriver??"dynamodb";return{APP_ENV:"production",LOG_CHANNEL:"stderr",CACHE_STORE:i,CACHE_DRIVER:i,SESSION_DRIVER:i,QUEUE_CONNECTION:"sqs",FILESYSTEM_DISK:"s3",VIEW_COMPILED_PATH:"/tmp/storage/framework/views",APP_SERVICES_CACHE:"/tmp/bootstrap/cache/services.php",APP_PACKAGES_CACHE:"/tmp/bootstrap/cache/packages.php",APP_CONFIG_CACHE:"/tmp/bootstrap/cache/config.php",APP_ROUTES_CACHE:"/tmp/bootstrap/cache/routes.php",APP_EVENTS_CACHE:"/tmp/bootstrap/cache/events.php"}}var dy=["composer install --no-dev --optimize-autoloader --no-interaction","php artisan config:cache","php artisan route:cache","php artisan event:cache","php artisan view:cache"];function*Ja(n){for(let i of Oi(n)){let s=xe(n,i);if(Qa(s).isDirectory())yield*Ja(s);else yield s}}function qE(n={}){let i=n.architecture??"x86_64",s=n.platform??(i==="arm64"?"linux/arm64":"linux/amd64"),o=n.onStep??(()=>{}),c=Mi(xe(Fi(),"tscloud-php-layer-")),l="tscloud-php-layer:build";try{Gi(xe(c,"Dockerfile"),YA(n)),o("Building PHP runtime image (docker)"),ut("docker",["build","--platform",s,"-t","tscloud-php-layer:build",c],{stdio:"inherit"}),o("Extracting /opt/php from image");let u=ut("docker",["create","--platform",s,"tscloud-php-layer:build"],{encoding:"utf-8"}).trim(),h=xe(c,"opt");Li(h,{recursive:!0});try{ut("docker",["cp",`${u}:/opt/php`,xe(h,"php")],{stdio:"inherit"})}finally{ut("docker",["rm",u],{stdio:"ignore"})}if(!$i(xe(h,"php","bin","php")))throw Error("layer build produced no /opt/php/bin/php");let y=[];for(let C of Ja(h)){let T=Ui(h,C).replace(/\\/g,"/"),w=Qa(C).mode&73?493:420;y.push({name:T,data:xi(C),mode:w})}o("Injecting runtime assets");let f=new Set(_i().map((C)=>C.path)),b=y.filter((C)=>!f.has(C.name));for(let C of _i())b.push({name:C.path,data:C.contents,mode:C.mode});return o("Packaging layer ZIP"),{zip:ki(b),architecture:i,fileCount:b.length}}finally{Wi(c,{recursive:!0,force:!0})}}var ly=[".git",".github","node_modules","tests","storage/logs","storage/framework/cache","storage/framework/sessions","storage/framework/views",".env",".env.local",".vapor",".ts-cloud","dist-lambda"];function zi(n,i){return i.some((s)=>n===s||n.startsWith(`${s}/`))}function*Xa(n,i,s){for(let o of Ki(n)){let c=Hi(n,o),l=Za(i,c).replace(/\\/g,"/");if(zi(l,s))continue;if(Ya(c).isDirectory())yield*Xa(c,i,s);else yield c}}function vo(n){if(n.skipBuild)return;let i=ua(n.projectRoot??process.cwd()),s=n.app.build??dy;for(let o of s)n.onStep?.(`build: ${o}`),Vi(o,{stdio:"inherit",cwd:i})}function To(n,i=[]){let s=ua(n),o=[...ly,co(),...i],c=[];for(let l of Xa(s,s,o)){let u=Za(s,l).replace(/\\/g,"/"),h=(Ya(l).mode&73)!==0;c.push({name:u,data:qi(l),mode:h?493:420})}return c}function Wd(n){let i=ua(n.projectRoot??process.cwd());vo(n),n.onStep?.("packaging application tree");let s=To(i,n.exclude);if(!s.length)throw Error(`No files to package under ${i}`);let o=ki(s),c=n.app.handlers?.http??"public/index.php";return{zip:o,sha256:ji("sha256").update(o).digest("hex"),handlers:{http:c,queue:n.app.handlers?.queue??c,cli:n.app.handlers?.cli??c},fileCount:s.length}}class Lm{optimizations=new Map;imageConfigs=new Map;ssgConfigs=new Map;prerenderConfigs=new Map;counter=0;createAssetOptimization(n){let i=`asset-opt-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.optimizations.set(i,s),s}createImageOptimization(n){let i=`image-opt-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.imageConfigs.set(i,s),s}createSSGConfig(n){let i=`ssg-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.ssgConfigs.set(i,s),s}createPrerenderConfig(n){let i=`prerender-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.prerenderConfigs.set(i,s),s}listOptimizations(){return Array.from(this.optimizations.values())}listImageConfigs(){return Array.from(this.imageConfigs.values())}clear(){this.optimizations.clear(),this.imageConfigs.clear(),this.ssgConfigs.clear(),this.prerenderConfigs.clear()}}var VE=new Lm;class $m{policies=new Map;versioningConfigs=new Map;replicationRules=new Map;tieringConfigs=new Map;objectLocks=new Map;transferAcceleration=new Map;accessPoints=new Map;glacierConfigs=new Map;inventories=new Map;batchOps=new Map;eventNotifications=new Map;counter=0;createLifecyclePolicy(n,i){let s=`lifecycle-${Date.now()}-${this.counter++}`,o={id:s,transitions:n,expiration:i};return this.policies.set(s,o),o}enableVersioning(n=!1){let i=`versioning-${Date.now()}-${this.counter++}`,s={id:i,enabled:!0,mfaDelete:n};return this.versioningConfigs.set(i,s),s}createReplicationRule(n,i,s){let o=`replication-${Date.now()}-${this.counter++}`,c={id:o,sourceRegion:n,destRegion:i,destBucket:s};return this.replicationRules.set(o,c),c}createIntelligentTiering(n,i){let s=`tiering-${Date.now()}-${this.counter++}`,o={id:s,archiveDays:n,deepArchiveDays:i};return this.tieringConfigs.set(s,o),o}enableObjectLock(n){let i=`object-lock-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,mode:n.mode||"COMPLIANCE",retentionDays:n.retentionDays,retentionYears:n.retentionYears,legalHoldEnabled:n.legalHoldEnabled||!1};return this.objectLocks.set(i,s),s}enableTransferAcceleration(n){let i=`transfer-accel-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n,enabled:!0,endpoint:`${n}.s3-accelerate.amazonaws.com`};return this.transferAcceleration.set(i,s),s}createAccessPoint(n){let i=`access-point-${Date.now()}-${this.counter++}`,s={id:i,name:n.name,bucketName:n.bucketName,vpcId:n.vpcId,publicAccessBlock:n.publicAccessBlock!==!1,policy:n.policy};return this.accessPoints.set(i,s),s}createGlacierArchive(n){let i=`glacier-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,archiveType:n.archiveType,transitionDays:n.transitionDays,restoreConfig:n.restoreTier?{tier:n.restoreTier,days:n.restoreDays||7}:void 0};return this.glacierConfigs.set(i,s),s}createInventory(n){let i=`inventory-${Date.now()}-${this.counter++}`,s={id:i,sourceBucket:n.sourceBucket,destinationBucket:n.destinationBucket,schedule:n.schedule||"Daily",format:n.format||"CSV",includedFields:n.includedFields||["Size","LastModifiedDate","StorageClass","ETag"],prefix:n.prefix};return this.inventories.set(i,s),s}createBatchOperation(n){let i=`batch-op-${Date.now()}-${this.counter++}`,s={id:i,operation:n.operation,manifestBucket:n.manifestBucket,manifestKey:n.manifestKey,priority:n.priority||10,status:"pending"};return this.batchOps.set(i,s),s}executeBatchOperation(n){let i=this.batchOps.get(n);if(!i)throw Error(`Batch operation not found: ${n}`);return i.status="in_progress",i.totalObjects=1000,i.processedObjects=0,i}getBatchOperationStatus(n){return this.batchOps.get(n)}createLambdaNotification(n){let i=`event-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,events:n.events,destination:{type:"Lambda",arn:n.lambdaArn},filter:n.prefix||n.suffix?{prefix:n.prefix,suffix:n.suffix}:void 0};return this.eventNotifications.set(i,s),s}createSQSNotification(n){let i=`event-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,events:n.events,destination:{type:"SQS",arn:n.queueArn},filter:n.prefix||n.suffix?{prefix:n.prefix,suffix:n.suffix}:void 0};return this.eventNotifications.set(i,s),s}createSNSNotification(n){let i=`event-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,events:n.events,destination:{type:"SNS",arn:n.topicArn},filter:n.prefix||n.suffix?{prefix:n.prefix,suffix:n.suffix}:void 0};return this.eventNotifications.set(i,s),s}generateObjectLockCF(n){let i={ObjectLockEnabled:"Enabled",ObjectLockConfiguration:{ObjectLockEnabled:"Enabled",Rule:{DefaultRetention:{Mode:n.mode}}}};if(n.retentionDays)i.ObjectLockConfiguration.Rule.DefaultRetention.Days=n.retentionDays;if(n.retentionYears)i.ObjectLockConfiguration.Rule.DefaultRetention.Years=n.retentionYears;return i}generateTransferAccelerationCF(n){return{AccelerateConfiguration:{AccelerationStatus:n.enabled?"Enabled":"Suspended"}}}generateAccessPointCF(n){return{Type:"AWS::S3::AccessPoint",Properties:{Name:n.name,Bucket:n.bucketName,...n.vpcId&&{VpcConfiguration:{VpcId:n.vpcId}},PublicAccessBlockConfiguration:n.publicAccessBlock?{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}:void 0,...n.policy&&{Policy:n.policy}}}}generateInventoryCF(n){return{Type:"AWS::S3::Bucket",Properties:{InventoryConfigurations:[{Id:n.id,Destination:{BucketArn:`arn:aws:s3:::${n.destinationBucket}`,Format:n.format},Enabled:!0,IncludedObjectVersions:"Current",OptionalFields:n.includedFields,ScheduleFrequency:n.schedule,...n.prefix&&{Prefix:n.prefix}}]}}}generateEventNotificationCF(n){let i=n.destination.type==="Lambda"?"LambdaConfigurations":n.destination.type==="SQS"?"QueueConfigurations":"TopicConfigurations",s=n.destination.type==="Lambda"?"Function":n.destination.type==="SQS"?"Queue":"Topic",o={Event:n.events[0],[s]:n.destination.arn};if(n.filter)o.Filter={S3Key:{Rules:[...n.filter.prefix?[{Name:"prefix",Value:n.filter.prefix}]:[],...n.filter.suffix?[{Name:"suffix",Value:n.filter.suffix}]:[]]}};return{NotificationConfiguration:{[i]:[o]}}}clear(){this.policies.clear(),this.versioningConfigs.clear(),this.replicationRules.clear(),this.tieringConfigs.clear(),this.objectLocks.clear(),this.transferAcceleration.clear(),this.accessPoints.clear(),this.glacierConfigs.clear(),this.inventories.clear(),this.batchOps.clear(),this.eventNotifications.clear()}}var jE=new $m;class Mm{checks=new Map;synthetics=new Map;uptimeTrackers=new Map;counter=0;createHealthCheck(n,i=30,s=10){let o=`health-${Date.now()}-${this.counter++}`,c={id:o,url:n,interval:i,timeout:s,status:"healthy"};return this.checks.set(o,c),c}createSyntheticMonitor(n,i,s,o){let c=`synthetic-${Date.now()}-${this.counter++}`,l={id:c,name:n,script:i,frequency:s,locations:o};return this.synthetics.set(c,l),l}trackUptime(n,i,s){let o=`uptime-${Date.now()}-${this.counter++}`,c=i/(i+s)*100,l={id:o,resource:n,uptime:i,downtime:s,availability:c};return this.uptimeTrackers.set(o,l),l}clear(){this.checks.clear(),this.synthetics.clear(),this.uptimeTrackers.clear()}}var zE=new Mm;class Fm{wafRules=new Map;shieldProtections=new Map;securityGroups=new Map;nacls=new Map;counter=0;createWAFRule(n,i,s,o){let c=`waf-${Date.now()}-${this.counter++}`,l={id:c,name:n,priority:i,action:s,conditions:o};return this.wafRules.set(c,l),l}enableShield(n,i="standard"){let s=`shield-${Date.now()}-${this.counter++}`,o={id:s,resourceArn:n,protectionType:i};return this.shieldProtections.set(s,o),o}createSecurityGroup(n,i,s){let o=`sg-${Date.now()}-${this.counter++}`,c={id:o,name:n,vpcId:i,rules:s};return this.securityGroups.set(o,c),c}createNACL(n,i){let s=`nacl-${Date.now()}-${this.counter++}`,o={id:s,vpcId:n,rules:i};return this.nacls.set(s,o),o}clear(){this.wafRules.clear(),this.shieldProtections.clear(),this.securityGroups.clear(),this.nacls.clear()}}var KE=new Fm;class Um{strategies=new Map;allocations=new Map;groups=new Map;counter=0;createTaggingStrategy(n,i){let s=`tagging-${Date.now()}-${this.counter++}`,o={id:s,tags:n,resources:i};return this.strategies.set(s,o),o}createCostAllocation(n,i){let s=`cost-${Date.now()}-${this.counter++}`,o={id:s,tagKey:n,allocations:i};return this.allocations.set(s,o),o}createResourceGroup(n,i,s){let o=`group-${Date.now()}-${this.counter++}`,c={id:o,name:n,query:{resourceTypeFilters:i,tagFilters:s}};return this.groups.set(o,c),c}clear(){this.strategies.clear(),this.allocations.clear(),this.groups.clear()}}var WE=new Um;
7355
+ export{ag,O,cg,rA,uI,nA,pI,gI,mI,hI,fI,yI,II,SI,CI,EI,dg,lg,Sd,Cd,co,L,d,Ed,ug,M,bd,p,iA,Ri,vd,Td,ge,wd,bI,r,t,vI,TI,g,wI,RI,DI,PI,NI,Gt,Rd,lo,sA,kI,BI,Re,je,Dd,pg,gg,_I,mg,hg,fg,Pd,Ag,De,Gr,qt,Nd,Vt,me,oA,kd,uo,yg,Ig,Sg,Cg,Bd,xI,F,S,a,A,ze,m,aA,Ke,U,ft,OI,cA,Q,_d,Pe,jt,po,ee,xd,te,dA,go,H,G,P,Di,v,zt,At,q,e,mo,LI,Eg,Od,$I,MI,FI,UI,Ld,QI,HI,GI,qI,VI,jI,zI,KI,WI,JI,XI,YI,lA,uA,pA,gA,mA,hA,fA,Kt,bg,vg,qr,Pi,ZI,Tg,eS,tS,Vr,rS,nS,iS,sS,oS,aS,AA,yA,IA,SA,CA,ho,cS,EA,bA,vA,V,dS,We,fo,Wt,TA,wg,wA,RA,DA,Rg,re,lS,uS,pS,gS,PA,mS,j,hS,fS,AS,Dg,Pg,yS,Ng,kg,IS,SS,CS,ES,bS,NA,$d,vS,TS,wS,RS,DS,kA,BA,PS,NS,kS,BS,_S,xS,OS,LS,$S,Bg,Md,MS,FS,US,QS,_g,xg,Og,HS,Lg,GS,qS,VS,jS,$g,zS,KS,WS,JS,XS,YS,ZS,eC,_A,xA,OA,LA,Mg,tC,rC,nC,iC,sC,oC,aC,cC,dC,$A,MA,FA,UA,lC,uC,Fg,pC,Ug,Qg,Hg,Gg,gC,mC,hC,fC,Ne,Ni,AC,yC,IC,SC,CC,EC,bC,vC,QA,TC,wC,qg,Vg,RC,DC,HA,PC,NC,kC,BC,_C,xC,OC,LC,$C,MC,FC,UC,QC,HC,GC,qC,VC,jC,zC,KC,WC,jg,JC,zg,XC,Kg,YC,Wg,ZC,Jg,eE,jr,tE,Xg,rE,Ao,nE,Yg,iE,Zg,sE,em,oE,tm,aE,rm,cE,zr,dE,nm,lE,im,uE,sm,pE,om,gE,am,mE,cm,hE,dm,fE,lm,AE,um,yE,pm,IE,gm,SE,mm,CE,hm,EE,fm,bE,Am,vE,ym,TE,Im,wE,Sm,RE,Cm,DE,Em,PE,bm,NE,vm,kE,Tm,BE,wm,_E,Rm,xE,GA,qA,VA,jA,Dm,OE,Pm,LE,Nm,$E,km,ME,ki,zA,KA,yo,Fd,Kr,WA,Io,Jt,Ud,Qd,JA,XA,Bm,YA,Hd,_m,FE,UE,So,Co,Eo,Gd,Bi,qd,Vd,bo,jd,zd,xm,ZA,ey,ty,QE,ry,ny,HE,iy,Om,sy,oy,ay,GE,cy,_i,Kd,dy,qE,ly,vo,To,Wd,Lm,VE,$m,jE,Mm,zE,Fm,KE,Um,WE};