@stacksjs/ts-cloud 0.11.7 → 0.12.1

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 (236) hide show
  1. package/dist/aws/index.js +1 -1
  2. package/dist/bin/chunk-0rtn6q5x.js +3 -0
  3. package/dist/bin/chunk-258ehp9s.js +1 -0
  4. package/dist/bin/chunk-2yctv06c.js +1 -0
  5. package/dist/bin/chunk-3276rveh.js +37 -0
  6. package/dist/bin/chunk-3m665jwp.js +70 -0
  7. package/dist/bin/chunk-3s2p9vxj.js +1 -0
  8. package/dist/bin/chunk-4esma5m9.js +1 -0
  9. package/dist/bin/chunk-4n0j3n3b.js +2 -0
  10. package/dist/bin/chunk-54bqchag.js +92 -0
  11. package/dist/bin/{chunk-4q6tad44.js → chunk-5bhx3bsa.js} +121 -121
  12. package/dist/bin/chunk-5zagqd20.js +1 -0
  13. package/dist/bin/chunk-7hw2js5h.js +512 -0
  14. package/dist/bin/chunk-8h1qr6x4.js +50 -0
  15. package/dist/bin/{chunk-w32xv8n4.js → chunk-9vdc7adf.js} +6 -6
  16. package/dist/bin/chunk-a1dd6sby.js +1 -0
  17. package/dist/bin/chunk-a4dw35gs.js +1 -0
  18. package/dist/bin/chunk-a9d55ker.js +1 -0
  19. package/dist/bin/chunk-awa1qade.js +9 -0
  20. package/dist/bin/chunk-b6by94pk.js +2 -0
  21. package/dist/bin/chunk-c8sypnbe.js +2 -0
  22. package/dist/bin/chunk-cx4e3d4w.js +1 -0
  23. package/dist/bin/chunk-d5a3vheh.js +2 -0
  24. package/dist/bin/chunk-e1fym2bd.js +1 -0
  25. package/dist/bin/chunk-ej4h0q2y.js +1 -0
  26. package/dist/bin/chunk-ett305ym.js +4 -0
  27. package/dist/bin/chunk-f11xf3n6.js +2 -0
  28. package/dist/bin/chunk-fq7ktvgy.js +3 -0
  29. package/dist/bin/chunk-fyq4th2m.js +1 -0
  30. package/dist/bin/chunk-g67qr8yf.js +1 -0
  31. package/dist/bin/chunk-gc82cx4h.js +1 -0
  32. package/dist/bin/chunk-hchtvpr9.js +1 -0
  33. package/dist/bin/chunk-hpe4jjce.js +1 -0
  34. package/dist/bin/chunk-k5vprsef.js +6 -0
  35. package/dist/bin/chunk-m22krd4z.js +3 -0
  36. package/dist/bin/chunk-mkppcwz8.js +1 -0
  37. package/dist/bin/chunk-mpjg0kc7.js +2 -0
  38. package/dist/bin/chunk-mrm4m4dk.js +2 -0
  39. package/dist/bin/chunk-nff46rxd.js +1 -0
  40. package/dist/bin/chunk-np1z3bgt.js +1 -0
  41. package/dist/bin/chunk-nskxkk6r.js +1 -0
  42. package/dist/bin/chunk-pez932b1.js +111 -0
  43. package/dist/bin/chunk-qsdf5kzk.js +2 -0
  44. package/dist/bin/chunk-r61qmhv1.js +2 -0
  45. package/dist/bin/chunk-r6gdcz5c.js +1 -0
  46. package/dist/bin/chunk-satwnr42.js +2 -0
  47. package/dist/bin/{chunk-dz1ec589.js → chunk-scqmd4qv.js} +30 -30
  48. package/dist/bin/chunk-smbycpt5.js +44 -0
  49. package/dist/bin/chunk-sn7e0sn7.js +2 -0
  50. package/dist/bin/chunk-ss574pka.js +1 -0
  51. package/dist/bin/chunk-tj0xb2d8.js +585 -0
  52. package/dist/bin/chunk-v3rzf9d0.js +141 -0
  53. package/dist/bin/chunk-wnpma6t3.js +34 -0
  54. package/dist/bin/chunk-xan0e052.js +5 -0
  55. package/dist/bin/chunk-xbk2y43r.js +60 -0
  56. package/dist/bin/chunk-xjp3v95e.js +6 -0
  57. package/dist/bin/chunk-xyt490vp.js +6 -0
  58. package/dist/bin/chunk-yn9r02gy.js +1 -0
  59. package/dist/bin/chunk-zhkhn9cc.js +1 -0
  60. package/dist/bin/cli.js +445 -430
  61. package/dist/bin/dashboard-server.js +1 -1
  62. package/dist/chunk-0zf72ngj.js +1 -0
  63. package/dist/chunk-2hpjte1d.js +704 -0
  64. package/dist/chunk-4m6gwhwr.js +5 -0
  65. package/dist/chunk-5m29dhke.js +34 -0
  66. package/dist/chunk-6fzeemcs.js +114 -0
  67. package/dist/{chunk-zz52xje8.js → chunk-6xcbfs2r.js} +111 -111
  68. package/dist/chunk-bpnhqb70.js +6 -0
  69. package/dist/chunk-ead1nkbr.js +60 -0
  70. package/dist/chunk-fea461tj.js +141 -0
  71. package/dist/chunk-fvjczc73.js +1 -0
  72. package/dist/chunk-gearw6rk.js +4 -0
  73. package/dist/chunk-j60hesb3.js +2 -0
  74. package/dist/chunk-pmgtmt3d.js +1 -0
  75. package/dist/chunk-prf2pkvq.js +5 -0
  76. package/dist/chunk-q0wffgw5.js +37 -0
  77. package/dist/chunk-qcemnt35.js +50 -0
  78. package/dist/chunk-qvbwsaay.js +1 -0
  79. package/dist/chunk-r2pbqcnz.js +2 -0
  80. package/dist/chunk-r6110zv2.js +1 -0
  81. package/dist/chunk-rr1yaj55.js +2 -0
  82. package/dist/chunk-wcrj06cg.js +44 -0
  83. package/dist/chunk-wte9mh18.js +92 -0
  84. package/dist/{chunk-aw0cgv5w.js → chunk-y1dh3znq.js} +52 -52
  85. package/dist/chunk-y6e86wjs.js +445 -0
  86. package/dist/chunk-y8b7ht4v.js +1 -0
  87. package/dist/chunk-yf487g6e.js +2 -0
  88. package/dist/chunk-zmmc9j5f.js +2 -0
  89. package/dist/deploy/index.js +1 -1
  90. package/dist/dns/index.js +1 -1
  91. package/dist/drivers/index.js +1 -1
  92. package/dist/index.d.ts +1 -0
  93. package/dist/index.js +91 -91
  94. package/dist/operations/drained-sites.d.ts +56 -0
  95. package/dist/operations/drained-sites.test.d.ts +1 -0
  96. package/dist/pages/cloudflare-pages.d.ts +240 -0
  97. package/dist/pages/cloudflare-pages.test.d.ts +1 -0
  98. package/dist/pages/index.d.ts +2 -0
  99. package/dist/protection/index.js +1 -1
  100. package/dist/push/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 +80 -80
  110. package/dist/ui/data/services.html +78 -78
  111. package/dist/ui/data/volumes.html +50 -50
  112. package/dist/ui/index.html +50 -50
  113. package/dist/ui/infrastructure/topology.html +118 -118
  114. package/dist/ui/integrations.html +2 -2
  115. package/dist/ui/operations/alerts.html +48 -48
  116. package/dist/ui/operations/configuration.html +6 -6
  117. package/dist/ui/operations/jobs.html +75 -75
  118. package/dist/ui/operations/maintenance.html +6 -6
  119. package/dist/ui/operations/observability.html +82 -82
  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 +54 -54
  125. package/dist/ui/operations/workloads.html +104 -104
  126. package/dist/ui/security.html +2 -2
  127. package/dist/ui/server/actions.html +56 -56
  128. package/dist/ui/server/activity.html +2 -2
  129. package/dist/ui/server/capacity.html +6 -6
  130. package/dist/ui/server/database.html +105 -105
  131. package/dist/ui/server/deployments.html +50 -50
  132. package/dist/ui/server/diagnostics.html +2 -2
  133. package/dist/ui/server/firewall.html +76 -76
  134. package/dist/ui/server/fleet.html +34 -34
  135. package/dist/ui/server/logs.html +24 -24
  136. package/dist/ui/server/metrics.html +112 -112
  137. package/dist/ui/server/security.html +1 -1
  138. package/dist/ui/server/services.html +26 -26
  139. package/dist/ui/server/sites.html +120 -120
  140. package/dist/ui/server/ssh-keys.html +52 -52
  141. package/dist/ui/server/team.html +144 -144
  142. package/dist/ui/server/terminal.html +15 -15
  143. package/dist/ui/serverless/alarms.html +52 -52
  144. package/dist/ui/serverless/assets.html +27 -27
  145. package/dist/ui/serverless/cost.html +2 -2
  146. package/dist/ui/serverless/data.html +35 -35
  147. package/dist/ui/serverless/deployments.html +27 -27
  148. package/dist/ui/serverless/firewall.html +2 -2
  149. package/dist/ui/serverless/functions.html +40 -40
  150. package/dist/ui/serverless/logs.html +24 -24
  151. package/dist/ui/serverless/metrics.html +2 -2
  152. package/dist/ui/serverless/queues.html +48 -48
  153. package/dist/ui/serverless/secrets.html +52 -52
  154. package/dist/ui/serverless/traces.html +6 -6
  155. package/dist/ui/serverless.html +53 -53
  156. package/dist/ui-src/src/charts.ts +8721 -13558
  157. package/dist/ui-src/src/topology.ts +2 -2
  158. package/package.json +4 -3
  159. package/dist/bin/chunk-0zwknfwp.js +0 -1
  160. package/dist/bin/chunk-3aph4c1w.js +0 -2
  161. package/dist/bin/chunk-4xhj37nj.js +0 -37
  162. package/dist/bin/chunk-5nkqza92.js +0 -1
  163. package/dist/bin/chunk-5nsqz5n3.js +0 -585
  164. package/dist/bin/chunk-64vczwwt.js +0 -1
  165. package/dist/bin/chunk-6tfwm33r.js +0 -6
  166. package/dist/bin/chunk-7g2ahkse.js +0 -1
  167. package/dist/bin/chunk-7zhgmp1s.js +0 -3
  168. package/dist/bin/chunk-82mj52xr.js +0 -141
  169. package/dist/bin/chunk-8khgprf6.js +0 -44
  170. package/dist/bin/chunk-9a88fp00.js +0 -2
  171. package/dist/bin/chunk-a7w13qfm.js +0 -2
  172. package/dist/bin/chunk-b4wt9jcg.js +0 -60
  173. package/dist/bin/chunk-btsyjhk7.js +0 -92
  174. package/dist/bin/chunk-c0bdafbx.js +0 -2
  175. package/dist/bin/chunk-cbsys5v8.js +0 -111
  176. package/dist/bin/chunk-cd0ps58j.js +0 -1
  177. package/dist/bin/chunk-d7ke90zt.js +0 -2
  178. package/dist/bin/chunk-djg4zyqk.js +0 -1
  179. package/dist/bin/chunk-dkaz333b.js +0 -1
  180. package/dist/bin/chunk-dkf4qsp2.js +0 -1
  181. package/dist/bin/chunk-e2bybahr.js +0 -3
  182. package/dist/bin/chunk-e5ab5twy.js +0 -50
  183. package/dist/bin/chunk-edvvx3hg.js +0 -1
  184. package/dist/bin/chunk-ehc63fvs.js +0 -2
  185. package/dist/bin/chunk-f06c5np9.js +0 -1
  186. package/dist/bin/chunk-g0fm1xcs.js +0 -1
  187. package/dist/bin/chunk-gq8794k6.js +0 -1
  188. package/dist/bin/chunk-hq9x489e.js +0 -70
  189. package/dist/bin/chunk-j447p8t4.js +0 -512
  190. package/dist/bin/chunk-ja1vjdn1.js +0 -6
  191. package/dist/bin/chunk-k3120rx6.js +0 -1
  192. package/dist/bin/chunk-kg61p5hw.js +0 -3
  193. package/dist/bin/chunk-mcr0r4at.js +0 -2
  194. package/dist/bin/chunk-mfrf9q4b.js +0 -2
  195. package/dist/bin/chunk-my3ewh3a.js +0 -34
  196. package/dist/bin/chunk-nw3d4k52.js +0 -1
  197. package/dist/bin/chunk-p70bc9yr.js +0 -1
  198. package/dist/bin/chunk-r6b3pq31.js +0 -4
  199. package/dist/bin/chunk-s4yzes15.js +0 -2
  200. package/dist/bin/chunk-sj5csg49.js +0 -2
  201. package/dist/bin/chunk-tvz9c388.js +0 -1
  202. package/dist/bin/chunk-wkx799z2.js +0 -1
  203. package/dist/bin/chunk-x6f61g36.js +0 -9
  204. package/dist/bin/chunk-xhwqpgwq.js +0 -2
  205. package/dist/bin/chunk-xk08030d.js +0 -6
  206. package/dist/bin/chunk-y1h63vpm.js +0 -1
  207. package/dist/bin/chunk-yw6f160x.js +0 -1
  208. package/dist/bin/chunk-zdt2rjk6.js +0 -1
  209. package/dist/bin/chunk-zh2d4704.js +0 -1
  210. package/dist/bin/chunk-znnawt0k.js +0 -1
  211. package/dist/bin/chunk-zpe64t4r.js +0 -1
  212. package/dist/bin/chunk-zsf6pccz.js +0 -1
  213. package/dist/chunk-1qdne0bf.js +0 -1
  214. package/dist/chunk-5vt93kxx.js +0 -1
  215. package/dist/chunk-73ztr55z.js +0 -2
  216. package/dist/chunk-95e6aeqz.js +0 -1
  217. package/dist/chunk-aj025v2s.js +0 -4
  218. package/dist/chunk-aw0spg20.js +0 -445
  219. package/dist/chunk-by2bwzk6.js +0 -141
  220. package/dist/chunk-dr4pj8hp.js +0 -5
  221. package/dist/chunk-hn40z11p.js +0 -37
  222. package/dist/chunk-kasdm9tx.js +0 -34
  223. package/dist/chunk-mz0dk78z.js +0 -6
  224. package/dist/chunk-nk7sav4r.js +0 -92
  225. package/dist/chunk-p10xt3jb.js +0 -1
  226. package/dist/chunk-q0rc1ax9.js +0 -114
  227. package/dist/chunk-q9q6cmt0.js +0 -1
  228. package/dist/chunk-rd38qdnf.js +0 -1
  229. package/dist/chunk-tz9myq9a.js +0 -2
  230. package/dist/chunk-wavjkdb8.js +0 -2
  231. package/dist/chunk-x3hay61c.js +0 -44
  232. package/dist/chunk-xcj8zfmg.js +0 -2
  233. package/dist/chunk-y4xkj2f1.js +0 -50
  234. package/dist/chunk-ywjkyg8p.js +0 -704
  235. package/dist/chunk-z2qqwy7e.js +0 -2
  236. package/dist/chunk-zam6ecam.js +0 -60
@@ -1,26 +1,26 @@
1
- import{op as ye}from"./chunk-ehc63fvs.js";import{createRequire as Bn}from"node:module";import{isAbsolute as Vt,join as At,relative as Xn}from"node:path";import{existsSync as Ke,readdirSync as Ci}from"node:fs";import{join as Ae}from"node:path";import{createHash as Wi}from"node:crypto";import{copyFileSync as Gi,existsSync as xt,readdirSync as Fi,readFileSync as ot,statSync as Vi,writeFileSync as ct}from"node:fs";import{basename as Ui,dirname as ya,extname as fa,join as He}from"node:path";import{existsSync as tr,readFileSync as Yt}from"node:fs";import{homedir as ar}from"node:os";import{join as rr}from"node:path";import{createHash as sr}from"node:crypto";import{existsSync as ut,mkdirSync as uo,readdirSync as wa,readFileSync as Ea,unlinkSync as qe,writeFileSync as mo}from"node:fs";import{join as Bt}from"node:path";import{createHash as Xt}from"node:crypto";import{createReadStream as po,readdirSync as go,statSync as Tt}from"node:fs";import{join as ho,relative as yo}from"node:path";import{deflateRawSync as Uo}from"node:zlib";import{execSync as Qo}from"node:child_process";import{createHash as Jo}from"node:crypto";import{cpSync as Yo,mkdtempSync as Zo,rmSync as Xo,writeFileSync as ec}from"node:fs";import{tmpdir as tc}from"node:os";import{dirname as ac,isAbsolute as rc,join as Le,resolve as nc}from"node:path";import{fileURLToPath as ic}from"node:url";import{execFileSync as Nt}from"node:child_process";import{mkdtempSync as yn,readFileSync as Dt,rmSync as fn}from"node:fs";import{tmpdir as Sn}from"node:os";import{dirname as yc,join as ve}from"node:path";import{fileURLToPath as fc}from"node:url";import{AsyncLocalStorage as bc}from"node:async_hooks";import{createHash as Ac}from"node:crypto";import{readFileSync as Fc}from"node:fs";import{dirname as Vc,join as Pn}from"node:path";import{fileURLToPath as Uc}from"node:url";import{execFileSync as dt}from"node:child_process";import{existsSync as Hc,mkdirSync as qc,mkdtempSync as zc,readdirSync as Qc,readFileSync as Jc,rmSync as Yc,statSync as In,writeFileSync as Zc}from"node:fs";import{tmpdir as Xc}from"node:os";import{join as Me,relative as el}from"node:path";import{execSync as tl}from"node:child_process";import{createHash as al}from"node:crypto";import{readdirSync as rl,readFileSync as nl,statSync as Nn}from"node:fs";import{join as il,relative as Dn,resolve as ha}from"node:path";var _n=Object.defineProperty,Wn=(e)=>e;function Gn(e,t){this[e]=Wn.bind(null,t)}var De=(e,t)=>{for(var a in t)_n(e,a,{get:t[a],enumerable:!0,configurable:!0,set:Gn.bind(t,a)})},Fn=(e,t)=>()=>(e&&(t=e(e=0)),t),Vn=Bn(import.meta.url),La={};De(La,{clearSigningKeyCache:()=>Qn,createPresignedUrl:()=>Ma,createPresignedUrlAsync:()=>Kn,detectServiceRegion:()=>qt,getSigningKeyCacheSize:()=>Jn,isNodeCryptoAvailable:()=>Yn,isWebCryptoAvailable:()=>Zn,makeAWSRequest:()=>_e,makeAWSRequestAsync:()=>qn,makeAWSRequestOnce:()=>Hn,parseJSONResponse:()=>zn,parseXMLResponse:()=>mt,signRequest:()=>K,signRequestAsync:()=>zt});function qt(e){let t=typeof e==="string"?new URL(e):e,{hostname:a,pathname:r}=t;if(a.endsWith(".on.aws")){let o=a.match(/^[^.]+\.lambda-url\.([^.]+)\.on\.aws$/);if(o)return{service:"lambda",region:o[1]};return{service:"",region:""}}if(a.endsWith(".r2.cloudflarestorage.com"))return{service:"s3",region:"auto"};if(a.endsWith(".backblazeb2.com")){let o=a.match(/^(?:[^.]+\.)?s3\.([^.]+)\.backblazeb2\.com$/);if(o)return{service:"s3",region:o[1]};return{service:"",region:""}}let n=a.replace("dualstack.","").match(/([^.]+)\.(?:([^.]+)\.)?amazonaws\.com(?:\.cn)?$/);if(!n)return{service:"",region:""};let i=n[1],s=n[2]||"";if(s==="us-gov")s="us-gov-west-1";else if(s==="s3"||s==="s3-accelerate")s="us-east-1",i="s3";else if(i==="iot")if(a.startsWith("iot."))i="execute-api";else if(a.startsWith("data.jobs.iot."))i="iot-jobs-data";else i=r==="/mqtt"?"iotdevicegateway":"iotdata";else if(i==="autoscaling");else if(!s&&i.startsWith("s3-"))s=i.slice(3).replace(/^fips-|^external-1/,""),i="s3";else if(i.endsWith("-fips"))i=i.slice(0,-5);else if(s&&/-\d$/.test(i)&&!/-\d$/.test(s))[i,s]=[s,i];return i=Va[i]||i,{service:i,region:s||"us-east-1"}}function K(e){let{method:t,url:a,body:r="",accessKeyId:n,secretAccessKey:i,sessionToken:s,signQuery:o=!1,expiresIn:c=86400,datetime:l}=e,u=new URL(a),m=u.hostname,p=qt(u),g=e.service||p.service,h=e.region||p.region;if(!g)throw Error("Could not detect service from URL. Please provide service explicitly.");if(!h)throw Error("Could not detect region from URL. Please provide region explicitly.");let y=l||new Date().toISOString().replace(/[:-]|\.\d{3}/g,""),b=y.substring(0,8),T=[b,h,g,"aws4_request"].join("/"),w="AWS4-HMAC-SHA256";if(o)return Un({urlObj:u,method:t,body:r,accessKeyId:n,secretAccessKey:i,sessionToken:s,service:g,region:h,timestamp:y,date:b,credentialScope:T,algorithm:w,expiresIn:c,cache:e.cache});let S=u.pathname||"/",E=Et(u.searchParams),v={host:m,"x-amz-date":y,...e.headers};if(s)v["x-amz-security-token"]=s;let P=Object.keys(v).some((we)=>we.toLowerCase()==="content-type");if(r&&!P)v["content-type"]="application/x-amz-json-1.0";if(g==="s3"&&!v["x-amz-content-sha256"])v["x-amz-content-sha256"]=Xe(r);let N=xa(v),I=Oa(v),D=v["x-amz-content-sha256"]||Xe(r),L=[t,Pt(S),E,N,I,D].join(`
2
- `),O=Xe(L),ce=[w,y,T,O].join(`
3
- `),j=e.cache??ke,ae=_a(i,b,h,g,ce,j),F=[`${w} Credential=${n}/${T}`,`SignedHeaders=${I}`,`Signature=${ae}`].join(", ");return v.authorization=F,{url:a,method:t,headers:v,body:r||void 0}}async function zt(e){let{method:t,url:a,body:r="",accessKeyId:n,secretAccessKey:i,sessionToken:s,signQuery:o=!1,expiresIn:c=86400,datetime:l}=e,u=new URL(a),m=u.hostname,p=qt(u),g=e.service||p.service,h=e.region||p.region;if(!g)throw Error("Could not detect service from URL. Please provide service explicitly.");if(!h)throw Error("Could not detect region from URL. Please provide region explicitly.");let y=l||new Date().toISOString().replace(/[:-]|\.\d{3}/g,""),b=y.substring(0,8),T=[b,h,g,"aws4_request"].join("/"),w="AWS4-HMAC-SHA256";if(o)return jn({urlObj:u,method:t,body:r,accessKeyId:n,secretAccessKey:i,sessionToken:s,service:g,region:h,timestamp:y,date:b,credentialScope:T,algorithm:w,expiresIn:c,cache:e.cache});let S=u.pathname||"/",E=Et(u.searchParams),v={host:m,"x-amz-date":y,...e.headers};if(s)v["x-amz-security-token"]=s;let P=Object.keys(v).some((Fe)=>Fe.toLowerCase()==="content-type");if(r&&!P)v["content-type"]="application/x-amz-json-1.0";let N=await ft(r);if(g==="s3"&&!v["x-amz-content-sha256"])v["x-amz-content-sha256"]=N;let I=xa(v),D=Oa(v),L=v["x-amz-content-sha256"]||N,O=[t,Pt(S),E,I,D,L].join(`
4
- `),ce=await ft(O),j=[w,y,T,ce].join(`
5
- `),ae=e.cache??ke,F=await Wa(i,b,h,g,j,ae),we=[`${w} Credential=${n}/${T}`,`SignedHeaders=${D}`,`Signature=${F}`].join(", ");return v.authorization=we,{url:a,method:t,headers:v,body:r||void 0}}function Un(e){let{urlObj:t,method:a,body:r,accessKeyId:n,secretAccessKey:i,sessionToken:s,service:o,region:c,timestamp:l,date:u,credentialScope:m,algorithm:p,expiresIn:g,cache:h}=e,y=new URL(t.toString());y.searchParams.set("X-Amz-Algorithm",p),y.searchParams.set("X-Amz-Credential",`${n}/${m}`),y.searchParams.set("X-Amz-Date",l),y.searchParams.set("X-Amz-Expires",String(g));let b=o==="s3"?"UNSIGNED-PAYLOAD":Xe(r);if(o==="s3")y.searchParams.set("X-Amz-Content-Sha256",b);let T="host";if(y.searchParams.set("X-Amz-SignedHeaders",T),s)y.searchParams.set("X-Amz-Security-Token",s);let w=Pt(y.pathname||"/"),S=`host:${y.hostname}
6
- `,E=Et(y.searchParams),v=[a,w,E,S,T,b].join(`
1
+ import{pp as he}from"./chunk-c8sypnbe.js";import{createRequire as Wn}from"node:module";import{isAbsolute as Vt,join as bt,relative as Xn}from"node:path";import{existsSync as Ke,readdirSync as Ai}from"node:fs";import{join as be}from"node:path";import{createHash as Bi}from"node:crypto";import{copyFileSync as Ui,existsSync as xt,readdirSync as Gi,readFileSync as st,statSync as Vi,writeFileSync as ot}from"node:fs";import{basename as Fi,dirname as ha,extname as ya,join as He}from"node:path";import{existsSync as er,readFileSync as $t}from"node:fs";import{homedir as tr}from"node:os";import{join as ar}from"node:path";import{createHash as ir}from"node:crypto";import{existsSync as lt,mkdirSync as lo,readdirSync as va,readFileSync as wa,unlinkSync as qe,writeFileSync as uo}from"node:fs";import{join as Wt}from"node:path";import{createHash as Xt}from"node:crypto";import{createReadStream as mo,readdirSync as po,statSync as Ct}from"node:fs";import{join as go,relative as ho}from"node:path";import{deflateRawSync as Fo}from"node:zlib";import{execSync as Jo}from"node:child_process";import{createHash as Qo}from"node:crypto";import{cpSync as $o,mkdtempSync as Yo,rmSync as Xo,writeFileSync as Zo}from"node:fs";import{tmpdir as ec}from"node:os";import{dirname as tc,isAbsolute as ac,join as Me,resolve as rc}from"node:path";import{fileURLToPath as nc}from"node:url";import{execFileSync as Rt}from"node:child_process";import{mkdtempSync as hn,readFileSync as Nt,rmSync as yn}from"node:fs";import{tmpdir as fn}from"node:os";import{dirname as hc,join as Te}from"node:path";import{fileURLToPath as yc}from"node:url";import{AsyncLocalStorage as Sc}from"node:async_hooks";import{createHash as bc}from"node:crypto";import{readFileSync as Gc}from"node:fs";import{dirname as Vc,join as En}from"node:path";import{fileURLToPath as Fc}from"node:url";import{execFileSync as ut}from"node:child_process";import{existsSync as Hc,mkdirSync as qc,mkdtempSync as zc,readdirSync as Jc,readFileSync as Qc,rmSync as $c,statSync as Pn,writeFileSync as Yc}from"node:fs";import{tmpdir as Xc}from"node:os";import{join as Le,relative as Zc}from"node:path";import{execSync as el}from"node:child_process";import{createHash as tl}from"node:crypto";import{readdirSync as al,readFileSync as rl,statSync as Rn}from"node:fs";import{join as nl,relative as Nn,resolve as ga}from"node:path";var _n=Object.defineProperty,Bn=(e)=>e;function Un(e,t){this[e]=Bn.bind(null,t)}var Ne=(e,t)=>{for(var a in t)_n(e,a,{get:t[a],enumerable:!0,configurable:!0,set:Un.bind(t,a)})},Gn=(e,t)=>()=>(e&&(t=e(e=0)),t),Vn=Wn(import.meta.url),Ma={};Ne(Ma,{signRequestAsync:()=>zt,signRequest:()=>K,parseXMLResponse:()=>dt,parseJSONResponse:()=>zn,makeAWSRequestOnce:()=>Hn,makeAWSRequestAsync:()=>qn,makeAWSRequest:()=>_e,isWebCryptoAvailable:()=>Yn,isNodeCryptoAvailable:()=>$n,getSigningKeyCacheSize:()=>Qn,detectServiceRegion:()=>qt,createPresignedUrlAsync:()=>Kn,createPresignedUrl:()=>La,clearSigningKeyCache:()=>Jn});function qt(e){let t=typeof e==="string"?new URL(e):e,{hostname:a,pathname:r}=t;if(a.endsWith(".on.aws")){let o=a.match(/^[^.]+\.lambda-url\.([^.]+)\.on\.aws$/);if(o)return{service:"lambda",region:o[1]};return{service:"",region:""}}if(a.endsWith(".r2.cloudflarestorage.com"))return{service:"s3",region:"auto"};if(a.endsWith(".backblazeb2.com")){let o=a.match(/^(?:[^.]+\.)?s3\.([^.]+)\.backblazeb2\.com$/);if(o)return{service:"s3",region:o[1]};return{service:"",region:""}}let n=a.replace("dualstack.","").match(/([^.]+)\.(?:([^.]+)\.)?amazonaws\.com(?:\.cn)?$/);if(!n)return{service:"",region:""};let i=n[1],s=n[2]||"";if(s==="us-gov")s="us-gov-west-1";else if(s==="s3"||s==="s3-accelerate")s="us-east-1",i="s3";else if(i==="iot")if(a.startsWith("iot."))i="execute-api";else if(a.startsWith("data.jobs.iot."))i="iot-jobs-data";else i=r==="/mqtt"?"iotdevicegateway":"iotdata";else if(i==="autoscaling");else if(!s&&i.startsWith("s3-"))s=i.slice(3).replace(/^fips-|^external-1/,""),i="s3";else if(i.endsWith("-fips"))i=i.slice(0,-5);else if(s&&/-\d$/.test(i)&&!/-\d$/.test(s))[i,s]=[s,i];return i=Va[i]||i,{service:i,region:s||"us-east-1"}}function K(e){let{method:t,url:a,body:r="",accessKeyId:n,secretAccessKey:i,sessionToken:s,signQuery:o=!1,expiresIn:c=86400,datetime:l}=e,u=new URL(a),m=u.hostname,p=qt(u),g=e.service||p.service,h=e.region||p.region;if(!g)throw Error("Could not detect service from URL. Please provide service explicitly.");if(!h)throw Error("Could not detect region from URL. Please provide region explicitly.");let y=l||new Date().toISOString().replace(/[:-]|\.\d{3}/g,""),b=y.substring(0,8),T=[b,h,g,"aws4_request"].join("/"),w="AWS4-HMAC-SHA256";if(o)return Fn({urlObj:u,method:t,body:r,accessKeyId:n,secretAccessKey:i,sessionToken:s,service:g,region:h,timestamp:y,date:b,credentialScope:T,algorithm:w,expiresIn:c,cache:e.cache});let S=u.pathname||"/",E=wt(u.searchParams),v={host:m,"x-amz-date":y,...e.headers};if(s)v["x-amz-security-token"]=s;let P=Object.keys(v).some((ve)=>ve.toLowerCase()==="content-type");if(r&&!P)v["content-type"]="application/x-amz-json-1.0";if(g==="s3"&&!v["x-amz-content-sha256"])v["x-amz-content-sha256"]=Xe(r);let N=xa(v),I=Oa(v),D=v["x-amz-content-sha256"]||Xe(r),M=[t,Et(S),E,N,I,D].join(`
2
+ `),O=Xe(M),oe=[w,y,T,O].join(`
3
+ `),j=e.cache??De,te=_a(i,b,h,g,oe,j),G=[`${w} Credential=${n}/${T}`,`SignedHeaders=${I}`,`Signature=${te}`].join(", ");return v.authorization=G,{url:a,method:t,headers:v,body:r||void 0}}async function zt(e){let{method:t,url:a,body:r="",accessKeyId:n,secretAccessKey:i,sessionToken:s,signQuery:o=!1,expiresIn:c=86400,datetime:l}=e,u=new URL(a),m=u.hostname,p=qt(u),g=e.service||p.service,h=e.region||p.region;if(!g)throw Error("Could not detect service from URL. Please provide service explicitly.");if(!h)throw Error("Could not detect region from URL. Please provide region explicitly.");let y=l||new Date().toISOString().replace(/[:-]|\.\d{3}/g,""),b=y.substring(0,8),T=[b,h,g,"aws4_request"].join("/"),w="AWS4-HMAC-SHA256";if(o)return jn({urlObj:u,method:t,body:r,accessKeyId:n,secretAccessKey:i,sessionToken:s,service:g,region:h,timestamp:y,date:b,credentialScope:T,algorithm:w,expiresIn:c,cache:e.cache});let S=u.pathname||"/",E=wt(u.searchParams),v={host:m,"x-amz-date":y,...e.headers};if(s)v["x-amz-security-token"]=s;let P=Object.keys(v).some((Ge)=>Ge.toLowerCase()==="content-type");if(r&&!P)v["content-type"]="application/x-amz-json-1.0";let N=await yt(r);if(g==="s3"&&!v["x-amz-content-sha256"])v["x-amz-content-sha256"]=N;let I=xa(v),D=Oa(v),M=v["x-amz-content-sha256"]||N,O=[t,Et(S),E,I,D,M].join(`
4
+ `),oe=await yt(O),j=[w,y,T,oe].join(`
5
+ `),te=e.cache??De,G=await Ba(i,b,h,g,j,te),ve=[`${w} Credential=${n}/${T}`,`SignedHeaders=${D}`,`Signature=${G}`].join(", ");return v.authorization=ve,{url:a,method:t,headers:v,body:r||void 0}}function Fn(e){let{urlObj:t,method:a,body:r,accessKeyId:n,secretAccessKey:i,sessionToken:s,service:o,region:c,timestamp:l,date:u,credentialScope:m,algorithm:p,expiresIn:g,cache:h}=e,y=new URL(t.toString());y.searchParams.set("X-Amz-Algorithm",p),y.searchParams.set("X-Amz-Credential",`${n}/${m}`),y.searchParams.set("X-Amz-Date",l),y.searchParams.set("X-Amz-Expires",String(g));let b=o==="s3"?"UNSIGNED-PAYLOAD":Xe(r);if(o==="s3")y.searchParams.set("X-Amz-Content-Sha256",b);let T="host";if(y.searchParams.set("X-Amz-SignedHeaders",T),s)y.searchParams.set("X-Amz-Security-Token",s);let w=Et(y.pathname||"/"),S=`host:${y.hostname}
6
+ `,E=wt(y.searchParams),v=[a,w,E,S,T,b].join(`
7
7
  `),P=[p,l,m,Xe(v)].join(`
8
- `),N=_a(i,u,c,o,P,h??ke);return y.searchParams.set("X-Amz-Signature",N),{url:y.toString(),method:a,headers:{},body:r||void 0}}async function jn(e){let{urlObj:t,method:a,body:r,accessKeyId:n,secretAccessKey:i,sessionToken:s,service:o,region:c,timestamp:l,date:u,credentialScope:m,algorithm:p,expiresIn:g,cache:h}=e,y=new URL(t.toString());y.searchParams.set("X-Amz-Algorithm",p),y.searchParams.set("X-Amz-Credential",`${n}/${m}`),y.searchParams.set("X-Amz-Date",l),y.searchParams.set("X-Amz-Expires",String(g));let b=o==="s3"?"UNSIGNED-PAYLOAD":await ft(r);if(o==="s3")y.searchParams.set("X-Amz-Content-Sha256",b);let T="host";if(y.searchParams.set("X-Amz-SignedHeaders",T),s)y.searchParams.set("X-Amz-Security-Token",s);let w=Pt(y.pathname||"/"),S=`host:${y.hostname}
9
- `,E=Et(y.searchParams),v=[a,w,E,S,T,b].join(`
10
- `),P=[p,l,m,await ft(v)].join(`
11
- `),N=await Wa(i,u,c,o,P,h??ke);return y.searchParams.set("X-Amz-Signature",N),{url:y.toString(),method:a,headers:{},body:r||void 0}}function Ma(e){let{url:t,method:a="GET",expiresIn:r=3600,...n}=e,i=Math.min(r,604800);return K({...n,url:t,method:a,signQuery:!0,expiresIn:i}).url}async function Kn(e){let{url:t,method:a="GET",expiresIn:r=3600,...n}=e,i=Math.min(r,604800);return(await zt({...n,url:t,method:a,signQuery:!0,expiresIn:i})).url}function xa(e){return Object.keys(e).sort().map((t)=>`${t.toLowerCase()}:${e[t].trim().replace(/\s+/g," ")}`).join(`
8
+ `),N=_a(i,u,c,o,P,h??De);return y.searchParams.set("X-Amz-Signature",N),{url:y.toString(),method:a,headers:{},body:r||void 0}}async function jn(e){let{urlObj:t,method:a,body:r,accessKeyId:n,secretAccessKey:i,sessionToken:s,service:o,region:c,timestamp:l,date:u,credentialScope:m,algorithm:p,expiresIn:g,cache:h}=e,y=new URL(t.toString());y.searchParams.set("X-Amz-Algorithm",p),y.searchParams.set("X-Amz-Credential",`${n}/${m}`),y.searchParams.set("X-Amz-Date",l),y.searchParams.set("X-Amz-Expires",String(g));let b=o==="s3"?"UNSIGNED-PAYLOAD":await yt(r);if(o==="s3")y.searchParams.set("X-Amz-Content-Sha256",b);let T="host";if(y.searchParams.set("X-Amz-SignedHeaders",T),s)y.searchParams.set("X-Amz-Security-Token",s);let w=Et(y.pathname||"/"),S=`host:${y.hostname}
9
+ `,E=wt(y.searchParams),v=[a,w,E,S,T,b].join(`
10
+ `),P=[p,l,m,await yt(v)].join(`
11
+ `),N=await Ba(i,u,c,o,P,h??De);return y.searchParams.set("X-Amz-Signature",N),{url:y.toString(),method:a,headers:{},body:r||void 0}}function La(e){let{url:t,method:a="GET",expiresIn:r=3600,...n}=e,i=Math.min(r,604800);return K({...n,url:t,method:a,signQuery:!0,expiresIn:i}).url}async function Kn(e){let{url:t,method:a="GET",expiresIn:r=3600,...n}=e,i=Math.min(r,604800);return(await zt({...n,url:t,method:a,signQuery:!0,expiresIn:i})).url}function xa(e){return Object.keys(e).sort().map((t)=>`${t.toLowerCase()}:${e[t].trim().replace(/\s+/g," ")}`).join(`
12
12
  `)+`
13
- `}function Oa(e){return Object.keys(e).sort().map((t)=>t.toLowerCase()).join(";")}function Et(e){let t=[];return e.forEach((a,r)=>{t.push([Ft(r),Ft(a)])}),t.sort((a,r)=>{if(a[0]<r[0])return-1;if(a[0]>r[0])return 1;if(a[1]<r[1])return-1;if(a[1]>r[1])return 1;return 0}),t.map(([a,r])=>`${a}=${r}`).join("&")}function Pt(e){return e.split("/").map((t)=>Ft(t)).join("/")}function Ft(e){return encodeURIComponent(e).replace(/[!'()*]/g,(t)=>`%${t.charCodeAt(0).toString(16).toUpperCase()}`)}function Xe(e){if(!We)throw Error("Synchronous hash not available in browser. Use signRequestAsync() instead.");return We.createHash("sha256").update(e,"utf8").digest("hex")}function Ue(e,t){if(!We)throw Error("Synchronous hmac not available in browser. Use signRequestAsync() instead.");return We.createHmac("sha256",e).update(t,"utf8").digest()}async function ft(e){let t=new TextEncoder().encode(e),a=await crypto.subtle.digest("SHA-256",t);return Ba(new Uint8Array(a))}async function je(e,t){let a=new TextEncoder,r=typeof e==="string"?a.encode(e):e,n=a.encode(t),i=await crypto.subtle.importKey("raw",r.buffer,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),s=await crypto.subtle.sign("HMAC",i,n.buffer);return new Uint8Array(s)}function Ba(e){return Array.from(e).map((t)=>t.toString(16).padStart(2,"0")).join("")}function _a(e,t,a,r,n,i){let s=`${e}:${t}:${a}:${r}`,o=i.get(s);if(!o){let c=Ue(`AWS4${e}`,t),l=Ue(c,a),u=Ue(l,r);if(o=Ue(u,"aws4_request"),i.size>=Fa){let m=i.keys().next().value;if(m)i.delete(m)}i.set(s,o)}return Ue(o,n).toString("hex")}async function Wa(e,t,a,r,n,i){let s=`${e}:${t}:${a}:${r}`,o=i.get(s);if(!o){let l=await je(`AWS4${e}`,t),u=await je(l,a),m=await je(u,r);if(o=await je(m,"aws4_request"),i.size>=Fa){let p=i.keys().next().value;if(p)i.delete(p)}i.set(s,o)}let c=await je(o,n);return Ba(c)}function Ga(e,t){return t.includes(e)}function St(e,t,a){let r=t*Math.pow(2,e),n=Math.random()*0.3*r;return Math.min(r+n,a)}function bt(e){return new Promise((t)=>setTimeout(t,e))}async function _e(e,t){let{maxRetries:a=3,initialDelayMs:r=100,maxDelayMs:n=5000,retryableStatusCodes:i=[429,500,502,503,504],timeoutMs:s=30000}=t??{},o,c;for(let l=0;l<=a;l++){let u=K(e),m={method:u.method,headers:u.headers};if(u.body)m.body=u.body;let p=new AbortController,g=setTimeout(()=>p.abort(),s);m.signal=p.signal;try{let h=await fetch(u.url,m);if(clearTimeout(g),c=h,h.ok)return h;if(l<a&&Ga(h.status,i)){let b=St(l,r,n);await bt(b);continue}let y=await h.text();throw Error(`AWS API request failed (${h.status}): ${y}`)}catch(h){if(clearTimeout(g),o=h,h instanceof Error&&h.name==="AbortError")o=Error(`Request timed out after ${s}ms`);if(l<a&&!(h instanceof Error&&h.message.includes("AWS API request failed"))){let y=St(l,r,n);await bt(y);continue}throw o}}throw o??Error("Request failed after retries")}async function Hn(e){return _e(e,{maxRetries:0})}async function qn(e,t){let{maxRetries:a=3,initialDelayMs:r=100,maxDelayMs:n=5000,retryableStatusCodes:i=[429,500,502,503,504],timeoutMs:s=30000}=t??{},o;for(let c=0;c<=a;c++){let l=await zt(e),u={method:l.method,headers:l.headers};if(l.body)u.body=l.body;let m=new AbortController,p=setTimeout(()=>m.abort(),s);u.signal=m.signal;try{let g=await fetch(l.url,u);if(clearTimeout(p),g.ok)return g;if(c<a&&Ga(g.status,i)){let y=St(c,r,n);await bt(y);continue}let h=await g.text();throw Error(`AWS API request failed (${g.status}): ${h}`)}catch(g){if(clearTimeout(p),o=g,g instanceof Error&&g.name==="AbortError")o=Error(`Request timed out after ${s}ms`);if(c<a&&!(g instanceof Error&&g.message.includes("AWS API request failed"))){let h=St(c,r,n);await bt(h);continue}throw o}}throw o??Error("Request failed after retries")}async function mt(e){let t=await e.text(),a={},r=/<(\w+)>([^<]+)<\/\1>/g,n;while((n=r.exec(t))!==null){let[,i,s]=n;a[i]=s}return a}async function zn(e){return await e.json()}function Qn(){ke.clear()}function Jn(){return ke.size}function Yn(){return We!==void 0}function Zn(){return typeof crypto<"u"&&typeof crypto.subtle<"u"}var We,ke,Fa=100,Va,rt=Fn(async()=>{try{We=await import("node:crypto")}catch{}ke=new Map,Va={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"}}),dl={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}},ml={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}}}},Ua=".ts-cloud",ei="TS_CLOUD_STATE_DIR",ja=null;function gl(e){ja=e?.trim()||null}function It(){return process.env[ei]?.trim()||ja||Ua}function ti(...e){return At(It(),...e)}function ai(e,...t){let a=It();return Vt(a)?At(a,...t):At(e,a,...t)}function hl(e,t=process.cwd()){let a=(n,i)=>{let s=Xn(n,i);return s===""||!s.startsWith("..")&&!Vt(s)},r=Vt(e)?e:At(t,e);return a(ai(t),r)}function Ka(e){let t=e.infrastructure?.compute!=null,a=Object.values(e.environments??{}).some((r)=>r?.app!=null);return{server:t,serverless:a}}function yl(e){if(e.mode==="server"||e.mode==="serverless")return e.mode;let{serverless:t}=Ka(e);return t?"serverless":"server"}function fl(e){let{server:t,serverless:a}=Ka(e);if(t&&a)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(e.mode==="server"&&a&&!t)return"Config sets `mode: 'server'` but declares a serverless app (`environments.<env>.app`). Remove the app or change the mode.";if(e.mode==="serverless"&&t&&!a)return"Config sets `mode: 'serverless'` but declares a server (`infrastructure.compute`). Remove the compute block or change the mode.";return null}function Sl(e){return e.infrastructure?.appDatabase??e.infrastructure?.compute?.database}function ri(e){return typeof e==="object"&&e!==null?e:{}}function ni(e){return e===!0||typeof e==="object"&&e!==null}function ii(e,t){let a=t?e.environments?.[t]:void 0;if(a?.domain)return a.domain;let r=Object.values(e.sites??{}),n=e.sites?.main?.domain??r.find((i)=>i.domain)?.domain;if(n)return n;return`${e.project?.slug??"app"}.local`}function si(e){let t=e.indexOf(".");return t>0?e.slice(t+1):void 0}function bl(e,t={}){let a=e.infrastructure?.compute?.managedServices?.mail,r=ri(a),n=t.environmentType??(t.environment?e.environments?.[t.environment]?.type:void 0),i=r.mode??(n==="production"?"server":"catcher"),s=i==="server",o=ii(e,t.environment),c=r.hostname??(s?`mail.${o}`:"localhost"),l=r.ports??{},u=s?{smtp:l.smtp??25,submission:l.submission??587,submissions:l.submissions??465,imap:l.imap??143,imaps:l.imaps??993,webmail:l.webmail??8080,managesieve:l.managesieve}:{smtp:l.smtp??1025,submission:l.submission,submissions:l.submissions,imap:l.imap,imaps:l.imaps,webmail:l.webmail??8025,managesieve:l.managesieve},m=r.tls??{},p=m.enabled??s,g=!!(m.certPath&&m.keyPath),h=(r.accounts??[]).map((I)=>({address:I.address,password:I.password})),y=typeof r.dkim==="object"&&r.dkim!==null?r.dkim:{},b=r.dkim===!1?!1:r.dkim===!0||s,T=typeof r.webmail==="object"&&r.webmail!==null?r.webmail:{},w=r.webmail===!1?!1:T.enabled??!0,S=r.spam??{},E=r.delivery??(s?"direct":"none"),v=r.expose??s,P=si(c),N=[...new Set([c,...P?[P]:[],...r.domains??[]])];return{enabled:ni(a),mode:i,version:r.version,hostname:c,domains:N,ports:u,tls:{enabled:p,acme:p&&!g&&(m.acme??!0),certPath:m.certPath,keyPath:m.keyPath,requireForAuth:m.requireForAuth??(p&&s),acmeEmail:m.acmeEmail??h[0]?.address},dkim:{enabled:b,selector:y.selector??"default",rotate:y.rotate??!1,rotateIntervalDays:y.rotateIntervalDays??90},webmail:{enabled:w,port:T.port??u.webmail,domain:T.domain},delivery:E,sesRegion:r.sesRegion??"us-east-1",accounts:h,storagePath:r.storagePath??"/var/lib/mail",maxMessageSize:r.maxMessageSize??26214400,spam:{enabled:S.enabled??s,enforce:S.enforce??!1,junkScore:S.junkScore??5,rejectScore:S.rejectScore??12,dnsbl:S.dnsbl??s,greylist:S.greylist??!1},webhookUrl:r.webhookUrl,expose:v,bindAddress:v?"0.0.0.0":"127.0.0.1"}}function Al(e){if(!e.enabled||!e.expose)return[];let t=[e.ports.smtp,e.ports.submission,e.ports.submissions,e.ports.imap,e.ports.imaps,e.ports.managesieve].filter((a)=>typeof a==="number");if(e.webmail.enabled&&!e.webmail.domain)t.push(e.webmail.port);return[...new Set(t)].sort((a,r)=>a-r)}function Cl(e){if(!e.enabled)return{};let t=e.ports.submission??e.ports.smtp,a={MAIL_MAILER:"smtp",MAIL_HOST:"127.0.0.1",MAIL_PORT:String(t)};if(e.mode==="server"){a.MAIL_ENCRYPTION=e.tls.enabled?"tls":"null";let r=e.accounts[0];if(r)a.MAIL_USERNAME=r.address,a.MAIL_PASSWORD=r.password}else a.MAIL_ENCRYPTION="null",a.MAIL_USERNAME="null",a.MAIL_PASSWORD="null";return a}function Tl(e){if(e.cloud?.provider)return e.cloud.provider;if(e.hetzner?.apiToken)return"hetzner";return"aws"}class oi{template;constructor(e){this.template={AWSTemplateFormatVersion:"2010-09-09",Description:e,Resources:{}}}addResource(e,t){return this.template.Resources[e]=t,this}addResources(e){return Object.assign(this.template.Resources,e),this}addParameter(e,t){if(!this.template.Parameters)this.template.Parameters={};return this.template.Parameters[e]=t,this}addOutput(e,t){if(!this.template.Outputs)this.template.Outputs={};return this.template.Outputs[e]=t,this}hasResource(e){return e in this.template.Resources}getResources(){return this.template.Resources}build(){return this.template}toJSON(e=!0){return JSON.stringify(this.template,null,e?2:0)}toYAML(){return this.convertToYAML(this.template)}convertToYAML(e,t=0){let a=" ".repeat(t),r="";for(let[n,i]of Object.entries(e)){if(i===null||i===void 0)continue;if(typeof i==="object"&&!Array.isArray(i))r+=`${a}${n}:
13
+ `}function Oa(e){return Object.keys(e).sort().map((t)=>t.toLowerCase()).join(";")}function wt(e){let t=[];return e.forEach((a,r)=>{t.push([Gt(r),Gt(a)])}),t.sort((a,r)=>{if(a[0]<r[0])return-1;if(a[0]>r[0])return 1;if(a[1]<r[1])return-1;if(a[1]>r[1])return 1;return 0}),t.map(([a,r])=>`${a}=${r}`).join("&")}function Et(e){return e.split("/").map((t)=>Gt(t)).join("/")}function Gt(e){return encodeURIComponent(e).replace(/[!'()*]/g,(t)=>`%${t.charCodeAt(0).toString(16).toUpperCase()}`)}function Xe(e){if(!Be)throw Error("Synchronous hash not available in browser. Use signRequestAsync() instead.");return Be.createHash("sha256").update(e,"utf8").digest("hex")}function Fe(e,t){if(!Be)throw Error("Synchronous hmac not available in browser. Use signRequestAsync() instead.");return Be.createHmac("sha256",e).update(t,"utf8").digest()}async function yt(e){let t=new TextEncoder().encode(e),a=await crypto.subtle.digest("SHA-256",t);return Wa(new Uint8Array(a))}async function je(e,t){let a=new TextEncoder,r=typeof e==="string"?a.encode(e):e,n=a.encode(t),i=await crypto.subtle.importKey("raw",r.buffer,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),s=await crypto.subtle.sign("HMAC",i,n.buffer);return new Uint8Array(s)}function Wa(e){return Array.from(e).map((t)=>t.toString(16).padStart(2,"0")).join("")}function _a(e,t,a,r,n,i){let s=`${e}:${t}:${a}:${r}`,o=i.get(s);if(!o){let c=Fe(`AWS4${e}`,t),l=Fe(c,a),u=Fe(l,r);if(o=Fe(u,"aws4_request"),i.size>=Ga){let m=i.keys().next().value;if(m)i.delete(m)}i.set(s,o)}return Fe(o,n).toString("hex")}async function Ba(e,t,a,r,n,i){let s=`${e}:${t}:${a}:${r}`,o=i.get(s);if(!o){let l=await je(`AWS4${e}`,t),u=await je(l,a),m=await je(u,r);if(o=await je(m,"aws4_request"),i.size>=Ga){let p=i.keys().next().value;if(p)i.delete(p)}i.set(s,o)}let c=await je(o,n);return Wa(c)}function Ua(e,t){return t.includes(e)}function ft(e,t,a){let r=t*Math.pow(2,e),n=Math.random()*0.3*r;return Math.min(r+n,a)}function St(e){return new Promise((t)=>setTimeout(t,e))}async function _e(e,t){let{maxRetries:a=3,initialDelayMs:r=100,maxDelayMs:n=5000,retryableStatusCodes:i=[429,500,502,503,504],timeoutMs:s=30000}=t??{},o,c;for(let l=0;l<=a;l++){let u=K(e),m={method:u.method,headers:u.headers};if(u.body)m.body=u.body;let p=new AbortController,g=setTimeout(()=>p.abort(),s);m.signal=p.signal;try{let h=await fetch(u.url,m);if(clearTimeout(g),c=h,h.ok)return h;if(l<a&&Ua(h.status,i)){let b=ft(l,r,n);await St(b);continue}let y=await h.text();throw Error(`AWS API request failed (${h.status}): ${y}`)}catch(h){if(clearTimeout(g),o=h,h instanceof Error&&h.name==="AbortError")o=Error(`Request timed out after ${s}ms`);if(l<a&&!(h instanceof Error&&h.message.includes("AWS API request failed"))){let y=ft(l,r,n);await St(y);continue}throw o}}throw o??Error("Request failed after retries")}async function Hn(e){return _e(e,{maxRetries:0})}async function qn(e,t){let{maxRetries:a=3,initialDelayMs:r=100,maxDelayMs:n=5000,retryableStatusCodes:i=[429,500,502,503,504],timeoutMs:s=30000}=t??{},o;for(let c=0;c<=a;c++){let l=await zt(e),u={method:l.method,headers:l.headers};if(l.body)u.body=l.body;let m=new AbortController,p=setTimeout(()=>m.abort(),s);u.signal=m.signal;try{let g=await fetch(l.url,u);if(clearTimeout(p),g.ok)return g;if(c<a&&Ua(g.status,i)){let y=ft(c,r,n);await St(y);continue}let h=await g.text();throw Error(`AWS API request failed (${g.status}): ${h}`)}catch(g){if(clearTimeout(p),o=g,g instanceof Error&&g.name==="AbortError")o=Error(`Request timed out after ${s}ms`);if(c<a&&!(g instanceof Error&&g.message.includes("AWS API request failed"))){let h=ft(c,r,n);await St(h);continue}throw o}}throw o??Error("Request failed after retries")}async function dt(e){let t=await e.text(),a={},r=/<(\w+)>([^<]+)<\/\1>/g,n;while((n=r.exec(t))!==null){let[,i,s]=n;a[i]=s}return a}async function zn(e){return await e.json()}function Jn(){De.clear()}function Qn(){return De.size}function $n(){return Be!==void 0}function Yn(){return typeof crypto<"u"&&typeof crypto.subtle<"u"}var Be,De,Ga=100,Va,at=Gn(async()=>{try{Be=await import("node:crypto")}catch{}De=new Map,Va={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"}}),ul={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}},dl={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}}}},Fa=".ts-cloud",Zn="TS_CLOUD_STATE_DIR",ja=null;function pl(e){ja=e?.trim()||null}function Pt(){return process.env[Zn]?.trim()||ja||Fa}function ei(...e){return bt(Pt(),...e)}function ti(e,...t){let a=Pt();return Vt(a)?bt(a,...t):bt(e,a,...t)}function gl(e,t=process.cwd()){let a=(n,i)=>{let s=Xn(n,i);return s===""||!s.startsWith("..")&&!Vt(s)},r=Vt(e)?e:bt(t,e);return a(ti(t),r)}function Ka(e){let t=e.infrastructure?.compute!=null,a=Object.values(e.environments??{}).some((r)=>r?.app!=null);return{server:t,serverless:a}}function hl(e){if(e.mode==="server"||e.mode==="serverless")return e.mode;let{serverless:t}=Ka(e);return t?"serverless":"server"}function yl(e){let{server:t,serverless:a}=Ka(e);if(t&&a)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(e.mode==="server"&&a&&!t)return"Config sets `mode: 'server'` but declares a serverless app (`environments.<env>.app`). Remove the app or change the mode.";if(e.mode==="serverless"&&t&&!a)return"Config sets `mode: 'serverless'` but declares a server (`infrastructure.compute`). Remove the compute block or change the mode.";return null}function fl(e){return e.infrastructure?.appDatabase??e.infrastructure?.compute?.database}function ai(e){return typeof e==="object"&&e!==null?e:{}}function ri(e){return e===!0||typeof e==="object"&&e!==null}function ni(e,t){let a=t?e.environments?.[t]:void 0;if(a?.domain)return a.domain;let r=Object.values(e.sites??{}),n=e.sites?.main?.domain??r.find((i)=>i.domain)?.domain;if(n)return n;return`${e.project?.slug??"app"}.local`}function ii(e){let t=e.indexOf(".");return t>0?e.slice(t+1):void 0}function Sl(e,t={}){let a=e.infrastructure?.compute?.managedServices?.mail,r=ai(a),n=t.environmentType??(t.environment?e.environments?.[t.environment]?.type:void 0),i=r.mode??(n==="production"?"server":"catcher"),s=i==="server",o=ni(e,t.environment),c=r.hostname??(s?`mail.${o}`:"localhost"),l=r.ports??{},u=s?{smtp:l.smtp??25,submission:l.submission??587,submissions:l.submissions??465,imap:l.imap??143,imaps:l.imaps??993,webmail:l.webmail??8080,managesieve:l.managesieve}:{smtp:l.smtp??1025,submission:l.submission,submissions:l.submissions,imap:l.imap,imaps:l.imaps,webmail:l.webmail??8025,managesieve:l.managesieve},m=r.tls??{},p=m.enabled??s,g=!!(m.certPath&&m.keyPath),h=(r.accounts??[]).map((I)=>({address:I.address,password:I.password})),y=typeof r.dkim==="object"&&r.dkim!==null?r.dkim:{},b=r.dkim===!1?!1:r.dkim===!0||s,T=typeof r.webmail==="object"&&r.webmail!==null?r.webmail:{},w=r.webmail===!1?!1:T.enabled??!0,S=r.spam??{},E=r.delivery??(s?"direct":"none"),v=r.expose??s,P=ii(c),N=[...new Set([c,...P?[P]:[],...r.domains??[]])];return{enabled:ri(a),mode:i,version:r.version,hostname:c,domains:N,ports:u,tls:{enabled:p,acme:p&&!g&&(m.acme??!0),certPath:m.certPath,keyPath:m.keyPath,requireForAuth:m.requireForAuth??(p&&s),acmeEmail:m.acmeEmail??h[0]?.address},dkim:{enabled:b,selector:y.selector??"default",rotate:y.rotate??!1,rotateIntervalDays:y.rotateIntervalDays??90},webmail:{enabled:w,port:T.port??u.webmail,domain:T.domain},delivery:E,sesRegion:r.sesRegion??"us-east-1",accounts:h,storagePath:r.storagePath??"/var/lib/mail",maxMessageSize:r.maxMessageSize??26214400,spam:{enabled:S.enabled??s,enforce:S.enforce??!1,junkScore:S.junkScore??5,rejectScore:S.rejectScore??12,dnsbl:S.dnsbl??s,greylist:S.greylist??!1},webhookUrl:r.webhookUrl,expose:v,bindAddress:v?"0.0.0.0":"127.0.0.1"}}function bl(e){if(!e.enabled||!e.expose)return[];let t=[e.ports.smtp,e.ports.submission,e.ports.submissions,e.ports.imap,e.ports.imaps,e.ports.managesieve].filter((a)=>typeof a==="number");if(e.webmail.enabled&&!e.webmail.domain)t.push(e.webmail.port);return[...new Set(t)].sort((a,r)=>a-r)}function Al(e){if(!e.enabled)return{};let t=e.ports.submission??e.ports.smtp,a={MAIL_MAILER:"smtp",MAIL_HOST:"127.0.0.1",MAIL_PORT:String(t)};if(e.mode==="server"){a.MAIL_ENCRYPTION=e.tls.enabled?"tls":"null";let r=e.accounts[0];if(r)a.MAIL_USERNAME=r.address,a.MAIL_PASSWORD=r.password}else a.MAIL_ENCRYPTION="null",a.MAIL_USERNAME="null",a.MAIL_PASSWORD="null";return a}function Cl(e){if(e.cloud?.provider)return e.cloud.provider;if(e.hetzner?.apiToken)return"hetzner";return"aws"}class si{template;constructor(e){this.template={AWSTemplateFormatVersion:"2010-09-09",Description:e,Resources:{}}}addResource(e,t){return this.template.Resources[e]=t,this}addResources(e){return Object.assign(this.template.Resources,e),this}addParameter(e,t){if(!this.template.Parameters)this.template.Parameters={};return this.template.Parameters[e]=t,this}addOutput(e,t){if(!this.template.Outputs)this.template.Outputs={};return this.template.Outputs[e]=t,this}hasResource(e){return e in this.template.Resources}getResources(){return this.template.Resources}build(){return this.template}toJSON(e=!0){return JSON.stringify(this.template,null,e?2:0)}toYAML(){return this.convertToYAML(this.template)}convertToYAML(e,t=0){let a=" ".repeat(t),r="";for(let[n,i]of Object.entries(e)){if(i===null||i===void 0)continue;if(typeof i==="object"&&!Array.isArray(i))r+=`${a}${n}:
14
14
  ${this.convertToYAML(i,t+1)}`;else if(Array.isArray(i)){r+=`${a}${n}:
15
15
  `;for(let s of i)if(typeof s==="object")r+=`${a} -
16
16
  ${this.convertToYAML(s,t+2)}`;else r+=`${a} - ${s}
17
17
  `}else r+=`${a}${n}: ${i}
18
- `}return r}}function vl(e){let t=[],a=[],r=[];if(ci(e,t),e.Resources)li(e.Resources,t,a);else t.push({path:"Resources",message:"Template must contain at least one resource",severity:"error"});if(e.Parameters)ui(e.Parameters,t,a);if(e.Outputs)di(e.Outputs,t);mi(e,t);let n=pi(e);if(n.length>0)for(let i of n)t.push({path:"Resources",message:`Circular dependency detected: ${i.join(" → ")}`,severity:"error"});return hi(e,a,r),{valid:t.length===0,errors:t,warnings:a,info:r}}function ci(e,t){if(!e.AWSTemplateFormatVersion)t.push({path:"AWSTemplateFormatVersion",message:"Template should specify AWSTemplateFormatVersion",severity:"error"});else if(e.AWSTemplateFormatVersion!=="2010-09-09")t.push({path:"AWSTemplateFormatVersion",message:'AWSTemplateFormatVersion must be "2010-09-09"',severity:"error"})}function li(e,t,a){let r=Object.keys(e);if(r.length===0){t.push({path:"Resources",message:"Template must contain at least one resource",severity:"error"});return}if(r.length>500)a.push({path:"Resources",message:`Template contains ${r.length} resources (limit is 500)`,severity:"warning"});for(let n of r){let i=e[n];if(!/^[a-zA-Z0-9]+$/.test(n))t.push({path:`Resources.${n}`,message:"Logical ID must contain only alphanumeric characters",severity:"error"});if(!i.Type)t.push({path:`Resources.${n}.Type`,message:"Resource Type is required",severity:"error"});else if(!i.Type.startsWith("AWS::")&&!i.Type.startsWith("Custom::"))t.push({path:`Resources.${n}.Type`,message:'Resource Type must start with "AWS::" or "Custom::"',severity:"error"});if(i.DeletionPolicy&&!["Delete","Retain","Snapshot"].includes(i.DeletionPolicy))t.push({path:`Resources.${n}.DeletionPolicy`,message:'DeletionPolicy must be "Delete", "Retain", or "Snapshot"',severity:"error"});if(!i.DeletionPolicy&&Ha(i.Type))a.push({path:`Resources.${n}.DeletionPolicy`,message:`${i.Type} should specify DeletionPolicy to prevent accidental data loss`,severity:"warning"})}}function ui(e,t,a){let r=Object.keys(e);if(r.length>200)a.push({path:"Parameters",message:`Template contains ${r.length} parameters (limit is 200)`,severity:"warning"});for(let n of r){let i=e[n];if(!i.Type)t.push({path:`Parameters.${n}.Type`,message:"Parameter Type is required",severity:"error"});let s=["String","Number","List<Number>","CommaDelimitedList","AWS::EC2::AvailabilityZone::Name","AWS::EC2::Image::Id","AWS::EC2::Instance::Id","AWS::EC2::KeyPair::KeyName","AWS::EC2::SecurityGroup::GroupName","AWS::EC2::SecurityGroup::Id","AWS::EC2::Subnet::Id","AWS::EC2::Volume::Id","AWS::EC2::VPC::Id","AWS::Route53::HostedZone::Id","List<AWS::EC2::AvailabilityZone::Name>","List<AWS::EC2::Image::Id>","List<AWS::EC2::Instance::Id>","List<AWS::EC2::SecurityGroup::GroupName>","List<AWS::EC2::SecurityGroup::Id>","List<AWS::EC2::Subnet::Id>","List<AWS::EC2::Volume::Id>","List<AWS::EC2::VPC::Id>","List<AWS::Route53::HostedZone::Id>","AWS::SSM::Parameter::Name","AWS::SSM::Parameter::Value<String>","AWS::SSM::Parameter::Value<List<String>>","AWS::SSM::Parameter::Value<CommaDelimitedList>"];if(i.Type&&!s.includes(i.Type))t.push({path:`Parameters.${n}.Type`,message:`Invalid parameter type: ${i.Type}`,severity:"error"})}}function di(e,t){let a=Object.keys(e);for(let r of a)if(!e[r].Value)t.push({path:`Outputs.${r}.Value`,message:"Output Value is required",severity:"error"})}function mi(e,t){let a=e.Resources||{},r=e.Parameters||{},n=new Set(Object.keys(a)),i=new Set(Object.keys(r));function s(o,c){if(typeof o!=="object"||o===null)return;if(o.Ref){let l=o.Ref;if(!n.has(l)&&!i.has(l)&&l!=="AWS::Region"&&l!=="AWS::AccountId"&&l!=="AWS::StackName"&&l!=="AWS::StackId"&&l!=="AWS::URLSuffix"&&l!=="AWS::Partition"&&l!=="AWS::NoValue")t.push({path:c,message:`Reference to non-existent resource or parameter: ${l}`,severity:"error"})}if(o["Fn::GetAtt"]){let l=o["Fn::GetAtt"];if(Array.isArray(l)&&l.length>=1){let u=l[0];if(!n.has(u))t.push({path:c,message:`GetAtt references non-existent resource: ${u}`,severity:"error"})}}for(let l in o)s(o[l],`${c}.${l}`)}for(let o in a)s(a[o],`Resources.${o}`);if(e.Outputs)for(let o in e.Outputs)s(e.Outputs[o],`Outputs.${o}`)}function pi(e){let t=e.Resources||{},a=new Map;for(let o in t){let c=new Set,l=t[o];if(l.DependsOn)if(Array.isArray(l.DependsOn))l.DependsOn.forEach((u)=>c.add(u));else c.add(l.DependsOn);gi(l).forEach((u)=>c.add(u)),a.set(o,c)}let r=[],n=new Set,i=new Set;function s(o,c){n.add(o),i.add(o),c.push(o);let l=a.get(o)||new Set;for(let u of l)if(!n.has(u))s(u,[...c]);else if(i.has(u)){let m=c.indexOf(u),p=[...c.slice(m),u];r.push(p)}i.delete(o)}for(let o of a.keys())if(!n.has(o))s(o,[]);return r}function gi(e){let t=new Set;function a(r){if(typeof r!=="object"||r===null)return;if(r.Ref&&typeof r.Ref==="string"){if(!r.Ref.startsWith("AWS::"))t.add(r.Ref)}if(r["Fn::GetAtt"]&&Array.isArray(r["Fn::GetAtt"]))t.add(r["Fn::GetAtt"][0]);for(let n in r)a(r[n])}return a(e),t}function Ha(e){return["AWS::S3::Bucket","AWS::DynamoDB::Table","AWS::RDS::DBInstance","AWS::RDS::DBCluster","AWS::ElastiCache::CacheCluster","AWS::ElastiCache::ReplicationGroup","AWS::EFS::FileSystem","AWS::OpenSearchService::Domain"].includes(e)}function hi(e,t,a){let r=e.Resources||{};if(!e.Description)a.push({path:"Description",message:"Consider adding a Description to the template",severity:"info"});for(let n in r){let i=r[n],s=i.Properties;if(s&&!s.Tags&&yi(i.Type))a.push({path:`Resources.${n}`,message:`Consider adding Tags to ${i.Type}`,severity:"info"});if(Ha(i.Type)){if(i.Type==="AWS::S3::Bucket"&&!s?.BucketEncryption)t.push({path:`Resources.${n}`,message:"S3 bucket should enable encryption",severity:"warning"});if(i.Type==="AWS::RDS::DBInstance"&&!s?.StorageEncrypted)t.push({path:`Resources.${n}`,message:"RDS instance should enable storage encryption",severity:"warning"})}}}function yi(e){return!["AWS::CloudFormation::Stack","AWS::CloudFormation::WaitCondition","AWS::CloudFormation::WaitConditionHandle"].includes(e)}function wl(e){let t=[],a=[],r=[],n=Buffer.byteLength(e,"utf8"),i=n/1024,s=51200,o=460800;if(n>460800)t.push({path:"Template",message:`Template size (${i.toFixed(2)} KB) exceeds maximum size of 450 KB`,severity:"error"});else if(n>51200)a.push({path:"Template",message:`Template size (${i.toFixed(2)} KB) exceeds 50 KB. Must use S3 for deployment.`,severity:"warning"});return{valid:t.length===0,errors:t,warnings:a,info:r}}function El(e){let t=[],a=[],r=[],n=e.Resources||{},i=e.Parameters||{},s=e.Outputs||{};if(Object.keys(n).length>500)t.push({path:"Resources",message:`Template has ${Object.keys(n).length} resources (limit is 500)`,severity:"error"});if(Object.keys(i).length>200)t.push({path:"Parameters",message:`Template has ${Object.keys(i).length} parameters (limit is 200)`,severity:"error"});if(Object.keys(s).length>200)t.push({path:"Outputs",message:`Template has ${Object.keys(s).length} outputs (limit is 200)`,severity:"error"});return{valid:t.length===0,errors:t,warnings:a,info:r}}var C={Ref:(e)=>({Ref:e}),GetAtt:(e,t)=>({"Fn::GetAtt":[e,t]}),Sub:(e,t)=>{if(t)return{"Fn::Sub":[e,t]};return{"Fn::Sub":e}},Join:(e,t)=>({"Fn::Join":[e,t]}),Select:(e,t)=>({"Fn::Select":[e,t]}),Split:(e,t)=>({"Fn::Split":[e,t]}),GetAZs:(e="")=>({"Fn::GetAZs":e}),ImportValue:(e)=>({"Fn::ImportValue":e}),If:(e,t,a)=>({"Fn::If":[e,t,a]}),Equals:(e,t)=>({"Fn::Equals":[e,t]}),And:(...e)=>({"Fn::And":e}),Or:(...e)=>({"Fn::Or":e}),Not:(e)=>({"Fn::Not":[e]}),Base64:(e)=>({"Fn::Base64":e})},Pl={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 A(e){let{slug:t,environment:a,resourceType:r,timestamp:n,suffix:i}=e,s=[t,a,r];if(n)s.push(n);if(i)s.push(i);return s.join("-")}function f(e){return e.split("-").map((t)=>t.charAt(0).toUpperCase()+t.slice(1)).join("")}function Il(){return Date.now().toString()}function Rl(e){return e.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/^-+|-+$/g,"").replace(/-+/g,"-")}function Nl(e,t){return e.project.stackName??`${e.project.slug}-${t}`}function Dl(e,t,a,r){return a.stackName??`${e.project.slug}-${r}-${t}-site`}function kl(e,t){return`${e.project.slug}-${t}`}function $l(e,t,a,r){if(r)return r;if(a==="main")return`${e}-${t}-site`;return`${e}-${t}-${a}`}function Ll(e,t,a,r){return r??`${e}-${t}-${a}`}function Ml(e,t){return`${e}-${t}-deploy`}function xl(e,t){return`${e.project.slug}-${t}-app`}function Ol(e,t){return`${e}-${t}-deployments`}function fi(e,t){return`${e}-${t}-assets`}class Si{nodes=new Map;addResource(e,t){let a=this.extractDependencies(t);this.nodes.set(e,{logicalId:e,resource:t,dependencies:a})}extractDependencies(e){let t=new Set;if(e.DependsOn)if(Array.isArray(e.DependsOn))e.DependsOn.forEach((a)=>t.add(a));else t.add(e.DependsOn);return this.findReferences(e.Properties||{},t),t}findReferences(e,t){if(!e||typeof e!=="object")return;if("Ref"in e&&typeof e.Ref==="string"){if(!e.Ref.startsWith("AWS::"))t.add(e.Ref)}if("Fn::GetAtt"in e&&Array.isArray(e["Fn::GetAtt"]))t.add(e["Fn::GetAtt"][0]);for(let a of Object.values(e))if(typeof a==="object")this.findReferences(a,t)}topologicalSort(){let e=[],t=new Set,a=new Set,r=(n)=>{if(t.has(n))return;if(a.has(n))throw Error(`Circular dependency detected: ${n}`);a.add(n);let i=this.nodes.get(n);if(i)for(let s of i.dependencies)r(s);a.delete(n),t.add(n),e.push(n)};for(let n of this.nodes.keys())r(n);return e}validate(){for(let[e,t]of this.nodes.entries())for(let a of t.dependencies)if(!this.nodes.has(a))throw Error(`Resource "${e}" depends on "${a}" which does not exist`)}getDependents(e){let t=[];for(let[a,r]of this.nodes.entries())if(r.dependencies.has(e))t.push(a);return t}}function Bl(e,t){let a=[],r=[],n=[],i=[],s=[],o=e.Resources||{},c=t.Resources||{},l=new Set([...Object.keys(o),...Object.keys(c)]);for(let m of l){let p=o[m],g=c[m];if(!p&&g)a.push({logicalId:m,action:"add",resourceType:g.Type});else if(p&&!g)r.push({logicalId:m,action:"remove",resourceType:p.Type});else if(p&&g)if(p.Type!==g.Type)i.push({logicalId:m,action:"replace",resourceType:g.Type,reason:`Type changed from ${p.Type} to ${g.Type}`});else{let h=qa(p.Properties||{},g.Properties||{});if(h.length>0)if(bi(p.Type,h))i.push({logicalId:m,action:"replace",resourceType:g.Type,changes:h,reason:"Property changes require replacement"});else n.push({logicalId:m,action:"update",resourceType:g.Type,changes:h});else s.push(m)}}let u=Ai([...r,...i,...n]);return{added:a,removed:r,updated:n,replaced:i,unchanged:s,summary:{totalChanges:a.length+r.length+n.length+i.length,requiresReplacement:i.length>0,dangerousChanges:u}}}function qa(e,t,a=""){let r=[],n=new Set([...Object.keys(e),...Object.keys(t)]);for(let i of n){let s=a?`${a}.${i}`:i,o=e[i],c=t[i];if(o===void 0&&c!==void 0)r.push({path:s,oldValue:void 0,newValue:c});else if(o!==void 0&&c===void 0)r.push({path:s,oldValue:o,newValue:void 0});else if(typeof o!==typeof c)r.push({path:s,oldValue:o,newValue:c});else if(typeof o==="object"&&o!==null)if(Array.isArray(o)&&Array.isArray(c)){if(JSON.stringify(o)!==JSON.stringify(c))r.push({path:s,oldValue:o,newValue:c})}else if(!Array.isArray(o)&&!Array.isArray(c)){let l=qa(o,c,s);r.push(...l)}else r.push({path:s,oldValue:o,newValue:c});else if(o!==c)r.push({path:s,oldValue:o,newValue:c})}return r}function bi(e,t){let a={"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"])}[e];if(!a)return!1;for(let r of t){let n=r.path.split(".")[0];if(a.has(n))return!0}return!1}function Ai(e){let t=[];for(let a of e){if(a.action==="remove"&&(a.resourceType==="AWS::RDS::DBInstance"||a.resourceType==="AWS::DynamoDB::Table"||a.resourceType==="AWS::ElastiCache::CacheCluster"))t.push(`Removing ${a.resourceType} ${a.logicalId} - data loss risk!`);if(a.action==="replace"&&(a.resourceType==="AWS::RDS::DBInstance"||a.resourceType==="AWS::DynamoDB::Table"))t.push(`Replacing ${a.resourceType} ${a.logicalId} - data loss risk!`);if((a.action==="remove"||a.action==="replace")&&a.resourceType==="AWS::S3::Bucket")t.push(`${a.action==="remove"?"Removing":"Replacing"} S3 bucket ${a.logicalId} - data loss risk!`);if(a.action==="replace"&&a.resourceType==="AWS::EC2::Instance")t.push(`Replacing EC2 instance ${a.logicalId} - downtime expected`);if(a.action==="update"&&a.resourceType==="AWS::EC2::SecurityGroup")t.push(`Updating security group ${a.logicalId} - may affect connectivity`);if((a.action==="update"||a.action==="replace")&&(a.resourceType==="AWS::IAM::Role"||a.resourceType==="AWS::IAM::Policy"))t.push(`Modifying IAM ${a.resourceType.split("::")[2]} ${a.logicalId} - may affect permissions`)}return t}function _l(e){let t=[];if(t.push(`=== Stack Update Analysis ===
18
+ `}return r}}function Tl(e){let t=[],a=[],r=[];if(oi(e,t),e.Resources)ci(e.Resources,t,a);else t.push({path:"Resources",message:"Template must contain at least one resource",severity:"error"});if(e.Parameters)li(e.Parameters,t,a);if(e.Outputs)ui(e.Outputs,t);di(e,t);let n=mi(e);if(n.length>0)for(let i of n)t.push({path:"Resources",message:`Circular dependency detected: ${i.join(" → ")}`,severity:"error"});return gi(e,a,r),{valid:t.length===0,errors:t,warnings:a,info:r}}function oi(e,t){if(!e.AWSTemplateFormatVersion)t.push({path:"AWSTemplateFormatVersion",message:"Template should specify AWSTemplateFormatVersion",severity:"error"});else if(e.AWSTemplateFormatVersion!=="2010-09-09")t.push({path:"AWSTemplateFormatVersion",message:'AWSTemplateFormatVersion must be "2010-09-09"',severity:"error"})}function ci(e,t,a){let r=Object.keys(e);if(r.length===0){t.push({path:"Resources",message:"Template must contain at least one resource",severity:"error"});return}if(r.length>500)a.push({path:"Resources",message:`Template contains ${r.length} resources (limit is 500)`,severity:"warning"});for(let n of r){let i=e[n];if(!/^[a-zA-Z0-9]+$/.test(n))t.push({path:`Resources.${n}`,message:"Logical ID must contain only alphanumeric characters",severity:"error"});if(!i.Type)t.push({path:`Resources.${n}.Type`,message:"Resource Type is required",severity:"error"});else if(!i.Type.startsWith("AWS::")&&!i.Type.startsWith("Custom::"))t.push({path:`Resources.${n}.Type`,message:'Resource Type must start with "AWS::" or "Custom::"',severity:"error"});if(i.DeletionPolicy&&!["Delete","Retain","Snapshot"].includes(i.DeletionPolicy))t.push({path:`Resources.${n}.DeletionPolicy`,message:'DeletionPolicy must be "Delete", "Retain", or "Snapshot"',severity:"error"});if(!i.DeletionPolicy&&Ha(i.Type))a.push({path:`Resources.${n}.DeletionPolicy`,message:`${i.Type} should specify DeletionPolicy to prevent accidental data loss`,severity:"warning"})}}function li(e,t,a){let r=Object.keys(e);if(r.length>200)a.push({path:"Parameters",message:`Template contains ${r.length} parameters (limit is 200)`,severity:"warning"});for(let n of r){let i=e[n];if(!i.Type)t.push({path:`Parameters.${n}.Type`,message:"Parameter Type is required",severity:"error"});let s=["String","Number","List<Number>","CommaDelimitedList","AWS::EC2::AvailabilityZone::Name","AWS::EC2::Image::Id","AWS::EC2::Instance::Id","AWS::EC2::KeyPair::KeyName","AWS::EC2::SecurityGroup::GroupName","AWS::EC2::SecurityGroup::Id","AWS::EC2::Subnet::Id","AWS::EC2::Volume::Id","AWS::EC2::VPC::Id","AWS::Route53::HostedZone::Id","List<AWS::EC2::AvailabilityZone::Name>","List<AWS::EC2::Image::Id>","List<AWS::EC2::Instance::Id>","List<AWS::EC2::SecurityGroup::GroupName>","List<AWS::EC2::SecurityGroup::Id>","List<AWS::EC2::Subnet::Id>","List<AWS::EC2::Volume::Id>","List<AWS::EC2::VPC::Id>","List<AWS::Route53::HostedZone::Id>","AWS::SSM::Parameter::Name","AWS::SSM::Parameter::Value<String>","AWS::SSM::Parameter::Value<List<String>>","AWS::SSM::Parameter::Value<CommaDelimitedList>"];if(i.Type&&!s.includes(i.Type))t.push({path:`Parameters.${n}.Type`,message:`Invalid parameter type: ${i.Type}`,severity:"error"})}}function ui(e,t){let a=Object.keys(e);for(let r of a)if(!e[r].Value)t.push({path:`Outputs.${r}.Value`,message:"Output Value is required",severity:"error"})}function di(e,t){let a=e.Resources||{},r=e.Parameters||{},n=new Set(Object.keys(a)),i=new Set(Object.keys(r));function s(o,c){if(typeof o!=="object"||o===null)return;if(o.Ref){let l=o.Ref;if(!n.has(l)&&!i.has(l)&&l!=="AWS::Region"&&l!=="AWS::AccountId"&&l!=="AWS::StackName"&&l!=="AWS::StackId"&&l!=="AWS::URLSuffix"&&l!=="AWS::Partition"&&l!=="AWS::NoValue")t.push({path:c,message:`Reference to non-existent resource or parameter: ${l}`,severity:"error"})}if(o["Fn::GetAtt"]){let l=o["Fn::GetAtt"];if(Array.isArray(l)&&l.length>=1){let u=l[0];if(!n.has(u))t.push({path:c,message:`GetAtt references non-existent resource: ${u}`,severity:"error"})}}for(let l in o)s(o[l],`${c}.${l}`)}for(let o in a)s(a[o],`Resources.${o}`);if(e.Outputs)for(let o in e.Outputs)s(e.Outputs[o],`Outputs.${o}`)}function mi(e){let t=e.Resources||{},a=new Map;for(let o in t){let c=new Set,l=t[o];if(l.DependsOn)if(Array.isArray(l.DependsOn))l.DependsOn.forEach((u)=>c.add(u));else c.add(l.DependsOn);pi(l).forEach((u)=>c.add(u)),a.set(o,c)}let r=[],n=new Set,i=new Set;function s(o,c){n.add(o),i.add(o),c.push(o);let l=a.get(o)||new Set;for(let u of l)if(!n.has(u))s(u,[...c]);else if(i.has(u)){let m=c.indexOf(u),p=[...c.slice(m),u];r.push(p)}i.delete(o)}for(let o of a.keys())if(!n.has(o))s(o,[]);return r}function pi(e){let t=new Set;function a(r){if(typeof r!=="object"||r===null)return;if(r.Ref&&typeof r.Ref==="string"){if(!r.Ref.startsWith("AWS::"))t.add(r.Ref)}if(r["Fn::GetAtt"]&&Array.isArray(r["Fn::GetAtt"]))t.add(r["Fn::GetAtt"][0]);for(let n in r)a(r[n])}return a(e),t}function Ha(e){return["AWS::S3::Bucket","AWS::DynamoDB::Table","AWS::RDS::DBInstance","AWS::RDS::DBCluster","AWS::ElastiCache::CacheCluster","AWS::ElastiCache::ReplicationGroup","AWS::EFS::FileSystem","AWS::OpenSearchService::Domain"].includes(e)}function gi(e,t,a){let r=e.Resources||{};if(!e.Description)a.push({path:"Description",message:"Consider adding a Description to the template",severity:"info"});for(let n in r){let i=r[n],s=i.Properties;if(s&&!s.Tags&&hi(i.Type))a.push({path:`Resources.${n}`,message:`Consider adding Tags to ${i.Type}`,severity:"info"});if(Ha(i.Type)){if(i.Type==="AWS::S3::Bucket"&&!s?.BucketEncryption)t.push({path:`Resources.${n}`,message:"S3 bucket should enable encryption",severity:"warning"});if(i.Type==="AWS::RDS::DBInstance"&&!s?.StorageEncrypted)t.push({path:`Resources.${n}`,message:"RDS instance should enable storage encryption",severity:"warning"})}}}function hi(e){return!["AWS::CloudFormation::Stack","AWS::CloudFormation::WaitCondition","AWS::CloudFormation::WaitConditionHandle"].includes(e)}function vl(e){let t=[],a=[],r=[],n=Buffer.byteLength(e,"utf8"),i=n/1024,s=51200,o=460800;if(n>460800)t.push({path:"Template",message:`Template size (${i.toFixed(2)} KB) exceeds maximum size of 450 KB`,severity:"error"});else if(n>51200)a.push({path:"Template",message:`Template size (${i.toFixed(2)} KB) exceeds 50 KB. Must use S3 for deployment.`,severity:"warning"});return{valid:t.length===0,errors:t,warnings:a,info:r}}function wl(e){let t=[],a=[],r=[],n=e.Resources||{},i=e.Parameters||{},s=e.Outputs||{};if(Object.keys(n).length>500)t.push({path:"Resources",message:`Template has ${Object.keys(n).length} resources (limit is 500)`,severity:"error"});if(Object.keys(i).length>200)t.push({path:"Parameters",message:`Template has ${Object.keys(i).length} parameters (limit is 200)`,severity:"error"});if(Object.keys(s).length>200)t.push({path:"Outputs",message:`Template has ${Object.keys(s).length} outputs (limit is 200)`,severity:"error"});return{valid:t.length===0,errors:t,warnings:a,info:r}}var C={Ref:(e)=>({Ref:e}),GetAtt:(e,t)=>({"Fn::GetAtt":[e,t]}),Sub:(e,t)=>{if(t)return{"Fn::Sub":[e,t]};return{"Fn::Sub":e}},Join:(e,t)=>({"Fn::Join":[e,t]}),Select:(e,t)=>({"Fn::Select":[e,t]}),Split:(e,t)=>({"Fn::Split":[e,t]}),GetAZs:(e="")=>({"Fn::GetAZs":e}),ImportValue:(e)=>({"Fn::ImportValue":e}),If:(e,t,a)=>({"Fn::If":[e,t,a]}),Equals:(e,t)=>({"Fn::Equals":[e,t]}),And:(...e)=>({"Fn::And":e}),Or:(...e)=>({"Fn::Or":e}),Not:(e)=>({"Fn::Not":[e]}),Base64:(e)=>({"Fn::Base64":e})},El={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 A(e){let{slug:t,environment:a,resourceType:r,timestamp:n,suffix:i}=e,s=[t,a,r];if(n)s.push(n);if(i)s.push(i);return s.join("-")}function f(e){return e.split("-").map((t)=>t.charAt(0).toUpperCase()+t.slice(1)).join("")}function Pl(){return Date.now().toString()}function Il(e){return e.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/^-+|-+$/g,"").replace(/-+/g,"-")}function Rl(e,t){return e.project.stackName??`${e.project.slug}-${t}`}function Nl(e,t,a,r){return a.stackName??`${e.project.slug}-${r}-${t}-site`}function Dl(e,t){return`${e.project.slug}-${t}`}function kl(e,t,a,r){if(r)return r;if(a==="main")return`${e}-${t}-site`;return`${e}-${t}-${a}`}function Ml(e,t,a,r){return r??`${e}-${t}-${a}`}function Ll(e,t){return`${e}-${t}-deploy`}function xl(e,t){return`${e.project.slug}-${t}-app`}function Ol(e,t){return`${e}-${t}-deployments`}function yi(e,t){return`${e}-${t}-assets`}class fi{nodes=new Map;addResource(e,t){let a=this.extractDependencies(t);this.nodes.set(e,{logicalId:e,resource:t,dependencies:a})}extractDependencies(e){let t=new Set;if(e.DependsOn)if(Array.isArray(e.DependsOn))e.DependsOn.forEach((a)=>t.add(a));else t.add(e.DependsOn);return this.findReferences(e.Properties||{},t),t}findReferences(e,t){if(!e||typeof e!=="object")return;if("Ref"in e&&typeof e.Ref==="string"){if(!e.Ref.startsWith("AWS::"))t.add(e.Ref)}if("Fn::GetAtt"in e&&Array.isArray(e["Fn::GetAtt"]))t.add(e["Fn::GetAtt"][0]);for(let a of Object.values(e))if(typeof a==="object")this.findReferences(a,t)}topologicalSort(){let e=[],t=new Set,a=new Set,r=(n)=>{if(t.has(n))return;if(a.has(n))throw Error(`Circular dependency detected: ${n}`);a.add(n);let i=this.nodes.get(n);if(i)for(let s of i.dependencies)r(s);a.delete(n),t.add(n),e.push(n)};for(let n of this.nodes.keys())r(n);return e}validate(){for(let[e,t]of this.nodes.entries())for(let a of t.dependencies)if(!this.nodes.has(a))throw Error(`Resource "${e}" depends on "${a}" which does not exist`)}getDependents(e){let t=[];for(let[a,r]of this.nodes.entries())if(r.dependencies.has(e))t.push(a);return t}}function Wl(e,t){let a=[],r=[],n=[],i=[],s=[],o=e.Resources||{},c=t.Resources||{},l=new Set([...Object.keys(o),...Object.keys(c)]);for(let m of l){let p=o[m],g=c[m];if(!p&&g)a.push({logicalId:m,action:"add",resourceType:g.Type});else if(p&&!g)r.push({logicalId:m,action:"remove",resourceType:p.Type});else if(p&&g)if(p.Type!==g.Type)i.push({logicalId:m,action:"replace",resourceType:g.Type,reason:`Type changed from ${p.Type} to ${g.Type}`});else{let h=qa(p.Properties||{},g.Properties||{});if(h.length>0)if(Si(p.Type,h))i.push({logicalId:m,action:"replace",resourceType:g.Type,changes:h,reason:"Property changes require replacement"});else n.push({logicalId:m,action:"update",resourceType:g.Type,changes:h});else s.push(m)}}let u=bi([...r,...i,...n]);return{added:a,removed:r,updated:n,replaced:i,unchanged:s,summary:{totalChanges:a.length+r.length+n.length+i.length,requiresReplacement:i.length>0,dangerousChanges:u}}}function qa(e,t,a=""){let r=[],n=new Set([...Object.keys(e),...Object.keys(t)]);for(let i of n){let s=a?`${a}.${i}`:i,o=e[i],c=t[i];if(o===void 0&&c!==void 0)r.push({path:s,oldValue:void 0,newValue:c});else if(o!==void 0&&c===void 0)r.push({path:s,oldValue:o,newValue:void 0});else if(typeof o!==typeof c)r.push({path:s,oldValue:o,newValue:c});else if(typeof o==="object"&&o!==null)if(Array.isArray(o)&&Array.isArray(c)){if(JSON.stringify(o)!==JSON.stringify(c))r.push({path:s,oldValue:o,newValue:c})}else if(!Array.isArray(o)&&!Array.isArray(c)){let l=qa(o,c,s);r.push(...l)}else r.push({path:s,oldValue:o,newValue:c});else if(o!==c)r.push({path:s,oldValue:o,newValue:c})}return r}function Si(e,t){let a={"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"])}[e];if(!a)return!1;for(let r of t){let n=r.path.split(".")[0];if(a.has(n))return!0}return!1}function bi(e){let t=[];for(let a of e){if(a.action==="remove"&&(a.resourceType==="AWS::RDS::DBInstance"||a.resourceType==="AWS::DynamoDB::Table"||a.resourceType==="AWS::ElastiCache::CacheCluster"))t.push(`Removing ${a.resourceType} ${a.logicalId} - data loss risk!`);if(a.action==="replace"&&(a.resourceType==="AWS::RDS::DBInstance"||a.resourceType==="AWS::DynamoDB::Table"))t.push(`Replacing ${a.resourceType} ${a.logicalId} - data loss risk!`);if((a.action==="remove"||a.action==="replace")&&a.resourceType==="AWS::S3::Bucket")t.push(`${a.action==="remove"?"Removing":"Replacing"} S3 bucket ${a.logicalId} - data loss risk!`);if(a.action==="replace"&&a.resourceType==="AWS::EC2::Instance")t.push(`Replacing EC2 instance ${a.logicalId} - downtime expected`);if(a.action==="update"&&a.resourceType==="AWS::EC2::SecurityGroup")t.push(`Updating security group ${a.logicalId} - may affect connectivity`);if((a.action==="update"||a.action==="replace")&&(a.resourceType==="AWS::IAM::Role"||a.resourceType==="AWS::IAM::Policy"))t.push(`Modifying IAM ${a.resourceType.split("::")[2]} ${a.logicalId} - may affect permissions`)}return t}function _l(e){let t=[];if(t.push(`=== Stack Update Analysis ===
19
19
  `),e.summary.totalChanges===0)return t.push(`No changes detected.
20
20
  `),t.join(`
21
21
  `);if(t.push(`Total changes: ${e.summary.totalChanges}`),t.push(`Requires replacement: ${e.summary.requiresReplacement?"Yes":"No"}
22
22
  `),e.summary.dangerousChanges.length>0){t.push("⚠️ DANGEROUS CHANGES DETECTED:");for(let a of e.summary.dangerousChanges)t.push(` • ${a}`);t.push("")}if(e.added.length>0){t.push(`✅ Resources to Add (${e.added.length}):`);for(let a of e.added)t.push(` + ${a.logicalId} (${a.resourceType})`);t.push("")}if(e.removed.length>0){t.push(`❌ Resources to Remove (${e.removed.length}):`);for(let a of e.removed)t.push(` - ${a.logicalId} (${a.resourceType})`);t.push("")}if(e.replaced.length>0){t.push(`\uD83D\uDD04 Resources to Replace (${e.replaced.length}):`);for(let a of e.replaced){if(t.push(` ~ ${a.logicalId} (${a.resourceType})`),a.reason)t.push(` Reason: ${a.reason}`);if(a.changes){for(let r of a.changes.slice(0,3))t.push(` • ${r.path}: ${JSON.stringify(r.oldValue)} → ${JSON.stringify(r.newValue)}`);if(a.changes.length>3)t.push(` ... and ${a.changes.length-3} more changes`)}}t.push("")}if(e.updated.length>0){t.push(`\uD83D\uDCDD Resources to Update (${e.updated.length}):`);for(let a of e.updated)if(t.push(` ~ ${a.logicalId} (${a.resourceType})`),a.changes){for(let r of a.changes.slice(0,3))t.push(` • ${r.path}: ${JSON.stringify(r.oldValue)} → ${JSON.stringify(r.newValue)}`);if(a.changes.length>3)t.push(` ... and ${a.changes.length-3} more changes`)}t.push("")}if(e.unchanged.length>0)t.push(`⚪ Unchanged Resources (${e.unchanged.length})`);return t.join(`
23
- `)}class Pe{static createBucket(e){let{name:t,bucketName:a,slug:r,environment:n,public:i=!1,versioning:s=!1,website:o=!1,encryption:c=!0,intelligentTiering:l=!1,cors:u,lifecycleRules:m}=e,p=a??A({slug:r,environment:n,resourceType:"s3",suffix:t}),g=f(p),h={Type:"AWS::S3::Bucket",Properties:{BucketName:p}};if(c)h.Properties.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(s)h.Properties.VersioningConfiguration={Status:"Enabled"};if(o)h.Properties.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"error.html"};if(!i)h.Properties.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(u&&u.length>0)h.Properties.CorsConfiguration={CorsRules:u.map((b)=>({AllowedOrigins:b.allowedOrigins,AllowedMethods:b.allowedMethods,AllowedHeaders:b.allowedHeaders,MaxAge:b.maxAge}))};if(m&&m.length>0)h.Properties.LifecycleConfiguration={Rules:m.map((b)=>({Id:b.id,Status:b.enabled?"Enabled":"Disabled",ExpirationInDays:b.expirationDays,Transitions:b.transitions?.map((T)=>({TransitionInDays:T.days,StorageClass:T.storageClass}))}))};if(l&&m){let b={id:"IntelligentTieringRule",enabled:!0,transitions:[{days:0,storageClass:"INTELLIGENT_TIERING"}]};if(!h.Properties.LifecycleConfiguration)h.Properties.LifecycleConfiguration={Rules:[]};h.Properties.LifecycleConfiguration.Rules.push({Id:b.id,Status:"Enabled",Transitions:b.transitions?.map((T)=>({TransitionInDays:T.days,StorageClass:T.storageClass}))})}let y;if(i)y={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:C.Ref(g),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[C.Join("",[C.GetAtt(g,"Arn"),"/*"])]}]}}};return{bucket:h,bucketPolicy:y,logicalId:g}}static enableVersioning(e){if(!e.Properties)e.Properties={};return e.Properties.VersioningConfiguration={Status:"Enabled"},e}static enableWebsiteHosting(e,t="index.html",a="error.html"){if(!e.Properties)e.Properties={};return e.Properties.WebsiteConfiguration={IndexDocument:t,ErrorDocument:a},e}static setLifecycleRules(e,t){if(!e.Properties)e.Properties={};return e.Properties.LifecycleConfiguration={Rules:t.map((a)=>({Id:a.id,Status:a.enabled?"Enabled":"Disabled",ExpirationInDays:a.expirationDays,Transitions:a.transitions?.map((r)=>({TransitionInDays:r.days,StorageClass:r.storageClass}))}))},e}static enableIntelligentTiering(e){if(!e.Properties)e.Properties={};if(!e.Properties.LifecycleConfiguration)e.Properties.LifecycleConfiguration={Rules:[]};return e.Properties.LifecycleConfiguration.Rules.push({Id:"IntelligentTieringRule",Status:"Enabled",Transitions:[{TransitionInDays:0,StorageClass:"INTELLIGENT_TIERING"}]}),e}static addLambdaNotification(e,t){if(!e.Properties)e.Properties={};if(!e.Properties.NotificationConfiguration)e.Properties.NotificationConfiguration={};if(!e.Properties.NotificationConfiguration.LambdaConfigurations)e.Properties.NotificationConfiguration.LambdaConfigurations=[];let a={Event:t.events[0],Function:t.functionArn};if(t.filter)a.Filter={S3Key:{Rules:[...t.filter.prefix?[{Name:"prefix",Value:t.filter.prefix}]:[],...t.filter.suffix?[{Name:"suffix",Value:t.filter.suffix}]:[]]}};for(let r of t.events){let n={...a,Event:r};e.Properties.NotificationConfiguration.LambdaConfigurations.push(n)}return e}static Notifications={onObjectCreated:(e)=>({functionArn:e,events:["s3:ObjectCreated:*"]}),onObjectRemoved:(e)=>({functionArn:e,events:["s3:ObjectRemoved:*"]}),onImageUpload:(e,t)=>({functionArn:e,events:["s3:ObjectCreated:*"],filter:{prefix:t,suffix:".jpg"}}),onFileType:(e,t,a)=>({functionArn:e,events:["s3:ObjectCreated:*"],filter:{prefix:a,suffix:t}}),onFolderUpload:(e,t)=>({functionArn:e,events:["s3:ObjectCreated:*"],filter:{prefix:t.endsWith("/")?t:`${t}/`}})};static createBackupPlan(e){let{name:t,slug:a,environment:r,bucketLogicalIds:n,retentionDays:i,schedule:s="cron(0 5 * * ? *)",vaultName:o,enableContinuousBackup:c=!1,moveToColdStorageAfterDays:l}=e,u=o||A({slug:a,environment:r,resourceType:"backup-vault",suffix:t}),m=f(u),p={Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:u}},g=A({slug:a,environment:r,resourceType:"backup-role",suffix:t}),h=f(g),y={Type:"AWS::IAM::Role",Properties:{RoleName:g,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"]}},b=A({slug:a,environment:r,resourceType:"backup-plan",suffix:t}),T=f(b),w={DeleteAfterDays:i};if(l&&l<i)w.MoveToColdStorageAfterDays=l;let S={Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:b,BackupPlanRule:[{RuleName:`${t}-daily-backup`,TargetBackupVault:C.Ref(m),ScheduleExpression:s,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:w,EnableContinuousBackup:c}]}}},E=A({slug:a,environment:r,resourceType:"backup-selection",suffix:t}),v=f(E),P=n.map((I)=>C.GetAtt(I,"Arn")),N={Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:C.Ref(T),BackupSelection:{SelectionName:E,IamRoleArn:C.GetAtt(h,"Arn"),Resources:P}}};return{vault:p,plan:S,selection:N,role:y,vaultLogicalId:m,planLogicalId:T,selectionLogicalId:v,roleLogicalId:h}}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(e){let{slug:t,environment:a,sourceDomain:r,targetDomain:n,protocol:i="https"}=e,s=A({slug:t,environment:a,resourceType:"s3",suffix:"www-redirect"}),o=f(s),c={Type:"AWS::S3::Bucket",Properties:{BucketName:r,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:n,Protocol:i}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1}}},l={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:C.Ref(o),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[C.Join("",[C.GetAtt(o,"Arn"),"/*"])]}]}}};return{bucket:c,bucketPolicy:l,logicalId:o}}static createDocsBucket(e){let{slug:t,environment:a,domain:r}=e,n=r||A({slug:t,environment:a,resourceType:"s3",suffix:"docs"}),i=f(n);return{bucket:{Type:"AWS::S3::Bucket",Properties:{BucketName:n,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},Tags:[{Key:"backup",Value:"weekly"}]}},logicalId:i}}static createEmailBucket(e){let{slug:t,environment:a}=e,r=A({slug:t,environment:a,resourceType:"s3",suffix:"email"}),n=f(r),i={Type:"AWS::S3::Bucket",Properties:{BucketName:r,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"}]}]}}},s={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:C.Ref(n),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowSESPuts",Effect:"Allow",Principal:{Service:"ses.amazonaws.com"},Action:"s3:PutObject",Resource:C.Join("",[C.GetAtt(n,"Arn"),"/*"]),Condition:{StringEquals:{"AWS:SourceAccount":C.Ref("AWS::AccountId")}}}]}}};return{bucket:i,bucketPolicy:s,logicalId:n}}static docsExist(e={}){let{projectRoot:t=process.cwd(),docsPaths:a=["docs","documentation","doc"]}=e;for(let r of a){let n=Ae(t,r);if(Ke(n)){let i=["dist","build",".bunpress/dist","_site","out","public"];for(let s of i){let o=Ae(n,s);if(Ke(o))try{if(Ci(o).length>0)return{exists:!0,path:n,hasDistFolder:!0,distPath:o}}catch{}}return{exists:!0,path:n,hasDistFolder:!1,distPath:null}}}return{exists:!1,path:null,hasDistFolder:!1,distPath:null}}static createDocsBucketIfExists(e){let t=Pe.docsExist({projectRoot:e.projectRoot,docsPaths:e.docsPaths});if(!t.exists)return{bucket:null,logicalId:null,docsInfo:t};let a=Pe.createDocsBucket({slug:e.slug,environment:e.environment,domain:e.domain});return{bucket:a.bucket,bucketPolicy:a.bucketPolicy,logicalId:a.logicalId,docsInfo:t}}static createPrivateBucket(e){let{slug:t,environment:a,enableVersioning:r=!0,retentionDays:n,encryptionKeyArn:i}=e,s=A({slug:t,environment:a,resourceType:"s3",suffix:"private"}),o=f(s);return{bucket:{Type:"AWS::S3::Bucket",Properties:{BucketName:s,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:i?{SSEAlgorithm:"aws:kms",KMSMasterKeyID:i}:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},VersioningConfiguration:r?{Status:"Enabled"}:void 0,LifecycleConfiguration:n?{Rules:[{Id:"RetentionPolicy",Status:"Enabled",ExpirationInDays:n}]}:void 0,Tags:[{Key:"backup",Value:"daily"}]}},logicalId:o}}static checkSourcePaths(e={}){let{projectRoot:t=process.cwd(),paths:a={}}=e,r=a.web||"views/web/dist",n=a.docs||"docs/dist",i=a.private||"private";return{web:{exists:Ke(Ae(t,r)),path:Ae(t,r)},docs:{exists:Ke(Ae(t,n)),path:Ae(t,n)},private:{exists:Ke(Ae(t,i)),path:Ae(t,i)}}}static createDeploymentBuckets(e){let{slug:t,environment:a,domain:r,projectRoot:n,paths:i}=e,s=Pe.checkSourcePaths({projectRoot:n,paths:i}),o={},c={web:!1,docs:!1,private:!1},l=Pe.createBucket({name:"web",slug:t,environment:a,public:!1,versioning:!1,encryption:!0});if(o[l.logicalId]=l.bucket,c.web=!0,s.docs.exists){let u=Pe.createDocsBucket({slug:t,environment:a,domain:r?`docs.${r}`:void 0});if(o[u.logicalId]=u.bucket,u.bucketPolicy)o[`${u.logicalId}Policy`]=u.bucketPolicy;c.docs=!0}if(s.private.exists){let u=Pe.createPrivateBucket({slug:t,environment:a,enableVersioning:!0});o[u.logicalId]=u.bucket,c.private=!0}return{resources:o,created:c,sourcePaths:s}}}class pe{static createRepository(e){let{name:t,slug:a,environment:r,scanOnPush:n=!0,imageMutability:i="MUTABLE",encryption:s="AES256",kmsKey:o,lifecyclePolicy:c,tags:l}=e,u=A({slug:a,environment:r,resourceType:"ecr",suffix:t}),m=f(u),p={Type:"AWS::ECR::Repository",Properties:{RepositoryName:u,ImageTagMutability:i,ImageScanningConfiguration:{ScanOnPush:n},EncryptionConfiguration:{EncryptionType:s,...o&&s==="KMS"?{KmsKey:o}:{}}}};if(c)p.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(pe.generateLifecyclePolicy(c))};if(l)p.Properties.Tags=Object.entries(l).map(([g,h])=>({Key:g,Value:h}));return{repository:p,logicalId:m}}static generateLifecyclePolicy(e){let t=[];if(e.untaggedImageExpireDays!==void 0)t.push({rulePriority:1,description:"Delete untagged images",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:e.untaggedImageExpireDays,countUnit:"days"},action:{type:"expire"}});if(e.maxImageCount!==void 0)t.push({rulePriority:t.length+1,description:"Keep only most recent images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:e.maxImageCount},action:{type:"expire"}});if(e.maxImageAgeDays!==void 0)t.push({rulePriority:t.length+1,description:"Delete images older than specified days",selection:{tagStatus:"any",countType:"sinceImagePushed",countNumber:e.maxImageAgeDays,countUnit:"days"},action:{type:"expire"}});return{rules:t}}static LifecyclePolicies={production:{maxImageCount:10,untaggedImageExpireDays:7},development:{maxImageCount:5,untaggedImageExpireDays:3},minimal:{maxImageCount:3,untaggedImageExpireDays:1},archive:{maxImageCount:50,untaggedImageExpireDays:30}};static enableImmutableTags(e){if(!e.Properties)e.Properties={};return e.Properties.ImageTagMutability="IMMUTABLE",e}static enableScanOnPush(e){if(!e.Properties)e.Properties={};return e.Properties.ImageScanningConfiguration={ScanOnPush:!0},e}static setLifecyclePolicy(e,t){if(!e.Properties)e.Properties={};return e.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(pe.generateLifecyclePolicy(t))},e}static addCrossAccountAccess(e,t){if(!e.Properties)e.Properties={};return e.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"CrossAccountPull",Effect:"Allow",Principal:{AWS:t.map((a)=>`arn:aws:iam::${a}:root`)},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:BatchCheckLayerAvailability"]}]},e}static addLambdaAccess(e){if(!e.Properties)e.Properties={};return e.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"LambdaECRImageRetrievalPolicy",Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage"]}]},e}static generateBunDockerfile(e){let{baseImage:t="oven/bun:1-debian",serverPath:a,port:r=3000,additionalDirs:n=[],healthCheckEndpoint:i="/health",nodeCompatible:s=!1,envVars:o={},buildCommands:c=[],runCommand:l}=e,u=["app","config",...n],m=l||`bun run ${a}`,p=`# Multi-stage build for Bun application
23
+ `)}class Ee{static createBucket(e){let{name:t,bucketName:a,slug:r,environment:n,public:i=!1,versioning:s=!1,website:o=!1,encryption:c=!0,intelligentTiering:l=!1,cors:u,lifecycleRules:m}=e,p=a??A({slug:r,environment:n,resourceType:"s3",suffix:t}),g=f(p),h={Type:"AWS::S3::Bucket",Properties:{BucketName:p}};if(c)h.Properties.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(s)h.Properties.VersioningConfiguration={Status:"Enabled"};if(o)h.Properties.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"error.html"};if(!i)h.Properties.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(u&&u.length>0)h.Properties.CorsConfiguration={CorsRules:u.map((b)=>({AllowedOrigins:b.allowedOrigins,AllowedMethods:b.allowedMethods,AllowedHeaders:b.allowedHeaders,MaxAge:b.maxAge}))};if(m&&m.length>0)h.Properties.LifecycleConfiguration={Rules:m.map((b)=>({Id:b.id,Status:b.enabled?"Enabled":"Disabled",ExpirationInDays:b.expirationDays,Transitions:b.transitions?.map((T)=>({TransitionInDays:T.days,StorageClass:T.storageClass}))}))};if(l&&m){let b={id:"IntelligentTieringRule",enabled:!0,transitions:[{days:0,storageClass:"INTELLIGENT_TIERING"}]};if(!h.Properties.LifecycleConfiguration)h.Properties.LifecycleConfiguration={Rules:[]};h.Properties.LifecycleConfiguration.Rules.push({Id:b.id,Status:"Enabled",Transitions:b.transitions?.map((T)=>({TransitionInDays:T.days,StorageClass:T.storageClass}))})}let y;if(i)y={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:C.Ref(g),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[C.Join("",[C.GetAtt(g,"Arn"),"/*"])]}]}}};return{bucket:h,bucketPolicy:y,logicalId:g}}static enableVersioning(e){if(!e.Properties)e.Properties={};return e.Properties.VersioningConfiguration={Status:"Enabled"},e}static enableWebsiteHosting(e,t="index.html",a="error.html"){if(!e.Properties)e.Properties={};return e.Properties.WebsiteConfiguration={IndexDocument:t,ErrorDocument:a},e}static setLifecycleRules(e,t){if(!e.Properties)e.Properties={};return e.Properties.LifecycleConfiguration={Rules:t.map((a)=>({Id:a.id,Status:a.enabled?"Enabled":"Disabled",ExpirationInDays:a.expirationDays,Transitions:a.transitions?.map((r)=>({TransitionInDays:r.days,StorageClass:r.storageClass}))}))},e}static enableIntelligentTiering(e){if(!e.Properties)e.Properties={};if(!e.Properties.LifecycleConfiguration)e.Properties.LifecycleConfiguration={Rules:[]};return e.Properties.LifecycleConfiguration.Rules.push({Id:"IntelligentTieringRule",Status:"Enabled",Transitions:[{TransitionInDays:0,StorageClass:"INTELLIGENT_TIERING"}]}),e}static addLambdaNotification(e,t){if(!e.Properties)e.Properties={};if(!e.Properties.NotificationConfiguration)e.Properties.NotificationConfiguration={};if(!e.Properties.NotificationConfiguration.LambdaConfigurations)e.Properties.NotificationConfiguration.LambdaConfigurations=[];let a={Event:t.events[0],Function:t.functionArn};if(t.filter)a.Filter={S3Key:{Rules:[...t.filter.prefix?[{Name:"prefix",Value:t.filter.prefix}]:[],...t.filter.suffix?[{Name:"suffix",Value:t.filter.suffix}]:[]]}};for(let r of t.events){let n={...a,Event:r};e.Properties.NotificationConfiguration.LambdaConfigurations.push(n)}return e}static Notifications={onObjectCreated:(e)=>({functionArn:e,events:["s3:ObjectCreated:*"]}),onObjectRemoved:(e)=>({functionArn:e,events:["s3:ObjectRemoved:*"]}),onImageUpload:(e,t)=>({functionArn:e,events:["s3:ObjectCreated:*"],filter:{prefix:t,suffix:".jpg"}}),onFileType:(e,t,a)=>({functionArn:e,events:["s3:ObjectCreated:*"],filter:{prefix:a,suffix:t}}),onFolderUpload:(e,t)=>({functionArn:e,events:["s3:ObjectCreated:*"],filter:{prefix:t.endsWith("/")?t:`${t}/`}})};static createBackupPlan(e){let{name:t,slug:a,environment:r,bucketLogicalIds:n,retentionDays:i,schedule:s="cron(0 5 * * ? *)",vaultName:o,enableContinuousBackup:c=!1,moveToColdStorageAfterDays:l}=e,u=o||A({slug:a,environment:r,resourceType:"backup-vault",suffix:t}),m=f(u),p={Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:u}},g=A({slug:a,environment:r,resourceType:"backup-role",suffix:t}),h=f(g),y={Type:"AWS::IAM::Role",Properties:{RoleName:g,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"]}},b=A({slug:a,environment:r,resourceType:"backup-plan",suffix:t}),T=f(b),w={DeleteAfterDays:i};if(l&&l<i)w.MoveToColdStorageAfterDays=l;let S={Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:b,BackupPlanRule:[{RuleName:`${t}-daily-backup`,TargetBackupVault:C.Ref(m),ScheduleExpression:s,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:w,EnableContinuousBackup:c}]}}},E=A({slug:a,environment:r,resourceType:"backup-selection",suffix:t}),v=f(E),P=n.map((I)=>C.GetAtt(I,"Arn")),N={Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:C.Ref(T),BackupSelection:{SelectionName:E,IamRoleArn:C.GetAtt(h,"Arn"),Resources:P}}};return{vault:p,plan:S,selection:N,role:y,vaultLogicalId:m,planLogicalId:T,selectionLogicalId:v,roleLogicalId:h}}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(e){let{slug:t,environment:a,sourceDomain:r,targetDomain:n,protocol:i="https"}=e,s=A({slug:t,environment:a,resourceType:"s3",suffix:"www-redirect"}),o=f(s),c={Type:"AWS::S3::Bucket",Properties:{BucketName:r,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:n,Protocol:i}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1}}},l={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:C.Ref(o),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[C.Join("",[C.GetAtt(o,"Arn"),"/*"])]}]}}};return{bucket:c,bucketPolicy:l,logicalId:o}}static createDocsBucket(e){let{slug:t,environment:a,domain:r}=e,n=r||A({slug:t,environment:a,resourceType:"s3",suffix:"docs"}),i=f(n);return{bucket:{Type:"AWS::S3::Bucket",Properties:{BucketName:n,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},Tags:[{Key:"backup",Value:"weekly"}]}},logicalId:i}}static createEmailBucket(e){let{slug:t,environment:a}=e,r=A({slug:t,environment:a,resourceType:"s3",suffix:"email"}),n=f(r),i={Type:"AWS::S3::Bucket",Properties:{BucketName:r,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"}]}]}}},s={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:C.Ref(n),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowSESPuts",Effect:"Allow",Principal:{Service:"ses.amazonaws.com"},Action:"s3:PutObject",Resource:C.Join("",[C.GetAtt(n,"Arn"),"/*"]),Condition:{StringEquals:{"AWS:SourceAccount":C.Ref("AWS::AccountId")}}}]}}};return{bucket:i,bucketPolicy:s,logicalId:n}}static docsExist(e={}){let{projectRoot:t=process.cwd(),docsPaths:a=["docs","documentation","doc"]}=e;for(let r of a){let n=be(t,r);if(Ke(n)){let i=["dist","build",".bunpress/dist","_site","out","public"];for(let s of i){let o=be(n,s);if(Ke(o))try{if(Ai(o).length>0)return{exists:!0,path:n,hasDistFolder:!0,distPath:o}}catch{}}return{exists:!0,path:n,hasDistFolder:!1,distPath:null}}}return{exists:!1,path:null,hasDistFolder:!1,distPath:null}}static createDocsBucketIfExists(e){let t=Ee.docsExist({projectRoot:e.projectRoot,docsPaths:e.docsPaths});if(!t.exists)return{bucket:null,logicalId:null,docsInfo:t};let a=Ee.createDocsBucket({slug:e.slug,environment:e.environment,domain:e.domain});return{bucket:a.bucket,bucketPolicy:a.bucketPolicy,logicalId:a.logicalId,docsInfo:t}}static createPrivateBucket(e){let{slug:t,environment:a,enableVersioning:r=!0,retentionDays:n,encryptionKeyArn:i}=e,s=A({slug:t,environment:a,resourceType:"s3",suffix:"private"}),o=f(s);return{bucket:{Type:"AWS::S3::Bucket",Properties:{BucketName:s,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:i?{SSEAlgorithm:"aws:kms",KMSMasterKeyID:i}:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},VersioningConfiguration:r?{Status:"Enabled"}:void 0,LifecycleConfiguration:n?{Rules:[{Id:"RetentionPolicy",Status:"Enabled",ExpirationInDays:n}]}:void 0,Tags:[{Key:"backup",Value:"daily"}]}},logicalId:o}}static checkSourcePaths(e={}){let{projectRoot:t=process.cwd(),paths:a={}}=e,r=a.web||"views/web/dist",n=a.docs||"docs/dist",i=a.private||"private";return{web:{exists:Ke(be(t,r)),path:be(t,r)},docs:{exists:Ke(be(t,n)),path:be(t,n)},private:{exists:Ke(be(t,i)),path:be(t,i)}}}static createDeploymentBuckets(e){let{slug:t,environment:a,domain:r,projectRoot:n,paths:i}=e,s=Ee.checkSourcePaths({projectRoot:n,paths:i}),o={},c={web:!1,docs:!1,private:!1},l=Ee.createBucket({name:"web",slug:t,environment:a,public:!1,versioning:!1,encryption:!0});if(o[l.logicalId]=l.bucket,c.web=!0,s.docs.exists){let u=Ee.createDocsBucket({slug:t,environment:a,domain:r?`docs.${r}`:void 0});if(o[u.logicalId]=u.bucket,u.bucketPolicy)o[`${u.logicalId}Policy`]=u.bucketPolicy;c.docs=!0}if(s.private.exists){let u=Ee.createPrivateBucket({slug:t,environment:a,enableVersioning:!0});o[u.logicalId]=u.bucket,c.private=!0}return{resources:o,created:c,sourcePaths:s}}}class me{static createRepository(e){let{name:t,slug:a,environment:r,scanOnPush:n=!0,imageMutability:i="MUTABLE",encryption:s="AES256",kmsKey:o,lifecyclePolicy:c,tags:l}=e,u=A({slug:a,environment:r,resourceType:"ecr",suffix:t}),m=f(u),p={Type:"AWS::ECR::Repository",Properties:{RepositoryName:u,ImageTagMutability:i,ImageScanningConfiguration:{ScanOnPush:n},EncryptionConfiguration:{EncryptionType:s,...o&&s==="KMS"?{KmsKey:o}:{}}}};if(c)p.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(me.generateLifecyclePolicy(c))};if(l)p.Properties.Tags=Object.entries(l).map(([g,h])=>({Key:g,Value:h}));return{repository:p,logicalId:m}}static generateLifecyclePolicy(e){let t=[];if(e.untaggedImageExpireDays!==void 0)t.push({rulePriority:1,description:"Delete untagged images",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:e.untaggedImageExpireDays,countUnit:"days"},action:{type:"expire"}});if(e.maxImageCount!==void 0)t.push({rulePriority:t.length+1,description:"Keep only most recent images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:e.maxImageCount},action:{type:"expire"}});if(e.maxImageAgeDays!==void 0)t.push({rulePriority:t.length+1,description:"Delete images older than specified days",selection:{tagStatus:"any",countType:"sinceImagePushed",countNumber:e.maxImageAgeDays,countUnit:"days"},action:{type:"expire"}});return{rules:t}}static LifecyclePolicies={production:{maxImageCount:10,untaggedImageExpireDays:7},development:{maxImageCount:5,untaggedImageExpireDays:3},minimal:{maxImageCount:3,untaggedImageExpireDays:1},archive:{maxImageCount:50,untaggedImageExpireDays:30}};static enableImmutableTags(e){if(!e.Properties)e.Properties={};return e.Properties.ImageTagMutability="IMMUTABLE",e}static enableScanOnPush(e){if(!e.Properties)e.Properties={};return e.Properties.ImageScanningConfiguration={ScanOnPush:!0},e}static setLifecyclePolicy(e,t){if(!e.Properties)e.Properties={};return e.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(me.generateLifecyclePolicy(t))},e}static addCrossAccountAccess(e,t){if(!e.Properties)e.Properties={};return e.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"CrossAccountPull",Effect:"Allow",Principal:{AWS:t.map((a)=>`arn:aws:iam::${a}:root`)},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:BatchCheckLayerAvailability"]}]},e}static addLambdaAccess(e){if(!e.Properties)e.Properties={};return e.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"LambdaECRImageRetrievalPolicy",Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage"]}]},e}static generateBunDockerfile(e){let{baseImage:t="oven/bun:1-debian",serverPath:a,port:r=3000,additionalDirs:n=[],healthCheckEndpoint:i="/health",nodeCompatible:s=!1,envVars:o={},buildCommands:c=[],runCommand:l}=e,u=["app","config",...n],m=l||`bun run ${a}`,p=`# 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", "${a}"]
77
- `,p}static generateDockerBuildCommands(e){let{repositoryUri:t,tag:a="latest",dockerfilePath:r="Dockerfile",context:n=".",additionalTags:i=[],buildArgs:s={},platform:o="linux/amd64",noCache:c=!1}=e,l=`${t}:${a}`,u=[a,...i],m=`docker build -f ${r} -t ${l}`;if(o)m+=` --platform ${o}`;if(c)m+=" --no-cache";for(let[h,y]of Object.entries(s))m+=` --build-arg ${h}=${y}`;m+=` ${n}`;let p=u.slice(1).map((h)=>`docker tag ${l} ${t}:${h}`),g=u.map((h)=>`docker push ${t}:${h}`);return{build:m,tag:p,push:g,all:[m,...p,...g]}}static generateEcrLoginCommand(e,t){return`aws ecr get-login-password --region ${e} | docker login --username AWS --password-stdin ${t}.dkr.ecr.${e}.amazonaws.com`}static buildRepositoryUri(e){return`${e.accountId}.dkr.ecr.${e.region}.amazonaws.com/${e.repositoryName}`}static generateImageTags(e){let t=["latest"];if(e.version){t.push(e.version);let a=e.version.split(".");if(a.length>=2)t.push(`${a[0]}.${a[1]}`);if(a.length>=1)t.push(a[0])}if(e.gitSha)t.push(e.gitSha.substring(0,7)),t.push(e.gitSha);if(e.gitBranch){let a=e.gitBranch.replace(/[^a-zA-Z0-9.-]/g,"-").replace(/^-+|-+$/g,"");t.push(a)}if(e.environment)t.push(e.environment);if(e.timestamp){let a=new Date().toISOString().replace(/[:.]/g,"-").substring(0,19);t.push(a)}return[...new Set(t)]}static DeploymentWorkflow={generateDeployScript:(e)=>{let t=pe.buildRepositoryUri({accountId:e.accountId,region:e.region,repositoryName:e.repositoryName}),a=e.tags||["latest"],r=a[0];return`#!/bin/bash
77
+ `,p}static generateDockerBuildCommands(e){let{repositoryUri:t,tag:a="latest",dockerfilePath:r="Dockerfile",context:n=".",additionalTags:i=[],buildArgs:s={},platform:o="linux/amd64",noCache:c=!1}=e,l=`${t}:${a}`,u=[a,...i],m=`docker build -f ${r} -t ${l}`;if(o)m+=` --platform ${o}`;if(c)m+=" --no-cache";for(let[h,y]of Object.entries(s))m+=` --build-arg ${h}=${y}`;m+=` ${n}`;let p=u.slice(1).map((h)=>`docker tag ${l} ${t}:${h}`),g=u.map((h)=>`docker push ${t}:${h}`);return{build:m,tag:p,push:g,all:[m,...p,...g]}}static generateEcrLoginCommand(e,t){return`aws ecr get-login-password --region ${e} | docker login --username AWS --password-stdin ${t}.dkr.ecr.${e}.amazonaws.com`}static buildRepositoryUri(e){return`${e.accountId}.dkr.ecr.${e.region}.amazonaws.com/${e.repositoryName}`}static generateImageTags(e){let t=["latest"];if(e.version){t.push(e.version);let a=e.version.split(".");if(a.length>=2)t.push(`${a[0]}.${a[1]}`);if(a.length>=1)t.push(a[0])}if(e.gitSha)t.push(e.gitSha.substring(0,7)),t.push(e.gitSha);if(e.gitBranch){let a=e.gitBranch.replace(/[^a-zA-Z0-9.-]/g,"-").replace(/^-+|-+$/g,"");t.push(a)}if(e.environment)t.push(e.environment);if(e.timestamp){let a=new Date().toISOString().replace(/[:.]/g,"-").substring(0,19);t.push(a)}return[...new Set(t)]}static DeploymentWorkflow={generateDeployScript:(e)=>{let t=me.buildRepositoryUri({accountId:e.accountId,region:e.region,repositoryName:e.repositoryName}),a=e.tags||["latest"],r=a[0];return`#!/bin/bash
78
78
  set -e
79
79
 
80
80
  # Configuration
@@ -85,7 +85,7 @@ IMAGE_URI="${t}"
85
85
  DOCKERFILE="${e.dockerfilePath||"Dockerfile"}"
86
86
 
87
87
  echo "=== ECR Login ==="
88
- ${pe.generateEcrLoginCommand(e.region,e.accountId)}
88
+ ${me.generateEcrLoginCommand(e.region,e.accountId)}
89
89
 
90
90
  echo "=== Building Image ==="
91
91
  docker build -f $DOCKERFILE -t $IMAGE_URI:${r} --platform linux/amd64 .
@@ -103,7 +103,7 @@ echo "Image: $IMAGE_URI:${r}"
103
103
  docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
104
104
  docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest`},...e.ecsCluster&&e.ecsService?[{name:"Deploy to ECS",run:`aws ecs update-service --cluster ${e.ecsCluster} --service ${e.ecsService} --force-new-deployment`}]:[]]}}};return`# Generated by ts-cloud
105
105
  ${JSON.stringify(t,null,2).replace(/"/g,"").replace(/,\n/g,`
106
- `)}`}};static DockerfileTemplates={bunServer:(e,t=3000)=>pe.generateBunDockerfile({serverPath:e,port:t}),bunWithBuild:(e,t,a=3000)=>pe.generateBunDockerfile({serverPath:e,port:a,buildCommands:[t]}),bunFullStack:(e,t=3000)=>pe.generateBunDockerfile({serverPath:e,port:t,additionalDirs:["public","views","dist"],buildCommands:["bun run build"]}),bunApi:(e,t=3000)=>pe.generateBunDockerfile({serverPath:e,port:t,healthCheckEndpoint:"/api/health"})}}class ne{static createDistribution(e){let{slug:t,environment:a,origin:r,customDomain:n,certificateArn:i,errorPages:s,cachePolicy:o,edgeFunctions:c,http3:l=!1,comment:u}=e,m=A({slug:t,environment:a,resourceType:"cdn"}),p=f(m),g={Id:"DefaultOrigin",DomainName:r.domainName,OriginPath:r.originPath||""},h;if(r.type==="s3"){let b=`${p}OAC`;h={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${m}-oac`,Description:`Origin Access Control for ${m}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},g.OriginAccessControlId=C.Ref(b)}else if(r.type==="alb"||r.type==="custom")g.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only"};let y={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:u||`CDN for ${m}`,DefaultRootObject:"index.html",Origins:[g],DefaultCacheBehavior:{TargetOriginId:"DefaultOrigin",ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0},PriceClass:"PriceClass_100",HttpVersion:l?"http2and3":"http2"}}};if(n&&i)y.Properties.DistributionConfig.Aliases=[n],y.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:i,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};if(s&&s.length>0)y.Properties.DistributionConfig.CustomErrorResponses=s.map((b)=>({ErrorCode:b.errorCode,ResponseCode:b.responseCode,ResponsePagePath:b.responsePagePath}));if(c&&c.length>0)y.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=c.map((b)=>({EventType:b.event,LambdaFunctionARN:b.functionArn}));return{distribution:y,originAccessControl:h,logicalId:p}}static setCustomDomain(e,t,a){return e.Properties.DistributionConfig.Aliases=[t],e.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:a,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"},e}static setErrorPages(e,t){return e.Properties.DistributionConfig.CustomErrorResponses=t.map((a)=>({ErrorCode:a.errorCode,ResponseCode:a.responseCode,ResponsePagePath:a.responsePagePath})),e}static enableHttp3(e){return e.Properties.DistributionConfig.HttpVersion="http2and3",e}static addEdgeFunction(e,t,a){if(!e.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations)e.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=[];return e.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations.push({EventType:t,LambdaFunctionARN:a}),e}static setCachePolicy(e,t){return e.Properties.DistributionConfig.Comment=`${e.Properties.DistributionConfig.Comment||""} (TTL: ${t.default||86400}s)`,e}static createSpaDistribution(e){return ne.createDistribution({...e,errorPages:[{errorCode:404,responseCode:200,responsePagePath:"/index.html"},{errorCode:403,responseCode:200,responsePagePath:"/index.html"}]})}static createDocsOriginRequestFunction(e){let{slug:t,environment:a}=e,r=A({slug:t,environment:a,resourceType:"edge-docs"}),n=f(r),i=f(`${r}-role`),s=f(`${r}-version`),o={Type:"AWS::IAM::Role",Properties:{RoleName:`${r}-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"]}},c=`
106
+ `)}`}};static DockerfileTemplates={bunServer:(e,t=3000)=>me.generateBunDockerfile({serverPath:e,port:t}),bunWithBuild:(e,t,a=3000)=>me.generateBunDockerfile({serverPath:e,port:a,buildCommands:[t]}),bunFullStack:(e,t=3000)=>me.generateBunDockerfile({serverPath:e,port:t,additionalDirs:["public","views","dist"],buildCommands:["bun run build"]}),bunApi:(e,t=3000)=>me.generateBunDockerfile({serverPath:e,port:t,healthCheckEndpoint:"/api/health"})}}class re{static createDistribution(e){let{slug:t,environment:a,origin:r,customDomain:n,certificateArn:i,errorPages:s,cachePolicy:o,edgeFunctions:c,http3:l=!1,comment:u}=e,m=A({slug:t,environment:a,resourceType:"cdn"}),p=f(m),g={Id:"DefaultOrigin",DomainName:r.domainName,OriginPath:r.originPath||""},h;if(r.type==="s3"){let b=`${p}OAC`;h={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${m}-oac`,Description:`Origin Access Control for ${m}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},g.OriginAccessControlId=C.Ref(b)}else if(r.type==="alb"||r.type==="custom")g.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only"};let y={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:u||`CDN for ${m}`,DefaultRootObject:"index.html",Origins:[g],DefaultCacheBehavior:{TargetOriginId:"DefaultOrigin",ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0},PriceClass:"PriceClass_100",HttpVersion:l?"http2and3":"http2"}}};if(n&&i)y.Properties.DistributionConfig.Aliases=[n],y.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:i,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};if(s&&s.length>0)y.Properties.DistributionConfig.CustomErrorResponses=s.map((b)=>({ErrorCode:b.errorCode,ResponseCode:b.responseCode,ResponsePagePath:b.responsePagePath}));if(c&&c.length>0)y.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=c.map((b)=>({EventType:b.event,LambdaFunctionARN:b.functionArn}));return{distribution:y,originAccessControl:h,logicalId:p}}static setCustomDomain(e,t,a){return e.Properties.DistributionConfig.Aliases=[t],e.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:a,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"},e}static setErrorPages(e,t){return e.Properties.DistributionConfig.CustomErrorResponses=t.map((a)=>({ErrorCode:a.errorCode,ResponseCode:a.responseCode,ResponsePagePath:a.responsePagePath})),e}static enableHttp3(e){return e.Properties.DistributionConfig.HttpVersion="http2and3",e}static addEdgeFunction(e,t,a){if(!e.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations)e.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=[];return e.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations.push({EventType:t,LambdaFunctionARN:a}),e}static setCachePolicy(e,t){return e.Properties.DistributionConfig.Comment=`${e.Properties.DistributionConfig.Comment||""} (TTL: ${t.default||86400}s)`,e}static createSpaDistribution(e){return re.createDistribution({...e,errorPages:[{errorCode:404,responseCode:200,responsePagePath:"/index.html"},{errorCode:403,responseCode:200,responsePagePath:"/index.html"}]})}static createDocsOriginRequestFunction(e){let{slug:t,environment:a}=e,r=A({slug:t,environment:a,resourceType:"edge-docs"}),n=f(r),i=f(`${r}-role`),s=f(`${r}-version`),o={Type:"AWS::IAM::Role",Properties:{RoleName:`${r}-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"]}},c=`
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:r,Description:"Lambda@Edge origin request handler for docs routing",Runtime:"nodejs20.x",Handler:"index.handler",Role:C.GetAtt(i,"Arn"),Code:{ZipFile:c},MemorySize:128,Timeout:5}},role:o,functionLogicalId:n,roleLogicalId:i,versionLogicalId:s}}static createDocsDistribution(e){let{slug:t,environment:a,origin:r,customDomain:n,certificateArn:i,lambdaEdgeFunctionArn:s}=e,o=ne.createDistribution({slug:t,environment:a,origin:r,customDomain:n,certificateArn:i,comment:`Docs CDN for ${t}`,errorPages:[{errorCode:404,responseCode:404,responsePagePath:"/404.html"},{errorCode:403,responseCode:403,responsePagePath:"/404.html"}]});if(s)ne.addEdgeFunction(o.distribution,"origin-request",s);return o.distribution.Properties.DistributionConfig.DefaultCacheBehavior.DefaultTTL=86400,o.distribution.Properties.DistributionConfig.DefaultCacheBehavior.MaxTTL=604800,o.distribution.Properties.DistributionConfig.DefaultCacheBehavior.MinTTL=0,o}static createApiDistribution(e){let{slug:t,environment:a,albDomainName:r,customDomain:n,certificateArn:i,pathPattern:s="/api/*",forwardHeaders:o=["Host","Origin","Authorization","Content-Type","Accept"],forwardCookies:c="all",whitelistedCookies:l,customOriginHeaders:u={}}=e,m=A({slug:t,environment:a,resourceType:"cdn-api"}),p=f(m),g=Object.entries(u).map(([T,w])=>({HeaderName:T,HeaderValue:w})),h={Id:"ALBOrigin",DomainName:r,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(g.length>0)h.OriginCustomHeaders=g;let y={Forward:c};if(c==="whitelist"&&l)y.WhitelistedNames=l;let b={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:`API CDN for ${m}`,Origins:[h],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:o,Cookies:y}},PriceClass:"PriceClass_100",HttpVersion:"http2"}}};if(n&&i)b.Properties.DistributionConfig.Aliases=[n],b.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:i,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};return{distribution:b,logicalId:p}}static createMultiOriginDistribution(e){let{slug:t,environment:a,s3BucketDomainName:r,albDomainName:n,apiPathPattern:i="/api/*",customDomain:s,certificateArn:o,customOriginHeaders:c={}}=e,l=A({slug:t,environment:a,resourceType:"cdn"}),u=f(l),m=`${u}OAC`,p={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${l}-oac`,Description:`Origin Access Control for ${l}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},g=Object.entries(c).map(([T,w])=>({HeaderName:T,HeaderValue:w})),h={Id:"S3Origin",DomainName:r,OriginAccessControlId:C.Ref(m)},y={Id:"ALBOrigin",DomainName:n,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(g.length>0)y.OriginCustomHeaders=g;let b={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:`Multi-origin CDN for ${l}`,DefaultRootObject:"index.html",Origins:[h,y],DefaultCacheBehavior:{TargetOriginId:"S3Origin",ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0},CacheBehaviors:[{PathPattern:i,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(s&&o)b.Properties.DistributionConfig.Aliases=[s],b.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:o,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};return{distribution:b,originAccessControl:p,logicalId:u,oacLogicalId:m}}static addAlbOrigin(e,t){let{originId:a,domainName:r,pathPattern:n,customHeaders:i={},forwardHeaders:s=["Host","Origin","Authorization","Content-Type","Accept"],cacheTtl:o={default:0,max:0,min:0}}=t,c=Object.entries(i).map(([u,m])=>({HeaderName:u,HeaderValue:m})),l={Id:a,DomainName:r,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(c.length>0)l.OriginCustomHeaders=c;if(!e.Properties.DistributionConfig.Origins)e.Properties.DistributionConfig.Origins=[];if(e.Properties.DistributionConfig.Origins.push(l),!e.Properties.DistributionConfig.CacheBehaviors)e.Properties.DistributionConfig.CacheBehaviors=[];return e.Properties.DistributionConfig.CacheBehaviors.push({PathPattern:n,TargetOriginId:a,ViewerProtocolPolicy:"https-only",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,DefaultTTL:o.default,MaxTTL:o.max,MinTTL:o.min,ForwardedValues:{QueryString:!0,Headers:s,Cookies:{Forward:"all"}}}),e}static addOriginHeader(e,t,a,r){let n=e.Properties.DistributionConfig.Origins?.find((i)=>i.Id===t);if(n){if(!n.OriginCustomHeaders)n.OriginCustomHeaders=[];n.OriginCustomHeaders.push({HeaderName:a,HeaderValue:r})}return e}static EdgeFunctionTemplates={docsOriginRequest:`
139
+ `.trim();return{lambdaFunction:{Type:"AWS::Lambda::Function",Properties:{FunctionName:r,Description:"Lambda@Edge origin request handler for docs routing",Runtime:"nodejs20.x",Handler:"index.handler",Role:C.GetAtt(i,"Arn"),Code:{ZipFile:c},MemorySize:128,Timeout:5}},role:o,functionLogicalId:n,roleLogicalId:i,versionLogicalId:s}}static createDocsDistribution(e){let{slug:t,environment:a,origin:r,customDomain:n,certificateArn:i,lambdaEdgeFunctionArn:s}=e,o=re.createDistribution({slug:t,environment:a,origin:r,customDomain:n,certificateArn:i,comment:`Docs CDN for ${t}`,errorPages:[{errorCode:404,responseCode:404,responsePagePath:"/404.html"},{errorCode:403,responseCode:403,responsePagePath:"/404.html"}]});if(s)re.addEdgeFunction(o.distribution,"origin-request",s);return o.distribution.Properties.DistributionConfig.DefaultCacheBehavior.DefaultTTL=86400,o.distribution.Properties.DistributionConfig.DefaultCacheBehavior.MaxTTL=604800,o.distribution.Properties.DistributionConfig.DefaultCacheBehavior.MinTTL=0,o}static createApiDistribution(e){let{slug:t,environment:a,albDomainName:r,customDomain:n,certificateArn:i,pathPattern:s="/api/*",forwardHeaders:o=["Host","Origin","Authorization","Content-Type","Accept"],forwardCookies:c="all",whitelistedCookies:l,customOriginHeaders:u={}}=e,m=A({slug:t,environment:a,resourceType:"cdn-api"}),p=f(m),g=Object.entries(u).map(([T,w])=>({HeaderName:T,HeaderValue:w})),h={Id:"ALBOrigin",DomainName:r,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(g.length>0)h.OriginCustomHeaders=g;let y={Forward:c};if(c==="whitelist"&&l)y.WhitelistedNames=l;let b={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:`API CDN for ${m}`,Origins:[h],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:o,Cookies:y}},PriceClass:"PriceClass_100",HttpVersion:"http2"}}};if(n&&i)b.Properties.DistributionConfig.Aliases=[n],b.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:i,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};return{distribution:b,logicalId:p}}static createMultiOriginDistribution(e){let{slug:t,environment:a,s3BucketDomainName:r,albDomainName:n,apiPathPattern:i="/api/*",customDomain:s,certificateArn:o,customOriginHeaders:c={}}=e,l=A({slug:t,environment:a,resourceType:"cdn"}),u=f(l),m=`${u}OAC`,p={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${l}-oac`,Description:`Origin Access Control for ${l}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},g=Object.entries(c).map(([T,w])=>({HeaderName:T,HeaderValue:w})),h={Id:"S3Origin",DomainName:r,OriginAccessControlId:C.Ref(m)},y={Id:"ALBOrigin",DomainName:n,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(g.length>0)y.OriginCustomHeaders=g;let b={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:`Multi-origin CDN for ${l}`,DefaultRootObject:"index.html",Origins:[h,y],DefaultCacheBehavior:{TargetOriginId:"S3Origin",ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0},CacheBehaviors:[{PathPattern:i,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(s&&o)b.Properties.DistributionConfig.Aliases=[s],b.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:o,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};return{distribution:b,originAccessControl:p,logicalId:u,oacLogicalId:m}}static addAlbOrigin(e,t){let{originId:a,domainName:r,pathPattern:n,customHeaders:i={},forwardHeaders:s=["Host","Origin","Authorization","Content-Type","Accept"],cacheTtl:o={default:0,max:0,min:0}}=t,c=Object.entries(i).map(([u,m])=>({HeaderName:u,HeaderValue:m})),l={Id:a,DomainName:r,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(c.length>0)l.OriginCustomHeaders=c;if(!e.Properties.DistributionConfig.Origins)e.Properties.DistributionConfig.Origins=[];if(e.Properties.DistributionConfig.Origins.push(l),!e.Properties.DistributionConfig.CacheBehaviors)e.Properties.DistributionConfig.CacheBehaviors=[];return e.Properties.DistributionConfig.CacheBehaviors.push({PathPattern:n,TargetOriginId:a,ViewerProtocolPolicy:"https-only",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,DefaultTTL:o.default,MaxTTL:o.max,MinTTL:o.min,ForwardedValues:{QueryString:!0,Headers:s,Cookies:{Forward:"all"}}}),e}static addOriginHeader(e,t,a,r){let n=e.Properties.DistributionConfig.Origins?.find((i)=>i.Id===t);if(n){if(!n.OriginCustomHeaders)n.OriginCustomHeaders=[];n.OriginCustomHeaders.push({HeaderName:a,HeaderValue:r})}return e}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:(e)=>{let{min:t=0,max:a=86400,default:r=86400}=e;return{MinTTL:t,MaxTTL:a,DefaultTTL:r}},cookies:(e,t)=>{let a={Forward:e==="allowList"?"whitelist":e};if(e==="allowList"&&t)a.WhitelistedNames=t;return a},allowedMethods:(e)=>{let t={ALL:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return t[e]||t.GET_HEAD},cachedMethods:(e)=>{let t={GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return t[e]||t.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:(e)=>{let{ttl:t={min:0,max:86400,default:86400},cookies:a="none",allowedCookies:r,allowedMethods:n="GET_HEAD",cachedMethods:i="GET_HEAD",compress:s=!0,forwardQueryString:o=!0,forwardHeaders:c=[]}=e;return{MinTTL:t.min,MaxTTL:t.max,DefaultTTL:t.default,Compress:s,AllowedMethods:ne.Config.allowedMethods(n),CachedMethods:ne.Config.cachedMethods(i),ForwardedValues:{QueryString:o,Headers:c,Cookies:ne.Config.cookies(a,r)}}}};static applyConfig(e,t){let a=e.Properties.DistributionConfig.DefaultCacheBehavior;if(t.ttl)a.MinTTL=t.ttl.min,a.MaxTTL=t.ttl.max,a.DefaultTTL=t.ttl.default;if(t.compress!==void 0)a.Compress=t.compress;if(t.allowedMethods)a.AllowedMethods=ne.Config.allowedMethods(t.allowedMethods);if(t.cachedMethods)a.CachedMethods=ne.Config.cachedMethods(t.cachedMethods);if(t.cookies){if(!a.ForwardedValues)a.ForwardedValues={QueryString:!0};a.ForwardedValues.Cookies=ne.Config.cookies(t.cookies,t.allowedCookies)}return e}}class q{static createHostedZone(e){let{domain:t,slug:a,environment:r,comment:n}=e,i=A({slug:a,environment:r,resourceType:"hostedzone"}),s=f(`${i}-${t.replace(/\./g,"")}`);return{zone:{Type:"AWS::Route53::HostedZone",Properties:{Name:t,HostedZoneConfig:{Comment:n||`Hosted zone for ${t}`}}},logicalId:s}}static createRecord(e){let{hostedZoneId:t,hostedZoneName:a,name:r,type:n,ttl:i,values:s,aliasTarget:o}=e,c=f(`record-${r.replace(/\./g,"")}-${n}`),l={Type:"AWS::Route53::RecordSet",Properties:{Name:r,Type:n}};if(t)l.Properties.HostedZoneId=t;else if(a)l.Properties.HostedZoneName=a;if(o)l.Properties.AliasTarget={DNSName:o.dnsName,HostedZoneId:o.hostedZoneId,EvaluateTargetHealth:o.evaluateTargetHealth??!1};else l.Properties.TTL=i||300,l.Properties.ResourceRecords=s||[];return{record:l,logicalId:c}}static createCloudFrontAlias(e,t,a){return q.createRecord({hostedZoneId:a,name:e,type:"A",aliasTarget:{dnsName:t,hostedZoneId:"Z2FDTNDATAQYW2",evaluateTargetHealth:!1}})}static createAlbAlias(e,t,a,r){return q.createRecord({hostedZoneId:r,name:e,type:"A",aliasTarget:{dnsName:t,hostedZoneId:a,evaluateTargetHealth:!0}})}static createCname(e,t,a,r=300){return q.createRecord({hostedZoneId:a,name:e,type:"CNAME",ttl:r,values:[t]})}static createWwwRedirect(e,t){return q.createRecord({hostedZoneId:t,name:`www.${e}`,type:"CNAME",ttl:300,values:[e]})}static createMxRecords(e,t,a,r=300){return q.createRecord({hostedZoneId:a,name:e,type:"MX",ttl:r,values:t.map((n)=>`${n.priority} ${n.server}`)})}static createTxtRecord(e,t,a,r=300){return q.createRecord({hostedZoneId:a,name:e,type:"TXT",ttl:r,values:[`"${t}"`]})}static createSpfRecord(e,t,a){return q.createTxtRecord(e,t,a)}static createDmarcRecord(e,t,a,r){let n=`v=DMARC1; p=${t}; rua=mailto:${a}`;return q.createTxtRecord(`_dmarc.${e}`,n,r)}static createS3WebsiteAlias(e,t,a,r){return q.createRecord({hostedZoneId:r,name:e,type:"A",aliasTarget:{dnsName:t,hostedZoneId:a,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(e,t){return`${e}.s3-website-${t}.amazonaws.com`}static createStoreRecord(e,t,a){return q.createCname(`store.${e}`,t,a)}static createApiRecord(e,t,a){return q.createCname(`api.${e}`,t,a)}static createDocsRecord(e,t,a){return q.createCname(`docs.${e}`,t,a)}static CloudFrontHostedZoneId="Z2FDTNDATAQYW2"}class G{static createCertificate(e){let{domain:t,subdomains:a=[],slug:r,environment:n,validationMethod:i="DNS",hostedZoneId:s}=e,o=A({slug:r,environment:n,resourceType:"acm"}),c=f(`${o}-${t.replace(/\./g,"")}`),l=[t];for(let m of a)if(m==="*")l.push(`*.${t}`);else l.push(`${m}.${t}`);let u={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:t,SubjectAlternativeNames:l,ValidationMethod:i}};if(i==="DNS"&&s)u.Properties.DomainValidationOptions=l.map((m)=>({DomainName:m,HostedZoneId:s}));return{certificate:u,logicalId:c}}static createKmsKey(e){let{description:t,slug:a,environment:r,enableRotation:n=!0,multiRegion:i=!1}=e,s=A({slug:a,environment:r,resourceType:"kms"}),o=f(s),c={Version:"2012-10-17",Statement:[{Sid:"Enable IAM User Permissions",Effect:"Allow",Principal:{AWS:C.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:"*"}]},l={Type:"AWS::KMS::Key",Properties:{Description:t,Enabled:!0,EnableKeyRotation:n,KeyPolicy:c,KeySpec:"SYMMETRIC_DEFAULT",KeyUsage:"ENCRYPT_DECRYPT",MultiRegion:i}},u=f(`${s}-alias`),m={Type:"AWS::KMS::Alias",Properties:{AliasName:`alias/${a}-${r}`,TargetKeyId:C.Ref(o)}};return{key:l,alias:m,logicalId:o,aliasId:u}}static createFirewall(e){let{slug:t,environment:a,scope:r="CLOUDFRONT",defaultAction:n="allow"}=e,i=A({slug:t,environment:a,resourceType:"waf"}),s=f(i);return{webAcl:{Type:"AWS::WAFv2::WebACL",Properties:{Name:i,Scope:r,DefaultAction:n==="allow"?{Allow:{}}:{Block:{}},Description:`WAF for ${t} ${a}`,Rules:[],VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i}-metric`}}},logicalId:s}}static setRateLimit(e,t){if(!e.Properties.Rules)e.Properties.Rules=[];return e.Properties.Rules.push({Name:t.name,Priority:t.priority,Statement:{RateBasedStatement:{Limit:t.requestsPerWindow,AggregateKeyType:t.aggregateKeyType||"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${t.name}-metric`}}),e}static blockCountries(e,t){if(!e.Properties.Rules)e.Properties.Rules=[];return e.Properties.Rules.push({Name:t.name,Priority:t.priority,Statement:{GeoMatchStatement:{CountryCodes:t.countryCodes}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${t.name}-metric`}}),e}static blockIpAddresses(e,t,a,r){let n=A({slug:a,environment:r,resourceType:"ipset"}),i=f(`${n}-${t.name}`),s={Type:"AWS::WAFv2::IPSet",Properties:{Name:`${n}-${t.name}`,Scope:e.Properties.Scope,IPAddressVersion:t.ipVersion||"IPV4",Addresses:t.ipAddresses,Description:`Blocked IPs for ${t.name}`}};if(!e.Properties.Rules)e.Properties.Rules=[];return e.Properties.Rules.push({Name:t.name,Priority:t.priority,Statement:{IPSetReferenceStatement:{Arn:C.GetAtt(i,"Arn")}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${t.name}-metric`}}),{webAcl:e,ipSet:s,ipSetLogicalId:i}}static addManagedRules(e,t){if(!e.Properties.Rules)e.Properties.Rules=[];let a={ManagedRuleGroupStatement:{VendorName:t.vendorName,Name:t.ruleName}};if(t.excludedRules&&t.excludedRules.length>0)a.ManagedRuleGroupStatement.ExcludedRules=t.excludedRules.map((r)=>({Name:r}));return e.Properties.Rules.push({Name:t.name,Priority:t.priority,Statement:a,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${t.name}-metric`}}),e}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(e,t){if(!e.Properties.Rules)e.Properties.Rules=[];let a=t.paths.map((r)=>({SearchString:r,FieldToMatch:{UriPath:{}},TextTransformation:[{Priority:0,Type:"LOWERCASE"}],PositionalConstraint:"STARTS_WITH"}));return e.Properties.Rules.push({Name:t.name,Priority:t.priority,Statement:{RateBasedStatement:{Limit:t.requestsPerWindow,AggregateKeyType:t.aggregateKeyType||"IP",ScopeDownStatement:{OrStatement:{Statements:a.map((r)=>({ByteMatchStatement:r}))}}}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${t.name}-metric`}}),e}static setHeaderRateLimit(e,t){if(!e.Properties.Rules)e.Properties.Rules=[];let a={RateBasedStatement:{Limit:t.requestsPerWindow,AggregateKeyType:"CUSTOM_KEYS",CustomKeys:[{Header:{Name:t.headerName,TextTransformations:[{Priority:0,Type:"NONE"}]}}]}};if(t.headerValue)a.RateBasedStatement.ScopeDownStatement={ByteMatchStatement:{SearchString:t.headerValue,FieldToMatch:{SingleHeader:{Name:t.headerName}},TextTransformation:[{Priority:0,Type:"NONE"}],PositionalConstraint:"EXACTLY"}};return e.Properties.Rules.push({Name:t.name,Priority:t.priority,Statement:a,Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${t.name}-metric`}}),e}static protectLoginEndpoint(e,t){let{loginPaths:a,priority:r,requestsPerMinute:n=10}=t;return G.setPathRateLimit(e,{name:"LoginRateLimit",priority:r,requestsPerWindow:n*5,paths:a}),e}static protectApiEndpoints(e,t){let{apiPaths:a,priority:r,requestsPerMinute:n=100}=t;return G.setPathRateLimit(e,{name:"ApiRateLimit",priority:r,requestsPerWindow:n*5,paths:a}),e}static createProtectedFirewall(e){let{slug:t,environment:a,scope:r="CLOUDFRONT",enableBotControl:n=!1,enableRateLimiting:i=!0,rateLimitPerMinute:s=2000}=e,{webAcl:o,logicalId:c}=G.createFirewall({slug:t,environment:a,scope:r,defaultAction:"allow"}),l=0;if(o=G.addManagedRules(o,{name:"AWSIPReputationList",priority:l++,...G.ManagedRuleGroups.AmazonIpReputation}),o=G.addManagedRules(o,{name:"AWSAnonymousIPList",priority:l++,...G.ManagedRuleGroups.AnonymousIpList}),o=G.addManagedRules(o,{name:"AWSCoreRuleSet",priority:l++,...G.ManagedRuleGroups.CoreRuleSet}),o=G.addManagedRules(o,{name:"AWSKnownBadInputs",priority:l++,...G.ManagedRuleGroups.KnownBadInputs}),o=G.addManagedRules(o,{name:"AWSSQLi",priority:l++,...G.ManagedRuleGroups.SqlDatabase}),n)o=G.addManagedRules(o,{name:"AWSBotControl",priority:l++,...G.ManagedRuleGroups.BotControl});if(i)o=G.setRateLimit(o,{name:"GlobalRateLimit",priority:l++,requestsPerWindow:s*5});return{webAcl:o,logicalId:c}}static RateLimitPresets={STANDARD:2000,HIGH_TRAFFIC:1e4,STRICT:100,LOGIN:10,API:100}}class k{static createServer(e){let{slug:t,environment:a,instanceType:r="t3.micro",imageId:n="ami-0f3caa1cf4417e51b",keyName:i,securityGroupIds:s,subnetId:o,userData:c,volumeSize:l=20,volumeType:u="gp3",encrypted:m=!0}=e,p=A({slug:t,environment:a,resourceType:"ec2"}),g=f(p),h={Type:"AWS::EC2::Instance",Properties:{ImageId:n,InstanceType:r,Tags:[{Key:"Name",Value:p},{Key:"Environment",Value:a}]}};if(i)h.Properties.KeyName=i;if(s)h.Properties.SecurityGroupIds=s;if(o)h.Properties.SubnetId=o;if(c)h.Properties.UserData=C.Base64(c);return h.Properties.BlockDeviceMappings=[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:l,VolumeType:u,Encrypted:m,DeleteOnTermination:!0}}],{instance:h,logicalId:g}}static createSecurityGroup(e){let{slug:t,environment:a,vpcId:r,description:n,ingress:i=[],egress:s=[]}=e,o=A({slug:t,environment:a,resourceType:"sg"}),c=f(o),l={Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:n||`Security group for ${t} ${a}`,Tags:[{Key:"Name",Value:o},{Key:"Environment",Value:a}]}};if(r)l.Properties.VpcId=r;if(i.length>0)l.Properties.SecurityGroupIngress=i.map((u)=>({IpProtocol:u.protocol,FromPort:u.fromPort,ToPort:u.toPort,CidrIp:u.cidr,SourceSecurityGroupId:u.sourceSecurityGroupId}));if(s.length>0)l.Properties.SecurityGroupEgress=s.map((u)=>({IpProtocol:u.protocol,FromPort:u.fromPort,ToPort:u.toPort,CidrIp:u.cidr,DestinationSecurityGroupId:u.sourceSecurityGroupId}));return{securityGroup:l,logicalId:c}}static createWebServerSecurityGroup(e,t,a){return k.createSecurityGroup({slug:e,environment:t,vpcId:a,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(e){let{slug:t,environment:a,scheme:r="internet-facing",subnets:n,securityGroups:i,type:s="application"}=e,o=A({slug:t,environment:a,resourceType:"alb"}),c=f(o),l={Type:"AWS::ElasticLoadBalancingV2::LoadBalancer",Properties:{Name:o,Scheme:r,Type:s,Subnets:n,Tags:[{Key:"Name",Value:o},{Key:"Environment",Value:a}]}};if(i)l.Properties.SecurityGroups=i;return{loadBalancer:l,logicalId:c}}static createTargetGroup(e){let{slug:t,environment:a,port:r,protocol:n="HTTP",vpcId:i,targetType:s="ip",healthCheckPath:o="/",healthCheckInterval:c=30,healthCheckTimeout:l=5,healthyThreshold:u=2,unhealthyThreshold:m=3}=e,p=A({slug:t,environment:a,resourceType:"tg"}),g=f(p);return{targetGroup:{Type:"AWS::ElasticLoadBalancingV2::TargetGroup",Properties:{Name:p,Port:r,Protocol:n,VpcId:i,TargetType:s,HealthCheckEnabled:!0,HealthCheckProtocol:n,HealthCheckPath:o,HealthCheckIntervalSeconds:c,HealthCheckTimeoutSeconds:l,HealthyThresholdCount:u,UnhealthyThresholdCount:m,Tags:[{Key:"Name",Value:p},{Key:"Environment",Value:a}]}},logicalId:g}}static createListener(e,t){let{port:a,protocol:r="HTTP",certificateArn:n,defaultTargetGroupArn:i}=t,s=f(`listener-${e}-${a}`),o={Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:C.Ref(e),Port:a,Protocol:r,DefaultActions:[{Type:"forward",TargetGroupArn:i}]}};if(r==="HTTPS"&&n)o.Properties.Certificates=[{CertificateArn:n}],o.Properties.SslPolicy="ELBSecurityPolicy-TLS13-1-2-2021-06";return{listener:o,logicalId:s}}static createEcsCluster(e,t){let a=A({slug:e,environment:t,resourceType:"ecs-cluster"}),r=f(a);return{cluster:{Type:"AWS::ECS::Cluster",Properties:{ClusterName:a,Tags:[{Key:"Name",Value:a},{Key:"Environment",Value:t}]}},logicalId:r}}static createFargateService(e){let{slug:t,environment:a,image:r,cpu:n="256",memory:i="512",desiredCount:s=1,containerPort:o=8080,environmentVariables:c={},secrets:l=[],healthCheck:u,logGroup:m,subnets:p,securityGroups:g,targetGroupArn:h}=e,{cluster:y,logicalId:b}=k.createEcsCluster(t,a),T=A({slug:t,environment:a,resourceType:"fargate"}),w=f(`${T}-execution-role`),S={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"]}},E=f(`${T}-task-role`),v={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]}}},P=f(`${T}-task`),N={Type:"AWS::ECS::TaskDefinition",Properties:{Family:T,TaskRoleArn:C.GetAtt(E,"Arn"),ExecutionRoleArn:C.GetAtt(w,"Arn"),NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:n,Memory:i,ContainerDefinitions:[{Name:t,Image:r,Essential:!0,PortMappings:[{ContainerPort:o,Protocol:"tcp"}],Environment:Object.entries(c).map(([L,O])=>({Name:L,Value:O})),Secrets:l.map((L)=>({Name:L.name,ValueFrom:L.valueFrom}))}],Tags:[{Key:"Name",Value:T},{Key:"Environment",Value:a}]}};if(u)N.Properties.ContainerDefinitions[0].HealthCheck={Command:u.command,Interval:u.interval||30,Timeout:u.timeout||5,Retries:u.retries||3,StartPeriod:60};if(m)N.Properties.ContainerDefinitions[0].LogConfiguration={LogDriver:"awslogs",Options:{"awslogs-group":m,"awslogs-region":C.Ref("AWS::Region"),"awslogs-stream-prefix":t}};let I=f(`${T}-service`),D={Type:"AWS::ECS::Service",Properties:{ServiceName:T,Cluster:C.Ref(b),TaskDefinition:C.Ref(P),DesiredCount:s,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{Subnets:p,SecurityGroups:g,AssignPublicIp:"ENABLED"}},Tags:[{Key:"Name",Value:T},{Key:"Environment",Value:a}]}};if(h)D.Properties.LoadBalancers=[{TargetGroupArn:h,ContainerName:t,ContainerPort:o}];return{cluster:y,taskDefinition:N,service:D,taskRole:v,executionRole:S,clusterLogicalId:b,taskDefinitionLogicalId:P,serviceLogicalId:I,taskRoleLogicalId:E,executionRoleLogicalId:w}}static createLambdaFunction(e){let{slug:t,environment:a,runtime:r,handler:n,code:i,timeout:s=30,memorySize:o=128,environmentVariables:c={},vpcConfig:l}=e,u=A({slug:t,environment:a,resourceType:"lambda"}),m=f(u),p=f(`${u}-role`),g={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(l)g.Properties.ManagedPolicyArns.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");let h={Type:"AWS::Lambda::Function",Properties:{FunctionName:u,Runtime:r,Role:C.GetAtt(p,"Arn"),Handler:n,Code:{...i.s3Bucket&&{S3Bucket:i.s3Bucket},...i.s3Key&&{S3Key:i.s3Key},...i.zipFile&&{ZipFile:i.zipFile}},Timeout:s,MemorySize:o,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:a}]}};if(Object.keys(c).length>0)h.Properties.Environment={Variables:c};if(l)h.Properties.VpcConfig={SecurityGroupIds:l.securityGroupIds,SubnetIds:l.subnetIds};return{lambdaFunction:h,role:g,logicalId:m,roleLogicalId:p}}static generateNodeServerUserData(e={}){let{nodeVersion:t="20",appRepo:a,environment:r={}}=e,n=Object.entries(r).map(([i,s])=>`echo "export ${i}='${s}'" >> /etc/environment`).join(`
212
+ `.trim()};static Config={ttl:(e)=>{let{min:t=0,max:a=86400,default:r=86400}=e;return{MinTTL:t,MaxTTL:a,DefaultTTL:r}},cookies:(e,t)=>{let a={Forward:e==="allowList"?"whitelist":e};if(e==="allowList"&&t)a.WhitelistedNames=t;return a},allowedMethods:(e)=>{let t={ALL:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return t[e]||t.GET_HEAD},cachedMethods:(e)=>{let t={GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return t[e]||t.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:(e)=>{let{ttl:t={min:0,max:86400,default:86400},cookies:a="none",allowedCookies:r,allowedMethods:n="GET_HEAD",cachedMethods:i="GET_HEAD",compress:s=!0,forwardQueryString:o=!0,forwardHeaders:c=[]}=e;return{MinTTL:t.min,MaxTTL:t.max,DefaultTTL:t.default,Compress:s,AllowedMethods:re.Config.allowedMethods(n),CachedMethods:re.Config.cachedMethods(i),ForwardedValues:{QueryString:o,Headers:c,Cookies:re.Config.cookies(a,r)}}}};static applyConfig(e,t){let a=e.Properties.DistributionConfig.DefaultCacheBehavior;if(t.ttl)a.MinTTL=t.ttl.min,a.MaxTTL=t.ttl.max,a.DefaultTTL=t.ttl.default;if(t.compress!==void 0)a.Compress=t.compress;if(t.allowedMethods)a.AllowedMethods=re.Config.allowedMethods(t.allowedMethods);if(t.cachedMethods)a.CachedMethods=re.Config.cachedMethods(t.cachedMethods);if(t.cookies){if(!a.ForwardedValues)a.ForwardedValues={QueryString:!0};a.ForwardedValues.Cookies=re.Config.cookies(t.cookies,t.allowedCookies)}return e}}class q{static createHostedZone(e){let{domain:t,slug:a,environment:r,comment:n}=e,i=A({slug:a,environment:r,resourceType:"hostedzone"}),s=f(`${i}-${t.replace(/\./g,"")}`);return{zone:{Type:"AWS::Route53::HostedZone",Properties:{Name:t,HostedZoneConfig:{Comment:n||`Hosted zone for ${t}`}}},logicalId:s}}static createRecord(e){let{hostedZoneId:t,hostedZoneName:a,name:r,type:n,ttl:i,values:s,aliasTarget:o}=e,c=f(`record-${r.replace(/\./g,"")}-${n}`),l={Type:"AWS::Route53::RecordSet",Properties:{Name:r,Type:n}};if(t)l.Properties.HostedZoneId=t;else if(a)l.Properties.HostedZoneName=a;if(o)l.Properties.AliasTarget={DNSName:o.dnsName,HostedZoneId:o.hostedZoneId,EvaluateTargetHealth:o.evaluateTargetHealth??!1};else l.Properties.TTL=i||300,l.Properties.ResourceRecords=s||[];return{record:l,logicalId:c}}static createCloudFrontAlias(e,t,a){return q.createRecord({hostedZoneId:a,name:e,type:"A",aliasTarget:{dnsName:t,hostedZoneId:"Z2FDTNDATAQYW2",evaluateTargetHealth:!1}})}static createAlbAlias(e,t,a,r){return q.createRecord({hostedZoneId:r,name:e,type:"A",aliasTarget:{dnsName:t,hostedZoneId:a,evaluateTargetHealth:!0}})}static createCname(e,t,a,r=300){return q.createRecord({hostedZoneId:a,name:e,type:"CNAME",ttl:r,values:[t]})}static createWwwRedirect(e,t){return q.createRecord({hostedZoneId:t,name:`www.${e}`,type:"CNAME",ttl:300,values:[e]})}static createMxRecords(e,t,a,r=300){return q.createRecord({hostedZoneId:a,name:e,type:"MX",ttl:r,values:t.map((n)=>`${n.priority} ${n.server}`)})}static createTxtRecord(e,t,a,r=300){return q.createRecord({hostedZoneId:a,name:e,type:"TXT",ttl:r,values:[`"${t}"`]})}static createSpfRecord(e,t,a){return q.createTxtRecord(e,t,a)}static createDmarcRecord(e,t,a,r){let n=`v=DMARC1; p=${t}; rua=mailto:${a}`;return q.createTxtRecord(`_dmarc.${e}`,n,r)}static createS3WebsiteAlias(e,t,a,r){return q.createRecord({hostedZoneId:r,name:e,type:"A",aliasTarget:{dnsName:t,hostedZoneId:a,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(e,t){return`${e}.s3-website-${t}.amazonaws.com`}static createStoreRecord(e,t,a){return q.createCname(`store.${e}`,t,a)}static createApiRecord(e,t,a){return q.createCname(`api.${e}`,t,a)}static createDocsRecord(e,t,a){return q.createCname(`docs.${e}`,t,a)}static CloudFrontHostedZoneId="Z2FDTNDATAQYW2"}class U{static createCertificate(e){let{domain:t,subdomains:a=[],slug:r,environment:n,validationMethod:i="DNS",hostedZoneId:s}=e,o=A({slug:r,environment:n,resourceType:"acm"}),c=f(`${o}-${t.replace(/\./g,"")}`),l=[t];for(let m of a)if(m==="*")l.push(`*.${t}`);else l.push(`${m}.${t}`);let u={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:t,SubjectAlternativeNames:l,ValidationMethod:i}};if(i==="DNS"&&s)u.Properties.DomainValidationOptions=l.map((m)=>({DomainName:m,HostedZoneId:s}));return{certificate:u,logicalId:c}}static createKmsKey(e){let{description:t,slug:a,environment:r,enableRotation:n=!0,multiRegion:i=!1}=e,s=A({slug:a,environment:r,resourceType:"kms"}),o=f(s),c={Version:"2012-10-17",Statement:[{Sid:"Enable IAM User Permissions",Effect:"Allow",Principal:{AWS:C.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:"*"}]},l={Type:"AWS::KMS::Key",Properties:{Description:t,Enabled:!0,EnableKeyRotation:n,KeyPolicy:c,KeySpec:"SYMMETRIC_DEFAULT",KeyUsage:"ENCRYPT_DECRYPT",MultiRegion:i}},u=f(`${s}-alias`),m={Type:"AWS::KMS::Alias",Properties:{AliasName:`alias/${a}-${r}`,TargetKeyId:C.Ref(o)}};return{key:l,alias:m,logicalId:o,aliasId:u}}static createFirewall(e){let{slug:t,environment:a,scope:r="CLOUDFRONT",defaultAction:n="allow"}=e,i=A({slug:t,environment:a,resourceType:"waf"}),s=f(i);return{webAcl:{Type:"AWS::WAFv2::WebACL",Properties:{Name:i,Scope:r,DefaultAction:n==="allow"?{Allow:{}}:{Block:{}},Description:`WAF for ${t} ${a}`,Rules:[],VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i}-metric`}}},logicalId:s}}static setRateLimit(e,t){if(!e.Properties.Rules)e.Properties.Rules=[];return e.Properties.Rules.push({Name:t.name,Priority:t.priority,Statement:{RateBasedStatement:{Limit:t.requestsPerWindow,AggregateKeyType:t.aggregateKeyType||"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${t.name}-metric`}}),e}static blockCountries(e,t){if(!e.Properties.Rules)e.Properties.Rules=[];return e.Properties.Rules.push({Name:t.name,Priority:t.priority,Statement:{GeoMatchStatement:{CountryCodes:t.countryCodes}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${t.name}-metric`}}),e}static blockIpAddresses(e,t,a,r){let n=A({slug:a,environment:r,resourceType:"ipset"}),i=f(`${n}-${t.name}`),s={Type:"AWS::WAFv2::IPSet",Properties:{Name:`${n}-${t.name}`,Scope:e.Properties.Scope,IPAddressVersion:t.ipVersion||"IPV4",Addresses:t.ipAddresses,Description:`Blocked IPs for ${t.name}`}};if(!e.Properties.Rules)e.Properties.Rules=[];return e.Properties.Rules.push({Name:t.name,Priority:t.priority,Statement:{IPSetReferenceStatement:{Arn:C.GetAtt(i,"Arn")}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${t.name}-metric`}}),{webAcl:e,ipSet:s,ipSetLogicalId:i}}static addManagedRules(e,t){if(!e.Properties.Rules)e.Properties.Rules=[];let a={ManagedRuleGroupStatement:{VendorName:t.vendorName,Name:t.ruleName}};if(t.excludedRules&&t.excludedRules.length>0)a.ManagedRuleGroupStatement.ExcludedRules=t.excludedRules.map((r)=>({Name:r}));return e.Properties.Rules.push({Name:t.name,Priority:t.priority,Statement:a,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${t.name}-metric`}}),e}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(e,t){if(!e.Properties.Rules)e.Properties.Rules=[];let a=t.paths.map((r)=>({SearchString:r,FieldToMatch:{UriPath:{}},TextTransformation:[{Priority:0,Type:"LOWERCASE"}],PositionalConstraint:"STARTS_WITH"}));return e.Properties.Rules.push({Name:t.name,Priority:t.priority,Statement:{RateBasedStatement:{Limit:t.requestsPerWindow,AggregateKeyType:t.aggregateKeyType||"IP",ScopeDownStatement:{OrStatement:{Statements:a.map((r)=>({ByteMatchStatement:r}))}}}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${t.name}-metric`}}),e}static setHeaderRateLimit(e,t){if(!e.Properties.Rules)e.Properties.Rules=[];let a={RateBasedStatement:{Limit:t.requestsPerWindow,AggregateKeyType:"CUSTOM_KEYS",CustomKeys:[{Header:{Name:t.headerName,TextTransformations:[{Priority:0,Type:"NONE"}]}}]}};if(t.headerValue)a.RateBasedStatement.ScopeDownStatement={ByteMatchStatement:{SearchString:t.headerValue,FieldToMatch:{SingleHeader:{Name:t.headerName}},TextTransformation:[{Priority:0,Type:"NONE"}],PositionalConstraint:"EXACTLY"}};return e.Properties.Rules.push({Name:t.name,Priority:t.priority,Statement:a,Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${t.name}-metric`}}),e}static protectLoginEndpoint(e,t){let{loginPaths:a,priority:r,requestsPerMinute:n=10}=t;return U.setPathRateLimit(e,{name:"LoginRateLimit",priority:r,requestsPerWindow:n*5,paths:a}),e}static protectApiEndpoints(e,t){let{apiPaths:a,priority:r,requestsPerMinute:n=100}=t;return U.setPathRateLimit(e,{name:"ApiRateLimit",priority:r,requestsPerWindow:n*5,paths:a}),e}static createProtectedFirewall(e){let{slug:t,environment:a,scope:r="CLOUDFRONT",enableBotControl:n=!1,enableRateLimiting:i=!0,rateLimitPerMinute:s=2000}=e,{webAcl:o,logicalId:c}=U.createFirewall({slug:t,environment:a,scope:r,defaultAction:"allow"}),l=0;if(o=U.addManagedRules(o,{name:"AWSIPReputationList",priority:l++,...U.ManagedRuleGroups.AmazonIpReputation}),o=U.addManagedRules(o,{name:"AWSAnonymousIPList",priority:l++,...U.ManagedRuleGroups.AnonymousIpList}),o=U.addManagedRules(o,{name:"AWSCoreRuleSet",priority:l++,...U.ManagedRuleGroups.CoreRuleSet}),o=U.addManagedRules(o,{name:"AWSKnownBadInputs",priority:l++,...U.ManagedRuleGroups.KnownBadInputs}),o=U.addManagedRules(o,{name:"AWSSQLi",priority:l++,...U.ManagedRuleGroups.SqlDatabase}),n)o=U.addManagedRules(o,{name:"AWSBotControl",priority:l++,...U.ManagedRuleGroups.BotControl});if(i)o=U.setRateLimit(o,{name:"GlobalRateLimit",priority:l++,requestsPerWindow:s*5});return{webAcl:o,logicalId:c}}static RateLimitPresets={STANDARD:2000,HIGH_TRAFFIC:1e4,STRICT:100,LOGIN:10,API:100}}class k{static createServer(e){let{slug:t,environment:a,instanceType:r="t3.micro",imageId:n="ami-0f3caa1cf4417e51b",keyName:i,securityGroupIds:s,subnetId:o,userData:c,volumeSize:l=20,volumeType:u="gp3",encrypted:m=!0}=e,p=A({slug:t,environment:a,resourceType:"ec2"}),g=f(p),h={Type:"AWS::EC2::Instance",Properties:{ImageId:n,InstanceType:r,Tags:[{Key:"Name",Value:p},{Key:"Environment",Value:a}]}};if(i)h.Properties.KeyName=i;if(s)h.Properties.SecurityGroupIds=s;if(o)h.Properties.SubnetId=o;if(c)h.Properties.UserData=C.Base64(c);return h.Properties.BlockDeviceMappings=[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:l,VolumeType:u,Encrypted:m,DeleteOnTermination:!0}}],{instance:h,logicalId:g}}static createSecurityGroup(e){let{slug:t,environment:a,vpcId:r,description:n,ingress:i=[],egress:s=[]}=e,o=A({slug:t,environment:a,resourceType:"sg"}),c=f(o),l={Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:n||`Security group for ${t} ${a}`,Tags:[{Key:"Name",Value:o},{Key:"Environment",Value:a}]}};if(r)l.Properties.VpcId=r;if(i.length>0)l.Properties.SecurityGroupIngress=i.map((u)=>({IpProtocol:u.protocol,FromPort:u.fromPort,ToPort:u.toPort,CidrIp:u.cidr,SourceSecurityGroupId:u.sourceSecurityGroupId}));if(s.length>0)l.Properties.SecurityGroupEgress=s.map((u)=>({IpProtocol:u.protocol,FromPort:u.fromPort,ToPort:u.toPort,CidrIp:u.cidr,DestinationSecurityGroupId:u.sourceSecurityGroupId}));return{securityGroup:l,logicalId:c}}static createWebServerSecurityGroup(e,t,a){return k.createSecurityGroup({slug:e,environment:t,vpcId:a,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(e){let{slug:t,environment:a,scheme:r="internet-facing",subnets:n,securityGroups:i,type:s="application"}=e,o=A({slug:t,environment:a,resourceType:"alb"}),c=f(o),l={Type:"AWS::ElasticLoadBalancingV2::LoadBalancer",Properties:{Name:o,Scheme:r,Type:s,Subnets:n,Tags:[{Key:"Name",Value:o},{Key:"Environment",Value:a}]}};if(i)l.Properties.SecurityGroups=i;return{loadBalancer:l,logicalId:c}}static createTargetGroup(e){let{slug:t,environment:a,port:r,protocol:n="HTTP",vpcId:i,targetType:s="ip",healthCheckPath:o="/",healthCheckInterval:c=30,healthCheckTimeout:l=5,healthyThreshold:u=2,unhealthyThreshold:m=3}=e,p=A({slug:t,environment:a,resourceType:"tg"}),g=f(p);return{targetGroup:{Type:"AWS::ElasticLoadBalancingV2::TargetGroup",Properties:{Name:p,Port:r,Protocol:n,VpcId:i,TargetType:s,HealthCheckEnabled:!0,HealthCheckProtocol:n,HealthCheckPath:o,HealthCheckIntervalSeconds:c,HealthCheckTimeoutSeconds:l,HealthyThresholdCount:u,UnhealthyThresholdCount:m,Tags:[{Key:"Name",Value:p},{Key:"Environment",Value:a}]}},logicalId:g}}static createListener(e,t){let{port:a,protocol:r="HTTP",certificateArn:n,defaultTargetGroupArn:i}=t,s=f(`listener-${e}-${a}`),o={Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:C.Ref(e),Port:a,Protocol:r,DefaultActions:[{Type:"forward",TargetGroupArn:i}]}};if(r==="HTTPS"&&n)o.Properties.Certificates=[{CertificateArn:n}],o.Properties.SslPolicy="ELBSecurityPolicy-TLS13-1-2-2021-06";return{listener:o,logicalId:s}}static createEcsCluster(e,t){let a=A({slug:e,environment:t,resourceType:"ecs-cluster"}),r=f(a);return{cluster:{Type:"AWS::ECS::Cluster",Properties:{ClusterName:a,Tags:[{Key:"Name",Value:a},{Key:"Environment",Value:t}]}},logicalId:r}}static createFargateService(e){let{slug:t,environment:a,image:r,cpu:n="256",memory:i="512",desiredCount:s=1,containerPort:o=8080,environmentVariables:c={},secrets:l=[],healthCheck:u,logGroup:m,subnets:p,securityGroups:g,targetGroupArn:h}=e,{cluster:y,logicalId:b}=k.createEcsCluster(t,a),T=A({slug:t,environment:a,resourceType:"fargate"}),w=f(`${T}-execution-role`),S={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"]}},E=f(`${T}-task-role`),v={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]}}},P=f(`${T}-task`),N={Type:"AWS::ECS::TaskDefinition",Properties:{Family:T,TaskRoleArn:C.GetAtt(E,"Arn"),ExecutionRoleArn:C.GetAtt(w,"Arn"),NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:n,Memory:i,ContainerDefinitions:[{Name:t,Image:r,Essential:!0,PortMappings:[{ContainerPort:o,Protocol:"tcp"}],Environment:Object.entries(c).map(([M,O])=>({Name:M,Value:O})),Secrets:l.map((M)=>({Name:M.name,ValueFrom:M.valueFrom}))}],Tags:[{Key:"Name",Value:T},{Key:"Environment",Value:a}]}};if(u)N.Properties.ContainerDefinitions[0].HealthCheck={Command:u.command,Interval:u.interval||30,Timeout:u.timeout||5,Retries:u.retries||3,StartPeriod:60};if(m)N.Properties.ContainerDefinitions[0].LogConfiguration={LogDriver:"awslogs",Options:{"awslogs-group":m,"awslogs-region":C.Ref("AWS::Region"),"awslogs-stream-prefix":t}};let I=f(`${T}-service`),D={Type:"AWS::ECS::Service",Properties:{ServiceName:T,Cluster:C.Ref(b),TaskDefinition:C.Ref(P),DesiredCount:s,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{Subnets:p,SecurityGroups:g,AssignPublicIp:"ENABLED"}},Tags:[{Key:"Name",Value:T},{Key:"Environment",Value:a}]}};if(h)D.Properties.LoadBalancers=[{TargetGroupArn:h,ContainerName:t,ContainerPort:o}];return{cluster:y,taskDefinition:N,service:D,taskRole:v,executionRole:S,clusterLogicalId:b,taskDefinitionLogicalId:P,serviceLogicalId:I,taskRoleLogicalId:E,executionRoleLogicalId:w}}static createLambdaFunction(e){let{slug:t,environment:a,runtime:r,handler:n,code:i,timeout:s=30,memorySize:o=128,environmentVariables:c={},vpcConfig:l}=e,u=A({slug:t,environment:a,resourceType:"lambda"}),m=f(u),p=f(`${u}-role`),g={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(l)g.Properties.ManagedPolicyArns.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");let h={Type:"AWS::Lambda::Function",Properties:{FunctionName:u,Runtime:r,Role:C.GetAtt(p,"Arn"),Handler:n,Code:{...i.s3Bucket&&{S3Bucket:i.s3Bucket},...i.s3Key&&{S3Key:i.s3Key},...i.zipFile&&{ZipFile:i.zipFile}},Timeout:s,MemorySize:o,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:a}]}};if(Object.keys(c).length>0)h.Properties.Environment={Variables:c};if(l)h.Properties.VpcConfig={SecurityGroupIds:l.securityGroupIds,SubnetIds:l.subnetIds};return{lambdaFunction:h,role:g,logicalId:m,roleLogicalId:p}}static generateNodeServerUserData(e={}){let{nodeVersion:t="20",appRepo:a,environment:r={}}=e,n=Object.entries(r).map(([i,s])=>`echo "export ${i}='${s}'" >> /etc/environment`).join(`
213
213
  `);return`#!/bin/bash
214
214
  # Update system
215
215
  yum update -y
@@ -310,7 +310,7 @@ systemctl enable caddy
310
310
  systemctl start caddy
311
311
 
312
312
  echo "Bun server setup complete!"
313
- `}static createLaunchConfiguration(e){let{slug:t,environment:a,imageId:r,instanceType:n,keyName:i,securityGroups:s,userData:o,volumeSize:c=20,volumeType:l="gp3",encrypted:u=!0,iamInstanceProfile:m}=e,p=A({slug:t,environment:a,resourceType:"launch-config"}),g=f(p),h={Type:"AWS::AutoScaling::LaunchConfiguration",Properties:{ImageId:r,InstanceType:n,BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:c,VolumeType:l,Encrypted:u,DeleteOnTermination:!0}}]}};if(i)h.Properties.KeyName=i;if(s)h.Properties.SecurityGroups=s;if(o)h.Properties.UserData=C.Base64(o);if(m)h.Properties.IamInstanceProfile=m;return{launchConfiguration:h,logicalId:g}}static createAutoScalingGroup(e){let{slug:t,environment:a,launchConfigurationName:r,minSize:n,maxSize:i,desiredCapacity:s,vpcZoneIdentifier:o,targetGroupArns:c,healthCheckType:l="EC2",healthCheckGracePeriod:u=300,cooldown:m=300,tags:p={}}=e,g=A({slug:t,environment:a,resourceType:"asg"}),h=f(g),y={Type:"AWS::AutoScaling::AutoScalingGroup",Properties:{AutoScalingGroupName:g,LaunchConfigurationName:r,MinSize:n,MaxSize:i,HealthCheckType:l,HealthCheckGracePeriod:u,Cooldown:m,Tags:[{Key:"Name",Value:g,PropagateAtLaunch:!0},{Key:"Environment",Value:a,PropagateAtLaunch:!0},...Object.entries(p).map(([b,T])=>({Key:b,Value:T,PropagateAtLaunch:!0}))]}};if(s!==void 0)y.Properties.DesiredCapacity=s;if(o)y.Properties.VPCZoneIdentifier=o;if(c)y.Properties.TargetGroupARNs=c;return y.UpdatePolicy={AutoScalingRollingUpdate:{MaxBatchSize:1,MinInstancesInService:Math.max(0,n-1),PauseTime:"PT5M",WaitOnResourceSignals:!1}},{autoScalingGroup:y,logicalId:h}}static createScalingPolicy(e){let{slug:t,environment:a,autoScalingGroupName:r,policyType:n="TargetTrackingScaling",targetValue:i=70,predefinedMetricType:s="ASGAverageCPUUtilization"}=e,o=A({slug:t,environment:a,resourceType:"scaling-policy"}),c=f(o),l={Type:"AWS::AutoScaling::ScalingPolicy",Properties:{AutoScalingGroupName:r,PolicyType:n}};if(n==="TargetTrackingScaling")l.Properties.TargetTrackingConfiguration={PredefinedMetricSpecification:{PredefinedMetricType:s},TargetValue:i};return{scalingPolicy:l,logicalId:c}}static AutoScaling={smallWebServer:(e,t,a,r,n)=>k.createAutoScalingGroup({slug:e,environment:t,launchConfigurationName:a,minSize:2,maxSize:4,desiredCapacity:2,vpcZoneIdentifier:r,targetGroupArns:n,healthCheckType:n?"ELB":"EC2",healthCheckGracePeriod:300}),mediumWebServer:(e,t,a,r,n)=>k.createAutoScalingGroup({slug:e,environment:t,launchConfigurationName:a,minSize:3,maxSize:10,desiredCapacity:3,vpcZoneIdentifier:r,targetGroupArns:n,healthCheckType:n?"ELB":"EC2",healthCheckGracePeriod:300}),largeWebServer:(e,t,a,r,n)=>k.createAutoScalingGroup({slug:e,environment:t,launchConfigurationName:a,minSize:5,maxSize:20,desiredCapacity:5,vpcZoneIdentifier:r,targetGroupArns:n,healthCheckType:n?"ELB":"EC2",healthCheckGracePeriod:300}),cpuScaling:(e,t,a,r=70)=>k.createScalingPolicy({slug:e,environment:t,autoScalingGroupName:a,policyType:"TargetTrackingScaling",predefinedMetricType:"ASGAverageCPUUtilization",targetValue:r}),requestCountScaling:(e,t,a,r=1000)=>k.createScalingPolicy({slug:e,environment:t,autoScalingGroupName:a,policyType:"TargetTrackingScaling",predefinedMetricType:"ALBRequestCountPerTarget",targetValue:r})};static Secrets={fromSecretsManager:(e)=>Object.entries(e).map(([t,a])=>({name:t,valueFrom:a})),fromJsonSecret:(e,t)=>`${e}:${t}::`,fromSecretVersion:(e,t)=>`${e}::${t}:`,fromSecretVersionStage:(e,t)=>`${e}:::${t}`,createAccessPolicy:(e)=>({PolicyName:"SecretsManagerAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],Resource:e}]}}),createKmsPolicy:(e)=>({PolicyName:"KMSDecryptAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["kms:Decrypt"],Resource:e}]}}),buildSecretArn:(e)=>`arn:aws:secretsmanager:${e.region}:${e.accountId}:secret:${e.secretName}`,buildSecretArnPattern:(e)=>{let t=e.region||"*",a=e.accountId||"*";return`arn:aws:secretsmanager:${t}:${a}:secret:${e.secretNamePrefix}*`},commonAppSecrets:(e)=>({DATABASE_URL:`${e}/database-url`,DATABASE_PASSWORD:`${e}/database-password`,REDIS_URL:`${e}/redis-url`,REDIS_PASSWORD:`${e}/redis-password`,API_KEY:`${e}/api-key`,JWT_SECRET:`${e}/jwt-secret`,ENCRYPTION_KEY:`${e}/encryption-key`,AWS_ACCESS_KEY_ID:`${e}/aws-access-key-id`,AWS_SECRET_ACCESS_KEY:`${e}/aws-secret-access-key`,MAIL_PASSWORD:`${e}/mail-password`,STRIPE_SECRET_KEY:`${e}/stripe-secret-key`,STRIPE_WEBHOOK_SECRET:`${e}/stripe-webhook-secret`})};static createFargateServiceWithSecrets(e){let{secretArns:t=[],kmsKeyArns:a=[],...r}=e,n=k.createFargateService(r);if(t.length>0){if(!n.executionRole.Properties.Policies)n.executionRole.Properties.Policies=[];if(n.executionRole.Properties.Policies.push(k.Secrets.createAccessPolicy(t)),a.length>0)n.executionRole.Properties.Policies.push(k.Secrets.createKmsPolicy(a))}return n}static generateSecretReferences(e){return e.secrets.map((t)=>{let a=`arn:aws:secretsmanager:${e.region}:${e.accountId}:secret:${e.secretPrefix}/${t}`;return{name:t.toUpperCase().replace(/-/g,"_"),valueFrom:a}})}static EnvSecrets={database:(e)=>[{name:"DB_HOST",valueFrom:`${e}:host::`},{name:"DB_PORT",valueFrom:`${e}:port::`},{name:"DB_USERNAME",valueFrom:`${e}:username::`},{name:"DB_PASSWORD",valueFrom:`${e}:password::`},{name:"DB_NAME",valueFrom:`${e}:dbname::`}],redis:(e)=>[{name:"REDIS_HOST",valueFrom:`${e}:host::`},{name:"REDIS_PORT",valueFrom:`${e}:port::`},{name:"REDIS_PASSWORD",valueFrom:`${e}:password::`}],apiCredentials:(e)=>[{name:"API_KEY",valueFrom:`${e}:apiKey::`},{name:"API_SECRET",valueFrom:`${e}:apiSecret::`}],mail:(e)=>[{name:"MAIL_HOST",valueFrom:`${e}:host::`},{name:"MAIL_PORT",valueFrom:`${e}:port::`},{name:"MAIL_USERNAME",valueFrom:`${e}:username::`},{name:"MAIL_PASSWORD",valueFrom:`${e}:password::`}],awsCredentials:(e)=>[{name:"AWS_ACCESS_KEY_ID",valueFrom:`${e}:accessKeyId::`},{name:"AWS_SECRET_ACCESS_KEY",valueFrom:`${e}:secretAccessKey::`}]};static createJumpBox(e){let{slug:t,environment:a,vpcId:r,subnetId:n,keyName:i,instanceType:s="t3.micro",imageId:o="ami-0f3caa1cf4417e51b",allowedCidrs:c=["0.0.0.0/0"],mountEfs:l}=e,u=A({slug:t,environment:a,resourceType:"jumpbox"}),m=f(`${u}-sg`),p={Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:`${u}-sg`,GroupDescription:`Security group for ${u} JumpBox SSH access`,VpcId:r,SecurityGroupIngress:c.map((v)=>({IpProtocol:"tcp",FromPort:22,ToPort:22,CidrIp:v,Description:`SSH access from ${v}`})),SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound traffic"}],Tags:[{Key:"Name",Value:`${u}-sg`},{Key:"Environment",Value:a}]}},g=f(`${u}-role`),h={Type:"AWS::IAM::Role",Properties:{RoleName:`${u}-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:l?[{PolicyName:"EFSAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess"],Resource:"*"}]}}]:void 0}},y=f(`${u}-profile`),b={Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:`${u}-profile`,Roles:[C.Ref(g)]}},T=`#!/bin/bash
313
+ `}static createLaunchConfiguration(e){let{slug:t,environment:a,imageId:r,instanceType:n,keyName:i,securityGroups:s,userData:o,volumeSize:c=20,volumeType:l="gp3",encrypted:u=!0,iamInstanceProfile:m}=e,p=A({slug:t,environment:a,resourceType:"launch-config"}),g=f(p),h={Type:"AWS::AutoScaling::LaunchConfiguration",Properties:{ImageId:r,InstanceType:n,BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:c,VolumeType:l,Encrypted:u,DeleteOnTermination:!0}}]}};if(i)h.Properties.KeyName=i;if(s)h.Properties.SecurityGroups=s;if(o)h.Properties.UserData=C.Base64(o);if(m)h.Properties.IamInstanceProfile=m;return{launchConfiguration:h,logicalId:g}}static createAutoScalingGroup(e){let{slug:t,environment:a,launchConfigurationName:r,minSize:n,maxSize:i,desiredCapacity:s,vpcZoneIdentifier:o,targetGroupArns:c,healthCheckType:l="EC2",healthCheckGracePeriod:u=300,cooldown:m=300,tags:p={}}=e,g=A({slug:t,environment:a,resourceType:"asg"}),h=f(g),y={Type:"AWS::AutoScaling::AutoScalingGroup",Properties:{AutoScalingGroupName:g,LaunchConfigurationName:r,MinSize:n,MaxSize:i,HealthCheckType:l,HealthCheckGracePeriod:u,Cooldown:m,Tags:[{Key:"Name",Value:g,PropagateAtLaunch:!0},{Key:"Environment",Value:a,PropagateAtLaunch:!0},...Object.entries(p).map(([b,T])=>({Key:b,Value:T,PropagateAtLaunch:!0}))]}};if(s!==void 0)y.Properties.DesiredCapacity=s;if(o)y.Properties.VPCZoneIdentifier=o;if(c)y.Properties.TargetGroupARNs=c;return y.UpdatePolicy={AutoScalingRollingUpdate:{MaxBatchSize:1,MinInstancesInService:Math.max(0,n-1),PauseTime:"PT5M",WaitOnResourceSignals:!1}},{autoScalingGroup:y,logicalId:h}}static createScalingPolicy(e){let{slug:t,environment:a,autoScalingGroupName:r,policyType:n="TargetTrackingScaling",targetValue:i=70,predefinedMetricType:s="ASGAverageCPUUtilization"}=e,o=A({slug:t,environment:a,resourceType:"scaling-policy"}),c=f(o),l={Type:"AWS::AutoScaling::ScalingPolicy",Properties:{AutoScalingGroupName:r,PolicyType:n}};if(n==="TargetTrackingScaling")l.Properties.TargetTrackingConfiguration={PredefinedMetricSpecification:{PredefinedMetricType:s},TargetValue:i};return{scalingPolicy:l,logicalId:c}}static AutoScaling={smallWebServer:(e,t,a,r,n)=>{return k.createAutoScalingGroup({slug:e,environment:t,launchConfigurationName:a,minSize:2,maxSize:4,desiredCapacity:2,vpcZoneIdentifier:r,targetGroupArns:n,healthCheckType:n?"ELB":"EC2",healthCheckGracePeriod:300})},mediumWebServer:(e,t,a,r,n)=>{return k.createAutoScalingGroup({slug:e,environment:t,launchConfigurationName:a,minSize:3,maxSize:10,desiredCapacity:3,vpcZoneIdentifier:r,targetGroupArns:n,healthCheckType:n?"ELB":"EC2",healthCheckGracePeriod:300})},largeWebServer:(e,t,a,r,n)=>{return k.createAutoScalingGroup({slug:e,environment:t,launchConfigurationName:a,minSize:5,maxSize:20,desiredCapacity:5,vpcZoneIdentifier:r,targetGroupArns:n,healthCheckType:n?"ELB":"EC2",healthCheckGracePeriod:300})},cpuScaling:(e,t,a,r=70)=>{return k.createScalingPolicy({slug:e,environment:t,autoScalingGroupName:a,policyType:"TargetTrackingScaling",predefinedMetricType:"ASGAverageCPUUtilization",targetValue:r})},requestCountScaling:(e,t,a,r=1000)=>{return k.createScalingPolicy({slug:e,environment:t,autoScalingGroupName:a,policyType:"TargetTrackingScaling",predefinedMetricType:"ALBRequestCountPerTarget",targetValue:r})}};static Secrets={fromSecretsManager:(e)=>{return Object.entries(e).map(([t,a])=>({name:t,valueFrom:a}))},fromJsonSecret:(e,t)=>{return`${e}:${t}::`},fromSecretVersion:(e,t)=>{return`${e}::${t}:`},fromSecretVersionStage:(e,t)=>{return`${e}:::${t}`},createAccessPolicy:(e)=>({PolicyName:"SecretsManagerAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],Resource:e}]}}),createKmsPolicy:(e)=>({PolicyName:"KMSDecryptAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["kms:Decrypt"],Resource:e}]}}),buildSecretArn:(e)=>{return`arn:aws:secretsmanager:${e.region}:${e.accountId}:secret:${e.secretName}`},buildSecretArnPattern:(e)=>{let t=e.region||"*",a=e.accountId||"*";return`arn:aws:secretsmanager:${t}:${a}:secret:${e.secretNamePrefix}*`},commonAppSecrets:(e)=>({DATABASE_URL:`${e}/database-url`,DATABASE_PASSWORD:`${e}/database-password`,REDIS_URL:`${e}/redis-url`,REDIS_PASSWORD:`${e}/redis-password`,API_KEY:`${e}/api-key`,JWT_SECRET:`${e}/jwt-secret`,ENCRYPTION_KEY:`${e}/encryption-key`,AWS_ACCESS_KEY_ID:`${e}/aws-access-key-id`,AWS_SECRET_ACCESS_KEY:`${e}/aws-secret-access-key`,MAIL_PASSWORD:`${e}/mail-password`,STRIPE_SECRET_KEY:`${e}/stripe-secret-key`,STRIPE_WEBHOOK_SECRET:`${e}/stripe-webhook-secret`})};static createFargateServiceWithSecrets(e){let{secretArns:t=[],kmsKeyArns:a=[],...r}=e,n=k.createFargateService(r);if(t.length>0){if(!n.executionRole.Properties.Policies)n.executionRole.Properties.Policies=[];if(n.executionRole.Properties.Policies.push(k.Secrets.createAccessPolicy(t)),a.length>0)n.executionRole.Properties.Policies.push(k.Secrets.createKmsPolicy(a))}return n}static generateSecretReferences(e){return e.secrets.map((t)=>{let a=`arn:aws:secretsmanager:${e.region}:${e.accountId}:secret:${e.secretPrefix}/${t}`;return{name:t.toUpperCase().replace(/-/g,"_"),valueFrom:a}})}static EnvSecrets={database:(e)=>[{name:"DB_HOST",valueFrom:`${e}:host::`},{name:"DB_PORT",valueFrom:`${e}:port::`},{name:"DB_USERNAME",valueFrom:`${e}:username::`},{name:"DB_PASSWORD",valueFrom:`${e}:password::`},{name:"DB_NAME",valueFrom:`${e}:dbname::`}],redis:(e)=>[{name:"REDIS_HOST",valueFrom:`${e}:host::`},{name:"REDIS_PORT",valueFrom:`${e}:port::`},{name:"REDIS_PASSWORD",valueFrom:`${e}:password::`}],apiCredentials:(e)=>[{name:"API_KEY",valueFrom:`${e}:apiKey::`},{name:"API_SECRET",valueFrom:`${e}:apiSecret::`}],mail:(e)=>[{name:"MAIL_HOST",valueFrom:`${e}:host::`},{name:"MAIL_PORT",valueFrom:`${e}:port::`},{name:"MAIL_USERNAME",valueFrom:`${e}:username::`},{name:"MAIL_PASSWORD",valueFrom:`${e}:password::`}],awsCredentials:(e)=>[{name:"AWS_ACCESS_KEY_ID",valueFrom:`${e}:accessKeyId::`},{name:"AWS_SECRET_ACCESS_KEY",valueFrom:`${e}:secretAccessKey::`}]};static createJumpBox(e){let{slug:t,environment:a,vpcId:r,subnetId:n,keyName:i,instanceType:s="t3.micro",imageId:o="ami-0f3caa1cf4417e51b",allowedCidrs:c=["0.0.0.0/0"],mountEfs:l}=e,u=A({slug:t,environment:a,resourceType:"jumpbox"}),m=f(`${u}-sg`),p={Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:`${u}-sg`,GroupDescription:`Security group for ${u} JumpBox SSH access`,VpcId:r,SecurityGroupIngress:c.map((v)=>({IpProtocol:"tcp",FromPort:22,ToPort:22,CidrIp:v,Description:`SSH access from ${v}`})),SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound traffic"}],Tags:[{Key:"Name",Value:`${u}-sg`},{Key:"Environment",Value:a}]}},g=f(`${u}-role`),h={Type:"AWS::IAM::Role",Properties:{RoleName:`${u}-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:l?[{PolicyName:"EFSAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess"],Resource:"*"}]}}]:void 0}},y=f(`${u}-profile`),b={Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:`${u}-profile`,Roles:[C.Ref(g)]}},T=`#!/bin/bash
314
314
  yum update -y
315
315
  yum install -y amazon-efs-utils nfs-utils jq curl wget htop
316
316
  `;if(l){let v=l.mountPath||"/mnt/efs";T+=`
@@ -318,7 +318,7 @@ yum install -y amazon-efs-utils nfs-utils jq curl wget htop
318
318
  mkdir -p ${v}
319
319
  mount -t efs ${l.fileSystemId}:/ ${v}
320
320
  echo "${l.fileSystemId}:/ ${v} efs defaults,_netdev 0 0" >> /etc/fstab
321
- `}let w=f(u),S={Type:"AWS::EC2::Instance",DependsOn:[y],Properties:{ImageId:o,InstanceType:s,KeyName:i,SubnetId:n,SecurityGroupIds:[C.Ref(m)],IamInstanceProfile:C.Ref(y),UserData:C.Base64(T),BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:20,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0}}],Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:a},{Key:"Purpose",Value:"JumpBox/Bastion"}]}},E={[m]:p,[g]:h,[y]:b,[w]:S};return{instance:S,securityGroup:p,instanceProfile:b,instanceRole:h,instanceLogicalId:w,securityGroupLogicalId:m,instanceProfileLogicalId:y,instanceRoleLogicalId:g,resources:E}}static JumpBox={withEfsMount:(e)=>k.createJumpBox({slug:e.slug,environment:e.environment,vpcId:e.vpcId,subnetId:e.subnetId,keyName:e.keyName,allowedCidrs:e.allowedCidrs,mountEfs:{fileSystemId:e.fileSystemId,mountPath:e.mountPath||"/mnt/efs"}}),minimal:(e)=>k.createJumpBox({slug:e.slug,environment:e.environment,vpcId:e.vpcId,subnetId:e.subnetId,keyName:e.keyName,instanceType:"t3.nano",allowedCidrs:e.allowedCidrs}),withDatabaseTools:(e)=>{let t=k.createJumpBox({slug:e.slug,environment:e.environment,vpcId:e.vpcId,subnetId:e.subnetId,keyName:e.keyName,allowedCidrs:e.allowedCidrs}),a=`#!/bin/bash
321
+ `}let w=f(u),S={Type:"AWS::EC2::Instance",DependsOn:[y],Properties:{ImageId:o,InstanceType:s,KeyName:i,SubnetId:n,SecurityGroupIds:[C.Ref(m)],IamInstanceProfile:C.Ref(y),UserData:C.Base64(T),BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:20,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0}}],Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:a},{Key:"Purpose",Value:"JumpBox/Bastion"}]}},E={[m]:p,[g]:h,[y]:b,[w]:S};return{instance:S,securityGroup:p,instanceProfile:b,instanceRole:h,instanceLogicalId:w,securityGroupLogicalId:m,instanceProfileLogicalId:y,instanceRoleLogicalId:g,resources:E}}static JumpBox={withEfsMount:(e)=>{return k.createJumpBox({slug:e.slug,environment:e.environment,vpcId:e.vpcId,subnetId:e.subnetId,keyName:e.keyName,allowedCidrs:e.allowedCidrs,mountEfs:{fileSystemId:e.fileSystemId,mountPath:e.mountPath||"/mnt/efs"}})},minimal:(e)=>{return k.createJumpBox({slug:e.slug,environment:e.environment,vpcId:e.vpcId,subnetId:e.subnetId,keyName:e.keyName,instanceType:"t3.nano",allowedCidrs:e.allowedCidrs})},withDatabaseTools:(e)=>{let t=k.createJumpBox({slug:e.slug,environment:e.environment,vpcId:e.vpcId,subnetId:e.subnetId,keyName:e.keyName,allowedCidrs:e.allowedCidrs}),a=`#!/bin/bash
322
322
  yum update -y
323
323
  yum install -y amazon-efs-utils nfs-utils jq curl wget htop
324
324
 
@@ -346,7 +346,7 @@ yum install -y mysql
346
346
  yum install -y redis
347
347
 
348
348
  echo "Database tools installed!"
349
- `),t},commonCidrs:{any:["0.0.0.0/0"],privateOnly:["10.0.0.0/8","172.16.0.0/12","192.168.0.0/16"]}};static InstanceSize={toInstanceType:(e,t="t3")=>`${t}.${e}`,specs:{nano:{vcpu:2,memory:0.5,instanceType:"t3.nano"},micro:{vcpu:2,memory:1,instanceType:"t3.micro"},small:{vcpu:2,memory:2,instanceType:"t3.small"},medium:{vcpu:2,memory:4,instanceType:"t3.medium"},large:{vcpu:2,memory:8,instanceType:"t3.large"},xlarge:{vcpu:4,memory:16,instanceType:"t3.xlarge"},"2xlarge":{vcpu:8,memory:32,instanceType:"t3.2xlarge"}},toFargateSpecs:(e)=>{let t={nano:{cpu:"256",memory:"512"},micro:{cpu:"256",memory:"1024"},small:{cpu:"512",memory:"1024"},medium:{cpu:"1024",memory:"2048"},large:{cpu:"2048",memory:"4096"},xlarge:{cpu:"4096",memory:"8192"},"2xlarge":{cpu:"4096",memory:"16384"}};return t[e]||t.medium},toLambdaMemory:(e)=>({nano:128,micro:256,small:512,medium:1024,large:2048,xlarge:4096,"2xlarge":8192})[e]||1024,presets:{webServer:"t3.small",apiServer:"t3.medium",worker:"t3.medium",database:"r6i.large",cache:"r6i.medium",compute:"c6i.large",general:"m6i.medium"}};static DiskConfig={create:(e)=>{let{size:t,type:a="ssd",encrypted:r=!0,iops:n,throughput:i,deleteOnTermination:s=!0}=e,o={standard:"gp2",ssd:"gp3",premium:"io2",gp2:"gp2",gp3:"gp3",io1:"io1",io2:"io2"}[a]||"gp3",c={VolumeSize:t,VolumeType:o,Encrypted:r,DeleteOnTermination:s};if((o==="io1"||o==="io2"||o==="gp3")&&n)c.Iops=n;if(o==="gp3"&&i)c.Throughput=i;return c},presets:{standard:{VolumeSize:20,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0},large:{VolumeSize:100,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0},highPerformance:{VolumeSize:50,VolumeType:"io2",Iops:3000,Encrypted:!0,DeleteOnTermination:!0},database:{VolumeSize:100,VolumeType:"io2",Iops:1e4,Encrypted:!0,DeleteOnTermination:!1}}};static SpotConfig={create:(e)=>{let{maxPrice:t,spotInstanceType:a="one-time",interruptionBehavior:r="terminate",blockDurationMinutes:n}=e,i={SpotInstanceType:a,InstanceInterruptionBehavior:r};if(t)i.MaxPrice=t;if(n)i.BlockDurationMinutes=n;return{SpotOptions:i}},presets:{standard:{spotInstanceType:"one-time",interruptionBehavior:"terminate"},persistent:{spotInstanceType:"persistent",interruptionBehavior:"stop"},costOptimized:{maxPrice:"0.05",spotInstanceType:"one-time",interruptionBehavior:"terminate"}}};static MixedInstances={create:(e)=>{let{instanceTypes:t,baseCapacity:a=0,onDemandPercentage:r=20,spotAllocationStrategy:n="capacity-optimized",spotMaxPrice:i}=e,s={OnDemandBaseCapacity:a,OnDemandPercentageAboveBaseCapacity:r,SpotAllocationStrategy:n};if(i)s.SpotMaxPrice=i;let o=t.map(({size:c,weight:l})=>{let u={InstanceType:k.InstanceSize.toInstanceType(c)};if(l)u.WeightedCapacity=String(l);return u});return{MixedInstancesPolicy:{InstancesDistribution:s,LaunchTemplate:{Overrides:o}}}},presets:{costOptimized:{baseCapacity:0,onDemandPercentage:20,spotAllocationStrategy:"lowest-price",instanceTypes:[{size:"small",weight:1},{size:"medium",weight:2}]},balanced:{baseCapacity:1,onDemandPercentage:50,spotAllocationStrategy:"capacity-optimized",instanceTypes:[{size:"medium",weight:1},{size:"large",weight:2}]},highAvailability:{baseCapacity:2,onDemandPercentage:80,spotAllocationStrategy:"capacity-optimized-prioritized",instanceTypes:[{size:"medium",weight:1}]}}};static AutoScalingConfig={create:(e)=>{let{min:t,max:a,desired:r=t,scaleUpThreshold:n=70,scaleDownThreshold:i=30,cooldownSeconds:s=300,targetMetric:o="cpu"}=e,c={cpu:"ASGAverageCPUUtilization",memory:"ASGAverageMemoryUtilization",requests:"ALBRequestCountPerTarget"};return{minSize:t,maxSize:a,desiredCapacity:r,scalingPolicies:[{policyType:"TargetTrackingScaling",targetValue:n,predefinedMetricType:c[o]||c.cpu,scaleInCooldown:s,scaleOutCooldown:s}]}},forEcs:(e)=>{let{min:t,max:a,cpuTarget:r=70,memoryTarget:n}=e,i=[{predefinedMetricType:"ECSServiceAverageCPUUtilization",targetValue:r}];if(n)i.push({predefinedMetricType:"ECSServiceAverageMemoryUtilization",targetValue:n});return{minCapacity:t,maxCapacity:a,targetTrackingPolicies:i}},presets:{small:{min:1,max:3,scaleUpThreshold:70,scaleDownThreshold:30},medium:{min:2,max:10,scaleUpThreshold:70,scaleDownThreshold:30},large:{min:3,max:50,scaleUpThreshold:60,scaleDownThreshold:40},highAvailability:{min:2,max:20,scaleUpThreshold:60,scaleDownThreshold:30}}};static LoadBalancerConfig={healthCheck:(e)=>{let{path:t="/",interval:a=30,timeout:r=5,healthyThreshold:n=2,unhealthyThreshold:i=5,protocol:s="HTTP"}=e,o={HealthCheckIntervalSeconds:a,HealthCheckTimeoutSeconds:r,HealthyThresholdCount:n,UnhealthyThresholdCount:i};if(s!=="TCP")o.HealthCheckPath=t,o.HealthCheckProtocol=s;return o},presets:{standard:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:5},fast:{path:"/health",interval:10,timeout:3,healthyThreshold:2,unhealthyThreshold:2},relaxed:{path:"/health",interval:60,timeout:30,healthyThreshold:2,unhealthyThreshold:10}}};static SslConfig={httpsListener:(e)=>{let{certificateArn:t,targetGroupArn:a,port:r=443,sslPolicy:n="ELBSecurityPolicy-TLS13-1-2-2021-06"}=e;return{Port:r,Protocol:"HTTPS",Certificates:[{CertificateArn:t}],SslPolicy:n,DefaultActions:[{Type:"forward",TargetGroupArn:a}]}},httpRedirectListener:(e=80)=>({Port:e,Protocol:"HTTP",DefaultActions:[{Type:"redirect",RedirectConfig:{Protocol:"HTTPS",Port:"443",StatusCode:"HTTP_301"}}]}),policies:{tls13:"ELBSecurityPolicy-TLS13-1-2-2021-06",tls12:"ELBSecurityPolicy-TLS-1-2-Ext-2018-06",tls11:"ELBSecurityPolicy-TLS-1-1-2017-01",fips:"ELBSecurityPolicy-TLS-1-2-Ext-FIPS-2022-05"}};static FunctionConfig={create:(e)=>{let{handler:t,runtime:a="nodejs20.x",timeout:r=30,memorySize:n=256,environmentVariables:i,reservedConcurrency:s}=e,o={Handler:t,Runtime:a,Timeout:r,MemorySize:n};if(i)o.Environment={Variables:i};if(s)o.ReservedConcurrentExecutions=s;return o},runtimes:{nodejs20:"nodejs20.x",nodejs18:"nodejs18.x",python312:"python3.12",python311:"python3.11",java21:"java21",java17:"java17",go:"provided.al2023",rust:"provided.al2023",bun:"provided.al2023"},presets:{api:{runtime:"nodejs20.x",timeout:30,memorySize:256},worker:{runtime:"nodejs20.x",timeout:300,memorySize:512},cron:{runtime:"nodejs20.x",timeout:900,memorySize:1024},dataProcessing:{runtime:"nodejs20.x",timeout:900,memorySize:3008}}};static UserData={generateAppServerScript:(e)=>{let{runtime:t="bun",runtimeVersion:a="latest",webServer:r="nginx",processManager:n="systemd",enableSsl:i=!0,sslEmail:s="admin@example.com",domain:o,appPort:c=3000,installDatabaseClients:l=!1,installRedis:u=!1,extraPackages:m=[]}=e,p=`#!/bin/bash
349
+ `),t},commonCidrs:{any:["0.0.0.0/0"],privateOnly:["10.0.0.0/8","172.16.0.0/12","192.168.0.0/16"]}};static InstanceSize={toInstanceType:(e,t="t3")=>{return`${t}.${e}`},specs:{nano:{vcpu:2,memory:0.5,instanceType:"t3.nano"},micro:{vcpu:2,memory:1,instanceType:"t3.micro"},small:{vcpu:2,memory:2,instanceType:"t3.small"},medium:{vcpu:2,memory:4,instanceType:"t3.medium"},large:{vcpu:2,memory:8,instanceType:"t3.large"},xlarge:{vcpu:4,memory:16,instanceType:"t3.xlarge"},"2xlarge":{vcpu:8,memory:32,instanceType:"t3.2xlarge"}},toFargateSpecs:(e)=>{let t={nano:{cpu:"256",memory:"512"},micro:{cpu:"256",memory:"1024"},small:{cpu:"512",memory:"1024"},medium:{cpu:"1024",memory:"2048"},large:{cpu:"2048",memory:"4096"},xlarge:{cpu:"4096",memory:"8192"},"2xlarge":{cpu:"4096",memory:"16384"}};return t[e]||t.medium},toLambdaMemory:(e)=>{return{nano:128,micro:256,small:512,medium:1024,large:2048,xlarge:4096,"2xlarge":8192}[e]||1024},presets:{webServer:"t3.small",apiServer:"t3.medium",worker:"t3.medium",database:"r6i.large",cache:"r6i.medium",compute:"c6i.large",general:"m6i.medium"}};static DiskConfig={create:(e)=>{let{size:t,type:a="ssd",encrypted:r=!0,iops:n,throughput:i,deleteOnTermination:s=!0}=e,o={standard:"gp2",ssd:"gp3",premium:"io2",gp2:"gp2",gp3:"gp3",io1:"io1",io2:"io2"}[a]||"gp3",c={VolumeSize:t,VolumeType:o,Encrypted:r,DeleteOnTermination:s};if((o==="io1"||o==="io2"||o==="gp3")&&n)c.Iops=n;if(o==="gp3"&&i)c.Throughput=i;return c},presets:{standard:{VolumeSize:20,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0},large:{VolumeSize:100,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0},highPerformance:{VolumeSize:50,VolumeType:"io2",Iops:3000,Encrypted:!0,DeleteOnTermination:!0},database:{VolumeSize:100,VolumeType:"io2",Iops:1e4,Encrypted:!0,DeleteOnTermination:!1}}};static SpotConfig={create:(e)=>{let{maxPrice:t,spotInstanceType:a="one-time",interruptionBehavior:r="terminate",blockDurationMinutes:n}=e,i={SpotInstanceType:a,InstanceInterruptionBehavior:r};if(t)i.MaxPrice=t;if(n)i.BlockDurationMinutes=n;return{SpotOptions:i}},presets:{standard:{spotInstanceType:"one-time",interruptionBehavior:"terminate"},persistent:{spotInstanceType:"persistent",interruptionBehavior:"stop"},costOptimized:{maxPrice:"0.05",spotInstanceType:"one-time",interruptionBehavior:"terminate"}}};static MixedInstances={create:(e)=>{let{instanceTypes:t,baseCapacity:a=0,onDemandPercentage:r=20,spotAllocationStrategy:n="capacity-optimized",spotMaxPrice:i}=e,s={OnDemandBaseCapacity:a,OnDemandPercentageAboveBaseCapacity:r,SpotAllocationStrategy:n};if(i)s.SpotMaxPrice=i;let o=t.map(({size:c,weight:l})=>{let u={InstanceType:k.InstanceSize.toInstanceType(c)};if(l)u.WeightedCapacity=String(l);return u});return{MixedInstancesPolicy:{InstancesDistribution:s,LaunchTemplate:{Overrides:o}}}},presets:{costOptimized:{baseCapacity:0,onDemandPercentage:20,spotAllocationStrategy:"lowest-price",instanceTypes:[{size:"small",weight:1},{size:"medium",weight:2}]},balanced:{baseCapacity:1,onDemandPercentage:50,spotAllocationStrategy:"capacity-optimized",instanceTypes:[{size:"medium",weight:1},{size:"large",weight:2}]},highAvailability:{baseCapacity:2,onDemandPercentage:80,spotAllocationStrategy:"capacity-optimized-prioritized",instanceTypes:[{size:"medium",weight:1}]}}};static AutoScalingConfig={create:(e)=>{let{min:t,max:a,desired:r=t,scaleUpThreshold:n=70,scaleDownThreshold:i=30,cooldownSeconds:s=300,targetMetric:o="cpu"}=e,c={cpu:"ASGAverageCPUUtilization",memory:"ASGAverageMemoryUtilization",requests:"ALBRequestCountPerTarget"};return{minSize:t,maxSize:a,desiredCapacity:r,scalingPolicies:[{policyType:"TargetTrackingScaling",targetValue:n,predefinedMetricType:c[o]||c.cpu,scaleInCooldown:s,scaleOutCooldown:s}]}},forEcs:(e)=>{let{min:t,max:a,cpuTarget:r=70,memoryTarget:n}=e,i=[{predefinedMetricType:"ECSServiceAverageCPUUtilization",targetValue:r}];if(n)i.push({predefinedMetricType:"ECSServiceAverageMemoryUtilization",targetValue:n});return{minCapacity:t,maxCapacity:a,targetTrackingPolicies:i}},presets:{small:{min:1,max:3,scaleUpThreshold:70,scaleDownThreshold:30},medium:{min:2,max:10,scaleUpThreshold:70,scaleDownThreshold:30},large:{min:3,max:50,scaleUpThreshold:60,scaleDownThreshold:40},highAvailability:{min:2,max:20,scaleUpThreshold:60,scaleDownThreshold:30}}};static LoadBalancerConfig={healthCheck:(e)=>{let{path:t="/",interval:a=30,timeout:r=5,healthyThreshold:n=2,unhealthyThreshold:i=5,protocol:s="HTTP"}=e,o={HealthCheckIntervalSeconds:a,HealthCheckTimeoutSeconds:r,HealthyThresholdCount:n,UnhealthyThresholdCount:i};if(s!=="TCP")o.HealthCheckPath=t,o.HealthCheckProtocol=s;return o},presets:{standard:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:5},fast:{path:"/health",interval:10,timeout:3,healthyThreshold:2,unhealthyThreshold:2},relaxed:{path:"/health",interval:60,timeout:30,healthyThreshold:2,unhealthyThreshold:10}}};static SslConfig={httpsListener:(e)=>{let{certificateArn:t,targetGroupArn:a,port:r=443,sslPolicy:n="ELBSecurityPolicy-TLS13-1-2-2021-06"}=e;return{Port:r,Protocol:"HTTPS",Certificates:[{CertificateArn:t}],SslPolicy:n,DefaultActions:[{Type:"forward",TargetGroupArn:a}]}},httpRedirectListener:(e=80)=>({Port:e,Protocol:"HTTP",DefaultActions:[{Type:"redirect",RedirectConfig:{Protocol:"HTTPS",Port:"443",StatusCode:"HTTP_301"}}]}),policies:{tls13:"ELBSecurityPolicy-TLS13-1-2-2021-06",tls12:"ELBSecurityPolicy-TLS-1-2-Ext-2018-06",tls11:"ELBSecurityPolicy-TLS-1-1-2017-01",fips:"ELBSecurityPolicy-TLS-1-2-Ext-FIPS-2022-05"}};static FunctionConfig={create:(e)=>{let{handler:t,runtime:a="nodejs20.x",timeout:r=30,memorySize:n=256,environmentVariables:i,reservedConcurrency:s}=e,o={Handler:t,Runtime:a,Timeout:r,MemorySize:n};if(i)o.Environment={Variables:i};if(s)o.ReservedConcurrentExecutions=s;return o},runtimes:{nodejs20:"nodejs20.x",nodejs18:"nodejs18.x",python312:"python3.12",python311:"python3.11",java21:"java21",java17:"java17",go:"provided.al2023",rust:"provided.al2023",bun:"provided.al2023"},presets:{api:{runtime:"nodejs20.x",timeout:30,memorySize:256},worker:{runtime:"nodejs20.x",timeout:300,memorySize:512},cron:{runtime:"nodejs20.x",timeout:900,memorySize:1024},dataProcessing:{runtime:"nodejs20.x",timeout:900,memorySize:3008}}};static UserData={generateAppServerScript:(e)=>{let{runtime:t="bun",runtimeVersion:a="latest",webServer:r="nginx",processManager:n="systemd",enableSsl:i=!0,sslEmail:s="admin@example.com",domain:o,appPort:c=3000,installDatabaseClients:l=!1,installRedis:u=!1,extraPackages:m=[]}=e,p=`#!/bin/bash
350
350
  set -e
351
351
 
352
352
  # Update system
@@ -604,7 +604,7 @@ ufw default allow outgoing
604
604
  ${e.map((t)=>`ufw allow ${t}`).join(`
605
605
  `)}
606
606
  ufw --force enable
607
- `},Presets:{bunWithNginx:(e,t=3000)=>k.UserData.generateAppServerScript({runtime:"bun",webServer:"nginx",processManager:"systemd",domain:e,appPort:t,enableSsl:!0}),bunWithCaddy:(e,t=3000)=>k.UserData.generateAppServerScript({runtime:"bun",webServer:"caddy",processManager:"systemd",domain:e,appPort:t,enableSsl:!1}),nodeWithPm2:(e,t=3000)=>k.UserData.generateAppServerScript({runtime:"node",webServer:"nginx",processManager:"pm2",domain:e,appPort:t,enableSsl:!0}),worker:(e="bun")=>k.UserData.generateAppServerScript({runtime:e,webServer:"none",processManager:"systemd",enableSsl:!1})}};static createElasticIp(e){let{slug:t,environment:a,domain:r,instanceLogicalId:n}=e,i=A({slug:t,environment:a,resourceType:"eip"}),s=f(i),o={Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:i},{Key:"Environment",Value:a},...r?[{Key:"Domain",Value:r}]:[]]}},c={[s]:o},l,u;if(n)u=f(`${i}-assoc`),l={Type:"AWS::EC2::EIPAssociation",Properties:{AllocationId:C.GetAtt(s,"AllocationId"),InstanceId:C.Ref(n)}},c[u]=l;return{eip:o,eipAssociation:l,eipLogicalId:s,associationLogicalId:u,resources:c}}static createServerModeStack(e){let{slug:t,environment:a,vpcId:r,subnetId:n,instanceType:i="t3.small",imageId:s="ami-0f3caa1cf4417e51b",keyName:o,domain:c,userData:l,allowedPorts:u=[22,80,443],volumeSize:m=20,volumeType:p="gp3"}=e,g={},h=A({slug:t,environment:a,resourceType:"server-sg"}),y=f(h),b={Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:h,GroupDescription:`Security group for ${t} server`,VpcId:r,SecurityGroupIngress:u.map((F)=>({IpProtocol:"tcp",FromPort:F,ToPort:F,CidrIp:"0.0.0.0/0",Description:`Port ${F}`})),SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound"}],Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:a}]}};g[y]=b;let T=A({slug:t,environment:a,resourceType:"server-role"}),w=f(T),S={Type:"AWS::IAM::Role",Properties:{RoleName:T,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:"*"}]}}]}};g[w]=S;let E=A({slug:t,environment:a,resourceType:"server-profile"}),v=f(E),P={Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:E,Roles:[C.Ref(w)]}};g[v]=P;let N=A({slug:t,environment:a,resourceType:"server"}),I=f(N),D={Type:"AWS::EC2::Instance",DependsOn:[v],Properties:{ImageId:s,InstanceType:i,KeyName:o,SubnetId:n,SecurityGroupIds:[C.Ref(y)],IamInstanceProfile:C.Ref(v),BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:m,VolumeType:p,Encrypted:!0,DeleteOnTermination:!0}}],Tags:[{Key:"Name",Value:N},{Key:"Environment",Value:a},...c?[{Key:"Domain",Value:c}]:[]]}};if(l)D.Properties.UserData=C.Base64(l);g[I]=D;let{eip:L,eipAssociation:O,eipLogicalId:ce,associationLogicalId:j,resources:ae}=k.createElasticIp({slug:t,environment:a,domain:c,instanceLogicalId:I});return Object.assign(g,ae),{instance:D,securityGroup:b,eip:L,eipAssociation:O,instanceRole:S,instanceProfile:P,resources:g,outputs:{instanceLogicalId:I,securityGroupLogicalId:y,eipLogicalId:ce,associationLogicalId:j,roleLogicalId:w,profileLogicalId:v}}}static ServerMode={webServer:(e)=>{let t=k.UserData.generateAppServerScript({runtime:e.runtime||"bun",webServer:e.webServer||"nginx",domain:e.domain,enableSsl:!0});return k.createServerModeStack({...e,userData:t,instanceType:"t3.small",allowedPorts:[22,80,443]})},workerServer:(e)=>{let t=k.UserData.generateAppServerScript({runtime:e.runtime||"bun",webServer:"none",installRedis:e.installRedis});return k.createServerModeStack({...e,userData:t,instanceType:"t3.medium",allowedPorts:[22]})},cacheServer:(e)=>k.createServerModeStack({...e,userData:`#!/bin/bash
607
+ `},Presets:{bunWithNginx:(e,t=3000)=>k.UserData.generateAppServerScript({runtime:"bun",webServer:"nginx",processManager:"systemd",domain:e,appPort:t,enableSsl:!0}),bunWithCaddy:(e,t=3000)=>k.UserData.generateAppServerScript({runtime:"bun",webServer:"caddy",processManager:"systemd",domain:e,appPort:t,enableSsl:!1}),nodeWithPm2:(e,t=3000)=>k.UserData.generateAppServerScript({runtime:"node",webServer:"nginx",processManager:"pm2",domain:e,appPort:t,enableSsl:!0}),worker:(e="bun")=>k.UserData.generateAppServerScript({runtime:e,webServer:"none",processManager:"systemd",enableSsl:!1})}};static createElasticIp(e){let{slug:t,environment:a,domain:r,instanceLogicalId:n}=e,i=A({slug:t,environment:a,resourceType:"eip"}),s=f(i),o={Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:i},{Key:"Environment",Value:a},...r?[{Key:"Domain",Value:r}]:[]]}},c={[s]:o},l,u;if(n)u=f(`${i}-assoc`),l={Type:"AWS::EC2::EIPAssociation",Properties:{AllocationId:C.GetAtt(s,"AllocationId"),InstanceId:C.Ref(n)}},c[u]=l;return{eip:o,eipAssociation:l,eipLogicalId:s,associationLogicalId:u,resources:c}}static createServerModeStack(e){let{slug:t,environment:a,vpcId:r,subnetId:n,instanceType:i="t3.small",imageId:s="ami-0f3caa1cf4417e51b",keyName:o,domain:c,userData:l,allowedPorts:u=[22,80,443],volumeSize:m=20,volumeType:p="gp3"}=e,g={},h=A({slug:t,environment:a,resourceType:"server-sg"}),y=f(h),b={Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:h,GroupDescription:`Security group for ${t} server`,VpcId:r,SecurityGroupIngress:u.map((G)=>({IpProtocol:"tcp",FromPort:G,ToPort:G,CidrIp:"0.0.0.0/0",Description:`Port ${G}`})),SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound"}],Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:a}]}};g[y]=b;let T=A({slug:t,environment:a,resourceType:"server-role"}),w=f(T),S={Type:"AWS::IAM::Role",Properties:{RoleName:T,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:"*"}]}}]}};g[w]=S;let E=A({slug:t,environment:a,resourceType:"server-profile"}),v=f(E),P={Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:E,Roles:[C.Ref(w)]}};g[v]=P;let N=A({slug:t,environment:a,resourceType:"server"}),I=f(N),D={Type:"AWS::EC2::Instance",DependsOn:[v],Properties:{ImageId:s,InstanceType:i,KeyName:o,SubnetId:n,SecurityGroupIds:[C.Ref(y)],IamInstanceProfile:C.Ref(v),BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:m,VolumeType:p,Encrypted:!0,DeleteOnTermination:!0}}],Tags:[{Key:"Name",Value:N},{Key:"Environment",Value:a},...c?[{Key:"Domain",Value:c}]:[]]}};if(l)D.Properties.UserData=C.Base64(l);g[I]=D;let{eip:M,eipAssociation:O,eipLogicalId:oe,associationLogicalId:j,resources:te}=k.createElasticIp({slug:t,environment:a,domain:c,instanceLogicalId:I});return Object.assign(g,te),{instance:D,securityGroup:b,eip:M,eipAssociation:O,instanceRole:S,instanceProfile:P,resources:g,outputs:{instanceLogicalId:I,securityGroupLogicalId:y,eipLogicalId:oe,associationLogicalId:j,roleLogicalId:w,profileLogicalId:v}}}static ServerMode={webServer:(e)=>{let t=k.UserData.generateAppServerScript({runtime:e.runtime||"bun",webServer:e.webServer||"nginx",domain:e.domain,enableSsl:!0});return k.createServerModeStack({...e,userData:t,instanceType:"t3.small",allowedPorts:[22,80,443]})},workerServer:(e)=>{let t=k.UserData.generateAppServerScript({runtime:e.runtime||"bun",webServer:"none",installRedis:e.installRedis});return k.createServerModeStack({...e,userData:t,instanceType:"t3.medium",allowedPorts:[22]})},cacheServer:(e)=>{return k.createServerModeStack({...e,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 B{static createVpc(e){let{slug:t,environment:a,cidr:r="10.0.0.0/16",enableDnsHostnames:n=!0,enableDnsSupport:i=!0}=e,s=A({slug:t,environment:a,resourceType:"vpc"}),o=f(s);return{vpc:{Type:"AWS::EC2::VPC",Properties:{CidrBlock:r,EnableDnsHostnames:n,EnableDnsSupport:i,Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:a}]}},logicalId:o}}static createSubnet(e){let{slug:t,environment:a,vpcId:r,type:n,cidr:i,availabilityZone:s,mapPublicIp:o=n==="public"}=e,c=A({slug:t,environment:a,resourceType:`subnet-${n}`}),l=f(`${c}-${s}`);return{subnet:{Type:"AWS::EC2::Subnet",Properties:{VpcId:r,CidrBlock:i,AvailabilityZone:s,MapPublicIpOnLaunch:o,Tags:[{Key:"Name",Value:`${c}-${s}`},{Key:"Environment",Value:a},{Key:"Type",Value:n}]}},logicalId:l}}static createInternetGateway(e,t){let a=A({slug:e,environment:t,resourceType:"igw"}),r=f(a);return{internetGateway:{Type:"AWS::EC2::InternetGateway",Properties:{Tags:[{Key:"Name",Value:a},{Key:"Environment",Value:t}]}},logicalId:r}}static attachInternetGateway(e,t){let a=f(`${e}-igw-attachment`);return{attachment:{Type:"AWS::EC2::VPCGatewayAttachment",Properties:{VpcId:C.Ref(e),InternetGatewayId:C.Ref(t)}},logicalId:a}}static createEip(e,t){let a=A({slug:e,environment:t,resourceType:"eip"}),r=f(a);return{eip:{Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:a},{Key:"Environment",Value:t}]}},logicalId:r}}static createNatGateway(e,t){let{slug:a,environment:r,subnetId:n}=e,i=A({slug:a,environment:r,resourceType:"nat"}),s=f(i);return{natGateway:{Type:"AWS::EC2::NatGateway",Properties:{AllocationId:C.GetAtt(t,"AllocationId"),SubnetId:n,Tags:[{Key:"Name",Value:i},{Key:"Environment",Value:r},{Key:"Warning",Value:"NAT Gateway incurs hourly charges"}]}},logicalId:s}}static createRouteTable(e,t,a,r){let n=A({slug:e,environment:t,resourceType:`rt-${r}`}),i=f(n);return{routeTable:{Type:"AWS::EC2::RouteTable",Properties:{VpcId:C.Ref(a),Tags:[{Key:"Name",Value:n},{Key:"Environment",Value:t},{Key:"Type",Value:r}]}},logicalId:i}}static createRoute(e,t,a){let r=f(`${e}-route-${a.type}`),n={Type:"AWS::EC2::Route",Properties:{RouteTableId:C.Ref(e),DestinationCidrBlock:t}};if(a.type==="igw")n.Properties.GatewayId=C.Ref(a.logicalId);else if(a.type==="nat")n.Properties.NatGatewayId=C.Ref(a.logicalId);else if(a.type==="instance")n.Properties.InstanceId=C.Ref(a.logicalId);return{route:n,logicalId:r}}static associateSubnetWithRouteTable(e,t){let a=f(`${e}-rt-assoc`);return{association:{Type:"AWS::EC2::SubnetRouteTableAssociation",Properties:{SubnetId:C.Ref(e),RouteTableId:C.Ref(t)}},logicalId:a}}static enableFlowLogs(e){let{slug:t,environment:a,resourceId:r,resourceType:n,trafficType:i="ALL",logGroupName:s}=e,o=A({slug:t,environment:a,resourceType:"flowlog"}),c=f(o);return{flowLog:{Type:"AWS::EC2::FlowLog",Properties:{ResourceType:n,ResourceIds:[r],TrafficType:i,LogDestinationType:"cloud-watch-logs",LogGroupName:s||`/aws/vpc/${t}-${a}`,Tags:[{Key:"Name",Value:o},{Key:"Environment",Value:a}]}},logicalId:c}}static calculateSubnetCidrs(e,t,a=3){let[r,n]=e.split("/"),i=Number.parseInt(n,10),s=Math.ceil(Math.log2(t*a)),o=i+s;if(o>28)throw Error("VPC CIDR is too small to accommodate requested subnets");let[c,l,u,m]=r.split(".").map(Number),p=(c<<24)+(l<<16)+(u<<8)+m,g=2**(32-o),h=[];for(let y=0;y<t*a;y++){let b=p+y*g,T=[b>>>24&255,b>>>16&255,b>>>8&255,b&255].join(".");h.push(`${T}/${o}`)}return h}static getAvailabilityZones(e,t){return["a","b","c","d","e","f"].slice(0,t).map((a)=>`${e}${a}`)}static createMultiAzNetwork(e){let{slug:t,environment:a,region:r,cidr:n="10.0.0.0/16",zones:i=3,enableNatGateway:s=!1,singleNatGateway:o=!1,enableFlowLogs:c=!1}=e,l={},u=[],m=[],p=[],{vpc:g,logicalId:h}=B.createVpc({slug:t,environment:a,cidr:n});l[h]=g;let{internetGateway:y,logicalId:b}=B.createInternetGateway(t,a);l[b]=y;let{attachment:T,logicalId:w}=B.attachInternetGateway(h,b);l[w]=T;let{routeTable:S,logicalId:E}=B.createRouteTable(t,a,h,"public");l[E]=S;let{route:v,logicalId:P}=B.createRoute(E,"0.0.0.0/0",{type:"igw",logicalId:b});v.DependsOn=w,l[P]=v;let N=B.calculateSubnetCidrs(n,i,2),I=B.getAvailabilityZones(r,i),D=[];for(let L=0;L<i;L++){let O=I[L],ce=N[L*2],j=N[L*2+1],{subnet:ae,logicalId:F}=B.createSubnet({slug:t,environment:a,vpcId:C.Ref(h),type:"public",cidr:ce,availabilityZone:O});l[F]=ae,u.push(F);let{association:we,logicalId:Fe}=B.associateSubnetWithRouteTable(F,E);l[Fe]=we;let{subnet:kt,logicalId:le}=B.createSubnet({slug:t,environment:a,vpcId:C.Ref(h),type:"private",cidr:j,availabilityZone:O});if(l[le]=kt,m.push(le),s&&(!o||L===0)){let{eip:re,logicalId:ue}=B.createEip(`${t}-${O}`,a);l[ue]=re;let{natGateway:Ee,logicalId:de}=B.createNatGateway({slug:`${t}-${O}`,environment:a,subnetId:C.Ref(F)},ue);Ee.DependsOn=w,l[de]=Ee,p.push(de);let{routeTable:Se,logicalId:$e}=B.createRouteTable(`${t}-${O}`,a,h,"private");l[$e]=Se,D.push($e);let{route:Ve,logicalId:R}=B.createRoute($e,"0.0.0.0/0",{type:"nat",logicalId:de});l[R]=Ve;let{association:x,logicalId:M}=B.associateSubnetWithRouteTable(le,$e);l[M]=x}else if(s&&o&&L>0){let{association:re,logicalId:ue}=B.associateSubnetWithRouteTable(le,D[0]);l[ue]=re}else{let{routeTable:re,logicalId:ue}=B.createRouteTable(`${t}-${O}-isolated`,a,h,"private");l[ue]=re;let{association:Ee,logicalId:de}=B.associateSubnetWithRouteTable(le,ue);l[de]=Ee}}if(c){let{flowLog:L,logicalId:O}=B.enableFlowLogs({slug:t,environment:a,resourceId:C.Ref(h),resourceType:"VPC"});l[O]=L}return{resources:l,outputs:{vpcId:h,publicSubnetIds:u,privateSubnetIds:m,natGatewayIds:p.length>0?p:void 0}}}static NatGatewayCostWarning=`
615
+ `,instanceType:"t3.medium",allowedPorts:[22,6379]})}}}class W{static createVpc(e){let{slug:t,environment:a,cidr:r="10.0.0.0/16",enableDnsHostnames:n=!0,enableDnsSupport:i=!0}=e,s=A({slug:t,environment:a,resourceType:"vpc"}),o=f(s);return{vpc:{Type:"AWS::EC2::VPC",Properties:{CidrBlock:r,EnableDnsHostnames:n,EnableDnsSupport:i,Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:a}]}},logicalId:o}}static createSubnet(e){let{slug:t,environment:a,vpcId:r,type:n,cidr:i,availabilityZone:s,mapPublicIp:o=n==="public"}=e,c=A({slug:t,environment:a,resourceType:`subnet-${n}`}),l=f(`${c}-${s}`);return{subnet:{Type:"AWS::EC2::Subnet",Properties:{VpcId:r,CidrBlock:i,AvailabilityZone:s,MapPublicIpOnLaunch:o,Tags:[{Key:"Name",Value:`${c}-${s}`},{Key:"Environment",Value:a},{Key:"Type",Value:n}]}},logicalId:l}}static createInternetGateway(e,t){let a=A({slug:e,environment:t,resourceType:"igw"}),r=f(a);return{internetGateway:{Type:"AWS::EC2::InternetGateway",Properties:{Tags:[{Key:"Name",Value:a},{Key:"Environment",Value:t}]}},logicalId:r}}static attachInternetGateway(e,t){let a=f(`${e}-igw-attachment`);return{attachment:{Type:"AWS::EC2::VPCGatewayAttachment",Properties:{VpcId:C.Ref(e),InternetGatewayId:C.Ref(t)}},logicalId:a}}static createEip(e,t){let a=A({slug:e,environment:t,resourceType:"eip"}),r=f(a);return{eip:{Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:a},{Key:"Environment",Value:t}]}},logicalId:r}}static createNatGateway(e,t){let{slug:a,environment:r,subnetId:n}=e,i=A({slug:a,environment:r,resourceType:"nat"}),s=f(i);return{natGateway:{Type:"AWS::EC2::NatGateway",Properties:{AllocationId:C.GetAtt(t,"AllocationId"),SubnetId:n,Tags:[{Key:"Name",Value:i},{Key:"Environment",Value:r},{Key:"Warning",Value:"NAT Gateway incurs hourly charges"}]}},logicalId:s}}static createRouteTable(e,t,a,r){let n=A({slug:e,environment:t,resourceType:`rt-${r}`}),i=f(n);return{routeTable:{Type:"AWS::EC2::RouteTable",Properties:{VpcId:C.Ref(a),Tags:[{Key:"Name",Value:n},{Key:"Environment",Value:t},{Key:"Type",Value:r}]}},logicalId:i}}static createRoute(e,t,a){let r=f(`${e}-route-${a.type}`),n={Type:"AWS::EC2::Route",Properties:{RouteTableId:C.Ref(e),DestinationCidrBlock:t}};if(a.type==="igw")n.Properties.GatewayId=C.Ref(a.logicalId);else if(a.type==="nat")n.Properties.NatGatewayId=C.Ref(a.logicalId);else if(a.type==="instance")n.Properties.InstanceId=C.Ref(a.logicalId);return{route:n,logicalId:r}}static associateSubnetWithRouteTable(e,t){let a=f(`${e}-rt-assoc`);return{association:{Type:"AWS::EC2::SubnetRouteTableAssociation",Properties:{SubnetId:C.Ref(e),RouteTableId:C.Ref(t)}},logicalId:a}}static enableFlowLogs(e){let{slug:t,environment:a,resourceId:r,resourceType:n,trafficType:i="ALL",logGroupName:s}=e,o=A({slug:t,environment:a,resourceType:"flowlog"}),c=f(o);return{flowLog:{Type:"AWS::EC2::FlowLog",Properties:{ResourceType:n,ResourceIds:[r],TrafficType:i,LogDestinationType:"cloud-watch-logs",LogGroupName:s||`/aws/vpc/${t}-${a}`,Tags:[{Key:"Name",Value:o},{Key:"Environment",Value:a}]}},logicalId:c}}static calculateSubnetCidrs(e,t,a=3){let[r,n]=e.split("/"),i=Number.parseInt(n,10),s=Math.ceil(Math.log2(t*a)),o=i+s;if(o>28)throw Error("VPC CIDR is too small to accommodate requested subnets");let[c,l,u,m]=r.split(".").map(Number),p=(c<<24)+(l<<16)+(u<<8)+m,g=2**(32-o),h=[];for(let y=0;y<t*a;y++){let b=p+y*g,T=[b>>>24&255,b>>>16&255,b>>>8&255,b&255].join(".");h.push(`${T}/${o}`)}return h}static getAvailabilityZones(e,t){return["a","b","c","d","e","f"].slice(0,t).map((a)=>`${e}${a}`)}static createMultiAzNetwork(e){let{slug:t,environment:a,region:r,cidr:n="10.0.0.0/16",zones:i=3,enableNatGateway:s=!1,singleNatGateway:o=!1,enableFlowLogs:c=!1}=e,l={},u=[],m=[],p=[],{vpc:g,logicalId:h}=W.createVpc({slug:t,environment:a,cidr:n});l[h]=g;let{internetGateway:y,logicalId:b}=W.createInternetGateway(t,a);l[b]=y;let{attachment:T,logicalId:w}=W.attachInternetGateway(h,b);l[w]=T;let{routeTable:S,logicalId:E}=W.createRouteTable(t,a,h,"public");l[E]=S;let{route:v,logicalId:P}=W.createRoute(E,"0.0.0.0/0",{type:"igw",logicalId:b});v.DependsOn=w,l[P]=v;let N=W.calculateSubnetCidrs(n,i,2),I=W.getAvailabilityZones(r,i),D=[];for(let M=0;M<i;M++){let O=I[M],oe=N[M*2],j=N[M*2+1],{subnet:te,logicalId:G}=W.createSubnet({slug:t,environment:a,vpcId:C.Ref(h),type:"public",cidr:oe,availabilityZone:O});l[G]=te,u.push(G);let{association:ve,logicalId:Ge}=W.associateSubnetWithRouteTable(G,E);l[Ge]=ve;let{subnet:Dt,logicalId:ce}=W.createSubnet({slug:t,environment:a,vpcId:C.Ref(h),type:"private",cidr:j,availabilityZone:O});if(l[ce]=Dt,m.push(ce),s&&(!o||M===0)){let{eip:ae,logicalId:le}=W.createEip(`${t}-${O}`,a);l[le]=ae;let{natGateway:we,logicalId:ue}=W.createNatGateway({slug:`${t}-${O}`,environment:a,subnetId:C.Ref(G)},le);we.DependsOn=w,l[ue]=we,p.push(ue);let{routeTable:fe,logicalId:ke}=W.createRouteTable(`${t}-${O}`,a,h,"private");l[ke]=fe,D.push(ke);let{route:Ve,logicalId:R}=W.createRoute(ke,"0.0.0.0/0",{type:"nat",logicalId:ue});l[R]=Ve;let{association:x,logicalId:L}=W.associateSubnetWithRouteTable(ce,ke);l[L]=x}else if(s&&o&&M>0){let{association:ae,logicalId:le}=W.associateSubnetWithRouteTable(ce,D[0]);l[le]=ae}else{let{routeTable:ae,logicalId:le}=W.createRouteTable(`${t}-${O}-isolated`,a,h,"private");l[le]=ae;let{association:we,logicalId:ue}=W.associateSubnetWithRouteTable(ce,le);l[ue]=we}}if(c){let{flowLog:M,logicalId:O}=W.enableFlowLogs({slug:t,environment:a,resourceId:C.Ref(h),resourceType:"VPC"});l[O]=M}return{resources:l,outputs:{vpcId:h,publicSubnetIds:u,privateSubnetIds:m,natGatewayIds:p.length>0?p: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
@@ -1166,7 +1166,7 @@ else if (encoding === 'quoted-printable') {
1166
1166
 
1167
1167
  return content;
1168
1168
  }
1169
- `}}var Ti={};De(Ti,{default:()=>vi,handler:()=>za});var za=`
1169
+ `}}var Ci={};Ne(Ci,{handler:()=>za,default:()=>Ti});var za=`
1170
1170
  const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');
1171
1171
  const { DynamoDBClient, PutItemCommand } = require('@aws-sdk/client-dynamodb');
1172
1172
 
@@ -1273,7 +1273,7 @@ catch (error) {
1273
1273
  };
1274
1274
  }
1275
1275
  };
1276
- `,vi=`
1276
+ `,Ti=`
1277
1277
  const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');
1278
1278
  const { DynamoDBClient, PutItemCommand } = require('@aws-sdk/client-dynamodb');
1279
1279
 
@@ -1380,7 +1380,7 @@ catch (error) {
1380
1380
  };
1381
1381
  }
1382
1382
  };
1383
- `,wi=`
1383
+ `,vi=`
1384
1384
  const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');
1385
1385
  const { DynamoDBClient, UpdateItemCommand } = require('@aws-sdk/client-dynamodb');
1386
1386
 
@@ -1487,7 +1487,7 @@ catch (error) {
1487
1487
  };
1488
1488
  }
1489
1489
  };
1490
- `,Ei=`
1490
+ `,wi=`
1491
1491
  const { S3Client, GetObjectCommand, PutObjectCommand } = require('@aws-sdk/client-s3');
1492
1492
  const { TranscribeClient, StartTranscriptionJobCommand, GetTranscriptionJobCommand } = require('@aws-sdk/client-transcribe');
1493
1493
  const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');
@@ -1658,7 +1658,7 @@ catch (error) {
1658
1658
 
1659
1659
  return { statusCode: 200, body: 'OK' };
1660
1660
  };
1661
- `;class ge{static LambdaCode={incomingCall:za,voicemail:Ei,missedCall:wi};static createConnectInstance(e){let{slug:t,environment:a,instanceAlias:r,inboundCallsEnabled:n=!0,outboundCallsEnabled:i=!0}=e;return{[`${t}ConnectInstance`]:{Type:"AWS::Connect::Instance",Properties:{InstanceAlias:r,IdentityManagementType:"CONNECT_MANAGED",Attributes:{InboundCalls:n,OutboundCalls:i,ContactflowLogs:!0,ContactLens:!0,AutoResolveBestVoices:!0,UseCustomTTSVoices:!1,EarlyMedia:!0}}}}}static createHoursOfOperation(e){return{[`${e.slug}HoursOfOperation`]:{Type:"AWS::Connect::HoursOfOperation",Properties:{InstanceArn:e.instanceArn,Name:e.name,TimeZone:e.timezone,Config:e.schedule.map((t)=>({Day:t.day,StartTime:{Hours:t.startHour,Minutes:t.startMinute},EndTime:{Hours:t.endHour,Minutes:t.endMinute}}))}}}}static createQueue(e){return{[`${e.slug}Queue`]:{Type:"AWS::Connect::Queue",Properties:{InstanceArn:e.instanceArn,Name:e.name,HoursOfOperationArn:e.hoursOfOperationArn,MaxContacts:e.maxContacts||10}}}}static createContactFlow(e){return{[`${e.slug}ContactFlow`]:{Type:"AWS::Connect::ContactFlow",Properties:{InstanceArn:e.instanceArn,Name:e.name,Type:e.type,Content:e.content}}}}static createBasicIvrFlow(e){let t={Version:"2019-10-30",StartAction:"greeting",Actions:[{Identifier:"greeting",Type:"MessageParticipant",Parameters:{Text:e.greeting},Transitions:{NextAction:"transfer_to_queue",Errors:[{NextAction:"disconnect"}]}},{Identifier:"transfer_to_queue",Type:"TransferToQueue",Parameters:{QueueId:e.queueArn},Transitions:{NextAction:e.voicemailLambdaArn?"voicemail":"disconnect",Errors:[{NextAction:"disconnect"}]}},...e.voicemailLambdaArn?[{Identifier:"voicemail",Type:"InvokeLambdaFunction",Parameters:{LambdaFunctionARN:e.voicemailLambdaArn},Transitions:{NextAction:"disconnect",Errors:[{NextAction:"disconnect"}]}}]:[],{Identifier:"disconnect",Type:"DisconnectParticipant",Parameters:{},Transitions:{}}]};return JSON.stringify(t)}static createPhoneLambdaRole(e){return{[`${e.slug}PhoneLambdaRole`]:{Type:"AWS::IAM::Role",Properties:{RoleName:`${e.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(e){return{[`${e.slug}IncomingCallLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-incoming-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:ge.LambdaCode.incomingCall},Environment:{Variables:{NOTIFICATION_TOPIC_ARN:e.notificationTopicArn||"",CALL_LOG_TABLE:e.callLogTable||"",WEBHOOK_URL:e.webhookUrl||""}}}}}}static createVoicemailLambda(e){return{[`${e.slug}VoicemailLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-voicemail`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:300,MemorySize:512,Code:{ZipFile:ge.LambdaCode.voicemail},Environment:{Variables:{VOICEMAIL_BUCKET:e.voicemailBucket,NOTIFICATION_TOPIC_ARN:e.notificationTopicArn||"",CALL_LOG_TABLE:e.callLogTable||"",TRANSCRIPTION_ENABLED:e.transcriptionEnabled?"true":"false"}}}}}}static createMissedCallLambda(e){return{[`${e.slug}MissedCallLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-missed-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:ge.LambdaCode.missedCall},Environment:{Variables:{NOTIFICATION_TOPIC_ARN:e.notificationTopicArn||"",CALL_LOG_TABLE:e.callLogTable||"",WEBHOOK_URL:e.webhookUrl||""}}}}}}static createCallLogTable(e){return{[`${e.slug}CallLogTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-call-log`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"contactId",AttributeType:"S"}],KeySchema:[{AttributeName:"contactId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createCompleteSetup(e){let t={},a={};Object.assign(t,ge.createPhoneLambdaRole({slug:e.slug})),Object.assign(t,ge.createCallLogTable({slug:e.slug})),t[`${e.slug}PhoneNotificationTopic`]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${e.slug}-phone-notifications`}},t[`${e.slug}VoicemailBucket`]={Type:"AWS::S3::Bucket",Properties:{BucketName:`${e.slug}-voicemails`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldVoicemails",Status:"Enabled",ExpirationInDays:90}]}}};let r={"Fn::GetAtt":[`${e.slug}PhoneLambdaRole`,"Arn"]},n={Ref:`${e.slug}PhoneNotificationTopic`},i={Ref:`${e.slug}CallLogTable`},s={Ref:`${e.slug}VoicemailBucket`};if(Object.assign(t,ge.createIncomingCallLambda({slug:e.slug,roleArn:r,notificationTopicArn:n,callLogTable:i,webhookUrl:e.webhookUrl})),e.voicemailEnabled!==!1)Object.assign(t,ge.createVoicemailLambda({slug:e.slug,roleArn:r,voicemailBucket:s,notificationTopicArn:n,callLogTable:i,transcriptionEnabled:e.transcriptionEnabled}));return Object.assign(t,ge.createMissedCallLambda({slug:e.slug,roleArn:r,notificationTopicArn:n,callLogTable:i,webhookUrl:e.webhookUrl})),a[`${e.slug}PhoneNotificationTopicArn`]={Description:"Phone notification topic ARN",Value:{Ref:`${e.slug}PhoneNotificationTopic`}},a[`${e.slug}CallLogTableName`]={Description:"Call log table name",Value:{Ref:`${e.slug}CallLogTable`}},a[`${e.slug}VoicemailBucketName`]={Description:"Voicemail bucket name",Value:{Ref:`${e.slug}VoicemailBucket`}},{resources:t,outputs:a}}}class se{static createQueue(e){let{slug:t,environment:a,name:r,delaySeconds:n=0,visibilityTimeout:i=30,messageRetentionPeriod:s=345600,maxMessageSize:o=262144,receiveMessageWaitTime:c=0,fifo:l=!1,contentBasedDeduplication:u=!1,encrypted:m=!0,kmsKeyId:p}=e,g=r||A({slug:t,environment:a,resourceType:"queue"}),h=l?`${g}.fifo`:g,y=f(g),b={Type:"AWS::SQS::Queue",Properties:{QueueName:h,DelaySeconds:n,MaximumMessageSize:o,MessageRetentionPeriod:s,ReceiveMessageWaitTimeSeconds:c,VisibilityTimeout:i,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:a}]}};if(l)b.Properties.FifoQueue=!0,b.Properties.ContentBasedDeduplication=u;if(m)if(p)b.Properties.KmsMasterKeyId=p;else b.Properties.SqsManagedSseEnabled=!0;return{queue:b,logicalId:y}}static createDeadLetterQueue(e,t){let{slug:a,environment:r,maxReceiveCount:n=3}=t,i=A({slug:a,environment:r,resourceType:"dlq"}),s=f(i),o={Type:"AWS::SQS::Queue",Properties:{QueueName:i,MessageRetentionPeriod:1209600,Tags:[{Key:"Name",Value:i},{Key:"Environment",Value:r},{Key:"Type",Value:"DeadLetterQueue"}]}},c={Type:"AWS::SQS::Queue",Properties:{RedrivePolicy:{deadLetterTargetArn:C.GetAtt(s,"Arn"),maxReceiveCount:n}}};return{deadLetterQueue:o,updatedSourceQueue:c,deadLetterLogicalId:s}}static createSchedule(e,t){let{slug:a,environment:r,name:n,description:i,enabled:s=!0}=t,o=n||A({slug:a,environment:r,resourceType:"schedule"}),c=f(o);return{rule:{Type:"AWS::Events::Rule",Properties:{Name:o,Description:i,ScheduleExpression:e,State:s?"ENABLED":"DISABLED",Targets:[]}},logicalId:c}}static scheduleEcsTask(e,t,a){let{slug:r,environment:n,name:i,description:s,enabled:o=!0,taskDefinitionArn:c,clusterArn:l,subnets:u,securityGroups:m=[],assignPublicIp:p=!1,taskCount:g=1,containerOverrides:h}=a,y=i||A({slug:r,environment:n,resourceType:"ecs-schedule"}),b=f(y),T={Id:"1",Arn:l,RoleArn:t,EcsParameters:{TaskDefinitionArn:c,TaskCount:g,LaunchType:"FARGATE",NetworkConfiguration:{awsvpcConfiguration:{Subnets:u,SecurityGroups:m,AssignPublicIp:p?"ENABLED":"DISABLED"}},PlatformVersion:"LATEST"}};if(h&&h.length>0)T.Input=JSON.stringify({containerOverrides:h});return{rule:{Type:"AWS::Events::Rule",Properties:{Name:y,Description:s||`Scheduled ECS task: ${c}`,ScheduleExpression:e,State:o?"ENABLED":"DISABLED",Targets:[T]}},logicalId:b}}static scheduleLambda(e,t){let{slug:a,environment:r,name:n,description:i,enabled:s=!0,functionArn:o,input:c}=t,l=n||A({slug:a,environment:r,resourceType:"lambda-schedule"}),u=f(l),m={Id:"1",Arn:o};if(c)m.Input=JSON.stringify(c);return{rule:{Type:"AWS::Events::Rule",Properties:{Name:l,Description:i||`Scheduled Lambda: ${o}`,ScheduleExpression:e,State:s?"ENABLED":"DISABLED",Targets:[m]}},logicalId:u}}static scheduleSqsMessage(e,t){let{slug:a,environment:r,name:n,description:i,enabled:s=!0,queueArn:o,messageGroupId:c}=t,l=n||A({slug:a,environment:r,resourceType:"sqs-schedule"}),u=f(l),m={Id:"1",Arn:o};if(c)m.SqsParameters={MessageGroupId:c};return{rule:{Type:"AWS::Events::Rule",Properties:{Name:l,Description:i||`Scheduled SQS message: ${o}`,ScheduleExpression:e,State:s?"ENABLED":"DISABLED",Targets:[m]}},logicalId:u}}static addTarget(e,t){if(!e.Properties.Targets)e.Properties.Targets=[];let a={Id:t.id,Arn:t.arn};if(t.roleArn)a.RoleArn=t.roleArn;if(t.input)a.Input=JSON.stringify(t.input);return e.Properties.Targets.push(a),e}static toCronExpression(e){if(e.startsWith("cron(")||e.startsWith("rate("))return e;return`cron(${e})`}static rateExpression(e,t){return`rate(${e} ${t})`}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(e){let t=e.toLowerCase().trim(),a=t.match(/^every\s+(\d+)\s+(minute|minutes|hour|hours|day|days)$/i);if(a){let l=parseInt(a[1],10),u=a[2].toLowerCase(),m=u.endsWith("s")&&l===1?u.slice(0,-1):u,p=!u.endsWith("s")&&l>1?`${u}s`:u;return`rate(${l} ${l===1?m:p})`}let r=t.match(/^every\s+(minute|hour|day)$/i);if(r)return`rate(1 ${r[1]})`;let n={"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(n[t])return n[t];let i=t.match(/^daily\s+at\s+(\d{1,2})\s*(am|pm)?$/i);if(i){let l=parseInt(i[1],10),u=i[2]?.toLowerCase();if(u==="pm"&&l!==12)l+=12;else if(u==="am"&&l===12)l=0;return`cron(0 ${l} * * ? *)`}let s=t.match(/^at\s+(\d{1,2}):(\d{2})$/i);if(s){let l=parseInt(s[1],10);return`cron(${parseInt(s[2],10)} ${l} * * ? *)`}let o={monday:"MON",tuesday:"TUE",wednesday:"WED",thursday:"THU",friday:"FRI",saturday:"SAT",sunday:"SUN"},c=t.match(/^every\s+(monday|tuesday|wednesday|thursday|friday|saturday|sunday)$/i);if(c)return`cron(0 0 ? * ${o[c[1].toLowerCase()]} *)`;return se.toCronExpression(e)}static JobConfig={create:(e)=>{let{name:t,handler:a,retries:r=3,backoff:n="exponential",backoffDelay:i=1000,maxDelay:s=30000,timeout:o=60000,jitter:c=!0}=e;return{name:t,handler:a,retries:r,backoff:n,backoffDelay:i,maxDelay:s,timeout:o,jitter:c}},calculateDelay:(e,t)=>{let{backoff:a,backoffDelay:r,maxDelay:n,jitter:i}=t,s;switch(a){case"linear":s=r*e;break;case"exponential":s=r*2**(e-1);break;case"fixed":default:s=r}if(s=Math.min(s,n||Number.MAX_SAFE_INTEGER),i){let o=s*0.25*Math.random();s+=o}return Math.floor(s)},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(e){let{containerName:t,jobClass:a,jobData:r,environment:n={}}=e,i=[{name:"JOB_CLASS",value:a}];if(r)i.push({name:"JOB_DATA",value:JSON.stringify(r)});for(let[s,o]of Object.entries(n))i.push({name:s,value:o});return{name:t,command:["bun","run","app/Jobs/runner.ts"],environment:i}}static createScheduledJob(e){let{slug:t,environment:a,schedule:r,jobClass:n,jobData:i,taskDefinitionArn:s,clusterArn:o,subnets:c,securityGroups:l=[],roleArn:u,containerName:m="app"}=e,p=se.rateStringToExpression(r),g=se.createJobContainerOverride({containerName:m,jobClass:n,jobData:i});return se.scheduleEcsTask(p,u,{slug:t,environment:a,name:`${t}-${n.toLowerCase().replace(/[^a-z0-9]/g,"-")}`,description:`Scheduled job: ${n}`,taskDefinitionArn:s,clusterArn:o,subnets:c,securityGroups:l,containerOverrides:[g]})}static QueuePresets={highThroughput:(e,t)=>se.createQueue({slug:e,environment:t,visibilityTimeout:30,receiveMessageWaitTime:0,delaySeconds:0}),longRunning:(e,t)=>se.createQueue({slug:e,environment:t,visibilityTimeout:300,messageRetentionPeriod:1209600}),fifo:(e,t)=>se.createQueue({slug:e,environment:t,fifo:!0,contentBasedDeduplication:!0}),delayed:(e,t,a=60)=>se.createQueue({slug:e,environment:t,delaySeconds:a})}}class Te{static async discoverJobs(e){let{projectRoot:t,jobsPath:a="app/Jobs"}=e,r=`${t}/${a}`,n=[];try{let i=await import("node:fs"),s=await import("node:path");if(!i.existsSync(r))return[];let o=i.readdirSync(r).filter((c)=>c.endsWith(".ts")&&!c.startsWith("_")&&c!=="runner.ts");for(let c of o){let l=s.join(r,c),u=c.replace(".ts",""),m=i.readFileSync(l,"utf-8"),p=Te.parseJobMetadata(m,u,l);if(p)n.push(p)}}catch{return[]}return n}static parseJobMetadata(e,t,a){let r=e.match(/export\s + const\s + schedule\s*=\s*['"`]([^'"`]+)['"`]/)||e.match(/schedule:\s*['"`]([^'"`]+)['"`]/),n=e.match(/export\s+const\s+enabled\s*=\s*(true|false)/)||e.match(/enabled:\s*(true|false)/),i=e.match(/export\s+const\s+retries\s*=\s*(\d+)/)||e.match(/retries:\s*(\d+)/),s=e.match(/export\s+const\s+timeout\s*=\s*(\d+)/)||e.match(/timeout:\s*(\d+)/),o=e.match(/export\s+const\s+backoff\s*=\s*['"`](linear|exponential|fixed)['"`]/)||e.match(/backoff:\s*['"`](linear|exponential|fixed)['"`]/),c=e.match(/export\s + const\s + description\s*=\s*['"`]([^'"`]+)['"`]/)||e.match(/description:\s*['"`]([^'"`]+)['"`]/);if(!(e.includes("export async function handle")||e.includes("export function handle")||e.includes("export default")))return null;return{name:t,path:a,schedule:r?.[1],handler:`${t}.handle`,enabled:n?.[1]!=="false",retries:i?parseInt(i[1],10):void 0,backoff:o?.[1],timeout:s?parseInt(s[1],10):void 0,description:c?.[1]}}static async discoverActions(e){let{projectRoot:t,actionsPath:a="app/Actions"}=e,r=`${t}/${a}`,n=[];try{let i=await import("node:fs"),s=await import("node:path");if(!i.existsSync(r))return[];let o=i.readdirSync(r).filter((c)=>c.endsWith(".ts")&&!c.startsWith("_"));for(let c of o){let l=s.join(r,c),u=c.replace(".ts",""),m=i.readFileSync(l,"utf-8"),p=Te.parseActionMetadata(m,u,l);if(p)n.push(p)}}catch{return[]}return n}static parseActionMetadata(e,t,a){if(!(e.includes("export async function handle")||e.includes("export function handle")||e.includes("export default")))return null;let r=e.match(/export\s + const\s + description\s*=\s*['"`]([^'"`]+)['"`]/)||e.match(/description:\s*['"`]([^'"`]+)['"`]/);return{name:t,path:a,handler:`${t}.handle`,description:r?.[1]}}static generateScheduledJobResources(e){let{slug:t,environment:a,jobs:r,taskDefinitionArn:n,clusterArn:i,subnets:s,securityGroups:o=[],roleArn:c,containerName:l="app"}=e,u={},m=0;for(let p of r){if(!p.schedule||!p.enabled)continue;let{rule:g,logicalId:h}=se.createScheduledJob({slug:t,environment:a,schedule:p.schedule,jobClass:p.name,taskDefinitionArn:n,clusterArn:i,subnets:s,securityGroups:o,roleArn:c,containerName:l});u[h]=g,m++}return{rules:u,count:m}}static generateJobRunnerScript(){return`#!/usr/bin/env bun
1661
+ `;class pe{static LambdaCode={incomingCall:za,voicemail:wi,missedCall:vi};static createConnectInstance(e){let{slug:t,environment:a,instanceAlias:r,inboundCallsEnabled:n=!0,outboundCallsEnabled:i=!0}=e;return{[`${t}ConnectInstance`]:{Type:"AWS::Connect::Instance",Properties:{InstanceAlias:r,IdentityManagementType:"CONNECT_MANAGED",Attributes:{InboundCalls:n,OutboundCalls:i,ContactflowLogs:!0,ContactLens:!0,AutoResolveBestVoices:!0,UseCustomTTSVoices:!1,EarlyMedia:!0}}}}}static createHoursOfOperation(e){return{[`${e.slug}HoursOfOperation`]:{Type:"AWS::Connect::HoursOfOperation",Properties:{InstanceArn:e.instanceArn,Name:e.name,TimeZone:e.timezone,Config:e.schedule.map((t)=>({Day:t.day,StartTime:{Hours:t.startHour,Minutes:t.startMinute},EndTime:{Hours:t.endHour,Minutes:t.endMinute}}))}}}}static createQueue(e){return{[`${e.slug}Queue`]:{Type:"AWS::Connect::Queue",Properties:{InstanceArn:e.instanceArn,Name:e.name,HoursOfOperationArn:e.hoursOfOperationArn,MaxContacts:e.maxContacts||10}}}}static createContactFlow(e){return{[`${e.slug}ContactFlow`]:{Type:"AWS::Connect::ContactFlow",Properties:{InstanceArn:e.instanceArn,Name:e.name,Type:e.type,Content:e.content}}}}static createBasicIvrFlow(e){let t={Version:"2019-10-30",StartAction:"greeting",Actions:[{Identifier:"greeting",Type:"MessageParticipant",Parameters:{Text:e.greeting},Transitions:{NextAction:"transfer_to_queue",Errors:[{NextAction:"disconnect"}]}},{Identifier:"transfer_to_queue",Type:"TransferToQueue",Parameters:{QueueId:e.queueArn},Transitions:{NextAction:e.voicemailLambdaArn?"voicemail":"disconnect",Errors:[{NextAction:"disconnect"}]}},...e.voicemailLambdaArn?[{Identifier:"voicemail",Type:"InvokeLambdaFunction",Parameters:{LambdaFunctionARN:e.voicemailLambdaArn},Transitions:{NextAction:"disconnect",Errors:[{NextAction:"disconnect"}]}}]:[],{Identifier:"disconnect",Type:"DisconnectParticipant",Parameters:{},Transitions:{}}]};return JSON.stringify(t)}static createPhoneLambdaRole(e){return{[`${e.slug}PhoneLambdaRole`]:{Type:"AWS::IAM::Role",Properties:{RoleName:`${e.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(e){return{[`${e.slug}IncomingCallLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-incoming-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:pe.LambdaCode.incomingCall},Environment:{Variables:{NOTIFICATION_TOPIC_ARN:e.notificationTopicArn||"",CALL_LOG_TABLE:e.callLogTable||"",WEBHOOK_URL:e.webhookUrl||""}}}}}}static createVoicemailLambda(e){return{[`${e.slug}VoicemailLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-voicemail`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:300,MemorySize:512,Code:{ZipFile:pe.LambdaCode.voicemail},Environment:{Variables:{VOICEMAIL_BUCKET:e.voicemailBucket,NOTIFICATION_TOPIC_ARN:e.notificationTopicArn||"",CALL_LOG_TABLE:e.callLogTable||"",TRANSCRIPTION_ENABLED:e.transcriptionEnabled?"true":"false"}}}}}}static createMissedCallLambda(e){return{[`${e.slug}MissedCallLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-missed-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:pe.LambdaCode.missedCall},Environment:{Variables:{NOTIFICATION_TOPIC_ARN:e.notificationTopicArn||"",CALL_LOG_TABLE:e.callLogTable||"",WEBHOOK_URL:e.webhookUrl||""}}}}}}static createCallLogTable(e){return{[`${e.slug}CallLogTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-call-log`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"contactId",AttributeType:"S"}],KeySchema:[{AttributeName:"contactId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createCompleteSetup(e){let t={},a={};Object.assign(t,pe.createPhoneLambdaRole({slug:e.slug})),Object.assign(t,pe.createCallLogTable({slug:e.slug})),t[`${e.slug}PhoneNotificationTopic`]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${e.slug}-phone-notifications`}},t[`${e.slug}VoicemailBucket`]={Type:"AWS::S3::Bucket",Properties:{BucketName:`${e.slug}-voicemails`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldVoicemails",Status:"Enabled",ExpirationInDays:90}]}}};let r={"Fn::GetAtt":[`${e.slug}PhoneLambdaRole`,"Arn"]},n={Ref:`${e.slug}PhoneNotificationTopic`},i={Ref:`${e.slug}CallLogTable`},s={Ref:`${e.slug}VoicemailBucket`};if(Object.assign(t,pe.createIncomingCallLambda({slug:e.slug,roleArn:r,notificationTopicArn:n,callLogTable:i,webhookUrl:e.webhookUrl})),e.voicemailEnabled!==!1)Object.assign(t,pe.createVoicemailLambda({slug:e.slug,roleArn:r,voicemailBucket:s,notificationTopicArn:n,callLogTable:i,transcriptionEnabled:e.transcriptionEnabled}));return Object.assign(t,pe.createMissedCallLambda({slug:e.slug,roleArn:r,notificationTopicArn:n,callLogTable:i,webhookUrl:e.webhookUrl})),a[`${e.slug}PhoneNotificationTopicArn`]={Description:"Phone notification topic ARN",Value:{Ref:`${e.slug}PhoneNotificationTopic`}},a[`${e.slug}CallLogTableName`]={Description:"Call log table name",Value:{Ref:`${e.slug}CallLogTable`}},a[`${e.slug}VoicemailBucketName`]={Description:"Voicemail bucket name",Value:{Ref:`${e.slug}VoicemailBucket`}},{resources:t,outputs:a}}}class ie{static createQueue(e){let{slug:t,environment:a,name:r,delaySeconds:n=0,visibilityTimeout:i=30,messageRetentionPeriod:s=345600,maxMessageSize:o=262144,receiveMessageWaitTime:c=0,fifo:l=!1,contentBasedDeduplication:u=!1,encrypted:m=!0,kmsKeyId:p}=e,g=r||A({slug:t,environment:a,resourceType:"queue"}),h=l?`${g}.fifo`:g,y=f(g),b={Type:"AWS::SQS::Queue",Properties:{QueueName:h,DelaySeconds:n,MaximumMessageSize:o,MessageRetentionPeriod:s,ReceiveMessageWaitTimeSeconds:c,VisibilityTimeout:i,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:a}]}};if(l)b.Properties.FifoQueue=!0,b.Properties.ContentBasedDeduplication=u;if(m)if(p)b.Properties.KmsMasterKeyId=p;else b.Properties.SqsManagedSseEnabled=!0;return{queue:b,logicalId:y}}static createDeadLetterQueue(e,t){let{slug:a,environment:r,maxReceiveCount:n=3}=t,i=A({slug:a,environment:r,resourceType:"dlq"}),s=f(i),o={Type:"AWS::SQS::Queue",Properties:{QueueName:i,MessageRetentionPeriod:1209600,Tags:[{Key:"Name",Value:i},{Key:"Environment",Value:r},{Key:"Type",Value:"DeadLetterQueue"}]}},c={Type:"AWS::SQS::Queue",Properties:{RedrivePolicy:{deadLetterTargetArn:C.GetAtt(s,"Arn"),maxReceiveCount:n}}};return{deadLetterQueue:o,updatedSourceQueue:c,deadLetterLogicalId:s}}static createSchedule(e,t){let{slug:a,environment:r,name:n,description:i,enabled:s=!0}=t,o=n||A({slug:a,environment:r,resourceType:"schedule"}),c=f(o);return{rule:{Type:"AWS::Events::Rule",Properties:{Name:o,Description:i,ScheduleExpression:e,State:s?"ENABLED":"DISABLED",Targets:[]}},logicalId:c}}static scheduleEcsTask(e,t,a){let{slug:r,environment:n,name:i,description:s,enabled:o=!0,taskDefinitionArn:c,clusterArn:l,subnets:u,securityGroups:m=[],assignPublicIp:p=!1,taskCount:g=1,containerOverrides:h}=a,y=i||A({slug:r,environment:n,resourceType:"ecs-schedule"}),b=f(y),T={Id:"1",Arn:l,RoleArn:t,EcsParameters:{TaskDefinitionArn:c,TaskCount:g,LaunchType:"FARGATE",NetworkConfiguration:{awsvpcConfiguration:{Subnets:u,SecurityGroups:m,AssignPublicIp:p?"ENABLED":"DISABLED"}},PlatformVersion:"LATEST"}};if(h&&h.length>0)T.Input=JSON.stringify({containerOverrides:h});return{rule:{Type:"AWS::Events::Rule",Properties:{Name:y,Description:s||`Scheduled ECS task: ${c}`,ScheduleExpression:e,State:o?"ENABLED":"DISABLED",Targets:[T]}},logicalId:b}}static scheduleLambda(e,t){let{slug:a,environment:r,name:n,description:i,enabled:s=!0,functionArn:o,input:c}=t,l=n||A({slug:a,environment:r,resourceType:"lambda-schedule"}),u=f(l),m={Id:"1",Arn:o};if(c)m.Input=JSON.stringify(c);return{rule:{Type:"AWS::Events::Rule",Properties:{Name:l,Description:i||`Scheduled Lambda: ${o}`,ScheduleExpression:e,State:s?"ENABLED":"DISABLED",Targets:[m]}},logicalId:u}}static scheduleSqsMessage(e,t){let{slug:a,environment:r,name:n,description:i,enabled:s=!0,queueArn:o,messageGroupId:c}=t,l=n||A({slug:a,environment:r,resourceType:"sqs-schedule"}),u=f(l),m={Id:"1",Arn:o};if(c)m.SqsParameters={MessageGroupId:c};return{rule:{Type:"AWS::Events::Rule",Properties:{Name:l,Description:i||`Scheduled SQS message: ${o}`,ScheduleExpression:e,State:s?"ENABLED":"DISABLED",Targets:[m]}},logicalId:u}}static addTarget(e,t){if(!e.Properties.Targets)e.Properties.Targets=[];let a={Id:t.id,Arn:t.arn};if(t.roleArn)a.RoleArn=t.roleArn;if(t.input)a.Input=JSON.stringify(t.input);return e.Properties.Targets.push(a),e}static toCronExpression(e){if(e.startsWith("cron(")||e.startsWith("rate("))return e;return`cron(${e})`}static rateExpression(e,t){return`rate(${e} ${t})`}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(e){let t=e.toLowerCase().trim(),a=t.match(/^every\s+(\d+)\s+(minute|minutes|hour|hours|day|days)$/i);if(a){let l=parseInt(a[1],10),u=a[2].toLowerCase(),m=u.endsWith("s")&&l===1?u.slice(0,-1):u,p=!u.endsWith("s")&&l>1?`${u}s`:u;return`rate(${l} ${l===1?m:p})`}let r=t.match(/^every\s+(minute|hour|day)$/i);if(r)return`rate(1 ${r[1]})`;let n={"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(n[t])return n[t];let i=t.match(/^daily\s+at\s+(\d{1,2})\s*(am|pm)?$/i);if(i){let l=parseInt(i[1],10),u=i[2]?.toLowerCase();if(u==="pm"&&l!==12)l+=12;else if(u==="am"&&l===12)l=0;return`cron(0 ${l} * * ? *)`}let s=t.match(/^at\s+(\d{1,2}):(\d{2})$/i);if(s){let l=parseInt(s[1],10);return`cron(${parseInt(s[2],10)} ${l} * * ? *)`}let o={monday:"MON",tuesday:"TUE",wednesday:"WED",thursday:"THU",friday:"FRI",saturday:"SAT",sunday:"SUN"},c=t.match(/^every\s+(monday|tuesday|wednesday|thursday|friday|saturday|sunday)$/i);if(c)return`cron(0 0 ? * ${o[c[1].toLowerCase()]} *)`;return ie.toCronExpression(e)}static JobConfig={create:(e)=>{let{name:t,handler:a,retries:r=3,backoff:n="exponential",backoffDelay:i=1000,maxDelay:s=30000,timeout:o=60000,jitter:c=!0}=e;return{name:t,handler:a,retries:r,backoff:n,backoffDelay:i,maxDelay:s,timeout:o,jitter:c}},calculateDelay:(e,t)=>{let{backoff:a,backoffDelay:r,maxDelay:n,jitter:i}=t,s;switch(a){case"linear":s=r*e;break;case"exponential":s=r*2**(e-1);break;case"fixed":default:s=r}if(s=Math.min(s,n||Number.MAX_SAFE_INTEGER),i){let o=s*0.25*Math.random();s+=o}return Math.floor(s)},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(e){let{containerName:t,jobClass:a,jobData:r,environment:n={}}=e,i=[{name:"JOB_CLASS",value:a}];if(r)i.push({name:"JOB_DATA",value:JSON.stringify(r)});for(let[s,o]of Object.entries(n))i.push({name:s,value:o});return{name:t,command:["bun","run","app/Jobs/runner.ts"],environment:i}}static createScheduledJob(e){let{slug:t,environment:a,schedule:r,jobClass:n,jobData:i,taskDefinitionArn:s,clusterArn:o,subnets:c,securityGroups:l=[],roleArn:u,containerName:m="app"}=e,p=ie.rateStringToExpression(r),g=ie.createJobContainerOverride({containerName:m,jobClass:n,jobData:i});return ie.scheduleEcsTask(p,u,{slug:t,environment:a,name:`${t}-${n.toLowerCase().replace(/[^a-z0-9]/g,"-")}`,description:`Scheduled job: ${n}`,taskDefinitionArn:s,clusterArn:o,subnets:c,securityGroups:l,containerOverrides:[g]})}static QueuePresets={highThroughput:(e,t)=>ie.createQueue({slug:e,environment:t,visibilityTimeout:30,receiveMessageWaitTime:0,delaySeconds:0}),longRunning:(e,t)=>ie.createQueue({slug:e,environment:t,visibilityTimeout:300,messageRetentionPeriod:1209600}),fifo:(e,t)=>ie.createQueue({slug:e,environment:t,fifo:!0,contentBasedDeduplication:!0}),delayed:(e,t,a=60)=>ie.createQueue({slug:e,environment:t,delaySeconds:a})}}class Ce{static async discoverJobs(e){let{projectRoot:t,jobsPath:a="app/Jobs"}=e,r=`${t}/${a}`,n=[];try{let i=await import("node:fs"),s=await import("node:path");if(!i.existsSync(r))return[];let o=i.readdirSync(r).filter((c)=>c.endsWith(".ts")&&!c.startsWith("_")&&c!=="runner.ts");for(let c of o){let l=s.join(r,c),u=c.replace(".ts",""),m=i.readFileSync(l,"utf-8"),p=Ce.parseJobMetadata(m,u,l);if(p)n.push(p)}}catch{return[]}return n}static parseJobMetadata(e,t,a){let r=e.match(/export\s + const\s + schedule\s*=\s*['"`]([^'"`]+)['"`]/)||e.match(/schedule:\s*['"`]([^'"`]+)['"`]/),n=e.match(/export\s+const\s+enabled\s*=\s*(true|false)/)||e.match(/enabled:\s*(true|false)/),i=e.match(/export\s+const\s+retries\s*=\s*(\d+)/)||e.match(/retries:\s*(\d+)/),s=e.match(/export\s+const\s+timeout\s*=\s*(\d+)/)||e.match(/timeout:\s*(\d+)/),o=e.match(/export\s+const\s+backoff\s*=\s*['"`](linear|exponential|fixed)['"`]/)||e.match(/backoff:\s*['"`](linear|exponential|fixed)['"`]/),c=e.match(/export\s + const\s + description\s*=\s*['"`]([^'"`]+)['"`]/)||e.match(/description:\s*['"`]([^'"`]+)['"`]/);if(!(e.includes("export async function handle")||e.includes("export function handle")||e.includes("export default")))return null;return{name:t,path:a,schedule:r?.[1],handler:`${t}.handle`,enabled:n?.[1]!=="false",retries:i?parseInt(i[1],10):void 0,backoff:o?.[1],timeout:s?parseInt(s[1],10):void 0,description:c?.[1]}}static async discoverActions(e){let{projectRoot:t,actionsPath:a="app/Actions"}=e,r=`${t}/${a}`,n=[];try{let i=await import("node:fs"),s=await import("node:path");if(!i.existsSync(r))return[];let o=i.readdirSync(r).filter((c)=>c.endsWith(".ts")&&!c.startsWith("_"));for(let c of o){let l=s.join(r,c),u=c.replace(".ts",""),m=i.readFileSync(l,"utf-8"),p=Ce.parseActionMetadata(m,u,l);if(p)n.push(p)}}catch{return[]}return n}static parseActionMetadata(e,t,a){if(!(e.includes("export async function handle")||e.includes("export function handle")||e.includes("export default")))return null;let r=e.match(/export\s + const\s + description\s*=\s*['"`]([^'"`]+)['"`]/)||e.match(/description:\s*['"`]([^'"`]+)['"`]/);return{name:t,path:a,handler:`${t}.handle`,description:r?.[1]}}static generateScheduledJobResources(e){let{slug:t,environment:a,jobs:r,taskDefinitionArn:n,clusterArn:i,subnets:s,securityGroups:o=[],roleArn:c,containerName:l="app"}=e,u={},m=0;for(let p of r){if(!p.schedule||!p.enabled)continue;let{rule:g,logicalId:h}=ie.createScheduledJob({slug:t,environment:a,schedule:p.schedule,jobClass:p.name,taskDefinitionArn:n,clusterArn:i,subnets:s,securityGroups:o,roleArn:c,containerName:l});u[h]=g,m++}return{rules:u,count:m}}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(e){let t=await Te.discoverJobs(e),a=t.filter((r)=>r.schedule&&r.enabled);return{jobs:t,scheduledCount:a.length,totalCount:t.length}}}var Fl={loadJobs:Te.discoverJobs,loadActions:Te.discoverActions,generateScheduledJobs:Te.generateScheduledJobResources,generateRunner:Te.generateJobRunnerScript,paths:{jobs:"app/Jobs",actions:"app/Actions",runner:"app/Jobs/runner.ts"}},Pi=`
1706
+ `}static async generateJobManifest(e){let t=await Ce.discoverJobs(e),a=t.filter((r)=>r.schedule&&r.enabled);return{jobs:t,scheduledCount:a.length,totalCount:t.length}}}var Gl={loadJobs:Ce.discoverJobs,loadActions:Ce.discoverActions,generateScheduledJobs:Ce.generateScheduledJobResources,generateRunner:Ce.generateJobRunnerScript,paths:{jobs:"app/Jobs",actions:"app/Actions",runner:"app/Jobs/runner.ts"}},Ei=`
1707
1707
  const { DynamoDBClient, UpdateItemCommand } = require('@aws-sdk/client-dynamodb');
1708
1708
  const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');
1709
1709
 
@@ -1826,7 +1826,7 @@ catch (error) {
1826
1826
 
1827
1827
  return { statusCode: 200, body: 'OK' };
1828
1828
  };
1829
- `,Ii=`
1829
+ `,Pi=`
1830
1830
  const { DynamoDBClient, PutItemCommand, DeleteItemCommand } = require('@aws-sdk/client-dynamodb');
1831
1831
  const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');
1832
1832
 
@@ -1978,7 +1978,7 @@ catch (error) {
1978
1978
 
1979
1979
  return { statusCode: 200, body: 'OK' };
1980
1980
  };
1981
- `,Ri={};De(Ri,{default:()=>Ni,handler:()=>Qa});var Qa=`
1981
+ `,Ii={};Ne(Ii,{handler:()=>Ja,default:()=>Ri});var Ja=`
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');
@@ -2142,7 +2142,7 @@ function resolveTemplate(template, data) {
2142
2142
  }
2143
2143
  return result;
2144
2144
  }
2145
- `,Ni=`
2145
+ `,Ri=`
2146
2146
  const { PinpointClient, SendMessagesCommand } = require('@aws-sdk/client-pinpoint');
2147
2147
  const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');
2148
2148
  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 z{static LambdaCode={send:Qa,receive:Ii,deliveryStatus:Pi};static createPinpointApp(e){return{[`${e.slug}PinpointApp`]:{Type:"AWS::Pinpoint::App",Properties:{Name:e.name||`${e.slug}-sms`}}}}static createSmsChannel(e){let t={ApplicationId:e.applicationId,Enabled:e.enabled!==!1};if(e.senderId)t.SenderId=e.senderId;if(e.shortCode)t.ShortCode=e.shortCode;return{[`${e.slug}SmsChannel`]:{Type:"AWS::Pinpoint::SMSChannel",Properties:t}}}static createSmsLambdaRole(e){return{[`${e.slug}SmsLambdaRole`]:{Type:"AWS::IAM::Role",Properties:{RoleName:`${e.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(e){return{[`${e.slug}SmsSendLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-sms-send`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:z.LambdaCode.send},Environment:{Variables:{PINPOINT_APP_ID:e.pinpointAppId,MESSAGE_LOG_TABLE:e.messageLogTable||"",SMS_SENDER_ID:e.senderId||"",SMS_ORIGINATION_NUMBER:e.originationNumber||""}}}}}}static createReceiveLambda(e){return{[`${e.slug}SmsReceiveLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-sms-receive`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:z.LambdaCode.receive},Environment:{Variables:{OPT_OUT_TABLE:e.optOutTable||"",MESSAGE_LOG_TABLE:e.messageLogTable||"",NOTIFICATION_TOPIC_ARN:e.notificationTopicArn||"",WEBHOOK_URL:e.webhookUrl||""}}}}}}static createDeliveryStatusLambda(e){return{[`${e.slug}SmsDeliveryStatusLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-sms-delivery-status`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:z.LambdaCode.deliveryStatus},Environment:{Variables:{MESSAGE_LOG_TABLE:e.messageLogTable||"",NOTIFICATION_TOPIC_ARN:e.notificationTopicArn||"",WEBHOOK_URL:e.webhookUrl||""}}}}}}static createMessageLogTable(e){return{[`${e.slug}SmsMessageLogTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-sms-messages`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createOptOutTable(e){return{[`${e.slug}SmsOptOutTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-sms-optouts`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}]}}}}static createNotificationTopic(e){return{[`${e.slug}SmsNotificationTopic`]:{Type:"AWS::SNS::Topic",Properties:{TopicName:`${e.slug}-sms-notifications`}}}}static createCompleteSetup(e){let t={},a={};Object.assign(t,z.createPinpointApp({slug:e.slug})),Object.assign(t,z.createSmsChannel({slug:e.slug,applicationId:{Ref:`${e.slug}PinpointApp`},senderId:e.senderId})),Object.assign(t,z.createSmsLambdaRole({slug:e.slug})),Object.assign(t,z.createMessageLogTable({slug:e.slug})),Object.assign(t,z.createOptOutTable({slug:e.slug})),Object.assign(t,z.createNotificationTopic({slug:e.slug}));let r={"Fn::GetAtt":[`${e.slug}SmsLambdaRole`,"Arn"]},n={Ref:`${e.slug}PinpointApp`},i={Ref:`${e.slug}SmsMessageLogTable`},s={Ref:`${e.slug}SmsOptOutTable`},o={Ref:`${e.slug}SmsNotificationTopic`};if(Object.assign(t,z.createSendLambda({slug:e.slug,roleArn:r,pinpointAppId:n,messageLogTable:i,senderId:e.senderId,originationNumber:e.originationNumber})),e.twoWayEnabled)Object.assign(t,z.createReceiveLambda({slug:e.slug,roleArn:r,optOutTable:s,messageLogTable:i,notificationTopicArn:o,webhookUrl:e.webhookUrl}));return Object.assign(t,z.createDeliveryStatusLambda({slug:e.slug,roleArn:r,messageLogTable:i,notificationTopicArn:o,webhookUrl:e.webhookUrl})),a[`${e.slug}PinpointAppId`]={Description:"Pinpoint application ID",Value:{Ref:`${e.slug}PinpointApp`}},a[`${e.slug}SmsSendLambdaArn`]={Description:"SMS send Lambda ARN",Value:{"Fn::GetAtt":[`${e.slug}SmsSendLambda`,"Arn"]}},a[`${e.slug}SmsNotificationTopicArn`]={Description:"SMS notification topic ARN",Value:{Ref:`${e.slug}SmsNotificationTopic`}},a[`${e.slug}SmsMessageLogTableName`]={Description:"SMS message log table name",Value:{Ref:`${e.slug}SmsMessageLogTable`}},{resources:t,outputs:a}}}function Mt(e){return e.replace(/[^a-zA-Z0-9]/g," ").trim().split(/\s+/).map((t)=>t.charAt(0).toUpperCase()+t.slice(1)).join("")||"User"}function Di(e,t){let a=(e||t).replace(/^\/+|\/+$/g,"");if(!a||a.split("/").includes(".."))throw Error(`sftp: invalid homeDirectory for user ${t}`);return a}function ki(e){let t=e.storage;if(t?.type==="efs"){let r="fileSystemId"in t?t.fileSystemId:void 0;if(!r||typeof r==="string"&&!r.trim())throw Error("sftp: EFS storage requires fileSystemId, or a fileSystem name defined in infrastructure.fileSystem");return{type:"efs",fileSystemId:r,posixProfile:t.posixProfile}}let a=(t?.type==="s3"?t.bucket??e.bucket:e.bucket)?.trim();if(!a)throw Error("sftp: S3 storage requires bucket, or a storageBucket name defined in infrastructure.storage");return{type:"s3",bucket:a}}function $i(e,t,a){let r=t.posixProfile??a;if(!r)throw Error(`sftp: user ${e} requires a posixProfile (uid/gid) on an EFS-backed server`);for(let n of[r.uid,r.gid,...r.secondaryGids??[]])if(!Number.isInteger(n)||n<0||n>4294967295)throw Error(`sftp: user ${e} has an invalid posixProfile id ${n}`);return{Uid:r.uid,Gid:r.gid,...r.secondaryGids?.length?{SecondaryGids:r.secondaryGids}:{}}}function Li(e,t){return typeof e==="string"?`/${e}/${t}`:{"Fn::Sub":[`/\${FileSystemId}/${t}`,{FileSystemId:e}]}}function Mi(e){return typeof e==="string"?{"Fn::Sub":"arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}".replace("${FileSystemId}",e)}:{"Fn::Sub":["arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}",{FileSystemId:e}]}}class xi{static create(e){let t=ki(e),a=t.type==="efs"?"EFS":"S3",r=e.endpointType??"PUBLIC";if(r==="VPC"&&(!e.endpointDetails?.vpcId||!e.endpointDetails.subnetIds.length))throw Error("sftp: VPC endpoints require endpointDetails.vpcId and at least one subnet");let n=`${Mt(e.slug)}${Mt(e.environment)}Sftp`,i=`${n}Server`,s={},o;if(e.logging!==!1){let c=`${n}LoggingRole`;s[c]={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/*"}]}}]}},o={"Fn::GetAtt":[c,"Arn"]}}s[i]={Type:"AWS::Transfer::Server",Properties:{Domain:a,EndpointType:r,IdentityProviderType:"SERVICE_MANAGED",Protocols:["SFTP"],...r==="VPC"?{EndpointDetails:{VpcId:e.endpointDetails.vpcId,SubnetIds:e.endpointDetails.subnetIds,...e.endpointDetails.securityGroupIds?.length?{SecurityGroupIds:e.endpointDetails.securityGroupIds}:{},...e.endpointDetails.addressAllocationIds?.length?{AddressAllocationIds:e.endpointDetails.addressAllocationIds}:{}}}:{},...e.securityPolicyName?{SecurityPolicyName:e.securityPolicyName}:{},...o?{LoggingRole:o}:{},Tags:[{Key:"Project",Value:e.slug},{Key:"Environment",Value:e.environment},{Key:"ManagedBy",Value:"ts-cloud"}]}};for(let[c,l]of Object.entries(e.users)){if(!/^[a-zA-Z0-9_.@-]{3,100}$/.test(c))throw Error(`sftp: invalid username ${c}`);if(!l.sshPublicKeys.length)throw Error(`sftp: user ${c} requires at least one SSH public key`);let u=Mt(c),m=Di(l.homeDirectory,c),p=`${n}${u}User`,g=l.roleArn;if(!g){let h=`${n}${u}Role`,y;if(t.type==="efs")y=[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:DescribeMountTargets"],Resource:Mi(t.fileSystemId)}];else{let b=`arn:aws:s3:::${t.bucket}`;y=[{Effect:"Allow",Action:["s3:ListBucket","s3:GetBucketLocation"],Resource:b,Condition:{StringLike:{"s3:prefix":[m,`${m}/*`]}}},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:GetObjectVersion"],Resource:`${b}/${m}/*`}]}s[h]={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:y}}]}},g={"Fn::GetAtt":[h,"Arn"]}}s[p]={Type:"AWS::Transfer::User",DependsOn:[i],Properties:{ServerId:{Ref:i},UserName:c,Role:g,HomeDirectoryType:"PATH",HomeDirectory:t.type==="efs"?Li(t.fileSystemId,m):`/${t.bucket}/${m}`,...t.type==="efs"?{PosixProfile:$i(c,l,t.posixProfile)}:{},SshPublicKeys:l.sshPublicKeys}}}return{resources:s,serverLogicalId:i,domain:a}}}class pt{static createBedrockRole(e,t){let{slug:a,environment:r,name:n,models:i=["*"],allowStreaming:s=!0}=t,o=n||A({slug:a,environment:r,resourceType:"bedrock-role"}),c=f(o),l=["bedrock:InvokeModel"];if(s)l.push("bedrock:InvokeModelWithResponseStream");let u=i.map((m)=>m==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${m}`);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:o,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:e},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:`${o}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:l,Resource:u}]}}],Tags:[{Key:"Name",Value:o},{Key:"Environment",Value:r}]}},logicalId:c}}static createBedrockPolicy(e){let{slug:t,environment:a,name:r,models:n=["*"],allowInvoke:i=!0,allowStreaming:s=!0,allowAsync:o=!1}=e,c=r||A({slug:t,environment:a,resourceType:"bedrock-policy"}),l=f(c),u=[];if(i)u.push("bedrock:InvokeModel");if(s)u.push("bedrock:InvokeModelWithResponseStream");if(o)u.push("bedrock:InvokeModelAsync");let m=n.map((p)=>p==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${p}`);return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:c,PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"BedrockModelInvocation",Effect:"Allow",Action:u,Resource:m}]}}},logicalId:l}}static enableBedrockForLambda(e){return pt.createBedrockRole("lambda.amazonaws.com",e)}static enableBedrockForEcs(e){return pt.createBedrockRole("ecs-tasks.amazonaws.com",e)}static enableBedrockForEc2(e){return pt.createBedrockRole("ec2.amazonaws.com",e)}static addBedrockPermissions(e,t=["*"],a=!0){let r=["bedrock:InvokeModel"];if(a)r.push("bedrock:InvokeModelWithResponseStream");let n=t.map((i)=>i==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${i}`);if(!e.Properties.Policies)e.Properties.Policies=[];return e.Properties.Policies.push({PolicyName:"bedrock-permissions",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:r,Resource:n}]}}),e}static Models={Claude3_5_Sonnet:"anthropic.claude-3-5-sonnet-20241022-v2:0",Claude3_5_Haiku:"anthropic.claude-3-5-haiku-20241022-v1:0",Claude3_Opus:"anthropic.claude-3-opus-20240229-v1:0",Claude3_Sonnet:"anthropic.claude-3-sonnet-20240229-v1:0",Claude3_Haiku:"anthropic.claude-3-haiku-20240307-v1:0",TitanTextG1Express:"amazon.titan-text-express-v1",TitanTextG1Lite:"amazon.titan-text-lite-v1",TitanEmbedG1Text:"amazon.titan-embed-text-v1",TitanImageG1:"amazon.titan-image-generator-v1",JurassicUltra:"ai21.j2-ultra-v1",JurassicMid:"ai21.j2-mid-v1",CommandText:"cohere.command-text-v14",CommandLight:"cohere.command-light-text-v14",EmbedEnglish:"cohere.embed-english-v3",EmbedMultilingual:"cohere.embed-multilingual-v3",Llama3_2_1B:"meta.llama3-2-1b-instruct-v1:0",Llama3_2_3B:"meta.llama3-2-3b-instruct-v1:0",Llama3_2_11B:"meta.llama3-2-11b-instruct-v1:0",Llama3_2_90B:"meta.llama3-2-90b-instruct-v1:0",Llama3_1_8B:"meta.llama3-1-8b-instruct-v1:0",Llama3_1_70B:"meta.llama3-1-70b-instruct-v1:0",Llama3_1_405B:"meta.llama3-1-405b-instruct-v1:0",Mistral7B:"mistral.mistral-7b-instruct-v0:2",Mixtral8x7B:"mistral.mixtral-8x7b-instruct-v0:1",MistralLarge:"mistral.mistral-large-2402-v1:0",StableDiffusionXL:"stability.stable-diffusion-xl-v1"};static ModelGroups={AllClaude:["anthropic.claude-3-5-sonnet-20241022-v2:0","anthropic.claude-3-5-haiku-20241022-v1:0","anthropic.claude-3-opus-20240229-v1:0","anthropic.claude-3-sonnet-20240229-v1:0","anthropic.claude-3-haiku-20240307-v1:0"],AllTitan:["amazon.titan-text-express-v1","amazon.titan-text-lite-v1","amazon.titan-embed-text-v1","amazon.titan-image-generator-v1"],AllLlama:["meta.llama3-2-1b-instruct-v1:0","meta.llama3-2-3b-instruct-v1:0","meta.llama3-2-11b-instruct-v1:0","meta.llama3-2-90b-instruct-v1:0","meta.llama3-1-8b-instruct-v1:0","meta.llama3-1-70b-instruct-v1:0","meta.llama3-1-405b-instruct-v1:0"],TextModels:["anthropic.claude-3-5-sonnet-20241022-v2:0","anthropic.claude-3-5-haiku-20241022-v1:0","amazon.titan-text-express-v1","meta.llama3-2-11b-instruct-v1:0","mistral.mistral-7b-instruct-v0:2"],EmbeddingModels:["amazon.titan-embed-text-v1","cohere.embed-english-v3","cohere.embed-multilingual-v3"],ImageModels:["amazon.titan-image-generator-v1","stability.stable-diffusion-xl-v1"]}}class Ut{static createPostgres(e){return Ut.createRDSInstance("postgres","16.2",e)}static createMysql(e){return Ut.createRDSInstance("mysql","8.0.35",e)}static createRDSInstance(e,t,a){let{slug:r,environment:n,instanceClass:i="db.t3.micro",allocatedStorage:s=20,storageType:o="gp3",masterUsername:c="admin",masterPassword:l,databaseName:u,subnetIds:m,securityGroupIds:p,encrypted:g=!0,kmsKeyId:h,multiAz:y=!1,backupRetentionDays:b=7,publiclyAccessible:T=!1,enableCloudwatchLogs:w=!0,deletionProtection:S=!0}=a,E=A({slug:r,environment:n,resourceType:`${e}-db`}),v=f(E),P,N;if(m&&m.length>0){let D=A({slug:r,environment:n,resourceType:"db-subnet-group"});N=f(D),P={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupName:D,DBSubnetGroupDescription:`Subnet group for ${E}`,SubnetIds:m,Tags:[{Key:"Name",Value:D},{Key:"Environment",Value:n}]}}}let I={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:E,DBInstanceClass:i,Engine:e,EngineVersion:t,MasterUsername:c,MasterUserPassword:l,AllocatedStorage:s,StorageType:o,StorageEncrypted:g,MultiAZ:y,BackupRetentionPeriod:b,PubliclyAccessible:T,DeletionProtection:S,Tags:[{Key:"Name",Value:E},{Key:"Environment",Value:n}]}};if(u)I.Properties.DBName=u;if(h)I.Properties.KmsKeyId=h;if(N)I.Properties.DBSubnetGroupName=C.Ref(N);if(p&&p.length>0)I.Properties.VPCSecurityGroups=p;if(w)I.Properties.EnableCloudwatchLogsExports=e==="postgres"?["postgresql"]:["error","general","slowquery"];return{dbInstance:I,subnetGroup:P,logicalId:v,subnetGroupId:N}}static createReadReplica(e,t){let{slug:a,environment:r,instanceClass:n="db.t3.micro",securityGroupIds:i,publiclyAccessible:s=!1}=t,o=A({slug:a,environment:r,resourceType:"db-replica"}),c=f(o),l={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:o,DBInstanceClass:n,SourceDBInstanceIdentifier:C.Ref(e),PubliclyAccessible:s,Tags:[{Key:"Name",Value:o},{Key:"Environment",Value:r},{Key:"Type",Value:"ReadReplica"}]}};if(i&&i.length>0)l.Properties.VPCSecurityGroups=i;return{replica:l,logicalId:c}}static createParameterGroup(e,t,a){let{slug:r,environment:n,parameters:i={}}=a,s=A({slug:r,environment:n,resourceType:"db-params"}),o=f(s),c=e==="postgres"?`postgres${t.split(".")[0]}`:`mysql${t.split(".")[0]}.${t.split(".")[1]}`;return{parameterGroup:{Type:"AWS::RDS::DBParameterGroup",Properties:{DBParameterGroupName:s,Description:`Parameter group for ${s}`,Family:c,Parameters:i,Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:n}]}},logicalId:o}}static enableBackup(e,t=7){return e.Properties.BackupRetentionPeriod=t,e}static createTable(e){let{slug:t,environment:a,tableName:r,partitionKey:n,sortKey:i,billingMode:s="PAY_PER_REQUEST",readCapacity:o=5,writeCapacity:c=5,streamEnabled:l=!1,streamViewType:u="NEW_AND_OLD_IMAGES",encrypted:m=!0,kmsKeyId:p,pointInTimeRecovery:g=!0,ttlAttribute:h}=e,y=r||A({slug:t,environment:a,resourceType:"table"}),b=f(y),T=[{AttributeName:n.name,AttributeType:n.type}];if(i)T.push({AttributeName:i.name,AttributeType:i.type});let w=[{AttributeName:n.name,KeyType:"HASH"}];if(i)w.push({AttributeName:i.name,KeyType:"RANGE"});let S={Type:"AWS::DynamoDB::Table",Properties:{TableName:y,BillingMode:s,AttributeDefinitions:T,KeySchema:w,Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:a}]}};if(s==="PROVISIONED")S.Properties.ProvisionedThroughput={ReadCapacityUnits:o,WriteCapacityUnits:c};if(l)S.Properties.StreamSpecification={StreamViewType:u};if(m)S.Properties.SSESpecification={SSEEnabled:!0,SSEType:p?"KMS":"AES256",KMSMasterKeyId:p};if(g)S.Properties.PointInTimeRecoverySpecification={PointInTimeRecoveryEnabled:!0};if(h)S.Properties.TimeToLiveSpecification={AttributeName:h,Enabled:!0};return{table:S,logicalId:b}}static addGlobalSecondaryIndex(e,t){let{indexName:a,partitionKey:r,sortKey:n,projectionType:i="ALL",nonKeyAttributes:s,readCapacity:o=5,writeCapacity:c=5}=t;if(!e.Properties.AttributeDefinitions.some((m)=>m.AttributeName===r.name))e.Properties.AttributeDefinitions.push({AttributeName:r.name,AttributeType:r.type});if(n&&!e.Properties.AttributeDefinitions.some((m)=>m.AttributeName===n.name))e.Properties.AttributeDefinitions.push({AttributeName:n.name,AttributeType:n.type});let l=[{AttributeName:r.name,KeyType:"HASH"}];if(n)l.push({AttributeName:n.name,KeyType:"RANGE"});let u={IndexName:a,KeySchema:l,Projection:{ProjectionType:i,NonKeyAttributes:i==="INCLUDE"?s:void 0},ProvisionedThroughput:void 0};if(e.Properties.BillingMode==="PROVISIONED")u.ProvisionedThroughput={ReadCapacityUnits:o,WriteCapacityUnits:c};if(!e.Properties.GlobalSecondaryIndexes)e.Properties.GlobalSecondaryIndexes=[];return e.Properties.GlobalSecondaryIndexes.push(u),e}static enableStreams(e,t="NEW_AND_OLD_IMAGES"){return e.Properties.StreamSpecification={StreamViewType:t},e}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 Oi{static createRedis(e){let{slug:t,environment:a,nodeType:r="cache.t3.micro",engineVersion:n="7.1",port:i=6379,subnetIds:s,securityGroupIds:o,numCacheClusters:c=2,automaticFailover:l=!0,multiAz:u=!0,clusterMode:m=!1,numNodeGroups:p=1,replicasPerNodeGroup:g=1,atRestEncryption:h=!0,transitEncryption:y=!0,authToken:b,kmsKeyId:T,snapshotRetentionDays:w=7,snapshotWindow:S,maintenanceWindow:E}=e,v=A({slug:t,environment:a,resourceType:"redis"}),P=f(v),N,I;if(s&&s.length>0){let L=A({slug:t,environment:a,resourceType:"cache-subnet-group"});I=f(L),N={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:L,Description:`Subnet group for ${v}`,SubnetIds:s,Tags:[{Key:"Name",Value:L},{Key:"Environment",Value:a}]}}}let D={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:v,ReplicationGroupDescription:`Redis cluster for ${t} ${a}`,Engine:"redis",EngineVersion:n,CacheNodeType:r,Port:i,AutomaticFailoverEnabled:l,MultiAZEnabled:u,AtRestEncryptionEnabled:h,TransitEncryptionEnabled:y,SnapshotRetentionLimit:w,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:v},{Key:"Environment",Value:a}]}};if(m)D.Properties.NumNodeGroups=p,D.Properties.ReplicasPerNodeGroup=g;else D.Properties.NumCacheClusters=c;if(b)D.Properties.AuthToken=b;if(T)D.Properties.KmsKeyId=T;if(I)D.Properties.CacheSubnetGroupName=C.Ref(I);if(o&&o.length>0)D.Properties.SecurityGroupIds=o;if(S)D.Properties.SnapshotWindow=S;if(E)D.Properties.PreferredMaintenanceWindow=E;return{replicationGroup:D,subnetGroup:N,logicalId:P,subnetGroupId:I}}static createMemcached(e){let{slug:t,environment:a,nodeType:r="cache.t3.micro",engineVersion:n="1.6.22",port:i=11211,numCacheNodes:s=2,subnetIds:o,securityGroupIds:c,azMode:l="cross-az",preferredAzs:u,maintenanceWindow:m}=e,p=A({slug:t,environment:a,resourceType:"memcached"}),g=f(p),h,y;if(o&&o.length>0){let T=A({slug:t,environment:a,resourceType:"cache-subnet-group"});y=f(T),h={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:T,Description:`Subnet group for ${p}`,SubnetIds:o,Tags:[{Key:"Name",Value:T},{Key:"Environment",Value:a}]}}}let b={Type:"AWS::ElastiCache::CacheCluster",Properties:{ClusterName:p,CacheNodeType:r,Engine:"memcached",EngineVersion:n,NumCacheNodes:s,Port:i,AZMode:l,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:p},{Key:"Environment",Value:a}]}};if(y)b.Properties.CacheSubnetGroupName=C.Ref(y);if(c&&c.length>0)b.Properties.VpcSecurityGroupIds=c;if(u&&u.length>0)b.Properties.PreferredAvailabilityZones=u;if(m)b.Properties.PreferredMaintenanceWindow=m;return{cluster:b,subnetGroup:h,logicalId:g,subnetGroupId:y}}static enableClusterMode(e,t=3,a=2){return delete e.Properties.NumCacheClusters,e.Properties.NumNodeGroups=t,e.Properties.ReplicasPerNodeGroup=a,e}static createRedisParameterGroup(e,t){let{slug:a,environment:r,parameters:n={}}=t,i=A({slug:a,environment:r,resourceType:"redis-params"}),s=f(i);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`redis${e.split(".")[0]}.x`,Description:`Parameter group for ${i}`,Properties:n,Tags:[{Key:"Name",Value:i},{Key:"Environment",Value:r}]}},logicalId:s}}static createMemcachedParameterGroup(e,t){let{slug:a,environment:r,parameters:n={}}=t,i=A({slug:a,environment:r,resourceType:"memcached-params"}),s=f(i);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`memcached${e.split(".")[0]}.${e.split(".")[1]}`,Description:`Parameter group for ${i}`,Properties:n,Tags:[{Key:"Name",Value:i},{Key:"Environment",Value:r}]}},logicalId:s}}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 ie{static createUser(e){let{slug:t,environment:a,userName:r,groups:n,managedPolicyArns:i}=e,s=r||A({slug:t,environment:a,resourceType:"user"}),o=f(s),c={Type:"AWS::IAM::User",Properties:{UserName:s,Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:a}]}};if(n&&n.length>0)c.Properties.Groups=n;if(i&&i.length>0)c.Properties.ManagedPolicyArns=i;return{user:c,logicalId:o}}static createRole(e){let{slug:t,environment:a,roleName:r,servicePrincipal:n,awsPrincipal:i,managedPolicyArns:s}=e,o=r||A({slug:t,environment:a,resourceType:"role"}),c=f(o),l={};if(n)l.Service=n;if(i)l.AWS=i;let u={Type:"AWS::IAM::Role",Properties:{RoleName:o,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:l,Action:"sts:AssumeRole"}]},Tags:[{Key:"Name",Value:o},{Key:"Environment",Value:a}]}};if(s&&s.length>0)u.Properties.ManagedPolicyArns=s;return{role:u,logicalId:c}}static createGroup(e){let{slug:t,environment:a,groupName:r,managedPolicyArns:n}=e,i=r||A({slug:t,environment:a,resourceType:"group"}),s=f(i),o={Type:"AWS::IAM::Group",Properties:{GroupName:i}};if(n&&n.length>0)o.Properties.ManagedPolicyArns=n;return{group:o,logicalId:s}}static createPolicy(e){let{slug:t,environment:a,policyName:r,description:n,statements:i}=e,s=r||A({slug:t,environment:a,resourceType:"policy"}),o=f(s),c=i.map((l)=>({Sid:l.sid,Effect:l.effect||"Allow",Action:l.actions,Resource:l.resources,Condition:l.conditions}));return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:s,Description:n||`Managed policy for ${s}`,PolicyDocument:{Version:"2012-10-17",Statement:c}}},logicalId:o}}static attachPolicyToRole(e,t){if(!e.Properties.ManagedPolicyArns)e.Properties.ManagedPolicyArns=[];if(!e.Properties.ManagedPolicyArns.includes(t))e.Properties.ManagedPolicyArns.push(t);return e}static attachPolicyToUser(e,t){if(!e.Properties.ManagedPolicyArns)e.Properties.ManagedPolicyArns=[];if(!e.Properties.ManagedPolicyArns.includes(t))e.Properties.ManagedPolicyArns.push(t);return e}static attachPolicyToGroup(e,t){if(!e.Properties.ManagedPolicyArns)e.Properties.ManagedPolicyArns=[];if(!e.Properties.ManagedPolicyArns.includes(t))e.Properties.ManagedPolicyArns.push(t);return e}static addInlinePolicyToRole(e,t,a){if(!e.Properties.Policies)e.Properties.Policies=[];let r=a.map((n)=>({Effect:n.effect||"Allow",Action:n.actions,Resource:n.resources}));return e.Properties.Policies.push({PolicyName:t,PolicyDocument:{Version:"2012-10-17",Statement:r}}),e}static addInlinePolicyToUser(e,t,a){if(!e.Properties.Policies)e.Properties.Policies=[];let r=a.map((n)=>({Effect:n.effect||"Allow",Action:n.actions,Resource:n.resources}));return e.Properties.Policies.push({PolicyName:t,PolicyDocument:{Version:"2012-10-17",Statement:r}}),e}static createAccessKey(e,t){let{slug:a,environment:r,status:n="Active"}=t,i=A({slug:a,environment:r,resourceType:"access-key"}),s=f(i);return{accessKey:{Type:"AWS::IAM::AccessKey",Properties:{UserName:C.Ref(e),Status:n}},logicalId:s}}static createInstanceProfile(e,t){let{slug:a,environment:r,profileName:n}=t,i=n||A({slug:a,environment:r,resourceType:"instance-profile"}),s=f(i);return{instanceProfile:{Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:i,Roles:[C.Ref(e)]}},logicalId:s}}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(e){let{slug:t,environment:a,permissions:r,createAccessKey:n=!0}=e,i={},s=[];if(r.s3Buckets&&r.s3Buckets.length>0)s.push({sid:"S3Access",actions:["s3:GetBucketLocation","s3:ListBucket","s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucketMultipartUploads","s3:AbortMultipartUpload"],resources:[...r.s3Buckets,...r.s3Buckets.map((g)=>`${g}/*`)]});if(r.cloudFrontDistributions&&r.cloudFrontDistributions.length>0)s.push({sid:"CloudFrontAccess",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations","cloudfront:GetDistribution"],resources:r.cloudFrontDistributions});if(r.ecrRepositories&&r.ecrRepositories.length>0)s.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:r.ecrRepositories}),s.push({sid:"ECRLogin",actions:["ecr:GetAuthorizationToken"],resources:"*"});if(r.ecsServices&&r.ecsServices.length>0)s.push({sid:"ECSAccess",actions:["ecs:DescribeServices","ecs:DescribeTaskDefinition","ecs:DescribeTasks","ecs:ListTasks","ecs:RegisterTaskDefinition","ecs:UpdateService","ecs:RunTask","ecs:StopTask"],resources:r.ecsServices}),s.push({sid:"ECSTaskDefinitions",actions:["ecs:RegisterTaskDefinition","ecs:DeregisterTaskDefinition"],resources:"*"}),s.push({sid:"ECSPassRole",actions:["iam:PassRole"],resources:"*",conditions:{StringLike:{"iam:PassedToService":"ecs-tasks.amazonaws.com"}}});if(r.cloudFormationStacks&&r.cloudFormationStacks.length>0)s.push({sid:"CloudFormationAccess",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:DescribeStackResources","cloudformation:GetTemplate","cloudformation:ListStackResources","cloudformation:ValidateTemplate"],resources:r.cloudFormationStacks});if(r.lambdaFunctions&&r.lambdaFunctions.length>0)s.push({sid:"LambdaAccess",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion","lambda:UpdateAlias","lambda:CreateAlias"],resources:r.lambdaFunctions});if(r.secretsManagerSecrets&&r.secretsManagerSecrets.length>0)s.push({sid:"SecretsManagerAccess",actions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],resources:r.secretsManagerSecrets});let{policy:o,logicalId:c}=ie.createPolicy({slug:t,environment:a,policyName:A({slug:t,environment:a,resourceType:"cicd-policy"}),description:`CI/CD deployment policy for ${t} (${a})`,statements:s});i[c]=o;let{user:l,logicalId:u}=ie.createUser({slug:t,environment:a,userName:A({slug:t,environment:a,resourceType:"cicd-user"}),managedPolicyArns:[C.Ref(c)]});i[u]=l;let m,p;if(n){let g=ie.createAccessKey(u,{slug:t,environment:a});m=g.accessKey,p=g.logicalId,i[p]=m}return{user:l,accessKey:m,policy:o,userLogicalId:u,accessKeyLogicalId:p,policyLogicalId:c,resources:i}}static createCrossAccountRole(e){let{slug:t,environment:a,trustedAccountIds:r,externalId:n,permissions:i,maxSessionDuration:s=3600}=e,o={},{policy:c,logicalId:l}=ie.createPolicy({slug:t,environment:a,policyName:A({slug:t,environment:a,resourceType:"cross-account-policy"}),description:`Cross-account access policy for ${t} (${a})`,statements:i});o[l]=c;let u=A({slug:t,environment:a,resourceType:"cross-account-role"}),m=f(u),p={};if(n)p.StringEquals={"sts:ExternalId":n};let g={Type:"AWS::IAM::Role",Properties:{RoleName:u,MaxSessionDuration:s,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:r.map((h)=>`arn:aws:iam::${h}:root`)},Action:"sts:AssumeRole",...Object.keys(p).length>0?{Condition:p}:{}}]},ManagedPolicyArns:[C.Ref(l)],Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:a},{Key:"Purpose",Value:"Cross-Account Access"}]}};return o[m]=g,{role:g,policy:c,roleLogicalId:m,policyLogicalId:l,resources:o}}static createCliUser(e){let{slug:t,environment:a,permissions:r="readonly"}=e,n={},i=[],s=[];switch(r){case"readonly":s=[ie.ManagedPolicies.ReadOnlyAccess];break;case"deploy":i=[{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":s=[ie.ManagedPolicies.AdministratorAccess];break}let o,c;if(i.length>0){let g=ie.createPolicy({slug:t,environment:a,policyName:A({slug:t,environment:a,resourceType:"cli-policy"}),description:`CLI access policy for ${t} (${a})`,statements:i});o=g.policy,c=g.logicalId,n[c]=o,s=[C.Ref(c)]}let{user:l,logicalId:u}=ie.createUser({slug:t,environment:a,userName:A({slug:t,environment:a,resourceType:"cli-user"}),managedPolicyArns:s});n[u]=l;let{accessKey:m,logicalId:p}=ie.createAccessKey(u,{slug:t,environment:a});return n[p]=m,{user:l,accessKey:m,policy:o,userLogicalId:u,accessKeyLogicalId:p,policyLogicalId:c,resources:n}}static CiCdPolicies={s3Deployment:(e)=>[{sid:"S3ListBuckets",actions:["s3:ListBucket","s3:GetBucketLocation"],resources:e},{sid:"S3Objects",actions:["s3:GetObject","s3:PutObject","s3:DeleteObject"],resources:e.map((t)=>`${t}/*`)}],cloudFrontInvalidation:(e)=>[{sid:"CloudFrontInvalidation",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations"],resources:e}],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:(e)=>[{sid:"ECRAuth",actions:["ecr:GetAuthorizationToken"],resources:"*"},{sid:"ECRPush",actions:["ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:PutImage"],resources:e}],lambdaDeployment:(e)=>[{sid:"LambdaDeploy",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion"],resources:e}],cloudFormationDeployment:(e)=>[{sid:"CloudFormationDeploy",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate"],resources:e}]}}class Bi{static createRestApi(e){let{slug:t,environment:a,name:r,description:n,endpointType:i="REGIONAL",binaryMediaTypes:s,compressionSize:o}=e,c=r||A({slug:t,environment:a,resourceType:"rest-api"}),l=f(c),u={Type:"AWS::ApiGateway::RestApi",Properties:{Name:c,Description:n||`REST API for ${t} ${a}`,EndpointConfiguration:{Types:[i]},Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:a}]}};if(s&&s.length>0)u.Properties.BinaryMediaTypes=s;if(o!==void 0)u.Properties.MinimumCompressionSize=o;return{restApi:u,logicalId:l}}static createHttpApi(e){let{slug:t,environment:a,name:r,description:n,corsEnabled:i=!0,corsOrigins:s=["*"],corsMethods:o=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],corsHeaders:c=["*"],corsMaxAge:l=86400,corsAllowCredentials:u=!1}=e,m=r||A({slug:t,environment:a,resourceType:"http-api"}),p=f(m),g={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:m,Description:n||`HTTP API for ${t} ${a}`,ProtocolType:"HTTP",Tags:{Name:m,Environment:a}}};if(i)g.Properties.CorsConfiguration={AllowOrigins:s,AllowMethods:o,AllowHeaders:c,MaxAge:l,AllowCredentials:u};return{httpApi:g,logicalId:p}}static createWebSocketApi(e){let{slug:t,environment:a,name:r,description:n}=e,i=r||A({slug:t,environment:a,resourceType:"ws-api"}),s=f(i);return{webSocketApi:{Type:"AWS::ApiGatewayV2::Api",Properties:{Name:i,Description:n||`WebSocket API for ${t} ${a}`,ProtocolType:"WEBSOCKET",Tags:{Name:i,Environment:a}}},logicalId:s}}static createDeployment(e,t){let{slug:a,environment:r,description:n}=t,i=A({slug:a,environment:r,resourceType:"api-deployment"}),s=f(i);return{deployment:{Type:"AWS::ApiGateway::Deployment",Properties:{RestApiId:C.Ref(e),Description:n||`Deployment for ${i}`}},logicalId:s}}static createStage(e,t,a){let{slug:r,environment:n,stageName:i,description:s,cacheEnabled:o=!1,cacheSize:c="0.5",variables:l,throttling:u}=a,m=A({slug:r,environment:n,resourceType:"api-stage"}),p=f(m),g={Type:"AWS::ApiGateway::Stage",Properties:{StageName:i||n,RestApiId:C.Ref(e),DeploymentId:C.Ref(t),Description:s,CacheClusterEnabled:o,Tags:[{Key:"Name",Value:m},{Key:"Environment",Value:n}]}};if(o)g.Properties.CacheClusterSize=c;if(l)g.Properties.Variables=l;if(u)g.Properties.MethodSettings=[{HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:u.burstLimit,ThrottlingRateLimit:u.rateLimit}];return{stage:g,logicalId:p}}static createAuthorizer(e,t){let{slug:a,environment:r,name:n,type:i,functionArn:s,identitySource:o,userPoolArns:c,ttl:l=300}=t,u=n||A({slug:a,environment:r,resourceType:"api-authorizer"}),m=f(u),p={Type:"AWS::ApiGateway::Authorizer",Properties:{Name:u,Type:i,RestApiId:C.Ref(e),AuthorizerResultTtlInSeconds:l}};if(i==="TOKEN"||i==="REQUEST"){if(!s)throw Error("Lambda authorizer requires functionArn");p.Properties.AuthorizerUri=s,p.Properties.IdentitySource=o||"method.request.header.Authorization"}if(i==="COGNITO_USER_POOLS"){if(!c||c.length===0)throw Error("Cognito authorizer requires userPoolArns");p.Properties.ProviderARNs=c,p.Properties.IdentitySource=o||"method.request.header.Authorization"}return{authorizer:p,logicalId:m}}static setCors(e,t={}){let{origins:a=["*"],methods:r=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],headers:n=["*"],maxAge:i=86400,allowCredentials:s=!1}=t;return e.Properties.CorsConfiguration={AllowOrigins:a,AllowMethods:r,AllowHeaders:n,MaxAge:i,AllowCredentials:s},e}static addThrottling(e,t=5000,a=1e4){if(!e.Properties.MethodSettings)e.Properties.MethodSettings=[];return e.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:t,ThrottlingRateLimit:a}),e}static enableCaching(e,t="0.5",a=300){if(e.Properties.CacheClusterEnabled=!0,e.Properties.CacheClusterSize=t,!e.Properties.MethodSettings)e.Properties.MethodSettings=[];return e.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",CachingEnabled:!0,CacheTtlInSeconds:a}),e}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(e){let{slug:t,environment:a,topicName:r,displayName:n,encrypted:i=!1,kmsKeyId:s}=e,o=r||A({slug:t,environment:a,resourceType:"topic"}),c=f(o),l={Type:"AWS::SNS::Topic",Properties:{TopicName:o,DisplayName:n||o,Tags:[{Key:"Name",Value:o},{Key:"Environment",Value:a}]}};if(i&&s)l.Properties.KmsMasterKeyId=s;return{topic:l,logicalId:c}}static subscribe(e,t){let{slug:a,environment:r,protocol:n,endpoint:i,filterPolicy:s,rawMessageDelivery:o=!1}=t,c=A({slug:a,environment:r,resourceType:"subscription"}),l=i.replace(/[^a-zA-Z0-9]/g,""),u=l.length>12?l.slice(-12):l,m=f(`${c}-${n}-${u}`),p={Type:"AWS::SNS::Subscription",Properties:{TopicArn:C.Ref(e),Protocol:n,Endpoint:i,RawMessageDelivery:o}};if(s)p.Properties.FilterPolicy=s;return{subscription:p,logicalId:m}}static subscribeEmail(e,t,a){return ee.subscribe(e,{...a,protocol:"email",endpoint:t})}static subscribeLambda(e,t,a){return ee.subscribe(e,{...a,protocol:"lambda",endpoint:t,rawMessageDelivery:!0})}static subscribeSqs(e,t,a){return ee.subscribe(e,{...a,protocol:"sqs",endpoint:t})}static subscribeHttp(e,t,a){let r=t.startsWith("https://")?"https":"http";return ee.subscribe(e,{...a,protocol:r,endpoint:t})}static subscribeSms(e,t,a){return ee.subscribe(e,{...a,protocol:"sms",endpoint:t})}static setTopicPolicy(e,t){let{slug:a,environment:r,allowedPrincipals:n,allowedServices:i,actions:s="SNS:Publish"}=t,o=A({slug:a,environment:r,resourceType:"topic-policy"}),c=f(o),l={};if(n)l.AWS=n;if(i)l.Service=i;return{policy:{Type:"AWS::SNS::TopicPolicy",Properties:{Topics:[C.Ref(e)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:l,Action:s,Resource:C.Ref(e)}]}}},logicalId:c}}static allowCloudWatchAlarms(e,t){return ee.setTopicPolicy(e,{...t,allowedServices:"cloudwatch.amazonaws.com",actions:"SNS:Publish"})}static allowEventBridge(e,t){return ee.setTopicPolicy(e,{...t,allowedServices:"events.amazonaws.com",actions:"SNS:Publish"})}static allowS3(e,t){return ee.setTopicPolicy(e,{...t,allowedServices:"s3.amazonaws.com",actions:"SNS:Publish"})}static enableEncryption(e,t){if(!e.Properties)e.Properties={};return e.Properties.KmsMasterKeyId=t,e}static addInlineSubscription(e,t,a){if(!e.Properties)e.Properties={};if(!e.Properties.Subscription)e.Properties.Subscription=[];return e.Properties.Subscription.push({Protocol:t,Endpoint:a}),e}static FilterPolicies={eventType:(e)=>({eventType:e}),status:(e)=>({status:e}),numericRange:(e,t,a)=>({[e]:[{numeric:[">=",t,"<=",a]}]}),prefix:(e,t)=>({[e]:[{prefix:t}]}),and:(...e)=>Object.assign({},...e),exists:(e,t)=>({[e]:[{exists:t}]})};static UseCases={createAlertTopic:(e)=>ee.createTopic({...e,topicName:e.topicName||`${e.slug}-${e.environment}-alerts`,displayName:e.displayName||"Alert Notifications"}),createEventFanout:(e)=>ee.createTopic({...e,topicName:e.topicName||`${e.slug}-${e.environment}-events`,displayName:e.displayName||"Event Fanout"}),createNotificationTopic:(e)=>ee.createTopic({...e,topicName:e.topicName||`${e.slug}-${e.environment}-notifications`,displayName:e.displayName||"User Notifications"})}}class _i{static createStateMachine(e){let{slug:t,environment:a,stateMachineName:r,type:n="STANDARD",definition:i,roleArn:s,loggingConfiguration:o,tracingConfiguration:c}=e,l=r||A({slug:t,environment:a,resourceType:"state-machine"}),u=f(l),m,p,g;if(s)g=s;else{let y=A({slug:t,environment:a,resourceType:"state-machine-role"});p=f(y),m={Type:"AWS::IAM::Role",Properties:{RoleName:y,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:y},{Key:"Environment",Value:a}]}},g=C.GetAtt(p,"Arn")}let h={Type:"AWS::StepFunctions::StateMachine",Properties:{StateMachineName:l,StateMachineType:n,DefinitionString:JSON.stringify(i),RoleArn:g,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:a}]}};if(o)h.Properties.LoggingConfiguration={Level:o.level,IncludeExecutionData:o.includeExecutionData,Destinations:o.destinations?.map((y)=>({CloudWatchLogsLogGroup:{LogGroupArn:y}}))};if(c)h.Properties.TracingConfiguration={Enabled:c.enabled};return{stateMachine:h,logicalId:u,role:m,roleLogicalId:p}}static createLambdaTask(e,t){return{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Parameters:{FunctionName:e,Payload:t?.parameters||{"Input.$":"$"}},ResultPath:t?.resultPath,Retry:t?.retry,Catch:t?.catch,Next:t?.next,End:t?.end}}static createDynamoDBTask(e,t,a,r){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"}[e],Parameters:{TableName:t,...a},ResultPath:r?.resultPath,Retry:r?.retry,Catch:r?.catch,Next:r?.next,End:r?.end}}static createSNSPublishTask(e,t,a){return{Type:"Task",Resource:"arn:aws:states:::sns:publish",Parameters:{TopicArn:e,Message:t},ResultPath:a?.resultPath,Retry:a?.retry,Catch:a?.catch,Next:a?.next,End:a?.end}}static createSQSSendMessageTask(e,t,a){return{Type:"Task",Resource:"arn:aws:states:::sqs:sendMessage",Parameters:{QueueUrl:e,MessageBody:t},ResultPath:a?.resultPath,Retry:a?.retry,Catch:a?.catch,Next:a?.next,End:a?.end}}static createPassState(e){return{Type:"Pass",Result:e?.result,ResultPath:e?.resultPath,Parameters:e?.parameters,Next:e?.next,End:e?.end}}static createWaitState(e){return{Type:"Wait",Seconds:e.seconds,Timestamp:e.timestamp,SecondsPath:e.secondsPath,TimestampPath:e.timestampPath,Next:e.next,End:e.end}}static createChoiceState(e,t){return{Type:"Choice",Choices:e,Default:t}}static createParallelState(e,t){return{Type:"Parallel",Branches:e,ResultPath:t?.resultPath,Retry:t?.retry,Catch:t?.catch,Next:t?.next,End:t?.end}}static createMapState(e,t){return{Type:"Map",ItemsPath:t?.itemsPath||"$.items",Iterator:e,MaxConcurrency:t?.maxConcurrency,ResultPath:t?.resultPath,Retry:t?.retry,Catch:t?.catch,Next:t?.next,End:t?.end}}static createSucceedState(){return{Type:"Succeed"}}static createFailState(e,t){return{Type:"Fail",Error:e,Cause:t}}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:(e,t,a,r)=>({ErrorEquals:e,IntervalSeconds:t,MaxAttempts:a,BackoffRate:r})};static CatchPolicies={all:(e,t)=>({ErrorEquals:["States.ALL"],Next:e,ResultPath:t||"$.error"}),specific:(e,t,a)=>({ErrorEquals:e,Next:t,ResultPath:a||"$.error"})};static Patterns={sequential:(e,t,a)=>{let r={};return a.forEach((n,i)=>{let s=i===a.length-1;r[n.name]={...n.state,Next:s?void 0:a[i+1].name,End:s}}),{Comment:"Sequential workflow",StartAt:a[0].name,States:r}},fanout:(e,t,a)=>({Comment:"Fan-out workflow",StartAt:"Parallel",States:{Parallel:{Type:"Parallel",Branches:a.map((r)=>r.definition),End:!0}}}),map:(e,t,a,r)=>({Comment:"Map workflow",StartAt:"Map",States:{Map:{Type:"Map",ItemsPath:"$.items",Iterator:a,MaxConcurrency:r,End:!0}}}),withErrorHandling:(e,t,a,r)=>({Comment:"Workflow with error handling",StartAt:"Main",States:{Main:{...a,Catch:[{ErrorEquals:["States.ALL"],Next:"ErrorHandler"}],Next:"Success"},ErrorHandler:r,Success:{Type:"Succeed"}}})}}class Ja{static createAlarm(e){let{slug:t,environment:a,alarmName:r,metricName:n,namespace:i,statistic:s="Average",period:o=300,evaluationPeriods:c=1,threshold:l,comparisonOperator:u,treatMissingData:m="notBreaching",actionsEnabled:p=!0,alarmActions:g,okActions:h,insufficientDataActions:y,dimensions:b,unit:T,datapointsToAlarm:w}=e,S=r||A({slug:t,environment:a,resourceType:"alarm"}),E=f(S),v={Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:S,MetricName:n,Namespace:i,Statistic:s,Period:o,EvaluationPeriods:c,Threshold:l,ComparisonOperator:u,TreatMissingData:m,ActionsEnabled:p}};if(g&&g.length>0)v.Properties.AlarmActions=g;if(h&&h.length>0)v.Properties.OKActions=h;if(y&&y.length>0)v.Properties.InsufficientDataActions=y;if(b)v.Properties.Dimensions=Object.entries(b).map(([P,N])=>({Name:P,Value:N}));if(T)v.Properties.Unit=T;if(w!==void 0)v.Properties.DatapointsToAlarm=w;return{alarm:v,logicalId:E}}static createCompositeAlarm(e){let{slug:t,environment:a,alarmName:r,alarmRule:n,actionsEnabled:i=!0,alarmActions:s,okActions:o,insufficientDataActions:c}=e,l=r||A({slug:t,environment:a,resourceType:"composite-alarm"}),u=f(l),m={Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:l,AlarmRule:n,ActionsEnabled:i}};if(s&&s.length>0)m.Properties.AlarmActions=s;if(o&&o.length>0)m.Properties.OKActions=o;if(c&&c.length>0)m.Properties.InsufficientDataActions=c;return{alarm:m,logicalId:u}}static createDashboard(e){let{slug:t,environment:a,dashboardName:r,widgets:n}=e,i=r||A({slug:t,environment:a,resourceType:"dashboard"}),s=f(i),o={widgets:n.map((c)=>({type:c.type,x:c.x,y:c.y,width:c.width,height:c.height,properties:c.properties}))};return{dashboard:{Type:"AWS::CloudWatch::Dashboard",Properties:{DashboardName:i,DashboardBody:JSON.stringify(o)}},logicalId:s}}static createLogGroup(e){let{slug:t,environment:a,logGroupName:r,retentionInDays:n,kmsKeyId:i}=e,s=r||A({slug:t,environment:a,resourceType:"log-group"}),o=f(s),c={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:s}};if(n!==void 0)c.Properties.RetentionInDays=n;if(i)c.Properties.KmsKeyId=i;return{logGroup:c,logicalId:o}}static createLogStream(e,t){let{slug:a,environment:r,logStreamName:n}=t,i=n||A({slug:a,environment:r,resourceType:"log-stream"}),s=f(i);return{logStream:{Type:"AWS::Logs::LogStream",Properties:{LogGroupName:C.Ref(e),LogStreamName:i}},logicalId:s}}static createMetricFilter(e,t){let{slug:a,environment:r,filterName:n,filterPattern:i,metricTransformations:s}=t,o=n||A({slug:a,environment:r,resourceType:"metric-filter"}),c=f(o);return{metricFilter:{Type:"AWS::Logs::MetricFilter",Properties:{LogGroupName:C.Ref(e),FilterPattern:i,MetricTransformations:s.map((l)=>({MetricName:l.metricName,MetricNamespace:l.metricNamespace,MetricValue:l.metricValue,DefaultValue:l.defaultValue,Unit:l.unit}))}},logicalId:c}}static AlarmTypes={highCpu:(e,t,a,r=80,n)=>({slug:e,environment:t,alarmName:`${e}-${t}-high-cpu`,metricName:"CPUUtilization",namespace:"AWS/EC2",statistic:"Average",period:300,evaluationPeriods:2,threshold:r,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:a},alarmActions:n?[n]:void 0}),highMemory:(e,t,a,r=80,n)=>({slug:e,environment:t,alarmName:`${e}-${t}-high-memory`,metricName:"MemoryUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:r,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:a},alarmActions:n?[n]:void 0}),highDisk:(e,t,a,r=80,n)=>({slug:e,environment:t,alarmName:`${e}-${t}-high-disk`,metricName:"DiskSpaceUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:r,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:a,Filesystem:"/dev/xvda1",MountPath:"/"},alarmActions:n?[n]:void 0}),lambdaErrors:(e,t,a,r=5,n)=>({slug:e,environment:t,alarmName:`${e}-${t}-lambda-errors`,metricName:"Errors",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:r,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:a},alarmActions:n?[n]:void 0}),lambdaThrottles:(e,t,a,r=10,n)=>({slug:e,environment:t,alarmName:`${e}-${t}-lambda-throttles`,metricName:"Throttles",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:r,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:a},alarmActions:n?[n]:void 0}),apiGateway5xxErrors:(e,t,a,r=10,n)=>({slug:e,environment:t,alarmName:`${e}-${t}-api-5xx-errors`,metricName:"5XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:1,threshold:r,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:a},alarmActions:n?[n]:void 0}),apiGateway4xxErrors:(e,t,a,r=50,n)=>({slug:e,environment:t,alarmName:`${e}-${t}-api-4xx-errors`,metricName:"4XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:2,threshold:r,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:a},alarmActions:n?[n]:void 0}),dynamoDBThrottles:(e,t,a,r=5,n)=>({slug:e,environment:t,alarmName:`${e}-${t}-dynamodb-throttles`,metricName:"UserErrors",namespace:"AWS/DynamoDB",statistic:"Sum",period:300,evaluationPeriods:1,threshold:r,comparisonOperator:"GreaterThanThreshold",dimensions:{TableName:a},alarmActions:n?[n]:void 0}),rdsCpu:(e,t,a,r=80,n)=>({slug:e,environment:t,alarmName:`${e}-${t}-rds-cpu`,metricName:"CPUUtilization",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:2,threshold:r,comparisonOperator:"GreaterThanThreshold",dimensions:{DBInstanceIdentifier:a},alarmActions:n?[n]:void 0}),rdsFreeStorage:(e,t,a,r=5368709120,n)=>({slug:e,environment:t,alarmName:`${e}-${t}-rds-storage`,metricName:"FreeStorageSpace",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:1,threshold:r,comparisonOperator:"LessThanThreshold",dimensions:{DBInstanceIdentifier:a},alarmActions:n?[n]:void 0,unit:"Bytes"}),sqsQueueDepth:(e,t,a,r=100,n)=>({slug:e,environment:t,alarmName:`${e}-${t}-sqs-depth`,metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",statistic:"Average",period:300,evaluationPeriods:2,threshold:r,comparisonOperator:"GreaterThanThreshold",dimensions:{QueueName:a},alarmActions:n?[n]:void 0}),albUnhealthyTargets:(e,t,a,r,n=1,i)=>({slug:e,environment:t,alarmName:`${e}-${t}-alb-unhealthy`,metricName:"UnHealthyHostCount",namespace:"AWS/ApplicationELB",statistic:"Average",period:300,evaluationPeriods:2,threshold:n,comparisonOperator:"GreaterThanThreshold",dimensions:{LoadBalancer:a,TargetGroup:r},alarmActions:i?[i]:void 0}),sesBounceRate:(e,t,a=5,r)=>({slug:e,environment:t,alarmName:`${e}-${t}-ses-bounce-rate`,metricName:"Reputation.BounceRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:a/100,comparisonOperator:"GreaterThanThreshold",alarmActions:r?[r]:void 0}),sesComplaintRate:(e,t,a=0.1,r)=>({slug:e,environment:t,alarmName:`${e}-${t}-ses-complaint-rate`,metricName:"Reputation.ComplaintRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:a/100,comparisonOperator:"GreaterThanThreshold",alarmActions:r?[r]:void 0}),smsDeliveryFailure:(e,t,a,r=10,n)=>({slug:e,environment:t,alarmName:`${e}-${t}-sms-delivery-failure`,metricName:"DirectSendMessagePermanentFailure",namespace:"AWS/Pinpoint",statistic:"Sum",period:300,evaluationPeriods:1,threshold:r,comparisonOperator:"GreaterThanThreshold",dimensions:{ApplicationId:a},alarmActions:n?[n]:void 0}),smsSpendLimit:(e,t,a=100,r)=>({slug:e,environment:t,alarmName:`${e}-${t}-sms-spend-limit`,metricName:"DirectSendMessageSpend",namespace:"AWS/Pinpoint",statistic:"Sum",period:86400,evaluationPeriods:1,threshold:a,comparisonOperator:"GreaterThanThreshold",alarmActions:r?[r]:void 0}),connectMissedCalls:(e,t,a,r=5,n)=>({slug:e,environment:t,alarmName:`${e}-${t}-connect-missed-calls`,metricName:"MissedCalls",namespace:"AWS/Connect",statistic:"Sum",period:3600,evaluationPeriods:1,threshold:r,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:a},alarmActions:n?[n]:void 0})};static DashboardWidgets={metric:(e,t,a,r,n,i)=>({type:"metric",x:e,y:t,width:a,height:r,properties:{metrics:n,title:i||"Metrics",region:"us-east-1",period:300}}),text:(e,t,a,r,n)=>({type:"text",x:e,y:t,width:a,height:r,properties:{markdown:n}}),log:(e,t,a,r,n,i)=>({type:"log",x:e,y:t,width:a,height:r,properties:{query:`SOURCE '${n.join("' | SOURCE '")}'
2309
+ `;class z{static LambdaCode={send:Ja,receive:Pi,deliveryStatus:Ei};static createPinpointApp(e){return{[`${e.slug}PinpointApp`]:{Type:"AWS::Pinpoint::App",Properties:{Name:e.name||`${e.slug}-sms`}}}}static createSmsChannel(e){let t={ApplicationId:e.applicationId,Enabled:e.enabled!==!1};if(e.senderId)t.SenderId=e.senderId;if(e.shortCode)t.ShortCode=e.shortCode;return{[`${e.slug}SmsChannel`]:{Type:"AWS::Pinpoint::SMSChannel",Properties:t}}}static createSmsLambdaRole(e){return{[`${e.slug}SmsLambdaRole`]:{Type:"AWS::IAM::Role",Properties:{RoleName:`${e.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(e){return{[`${e.slug}SmsSendLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-sms-send`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:z.LambdaCode.send},Environment:{Variables:{PINPOINT_APP_ID:e.pinpointAppId,MESSAGE_LOG_TABLE:e.messageLogTable||"",SMS_SENDER_ID:e.senderId||"",SMS_ORIGINATION_NUMBER:e.originationNumber||""}}}}}}static createReceiveLambda(e){return{[`${e.slug}SmsReceiveLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-sms-receive`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:z.LambdaCode.receive},Environment:{Variables:{OPT_OUT_TABLE:e.optOutTable||"",MESSAGE_LOG_TABLE:e.messageLogTable||"",NOTIFICATION_TOPIC_ARN:e.notificationTopicArn||"",WEBHOOK_URL:e.webhookUrl||""}}}}}}static createDeliveryStatusLambda(e){return{[`${e.slug}SmsDeliveryStatusLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-sms-delivery-status`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:z.LambdaCode.deliveryStatus},Environment:{Variables:{MESSAGE_LOG_TABLE:e.messageLogTable||"",NOTIFICATION_TOPIC_ARN:e.notificationTopicArn||"",WEBHOOK_URL:e.webhookUrl||""}}}}}}static createMessageLogTable(e){return{[`${e.slug}SmsMessageLogTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-sms-messages`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createOptOutTable(e){return{[`${e.slug}SmsOptOutTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-sms-optouts`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}]}}}}static createNotificationTopic(e){return{[`${e.slug}SmsNotificationTopic`]:{Type:"AWS::SNS::Topic",Properties:{TopicName:`${e.slug}-sms-notifications`}}}}static createCompleteSetup(e){let t={},a={};Object.assign(t,z.createPinpointApp({slug:e.slug})),Object.assign(t,z.createSmsChannel({slug:e.slug,applicationId:{Ref:`${e.slug}PinpointApp`},senderId:e.senderId})),Object.assign(t,z.createSmsLambdaRole({slug:e.slug})),Object.assign(t,z.createMessageLogTable({slug:e.slug})),Object.assign(t,z.createOptOutTable({slug:e.slug})),Object.assign(t,z.createNotificationTopic({slug:e.slug}));let r={"Fn::GetAtt":[`${e.slug}SmsLambdaRole`,"Arn"]},n={Ref:`${e.slug}PinpointApp`},i={Ref:`${e.slug}SmsMessageLogTable`},s={Ref:`${e.slug}SmsOptOutTable`},o={Ref:`${e.slug}SmsNotificationTopic`};if(Object.assign(t,z.createSendLambda({slug:e.slug,roleArn:r,pinpointAppId:n,messageLogTable:i,senderId:e.senderId,originationNumber:e.originationNumber})),e.twoWayEnabled)Object.assign(t,z.createReceiveLambda({slug:e.slug,roleArn:r,optOutTable:s,messageLogTable:i,notificationTopicArn:o,webhookUrl:e.webhookUrl}));return Object.assign(t,z.createDeliveryStatusLambda({slug:e.slug,roleArn:r,messageLogTable:i,notificationTopicArn:o,webhookUrl:e.webhookUrl})),a[`${e.slug}PinpointAppId`]={Description:"Pinpoint application ID",Value:{Ref:`${e.slug}PinpointApp`}},a[`${e.slug}SmsSendLambdaArn`]={Description:"SMS send Lambda ARN",Value:{"Fn::GetAtt":[`${e.slug}SmsSendLambda`,"Arn"]}},a[`${e.slug}SmsNotificationTopicArn`]={Description:"SMS notification topic ARN",Value:{Ref:`${e.slug}SmsNotificationTopic`}},a[`${e.slug}SmsMessageLogTableName`]={Description:"SMS message log table name",Value:{Ref:`${e.slug}SmsMessageLogTable`}},{resources:t,outputs:a}}}function Lt(e){return e.replace(/[^a-zA-Z0-9]/g," ").trim().split(/\s+/).map((t)=>t.charAt(0).toUpperCase()+t.slice(1)).join("")||"User"}function Ni(e,t){let a=(e||t).replace(/^\/+|\/+$/g,"");if(!a||a.split("/").includes(".."))throw Error(`sftp: invalid homeDirectory for user ${t}`);return a}function Di(e){let t=e.storage;if(t?.type==="efs"){let r="fileSystemId"in t?t.fileSystemId:void 0;if(!r||typeof r==="string"&&!r.trim())throw Error("sftp: EFS storage requires fileSystemId, or a fileSystem name defined in infrastructure.fileSystem");return{type:"efs",fileSystemId:r,posixProfile:t.posixProfile}}let a=(t?.type==="s3"?t.bucket??e.bucket:e.bucket)?.trim();if(!a)throw Error("sftp: S3 storage requires bucket, or a storageBucket name defined in infrastructure.storage");return{type:"s3",bucket:a}}function ki(e,t,a){let r=t.posixProfile??a;if(!r)throw Error(`sftp: user ${e} requires a posixProfile (uid/gid) on an EFS-backed server`);for(let n of[r.uid,r.gid,...r.secondaryGids??[]])if(!Number.isInteger(n)||n<0||n>4294967295)throw Error(`sftp: user ${e} has an invalid posixProfile id ${n}`);return{Uid:r.uid,Gid:r.gid,...r.secondaryGids?.length?{SecondaryGids:r.secondaryGids}:{}}}function Mi(e,t){return typeof e==="string"?`/${e}/${t}`:{"Fn::Sub":[`/\${FileSystemId}/${t}`,{FileSystemId:e}]}}function Li(e){return typeof e==="string"?{"Fn::Sub":"arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}".replace("${FileSystemId}",e)}:{"Fn::Sub":["arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}",{FileSystemId:e}]}}class xi{static create(e){let t=Di(e),a=t.type==="efs"?"EFS":"S3",r=e.endpointType??"PUBLIC";if(r==="VPC"&&(!e.endpointDetails?.vpcId||!e.endpointDetails.subnetIds.length))throw Error("sftp: VPC endpoints require endpointDetails.vpcId and at least one subnet");let n=`${Lt(e.slug)}${Lt(e.environment)}Sftp`,i=`${n}Server`,s={},o;if(e.logging!==!1){let c=`${n}LoggingRole`;s[c]={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/*"}]}}]}},o={"Fn::GetAtt":[c,"Arn"]}}s[i]={Type:"AWS::Transfer::Server",Properties:{Domain:a,EndpointType:r,IdentityProviderType:"SERVICE_MANAGED",Protocols:["SFTP"],...r==="VPC"?{EndpointDetails:{VpcId:e.endpointDetails.vpcId,SubnetIds:e.endpointDetails.subnetIds,...e.endpointDetails.securityGroupIds?.length?{SecurityGroupIds:e.endpointDetails.securityGroupIds}:{},...e.endpointDetails.addressAllocationIds?.length?{AddressAllocationIds:e.endpointDetails.addressAllocationIds}:{}}}:{},...e.securityPolicyName?{SecurityPolicyName:e.securityPolicyName}:{},...o?{LoggingRole:o}:{},Tags:[{Key:"Project",Value:e.slug},{Key:"Environment",Value:e.environment},{Key:"ManagedBy",Value:"ts-cloud"}]}};for(let[c,l]of Object.entries(e.users)){if(!/^[a-zA-Z0-9_.@-]{3,100}$/.test(c))throw Error(`sftp: invalid username ${c}`);if(!l.sshPublicKeys.length)throw Error(`sftp: user ${c} requires at least one SSH public key`);let u=Lt(c),m=Ni(l.homeDirectory,c),p=`${n}${u}User`,g=l.roleArn;if(!g){let h=`${n}${u}Role`,y;if(t.type==="efs")y=[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:DescribeMountTargets"],Resource:Li(t.fileSystemId)}];else{let b=`arn:aws:s3:::${t.bucket}`;y=[{Effect:"Allow",Action:["s3:ListBucket","s3:GetBucketLocation"],Resource:b,Condition:{StringLike:{"s3:prefix":[m,`${m}/*`]}}},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:GetObjectVersion"],Resource:`${b}/${m}/*`}]}s[h]={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:y}}]}},g={"Fn::GetAtt":[h,"Arn"]}}s[p]={Type:"AWS::Transfer::User",DependsOn:[i],Properties:{ServerId:{Ref:i},UserName:c,Role:g,HomeDirectoryType:"PATH",HomeDirectory:t.type==="efs"?Mi(t.fileSystemId,m):`/${t.bucket}/${m}`,...t.type==="efs"?{PosixProfile:ki(c,l,t.posixProfile)}:{},SshPublicKeys:l.sshPublicKeys}}}return{resources:s,serverLogicalId:i,domain:a}}}class mt{static createBedrockRole(e,t){let{slug:a,environment:r,name:n,models:i=["*"],allowStreaming:s=!0}=t,o=n||A({slug:a,environment:r,resourceType:"bedrock-role"}),c=f(o),l=["bedrock:InvokeModel"];if(s)l.push("bedrock:InvokeModelWithResponseStream");let u=i.map((m)=>m==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${m}`);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:o,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:e},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:`${o}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:l,Resource:u}]}}],Tags:[{Key:"Name",Value:o},{Key:"Environment",Value:r}]}},logicalId:c}}static createBedrockPolicy(e){let{slug:t,environment:a,name:r,models:n=["*"],allowInvoke:i=!0,allowStreaming:s=!0,allowAsync:o=!1}=e,c=r||A({slug:t,environment:a,resourceType:"bedrock-policy"}),l=f(c),u=[];if(i)u.push("bedrock:InvokeModel");if(s)u.push("bedrock:InvokeModelWithResponseStream");if(o)u.push("bedrock:InvokeModelAsync");let m=n.map((p)=>p==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${p}`);return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:c,PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"BedrockModelInvocation",Effect:"Allow",Action:u,Resource:m}]}}},logicalId:l}}static enableBedrockForLambda(e){return mt.createBedrockRole("lambda.amazonaws.com",e)}static enableBedrockForEcs(e){return mt.createBedrockRole("ecs-tasks.amazonaws.com",e)}static enableBedrockForEc2(e){return mt.createBedrockRole("ec2.amazonaws.com",e)}static addBedrockPermissions(e,t=["*"],a=!0){let r=["bedrock:InvokeModel"];if(a)r.push("bedrock:InvokeModelWithResponseStream");let n=t.map((i)=>i==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${i}`);if(!e.Properties.Policies)e.Properties.Policies=[];return e.Properties.Policies.push({PolicyName:"bedrock-permissions",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:r,Resource:n}]}}),e}static Models={Claude3_5_Sonnet:"anthropic.claude-3-5-sonnet-20241022-v2:0",Claude3_5_Haiku:"anthropic.claude-3-5-haiku-20241022-v1:0",Claude3_Opus:"anthropic.claude-3-opus-20240229-v1:0",Claude3_Sonnet:"anthropic.claude-3-sonnet-20240229-v1:0",Claude3_Haiku:"anthropic.claude-3-haiku-20240307-v1:0",TitanTextG1Express:"amazon.titan-text-express-v1",TitanTextG1Lite:"amazon.titan-text-lite-v1",TitanEmbedG1Text:"amazon.titan-embed-text-v1",TitanImageG1:"amazon.titan-image-generator-v1",JurassicUltra:"ai21.j2-ultra-v1",JurassicMid:"ai21.j2-mid-v1",CommandText:"cohere.command-text-v14",CommandLight:"cohere.command-light-text-v14",EmbedEnglish:"cohere.embed-english-v3",EmbedMultilingual:"cohere.embed-multilingual-v3",Llama3_2_1B:"meta.llama3-2-1b-instruct-v1:0",Llama3_2_3B:"meta.llama3-2-3b-instruct-v1:0",Llama3_2_11B:"meta.llama3-2-11b-instruct-v1:0",Llama3_2_90B:"meta.llama3-2-90b-instruct-v1:0",Llama3_1_8B:"meta.llama3-1-8b-instruct-v1:0",Llama3_1_70B:"meta.llama3-1-70b-instruct-v1:0",Llama3_1_405B:"meta.llama3-1-405b-instruct-v1:0",Mistral7B:"mistral.mistral-7b-instruct-v0:2",Mixtral8x7B:"mistral.mixtral-8x7b-instruct-v0:1",MistralLarge:"mistral.mistral-large-2402-v1:0",StableDiffusionXL:"stability.stable-diffusion-xl-v1"};static ModelGroups={AllClaude:["anthropic.claude-3-5-sonnet-20241022-v2:0","anthropic.claude-3-5-haiku-20241022-v1:0","anthropic.claude-3-opus-20240229-v1:0","anthropic.claude-3-sonnet-20240229-v1:0","anthropic.claude-3-haiku-20240307-v1:0"],AllTitan:["amazon.titan-text-express-v1","amazon.titan-text-lite-v1","amazon.titan-embed-text-v1","amazon.titan-image-generator-v1"],AllLlama:["meta.llama3-2-1b-instruct-v1:0","meta.llama3-2-3b-instruct-v1:0","meta.llama3-2-11b-instruct-v1:0","meta.llama3-2-90b-instruct-v1:0","meta.llama3-1-8b-instruct-v1:0","meta.llama3-1-70b-instruct-v1:0","meta.llama3-1-405b-instruct-v1:0"],TextModels:["anthropic.claude-3-5-sonnet-20241022-v2:0","anthropic.claude-3-5-haiku-20241022-v1:0","amazon.titan-text-express-v1","meta.llama3-2-11b-instruct-v1:0","mistral.mistral-7b-instruct-v0:2"],EmbeddingModels:["amazon.titan-embed-text-v1","cohere.embed-english-v3","cohere.embed-multilingual-v3"],ImageModels:["amazon.titan-image-generator-v1","stability.stable-diffusion-xl-v1"]}}class Ft{static createPostgres(e){return Ft.createRDSInstance("postgres","16.2",e)}static createMysql(e){return Ft.createRDSInstance("mysql","8.0.35",e)}static createRDSInstance(e,t,a){let{slug:r,environment:n,instanceClass:i="db.t3.micro",allocatedStorage:s=20,storageType:o="gp3",masterUsername:c="admin",masterPassword:l,databaseName:u,subnetIds:m,securityGroupIds:p,encrypted:g=!0,kmsKeyId:h,multiAz:y=!1,backupRetentionDays:b=7,publiclyAccessible:T=!1,enableCloudwatchLogs:w=!0,deletionProtection:S=!0}=a,E=A({slug:r,environment:n,resourceType:`${e}-db`}),v=f(E),P,N;if(m&&m.length>0){let D=A({slug:r,environment:n,resourceType:"db-subnet-group"});N=f(D),P={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupName:D,DBSubnetGroupDescription:`Subnet group for ${E}`,SubnetIds:m,Tags:[{Key:"Name",Value:D},{Key:"Environment",Value:n}]}}}let I={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:E,DBInstanceClass:i,Engine:e,EngineVersion:t,MasterUsername:c,MasterUserPassword:l,AllocatedStorage:s,StorageType:o,StorageEncrypted:g,MultiAZ:y,BackupRetentionPeriod:b,PubliclyAccessible:T,DeletionProtection:S,Tags:[{Key:"Name",Value:E},{Key:"Environment",Value:n}]}};if(u)I.Properties.DBName=u;if(h)I.Properties.KmsKeyId=h;if(N)I.Properties.DBSubnetGroupName=C.Ref(N);if(p&&p.length>0)I.Properties.VPCSecurityGroups=p;if(w)I.Properties.EnableCloudwatchLogsExports=e==="postgres"?["postgresql"]:["error","general","slowquery"];return{dbInstance:I,subnetGroup:P,logicalId:v,subnetGroupId:N}}static createReadReplica(e,t){let{slug:a,environment:r,instanceClass:n="db.t3.micro",securityGroupIds:i,publiclyAccessible:s=!1}=t,o=A({slug:a,environment:r,resourceType:"db-replica"}),c=f(o),l={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:o,DBInstanceClass:n,SourceDBInstanceIdentifier:C.Ref(e),PubliclyAccessible:s,Tags:[{Key:"Name",Value:o},{Key:"Environment",Value:r},{Key:"Type",Value:"ReadReplica"}]}};if(i&&i.length>0)l.Properties.VPCSecurityGroups=i;return{replica:l,logicalId:c}}static createParameterGroup(e,t,a){let{slug:r,environment:n,parameters:i={}}=a,s=A({slug:r,environment:n,resourceType:"db-params"}),o=f(s),c=e==="postgres"?`postgres${t.split(".")[0]}`:`mysql${t.split(".")[0]}.${t.split(".")[1]}`;return{parameterGroup:{Type:"AWS::RDS::DBParameterGroup",Properties:{DBParameterGroupName:s,Description:`Parameter group for ${s}`,Family:c,Parameters:i,Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:n}]}},logicalId:o}}static enableBackup(e,t=7){return e.Properties.BackupRetentionPeriod=t,e}static createTable(e){let{slug:t,environment:a,tableName:r,partitionKey:n,sortKey:i,billingMode:s="PAY_PER_REQUEST",readCapacity:o=5,writeCapacity:c=5,streamEnabled:l=!1,streamViewType:u="NEW_AND_OLD_IMAGES",encrypted:m=!0,kmsKeyId:p,pointInTimeRecovery:g=!0,ttlAttribute:h}=e,y=r||A({slug:t,environment:a,resourceType:"table"}),b=f(y),T=[{AttributeName:n.name,AttributeType:n.type}];if(i)T.push({AttributeName:i.name,AttributeType:i.type});let w=[{AttributeName:n.name,KeyType:"HASH"}];if(i)w.push({AttributeName:i.name,KeyType:"RANGE"});let S={Type:"AWS::DynamoDB::Table",Properties:{TableName:y,BillingMode:s,AttributeDefinitions:T,KeySchema:w,Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:a}]}};if(s==="PROVISIONED")S.Properties.ProvisionedThroughput={ReadCapacityUnits:o,WriteCapacityUnits:c};if(l)S.Properties.StreamSpecification={StreamViewType:u};if(m)S.Properties.SSESpecification={SSEEnabled:!0,SSEType:p?"KMS":"AES256",KMSMasterKeyId:p};if(g)S.Properties.PointInTimeRecoverySpecification={PointInTimeRecoveryEnabled:!0};if(h)S.Properties.TimeToLiveSpecification={AttributeName:h,Enabled:!0};return{table:S,logicalId:b}}static addGlobalSecondaryIndex(e,t){let{indexName:a,partitionKey:r,sortKey:n,projectionType:i="ALL",nonKeyAttributes:s,readCapacity:o=5,writeCapacity:c=5}=t;if(!e.Properties.AttributeDefinitions.some((m)=>m.AttributeName===r.name))e.Properties.AttributeDefinitions.push({AttributeName:r.name,AttributeType:r.type});if(n&&!e.Properties.AttributeDefinitions.some((m)=>m.AttributeName===n.name))e.Properties.AttributeDefinitions.push({AttributeName:n.name,AttributeType:n.type});let l=[{AttributeName:r.name,KeyType:"HASH"}];if(n)l.push({AttributeName:n.name,KeyType:"RANGE"});let u={IndexName:a,KeySchema:l,Projection:{ProjectionType:i,NonKeyAttributes:i==="INCLUDE"?s:void 0},ProvisionedThroughput:void 0};if(e.Properties.BillingMode==="PROVISIONED")u.ProvisionedThroughput={ReadCapacityUnits:o,WriteCapacityUnits:c};if(!e.Properties.GlobalSecondaryIndexes)e.Properties.GlobalSecondaryIndexes=[];return e.Properties.GlobalSecondaryIndexes.push(u),e}static enableStreams(e,t="NEW_AND_OLD_IMAGES"){return e.Properties.StreamSpecification={StreamViewType:t},e}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 Oi{static createRedis(e){let{slug:t,environment:a,nodeType:r="cache.t3.micro",engineVersion:n="7.1",port:i=6379,subnetIds:s,securityGroupIds:o,numCacheClusters:c=2,automaticFailover:l=!0,multiAz:u=!0,clusterMode:m=!1,numNodeGroups:p=1,replicasPerNodeGroup:g=1,atRestEncryption:h=!0,transitEncryption:y=!0,authToken:b,kmsKeyId:T,snapshotRetentionDays:w=7,snapshotWindow:S,maintenanceWindow:E}=e,v=A({slug:t,environment:a,resourceType:"redis"}),P=f(v),N,I;if(s&&s.length>0){let M=A({slug:t,environment:a,resourceType:"cache-subnet-group"});I=f(M),N={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:M,Description:`Subnet group for ${v}`,SubnetIds:s,Tags:[{Key:"Name",Value:M},{Key:"Environment",Value:a}]}}}let D={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:v,ReplicationGroupDescription:`Redis cluster for ${t} ${a}`,Engine:"redis",EngineVersion:n,CacheNodeType:r,Port:i,AutomaticFailoverEnabled:l,MultiAZEnabled:u,AtRestEncryptionEnabled:h,TransitEncryptionEnabled:y,SnapshotRetentionLimit:w,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:v},{Key:"Environment",Value:a}]}};if(m)D.Properties.NumNodeGroups=p,D.Properties.ReplicasPerNodeGroup=g;else D.Properties.NumCacheClusters=c;if(b)D.Properties.AuthToken=b;if(T)D.Properties.KmsKeyId=T;if(I)D.Properties.CacheSubnetGroupName=C.Ref(I);if(o&&o.length>0)D.Properties.SecurityGroupIds=o;if(S)D.Properties.SnapshotWindow=S;if(E)D.Properties.PreferredMaintenanceWindow=E;return{replicationGroup:D,subnetGroup:N,logicalId:P,subnetGroupId:I}}static createMemcached(e){let{slug:t,environment:a,nodeType:r="cache.t3.micro",engineVersion:n="1.6.22",port:i=11211,numCacheNodes:s=2,subnetIds:o,securityGroupIds:c,azMode:l="cross-az",preferredAzs:u,maintenanceWindow:m}=e,p=A({slug:t,environment:a,resourceType:"memcached"}),g=f(p),h,y;if(o&&o.length>0){let T=A({slug:t,environment:a,resourceType:"cache-subnet-group"});y=f(T),h={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:T,Description:`Subnet group for ${p}`,SubnetIds:o,Tags:[{Key:"Name",Value:T},{Key:"Environment",Value:a}]}}}let b={Type:"AWS::ElastiCache::CacheCluster",Properties:{ClusterName:p,CacheNodeType:r,Engine:"memcached",EngineVersion:n,NumCacheNodes:s,Port:i,AZMode:l,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:p},{Key:"Environment",Value:a}]}};if(y)b.Properties.CacheSubnetGroupName=C.Ref(y);if(c&&c.length>0)b.Properties.VpcSecurityGroupIds=c;if(u&&u.length>0)b.Properties.PreferredAvailabilityZones=u;if(m)b.Properties.PreferredMaintenanceWindow=m;return{cluster:b,subnetGroup:h,logicalId:g,subnetGroupId:y}}static enableClusterMode(e,t=3,a=2){return delete e.Properties.NumCacheClusters,e.Properties.NumNodeGroups=t,e.Properties.ReplicasPerNodeGroup=a,e}static createRedisParameterGroup(e,t){let{slug:a,environment:r,parameters:n={}}=t,i=A({slug:a,environment:r,resourceType:"redis-params"}),s=f(i);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`redis${e.split(".")[0]}.x`,Description:`Parameter group for ${i}`,Properties:n,Tags:[{Key:"Name",Value:i},{Key:"Environment",Value:r}]}},logicalId:s}}static createMemcachedParameterGroup(e,t){let{slug:a,environment:r,parameters:n={}}=t,i=A({slug:a,environment:r,resourceType:"memcached-params"}),s=f(i);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`memcached${e.split(".")[0]}.${e.split(".")[1]}`,Description:`Parameter group for ${i}`,Properties:n,Tags:[{Key:"Name",Value:i},{Key:"Environment",Value:r}]}},logicalId:s}}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 ne{static createUser(e){let{slug:t,environment:a,userName:r,groups:n,managedPolicyArns:i}=e,s=r||A({slug:t,environment:a,resourceType:"user"}),o=f(s),c={Type:"AWS::IAM::User",Properties:{UserName:s,Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:a}]}};if(n&&n.length>0)c.Properties.Groups=n;if(i&&i.length>0)c.Properties.ManagedPolicyArns=i;return{user:c,logicalId:o}}static createRole(e){let{slug:t,environment:a,roleName:r,servicePrincipal:n,awsPrincipal:i,managedPolicyArns:s}=e,o=r||A({slug:t,environment:a,resourceType:"role"}),c=f(o),l={};if(n)l.Service=n;if(i)l.AWS=i;let u={Type:"AWS::IAM::Role",Properties:{RoleName:o,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:l,Action:"sts:AssumeRole"}]},Tags:[{Key:"Name",Value:o},{Key:"Environment",Value:a}]}};if(s&&s.length>0)u.Properties.ManagedPolicyArns=s;return{role:u,logicalId:c}}static createGroup(e){let{slug:t,environment:a,groupName:r,managedPolicyArns:n}=e,i=r||A({slug:t,environment:a,resourceType:"group"}),s=f(i),o={Type:"AWS::IAM::Group",Properties:{GroupName:i}};if(n&&n.length>0)o.Properties.ManagedPolicyArns=n;return{group:o,logicalId:s}}static createPolicy(e){let{slug:t,environment:a,policyName:r,description:n,statements:i}=e,s=r||A({slug:t,environment:a,resourceType:"policy"}),o=f(s),c=i.map((l)=>({Sid:l.sid,Effect:l.effect||"Allow",Action:l.actions,Resource:l.resources,Condition:l.conditions}));return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:s,Description:n||`Managed policy for ${s}`,PolicyDocument:{Version:"2012-10-17",Statement:c}}},logicalId:o}}static attachPolicyToRole(e,t){if(!e.Properties.ManagedPolicyArns)e.Properties.ManagedPolicyArns=[];if(!e.Properties.ManagedPolicyArns.includes(t))e.Properties.ManagedPolicyArns.push(t);return e}static attachPolicyToUser(e,t){if(!e.Properties.ManagedPolicyArns)e.Properties.ManagedPolicyArns=[];if(!e.Properties.ManagedPolicyArns.includes(t))e.Properties.ManagedPolicyArns.push(t);return e}static attachPolicyToGroup(e,t){if(!e.Properties.ManagedPolicyArns)e.Properties.ManagedPolicyArns=[];if(!e.Properties.ManagedPolicyArns.includes(t))e.Properties.ManagedPolicyArns.push(t);return e}static addInlinePolicyToRole(e,t,a){if(!e.Properties.Policies)e.Properties.Policies=[];let r=a.map((n)=>({Effect:n.effect||"Allow",Action:n.actions,Resource:n.resources}));return e.Properties.Policies.push({PolicyName:t,PolicyDocument:{Version:"2012-10-17",Statement:r}}),e}static addInlinePolicyToUser(e,t,a){if(!e.Properties.Policies)e.Properties.Policies=[];let r=a.map((n)=>({Effect:n.effect||"Allow",Action:n.actions,Resource:n.resources}));return e.Properties.Policies.push({PolicyName:t,PolicyDocument:{Version:"2012-10-17",Statement:r}}),e}static createAccessKey(e,t){let{slug:a,environment:r,status:n="Active"}=t,i=A({slug:a,environment:r,resourceType:"access-key"}),s=f(i);return{accessKey:{Type:"AWS::IAM::AccessKey",Properties:{UserName:C.Ref(e),Status:n}},logicalId:s}}static createInstanceProfile(e,t){let{slug:a,environment:r,profileName:n}=t,i=n||A({slug:a,environment:r,resourceType:"instance-profile"}),s=f(i);return{instanceProfile:{Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:i,Roles:[C.Ref(e)]}},logicalId:s}}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(e){let{slug:t,environment:a,permissions:r,createAccessKey:n=!0}=e,i={},s=[];if(r.s3Buckets&&r.s3Buckets.length>0)s.push({sid:"S3Access",actions:["s3:GetBucketLocation","s3:ListBucket","s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucketMultipartUploads","s3:AbortMultipartUpload"],resources:[...r.s3Buckets,...r.s3Buckets.map((g)=>`${g}/*`)]});if(r.cloudFrontDistributions&&r.cloudFrontDistributions.length>0)s.push({sid:"CloudFrontAccess",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations","cloudfront:GetDistribution"],resources:r.cloudFrontDistributions});if(r.ecrRepositories&&r.ecrRepositories.length>0)s.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:r.ecrRepositories}),s.push({sid:"ECRLogin",actions:["ecr:GetAuthorizationToken"],resources:"*"});if(r.ecsServices&&r.ecsServices.length>0)s.push({sid:"ECSAccess",actions:["ecs:DescribeServices","ecs:DescribeTaskDefinition","ecs:DescribeTasks","ecs:ListTasks","ecs:RegisterTaskDefinition","ecs:UpdateService","ecs:RunTask","ecs:StopTask"],resources:r.ecsServices}),s.push({sid:"ECSTaskDefinitions",actions:["ecs:RegisterTaskDefinition","ecs:DeregisterTaskDefinition"],resources:"*"}),s.push({sid:"ECSPassRole",actions:["iam:PassRole"],resources:"*",conditions:{StringLike:{"iam:PassedToService":"ecs-tasks.amazonaws.com"}}});if(r.cloudFormationStacks&&r.cloudFormationStacks.length>0)s.push({sid:"CloudFormationAccess",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:DescribeStackResources","cloudformation:GetTemplate","cloudformation:ListStackResources","cloudformation:ValidateTemplate"],resources:r.cloudFormationStacks});if(r.lambdaFunctions&&r.lambdaFunctions.length>0)s.push({sid:"LambdaAccess",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion","lambda:UpdateAlias","lambda:CreateAlias"],resources:r.lambdaFunctions});if(r.secretsManagerSecrets&&r.secretsManagerSecrets.length>0)s.push({sid:"SecretsManagerAccess",actions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],resources:r.secretsManagerSecrets});let{policy:o,logicalId:c}=ne.createPolicy({slug:t,environment:a,policyName:A({slug:t,environment:a,resourceType:"cicd-policy"}),description:`CI/CD deployment policy for ${t} (${a})`,statements:s});i[c]=o;let{user:l,logicalId:u}=ne.createUser({slug:t,environment:a,userName:A({slug:t,environment:a,resourceType:"cicd-user"}),managedPolicyArns:[C.Ref(c)]});i[u]=l;let m,p;if(n){let g=ne.createAccessKey(u,{slug:t,environment:a});m=g.accessKey,p=g.logicalId,i[p]=m}return{user:l,accessKey:m,policy:o,userLogicalId:u,accessKeyLogicalId:p,policyLogicalId:c,resources:i}}static createCrossAccountRole(e){let{slug:t,environment:a,trustedAccountIds:r,externalId:n,permissions:i,maxSessionDuration:s=3600}=e,o={},{policy:c,logicalId:l}=ne.createPolicy({slug:t,environment:a,policyName:A({slug:t,environment:a,resourceType:"cross-account-policy"}),description:`Cross-account access policy for ${t} (${a})`,statements:i});o[l]=c;let u=A({slug:t,environment:a,resourceType:"cross-account-role"}),m=f(u),p={};if(n)p.StringEquals={"sts:ExternalId":n};let g={Type:"AWS::IAM::Role",Properties:{RoleName:u,MaxSessionDuration:s,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:r.map((h)=>`arn:aws:iam::${h}:root`)},Action:"sts:AssumeRole",...Object.keys(p).length>0?{Condition:p}:{}}]},ManagedPolicyArns:[C.Ref(l)],Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:a},{Key:"Purpose",Value:"Cross-Account Access"}]}};return o[m]=g,{role:g,policy:c,roleLogicalId:m,policyLogicalId:l,resources:o}}static createCliUser(e){let{slug:t,environment:a,permissions:r="readonly"}=e,n={},i=[],s=[];switch(r){case"readonly":s=[ne.ManagedPolicies.ReadOnlyAccess];break;case"deploy":i=[{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":s=[ne.ManagedPolicies.AdministratorAccess];break}let o,c;if(i.length>0){let g=ne.createPolicy({slug:t,environment:a,policyName:A({slug:t,environment:a,resourceType:"cli-policy"}),description:`CLI access policy for ${t} (${a})`,statements:i});o=g.policy,c=g.logicalId,n[c]=o,s=[C.Ref(c)]}let{user:l,logicalId:u}=ne.createUser({slug:t,environment:a,userName:A({slug:t,environment:a,resourceType:"cli-user"}),managedPolicyArns:s});n[u]=l;let{accessKey:m,logicalId:p}=ne.createAccessKey(u,{slug:t,environment:a});return n[p]=m,{user:l,accessKey:m,policy:o,userLogicalId:u,accessKeyLogicalId:p,policyLogicalId:c,resources:n}}static CiCdPolicies={s3Deployment:(e)=>[{sid:"S3ListBuckets",actions:["s3:ListBucket","s3:GetBucketLocation"],resources:e},{sid:"S3Objects",actions:["s3:GetObject","s3:PutObject","s3:DeleteObject"],resources:e.map((t)=>`${t}/*`)}],cloudFrontInvalidation:(e)=>[{sid:"CloudFrontInvalidation",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations"],resources:e}],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:(e)=>[{sid:"ECRAuth",actions:["ecr:GetAuthorizationToken"],resources:"*"},{sid:"ECRPush",actions:["ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:PutImage"],resources:e}],lambdaDeployment:(e)=>[{sid:"LambdaDeploy",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion"],resources:e}],cloudFormationDeployment:(e)=>[{sid:"CloudFormationDeploy",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate"],resources:e}]}}class Wi{static createRestApi(e){let{slug:t,environment:a,name:r,description:n,endpointType:i="REGIONAL",binaryMediaTypes:s,compressionSize:o}=e,c=r||A({slug:t,environment:a,resourceType:"rest-api"}),l=f(c),u={Type:"AWS::ApiGateway::RestApi",Properties:{Name:c,Description:n||`REST API for ${t} ${a}`,EndpointConfiguration:{Types:[i]},Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:a}]}};if(s&&s.length>0)u.Properties.BinaryMediaTypes=s;if(o!==void 0)u.Properties.MinimumCompressionSize=o;return{restApi:u,logicalId:l}}static createHttpApi(e){let{slug:t,environment:a,name:r,description:n,corsEnabled:i=!0,corsOrigins:s=["*"],corsMethods:o=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],corsHeaders:c=["*"],corsMaxAge:l=86400,corsAllowCredentials:u=!1}=e,m=r||A({slug:t,environment:a,resourceType:"http-api"}),p=f(m),g={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:m,Description:n||`HTTP API for ${t} ${a}`,ProtocolType:"HTTP",Tags:{Name:m,Environment:a}}};if(i)g.Properties.CorsConfiguration={AllowOrigins:s,AllowMethods:o,AllowHeaders:c,MaxAge:l,AllowCredentials:u};return{httpApi:g,logicalId:p}}static createWebSocketApi(e){let{slug:t,environment:a,name:r,description:n}=e,i=r||A({slug:t,environment:a,resourceType:"ws-api"}),s=f(i);return{webSocketApi:{Type:"AWS::ApiGatewayV2::Api",Properties:{Name:i,Description:n||`WebSocket API for ${t} ${a}`,ProtocolType:"WEBSOCKET",Tags:{Name:i,Environment:a}}},logicalId:s}}static createDeployment(e,t){let{slug:a,environment:r,description:n}=t,i=A({slug:a,environment:r,resourceType:"api-deployment"}),s=f(i);return{deployment:{Type:"AWS::ApiGateway::Deployment",Properties:{RestApiId:C.Ref(e),Description:n||`Deployment for ${i}`}},logicalId:s}}static createStage(e,t,a){let{slug:r,environment:n,stageName:i,description:s,cacheEnabled:o=!1,cacheSize:c="0.5",variables:l,throttling:u}=a,m=A({slug:r,environment:n,resourceType:"api-stage"}),p=f(m),g={Type:"AWS::ApiGateway::Stage",Properties:{StageName:i||n,RestApiId:C.Ref(e),DeploymentId:C.Ref(t),Description:s,CacheClusterEnabled:o,Tags:[{Key:"Name",Value:m},{Key:"Environment",Value:n}]}};if(o)g.Properties.CacheClusterSize=c;if(l)g.Properties.Variables=l;if(u)g.Properties.MethodSettings=[{HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:u.burstLimit,ThrottlingRateLimit:u.rateLimit}];return{stage:g,logicalId:p}}static createAuthorizer(e,t){let{slug:a,environment:r,name:n,type:i,functionArn:s,identitySource:o,userPoolArns:c,ttl:l=300}=t,u=n||A({slug:a,environment:r,resourceType:"api-authorizer"}),m=f(u),p={Type:"AWS::ApiGateway::Authorizer",Properties:{Name:u,Type:i,RestApiId:C.Ref(e),AuthorizerResultTtlInSeconds:l}};if(i==="TOKEN"||i==="REQUEST"){if(!s)throw Error("Lambda authorizer requires functionArn");p.Properties.AuthorizerUri=s,p.Properties.IdentitySource=o||"method.request.header.Authorization"}if(i==="COGNITO_USER_POOLS"){if(!c||c.length===0)throw Error("Cognito authorizer requires userPoolArns");p.Properties.ProviderARNs=c,p.Properties.IdentitySource=o||"method.request.header.Authorization"}return{authorizer:p,logicalId:m}}static setCors(e,t={}){let{origins:a=["*"],methods:r=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],headers:n=["*"],maxAge:i=86400,allowCredentials:s=!1}=t;return e.Properties.CorsConfiguration={AllowOrigins:a,AllowMethods:r,AllowHeaders:n,MaxAge:i,AllowCredentials:s},e}static addThrottling(e,t=5000,a=1e4){if(!e.Properties.MethodSettings)e.Properties.MethodSettings=[];return e.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:t,ThrottlingRateLimit:a}),e}static enableCaching(e,t="0.5",a=300){if(e.Properties.CacheClusterEnabled=!0,e.Properties.CacheClusterSize=t,!e.Properties.MethodSettings)e.Properties.MethodSettings=[];return e.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",CachingEnabled:!0,CacheTtlInSeconds:a}),e}static CacheSizes={Small:"0.5",Medium:"1.6",Large:"6.1",XLarge:"13.5",XXLarge:"28.4",XXXLarge:"58.2",Huge:"118",Massive:"237"};static ThrottlingPresets={Light:{burstLimit:100,rateLimit:50},Medium:{burstLimit:500,rateLimit:250},Heavy:{burstLimit:2000,rateLimit:1000},Default:{burstLimit:5000,rateLimit:1e4}}}class Z{static createTopic(e){let{slug:t,environment:a,topicName:r,displayName:n,encrypted:i=!1,kmsKeyId:s}=e,o=r||A({slug:t,environment:a,resourceType:"topic"}),c=f(o),l={Type:"AWS::SNS::Topic",Properties:{TopicName:o,DisplayName:n||o,Tags:[{Key:"Name",Value:o},{Key:"Environment",Value:a}]}};if(i&&s)l.Properties.KmsMasterKeyId=s;return{topic:l,logicalId:c}}static subscribe(e,t){let{slug:a,environment:r,protocol:n,endpoint:i,filterPolicy:s,rawMessageDelivery:o=!1}=t,c=A({slug:a,environment:r,resourceType:"subscription"}),l=i.replace(/[^a-zA-Z0-9]/g,""),u=l.length>12?l.slice(-12):l,m=f(`${c}-${n}-${u}`),p={Type:"AWS::SNS::Subscription",Properties:{TopicArn:C.Ref(e),Protocol:n,Endpoint:i,RawMessageDelivery:o}};if(s)p.Properties.FilterPolicy=s;return{subscription:p,logicalId:m}}static subscribeEmail(e,t,a){return Z.subscribe(e,{...a,protocol:"email",endpoint:t})}static subscribeLambda(e,t,a){return Z.subscribe(e,{...a,protocol:"lambda",endpoint:t,rawMessageDelivery:!0})}static subscribeSqs(e,t,a){return Z.subscribe(e,{...a,protocol:"sqs",endpoint:t})}static subscribeHttp(e,t,a){let r=t.startsWith("https://")?"https":"http";return Z.subscribe(e,{...a,protocol:r,endpoint:t})}static subscribeSms(e,t,a){return Z.subscribe(e,{...a,protocol:"sms",endpoint:t})}static setTopicPolicy(e,t){let{slug:a,environment:r,allowedPrincipals:n,allowedServices:i,actions:s="SNS:Publish"}=t,o=A({slug:a,environment:r,resourceType:"topic-policy"}),c=f(o),l={};if(n)l.AWS=n;if(i)l.Service=i;return{policy:{Type:"AWS::SNS::TopicPolicy",Properties:{Topics:[C.Ref(e)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:l,Action:s,Resource:C.Ref(e)}]}}},logicalId:c}}static allowCloudWatchAlarms(e,t){return Z.setTopicPolicy(e,{...t,allowedServices:"cloudwatch.amazonaws.com",actions:"SNS:Publish"})}static allowEventBridge(e,t){return Z.setTopicPolicy(e,{...t,allowedServices:"events.amazonaws.com",actions:"SNS:Publish"})}static allowS3(e,t){return Z.setTopicPolicy(e,{...t,allowedServices:"s3.amazonaws.com",actions:"SNS:Publish"})}static enableEncryption(e,t){if(!e.Properties)e.Properties={};return e.Properties.KmsMasterKeyId=t,e}static addInlineSubscription(e,t,a){if(!e.Properties)e.Properties={};if(!e.Properties.Subscription)e.Properties.Subscription=[];return e.Properties.Subscription.push({Protocol:t,Endpoint:a}),e}static FilterPolicies={eventType:(e)=>({eventType:e}),status:(e)=>({status:e}),numericRange:(e,t,a)=>({[e]:[{numeric:[">=",t,"<=",a]}]}),prefix:(e,t)=>({[e]:[{prefix:t}]}),and:(...e)=>{return Object.assign({},...e)},exists:(e,t)=>({[e]:[{exists:t}]})};static UseCases={createAlertTopic:(e)=>{return Z.createTopic({...e,topicName:e.topicName||`${e.slug}-${e.environment}-alerts`,displayName:e.displayName||"Alert Notifications"})},createEventFanout:(e)=>{return Z.createTopic({...e,topicName:e.topicName||`${e.slug}-${e.environment}-events`,displayName:e.displayName||"Event Fanout"})},createNotificationTopic:(e)=>{return Z.createTopic({...e,topicName:e.topicName||`${e.slug}-${e.environment}-notifications`,displayName:e.displayName||"User Notifications"})}}}class _i{static createStateMachine(e){let{slug:t,environment:a,stateMachineName:r,type:n="STANDARD",definition:i,roleArn:s,loggingConfiguration:o,tracingConfiguration:c}=e,l=r||A({slug:t,environment:a,resourceType:"state-machine"}),u=f(l),m,p,g;if(s)g=s;else{let y=A({slug:t,environment:a,resourceType:"state-machine-role"});p=f(y),m={Type:"AWS::IAM::Role",Properties:{RoleName:y,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:y},{Key:"Environment",Value:a}]}},g=C.GetAtt(p,"Arn")}let h={Type:"AWS::StepFunctions::StateMachine",Properties:{StateMachineName:l,StateMachineType:n,DefinitionString:JSON.stringify(i),RoleArn:g,Tags:[{Key:"Name",Value:l},{Key:"Environment",Value:a}]}};if(o)h.Properties.LoggingConfiguration={Level:o.level,IncludeExecutionData:o.includeExecutionData,Destinations:o.destinations?.map((y)=>({CloudWatchLogsLogGroup:{LogGroupArn:y}}))};if(c)h.Properties.TracingConfiguration={Enabled:c.enabled};return{stateMachine:h,logicalId:u,role:m,roleLogicalId:p}}static createLambdaTask(e,t){return{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Parameters:{FunctionName:e,Payload:t?.parameters||{"Input.$":"$"}},ResultPath:t?.resultPath,Retry:t?.retry,Catch:t?.catch,Next:t?.next,End:t?.end}}static createDynamoDBTask(e,t,a,r){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"}[e],Parameters:{TableName:t,...a},ResultPath:r?.resultPath,Retry:r?.retry,Catch:r?.catch,Next:r?.next,End:r?.end}}static createSNSPublishTask(e,t,a){return{Type:"Task",Resource:"arn:aws:states:::sns:publish",Parameters:{TopicArn:e,Message:t},ResultPath:a?.resultPath,Retry:a?.retry,Catch:a?.catch,Next:a?.next,End:a?.end}}static createSQSSendMessageTask(e,t,a){return{Type:"Task",Resource:"arn:aws:states:::sqs:sendMessage",Parameters:{QueueUrl:e,MessageBody:t},ResultPath:a?.resultPath,Retry:a?.retry,Catch:a?.catch,Next:a?.next,End:a?.end}}static createPassState(e){return{Type:"Pass",Result:e?.result,ResultPath:e?.resultPath,Parameters:e?.parameters,Next:e?.next,End:e?.end}}static createWaitState(e){return{Type:"Wait",Seconds:e.seconds,Timestamp:e.timestamp,SecondsPath:e.secondsPath,TimestampPath:e.timestampPath,Next:e.next,End:e.end}}static createChoiceState(e,t){return{Type:"Choice",Choices:e,Default:t}}static createParallelState(e,t){return{Type:"Parallel",Branches:e,ResultPath:t?.resultPath,Retry:t?.retry,Catch:t?.catch,Next:t?.next,End:t?.end}}static createMapState(e,t){return{Type:"Map",ItemsPath:t?.itemsPath||"$.items",Iterator:e,MaxConcurrency:t?.maxConcurrency,ResultPath:t?.resultPath,Retry:t?.retry,Catch:t?.catch,Next:t?.next,End:t?.end}}static createSucceedState(){return{Type:"Succeed"}}static createFailState(e,t){return{Type:"Fail",Error:e,Cause:t}}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:(e,t,a,r)=>({ErrorEquals:e,IntervalSeconds:t,MaxAttempts:a,BackoffRate:r})};static CatchPolicies={all:(e,t)=>({ErrorEquals:["States.ALL"],Next:e,ResultPath:t||"$.error"}),specific:(e,t,a)=>({ErrorEquals:e,Next:t,ResultPath:a||"$.error"})};static Patterns={sequential:(e,t,a)=>{let r={};return a.forEach((n,i)=>{let s=i===a.length-1;r[n.name]={...n.state,Next:s?void 0:a[i+1].name,End:s}}),{Comment:"Sequential workflow",StartAt:a[0].name,States:r}},fanout:(e,t,a)=>{return{Comment:"Fan-out workflow",StartAt:"Parallel",States:{Parallel:{Type:"Parallel",Branches:a.map((r)=>r.definition),End:!0}}}},map:(e,t,a,r)=>{return{Comment:"Map workflow",StartAt:"Map",States:{Map:{Type:"Map",ItemsPath:"$.items",Iterator:a,MaxConcurrency:r,End:!0}}}},withErrorHandling:(e,t,a,r)=>{return{Comment:"Workflow with error handling",StartAt:"Main",States:{Main:{...a,Catch:[{ErrorEquals:["States.ALL"],Next:"ErrorHandler"}],Next:"Success"},ErrorHandler:r,Success:{Type:"Succeed"}}}}}}class Qa{static createAlarm(e){let{slug:t,environment:a,alarmName:r,metricName:n,namespace:i,statistic:s="Average",period:o=300,evaluationPeriods:c=1,threshold:l,comparisonOperator:u,treatMissingData:m="notBreaching",actionsEnabled:p=!0,alarmActions:g,okActions:h,insufficientDataActions:y,dimensions:b,unit:T,datapointsToAlarm:w}=e,S=r||A({slug:t,environment:a,resourceType:"alarm"}),E=f(S),v={Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:S,MetricName:n,Namespace:i,Statistic:s,Period:o,EvaluationPeriods:c,Threshold:l,ComparisonOperator:u,TreatMissingData:m,ActionsEnabled:p}};if(g&&g.length>0)v.Properties.AlarmActions=g;if(h&&h.length>0)v.Properties.OKActions=h;if(y&&y.length>0)v.Properties.InsufficientDataActions=y;if(b)v.Properties.Dimensions=Object.entries(b).map(([P,N])=>({Name:P,Value:N}));if(T)v.Properties.Unit=T;if(w!==void 0)v.Properties.DatapointsToAlarm=w;return{alarm:v,logicalId:E}}static createCompositeAlarm(e){let{slug:t,environment:a,alarmName:r,alarmRule:n,actionsEnabled:i=!0,alarmActions:s,okActions:o,insufficientDataActions:c}=e,l=r||A({slug:t,environment:a,resourceType:"composite-alarm"}),u=f(l),m={Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:l,AlarmRule:n,ActionsEnabled:i}};if(s&&s.length>0)m.Properties.AlarmActions=s;if(o&&o.length>0)m.Properties.OKActions=o;if(c&&c.length>0)m.Properties.InsufficientDataActions=c;return{alarm:m,logicalId:u}}static createDashboard(e){let{slug:t,environment:a,dashboardName:r,widgets:n}=e,i=r||A({slug:t,environment:a,resourceType:"dashboard"}),s=f(i),o={widgets:n.map((c)=>({type:c.type,x:c.x,y:c.y,width:c.width,height:c.height,properties:c.properties}))};return{dashboard:{Type:"AWS::CloudWatch::Dashboard",Properties:{DashboardName:i,DashboardBody:JSON.stringify(o)}},logicalId:s}}static createLogGroup(e){let{slug:t,environment:a,logGroupName:r,retentionInDays:n,kmsKeyId:i}=e,s=r||A({slug:t,environment:a,resourceType:"log-group"}),o=f(s),c={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:s}};if(n!==void 0)c.Properties.RetentionInDays=n;if(i)c.Properties.KmsKeyId=i;return{logGroup:c,logicalId:o}}static createLogStream(e,t){let{slug:a,environment:r,logStreamName:n}=t,i=n||A({slug:a,environment:r,resourceType:"log-stream"}),s=f(i);return{logStream:{Type:"AWS::Logs::LogStream",Properties:{LogGroupName:C.Ref(e),LogStreamName:i}},logicalId:s}}static createMetricFilter(e,t){let{slug:a,environment:r,filterName:n,filterPattern:i,metricTransformations:s}=t,o=n||A({slug:a,environment:r,resourceType:"metric-filter"}),c=f(o);return{metricFilter:{Type:"AWS::Logs::MetricFilter",Properties:{LogGroupName:C.Ref(e),FilterPattern:i,MetricTransformations:s.map((l)=>({MetricName:l.metricName,MetricNamespace:l.metricNamespace,MetricValue:l.metricValue,DefaultValue:l.defaultValue,Unit:l.unit}))}},logicalId:c}}static AlarmTypes={highCpu:(e,t,a,r=80,n)=>({slug:e,environment:t,alarmName:`${e}-${t}-high-cpu`,metricName:"CPUUtilization",namespace:"AWS/EC2",statistic:"Average",period:300,evaluationPeriods:2,threshold:r,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:a},alarmActions:n?[n]:void 0}),highMemory:(e,t,a,r=80,n)=>({slug:e,environment:t,alarmName:`${e}-${t}-high-memory`,metricName:"MemoryUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:r,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:a},alarmActions:n?[n]:void 0}),highDisk:(e,t,a,r=80,n)=>({slug:e,environment:t,alarmName:`${e}-${t}-high-disk`,metricName:"DiskSpaceUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:r,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:a,Filesystem:"/dev/xvda1",MountPath:"/"},alarmActions:n?[n]:void 0}),lambdaErrors:(e,t,a,r=5,n)=>({slug:e,environment:t,alarmName:`${e}-${t}-lambda-errors`,metricName:"Errors",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:r,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:a},alarmActions:n?[n]:void 0}),lambdaThrottles:(e,t,a,r=10,n)=>({slug:e,environment:t,alarmName:`${e}-${t}-lambda-throttles`,metricName:"Throttles",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:r,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:a},alarmActions:n?[n]:void 0}),apiGateway5xxErrors:(e,t,a,r=10,n)=>({slug:e,environment:t,alarmName:`${e}-${t}-api-5xx-errors`,metricName:"5XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:1,threshold:r,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:a},alarmActions:n?[n]:void 0}),apiGateway4xxErrors:(e,t,a,r=50,n)=>({slug:e,environment:t,alarmName:`${e}-${t}-api-4xx-errors`,metricName:"4XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:2,threshold:r,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:a},alarmActions:n?[n]:void 0}),dynamoDBThrottles:(e,t,a,r=5,n)=>({slug:e,environment:t,alarmName:`${e}-${t}-dynamodb-throttles`,metricName:"UserErrors",namespace:"AWS/DynamoDB",statistic:"Sum",period:300,evaluationPeriods:1,threshold:r,comparisonOperator:"GreaterThanThreshold",dimensions:{TableName:a},alarmActions:n?[n]:void 0}),rdsCpu:(e,t,a,r=80,n)=>({slug:e,environment:t,alarmName:`${e}-${t}-rds-cpu`,metricName:"CPUUtilization",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:2,threshold:r,comparisonOperator:"GreaterThanThreshold",dimensions:{DBInstanceIdentifier:a},alarmActions:n?[n]:void 0}),rdsFreeStorage:(e,t,a,r=5368709120,n)=>({slug:e,environment:t,alarmName:`${e}-${t}-rds-storage`,metricName:"FreeStorageSpace",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:1,threshold:r,comparisonOperator:"LessThanThreshold",dimensions:{DBInstanceIdentifier:a},alarmActions:n?[n]:void 0,unit:"Bytes"}),sqsQueueDepth:(e,t,a,r=100,n)=>({slug:e,environment:t,alarmName:`${e}-${t}-sqs-depth`,metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",statistic:"Average",period:300,evaluationPeriods:2,threshold:r,comparisonOperator:"GreaterThanThreshold",dimensions:{QueueName:a},alarmActions:n?[n]:void 0}),albUnhealthyTargets:(e,t,a,r,n=1,i)=>({slug:e,environment:t,alarmName:`${e}-${t}-alb-unhealthy`,metricName:"UnHealthyHostCount",namespace:"AWS/ApplicationELB",statistic:"Average",period:300,evaluationPeriods:2,threshold:n,comparisonOperator:"GreaterThanThreshold",dimensions:{LoadBalancer:a,TargetGroup:r},alarmActions:i?[i]:void 0}),sesBounceRate:(e,t,a=5,r)=>({slug:e,environment:t,alarmName:`${e}-${t}-ses-bounce-rate`,metricName:"Reputation.BounceRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:a/100,comparisonOperator:"GreaterThanThreshold",alarmActions:r?[r]:void 0}),sesComplaintRate:(e,t,a=0.1,r)=>({slug:e,environment:t,alarmName:`${e}-${t}-ses-complaint-rate`,metricName:"Reputation.ComplaintRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:a/100,comparisonOperator:"GreaterThanThreshold",alarmActions:r?[r]:void 0}),smsDeliveryFailure:(e,t,a,r=10,n)=>({slug:e,environment:t,alarmName:`${e}-${t}-sms-delivery-failure`,metricName:"DirectSendMessagePermanentFailure",namespace:"AWS/Pinpoint",statistic:"Sum",period:300,evaluationPeriods:1,threshold:r,comparisonOperator:"GreaterThanThreshold",dimensions:{ApplicationId:a},alarmActions:n?[n]:void 0}),smsSpendLimit:(e,t,a=100,r)=>({slug:e,environment:t,alarmName:`${e}-${t}-sms-spend-limit`,metricName:"DirectSendMessageSpend",namespace:"AWS/Pinpoint",statistic:"Sum",period:86400,evaluationPeriods:1,threshold:a,comparisonOperator:"GreaterThanThreshold",alarmActions:r?[r]:void 0}),connectMissedCalls:(e,t,a,r=5,n)=>({slug:e,environment:t,alarmName:`${e}-${t}-connect-missed-calls`,metricName:"MissedCalls",namespace:"AWS/Connect",statistic:"Sum",period:3600,evaluationPeriods:1,threshold:r,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:a},alarmActions:n?[n]:void 0})};static DashboardWidgets={metric:(e,t,a,r,n,i)=>({type:"metric",x:e,y:t,width:a,height:r,properties:{metrics:n,title:i||"Metrics",region:"us-east-1",period:300}}),text:(e,t,a,r,n)=>({type:"text",x:e,y:t,width:a,height:r,properties:{markdown:n}}),log:(e,t,a,r,n,i)=>({type:"log",x:e,y:t,width:a,height:r,properties:{query:`SOURCE '${n.join("' | SOURCE '")}'
2310
2310
  | fields @timestamp, @message
2311
2311
  | sort @timestamp desc
2312
2312
  | limit 20`,region:"us-east-1",title:i||"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:(e,t)=>`{ $.${e} = "${t}" }`,httpStatus:(e)=>`[..., status_code = ${e}, ...]`,http4xx:"[..., status_code = 4*, ...]",http5xx:"[..., status_code = 5*, ...]"};static createApplicationDashboard(e){let{slug:t,environment:a,region:r="us-east-1",components:n={}}=e,i=[],s=0;if(i.push({type:"text",x:0,y:s,width:24,height:1,properties:{markdown:`# ${t.toUpperCase()} Dashboard (${a})`}}),s+=1,n.ec2InstanceIds&&n.ec2InstanceIds.length>0)i.push({type:"text",x:0,y:s,width:24,height:1,properties:{markdown:"## EC2 Instances"}}),s+=1,i.push({type:"metric",x:0,y:s,width:8,height:6,properties:{title:"CPU Utilization",region:r,metrics:n.ec2InstanceIds.map((o)=>["AWS/EC2","CPUUtilization","InstanceId",o]),period:300,stat:"Average"}}),i.push({type:"metric",x:8,y:s,width:8,height:6,properties:{title:"Network Traffic",region:r,metrics:[...n.ec2InstanceIds.flatMap((o)=>[["AWS/EC2","NetworkIn","InstanceId",o,{label:`${o} In`}],["AWS/EC2","NetworkOut","InstanceId",o,{label:`${o} Out`}]])],period:300,stat:"Sum"}}),i.push({type:"metric",x:16,y:s,width:8,height:6,properties:{title:"Status Checks",region:r,metrics:n.ec2InstanceIds.map((o)=>["AWS/EC2","StatusCheckFailed","InstanceId",o]),period:60,stat:"Maximum"}}),s+=6;if(n.lambdaFunctionNames&&n.lambdaFunctionNames.length>0)i.push({type:"text",x:0,y:s,width:24,height:1,properties:{markdown:"## Lambda Functions"}}),s+=1,i.push({type:"metric",x:0,y:s,width:8,height:6,properties:{title:"Invocations",region:r,metrics:n.lambdaFunctionNames.map((o)=>["AWS/Lambda","Invocations","FunctionName",o]),period:300,stat:"Sum"}}),i.push({type:"metric",x:8,y:s,width:8,height:6,properties:{title:"Duration",region:r,metrics:n.lambdaFunctionNames.map((o)=>["AWS/Lambda","Duration","FunctionName",o]),period:300,stat:"Average"}}),i.push({type:"metric",x:16,y:s,width:8,height:6,properties:{title:"Errors",region:r,metrics:n.lambdaFunctionNames.map((o)=>["AWS/Lambda","Errors","FunctionName",o]),period:300,stat:"Sum"}}),s+=6;if(n.ecsClusterName&&n.ecsServiceName)i.push({type:"text",x:0,y:s,width:24,height:1,properties:{markdown:"## ECS Service"}}),s+=1,i.push({type:"metric",x:0,y:s,width:8,height:6,properties:{title:"CPU Utilization",region:r,metrics:[["AWS/ECS","CPUUtilization","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:300,stat:"Average"}}),i.push({type:"metric",x:8,y:s,width:8,height:6,properties:{title:"Memory Utilization",region:r,metrics:[["AWS/ECS","MemoryUtilization","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:300,stat:"Average"}}),i.push({type:"metric",x:16,y:s,width:8,height:6,properties:{title:"Running Tasks",region:r,metrics:[["ECS/ContainerInsights","RunningTaskCount","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:60,stat:"Average"}}),s+=6;if(n.albName)i.push({type:"text",x:0,y:s,width:24,height:1,properties:{markdown:"## Application Load Balancer"}}),s+=1,i.push({type:"metric",x:0,y:s,width:8,height:6,properties:{title:"Request Count",region:r,metrics:[["AWS/ApplicationELB","RequestCount","LoadBalancer",n.albName]],period:60,stat:"Sum"}}),i.push({type:"metric",x:8,y:s,width:8,height:6,properties:{title:"Response Time",region:r,metrics:[["AWS/ApplicationELB","TargetResponseTime","LoadBalancer",n.albName]],period:60,stat:"Average"}}),i.push({type:"metric",x:16,y:s,width:8,height:6,properties:{title:"HTTP Errors",region:r,metrics:[["AWS/ApplicationELB","HTTPCode_Target_4XX_Count","LoadBalancer",n.albName,{label:"4XX"}],["AWS/ApplicationELB","HTTPCode_Target_5XX_Count","LoadBalancer",n.albName,{label:"5XX"}]],period:60,stat:"Sum"}}),s+=6;if(n.rdsInstanceId)i.push({type:"text",x:0,y:s,width:24,height:1,properties:{markdown:"## RDS Database"}}),s+=1,i.push({type:"metric",x:0,y:s,width:8,height:6,properties:{title:"CPU Utilization",region:r,metrics:[["AWS/RDS","CPUUtilization","DBInstanceIdentifier",n.rdsInstanceId]],period:300,stat:"Average"}}),i.push({type:"metric",x:8,y:s,width:8,height:6,properties:{title:"Database Connections",region:r,metrics:[["AWS/RDS","DatabaseConnections","DBInstanceIdentifier",n.rdsInstanceId]],period:60,stat:"Sum"}}),i.push({type:"metric",x:16,y:s,width:8,height:6,properties:{title:"Free Storage Space",region:r,metrics:[["AWS/RDS","FreeStorageSpace","DBInstanceIdentifier",n.rdsInstanceId]],period:300,stat:"Average"}}),s+=6;if(n.sqsQueueNames&&n.sqsQueueNames.length>0)i.push({type:"text",x:0,y:s,width:24,height:1,properties:{markdown:"## SQS Queues"}}),s+=1,i.push({type:"metric",x:0,y:s,width:12,height:6,properties:{title:"Messages Visible",region:r,metrics:n.sqsQueueNames.map((o)=>["AWS/SQS","ApproximateNumberOfMessagesVisible","QueueName",o]),period:60,stat:"Sum"}}),i.push({type:"metric",x:12,y:s,width:12,height:6,properties:{title:"Message Age",region:r,metrics:n.sqsQueueNames.map((o)=>["AWS/SQS","ApproximateAgeOfOldestMessage","QueueName",o]),period:60,stat:"Maximum"}}),s+=6;if(n.logGroupNames&&n.logGroupNames.length>0)i.push({type:"text",x:0,y:s,width:24,height:1,properties:{markdown:"## Application Logs"}}),s+=1,i.push({type:"log",x:0,y:s,width:24,height:6,properties:{query:`SOURCE '${n.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:r,title:"Recent Errors and Warnings"}}),s+=6;return Ja.createDashboard({slug:t,environment:a,widgets:i})}static DashboardTemplates={staticWebsite:(e)=>({slug:e.slug,environment:e.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${e.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",e.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",e.cloudFrontDistributionId,"Region","Global",{label:"4XX"}],["AWS/CloudFront","5xxErrorRate","DistributionId",e.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",e.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:0,y:7,width:12,height:6,properties:{title:"S3 Bucket Size",region:e.region||"us-east-1",metrics:[["AWS/S3","BucketSizeBytes","BucketName",e.s3BucketName,"StorageType","StandardStorage"]],period:86400,stat:"Average"}},{type:"metric",x:12,y:7,width:12,height:6,properties:{title:"S3 Number of Objects",region:e.region||"us-east-1",metrics:[["AWS/S3","NumberOfObjects","BucketName",e.s3BucketName,"StorageType","AllStorageTypes"]],period:86400,stat:"Average"}}]}),serverlessApi:(e)=>({slug:e.slug,environment:e.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${e.slug.toUpperCase()} Serverless API Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"API Requests",region:e.region||"us-east-1",metrics:[["AWS/ApiGateway","Count","ApiName",e.apiGatewayName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"API Latency",region:e.region||"us-east-1",metrics:[["AWS/ApiGateway","Latency","ApiName",e.apiGatewayName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"API Errors",region:e.region||"us-east-1",metrics:[["AWS/ApiGateway","4XXError","ApiName",e.apiGatewayName,{label:"4XX"}],["AWS/ApiGateway","5XXError","ApiName",e.apiGatewayName,{label:"5XX"}]],period:60,stat:"Sum"}},...e.lambdaFunctionNames.map((t,a)=>({type:"metric",x:a%3*8,y:7+Math.floor(a/3)*6,width:8,height:6,properties:{title:`${t} Metrics`,region:e.region||"us-east-1",metrics:[["AWS/Lambda","Invocations","FunctionName",t],["AWS/Lambda","Duration","FunctionName",t],["AWS/Lambda","Errors","FunctionName",t]],period:300,stat:"Sum"}}))]}),containerService:(e)=>({slug:e.slug,environment:e.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${e.slug.toUpperCase()} Container Service Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"ECS CPU",region:e.region||"us-east-1",metrics:[["AWS/ECS","CPUUtilization","ClusterName",e.ecsClusterName,"ServiceName",e.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"ECS Memory",region:e.region||"us-east-1",metrics:[["AWS/ECS","MemoryUtilization","ClusterName",e.ecsClusterName,"ServiceName",e.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Running Tasks",region:e.region||"us-east-1",metrics:[["ECS/ContainerInsights","RunningTaskCount","ClusterName",e.ecsClusterName,"ServiceName",e.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:0,y:7,width:8,height:6,properties:{title:"ALB Requests",region:e.region||"us-east-1",metrics:[["AWS/ApplicationELB","RequestCount","LoadBalancer",e.albName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:7,width:8,height:6,properties:{title:"Response Time",region:e.region||"us-east-1",metrics:[["AWS/ApplicationELB","TargetResponseTime","LoadBalancer",e.albName]],period:60,stat:"Average"}},{type:"metric",x:16,y:7,width:8,height:6,properties:{title:"Healthy Hosts",region:e.region||"us-east-1",metrics:[["AWS/ApplicationELB","HealthyHostCount","LoadBalancer",e.albName]],period:60,stat:"Average"}},...e.rdsInstanceId?[{type:"metric",x:0,y:13,width:12,height:6,properties:{title:"RDS CPU",region:e.region||"us-east-1",metrics:[["AWS/RDS","CPUUtilization","DBInstanceIdentifier",e.rdsInstanceId]],period:300,stat:"Average"}},{type:"metric",x:12,y:13,width:12,height:6,properties:{title:"RDS Connections",region:e.region||"us-east-1",metrics:[["AWS/RDS","DatabaseConnections","DBInstanceIdentifier",e.rdsInstanceId]],period:60,stat:"Sum"}}]:[]]})};static Config={createAlarmConfig:(e)=>{let{metricName:t,namespace:a,threshold:r,comparisonOperator:n="GreaterThanThreshold",evaluationPeriods:i=1,period:s=300,statistic:o="Average",treatMissingData:c="missing"}=e;return{MetricName:t,Namespace:a,Threshold:r,ComparisonOperator:n,EvaluationPeriods:i,Period:s,Statistic:o,TreatMissingData:c}},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:(e=80)=>({metricName:"CPUUtilization",threshold:e,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highMemory:(e=80)=>({metricName:"MemoryUtilization",threshold:e,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highErrors:(e=10)=>({metricName:"Errors",threshold:e,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:1,period:60,statistic:"Sum"}),highLatency:(e=5000)=>({metricName:"Duration",threshold:e,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowHealthyHosts:(e=1)=>({metricName:"HealthyHostCount",namespace:"AWS/ApplicationELB",threshold:e,comparisonOperator:"LessThanThreshold",evaluationPeriods:2,period:60,statistic:"Minimum"}),queueDepth:(e=1000)=>({metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",threshold:e,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowStorage:(e=10737418240)=>({metricName:"FreeStorageSpace",namespace:"AWS/RDS",threshold:e,comparisonOperator:"LessThanThreshold",evaluationPeriods:1,period:300,statistic:"Average"})}}}class Q{static createUserPool(e){let{slug:t,environment:a,userPoolName:r,aliasAttributes:n,autoVerifiedAttributes:i,passwordPolicy:s,mfaConfiguration:o,emailConfiguration:c,smsConfiguration:l,lambdaTriggers:u,userPoolAddOns:m,accountRecoverySetting:p}=e,g=r||A({slug:t,environment:a,resourceType:"user-pool"}),h=f(g),y={Type:"AWS::Cognito::UserPool",Properties:{UserPoolName:g,Policies:s?{PasswordPolicy:{MinimumLength:s.minimumLength,RequireLowercase:s.requireLowercase,RequireUppercase:s.requireUppercase,RequireNumbers:s.requireNumbers,RequireSymbols:s.requireSymbols,TemporaryPasswordValidityDays:s.temporaryPasswordValidityDays}}:void 0,MfaConfiguration:o,Schema:[{Name:"email",AttributeDataType:"String",Required:!0,Mutable:!1}]}};if(n&&n.length>0)y.Properties.UsernameAttributes=n;if(i&&i.length>0)y.Properties.AutoVerifiedAttributes=i;if(c)y.Properties.EmailConfiguration={EmailSendingAccount:c.emailSendingAccount,From:c.from,ReplyToEmailAddress:c.replyToEmailAddress,SourceArn:c.sourceArn,ConfigurationSet:c.configurationSet};if(l)y.Properties.SmsConfiguration={ExternalId:l.externalId,SnsCallerArn:l.snsCallerArn};if(u)y.Properties.LambdaConfig={PreSignUp:u.preSignUp,PostConfirmation:u.postConfirmation,PreAuthentication:u.preAuthentication,PostAuthentication:u.postAuthentication,CustomMessage:u.customMessage,DefineAuthChallenge:u.defineAuthChallenge,CreateAuthChallenge:u.createAuthChallenge,VerifyAuthChallengeResponse:u.verifyAuthChallengeResponse,PreTokenGeneration:u.preTokenGeneration,UserMigration:u.userMigration};if(m)y.Properties.UserPoolAddOns={AdvancedSecurityMode:m.advancedSecurityMode};if(p)y.Properties.AccountRecoverySetting={RecoveryMechanisms:p.recoveryMechanisms};return{userPool:y,logicalId:h}}static createUserPoolClient(e,t){let{slug:a,environment:r,clientName:n,generateSecret:i=!1,refreshTokenValidity:s,accessTokenValidity:o,idTokenValidity:c,tokenValidityUnits:l,readAttributes:u,writeAttributes:m,explicitAuthFlows:p,preventUserExistenceErrors:g,enableTokenRevocation:h,callbackURLs:y,logoutURLs:b,allowedOAuthFlows:T,allowedOAuthScopes:w,allowedOAuthFlowsUserPoolClient:S,supportedIdentityProviders:E}=t,v=n||A({slug:a,environment:r,resourceType:"user-pool-client"}),P=f(v);return{client:{Type:"AWS::Cognito::UserPoolClient",Properties:{ClientName:v,UserPoolId:C.Ref(e),GenerateSecret:i,RefreshTokenValidity:s,AccessTokenValidity:o,IdTokenValidity:c,TokenValidityUnits:l,ReadAttributes:u,WriteAttributes:m,ExplicitAuthFlows:p,PreventUserExistenceErrors:g,EnableTokenRevocation:h,CallbackURLs:y,LogoutURLs:b,AllowedOAuthFlows:T,AllowedOAuthScopes:w,AllowedOAuthFlowsUserPoolClient:S,SupportedIdentityProviders:E}},logicalId:P}}static createUserPoolDomain(e,t){let{slug:a,environment:r,domain:n,customDomainConfig:i}=t,s=A({slug:a,environment:r,resourceType:"user-pool-domain"}),o=f(s);return{domain:{Type:"AWS::Cognito::UserPoolDomain",Properties:{Domain:n,UserPoolId:C.Ref(e),CustomDomainConfig:i}},logicalId:o}}static createIdentityPool(e){let{slug:t,environment:a,identityPoolName:r,allowUnauthenticatedIdentities:n=!1,cognitoIdentityProviders:i,supportedLoginProviders:s,samlProviderARNs:o,openIdConnectProviderARNs:c}=e,l=r||A({slug:t,environment:a,resourceType:"identity-pool"}),u=f(l);return{identityPool:{Type:"AWS::Cognito::IdentityPool",Properties:{IdentityPoolName:l,AllowUnauthenticatedIdentities:n,CognitoIdentityProviders:i,SupportedLoginProviders:s,SamlProviderARNs:o,OpenIdConnectProviderARNs:c}},logicalId:u}}static createIdentityPoolRoleAttachment(e,t){let{slug:a,environment:r,authenticatedRole:n,unauthenticatedRole:i,roleMappings:s}=t,o=A({slug:a,environment:r,resourceType:"identity-pool-role-attachment"}),c=f(o),l={authenticated:n};if(i)l.unauthenticated=i;return{attachment:{Type:"AWS::Cognito::IdentityPoolRoleAttachment",Properties:{IdentityPoolId:C.Ref(e),Roles:l,RoleMappings:s}},logicalId:c}}static createAuthenticatedRole(e){let{slug:t,environment:a,identityPoolLogicalId:r}=e,n=A({slug:t,environment:a,resourceType:"cognito-authenticated-role"}),i=f(n);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:n,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":C.Ref(r)},"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:n},{Key:"Environment",Value:a}]}},logicalId:i}}static createUnauthenticatedRole(e){let{slug:t,environment:a,identityPoolLogicalId:r}=e,n=A({slug:t,environment:a,resourceType:"cognito-unauthenticated-role"}),i=f(n);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:n,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":C.Ref(r)},"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:n},{Key:"Environment",Value:a}]}},logicalId:i}}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:(e,t,a)=>{let{userPool:r,logicalId:n}=Q.createUserPool({slug:e,environment:t,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:Q.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:i,logicalId:s}=Q.createUserPoolClient(n,{slug:e,environment:t,explicitAuthFlows:[...Q.AuthFlows.standard],callbackURLs:[a],allowedOAuthFlows:["code"],allowedOAuthScopes:[...Q.OAuthScopes.basic],allowedOAuthFlowsUserPoolClient:!0});return{userPool:r,poolId:n,client:i,clientId:s}},mobileApp:(e,t)=>{let{userPool:a,logicalId:r}=Q.createUserPool({slug:e,environment:t,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:Q.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:n,logicalId:i}=Q.createUserPoolClient(r,{slug:e,environment:t,explicitAuthFlows:[...Q.AuthFlows.standard]}),{identityPool:s,logicalId:o}=Q.createIdentityPool({slug:e,environment:t,allowUnauthenticatedIdentities:!1,cognitoIdentityProviders:[{ClientId:C.Ref(i),ProviderName:C.GetAtt(r,"ProviderName")}]}),{role:c,logicalId:l}=Q.createAuthenticatedRole({slug:e,environment:t,identityPoolLogicalId:o}),{attachment:u,logicalId:m}=Q.createIdentityPoolRoleAttachment(o,{slug:e,environment:t,authenticatedRole:C.GetAtt(l,"Arn")});return{userPool:a,poolId:r,client:n,clientId:i,identityPool:s,identityPoolId:o,authRole:c,authRoleId:l,attachment:u,attachmentId:m}}}}class J{static createApplication(e){let{slug:t,environment:a,applicationName:r,computePlatform:n}=e,i=r||A({slug:t,environment:a,resourceType:"deploy-app"}),s=f(i);return{application:{Type:"AWS::CodeDeploy::Application",Properties:{ApplicationName:i,ComputePlatform:n,Tags:[{Key:"Name",Value:i},{Key:"Environment",Value:a}]}},logicalId:s}}static createDeploymentGroup(e,t){let{slug:a,environment:r,deploymentGroupName:n,serviceRoleArn:i,autoScalingGroups:s,ec2TagFilters:o,deploymentConfigName:c,autoRollbackConfiguration:l,alarmConfiguration:u,loadBalancerInfo:m,blueGreenDeploymentConfiguration:p}=t,g=n||A({slug:a,environment:r,resourceType:"deploy-group"}),h=f(g);return{deploymentGroup:{Type:"AWS::CodeDeploy::DeploymentGroup",Properties:{ApplicationName:C.Ref(e),DeploymentGroupName:g,ServiceRoleArn:i,AutoScalingGroups:s,Ec2TagFilters:o?.map((y)=>({Key:y.key,Value:y.value,Type:y.type})),DeploymentConfigName:c,AutoRollbackConfiguration:l?{Enabled:l.enabled,Events:l.events}:void 0,AlarmConfiguration:u?{Enabled:u.enabled,Alarms:u.alarms?.map((y)=>({Name:y.name})),IgnorePollAlarmFailure:u.ignorePollAlarmFailure}:void 0,LoadBalancerInfo:m?{TargetGroupInfoList:m.targetGroupInfoList?.map((y)=>({Name:y.name})),ElbInfoList:m.elbInfoList?.map((y)=>({Name:y.name}))}:void 0,BlueGreenDeploymentConfiguration:p?{TerminateBlueInstancesOnDeploymentSuccess:p.terminateBlueInstancesOnDeploymentSuccess?{Action:p.terminateBlueInstancesOnDeploymentSuccess.action,TerminationWaitTimeInMinutes:p.terminateBlueInstancesOnDeploymentSuccess.terminationWaitTimeInMinutes}:void 0,DeploymentReadyOption:p.deploymentReadyOption?{ActionOnTimeout:p.deploymentReadyOption.actionOnTimeout,WaitTimeInMinutes:p.deploymentReadyOption.waitTimeInMinutes}:void 0,GreenFleetProvisioningOption:p.greenFleetProvisioningOption?{Action:p.greenFleetProvisioningOption.action}:void 0}:void 0,Tags:[{Key:"Name",Value:g},{Key:"Environment",Value:r}]}},logicalId:h}}static createDeploymentConfig(e){let{slug:t,environment:a,deploymentConfigName:r,minimumHealthyHosts:n,trafficRoutingConfig:i}=e,s=r||A({slug:t,environment:a,resourceType:"deploy-config"}),o=f(s);return{deploymentConfig:{Type:"AWS::CodeDeploy::DeploymentConfig",Properties:{DeploymentConfigName:s,MinimumHealthyHosts:n?{Type:n.type,Value:n.value}:void 0,TrafficRoutingConfig:i?{Type:i.type,TimeBasedCanary:i.timeBasedCanary?{CanaryPercentage:i.timeBasedCanary.canaryPercentage,CanaryInterval:i.timeBasedCanary.canaryInterval}:void 0,TimeBasedLinear:i.timeBasedLinear?{LinearPercentage:i.timeBasedLinear.linearPercentage,LinearInterval:i.timeBasedLinear.linearInterval}:void 0}:void 0}},logicalId:o}}static DeploymentConfigs={allAtOnce:()=>({type:"FLEET_PERCENT",value:0}),halfAtATime:()=>({type:"FLEET_PERCENT",value:50}),oneAtATime:()=>({type:"HOST_COUNT",value:1}),custom:(e,t)=>({type:e,value:t})};static TrafficRouting={allAtOnce:()=>({type:"AllAtOnce"}),canary:(e,t)=>({type:"TimeBasedCanary",timeBasedCanary:{canaryPercentage:e,canaryInterval:t}}),linear:(e,t)=>({type:"TimeBasedLinear",timeBasedLinear:{linearPercentage:e,linearInterval:t}})};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:(e)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:e},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withManualApproval:(e)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"STOP_DEPLOYMENT",waitTimeInMinutes:e},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:(e,t,a,r)=>{let{application:n,logicalId:i}=J.createApplication({slug:e,environment:t,computePlatform:"Server"}),{deploymentGroup:s,logicalId:o}=J.createDeploymentGroup(i,{slug:e,environment:t,serviceRoleArn:a,autoScalingGroups:r,deploymentConfigName:"CodeDeployDefault.OneAtATime",autoRollbackConfiguration:J.RollbackConfigs.onFailure()});return{application:n,appId:i,deploymentGroup:s,groupId:o}},lambdaCanaryDeployment:(e,t,a,r=10,n=5)=>{let{application:i,logicalId:s}=J.createApplication({slug:e,environment:t,computePlatform:"Lambda"}),{deploymentConfig:o,logicalId:c}=J.createDeploymentConfig({slug:e,environment:t,trafficRoutingConfig:J.TrafficRouting.canary(r,n)}),{deploymentGroup:l,logicalId:u}=J.createDeploymentGroup(s,{slug:e,environment:t,serviceRoleArn:a,deploymentConfigName:C.Ref(c),autoRollbackConfiguration:J.RollbackConfigs.onAlarmOrFailure()});return{application:i,appId:s,deploymentConfig:o,configId:c,deploymentGroup:l,groupId:u}},ecsBlueGreenDeployment:(e,t,a,r)=>{let{application:n,logicalId:i}=J.createApplication({slug:e,environment:t,computePlatform:"ECS"}),{deploymentGroup:s,logicalId:o}=J.createDeploymentGroup(i,{slug:e,environment:t,serviceRoleArn:a,loadBalancerInfo:{targetGroupInfoList:[{name:r}]},blueGreenDeploymentConfiguration:J.BlueGreenConfigs.standard(),autoRollbackConfiguration:J.RollbackConfigs.onFailure()});return{application:n,appId:i,deploymentGroup:s,groupId:o}}};static Strategies={rolling:(e=25)=>({type:"rolling",batchPercentage:e}),blueGreen:()=>({type:"blue-green"}),canary:(e=10,t=5)=>({type:"canary",canaryPercentage:e,canaryInterval:t}),allAtOnce:()=>({type:"all-at-once"})}}class U{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(e,t="md5"){let a=ot(e);return Wi(t).update(a).digest("hex")}static computeShortHash(e){return U.computeFileHash(e).slice(0,8)}static getContentType(e){let t=fa(e).toLowerCase();return U.ContentTypes[t]||"application/octet-stream"}static shouldHashFile(e,t){return![...U.NoHashPatterns,...t||[]].some((a)=>a.test(e))}static generateHashedFilename(e,t){let a=fa(e),r=Ui(e,a),n=ya(e);if(n===".")return`${r}.${t}${a}`;return He(n,`${r}.${t}${a}`)}static collectFiles(e,t){let a=[],r=t||e;if(!xt(e))return a;let n=Fi(e,{withFileTypes:!0});for(let i of n){let s=He(e,i.name);if(i.isDirectory())a.push(...U.collectFiles(s,r));else if(i.isFile())a.push(s)}return a}static hashDirectory(e){let{sourceDir:t,outputDir:a,excludePatterns:r=[],hashAlgorithm:n="md5",copyUnhashed:i=!0}=e,s=U.collectFiles(t),o=[],c={};for(let u of s){let m=u.replace(t,"").replace(/^[/\\]/,""),p=U.shouldHashFile(m,r),g=Vi(u),h=p?U.computeFileHash(u,n).slice(0,8):"",y=p?U.generateHashedFilename(m,h):m,b={originalPath:m,hashedPath:y,hash:h,size:g.size,contentType:U.getContentType(u)};if(o.push(b),c[m]=y,a){let T=He(a,y),w=ya(T);if(!xt(w)){let{mkdirSync:S}=Vn("node:fs");S(w,{recursive:!0})}if(p||i)Gi(u,T)}}let l={version:"1.0",timestamp:new Date().toISOString(),assets:o,hashMap:c};if(a){let u=He(a,"asset-manifest.json");ct(u,JSON.stringify(l,null,2))}return l}static getInvalidationPaths(e,t){let a=[];if(!e)return["/*"];let r=e.hashMap,n=t.hashMap;for(let[i,s]of Object.entries(n)){let o=r[i];if(!o||o!==s){if(a.push(`/${i}`),o&&o!==s)a.push(`/${o}`)}}for(let[i,s]of Object.entries(r))if(!n[i])a.push(`/${i}`),a.push(`/${s}`);if(a.length>100)return["/*"];return[...new Set(a)]}static updateHtmlReferences(e){let{htmlDir:t,manifest:a,basePath:r=""}=e,n=U.collectFiles(t).filter((i)=>i.endsWith(".html")||i.endsWith(".htm"));for(let i of n){let s=ot(i,"utf-8");for(let[o,c]of Object.entries(a.hashMap)){if(o===c)continue;let l=[new RegExp(`(src|href)=["']${r}/?${U.escapeRegExp(o)}["']`,"g"),new RegExp(`url\\(["']?${r}/?${U.escapeRegExp(o)}["']?\\)`,"g")];for(let u of l)s=s.replace(u,(m)=>m.replace(o,c))}ct(i,s)}}static updateCssReferences(e){let{cssDir:t,manifest:a,basePath:r=""}=e,n=U.collectFiles(t).filter((i)=>i.endsWith(".css"));for(let i of n){let s=ot(i,"utf-8");for(let[o,c]of Object.entries(a.hashMap)){if(o===c)continue;let l=new RegExp(`url\\(["']?${r}/?${U.escapeRegExp(o)}["']?\\)`,"g");s=s.replace(l,`url(${r}/${c})`)}ct(i,s)}}static escapeRegExp(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}static generateS3DeploymentManifest(e){let{sourceDir:t,keyPrefix:a="",excludePatterns:r=[],cacheControl:n={hashed:"public, max-age=31536000, immutable",unhashed:"public, max-age=3600",html:"public, max-age=0, must-revalidate"}}=e;return U.hashDirectory({sourceDir:t,excludePatterns:r}).assets.map((i)=>{let s=i.hash!=="",o=i.contentType==="text/html",c=n.unhashed||"public, max-age=3600";if(o)c=n.html||"public, max-age=0, must-revalidate";else if(s)c=n.hashed||"public, max-age=31536000, immutable";return{localPath:He(t,i.originalPath),s3Key:a?`${a}/${i.hashedPath}`:i.hashedPath,contentType:i.contentType,cacheControl:c,hash:i.hash}})}static compareManifests(e,t){let a={added:[],removed:[],changed:[],unchanged:[]},r=new Set(Object.keys(e.hashMap)),n=new Set(Object.keys(t.hashMap));for(let i of n)if(!r.has(i))a.added.push(i);for(let i of r)if(!n.has(i))a.removed.push(i);for(let i of n)if(r.has(i))if(e.hashMap[i]!==t.hashMap[i])a.changed.push(i);else a.unchanged.push(i);return a}static loadManifest(e){if(!xt(e))return null;try{let t=ot(e,"utf-8");return JSON.parse(t)}catch{return null}}static saveManifest(e,t){ct(t,JSON.stringify(e,null,2))}}class Qe{static createSecret(e){let{slug:t,environment:a,secretName:r,description:n,secretString:i,kmsKeyId:s,tags:o}=e,c=r||A({slug:t,environment:a,resourceType:"secret"}),l=f(c),u={Type:"AWS::SecretsManager::Secret",Properties:{Name:c,Description:n,SecretString:i,Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:a},...o?Object.entries(o).map(([m,p])=>({Key:m,Value:p})):[]]}};if(s)u.Properties.KmsKeyId=s;return{secret:u,logicalId:l}}static createGeneratedSecret(e){let{slug:t,environment:a,secretName:r,description:n,excludeCharacters:i,excludeLowercase:s,excludeNumbers:o,excludePunctuation:c,excludeUppercase:l,passwordLength:u,requireEachIncludedType:m,kmsKeyId:p,tags:g}=e,h=r||A({slug:t,environment:a,resourceType:"secret"}),y=f(h),b={Type:"AWS::SecretsManager::Secret",Properties:{Name:h,Description:n,GenerateSecretString:{ExcludeCharacters:i,ExcludeLowercase:s,ExcludeNumbers:o,ExcludePunctuation:c,ExcludeUppercase:l,PasswordLength:u||32,RequireEachIncludedType:m!==!1},Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:a},...g?Object.entries(g).map(([T,w])=>({Key:T,Value:w})):[]]}};if(p)b.Properties.KmsKeyId=p;return{secret:b,logicalId:y}}static createDatabaseSecret(e){let{slug:t,environment:a,secretName:r,username:n,dbname:i,engine:s,host:o,port:c,kmsKeyId:l}=e,u=r||A({slug:t,environment:a,resourceType:"db-secret"}),m=f(u),p={username:n};if(i)p.dbname=i;if(s)p.engine=s;if(o)p.host=o;if(c)p.port=c;let g={Type:"AWS::SecretsManager::Secret",Properties:{Name:u,Description:`Database credentials for ${n}`,GenerateSecretString:{SecretStringTemplate:JSON.stringify(p),GenerateStringKey:"password",PasswordLength:32,ExcludeCharacters:'"@/\\',RequireEachIncludedType:!0},Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:a},{Key:"Type",Value:"database"}]}};if(l)g.Properties.KmsKeyId=l;return{secret:g,logicalId:m}}static attachToDatabase(e){let{slug:t,environment:a,secretId:r,targetId:n,targetType:i}=e,s=A({slug:t,environment:a,resourceType:"secret-attachment"}),o=f(s);return{attachment:{Type:"AWS::SecretsManager::SecretTargetAttachment",Properties:{SecretId:r,TargetId:n,TargetType:i}},logicalId:o}}static enableRotation(e){let{slug:t,environment:a,secretId:r,rotationLambdaArn:n,automaticallyAfterDays:i,rotationType:s,kmsKeyArn:o,vpcSecurityGroupIds:c,vpcSubnetIds:l}=e,u=A({slug:t,environment:a,resourceType:"secret-rotation"}),m=f(u),p={Type:"AWS::SecretsManager::RotationSchedule",Properties:{SecretId:r,RotationRules:{AutomaticallyAfterDays:i||30}}};if(n)p.Properties.RotationLambdaARN=n;else if(s)p.Properties.HostedRotationLambda={RotationType:s,KmsKeyArn:o,VpcSecurityGroupIds:c,VpcSubnetIds:l};return{rotation:p,logicalId:m}}static SecretTypes={apiKey:(e,t,a)=>Qe.createGeneratedSecret({slug:e,environment:t,secretName:`${e}-${t}-${a}-api-key`,description:`API key for ${a}`,passwordLength:32,excludePunctuation:!0,excludeLowercase:!1,excludeUppercase:!1,excludeNumbers:!1}),oauthClientSecret:(e,t,a)=>Qe.createGeneratedSecret({slug:e,environment:t,secretName:`${e}-${t}-${a}-oauth-secret`,description:`OAuth client secret for ${a}`,passwordLength:64,excludeCharacters:"\"'`\\/@",requireEachIncludedType:!0}),jwtSecret:(e,t)=>Qe.createGeneratedSecret({slug:e,environment:t,secretName:`${e}-${t}-jwt-secret`,description:"JWT signing secret",passwordLength:64,excludePunctuation:!0}),encryptionKey:(e,t)=>Qe.createGeneratedSecret({slug:e,environment:t,secretName:`${e}-${t}-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 W{static createParameter(e){let{slug:t,environment:a,parameterName:r,value:n,type:i="String",description:s,tier:o="Standard",tags:c}=e,l=r||A({slug:t,environment:a,resourceType:"parameter"}),u=f(l);return{parameter:{Type:"AWS::SSM::Parameter",Properties:{Name:`/${t}/${a}/${l}`,Type:i,Value:n,Description:s,Tier:o,Tags:{Name:l,Environment:a,...c}}},logicalId:u}}static createString(e,t,a,r,n){return W.createParameter({slug:e,environment:t,parameterName:a,value:r,type:"String",description:n})}static createSecureString(e,t,a,r,n){return W.createParameter({slug:e,environment:t,parameterName:a,value:r,type:"SecureString",description:n})}static createStringList(e,t,a,r,n){return W.createParameter({slug:e,environment:t,parameterName:a,value:r.join(","),type:"StringList",description:n})}static Parameters={databaseUrl:(e,t,a)=>W.createSecureString(e,t,"database-url",a,"Database connection URL"),apiEndpoint:(e,t,a)=>W.createString(e,t,"api-endpoint",a,"API endpoint URL"),appVersion:(e,t,a)=>W.createString(e,t,"app-version",a,"Application version"),featureFlags:(e,t,a)=>W.createStringList(e,t,"feature-flags",a,"Enabled feature flags"),apiKey:(e,t,a,r)=>W.createSecureString(e,t,`${a}-api-key`,r,`API key for ${a}`),oauthCredentials:(e,t,a,r)=>{let n=W.createString(e,t,"oauth-client-id",a,"OAuth client ID"),i=W.createSecureString(e,t,"oauth-client-secret",r,"OAuth client secret");return{clientId:n,clientSecret:i}},smtpCredentials:(e,t,a,r,n,i)=>{let s=W.createString(e,t,"smtp-username",a,"SMTP username"),o=W.createSecureString(e,t,"smtp-password",r,"SMTP password"),c=W.createString(e,t,"smtp-host",n,"SMTP host"),l=W.createString(e,t,"smtp-port",i.toString(),"SMTP port");return{username:s,password:o,host:c,port:l}},redisUrl:(e,t,a)=>W.createSecureString(e,t,"redis-url",a,"Redis connection URL"),s3Bucket:(e,t,a)=>W.createString(e,t,"s3-bucket",a,"S3 bucket name"),cloudFrontDistribution:(e,t,a)=>W.createString(e,t,"cloudfront-distribution-id",a,"CloudFront distribution ID")}}class Je{static createDomain(e){let{slug:t,environment:a,domainName:r,engineVersion:n="OpenSearch_2.11",instanceType:i="t3.small.search",instanceCount:s=1,volumeSize:o=10,volumeType:c="gp3",dedicatedMaster:l=!1,dedicatedMasterType:u,dedicatedMasterCount:m=3,multiAz:p=!1,availabilityZoneCount:g=2,vpc:h,encryption:y,enforceHttps:b=!0,tlsSecurityPolicy:T="Policy-Min-TLS-1-2-2019-07",advancedSecurity:w,autoSnapshotHour:S=0,autoTune:E=!0,tags:v={}}=e,P=r||A({slug:t,environment:a,resourceType:"search"}),N=f(P);return{domain:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:P,EngineVersion:n,ClusterConfig:{InstanceType:i,InstanceCount:s,DedicatedMasterEnabled:l,...l&&{DedicatedMasterType:u||i,DedicatedMasterCount:m},ZoneAwarenessEnabled:p,...p&&{ZoneAwarenessConfig:{AvailabilityZoneCount:g}}},EBSOptions:{EBSEnabled:!0,VolumeType:c,VolumeSize:o},DomainEndpointOptions:{EnforceHTTPS:b,TLSSecurityPolicy:T},SnapshotOptions:{AutomatedSnapshotStartHour:S},...h&&{VPCOptions:{SubnetIds:h.subnetIds,SecurityGroupIds:h.securityGroupIds}},...y&&{EncryptionAtRestOptions:{Enabled:y.atRest??!0,...y.kmsKeyId&&{KmsKeyId:y.kmsKeyId}},NodeToNodeEncryptionOptions:{Enabled:y.nodeToNode??!0}},...w&&{AdvancedSecurityOptions:{Enabled:w.enabled,InternalUserDatabaseEnabled:w.internalUserDatabase??!0,...w.masterUserName&&w.masterUserPassword&&{MasterUserOptions:{MasterUserName:w.masterUserName,MasterUserPassword:w.masterUserPassword}},...w.masterUserArn&&{MasterUserOptions:{MasterUserARN:w.masterUserArn}}}},...E&&{AutoTuneOptions:{DesiredState:"ENABLED"}},Tags:[{Key:"Name",Value:P},{Key:"Environment",Value:a},...Object.entries(v).map(([I,D])=>({Key:I,Value:D}))]}},logicalId:N}}static createAccessPolicy(e,t){let{ipAddresses:a,iamPrincipalArns:r,allowAll:n,vpcEndpoint:i}=t;if(n)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:e}]};let s=[];if(r&&r.length>0)s.push({Effect:"Allow",Principal:{AWS:r},Action:"es:*",Resource:e});if(a&&a.length>0)s.push({Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:e,Condition:{IpAddress:{"aws:SourceIp":a}}});if(i)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:e}]};return{Version:"2012-10-17",Statement:s}}static DomainPresets={development:(e,t)=>Je.createDomain({slug:e,environment:t,instanceType:"t3.small.search",instanceCount:1,volumeSize:10,multiAz:!1,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!1}),production:(e,t,a)=>Je.createDomain({slug:e,environment:t,instanceType:"m6g.large.search",instanceCount:3,volumeSize:100,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"m6g.large.search",dedicatedMasterCount:3,vpc:a,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!0},autoTune:!0}),costOptimized:(e,t)=>Je.createDomain({slug:e,environment:t,instanceType:"t3.medium.search",instanceCount:2,volumeSize:20,volumeType:"gp3",multiAz:!0,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!0}),highPerformance:(e,t,a)=>Je.createDomain({slug:e,environment:t,instanceType:"r6g.2xlarge.search",instanceCount:6,volumeSize:500,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"c6g.xlarge.search",dedicatedMasterCount:3,vpc:a,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 gt{static createDomainRedirectBucket(e){let{slug:t,environment:a,sourceDomain:r,targetDomain:n,protocol:i="https"}=e,s=A({slug:t,environment:a,resourceType:"s3",suffix:"redirect"}),o=f(s),c=f(`${s}-policy`),l={Type:"AWS::S3::Bucket",Properties:{BucketName:r,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:n,Protocol:i}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1},Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:a},{Key:"Purpose",Value:"Domain Redirect"}]}},u={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:C.Ref(o),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[C.Join("",[C.GetAtt(o,"Arn"),"/*"])]}]}}};return{bucket:l,bucketPolicy:u,logicalId:o,policyLogicalId:c}}static createPathRedirectFunction(e){let{slug:t,environment:a,rules:r}=e,n=A({slug:t,environment:a,resourceType:"cf-redirect"}),i=f(n),s=gt.generateRedirectFunctionCode(r);return{function:{Type:"AWS::CloudFront::Function",Properties:{Name:n,AutoPublish:!0,FunctionConfig:{Comment:`Path redirect function for ${t} (${a})`,Runtime:"cloudfront-js-2.0"},FunctionCode:s}},logicalId:i,functionCode:s}}static generateRedirectFunctionCode(e){return`function handler(event) {
2316
+ | limit 50`,region:r,title:"Recent Errors and Warnings"}}),s+=6;return Qa.createDashboard({slug:t,environment:a,widgets:i})}static DashboardTemplates={staticWebsite:(e)=>({slug:e.slug,environment:e.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${e.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",e.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",e.cloudFrontDistributionId,"Region","Global",{label:"4XX"}],["AWS/CloudFront","5xxErrorRate","DistributionId",e.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",e.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:0,y:7,width:12,height:6,properties:{title:"S3 Bucket Size",region:e.region||"us-east-1",metrics:[["AWS/S3","BucketSizeBytes","BucketName",e.s3BucketName,"StorageType","StandardStorage"]],period:86400,stat:"Average"}},{type:"metric",x:12,y:7,width:12,height:6,properties:{title:"S3 Number of Objects",region:e.region||"us-east-1",metrics:[["AWS/S3","NumberOfObjects","BucketName",e.s3BucketName,"StorageType","AllStorageTypes"]],period:86400,stat:"Average"}}]}),serverlessApi:(e)=>({slug:e.slug,environment:e.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${e.slug.toUpperCase()} Serverless API Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"API Requests",region:e.region||"us-east-1",metrics:[["AWS/ApiGateway","Count","ApiName",e.apiGatewayName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"API Latency",region:e.region||"us-east-1",metrics:[["AWS/ApiGateway","Latency","ApiName",e.apiGatewayName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"API Errors",region:e.region||"us-east-1",metrics:[["AWS/ApiGateway","4XXError","ApiName",e.apiGatewayName,{label:"4XX"}],["AWS/ApiGateway","5XXError","ApiName",e.apiGatewayName,{label:"5XX"}]],period:60,stat:"Sum"}},...e.lambdaFunctionNames.map((t,a)=>({type:"metric",x:a%3*8,y:7+Math.floor(a/3)*6,width:8,height:6,properties:{title:`${t} Metrics`,region:e.region||"us-east-1",metrics:[["AWS/Lambda","Invocations","FunctionName",t],["AWS/Lambda","Duration","FunctionName",t],["AWS/Lambda","Errors","FunctionName",t]],period:300,stat:"Sum"}}))]}),containerService:(e)=>({slug:e.slug,environment:e.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${e.slug.toUpperCase()} Container Service Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"ECS CPU",region:e.region||"us-east-1",metrics:[["AWS/ECS","CPUUtilization","ClusterName",e.ecsClusterName,"ServiceName",e.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"ECS Memory",region:e.region||"us-east-1",metrics:[["AWS/ECS","MemoryUtilization","ClusterName",e.ecsClusterName,"ServiceName",e.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Running Tasks",region:e.region||"us-east-1",metrics:[["ECS/ContainerInsights","RunningTaskCount","ClusterName",e.ecsClusterName,"ServiceName",e.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:0,y:7,width:8,height:6,properties:{title:"ALB Requests",region:e.region||"us-east-1",metrics:[["AWS/ApplicationELB","RequestCount","LoadBalancer",e.albName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:7,width:8,height:6,properties:{title:"Response Time",region:e.region||"us-east-1",metrics:[["AWS/ApplicationELB","TargetResponseTime","LoadBalancer",e.albName]],period:60,stat:"Average"}},{type:"metric",x:16,y:7,width:8,height:6,properties:{title:"Healthy Hosts",region:e.region||"us-east-1",metrics:[["AWS/ApplicationELB","HealthyHostCount","LoadBalancer",e.albName]],period:60,stat:"Average"}},...e.rdsInstanceId?[{type:"metric",x:0,y:13,width:12,height:6,properties:{title:"RDS CPU",region:e.region||"us-east-1",metrics:[["AWS/RDS","CPUUtilization","DBInstanceIdentifier",e.rdsInstanceId]],period:300,stat:"Average"}},{type:"metric",x:12,y:13,width:12,height:6,properties:{title:"RDS Connections",region:e.region||"us-east-1",metrics:[["AWS/RDS","DatabaseConnections","DBInstanceIdentifier",e.rdsInstanceId]],period:60,stat:"Sum"}}]:[]]})};static Config={createAlarmConfig:(e)=>{let{metricName:t,namespace:a,threshold:r,comparisonOperator:n="GreaterThanThreshold",evaluationPeriods:i=1,period:s=300,statistic:o="Average",treatMissingData:c="missing"}=e;return{MetricName:t,Namespace:a,Threshold:r,ComparisonOperator:n,EvaluationPeriods:i,Period:s,Statistic:o,TreatMissingData:c}},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:(e=80)=>({metricName:"CPUUtilization",threshold:e,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highMemory:(e=80)=>({metricName:"MemoryUtilization",threshold:e,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highErrors:(e=10)=>({metricName:"Errors",threshold:e,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:1,period:60,statistic:"Sum"}),highLatency:(e=5000)=>({metricName:"Duration",threshold:e,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowHealthyHosts:(e=1)=>({metricName:"HealthyHostCount",namespace:"AWS/ApplicationELB",threshold:e,comparisonOperator:"LessThanThreshold",evaluationPeriods:2,period:60,statistic:"Minimum"}),queueDepth:(e=1000)=>({metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",threshold:e,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowStorage:(e=10737418240)=>({metricName:"FreeStorageSpace",namespace:"AWS/RDS",threshold:e,comparisonOperator:"LessThanThreshold",evaluationPeriods:1,period:300,statistic:"Average"})}}}class J{static createUserPool(e){let{slug:t,environment:a,userPoolName:r,aliasAttributes:n,autoVerifiedAttributes:i,passwordPolicy:s,mfaConfiguration:o,emailConfiguration:c,smsConfiguration:l,lambdaTriggers:u,userPoolAddOns:m,accountRecoverySetting:p}=e,g=r||A({slug:t,environment:a,resourceType:"user-pool"}),h=f(g),y={Type:"AWS::Cognito::UserPool",Properties:{UserPoolName:g,Policies:s?{PasswordPolicy:{MinimumLength:s.minimumLength,RequireLowercase:s.requireLowercase,RequireUppercase:s.requireUppercase,RequireNumbers:s.requireNumbers,RequireSymbols:s.requireSymbols,TemporaryPasswordValidityDays:s.temporaryPasswordValidityDays}}:void 0,MfaConfiguration:o,Schema:[{Name:"email",AttributeDataType:"String",Required:!0,Mutable:!1}]}};if(n&&n.length>0)y.Properties.UsernameAttributes=n;if(i&&i.length>0)y.Properties.AutoVerifiedAttributes=i;if(c)y.Properties.EmailConfiguration={EmailSendingAccount:c.emailSendingAccount,From:c.from,ReplyToEmailAddress:c.replyToEmailAddress,SourceArn:c.sourceArn,ConfigurationSet:c.configurationSet};if(l)y.Properties.SmsConfiguration={ExternalId:l.externalId,SnsCallerArn:l.snsCallerArn};if(u)y.Properties.LambdaConfig={PreSignUp:u.preSignUp,PostConfirmation:u.postConfirmation,PreAuthentication:u.preAuthentication,PostAuthentication:u.postAuthentication,CustomMessage:u.customMessage,DefineAuthChallenge:u.defineAuthChallenge,CreateAuthChallenge:u.createAuthChallenge,VerifyAuthChallengeResponse:u.verifyAuthChallengeResponse,PreTokenGeneration:u.preTokenGeneration,UserMigration:u.userMigration};if(m)y.Properties.UserPoolAddOns={AdvancedSecurityMode:m.advancedSecurityMode};if(p)y.Properties.AccountRecoverySetting={RecoveryMechanisms:p.recoveryMechanisms};return{userPool:y,logicalId:h}}static createUserPoolClient(e,t){let{slug:a,environment:r,clientName:n,generateSecret:i=!1,refreshTokenValidity:s,accessTokenValidity:o,idTokenValidity:c,tokenValidityUnits:l,readAttributes:u,writeAttributes:m,explicitAuthFlows:p,preventUserExistenceErrors:g,enableTokenRevocation:h,callbackURLs:y,logoutURLs:b,allowedOAuthFlows:T,allowedOAuthScopes:w,allowedOAuthFlowsUserPoolClient:S,supportedIdentityProviders:E}=t,v=n||A({slug:a,environment:r,resourceType:"user-pool-client"}),P=f(v);return{client:{Type:"AWS::Cognito::UserPoolClient",Properties:{ClientName:v,UserPoolId:C.Ref(e),GenerateSecret:i,RefreshTokenValidity:s,AccessTokenValidity:o,IdTokenValidity:c,TokenValidityUnits:l,ReadAttributes:u,WriteAttributes:m,ExplicitAuthFlows:p,PreventUserExistenceErrors:g,EnableTokenRevocation:h,CallbackURLs:y,LogoutURLs:b,AllowedOAuthFlows:T,AllowedOAuthScopes:w,AllowedOAuthFlowsUserPoolClient:S,SupportedIdentityProviders:E}},logicalId:P}}static createUserPoolDomain(e,t){let{slug:a,environment:r,domain:n,customDomainConfig:i}=t,s=A({slug:a,environment:r,resourceType:"user-pool-domain"}),o=f(s);return{domain:{Type:"AWS::Cognito::UserPoolDomain",Properties:{Domain:n,UserPoolId:C.Ref(e),CustomDomainConfig:i}},logicalId:o}}static createIdentityPool(e){let{slug:t,environment:a,identityPoolName:r,allowUnauthenticatedIdentities:n=!1,cognitoIdentityProviders:i,supportedLoginProviders:s,samlProviderARNs:o,openIdConnectProviderARNs:c}=e,l=r||A({slug:t,environment:a,resourceType:"identity-pool"}),u=f(l);return{identityPool:{Type:"AWS::Cognito::IdentityPool",Properties:{IdentityPoolName:l,AllowUnauthenticatedIdentities:n,CognitoIdentityProviders:i,SupportedLoginProviders:s,SamlProviderARNs:o,OpenIdConnectProviderARNs:c}},logicalId:u}}static createIdentityPoolRoleAttachment(e,t){let{slug:a,environment:r,authenticatedRole:n,unauthenticatedRole:i,roleMappings:s}=t,o=A({slug:a,environment:r,resourceType:"identity-pool-role-attachment"}),c=f(o),l={authenticated:n};if(i)l.unauthenticated=i;return{attachment:{Type:"AWS::Cognito::IdentityPoolRoleAttachment",Properties:{IdentityPoolId:C.Ref(e),Roles:l,RoleMappings:s}},logicalId:c}}static createAuthenticatedRole(e){let{slug:t,environment:a,identityPoolLogicalId:r}=e,n=A({slug:t,environment:a,resourceType:"cognito-authenticated-role"}),i=f(n);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:n,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":C.Ref(r)},"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:n},{Key:"Environment",Value:a}]}},logicalId:i}}static createUnauthenticatedRole(e){let{slug:t,environment:a,identityPoolLogicalId:r}=e,n=A({slug:t,environment:a,resourceType:"cognito-unauthenticated-role"}),i=f(n);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:n,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":C.Ref(r)},"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:n},{Key:"Environment",Value:a}]}},logicalId:i}}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:(e,t,a)=>{let{userPool:r,logicalId:n}=J.createUserPool({slug:e,environment:t,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:J.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:i,logicalId:s}=J.createUserPoolClient(n,{slug:e,environment:t,explicitAuthFlows:[...J.AuthFlows.standard],callbackURLs:[a],allowedOAuthFlows:["code"],allowedOAuthScopes:[...J.OAuthScopes.basic],allowedOAuthFlowsUserPoolClient:!0});return{userPool:r,poolId:n,client:i,clientId:s}},mobileApp:(e,t)=>{let{userPool:a,logicalId:r}=J.createUserPool({slug:e,environment:t,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:J.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:n,logicalId:i}=J.createUserPoolClient(r,{slug:e,environment:t,explicitAuthFlows:[...J.AuthFlows.standard]}),{identityPool:s,logicalId:o}=J.createIdentityPool({slug:e,environment:t,allowUnauthenticatedIdentities:!1,cognitoIdentityProviders:[{ClientId:C.Ref(i),ProviderName:C.GetAtt(r,"ProviderName")}]}),{role:c,logicalId:l}=J.createAuthenticatedRole({slug:e,environment:t,identityPoolLogicalId:o}),{attachment:u,logicalId:m}=J.createIdentityPoolRoleAttachment(o,{slug:e,environment:t,authenticatedRole:C.GetAtt(l,"Arn")});return{userPool:a,poolId:r,client:n,clientId:i,identityPool:s,identityPoolId:o,authRole:c,authRoleId:l,attachment:u,attachmentId:m}}}}class Q{static createApplication(e){let{slug:t,environment:a,applicationName:r,computePlatform:n}=e,i=r||A({slug:t,environment:a,resourceType:"deploy-app"}),s=f(i);return{application:{Type:"AWS::CodeDeploy::Application",Properties:{ApplicationName:i,ComputePlatform:n,Tags:[{Key:"Name",Value:i},{Key:"Environment",Value:a}]}},logicalId:s}}static createDeploymentGroup(e,t){let{slug:a,environment:r,deploymentGroupName:n,serviceRoleArn:i,autoScalingGroups:s,ec2TagFilters:o,deploymentConfigName:c,autoRollbackConfiguration:l,alarmConfiguration:u,loadBalancerInfo:m,blueGreenDeploymentConfiguration:p}=t,g=n||A({slug:a,environment:r,resourceType:"deploy-group"}),h=f(g);return{deploymentGroup:{Type:"AWS::CodeDeploy::DeploymentGroup",Properties:{ApplicationName:C.Ref(e),DeploymentGroupName:g,ServiceRoleArn:i,AutoScalingGroups:s,Ec2TagFilters:o?.map((y)=>({Key:y.key,Value:y.value,Type:y.type})),DeploymentConfigName:c,AutoRollbackConfiguration:l?{Enabled:l.enabled,Events:l.events}:void 0,AlarmConfiguration:u?{Enabled:u.enabled,Alarms:u.alarms?.map((y)=>({Name:y.name})),IgnorePollAlarmFailure:u.ignorePollAlarmFailure}:void 0,LoadBalancerInfo:m?{TargetGroupInfoList:m.targetGroupInfoList?.map((y)=>({Name:y.name})),ElbInfoList:m.elbInfoList?.map((y)=>({Name:y.name}))}:void 0,BlueGreenDeploymentConfiguration:p?{TerminateBlueInstancesOnDeploymentSuccess:p.terminateBlueInstancesOnDeploymentSuccess?{Action:p.terminateBlueInstancesOnDeploymentSuccess.action,TerminationWaitTimeInMinutes:p.terminateBlueInstancesOnDeploymentSuccess.terminationWaitTimeInMinutes}:void 0,DeploymentReadyOption:p.deploymentReadyOption?{ActionOnTimeout:p.deploymentReadyOption.actionOnTimeout,WaitTimeInMinutes:p.deploymentReadyOption.waitTimeInMinutes}:void 0,GreenFleetProvisioningOption:p.greenFleetProvisioningOption?{Action:p.greenFleetProvisioningOption.action}:void 0}:void 0,Tags:[{Key:"Name",Value:g},{Key:"Environment",Value:r}]}},logicalId:h}}static createDeploymentConfig(e){let{slug:t,environment:a,deploymentConfigName:r,minimumHealthyHosts:n,trafficRoutingConfig:i}=e,s=r||A({slug:t,environment:a,resourceType:"deploy-config"}),o=f(s);return{deploymentConfig:{Type:"AWS::CodeDeploy::DeploymentConfig",Properties:{DeploymentConfigName:s,MinimumHealthyHosts:n?{Type:n.type,Value:n.value}:void 0,TrafficRoutingConfig:i?{Type:i.type,TimeBasedCanary:i.timeBasedCanary?{CanaryPercentage:i.timeBasedCanary.canaryPercentage,CanaryInterval:i.timeBasedCanary.canaryInterval}:void 0,TimeBasedLinear:i.timeBasedLinear?{LinearPercentage:i.timeBasedLinear.linearPercentage,LinearInterval:i.timeBasedLinear.linearInterval}:void 0}:void 0}},logicalId:o}}static DeploymentConfigs={allAtOnce:()=>({type:"FLEET_PERCENT",value:0}),halfAtATime:()=>({type:"FLEET_PERCENT",value:50}),oneAtATime:()=>({type:"HOST_COUNT",value:1}),custom:(e,t)=>({type:e,value:t})};static TrafficRouting={allAtOnce:()=>({type:"AllAtOnce"}),canary:(e,t)=>({type:"TimeBasedCanary",timeBasedCanary:{canaryPercentage:e,canaryInterval:t}}),linear:(e,t)=>({type:"TimeBasedLinear",timeBasedLinear:{linearPercentage:e,linearInterval:t}})};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:(e)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:e},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withManualApproval:(e)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"STOP_DEPLOYMENT",waitTimeInMinutes:e},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:(e,t,a,r)=>{let{application:n,logicalId:i}=Q.createApplication({slug:e,environment:t,computePlatform:"Server"}),{deploymentGroup:s,logicalId:o}=Q.createDeploymentGroup(i,{slug:e,environment:t,serviceRoleArn:a,autoScalingGroups:r,deploymentConfigName:"CodeDeployDefault.OneAtATime",autoRollbackConfiguration:Q.RollbackConfigs.onFailure()});return{application:n,appId:i,deploymentGroup:s,groupId:o}},lambdaCanaryDeployment:(e,t,a,r=10,n=5)=>{let{application:i,logicalId:s}=Q.createApplication({slug:e,environment:t,computePlatform:"Lambda"}),{deploymentConfig:o,logicalId:c}=Q.createDeploymentConfig({slug:e,environment:t,trafficRoutingConfig:Q.TrafficRouting.canary(r,n)}),{deploymentGroup:l,logicalId:u}=Q.createDeploymentGroup(s,{slug:e,environment:t,serviceRoleArn:a,deploymentConfigName:C.Ref(c),autoRollbackConfiguration:Q.RollbackConfigs.onAlarmOrFailure()});return{application:i,appId:s,deploymentConfig:o,configId:c,deploymentGroup:l,groupId:u}},ecsBlueGreenDeployment:(e,t,a,r)=>{let{application:n,logicalId:i}=Q.createApplication({slug:e,environment:t,computePlatform:"ECS"}),{deploymentGroup:s,logicalId:o}=Q.createDeploymentGroup(i,{slug:e,environment:t,serviceRoleArn:a,loadBalancerInfo:{targetGroupInfoList:[{name:r}]},blueGreenDeploymentConfiguration:Q.BlueGreenConfigs.standard(),autoRollbackConfiguration:Q.RollbackConfigs.onFailure()});return{application:n,appId:i,deploymentGroup:s,groupId:o}}};static Strategies={rolling:(e=25)=>({type:"rolling",batchPercentage:e}),blueGreen:()=>({type:"blue-green"}),canary:(e=10,t=5)=>({type:"canary",canaryPercentage:e,canaryInterval:t}),allAtOnce:()=>({type:"all-at-once"})}}class F{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(e,t="md5"){let a=st(e);return Bi(t).update(a).digest("hex")}static computeShortHash(e){return F.computeFileHash(e).slice(0,8)}static getContentType(e){let t=ya(e).toLowerCase();return F.ContentTypes[t]||"application/octet-stream"}static shouldHashFile(e,t){return![...F.NoHashPatterns,...t||[]].some((a)=>a.test(e))}static generateHashedFilename(e,t){let a=ya(e),r=Fi(e,a),n=ha(e);if(n===".")return`${r}.${t}${a}`;return He(n,`${r}.${t}${a}`)}static collectFiles(e,t){let a=[],r=t||e;if(!xt(e))return a;let n=Gi(e,{withFileTypes:!0});for(let i of n){let s=He(e,i.name);if(i.isDirectory())a.push(...F.collectFiles(s,r));else if(i.isFile())a.push(s)}return a}static hashDirectory(e){let{sourceDir:t,outputDir:a,excludePatterns:r=[],hashAlgorithm:n="md5",copyUnhashed:i=!0}=e,s=F.collectFiles(t),o=[],c={};for(let u of s){let m=u.replace(t,"").replace(/^[/\\]/,""),p=F.shouldHashFile(m,r),g=Vi(u),h=p?F.computeFileHash(u,n).slice(0,8):"",y=p?F.generateHashedFilename(m,h):m,b={originalPath:m,hashedPath:y,hash:h,size:g.size,contentType:F.getContentType(u)};if(o.push(b),c[m]=y,a){let T=He(a,y),w=ha(T);if(!xt(w)){let{mkdirSync:S}=Vn("node:fs");S(w,{recursive:!0})}if(p||i)Ui(u,T)}}let l={version:"1.0",timestamp:new Date().toISOString(),assets:o,hashMap:c};if(a){let u=He(a,"asset-manifest.json");ot(u,JSON.stringify(l,null,2))}return l}static getInvalidationPaths(e,t){let a=[];if(!e)return["/*"];let r=e.hashMap,n=t.hashMap;for(let[i,s]of Object.entries(n)){let o=r[i];if(!o||o!==s){if(a.push(`/${i}`),o&&o!==s)a.push(`/${o}`)}}for(let[i,s]of Object.entries(r))if(!n[i])a.push(`/${i}`),a.push(`/${s}`);if(a.length>100)return["/*"];return[...new Set(a)]}static updateHtmlReferences(e){let{htmlDir:t,manifest:a,basePath:r=""}=e,n=F.collectFiles(t).filter((i)=>i.endsWith(".html")||i.endsWith(".htm"));for(let i of n){let s=st(i,"utf-8");for(let[o,c]of Object.entries(a.hashMap)){if(o===c)continue;let l=[new RegExp(`(src|href)=["']${r}/?${F.escapeRegExp(o)}["']`,"g"),new RegExp(`url\\(["']?${r}/?${F.escapeRegExp(o)}["']?\\)`,"g")];for(let u of l)s=s.replace(u,(m)=>{return m.replace(o,c)})}ot(i,s)}}static updateCssReferences(e){let{cssDir:t,manifest:a,basePath:r=""}=e,n=F.collectFiles(t).filter((i)=>i.endsWith(".css"));for(let i of n){let s=st(i,"utf-8");for(let[o,c]of Object.entries(a.hashMap)){if(o===c)continue;let l=new RegExp(`url\\(["']?${r}/?${F.escapeRegExp(o)}["']?\\)`,"g");s=s.replace(l,`url(${r}/${c})`)}ot(i,s)}}static escapeRegExp(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}static generateS3DeploymentManifest(e){let{sourceDir:t,keyPrefix:a="",excludePatterns:r=[],cacheControl:n={hashed:"public, max-age=31536000, immutable",unhashed:"public, max-age=3600",html:"public, max-age=0, must-revalidate"}}=e;return F.hashDirectory({sourceDir:t,excludePatterns:r}).assets.map((i)=>{let s=i.hash!=="",o=i.contentType==="text/html",c=n.unhashed||"public, max-age=3600";if(o)c=n.html||"public, max-age=0, must-revalidate";else if(s)c=n.hashed||"public, max-age=31536000, immutable";return{localPath:He(t,i.originalPath),s3Key:a?`${a}/${i.hashedPath}`:i.hashedPath,contentType:i.contentType,cacheControl:c,hash:i.hash}})}static compareManifests(e,t){let a={added:[],removed:[],changed:[],unchanged:[]},r=new Set(Object.keys(e.hashMap)),n=new Set(Object.keys(t.hashMap));for(let i of n)if(!r.has(i))a.added.push(i);for(let i of r)if(!n.has(i))a.removed.push(i);for(let i of n)if(r.has(i))if(e.hashMap[i]!==t.hashMap[i])a.changed.push(i);else a.unchanged.push(i);return a}static loadManifest(e){if(!xt(e))return null;try{let t=st(e,"utf-8");return JSON.parse(t)}catch{return null}}static saveManifest(e,t){ot(t,JSON.stringify(e,null,2))}}class Je{static createSecret(e){let{slug:t,environment:a,secretName:r,description:n,secretString:i,kmsKeyId:s,tags:o}=e,c=r||A({slug:t,environment:a,resourceType:"secret"}),l=f(c),u={Type:"AWS::SecretsManager::Secret",Properties:{Name:c,Description:n,SecretString:i,Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:a},...o?Object.entries(o).map(([m,p])=>({Key:m,Value:p})):[]]}};if(s)u.Properties.KmsKeyId=s;return{secret:u,logicalId:l}}static createGeneratedSecret(e){let{slug:t,environment:a,secretName:r,description:n,excludeCharacters:i,excludeLowercase:s,excludeNumbers:o,excludePunctuation:c,excludeUppercase:l,passwordLength:u,requireEachIncludedType:m,kmsKeyId:p,tags:g}=e,h=r||A({slug:t,environment:a,resourceType:"secret"}),y=f(h),b={Type:"AWS::SecretsManager::Secret",Properties:{Name:h,Description:n,GenerateSecretString:{ExcludeCharacters:i,ExcludeLowercase:s,ExcludeNumbers:o,ExcludePunctuation:c,ExcludeUppercase:l,PasswordLength:u||32,RequireEachIncludedType:m!==!1},Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:a},...g?Object.entries(g).map(([T,w])=>({Key:T,Value:w})):[]]}};if(p)b.Properties.KmsKeyId=p;return{secret:b,logicalId:y}}static createDatabaseSecret(e){let{slug:t,environment:a,secretName:r,username:n,dbname:i,engine:s,host:o,port:c,kmsKeyId:l}=e,u=r||A({slug:t,environment:a,resourceType:"db-secret"}),m=f(u),p={username:n};if(i)p.dbname=i;if(s)p.engine=s;if(o)p.host=o;if(c)p.port=c;let g={Type:"AWS::SecretsManager::Secret",Properties:{Name:u,Description:`Database credentials for ${n}`,GenerateSecretString:{SecretStringTemplate:JSON.stringify(p),GenerateStringKey:"password",PasswordLength:32,ExcludeCharacters:'"@/\\',RequireEachIncludedType:!0},Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:a},{Key:"Type",Value:"database"}]}};if(l)g.Properties.KmsKeyId=l;return{secret:g,logicalId:m}}static attachToDatabase(e){let{slug:t,environment:a,secretId:r,targetId:n,targetType:i}=e,s=A({slug:t,environment:a,resourceType:"secret-attachment"}),o=f(s);return{attachment:{Type:"AWS::SecretsManager::SecretTargetAttachment",Properties:{SecretId:r,TargetId:n,TargetType:i}},logicalId:o}}static enableRotation(e){let{slug:t,environment:a,secretId:r,rotationLambdaArn:n,automaticallyAfterDays:i,rotationType:s,kmsKeyArn:o,vpcSecurityGroupIds:c,vpcSubnetIds:l}=e,u=A({slug:t,environment:a,resourceType:"secret-rotation"}),m=f(u),p={Type:"AWS::SecretsManager::RotationSchedule",Properties:{SecretId:r,RotationRules:{AutomaticallyAfterDays:i||30}}};if(n)p.Properties.RotationLambdaARN=n;else if(s)p.Properties.HostedRotationLambda={RotationType:s,KmsKeyArn:o,VpcSecurityGroupIds:c,VpcSubnetIds:l};return{rotation:p,logicalId:m}}static SecretTypes={apiKey:(e,t,a)=>{return Je.createGeneratedSecret({slug:e,environment:t,secretName:`${e}-${t}-${a}-api-key`,description:`API key for ${a}`,passwordLength:32,excludePunctuation:!0,excludeLowercase:!1,excludeUppercase:!1,excludeNumbers:!1})},oauthClientSecret:(e,t,a)=>{return Je.createGeneratedSecret({slug:e,environment:t,secretName:`${e}-${t}-${a}-oauth-secret`,description:`OAuth client secret for ${a}`,passwordLength:64,excludeCharacters:"\"'`\\/@",requireEachIncludedType:!0})},jwtSecret:(e,t)=>{return Je.createGeneratedSecret({slug:e,environment:t,secretName:`${e}-${t}-jwt-secret`,description:"JWT signing secret",passwordLength:64,excludePunctuation:!0})},encryptionKey:(e,t)=>{return Je.createGeneratedSecret({slug:e,environment:t,secretName:`${e}-${t}-encryption-key`,description:"Data encryption key",passwordLength:64,excludeCharacters:"+/=",excludePunctuation:!0})}};static RotationTypes={MySQLSingleUser:"MySQLSingleUser",MySQLMultiUser:"MySQLMultiUser",PostgreSQLSingleUser:"PostgreSQLSingleUser",PostgreSQLMultiUser:"PostgreSQLMultiUser",OracleSingleUser:"OracleSingleUser",OracleMultiUser:"OracleMultiUser",MariaDBSingleUser:"MariaDBSingleUser",MariaDBMultiUser:"MariaDBMultiUser",SQLServerSingleUser:"SQLServerSingleUser",SQLServerMultiUser:"SQLServerMultiUser",RedshiftSingleUser:"RedshiftSingleUser",RedshiftMultiUser:"RedshiftMultiUser",MongoDBSingleUser:"MongoDBSingleUser",MongoDBMultiUser:"MongoDBMultiUser"}}class B{static createParameter(e){let{slug:t,environment:a,parameterName:r,value:n,type:i="String",description:s,tier:o="Standard",tags:c}=e,l=r||A({slug:t,environment:a,resourceType:"parameter"}),u=f(l);return{parameter:{Type:"AWS::SSM::Parameter",Properties:{Name:`/${t}/${a}/${l}`,Type:i,Value:n,Description:s,Tier:o,Tags:{Name:l,Environment:a,...c}}},logicalId:u}}static createString(e,t,a,r,n){return B.createParameter({slug:e,environment:t,parameterName:a,value:r,type:"String",description:n})}static createSecureString(e,t,a,r,n){return B.createParameter({slug:e,environment:t,parameterName:a,value:r,type:"SecureString",description:n})}static createStringList(e,t,a,r,n){return B.createParameter({slug:e,environment:t,parameterName:a,value:r.join(","),type:"StringList",description:n})}static Parameters={databaseUrl:(e,t,a)=>{return B.createSecureString(e,t,"database-url",a,"Database connection URL")},apiEndpoint:(e,t,a)=>{return B.createString(e,t,"api-endpoint",a,"API endpoint URL")},appVersion:(e,t,a)=>{return B.createString(e,t,"app-version",a,"Application version")},featureFlags:(e,t,a)=>{return B.createStringList(e,t,"feature-flags",a,"Enabled feature flags")},apiKey:(e,t,a,r)=>{return B.createSecureString(e,t,`${a}-api-key`,r,`API key for ${a}`)},oauthCredentials:(e,t,a,r)=>{let n=B.createString(e,t,"oauth-client-id",a,"OAuth client ID"),i=B.createSecureString(e,t,"oauth-client-secret",r,"OAuth client secret");return{clientId:n,clientSecret:i}},smtpCredentials:(e,t,a,r,n,i)=>{let s=B.createString(e,t,"smtp-username",a,"SMTP username"),o=B.createSecureString(e,t,"smtp-password",r,"SMTP password"),c=B.createString(e,t,"smtp-host",n,"SMTP host"),l=B.createString(e,t,"smtp-port",i.toString(),"SMTP port");return{username:s,password:o,host:c,port:l}},redisUrl:(e,t,a)=>{return B.createSecureString(e,t,"redis-url",a,"Redis connection URL")},s3Bucket:(e,t,a)=>{return B.createString(e,t,"s3-bucket",a,"S3 bucket name")},cloudFrontDistribution:(e,t,a)=>{return B.createString(e,t,"cloudfront-distribution-id",a,"CloudFront distribution ID")}}}class Qe{static createDomain(e){let{slug:t,environment:a,domainName:r,engineVersion:n="OpenSearch_2.11",instanceType:i="t3.small.search",instanceCount:s=1,volumeSize:o=10,volumeType:c="gp3",dedicatedMaster:l=!1,dedicatedMasterType:u,dedicatedMasterCount:m=3,multiAz:p=!1,availabilityZoneCount:g=2,vpc:h,encryption:y,enforceHttps:b=!0,tlsSecurityPolicy:T="Policy-Min-TLS-1-2-2019-07",advancedSecurity:w,autoSnapshotHour:S=0,autoTune:E=!0,tags:v={}}=e,P=r||A({slug:t,environment:a,resourceType:"search"}),N=f(P);return{domain:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:P,EngineVersion:n,ClusterConfig:{InstanceType:i,InstanceCount:s,DedicatedMasterEnabled:l,...l&&{DedicatedMasterType:u||i,DedicatedMasterCount:m},ZoneAwarenessEnabled:p,...p&&{ZoneAwarenessConfig:{AvailabilityZoneCount:g}}},EBSOptions:{EBSEnabled:!0,VolumeType:c,VolumeSize:o},DomainEndpointOptions:{EnforceHTTPS:b,TLSSecurityPolicy:T},SnapshotOptions:{AutomatedSnapshotStartHour:S},...h&&{VPCOptions:{SubnetIds:h.subnetIds,SecurityGroupIds:h.securityGroupIds}},...y&&{EncryptionAtRestOptions:{Enabled:y.atRest??!0,...y.kmsKeyId&&{KmsKeyId:y.kmsKeyId}},NodeToNodeEncryptionOptions:{Enabled:y.nodeToNode??!0}},...w&&{AdvancedSecurityOptions:{Enabled:w.enabled,InternalUserDatabaseEnabled:w.internalUserDatabase??!0,...w.masterUserName&&w.masterUserPassword&&{MasterUserOptions:{MasterUserName:w.masterUserName,MasterUserPassword:w.masterUserPassword}},...w.masterUserArn&&{MasterUserOptions:{MasterUserARN:w.masterUserArn}}}},...E&&{AutoTuneOptions:{DesiredState:"ENABLED"}},Tags:[{Key:"Name",Value:P},{Key:"Environment",Value:a},...Object.entries(v).map(([I,D])=>({Key:I,Value:D}))]}},logicalId:N}}static createAccessPolicy(e,t){let{ipAddresses:a,iamPrincipalArns:r,allowAll:n,vpcEndpoint:i}=t;if(n)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:e}]};let s=[];if(r&&r.length>0)s.push({Effect:"Allow",Principal:{AWS:r},Action:"es:*",Resource:e});if(a&&a.length>0)s.push({Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:e,Condition:{IpAddress:{"aws:SourceIp":a}}});if(i)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:e}]};return{Version:"2012-10-17",Statement:s}}static DomainPresets={development:(e,t)=>{return Qe.createDomain({slug:e,environment:t,instanceType:"t3.small.search",instanceCount:1,volumeSize:10,multiAz:!1,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!1})},production:(e,t,a)=>{return Qe.createDomain({slug:e,environment:t,instanceType:"m6g.large.search",instanceCount:3,volumeSize:100,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"m6g.large.search",dedicatedMasterCount:3,vpc:a,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!0},autoTune:!0})},costOptimized:(e,t)=>{return Qe.createDomain({slug:e,environment:t,instanceType:"t3.medium.search",instanceCount:2,volumeSize:20,volumeType:"gp3",multiAz:!0,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!0})},highPerformance:(e,t,a)=>{return Qe.createDomain({slug:e,environment:t,instanceType:"r6g.2xlarge.search",instanceCount:6,volumeSize:500,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"c6g.xlarge.search",dedicatedMasterCount:3,vpc:a,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!1},autoTune:!0})}};static InstanceTypes={"t3.small.search":"t3.small.search","t3.medium.search":"t3.medium.search","m6g.large.search":"m6g.large.search","m6g.xlarge.search":"m6g.xlarge.search","m6g.2xlarge.search":"m6g.2xlarge.search","r6g.large.search":"r6g.large.search","r6g.xlarge.search":"r6g.xlarge.search","r6g.2xlarge.search":"r6g.2xlarge.search","r6g.4xlarge.search":"r6g.4xlarge.search","c6g.large.search":"c6g.large.search","c6g.xlarge.search":"c6g.xlarge.search","c6g.2xlarge.search":"c6g.2xlarge.search"};static EngineVersions={"OpenSearch_2.11":"OpenSearch_2.11","OpenSearch_2.9":"OpenSearch_2.9","OpenSearch_2.7":"OpenSearch_2.7","OpenSearch_1.3":"OpenSearch_1.3","Elasticsearch_7.10":"Elasticsearch_7.10"}}class pt{static createDomainRedirectBucket(e){let{slug:t,environment:a,sourceDomain:r,targetDomain:n,protocol:i="https"}=e,s=A({slug:t,environment:a,resourceType:"s3",suffix:"redirect"}),o=f(s),c=f(`${s}-policy`),l={Type:"AWS::S3::Bucket",Properties:{BucketName:r,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:n,Protocol:i}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1},Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:a},{Key:"Purpose",Value:"Domain Redirect"}]}},u={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:C.Ref(o),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[C.Join("",[C.GetAtt(o,"Arn"),"/*"])]}]}}};return{bucket:l,bucketPolicy:u,logicalId:o,policyLogicalId:c}}static createPathRedirectFunction(e){let{slug:t,environment:a,rules:r}=e,n=A({slug:t,environment:a,resourceType:"cf-redirect"}),i=f(n),s=pt.generateRedirectFunctionCode(r);return{function:{Type:"AWS::CloudFront::Function",Properties:{Name:n,AutoPublish:!0,FunctionConfig:{Comment:`Path redirect function for ${t} (${a})`,Runtime:"cloudfront-js-2.0"},FunctionCode:s}},logicalId:i,functionCode:s}}static generateRedirectFunctionCode(e){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 @@ ${e.map((t)=>{let a=t.preserveQueryString!==!1,r=t.statusCode||301;return` '${t
2367
2367
  }
2368
2368
 
2369
2369
  return request;
2370
- }`}static CommonRedirects={wwwToApex:(e,t="https")=>({slug:e.replace(/\./g,"-"),environment:"production",sourceDomain:`www.${e}`,targetDomain:e,protocol:t,preservePath:!0}),apexToWww:(e,t="https")=>({slug:e.replace(/\./g,"-"),environment:"production",sourceDomain:e,targetDomain:`www.${e}`,protocol:t,preservePath:!0}),httpToHttps:(e="/")=>({source:e,target:e,statusCode:301}),addTrailingSlash:(e)=>e.map((t)=>({source:t.endsWith("/")?t.slice(0,-1):t,target:t.endsWith("/")?t:`${t}/`,statusCode:301})),removeTrailingSlash:(e)=>e.map((t)=>({source:t.endsWith("/")&&t!=="/"?t:`${t}/`,target:t.endsWith("/")&&t!=="/"?t.slice(0,-1):t,statusCode:301}))};static Patterns={flattenBlogUrls:(e)=>e.map(({oldPath:t,newPath:a})=>({source:t,target:a,statusCode:301,preserveQueryString:!0})),categoryRename:(e,t)=>[{source:`/${e}`,target:`/${t}`,statusCode:301},{source:`/${e}/`,target:`/${t}/`,statusCode:301}],productSlugChange:(e)=>e.map(({oldSlug:t,newSlug:a})=>({source:`/products/${t}`,target:`/products/${a}`,statusCode:301})),apiVersionRedirect:(e,t,a)=>a.map((r)=>({source:`/api/${e}/${r}`,target:`/api/${t}/${r}`,statusCode:307,preserveQueryString:!0})),gonePages:(e)=>e.map((t)=>({source:t,target:"/410",statusCode:301}))};static createRedirectSetup(e){let{slug:t,environment:a,domainRedirects:r=[],pathRedirects:n=[]}=e,i={},s=[];for(let c of r){let{bucket:l,bucketPolicy:u,logicalId:m,policyLogicalId:p}=gt.createDomainRedirectBucket({...c,slug:t,environment:a});i[m]=l,i[p]=u,s.push(m)}let o=null;if(n.length>0){let{function:c,logicalId:l}=gt.createPathRedirectFunction({slug:t,environment:a,rules:n});i[l]=c,o=l}return{resources:i,outputs:{domainRedirectBuckets:s,pathRedirectFunctionLogicalId:o}}}static fromMapping(e,t){return Object.entries(e).map(([a,r])=>({source:a,target:r,statusCode:t?.statusCode||301,preserveQueryString:t?.preserveQueryString??!0}))}static validateRules(e){let t=[],a=[],r=new Set;for(let n of e){if(r.has(n.source))t.push(`Duplicate source path: ${n.source}`);if(r.add(n.source),n.source===n.target)t.push(`Redirect loop detected: ${n.source} -> ${n.target}`);if(!n.target.startsWith("/")&&!n.target.startsWith("http"))a.push(`Target URL should start with / or http: ${n.target}`);if(!n.source||n.source.trim()==="")t.push("Source path cannot be empty");if(!n.target||n.target.trim()==="")t.push("Target path cannot be empty")}for(let n of e){let i=e.find((s)=>s.source===n.target);if(i)a.push(`Potential redirect chain: ${n.source} -> ${n.target} -> ${i.target}`)}return{valid:t.length===0,errors:t,warnings:a}}}class Y{static generate(e){let t={},{slug:a,environment:r,region:n="us-east-1"}=e,i=Y.createLambdaExecutionRole(a,r);if(Object.assign(t,i.resources),e.email?.enabled){let s=Y.generateEmailResources(e,i.roleArn);Object.assign(t,s)}if(e.phone?.enabled){let s=Y.generatePhoneResources(e,i.roleArn);Object.assign(t,s)}if(e.sms?.enabled){let s=Y.generateSmsResources(e,i.roleArn);Object.assign(t,s)}return t}static createLambdaExecutionRole(e,t){let a=`${e}-${t}-communication-role`,r=f(a);return{resources:{[r]:{Type:"AWS::IAM::Role",Properties:{RoleName:a,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:C.GetAtt(r,"Arn"),roleName:a}}static generateEmailResources(e,t){let{slug:a,environment:r,email:n}=e;if(!n)return{};let i={},s=`${a}-${r}`,o=`${s}-email-storage`,c=f(o);i[c]={Type:"AWS::S3::Bucket",Properties:{BucketName:o,LifecycleConfiguration:{Rules:[{Id:"ArchiveOldEmails",Status:"Enabled",Transitions:n.server?.storage?.archiveAfterDays?[{StorageClass:"GLACIER",TransitionInDays:n.server.storage.archiveAfterDays}]:[],ExpirationInDays:n.server?.storage?.retentionDays||365}]},NotificationConfiguration:{LambdaConfigurations:[]}}};let l=f(`${s}-ses-identity`);if(i[l]={Type:"AWS::SES::EmailIdentity",Properties:{EmailIdentity:n.domain,DkimSigningAttributes:{NextSigningKeyLength:"RSA_2048_BIT"},FeedbackAttributes:{EmailForwardingEnabled:!0}}},n.notifications?.bounces||n.notifications?.complaints){let u=f(`${s}-bounce-topic`);i[u]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${s}-email-bounces`}};let m=f(`${s}-complaint-topic`);i[m]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${s}-email-complaints`}}}if(n.server?.enabled){let u=f(`${s}-inbound-email`);i[u]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${s}-inbound-email`,Runtime:"nodejs20.x",Handler:"index.handler",Role:t,Timeout:60,MemorySize:256,Code:{ZipFile:Y.InboundEmailCode},Environment:{Variables:{EMAIL_BUCKET:o,DOMAIN:n.domain}}}};let m=f(`${s}-outbound-email`);i[m]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${s}-outbound-email`,Runtime:"nodejs20.x",Handler:"index.handler",Role:t,Timeout:30,MemorySize:256,Code:{ZipFile:Y.OutboundEmailCode},Environment:{Variables:{EMAIL_BUCKET:o,DOMAIN:n.domain}}}}}if(n.advanced?.analytics){let u=f(`${s}-email-analytics`);i[u]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-email-analytics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(n.advanced?.scheduling){let u=f(`${s}-email-scheduler`);i[u]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${s}-email-scheduler`,Runtime:"nodejs20.x",Handler:"index.handler",Role:t,Timeout:300,MemorySize:256,Code:{ZipFile:Y.EmailSchedulerCode},Environment:{Variables:{EMAIL_BUCKET:o}}}};let m=f(`${s}-email-scheduler-rule`);i[m]={Type:"AWS::Events::Rule",Properties:{Name:`${s}-email-scheduler`,ScheduleExpression:"rate(1 minute)",State:"ENABLED",Targets:[{Id:"EmailSchedulerTarget",Arn:C.GetAtt(u,"Arn")}]}}}if(n.advanced?.threading){let u=f(`${s}-email-threading`);i[u]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${s}-email-threading`,Runtime:"nodejs20.x",Handler:"index.handler",Role:t,Timeout:60,MemorySize:256,Code:{ZipFile:Y.EmailThreadingCode},Environment:{Variables:{EMAIL_BUCKET:o}}}}}if(n.advanced?.rules){let u=f(`${s}-email-rules`);i[u]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-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(n.advanced?.sharedMailboxes){let u=f(`${s}-shared-mailboxes`);i[u]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-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(n.advanced?.search){let u=f(`${s}-email-search`);i[u]={Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:`${s}-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 i}static generatePhoneResources(e,t){let{slug:a,environment:r,phone:n}=e;if(!n)return{};let i={},s=`${a}-${r}`,o=f(`${s}-call-log`);if(i[o]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-call-log`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"contactId",AttributeType:"S"}],KeySchema:[{AttributeName:"contactId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}},n.voicemail?.enabled){let u=f(`${s}-voicemail`);i[u]={Type:"AWS::S3::Bucket",Properties:{BucketName:`${s}-voicemail`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldVoicemails",Status:"Enabled",ExpirationInDays:90}]}}}}let c=f(`${s}-phone-notifications`);i[c]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${s}-phone-notifications`}};let l=f(`${s}-incoming-call`);if(i[l]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${s}-incoming-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:t,Timeout:30,MemorySize:256,Code:{ZipFile:Y.IncomingCallCode},Environment:{Variables:{CALL_LOG_TABLE:`${s}-call-log`,NOTIFICATION_TOPIC_ARN:C.Ref(c)}}}},n.voicemail?.enabled){let u=f(`${s}-voicemail-handler`);i[u]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${s}-voicemail-handler`,Runtime:"nodejs20.x",Handler:"index.handler",Role:t,Timeout:n.voicemail.transcription?300:60,MemorySize:256,Code:{ZipFile:Y.VoicemailCode},Environment:{Variables:{VOICEMAIL_BUCKET:`${s}-voicemail`,TRANSCRIPTION_ENABLED:String(n.voicemail.transcription||!1),NOTIFICATION_TOPIC_ARN:C.Ref(c)}}}}}if(n.advanced?.recording){let u=f(`${s}-call-recordings`);i[u]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-call-recordings`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"recordingId",AttributeType:"S"}],KeySchema:[{AttributeName:"recordingId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(n.advanced?.callbacks){let u=f(`${s}-callbacks`);i[u]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-callbacks`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(n.advanced?.analytics){let u=f(`${s}-call-metrics`);i[u]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-call-metrics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"period",AttributeType:"S"}],KeySchema:[{AttributeName:"period",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}return i}static generateSmsResources(e,t){let{slug:a,environment:r,sms:n}=e;if(!n)return{};let i={},s=`${a}-${r}`,o=f(`${s}-pinpoint-app`);i[o]={Type:"AWS::Pinpoint::App",Properties:{Name:`${s}-sms`}};let c=f(`${s}-sms-channel`);i[c]={Type:"AWS::Pinpoint::SMSChannel",Properties:{ApplicationId:C.Ref(o),Enabled:!0,SenderId:n.senderId}};let l=f(`${s}-sms-log`);if(i[l]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-sms-log`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}},n.optOut?.enabled){let g=f(`${s}-sms-optout`);i[g]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-sms-optout`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}]}}}let u=f(`${s}-sms-notifications`);i[u]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${s}-sms-notifications`}};let m=f(`${s}-send-sms`);i[m]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${s}-send-sms`,Runtime:"nodejs20.x",Handler:"index.handler",Role:t,Timeout:30,MemorySize:256,Code:{ZipFile:Y.SendSmsCode},Environment:{Variables:{PINPOINT_APP_ID:C.Ref(o),MESSAGE_LOG_TABLE:`${s}-sms-log`,OPT_OUT_TABLE:n.optOut?.enabled?`${s}-sms-optout`:"",MESSAGE_TYPE:n.messageType||"TRANSACTIONAL"}}}};let p=f(`${s}-receive-sms`);if(i[p]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${s}-receive-sms`,Runtime:"nodejs20.x",Handler:"index.handler",Role:t,Timeout:30,MemorySize:256,Code:{ZipFile:Y.ReceiveSmsCode},Environment:{Variables:{MESSAGE_LOG_TABLE:`${s}-sms-log`,OPT_OUT_TABLE:n.optOut?.enabled?`${s}-sms-optout`:"",NOTIFICATION_TOPIC_ARN:C.Ref(u)}}}},n.advanced?.campaigns){let g=f(`${s}-sms-campaigns`);i[g]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-sms-campaigns`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}if(n.advanced?.analytics){let g=f(`${s}-sms-analytics`);i[g]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-sms-analytics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"period",AttributeType:"S"}],KeySchema:[{AttributeName:"period",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(n.advanced?.linkTracking){let g=f(`${s}-short-links`);i[g]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-short-links`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(n.advanced?.chatbot){let g=f(`${s}-chatbot-sessions`);i[g]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-chatbot-sessions`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}};let h=f(`${s}-chatbot-rules`);i[h]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-chatbot-rules`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}if(n.advanced?.abTesting){let g=f(`${s}-ab-tests`);i[g]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-ab-tests`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}if(n.advanced?.mms){let g=f(`${s}-mms-media`);i[g]={Type:"AWS::S3::Bucket",Properties:{BucketName:`${s}-mms-media`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldMedia",Status:"Enabled",ExpirationInDays:30}]}}}}return i}static InboundEmailCode=`
2370
+ }`}static CommonRedirects={wwwToApex:(e,t="https")=>({slug:e.replace(/\./g,"-"),environment:"production",sourceDomain:`www.${e}`,targetDomain:e,protocol:t,preservePath:!0}),apexToWww:(e,t="https")=>({slug:e.replace(/\./g,"-"),environment:"production",sourceDomain:e,targetDomain:`www.${e}`,protocol:t,preservePath:!0}),httpToHttps:(e="/")=>({source:e,target:e,statusCode:301}),addTrailingSlash:(e)=>e.map((t)=>({source:t.endsWith("/")?t.slice(0,-1):t,target:t.endsWith("/")?t:`${t}/`,statusCode:301})),removeTrailingSlash:(e)=>e.map((t)=>({source:t.endsWith("/")&&t!=="/"?t:`${t}/`,target:t.endsWith("/")&&t!=="/"?t.slice(0,-1):t,statusCode:301}))};static Patterns={flattenBlogUrls:(e)=>e.map(({oldPath:t,newPath:a})=>({source:t,target:a,statusCode:301,preserveQueryString:!0})),categoryRename:(e,t)=>[{source:`/${e}`,target:`/${t}`,statusCode:301},{source:`/${e}/`,target:`/${t}/`,statusCode:301}],productSlugChange:(e)=>e.map(({oldSlug:t,newSlug:a})=>({source:`/products/${t}`,target:`/products/${a}`,statusCode:301})),apiVersionRedirect:(e,t,a)=>a.map((r)=>({source:`/api/${e}/${r}`,target:`/api/${t}/${r}`,statusCode:307,preserveQueryString:!0})),gonePages:(e)=>e.map((t)=>({source:t,target:"/410",statusCode:301}))};static createRedirectSetup(e){let{slug:t,environment:a,domainRedirects:r=[],pathRedirects:n=[]}=e,i={},s=[];for(let c of r){let{bucket:l,bucketPolicy:u,logicalId:m,policyLogicalId:p}=pt.createDomainRedirectBucket({...c,slug:t,environment:a});i[m]=l,i[p]=u,s.push(m)}let o=null;if(n.length>0){let{function:c,logicalId:l}=pt.createPathRedirectFunction({slug:t,environment:a,rules:n});i[l]=c,o=l}return{resources:i,outputs:{domainRedirectBuckets:s,pathRedirectFunctionLogicalId:o}}}static fromMapping(e,t){return Object.entries(e).map(([a,r])=>({source:a,target:r,statusCode:t?.statusCode||301,preserveQueryString:t?.preserveQueryString??!0}))}static validateRules(e){let t=[],a=[],r=new Set;for(let n of e){if(r.has(n.source))t.push(`Duplicate source path: ${n.source}`);if(r.add(n.source),n.source===n.target)t.push(`Redirect loop detected: ${n.source} -> ${n.target}`);if(!n.target.startsWith("/")&&!n.target.startsWith("http"))a.push(`Target URL should start with / or http: ${n.target}`);if(!n.source||n.source.trim()==="")t.push("Source path cannot be empty");if(!n.target||n.target.trim()==="")t.push("Target path cannot be empty")}for(let n of e){let i=e.find((s)=>s.source===n.target);if(i)a.push(`Potential redirect chain: ${n.source} -> ${n.target} -> ${i.target}`)}return{valid:t.length===0,errors:t,warnings:a}}}class ${static generate(e){let t={},{slug:a,environment:r,region:n="us-east-1"}=e,i=$.createLambdaExecutionRole(a,r);if(Object.assign(t,i.resources),e.email?.enabled){let s=$.generateEmailResources(e,i.roleArn);Object.assign(t,s)}if(e.phone?.enabled){let s=$.generatePhoneResources(e,i.roleArn);Object.assign(t,s)}if(e.sms?.enabled){let s=$.generateSmsResources(e,i.roleArn);Object.assign(t,s)}return t}static createLambdaExecutionRole(e,t){let a=`${e}-${t}-communication-role`,r=f(a);return{resources:{[r]:{Type:"AWS::IAM::Role",Properties:{RoleName:a,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:C.GetAtt(r,"Arn"),roleName:a}}static generateEmailResources(e,t){let{slug:a,environment:r,email:n}=e;if(!n)return{};let i={},s=`${a}-${r}`,o=`${s}-email-storage`,c=f(o);i[c]={Type:"AWS::S3::Bucket",Properties:{BucketName:o,LifecycleConfiguration:{Rules:[{Id:"ArchiveOldEmails",Status:"Enabled",Transitions:n.server?.storage?.archiveAfterDays?[{StorageClass:"GLACIER",TransitionInDays:n.server.storage.archiveAfterDays}]:[],ExpirationInDays:n.server?.storage?.retentionDays||365}]},NotificationConfiguration:{LambdaConfigurations:[]}}};let l=f(`${s}-ses-identity`);if(i[l]={Type:"AWS::SES::EmailIdentity",Properties:{EmailIdentity:n.domain,DkimSigningAttributes:{NextSigningKeyLength:"RSA_2048_BIT"},FeedbackAttributes:{EmailForwardingEnabled:!0}}},n.notifications?.bounces||n.notifications?.complaints){let u=f(`${s}-bounce-topic`);i[u]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${s}-email-bounces`}};let m=f(`${s}-complaint-topic`);i[m]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${s}-email-complaints`}}}if(n.server?.enabled){let u=f(`${s}-inbound-email`);i[u]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${s}-inbound-email`,Runtime:"nodejs20.x",Handler:"index.handler",Role:t,Timeout:60,MemorySize:256,Code:{ZipFile:$.InboundEmailCode},Environment:{Variables:{EMAIL_BUCKET:o,DOMAIN:n.domain}}}};let m=f(`${s}-outbound-email`);i[m]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${s}-outbound-email`,Runtime:"nodejs20.x",Handler:"index.handler",Role:t,Timeout:30,MemorySize:256,Code:{ZipFile:$.OutboundEmailCode},Environment:{Variables:{EMAIL_BUCKET:o,DOMAIN:n.domain}}}}}if(n.advanced?.analytics){let u=f(`${s}-email-analytics`);i[u]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-email-analytics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(n.advanced?.scheduling){let u=f(`${s}-email-scheduler`);i[u]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${s}-email-scheduler`,Runtime:"nodejs20.x",Handler:"index.handler",Role:t,Timeout:300,MemorySize:256,Code:{ZipFile:$.EmailSchedulerCode},Environment:{Variables:{EMAIL_BUCKET:o}}}};let m=f(`${s}-email-scheduler-rule`);i[m]={Type:"AWS::Events::Rule",Properties:{Name:`${s}-email-scheduler`,ScheduleExpression:"rate(1 minute)",State:"ENABLED",Targets:[{Id:"EmailSchedulerTarget",Arn:C.GetAtt(u,"Arn")}]}}}if(n.advanced?.threading){let u=f(`${s}-email-threading`);i[u]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${s}-email-threading`,Runtime:"nodejs20.x",Handler:"index.handler",Role:t,Timeout:60,MemorySize:256,Code:{ZipFile:$.EmailThreadingCode},Environment:{Variables:{EMAIL_BUCKET:o}}}}}if(n.advanced?.rules){let u=f(`${s}-email-rules`);i[u]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-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(n.advanced?.sharedMailboxes){let u=f(`${s}-shared-mailboxes`);i[u]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-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(n.advanced?.search){let u=f(`${s}-email-search`);i[u]={Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:`${s}-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 i}static generatePhoneResources(e,t){let{slug:a,environment:r,phone:n}=e;if(!n)return{};let i={},s=`${a}-${r}`,o=f(`${s}-call-log`);if(i[o]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-call-log`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"contactId",AttributeType:"S"}],KeySchema:[{AttributeName:"contactId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}},n.voicemail?.enabled){let u=f(`${s}-voicemail`);i[u]={Type:"AWS::S3::Bucket",Properties:{BucketName:`${s}-voicemail`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldVoicemails",Status:"Enabled",ExpirationInDays:90}]}}}}let c=f(`${s}-phone-notifications`);i[c]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${s}-phone-notifications`}};let l=f(`${s}-incoming-call`);if(i[l]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${s}-incoming-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:t,Timeout:30,MemorySize:256,Code:{ZipFile:$.IncomingCallCode},Environment:{Variables:{CALL_LOG_TABLE:`${s}-call-log`,NOTIFICATION_TOPIC_ARN:C.Ref(c)}}}},n.voicemail?.enabled){let u=f(`${s}-voicemail-handler`);i[u]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${s}-voicemail-handler`,Runtime:"nodejs20.x",Handler:"index.handler",Role:t,Timeout:n.voicemail.transcription?300:60,MemorySize:256,Code:{ZipFile:$.VoicemailCode},Environment:{Variables:{VOICEMAIL_BUCKET:`${s}-voicemail`,TRANSCRIPTION_ENABLED:String(n.voicemail.transcription||!1),NOTIFICATION_TOPIC_ARN:C.Ref(c)}}}}}if(n.advanced?.recording){let u=f(`${s}-call-recordings`);i[u]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-call-recordings`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"recordingId",AttributeType:"S"}],KeySchema:[{AttributeName:"recordingId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(n.advanced?.callbacks){let u=f(`${s}-callbacks`);i[u]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-callbacks`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(n.advanced?.analytics){let u=f(`${s}-call-metrics`);i[u]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-call-metrics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"period",AttributeType:"S"}],KeySchema:[{AttributeName:"period",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}return i}static generateSmsResources(e,t){let{slug:a,environment:r,sms:n}=e;if(!n)return{};let i={},s=`${a}-${r}`,o=f(`${s}-pinpoint-app`);i[o]={Type:"AWS::Pinpoint::App",Properties:{Name:`${s}-sms`}};let c=f(`${s}-sms-channel`);i[c]={Type:"AWS::Pinpoint::SMSChannel",Properties:{ApplicationId:C.Ref(o),Enabled:!0,SenderId:n.senderId}};let l=f(`${s}-sms-log`);if(i[l]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-sms-log`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}},n.optOut?.enabled){let g=f(`${s}-sms-optout`);i[g]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-sms-optout`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}]}}}let u=f(`${s}-sms-notifications`);i[u]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${s}-sms-notifications`}};let m=f(`${s}-send-sms`);i[m]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${s}-send-sms`,Runtime:"nodejs20.x",Handler:"index.handler",Role:t,Timeout:30,MemorySize:256,Code:{ZipFile:$.SendSmsCode},Environment:{Variables:{PINPOINT_APP_ID:C.Ref(o),MESSAGE_LOG_TABLE:`${s}-sms-log`,OPT_OUT_TABLE:n.optOut?.enabled?`${s}-sms-optout`:"",MESSAGE_TYPE:n.messageType||"TRANSACTIONAL"}}}};let p=f(`${s}-receive-sms`);if(i[p]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${s}-receive-sms`,Runtime:"nodejs20.x",Handler:"index.handler",Role:t,Timeout:30,MemorySize:256,Code:{ZipFile:$.ReceiveSmsCode},Environment:{Variables:{MESSAGE_LOG_TABLE:`${s}-sms-log`,OPT_OUT_TABLE:n.optOut?.enabled?`${s}-sms-optout`:"",NOTIFICATION_TOPIC_ARN:C.Ref(u)}}}},n.advanced?.campaigns){let g=f(`${s}-sms-campaigns`);i[g]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-sms-campaigns`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}if(n.advanced?.analytics){let g=f(`${s}-sms-analytics`);i[g]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-sms-analytics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"period",AttributeType:"S"}],KeySchema:[{AttributeName:"period",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(n.advanced?.linkTracking){let g=f(`${s}-short-links`);i[g]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-short-links`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(n.advanced?.chatbot){let g=f(`${s}-chatbot-sessions`);i[g]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-chatbot-sessions`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}};let h=f(`${s}-chatbot-rules`);i[h]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-chatbot-rules`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}if(n.advanced?.abTesting){let g=f(`${s}-ab-tests`);i[g]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${s}-ab-tests`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}if(n.advanced?.mms){let g=f(`${s}-mms-media`);i[g]={Type:"AWS::S3::Bucket",Properties:{BucketName:`${s}-mms-media`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldMedia",Status:"Enabled",ExpirationInDays:30}]}}}}return i}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 d={ref:(e)=>({Ref:e}),getAtt:(e,t)=>({"Fn::GetAtt":[e,t]}),join:(e,t)=>({"Fn::Join":[e,t]}),sub:(e,t)=>t?{"Fn::Sub":[e,t]}:{"Fn::Sub":e},select:(e,t)=>({"Fn::Select":[e,t]}),split:(e,t)=>({"Fn::Split":[e,t]}),getAZs:(e="")=>({"Fn::GetAZs":e}),importValue:(e)=>({"Fn::ImportValue":e}),findInMap:(e,t,a)=>({"Fn::FindInMap":[e,t,a]}),base64:(e)=>({"Fn::Base64":e}),cidr:(e,t,a)=>({"Fn::Cidr":[e,t,a]}),equals:(e,t)=>({"Fn::Equals":[e,t]}),if:(e,t,a)=>({"Fn::If":[e,t,a]}),not:(e)=>({"Fn::Not":[e]}),and:(...e)=>({"Fn::And":e}),or:(...e)=>({"Fn::Or":e})},Ct={s3Bucket:(e)=>d.sub(`arn:aws:s3:::${e}`),s3Object:(e,t="*")=>d.sub(`arn:aws:s3:::${e}/${t}`),lambda:(e,t,a)=>d.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${e}`,t&&a?{"AWS::Region":t,"AWS::AccountId":a}:void 0),dynamodb:(e)=>d.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${e}`),sqs:(e)=>d.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${e}`),sns:(e)=>d.sub(`arn:aws:sns:\${AWS::Region}:\${AWS::AccountId}:${e}`),kinesis:(e)=>d.sub(`arn:aws:kinesis:\${AWS::Region}:\${AWS::AccountId}:stream/${e}`),iam:(e,t)=>d.sub(`arn:aws:iam::\${AWS::AccountId}:${e}/${t}`),secretsManager:(e)=>d.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${e}`),cloudwatch:(e)=>d.sub(`arn:aws:logs:\${AWS::Region}:\${AWS::AccountId}:log-group:${e}`)},Kl={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 ji(e,t){if(t.type==="http")Ki(e,t);else if(t.type==="rest")Hi(e,t);else if(t.type==="websocket")qi(e,t)}function Ki(e,t){let a={Name:d.sub("${AWS::StackName}-http-api"),ProtocolType:"HTTP"};if(t.cors)a.CorsConfiguration={AllowOrigins:t.cors.allowOrigins,AllowMethods:t.cors.allowMethods,AllowHeaders:t.cors.allowHeaders||["*"],MaxAge:t.cors.maxAge||300};if(e.addResource("HttpApi","AWS::ApiGatewayV2::Api",a),e.addResource("HttpApiStage","AWS::ApiGatewayV2::Stage",{ApiId:d.ref("HttpApi"),StageName:"$default",AutoDeploy:!0,DefaultRouteSettings:t.throttling?{ThrottlingBurstLimit:t.throttling.burstLimit,ThrottlingRateLimit:t.throttling.rateLimit}:void 0,AccessLogSettings:{DestinationArn:d.getAtt("ApiLogGroup","Arn"),Format:"$context.requestId $context.error.message $context.error.messageString"}},{dependsOn:["HttpApi","ApiLogGroup"]}),e.addResource("ApiLogGroup","AWS::Logs::LogGroup",{LogGroupName:d.sub("/aws/apigateway/${AWS::StackName}-http-api"),RetentionInDays:14}),t.authorizer)zi(e,"HttpApi",t.authorizer);if(t.customDomain)Qt(e,"HttpApi",t.customDomain,"HTTP");e.addOutputs({HttpApiId:{Description:"HTTP API ID",Value:d.ref("HttpApi"),Export:{Name:d.sub("${AWS::StackName}-http-api-id")}},HttpApiEndpoint:{Description:"HTTP API endpoint",Value:d.getAtt("HttpApi","ApiEndpoint"),Export:{Name:d.sub("${AWS::StackName}-http-api-endpoint")}}})}function Hi(e,t){e.addResource("RestApi","AWS::ApiGateway::RestApi",{Name:d.sub("${AWS::StackName}-rest-api"),Description:d.sub("REST API for ${AWS::StackName}"),EndpointConfiguration:{Types:["REGIONAL"]}}),e.addResource("ApiGatewayAccount","AWS::ApiGateway::Account",{CloudWatchRoleArn:d.getAtt("ApiGatewayCloudWatchRole","Arn")},{dependsOn:"ApiGatewayCloudWatchRole"}),e.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"]}),e.addResource("RestApiDeployment","AWS::ApiGateway::Deployment",{RestApiId:d.ref("RestApi"),Description:"Initial deployment"},{dependsOn:"RestApi"});let a={RestApiId:d.ref("RestApi"),DeploymentId:d.ref("RestApiDeployment"),StageName:"prod",Description:"Production stage",MethodSettings:[{ResourcePath:"/*",HttpMethod:"*",LoggingLevel:"INFO",DataTraceEnabled:!0,MetricsEnabled:!0}]};if(t.throttling)a.MethodSettings[0].ThrottlingBurstLimit=t.throttling.burstLimit,a.MethodSettings[0].ThrottlingRateLimit=t.throttling.rateLimit;if(e.addResource("RestApiStage","AWS::ApiGateway::Stage",a,{dependsOn:["RestApi","RestApiDeployment"]}),t.customDomain)Qt(e,"RestApi",t.customDomain,"REST");e.addOutputs({RestApiId:{Description:"REST API ID",Value:d.ref("RestApi"),Export:{Name:d.sub("${AWS::StackName}-rest-api-id")}},RestApiEndpoint:{Description:"REST API endpoint",Value:d.sub("https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/prod"),Export:{Name:d.sub("${AWS::StackName}-rest-api-endpoint")}}})}function qi(e,t){if(e.addResource("WebSocketApi","AWS::ApiGatewayV2::Api",{Name:d.sub("${AWS::StackName}-websocket-api"),ProtocolType:"WEBSOCKET",RouteSelectionExpression:"$request.body.action"}),t.routes){if(t.routes.connect)lt(e,"$connect",t.routes.connect.functionName);if(t.routes.disconnect)lt(e,"$disconnect",t.routes.disconnect.functionName);if(t.routes.default)lt(e,"$default",t.routes.default.functionName);if(t.routes.custom)t.routes.custom.forEach((a)=>{lt(e,a.routeKey,a.functionName)})}if(e.addResource("WebSocketApiStage","AWS::ApiGatewayV2::Stage",{ApiId:d.ref("WebSocketApi"),StageName:"prod",AutoDeploy:!0,DefaultRouteSettings:t.throttling?{ThrottlingBurstLimit:t.throttling.burstLimit,ThrottlingRateLimit:t.throttling.rateLimit}:void 0},{dependsOn:"WebSocketApi"}),t.customDomain)Qt(e,"WebSocketApi",t.customDomain,"WEBSOCKET");e.addOutputs({WebSocketApiId:{Description:"WebSocket API ID",Value:d.ref("WebSocketApi"),Export:{Name:d.sub("${AWS::StackName}-websocket-api-id")}},WebSocketApiEndpoint:{Description:"WebSocket API endpoint",Value:d.getAtt("WebSocketApi","ApiEndpoint"),Export:{Name:d.sub("${AWS::StackName}-websocket-api-endpoint")}}})}function lt(e,t,a){let r=e.toLogicalId(`websocket-route-${t}`),n=e.toLogicalId(`websocket-integration-${t}`),i=e.toLogicalId(`${a}-function`);e.addResource(n,"AWS::ApiGatewayV2::Integration",{ApiId:d.ref("WebSocketApi"),IntegrationType:"AWS_PROXY",IntegrationUri:d.sub(`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${i}.Arn}/invocations`)},{dependsOn:["WebSocketApi",i]}),e.addResource(r,"AWS::ApiGatewayV2::Route",{ApiId:d.ref("WebSocketApi"),RouteKey:t,Target:d.join("/",["integrations",d.ref(n)])},{dependsOn:["WebSocketApi",n]}),e.addResource(`${r}Permission`,"AWS::Lambda::Permission",{FunctionName:d.ref(i),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:d.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${WebSocketApi}/*")},{dependsOn:[i,"WebSocketApi"]})}function Qt(e,t,a,r){let n={DomainName:a.domain};if(r==="REST")n.CertificateArn=a.certificateArn,n.EndpointConfiguration={Types:["REGIONAL"]},e.addResource("ApiCustomDomain","AWS::ApiGateway::DomainName",n),e.addResource("ApiBasePathMapping","AWS::ApiGateway::BasePathMapping",{DomainName:d.ref("ApiCustomDomain"),RestApiId:d.ref(t),Stage:d.ref("RestApiStage")},{dependsOn:["ApiCustomDomain",t,"RestApiStage"]});else n.DomainNameConfigurations=[{CertificateArn:a.certificateArn,EndpointType:"REGIONAL"}],e.addResource("ApiCustomDomain","AWS::ApiGatewayV2::DomainName",n),e.addResource("ApiMapping","AWS::ApiGatewayV2::ApiMapping",{ApiId:d.ref(t),DomainName:d.ref("ApiCustomDomain"),Stage:r==="HTTP"?d.ref("HttpApiStage"):d.ref("WebSocketApiStage")},{dependsOn:["ApiCustomDomain",t]});if(a.dnsProvider!=="external")e.addResource("ApiDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:d.sub(`${Qi(a.domain)}.`),Name:a.domain,Type:"A",AliasTarget:{HostedZoneId:d.getAtt("ApiCustomDomain","RegionalHostedZoneId"),DNSName:d.getAtt("ApiCustomDomain","RegionalDomainName"),EvaluateTargetHealth:!1}},{dependsOn:"ApiCustomDomain"});e.addOutputs({ApiCustomDomainName:{Description:"Configured API custom domain",Value:a.domain},ApiCustomDomainTarget:{Description:"DNS target for Route53 or an external DNS provider",Value:d.getAtt("ApiCustomDomain","RegionalDomainName")},ApiCustomDomainHostedZoneId:{Description:"Regional API Gateway hosted zone ID",Value:d.getAtt("ApiCustomDomain","RegionalHostedZoneId")}})}function zi(e,t,a){if(!a)return;if(a.type==="jwt")e.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:d.ref(t),AuthorizerType:"JWT",IdentitySource:[a.identitySource||"$request.header.Authorization"],JwtConfiguration:{Issuer:a.issuer,Audience:a.audience},Name:"JWTAuthorizer"},{dependsOn:t});else if(a.type==="lambda")e.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:d.ref(t),AuthorizerType:"REQUEST",AuthorizerUri:a.authorizerUri,IdentitySource:[a.identitySource||"$request.header.Authorization"],Name:"LambdaAuthorizer"},{dependsOn:t})}function Qi(e){let t=e.split(".");if(t.length>=2)return t.slice(-2).join(".");return e}function Ji(e,t){if(t.redis)Yi(e,t.redis);if(t.memcached)Zi(e,t.memcached);if(t.elasticache)Xi(e,t.elasticache)}function Yi(e,t){if(!t)return;if(e.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache Redis cluster",SubnetIds:[d.ref("PrivateSubnet1"),d.ref("PrivateSubnet2")],Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-cache-subnet-group")}]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]}),e.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Redis",VpcId:d.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:t.port||6379,ToPort:t.port||6379,SourceSecurityGroupId:d.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]}),t.parameterGroup&&Object.keys(t.parameterGroup).length>0)e.addResource("CacheParameterGroup","AWS::ElastiCache::ParameterGroup",{Description:"Parameter group for Redis",CacheParameterGroupFamily:`redis${t.engineVersion.split(".")[0]}`,Properties:t.parameterGroup});if(t.numCacheNodes>1||t.automaticFailoverEnabled)e.addResource("RedisReplicationGroup","AWS::ElastiCache::ReplicationGroup",{ReplicationGroupDescription:"Redis replication group",ReplicationGroupId:d.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:t.engineVersion,CacheNodeType:t.nodeType,NumCacheClusters:t.numCacheNodes,AutomaticFailoverEnabled:t.automaticFailoverEnabled||!1,MultiAZEnabled:t.automaticFailoverEnabled||!1,Port:t.port||6379,CacheSubnetGroupName:d.ref("CacheSubnetGroup"),SecurityGroupIds:[d.ref("CacheSecurityGroup")],CacheParameterGroupName:t.parameterGroup?d.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:t.snapshotRetentionLimit||5,SnapshotWindow:t.snapshotWindow||"03:00-05:00",PreferredMaintenanceWindow:"sun:05:00-sun:06:00",AtRestEncryptionEnabled:!0,TransitEncryptionEnabled:!0,Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-redis")}]},{dependsOn:t.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),e.addOutputs({RedisEndpoint:{Description:"Redis primary endpoint",Value:d.getAtt("RedisReplicationGroup","PrimaryEndPoint.Address"),Export:{Name:d.sub("${AWS::StackName}-redis-endpoint")}},RedisPort:{Description:"Redis port",Value:d.getAtt("RedisReplicationGroup","PrimaryEndPoint.Port"),Export:{Name:d.sub("${AWS::StackName}-redis-port")}}});else e.addResource("RedisCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:d.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:t.engineVersion,CacheNodeType:t.nodeType,NumCacheNodes:1,Port:t.port||6379,CacheSubnetGroupName:d.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[d.ref("CacheSecurityGroup")],CacheParameterGroupName:t.parameterGroup?d.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:t.snapshotRetentionLimit||5,SnapshotWindow:t.snapshotWindow||"03:00-05:00",PreferredMaintenanceWindow:"sun:05:00-sun:06:00",Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-redis")}]},{dependsOn:t.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),e.addOutputs({RedisEndpoint:{Description:"Redis endpoint",Value:d.getAtt("RedisCacheCluster","RedisEndpoint.Address"),Export:{Name:d.sub("${AWS::StackName}-redis-endpoint")}},RedisPort:{Description:"Redis port",Value:d.getAtt("RedisCacheCluster","RedisEndpoint.Port"),Export:{Name:d.sub("${AWS::StackName}-redis-port")}}})}function Zi(e,t){if(!t)return;if(!e.hasResource("CacheSubnetGroup"))e.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[d.ref("PrivateSubnet1"),d.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!e.hasResource("CacheSecurityGroup"))e.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Memcached",VpcId:d.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:t.port||11211,ToPort:t.port||11211,SourceSecurityGroupId:d.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});e.addResource("MemcachedCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:d.sub("${AWS::StackName}-memcached"),Engine:"memcached",EngineVersion:t.engineVersion,CacheNodeType:t.nodeType,NumCacheNodes:t.numCacheNodes,Port:t.port||11211,CacheSubnetGroupName:d.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[d.ref("CacheSecurityGroup")],PreferredMaintenanceWindow:"sun:05:00-sun:06:00",Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-memcached")}]},{dependsOn:["CacheSubnetGroup","CacheSecurityGroup"]}),e.addOutputs({MemcachedEndpoint:{Description:"Memcached configuration endpoint",Value:d.getAtt("MemcachedCacheCluster","ConfigurationEndpoint.Address"),Export:{Name:d.sub("${AWS::StackName}-memcached-endpoint")}},MemcachedPort:{Description:"Memcached port",Value:d.getAtt("MemcachedCacheCluster","ConfigurationEndpoint.Port"),Export:{Name:d.sub("${AWS::StackName}-memcached-port")}}})}function Xi(e,t){if(!t)return;let a=t.engine==="redis";if(!e.hasResource("CacheSubnetGroup"))e.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[d.ref("PrivateSubnet1"),d.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!e.hasResource("CacheSecurityGroup"))e.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache",VpcId:d.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:a?6379:11211,ToPort:a?6379:11211,SourceSecurityGroupId:d.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});e.addResource("CacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:d.sub(`\${AWS::StackName}-${t.engine}`),Engine:t.engine,EngineVersion:t.engineVersion,CacheNodeType:t.nodeType,NumCacheNodes:t.numCacheNodes,CacheSubnetGroupName:d.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[d.ref("CacheSecurityGroup")],Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-${t.engine}`)}]},{dependsOn:["CacheSubnetGroup","CacheSecurityGroup"]})}function es(e,t){if(!t.enabled)return;e.addResource("CloudFrontOriginAccessIdentity","AWS::CloudFront::CloudFrontOriginAccessIdentity",{CloudFrontOriginAccessIdentityConfig:{Comment:d.sub("${AWS::StackName} CloudFront OAI")}});let a=[],r=[];if(!t.origins||t.origins.length===0)a.push({Id:"S3Origin",DomainName:d.getAtt("StaticBucket","DomainName"),S3OriginConfig:{OriginAccessIdentity:d.sub("origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}")}});else t.origins.forEach((s,o)=>{let c={Id:s.id,DomainName:s.domainName};if(s.originPath)c.OriginPath=s.originPath;if(s.domainName.includes("s3"))c.S3OriginConfig={OriginAccessIdentity:d.sub("origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}")};else c.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"]};if(a.push(c),o>0||s.pathPattern)r.push({PathPattern:s.pathPattern||`/${s.id}/*`,TargetOriginId:s.id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:t.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:t.cachePolicy?.minTTL||0,DefaultTTL:t.cachePolicy?.defaultTTL||86400,MaxTTL:t.cachePolicy?.maxTTL||31536000})});let n={TargetOriginId:a[0].Id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:t.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:t.cachePolicy?.minTTL||0,DefaultTTL:t.cachePolicy?.defaultTTL||86400,MaxTTL:t.cachePolicy?.maxTTL||31536000};if(t.edgeFunctions&&t.edgeFunctions.length>0)n.LambdaFunctionAssociations=t.edgeFunctions.map((s)=>({EventType:s.eventType,LambdaFunctionARN:s.functionArn}));let i={Enabled:!0,HttpVersion:t.http3?"http3":"http2",IPV6Enabled:!0,Origins:a,DefaultCacheBehavior:n,PriceClass:t.priceClass||"PriceClass_100",ViewerCertificate:{}};if(r.length>0)i.CacheBehaviors=r;if(t.customDomain)i.Aliases=[t.customDomain.domain],i.ViewerCertificate={AcmCertificateArn:t.customDomain.certificateArn,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};else i.ViewerCertificate={CloudFrontDefaultCertificate:!0};if(t.errorPages)i.CustomErrorResponses=Object.entries(t.errorPages).map(([s,o])=>({ErrorCode:Number.parseInt(s),ResponseCode:200,ResponsePagePath:o,ErrorCachingMinTTL:300}));if(i.DefaultRootObject="index.html",i.Comment=d.sub("${AWS::StackName} CloudFront Distribution"),e.addResource("CloudFrontDistribution","AWS::CloudFront::Distribution",{DistributionConfig:i},{dependsOn:"CloudFrontOriginAccessIdentity"}),!t.origins||t.origins.length===0)e.addResource("StaticBucketPolicyForCloudFront","AWS::S3::BucketPolicy",{Bucket:d.ref("StaticBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowCloudFrontAccess",Effect:"Allow",Principal:{CanonicalUser:d.getAtt("CloudFrontOriginAccessIdentity","S3CanonicalUserId")},Action:"s3:GetObject",Resource:d.join("",[d.getAtt("StaticBucket","Arn"),"/*"])}]}},{dependsOn:["StaticBucket","CloudFrontOriginAccessIdentity"]});if(t.customDomain)e.addResource("CloudFrontDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:d.sub(`${ts(t.customDomain.domain)}.`),Name:t.customDomain.domain,Type:"A",AliasTarget:{HostedZoneId:"Z2FDTNDATAQYW2",DNSName:d.getAtt("CloudFrontDistribution","DomainName"),EvaluateTargetHealth:!1}},{dependsOn:"CloudFrontDistribution"});if(e.addOutputs({CloudFrontDistributionId:{Description:"CloudFront distribution ID",Value:d.ref("CloudFrontDistribution"),Export:{Name:d.sub("${AWS::StackName}-cloudfront-id")}},CloudFrontDomainName:{Description:"CloudFront distribution domain name",Value:d.getAtt("CloudFrontDistribution","DomainName"),Export:{Name:d.sub("${AWS::StackName}-cloudfront-domain")}}}),t.customDomain)e.addOutputs({CloudFrontURL:{Description:"CloudFront custom domain URL",Value:d.sub(`https://${t.customDomain.domain}`)}})}function ts(e){let t=e.split(".");if(t.length>=2)return t.slice(-2).join(".");return e}function as(e,t){if(t.server)rs(e,t.server);if(t.fargate)Sa(e,"app",t.fargate);if(t.services)t.services.forEach((a)=>{if(a.type==="fargate")Sa(e,a.name,{taskDefinition:a.taskDefinition,service:a.service})})}function rs(e,t){if(!t)return;e.addResource("AppSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for application instances",VpcId:d.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:3000,ToPort:3000,SourceSecurityGroupId:d.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:d.sub("${AWS::StackName}-app-sg")}]},{dependsOn:"VPC"}),e.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:d.sub("${AWS::StackName}-ec2-role")}]}),e.addResource("EC2InstanceProfile","AWS::IAM::InstanceProfile",{Roles:[d.ref("EC2InstanceRole")]},{dependsOn:"EC2InstanceRole"});let a=t.userData||`#!/bin/bash
2468
+ };`}var d={ref:(e)=>({Ref:e}),getAtt:(e,t)=>({"Fn::GetAtt":[e,t]}),join:(e,t)=>({"Fn::Join":[e,t]}),sub:(e,t)=>t?{"Fn::Sub":[e,t]}:{"Fn::Sub":e},select:(e,t)=>({"Fn::Select":[e,t]}),split:(e,t)=>({"Fn::Split":[e,t]}),getAZs:(e="")=>({"Fn::GetAZs":e}),importValue:(e)=>({"Fn::ImportValue":e}),findInMap:(e,t,a)=>({"Fn::FindInMap":[e,t,a]}),base64:(e)=>({"Fn::Base64":e}),cidr:(e,t,a)=>({"Fn::Cidr":[e,t,a]}),equals:(e,t)=>({"Fn::Equals":[e,t]}),if:(e,t,a)=>({"Fn::If":[e,t,a]}),not:(e)=>({"Fn::Not":[e]}),and:(...e)=>({"Fn::And":e}),or:(...e)=>({"Fn::Or":e})},At={s3Bucket:(e)=>d.sub(`arn:aws:s3:::${e}`),s3Object:(e,t="*")=>d.sub(`arn:aws:s3:::${e}/${t}`),lambda:(e,t,a)=>d.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${e}`,t&&a?{"AWS::Region":t,"AWS::AccountId":a}:void 0),dynamodb:(e)=>d.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${e}`),sqs:(e)=>d.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${e}`),sns:(e)=>d.sub(`arn:aws:sns:\${AWS::Region}:\${AWS::AccountId}:${e}`),kinesis:(e)=>d.sub(`arn:aws:kinesis:\${AWS::Region}:\${AWS::AccountId}:stream/${e}`),iam:(e,t)=>d.sub(`arn:aws:iam::\${AWS::AccountId}:${e}/${t}`),secretsManager:(e)=>d.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${e}`),cloudwatch:(e)=>d.sub(`arn:aws:logs:\${AWS::Region}:\${AWS::AccountId}:log-group:${e}`)},Kl={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 ji(e,t){if(t.type==="http")Ki(e,t);else if(t.type==="rest")Hi(e,t);else if(t.type==="websocket")qi(e,t)}function Ki(e,t){let a={Name:d.sub("${AWS::StackName}-http-api"),ProtocolType:"HTTP"};if(t.cors)a.CorsConfiguration={AllowOrigins:t.cors.allowOrigins,AllowMethods:t.cors.allowMethods,AllowHeaders:t.cors.allowHeaders||["*"],MaxAge:t.cors.maxAge||300};if(e.addResource("HttpApi","AWS::ApiGatewayV2::Api",a),e.addResource("HttpApiStage","AWS::ApiGatewayV2::Stage",{ApiId:d.ref("HttpApi"),StageName:"$default",AutoDeploy:!0,DefaultRouteSettings:t.throttling?{ThrottlingBurstLimit:t.throttling.burstLimit,ThrottlingRateLimit:t.throttling.rateLimit}:void 0,AccessLogSettings:{DestinationArn:d.getAtt("ApiLogGroup","Arn"),Format:"$context.requestId $context.error.message $context.error.messageString"}},{dependsOn:["HttpApi","ApiLogGroup"]}),e.addResource("ApiLogGroup","AWS::Logs::LogGroup",{LogGroupName:d.sub("/aws/apigateway/${AWS::StackName}-http-api"),RetentionInDays:14}),t.authorizer)zi(e,"HttpApi",t.authorizer);if(t.customDomain)Jt(e,"HttpApi",t.customDomain,"HTTP");e.addOutputs({HttpApiId:{Description:"HTTP API ID",Value:d.ref("HttpApi"),Export:{Name:d.sub("${AWS::StackName}-http-api-id")}},HttpApiEndpoint:{Description:"HTTP API endpoint",Value:d.getAtt("HttpApi","ApiEndpoint"),Export:{Name:d.sub("${AWS::StackName}-http-api-endpoint")}}})}function Hi(e,t){e.addResource("RestApi","AWS::ApiGateway::RestApi",{Name:d.sub("${AWS::StackName}-rest-api"),Description:d.sub("REST API for ${AWS::StackName}"),EndpointConfiguration:{Types:["REGIONAL"]}}),e.addResource("ApiGatewayAccount","AWS::ApiGateway::Account",{CloudWatchRoleArn:d.getAtt("ApiGatewayCloudWatchRole","Arn")},{dependsOn:"ApiGatewayCloudWatchRole"}),e.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"]}),e.addResource("RestApiDeployment","AWS::ApiGateway::Deployment",{RestApiId:d.ref("RestApi"),Description:"Initial deployment"},{dependsOn:"RestApi"});let a={RestApiId:d.ref("RestApi"),DeploymentId:d.ref("RestApiDeployment"),StageName:"prod",Description:"Production stage",MethodSettings:[{ResourcePath:"/*",HttpMethod:"*",LoggingLevel:"INFO",DataTraceEnabled:!0,MetricsEnabled:!0}]};if(t.throttling)a.MethodSettings[0].ThrottlingBurstLimit=t.throttling.burstLimit,a.MethodSettings[0].ThrottlingRateLimit=t.throttling.rateLimit;if(e.addResource("RestApiStage","AWS::ApiGateway::Stage",a,{dependsOn:["RestApi","RestApiDeployment"]}),t.customDomain)Jt(e,"RestApi",t.customDomain,"REST");e.addOutputs({RestApiId:{Description:"REST API ID",Value:d.ref("RestApi"),Export:{Name:d.sub("${AWS::StackName}-rest-api-id")}},RestApiEndpoint:{Description:"REST API endpoint",Value:d.sub("https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/prod"),Export:{Name:d.sub("${AWS::StackName}-rest-api-endpoint")}}})}function qi(e,t){if(e.addResource("WebSocketApi","AWS::ApiGatewayV2::Api",{Name:d.sub("${AWS::StackName}-websocket-api"),ProtocolType:"WEBSOCKET",RouteSelectionExpression:"$request.body.action"}),t.routes){if(t.routes.connect)ct(e,"$connect",t.routes.connect.functionName);if(t.routes.disconnect)ct(e,"$disconnect",t.routes.disconnect.functionName);if(t.routes.default)ct(e,"$default",t.routes.default.functionName);if(t.routes.custom)t.routes.custom.forEach((a)=>{ct(e,a.routeKey,a.functionName)})}if(e.addResource("WebSocketApiStage","AWS::ApiGatewayV2::Stage",{ApiId:d.ref("WebSocketApi"),StageName:"prod",AutoDeploy:!0,DefaultRouteSettings:t.throttling?{ThrottlingBurstLimit:t.throttling.burstLimit,ThrottlingRateLimit:t.throttling.rateLimit}:void 0},{dependsOn:"WebSocketApi"}),t.customDomain)Jt(e,"WebSocketApi",t.customDomain,"WEBSOCKET");e.addOutputs({WebSocketApiId:{Description:"WebSocket API ID",Value:d.ref("WebSocketApi"),Export:{Name:d.sub("${AWS::StackName}-websocket-api-id")}},WebSocketApiEndpoint:{Description:"WebSocket API endpoint",Value:d.getAtt("WebSocketApi","ApiEndpoint"),Export:{Name:d.sub("${AWS::StackName}-websocket-api-endpoint")}}})}function ct(e,t,a){let r=e.toLogicalId(`websocket-route-${t}`),n=e.toLogicalId(`websocket-integration-${t}`),i=e.toLogicalId(`${a}-function`);e.addResource(n,"AWS::ApiGatewayV2::Integration",{ApiId:d.ref("WebSocketApi"),IntegrationType:"AWS_PROXY",IntegrationUri:d.sub(`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${i}.Arn}/invocations`)},{dependsOn:["WebSocketApi",i]}),e.addResource(r,"AWS::ApiGatewayV2::Route",{ApiId:d.ref("WebSocketApi"),RouteKey:t,Target:d.join("/",["integrations",d.ref(n)])},{dependsOn:["WebSocketApi",n]}),e.addResource(`${r}Permission`,"AWS::Lambda::Permission",{FunctionName:d.ref(i),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:d.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${WebSocketApi}/*")},{dependsOn:[i,"WebSocketApi"]})}function Jt(e,t,a,r){let n={DomainName:a.domain};if(r==="REST")n.CertificateArn=a.certificateArn,n.EndpointConfiguration={Types:["REGIONAL"]},e.addResource("ApiCustomDomain","AWS::ApiGateway::DomainName",n),e.addResource("ApiBasePathMapping","AWS::ApiGateway::BasePathMapping",{DomainName:d.ref("ApiCustomDomain"),RestApiId:d.ref(t),Stage:d.ref("RestApiStage")},{dependsOn:["ApiCustomDomain",t,"RestApiStage"]});else n.DomainNameConfigurations=[{CertificateArn:a.certificateArn,EndpointType:"REGIONAL"}],e.addResource("ApiCustomDomain","AWS::ApiGatewayV2::DomainName",n),e.addResource("ApiMapping","AWS::ApiGatewayV2::ApiMapping",{ApiId:d.ref(t),DomainName:d.ref("ApiCustomDomain"),Stage:r==="HTTP"?d.ref("HttpApiStage"):d.ref("WebSocketApiStage")},{dependsOn:["ApiCustomDomain",t]});if(a.dnsProvider!=="external")e.addResource("ApiDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:d.sub(`${Ji(a.domain)}.`),Name:a.domain,Type:"A",AliasTarget:{HostedZoneId:d.getAtt("ApiCustomDomain","RegionalHostedZoneId"),DNSName:d.getAtt("ApiCustomDomain","RegionalDomainName"),EvaluateTargetHealth:!1}},{dependsOn:"ApiCustomDomain"});e.addOutputs({ApiCustomDomainName:{Description:"Configured API custom domain",Value:a.domain},ApiCustomDomainTarget:{Description:"DNS target for Route53 or an external DNS provider",Value:d.getAtt("ApiCustomDomain","RegionalDomainName")},ApiCustomDomainHostedZoneId:{Description:"Regional API Gateway hosted zone ID",Value:d.getAtt("ApiCustomDomain","RegionalHostedZoneId")}})}function zi(e,t,a){if(!a)return;if(a.type==="jwt")e.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:d.ref(t),AuthorizerType:"JWT",IdentitySource:[a.identitySource||"$request.header.Authorization"],JwtConfiguration:{Issuer:a.issuer,Audience:a.audience},Name:"JWTAuthorizer"},{dependsOn:t});else if(a.type==="lambda")e.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:d.ref(t),AuthorizerType:"REQUEST",AuthorizerUri:a.authorizerUri,IdentitySource:[a.identitySource||"$request.header.Authorization"],Name:"LambdaAuthorizer"},{dependsOn:t})}function Ji(e){let t=e.split(".");if(t.length>=2)return t.slice(-2).join(".");return e}function Qi(e,t){if(t.redis)$i(e,t.redis);if(t.memcached)Yi(e,t.memcached);if(t.elasticache)Xi(e,t.elasticache)}function $i(e,t){if(!t)return;if(e.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache Redis cluster",SubnetIds:[d.ref("PrivateSubnet1"),d.ref("PrivateSubnet2")],Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-cache-subnet-group")}]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]}),e.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Redis",VpcId:d.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:t.port||6379,ToPort:t.port||6379,SourceSecurityGroupId:d.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]}),t.parameterGroup&&Object.keys(t.parameterGroup).length>0)e.addResource("CacheParameterGroup","AWS::ElastiCache::ParameterGroup",{Description:"Parameter group for Redis",CacheParameterGroupFamily:`redis${t.engineVersion.split(".")[0]}`,Properties:t.parameterGroup});if(t.numCacheNodes>1||t.automaticFailoverEnabled)e.addResource("RedisReplicationGroup","AWS::ElastiCache::ReplicationGroup",{ReplicationGroupDescription:"Redis replication group",ReplicationGroupId:d.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:t.engineVersion,CacheNodeType:t.nodeType,NumCacheClusters:t.numCacheNodes,AutomaticFailoverEnabled:t.automaticFailoverEnabled||!1,MultiAZEnabled:t.automaticFailoverEnabled||!1,Port:t.port||6379,CacheSubnetGroupName:d.ref("CacheSubnetGroup"),SecurityGroupIds:[d.ref("CacheSecurityGroup")],CacheParameterGroupName:t.parameterGroup?d.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:t.snapshotRetentionLimit||5,SnapshotWindow:t.snapshotWindow||"03:00-05:00",PreferredMaintenanceWindow:"sun:05:00-sun:06:00",AtRestEncryptionEnabled:!0,TransitEncryptionEnabled:!0,Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-redis")}]},{dependsOn:t.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),e.addOutputs({RedisEndpoint:{Description:"Redis primary endpoint",Value:d.getAtt("RedisReplicationGroup","PrimaryEndPoint.Address"),Export:{Name:d.sub("${AWS::StackName}-redis-endpoint")}},RedisPort:{Description:"Redis port",Value:d.getAtt("RedisReplicationGroup","PrimaryEndPoint.Port"),Export:{Name:d.sub("${AWS::StackName}-redis-port")}}});else e.addResource("RedisCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:d.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:t.engineVersion,CacheNodeType:t.nodeType,NumCacheNodes:1,Port:t.port||6379,CacheSubnetGroupName:d.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[d.ref("CacheSecurityGroup")],CacheParameterGroupName:t.parameterGroup?d.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:t.snapshotRetentionLimit||5,SnapshotWindow:t.snapshotWindow||"03:00-05:00",PreferredMaintenanceWindow:"sun:05:00-sun:06:00",Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-redis")}]},{dependsOn:t.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),e.addOutputs({RedisEndpoint:{Description:"Redis endpoint",Value:d.getAtt("RedisCacheCluster","RedisEndpoint.Address"),Export:{Name:d.sub("${AWS::StackName}-redis-endpoint")}},RedisPort:{Description:"Redis port",Value:d.getAtt("RedisCacheCluster","RedisEndpoint.Port"),Export:{Name:d.sub("${AWS::StackName}-redis-port")}}})}function Yi(e,t){if(!t)return;if(!e.hasResource("CacheSubnetGroup"))e.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[d.ref("PrivateSubnet1"),d.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!e.hasResource("CacheSecurityGroup"))e.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Memcached",VpcId:d.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:t.port||11211,ToPort:t.port||11211,SourceSecurityGroupId:d.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});e.addResource("MemcachedCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:d.sub("${AWS::StackName}-memcached"),Engine:"memcached",EngineVersion:t.engineVersion,CacheNodeType:t.nodeType,NumCacheNodes:t.numCacheNodes,Port:t.port||11211,CacheSubnetGroupName:d.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[d.ref("CacheSecurityGroup")],PreferredMaintenanceWindow:"sun:05:00-sun:06:00",Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-memcached")}]},{dependsOn:["CacheSubnetGroup","CacheSecurityGroup"]}),e.addOutputs({MemcachedEndpoint:{Description:"Memcached configuration endpoint",Value:d.getAtt("MemcachedCacheCluster","ConfigurationEndpoint.Address"),Export:{Name:d.sub("${AWS::StackName}-memcached-endpoint")}},MemcachedPort:{Description:"Memcached port",Value:d.getAtt("MemcachedCacheCluster","ConfigurationEndpoint.Port"),Export:{Name:d.sub("${AWS::StackName}-memcached-port")}}})}function Xi(e,t){if(!t)return;let a=t.engine==="redis";if(!e.hasResource("CacheSubnetGroup"))e.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[d.ref("PrivateSubnet1"),d.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!e.hasResource("CacheSecurityGroup"))e.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache",VpcId:d.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:a?6379:11211,ToPort:a?6379:11211,SourceSecurityGroupId:d.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});e.addResource("CacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:d.sub(`\${AWS::StackName}-${t.engine}`),Engine:t.engine,EngineVersion:t.engineVersion,CacheNodeType:t.nodeType,NumCacheNodes:t.numCacheNodes,CacheSubnetGroupName:d.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[d.ref("CacheSecurityGroup")],Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-${t.engine}`)}]},{dependsOn:["CacheSubnetGroup","CacheSecurityGroup"]})}function Zi(e,t){if(!t.enabled)return;e.addResource("CloudFrontOriginAccessIdentity","AWS::CloudFront::CloudFrontOriginAccessIdentity",{CloudFrontOriginAccessIdentityConfig:{Comment:d.sub("${AWS::StackName} CloudFront OAI")}});let a=[],r=[];if(!t.origins||t.origins.length===0)a.push({Id:"S3Origin",DomainName:d.getAtt("StaticBucket","DomainName"),S3OriginConfig:{OriginAccessIdentity:d.sub("origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}")}});else t.origins.forEach((s,o)=>{let c={Id:s.id,DomainName:s.domainName};if(s.originPath)c.OriginPath=s.originPath;if(s.domainName.includes("s3"))c.S3OriginConfig={OriginAccessIdentity:d.sub("origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}")};else c.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"]};if(a.push(c),o>0||s.pathPattern)r.push({PathPattern:s.pathPattern||`/${s.id}/*`,TargetOriginId:s.id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:t.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:t.cachePolicy?.minTTL||0,DefaultTTL:t.cachePolicy?.defaultTTL||86400,MaxTTL:t.cachePolicy?.maxTTL||31536000})});let n={TargetOriginId:a[0].Id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:t.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:t.cachePolicy?.minTTL||0,DefaultTTL:t.cachePolicy?.defaultTTL||86400,MaxTTL:t.cachePolicy?.maxTTL||31536000};if(t.edgeFunctions&&t.edgeFunctions.length>0)n.LambdaFunctionAssociations=t.edgeFunctions.map((s)=>({EventType:s.eventType,LambdaFunctionARN:s.functionArn}));let i={Enabled:!0,HttpVersion:t.http3?"http3":"http2",IPV6Enabled:!0,Origins:a,DefaultCacheBehavior:n,PriceClass:t.priceClass||"PriceClass_100",ViewerCertificate:{}};if(r.length>0)i.CacheBehaviors=r;if(t.customDomain)i.Aliases=[t.customDomain.domain],i.ViewerCertificate={AcmCertificateArn:t.customDomain.certificateArn,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};else i.ViewerCertificate={CloudFrontDefaultCertificate:!0};if(t.errorPages)i.CustomErrorResponses=Object.entries(t.errorPages).map(([s,o])=>({ErrorCode:Number.parseInt(s),ResponseCode:200,ResponsePagePath:o,ErrorCachingMinTTL:300}));if(i.DefaultRootObject="index.html",i.Comment=d.sub("${AWS::StackName} CloudFront Distribution"),e.addResource("CloudFrontDistribution","AWS::CloudFront::Distribution",{DistributionConfig:i},{dependsOn:"CloudFrontOriginAccessIdentity"}),!t.origins||t.origins.length===0)e.addResource("StaticBucketPolicyForCloudFront","AWS::S3::BucketPolicy",{Bucket:d.ref("StaticBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowCloudFrontAccess",Effect:"Allow",Principal:{CanonicalUser:d.getAtt("CloudFrontOriginAccessIdentity","S3CanonicalUserId")},Action:"s3:GetObject",Resource:d.join("",[d.getAtt("StaticBucket","Arn"),"/*"])}]}},{dependsOn:["StaticBucket","CloudFrontOriginAccessIdentity"]});if(t.customDomain)e.addResource("CloudFrontDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:d.sub(`${es(t.customDomain.domain)}.`),Name:t.customDomain.domain,Type:"A",AliasTarget:{HostedZoneId:"Z2FDTNDATAQYW2",DNSName:d.getAtt("CloudFrontDistribution","DomainName"),EvaluateTargetHealth:!1}},{dependsOn:"CloudFrontDistribution"});if(e.addOutputs({CloudFrontDistributionId:{Description:"CloudFront distribution ID",Value:d.ref("CloudFrontDistribution"),Export:{Name:d.sub("${AWS::StackName}-cloudfront-id")}},CloudFrontDomainName:{Description:"CloudFront distribution domain name",Value:d.getAtt("CloudFrontDistribution","DomainName"),Export:{Name:d.sub("${AWS::StackName}-cloudfront-domain")}}}),t.customDomain)e.addOutputs({CloudFrontURL:{Description:"CloudFront custom domain URL",Value:d.sub(`https://${t.customDomain.domain}`)}})}function es(e){let t=e.split(".");if(t.length>=2)return t.slice(-2).join(".");return e}function ts(e,t){if(t.server)as(e,t.server);if(t.fargate)fa(e,"app",t.fargate);if(t.services)t.services.forEach((a)=>{if(a.type==="fargate")fa(e,a.name,{taskDefinition:a.taskDefinition,service:a.service})})}function as(e,t){if(!t)return;e.addResource("AppSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for application instances",VpcId:d.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:3000,ToPort:3000,SourceSecurityGroupId:d.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:d.sub("${AWS::StackName}-app-sg")}]},{dependsOn:"VPC"}),e.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:d.sub("${AWS::StackName}-ec2-role")}]}),e.addResource("EC2InstanceProfile","AWS::IAM::InstanceProfile",{Roles:[d.ref("EC2InstanceRole")]},{dependsOn:"EC2InstanceRole"});let a=t.userData||`#!/bin/bash
2469
2469
  set -e
2470
2470
  # Update system
2471
2471
  yum update -y || apt-get update -y
@@ -2480,20 +2480,20 @@ rpm -U ./amazon-cloudwatch-agent.rpm || true
2480
2480
 
2481
2481
  # Signal completion
2482
2482
  /opt/aws/bin/cfn-signal -e $? --stack \${AWS::StackName} --resource AutoScalingGroup --region \${AWS::Region}
2483
- `;if(e.addResource("LaunchTemplate","AWS::EC2::LaunchTemplate",{LaunchTemplateName:d.sub("${AWS::StackName}-template"),LaunchTemplateData:{ImageId:t.ami||d.findInMap("RegionMap",d.ref("AWS::Region"),"AMI"),InstanceType:t.instanceType,IamInstanceProfile:{Arn:d.getAtt("EC2InstanceProfile","Arn")},SecurityGroupIds:[d.ref("AppSecurityGroup")],UserData:d.base64(d.sub(a)),TagSpecifications:[{ResourceType:"instance",Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-instance")}]}],MetadataOptions:{HttpTokens:"required",HttpPutResponseHopLimit:1}}},{dependsOn:["AppSecurityGroup","EC2InstanceProfile"]}),t.loadBalancer){ns(e,t.loadBalancer);let r={LaunchTemplate:{LaunchTemplateId:d.ref("LaunchTemplate"),Version:d.getAtt("LaunchTemplate","LatestVersionNumber")},MinSize:t.autoScaling?.min.toString()||"1",MaxSize:t.autoScaling?.max.toString()||"3",DesiredCapacity:t.autoScaling?.min.toString()||"2",VPCZoneIdentifier:[d.ref("PrivateSubnet1"),d.ref("PrivateSubnet2")],TargetGroupARNs:[d.ref("TargetGroup")],HealthCheckType:"ELB",HealthCheckGracePeriod:300,Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-asg"),PropagateAtLaunch:!0}]};if(e.addResource("AutoScalingGroup","AWS::AutoScaling::AutoScalingGroup",r,{dependsOn:["LaunchTemplate","TargetGroup"]}),t.autoScaling)e.addResource("ScaleUpPolicy","AWS::AutoScaling::ScalingPolicy",{AdjustmentType:"ChangeInCapacity",AutoScalingGroupName:d.ref("AutoScalingGroup"),Cooldown:t.autoScaling.scaleUpCooldown?.toString()||"300",ScalingAdjustment:"1"},{dependsOn:"AutoScalingGroup"}),e.addResource("ScaleDownPolicy","AWS::AutoScaling::ScalingPolicy",{AdjustmentType:"ChangeInCapacity",AutoScalingGroupName:d.ref("AutoScalingGroup"),Cooldown:t.autoScaling.scaleDownCooldown?.toString()||"300",ScalingAdjustment:"-1"},{dependsOn:"AutoScalingGroup"}),e.addResource("HighCPUAlarm","AWS::CloudWatch::Alarm",{AlarmDescription:"Scale up when CPU exceeds target",MetricName:"CPUUtilization",Namespace:"AWS/EC2",Statistic:"Average",Period:"300",EvaluationPeriods:"2",Threshold:(t.autoScaling.targetCPU||70).toString(),AlarmActions:[d.ref("ScaleUpPolicy")],Dimensions:[{Name:"AutoScalingGroupName",Value:d.ref("AutoScalingGroup")}],ComparisonOperator:"GreaterThanThreshold"},{dependsOn:["AutoScalingGroup","ScaleUpPolicy"]}),e.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:((t.autoScaling.targetCPU||70)-20).toString(),AlarmActions:[d.ref("ScaleDownPolicy")],Dimensions:[{Name:"AutoScalingGroupName",Value:d.ref("AutoScalingGroup")}],ComparisonOperator:"LessThanThreshold"},{dependsOn:["AutoScalingGroup","ScaleDownPolicy"]})}}function ns(e,t){if(!t)return;e.addResource("ALBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for Application Load Balancer",VpcId:d.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:d.sub("${AWS::StackName}-alb-sg")}]},{dependsOn:"VPC"}),e.addResource("LoadBalancer","AWS::ElasticLoadBalancingV2::LoadBalancer",{Name:d.sub("${AWS::StackName}-alb"),Type:t.type||"application",Scheme:"internet-facing",IpAddressType:"ipv4",Subnets:[d.ref("PublicSubnet1"),d.ref("PublicSubnet2")],SecurityGroups:[d.ref("ALBSecurityGroup")],Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-alb")}]},{dependsOn:["PublicSubnet1","PublicSubnet2","ALBSecurityGroup"]}),e.addResource("TargetGroup","AWS::ElasticLoadBalancingV2::TargetGroup",{Name:d.sub("${AWS::StackName}-tg"),Port:3000,Protocol:"HTTP",VpcId:d.ref("VPC"),HealthCheckEnabled:!0,HealthCheckPath:t.healthCheck?.path||"/health",HealthCheckProtocol:"HTTP",HealthCheckIntervalSeconds:t.healthCheck?.interval||30,HealthCheckTimeoutSeconds:t.healthCheck?.timeout||5,HealthyThresholdCount:t.healthCheck?.healthyThreshold||2,UnhealthyThresholdCount:t.healthCheck?.unhealthyThreshold||3,TargetType:"instance",Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-tg")}]},{dependsOn:"VPC"}),e.addResource("LoadBalancerListener","AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:d.ref("LoadBalancer"),Port:80,Protocol:"HTTP",DefaultActions:[{Type:"forward",TargetGroupArn:d.ref("TargetGroup")}]},{dependsOn:["LoadBalancer","TargetGroup"]}),e.addOutputs({LoadBalancerDNS:{Description:"Load Balancer DNS Name",Value:d.getAtt("LoadBalancer","DNSName"),Export:{Name:d.sub("${AWS::StackName}-alb-dns")}}})}function Sa(e,t,a){let r=e.toLogicalId(t),n=a.taskDefinition.containerDefinitions?.[0],i=n?.name||n?.Name||t,s=n?.portMappings?.[0]?.containerPort||n?.PortMappings?.[0]?.ContainerPort||3000,o=(a.taskDefinition.containerDefinitions||[]).flatMap((p)=>(p.secrets||p.Secrets||[]).map((g)=>g.valueFrom||g.ValueFrom)).filter(Boolean);if(!e.hasResource("ECSCluster"))e.addResource("ECSCluster","AWS::ECS::Cluster",{ClusterName:d.sub("${AWS::StackName}-cluster"),Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-cluster")}]});if(e.addResource(`${r}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"],...o.length?{Policies:[{PolicyName:"read-task-secrets",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameters"],Resource:o},{Effect:"Allow",Action:"kms:Decrypt",Resource:"*"}]}}]}:{}}),e.addResource(`${r}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:d.sub("arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:${AWS::StackName}-*")},{Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail"],Resource:"*"}]}}]}),!e.hasResource("ALBSecurityGroup"))e.addResource("ALBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Public ingress for the application load balancer",VpcId:d.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:80,ToPort:80,CidrIp:"0.0.0.0/0"},...a.loadBalancer?.customDomain?.certificateArn?[{IpProtocol:"tcp",FromPort:443,ToPort:443,CidrIp:"0.0.0.0/0"}]:[]],SecurityGroupEgress:[{IpProtocol:"tcp",FromPort:s,ToPort:s,CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-alb-sg")}]},{dependsOn:"VPC"});if(!e.hasResource("AppSecurityGroup"))e.addResource("AppSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Only the application load balancer may reach Fargate tasks",VpcId:d.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:s,ToPort:s,SourceSecurityGroupId:d.ref("ALBSecurityGroup")}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-app-sg")}]},{dependsOn:["VPC","ALBSecurityGroup"]});let c=(a.taskDefinition.containerDefinitions||[{name:t,image:d.sub(`\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.amazonaws.com/${t}:latest`),portMappings:[{containerPort:3000}]}]).map((p)=>({Name:p.Name||p.name,Image:p.Image||p.image,Essential:p.Essential??p.essential??!0,PortMappings:(p.PortMappings||p.portMappings||[]).map((g)=>({ContainerPort:g.ContainerPort??g.containerPort,Protocol:g.Protocol||g.protocol||"tcp"})),Environment:Array.isArray(p.Environment||p.environment)?(p.Environment||p.environment).map((g)=>({Name:g.Name||g.name,Value:g.Value??g.value})):Object.entries(p.Environment||p.environment||{}).map(([g,h])=>({Name:g,Value:h})),Secrets:(p.Secrets||p.secrets||[]).map((g)=>({Name:g.Name||g.name,ValueFrom:g.ValueFrom||g.valueFrom})),HealthCheck:p.HealthCheck||p.healthCheck,Command:p.Command||p.command,EntryPoint:p.EntryPoint||p.entryPoint,LogConfiguration:p.LogConfiguration||p.logConfiguration||{LogDriver:"awslogs",Options:{"awslogs-group":d.ref(`${r}LogGroup`),"awslogs-region":d.ref("AWS::Region"),"awslogs-stream-prefix":t}}}));e.addResource(`${r}TaskDefinition`,"AWS::ECS::TaskDefinition",{Family:d.sub(`\${AWS::StackName}-${t}`),NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:a.taskDefinition.cpu,Memory:a.taskDefinition.memory,ExecutionRoleArn:d.getAtt(`${r}TaskExecutionRole`,"Arn"),TaskRoleArn:d.getAtt(`${r}TaskRole`,"Arn"),ContainerDefinitions:c},{dependsOn:[`${r}TaskExecutionRole`,`${r}TaskRole`,`${r}LogGroup`]}),e.addResource(`${r}LogGroup`,"AWS::Logs::LogGroup",{LogGroupName:d.sub(`/ecs/\${AWS::StackName}/${t}`),RetentionInDays:14});let l=a.service.healthCheck||{};e.addResource(`${r}TargetGroup`,"AWS::ElasticLoadBalancingV2::TargetGroup",{VpcId:d.ref("VPC"),Port:s,Protocol:"HTTP",TargetType:"ip",HealthCheckEnabled:!0,HealthCheckPath:l.path||"/health",HealthCheckProtocol:"HTTP",HealthCheckIntervalSeconds:l.interval||30,HealthCheckTimeoutSeconds:l.timeout||5,HealthyThresholdCount:l.healthyThreshold||2,UnhealthyThresholdCount:l.unhealthyThreshold||3,Matcher:{HttpCode:"200-399"},TargetGroupAttributes:[{Key:"deregistration_delay.timeout_seconds",Value:"30"}]},{dependsOn:"VPC"}),e.addResource(`${r}LoadBalancer`,"AWS::ElasticLoadBalancingV2::LoadBalancer",{Type:"application",Scheme:"internet-facing",IpAddressType:"ipv4",Subnets:[d.ref("PublicSubnet1"),d.ref("PublicSubnet2")],SecurityGroups:[d.ref("ALBSecurityGroup")],LoadBalancerAttributes:[{Key:"routing.http.drop_invalid_header_fields.enabled",Value:"true"},{Key:"deletion_protection.enabled",Value:String(a.loadBalancer?.deletionProtection===!0)}],Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-${t}-alb`)}]},{dependsOn:["PublicSubnet1","PublicSubnet2","ALBSecurityGroup"]});let u=a.loadBalancer?.customDomain?.certificateArn,m=a.loadBalancer?.originVerifyHeader;if(e.addResource(`${r}HttpListener`,"AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:d.ref(`${r}LoadBalancer`),Port:80,Protocol:"HTTP",DefaultActions:u?[{Type:"redirect",RedirectConfig:{Protocol:"HTTPS",Port:"443",StatusCode:"HTTP_301"}}]:m?[{Type:"fixed-response",FixedResponseConfig:{StatusCode:"403",ContentType:"text/plain",MessageBody:"Forbidden"}}]:[{Type:"forward",TargetGroupArn:d.ref(`${r}TargetGroup`)}]},{dependsOn:[`${r}LoadBalancer`,`${r}TargetGroup`]}),u)e.addResource(`${r}HttpsListener`,"AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:d.ref(`${r}LoadBalancer`),Port:443,Protocol:"HTTPS",Certificates:[{CertificateArn:u}],SslPolicy:"ELBSecurityPolicy-TLS13-1-2-2021-06",DefaultActions:m?[{Type:"fixed-response",FixedResponseConfig:{StatusCode:"403",ContentType:"text/plain",MessageBody:"Forbidden"}}]:[{Type:"forward",TargetGroupArn:d.ref(`${r}TargetGroup`)}]},{dependsOn:[`${r}LoadBalancer`,`${r}TargetGroup`]});if(m){let p=u?`${r}HttpsListener`:`${r}HttpListener`;e.addResource(`${r}OriginVerifyRule`,"AWS::ElasticLoadBalancingV2::ListenerRule",{ListenerArn:d.ref(p),Priority:1,Conditions:[{Field:"http-header",HttpHeaderConfig:{HttpHeaderName:m.name,Values:[m.value]}}],Actions:[{Type:"forward",TargetGroupArn:d.ref(`${r}TargetGroup`)}]},{dependsOn:[p,`${r}TargetGroup`]})}if(e.addResource(`${r}Service`,"AWS::ECS::Service",{ServiceName:d.sub(`\${AWS::StackName}-${t}`),Cluster:d.ref("ECSCluster"),TaskDefinition:d.ref(`${r}TaskDefinition`),DesiredCount:a.service.desiredCount,LaunchType:"FARGATE",PlatformVersion:"LATEST",HealthCheckGracePeriodSeconds:60,DeploymentConfiguration:{MinimumHealthyPercent:100,MaximumPercent:200,DeploymentCircuitBreaker:{Enable:!0,Rollback:!0}},LoadBalancers:[{ContainerName:i,ContainerPort:s,TargetGroupArn:d.ref(`${r}TargetGroup`)}],NetworkConfiguration:{AwsvpcConfiguration:{AssignPublicIp:"DISABLED",Subnets:[d.ref("PrivateSubnet1"),d.ref("PrivateSubnet2")],SecurityGroups:[d.ref("AppSecurityGroup")]}}},{dependsOn:["ECSCluster",`${r}TaskDefinition`,m?`${r}OriginVerifyRule`:u?`${r}HttpsListener`:`${r}HttpListener`]}),a.service.autoScaling){let p=a.service.autoScaling;e.addResource(`${r}ScalableTarget`,"AWS::ApplicationAutoScaling::ScalableTarget",{MinCapacity:p.min,MaxCapacity:p.max,ResourceId:d.join("/",["service",d.ref("ECSCluster"),d.getAtt(`${r}Service`,"Name")]),RoleARN:d.sub("arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService"),ScalableDimension:"ecs:service:DesiredCount",ServiceNamespace:"ecs"},{dependsOn:`${r}Service`}),e.addResource(`${r}ScalingPolicy`,"AWS::ApplicationAutoScaling::ScalingPolicy",{PolicyType:"TargetTrackingScaling",ScalingTargetId:d.ref(`${r}ScalableTarget`),TargetTrackingScalingPolicyConfiguration:{TargetValue:p.targetCPU||70,PredefinedMetricSpecification:{PredefinedMetricType:"ECSServiceAverageCPUUtilization"},ScaleInCooldown:60,ScaleOutCooldown:30}},{dependsOn:`${r}ScalableTarget`})}e.addOutputs({[`${r}ClusterName`]:{Description:"ECS cluster name",Value:d.ref("ECSCluster")},[`${r}ServiceName`]:{Description:"ECS service name",Value:d.getAtt(`${r}Service`,"Name")},[`${r}LoadBalancerDnsName`]:{Description:"ALB origin hostname",Value:d.getAtt(`${r}LoadBalancer`,"DNSName")},[`${r}LoadBalancerHostedZoneId`]:{Description:"ALB canonical hosted zone ID",Value:d.getAtt(`${r}LoadBalancer`,"CanonicalHostedZoneID")},[`${r}TargetGroupArn`]:{Description:"ECS target group ARN",Value:d.ref(`${r}TargetGroup`)}})}function is(e,t){if(t.postgres)ba(e,"postgres",t.postgres);if(t.mysql)ba(e,"mysql",t.mysql);if(t.dynamodb?.tables)t.dynamodb.tables.forEach((a)=>{ss(e,a)})}function ba(e,t,a){if(!a)return;let r=t==="postgres"?"postgres":"mysql",n=e.toLogicalId(`${r}-db`);e.addResource("DBSubnetGroup","AWS::RDS::DBSubnetGroup",{DBSubnetGroupDescription:"Subnet group for RDS instance",SubnetIds:[d.ref("PrivateSubnet1"),d.ref("PrivateSubnet2")],Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-db-subnet-group")}]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]}),e.addResource("DBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for RDS instance",VpcId:d.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:t==="postgres"?5432:3306,ToPort:t==="postgres"?5432:3306,SourceSecurityGroupId:d.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-db-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});let i=t==="postgres"?`postgres${a.version.split(".")[0]}`:`mysql${a.version.split(".")[0]}.${a.version.split(".")[1]||"0"}`;if(a.parameters&&Object.keys(a.parameters).length>0)e.addResource("DBParameterGroup","AWS::RDS::DBParameterGroup",{Description:`Parameter group for ${r}`,Family:i,Parameters:a.parameters,Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-db-params")}]});e.addResource("DBSecret","AWS::SecretsManager::Secret",{Description:"Database credentials",GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"admin"}),GenerateStringKey:"password",PasswordLength:32,ExcludeCharacters:'"@/\\'},Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-db-secret")}]},{deletionPolicy:"Retain",updateReplacePolicy:"Retain"});let s={Engine:r,EngineVersion:a.version,DBInstanceClass:a.instanceClass,AllocatedStorage:a.allocatedStorage.toString(),MaxAllocatedStorage:a.maxAllocatedStorage?.toString(),StorageType:"gp3",StorageEncrypted:!0,MultiAZ:a.multiAZ!==!1,DBSubnetGroupName:d.ref("DBSubnetGroup"),VPCSecurityGroups:[d.ref("DBSecurityGroup")],MasterUsername:d.sub("{{resolve:secretsmanager:${DBSecret}:SecretString:username}}"),MasterUserPassword:d.sub("{{resolve:secretsmanager:${DBSecret}:SecretString:password}}"),BackupRetentionPeriod:a.backupRetentionDays||7,PreferredBackupWindow:a.preferredBackupWindow||"03:00-04:00",PreferredMaintenanceWindow:a.preferredMaintenanceWindow||"sun:04:00-sun:05:00",EnablePerformanceInsights:a.enablePerformanceInsights!==!1,PerformanceInsightsRetentionPeriod:a.performanceInsightsRetention||7,DeletionProtection:a.deletionProtection!==!1,CopyTagsToSnapshot:!0,EnableCloudwatchLogsExports:t==="postgres"?["postgresql"]:["error","general","slowquery"],Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-${r}-db`)}]};if(a.parameters&&Object.keys(a.parameters).length>0)s.DBParameterGroupName=d.ref("DBParameterGroup");e.addResource(n,"AWS::RDS::DBInstance",s,{dependsOn:["DBSubnetGroup","DBSecurityGroup","DBSecret"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),e.addResource("DBSecretAttachment","AWS::SecretsManager::SecretTargetAttachment",{SecretId:d.ref("DBSecret"),TargetId:d.ref(n),TargetType:"AWS::RDS::DBInstance"},{dependsOn:[n,"DBSecret"]}),e.addOutputs({DBEndpoint:{Description:"Database endpoint",Value:d.getAtt(n,"Endpoint.Address"),Export:{Name:d.sub("${AWS::StackName}-db-endpoint")}},DBPort:{Description:"Database port",Value:d.getAtt(n,"Endpoint.Port"),Export:{Name:d.sub("${AWS::StackName}-db-port")}},DBSecretArn:{Description:"ARN of the database credentials secret",Value:d.ref("DBSecret"),Export:{Name:d.sub("${AWS::StackName}-db-secret-arn")}}})}function ss(e,t){let a=e.toLogicalId(`${t.name}-table`),r={TableName:d.sub(`\${AWS::StackName}-${t.name}`),BillingMode:t.billingMode||"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:t.partitionKey,AttributeType:"S"}],KeySchema:[{AttributeName:t.partitionKey,KeyType:"HASH"}],Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-${t.name}`)}]};if(t.sortKey)r.AttributeDefinitions.push({AttributeName:t.sortKey,AttributeType:"S"}),r.KeySchema.push({AttributeName:t.sortKey,KeyType:"RANGE"});if(t.billingMode==="PROVISIONED")r.ProvisionedThroughput={ReadCapacityUnits:t.readCapacity||5,WriteCapacityUnits:t.writeCapacity||5};if(t.streamEnabled)r.StreamSpecification={StreamViewType:"NEW_AND_OLD_IMAGES"};if(t.pointInTimeRecovery)r.PointInTimeRecoverySpecification={PointInTimeRecoveryEnabled:!0};if(t.ttl?.enabled)r.TimeToLiveSpecification={Enabled:!0,AttributeName:t.ttl.attributeName};if(t.globalSecondaryIndexes&&t.globalSecondaryIndexes.length>0)r.GlobalSecondaryIndexes=t.globalSecondaryIndexes.map((n)=>{let i=new Set(r.AttributeDefinitions.map((o)=>o.AttributeName));if(!i.has(n.partitionKey))r.AttributeDefinitions.push({AttributeName:n.partitionKey,AttributeType:"S"});if(n.sortKey&&!i.has(n.sortKey))r.AttributeDefinitions.push({AttributeName:n.sortKey,AttributeType:"S"});let s={IndexName:n.name,KeySchema:[{AttributeName:n.partitionKey,KeyType:"HASH"}],Projection:{ProjectionType:n.projectionType||"ALL"}};if(n.sortKey)s.KeySchema.push({AttributeName:n.sortKey,KeyType:"RANGE"});if(n.projectionType==="INCLUDE"&&n.nonKeyAttributes)s.Projection.NonKeyAttributes=n.nonKeyAttributes;if(t.billingMode==="PROVISIONED")s.ProvisionedThroughput={ReadCapacityUnits:t.readCapacity||5,WriteCapacityUnits:t.writeCapacity||5};return s});if(e.addResource(a,"AWS::DynamoDB::Table",r,{deletionPolicy:"Retain"}),e.addOutputs({[`${a}Name`]:{Description:`${t.name} table name`,Value:d.ref(a),Export:{Name:d.sub(`\${AWS::StackName}-${t.name}-table`)}},[`${a}Arn`]:{Description:`${t.name} table ARN`,Value:d.getAtt(a,"Arn"),Export:{Name:d.sub(`\${AWS::StackName}-${t.name}-table-arn`)}}}),t.streamEnabled)e.addOutputs({[`${a}StreamArn`]:{Description:`${t.name} stream ARN`,Value:d.getAtt(a,"StreamArn"),Export:{Name:d.sub(`\${AWS::StackName}-${t.name}-stream-arn`)}}})}function os(e,t){for(let[a,r]of Object.entries(t))r.forEach((n)=>{cs(e,n,a)})}function cs(e,t,a){let r=e.toLogicalId(`${a}-${t.name}-function`),n=`${r}Role`;e.addResource(n,"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:[...us(t.events||[])]}}],Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-${t.name}-role`)}]});let i={FunctionName:d.sub(`\${AWS::StackName}-${t.name}`),Runtime:t.runtime,Handler:t.handler,Role:d.getAtt(n,"Arn"),MemorySize:t.memory,Timeout:t.timeout,Code:{ZipFile:`exports.handler = async (event) => {
2483
+ `;if(e.addResource("LaunchTemplate","AWS::EC2::LaunchTemplate",{LaunchTemplateName:d.sub("${AWS::StackName}-template"),LaunchTemplateData:{ImageId:t.ami||d.findInMap("RegionMap",d.ref("AWS::Region"),"AMI"),InstanceType:t.instanceType,IamInstanceProfile:{Arn:d.getAtt("EC2InstanceProfile","Arn")},SecurityGroupIds:[d.ref("AppSecurityGroup")],UserData:d.base64(d.sub(a)),TagSpecifications:[{ResourceType:"instance",Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-instance")}]}],MetadataOptions:{HttpTokens:"required",HttpPutResponseHopLimit:1}}},{dependsOn:["AppSecurityGroup","EC2InstanceProfile"]}),t.loadBalancer){rs(e,t.loadBalancer);let r={LaunchTemplate:{LaunchTemplateId:d.ref("LaunchTemplate"),Version:d.getAtt("LaunchTemplate","LatestVersionNumber")},MinSize:t.autoScaling?.min.toString()||"1",MaxSize:t.autoScaling?.max.toString()||"3",DesiredCapacity:t.autoScaling?.min.toString()||"2",VPCZoneIdentifier:[d.ref("PrivateSubnet1"),d.ref("PrivateSubnet2")],TargetGroupARNs:[d.ref("TargetGroup")],HealthCheckType:"ELB",HealthCheckGracePeriod:300,Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-asg"),PropagateAtLaunch:!0}]};if(e.addResource("AutoScalingGroup","AWS::AutoScaling::AutoScalingGroup",r,{dependsOn:["LaunchTemplate","TargetGroup"]}),t.autoScaling)e.addResource("ScaleUpPolicy","AWS::AutoScaling::ScalingPolicy",{AdjustmentType:"ChangeInCapacity",AutoScalingGroupName:d.ref("AutoScalingGroup"),Cooldown:t.autoScaling.scaleUpCooldown?.toString()||"300",ScalingAdjustment:"1"},{dependsOn:"AutoScalingGroup"}),e.addResource("ScaleDownPolicy","AWS::AutoScaling::ScalingPolicy",{AdjustmentType:"ChangeInCapacity",AutoScalingGroupName:d.ref("AutoScalingGroup"),Cooldown:t.autoScaling.scaleDownCooldown?.toString()||"300",ScalingAdjustment:"-1"},{dependsOn:"AutoScalingGroup"}),e.addResource("HighCPUAlarm","AWS::CloudWatch::Alarm",{AlarmDescription:"Scale up when CPU exceeds target",MetricName:"CPUUtilization",Namespace:"AWS/EC2",Statistic:"Average",Period:"300",EvaluationPeriods:"2",Threshold:(t.autoScaling.targetCPU||70).toString(),AlarmActions:[d.ref("ScaleUpPolicy")],Dimensions:[{Name:"AutoScalingGroupName",Value:d.ref("AutoScalingGroup")}],ComparisonOperator:"GreaterThanThreshold"},{dependsOn:["AutoScalingGroup","ScaleUpPolicy"]}),e.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:((t.autoScaling.targetCPU||70)-20).toString(),AlarmActions:[d.ref("ScaleDownPolicy")],Dimensions:[{Name:"AutoScalingGroupName",Value:d.ref("AutoScalingGroup")}],ComparisonOperator:"LessThanThreshold"},{dependsOn:["AutoScalingGroup","ScaleDownPolicy"]})}}function rs(e,t){if(!t)return;e.addResource("ALBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for Application Load Balancer",VpcId:d.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:d.sub("${AWS::StackName}-alb-sg")}]},{dependsOn:"VPC"}),e.addResource("LoadBalancer","AWS::ElasticLoadBalancingV2::LoadBalancer",{Name:d.sub("${AWS::StackName}-alb"),Type:t.type||"application",Scheme:"internet-facing",IpAddressType:"ipv4",Subnets:[d.ref("PublicSubnet1"),d.ref("PublicSubnet2")],SecurityGroups:[d.ref("ALBSecurityGroup")],Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-alb")}]},{dependsOn:["PublicSubnet1","PublicSubnet2","ALBSecurityGroup"]}),e.addResource("TargetGroup","AWS::ElasticLoadBalancingV2::TargetGroup",{Name:d.sub("${AWS::StackName}-tg"),Port:3000,Protocol:"HTTP",VpcId:d.ref("VPC"),HealthCheckEnabled:!0,HealthCheckPath:t.healthCheck?.path||"/health",HealthCheckProtocol:"HTTP",HealthCheckIntervalSeconds:t.healthCheck?.interval||30,HealthCheckTimeoutSeconds:t.healthCheck?.timeout||5,HealthyThresholdCount:t.healthCheck?.healthyThreshold||2,UnhealthyThresholdCount:t.healthCheck?.unhealthyThreshold||3,TargetType:"instance",Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-tg")}]},{dependsOn:"VPC"}),e.addResource("LoadBalancerListener","AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:d.ref("LoadBalancer"),Port:80,Protocol:"HTTP",DefaultActions:[{Type:"forward",TargetGroupArn:d.ref("TargetGroup")}]},{dependsOn:["LoadBalancer","TargetGroup"]}),e.addOutputs({LoadBalancerDNS:{Description:"Load Balancer DNS Name",Value:d.getAtt("LoadBalancer","DNSName"),Export:{Name:d.sub("${AWS::StackName}-alb-dns")}}})}function fa(e,t,a){let r=e.toLogicalId(t),n=a.taskDefinition.containerDefinitions?.[0],i=n?.name||n?.Name||t,s=n?.portMappings?.[0]?.containerPort||n?.PortMappings?.[0]?.ContainerPort||3000,o=(a.taskDefinition.containerDefinitions||[]).flatMap((p)=>(p.secrets||p.Secrets||[]).map((g)=>g.valueFrom||g.ValueFrom)).filter(Boolean);if(!e.hasResource("ECSCluster"))e.addResource("ECSCluster","AWS::ECS::Cluster",{ClusterName:d.sub("${AWS::StackName}-cluster"),Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-cluster")}]});if(e.addResource(`${r}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"],...o.length?{Policies:[{PolicyName:"read-task-secrets",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameters"],Resource:o},{Effect:"Allow",Action:"kms:Decrypt",Resource:"*"}]}}]}:{}}),e.addResource(`${r}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:d.sub("arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:${AWS::StackName}-*")},{Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail"],Resource:"*"}]}}]}),!e.hasResource("ALBSecurityGroup"))e.addResource("ALBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Public ingress for the application load balancer",VpcId:d.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:80,ToPort:80,CidrIp:"0.0.0.0/0"},...a.loadBalancer?.customDomain?.certificateArn?[{IpProtocol:"tcp",FromPort:443,ToPort:443,CidrIp:"0.0.0.0/0"}]:[]],SecurityGroupEgress:[{IpProtocol:"tcp",FromPort:s,ToPort:s,CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-alb-sg")}]},{dependsOn:"VPC"});if(!e.hasResource("AppSecurityGroup"))e.addResource("AppSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Only the application load balancer may reach Fargate tasks",VpcId:d.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:s,ToPort:s,SourceSecurityGroupId:d.ref("ALBSecurityGroup")}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-app-sg")}]},{dependsOn:["VPC","ALBSecurityGroup"]});let c=(a.taskDefinition.containerDefinitions||[{name:t,image:d.sub(`\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.amazonaws.com/${t}:latest`),portMappings:[{containerPort:3000}]}]).map((p)=>({Name:p.Name||p.name,Image:p.Image||p.image,Essential:p.Essential??p.essential??!0,PortMappings:(p.PortMappings||p.portMappings||[]).map((g)=>({ContainerPort:g.ContainerPort??g.containerPort,Protocol:g.Protocol||g.protocol||"tcp"})),Environment:Array.isArray(p.Environment||p.environment)?(p.Environment||p.environment).map((g)=>({Name:g.Name||g.name,Value:g.Value??g.value})):Object.entries(p.Environment||p.environment||{}).map(([g,h])=>({Name:g,Value:h})),Secrets:(p.Secrets||p.secrets||[]).map((g)=>({Name:g.Name||g.name,ValueFrom:g.ValueFrom||g.valueFrom})),HealthCheck:p.HealthCheck||p.healthCheck,Command:p.Command||p.command,EntryPoint:p.EntryPoint||p.entryPoint,LogConfiguration:p.LogConfiguration||p.logConfiguration||{LogDriver:"awslogs",Options:{"awslogs-group":d.ref(`${r}LogGroup`),"awslogs-region":d.ref("AWS::Region"),"awslogs-stream-prefix":t}}}));e.addResource(`${r}TaskDefinition`,"AWS::ECS::TaskDefinition",{Family:d.sub(`\${AWS::StackName}-${t}`),NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:a.taskDefinition.cpu,Memory:a.taskDefinition.memory,ExecutionRoleArn:d.getAtt(`${r}TaskExecutionRole`,"Arn"),TaskRoleArn:d.getAtt(`${r}TaskRole`,"Arn"),ContainerDefinitions:c},{dependsOn:[`${r}TaskExecutionRole`,`${r}TaskRole`,`${r}LogGroup`]}),e.addResource(`${r}LogGroup`,"AWS::Logs::LogGroup",{LogGroupName:d.sub(`/ecs/\${AWS::StackName}/${t}`),RetentionInDays:14});let l=a.service.healthCheck||{};e.addResource(`${r}TargetGroup`,"AWS::ElasticLoadBalancingV2::TargetGroup",{VpcId:d.ref("VPC"),Port:s,Protocol:"HTTP",TargetType:"ip",HealthCheckEnabled:!0,HealthCheckPath:l.path||"/health",HealthCheckProtocol:"HTTP",HealthCheckIntervalSeconds:l.interval||30,HealthCheckTimeoutSeconds:l.timeout||5,HealthyThresholdCount:l.healthyThreshold||2,UnhealthyThresholdCount:l.unhealthyThreshold||3,Matcher:{HttpCode:"200-399"},TargetGroupAttributes:[{Key:"deregistration_delay.timeout_seconds",Value:"30"}]},{dependsOn:"VPC"}),e.addResource(`${r}LoadBalancer`,"AWS::ElasticLoadBalancingV2::LoadBalancer",{Type:"application",Scheme:"internet-facing",IpAddressType:"ipv4",Subnets:[d.ref("PublicSubnet1"),d.ref("PublicSubnet2")],SecurityGroups:[d.ref("ALBSecurityGroup")],LoadBalancerAttributes:[{Key:"routing.http.drop_invalid_header_fields.enabled",Value:"true"},{Key:"deletion_protection.enabled",Value:String(a.loadBalancer?.deletionProtection===!0)}],Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-${t}-alb`)}]},{dependsOn:["PublicSubnet1","PublicSubnet2","ALBSecurityGroup"]});let u=a.loadBalancer?.customDomain?.certificateArn,m=a.loadBalancer?.originVerifyHeader;if(e.addResource(`${r}HttpListener`,"AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:d.ref(`${r}LoadBalancer`),Port:80,Protocol:"HTTP",DefaultActions:u?[{Type:"redirect",RedirectConfig:{Protocol:"HTTPS",Port:"443",StatusCode:"HTTP_301"}}]:m?[{Type:"fixed-response",FixedResponseConfig:{StatusCode:"403",ContentType:"text/plain",MessageBody:"Forbidden"}}]:[{Type:"forward",TargetGroupArn:d.ref(`${r}TargetGroup`)}]},{dependsOn:[`${r}LoadBalancer`,`${r}TargetGroup`]}),u)e.addResource(`${r}HttpsListener`,"AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:d.ref(`${r}LoadBalancer`),Port:443,Protocol:"HTTPS",Certificates:[{CertificateArn:u}],SslPolicy:"ELBSecurityPolicy-TLS13-1-2-2021-06",DefaultActions:m?[{Type:"fixed-response",FixedResponseConfig:{StatusCode:"403",ContentType:"text/plain",MessageBody:"Forbidden"}}]:[{Type:"forward",TargetGroupArn:d.ref(`${r}TargetGroup`)}]},{dependsOn:[`${r}LoadBalancer`,`${r}TargetGroup`]});if(m){let p=u?`${r}HttpsListener`:`${r}HttpListener`;e.addResource(`${r}OriginVerifyRule`,"AWS::ElasticLoadBalancingV2::ListenerRule",{ListenerArn:d.ref(p),Priority:1,Conditions:[{Field:"http-header",HttpHeaderConfig:{HttpHeaderName:m.name,Values:[m.value]}}],Actions:[{Type:"forward",TargetGroupArn:d.ref(`${r}TargetGroup`)}]},{dependsOn:[p,`${r}TargetGroup`]})}if(e.addResource(`${r}Service`,"AWS::ECS::Service",{ServiceName:d.sub(`\${AWS::StackName}-${t}`),Cluster:d.ref("ECSCluster"),TaskDefinition:d.ref(`${r}TaskDefinition`),DesiredCount:a.service.desiredCount,LaunchType:"FARGATE",PlatformVersion:"LATEST",HealthCheckGracePeriodSeconds:60,DeploymentConfiguration:{MinimumHealthyPercent:100,MaximumPercent:200,DeploymentCircuitBreaker:{Enable:!0,Rollback:!0}},LoadBalancers:[{ContainerName:i,ContainerPort:s,TargetGroupArn:d.ref(`${r}TargetGroup`)}],NetworkConfiguration:{AwsvpcConfiguration:{AssignPublicIp:"DISABLED",Subnets:[d.ref("PrivateSubnet1"),d.ref("PrivateSubnet2")],SecurityGroups:[d.ref("AppSecurityGroup")]}}},{dependsOn:["ECSCluster",`${r}TaskDefinition`,m?`${r}OriginVerifyRule`:u?`${r}HttpsListener`:`${r}HttpListener`]}),a.service.autoScaling){let p=a.service.autoScaling;e.addResource(`${r}ScalableTarget`,"AWS::ApplicationAutoScaling::ScalableTarget",{MinCapacity:p.min,MaxCapacity:p.max,ResourceId:d.join("/",["service",d.ref("ECSCluster"),d.getAtt(`${r}Service`,"Name")]),RoleARN:d.sub("arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService"),ScalableDimension:"ecs:service:DesiredCount",ServiceNamespace:"ecs"},{dependsOn:`${r}Service`}),e.addResource(`${r}ScalingPolicy`,"AWS::ApplicationAutoScaling::ScalingPolicy",{PolicyType:"TargetTrackingScaling",ScalingTargetId:d.ref(`${r}ScalableTarget`),TargetTrackingScalingPolicyConfiguration:{TargetValue:p.targetCPU||70,PredefinedMetricSpecification:{PredefinedMetricType:"ECSServiceAverageCPUUtilization"},ScaleInCooldown:60,ScaleOutCooldown:30}},{dependsOn:`${r}ScalableTarget`})}e.addOutputs({[`${r}ClusterName`]:{Description:"ECS cluster name",Value:d.ref("ECSCluster")},[`${r}ServiceName`]:{Description:"ECS service name",Value:d.getAtt(`${r}Service`,"Name")},[`${r}LoadBalancerDnsName`]:{Description:"ALB origin hostname",Value:d.getAtt(`${r}LoadBalancer`,"DNSName")},[`${r}LoadBalancerHostedZoneId`]:{Description:"ALB canonical hosted zone ID",Value:d.getAtt(`${r}LoadBalancer`,"CanonicalHostedZoneID")},[`${r}TargetGroupArn`]:{Description:"ECS target group ARN",Value:d.ref(`${r}TargetGroup`)}})}function ns(e,t){if(t.postgres)Sa(e,"postgres",t.postgres);if(t.mysql)Sa(e,"mysql",t.mysql);if(t.dynamodb?.tables)t.dynamodb.tables.forEach((a)=>{is(e,a)})}function Sa(e,t,a){if(!a)return;let r=t==="postgres"?"postgres":"mysql",n=e.toLogicalId(`${r}-db`);e.addResource("DBSubnetGroup","AWS::RDS::DBSubnetGroup",{DBSubnetGroupDescription:"Subnet group for RDS instance",SubnetIds:[d.ref("PrivateSubnet1"),d.ref("PrivateSubnet2")],Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-db-subnet-group")}]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]}),e.addResource("DBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for RDS instance",VpcId:d.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:t==="postgres"?5432:3306,ToPort:t==="postgres"?5432:3306,SourceSecurityGroupId:d.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-db-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});let i=t==="postgres"?`postgres${a.version.split(".")[0]}`:`mysql${a.version.split(".")[0]}.${a.version.split(".")[1]||"0"}`;if(a.parameters&&Object.keys(a.parameters).length>0)e.addResource("DBParameterGroup","AWS::RDS::DBParameterGroup",{Description:`Parameter group for ${r}`,Family:i,Parameters:a.parameters,Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-db-params")}]});e.addResource("DBSecret","AWS::SecretsManager::Secret",{Description:"Database credentials",GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"admin"}),GenerateStringKey:"password",PasswordLength:32,ExcludeCharacters:'"@/\\'},Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-db-secret")}]},{deletionPolicy:"Retain",updateReplacePolicy:"Retain"});let s={Engine:r,EngineVersion:a.version,DBInstanceClass:a.instanceClass,AllocatedStorage:a.allocatedStorage.toString(),MaxAllocatedStorage:a.maxAllocatedStorage?.toString(),StorageType:"gp3",StorageEncrypted:!0,MultiAZ:a.multiAZ!==!1,DBSubnetGroupName:d.ref("DBSubnetGroup"),VPCSecurityGroups:[d.ref("DBSecurityGroup")],MasterUsername:d.sub("{{resolve:secretsmanager:${DBSecret}:SecretString:username}}"),MasterUserPassword:d.sub("{{resolve:secretsmanager:${DBSecret}:SecretString:password}}"),BackupRetentionPeriod:a.backupRetentionDays||7,PreferredBackupWindow:a.preferredBackupWindow||"03:00-04:00",PreferredMaintenanceWindow:a.preferredMaintenanceWindow||"sun:04:00-sun:05:00",EnablePerformanceInsights:a.enablePerformanceInsights!==!1,PerformanceInsightsRetentionPeriod:a.performanceInsightsRetention||7,DeletionProtection:a.deletionProtection!==!1,CopyTagsToSnapshot:!0,EnableCloudwatchLogsExports:t==="postgres"?["postgresql"]:["error","general","slowquery"],Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-${r}-db`)}]};if(a.parameters&&Object.keys(a.parameters).length>0)s.DBParameterGroupName=d.ref("DBParameterGroup");e.addResource(n,"AWS::RDS::DBInstance",s,{dependsOn:["DBSubnetGroup","DBSecurityGroup","DBSecret"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),e.addResource("DBSecretAttachment","AWS::SecretsManager::SecretTargetAttachment",{SecretId:d.ref("DBSecret"),TargetId:d.ref(n),TargetType:"AWS::RDS::DBInstance"},{dependsOn:[n,"DBSecret"]}),e.addOutputs({DBEndpoint:{Description:"Database endpoint",Value:d.getAtt(n,"Endpoint.Address"),Export:{Name:d.sub("${AWS::StackName}-db-endpoint")}},DBPort:{Description:"Database port",Value:d.getAtt(n,"Endpoint.Port"),Export:{Name:d.sub("${AWS::StackName}-db-port")}},DBSecretArn:{Description:"ARN of the database credentials secret",Value:d.ref("DBSecret"),Export:{Name:d.sub("${AWS::StackName}-db-secret-arn")}}})}function is(e,t){let a=e.toLogicalId(`${t.name}-table`),r={TableName:d.sub(`\${AWS::StackName}-${t.name}`),BillingMode:t.billingMode||"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:t.partitionKey,AttributeType:"S"}],KeySchema:[{AttributeName:t.partitionKey,KeyType:"HASH"}],Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-${t.name}`)}]};if(t.sortKey)r.AttributeDefinitions.push({AttributeName:t.sortKey,AttributeType:"S"}),r.KeySchema.push({AttributeName:t.sortKey,KeyType:"RANGE"});if(t.billingMode==="PROVISIONED")r.ProvisionedThroughput={ReadCapacityUnits:t.readCapacity||5,WriteCapacityUnits:t.writeCapacity||5};if(t.streamEnabled)r.StreamSpecification={StreamViewType:"NEW_AND_OLD_IMAGES"};if(t.pointInTimeRecovery)r.PointInTimeRecoverySpecification={PointInTimeRecoveryEnabled:!0};if(t.ttl?.enabled)r.TimeToLiveSpecification={Enabled:!0,AttributeName:t.ttl.attributeName};if(t.globalSecondaryIndexes&&t.globalSecondaryIndexes.length>0)r.GlobalSecondaryIndexes=t.globalSecondaryIndexes.map((n)=>{let i=new Set(r.AttributeDefinitions.map((o)=>o.AttributeName));if(!i.has(n.partitionKey))r.AttributeDefinitions.push({AttributeName:n.partitionKey,AttributeType:"S"});if(n.sortKey&&!i.has(n.sortKey))r.AttributeDefinitions.push({AttributeName:n.sortKey,AttributeType:"S"});let s={IndexName:n.name,KeySchema:[{AttributeName:n.partitionKey,KeyType:"HASH"}],Projection:{ProjectionType:n.projectionType||"ALL"}};if(n.sortKey)s.KeySchema.push({AttributeName:n.sortKey,KeyType:"RANGE"});if(n.projectionType==="INCLUDE"&&n.nonKeyAttributes)s.Projection.NonKeyAttributes=n.nonKeyAttributes;if(t.billingMode==="PROVISIONED")s.ProvisionedThroughput={ReadCapacityUnits:t.readCapacity||5,WriteCapacityUnits:t.writeCapacity||5};return s});if(e.addResource(a,"AWS::DynamoDB::Table",r,{deletionPolicy:"Retain"}),e.addOutputs({[`${a}Name`]:{Description:`${t.name} table name`,Value:d.ref(a),Export:{Name:d.sub(`\${AWS::StackName}-${t.name}-table`)}},[`${a}Arn`]:{Description:`${t.name} table ARN`,Value:d.getAtt(a,"Arn"),Export:{Name:d.sub(`\${AWS::StackName}-${t.name}-table-arn`)}}}),t.streamEnabled)e.addOutputs({[`${a}StreamArn`]:{Description:`${t.name} stream ARN`,Value:d.getAtt(a,"StreamArn"),Export:{Name:d.sub(`\${AWS::StackName}-${t.name}-stream-arn`)}}})}function ss(e,t){for(let[a,r]of Object.entries(t))r.forEach((n)=>{os(e,n,a)})}function os(e,t,a){let r=e.toLogicalId(`${a}-${t.name}-function`),n=`${r}Role`;e.addResource(n,"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:[...ls(t.events||[])]}}],Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-${t.name}-role`)}]});let i={FunctionName:d.sub(`\${AWS::StackName}-${t.name}`),Runtime:t.runtime,Handler:t.handler,Role:d.getAtt(n,"Arn"),MemorySize:t.memory,Timeout:t.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:t.environment?{Variables:t.environment}:void 0,Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-${t.name}`)}]};if(a!=="edge")i.VpcConfig={SubnetIds:[d.ref("PrivateSubnet1"),d.ref("PrivateSubnet2")],SecurityGroupIds:[d.ref("AppSecurityGroup")]};if(e.addResource(r,"AWS::Lambda::Function",i,{dependsOn:n}),e.addResource(`${r}LogGroup`,"AWS::Logs::LogGroup",{LogGroupName:d.sub(`/aws/lambda/\${AWS::StackName}-${t.name}`),RetentionInDays:14}),t.events)t.events.forEach((s,o)=>{ls(e,r,s,o)});e.addOutputs({[`${r}Arn`]:{Description:`${t.name} function ARN`,Value:d.getAtt(r,"Arn"),Export:{Name:d.sub(`\${AWS::StackName}-${t.name}-function-arn`)}}})}function ls(e,t,a,r){let n=`${t}EventSource${r}`;switch(a.type){case"http":break;case"s3":if(a.bucket){let i=e.toLogicalId(`${a.bucket}-bucket`);e.addResource(`${n}Permission`,"AWS::Lambda::Permission",{FunctionName:d.ref(t),Action:"lambda:InvokeFunction",Principal:"s3.amazonaws.com",SourceArn:Ct.s3Bucket(d.ref(i))},{dependsOn:[t,i]})}break;case"sqs":if(a.queueName){let i=e.toLogicalId(`${a.queueName}-queue`);e.addResource(n,"AWS::Lambda::EventSourceMapping",{EventSourceArn:d.getAtt(i,"Arn"),FunctionName:d.ref(t),BatchSize:a.batchSize||10},{dependsOn:[t,i]})}break;case"kinesis":if(a.streamName){let i=e.toLogicalId(`${a.streamName}-stream`);e.addResource(n,"AWS::Lambda::EventSourceMapping",{EventSourceArn:d.getAtt(i,"Arn"),FunctionName:d.ref(t),BatchSize:a.batchSize||100,StartingPosition:a.startingPosition||"LATEST",ParallelizationFactor:a.parallelizationFactor||1},{dependsOn:[t,i]})}break;case"dynamodb-stream":if(a.tableName){let i=e.toLogicalId(`${a.tableName}-table`);e.addResource(n,"AWS::Lambda::EventSourceMapping",{EventSourceArn:d.getAtt(i,"StreamArn"),FunctionName:d.ref(t),BatchSize:a.batchSize||100,StartingPosition:a.startingPosition||"LATEST"},{dependsOn:[t,i]})}break;case"schedule":if(a.expression)e.addResource(`${n}Rule`,"AWS::Events::Rule",{ScheduleExpression:a.expression,State:"ENABLED",Targets:[{Arn:d.getAtt(t,"Arn"),Id:`${t}Target`}]},{dependsOn:t}),e.addResource(`${n}Permission`,"AWS::Lambda::Permission",{FunctionName:d.ref(t),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:d.getAtt(`${n}Rule`,"Arn")},{dependsOn:[t,`${n}Rule`]});break}}function us(e){let t=[];if(!e)return t;if(e.forEach((a)=>{switch(a.type){case"s3":t.push({Effect:"Allow",Action:["s3:GetObject","s3:GetObjectVersion"],Resource:a.bucket?`arn:aws:s3:::${a.bucket}/*`:"arn:aws:s3:::*/*"});break;case"sqs":t.push({Effect:"Allow",Action:["sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes"],Resource:a.queueName?Ct.sqs(a.queueName):"arn:aws:sqs:*:*:*"});break;case"kinesis":t.push({Effect:"Allow",Action:["kinesis:GetRecords","kinesis:GetShardIterator","kinesis:DescribeStream","kinesis:ListStreams"],Resource:a.streamName?Ct.kinesis(a.streamName):"arn:aws:kinesis:*:*:stream/*"});break;case"dynamodb-stream":t.push({Effect:"Allow",Action:["dynamodb:GetRecords","dynamodb:GetShardIterator","dynamodb:DescribeStream","dynamodb:ListStreams"],Resource:a.tableName?d.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${a.tableName}/stream/*`):"arn:aws:dynamodb:*:*:table/*/stream/*"});break}}),t.length===0)t.push({Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:"arn:aws:logs:*:*:*"});return t}function ds(e,t){if(t.topics)t.topics.forEach((a)=>{ms(e,a)})}function ms(e,t){let a=e.toLogicalId(`${t.name}-topic`);if(e.addResource(a,"AWS::SNS::Topic",{TopicName:d.sub(`\${AWS::StackName}-${t.name}`),DisplayName:t.displayName||t.name,Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-${t.name}`)}]}),e.addResource(`${a}Policy`,"AWS::SNS::TopicPolicy",{Topics:[d.ref(a)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["events.amazonaws.com","cloudwatch.amazonaws.com","s3.amazonaws.com"]},Action:"sns:Publish",Resource:d.ref(a)},{Effect:"Allow",Principal:{AWS:d.sub("arn:aws:iam::${AWS::AccountId}:root")},Action:["sns:Subscribe","sns:Publish","sns:Receive"],Resource:d.ref(a)}]}},{dependsOn:a}),t.subscriptions)t.subscriptions.forEach((r,n)=>{let i=`${a}Subscription${n+1}`,s={Protocol:r.protocol,TopicArn:d.ref(a),Endpoint:r.endpoint};if(r.filterPolicy)s.FilterPolicy=r.filterPolicy;if(r.protocol==="sqs"){let o=e.toLogicalId(`${r.endpoint}-queue`);s.Endpoint=d.getAtt(o,"Arn")}if(r.protocol==="lambda"){let o=e.toLogicalId(r.endpoint);s.Endpoint=d.getAtt(o,"Arn"),e.addResource(`${i}Permission`,"AWS::Lambda::Permission",{FunctionName:d.ref(o),Action:"lambda:InvokeFunction",Principal:"sns.amazonaws.com",SourceArn:d.ref(a)},{dependsOn:[o,a]})}e.addResource(i,"AWS::SNS::Subscription",s,{dependsOn:a})});e.addOutputs({[`${a}Arn`]:{Description:`${t.name} topic ARN`,Value:d.ref(a),Export:{Name:d.sub(`\${AWS::StackName}-${t.name}-topic-arn`)}}})}function ps(e,t){if(t.alarms&&t.alarms.length>0)e.addResource("AlarmTopic","AWS::SNS::Topic",{TopicName:d.sub("${AWS::StackName}-alarms"),DisplayName:"CloudWatch Alarms",Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-alarms")}]}),t.alarms.forEach((a,r)=>{gs(e,a,r)});if(t.dashboard)hs(e,t.dashboard);if(t.logs?.groups)t.logs.groups.forEach((a)=>{ys(e,a,t.logs?.retention)})}function gs(e,t,a){let r=e.toLogicalId(`alarm-${t.name||t.metric}-${a}`),n={AlarmName:t.name||d.sub(`\${AWS::StackName}-${t.metric}`),AlarmDescription:`Alarm for ${t.metric}`,MetricName:t.metric,Namespace:t.namespace||jt(t.metric,t.service),Statistic:t.statistic||"Average",Period:t.period||300,EvaluationPeriods:t.evaluationPeriods||1,Threshold:t.threshold,ComparisonOperator:t.comparisonOperator||"GreaterThanThreshold",TreatMissingData:t.treatMissingData||"notBreaching",AlarmActions:[d.ref("AlarmTopic")],OKActions:[d.ref("AlarmTopic")]};if(t.dimensions)n.Dimensions=Object.entries(t.dimensions).map(([i,s])=>({Name:i,Value:s}));else if(t.service)n.Dimensions=fs(t.service);e.addResource(r,"AWS::CloudWatch::Alarm",n,{dependsOn:"AlarmTopic"})}function hs(e,t){if(!t)return;let a=[],r=0,n=0;t.widgets?.forEach((i)=>{let s=i.width||12,o=i.height||6;if(i.type==="metric"&&i.metrics){let c=i.metrics.map((l)=>{if(typeof l==="string")return[jt(l),l];else return[jt(l.metric,l.service),l.metric]});a.push({type:"metric",x:r,y:n,width:s,height:o,properties:{metrics:c,period:300,stat:"Average",region:d.ref("AWS::Region"),title:i.metrics.length>1?"Multiple Metrics":typeof i.metrics[0]==="string"?i.metrics[0]:i.metrics[0].metric}})}else if(i.type==="log"&&i.logGroup)a.push({type:"log",x:r,y:n,width:s,height:o,properties:{query:`SOURCE '${i.logGroup}'
2486
+ };`},Environment:t.environment?{Variables:t.environment}:void 0,Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-${t.name}`)}]};if(a!=="edge")i.VpcConfig={SubnetIds:[d.ref("PrivateSubnet1"),d.ref("PrivateSubnet2")],SecurityGroupIds:[d.ref("AppSecurityGroup")]};if(e.addResource(r,"AWS::Lambda::Function",i,{dependsOn:n}),e.addResource(`${r}LogGroup`,"AWS::Logs::LogGroup",{LogGroupName:d.sub(`/aws/lambda/\${AWS::StackName}-${t.name}`),RetentionInDays:14}),t.events)t.events.forEach((s,o)=>{cs(e,r,s,o)});e.addOutputs({[`${r}Arn`]:{Description:`${t.name} function ARN`,Value:d.getAtt(r,"Arn"),Export:{Name:d.sub(`\${AWS::StackName}-${t.name}-function-arn`)}}})}function cs(e,t,a,r){let n=`${t}EventSource${r}`;switch(a.type){case"http":break;case"s3":if(a.bucket){let i=e.toLogicalId(`${a.bucket}-bucket`);e.addResource(`${n}Permission`,"AWS::Lambda::Permission",{FunctionName:d.ref(t),Action:"lambda:InvokeFunction",Principal:"s3.amazonaws.com",SourceArn:At.s3Bucket(d.ref(i))},{dependsOn:[t,i]})}break;case"sqs":if(a.queueName){let i=e.toLogicalId(`${a.queueName}-queue`);e.addResource(n,"AWS::Lambda::EventSourceMapping",{EventSourceArn:d.getAtt(i,"Arn"),FunctionName:d.ref(t),BatchSize:a.batchSize||10},{dependsOn:[t,i]})}break;case"kinesis":if(a.streamName){let i=e.toLogicalId(`${a.streamName}-stream`);e.addResource(n,"AWS::Lambda::EventSourceMapping",{EventSourceArn:d.getAtt(i,"Arn"),FunctionName:d.ref(t),BatchSize:a.batchSize||100,StartingPosition:a.startingPosition||"LATEST",ParallelizationFactor:a.parallelizationFactor||1},{dependsOn:[t,i]})}break;case"dynamodb-stream":if(a.tableName){let i=e.toLogicalId(`${a.tableName}-table`);e.addResource(n,"AWS::Lambda::EventSourceMapping",{EventSourceArn:d.getAtt(i,"StreamArn"),FunctionName:d.ref(t),BatchSize:a.batchSize||100,StartingPosition:a.startingPosition||"LATEST"},{dependsOn:[t,i]})}break;case"schedule":if(a.expression)e.addResource(`${n}Rule`,"AWS::Events::Rule",{ScheduleExpression:a.expression,State:"ENABLED",Targets:[{Arn:d.getAtt(t,"Arn"),Id:`${t}Target`}]},{dependsOn:t}),e.addResource(`${n}Permission`,"AWS::Lambda::Permission",{FunctionName:d.ref(t),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:d.getAtt(`${n}Rule`,"Arn")},{dependsOn:[t,`${n}Rule`]});break}}function ls(e){let t=[];if(!e)return t;if(e.forEach((a)=>{switch(a.type){case"s3":t.push({Effect:"Allow",Action:["s3:GetObject","s3:GetObjectVersion"],Resource:a.bucket?`arn:aws:s3:::${a.bucket}/*`:"arn:aws:s3:::*/*"});break;case"sqs":t.push({Effect:"Allow",Action:["sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes"],Resource:a.queueName?At.sqs(a.queueName):"arn:aws:sqs:*:*:*"});break;case"kinesis":t.push({Effect:"Allow",Action:["kinesis:GetRecords","kinesis:GetShardIterator","kinesis:DescribeStream","kinesis:ListStreams"],Resource:a.streamName?At.kinesis(a.streamName):"arn:aws:kinesis:*:*:stream/*"});break;case"dynamodb-stream":t.push({Effect:"Allow",Action:["dynamodb:GetRecords","dynamodb:GetShardIterator","dynamodb:DescribeStream","dynamodb:ListStreams"],Resource:a.tableName?d.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${a.tableName}/stream/*`):"arn:aws:dynamodb:*:*:table/*/stream/*"});break}}),t.length===0)t.push({Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:"arn:aws:logs:*:*:*"});return t}function us(e,t){if(t.topics)t.topics.forEach((a)=>{ds(e,a)})}function ds(e,t){let a=e.toLogicalId(`${t.name}-topic`);if(e.addResource(a,"AWS::SNS::Topic",{TopicName:d.sub(`\${AWS::StackName}-${t.name}`),DisplayName:t.displayName||t.name,Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-${t.name}`)}]}),e.addResource(`${a}Policy`,"AWS::SNS::TopicPolicy",{Topics:[d.ref(a)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["events.amazonaws.com","cloudwatch.amazonaws.com","s3.amazonaws.com"]},Action:"sns:Publish",Resource:d.ref(a)},{Effect:"Allow",Principal:{AWS:d.sub("arn:aws:iam::${AWS::AccountId}:root")},Action:["sns:Subscribe","sns:Publish","sns:Receive"],Resource:d.ref(a)}]}},{dependsOn:a}),t.subscriptions)t.subscriptions.forEach((r,n)=>{let i=`${a}Subscription${n+1}`,s={Protocol:r.protocol,TopicArn:d.ref(a),Endpoint:r.endpoint};if(r.filterPolicy)s.FilterPolicy=r.filterPolicy;if(r.protocol==="sqs"){let o=e.toLogicalId(`${r.endpoint}-queue`);s.Endpoint=d.getAtt(o,"Arn")}if(r.protocol==="lambda"){let o=e.toLogicalId(r.endpoint);s.Endpoint=d.getAtt(o,"Arn"),e.addResource(`${i}Permission`,"AWS::Lambda::Permission",{FunctionName:d.ref(o),Action:"lambda:InvokeFunction",Principal:"sns.amazonaws.com",SourceArn:d.ref(a)},{dependsOn:[o,a]})}e.addResource(i,"AWS::SNS::Subscription",s,{dependsOn:a})});e.addOutputs({[`${a}Arn`]:{Description:`${t.name} topic ARN`,Value:d.ref(a),Export:{Name:d.sub(`\${AWS::StackName}-${t.name}-topic-arn`)}}})}function ms(e,t){if(t.alarms&&t.alarms.length>0)e.addResource("AlarmTopic","AWS::SNS::Topic",{TopicName:d.sub("${AWS::StackName}-alarms"),DisplayName:"CloudWatch Alarms",Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-alarms")}]}),t.alarms.forEach((a,r)=>{ps(e,a,r)});if(t.dashboard)gs(e,t.dashboard);if(t.logs?.groups)t.logs.groups.forEach((a)=>{hs(e,a,t.logs?.retention)})}function ps(e,t,a){let r=e.toLogicalId(`alarm-${t.name||t.metric}-${a}`),n={AlarmName:t.name||d.sub(`\${AWS::StackName}-${t.metric}`),AlarmDescription:`Alarm for ${t.metric}`,MetricName:t.metric,Namespace:t.namespace||jt(t.metric,t.service),Statistic:t.statistic||"Average",Period:t.period||300,EvaluationPeriods:t.evaluationPeriods||1,Threshold:t.threshold,ComparisonOperator:t.comparisonOperator||"GreaterThanThreshold",TreatMissingData:t.treatMissingData||"notBreaching",AlarmActions:[d.ref("AlarmTopic")],OKActions:[d.ref("AlarmTopic")]};if(t.dimensions)n.Dimensions=Object.entries(t.dimensions).map(([i,s])=>({Name:i,Value:s}));else if(t.service)n.Dimensions=ys(t.service);e.addResource(r,"AWS::CloudWatch::Alarm",n,{dependsOn:"AlarmTopic"})}function gs(e,t){if(!t)return;let a=[],r=0,n=0;t.widgets?.forEach((i)=>{let s=i.width||12,o=i.height||6;if(i.type==="metric"&&i.metrics){let c=i.metrics.map((l)=>{if(typeof l==="string")return[jt(l),l];else return[jt(l.metric,l.service),l.metric]});a.push({type:"metric",x:r,y:n,width:s,height:o,properties:{metrics:c,period:300,stat:"Average",region:d.ref("AWS::Region"),title:i.metrics.length>1?"Multiple Metrics":typeof i.metrics[0]==="string"?i.metrics[0]:i.metrics[0].metric}})}else if(i.type==="log"&&i.logGroup)a.push({type:"log",x:r,y:n,width:s,height:o,properties:{query:`SOURCE '${i.logGroup}'
2487
2487
  | fields @timestamp, @message
2488
2488
  | sort @timestamp desc
2489
- | limit 20`,region:d.ref("AWS::Region"),title:`Logs: ${i.logGroup}`}});else if(i.type==="text"&&i.text)a.push({type:"text",x:r,y:n,width:s,height:o,properties:{markdown:i.text}});if(r+=s,r>=24)r=0,n+=o}),e.addResource("CloudWatchDashboard","AWS::CloudWatch::Dashboard",{DashboardName:d.sub(`\${AWS::StackName}-${t.name}`),DashboardBody:JSON.stringify({widgets:a})}),e.addOutputs({DashboardURL:{Description:"CloudWatch Dashboard URL",Value:d.sub("https://console.aws.amazon.com/cloudwatch/home?region=${AWS::Region}#dashboards:name=${CloudWatchDashboard}")}})}function ys(e,t,a){let r=e.toLogicalId(`${t}-log-group`);e.addResource(r,"AWS::Logs::LogGroup",{LogGroupName:d.sub(`/aws/\${AWS::StackName}/${t}`),RetentionInDays:a||14,Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-${t}`)}]})}function jt(e,t){if(t)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"}[t.toLowerCase()]||"AWS/CloudWatch";let a=e.toLowerCase();if(a.includes("cpu")||a.includes("memory")||a.includes("network"))return"AWS/EC2";if(a.includes("lambda")||a.includes("invocation")||a.includes("duration"))return"AWS/Lambda";if(a.includes("request")||a.includes("latency")||a.includes("target"))return"AWS/ApplicationELB";if(a.includes("database")||a.includes("connection"))return"AWS/RDS";if(a.includes("read")||a.includes("write")||a.includes("consumed"))return"AWS/DynamoDB";return"AWS/CloudWatch"}function fs(e){return{ec2:[{Name:"InstanceId",Value:d.ref("EC2Instance")}],ecs:[{Name:"ClusterName",Value:d.ref("ECSCluster")},{Name:"ServiceName",Value:d.getAtt("ECSService","Name")}],lambda:[{Name:"FunctionName",Value:d.ref("LambdaFunction")}],rds:[{Name:"DBInstanceIdentifier",Value:d.ref("Database")}],dynamodb:[{Name:"TableName",Value:d.ref("DynamoDBTable")}],alb:[{Name:"LoadBalancer",Value:d.getAtt("LoadBalancer","LoadBalancerFullName")}],apigateway:[{Name:"ApiName",Value:d.ref("HttpApi")}]}[e.toLowerCase()]||[]}function Ss(e,t){if(!t.vpc)return;let{cidr:a="10.0.0.0/16",availabilityZones:r=2,natGateways:n=1,enableDnsHostnames:i=!0,enableDnsSupport:s=!0}=t.vpc;e.addResource("VPC","AWS::EC2::VPC",{CidrBlock:a,EnableDnsHostnames:i,EnableDnsSupport:s,Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-vpc")}]}),e.addResource("InternetGateway","AWS::EC2::InternetGateway",{Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-igw")}]}),e.addResource("VPCGatewayAttachment","AWS::EC2::VPCGatewayAttachment",{VpcId:d.ref("VPC"),InternetGatewayId:d.ref("InternetGateway")},{dependsOn:["VPC","InternetGateway"]});let o=[];for(let m=0;m<r;m++){let p=`PublicSubnet${m+1}`;o.push(p),e.addResource(p,"AWS::EC2::Subnet",{VpcId:d.ref("VPC"),CidrBlock:d.select(m,d.cidr(d.getAtt("VPC","CidrBlock"),r*2,8)),AvailabilityZone:d.select(m,d.getAZs()),MapPublicIpOnLaunch:!0,Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-public-${m+1}`)},{Key:"Type",Value:"public"}]},{dependsOn:"VPC"})}let c=[];for(let m=0;m<r;m++){let p=`PrivateSubnet${m+1}`;c.push(p),e.addResource(p,"AWS::EC2::Subnet",{VpcId:d.ref("VPC"),CidrBlock:d.select(m+r,d.cidr(d.getAtt("VPC","CidrBlock"),r*2,8)),AvailabilityZone:d.select(m,d.getAZs()),MapPublicIpOnLaunch:!1,Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-private-${m+1}`)},{Key:"Type",Value:"private"}]},{dependsOn:"VPC"})}let l=[];for(let m=0;m<n;m++){let p=`NatEIP${m+1}`;l.push(p),e.addResource(p,"AWS::EC2::EIP",{Domain:"vpc",Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-nat-eip-${m+1}`)}]},{dependsOn:"VPCGatewayAttachment"})}let u=[];for(let m=0;m<n;m++){let p=`NatGateway${m+1}`;u.push(p);let g=m%r;e.addResource(p,"AWS::EC2::NatGateway",{AllocationId:d.getAtt(l[m],"AllocationId"),SubnetId:d.ref(o[g]),Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-nat-${m+1}`)}]},{dependsOn:[l[m],o[g]]})}e.addResource("PublicRouteTable","AWS::EC2::RouteTable",{VpcId:d.ref("VPC"),Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-public-rt")}]},{dependsOn:"VPC"}),e.addResource("PublicRoute","AWS::EC2::Route",{RouteTableId:d.ref("PublicRouteTable"),DestinationCidrBlock:"0.0.0.0/0",GatewayId:d.ref("InternetGateway")},{dependsOn:["PublicRouteTable","VPCGatewayAttachment"]}),o.forEach((m,p)=>{e.addResource(`PublicSubnetRouteTableAssociation${p+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:d.ref(m),RouteTableId:d.ref("PublicRouteTable")},{dependsOn:[m,"PublicRouteTable"]})}),c.forEach((m,p)=>{let g=`PrivateRouteTable${p+1}`,h=p%n;e.addResource(g,"AWS::EC2::RouteTable",{VpcId:d.ref("VPC"),Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-private-rt-${p+1}`)}]},{dependsOn:"VPC"}),e.addResource(`PrivateRoute${p+1}`,"AWS::EC2::Route",{RouteTableId:d.ref(g),DestinationCidrBlock:"0.0.0.0/0",NatGatewayId:d.ref(u[h])},{dependsOn:[g,u[h]]}),e.addResource(`PrivateSubnetRouteTableAssociation${p+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:d.ref(m),RouteTableId:d.ref(g)},{dependsOn:[m,g]})}),e.addResource("S3VPCEndpoint","AWS::EC2::VPCEndpoint",{VpcId:d.ref("VPC"),ServiceName:d.sub("com.amazonaws.${AWS::Region}.s3"),VpcEndpointType:"Gateway",RouteTableIds:[d.ref("PublicRouteTable"),...Array.from({length:r},(m,p)=>d.ref(`PrivateRouteTable${p+1}`))]},{dependsOn:"VPC"}),e.addResource("NetworkAcl","AWS::EC2::NetworkAcl",{VpcId:d.ref("VPC"),Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-nacl")}]},{dependsOn:"VPC"}),e.addResource("NetworkAclEntryInbound","AWS::EC2::NetworkAclEntry",{NetworkAclId:d.ref("NetworkAcl"),RuleNumber:100,Protocol:-1,RuleAction:"allow",CidrBlock:"0.0.0.0/0"},{dependsOn:"NetworkAcl"}),e.addResource("NetworkAclEntryOutbound","AWS::EC2::NetworkAclEntry",{NetworkAclId:d.ref("NetworkAcl"),RuleNumber:100,Protocol:-1,Egress:!0,RuleAction:"allow",CidrBlock:"0.0.0.0/0"},{dependsOn:"NetworkAcl"}),e.addOutputs({VPCId:{Description:"VPC ID",Value:d.ref("VPC"),Export:{Name:d.sub("${AWS::StackName}-VPC")}},PublicSubnets:{Description:"Public subnet IDs",Value:d.join(",",o.map((m)=>d.ref(m))),Export:{Name:d.sub("${AWS::StackName}-PublicSubnets")}},PrivateSubnets:{Description:"Private subnet IDs",Value:d.join(",",c.map((m)=>d.ref(m))),Export:{Name:d.sub("${AWS::StackName}-PrivateSubnets")}}})}function bs(e,t){for(let[a,r]of Object.entries(t))As(e,a,r)}function As(e,t,a){let r=e.toLogicalId(`${t}-queue`),n=a.fifo||!1,i;if(a.deadLetterQueue){let o=`${r}DLQ`;e.addResource(o,"AWS::SQS::Queue",{QueueName:n?d.sub(`\${AWS::StackName}-${t}-dlq.fifo`):d.sub(`\${AWS::StackName}-${t}-dlq`),FifoQueue:n,MessageRetentionPeriod:1209600,Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-${t}-dlq`)}]},{deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),i=d.getAtt(o,"Arn")}let s={QueueName:n?d.sub(`\${AWS::StackName}-${t}.fifo`):d.sub(`\${AWS::StackName}-${t}`),FifoQueue:n,VisibilityTimeout:a.visibilityTimeout||30,MessageRetentionPeriod:a.messageRetentionPeriod||345600,ReceiveMessageWaitTimeSeconds:a.receiveMessageWaitTime||0,Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-${t}`)}]};if(n&&a.contentBasedDeduplication)s.ContentBasedDeduplication=!0;if(a.deadLetterQueue&&i)s.RedrivePolicy={deadLetterTargetArn:i,maxReceiveCount:a.maxReceiveCount||3};if(e.addResource(r,"AWS::SQS::Queue",s,{dependsOn:a.deadLetterQueue?`${r}DLQ`:void 0,deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),e.addResource(`${r}Policy`,"AWS::SQS::QueuePolicy",{Queues:[d.ref(r)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["lambda.amazonaws.com","events.amazonaws.com","sns.amazonaws.com"]},Action:"sqs:SendMessage",Resource:d.getAtt(r,"Arn"),Condition:{ArnEquals:{"aws:SourceArn":d.sub("arn:aws:*:${AWS::Region}:${AWS::AccountId}:*")}}}]}},{dependsOn:r}),e.addOutputs({[`${r}Url`]:{Description:`${t} queue URL`,Value:d.ref(r),Export:{Name:d.sub(`\${AWS::StackName}-${t}-queue-url`)}},[`${r}Arn`]:{Description:`${t} queue ARN`,Value:d.getAtt(r,"Arn"),Export:{Name:d.sub(`\${AWS::StackName}-${t}-queue-arn`)}}}),a.deadLetterQueue)e.addOutputs({[`${r}DLQUrl`]:{Description:`${t} dead letter queue URL`,Value:d.ref(`${r}DLQ`),Export:{Name:d.sub(`\${AWS::StackName}-${t}-dlq-url`)}}})}function Cs(e,t){if(t.certificate)Ts(e,t.certificate);if(t.waf?.enabled)vs(e,t.waf);if(t.securityGroups)for(let[a,r]of Object.entries(t.securityGroups))ws(e,a,r)}function Ts(e,t){if(!t)return;let a=[t.domain];if(t.subdomains)a.push(...t.subdomains);e.addResource("Certificate","AWS::CertificateManager::Certificate",{DomainName:t.domain,SubjectAlternativeNames:t.subdomains,ValidationMethod:t.validationMethod||"DNS",DomainValidationOptions:a.map((r)=>({DomainName:r,HostedZoneId:d.ref("HostedZone")})),Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-certificate")}]}),e.addOutputs({CertificateArn:{Description:"ACM Certificate ARN",Value:d.ref("Certificate"),Export:{Name:d.sub("${AWS::StackName}-certificate-arn")}}})}function vs(e,t){if(!t)return;let a=[],r=t.rules||["rateLimit","sqlInjection","xss"];if(r.includes("rateLimit"))a.push({Name:"RateLimitRule",Priority:1,Statement:{RateBasedStatement:{Limit:t.rateLimit||2000,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"RateLimitRule"}});let n=a.length+1;if(r.includes("sqlInjection"))a.push({Name:"AWSManagedRulesSQLi",Priority:n++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesSQLiRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesSQLi"}});if(r.includes("xss"))a.push({Name:"AWSManagedRulesXSS",Priority:n++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesXSS"}});if(r.includes("knownBadInputs"))a.push({Name:"AWSManagedRulesKnownBadInputs",Priority:n++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesKnownBadInputs"}});if(r.includes("coreRuleSet"))a.push({Name:"AWSManagedRulesCoreRuleSet",Priority:n++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesCommonRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesCoreRuleSet"}});if(r.includes("linuxRuleSet"))a.push({Name:"AWSManagedRulesLinuxRuleSet",Priority:n++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesLinuxRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesLinuxRuleSet"}});if(r.includes("apiProtection"))a.push({Name:"AWSManagedRulesAPIProtection",Priority:n++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesAmazonIpReputationList"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesAPIProtection"}});if(r.includes("geoBlock"))a.push({Name:"GeoBlockRule",Priority:n++,Statement:{GeoMatchStatement:{CountryCodes:["CN","RU"]}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"GeoBlockRule"}});if(r.includes("connectionLimit"))a.push({Name:"ConnectionLimitRule",Priority:n++,Statement:{RateBasedStatement:{Limit:100,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"ConnectionLimitRule"}});if(e.addResource("WebACL","AWS::WAFv2::WebACL",{Name:d.sub("${AWS::StackName}-waf"),Scope:t.scope||"REGIONAL",DefaultAction:{Allow:{}},Rules:a,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:d.sub("${AWS::StackName}-waf")},Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-waf")}]}),e.hasResource("LoadBalancer"))e.addResource("WebACLAssociation","AWS::WAFv2::WebACLAssociation",{ResourceArn:d.ref("LoadBalancer"),WebACLArn:d.getAtt("WebACL","Arn")},{dependsOn:["WebACL","LoadBalancer"]});e.addOutputs({WebACLId:{Description:"WAF Web ACL ID",Value:d.ref("WebACL"),Export:{Name:d.sub("${AWS::StackName}-waf-id")}},WebACLArn:{Description:"WAF Web ACL ARN",Value:d.getAtt("WebACL","Arn"),Export:{Name:d.sub("${AWS::StackName}-waf-arn")}}})}function ws(e,t,a){if(!a)return;let r=e.toLogicalId(`${t}-security-group`),n=a.ingress?.map((s)=>({IpProtocol:s.protocol,FromPort:s.port,ToPort:s.port,CidrIp:s.cidr,SourceSecurityGroupId:s.source?d.ref(s.source):void 0}))||[],i=a.egress?.map((s)=>({IpProtocol:s.protocol,FromPort:s.port,ToPort:s.port,CidrIp:s.cidr||"0.0.0.0/0"}))||[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}];e.addResource(r,"AWS::EC2::SecurityGroup",{GroupDescription:`Security group for ${t}`,VpcId:d.ref("VPC"),SecurityGroupIngress:n,SecurityGroupEgress:i,Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-${t}-sg`)}]},{dependsOn:"VPC"}),e.addOutputs({[`${r}Id`]:{Description:`${t} security group ID`,Value:d.ref(r),Export:{Name:d.sub(`\${AWS::StackName}-${t}-sg-id`)}}})}function Es(e,t){for(let[a,r]of Object.entries(t)){if(r.type==="efs"){Is(e,a,r);continue}Ps(e,a,r)}}function Ps(e,t,a){let r=e.toLogicalId(`${t}-bucket`),n={BucketName:d.sub(`\${AWS::StackName}-${t}`),Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-${t}`)}]};if(a.versioning)n.VersioningConfiguration={Status:"Enabled"};if(a.encryption)n.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(!a.public)n.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(a.website)n.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"index.html"};if(a.cors&&a.cors.length>0)n.CorsConfiguration={CorsRules:a.cors.map((i)=>({AllowedOrigins:i.allowedOrigins,AllowedMethods:i.allowedMethods,AllowedHeaders:i.allowedHeaders||["*"],MaxAge:i.maxAge||3600}))};if(a.lifecycleRules&&a.lifecycleRules.length>0)n.LifecycleConfiguration={Rules:a.lifecycleRules.map((i)=>({Id:i.id,Status:i.enabled?"Enabled":"Disabled",ExpirationInDays:i.expirationDays,Transitions:i.transitions?.map((s)=>({TransitionInDays:s.days,StorageClass:s.storageClass}))}))};if(a.intelligentTiering)n.IntelligentTieringConfigurations=[{Id:"EntireBucket",Status:"Enabled",Tierings:[{AccessTier:"ARCHIVE_ACCESS",Days:90},{AccessTier:"DEEP_ARCHIVE_ACCESS",Days:180}]}];if(e.addResource(r,"AWS::S3::Bucket",n,{deletionPolicy:a.versioning?"Retain":"Delete"}),a.public)e.addResource(`${r}Policy`,"AWS::S3::BucketPolicy",{Bucket:d.ref(r),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:"s3:GetObject",Resource:d.join("",[Ct.s3Bucket(d.ref(r)),"/*"])}]}},{dependsOn:r});if(e.addOutputs({[`${r}Name`]:{Description:`${t} bucket name`,Value:d.ref(r),Export:{Name:d.sub(`\${AWS::StackName}-${t}-bucket`)}},[`${r}Arn`]:{Description:`${t} bucket ARN`,Value:d.getAtt(r,"Arn"),Export:{Name:d.sub(`\${AWS::StackName}-${t}-bucket-arn`)}}}),a.website)e.addOutputs({[`${r}WebsiteURL`]:{Description:`${t} website URL`,Value:d.getAtt(r,"WebsiteURL")}})}function Is(e,t,a){let r=e.toLogicalId(`${t}-efs`),n={Encrypted:a.encryption!==!1,PerformanceMode:a.performanceMode||"generalPurpose",ThroughputMode:a.throughputMode||"bursting",FileSystemTags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-${t}`)}]};if(a.lifecyclePolicy){if(n.LifecyclePolicies=[],a.lifecyclePolicy.transitionToIA)n.LifecyclePolicies.push({TransitionToIA:`AFTER_${a.lifecyclePolicy.transitionToIA}_DAYS`});if(a.lifecyclePolicy.transitionToPrimaryStorageClass)n.LifecyclePolicies.push({TransitionToPrimaryStorageClass:"AFTER_1_ACCESS"})}e.addResource(r,"AWS::EFS::FileSystem",n,{deletionPolicy:"Retain"});let i=2;for(let s=0;s<i;s++)e.addResource(`${r}MountTarget${s+1}`,"AWS::EFS::MountTarget",{FileSystemId:d.ref(r),SubnetId:d.ref(`PrivateSubnet${s+1}`),SecurityGroups:[d.ref("EFSSecurityGroup")]},{dependsOn:[r,`PrivateSubnet${s+1}`]});e.addResource("EFSSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for EFS mount targets",VpcId:d.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:2049,ToPort:2049,SourceSecurityGroupId:d.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-efs-sg")}]},{dependsOn:"VPC"}),e.addOutputs({[`${r}Id`]:{Description:`${t} EFS file system ID`,Value:d.ref(r),Export:{Name:d.sub(`\${AWS::StackName}-${t}-efs`)}}})}class Ya{template;config;resourceDependencies;constructor(e){this.config=e,this.resourceDependencies=new Map,this.template={AWSTemplateFormatVersion:"2010-09-09",Description:`Infrastructure for ${e.project.name} (${e.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:d.equals(d.ref("Environment"),"production"),HasDomain:d.not([d.equals(this.config.environments?.production?.domain||"","")])}}addResources(){let{infrastructure:e}=this.config;if(!e)return;if(e.network)this.addNetworkResources(e.network);if(e.storage)this.addStorageResources(e.storage);if(e.compute)this.addComputeResources(e.compute);if(e.databases)this.addDatabaseResources(e.databases);if(e.cache)this.addCacheResources(e.cache);if(e.cdn)this.addCDNResources(e.cdn);if(e.apiGateway)this.addApiGatewayResources(e.apiGateway);if(e.functions)this.addFunctionResources(e.functions);if(e.queues)this.addQueueResources(e.queues);if(e.messaging)this.addMessagingResources(e.messaging);if(e.monitoring)this.addMonitoringResources(e.monitoring);if(e.security)this.addSecurityResources(e.security)}initializeOutputs(){let e=this.template.Outputs||{};if(this.template.Outputs={StackName:{Description:"Stack name",Value:d.ref("AWS::StackName"),Export:{Name:d.sub("${AWS::StackName}-Name")}},Region:{Description:"AWS Region",Value:d.ref("AWS::Region"),Export:{Name:d.sub("${AWS::StackName}-Region")}},...e},this.config.environments?.production?.domain)this.template.Outputs.Domain={Description:"Production domain",Value:this.config.environments.production.domain,Condition:"HasDomain"}}addResource(e,t,a,r){let n={Type:t,Properties:a};if(r?.dependsOn)n.DependsOn=r.dependsOn,this.trackDependency(e,r.dependsOn);if(r?.condition)n.Condition=r.condition;if(r?.deletionPolicy)n.DeletionPolicy=r.deletionPolicy;if(r?.updateReplacePolicy)n.UpdateReplacePolicy=r.updateReplacePolicy;this.template.Resources[e]=n}addOutputs(e){this.template.Outputs={...this.template.Outputs,...e}}getOutputs(){return this.template.Outputs||{}}hasResource(e){return e in this.template.Resources}getResource(e){return this.template.Resources[e]}trackDependency(e,t){if(!this.resourceDependencies.has(e))this.resourceDependencies.set(e,new Set);(Array.isArray(t)?t:[t]).forEach((a)=>this.resourceDependencies.get(e).add(a))}resolveDependencies(){let e=new Set,t=new Set,a=(r)=>{if(t.has(r))throw Error(`Circular dependency detected involving resource: ${r}`);if(e.has(r))return!0;e.add(r),t.add(r);let n=this.resourceDependencies.get(r);if(n)for(let i of n)a(i);return t.delete(r),!0};for(let r of this.resourceDependencies.keys())a(r)}toLogicalId(e){return e.split(/[-_\s]/).map((t)=>t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()).join("")}addNetworkResources(e){Ss(this,e)}addStorageResources(e){Es(this,e)}addComputeResources(e){as(this,e)}addDatabaseResources(e){is(this,e)}addFunctionResources(e){os(this,e)}addCacheResources(e){Ji(this,e)}addQueueResources(e){bs(this,e)}addMessagingResources(e){ds(this,e)}addCDNResources(e){es(this,e)}addApiGatewayResources(e){ji(this,e)}addMonitoringResources(e){ps(this,e)}addSecurityResources(e){Cs(this,e)}}function Hl(e){return new Ya(e).build()}function ql(e){let{name:t,slug:a,domain:r,subdomain:n}=e;return{project:{name:t,slug:a,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:n&&r?`${n}.${r}`:r}},infrastructure:{storage:{assets:{public:!0,versioning:!1,website:!0,encryption:!1,cors:[{allowedOrigins:["*"],allowedMethods:["GET","HEAD"],allowedHeaders:["*"],maxAge:3600}]}},cdn:{enabled:!0,customDomain:r?{domain:n&&r?`${n}.${r}`:r,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 zl(e){let{name:t,slug:a,domain:r,instanceType:n="t3.small",minInstances:i=2,maxInstances:s=10}=e;return{project:{name:t,slug:a,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:r}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:n,ami:"ubuntu-22.04",keyPair:`${a}-key`,autoScaling:{min:i,max:s,desired:i,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:r?{domain:r,subdomains:[`*.${r}`],validationMethod:"DNS"}:void 0}}}}function Ql(e){let{name:t,slug:a,domain:r,taskCpu:n="256",taskMemory:i="512",desiredCount:s=2}=e;return{project:{name:t,slug:a,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:r}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:0}},compute:{fargate:{taskDefinition:{cpu:n,memory:i,containerDefinitions:[{name:"app",image:`${a}-app:latest`,portMappings:[{containerPort:3000}],environment:[],secrets:[]}]},service:{desiredCount:s,healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3},autoScaling:{min:s,max:s*5,targetCPU:70,targetMemory:80}},loadBalancer:{type:"application"}}},databases:{dynamodb:{tables:{[`${a}-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:`${a}-queue`}]}},security:{certificate:r?{domain:r,subdomains:[`*.${r}`],validationMethod:"DNS"}:void 0}}}}function Jl(e){let{name:t,slug:a,entry:r,domain:n,runtime:i="nodejs20.x",memory:s=1024,build:o,deploy:c,assets:l,queues:u=!0,scheduler:m="on",region:p="us-east-1"}=e;return{project:{name:t,slug:a,region:p},mode:"serverless",environments:{production:{type:"production",domain:n,app:{kind:"node",runtime:i,entry:r,memory:s,build:o,deploy:c,assets:l,queues:u,scheduler:m,domain:n}}}}}function Yl(e){let t=e.database!==!1,a=e.cache!==!1,r=e.queue!==!1;return{project:{name:e.name,slug:e.slug,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:e.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:e.imageUri,portMappings:[{containerPort:3000}],environment:[{name:"NODE_ENV",value:"production"},{name:"PORT",value:"3000"},{name:"AWS_REGION",value:d.ref("AWS::Region")},...t?[{name:"DB_HOST",value:d.getAtt("PostgresDb","Endpoint.Address")},{name:"DB_PORT",value:d.getAtt("PostgresDb","Endpoint.Port")}]:[],...a?[{name:"REDIS_HOST",value:d.getAtt("RedisReplicationGroup","PrimaryEndPoint.Address")},{name:"REDIS_PORT",value:d.getAtt("RedisReplicationGroup","PrimaryEndPoint.Port")},{name:"REDIS_TLS",value:"true"}]:[],...r?[{name:"QUEUE_URL",value:d.ref("JobsQueue")}]:[],{name:"MAIL_TRANSPORT",value:"ses"}],secrets:t?[{name:"DB_USERNAME",valueFrom:d.sub("${DBSecret}:username::")},{name:"DB_PASSWORD",valueFrom:d.sub("${DBSecret}:password::")}]:[]}]},service:{desiredCount:e.desiredCount||1,healthCheck:{path:"/api/health",interval:30,timeout:5},autoScaling:{min:e.desiredCount||1,max:6,targetCPU:70}},loadBalancer:{type:"application",...e.certificateArn?{customDomain:{domain:e.domain,certificateArn:e.certificateArn}}:{},...e.originVerifySecret?{originVerifyHeader:{name:"X-Origin-Verify",value:e.originVerifySecret}}:{}}}},...t?{databases:{postgres:{engine:"postgres",version:"16",instanceClass:"db.t4g.micro",allocatedStorage:20,maxAllocatedStorage:100,multiAZ:!1,backupRetentionDays:7,deletionProtection:!0}}}:{},...a?{cache:{redis:{nodeType:"cache.t4g.micro",numCacheNodes:2,engine:"redis",engineVersion:"7.1",automaticFailoverEnabled:!0,snapshotRetentionLimit:5}}}:{},...r?{queues:{jobs:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0,maxReceiveCount:3,receiveMessageWaitTime:20}}}:{}}}}function Zl(e){let{name:t,slug:a,domain:r,apiSubdomain:n="api"}=e;return{project:{name:t,slug:a,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:r}},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:r,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:`${a}-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:`${n}.${r}`,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:r,subdomains:[`*.${r}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss"]}}}}}function Xl(e){let{name:t,slug:a,domain:r}=e;return{project:{name:t,slug:a,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:r}},infrastructure:{apiGateway:{type:"HTTP",cors:{allowOrigins:["*"],allowMethods:["GET","POST","PUT","DELETE","PATCH"],allowHeaders:["Content-Type","Authorization"],maxAge:3600},customDomain:r?{domain:r,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:{[`${a}-users`]:{partitionKey:{name:"userId",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0,globalSecondaryIndexes:[{name:"EmailIndex",partitionKey:{name:"email",type:"S"},projection:"ALL"}]},[`${a}-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:r?{domain:r,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 eu(e){let{name:t,slug:a,domain:r,instanceType:n="t3.small"}=e;return{project:{name:t,slug:a,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:r}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:n,ami:"ubuntu-22.04",keyPair:`${a}-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:r,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,origins:[{type:"alb",pathPattern:"/wp-content/*"}]},security:{certificate:{domain:r,subdomains:[`www.${r}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss","wordpressRules"]}}}}}function tu(e){let{name:t,slug:a,domain:r,apiDomain:n}=e;return{project:{name:t,slug:a,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:r}},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:r,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},...n?{api:{runtime:"nodejs20.x",handler:"dist/api/index.handler",memory:1024,timeout:30,events:[{type:"http",path:"/{proxy+}",method:"ANY"}]}}:{}},apiGateway:n?{type:"HTTP",customDomain:{domain:n,certificateArn:"TO_BE_GENERATED"},cors:{allowOrigins:[r],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:r,subdomains:n?[n]:[],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","geoBlock"]}}}}}function au(e){let{name:t,slug:a,domain:r,services:n}=e;return{project:{name:t,slug:a,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:r}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:3,natGateways:2}},compute:{services:n.map((i)=>({name:i.name,type:"fargate",taskDefinition:{cpu:i.cpu||"256",memory:i.memory||"512",containerDefinitions:[{name:i.name,image:`${a}-${i.name}:latest`,portMappings:[{containerPort:i.port}],healthCheck:{command:["CMD-SHELL",`curl -f http://localhost:${i.port}/health || exit 1`],interval:30,timeout:5,retries:3}}]},service:{desiredCount:i.desiredCount||2,serviceDiscovery:{enabled:!0,namespace:`${a}.local`},autoScaling:{min:2,max:10,targetCPU:70}}}))},apiGateway:{type:"HTTP",customDomain:{domain:r,certificateArn:"TO_BE_GENERATED"},cors:{allowOrigins:["*"],allowMethods:["GET","POST","PUT","DELETE","PATCH"]},routes:n.map((i)=>({path:`/${i.name}/{proxy+}`,integration:{type:"vpc-link",service:i.name}}))},databases:{dynamodb:{tables:Object.fromEntries(n.map((i)=>[`${a}-${i.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:`${a}-events`,subscriptions:n.map((i)=>({protocol:"sqs",endpoint:`${a}-${i.name}-queue`,filterPolicy:{service:[i.name]}}))}}},monitoring:{dashboard:{name:`${a}-microservices`,widgets:n.map((i)=>({type:"metric",metrics:[{service:i.name,metric:"CPUUtilization"},{service:i.name,metric:"MemoryUtilization"},{service:i.name,metric:"RequestCount"}]}))},alarms:n.flatMap((i)=>[{name:`${i.name}-high-cpu`,metric:"CPUUtilization",threshold:80,service:i.name},{name:`${i.name}-errors`,metric:"Errors",threshold:10,service:i.name}])},security:{certificate:{domain:r,validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection"]}}}}}function ru(e){let{name:t,slug:a,domain:r}=e;return{project:{name:t,slug:a,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:r}},infrastructure:{apiGateway:{type:"websocket",customDomain:r?{domain:r,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:`${a}-messages`,startingPosition:"LATEST",batchSize:100}]}},databases:{dynamodb:{tables:{[`${a}-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"}]},[`${a}-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"}]},[`${a}-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:`${a}-realtime`,widgets:[{type:"metric",metrics:["WebSocketConnections","MessagesSent","IntegrationLatency"]}]}},security:{certificate:r?{domain:r,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","connectionLimit"]}}}}}function nu(e){let{name:t,slug:a,retentionDays:r=7}=e;return{project:{name:t,slug:a,region:"us-east-1"},mode:"serverless",infrastructure:{streaming:{dataStream:{name:`${a}-stream`,shardCount:2,retentionPeriod:r*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:`${a}-stream`,batchSize:1000,startingPosition:"LATEST",parallelizationFactor:10}]},transformer:{runtime:"nodejs20.x",handler:"dist/processors/transform.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${a}-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:`${a}_analytics`,workgroup:`${a}-workgroup`,outputBucket:`${a}-query-results`,tables:[{name:"raw_events",location:`s3://${a}-raw/events/`,format:"parquet",partitionKeys:["year","month","day"]},{name:"processed_events",location:`s3://${a}-processed/events/`,format:"parquet",partitionKeys:["year","month","day"]}]},glue:{crawlers:[{name:`${a}-crawler`,databaseName:`${a}_analytics`,s3Targets:[`s3://${a}-raw/`,`s3://${a}-processed/`],schedule:"cron(0 2 * * ? *)"}],jobs:[{name:`${a}-etl-job`,scriptLocation:`s3://${a}-scripts/etl.py`,role:`${a}-glue-role`,maxCapacity:10,timeout:120}]}},databases:{dynamodb:{tables:{[`${a}-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:`${a}-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:`${a}-pipeline`,widgets:[{type:"metric",metrics:["KinesisIncomingRecords","LambdaInvocations","S3ObjectsCreated","GlueJobsSucceeded"]}]},alarms:[{metric:"LambdaErrors",threshold:10,evaluationPeriods:1},{metric:"KinesisIteratorAge",threshold:60000,evaluationPeriods:2}]}}}}function iu(e){let{name:t,slug:a,domain:r,modelS3Path:n=`s3://${a}-models/`,instanceType:i="ml.t3.medium"}=e;return{project:{name:t,slug:a,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:r}},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:`${a}-inference`,modelS3Path:n,instanceType:i,initialInstanceCount:1,autoScaling:{minInstances:1,maxInstances:5,targetInvocationsPerInstance:1000}}],trainingJobs:[{name:`${a}-training`,algorithmSpecification:{trainingImage:"TO_BE_SPECIFIED",trainingInputMode:"File"},instanceType:"ml.p3.2xlarge",instanceCount:1,volumeSizeInGB:50,maxRuntimeInSeconds:86400}]}},apiGateway:{type:"HTTP",customDomain:r?{domain:r,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:`${a}-inference`,MODEL_BUCKET:`${a}-models`}},"batch-predict":{runtime:"python3.11",handler:"handlers/batchPredict.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${a}-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:{[`${a}-predictions`]:{partitionKey:{name:"requestId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0},[`${a}-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:`${a}-ml`,widgets:[{type:"metric",metrics:["SageMakerInvocations","SageMakerModelLatency","APIGatewayRequests","LambdaErrors"]}]},alarms:[{metric:"SageMakerModelLatency",threshold:1000,evaluationPeriods:2},{metric:"SageMakerInvocationErrors",threshold:10,evaluationPeriods:1}]},security:{certificate:r?{domain:r,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","apiProtection"]}}}}}function su(e){let{name:t,slug:a,domain:r,instanceType:n="t3.medium",minInstances:i=2,maxInstances:s=10,databaseEngine:o="mysql",sessionStore:c="redis"}=e;return{project:{name:t,slug:a,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:r}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:2}},compute:{server:{instanceType:n,ami:"ubuntu-22.04",autoScaling:{min:i,max:s,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:d.ref("AWS::Region"),title:`Logs: ${i.logGroup}`}});else if(i.type==="text"&&i.text)a.push({type:"text",x:r,y:n,width:s,height:o,properties:{markdown:i.text}});if(r+=s,r>=24)r=0,n+=o}),e.addResource("CloudWatchDashboard","AWS::CloudWatch::Dashboard",{DashboardName:d.sub(`\${AWS::StackName}-${t.name}`),DashboardBody:JSON.stringify({widgets:a})}),e.addOutputs({DashboardURL:{Description:"CloudWatch Dashboard URL",Value:d.sub("https://console.aws.amazon.com/cloudwatch/home?region=${AWS::Region}#dashboards:name=${CloudWatchDashboard}")}})}function hs(e,t,a){let r=e.toLogicalId(`${t}-log-group`);e.addResource(r,"AWS::Logs::LogGroup",{LogGroupName:d.sub(`/aws/\${AWS::StackName}/${t}`),RetentionInDays:a||14,Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-${t}`)}]})}function jt(e,t){if(t)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"}[t.toLowerCase()]||"AWS/CloudWatch";let a=e.toLowerCase();if(a.includes("cpu")||a.includes("memory")||a.includes("network"))return"AWS/EC2";if(a.includes("lambda")||a.includes("invocation")||a.includes("duration"))return"AWS/Lambda";if(a.includes("request")||a.includes("latency")||a.includes("target"))return"AWS/ApplicationELB";if(a.includes("database")||a.includes("connection"))return"AWS/RDS";if(a.includes("read")||a.includes("write")||a.includes("consumed"))return"AWS/DynamoDB";return"AWS/CloudWatch"}function ys(e){return{ec2:[{Name:"InstanceId",Value:d.ref("EC2Instance")}],ecs:[{Name:"ClusterName",Value:d.ref("ECSCluster")},{Name:"ServiceName",Value:d.getAtt("ECSService","Name")}],lambda:[{Name:"FunctionName",Value:d.ref("LambdaFunction")}],rds:[{Name:"DBInstanceIdentifier",Value:d.ref("Database")}],dynamodb:[{Name:"TableName",Value:d.ref("DynamoDBTable")}],alb:[{Name:"LoadBalancer",Value:d.getAtt("LoadBalancer","LoadBalancerFullName")}],apigateway:[{Name:"ApiName",Value:d.ref("HttpApi")}]}[e.toLowerCase()]||[]}function fs(e,t){if(!t.vpc)return;let{cidr:a="10.0.0.0/16",availabilityZones:r=2,natGateways:n=1,enableDnsHostnames:i=!0,enableDnsSupport:s=!0}=t.vpc;e.addResource("VPC","AWS::EC2::VPC",{CidrBlock:a,EnableDnsHostnames:i,EnableDnsSupport:s,Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-vpc")}]}),e.addResource("InternetGateway","AWS::EC2::InternetGateway",{Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-igw")}]}),e.addResource("VPCGatewayAttachment","AWS::EC2::VPCGatewayAttachment",{VpcId:d.ref("VPC"),InternetGatewayId:d.ref("InternetGateway")},{dependsOn:["VPC","InternetGateway"]});let o=[];for(let m=0;m<r;m++){let p=`PublicSubnet${m+1}`;o.push(p),e.addResource(p,"AWS::EC2::Subnet",{VpcId:d.ref("VPC"),CidrBlock:d.select(m,d.cidr(d.getAtt("VPC","CidrBlock"),r*2,8)),AvailabilityZone:d.select(m,d.getAZs()),MapPublicIpOnLaunch:!0,Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-public-${m+1}`)},{Key:"Type",Value:"public"}]},{dependsOn:"VPC"})}let c=[];for(let m=0;m<r;m++){let p=`PrivateSubnet${m+1}`;c.push(p),e.addResource(p,"AWS::EC2::Subnet",{VpcId:d.ref("VPC"),CidrBlock:d.select(m+r,d.cidr(d.getAtt("VPC","CidrBlock"),r*2,8)),AvailabilityZone:d.select(m,d.getAZs()),MapPublicIpOnLaunch:!1,Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-private-${m+1}`)},{Key:"Type",Value:"private"}]},{dependsOn:"VPC"})}let l=[];for(let m=0;m<n;m++){let p=`NatEIP${m+1}`;l.push(p),e.addResource(p,"AWS::EC2::EIP",{Domain:"vpc",Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-nat-eip-${m+1}`)}]},{dependsOn:"VPCGatewayAttachment"})}let u=[];for(let m=0;m<n;m++){let p=`NatGateway${m+1}`;u.push(p);let g=m%r;e.addResource(p,"AWS::EC2::NatGateway",{AllocationId:d.getAtt(l[m],"AllocationId"),SubnetId:d.ref(o[g]),Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-nat-${m+1}`)}]},{dependsOn:[l[m],o[g]]})}e.addResource("PublicRouteTable","AWS::EC2::RouteTable",{VpcId:d.ref("VPC"),Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-public-rt")}]},{dependsOn:"VPC"}),e.addResource("PublicRoute","AWS::EC2::Route",{RouteTableId:d.ref("PublicRouteTable"),DestinationCidrBlock:"0.0.0.0/0",GatewayId:d.ref("InternetGateway")},{dependsOn:["PublicRouteTable","VPCGatewayAttachment"]}),o.forEach((m,p)=>{e.addResource(`PublicSubnetRouteTableAssociation${p+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:d.ref(m),RouteTableId:d.ref("PublicRouteTable")},{dependsOn:[m,"PublicRouteTable"]})}),c.forEach((m,p)=>{let g=`PrivateRouteTable${p+1}`,h=p%n;e.addResource(g,"AWS::EC2::RouteTable",{VpcId:d.ref("VPC"),Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-private-rt-${p+1}`)}]},{dependsOn:"VPC"}),e.addResource(`PrivateRoute${p+1}`,"AWS::EC2::Route",{RouteTableId:d.ref(g),DestinationCidrBlock:"0.0.0.0/0",NatGatewayId:d.ref(u[h])},{dependsOn:[g,u[h]]}),e.addResource(`PrivateSubnetRouteTableAssociation${p+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:d.ref(m),RouteTableId:d.ref(g)},{dependsOn:[m,g]})}),e.addResource("S3VPCEndpoint","AWS::EC2::VPCEndpoint",{VpcId:d.ref("VPC"),ServiceName:d.sub("com.amazonaws.${AWS::Region}.s3"),VpcEndpointType:"Gateway",RouteTableIds:[d.ref("PublicRouteTable"),...Array.from({length:r},(m,p)=>d.ref(`PrivateRouteTable${p+1}`))]},{dependsOn:"VPC"}),e.addResource("NetworkAcl","AWS::EC2::NetworkAcl",{VpcId:d.ref("VPC"),Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-nacl")}]},{dependsOn:"VPC"}),e.addResource("NetworkAclEntryInbound","AWS::EC2::NetworkAclEntry",{NetworkAclId:d.ref("NetworkAcl"),RuleNumber:100,Protocol:-1,RuleAction:"allow",CidrBlock:"0.0.0.0/0"},{dependsOn:"NetworkAcl"}),e.addResource("NetworkAclEntryOutbound","AWS::EC2::NetworkAclEntry",{NetworkAclId:d.ref("NetworkAcl"),RuleNumber:100,Protocol:-1,Egress:!0,RuleAction:"allow",CidrBlock:"0.0.0.0/0"},{dependsOn:"NetworkAcl"}),e.addOutputs({VPCId:{Description:"VPC ID",Value:d.ref("VPC"),Export:{Name:d.sub("${AWS::StackName}-VPC")}},PublicSubnets:{Description:"Public subnet IDs",Value:d.join(",",o.map((m)=>d.ref(m))),Export:{Name:d.sub("${AWS::StackName}-PublicSubnets")}},PrivateSubnets:{Description:"Private subnet IDs",Value:d.join(",",c.map((m)=>d.ref(m))),Export:{Name:d.sub("${AWS::StackName}-PrivateSubnets")}}})}function Ss(e,t){for(let[a,r]of Object.entries(t))bs(e,a,r)}function bs(e,t,a){let r=e.toLogicalId(`${t}-queue`),n=a.fifo||!1,i;if(a.deadLetterQueue){let o=`${r}DLQ`;e.addResource(o,"AWS::SQS::Queue",{QueueName:n?d.sub(`\${AWS::StackName}-${t}-dlq.fifo`):d.sub(`\${AWS::StackName}-${t}-dlq`),FifoQueue:n,MessageRetentionPeriod:1209600,Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-${t}-dlq`)}]},{deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),i=d.getAtt(o,"Arn")}let s={QueueName:n?d.sub(`\${AWS::StackName}-${t}.fifo`):d.sub(`\${AWS::StackName}-${t}`),FifoQueue:n,VisibilityTimeout:a.visibilityTimeout||30,MessageRetentionPeriod:a.messageRetentionPeriod||345600,ReceiveMessageWaitTimeSeconds:a.receiveMessageWaitTime||0,Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-${t}`)}]};if(n&&a.contentBasedDeduplication)s.ContentBasedDeduplication=!0;if(a.deadLetterQueue&&i)s.RedrivePolicy={deadLetterTargetArn:i,maxReceiveCount:a.maxReceiveCount||3};if(e.addResource(r,"AWS::SQS::Queue",s,{dependsOn:a.deadLetterQueue?`${r}DLQ`:void 0,deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),e.addResource(`${r}Policy`,"AWS::SQS::QueuePolicy",{Queues:[d.ref(r)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["lambda.amazonaws.com","events.amazonaws.com","sns.amazonaws.com"]},Action:"sqs:SendMessage",Resource:d.getAtt(r,"Arn"),Condition:{ArnEquals:{"aws:SourceArn":d.sub("arn:aws:*:${AWS::Region}:${AWS::AccountId}:*")}}}]}},{dependsOn:r}),e.addOutputs({[`${r}Url`]:{Description:`${t} queue URL`,Value:d.ref(r),Export:{Name:d.sub(`\${AWS::StackName}-${t}-queue-url`)}},[`${r}Arn`]:{Description:`${t} queue ARN`,Value:d.getAtt(r,"Arn"),Export:{Name:d.sub(`\${AWS::StackName}-${t}-queue-arn`)}}}),a.deadLetterQueue)e.addOutputs({[`${r}DLQUrl`]:{Description:`${t} dead letter queue URL`,Value:d.ref(`${r}DLQ`),Export:{Name:d.sub(`\${AWS::StackName}-${t}-dlq-url`)}}})}function As(e,t){if(t.certificate)Cs(e,t.certificate);if(t.waf?.enabled)Ts(e,t.waf);if(t.securityGroups)for(let[a,r]of Object.entries(t.securityGroups))vs(e,a,r)}function Cs(e,t){if(!t)return;let a=[t.domain];if(t.subdomains)a.push(...t.subdomains);e.addResource("Certificate","AWS::CertificateManager::Certificate",{DomainName:t.domain,SubjectAlternativeNames:t.subdomains,ValidationMethod:t.validationMethod||"DNS",DomainValidationOptions:a.map((r)=>({DomainName:r,HostedZoneId:d.ref("HostedZone")})),Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-certificate")}]}),e.addOutputs({CertificateArn:{Description:"ACM Certificate ARN",Value:d.ref("Certificate"),Export:{Name:d.sub("${AWS::StackName}-certificate-arn")}}})}function Ts(e,t){if(!t)return;let a=[],r=t.rules||["rateLimit","sqlInjection","xss"];if(r.includes("rateLimit"))a.push({Name:"RateLimitRule",Priority:1,Statement:{RateBasedStatement:{Limit:t.rateLimit||2000,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"RateLimitRule"}});let n=a.length+1;if(r.includes("sqlInjection"))a.push({Name:"AWSManagedRulesSQLi",Priority:n++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesSQLiRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesSQLi"}});if(r.includes("xss"))a.push({Name:"AWSManagedRulesXSS",Priority:n++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesXSS"}});if(r.includes("knownBadInputs"))a.push({Name:"AWSManagedRulesKnownBadInputs",Priority:n++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesKnownBadInputs"}});if(r.includes("coreRuleSet"))a.push({Name:"AWSManagedRulesCoreRuleSet",Priority:n++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesCommonRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesCoreRuleSet"}});if(r.includes("linuxRuleSet"))a.push({Name:"AWSManagedRulesLinuxRuleSet",Priority:n++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesLinuxRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesLinuxRuleSet"}});if(r.includes("apiProtection"))a.push({Name:"AWSManagedRulesAPIProtection",Priority:n++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesAmazonIpReputationList"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesAPIProtection"}});if(r.includes("geoBlock"))a.push({Name:"GeoBlockRule",Priority:n++,Statement:{GeoMatchStatement:{CountryCodes:["CN","RU"]}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"GeoBlockRule"}});if(r.includes("connectionLimit"))a.push({Name:"ConnectionLimitRule",Priority:n++,Statement:{RateBasedStatement:{Limit:100,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"ConnectionLimitRule"}});if(e.addResource("WebACL","AWS::WAFv2::WebACL",{Name:d.sub("${AWS::StackName}-waf"),Scope:t.scope||"REGIONAL",DefaultAction:{Allow:{}},Rules:a,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:d.sub("${AWS::StackName}-waf")},Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-waf")}]}),e.hasResource("LoadBalancer"))e.addResource("WebACLAssociation","AWS::WAFv2::WebACLAssociation",{ResourceArn:d.ref("LoadBalancer"),WebACLArn:d.getAtt("WebACL","Arn")},{dependsOn:["WebACL","LoadBalancer"]});e.addOutputs({WebACLId:{Description:"WAF Web ACL ID",Value:d.ref("WebACL"),Export:{Name:d.sub("${AWS::StackName}-waf-id")}},WebACLArn:{Description:"WAF Web ACL ARN",Value:d.getAtt("WebACL","Arn"),Export:{Name:d.sub("${AWS::StackName}-waf-arn")}}})}function vs(e,t,a){if(!a)return;let r=e.toLogicalId(`${t}-security-group`),n=a.ingress?.map((s)=>({IpProtocol:s.protocol,FromPort:s.port,ToPort:s.port,CidrIp:s.cidr,SourceSecurityGroupId:s.source?d.ref(s.source):void 0}))||[],i=a.egress?.map((s)=>({IpProtocol:s.protocol,FromPort:s.port,ToPort:s.port,CidrIp:s.cidr||"0.0.0.0/0"}))||[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}];e.addResource(r,"AWS::EC2::SecurityGroup",{GroupDescription:`Security group for ${t}`,VpcId:d.ref("VPC"),SecurityGroupIngress:n,SecurityGroupEgress:i,Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-${t}-sg`)}]},{dependsOn:"VPC"}),e.addOutputs({[`${r}Id`]:{Description:`${t} security group ID`,Value:d.ref(r),Export:{Name:d.sub(`\${AWS::StackName}-${t}-sg-id`)}}})}function ws(e,t){for(let[a,r]of Object.entries(t)){if(r.type==="efs"){Ps(e,a,r);continue}Es(e,a,r)}}function Es(e,t,a){let r=e.toLogicalId(`${t}-bucket`),n={BucketName:d.sub(`\${AWS::StackName}-${t}`),Tags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-${t}`)}]};if(a.versioning)n.VersioningConfiguration={Status:"Enabled"};if(a.encryption)n.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(!a.public)n.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(a.website)n.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"index.html"};if(a.cors&&a.cors.length>0)n.CorsConfiguration={CorsRules:a.cors.map((i)=>({AllowedOrigins:i.allowedOrigins,AllowedMethods:i.allowedMethods,AllowedHeaders:i.allowedHeaders||["*"],MaxAge:i.maxAge||3600}))};if(a.lifecycleRules&&a.lifecycleRules.length>0)n.LifecycleConfiguration={Rules:a.lifecycleRules.map((i)=>({Id:i.id,Status:i.enabled?"Enabled":"Disabled",ExpirationInDays:i.expirationDays,Transitions:i.transitions?.map((s)=>({TransitionInDays:s.days,StorageClass:s.storageClass}))}))};if(a.intelligentTiering)n.IntelligentTieringConfigurations=[{Id:"EntireBucket",Status:"Enabled",Tierings:[{AccessTier:"ARCHIVE_ACCESS",Days:90},{AccessTier:"DEEP_ARCHIVE_ACCESS",Days:180}]}];if(e.addResource(r,"AWS::S3::Bucket",n,{deletionPolicy:a.versioning?"Retain":"Delete"}),a.public)e.addResource(`${r}Policy`,"AWS::S3::BucketPolicy",{Bucket:d.ref(r),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:"s3:GetObject",Resource:d.join("",[At.s3Bucket(d.ref(r)),"/*"])}]}},{dependsOn:r});if(e.addOutputs({[`${r}Name`]:{Description:`${t} bucket name`,Value:d.ref(r),Export:{Name:d.sub(`\${AWS::StackName}-${t}-bucket`)}},[`${r}Arn`]:{Description:`${t} bucket ARN`,Value:d.getAtt(r,"Arn"),Export:{Name:d.sub(`\${AWS::StackName}-${t}-bucket-arn`)}}}),a.website)e.addOutputs({[`${r}WebsiteURL`]:{Description:`${t} website URL`,Value:d.getAtt(r,"WebsiteURL")}})}function Ps(e,t,a){let r=e.toLogicalId(`${t}-efs`),n={Encrypted:a.encryption!==!1,PerformanceMode:a.performanceMode||"generalPurpose",ThroughputMode:a.throughputMode||"bursting",FileSystemTags:[{Key:"Name",Value:d.sub(`\${AWS::StackName}-${t}`)}]};if(a.lifecyclePolicy){if(n.LifecyclePolicies=[],a.lifecyclePolicy.transitionToIA)n.LifecyclePolicies.push({TransitionToIA:`AFTER_${a.lifecyclePolicy.transitionToIA}_DAYS`});if(a.lifecyclePolicy.transitionToPrimaryStorageClass)n.LifecyclePolicies.push({TransitionToPrimaryStorageClass:"AFTER_1_ACCESS"})}e.addResource(r,"AWS::EFS::FileSystem",n,{deletionPolicy:"Retain"});let i=2;for(let s=0;s<i;s++)e.addResource(`${r}MountTarget${s+1}`,"AWS::EFS::MountTarget",{FileSystemId:d.ref(r),SubnetId:d.ref(`PrivateSubnet${s+1}`),SecurityGroups:[d.ref("EFSSecurityGroup")]},{dependsOn:[r,`PrivateSubnet${s+1}`]});e.addResource("EFSSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for EFS mount targets",VpcId:d.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:2049,ToPort:2049,SourceSecurityGroupId:d.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:d.sub("${AWS::StackName}-efs-sg")}]},{dependsOn:"VPC"}),e.addOutputs({[`${r}Id`]:{Description:`${t} EFS file system ID`,Value:d.ref(r),Export:{Name:d.sub(`\${AWS::StackName}-${t}-efs`)}}})}class $a{template;config;resourceDependencies;constructor(e){this.config=e,this.resourceDependencies=new Map,this.template={AWSTemplateFormatVersion:"2010-09-09",Description:`Infrastructure for ${e.project.name} (${e.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:d.equals(d.ref("Environment"),"production"),HasDomain:d.not([d.equals(this.config.environments?.production?.domain||"","")])}}addResources(){let{infrastructure:e}=this.config;if(!e)return;if(e.network)this.addNetworkResources(e.network);if(e.storage)this.addStorageResources(e.storage);if(e.compute)this.addComputeResources(e.compute);if(e.databases)this.addDatabaseResources(e.databases);if(e.cache)this.addCacheResources(e.cache);if(e.cdn)this.addCDNResources(e.cdn);if(e.apiGateway)this.addApiGatewayResources(e.apiGateway);if(e.functions)this.addFunctionResources(e.functions);if(e.queues)this.addQueueResources(e.queues);if(e.messaging)this.addMessagingResources(e.messaging);if(e.monitoring)this.addMonitoringResources(e.monitoring);if(e.security)this.addSecurityResources(e.security)}initializeOutputs(){let e=this.template.Outputs||{};if(this.template.Outputs={StackName:{Description:"Stack name",Value:d.ref("AWS::StackName"),Export:{Name:d.sub("${AWS::StackName}-Name")}},Region:{Description:"AWS Region",Value:d.ref("AWS::Region"),Export:{Name:d.sub("${AWS::StackName}-Region")}},...e},this.config.environments?.production?.domain)this.template.Outputs.Domain={Description:"Production domain",Value:this.config.environments.production.domain,Condition:"HasDomain"}}addResource(e,t,a,r){let n={Type:t,Properties:a};if(r?.dependsOn)n.DependsOn=r.dependsOn,this.trackDependency(e,r.dependsOn);if(r?.condition)n.Condition=r.condition;if(r?.deletionPolicy)n.DeletionPolicy=r.deletionPolicy;if(r?.updateReplacePolicy)n.UpdateReplacePolicy=r.updateReplacePolicy;this.template.Resources[e]=n}addOutputs(e){this.template.Outputs={...this.template.Outputs,...e}}getOutputs(){return this.template.Outputs||{}}hasResource(e){return e in this.template.Resources}getResource(e){return this.template.Resources[e]}trackDependency(e,t){if(!this.resourceDependencies.has(e))this.resourceDependencies.set(e,new Set);(Array.isArray(t)?t:[t]).forEach((a)=>this.resourceDependencies.get(e).add(a))}resolveDependencies(){let e=new Set,t=new Set,a=(r)=>{if(t.has(r))throw Error(`Circular dependency detected involving resource: ${r}`);if(e.has(r))return!0;e.add(r),t.add(r);let n=this.resourceDependencies.get(r);if(n)for(let i of n)a(i);return t.delete(r),!0};for(let r of this.resourceDependencies.keys())a(r)}toLogicalId(e){return e.split(/[-_\s]/).map((t)=>t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()).join("")}addNetworkResources(e){fs(this,e)}addStorageResources(e){ws(this,e)}addComputeResources(e){ts(this,e)}addDatabaseResources(e){ns(this,e)}addFunctionResources(e){ss(this,e)}addCacheResources(e){Qi(this,e)}addQueueResources(e){Ss(this,e)}addMessagingResources(e){us(this,e)}addCDNResources(e){Zi(this,e)}addApiGatewayResources(e){ji(this,e)}addMonitoringResources(e){ms(this,e)}addSecurityResources(e){As(this,e)}}function Hl(e){return new $a(e).build()}function ql(e){let{name:t,slug:a,domain:r,subdomain:n}=e;return{project:{name:t,slug:a,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:n&&r?`${n}.${r}`:r}},infrastructure:{storage:{assets:{public:!0,versioning:!1,website:!0,encryption:!1,cors:[{allowedOrigins:["*"],allowedMethods:["GET","HEAD"],allowedHeaders:["*"],maxAge:3600}]}},cdn:{enabled:!0,customDomain:r?{domain:n&&r?`${n}.${r}`:r,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 zl(e){let{name:t,slug:a,domain:r,instanceType:n="t3.small",minInstances:i=2,maxInstances:s=10}=e;return{project:{name:t,slug:a,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:r}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:n,ami:"ubuntu-22.04",keyPair:`${a}-key`,autoScaling:{min:i,max:s,desired:i,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:r?{domain:r,subdomains:[`*.${r}`],validationMethod:"DNS"}:void 0}}}}function Jl(e){let{name:t,slug:a,domain:r,taskCpu:n="256",taskMemory:i="512",desiredCount:s=2}=e;return{project:{name:t,slug:a,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:r}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:0}},compute:{fargate:{taskDefinition:{cpu:n,memory:i,containerDefinitions:[{name:"app",image:`${a}-app:latest`,portMappings:[{containerPort:3000}],environment:[],secrets:[]}]},service:{desiredCount:s,healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3},autoScaling:{min:s,max:s*5,targetCPU:70,targetMemory:80}},loadBalancer:{type:"application"}}},databases:{dynamodb:{tables:{[`${a}-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:`${a}-queue`}]}},security:{certificate:r?{domain:r,subdomains:[`*.${r}`],validationMethod:"DNS"}:void 0}}}}function Ql(e){let{name:t,slug:a,entry:r,domain:n,runtime:i="nodejs20.x",memory:s=1024,build:o,deploy:c,assets:l,queues:u=!0,scheduler:m="on",region:p="us-east-1"}=e;return{project:{name:t,slug:a,region:p},mode:"serverless",environments:{production:{type:"production",domain:n,app:{kind:"node",runtime:i,entry:r,memory:s,build:o,deploy:c,assets:l,queues:u,scheduler:m,domain:n}}}}}function $l(e){let t=e.database!==!1,a=e.cache!==!1,r=e.queue!==!1;return{project:{name:e.name,slug:e.slug,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:e.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:e.imageUri,portMappings:[{containerPort:3000}],environment:[{name:"NODE_ENV",value:"production"},{name:"PORT",value:"3000"},{name:"AWS_REGION",value:d.ref("AWS::Region")},...t?[{name:"DB_HOST",value:d.getAtt("PostgresDb","Endpoint.Address")},{name:"DB_PORT",value:d.getAtt("PostgresDb","Endpoint.Port")}]:[],...a?[{name:"REDIS_HOST",value:d.getAtt("RedisReplicationGroup","PrimaryEndPoint.Address")},{name:"REDIS_PORT",value:d.getAtt("RedisReplicationGroup","PrimaryEndPoint.Port")},{name:"REDIS_TLS",value:"true"}]:[],...r?[{name:"QUEUE_URL",value:d.ref("JobsQueue")}]:[],{name:"MAIL_TRANSPORT",value:"ses"}],secrets:t?[{name:"DB_USERNAME",valueFrom:d.sub("${DBSecret}:username::")},{name:"DB_PASSWORD",valueFrom:d.sub("${DBSecret}:password::")}]:[]}]},service:{desiredCount:e.desiredCount||1,healthCheck:{path:"/api/health",interval:30,timeout:5},autoScaling:{min:e.desiredCount||1,max:6,targetCPU:70}},loadBalancer:{type:"application",...e.certificateArn?{customDomain:{domain:e.domain,certificateArn:e.certificateArn}}:{},...e.originVerifySecret?{originVerifyHeader:{name:"X-Origin-Verify",value:e.originVerifySecret}}:{}}}},...t?{databases:{postgres:{engine:"postgres",version:"16",instanceClass:"db.t4g.micro",allocatedStorage:20,maxAllocatedStorage:100,multiAZ:!1,backupRetentionDays:7,deletionProtection:!0}}}:{},...a?{cache:{redis:{nodeType:"cache.t4g.micro",numCacheNodes:2,engine:"redis",engineVersion:"7.1",automaticFailoverEnabled:!0,snapshotRetentionLimit:5}}}:{},...r?{queues:{jobs:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0,maxReceiveCount:3,receiveMessageWaitTime:20}}}:{}}}}function Yl(e){let{name:t,slug:a,domain:r,apiSubdomain:n="api"}=e;return{project:{name:t,slug:a,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:r}},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:r,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:`${a}-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:`${n}.${r}`,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:r,subdomains:[`*.${r}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss"]}}}}}function Xl(e){let{name:t,slug:a,domain:r}=e;return{project:{name:t,slug:a,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:r}},infrastructure:{apiGateway:{type:"HTTP",cors:{allowOrigins:["*"],allowMethods:["GET","POST","PUT","DELETE","PATCH"],allowHeaders:["Content-Type","Authorization"],maxAge:3600},customDomain:r?{domain:r,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:{[`${a}-users`]:{partitionKey:{name:"userId",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0,globalSecondaryIndexes:[{name:"EmailIndex",partitionKey:{name:"email",type:"S"},projection:"ALL"}]},[`${a}-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:r?{domain:r,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 Zl(e){let{name:t,slug:a,domain:r,instanceType:n="t3.small"}=e;return{project:{name:t,slug:a,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:r}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:n,ami:"ubuntu-22.04",keyPair:`${a}-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:r,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,origins:[{type:"alb",pathPattern:"/wp-content/*"}]},security:{certificate:{domain:r,subdomains:[`www.${r}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss","wordpressRules"]}}}}}function eu(e){let{name:t,slug:a,domain:r,apiDomain:n}=e;return{project:{name:t,slug:a,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:r}},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:r,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},...n?{api:{runtime:"nodejs20.x",handler:"dist/api/index.handler",memory:1024,timeout:30,events:[{type:"http",path:"/{proxy+}",method:"ANY"}]}}:{}},apiGateway:n?{type:"HTTP",customDomain:{domain:n,certificateArn:"TO_BE_GENERATED"},cors:{allowOrigins:[r],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:r,subdomains:n?[n]:[],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","geoBlock"]}}}}}function tu(e){let{name:t,slug:a,domain:r,services:n}=e;return{project:{name:t,slug:a,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:r}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:3,natGateways:2}},compute:{services:n.map((i)=>({name:i.name,type:"fargate",taskDefinition:{cpu:i.cpu||"256",memory:i.memory||"512",containerDefinitions:[{name:i.name,image:`${a}-${i.name}:latest`,portMappings:[{containerPort:i.port}],healthCheck:{command:["CMD-SHELL",`curl -f http://localhost:${i.port}/health || exit 1`],interval:30,timeout:5,retries:3}}]},service:{desiredCount:i.desiredCount||2,serviceDiscovery:{enabled:!0,namespace:`${a}.local`},autoScaling:{min:2,max:10,targetCPU:70}}}))},apiGateway:{type:"HTTP",customDomain:{domain:r,certificateArn:"TO_BE_GENERATED"},cors:{allowOrigins:["*"],allowMethods:["GET","POST","PUT","DELETE","PATCH"]},routes:n.map((i)=>({path:`/${i.name}/{proxy+}`,integration:{type:"vpc-link",service:i.name}}))},databases:{dynamodb:{tables:Object.fromEntries(n.map((i)=>[`${a}-${i.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:`${a}-events`,subscriptions:n.map((i)=>({protocol:"sqs",endpoint:`${a}-${i.name}-queue`,filterPolicy:{service:[i.name]}}))}}},monitoring:{dashboard:{name:`${a}-microservices`,widgets:n.map((i)=>({type:"metric",metrics:[{service:i.name,metric:"CPUUtilization"},{service:i.name,metric:"MemoryUtilization"},{service:i.name,metric:"RequestCount"}]}))},alarms:n.flatMap((i)=>[{name:`${i.name}-high-cpu`,metric:"CPUUtilization",threshold:80,service:i.name},{name:`${i.name}-errors`,metric:"Errors",threshold:10,service:i.name}])},security:{certificate:{domain:r,validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection"]}}}}}function au(e){let{name:t,slug:a,domain:r}=e;return{project:{name:t,slug:a,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:r}},infrastructure:{apiGateway:{type:"websocket",customDomain:r?{domain:r,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:`${a}-messages`,startingPosition:"LATEST",batchSize:100}]}},databases:{dynamodb:{tables:{[`${a}-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"}]},[`${a}-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"}]},[`${a}-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:`${a}-realtime`,widgets:[{type:"metric",metrics:["WebSocketConnections","MessagesSent","IntegrationLatency"]}]}},security:{certificate:r?{domain:r,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","connectionLimit"]}}}}}function ru(e){let{name:t,slug:a,retentionDays:r=7}=e;return{project:{name:t,slug:a,region:"us-east-1"},mode:"serverless",infrastructure:{streaming:{dataStream:{name:`${a}-stream`,shardCount:2,retentionPeriod:r*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:`${a}-stream`,batchSize:1000,startingPosition:"LATEST",parallelizationFactor:10}]},transformer:{runtime:"nodejs20.x",handler:"dist/processors/transform.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${a}-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:`${a}_analytics`,workgroup:`${a}-workgroup`,outputBucket:`${a}-query-results`,tables:[{name:"raw_events",location:`s3://${a}-raw/events/`,format:"parquet",partitionKeys:["year","month","day"]},{name:"processed_events",location:`s3://${a}-processed/events/`,format:"parquet",partitionKeys:["year","month","day"]}]},glue:{crawlers:[{name:`${a}-crawler`,databaseName:`${a}_analytics`,s3Targets:[`s3://${a}-raw/`,`s3://${a}-processed/`],schedule:"cron(0 2 * * ? *)"}],jobs:[{name:`${a}-etl-job`,scriptLocation:`s3://${a}-scripts/etl.py`,role:`${a}-glue-role`,maxCapacity:10,timeout:120}]}},databases:{dynamodb:{tables:{[`${a}-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:`${a}-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:`${a}-pipeline`,widgets:[{type:"metric",metrics:["KinesisIncomingRecords","LambdaInvocations","S3ObjectsCreated","GlueJobsSucceeded"]}]},alarms:[{metric:"LambdaErrors",threshold:10,evaluationPeriods:1},{metric:"KinesisIteratorAge",threshold:60000,evaluationPeriods:2}]}}}}function nu(e){let{name:t,slug:a,domain:r,modelS3Path:n=`s3://${a}-models/`,instanceType:i="ml.t3.medium"}=e;return{project:{name:t,slug:a,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:r}},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:`${a}-inference`,modelS3Path:n,instanceType:i,initialInstanceCount:1,autoScaling:{minInstances:1,maxInstances:5,targetInvocationsPerInstance:1000}}],trainingJobs:[{name:`${a}-training`,algorithmSpecification:{trainingImage:"TO_BE_SPECIFIED",trainingInputMode:"File"},instanceType:"ml.p3.2xlarge",instanceCount:1,volumeSizeInGB:50,maxRuntimeInSeconds:86400}]}},apiGateway:{type:"HTTP",customDomain:r?{domain:r,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:`${a}-inference`,MODEL_BUCKET:`${a}-models`}},"batch-predict":{runtime:"python3.11",handler:"handlers/batchPredict.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${a}-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:{[`${a}-predictions`]:{partitionKey:{name:"requestId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0},[`${a}-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:`${a}-ml`,widgets:[{type:"metric",metrics:["SageMakerInvocations","SageMakerModelLatency","APIGatewayRequests","LambdaErrors"]}]},alarms:[{metric:"SageMakerModelLatency",threshold:1000,evaluationPeriods:2},{metric:"SageMakerInvocationErrors",threshold:10,evaluationPeriods:1}]},security:{certificate:r?{domain:r,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","apiProtection"]}}}}}function iu(e){let{name:t,slug:a,domain:r,instanceType:n="t3.medium",minInstances:i=2,maxInstances:s=10,databaseEngine:o="mysql",sessionStore:c="redis"}=e;return{project:{name:t,slug:a,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:r}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:2}},compute:{server:{instanceType:n,ami:"ubuntu-22.04",autoScaling:{min:i,max:s,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:[r||"*"],allowedMethods:["GET","HEAD"]}]}},cdn:{enabled:!0,origins:[{originId:"static-assets",domainName:`${a}-static.s3.amazonaws.com`,pathPattern:"/static/*"}],customDomain:r?{domain:r,certificateArn:"TO_BE_GENERATED"}:void 0,cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0},databases:o==="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:c==="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:`${a}-jobs`,batchSize:10}]},"email-sender":{runtime:"nodejs20.x",handler:"dist/workers/email.handler",memory:512,timeout:60,events:[{type:"sqs",queueName:`${a}-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:`${a}-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:[`${a}-app`,`${a}-nginx`,`${a}-workers`]}},security:{certificate:r?{domain:r,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:o==="mysql"?3306:5432,protocol:"tcp",source:"app-sg"}]},...c==="redis"&&{cache:{ingress:[{port:6379,protocol:"tcp",source:"app-sg"}]}}}}}}}function ou(e){let{name:t,slug:a,domain:r,repository:n,phpVersion:i="8.3",size:s="small",database:o=a.replace(/-/g,"_"),databasePassword:c,sslEmail:l,deployStrategy:u="push",provider:m="hetzner"}=e;return{project:{name:t,slug:a,region:"us-east-1"},mode:"server",cloud:{provider:m},environments:{production:{type:"production",domain:r}},infrastructure:{compute:{mode:"server",size:s,runtime:"php",webServer:"nginx",php:{versions:[i],default:i},managedServices:{mysql:!0,redis:!0},firewall:{enabled:!0},autoUpdates:!0,monitoring:!0,backups:{enabled:!0,schedule:"0 2 * * *",retentionCount:7}},appDatabase:{engine:"mysql",name:o,username:o,password:c}},sites:{main:{root:".",type:"laravel",domain:r,phpVersion:i,repository:{...n,strategy:u},scheduler:!0,queues:[{connection:"redis",queue:"default",processes:1}],ssl:{provider:"letsencrypt",email:l}}}}}function cu(e){let{name:t,slug:a,domain:r,layers:n,phpVersion:i="8.3",architecture:s="x86_64",memory:o=1024,build:c,deploy:l=["migrate --force"],cache:u="dynamodb",scheduler:m="on",region:p="us-east-1"}=e;return{project:{name:t,slug:a,region:p},mode:"serverless",environments:{production:{type:"production",domain:r,app:{kind:"php",runtime:"provided.al2023",phpVersion:i,architecture:s,layers:n,memory:o,build:c,deploy:l,assets:"public",queues:!0,scheduler:m,cache:{driver:u},domain:r}}}}}function lu(e){return{root:e.root??"packages/ui/dist",deploy:"server",type:"static",domain:e.domain,build:e.build??"cd packages/ui && bun install && bun run build",ssl:{provider:"letsencrypt"},auth:{username:e.username??"admin",password:e.password}}}var Rs=Ua,Ns="./node_modules/@stacksjs/ts-cloud/dist/bin/dashboard-server.js";function Ds(e){let t=e.split(".").filter(Boolean);return t.length<=2?e:t.slice(-2).join(".")}function ks(e){let t=2166136261;for(let a=0;a<e.length;a++)t^=e.charCodeAt(a),t=Math.imul(t,16777619);return t>>>0}var $s=20000,Ls=12000;function Ms(e){return $s+ks(e)%Ls}function Za(e,t){let a=Ds(e);if(a===e)return`dashboard.${a}`;for(let r of t)if(r===a)return`dashboard.${a}`;return`dashboard.${e}`}function Xa(e,t){let a=[],r=e.infrastructure?.dns?.domain;if(r&&!e.cloud?.attachTo)a.push(r);if(t&&e.environments?.[t]?.domain)a.push(e.environments[t].domain);for(let n of Object.values(e.sites??{})){let i=n;if(!i||i.redirect)continue;let s=i.domain;if(typeof s==="string")a.push(s);else if(Array.isArray(s))a.push(...s.filter((o)=>typeof o==="string"))}return a.filter((n)=>n&&!n.startsWith("dashboard."))}function xs(e,t,a){if(a)return a;let r=Xa(e,t),n=r[0];if(!n)return null;return Za(n,r)}function Os(e,t,a){if(a)return[a];let r=Xa(e,t),n=[];for(let i of r){let s=Za(i,r);if(!n.includes(s))n.push(s)}return n}function Bs(e){return Object.entries(e.sites??{}).some(([t,a])=>{if(!a)return!1;let r=a.root??"";return _s(t)||r==="ui/dist"||r.endsWith("/ui/dist")||r.endsWith("/dist/ui")})}var er="dashboard-";function Aa(e){return er+e.replace(/^dashboard\./,"").replace(/\./g,"-")}function _s(e){return e==="dashboard"||e.startsWith(er)}function Ws(e,t,a){if(Bs(e))return[];if(e.cloud?.attachTo)return[];let r=a.password?{auth:{username:a.username||"admin",password:a.password,realm:a.realm}}:{},n=a.build===!1||a.build===void 0?{}:{build:a.build};if(a.live!==!1){let i=xs(e,t,a.domain);if(!i)return[];let s=a.port??Ms(i),o=e.infrastructure?.appDatabase??e.infrastructure?.compute?.database,c={root:a.uiRoot,deploy:"server",domain:i,preStart:["bun install --production --no-save"],start:`bun ${Ns} --box --host 127.0.0.1 --port ${s}`,port:s,cpuWeight:10,ioWeight:10,tasksMax:128,env:{APP_ENV:"production",NODE_ENV:"production",TS_CLOUD_DASHBOARD_TELEMETRY:"1",...o?.password?{TS_CLOUD_DASHBOARD_DB_PASSWORD:o.password}:{}},zeroDowntime:!1,sharedPaths:[Rs],healthCheck:{path:"/login"},ssl:{provider:"letsencrypt"}};return[{name:Aa(i),site:c}]}return Os(e,t,a.domain).map((i)=>({name:Aa(i),site:{root:a.uiRoot,deploy:"server",type:"static",domain:i,ssl:{provider:"letsencrypt"},...n,...r}}))}function uu(e,t,a){return Ws(e,t,a)[0]??null}function Jt(e,t){let a={...e};for(let r in t){let n=t[r],i=a[r];if(n===void 0)continue;if(Array.isArray(n)&&Array.isArray(i))a[r]=[...i,...n];else if(typeof n==="object"&&n!==null&&!Array.isArray(n)&&typeof i==="object"&&i!==null&&!Array.isArray(i))a[r]=Jt(i,n);else a[r]=n}return a}function Ca(e,t){return Jt(e,t)}function du(...e){return e.reduce((t,a)=>Jt(t,a),{})}function mu(e,t){return(a)=>{let r=e(a);if(typeof t==="function")return Ca(r,t(r,a));return Ca(r,t)}}function Ge(e){return{infrastructure:e}}function pu(e){return Ge({monitoring:e})}function gu(e){return Ge({security:e})}function hu(e){return Ge({databases:e})}function yu(e){return Ge({cache:e})}function fu(e){return Ge({cdn:e})}function Su(e){return Ge({queues:e})}rt();function Gs(){let e=process.env.AWS_ACCESS_KEY_ID,t=process.env.AWS_SECRET_ACCESS_KEY;if(!e||!t)return null;return{accessKeyId:e,secretAccessKey:t,sessionToken:process.env.AWS_SESSION_TOKEN}}function Fs(e){let t=e?.profile||process.env.AWS_PROFILE||"default",a=e?.credentialsFile||rr(ar(),".aws","credentials");if(!tr(a))return null;try{let r=Yt(a,"utf-8");return Vs(r,t)}catch{return null}}function Vs(e,t){let a=e.split(`
2494
- `),r=null,n,i,s;for(let o of a){let c=o.trim();if(!c||c.startsWith("#")||c.startsWith(";"))continue;let l=c.match(/^\[([^\]]+)\]$/);if(l){if(r===t&&n&&i)return{accessKeyId:n,secretAccessKey:i,sessionToken:s};r=l[1],n=void 0,i=void 0,s=void 0;continue}if(r===t){let[u,...m]=c.split("="),p=m.join("=").trim();switch(u.trim().toLowerCase()){case"aws_access_key_id":n=p;break;case"aws_secret_access_key":i=p;break;case"aws_session_token":s=p;break}}}if(r===t&&n&&i)return{accessKeyId:n,secretAccessKey:i,sessionToken:s};return null}async function Us(e){let t=e?.timeout??1000,a="http://169.254.169.254";try{let r=await et("http://169.254.169.254/latest/api/token",{method:"PUT",headers:{"X-aws-ec2-metadata-token-ttl-seconds":"21600"}},t);if(!r.ok)return null;let n=await r.text(),i=await et("http://169.254.169.254/latest/meta-data/iam/security-credentials/",{headers:{"X-aws-ec2-metadata-token":n}},t);if(!i.ok)return null;let s=(await i.text()).trim(),o=await et(`http://169.254.169.254/latest/meta-data/iam/security-credentials/${s}`,{headers:{"X-aws-ec2-metadata-token":n}},t);if(!o.ok)return null;let c=await o.json();return{accessKeyId:c.AccessKeyId,secretAccessKey:c.SecretAccessKey,sessionToken:c.Token,expiration:new Date(c.Expiration)}}catch{return null}}async function js(e){let t=e?.timeout??1000,a=process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI,r=process.env.AWS_CONTAINER_CREDENTIALS_FULL_URI,n=null;if(a)n=`http://169.254.170.2${a}`;else if(r)n=r;if(!n)return null;try{let i={},s=process.env.AWS_CONTAINER_AUTHORIZATION_TOKEN;if(s)i.Authorization=s;let o=await et(n,{headers:i},t);if(!o.ok)return null;let c=await o.json();return{accessKeyId:c.AccessKeyId,secretAccessKey:c.SecretAccessKey,sessionToken:c.Token,expiration:new Date(c.Expiration)}}catch{return null}}async function Ks(e){let t=e?.timeout??5000,a=process.env.AWS_WEB_IDENTITY_TOKEN_FILE,r=process.env.AWS_ROLE_ARN,n=process.env.AWS_ROLE_SESSION_NAME||"ts-cloud-session";if(!a||!r)return null;try{let i=Yt(a,"utf-8").trim(),s=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION||"us-east-1",o=s.startsWith("us-gov")?`https://sts.${s}.amazonaws.com`:s==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${s}.amazonaws.com`,c=new URLSearchParams({Action:"AssumeRoleWithWebIdentity",Version:"2011-06-15",RoleArn:r,RoleSessionName:n,WebIdentityToken:i}),l=await et(`${o}/?${c.toString()}`,{method:"POST"},t);if(!l.ok)return null;let u=await l.text(),m=Ye(u,"AccessKeyId"),p=Ye(u,"SecretAccessKey"),g=Ye(u,"SessionToken"),h=Ye(u,"Expiration");if(!m||!p)return null;return{accessKeyId:m,secretAccessKey:p,sessionToken:g??void 0,expiration:h?new Date(h):void 0}}catch{return null}}async function Rt(e){let t=Gs();if(t)return t;let a=Fs(e);if(a)return a;let r=await Ks(e);if(r)return r;let n=await js(e);if(n)return n;let i=await Us(e);if(i)return i;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 Tu(e){let t=null,a=null;return async()=>{if(t){if(!t.expiration)return t;let r=300000;if(t.expiration.getTime()-Date.now()>r)return t}if(a)return a;return a=Rt(e).then((r)=>(t=r,a=null,r)).catch((r)=>{throw a=null,r}),a}}async function et(e,t,a){let r=new AbortController,n=setTimeout(()=>r.abort(),a);try{let i=await fetch(e,{...t,signal:r.signal});return clearTimeout(n),i}catch(i){throw clearTimeout(n),i}}function Ye(e,t){let a=new RegExp(`<${t}>([^<]+)</${t}>`),r=e.match(a);return r?r[1]:null}async function Zt(e){return Rt({profile:e})}function Hs(e){let t=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION;if(t)return t;let a=rr(ar(),".aws","config");if(tr(a))try{let r=Yt(a,"utf-8"),n=e||process.env.AWS_PROFILE||"default",i=n==="default"?"[default]":`[profile ${n}]`,s=r.split(`
2495
- `),o=!1;for(let c of s){let l=c.trim();if(l.startsWith("[")){o=l===i;continue}if(o&&l.startsWith("region")){let[,u]=l.split("=");if(u)return u.trim()}}}catch{}return"us-east-1"}async function qs(e){let t=e||await Rt(),a=Hs(),{signRequest:r}=await rt().then(()=>La),n=a.startsWith("us-gov")?`https://sts.${a}.amazonaws.com`:a==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${a}.amazonaws.com`,i="Action=GetCallerIdentity&Version=2011-06-15",s=r({method:"POST",url:n,body:"Action=GetCallerIdentity&Version=2011-06-15",headers:{"Content-Type":"application/x-www-form-urlencoded"},...t,service:"sts",region:a}),o=await fetch(s.url,{method:s.method,headers:s.headers,body:s.body});if(!o.ok)throw Error(`Failed to get account ID: ${await o.text()}`);let c=await o.text(),l=Ye(c,"Account");if(!l)throw Error("Failed to parse account ID from response");return l}await rt();class zs{profile;credentials=null;region;constructor(e="us-east-1",t="default"){this.profile=t,this.region=e}async init(){if(this.credentials=await Zt(this.profile),this.credentials.region)this.region=this.credentials.region}async ensureCredentials(){if(!this.credentials)await this.init();return this.credentials}async request(e,t){let a=await this.ensureCredentials(),r={Action:e,Version:"2010-05-15",...Kt(t)},n=new URLSearchParams(r).toString(),i=await(await _e({method:"POST",url:`https://cloudformation.${this.region}.amazonaws.com/`,service:"cloudformation",region:this.region,headers:{"Content-Type":"application/x-www-form-urlencoded"},body:n,accessKeyId:a.accessKeyId,secretAccessKey:a.secretAccessKey,sessionToken:a.sessionToken})).text();return Qs(i)}async createStack(e){let t={StackName:e.stackName};if(e.templateBody)t.TemplateBody=e.templateBody;else if(e.templateURL)t.TemplateURL=e.templateURL;else throw Error("Either templateBody or templateURL must be provided");if(e.parameters)for(let[r,[n,i]]of Object.entries(e.parameters).entries())t[`Parameters.member.${r+1}.ParameterKey`]=n,t[`Parameters.member.${r+1}.ParameterValue`]=i;if(e.capabilities)for(let[r,n]of e.capabilities.entries())t[`Capabilities.member.${r+1}`]=n;if(e.tags)for(let[r,[n,i]]of Object.entries(e.tags).entries())t[`Tags.member.${r+1}.Key`]=n,t[`Tags.member.${r+1}.Value`]=i;if(e.timeoutInMinutes)t.TimeoutInMinutes=e.timeoutInMinutes;if(e.onFailure)t.OnFailure=e.onFailure;let a=await this.request("CreateStack",t);return(a?.CreateStackResult||a?.CreateStackResponse?.CreateStackResult||a)?.StackId}async updateStack(e){let t={StackName:e.stackName};if(e.templateBody)t.TemplateBody=e.templateBody;else if(e.templateURL)t.TemplateURL=e.templateURL;if(e.parameters)for(let[r,[n,i]]of Object.entries(e.parameters).entries())t[`Parameters.member.${r+1}.ParameterKey`]=n,t[`Parameters.member.${r+1}.ParameterValue`]=i;if(e.capabilities)for(let[r,n]of e.capabilities.entries())t[`Capabilities.member.${r+1}`]=n;if(e.tags)for(let[r,[n,i]]of Object.entries(e.tags).entries())t[`Tags.member.${r+1}.Key`]=n,t[`Tags.member.${r+1}.Value`]=i;let a=await this.request("UpdateStack",t);return(a?.UpdateStackResult||a?.UpdateStackResponse?.UpdateStackResult||a)?.StackId}async deleteStack(e){await this.request("DeleteStack",{StackName:e})}async describeStack(e){let t=await this.request("DescribeStacks",{StackName:e}),a=(t?.DescribeStacksResult||t?.DescribeStacksResponse?.DescribeStacksResult||t)?.Stacks?.member,r=Array.isArray(a)?a[0]:a;if(!r)throw Error(`Stack ${e} not found`);return Js(r)}async listStacks(e){let t={};if(e)for(let[r,n]of e.entries())t[`StackStatusFilter.member.${r+1}`]=n;let a=await this.request("ListStacks",t);return Ys(a)}async describeStackEvents(e){let t=await this.request("DescribeStackEvents",{StackName:e});return Zs(t)}async waitForStack(e,t,a){let r=0,n=null;while(r<360){r++;let i=await this.describeStack(e);if(a)try{let s=await this.describeStackEvents(e),o=[];if(n){for(let c of s){if(c.EventId===n)break;o.push(c)}o.reverse()}else if(s.length>0)o=[s[0]];for(let c of o)a(c);if(s.length>0)n=s[0].EventId}catch{}if(i.StackStatus&&t.includes(i.StackStatus))return i;if(i.StackStatus?.includes("FAILED")||i.StackStatus?.includes("ROLLBACK"))throw Error(`Stack reached failed state: ${i.StackStatus}
2496
- Reason: ${i.StackStatusReason||"Unknown"}`);await new Promise((s)=>setTimeout(s,5000))}throw Error(`Timeout waiting for stack ${e} to complete`)}async waitForStackWithProgress(e,t,a){let r={"stack-create-complete":["CREATE_COMPLETE"],"stack-update-complete":["UPDATE_COMPLETE"],"stack-delete-complete":["DELETE_COMPLETE"]}[t];if(!r)throw Error(`Unknown waiter: ${t}`);return this.waitForStack(e,r,a)}async createChangeSet(e){let t={StackName:e.stackName,ChangeSetName:e.changeSetName,ChangeSetType:"UPDATE"};if(e.templateBody)t.TemplateBody=e.templateBody;else if(e.templateURL)t.TemplateURL=e.templateURL;if(e.parameters)for(let[a,[r,n]]of Object.entries(e.parameters).entries())t[`Parameters.member.${a+1}.ParameterKey`]=r,t[`Parameters.member.${a+1}.ParameterValue`]=n;if(e.capabilities)for(let[a,r]of e.capabilities.entries())t[`Capabilities.member.${a+1}`]=r;return(await this.request("CreateChangeSet",t)).ChangeSetId}async executeChangeSet(e,t){await this.request("ExecuteChangeSet",{ChangeSetName:e,StackName:t})}async describeStacks(e){let t=typeof e==="string"?e:e.stackName;try{return{Stacks:[await this.describeStack(t)]}}catch{return{Stacks:[]}}}async getStackOutputs(e){let t=await this.request("DescribeStacks",{StackName:e}),a=(t?.DescribeStacksResult||t?.DescribeStacksResponse?.DescribeStacksResult||t)?.Stacks?.member,r=Array.isArray(a)?a[0]:a;if(!r)return{};let n={},i=r.Outputs?.member;if(i){let s=Array.isArray(i)?i:[i];for(let o of s)if(o.OutputKey&&o.OutputValue)n[o.OutputKey]=o.OutputValue}return n}}function Kt(e,t=""){let a={};for(let[r,n]of Object.entries(e)){let i=t?`${t}.${r}`:r;if(Array.isArray(n))n.forEach((s,o)=>{if(typeof s==="object")Object.assign(a,Kt(s,`${i}.${o+1}`));else a[`${i}.${o+1}`]=String(s)});else if(typeof n==="object"&&n!==null)Object.assign(a,Kt(n,i));else if(n!==void 0&&n!==null)a[i]=String(n)}return a}function Qs(e){e=e.replace(/<\?xml[^?]*\?>\s*/,"").trim();function t(r,n,i){let s=1,o=i,c=`<${n}`,l=`</${n}>`;while(o<r.length&&s>0){let u=r.indexOf(c,o),m=r.indexOf(l,o);if(m===-1)return-1;if(u!==-1&&u<m){let p=r[u+c.length];if(p===">"||p===" "||p==="/"){let g=r.indexOf(">",u);if(g!==-1&&r[g-1]==="/")o=g+1;else s++,o=g+1}else o=u+c.length}else{if(s--,s===0)return m;o=m+l.length}}return-1}function a(r,n){while(n<r.length&&/\s/.test(r[n]))n++;if(n>=r.length||r[n]!=="<"){let g=r.indexOf("<",n);if(g===-1)return{value:r.slice(n).trim(),end:r.length};return{value:r.slice(n,g).trim(),end:g}}if(r[n+1]==="/")return{value:void 0,end:n};let i=r.slice(n).match(/^<(\w+)([^>]*?)\/?>/);if(!i)return{value:void 0,end:n+1};let s=i[1];if(i[0].endsWith("/>"))return{value:"",end:n+i[0].length};let o=n+i[0].length,c=`</${s}>`,l=t(r,s,o);if(l===-1)return{value:void 0,end:n+i[0].length};let u=r.slice(o,l).trim();if(!u.includes("<"))return{value:u,end:l+c.length};let m={},p=o;while(p<l){while(p<l&&/\s/.test(r[p]))p++;if(p>=l)break;if(r[p]!=="<"||r[p+1]==="/")break;let g=r.slice(p).match(/^<(\w+)/);if(!g)break;let h=g[1],y=a(r,p);if(y.value===void 0){p++;continue}if(h==="member"||m[h]!==void 0){if(!Array.isArray(m[h]))m[h]=m[h]!==void 0?[m[h]]:[];m[h].push(y.value)}else m[h]=y.value;p=y.end}return{value:m,end:l+c.length}}return a(e,0).value||{}}function Js(e){return{StackName:e.StackName||"",StackId:e.StackId,StackStatus:e.StackStatus,CreationTime:e.CreationTime,LastUpdatedTime:e.LastUpdatedTime,StackStatusReason:e.StackStatusReason,Description:e.Description}}function Ys(e){let t=(e?.ListStacksResult||e?.ListStacksResponse?.ListStacksResult||e)?.StackSummaries?.member;if(!t)return[];return(Array.isArray(t)?t:[t]).map((a)=>({StackName:a.StackName||"",StackId:a.StackId,StackStatus:a.StackStatus,CreationTime:a.CreationTime,LastUpdatedTime:a.LastUpdatedTime,StackStatusReason:a.StackStatusReason,Description:a.Description}))}function Zs(e){let t=(e?.DescribeStackEventsResult||e?.DescribeStackEventsResponse?.DescribeStackEventsResult||e)?.StackEvents?.member;if(!t)return[];return(Array.isArray(t)?t:[t]).map((a)=>({StackId:a.StackId||"",EventId:a.EventId||"",StackName:a.StackName||"",LogicalResourceId:a.LogicalResourceId||"",PhysicalResourceId:a.PhysicalResourceId,ResourceType:a.ResourceType||"",Timestamp:a.Timestamp||"",ResourceStatus:a.ResourceStatus||"",ResourceStatusReason:a.ResourceStatusReason}))}await rt();var Xs=5242880,Ot=5242880,eo=5242880;class nr{region;endpoint;forcePathStyle;credentials;credentialOptions;retryOptions;constructor(e={}){this.region=e.region||process.env.AWS_REGION||"us-east-1",this.endpoint=e.endpoint||`https://s3.${this.region}.amazonaws.com`,this.forcePathStyle=e.forcePathStyle||!1,this.credentials=e.credentials,this.credentialOptions=e.credentialOptions,this.retryOptions=e.retryOptions||{}}async getCredentials(){if(this.credentials)return this.credentials;return Rt(this.credentialOptions)}buildUrl(e,t){let a=t?encodeURIComponent(t).replace(/%2F/g,"/"):"";if(this.forcePathStyle)return t?`${this.endpoint}/${e}/${a}`:`${this.endpoint}/${e}`;let r=new URL(this.endpoint);return r.hostname=`${e}.${r.hostname}`,t?`${r.origin}/${a}`:r.origin}async get(e,t,a={}){let r=await this.getCredentials(),n=this.buildUrl(e,t),i={};if(a.range)i.Range=a.range;if(a.ifModifiedSince)i["If-Modified-Since"]=a.ifModifiedSince.toUTCString();if(a.ifMatch)i["If-Match"]=a.ifMatch;if(a.ifNoneMatch)i["If-None-Match"]=a.ifNoneMatch;let s=new URL(n);if(a.responseContentType)s.searchParams.set("response-content-type",a.responseContentType);if(a.responseContentDisposition)s.searchParams.set("response-content-disposition",a.responseContentDisposition);let o=K({method:"GET",url:s.toString(),headers:i,...r,service:"s3",region:this.region}),c=await fetch(o.url,{method:o.method,headers:o.headers});if(!c.ok&&c.status!==304){let l=await c.text();throw new Z(`Failed to get object: ${l}`,c.status,e,t)}return c}async getText(e,t,a={}){return(await this.get(e,t,a)).text()}async getJSON(e,t,a={}){return(await this.get(e,t,a)).json()}async getBuffer(e,t,a={}){return(await this.get(e,t,a)).arrayBuffer()}async put(e,t,a,r={}){let n,i;if(typeof a==="string")n=new TextEncoder().encode(a).length,i=a;else if(a instanceof ArrayBuffer)n=a.byteLength,i=a;else if(a instanceof Uint8Array)n=a.byteLength,i=a;else if(a instanceof Blob)n=a.size,i=a;else return this.uploadMultipart(e,t,a,{...r,partSize:Ot});if(n>eo){let s=ro(i).stream();return this.uploadMultipart(e,t,s,{...r,partSize:Ot})}return this.putSimple(e,t,i,n,r)}async putSimple(e,t,a,r,n){let i=await this.getCredentials(),s=this.buildUrl(e,t),o={"Content-Length":String(r),"Content-Type":n.contentType||Ta(t)};if(n.contentEncoding)o["Content-Encoding"]=n.contentEncoding;if(n.cacheControl)o["Cache-Control"]=n.cacheControl;if(n.contentDisposition)o["Content-Disposition"]=n.contentDisposition;if(n.storageClass)o["x-amz-storage-class"]=n.storageClass;if(n.serverSideEncryption)o["x-amz-server-side-encryption"]=n.serverSideEncryption;if(n.acl)o["x-amz-acl"]=n.acl;if(n.tagging)o["x-amz-tagging"]=n.tagging;if(n.metadata)for(let[m,p]of Object.entries(n.metadata))o[`x-amz-meta-${m.toLowerCase()}`]=p;let c;if(typeof a==="string")c=a;else if(a instanceof Blob)c=await a.text();else c=new TextDecoder().decode(a instanceof ArrayBuffer?new Uint8Array(a):a);let l=K({method:"PUT",url:s,headers:o,body:c,...i,service:"s3",region:this.region}),u=await fetch(l.url,{method:l.method,headers:l.headers,body:a});if(!u.ok){let m=await u.text();throw new Z(`Failed to put object: ${m}`,u.status,e,t)}return{etag:(u.headers.get("ETag")||"").replace(/"/g,"")}}async delete(e,t){let a=await this.getCredentials(),r=this.buildUrl(e,t),n=K({method:"DELETE",url:r,...a,service:"s3",region:this.region}),i=await fetch(n.url,{method:n.method,headers:n.headers});if(!i.ok&&i.status!==204){let s=await i.text();throw new Z(`Failed to delete object: ${s}`,i.status,e,t)}}async deleteMany(e,t){let a=await this.getCredentials(),r=`${this.buildUrl(e)}?delete`,n=`<?xml version="1.0" encoding="UTF-8"?><Delete><Quiet>false</Quiet>${t.map((g)=>`<Object><Key>${ao(g)}</Key></Object>`).join("")}</Delete>`,i=K({method:"POST",url:r,headers:{"Content-Type":"application/xml"},body:n,...a,service:"s3",region:this.region}),s=await fetch(i.url,{method:i.method,headers:i.headers,body:n});if(!s.ok){let g=await s.text();throw new Z(`Failed to delete objects: ${g}`,s.status,e)}let o=await s.text(),c=[],l=[],u=/<Deleted><Key>([^<]+)<\/Key>/g,m;while((m=u.exec(o))!==null)c.push(m[1]);let p=/<Error><Key>([^<]+)<\/Key><Code>([^<]+)<\/Code><Message>([^<]+)<\/Message>/g;while((m=p.exec(o))!==null)l.push({key:m[1],error:`${m[2]}: ${m[3]}`});return{deleted:c,errors:l}}async list(e,t={}){let a=await this.getCredentials(),r=new URL(this.buildUrl(e));if(r.searchParams.set("list-type","2"),t.prefix)r.searchParams.set("prefix",t.prefix);if(t.delimiter)r.searchParams.set("delimiter",t.delimiter);if(t.maxKeys)r.searchParams.set("max-keys",String(t.maxKeys));if(t.continuationToken)r.searchParams.set("continuation-token",t.continuationToken);if(t.startAfter)r.searchParams.set("start-after",t.startAfter);let n=K({method:"GET",url:r.toString(),...a,service:"s3",region:this.region}),i=await fetch(n.url,{method:n.method,headers:n.headers});if(!i.ok){let o=await i.text();throw new Z(`Failed to list objects: ${o}`,i.status,e)}let s=await i.text();return to(s)}async*listAll(e,t={}){let a;do{let r=await this.list(e,{...t,continuationToken:a});for(let n of r.contents)yield n;a=r.nextContinuationToken}while(a)}async head(e,t){let a=await this.getCredentials(),r=this.buildUrl(e,t),n=K({method:"HEAD",url:r,...a,service:"s3",region:this.region}),i=await fetch(n.url,{method:n.method,headers:n.headers});if(i.status===404)return null;if(!i.ok){let o=await i.text();throw new Z(`Failed to head object: ${o}`,i.status,e,t)}let s={};return i.headers.forEach((o,c)=>{if(c.toLowerCase().startsWith("x-amz-meta-"))s[c.slice(11)]=o}),{contentLength:Number(i.headers.get("Content-Length")||0),contentType:i.headers.get("Content-Type")||"application/octet-stream",etag:(i.headers.get("ETag")||"").replace(/"/g,""),lastModified:new Date(i.headers.get("Last-Modified")||0),metadata:s,storageClass:i.headers.get("x-amz-storage-class")||void 0,serverSideEncryption:i.headers.get("x-amz-server-side-encryption")||void 0}}async exists(e,t){return await this.head(e,t)!==null}async copy(e,t,a,r,n={}){let i=await this.getCredentials(),s=this.buildUrl(a,r),o={"x-amz-copy-source":`/${e}/${encodeURIComponent(t)}`};if(n.metadataDirective)o["x-amz-metadata-directive"]=n.metadataDirective;if(n.contentType)o["Content-Type"]=n.contentType;if(n.storageClass)o["x-amz-storage-class"]=n.storageClass;if(n.acl)o["x-amz-acl"]=n.acl;if(n.metadata)for(let[m,p]of Object.entries(n.metadata))o[`x-amz-meta-${m.toLowerCase()}`]=p;let c=K({method:"PUT",url:s,headers:o,...i,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(!l.ok){let m=await l.text();throw new Z(`Failed to copy object: ${m}`,l.status,a,r)}let u=(await l.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:u?u[1]:""}}async getPresignedUrl(e,t,a={}){let r=await this.getCredentials(),n=this.buildUrl(e,t);return Ma({url:n,method:a.method||"GET",expiresIn:a.expiresIn||3600,...r,service:"s3",region:this.region})}async uploadMultipart(e,t,a,r={}){let n=await this.getCredentials(),i=Math.max(r.partSize||Ot,Xs),s,o;if(a instanceof ReadableStream)s=a;else if(a instanceof Blob)s=a.stream(),o=a.size;else{let u=new Blob([a]);s=u.stream(),o=u.size}let{uploadId:c,baseUrl:l}=await this.initiateMultipartUpload(e,t,r);try{let u=await this.uploadParts(e,t,l,c,s,i,n,o,r.concurrency||4,r.onProgress);return await this.completeMultipartUpload(e,t,l,c,u)}catch(u){throw await this.abortMultipartUpload(e,t,c,l).catch(()=>{}),u}}async initiateMultipartUpload(e,t,a){let r=await this.getCredentials(),n=this.buildUrl(e,t),i=`${n}?uploads`,s={"Content-Type":a.contentType||Ta(t)};if(a.storageClass)s["x-amz-storage-class"]=a.storageClass;if(a.serverSideEncryption)s["x-amz-server-side-encryption"]=a.serverSideEncryption;if(a.acl)s["x-amz-acl"]=a.acl;if(a.metadata)for(let[m,p]of Object.entries(a.metadata))s[`x-amz-meta-${m.toLowerCase()}`]=p;let o=K({method:"POST",url:i,headers:s,...r,service:"s3",region:this.region}),c=await fetch(o.url,{method:o.method,headers:o.headers});if(!c.ok){let m=await c.text();throw new Z(`Failed to initiate multipart upload: ${m}`,c.status,e,t)}let l=(await c.text()).match(/<UploadId>([^<]+)<\/UploadId>/);if(!l)throw new Z("Failed to parse upload ID from response",0,e,t);let u=n;if(c.url)try{let m=new URL(c.url);m.search="",u=m.toString()}catch{}return{uploadId:l[1],baseUrl:u}}async uploadParts(e,t,a,r,n,i,s,o,c,l){let u=[],m=n.getReader(),p=1,g=new Uint8Array(0),h=0,y=o?Math.ceil(o/i):void 0,b=new Map,T=async(S,E)=>{let v=`${a}?partNumber=${E}&uploadId=${encodeURIComponent(r)}`,P={"Content-Length":String(S.byteLength),"x-amz-content-sha256":"UNSIGNED-PAYLOAD"},N=K({method:"PUT",url:v,headers:P,...s,service:"s3",region:this.region}),I=await fetch(N.url,{method:N.method,headers:N.headers,body:S,redirect:"error"});if(!I.ok){let L=await I.text();throw new Z(`Failed to upload part ${E}: ${L}`,I.status,e,t)}let D=(I.headers.get("ETag")||"").replace(/"/g,"");if(!D)throw new Z(`Missing ETag for part ${E}`,I.status,e,t);return{partNumber:E,etag:D}},w=async()=>{let S=await Promise.race(b.values());b.delete(S.partNumber),u.push(S)};while(!0){let{done:S,value:E}=await m.read();if(E){let v=new Uint8Array(g.length+E.length);v.set(g),v.set(E,g.length),g=v}while(g.length>=i||S&&g.length>0){let v=g.slice(0,i);g=g.slice(i);let P=p++;if(b.size>=c)await w();if(b.set(P,T(v,P)),h+=v.byteLength,l)l({loaded:h,total:o||h,part:P,totalParts:y||P})}if(S)break}while(b.size>0)await w();return u.sort((S,E)=>S.partNumber-E.partNumber),u}async completeMultipartUpload(e,t,a,r,n){let i=await this.getCredentials(),s=`${a}?uploadId=${encodeURIComponent(r)}`,o=`<?xml version="1.0" encoding="UTF-8"?><CompleteMultipartUpload>${n.map((m)=>`<Part><PartNumber>${m.partNumber}</PartNumber><ETag>"${m.etag}"</ETag></Part>`).join("")}</CompleteMultipartUpload>`,c=K({method:"POST",url:s,headers:{"Content-Type":"application/xml"},body:o,...i,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers,body:o});if(!l.ok){let m=await l.text();throw new Z(`Failed to complete multipart upload: ${m}`,l.status,e,t)}let u=(await l.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:u?u[1]:""}}async abortMultipartUpload(e,t,a,r){let n=await this.getCredentials(),i=`${r??this.buildUrl(e,t)}?uploadId=${encodeURIComponent(a)}`,s=K({method:"DELETE",url:i,...n,service:"s3",region:this.region});await fetch(s.url,{method:s.method,headers:s.headers})}async emptyAndDeleteBucket(e){let t=[];for await(let i of this.listAll(e,{}))if(t.push(i.key),t.length>=1000)await this.deleteMany(e,t),t=[];if(t.length>0)await this.deleteMany(e,t);let a=await this.getCredentials(),r=this.buildUrl(e),n=K({method:"DELETE",url:r,...a,service:"s3",region:this.region});await fetch(n.url,{method:n.method,headers:n.headers})}}class Z extends Error{statusCode;bucket;key;constructor(e,t,a,r){super(e);this.statusCode=t,this.bucket=a,this.key=r,this.name="S3Error"}}function to(e){let t=[],a=[],r=/<Contents>([\s\S]*?)<\/Contents>/g,n;while((n=r.exec(e))!==null){let s=n[1];t.push({key:X(s,"Key")||"",lastModified:new Date(X(s,"LastModified")||0),etag:(X(s,"ETag")||"").replace(/"/g,""),size:Number(X(s,"Size")||0),storageClass:X(s,"StorageClass")||"STANDARD"})}let i=/<CommonPrefixes><Prefix>([^<]+)<\/Prefix><\/CommonPrefixes>/g;while((n=i.exec(e))!==null)a.push(n[1]);return{contents:t,commonPrefixes:a,isTruncated:X(e,"IsTruncated")==="true",continuationToken:X(e,"ContinuationToken")||void 0,nextContinuationToken:X(e,"NextContinuationToken")||void 0,keyCount:Number(X(e,"KeyCount")||0),maxKeys:Number(X(e,"MaxKeys")||1000),prefix:X(e,"Prefix")||void 0,delimiter:X(e,"Delimiter")||void 0}}function X(e,t){let a=new RegExp(`<${t}>([^<]*)</${t}>`),r=e.match(a);return r?r[1]:null}function ao(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function Ta(e){let t=e.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"}[t||""]||"application/octet-stream"}function ro(e){if(e instanceof Blob)return e;if(typeof e==="string")return new Blob([e],{type:"text/plain"});return new Blob([e])}function vu(e){return new nr(e)}await rt();class no{profile;credentials=null;constructor(e="default"){this.profile=e}async init(){this.credentials=await Zt(this.profile)}async ensureCredentials(){if(!this.credentials)await this.init();return this.credentials}async createInvalidation(e){let t=await this.ensureCredentials(),a=e.callerReference||`invalidation-${Date.now()}`,r=`<?xml version="1.0" encoding="UTF-8"?>
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:[r||"*"],allowedMethods:["GET","HEAD"]}]}},cdn:{enabled:!0,origins:[{originId:"static-assets",domainName:`${a}-static.s3.amazonaws.com`,pathPattern:"/static/*"}],customDomain:r?{domain:r,certificateArn:"TO_BE_GENERATED"}:void 0,cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0},databases:o==="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:c==="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:`${a}-jobs`,batchSize:10}]},"email-sender":{runtime:"nodejs20.x",handler:"dist/workers/email.handler",memory:512,timeout:60,events:[{type:"sqs",queueName:`${a}-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:`${a}-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:[`${a}-app`,`${a}-nginx`,`${a}-workers`]}},security:{certificate:r?{domain:r,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:o==="mysql"?3306:5432,protocol:"tcp",source:"app-sg"}]},...c==="redis"&&{cache:{ingress:[{port:6379,protocol:"tcp",source:"app-sg"}]}}}}}}}function su(e){let{name:t,slug:a,domain:r,repository:n,phpVersion:i="8.3",size:s="small",database:o=a.replace(/-/g,"_"),databasePassword:c,sslEmail:l,deployStrategy:u="push",provider:m="hetzner"}=e;return{project:{name:t,slug:a,region:"us-east-1"},mode:"server",cloud:{provider:m},environments:{production:{type:"production",domain:r}},infrastructure:{compute:{mode:"server",size:s,runtime:"php",webServer:"nginx",php:{versions:[i],default:i},managedServices:{mysql:!0,redis:!0},firewall:{enabled:!0},autoUpdates:!0,monitoring:!0,backups:{enabled:!0,schedule:"0 2 * * *",retentionCount:7}},appDatabase:{engine:"mysql",name:o,username:o,password:c}},sites:{main:{root:".",type:"laravel",domain:r,phpVersion:i,repository:{...n,strategy:u},scheduler:!0,queues:[{connection:"redis",queue:"default",processes:1}],ssl:{provider:"letsencrypt",email:l}}}}}function ou(e){let{name:t,slug:a,domain:r,layers:n,phpVersion:i="8.3",architecture:s="x86_64",memory:o=1024,build:c,deploy:l=["migrate --force"],cache:u="dynamodb",scheduler:m="on",region:p="us-east-1"}=e;return{project:{name:t,slug:a,region:p},mode:"serverless",environments:{production:{type:"production",domain:r,app:{kind:"php",runtime:"provided.al2023",phpVersion:i,architecture:s,layers:n,memory:o,build:c,deploy:l,assets:"public",queues:!0,scheduler:m,cache:{driver:u},domain:r}}}}}function cu(e){return{root:e.root??"packages/ui/dist",deploy:"server",type:"static",domain:e.domain,build:e.build??"cd packages/ui && bun install && bun run build",ssl:{provider:"letsencrypt"},auth:{username:e.username??"admin",password:e.password}}}var Is=Fa,Rs="./node_modules/@stacksjs/ts-cloud/dist/bin/dashboard-server.js";function Ns(e){let t=e.split(".").filter(Boolean);return t.length<=2?e:t.slice(-2).join(".")}function Ds(e){let t=2166136261;for(let a=0;a<e.length;a++)t^=e.charCodeAt(a),t=Math.imul(t,16777619);return t>>>0}var ks=20000,Ms=12000;function Ls(e){return ks+Ds(e)%Ms}function Ya(e,t){let a=Ns(e);if(a===e)return`dashboard.${a}`;for(let r of t)if(r===a)return`dashboard.${a}`;return`dashboard.${e}`}function Xa(e,t){let a=[],r=e.infrastructure?.dns?.domain;if(r&&!e.cloud?.attachTo)a.push(r);if(t&&e.environments?.[t]?.domain)a.push(e.environments[t].domain);for(let n of Object.values(e.sites??{})){let i=n;if(!i||i.redirect)continue;let s=i.domain;if(typeof s==="string")a.push(s);else if(Array.isArray(s))a.push(...s.filter((o)=>typeof o==="string"))}return a.filter((n)=>n&&!n.startsWith("dashboard."))}function xs(e,t,a){if(a)return a;let r=Xa(e,t),n=r[0];if(!n)return null;return Ya(n,r)}function Os(e,t,a){if(a)return[a];let r=Xa(e,t),n=[];for(let i of r){let s=Ya(i,r);if(!n.includes(s))n.push(s)}return n}function Ws(e){return Object.entries(e.sites??{}).some(([t,a])=>{if(!a)return!1;let r=a.root??"";return _s(t)||r==="ui/dist"||r.endsWith("/ui/dist")||r.endsWith("/dist/ui")})}var Za="dashboard-";function ba(e){return Za+e.replace(/^dashboard\./,"").replace(/\./g,"-")}function _s(e){return e==="dashboard"||e.startsWith(Za)}function Bs(e,t,a){if(Ws(e))return[];if(e.cloud?.attachTo)return[];let r=a.password?{auth:{username:a.username||"admin",password:a.password,realm:a.realm}}:{},n=a.build===!1||a.build===void 0?{}:{build:a.build};if(a.live!==!1){let i=xs(e,t,a.domain);if(!i)return[];let s=a.port??Ls(i),o=e.infrastructure?.appDatabase??e.infrastructure?.compute?.database,c={root:a.uiRoot,deploy:"server",domain:i,preStart:["bun install --production --no-save"],start:`bun ${Rs} --box --host 127.0.0.1 --port ${s}`,port:s,cpuWeight:10,ioWeight:10,tasksMax:128,env:{APP_ENV:"production",NODE_ENV:"production",TS_CLOUD_DASHBOARD_TELEMETRY:"1",...o?.password?{TS_CLOUD_DASHBOARD_DB_PASSWORD:o.password}:{}},zeroDowntime:!1,sharedPaths:[Is],healthCheck:{path:"/login"},ssl:{provider:"letsencrypt"}};return[{name:ba(i),site:c}]}return Os(e,t,a.domain).map((i)=>({name:ba(i),site:{root:a.uiRoot,deploy:"server",type:"static",domain:i,ssl:{provider:"letsencrypt"},...n,...r}}))}function lu(e,t,a){return Bs(e,t,a)[0]??null}function Qt(e,t){let a={...e};for(let r in t){let n=t[r],i=a[r];if(n===void 0)continue;if(Array.isArray(n)&&Array.isArray(i))a[r]=[...i,...n];else if(typeof n==="object"&&n!==null&&!Array.isArray(n)&&typeof i==="object"&&i!==null&&!Array.isArray(i))a[r]=Qt(i,n);else a[r]=n}return a}function Aa(e,t){return Qt(e,t)}function uu(...e){return e.reduce((t,a)=>Qt(t,a),{})}function du(e,t){return(a)=>{let r=e(a);if(typeof t==="function")return Aa(r,t(r,a));return Aa(r,t)}}function Ue(e){return{infrastructure:e}}function mu(e){return Ue({monitoring:e})}function pu(e){return Ue({security:e})}function gu(e){return Ue({databases:e})}function hu(e){return Ue({cache:e})}function yu(e){return Ue({cdn:e})}function fu(e){return Ue({queues:e})}at();function Us(){let e=process.env.AWS_ACCESS_KEY_ID,t=process.env.AWS_SECRET_ACCESS_KEY;if(!e||!t)return null;return{accessKeyId:e,secretAccessKey:t,sessionToken:process.env.AWS_SESSION_TOKEN}}function Gs(e){let t=e?.profile||process.env.AWS_PROFILE||"default",a=e?.credentialsFile||ar(tr(),".aws","credentials");if(!er(a))return null;try{let r=$t(a,"utf-8");return Vs(r,t)}catch{return null}}function Vs(e,t){let a=e.split(`
2494
+ `),r=null,n,i,s;for(let o of a){let c=o.trim();if(!c||c.startsWith("#")||c.startsWith(";"))continue;let l=c.match(/^\[([^\]]+)\]$/);if(l){if(r===t&&n&&i)return{accessKeyId:n,secretAccessKey:i,sessionToken:s};r=l[1],n=void 0,i=void 0,s=void 0;continue}if(r===t){let[u,...m]=c.split("="),p=m.join("=").trim();switch(u.trim().toLowerCase()){case"aws_access_key_id":n=p;break;case"aws_secret_access_key":i=p;break;case"aws_session_token":s=p;break}}}if(r===t&&n&&i)return{accessKeyId:n,secretAccessKey:i,sessionToken:s};return null}async function Fs(e){let t=e?.timeout??1000,a="http://169.254.169.254";try{let r=await Ze("http://169.254.169.254/latest/api/token",{method:"PUT",headers:{"X-aws-ec2-metadata-token-ttl-seconds":"21600"}},t);if(!r.ok)return null;let n=await r.text(),i=await Ze("http://169.254.169.254/latest/meta-data/iam/security-credentials/",{headers:{"X-aws-ec2-metadata-token":n}},t);if(!i.ok)return null;let s=(await i.text()).trim(),o=await Ze(`http://169.254.169.254/latest/meta-data/iam/security-credentials/${s}`,{headers:{"X-aws-ec2-metadata-token":n}},t);if(!o.ok)return null;let c=await o.json();return{accessKeyId:c.AccessKeyId,secretAccessKey:c.SecretAccessKey,sessionToken:c.Token,expiration:new Date(c.Expiration)}}catch{return null}}async function js(e){let t=e?.timeout??1000,a=process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI,r=process.env.AWS_CONTAINER_CREDENTIALS_FULL_URI,n=null;if(a)n=`http://169.254.170.2${a}`;else if(r)n=r;if(!n)return null;try{let i={},s=process.env.AWS_CONTAINER_AUTHORIZATION_TOKEN;if(s)i.Authorization=s;let o=await Ze(n,{headers:i},t);if(!o.ok)return null;let c=await o.json();return{accessKeyId:c.AccessKeyId,secretAccessKey:c.SecretAccessKey,sessionToken:c.Token,expiration:new Date(c.Expiration)}}catch{return null}}async function Ks(e){let t=e?.timeout??5000,a=process.env.AWS_WEB_IDENTITY_TOKEN_FILE,r=process.env.AWS_ROLE_ARN,n=process.env.AWS_ROLE_SESSION_NAME||"ts-cloud-session";if(!a||!r)return null;try{let i=$t(a,"utf-8").trim(),s=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION||"us-east-1",o=s.startsWith("us-gov")?`https://sts.${s}.amazonaws.com`:s==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${s}.amazonaws.com`,c=new URLSearchParams({Action:"AssumeRoleWithWebIdentity",Version:"2011-06-15",RoleArn:r,RoleSessionName:n,WebIdentityToken:i}),l=await Ze(`${o}/?${c.toString()}`,{method:"POST"},t);if(!l.ok)return null;let u=await l.text(),m=$e(u,"AccessKeyId"),p=$e(u,"SecretAccessKey"),g=$e(u,"SessionToken"),h=$e(u,"Expiration");if(!m||!p)return null;return{accessKeyId:m,secretAccessKey:p,sessionToken:g??void 0,expiration:h?new Date(h):void 0}}catch{return null}}async function It(e){let t=Us();if(t)return t;let a=Gs(e);if(a)return a;let r=await Ks(e);if(r)return r;let n=await js(e);if(n)return n;let i=await Fs(e);if(i)return i;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 Cu(e){let t=null,a=null;return async()=>{if(t){if(!t.expiration)return t;let r=300000;if(t.expiration.getTime()-Date.now()>r)return t}if(a)return a;return a=It(e).then((r)=>{return t=r,a=null,r}).catch((r)=>{throw a=null,r}),a}}async function Ze(e,t,a){let r=new AbortController,n=setTimeout(()=>r.abort(),a);try{let i=await fetch(e,{...t,signal:r.signal});return clearTimeout(n),i}catch(i){throw clearTimeout(n),i}}function $e(e,t){let a=new RegExp(`<${t}>([^<]+)</${t}>`),r=e.match(a);return r?r[1]:null}async function Yt(e){return It({profile:e})}function Hs(e){let t=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION;if(t)return t;let a=ar(tr(),".aws","config");if(er(a))try{let r=$t(a,"utf-8"),n=e||process.env.AWS_PROFILE||"default",i=n==="default"?"[default]":`[profile ${n}]`,s=r.split(`
2495
+ `),o=!1;for(let c of s){let l=c.trim();if(l.startsWith("[")){o=l===i;continue}if(o&&l.startsWith("region")){let[,u]=l.split("=");if(u)return u.trim()}}}catch{}return"us-east-1"}async function qs(e){let t=e||await It(),a=Hs(),{signRequest:r}=await at().then(()=>Ma),n=a.startsWith("us-gov")?`https://sts.${a}.amazonaws.com`:a==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${a}.amazonaws.com`,i="Action=GetCallerIdentity&Version=2011-06-15",s=r({method:"POST",url:n,body:"Action=GetCallerIdentity&Version=2011-06-15",headers:{"Content-Type":"application/x-www-form-urlencoded"},...t,service:"sts",region:a}),o=await fetch(s.url,{method:s.method,headers:s.headers,body:s.body});if(!o.ok)throw Error(`Failed to get account ID: ${await o.text()}`);let c=await o.text(),l=$e(c,"Account");if(!l)throw Error("Failed to parse account ID from response");return l}await at();class zs{profile;credentials=null;region;constructor(e="us-east-1",t="default"){this.profile=t,this.region=e}async init(){if(this.credentials=await Yt(this.profile),this.credentials.region)this.region=this.credentials.region}async ensureCredentials(){if(!this.credentials)await this.init();return this.credentials}async request(e,t){let a=await this.ensureCredentials(),r={Action:e,Version:"2010-05-15",...Kt(t)},n=new URLSearchParams(r).toString(),i=await(await _e({method:"POST",url:`https://cloudformation.${this.region}.amazonaws.com/`,service:"cloudformation",region:this.region,headers:{"Content-Type":"application/x-www-form-urlencoded"},body:n,accessKeyId:a.accessKeyId,secretAccessKey:a.secretAccessKey,sessionToken:a.sessionToken})).text();return Js(i)}async createStack(e){let t={StackName:e.stackName};if(e.templateBody)t.TemplateBody=e.templateBody;else if(e.templateURL)t.TemplateURL=e.templateURL;else throw Error("Either templateBody or templateURL must be provided");if(e.parameters)for(let[r,[n,i]]of Object.entries(e.parameters).entries())t[`Parameters.member.${r+1}.ParameterKey`]=n,t[`Parameters.member.${r+1}.ParameterValue`]=i;if(e.capabilities)for(let[r,n]of e.capabilities.entries())t[`Capabilities.member.${r+1}`]=n;if(e.tags)for(let[r,[n,i]]of Object.entries(e.tags).entries())t[`Tags.member.${r+1}.Key`]=n,t[`Tags.member.${r+1}.Value`]=i;if(e.timeoutInMinutes)t.TimeoutInMinutes=e.timeoutInMinutes;if(e.onFailure)t.OnFailure=e.onFailure;let a=await this.request("CreateStack",t);return(a?.CreateStackResult||a?.CreateStackResponse?.CreateStackResult||a)?.StackId}async updateStack(e){let t={StackName:e.stackName};if(e.templateBody)t.TemplateBody=e.templateBody;else if(e.templateURL)t.TemplateURL=e.templateURL;if(e.parameters)for(let[r,[n,i]]of Object.entries(e.parameters).entries())t[`Parameters.member.${r+1}.ParameterKey`]=n,t[`Parameters.member.${r+1}.ParameterValue`]=i;if(e.capabilities)for(let[r,n]of e.capabilities.entries())t[`Capabilities.member.${r+1}`]=n;if(e.tags)for(let[r,[n,i]]of Object.entries(e.tags).entries())t[`Tags.member.${r+1}.Key`]=n,t[`Tags.member.${r+1}.Value`]=i;let a=await this.request("UpdateStack",t);return(a?.UpdateStackResult||a?.UpdateStackResponse?.UpdateStackResult||a)?.StackId}async deleteStack(e){await this.request("DeleteStack",{StackName:e})}async describeStack(e){let t=await this.request("DescribeStacks",{StackName:e}),a=(t?.DescribeStacksResult||t?.DescribeStacksResponse?.DescribeStacksResult||t)?.Stacks?.member,r=Array.isArray(a)?a[0]:a;if(!r)throw Error(`Stack ${e} not found`);return Qs(r)}async listStacks(e){let t={};if(e)for(let[r,n]of e.entries())t[`StackStatusFilter.member.${r+1}`]=n;let a=await this.request("ListStacks",t);return $s(a)}async describeStackEvents(e){let t=await this.request("DescribeStackEvents",{StackName:e});return Ys(t)}async waitForStack(e,t,a){let r=0,n=null;while(r<360){r++;let i=await this.describeStack(e);if(a)try{let s=await this.describeStackEvents(e),o=[];if(n){for(let c of s){if(c.EventId===n)break;o.push(c)}o.reverse()}else if(s.length>0)o=[s[0]];for(let c of o)a(c);if(s.length>0)n=s[0].EventId}catch{}if(i.StackStatus&&t.includes(i.StackStatus))return i;if(i.StackStatus?.includes("FAILED")||i.StackStatus?.includes("ROLLBACK"))throw Error(`Stack reached failed state: ${i.StackStatus}
2496
+ Reason: ${i.StackStatusReason||"Unknown"}`);await new Promise((s)=>setTimeout(s,5000))}throw Error(`Timeout waiting for stack ${e} to complete`)}async waitForStackWithProgress(e,t,a){let r={"stack-create-complete":["CREATE_COMPLETE"],"stack-update-complete":["UPDATE_COMPLETE"],"stack-delete-complete":["DELETE_COMPLETE"]}[t];if(!r)throw Error(`Unknown waiter: ${t}`);return this.waitForStack(e,r,a)}async createChangeSet(e){let t={StackName:e.stackName,ChangeSetName:e.changeSetName,ChangeSetType:"UPDATE"};if(e.templateBody)t.TemplateBody=e.templateBody;else if(e.templateURL)t.TemplateURL=e.templateURL;if(e.parameters)for(let[a,[r,n]]of Object.entries(e.parameters).entries())t[`Parameters.member.${a+1}.ParameterKey`]=r,t[`Parameters.member.${a+1}.ParameterValue`]=n;if(e.capabilities)for(let[a,r]of e.capabilities.entries())t[`Capabilities.member.${a+1}`]=r;return(await this.request("CreateChangeSet",t)).ChangeSetId}async executeChangeSet(e,t){await this.request("ExecuteChangeSet",{ChangeSetName:e,StackName:t})}async describeStacks(e){let t=typeof e==="string"?e:e.stackName;try{return{Stacks:[await this.describeStack(t)]}}catch{return{Stacks:[]}}}async getStackOutputs(e){let t=await this.request("DescribeStacks",{StackName:e}),a=(t?.DescribeStacksResult||t?.DescribeStacksResponse?.DescribeStacksResult||t)?.Stacks?.member,r=Array.isArray(a)?a[0]:a;if(!r)return{};let n={},i=r.Outputs?.member;if(i){let s=Array.isArray(i)?i:[i];for(let o of s)if(o.OutputKey&&o.OutputValue)n[o.OutputKey]=o.OutputValue}return n}}function Kt(e,t=""){let a={};for(let[r,n]of Object.entries(e)){let i=t?`${t}.${r}`:r;if(Array.isArray(n))n.forEach((s,o)=>{if(typeof s==="object")Object.assign(a,Kt(s,`${i}.${o+1}`));else a[`${i}.${o+1}`]=String(s)});else if(typeof n==="object"&&n!==null)Object.assign(a,Kt(n,i));else if(n!==void 0&&n!==null)a[i]=String(n)}return a}function Js(e){e=e.replace(/<\?xml[^?]*\?>\s*/,"").trim();function t(r,n,i){let s=1,o=i,c=`<${n}`,l=`</${n}>`;while(o<r.length&&s>0){let u=r.indexOf(c,o),m=r.indexOf(l,o);if(m===-1)return-1;if(u!==-1&&u<m){let p=r[u+c.length];if(p===">"||p===" "||p==="/"){let g=r.indexOf(">",u);if(g!==-1&&r[g-1]==="/")o=g+1;else s++,o=g+1}else o=u+c.length}else{if(s--,s===0)return m;o=m+l.length}}return-1}function a(r,n){while(n<r.length&&/\s/.test(r[n]))n++;if(n>=r.length||r[n]!=="<"){let g=r.indexOf("<",n);if(g===-1)return{value:r.slice(n).trim(),end:r.length};return{value:r.slice(n,g).trim(),end:g}}if(r[n+1]==="/")return{value:void 0,end:n};let i=r.slice(n).match(/^<(\w+)([^>]*?)\/?>/);if(!i)return{value:void 0,end:n+1};let s=i[1];if(i[0].endsWith("/>"))return{value:"",end:n+i[0].length};let o=n+i[0].length,c=`</${s}>`,l=t(r,s,o);if(l===-1)return{value:void 0,end:n+i[0].length};let u=r.slice(o,l).trim();if(!u.includes("<"))return{value:u,end:l+c.length};let m={},p=o;while(p<l){while(p<l&&/\s/.test(r[p]))p++;if(p>=l)break;if(r[p]!=="<"||r[p+1]==="/")break;let g=r.slice(p).match(/^<(\w+)/);if(!g)break;let h=g[1],y=a(r,p);if(y.value===void 0){p++;continue}if(h==="member"||m[h]!==void 0){if(!Array.isArray(m[h]))m[h]=m[h]!==void 0?[m[h]]:[];m[h].push(y.value)}else m[h]=y.value;p=y.end}return{value:m,end:l+c.length}}return a(e,0).value||{}}function Qs(e){return{StackName:e.StackName||"",StackId:e.StackId,StackStatus:e.StackStatus,CreationTime:e.CreationTime,LastUpdatedTime:e.LastUpdatedTime,StackStatusReason:e.StackStatusReason,Description:e.Description}}function $s(e){let t=(e?.ListStacksResult||e?.ListStacksResponse?.ListStacksResult||e)?.StackSummaries?.member;if(!t)return[];return(Array.isArray(t)?t:[t]).map((a)=>({StackName:a.StackName||"",StackId:a.StackId,StackStatus:a.StackStatus,CreationTime:a.CreationTime,LastUpdatedTime:a.LastUpdatedTime,StackStatusReason:a.StackStatusReason,Description:a.Description}))}function Ys(e){let t=(e?.DescribeStackEventsResult||e?.DescribeStackEventsResponse?.DescribeStackEventsResult||e)?.StackEvents?.member;if(!t)return[];return(Array.isArray(t)?t:[t]).map((a)=>({StackId:a.StackId||"",EventId:a.EventId||"",StackName:a.StackName||"",LogicalResourceId:a.LogicalResourceId||"",PhysicalResourceId:a.PhysicalResourceId,ResourceType:a.ResourceType||"",Timestamp:a.Timestamp||"",ResourceStatus:a.ResourceStatus||"",ResourceStatusReason:a.ResourceStatusReason}))}await at();var Xs=5242880,Ot=5242880,Zs=5242880;class rr{region;endpoint;forcePathStyle;credentials;credentialOptions;retryOptions;constructor(e={}){this.region=e.region||process.env.AWS_REGION||"us-east-1",this.endpoint=e.endpoint||`https://s3.${this.region}.amazonaws.com`,this.forcePathStyle=e.forcePathStyle||!1,this.credentials=e.credentials,this.credentialOptions=e.credentialOptions,this.retryOptions=e.retryOptions||{}}async getCredentials(){if(this.credentials)return this.credentials;return It(this.credentialOptions)}buildUrl(e,t){let a=t?encodeURIComponent(t).replace(/%2F/g,"/"):"";if(this.forcePathStyle)return t?`${this.endpoint}/${e}/${a}`:`${this.endpoint}/${e}`;let r=new URL(this.endpoint);return r.hostname=`${e}.${r.hostname}`,t?`${r.origin}/${a}`:r.origin}async get(e,t,a={}){let r=await this.getCredentials(),n=this.buildUrl(e,t),i={};if(a.range)i.Range=a.range;if(a.ifModifiedSince)i["If-Modified-Since"]=a.ifModifiedSince.toUTCString();if(a.ifMatch)i["If-Match"]=a.ifMatch;if(a.ifNoneMatch)i["If-None-Match"]=a.ifNoneMatch;let s=new URL(n);if(a.responseContentType)s.searchParams.set("response-content-type",a.responseContentType);if(a.responseContentDisposition)s.searchParams.set("response-content-disposition",a.responseContentDisposition);let o=K({method:"GET",url:s.toString(),headers:i,...r,service:"s3",region:this.region}),c=await fetch(o.url,{method:o.method,headers:o.headers});if(!c.ok&&c.status!==304){let l=await c.text();throw new Y(`Failed to get object: ${l}`,c.status,e,t)}return c}async getText(e,t,a={}){return(await this.get(e,t,a)).text()}async getJSON(e,t,a={}){return(await this.get(e,t,a)).json()}async getBuffer(e,t,a={}){return(await this.get(e,t,a)).arrayBuffer()}async put(e,t,a,r={}){let n,i;if(typeof a==="string")n=new TextEncoder().encode(a).length,i=a;else if(a instanceof ArrayBuffer)n=a.byteLength,i=a;else if(a instanceof Uint8Array)n=a.byteLength,i=a;else if(a instanceof Blob)n=a.size,i=a;else return this.uploadMultipart(e,t,a,{...r,partSize:Ot});if(n>Zs){let s=ao(i).stream();return this.uploadMultipart(e,t,s,{...r,partSize:Ot})}return this.putSimple(e,t,i,n,r)}async putSimple(e,t,a,r,n){let i=await this.getCredentials(),s=this.buildUrl(e,t),o={"Content-Length":String(r),"Content-Type":n.contentType||Ca(t)};if(n.contentEncoding)o["Content-Encoding"]=n.contentEncoding;if(n.cacheControl)o["Cache-Control"]=n.cacheControl;if(n.contentDisposition)o["Content-Disposition"]=n.contentDisposition;if(n.storageClass)o["x-amz-storage-class"]=n.storageClass;if(n.serverSideEncryption)o["x-amz-server-side-encryption"]=n.serverSideEncryption;if(n.acl)o["x-amz-acl"]=n.acl;if(n.tagging)o["x-amz-tagging"]=n.tagging;if(n.metadata)for(let[m,p]of Object.entries(n.metadata))o[`x-amz-meta-${m.toLowerCase()}`]=p;let c;if(typeof a==="string")c=a;else if(a instanceof Blob)c=await a.text();else c=new TextDecoder().decode(a instanceof ArrayBuffer?new Uint8Array(a):a);let l=K({method:"PUT",url:s,headers:o,body:c,...i,service:"s3",region:this.region}),u=await fetch(l.url,{method:l.method,headers:l.headers,body:a});if(!u.ok){let m=await u.text();throw new Y(`Failed to put object: ${m}`,u.status,e,t)}return{etag:(u.headers.get("ETag")||"").replace(/"/g,"")}}async delete(e,t){let a=await this.getCredentials(),r=this.buildUrl(e,t),n=K({method:"DELETE",url:r,...a,service:"s3",region:this.region}),i=await fetch(n.url,{method:n.method,headers:n.headers});if(!i.ok&&i.status!==204){let s=await i.text();throw new Y(`Failed to delete object: ${s}`,i.status,e,t)}}async deleteMany(e,t){let a=await this.getCredentials(),r=`${this.buildUrl(e)}?delete`,n=`<?xml version="1.0" encoding="UTF-8"?><Delete><Quiet>false</Quiet>${t.map((g)=>`<Object><Key>${to(g)}</Key></Object>`).join("")}</Delete>`,i=K({method:"POST",url:r,headers:{"Content-Type":"application/xml"},body:n,...a,service:"s3",region:this.region}),s=await fetch(i.url,{method:i.method,headers:i.headers,body:n});if(!s.ok){let g=await s.text();throw new Y(`Failed to delete objects: ${g}`,s.status,e)}let o=await s.text(),c=[],l=[],u=/<Deleted><Key>([^<]+)<\/Key>/g,m;while((m=u.exec(o))!==null)c.push(m[1]);let p=/<Error><Key>([^<]+)<\/Key><Code>([^<]+)<\/Code><Message>([^<]+)<\/Message>/g;while((m=p.exec(o))!==null)l.push({key:m[1],error:`${m[2]}: ${m[3]}`});return{deleted:c,errors:l}}async list(e,t={}){let a=await this.getCredentials(),r=new URL(this.buildUrl(e));if(r.searchParams.set("list-type","2"),t.prefix)r.searchParams.set("prefix",t.prefix);if(t.delimiter)r.searchParams.set("delimiter",t.delimiter);if(t.maxKeys)r.searchParams.set("max-keys",String(t.maxKeys));if(t.continuationToken)r.searchParams.set("continuation-token",t.continuationToken);if(t.startAfter)r.searchParams.set("start-after",t.startAfter);let n=K({method:"GET",url:r.toString(),...a,service:"s3",region:this.region}),i=await fetch(n.url,{method:n.method,headers:n.headers});if(!i.ok){let o=await i.text();throw new Y(`Failed to list objects: ${o}`,i.status,e)}let s=await i.text();return eo(s)}async*listAll(e,t={}){let a;do{let r=await this.list(e,{...t,continuationToken:a});for(let n of r.contents)yield n;a=r.nextContinuationToken}while(a)}async head(e,t){let a=await this.getCredentials(),r=this.buildUrl(e,t),n=K({method:"HEAD",url:r,...a,service:"s3",region:this.region}),i=await fetch(n.url,{method:n.method,headers:n.headers});if(i.status===404)return null;if(!i.ok){let o=await i.text();throw new Y(`Failed to head object: ${o}`,i.status,e,t)}let s={};return i.headers.forEach((o,c)=>{if(c.toLowerCase().startsWith("x-amz-meta-"))s[c.slice(11)]=o}),{contentLength:Number(i.headers.get("Content-Length")||0),contentType:i.headers.get("Content-Type")||"application/octet-stream",etag:(i.headers.get("ETag")||"").replace(/"/g,""),lastModified:new Date(i.headers.get("Last-Modified")||0),metadata:s,storageClass:i.headers.get("x-amz-storage-class")||void 0,serverSideEncryption:i.headers.get("x-amz-server-side-encryption")||void 0}}async exists(e,t){return await this.head(e,t)!==null}async copy(e,t,a,r,n={}){let i=await this.getCredentials(),s=this.buildUrl(a,r),o={"x-amz-copy-source":`/${e}/${encodeURIComponent(t)}`};if(n.metadataDirective)o["x-amz-metadata-directive"]=n.metadataDirective;if(n.contentType)o["Content-Type"]=n.contentType;if(n.storageClass)o["x-amz-storage-class"]=n.storageClass;if(n.acl)o["x-amz-acl"]=n.acl;if(n.metadata)for(let[m,p]of Object.entries(n.metadata))o[`x-amz-meta-${m.toLowerCase()}`]=p;let c=K({method:"PUT",url:s,headers:o,...i,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers});if(!l.ok){let m=await l.text();throw new Y(`Failed to copy object: ${m}`,l.status,a,r)}let u=(await l.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:u?u[1]:""}}async getPresignedUrl(e,t,a={}){let r=await this.getCredentials(),n=this.buildUrl(e,t);return La({url:n,method:a.method||"GET",expiresIn:a.expiresIn||3600,...r,service:"s3",region:this.region})}async uploadMultipart(e,t,a,r={}){let n=await this.getCredentials(),i=Math.max(r.partSize||Ot,Xs),s,o;if(a instanceof ReadableStream)s=a;else if(a instanceof Blob)s=a.stream(),o=a.size;else{let u=new Blob([a]);s=u.stream(),o=u.size}let{uploadId:c,baseUrl:l}=await this.initiateMultipartUpload(e,t,r);try{let u=await this.uploadParts(e,t,l,c,s,i,n,o,r.concurrency||4,r.onProgress);return await this.completeMultipartUpload(e,t,l,c,u)}catch(u){throw await this.abortMultipartUpload(e,t,c,l).catch(()=>{}),u}}async initiateMultipartUpload(e,t,a){let r=await this.getCredentials(),n=this.buildUrl(e,t),i=`${n}?uploads`,s={"Content-Type":a.contentType||Ca(t)};if(a.storageClass)s["x-amz-storage-class"]=a.storageClass;if(a.serverSideEncryption)s["x-amz-server-side-encryption"]=a.serverSideEncryption;if(a.acl)s["x-amz-acl"]=a.acl;if(a.metadata)for(let[m,p]of Object.entries(a.metadata))s[`x-amz-meta-${m.toLowerCase()}`]=p;let o=K({method:"POST",url:i,headers:s,...r,service:"s3",region:this.region}),c=await fetch(o.url,{method:o.method,headers:o.headers});if(!c.ok){let m=await c.text();throw new Y(`Failed to initiate multipart upload: ${m}`,c.status,e,t)}let l=(await c.text()).match(/<UploadId>([^<]+)<\/UploadId>/);if(!l)throw new Y("Failed to parse upload ID from response",0,e,t);let u=n;if(c.url)try{let m=new URL(c.url);m.search="",u=m.toString()}catch{}return{uploadId:l[1],baseUrl:u}}async uploadParts(e,t,a,r,n,i,s,o,c,l){let u=[],m=n.getReader(),p=1,g=new Uint8Array(0),h=0,y=o?Math.ceil(o/i):void 0,b=new Map,T=async(S,E)=>{let v=`${a}?partNumber=${E}&uploadId=${encodeURIComponent(r)}`,P={"Content-Length":String(S.byteLength),"x-amz-content-sha256":"UNSIGNED-PAYLOAD"},N=K({method:"PUT",url:v,headers:P,...s,service:"s3",region:this.region}),I=await fetch(N.url,{method:N.method,headers:N.headers,body:S,redirect:"error"});if(!I.ok){let M=await I.text();throw new Y(`Failed to upload part ${E}: ${M}`,I.status,e,t)}let D=(I.headers.get("ETag")||"").replace(/"/g,"");if(!D)throw new Y(`Missing ETag for part ${E}`,I.status,e,t);return{partNumber:E,etag:D}},w=async()=>{let S=await Promise.race(b.values());b.delete(S.partNumber),u.push(S)};while(!0){let{done:S,value:E}=await m.read();if(E){let v=new Uint8Array(g.length+E.length);v.set(g),v.set(E,g.length),g=v}while(g.length>=i||S&&g.length>0){let v=g.slice(0,i);g=g.slice(i);let P=p++;if(b.size>=c)await w();if(b.set(P,T(v,P)),h+=v.byteLength,l)l({loaded:h,total:o||h,part:P,totalParts:y||P})}if(S)break}while(b.size>0)await w();return u.sort((S,E)=>S.partNumber-E.partNumber),u}async completeMultipartUpload(e,t,a,r,n){let i=await this.getCredentials(),s=`${a}?uploadId=${encodeURIComponent(r)}`,o=`<?xml version="1.0" encoding="UTF-8"?><CompleteMultipartUpload>${n.map((m)=>`<Part><PartNumber>${m.partNumber}</PartNumber><ETag>"${m.etag}"</ETag></Part>`).join("")}</CompleteMultipartUpload>`,c=K({method:"POST",url:s,headers:{"Content-Type":"application/xml"},body:o,...i,service:"s3",region:this.region}),l=await fetch(c.url,{method:c.method,headers:c.headers,body:o});if(!l.ok){let m=await l.text();throw new Y(`Failed to complete multipart upload: ${m}`,l.status,e,t)}let u=(await l.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:u?u[1]:""}}async abortMultipartUpload(e,t,a,r){let n=await this.getCredentials(),i=`${r??this.buildUrl(e,t)}?uploadId=${encodeURIComponent(a)}`,s=K({method:"DELETE",url:i,...n,service:"s3",region:this.region});await fetch(s.url,{method:s.method,headers:s.headers})}async emptyAndDeleteBucket(e){let t=[];for await(let i of this.listAll(e,{}))if(t.push(i.key),t.length>=1000)await this.deleteMany(e,t),t=[];if(t.length>0)await this.deleteMany(e,t);let a=await this.getCredentials(),r=this.buildUrl(e),n=K({method:"DELETE",url:r,...a,service:"s3",region:this.region});await fetch(n.url,{method:n.method,headers:n.headers})}}class Y extends Error{statusCode;bucket;key;constructor(e,t,a,r){super(e);this.statusCode=t,this.bucket=a,this.key=r,this.name="S3Error"}}function eo(e){let t=[],a=[],r=/<Contents>([\s\S]*?)<\/Contents>/g,n;while((n=r.exec(e))!==null){let s=n[1];t.push({key:X(s,"Key")||"",lastModified:new Date(X(s,"LastModified")||0),etag:(X(s,"ETag")||"").replace(/"/g,""),size:Number(X(s,"Size")||0),storageClass:X(s,"StorageClass")||"STANDARD"})}let i=/<CommonPrefixes><Prefix>([^<]+)<\/Prefix><\/CommonPrefixes>/g;while((n=i.exec(e))!==null)a.push(n[1]);return{contents:t,commonPrefixes:a,isTruncated:X(e,"IsTruncated")==="true",continuationToken:X(e,"ContinuationToken")||void 0,nextContinuationToken:X(e,"NextContinuationToken")||void 0,keyCount:Number(X(e,"KeyCount")||0),maxKeys:Number(X(e,"MaxKeys")||1000),prefix:X(e,"Prefix")||void 0,delimiter:X(e,"Delimiter")||void 0}}function X(e,t){let a=new RegExp(`<${t}>([^<]*)</${t}>`),r=e.match(a);return r?r[1]:null}function to(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function Ca(e){let t=e.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"}[t||""]||"application/octet-stream"}function ao(e){if(e instanceof Blob)return e;if(typeof e==="string")return new Blob([e],{type:"text/plain"});return new Blob([e])}function Tu(e){return new rr(e)}await at();class ro{profile;credentials=null;constructor(e="default"){this.profile=e}async init(){this.credentials=await Yt(this.profile)}async ensureCredentials(){if(!this.credentials)await this.init();return this.credentials}async createInvalidation(e){let t=await this.ensureCredentials(),a=e.callerReference||`invalidation-${Date.now()}`,r=`<?xml version="1.0" encoding="UTF-8"?>
2497
2497
  <InvalidationBatch>
2498
2498
  <Paths>
2499
2499
  <Quantity>${e.paths.length}</Quantity>
@@ -2502,24 +2502,24 @@ Reason: ${i.StackStatusReason||"Unknown"}`);await new Promise((s)=>setTimeout(s,
2502
2502
  </Items>
2503
2503
  </Paths>
2504
2504
  <CallerReference>${a}</CallerReference>
2505
- </InvalidationBatch>`,n=`https://cloudfront.amazonaws.com/2020-05-31/distribution/${e.distributionId}/invalidation`,i=await _e({method:"POST",url:n,service:"cloudfront",region:"us-east-1",headers:{"Content-Type":"text/xml"},body:r,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey,sessionToken:t.sessionToken});return(await mt(i)).Id}async getInvalidation(e,t){let a=await this.ensureCredentials(),r=`https://cloudfront.amazonaws.com/2020-05-31/distribution/${e}/invalidation/${t}`,n=await _e({method:"GET",url:r,service:"cloudfront",region:"us-east-1",accessKeyId:a.accessKeyId,secretAccessKey:a.secretAccessKey,sessionToken:a.sessionToken});return await mt(n)}async listInvalidations(e){let t=await this.ensureCredentials(),a=`https://cloudfront.amazonaws.com/2020-05-31/distribution/${e}/invalidation`,r=await _e({method:"GET",url:a,service:"cloudfront",region:"us-east-1",accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey,sessionToken:t.sessionToken});return(await mt(r)).Items||[]}async waitForInvalidation(e,t,a=60,r=5000){for(let n=0;n<a;n++){if((await this.getInvalidation(e,t)).Status==="Completed")return;if(n<a-1)await new Promise((i)=>setTimeout(i,r))}throw Error(`Invalidation ${t} did not complete within the expected time`)}async invalidateAll(e){return await this.createInvalidation({distributionId:e,paths:["/*"]})}}class fe extends Error{code;solution;details;constructor(e,t,a,r){super(e);this.code=t,this.solution=a,this.details=r,this.name="CloudError",Error.captureStackTrace?.(this,fe)}toString(){let e=`${this.name} [${this.code}]: ${this.message}`;if(this.solution)e+=`
2505
+ </InvalidationBatch>`,n=`https://cloudfront.amazonaws.com/2020-05-31/distribution/${e.distributionId}/invalidation`,i=await _e({method:"POST",url:n,service:"cloudfront",region:"us-east-1",headers:{"Content-Type":"text/xml"},body:r,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey,sessionToken:t.sessionToken});return(await dt(i)).Id}async getInvalidation(e,t){let a=await this.ensureCredentials(),r=`https://cloudfront.amazonaws.com/2020-05-31/distribution/${e}/invalidation/${t}`,n=await _e({method:"GET",url:r,service:"cloudfront",region:"us-east-1",accessKeyId:a.accessKeyId,secretAccessKey:a.secretAccessKey,sessionToken:a.sessionToken});return await dt(n)}async listInvalidations(e){let t=await this.ensureCredentials(),a=`https://cloudfront.amazonaws.com/2020-05-31/distribution/${e}/invalidation`,r=await _e({method:"GET",url:a,service:"cloudfront",region:"us-east-1",accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey,sessionToken:t.sessionToken});return(await dt(r)).Items||[]}async waitForInvalidation(e,t,a=60,r=5000){for(let n=0;n<a;n++){if((await this.getInvalidation(e,t)).Status==="Completed")return;if(n<a-1)await new Promise((i)=>setTimeout(i,r))}throw Error(`Invalidation ${t} did not complete within the expected time`)}async invalidateAll(e){return await this.createInvalidation({distributionId:e,paths:["/*"]})}}class ye extends Error{code;solution;details;constructor(e,t,a,r){super(e);this.code=t,this.solution=a,this.details=r,this.name="CloudError",Error.captureStackTrace?.(this,ye)}toString(){let e=`${this.name} [${this.code}]: ${this.message}`;if(this.solution)e+=`
2506
2506
 
2507
2507
  \uD83D\uDCA1 Solution: ${this.solution}`;if(this.details&&Object.keys(this.details).length>0){e+=`
2508
2508
 
2509
2509
  Details:`;for(let[t,a]of Object.entries(this.details))e+=`
2510
- ${t}: ${JSON.stringify(a)}`}return e}}class ht extends fe{constructor(e,t,a){super(e,"CONFIG_ERROR",t,a);this.name="ConfigurationError"}}class Ie extends fe{constructor(e,t,a){super(e,"CREDENTIAL_ERROR",t,a);this.name="CredentialError"}}class io extends fe{constructor(e,t,a){super(e,"DEPLOYMENT_ERROR",t,a);this.name="DeploymentError"}}class ir extends fe{constructor(e,t,a){super(e,"VALIDATION_ERROR",t,a);this.name="ValidationError"}}class so extends fe{statusCode;constructor(e,t,a,r){super(e,"AWS_API_ERROR",a,r);this.statusCode=t,this.name="AWSAPIError"}}var oo={NO_CREDENTIALS:{message:"AWS credentials not found",solution:`Configure AWS credentials using one of these methods:
2510
+ ${t}: ${JSON.stringify(a)}`}return e}}class gt extends ye{constructor(e,t,a){super(e,"CONFIG_ERROR",t,a);this.name="ConfigurationError"}}class Pe extends ye{constructor(e,t,a){super(e,"CREDENTIAL_ERROR",t,a);this.name="CredentialError"}}class no extends ye{constructor(e,t,a){super(e,"DEPLOYMENT_ERROR",t,a);this.name="DeploymentError"}}class nr extends ye{constructor(e,t,a){super(e,"VALIDATION_ERROR",t,a);this.name="ValidationError"}}class io extends ye{statusCode;constructor(e,t,a,r){super(e,"AWS_API_ERROR",a,r);this.statusCode=t,this.name="AWSAPIError"}}var so={NO_CREDENTIALS:{message:"AWS credentials not found",solution:`Configure AWS credentials using one of these methods:
2511
2511
  1. Set environment variables: AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
2512
2512
  2. Create ~/.aws/credentials file with your credentials
2513
2513
  3. Use an IAM role (for EC2 instances)
2514
- 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 co(e){return oo[e]}function va(e,t){let a=co(e);return new fe(a.message,e,a.solution,t)}class te{static verboseMode=!1;static debugMode=!1;static setVerbose(e){this.verboseMode=e}static setDebug(e){this.debugMode=e}static verbose(e,...t){if(this.verboseMode)console.log(`[VERBOSE] ${e}`,...t)}static debug(e,...t){if(this.debugMode)console.log(`[DEBUG] ${e}`,...t)}static info(e,...t){console.log(`ℹ ${e}`,...t)}static warn(e,...t){console.warn(`⚠ ${e}`,...t)}static error(e,t){if(console.error(`✖ ${e}`),t){if(t instanceof fe)console.error(t.toString());else console.error(t.message);if(this.debugMode&&t.stack)console.error(`
2515
- Stack trace:`),console.error(t.stack)}}static success(e){console.log(`✔ ${e}`)}}function wu(e){if(!e)throw va("MISSING_CONFIG");if(!e.project)throw new ht("Missing required field: project","Add a project configuration with name, slug, and region",{field:"project"});if(!e.project.name)throw new ht("Missing required field: project.name","Add a project name to your configuration",{field:"project.name"});if(!e.project.slug)throw new ht("Missing required field: project.slug","Add a project slug (lowercase, alphanumeric with hyphens)",{field:"project.slug"});if(!/^[a-z0-9-]+$/.test(e.project.slug))throw new ir("Invalid project slug format","Use only lowercase letters, numbers, and hyphens",{slug:e.project.slug});if(e.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(e.project.region))throw va("INVALID_REGION",{region:e.project.region})}te.success("Configuration validation passed")}function Eu(e){let t=[];if(e.environments?.production&&e.infrastructure?.database){let a=e.infrastructure.database;if((a.postgres||a.mysql)&&!a.postgres?.multiAZ&&!a.mysql?.multiAZ)t.push("Production database should use Multi-AZ for high availability")}if(e.infrastructure?.storage){for(let[a,r]of Object.entries(e.infrastructure.storage))if(r.encryption===!1)t.push(`Storage "${a}" is not encrypted - consider enabling encryption for security`)}if(e.infrastructure?.storage){for(let[a,r]of Object.entries(e.infrastructure.storage))if(r.public===!0)t.push(`Storage "${a}" is publicly accessible - ensure this is intentional`)}if(e.infrastructure?.database){let a=e.infrastructure.database;if(a.postgres||a.mysql){let r=a.postgres?.backupRetentionDays||a.mysql?.backupRetentionDays;if(!r||r<7)t.push("Database backup retention is less than 7 days - consider increasing for production")}}if(!e.infrastructure?.monitoring)t.push("No monitoring configured - consider adding CloudWatch alarms");return t}async function Pu(e="default"){try{te.verbose("Resolving AWS credentials...");let t=await Zt(e);if(!t.accessKeyId||!t.secretAccessKey)throw new Ie("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:",t.accessKeyId.substring(0,8)+"..."),te.verbose("Testing credentials with GetCallerIdentity...");let a;try{a=await qs(t),te.verbose("Credentials are valid"),te.debug("Account ID:",a)}catch(r){if(r instanceof Error)if(r.message.includes("InvalidClientTokenId"))throw new Ie("Invalid AWS access key ID","Check that your AWS_ACCESS_KEY_ID is correct");else if(r.message.includes("SignatureDoesNotMatch"))throw new Ie("Invalid AWS secret access key","Check that your AWS_SECRET_ACCESS_KEY is correct");else if(r.message.includes("ExpiredToken"))throw new Ie("AWS credentials have expired","Refresh your temporary credentials or use long-term credentials");else throw new Ie(`Failed to validate credentials: ${r.message}`,"Verify your AWS credentials are correct and have the necessary permissions");throw r}return{valid:!0,accountId:a,region:t.region}}catch(t){if(t instanceof Ie)throw t;return{valid:!1,error:t instanceof Error?t.message:"Unknown error"}}}async function Iu(e,t){return{allowed:t,denied:[]}}function lo(e){let t=new Set(["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate","cloudformation:ListStacks"]);if(e.infrastructure){if(e.infrastructure.storage)t.add("s3:CreateBucket"),t.add("s3:DeleteBucket"),t.add("s3:PutBucketPolicy"),t.add("s3:PutBucketVersioning"),t.add("s3:PutBucketEncryption"),t.add("s3:PutObject"),t.add("s3:GetObject");if(e.infrastructure.compute){if(e.infrastructure.compute.server)t.add("ec2:RunInstances"),t.add("ec2:TerminateInstances"),t.add("ec2:DescribeInstances"),t.add("autoscaling:CreateAutoScalingGroup"),t.add("autoscaling:UpdateAutoScalingGroup"),t.add("autoscaling:DeleteAutoScalingGroup"),t.add("elasticloadbalancing:CreateLoadBalancer"),t.add("elasticloadbalancing:DeleteLoadBalancer");if(e.infrastructure.compute.fargate)t.add("ecs:CreateCluster"),t.add("ecs:DeleteCluster"),t.add("ecs:CreateService"),t.add("ecs:UpdateService"),t.add("ecs:DeleteService"),t.add("ecs:RegisterTaskDefinition")}if(e.infrastructure.database){if(e.infrastructure.database.postgres||e.infrastructure.database.mysql)t.add("rds:CreateDBInstance"),t.add("rds:DeleteDBInstance"),t.add("rds:ModifyDBInstance"),t.add("rds:DescribeDBInstances");if(e.infrastructure.database.dynamodb)t.add("dynamodb:CreateTable"),t.add("dynamodb:DeleteTable"),t.add("dynamodb:UpdateTable"),t.add("dynamodb:DescribeTable")}if(e.infrastructure.functions)t.add("lambda:CreateFunction"),t.add("lambda:DeleteFunction"),t.add("lambda:UpdateFunctionCode"),t.add("lambda:UpdateFunctionConfiguration"),t.add("lambda:AddPermission");if(e.infrastructure.cdn)t.add("cloudfront:CreateDistribution"),t.add("cloudfront:UpdateDistribution"),t.add("cloudfront:DeleteDistribution"),t.add("cloudfront:GetDistribution");if(e.infrastructure.network)t.add("ec2:CreateVpc"),t.add("ec2:DeleteVpc"),t.add("ec2:CreateSubnet"),t.add("ec2:DeleteSubnet"),t.add("ec2:CreateInternetGateway"),t.add("ec2:DeleteInternetGateway"),t.add("ec2:CreateNatGateway"),t.add("ec2:DeleteNatGateway"),t.add("ec2:CreateRouteTable"),t.add("ec2:DeleteRouteTable"),t.add("ec2:CreateSecurityGroup"),t.add("ec2:DeleteSecurityGroup")}return t.add("iam:CreateRole"),t.add("iam:DeleteRole"),t.add("iam:AttachRolePolicy"),t.add("iam:DetachRolePolicy"),t.add("iam:PutRolePolicy"),t.add("iam:GetRole"),t.add("iam:PassRole"),Array.from(t).sort()}function Ru(e){let t=lo(e);return JSON.stringify({Version:"2012-10-17",Statement:[{Effect:"Allow",Action:t,Resource:"*"}]},null,2)}var H={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 Nu(e){let t=[];if(te.verbose("Checking AWS service quotas..."),e.infrastructure?.compute?.server){let r=e.infrastructure.compute.server.autoScaling?.max||1;t.push({service:"EC2",quotaName:"Running On-Demand Instances",currentValue:r,limit:H.ec2["Running On-Demand Instances"],percentage:r/H.ec2["Running On-Demand Instances"]*100,warning:r>H.ec2["Running On-Demand Instances"]*0.8})}if(e.infrastructure?.network?.vpc)t.push({service:"EC2",quotaName:"VPCs",currentValue:1,limit:H.ec2.VPCs,percentage:1/H.ec2.VPCs*100,warning:!1});if(e.infrastructure?.database?.postgres||e.infrastructure?.database?.mysql)t.push({service:"RDS",quotaName:"DB Instances",currentValue:1,limit:H.rds["DB Instances"],percentage:1/H.rds["DB Instances"]*100,warning:!1});if(e.infrastructure?.storage){let r=Object.keys(e.infrastructure.storage).length;t.push({service:"S3",quotaName:"Buckets",currentValue:r,limit:H.s3.Buckets,percentage:r/H.s3.Buckets*100,warning:r>H.s3.Buckets*0.8})}if(e.infrastructure?.functions){let r=0;for(let n of Object.values(e.infrastructure.functions))if(Array.isArray(n))r+=n.length;t.push({service:"Lambda",quotaName:"Functions (estimated)",currentValue:r,limit:1000,percentage:r/1000*100,warning:r>800})}if(e.infrastructure?.database?.dynamodb){let r=e.infrastructure.database.dynamodb.tables?.length||0;t.push({service:"DynamoDB",quotaName:"Tables",currentValue:r,limit:H.dynamodb.Tables,percentage:r/H.dynamodb.Tables*100,warning:r>H.dynamodb.Tables*0.8})}let a=t.filter((r)=>r.warning);if(a.length>0){te.warn("Service quota warnings detected:");for(let r of a)te.warn(` ${r.service} - ${r.quotaName}: ${r.currentValue}/${r.limit} (${r.percentage.toFixed(1)}%)`)}else te.verbose("All service quotas are within limits");return t}function Du(e){if(e.length===0)return"No quotas to check";let t=`Service Quota Usage:
2514
+ 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 oo(e){return so[e]}function Ta(e,t){let a=oo(e);return new ye(a.message,e,a.solution,t)}class ee{static verboseMode=!1;static debugMode=!1;static setVerbose(e){this.verboseMode=e}static setDebug(e){this.debugMode=e}static verbose(e,...t){if(this.verboseMode)console.log(`[VERBOSE] ${e}`,...t)}static debug(e,...t){if(this.debugMode)console.log(`[DEBUG] ${e}`,...t)}static info(e,...t){console.log(`ℹ ${e}`,...t)}static warn(e,...t){console.warn(`⚠ ${e}`,...t)}static error(e,t){if(console.error(`✖ ${e}`),t){if(t instanceof ye)console.error(t.toString());else console.error(t.message);if(this.debugMode&&t.stack)console.error(`
2515
+ Stack trace:`),console.error(t.stack)}}static success(e){console.log(`✔ ${e}`)}}function vu(e){if(!e)throw Ta("MISSING_CONFIG");if(!e.project)throw new gt("Missing required field: project","Add a project configuration with name, slug, and region",{field:"project"});if(!e.project.name)throw new gt("Missing required field: project.name","Add a project name to your configuration",{field:"project.name"});if(!e.project.slug)throw new gt("Missing required field: project.slug","Add a project slug (lowercase, alphanumeric with hyphens)",{field:"project.slug"});if(!/^[a-z0-9-]+$/.test(e.project.slug))throw new nr("Invalid project slug format","Use only lowercase letters, numbers, and hyphens",{slug:e.project.slug});if(e.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(e.project.region))throw Ta("INVALID_REGION",{region:e.project.region})}ee.success("Configuration validation passed")}function wu(e){let t=[];if(e.environments?.production&&e.infrastructure?.database){let a=e.infrastructure.database;if((a.postgres||a.mysql)&&!a.postgres?.multiAZ&&!a.mysql?.multiAZ)t.push("Production database should use Multi-AZ for high availability")}if(e.infrastructure?.storage){for(let[a,r]of Object.entries(e.infrastructure.storage))if(r.encryption===!1)t.push(`Storage "${a}" is not encrypted - consider enabling encryption for security`)}if(e.infrastructure?.storage){for(let[a,r]of Object.entries(e.infrastructure.storage))if(r.public===!0)t.push(`Storage "${a}" is publicly accessible - ensure this is intentional`)}if(e.infrastructure?.database){let a=e.infrastructure.database;if(a.postgres||a.mysql){let r=a.postgres?.backupRetentionDays||a.mysql?.backupRetentionDays;if(!r||r<7)t.push("Database backup retention is less than 7 days - consider increasing for production")}}if(!e.infrastructure?.monitoring)t.push("No monitoring configured - consider adding CloudWatch alarms");return t}async function Eu(e="default"){try{ee.verbose("Resolving AWS credentials...");let t=await Yt(e);if(!t.accessKeyId||!t.secretAccessKey)throw new Pe("AWS credentials are incomplete","Ensure both AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are set");ee.verbose("Credentials resolved successfully"),ee.debug("Access Key ID:",t.accessKeyId.substring(0,8)+"..."),ee.verbose("Testing credentials with GetCallerIdentity...");let a;try{a=await qs(t),ee.verbose("Credentials are valid"),ee.debug("Account ID:",a)}catch(r){if(r instanceof Error)if(r.message.includes("InvalidClientTokenId"))throw new Pe("Invalid AWS access key ID","Check that your AWS_ACCESS_KEY_ID is correct");else if(r.message.includes("SignatureDoesNotMatch"))throw new Pe("Invalid AWS secret access key","Check that your AWS_SECRET_ACCESS_KEY is correct");else if(r.message.includes("ExpiredToken"))throw new Pe("AWS credentials have expired","Refresh your temporary credentials or use long-term credentials");else throw new Pe(`Failed to validate credentials: ${r.message}`,"Verify your AWS credentials are correct and have the necessary permissions");throw r}return{valid:!0,accountId:a,region:t.region}}catch(t){if(t instanceof Pe)throw t;return{valid:!1,error:t instanceof Error?t.message:"Unknown error"}}}async function Pu(e,t){return{allowed:t,denied:[]}}function co(e){let t=new Set(["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate","cloudformation:ListStacks"]);if(e.infrastructure){if(e.infrastructure.storage)t.add("s3:CreateBucket"),t.add("s3:DeleteBucket"),t.add("s3:PutBucketPolicy"),t.add("s3:PutBucketVersioning"),t.add("s3:PutBucketEncryption"),t.add("s3:PutObject"),t.add("s3:GetObject");if(e.infrastructure.compute){if(e.infrastructure.compute.server)t.add("ec2:RunInstances"),t.add("ec2:TerminateInstances"),t.add("ec2:DescribeInstances"),t.add("autoscaling:CreateAutoScalingGroup"),t.add("autoscaling:UpdateAutoScalingGroup"),t.add("autoscaling:DeleteAutoScalingGroup"),t.add("elasticloadbalancing:CreateLoadBalancer"),t.add("elasticloadbalancing:DeleteLoadBalancer");if(e.infrastructure.compute.fargate)t.add("ecs:CreateCluster"),t.add("ecs:DeleteCluster"),t.add("ecs:CreateService"),t.add("ecs:UpdateService"),t.add("ecs:DeleteService"),t.add("ecs:RegisterTaskDefinition")}if(e.infrastructure.database){if(e.infrastructure.database.postgres||e.infrastructure.database.mysql)t.add("rds:CreateDBInstance"),t.add("rds:DeleteDBInstance"),t.add("rds:ModifyDBInstance"),t.add("rds:DescribeDBInstances");if(e.infrastructure.database.dynamodb)t.add("dynamodb:CreateTable"),t.add("dynamodb:DeleteTable"),t.add("dynamodb:UpdateTable"),t.add("dynamodb:DescribeTable")}if(e.infrastructure.functions)t.add("lambda:CreateFunction"),t.add("lambda:DeleteFunction"),t.add("lambda:UpdateFunctionCode"),t.add("lambda:UpdateFunctionConfiguration"),t.add("lambda:AddPermission");if(e.infrastructure.cdn)t.add("cloudfront:CreateDistribution"),t.add("cloudfront:UpdateDistribution"),t.add("cloudfront:DeleteDistribution"),t.add("cloudfront:GetDistribution");if(e.infrastructure.network)t.add("ec2:CreateVpc"),t.add("ec2:DeleteVpc"),t.add("ec2:CreateSubnet"),t.add("ec2:DeleteSubnet"),t.add("ec2:CreateInternetGateway"),t.add("ec2:DeleteInternetGateway"),t.add("ec2:CreateNatGateway"),t.add("ec2:DeleteNatGateway"),t.add("ec2:CreateRouteTable"),t.add("ec2:DeleteRouteTable"),t.add("ec2:CreateSecurityGroup"),t.add("ec2:DeleteSecurityGroup")}return t.add("iam:CreateRole"),t.add("iam:DeleteRole"),t.add("iam:AttachRolePolicy"),t.add("iam:DetachRolePolicy"),t.add("iam:PutRolePolicy"),t.add("iam:GetRole"),t.add("iam:PassRole"),Array.from(t).sort()}function Iu(e){let t=co(e);return JSON.stringify({Version:"2012-10-17",Statement:[{Effect:"Allow",Action:t,Resource:"*"}]},null,2)}var H={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 Ru(e){let t=[];if(ee.verbose("Checking AWS service quotas..."),e.infrastructure?.compute?.server){let r=e.infrastructure.compute.server.autoScaling?.max||1;t.push({service:"EC2",quotaName:"Running On-Demand Instances",currentValue:r,limit:H.ec2["Running On-Demand Instances"],percentage:r/H.ec2["Running On-Demand Instances"]*100,warning:r>H.ec2["Running On-Demand Instances"]*0.8})}if(e.infrastructure?.network?.vpc)t.push({service:"EC2",quotaName:"VPCs",currentValue:1,limit:H.ec2.VPCs,percentage:1/H.ec2.VPCs*100,warning:!1});if(e.infrastructure?.database?.postgres||e.infrastructure?.database?.mysql)t.push({service:"RDS",quotaName:"DB Instances",currentValue:1,limit:H.rds["DB Instances"],percentage:1/H.rds["DB Instances"]*100,warning:!1});if(e.infrastructure?.storage){let r=Object.keys(e.infrastructure.storage).length;t.push({service:"S3",quotaName:"Buckets",currentValue:r,limit:H.s3.Buckets,percentage:r/H.s3.Buckets*100,warning:r>H.s3.Buckets*0.8})}if(e.infrastructure?.functions){let r=0;for(let n of Object.values(e.infrastructure.functions))if(Array.isArray(n))r+=n.length;t.push({service:"Lambda",quotaName:"Functions (estimated)",currentValue:r,limit:1000,percentage:r/1000*100,warning:r>800})}if(e.infrastructure?.database?.dynamodb){let r=e.infrastructure.database.dynamodb.tables?.length||0;t.push({service:"DynamoDB",quotaName:"Tables",currentValue:r,limit:H.dynamodb.Tables,percentage:r/H.dynamodb.Tables*100,warning:r>H.dynamodb.Tables*0.8})}let a=t.filter((r)=>r.warning);if(a.length>0){ee.warn("Service quota warnings detected:");for(let r of a)ee.warn(` ${r.service} - ${r.quotaName}: ${r.currentValue}/${r.limit} (${r.percentage.toFixed(1)}%)`)}else ee.verbose("All service quotas are within limits");return t}function Nu(e){if(e.length===0)return"No quotas to check";let t=`Service Quota Usage:
2516
2516
 
2517
2517
  `,a=e.reduce((r,n)=>{if(!r[n.service])r[n.service]=[];return r[n.service].push(n),r},{});for(let[r,n]of Object.entries(a)){t+=`${r}:
2518
2518
  `;for(let i of n){let s=i.warning?"⚠":"✓";t+=` ${s} ${i.quotaName}: ${i.currentValue}/${i.limit} (${i.percentage.toFixed(1)}%)
2519
2519
  `}t+=`
2520
- `}return t}function ku(e){let t=[];for(let a of e)if(a.percentage>=100)t.push(`Request quota increase for ${a.service} - ${a.quotaName} (currently ${a.limit})`);else if(a.warning)t.push(`Consider requesting quota increase for ${a.service} - ${a.quotaName} (${a.percentage.toFixed(1)}% used)`);return t}class or{cacheDir;ttl;constructor(e,t={}){this.cacheDir=e,this.ttl=t.ttl||86400000}ensureCacheDir(){if(!ut(this.cacheDir))uo(this.cacheDir,{recursive:!0})}getCachePath(e){let t=sr("sha256").update(e).digest("hex");return Bt(this.cacheDir,`${t}.json`)}get(e){let t=this.getCachePath(e);if(!ut(t))return;try{let a=Ea(t,"utf-8"),r=JSON.parse(a);if(Date.now()-r.timestamp>this.ttl){qe(t);return}return r.value}catch{qe(t);return}}set(e,t,a){this.ensureCacheDir();let r=this.getCachePath(e),n={value:t,timestamp:Date.now(),hash:a};mo(r,JSON.stringify(n),"utf-8")}has(e){return this.get(e)!==void 0}clear(){if(!ut(this.cacheDir))return;let e=wa(this.cacheDir);for(let t of e)qe(Bt(this.cacheDir,t))}prune(){if(!ut(this.cacheDir))return;let e=wa(this.cacheDir),t=Date.now();for(let a of e){let r=Bt(this.cacheDir,a);try{let n=Ea(r,"utf-8"),i=JSON.parse(n);if(t-i.timestamp>this.ttl)qe(r)}catch{qe(r)}}}}class cr{cache;constructor(e=ti("cache","templates")){this.cache=new or(e,{ttl:86400000})}getTemplate(e){return this.cache.get(`template:${e}`)}setTemplate(e,t){let a=this.hashTemplate(t);this.cache.set(`template:${e}`,t,a)}hasChanged(e,t){let a=this.cache.get(`template:${e}`);if(!a)return!0;let r=this.hashTemplate(a),n=this.hashTemplate(t);return r!==n}hashTemplate(e){return sr("sha256").update(e).digest("hex")}clear(){this.cache.clear()}prune(){this.cache.prune()}}var _t=null;function xu(){if(!_t)_t=new cr;return _t}async function lr(e,t={}){let a=t.algorithm||"sha256",r=t.chunkSize||65536;return new Promise((n,i)=>{let s=Xt(a),o=po(e,{highWaterMark:r});o.on("data",(c)=>s.update(c)),o.on("end",()=>n(s.digest("hex"))),o.on("error",i)})}function ur(e,t="sha256"){return Xt(t).update(e).digest("hex")}function Wu(e,t="sha256"){return Xt(t).update(e).digest("hex")}async function Gu(e,t={}){let a=t.ignorePatterns||["node_modules",".git","dist","build",It()],r=[];async function n(i){let s=go(i,{withFileTypes:!0});for(let o of s){let c=ho(i,o.name),l=yo(e,c);if(a.some((u)=>l.includes(u)))continue;if(o.isDirectory())await n(c);else if(o.isFile()){let u=Tt(c),m=await lr(c,t);r.push({path:l,hash:m,size:u.size,mtime:u.mtimeMs})}}}return await n(e),r}function Fu(e){let t=[...e].sort((a,r)=>a.path.localeCompare(r.path)).map((a)=>`${a.path}:${a.hash}`).join(`
2521
- `);return ur(t)}function Vu(e){let t=Tt(e);return ur(`${e}:${t.size}:${t.mtimeMs}`)}function Uu(e,t){let a=new Map(e.map((o)=>[o.path,o])),r=new Map(t.map((o)=>[o.path,o])),n=[],i=[],s=[];for(let[o,c]of r){let l=a.get(o);if(!l)n.push(c);else if(l.hash!==c.hash)i.push(c)}for(let[o,c]of a)if(!r.has(o))s.push(c);return{added:n,modified:i,deleted:s}}class fo{cache;constructor(){this.cache=new Map}get(e){let t=Tt(e),a=this.cache.get(e);if(a&&a.mtime===t.mtimeMs&&a.size===t.size)return a.hash;return}set(e,t){let a=Tt(e);this.cache.set(e,{hash:t,mtime:a.mtimeMs,size:a.size})}async getOrCompute(e,t={}){let a=this.get(e);if(a)return a;let r=await lr(e,t);return this.set(e,r),r}clear(){this.cache.clear()}}async function ea(e,t={}){let a=t.concurrency||5,r=t.stopOnError??!0,n=[],i=[],s=Date.now(),o=[...e],c=[];async function l(p,g){try{let h=await p();n[g]=h}catch(h){let y=h instanceof Error?h:Error(String(h));if(i.push(y),r)throw o.length=0,y}}let u=0;while(o.length>0||c.length>0){while(c.length<a&&o.length>0){let p=o.shift(),g=u++,h=l(p,g);c.push(h)}if(c.length>0){await Promise.race(c);for(let p=c.length-1;p>=0;p--)if(await Promise.race([c[p].then(()=>!0),Promise.resolve(!1)]))c.splice(p,1)}if(r&&i.length>0)break}let m=Date.now()-s;return{results:n.filter((p)=>p!==void 0),errors:i,duration:m}}async function ju(e,t,a={}){let r=e.map((n)=>()=>t(n));return ea(r,a)}async function Ku(e,t,a=5){let r=e.map((i,s)=>()=>t(i,s)),n=await ea(r,{concurrency:a,stopOnError:!1});if(n.errors.length>0)throw AggregateError(n.errors,"Parallel map failed");return n.results}async function Hu(e,t={}){let a=t.retries||3,r=t.retryDelay||1000,n=e.map((i)=>async()=>{let s;for(let o=0;o<=a;o++)try{return await i()}catch(c){if(s=c instanceof Error?c:Error(String(c)),o<a)await dr(r*(o+1))}throw s});return ea(n,t)}async function qu(e){let t=[];for(let a of e){let r=await a();t.push(r)}return t}function dr(e){return new Promise((t)=>setTimeout(t,e))}async function zu(e,t,a="Operation timed out"){return Promise.race([e(),new Promise((r,n)=>setTimeout(()=>n(Error(a)),t))])}class So{maxConcurrent;minInterval;queue=[];running=0;lastExecution=0;constructor(e=5,t=100){this.maxConcurrent=e,this.minInterval=t}async execute(e){await this.waitForSlot(),this.running++,this.lastExecution=Date.now();try{return await e()}finally{this.running--,this.processQueue()}}waitForSlot(){if(this.running<this.maxConcurrent){let e=Date.now()-this.lastExecution;if(e>=this.minInterval)return Promise.resolve();return dr(this.minInterval-e)}return new Promise((e)=>this.queue.push(e))}processQueue(){if(this.queue.length>0&&this.running<this.maxConcurrent)this.queue.shift()()}stats(){return{running:this.running,queued:this.queue.length}}}function bo(e,t){let a=[];for(let r=0;r<e.length;r+=t)a.push(e.slice(r,r+t));return a}async function Qu(e,t,a){let r=bo(e,t),n=[];for(let i of r){let s=await a(i);n.push(...s)}return n}function Ju(e,t){let a=[],r=[],n=[],i=[],s=e.Resources||{},o=t.Resources||{},c=new Set(Object.keys(s)),l=new Set(Object.keys(o));for(let p of l)if(!c.has(p))a.push(p);for(let p of c)if(!l.has(p))n.push(p);for(let p of l)if(c.has(p)){let g=s[p],h=o[p];if(JSON.stringify(g)!==JSON.stringify(h))r.push(p);else i.push(p)}let u=JSON.stringify(e.Parameters||{})!==JSON.stringify(t.Parameters||{}),m=JSON.stringify(e.Outputs||{})!==JSON.stringify(t.Outputs||{});return{added:a,modified:r,deleted:n,unchanged:i,parametersChanged:u,outputsChanged:m,hasChanges:a.length>0||r.length>0||n.length>0||u||m}}function Yu(e){let t=[];if(!e.hasChanges)return"No changes detected";if(e.added.length>0){t.push(`Added resources (${e.added.length}):`);for(let a of e.added)t.push(` + ${a}`)}if(e.modified.length>0){t.push(`Modified resources (${e.modified.length}):`);for(let a of e.modified)t.push(` ~ ${a}`)}if(e.deleted.length>0){t.push(`Deleted resources (${e.deleted.length}):`);for(let a of e.deleted)t.push(` - ${a}`)}if(e.parametersChanged)t.push("Parameters changed");if(e.outputsChanged)t.push("Outputs changed");return t.join(`
2522
- `)}function Zu(e,t,a){if(e.deleted.length>0)return!0;for(let r of e.modified){let n=t.Resources[r],i=a.Resources[r];if(n.Type!==i.Type)return!0;let s=Ao(i.Type);for(let o of s){let c=n.Properties?.[o],l=i.Properties?.[o];if(JSON.stringify(c)!==JSON.stringify(l))return!0}}return!1}function Ao(e){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"]}[e]||[]}function Xu(e){let t=[],a=[],r=[];t.push(...e.added);for(let n of e.modified)a.push(n);return r.push(...e.deleted),{safe:t,caution:a,dangerous:r}}function ed(e){if(!e.hasChanges)return{strategy:"skip",reason:"No changes detected"};if(e.deleted.length>0)return{strategy:"replace",reason:"Resources will be deleted"};if(e.added.length>0&&e.modified.length===0)return{strategy:"update",reason:"Only new resources added"};return{strategy:"update",reason:"Resources will be updated"}}function td(e){let t=e.added.length+e.modified.length+e.deleted.length+e.unchanged.length,a=e.added.length+e.modified.length+e.deleted.length,r=t>0?a/t*100:0;return{total:t,added:e.added.length,modified:e.modified.length,deleted:e.deleted.length,unchanged:e.unchanged.length,changePercentage:r}}var ad={$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 rd(e){let t=[];if(!e.project)t.push("Missing required field: project");else{if(!e.project.name)t.push("Missing required field: project.name");if(!e.project.slug)t.push("Missing required field: project.slug")}if(e.project?.slug&&!/^[a-z0-9-]+$/.test(e.project.slug))t.push("Invalid project.slug: must contain only lowercase letters, numbers, and hyphens");let a=["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(e.project?.region&&!a.includes(e.project.region))t.push(`Invalid region: ${e.project.region}. Must be one of: ${a.join(", ")}`);if(e.mode&&!["server","serverless"].includes(e.mode))t.push("Invalid mode: must be one of server or serverless");return{valid:t.length===0,errors:t}}var mr={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 ta(){return mr}function nd(){return mr.enabled}function id(e){let t=ta();if(!t.enabled)return"";switch(e.toLowerCase()){case"dynamodb":return t.dynamodbEndpoint;case"s3":return t.s3Endpoint;case"localstack":case"cloudformation":case"lambda":case"apigateway":case"sns":case"sqs":case"cloudwatch":case"iam":case"sts":return t.localstackEndpoint;default:return t.localstackEndpoint}}function sd(){let e=ta();return{accessKeyId:e.awsAccessKeyId,secretAccessKey:e.awsSecretAccessKey,region:e.awsRegion}}function od(){let e=ta();if(!e.enabled)return{};return{AWS_ACCESS_KEY_ID:e.awsAccessKeyId,AWS_SECRET_ACCESS_KEY:e.awsSecretAccessKey,AWS_REGION:e.awsRegion,AWS_ENDPOINT_URL:e.localstackEndpoint,LOCALSTACK_ENDPOINT:e.localstackEndpoint,TS_CLOUD_LOCAL:"true"}}class pr{stacks=new Map;stackEvents=new Map;async createStack(e){let t=`arn:aws:cloudformation:${e.region||"us-east-1"}:123456789012:stack/${e.StackName}/${Date.now()}`;return this.stacks.set(e.StackName,{StackId:t,StackName:e.StackName,StackStatus:"CREATE_IN_PROGRESS",CreationTime:new Date().toISOString(),TemplateBody:e.TemplateBody,Parameters:e.Parameters||[]}),this.addEvent(e.StackName,{EventId:Date.now().toString(),StackName:e.StackName,LogicalResourceId:e.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_IN_PROGRESS"}),setTimeout(()=>{let a=this.stacks.get(e.StackName);if(a)a.StackStatus="CREATE_COMPLETE",this.addEvent(e.StackName,{EventId:(Date.now()+1).toString(),StackName:e.StackName,LogicalResourceId:e.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_COMPLETE"})},100),{StackId:t}}async updateStack(e){let t=this.stacks.get(e.StackName);if(!t)throw Error(`Stack ${e.StackName} does not exist`);return t.StackStatus="UPDATE_IN_PROGRESS",t.TemplateBody=e.TemplateBody||t.TemplateBody,this.addEvent(e.StackName,{EventId:Date.now().toString(),StackName:e.StackName,LogicalResourceId:e.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_IN_PROGRESS"}),setTimeout(()=>{t.StackStatus="UPDATE_COMPLETE",this.addEvent(e.StackName,{EventId:(Date.now()+1).toString(),StackName:e.StackName,LogicalResourceId:e.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_COMPLETE"})},100),{StackId:t.StackId}}async deleteStack(e){let t=this.stacks.get(e.StackName);if(!t)throw Error(`Stack ${e.StackName} does not exist`);t.StackStatus="DELETE_IN_PROGRESS",this.addEvent(e.StackName,{EventId:Date.now().toString(),StackName:e.StackName,LogicalResourceId:e.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_IN_PROGRESS"}),setTimeout(()=>{this.stacks.delete(e.StackName),this.addEvent(e.StackName,{EventId:(Date.now()+1).toString(),StackName:e.StackName,LogicalResourceId:e.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_COMPLETE"})},100)}async describeStacks(e){if(e.StackName){let t=this.stacks.get(e.StackName);if(!t)throw Error(`Stack ${e.StackName} does not exist`);return{Stacks:[t]}}return{Stacks:Array.from(this.stacks.values())}}async describeStackEvents(e){return{StackEvents:this.stackEvents.get(e.StackName)||[]}}addEvent(e,t){if(!this.stackEvents.has(e))this.stackEvents.set(e,[]);this.stackEvents.get(e).unshift(t)}reset(){this.stacks.clear(),this.stackEvents.clear()}}class gr{buckets=new Map;async createBucket(e){return this.buckets.set(e.Bucket,new Map),{Location:`/${e.Bucket}`}}async deleteBucket(e){this.buckets.delete(e.Bucket)}async putObject(e){let t=this.buckets.get(e.Bucket);if(!t)t=new Map,this.buckets.set(e.Bucket,t);return t.set(e.Key,Buffer.from(e.Body||"")),{ETag:`"${Date.now()}"`}}async getObject(e){let t=this.buckets.get(e.Bucket);if(!t)throw Error(`Bucket ${e.Bucket} does not exist`);let a=t.get(e.Key);if(!a)throw Error(`Object ${e.Key} does not exist`);return{Body:a,ContentLength:a.length}}async deleteObject(e){let t=this.buckets.get(e.Bucket);if(t)t.delete(e.Key)}async listObjects(e){let t=this.buckets.get(e.Bucket);if(!t)throw Error(`Bucket ${e.Bucket} does not exist`);return{Contents:Array.from(t.keys()).map((a)=>({Key:a,Size:t.get(a).length,LastModified:new Date().toISOString()}))}}reset(){this.buckets.clear()}}class hr{tables=new Map;data=new Map;async createTable(e){return this.tables.set(e.TableName,{TableName:e.TableName,KeySchema:e.KeySchema,AttributeDefinitions:e.AttributeDefinitions,TableStatus:"ACTIVE",CreationDateTime:new Date().toISOString()}),this.data.set(e.TableName,new Map),{TableDescription:this.tables.get(e.TableName)}}async deleteTable(e){this.tables.delete(e.TableName),this.data.delete(e.TableName)}async putItem(e){let t=this.data.get(e.TableName);if(!t)t=new Map,this.data.set(e.TableName,t);let a=JSON.stringify(e.Item);t.set(a,e.Item)}async getItem(e){let t=this.data.get(e.TableName);if(!t)return{};let a=JSON.stringify(e.Key),r=t.get(a);return r?{Item:r}:{}}async deleteItem(e){let t=this.data.get(e.TableName);if(t){let a=JSON.stringify(e.Key);t.delete(a)}}async scan(e){let t=this.data.get(e.TableName);if(!t)return{Items:[]};return{Items:Array.from(t.values())}}reset(){this.tables.clear(),this.data.clear()}}function cd(e){return{cloudformation:new pr,s3:new gr,dynamodb:new hr}}class yr{environments=new Map;async createPreviewEnvironment(e){let{branch:t,pr:a,commitSha:r,ttl:n=24,baseConfig:i,region:s="us-east-1"}=e,o=this.generatePreviewId(t,a,r),c=this.generatePreviewName(t,a),l=`preview-${c}`,u=new Date,m=new Date(u.getTime()+n*60*60*1000),p={id:o,name:c,branch:t,pr:a,commitSha:r,createdAt:u,expiresAt:m,status:"creating",stackName:l,region:s,resources:[]};this.environments.set(o,p);try{let g=this.createPreviewConfig(i,c);return p.status="active",p.url=`https://${c}.preview.example.com`,p}catch(g){throw p.status="failed",g}}async destroyPreviewEnvironment(e){let t=this.environments.get(e);if(!t)throw Error(`Preview environment ${e} not found`);t.status="destroying";try{t.status="destroyed",this.environments.delete(e)}catch(a){throw Error(`Failed to destroy preview environment: ${a}`)}}getPreviewEnvironment(e){return this.environments.get(e)}getPreviewEnvironmentByBranch(e){return Array.from(this.environments.values()).find((t)=>t.branch===e)}getPreviewEnvironmentByPR(e){return Array.from(this.environments.values()).find((t)=>t.pr===e)}listPreviewEnvironments(){return Array.from(this.environments.values())}listActivePreviewEnvironments(){return this.listPreviewEnvironments().filter((e)=>e.status==="active")}async cleanupExpiredEnvironments(e={}){let{maxAge:t,keepCount:a,dryRun:r=!1}=e,n=[],i=[],s=new Date,o=this.listPreviewEnvironments().sort((c,l)=>l.createdAt.getTime()-c.createdAt.getTime());for(let c=0;c<o.length;c++){let l=o[c];if(l.status!=="active")continue;let u=!1;if(l.expiresAt<s)u=!0;if(t){if((s.getTime()-l.createdAt.getTime())/3600000>t)u=!0}if(a&&c>=a)u=!0;if(u)if(r)n.push(l.id);else try{await this.destroyPreviewEnvironment(l.id),n.push(l.id)}catch(m){i.push(l.id)}}return{destroyed:n,failed:i}}async updatePreviewEnvironment(e,t){let a=this.environments.get(e);if(!a)throw Error(`Preview environment ${e} not found`);a.commitSha=t,a.status="creating";try{return a.status="active",a}catch(r){throw a.status="failed",r}}async getPreviewEnvironmentsCost(){let e={},t=0;for(let a of this.environments.values())e[a.id]=0,t+=0;return{total:t,byEnvironment:e}}generatePreviewId(e,t,a){let r=e.replace(/[^a-z0-9-]/gi,"-").toLowerCase(),n=a?.substring(0,7)||Date.now().toString();return t?`pr-${t}-${n}`:`${r}-${n}`}generatePreviewName(e,t){let a=e.replace(/[^a-z0-9-]/gi,"-").toLowerCase();return t?`pr-${t}`:a}createPreviewConfig(e,t){return{...e,project:{...e.project,name:`${e.project.name} Preview (${t})`,slug:`${e.project.slug}-preview-${t}`}}}}var ld=new yr;function ud(e={}){let{workflowName:t="Preview Environment",trigger:a="pull_request",branches:r=["main","develop"],awsRegion:n="us-east-1",awsRole:i,configFile:s="cloud.config.ts",ttl:o=24}=e;return`name: ${t}
2520
+ `}return t}function Du(e){let t=[];for(let a of e)if(a.percentage>=100)t.push(`Request quota increase for ${a.service} - ${a.quotaName} (currently ${a.limit})`);else if(a.warning)t.push(`Consider requesting quota increase for ${a.service} - ${a.quotaName} (${a.percentage.toFixed(1)}% used)`);return t}class sr{cacheDir;ttl;constructor(e,t={}){this.cacheDir=e,this.ttl=t.ttl||86400000}ensureCacheDir(){if(!lt(this.cacheDir))lo(this.cacheDir,{recursive:!0})}getCachePath(e){let t=ir("sha256").update(e).digest("hex");return Wt(this.cacheDir,`${t}.json`)}get(e){let t=this.getCachePath(e);if(!lt(t))return;try{let a=wa(t,"utf-8"),r=JSON.parse(a);if(Date.now()-r.timestamp>this.ttl){qe(t);return}return r.value}catch{qe(t);return}}set(e,t,a){this.ensureCacheDir();let r=this.getCachePath(e),n={value:t,timestamp:Date.now(),hash:a};uo(r,JSON.stringify(n),"utf-8")}has(e){return this.get(e)!==void 0}clear(){if(!lt(this.cacheDir))return;let e=va(this.cacheDir);for(let t of e)qe(Wt(this.cacheDir,t))}prune(){if(!lt(this.cacheDir))return;let e=va(this.cacheDir),t=Date.now();for(let a of e){let r=Wt(this.cacheDir,a);try{let n=wa(r,"utf-8"),i=JSON.parse(n);if(t-i.timestamp>this.ttl)qe(r)}catch{qe(r)}}}}class or{cache;constructor(e=ei("cache","templates")){this.cache=new sr(e,{ttl:86400000})}getTemplate(e){return this.cache.get(`template:${e}`)}setTemplate(e,t){let a=this.hashTemplate(t);this.cache.set(`template:${e}`,t,a)}hasChanged(e,t){let a=this.cache.get(`template:${e}`);if(!a)return!0;let r=this.hashTemplate(a),n=this.hashTemplate(t);return r!==n}hashTemplate(e){return ir("sha256").update(e).digest("hex")}clear(){this.cache.clear()}prune(){this.cache.prune()}}var _t=null;function xu(){if(!_t)_t=new or;return _t}async function cr(e,t={}){let a=t.algorithm||"sha256",r=t.chunkSize||65536;return new Promise((n,i)=>{let s=Xt(a),o=mo(e,{highWaterMark:r});o.on("data",(c)=>s.update(c)),o.on("end",()=>n(s.digest("hex"))),o.on("error",i)})}function lr(e,t="sha256"){return Xt(t).update(e).digest("hex")}function Bu(e,t="sha256"){return Xt(t).update(e).digest("hex")}async function Uu(e,t={}){let a=t.ignorePatterns||["node_modules",".git","dist","build",Pt()],r=[];async function n(i){let s=po(i,{withFileTypes:!0});for(let o of s){let c=go(i,o.name),l=ho(e,c);if(a.some((u)=>l.includes(u)))continue;if(o.isDirectory())await n(c);else if(o.isFile()){let u=Ct(c),m=await cr(c,t);r.push({path:l,hash:m,size:u.size,mtime:u.mtimeMs})}}}return await n(e),r}function Gu(e){let t=[...e].sort((a,r)=>a.path.localeCompare(r.path)).map((a)=>`${a.path}:${a.hash}`).join(`
2521
+ `);return lr(t)}function Vu(e){let t=Ct(e);return lr(`${e}:${t.size}:${t.mtimeMs}`)}function Fu(e,t){let a=new Map(e.map((o)=>[o.path,o])),r=new Map(t.map((o)=>[o.path,o])),n=[],i=[],s=[];for(let[o,c]of r){let l=a.get(o);if(!l)n.push(c);else if(l.hash!==c.hash)i.push(c)}for(let[o,c]of a)if(!r.has(o))s.push(c);return{added:n,modified:i,deleted:s}}class yo{cache;constructor(){this.cache=new Map}get(e){let t=Ct(e),a=this.cache.get(e);if(a&&a.mtime===t.mtimeMs&&a.size===t.size)return a.hash;return}set(e,t){let a=Ct(e);this.cache.set(e,{hash:t,mtime:a.mtimeMs,size:a.size})}async getOrCompute(e,t={}){let a=this.get(e);if(a)return a;let r=await cr(e,t);return this.set(e,r),r}clear(){this.cache.clear()}}async function Zt(e,t={}){let a=t.concurrency||5,r=t.stopOnError??!0,n=[],i=[],s=Date.now(),o=[...e],c=[];async function l(p,g){try{let h=await p();n[g]=h}catch(h){let y=h instanceof Error?h:Error(String(h));if(i.push(y),r)throw o.length=0,y}}let u=0;while(o.length>0||c.length>0){while(c.length<a&&o.length>0){let p=o.shift(),g=u++,h=l(p,g);c.push(h)}if(c.length>0){await Promise.race(c);for(let p=c.length-1;p>=0;p--)if(await Promise.race([c[p].then(()=>!0),Promise.resolve(!1)]))c.splice(p,1)}if(r&&i.length>0)break}let m=Date.now()-s;return{results:n.filter((p)=>p!==void 0),errors:i,duration:m}}async function ju(e,t,a={}){let r=e.map((n)=>()=>t(n));return Zt(r,a)}async function Ku(e,t,a=5){let r=e.map((i,s)=>()=>t(i,s)),n=await Zt(r,{concurrency:a,stopOnError:!1});if(n.errors.length>0)throw AggregateError(n.errors,"Parallel map failed");return n.results}async function Hu(e,t={}){let a=t.retries||3,r=t.retryDelay||1000,n=e.map((i)=>async()=>{let s;for(let o=0;o<=a;o++)try{return await i()}catch(c){if(s=c instanceof Error?c:Error(String(c)),o<a)await ur(r*(o+1))}throw s});return Zt(n,t)}async function qu(e){let t=[];for(let a of e){let r=await a();t.push(r)}return t}function ur(e){return new Promise((t)=>setTimeout(t,e))}async function zu(e,t,a="Operation timed out"){return Promise.race([e(),new Promise((r,n)=>setTimeout(()=>n(Error(a)),t))])}class fo{maxConcurrent;minInterval;queue=[];running=0;lastExecution=0;constructor(e=5,t=100){this.maxConcurrent=e,this.minInterval=t}async execute(e){await this.waitForSlot(),this.running++,this.lastExecution=Date.now();try{return await e()}finally{this.running--,this.processQueue()}}waitForSlot(){if(this.running<this.maxConcurrent){let e=Date.now()-this.lastExecution;if(e>=this.minInterval)return Promise.resolve();return ur(this.minInterval-e)}return new Promise((e)=>this.queue.push(e))}processQueue(){if(this.queue.length>0&&this.running<this.maxConcurrent)this.queue.shift()()}stats(){return{running:this.running,queued:this.queue.length}}}function So(e,t){let a=[];for(let r=0;r<e.length;r+=t)a.push(e.slice(r,r+t));return a}async function Ju(e,t,a){let r=So(e,t),n=[];for(let i of r){let s=await a(i);n.push(...s)}return n}function Qu(e,t){let a=[],r=[],n=[],i=[],s=e.Resources||{},o=t.Resources||{},c=new Set(Object.keys(s)),l=new Set(Object.keys(o));for(let p of l)if(!c.has(p))a.push(p);for(let p of c)if(!l.has(p))n.push(p);for(let p of l)if(c.has(p)){let g=s[p],h=o[p];if(JSON.stringify(g)!==JSON.stringify(h))r.push(p);else i.push(p)}let u=JSON.stringify(e.Parameters||{})!==JSON.stringify(t.Parameters||{}),m=JSON.stringify(e.Outputs||{})!==JSON.stringify(t.Outputs||{});return{added:a,modified:r,deleted:n,unchanged:i,parametersChanged:u,outputsChanged:m,hasChanges:a.length>0||r.length>0||n.length>0||u||m}}function $u(e){let t=[];if(!e.hasChanges)return"No changes detected";if(e.added.length>0){t.push(`Added resources (${e.added.length}):`);for(let a of e.added)t.push(` + ${a}`)}if(e.modified.length>0){t.push(`Modified resources (${e.modified.length}):`);for(let a of e.modified)t.push(` ~ ${a}`)}if(e.deleted.length>0){t.push(`Deleted resources (${e.deleted.length}):`);for(let a of e.deleted)t.push(` - ${a}`)}if(e.parametersChanged)t.push("Parameters changed");if(e.outputsChanged)t.push("Outputs changed");return t.join(`
2522
+ `)}function Yu(e,t,a){if(e.deleted.length>0)return!0;for(let r of e.modified){let n=t.Resources[r],i=a.Resources[r];if(n.Type!==i.Type)return!0;let s=bo(i.Type);for(let o of s){let c=n.Properties?.[o],l=i.Properties?.[o];if(JSON.stringify(c)!==JSON.stringify(l))return!0}}return!1}function bo(e){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"]}[e]||[]}function Xu(e){let t=[],a=[],r=[];t.push(...e.added);for(let n of e.modified)a.push(n);return r.push(...e.deleted),{safe:t,caution:a,dangerous:r}}function Zu(e){if(!e.hasChanges)return{strategy:"skip",reason:"No changes detected"};if(e.deleted.length>0)return{strategy:"replace",reason:"Resources will be deleted"};if(e.added.length>0&&e.modified.length===0)return{strategy:"update",reason:"Only new resources added"};return{strategy:"update",reason:"Resources will be updated"}}function ed(e){let t=e.added.length+e.modified.length+e.deleted.length+e.unchanged.length,a=e.added.length+e.modified.length+e.deleted.length,r=t>0?a/t*100:0;return{total:t,added:e.added.length,modified:e.modified.length,deleted:e.deleted.length,unchanged:e.unchanged.length,changePercentage:r}}var td={$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 ad(e){let t=[];if(!e.project)t.push("Missing required field: project");else{if(!e.project.name)t.push("Missing required field: project.name");if(!e.project.slug)t.push("Missing required field: project.slug")}if(e.project?.slug&&!/^[a-z0-9-]+$/.test(e.project.slug))t.push("Invalid project.slug: must contain only lowercase letters, numbers, and hyphens");let a=["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(e.project?.region&&!a.includes(e.project.region))t.push(`Invalid region: ${e.project.region}. Must be one of: ${a.join(", ")}`);if(e.mode&&!["server","serverless"].includes(e.mode))t.push("Invalid mode: must be one of server or serverless");return{valid:t.length===0,errors:t}}var dr={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 ea(){return dr}function rd(){return dr.enabled}function nd(e){let t=ea();if(!t.enabled)return"";switch(e.toLowerCase()){case"dynamodb":return t.dynamodbEndpoint;case"s3":return t.s3Endpoint;case"localstack":case"cloudformation":case"lambda":case"apigateway":case"sns":case"sqs":case"cloudwatch":case"iam":case"sts":return t.localstackEndpoint;default:return t.localstackEndpoint}}function id(){let e=ea();return{accessKeyId:e.awsAccessKeyId,secretAccessKey:e.awsSecretAccessKey,region:e.awsRegion}}function sd(){let e=ea();if(!e.enabled)return{};return{AWS_ACCESS_KEY_ID:e.awsAccessKeyId,AWS_SECRET_ACCESS_KEY:e.awsSecretAccessKey,AWS_REGION:e.awsRegion,AWS_ENDPOINT_URL:e.localstackEndpoint,LOCALSTACK_ENDPOINT:e.localstackEndpoint,TS_CLOUD_LOCAL:"true"}}class mr{stacks=new Map;stackEvents=new Map;async createStack(e){let t=`arn:aws:cloudformation:${e.region||"us-east-1"}:123456789012:stack/${e.StackName}/${Date.now()}`;return this.stacks.set(e.StackName,{StackId:t,StackName:e.StackName,StackStatus:"CREATE_IN_PROGRESS",CreationTime:new Date().toISOString(),TemplateBody:e.TemplateBody,Parameters:e.Parameters||[]}),this.addEvent(e.StackName,{EventId:Date.now().toString(),StackName:e.StackName,LogicalResourceId:e.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_IN_PROGRESS"}),setTimeout(()=>{let a=this.stacks.get(e.StackName);if(a)a.StackStatus="CREATE_COMPLETE",this.addEvent(e.StackName,{EventId:(Date.now()+1).toString(),StackName:e.StackName,LogicalResourceId:e.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_COMPLETE"})},100),{StackId:t}}async updateStack(e){let t=this.stacks.get(e.StackName);if(!t)throw Error(`Stack ${e.StackName} does not exist`);return t.StackStatus="UPDATE_IN_PROGRESS",t.TemplateBody=e.TemplateBody||t.TemplateBody,this.addEvent(e.StackName,{EventId:Date.now().toString(),StackName:e.StackName,LogicalResourceId:e.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_IN_PROGRESS"}),setTimeout(()=>{t.StackStatus="UPDATE_COMPLETE",this.addEvent(e.StackName,{EventId:(Date.now()+1).toString(),StackName:e.StackName,LogicalResourceId:e.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_COMPLETE"})},100),{StackId:t.StackId}}async deleteStack(e){let t=this.stacks.get(e.StackName);if(!t)throw Error(`Stack ${e.StackName} does not exist`);t.StackStatus="DELETE_IN_PROGRESS",this.addEvent(e.StackName,{EventId:Date.now().toString(),StackName:e.StackName,LogicalResourceId:e.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_IN_PROGRESS"}),setTimeout(()=>{this.stacks.delete(e.StackName),this.addEvent(e.StackName,{EventId:(Date.now()+1).toString(),StackName:e.StackName,LogicalResourceId:e.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_COMPLETE"})},100)}async describeStacks(e){if(e.StackName){let t=this.stacks.get(e.StackName);if(!t)throw Error(`Stack ${e.StackName} does not exist`);return{Stacks:[t]}}return{Stacks:Array.from(this.stacks.values())}}async describeStackEvents(e){return{StackEvents:this.stackEvents.get(e.StackName)||[]}}addEvent(e,t){if(!this.stackEvents.has(e))this.stackEvents.set(e,[]);this.stackEvents.get(e).unshift(t)}reset(){this.stacks.clear(),this.stackEvents.clear()}}class pr{buckets=new Map;async createBucket(e){return this.buckets.set(e.Bucket,new Map),{Location:`/${e.Bucket}`}}async deleteBucket(e){this.buckets.delete(e.Bucket)}async putObject(e){let t=this.buckets.get(e.Bucket);if(!t)t=new Map,this.buckets.set(e.Bucket,t);return t.set(e.Key,Buffer.from(e.Body||"")),{ETag:`"${Date.now()}"`}}async getObject(e){let t=this.buckets.get(e.Bucket);if(!t)throw Error(`Bucket ${e.Bucket} does not exist`);let a=t.get(e.Key);if(!a)throw Error(`Object ${e.Key} does not exist`);return{Body:a,ContentLength:a.length}}async deleteObject(e){let t=this.buckets.get(e.Bucket);if(t)t.delete(e.Key)}async listObjects(e){let t=this.buckets.get(e.Bucket);if(!t)throw Error(`Bucket ${e.Bucket} does not exist`);return{Contents:Array.from(t.keys()).map((a)=>({Key:a,Size:t.get(a).length,LastModified:new Date().toISOString()}))}}reset(){this.buckets.clear()}}class gr{tables=new Map;data=new Map;async createTable(e){return this.tables.set(e.TableName,{TableName:e.TableName,KeySchema:e.KeySchema,AttributeDefinitions:e.AttributeDefinitions,TableStatus:"ACTIVE",CreationDateTime:new Date().toISOString()}),this.data.set(e.TableName,new Map),{TableDescription:this.tables.get(e.TableName)}}async deleteTable(e){this.tables.delete(e.TableName),this.data.delete(e.TableName)}async putItem(e){let t=this.data.get(e.TableName);if(!t)t=new Map,this.data.set(e.TableName,t);let a=JSON.stringify(e.Item);t.set(a,e.Item)}async getItem(e){let t=this.data.get(e.TableName);if(!t)return{};let a=JSON.stringify(e.Key),r=t.get(a);return r?{Item:r}:{}}async deleteItem(e){let t=this.data.get(e.TableName);if(t){let a=JSON.stringify(e.Key);t.delete(a)}}async scan(e){let t=this.data.get(e.TableName);if(!t)return{Items:[]};return{Items:Array.from(t.values())}}reset(){this.tables.clear(),this.data.clear()}}function od(e){return{cloudformation:new mr,s3:new pr,dynamodb:new gr}}class hr{environments=new Map;async createPreviewEnvironment(e){let{branch:t,pr:a,commitSha:r,ttl:n=24,baseConfig:i,region:s="us-east-1"}=e,o=this.generatePreviewId(t,a,r),c=this.generatePreviewName(t,a),l=`preview-${c}`,u=new Date,m=new Date(u.getTime()+n*60*60*1000),p={id:o,name:c,branch:t,pr:a,commitSha:r,createdAt:u,expiresAt:m,status:"creating",stackName:l,region:s,resources:[]};this.environments.set(o,p);try{let g=this.createPreviewConfig(i,c);return p.status="active",p.url=`https://${c}.preview.example.com`,p}catch(g){throw p.status="failed",g}}async destroyPreviewEnvironment(e){let t=this.environments.get(e);if(!t)throw Error(`Preview environment ${e} not found`);t.status="destroying";try{t.status="destroyed",this.environments.delete(e)}catch(a){throw Error(`Failed to destroy preview environment: ${a}`)}}getPreviewEnvironment(e){return this.environments.get(e)}getPreviewEnvironmentByBranch(e){return Array.from(this.environments.values()).find((t)=>t.branch===e)}getPreviewEnvironmentByPR(e){return Array.from(this.environments.values()).find((t)=>t.pr===e)}listPreviewEnvironments(){return Array.from(this.environments.values())}listActivePreviewEnvironments(){return this.listPreviewEnvironments().filter((e)=>e.status==="active")}async cleanupExpiredEnvironments(e={}){let{maxAge:t,keepCount:a,dryRun:r=!1}=e,n=[],i=[],s=new Date,o=this.listPreviewEnvironments().sort((c,l)=>l.createdAt.getTime()-c.createdAt.getTime());for(let c=0;c<o.length;c++){let l=o[c];if(l.status!=="active")continue;let u=!1;if(l.expiresAt<s)u=!0;if(t){if((s.getTime()-l.createdAt.getTime())/3600000>t)u=!0}if(a&&c>=a)u=!0;if(u)if(r)n.push(l.id);else try{await this.destroyPreviewEnvironment(l.id),n.push(l.id)}catch(m){i.push(l.id)}}return{destroyed:n,failed:i}}async updatePreviewEnvironment(e,t){let a=this.environments.get(e);if(!a)throw Error(`Preview environment ${e} not found`);a.commitSha=t,a.status="creating";try{return a.status="active",a}catch(r){throw a.status="failed",r}}async getPreviewEnvironmentsCost(){let e={},t=0;for(let a of this.environments.values())e[a.id]=0,t+=0;return{total:t,byEnvironment:e}}generatePreviewId(e,t,a){let r=e.replace(/[^a-z0-9-]/gi,"-").toLowerCase(),n=a?.substring(0,7)||Date.now().toString();return t?`pr-${t}-${n}`:`${r}-${n}`}generatePreviewName(e,t){let a=e.replace(/[^a-z0-9-]/gi,"-").toLowerCase();return t?`pr-${t}`:a}createPreviewConfig(e,t){return{...e,project:{...e.project,name:`${e.project.name} Preview (${t})`,slug:`${e.project.slug}-preview-${t}`}}}}var cd=new hr;function ld(e={}){let{workflowName:t="Preview Environment",trigger:a="pull_request",branches:r=["main","develop"],awsRegion:n="us-east-1",awsRole:i,configFile:s="cloud.config.ts",ttl:o=24}=e;return`name: ${t}
2523
2523
 
2524
2524
  on:
2525
2525
  ${a}:
@@ -2653,7 +2653,7 @@ jobs:
2653
2653
  run: |
2654
2654
  # Clean up environments older than TTL
2655
2655
  bun run cloud env:cleanup --max-age=\${{ env.TTL_HOURS }}
2656
- `}function dd(e={}){let{schedule:t="0 0 * * *",maxAge:a=48,keepCount:r=10}=e;return`name: Cleanup Stale Preview Environments
2656
+ `}function ud(e={}){let{schedule:t="0 0 * * *",maxAge:a=48,keepCount:r=10}=e;return`name: Cleanup Stale Preview Environments
2657
2657
 
2658
2658
  on:
2659
2659
  schedule:
@@ -2698,7 +2698,7 @@ jobs:
2698
2698
  - name: Report cleanup results
2699
2699
  run: |
2700
2700
  bun run cloud env:list --status=destroyed
2701
- `}function md(e={}){let{schedule:t="0 8 * * 1",webhookUrl:a}=e;return`name: Preview Environment Cost Report
2701
+ `}function dd(e={}){let{schedule:t="0 8 * * 1",webhookUrl:a}=e;return`name: Preview Environment Cost Report
2702
2702
 
2703
2703
  on:
2704
2704
  schedule:
@@ -2747,15 +2747,15 @@ jobs:
2747
2747
  curl -X POST -H 'Content-type: application/json' \\
2748
2748
  --data '{"text":"Preview Environment Cost Report\\n\${{ steps.cost.outputs.cost_json }}"}' \\
2749
2749
  $SLACK_WEBHOOK_URL`:'run: |\n echo "${{ steps.cost.outputs.cost_json }}"'}
2750
- `}class fr{channels=[];addChannel(e){this.channels.push(e)}removeChannel(e){this.channels=this.channels.filter((t)=>t.type!==e)}async notify(e){let t=this.channels.map((a)=>this.sendToChannel(a,e));await Promise.allSettled(t)}async sendToChannel(e,t){switch(e.type){case"slack":await this.sendToSlack(e.config,t);break;case"discord":await this.sendToDiscord(e.config,t);break;case"email":await this.sendToEmail(e.config,t);break;case"webhook":await this.sendToWebhook(e.config,t);break}}async sendToSlack(e,t){let a=this.formatSlackMessage(t,e),r=await fetch(e.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)});if(!r.ok)throw Error(`Failed to send Slack notification: ${r.statusText}`)}formatSlackMessage(e,t){let{environment:a,type:r}=e,n={created:":rocket:",updated:":arrows_counterclockwise:",destroyed:":wastebasket:",failed:":x:",expired:":hourglass_flowing_sand:"}[r],i={created:"#36a64f",updated:"#2196F3",destroyed:"#808080",failed:"#f44336",expired:"#ff9800"}[r],s={created:"Preview Environment Created",updated:"Preview Environment Updated",destroyed:"Preview Environment Destroyed",failed:"Preview Environment Failed",expired:"Preview Environment Expired"}[r];return{username:t.username||"ts-cloud",icon_emoji:t.iconEmoji||":cloud:",channel:t.channel,attachments:[{color:i,title:`${n} ${s}`,fields:[{title:"Environment",value:a.name,short:!0},{title:"Branch",value:a.branch,short:!0},...a.pr?[{title:"PR",value:`#${a.pr}`,short:!0}]:[],{title:"Commit",value:a.commitSha.substring(0,7),short:!0},...a.url?[{title:"URL",value:a.url,short:!1}]:[],...r==="created"?[{title:"Expires",value:a.expiresAt.toLocaleString(),short:!0}]:[]],footer:"ts-cloud Preview Environments",ts:Math.floor(e.timestamp.getTime()/1000)}]}}async sendToDiscord(e,t){let a=this.formatDiscordMessage(t,e),r=await fetch(e.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)});if(!r.ok)throw Error(`Failed to send Discord notification: ${r.statusText}`)}formatDiscordMessage(e,t){let{environment:a,type:r}=e,n={created:":rocket:",updated:":arrows_counterclockwise:",destroyed:":wastebasket:",failed:":x:",expired:":hourglass:"}[r],i={created:3581519,updated:2201331,destroyed:8421504,failed:16007990,expired:16750592}[r],s={created:"Preview Environment Created",updated:"Preview Environment Updated",destroyed:"Preview Environment Destroyed",failed:"Preview Environment Failed",expired:"Preview Environment Expired"}[r];return{username:t.username||"ts-cloud",avatar_url:t.avatarUrl,embeds:[{title:`${n} ${s}`,color:i,fields:[{name:"Environment",value:a.name,inline:!0},{name:"Branch",value:a.branch,inline:!0},...a.pr?[{name:"PR",value:`#${a.pr}`,inline:!0}]:[],{name:"Commit",value:`\`${a.commitSha.substring(0,7)}\``,inline:!0},...a.url?[{name:"URL",value:a.url,inline:!1}]:[]],timestamp:e.timestamp.toISOString(),footer:{text:"ts-cloud Preview Environments"}}]}}async sendToEmail(e,t){console.log(`Email notification would be sent to ${e.to.join(", ")}`)}async sendToWebhook(e,t){let a=await fetch(e.url,{method:e.method||"POST",headers:{"Content-Type":"application/json",...e.headers},body:JSON.stringify({event:t.type,environment:t.environment,timestamp:t.timestamp.toISOString(),metadata:t.metadata})});if(!a.ok)throw Error(`Failed to send webhook notification: ${a.statusText}`)}}var pd=new fr;function gd(e){let{columns:t,data:a,border:r=!0,header:n=!0,compact:i=!1,maxWidth:s}=e;if(a.length===0)return"No data to display";let o=t.map((l)=>{let u=l.label.length,m=Math.max(...a.map((g)=>(l.formatter?l.formatter(g[l.key]):String(g[l.key]||"")).length)),p=l.width||Math.max(u,m);if(s&&p>s)p=s;return p}),c=[];if(r)c.push(Wt(o,"top",i));if(n){if(c.push(Pa(t.map((l)=>l.label),o,t.map((l)=>l.align||"left"),r)),r)c.push(Wt(o,"middle",i))}for(let l of a){let u=t.map((m)=>{let p=m.formatter?m.formatter(l[m.key]):String(l[m.key]||"");return To(p,o[t.indexOf(m)])});c.push(Pa(u,o,t.map((m)=>m.align||"left"),r))}if(r)c.push(Wt(o,"bottom",i));return c.join(`
2751
- `)}function Pa(e,t,a,r){let n=e.map((i,s)=>{let o=t[s],c=a[s];return Co(i,o,c)});if(r)return`│ ${n.join(" │ ")} │`;return n.join(" ")}function Wt(e,t,a){let r=t==="top"?"┌":t==="middle"?"├":"└",n=t==="top"?"┐":t==="middle"?"┤":"┘",i=t==="top"?"┬":t==="middle"?"┼":"┴",s="─";if(a)return r+e.map((o)=>"─".repeat(o+2)).join(i)+n;return r+e.map((o)=>"─".repeat(o+2)).join(i)+n}function Co(e,t,a){let r=Sr(e).length;if(r>=t)return e;let n=t-r;switch(a){case"right":return" ".repeat(n)+e;case"center":{let i=Math.floor(n/2),s=n-i;return" ".repeat(i)+e+" ".repeat(s)}default:return e+" ".repeat(n)}}function To(e,t){if(Sr(e).length<=t)return e;return e.substring(0,t-1)+"…"}function Sr(e){return e.replace(/\x1B\[[0-9;]*m/g,"")}function hd(e,t={}){let{indent:a=" ",showMetadata:r=!1}=t,n=[];function i(s,o,c){let l=o+(c?"└─ ":"├─ ")+s.label;if(n.push(l),r&&s.metadata){let u=o+(c?" ":"│ ");for(let[m,p]of Object.entries(s.metadata))n.push(`${u}${m}: ${p}`)}if(s.children&&s.children.length>0){let u=o+(c?" ":"│ ");s.children.forEach((m,p)=>{i(m,u,p===s.children.length-1)})}}return e.forEach((s,o)=>{i(s,"",o===e.length-1)}),n.join(`
2752
- `)}function yd(e){let{total:t,current:a,width:r=40,format:n=":bar :percent :current/:total",complete:i="█",incomplete:s="░"}=e,o=Math.min(100,Math.max(0,a/t*100)),c=Math.floor(r*a/t),l=r-c,u=i.repeat(c)+s.repeat(l);return n.replace(":bar",u).replace(":percent",`${o.toFixed(0)}%`).replace(":current",String(a)).replace(":total",String(t))}function fd(e,t=2){if(e===0)return"0 Bytes";let a=1024,r=t<0?0:t,n=["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"],i=Math.floor(Math.log(e)/Math.log(a));return`${Number.parseFloat((e/Math.pow(a,i)).toFixed(r))} ${n[i]}`}function Sd(e){if(e<1000)return`${e}ms`;let t=Math.floor(e/1000);if(t<60)return`${t}s`;let a=Math.floor(t/60),r=t%60;if(a<60)return r>0?`${a}m ${r}s`:`${a}m`;let n=Math.floor(a/60),i=a%60;if(n<24)return i>0?`${n}h ${i}m`:`${n}h`;let s=Math.floor(n/24),o=n%24;return o>0?`${s}d ${o}h`:`${s}d`}function bd(e,t="•"){return e.map((a)=>`${t} ${a}`).join(`
2753
- `)}function Ad(e,t={}){let{indent:a="",separator:r=": "}=t,n=Math.max(...Object.keys(e).map((i)=>i.length));return Object.entries(e).map(([i,s])=>{let o=i.padEnd(n);return`${a}${o}${r}${s}`}).join(`
2754
- `)}class vo{total;current=0;width;format;message;showETA;showPercentage;showCounter;startTime=Date.now();lastUpdate=0;constructor(e){this.total=e.total,this.current=e.current||0,this.width=e.width||40,this.format=e.format||":message :bar :percent :eta",this.message=e.message||"Progress",this.showETA=e.showETA!==!1,this.showPercentage=e.showPercentage!==!1,this.showCounter=e.showCounter!==!1}tick(e=1){this.current=Math.min(this.total,this.current+e),this.lastUpdate=Date.now()}update(e){this.current=Math.min(this.total,Math.max(0,e)),this.lastUpdate=Date.now()}setMessage(e){this.message=e}getPercentage(){return Math.min(100,this.current/this.total*100)}getETA(){if(this.current===0)return 0;let e=Date.now()-this.startTime,t=this.current/e,a=this.total-this.current;return Math.round(a/t)}getETAFormatted(){if(this.current===0)return"calculating...";if(this.current===this.total)return"complete";let e=this.getETA();if(e<1000)return"< 1s";if(e<60000)return`${Math.round(e/1000)}s`;let t=Math.floor(e/60000);if(t<60)return`${t}m`;let a=Math.floor(t/60),r=t%60;if(a<24)return r>0?`${a}h ${r}m`:`${a}h`;let n=Math.floor(a/24),i=a%24;return i>0?`${n}d ${i}h`:`${n}d`}render(){let e=this.getPercentage(),t=Math.floor(this.width*this.current/this.total),a=this.width-t,r="█".repeat(t)+"░".repeat(a),n=`${e.toFixed(1)}%`,i=`${this.current}/${this.total}`,s=this.showETA?`ETA: ${this.getETAFormatted()}`:"",o=this.format.replace(":message",this.message).replace(":bar",r).replace(":percent",this.showPercentage?n:"").replace(":counter",this.showCounter?i:"").replace(":eta",s).replace(":current",String(this.current)).replace(":total",String(this.total));return o=o.replace(/\s+/g," ").trim(),o}isComplete(){return this.current>=this.total}}class wo{steps;currentStepIndex=0;constructor(e){this.steps=e.map((t)=>({name:t,status:"pending"}))}startStep(e,t){if(e>=0&&e<this.steps.length)this.steps[e].status="active",this.steps[e].message=t,this.currentStepIndex=e}completeStep(e){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="completed",this.steps[this.currentStepIndex].message=e,this.currentStepIndex++}failStep(e){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="failed",this.steps[this.currentStepIndex].error=e}skipStep(e){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="skipped",this.steps[this.currentStepIndex].message=e,this.currentStepIndex++}getStep(e){return this.steps[e]}getSteps(){return this.steps}render(){let e=[];for(let t of this.steps){let a=`${this.getStatusIcon(t.status)} ${t.name}`;if(t.message)a+=` - ${t.message}`;if(t.error)a+=`
2750
+ `}class yr{channels=[];addChannel(e){this.channels.push(e)}removeChannel(e){this.channels=this.channels.filter((t)=>t.type!==e)}async notify(e){let t=this.channels.map((a)=>this.sendToChannel(a,e));await Promise.allSettled(t)}async sendToChannel(e,t){switch(e.type){case"slack":await this.sendToSlack(e.config,t);break;case"discord":await this.sendToDiscord(e.config,t);break;case"email":await this.sendToEmail(e.config,t);break;case"webhook":await this.sendToWebhook(e.config,t);break}}async sendToSlack(e,t){let a=this.formatSlackMessage(t,e),r=await fetch(e.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)});if(!r.ok)throw Error(`Failed to send Slack notification: ${r.statusText}`)}formatSlackMessage(e,t){let{environment:a,type:r}=e,n={created:":rocket:",updated:":arrows_counterclockwise:",destroyed:":wastebasket:",failed:":x:",expired:":hourglass_flowing_sand:"}[r],i={created:"#36a64f",updated:"#2196F3",destroyed:"#808080",failed:"#f44336",expired:"#ff9800"}[r],s={created:"Preview Environment Created",updated:"Preview Environment Updated",destroyed:"Preview Environment Destroyed",failed:"Preview Environment Failed",expired:"Preview Environment Expired"}[r];return{username:t.username||"ts-cloud",icon_emoji:t.iconEmoji||":cloud:",channel:t.channel,attachments:[{color:i,title:`${n} ${s}`,fields:[{title:"Environment",value:a.name,short:!0},{title:"Branch",value:a.branch,short:!0},...a.pr?[{title:"PR",value:`#${a.pr}`,short:!0}]:[],{title:"Commit",value:a.commitSha.substring(0,7),short:!0},...a.url?[{title:"URL",value:a.url,short:!1}]:[],...r==="created"?[{title:"Expires",value:a.expiresAt.toLocaleString(),short:!0}]:[]],footer:"ts-cloud Preview Environments",ts:Math.floor(e.timestamp.getTime()/1000)}]}}async sendToDiscord(e,t){let a=this.formatDiscordMessage(t,e),r=await fetch(e.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)});if(!r.ok)throw Error(`Failed to send Discord notification: ${r.statusText}`)}formatDiscordMessage(e,t){let{environment:a,type:r}=e,n={created:":rocket:",updated:":arrows_counterclockwise:",destroyed:":wastebasket:",failed:":x:",expired:":hourglass:"}[r],i={created:3581519,updated:2201331,destroyed:8421504,failed:16007990,expired:16750592}[r],s={created:"Preview Environment Created",updated:"Preview Environment Updated",destroyed:"Preview Environment Destroyed",failed:"Preview Environment Failed",expired:"Preview Environment Expired"}[r];return{username:t.username||"ts-cloud",avatar_url:t.avatarUrl,embeds:[{title:`${n} ${s}`,color:i,fields:[{name:"Environment",value:a.name,inline:!0},{name:"Branch",value:a.branch,inline:!0},...a.pr?[{name:"PR",value:`#${a.pr}`,inline:!0}]:[],{name:"Commit",value:`\`${a.commitSha.substring(0,7)}\``,inline:!0},...a.url?[{name:"URL",value:a.url,inline:!1}]:[]],timestamp:e.timestamp.toISOString(),footer:{text:"ts-cloud Preview Environments"}}]}}async sendToEmail(e,t){console.log(`Email notification would be sent to ${e.to.join(", ")}`)}async sendToWebhook(e,t){let a=await fetch(e.url,{method:e.method||"POST",headers:{"Content-Type":"application/json",...e.headers},body:JSON.stringify({event:t.type,environment:t.environment,timestamp:t.timestamp.toISOString(),metadata:t.metadata})});if(!a.ok)throw Error(`Failed to send webhook notification: ${a.statusText}`)}}var md=new yr;function pd(e){let{columns:t,data:a,border:r=!0,header:n=!0,compact:i=!1,maxWidth:s}=e;if(a.length===0)return"No data to display";let o=t.map((l)=>{let u=l.label.length,m=Math.max(...a.map((g)=>{return(l.formatter?l.formatter(g[l.key]):String(g[l.key]||"")).length})),p=l.width||Math.max(u,m);if(s&&p>s)p=s;return p}),c=[];if(r)c.push(Bt(o,"top",i));if(n){if(c.push(Ea(t.map((l)=>l.label),o,t.map((l)=>l.align||"left"),r)),r)c.push(Bt(o,"middle",i))}for(let l of a){let u=t.map((m)=>{let p=m.formatter?m.formatter(l[m.key]):String(l[m.key]||"");return Co(p,o[t.indexOf(m)])});c.push(Ea(u,o,t.map((m)=>m.align||"left"),r))}if(r)c.push(Bt(o,"bottom",i));return c.join(`
2751
+ `)}function Ea(e,t,a,r){let n=e.map((i,s)=>{let o=t[s],c=a[s];return Ao(i,o,c)});if(r)return`│ ${n.join(" │ ")} │`;return n.join(" ")}function Bt(e,t,a){let r=t==="top"?"┌":t==="middle"?"├":"└",n=t==="top"?"┐":t==="middle"?"┤":"┘",i=t==="top"?"┬":t==="middle"?"┼":"┴",s="─";if(a)return r+e.map((o)=>"─".repeat(o+2)).join(i)+n;return r+e.map((o)=>"─".repeat(o+2)).join(i)+n}function Ao(e,t,a){let r=fr(e).length;if(r>=t)return e;let n=t-r;switch(a){case"right":return" ".repeat(n)+e;case"center":{let i=Math.floor(n/2),s=n-i;return" ".repeat(i)+e+" ".repeat(s)}default:return e+" ".repeat(n)}}function Co(e,t){if(fr(e).length<=t)return e;return e.substring(0,t-1)+"…"}function fr(e){return e.replace(/\x1B\[[0-9;]*m/g,"")}function gd(e,t={}){let{indent:a=" ",showMetadata:r=!1}=t,n=[];function i(s,o,c){let l=o+(c?"└─ ":"├─ ")+s.label;if(n.push(l),r&&s.metadata){let u=o+(c?" ":"│ ");for(let[m,p]of Object.entries(s.metadata))n.push(`${u}${m}: ${p}`)}if(s.children&&s.children.length>0){let u=o+(c?" ":"│ ");s.children.forEach((m,p)=>{i(m,u,p===s.children.length-1)})}}return e.forEach((s,o)=>{i(s,"",o===e.length-1)}),n.join(`
2752
+ `)}function hd(e){let{total:t,current:a,width:r=40,format:n=":bar :percent :current/:total",complete:i="█",incomplete:s="░"}=e,o=Math.min(100,Math.max(0,a/t*100)),c=Math.floor(r*a/t),l=r-c,u=i.repeat(c)+s.repeat(l);return n.replace(":bar",u).replace(":percent",`${o.toFixed(0)}%`).replace(":current",String(a)).replace(":total",String(t))}function yd(e,t=2){if(e===0)return"0 Bytes";let a=1024,r=t<0?0:t,n=["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"],i=Math.floor(Math.log(e)/Math.log(a));return`${Number.parseFloat((e/Math.pow(a,i)).toFixed(r))} ${n[i]}`}function fd(e){if(e<1000)return`${e}ms`;let t=Math.floor(e/1000);if(t<60)return`${t}s`;let a=Math.floor(t/60),r=t%60;if(a<60)return r>0?`${a}m ${r}s`:`${a}m`;let n=Math.floor(a/60),i=a%60;if(n<24)return i>0?`${n}h ${i}m`:`${n}h`;let s=Math.floor(n/24),o=n%24;return o>0?`${s}d ${o}h`:`${s}d`}function Sd(e,t="•"){return e.map((a)=>`${t} ${a}`).join(`
2753
+ `)}function bd(e,t={}){let{indent:a="",separator:r=": "}=t,n=Math.max(...Object.keys(e).map((i)=>i.length));return Object.entries(e).map(([i,s])=>{let o=i.padEnd(n);return`${a}${o}${r}${s}`}).join(`
2754
+ `)}class To{total;current=0;width;format;message;showETA;showPercentage;showCounter;startTime=Date.now();lastUpdate=0;constructor(e){this.total=e.total,this.current=e.current||0,this.width=e.width||40,this.format=e.format||":message :bar :percent :eta",this.message=e.message||"Progress",this.showETA=e.showETA!==!1,this.showPercentage=e.showPercentage!==!1,this.showCounter=e.showCounter!==!1}tick(e=1){this.current=Math.min(this.total,this.current+e),this.lastUpdate=Date.now()}update(e){this.current=Math.min(this.total,Math.max(0,e)),this.lastUpdate=Date.now()}setMessage(e){this.message=e}getPercentage(){return Math.min(100,this.current/this.total*100)}getETA(){if(this.current===0)return 0;let e=Date.now()-this.startTime,t=this.current/e,a=this.total-this.current;return Math.round(a/t)}getETAFormatted(){if(this.current===0)return"calculating...";if(this.current===this.total)return"complete";let e=this.getETA();if(e<1000)return"< 1s";if(e<60000)return`${Math.round(e/1000)}s`;let t=Math.floor(e/60000);if(t<60)return`${t}m`;let a=Math.floor(t/60),r=t%60;if(a<24)return r>0?`${a}h ${r}m`:`${a}h`;let n=Math.floor(a/24),i=a%24;return i>0?`${n}d ${i}h`:`${n}d`}render(){let e=this.getPercentage(),t=Math.floor(this.width*this.current/this.total),a=this.width-t,r="█".repeat(t)+"░".repeat(a),n=`${e.toFixed(1)}%`,i=`${this.current}/${this.total}`,s=this.showETA?`ETA: ${this.getETAFormatted()}`:"",o=this.format.replace(":message",this.message).replace(":bar",r).replace(":percent",this.showPercentage?n:"").replace(":counter",this.showCounter?i:"").replace(":eta",s).replace(":current",String(this.current)).replace(":total",String(this.total));return o=o.replace(/\s+/g," ").trim(),o}isComplete(){return this.current>=this.total}}class vo{steps;currentStepIndex=0;constructor(e){this.steps=e.map((t)=>({name:t,status:"pending"}))}startStep(e,t){if(e>=0&&e<this.steps.length)this.steps[e].status="active",this.steps[e].message=t,this.currentStepIndex=e}completeStep(e){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="completed",this.steps[this.currentStepIndex].message=e,this.currentStepIndex++}failStep(e){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="failed",this.steps[this.currentStepIndex].error=e}skipStep(e){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="skipped",this.steps[this.currentStepIndex].message=e,this.currentStepIndex++}getStep(e){return this.steps[e]}getSteps(){return this.steps}render(){let e=[];for(let t of this.steps){let a=`${this.getStatusIcon(t.status)} ${t.name}`;if(t.message)a+=` - ${t.message}`;if(t.error)a+=`
2755
2755
  Error: ${t.error}`;e.push(a)}return e.join(`
2756
- `)}getStatusIcon(e){switch(e){case"pending":return"○";case"active":return"◐";case"completed":return"✓";case"failed":return"✗";case"skipped":return"⊘";default:return"○"}}isComplete(){return this.steps.every((e)=>e.status==="completed"||e.status==="skipped")}hasFailed(){return this.steps.some((e)=>e.status==="failed")}}class Eo{frames=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];currentFrame=0;message;interval=null;constructor(e="Loading..."){this.message=e}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(e){this.message=e}render(){return`${this.frames[this.currentFrame]} ${this.message}`}succeed(e){return this.stop(),`✓ ${e||this.message}`}fail(e){return this.stop(),`✗ ${e||this.message}`}warn(e){return this.stop(),`⚠ ${e||this.message}`}info(e){return this.stop(),`ℹ ${e||this.message}`}}class Po{tasks=[];add(e){return this.tasks.push({title:e,status:"pending"}),this.tasks.length-1}start(e){if(e>=0&&e<this.tasks.length)this.tasks[e].status="running"}complete(e,t){if(e>=0&&e<this.tasks.length)this.tasks[e].status="completed",this.tasks[e].output=t}fail(e,t){if(e>=0&&e<this.tasks.length)this.tasks[e].status="failed",this.tasks[e].output=t}render(){let e=[];for(let t of this.tasks){let a=`${this.getStatusIcon(t.status)} ${t.title}`;if(t.output)a+=`
2756
+ `)}getStatusIcon(e){switch(e){case"pending":return"○";case"active":return"◐";case"completed":return"✓";case"failed":return"✗";case"skipped":return"⊘";default:return"○"}}isComplete(){return this.steps.every((e)=>e.status==="completed"||e.status==="skipped")}hasFailed(){return this.steps.some((e)=>e.status==="failed")}}class wo{frames=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];currentFrame=0;message;interval=null;constructor(e="Loading..."){this.message=e}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(e){this.message=e}render(){return`${this.frames[this.currentFrame]} ${this.message}`}succeed(e){return this.stop(),`✓ ${e||this.message}`}fail(e){return this.stop(),`✗ ${e||this.message}`}warn(e){return this.stop(),`⚠ ${e||this.message}`}info(e){return this.stop(),`ℹ ${e||this.message}`}}class Eo{tasks=[];add(e){return this.tasks.push({title:e,status:"pending"}),this.tasks.length-1}start(e){if(e>=0&&e<this.tasks.length)this.tasks[e].status="running"}complete(e,t){if(e>=0&&e<this.tasks.length)this.tasks[e].status="completed",this.tasks[e].output=t}fail(e,t){if(e>=0&&e<this.tasks.length)this.tasks[e].status="failed",this.tasks[e].output=t}render(){let e=[];for(let t of this.tasks){let a=`${this.getStatusIcon(t.status)} ${t.title}`;if(t.output)a+=`
2757
2757
  ${t.output}`;e.push(a)}return e.join(`
2758
- `)}getStatusIcon(e){switch(e){case"pending":return"○";case"running":return"◐";case"completed":return"✓";case"failed":return"✗";default:return"○"}}}function Io(e,t){let a=[];for(let r=0;r<=t.length;r++)a[r]=[r];for(let r=0;r<=e.length;r++)a[0][r]=r;for(let r=1;r<=t.length;r++)for(let n=1;n<=e.length;n++)if(t.charAt(r-1)===e.charAt(n-1))a[r][n]=a[r-1][n-1];else a[r][n]=Math.min(a[r-1][n-1]+1,a[r][n-1]+1,a[r-1][n]+1);return a[t.length][e.length]}function Ro(e,t){let a=Io(e.toLowerCase(),t.toLowerCase()),r=Math.max(e.length,t.length);if(r===0)return 1;return 1-a/r}function br(e,t,a=0.5){return t.map((r)=>({command:r,score:Ro(e,r)})).filter((r)=>r.score>=a).sort((r,n)=>n.score-r.score).map((r)=>r.command).slice(0,5)}function Cd(e,t){if(t.length===0)return`Unknown command: '${e}'
2758
+ `)}getStatusIcon(e){switch(e){case"pending":return"○";case"running":return"◐";case"completed":return"✓";case"failed":return"✗";default:return"○"}}}function Po(e,t){let a=[];for(let r=0;r<=t.length;r++)a[r]=[r];for(let r=0;r<=e.length;r++)a[0][r]=r;for(let r=1;r<=t.length;r++)for(let n=1;n<=e.length;n++)if(t.charAt(r-1)===e.charAt(n-1))a[r][n]=a[r-1][n-1];else a[r][n]=Math.min(a[r-1][n-1]+1,a[r][n-1]+1,a[r-1][n]+1);return a[t.length][e.length]}function Io(e,t){let a=Po(e.toLowerCase(),t.toLowerCase()),r=Math.max(e.length,t.length);if(r===0)return 1;return 1-a/r}function Sr(e,t,a=0.5){return t.map((r)=>({command:r,score:Io(e,r)})).filter((r)=>r.score>=a).sort((r,n)=>n.score-r.score).map((r)=>r.command).slice(0,5)}function Ad(e,t){if(t.length===0)return`Unknown command: '${e}'
2759
2759
 
2760
2760
  Run 'ts-cloud --help' to see available commands.`;if(t.length===1)return`Unknown command: '${e}'
2761
2761
 
@@ -2763,17 +2763,17 @@ Did you mean: ${t[0]}?`;return`Unknown command: '${e}'
2763
2763
 
2764
2764
  Did you mean one of these?
2765
2765
  ${t.map((a)=>` • ${a}`).join(`
2766
- `)}`}function Td(e,t){return br(e,t,0.7).length>0}function vd(e,t){let a=t.find((i)=>i.commands.some((s)=>s.name===e||s.aliases?.includes(e)));if(!a)return"No contextual help available.";let r=[];r.push(`${a.name}`),r.push("─".repeat(a.name.length)),r.push(a.description),r.push(""),r.push("Related commands:");for(let i of a.commands)if(r.push(` ${i.name.padEnd(20)} ${i.description}`),i.aliases&&i.aliases.length>0)r.push(` Aliases: ${i.aliases.join(", ")}`);let n=a.commands.find((i)=>i.name===e||i.aliases?.includes(e));if(n?.examples&&n.examples.length>0){r.push(""),r.push("Examples:");for(let i of n.examples)r.push(` ${i}`)}return r.join(`
2767
- `)}function wd(e,t){let a=[],r=e.toLowerCase();for(let n of t)for(let i of n.commands){let s=i.name.toLowerCase().includes(r),o=i.description.toLowerCase().includes(r),c=i.aliases?.some((l)=>l.toLowerCase().includes(r));if(s||o||c)a.push({command:i,category:n.name})}return a}function Ed(e,t,a=10){let r=e.toLowerCase(),n=t.filter((s)=>s.toLowerCase().startsWith(r)),i=t.filter((s)=>s.toLowerCase().includes(r)&&!s.toLowerCase().startsWith(r));return[...n,...i].slice(0,a)}function Pd(e,t){let a=e.toLowerCase();return t.filter((r)=>{let n=r.name.toLowerCase().includes(a),i=r.alias?.toLowerCase().includes(a);return n||i})}function Id(e){if(e.length===0)return"No matching flags found.";let t=[];for(let a of e){let r=` --${a.name}`;if(a.alias)r+=`, -${a.alias}`;if(r=r.padEnd(30),r+=a.description,a.required)r+=" (required)";t.push(r)}return t.join(`
2768
- `)}function Rd(e){let t=[];if(t.push(`Usage: ts-cloud ${e.name}`),t.push(""),t.push(e.description),e.aliases&&e.aliases.length>0)t.push(""),t.push(`Aliases: ${e.aliases.join(", ")}`);if(e.examples&&e.examples.length>0){t.push(""),t.push("Examples:");for(let a of e.examples)t.push(` ${a}`)}return t.join(`
2769
- `)}function Nd(e,t,a=[]){let r={valid:!0,errors:[],warnings:[],suggestions:[]},[n,...i]=e.split(" ");if(!t.includes(n)){r.valid=!1,r.errors.push(`Unknown command: ${n}`);let s=br(n,t);if(s.length>0)r.suggestions.push(...s)}for(let s of a)if(!i.some((o)=>o===`--${s}`||o.startsWith(`--${s}=`)))r.valid=!1,r.errors.push(`Missing required flag: --${s}`);return r}class No{options;running=!1;history={commands:[],maxSize:1000};historyIndex=-1;constructor(e){this.options={prompt:e.prompt||"> ",welcome:e.welcome||'Welcome to ts-cloud interactive mode. Type "help" for available commands.',...e}}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 e=await this.readInput();if(!e.trim())continue;this.addToHistory(e),await this.executeCommand(e)}catch(e){if(e instanceof Error)console.error(`Error: ${e.message}`)}if(this.options.historyFile)await this.saveHistory()}stop(){this.running=!1}async readInput(){return new Promise((e)=>{process.stdout.write(this.options.prompt||"> "),e("")})}async executeCommand(e){let[t,...a]=this.parseCommand(e);if(t==="exit"||t==="quit"){this.stop();return}if(t==="help"){this.showHelp();return}if(t==="history"){this.showHistory();return}if(t==="clear"){console.clear();return}let r=this.findCommand(t);if(!r){console.error(`Unknown command: ${t}`),console.log('Type "help" to see available commands.');return}try{await r.handler(a)}catch(n){if(n instanceof Error)console.error(`Command failed: ${n.message}`)}}parseCommand(e){return e.trim().split(/\s+/)}findCommand(e){for(let[t,a]of this.options.commands)if(a.name===e||a.aliases?.includes(e))return a;return}showHelp(){console.log("Available commands:"),console.log("");let e=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 t of e){let a=` ${t.name.padEnd(20)} ${t.description}`;if(t.aliases&&t.aliases.length>0)a+=` (aliases: ${t.aliases.join(", ")})`;console.log(a)}}showHistory(){if(this.history.commands.length===0){console.log("No command history");return}console.log("Command history:"),this.history.commands.forEach((e,t)=>{console.log(` ${(t+1).toString().padStart(4)} ${e}`)})}addToHistory(e){if(this.history.commands[this.history.commands.length-1]===e)return;if(this.history.commands.push(e),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(e){let t=[],a=["help","history","clear","exit","quit"];for(let r of a)if(r.startsWith(e))t.push(r);for(let[r,n]of this.options.commands){if(n.name.startsWith(e))t.push(n.name);if(n.aliases){for(let i of n.aliases)if(i.startsWith(e))t.push(i)}}return t}async loadHistory(){if(!this.options.historyFile)return;try{let e=await(await import("node:fs/promises")).readFile(this.options.historyFile,"utf-8");this.history.commands=e.split(`
2766
+ `)}`}function Cd(e,t){return Sr(e,t,0.7).length>0}function Td(e,t){let a=t.find((i)=>i.commands.some((s)=>s.name===e||s.aliases?.includes(e)));if(!a)return"No contextual help available.";let r=[];r.push(`${a.name}`),r.push("─".repeat(a.name.length)),r.push(a.description),r.push(""),r.push("Related commands:");for(let i of a.commands)if(r.push(` ${i.name.padEnd(20)} ${i.description}`),i.aliases&&i.aliases.length>0)r.push(` Aliases: ${i.aliases.join(", ")}`);let n=a.commands.find((i)=>i.name===e||i.aliases?.includes(e));if(n?.examples&&n.examples.length>0){r.push(""),r.push("Examples:");for(let i of n.examples)r.push(` ${i}`)}return r.join(`
2767
+ `)}function vd(e,t){let a=[],r=e.toLowerCase();for(let n of t)for(let i of n.commands){let s=i.name.toLowerCase().includes(r),o=i.description.toLowerCase().includes(r),c=i.aliases?.some((l)=>l.toLowerCase().includes(r));if(s||o||c)a.push({command:i,category:n.name})}return a}function wd(e,t,a=10){let r=e.toLowerCase(),n=t.filter((s)=>s.toLowerCase().startsWith(r)),i=t.filter((s)=>s.toLowerCase().includes(r)&&!s.toLowerCase().startsWith(r));return[...n,...i].slice(0,a)}function Ed(e,t){let a=e.toLowerCase();return t.filter((r)=>{let n=r.name.toLowerCase().includes(a),i=r.alias?.toLowerCase().includes(a);return n||i})}function Pd(e){if(e.length===0)return"No matching flags found.";let t=[];for(let a of e){let r=` --${a.name}`;if(a.alias)r+=`, -${a.alias}`;if(r=r.padEnd(30),r+=a.description,a.required)r+=" (required)";t.push(r)}return t.join(`
2768
+ `)}function Id(e){let t=[];if(t.push(`Usage: ts-cloud ${e.name}`),t.push(""),t.push(e.description),e.aliases&&e.aliases.length>0)t.push(""),t.push(`Aliases: ${e.aliases.join(", ")}`);if(e.examples&&e.examples.length>0){t.push(""),t.push("Examples:");for(let a of e.examples)t.push(` ${a}`)}return t.join(`
2769
+ `)}function Rd(e,t,a=[]){let r={valid:!0,errors:[],warnings:[],suggestions:[]},[n,...i]=e.split(" ");if(!t.includes(n)){r.valid=!1,r.errors.push(`Unknown command: ${n}`);let s=Sr(n,t);if(s.length>0)r.suggestions.push(...s)}for(let s of a)if(!i.some((o)=>o===`--${s}`||o.startsWith(`--${s}=`)))r.valid=!1,r.errors.push(`Missing required flag: --${s}`);return r}class Ro{options;running=!1;history={commands:[],maxSize:1000};historyIndex=-1;constructor(e){this.options={prompt:e.prompt||"> ",welcome:e.welcome||'Welcome to ts-cloud interactive mode. Type "help" for available commands.',...e}}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 e=await this.readInput();if(!e.trim())continue;this.addToHistory(e),await this.executeCommand(e)}catch(e){if(e instanceof Error)console.error(`Error: ${e.message}`)}if(this.options.historyFile)await this.saveHistory()}stop(){this.running=!1}async readInput(){return new Promise((e)=>{process.stdout.write(this.options.prompt||"> "),e("")})}async executeCommand(e){let[t,...a]=this.parseCommand(e);if(t==="exit"||t==="quit"){this.stop();return}if(t==="help"){this.showHelp();return}if(t==="history"){this.showHistory();return}if(t==="clear"){console.clear();return}let r=this.findCommand(t);if(!r){console.error(`Unknown command: ${t}`),console.log('Type "help" to see available commands.');return}try{await r.handler(a)}catch(n){if(n instanceof Error)console.error(`Command failed: ${n.message}`)}}parseCommand(e){return e.trim().split(/\s+/)}findCommand(e){for(let[t,a]of this.options.commands)if(a.name===e||a.aliases?.includes(e))return a;return}showHelp(){console.log("Available commands:"),console.log("");let e=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 t of e){let a=` ${t.name.padEnd(20)} ${t.description}`;if(t.aliases&&t.aliases.length>0)a+=` (aliases: ${t.aliases.join(", ")})`;console.log(a)}}showHistory(){if(this.history.commands.length===0){console.log("No command history");return}console.log("Command history:"),this.history.commands.forEach((e,t)=>{console.log(` ${(t+1).toString().padStart(4)} ${e}`)})}addToHistory(e){if(this.history.commands[this.history.commands.length-1]===e)return;if(this.history.commands.push(e),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(e){let t=[],a=["help","history","clear","exit","quit"];for(let r of a)if(r.startsWith(e))t.push(r);for(let[r,n]of this.options.commands){if(n.name.startsWith(e))t.push(n.name);if(n.aliases){for(let i of n.aliases)if(i.startsWith(e))t.push(i)}}return t}async loadHistory(){if(!this.options.historyFile)return;try{let e=await(await import("node:fs/promises")).readFile(this.options.historyFile,"utf-8");this.history.commands=e.split(`
2770
2770
  `).filter((t)=>t.trim()),this.historyIndex=this.history.commands.length}catch{}}async saveHistory(){if(!this.options.historyFile)return;try{await(await import("node:fs/promises")).writeFile(this.options.historyFile,this.history.commands.join(`
2771
- `))}catch(e){console.error(`Failed to save history: ${e}`)}}searchHistory(e){return this.history.commands.filter((t)=>t.includes(e))}clearHistory(){this.history.commands=[],this.historyIndex=0}}class Do{variables=new Map;workingDirectory=process.cwd();set(e,t){this.variables.set(e,t)}get(e){return this.variables.get(e)}has(e){return this.variables.has(e)}delete(e){this.variables.delete(e)}getAll(){return Object.fromEntries(this.variables)}clear(){this.variables.clear()}setWorkingDirectory(e){this.workingDirectory=e}getWorkingDirectory(){return this.workingDirectory}}class ko{command={};name(e){return this.command.name=e,this}description(e){return this.command.description=e,this}aliases(...e){return this.command.aliases=e,this}handler(e){return this.command.handler=e,this}autocomplete(e){return this.command.autocomplete=e,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 $o{entries=[];maxSize;persistFile;trackOutput;constructor(e={}){this.maxSize=e.maxSize||1000,this.persistFile=e.persistFile,this.trackOutput=e.trackOutput||!1}add(e){if(this.entries.push({...e,timestamp:new Date}),this.entries.length>this.maxSize)this.entries=this.entries.slice(-this.maxSize)}getAll(){return[...this.entries]}getRecent(e=10){return this.entries.slice(-e)}search(e){let t=e.toLowerCase();return this.entries.filter((a)=>a.command.toLowerCase().includes(t))}searchByDate(e,t){return this.entries.filter((a)=>a.timestamp>=e&&a.timestamp<=t)}getSuccessful(){return this.entries.filter((e)=>e.success)}getFailed(){return this.entries.filter((e)=>!e.success)}getMostUsed(e=10){let t=new Map;for(let a of this.entries){let r=a.command.split(" ")[0];t.set(r,(t.get(r)||0)+1)}return Array.from(t.entries()).map(([a,r])=>({command:a,count:r})).sort((a,r)=>r.count-a.count).slice(0,e)}getStats(){let e=this.entries.length,t=this.entries.filter((o)=>o.success).length,a=this.entries.filter((o)=>!o.success).length,r=this.entries.filter((o)=>o.duration!==void 0),n=r.length>0?r.reduce((o,c)=>o+(c.duration||0),0)/r.length:0,i=this.getMostUsed(1),s=i.length>0?i[0].command:"N/A";return{total:e,successful:t,failed:a,averageDuration:n,mostUsed:s}}clear(){this.entries=[]}getByIndex(e){if(e<0||e>=this.entries.length)return;return this.entries[e]}removeByIndex(e){if(e>=0&&e<this.entries.length)this.entries.splice(e,1)}async save(){if(!this.persistFile)return;try{let e=await import("node:fs/promises"),t=JSON.stringify(this.entries,null,2);await e.writeFile(this.persistFile,t,"utf-8")}catch(e){throw Error(`Failed to save history: ${e}`)}}async load(){if(!this.persistFile)return;try{let e=await(await import("node:fs/promises")).readFile(this.persistFile,"utf-8"),t=JSON.parse(e);this.entries=t.map((a)=>({...a,timestamp:new Date(a.timestamp)}))}catch{this.entries=[]}}exportJSON(){return JSON.stringify(this.entries,null,2)}exportCSV(){return["Timestamp,Command,Success,Duration",...this.entries.map((e)=>[e.timestamp.toISOString(),`"${e.command.replace(/"/g,'""')}"`,e.success,e.duration||""].join(","))].join(`
2772
- `)}importJSON(e){let t=JSON.parse(e).map((a)=>({...a,timestamp:new Date(a.timestamp)}));if(this.entries.push(...t),this.entries.length>this.maxSize)this.entries=this.entries.slice(-this.maxSize)}groupByDate(){let e=new Map;for(let t of this.entries){let a=t.timestamp.toISOString().split("T")[0];if(!e.has(a))e.set(a,[]);e.get(a).push(t)}return e}groupByCommand(){let e=new Map;for(let t of this.entries){let a=t.command.split(" ")[0];if(!e.has(a))e.set(a,[]);e.get(a).push(t)}return e}replay(e){return this.getByIndex(e)?.command}getSuggestions(e,t=5){let a=e.toLowerCase(),r=this.entries.filter((n)=>n.command.toLowerCase().startsWith(a)).map((n)=>n.command);return[...new Set(r)].slice(0,t)}analyzePatterns(){let e=new Map,t=new Map;for(let r of this.entries){let n=r.timestamp.getHours(),i=r.timestamp.getDay();e.set(n,(e.get(n)||0)+1),t.set(i,(t.get(i)||0)+1)}let a=this.entries.length>0?this.getSuccessful().length/this.entries.length:0;return{timeOfDay:e,dayOfWeek:t,successRate:a}}}function Dd(e,t={}){let{maxWidth:a=100}=t;if(e.length===0)return"No command history";let r=[];for(let n=0;n<e.length;n++){let i=e[n],s=(n+1).toString().padStart(4),o=i.timestamp.toLocaleString(),c=i.success?"✓":"✗",l=i.command;if(l.length>a-30)l=l.substring(0,a-33)+"...";let u=`${s} ${o} ${c} ${l}`;if(i.duration)u+=` (${i.duration}ms)`;r.push(u)}return r.join(`
2773
- `)}function kd(e){let t=[];return t.push("Command History Statistics"),t.push("─".repeat(30)),t.push(`Total commands: ${e.total}`),t.push(`Successful: ${e.successful}`),t.push(`Failed: ${e.failed}`),t.push(`Success rate: ${(e.successful/e.total*100).toFixed(1)}%`),t.push(`Average duration: ${e.averageDuration.toFixed(0)}ms`),t.push(`Most used: ${e.mostUsed}`),t.join(`
2774
- `)}class Ar{deployments=new Map;async deploy(e,t){let a=this.generateDeploymentId(),r={id:a,regions:t.regions.map((n)=>({region:n.code,stackName:this.getStackName(e,n.code),status:"pending"})),status:"deploying",startTime:new Date};this.deployments.set(a,r);try{let n=t.regions.find((s)=>s.isPrimary)||t.regions[0];await this.deployToRegion(e,n,r);let i=t.regions.filter((s)=>s.code!==n.code);if(await Promise.all(i.map((s)=>this.deployToRegion(e,s,r))),t.globalResources)await this.deployGlobalResources(r,t);if(t.replication)await this.setupReplication(r,t);if(t.failover?.enabled)await this.setupFailover(r,t);return r.status="deployed",r.endTime=new Date,r}catch(n){throw r.status="failed",r.endTime=new Date,n}}async deployToRegion(e,t,a){let r=a.regions.find((n)=>n.region===t.code);if(!r)throw Error(`Region deployment not found: ${t.code}`);r.status="deploying",r.startTime=new Date;try{let n=this.createRegionConfig(e,t);await this.deployStack(r.stackName,n,t.code),r.status="deployed",r.endTime=new Date,r.outputs={stackId:`arn:aws:cloudformation:${t.code}:123456789012:stack/${r.stackName}/guid`,endpoint:`https://${r.stackName}.${t.code}.example.com`}}catch(n){throw r.status="failed",r.endTime=new Date,r.error=n instanceof Error?n.message:String(n),n}}async deployGlobalResources(e,t){let a={};if(t.globalResources?.route53)a.route53=await this.deployRoute53(e,t);if(t.globalResources?.cloudfront)a.cloudfront=await this.deployCloudFront(e,t);if(t.globalResources?.waf)a.waf=await this.deployWAF(e);e.globalResources=a}async deployRoute53(e,t){let a=[],r=[];for(let n of e.regions){if(n.status!=="deployed")continue;let i={id:`health-${n.region}`,endpoint:n.outputs?.endpoint,path:t.failover?.healthCheckPath||"/health",region:n.region};a.push(i);let s={name:"example.com",type:"A",region:n.region,setIdentifier:n.region,healthCheckId:i.id,resourceRecords:[n.outputs?.endpoint]};r.push(s)}return{healthChecks:a,recordSets:r,hostedZoneId:"Z1234567890ABC"}}async deployCloudFront(e,t){return{distributionId:"E1234567890ABC",domainName:"d1234567890abc.cloudfront.net",origins:e.regions.filter((a)=>a.status==="deployed").map((a,r)=>{let n=t.regions[r];return{id:`origin-${a.region}`,domainName:a.outputs?.endpoint,weight:n?.weight||100}}),status:"Deployed"}}async deployWAF(e){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(e,t){if(t.replication?.s3)await this.setupS3Replication(e);if(t.replication?.dynamodb)await this.setupDynamoDBReplication(e);if(t.replication?.secrets)await this.setupSecretsReplication(e)}async setupS3Replication(e){let t=e.regions.filter((a)=>a.status==="deployed");for(let a=0;a<t.length-1;a++){let r=t[a],n=t[a+1];console.log(`Setting up S3 replication: ${r.region} -> ${n.region}`)}}async setupDynamoDBReplication(e){let t=e.regions.filter((a)=>a.status==="deployed").map((a)=>a.region);console.log(`Setting up DynamoDB global table in regions: ${t.join(", ")}`)}async setupSecretsReplication(e){let t=e.regions.filter((a)=>a.status==="deployed").map((a)=>a.region);console.log(`Setting up Secrets Manager replication in regions: ${t.join(", ")}`)}async setupFailover(e,t){let a=e.regions.find((n,i)=>t.regions[i]?.isPrimary)||e.regions[0],r=e.regions.filter((n)=>n.region!==a.region);console.log(`Setting up failover: primary=${a.region}, secondary=${r.map((n)=>n.region).join(", ")}`)}async destroy(e){let t=this.deployments.get(e);if(!t)throw Error(`Deployment not found: ${e}`);t.status="rolling-back";try{if(t.globalResources)await this.destroyGlobalResources(t.globalResources);await Promise.all(t.regions.map((a)=>this.destroyRegionStack(a))),this.deployments.delete(e)}catch(a){throw t.status="failed",a}}async destroyGlobalResources(e){if(e.waf)console.log("Destroying WAF resources");if(e.cloudfront)console.log("Destroying CloudFront distribution");if(e.route53)console.log("Destroying Route53 resources")}async destroyRegionStack(e){if(e.status!=="deployed")return;e.status="rolling-back";try{console.log(`Destroying stack ${e.stackName} in ${e.region}`),e.status="pending"}catch(t){throw e.status="failed",e.error=t instanceof Error?t.message:String(t),t}}getDeployment(e){return this.deployments.get(e)}listDeployments(){return Array.from(this.deployments.values())}getStackName(e,t){return`${e.project.slug}-${t}`}createRegionConfig(e,t){return{...e,infrastructure:{...e.infrastructure}}}async deployStack(e,t,a){console.log(`Deploying stack ${e} to ${a}`)}generateDeploymentId(){return`deploy-${Date.now()}-${Math.random().toString(36).substring(7)}`}}var $d=new Ar;class Cr{references=[];exports=new Map;addExport(e){let t=`${e.region}:${e.exportName}`;if(!this.exports.has(e.region))this.exports.set(e.region,[]);this.exports.get(e.region).push(e)}getExport(e,t){let a=this.exports.get(e);if(!a)return;return a.find((r)=>r.exportName===t)?.value}createReference(e,t,a,r){let n=`/cross-region/${e}/${a}/${r}`;return this.references.push({sourceRegion:e,targetRegion:t,resourceType:a,resourceId:r,value:n}),n}async resolveReference(e,t){let a=this.references.find((r)=>r.targetRegion===e&&r.value===t);if(!a)throw Error(`Reference not found: ${t}`);return`arn:aws:resource:${a.sourceRegion}:123456789012:${a.resourceType}/${a.resourceId}`}getReferencesForRegion(e){return this.references.filter((t)=>t.sourceRegion===e||t.targetRegion===e)}clear(){this.references=[],this.exports.clear()}}class Tr{resources=new Map;register(e){this.resources.set(e.id,e)}get(e){return this.resources.get(e)}getByType(e){return Array.from(this.resources.values()).filter((t)=>t.type===e)}getCloudFrontDistributions(){return this.getByType("cloudfront")}getRoute53HostedZones(){return this.getByType("route53")}getWAFWebACLs(){return this.getByType("waf")}remove(e){this.resources.delete(e)}clear(){this.resources.clear()}}class vr{pairs=[];addPair(e){this.pairs.push(e)}getPairedRegion(e){let t=this.pairs.find((a)=>a.primary===e||a.secondary===e);if(!t)return;return t.primary===e?t.secondary:t.primary}getAllPairs(){return[...this.pairs]}getReplicatedPairs(){return this.pairs.filter((e)=>e.replicationConfig)}getFailoverPairs(){return this.pairs.filter((e)=>e.failoverConfig?.automatic)}arePaired(e,t){return this.pairs.some((a)=>a.primary===e&&a.secondary===t||a.primary===t&&a.secondary===e)}clear(){this.pairs=[]}}class wr{dependencies=[];addDependency(e){this.dependencies.push(e)}getDependencies(e,t){return this.dependencies.filter((a)=>a.dependentStack===e&&a.dependentRegion===t)}getDependents(e,t){return this.dependencies.filter((a)=>a.dependsOnStack===e&&a.dependsOnRegion===t)}hasDependencies(e,t){return this.getDependencies(e,t).length>0}getDeploymentOrder(e){let t=new Set,a=[],r=(n)=>{let i=`${n.name}:${n.region}`;if(t.has(i))return;t.add(i);let s=this.getDependencies(n.name,n.region);for(let o of s)r({name:o.dependsOnStack,region:o.dependsOnRegion});a.push(n)};for(let n of e)r(n);return a}detectCircularDependencies(){let e=new Set,t=new Set,a=(r,n)=>{let i=`${r}:${n}`;if(t.has(i))return!0;if(e.has(i))return!1;e.add(i),t.add(i);let s=this.getDependencies(r,n);for(let o of s)if(a(o.dependsOnStack,o.dependsOnRegion))return!0;return t.delete(i),!1};for(let r of this.dependencies)if(a(r.dependentStack,r.dependentRegion))return!0;return!1}clear(){this.dependencies=[]}}var Ld=new Cr,Md=new Tr,xd=new vr,Od=new wr,oe=[{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 Ze(e){return oe.find((t)=>t.code===e)}function Bd(){return oe}function _d(e){let t=e.toLowerCase();return oe.filter((a)=>a.location.toLowerCase().includes(t))}function Wd(e){return oe.filter((t)=>t.compliance.includes(e))}function Gd(e){return oe.filter((t)=>t.pricing.tier===e)}function Fd(e){return oe.some((t)=>t.code===e)}function Vd(e){if(e.continent==="North America")return Ze("us-east-1");if(e.continent==="Europe")return Ze("eu-west-1");if(e.continent==="Asia")return Ze("ap-southeast-1");return Ze("us-east-1")}function Ud(e){let t=[...oe];if(e.compliance)t=t.filter((a)=>e.compliance.every((r)=>a.compliance.includes(r)));if(e.requiredServices)t=t.filter((a)=>e.requiredServices.every((r)=>a.services[r]));if(e.pricingSensitive)t.sort((a,r)=>a.pricing.multiplier-r.pricing.multiplier);return t.slice(0,5)}function jd(e){let t=Ze(e);if(!t)throw Error(`Invalid region: ${e}`);let a=[];for(let r of oe){if(r.code===e)continue;let n=Lo(t,r),i=Mo(t,r);a.push({primary:t,secondary:r,distance:n,sameContinent:i})}return a.sort((r,n)=>{if(r.sameContinent!==n.sameContinent)return r.sameContinent?1:-1;return r.distance-n.distance}),a.slice(0,3)}function Lo(e,t){let a={"North America":0,"South America":1,Europe:2,Asia:3,Africa:4,Oceania:5},r=at(e.location),n=at(t.location);return Math.abs((a[r]||0)-(a[n]||0))}function Mo(e,t){return at(e.location)===at(t.location)}function at(e){if(e.includes("USA")||e.includes("Canada"))return"North America";if(e.includes("Europe")||e.includes("Ireland")||e.includes("Germany"))return"Europe";if(e.includes("Asia")||e.includes("Singapore")||e.includes("Japan"))return"Asia";if(e.includes("Brazil"))return"South America";if(e.includes("Australia"))return"Oceania";return"Unknown"}function xo(e){return`${e.name} (${e.code})`}function Kd(e){return e.map((t)=>xo(t)).join(`
2775
- `)}function Hd(){let e={total:oe.length,byContinent:{},byPricingTier:{}};for(let t of oe){let a=at(t.location);e.byContinent[a]=(e.byContinent[a]||0)+1,e.byPricingTier[t.pricing.tier]=(e.byPricingTier[t.pricing.tier]||0)+1}return e}class Er{accounts=new Map;crossAccountRoles=[];accountMappings=[];registerAccount(e){this.accounts.set(e.id,e)}getAccount(e){return this.accounts.get(e)}getAccountByAlias(e){return Array.from(this.accounts.values()).find((t)=>t.alias===e)}listAccounts(){return Array.from(this.accounts.values())}getAccountsByRole(e){return Array.from(this.accounts.values()).filter((t)=>t.role===e)}createCrossAccountRole(e,t,a,r,n){let i={roleArn:`arn:aws:iam::${t}:role/${a}`,roleName:a,sourceAccountId:e,targetAccountId:t,permissions:r,externalId:n?.externalId,sessionDuration:n?.sessionDuration||3600};return this.crossAccountRoles.push(i),i}getAssumeRolePolicyDocument(e,t){let a={Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${e}:root`},Action:"sts:AssumeRole"}]};if(t)a.Statement[0].Condition={StringEquals:{"sts:ExternalId":t}};return a}generateCrossAccountPolicy(e){return{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:e,Resource:"*"}]}}mapEnvironmentToAccount(e,t,a){this.accountMappings.push({environment:e,accountId:t,region:a})}getAccountForEnvironment(e){return this.accountMappings.find((t)=>t.environment===e)}async assumeRole(e,t,a){return console.log(`Assuming role: ${e} with session: ${t}`),{accessKeyId:"AKIAIOSFODNN7EXAMPLE",secretAccessKey:"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",sessionToken:"token",expiration:new Date(Date.now()+3600000)}}async getCredentialsForAccount(e){let t=this.accounts.get(e);if(!t)throw Error(`Account not found: ${e}`);if(t.assumeRoleArn){let a=await this.assumeRole(t.assumeRoleArn,`ts-cloud-${Date.now()}`);return{accessKeyId:a.accessKeyId,secretAccessKey:a.secretAccessKey,sessionToken:a.sessionToken}}throw Error("No credentials available for account")}listCrossAccountRoles(){return[...this.crossAccountRoles]}getCrossAccountRolesForAccount(e){return this.crossAccountRoles.filter((t)=>t.sourceAccountId===e||t.targetAccountId===e)}async validateAccountAccess(e){try{let t=await this.getCredentialsForAccount(e);return console.log(`Validating access to account: ${e}`),!0}catch{return!1}}async getConsolidatedBilling(){let e={};for(let t of this.accounts.values())e[t.id]=Math.random()*1000;return{totalCost:Object.values(e).reduce((t,a)=>t+a,0),byAccount:e}}clear(){this.accounts.clear(),this.crossAccountRoles=[],this.accountMappings=[]}}class Pr{organizationId;organizationalUnits=new Map;getOrganizationId(){return this.organizationId}setOrganizationId(e){this.organizationId=e}createOrganizationalUnit(e,t){let a={id:`ou-${Date.now()}`,name:e,parentId:t,accounts:[]};return this.organizationalUnits.set(a.id,a),a}getOrganizationalUnit(e){return this.organizationalUnits.get(e)}listOrganizationalUnits(){return Array.from(this.organizationalUnits.values())}addAccountToOU(e,t){let a=this.organizationalUnits.get(e);if(!a)throw Error(`Organizational unit not found: ${e}`);if(!a.accounts.includes(t))a.accounts.push(t)}removeAccountFromOU(e,t){let a=this.organizationalUnits.get(e);if(!a)throw Error(`Organizational unit not found: ${e}`);a.accounts=a.accounts.filter((r)=>r!==t)}getAccountsInOU(e){let t=this.organizationalUnits.get(e);if(!t)return[];return[...t.accounts]}applyServiceControlPolicy(e,t){return{id:`scp-${Date.now()}`,name:"Custom SCP",targetId:e,policyDocument:t}}clear(){this.organizationId=void 0,this.organizationalUnits.clear()}}var qd=new Er,zd=new Pr,Oo={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"}]}},Qd={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"]}}}]}}},Jd={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 Yd(e){return Oo[e]}function Zd(e,t){return{Type:"AWS::IAM::Role",Properties:{RoleName:e.roleName,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${e.sourceAccountId}:root`},Action:"sts:AssumeRole",...e.externalId&&{Condition:{StringEquals:{"sts:ExternalId":e.externalId}}}}]},Policies:[{PolicyName:`${e.roleName}Policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:e.permissions,Resource:"*"}]}}],...t&&{ManagedPolicyArns:t},MaxSessionDuration:e.sessionDuration||3600,Tags:[{Key:"ManagedBy",Value:"TS-Cloud"},{Key:"SourceAccount",Value:e.sourceAccountId}]}}}function Xd(e){let t=[],a=[],r=e.accounts.filter((c)=>c.role==="management");if(r.length===0)t.push("No management account defined");if(r.length>1)t.push("Multiple management accounts defined");let n=e.accounts.map((c)=>c.email),i=n.filter((c,l)=>n.indexOf(c)!==l);if(i.length>0)t.push(`Duplicate email addresses: ${i.join(", ")}`);let s=e.accounts.map((c)=>c.alias),o=s.filter((c,l)=>s.indexOf(c)!==l);if(o.length>0)t.push(`Duplicate aliases: ${o.join(", ")}`);if(!e.accounts.some((c)=>c.role==="security"))a.push("No dedicated security account - consider adding one for audit logs");if(e.accounts.length<3)a.push("Less than 3 accounts - consider separating environments");if(!e.accounts.some((c)=>c.role==="production"))a.push("No production account defined");return{valid:t.length===0,errors:t,warnings:a}}function em(e){let t=[];if(t.push(`${e.name}`),t.push("─".repeat(e.name.length)),t.push(e.description),t.push(""),e.organizationalUnits){t.push("Organizational Units:");for(let a of e.organizationalUnits){let r=a.parent?" └─ ":" ";t.push(`${r}${a.name}`)}t.push("")}t.push("Accounts:");for(let a of e.accounts)t.push(` ${a.alias.padEnd(20)} ${a.role.padEnd(15)} ${a.email}`),t.push(` ${"".padEnd(20)} ${a.description}`),t.push("");return t.join(`
2776
- `)}function tm(e={}){let{workflowName:t="Deploy",trigger:a="push",branches:r=["main"],environments:n=["production"],awsRegion:i="us-east-1",awsRole:s,bunVersion:o="latest",deployCommand:c="bun run cloud deploy",testCommand:l="bun test",buildCommand:u="bun run build"}=e,m=!!s;return`name: ${t}
2771
+ `))}catch(e){console.error(`Failed to save history: ${e}`)}}searchHistory(e){return this.history.commands.filter((t)=>t.includes(e))}clearHistory(){this.history.commands=[],this.historyIndex=0}}class No{variables=new Map;workingDirectory=process.cwd();set(e,t){this.variables.set(e,t)}get(e){return this.variables.get(e)}has(e){return this.variables.has(e)}delete(e){this.variables.delete(e)}getAll(){return Object.fromEntries(this.variables)}clear(){this.variables.clear()}setWorkingDirectory(e){this.workingDirectory=e}getWorkingDirectory(){return this.workingDirectory}}class Do{command={};name(e){return this.command.name=e,this}description(e){return this.command.description=e,this}aliases(...e){return this.command.aliases=e,this}handler(e){return this.command.handler=e,this}autocomplete(e){return this.command.autocomplete=e,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 ko{entries=[];maxSize;persistFile;trackOutput;constructor(e={}){this.maxSize=e.maxSize||1000,this.persistFile=e.persistFile,this.trackOutput=e.trackOutput||!1}add(e){if(this.entries.push({...e,timestamp:new Date}),this.entries.length>this.maxSize)this.entries=this.entries.slice(-this.maxSize)}getAll(){return[...this.entries]}getRecent(e=10){return this.entries.slice(-e)}search(e){let t=e.toLowerCase();return this.entries.filter((a)=>a.command.toLowerCase().includes(t))}searchByDate(e,t){return this.entries.filter((a)=>a.timestamp>=e&&a.timestamp<=t)}getSuccessful(){return this.entries.filter((e)=>e.success)}getFailed(){return this.entries.filter((e)=>!e.success)}getMostUsed(e=10){let t=new Map;for(let a of this.entries){let r=a.command.split(" ")[0];t.set(r,(t.get(r)||0)+1)}return Array.from(t.entries()).map(([a,r])=>({command:a,count:r})).sort((a,r)=>r.count-a.count).slice(0,e)}getStats(){let e=this.entries.length,t=this.entries.filter((o)=>o.success).length,a=this.entries.filter((o)=>!o.success).length,r=this.entries.filter((o)=>o.duration!==void 0),n=r.length>0?r.reduce((o,c)=>o+(c.duration||0),0)/r.length:0,i=this.getMostUsed(1),s=i.length>0?i[0].command:"N/A";return{total:e,successful:t,failed:a,averageDuration:n,mostUsed:s}}clear(){this.entries=[]}getByIndex(e){if(e<0||e>=this.entries.length)return;return this.entries[e]}removeByIndex(e){if(e>=0&&e<this.entries.length)this.entries.splice(e,1)}async save(){if(!this.persistFile)return;try{let e=await import("node:fs/promises"),t=JSON.stringify(this.entries,null,2);await e.writeFile(this.persistFile,t,"utf-8")}catch(e){throw Error(`Failed to save history: ${e}`)}}async load(){if(!this.persistFile)return;try{let e=await(await import("node:fs/promises")).readFile(this.persistFile,"utf-8"),t=JSON.parse(e);this.entries=t.map((a)=>({...a,timestamp:new Date(a.timestamp)}))}catch{this.entries=[]}}exportJSON(){return JSON.stringify(this.entries,null,2)}exportCSV(){return["Timestamp,Command,Success,Duration",...this.entries.map((e)=>[e.timestamp.toISOString(),`"${e.command.replace(/"/g,'""')}"`,e.success,e.duration||""].join(","))].join(`
2772
+ `)}importJSON(e){let t=JSON.parse(e).map((a)=>({...a,timestamp:new Date(a.timestamp)}));if(this.entries.push(...t),this.entries.length>this.maxSize)this.entries=this.entries.slice(-this.maxSize)}groupByDate(){let e=new Map;for(let t of this.entries){let a=t.timestamp.toISOString().split("T")[0];if(!e.has(a))e.set(a,[]);e.get(a).push(t)}return e}groupByCommand(){let e=new Map;for(let t of this.entries){let a=t.command.split(" ")[0];if(!e.has(a))e.set(a,[]);e.get(a).push(t)}return e}replay(e){return this.getByIndex(e)?.command}getSuggestions(e,t=5){let a=e.toLowerCase(),r=this.entries.filter((n)=>n.command.toLowerCase().startsWith(a)).map((n)=>n.command);return[...new Set(r)].slice(0,t)}analyzePatterns(){let e=new Map,t=new Map;for(let r of this.entries){let n=r.timestamp.getHours(),i=r.timestamp.getDay();e.set(n,(e.get(n)||0)+1),t.set(i,(t.get(i)||0)+1)}let a=this.entries.length>0?this.getSuccessful().length/this.entries.length:0;return{timeOfDay:e,dayOfWeek:t,successRate:a}}}function Nd(e,t={}){let{maxWidth:a=100}=t;if(e.length===0)return"No command history";let r=[];for(let n=0;n<e.length;n++){let i=e[n],s=(n+1).toString().padStart(4),o=i.timestamp.toLocaleString(),c=i.success?"✓":"✗",l=i.command;if(l.length>a-30)l=l.substring(0,a-33)+"...";let u=`${s} ${o} ${c} ${l}`;if(i.duration)u+=` (${i.duration}ms)`;r.push(u)}return r.join(`
2773
+ `)}function Dd(e){let t=[];return t.push("Command History Statistics"),t.push("─".repeat(30)),t.push(`Total commands: ${e.total}`),t.push(`Successful: ${e.successful}`),t.push(`Failed: ${e.failed}`),t.push(`Success rate: ${(e.successful/e.total*100).toFixed(1)}%`),t.push(`Average duration: ${e.averageDuration.toFixed(0)}ms`),t.push(`Most used: ${e.mostUsed}`),t.join(`
2774
+ `)}class br{deployments=new Map;async deploy(e,t){let a=this.generateDeploymentId(),r={id:a,regions:t.regions.map((n)=>({region:n.code,stackName:this.getStackName(e,n.code),status:"pending"})),status:"deploying",startTime:new Date};this.deployments.set(a,r);try{let n=t.regions.find((s)=>s.isPrimary)||t.regions[0];await this.deployToRegion(e,n,r);let i=t.regions.filter((s)=>s.code!==n.code);if(await Promise.all(i.map((s)=>this.deployToRegion(e,s,r))),t.globalResources)await this.deployGlobalResources(r,t);if(t.replication)await this.setupReplication(r,t);if(t.failover?.enabled)await this.setupFailover(r,t);return r.status="deployed",r.endTime=new Date,r}catch(n){throw r.status="failed",r.endTime=new Date,n}}async deployToRegion(e,t,a){let r=a.regions.find((n)=>n.region===t.code);if(!r)throw Error(`Region deployment not found: ${t.code}`);r.status="deploying",r.startTime=new Date;try{let n=this.createRegionConfig(e,t);await this.deployStack(r.stackName,n,t.code),r.status="deployed",r.endTime=new Date,r.outputs={stackId:`arn:aws:cloudformation:${t.code}:123456789012:stack/${r.stackName}/guid`,endpoint:`https://${r.stackName}.${t.code}.example.com`}}catch(n){throw r.status="failed",r.endTime=new Date,r.error=n instanceof Error?n.message:String(n),n}}async deployGlobalResources(e,t){let a={};if(t.globalResources?.route53)a.route53=await this.deployRoute53(e,t);if(t.globalResources?.cloudfront)a.cloudfront=await this.deployCloudFront(e,t);if(t.globalResources?.waf)a.waf=await this.deployWAF(e);e.globalResources=a}async deployRoute53(e,t){let a=[],r=[];for(let n of e.regions){if(n.status!=="deployed")continue;let i={id:`health-${n.region}`,endpoint:n.outputs?.endpoint,path:t.failover?.healthCheckPath||"/health",region:n.region};a.push(i);let s={name:"example.com",type:"A",region:n.region,setIdentifier:n.region,healthCheckId:i.id,resourceRecords:[n.outputs?.endpoint]};r.push(s)}return{healthChecks:a,recordSets:r,hostedZoneId:"Z1234567890ABC"}}async deployCloudFront(e,t){return{distributionId:"E1234567890ABC",domainName:"d1234567890abc.cloudfront.net",origins:e.regions.filter((a)=>a.status==="deployed").map((a,r)=>{let n=t.regions[r];return{id:`origin-${a.region}`,domainName:a.outputs?.endpoint,weight:n?.weight||100}}),status:"Deployed"}}async deployWAF(e){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(e,t){if(t.replication?.s3)await this.setupS3Replication(e);if(t.replication?.dynamodb)await this.setupDynamoDBReplication(e);if(t.replication?.secrets)await this.setupSecretsReplication(e)}async setupS3Replication(e){let t=e.regions.filter((a)=>a.status==="deployed");for(let a=0;a<t.length-1;a++){let r=t[a],n=t[a+1];console.log(`Setting up S3 replication: ${r.region} -> ${n.region}`)}}async setupDynamoDBReplication(e){let t=e.regions.filter((a)=>a.status==="deployed").map((a)=>a.region);console.log(`Setting up DynamoDB global table in regions: ${t.join(", ")}`)}async setupSecretsReplication(e){let t=e.regions.filter((a)=>a.status==="deployed").map((a)=>a.region);console.log(`Setting up Secrets Manager replication in regions: ${t.join(", ")}`)}async setupFailover(e,t){let a=e.regions.find((n,i)=>t.regions[i]?.isPrimary)||e.regions[0],r=e.regions.filter((n)=>n.region!==a.region);console.log(`Setting up failover: primary=${a.region}, secondary=${r.map((n)=>n.region).join(", ")}`)}async destroy(e){let t=this.deployments.get(e);if(!t)throw Error(`Deployment not found: ${e}`);t.status="rolling-back";try{if(t.globalResources)await this.destroyGlobalResources(t.globalResources);await Promise.all(t.regions.map((a)=>this.destroyRegionStack(a))),this.deployments.delete(e)}catch(a){throw t.status="failed",a}}async destroyGlobalResources(e){if(e.waf)console.log("Destroying WAF resources");if(e.cloudfront)console.log("Destroying CloudFront distribution");if(e.route53)console.log("Destroying Route53 resources")}async destroyRegionStack(e){if(e.status!=="deployed")return;e.status="rolling-back";try{console.log(`Destroying stack ${e.stackName} in ${e.region}`),e.status="pending"}catch(t){throw e.status="failed",e.error=t instanceof Error?t.message:String(t),t}}getDeployment(e){return this.deployments.get(e)}listDeployments(){return Array.from(this.deployments.values())}getStackName(e,t){return`${e.project.slug}-${t}`}createRegionConfig(e,t){return{...e,infrastructure:{...e.infrastructure}}}async deployStack(e,t,a){console.log(`Deploying stack ${e} to ${a}`)}generateDeploymentId(){return`deploy-${Date.now()}-${Math.random().toString(36).substring(7)}`}}var kd=new br;class Ar{references=[];exports=new Map;addExport(e){let t=`${e.region}:${e.exportName}`;if(!this.exports.has(e.region))this.exports.set(e.region,[]);this.exports.get(e.region).push(e)}getExport(e,t){let a=this.exports.get(e);if(!a)return;return a.find((r)=>r.exportName===t)?.value}createReference(e,t,a,r){let n=`/cross-region/${e}/${a}/${r}`;return this.references.push({sourceRegion:e,targetRegion:t,resourceType:a,resourceId:r,value:n}),n}async resolveReference(e,t){let a=this.references.find((r)=>r.targetRegion===e&&r.value===t);if(!a)throw Error(`Reference not found: ${t}`);return`arn:aws:resource:${a.sourceRegion}:123456789012:${a.resourceType}/${a.resourceId}`}getReferencesForRegion(e){return this.references.filter((t)=>t.sourceRegion===e||t.targetRegion===e)}clear(){this.references=[],this.exports.clear()}}class Cr{resources=new Map;register(e){this.resources.set(e.id,e)}get(e){return this.resources.get(e)}getByType(e){return Array.from(this.resources.values()).filter((t)=>t.type===e)}getCloudFrontDistributions(){return this.getByType("cloudfront")}getRoute53HostedZones(){return this.getByType("route53")}getWAFWebACLs(){return this.getByType("waf")}remove(e){this.resources.delete(e)}clear(){this.resources.clear()}}class Tr{pairs=[];addPair(e){this.pairs.push(e)}getPairedRegion(e){let t=this.pairs.find((a)=>a.primary===e||a.secondary===e);if(!t)return;return t.primary===e?t.secondary:t.primary}getAllPairs(){return[...this.pairs]}getReplicatedPairs(){return this.pairs.filter((e)=>e.replicationConfig)}getFailoverPairs(){return this.pairs.filter((e)=>e.failoverConfig?.automatic)}arePaired(e,t){return this.pairs.some((a)=>a.primary===e&&a.secondary===t||a.primary===t&&a.secondary===e)}clear(){this.pairs=[]}}class vr{dependencies=[];addDependency(e){this.dependencies.push(e)}getDependencies(e,t){return this.dependencies.filter((a)=>a.dependentStack===e&&a.dependentRegion===t)}getDependents(e,t){return this.dependencies.filter((a)=>a.dependsOnStack===e&&a.dependsOnRegion===t)}hasDependencies(e,t){return this.getDependencies(e,t).length>0}getDeploymentOrder(e){let t=new Set,a=[],r=(n)=>{let i=`${n.name}:${n.region}`;if(t.has(i))return;t.add(i);let s=this.getDependencies(n.name,n.region);for(let o of s)r({name:o.dependsOnStack,region:o.dependsOnRegion});a.push(n)};for(let n of e)r(n);return a}detectCircularDependencies(){let e=new Set,t=new Set,a=(r,n)=>{let i=`${r}:${n}`;if(t.has(i))return!0;if(e.has(i))return!1;e.add(i),t.add(i);let s=this.getDependencies(r,n);for(let o of s)if(a(o.dependsOnStack,o.dependsOnRegion))return!0;return t.delete(i),!1};for(let r of this.dependencies)if(a(r.dependentStack,r.dependentRegion))return!0;return!1}clear(){this.dependencies=[]}}var Md=new Ar,Ld=new Cr,xd=new Tr,Od=new vr,se=[{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 Ye(e){return se.find((t)=>t.code===e)}function Wd(){return se}function _d(e){let t=e.toLowerCase();return se.filter((a)=>a.location.toLowerCase().includes(t))}function Bd(e){return se.filter((t)=>t.compliance.includes(e))}function Ud(e){return se.filter((t)=>t.pricing.tier===e)}function Gd(e){return se.some((t)=>t.code===e)}function Vd(e){if(e.continent==="North America")return Ye("us-east-1");if(e.continent==="Europe")return Ye("eu-west-1");if(e.continent==="Asia")return Ye("ap-southeast-1");return Ye("us-east-1")}function Fd(e){let t=[...se];if(e.compliance)t=t.filter((a)=>e.compliance.every((r)=>a.compliance.includes(r)));if(e.requiredServices)t=t.filter((a)=>e.requiredServices.every((r)=>a.services[r]));if(e.pricingSensitive)t.sort((a,r)=>a.pricing.multiplier-r.pricing.multiplier);return t.slice(0,5)}function jd(e){let t=Ye(e);if(!t)throw Error(`Invalid region: ${e}`);let a=[];for(let r of se){if(r.code===e)continue;let n=Mo(t,r),i=Lo(t,r);a.push({primary:t,secondary:r,distance:n,sameContinent:i})}return a.sort((r,n)=>{if(r.sameContinent!==n.sameContinent)return r.sameContinent?1:-1;return r.distance-n.distance}),a.slice(0,3)}function Mo(e,t){let a={"North America":0,"South America":1,Europe:2,Asia:3,Africa:4,Oceania:5},r=tt(e.location),n=tt(t.location);return Math.abs((a[r]||0)-(a[n]||0))}function Lo(e,t){return tt(e.location)===tt(t.location)}function tt(e){if(e.includes("USA")||e.includes("Canada"))return"North America";if(e.includes("Europe")||e.includes("Ireland")||e.includes("Germany"))return"Europe";if(e.includes("Asia")||e.includes("Singapore")||e.includes("Japan"))return"Asia";if(e.includes("Brazil"))return"South America";if(e.includes("Australia"))return"Oceania";return"Unknown"}function xo(e){return`${e.name} (${e.code})`}function Kd(e){return e.map((t)=>xo(t)).join(`
2775
+ `)}function Hd(){let e={total:se.length,byContinent:{},byPricingTier:{}};for(let t of se){let a=tt(t.location);e.byContinent[a]=(e.byContinent[a]||0)+1,e.byPricingTier[t.pricing.tier]=(e.byPricingTier[t.pricing.tier]||0)+1}return e}class wr{accounts=new Map;crossAccountRoles=[];accountMappings=[];registerAccount(e){this.accounts.set(e.id,e)}getAccount(e){return this.accounts.get(e)}getAccountByAlias(e){return Array.from(this.accounts.values()).find((t)=>t.alias===e)}listAccounts(){return Array.from(this.accounts.values())}getAccountsByRole(e){return Array.from(this.accounts.values()).filter((t)=>t.role===e)}createCrossAccountRole(e,t,a,r,n){let i={roleArn:`arn:aws:iam::${t}:role/${a}`,roleName:a,sourceAccountId:e,targetAccountId:t,permissions:r,externalId:n?.externalId,sessionDuration:n?.sessionDuration||3600};return this.crossAccountRoles.push(i),i}getAssumeRolePolicyDocument(e,t){let a={Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${e}:root`},Action:"sts:AssumeRole"}]};if(t)a.Statement[0].Condition={StringEquals:{"sts:ExternalId":t}};return a}generateCrossAccountPolicy(e){return{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:e,Resource:"*"}]}}mapEnvironmentToAccount(e,t,a){this.accountMappings.push({environment:e,accountId:t,region:a})}getAccountForEnvironment(e){return this.accountMappings.find((t)=>t.environment===e)}async assumeRole(e,t,a){return console.log(`Assuming role: ${e} with session: ${t}`),{accessKeyId:"AKIAIOSFODNN7EXAMPLE",secretAccessKey:"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",sessionToken:"token",expiration:new Date(Date.now()+3600000)}}async getCredentialsForAccount(e){let t=this.accounts.get(e);if(!t)throw Error(`Account not found: ${e}`);if(t.assumeRoleArn){let a=await this.assumeRole(t.assumeRoleArn,`ts-cloud-${Date.now()}`);return{accessKeyId:a.accessKeyId,secretAccessKey:a.secretAccessKey,sessionToken:a.sessionToken}}throw Error("No credentials available for account")}listCrossAccountRoles(){return[...this.crossAccountRoles]}getCrossAccountRolesForAccount(e){return this.crossAccountRoles.filter((t)=>t.sourceAccountId===e||t.targetAccountId===e)}async validateAccountAccess(e){try{let t=await this.getCredentialsForAccount(e);return console.log(`Validating access to account: ${e}`),!0}catch{return!1}}async getConsolidatedBilling(){let e={};for(let t of this.accounts.values())e[t.id]=Math.random()*1000;return{totalCost:Object.values(e).reduce((t,a)=>t+a,0),byAccount:e}}clear(){this.accounts.clear(),this.crossAccountRoles=[],this.accountMappings=[]}}class Er{organizationId;organizationalUnits=new Map;getOrganizationId(){return this.organizationId}setOrganizationId(e){this.organizationId=e}createOrganizationalUnit(e,t){let a={id:`ou-${Date.now()}`,name:e,parentId:t,accounts:[]};return this.organizationalUnits.set(a.id,a),a}getOrganizationalUnit(e){return this.organizationalUnits.get(e)}listOrganizationalUnits(){return Array.from(this.organizationalUnits.values())}addAccountToOU(e,t){let a=this.organizationalUnits.get(e);if(!a)throw Error(`Organizational unit not found: ${e}`);if(!a.accounts.includes(t))a.accounts.push(t)}removeAccountFromOU(e,t){let a=this.organizationalUnits.get(e);if(!a)throw Error(`Organizational unit not found: ${e}`);a.accounts=a.accounts.filter((r)=>r!==t)}getAccountsInOU(e){let t=this.organizationalUnits.get(e);if(!t)return[];return[...t.accounts]}applyServiceControlPolicy(e,t){return{id:`scp-${Date.now()}`,name:"Custom SCP",targetId:e,policyDocument:t}}clear(){this.organizationId=void 0,this.organizationalUnits.clear()}}var qd=new wr,zd=new Er,Oo={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"}]}},Jd={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"]}}}]}}},Qd={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 $d(e){return Oo[e]}function Yd(e,t){return{Type:"AWS::IAM::Role",Properties:{RoleName:e.roleName,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${e.sourceAccountId}:root`},Action:"sts:AssumeRole",...e.externalId&&{Condition:{StringEquals:{"sts:ExternalId":e.externalId}}}}]},Policies:[{PolicyName:`${e.roleName}Policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:e.permissions,Resource:"*"}]}}],...t&&{ManagedPolicyArns:t},MaxSessionDuration:e.sessionDuration||3600,Tags:[{Key:"ManagedBy",Value:"TS-Cloud"},{Key:"SourceAccount",Value:e.sourceAccountId}]}}}function Xd(e){let t=[],a=[],r=e.accounts.filter((c)=>c.role==="management");if(r.length===0)t.push("No management account defined");if(r.length>1)t.push("Multiple management accounts defined");let n=e.accounts.map((c)=>c.email),i=n.filter((c,l)=>n.indexOf(c)!==l);if(i.length>0)t.push(`Duplicate email addresses: ${i.join(", ")}`);let s=e.accounts.map((c)=>c.alias),o=s.filter((c,l)=>s.indexOf(c)!==l);if(o.length>0)t.push(`Duplicate aliases: ${o.join(", ")}`);if(!e.accounts.some((c)=>c.role==="security"))a.push("No dedicated security account - consider adding one for audit logs");if(e.accounts.length<3)a.push("Less than 3 accounts - consider separating environments");if(!e.accounts.some((c)=>c.role==="production"))a.push("No production account defined");return{valid:t.length===0,errors:t,warnings:a}}function Zd(e){let t=[];if(t.push(`${e.name}`),t.push("─".repeat(e.name.length)),t.push(e.description),t.push(""),e.organizationalUnits){t.push("Organizational Units:");for(let a of e.organizationalUnits){let r=a.parent?" └─ ":" ";t.push(`${r}${a.name}`)}t.push("")}t.push("Accounts:");for(let a of e.accounts)t.push(` ${a.alias.padEnd(20)} ${a.role.padEnd(15)} ${a.email}`),t.push(` ${"".padEnd(20)} ${a.description}`),t.push("");return t.join(`
2776
+ `)}function em(e={}){let{workflowName:t="Deploy",trigger:a="push",branches:r=["main"],environments:n=["production"],awsRegion:i="us-east-1",awsRole:s,bunVersion:o="latest",deployCommand:c="bun run cloud deploy",testCommand:l="bun test",buildCommand:u="bun run build"}=e,m=!!s;return`name: ${t}
2777
2777
 
2778
2778
  on:
2779
2779
  ${a}:
@@ -2842,7 +2842,7 @@ jobs:
2842
2842
 
2843
2843
  - name: Post-deployment tests
2844
2844
  run: bun run cloud test:smoke
2845
- `}function am(e){let{environments:t,awsRegion:a="us-east-1",awsRole:r}=e,n=!!r;return`name: Multi-Environment Deploy
2845
+ `}function tm(e){let{environments:t,awsRegion:a="us-east-1",awsRole:r}=e,n=!!r;return`name: Multi-Environment Deploy
2846
2846
 
2847
2847
  on:
2848
2848
  push:
@@ -2898,7 +2898,7 @@ ${t.map((i,s)=>` ${s>0?"elif":"if"} [[ "\${{ github.ref }}" == "refs/he
2898
2898
 
2899
2899
  - name: Deploy
2900
2900
  run: bun run cloud deploy --env=\${{ needs.determine-environment.outputs.environment }}
2901
- `}function rm(e={}){let{awsRegion:t="us-east-1",awsRole:a,ttl:r=24}=e,n=!!a;return`name: PR Preview Environment
2901
+ `}function am(e={}){let{awsRegion:t="us-east-1",awsRole:a,ttl:r=24}=e,n=!!a;return`name: PR Preview Environment
2902
2902
 
2903
2903
  on:
2904
2904
  pull_request:
@@ -3003,7 +3003,7 @@ jobs:
3003
3003
  bun run cloud env:preview --destroy \\
3004
3004
  --branch=\${{ github.head_ref }} \\
3005
3005
  --pr=\${{ github.event.pull_request.number }}
3006
- `}function nm(e){let{schedule:t,environment:a,awsRegion:r="us-east-1",awsRole:n}=e;return`name: Scheduled Deployment
3006
+ `}function rm(e){let{schedule:t,environment:a,awsRegion:r="us-east-1",awsRole:n}=e;return`name: Scheduled Deployment
3007
3007
 
3008
3008
  on:
3009
3009
  schedule:
@@ -3045,7 +3045,7 @@ jobs:
3045
3045
 
3046
3046
  - name: Deploy
3047
3047
  run: bun run cloud deploy --env=\${{ env.ENVIRONMENT }}
3048
- `}function im(e){let{matrix:t,awsRole:a}=e,r=!!a;return`name: Matrix Deployment
3048
+ `}function nm(e){let{matrix:t,awsRole:a}=e,r=!!a;return`name: Matrix Deployment
3049
3049
 
3050
3050
  on:
3051
3051
  workflow_dispatch:
@@ -3092,7 +3092,7 @@ ${t.map((n)=>` - environment: ${n.environment}
3092
3092
 
3093
3093
  - name: Deploy to \${{ matrix.environment }} (\${{ matrix.region }})
3094
3094
  run: bun run cloud deploy --env=\${{ matrix.environment }} --region=\${{ matrix.region }}
3095
- `}function sm(e={}){let{stages:t=["test","build","deploy"],environments:a=["production"],awsRegion:r="us-east-1",dockerImage:n="oven/bun:latest",deployCommand:i="bun run cloud deploy",testCommand:s="bun test",buildCommand:o="bun run build"}=e;return`stages:
3095
+ `}function im(e={}){let{stages:t=["test","build","deploy"],environments:a=["production"],awsRegion:r="us-east-1",dockerImage:n="oven/bun:latest",deployCommand:i="bun run cloud deploy",testCommand:s="bun test",buildCommand:o="bun run build"}=e;return`stages:
3096
3096
  ${t.map((c)=>` - ${c}`).join(`
3097
3097
  `)}
3098
3098
 
@@ -3140,7 +3140,7 @@ deploy:
3140
3140
  only:
3141
3141
  - main
3142
3142
  when: manual
3143
- `}function om(e){let{environments:t,awsRegion:a="us-east-1"}=e,r=t.map((n)=>`
3143
+ `}function sm(e){let{environments:t,awsRegion:a="us-east-1"}=e,r=t.map((n)=>`
3144
3144
  deploy:${n.name}:
3145
3145
  stage: deploy
3146
3146
  script:
@@ -3181,7 +3181,7 @@ build:
3181
3181
  paths:
3182
3182
  - dist/
3183
3183
  ${r}
3184
- `}function cm(e={}){let{awsRegion:t="us-east-1",ttl:a=24}=e;return`stages:
3184
+ `}function om(e={}){let{awsRegion:t="us-east-1",ttl:a=24}=e;return`stages:
3185
3185
  - build
3186
3186
  - deploy
3187
3187
  - cleanup
@@ -3226,7 +3226,7 @@ cleanup:preview:
3226
3226
  when: manual
3227
3227
  only:
3228
3228
  - merge_requests
3229
- `}function lm(e){let{environment:t,awsRegion:a="us-east-1"}=e;return`stages:
3229
+ `}function cm(e){let{environment:t,awsRegion:a="us-east-1"}=e;return`stages:
3230
3230
  - deploy
3231
3231
 
3232
3232
  variables:
@@ -3245,7 +3245,7 @@ deploy:scheduled:
3245
3245
  name: \${ENVIRONMENT}
3246
3246
  only:
3247
3247
  - schedules
3248
- `}function um(e){let{environments:t,awsRegion:a="us-east-1"}=e,r=t.map((n)=>`
3248
+ `}function lm(e){let{environments:t,awsRegion:a="us-east-1"}=e,r=t.map((n)=>`
3249
3249
  deploy:${n}:
3250
3250
  stage: deploy
3251
3251
  script:
@@ -3266,7 +3266,7 @@ variables:
3266
3266
  default:
3267
3267
  image: oven/bun:latest
3268
3268
  ${r}
3269
- `}function dm(e={}){let{awsRegion:t="us-east-1",dockerImage:a="oven/bun:latest",deployCommand:r="bun run cloud deploy",testCommand:n="bun test",buildCommand:i="bun run build",workflows:s=!0}=e;return`version: 2.1
3269
+ `}function um(e={}){let{awsRegion:t="us-east-1",dockerImage:a="oven/bun:latest",deployCommand:r="bun run cloud deploy",testCommand:n="bun test",buildCommand:i="bun run build",workflows:s=!0}=e;return`version: 2.1
3270
3270
 
3271
3271
  orbs:
3272
3272
  aws-cli: circleci/aws-cli@4.0
@@ -3349,7 +3349,7 @@ ${s?`workflows:
3349
3349
  branches:
3350
3350
  only: main
3351
3351
  `:""}
3352
- `}function mm(e){let{environments:t,awsRegion:a="us-east-1"}=e,r=t.map((i)=>`
3352
+ `}function dm(e){let{environments:t,awsRegion:a="us-east-1"}=e,r=t.map((i)=>`
3353
3353
  deploy-${i.name}:
3354
3354
  executor: bun-executor
3355
3355
  steps:
@@ -3425,7 +3425,7 @@ workflows:
3425
3425
  requires:
3426
3426
  - test
3427
3427
  ${n}
3428
- `}function pm(e){let{schedule:t,environment:a,awsRegion:r="us-east-1"}=e;return`version: 2.1
3428
+ `}function mm(e){let{schedule:t,environment:a,awsRegion:r="us-east-1"}=e;return`version: 2.1
3429
3429
 
3430
3430
  orbs:
3431
3431
  aws-cli: circleci/aws-cli@4.0
@@ -3462,7 +3462,7 @@ workflows:
3462
3462
  only: main
3463
3463
  jobs:
3464
3464
  - deploy
3465
- `}function gm(e){let{environments:t,awsRegion:a="us-east-1"}=e,r=t.map((i)=>`
3465
+ `}function pm(e){let{environments:t,awsRegion:a="us-east-1"}=e,r=t.map((i)=>`
3466
3466
  deploy-${i}:
3467
3467
  executor: bun-executor
3468
3468
  steps:
@@ -3538,7 +3538,7 @@ workflows:
3538
3538
  requires:
3539
3539
  - test
3540
3540
  ${n}
3541
- `}function hm(e){let{regions:t,environment:a}=e,r=t.map((i)=>`
3541
+ `}function gm(e){let{regions:t,environment:a}=e,r=t.map((i)=>`
3542
3542
  deploy-${i.replace(/-/g,"_")}:
3543
3543
  executor: bun-executor
3544
3544
  environment:
@@ -3607,7 +3607,7 @@ workflows:
3607
3607
  requires:
3608
3608
  - test
3609
3609
  ${n}
3610
- `}class Ir{backupPlans=new Map;backupVaults=new Map;restoreJobs=new Map;continuousBackups=new Map;planCounter=0;restoreCounter=0;continuousBackupCounter=0;createVault(e){this.backupVaults.set(e.name,e)}getVault(e){return this.backupVaults.get(e)}createBackupPlan(e){let t=`backup-plan-${Date.now()}-${this.planCounter++}`,a={id:t,...e};return this.backupPlans.set(t,a),a}getBackupPlan(e){return this.backupPlans.get(e)}listBackupPlans(){return Array.from(this.backupPlans.values())}createRDSBackupPlan(e){let{dbInstanceArn:t,schedule:a="0 2 * * *",retentionDays:r=7,vaultName:n="default-vault"}=e;return this.createBackupPlan({name:"RDS Daily Backup",schedule:a,retentionDays:r,vaultName:n,resources:[{resourceArn:t,resourceType:"rds",region:"us-east-1"}],lifecycle:{moveTocoldStorageAfterDays:30,deleteAfterDays:r}})}createDynamoDBBackupPlan(e){let{tableArn:t,schedule:a="0 3 * * *",retentionDays:r=35,crossRegionCopy:n}=e;return this.createBackupPlan({name:"DynamoDB Daily Backup",schedule:a,retentionDays:r,vaultName:"dynamodb-vault",resources:[{resourceArn:t,resourceType:"dynamodb",region:"us-east-1"}],lifecycle:{deleteAfterDays:r},tags:n?{CrossRegionCopy:n.join(",")}:void 0})}createEFSBackupPlan(e){let{fileSystemArn:t,schedule:a="0 1 * * *",retentionDays:r=30}=e;return this.createBackupPlan({name:"EFS Daily Backup",schedule:a,retentionDays:r,vaultName:"efs-vault",resources:[{resourceArn:t,resourceType:"efs",region:"us-east-1"}],lifecycle:{deleteAfterDays:r}})}enableContinuousBackup(e,t=35){let a=`continuous-backup-${Date.now()}-${this.continuousBackupCounter++}`,r={id:a,resourceId:e,enabled:!0,retentionDays:t};return this.continuousBackups.set(a,r),r}getContinuousBackup(e){return this.continuousBackups.get(e)}enablePointInTimeRecovery(e,t){return{enabled:!0,earliestRestorableTime:new Date(Date.now()-604800000),latestRestorableTime:new Date}}async restoreFromBackup(e){let{backupId:t,resourceType:a,targetRegion:r}=e,n={id:`restore-${Date.now()}-${this.restoreCounter++}`,backupId:t,resourceType:a,status:"pending",startTime:new Date,targetRegion:r};return this.restoreJobs.set(n.id,n),setTimeout(()=>{n.status="running"},100),setTimeout(()=>{n.status="completed",n.endTime=new Date},1000),n}async restoreToPointInTime(e){let{sourceResourceArn:t,targetResourceName:a,restoreTime:r,resourceType:n}=e,i={id:`pitr-${Date.now()}-${this.restoreCounter++}`,backupId:`pitr-${r.getTime()}`,resourceType:n,status:"pending",startTime:new Date};return this.restoreJobs.set(i.id,i),console.log(`Restoring ${n} from ${t} to ${a} at ${r.toISOString()}`),setTimeout(()=>{i.status="completed",i.endTime=new Date},2000),i}getRestoreJob(e){return this.restoreJobs.get(e)}listRestoreJobs(){return Array.from(this.restoreJobs.values())}setupCrossRegionReplication(e){let{sourceVault:t,sourceRegion:a,targetRegions:r}=e;console.log("Setting up cross-region replication:"),console.log(` Source: ${t} in ${a}`),console.log(` Targets: ${r.join(", ")}`)}generateBackupVaultCF(e){return{Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:e.name,...e.encryptionKeyArn&&{EncryptionKeyArn:e.encryptionKeyArn},...e.accessPolicy&&{AccessPolicy:e.accessPolicy}}}}generateBackupPlanCF(e){return{Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:e.name,BackupPlanRule:[{RuleName:"DailyBackup",TargetBackupVault:e.vaultName,ScheduleExpression:`cron(${e.schedule})`,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:e.lifecycle?{...e.lifecycle.moveTocoldStorageAfterDays&&{MoveToColdStorageAfterDays:e.lifecycle.moveTocoldStorageAfterDays},...e.lifecycle.deleteAfterDays&&{DeleteAfterDays:e.lifecycle.deleteAfterDays}}:void 0}]},...e.tags&&{BackupPlanTags:e.tags}}}}generateBackupSelectionCF(e){return{Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:{Ref:`BackupPlan${e.id}`},BackupSelection:{SelectionName:`${e.name}Selection`,IamRoleArn:"arn:aws:iam::123456789012:role/service-role/AWSBackupDefaultServiceRole",Resources:e.resources.map((t)=>t.resourceArn)}}}}clear(){this.backupPlans.clear(),this.backupVaults.clear(),this.restoreJobs.clear(),this.continuousBackups.clear(),this.planCounter=0,this.restoreCounter=0,this.continuousBackupCounter=0}}var ym=new Ir;class Rr{drPlans=new Map;failoverTests=new Map;planCounter=0;testCounter=0;createDRPlan(e){let t=`dr-plan-${Date.now()}-${this.planCounter++}`,a={id:t,...e};return this.drPlans.set(t,a),a}createRDSDRPlan(e){let{primaryDbArn:t,secondaryDbArn:a,primaryRegion:r,secondaryRegion:n,rto:i=60,rpo:s=5}=e;return this.createDRPlan({name:"RDS Multi-Region DR",primaryRegion:r,secondaryRegion:n,rto:i,rpo:s,resources:[{resourceId:"primary-db",resourceType:"rds",primaryArn:t,secondaryArn:a,replicationEnabled:!0}],runbook:this.generateRDSRunbook(r,n),testSchedule:"0 0 1 * *"})}createDynamoDBDRPlan(e){let{tableArn:t,regions:a,rto:r=15,rpo:n=1}=e;return this.createDRPlan({name:"DynamoDB Global Tables DR",primaryRegion:a[0],secondaryRegion:a[1],rto:r,rpo:n,resources:[{resourceId:"dynamodb-table",resourceType:"dynamodb",primaryArn:t,replicationEnabled:!0}],runbook:this.generateDynamoDBRunbook(a)})}generateRDSRunbook(e,t){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 "+e,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 "+t,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(e){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(e,t=!1){let a=this.drPlans.get(e);if(!a)throw Error(`DR plan not found: ${e}`);let r=Date.now(),n=0;console.log(`${t?"[DRY RUN] ":""}Executing failover for plan: ${a.name}`),console.log(`Primary: ${a.primaryRegion} -> Secondary: ${a.secondaryRegion}`),console.log(`RTO: ${a.rto} minutes, RPO: ${a.rpo} minutes`),console.log("");for(let i of a.runbook.steps){if(console.log(`Step ${i.order}: ${i.name}`),console.log(` ${i.description}`),console.log(` Action: ${i.action}`),console.log(` Estimated: ${i.estimatedDuration} minutes`),t)console.log(" [SKIPPED - DRY RUN]");else if(i.automatable)console.log(" [AUTOMATED]");else console.log(" [MANUAL - WAITING]");n++,console.log("")}return{success:!0,duration:(Date.now()-r)/1000/60,completedSteps:n}}scheduleFailoverTest(e,t){let a={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:e,status:"scheduled",startTime:t};return this.failoverTests.set(a.id,a),a}async runFailoverTest(e){let t=this.drPlans.get(e);if(!t)throw Error(`DR plan not found: ${e}`);let a={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:e,status:"running",startTime:new Date,results:[]};this.failoverTests.set(a.id,a),console.log(`Running failover test for plan: ${t.name}`),console.log("This is a non-destructive test using test resources"),console.log("");for(let r of t.runbook.steps){let n=Date.now();console.log(`Testing step ${r.order}: ${r.name}`);let i={step:r.name,status:"success",duration:(Date.now()-n)/1000,message:`Successfully validated step ${r.order}`};a.results.push(i)}return a.status="completed",a.endTime=new Date,a}getDRPlan(e){return this.drPlans.get(e)}listDRPlans(){return Array.from(this.drPlans.values())}getFailoverTest(e){return this.failoverTests.get(e)}listFailoverTests(){return Array.from(this.failoverTests.values())}validateDRPlan(e){let t=[],a=[];if(e.rto<e.rpo)a.push("RTO cannot be less than RPO");if(e.rto>240)t.push("RTO exceeds 4 hours - consider improving recovery time");if(e.rpo>60)t.push("RPO exceeds 1 hour - consider more frequent backups");if(e.resources.length===0)a.push("No resources defined in DR plan");for(let i of e.resources){if(!i.replicationEnabled)t.push(`Resource ${i.resourceId} does not have replication enabled`);if(!i.secondaryArn&&i.resourceType!=="dynamodb")t.push(`Resource ${i.resourceId} does not have secondary resource defined`)}if(e.runbook.steps.length===0)a.push("No recovery steps defined in runbook");let r=e.runbook.steps.reduce((i,s)=>i+s.estimatedDuration,0);if(r>e.rto)t.push(`Estimated recovery duration (${r}m) exceeds RTO (${e.rto}m)`);let n=e.runbook.steps.filter((i)=>!i.automatable);if(n.length>0)t.push(`${n.length} manual steps in runbook - consider automation`);return{valid:a.length===0,warnings:t,errors:a}}clear(){this.drPlans.clear(),this.failoverTests.clear(),this.planCounter=0,this.testCounter=0}}var fm=new Rr;class Nr{configRules=new Map;configRecorders=new Map;deliveryChannels=new Map;ruleCounter=0;createConfigRecorder(e){return this.configRecorders.set(e.name,e),e}createDeliveryChannel(e){return this.deliveryChannels.set(e.name,e),e}createConfigRule(e){let t=`config-rule-${Date.now()}-${this.ruleCounter++}`,a={id:t,...e};return this.configRules.set(t,a),a}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(e=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:e},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(e){return this.createConfigRule({name:e.name,description:e.description,source:"CUSTOM_LAMBDA",lambdaFunctionArn:e.lambdaFunctionArn,scope:e.resourceTypes?{complianceResourceTypes:e.resourceTypes}:void 0,maxExecutionFrequency:e.maxExecutionFrequency,inputParameters:e.inputParameters})}createCompliancePreset(e){let t=[];switch(e){case"hipaa":t.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createRdsBackupRule(7),this.createVpcFlowLogsRule());break;case"pci-dss":t.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createIamMfaRule(),this.createRootAccountMfaRule(),this.createVpcFlowLogsRule());break;case"sox":t.push(this.createS3VersioningRule(),this.createCloudTrailEnabledRule(),this.createRdsBackupRule(30),this.createIamPasswordPolicyRule());break;case"gdpr":t.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createRdsSnapshotEncryptionRule());break;case"basic":t.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamMfaRule(),this.createRootAccountMfaRule());break}return t}getConfigRule(e){return this.configRules.get(e)}listConfigRules(){return Array.from(this.configRules.values())}getConfigRecorder(e){return this.configRecorders.get(e)}listConfigRecorders(){return Array.from(this.configRecorders.values())}getDeliveryChannel(e){return this.deliveryChannels.get(e)}listDeliveryChannels(){return Array.from(this.deliveryChannels.values())}generateConfigRuleCF(e){let t={Type:"AWS::Config::ConfigRule",Properties:{ConfigRuleName:e.name,Description:e.description,Source:{Owner:e.source==="AWS_MANAGED"?"AWS":"CUSTOM_LAMBDA"}}};if(e.source==="AWS_MANAGED"&&e.identifier)t.Properties.Source.SourceIdentifier=e.identifier;if(e.source==="CUSTOM_LAMBDA"&&e.lambdaFunctionArn)t.Properties.Source.SourceIdentifier=e.lambdaFunctionArn,t.Properties.Source.SourceDetails=[{EventSource:"aws.config",MessageType:"ConfigurationItemChangeNotification"}];if(e.inputParameters)t.Properties.InputParameters=JSON.stringify(e.inputParameters);if(e.scope){if(t.Properties.Scope={},e.scope.complianceResourceTypes)t.Properties.Scope.ComplianceResourceTypes=e.scope.complianceResourceTypes;if(e.scope.tagKey)t.Properties.Scope.TagKey=e.scope.tagKey;if(e.scope.tagValue)t.Properties.Scope.TagValue=e.scope.tagValue}if(e.maxExecutionFrequency)t.Properties.MaximumExecutionFrequency=e.maxExecutionFrequency;return t}generateConfigRecorderCF(e){return{Type:"AWS::Config::ConfigurationRecorder",Properties:{Name:e.name,RoleArn:e.roleArn,RecordingGroup:e.recordingGroup||{AllSupported:!0,IncludeGlobalResourceTypes:!0}}}}generateDeliveryChannelCF(e){return{Type:"AWS::Config::DeliveryChannel",Properties:{Name:e.name,S3BucketName:e.s3BucketName,...e.s3KeyPrefix&&{S3KeyPrefix:e.s3KeyPrefix},...e.snsTopicArn&&{SnsTopicARN:e.snsTopicArn},...e.configSnapshotDeliveryProperties&&{ConfigSnapshotDeliveryProperties:e.configSnapshotDeliveryProperties}}}}clear(){this.configRules.clear(),this.configRecorders.clear(),this.deliveryChannels.clear(),this.ruleCounter=0}}var Sm=new Nr;class Dr{trails=new Map;trailCounter=0;createTrail(e){let t=`trail-${Date.now()}-${this.trailCounter++}`,a={id:t,...e};return this.trails.set(t,a),a}createOrganizationTrail(e){return this.createTrail({name:e.name,s3BucketName:e.s3BucketName,s3KeyPrefix:"organization-trail",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:e.kmsKeyId,cloudWatchLogsLogGroupArn:e.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:e.cloudWatchLogsRoleArn})}createSecurityAuditTrail(e){return this.createTrail({name:e.name,s3BucketName:e.s3BucketName,s3KeyPrefix:"security-audit",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:e.kmsKeyId,cloudWatchLogsLogGroupArn:e.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:e.cloudWatchLogsRoleArn,eventSelectors:[{readWriteType:"All",includeManagementEvents:!0,excludeManagementEventSources:[]}],insightSelectors:[{insightType:"ApiCallRateInsight"},{insightType:"ApiErrorRateInsight"}]})}createDataEventsTrail(e){let t=[];if(e.s3DataBuckets&&e.s3DataBuckets.length>0)t.push({type:"AWS::S3::Object",values:e.s3DataBuckets.map((a)=>`arn:aws:s3:::${a}/*`)});if(e.lambdaFunctions&&e.lambdaFunctions.length>0)t.push({type:"AWS::Lambda::Function",values:e.lambdaFunctions});return this.createTrail({name:e.name,s3BucketName:e.s3BucketName,s3KeyPrefix:"data-events",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"All",includeManagementEvents:!1,dataResources:t}]})}createAdvancedTrail(e){return this.createTrail({name:e.name,s3BucketName:e.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,advancedEventSelectors:e.selectors})}createReadOnlyTrail(e){return this.createTrail({name:e.name,s3BucketName:e.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"ReadOnly",includeManagementEvents:!0}]})}createWriteOnlyTrail(e){return this.createTrail({name:e.name,s3BucketName:e.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"WriteOnly",includeManagementEvents:!0}]})}getTrail(e){return this.trails.get(e)}listTrails(){return Array.from(this.trails.values())}generateTrailCF(e){let t={Type:"AWS::CloudTrail::Trail",Properties:{TrailName:e.name,S3BucketName:e.s3BucketName,IsLogging:!0,IncludeGlobalServiceEvents:e.includeGlobalServiceEvents??!0,IsMultiRegionTrail:e.isMultiRegionTrail??!0,EnableLogFileValidation:e.enableLogFileValidation??!0}};if(e.s3KeyPrefix)t.Properties.S3KeyPrefix=e.s3KeyPrefix;if(e.cloudWatchLogsLogGroupArn)t.Properties.CloudWatchLogsLogGroupArn=e.cloudWatchLogsLogGroupArn;if(e.cloudWatchLogsRoleArn)t.Properties.CloudWatchLogsRoleArn=e.cloudWatchLogsRoleArn;if(e.snsTopicName)t.Properties.SnsTopicName=e.snsTopicName;if(e.kmsKeyId)t.Properties.KMSKeyId=e.kmsKeyId;if(e.eventSelectors)t.Properties.EventSelectors=e.eventSelectors.map((a)=>({ReadWriteType:a.readWriteType,IncludeManagementEvents:a.includeManagementEvents??!0,...a.dataResources&&{DataResources:a.dataResources.map((r)=>({Type:r.type,Values:r.values}))},...a.excludeManagementEventSources&&{ExcludeManagementEventSources:a.excludeManagementEventSources}}));if(e.insightSelectors)t.Properties.InsightSelectors=e.insightSelectors.map((a)=>({InsightType:a.insightType}));if(e.advancedEventSelectors)t.Properties.AdvancedEventSelectors=e.advancedEventSelectors.map((a)=>({Name:a.name,FieldSelectors:a.fieldSelectors.map((r)=>({Field:r.field,...r.equals&&{Equals:r.equals},...r.startsWith&&{StartsWith:r.startsWith},...r.endsWith&&{EndsWith:r.endsWith},...r.notEquals&&{NotEquals:r.notEquals},...r.notStartsWith&&{NotStartsWith:r.notStartsWith},...r.notEndsWith&&{NotEndsWith:r.notEndsWith}}))}));return t}generateBucketPolicy(e,t){return{Version:"2012-10-17",Statement:[{Sid:"AWSCloudTrailAclCheck",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:GetBucketAcl",Resource:`arn:aws:s3:::${e}`},{Sid:"AWSCloudTrailWrite",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:PutObject",Resource:t.map((a)=>`arn:aws:s3:::${e}/AWSLogs/${a}/*`),Condition:{StringEquals:{"s3:x-amz-acl":"bucket-owner-full-control"}}}]}}clear(){this.trails.clear(),this.trailCounter=0}}var bm=new Dr;class kr{detectors=new Map;threatIntelSets=new Map;ipSets=new Map;filters=new Map;detectorCounter=0;threatIntelCounter=0;ipSetCounter=0;filterCounter=0;createDetector(e){let t=`detector-${Date.now()}-${this.detectorCounter++}`,a={id:t,...e};return this.detectors.set(t,a),a}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(e){let t=`threat-intel-${Date.now()}-${this.threatIntelCounter++}`,a={id:t,...e};return this.threatIntelSets.set(t,a),a}createIPSet(e){let t=`ip-set-${Date.now()}-${this.ipSetCounter++}`,a={id:t,...e};return this.ipSets.set(t,a),a}createFindingFilter(e){let t=`filter-${Date.now()}-${this.filterCounter++}`,a={id:t,...e};return this.filters.set(t,a),a}createLowSeverityArchiveFilter(e){return this.createFindingFilter({detectorId:e,name:"archive-low-severity",description:"Automatically archive low severity findings",action:"ARCHIVE",rank:1,findingCriteria:{criterion:{severity:{lt:4}}}})}createFindingTypeFilter(e,t,a){return this.createFindingFilter({detectorId:e,name:`filter-finding-types-${a.toLowerCase()}`,description:`${a==="ARCHIVE"?"Archive":"Keep"} specific finding types`,action:a,rank:2,findingCriteria:{criterion:{type:{eq:t}}}})}createTrustedIPFilter(e,t){return this.createFindingFilter({detectorId:e,name:"trusted-ip-addresses",description:"Archive findings from trusted IP addresses",action:"ARCHIVE",rank:3,findingCriteria:{criterion:{"resource.instanceDetails.networkInterfaces.privateIpAddress":{eq:t}}}})}getDetector(e){return this.detectors.get(e)}listDetectors(){return Array.from(this.detectors.values())}getThreatIntelSet(e){return this.threatIntelSets.get(e)}listThreatIntelSets(){return Array.from(this.threatIntelSets.values())}getIPSet(e){return this.ipSets.get(e)}listIPSets(){return Array.from(this.ipSets.values())}getFindingFilter(e){return this.filters.get(e)}listFindingFilters(){return Array.from(this.filters.values())}generateDetectorCF(e){let t={Type:"AWS::GuardDuty::Detector",Properties:{Enable:e.enable}};if(e.findingPublishingFrequency)t.Properties.FindingPublishingFrequency=e.findingPublishingFrequency;if(e.dataSources){if(t.Properties.DataSources={},e.dataSources.s3Logs)t.Properties.DataSources.S3Logs={Enable:e.dataSources.s3Logs.enable};if(e.dataSources.kubernetes)t.Properties.DataSources.Kubernetes={AuditLogs:{Enable:e.dataSources.kubernetes.auditLogs.enable}};if(e.dataSources.malwareProtection)t.Properties.DataSources.MalwareProtection={ScanEc2InstanceWithFindings:{EbsVolumes:{Enable:e.dataSources.malwareProtection.scanEc2InstanceWithFindings.ebsVolumes.enable}}}}if(e.features)t.Properties.Features=e.features.map((a)=>({Name:a.name,Status:a.status,...a.additionalConfiguration&&{AdditionalConfiguration:a.additionalConfiguration}}));return t}generateThreatIntelSetCF(e){return{Type:"AWS::GuardDuty::ThreatIntelSet",Properties:{DetectorId:e.detectorId,Name:e.name,Format:e.format,Location:e.location,Activate:e.activate}}}generateIPSetCF(e){return{Type:"AWS::GuardDuty::IPSet",Properties:{DetectorId:e.detectorId,Name:e.name,Format:e.format,Location:e.location,Activate:e.activate}}}generateFilterCF(e){return{Type:"AWS::GuardDuty::Filter",Properties:{DetectorId:e.detectorId,Name:e.name,Description:e.description,Action:e.action,Rank:e.rank,FindingCriteria:{Criterion:e.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 Am=new kr;class xe{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(e){let t=`hub-${Date.now()}-${this.hubCounter++}`,a={id:t,...e};return this.hubs.set(t,a),a}createComprehensiveHub(){return this.createHub({enable:!0,controlFindingGenerator:"SECURITY_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...xe.Standards.AWS_FOUNDATIONAL_SECURITY,enabled:!0},{id:"cis-1-4",...xe.Standards.CIS_AWS_FOUNDATIONS_1_4,enabled:!0},{id:"pci-dss",...xe.Standards.PCI_DSS,enabled:!0}]})}createBasicHub(){return this.createHub({enable:!0,controlFindingGenerator:"STANDARD_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...xe.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(e){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:e.map((t)=>({value:t,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(e,t){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:`Suppress False Positives - ${e}`,description:`Automatically suppress known false positives from ${e}`,actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"SUPPRESSED"},note:{text:"Known false positive - automatically suppressed",updatedBy:"SecurityHub Automation"}}}],criteria:{productName:[{value:e,comparison:"EQUALS"}],title:t.map((a)=>({value:a,comparison:"PREFIX"}))},ruleStatus:"ENABLED",ruleOrder:10}}getHub(e){return this.hubs.get(e)}listHubs(){return Array.from(this.hubs.values())}generateHubCF(e){let t={Type:"AWS::SecurityHub::Hub",Properties:{}};if(e.controlFindingGenerator)t.Properties.ControlFindingGenerator=e.controlFindingGenerator;if(e.enableDefaultStandards!==void 0)t.Properties.EnableDefaultStandards=e.enableDefaultStandards;return t}generateStandardCF(e){let t={Type:"AWS::SecurityHub::Standard",Properties:{StandardsArn:e.arn}};if(e.disabledControls&&e.disabledControls.length>0)t.Properties.DisabledStandardsControls=e.disabledControls.map((a)=>({StandardsControlArn:a,Reason:"Disabled by configuration"}));return t}generateAutomationRuleCF(e){return{Type:"AWS::SecurityHub::AutomationRule",Properties:{RuleName:e.ruleName,Description:e.description,Actions:e.actions.map((t)=>({Type:t.type,FindingFieldsUpdate:t.findingFieldsUpdate})),Criteria:e.criteria,RuleStatus:e.ruleStatus,RuleOrder:e.ruleOrder}}}clear(){this.hubs.clear(),this.hubCounter=0,this.ruleCounter=0}}var Cm=new xe;class $r{deployments=new Map;deploymentHistory=new Map;deploymentCounter=0;resultCounter=0;createDeployment(e){let t=`bg-deployment-${Date.now()}-${this.deploymentCounter++}`,a={id:t,...e};return this.deployments.set(t,a),a}createALBDeployment(e){return this.createDeployment({name:e.name,blueEnvironment:{name:"blue",targetGroupArn:e.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:e.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:e.listenerArn,switchoverTimeSeconds:0},autoPromote:e.autoPromote,healthCheckConfig:e.healthCheckConfig})}createRoute53Deployment(e){return this.createDeployment({name:e.name,blueEnvironment:{name:"blue",targetGroupArn:e.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:e.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"route53",hostedZoneId:e.hostedZoneId,switchoverTimeSeconds:e.switchoverTimeSeconds||60}})}createECSDeployment(e){return this.createDeployment({name:e.name,blueEnvironment:{name:"blue",targetGroupArn:e.blueTargetGroupArn,taskDefinitionArn:e.blueTaskDefinitionArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:e.greenTargetGroupArn,taskDefinitionArn:e.greenTaskDefinitionArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:e.listenerArn},autoRollback:e.autoRollback??!0})}async executeDeployment(e,t=!1){let a=this.deployments.get(e);if(!a)throw Error(`Deployment not found: ${e}`);let r={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!1,errors:[]};console.log(`${t?"[DRY RUN] ":""}Starting blue/green deployment: ${a.name}`),console.log(` Active environment: ${a.activeEnvironment}`),console.log(` Routing type: ${a.routingConfig.type}`);let n=a.activeEnvironment==="blue"?"green":"blue";if(console.log(` Switching to: ${n}`),console.log(`\\n1. Deploying to ${n} environment`),!t)await new Promise((i)=>setTimeout(i,100));if(console.log(`\\n2. Running health checks on ${n} environment`),a.healthCheckConfig){let i=await this.runHealthChecks(a,n,t);if(r.healthChecksPassed=i,!i){if(r.errors?.push("Health checks failed"),r.endTime=new Date,a.autoRollback)console.log(" Auto-rollback enabled - keeping current environment active"),r.rolledBackAt=new Date;return this.recordDeployment(e,r),r}}else r.healthChecksPassed=!0;if(console.log(`\\n3. Switching traffic to ${n} environment`),!t)a.activeEnvironment=n,r.switchedAt=new Date;if(console.log(`\\n4. Monitoring ${n} environment`),!t)await new Promise((i)=>setTimeout(i,100));return r.success=!0,r.endTime=new Date,console.log("\\n✓ Deployment completed successfully"),this.recordDeployment(e,r),r}async rollback(e){let t=this.deployments.get(e);if(!t)throw Error(`Deployment not found: ${e}`);let a={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!0,errors:[]};console.log(`Rolling back deployment: ${t.name}`);let r=t.activeEnvironment==="blue"?"green":"blue";return t.activeEnvironment=r,a.success=!0,a.rolledBackAt=new Date,a.endTime=new Date,console.log(` Switched back to: ${r}`),this.recordDeployment(e,a),a}async runHealthChecks(e,t,a){let r=e.healthCheckConfig;if(console.log(` Health check path: ${r.path||"/"}`),console.log(` Healthy threshold: ${r.healthyThreshold}`),console.log(` Interval: ${r.interval}s`),a)return console.log(" [SKIPPED - DRY RUN]"),!0;let n=0,i=r.healthyThreshold+2;for(let s=0;s<i;s++)if(await new Promise((o)=>setTimeout(o,50)),Math.random()>0.1){if(n++,console.log(` Check ${s+1}: ✓ Healthy (${n}/${r.healthyThreshold})`),n>=r.healthyThreshold)return!0}else n=0,console.log(` Check ${s+1}: ✗ Unhealthy`);return!1}recordDeployment(e,t){if(!this.deploymentHistory.has(e))this.deploymentHistory.set(e,[]);this.deploymentHistory.get(e).push(t)}getDeployment(e){return this.deployments.get(e)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(e){return this.deploymentHistory.get(e)||[]}generateALBListenerCF(e){let t=e.activeEnvironment==="blue"?e.blueEnvironment:e.greenEnvironment;return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:e.routingConfig.listenerArn,Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",TargetGroupArn:t.targetGroupArn}]}}}generateRoute53RecordSetCF(e,t){return[{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:e.routingConfig.hostedZoneId,Name:t,Type:"A",SetIdentifier:"blue",Weight:e.activeEnvironment==="blue"?100:0,AliasTarget:{HostedZoneId:e.routingConfig.hostedZoneId,DNSName:e.blueEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}},{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:e.routingConfig.hostedZoneId,Name:t,Type:"A",SetIdentifier:"green",Weight:e.activeEnvironment==="green"?100:0,AliasTarget:{HostedZoneId:e.routingConfig.hostedZoneId,DNSName:e.greenEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}}]}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var Tm=new $r;class vt{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(e){let t=`canary-${Date.now()}-${this.deploymentCounter++}`,a={id:t,...e};return this.deployments.set(t,a),a}createLambdaCanaryDeployment(e){let t=e.strategy||"BALANCED",a=vt.Strategies[t].map((r)=>({...r,alarmThresholds:{errorRate:e.errorRateThreshold||1,latencyP99:e.latencyThreshold||1000}}));return this.createDeployment({name:e.name,baselineVersion:{version:"baseline",functionVersionArn:e.baselineVersionArn,weight:100},canaryVersion:{version:"canary",functionVersionArn:e.canaryVersionArn,weight:0},stages:a,currentStage:0,status:"pending",autoPromote:e.autoPromote??!0,autoRollback:!0})}createECSCanaryDeployment(e){let t=e.strategy||"CONSERVATIVE",a=vt.Strategies[t];return this.createDeployment({name:e.name,baselineVersion:{version:"baseline",taskDefinitionArn:e.baselineTaskDefinitionArn,targetGroupArn:e.baselineTargetGroupArn,weight:100},canaryVersion:{version:"canary",taskDefinitionArn:e.canaryTaskDefinitionArn,targetGroupArn:e.canaryTargetGroupArn,weight:0},stages:a,currentStage:0,status:"pending",autoRollback:!0})}async executeDeployment(e,t=!1){let a=this.deployments.get(e);if(!a)throw Error(`Deployment not found: ${e}`);let r={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,completedStages:0,rolledBack:!1};console.log(`${t?"[DRY RUN] ":""}Starting canary deployment: ${a.name}`),console.log(` Strategy: ${a.stages.length} stages`),console.log(` Auto-promote: ${a.autoPromote}`),console.log(` Auto-rollback: ${a.autoRollback}`),console.log(""),a.status="in_progress";for(let n=0;n<a.stages.length;n++){let i=a.stages[n];if(a.currentStage=n,console.log(`Stage ${n+1}/${a.stages.length}: ${i.name}`),console.log(` Traffic: ${i.trafficPercentage}% canary, ${100-i.trafficPercentage}% baseline`),console.log(` Duration: ${i.durationMinutes} minutes`),!t)a.baselineVersion.weight=100-i.trafficPercentage,a.canaryVersion.weight=i.trafficPercentage;if(!await this.monitorStage(a,i,t)){if(console.log(" ✗ Stage failed - metrics exceeded thresholds"),a.autoRollback)console.log("\\n Rolling back deployment..."),await this.rollback(e,t),r.rolledBack=!0,r.reason="Metrics exceeded thresholds";return r.endTime=new Date,a.status="rolled_back",this.recordDeployment(e,r),r}console.log(" ✓ Stage completed successfully"),r.completedStages++,console.log("")}return a.status="completed",r.success=!0,r.endTime=new Date,console.log("✓ Canary deployment completed successfully"),this.recordDeployment(e,r),r}async monitorStage(e,t,a){if(console.log(" Monitoring metrics..."),a)return console.log(" [SKIPPED - DRY RUN]"),!0;await new Promise((n)=>setTimeout(n,100));let r={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)*t.trafficPercentage/100)};if(e.metrics=r,console.log(` Baseline: ${r.baselineErrorRate.toFixed(2)}% errors, ${r.baselineLatencyP99.toFixed(0)}ms P99`),console.log(` Canary: ${r.canaryErrorRate.toFixed(2)}% errors, ${r.canaryLatencyP99.toFixed(0)}ms P99`),t.alarmThresholds){let{errorRate:n,latencyP99:i}=t.alarmThresholds;if(n&&r.canaryErrorRate>n)return console.log(` ⚠ Error rate exceeded threshold: ${r.canaryErrorRate.toFixed(2)}% > ${n}%`),!1;if(i&&r.canaryLatencyP99>i)return console.log(` ⚠ Latency P99 exceeded threshold: ${r.canaryLatencyP99.toFixed(0)}ms > ${i}ms`),!1}return!0}async rollback(e,t=!1){let a=this.deployments.get(e);if(!a)throw Error(`Deployment not found: ${e}`);if(console.log(`${t?"[DRY RUN] ":""}Rolling back canary deployment: ${a.name}`),!t)a.baselineVersion.weight=100,a.canaryVersion.weight=0,a.status="rolled_back";console.log(" Traffic restored to baseline: 100%")}promoteCanary(e){let t=this.deployments.get(e);if(!t)throw Error(`Deployment not found: ${e}`);console.log(`Promoting canary to baseline: ${t.name}`);let a=t.baselineVersion;t.baselineVersion=t.canaryVersion,t.canaryVersion=a,t.baselineVersion.weight=100,t.canaryVersion.weight=0,t.status="completed",console.log(" Canary promoted successfully")}recordDeployment(e,t){if(!this.deploymentHistory.has(e))this.deploymentHistory.set(e,[]);this.deploymentHistory.get(e).push(t)}getDeployment(e){return this.deployments.get(e)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(e){return this.deploymentHistory.get(e)||[]}generateLambdaAliasCF(e,t){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:{Ref:"LambdaFunction"},Name:t,FunctionVersion:e.canaryVersion.version,RoutingConfig:{AdditionalVersionWeights:[{FunctionVersion:e.baselineVersion.version,FunctionWeight:e.baselineVersion.weight/100}]}}}}generateALBListenerRuleCF(e){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:[{TargetGroupArn:e.baselineVersion.targetGroupArn,Weight:e.baselineVersion.weight},{TargetGroupArn:e.canaryVersion.targetGroupArn,Weight:e.canaryVersion.weight}],TargetGroupStickinessConfig:{Enabled:!1}}}]}}}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var vm=new vt;class Lr{tests=new Map;testCounter=0;createTest(e){let t=`abtest-${Date.now()}-${this.testCounter++}`,a={id:t,...e};return this.tests.set(t,a),a}createSimpleABTest(e){let t=e.variantTrafficPercentage||50;return this.createTest({name:e.name,description:e.description,variants:[{id:"control",name:"Control",description:"Original version",trafficPercentage:100-t,targetGroupArn:e.controlTargetGroupArn,weight:100-t},{id:"variant-a",name:"Variant A",description:"Test version",trafficPercentage:t,targetGroupArn:e.variantTargetGroupArn,weight:t}],routingStrategy:{type:e.stickySession?"cookie":"random",cookieName:e.stickySession?"ab_variant":void 0,stickySession:e.stickySession??!1,sessionDuration:1440},startTime:new Date,status:"draft"})}createMultivariateTest(e){let t=e.variants.reduce((a,r)=>a+r.trafficPercentage,0);if(t!==100)throw Error(`Traffic percentages must sum to 100, got ${t}`);return this.createTest({name:e.name,description:e.description,variants:e.variants.map((a,r)=>({id:`variant-${r}`,name:a.name,description:a.description,trafficPercentage:a.trafficPercentage,targetGroupArn:a.targetGroupArn,weight:a.trafficPercentage})),routingStrategy:e.routingStrategy||{type:"random",stickySession:!1},startTime:new Date,status:"draft"})}createHeaderBasedTest(e){return this.createTest({name:e.name,description:`Route based on ${e.headerName} header`,variants:[{id:"control",name:"Control",trafficPercentage:50,targetGroupArn:e.controlTargetGroupArn,weight:50},{id:"variant-a",name:"Variant A",trafficPercentage:50,targetGroupArn:e.variantTargetGroupArn,weight:50}],routingStrategy:{type:"header",headerName:e.headerName,stickySession:!1},startTime:new Date,status:"draft"})}createGeoBasedTest(e){return this.createTest({name:e.name,description:"Route based on geographic location",variants:[{id:"control",name:"Control (Rest of World)",trafficPercentage:50,targetGroupArn:e.controlTargetGroupArn,weight:50},{id:"variant-a",name:`Variant A (${e.regions.join(", ")})`,trafficPercentage:50,targetGroupArn:e.variantTargetGroupArn,weight:50}],routingStrategy:{type:"geo",stickySession:!0,sessionDuration:1440},startTime:new Date,status:"draft"})}startTest(e){let t=this.tests.get(e);if(!t)throw Error(`Test not found: ${e}`);if(t.status!=="draft"&&t.status!=="paused")throw Error(`Cannot start test in ${t.status} status`);t.status="active",t.startTime=new Date,console.log(`Started A/B test: ${t.name}`),console.log(` Variants: ${t.variants.length}`),t.variants.forEach((a)=>{console.log(` - ${a.name}: ${a.trafficPercentage}%`)})}pauseTest(e){let t=this.tests.get(e);if(!t)throw Error(`Test not found: ${e}`);t.status="paused",console.log(`Paused A/B test: ${t.name}`)}updateTrafficSplit(e,t,a){let r=this.tests.get(e);if(!r)throw Error(`Test not found: ${e}`);let n=r.variants.find((s)=>s.id===t);if(!n)throw Error(`Variant not found: ${t}`);let i=n.trafficPercentage;n.trafficPercentage=a,n.weight=a,console.log(`Updated ${n.name} traffic: ${i}% → ${a}%`)}analyzeResults(e){let t=this.tests.get(e);if(!t)throw Error(`Test not found: ${e}`);if(!t.metrics)t.metrics=this.collectMetrics(t);let a=t.variants[0],r=0;for(let l of t.variants){let u=t.metrics.variants[l.id];if(u&&u.conversionRate>r)r=u.conversionRate,a=l}let n=t.metrics.variants.control||t.metrics.variants[t.variants[0].id],i=t.metrics.variants[a.id],s=(i.conversionRate-n.conversionRate)/n.conversionRate*100,o=100,c=i.requests>o&&n.requests>o&&Math.abs(s)>10;return{testId:e,winningVariant:a.name,confidence:c?95:75,improvement:s,statisticalSignificance:c,metrics:t.metrics,recommendation:this.generateRecommendation(s,c,a.name)}}declareWinner(e,t){let a=this.tests.get(e);if(!a)throw Error(`Test not found: ${e}`);let r=a.variants.find((n)=>n.id===t);if(!r)throw Error(`Variant not found: ${t}`);a.variants.forEach((n)=>{if(n.id===t)n.trafficPercentage=100,n.weight=100;else n.trafficPercentage=0,n.weight=0}),a.status="completed",a.endTime=new Date,a.winner=t,console.log(`Declared winner: ${r.name}`),console.log(` All traffic now routed to ${r.name}`)}collectMetrics(e){let t={},a=0;for(let r of e.variants){let n=Math.floor(Math.random()*1000)+500,i=Math.floor(n*(Math.random()*0.1+0.05)),s=i/n*100;t[r.id]={requests:n,conversions:i,conversionRate:s,averageLatency:150+Math.random()*100,errorRate:Math.random()*0.5,revenue:i*(Math.random()*50+100)},a+=n}return{variants:t,totalRequests:a,startTime:e.startTime,lastUpdated:new Date}}generateRecommendation(e,t,a){if(!t)return"Continue test - sample size too small or no significant difference detected";if(e>20)return`Strong winner detected - ${a} shows ${e.toFixed(1)}% improvement. Recommend deploying to all traffic.`;if(e>10)return`Moderate improvement - ${a} shows ${e.toFixed(1)}% improvement. Consider deploying.`;if(e>0)return`Minor improvement - ${a} shows ${e.toFixed(1)}% improvement. May not be worth the complexity.`;return"No improvement detected - consider reverting to control variant"}getTest(e){return this.tests.get(e)}listTests(){return Array.from(this.tests.values())}generateALBListenerRuleCF(e){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:e.variants.map((t)=>({TargetGroupArn:t.targetGroupArn,Weight:t.weight})),TargetGroupStickinessConfig:{Enabled:e.routingStrategy.stickySession||!1,DurationSeconds:e.routingStrategy.sessionDuration?e.routingStrategy.sessionDuration*60:void 0}}}]}}}generateLambdaEdgeFunction(e){return`'use strict';
3610
+ `}class Pr{backupPlans=new Map;backupVaults=new Map;restoreJobs=new Map;continuousBackups=new Map;planCounter=0;restoreCounter=0;continuousBackupCounter=0;createVault(e){this.backupVaults.set(e.name,e)}getVault(e){return this.backupVaults.get(e)}createBackupPlan(e){let t=`backup-plan-${Date.now()}-${this.planCounter++}`,a={id:t,...e};return this.backupPlans.set(t,a),a}getBackupPlan(e){return this.backupPlans.get(e)}listBackupPlans(){return Array.from(this.backupPlans.values())}createRDSBackupPlan(e){let{dbInstanceArn:t,schedule:a="0 2 * * *",retentionDays:r=7,vaultName:n="default-vault"}=e;return this.createBackupPlan({name:"RDS Daily Backup",schedule:a,retentionDays:r,vaultName:n,resources:[{resourceArn:t,resourceType:"rds",region:"us-east-1"}],lifecycle:{moveTocoldStorageAfterDays:30,deleteAfterDays:r}})}createDynamoDBBackupPlan(e){let{tableArn:t,schedule:a="0 3 * * *",retentionDays:r=35,crossRegionCopy:n}=e;return this.createBackupPlan({name:"DynamoDB Daily Backup",schedule:a,retentionDays:r,vaultName:"dynamodb-vault",resources:[{resourceArn:t,resourceType:"dynamodb",region:"us-east-1"}],lifecycle:{deleteAfterDays:r},tags:n?{CrossRegionCopy:n.join(",")}:void 0})}createEFSBackupPlan(e){let{fileSystemArn:t,schedule:a="0 1 * * *",retentionDays:r=30}=e;return this.createBackupPlan({name:"EFS Daily Backup",schedule:a,retentionDays:r,vaultName:"efs-vault",resources:[{resourceArn:t,resourceType:"efs",region:"us-east-1"}],lifecycle:{deleteAfterDays:r}})}enableContinuousBackup(e,t=35){let a=`continuous-backup-${Date.now()}-${this.continuousBackupCounter++}`,r={id:a,resourceId:e,enabled:!0,retentionDays:t};return this.continuousBackups.set(a,r),r}getContinuousBackup(e){return this.continuousBackups.get(e)}enablePointInTimeRecovery(e,t){return{enabled:!0,earliestRestorableTime:new Date(Date.now()-604800000),latestRestorableTime:new Date}}async restoreFromBackup(e){let{backupId:t,resourceType:a,targetRegion:r}=e,n={id:`restore-${Date.now()}-${this.restoreCounter++}`,backupId:t,resourceType:a,status:"pending",startTime:new Date,targetRegion:r};return this.restoreJobs.set(n.id,n),setTimeout(()=>{n.status="running"},100),setTimeout(()=>{n.status="completed",n.endTime=new Date},1000),n}async restoreToPointInTime(e){let{sourceResourceArn:t,targetResourceName:a,restoreTime:r,resourceType:n}=e,i={id:`pitr-${Date.now()}-${this.restoreCounter++}`,backupId:`pitr-${r.getTime()}`,resourceType:n,status:"pending",startTime:new Date};return this.restoreJobs.set(i.id,i),console.log(`Restoring ${n} from ${t} to ${a} at ${r.toISOString()}`),setTimeout(()=>{i.status="completed",i.endTime=new Date},2000),i}getRestoreJob(e){return this.restoreJobs.get(e)}listRestoreJobs(){return Array.from(this.restoreJobs.values())}setupCrossRegionReplication(e){let{sourceVault:t,sourceRegion:a,targetRegions:r}=e;console.log("Setting up cross-region replication:"),console.log(` Source: ${t} in ${a}`),console.log(` Targets: ${r.join(", ")}`)}generateBackupVaultCF(e){return{Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:e.name,...e.encryptionKeyArn&&{EncryptionKeyArn:e.encryptionKeyArn},...e.accessPolicy&&{AccessPolicy:e.accessPolicy}}}}generateBackupPlanCF(e){return{Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:e.name,BackupPlanRule:[{RuleName:"DailyBackup",TargetBackupVault:e.vaultName,ScheduleExpression:`cron(${e.schedule})`,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:e.lifecycle?{...e.lifecycle.moveTocoldStorageAfterDays&&{MoveToColdStorageAfterDays:e.lifecycle.moveTocoldStorageAfterDays},...e.lifecycle.deleteAfterDays&&{DeleteAfterDays:e.lifecycle.deleteAfterDays}}:void 0}]},...e.tags&&{BackupPlanTags:e.tags}}}}generateBackupSelectionCF(e){return{Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:{Ref:`BackupPlan${e.id}`},BackupSelection:{SelectionName:`${e.name}Selection`,IamRoleArn:"arn:aws:iam::123456789012:role/service-role/AWSBackupDefaultServiceRole",Resources:e.resources.map((t)=>t.resourceArn)}}}}clear(){this.backupPlans.clear(),this.backupVaults.clear(),this.restoreJobs.clear(),this.continuousBackups.clear(),this.planCounter=0,this.restoreCounter=0,this.continuousBackupCounter=0}}var hm=new Pr;class Ir{drPlans=new Map;failoverTests=new Map;planCounter=0;testCounter=0;createDRPlan(e){let t=`dr-plan-${Date.now()}-${this.planCounter++}`,a={id:t,...e};return this.drPlans.set(t,a),a}createRDSDRPlan(e){let{primaryDbArn:t,secondaryDbArn:a,primaryRegion:r,secondaryRegion:n,rto:i=60,rpo:s=5}=e;return this.createDRPlan({name:"RDS Multi-Region DR",primaryRegion:r,secondaryRegion:n,rto:i,rpo:s,resources:[{resourceId:"primary-db",resourceType:"rds",primaryArn:t,secondaryArn:a,replicationEnabled:!0}],runbook:this.generateRDSRunbook(r,n),testSchedule:"0 0 1 * *"})}createDynamoDBDRPlan(e){let{tableArn:t,regions:a,rto:r=15,rpo:n=1}=e;return this.createDRPlan({name:"DynamoDB Global Tables DR",primaryRegion:a[0],secondaryRegion:a[1],rto:r,rpo:n,resources:[{resourceId:"dynamodb-table",resourceType:"dynamodb",primaryArn:t,replicationEnabled:!0}],runbook:this.generateDynamoDBRunbook(a)})}generateRDSRunbook(e,t){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 "+e,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 "+t,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(e){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(e,t=!1){let a=this.drPlans.get(e);if(!a)throw Error(`DR plan not found: ${e}`);let r=Date.now(),n=0;console.log(`${t?"[DRY RUN] ":""}Executing failover for plan: ${a.name}`),console.log(`Primary: ${a.primaryRegion} -> Secondary: ${a.secondaryRegion}`),console.log(`RTO: ${a.rto} minutes, RPO: ${a.rpo} minutes`),console.log("");for(let i of a.runbook.steps){if(console.log(`Step ${i.order}: ${i.name}`),console.log(` ${i.description}`),console.log(` Action: ${i.action}`),console.log(` Estimated: ${i.estimatedDuration} minutes`),t)console.log(" [SKIPPED - DRY RUN]");else if(i.automatable)console.log(" [AUTOMATED]");else console.log(" [MANUAL - WAITING]");n++,console.log("")}return{success:!0,duration:(Date.now()-r)/1000/60,completedSteps:n}}scheduleFailoverTest(e,t){let a={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:e,status:"scheduled",startTime:t};return this.failoverTests.set(a.id,a),a}async runFailoverTest(e){let t=this.drPlans.get(e);if(!t)throw Error(`DR plan not found: ${e}`);let a={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:e,status:"running",startTime:new Date,results:[]};this.failoverTests.set(a.id,a),console.log(`Running failover test for plan: ${t.name}`),console.log("This is a non-destructive test using test resources"),console.log("");for(let r of t.runbook.steps){let n=Date.now();console.log(`Testing step ${r.order}: ${r.name}`);let i={step:r.name,status:"success",duration:(Date.now()-n)/1000,message:`Successfully validated step ${r.order}`};a.results.push(i)}return a.status="completed",a.endTime=new Date,a}getDRPlan(e){return this.drPlans.get(e)}listDRPlans(){return Array.from(this.drPlans.values())}getFailoverTest(e){return this.failoverTests.get(e)}listFailoverTests(){return Array.from(this.failoverTests.values())}validateDRPlan(e){let t=[],a=[];if(e.rto<e.rpo)a.push("RTO cannot be less than RPO");if(e.rto>240)t.push("RTO exceeds 4 hours - consider improving recovery time");if(e.rpo>60)t.push("RPO exceeds 1 hour - consider more frequent backups");if(e.resources.length===0)a.push("No resources defined in DR plan");for(let i of e.resources){if(!i.replicationEnabled)t.push(`Resource ${i.resourceId} does not have replication enabled`);if(!i.secondaryArn&&i.resourceType!=="dynamodb")t.push(`Resource ${i.resourceId} does not have secondary resource defined`)}if(e.runbook.steps.length===0)a.push("No recovery steps defined in runbook");let r=e.runbook.steps.reduce((i,s)=>i+s.estimatedDuration,0);if(r>e.rto)t.push(`Estimated recovery duration (${r}m) exceeds RTO (${e.rto}m)`);let n=e.runbook.steps.filter((i)=>!i.automatable);if(n.length>0)t.push(`${n.length} manual steps in runbook - consider automation`);return{valid:a.length===0,warnings:t,errors:a}}clear(){this.drPlans.clear(),this.failoverTests.clear(),this.planCounter=0,this.testCounter=0}}var ym=new Ir;class Rr{configRules=new Map;configRecorders=new Map;deliveryChannels=new Map;ruleCounter=0;createConfigRecorder(e){return this.configRecorders.set(e.name,e),e}createDeliveryChannel(e){return this.deliveryChannels.set(e.name,e),e}createConfigRule(e){let t=`config-rule-${Date.now()}-${this.ruleCounter++}`,a={id:t,...e};return this.configRules.set(t,a),a}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(e=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:e},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(e){return this.createConfigRule({name:e.name,description:e.description,source:"CUSTOM_LAMBDA",lambdaFunctionArn:e.lambdaFunctionArn,scope:e.resourceTypes?{complianceResourceTypes:e.resourceTypes}:void 0,maxExecutionFrequency:e.maxExecutionFrequency,inputParameters:e.inputParameters})}createCompliancePreset(e){let t=[];switch(e){case"hipaa":t.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createRdsBackupRule(7),this.createVpcFlowLogsRule());break;case"pci-dss":t.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createIamMfaRule(),this.createRootAccountMfaRule(),this.createVpcFlowLogsRule());break;case"sox":t.push(this.createS3VersioningRule(),this.createCloudTrailEnabledRule(),this.createRdsBackupRule(30),this.createIamPasswordPolicyRule());break;case"gdpr":t.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createRdsSnapshotEncryptionRule());break;case"basic":t.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamMfaRule(),this.createRootAccountMfaRule());break}return t}getConfigRule(e){return this.configRules.get(e)}listConfigRules(){return Array.from(this.configRules.values())}getConfigRecorder(e){return this.configRecorders.get(e)}listConfigRecorders(){return Array.from(this.configRecorders.values())}getDeliveryChannel(e){return this.deliveryChannels.get(e)}listDeliveryChannels(){return Array.from(this.deliveryChannels.values())}generateConfigRuleCF(e){let t={Type:"AWS::Config::ConfigRule",Properties:{ConfigRuleName:e.name,Description:e.description,Source:{Owner:e.source==="AWS_MANAGED"?"AWS":"CUSTOM_LAMBDA"}}};if(e.source==="AWS_MANAGED"&&e.identifier)t.Properties.Source.SourceIdentifier=e.identifier;if(e.source==="CUSTOM_LAMBDA"&&e.lambdaFunctionArn)t.Properties.Source.SourceIdentifier=e.lambdaFunctionArn,t.Properties.Source.SourceDetails=[{EventSource:"aws.config",MessageType:"ConfigurationItemChangeNotification"}];if(e.inputParameters)t.Properties.InputParameters=JSON.stringify(e.inputParameters);if(e.scope){if(t.Properties.Scope={},e.scope.complianceResourceTypes)t.Properties.Scope.ComplianceResourceTypes=e.scope.complianceResourceTypes;if(e.scope.tagKey)t.Properties.Scope.TagKey=e.scope.tagKey;if(e.scope.tagValue)t.Properties.Scope.TagValue=e.scope.tagValue}if(e.maxExecutionFrequency)t.Properties.MaximumExecutionFrequency=e.maxExecutionFrequency;return t}generateConfigRecorderCF(e){return{Type:"AWS::Config::ConfigurationRecorder",Properties:{Name:e.name,RoleArn:e.roleArn,RecordingGroup:e.recordingGroup||{AllSupported:!0,IncludeGlobalResourceTypes:!0}}}}generateDeliveryChannelCF(e){return{Type:"AWS::Config::DeliveryChannel",Properties:{Name:e.name,S3BucketName:e.s3BucketName,...e.s3KeyPrefix&&{S3KeyPrefix:e.s3KeyPrefix},...e.snsTopicArn&&{SnsTopicARN:e.snsTopicArn},...e.configSnapshotDeliveryProperties&&{ConfigSnapshotDeliveryProperties:e.configSnapshotDeliveryProperties}}}}clear(){this.configRules.clear(),this.configRecorders.clear(),this.deliveryChannels.clear(),this.ruleCounter=0}}var fm=new Rr;class Nr{trails=new Map;trailCounter=0;createTrail(e){let t=`trail-${Date.now()}-${this.trailCounter++}`,a={id:t,...e};return this.trails.set(t,a),a}createOrganizationTrail(e){return this.createTrail({name:e.name,s3BucketName:e.s3BucketName,s3KeyPrefix:"organization-trail",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:e.kmsKeyId,cloudWatchLogsLogGroupArn:e.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:e.cloudWatchLogsRoleArn})}createSecurityAuditTrail(e){return this.createTrail({name:e.name,s3BucketName:e.s3BucketName,s3KeyPrefix:"security-audit",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:e.kmsKeyId,cloudWatchLogsLogGroupArn:e.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:e.cloudWatchLogsRoleArn,eventSelectors:[{readWriteType:"All",includeManagementEvents:!0,excludeManagementEventSources:[]}],insightSelectors:[{insightType:"ApiCallRateInsight"},{insightType:"ApiErrorRateInsight"}]})}createDataEventsTrail(e){let t=[];if(e.s3DataBuckets&&e.s3DataBuckets.length>0)t.push({type:"AWS::S3::Object",values:e.s3DataBuckets.map((a)=>`arn:aws:s3:::${a}/*`)});if(e.lambdaFunctions&&e.lambdaFunctions.length>0)t.push({type:"AWS::Lambda::Function",values:e.lambdaFunctions});return this.createTrail({name:e.name,s3BucketName:e.s3BucketName,s3KeyPrefix:"data-events",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"All",includeManagementEvents:!1,dataResources:t}]})}createAdvancedTrail(e){return this.createTrail({name:e.name,s3BucketName:e.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,advancedEventSelectors:e.selectors})}createReadOnlyTrail(e){return this.createTrail({name:e.name,s3BucketName:e.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"ReadOnly",includeManagementEvents:!0}]})}createWriteOnlyTrail(e){return this.createTrail({name:e.name,s3BucketName:e.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"WriteOnly",includeManagementEvents:!0}]})}getTrail(e){return this.trails.get(e)}listTrails(){return Array.from(this.trails.values())}generateTrailCF(e){let t={Type:"AWS::CloudTrail::Trail",Properties:{TrailName:e.name,S3BucketName:e.s3BucketName,IsLogging:!0,IncludeGlobalServiceEvents:e.includeGlobalServiceEvents??!0,IsMultiRegionTrail:e.isMultiRegionTrail??!0,EnableLogFileValidation:e.enableLogFileValidation??!0}};if(e.s3KeyPrefix)t.Properties.S3KeyPrefix=e.s3KeyPrefix;if(e.cloudWatchLogsLogGroupArn)t.Properties.CloudWatchLogsLogGroupArn=e.cloudWatchLogsLogGroupArn;if(e.cloudWatchLogsRoleArn)t.Properties.CloudWatchLogsRoleArn=e.cloudWatchLogsRoleArn;if(e.snsTopicName)t.Properties.SnsTopicName=e.snsTopicName;if(e.kmsKeyId)t.Properties.KMSKeyId=e.kmsKeyId;if(e.eventSelectors)t.Properties.EventSelectors=e.eventSelectors.map((a)=>({ReadWriteType:a.readWriteType,IncludeManagementEvents:a.includeManagementEvents??!0,...a.dataResources&&{DataResources:a.dataResources.map((r)=>({Type:r.type,Values:r.values}))},...a.excludeManagementEventSources&&{ExcludeManagementEventSources:a.excludeManagementEventSources}}));if(e.insightSelectors)t.Properties.InsightSelectors=e.insightSelectors.map((a)=>({InsightType:a.insightType}));if(e.advancedEventSelectors)t.Properties.AdvancedEventSelectors=e.advancedEventSelectors.map((a)=>({Name:a.name,FieldSelectors:a.fieldSelectors.map((r)=>({Field:r.field,...r.equals&&{Equals:r.equals},...r.startsWith&&{StartsWith:r.startsWith},...r.endsWith&&{EndsWith:r.endsWith},...r.notEquals&&{NotEquals:r.notEquals},...r.notStartsWith&&{NotStartsWith:r.notStartsWith},...r.notEndsWith&&{NotEndsWith:r.notEndsWith}}))}));return t}generateBucketPolicy(e,t){return{Version:"2012-10-17",Statement:[{Sid:"AWSCloudTrailAclCheck",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:GetBucketAcl",Resource:`arn:aws:s3:::${e}`},{Sid:"AWSCloudTrailWrite",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:PutObject",Resource:t.map((a)=>`arn:aws:s3:::${e}/AWSLogs/${a}/*`),Condition:{StringEquals:{"s3:x-amz-acl":"bucket-owner-full-control"}}}]}}clear(){this.trails.clear(),this.trailCounter=0}}var Sm=new Nr;class Dr{detectors=new Map;threatIntelSets=new Map;ipSets=new Map;filters=new Map;detectorCounter=0;threatIntelCounter=0;ipSetCounter=0;filterCounter=0;createDetector(e){let t=`detector-${Date.now()}-${this.detectorCounter++}`,a={id:t,...e};return this.detectors.set(t,a),a}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(e){let t=`threat-intel-${Date.now()}-${this.threatIntelCounter++}`,a={id:t,...e};return this.threatIntelSets.set(t,a),a}createIPSet(e){let t=`ip-set-${Date.now()}-${this.ipSetCounter++}`,a={id:t,...e};return this.ipSets.set(t,a),a}createFindingFilter(e){let t=`filter-${Date.now()}-${this.filterCounter++}`,a={id:t,...e};return this.filters.set(t,a),a}createLowSeverityArchiveFilter(e){return this.createFindingFilter({detectorId:e,name:"archive-low-severity",description:"Automatically archive low severity findings",action:"ARCHIVE",rank:1,findingCriteria:{criterion:{severity:{lt:4}}}})}createFindingTypeFilter(e,t,a){return this.createFindingFilter({detectorId:e,name:`filter-finding-types-${a.toLowerCase()}`,description:`${a==="ARCHIVE"?"Archive":"Keep"} specific finding types`,action:a,rank:2,findingCriteria:{criterion:{type:{eq:t}}}})}createTrustedIPFilter(e,t){return this.createFindingFilter({detectorId:e,name:"trusted-ip-addresses",description:"Archive findings from trusted IP addresses",action:"ARCHIVE",rank:3,findingCriteria:{criterion:{"resource.instanceDetails.networkInterfaces.privateIpAddress":{eq:t}}}})}getDetector(e){return this.detectors.get(e)}listDetectors(){return Array.from(this.detectors.values())}getThreatIntelSet(e){return this.threatIntelSets.get(e)}listThreatIntelSets(){return Array.from(this.threatIntelSets.values())}getIPSet(e){return this.ipSets.get(e)}listIPSets(){return Array.from(this.ipSets.values())}getFindingFilter(e){return this.filters.get(e)}listFindingFilters(){return Array.from(this.filters.values())}generateDetectorCF(e){let t={Type:"AWS::GuardDuty::Detector",Properties:{Enable:e.enable}};if(e.findingPublishingFrequency)t.Properties.FindingPublishingFrequency=e.findingPublishingFrequency;if(e.dataSources){if(t.Properties.DataSources={},e.dataSources.s3Logs)t.Properties.DataSources.S3Logs={Enable:e.dataSources.s3Logs.enable};if(e.dataSources.kubernetes)t.Properties.DataSources.Kubernetes={AuditLogs:{Enable:e.dataSources.kubernetes.auditLogs.enable}};if(e.dataSources.malwareProtection)t.Properties.DataSources.MalwareProtection={ScanEc2InstanceWithFindings:{EbsVolumes:{Enable:e.dataSources.malwareProtection.scanEc2InstanceWithFindings.ebsVolumes.enable}}}}if(e.features)t.Properties.Features=e.features.map((a)=>({Name:a.name,Status:a.status,...a.additionalConfiguration&&{AdditionalConfiguration:a.additionalConfiguration}}));return t}generateThreatIntelSetCF(e){return{Type:"AWS::GuardDuty::ThreatIntelSet",Properties:{DetectorId:e.detectorId,Name:e.name,Format:e.format,Location:e.location,Activate:e.activate}}}generateIPSetCF(e){return{Type:"AWS::GuardDuty::IPSet",Properties:{DetectorId:e.detectorId,Name:e.name,Format:e.format,Location:e.location,Activate:e.activate}}}generateFilterCF(e){return{Type:"AWS::GuardDuty::Filter",Properties:{DetectorId:e.detectorId,Name:e.name,Description:e.description,Action:e.action,Rank:e.rank,FindingCriteria:{Criterion:e.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 bm=new Dr;class xe{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(e){let t=`hub-${Date.now()}-${this.hubCounter++}`,a={id:t,...e};return this.hubs.set(t,a),a}createComprehensiveHub(){return this.createHub({enable:!0,controlFindingGenerator:"SECURITY_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...xe.Standards.AWS_FOUNDATIONAL_SECURITY,enabled:!0},{id:"cis-1-4",...xe.Standards.CIS_AWS_FOUNDATIONS_1_4,enabled:!0},{id:"pci-dss",...xe.Standards.PCI_DSS,enabled:!0}]})}createBasicHub(){return this.createHub({enable:!0,controlFindingGenerator:"STANDARD_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...xe.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(e){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:e.map((t)=>({value:t,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(e,t){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:`Suppress False Positives - ${e}`,description:`Automatically suppress known false positives from ${e}`,actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"SUPPRESSED"},note:{text:"Known false positive - automatically suppressed",updatedBy:"SecurityHub Automation"}}}],criteria:{productName:[{value:e,comparison:"EQUALS"}],title:t.map((a)=>({value:a,comparison:"PREFIX"}))},ruleStatus:"ENABLED",ruleOrder:10}}getHub(e){return this.hubs.get(e)}listHubs(){return Array.from(this.hubs.values())}generateHubCF(e){let t={Type:"AWS::SecurityHub::Hub",Properties:{}};if(e.controlFindingGenerator)t.Properties.ControlFindingGenerator=e.controlFindingGenerator;if(e.enableDefaultStandards!==void 0)t.Properties.EnableDefaultStandards=e.enableDefaultStandards;return t}generateStandardCF(e){let t={Type:"AWS::SecurityHub::Standard",Properties:{StandardsArn:e.arn}};if(e.disabledControls&&e.disabledControls.length>0)t.Properties.DisabledStandardsControls=e.disabledControls.map((a)=>({StandardsControlArn:a,Reason:"Disabled by configuration"}));return t}generateAutomationRuleCF(e){return{Type:"AWS::SecurityHub::AutomationRule",Properties:{RuleName:e.ruleName,Description:e.description,Actions:e.actions.map((t)=>({Type:t.type,FindingFieldsUpdate:t.findingFieldsUpdate})),Criteria:e.criteria,RuleStatus:e.ruleStatus,RuleOrder:e.ruleOrder}}}clear(){this.hubs.clear(),this.hubCounter=0,this.ruleCounter=0}}var Am=new xe;class kr{deployments=new Map;deploymentHistory=new Map;deploymentCounter=0;resultCounter=0;createDeployment(e){let t=`bg-deployment-${Date.now()}-${this.deploymentCounter++}`,a={id:t,...e};return this.deployments.set(t,a),a}createALBDeployment(e){return this.createDeployment({name:e.name,blueEnvironment:{name:"blue",targetGroupArn:e.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:e.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:e.listenerArn,switchoverTimeSeconds:0},autoPromote:e.autoPromote,healthCheckConfig:e.healthCheckConfig})}createRoute53Deployment(e){return this.createDeployment({name:e.name,blueEnvironment:{name:"blue",targetGroupArn:e.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:e.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"route53",hostedZoneId:e.hostedZoneId,switchoverTimeSeconds:e.switchoverTimeSeconds||60}})}createECSDeployment(e){return this.createDeployment({name:e.name,blueEnvironment:{name:"blue",targetGroupArn:e.blueTargetGroupArn,taskDefinitionArn:e.blueTaskDefinitionArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:e.greenTargetGroupArn,taskDefinitionArn:e.greenTaskDefinitionArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:e.listenerArn},autoRollback:e.autoRollback??!0})}async executeDeployment(e,t=!1){let a=this.deployments.get(e);if(!a)throw Error(`Deployment not found: ${e}`);let r={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!1,errors:[]};console.log(`${t?"[DRY RUN] ":""}Starting blue/green deployment: ${a.name}`),console.log(` Active environment: ${a.activeEnvironment}`),console.log(` Routing type: ${a.routingConfig.type}`);let n=a.activeEnvironment==="blue"?"green":"blue";if(console.log(` Switching to: ${n}`),console.log(`\\n1. Deploying to ${n} environment`),!t)await new Promise((i)=>setTimeout(i,100));if(console.log(`\\n2. Running health checks on ${n} environment`),a.healthCheckConfig){let i=await this.runHealthChecks(a,n,t);if(r.healthChecksPassed=i,!i){if(r.errors?.push("Health checks failed"),r.endTime=new Date,a.autoRollback)console.log(" Auto-rollback enabled - keeping current environment active"),r.rolledBackAt=new Date;return this.recordDeployment(e,r),r}}else r.healthChecksPassed=!0;if(console.log(`\\n3. Switching traffic to ${n} environment`),!t)a.activeEnvironment=n,r.switchedAt=new Date;if(console.log(`\\n4. Monitoring ${n} environment`),!t)await new Promise((i)=>setTimeout(i,100));return r.success=!0,r.endTime=new Date,console.log("\\n✓ Deployment completed successfully"),this.recordDeployment(e,r),r}async rollback(e){let t=this.deployments.get(e);if(!t)throw Error(`Deployment not found: ${e}`);let a={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!0,errors:[]};console.log(`Rolling back deployment: ${t.name}`);let r=t.activeEnvironment==="blue"?"green":"blue";return t.activeEnvironment=r,a.success=!0,a.rolledBackAt=new Date,a.endTime=new Date,console.log(` Switched back to: ${r}`),this.recordDeployment(e,a),a}async runHealthChecks(e,t,a){let r=e.healthCheckConfig;if(console.log(` Health check path: ${r.path||"/"}`),console.log(` Healthy threshold: ${r.healthyThreshold}`),console.log(` Interval: ${r.interval}s`),a)return console.log(" [SKIPPED - DRY RUN]"),!0;let n=0,i=r.healthyThreshold+2;for(let s=0;s<i;s++)if(await new Promise((o)=>setTimeout(o,50)),Math.random()>0.1){if(n++,console.log(` Check ${s+1}: ✓ Healthy (${n}/${r.healthyThreshold})`),n>=r.healthyThreshold)return!0}else n=0,console.log(` Check ${s+1}: ✗ Unhealthy`);return!1}recordDeployment(e,t){if(!this.deploymentHistory.has(e))this.deploymentHistory.set(e,[]);this.deploymentHistory.get(e).push(t)}getDeployment(e){return this.deployments.get(e)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(e){return this.deploymentHistory.get(e)||[]}generateALBListenerCF(e){let t=e.activeEnvironment==="blue"?e.blueEnvironment:e.greenEnvironment;return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:e.routingConfig.listenerArn,Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",TargetGroupArn:t.targetGroupArn}]}}}generateRoute53RecordSetCF(e,t){return[{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:e.routingConfig.hostedZoneId,Name:t,Type:"A",SetIdentifier:"blue",Weight:e.activeEnvironment==="blue"?100:0,AliasTarget:{HostedZoneId:e.routingConfig.hostedZoneId,DNSName:e.blueEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}},{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:e.routingConfig.hostedZoneId,Name:t,Type:"A",SetIdentifier:"green",Weight:e.activeEnvironment==="green"?100:0,AliasTarget:{HostedZoneId:e.routingConfig.hostedZoneId,DNSName:e.greenEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}}]}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var Cm=new kr;class Tt{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(e){let t=`canary-${Date.now()}-${this.deploymentCounter++}`,a={id:t,...e};return this.deployments.set(t,a),a}createLambdaCanaryDeployment(e){let t=e.strategy||"BALANCED",a=Tt.Strategies[t].map((r)=>({...r,alarmThresholds:{errorRate:e.errorRateThreshold||1,latencyP99:e.latencyThreshold||1000}}));return this.createDeployment({name:e.name,baselineVersion:{version:"baseline",functionVersionArn:e.baselineVersionArn,weight:100},canaryVersion:{version:"canary",functionVersionArn:e.canaryVersionArn,weight:0},stages:a,currentStage:0,status:"pending",autoPromote:e.autoPromote??!0,autoRollback:!0})}createECSCanaryDeployment(e){let t=e.strategy||"CONSERVATIVE",a=Tt.Strategies[t];return this.createDeployment({name:e.name,baselineVersion:{version:"baseline",taskDefinitionArn:e.baselineTaskDefinitionArn,targetGroupArn:e.baselineTargetGroupArn,weight:100},canaryVersion:{version:"canary",taskDefinitionArn:e.canaryTaskDefinitionArn,targetGroupArn:e.canaryTargetGroupArn,weight:0},stages:a,currentStage:0,status:"pending",autoRollback:!0})}async executeDeployment(e,t=!1){let a=this.deployments.get(e);if(!a)throw Error(`Deployment not found: ${e}`);let r={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,completedStages:0,rolledBack:!1};console.log(`${t?"[DRY RUN] ":""}Starting canary deployment: ${a.name}`),console.log(` Strategy: ${a.stages.length} stages`),console.log(` Auto-promote: ${a.autoPromote}`),console.log(` Auto-rollback: ${a.autoRollback}`),console.log(""),a.status="in_progress";for(let n=0;n<a.stages.length;n++){let i=a.stages[n];if(a.currentStage=n,console.log(`Stage ${n+1}/${a.stages.length}: ${i.name}`),console.log(` Traffic: ${i.trafficPercentage}% canary, ${100-i.trafficPercentage}% baseline`),console.log(` Duration: ${i.durationMinutes} minutes`),!t)a.baselineVersion.weight=100-i.trafficPercentage,a.canaryVersion.weight=i.trafficPercentage;if(!await this.monitorStage(a,i,t)){if(console.log(" ✗ Stage failed - metrics exceeded thresholds"),a.autoRollback)console.log("\\n Rolling back deployment..."),await this.rollback(e,t),r.rolledBack=!0,r.reason="Metrics exceeded thresholds";return r.endTime=new Date,a.status="rolled_back",this.recordDeployment(e,r),r}console.log(" ✓ Stage completed successfully"),r.completedStages++,console.log("")}return a.status="completed",r.success=!0,r.endTime=new Date,console.log("✓ Canary deployment completed successfully"),this.recordDeployment(e,r),r}async monitorStage(e,t,a){if(console.log(" Monitoring metrics..."),a)return console.log(" [SKIPPED - DRY RUN]"),!0;await new Promise((n)=>setTimeout(n,100));let r={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)*t.trafficPercentage/100)};if(e.metrics=r,console.log(` Baseline: ${r.baselineErrorRate.toFixed(2)}% errors, ${r.baselineLatencyP99.toFixed(0)}ms P99`),console.log(` Canary: ${r.canaryErrorRate.toFixed(2)}% errors, ${r.canaryLatencyP99.toFixed(0)}ms P99`),t.alarmThresholds){let{errorRate:n,latencyP99:i}=t.alarmThresholds;if(n&&r.canaryErrorRate>n)return console.log(` ⚠ Error rate exceeded threshold: ${r.canaryErrorRate.toFixed(2)}% > ${n}%`),!1;if(i&&r.canaryLatencyP99>i)return console.log(` ⚠ Latency P99 exceeded threshold: ${r.canaryLatencyP99.toFixed(0)}ms > ${i}ms`),!1}return!0}async rollback(e,t=!1){let a=this.deployments.get(e);if(!a)throw Error(`Deployment not found: ${e}`);if(console.log(`${t?"[DRY RUN] ":""}Rolling back canary deployment: ${a.name}`),!t)a.baselineVersion.weight=100,a.canaryVersion.weight=0,a.status="rolled_back";console.log(" Traffic restored to baseline: 100%")}promoteCanary(e){let t=this.deployments.get(e);if(!t)throw Error(`Deployment not found: ${e}`);console.log(`Promoting canary to baseline: ${t.name}`);let a=t.baselineVersion;t.baselineVersion=t.canaryVersion,t.canaryVersion=a,t.baselineVersion.weight=100,t.canaryVersion.weight=0,t.status="completed",console.log(" Canary promoted successfully")}recordDeployment(e,t){if(!this.deploymentHistory.has(e))this.deploymentHistory.set(e,[]);this.deploymentHistory.get(e).push(t)}getDeployment(e){return this.deployments.get(e)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(e){return this.deploymentHistory.get(e)||[]}generateLambdaAliasCF(e,t){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:{Ref:"LambdaFunction"},Name:t,FunctionVersion:e.canaryVersion.version,RoutingConfig:{AdditionalVersionWeights:[{FunctionVersion:e.baselineVersion.version,FunctionWeight:e.baselineVersion.weight/100}]}}}}generateALBListenerRuleCF(e){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:[{TargetGroupArn:e.baselineVersion.targetGroupArn,Weight:e.baselineVersion.weight},{TargetGroupArn:e.canaryVersion.targetGroupArn,Weight:e.canaryVersion.weight}],TargetGroupStickinessConfig:{Enabled:!1}}}]}}}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var Tm=new Tt;class Mr{tests=new Map;testCounter=0;createTest(e){let t=`abtest-${Date.now()}-${this.testCounter++}`,a={id:t,...e};return this.tests.set(t,a),a}createSimpleABTest(e){let t=e.variantTrafficPercentage||50;return this.createTest({name:e.name,description:e.description,variants:[{id:"control",name:"Control",description:"Original version",trafficPercentage:100-t,targetGroupArn:e.controlTargetGroupArn,weight:100-t},{id:"variant-a",name:"Variant A",description:"Test version",trafficPercentage:t,targetGroupArn:e.variantTargetGroupArn,weight:t}],routingStrategy:{type:e.stickySession?"cookie":"random",cookieName:e.stickySession?"ab_variant":void 0,stickySession:e.stickySession??!1,sessionDuration:1440},startTime:new Date,status:"draft"})}createMultivariateTest(e){let t=e.variants.reduce((a,r)=>a+r.trafficPercentage,0);if(t!==100)throw Error(`Traffic percentages must sum to 100, got ${t}`);return this.createTest({name:e.name,description:e.description,variants:e.variants.map((a,r)=>({id:`variant-${r}`,name:a.name,description:a.description,trafficPercentage:a.trafficPercentage,targetGroupArn:a.targetGroupArn,weight:a.trafficPercentage})),routingStrategy:e.routingStrategy||{type:"random",stickySession:!1},startTime:new Date,status:"draft"})}createHeaderBasedTest(e){return this.createTest({name:e.name,description:`Route based on ${e.headerName} header`,variants:[{id:"control",name:"Control",trafficPercentage:50,targetGroupArn:e.controlTargetGroupArn,weight:50},{id:"variant-a",name:"Variant A",trafficPercentage:50,targetGroupArn:e.variantTargetGroupArn,weight:50}],routingStrategy:{type:"header",headerName:e.headerName,stickySession:!1},startTime:new Date,status:"draft"})}createGeoBasedTest(e){return this.createTest({name:e.name,description:"Route based on geographic location",variants:[{id:"control",name:"Control (Rest of World)",trafficPercentage:50,targetGroupArn:e.controlTargetGroupArn,weight:50},{id:"variant-a",name:`Variant A (${e.regions.join(", ")})`,trafficPercentage:50,targetGroupArn:e.variantTargetGroupArn,weight:50}],routingStrategy:{type:"geo",stickySession:!0,sessionDuration:1440},startTime:new Date,status:"draft"})}startTest(e){let t=this.tests.get(e);if(!t)throw Error(`Test not found: ${e}`);if(t.status!=="draft"&&t.status!=="paused")throw Error(`Cannot start test in ${t.status} status`);t.status="active",t.startTime=new Date,console.log(`Started A/B test: ${t.name}`),console.log(` Variants: ${t.variants.length}`),t.variants.forEach((a)=>{console.log(` - ${a.name}: ${a.trafficPercentage}%`)})}pauseTest(e){let t=this.tests.get(e);if(!t)throw Error(`Test not found: ${e}`);t.status="paused",console.log(`Paused A/B test: ${t.name}`)}updateTrafficSplit(e,t,a){let r=this.tests.get(e);if(!r)throw Error(`Test not found: ${e}`);let n=r.variants.find((s)=>s.id===t);if(!n)throw Error(`Variant not found: ${t}`);let i=n.trafficPercentage;n.trafficPercentage=a,n.weight=a,console.log(`Updated ${n.name} traffic: ${i}% → ${a}%`)}analyzeResults(e){let t=this.tests.get(e);if(!t)throw Error(`Test not found: ${e}`);if(!t.metrics)t.metrics=this.collectMetrics(t);let a=t.variants[0],r=0;for(let l of t.variants){let u=t.metrics.variants[l.id];if(u&&u.conversionRate>r)r=u.conversionRate,a=l}let n=t.metrics.variants.control||t.metrics.variants[t.variants[0].id],i=t.metrics.variants[a.id],s=(i.conversionRate-n.conversionRate)/n.conversionRate*100,o=100,c=i.requests>o&&n.requests>o&&Math.abs(s)>10;return{testId:e,winningVariant:a.name,confidence:c?95:75,improvement:s,statisticalSignificance:c,metrics:t.metrics,recommendation:this.generateRecommendation(s,c,a.name)}}declareWinner(e,t){let a=this.tests.get(e);if(!a)throw Error(`Test not found: ${e}`);let r=a.variants.find((n)=>n.id===t);if(!r)throw Error(`Variant not found: ${t}`);a.variants.forEach((n)=>{if(n.id===t)n.trafficPercentage=100,n.weight=100;else n.trafficPercentage=0,n.weight=0}),a.status="completed",a.endTime=new Date,a.winner=t,console.log(`Declared winner: ${r.name}`),console.log(` All traffic now routed to ${r.name}`)}collectMetrics(e){let t={},a=0;for(let r of e.variants){let n=Math.floor(Math.random()*1000)+500,i=Math.floor(n*(Math.random()*0.1+0.05)),s=i/n*100;t[r.id]={requests:n,conversions:i,conversionRate:s,averageLatency:150+Math.random()*100,errorRate:Math.random()*0.5,revenue:i*(Math.random()*50+100)},a+=n}return{variants:t,totalRequests:a,startTime:e.startTime,lastUpdated:new Date}}generateRecommendation(e,t,a){if(!t)return"Continue test - sample size too small or no significant difference detected";if(e>20)return`Strong winner detected - ${a} shows ${e.toFixed(1)}% improvement. Recommend deploying to all traffic.`;if(e>10)return`Moderate improvement - ${a} shows ${e.toFixed(1)}% improvement. Consider deploying.`;if(e>0)return`Minor improvement - ${a} shows ${e.toFixed(1)}% improvement. May not be worth the complexity.`;return"No improvement detected - consider reverting to control variant"}getTest(e){return this.tests.get(e)}listTests(){return Array.from(this.tests.values())}generateALBListenerRuleCF(e){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:e.variants.map((t)=>({TargetGroupArn:t.targetGroupArn,Weight:t.weight})),TargetGroupStickinessConfig:{Enabled:e.routingStrategy.stickySession||!1,DurationSeconds:e.routingStrategy.sessionDuration?e.routingStrategy.sessionDuration*60:void 0}}}]}}}generateLambdaEdgeFunction(e){return`'use strict';
3611
3611
 
3612
3612
  exports.handler = (event, _context, _callback) => {
3613
3613
  const request = event.Records[0].cf.request;
@@ -3631,9 +3631,9 @@ exports.handler = (event, _context, _callback) => {
3631
3631
  const random = Math.random() * 100;
3632
3632
  const _cumulative = 0;
3633
3633
 
3634
- ${e.variants.map((t,a)=>`if (random < ${t.trafficPercentage+(a>0?e.variants.slice(0,a).reduce((r,n)=>r+n.trafficPercentage,0):0)}) {
3634
+ ${e.variants.map((t,a)=>{return`if (random < ${t.trafficPercentage+(a>0?e.variants.slice(0,a).reduce((r,n)=>r+n.trafficPercentage,0):0)}) {
3635
3635
  variant = '${t.id}';
3636
- }`).join(" else ")}
3636
+ }`}).join(" else ")}
3637
3637
  }
3638
3638
 
3639
3639
  // Set variant cookie
@@ -3654,7 +3654,7 @@ exports.handler = (event, _context, _callback) => {
3654
3654
  }`).join(" else ")}
3655
3655
 
3656
3656
  callback(null, request);
3657
- };`}clear(){this.tests.clear(),this.testCounter=0}}var wm=new Lr;class Mr{rollouts=new Map;flags=new Map;gates=new Map;counter=0;createProgressiveRollout(e,t){let a=`rollout-${Date.now()}-${this.counter++}`,r={id:a,name:e,stages:t,currentStage:0};return this.rollouts.set(a,r),r}createFeatureFlag(e,t=0){let a=`flag-${Date.now()}-${this.counter++}`,r={id:a,name:e,enabled:!1,rolloutPercentage:t,targetingRules:[]};return this.flags.set(a,r),r}createDeploymentGate(e,t,a,r){let n=`gate-${Date.now()}-${this.counter++}`,i={id:n,name:e,type:t,approvers:a,conditions:r};return this.gates.set(n,i),i}clear(){this.rollouts.clear(),this.flags.clear(),this.gates.clear()}}var Em=new Mr;class xr{configs=new Map;samplingRules=new Map;configCounter=0;ruleCounter=0;createConfig(e){let t=`xray-config-${Date.now()}-${this.configCounter++}`,a={id:t,...e};return this.configs.set(t,a),a}createLambdaConfig(e){return this.createConfig({name:`${e.functionName}-xray`,serviceName:e.functionName,samplingRate:e.samplingRate||0.1,enableActiveTracing:!0})}createECSConfig(e){return this.createConfig({name:`${e.serviceName}-xray`,serviceName:`${e.clusterName}/${e.serviceName}`,samplingRate:e.samplingRate||0.05,enableActiveTracing:!0})}createAPIGatewayConfig(e){return this.createConfig({name:`${e.apiName}-${e.stage}-xray`,serviceName:`${e.apiName}/${e.stage}`,samplingRate:e.samplingRate||0.05,enableActiveTracing:!0})}createSamplingRule(e){let t=`sampling-rule-${Date.now()}-${this.ruleCounter++}`,a={id:t,...e};return this.samplingRules.set(t,a),a}createHighPrioritySamplingRule(e){return this.createSamplingRule({ruleName:e.ruleName,priority:100,fixedRate:1,reservoirSize:100,serviceName:e.serviceName,serviceType:"*",host:"*",httpMethod:"*",urlPath:e.urlPath,version:1})}createErrorSamplingRule(e){return this.createSamplingRule({ruleName:`${e}-errors`,priority:200,fixedRate:1,reservoirSize:50,serviceName:e,serviceType:"*",host:"*",httpMethod:"*",urlPath:"/error/*",version:1})}createDefaultSamplingRule(e,t=0.05){return this.createSamplingRule({ruleName:`${e}-default`,priority:1000,fixedRate:t,reservoirSize:10,serviceName:e,serviceType:"*",host:"*",httpMethod:"*",urlPath:"*",version:1})}getConfig(e){return this.configs.get(e)}listConfigs(){return Array.from(this.configs.values())}getSamplingRule(e){return this.samplingRules.get(e)}listSamplingRules(){return Array.from(this.samplingRules.values())}generateLambdaXRayCF(e){return{TracingConfig:{Mode:e.enableActiveTracing?"Active":"PassThrough"}}}generateAPIGatewayXRayCF(e){return{TracingEnabled:e.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(e){return{Type:"AWS::XRay::SamplingRule",Properties:{SamplingRule:{RuleName:e.ruleName,Priority:e.priority,FixedRate:e.fixedRate,ReservoirSize:e.reservoirSize,ServiceName:e.serviceName,ServiceType:e.serviceType,Host:e.host,HTTPMethod:e.httpMethod,URLPath:e.urlPath,Version:e.version,ResourceARN:"*"}}}}createTrace(e,t){return{id:`trace-${Date.now()}-${this.configCounter++}`,traceId:e,spans:t}}clear(){this.configs.clear(),this.samplingRules.clear(),this.configCounter=0,this.ruleCounter=0}}var Pm=new xr;class Or{namespaces=new Map;metrics=new Map;namespaceCounter=0;metricCounter=0;alarmCounter=0;createNamespace(e){let t=`namespace-${Date.now()}-${this.namespaceCounter++}`,a={id:t,...e};return this.namespaces.set(t,a),a}createMetric(e){let t=`metric-${Date.now()}-${this.metricCounter++}`,a={id:t,...e};return this.metrics.set(t,a),a}createBusinessMetric(e){return this.createMetric({name:e.name,namespace:e.namespace,unit:e.unit,dimensions:[{name:"Environment",value:"production"},{name:"Type",value:"Business"}]})}createApplicationMetric(e){return this.createMetric({name:e.name,namespace:e.namespace,unit:e.unit,dimensions:[{name:"Service",value:e.serviceName},{name:"Type",value:"Application"}]})}createPerformanceMetric(e){return this.createMetric({name:e.name,namespace:e.namespace,unit:"Milliseconds",dimensions:[{name:"Operation",value:e.operation},{name:"Type",value:"Performance"}]})}createErrorMetric(e){return this.createMetric({name:e.name,namespace:e.namespace,unit:"Count",dimensions:[{name:"ErrorType",value:e.errorType},{name:"Type",value:"Error"}]})}createAlarm(e,t){let a=this.metrics.get(e);if(!a)throw Error(`Metric not found: ${e}`);let r={id:`alarm-${Date.now()}-${this.alarmCounter++}`,...t};if(!a.alarms)a.alarms=[];return a.alarms.push(r),r}createErrorRateAlarm(e){return this.createAlarm(e.metricId,{name:e.name,description:`Alert when error rate exceeds ${e.threshold} errors/min`,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:2,threshold:e.threshold,period:60,statistic:"Sum",treatMissingData:"notBreaching",actionsEnabled:!0,alarmActions:e.snsTopicArn?[e.snsTopicArn]:void 0})}createLatencyAlarm(e){return this.createAlarm(e.metricId,{name:e.name,description:`Alert when latency exceeds ${e.thresholdMs}ms`,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,threshold:e.thresholdMs,period:300,statistic:"Average",treatMissingData:"notBreaching",actionsEnabled:!0,alarmActions:e.snsTopicArn?[e.snsTopicArn]:void 0})}createThroughputAlarm(e){return this.createAlarm(e.metricId,{name:e.name,description:`Alert when throughput drops below ${e.minimumThreshold}`,comparisonOperator:"LessThanThreshold",evaluationPeriods:2,threshold:e.minimumThreshold,period:300,statistic:"Sum",treatMissingData:"breaching",actionsEnabled:!0,alarmActions:e.snsTopicArn?[e.snsTopicArn]:void 0})}createCompositeAlarm(e){return{name:e.name,description:e.description,alarmRule:e.alarmRule,actionsEnabled:e.actionsEnabled??!0,alarmActions:e.alarmActions}}getNamespace(e){return this.namespaces.get(e)}listNamespaces(){return Array.from(this.namespaces.values())}getMetric(e){return this.metrics.get(e)}listMetrics(){return Array.from(this.metrics.values())}generateAlarmCF(e,t){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:t.name,AlarmDescription:t.description,ComparisonOperator:t.comparisonOperator,EvaluationPeriods:t.evaluationPeriods,MetricName:e.name,Namespace:e.namespace,Period:t.period,Statistic:t.statistic,Threshold:t.threshold,TreatMissingData:t.treatMissingData||"notBreaching",ActionsEnabled:t.actionsEnabled??!0,...t.alarmActions&&{AlarmActions:t.alarmActions},...t.okActions&&{OKActions:t.okActions},...t.insufficientDataActions&&{InsufficientDataActions:t.insufficientDataActions},...e.dimensions&&{Dimensions:e.dimensions.map((a)=>({Name:a.name,Value:a.value}))}}}}generateCompositeAlarmCF(e){return{Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:e.name,AlarmDescription:e.description,AlarmRule:e.alarmRule,ActionsEnabled:e.actionsEnabled,...e.alarmActions&&{AlarmActions:e.alarmActions}}}}generateDashboardWidget(e){return{type:"metric",properties:{metrics:[[e.namespace,e.name,...e.dimensions?.flatMap((t)=>[t.name,t.value])||[]]],period:300,stat:"Average",region:"us-east-1",title:e.name}}}publishCustomMetric(e,t,a,r={},n="Count"){return{id:`metric-${Date.now()}-${this.metricCounter++}`,namespace:e,name:t,dimensions:r,value:a,unit:n,timestamp:new Date}}clear(){this.namespaces.clear(),this.metrics.clear(),this.namespaceCounter=0,this.metricCounter=0,this.alarmCounter=0}}var Im=new Or;class Br{logGroups=new Map;queries=new Map;insightsQueries=new Map;logGroupCounter=0;filterCounter=0;queryCounter=0;createLogGroup(e){let t=`log-group-${Date.now()}-${this.logGroupCounter++}`,a={id:t,...e};return this.logGroups.set(t,a),a}createLambdaLogGroup(e,t=7){return this.createLogGroup({name:`/aws/lambda/${e}`,retentionDays:t})}createECSLogGroup(e){return this.createLogGroup({name:`/ecs/${e.clusterName}/${e.serviceName}`,retentionDays:e.retentionDays||14})}createAPIGatewayLogGroup(e,t,a=30){return this.createLogGroup({name:`/aws/apigateway/${e}/${t}`,retentionDays:a})}createApplicationLogGroup(e){return this.createLogGroup({name:`/application/${e.appName}/${e.environment}`,retentionDays:e.retentionDays||30,kmsKeyId:e.kmsKeyId})}createMetricFilter(e,t){let a=this.logGroups.get(e);if(!a)throw Error(`Log group not found: ${e}`);let r={id:`filter-${Date.now()}-${this.filterCounter++}`,...t};if(!a.metricFilters)a.metricFilters=[];return a.metricFilters.push(r),r}createErrorCountFilter(e,t){return this.createMetricFilter(e,{name:"ErrorCount",filterPattern:"[timestamp, request_id, level = ERROR*, ...]",metricTransformations:[{metricName:"ErrorCount",metricNamespace:t,metricValue:"1",defaultValue:0,unit:"Count"}]})}createLatencyFilter(e,t){return this.createMetricFilter(e,{name:"Latency",filterPattern:"[timestamp, request_id, level, duration, ...]",metricTransformations:[{metricName:"ResponseTime",metricNamespace:t,metricValue:"$duration",unit:"Milliseconds"}]})}createCustomPatternFilter(e){return this.createMetricFilter(e.logGroupId,{name:e.name,filterPattern:e.pattern,metricTransformations:[{metricName:e.metricName,metricNamespace:e.namespace,metricValue:"1",defaultValue:0,unit:"Count"}]})}createSubscriptionFilter(e,t){let a=this.logGroups.get(e);if(!a)throw Error(`Log group not found: ${e}`);let r={id:`subscription-${Date.now()}-${this.filterCounter++}`,...t};if(!a.subscriptionFilters)a.subscriptionFilters=[];return a.subscriptionFilters.push(r),r}createKinesisSubscription(e){let t=this.logGroups.get(e.logGroupId);if(!t)throw Error(`Log group not found: ${e.logGroupId}`);return this.createSubscriptionFilter(e.logGroupId,{name:"KinesisSubscription",logGroupName:t.name,filterPattern:e.filterPattern||"",destinationArn:e.kinesisStreamArn,roleArn:e.roleArn,distribution:"Random"})}createLambdaSubscription(e){let t=this.logGroups.get(e.logGroupId);if(!t)throw Error(`Log group not found: ${e.logGroupId}`);return this.createSubscriptionFilter(e.logGroupId,{name:"LambdaSubscription",logGroupName:t.name,filterPattern:e.filterPattern||"",destinationArn:e.lambdaFunctionArn,distribution:"ByLogStream"})}createInsightsQuery(e){let t=`query-${Date.now()}-${this.queryCounter++}`,a={id:t,...e};return this.insightsQueries.set(t,a),a}createErrorAnalysisQuery(e){return this.createInsightsQuery({name:"Error Analysis",description:"Analyze error patterns and frequencies",query:`fields @timestamp, @message
3657
+ };`}clear(){this.tests.clear(),this.testCounter=0}}var vm=new Mr;class Lr{rollouts=new Map;flags=new Map;gates=new Map;counter=0;createProgressiveRollout(e,t){let a=`rollout-${Date.now()}-${this.counter++}`,r={id:a,name:e,stages:t,currentStage:0};return this.rollouts.set(a,r),r}createFeatureFlag(e,t=0){let a=`flag-${Date.now()}-${this.counter++}`,r={id:a,name:e,enabled:!1,rolloutPercentage:t,targetingRules:[]};return this.flags.set(a,r),r}createDeploymentGate(e,t,a,r){let n=`gate-${Date.now()}-${this.counter++}`,i={id:n,name:e,type:t,approvers:a,conditions:r};return this.gates.set(n,i),i}clear(){this.rollouts.clear(),this.flags.clear(),this.gates.clear()}}var wm=new Lr;class xr{configs=new Map;samplingRules=new Map;configCounter=0;ruleCounter=0;createConfig(e){let t=`xray-config-${Date.now()}-${this.configCounter++}`,a={id:t,...e};return this.configs.set(t,a),a}createLambdaConfig(e){return this.createConfig({name:`${e.functionName}-xray`,serviceName:e.functionName,samplingRate:e.samplingRate||0.1,enableActiveTracing:!0})}createECSConfig(e){return this.createConfig({name:`${e.serviceName}-xray`,serviceName:`${e.clusterName}/${e.serviceName}`,samplingRate:e.samplingRate||0.05,enableActiveTracing:!0})}createAPIGatewayConfig(e){return this.createConfig({name:`${e.apiName}-${e.stage}-xray`,serviceName:`${e.apiName}/${e.stage}`,samplingRate:e.samplingRate||0.05,enableActiveTracing:!0})}createSamplingRule(e){let t=`sampling-rule-${Date.now()}-${this.ruleCounter++}`,a={id:t,...e};return this.samplingRules.set(t,a),a}createHighPrioritySamplingRule(e){return this.createSamplingRule({ruleName:e.ruleName,priority:100,fixedRate:1,reservoirSize:100,serviceName:e.serviceName,serviceType:"*",host:"*",httpMethod:"*",urlPath:e.urlPath,version:1})}createErrorSamplingRule(e){return this.createSamplingRule({ruleName:`${e}-errors`,priority:200,fixedRate:1,reservoirSize:50,serviceName:e,serviceType:"*",host:"*",httpMethod:"*",urlPath:"/error/*",version:1})}createDefaultSamplingRule(e,t=0.05){return this.createSamplingRule({ruleName:`${e}-default`,priority:1000,fixedRate:t,reservoirSize:10,serviceName:e,serviceType:"*",host:"*",httpMethod:"*",urlPath:"*",version:1})}getConfig(e){return this.configs.get(e)}listConfigs(){return Array.from(this.configs.values())}getSamplingRule(e){return this.samplingRules.get(e)}listSamplingRules(){return Array.from(this.samplingRules.values())}generateLambdaXRayCF(e){return{TracingConfig:{Mode:e.enableActiveTracing?"Active":"PassThrough"}}}generateAPIGatewayXRayCF(e){return{TracingEnabled:e.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(e){return{Type:"AWS::XRay::SamplingRule",Properties:{SamplingRule:{RuleName:e.ruleName,Priority:e.priority,FixedRate:e.fixedRate,ReservoirSize:e.reservoirSize,ServiceName:e.serviceName,ServiceType:e.serviceType,Host:e.host,HTTPMethod:e.httpMethod,URLPath:e.urlPath,Version:e.version,ResourceARN:"*"}}}}createTrace(e,t){return{id:`trace-${Date.now()}-${this.configCounter++}`,traceId:e,spans:t}}clear(){this.configs.clear(),this.samplingRules.clear(),this.configCounter=0,this.ruleCounter=0}}var Em=new xr;class Or{namespaces=new Map;metrics=new Map;namespaceCounter=0;metricCounter=0;alarmCounter=0;createNamespace(e){let t=`namespace-${Date.now()}-${this.namespaceCounter++}`,a={id:t,...e};return this.namespaces.set(t,a),a}createMetric(e){let t=`metric-${Date.now()}-${this.metricCounter++}`,a={id:t,...e};return this.metrics.set(t,a),a}createBusinessMetric(e){return this.createMetric({name:e.name,namespace:e.namespace,unit:e.unit,dimensions:[{name:"Environment",value:"production"},{name:"Type",value:"Business"}]})}createApplicationMetric(e){return this.createMetric({name:e.name,namespace:e.namespace,unit:e.unit,dimensions:[{name:"Service",value:e.serviceName},{name:"Type",value:"Application"}]})}createPerformanceMetric(e){return this.createMetric({name:e.name,namespace:e.namespace,unit:"Milliseconds",dimensions:[{name:"Operation",value:e.operation},{name:"Type",value:"Performance"}]})}createErrorMetric(e){return this.createMetric({name:e.name,namespace:e.namespace,unit:"Count",dimensions:[{name:"ErrorType",value:e.errorType},{name:"Type",value:"Error"}]})}createAlarm(e,t){let a=this.metrics.get(e);if(!a)throw Error(`Metric not found: ${e}`);let r={id:`alarm-${Date.now()}-${this.alarmCounter++}`,...t};if(!a.alarms)a.alarms=[];return a.alarms.push(r),r}createErrorRateAlarm(e){return this.createAlarm(e.metricId,{name:e.name,description:`Alert when error rate exceeds ${e.threshold} errors/min`,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:2,threshold:e.threshold,period:60,statistic:"Sum",treatMissingData:"notBreaching",actionsEnabled:!0,alarmActions:e.snsTopicArn?[e.snsTopicArn]:void 0})}createLatencyAlarm(e){return this.createAlarm(e.metricId,{name:e.name,description:`Alert when latency exceeds ${e.thresholdMs}ms`,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,threshold:e.thresholdMs,period:300,statistic:"Average",treatMissingData:"notBreaching",actionsEnabled:!0,alarmActions:e.snsTopicArn?[e.snsTopicArn]:void 0})}createThroughputAlarm(e){return this.createAlarm(e.metricId,{name:e.name,description:`Alert when throughput drops below ${e.minimumThreshold}`,comparisonOperator:"LessThanThreshold",evaluationPeriods:2,threshold:e.minimumThreshold,period:300,statistic:"Sum",treatMissingData:"breaching",actionsEnabled:!0,alarmActions:e.snsTopicArn?[e.snsTopicArn]:void 0})}createCompositeAlarm(e){return{name:e.name,description:e.description,alarmRule:e.alarmRule,actionsEnabled:e.actionsEnabled??!0,alarmActions:e.alarmActions}}getNamespace(e){return this.namespaces.get(e)}listNamespaces(){return Array.from(this.namespaces.values())}getMetric(e){return this.metrics.get(e)}listMetrics(){return Array.from(this.metrics.values())}generateAlarmCF(e,t){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:t.name,AlarmDescription:t.description,ComparisonOperator:t.comparisonOperator,EvaluationPeriods:t.evaluationPeriods,MetricName:e.name,Namespace:e.namespace,Period:t.period,Statistic:t.statistic,Threshold:t.threshold,TreatMissingData:t.treatMissingData||"notBreaching",ActionsEnabled:t.actionsEnabled??!0,...t.alarmActions&&{AlarmActions:t.alarmActions},...t.okActions&&{OKActions:t.okActions},...t.insufficientDataActions&&{InsufficientDataActions:t.insufficientDataActions},...e.dimensions&&{Dimensions:e.dimensions.map((a)=>({Name:a.name,Value:a.value}))}}}}generateCompositeAlarmCF(e){return{Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:e.name,AlarmDescription:e.description,AlarmRule:e.alarmRule,ActionsEnabled:e.actionsEnabled,...e.alarmActions&&{AlarmActions:e.alarmActions}}}}generateDashboardWidget(e){return{type:"metric",properties:{metrics:[[e.namespace,e.name,...e.dimensions?.flatMap((t)=>[t.name,t.value])||[]]],period:300,stat:"Average",region:"us-east-1",title:e.name}}}publishCustomMetric(e,t,a,r={},n="Count"){return{id:`metric-${Date.now()}-${this.metricCounter++}`,namespace:e,name:t,dimensions:r,value:a,unit:n,timestamp:new Date}}clear(){this.namespaces.clear(),this.metrics.clear(),this.namespaceCounter=0,this.metricCounter=0,this.alarmCounter=0}}var Pm=new Or;class Wr{logGroups=new Map;queries=new Map;insightsQueries=new Map;logGroupCounter=0;filterCounter=0;queryCounter=0;createLogGroup(e){let t=`log-group-${Date.now()}-${this.logGroupCounter++}`,a={id:t,...e};return this.logGroups.set(t,a),a}createLambdaLogGroup(e,t=7){return this.createLogGroup({name:`/aws/lambda/${e}`,retentionDays:t})}createECSLogGroup(e){return this.createLogGroup({name:`/ecs/${e.clusterName}/${e.serviceName}`,retentionDays:e.retentionDays||14})}createAPIGatewayLogGroup(e,t,a=30){return this.createLogGroup({name:`/aws/apigateway/${e}/${t}`,retentionDays:a})}createApplicationLogGroup(e){return this.createLogGroup({name:`/application/${e.appName}/${e.environment}`,retentionDays:e.retentionDays||30,kmsKeyId:e.kmsKeyId})}createMetricFilter(e,t){let a=this.logGroups.get(e);if(!a)throw Error(`Log group not found: ${e}`);let r={id:`filter-${Date.now()}-${this.filterCounter++}`,...t};if(!a.metricFilters)a.metricFilters=[];return a.metricFilters.push(r),r}createErrorCountFilter(e,t){return this.createMetricFilter(e,{name:"ErrorCount",filterPattern:"[timestamp, request_id, level = ERROR*, ...]",metricTransformations:[{metricName:"ErrorCount",metricNamespace:t,metricValue:"1",defaultValue:0,unit:"Count"}]})}createLatencyFilter(e,t){return this.createMetricFilter(e,{name:"Latency",filterPattern:"[timestamp, request_id, level, duration, ...]",metricTransformations:[{metricName:"ResponseTime",metricNamespace:t,metricValue:"$duration",unit:"Milliseconds"}]})}createCustomPatternFilter(e){return this.createMetricFilter(e.logGroupId,{name:e.name,filterPattern:e.pattern,metricTransformations:[{metricName:e.metricName,metricNamespace:e.namespace,metricValue:"1",defaultValue:0,unit:"Count"}]})}createSubscriptionFilter(e,t){let a=this.logGroups.get(e);if(!a)throw Error(`Log group not found: ${e}`);let r={id:`subscription-${Date.now()}-${this.filterCounter++}`,...t};if(!a.subscriptionFilters)a.subscriptionFilters=[];return a.subscriptionFilters.push(r),r}createKinesisSubscription(e){let t=this.logGroups.get(e.logGroupId);if(!t)throw Error(`Log group not found: ${e.logGroupId}`);return this.createSubscriptionFilter(e.logGroupId,{name:"KinesisSubscription",logGroupName:t.name,filterPattern:e.filterPattern||"",destinationArn:e.kinesisStreamArn,roleArn:e.roleArn,distribution:"Random"})}createLambdaSubscription(e){let t=this.logGroups.get(e.logGroupId);if(!t)throw Error(`Log group not found: ${e.logGroupId}`);return this.createSubscriptionFilter(e.logGroupId,{name:"LambdaSubscription",logGroupName:t.name,filterPattern:e.filterPattern||"",destinationArn:e.lambdaFunctionArn,distribution:"ByLogStream"})}createInsightsQuery(e){let t=`query-${Date.now()}-${this.queryCounter++}`,a={id:t,...e};return this.insightsQueries.set(t,a),a}createErrorAnalysisQuery(e){return this.createInsightsQuery({name:"Error Analysis",description:"Analyze error patterns and frequencies",query:`fields @timestamp, @message
3658
3658
  | filter @message like /ERROR/
3659
3659
  | stats count() by bin(5m)
3660
3660
  | sort @timestamp desc`,logGroupNames:e})}createLatencyAnalysisQuery(e){return this.createInsightsQuery({name:"Latency Analysis",description:"Analyze request latency patterns",query:`fields @timestamp, @duration
@@ -3664,7 +3664,7 @@ exports.handler = (event, _context, _callback) => {
3664
3664
  | filter @message like /ERROR/
3665
3665
  | stats count() as error_count by @message
3666
3666
  | sort error_count desc
3667
- | limit 20`,logGroupNames:e})}getLogGroup(e){return this.logGroups.get(e)}listLogGroups(){return Array.from(this.logGroups.values())}getInsightsQuery(e){return this.insightsQueries.get(e)}listInsightsQueries(){return Array.from(this.insightsQueries.values())}generateLogGroupCF(e){return{Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:e.name,...e.retentionDays&&{RetentionInDays:e.retentionDays},...e.kmsKeyId&&{KmsKeyId:e.kmsKeyId}}}}generateMetricFilterCF(e,t){return{Type:"AWS::Logs::MetricFilter",Properties:{FilterName:t.name,FilterPattern:t.filterPattern,LogGroupName:e.name,MetricTransformations:t.metricTransformations.map((a)=>({MetricName:a.metricName,MetricNamespace:a.metricNamespace,MetricValue:a.metricValue,...a.defaultValue!==void 0&&{DefaultValue:a.defaultValue},...a.unit&&{Unit:a.unit},...a.dimensions&&{Dimensions:a.dimensions}}))}}}generateSubscriptionFilterCF(e){return{Type:"AWS::Logs::SubscriptionFilter",Properties:{FilterName:e.name,FilterPattern:e.filterPattern,LogGroupName:e.logGroupName,DestinationArn:e.destinationArn,...e.roleArn&&{RoleArn:e.roleArn},...e.distribution&&{Distribution:e.distribution}}}}generateQueryDefinitionCF(e){return{Type:"AWS::Logs::QueryDefinition",Properties:{Name:e.name,QueryString:e.query,LogGroupNames:e.logGroupNames}}}createLogAggregation(e,t,a=7){let r=`aggregation-${Date.now()}-${this.logGroupCounter++}`,n=this.createLogGroup({name:e,retentionDays:a});return t.forEach((i)=>{this.createMetricFilter(n.id,{name:i.metric,filterPattern:i.pattern,metricTransformations:[{metricName:i.metric,metricNamespace:"CustomMetrics",metricValue:"1",defaultValue:0,unit:"Count"}]})}),{id:r,logGroup:e,filters:t,retention:a}}clear(){this.logGroups.clear(),this.queries.clear(),this.insightsQueries.clear(),this.logGroupCounter=0,this.filterCounter=0,this.queryCounter=0}}var Rm=new Br;class Oe{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(e){let t=`canary-${Date.now()}-${this.canaryCounter++}`,a={id:t,...e};return this.canaries.set(t,a),a}createHeartbeatCanary(e){let t=`
3667
+ | limit 20`,logGroupNames:e})}getLogGroup(e){return this.logGroups.get(e)}listLogGroups(){return Array.from(this.logGroups.values())}getInsightsQuery(e){return this.insightsQueries.get(e)}listInsightsQueries(){return Array.from(this.insightsQueries.values())}generateLogGroupCF(e){return{Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:e.name,...e.retentionDays&&{RetentionInDays:e.retentionDays},...e.kmsKeyId&&{KmsKeyId:e.kmsKeyId}}}}generateMetricFilterCF(e,t){return{Type:"AWS::Logs::MetricFilter",Properties:{FilterName:t.name,FilterPattern:t.filterPattern,LogGroupName:e.name,MetricTransformations:t.metricTransformations.map((a)=>({MetricName:a.metricName,MetricNamespace:a.metricNamespace,MetricValue:a.metricValue,...a.defaultValue!==void 0&&{DefaultValue:a.defaultValue},...a.unit&&{Unit:a.unit},...a.dimensions&&{Dimensions:a.dimensions}}))}}}generateSubscriptionFilterCF(e){return{Type:"AWS::Logs::SubscriptionFilter",Properties:{FilterName:e.name,FilterPattern:e.filterPattern,LogGroupName:e.logGroupName,DestinationArn:e.destinationArn,...e.roleArn&&{RoleArn:e.roleArn},...e.distribution&&{Distribution:e.distribution}}}}generateQueryDefinitionCF(e){return{Type:"AWS::Logs::QueryDefinition",Properties:{Name:e.name,QueryString:e.query,LogGroupNames:e.logGroupNames}}}createLogAggregation(e,t,a=7){let r=`aggregation-${Date.now()}-${this.logGroupCounter++}`,n=this.createLogGroup({name:e,retentionDays:a});return t.forEach((i)=>{this.createMetricFilter(n.id,{name:i.metric,filterPattern:i.pattern,metricTransformations:[{metricName:i.metric,metricNamespace:"CustomMetrics",metricValue:"1",defaultValue:0,unit:"Count"}]})}),{id:r,logGroup:e,filters:t,retention:a}}clear(){this.logGroups.clear(),this.queries.clear(),this.insightsQueries.clear(),this.logGroupCounter=0,this.filterCounter=0,this.queryCounter=0}}var Im=new Wr;class Oe{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(e){let t=`canary-${Date.now()}-${this.canaryCounter++}`,a={id:t,...e};return this.canaries.set(t,a),a}createHeartbeatCanary(e){let t=`
3668
3668
  const synthetics = require('Synthetics');
3669
3669
  const log = require('SyntheticsLogger');
3670
3670
 
@@ -3755,35 +3755,35 @@ const workflowCheck = async function () {
3755
3755
  exports.handler = async () => {
3756
3756
  return await workflowCheck();
3757
3757
  };
3758
- `;return this.createCanary({name:e.name,description:e.description,runtimeVersion:Oe.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:t},schedule:{expression:`rate(${e.interval} minutes)`},runConfig:{timeoutInSeconds:180,memoryInMB:1024,activeTracing:!0},artifactS3Location:`s3://${e.s3Bucket}/canary-artifacts/${e.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}generateActionScript(e){switch(e.type){case"click":return`await page.click('${e.selector}');`;case"type":return`await page.type('${e.selector}', '${e.value}');`;case"wait":return`await page.waitForTimeout(${e.duration});`;case"waitForSelector":return`await page.waitForSelector('${e.selector}');`;default:return""}}createAlarm(e,t){let a=this.canaries.get(e);if(!a)throw Error(`Canary not found: ${e}`);let r={id:`alarm-${Date.now()}-${this.alarmCounter++}`,...t};if(!a.alarms)a.alarms=[];return a.alarms.push(r),r}getCanary(e){return this.canaries.get(e)}listCanaries(){return Array.from(this.canaries.values())}generateCanaryCF(e){let t={Type:"AWS::Synthetics::Canary",Properties:{Name:e.name,RuntimeVersion:e.runtimeVersion,ExecutionRoleArn:{"Fn::GetAtt":["CanaryExecutionRole","Arn"]},Schedule:{Expression:e.schedule.expression,...e.schedule.durationInSeconds&&{DurationInSeconds:e.schedule.durationInSeconds}},ArtifactS3Location:e.artifactS3Location,StartCanaryAfterCreation:!0}};if(e.code.type==="script")t.Properties.Code={Handler:e.handler,Script:e.code.script};else t.Properties.Code={Handler:e.handler,S3Bucket:e.code.s3Bucket,S3Key:e.code.s3Key,...e.code.s3Version&&{S3ObjectVersion:e.code.s3Version}};if(e.runConfig)t.Properties.RunConfig={TimeoutInSeconds:e.runConfig.timeoutInSeconds,MemoryInMB:e.runConfig.memoryInMB,...e.runConfig.environmentVariables&&{EnvironmentVariables:e.runConfig.environmentVariables},...e.runConfig.activeTracing!==void 0&&{ActiveTracing:e.runConfig.activeTracing}};if(e.vpcConfig)t.Properties.VPCConfig={SubnetIds:e.vpcConfig.subnetIds,SecurityGroupIds:e.vpcConfig.securityGroupIds};if(e.successRetentionPeriod)t.Properties.SuccessRetentionPeriod=e.successRetentionPeriod;if(e.failureRetentionPeriod)t.Properties.FailureRetentionPeriod=e.failureRetentionPeriod;return t}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 Nm=new Oe;class _r{plans=new Map;migrations=new Map;planCounter=0;migrationCounter=0;createPlan(e){let t=`migration-plan-${Date.now()}-${this.planCounter++}`,a={id:t,...e};return this.plans.set(t,a),a}createMigration(e){let t=`migration-${Date.now()}-${this.migrationCounter++}`,a=this.generateChecksum(e.up+e.down),r={id:t,checksum:a,...e};return this.migrations.set(t,r),r}createSchemaMigration(e){let{up:t,down:a}=this.generateSchemaSQL(e.changes,e.tableName,e.engine);return this.createMigration({version:e.version,name:e.name,description:`Schema changes for ${e.tableName}`,up:t,down:a})}createDataMigration(e){return this.createMigration({version:e.version,name:e.name,description:e.description,up:e.upSQL,down:e.downSQL})}addMigrationToPlan(e,t){let a=this.plans.get(e);if(!a)throw Error(`Migration plan not found: ${e}`);a.migrations.push(t)}async executePlan(e,t=!1){let a=this.plans.get(e);if(!a)throw Error(`Migration plan not found: ${e}`);let r=Date.now(),n=[],i=[];if(console.log(`${t?"[DRY RUN] ":""}Executing migration plan: ${a.name}`),console.log(`Database: ${a.database.type} - ${a.database.identifier}`),console.log(`Migrations to apply: ${a.migrations.length}
3758
+ `;return this.createCanary({name:e.name,description:e.description,runtimeVersion:Oe.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:t},schedule:{expression:`rate(${e.interval} minutes)`},runConfig:{timeoutInSeconds:180,memoryInMB:1024,activeTracing:!0},artifactS3Location:`s3://${e.s3Bucket}/canary-artifacts/${e.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}generateActionScript(e){switch(e.type){case"click":return`await page.click('${e.selector}');`;case"type":return`await page.type('${e.selector}', '${e.value}');`;case"wait":return`await page.waitForTimeout(${e.duration});`;case"waitForSelector":return`await page.waitForSelector('${e.selector}');`;default:return""}}createAlarm(e,t){let a=this.canaries.get(e);if(!a)throw Error(`Canary not found: ${e}`);let r={id:`alarm-${Date.now()}-${this.alarmCounter++}`,...t};if(!a.alarms)a.alarms=[];return a.alarms.push(r),r}getCanary(e){return this.canaries.get(e)}listCanaries(){return Array.from(this.canaries.values())}generateCanaryCF(e){let t={Type:"AWS::Synthetics::Canary",Properties:{Name:e.name,RuntimeVersion:e.runtimeVersion,ExecutionRoleArn:{"Fn::GetAtt":["CanaryExecutionRole","Arn"]},Schedule:{Expression:e.schedule.expression,...e.schedule.durationInSeconds&&{DurationInSeconds:e.schedule.durationInSeconds}},ArtifactS3Location:e.artifactS3Location,StartCanaryAfterCreation:!0}};if(e.code.type==="script")t.Properties.Code={Handler:e.handler,Script:e.code.script};else t.Properties.Code={Handler:e.handler,S3Bucket:e.code.s3Bucket,S3Key:e.code.s3Key,...e.code.s3Version&&{S3ObjectVersion:e.code.s3Version}};if(e.runConfig)t.Properties.RunConfig={TimeoutInSeconds:e.runConfig.timeoutInSeconds,MemoryInMB:e.runConfig.memoryInMB,...e.runConfig.environmentVariables&&{EnvironmentVariables:e.runConfig.environmentVariables},...e.runConfig.activeTracing!==void 0&&{ActiveTracing:e.runConfig.activeTracing}};if(e.vpcConfig)t.Properties.VPCConfig={SubnetIds:e.vpcConfig.subnetIds,SecurityGroupIds:e.vpcConfig.securityGroupIds};if(e.successRetentionPeriod)t.Properties.SuccessRetentionPeriod=e.successRetentionPeriod;if(e.failureRetentionPeriod)t.Properties.FailureRetentionPeriod=e.failureRetentionPeriod;return t}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 Rm=new Oe;class _r{plans=new Map;migrations=new Map;planCounter=0;migrationCounter=0;createPlan(e){let t=`migration-plan-${Date.now()}-${this.planCounter++}`,a={id:t,...e};return this.plans.set(t,a),a}createMigration(e){let t=`migration-${Date.now()}-${this.migrationCounter++}`,a=this.generateChecksum(e.up+e.down),r={id:t,checksum:a,...e};return this.migrations.set(t,r),r}createSchemaMigration(e){let{up:t,down:a}=this.generateSchemaSQL(e.changes,e.tableName,e.engine);return this.createMigration({version:e.version,name:e.name,description:`Schema changes for ${e.tableName}`,up:t,down:a})}createDataMigration(e){return this.createMigration({version:e.version,name:e.name,description:e.description,up:e.upSQL,down:e.downSQL})}addMigrationToPlan(e,t){let a=this.plans.get(e);if(!a)throw Error(`Migration plan not found: ${e}`);a.migrations.push(t)}async executePlan(e,t=!1){let a=this.plans.get(e);if(!a)throw Error(`Migration plan not found: ${e}`);let r=Date.now(),n=[],i=[];if(console.log(`${t?"[DRY RUN] ":""}Executing migration plan: ${a.name}`),console.log(`Database: ${a.database.type} - ${a.database.identifier}`),console.log(`Migrations to apply: ${a.migrations.length}
3759
3759
  `),a.backupBeforeMigration&&!t)console.log("Creating database backup before migration...");for(let o of a.migrations)try{if(console.log(`Applying migration: ${o.version} - ${o.name}`),!t){if(this.generateChecksum(o.up+o.down)!==o.checksum)throw Error("Migration checksum mismatch - migration has been modified");let c=Date.now();o.appliedAt=new Date,o.executionTimeMs=Date.now()-c,console.log(`✓ Applied in ${o.executionTimeMs}ms
3760
3760
  `)}else console.log(`[SKIPPED - DRY RUN]
3761
3761
  `);n.push(o.version)}catch(c){if(console.error(`✗ Failed: ${c instanceof Error?c.message:String(c)}
3762
3762
  `),i.push(o.version),!t)return console.log("Rolling back previously applied migrations..."),await this.rollbackMigrations(n.reverse(),a),{success:!1,version:o.version,appliedMigrations:[],failedMigrations:i,executionTimeMs:Date.now()-r,error:c instanceof Error?c.message:String(c),rollbackPerformed:!0}}let s=Date.now()-r;return console.log(`${t?"[DRY RUN] ":""}Migration plan completed successfully`),console.log(`Total time: ${s}ms`),{success:!0,version:a.migrations[a.migrations.length-1]?.version||"unknown",appliedMigrations:n,failedMigrations:i,executionTimeMs:s}}async rollbackMigrations(e,t){for(let a of e){let r=t.migrations.find((n)=>n.version===a);if(r)console.log(`Rolling back: ${r.version} - ${r.name}`),r.rolledBackAt=new Date,console.log(`✓ Rolled back
3763
3763
  `)}}getMigrationStatus(e){let t=this.plans.get(e);if(!t)throw Error(`Migration plan not found: ${e}`);let a=t.migrations.filter((n)=>n.appliedAt&&!n.rolledBackAt),r=t.migrations.filter((n)=>!n.appliedAt);return{currentVersion:a[a.length-1]?.version||"0.0.0",pendingMigrations:r,appliedMigrations:a,lastMigration:a[a.length-1]}}generateSchemaSQL(e,t,a="postgres"){let r=[],n=[];for(let i of e)switch(i.type){case"add_column":r.push(`ALTER TABLE ${t} ADD COLUMN ${i.columnName} ${i.columnType}${i.nullable===!1?" NOT NULL":""}${i.defaultValue?` DEFAULT ${i.defaultValue}`:""}; `),n.push(`ALTER TABLE ${t} DROP COLUMN ${i.columnName};`);break;case"drop_column":r.push(`ALTER TABLE ${t} DROP COLUMN ${i.columnName};`),n.push(`-- Cannot restore dropped column ${i.columnName}`);break;case"modify_column":if(a==="postgres")r.push(`ALTER TABLE ${t} ALTER COLUMN ${i.columnName} TYPE ${i.newType};`);else r.push(`ALTER TABLE ${t} MODIFY COLUMN ${i.columnName} ${i.newType};`);n.push(`-- Reverting ${i.columnName} type change requires manual intervention`);break;case"add_index":r.push(`CREATE INDEX ${i.indexName} ON ${t} (${(i.columns??[]).join(", ")});`),n.push(`DROP INDEX ${i.indexName};`);break;case"drop_index":r.push(`DROP INDEX ${i.indexName};`),n.push(`-- Cannot restore index ${i.indexName} without schema details`);break}return{up:r.join(`
3764
3764
  `),down:n.reverse().join(`
3765
- `)}}generateChecksum(e){let t=0;for(let a=0;a<e.length;a++){let r=e.charCodeAt(a);t=(t<<5)-t+r,t=t&t}return t.toString(16)}validatePlan(e){let t=this.plans.get(e);if(!t)return{valid:!1,errors:["Migration plan not found"]};let a=[],r=new Set;for(let n of t.migrations){if(r.has(n.version))a.push(`Duplicate migration version: ${n.version}`);r.add(n.version)}for(let n of t.migrations)if(!n.down||n.down.trim()==="")a.push(`Migration ${n.version} is missing rollback SQL`);for(let n of t.migrations)if(this.generateChecksum(n.up+n.down)!==n.checksum)a.push(`Migration ${n.version} has invalid checksum`);return{valid:a.length===0,errors:a}}getPlan(e){return this.plans.get(e)}listPlans(){return Array.from(this.plans.values())}getMigration(e){return this.migrations.get(e)}listMigrations(){return Array.from(this.migrations.values())}clear(){this.plans.clear(),this.migrations.clear(),this.planCounter=0,this.migrationCounter=0}}var Dm=new _r;class Wr{replicas=new Map;replicationGroups=new Map;proxies=new Map;proxyTargets=new Map;replicaCounter=0;groupCounter=0;proxyCounter=0;targetCounter=0;createReplica(e){let t=`replica-${Date.now()}-${this.replicaCounter++}`,a={id:t,status:"creating",...e};return this.replicas.set(t,a),a}createRDSReplica(e){return this.createReplica({name:e.name,sourceDatabase:e.sourceDatabase,region:e.region||"us-east-1",instanceClass:e.instanceClass||"db.t3.medium",multiAZ:e.multiAZ||!1,autoMinorVersionUpgrade:!0,backupRetentionPeriod:7})}createCrossRegionReplica(e){return this.createReplica({name:e.name,sourceDatabase:e.sourceDatabase,region:e.targetRegion,instanceClass:e.instanceClass||"db.t3.medium",multiAZ:!0,autoMinorVersionUpgrade:!0,backupRetentionPeriod:7})}createReplicationGroup(e){let t=`replication-group-${Date.now()}-${this.groupCounter++}`,a={id:t,...e};return this.replicationGroups.set(t,a),a}createAutoScalingReplicationGroup(e){return this.createReplicationGroup({name:e.name,primaryDatabase:e.primaryDatabase,replicas:[],loadBalancing:e.loadBalancing||{type:"round-robin"},failoverEnabled:!0,autoScaling:{enabled:!0,minReplicas:e.minReplicas,maxReplicas:e.maxReplicas,targetCPU:e.targetCPU||70,scaleUpCooldown:300,scaleDownCooldown:600}})}addReplicaToGroup(e,t){let a=this.replicationGroups.get(e);if(!a)throw Error(`Replication group not found: ${e}`);a.replicas.push(t)}createProxy(e){let t=`rds-proxy-${Date.now()}-${this.proxyCounter++}`,a={id:t,...e};return this.proxies.set(t,a),a}createConnectionPoolProxy(e){return this.createProxy({name:e.name,engineFamily:e.engineFamily,targetDatabase:e.targetDatabase,maxConnectionsPercent:e.maxConnections||100,maxIdleConnectionsPercent:50,connectionBorrowTimeout:120,sessionPinningFilters:["EXCLUDE_VARIABLE_SETS"],requireTLS:!0,idleClientTimeout:1800,vpcSubnetIds:e.vpcSubnetIds,securityGroupIds:e.securityGroupIds,secretArn:e.secretArn})}createServerlessProxy(e){return this.createProxy({name:e.name,engineFamily:e.engineFamily,targetDatabase:e.targetDatabase,maxConnectionsPercent:100,maxIdleConnectionsPercent:10,connectionBorrowTimeout:60,sessionPinningFilters:["EXCLUDE_VARIABLE_SETS"],requireTLS:!0,idleClientTimeout:300,vpcSubnetIds:e.vpcSubnetIds,securityGroupIds:e.securityGroupIds,secretArn:e.secretArn})}addProxyTarget(e){let t=`proxy-target-${Date.now()}-${this.targetCounter++}`,a={id:t,...e};return this.proxyTargets.set(t,a),a}promoteReplica(e){let t=this.replicas.get(e);if(!t)return{success:!1,message:"Replica not found"};if(console.log(`Promoting replica to primary: ${t.name}`),console.log(`Region: ${t.region}`),console.log(`
3765
+ `)}}generateChecksum(e){let t=0;for(let a=0;a<e.length;a++){let r=e.charCodeAt(a);t=(t<<5)-t+r,t=t&t}return t.toString(16)}validatePlan(e){let t=this.plans.get(e);if(!t)return{valid:!1,errors:["Migration plan not found"]};let a=[],r=new Set;for(let n of t.migrations){if(r.has(n.version))a.push(`Duplicate migration version: ${n.version}`);r.add(n.version)}for(let n of t.migrations)if(!n.down||n.down.trim()==="")a.push(`Migration ${n.version} is missing rollback SQL`);for(let n of t.migrations)if(this.generateChecksum(n.up+n.down)!==n.checksum)a.push(`Migration ${n.version} has invalid checksum`);return{valid:a.length===0,errors:a}}getPlan(e){return this.plans.get(e)}listPlans(){return Array.from(this.plans.values())}getMigration(e){return this.migrations.get(e)}listMigrations(){return Array.from(this.migrations.values())}clear(){this.plans.clear(),this.migrations.clear(),this.planCounter=0,this.migrationCounter=0}}var Nm=new _r;class Br{replicas=new Map;replicationGroups=new Map;proxies=new Map;proxyTargets=new Map;replicaCounter=0;groupCounter=0;proxyCounter=0;targetCounter=0;createReplica(e){let t=`replica-${Date.now()}-${this.replicaCounter++}`,a={id:t,status:"creating",...e};return this.replicas.set(t,a),a}createRDSReplica(e){return this.createReplica({name:e.name,sourceDatabase:e.sourceDatabase,region:e.region||"us-east-1",instanceClass:e.instanceClass||"db.t3.medium",multiAZ:e.multiAZ||!1,autoMinorVersionUpgrade:!0,backupRetentionPeriod:7})}createCrossRegionReplica(e){return this.createReplica({name:e.name,sourceDatabase:e.sourceDatabase,region:e.targetRegion,instanceClass:e.instanceClass||"db.t3.medium",multiAZ:!0,autoMinorVersionUpgrade:!0,backupRetentionPeriod:7})}createReplicationGroup(e){let t=`replication-group-${Date.now()}-${this.groupCounter++}`,a={id:t,...e};return this.replicationGroups.set(t,a),a}createAutoScalingReplicationGroup(e){return this.createReplicationGroup({name:e.name,primaryDatabase:e.primaryDatabase,replicas:[],loadBalancing:e.loadBalancing||{type:"round-robin"},failoverEnabled:!0,autoScaling:{enabled:!0,minReplicas:e.minReplicas,maxReplicas:e.maxReplicas,targetCPU:e.targetCPU||70,scaleUpCooldown:300,scaleDownCooldown:600}})}addReplicaToGroup(e,t){let a=this.replicationGroups.get(e);if(!a)throw Error(`Replication group not found: ${e}`);a.replicas.push(t)}createProxy(e){let t=`rds-proxy-${Date.now()}-${this.proxyCounter++}`,a={id:t,...e};return this.proxies.set(t,a),a}createConnectionPoolProxy(e){return this.createProxy({name:e.name,engineFamily:e.engineFamily,targetDatabase:e.targetDatabase,maxConnectionsPercent:e.maxConnections||100,maxIdleConnectionsPercent:50,connectionBorrowTimeout:120,sessionPinningFilters:["EXCLUDE_VARIABLE_SETS"],requireTLS:!0,idleClientTimeout:1800,vpcSubnetIds:e.vpcSubnetIds,securityGroupIds:e.securityGroupIds,secretArn:e.secretArn})}createServerlessProxy(e){return this.createProxy({name:e.name,engineFamily:e.engineFamily,targetDatabase:e.targetDatabase,maxConnectionsPercent:100,maxIdleConnectionsPercent:10,connectionBorrowTimeout:60,sessionPinningFilters:["EXCLUDE_VARIABLE_SETS"],requireTLS:!0,idleClientTimeout:300,vpcSubnetIds:e.vpcSubnetIds,securityGroupIds:e.securityGroupIds,secretArn:e.secretArn})}addProxyTarget(e){let t=`proxy-target-${Date.now()}-${this.targetCounter++}`,a={id:t,...e};return this.proxyTargets.set(t,a),a}promoteReplica(e){let t=this.replicas.get(e);if(!t)return{success:!1,message:"Replica not found"};if(console.log(`Promoting replica to primary: ${t.name}`),console.log(`Region: ${t.region}`),console.log(`
3766
3766
  1. Checking replication lag...`),t.replicationLag&&t.replicationLag>5000)return{success:!1,message:`Replication lag too high: ${t.replicationLag}ms`};return console.log(` Replication lag: ${t.replicationLag||0}ms (acceptable)`),console.log(`
3767
3767
  2. Promoting replica to standalone instance...`),console.log(`
3768
3768
  3. Updating DNS records...`),console.log(`
3769
3769
  4. Updating application configuration...`),console.log(`
3770
- ✓ Promotion completed successfully`),t.status="available",{success:!0,message:"Replica promoted successfully"}}getReplicationLag(e){if(!this.replicas.get(e))throw Error(`Replica not found: ${e}`);return Math.floor(Math.random()*1000)}getReplica(e){return this.replicas.get(e)}listReplicas(){return Array.from(this.replicas.values())}getReplicationGroup(e){return this.replicationGroups.get(e)}listReplicationGroups(){return Array.from(this.replicationGroups.values())}getProxy(e){return this.proxies.get(e)}listProxies(){return Array.from(this.proxies.values())}generateReplicaCF(e){return{Type:"AWS::RDS::DBInstance",Properties:{SourceDBInstanceIdentifier:e.sourceDatabase,DBInstanceIdentifier:e.name,DBInstanceClass:e.instanceClass,MultiAZ:e.multiAZ||!1,AutoMinorVersionUpgrade:e.autoMinorVersionUpgrade??!0,...e.backupRetentionPeriod&&{BackupRetentionPeriod:e.backupRetentionPeriod},...e.preferredBackupWindow&&{PreferredBackupWindow:e.preferredBackupWindow},...e.preferredMaintenanceWindow&&{PreferredMaintenanceWindow:e.preferredMaintenanceWindow}}}}generateProxyCF(e){return{Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:e.name,EngineFamily:e.engineFamily,Auth:[{AuthScheme:"SECRETS",SecretArn:e.secretArn,IAMAuth:"DISABLED"}],RoleArn:{"Fn::GetAtt":["RDSProxyRole","Arn"]},VpcSubnetIds:e.vpcSubnetIds,VpcSecurityGroupIds:e.securityGroupIds,RequireTLS:e.requireTLS??!0,IdleClientTimeout:e.idleClientTimeout||1800,...e.maxConnectionsPercent&&{MaxConnectionsPercent:e.maxConnectionsPercent},...e.maxIdleConnectionsPercent&&{MaxIdleConnectionsPercent:e.maxIdleConnectionsPercent},...e.connectionBorrowTimeout&&{ConnectionBorrowTimeout:e.connectionBorrowTimeout}}}}generateProxyTargetCF(e,t){return{Type:"AWS::RDS::DBProxyTargetGroup",Properties:{DBProxyName:t.name,TargetGroupName:"default",DBInstanceIdentifiers:[e.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 km=new Wr;class Gr{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(e){let t=`pi-${Date.now()}-${this.insightsCounter++}`,a={id:t,name:e.name,databaseIdentifier:e.databaseIdentifier,enabled:!0,retentionPeriod:e.retentionPeriod||7,kmsKeyId:e.kmsKeyId};return this.insights.set(t,a),a}enableSlowQueryLog(e){let t=`slow-query-${Date.now()}-${this.logCounter++}`,a={id:t,name:e.name,databaseIdentifier:e.databaseIdentifier,enabled:!0,logDestination:e.logDestination,cloudwatchLogGroup:e.cloudwatchLogGroup,s3Bucket:e.s3Bucket,s3Prefix:e.s3Bucket?"slow-queries/":void 0,minExecutionTime:e.minExecutionTime||1000};return this.slowQueryLogs.set(t,a),a}recordQueryMetric(e){let t=`metric-${Date.now()}-${this.metricCounter++}`,a={id:t,timestamp:new Date,...e};return this.queryMetrics.set(t,a),a}generatePerformanceReport(e){let t=`report-${Date.now()}-${this.reportCounter++}`,a={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)},r=Array.from(this.queryMetrics.values()),n=r.sort((c,l)=>l.executionCount-c.executionCount).slice(0,10),i=r.filter((c)=>c.avgExecutionTime>1000).sort((c,l)=>l.avgExecutionTime-c.avgExecutionTime).slice(0,10),s=this.generateRecommendations(a,i),o={id:t,name:e.name,databaseIdentifier:e.databaseIdentifier,reportType:e.reportType,metrics:a,topQueries:n,slowQueries:i,recommendations:s,generatedAt:new Date};return this.reports.set(t,o),o}generateRecommendations(e,t){let a=[];if(e.avgCPU>70)a.push({type:"scaling",severity:"high",title:"High CPU Usage",description:`Average CPU usage is ${e.avgCPU.toFixed(1)}%, which is above the recommended threshold of 70%.`,impact:"Performance degradation, increased latency, potential timeouts",effort:"medium"});if(e.cacheHitRatio<95)a.push({type:"configuration",severity:"medium",title:"Low Cache Hit Ratio",description:`Cache hit ratio is ${e.cacheHitRatio.toFixed(1)}%. Consider increasing buffer pool size.`,impact:"Increased disk I/O, slower query performance",effort:"low"});if(e.deadlocks>0)a.push({type:"query",severity:"medium",title:"Deadlocks Detected",description:`${e.deadlocks} deadlock(s) detected. Review transaction isolation levels and query patterns.`,impact:"Transaction failures, application errors",effort:"high"});if(t.length>0)a.push({type:"index",severity:"high",title:"Slow Queries Detected",description:`${t.length} slow queries detected. Consider adding indexes or optimizing queries.`,impact:"High latency, poor user experience",effort:"medium"});if(e.avgReadLatency>10||e.avgWriteLatency>10)a.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 a}analyzeQuery(e){let t=`analysis-${Date.now()}-${Math.random().toString(36).slice(2,9)}`,a=[{id:1,operation:"Seq Scan",table:"users",rows:1e4,cost:850.5,children:[]}],r=[];if(e.toLowerCase().includes("select *"))r.push({type:"full_table_scan",severity:"warning",description:"Query selects all columns. Consider selecting only required columns."});if(!e.toLowerCase().includes("where")&&e.toLowerCase().includes("select"))r.push({type:"full_table_scan",severity:"critical",description:"Query has no WHERE clause and may scan entire table."});return{id:t,queryId:t,sql:e,executionPlan:a,bottlenecks:r,recommendations:["Add appropriate indexes on WHERE clause columns","Consider using EXPLAIN ANALYZE to get actual execution statistics","Review and optimize JOIN conditions"],estimatedCost:a[0].cost}}recommendIndex(e){let t=`index-rec-${Date.now()}-${this.recommendationCounter++}`,a=`idx_${e.tableName}_${e.columns.join("_")}`,r={id:t,tableName:e.tableName,columns:e.columns,reason:e.reason,estimatedImprovement:e.estimatedImprovement||50,estimatedSize:e.columns.length*10,createSQL:`CREATE INDEX ${a} ON ${e.tableName} (${e.columns.join(", ")});`};return this.indexRecommendations.set(t,r),r}getInsights(e){return this.insights.get(e)}listInsights(){return Array.from(this.insights.values())}getSlowQueryLog(e){return this.slowQueryLogs.get(e)}listSlowQueryLogs(){return Array.from(this.slowQueryLogs.values())}getReport(e){return this.reports.get(e)}listReports(){return Array.from(this.reports.values())}listIndexRecommendations(){return Array.from(this.indexRecommendations.values())}generatePerformanceInsightsCF(e){return{EnablePerformanceInsights:e.enabled,PerformanceInsightsRetentionPeriod:e.retentionPeriod,...e.kmsKeyId&&{PerformanceInsightsKMSKeyId:e.kmsKeyId}}}generateSlowQueryAlarmCF(e){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:e.alarmName,AlarmDescription:"Alert when slow queries exceed threshold",MetricName:"SlowQueryCount",Namespace:"AWS/RDS",Statistic:"Sum",Period:300,EvaluationPeriods:1,Threshold:e.threshold,ComparisonOperator:"GreaterThanThreshold",...e.snsTopicArn&&{AlarmActions:[e.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 $m=new Gr;class Fr{users=new Map;roles=new Map;audits=new Map;userCounter=0;roleCounter=0;auditCounter=0;createUser(e){let t=`db-user-${Date.now()}-${this.userCounter++}`,a={id:t,createdAt:new Date,...e};return this.users.set(t,a),a}createReadOnlyUser(e){let t=e.tables?e.tables.map((a)=>({database:e.database,table:a,privileges:["SELECT"]})):[{database:e.database,privileges:["SELECT"]}];return this.createUser({username:e.username,database:e.database,privileges:t,passwordSecretArn:e.passwordSecretArn,rotationEnabled:!0,rotationDays:90})}createReadWriteUser(e){let t=e.tables?e.tables.map((a)=>({database:e.database,table:a,privileges:["SELECT","INSERT","UPDATE","DELETE"]})):[{database:e.database,privileges:["SELECT","INSERT","UPDATE","DELETE"]}];return this.createUser({username:e.username,database:e.database,privileges:t,passwordSecretArn:e.passwordSecretArn,rotationEnabled:!0,rotationDays:60})}createAdminUser(e){return this.createUser({username:e.username,database:e.database,privileges:[{database:e.database,privileges:["ALL"]}],passwordSecretArn:e.passwordSecretArn,rotationEnabled:!0,rotationDays:30})}createApplicationUser(e){let t=e.tables.map((a)=>({database:e.database,table:a.name,privileges:a.privileges}));return this.createUser({username:e.username,database:e.database,privileges:t,passwordSecretArn:e.passwordSecretArn,rotationEnabled:!0,rotationDays:90})}createRole(e){let t=`role-${Date.now()}-${this.roleCounter++}`,a={id:t,users:[],...e};return this.roles.set(t,a),a}assignUserToRole(e,t){let a=this.users.get(e),r=this.roles.get(t);if(!a)throw Error(`User not found: ${e}`);if(!r)throw Error(`Role not found: ${t}`);r.users.push(e);for(let n of r.privileges){let i=a.privileges.find((s)=>s.database===n.database&&s.table===n.table);if(i)i.privileges=Array.from(new Set([...i.privileges,...n.privileges]));else a.privileges.push({...n})}}grantPrivileges(e,t){let a=this.users.get(e);if(!a)return{success:!1,message:"User not found"};for(let r of t){let n=a.privileges.find((i)=>i.database===r.database&&i.table===r.table);if(n)n.privileges=Array.from(new Set([...n.privileges,...r.privileges]));else a.privileges.push(r)}return this.auditAccess({username:a.username,action:"GRANT",database:t[0]?.database,table:t[0]?.table,success:!0}),{success:!0,message:"Privileges granted successfully"}}revokePrivileges(e,t){let a=this.users.get(e);if(!a)return{success:!1,message:"User not found"};for(let r of t){let n=a.privileges.findIndex((i)=>i.database===r.database&&i.table===r.table);if(n!==-1){let i=a.privileges[n];if(i.privileges=i.privileges.filter((s)=>!r.privileges.includes(s)),i.privileges.length===0)a.privileges.splice(n,1)}}return this.auditAccess({username:a.username,action:"REVOKE",database:t[0]?.database,table:t[0]?.table,success:!0}),{success:!0,message:"Privileges revoked successfully"}}rotatePassword(e){let t=this.users.get(e);if(!t)return{success:!1};let a=`arn:aws:secretsmanager:us-east-1:123456789012:secret:db-${t.username}-${Date.now()}`;return t.passwordSecretArn=a,t.lastRotated=new Date,console.log(`Password rotated for user: ${t.username}`),{success:!0,newSecretArn:a}}needsPasswordRotation(e){let t=this.users.get(e);if(!t||!t.rotationEnabled||!t.lastRotated||!t.rotationDays)return!1;return(Date.now()-t.lastRotated.getTime())/86400000>=t.rotationDays}auditAccess(e){let t=`audit-${Date.now()}-${this.auditCounter++}`,a={id:t,timestamp:new Date,...e};return this.audits.set(t,a),a}getUserAccessHistory(e,t=100){return Array.from(this.audits.values()).filter((a)=>a.username===e).sort((a,r)=>r.timestamp.getTime()-a.timestamp.getTime()).slice(0,t)}getFailedLoginAttempts(e,t=24){let a=Date.now()-t*60*60*1000;return Array.from(this.audits.values()).filter((r)=>r.username===e&&r.action==="LOGIN"&&!r.success&&r.timestamp.getTime()>a)}generateCreateUserSQL(e,t="postgres"){let a=[];if(t==="postgres"){a.push(`CREATE USER ${e.username} WITH PASSWORD '${e.passwordSecretArn}';`);for(let r of e.privileges)if(r.privileges.includes("ALL"))a.push(`GRANT ALL PRIVILEGES ON DATABASE ${r.database} TO ${e.username};`);else{let n=r.privileges.join(", ");if(r.table)a.push(`GRANT ${n} ON ${r.database}.${r.table} TO ${e.username};`);else a.push(`GRANT ${n} ON DATABASE ${r.database} TO ${e.username};`)}}else{a.push(`CREATE USER '${e.username}'@'%' IDENTIFIED BY '${e.passwordSecretArn}';`);for(let r of e.privileges){let n=r.privileges.includes("ALL")?"ALL PRIVILEGES":r.privileges.join(", "),i=r.table?`${r.database}.${r.table}`:`${r.database}.*`;a.push(`GRANT ${n} ON ${i} TO '${e.username}'@'%';`)}a.push("FLUSH PRIVILEGES;")}return a.join(`
3771
- `)}getUser(e){return this.users.get(e)}listUsers(){return Array.from(this.users.values())}getRole(e){return this.roles.get(e)}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 Lm=new Fr;class Vr{rotations=new Map;schedules=new Map;rotationCounter=0;scheduleCounter=0;createRotation(e){let t=`rotation-${Date.now()}-${this.rotationCounter++}`,a={id:t,...e};return this.rotations.set(t,a),a}enableRDSRotation(e){let t=this.createRotation({secretId:e.secretId,secretType:"rds_credentials",rotationEnabled:!0,rotationDays:e.rotationDays||30,rotationLambdaArn:this.generateRDSRotationLambdaArn(e.engine)});return t.nextRotation=new Date(Date.now()+t.rotationDays*24*60*60*1000),t}enableAPIKeyRotation(e){return this.createRotation({secretId:e.secretId,secretType:"api_key",rotationEnabled:!0,rotationDays:e.rotationDays||90,rotationLambdaArn:e.rotationLambdaArn})}enableOAuthRotation(e){return this.createRotation({secretId:e.secretId,secretType:"oauth_token",rotationEnabled:!0,rotationDays:e.rotationDays||60,rotationLambdaArn:e.rotationLambdaArn})}enableSSHKeyRotation(e){return this.createRotation({secretId:e.secretId,secretType:"ssh_key",rotationEnabled:!0,rotationDays:e.rotationDays||180,rotationLambdaArn:e.rotationLambdaArn})}createSchedule(e){let t=`schedule-${Date.now()}-${this.scheduleCounter++}`,a={id:t,...e};return this.schedules.set(t,a),a}async executeRotation(e){let t=this.rotations.get(e);if(!t)throw Error(`Rotation not found: ${e}`);console.log(`
3770
+ ✓ Promotion completed successfully`),t.status="available",{success:!0,message:"Replica promoted successfully"}}getReplicationLag(e){if(!this.replicas.get(e))throw Error(`Replica not found: ${e}`);return Math.floor(Math.random()*1000)}getReplica(e){return this.replicas.get(e)}listReplicas(){return Array.from(this.replicas.values())}getReplicationGroup(e){return this.replicationGroups.get(e)}listReplicationGroups(){return Array.from(this.replicationGroups.values())}getProxy(e){return this.proxies.get(e)}listProxies(){return Array.from(this.proxies.values())}generateReplicaCF(e){return{Type:"AWS::RDS::DBInstance",Properties:{SourceDBInstanceIdentifier:e.sourceDatabase,DBInstanceIdentifier:e.name,DBInstanceClass:e.instanceClass,MultiAZ:e.multiAZ||!1,AutoMinorVersionUpgrade:e.autoMinorVersionUpgrade??!0,...e.backupRetentionPeriod&&{BackupRetentionPeriod:e.backupRetentionPeriod},...e.preferredBackupWindow&&{PreferredBackupWindow:e.preferredBackupWindow},...e.preferredMaintenanceWindow&&{PreferredMaintenanceWindow:e.preferredMaintenanceWindow}}}}generateProxyCF(e){return{Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:e.name,EngineFamily:e.engineFamily,Auth:[{AuthScheme:"SECRETS",SecretArn:e.secretArn,IAMAuth:"DISABLED"}],RoleArn:{"Fn::GetAtt":["RDSProxyRole","Arn"]},VpcSubnetIds:e.vpcSubnetIds,VpcSecurityGroupIds:e.securityGroupIds,RequireTLS:e.requireTLS??!0,IdleClientTimeout:e.idleClientTimeout||1800,...e.maxConnectionsPercent&&{MaxConnectionsPercent:e.maxConnectionsPercent},...e.maxIdleConnectionsPercent&&{MaxIdleConnectionsPercent:e.maxIdleConnectionsPercent},...e.connectionBorrowTimeout&&{ConnectionBorrowTimeout:e.connectionBorrowTimeout}}}}generateProxyTargetCF(e,t){return{Type:"AWS::RDS::DBProxyTargetGroup",Properties:{DBProxyName:t.name,TargetGroupName:"default",DBInstanceIdentifiers:[e.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 Dm=new Br;class Ur{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(e){let t=`pi-${Date.now()}-${this.insightsCounter++}`,a={id:t,name:e.name,databaseIdentifier:e.databaseIdentifier,enabled:!0,retentionPeriod:e.retentionPeriod||7,kmsKeyId:e.kmsKeyId};return this.insights.set(t,a),a}enableSlowQueryLog(e){let t=`slow-query-${Date.now()}-${this.logCounter++}`,a={id:t,name:e.name,databaseIdentifier:e.databaseIdentifier,enabled:!0,logDestination:e.logDestination,cloudwatchLogGroup:e.cloudwatchLogGroup,s3Bucket:e.s3Bucket,s3Prefix:e.s3Bucket?"slow-queries/":void 0,minExecutionTime:e.minExecutionTime||1000};return this.slowQueryLogs.set(t,a),a}recordQueryMetric(e){let t=`metric-${Date.now()}-${this.metricCounter++}`,a={id:t,timestamp:new Date,...e};return this.queryMetrics.set(t,a),a}generatePerformanceReport(e){let t=`report-${Date.now()}-${this.reportCounter++}`,a={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)},r=Array.from(this.queryMetrics.values()),n=r.sort((c,l)=>l.executionCount-c.executionCount).slice(0,10),i=r.filter((c)=>c.avgExecutionTime>1000).sort((c,l)=>l.avgExecutionTime-c.avgExecutionTime).slice(0,10),s=this.generateRecommendations(a,i),o={id:t,name:e.name,databaseIdentifier:e.databaseIdentifier,reportType:e.reportType,metrics:a,topQueries:n,slowQueries:i,recommendations:s,generatedAt:new Date};return this.reports.set(t,o),o}generateRecommendations(e,t){let a=[];if(e.avgCPU>70)a.push({type:"scaling",severity:"high",title:"High CPU Usage",description:`Average CPU usage is ${e.avgCPU.toFixed(1)}%, which is above the recommended threshold of 70%.`,impact:"Performance degradation, increased latency, potential timeouts",effort:"medium"});if(e.cacheHitRatio<95)a.push({type:"configuration",severity:"medium",title:"Low Cache Hit Ratio",description:`Cache hit ratio is ${e.cacheHitRatio.toFixed(1)}%. Consider increasing buffer pool size.`,impact:"Increased disk I/O, slower query performance",effort:"low"});if(e.deadlocks>0)a.push({type:"query",severity:"medium",title:"Deadlocks Detected",description:`${e.deadlocks} deadlock(s) detected. Review transaction isolation levels and query patterns.`,impact:"Transaction failures, application errors",effort:"high"});if(t.length>0)a.push({type:"index",severity:"high",title:"Slow Queries Detected",description:`${t.length} slow queries detected. Consider adding indexes or optimizing queries.`,impact:"High latency, poor user experience",effort:"medium"});if(e.avgReadLatency>10||e.avgWriteLatency>10)a.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 a}analyzeQuery(e){let t=`analysis-${Date.now()}-${Math.random().toString(36).slice(2,9)}`,a=[{id:1,operation:"Seq Scan",table:"users",rows:1e4,cost:850.5,children:[]}],r=[];if(e.toLowerCase().includes("select *"))r.push({type:"full_table_scan",severity:"warning",description:"Query selects all columns. Consider selecting only required columns."});if(!e.toLowerCase().includes("where")&&e.toLowerCase().includes("select"))r.push({type:"full_table_scan",severity:"critical",description:"Query has no WHERE clause and may scan entire table."});return{id:t,queryId:t,sql:e,executionPlan:a,bottlenecks:r,recommendations:["Add appropriate indexes on WHERE clause columns","Consider using EXPLAIN ANALYZE to get actual execution statistics","Review and optimize JOIN conditions"],estimatedCost:a[0].cost}}recommendIndex(e){let t=`index-rec-${Date.now()}-${this.recommendationCounter++}`,a=`idx_${e.tableName}_${e.columns.join("_")}`,r={id:t,tableName:e.tableName,columns:e.columns,reason:e.reason,estimatedImprovement:e.estimatedImprovement||50,estimatedSize:e.columns.length*10,createSQL:`CREATE INDEX ${a} ON ${e.tableName} (${e.columns.join(", ")});`};return this.indexRecommendations.set(t,r),r}getInsights(e){return this.insights.get(e)}listInsights(){return Array.from(this.insights.values())}getSlowQueryLog(e){return this.slowQueryLogs.get(e)}listSlowQueryLogs(){return Array.from(this.slowQueryLogs.values())}getReport(e){return this.reports.get(e)}listReports(){return Array.from(this.reports.values())}listIndexRecommendations(){return Array.from(this.indexRecommendations.values())}generatePerformanceInsightsCF(e){return{EnablePerformanceInsights:e.enabled,PerformanceInsightsRetentionPeriod:e.retentionPeriod,...e.kmsKeyId&&{PerformanceInsightsKMSKeyId:e.kmsKeyId}}}generateSlowQueryAlarmCF(e){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:e.alarmName,AlarmDescription:"Alert when slow queries exceed threshold",MetricName:"SlowQueryCount",Namespace:"AWS/RDS",Statistic:"Sum",Period:300,EvaluationPeriods:1,Threshold:e.threshold,ComparisonOperator:"GreaterThanThreshold",...e.snsTopicArn&&{AlarmActions:[e.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 km=new Ur;class Gr{users=new Map;roles=new Map;audits=new Map;userCounter=0;roleCounter=0;auditCounter=0;createUser(e){let t=`db-user-${Date.now()}-${this.userCounter++}`,a={id:t,createdAt:new Date,...e};return this.users.set(t,a),a}createReadOnlyUser(e){let t=e.tables?e.tables.map((a)=>({database:e.database,table:a,privileges:["SELECT"]})):[{database:e.database,privileges:["SELECT"]}];return this.createUser({username:e.username,database:e.database,privileges:t,passwordSecretArn:e.passwordSecretArn,rotationEnabled:!0,rotationDays:90})}createReadWriteUser(e){let t=e.tables?e.tables.map((a)=>({database:e.database,table:a,privileges:["SELECT","INSERT","UPDATE","DELETE"]})):[{database:e.database,privileges:["SELECT","INSERT","UPDATE","DELETE"]}];return this.createUser({username:e.username,database:e.database,privileges:t,passwordSecretArn:e.passwordSecretArn,rotationEnabled:!0,rotationDays:60})}createAdminUser(e){return this.createUser({username:e.username,database:e.database,privileges:[{database:e.database,privileges:["ALL"]}],passwordSecretArn:e.passwordSecretArn,rotationEnabled:!0,rotationDays:30})}createApplicationUser(e){let t=e.tables.map((a)=>({database:e.database,table:a.name,privileges:a.privileges}));return this.createUser({username:e.username,database:e.database,privileges:t,passwordSecretArn:e.passwordSecretArn,rotationEnabled:!0,rotationDays:90})}createRole(e){let t=`role-${Date.now()}-${this.roleCounter++}`,a={id:t,users:[],...e};return this.roles.set(t,a),a}assignUserToRole(e,t){let a=this.users.get(e),r=this.roles.get(t);if(!a)throw Error(`User not found: ${e}`);if(!r)throw Error(`Role not found: ${t}`);r.users.push(e);for(let n of r.privileges){let i=a.privileges.find((s)=>s.database===n.database&&s.table===n.table);if(i)i.privileges=Array.from(new Set([...i.privileges,...n.privileges]));else a.privileges.push({...n})}}grantPrivileges(e,t){let a=this.users.get(e);if(!a)return{success:!1,message:"User not found"};for(let r of t){let n=a.privileges.find((i)=>i.database===r.database&&i.table===r.table);if(n)n.privileges=Array.from(new Set([...n.privileges,...r.privileges]));else a.privileges.push(r)}return this.auditAccess({username:a.username,action:"GRANT",database:t[0]?.database,table:t[0]?.table,success:!0}),{success:!0,message:"Privileges granted successfully"}}revokePrivileges(e,t){let a=this.users.get(e);if(!a)return{success:!1,message:"User not found"};for(let r of t){let n=a.privileges.findIndex((i)=>i.database===r.database&&i.table===r.table);if(n!==-1){let i=a.privileges[n];if(i.privileges=i.privileges.filter((s)=>!r.privileges.includes(s)),i.privileges.length===0)a.privileges.splice(n,1)}}return this.auditAccess({username:a.username,action:"REVOKE",database:t[0]?.database,table:t[0]?.table,success:!0}),{success:!0,message:"Privileges revoked successfully"}}rotatePassword(e){let t=this.users.get(e);if(!t)return{success:!1};let a=`arn:aws:secretsmanager:us-east-1:123456789012:secret:db-${t.username}-${Date.now()}`;return t.passwordSecretArn=a,t.lastRotated=new Date,console.log(`Password rotated for user: ${t.username}`),{success:!0,newSecretArn:a}}needsPasswordRotation(e){let t=this.users.get(e);if(!t||!t.rotationEnabled||!t.lastRotated||!t.rotationDays)return!1;return(Date.now()-t.lastRotated.getTime())/86400000>=t.rotationDays}auditAccess(e){let t=`audit-${Date.now()}-${this.auditCounter++}`,a={id:t,timestamp:new Date,...e};return this.audits.set(t,a),a}getUserAccessHistory(e,t=100){return Array.from(this.audits.values()).filter((a)=>a.username===e).sort((a,r)=>r.timestamp.getTime()-a.timestamp.getTime()).slice(0,t)}getFailedLoginAttempts(e,t=24){let a=Date.now()-t*60*60*1000;return Array.from(this.audits.values()).filter((r)=>r.username===e&&r.action==="LOGIN"&&!r.success&&r.timestamp.getTime()>a)}generateCreateUserSQL(e,t="postgres"){let a=[];if(t==="postgres"){a.push(`CREATE USER ${e.username} WITH PASSWORD '${e.passwordSecretArn}';`);for(let r of e.privileges)if(r.privileges.includes("ALL"))a.push(`GRANT ALL PRIVILEGES ON DATABASE ${r.database} TO ${e.username};`);else{let n=r.privileges.join(", ");if(r.table)a.push(`GRANT ${n} ON ${r.database}.${r.table} TO ${e.username};`);else a.push(`GRANT ${n} ON DATABASE ${r.database} TO ${e.username};`)}}else{a.push(`CREATE USER '${e.username}'@'%' IDENTIFIED BY '${e.passwordSecretArn}';`);for(let r of e.privileges){let n=r.privileges.includes("ALL")?"ALL PRIVILEGES":r.privileges.join(", "),i=r.table?`${r.database}.${r.table}`:`${r.database}.*`;a.push(`GRANT ${n} ON ${i} TO '${e.username}'@'%';`)}a.push("FLUSH PRIVILEGES;")}return a.join(`
3771
+ `)}getUser(e){return this.users.get(e)}listUsers(){return Array.from(this.users.values())}getRole(e){return this.roles.get(e)}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 Mm=new Gr;class Vr{rotations=new Map;schedules=new Map;rotationCounter=0;scheduleCounter=0;createRotation(e){let t=`rotation-${Date.now()}-${this.rotationCounter++}`,a={id:t,...e};return this.rotations.set(t,a),a}enableRDSRotation(e){let t=this.createRotation({secretId:e.secretId,secretType:"rds_credentials",rotationEnabled:!0,rotationDays:e.rotationDays||30,rotationLambdaArn:this.generateRDSRotationLambdaArn(e.engine)});return t.nextRotation=new Date(Date.now()+t.rotationDays*24*60*60*1000),t}enableAPIKeyRotation(e){return this.createRotation({secretId:e.secretId,secretType:"api_key",rotationEnabled:!0,rotationDays:e.rotationDays||90,rotationLambdaArn:e.rotationLambdaArn})}enableOAuthRotation(e){return this.createRotation({secretId:e.secretId,secretType:"oauth_token",rotationEnabled:!0,rotationDays:e.rotationDays||60,rotationLambdaArn:e.rotationLambdaArn})}enableSSHKeyRotation(e){return this.createRotation({secretId:e.secretId,secretType:"ssh_key",rotationEnabled:!0,rotationDays:e.rotationDays||180,rotationLambdaArn:e.rotationLambdaArn})}createSchedule(e){let t=`schedule-${Date.now()}-${this.scheduleCounter++}`,a={id:t,...e};return this.schedules.set(t,a),a}async executeRotation(e){let t=this.rotations.get(e);if(!t)throw Error(`Rotation not found: ${e}`);console.log(`
3772
3772
  Executing rotation for secret: ${t.secretId}`),console.log(`Secret type: ${t.secretType}`),console.log(`Rotation interval: ${t.rotationDays} days`);try{console.log(`
3773
3773
  Rotation steps:`),console.log("1. Creating new secret version...");let a=`v${Date.now()}`;console.log("2. Testing new credentials..."),console.log("3. Updating application references..."),console.log("4. Marking previous version as deprecated...");let r=t.versionStages?.[0]||"v1";return console.log("5. Finalizing rotation..."),t.lastRotated=new Date,t.nextRotation=new Date(Date.now()+t.rotationDays*24*60*60*1000),console.log(`
3774
3774
  ✓ Rotation completed successfully`),console.log(` New version: ${a}`),console.log(` Next rotation: ${t.nextRotation.toISOString()}`),{success:!0,secretId:t.secretId,oldVersion:r,newVersion:a,rotatedAt:new Date}}catch(a){return console.error(`
3775
- ✗ Rotation failed:`,a),{success:!1,secretId:t.secretId,oldVersion:"unknown",newVersion:"unknown",rotatedAt:new Date,error:a instanceof Error?a.message:String(a)}}}needsRotation(e){let t=this.rotations.get(e);if(!t||!t.rotationEnabled)return!1;if(!t.lastRotated)return!0;return(Date.now()-t.lastRotated.getTime())/86400000>=t.rotationDays}getSecretsNeedingRotation(){return Array.from(this.rotations.values()).filter((e)=>this.needsRotation(e.id))}generateRDSRotationLambdaArn(e){let t={postgres:"SecretsManagerRDSPostgreSQLRotationSingleUser",mysql:"SecretsManagerRDSMySQLRotationSingleUser",sqlserver:"SecretsManagerRDSSQLServerRotationSingleUser",oracle:"SecretsManagerRDSOracleRotationSingleUser"};return`arn:aws:lambda:us-east-1:123456789012:function:${t[e]||t.postgres}`}getRotation(e){return this.rotations.get(e)}listRotations(){return Array.from(this.rotations.values())}getSchedule(e){return this.schedules.get(e)}listSchedules(){return Array.from(this.schedules.values())}generateRotationCF(e){return{RotationEnabled:e.rotationEnabled,RotationRules:{AutomaticallyAfterDays:e.rotationDays},...e.rotationLambdaArn&&{RotationLambdaARN:e.rotationLambdaArn}}}generateRotationLambdaCF(e){return{Type:"AWS::Lambda::Function",Properties:{FunctionName:e.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"}},...e.vpcConfig&&{VpcConfig:{SubnetIds:e.vpcConfig.subnetIds,SecurityGroupIds:e.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(e){return{Type:"AWS::Events::Rule",Properties:{Name:e.name,Description:`Rotation schedule for ${e.secrets.length} secrets`,ScheduleExpression:e.schedule,State:e.enabled?"ENABLED":"DISABLED",Targets:[{Arn:{"Fn::GetAtt":["RotationStateMachine","Arn"]},RoleArn:{"Fn::GetAtt":["EventBridgeRotationRole","Arn"]},Input:JSON.stringify({secrets:e.secrets})}]}}}clear(){this.rotations.clear(),this.schedules.clear(),this.rotationCounter=0,this.scheduleCounter=0}}var Mm=new Vr;class Ur{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(e){let t=`version-${Date.now()}-${this.versionCounter++}`,a={id:t,...e};return this.versions.set(t,a),this.auditAction({secretId:e.secretId,action:"CREATE",actor:"system",versionId:e.versionId,success:!0}),a}getVersionByStage(e,t){return Array.from(this.versions.values()).find((a)=>a.secretId===e&&a.versionStages.includes(t))}listVersions(e){return Array.from(this.versions.values()).filter((t)=>t.secretId===e).sort((t,a)=>a.createdAt.getTime()-t.createdAt.getTime())}deprecateVersion(e){let t=Array.from(this.versions.values()).find((a)=>a.versionId===e);if(t)t.deprecatedAt=new Date,t.versionStages=t.versionStages.filter((a)=>a!=="AWSCURRENT"),this.auditAction({secretId:t.secretId,action:"UPDATE",actor:"system",versionId:e,success:!0})}restoreVersion(e){let t=Array.from(this.versions.values()).find((a)=>a.versionId===e);if(t)Array.from(this.versions.values()).filter((a)=>a.secretId===t.secretId&&a.versionId!==e).forEach((a)=>{a.versionStages=a.versionStages.filter((r)=>r!=="AWSCURRENT")}),t.versionStages.push("AWSCURRENT"),t.deprecatedAt=void 0,this.auditAction({secretId:t.secretId,action:"RESTORE",actor:"system",versionId:e,success:!0})}auditAction(e){let t=`audit-${Date.now()}-${this.auditCounter++}`,a={id:t,timestamp:new Date,...e};return this.audits.set(t,a),a}getAuditTrail(e,t=100){return Array.from(this.audits.values()).filter((a)=>a.secretId===e).sort((a,r)=>r.timestamp.getTime()-a.timestamp.getTime()).slice(0,t)}getFailedAccesses(e,t=24){let a=Date.now()-t*60*60*1000;return Array.from(this.audits.values()).filter((r)=>r.secretId===e&&!r.success&&r.timestamp.getTime()>a)}registerExternalManager(e){let t=`ext-manager-${Date.now()}-${this.managerCounter++}`,a={id:t,...e};return this.externalManagers.set(t,a),a}registerVault(e){return this.registerExternalManager({type:"vault",name:e.name,endpoint:e.endpoint,authentication:{type:e.token?"token":"iam",credentials:e.token?{token:e.token}:void 0,roleArn:e.roleArn},syncEnabled:e.syncEnabled||!1,syncInterval:60})}registerOnePassword(e){return this.registerExternalManager({type:"onepassword",name:e.name,endpoint:e.endpoint||"https://my.1password.com",authentication:{type:"apikey",credentials:{apiKey:e.apiKey}},syncEnabled:e.syncEnabled||!1,syncInterval:30})}enableReplication(e){let t=`replication-${Date.now()}-${this.replicationCounter++}`,a={id:t,secretId:e.secretId,sourceRegion:e.sourceRegion,replicaRegions:e.replicaRegions,kmsKeyIds:e.kmsKeyIds,status:"replicating"};return this.replications.set(t,a),this.auditAction({secretId:e.secretId,action:"REPLICATE",actor:"system",success:!0}),setTimeout(()=>{a.status="completed"},100),a}createPolicy(e){let t=`policy-${Date.now()}-${this.policyCounter++}`,a={id:t,secretId:e.secretId,policy:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:e.allowedPrincipals},Action:e.allowedActions,Resource:"*"}]}};return this.policies.set(t,a),a}createCrossAccountPolicy(e){let t=e.roleNames.map((a)=>`arn:aws:iam::${e.accountId}:role/${a}`);return this.createPolicy({secretId:e.secretId,allowedPrincipals:t,allowedActions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"]})}getVersion(e){return this.versions.get(e)}getExternalManager(e){return this.externalManagers.get(e)}listExternalManagers(){return Array.from(this.externalManagers.values())}getReplication(e){return this.replications.get(e)}listReplications(){return Array.from(this.replications.values())}generateSecretCF(e){return{Type:"AWS::SecretsManager::Secret",Properties:{Name:e.name,Description:e.description,...e.kmsKeyId&&{KmsKeyId:e.kmsKeyId},...e.replicaRegions&&{ReplicaRegions:e.replicaRegions.map((t)=>({Region:t}))}}}}generateSecretPolicyCF(e){return{Type:"AWS::SecretsManager::ResourcePolicy",Properties:{SecretId:e.secretId,ResourcePolicy:e.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 xm=new Ur;class jr{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(e){let t=`cert-${Date.now()}-${this.certificateCounter++}`,a=`arn:aws:acm:us-east-1:123456789012:certificate/${t}`,r={id:t,arn:a,domainName:e.domainName,subjectAlternativeNames:e.subjectAlternativeNames,validationMethod:e.validationMethod||"DNS",status:"PENDING_VALIDATION"};return this.certificates.set(t,r),this.createValidation(r),r}requestWildcardCertificate(e){let t=[];if(e.includeApex)t.push(e.domainName.replace("*.",""));return this.requestCertificate({domainName:e.domainName,subjectAlternativeNames:t.length>0?t:void 0,validationMethod:"DNS"})}requestMultiDomainCertificate(e){return this.requestCertificate({domainName:e.primaryDomain,subjectAlternativeNames:e.additionalDomains,validationMethod:e.validationMethod||"DNS"})}createValidation(e){let t={domainName:e.domainName,validationMethod:e.validationMethod,validationStatus:"PENDING"};if(e.validationMethod==="DNS")t.resourceRecords=[{name:`_${Math.random().toString(36).slice(2)}.${e.domainName}`,type:"CNAME",value:`_${Math.random().toString(36).slice(2)}.acm-validations.aws.`}];else t.validationEmails=[`admin@${e.domainName}`,`administrator@${e.domainName}`,`hostmaster@${e.domainName}`];return this.validations.set(e.id,t),t}validateCertificate(e){let t=this.certificates.get(e),a=this.validations.get(e);if(!t||!a)return{success:!1,message:"Certificate or validation not found"};return a.validationStatus="SUCCESS",t.status="ISSUED",t.issuedAt=new Date,t.expiresAt=new Date(Date.now()+31536000000),t.renewalEligibility=!0,t.issuer="Amazon",{success:!0,message:"Certificate validated and issued successfully"}}enableAutoRenewal(e){let t=`renewal-${Date.now()}-${this.renewalCounter++}`,a={id:t,certificateArn:e.certificateArn,autoRenew:!0,renewBeforeDays:e.renewBeforeDays||30};return this.renewals.set(t,a),a}async renewCertificate(e){let t=this.renewals.get(e);if(!t)return{success:!1,message:"Renewal configuration not found"};let a=Array.from(this.certificates.values()).find((r)=>r.arn===t.certificateArn);if(!a)return{success:!1,message:"Certificate not found"};console.log(`
3775
+ ✗ Rotation failed:`,a),{success:!1,secretId:t.secretId,oldVersion:"unknown",newVersion:"unknown",rotatedAt:new Date,error:a instanceof Error?a.message:String(a)}}}needsRotation(e){let t=this.rotations.get(e);if(!t||!t.rotationEnabled)return!1;if(!t.lastRotated)return!0;return(Date.now()-t.lastRotated.getTime())/86400000>=t.rotationDays}getSecretsNeedingRotation(){return Array.from(this.rotations.values()).filter((e)=>this.needsRotation(e.id))}generateRDSRotationLambdaArn(e){let t={postgres:"SecretsManagerRDSPostgreSQLRotationSingleUser",mysql:"SecretsManagerRDSMySQLRotationSingleUser",sqlserver:"SecretsManagerRDSSQLServerRotationSingleUser",oracle:"SecretsManagerRDSOracleRotationSingleUser"};return`arn:aws:lambda:us-east-1:123456789012:function:${t[e]||t.postgres}`}getRotation(e){return this.rotations.get(e)}listRotations(){return Array.from(this.rotations.values())}getSchedule(e){return this.schedules.get(e)}listSchedules(){return Array.from(this.schedules.values())}generateRotationCF(e){return{RotationEnabled:e.rotationEnabled,RotationRules:{AutomaticallyAfterDays:e.rotationDays},...e.rotationLambdaArn&&{RotationLambdaARN:e.rotationLambdaArn}}}generateRotationLambdaCF(e){return{Type:"AWS::Lambda::Function",Properties:{FunctionName:e.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"}},...e.vpcConfig&&{VpcConfig:{SubnetIds:e.vpcConfig.subnetIds,SecurityGroupIds:e.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(e){return{Type:"AWS::Events::Rule",Properties:{Name:e.name,Description:`Rotation schedule for ${e.secrets.length} secrets`,ScheduleExpression:e.schedule,State:e.enabled?"ENABLED":"DISABLED",Targets:[{Arn:{"Fn::GetAtt":["RotationStateMachine","Arn"]},RoleArn:{"Fn::GetAtt":["EventBridgeRotationRole","Arn"]},Input:JSON.stringify({secrets:e.secrets})}]}}}clear(){this.rotations.clear(),this.schedules.clear(),this.rotationCounter=0,this.scheduleCounter=0}}var Lm=new Vr;class Fr{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(e){let t=`version-${Date.now()}-${this.versionCounter++}`,a={id:t,...e};return this.versions.set(t,a),this.auditAction({secretId:e.secretId,action:"CREATE",actor:"system",versionId:e.versionId,success:!0}),a}getVersionByStage(e,t){return Array.from(this.versions.values()).find((a)=>a.secretId===e&&a.versionStages.includes(t))}listVersions(e){return Array.from(this.versions.values()).filter((t)=>t.secretId===e).sort((t,a)=>a.createdAt.getTime()-t.createdAt.getTime())}deprecateVersion(e){let t=Array.from(this.versions.values()).find((a)=>a.versionId===e);if(t)t.deprecatedAt=new Date,t.versionStages=t.versionStages.filter((a)=>a!=="AWSCURRENT"),this.auditAction({secretId:t.secretId,action:"UPDATE",actor:"system",versionId:e,success:!0})}restoreVersion(e){let t=Array.from(this.versions.values()).find((a)=>a.versionId===e);if(t)Array.from(this.versions.values()).filter((a)=>a.secretId===t.secretId&&a.versionId!==e).forEach((a)=>{a.versionStages=a.versionStages.filter((r)=>r!=="AWSCURRENT")}),t.versionStages.push("AWSCURRENT"),t.deprecatedAt=void 0,this.auditAction({secretId:t.secretId,action:"RESTORE",actor:"system",versionId:e,success:!0})}auditAction(e){let t=`audit-${Date.now()}-${this.auditCounter++}`,a={id:t,timestamp:new Date,...e};return this.audits.set(t,a),a}getAuditTrail(e,t=100){return Array.from(this.audits.values()).filter((a)=>a.secretId===e).sort((a,r)=>r.timestamp.getTime()-a.timestamp.getTime()).slice(0,t)}getFailedAccesses(e,t=24){let a=Date.now()-t*60*60*1000;return Array.from(this.audits.values()).filter((r)=>r.secretId===e&&!r.success&&r.timestamp.getTime()>a)}registerExternalManager(e){let t=`ext-manager-${Date.now()}-${this.managerCounter++}`,a={id:t,...e};return this.externalManagers.set(t,a),a}registerVault(e){return this.registerExternalManager({type:"vault",name:e.name,endpoint:e.endpoint,authentication:{type:e.token?"token":"iam",credentials:e.token?{token:e.token}:void 0,roleArn:e.roleArn},syncEnabled:e.syncEnabled||!1,syncInterval:60})}registerOnePassword(e){return this.registerExternalManager({type:"onepassword",name:e.name,endpoint:e.endpoint||"https://my.1password.com",authentication:{type:"apikey",credentials:{apiKey:e.apiKey}},syncEnabled:e.syncEnabled||!1,syncInterval:30})}enableReplication(e){let t=`replication-${Date.now()}-${this.replicationCounter++}`,a={id:t,secretId:e.secretId,sourceRegion:e.sourceRegion,replicaRegions:e.replicaRegions,kmsKeyIds:e.kmsKeyIds,status:"replicating"};return this.replications.set(t,a),this.auditAction({secretId:e.secretId,action:"REPLICATE",actor:"system",success:!0}),setTimeout(()=>{a.status="completed"},100),a}createPolicy(e){let t=`policy-${Date.now()}-${this.policyCounter++}`,a={id:t,secretId:e.secretId,policy:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:e.allowedPrincipals},Action:e.allowedActions,Resource:"*"}]}};return this.policies.set(t,a),a}createCrossAccountPolicy(e){let t=e.roleNames.map((a)=>`arn:aws:iam::${e.accountId}:role/${a}`);return this.createPolicy({secretId:e.secretId,allowedPrincipals:t,allowedActions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"]})}getVersion(e){return this.versions.get(e)}getExternalManager(e){return this.externalManagers.get(e)}listExternalManagers(){return Array.from(this.externalManagers.values())}getReplication(e){return this.replications.get(e)}listReplications(){return Array.from(this.replications.values())}generateSecretCF(e){return{Type:"AWS::SecretsManager::Secret",Properties:{Name:e.name,Description:e.description,...e.kmsKeyId&&{KmsKeyId:e.kmsKeyId},...e.replicaRegions&&{ReplicaRegions:e.replicaRegions.map((t)=>({Region:t}))}}}}generateSecretPolicyCF(e){return{Type:"AWS::SecretsManager::ResourcePolicy",Properties:{SecretId:e.secretId,ResourcePolicy:e.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 xm=new Fr;class jr{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(e){let t=`cert-${Date.now()}-${this.certificateCounter++}`,a=`arn:aws:acm:us-east-1:123456789012:certificate/${t}`,r={id:t,arn:a,domainName:e.domainName,subjectAlternativeNames:e.subjectAlternativeNames,validationMethod:e.validationMethod||"DNS",status:"PENDING_VALIDATION"};return this.certificates.set(t,r),this.createValidation(r),r}requestWildcardCertificate(e){let t=[];if(e.includeApex)t.push(e.domainName.replace("*.",""));return this.requestCertificate({domainName:e.domainName,subjectAlternativeNames:t.length>0?t:void 0,validationMethod:"DNS"})}requestMultiDomainCertificate(e){return this.requestCertificate({domainName:e.primaryDomain,subjectAlternativeNames:e.additionalDomains,validationMethod:e.validationMethod||"DNS"})}createValidation(e){let t={domainName:e.domainName,validationMethod:e.validationMethod,validationStatus:"PENDING"};if(e.validationMethod==="DNS")t.resourceRecords=[{name:`_${Math.random().toString(36).slice(2)}.${e.domainName}`,type:"CNAME",value:`_${Math.random().toString(36).slice(2)}.acm-validations.aws.`}];else t.validationEmails=[`admin@${e.domainName}`,`administrator@${e.domainName}`,`hostmaster@${e.domainName}`];return this.validations.set(e.id,t),t}validateCertificate(e){let t=this.certificates.get(e),a=this.validations.get(e);if(!t||!a)return{success:!1,message:"Certificate or validation not found"};return a.validationStatus="SUCCESS",t.status="ISSUED",t.issuedAt=new Date,t.expiresAt=new Date(Date.now()+31536000000),t.renewalEligibility=!0,t.issuer="Amazon",{success:!0,message:"Certificate validated and issued successfully"}}enableAutoRenewal(e){let t=`renewal-${Date.now()}-${this.renewalCounter++}`,a={id:t,certificateArn:e.certificateArn,autoRenew:!0,renewBeforeDays:e.renewBeforeDays||30};return this.renewals.set(t,a),a}async renewCertificate(e){let t=this.renewals.get(e);if(!t)return{success:!1,message:"Renewal configuration not found"};let a=Array.from(this.certificates.values()).find((r)=>r.arn===t.certificateArn);if(!a)return{success:!1,message:"Certificate not found"};console.log(`
3776
3776
  Renewing certificate: ${a.domainName}`),console.log(`Certificate ARN: ${a.arn}`);try{return console.log(`
3777
3777
  1. Requesting new certificate...`),console.log("2. Validating domain ownership..."),console.log("3. Issuing renewed certificate..."),console.log("4. Updating resource associations..."),a.issuedAt=new Date,a.expiresAt=new Date(Date.now()+31536000000),t.lastRenewal=new Date,t.renewalStatus="success",t.nextRenewal=new Date(a.expiresAt.getTime()-t.renewBeforeDays*24*60*60*1000),console.log(`
3778
3778
  ✓ Certificate renewed successfully`),console.log(` New expiration: ${a.expiresAt.toISOString()}`),console.log(` Next renewal: ${t.nextRenewal.toISOString()}`),{success:!0,message:"Certificate renewed successfully"}}catch(r){return t.renewalStatus="failed",this.createAlert({certificateArn:a.arn,alertType:"renewal_failed",severity:"critical",message:`Certificate renewal failed: ${r}`}),{success:!1,message:r instanceof Error?r.message:String(r)}}}createMonitor(e){let t=`monitor-${Date.now()}-${this.monitorCounter++}`,a={id:t,...e};return this.monitors.set(t,a),a}checkExpiration(){let e=[],t=Date.now();for(let a of this.certificates.values()){if(!a.expiresAt)continue;let r=(a.expiresAt.getTime()-t)/86400000;if(r<0)e.push(this.createAlert({certificateArn:a.arn,alertType:"expired",severity:"critical",message:`Certificate has expired for ${a.domainName}`}));else if(r<30)e.push(this.createAlert({certificateArn:a.arn,alertType:"expiring_soon",severity:r<7?"critical":"warning",message:`Certificate expiring in ${Math.floor(r)} days for ${a.domainName}`}))}return e}createAlert(e){let t=`alert-${Date.now()}-${this.alertCounter++}`,a={id:t,timestamp:new Date,acknowledged:!1,...e};return this.alerts.set(t,a),a}acknowledgeAlert(e){let t=this.alerts.get(e);if(t)t.acknowledged=!0}getCertificate(e){return this.certificates.get(e)}listCertificates(){return Array.from(this.certificates.values())}getExpiringCertificates(e=30){let t=Date.now()+e*24*60*60*1000;return Array.from(this.certificates.values()).filter((a)=>a.expiresAt&&a.expiresAt.getTime()<t)}getValidation(e){return this.validations.get(e)}getRenewal(e){return this.renewals.get(e)}listRenewals(){return Array.from(this.renewals.values())}listAlerts(e=!1){return Array.from(this.alerts.values()).filter((t)=>t.acknowledged===e)}generateCertificateCF(e){return{Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:e.domainName,...e.subjectAlternativeNames&&{SubjectAlternativeNames:e.subjectAlternativeNames},ValidationMethod:e.validationMethod}}}generateExpirationAlarmCF(e){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:e.alarmName,AlarmDescription:`Certificate expiring in ${e.daysBeforeExpiration} days`,MetricName:"DaysToExpiry",Namespace:"AWS/CertificateManager",Statistic:"Minimum",Period:86400,EvaluationPeriods:1,Threshold:e.daysBeforeExpiration,ComparisonOperator:"LessThanThreshold",Dimensions:[{Name:"CertificateArn",Value:e.certificateArn}],...e.snsTopicArn&&{AlarmActions:[e.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 Om=new jr;class Kr{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(e){let t=`scan-${Date.now()}-${this.scanCounter++}`,a={id:t,status:"queued",findings:[],...e};return this.scans.set(t,a),a}createContainerScan(e){return this.createScan({name:e.name,scanType:"container_image",target:{type:"ecr_image",identifier:e.imageUri,region:e.region||"us-east-1"}})}createLambdaScan(e){return this.createScan({name:e.name,scanType:"vulnerability",target:{type:"lambda",identifier:e.functionName,region:e.region||"us-east-1"}})}createSecretsDetectionScan(e){return this.createScan({name:e.name,scanType:"secrets_detection",target:{type:"repository",identifier:e.repositoryUrl}})}async executeScan(e){let t=this.scans.get(e);if(!t)throw Error(`Scan not found: ${e}`);console.log(`
3779
3779
  Executing security scan: ${t.name}`),console.log(`Scan type: ${t.scanType}`),console.log(`Target: ${t.target.type} - ${t.target.identifier}`),t.status="running",t.startedAt=new Date;try{console.log(`
3780
3780
  Scanning...`);let a=this.simulateFindings(t);return t.findings=a,t.status="completed",t.completedAt=new Date,t.summary={totalFindings:a.length,criticalCount:a.filter((r)=>r.severity==="CRITICAL").length,highCount:a.filter((r)=>r.severity==="HIGH").length,mediumCount:a.filter((r)=>r.severity==="MEDIUM").length,lowCount:a.filter((r)=>r.severity==="LOW").length,infoCount:a.filter((r)=>r.severity==="INFO").length,executionTime:t.completedAt.getTime()-t.startedAt.getTime()},console.log(`
3781
- ✓ Scan completed`),console.log(` Findings: ${t.summary.totalFindings}`),console.log(` Critical: ${t.summary.criticalCount}`),console.log(` High: ${t.summary.highCount}`),console.log(` Medium: ${t.summary.mediumCount}`),console.log(` Low: ${t.summary.lowCount}`),t}catch(a){throw t.status="failed",t.completedAt=new Date,a}}simulateFindings(e){let t=[],a=new Date;if(e.scanType==="container_image")t.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:e.target.identifier,remediation:"Update OpenSSL to version 1.1.1l or later",status:"OPEN",firstDetected:a,lastSeen:a})),t.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:e.target.identifier,remediation:"Update lodash to version 4.17.21 or later",status:"OPEN",firstDetected:a,lastSeen:a}));else if(e.scanType==="secrets_detection")t.push(this.createFinding({severity:"CRITICAL",title:"AWS Access Key exposed in code",description:"Hardcoded AWS access key found in source code",affectedResource:`${e.target.identifier}/src/config.ts:12`,remediation:"Remove hardcoded credentials and use AWS Secrets Manager",status:"OPEN",firstDetected:a,lastSeen:a}));return t}createFinding(e){let t=`finding-${Date.now()}-${this.findingCounter++}`,a={id:t,...e};return this.findings.set(t,a),a}suppressFinding(e,t){let a=this.findings.get(e);if(a){if(a.status="SUPPRESSED",console.log(`Finding suppressed: ${a.title}`),t)console.log(`Reason: ${t}`)}}resolveFinding(e){let t=this.findings.get(e);if(t)t.status="RESOLVED",console.log(`Finding resolved: ${t.title}`)}generateReport(e){let t=`report-${Date.now()}-${this.reportCounter++}`,a={id:t,scanId:e.scanId,reportType:e.reportType,format:e.format,generatedAt:new Date,s3Location:`s3://security-reports/${t}.${e.format}`};return this.reports.set(t,a),a}runComplianceCheck(e){let t=[];if(e.framework.includes("CIS"))t.push(this.createComplianceCheck({framework:e.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:e.resourceType,resourceId:e.resourceId})),t.push(this.createComplianceCheck({framework:e.framework,checkId:"2.1",title:"Ensure CloudTrail is enabled",description:"CloudTrail should be enabled in all regions",status:"FAIL",severity:"HIGH",resourceType:e.resourceType,resourceId:e.resourceId,remediation:"Enable CloudTrail in all regions"}));return t}createComplianceCheck(e){let t=`check-${Date.now()}-${this.checkCounter++}`,a={id:t,...e};return this.complianceChecks.set(t,a),a}assessSecurityPosture(e){let t=`posture-${Date.now()}-${this.postureCounter++}`,a=Array.from(this.complianceChecks.values()),r=a.filter((c)=>c.status==="PASS").length,n=a.length,i=n>0?Math.round(r/n*100):0,s;if(i>=90)s="A";else if(i>=80)s="B";else if(i>=70)s="C";else if(i>=60)s="D";else s="F";let o={id:t,accountId:e.accountId,region:e.region,score:i,grade:s,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(t,o),o}getScan(e){return this.scans.get(e)}listScans(){return Array.from(this.scans.values())}getOpenFindings(e){return Array.from(this.findings.values()).filter((t)=>t.status==="OPEN"&&(!e||t.severity===e))}getComplianceChecksByStatus(e){return Array.from(this.complianceChecks.values()).filter((t)=>t.status===e)}listPostures(){return Array.from(this.postures.values())}generateECRScanCF(e){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:e,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 Bm=new Kr;class Hr{configs=new Map;results=new Map;policies=new Map;configCounter=0;resultCounter=0;policyCounter=0;configureScan(e){let t=`scan-config-${Date.now()}-${this.configCounter++}`,a={id:t,...e};return this.configs.set(t,a),a}configureTrivyScan(e){return this.configureScan({repository:e.repository,imageTag:e.imageTag,scanner:"trivy",scanOnPush:e.scanOnPush??!0,ignoreUnfixed:e.ignoreUnfixed??!1,failOnSeverity:"HIGH"})}configureSnykScan(e){return this.configureScan({repository:e.repository,imageTag:e.imageTag,scanner:"snyk",scanOnPush:e.scanOnPush??!0,failOnSeverity:"HIGH"})}configureECRScan(e){return this.configureScan({repository:e.repository,imageTag:"latest",scanner:"ecr",scanOnPush:e.scanOnPush??!0,failOnSeverity:"CRITICAL"})}async scanImage(e){let t=this.configs.get(e);if(!t)throw Error(`Scan config not found: ${e}`);let a=`${t.repository}:${t.imageTag}`;console.log(`
3781
+ ✓ Scan completed`),console.log(` Findings: ${t.summary.totalFindings}`),console.log(` Critical: ${t.summary.criticalCount}`),console.log(` High: ${t.summary.highCount}`),console.log(` Medium: ${t.summary.mediumCount}`),console.log(` Low: ${t.summary.lowCount}`),t}catch(a){throw t.status="failed",t.completedAt=new Date,a}}simulateFindings(e){let t=[],a=new Date;if(e.scanType==="container_image")t.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:e.target.identifier,remediation:"Update OpenSSL to version 1.1.1l or later",status:"OPEN",firstDetected:a,lastSeen:a})),t.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:e.target.identifier,remediation:"Update lodash to version 4.17.21 or later",status:"OPEN",firstDetected:a,lastSeen:a}));else if(e.scanType==="secrets_detection")t.push(this.createFinding({severity:"CRITICAL",title:"AWS Access Key exposed in code",description:"Hardcoded AWS access key found in source code",affectedResource:`${e.target.identifier}/src/config.ts:12`,remediation:"Remove hardcoded credentials and use AWS Secrets Manager",status:"OPEN",firstDetected:a,lastSeen:a}));return t}createFinding(e){let t=`finding-${Date.now()}-${this.findingCounter++}`,a={id:t,...e};return this.findings.set(t,a),a}suppressFinding(e,t){let a=this.findings.get(e);if(a){if(a.status="SUPPRESSED",console.log(`Finding suppressed: ${a.title}`),t)console.log(`Reason: ${t}`)}}resolveFinding(e){let t=this.findings.get(e);if(t)t.status="RESOLVED",console.log(`Finding resolved: ${t.title}`)}generateReport(e){let t=`report-${Date.now()}-${this.reportCounter++}`,a={id:t,scanId:e.scanId,reportType:e.reportType,format:e.format,generatedAt:new Date,s3Location:`s3://security-reports/${t}.${e.format}`};return this.reports.set(t,a),a}runComplianceCheck(e){let t=[];if(e.framework.includes("CIS"))t.push(this.createComplianceCheck({framework:e.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:e.resourceType,resourceId:e.resourceId})),t.push(this.createComplianceCheck({framework:e.framework,checkId:"2.1",title:"Ensure CloudTrail is enabled",description:"CloudTrail should be enabled in all regions",status:"FAIL",severity:"HIGH",resourceType:e.resourceType,resourceId:e.resourceId,remediation:"Enable CloudTrail in all regions"}));return t}createComplianceCheck(e){let t=`check-${Date.now()}-${this.checkCounter++}`,a={id:t,...e};return this.complianceChecks.set(t,a),a}assessSecurityPosture(e){let t=`posture-${Date.now()}-${this.postureCounter++}`,a=Array.from(this.complianceChecks.values()),r=a.filter((c)=>c.status==="PASS").length,n=a.length,i=n>0?Math.round(r/n*100):0,s;if(i>=90)s="A";else if(i>=80)s="B";else if(i>=70)s="C";else if(i>=60)s="D";else s="F";let o={id:t,accountId:e.accountId,region:e.region,score:i,grade:s,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(t,o),o}getScan(e){return this.scans.get(e)}listScans(){return Array.from(this.scans.values())}getOpenFindings(e){return Array.from(this.findings.values()).filter((t)=>t.status==="OPEN"&&(!e||t.severity===e))}getComplianceChecksByStatus(e){return Array.from(this.complianceChecks.values()).filter((t)=>t.status===e)}listPostures(){return Array.from(this.postures.values())}generateECRScanCF(e){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:e,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 Wm=new Kr;class Hr{configs=new Map;results=new Map;policies=new Map;configCounter=0;resultCounter=0;policyCounter=0;configureScan(e){let t=`scan-config-${Date.now()}-${this.configCounter++}`,a={id:t,...e};return this.configs.set(t,a),a}configureTrivyScan(e){return this.configureScan({repository:e.repository,imageTag:e.imageTag,scanner:"trivy",scanOnPush:e.scanOnPush??!0,ignoreUnfixed:e.ignoreUnfixed??!1,failOnSeverity:"HIGH"})}configureSnykScan(e){return this.configureScan({repository:e.repository,imageTag:e.imageTag,scanner:"snyk",scanOnPush:e.scanOnPush??!0,failOnSeverity:"HIGH"})}configureECRScan(e){return this.configureScan({repository:e.repository,imageTag:"latest",scanner:"ecr",scanOnPush:e.scanOnPush??!0,failOnSeverity:"CRITICAL"})}async scanImage(e){let t=this.configs.get(e);if(!t)throw Error(`Scan config not found: ${e}`);let a=`${t.repository}:${t.imageTag}`;console.log(`
3782
3782
  Scanning image: ${a}`),console.log(`Scanner: ${t.scanner}`);let r=`scan-result-${Date.now()}-${this.resultCounter++}`,n=this.simulateVulnerabilities(t),i={total:n.length,critical:n.filter((c)=>c.severity==="CRITICAL").length,high:n.filter((c)=>c.severity==="HIGH").length,medium:n.filter((c)=>c.severity==="MEDIUM").length,low:n.filter((c)=>c.severity==="LOW").length,unknown:n.filter((c)=>c.severity==="UNKNOWN").length},s=this.evaluateScanResult(t,i),o={id:r,imageUri:a,scannerType:t.scanner,scanDate:new Date,vulnerabilities:n,summary:i,passed:s};return this.results.set(r,o),console.log(`
3783
3783
  Scan Results:`),console.log(` Total vulnerabilities: ${i.total}`),console.log(` Critical: ${i.critical}`),console.log(` High: ${i.high}`),console.log(` Medium: ${i.medium}`),console.log(` Low: ${i.low}`),console.log(` Status: ${s?"✓ PASSED":"✗ FAILED"}`),o}simulateVulnerabilities(e){let t=[];if(e.scanner==="trivy"||e.scanner==="ecr")t.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}),t.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 t}evaluateScanResult(e,t){if(!e.failOnSeverity)return!0;switch(e.failOnSeverity){case"CRITICAL":return t.critical===0;case"HIGH":return t.critical===0&&t.high===0;case"MEDIUM":return t.critical===0&&t.high===0&&t.medium===0;case"LOW":return t.total===0;default:return!0}}createPolicy(e){let t=`policy-${Date.now()}-${this.policyCounter++}`,a={id:t,...e};return this.policies.set(t,a),a}createStrictPolicy(e){return this.createPolicy({name:e,allowedSeverities:[],maxCritical:0,maxHigh:0,blockOnFailure:!0,exemptions:[]})}createPermissivePolicy(e){return this.createPolicy({name:e,allowedSeverities:["CRITICAL","HIGH","MEDIUM","LOW"],maxCritical:5,maxHigh:10,blockOnFailure:!1,exemptions:[]})}getConfig(e){return this.configs.get(e)}listConfigs(){return Array.from(this.configs.values())}getResult(e){return this.results.get(e)}listResults(){return Array.from(this.results.values())}generateECRScanCF(e){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:e.repository,ImageScanningConfiguration:{ScanOnPush:e.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 _m=new Hr;class qr{configs=new Map;multiStageConfigs=new Map;optimizations=new Map;analyses=new Map;configCounter=0;multiStageCounter=0;optimizationCounter=0;analysisCounter=0;createBuildConfig(e){let t=`build-config-${Date.now()}-${this.configCounter++}`,a={id:t,...e};return this.configs.set(t,a),a}createOptimizedBuildConfig(e){let t={type:e.enableCache?"registry":"inline",cacheFrom:e.registry?[`${e.registry}/cache`]:void 0,cacheTo:e.registry?`${e.registry}/cache`:void 0,maxCacheAge:7};return this.createBuildConfig({name:e.name,dockerfile:e.dockerfile,context:".",cacheStrategy:t,buildArgs:{BUILDKIT_INLINE_CACHE:"1"}})}createMultiStageConfig(e){let t=`multi-stage-${Date.now()}-${this.multiStageCounter++}`,a={id:t,...e};return this.multiStageConfigs.set(t,a),a}createNodeMultiStageBuild(e){let t=e.nodeVersion||"18-alpine";return this.createMultiStageConfig({name:e.name,targetStage:e.targetStage||"production",stages:[{name:"dependencies",baseImage:`node:${t}`,workdir:"/app",commands:["COPY package*.json ./","RUN npm ci --only=production"]},{name:"build",baseImage:`node:${t}`,workdir:"/app",commands:["COPY package*.json ./","RUN npm ci","COPY . .","RUN npm run build"]},{name:"production",baseImage:`node:${t}`,workdir:"/app",copyFrom:["dependencies:/app/node_modules","build:/app/dist"],commands:["COPY package*.json ./","ENV NODE_ENV=production",'CMD ["node", "dist/index.js"]']}]})}generateDockerfile(e){let t=this.multiStageConfigs.get(e);if(!t)throw Error(`Multi-stage config not found: ${e}`);let a=[];for(let r of t.stages){if(a.push(`# Stage: ${r.name}`),a.push(`FROM ${r.baseImage} AS ${r.name}`),r.workdir)a.push(`WORKDIR ${r.workdir}`);if(r.env)for(let[n,i]of Object.entries(r.env))a.push(`ENV ${n}=${i}`);for(let n of r.commands)a.push(n);a.push("")}return a.join(`
3784
3784
  `)}analyzeImage(e,t){let a=`analysis-${Date.now()}-${this.analysisCounter++}`,r=t.map((o)=>({...o,cacheable:this.isLayerCacheable(o.command)})),n=r.reduce((o,c)=>o+c.size,0),i=r.filter((o)=>!o.cacheable&&o.size>100).length,s={id:a,imageId:e,layers:r,totalSize:n,unnecessaryLayers:i};return this.analyses.set(a,s),s}isLayerCacheable(e){let t=["FROM","RUN","COPY","ADD","WORKDIR","ENV"],a=["CMD","ENTRYPOINT","LABEL"];for(let r of t)if(e.startsWith(r))return!0;for(let r of a)if(e.startsWith(r))return!1;return!1}generateOptimizations(e){let t=this.analyses.get(e);if(!t)throw Error(`Analysis not found: ${e}`);let a=`optimization-${Date.now()}-${this.optimizationCounter++}`,r=[],n=t.layers.filter((l)=>l.command.startsWith("RUN"));if(n.length>5)r.push({type:"layer_reduction",priority:"high",title:"Combine RUN commands",description:`${n.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 i=t.layers[0];if(i.command.includes("ubuntu")||i.command.includes("debian"))r.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 s=t.layers.filter((l)=>l.command.startsWith("COPY"));if(s.length>0&&s[0].index>3)r.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 ./
3785
3785
  RUN npm install
3786
- COPY . .`,impact:"Improve build time by 60-80% on subsequent builds"});let o={sizeBefore:t.totalSize,sizeAfter:t.totalSize*0.6,timeBefore:300,timeAfter:120},c={id:a,name:`Optimization for ${t.imageId}`,recommendations:r,estimatedSavings:o};return this.optimizations.set(a,c),c}getBuildConfig(e){return this.configs.get(e)}listBuildConfigs(){return Array.from(this.configs.values())}getMultiStageConfig(e){return this.multiStageConfigs.get(e)}listMultiStageConfigs(){return Array.from(this.multiStageConfigs.values())}getOptimization(e){return this.optimizations.get(e)}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 Wm=new qr;class zr{registries=new Map;credentials=new Map;registryCounter=0;credentialsCounter=0;createRegistry(e){let t=`registry-${Date.now()}-${this.registryCounter++}`,a={id:t,...e};return this.registries.set(t,a),a}createECRRepository(e){return this.createRegistry({name:e.name,registryType:"ecr",repositoryUri:`123456789012.dkr.ecr.${e.region||"us-east-1"}.amazonaws.com/${e.name}`,region:e.region||"us-east-1",encryption:{encryptionType:e.encryption||"AES256",kmsKeyId:e.kmsKeyId},scanning:{scanOnPush:e.scanOnPush??!0}})}createManagedRepository(e){let t=this.createECRRepository({name:e.name,region:e.region,scanOnPush:!0,encryption:"KMS"});return t.lifecycle={id:`lifecycle-${Date.now()}`,rules:[{rulePriority:1,description:"Keep only last N images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:e.maxImageCount||10},action:{type:"expire"}},{rulePriority:2,description:"Remove images older than N days",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:e.maxImageAgeDays||30,countUnit:"days"},action:{type:"expire"}}]},t}enableReplication(e,t){let a=this.registries.get(e);if(!a)throw Error(`Registry not found: ${e}`);return a.replication={enabled:!0,destinations:t},a}createCredentials(e){let t=`creds-${Date.now()}-${this.credentialsCounter++}`,a={id:t,...e};return this.credentials.set(t,a),a}getRegistry(e){return this.registries.get(e)}listRegistries(){return Array.from(this.registries.values())}generateECRRepositoryCF(e){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:e.name,ImageScanningConfiguration:{ScanOnPush:e.scanning?.scanOnPush??!1},EncryptionConfiguration:{EncryptionType:e.encryption?.encryptionType||"AES256",...e.encryption?.kmsKeyId&&{KmsKey:e.encryption.kmsKeyId}},ImageTagMutability:"MUTABLE",...e.lifecycle&&{LifecyclePolicy:{LifecyclePolicyText:JSON.stringify({rules:e.lifecycle.rules})}}}}}generateReplicationConfigCF(e){return{Type:"AWS::ECR::ReplicationConfiguration",Properties:{ReplicationConfiguration:{Rules:e.destinations.map((t)=>({Destinations:[{Region:t.region,...t.registryId&&{RegistryId:t.registryId}}]}))}}}}clear(){this.registries.clear(),this.credentials.clear(),this.registryCounter=0,this.credentialsCounter=0}}var Gm=new zr;class Qr{meshes=new Map;virtualNodes=new Map;virtualRouters=new Map;virtualGateways=new Map;meshCounter=0;nodeCounter=0;routerCounter=0;gatewayCounter=0;createMesh(e){let t=`mesh-${Date.now()}-${this.meshCounter++}`,a={id:t,...e};return this.meshes.set(t,a),a}createAppMesh(e){return this.createMesh({name:e.name,meshType:"app_mesh",services:e.services,virtualNodes:[],virtualRouters:[],virtualGateways:[]})}createVirtualNode(e){let t=`vnode-${Date.now()}-${this.nodeCounter++}`,a={id:t,...e};return this.virtualNodes.set(t,a),a}createHTTPVirtualNode(e){return this.createVirtualNode({name:e.name,serviceName:e.serviceName,listeners:[{port:e.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:e.namespace,serviceName:e.serviceName}})}createVirtualRouter(e){let t=`vrouter-${Date.now()}-${this.routerCounter++}`,a={id:t,...e};return this.virtualRouters.set(t,a),a}createCanaryRoute(e){return this.createVirtualRouter({name:e.name,listeners:[{port:e.port,protocol:e.protocol}],routes:[{name:"canary-route",match:{prefix:"/"},action:{weightedTargets:[{virtualNode:e.stableTarget,weight:100-e.canaryWeight},{virtualNode:e.canaryTarget,weight:e.canaryWeight}]},retryPolicy:{maxRetries:3,perRetryTimeout:5000,httpRetryEvents:["server-error","gateway-error"],tcpRetryEvents:["connection-error"]}}]})}createVirtualGateway(e){let t=`vgateway-${Date.now()}-${this.gatewayCounter++}`,a={id:t,...e};return this.virtualGateways.set(t,a),a}createIngressGateway(e){let t={port:e.port,protocol:"http",healthCheck:{protocol:"http",path:"/health",interval:30,timeout:10,healthyThreshold:2,unhealthyThreshold:3}};if(e.enableTLS&&e.certificateArn)t.tls={mode:"STRICT",certificate:{acm:e.certificateArn}};return this.createVirtualGateway({name:e.name,listeners:[t],logging:{accessLog:{file:{path:"/dev/stdout"}}}})}getMesh(e){return this.meshes.get(e)}listMeshes(){return Array.from(this.meshes.values())}getVirtualNode(e){return this.virtualNodes.get(e)}listVirtualNodes(){return Array.from(this.virtualNodes.values())}generateMeshCF(e){return{Type:"AWS::AppMesh::Mesh",Properties:{MeshName:e.name,Spec:{EgressFilter:{Type:"ALLOW_ALL"}}}}}generateVirtualNodeCF(e,t){return{Type:"AWS::AppMesh::VirtualNode",Properties:{MeshName:t,VirtualNodeName:e.name,Spec:{Listeners:e.listeners.map((a)=>({PortMapping:{Port:a.port,Protocol:a.protocol},...a.healthCheck&&{HealthCheck:{Protocol:a.healthCheck.protocol,...a.healthCheck.path&&{Path:a.healthCheck.path},IntervalMillis:a.healthCheck.interval*1000,TimeoutMillis:a.healthCheck.timeout*1000,HealthyThreshold:a.healthCheck.healthyThreshold,UnhealthyThreshold:a.healthCheck.unhealthyThreshold}}})),ServiceDiscovery:{AWSCloudMap:{NamespaceName:e.serviceDiscovery.namespace,ServiceName:e.serviceDiscovery.serviceName}}}}}}generateVirtualRouterCF(e,t){return{Type:"AWS::AppMesh::VirtualRouter",Properties:{MeshName:t,VirtualRouterName:e.name,Spec:{Listeners:e.listeners.map((a)=>({PortMapping:{Port:a.port,Protocol:a.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 Fm=new Qr;class Jr{layers=new Map;versions=new Map;permissions=new Map;layerCounter=0;versionCounter=0;permissionCounter=0;createLayer(e){let t=`layer-${Date.now()}-${this.layerCounter++}`,a=1,r={id:t,layerArn:`arn:aws:lambda:us-east-1:123456789012:layer:${e.layerName}:1`,version:1,...e};return this.layers.set(t,r),r}createNodeDependenciesLayer(e){return this.createLayer({layerName:e.layerName,description:"Node.js dependencies layer",compatibleRuntimes:[`nodejs${e.nodeVersion}`],content:{type:"s3",s3Bucket:e.s3Bucket,s3Key:e.s3Key},size:5242880})}createUtilitiesLayer(e){return this.createLayer({layerName:e.layerName,description:"Shared utilities and helpers",compatibleRuntimes:e.runtimes,content:{type:"s3",s3Bucket:e.s3Bucket,s3Key:e.s3Key},size:1048576})}publishVersion(e){let t=this.layers.get(e);if(!t)throw Error(`Layer not found: ${e}`);let a=`version-${Date.now()}-${this.versionCounter++}`,r=t.version+1,n={id:a,layerName:t.layerName,version:r,createdAt:new Date,compatibleRuntimes:t.compatibleRuntimes,size:t.size,codeHash:this.generateHash()};return this.versions.set(a,n),t.version=r,t.layerArn=`arn:aws:lambda:us-east-1:123456789012:layer:${t.layerName}:${r}`,n}addPermission(e){let t=`permission-${Date.now()}-${this.permissionCounter++}`,a={id:t,layerName:e.layerName,version:e.version,principal:e.principal,action:"lambda:GetLayerVersion",organizationId:e.organizationId};return this.permissions.set(t,a),a}generateHash(){return Math.random().toString(36).substring(2,15)}getLayer(e){return this.layers.get(e)}listLayers(){return Array.from(this.layers.values())}getLayerVersions(e){return Array.from(this.versions.values()).filter((t)=>t.layerName===e)}generateLayerCF(e){return{Type:"AWS::Lambda::LayerVersion",Properties:{LayerName:e.layerName,Description:e.description,Content:e.content.type==="s3"?{S3Bucket:e.content.s3Bucket,S3Key:e.content.s3Key,...e.content.s3ObjectVersion&&{S3ObjectVersion:e.content.s3ObjectVersion}}:{ZipFile:e.content.zipFile},CompatibleRuntimes:e.compatibleRuntimes,...e.licenseInfo&&{LicenseInfo:e.licenseInfo}}}}generateLayerPermissionCF(e){return{Type:"AWS::Lambda::LayerVersionPermission",Properties:{LayerVersionArn:`arn:aws:lambda:us-east-1:123456789012:layer:${e.layerName}:${e.version}`,Action:e.action,Principal:e.principal,...e.organizationId&&{OrganizationId:e.organizationId}}}}clear(){this.layers.clear(),this.versions.clear(),this.permissions.clear(),this.layerCounter=0,this.versionCounter=0,this.permissionCounter=0}}var Vm=new Jr;class Yr{versions=new Map;aliases=new Map;deployments=new Map;versionCounter=0;aliasCounter=0;deploymentCounter=0;publishVersion(e){let t=`version-${Date.now()}-${this.versionCounter++}`,a=this.getNextVersionNumber(e.functionName),r={id:t,functionName:e.functionName,version:a.toString(),functionArn:`arn:aws:lambda:us-east-1:123456789012:function:${e.functionName}:${a}`,codeHash:this.generateHash(),description:e.description,runtime:e.runtime,memorySize:e.memorySize,timeout:e.timeout,publishedAt:new Date};return this.versions.set(t,r),r}getNextVersionNumber(e){let t=Array.from(this.versions.values()).filter((a)=>a.functionName===e).map((a)=>parseInt(a.version));return t.length>0?Math.max(...t)+1:1}createAlias(e){let t=`alias-${Date.now()}-${this.aliasCounter++}`,a={id:t,aliasArn:`arn:aws:lambda:us-east-1:123456789012:function:${e.functionName}:${e.aliasName}`,revisionId:this.generateHash(),...e};return this.aliases.set(t,a),a}createProductionAlias(e){return this.createAlias({functionName:e.functionName,aliasName:"production",functionVersion:e.version,description:"Production alias"})}createStagingAlias(e){return this.createAlias({functionName:e.functionName,aliasName:"staging",functionVersion:e.version,description:"Staging alias"})}updateAlias(e,t){let a=this.aliases.get(e);if(!a)throw Error(`Alias not found: ${e}`);return a.functionVersion=t,a.revisionId=this.generateHash(),a}configureWeightedRouting(e,t){let a=this.aliases.get(e);if(!a)throw Error(`Alias not found: ${e}`);return a.routingConfig={additionalVersionWeights:t},a}createCanaryDeployment(e){let t=`deployment-${Date.now()}-${this.deploymentCounter++}`,a=Array.from(this.aliases.values()).find((n)=>n.functionName===e.functionName&&n.aliasName===e.aliasName);if(!a)a=this.createAlias({functionName:e.functionName,aliasName:e.aliasName,functionVersion:e.fromVersion});this.configureWeightedRouting(a.id,{[e.toVersion]:e.canaryWeight});let r={id:t,functionName:e.functionName,fromVersion:e.fromVersion,toVersion:e.toVersion,aliasName:e.aliasName,strategy:"canary",status:"in_progress",startedAt:new Date};return this.deployments.set(t,r),r}completeDeployment(e){let t=this.deployments.get(e);if(!t)throw Error(`Deployment not found: ${e}`);let a=Array.from(this.aliases.values()).find((r)=>r.functionName===t.functionName&&r.aliasName===t.aliasName);if(a)a.functionVersion=t.toVersion,a.routingConfig=void 0;return t.status="completed",t.completedAt=new Date,t}rollbackDeployment(e){let t=this.deployments.get(e);if(!t)throw Error(`Deployment not found: ${e}`);let a=Array.from(this.aliases.values()).find((r)=>r.functionName===t.functionName&&r.aliasName===t.aliasName);if(a)a.functionVersion=t.fromVersion,a.routingConfig=void 0;return t.status="failed",t.completedAt=new Date,t}generateHash(){return Math.random().toString(36).substring(2,15)}getVersion(e){return this.versions.get(e)}listVersions(e){let t=Array.from(this.versions.values());return e?t.filter((a)=>a.functionName===e):t}getAlias(e){return this.aliases.get(e)}listAliases(e){let t=Array.from(this.aliases.values());return e?t.filter((a)=>a.functionName===e):t}generateVersionCF(e){return{Type:"AWS::Lambda::Version",Properties:{FunctionName:e.functionName,Description:e.description}}}generateAliasCF(e){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:e.functionName,Name:e.aliasName,FunctionVersion:e.functionVersion,Description:e.description,...e.routingConfig&&{RoutingConfig:{AdditionalVersionWeights:Object.entries(e.routingConfig.additionalVersionWeights||{}).map(([t,a])=>({FunctionVersion:t,FunctionWeight:a}))}}}}}clear(){this.versions.clear(),this.aliases.clear(),this.deployments.clear(),this.versionCounter=0,this.aliasCounter=0,this.deploymentCounter=0}}var Um=new Yr;class Zr{configs=new Map;provisionedConfigs=new Map;schedules=new Map;autoScalingConfigs=new Map;configCounter=0;provisionedCounter=0;scheduleCounter=0;autoScalingCounter=0;setReservedConcurrency(e){let t=`concurrency-${Date.now()}-${this.configCounter++}`,a={id:t,functionName:e.functionName,reservedConcurrency:e.reservedConcurrency};return this.configs.set(t,a),a}setProvisionedConcurrency(e){let t=`provisioned-${Date.now()}-${this.provisionedCounter++}`,a={id:t,functionName:e.functionName,qualifier:e.qualifier,provisionedConcurrentExecutions:e.provisionedConcurrentExecutions,status:"pending",lastModified:new Date};return this.provisionedConfigs.set(t,a),setTimeout(()=>{a.status="ready",a.allocatedConcurrency=e.provisionedConcurrentExecutions,a.availableConcurrency=e.provisionedConcurrentExecutions},100),a}configureWarmPool(e){return this.setProvisionedConcurrency({functionName:e.functionName,qualifier:e.alias,provisionedConcurrentExecutions:e.minInstances})}createSchedule(e){let t=`schedule-${Date.now()}-${this.scheduleCounter++}`,a={id:t,...e};return this.schedules.set(t,a),a}createBusinessHoursSchedule(e){return this.createSchedule({name:`${e.functionName}-business-hours`,functionName:e.functionName,qualifier:e.qualifier,schedule:[{name:"business-hours",cronExpression:"0 8 * * MON-FRI",targetConcurrency:e.businessHoursConcurrency},{name:"off-hours",cronExpression:"0 18 * * MON-FRI",targetConcurrency:e.offHoursConcurrency},{name:"weekend",cronExpression:"0 0 * * SAT",targetConcurrency:e.offHoursConcurrency}]})}configureAutoScaling(e){let t=`autoscaling-${Date.now()}-${this.autoScalingCounter++}`,a={id:t,...e};return this.autoScalingConfigs.set(t,a),a}configurePredictiveScaling(e){return this.configureAutoScaling({functionName:e.functionName,qualifier:e.qualifier,minCapacity:e.baselineCapacity,maxCapacity:e.peakCapacity,targetUtilization:0.7,scaleInCooldown:300,scaleOutCooldown:60})}getConfig(e){return this.configs.get(e)}listConfigs(){return Array.from(this.configs.values())}getProvisionedConfig(e){return this.provisionedConfigs.get(e)}listProvisionedConfigs(){return Array.from(this.provisionedConfigs.values())}generateReservedConcurrencyCF(e){return{Type:"AWS::Lambda::Function",Properties:{FunctionName:e.functionName,ReservedConcurrentExecutions:e.reservedConcurrency}}}generateProvisionedConcurrencyCF(e){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:e.functionName,Name:e.qualifier,ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:e.provisionedConcurrentExecutions}}}}generateAutoScalingTargetCF(e){return{Type:"AWS::ApplicationAutoScaling::ScalableTarget",Properties:{ServiceNamespace:"lambda",ResourceId:`function:${e.functionName}:${e.qualifier}`,ScalableDimension:"lambda:function:ProvisionedConcurrentExecutions",MinCapacity:e.minCapacity,MaxCapacity:e.maxCapacity}}}generateAutoScalingPolicyCF(e){return{Type:"AWS::ApplicationAutoScaling::ScalingPolicy",Properties:{PolicyName:`${e.functionName}-autoscaling`,PolicyType:"TargetTrackingScaling",ScalingTargetId:{Ref:`${e.functionName}AutoScalingTarget`},TargetTrackingScalingPolicyConfiguration:{TargetValue:e.targetUtilization*100,PredefinedMetricSpecification:{PredefinedMetricType:"LambdaProvisionedConcurrencyUtilization"},ScaleInCooldown:e.scaleInCooldown||300,ScaleOutCooldown:e.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 jm=new Zr;class Xr{destinations=new Map;records=new Map;eventBridgeDestinations=new Map;destinationCounter=0;recordCounter=0;eventBridgeCounter=0;configureDestinations(e){let t=`destination-${Date.now()}-${this.destinationCounter++}`,a={id:t,...e};return this.destinations.set(t,a),a}configureSQSDestination(e){let t={type:"sqs",arn:e.queueArn};return this.configureDestinations({functionName:e.functionName,successDestination:e.onSuccess?t:void 0,failureDestination:e.onFailure?t:void 0,maxEventAge:21600,maxRetries:2})}configureSNSDestination(e){let t={type:"sns",arn:e.topicArn};return this.configureDestinations({functionName:e.functionName,successDestination:e.onSuccess?t:void 0,failureDestination:e.onFailure?t:void 0,maxEventAge:21600,maxRetries:2})}configureEventBridgeDestination(e){let t={type:"eventbridge",arn:e.eventBusArn};return this.configureDestinations({functionName:e.functionName,successDestination:e.onSuccess?t:void 0,failureDestination:e.onFailure?t:void 0,maxEventAge:21600,maxRetries:2})}configureLambdaDestination(e){let t={type:"lambda",arn:e.destinationFunctionArn};return this.configureDestinations({functionName:e.functionName,successDestination:e.onSuccess?t:void 0,failureDestination:e.onFailure?t:void 0,maxEventAge:21600,maxRetries:2})}configureDLQWithNotification(e){return this.configureDestinations({functionName:e.functionName,failureDestination:{type:"sqs",arn:e.dlqArn},maxEventAge:3600,maxRetries:0})}createEventBridgeIntegration(e){let t=`eventbridge-${Date.now()}-${this.eventBridgeCounter++}`,a={id:t,functionName:e.functionName,eventBusArn:e.eventBusArn,detailType:e.detailType||"Lambda Function Invocation Result",source:e.source||`lambda.${e.functionName}`};return this.eventBridgeDestinations.set(t,a),a}sendToDestination(e){let t=Array.from(this.destinations.values()).find((i)=>i.functionName===e.functionName);if(!t)return null;let a=e.status==="success"?t.successDestination:t.failureDestination;if(!a)return null;let r=`record-${Date.now()}-${this.recordCounter++}`,n={id:r,timestamp:new Date,functionName:e.functionName,requestId:e.requestId,status:e.status,destinationType:a.type,destinationArn:a.arn,payload:e.payload,error:e.error};return this.records.set(r,n),n}getDestination(e){return this.destinations.get(e)}listDestinations(e){let t=Array.from(this.destinations.values());return e?t.filter((a)=>a.functionName===e):t}getDestinationRecords(e){let t=Array.from(this.records.values());return e?t.filter((a)=>a.functionName===e):t}generateEventInvokeConfigCF(e){return{Type:"AWS::Lambda::EventInvokeConfig",Properties:{FunctionName:e.functionName,Qualifier:e.qualifier||"$LATEST",MaximumEventAgeInSeconds:e.maxEventAge||21600,MaximumRetryAttempts:e.maxRetries??2,...e.successDestination&&{DestinationConfig:{OnSuccess:{Destination:e.successDestination.arn}}},...e.failureDestination&&{DestinationConfig:{OnFailure:{Destination:e.failureDestination.arn}}}}}}generateEventBridgeRuleCF(e){return{Type:"AWS::Events::Rule",Properties:{EventBusName:e.eventBusArn.split("/").pop(),EventPattern:{source:[e.source],"detail-type":[e.detailType]},State:"ENABLED",Targets:[{Arn:`arn:aws:lambda:us-east-1:123456789012:function:${e.functionName}`,Id:e.id}]}}}clear(){this.destinations.clear(),this.records.clear(),this.eventBridgeDestinations.clear(),this.destinationCounter=0,this.recordCounter=0,this.eventBridgeCounter=0}}var Km=new Xr;class en{vpcConfigs=new Map;endpoints=new Map;networkInterfaces=new Map;connectivity=new Map;configCounter=0;endpointCounter=0;eniCounter=0;connectivityCounter=0;configureVPC(e){let t=`vpc-config-${Date.now()}-${this.configCounter++}`,a={id:t,...e};this.vpcConfigs.set(t,a);for(let r of e.subnetIds)this.createNetworkInterface({functionName:e.functionName,subnetId:r});return a}configurePrivateVPC(e){return this.configureVPC({functionName:e.functionName,vpcId:e.vpcId,subnetIds:e.privateSubnetIds,securityGroupIds:[e.securityGroupId],ipv6Allowed:!1})}configureMultiAZVPC(e){if(e.subnetIds.length<2)throw Error("Multi-AZ configuration requires at least 2 subnets");return this.configureVPC({functionName:e.functionName,vpcId:e.vpcId,subnetIds:e.subnetIds,securityGroupIds:e.securityGroupIds})}createVPCEndpoint(e){let t=`endpoint-${Date.now()}-${this.endpointCounter++}`,a={id:t,...e};return this.endpoints.set(t,a),a}createS3Endpoint(e){return this.createVPCEndpoint({vpcId:e.vpcId,serviceName:"com.amazonaws.us-east-1.s3",endpointType:"Gateway",privateDnsEnabled:!1})}createDynamoDBEndpoint(e){return this.createVPCEndpoint({vpcId:e.vpcId,serviceName:"com.amazonaws.us-east-1.dynamodb",endpointType:"Gateway",privateDnsEnabled:!1})}createSecretsManagerEndpoint(e){return this.createVPCEndpoint({vpcId:e.vpcId,serviceName:"com.amazonaws.us-east-1.secretsmanager",endpointType:"Interface",subnetIds:e.subnetIds,securityGroupIds:e.securityGroupIds,privateDnsEnabled:!0})}createNetworkInterface(e){let t=`eni-${Date.now()}-${this.eniCounter++}`,a={id:t,functionName:e.functionName,networkInterfaceId:`eni-${Math.random().toString(36).substring(2,15)}`,subnetId:e.subnetId,privateIpAddress:`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`,status:"creating",attachedAt:new Date};return this.networkInterfaces.set(t,a),setTimeout(()=>{a.status="available"},100),a}analyzeConnectivity(e){let t=`connectivity-${Date.now()}-${this.connectivityCounter++}`,a=Array.from(this.vpcConfigs.values()).find((c)=>c.functionName===e.functionName),r=Array.from(this.endpoints.values()).filter((c)=>c.vpcId===a?.vpcId).map((c)=>c.serviceName),n=[],i=e.hasNATGateway??!1,s=e.hasInternetGateway??!1;if(!i&&!s)n.push("Add NAT Gateway for internet access");if(!r.includes("com.amazonaws.us-east-1.s3"))n.push("Add S3 VPC endpoint to reduce NAT costs");if(!r.includes("com.amazonaws.us-east-1.dynamodb"))n.push("Add DynamoDB VPC endpoint for private access");let o={id:t,functionName:e.functionName,hasInternetAccess:i||s,hasNATGateway:i,hasVPCEndpoints:r.length>0,endpoints:r,recommendations:n};return this.connectivity.set(t,o),o}getVPCConfig(e){return this.vpcConfigs.get(e)}listVPCConfigs(e){let t=Array.from(this.vpcConfigs.values());return e?t.filter((a)=>a.functionName===e):t}getNetworkInterfaces(e){return Array.from(this.networkInterfaces.values()).filter((t)=>t.functionName===e)}listVPCEndpoints(e){let t=Array.from(this.endpoints.values());return e?t.filter((a)=>a.vpcId===e):t}generateVPCConfigCF(e){return{VpcConfig:{SubnetIds:e.subnetIds,SecurityGroupIds:e.securityGroupIds,...e.ipv6Allowed&&{Ipv6AllowedForDualStack:!0}}}}generateVPCEndpointCF(e){return{Type:"AWS::EC2::VPCEndpoint",Properties:{VpcId:e.vpcId,ServiceName:e.serviceName,VpcEndpointType:e.endpointType,...e.subnetIds&&{SubnetIds:e.subnetIds},...e.securityGroupIds&&{SecurityGroupIds:e.securityGroupIds},...e.privateDnsEnabled!==void 0&&{PrivateDnsEnabled:e.privateDnsEnabled}}}}generateSecurityGroupCF(e){return{Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:e.groupName,GroupDescription:`Security group for Lambda ${e.groupName}`,VpcId:e.vpcId,...e.ingressRules&&{SecurityGroupIngress:e.ingressRules.map((t)=>({IpProtocol:t.protocol,FromPort:t.fromPort,ToPort:t.toPort,...t.cidrIp&&{CidrIp:t.cidrIp},...t.sourceSecurityGroupId&&{SourceSecurityGroupId:t.sourceSecurityGroupId}}))},...e.egressRules&&{SecurityGroupEgress:e.egressRules.map((t)=>({IpProtocol:t.protocol,FromPort:t.fromPort,ToPort:t.toPort,CidrIp:t.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 Hm=new en;class tn{dlqConfigs=new Map;messages=new Map;alarms=new Map;reprocessing=new Map;configCounter=0;messageCounter=0;alarmCounter=0;reprocessCounter=0;configureDLQ(e){let t=`dlq-${Date.now()}-${this.configCounter++}`,a={id:t,...e};return this.dlqConfigs.set(t,a),a}configureSQSDLQ(e){return this.configureDLQ({functionName:e.functionName,targetArn:e.queueArn,targetType:"sqs",maxReceiveCount:e.maxReceiveCount||3,retentionPeriod:e.retentionPeriod||1209600})}configureSNSDLQ(e){return this.configureDLQ({functionName:e.functionName,targetArn:e.topicArn,targetType:"sns"})}configureDLQWithAlarm(e){let t=this.configureSQSDLQ({functionName:e.functionName,queueArn:e.queueArn});return this.createDLQAlarm({dlqConfigId:t.id,alarmName:`${e.functionName}-dlq-alarm`,threshold:e.alarmThreshold,evaluationPeriods:1,notificationTopicArn:e.notificationTopicArn,enabled:!0}),t}sendToDLQ(e){let t=`message-${Date.now()}-${this.messageCounter++}`,a={id:t,timestamp:new Date,...e};return this.messages.set(t,a),a}createDLQAlarm(e){let t=`alarm-${Date.now()}-${this.alarmCounter++}`,a={id:t,...e};return this.alarms.set(t,a),a}createAgeAlarm(e){let t=this.dlqConfigs.get(e.dlqConfigId);if(!t)throw Error(`DLQ config not found: ${e.dlqConfigId}`);return this.createDLQAlarm({dlqConfigId:e.dlqConfigId,alarmName:`${t.functionName}-dlq-age-alarm`,threshold:e.maxAgeSeconds,evaluationPeriods:1,notificationTopicArn:e.notificationTopicArn,enabled:!0})}async reprocessMessage(e){let t=this.messages.get(e);if(!t)throw Error(`Message not found: ${e}`);let a=Array.from(this.dlqConfigs.values()).find((i)=>i.functionName===t.functionName);if(!a)throw Error(`DLQ config not found for function: ${t.functionName}`);let r=`reprocess-${Date.now()}-${this.reprocessCounter++}`,n={id:r,dlqConfigId:a.id,messageId:e,status:"pending",startedAt:new Date};return this.reprocessing.set(r,n),setTimeout(()=>{n.status="processing",setTimeout(()=>{let i=Math.random()>0.3;if(n.status=i?"success":"failed",n.completedAt=new Date,!i)n.error="Reprocessing failed - same error occurred";else this.messages.delete(e)},100)},50),n}async batchReprocess(e){let t=this.dlqConfigs.get(e.dlqConfigId);if(!t)throw Error(`DLQ config not found: ${e.dlqConfigId}`);let a=Array.from(this.messages.values()).filter((r)=>r.functionName===t.functionName).slice(0,e.maxMessages||10).map((r)=>this.reprocessMessage(r.id));return Promise.all(a)}getDLQStats(e){let t=this.dlqConfigs.get(e);if(!t)throw Error(`DLQ config not found: ${e}`);let a=Array.from(this.messages.values()).filter((s)=>s.functionName===t.functionName),r={},n=0;for(let s of a)r[s.errorType]=(r[s.errorType]||0)+1,n+=s.attemptCount;let i=a.map((s)=>s.timestamp);return{totalMessages:a.length,oldestMessage:i.length>0?new Date(Math.min(...i.map((s)=>s.getTime()))):void 0,newestMessage:i.length>0?new Date(Math.max(...i.map((s)=>s.getTime()))):void 0,averageAttempts:a.length>0?n/a.length:0,errorTypes:r}}getDLQConfig(e){return this.dlqConfigs.get(e)}listDLQConfigs(){return Array.from(this.dlqConfigs.values())}getDLQMessages(e){let t=this.dlqConfigs.get(e);if(!t)return[];return Array.from(this.messages.values()).filter((a)=>a.functionName===t.functionName)}generateDLQCF(e){return{DeadLetterConfig:{TargetArn:e.targetArn}}}generateSQSDLQCF(e){return{Type:"AWS::SQS::Queue",Properties:{QueueName:`${e.functionName}-dlq`,MessageRetentionPeriod:e.retentionPeriod||1209600,...e.maxReceiveCount&&{RedrivePolicy:{deadLetterTargetArn:e.targetArn,maxReceiveCount:e.maxReceiveCount}}}}}generateDLQAlarmCF(e){let t=this.dlqConfigs.get(e.dlqConfigId);if(!t)throw Error(`DLQ config not found: ${e.dlqConfigId}`);return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:e.alarmName,AlarmDescription:`DLQ alarm for ${t.functionName}`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Sum",Period:300,EvaluationPeriods:e.evaluationPeriods,Threshold:e.threshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:t.targetArn.split(":").pop()}],...e.notificationTopicArn&&{AlarmActions:[e.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 qm=new tn;class an{policies=new Map;healthChecks=new Map;trafficPolicies=new Map;policyCounter=0;healthCheckCounter=0;trafficPolicyCounter=0;createWeightedPolicy(e){let t=`policy-${Date.now()}-${this.policyCounter++}`,a={id:t,type:"weighted",...e};return this.policies.set(t,a),a}createLatencyPolicy(e){let t=`policy-${Date.now()}-${this.policyCounter++}`,a={id:t,type:"latency",...e};return this.policies.set(t,a),a}createFailoverPolicy(e){let t=`policy-${Date.now()}-${this.policyCounter++}`,a={id:t,type:"failover",...e};return this.policies.set(t,a),a}createGeolocationPolicy(e){let t=`policy-${Date.now()}-${this.policyCounter++}`,a={id:t,type:"geolocation",...e};return this.policies.set(t,a),a}createGeoproximityPolicy(e){let t=`policy-${Date.now()}-${this.policyCounter++}`,a={id:t,type:"geoproximity",...e};return this.policies.set(t,a),a}createHTTPHealthCheck(e){let t=`health-check-${Date.now()}-${this.healthCheckCounter++}`,a={id:t,type:e.port===443?"https":"http",requestInterval:e.requestInterval||30,failureThreshold:e.failureThreshold||3,healthCheckStatus:"Unknown",port:e.port||(e.port===443?443:80),...e};return this.healthChecks.set(t,a),setTimeout(()=>{a.healthCheckStatus=Math.random()>0.2?"Healthy":"Unhealthy"},100),a}createTCPHealthCheck(e){let t=`health-check-${Date.now()}-${this.healthCheckCounter++}`,a={id:t,type:"tcp",fullyQualifiedDomainName:e.ipAddress,requestInterval:e.requestInterval||30,failureThreshold:e.failureThreshold||3,healthCheckStatus:"Unknown",...e};return this.healthChecks.set(t,a),setTimeout(()=>{a.healthCheckStatus=Math.random()>0.1?"Healthy":"Unhealthy"},100),a}createCalculatedHealthCheck(e){let t=`health-check-${Date.now()}-${this.healthCheckCounter++}`,a={id:t,type:"calculated",requestInterval:30,failureThreshold:0,healthCheckStatus:"Unknown",...e};return this.healthChecks.set(t,a),setTimeout(()=>{let r=e.childHealthChecks.filter((n)=>this.healthChecks.get(n)?.healthCheckStatus==="Healthy").length;a.healthCheckStatus=r>=e.healthThreshold?"Healthy":"Unhealthy"},150),a}createTrafficPolicy(e){let t=`traffic-policy-${Date.now()}-${this.trafficPolicyCounter++}`,a={id:t,version:1,...e};return this.trafficPolicies.set(t,a),a}createFailoverTrafficPolicy(e){return this.createTrafficPolicy({name:e.name,document:{recordType:e.recordType||"A",startRule:"failover",endpoints:{primary:{type:"value",value:e.primaryEndpoint},secondary:{type:"value",value:e.secondaryEndpoint}},rules:{failover:{ruleType:"failover",primary:"primary",secondary:"secondary"}}}})}createGeoproximityTrafficPolicy(e){let t={},a=[];return e.locations.forEach((r,n)=>{let i=`endpoint${n}`;t[i]={type:"value",value:r.endpoint},a.push({endpointReference:i,region:r.region,latitude:r.latitude,longitude:r.longitude,bias:r.bias})}),this.createTrafficPolicy({name:e.name,document:{recordType:"A",startRule:"geoproximity",endpoints:t,rules:{geoproximity:{ruleType:"geoproximity",locations:a}}}})}getPolicy(e){return this.policies.get(e)}listPolicies(){return Array.from(this.policies.values())}getHealthCheck(e){return this.healthChecks.get(e)}listHealthChecks(){return Array.from(this.healthChecks.values())}getHealthCheckStatus(e){return this.healthChecks.get(e)?.healthCheckStatus||"Unknown"}generateHealthCheckCF(e){let t={Type:"AWS::Route53::HealthCheck",Properties:{HealthCheckConfig:{Type:e.type.toUpperCase(),RequestInterval:e.requestInterval,FailureThreshold:e.failureThreshold,...e.measureLatency&&{MeasureLatency:!0}},HealthCheckTags:[{Key:"Name",Value:e.name}]}};if(e.type==="calculated"){let a=e;t.Properties.HealthCheckConfig.ChildHealthChecks=a.childHealthChecks,t.Properties.HealthCheckConfig.HealthThreshold=a.healthThreshold}else{if(e.ipAddress)t.Properties.HealthCheckConfig.IPAddress=e.ipAddress;if(e.fullyQualifiedDomainName)t.Properties.HealthCheckConfig.FullyQualifiedDomainName=e.fullyQualifiedDomainName;if(e.port)t.Properties.HealthCheckConfig.Port=e.port;if(e.resourcePath)t.Properties.HealthCheckConfig.ResourcePath=e.resourcePath;if(e.enableSNI)t.Properties.HealthCheckConfig.EnableSNI=!0}return t}generateWeightedRecordSetCF(e){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:e.hostedZoneId,Name:e.name,Type:e.type,TTL:e.ttl,ResourceRecords:e.resourceRecords,Weight:e.weight,SetIdentifier:e.setIdentifier,...e.healthCheckId&&{HealthCheckId:e.healthCheckId}}}}generateFailoverRecordSetCF(e){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:e.hostedZoneId,Name:e.name,Type:e.type,TTL:e.ttl,ResourceRecords:e.resourceRecords,Failover:e.failover,SetIdentifier:e.setIdentifier,...e.healthCheckId&&{HealthCheckId:e.healthCheckId}}}}clear(){this.policies.clear(),this.healthChecks.clear(),this.trafficPolicies.clear(),this.policyCounter=0,this.healthCheckCounter=0,this.trafficPolicyCounter=0}}var zm=new an;class rn{configs=new Map;ksks=new Map;validations=new Map;configCounter=0;kskCounter=0;validationCounter=0;enableDNSSEC(e){let t=`dnssec-${Date.now()}-${this.configCounter++}`,a={id:t,hostedZoneId:e.hostedZoneId,status:"SIGNING",signingStatus:"Initializing DNSSEC signing"};if(this.configs.set(t,a),e.kmsKeyArn)this.createKSK({name:`ksk-${e.hostedZoneId}`,hostedZoneId:e.hostedZoneId,kmsKeyArn:e.kmsKeyArn});return setTimeout(()=>{a.status="SIGNED",a.signingStatus="DNSSEC signing complete"},100),a}disableDNSSEC(e){let t=this.configs.get(e);if(!t)throw Error(`DNSSEC config not found: ${e}`);return t.status="DELETING",t.signingStatus="Removing DNSSEC signing",setTimeout(()=>{t.status="NOT_SIGNING",t.signingStatus="DNSSEC signing removed"},100),t}createKSK(e){let t=`ksk-${Date.now()}-${this.kskCounter++}`,a={id:t,status:"ACTIVE",flag:257,keyManagementServiceArn:e.kmsKeyArn,digestAlgorithm:2,keyTag:Math.floor(Math.random()*65535),publicKey:this.generatePublicKey(),...e};a.dnskeyRecord=`${a.flag} 3 8 ${a.publicKey}`;let r=this.generateDigest(a.dnskeyRecord);return a.digestValue=r,a.dsRecord=`${a.keyTag} 8 ${a.digestAlgorithm} ${r}`,this.ksks.set(t,a),a}deactivateKSK(e){let t=this.ksks.get(e);if(!t)throw Error(`KSK not found: ${e}`);return t.status="INACTIVE",t}validateDNSSEC(e){let t=`validation-${Date.now()}-${this.validationCounter++}`,a=e.checkDNSKEY!==!1?Math.random()>0.1:!1,r=e.checkRRSIG!==!1?Math.random()>0.1:!1,n=a&&r,i=[];if(!a)i.push("DNSKEY record not found");if(!r)i.push("RRSIG record not found");let s;if(!a&&!r)s="INSECURE";else if(a&&r&&n)s="VALID";else if(a||r)s="BOGUS",i.push("Invalid signature or incomplete DNSSEC chain");else s="INVALID";let o={id:t,domain:e.domain,validationStatus:s,dnskeyPresent:a,rrsigPresent:r,validSignature:n,errors:i};return this.validations.set(t,o),o}getDNSSECConfig(e){return this.configs.get(e)}listDNSSECConfigs(){return Array.from(this.configs.values())}getKSK(e){return this.ksks.get(e)}listKSKs(e){let t=Array.from(this.ksks.values());return e?t.filter((a)=>a.hostedZoneId===e):t}getDSRecord(e){let t=this.ksks.get(e);if(!t||!t.dsRecord)throw Error("DS record not available");return t.dsRecord}generatePublicKey(){let e="";for(let t=0;t<256;t++)e+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(Math.floor(Math.random()*64));return e}generateDigest(e){let t="";for(let a=0;a<64;a++)t+="0123456789ABCDEF".charAt(Math.floor(Math.random()*16));return t}generateDNSSECCF(e){return{Type:"AWS::Route53::DNSSEC",Properties:{HostedZoneId:e.hostedZoneId}}}generateKSKCF(e){return{Type:"AWS::Route53::KeySigningKey",Properties:{Name:e.name,HostedZoneId:e.hostedZoneId,KeyManagementServiceArn:e.keyManagementServiceArn,Status:e.status}}}clear(){this.configs.clear(),this.ksks.clear(),this.validations.clear(),this.configCounter=0,this.kskCounter=0,this.validationCounter=0}}var Qm=new rn;class nn{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(e){let t=`endpoint-${Date.now()}-${this.endpointCounter++}`,a={id:t,status:"CREATING",...e};return this.endpoints.set(t,a),setTimeout(()=>{a.status="OPERATIONAL",a.ipAddresses.forEach((r)=>{if(!r.ip)r.ip=`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`})},100),a}createInboundEndpoint(e){return this.createResolverEndpoint({name:e.name,direction:"INBOUND",ipAddresses:e.subnetIds.map((t)=>({subnetId:t})),securityGroupIds:e.securityGroupIds})}createOutboundEndpoint(e){return this.createResolverEndpoint({name:e.name,direction:"OUTBOUND",ipAddresses:e.subnetIds.map((t)=>({subnetId:t})),securityGroupIds:e.securityGroupIds})}createResolverRule(e){let t=`rule-${Date.now()}-${this.ruleCounter++}`,a={id:t,status:"CREATING",...e};return this.rules.set(t,a),setTimeout(()=>{a.status="COMPLETE"},100),a}createForwardRule(e){return this.createResolverRule({name:e.name,ruleType:"FORWARD",domainName:e.domainName,targetIps:e.targetIps,resolverEndpointId:e.resolverEndpointId})}createSystemRule(e){return this.createResolverRule({name:e.name,ruleType:"SYSTEM",domainName:e.domainName})}createFirewallDomainList(e){let t=`domain-list-${Date.now()}-${this.domainListCounter++}`,a={id:t,status:"CREATING",...e};return this.domainLists.set(t,a),setTimeout(()=>{a.status="COMPLETE"},100),a}createFirewallRuleGroup(e){let t=`rule-group-${Date.now()}-${this.ruleGroupCounter++}`,a={id:t,name:e.name,rules:e.rules.map((r,n)=>({id:`rule-${t}-${n}`,...r})),shareStatus:"NOT_SHARED"};return this.ruleGroups.set(t,a),a}createBlockRule(e){return this.createFirewallRuleGroup({name:e.name,rules:[{name:e.name,priority:e.priority,action:"BLOCK",blockResponse:e.blockResponse||"NODATA",blockOverrideDomain:e.blockOverrideDomain,firewallDomainListId:e.domainListId}]})}createAllowRule(e){return this.createFirewallRuleGroup({name:e.name,rules:[{name:e.name,priority:e.priority,action:"ALLOW",firewallDomainListId:e.domainListId}]})}createDNSFirewall(e){let t=`firewall-${Date.now()}-${this.firewallCounter++}`,a={id:t,name:e.name,firewallRuleGroupAssociations:e.ruleGroupAssociations.map((r,n)=>({id:`assoc-${t}-${n}`,vpcId:e.vpcId,firewallRuleGroupId:r.firewallRuleGroupId,priority:r.priority,mutationProtection:r.mutationProtection||"DISABLED",status:"COMPLETE"}))};return this.firewalls.set(t,a),a}createMalwareProtectionFirewall(e){let t=this.createFirewallDomainList({name:`${e.name}-malware-domains`,domains:e.maliciousDomains}),a=this.createBlockRule({name:`${e.name}-block-malware`,priority:100,domainListId:t.id,blockResponse:"NXDOMAIN"});return this.createDNSFirewall({name:e.name,vpcId:e.vpcId,ruleGroupAssociations:[{firewallRuleGroupId:a.id,priority:100,mutationProtection:"ENABLED"}]})}getEndpoint(e){return this.endpoints.get(e)}listEndpoints(e){let t=Array.from(this.endpoints.values());return e?t.filter((a)=>a.direction===e):t}getRule(e){return this.rules.get(e)}listRules(){return Array.from(this.rules.values())}getFirewall(e){return this.firewalls.get(e)}listFirewalls(){return Array.from(this.firewalls.values())}generateResolverEndpointCF(e){return{Type:"AWS::Route53Resolver::ResolverEndpoint",Properties:{Name:e.name,Direction:e.direction,IpAddresses:e.ipAddresses.map((t)=>({SubnetId:t.subnetId,...t.ip&&{Ip:t.ip}})),SecurityGroupIds:e.securityGroupIds}}}generateResolverRuleCF(e){return{Type:"AWS::Route53Resolver::ResolverRule",Properties:{Name:e.name,RuleType:e.ruleType,DomainName:e.domainName,...e.targetIps&&{TargetIps:e.targetIps.map((t)=>({Ip:t.ip,Port:t.port||53}))},...e.resolverEndpointId&&{ResolverEndpointId:e.resolverEndpointId}}}}generateFirewallRuleGroupCF(e){return{Type:"AWS::Route53Resolver::FirewallRuleGroup",Properties:{Name:e.name,FirewallRules:e.rules.map((t)=>({Name:t.name,Priority:t.priority,Action:t.action,FirewallDomainListId:t.firewallDomainListId,...t.blockResponse&&{BlockResponse:t.blockResponse},...t.blockOverrideDomain&&{BlockOverrideDomain:t.blockOverrideDomain},...t.blockOverrideTTL&&{BlockOverrideTtl:t.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 Jm=new nn;class sn{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(e){let t=`bounce-${Date.now()}-${this.bounceCounter++}`,a={id:t,...e};if(this.bounces.set(t,a),e.bounceType==="Permanent")this.addToSuppressionList({emailAddress:e.recipient,reason:"BOUNCE"});return a}recordComplaint(e){let t=`complaint-${Date.now()}-${this.complaintCounter++}`,a={id:t,...e};this.complaints.set(t,a);for(let r of e.recipients)this.addToSuppressionList({emailAddress:r,reason:"COMPLAINT"});return a}createBounceHandler(e){let t=`handler-${Date.now()}-${this.handlerCounter++}`,a={id:t,...e};return this.handlers.set(t,a),a}createAutomaticBounceHandler(e){return this.createBounceHandler({name:e.name,bounceThreshold:5,complaintThreshold:0.1,suppressionDuration:2592000,autoSuppress:!0,notificationTopicArn:e.notificationTopicArn})}addToSuppressionList(e){let t=`suppression-${Date.now()}-${this.suppressionCounter++}`,a=e.expirationDays?new Date(Date.now()+e.expirationDays*24*60*60*1000):void 0,r={id:t,emailAddress:e.emailAddress,reason:e.reason,suppressedAt:new Date,expiresAt:a,bounceCount:e.reason==="BOUNCE"?1:0,complaintCount:e.reason==="COMPLAINT"?1:0};return this.suppressionList.set(e.emailAddress,r),r}removeFromSuppressionList(e){return this.suppressionList.delete(e)}isSuppressed(e){let t=this.suppressionList.get(e);if(!t)return!1;if(t.expiresAt&&t.expiresAt<new Date)return this.suppressionList.delete(e),!1;return!0}getBounceStatistics(e,t){let a=Array.from(this.bounces.values()).filter((u)=>u.timestamp>=e&&u.timestamp<=t),r=a.length,n=a.filter((u)=>u.bounceType==="Permanent").length,i=a.filter((u)=>u.bounceType==="Transient").length,s=r*10,o=r/s*100,c=new Map;for(let u of a)c.set(u.recipient,(c.get(u.recipient)||0)+1);let l=Array.from(c.entries()).map(([u,m])=>({email:u,count:m})).sort((u,m)=>m.count-u.count).slice(0,10);return{totalBounces:r,permanentBounces:n,transientBounces:i,bounceRate:o,topRecipients:l}}getComplaintStatistics(e,t){let a=Array.from(this.complaints.values()).filter((c)=>c.timestamp>=e&&c.timestamp<=t),r=a.length,n=new Set;for(let c of a)for(let l of c.recipients)n.add(l);let i=n.size,s=r*1000,o=r/s*100;return{totalComplaints:r,uniqueComplainters:i,complaintRate:o}}calculateReputationMetrics(){let e=`metrics-${Date.now()}-${this.metricsCounter++}`,t=new Date,a=new Date(t.getTime()-86400000),r=this.getBounceStatistics(a,t),n=this.getComplaintStatistics(a,t),i;if(r.bounceRate>10||n.complaintRate>0.5)i="Shutdown";else if(r.bounceRate>5||n.complaintRate>0.1)i="Probation";else if(r.bounceRate>2||n.complaintRate>0.05)i="Warning";else i="Good";let s={id:e,timestamp:t,bounceRate:r.bounceRate,complaintRate:n.complaintRate,sendingQuota:50000,maxSendRate:14,sentLast24Hours:r.totalBounces*10,reputationStatus:i};return this.metrics.set(e,s),s}getBounces(e){let t=Array.from(this.bounces.values());return e?t.filter((a)=>a.messageId===e):t}getComplaints(e){let t=Array.from(this.complaints.values());return e?t.filter((a)=>a.messageId===e):t}listSuppressionList(e){let t=Array.from(this.suppressionList.values());return e?t.filter((a)=>a.reason===e):t}generateSNSSubscriptionCF(e){return{Type:"AWS::SNS::Subscription",Properties:{TopicArn:e.topicArn,Endpoint:e.endpoint,Protocol:e.protocol}}}generateEventDestinationCF(e){return{Type:"AWS::SES::ConfigurationSetEventDestination",Properties:{ConfigurationSetName:e.configurationSetName,EventDestination:{Name:e.eventDestinationName,Enabled:!0,MatchingEventTypes:e.eventTypes,...e.snsTopicArn&&{SnsDestination:{TopicARN:e.snsTopicArn}},...e.cloudWatchDestination&&{CloudWatchDestination:e.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 Ym=new sn;class on{events=new Map;campaigns=new Map;reports=new Map;abTests=new Map;eventCounter=0;campaignCounter=0;reportCounter=0;abTestCounter=0;trackEvent(e){let t=`event-${Date.now()}-${this.eventCounter++}`,a={id:t,...e};if(this.events.set(t,a),e.tags?.campaignId)this.updateCampaignStats(e.tags.campaignId,e.eventType);return a}trackOpen(e){return this.trackEvent({...e,eventType:"open",timestamp:new Date})}trackClick(e){return this.trackEvent({...e,eventType:"click",timestamp:new Date})}createCampaign(e){let t=`campaign-${Date.now()}-${this.campaignCounter++}`,a={id:t,sentCount:0,deliveredCount:0,openCount:0,clickCount:0,bounceCount:0,complaintCount:0,createdAt:new Date,...e};return this.campaigns.set(t,a),a}updateCampaignStats(e,t){let a=this.campaigns.get(e);if(!a)return;switch(t){case"send":a.sentCount++;break;case"delivery":a.deliveredCount++;break;case"open":a.openCount++;break;case"click":a.clickCount++;break;case"bounce":a.bounceCount++;break;case"complaint":a.complaintCount++;break}}generateReport(e){let t=`report-${Date.now()}-${this.reportCounter++}`,a=Array.from(this.events.values()).filter((S)=>{let E=S.timestamp>=e.startDate&&S.timestamp<=e.endDate,v=!e.campaignId||S.tags?.campaignId===e.campaignId;return E&&v}),r=a.filter((S)=>S.eventType==="send").length,n=a.filter((S)=>S.eventType==="delivery").length,i=a.filter((S)=>S.eventType==="open").length,s=a.filter((S)=>S.eventType==="click").length,o=a.filter((S)=>S.eventType==="bounce").length,c=a.filter((S)=>S.eventType==="complaint").length,l=r>0?n/r*100:0,u=n>0?i/n*100:0,m=n>0?s/n*100:0,p=i>0?s/i*100:0,g=r>0?o/r*100:0,h=n>0?c/n*100:0,y=new Map;for(let S of a)if(S.eventType==="click"){let E=S;y.set(E.link,(y.get(E.link)||0)+1)}let b=Array.from(y.entries()).map(([S,E])=>({link:S,clicks:E})).sort((S,E)=>E.clicks-S.clicks).slice(0,10),T={desktop:0,mobile:0,tablet:0,unknown:0};for(let S of a)if(S.eventType==="open"||S.eventType==="click"){let E=S.userAgent.toLowerCase();if(E.includes("mobile"))T.mobile++;else if(E.includes("tablet"))T.tablet++;else if(E.includes("mozilla"))T.desktop++;else T.unknown++}let w={id:t,campaignId:e.campaignId,startDate:e.startDate,endDate:e.endDate,totalSent:r,totalDelivered:n,totalOpened:i,totalClicked:s,totalBounced:o,totalComplaints:c,deliveryRate:l,openRate:u,clickRate:m,clickToOpenRate:p,bounceRate:g,complaintRate:h,topLinks:b,deviceBreakdown:T,locationBreakdown:{}};return this.reports.set(t,w),w}createABTest(e){let t=`abtest-${Date.now()}-${this.abTestCounter++}`,a={id:t,name:e.name,variants:e.variants.map((r,n)=>({id:`variant-${t}-${n}`,sentCount:0,openCount:0,clickCount:0,conversionCount:0,...r})),status:"draft"};return this.abTests.set(t,a),a}startABTest(e){let t=this.abTests.get(e);if(!t)throw Error(`A/B test not found: ${e}`);return t.status="running",t.startedAt=new Date,t}completeABTest(e){let t=this.abTests.get(e);if(!t)throw Error(`A/B test not found: ${e}`);let a=t.variants[0],r=0;for(let n of t.variants){let i=n.sentCount>0?n.openCount/n.sentCount:0;if(i>r)r=i,a=n}return t.status="completed",t.completedAt=new Date,t.winner=a.id,t}getCampaign(e){return this.campaigns.get(e)}listCampaigns(){return Array.from(this.campaigns.values())}getEvents(e){let t=Array.from(this.events.values());if(e?.messageId)t=t.filter((a)=>a.messageId===e.messageId);if(e?.eventType)t=t.filter((a)=>a.eventType===e.eventType);if(e?.startDate)t=t.filter((a)=>a.timestamp>=e.startDate);if(e?.endDate)t=t.filter((a)=>a.timestamp<=e.endDate);return t}generateTrackingConfigurationCF(e){return{Type:"AWS::SES::ConfigurationSet",Properties:{Name:e.configurationSetName,...e.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 Zm=new on;class cn{dashboards=new Map;warmupPlans=new Map;domainReputations=new Map;dashboardCounter=0;warmupCounter=0;domainCounter=0;getReputationDashboard(){let e=`dashboard-${Date.now()}-${this.dashboardCounter++}`,t=Math.random()*5,a=Math.random()*0.5,r=Math.floor(Math.random()*10),n=Math.max(0,100-t*10-a*100-r*2),i=[];if(t>2)i.push("Reduce bounce rate by cleaning email list");if(a>0.1)i.push("Review email content and unsubscribe process");if(r>5)i.push("Improve email relevance and targeting");let s={id:e,timestamp:new Date,overallScore:n,bounceRate:t,complaintRate:a,spamReports:r,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:i};return this.dashboards.set(e,s),s}checkBlacklists(){return["Spamhaus ZEN","Spamcop","SORBS","Barracuda","URIBL"].map((e)=>({listName:e,listed:Math.random()>0.95,delistUrl:`https://www.${e.toLowerCase().replace(/\s/g,"")}.org/delist`}))}createWarmupPlan(e){let t=`warmup-${Date.now()}-${this.warmupCounter++}`,a=[],r=(e.targetDailyLimit-e.initialDailyLimit)/e.durationDays;for(let i=0;i<e.durationDays;i++)a.push(Math.floor(e.initialDailyLimit+r*i));let n={id:t,name:e.name,startDate:new Date,currentDay:1,totalDays:e.durationDays,dailyLimits:a,currentLimit:a[0],status:"active"};return this.warmupPlans.set(t,n),n}createAggressiveWarmupPlan(e){return this.createWarmupPlan({name:e.name,initialDailyLimit:500,targetDailyLimit:50000,durationDays:14})}createConservativeWarmupPlan(e){return this.createWarmupPlan({name:e.name,initialDailyLimit:200,targetDailyLimit:50000,durationDays:30})}advanceWarmupPlan(e){let t=this.warmupPlans.get(e);if(!t)throw Error(`Warmup plan not found: ${e}`);if(t.currentDay<t.totalDays)t.currentDay++,t.currentLimit=t.dailyLimits[t.currentDay-1];if(t.currentDay>=t.totalDays)t.status="completed";return t}trackDomainReputation(e){let t=`domain-${Date.now()}-${this.domainCounter++}`,a=e.delivered/e.totalSent*100,r=e.delivered>0?e.opened/e.delivered*100:0,n=e.delivered>0?e.clicked/e.delivered*100:0,i=e.bounced/e.totalSent*100,s=e.delivered>0?e.complained/e.delivered*100:0,o=r*0.4+n*0.6,c=Math.max(0,100-i*10-s*100+o*0.2),l={id:t,domain:e.domain,reputationScore:c,totalSent:e.totalSent,deliveryRate:a,openRate:r,clickRate:n,bounceRate:i,complaintRate:s,engagementScore:o};return this.domainReputations.set(e.domain,l),l}getDomainReputation(e){return this.domainReputations.get(e)}listDomainReputations(){return Array.from(this.domainReputations.values())}getWarmupPlan(e){return this.warmupPlans.get(e)}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 Xm=new cn;class ln{templates=new Map;versions=new Map;tests=new Map;templateCounter=0;testCounter=0;createTemplate(e){let t=`template-${Date.now()}-${this.templateCounter++}`,a=this.extractVariables(e.subject+e.htmlPart+e.textPart),r={id:t,variables:a,createdAt:new Date,updatedAt:new Date,version:1,...e};return this.templates.set(t,r),this.addVersion({templateId:t,version:1,subject:e.subject,htmlPart:e.htmlPart,textPart:e.textPart,createdBy:"system"}),r}createWelcomeTemplate(e){return this.createTemplate({name:e.name,subject:"Welcome to {{companyName}}!",htmlPart:`
3786
+ COPY . .`,impact:"Improve build time by 60-80% on subsequent builds"});let o={sizeBefore:t.totalSize,sizeAfter:t.totalSize*0.6,timeBefore:300,timeAfter:120},c={id:a,name:`Optimization for ${t.imageId}`,recommendations:r,estimatedSavings:o};return this.optimizations.set(a,c),c}getBuildConfig(e){return this.configs.get(e)}listBuildConfigs(){return Array.from(this.configs.values())}getMultiStageConfig(e){return this.multiStageConfigs.get(e)}listMultiStageConfigs(){return Array.from(this.multiStageConfigs.values())}getOptimization(e){return this.optimizations.get(e)}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 Bm=new qr;class zr{registries=new Map;credentials=new Map;registryCounter=0;credentialsCounter=0;createRegistry(e){let t=`registry-${Date.now()}-${this.registryCounter++}`,a={id:t,...e};return this.registries.set(t,a),a}createECRRepository(e){return this.createRegistry({name:e.name,registryType:"ecr",repositoryUri:`123456789012.dkr.ecr.${e.region||"us-east-1"}.amazonaws.com/${e.name}`,region:e.region||"us-east-1",encryption:{encryptionType:e.encryption||"AES256",kmsKeyId:e.kmsKeyId},scanning:{scanOnPush:e.scanOnPush??!0}})}createManagedRepository(e){let t=this.createECRRepository({name:e.name,region:e.region,scanOnPush:!0,encryption:"KMS"});return t.lifecycle={id:`lifecycle-${Date.now()}`,rules:[{rulePriority:1,description:"Keep only last N images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:e.maxImageCount||10},action:{type:"expire"}},{rulePriority:2,description:"Remove images older than N days",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:e.maxImageAgeDays||30,countUnit:"days"},action:{type:"expire"}}]},t}enableReplication(e,t){let a=this.registries.get(e);if(!a)throw Error(`Registry not found: ${e}`);return a.replication={enabled:!0,destinations:t},a}createCredentials(e){let t=`creds-${Date.now()}-${this.credentialsCounter++}`,a={id:t,...e};return this.credentials.set(t,a),a}getRegistry(e){return this.registries.get(e)}listRegistries(){return Array.from(this.registries.values())}generateECRRepositoryCF(e){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:e.name,ImageScanningConfiguration:{ScanOnPush:e.scanning?.scanOnPush??!1},EncryptionConfiguration:{EncryptionType:e.encryption?.encryptionType||"AES256",...e.encryption?.kmsKeyId&&{KmsKey:e.encryption.kmsKeyId}},ImageTagMutability:"MUTABLE",...e.lifecycle&&{LifecyclePolicy:{LifecyclePolicyText:JSON.stringify({rules:e.lifecycle.rules})}}}}}generateReplicationConfigCF(e){return{Type:"AWS::ECR::ReplicationConfiguration",Properties:{ReplicationConfiguration:{Rules:e.destinations.map((t)=>({Destinations:[{Region:t.region,...t.registryId&&{RegistryId:t.registryId}}]}))}}}}clear(){this.registries.clear(),this.credentials.clear(),this.registryCounter=0,this.credentialsCounter=0}}var Um=new zr;class Jr{meshes=new Map;virtualNodes=new Map;virtualRouters=new Map;virtualGateways=new Map;meshCounter=0;nodeCounter=0;routerCounter=0;gatewayCounter=0;createMesh(e){let t=`mesh-${Date.now()}-${this.meshCounter++}`,a={id:t,...e};return this.meshes.set(t,a),a}createAppMesh(e){return this.createMesh({name:e.name,meshType:"app_mesh",services:e.services,virtualNodes:[],virtualRouters:[],virtualGateways:[]})}createVirtualNode(e){let t=`vnode-${Date.now()}-${this.nodeCounter++}`,a={id:t,...e};return this.virtualNodes.set(t,a),a}createHTTPVirtualNode(e){return this.createVirtualNode({name:e.name,serviceName:e.serviceName,listeners:[{port:e.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:e.namespace,serviceName:e.serviceName}})}createVirtualRouter(e){let t=`vrouter-${Date.now()}-${this.routerCounter++}`,a={id:t,...e};return this.virtualRouters.set(t,a),a}createCanaryRoute(e){return this.createVirtualRouter({name:e.name,listeners:[{port:e.port,protocol:e.protocol}],routes:[{name:"canary-route",match:{prefix:"/"},action:{weightedTargets:[{virtualNode:e.stableTarget,weight:100-e.canaryWeight},{virtualNode:e.canaryTarget,weight:e.canaryWeight}]},retryPolicy:{maxRetries:3,perRetryTimeout:5000,httpRetryEvents:["server-error","gateway-error"],tcpRetryEvents:["connection-error"]}}]})}createVirtualGateway(e){let t=`vgateway-${Date.now()}-${this.gatewayCounter++}`,a={id:t,...e};return this.virtualGateways.set(t,a),a}createIngressGateway(e){let t={port:e.port,protocol:"http",healthCheck:{protocol:"http",path:"/health",interval:30,timeout:10,healthyThreshold:2,unhealthyThreshold:3}};if(e.enableTLS&&e.certificateArn)t.tls={mode:"STRICT",certificate:{acm:e.certificateArn}};return this.createVirtualGateway({name:e.name,listeners:[t],logging:{accessLog:{file:{path:"/dev/stdout"}}}})}getMesh(e){return this.meshes.get(e)}listMeshes(){return Array.from(this.meshes.values())}getVirtualNode(e){return this.virtualNodes.get(e)}listVirtualNodes(){return Array.from(this.virtualNodes.values())}generateMeshCF(e){return{Type:"AWS::AppMesh::Mesh",Properties:{MeshName:e.name,Spec:{EgressFilter:{Type:"ALLOW_ALL"}}}}}generateVirtualNodeCF(e,t){return{Type:"AWS::AppMesh::VirtualNode",Properties:{MeshName:t,VirtualNodeName:e.name,Spec:{Listeners:e.listeners.map((a)=>({PortMapping:{Port:a.port,Protocol:a.protocol},...a.healthCheck&&{HealthCheck:{Protocol:a.healthCheck.protocol,...a.healthCheck.path&&{Path:a.healthCheck.path},IntervalMillis:a.healthCheck.interval*1000,TimeoutMillis:a.healthCheck.timeout*1000,HealthyThreshold:a.healthCheck.healthyThreshold,UnhealthyThreshold:a.healthCheck.unhealthyThreshold}}})),ServiceDiscovery:{AWSCloudMap:{NamespaceName:e.serviceDiscovery.namespace,ServiceName:e.serviceDiscovery.serviceName}}}}}}generateVirtualRouterCF(e,t){return{Type:"AWS::AppMesh::VirtualRouter",Properties:{MeshName:t,VirtualRouterName:e.name,Spec:{Listeners:e.listeners.map((a)=>({PortMapping:{Port:a.port,Protocol:a.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 Gm=new Jr;class Qr{layers=new Map;versions=new Map;permissions=new Map;layerCounter=0;versionCounter=0;permissionCounter=0;createLayer(e){let t=`layer-${Date.now()}-${this.layerCounter++}`,a=1,r={id:t,layerArn:`arn:aws:lambda:us-east-1:123456789012:layer:${e.layerName}:1`,version:1,...e};return this.layers.set(t,r),r}createNodeDependenciesLayer(e){return this.createLayer({layerName:e.layerName,description:"Node.js dependencies layer",compatibleRuntimes:[`nodejs${e.nodeVersion}`],content:{type:"s3",s3Bucket:e.s3Bucket,s3Key:e.s3Key},size:5242880})}createUtilitiesLayer(e){return this.createLayer({layerName:e.layerName,description:"Shared utilities and helpers",compatibleRuntimes:e.runtimes,content:{type:"s3",s3Bucket:e.s3Bucket,s3Key:e.s3Key},size:1048576})}publishVersion(e){let t=this.layers.get(e);if(!t)throw Error(`Layer not found: ${e}`);let a=`version-${Date.now()}-${this.versionCounter++}`,r=t.version+1,n={id:a,layerName:t.layerName,version:r,createdAt:new Date,compatibleRuntimes:t.compatibleRuntimes,size:t.size,codeHash:this.generateHash()};return this.versions.set(a,n),t.version=r,t.layerArn=`arn:aws:lambda:us-east-1:123456789012:layer:${t.layerName}:${r}`,n}addPermission(e){let t=`permission-${Date.now()}-${this.permissionCounter++}`,a={id:t,layerName:e.layerName,version:e.version,principal:e.principal,action:"lambda:GetLayerVersion",organizationId:e.organizationId};return this.permissions.set(t,a),a}generateHash(){return Math.random().toString(36).substring(2,15)}getLayer(e){return this.layers.get(e)}listLayers(){return Array.from(this.layers.values())}getLayerVersions(e){return Array.from(this.versions.values()).filter((t)=>t.layerName===e)}generateLayerCF(e){return{Type:"AWS::Lambda::LayerVersion",Properties:{LayerName:e.layerName,Description:e.description,Content:e.content.type==="s3"?{S3Bucket:e.content.s3Bucket,S3Key:e.content.s3Key,...e.content.s3ObjectVersion&&{S3ObjectVersion:e.content.s3ObjectVersion}}:{ZipFile:e.content.zipFile},CompatibleRuntimes:e.compatibleRuntimes,...e.licenseInfo&&{LicenseInfo:e.licenseInfo}}}}generateLayerPermissionCF(e){return{Type:"AWS::Lambda::LayerVersionPermission",Properties:{LayerVersionArn:`arn:aws:lambda:us-east-1:123456789012:layer:${e.layerName}:${e.version}`,Action:e.action,Principal:e.principal,...e.organizationId&&{OrganizationId:e.organizationId}}}}clear(){this.layers.clear(),this.versions.clear(),this.permissions.clear(),this.layerCounter=0,this.versionCounter=0,this.permissionCounter=0}}var Vm=new Qr;class $r{versions=new Map;aliases=new Map;deployments=new Map;versionCounter=0;aliasCounter=0;deploymentCounter=0;publishVersion(e){let t=`version-${Date.now()}-${this.versionCounter++}`,a=this.getNextVersionNumber(e.functionName),r={id:t,functionName:e.functionName,version:a.toString(),functionArn:`arn:aws:lambda:us-east-1:123456789012:function:${e.functionName}:${a}`,codeHash:this.generateHash(),description:e.description,runtime:e.runtime,memorySize:e.memorySize,timeout:e.timeout,publishedAt:new Date};return this.versions.set(t,r),r}getNextVersionNumber(e){let t=Array.from(this.versions.values()).filter((a)=>a.functionName===e).map((a)=>parseInt(a.version));return t.length>0?Math.max(...t)+1:1}createAlias(e){let t=`alias-${Date.now()}-${this.aliasCounter++}`,a={id:t,aliasArn:`arn:aws:lambda:us-east-1:123456789012:function:${e.functionName}:${e.aliasName}`,revisionId:this.generateHash(),...e};return this.aliases.set(t,a),a}createProductionAlias(e){return this.createAlias({functionName:e.functionName,aliasName:"production",functionVersion:e.version,description:"Production alias"})}createStagingAlias(e){return this.createAlias({functionName:e.functionName,aliasName:"staging",functionVersion:e.version,description:"Staging alias"})}updateAlias(e,t){let a=this.aliases.get(e);if(!a)throw Error(`Alias not found: ${e}`);return a.functionVersion=t,a.revisionId=this.generateHash(),a}configureWeightedRouting(e,t){let a=this.aliases.get(e);if(!a)throw Error(`Alias not found: ${e}`);return a.routingConfig={additionalVersionWeights:t},a}createCanaryDeployment(e){let t=`deployment-${Date.now()}-${this.deploymentCounter++}`,a=Array.from(this.aliases.values()).find((n)=>n.functionName===e.functionName&&n.aliasName===e.aliasName);if(!a)a=this.createAlias({functionName:e.functionName,aliasName:e.aliasName,functionVersion:e.fromVersion});this.configureWeightedRouting(a.id,{[e.toVersion]:e.canaryWeight});let r={id:t,functionName:e.functionName,fromVersion:e.fromVersion,toVersion:e.toVersion,aliasName:e.aliasName,strategy:"canary",status:"in_progress",startedAt:new Date};return this.deployments.set(t,r),r}completeDeployment(e){let t=this.deployments.get(e);if(!t)throw Error(`Deployment not found: ${e}`);let a=Array.from(this.aliases.values()).find((r)=>r.functionName===t.functionName&&r.aliasName===t.aliasName);if(a)a.functionVersion=t.toVersion,a.routingConfig=void 0;return t.status="completed",t.completedAt=new Date,t}rollbackDeployment(e){let t=this.deployments.get(e);if(!t)throw Error(`Deployment not found: ${e}`);let a=Array.from(this.aliases.values()).find((r)=>r.functionName===t.functionName&&r.aliasName===t.aliasName);if(a)a.functionVersion=t.fromVersion,a.routingConfig=void 0;return t.status="failed",t.completedAt=new Date,t}generateHash(){return Math.random().toString(36).substring(2,15)}getVersion(e){return this.versions.get(e)}listVersions(e){let t=Array.from(this.versions.values());return e?t.filter((a)=>a.functionName===e):t}getAlias(e){return this.aliases.get(e)}listAliases(e){let t=Array.from(this.aliases.values());return e?t.filter((a)=>a.functionName===e):t}generateVersionCF(e){return{Type:"AWS::Lambda::Version",Properties:{FunctionName:e.functionName,Description:e.description}}}generateAliasCF(e){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:e.functionName,Name:e.aliasName,FunctionVersion:e.functionVersion,Description:e.description,...e.routingConfig&&{RoutingConfig:{AdditionalVersionWeights:Object.entries(e.routingConfig.additionalVersionWeights||{}).map(([t,a])=>({FunctionVersion:t,FunctionWeight:a}))}}}}}clear(){this.versions.clear(),this.aliases.clear(),this.deployments.clear(),this.versionCounter=0,this.aliasCounter=0,this.deploymentCounter=0}}var Fm=new $r;class Yr{configs=new Map;provisionedConfigs=new Map;schedules=new Map;autoScalingConfigs=new Map;configCounter=0;provisionedCounter=0;scheduleCounter=0;autoScalingCounter=0;setReservedConcurrency(e){let t=`concurrency-${Date.now()}-${this.configCounter++}`,a={id:t,functionName:e.functionName,reservedConcurrency:e.reservedConcurrency};return this.configs.set(t,a),a}setProvisionedConcurrency(e){let t=`provisioned-${Date.now()}-${this.provisionedCounter++}`,a={id:t,functionName:e.functionName,qualifier:e.qualifier,provisionedConcurrentExecutions:e.provisionedConcurrentExecutions,status:"pending",lastModified:new Date};return this.provisionedConfigs.set(t,a),setTimeout(()=>{a.status="ready",a.allocatedConcurrency=e.provisionedConcurrentExecutions,a.availableConcurrency=e.provisionedConcurrentExecutions},100),a}configureWarmPool(e){return this.setProvisionedConcurrency({functionName:e.functionName,qualifier:e.alias,provisionedConcurrentExecutions:e.minInstances})}createSchedule(e){let t=`schedule-${Date.now()}-${this.scheduleCounter++}`,a={id:t,...e};return this.schedules.set(t,a),a}createBusinessHoursSchedule(e){return this.createSchedule({name:`${e.functionName}-business-hours`,functionName:e.functionName,qualifier:e.qualifier,schedule:[{name:"business-hours",cronExpression:"0 8 * * MON-FRI",targetConcurrency:e.businessHoursConcurrency},{name:"off-hours",cronExpression:"0 18 * * MON-FRI",targetConcurrency:e.offHoursConcurrency},{name:"weekend",cronExpression:"0 0 * * SAT",targetConcurrency:e.offHoursConcurrency}]})}configureAutoScaling(e){let t=`autoscaling-${Date.now()}-${this.autoScalingCounter++}`,a={id:t,...e};return this.autoScalingConfigs.set(t,a),a}configurePredictiveScaling(e){return this.configureAutoScaling({functionName:e.functionName,qualifier:e.qualifier,minCapacity:e.baselineCapacity,maxCapacity:e.peakCapacity,targetUtilization:0.7,scaleInCooldown:300,scaleOutCooldown:60})}getConfig(e){return this.configs.get(e)}listConfigs(){return Array.from(this.configs.values())}getProvisionedConfig(e){return this.provisionedConfigs.get(e)}listProvisionedConfigs(){return Array.from(this.provisionedConfigs.values())}generateReservedConcurrencyCF(e){return{Type:"AWS::Lambda::Function",Properties:{FunctionName:e.functionName,ReservedConcurrentExecutions:e.reservedConcurrency}}}generateProvisionedConcurrencyCF(e){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:e.functionName,Name:e.qualifier,ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:e.provisionedConcurrentExecutions}}}}generateAutoScalingTargetCF(e){return{Type:"AWS::ApplicationAutoScaling::ScalableTarget",Properties:{ServiceNamespace:"lambda",ResourceId:`function:${e.functionName}:${e.qualifier}`,ScalableDimension:"lambda:function:ProvisionedConcurrentExecutions",MinCapacity:e.minCapacity,MaxCapacity:e.maxCapacity}}}generateAutoScalingPolicyCF(e){return{Type:"AWS::ApplicationAutoScaling::ScalingPolicy",Properties:{PolicyName:`${e.functionName}-autoscaling`,PolicyType:"TargetTrackingScaling",ScalingTargetId:{Ref:`${e.functionName}AutoScalingTarget`},TargetTrackingScalingPolicyConfiguration:{TargetValue:e.targetUtilization*100,PredefinedMetricSpecification:{PredefinedMetricType:"LambdaProvisionedConcurrencyUtilization"},ScaleInCooldown:e.scaleInCooldown||300,ScaleOutCooldown:e.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 jm=new Yr;class Xr{destinations=new Map;records=new Map;eventBridgeDestinations=new Map;destinationCounter=0;recordCounter=0;eventBridgeCounter=0;configureDestinations(e){let t=`destination-${Date.now()}-${this.destinationCounter++}`,a={id:t,...e};return this.destinations.set(t,a),a}configureSQSDestination(e){let t={type:"sqs",arn:e.queueArn};return this.configureDestinations({functionName:e.functionName,successDestination:e.onSuccess?t:void 0,failureDestination:e.onFailure?t:void 0,maxEventAge:21600,maxRetries:2})}configureSNSDestination(e){let t={type:"sns",arn:e.topicArn};return this.configureDestinations({functionName:e.functionName,successDestination:e.onSuccess?t:void 0,failureDestination:e.onFailure?t:void 0,maxEventAge:21600,maxRetries:2})}configureEventBridgeDestination(e){let t={type:"eventbridge",arn:e.eventBusArn};return this.configureDestinations({functionName:e.functionName,successDestination:e.onSuccess?t:void 0,failureDestination:e.onFailure?t:void 0,maxEventAge:21600,maxRetries:2})}configureLambdaDestination(e){let t={type:"lambda",arn:e.destinationFunctionArn};return this.configureDestinations({functionName:e.functionName,successDestination:e.onSuccess?t:void 0,failureDestination:e.onFailure?t:void 0,maxEventAge:21600,maxRetries:2})}configureDLQWithNotification(e){return this.configureDestinations({functionName:e.functionName,failureDestination:{type:"sqs",arn:e.dlqArn},maxEventAge:3600,maxRetries:0})}createEventBridgeIntegration(e){let t=`eventbridge-${Date.now()}-${this.eventBridgeCounter++}`,a={id:t,functionName:e.functionName,eventBusArn:e.eventBusArn,detailType:e.detailType||"Lambda Function Invocation Result",source:e.source||`lambda.${e.functionName}`};return this.eventBridgeDestinations.set(t,a),a}sendToDestination(e){let t=Array.from(this.destinations.values()).find((i)=>i.functionName===e.functionName);if(!t)return null;let a=e.status==="success"?t.successDestination:t.failureDestination;if(!a)return null;let r=`record-${Date.now()}-${this.recordCounter++}`,n={id:r,timestamp:new Date,functionName:e.functionName,requestId:e.requestId,status:e.status,destinationType:a.type,destinationArn:a.arn,payload:e.payload,error:e.error};return this.records.set(r,n),n}getDestination(e){return this.destinations.get(e)}listDestinations(e){let t=Array.from(this.destinations.values());return e?t.filter((a)=>a.functionName===e):t}getDestinationRecords(e){let t=Array.from(this.records.values());return e?t.filter((a)=>a.functionName===e):t}generateEventInvokeConfigCF(e){return{Type:"AWS::Lambda::EventInvokeConfig",Properties:{FunctionName:e.functionName,Qualifier:e.qualifier||"$LATEST",MaximumEventAgeInSeconds:e.maxEventAge||21600,MaximumRetryAttempts:e.maxRetries??2,...e.successDestination&&{DestinationConfig:{OnSuccess:{Destination:e.successDestination.arn}}},...e.failureDestination&&{DestinationConfig:{OnFailure:{Destination:e.failureDestination.arn}}}}}}generateEventBridgeRuleCF(e){return{Type:"AWS::Events::Rule",Properties:{EventBusName:e.eventBusArn.split("/").pop(),EventPattern:{source:[e.source],"detail-type":[e.detailType]},State:"ENABLED",Targets:[{Arn:`arn:aws:lambda:us-east-1:123456789012:function:${e.functionName}`,Id:e.id}]}}}clear(){this.destinations.clear(),this.records.clear(),this.eventBridgeDestinations.clear(),this.destinationCounter=0,this.recordCounter=0,this.eventBridgeCounter=0}}var Km=new Xr;class Zr{vpcConfigs=new Map;endpoints=new Map;networkInterfaces=new Map;connectivity=new Map;configCounter=0;endpointCounter=0;eniCounter=0;connectivityCounter=0;configureVPC(e){let t=`vpc-config-${Date.now()}-${this.configCounter++}`,a={id:t,...e};this.vpcConfigs.set(t,a);for(let r of e.subnetIds)this.createNetworkInterface({functionName:e.functionName,subnetId:r});return a}configurePrivateVPC(e){return this.configureVPC({functionName:e.functionName,vpcId:e.vpcId,subnetIds:e.privateSubnetIds,securityGroupIds:[e.securityGroupId],ipv6Allowed:!1})}configureMultiAZVPC(e){if(e.subnetIds.length<2)throw Error("Multi-AZ configuration requires at least 2 subnets");return this.configureVPC({functionName:e.functionName,vpcId:e.vpcId,subnetIds:e.subnetIds,securityGroupIds:e.securityGroupIds})}createVPCEndpoint(e){let t=`endpoint-${Date.now()}-${this.endpointCounter++}`,a={id:t,...e};return this.endpoints.set(t,a),a}createS3Endpoint(e){return this.createVPCEndpoint({vpcId:e.vpcId,serviceName:"com.amazonaws.us-east-1.s3",endpointType:"Gateway",privateDnsEnabled:!1})}createDynamoDBEndpoint(e){return this.createVPCEndpoint({vpcId:e.vpcId,serviceName:"com.amazonaws.us-east-1.dynamodb",endpointType:"Gateway",privateDnsEnabled:!1})}createSecretsManagerEndpoint(e){return this.createVPCEndpoint({vpcId:e.vpcId,serviceName:"com.amazonaws.us-east-1.secretsmanager",endpointType:"Interface",subnetIds:e.subnetIds,securityGroupIds:e.securityGroupIds,privateDnsEnabled:!0})}createNetworkInterface(e){let t=`eni-${Date.now()}-${this.eniCounter++}`,a={id:t,functionName:e.functionName,networkInterfaceId:`eni-${Math.random().toString(36).substring(2,15)}`,subnetId:e.subnetId,privateIpAddress:`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`,status:"creating",attachedAt:new Date};return this.networkInterfaces.set(t,a),setTimeout(()=>{a.status="available"},100),a}analyzeConnectivity(e){let t=`connectivity-${Date.now()}-${this.connectivityCounter++}`,a=Array.from(this.vpcConfigs.values()).find((c)=>c.functionName===e.functionName),r=Array.from(this.endpoints.values()).filter((c)=>c.vpcId===a?.vpcId).map((c)=>c.serviceName),n=[],i=e.hasNATGateway??!1,s=e.hasInternetGateway??!1;if(!i&&!s)n.push("Add NAT Gateway for internet access");if(!r.includes("com.amazonaws.us-east-1.s3"))n.push("Add S3 VPC endpoint to reduce NAT costs");if(!r.includes("com.amazonaws.us-east-1.dynamodb"))n.push("Add DynamoDB VPC endpoint for private access");let o={id:t,functionName:e.functionName,hasInternetAccess:i||s,hasNATGateway:i,hasVPCEndpoints:r.length>0,endpoints:r,recommendations:n};return this.connectivity.set(t,o),o}getVPCConfig(e){return this.vpcConfigs.get(e)}listVPCConfigs(e){let t=Array.from(this.vpcConfigs.values());return e?t.filter((a)=>a.functionName===e):t}getNetworkInterfaces(e){return Array.from(this.networkInterfaces.values()).filter((t)=>t.functionName===e)}listVPCEndpoints(e){let t=Array.from(this.endpoints.values());return e?t.filter((a)=>a.vpcId===e):t}generateVPCConfigCF(e){return{VpcConfig:{SubnetIds:e.subnetIds,SecurityGroupIds:e.securityGroupIds,...e.ipv6Allowed&&{Ipv6AllowedForDualStack:!0}}}}generateVPCEndpointCF(e){return{Type:"AWS::EC2::VPCEndpoint",Properties:{VpcId:e.vpcId,ServiceName:e.serviceName,VpcEndpointType:e.endpointType,...e.subnetIds&&{SubnetIds:e.subnetIds},...e.securityGroupIds&&{SecurityGroupIds:e.securityGroupIds},...e.privateDnsEnabled!==void 0&&{PrivateDnsEnabled:e.privateDnsEnabled}}}}generateSecurityGroupCF(e){return{Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:e.groupName,GroupDescription:`Security group for Lambda ${e.groupName}`,VpcId:e.vpcId,...e.ingressRules&&{SecurityGroupIngress:e.ingressRules.map((t)=>({IpProtocol:t.protocol,FromPort:t.fromPort,ToPort:t.toPort,...t.cidrIp&&{CidrIp:t.cidrIp},...t.sourceSecurityGroupId&&{SourceSecurityGroupId:t.sourceSecurityGroupId}}))},...e.egressRules&&{SecurityGroupEgress:e.egressRules.map((t)=>({IpProtocol:t.protocol,FromPort:t.fromPort,ToPort:t.toPort,CidrIp:t.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 Hm=new Zr;class en{dlqConfigs=new Map;messages=new Map;alarms=new Map;reprocessing=new Map;configCounter=0;messageCounter=0;alarmCounter=0;reprocessCounter=0;configureDLQ(e){let t=`dlq-${Date.now()}-${this.configCounter++}`,a={id:t,...e};return this.dlqConfigs.set(t,a),a}configureSQSDLQ(e){return this.configureDLQ({functionName:e.functionName,targetArn:e.queueArn,targetType:"sqs",maxReceiveCount:e.maxReceiveCount||3,retentionPeriod:e.retentionPeriod||1209600})}configureSNSDLQ(e){return this.configureDLQ({functionName:e.functionName,targetArn:e.topicArn,targetType:"sns"})}configureDLQWithAlarm(e){let t=this.configureSQSDLQ({functionName:e.functionName,queueArn:e.queueArn});return this.createDLQAlarm({dlqConfigId:t.id,alarmName:`${e.functionName}-dlq-alarm`,threshold:e.alarmThreshold,evaluationPeriods:1,notificationTopicArn:e.notificationTopicArn,enabled:!0}),t}sendToDLQ(e){let t=`message-${Date.now()}-${this.messageCounter++}`,a={id:t,timestamp:new Date,...e};return this.messages.set(t,a),a}createDLQAlarm(e){let t=`alarm-${Date.now()}-${this.alarmCounter++}`,a={id:t,...e};return this.alarms.set(t,a),a}createAgeAlarm(e){let t=this.dlqConfigs.get(e.dlqConfigId);if(!t)throw Error(`DLQ config not found: ${e.dlqConfigId}`);return this.createDLQAlarm({dlqConfigId:e.dlqConfigId,alarmName:`${t.functionName}-dlq-age-alarm`,threshold:e.maxAgeSeconds,evaluationPeriods:1,notificationTopicArn:e.notificationTopicArn,enabled:!0})}async reprocessMessage(e){let t=this.messages.get(e);if(!t)throw Error(`Message not found: ${e}`);let a=Array.from(this.dlqConfigs.values()).find((i)=>i.functionName===t.functionName);if(!a)throw Error(`DLQ config not found for function: ${t.functionName}`);let r=`reprocess-${Date.now()}-${this.reprocessCounter++}`,n={id:r,dlqConfigId:a.id,messageId:e,status:"pending",startedAt:new Date};return this.reprocessing.set(r,n),setTimeout(()=>{n.status="processing",setTimeout(()=>{let i=Math.random()>0.3;if(n.status=i?"success":"failed",n.completedAt=new Date,!i)n.error="Reprocessing failed - same error occurred";else this.messages.delete(e)},100)},50),n}async batchReprocess(e){let t=this.dlqConfigs.get(e.dlqConfigId);if(!t)throw Error(`DLQ config not found: ${e.dlqConfigId}`);let a=Array.from(this.messages.values()).filter((r)=>r.functionName===t.functionName).slice(0,e.maxMessages||10).map((r)=>this.reprocessMessage(r.id));return Promise.all(a)}getDLQStats(e){let t=this.dlqConfigs.get(e);if(!t)throw Error(`DLQ config not found: ${e}`);let a=Array.from(this.messages.values()).filter((s)=>s.functionName===t.functionName),r={},n=0;for(let s of a)r[s.errorType]=(r[s.errorType]||0)+1,n+=s.attemptCount;let i=a.map((s)=>s.timestamp);return{totalMessages:a.length,oldestMessage:i.length>0?new Date(Math.min(...i.map((s)=>s.getTime()))):void 0,newestMessage:i.length>0?new Date(Math.max(...i.map((s)=>s.getTime()))):void 0,averageAttempts:a.length>0?n/a.length:0,errorTypes:r}}getDLQConfig(e){return this.dlqConfigs.get(e)}listDLQConfigs(){return Array.from(this.dlqConfigs.values())}getDLQMessages(e){let t=this.dlqConfigs.get(e);if(!t)return[];return Array.from(this.messages.values()).filter((a)=>a.functionName===t.functionName)}generateDLQCF(e){return{DeadLetterConfig:{TargetArn:e.targetArn}}}generateSQSDLQCF(e){return{Type:"AWS::SQS::Queue",Properties:{QueueName:`${e.functionName}-dlq`,MessageRetentionPeriod:e.retentionPeriod||1209600,...e.maxReceiveCount&&{RedrivePolicy:{deadLetterTargetArn:e.targetArn,maxReceiveCount:e.maxReceiveCount}}}}}generateDLQAlarmCF(e){let t=this.dlqConfigs.get(e.dlqConfigId);if(!t)throw Error(`DLQ config not found: ${e.dlqConfigId}`);return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:e.alarmName,AlarmDescription:`DLQ alarm for ${t.functionName}`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Sum",Period:300,EvaluationPeriods:e.evaluationPeriods,Threshold:e.threshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:t.targetArn.split(":").pop()}],...e.notificationTopicArn&&{AlarmActions:[e.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 qm=new en;class tn{policies=new Map;healthChecks=new Map;trafficPolicies=new Map;policyCounter=0;healthCheckCounter=0;trafficPolicyCounter=0;createWeightedPolicy(e){let t=`policy-${Date.now()}-${this.policyCounter++}`,a={id:t,type:"weighted",...e};return this.policies.set(t,a),a}createLatencyPolicy(e){let t=`policy-${Date.now()}-${this.policyCounter++}`,a={id:t,type:"latency",...e};return this.policies.set(t,a),a}createFailoverPolicy(e){let t=`policy-${Date.now()}-${this.policyCounter++}`,a={id:t,type:"failover",...e};return this.policies.set(t,a),a}createGeolocationPolicy(e){let t=`policy-${Date.now()}-${this.policyCounter++}`,a={id:t,type:"geolocation",...e};return this.policies.set(t,a),a}createGeoproximityPolicy(e){let t=`policy-${Date.now()}-${this.policyCounter++}`,a={id:t,type:"geoproximity",...e};return this.policies.set(t,a),a}createHTTPHealthCheck(e){let t=`health-check-${Date.now()}-${this.healthCheckCounter++}`,a={id:t,type:e.port===443?"https":"http",requestInterval:e.requestInterval||30,failureThreshold:e.failureThreshold||3,healthCheckStatus:"Unknown",port:e.port||(e.port===443?443:80),...e};return this.healthChecks.set(t,a),setTimeout(()=>{a.healthCheckStatus=Math.random()>0.2?"Healthy":"Unhealthy"},100),a}createTCPHealthCheck(e){let t=`health-check-${Date.now()}-${this.healthCheckCounter++}`,a={id:t,type:"tcp",fullyQualifiedDomainName:e.ipAddress,requestInterval:e.requestInterval||30,failureThreshold:e.failureThreshold||3,healthCheckStatus:"Unknown",...e};return this.healthChecks.set(t,a),setTimeout(()=>{a.healthCheckStatus=Math.random()>0.1?"Healthy":"Unhealthy"},100),a}createCalculatedHealthCheck(e){let t=`health-check-${Date.now()}-${this.healthCheckCounter++}`,a={id:t,type:"calculated",requestInterval:30,failureThreshold:0,healthCheckStatus:"Unknown",...e};return this.healthChecks.set(t,a),setTimeout(()=>{let r=e.childHealthChecks.filter((n)=>{return this.healthChecks.get(n)?.healthCheckStatus==="Healthy"}).length;a.healthCheckStatus=r>=e.healthThreshold?"Healthy":"Unhealthy"},150),a}createTrafficPolicy(e){let t=`traffic-policy-${Date.now()}-${this.trafficPolicyCounter++}`,a={id:t,version:1,...e};return this.trafficPolicies.set(t,a),a}createFailoverTrafficPolicy(e){return this.createTrafficPolicy({name:e.name,document:{recordType:e.recordType||"A",startRule:"failover",endpoints:{primary:{type:"value",value:e.primaryEndpoint},secondary:{type:"value",value:e.secondaryEndpoint}},rules:{failover:{ruleType:"failover",primary:"primary",secondary:"secondary"}}}})}createGeoproximityTrafficPolicy(e){let t={},a=[];return e.locations.forEach((r,n)=>{let i=`endpoint${n}`;t[i]={type:"value",value:r.endpoint},a.push({endpointReference:i,region:r.region,latitude:r.latitude,longitude:r.longitude,bias:r.bias})}),this.createTrafficPolicy({name:e.name,document:{recordType:"A",startRule:"geoproximity",endpoints:t,rules:{geoproximity:{ruleType:"geoproximity",locations:a}}}})}getPolicy(e){return this.policies.get(e)}listPolicies(){return Array.from(this.policies.values())}getHealthCheck(e){return this.healthChecks.get(e)}listHealthChecks(){return Array.from(this.healthChecks.values())}getHealthCheckStatus(e){return this.healthChecks.get(e)?.healthCheckStatus||"Unknown"}generateHealthCheckCF(e){let t={Type:"AWS::Route53::HealthCheck",Properties:{HealthCheckConfig:{Type:e.type.toUpperCase(),RequestInterval:e.requestInterval,FailureThreshold:e.failureThreshold,...e.measureLatency&&{MeasureLatency:!0}},HealthCheckTags:[{Key:"Name",Value:e.name}]}};if(e.type==="calculated"){let a=e;t.Properties.HealthCheckConfig.ChildHealthChecks=a.childHealthChecks,t.Properties.HealthCheckConfig.HealthThreshold=a.healthThreshold}else{if(e.ipAddress)t.Properties.HealthCheckConfig.IPAddress=e.ipAddress;if(e.fullyQualifiedDomainName)t.Properties.HealthCheckConfig.FullyQualifiedDomainName=e.fullyQualifiedDomainName;if(e.port)t.Properties.HealthCheckConfig.Port=e.port;if(e.resourcePath)t.Properties.HealthCheckConfig.ResourcePath=e.resourcePath;if(e.enableSNI)t.Properties.HealthCheckConfig.EnableSNI=!0}return t}generateWeightedRecordSetCF(e){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:e.hostedZoneId,Name:e.name,Type:e.type,TTL:e.ttl,ResourceRecords:e.resourceRecords,Weight:e.weight,SetIdentifier:e.setIdentifier,...e.healthCheckId&&{HealthCheckId:e.healthCheckId}}}}generateFailoverRecordSetCF(e){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:e.hostedZoneId,Name:e.name,Type:e.type,TTL:e.ttl,ResourceRecords:e.resourceRecords,Failover:e.failover,SetIdentifier:e.setIdentifier,...e.healthCheckId&&{HealthCheckId:e.healthCheckId}}}}clear(){this.policies.clear(),this.healthChecks.clear(),this.trafficPolicies.clear(),this.policyCounter=0,this.healthCheckCounter=0,this.trafficPolicyCounter=0}}var zm=new tn;class an{configs=new Map;ksks=new Map;validations=new Map;configCounter=0;kskCounter=0;validationCounter=0;enableDNSSEC(e){let t=`dnssec-${Date.now()}-${this.configCounter++}`,a={id:t,hostedZoneId:e.hostedZoneId,status:"SIGNING",signingStatus:"Initializing DNSSEC signing"};if(this.configs.set(t,a),e.kmsKeyArn)this.createKSK({name:`ksk-${e.hostedZoneId}`,hostedZoneId:e.hostedZoneId,kmsKeyArn:e.kmsKeyArn});return setTimeout(()=>{a.status="SIGNED",a.signingStatus="DNSSEC signing complete"},100),a}disableDNSSEC(e){let t=this.configs.get(e);if(!t)throw Error(`DNSSEC config not found: ${e}`);return t.status="DELETING",t.signingStatus="Removing DNSSEC signing",setTimeout(()=>{t.status="NOT_SIGNING",t.signingStatus="DNSSEC signing removed"},100),t}createKSK(e){let t=`ksk-${Date.now()}-${this.kskCounter++}`,a={id:t,status:"ACTIVE",flag:257,keyManagementServiceArn:e.kmsKeyArn,digestAlgorithm:2,keyTag:Math.floor(Math.random()*65535),publicKey:this.generatePublicKey(),...e};a.dnskeyRecord=`${a.flag} 3 8 ${a.publicKey}`;let r=this.generateDigest(a.dnskeyRecord);return a.digestValue=r,a.dsRecord=`${a.keyTag} 8 ${a.digestAlgorithm} ${r}`,this.ksks.set(t,a),a}deactivateKSK(e){let t=this.ksks.get(e);if(!t)throw Error(`KSK not found: ${e}`);return t.status="INACTIVE",t}validateDNSSEC(e){let t=`validation-${Date.now()}-${this.validationCounter++}`,a=e.checkDNSKEY!==!1?Math.random()>0.1:!1,r=e.checkRRSIG!==!1?Math.random()>0.1:!1,n=a&&r,i=[];if(!a)i.push("DNSKEY record not found");if(!r)i.push("RRSIG record not found");let s;if(!a&&!r)s="INSECURE";else if(a&&r&&n)s="VALID";else if(a||r)s="BOGUS",i.push("Invalid signature or incomplete DNSSEC chain");else s="INVALID";let o={id:t,domain:e.domain,validationStatus:s,dnskeyPresent:a,rrsigPresent:r,validSignature:n,errors:i};return this.validations.set(t,o),o}getDNSSECConfig(e){return this.configs.get(e)}listDNSSECConfigs(){return Array.from(this.configs.values())}getKSK(e){return this.ksks.get(e)}listKSKs(e){let t=Array.from(this.ksks.values());return e?t.filter((a)=>a.hostedZoneId===e):t}getDSRecord(e){let t=this.ksks.get(e);if(!t||!t.dsRecord)throw Error("DS record not available");return t.dsRecord}generatePublicKey(){let e="";for(let t=0;t<256;t++)e+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(Math.floor(Math.random()*64));return e}generateDigest(e){let t="";for(let a=0;a<64;a++)t+="0123456789ABCDEF".charAt(Math.floor(Math.random()*16));return t}generateDNSSECCF(e){return{Type:"AWS::Route53::DNSSEC",Properties:{HostedZoneId:e.hostedZoneId}}}generateKSKCF(e){return{Type:"AWS::Route53::KeySigningKey",Properties:{Name:e.name,HostedZoneId:e.hostedZoneId,KeyManagementServiceArn:e.keyManagementServiceArn,Status:e.status}}}clear(){this.configs.clear(),this.ksks.clear(),this.validations.clear(),this.configCounter=0,this.kskCounter=0,this.validationCounter=0}}var Jm=new an;class rn{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(e){let t=`endpoint-${Date.now()}-${this.endpointCounter++}`,a={id:t,status:"CREATING",...e};return this.endpoints.set(t,a),setTimeout(()=>{a.status="OPERATIONAL",a.ipAddresses.forEach((r)=>{if(!r.ip)r.ip=`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`})},100),a}createInboundEndpoint(e){return this.createResolverEndpoint({name:e.name,direction:"INBOUND",ipAddresses:e.subnetIds.map((t)=>({subnetId:t})),securityGroupIds:e.securityGroupIds})}createOutboundEndpoint(e){return this.createResolverEndpoint({name:e.name,direction:"OUTBOUND",ipAddresses:e.subnetIds.map((t)=>({subnetId:t})),securityGroupIds:e.securityGroupIds})}createResolverRule(e){let t=`rule-${Date.now()}-${this.ruleCounter++}`,a={id:t,status:"CREATING",...e};return this.rules.set(t,a),setTimeout(()=>{a.status="COMPLETE"},100),a}createForwardRule(e){return this.createResolverRule({name:e.name,ruleType:"FORWARD",domainName:e.domainName,targetIps:e.targetIps,resolverEndpointId:e.resolverEndpointId})}createSystemRule(e){return this.createResolverRule({name:e.name,ruleType:"SYSTEM",domainName:e.domainName})}createFirewallDomainList(e){let t=`domain-list-${Date.now()}-${this.domainListCounter++}`,a={id:t,status:"CREATING",...e};return this.domainLists.set(t,a),setTimeout(()=>{a.status="COMPLETE"},100),a}createFirewallRuleGroup(e){let t=`rule-group-${Date.now()}-${this.ruleGroupCounter++}`,a={id:t,name:e.name,rules:e.rules.map((r,n)=>({id:`rule-${t}-${n}`,...r})),shareStatus:"NOT_SHARED"};return this.ruleGroups.set(t,a),a}createBlockRule(e){return this.createFirewallRuleGroup({name:e.name,rules:[{name:e.name,priority:e.priority,action:"BLOCK",blockResponse:e.blockResponse||"NODATA",blockOverrideDomain:e.blockOverrideDomain,firewallDomainListId:e.domainListId}]})}createAllowRule(e){return this.createFirewallRuleGroup({name:e.name,rules:[{name:e.name,priority:e.priority,action:"ALLOW",firewallDomainListId:e.domainListId}]})}createDNSFirewall(e){let t=`firewall-${Date.now()}-${this.firewallCounter++}`,a={id:t,name:e.name,firewallRuleGroupAssociations:e.ruleGroupAssociations.map((r,n)=>({id:`assoc-${t}-${n}`,vpcId:e.vpcId,firewallRuleGroupId:r.firewallRuleGroupId,priority:r.priority,mutationProtection:r.mutationProtection||"DISABLED",status:"COMPLETE"}))};return this.firewalls.set(t,a),a}createMalwareProtectionFirewall(e){let t=this.createFirewallDomainList({name:`${e.name}-malware-domains`,domains:e.maliciousDomains}),a=this.createBlockRule({name:`${e.name}-block-malware`,priority:100,domainListId:t.id,blockResponse:"NXDOMAIN"});return this.createDNSFirewall({name:e.name,vpcId:e.vpcId,ruleGroupAssociations:[{firewallRuleGroupId:a.id,priority:100,mutationProtection:"ENABLED"}]})}getEndpoint(e){return this.endpoints.get(e)}listEndpoints(e){let t=Array.from(this.endpoints.values());return e?t.filter((a)=>a.direction===e):t}getRule(e){return this.rules.get(e)}listRules(){return Array.from(this.rules.values())}getFirewall(e){return this.firewalls.get(e)}listFirewalls(){return Array.from(this.firewalls.values())}generateResolverEndpointCF(e){return{Type:"AWS::Route53Resolver::ResolverEndpoint",Properties:{Name:e.name,Direction:e.direction,IpAddresses:e.ipAddresses.map((t)=>({SubnetId:t.subnetId,...t.ip&&{Ip:t.ip}})),SecurityGroupIds:e.securityGroupIds}}}generateResolverRuleCF(e){return{Type:"AWS::Route53Resolver::ResolverRule",Properties:{Name:e.name,RuleType:e.ruleType,DomainName:e.domainName,...e.targetIps&&{TargetIps:e.targetIps.map((t)=>({Ip:t.ip,Port:t.port||53}))},...e.resolverEndpointId&&{ResolverEndpointId:e.resolverEndpointId}}}}generateFirewallRuleGroupCF(e){return{Type:"AWS::Route53Resolver::FirewallRuleGroup",Properties:{Name:e.name,FirewallRules:e.rules.map((t)=>({Name:t.name,Priority:t.priority,Action:t.action,FirewallDomainListId:t.firewallDomainListId,...t.blockResponse&&{BlockResponse:t.blockResponse},...t.blockOverrideDomain&&{BlockOverrideDomain:t.blockOverrideDomain},...t.blockOverrideTTL&&{BlockOverrideTtl:t.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 Qm=new rn;class nn{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(e){let t=`bounce-${Date.now()}-${this.bounceCounter++}`,a={id:t,...e};if(this.bounces.set(t,a),e.bounceType==="Permanent")this.addToSuppressionList({emailAddress:e.recipient,reason:"BOUNCE"});return a}recordComplaint(e){let t=`complaint-${Date.now()}-${this.complaintCounter++}`,a={id:t,...e};this.complaints.set(t,a);for(let r of e.recipients)this.addToSuppressionList({emailAddress:r,reason:"COMPLAINT"});return a}createBounceHandler(e){let t=`handler-${Date.now()}-${this.handlerCounter++}`,a={id:t,...e};return this.handlers.set(t,a),a}createAutomaticBounceHandler(e){return this.createBounceHandler({name:e.name,bounceThreshold:5,complaintThreshold:0.1,suppressionDuration:2592000,autoSuppress:!0,notificationTopicArn:e.notificationTopicArn})}addToSuppressionList(e){let t=`suppression-${Date.now()}-${this.suppressionCounter++}`,a=e.expirationDays?new Date(Date.now()+e.expirationDays*24*60*60*1000):void 0,r={id:t,emailAddress:e.emailAddress,reason:e.reason,suppressedAt:new Date,expiresAt:a,bounceCount:e.reason==="BOUNCE"?1:0,complaintCount:e.reason==="COMPLAINT"?1:0};return this.suppressionList.set(e.emailAddress,r),r}removeFromSuppressionList(e){return this.suppressionList.delete(e)}isSuppressed(e){let t=this.suppressionList.get(e);if(!t)return!1;if(t.expiresAt&&t.expiresAt<new Date)return this.suppressionList.delete(e),!1;return!0}getBounceStatistics(e,t){let a=Array.from(this.bounces.values()).filter((u)=>u.timestamp>=e&&u.timestamp<=t),r=a.length,n=a.filter((u)=>u.bounceType==="Permanent").length,i=a.filter((u)=>u.bounceType==="Transient").length,s=r*10,o=r/s*100,c=new Map;for(let u of a)c.set(u.recipient,(c.get(u.recipient)||0)+1);let l=Array.from(c.entries()).map(([u,m])=>({email:u,count:m})).sort((u,m)=>m.count-u.count).slice(0,10);return{totalBounces:r,permanentBounces:n,transientBounces:i,bounceRate:o,topRecipients:l}}getComplaintStatistics(e,t){let a=Array.from(this.complaints.values()).filter((c)=>c.timestamp>=e&&c.timestamp<=t),r=a.length,n=new Set;for(let c of a)for(let l of c.recipients)n.add(l);let i=n.size,s=r*1000,o=r/s*100;return{totalComplaints:r,uniqueComplainters:i,complaintRate:o}}calculateReputationMetrics(){let e=`metrics-${Date.now()}-${this.metricsCounter++}`,t=new Date,a=new Date(t.getTime()-86400000),r=this.getBounceStatistics(a,t),n=this.getComplaintStatistics(a,t),i;if(r.bounceRate>10||n.complaintRate>0.5)i="Shutdown";else if(r.bounceRate>5||n.complaintRate>0.1)i="Probation";else if(r.bounceRate>2||n.complaintRate>0.05)i="Warning";else i="Good";let s={id:e,timestamp:t,bounceRate:r.bounceRate,complaintRate:n.complaintRate,sendingQuota:50000,maxSendRate:14,sentLast24Hours:r.totalBounces*10,reputationStatus:i};return this.metrics.set(e,s),s}getBounces(e){let t=Array.from(this.bounces.values());return e?t.filter((a)=>a.messageId===e):t}getComplaints(e){let t=Array.from(this.complaints.values());return e?t.filter((a)=>a.messageId===e):t}listSuppressionList(e){let t=Array.from(this.suppressionList.values());return e?t.filter((a)=>a.reason===e):t}generateSNSSubscriptionCF(e){return{Type:"AWS::SNS::Subscription",Properties:{TopicArn:e.topicArn,Endpoint:e.endpoint,Protocol:e.protocol}}}generateEventDestinationCF(e){return{Type:"AWS::SES::ConfigurationSetEventDestination",Properties:{ConfigurationSetName:e.configurationSetName,EventDestination:{Name:e.eventDestinationName,Enabled:!0,MatchingEventTypes:e.eventTypes,...e.snsTopicArn&&{SnsDestination:{TopicARN:e.snsTopicArn}},...e.cloudWatchDestination&&{CloudWatchDestination:e.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 $m=new nn;class sn{events=new Map;campaigns=new Map;reports=new Map;abTests=new Map;eventCounter=0;campaignCounter=0;reportCounter=0;abTestCounter=0;trackEvent(e){let t=`event-${Date.now()}-${this.eventCounter++}`,a={id:t,...e};if(this.events.set(t,a),e.tags?.campaignId)this.updateCampaignStats(e.tags.campaignId,e.eventType);return a}trackOpen(e){return this.trackEvent({...e,eventType:"open",timestamp:new Date})}trackClick(e){return this.trackEvent({...e,eventType:"click",timestamp:new Date})}createCampaign(e){let t=`campaign-${Date.now()}-${this.campaignCounter++}`,a={id:t,sentCount:0,deliveredCount:0,openCount:0,clickCount:0,bounceCount:0,complaintCount:0,createdAt:new Date,...e};return this.campaigns.set(t,a),a}updateCampaignStats(e,t){let a=this.campaigns.get(e);if(!a)return;switch(t){case"send":a.sentCount++;break;case"delivery":a.deliveredCount++;break;case"open":a.openCount++;break;case"click":a.clickCount++;break;case"bounce":a.bounceCount++;break;case"complaint":a.complaintCount++;break}}generateReport(e){let t=`report-${Date.now()}-${this.reportCounter++}`,a=Array.from(this.events.values()).filter((S)=>{let E=S.timestamp>=e.startDate&&S.timestamp<=e.endDate,v=!e.campaignId||S.tags?.campaignId===e.campaignId;return E&&v}),r=a.filter((S)=>S.eventType==="send").length,n=a.filter((S)=>S.eventType==="delivery").length,i=a.filter((S)=>S.eventType==="open").length,s=a.filter((S)=>S.eventType==="click").length,o=a.filter((S)=>S.eventType==="bounce").length,c=a.filter((S)=>S.eventType==="complaint").length,l=r>0?n/r*100:0,u=n>0?i/n*100:0,m=n>0?s/n*100:0,p=i>0?s/i*100:0,g=r>0?o/r*100:0,h=n>0?c/n*100:0,y=new Map;for(let S of a)if(S.eventType==="click"){let E=S;y.set(E.link,(y.get(E.link)||0)+1)}let b=Array.from(y.entries()).map(([S,E])=>({link:S,clicks:E})).sort((S,E)=>E.clicks-S.clicks).slice(0,10),T={desktop:0,mobile:0,tablet:0,unknown:0};for(let S of a)if(S.eventType==="open"||S.eventType==="click"){let E=S.userAgent.toLowerCase();if(E.includes("mobile"))T.mobile++;else if(E.includes("tablet"))T.tablet++;else if(E.includes("mozilla"))T.desktop++;else T.unknown++}let w={id:t,campaignId:e.campaignId,startDate:e.startDate,endDate:e.endDate,totalSent:r,totalDelivered:n,totalOpened:i,totalClicked:s,totalBounced:o,totalComplaints:c,deliveryRate:l,openRate:u,clickRate:m,clickToOpenRate:p,bounceRate:g,complaintRate:h,topLinks:b,deviceBreakdown:T,locationBreakdown:{}};return this.reports.set(t,w),w}createABTest(e){let t=`abtest-${Date.now()}-${this.abTestCounter++}`,a={id:t,name:e.name,variants:e.variants.map((r,n)=>({id:`variant-${t}-${n}`,sentCount:0,openCount:0,clickCount:0,conversionCount:0,...r})),status:"draft"};return this.abTests.set(t,a),a}startABTest(e){let t=this.abTests.get(e);if(!t)throw Error(`A/B test not found: ${e}`);return t.status="running",t.startedAt=new Date,t}completeABTest(e){let t=this.abTests.get(e);if(!t)throw Error(`A/B test not found: ${e}`);let a=t.variants[0],r=0;for(let n of t.variants){let i=n.sentCount>0?n.openCount/n.sentCount:0;if(i>r)r=i,a=n}return t.status="completed",t.completedAt=new Date,t.winner=a.id,t}getCampaign(e){return this.campaigns.get(e)}listCampaigns(){return Array.from(this.campaigns.values())}getEvents(e){let t=Array.from(this.events.values());if(e?.messageId)t=t.filter((a)=>a.messageId===e.messageId);if(e?.eventType)t=t.filter((a)=>a.eventType===e.eventType);if(e?.startDate)t=t.filter((a)=>a.timestamp>=e.startDate);if(e?.endDate)t=t.filter((a)=>a.timestamp<=e.endDate);return t}generateTrackingConfigurationCF(e){return{Type:"AWS::SES::ConfigurationSet",Properties:{Name:e.configurationSetName,...e.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 Ym=new sn;class on{dashboards=new Map;warmupPlans=new Map;domainReputations=new Map;dashboardCounter=0;warmupCounter=0;domainCounter=0;getReputationDashboard(){let e=`dashboard-${Date.now()}-${this.dashboardCounter++}`,t=Math.random()*5,a=Math.random()*0.5,r=Math.floor(Math.random()*10),n=Math.max(0,100-t*10-a*100-r*2),i=[];if(t>2)i.push("Reduce bounce rate by cleaning email list");if(a>0.1)i.push("Review email content and unsubscribe process");if(r>5)i.push("Improve email relevance and targeting");let s={id:e,timestamp:new Date,overallScore:n,bounceRate:t,complaintRate:a,spamReports:r,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:i};return this.dashboards.set(e,s),s}checkBlacklists(){return["Spamhaus ZEN","Spamcop","SORBS","Barracuda","URIBL"].map((e)=>({listName:e,listed:Math.random()>0.95,delistUrl:`https://www.${e.toLowerCase().replace(/\s/g,"")}.org/delist`}))}createWarmupPlan(e){let t=`warmup-${Date.now()}-${this.warmupCounter++}`,a=[],r=(e.targetDailyLimit-e.initialDailyLimit)/e.durationDays;for(let i=0;i<e.durationDays;i++)a.push(Math.floor(e.initialDailyLimit+r*i));let n={id:t,name:e.name,startDate:new Date,currentDay:1,totalDays:e.durationDays,dailyLimits:a,currentLimit:a[0],status:"active"};return this.warmupPlans.set(t,n),n}createAggressiveWarmupPlan(e){return this.createWarmupPlan({name:e.name,initialDailyLimit:500,targetDailyLimit:50000,durationDays:14})}createConservativeWarmupPlan(e){return this.createWarmupPlan({name:e.name,initialDailyLimit:200,targetDailyLimit:50000,durationDays:30})}advanceWarmupPlan(e){let t=this.warmupPlans.get(e);if(!t)throw Error(`Warmup plan not found: ${e}`);if(t.currentDay<t.totalDays)t.currentDay++,t.currentLimit=t.dailyLimits[t.currentDay-1];if(t.currentDay>=t.totalDays)t.status="completed";return t}trackDomainReputation(e){let t=`domain-${Date.now()}-${this.domainCounter++}`,a=e.delivered/e.totalSent*100,r=e.delivered>0?e.opened/e.delivered*100:0,n=e.delivered>0?e.clicked/e.delivered*100:0,i=e.bounced/e.totalSent*100,s=e.delivered>0?e.complained/e.delivered*100:0,o=r*0.4+n*0.6,c=Math.max(0,100-i*10-s*100+o*0.2),l={id:t,domain:e.domain,reputationScore:c,totalSent:e.totalSent,deliveryRate:a,openRate:r,clickRate:n,bounceRate:i,complaintRate:s,engagementScore:o};return this.domainReputations.set(e.domain,l),l}getDomainReputation(e){return this.domainReputations.get(e)}listDomainReputations(){return Array.from(this.domainReputations.values())}getWarmupPlan(e){return this.warmupPlans.get(e)}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 Xm=new on;class cn{templates=new Map;versions=new Map;tests=new Map;templateCounter=0;testCounter=0;createTemplate(e){let t=`template-${Date.now()}-${this.templateCounter++}`,a=this.extractVariables(e.subject+e.htmlPart+e.textPart),r={id:t,variables:a,createdAt:new Date,updatedAt:new Date,version:1,...e};return this.templates.set(t,r),this.addVersion({templateId:t,version:1,subject:e.subject,htmlPart:e.htmlPart,textPart:e.textPart,createdBy:"system"}),r}createWelcomeTemplate(e){return this.createTemplate({name:e.name,subject:"Welcome to {{companyName}}!",htmlPart:`
3787
3787
  <html>
3788
3788
  <body>
3789
3789
  <h1>Welcome, {{userName}}!</h1>
@@ -3803,7 +3803,7 @@ COPY . .`,impact:"Improve build time by 60-80% on subsequent builds"});let o={si
3803
3803
  <p>If you didn't request this, please ignore this email.</p>
3804
3804
  </body>
3805
3805
  </html>
3806
- `,textPart:"Hi {{userName}}, reset your password at: {{resetUrl}}. This link expires in {{expirationHours}} hours."})}updateTemplate(e,t,a){let r=this.templates.get(e);if(!r)throw Error(`Template not found: ${e}`);if(t.subject)r.subject=t.subject;if(t.htmlPart)r.htmlPart=t.htmlPart;if(t.textPart)r.textPart=t.textPart;return r.version++,r.updatedAt=new Date,r.variables=this.extractVariables(r.subject+r.htmlPart+r.textPart),this.addVersion({templateId:e,version:r.version,subject:r.subject,htmlPart:r.htmlPart,textPart:r.textPart,createdBy:"system",changelog:a}),r}addVersion(e){let t={id:`version-${e.templateId}-${e.version}`,createdAt:new Date,...e},a=this.versions.get(e.templateId)||[];return a.push(t),this.versions.set(e.templateId,a),t}extractVariables(e){let t=/\{\{([^}]+)\}\}/g,a=new Set,r;while((r=t.exec(e))!==null)a.add(r[1].trim());return Array.from(a)}renderTemplate(e,t){let a=this.templates.get(e);if(!a)throw Error(`Template not found: ${e}`);let r=(n)=>n.replace(/\{\{([^}]+)\}\}/g,(i,s)=>{let o=s.trim();return t[o]!==void 0?String(t[o]):i});return{subject:r(a.subject),html:r(a.htmlPart),text:r(a.textPart)}}testTemplate(e,t){let a=`test-${Date.now()}-${this.testCounter++}`,r=this.renderTemplate(e,t),n={id:a,templateId:e,testData:t,renderedSubject:r.subject,renderedHtml:r.html,renderedText:r.text,timestamp:new Date};return this.tests.set(a,n),n}getTemplate(e){return this.templates.get(e)}listTemplates(){return Array.from(this.templates.values())}getTemplateVersions(e){return this.versions.get(e)||[]}revertToVersion(e,t){let a=this.templates.get(e);if(!a)throw Error(`Template not found: ${e}`);let r=(this.versions.get(e)||[]).find((n)=>n.version===t);if(!r)throw Error(`Version ${t} not found for template ${e}`);return a.subject=r.subject,a.htmlPart=r.htmlPart,a.textPart=r.textPart,a.version++,a.updatedAt=new Date,this.addVersion({templateId:e,version:a.version,subject:a.subject,htmlPart:a.htmlPart,textPart:a.textPart,createdBy:"system",changelog:`Reverted to version ${t}`}),a}generateTemplateCF(e){return{Type:"AWS::SES::Template",Properties:{Template:{TemplateName:e.name,SubjectPart:e.subject,HtmlPart:e.htmlPart,TextPart:e.textPart}}}}clear(){this.templates.clear(),this.versions.clear(),this.tests.clear(),this.templateCounter=0,this.testCounter=0}}var ep=new ln,Bo={};De(Bo,{EmailAnalyticsModule:()=>tt,EmailRules:()=>sa,EmailScheduling:()=>na,EmailSearch:()=>aa,EmailTemplates:()=>Re,EmailThreading:()=>ra,SharedMailboxes:()=>ia});class aa{static createSearchDomain(e){let{slug:t,environment:a,domainName:r,instanceType:n="t3.small.search",instanceCount:i=1,ebsVolumeSize:s=10,masterUserName:o="admin",masterUserPassword:c}=e,l=r||`${t}-${a}-email-search`;return{[`${t}EmailSearchDomain`]:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:l,EngineVersion:"OpenSearch_2.11",ClusterConfig:{InstanceType:n,InstanceCount:i,DedicatedMasterEnabled:!1,ZoneAwarenessEnabled:!1},EBSOptions:{EBSEnabled:!0,VolumeType:"gp3",VolumeSize:s},NodeToNodeEncryptionOptions:{Enabled:!0},EncryptionAtRestOptions:{Enabled:!0},DomainEndpointOptions:{EnforceHTTPS:!0},AdvancedSecurityOptions:{Enabled:!0,InternalUserDatabaseEnabled:!0,MasterUserOptions:{MasterUserName:o,MasterUserPassword:c||`${t}-search-${Date.now()}`}},AccessPolicies:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:`arn:aws:es:*:*:domain/${l}/*`}]}}}}}static createIndexerLambda(e){return{[`${e.slug}EmailIndexerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-email-indexer`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:60,MemorySize:512,Code:{ZipFile:aa.IndexerLambdaCode},Environment:{Variables:{OPENSEARCH_ENDPOINT:e.searchDomainEndpoint,EMAIL_BUCKET:e.emailBucket}}}}}}static IndexerLambdaCode=`
3806
+ `,textPart:"Hi {{userName}}, reset your password at: {{resetUrl}}. This link expires in {{expirationHours}} hours."})}updateTemplate(e,t,a){let r=this.templates.get(e);if(!r)throw Error(`Template not found: ${e}`);if(t.subject)r.subject=t.subject;if(t.htmlPart)r.htmlPart=t.htmlPart;if(t.textPart)r.textPart=t.textPart;return r.version++,r.updatedAt=new Date,r.variables=this.extractVariables(r.subject+r.htmlPart+r.textPart),this.addVersion({templateId:e,version:r.version,subject:r.subject,htmlPart:r.htmlPart,textPart:r.textPart,createdBy:"system",changelog:a}),r}addVersion(e){let t={id:`version-${e.templateId}-${e.version}`,createdAt:new Date,...e},a=this.versions.get(e.templateId)||[];return a.push(t),this.versions.set(e.templateId,a),t}extractVariables(e){let t=/\{\{([^}]+)\}\}/g,a=new Set,r;while((r=t.exec(e))!==null)a.add(r[1].trim());return Array.from(a)}renderTemplate(e,t){let a=this.templates.get(e);if(!a)throw Error(`Template not found: ${e}`);let r=(n)=>{return n.replace(/\{\{([^}]+)\}\}/g,(i,s)=>{let o=s.trim();return t[o]!==void 0?String(t[o]):i})};return{subject:r(a.subject),html:r(a.htmlPart),text:r(a.textPart)}}testTemplate(e,t){let a=`test-${Date.now()}-${this.testCounter++}`,r=this.renderTemplate(e,t),n={id:a,templateId:e,testData:t,renderedSubject:r.subject,renderedHtml:r.html,renderedText:r.text,timestamp:new Date};return this.tests.set(a,n),n}getTemplate(e){return this.templates.get(e)}listTemplates(){return Array.from(this.templates.values())}getTemplateVersions(e){return this.versions.get(e)||[]}revertToVersion(e,t){let a=this.templates.get(e);if(!a)throw Error(`Template not found: ${e}`);let r=(this.versions.get(e)||[]).find((n)=>n.version===t);if(!r)throw Error(`Version ${t} not found for template ${e}`);return a.subject=r.subject,a.htmlPart=r.htmlPart,a.textPart=r.textPart,a.version++,a.updatedAt=new Date,this.addVersion({templateId:e,version:a.version,subject:a.subject,htmlPart:a.htmlPart,textPart:a.textPart,createdBy:"system",changelog:`Reverted to version ${t}`}),a}generateTemplateCF(e){return{Type:"AWS::SES::Template",Properties:{Template:{TemplateName:e.name,SubjectPart:e.subject,HtmlPart:e.htmlPart,TextPart:e.textPart}}}}clear(){this.templates.clear(),this.versions.clear(),this.tests.clear(),this.templateCounter=0,this.testCounter=0}}var Zm=new cn,Wo={};Ne(Wo,{SharedMailboxes:()=>na,EmailThreading:()=>aa,EmailTemplates:()=>Ie,EmailSearch:()=>ta,EmailScheduling:()=>ra,EmailRules:()=>ia,EmailAnalyticsModule:()=>et});class ta{static createSearchDomain(e){let{slug:t,environment:a,domainName:r,instanceType:n="t3.small.search",instanceCount:i=1,ebsVolumeSize:s=10,masterUserName:o="admin",masterUserPassword:c}=e,l=r||`${t}-${a}-email-search`;return{[`${t}EmailSearchDomain`]:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:l,EngineVersion:"OpenSearch_2.11",ClusterConfig:{InstanceType:n,InstanceCount:i,DedicatedMasterEnabled:!1,ZoneAwarenessEnabled:!1},EBSOptions:{EBSEnabled:!0,VolumeType:"gp3",VolumeSize:s},NodeToNodeEncryptionOptions:{Enabled:!0},EncryptionAtRestOptions:{Enabled:!0},DomainEndpointOptions:{EnforceHTTPS:!0},AdvancedSecurityOptions:{Enabled:!0,InternalUserDatabaseEnabled:!0,MasterUserOptions:{MasterUserName:o,MasterUserPassword:c||`${t}-search-${Date.now()}`}},AccessPolicies:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:`arn:aws:es:*:*:domain/${l}/*`}]}}}}}static createIndexerLambda(e){return{[`${e.slug}EmailIndexerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-email-indexer`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:60,MemorySize:512,Code:{ZipFile:ta.IndexerLambdaCode},Environment:{Variables:{OPENSEARCH_ENDPOINT:e.searchDomainEndpoint,EMAIL_BUCKET:e.emailBucket}}}}}}static IndexerLambdaCode=`
3807
3807
  const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
3808
3808
  const https = require('https');
3809
3809
 
@@ -3903,7 +3903,7 @@ async function indexDocument(doc) {
3903
3903
  req.end();
3904
3904
  });
3905
3905
  }
3906
- `;static getIndexMapping(){return{mappings:{properties:{messageId:{type:"keyword"},from:{type:"keyword"},fromName:{type:"text"},to:{type:"keyword"},toName:{type:"text"},cc:{type:"keyword"},subject:{type:"text",analyzer:"standard",fields:{keyword:{type:"keyword"}}},body:{type:"text",analyzer:"standard"},bodyPreview:{type:"text"},date:{type:"date"},receivedAt:{type:"date"},hasAttachments:{type:"boolean"},attachmentNames:{type:"keyword"},labels:{type:"keyword"},folder:{type:"keyword"},threadId:{type:"keyword"},isRead:{type:"boolean"},isStarred:{type:"boolean"},mailbox:{type:"keyword"}}},settings:{number_of_shards:1,number_of_replicas:0}}}static buildSearchQuery(e){let t=[],a=[];if(e.query)t.push({multi_match:{query:e.query,fields:["subject^3","body","fromName","toName"],type:"best_fields",fuzziness:"AUTO"}});if(e.from)a.push({term:{from:e.from}});if(e.to)a.push({term:{to:e.to}});if(e.subject)t.push({match_phrase:{subject:e.subject}});if(e.hasAttachments!==void 0)a.push({term:{hasAttachments:e.hasAttachments}});if(e.folder)a.push({term:{folder:e.folder}});if(e.labels&&e.labels.length>0)a.push({terms:{labels:e.labels}});if(e.isRead!==void 0)a.push({term:{isRead:e.isRead}});if(e.dateFrom||e.dateTo){let i={date:{}};if(e.dateFrom)i.date.gte=e.dateFrom;if(e.dateTo)i.date.lte=e.dateTo;a.push({range:i})}let r={bool:{}};if(t.length>0)r.bool.must=t;if(a.length>0)r.bool.filter=a;if(t.length===0&&a.length===0)r.bool.must=[{match_all:{}}];let n=[];if(e.sort==="relevance"&&e.query)n.push({_score:e.sortOrder||"desc"});return n.push({date:e.sortOrder||"desc"}),{query:r,sort:n,from:e.offset||0,size:e.limit||20,highlight:{fields:{subject:{},body:{fragment_size:150,number_of_fragments:3}}}}}}class ra{static ThreadingLambdaCode=`
3906
+ `;static getIndexMapping(){return{mappings:{properties:{messageId:{type:"keyword"},from:{type:"keyword"},fromName:{type:"text"},to:{type:"keyword"},toName:{type:"text"},cc:{type:"keyword"},subject:{type:"text",analyzer:"standard",fields:{keyword:{type:"keyword"}}},body:{type:"text",analyzer:"standard"},bodyPreview:{type:"text"},date:{type:"date"},receivedAt:{type:"date"},hasAttachments:{type:"boolean"},attachmentNames:{type:"keyword"},labels:{type:"keyword"},folder:{type:"keyword"},threadId:{type:"keyword"},isRead:{type:"boolean"},isStarred:{type:"boolean"},mailbox:{type:"keyword"}}},settings:{number_of_shards:1,number_of_replicas:0}}}static buildSearchQuery(e){let t=[],a=[];if(e.query)t.push({multi_match:{query:e.query,fields:["subject^3","body","fromName","toName"],type:"best_fields",fuzziness:"AUTO"}});if(e.from)a.push({term:{from:e.from}});if(e.to)a.push({term:{to:e.to}});if(e.subject)t.push({match_phrase:{subject:e.subject}});if(e.hasAttachments!==void 0)a.push({term:{hasAttachments:e.hasAttachments}});if(e.folder)a.push({term:{folder:e.folder}});if(e.labels&&e.labels.length>0)a.push({terms:{labels:e.labels}});if(e.isRead!==void 0)a.push({term:{isRead:e.isRead}});if(e.dateFrom||e.dateTo){let i={date:{}};if(e.dateFrom)i.date.gte=e.dateFrom;if(e.dateTo)i.date.lte=e.dateTo;a.push({range:i})}let r={bool:{}};if(t.length>0)r.bool.must=t;if(a.length>0)r.bool.filter=a;if(t.length===0&&a.length===0)r.bool.must=[{match_all:{}}];let n=[];if(e.sort==="relevance"&&e.query)n.push({_score:e.sortOrder||"desc"});return n.push({date:e.sortOrder||"desc"}),{query:r,sort:n,from:e.offset||0,size:e.limit||20,highlight:{fields:{subject:{},body:{fragment_size:150,number_of_fragments:3}}}}}}class aa{static ThreadingLambdaCode=`
3907
3907
  const { S3Client, GetObjectCommand, PutObjectCommand } = require('@aws-sdk/client-s3');
3908
3908
  const crypto = require('crypto');
3909
3909
 
@@ -4043,7 +4043,7 @@ catch {
4043
4043
  ContentType: 'application/json',
4044
4044
  }));
4045
4045
  }
4046
- `;static createThreadingLambda(e){return{[`${e.slug}EmailThreadingLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-email-threading`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:ra.ThreadingLambdaCode},Environment:{Variables:{EMAIL_BUCKET:e.emailBucket}}}}}}static async getThreads(e){let{s3Client:t,bucket:a,mailbox:r,limit:n=50,offset:i=0}=e,[s,o]=r.includes("@")?r.split("@"):[r,"default"],c=`mailboxes/${o}/${s}/threads.json`;try{let l=await t.send({Bucket:a,Key:c}),u=JSON.parse(l.Body),m=Object.values(u);return m.sort((p,g)=>new Date(g.lastMessageDate).getTime()-new Date(p.lastMessageDate).getTime()),m.slice(i,i+n)}catch{return[]}}static async getThread(e){let{s3Client:t,bucket:a,mailbox:r,threadId:n}=e,[i,s]=r.includes("@")?r.split("@"):[r,"default"],o=`mailboxes/${s}/${i}/threads.json`;try{let c=await t.send({Bucket:a,Key:o});return JSON.parse(c.Body)[n]||null}catch{return null}}}class na{static SchedulerLambdaCode=`
4046
+ `;static createThreadingLambda(e){return{[`${e.slug}EmailThreadingLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-email-threading`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:aa.ThreadingLambdaCode},Environment:{Variables:{EMAIL_BUCKET:e.emailBucket}}}}}}static async getThreads(e){let{s3Client:t,bucket:a,mailbox:r,limit:n=50,offset:i=0}=e,[s,o]=r.includes("@")?r.split("@"):[r,"default"],c=`mailboxes/${o}/${s}/threads.json`;try{let l=await t.send({Bucket:a,Key:c}),u=JSON.parse(l.Body),m=Object.values(u);return m.sort((p,g)=>new Date(g.lastMessageDate).getTime()-new Date(p.lastMessageDate).getTime()),m.slice(i,i+n)}catch{return[]}}static async getThread(e){let{s3Client:t,bucket:a,mailbox:r,threadId:n}=e,[i,s]=r.includes("@")?r.split("@"):[r,"default"],o=`mailboxes/${s}/${i}/threads.json`;try{let c=await t.send({Bucket:a,Key:o});return JSON.parse(c.Body)[n]||null}catch{return null}}}class ra{static SchedulerLambdaCode=`
4047
4047
  const { S3Client, GetObjectCommand, PutObjectCommand, DeleteObjectCommand, ListObjectsV2Command } = require('@aws-sdk/client-s3');
4048
4048
  const { SESClient, SendRawEmailCommand } = require('@aws-sdk/client-ses');
4049
4049
 
@@ -4172,7 +4172,7 @@ else {
4172
4172
 
4173
4173
  return raw;
4174
4174
  }
4175
- `;static createSchedulerLambda(e){return{[`${e.slug}EmailSchedulerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-email-scheduler`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:300,MemorySize:256,Code:{ZipFile:na.SchedulerLambdaCode},Environment:{Variables:{EMAIL_BUCKET:e.emailBucket}}}}}}static createSchedulerRule(e){return{[`${e.slug}EmailSchedulerRule`]:{Type:"AWS::Events::Rule",Properties:{Name:`${e.slug}-email-scheduler`,Description:"Trigger email scheduler every minute",ScheduleExpression:e.scheduleExpression||"rate(1 minute)",State:"ENABLED",Targets:[{Id:"EmailSchedulerTarget",Arn:e.lambdaArn}]}},[`${e.slug}EmailSchedulerPermission`]:{Type:"AWS::Lambda::Permission",Properties:{FunctionName:e.lambdaArn,Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:{"Fn::GetAtt":[`${e.slug}EmailSchedulerRule`,"Arn"]}}}}}static async scheduleEmail(e){let{s3Client:t,bucket:a,email:r,scheduledFor:n,timezone:i}=e,s=`sched-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,o={id:s,email:r,scheduledFor:typeof n==="string"?n:n.toISOString(),timezone:i,status:"pending",createdAt:new Date().toISOString()};return await t.send({Bucket:a,Key:`scheduled/${s}.json`,Body:JSON.stringify(o,null,2),ContentType:"application/json"}),o}static async cancelScheduledEmail(e){let{s3Client:t,bucket:a,id:r}=e;try{let n=await t.send({Bucket:a,Key:`scheduled/${r}.json`}),i=JSON.parse(n.Body);if(i.status!=="pending")return!1;return i.status="cancelled",await t.send({Bucket:a,Key:`scheduled/${r}.json`,Body:JSON.stringify(i,null,2),ContentType:"application/json"}),!0}catch{return!1}}static async listScheduledEmails(e){let{s3Client:t,bucket:a,status:r}=e,n=await t.send({Bucket:a,Prefix:"scheduled/"}),i=[];for(let s of n.Contents||[]){if(!s.Key.endsWith(".json"))continue;try{let o=await t.send({Bucket:a,Key:s.Key}),c=JSON.parse(o.Body);if(!r||c.status===r)i.push(c)}catch{}}return i.sort((s,o)=>new Date(s.scheduledFor).getTime()-new Date(o.scheduledFor).getTime()),i}}class tt{static TrackingPixelLambdaCode=`
4175
+ `;static createSchedulerLambda(e){return{[`${e.slug}EmailSchedulerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-email-scheduler`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:300,MemorySize:256,Code:{ZipFile:ra.SchedulerLambdaCode},Environment:{Variables:{EMAIL_BUCKET:e.emailBucket}}}}}}static createSchedulerRule(e){return{[`${e.slug}EmailSchedulerRule`]:{Type:"AWS::Events::Rule",Properties:{Name:`${e.slug}-email-scheduler`,Description:"Trigger email scheduler every minute",ScheduleExpression:e.scheduleExpression||"rate(1 minute)",State:"ENABLED",Targets:[{Id:"EmailSchedulerTarget",Arn:e.lambdaArn}]}},[`${e.slug}EmailSchedulerPermission`]:{Type:"AWS::Lambda::Permission",Properties:{FunctionName:e.lambdaArn,Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:{"Fn::GetAtt":[`${e.slug}EmailSchedulerRule`,"Arn"]}}}}}static async scheduleEmail(e){let{s3Client:t,bucket:a,email:r,scheduledFor:n,timezone:i}=e,s=`sched-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,o={id:s,email:r,scheduledFor:typeof n==="string"?n:n.toISOString(),timezone:i,status:"pending",createdAt:new Date().toISOString()};return await t.send({Bucket:a,Key:`scheduled/${s}.json`,Body:JSON.stringify(o,null,2),ContentType:"application/json"}),o}static async cancelScheduledEmail(e){let{s3Client:t,bucket:a,id:r}=e;try{let n=await t.send({Bucket:a,Key:`scheduled/${r}.json`}),i=JSON.parse(n.Body);if(i.status!=="pending")return!1;return i.status="cancelled",await t.send({Bucket:a,Key:`scheduled/${r}.json`,Body:JSON.stringify(i,null,2),ContentType:"application/json"}),!0}catch{return!1}}static async listScheduledEmails(e){let{s3Client:t,bucket:a,status:r}=e,n=await t.send({Bucket:a,Prefix:"scheduled/"}),i=[];for(let s of n.Contents||[]){if(!s.Key.endsWith(".json"))continue;try{let o=await t.send({Bucket:a,Key:s.Key}),c=JSON.parse(o.Body);if(!r||c.status===r)i.push(c)}catch{}}return i.sort((s,o)=>new Date(s.scheduledFor).getTime()-new Date(o.scheduledFor).getTime()),i}}class et{static TrackingPixelLambdaCode=`
4176
4176
  const { DynamoDBClient, UpdateItemCommand } = require('@aws-sdk/client-dynamodb');
4177
4177
 
4178
4178
  const dynamodb = new DynamoDBClient({});
@@ -4375,7 +4375,7 @@ catch (error) {
4375
4375
 
4376
4376
  return { statusCode: 200 };
4377
4377
  };
4378
- `;static createAnalyticsTable(e){return{[`${e.slug}EmailAnalyticsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-email-analytics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createTrackingPixelLambda(e){return{[`${e.slug}TrackingPixelLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-tracking-pixel`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:10,MemorySize:128,Code:{ZipFile:tt.TrackingPixelLambdaCode},Environment:{Variables:{ANALYTICS_TABLE:e.analyticsTable}}}}}}static createClickTrackingLambda(e){return{[`${e.slug}ClickTrackingLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-click-tracking`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:10,MemorySize:128,Code:{ZipFile:tt.ClickTrackingLambdaCode},Environment:{Variables:{ANALYTICS_TABLE:e.analyticsTable}}}}}}static createSesEventProcessorLambda(e){return{[`${e.slug}SesEventProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-ses-event-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:tt.SesEventProcessorCode},Environment:{Variables:{ANALYTICS_TABLE:e.analyticsTable}}}}}}static injectTracking(e){let{html:t,messageId:a,trackingDomain:r}=e,n=`<img src="https://${r}/track/open/${a}" width="1" height="1" style="display:none" alt="" />`,i=t.replace("</body>",`${n}</body>`);return i=i.replace(/href="(https?:\/\/[^"]+)"/g,(s,o)=>{let c=encodeURIComponent(o);return`href="https://${r}/track/click/${a}?url=${c}"`}),i}static calculateMetrics(e){let t=e.filter((c)=>c.sent).length,a=e.filter((c)=>c.delivered).length,r=e.filter((c)=>c.opened).length,n=e.filter((c)=>c.clicked).length,i=e.filter((c)=>c.bounced).length,s=e.filter((c)=>c.complained).length,o=e.filter((c)=>c.unsubscribed).length;return{period:new Date().toISOString(),sent:t,delivered:a,opened:r,clicked:n,bounced:i,complained:s,unsubscribed:o,deliveryRate:t>0?a/t*100:0,openRate:a>0?r/a*100:0,clickRate:r>0?n/r*100:0,bounceRate:t>0?i/t*100:0,complaintRate:a>0?s/a*100:0}}}class Re{static TemplateRendererCode=`
4378
+ `;static createAnalyticsTable(e){return{[`${e.slug}EmailAnalyticsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-email-analytics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createTrackingPixelLambda(e){return{[`${e.slug}TrackingPixelLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-tracking-pixel`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:10,MemorySize:128,Code:{ZipFile:et.TrackingPixelLambdaCode},Environment:{Variables:{ANALYTICS_TABLE:e.analyticsTable}}}}}}static createClickTrackingLambda(e){return{[`${e.slug}ClickTrackingLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-click-tracking`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:10,MemorySize:128,Code:{ZipFile:et.ClickTrackingLambdaCode},Environment:{Variables:{ANALYTICS_TABLE:e.analyticsTable}}}}}}static createSesEventProcessorLambda(e){return{[`${e.slug}SesEventProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-ses-event-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:et.SesEventProcessorCode},Environment:{Variables:{ANALYTICS_TABLE:e.analyticsTable}}}}}}static injectTracking(e){let{html:t,messageId:a,trackingDomain:r}=e,n=`<img src="https://${r}/track/open/${a}" width="1" height="1" style="display:none" alt="" />`,i=t.replace("</body>",`${n}</body>`);return i=i.replace(/href="(https?:\/\/[^"]+)"/g,(s,o)=>{let c=encodeURIComponent(o);return`href="https://${r}/track/click/${a}?url=${c}"`}),i}static calculateMetrics(e){let t=e.filter((c)=>c.sent).length,a=e.filter((c)=>c.delivered).length,r=e.filter((c)=>c.opened).length,n=e.filter((c)=>c.clicked).length,i=e.filter((c)=>c.bounced).length,s=e.filter((c)=>c.complained).length,o=e.filter((c)=>c.unsubscribed).length;return{period:new Date().toISOString(),sent:t,delivered:a,opened:r,clicked:n,bounced:i,complained:s,unsubscribed:o,deliveryRate:t>0?a/t*100:0,openRate:a>0?r/a*100:0,clickRate:r>0?n/r*100:0,bounceRate:t>0?i/t*100:0,complaintRate:a>0?s/a*100:0}}}class Ie{static TemplateRendererCode=`
4379
4379
  const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
4380
4380
 
4381
4381
  const s3 = new S3Client({});
@@ -4630,7 +4630,7 @@ The {{appName}} Team`,variables:["appName","userName","resetUrl","expiresIn"],ca
4630
4630
 
4631
4631
  <p>Best regards,<br>The {{appName}} Team</p>
4632
4632
  </body>
4633
- </html>`,variables:["invoiceNumber","customerName","period","items","total","paymentUrl","appName"],category:"billing"}};static createTemplateBucket(e){return{[`${e.slug}EmailTemplateBucket`]:{Type:"AWS::S3::Bucket",Properties:{BucketName:`${e.slug}-email-templates`,VersioningConfiguration:{Status:"Enabled"}}}}}static createTemplateRendererLambda(e){return{[`${e.slug}TemplateRendererLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-template-renderer`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Re.TemplateRendererCode},Environment:{Variables:{TEMPLATE_BUCKET:e.templateBucket}}}}}}static render(e,t){if(!e||!t)return e;let a=e;return a=a.replace(/\{\{\s*([\w.]+)\s*\}\}/g,(r,n)=>{let i=Re.getNestedValue(t,n);return i!==void 0?String(i):r}),a=a.replace(/\{\{#if\s+([\w.]+)\}\}([\s\S]*?)\{\{\/if\}\}/g,(r,n,i)=>Re.getNestedValue(t,n)?i:""),a=a.replace(/\{\{#unless\s+([\w.]+)\}\}([\s\S]*?)\{\{\/unless\}\}/g,(r,n,i)=>!Re.getNestedValue(t,n)?i:""),a=a.replace(/\{\{#each\s+([\w.]+)\}\}([\s\S]*?)\{\{\/each\}\}/g,(r,n,i)=>{let s=Re.getNestedValue(t,n);if(!Array.isArray(s))return"";return s.map((o,c)=>{let l=i;if(l=l.replace(/\{\{this\}\}/g,String(o)),l=l.replace(/\{\{@index\}\}/g,String(c)),typeof o==="object")Object.entries(o).forEach(([u,m])=>{l=l.replace(new RegExp(`\\{\\{\\s*${u}\\s*\\}\\}`,"g"),String(m))});return l}).join("")}),a}static getNestedValue(e,t){return t.split(".").reduce((a,r)=>a?.[r],e)}static extractVariables(e){let t=new Set,a=e.matchAll(/\{\{\s*([\w.]+)\s*\}\}/g);for(let n of a)if(!n[1].startsWith("#")&&!n[1].startsWith("/")&&!n[1].startsWith("@"))t.add(n[1].split(".")[0]);let r=e.matchAll(/\{\{#(?:if|unless|each)\s+([\w.]+)\}\}/g);for(let n of r)t.add(n[1].split(".")[0]);return Array.from(t)}}class ia{static SharedMailboxLambdaCode=`
4633
+ </html>`,variables:["invoiceNumber","customerName","period","items","total","paymentUrl","appName"],category:"billing"}};static createTemplateBucket(e){return{[`${e.slug}EmailTemplateBucket`]:{Type:"AWS::S3::Bucket",Properties:{BucketName:`${e.slug}-email-templates`,VersioningConfiguration:{Status:"Enabled"}}}}}static createTemplateRendererLambda(e){return{[`${e.slug}TemplateRendererLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-template-renderer`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Ie.TemplateRendererCode},Environment:{Variables:{TEMPLATE_BUCKET:e.templateBucket}}}}}}static render(e,t){if(!e||!t)return e;let a=e;return a=a.replace(/\{\{\s*([\w.]+)\s*\}\}/g,(r,n)=>{let i=Ie.getNestedValue(t,n);return i!==void 0?String(i):r}),a=a.replace(/\{\{#if\s+([\w.]+)\}\}([\s\S]*?)\{\{\/if\}\}/g,(r,n,i)=>{return Ie.getNestedValue(t,n)?i:""}),a=a.replace(/\{\{#unless\s+([\w.]+)\}\}([\s\S]*?)\{\{\/unless\}\}/g,(r,n,i)=>{return!Ie.getNestedValue(t,n)?i:""}),a=a.replace(/\{\{#each\s+([\w.]+)\}\}([\s\S]*?)\{\{\/each\}\}/g,(r,n,i)=>{let s=Ie.getNestedValue(t,n);if(!Array.isArray(s))return"";return s.map((o,c)=>{let l=i;if(l=l.replace(/\{\{this\}\}/g,String(o)),l=l.replace(/\{\{@index\}\}/g,String(c)),typeof o==="object")Object.entries(o).forEach(([u,m])=>{l=l.replace(new RegExp(`\\{\\{\\s*${u}\\s*\\}\\}`,"g"),String(m))});return l}).join("")}),a}static getNestedValue(e,t){return t.split(".").reduce((a,r)=>a?.[r],e)}static extractVariables(e){let t=new Set,a=e.matchAll(/\{\{\s*([\w.]+)\s*\}\}/g);for(let n of a)if(!n[1].startsWith("#")&&!n[1].startsWith("/")&&!n[1].startsWith("@"))t.add(n[1].split(".")[0]);let r=e.matchAll(/\{\{#(?:if|unless|each)\s+([\w.]+)\}\}/g);for(let n of r)t.add(n[1].split(".")[0]);return Array.from(t)}}class na{static SharedMailboxLambdaCode=`
4634
4634
  const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
4635
4635
  const { DynamoDBClient, GetItemCommand, PutItemCommand, QueryCommand, UpdateItemCommand } = require('@aws-sdk/client-dynamodb');
4636
4636
 
@@ -4861,7 +4861,7 @@ function unmarshallMailbox(item) {
4861
4861
  updatedAt: item.updatedAt.S,
4862
4862
  };
4863
4863
  }
4864
- `;static createMailboxTable(e){return{[`${e.slug}SharedMailboxTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-shared-mailboxes`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"},{AttributeName:"type",AttributeType:"S"},{AttributeName:"mailboxId",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],GlobalSecondaryIndexes:[{IndexName:"type-index",KeySchema:[{AttributeName:"type",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"}},{IndexName:"mailbox-index",KeySchema:[{AttributeName:"mailboxId",KeyType:"HASH"},{AttributeName:"id",KeyType:"RANGE"}],Projection:{ProjectionType:"ALL"}}]}}}}static createSharedMailboxLambda(e){return{[`${e.slug}SharedMailboxLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-shared-mailbox`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:ia.SharedMailboxLambdaCode},Environment:{Variables:{EMAIL_BUCKET:e.emailBucket,MAILBOX_TABLE:e.mailboxTable}}}}}}static PermissionSets={owner:{read:!0,send:!0,delete:!0,manage:!0,assignTo:!0},admin:{read:!0,send:!0,delete:!0,manage:!0,assignTo:!0},member:{read:!0,send:!0,delete:!1,manage:!1,assignTo:!0},viewer:{read:!0,send:!1,delete:!1,manage:!1,assignTo:!1}}}class sa{static RuleProcessorCode=`
4864
+ `;static createMailboxTable(e){return{[`${e.slug}SharedMailboxTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-shared-mailboxes`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"},{AttributeName:"type",AttributeType:"S"},{AttributeName:"mailboxId",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],GlobalSecondaryIndexes:[{IndexName:"type-index",KeySchema:[{AttributeName:"type",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"}},{IndexName:"mailbox-index",KeySchema:[{AttributeName:"mailboxId",KeyType:"HASH"},{AttributeName:"id",KeyType:"RANGE"}],Projection:{ProjectionType:"ALL"}}]}}}}static createSharedMailboxLambda(e){return{[`${e.slug}SharedMailboxLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-shared-mailbox`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:na.SharedMailboxLambdaCode},Environment:{Variables:{EMAIL_BUCKET:e.emailBucket,MAILBOX_TABLE:e.mailboxTable}}}}}}static PermissionSets={owner:{read:!0,send:!0,delete:!0,manage:!0,assignTo:!0},admin:{read:!0,send:!0,delete:!0,manage:!0,assignTo:!0},member:{read:!0,send:!0,delete:!1,manage:!1,assignTo:!0},viewer:{read:!0,send:!1,delete:!1,manage:!1,assignTo:!1}}}class ia{static RuleProcessorCode=`
4865
4865
  const { S3Client, GetObjectCommand, PutObjectCommand, CopyObjectCommand, DeleteObjectCommand } = require('@aws-sdk/client-s3');
4866
4866
  const { DynamoDBClient, QueryCommand } = require('@aws-sdk/client-dynamodb');
4867
4867
  const { LambdaClient, InvokeCommand } = require('@aws-sdk/client-lambda');
@@ -5174,7 +5174,7 @@ async function invokeLambda(functionName, metadata) {
5174
5174
  Payload: JSON.stringify(metadata),
5175
5175
  }));
5176
5176
  }
5177
- `;static createRulesTable(e){return{[`${e.slug}EmailRulesTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.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(e){return{[`${e.slug}EmailRuleProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-email-rule-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:sa.RuleProcessorCode},Environment:{Variables:{EMAIL_BUCKET:e.emailBucket,RULES_TABLE:e.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 _o={};De(_o,{default:()=>Go,handler:()=>Wo});var Wo=`
5177
+ `;static createRulesTable(e){return{[`${e.slug}EmailRulesTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.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(e){return{[`${e.slug}EmailRuleProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-email-rule-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:ia.RuleProcessorCode},Environment:{Variables:{EMAIL_BUCKET:e.emailBucket,RULES_TABLE:e.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 _o={};Ne(_o,{handler:()=>Bo,default:()=>Uo});var Bo=`
5178
5178
  const { S3Client, GetObjectCommand, PutObjectCommand, CopyObjectCommand } = require('@aws-sdk/client-s3');
5179
5179
  const s3 = new S3Client({});
5180
5180
 
@@ -5332,7 +5332,7 @@ catch (error) {
5332
5332
 
5333
5333
  return { statusCode: 200, body: 'OK' };
5334
5334
  };
5335
- `,Go=`
5335
+ `,Uo=`
5336
5336
  const { S3Client, GetObjectCommand, PutObjectCommand, CopyObjectCommand } = require('@aws-sdk/client-s3');
5337
5337
  const s3 = new S3Client({});
5338
5338
 
@@ -5490,7 +5490,7 @@ catch (error) {
5490
5490
 
5491
5491
  return { statusCode: 200, body: 'OK' };
5492
5492
  };
5493
- `,Fo={};De(Fo,{CallAnalytics:()=>ca,CallRecording:()=>oa,Callbacks:()=>wt,IVRBuilder:()=>Be});class oa{static RecordingProcessorCode=`
5493
+ `,Go={};Ne(Go,{IVRBuilder:()=>We,Callbacks:()=>vt,CallRecording:()=>sa,CallAnalytics:()=>oa});class sa{static RecordingProcessorCode=`
5494
5494
  const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
5495
5495
  const { TranscribeClient, StartTranscriptionJobCommand } = require('@aws-sdk/client-transcribe');
5496
5496
  const { DynamoDBClient, PutItemCommand, UpdateItemCommand } = require('@aws-sdk/client-dynamodb');
@@ -5682,7 +5682,7 @@ else if (jobStatus === 'FAILED') {
5682
5682
 
5683
5683
  return { statusCode: 200 };
5684
5684
  };
5685
- `;static createRecordingsTable(e){return{[`${e.slug}CallRecordingsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-call-recordings`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"recordingId",AttributeType:"S"},{AttributeName:"transcriptionJobName",AttributeType:"S"}],KeySchema:[{AttributeName:"recordingId",KeyType:"HASH"}],GlobalSecondaryIndexes:[{IndexName:"job-index",KeySchema:[{AttributeName:"transcriptionJobName",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"}}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createRecordingProcessorLambda(e){return{[`${e.slug}RecordingProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-recording-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:oa.RecordingProcessorCode},Environment:{Variables:{RECORDING_BUCKET:e.recordingBucket,RECORDINGS_TABLE:e.recordingsTable}}}}}}}class Be{nodes=[];connections=[];startNodeId="";static create(e){return new Be}start(){let e={id:this.generateId(),type:"start",position:{x:0,y:0},config:{}};return this.nodes.push(e),this.startNodeId=e.id,this}playPrompt(e,t){let a={id:this.generateId(),type:"play-prompt",position:{x:0,y:0},config:{text:e,textType:t?.ssml?"ssml":"text",voice:t?.voice||"Joanna"}};return this.nodes.push(a),this.connectToLast(a.id),this}getInput(e,t){let a={id:this.generateId(),type:"get-input",position:{x:0,y:0},config:{prompt:e,maxDigits:t?.maxDigits||1,timeout:t?.timeout||5,errorPrompt:t?.errorPrompt||"Sorry, I didn't get that."}};return this.nodes.push(a),this.connectToLast(a.id),this}menu(e,t){let a={id:this.generateId(),type:"menu",position:{x:0,y:0},config:{prompt:e,options:t}};return this.nodes.push(a),this.connectToLast(a.id),this}transferToQueue(e,t){let a={id:this.generateId(),type:"transfer-queue",position:{x:0,y:0},config:{queueArn:e,priority:t?.priority||5}};return this.nodes.push(a),this.connectToLast(a.id),this}transferToPhone(e){let t={id:this.generateId(),type:"transfer-phone",position:{x:0,y:0},config:{phoneNumber:e}};return this.nodes.push(t),this.connectToLast(t.id),this}invokeLambda(e,t){let a={id:this.generateId(),type:"invoke-lambda",position:{x:0,y:0},config:{functionArn:e,timeout:t?.timeout||8}};return this.nodes.push(a),this.connectToLast(a.id),this}setAttribute(e,t){let a={id:this.generateId(),type:"set-attribute",position:{x:0,y:0},config:{key:e,value:t}};return this.nodes.push(a),this.connectToLast(a.id),this}checkHours(e){let t={id:this.generateId(),type:"check-hours",position:{x:0,y:0},config:{hoursOfOperationArn:e}};return this.nodes.push(t),this.connectToLast(t.id),this}recordVoicemail(e){let t={id:this.generateId(),type:"record-voicemail",position:{x:0,y:0},config:{maxDuration:e?.maxDuration||120,greeting:e?.greeting||"Please leave a message after the beep.",beep:e?.beep!==!1}};return this.nodes.push(t),this.connectToLast(t.id),this}wait(e){let t={id:this.generateId(),type:"wait",position:{x:0,y:0},config:{seconds:e}};return this.nodes.push(t),this.connectToLast(t.id),this}disconnect(){let e={id:this.generateId(),type:"disconnect",position:{x:0,y:0},config:{}};return this.nodes.push(e),this.connectToLast(e.id),this}build(){return{id:this.generateId(),name:"IVR Flow",nodes:this.nodes,connections:this.connections,startNodeId:this.startNodeId,version:1,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()}}toContactFlow(){let e=[],t=new Map(this.nodes.map((r)=>[r.id,r]));for(let r of this.nodes){let n=this.nodeToAction(r,t);if(n)e.push(n)}let a={Version:"2019-10-30",StartAction:this.startNodeId,Actions:e};return JSON.stringify(a,null,2)}nodeToAction(e,t){let a=this.getNextNodeId(e.id),r={NextAction:a||"disconnect",Errors:[{NextAction:"disconnect"}]};switch(e.type){case"start":return null;case"play-prompt":return{Identifier:e.id,Type:"MessageParticipant",Parameters:{Text:e.config.text,TextType:e.config.textType},Transitions:r};case"get-input":return{Identifier:e.id,Type:"GetParticipantInput",Parameters:{Text:e.config.prompt,InputTimeLimitSeconds:e.config.timeout,MaxDigits:e.config.maxDigits},Transitions:{...r,Conditions:[]}};case"transfer-queue":return{Identifier:e.id,Type:"TransferToQueue",Parameters:{QueueId:e.config.queueArn},Transitions:r};case"transfer-phone":return{Identifier:e.id,Type:"TransferToPhoneNumber",Parameters:{PhoneNumber:e.config.phoneNumber},Transitions:r};case"invoke-lambda":return{Identifier:e.id,Type:"InvokeLambdaFunction",Parameters:{LambdaFunctionARN:e.config.functionArn,InvocationTimeLimitSeconds:e.config.timeout},Transitions:r};case"set-attribute":return{Identifier:e.id,Type:"UpdateContactAttributes",Parameters:{Attributes:{[e.config.key]:e.config.value}},Transitions:r};case"check-hours":return{Identifier:e.id,Type:"CheckHoursOfOperation",Parameters:{HoursOfOperationId:e.config.hoursOfOperationArn},Transitions:{NextAction:a,Conditions:[{NextAction:a,Condition:{Operator:"Equals",Operands:["True"]}}],Errors:[{NextAction:"disconnect"}]}};case"wait":return{Identifier:e.id,Type:"Wait",Parameters:{Seconds:e.config.seconds},Transitions:r};case"disconnect":return{Identifier:e.id,Type:"DisconnectParticipant",Parameters:{},Transitions:{}};default:return null}}connectToLast(e){if(this.nodes.length>1){let t=this.nodes[this.nodes.length-2];this.connections.push({id:this.generateId(),sourceNodeId:t.id,targetNodeId:e,sourcePort:"default"})}}getNextNodeId(e){return this.connections.find((t)=>t.sourceNodeId===e)?.targetNodeId||null}generateId(){return`node-${Date.now()}-${Math.random().toString(36).substr(2,9)}`}static Templates={basicSupport:()=>Be.create("Basic Support").start().playPrompt("Welcome to customer support.").menu("Press 1 for sales, 2 for support, or 3 to leave a message.",{"1":"sales","2":"support","3":"voicemail"}),afterHours:(e)=>Be.create("After Hours").start().playPrompt(e).recordVoicemail({greeting:"Please leave your name, number, and a brief message.",maxDuration:120}).playPrompt("Thank you for your message. Goodbye.").disconnect(),callbackRequest:(e)=>Be.create("Callback Request").start().playPrompt("All agents are currently busy.").getInput("Press 1 to request a callback, or 2 to wait.",{maxDigits:1}).invokeLambda(e).playPrompt("We will call you back shortly. Goodbye.").disconnect()}}class ca{static MetricsAggregatorCode=`
5685
+ `;static createRecordingsTable(e){return{[`${e.slug}CallRecordingsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-call-recordings`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"recordingId",AttributeType:"S"},{AttributeName:"transcriptionJobName",AttributeType:"S"}],KeySchema:[{AttributeName:"recordingId",KeyType:"HASH"}],GlobalSecondaryIndexes:[{IndexName:"job-index",KeySchema:[{AttributeName:"transcriptionJobName",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"}}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createRecordingProcessorLambda(e){return{[`${e.slug}RecordingProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-recording-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:sa.RecordingProcessorCode},Environment:{Variables:{RECORDING_BUCKET:e.recordingBucket,RECORDINGS_TABLE:e.recordingsTable}}}}}}}class We{nodes=[];connections=[];startNodeId="";static create(e){return new We}start(){let e={id:this.generateId(),type:"start",position:{x:0,y:0},config:{}};return this.nodes.push(e),this.startNodeId=e.id,this}playPrompt(e,t){let a={id:this.generateId(),type:"play-prompt",position:{x:0,y:0},config:{text:e,textType:t?.ssml?"ssml":"text",voice:t?.voice||"Joanna"}};return this.nodes.push(a),this.connectToLast(a.id),this}getInput(e,t){let a={id:this.generateId(),type:"get-input",position:{x:0,y:0},config:{prompt:e,maxDigits:t?.maxDigits||1,timeout:t?.timeout||5,errorPrompt:t?.errorPrompt||"Sorry, I didn't get that."}};return this.nodes.push(a),this.connectToLast(a.id),this}menu(e,t){let a={id:this.generateId(),type:"menu",position:{x:0,y:0},config:{prompt:e,options:t}};return this.nodes.push(a),this.connectToLast(a.id),this}transferToQueue(e,t){let a={id:this.generateId(),type:"transfer-queue",position:{x:0,y:0},config:{queueArn:e,priority:t?.priority||5}};return this.nodes.push(a),this.connectToLast(a.id),this}transferToPhone(e){let t={id:this.generateId(),type:"transfer-phone",position:{x:0,y:0},config:{phoneNumber:e}};return this.nodes.push(t),this.connectToLast(t.id),this}invokeLambda(e,t){let a={id:this.generateId(),type:"invoke-lambda",position:{x:0,y:0},config:{functionArn:e,timeout:t?.timeout||8}};return this.nodes.push(a),this.connectToLast(a.id),this}setAttribute(e,t){let a={id:this.generateId(),type:"set-attribute",position:{x:0,y:0},config:{key:e,value:t}};return this.nodes.push(a),this.connectToLast(a.id),this}checkHours(e){let t={id:this.generateId(),type:"check-hours",position:{x:0,y:0},config:{hoursOfOperationArn:e}};return this.nodes.push(t),this.connectToLast(t.id),this}recordVoicemail(e){let t={id:this.generateId(),type:"record-voicemail",position:{x:0,y:0},config:{maxDuration:e?.maxDuration||120,greeting:e?.greeting||"Please leave a message after the beep.",beep:e?.beep!==!1}};return this.nodes.push(t),this.connectToLast(t.id),this}wait(e){let t={id:this.generateId(),type:"wait",position:{x:0,y:0},config:{seconds:e}};return this.nodes.push(t),this.connectToLast(t.id),this}disconnect(){let e={id:this.generateId(),type:"disconnect",position:{x:0,y:0},config:{}};return this.nodes.push(e),this.connectToLast(e.id),this}build(){return{id:this.generateId(),name:"IVR Flow",nodes:this.nodes,connections:this.connections,startNodeId:this.startNodeId,version:1,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()}}toContactFlow(){let e=[],t=new Map(this.nodes.map((r)=>[r.id,r]));for(let r of this.nodes){let n=this.nodeToAction(r,t);if(n)e.push(n)}let a={Version:"2019-10-30",StartAction:this.startNodeId,Actions:e};return JSON.stringify(a,null,2)}nodeToAction(e,t){let a=this.getNextNodeId(e.id),r={NextAction:a||"disconnect",Errors:[{NextAction:"disconnect"}]};switch(e.type){case"start":return null;case"play-prompt":return{Identifier:e.id,Type:"MessageParticipant",Parameters:{Text:e.config.text,TextType:e.config.textType},Transitions:r};case"get-input":return{Identifier:e.id,Type:"GetParticipantInput",Parameters:{Text:e.config.prompt,InputTimeLimitSeconds:e.config.timeout,MaxDigits:e.config.maxDigits},Transitions:{...r,Conditions:[]}};case"transfer-queue":return{Identifier:e.id,Type:"TransferToQueue",Parameters:{QueueId:e.config.queueArn},Transitions:r};case"transfer-phone":return{Identifier:e.id,Type:"TransferToPhoneNumber",Parameters:{PhoneNumber:e.config.phoneNumber},Transitions:r};case"invoke-lambda":return{Identifier:e.id,Type:"InvokeLambdaFunction",Parameters:{LambdaFunctionARN:e.config.functionArn,InvocationTimeLimitSeconds:e.config.timeout},Transitions:r};case"set-attribute":return{Identifier:e.id,Type:"UpdateContactAttributes",Parameters:{Attributes:{[e.config.key]:e.config.value}},Transitions:r};case"check-hours":return{Identifier:e.id,Type:"CheckHoursOfOperation",Parameters:{HoursOfOperationId:e.config.hoursOfOperationArn},Transitions:{NextAction:a,Conditions:[{NextAction:a,Condition:{Operator:"Equals",Operands:["True"]}}],Errors:[{NextAction:"disconnect"}]}};case"wait":return{Identifier:e.id,Type:"Wait",Parameters:{Seconds:e.config.seconds},Transitions:r};case"disconnect":return{Identifier:e.id,Type:"DisconnectParticipant",Parameters:{},Transitions:{}};default:return null}}connectToLast(e){if(this.nodes.length>1){let t=this.nodes[this.nodes.length-2];this.connections.push({id:this.generateId(),sourceNodeId:t.id,targetNodeId:e,sourcePort:"default"})}}getNextNodeId(e){return this.connections.find((t)=>t.sourceNodeId===e)?.targetNodeId||null}generateId(){return`node-${Date.now()}-${Math.random().toString(36).substr(2,9)}`}static Templates={basicSupport:()=>{return We.create("Basic Support").start().playPrompt("Welcome to customer support.").menu("Press 1 for sales, 2 for support, or 3 to leave a message.",{"1":"sales","2":"support","3":"voicemail"})},afterHours:(e)=>{return We.create("After Hours").start().playPrompt(e).recordVoicemail({greeting:"Please leave your name, number, and a brief message.",maxDuration:120}).playPrompt("Thank you for your message. Goodbye.").disconnect()},callbackRequest:(e)=>{return We.create("Callback Request").start().playPrompt("All agents are currently busy.").getInput("Press 1 to request a callback, or 2 to wait.",{maxDigits:1}).invokeLambda(e).playPrompt("We will call you back shortly. Goodbye.").disconnect()}}}class oa{static MetricsAggregatorCode=`
5686
5686
  const { DynamoDBClient, PutItemCommand, ScanCommand } = require('@aws-sdk/client-dynamodb');
5687
5687
 
5688
5688
  const dynamodb = new DynamoDBClient({});
@@ -5881,7 +5881,7 @@ catch (error) {
5881
5881
  };
5882
5882
  }
5883
5883
  };
5884
- `;static createMetricsTable(e){return{[`${e.slug}CallMetricsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-call-metrics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"period",AttributeType:"S"}],KeySchema:[{AttributeName:"period",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createMetricsAggregatorLambda(e){return{[`${e.slug}CallMetricsAggregatorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-call-metrics-aggregator`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:ca.MetricsAggregatorCode},Environment:{Variables:{CALL_LOG_TABLE:e.callLogTable,METRICS_TABLE:e.metricsTable}}}}}}static createMetricsSchedule(e){return{[`${e.slug}CallMetricsSchedule`]:{Type:"AWS::Events::Rule",Properties:{Name:`${e.slug}-call-metrics-schedule`,Description:"Aggregate call metrics hourly",ScheduleExpression:"rate(1 hour)",State:"ENABLED",Targets:[{Id:"MetricsAggregatorTarget",Arn:e.lambdaArn}]}}}}}class wt{static CallbackRequestCode=`
5884
+ `;static createMetricsTable(e){return{[`${e.slug}CallMetricsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-call-metrics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"period",AttributeType:"S"}],KeySchema:[{AttributeName:"period",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createMetricsAggregatorLambda(e){return{[`${e.slug}CallMetricsAggregatorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-call-metrics-aggregator`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:oa.MetricsAggregatorCode},Environment:{Variables:{CALL_LOG_TABLE:e.callLogTable,METRICS_TABLE:e.metricsTable}}}}}}static createMetricsSchedule(e){return{[`${e.slug}CallMetricsSchedule`]:{Type:"AWS::Events::Rule",Properties:{Name:`${e.slug}-call-metrics-schedule`,Description:"Aggregate call metrics hourly",ScheduleExpression:"rate(1 hour)",State:"ENABLED",Targets:[{Id:"MetricsAggregatorTarget",Arn:e.lambdaArn}]}}}}}class vt{static CallbackRequestCode=`
5885
5885
  const { DynamoDBClient, PutItemCommand, UpdateItemCommand } = require('@aws-sdk/client-dynamodb');
5886
5886
  const { ConnectClient, StartOutboundVoiceContactCommand } = require('@aws-sdk/client-connect');
5887
5887
  const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');
@@ -6171,7 +6171,7 @@ catch (error) {
6171
6171
  return { statusCode: 500, error: error.message };
6172
6172
  }
6173
6173
  };
6174
- `;static createCallbacksTable(e){return{[`${e.slug}CallbacksTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-callbacks`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createCallbackRequestLambda(e){return{[`${e.slug}CallbackRequestLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-callback-request`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:wt.CallbackRequestCode},Environment:{Variables:{CALLBACKS_TABLE:e.callbacksTable,NOTIFICATION_TOPIC_ARN:e.notificationTopicArn||""}}}}}}static createCallbackProcessorLambda(e){return{[`${e.slug}CallbackProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-callback-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:300,MemorySize:256,Code:{ZipFile:wt.CallbackProcessorCode},Environment:{Variables:{CALLBACKS_TABLE:e.callbacksTable,CONNECT_INSTANCE_ID:e.connectInstanceId,CONTACT_FLOW_ID:e.contactFlowId,SOURCE_PHONE_NUMBER:e.sourcePhoneNumber,QUEUE_ID:e.queueId||""}}}}}}}var Vo={};De(Vo,{AbTesting:()=>Ce,LinkTracking:()=>pa,MmsSupport:()=>da,SmsAnalytics:()=>ua,SmsCampaigns:()=>la,SmsChatbot:()=>ma});class la{static CampaignManagerCode=`
6174
+ `;static createCallbacksTable(e){return{[`${e.slug}CallbacksTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-callbacks`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createCallbackRequestLambda(e){return{[`${e.slug}CallbackRequestLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-callback-request`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:vt.CallbackRequestCode},Environment:{Variables:{CALLBACKS_TABLE:e.callbacksTable,NOTIFICATION_TOPIC_ARN:e.notificationTopicArn||""}}}}}}static createCallbackProcessorLambda(e){return{[`${e.slug}CallbackProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-callback-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:300,MemorySize:256,Code:{ZipFile:vt.CallbackProcessorCode},Environment:{Variables:{CALLBACKS_TABLE:e.callbacksTable,CONNECT_INSTANCE_ID:e.connectInstanceId,CONTACT_FLOW_ID:e.contactFlowId,SOURCE_PHONE_NUMBER:e.sourcePhoneNumber,QUEUE_ID:e.queueId||""}}}}}}}var Vo={};Ne(Vo,{SmsChatbot:()=>da,SmsCampaigns:()=>ca,SmsAnalytics:()=>la,MmsSupport:()=>ua,LinkTracking:()=>ma,AbTesting:()=>Ae});class ca{static CampaignManagerCode=`
6175
6175
  const { DynamoDBClient, PutItemCommand, GetItemCommand, UpdateItemCommand, ScanCommand } = require('@aws-sdk/client-dynamodb');
6176
6176
 
6177
6177
  const dynamodb = new DynamoDBClient({});
@@ -6555,7 +6555,7 @@ function unmarshallCampaign(item) {
6555
6555
  stats: JSON.parse(item.stats?.S || '{}'),
6556
6556
  };
6557
6557
  }
6558
- `;static createCampaignsTable(e){return{[`${e.slug}SmsCampaignsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-sms-campaigns`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}}static createCampaignManagerLambda(e){return{[`${e.slug}SmsCampaignManagerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-sms-campaign-manager`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:la.CampaignManagerCode},Environment:{Variables:{CAMPAIGNS_TABLE:e.campaignsTable}}}}}}}class ua{static AnalyticsAggregatorCode=`
6558
+ `;static createCampaignsTable(e){return{[`${e.slug}SmsCampaignsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-sms-campaigns`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}}static createCampaignManagerLambda(e){return{[`${e.slug}SmsCampaignManagerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-sms-campaign-manager`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:ca.CampaignManagerCode},Environment:{Variables:{CAMPAIGNS_TABLE:e.campaignsTable}}}}}}}class la{static AnalyticsAggregatorCode=`
6559
6559
  const { DynamoDBClient, ScanCommand, PutItemCommand } = require('@aws-sdk/client-dynamodb');
6560
6560
 
6561
6561
  const dynamodb = new DynamoDBClient({});
@@ -6750,7 +6750,7 @@ catch (error) {
6750
6750
 
6751
6751
  return { statusCode: 200 };
6752
6752
  };
6753
- `;static createAnalyticsTable(e){return{[`${e.slug}SmsAnalyticsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-sms-analytics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"period",AttributeType:"S"}],KeySchema:[{AttributeName:"period",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createDeliveryReportsTable(e){return{[`${e.slug}SmsDeliveryReportsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-sms-delivery-reports`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createAnalyticsAggregatorLambda(e){return{[`${e.slug}SmsAnalyticsAggregatorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-sms-analytics-aggregator`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:ua.AnalyticsAggregatorCode},Environment:{Variables:{MESSAGE_LOG_TABLE:e.messageLogTable,ANALYTICS_TABLE:e.analyticsTable}}}}}}}class da{static MmsSenderCode=`
6753
+ `;static createAnalyticsTable(e){return{[`${e.slug}SmsAnalyticsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-sms-analytics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"period",AttributeType:"S"}],KeySchema:[{AttributeName:"period",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createDeliveryReportsTable(e){return{[`${e.slug}SmsDeliveryReportsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-sms-delivery-reports`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createAnalyticsAggregatorLambda(e){return{[`${e.slug}SmsAnalyticsAggregatorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-sms-analytics-aggregator`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:la.AnalyticsAggregatorCode},Environment:{Variables:{MESSAGE_LOG_TABLE:e.messageLogTable,ANALYTICS_TABLE:e.analyticsTable}}}}}}}class ua{static MmsSenderCode=`
6754
6754
  const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');
6755
6755
  const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');
6756
6756
  const { DynamoDBClient, PutItemCommand } = require('@aws-sdk/client-dynamodb');
@@ -6942,8 +6942,8 @@ async function sendFallbackSms(to, message) {
6942
6942
  fallback: true,
6943
6943
  };
6944
6944
  }
6945
- `;static createMediaBucket(e){return{[`${e.slug}MmsMediaBucket`]:{Type:"AWS::S3::Bucket",Properties:{BucketName:`${e.slug}-mms-media`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldMedia",Status:"Enabled",ExpirationInDays:30}]},CorsConfiguration:{CorsRules:[{AllowedOrigins:["*"],AllowedMethods:["GET"],AllowedHeaders:["*"],MaxAge:3600}]}}}}}static createMmsSenderLambda(e){return{[`${e.slug}MmsSenderLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-mms-sender`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:60,MemorySize:512,Code:{ZipFile:da.MmsSenderCode},Environment:{Variables:{MEDIA_BUCKET:e.mediaBucket,MESSAGE_LOG_TABLE:e.messageLogTable,ORIGINATION_NUMBER:e.originationNumber||""}}}}}}static SupportedMediaTypes={image:["image/jpeg","image/png","image/gif"],video:["video/mp4","video/3gpp"],audio:["audio/mpeg","audio/wav"]};static MediaSizeLimits={image:1048576,video:5242880,audio:1048576}}class ma{static ChatbotProcessorCode=["const { DynamoDBClient, GetItemCommand, PutItemCommand, UpdateItemCommand, ScanCommand } = require('@aws-sdk/client-dynamodb');","const { BedrockRuntimeClient, InvokeModelCommand } = require('@aws-sdk/client-bedrock-runtime');","const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');","","const dynamodb = new DynamoDBClient({});","const bedrock = new BedrockRuntimeClient({});","const sns = new SNSClient({});","","const SESSIONS_TABLE = process.env.SESSIONS_TABLE;","const RULES_TABLE = process.env.RULES_TABLE;","const CHATBOT_CONFIG = JSON.parse(process.env.CHATBOT_CONFIG || '{}');","","exports.handler = async (event) => {"," console.log('Chatbot event:', JSON.stringify(event, null, 2));"," for (const record of event.Records) {"," try {"," const message = JSON.parse(record.Sns?.Message || record.body || '{}');"," const { originationNumber, messageBody } = message;"," if (!originationNumber || !messageBody) continue;"," const response = await processMessage(originationNumber, messageBody.trim());"," await sendResponse(originationNumber, response);"," } catch (error) {"," console.error('Error:', error);"," }"," }"," return { statusCode: 200 };","};","","async function processMessage(phoneNumber, message) {"," const rules = await getRules();"," const lowerMessage = message.toLowerCase();"," for (const rule of rules) {"," for (const pattern of rule.patterns) {"," if (new RegExp(pattern, 'i').test(lowerMessage)) {"," return rule.response;"," }"," }"," }"," return CHATBOT_CONFIG.fallbackMessage || 'Sorry, I did not understand. Please try again.';","}","","async function getRules() {"," const result = await dynamodb.send(new ScanCommand({ TableName: RULES_TABLE }));"," return (result.Items || []).map(item => ({"," patterns: JSON.parse(item.patterns?.S || '[]'),"," response: item.response?.S || '',"," })).sort((a, b) => (a.priority || 0) - (b.priority || 0));","}","","async function sendResponse(phoneNumber, message) {"," await sns.send(new PublishCommand({"," PhoneNumber: phoneNumber,"," Message: message.substring(0, 1600),"," MessageAttributes: {"," 'AWS.SNS.SMS.SMSType': { DataType: 'String', StringValue: 'Transactional' },"," },"," }));","}"].join(`
6946
- `);static createSessionsTable(e){return{[`${e.slug}ChatbotSessionsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-chatbot-sessions`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createRulesTable(e){return{[`${e.slug}ChatbotRulesTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-chatbot-rules`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}}static createChatbotProcessorLambda(e){return{[`${e.slug}ChatbotProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-chatbot-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:ma.ChatbotProcessorCode},Environment:{Variables:{SESSIONS_TABLE:e.sessionsTable,RULES_TABLE:e.rulesTable,CHATBOT_CONFIG:JSON.stringify(e.chatbotConfig),ORIGINATION_NUMBER:e.originationNumber||""}}}}}}static DefaultRules=[{id:"greeting",priority:1,patterns:["^(hi|hello|hey|howdy)$","^good (morning|afternoon|evening)"],response:"Hello! How can I help you today?"},{id:"help",priority:2,patterns:["^help$","what can you do","how does this work"],response:"I can help with: 1) Account info 2) Support 3) Hours. Reply with a number."},{id:"hours",priority:3,patterns:["hours","open","when are you"],response:"We are open Mon-Fri 9am-5pm EST. Closed weekends."},{id:"thanks",priority:4,patterns:["^(thanks|thank you|thx)"],response:"You're welcome! Is there anything else I can help with?"},{id:"bye",priority:5,patterns:["^(bye|goodbye|quit|exit|stop)$"],response:"Goodbye! Text us anytime if you need help.",action:"end"}]}class pa{static LinkShortenerCode=`
6945
+ `;static createMediaBucket(e){return{[`${e.slug}MmsMediaBucket`]:{Type:"AWS::S3::Bucket",Properties:{BucketName:`${e.slug}-mms-media`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldMedia",Status:"Enabled",ExpirationInDays:30}]},CorsConfiguration:{CorsRules:[{AllowedOrigins:["*"],AllowedMethods:["GET"],AllowedHeaders:["*"],MaxAge:3600}]}}}}}static createMmsSenderLambda(e){return{[`${e.slug}MmsSenderLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-mms-sender`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:60,MemorySize:512,Code:{ZipFile:ua.MmsSenderCode},Environment:{Variables:{MEDIA_BUCKET:e.mediaBucket,MESSAGE_LOG_TABLE:e.messageLogTable,ORIGINATION_NUMBER:e.originationNumber||""}}}}}}static SupportedMediaTypes={image:["image/jpeg","image/png","image/gif"],video:["video/mp4","video/3gpp"],audio:["audio/mpeg","audio/wav"]};static MediaSizeLimits={image:1048576,video:5242880,audio:1048576}}class da{static ChatbotProcessorCode=["const { DynamoDBClient, GetItemCommand, PutItemCommand, UpdateItemCommand, ScanCommand } = require('@aws-sdk/client-dynamodb');","const { BedrockRuntimeClient, InvokeModelCommand } = require('@aws-sdk/client-bedrock-runtime');","const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');","","const dynamodb = new DynamoDBClient({});","const bedrock = new BedrockRuntimeClient({});","const sns = new SNSClient({});","","const SESSIONS_TABLE = process.env.SESSIONS_TABLE;","const RULES_TABLE = process.env.RULES_TABLE;","const CHATBOT_CONFIG = JSON.parse(process.env.CHATBOT_CONFIG || '{}');","","exports.handler = async (event) => {"," console.log('Chatbot event:', JSON.stringify(event, null, 2));"," for (const record of event.Records) {"," try {"," const message = JSON.parse(record.Sns?.Message || record.body || '{}');"," const { originationNumber, messageBody } = message;"," if (!originationNumber || !messageBody) continue;"," const response = await processMessage(originationNumber, messageBody.trim());"," await sendResponse(originationNumber, response);"," } catch (error) {"," console.error('Error:', error);"," }"," }"," return { statusCode: 200 };","};","","async function processMessage(phoneNumber, message) {"," const rules = await getRules();"," const lowerMessage = message.toLowerCase();"," for (const rule of rules) {"," for (const pattern of rule.patterns) {"," if (new RegExp(pattern, 'i').test(lowerMessage)) {"," return rule.response;"," }"," }"," }"," return CHATBOT_CONFIG.fallbackMessage || 'Sorry, I did not understand. Please try again.';","}","","async function getRules() {"," const result = await dynamodb.send(new ScanCommand({ TableName: RULES_TABLE }));"," return (result.Items || []).map(item => ({"," patterns: JSON.parse(item.patterns?.S || '[]'),"," response: item.response?.S || '',"," })).sort((a, b) => (a.priority || 0) - (b.priority || 0));","}","","async function sendResponse(phoneNumber, message) {"," await sns.send(new PublishCommand({"," PhoneNumber: phoneNumber,"," Message: message.substring(0, 1600),"," MessageAttributes: {"," 'AWS.SNS.SMS.SMSType': { DataType: 'String', StringValue: 'Transactional' },"," },"," }));","}"].join(`
6946
+ `);static createSessionsTable(e){return{[`${e.slug}ChatbotSessionsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-chatbot-sessions`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createRulesTable(e){return{[`${e.slug}ChatbotRulesTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-chatbot-rules`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}}static createChatbotProcessorLambda(e){return{[`${e.slug}ChatbotProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-chatbot-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:da.ChatbotProcessorCode},Environment:{Variables:{SESSIONS_TABLE:e.sessionsTable,RULES_TABLE:e.rulesTable,CHATBOT_CONFIG:JSON.stringify(e.chatbotConfig),ORIGINATION_NUMBER:e.originationNumber||""}}}}}}static DefaultRules=[{id:"greeting",priority:1,patterns:["^(hi|hello|hey|howdy)$","^good (morning|afternoon|evening)"],response:"Hello! How can I help you today?"},{id:"help",priority:2,patterns:["^help$","what can you do","how does this work"],response:"I can help with: 1) Account info 2) Support 3) Hours. Reply with a number."},{id:"hours",priority:3,patterns:["hours","open","when are you"],response:"We are open Mon-Fri 9am-5pm EST. Closed weekends."},{id:"thanks",priority:4,patterns:["^(thanks|thank you|thx)"],response:"You're welcome! Is there anything else I can help with?"},{id:"bye",priority:5,patterns:["^(bye|goodbye|quit|exit|stop)$"],response:"Goodbye! Text us anytime if you need help.",action:"end"}]}class ma{static LinkShortenerCode=`
6947
6947
  const { DynamoDBClient, PutItemCommand, GetItemCommand, UpdateItemCommand } = require('@aws-sdk/client-dynamodb');
6948
6948
  const crypto = require('crypto');
6949
6949
 
@@ -7077,7 +7077,7 @@ function generateShortId() {
7077
7077
  }
7078
7078
  return id;
7079
7079
  }
7080
- `;static createLinksTable(e){return{[`${e.slug}ShortLinksTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-short-links`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createLinkShortenerLambda(e){return{[`${e.slug}LinkShortenerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-link-shortener`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:10,MemorySize:128,Code:{ZipFile:pa.LinkShortenerCode},Environment:{Variables:{LINKS_TABLE:e.linksTable,SHORT_DOMAIN:e.shortDomain||""}}}}}}static shortenUrlsInMessage(e,t,a){let r=/(https?:\/\/[^\s]+)/g,n=[],i=0;return{message:e.replace(r,(s)=>{let o=`${a}-${i++}`,c=`https://${t}/l/${o}`;return n.push({original:s,short:c,id:o}),c}),links:n}}}class Ce{static AbTestManagerCode=`
7080
+ `;static createLinksTable(e){return{[`${e.slug}ShortLinksTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-short-links`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createLinkShortenerLambda(e){return{[`${e.slug}LinkShortenerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-link-shortener`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:10,MemorySize:128,Code:{ZipFile:ma.LinkShortenerCode},Environment:{Variables:{LINKS_TABLE:e.linksTable,SHORT_DOMAIN:e.shortDomain||""}}}}}}static shortenUrlsInMessage(e,t,a){let r=/(https?:\/\/[^\s]+)/g,n=[],i=0;return{message:e.replace(r,(s)=>{let o=`${a}-${i++}`,c=`https://${t}/l/${o}`;return n.push({original:s,short:c,id:o}),c}),links:n}}}class Ae{static AbTestManagerCode=`
7081
7081
  const { DynamoDBClient, PutItemCommand, GetItemCommand, UpdateItemCommand, ScanCommand } = require('@aws-sdk/client-dynamodb');
7082
7082
 
7083
7083
  const dynamodb = new DynamoDBClient({});
@@ -7271,7 +7271,7 @@ function unmarshallTest(item) {
7271
7271
 
7272
7272
  return test;
7273
7273
  }
7274
- `;static createAbTestsTable(e){return{[`${e.slug}AbTestsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-ab-tests`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}}static createAbTestManagerLambda(e){return{[`${e.slug}AbTestManagerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-ab-test-manager`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Ce.AbTestManagerCode},Environment:{Variables:{AB_TESTS_TABLE:e.abTestsTable}}}}}}static selectVariant(e,t){let a=Ce.hashString(t+e.id)%100,r=0;for(let n=0;n<e.variants.length;n++)if(r+=e.trafficSplit[n],a<r)return e.variants[n];return e.variants[e.variants.length-1]}static determineWinner(e){if(e.variants.length===0)return null;let t=e.winningCriteria,a=e.variants[0],r=Ce.getMetricValue(a,t);for(let n of e.variants.slice(1)){let i=Ce.getMetricValue(n,t);if(i>r)r=i,a=n}return a}static calculateSignificance(e,t,a){let r=e.stats.sent,n=t.stats.sent;if(r<30||n<30)return 0;let i=Ce.getMetricValue(e,a)/100,s=Ce.getMetricValue(t,a)/100,o=(i*r+s*n)/(r+n),c=Math.sqrt(o*(1-o)*(1/r+1/n));if(c===0)return 0;let l=Math.abs(i-s)/c;if(l>=2.576)return 99;if(l>=1.96)return 95;if(l>=1.645)return 90;if(l>=1.28)return 80;return Math.round(l*30)}static getMetricValue(e,t){switch(t){case"delivery_rate":return e.stats.deliveryRate;case"click_rate":return e.stats.clickRate;case"reply_rate":return e.stats.replyRate;case"conversion_rate":return e.stats.conversionRate;default:return e.stats.deliveryRate}}static hashString(e){let t=0;for(let a=0;a<e.length;a++){let r=e.charCodeAt(a);t=(t<<5)-t+r,t=t&t}return Math.abs(t)}}class un{queues=new Map;messageGroups=new Map;deduplicationConfigs=new Map;messages=new Map;queueCounter=0;groupCounter=0;deduplicationCounter=0;messageCounter=0;sequenceCounter=0;createFIFOQueue(e){let t=`fifo-queue-${Date.now()}-${this.queueCounter++}`,a=e.name.endsWith(".fifo")?e.name:`${e.name}.fifo`,{name:r,...n}=e,i={id:t,name:a,queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${a}`,...n};return this.queues.set(t,i),this.createDeduplicationConfig({queueId:t,contentBasedDeduplication:e.contentBasedDeduplication,deduplicationInterval:300}),i}createHighThroughputFIFO(e){return this.createFIFOQueue({name:e.name,contentBasedDeduplication:e.contentBasedDeduplication??!0,deduplicationScope:"messageGroup",fifoThroughputLimit:"perMessageGroupId",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createStandardFIFO(e){return this.createFIFOQueue({name:e.name,contentBasedDeduplication:e.contentBasedDeduplication??!1,deduplicationScope:"queue",fifoThroughputLimit:"perQueue",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createDeduplicationConfig(e){let t={id:`dedup-${Date.now()}-${this.deduplicationCounter++}`,deduplicationHashes:new Map,...e};return this.deduplicationConfigs.set(e.queueId,t),t}sendMessage(e){let t=this.queues.get(e.queueId);if(!t)throw Error(`Queue not found: ${e.queueId}`);let a=this.deduplicationConfigs.get(e.queueId);if(a){let s=e.messageDeduplicationId||(t.contentBasedDeduplication?this.generateHash(e.messageBody):void 0);if(s&&this.isDuplicate(a,s))return null;if(s)a.deduplicationHashes.set(s,new Date)}let r=`msg-${Date.now()}-${this.messageCounter++}`,n=this.generateSequenceNumber(),i={id:r,messageId:r,messageGroupId:e.messageGroupId,messageDeduplicationId:e.messageDeduplicationId,body:e.messageBody,attributes:e.messageAttributes||{},sentTimestamp:new Date,sequenceNumber:n};return this.messages.set(r,i),this.updateMessageGroup(e.queueId,e.messageGroupId),i}isDuplicate(e,t){let a=e.deduplicationHashes.get(t);if(!a)return!1;if((Date.now()-a.getTime())/1000>e.deduplicationInterval)return e.deduplicationHashes.delete(t),!1;return!0}generateHash(e){let t=0;for(let a=0;a<e.length;a++){let r=e.charCodeAt(a);t=(t<<5)-t+r,t=t&t}return Math.abs(t).toString(36)}generateSequenceNumber(){return`${Date.now()}${this.sequenceCounter++}`.padStart(20,"0")}updateMessageGroup(e,t){let a=`${e}-${t}`,r=this.messageGroups.get(a);if(!r)r={id:`group-${Date.now()}-${this.groupCounter++}`,messageGroupId:t,queueId:e,messagesInFlight:0},this.messageGroups.set(a,r);r.messagesInFlight++,r.lastMessageTimestamp=new Date}getMessageGroups(e){return Array.from(this.messageGroups.values()).filter((t)=>t.queueId===e)}getQueue(e){return this.queues.get(e)}listQueues(){return Array.from(this.queues.values())}getMessages(e,t){let a=Array.from(this.messages.values());if(t)a=a.filter((r)=>r.messageGroupId===t);return a.sort((r,n)=>r.sequenceNumber.localeCompare(n.sequenceNumber))}generateFIFOQueueCF(e){return{Type:"AWS::SQS::Queue",Properties:{QueueName:e.name,FifoQueue:!0,ContentBasedDeduplication:e.contentBasedDeduplication,DeduplicationScope:e.deduplicationScope,FifoThroughputLimit:e.fifoThroughputLimit,MessageRetentionPeriod:e.messageRetentionPeriod,VisibilityTimeout:e.visibilityTimeout,ReceiveMessageWaitTimeSeconds:e.receiveMessageWaitTime,...e.deadLetterTargetArn&&{RedrivePolicy:{deadLetterTargetArn:e.deadLetterTargetArn,maxReceiveCount:e.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 tp=new un;class dn{monitors=new Map;metrics=new Map;alerts=new Map;reprocessJobs=new Map;monitorCounter=0;metricsCounter=0;alertCounter=0;jobCounter=0;createDLQMonitor(e){let t=`dlq-monitor-${Date.now()}-${this.monitorCounter++}`,a={id:t,...e};return this.monitors.set(t,a),a}createAutomatedMonitor(e){return this.createDLQMonitor({name:e.name,queueUrl:e.queueUrl,sourceQueues:e.sourceQueues,maxReceiveCount:3,alarmThreshold:10,autoReprocess:!0,reprocessStrategy:"scheduled",notificationTopicArn:e.notificationTopicArn})}collectMetrics(e){let t={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:e,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)},a=this.metrics.get(e)||[];return a.push(t),this.metrics.set(e,a),this.checkForAlerts(e,t),t}checkForAlerts(e,t){let a=Array.from(this.monitors.values()).find((n)=>n.queueUrl===e);if(!a)return;if(t.approximateNumberOfMessages>=a.alarmThreshold)this.createAlert({monitorId:a.id,alertType:"threshold_exceeded",severity:"high",message:`DLQ ${a.name} has ${t.approximateNumberOfMessages} messages (threshold: ${a.alarmThreshold})`});let r=3600;if(t.approximateAgeOfOldestMessage>r)this.createAlert({monitorId:a.id,alertType:"old_message",severity:"medium",message:`DLQ ${a.name} has messages older than ${r} seconds`})}createAlert(e){let t=`alert-${Date.now()}-${this.alertCounter++}`,a={id:t,timestamp:new Date,acknowledged:!1,...e};return this.alerts.set(t,a),a}acknowledgeAlert(e){let t=this.alerts.get(e);if(!t)throw Error(`Alert not found: ${e}`);return t.acknowledged=!0,t}createReprocessJob(e){let t=`reprocess-${Date.now()}-${this.jobCounter++}`,a={id:t,queueUrl:e.queueUrl,messageId:e.messageId,attempts:0,status:"pending"};return this.reprocessJobs.set(t,a),a}async executeReprocessJob(e){let t=this.reprocessJobs.get(e);if(!t)throw Error(`Reprocess job not found: ${e}`);t.status="processing",t.startedAt=new Date,t.attempts++,await new Promise((r)=>setTimeout(r,100));let a=Math.random()>0.3;if(t.status=a?"success":"failed",t.completedAt=new Date,!a)t.error="Reprocessing failed - original error still present";return t}async batchReprocess(e){let t=[];for(let a=0;a<e.maxMessages;a++){let r=this.createReprocessJob({queueUrl:e.queueUrl,messageId:`msg-${a}`});await this.executeReprocessJob(r.id),t.push(r)}return t}getDLQStatistics(e,t=24){let a=new Date(Date.now()-t*60*60*1000),r=(this.metrics.get(e)||[]).filter((u)=>u.timestamp>=a);if(r.length===0)return{totalMessages:0,avgAge:0,messagesReceived:0,messagesDeleted:0,messagesReprocessed:0,successRate:0};let n=r[r.length-1],i=r.reduce((u,m)=>u+m.messagesReceived,0),s=r.reduce((u,m)=>u+m.messagesDeleted,0),o=r.reduce((u,m)=>u+m.messagesReprocessed,0),c=r.reduce((u,m)=>u+m.approximateAgeOfOldestMessage,0)/r.length,l=o>0?s/o*100:0;return{totalMessages:n.approximateNumberOfMessages,avgAge:c,messagesReceived:i,messagesDeleted:s,messagesReprocessed:o,successRate:l}}getMonitor(e){return this.monitors.get(e)}listMonitors(){return Array.from(this.monitors.values())}getAlerts(e,t){let a=Array.from(this.alerts.values());if(e)a=a.filter((r)=>r.monitorId===e);if(t!==void 0)a=a.filter((r)=>r.acknowledged===t);return a.sort((r,n)=>n.timestamp.getTime()-r.timestamp.getTime())}getReprocessJobs(e){let t=Array.from(this.reprocessJobs.values());if(e)t=t.filter((a)=>a.queueUrl===e);return t}generateDLQAlarmCF(e){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${e.name}-messages-alarm`,AlarmDescription:`Alert when DLQ ${e.name} exceeds threshold`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Average",Period:300,EvaluationPeriods:1,Threshold:e.alarmThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:e.queueUrl.split("/").pop()}],...e.notificationTopicArn&&{AlarmActions:[e.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 ap=new dn;class mn{configs=new Map;jobs=new Map;metrics=new Map;configCounter=0;jobCounter=0;metricsCounter=0;createBatchConfig(e){let t=`batch-config-${Date.now()}-${this.configCounter++}`,a={id:t,...e};return this.configs.set(t,a),a}createHighThroughputConfig(e){return this.createBatchConfig({queueUrl:e.queueUrl,batchSize:10,maxWaitTime:100,parallelProcessors:10,retryAttempts:3,visibilityTimeout:30})}createLowLatencyConfig(e){return this.createBatchConfig({queueUrl:e.queueUrl,batchSize:1,maxWaitTime:0,parallelProcessors:5,retryAttempts:2,visibilityTimeout:10})}createBatchJob(e){let t=`batch-job-${Date.now()}-${this.jobCounter++}`;if(!this.configs.get(e.configId))throw Error(`Batch config not found: ${e.configId}`);let a=[];for(let n=0;n<e.messageCount;n++)a.push({id:`msg-${t}-${n}`,messageId:`${t}-${n}`,body:`Message ${n}`,receiptHandle:`receipt-${t}-${n}`,attributes:{},status:"pending"});let r={id:t,configId:e.configId,messages:a,status:"pending",processedCount:0,failedCount:0};return this.jobs.set(t,r),r}async processBatchJob(e){let t=this.jobs.get(e);if(!t)throw Error(`Batch job not found: ${e}`);let a=this.configs.get(t.configId);if(!a)throw Error(`Batch config not found: ${t.configId}`);t.status="processing",t.startedAt=new Date;let r=this.chunkArray(t.messages,a.batchSize);for(let n of r)await this.processBatch(n,a);return t.processedCount=t.messages.filter((n)=>n.status==="success").length,t.failedCount=t.messages.filter((n)=>n.status==="failed").length,t.status=t.failedCount===0?"completed":"failed",t.completedAt=new Date,this.collectProcessorMetrics(a.id,t),t}async processBatch(e,t){let a=e.map((r)=>this.processMessage(r,t));await Promise.all(a)}async processMessage(e,t){e.status="processing";let a=Date.now();await new Promise((n)=>setTimeout(n,Math.random()*100));let r=Date.now()-a;if(e.processingTime=r,Math.random()>0.1)e.status="success";else e.status="failed",e.error="Processing error"}chunkArray(e,t){let a=[];for(let r=0;r<e.length;r+=t)a.push(e.slice(r,r+t));return a}collectProcessorMetrics(e,t){let a=`metrics-${Date.now()}-${this.metricsCounter++}`,r=t.messages.filter((u)=>u.status==="success").map((u)=>u.processingTime||0).filter((u)=>u>0),n=r.length>0?r.reduce((u,m)=>u+m,0)/r.length:0,i=t.completedAt&&t.startedAt?(t.completedAt.getTime()-t.startedAt.getTime())/1000:1,s=t.processedCount/i,o=t.messages.length>0?t.failedCount/t.messages.length*100:0,c={id:a,configId:e,timestamp:new Date,messagesProcessed:t.processedCount,averageProcessingTime:n,throughput:s,errorRate:o},l=this.metrics.get(e)||[];l.push(c),this.metrics.set(e,l)}getBatchStatistics(e){let t=this.metrics.get(e)||[];if(t.length===0)return{totalJobsProcessed:0,totalMessagesProcessed:0,averageThroughput:0,averageErrorRate:0,averageProcessingTime:0};let a=t.reduce((s,o)=>s+o.messagesProcessed,0),r=t.reduce((s,o)=>s+o.throughput,0)/t.length,n=t.reduce((s,o)=>s+o.errorRate,0)/t.length,i=t.reduce((s,o)=>s+o.averageProcessingTime,0)/t.length;return{totalJobsProcessed:t.length,totalMessagesProcessed:a,averageThroughput:r,averageErrorRate:n,averageProcessingTime:i}}optimizeBatchConfig(e){let t=this.configs.get(e);if(!t)throw Error(`Batch config not found: ${e}`);let a=this.getBatchStatistics(e);if(a.averageErrorRate<5&&t.batchSize<10)t.batchSize=Math.min(10,t.batchSize+1);if(a.averageErrorRate>20&&t.batchSize>1)t.batchSize=Math.max(1,t.batchSize-1);if(a.averageThroughput<5&&t.parallelProcessors<20)t.parallelProcessors++;return t}getConfig(e){return this.configs.get(e)}listConfigs(){return Array.from(this.configs.values())}getJob(e){return this.jobs.get(e)}listJobs(e){let t=Array.from(this.jobs.values());if(e)t=t.filter((a)=>a.configId===e);return t}generateBatchProcessorCF(e){return{Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:`arn:aws:sqs:us-east-1:123456789012:${e.queueUrl.split("/").pop()}`,FunctionName:"batch-processor-function",BatchSize:e.batchSize,MaximumBatchingWindowInSeconds:e.maxWaitTime/1000,FunctionResponseTypes:["ReportBatchItemFailures"]}}}clear(){this.configs.clear(),this.jobs.clear(),this.metrics.clear(),this.configCounter=0,this.jobCounter=0,this.metricsCounter=0}}var rp=new mn;class pn{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(e){let t=`queue-${Date.now()}-${this.queueCounter++}`,a={id:t,purgeInProgress:!1,...e};return this.queues.set(t,a),a}createStandardQueue(e){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${e.queueName}`,queueName:e.queueName,messageRetentionPeriod:(e.messageRetentionDays||4)*24*60*60,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:0})}createLongPollingQueue(e){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${e.queueName}`,queueName:e.queueName,messageRetentionPeriod:345600,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:e.waitTimeSeconds||20})}createRetentionPolicy(e){let t=`retention-${Date.now()}-${this.retentionCounter++}`,a={id:t,...e};this.retentionPolicies.set(t,a);let r=this.queues.get(e.queueId);if(r)r.messageRetentionPeriod=e.retentionPeriod;return a}createShortRetentionPolicy(e){return this.createRetentionPolicy({queueId:e.queueId,retentionPeriod:e.retentionHours*60*60,autoCleanup:!0,archiveExpiredMessages:!1})}createArchivalRetentionPolicy(e){return this.createRetentionPolicy({queueId:e.queueId,retentionPeriod:e.retentionDays*24*60*60,autoCleanup:!0,cleanupSchedule:"cron(0 0 * * ? *)",archiveExpiredMessages:!0,archiveS3Bucket:e.s3Bucket})}createDelayQueue(e){let t=`delay-${Date.now()}-${this.delayCounter++}`,a={id:t,...e};this.delayQueues.set(t,a);let r=Array.from(this.queues.values()).find((n)=>n.queueUrl===e.queueUrl);if(r)r.delaySeconds=e.defaultDelay;return a}createScheduledDelayQueue(e){return this.createDelayQueue({queueUrl:e.queueUrl,defaultDelay:e.delayMinutes*60,perMessageDelay:!1,maxDelay:900})}async purgeQueue(e){let t=this.queues.get(e);if(!t)throw Error(`Queue not found: ${e}`);if(t.purgeInProgress)throw Error("Purge already in progress for this queue");let a=`purge-${Date.now()}-${this.purgeCounter++}`,r={id:a,queueUrl:t.queueUrl,status:"in_progress",startedAt:new Date};return this.purgeOperations.set(a,r),t.purgeInProgress=!0,setTimeout(()=>{r.status="completed",r.completedAt=new Date,r.messagesPurged=Math.floor(Math.random()*1000),t.purgeInProgress=!1},100),r}collectQueueMetrics(e){let t={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:e,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)},a=this.metrics.get(e)||[];return a.push(t),this.metrics.set(e,a),t}getQueueHealth(e){let t=this.metrics.get(e)||[];if(t.length===0)return{status:"healthy",issues:[],recommendations:[]};let a=t[t.length-1],r=[],n=[],i="healthy";if(a.approximateNumberOfMessages>1e4)i="critical",r.push("Large message backlog detected"),n.push("Increase consumer capacity");else if(a.approximateNumberOfMessages>1000)i="warning",r.push("Growing message backlog"),n.push("Monitor consumer performance");if(a.oldestMessageAge&&a.oldestMessageAge>3600){if(i!=="critical")i="warning";r.push("Old messages in queue"),n.push("Review message processing")}if(a.approximateNumberOfMessagesDelayed>100){if(i!=="critical")i="warning";r.push("High number of delayed messages")}return{status:i,issues:r,recommendations:n}}getQueue(e){return this.queues.get(e)}listQueues(){return Array.from(this.queues.values())}getRetentionPolicy(e){return this.retentionPolicies.get(e)}listRetentionPolicies(){return Array.from(this.retentionPolicies.values())}getPurgeOperations(e){let t=Array.from(this.purgeOperations.values());if(e)t=t.filter((a)=>a.queueUrl===e);return t}generateQueueCF(e){return{Type:"AWS::SQS::Queue",Properties:{QueueName:e.queueName,MessageRetentionPeriod:e.messageRetentionPeriod,DelaySeconds:e.delaySeconds,MaximumMessageSize:e.maximumMessageSize,ReceiveMessageWaitTimeSeconds:e.receiveMessageWaitTime}}}generateCleanupRuleCF(e){return{Type:"AWS::Events::Rule",Properties:{Name:`${e.id}-cleanup`,Description:"Automated queue cleanup",ScheduleExpression:e.cleanupSchedule||"cron(0 0 * * ? *)",State:"ENABLED",Targets:[{Arn:"arn:aws:lambda:us-east-1:123456789012:function:queue-cleanup",Id:e.id,Input:JSON.stringify({queueId:e.queueId,archiveBucket:e.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 np=new pn,jo=(()=>{let e=[];for(let t=0;t<256;t++){let a=t;for(let r=0;r<8;r++)a=a&1?3988292384^a>>>1:a>>>1;e[t]=a>>>0}return e})();function Ko(e){let t=4294967295;for(let a=0;a<e.length;a++)t=jo[(t^e[a])&255]^t>>>8;return(t^4294967295)>>>0}function Ho(e){if(typeof e==="string")return Buffer.from(e,"utf-8");if(Buffer.isBuffer(e))return e;return Buffer.from(e)}function qo(e){let t=Math.max(1980,e.getFullYear()),a=(e.getHours()<<11|e.getMinutes()<<5|e.getSeconds()>>1)&65535,r=(t-1980<<9|e.getMonth()+1<<5|e.getDate())&65535;return{time:a,date:r}}function nt(e){let t=[],a=[],r=0;for(let s of e){let o=Ho(s.data),c=Uo(o),l=Ko(o),u=Buffer.from(s.name.replace(/\\/g,"/"),"utf-8"),{time:m,date:p}=qo(s.date??new Date(0)),g=s.mode??420,h=Buffer.alloc(30+u.length);h.writeUInt32LE(67324752,0),h.writeUInt16LE(20,4),h.writeUInt16LE(0,6),h.writeUInt16LE(8,8),h.writeUInt16LE(m,10),h.writeUInt16LE(p,12),h.writeUInt32LE(l,14),h.writeUInt32LE(c.length,18),h.writeUInt32LE(o.length,22),h.writeUInt16LE(u.length,26),h.writeUInt16LE(0,28),u.copy(h,30);let y=Buffer.alloc(46+u.length);y.writeUInt32LE(33639248,0),y.writeUInt16LE(798,4),y.writeUInt16LE(20,6),y.writeUInt16LE(0,8),y.writeUInt16LE(8,10),y.writeUInt16LE(m,12),y.writeUInt16LE(p,14),y.writeUInt32LE(l,16),y.writeUInt32LE(c.length,20),y.writeUInt32LE(o.length,24),y.writeUInt16LE(u.length,28),y.writeUInt16LE(0,30),y.writeUInt16LE(0,32),y.writeUInt16LE(0,34),y.writeUInt16LE(0,36),y.writeUInt32LE((g&65535)<<16,38),y.writeUInt32LE(r,42),u.copy(y,46),t.push(h,c),a.push(y),r+=h.length+c.length}let n=Buffer.concat(a),i=Buffer.alloc(22);return i.writeUInt32LE(101010256,0),i.writeUInt16LE(0,4),i.writeUInt16LE(0,6),i.writeUInt16LE(e.length,8),i.writeUInt16LE(e.length,10),i.writeUInt32LE(n.length,12),i.writeUInt32LE(r,16),i.writeUInt16LE(0,20),Buffer.concat([...t,n,i])}function zo(e){let t=e.adapterImport??"./adapter",a=e.entryImport.replace(/\\/g,"/");return`// Generated by ts-cloud — serverless app bootstrap. Do not edit.
7274
+ `;static createAbTestsTable(e){return{[`${e.slug}AbTestsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e.slug}-ab-tests`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}}static createAbTestManagerLambda(e){return{[`${e.slug}AbTestManagerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e.slug}-ab-test-manager`,Runtime:"nodejs20.x",Handler:"index.handler",Role:e.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Ae.AbTestManagerCode},Environment:{Variables:{AB_TESTS_TABLE:e.abTestsTable}}}}}}static selectVariant(e,t){let a=Ae.hashString(t+e.id)%100,r=0;for(let n=0;n<e.variants.length;n++)if(r+=e.trafficSplit[n],a<r)return e.variants[n];return e.variants[e.variants.length-1]}static determineWinner(e){if(e.variants.length===0)return null;let t=e.winningCriteria,a=e.variants[0],r=Ae.getMetricValue(a,t);for(let n of e.variants.slice(1)){let i=Ae.getMetricValue(n,t);if(i>r)r=i,a=n}return a}static calculateSignificance(e,t,a){let r=e.stats.sent,n=t.stats.sent;if(r<30||n<30)return 0;let i=Ae.getMetricValue(e,a)/100,s=Ae.getMetricValue(t,a)/100,o=(i*r+s*n)/(r+n),c=Math.sqrt(o*(1-o)*(1/r+1/n));if(c===0)return 0;let l=Math.abs(i-s)/c;if(l>=2.576)return 99;if(l>=1.96)return 95;if(l>=1.645)return 90;if(l>=1.28)return 80;return Math.round(l*30)}static getMetricValue(e,t){switch(t){case"delivery_rate":return e.stats.deliveryRate;case"click_rate":return e.stats.clickRate;case"reply_rate":return e.stats.replyRate;case"conversion_rate":return e.stats.conversionRate;default:return e.stats.deliveryRate}}static hashString(e){let t=0;for(let a=0;a<e.length;a++){let r=e.charCodeAt(a);t=(t<<5)-t+r,t=t&t}return Math.abs(t)}}class ln{queues=new Map;messageGroups=new Map;deduplicationConfigs=new Map;messages=new Map;queueCounter=0;groupCounter=0;deduplicationCounter=0;messageCounter=0;sequenceCounter=0;createFIFOQueue(e){let t=`fifo-queue-${Date.now()}-${this.queueCounter++}`,a=e.name.endsWith(".fifo")?e.name:`${e.name}.fifo`,{name:r,...n}=e,i={id:t,name:a,queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${a}`,...n};return this.queues.set(t,i),this.createDeduplicationConfig({queueId:t,contentBasedDeduplication:e.contentBasedDeduplication,deduplicationInterval:300}),i}createHighThroughputFIFO(e){return this.createFIFOQueue({name:e.name,contentBasedDeduplication:e.contentBasedDeduplication??!0,deduplicationScope:"messageGroup",fifoThroughputLimit:"perMessageGroupId",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createStandardFIFO(e){return this.createFIFOQueue({name:e.name,contentBasedDeduplication:e.contentBasedDeduplication??!1,deduplicationScope:"queue",fifoThroughputLimit:"perQueue",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createDeduplicationConfig(e){let t={id:`dedup-${Date.now()}-${this.deduplicationCounter++}`,deduplicationHashes:new Map,...e};return this.deduplicationConfigs.set(e.queueId,t),t}sendMessage(e){let t=this.queues.get(e.queueId);if(!t)throw Error(`Queue not found: ${e.queueId}`);let a=this.deduplicationConfigs.get(e.queueId);if(a){let s=e.messageDeduplicationId||(t.contentBasedDeduplication?this.generateHash(e.messageBody):void 0);if(s&&this.isDuplicate(a,s))return null;if(s)a.deduplicationHashes.set(s,new Date)}let r=`msg-${Date.now()}-${this.messageCounter++}`,n=this.generateSequenceNumber(),i={id:r,messageId:r,messageGroupId:e.messageGroupId,messageDeduplicationId:e.messageDeduplicationId,body:e.messageBody,attributes:e.messageAttributes||{},sentTimestamp:new Date,sequenceNumber:n};return this.messages.set(r,i),this.updateMessageGroup(e.queueId,e.messageGroupId),i}isDuplicate(e,t){let a=e.deduplicationHashes.get(t);if(!a)return!1;if((Date.now()-a.getTime())/1000>e.deduplicationInterval)return e.deduplicationHashes.delete(t),!1;return!0}generateHash(e){let t=0;for(let a=0;a<e.length;a++){let r=e.charCodeAt(a);t=(t<<5)-t+r,t=t&t}return Math.abs(t).toString(36)}generateSequenceNumber(){return`${Date.now()}${this.sequenceCounter++}`.padStart(20,"0")}updateMessageGroup(e,t){let a=`${e}-${t}`,r=this.messageGroups.get(a);if(!r)r={id:`group-${Date.now()}-${this.groupCounter++}`,messageGroupId:t,queueId:e,messagesInFlight:0},this.messageGroups.set(a,r);r.messagesInFlight++,r.lastMessageTimestamp=new Date}getMessageGroups(e){return Array.from(this.messageGroups.values()).filter((t)=>t.queueId===e)}getQueue(e){return this.queues.get(e)}listQueues(){return Array.from(this.queues.values())}getMessages(e,t){let a=Array.from(this.messages.values());if(t)a=a.filter((r)=>r.messageGroupId===t);return a.sort((r,n)=>r.sequenceNumber.localeCompare(n.sequenceNumber))}generateFIFOQueueCF(e){return{Type:"AWS::SQS::Queue",Properties:{QueueName:e.name,FifoQueue:!0,ContentBasedDeduplication:e.contentBasedDeduplication,DeduplicationScope:e.deduplicationScope,FifoThroughputLimit:e.fifoThroughputLimit,MessageRetentionPeriod:e.messageRetentionPeriod,VisibilityTimeout:e.visibilityTimeout,ReceiveMessageWaitTimeSeconds:e.receiveMessageWaitTime,...e.deadLetterTargetArn&&{RedrivePolicy:{deadLetterTargetArn:e.deadLetterTargetArn,maxReceiveCount:e.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 ep=new ln;class un{monitors=new Map;metrics=new Map;alerts=new Map;reprocessJobs=new Map;monitorCounter=0;metricsCounter=0;alertCounter=0;jobCounter=0;createDLQMonitor(e){let t=`dlq-monitor-${Date.now()}-${this.monitorCounter++}`,a={id:t,...e};return this.monitors.set(t,a),a}createAutomatedMonitor(e){return this.createDLQMonitor({name:e.name,queueUrl:e.queueUrl,sourceQueues:e.sourceQueues,maxReceiveCount:3,alarmThreshold:10,autoReprocess:!0,reprocessStrategy:"scheduled",notificationTopicArn:e.notificationTopicArn})}collectMetrics(e){let t={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:e,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)},a=this.metrics.get(e)||[];return a.push(t),this.metrics.set(e,a),this.checkForAlerts(e,t),t}checkForAlerts(e,t){let a=Array.from(this.monitors.values()).find((n)=>n.queueUrl===e);if(!a)return;if(t.approximateNumberOfMessages>=a.alarmThreshold)this.createAlert({monitorId:a.id,alertType:"threshold_exceeded",severity:"high",message:`DLQ ${a.name} has ${t.approximateNumberOfMessages} messages (threshold: ${a.alarmThreshold})`});let r=3600;if(t.approximateAgeOfOldestMessage>r)this.createAlert({monitorId:a.id,alertType:"old_message",severity:"medium",message:`DLQ ${a.name} has messages older than ${r} seconds`})}createAlert(e){let t=`alert-${Date.now()}-${this.alertCounter++}`,a={id:t,timestamp:new Date,acknowledged:!1,...e};return this.alerts.set(t,a),a}acknowledgeAlert(e){let t=this.alerts.get(e);if(!t)throw Error(`Alert not found: ${e}`);return t.acknowledged=!0,t}createReprocessJob(e){let t=`reprocess-${Date.now()}-${this.jobCounter++}`,a={id:t,queueUrl:e.queueUrl,messageId:e.messageId,attempts:0,status:"pending"};return this.reprocessJobs.set(t,a),a}async executeReprocessJob(e){let t=this.reprocessJobs.get(e);if(!t)throw Error(`Reprocess job not found: ${e}`);t.status="processing",t.startedAt=new Date,t.attempts++,await new Promise((r)=>setTimeout(r,100));let a=Math.random()>0.3;if(t.status=a?"success":"failed",t.completedAt=new Date,!a)t.error="Reprocessing failed - original error still present";return t}async batchReprocess(e){let t=[];for(let a=0;a<e.maxMessages;a++){let r=this.createReprocessJob({queueUrl:e.queueUrl,messageId:`msg-${a}`});await this.executeReprocessJob(r.id),t.push(r)}return t}getDLQStatistics(e,t=24){let a=new Date(Date.now()-t*60*60*1000),r=(this.metrics.get(e)||[]).filter((u)=>u.timestamp>=a);if(r.length===0)return{totalMessages:0,avgAge:0,messagesReceived:0,messagesDeleted:0,messagesReprocessed:0,successRate:0};let n=r[r.length-1],i=r.reduce((u,m)=>u+m.messagesReceived,0),s=r.reduce((u,m)=>u+m.messagesDeleted,0),o=r.reduce((u,m)=>u+m.messagesReprocessed,0),c=r.reduce((u,m)=>u+m.approximateAgeOfOldestMessage,0)/r.length,l=o>0?s/o*100:0;return{totalMessages:n.approximateNumberOfMessages,avgAge:c,messagesReceived:i,messagesDeleted:s,messagesReprocessed:o,successRate:l}}getMonitor(e){return this.monitors.get(e)}listMonitors(){return Array.from(this.monitors.values())}getAlerts(e,t){let a=Array.from(this.alerts.values());if(e)a=a.filter((r)=>r.monitorId===e);if(t!==void 0)a=a.filter((r)=>r.acknowledged===t);return a.sort((r,n)=>n.timestamp.getTime()-r.timestamp.getTime())}getReprocessJobs(e){let t=Array.from(this.reprocessJobs.values());if(e)t=t.filter((a)=>a.queueUrl===e);return t}generateDLQAlarmCF(e){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${e.name}-messages-alarm`,AlarmDescription:`Alert when DLQ ${e.name} exceeds threshold`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Average",Period:300,EvaluationPeriods:1,Threshold:e.alarmThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:e.queueUrl.split("/").pop()}],...e.notificationTopicArn&&{AlarmActions:[e.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 tp=new un;class dn{configs=new Map;jobs=new Map;metrics=new Map;configCounter=0;jobCounter=0;metricsCounter=0;createBatchConfig(e){let t=`batch-config-${Date.now()}-${this.configCounter++}`,a={id:t,...e};return this.configs.set(t,a),a}createHighThroughputConfig(e){return this.createBatchConfig({queueUrl:e.queueUrl,batchSize:10,maxWaitTime:100,parallelProcessors:10,retryAttempts:3,visibilityTimeout:30})}createLowLatencyConfig(e){return this.createBatchConfig({queueUrl:e.queueUrl,batchSize:1,maxWaitTime:0,parallelProcessors:5,retryAttempts:2,visibilityTimeout:10})}createBatchJob(e){let t=`batch-job-${Date.now()}-${this.jobCounter++}`;if(!this.configs.get(e.configId))throw Error(`Batch config not found: ${e.configId}`);let a=[];for(let n=0;n<e.messageCount;n++)a.push({id:`msg-${t}-${n}`,messageId:`${t}-${n}`,body:`Message ${n}`,receiptHandle:`receipt-${t}-${n}`,attributes:{},status:"pending"});let r={id:t,configId:e.configId,messages:a,status:"pending",processedCount:0,failedCount:0};return this.jobs.set(t,r),r}async processBatchJob(e){let t=this.jobs.get(e);if(!t)throw Error(`Batch job not found: ${e}`);let a=this.configs.get(t.configId);if(!a)throw Error(`Batch config not found: ${t.configId}`);t.status="processing",t.startedAt=new Date;let r=this.chunkArray(t.messages,a.batchSize);for(let n of r)await this.processBatch(n,a);return t.processedCount=t.messages.filter((n)=>n.status==="success").length,t.failedCount=t.messages.filter((n)=>n.status==="failed").length,t.status=t.failedCount===0?"completed":"failed",t.completedAt=new Date,this.collectProcessorMetrics(a.id,t),t}async processBatch(e,t){let a=e.map((r)=>this.processMessage(r,t));await Promise.all(a)}async processMessage(e,t){e.status="processing";let a=Date.now();await new Promise((n)=>setTimeout(n,Math.random()*100));let r=Date.now()-a;if(e.processingTime=r,Math.random()>0.1)e.status="success";else e.status="failed",e.error="Processing error"}chunkArray(e,t){let a=[];for(let r=0;r<e.length;r+=t)a.push(e.slice(r,r+t));return a}collectProcessorMetrics(e,t){let a=`metrics-${Date.now()}-${this.metricsCounter++}`,r=t.messages.filter((u)=>u.status==="success").map((u)=>u.processingTime||0).filter((u)=>u>0),n=r.length>0?r.reduce((u,m)=>u+m,0)/r.length:0,i=t.completedAt&&t.startedAt?(t.completedAt.getTime()-t.startedAt.getTime())/1000:1,s=t.processedCount/i,o=t.messages.length>0?t.failedCount/t.messages.length*100:0,c={id:a,configId:e,timestamp:new Date,messagesProcessed:t.processedCount,averageProcessingTime:n,throughput:s,errorRate:o},l=this.metrics.get(e)||[];l.push(c),this.metrics.set(e,l)}getBatchStatistics(e){let t=this.metrics.get(e)||[];if(t.length===0)return{totalJobsProcessed:0,totalMessagesProcessed:0,averageThroughput:0,averageErrorRate:0,averageProcessingTime:0};let a=t.reduce((s,o)=>s+o.messagesProcessed,0),r=t.reduce((s,o)=>s+o.throughput,0)/t.length,n=t.reduce((s,o)=>s+o.errorRate,0)/t.length,i=t.reduce((s,o)=>s+o.averageProcessingTime,0)/t.length;return{totalJobsProcessed:t.length,totalMessagesProcessed:a,averageThroughput:r,averageErrorRate:n,averageProcessingTime:i}}optimizeBatchConfig(e){let t=this.configs.get(e);if(!t)throw Error(`Batch config not found: ${e}`);let a=this.getBatchStatistics(e);if(a.averageErrorRate<5&&t.batchSize<10)t.batchSize=Math.min(10,t.batchSize+1);if(a.averageErrorRate>20&&t.batchSize>1)t.batchSize=Math.max(1,t.batchSize-1);if(a.averageThroughput<5&&t.parallelProcessors<20)t.parallelProcessors++;return t}getConfig(e){return this.configs.get(e)}listConfigs(){return Array.from(this.configs.values())}getJob(e){return this.jobs.get(e)}listJobs(e){let t=Array.from(this.jobs.values());if(e)t=t.filter((a)=>a.configId===e);return t}generateBatchProcessorCF(e){return{Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:`arn:aws:sqs:us-east-1:123456789012:${e.queueUrl.split("/").pop()}`,FunctionName:"batch-processor-function",BatchSize:e.batchSize,MaximumBatchingWindowInSeconds:e.maxWaitTime/1000,FunctionResponseTypes:["ReportBatchItemFailures"]}}}clear(){this.configs.clear(),this.jobs.clear(),this.metrics.clear(),this.configCounter=0,this.jobCounter=0,this.metricsCounter=0}}var ap=new dn;class mn{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(e){let t=`queue-${Date.now()}-${this.queueCounter++}`,a={id:t,purgeInProgress:!1,...e};return this.queues.set(t,a),a}createStandardQueue(e){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${e.queueName}`,queueName:e.queueName,messageRetentionPeriod:(e.messageRetentionDays||4)*24*60*60,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:0})}createLongPollingQueue(e){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${e.queueName}`,queueName:e.queueName,messageRetentionPeriod:345600,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:e.waitTimeSeconds||20})}createRetentionPolicy(e){let t=`retention-${Date.now()}-${this.retentionCounter++}`,a={id:t,...e};this.retentionPolicies.set(t,a);let r=this.queues.get(e.queueId);if(r)r.messageRetentionPeriod=e.retentionPeriod;return a}createShortRetentionPolicy(e){return this.createRetentionPolicy({queueId:e.queueId,retentionPeriod:e.retentionHours*60*60,autoCleanup:!0,archiveExpiredMessages:!1})}createArchivalRetentionPolicy(e){return this.createRetentionPolicy({queueId:e.queueId,retentionPeriod:e.retentionDays*24*60*60,autoCleanup:!0,cleanupSchedule:"cron(0 0 * * ? *)",archiveExpiredMessages:!0,archiveS3Bucket:e.s3Bucket})}createDelayQueue(e){let t=`delay-${Date.now()}-${this.delayCounter++}`,a={id:t,...e};this.delayQueues.set(t,a);let r=Array.from(this.queues.values()).find((n)=>n.queueUrl===e.queueUrl);if(r)r.delaySeconds=e.defaultDelay;return a}createScheduledDelayQueue(e){return this.createDelayQueue({queueUrl:e.queueUrl,defaultDelay:e.delayMinutes*60,perMessageDelay:!1,maxDelay:900})}async purgeQueue(e){let t=this.queues.get(e);if(!t)throw Error(`Queue not found: ${e}`);if(t.purgeInProgress)throw Error("Purge already in progress for this queue");let a=`purge-${Date.now()}-${this.purgeCounter++}`,r={id:a,queueUrl:t.queueUrl,status:"in_progress",startedAt:new Date};return this.purgeOperations.set(a,r),t.purgeInProgress=!0,setTimeout(()=>{r.status="completed",r.completedAt=new Date,r.messagesPurged=Math.floor(Math.random()*1000),t.purgeInProgress=!1},100),r}collectQueueMetrics(e){let t={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:e,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)},a=this.metrics.get(e)||[];return a.push(t),this.metrics.set(e,a),t}getQueueHealth(e){let t=this.metrics.get(e)||[];if(t.length===0)return{status:"healthy",issues:[],recommendations:[]};let a=t[t.length-1],r=[],n=[],i="healthy";if(a.approximateNumberOfMessages>1e4)i="critical",r.push("Large message backlog detected"),n.push("Increase consumer capacity");else if(a.approximateNumberOfMessages>1000)i="warning",r.push("Growing message backlog"),n.push("Monitor consumer performance");if(a.oldestMessageAge&&a.oldestMessageAge>3600){if(i!=="critical")i="warning";r.push("Old messages in queue"),n.push("Review message processing")}if(a.approximateNumberOfMessagesDelayed>100){if(i!=="critical")i="warning";r.push("High number of delayed messages")}return{status:i,issues:r,recommendations:n}}getQueue(e){return this.queues.get(e)}listQueues(){return Array.from(this.queues.values())}getRetentionPolicy(e){return this.retentionPolicies.get(e)}listRetentionPolicies(){return Array.from(this.retentionPolicies.values())}getPurgeOperations(e){let t=Array.from(this.purgeOperations.values());if(e)t=t.filter((a)=>a.queueUrl===e);return t}generateQueueCF(e){return{Type:"AWS::SQS::Queue",Properties:{QueueName:e.queueName,MessageRetentionPeriod:e.messageRetentionPeriod,DelaySeconds:e.delaySeconds,MaximumMessageSize:e.maximumMessageSize,ReceiveMessageWaitTimeSeconds:e.receiveMessageWaitTime}}}generateCleanupRuleCF(e){return{Type:"AWS::Events::Rule",Properties:{Name:`${e.id}-cleanup`,Description:"Automated queue cleanup",ScheduleExpression:e.cleanupSchedule||"cron(0 0 * * ? *)",State:"ENABLED",Targets:[{Arn:"arn:aws:lambda:us-east-1:123456789012:function:queue-cleanup",Id:e.id,Input:JSON.stringify({queueId:e.queueId,archiveBucket:e.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 rp=new mn,jo=(()=>{let e=[];for(let t=0;t<256;t++){let a=t;for(let r=0;r<8;r++)a=a&1?3988292384^a>>>1:a>>>1;e[t]=a>>>0}return e})();function Ko(e){let t=4294967295;for(let a=0;a<e.length;a++)t=jo[(t^e[a])&255]^t>>>8;return(t^4294967295)>>>0}function Ho(e){if(typeof e==="string")return Buffer.from(e,"utf-8");if(Buffer.isBuffer(e))return e;return Buffer.from(e)}function qo(e){let t=Math.max(1980,e.getFullYear()),a=(e.getHours()<<11|e.getMinutes()<<5|e.getSeconds()>>1)&65535,r=(t-1980<<9|e.getMonth()+1<<5|e.getDate())&65535;return{time:a,date:r}}function rt(e){let t=[],a=[],r=0;for(let s of e){let o=Ho(s.data),c=Fo(o),l=Ko(o),u=Buffer.from(s.name.replace(/\\/g,"/"),"utf-8"),{time:m,date:p}=qo(s.date??new Date(0)),g=s.mode??420,h=Buffer.alloc(30+u.length);h.writeUInt32LE(67324752,0),h.writeUInt16LE(20,4),h.writeUInt16LE(0,6),h.writeUInt16LE(8,8),h.writeUInt16LE(m,10),h.writeUInt16LE(p,12),h.writeUInt32LE(l,14),h.writeUInt32LE(c.length,18),h.writeUInt32LE(o.length,22),h.writeUInt16LE(u.length,26),h.writeUInt16LE(0,28),u.copy(h,30);let y=Buffer.alloc(46+u.length);y.writeUInt32LE(33639248,0),y.writeUInt16LE(798,4),y.writeUInt16LE(20,6),y.writeUInt16LE(0,8),y.writeUInt16LE(8,10),y.writeUInt16LE(m,12),y.writeUInt16LE(p,14),y.writeUInt32LE(l,16),y.writeUInt32LE(c.length,20),y.writeUInt32LE(o.length,24),y.writeUInt16LE(u.length,28),y.writeUInt16LE(0,30),y.writeUInt16LE(0,32),y.writeUInt16LE(0,34),y.writeUInt16LE(0,36),y.writeUInt32LE((g&65535)<<16,38),y.writeUInt32LE(r,42),u.copy(y,46),t.push(h,c),a.push(y),r+=h.length+c.length}let n=Buffer.concat(a),i=Buffer.alloc(22);return i.writeUInt32LE(101010256,0),i.writeUInt16LE(0,4),i.writeUInt16LE(0,6),i.writeUInt16LE(e.length,8),i.writeUInt16LE(e.length,10),i.writeUInt32LE(n.length,12),i.writeUInt32LE(r,16),i.writeUInt16LE(0,20),Buffer.concat([...t,n,i])}function zo(e){let t=e.adapterImport??"./adapter",a=e.entryImport.replace(/\\/g,"/");return`// Generated by ts-cloud — serverless app bootstrap. Do not edit.
7275
7275
  import * as __userModule from ${JSON.stringify(a)}
7276
7276
  import { resolveApp, createHandlers } from ${JSON.stringify(t)}
7277
7277
 
@@ -7281,9 +7281,9 @@ const __handlers = createHandlers(__app)
7281
7281
  export const http = __handlers.http
7282
7282
  export const queue = __handlers.queue
7283
7283
  export const cli = __handlers.cli
7284
- `}var sc=["adapter.ts","recursion.ts","auto-recursion.ts"];function oc(){return Le(ac(ic(import.meta.url)),"runtime")}function cc(e,t,a){for(let r of e??[])a?.(`build: ${r}`),Qo(r,{stdio:"inherit",cwd:t})}function lc(e){return Jo("sha256").update(e).digest("hex")}function mp(e,t,a){return`deployments/${e}/${t}/${a}.zip`}async function pp(e){let t=nc(e.projectRoot??process.cwd()),{app:a}=e;if(!e.skipBuild)cc(a.build,t,e.onStep);let r=a.entry;if(!r)throw Error("serverless app: `entry` is required to package a Node/Bun application");let n=rc(r)?r:Le(t,r),i=Zo(Le(tc(),"tscloud-pkg-"));try{for(let p of sc)Yo(Le(oc(),p),Le(i,p));let s=Le(i,"bootstrap.ts");ec(s,zo({entryImport:n,adapterImport:"./adapter"})),e.onStep?.("bundling application");let o=await Bun.build({entrypoints:[s],target:a.kind==="bun"?"bun":"node",format:"esm",minify:!1,sourcemap:"none"});if(!o.success){let p=o.logs.map((g)=>String(g)).join(`
7284
+ `}var ic=["adapter.ts","recursion.ts","auto-recursion.ts"];function sc(){return Me(tc(nc(import.meta.url)),"runtime")}function oc(e,t,a){for(let r of e??[])a?.(`build: ${r}`),Jo(r,{stdio:"inherit",cwd:t})}function cc(e){return Qo("sha256").update(e).digest("hex")}function dp(e,t,a){return`deployments/${e}/${t}/${a}.zip`}async function mp(e){let t=rc(e.projectRoot??process.cwd()),{app:a}=e;if(!e.skipBuild)oc(a.build,t,e.onStep);let r=a.entry;if(!r)throw Error("serverless app: `entry` is required to package a Node/Bun application");let n=ac(r)?r:Me(t,r),i=Yo(Me(ec(),"tscloud-pkg-"));try{for(let p of ic)$o(Me(sc(),p),Me(i,p));let s=Me(i,"bootstrap.ts");Zo(s,zo({entryImport:n,adapterImport:"./adapter"})),e.onStep?.("bundling application");let o=await Bun.build({entrypoints:[s],target:a.kind==="bun"?"bun":"node",format:"esm",minify:!1,sourcemap:"none"});if(!o.success){let p=o.logs.map((g)=>String(g)).join(`
7285
7285
  `);throw Error(`serverless app bundle failed:
7286
- ${p}`)}let c=o.outputs[0],l=Buffer.from(await c.arrayBuffer()),u="index",m=nt([{name:`${u}.mjs`,data:l}]);return{zip:m,bundle:l,sha256:lc(m),handlerFile:u,handlers:{http:a.handlers?.http??`${u}.http`,queue:a.handlers?.queue??`${u}.queue`,cli:a.handlers?.cli??`${u}.cli`},bundleBytes:l.length}}finally{Xo(i,{recursive:!0,force:!0})}}var uc=["18","20","22"];function dc(e){if(!e)return"22";let t=String(e).match(/(\d+)/);return t?t[1]:"22"}function mc(e){let t=e.kind??"node";if(t==="php")return{lambdaRuntime:"provided.al2023",kind:"php",version:e.phpVersion??"8.3",usesLayer:!0,layerKind:"php",layerEnvVar:"TSCLOUD_PHP_LAYER_ARN"};if(t==="bun")return{lambdaRuntime:"provided.al2023",kind:"bun",version:e.runtimeVersion??"latest",usesLayer:!0,layerKind:"bun",layerEnvVar:"TSCLOUD_BUN_LAYER_ARN"};let a=dc(e.runtimeVersion);if(e.runtime!=="provided.al2023"&&uc.includes(a))return{lambdaRuntime:e.runtime&&e.runtime.startsWith("nodejs")?e.runtime:`nodejs${a}.x`,kind:"node",version:a,usesLayer:!1};return{lambdaRuntime:"provided.al2023",kind:"node",version:a,usesLayer:!0,layerKind:"node",layerEnvVar:"TSCLOUD_NODE_LAYER_ARN"}}function gn(e,t,a){if(e.queues===!1)return[];if(e.queues===void 0||e.queues===!0)return[{name:`${t}-${a}-default`}];return e.queues.map((r)=>{if(typeof r==="string")return{name:`${t}-${a}-${r}`};let[n,i]=Object.entries(r)[0];return{name:`${t}-${a}-${n}`,concurrency:i}})}function gp(e,t,a){return gn(e,t,a).map((r)=>r.name)}function hp(e){let{app:t,environment:a,handlers:r}=e,n=e.config.project.slug,i=mc(t).lambdaRuntime,s=t.architecture??"x86_64",o=e.config.project.region,c={http:`${n}-${a}-http`,queue:`${n}-${a}-queue`,cli:`${n}-${a}-cli`};if(t.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 l=gn(t,n,a),u=l.map((R)=>R.name),m=u.length>0,p=t.logRetention??14,g=t.packaging==="image";if(g&&t.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 h=(t.scheduler??"on")!=="off",y=(t.cache?.driver??"dynamodb")==="dynamodb",b=Boolean(t.assets),T=fi(n,a),w=t.tmpStorage??512,S={},E={},v=[{PolicyName:"tscloud-serverless-app",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:d.sub("arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*")},{Effect:"Allow",Action:["lambda:InvokeFunction"],Resource:d.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${n}-${a}-*`)},{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameter","ssm:GetParameters","ssm:GetParametersByPath"],Resource:[d.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${n}/${a}/*`),d.sub(`arn:aws:ssm:\${AWS::Region}:\${AWS::AccountId}:parameter/${n}/${a}/*`)]},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[d.sub(`arn:aws:s3:::${T}`),d.sub(`arn:aws:s3:::${T}/*`),...t.storage?.bucket?[d.sub(`arn:aws:s3:::${t.storage.bucket}`),d.sub(`arn:aws:s3:::${t.storage.bucket}/*`)]:[]]}]}}];if(m)v[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["sqs:SendMessage","sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes","sqs:GetQueueUrl"],Resource:d.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${n}-${a}-*`)});if(y)v[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:BatchGetItem","dynamodb:BatchWriteItem"],Resource:d.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${n}-${a}-cache*`)});let P=["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"];if(t.vpc?.subnets?.length)P.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");if(t.lambdaInsights)P.push("arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy");S.AppRole={Type:"AWS::IAM::Role",Properties:{RoleName:`${n}-${a}-app-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:P,Policies:v}};let N=(R)=>({TSCLOUD_LAMBDA_MODE:R,TSCLOUD_ENV:a,...t.octane?{TSCLOUD_OCTANE:"1"}:{},...t.scheduler==="sub-minute"?{TSCLOUD_SCHEDULER:"sub-minute"}:{},...y?{TSCLOUD_CACHE_TABLE:`${n}-${a}-cache`}:{},...m?{TSCLOUD_QUEUE:u[0]}:{},...t.env??{}}),I=Boolean(t.efs),D=typeof t.efs==="object"?t.efs:{},L=D.mountPath??"/mnt/local",O=I&&!D.accessPointArn,ce=D.accessPointArn??(O?d.getAtt("EfsAccessPoint","Arn"):void 0),j=t.vpc?.subnets??[],ae=j.length>0,F=t.cache?.driver==="elasticache"||t.database?.connection==="aurora-serverless"||Boolean(t.rdsProxy)||I;if(F&&!ae)throw Error("serverless app: elasticache / aurora-serverless / rdsProxy / efs require app.vpc.subnets (private subnets) to be set.");let we=ae?{VpcConfig:{SubnetIds:j,SecurityGroupIds:[...t.vpc?.securityGroups??[],...F?[d.getAtt("DataSecurityGroup","GroupId")]:[]]}}:{},Fe=O?j.map((R,x)=>`EfsMountTarget${x}`):[],kt=I?{FileSystemConfigs:[{Arn:ce,LocalMountPath:L}]}:{};if(I)v[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess","elasticfilesystem:DescribeMountTargets"],Resource:"*"});function le(R,x,M,V,me,it,be,st=w){S[`${R}LogGroup`]={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:`/aws/lambda/${x}`,RetentionInDays:p}};let $t=[...e.runtimeLayers??[],...t.lambdaInsights?[t.lambdaInsights.layerArn]:[]],Lt=g?{PackageType:"Image",Code:{ImageUri:d.ref("ImageUri")},...t.kind==="php"?{}:{ImageConfig:{Command:[M]}}}:{Runtime:i,Handler:M,Code:{S3Bucket:d.ref("ArtifactBucket"),S3Key:d.ref("ArtifactKey")},...$t.length?{Layers:[...new Set($t)]}:{}};S[R]={Type:"AWS::Lambda::Function",DependsOn:[`${R}LogGroup`,...Fe],Properties:{FunctionName:x,Architectures:[s],MemorySize:me,Timeout:it,Role:d.getAtt("AppRole","Arn"),Environment:{Variables:N(V)},EphemeralStorage:{Size:st},...Lt,...be!==void 0?{ReservedConcurrentExecutions:be}:{},...we,...kt}}}if(le("HttpFunction",c.http,r.http,"http",t.memory??1024,t.timeout??28,t.concurrency,w),le("CliFunction",c.cli,r.cli,"cli",t.cliMemory??1024,t.cliTimeout??900,void 0,t.cliTmpStorage??w),m)le("QueueFunction",c.queue,r.queue,"queue",t.queueMemory??1024,t.queueTimeout??120,void 0,t.queueTmpStorage??w);let re=(t.provisionedConcurrency??0)>0?t.provisionedConcurrency:0,ue=["HttpFunction","CliFunction",...m?["QueueFunction"]:[]];if(re)for(let R of ue)S[`${R}Version`]={Type:"AWS::Lambda::Version",DeletionPolicy:"Retain",Properties:{FunctionName:d.ref(R)}},S[`${R}Alias`]={Type:"AWS::Lambda::Alias",Properties:{FunctionName:d.ref(R),Name:"live",FunctionVersion:d.getAtt(`${R}Version`,"Version"),ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:re}}};let Ee=(R)=>re?d.ref(`${R}Alias`):d.getAtt(R,"Arn"),de=(R)=>re?d.ref(`${R}Alias`):d.ref(R);S.HttpApi={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:`${n}-${a}`,ProtocolType:"HTTP"}},S.HttpIntegration={Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:d.ref("HttpApi"),IntegrationType:"AWS_PROXY",IntegrationUri:Ee("HttpFunction"),PayloadFormatVersion:"2.0"}},S.HttpRoute={Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:d.ref("HttpApi"),RouteKey:"$default",Target:d.join("/",["integrations",d.ref("HttpIntegration")])}},S.HttpStage={Type:"AWS::ApiGatewayV2::Stage",Properties:{ApiId:d.ref("HttpApi"),StageName:"$default",AutoDeploy:!0}},S.HttpPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:de("HttpFunction"),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:d.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${HttpApi}/*/*")}},E.HttpApiEndpoint={Description:"HTTP API endpoint",Value:d.getAtt("HttpApi","ApiEndpoint")},E.HttpApiId={Description:"HTTP API id",Value:d.ref("HttpApi")};let Se=(Array.isArray(t.domain)?t.domain:t.domain?[t.domain]:[]).filter(Boolean);if(Se.length){if(!t.certificateArn&&!t.hostedZoneId)throw Error("serverless app: a custom `domain` needs either `certificateArn` (pre-issued, regional) or `hostedZoneId` (to auto-issue + validate an ACM cert).");let R=t.certificateArn;if(!R)S.HttpCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:Se[0],...Se.length>1?{SubjectAlternativeNames:Se.slice(1)}:{},ValidationMethod:"DNS",DomainValidationOptions:Se.map((x)=>({DomainName:x,HostedZoneId:t.hostedZoneId}))}},R=d.ref("HttpCertificate");Se.forEach((x,M)=>{let V=`HttpDomain${M}`;if(S[V]={Type:"AWS::ApiGatewayV2::DomainName",Properties:{DomainName:x,DomainNameConfigurations:[{CertificateArn:R,EndpointType:"REGIONAL"}]}},S[`HttpApiMapping${M}`]={Type:"AWS::ApiGatewayV2::ApiMapping",DependsOn:["HttpStage"],Properties:{ApiId:d.ref("HttpApi"),DomainName:d.ref(V),Stage:"$default"}},t.hostedZoneId)S[`HttpDomainRecord${M}`]={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:t.hostedZoneId,Name:x,Type:"A",AliasTarget:{DNSName:d.getAtt(V,"RegionalDomainName"),HostedZoneId:d.getAtt(V,"RegionalHostedZoneId")}}};E[`CustomDomain${M}`]={Description:`Custom domain ${x}`,Value:x},E[`CustomDomainTarget${M}`]={Description:`Point ${x} (CNAME/alias) at this APIGW regional domain`,Value:d.getAtt(V,"RegionalDomainName")}})}if(m)S.AppQueueDlq={Type:"AWS::SQS::Queue",Properties:{QueueName:`${n}-${a}-dlq`,MessageRetentionPeriod:1209600}},l.forEach((R,x)=>{let M=`AppQueue${x}`,V=t.queueTimeout??120;S[M]={Type:"AWS::SQS::Queue",Properties:{QueueName:R.name,VisibilityTimeout:Math.min(43200,V*6),RedrivePolicy:{deadLetterTargetArn:d.getAtt("AppQueueDlq","Arn"),maxReceiveCount:t.queueTries??3}}};let me=R.concurrency??t.queueConcurrency;S[`${M}Mapping`]={Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:d.getAtt(M,"Arn"),FunctionName:de("QueueFunction"),BatchSize:1,FunctionResponseTypes:["ReportBatchItemFailures"],...me?{ScalingConfig:{MaximumConcurrency:Math.max(2,me)}}:{}}},E[`QueueUrl${x}`]={Description:`Queue URL: ${R.name}`,Value:d.ref(M)}});if(h)S.SchedulerRule={Type:"AWS::Events::Rule",Properties:{Name:`${n}-${a}-scheduler`,ScheduleExpression:"rate(1 minute)",State:"ENABLED",Targets:[{Id:"cli",Arn:Ee("CliFunction"),Input:JSON.stringify({command:"schedule:run"})}]}},S.SchedulerPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:de("CliFunction"),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:d.getAtt("SchedulerRule","Arn")}};if(t.warm&&t.warm>0){let R={http:"HttpFunction",queue:"QueueFunction",cli:"CliFunction"},x=(t.warmFunctions??["http"]).filter((M)=>M!=="queue"||m);for(let M of x){let V=M.charAt(0).toUpperCase()+M.slice(1),me=Math.ceil(t.warm/5),it=0;for(let be=0;be<me;be++){let st=Math.min(5,t.warm-it);S[`Warmer${V}Rule${be}`]={Type:"AWS::Events::Rule",Properties:{Name:`${n}-${a}-warmer-${M}-${be}`,ScheduleExpression:"rate(5 minutes)",State:"ENABLED",Targets:Array.from({length:st},($t,Lt)=>({Id:`warm-${M}-${be}-${Lt}`,Arn:d.getAtt(R[M],"Arn"),Input:JSON.stringify({warmer:!0})}))}},it+=st}S[`Warmer${V}Permission`]={Type:"AWS::Lambda::Permission",Properties:{FunctionName:d.ref(R[M]),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:d.sub(`arn:aws:events:\${AWS::Region}:\${AWS::AccountId}:rule/${n}-${a}-warmer-${M}-*`)}}}}if(y)S.CacheTable={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n}-${a}-cache`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"key",AttributeType:"S"}],KeySchema:[{AttributeName:"key",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"expires_at",Enabled:!0}}},E.CacheTableName={Description:"DynamoDB cache table",Value:d.ref("CacheTable")};if(b){if(S.AssetsBucket={Type:"AWS::S3::Bucket",Properties:{BucketName:T,PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}}},S.AssetsOAC={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${n}-${a}-assets-oac`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},S.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:d.getAtt("AssetsBucket","RegionalDomainName"),OriginAccessControlId:d.ref("AssetsOAC"),S3OriginConfig:{OriginAccessIdentity:""}}],...t.assetDomain?{Aliases:[t.assetDomain],ViewerCertificate:{AcmCertificateArn:t.assetCertificateArn??d.ref("AssetsCertificate"),SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}}:{}}}},t.assetDomain){if(!t.assetCertificateArn){if(!t.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(o!=="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 ${o}. Supply a pre-issued us-east-1 \`assetCertificateArn\` instead.`);S.AssetsCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:t.assetDomain,ValidationMethod:"DNS",DomainValidationOptions:[{DomainName:t.assetDomain,HostedZoneId:t.hostedZoneId}]}}}if(t.hostedZoneId)S.AssetsDomainRecord={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:t.hostedZoneId,Name:t.assetDomain,Type:"A",AliasTarget:{DNSName:d.getAtt("AssetsDistribution","DomainName"),HostedZoneId:"Z2FDTNDATAQYW2"}}};E.AssetDomain={Description:"Custom asset CDN host",Value:t.assetDomain}}S.AssetsBucketPolicy={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:d.ref("AssetsBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:d.sub(`arn:aws:s3:::${T}/*`),Condition:{StringEquals:{"AWS:SourceArn":d.sub("arn:aws:cloudfront::${AWS::AccountId}:distribution/${AssetsDistribution}")}}}]}}},E.AssetsBucketName={Description:"Assets bucket",Value:d.ref("AssetsBucket")},E.AssetsCdnDomain={Description:"Assets CloudFront domain",Value:d.getAtt("AssetsDistribution","DomainName")}}if(t.firewall?.enabled){let R=[],x=0;if(t.firewall.rateLimit)R.push({Name:"rate-limit",Priority:x++,Action:{Block:{}},Statement:{RateBasedStatement:{Limit:t.firewall.rateLimit,AggregateKeyType:"IP"}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n}-${a}-rate`}});let M={sqlInjection:"AWSManagedRulesSQLiRuleSet",xss:"AWSManagedRulesCommonRuleSet",common:"AWSManagedRulesCommonRuleSet",botControl:"AWSManagedRulesBotControlRuleSet",ipReputation:"AWSManagedRulesAmazonIpReputationList"};for(let V of t.firewall.rules??[]){let me=M[V];if(!me)continue;R.push({Name:`managed-${V}`,Priority:x++,OverrideAction:{None:{}},Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:me}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n}-${a}-${V}`}})}S.WebAcl={Type:"AWS::WAFv2::WebACL",Properties:{Name:`${n}-${a}-waf`,Scope:"REGIONAL",DefaultAction:{Allow:{}},Rules:R,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n}-${a}-waf`}}},E.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:d.getAtt("WebAcl","Arn")}}if(ae&&F){if(!t.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.");S.DataSecurityGroup={Type:"AWS::EC2::SecurityGroup",Properties:{VpcId:t.vpc.id,GroupDescription:`${n}-${a} serverless data access`,SecurityGroupIngress:[{IpProtocol:"-1",CidrIp:"10.0.0.0/8"}]}}}if(O)S.EfsFileSystem={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:!0,FileSystemTags:[{Key:"Name",Value:`${n}-${a}-efs`}]}},j.forEach((R,x)=>{S[`EfsMountTarget${x}`]={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:d.ref("EfsFileSystem"),SubnetId:R,SecurityGroups:[d.getAtt("DataSecurityGroup","GroupId")]}}}),S.EfsAccessPoint={Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:d.ref("EfsFileSystem"),PosixUser:{Uid:1001,Gid:1001},RootDirectory:{Path:"/lambda",CreationInfo:{OwnerUid:1001,OwnerGid:1001,Permissions:"0755"}}}},E.EfsFileSystemId={Description:"EFS file system id",Value:d.ref("EfsFileSystem")};if(t.cache?.driver==="elasticache")S.CacheSubnetGroup={Type:"AWS::ElastiCache::SubnetGroup",Properties:{Description:`${n}-${a} cache subnets`,SubnetIds:j}},S.CacheCluster={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:`${n}-${a}-cache`,ReplicationGroupDescription:`${n}-${a} redis`,Engine:"redis",CacheNodeType:"cache.t4g.micro",NumCacheClusters:1,AutomaticFailoverEnabled:!1,CacheSubnetGroupName:d.ref("CacheSubnetGroup"),SecurityGroupIds:[d.getAtt("DataSecurityGroup","GroupId")],TransitEncryptionEnabled:!1}},E.CacheEndpoint={Description:"Redis primary endpoint",Value:d.getAtt("CacheCluster","PrimaryEndPoint.Address")};if(t.database?.connection==="aurora-serverless")S.DbSubnetGroup={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupDescription:`${n}-${a} db subnets`,SubnetIds:j}},S.DbSecret={Type:"AWS::SecretsManager::Secret",Properties:{Name:`${n}/${a}/db`,GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"app"}),GenerateStringKey:"password",PasswordLength:32,ExcludePunctuation:!0}}},S.DbCluster={Type:"AWS::RDS::DBCluster",Properties:{Engine:"aurora-mysql",EngineMode:"provisioned",DBClusterIdentifier:`${n}-${a}-db`,DatabaseName:"app",MasterUsername:d.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:username}}"),MasterUserPassword:d.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:password}}"),ServerlessV2ScalingConfiguration:{MinCapacity:t.database?.minCapacity??0.5,MaxCapacity:t.database?.maxCapacity??4},DBSubnetGroupName:d.ref("DbSubnetGroup"),VpcSecurityGroupIds:[d.getAtt("DataSecurityGroup","GroupId")]}},S.DbInstance={Type:"AWS::RDS::DBInstance",Properties:{Engine:"aurora-mysql",DBInstanceClass:"db.serverless",DBClusterIdentifier:d.ref("DbCluster")}},E.DbEndpoint={Description:"Aurora cluster endpoint",Value:d.getAtt("DbCluster","Endpoint.Address")};if(t.rdsProxy&&t.database?.connection==="aurora-serverless")S.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:d.ref("DbSecret")}]}}]}},S.DbProxy={Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:typeof t.rdsProxy==="object"&&t.rdsProxy.name?t.rdsProxy.name:`${n}-${a}-proxy`,EngineFamily:"MYSQL",RoleArn:d.getAtt("DbProxyRole","Arn"),Auth:[{AuthScheme:"SECRETS",SecretArn:d.ref("DbSecret"),IAMAuth:"DISABLED"}],VpcSubnetIds:j,VpcSecurityGroupIds:[d.getAtt("DataSecurityGroup","GroupId")],RequireTLS:!1}},S.DbProxyTargetGroup={Type:"AWS::RDS::DBProxyTargetGroup",DependsOn:["DbInstance"],Properties:{DBProxyName:d.ref("DbProxy"),TargetGroupName:"default",DBClusterIdentifiers:[d.ref("DbCluster")]}},E.DbProxyEndpoint={Description:"RDS Proxy endpoint",Value:d.getAtt("DbProxy","Endpoint")};if(E.HttpFunctionName={Description:"HTTP function name",Value:d.ref("HttpFunction")},E.CliFunctionName={Description:"CLI function name",Value:d.ref("CliFunction")},m)E.QueueFunctionName={Description:"Queue function name",Value:d.ref("QueueFunction")};let $e={AWSTemplateFormatVersion:"2010-09-09",Description:`Serverless application for ${e.config.project.name} (${n}-${a})`,Parameters:g?{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:S,Outputs:E},Ve={};for(let R of Object.values(S))Ve[R.Type]=(Ve[R.Type]??0)+1;return{template:$e,functionNames:c,queueNames:u,resourceSummary:Ve}}var pc=["cli","fpm","curl","mbstring","xml","pdo","mysqlnd","gd","bcmath","intl","opcache","sodium","process","pecl-redis6","pecl-apcu","pgsql"];function gc(e){let t=`php${e.replace(".","")}`;return pc.map((a)=>`${t}-php-${a}`)}function hn(e,t){let a=`php${e.replace(".","")}`,r=gc(e).join(" \\\n "),n=`/opt/remi/${a}/root`,i=`/etc/opt/remi/${a}`;return`${t?`FROM almalinux:9 AS ${t}`:"FROM almalinux:9"}
7286
+ ${p}`)}let c=o.outputs[0],l=Buffer.from(await c.arrayBuffer()),u="index",m=rt([{name:`${u}.mjs`,data:l}]);return{zip:m,bundle:l,sha256:cc(m),handlerFile:u,handlers:{http:a.handlers?.http??`${u}.http`,queue:a.handlers?.queue??`${u}.queue`,cli:a.handlers?.cli??`${u}.cli`},bundleBytes:l.length}}finally{Xo(i,{recursive:!0,force:!0})}}var lc=["18","20","22"];function uc(e){if(!e)return"22";let t=String(e).match(/(\d+)/);return t?t[1]:"22"}function dc(e){let t=e.kind??"node";if(t==="php")return{lambdaRuntime:"provided.al2023",kind:"php",version:e.phpVersion??"8.3",usesLayer:!0,layerKind:"php",layerEnvVar:"TSCLOUD_PHP_LAYER_ARN"};if(t==="bun")return{lambdaRuntime:"provided.al2023",kind:"bun",version:e.runtimeVersion??"latest",usesLayer:!0,layerKind:"bun",layerEnvVar:"TSCLOUD_BUN_LAYER_ARN"};let a=uc(e.runtimeVersion);if(e.runtime!=="provided.al2023"&&lc.includes(a))return{lambdaRuntime:e.runtime&&e.runtime.startsWith("nodejs")?e.runtime:`nodejs${a}.x`,kind:"node",version:a,usesLayer:!1};return{lambdaRuntime:"provided.al2023",kind:"node",version:a,usesLayer:!0,layerKind:"node",layerEnvVar:"TSCLOUD_NODE_LAYER_ARN"}}function pn(e,t,a){if(e.queues===!1)return[];if(e.queues===void 0||e.queues===!0)return[{name:`${t}-${a}-default`}];return e.queues.map((r)=>{if(typeof r==="string")return{name:`${t}-${a}-${r}`};let[n,i]=Object.entries(r)[0];return{name:`${t}-${a}-${n}`,concurrency:i}})}function pp(e,t,a){return pn(e,t,a).map((r)=>r.name)}function gp(e){let{app:t,environment:a,handlers:r}=e,n=e.config.project.slug,i=dc(t).lambdaRuntime,s=t.architecture??"x86_64",o=e.config.project.region,c={http:`${n}-${a}-http`,queue:`${n}-${a}-queue`,cli:`${n}-${a}-cli`};if(t.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 l=pn(t,n,a),u=l.map((R)=>R.name),m=u.length>0,p=t.logRetention??14,g=t.packaging==="image";if(g&&t.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 h=(t.scheduler??"on")!=="off",y=(t.cache?.driver??"dynamodb")==="dynamodb",b=Boolean(t.assets),T=yi(n,a),w=t.tmpStorage??512,S={},E={},v=[{PolicyName:"tscloud-serverless-app",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:d.sub("arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*")},{Effect:"Allow",Action:["lambda:InvokeFunction"],Resource:d.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${n}-${a}-*`)},{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameter","ssm:GetParameters","ssm:GetParametersByPath"],Resource:[d.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${n}/${a}/*`),d.sub(`arn:aws:ssm:\${AWS::Region}:\${AWS::AccountId}:parameter/${n}/${a}/*`)]},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[d.sub(`arn:aws:s3:::${T}`),d.sub(`arn:aws:s3:::${T}/*`),...t.storage?.bucket?[d.sub(`arn:aws:s3:::${t.storage.bucket}`),d.sub(`arn:aws:s3:::${t.storage.bucket}/*`)]:[]]}]}}];if(m)v[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["sqs:SendMessage","sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes","sqs:GetQueueUrl"],Resource:d.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${n}-${a}-*`)});if(y)v[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:BatchGetItem","dynamodb:BatchWriteItem"],Resource:d.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${n}-${a}-cache*`)});let P=["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"];if(t.vpc?.subnets?.length)P.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");if(t.lambdaInsights)P.push("arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy");S.AppRole={Type:"AWS::IAM::Role",Properties:{RoleName:`${n}-${a}-app-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:P,Policies:v}};let N=(R)=>({TSCLOUD_LAMBDA_MODE:R,TSCLOUD_ENV:a,...t.octane?{TSCLOUD_OCTANE:"1"}:{},...t.scheduler==="sub-minute"?{TSCLOUD_SCHEDULER:"sub-minute"}:{},...y?{TSCLOUD_CACHE_TABLE:`${n}-${a}-cache`}:{},...m?{TSCLOUD_QUEUE:u[0]}:{},...t.env??{}}),I=Boolean(t.efs),D=typeof t.efs==="object"?t.efs:{},M=D.mountPath??"/mnt/local",O=I&&!D.accessPointArn,oe=D.accessPointArn??(O?d.getAtt("EfsAccessPoint","Arn"):void 0),j=t.vpc?.subnets??[],te=j.length>0,G=t.cache?.driver==="elasticache"||t.database?.connection==="aurora-serverless"||Boolean(t.rdsProxy)||I;if(G&&!te)throw Error("serverless app: elasticache / aurora-serverless / rdsProxy / efs require app.vpc.subnets (private subnets) to be set.");let ve=te?{VpcConfig:{SubnetIds:j,SecurityGroupIds:[...t.vpc?.securityGroups??[],...G?[d.getAtt("DataSecurityGroup","GroupId")]:[]]}}:{},Ge=O?j.map((R,x)=>`EfsMountTarget${x}`):[],Dt=I?{FileSystemConfigs:[{Arn:oe,LocalMountPath:M}]}:{};if(I)v[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess","elasticfilesystem:DescribeMountTargets"],Resource:"*"});function ce(R,x,L,V,de,nt,Se,it=w){S[`${R}LogGroup`]={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:`/aws/lambda/${x}`,RetentionInDays:p}};let kt=[...e.runtimeLayers??[],...t.lambdaInsights?[t.lambdaInsights.layerArn]:[]],Mt=g?{PackageType:"Image",Code:{ImageUri:d.ref("ImageUri")},...t.kind==="php"?{}:{ImageConfig:{Command:[L]}}}:{Runtime:i,Handler:L,Code:{S3Bucket:d.ref("ArtifactBucket"),S3Key:d.ref("ArtifactKey")},...kt.length?{Layers:[...new Set(kt)]}:{}};S[R]={Type:"AWS::Lambda::Function",DependsOn:[`${R}LogGroup`,...Ge],Properties:{FunctionName:x,Architectures:[s],MemorySize:de,Timeout:nt,Role:d.getAtt("AppRole","Arn"),Environment:{Variables:N(V)},EphemeralStorage:{Size:it},...Mt,...Se!==void 0?{ReservedConcurrentExecutions:Se}:{},...ve,...Dt}}}if(ce("HttpFunction",c.http,r.http,"http",t.memory??1024,t.timeout??28,t.concurrency,w),ce("CliFunction",c.cli,r.cli,"cli",t.cliMemory??1024,t.cliTimeout??900,void 0,t.cliTmpStorage??w),m)ce("QueueFunction",c.queue,r.queue,"queue",t.queueMemory??1024,t.queueTimeout??120,void 0,t.queueTmpStorage??w);let ae=(t.provisionedConcurrency??0)>0?t.provisionedConcurrency:0,le=["HttpFunction","CliFunction",...m?["QueueFunction"]:[]];if(ae)for(let R of le)S[`${R}Version`]={Type:"AWS::Lambda::Version",DeletionPolicy:"Retain",Properties:{FunctionName:d.ref(R)}},S[`${R}Alias`]={Type:"AWS::Lambda::Alias",Properties:{FunctionName:d.ref(R),Name:"live",FunctionVersion:d.getAtt(`${R}Version`,"Version"),ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:ae}}};let we=(R)=>ae?d.ref(`${R}Alias`):d.getAtt(R,"Arn"),ue=(R)=>ae?d.ref(`${R}Alias`):d.ref(R);S.HttpApi={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:`${n}-${a}`,ProtocolType:"HTTP"}},S.HttpIntegration={Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:d.ref("HttpApi"),IntegrationType:"AWS_PROXY",IntegrationUri:we("HttpFunction"),PayloadFormatVersion:"2.0"}},S.HttpRoute={Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:d.ref("HttpApi"),RouteKey:"$default",Target:d.join("/",["integrations",d.ref("HttpIntegration")])}},S.HttpStage={Type:"AWS::ApiGatewayV2::Stage",Properties:{ApiId:d.ref("HttpApi"),StageName:"$default",AutoDeploy:!0}},S.HttpPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:ue("HttpFunction"),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:d.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${HttpApi}/*/*")}},E.HttpApiEndpoint={Description:"HTTP API endpoint",Value:d.getAtt("HttpApi","ApiEndpoint")},E.HttpApiId={Description:"HTTP API id",Value:d.ref("HttpApi")};let fe=(Array.isArray(t.domain)?t.domain:t.domain?[t.domain]:[]).filter(Boolean);if(fe.length){if(!t.certificateArn&&!t.hostedZoneId)throw Error("serverless app: a custom `domain` needs either `certificateArn` (pre-issued, regional) or `hostedZoneId` (to auto-issue + validate an ACM cert).");let R=t.certificateArn;if(!R)S.HttpCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:fe[0],...fe.length>1?{SubjectAlternativeNames:fe.slice(1)}:{},ValidationMethod:"DNS",DomainValidationOptions:fe.map((x)=>({DomainName:x,HostedZoneId:t.hostedZoneId}))}},R=d.ref("HttpCertificate");fe.forEach((x,L)=>{let V=`HttpDomain${L}`;if(S[V]={Type:"AWS::ApiGatewayV2::DomainName",Properties:{DomainName:x,DomainNameConfigurations:[{CertificateArn:R,EndpointType:"REGIONAL"}]}},S[`HttpApiMapping${L}`]={Type:"AWS::ApiGatewayV2::ApiMapping",DependsOn:["HttpStage"],Properties:{ApiId:d.ref("HttpApi"),DomainName:d.ref(V),Stage:"$default"}},t.hostedZoneId)S[`HttpDomainRecord${L}`]={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:t.hostedZoneId,Name:x,Type:"A",AliasTarget:{DNSName:d.getAtt(V,"RegionalDomainName"),HostedZoneId:d.getAtt(V,"RegionalHostedZoneId")}}};E[`CustomDomain${L}`]={Description:`Custom domain ${x}`,Value:x},E[`CustomDomainTarget${L}`]={Description:`Point ${x} (CNAME/alias) at this APIGW regional domain`,Value:d.getAtt(V,"RegionalDomainName")}})}if(m)S.AppQueueDlq={Type:"AWS::SQS::Queue",Properties:{QueueName:`${n}-${a}-dlq`,MessageRetentionPeriod:1209600}},l.forEach((R,x)=>{let L=`AppQueue${x}`,V=t.queueTimeout??120;S[L]={Type:"AWS::SQS::Queue",Properties:{QueueName:R.name,VisibilityTimeout:Math.min(43200,V*6),RedrivePolicy:{deadLetterTargetArn:d.getAtt("AppQueueDlq","Arn"),maxReceiveCount:t.queueTries??3}}};let de=R.concurrency??t.queueConcurrency;S[`${L}Mapping`]={Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:d.getAtt(L,"Arn"),FunctionName:ue("QueueFunction"),BatchSize:1,FunctionResponseTypes:["ReportBatchItemFailures"],...de?{ScalingConfig:{MaximumConcurrency:Math.max(2,de)}}:{}}},E[`QueueUrl${x}`]={Description:`Queue URL: ${R.name}`,Value:d.ref(L)}});if(h)S.SchedulerRule={Type:"AWS::Events::Rule",Properties:{Name:`${n}-${a}-scheduler`,ScheduleExpression:"rate(1 minute)",State:"ENABLED",Targets:[{Id:"cli",Arn:we("CliFunction"),Input:JSON.stringify({command:"schedule:run"})}]}},S.SchedulerPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:ue("CliFunction"),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:d.getAtt("SchedulerRule","Arn")}};if(t.warm&&t.warm>0){let R={http:"HttpFunction",queue:"QueueFunction",cli:"CliFunction"},x=(t.warmFunctions??["http"]).filter((L)=>L!=="queue"||m);for(let L of x){let V=L.charAt(0).toUpperCase()+L.slice(1),de=Math.ceil(t.warm/5),nt=0;for(let Se=0;Se<de;Se++){let it=Math.min(5,t.warm-nt);S[`Warmer${V}Rule${Se}`]={Type:"AWS::Events::Rule",Properties:{Name:`${n}-${a}-warmer-${L}-${Se}`,ScheduleExpression:"rate(5 minutes)",State:"ENABLED",Targets:Array.from({length:it},(kt,Mt)=>({Id:`warm-${L}-${Se}-${Mt}`,Arn:d.getAtt(R[L],"Arn"),Input:JSON.stringify({warmer:!0})}))}},nt+=it}S[`Warmer${V}Permission`]={Type:"AWS::Lambda::Permission",Properties:{FunctionName:d.ref(R[L]),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:d.sub(`arn:aws:events:\${AWS::Region}:\${AWS::AccountId}:rule/${n}-${a}-warmer-${L}-*`)}}}}if(y)S.CacheTable={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n}-${a}-cache`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"key",AttributeType:"S"}],KeySchema:[{AttributeName:"key",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"expires_at",Enabled:!0}}},E.CacheTableName={Description:"DynamoDB cache table",Value:d.ref("CacheTable")};if(b){if(S.AssetsBucket={Type:"AWS::S3::Bucket",Properties:{BucketName:T,PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}}},S.AssetsOAC={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${n}-${a}-assets-oac`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},S.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:d.getAtt("AssetsBucket","RegionalDomainName"),OriginAccessControlId:d.ref("AssetsOAC"),S3OriginConfig:{OriginAccessIdentity:""}}],...t.assetDomain?{Aliases:[t.assetDomain],ViewerCertificate:{AcmCertificateArn:t.assetCertificateArn??d.ref("AssetsCertificate"),SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}}:{}}}},t.assetDomain){if(!t.assetCertificateArn){if(!t.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(o!=="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 ${o}. Supply a pre-issued us-east-1 \`assetCertificateArn\` instead.`);S.AssetsCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:t.assetDomain,ValidationMethod:"DNS",DomainValidationOptions:[{DomainName:t.assetDomain,HostedZoneId:t.hostedZoneId}]}}}if(t.hostedZoneId)S.AssetsDomainRecord={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:t.hostedZoneId,Name:t.assetDomain,Type:"A",AliasTarget:{DNSName:d.getAtt("AssetsDistribution","DomainName"),HostedZoneId:"Z2FDTNDATAQYW2"}}};E.AssetDomain={Description:"Custom asset CDN host",Value:t.assetDomain}}S.AssetsBucketPolicy={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:d.ref("AssetsBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:d.sub(`arn:aws:s3:::${T}/*`),Condition:{StringEquals:{"AWS:SourceArn":d.sub("arn:aws:cloudfront::${AWS::AccountId}:distribution/${AssetsDistribution}")}}}]}}},E.AssetsBucketName={Description:"Assets bucket",Value:d.ref("AssetsBucket")},E.AssetsCdnDomain={Description:"Assets CloudFront domain",Value:d.getAtt("AssetsDistribution","DomainName")}}if(t.firewall?.enabled){let R=[],x=0;if(t.firewall.rateLimit)R.push({Name:"rate-limit",Priority:x++,Action:{Block:{}},Statement:{RateBasedStatement:{Limit:t.firewall.rateLimit,AggregateKeyType:"IP"}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n}-${a}-rate`}});let L={sqlInjection:"AWSManagedRulesSQLiRuleSet",xss:"AWSManagedRulesCommonRuleSet",common:"AWSManagedRulesCommonRuleSet",botControl:"AWSManagedRulesBotControlRuleSet",ipReputation:"AWSManagedRulesAmazonIpReputationList"};for(let V of t.firewall.rules??[]){let de=L[V];if(!de)continue;R.push({Name:`managed-${V}`,Priority:x++,OverrideAction:{None:{}},Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:de}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n}-${a}-${V}`}})}S.WebAcl={Type:"AWS::WAFv2::WebACL",Properties:{Name:`${n}-${a}-waf`,Scope:"REGIONAL",DefaultAction:{Allow:{}},Rules:R,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${n}-${a}-waf`}}},E.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:d.getAtt("WebAcl","Arn")}}if(te&&G){if(!t.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.");S.DataSecurityGroup={Type:"AWS::EC2::SecurityGroup",Properties:{VpcId:t.vpc.id,GroupDescription:`${n}-${a} serverless data access`,SecurityGroupIngress:[{IpProtocol:"-1",CidrIp:"10.0.0.0/8"}]}}}if(O)S.EfsFileSystem={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:!0,FileSystemTags:[{Key:"Name",Value:`${n}-${a}-efs`}]}},j.forEach((R,x)=>{S[`EfsMountTarget${x}`]={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:d.ref("EfsFileSystem"),SubnetId:R,SecurityGroups:[d.getAtt("DataSecurityGroup","GroupId")]}}}),S.EfsAccessPoint={Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:d.ref("EfsFileSystem"),PosixUser:{Uid:1001,Gid:1001},RootDirectory:{Path:"/lambda",CreationInfo:{OwnerUid:1001,OwnerGid:1001,Permissions:"0755"}}}},E.EfsFileSystemId={Description:"EFS file system id",Value:d.ref("EfsFileSystem")};if(t.cache?.driver==="elasticache")S.CacheSubnetGroup={Type:"AWS::ElastiCache::SubnetGroup",Properties:{Description:`${n}-${a} cache subnets`,SubnetIds:j}},S.CacheCluster={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:`${n}-${a}-cache`,ReplicationGroupDescription:`${n}-${a} redis`,Engine:"redis",CacheNodeType:"cache.t4g.micro",NumCacheClusters:1,AutomaticFailoverEnabled:!1,CacheSubnetGroupName:d.ref("CacheSubnetGroup"),SecurityGroupIds:[d.getAtt("DataSecurityGroup","GroupId")],TransitEncryptionEnabled:!1}},E.CacheEndpoint={Description:"Redis primary endpoint",Value:d.getAtt("CacheCluster","PrimaryEndPoint.Address")};if(t.database?.connection==="aurora-serverless")S.DbSubnetGroup={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupDescription:`${n}-${a} db subnets`,SubnetIds:j}},S.DbSecret={Type:"AWS::SecretsManager::Secret",Properties:{Name:`${n}/${a}/db`,GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"app"}),GenerateStringKey:"password",PasswordLength:32,ExcludePunctuation:!0}}},S.DbCluster={Type:"AWS::RDS::DBCluster",Properties:{Engine:"aurora-mysql",EngineMode:"provisioned",DBClusterIdentifier:`${n}-${a}-db`,DatabaseName:"app",MasterUsername:d.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:username}}"),MasterUserPassword:d.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:password}}"),ServerlessV2ScalingConfiguration:{MinCapacity:t.database?.minCapacity??0.5,MaxCapacity:t.database?.maxCapacity??4},DBSubnetGroupName:d.ref("DbSubnetGroup"),VpcSecurityGroupIds:[d.getAtt("DataSecurityGroup","GroupId")]}},S.DbInstance={Type:"AWS::RDS::DBInstance",Properties:{Engine:"aurora-mysql",DBInstanceClass:"db.serverless",DBClusterIdentifier:d.ref("DbCluster")}},E.DbEndpoint={Description:"Aurora cluster endpoint",Value:d.getAtt("DbCluster","Endpoint.Address")};if(t.rdsProxy&&t.database?.connection==="aurora-serverless")S.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:d.ref("DbSecret")}]}}]}},S.DbProxy={Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:typeof t.rdsProxy==="object"&&t.rdsProxy.name?t.rdsProxy.name:`${n}-${a}-proxy`,EngineFamily:"MYSQL",RoleArn:d.getAtt("DbProxyRole","Arn"),Auth:[{AuthScheme:"SECRETS",SecretArn:d.ref("DbSecret"),IAMAuth:"DISABLED"}],VpcSubnetIds:j,VpcSecurityGroupIds:[d.getAtt("DataSecurityGroup","GroupId")],RequireTLS:!1}},S.DbProxyTargetGroup={Type:"AWS::RDS::DBProxyTargetGroup",DependsOn:["DbInstance"],Properties:{DBProxyName:d.ref("DbProxy"),TargetGroupName:"default",DBClusterIdentifiers:[d.ref("DbCluster")]}},E.DbProxyEndpoint={Description:"RDS Proxy endpoint",Value:d.getAtt("DbProxy","Endpoint")};if(E.HttpFunctionName={Description:"HTTP function name",Value:d.ref("HttpFunction")},E.CliFunctionName={Description:"CLI function name",Value:d.ref("CliFunction")},m)E.QueueFunctionName={Description:"Queue function name",Value:d.ref("QueueFunction")};let ke={AWSTemplateFormatVersion:"2010-09-09",Description:`Serverless application for ${e.config.project.name} (${n}-${a})`,Parameters:g?{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:S,Outputs:E},Ve={};for(let R of Object.values(S))Ve[R.Type]=(Ve[R.Type]??0)+1;return{template:ke,functionNames:c,queueNames:u,resourceSummary:Ve}}var mc=["cli","fpm","curl","mbstring","xml","pdo","mysqlnd","gd","bcmath","intl","opcache","sodium","process","pecl-redis6","pecl-apcu","pgsql"];function pc(e){let t=`php${e.replace(".","")}`;return mc.map((a)=>`${t}-php-${a}`)}function gn(e,t){let a=`php${e.replace(".","")}`,r=pc(e).join(" \\\n "),n=`/opt/remi/${a}/root`,i=`/etc/opt/remi/${a}`;return`${t?`FROM almalinux:9 AS ${t}`:"FROM almalinux:9"}
7287
7287
 
7288
7288
  # Build PHP on AlmaLinux 9 (where Remi's version-isolated SCL packages install
7289
7289
  # cleanly — Remi's release RPM rejects Amazon Linux 2023). AlmaLinux 9 shares
@@ -7323,9 +7323,9 @@ RUN printf 'extension_dir=/opt/php/lib/php/modules\\n' > /opt/php/etc/php.ini &&
7323
7323
  # Runtime assets (bootstrap, runtime loops, fpm config) are added by the build
7324
7324
  # orchestrator after the image is produced. Export /opt as the layer payload.
7325
7325
  CMD ["true"]
7326
- `}function hc(e={}){let t=e.phpVersion??"8.3";return`# ts-cloud PHP ${t} runtime layer (generated) — AWS Lambda provided.al2023.
7327
- ${hn(t)}`}function yp(e){if(e.kind==="php"){let t=e.phpVersion??"8.3";return`# ts-cloud serverless PHP app image (generated, multi-stage).
7328
- ${hn(t,"phpbuild")}
7326
+ `}function gc(e={}){let t=e.phpVersion??"8.3";return`# ts-cloud PHP ${t} runtime layer (generated) — AWS Lambda provided.al2023.
7327
+ ${gn(t)}`}function hp(e){if(e.kind==="php"){let t=e.phpVersion??"8.3";return`# ts-cloud serverless PHP app image (generated, multi-stage).
7328
+ ${gn(t,"phpbuild")}
7329
7329
 
7330
7330
  FROM public.ecr.aws/lambda/provided:al2023
7331
7331
  # Bake the relocated PHP runtime from the build stage.
@@ -7344,7 +7344,7 @@ COPY app/ \${LAMBDA_TASK_ROOT}/
7344
7344
 
7345
7345
  # Per-function CMD (e.g. index.http) is supplied via ImageConfig.Command.
7346
7346
  CMD [ "index.http" ]
7347
- `}function bn(){return yc(fc(import.meta.url))}function An(){return Dt(ve(bn(),"runtime.mjs"),"utf-8")}function Cn(e){return Dt(ve(bn(),`${e}-bootstrap`),"utf-8")}function Tp(e){let t=e.architecture??"x86_64",a=t==="arm64"?"arm64":"x64",r=e.version.replace(/^v/,""),n=e.onStep??(()=>{}),i=yn(ve(Sn(),"tscloud-node-layer-"));try{let s=r.includes(".")?r:Sc(r),o=`node-v${s}-linux-${a}`,c=`https://nodejs.org/dist/v${s}/${o}.tar.xz`;n(`downloading Node ${s} (${t})`);let l=ve(i,"node.tar.xz");Tn(c,l),n("extracting node binary"),Nt("tar",["-xf",l,"-C",i,`${o}/bin/node`],{stdio:"inherit"});let u=Dt(ve(i,o,"bin","node"));n("packaging layer");let m=[{name:"bootstrap",data:Cn("node"),mode:493},{name:"runtime.mjs",data:An(),mode:420},{name:"bin/node",data:u,mode:493}];return{zip:nt(m),architecture:t,version:s,fileCount:m.length}}finally{fn(i,{recursive:!0,force:!0})}}function vp(e){let t=e.architecture??"x86_64",a=t==="arm64"?"bun-linux-aarch64":"bun-linux-x64",r=e.version==="latest"?"":e.version.replace(/^v/,""),n=e.onStep??(()=>{}),i=yn(ve(Sn(),"tscloud-bun-layer-"));try{let s=r?`https://github.com/oven-sh/bun/releases/download/bun-v${r}/${a}.zip`:`https://github.com/oven-sh/bun/releases/latest/download/${a}.zip`;n(`downloading Bun ${r||"latest"} (${t})`);let o=ve(i,"bun.zip");Tn(s,o),n("extracting bun binary"),Nt("unzip",["-o","-q",o,"-d",i],{stdio:"inherit"});let c=Dt(ve(i,a,"bun"));n("packaging layer");let l=[{name:"bootstrap",data:Cn("bun"),mode:493},{name:"runtime.mjs",data:An(),mode:420},{name:"bin/bun",data:c,mode:493}];return{zip:nt(l),architecture:t,version:r||"latest",fileCount:l.length}}finally{fn(i,{recursive:!0,force:!0})}}function Tn(e,t){Nt("curl",["-fsSL","-o",t,e],{stdio:["ignore","ignore","inherit"]})}function Sc(e){let t=Nt("curl",["-fsSL","https://nodejs.org/dist/index.json"],{encoding:"utf-8"}),a=JSON.parse(t).find((r)=>r.version.startsWith(`v${e}.`));if(!a)throw Error(`No Node release found for major version ${e}`);return a.version.replace(/^v/,"")}var Ia="x-ts-cloud-invoke-depth",Ra="x-ts-cloud-invoke-chain",Na="x-ts-cloud-trace-id";function Cc(e){return Ac("sha256").update(e).digest("hex").slice(0,8)}var ga={maxDepth:10,maxRepeats:3,maxInvocationsPerTrace:100,traceWindowMs:60000,breakerThreshold:5,breakerCooldownMs:60000};function Gt(e,t){if(typeof e.get==="function")return e.get(t)??void 0;let a=e;return a[t]??a[t.toLowerCase()]??a[t.toUpperCase()]}function Tc(e,t=64){if(!e)return[];return e.split(".").map((a)=>a.trim()).filter((a)=>/^[0-9a-f]{8}$/.test(a)).slice(-t)}function vc(e,t=ga){let a=Cc(e.functionId),r=Tc(Gt(e.headers,Ra)),n=e.traceId??Gt(e.headers,Na)??crypto.randomUUID(),i=[...r,a],s=r.filter((m)=>m===a).length,o=r[r.length-1]===a,c=Number.parseInt(Gt(e.headers,Ia)??"",10),l=Math.max(i.length,Number.isFinite(c)?c+1:0),u="ok";if(l>t.maxDepth)u="depth_exceeded";else if(s>=t.maxRepeats)u="cycle_detected";else if(o&&t.maxRepeats<=1)u="self_invocation";return{reason:u,depth:l,chain:i,traceId:n,selfInvocation:o,repeats:s,propagate:{[Ia]:String(l),[Ra]:i.join("."),[Na]:n}}}var vn={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 wn{limits;clock;traces=new Map;breakers=new Map;constructor(e=ga,t=()=>Date.now()){this.limits=e,this.clock=t}check(e){let t=this.clock();this.expireTraces(t);let a=vc(e,this.limits),r=this.breakers.get(e.functionId);if(r?.openUntil!=null&&r.openUntil>t)return this.deny(e.functionId,a,"breaker_open",t,!1);if(a.reason!=="ok")return this.deny(e.functionId,a,a.reason,t,!0);let n=this.traces.get(a.traceId)??{count:0,firstAt:t};if(n.count>=this.limits.maxInvocationsPerTrace)return this.traces.set(a.traceId,n),this.deny(e.functionId,a,"trace_budget_exceeded",t,!0);if(this.traces.set(a.traceId,{count:n.count+1,firstAt:n.firstAt}),r)this.breakers.set(e.functionId,{consecutiveBlocks:0});return{...a,allowed:!0,reason:"ok",propagate:a.propagate}}deny(e,t,a,r,n){if(n){let i=this.breakers.get(e)??{consecutiveBlocks:0},s=i.consecutiveBlocks+1;this.breakers.set(e,{consecutiveBlocks:s,openUntil:s>=this.limits.breakerThreshold?r+this.limits.breakerCooldownMs:i.openUntil})}return{...t,allowed:!1,reason:a,message:vn[a]}}breakerOpen(e){let t=this.breakers.get(e);return t?.openUntil!=null&&t.openUntil>this.clock()}reset(e){if(e){this.breakers.delete(e);return}this.breakers.clear(),this.traces.clear()}expireTraces(e){if(this.traces.size===0)return;for(let[t,a]of this.traces)if(e-a.firstAt>this.limits.traceWindowMs)this.traces.delete(t)}get trackedTraces(){return this.traces.size}}function wc(e){return{...e.propagate}}function Ec(e){return{status:508,headers:{"content-type":"application/json","x-ts-cloud-recursion-blocked":e.reason},body:{error:"recursion_blocked",reason:e.reason,message:e.message??vn[e.reason],depth:e.depth,traceId:e.traceId}}}var En=new bc;function Da(e){let t=globalThis.process?.env?.[e];if(t==null||t==="")return;return t!=="0"&&t.toLowerCase()!=="false"}function Pc(){let e=globalThis.process?.env??{};return e.TS_CLOUD_FUNCTION_ID||e.AWS_LAMBDA_FUNCTION_NAME||e.FUNCTION_NAME||"function"}function Ic(e){let t=e===!1?{enabled:!1}:e??{},a=Da("TS_CLOUD_RECURSION_PROTECTION"),r=Da("TS_CLOUD_RECURSION_DETECTION_ONLY");return{enabled:a??t.enabled??!0,detectionOnly:r??t.detectionOnly??!1,limits:{...ga,...t.limits},functionId:t.functionId??Pc()}}var Ne,he;function Rc(){let e=globalThis.fetch;if(!e||Ne===e)return()=>{};he=e;let t=async(a,r)=>{let n=En.getStore();if(!n)return he(a,r);let i=new Headers(r?.headers??(a instanceof Request?a.headers:void 0));for(let[s,o]of Object.entries(wc(n)))i.set(s,o);if(a instanceof Request)return he(new Request(a,{headers:i}),r);return he(a,{...r,headers:i})};return Object.assign(t,e),globalThis.fetch=t,Ne=t,()=>{if(globalThis.fetch===Ne&&he)globalThis.fetch=he;Ne=void 0}}var yt,Ht;function Nc(e){if(!yt||JSON.stringify(Ht)!==JSON.stringify(e))yt=new wn(e),Ht=e;return yt}function Pp(){if(yt=void 0,Ht=void 0,Ne&&he&&globalThis.fetch===Ne)globalThis.fetch=he;Ne=void 0,he=void 0}function Dc(e,t){let a=Ic(t);if(!a.enabled)return;let r=Nc(a.limits),n={functionId:a.functionId,headers:e},i=r.check(n);return{verdict:i,blocked:!i.allowed&&!a.detectionOnly,observed:!i.allowed&&a.detectionOnly}}function kc(e,t){return Rc(),En.run(e,t)}function Ip(e){let t=e,a=t?.default??t;if(typeof a==="function")return{fetch:a};return{fetch:a?.fetch??t?.fetch,queue:a?.queue??t?.queue,cli:a?.cli??t?.cli}}var $c=/^(?:text\/|application\/(?:json|xml|javascript|graphql|x-www-form-urlencoded|.*\+json|.*\+xml)|image\/svg)/i;function Lc(e){if(!e)return!0;return $c.test(e)}function Mc(e){if(e?.maintenance)return e.maintenance;let t=globalThis.process?.env??{};return{enabled:t.MAINTENANCE_MODE==="1"||t.MAINTENANCE_MODE==="true",bypassSecret:t.MAINTENANCE_BYPASS_SECRET}}function xc(e){let t=e.requestContext?.domainName??"localhost",a=e.rawQueryString?`?${e.rawQueryString}`:"",r=`https://${t}${e.rawPath||"/"}${a}`,n=new Headers;for(let[o,c]of Object.entries(e.headers??{}))if(c!==void 0)n.set(o,c);if(e.cookies?.length)n.set("cookie",e.cookies.join("; "));let i=e.requestContext.http.method,s;if(e.body!==void 0&&i!=="GET"&&i!=="HEAD")s=e.isBase64Encoded?new Uint8Array(Buffer.from(e.body,"base64")):new TextEncoder().encode(e.body);return new Request(r,{method:i,headers:n,body:s})}async function ka(e){let t={},a=[],r=typeof e.headers.getSetCookie==="function"?e.headers.getSetCookie():[];for(let s of r)a.push(s);e.headers.forEach((s,o)=>{if(o.toLowerCase()==="set-cookie")return;t[o]=s});let n=Buffer.from(await e.arrayBuffer()),i=Lc(e.headers.get("content-type"));return{statusCode:e.status,headers:t,...a.length?{cookies:a}:{},body:i?n.toString("utf-8"):n.toString("base64"),isBase64Encoded:!i}}function Oc(e,t){return async(a)=>{if(a.warmer)return{statusCode:200,headers:{"content-type":"text/plain"},body:"warm",isBase64Encoded:!1};if(!e)return{statusCode:501,headers:{"content-type":"text/plain"},body:"No HTTP handler configured",isBase64Encoded:!1};let r=Mc(t);if(r.enabled){let s=a.headers?.["x-maintenance-bypass"]??a.cookies?.find((o)=>o.startsWith("tscloud_bypass="))?.split("=")[1];if(!r.bypassSecret||s!==r.bypassSecret)return{statusCode:503,headers:{"content-type":"text/plain","retry-after":"120"},body:"Service temporarily unavailable (maintenance mode)",isBase64Encoded:!1}}let n=Dc(a.headers??{},t?.recursionProtection);if(n?.blocked){let s=Ec(n.verdict);return{statusCode:s.status,headers:{...s.headers,"retry-after":"60"},body:JSON.stringify(s.body),isBase64Encoded:!1}}let i=xc(a);if(!n){let s=await e(i);return ka(s)}if(n.observed)console.warn(`[ts-cloud] recursion detected (${n.verdict.reason}) at depth ${n.verdict.depth}; detection-only mode let it run`);return kc(n.verdict,async()=>ka(await e(i)))}}function Bc(e){try{return JSON.parse(e)}catch{return e}}function _c(e){return async(t)=>{let a=[];if(t.warmer)return{batchItemFailures:a};if(!e)return{batchItemFailures:a};for(let r of t.Records??[])try{await e(Bc(r.body),r)}catch{a.push({itemIdentifier:r.messageId})}return{batchItemFailures:a}}}function Wc(e){return async(t)=>{if(t.warmer)return{statusCode:0,output:"warm"};if(!e)return{statusCode:501,output:"No CLI handler configured"};return e(t)}}function Rp(e,t){return{http:Oc(e.fetch,t),queue:_c(e.queue),cli:Wc(e.cli)}}function Gc(e={}){let t=e.socketPath??"/tmp/.tscloud-fpm.sock",a=e.maxChildren??1;return`; ts-cloud php-fpm configuration (generated) — AWS Lambda custom runtime.
7347
+ `}function Sn(){return hc(yc(import.meta.url))}function bn(){return Nt(Te(Sn(),"runtime.mjs"),"utf-8")}function An(e){return Nt(Te(Sn(),`${e}-bootstrap`),"utf-8")}function Cp(e){let t=e.architecture??"x86_64",a=t==="arm64"?"arm64":"x64",r=e.version.replace(/^v/,""),n=e.onStep??(()=>{}),i=hn(Te(fn(),"tscloud-node-layer-"));try{let s=r.includes(".")?r:fc(r),o=`node-v${s}-linux-${a}`,c=`https://nodejs.org/dist/v${s}/${o}.tar.xz`;n(`downloading Node ${s} (${t})`);let l=Te(i,"node.tar.xz");Cn(c,l),n("extracting node binary"),Rt("tar",["-xf",l,"-C",i,`${o}/bin/node`],{stdio:"inherit"});let u=Nt(Te(i,o,"bin","node"));n("packaging layer");let m=[{name:"bootstrap",data:An("node"),mode:493},{name:"runtime.mjs",data:bn(),mode:420},{name:"bin/node",data:u,mode:493}];return{zip:rt(m),architecture:t,version:s,fileCount:m.length}}finally{yn(i,{recursive:!0,force:!0})}}function Tp(e){let t=e.architecture??"x86_64",a=t==="arm64"?"bun-linux-aarch64":"bun-linux-x64",r=e.version==="latest"?"":e.version.replace(/^v/,""),n=e.onStep??(()=>{}),i=hn(Te(fn(),"tscloud-bun-layer-"));try{let s=r?`https://github.com/oven-sh/bun/releases/download/bun-v${r}/${a}.zip`:`https://github.com/oven-sh/bun/releases/latest/download/${a}.zip`;n(`downloading Bun ${r||"latest"} (${t})`);let o=Te(i,"bun.zip");Cn(s,o),n("extracting bun binary"),Rt("unzip",["-o","-q",o,"-d",i],{stdio:"inherit"});let c=Nt(Te(i,a,"bun"));n("packaging layer");let l=[{name:"bootstrap",data:An("bun"),mode:493},{name:"runtime.mjs",data:bn(),mode:420},{name:"bin/bun",data:c,mode:493}];return{zip:rt(l),architecture:t,version:r||"latest",fileCount:l.length}}finally{yn(i,{recursive:!0,force:!0})}}function Cn(e,t){Rt("curl",["-fsSL","-o",t,e],{stdio:["ignore","ignore","inherit"]})}function fc(e){let t=Rt("curl",["-fsSL","https://nodejs.org/dist/index.json"],{encoding:"utf-8"}),a=JSON.parse(t).find((r)=>r.version.startsWith(`v${e}.`));if(!a)throw Error(`No Node release found for major version ${e}`);return a.version.replace(/^v/,"")}var Pa="x-ts-cloud-invoke-depth",Ia="x-ts-cloud-invoke-chain",Ra="x-ts-cloud-trace-id";function Ac(e){return bc("sha256").update(e).digest("hex").slice(0,8)}var pa={maxDepth:10,maxRepeats:3,maxInvocationsPerTrace:100,traceWindowMs:60000,breakerThreshold:5,breakerCooldownMs:60000};function Ut(e,t){if(typeof e.get==="function")return e.get(t)??void 0;let a=e;return a[t]??a[t.toLowerCase()]??a[t.toUpperCase()]}function Cc(e,t=64){if(!e)return[];return e.split(".").map((a)=>a.trim()).filter((a)=>/^[0-9a-f]{8}$/.test(a)).slice(-t)}function Tc(e,t=pa){let a=Ac(e.functionId),r=Cc(Ut(e.headers,Ia)),n=e.traceId??Ut(e.headers,Ra)??crypto.randomUUID(),i=[...r,a],s=r.filter((m)=>m===a).length,o=r[r.length-1]===a,c=Number.parseInt(Ut(e.headers,Pa)??"",10),l=Math.max(i.length,Number.isFinite(c)?c+1:0),u="ok";if(l>t.maxDepth)u="depth_exceeded";else if(s>=t.maxRepeats)u="cycle_detected";else if(o&&t.maxRepeats<=1)u="self_invocation";return{reason:u,depth:l,chain:i,traceId:n,selfInvocation:o,repeats:s,propagate:{[Pa]:String(l),[Ia]:i.join("."),[Ra]:n}}}var Tn={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 vn{limits;clock;traces=new Map;breakers=new Map;constructor(e=pa,t=()=>Date.now()){this.limits=e,this.clock=t}check(e){let t=this.clock();this.expireTraces(t);let a=Tc(e,this.limits),r=this.breakers.get(e.functionId);if(r?.openUntil!=null&&r.openUntil>t)return this.deny(e.functionId,a,"breaker_open",t,!1);if(a.reason!=="ok")return this.deny(e.functionId,a,a.reason,t,!0);let n=this.traces.get(a.traceId)??{count:0,firstAt:t};if(n.count>=this.limits.maxInvocationsPerTrace)return this.traces.set(a.traceId,n),this.deny(e.functionId,a,"trace_budget_exceeded",t,!0);if(this.traces.set(a.traceId,{count:n.count+1,firstAt:n.firstAt}),r)this.breakers.set(e.functionId,{consecutiveBlocks:0});return{...a,allowed:!0,reason:"ok",propagate:a.propagate}}deny(e,t,a,r,n){if(n){let i=this.breakers.get(e)??{consecutiveBlocks:0},s=i.consecutiveBlocks+1;this.breakers.set(e,{consecutiveBlocks:s,openUntil:s>=this.limits.breakerThreshold?r+this.limits.breakerCooldownMs:i.openUntil})}return{...t,allowed:!1,reason:a,message:Tn[a]}}breakerOpen(e){let t=this.breakers.get(e);return t?.openUntil!=null&&t.openUntil>this.clock()}reset(e){if(e){this.breakers.delete(e);return}this.breakers.clear(),this.traces.clear()}expireTraces(e){if(this.traces.size===0)return;for(let[t,a]of this.traces)if(e-a.firstAt>this.limits.traceWindowMs)this.traces.delete(t)}get trackedTraces(){return this.traces.size}}function vc(e){return{...e.propagate}}function wc(e){return{status:508,headers:{"content-type":"application/json","x-ts-cloud-recursion-blocked":e.reason},body:{error:"recursion_blocked",reason:e.reason,message:e.message??Tn[e.reason],depth:e.depth,traceId:e.traceId}}}var wn=new Sc;function Na(e){let t=globalThis.process?.env?.[e];if(t==null||t==="")return;return t!=="0"&&t.toLowerCase()!=="false"}function Ec(){let e=globalThis.process?.env??{};return e.TS_CLOUD_FUNCTION_ID||e.AWS_LAMBDA_FUNCTION_NAME||e.FUNCTION_NAME||"function"}function Pc(e){let t=e===!1?{enabled:!1}:e??{},a=Na("TS_CLOUD_RECURSION_PROTECTION"),r=Na("TS_CLOUD_RECURSION_DETECTION_ONLY");return{enabled:a??t.enabled??!0,detectionOnly:r??t.detectionOnly??!1,limits:{...pa,...t.limits},functionId:t.functionId??Ec()}}var Re,ge;function Ic(){let e=globalThis.fetch;if(!e||Re===e)return()=>{};ge=e;let t=async(a,r)=>{let n=wn.getStore();if(!n)return ge(a,r);let i=new Headers(r?.headers??(a instanceof Request?a.headers:void 0));for(let[s,o]of Object.entries(vc(n)))i.set(s,o);if(a instanceof Request)return ge(new Request(a,{headers:i}),r);return ge(a,{...r,headers:i})};return Object.assign(t,e),globalThis.fetch=t,Re=t,()=>{if(globalThis.fetch===Re&&ge)globalThis.fetch=ge;Re=void 0}}var ht,Ht;function Rc(e){if(!ht||JSON.stringify(Ht)!==JSON.stringify(e))ht=new vn(e),Ht=e;return ht}function Ep(){if(ht=void 0,Ht=void 0,Re&&ge&&globalThis.fetch===Re)globalThis.fetch=ge;Re=void 0,ge=void 0}function Nc(e,t){let a=Pc(t);if(!a.enabled)return;let r=Rc(a.limits),n={functionId:a.functionId,headers:e},i=r.check(n);return{verdict:i,blocked:!i.allowed&&!a.detectionOnly,observed:!i.allowed&&a.detectionOnly}}function Dc(e,t){return Ic(),wn.run(e,t)}function Pp(e){let t=e,a=t?.default??t;if(typeof a==="function")return{fetch:a};return{fetch:a?.fetch??t?.fetch,queue:a?.queue??t?.queue,cli:a?.cli??t?.cli}}var kc=/^(?:text\/|application\/(?:json|xml|javascript|graphql|x-www-form-urlencoded|.*\+json|.*\+xml)|image\/svg)/i;function Mc(e){if(!e)return!0;return kc.test(e)}function Lc(e){if(e?.maintenance)return e.maintenance;let t=globalThis.process?.env??{};return{enabled:t.MAINTENANCE_MODE==="1"||t.MAINTENANCE_MODE==="true",bypassSecret:t.MAINTENANCE_BYPASS_SECRET}}function xc(e){let t=e.requestContext?.domainName??"localhost",a=e.rawQueryString?`?${e.rawQueryString}`:"",r=`https://${t}${e.rawPath||"/"}${a}`,n=new Headers;for(let[o,c]of Object.entries(e.headers??{}))if(c!==void 0)n.set(o,c);if(e.cookies?.length)n.set("cookie",e.cookies.join("; "));let i=e.requestContext.http.method,s;if(e.body!==void 0&&i!=="GET"&&i!=="HEAD")s=e.isBase64Encoded?new Uint8Array(Buffer.from(e.body,"base64")):new TextEncoder().encode(e.body);return new Request(r,{method:i,headers:n,body:s})}async function Da(e){let t={},a=[],r=typeof e.headers.getSetCookie==="function"?e.headers.getSetCookie():[];for(let s of r)a.push(s);e.headers.forEach((s,o)=>{if(o.toLowerCase()==="set-cookie")return;t[o]=s});let n=Buffer.from(await e.arrayBuffer()),i=Mc(e.headers.get("content-type"));return{statusCode:e.status,headers:t,...a.length?{cookies:a}:{},body:i?n.toString("utf-8"):n.toString("base64"),isBase64Encoded:!i}}function Oc(e,t){return async(a)=>{if(a.warmer)return{statusCode:200,headers:{"content-type":"text/plain"},body:"warm",isBase64Encoded:!1};if(!e)return{statusCode:501,headers:{"content-type":"text/plain"},body:"No HTTP handler configured",isBase64Encoded:!1};let r=Lc(t);if(r.enabled){let s=a.headers?.["x-maintenance-bypass"]??a.cookies?.find((o)=>o.startsWith("tscloud_bypass="))?.split("=")[1];if(!r.bypassSecret||s!==r.bypassSecret)return{statusCode:503,headers:{"content-type":"text/plain","retry-after":"120"},body:"Service temporarily unavailable (maintenance mode)",isBase64Encoded:!1}}let n=Nc(a.headers??{},t?.recursionProtection);if(n?.blocked){let s=wc(n.verdict);return{statusCode:s.status,headers:{...s.headers,"retry-after":"60"},body:JSON.stringify(s.body),isBase64Encoded:!1}}let i=xc(a);if(!n){let s=await e(i);return Da(s)}if(n.observed)console.warn(`[ts-cloud] recursion detected (${n.verdict.reason}) at depth ${n.verdict.depth}; detection-only mode let it run`);return Dc(n.verdict,async()=>Da(await e(i)))}}function Wc(e){try{return JSON.parse(e)}catch{return e}}function _c(e){return async(t)=>{let a=[];if(t.warmer)return{batchItemFailures:a};if(!e)return{batchItemFailures:a};for(let r of t.Records??[])try{await e(Wc(r.body),r)}catch{a.push({itemIdentifier:r.messageId})}return{batchItemFailures:a}}}function Bc(e){return async(t)=>{if(t.warmer)return{statusCode:0,output:"warm"};if(!e)return{statusCode:501,output:"No CLI handler configured"};return e(t)}}function Ip(e,t){return{http:Oc(e.fetch,t),queue:_c(e.queue),cli:Bc(e.cli)}}function Uc(e={}){let t=e.socketPath??"/tmp/.tscloud-fpm.sock",a=e.maxChildren??1;return`; ts-cloud php-fpm configuration (generated) — AWS Lambda custom runtime.
7348
7348
  [global]
7349
7349
  daemonize = no
7350
7350
  error_log = ${e.errorLog??"/tmp/storage/logs/php-fpm.log"}
@@ -7361,4 +7361,4 @@ decorate_workers_output = no
7361
7361
  php_admin_value[error_log] = /dev/stderr
7362
7362
  php_admin_flag[log_errors] = on
7363
7363
  clear_env = no
7364
- `}function jc(){return Pn(Vc(Uc(import.meta.url)),"runtime-assets")}function $a(){let e=jc(),t=(a)=>Fc(Pn(e,a),"utf-8");return[{path:"bootstrap",contents:t("bootstrap"),mode:493},{path:"tscloud/runtime.php",contents:t("runtime.php"),mode:420},{path:"tscloud/octane-runtime.php",contents:t("octane-runtime.php"),mode:420},{path:"tscloud/cli-runtime.php",contents:t("cli-runtime.php"),mode:420},{path:"tscloud/fastcgi-client.php",contents:t("fastcgi-client.php"),mode:420},{path:"tscloud/php-fpm.conf",contents:Gc(),mode:420}]}function $p(e={}){let t=e.cacheDriver??"dynamodb";return{APP_ENV:"production",LOG_CHANNEL:"stderr",CACHE_STORE:t,CACHE_DRIVER:t,SESSION_DRIVER:t,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 Kc=["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*Rn(e){for(let t of Qc(e)){let a=Me(e,t);if(In(a).isDirectory())yield*Rn(a);else yield a}}function Bp(e={}){let t=e.architecture??"x86_64",a=e.platform??(t==="arm64"?"linux/arm64":"linux/amd64"),r=e.onStep??(()=>{}),n=zc(Me(Xc(),"tscloud-php-layer-")),i="tscloud-php-layer:build";try{Zc(Me(n,"Dockerfile"),hc(e)),r("Building PHP runtime image (docker)"),dt("docker",["build","--platform",a,"-t","tscloud-php-layer:build",n],{stdio:"inherit"}),r("Extracting /opt/php from image");let s=dt("docker",["create","--platform",a,"tscloud-php-layer:build"],{encoding:"utf-8"}).trim(),o=Me(n,"opt");qc(o,{recursive:!0});try{dt("docker",["cp",`${s}:/opt/php`,Me(o,"php")],{stdio:"inherit"})}finally{dt("docker",["rm",s],{stdio:"ignore"})}if(!Hc(Me(o,"php","bin","php")))throw Error("layer build produced no /opt/php/bin/php");let c=[];for(let m of Rn(o)){let p=el(o,m).replace(/\\/g,"/"),g=In(m).mode&73?493:420;c.push({name:p,data:Jc(m),mode:g})}r("Injecting runtime assets");let l=new Set($a().map((m)=>m.path)),u=c.filter((m)=>!l.has(m.name));for(let m of $a())u.push({name:m.path,data:m.contents,mode:m.mode});return r("Packaging layer ZIP"),{zip:nt(u),architecture:t,fileCount:u.length}}finally{Yc(n,{recursive:!0,force:!0})}}var sl=[".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 ol(e,t){return t.some((a)=>e===a||e.startsWith(`${a}/`))}function*kn(e,t,a){for(let r of rl(e)){let n=il(e,r),i=Dn(t,n).replace(/\\/g,"/");if(ol(i,a))continue;if(Nn(n).isDirectory())yield*kn(n,t,a);else yield n}}function cl(e){if(e.skipBuild)return;let t=ha(e.projectRoot??process.cwd()),a=e.app.build??Kc;for(let r of a)e.onStep?.(`build: ${r}`),tl(r,{stdio:"inherit",cwd:t})}function ll(e,t=[]){let a=ha(e),r=[...sl,It(),...t],n=[];for(let i of kn(a,a,r)){let s=Dn(a,i).replace(/\\/g,"/"),o=(Nn(i).mode&73)!==0;n.push({name:s,data:nl(i),mode:o?493:420})}return n}function Vp(e){let t=ha(e.projectRoot??process.cwd());cl(e),e.onStep?.("packaging application tree");let a=ll(t,e.exclude);if(!a.length)throw Error(`No files to package under ${t}`);let r=nt(a),n=e.app.handlers?.http??"public/index.php";return{zip:r,sha256:al("sha256").update(r).digest("hex"),handlers:{http:n,queue:e.app.handlers?.queue??n,cli:e.app.handlers?.cli??n},fileCount:a.length}}class $n{optimizations=new Map;imageConfigs=new Map;ssgConfigs=new Map;prerenderConfigs=new Map;counter=0;createAssetOptimization(e){let t=`asset-opt-${Date.now()}-${this.counter++}`,a={id:t,...e};return this.optimizations.set(t,a),a}createImageOptimization(e){let t=`image-opt-${Date.now()}-${this.counter++}`,a={id:t,...e};return this.imageConfigs.set(t,a),a}createSSGConfig(e){let t=`ssg-${Date.now()}-${this.counter++}`,a={id:t,...e};return this.ssgConfigs.set(t,a),a}createPrerenderConfig(e){let t=`prerender-${Date.now()}-${this.counter++}`,a={id:t,...e};return this.prerenderConfigs.set(t,a),a}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 Up=new $n;class Ln{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(e,t){let a=`lifecycle-${Date.now()}-${this.counter++}`,r={id:a,transitions:e,expiration:t};return this.policies.set(a,r),r}enableVersioning(e=!1){let t=`versioning-${Date.now()}-${this.counter++}`,a={id:t,enabled:!0,mfaDelete:e};return this.versioningConfigs.set(t,a),a}createReplicationRule(e,t,a){let r=`replication-${Date.now()}-${this.counter++}`,n={id:r,sourceRegion:e,destRegion:t,destBucket:a};return this.replicationRules.set(r,n),n}createIntelligentTiering(e,t){let a=`tiering-${Date.now()}-${this.counter++}`,r={id:a,archiveDays:e,deepArchiveDays:t};return this.tieringConfigs.set(a,r),r}enableObjectLock(e){let t=`object-lock-${Date.now()}-${this.counter++}`,a={id:t,bucketName:e.bucketName,mode:e.mode||"COMPLIANCE",retentionDays:e.retentionDays,retentionYears:e.retentionYears,legalHoldEnabled:e.legalHoldEnabled||!1};return this.objectLocks.set(t,a),a}enableTransferAcceleration(e){let t=`transfer-accel-${Date.now()}-${this.counter++}`,a={id:t,bucketName:e,enabled:!0,endpoint:`${e}.s3-accelerate.amazonaws.com`};return this.transferAcceleration.set(t,a),a}createAccessPoint(e){let t=`access-point-${Date.now()}-${this.counter++}`,a={id:t,name:e.name,bucketName:e.bucketName,vpcId:e.vpcId,publicAccessBlock:e.publicAccessBlock!==!1,policy:e.policy};return this.accessPoints.set(t,a),a}createGlacierArchive(e){let t=`glacier-${Date.now()}-${this.counter++}`,a={id:t,bucketName:e.bucketName,archiveType:e.archiveType,transitionDays:e.transitionDays,restoreConfig:e.restoreTier?{tier:e.restoreTier,days:e.restoreDays||7}:void 0};return this.glacierConfigs.set(t,a),a}createInventory(e){let t=`inventory-${Date.now()}-${this.counter++}`,a={id:t,sourceBucket:e.sourceBucket,destinationBucket:e.destinationBucket,schedule:e.schedule||"Daily",format:e.format||"CSV",includedFields:e.includedFields||["Size","LastModifiedDate","StorageClass","ETag"],prefix:e.prefix};return this.inventories.set(t,a),a}createBatchOperation(e){let t=`batch-op-${Date.now()}-${this.counter++}`,a={id:t,operation:e.operation,manifestBucket:e.manifestBucket,manifestKey:e.manifestKey,priority:e.priority||10,status:"pending"};return this.batchOps.set(t,a),a}executeBatchOperation(e){let t=this.batchOps.get(e);if(!t)throw Error(`Batch operation not found: ${e}`);return t.status="in_progress",t.totalObjects=1000,t.processedObjects=0,t}getBatchOperationStatus(e){return this.batchOps.get(e)}createLambdaNotification(e){let t=`event-${Date.now()}-${this.counter++}`,a={id:t,bucketName:e.bucketName,events:e.events,destination:{type:"Lambda",arn:e.lambdaArn},filter:e.prefix||e.suffix?{prefix:e.prefix,suffix:e.suffix}:void 0};return this.eventNotifications.set(t,a),a}createSQSNotification(e){let t=`event-${Date.now()}-${this.counter++}`,a={id:t,bucketName:e.bucketName,events:e.events,destination:{type:"SQS",arn:e.queueArn},filter:e.prefix||e.suffix?{prefix:e.prefix,suffix:e.suffix}:void 0};return this.eventNotifications.set(t,a),a}createSNSNotification(e){let t=`event-${Date.now()}-${this.counter++}`,a={id:t,bucketName:e.bucketName,events:e.events,destination:{type:"SNS",arn:e.topicArn},filter:e.prefix||e.suffix?{prefix:e.prefix,suffix:e.suffix}:void 0};return this.eventNotifications.set(t,a),a}generateObjectLockCF(e){let t={ObjectLockEnabled:"Enabled",ObjectLockConfiguration:{ObjectLockEnabled:"Enabled",Rule:{DefaultRetention:{Mode:e.mode}}}};if(e.retentionDays)t.ObjectLockConfiguration.Rule.DefaultRetention.Days=e.retentionDays;if(e.retentionYears)t.ObjectLockConfiguration.Rule.DefaultRetention.Years=e.retentionYears;return t}generateTransferAccelerationCF(e){return{AccelerateConfiguration:{AccelerationStatus:e.enabled?"Enabled":"Suspended"}}}generateAccessPointCF(e){return{Type:"AWS::S3::AccessPoint",Properties:{Name:e.name,Bucket:e.bucketName,...e.vpcId&&{VpcConfiguration:{VpcId:e.vpcId}},PublicAccessBlockConfiguration:e.publicAccessBlock?{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}:void 0,...e.policy&&{Policy:e.policy}}}}generateInventoryCF(e){return{Type:"AWS::S3::Bucket",Properties:{InventoryConfigurations:[{Id:e.id,Destination:{BucketArn:`arn:aws:s3:::${e.destinationBucket}`,Format:e.format},Enabled:!0,IncludedObjectVersions:"Current",OptionalFields:e.includedFields,ScheduleFrequency:e.schedule,...e.prefix&&{Prefix:e.prefix}}]}}}generateEventNotificationCF(e){let t=e.destination.type==="Lambda"?"LambdaConfigurations":e.destination.type==="SQS"?"QueueConfigurations":"TopicConfigurations",a=e.destination.type==="Lambda"?"Function":e.destination.type==="SQS"?"Queue":"Topic",r={Event:e.events[0],[a]:e.destination.arn};if(e.filter)r.Filter={S3Key:{Rules:[...e.filter.prefix?[{Name:"prefix",Value:e.filter.prefix}]:[],...e.filter.suffix?[{Name:"suffix",Value:e.filter.suffix}]:[]]}};return{NotificationConfiguration:{[t]:[r]}}}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 jp=new Ln;class Mn{checks=new Map;synthetics=new Map;uptimeTrackers=new Map;counter=0;createHealthCheck(e,t=30,a=10){let r=`health-${Date.now()}-${this.counter++}`,n={id:r,url:e,interval:t,timeout:a,status:"healthy"};return this.checks.set(r,n),n}createSyntheticMonitor(e,t,a,r){let n=`synthetic-${Date.now()}-${this.counter++}`,i={id:n,name:e,script:t,frequency:a,locations:r};return this.synthetics.set(n,i),i}trackUptime(e,t,a){let r=`uptime-${Date.now()}-${this.counter++}`,n=t/(t+a)*100,i={id:r,resource:e,uptime:t,downtime:a,availability:n};return this.uptimeTrackers.set(r,i),i}clear(){this.checks.clear(),this.synthetics.clear(),this.uptimeTrackers.clear()}}var Kp=new Mn;class xn{wafRules=new Map;shieldProtections=new Map;securityGroups=new Map;nacls=new Map;counter=0;createWAFRule(e,t,a,r){let n=`waf-${Date.now()}-${this.counter++}`,i={id:n,name:e,priority:t,action:a,conditions:r};return this.wafRules.set(n,i),i}enableShield(e,t="standard"){let a=`shield-${Date.now()}-${this.counter++}`,r={id:a,resourceArn:e,protectionType:t};return this.shieldProtections.set(a,r),r}createSecurityGroup(e,t,a){let r=`sg-${Date.now()}-${this.counter++}`,n={id:r,name:e,vpcId:t,rules:a};return this.securityGroups.set(r,n),n}createNACL(e,t){let a=`nacl-${Date.now()}-${this.counter++}`,r={id:a,vpcId:e,rules:t};return this.nacls.set(a,r),r}clear(){this.wafRules.clear(),this.shieldProtections.clear(),this.securityGroups.clear(),this.nacls.clear()}}var Hp=new xn;class On{strategies=new Map;allocations=new Map;groups=new Map;counter=0;createTaggingStrategy(e,t){let a=`tagging-${Date.now()}-${this.counter++}`,r={id:a,tags:e,resources:t};return this.strategies.set(a,r),r}createCostAllocation(e,t){let a=`cost-${Date.now()}-${this.counter++}`,r={id:a,tagKey:e,allocations:t};return this.allocations.set(a,r),r}createResourceGroup(e,t,a){let r=`group-${Date.now()}-${this.counter++}`,n={id:r,name:e,query:{resourceTypeFilters:t,tagFilters:a}};return this.groups.set(r,n),n}clear(){this.strategies.clear(),this.allocations.clear(),this.groups.clear()}}var qp=new On;export{qt as gh,K as hh,zt as ih,Ma as jh,Kn as kh,_e as lh,Hn as mh,qn as nh,mt as oh,zn as ph,Qn as qh,Jn as rh,Yn as sh,Zn as th,dl as uh,ml as vh,Ua as wh,ei as xh,gl as yh,It as zh,ti as Ah,ai as Bh,hl as Ch,Ka as Dh,yl as Eh,fl as Fh,Sl as Gh,ni as Hh,bl as Ih,Al as Jh,Cl as Kh,Tl as Lh,oi as Mh,vl as Nh,wl as Oh,El as Ph,Pl as Qh,A as Rh,f as Sh,Il as Th,Rl as Uh,Nl as Vh,Dl as Wh,kl as Xh,$l as Yh,Ll as Zh,Ml as _h,xl as $h,Ol as ai,fi as bi,Si as ci,Bl as di,_l as ei,Pe as fi,pe as gi,ne as hi,q as ii,G as ji,k as ki,B as li,ze as mi,_ as ni,Ti as oi,ge as pi,se as qi,Te as ri,Fl as si,Ri as ti,z as ui,xi as vi,pt as wi,Ut as xi,Oi as yi,ie as zi,Bi as Ai,ee as Bi,_i as Ci,Ja as Di,Q as Ei,J as Fi,U as Gi,Qe as Hi,W as Ii,Je as Ji,gt as Ki,Y as Li,d as Mi,Ct as Ni,Kl as Oi,Ya as Pi,Hl as Qi,ql as Ri,zl as Si,Ql as Ti,Jl as Ui,Yl as Vi,Zl as Wi,Xl as Xi,eu as Yi,tu as Zi,au as _i,ru as $i,nu as aj,iu as bj,su as cj,ou as dj,cu as ej,lu as fj,Rs as gj,Ns as hj,$s as ij,Ls as jj,Ms as kj,xs as lj,Os as mj,Bs as nj,er as oj,Aa as pj,_s as qj,Ws as rj,uu as sj,Ca as tj,du as uj,mu as vj,Ge as wj,pu as xj,gu as yj,hu as zj,yu as Aj,fu as Bj,Su as Cj,Gs as Dj,Fs as Ej,Us as Fj,js as Gj,Ks as Hj,Rt as Ij,Tu as Jj,Zt as Kj,Hs as Lj,qs as Mj,zs as Nj,nr as Oj,Z as Pj,vu as Qj,no as Rj,fe as Sj,ht as Tj,Ie as Uj,io as Vj,ir as Wj,so as Xj,oo as Yj,co as Zj,va as _j,te as $j,wu as ak,Eu as bk,Pu as ck,Iu as dk,lo as ek,Ru as fk,H as gk,Nu as hk,Du as ik,ku as jk,or as kk,cr as lk,xu as mk,lr as nk,ur as ok,Wu as pk,Gu as qk,Fu as rk,Vu as sk,Uu as tk,fo as uk,ea as vk,ju as wk,Ku as xk,Hu as yk,qu as zk,zu as Ak,So as Bk,bo as Ck,Qu as Dk,Ju as Ek,Yu as Fk,Zu as Gk,Xu as Hk,ed as Ik,td as Jk,ad as Kk,rd as Lk,mr as Mk,ta as Nk,nd as Ok,id as Pk,sd as Qk,od as Rk,pr as Sk,gr as Tk,hr as Uk,cd as Vk,yr as Wk,ld as Xk,ud as Yk,dd as Zk,md as _k,fr as $k,pd as al,gd as bl,hd as cl,yd as dl,fd as el,Sd as fl,bd as gl,Ad as hl,vo as il,wo as jl,Eo as kl,Po as ll,br as ml,Cd as nl,Td as ol,vd as pl,wd as ql,Ed as rl,Pd as sl,Id as tl,Rd as ul,Nd as vl,No as wl,Do as xl,ko as yl,$o as zl,Dd as Al,kd as Bl,Ar as Cl,$d as Dl,Cr as El,Tr as Fl,vr as Gl,wr as Hl,Ld as Il,Md as Jl,xd as Kl,Od as Ll,oe as Ml,Ze as Nl,Bd as Ol,_d as Pl,Wd as Ql,Gd as Rl,Fd as Sl,Vd as Tl,Ud as Ul,jd as Vl,xo as Wl,Kd as Xl,Hd as Yl,Er as Zl,Pr as _l,qd as $l,zd as am,Oo as bm,Qd as cm,Jd as dm,Yd as em,Zd as fm,Xd as gm,em as hm,tm as im,am as jm,rm as km,nm as lm,im as mm,sm as nm,om,cm as pm,lm as qm,um as rm,dm as sm,mm as tm,pm as um,gm as vm,hm as wm,Ir as xm,ym,Rr as zm,fm as Am,Nr as Bm,Sm as Cm,Dr as Dm,bm as Em,kr as Fm,Am as Gm,xe as Hm,Cm as Im,$r as Jm,Tm as Km,vt as Lm,vm as Mm,Lr as Nm,wm as Om,Mr as Pm,Em as Qm,xr as Rm,Pm as Sm,Or as Tm,Im as Um,Br as Vm,Rm as Wm,Oe as Xm,Nm as Ym,_r as Zm,Dm as _m,Wr as $m,km as an,Gr as bn,$m as cn,Fr as dn,Lm as en,Vr as fn,Mm as gn,Ur as hn,xm as in,jr as jn,Om as kn,Kr as ln,Bm as mn,Hr as nn,_m as on,qr as pn,Wm as qn,zr as rn,Gm as sn,Qr as tn,Fm as un,Jr as vn,Vm as wn,Yr as xn,Um as yn,Zr as zn,jm as An,Xr as Bn,Km as Cn,en as Dn,Hm as En,tn as Fn,qm as Gn,an as Hn,zm as In,rn as Jn,Qm as Kn,nn as Ln,Jm as Mn,sn as Nn,Ym as On,on as Pn,Zm as Qn,cn as Rn,Xm as Sn,ln as Tn,ep as Un,Bo as Vn,_o as Wn,Fo as Xn,Vo as Yn,un as Zn,tp as _n,dn as $n,ap as ao,mn as bo,rp as co,pn as do,np as eo,nt as fo,zo as go,cc as ho,lc as io,mp as jo,pp as ko,uc as lo,mc as mo,gn as no,gp as oo,hp as po,pc as qo,gc as ro,hn as so,hc as to,yp as uo,An as vo,Tp as wo,vp as xo,Ia as yo,Ra as zo,Na as Ao,Cc as Bo,ga as Co,Tc as Do,vc as Eo,wn as Fo,wc as Go,Ec as Ho,En as Io,Ic as Jo,Rc as Ko,Nc as Lo,Pp as Mo,Dc as No,kc as Oo,Ip as Po,xc as Qo,ka as Ro,Oc as So,_c as To,Wc as Uo,Rp as Vo,Gc as Wo,$a as Xo,$p as Yo,Kc as Zo,Bp as _o,sl as $o,cl as ap,ll as bp,Vp as cp,$n as dp,Up as ep,Ln as fp,jp as gp,Mn as hp,Kp as ip,xn as jp,Hp as kp,On as lp,qp as mp};
7364
+ `}function jc(){return En(Vc(Fc(import.meta.url)),"runtime-assets")}function ka(){let e=jc(),t=(a)=>Gc(En(e,a),"utf-8");return[{path:"bootstrap",contents:t("bootstrap"),mode:493},{path:"tscloud/runtime.php",contents:t("runtime.php"),mode:420},{path:"tscloud/octane-runtime.php",contents:t("octane-runtime.php"),mode:420},{path:"tscloud/cli-runtime.php",contents:t("cli-runtime.php"),mode:420},{path:"tscloud/fastcgi-client.php",contents:t("fastcgi-client.php"),mode:420},{path:"tscloud/php-fpm.conf",contents:Uc(),mode:420}]}function kp(e={}){let t=e.cacheDriver??"dynamodb";return{APP_ENV:"production",LOG_CHANNEL:"stderr",CACHE_STORE:t,CACHE_DRIVER:t,SESSION_DRIVER:t,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 Kc=["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*In(e){for(let t of Jc(e)){let a=Le(e,t);if(Pn(a).isDirectory())yield*In(a);else yield a}}function Wp(e={}){let t=e.architecture??"x86_64",a=e.platform??(t==="arm64"?"linux/arm64":"linux/amd64"),r=e.onStep??(()=>{}),n=zc(Le(Xc(),"tscloud-php-layer-")),i="tscloud-php-layer:build";try{Yc(Le(n,"Dockerfile"),gc(e)),r("Building PHP runtime image (docker)"),ut("docker",["build","--platform",a,"-t","tscloud-php-layer:build",n],{stdio:"inherit"}),r("Extracting /opt/php from image");let s=ut("docker",["create","--platform",a,"tscloud-php-layer:build"],{encoding:"utf-8"}).trim(),o=Le(n,"opt");qc(o,{recursive:!0});try{ut("docker",["cp",`${s}:/opt/php`,Le(o,"php")],{stdio:"inherit"})}finally{ut("docker",["rm",s],{stdio:"ignore"})}if(!Hc(Le(o,"php","bin","php")))throw Error("layer build produced no /opt/php/bin/php");let c=[];for(let m of In(o)){let p=Zc(o,m).replace(/\\/g,"/"),g=Pn(m).mode&73?493:420;c.push({name:p,data:Qc(m),mode:g})}r("Injecting runtime assets");let l=new Set(ka().map((m)=>m.path)),u=c.filter((m)=>!l.has(m.name));for(let m of ka())u.push({name:m.path,data:m.contents,mode:m.mode});return r("Packaging layer ZIP"),{zip:rt(u),architecture:t,fileCount:u.length}}finally{$c(n,{recursive:!0,force:!0})}}var il=[".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 sl(e,t){return t.some((a)=>e===a||e.startsWith(`${a}/`))}function*Dn(e,t,a){for(let r of al(e)){let n=nl(e,r),i=Nn(t,n).replace(/\\/g,"/");if(sl(i,a))continue;if(Rn(n).isDirectory())yield*Dn(n,t,a);else yield n}}function ol(e){if(e.skipBuild)return;let t=ga(e.projectRoot??process.cwd()),a=e.app.build??Kc;for(let r of a)e.onStep?.(`build: ${r}`),el(r,{stdio:"inherit",cwd:t})}function cl(e,t=[]){let a=ga(e),r=[...il,Pt(),...t],n=[];for(let i of Dn(a,a,r)){let s=Nn(a,i).replace(/\\/g,"/"),o=(Rn(i).mode&73)!==0;n.push({name:s,data:rl(i),mode:o?493:420})}return n}function Vp(e){let t=ga(e.projectRoot??process.cwd());ol(e),e.onStep?.("packaging application tree");let a=cl(t,e.exclude);if(!a.length)throw Error(`No files to package under ${t}`);let r=rt(a),n=e.app.handlers?.http??"public/index.php";return{zip:r,sha256:tl("sha256").update(r).digest("hex"),handlers:{http:n,queue:e.app.handlers?.queue??n,cli:e.app.handlers?.cli??n},fileCount:a.length}}class kn{optimizations=new Map;imageConfigs=new Map;ssgConfigs=new Map;prerenderConfigs=new Map;counter=0;createAssetOptimization(e){let t=`asset-opt-${Date.now()}-${this.counter++}`,a={id:t,...e};return this.optimizations.set(t,a),a}createImageOptimization(e){let t=`image-opt-${Date.now()}-${this.counter++}`,a={id:t,...e};return this.imageConfigs.set(t,a),a}createSSGConfig(e){let t=`ssg-${Date.now()}-${this.counter++}`,a={id:t,...e};return this.ssgConfigs.set(t,a),a}createPrerenderConfig(e){let t=`prerender-${Date.now()}-${this.counter++}`,a={id:t,...e};return this.prerenderConfigs.set(t,a),a}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 Fp=new kn;class Mn{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(e,t){let a=`lifecycle-${Date.now()}-${this.counter++}`,r={id:a,transitions:e,expiration:t};return this.policies.set(a,r),r}enableVersioning(e=!1){let t=`versioning-${Date.now()}-${this.counter++}`,a={id:t,enabled:!0,mfaDelete:e};return this.versioningConfigs.set(t,a),a}createReplicationRule(e,t,a){let r=`replication-${Date.now()}-${this.counter++}`,n={id:r,sourceRegion:e,destRegion:t,destBucket:a};return this.replicationRules.set(r,n),n}createIntelligentTiering(e,t){let a=`tiering-${Date.now()}-${this.counter++}`,r={id:a,archiveDays:e,deepArchiveDays:t};return this.tieringConfigs.set(a,r),r}enableObjectLock(e){let t=`object-lock-${Date.now()}-${this.counter++}`,a={id:t,bucketName:e.bucketName,mode:e.mode||"COMPLIANCE",retentionDays:e.retentionDays,retentionYears:e.retentionYears,legalHoldEnabled:e.legalHoldEnabled||!1};return this.objectLocks.set(t,a),a}enableTransferAcceleration(e){let t=`transfer-accel-${Date.now()}-${this.counter++}`,a={id:t,bucketName:e,enabled:!0,endpoint:`${e}.s3-accelerate.amazonaws.com`};return this.transferAcceleration.set(t,a),a}createAccessPoint(e){let t=`access-point-${Date.now()}-${this.counter++}`,a={id:t,name:e.name,bucketName:e.bucketName,vpcId:e.vpcId,publicAccessBlock:e.publicAccessBlock!==!1,policy:e.policy};return this.accessPoints.set(t,a),a}createGlacierArchive(e){let t=`glacier-${Date.now()}-${this.counter++}`,a={id:t,bucketName:e.bucketName,archiveType:e.archiveType,transitionDays:e.transitionDays,restoreConfig:e.restoreTier?{tier:e.restoreTier,days:e.restoreDays||7}:void 0};return this.glacierConfigs.set(t,a),a}createInventory(e){let t=`inventory-${Date.now()}-${this.counter++}`,a={id:t,sourceBucket:e.sourceBucket,destinationBucket:e.destinationBucket,schedule:e.schedule||"Daily",format:e.format||"CSV",includedFields:e.includedFields||["Size","LastModifiedDate","StorageClass","ETag"],prefix:e.prefix};return this.inventories.set(t,a),a}createBatchOperation(e){let t=`batch-op-${Date.now()}-${this.counter++}`,a={id:t,operation:e.operation,manifestBucket:e.manifestBucket,manifestKey:e.manifestKey,priority:e.priority||10,status:"pending"};return this.batchOps.set(t,a),a}executeBatchOperation(e){let t=this.batchOps.get(e);if(!t)throw Error(`Batch operation not found: ${e}`);return t.status="in_progress",t.totalObjects=1000,t.processedObjects=0,t}getBatchOperationStatus(e){return this.batchOps.get(e)}createLambdaNotification(e){let t=`event-${Date.now()}-${this.counter++}`,a={id:t,bucketName:e.bucketName,events:e.events,destination:{type:"Lambda",arn:e.lambdaArn},filter:e.prefix||e.suffix?{prefix:e.prefix,suffix:e.suffix}:void 0};return this.eventNotifications.set(t,a),a}createSQSNotification(e){let t=`event-${Date.now()}-${this.counter++}`,a={id:t,bucketName:e.bucketName,events:e.events,destination:{type:"SQS",arn:e.queueArn},filter:e.prefix||e.suffix?{prefix:e.prefix,suffix:e.suffix}:void 0};return this.eventNotifications.set(t,a),a}createSNSNotification(e){let t=`event-${Date.now()}-${this.counter++}`,a={id:t,bucketName:e.bucketName,events:e.events,destination:{type:"SNS",arn:e.topicArn},filter:e.prefix||e.suffix?{prefix:e.prefix,suffix:e.suffix}:void 0};return this.eventNotifications.set(t,a),a}generateObjectLockCF(e){let t={ObjectLockEnabled:"Enabled",ObjectLockConfiguration:{ObjectLockEnabled:"Enabled",Rule:{DefaultRetention:{Mode:e.mode}}}};if(e.retentionDays)t.ObjectLockConfiguration.Rule.DefaultRetention.Days=e.retentionDays;if(e.retentionYears)t.ObjectLockConfiguration.Rule.DefaultRetention.Years=e.retentionYears;return t}generateTransferAccelerationCF(e){return{AccelerateConfiguration:{AccelerationStatus:e.enabled?"Enabled":"Suspended"}}}generateAccessPointCF(e){return{Type:"AWS::S3::AccessPoint",Properties:{Name:e.name,Bucket:e.bucketName,...e.vpcId&&{VpcConfiguration:{VpcId:e.vpcId}},PublicAccessBlockConfiguration:e.publicAccessBlock?{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}:void 0,...e.policy&&{Policy:e.policy}}}}generateInventoryCF(e){return{Type:"AWS::S3::Bucket",Properties:{InventoryConfigurations:[{Id:e.id,Destination:{BucketArn:`arn:aws:s3:::${e.destinationBucket}`,Format:e.format},Enabled:!0,IncludedObjectVersions:"Current",OptionalFields:e.includedFields,ScheduleFrequency:e.schedule,...e.prefix&&{Prefix:e.prefix}}]}}}generateEventNotificationCF(e){let t=e.destination.type==="Lambda"?"LambdaConfigurations":e.destination.type==="SQS"?"QueueConfigurations":"TopicConfigurations",a=e.destination.type==="Lambda"?"Function":e.destination.type==="SQS"?"Queue":"Topic",r={Event:e.events[0],[a]:e.destination.arn};if(e.filter)r.Filter={S3Key:{Rules:[...e.filter.prefix?[{Name:"prefix",Value:e.filter.prefix}]:[],...e.filter.suffix?[{Name:"suffix",Value:e.filter.suffix}]:[]]}};return{NotificationConfiguration:{[t]:[r]}}}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 jp=new Mn;class Ln{checks=new Map;synthetics=new Map;uptimeTrackers=new Map;counter=0;createHealthCheck(e,t=30,a=10){let r=`health-${Date.now()}-${this.counter++}`,n={id:r,url:e,interval:t,timeout:a,status:"healthy"};return this.checks.set(r,n),n}createSyntheticMonitor(e,t,a,r){let n=`synthetic-${Date.now()}-${this.counter++}`,i={id:n,name:e,script:t,frequency:a,locations:r};return this.synthetics.set(n,i),i}trackUptime(e,t,a){let r=`uptime-${Date.now()}-${this.counter++}`,n=t/(t+a)*100,i={id:r,resource:e,uptime:t,downtime:a,availability:n};return this.uptimeTrackers.set(r,i),i}clear(){this.checks.clear(),this.synthetics.clear(),this.uptimeTrackers.clear()}}var Kp=new Ln;class xn{wafRules=new Map;shieldProtections=new Map;securityGroups=new Map;nacls=new Map;counter=0;createWAFRule(e,t,a,r){let n=`waf-${Date.now()}-${this.counter++}`,i={id:n,name:e,priority:t,action:a,conditions:r};return this.wafRules.set(n,i),i}enableShield(e,t="standard"){let a=`shield-${Date.now()}-${this.counter++}`,r={id:a,resourceArn:e,protectionType:t};return this.shieldProtections.set(a,r),r}createSecurityGroup(e,t,a){let r=`sg-${Date.now()}-${this.counter++}`,n={id:r,name:e,vpcId:t,rules:a};return this.securityGroups.set(r,n),n}createNACL(e,t){let a=`nacl-${Date.now()}-${this.counter++}`,r={id:a,vpcId:e,rules:t};return this.nacls.set(a,r),r}clear(){this.wafRules.clear(),this.shieldProtections.clear(),this.securityGroups.clear(),this.nacls.clear()}}var Hp=new xn;class On{strategies=new Map;allocations=new Map;groups=new Map;counter=0;createTaggingStrategy(e,t){let a=`tagging-${Date.now()}-${this.counter++}`,r={id:a,tags:e,resources:t};return this.strategies.set(a,r),r}createCostAllocation(e,t){let a=`cost-${Date.now()}-${this.counter++}`,r={id:a,tagKey:e,allocations:t};return this.allocations.set(a,r),r}createResourceGroup(e,t,a){let r=`group-${Date.now()}-${this.counter++}`,n={id:r,name:e,query:{resourceTypeFilters:t,tagFilters:a}};return this.groups.set(r,n),n}clear(){this.strategies.clear(),this.allocations.clear(),this.groups.clear()}}var qp=new On;export{qt as gh,K as hh,zt as ih,La as jh,Kn as kh,_e as lh,Hn as mh,qn as nh,dt as oh,zn as ph,Jn as qh,Qn as rh,$n as sh,Yn as th,ul as uh,dl as vh,Fa as wh,Zn as xh,pl as yh,Pt as zh,ei as Ah,ti as Bh,gl as Ch,Ka as Dh,hl as Eh,yl as Fh,fl as Gh,ri as Hh,Sl as Ih,bl as Jh,Al as Kh,Cl as Lh,si as Mh,Tl as Nh,vl as Oh,wl as Ph,El as Qh,A as Rh,f as Sh,Pl as Th,Il as Uh,Rl as Vh,Nl as Wh,Dl as Xh,kl as Yh,Ml as Zh,Ll as _h,xl as $h,Ol as ai,yi as bi,fi as ci,Wl as di,_l as ei,Ee as fi,me as gi,re as hi,q as ii,U as ji,k as ki,W as li,ze as mi,_ as ni,Ci as oi,pe as pi,ie as qi,Ce as ri,Gl as si,Ii as ti,z as ui,xi as vi,mt as wi,Ft as xi,Oi as yi,ne as zi,Wi as Ai,Z as Bi,_i as Ci,Qa as Di,J as Ei,Q as Fi,F as Gi,Je as Hi,B as Ii,Qe as Ji,pt as Ki,$ as Li,d as Mi,At as Ni,Kl as Oi,$a as Pi,Hl as Qi,ql as Ri,zl as Si,Jl as Ti,Ql as Ui,$l as Vi,Yl as Wi,Xl as Xi,Zl as Yi,eu as Zi,tu as _i,au as $i,ru as aj,nu as bj,iu as cj,su as dj,ou as ej,cu as fj,Is as gj,Rs as hj,ks as ij,Ms as jj,Ls as kj,xs as lj,Os as mj,Ws as nj,Za as oj,ba as pj,_s as qj,Bs as rj,lu as sj,Aa as tj,uu as uj,du as vj,Ue as wj,mu as xj,pu as yj,gu as zj,hu as Aj,yu as Bj,fu as Cj,Us as Dj,Gs as Ej,Fs as Fj,js as Gj,Ks as Hj,It as Ij,Cu as Jj,Yt as Kj,Hs as Lj,qs as Mj,zs as Nj,rr as Oj,Y as Pj,Tu as Qj,ro as Rj,ye as Sj,gt as Tj,Pe as Uj,no as Vj,nr as Wj,io as Xj,so as Yj,oo as Zj,Ta as _j,ee as $j,vu as ak,wu as bk,Eu as ck,Pu as dk,co as ek,Iu as fk,H as gk,Ru as hk,Nu as ik,Du as jk,sr as kk,or as lk,xu as mk,cr as nk,lr as ok,Bu as pk,Uu as qk,Gu as rk,Vu as sk,Fu as tk,yo as uk,Zt as vk,ju as wk,Ku as xk,Hu as yk,qu as zk,zu as Ak,fo as Bk,So as Ck,Ju as Dk,Qu as Ek,$u as Fk,Yu as Gk,Xu as Hk,Zu as Ik,ed as Jk,td as Kk,ad as Lk,dr as Mk,ea as Nk,rd as Ok,nd as Pk,id as Qk,sd as Rk,mr as Sk,pr as Tk,gr as Uk,od as Vk,hr as Wk,cd as Xk,ld as Yk,ud as Zk,dd as _k,yr as $k,md as al,pd as bl,gd as cl,hd as dl,yd as el,fd as fl,Sd as gl,bd as hl,To as il,vo as jl,wo as kl,Eo as ll,Sr as ml,Ad as nl,Cd as ol,Td as pl,vd as ql,wd as rl,Ed as sl,Pd as tl,Id as ul,Rd as vl,Ro as wl,No as xl,Do as yl,ko as zl,Nd as Al,Dd as Bl,br as Cl,kd as Dl,Ar as El,Cr as Fl,Tr as Gl,vr as Hl,Md as Il,Ld as Jl,xd as Kl,Od as Ll,se as Ml,Ye as Nl,Wd as Ol,_d as Pl,Bd as Ql,Ud as Rl,Gd as Sl,Vd as Tl,Fd as Ul,jd as Vl,xo as Wl,Kd as Xl,Hd as Yl,wr as Zl,Er as _l,qd as $l,zd as am,Oo as bm,Jd as cm,Qd as dm,$d as em,Yd as fm,Xd as gm,Zd as hm,em as im,tm as jm,am as km,rm as lm,nm as mm,im as nm,sm as om,om as pm,cm as qm,lm as rm,um as sm,dm as tm,mm as um,pm as vm,gm as wm,Pr as xm,hm as ym,Ir as zm,ym as Am,Rr as Bm,fm as Cm,Nr as Dm,Sm as Em,Dr as Fm,bm as Gm,xe as Hm,Am as Im,kr as Jm,Cm as Km,Tt as Lm,Tm as Mm,Mr as Nm,vm as Om,Lr as Pm,wm as Qm,xr as Rm,Em as Sm,Or as Tm,Pm as Um,Wr as Vm,Im as Wm,Oe as Xm,Rm as Ym,_r as Zm,Nm as _m,Br as $m,Dm as an,Ur as bn,km as cn,Gr as dn,Mm as en,Vr as fn,Lm as gn,Fr as hn,xm as in,jr as jn,Om as kn,Kr as ln,Wm as mn,Hr as nn,_m as on,qr as pn,Bm as qn,zr as rn,Um as sn,Jr as tn,Gm as un,Qr as vn,Vm as wn,$r as xn,Fm as yn,Yr as zn,jm as An,Xr as Bn,Km as Cn,Zr as Dn,Hm as En,en as Fn,qm as Gn,tn as Hn,zm as In,an as Jn,Jm as Kn,rn as Ln,Qm as Mn,nn as Nn,$m as On,sn as Pn,Ym as Qn,on as Rn,Xm as Sn,cn as Tn,Zm as Un,Wo as Vn,_o as Wn,Go as Xn,Vo as Yn,ln as Zn,ep as _n,un as $n,tp as ao,dn as bo,ap as co,mn as do,rp as eo,rt as fo,zo as go,oc as ho,cc as io,dp as jo,mp as ko,lc as lo,dc as mo,pn as no,pp as oo,gp as po,mc as qo,pc as ro,gn as so,gc as to,hp as uo,bn as vo,Cp as wo,Tp as xo,Pa as yo,Ia as zo,Ra as Ao,Ac as Bo,pa as Co,Cc as Do,Tc as Eo,vn as Fo,vc as Go,wc as Ho,wn as Io,Pc as Jo,Ic as Ko,Rc as Lo,Ep as Mo,Nc as No,Dc as Oo,Pp as Po,xc as Qo,Da as Ro,Oc as So,_c as To,Bc as Uo,Ip as Vo,Uc as Wo,ka as Xo,kp as Yo,Kc as Zo,Wp as _o,il as $o,ol as ap,cl as bp,Vp as cp,kn as dp,Fp as ep,Mn as fp,jp as gp,Ln as hp,Kp as ip,xn as jp,Hp as kp,On as lp,qp as mp};