@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
package/dist/index.js CHANGED
@@ -1,17 +1,17 @@
1
- import{$ as Gg,$a as LC,$b as LS,$c as rA,A as xf,Aa as cC,Ab as cS,B as Lf,Ba as lC,Bb as lS,Bc as Ri,C as Mf,Ca as dC,Cb as dS,Cc as Ti,D as Ff,Da as uC,Db as uS,Dc as $i,E as bg,Ea as pC,Eb as pS,Ec as Pi,F as Rg,Fa as mC,Fb as mS,Fc as Ii,G as Tg,Ga as fC,Gb as fS,Gc as Di,H as $g,Ha as gC,Hb as gS,Hc as Ei,I as Pg,Ia as hC,Ib as hS,J as Ig,Ja as yC,Jb as yS,K as Dg,Ka as CC,Kb as CS,L as Eg,La as SC,Lb as SS,M as wg,Ma as AC,Mb as AS,N as vg,Na as bC,Nb as bS,O as Og,Oa as RC,Ob as RS,P as Ng,Pa as TC,Pb as TS,Pc as GS,Q as kg,Qa as $C,Qb as $S,Qc as US,R as xg,Ra as PC,Rb as PS,Rc as KS,S as Lg,Sa as IC,Sb as IS,Sc as qS,T as Mg,Ta as DC,Tb as DS,Tc as ZS,U as Fg,Ua as EC,Ub as ES,Uc as jS,V as Vg,Va as wC,Vb as wS,Vc as JS,W as _g,Wa as vC,Wb as vS,Wc as YS,X as Bg,Xa as OC,Xb as OS,Xc as QS,Y as Wg,Ya as NC,Yb as NS,Yc as XS,Z as Hg,Za as kC,Zb as kS,Zc as eA,_ as zg,_a as xC,_b as xS,_c as tA,a as Um,aa as Ug,ab as MC,ac as MS,ad as nA,b as Km,ba as Kg,bb as FC,bc as FS,bd as iA,c as qm,ca as Vy,cb as VC,cc as VS,cd as oA,d as Zm,da as _y,db as _C,dc as _S,dd as aA,e as jm,ea as By,eb as BC,ec as BS,ed as sA,f as Jm,fa as Wy,fb as WC,fc as WS,fd as cA,g as Ym,ga as Hy,gb as HC,gc as HS,gd as lA,h as Qm,ha as zy,hb as zC,hc as zS,hd as dA,i as Xm,ia as Gy,ib as GC,id as uA,j as ef,ja as Uy,jb as UC,jd as pA,k as tf,ka as Ky,kb as KC,kd as mA,l as rf,la as qy,lb as qC,ld as fA,m as nf,ma as Zy,mb as ZC,md as gA,n as of,na as jy,nb as jC,nd as hA,o as af,oa as Jy,ob as JC,od as wi,p as sf,pa as Yy,pb as YC,pc as Ai,pd as vi,q as cf,qa as Qy,qb as QC,qd as Oi,r as lf,ra as Xy,rb as XC,rd as Ni,s as df,sa as eC,sb as eS,t as uf,ta as tC,tb as tS,u as pf,ua as rC,ub as rS,v as mf,va as nC,vb as nS,w as ff,wa as iC,wb as iS,x as gf,xa as oC,xb as oS,y as Nf,ya as aC,yb as aS,z as kf,za as sC,zb as sS}from"./chunk-ywjkyg8p.js";import{Ad as Si,sd as ui,td as pi,ud as mi,vd as fi,wd as gi,xd as hi,yd as yi,zd as Ci}from"./chunk-zam6ecam.js";import{Id as bi}from"./chunk-dr4pj8hp.js";import{$d as wr,Be as Vr,Fe as _r,Jd as Bt,Ld as Wt,Le as Br,Md as Ht,Nd as zt,Od as Gt,Oe as Wr,Pd as Ut,Pe as Hr,Qd as Kt,Qe as zr,Re as Gr,Sd as Zt,Td as Sr,Ud as br,Vd as Rr,Wd as Tr,We as Ur,Xd as $r,Yd as Pr,Zd as Ir,_d as Dr,ae as vr,be as Or,ce as Nr,de as kr,ef as Kr,if as qr,ke as xr,nf as Zr,pe as Lr,te as Mr,xe as Fr}from"./chunk-q0rc1ax9.js";import{of as Rt,pf as $t,qf as Pt}from"./chunk-kasdm9tx.js";import{sf as Me}from"./chunk-by2bwzk6.js";import{tf as Cr}from"./chunk-73ztr55z.js";import{uf as Er}from"./chunk-xcj8zfmg.js";import{Af as er,Bf as tr,Cf as rr,Df as nr,Ef as ir,Ff as or,Gf as ar,Hf as sr,If as cr,Jf as lr,Kf as dr,Lf as ur,Mf as pr,Nf as J,Of as mr,Pf as fr,Qf as gr,Rf as hr,Sf as yr,vf as jt,wf as Jt,xf as Yt,yf as Qt,zf as Xt}from"./chunk-tz9myq9a.js";import{Tf as j}from"./chunk-y4xkj2f1.js";import{$f as tn,$g as Nn,Ah as _n,Bh as Bn,Fh as Wn,Gh as Hn,Hg as Cn,Hh as zn,Ig as Sn,Ih as Gn,Jh as Un,Kg as An,Kh as Kn,Lg as bn,Lh as qn,Mg as Rn,Ng as Tn,Nh as Zn,Og as $n,Oh as jn,Ph as Jn,Qh as Yn,Rg as Pn,Sg as In,Tg as Dn,Uf as jr,Vf as Jr,Wf as Yr,Xf as Qr,Xg as En,Yf as ue,Yg as wn,Zf as Xr,Zg as vn,_f as en,_g as On,ag as rn,ah as kn,bg as nn,ig as Ee,lg as on,mg as an,ng as sn,og as cn,oh as xn,ph as Ln,qg as ln,qh as Mn,rg as dn,rh as Fn,vg as un,wg as pe,zh as Vn}from"./chunk-aw0spg20.js";import{Vh as qt,Wh as Ar}from"./chunk-aj025v2s.js";import{Xh as Le}from"./chunk-wavjkdb8.js";import{Zh as Tt}from"./chunk-nk7sav4r.js";import{$h as bt}from"./chunk-mz0dk78z.js";import{$i as Sg,$j as Uh,Ai as Kf,Aj as Ch,Ak as my,Bi as qf,Bj as Sh,Bk as fy,Ci as Zf,Cj as Ah,Ck as gy,Di as jf,Dj as bh,Dk as hy,Ei as Jf,Ej as Rh,Ek as yy,Fi as Yf,Fj as Th,Fk as Cy,Gi as Qf,Gj as $h,Gk as Sy,Hi as Xf,Hj as Ph,Hk as Ay,Ii as eg,Ij as Ih,Ik as Ot,Ji as tg,Jj as Dh,Jk as by,Ki as rg,Kj as Eh,Kk as Ry,Li as ng,Lj as wh,Lk as Ty,Mi as ig,Mj as vh,Mk as $y,Ni as og,Nj as Oh,Nk as Py,Oi as ag,Oj as Nh,Ok as Iy,Pi as sg,Pj as kh,Pk as Dy,Qi as cg,Qj as xh,Qk as Ey,Ri as lg,Rj as Lh,Rk as wy,Si as dg,Sj as Mh,Sk as vy,Ti as ug,Tj as Fh,Tk as Oy,Ui as pg,Uj as Vh,Uk as Ny,Vi as mg,Vj as _h,Vk as ky,Wi as fg,Wj as Bh,Wk as xy,Xi as gg,Xj as Wh,Xk as Ly,Yi as hg,Yj as Hh,Yk as My,Zi as yg,Zj as zh,Zk as Fy,_i as Cg,_j as Gh,aj as Ag,ak as Kh,bj as qg,bk as qh,ci as hf,cj as Zg,ck as Zh,di as yf,dj as jg,dk as jh,ei as Cf,ej as Jg,ek as Jh,fi as Sf,fj as Yg,fk as Yh,gi as Af,gj as Qg,gk as Qh,hi as bf,hj as Xg,hk as Xh,ii as Rf,ij as eh,ik as ey,ji as Tf,jj as th,jk as ty,ki as $f,kj as rh,kk as ry,li as Pf,lj as nh,lk as ny,mi as If,mj as ih,mk as iy,ni as Df,nj as oh,nk as oy,oi as Ef,oj as ah,ok as ay,pi as wf,pj as sh,pk as sy,qi as vf,qj as ch,qk as It,ri as Of,rj as lh,rk as Dt,si as Vf,sj as dh,sk as Et,ti as _f,tj as uh,tk as wt,ui as Bf,uj as ph,uk as vt,vi as Wf,vj as mh,vk as cy,wi as Hf,wj as fh,wk as ly,xi as zf,xj as gh,xk as dy,yi as Gf,yj as hh,yk as uy,zi as Uf,zj as yh,zk as py}from"./chunk-aw0cgv5w.js";import{$k as Xn,_k as Qn,al as ei,bl as ti,cl as ri,dl as ni,el as ii,gl as oi,hl as ai,il as si,jl as ci,kl as li,ll as di}from"./chunk-1qdne0bf.js";import{nl as pn,ol as mn,pl as fn,ql as gn,rl as hn,sl as yn}from"./chunk-hn40z11p.js";import{Al as _t,tl as Nt,ul as kt,vl as xt,wl as Lt,xl as Mt,yl as Ft,zl as Vt}from"./chunk-x3hay61c.js";import{$l as Ua,$m as De,$n as Ic,$o as Il,$p as Id,$q as Iu,$r as Ip,$s as hm,Am as fs,An as Xs,Ao as Xc,Ap as Xl,Aq as Xd,Ar as Xu,As as Xp,At as zm,Bl as Sa,Bm as te,Bn as ec,Bo as el,Bp as ed,Bq as eu,Br as ep,Bs as em,Bt as Gm,Cl as Aa,Cm as w,Cn as tc,Co as tl,Cp as td,Cq as tu,Cr as tp,Cs as tm,Dl as ba,Dm as Re,Dn as rc,Do as rl,Dp as rd,Dq as ru,Dr as rp,Ds as rm,El as Ra,Em as K,En as nc,Eo as nl,Ep as nd,Eq as nu,Er as np,Es as nm,Fl as Ta,Fm as L,Fn as ic,Fo as il,Fp as id,Fq as iu,Fr as ip,Fs as im,Gl as $a,Gm as gs,Gn as oc,Go as ol,Gp as od,Gq as ou,Gr as op,Gs as om,Hl as Pa,Hm as hs,Hn as ac,Ho as al,Hp as ad,Hq as au,Hr as ap,Hs as am,Il as Ia,Im as re,In as sc,Io as sl,Ip as sd,Iq as su,Ir as sp,Is as sm,Jl as Da,Jm as ys,Jn as cc,Jo as cl,Jp as cd,Jq as cu,Jr as cp,Js as cm,Kl as Ea,Km as Cs,Kn as lc,Ko as ll,Kp as ld,Kq as lu,Kr as lp,Ks as lm,Ll as wa,Lm as Ss,Ln as dc,Lo as dl,Lp as dd,Lq as du,Lr as dp,Ls as dm,Ml as va,Mm as As,Mn as uc,Mo as ul,Mp as ud,Mq as uu,Mr as up,Ms as um,Nl as Oa,Nm as Te,Nn as pc,No as pl,Np as pd,Nq as pu,Nr as pp,Ns as ut,Ol as Na,Om as M,On as mc,Oo as ml,Op as md,Oq as mu,Or as mp,Os as pt,Pl as ka,Pm as q,Pn as fc,Po as fl,Pp as fd,Pq as fu,Pr as fp,Ps as mt,Ql as xa,Qm as ne,Qn as gc,Qo as gl,Qp as gd,Qq as gu,Qr as gp,Qs as ft,Rl as La,Rm as $e,Rn as hc,Ro as hl,Rp as hd,Rq as hu,Rr as hp,Rs as gt,Sl as Ma,Sm as Pe,Sn as yc,So as yl,Sp as yd,Sq as yu,Sr as yp,Ss as ht,Tl as Fa,Tm as bs,Tn as Cc,To as Cl,Tp as Cd,Tq as Cu,Tr as Cp,Ts as yt,Ul as Va,Um as Rs,Un as Sc,Uo as Sl,Up as Sd,Uq as Su,Ur as Sp,Us as Ct,Vl as _a,Vm as Ie,Vn as Ac,Vo as Al,Vp as Ad,Vq as Au,Vr as Ap,Vs as St,Wl as Ba,Wm as Ts,Wn as bc,Wo as bl,Wp as bd,Wq as bu,Wr as bp,Ws as At,Xl as Wa,Xm as $s,Xn as Rc,Xo as Rl,Xp as Rd,Xq as Ru,Xr as Rp,Xs as pm,Yl as Ha,Ym as Ps,Yn as Tc,Yo as Tl,Yp as Td,Yq as Tu,Yr as Tp,Ys as mm,Zl as za,Zm as Is,Zn as $c,Zo as $l,Zp as $d,Zq as $u,Zr as $p,Zs as fm,_l as Ga,_m as Ds,_n as Pc,_o as Pl,_p as Pd,_q as Pu,_r as Pp,_s as gm,am as Ka,an as Z,ao as Dc,ap as Dl,aq as Dd,ar as Du,as as Dp,at as ym,bm as qa,bn as Es,bo as Ec,bp as El,bq as Ed,br as Eu,bs as Ep,bt as Cm,cm as Za,cn as ws,co as wc,cp as wl,cq as wd,cr as wu,cs as wp,ct as Sm,dm as ja,dn as vs,do as vc,dp as vl,dq as vd,dr as vu,ds as vp,dt as Am,em as Ja,en as Os,eo as Oc,ep as Ol,eq as Od,er as Ou,es as Op,et as bm,fm as Se,fn as Ns,fo as Nc,fp as Nl,fq as Nd,fr as Nu,fs as Np,ft as Rm,gm as Ya,gn as ks,go as kc,gp as kl,gq as kd,gr as ku,gs as kp,gt as Tm,hm as Ae,hn as xs,ho as xc,hp as xl,hq as xd,hr as xu,hs as xp,ht as $m,im as be,in as Ls,io as Lc,ip as Ll,iq as Ld,ir as Lu,is as Lp,it as Pm,jm as Qa,jn as Ms,jo as Mc,jp as Ml,jq as Md,jr as Mu,js as Mp,jt as Im,km as Xa,kn as Fs,ko as Fc,kp as Fl,kq as Fd,kr as Fu,ks as Fp,kt as Dm,lm as es,ln as Vs,lo as Vc,lp as Vl,lq as Vd,lr as Vu,ls as Vp,lt as Em,mm as ts,mn as _s,mo as _c,mp as _l,mq as _d,mr as _u,ms as _p,mt as wm,nm as rs,nn as Bs,no as Bc,np as Bl,nq as Bd,nr as Bu,ns as Bp,nt as vm,om as ns,on as Ws,oo as Wc,op as Wl,oq as Wd,or as Wu,os as Wp,ot as Om,pm as is,pn as Hs,po as Hc,pp as Hl,pq as Hd,pr as Hu,ps as Hp,pt as Nm,qm as os,qn as zs,qo as zc,qp as zl,qq as zd,qr as zu,qs as zp,qt as km,rm as as,rn as Gs,ro as Gc,rp as Gl,rq as Gd,rr as Gu,rs as Gp,rt as xm,sm as ss,sn as Us,so as Uc,sp as Ul,sq as Ud,sr as Uu,ss as Up,st as Lm,tm as cs,tn as Ks,to as Kc,tp as Kl,tq as Kd,tr as Ku,ts as Kp,tt as Mm,um as ls,un as qs,uo as qc,up as ql,uq as qd,ur as qu,us as qp,ut as Fm,vm as ds,vn as Zs,vo as Zc,vp as Zl,vq as Zd,vr as Zu,vs as Zp,vt as Vm,wm as us,wn as js,wo as jc,wp as jl,wq as jd,wr as ju,ws as jp,wt as _m,xm as ee,xn as Js,xo as Jc,xp as Jl,xq as Jd,xr as Ju,xs as Jp,xt as Bm,ym as ps,yn as Ys,yo as Yc,yp as Yl,yq as Yd,yr as Yu,ys as Yp,yt as Wm,zm as ms,zn as Qs,zo as Qc,zp as Ql,zq as Qd,zr as Qu,zs as Qp,zt as Hm}from"./chunk-zz52xje8.js";import{Ct as Je}from"./chunk-z2qqwy7e.js";import{createHmac as fe,createSign as _e,timingSafeEqual as Be}from"node:crypto";function B(e){let t=e instanceof Date?e.getTime():e;if(!Number.isFinite(t))throw TypeError("Media access timestamp must be finite");return Math.floor(t/1000)}function ge(e){return Buffer.from(e).toString("base64").replaceAll("+","-").replaceAll("=","_").replaceAll("/","~")}function We(e){return Buffer.from(e).toString("base64url")}function he(e,t=!1){if(!e||/[\r\n]/.test(e))throw TypeError("Media resource is invalid");let r=t?e.replaceAll("*","wildcard"):e,n=new URL(r);if(!["http:","https:"].includes(n.protocol))throw TypeError("Media resource must use HTTP or HTTPS");if(!t&&e.includes("*"))throw TypeError("Canned policies cannot contain wildcards")}function ye(e,t){let r=_e("RSA-SHA1");return r.update(e),r.end(),ge(r.sign(t))}function Ce(e){he(e.resource,!0);let r={DateLessThan:{"AWS:EpochTime":B(e.expiresAt)}};if(e.activeAt!==void 0)r.DateGreaterThan={"AWS:EpochTime":B(e.activeAt)};if(e.ipAddress)r.IpAddress={"AWS:SourceIp":e.ipAddress};return JSON.stringify({Statement:[{Resource:e.resource,Condition:r}]})}function xi(e,t,r){he(e);let n=B(t),o=e.includes("?")?"&":"?",l=Ce({resource:e,expiresAt:t}),c=ye(l,r.privateKey);return`${e}${o}Expires=${n}&Signature=${encodeURIComponent(c)}&Key-Pair-Id=${encodeURIComponent(r.keyPairId)}`}function Li(e,t){let r=Ce(e);return{"CloudFront-Key-Pair-Id":t.keyPairId,"CloudFront-Policy":ge(Buffer.from(r)),"CloudFront-Signature":ye(r,t.privateKey)}}function Mi(e){if(!e.resource||/[\r\n]/.test(e.resource))throw TypeError("Media resource is invalid");let t=We(Buffer.from(JSON.stringify({resource:e.resource,expiresAt:B(e.expiresAt),...e.keyId?{keyId:e.keyId}:{},...e.audience?{audience:e.audience}:{}}))),r=fe("sha256",e.secret).update(t).digest("base64url");return`${t}.${r}`}function Fi(e,t){let[r,n,o]=e.split(".");if(!r||!n||o)return null;let l=fe("sha256",t.secret).update(r).digest(),c;try{c=Buffer.from(n,"base64url")}catch{return null}if(l.length!==c.length||!Be(l,c))return null;try{let s=JSON.parse(Buffer.from(r,"base64url").toString("utf8")),u=B(t.now??Date.now());if(!s.resource||!Number.isSafeInteger(s.expiresAt)||s.expiresAt<=u)return null;if(t.resource&&s.resource!==t.resource)return null;if(t.audience&&s.audience!==t.audience)return null;return s}catch{return null}}function Vi(e,t=!1){let r=new URL(e,"https://media.invalid").pathname.toLowerCase(),n=/\.(?:m3u8|mpd|vtt|json)$/.test(r),o=/\.(?:key|license)$/.test(r)||r.includes("/keys/")||r.includes("/licenses/");return{"Accept-Ranges":"bytes","Cache-Control":t&&(n||o)?"private, no-store":n?"public, max-age=5, s-maxage=30, stale-while-revalidate=30":"public, max-age=31536000, immutable","Cross-Origin-Resource-Policy":"cross-origin","X-Content-Type-Options":"nosniff"}}function _i(e){if(!/^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/.test(e.bucket))throw TypeError("Media bucket is invalid");if(!/^[a-z0-9-]+$/.test(e.region))throw TypeError("Media bucket region is invalid");let t=e.prefix?`/${e.prefix.replace(/^\/+|\/+$/g,"")}`:"",r=e.protected??!1,n="public, max-age=31536000, immutable",o=r?"private, no-store":"public, max-age=5, s-maxage=30, stale-while-revalidate=30";return{originDomain:`${e.bucket}.s3.${e.region}.amazonaws.com`,originPath:t,domain:e.domain,trustedKeyGroupIds:[...new Set(e.trustedKeyGroupIds??[])],behaviors:[{pathPattern:"*.m3u8",cacheControl:o,compress:!0,signed:r},{pathPattern:"*.mpd",cacheControl:o,compress:!0,signed:r},{pathPattern:"*.vtt",cacheControl:o,compress:!0,signed:r},{pathPattern:"*",cacheControl:n,compress:!1,signed:r}],responseHeaders:{"Access-Control-Allow-Headers":"Range, If-Range","Access-Control-Allow-Methods":"GET, HEAD, OPTIONS","Access-Control-Allow-Origin":"*","Access-Control-Expose-Headers":"Accept-Ranges, Content-Length, Content-Range, ETag","X-Content-Type-Options":"nosniff"}}}class He{builder;config;environment;mergedConfig;serverEipLogicalIds=new Map;constructor(e){this.config=e.config,this.environment=e.environment,this.builder=new Se(`${this.config.project.name} - ${this.environment}`),this.mergedConfig=this.mergeEnvironmentConfig()}mergeEnvironmentConfig(){let t=this.config.environments[this.environment]?.infrastructure;if(!t)return this.config;return{...this.config,infrastructure:{...this.config.infrastructure,...t,compute:{...this.config.infrastructure?.compute,...t.compute},storage:{...this.config.infrastructure?.storage,...t.storage},functions:{...this.config.infrastructure?.functions,...t.functions},servers:{...this.config.infrastructure?.servers,...t.servers},databases:{...this.config.infrastructure?.databases,...t.databases},cdn:{...this.config.infrastructure?.cdn,...t.cdn},sftp:t.sftp??this.config.infrastructure?.sftp,queues:{...this.config.infrastructure?.queues,...t.queues},redirects:{...this.config.infrastructure?.redirects,...t.redirects},realtime:{...this.config.infrastructure?.realtime,...t.realtime},cache:{...this.config.infrastructure?.cache,...t.cache},fileSystem:{...this.config.infrastructure?.fileSystem,...t.fileSystem},email:{...this.config.infrastructure?.email,...t.email},search:{...this.config.infrastructure?.search,...t.search},ai:{...this.config.infrastructure?.ai,...t.ai}}}}shouldDeploy(e){if(e.environments&&!e.environments.includes(this.environment))return!1;if(e.requiresFeatures){let t=this.config.features||{};if(!e.requiresFeatures.every((n)=>t[n]===!0))return!1}if(e.regions){let t=this.config.environments[this.environment]?.region||this.config.project.region;if(!e.regions.includes(t))return!1}if(e.condition&&typeof e.condition==="function")return e.condition(this.config,this.environment);return!0}resolveApiOriginPort(){let e=this.mergedConfig.infrastructure?.api?.port??this.mergedConfig.ports?.api,t=Number(e||3008);return Number.isFinite(t)&&t>0?t:3008}defaultComputeCachePathPatterns(){return["/api/*","/auth/*","/publisher/api/*","/publisher/*","/publish","/publish/*","/analytics/*","/packages/*","/npm/*","/zig/*","/php/*","/commits/*","/health","/dashboard/*","/search","/login","/logout","/signup","/account","/account/*"]}shouldRouteStorageBucketToCompute(e,t){return e==="public"||t.routeCompute===!0}storageBucketName(e,t,r){return this.mergedConfig.infrastructure?.storage?.[r]?.bucket??`${e}-${t}-${r}`}fileSystemLogicalId(e,t,r){return be(Ae({slug:`${e}-${r}`,environment:t,resourceType:"efs"}))}resolveSftpStorage(e,t,r){let n=e.storage;if(n?.type==="efs"&&n.fileSystem){if(!this.mergedConfig.infrastructure?.fileSystem?.[n.fileSystem])throw Error(`sftp: storage.fileSystem "${n.fileSystem}" is not defined in infrastructure.fileSystem`);return{type:"efs",fileSystemId:{Ref:this.fileSystemLogicalId(t,r,n.fileSystem)},posixProfile:n.posixProfile}}if(n?.type==="s3"&&n.storageBucket){if(!this.mergedConfig.infrastructure?.storage?.[n.storageBucket])throw Error(`sftp: storage.storageBucket "${n.storageBucket}" is not defined in infrastructure.storage`);return{type:"s3",bucket:this.storageBucketName(t,r,n.storageBucket)}}return}resolveComputeCachePathPatterns(e){if(e&&e.length>0)return e;return this.defaultComputeCachePathPatterns()}createComputeCacheBehavior(e,t){return{PathPattern:e,TargetOriginId:t,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD"],Compress:!0,CachePolicyId:"4135ea2d-6df8-44a3-9df3-4b5a84be39ad",OriginRequestPolicyId:"b689b0a8-53d0-40ab-baf2-68738e2966ac"}}appendComputeAppOrigin(e,t,r,n,o,l){let c=this.serverEipLogicalIds.get("app"),s=this.serverEipLogicalIds.get("appInstance");if(!c)return;let u=`EC2-${n}-${o}-api`,h=this.mergedConfig.infrastructure?.servers?.app?.region||this.mergedConfig.project?.region||"us-east-1",d=h==="us-east-1"?".compute-1.amazonaws.com":`.${h}.compute.amazonaws.com`,b={"Fn::Join":["",["ec2-",{"Fn::Join":["-",{"Fn::Split":[".",{Ref:c}]}]},d]]},A=this.resolveApiOriginPort();if(e.push({Id:u,DomainName:b,CustomOriginConfig:{HTTPPort:A,HTTPSPort:443,OriginProtocolPolicy:"http-only",OriginSSLProtocols:["TLSv1.2"]}}),r.push(c),s)r.push(s);for(let T of l)t.push(this.createComputeCacheBehavior(T,u))}buildCaddyfile(e){let t=e.filter(([,o])=>typeof o.domain==="string"&&o.domain&&typeof o.port==="number");if(t.length===0)return;let r=new Map;for(let[,o]of t){let l=r.get(o.domain)??[];l.push({port:o.port,path:o.path}),r.set(o.domain,l)}let n=[];for(let[o,l]of r){let s=[...l].sort((u,h)=>{let d=!u.path||u.path==="/",b=!h.path||h.path==="/";if(d&&!b)return 1;if(!d&&b)return-1;return(h.path?.length??0)-(u.path?.length??0)}).map((u)=>{let h=!u.path||u.path==="/",d=`reverse_proxy localhost:${u.port}`;return h?` handle {
2
- ${d}
3
- }`:` handle ${u.path} {
4
- ${d}
5
- }`});n.push(`${o} {
6
- ${s.join(`
1
+ import{$ as eQ,$a as lK,$b as lU,$c as G7,A as d_,Aa as RK,Ab as RU,B as l_,Ba as AK,Bb as AU,Bc as DM,C as r_,Ca as zK,Cb as zU,Cc as kM,D as t_,Da as xK,Db as xU,Dc as LM,E as kQ,Ea as qK,Eb as qU,Ec as yM,F as LQ,Fa as NK,Fb as NU,Fc as bM,G as yQ,Ga as PK,Gb as PU,Gc as hM,H as bQ,Ha as SK,Hb as SU,Hc as CM,I as hQ,Ia as BK,Ib as BU,J as CQ,Ja as TK,Jb as TU,K as IQ,Ka as wK,Kb as wU,L as fQ,La as jK,Lb as jU,M as pQ,Ma as DK,Mb as DU,N as mQ,Na as kK,Nb as kU,O as vQ,Oa as LK,Ob as LU,P as cQ,Pa as yK,Pb as yU,Pc as eU,Q as uQ,Qa as bK,Qb as bU,Qc as $7,R as dQ,Ra as hK,Rb as hU,Rc as M7,S as lQ,Sa as CK,Sb as CU,Sc as J7,T as rQ,Ta as IK,Tb as IU,Tc as X7,U as tQ,Ua as fK,Ub as fU,Uc as Y7,V as gQ,Va as pK,Vb as pU,Vc as W7,W as iQ,Wa as mK,Wb as mU,Wc as _7,X as aQ,Xa as vK,Xb as vU,Xc as Q7,Y as oQ,Ya as cK,Yb as cU,Yc as F7,Z as sQ,Za as uK,Zb as uU,Zc as K7,_ as nQ,_a as dK,_b as dU,_c as U7,a as M_,aa as $5,ab as rK,ac as rU,ad as V7,b as J_,ba as M5,bb as tK,bc as tU,bd as O7,c as X_,ca as gF,cb as gK,cc as gU,cd as Z7,d as Y_,da as iF,db as iK,dc as iU,dd as E7,e as W_,ea as aF,eb as aK,ec as aU,ed as H7,f as __,fa as oF,fb as oK,fc as oU,fd as R7,g as Q_,ga as sF,gb as sK,gc as sU,gd as A7,h as F_,ha as nF,hb as nK,hc as nU,hd as z7,i as K_,ia as eF,ib as eK,id as x7,j as U_,ja as $K,jb as $U,jd as q7,k as G_,ka as MK,kb as MU,kd as N7,l as V_,la as JK,lb as JU,ld as P7,m as O_,ma as XK,mb as XU,md as S7,n as Z_,na as YK,nb as YU,nd as B7,o as E_,oa as WK,ob as WU,od as IM,p as H_,pa as _K,pb as _U,pc as wM,pd as fM,q as R_,qa as QK,qb as QU,qd as pM,r as A_,ra as FK,rb as FU,rd as mM,s as z_,sa as KK,sb as KU,t as x_,ta as UK,tb as UU,u as q_,ua as GK,ub as GU,v as N_,va as VK,vb as VU,w as P_,wa as OK,wb as OU,x as S_,xa as ZK,xb as ZU,y as c_,ya as EK,yb as EU,z as u_,za as HK,zb as HU}from"./chunk-2hpjte1d.js";import{Ad as TM,sd as AM,td as zM,ud as xM,vd as qM,wd as NM,xd as PM,yd as SM,zd as BM}from"./chunk-ead1nkbr.js";import{Id as jM}from"./chunk-prf2pkvq.js";import{$d as f6,Be as t6,Fe as g6,Jd as i$,Ld as a$,Le as i6,Md as o$,Nd as s$,Od as n$,Oe as a6,Pd as e$,Pe as o6,Qd as $6,Qe as s6,Re as n6,Sd as J6,Td as w6,Ud as D6,Vd as k6,Wd as L6,We as e6,Xd as y6,Yd as b6,Zd as h6,_d as C6,ae as p6,be as m6,ce as v6,de as c6,ef as $3,if as M3,ke as u6,nf as J3,pe as d6,te as l6,xe as r6}from"./chunk-6fzeemcs.js";import{of as k$,pf as y$,qf as b$}from"./chunk-5m29dhke.js";import{sf as v0}from"./chunk-fea461tj.js";import{tf as T6}from"./chunk-zmmc9j5f.js";import{uf as I6}from"./chunk-j60hesb3.js";import{Af as F6,Bf as K6,Cf as U6,Df as G6,Ef as V6,Ff as O6,Gf as Z6,Hf as E6,If as H6,Jf as R6,Kf as A6,Lf as z6,Mf as x6,Nf as o,Of as q6,Pf as N6,Qf as P6,Rf as S6,Sf as B6,vf as X6,wf as Y6,xf as W6,yf as _6,zf as Q6}from"./chunk-yf487g6e.js";import{Tf as a}from"./chunk-qcemnt35.js";import{$f as K3,$g as m3,Ah as t3,Bh as g3,Fh as i3,Gh as a3,Hg as B3,Hh as o3,Ig as T3,Ih as s3,Jh as n3,Kg as w3,Kh as e3,Lg as j3,Lh as $M,Mg as D3,Ng as k3,Nh as MM,Og as L3,Oh as JM,Ph as XM,Qh as YM,Rg as y3,Sg as b3,Tg as h3,Uf as X3,Vf as Y3,Wf as W3,Xf as _3,Xg as C3,Yf as V0,Yg as I3,Zf as Q3,Zg as f3,_f as F3,_g as p3,ag as U3,ah as v3,bg as G3,ig as D0,lg as V3,mg as O3,ng as Z3,og as E3,oh as c3,ph as u3,qg as H3,qh as d3,rg as R3,rh as l3,vg as A3,wg as O0,zh as r3}from"./chunk-y6e86wjs.js";import{Vh as M6,Wh as j6}from"./chunk-gearw6rk.js";import{Xh as m0}from"./chunk-r2pbqcnz.js";import{Zh as L$}from"./chunk-wte9mh18.js";import{$h as D$}from"./chunk-bpnhqb70.js";import{$i as jQ,$j as $F,Ai as MQ,Aj as w5,Ak as NF,Bi as JQ,Bj as j5,Bk as PF,Ci as XQ,Cj as D5,Ck as SF,Di as YQ,Dj as k5,Dk as BF,Ei as WQ,Ej as L5,Ek as TF,Fi as _Q,Fj as y5,Fk as wF,Gi as QQ,Gj as b5,Gk as jF,Hi as FQ,Hj as h5,Hk as DF,Ii as KQ,Ij as C5,Ik as m$,Ji as UQ,Jj as I5,Jk as kF,Ki as GQ,Kj as f5,Kk as LF,Li as VQ,Lj as p5,Lk as yF,Mi as OQ,Mj as m5,Mk as bF,Ni as ZQ,Nj as v5,Nk as hF,Oi as EQ,Oj as c5,Ok as CF,Pi as HQ,Pj as u5,Pk as IF,Qi as RQ,Qj as d5,Qk as fF,Ri as AQ,Rj as l5,Rk as pF,Si as zQ,Sj as r5,Sk as mF,Ti as xQ,Tj as t5,Tk as vF,Ui as qQ,Uj as g5,Uk as cF,Vi as NQ,Vj as i5,Vk as uF,Wi as PQ,Wj as a5,Wk as dF,Xi as SQ,Xj as o5,Xk as lF,Yi as BQ,Yj as s5,Yk as rF,Zi as TQ,Zj as n5,Zk as tF,_i as wQ,_j as e5,aj as DQ,ak as MF,bj as J5,bk as JF,ci as B_,cj as X5,ck as XF,di as T_,dj as Y5,dk as YF,ei as w_,ej as W5,ek as WF,fi as j_,fj as _5,fk as _F,gi as D_,gj as Q5,gk as QF,hi as k_,hj as F5,hk as FF,ii as L_,ij as K5,ik as KF,ji as y_,jj as U5,jk as UF,ki as b_,kj as G5,kk as GF,li as h_,lj as V5,lk as VF,mi as C_,mj as O5,mk as OF,ni as I_,nj as Z5,nk as ZF,oi as f_,oj as E5,ok as EF,pi as p_,pj as H5,pk as HF,qi as m_,qj as R5,qk as h$,ri as v_,rj as A5,rk as C$,si as g_,sj as z5,sk as I$,ti as i_,tj as x5,tk as f$,ui as a_,uj as q5,uk as p$,vi as o_,vj as N5,vk as RF,wi as s_,wj as P5,wk as AF,xi as n_,xj as S5,xk as zF,yi as e_,yj as B5,yk as xF,zi as $Q,zj as T5,zk as qF}from"./chunk-y1dh3znq.js";import{$k as _M,_k as WM,al as QM,bl as FM,cl as KM,dl as UM,el as GM,gl as VM,hl as OM,il as ZM,jl as EM,kl as HM,ll as RM}from"./chunk-fvjczc73.js";import{nl as z3,ol as x3,pl as q3,ql as N3,rl as P3,sl as S3}from"./chunk-q0wffgw5.js";import{Al as g$,tl as v$,ul as c$,vl as u$,wl as d$,xl as l$,yl as r$,zl as t$}from"./chunk-wcrj06cg.js";import{$l as M1,$m as j0,$n as I9,$o as IJ,$p as IX,$q as IY,$r as I2,$s as TW,Am as S1,An as K9,Ao as KJ,Ap as KX,Aq as KY,Ar as K2,As as KW,At as eW,Bl as D4,Bm as J0,Bn as U9,Bo as UJ,Bp as UX,Bq as UY,Br as U2,Bs as UW,Bt as $_,Cl as k4,Cm as j,Cn as G9,Co as GJ,Cp as GX,Cq as GY,Cr as G2,Cs as GW,Dl as L4,Dm as P0,Dn as V9,Do as VJ,Dp as VX,Dq as VY,Dr as V2,Ds as VW,El as y4,Em as r,En as O9,Eo as OJ,Ep as OX,Eq as OY,Er as O2,Es as OW,Fl as b4,Fm as h,Fn as Z9,Fo as ZJ,Fp as ZX,Fq as ZY,Fr as Z2,Fs as ZW,Gl as h4,Gm as B1,Gn as E9,Go as EJ,Gp as EX,Gq as EY,Gr as E2,Gs as EW,Hl as C4,Hm as T1,Hn as H9,Ho as HJ,Hp as HX,Hq as HY,Hr as H2,Hs as HW,Il as I4,Im as X0,In as R9,Io as RJ,Ip as RX,Iq as RY,Ir as R2,Is as RW,Jl as f4,Jm as w1,Jn as A9,Jo as AJ,Jp as AX,Jq as AY,Jr as A2,Js as AW,Kl as p4,Km as j1,Kn as z9,Ko as zJ,Kp as zX,Kq as zY,Kr as z2,Ks as zW,Ll as m4,Lm as D1,Ln as x9,Lo as xJ,Lp as xX,Lq as xY,Lr as x2,Ls as xW,Ml as v4,Mm as k1,Mn as q9,Mo as qJ,Mp as qX,Mq as qY,Mr as q2,Ms as qW,Nl as c4,Nm as S0,Nn as N9,No as NJ,Np as NX,Nq as NY,Nr as N2,Ns as z$,Ol as u4,Om as C,On as P9,Oo as PJ,Op as PX,Oq as PY,Or as P2,Os as x$,Pl as d4,Pm as t,Pn as S9,Po as SJ,Pp as SX,Pq as SY,Pr as S2,Ps as q$,Ql as l4,Qm as Y0,Qn as B9,Qo as BJ,Qp as BX,Qq as BY,Qr as B2,Qs as N$,Rl as r4,Rm as B0,Rn as T9,Ro as TJ,Rp as TX,Rq as TY,Rr as T2,Rs as P$,Sl as t4,Sm as T0,Sn as w9,So as wJ,Sp as wX,Sq as wY,Sr as w2,Ss as S$,Tl as g4,Tm as L1,Tn as j9,To as jJ,Tp as jX,Tq as jY,Tr as j2,Ts as B$,Ul as i4,Um as y1,Un as D9,Uo as DJ,Up as DX,Uq as DY,Ur as D2,Us as T$,Vl as a4,Vm as w0,Vn as k9,Vo as kJ,Vp as kX,Vq as kY,Vr as k2,Vs as w$,Wl as o4,Wm as b1,Wn as L9,Wo as LJ,Wp as LX,Wq as LY,Wr as L2,Ws as j$,Xl as s4,Xm as h1,Xn as y9,Xo as yJ,Xp as yX,Xq as yY,Xr as y2,Xs as NW,Yl as n4,Ym as C1,Yn as b9,Yo as bJ,Yp as bX,Yq as bY,Yr as b2,Ys as PW,Zl as e4,Zm as I1,Zn as h9,Zo as hJ,Zp as hX,Zq as hY,Zr as h2,Zs as SW,_l as $1,_m as f1,_n as C9,_o as CJ,_p as CX,_q as CY,_r as C2,_s as BW,am as J1,an as g,ao as f9,ap as fJ,aq as fX,ar as fY,as as f2,at as wW,bm as X1,bn as p1,bo as p9,bp as pJ,bq as pX,br as pY,bs as p2,bt as jW,cm as Y1,cn as m1,co as m9,cp as mJ,cq as mX,cr as mY,cs as m2,ct as DW,dm as W1,dn as v1,do as v9,dp as vJ,dq as vX,dr as vY,ds as v2,dt as kW,em as _1,en as c1,eo as c9,ep as cJ,eq as cX,er as cY,es as c2,et as LW,fm as x0,fn as u1,fo as u9,fp as uJ,fq as uX,fr as uY,fs as u2,ft as yW,gm as Q1,gn as d1,go as d9,gp as dJ,gq as dX,gr as dY,gs as d2,gt as bW,hm as q0,hn as l1,ho as l9,hp as lJ,hq as lX,hr as lY,hs as l2,ht as hW,im as N0,in as r1,io as r9,ip as rJ,iq as rX,ir as rY,is as r2,it as CW,jm as F1,jn as t1,jo as t9,jp as tJ,jq as tX,jr as tY,js as t2,jt as IW,km as K1,kn as g1,ko as g9,kp as gJ,kq as gX,kr as gY,ks as g2,kt as fW,lm as U1,ln as i1,lo as i9,lp as iJ,lq as iX,lr as iY,ls as i2,lt as pW,mm as G1,mn as a1,mo as a9,mp as aJ,mq as aX,mr as aY,ms as a2,mt as mW,nm as V1,nn as o1,no as o9,np as oJ,nq as oX,nr as oY,ns as o2,nt as vW,om as O1,on as s1,oo as s9,op as sJ,oq as sX,or as sY,os as s2,ot as cW,pm as Z1,pn as n1,po as n9,pp as nJ,pq as nX,pr as nY,ps as n2,pt as uW,qm as E1,qn as e1,qo as e9,qp as eJ,qq as eX,qr as eY,qs as e2,qt as dW,rm as H1,rn as $9,ro as $J,rp as $X,rq as $Y,rr as $2,rs as $W,rt as lW,sm as R1,sn as M9,so as MJ,sp as MX,sq as MY,sr as M2,ss as MW,st as rW,tm as A1,tn as J9,to as JJ,tp as JX,tq as JY,tr as J2,ts as JW,tt as tW,um as z1,un as X9,uo as XJ,up as XX,uq as XY,ur as X2,us as XW,ut as gW,vm as x1,vn as Y9,vo as YJ,vp as YX,vq as YY,vr as Y2,vs as YW,vt as iW,wm as q1,wn as W9,wo as WJ,wp as WX,wq as WY,wr as W2,ws as WW,wt as aW,xm as M0,xn as _9,xo as _J,xp as _X,xq as _Y,xr as _2,xs as _W,xt as oW,ym as N1,yn as Q9,yo as QJ,yp as QX,yq as QY,yr as Q2,ys as QW,yt as sW,zm as P1,zn as F9,zo as FJ,zp as FX,zq as FY,zr as F2,zs as FW,zt as nW}from"./chunk-6xcbfs2r.js";import{Ct as Z$,Et as i}from"./chunk-rr1yaj55.js";import{createHmac as E0,createSign as d0,timingSafeEqual as l0}from"node:crypto";function m($){let M=$ instanceof Date?$.getTime():$;if(!Number.isFinite(M))throw TypeError("Media access timestamp must be finite");return Math.floor(M/1000)}function H0($){return Buffer.from($).toString("base64").replaceAll("+","-").replaceAll("=","_").replaceAll("/","~")}function r0($){return Buffer.from($).toString("base64url")}function R0($,M=!1){if(!$||/[\r\n]/.test($))throw TypeError("Media resource is invalid");let J=M?$.replaceAll("*","wildcard"):$,X=new URL(J);if(!["http:","https:"].includes(X.protocol))throw TypeError("Media resource must use HTTP or HTTPS");if(!M&&$.includes("*"))throw TypeError("Canned policies cannot contain wildcards")}function A0($,M){let J=d0("RSA-SHA1");return J.update($),J.end(),H0(J.sign(M))}function z0($){R0($.resource,!0);let J={DateLessThan:{"AWS:EpochTime":m($.expiresAt)}};if($.activeAt!==void 0)J.DateGreaterThan={"AWS:EpochTime":m($.activeAt)};if($.ipAddress)J.IpAddress={"AWS:SourceIp":$.ipAddress};return JSON.stringify({Statement:[{Resource:$.resource,Condition:J}]})}function cM($,M,J){R0($);let X=m(M),Y=$.includes("?")?"&":"?",U=z0({resource:$,expiresAt:M}),Q=A0(U,J.privateKey);return`${$}${Y}Expires=${X}&Signature=${encodeURIComponent(Q)}&Key-Pair-Id=${encodeURIComponent(J.keyPairId)}`}function uM($,M){let J=z0($);return{"CloudFront-Key-Pair-Id":M.keyPairId,"CloudFront-Policy":H0(Buffer.from(J)),"CloudFront-Signature":A0(J,M.privateKey)}}function dM($){if(!$.resource||/[\r\n]/.test($.resource))throw TypeError("Media resource is invalid");let M=r0(Buffer.from(JSON.stringify({resource:$.resource,expiresAt:m($.expiresAt),...$.keyId?{keyId:$.keyId}:{},...$.audience?{audience:$.audience}:{}}))),J=E0("sha256",$.secret).update(M).digest("base64url");return`${M}.${J}`}function lM($,M){let[J,X,Y]=$.split(".");if(!J||!X||Y)return null;let U=E0("sha256",M.secret).update(J).digest(),Q;try{Q=Buffer.from(X,"base64url")}catch{return null}if(U.length!==Q.length||!l0(U,Q))return null;try{let _=JSON.parse(Buffer.from(J,"base64url").toString("utf8")),K=m(M.now??Date.now());if(!_.resource||!Number.isSafeInteger(_.expiresAt)||_.expiresAt<=K)return null;if(M.resource&&_.resource!==M.resource)return null;if(M.audience&&_.audience!==M.audience)return null;return _}catch{return null}}function rM($,M=!1){let J=new URL($,"https://media.invalid").pathname.toLowerCase(),X=/\.(?:m3u8|mpd|vtt|json)$/.test(J),Y=/\.(?:key|license)$/.test(J)||J.includes("/keys/")||J.includes("/licenses/");return{"Accept-Ranges":"bytes","Cache-Control":M&&(X||Y)?"private, no-store":X?"public, max-age=5, s-maxage=30, stale-while-revalidate=30":"public, max-age=31536000, immutable","Cross-Origin-Resource-Policy":"cross-origin","X-Content-Type-Options":"nosniff"}}function tM($){if(!/^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/.test($.bucket))throw TypeError("Media bucket is invalid");if(!/^[a-z0-9-]+$/.test($.region))throw TypeError("Media bucket region is invalid");let M=$.prefix?`/${$.prefix.replace(/^\/+|\/+$/g,"")}`:"",J=$.protected??!1,X="public, max-age=31536000, immutable",Y=J?"private, no-store":"public, max-age=5, s-maxage=30, stale-while-revalidate=30";return{originDomain:`${$.bucket}.s3.${$.region}.amazonaws.com`,originPath:M,domain:$.domain,trustedKeyGroupIds:[...new Set($.trustedKeyGroupIds??[])],behaviors:[{pathPattern:"*.m3u8",cacheControl:Y,compress:!0,signed:J},{pathPattern:"*.mpd",cacheControl:Y,compress:!0,signed:J},{pathPattern:"*.vtt",cacheControl:Y,compress:!0,signed:J},{pathPattern:"*",cacheControl:X,compress:!1,signed:J}],responseHeaders:{"Access-Control-Allow-Headers":"Range, If-Range","Access-Control-Allow-Methods":"GET, HEAD, OPTIONS","Access-Control-Allow-Origin":"*","Access-Control-Expose-Headers":"Accept-Ranges, Content-Length, Content-Range, ETag","X-Content-Type-Options":"nosniff"}}}class t0{builder;config;environment;mergedConfig;serverEipLogicalIds=new Map;constructor($){this.config=$.config,this.environment=$.environment,this.builder=new x0(`${this.config.project.name} - ${this.environment}`),this.mergedConfig=this.mergeEnvironmentConfig()}mergeEnvironmentConfig(){let M=this.config.environments[this.environment]?.infrastructure;if(!M)return this.config;return{...this.config,infrastructure:{...this.config.infrastructure,...M,compute:{...this.config.infrastructure?.compute,...M.compute},storage:{...this.config.infrastructure?.storage,...M.storage},functions:{...this.config.infrastructure?.functions,...M.functions},servers:{...this.config.infrastructure?.servers,...M.servers},databases:{...this.config.infrastructure?.databases,...M.databases},cdn:{...this.config.infrastructure?.cdn,...M.cdn},sftp:M.sftp??this.config.infrastructure?.sftp,queues:{...this.config.infrastructure?.queues,...M.queues},redirects:{...this.config.infrastructure?.redirects,...M.redirects},realtime:{...this.config.infrastructure?.realtime,...M.realtime},cache:{...this.config.infrastructure?.cache,...M.cache},fileSystem:{...this.config.infrastructure?.fileSystem,...M.fileSystem},email:{...this.config.infrastructure?.email,...M.email},search:{...this.config.infrastructure?.search,...M.search},ai:{...this.config.infrastructure?.ai,...M.ai}}}}shouldDeploy($){if($.environments&&!$.environments.includes(this.environment))return!1;if($.requiresFeatures){let M=this.config.features||{};if(!$.requiresFeatures.every((X)=>M[X]===!0))return!1}if($.regions){let M=this.config.environments[this.environment]?.region||this.config.project.region;if(!$.regions.includes(M))return!1}if($.condition&&typeof $.condition==="function")return $.condition(this.config,this.environment);return!0}resolveApiOriginPort(){let $=this.mergedConfig.infrastructure?.api?.port??this.mergedConfig.ports?.api,M=Number($||3008);return Number.isFinite(M)&&M>0?M:3008}defaultComputeCachePathPatterns(){return["/api/*","/auth/*","/publisher/api/*","/publisher/*","/publish","/publish/*","/analytics/*","/packages/*","/npm/*","/zig/*","/php/*","/commits/*","/health","/dashboard/*","/search","/login","/logout","/signup","/account","/account/*"]}shouldRouteStorageBucketToCompute($,M){return $==="public"||M.routeCompute===!0}storageBucketName($,M,J){return this.mergedConfig.infrastructure?.storage?.[J]?.bucket??`${$}-${M}-${J}`}fileSystemLogicalId($,M,J){return N0(q0({slug:`${$}-${J}`,environment:M,resourceType:"efs"}))}resolveSftpStorage($,M,J){let X=$.storage;if(X?.type==="efs"&&X.fileSystem){if(!this.mergedConfig.infrastructure?.fileSystem?.[X.fileSystem])throw Error(`sftp: storage.fileSystem "${X.fileSystem}" is not defined in infrastructure.fileSystem`);return{type:"efs",fileSystemId:{Ref:this.fileSystemLogicalId(M,J,X.fileSystem)},posixProfile:X.posixProfile}}if(X?.type==="s3"&&X.storageBucket){if(!this.mergedConfig.infrastructure?.storage?.[X.storageBucket])throw Error(`sftp: storage.storageBucket "${X.storageBucket}" is not defined in infrastructure.storage`);return{type:"s3",bucket:this.storageBucketName(M,J,X.storageBucket)}}return}resolveComputeCachePathPatterns($){if($&&$.length>0)return $;return this.defaultComputeCachePathPatterns()}createComputeCacheBehavior($,M){return{PathPattern:$,TargetOriginId:M,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD"],Compress:!0,CachePolicyId:"4135ea2d-6df8-44a3-9df3-4b5a84be39ad",OriginRequestPolicyId:"b689b0a8-53d0-40ab-baf2-68738e2966ac"}}appendComputeAppOrigin($,M,J,X,Y,U){let Q=this.serverEipLogicalIds.get("app"),_=this.serverEipLogicalIds.get("appInstance");if(!Q)return;let K=`EC2-${X}-${Y}-api`,V=this.mergedConfig.infrastructure?.servers?.app?.region||this.mergedConfig.project?.region||"us-east-1",G=V==="us-east-1"?".compute-1.amazonaws.com":`.${V}.compute.amazonaws.com`,q={"Fn::Join":["",["ec2-",{"Fn::Join":["-",{"Fn::Split":[".",{Ref:Q}]}]},G]]},A=this.resolveApiOriginPort();if($.push({Id:K,DomainName:q,CustomOriginConfig:{HTTPPort:A,HTTPSPort:443,OriginProtocolPolicy:"http-only",OriginSSLProtocols:["TLSv1.2"]}}),J.push(Q),_)J.push(_);for(let P of U)M.push(this.createComputeCacheBehavior(P,K))}buildCaddyfile($){let M=$.filter(([,Y])=>typeof Y.domain==="string"&&Y.domain&&typeof Y.port==="number");if(M.length===0)return;let J=new Map;for(let[,Y]of M){let U=J.get(Y.domain)??[];U.push({port:Y.port,path:Y.path}),J.set(Y.domain,U)}let X=[];for(let[Y,U]of J){let _=[...U].sort((K,V)=>{let G=!K.path||K.path==="/",q=!V.path||V.path==="/";if(G&&!q)return 1;if(!G&&q)return-1;return(V.path?.length??0)-(K.path?.length??0)}).map((K)=>{let V=!K.path||K.path==="/",G=`reverse_proxy localhost:${K.port}`;return V?` handle {
2
+ ${G}
3
+ }`:` handle ${K.path} {
4
+ ${G}
5
+ }`});X.push(`${Y} {
6
+ ${_.join(`
7
7
  `)}
8
- }`)}return n.join(`
8
+ }`)}return X.join(`
9
9
 
10
- `)}normalizeMountPath(e){let t=e?.mountPath||e?.path;if(!t||t==="/")return;let r=`/${t}`.replace(/\/+/g,"/").replace(/\/$/,"");return r==="/"?void 0:r}storageBucketLogicalId(e,t,r){return`${e}-${t}-s3-${r}`.split(/[^a-zA-Z0-9]+/).filter(Boolean).map((n)=>n.charAt(0).toUpperCase()+n.slice(1)).join("")}pathMountRewriteFunctionCode(e,t="directory"){return`function handler(event) { var request = event.request; var prefix = ${JSON.stringify(e)}; var rewriteStyle = ${JSON.stringify(t)}; var uri = request.uri; if (uri === prefix) { uri = '/'; } else if (uri.indexOf(prefix + '/') === 0) { uri = uri.substring(prefix.length); } if (uri === '' || uri === '/') { request.uri = '/index.html'; return request; } if (uri.endsWith('/')) { request.uri = uri + 'index.html'; return request; } var lastSegment = uri.substring(uri.lastIndexOf('/') + 1); if (lastSegment.indexOf('.') === -1) { request.uri = rewriteStyle === 'flat' ? uri + '.html' : uri + '/index.html'; return request; } request.uri = uri; return request; }`}generate(){let e=this.mergedConfig.project.slug,t=this.environment,r=!!(this.mergedConfig.infrastructure?.functions&&Object.keys(this.mergedConfig.infrastructure.functions).length>0||this.mergedConfig.infrastructure?.api),n=!!(this.mergedConfig.infrastructure?.servers&&Object.keys(this.mergedConfig.infrastructure.servers).length>0),o=!!this.mergedConfig.infrastructure?.compute;if(!!((this.mergedConfig.mode||"server")==="serverless"&&this.mergedConfig.infrastructure?.containers&&Object.keys(this.mergedConfig.infrastructure.containers).length>0))this.generateNetworkInfrastructure(e,t),this.generateContainerInfrastructure(e,t);if(r)this.generateServerless(e,t);if(n)this.generateServer(e,t);if(o)this.generateComputeApp(e,t);if(this.mergedConfig.infrastructure?.jumpBox)this.generateJumpBox(e,t);if(this.generateSharedInfrastructure(e,t),this.config.tags)this.applyGlobalTags(this.config.tags);return this}applyGlobalTags(e){}generateNetworkInfrastructure(e,t){if(this.builder.hasResource("VPC"))return;let n=this.mergedConfig.infrastructure?.network?.cidr||"10.0.0.0/16",{vpc:o,logicalId:l}=Re.createVpc({slug:e,environment:t,cidr:n,enableDnsHostnames:!0,enableDnsSupport:!0});this.builder.addResource("VPC",o);let c=`${e}${t}IGW`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(c,{Type:"AWS::EC2::InternetGateway",Properties:{Tags:[{Key:"Name",Value:`${e}-${t}-igw`},{Key:"Environment",Value:t}]}});let s=`${e}${t}IGWAttach`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(s,{Type:"AWS::EC2::VPCGatewayAttachment",Properties:{VpcId:{Ref:"VPC"},InternetGatewayId:{Ref:c}}});let u=`${e}${t}PublicRT`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(u,{Type:"AWS::EC2::RouteTable",Properties:{VpcId:{Ref:"VPC"},Tags:[{Key:"Name",Value:`${e}-${t}-public-rt`},{Key:"Environment",Value:t}]}}),this.builder.addResource(`${e}${t}PublicRoute`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::EC2::Route",Properties:{RouteTableId:{Ref:u},DestinationCidrBlock:"0.0.0.0/0",GatewayId:{Ref:c}},DependsOn:s});let h=this.mergedConfig.environments[t]?.region||this.mergedConfig.project.region||"us-east-1",d=["a","b"];for(let b=0;b<2;b++){let A=`PublicSubnet${b+1}`;this.builder.addResource(A,{Type:"AWS::EC2::Subnet",Properties:{VpcId:{Ref:"VPC"},CidrBlock:`10.0.${b}.0/24`,AvailabilityZone:`${h}${d[b]}`,MapPublicIpOnLaunch:!0,Tags:[{Key:"Name",Value:`${e}-${t}-public-${d[b]}`},{Key:"Environment",Value:t}]}}),this.builder.addResource(`${A}RTAssoc`,{Type:"AWS::EC2::SubnetRouteTableAssociation",Properties:{SubnetId:{Ref:A},RouteTableId:{Ref:u}}})}}generateContainerInfrastructure(e,t){let r=this.mergedConfig.infrastructure?.containers;if(!r)return;let n=this.mergedConfig.infrastructure?.loadBalancer,o=this.mergedConfig.infrastructure?.ssl,l=this.mergedConfig.infrastructure?.dns,c;if(o?.enabled&&o.domains?.length)if(o.certificateArn);else{let d=o.domains[0],b=o.domains.slice(1).map((g)=>{if(g.includes(".")&&g.endsWith(d))return g.replace(`.${d}`,"");return g}),{certificate:A,logicalId:T}=te.createCertificate({domain:d,subdomains:b,slug:e,environment:t,validationMethod:"DNS",hostedZoneId:l?.hostedZoneId});c=T,this.builder.addResource(T,A)}let s="ECSCluster";this.builder.addResource(s,{Type:"AWS::ECS::Cluster",Properties:{ClusterName:`${e}-${t}`,ClusterSettings:[{Name:"containerInsights",Value:"enabled"}],Tags:[{Key:"Name",Value:`${e}-${t}`},{Key:"Environment",Value:t}]}});let u=`${e}${t}ALBSecurityGroup`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(u,{Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:`ALB security group for ${e}-${t}`,VpcId:{Ref:"VPC"},SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:80,ToPort:80,CidrIp:"0.0.0.0/0",Description:"HTTP"},{IpProtocol:"tcp",FromPort:443,ToPort:443,CidrIp:"0.0.0.0/0",Description:"HTTPS"}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound"}],Tags:[{Key:"Name",Value:`${e}-${t}-alb-sg`},{Key:"Environment",Value:t}]}});let h=`${e}${t}ECSSecurityGroup`.replace(/[^a-zA-Z0-9]/g,"");for(let[d,b]of Object.entries(r)){let A=b.port||3000;this.builder.addResource(h,{Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:`ECS tasks security group for ${e}-${t}`,VpcId:{Ref:"VPC"},SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:A,ToPort:A,SourceSecurityGroupId:{Ref:u},Description:"Allow traffic from ALB"}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound"}],Tags:[{Key:"Name",Value:`${e}-${t}-ecs-sg`},{Key:"Environment",Value:t}]}});let T=`${e}${t}TaskExecRole`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(T,{Type:"AWS::IAM::Role",Properties:{RoleName:`${e}-${t}-ecs-exec-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"],Policies:[{PolicyName:"ECRPullPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["ecr:GetAuthorizationToken","ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","logs:CreateLogStream","logs:PutLogEvents"],Resource:"*"}]}}]}});let g=`${e}${t}TaskRole`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(g,{Type:"AWS::IAM::Role",Properties:{RoleName:`${e}-${t}-ecs-task-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"TaskPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogStream","logs:PutLogEvents"],Resource:"*"},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:ListBucket"],Resource:"*"}]}}]}});let m=`${e}${t}${d}LogGroup`.replace(/[^a-zA-Z0-9]/g,""),a=`/ecs/${e}-${t}-${d}`;this.builder.addResource(m,{Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:a,RetentionInDays:30}});let y=`${e}${t}${d}TaskDef`.replace(/[^a-zA-Z0-9]/g,""),i=String(b.cpu||512),p=String(b.memory||1024);this.builder.addResource(y,{Type:"AWS::ECS::TaskDefinition",Properties:{Family:`${e}-${t}-${d}`,NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:i,Memory:p,ExecutionRoleArn:{"Fn::GetAtt":[T,"Arn"]},TaskRoleArn:{"Fn::GetAtt":[g,"Arn"]},ContainerDefinitions:[{Name:d,Image:{"Fn::Sub":`\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.amazonaws.com/${e}:latest`},Essential:!0,PortMappings:[{ContainerPort:A,Protocol:"tcp"}],LogConfiguration:{LogDriver:"awslogs",Options:{"awslogs-group":a,"awslogs-region":{Ref:"AWS::Region"},"awslogs-stream-prefix":d}},HealthCheck:{Command:["CMD-SHELL",`curl -f http://localhost:${A}${b.healthCheck||"/health"} || exit 1`],Interval:30,Timeout:5,Retries:3,StartPeriod:60}}],Tags:[{Key:"Name",Value:`${e}-${t}-${d}`},{Key:"Environment",Value:t}]},DependsOn:[T,g,m]});let f=`${e}${t}ALB`.replace(/[^a-zA-Z0-9]/g,"");if(n?.enabled!==!1){this.builder.addResource(f,{Type:"AWS::ElasticLoadBalancingV2::LoadBalancer",Properties:{Name:`${e}-${t}-alb`,Scheme:"internet-facing",Type:"application",Subnets:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}],SecurityGroups:[{Ref:u}],Tags:[{Key:"Name",Value:`${e}-${t}-alb`},{Key:"Environment",Value:t}]}});let C=`${e}${t}TargetGroup`.replace(/[^a-zA-Z0-9]/g,""),S=n?.healthCheck?.path||b.healthCheck||"/health";this.builder.addResource(C,{Type:"AWS::ElasticLoadBalancingV2::TargetGroup",Properties:{Name:`${e}-${t}-tg`,Port:A,Protocol:"HTTP",VpcId:{Ref:"VPC"},TargetType:"ip",HealthCheckPath:S,HealthCheckIntervalSeconds:n?.healthCheck?.interval||30,HealthyThresholdCount:n?.healthCheck?.healthyThreshold||2,UnhealthyThresholdCount:n?.healthCheck?.unhealthyThreshold||5,HealthCheckTimeoutSeconds:10,Tags:[{Key:"Name",Value:`${e}-${t}-tg`},{Key:"Environment",Value:t}]}});let R=`${e}${t}HTTPListener`.replace(/[^a-zA-Z0-9]/g,"");if(o?.enabled&&o?.redirectHttp)this.builder.addResource(R,{Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:{Ref:f},Port:80,Protocol:"HTTP",DefaultActions:[{Type:"redirect",RedirectConfig:{Protocol:"HTTPS",Port:"443",StatusCode:"HTTP_301"}}]}});else this.builder.addResource(R,{Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:{Ref:f},Port:80,Protocol:"HTTP",DefaultActions:[{Type:"forward",TargetGroupArn:{Ref:C}}]}});if(o?.enabled){let v=o.certificateArn||(c?{Ref:c}:void 0);if(v){let O=`${e}${t}HTTPSListener`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(O,{Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:{Ref:f},Port:443,Protocol:"HTTPS",Certificates:[{CertificateArn:v}],DefaultActions:[{Type:"forward",TargetGroupArn:{Ref:C}}],SslPolicy:"ELBSecurityPolicy-TLS13-1-2-2021-06"}})}}let I=`${e}${t}${d}Service`.replace(/[^a-zA-Z0-9]/g,""),D=b.desiredCount||1;this.builder.addResource(I,{Type:"AWS::ECS::Service",Properties:{ServiceName:`${e}-${t}-${d}`,Cluster:{Ref:s},TaskDefinition:{Ref:y},DesiredCount:D,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{AssignPublicIp:"ENABLED",SecurityGroups:[{Ref:h}],Subnets:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]}},LoadBalancers:[{ContainerName:d,ContainerPort:A,TargetGroupArn:{Ref:C}}],HealthCheckGracePeriodSeconds:120,Tags:[{Key:"Name",Value:`${e}-${t}-${d}`},{Key:"Environment",Value:t}]},DependsOn:[y,R,C]});let P=b.autoScaling;if(P){let v=`${e}${t}${d}ScalableTarget`.replace(/[^a-zA-Z0-9]/g,"");if(this.builder.addResource(v,{Type:"AWS::ApplicationAutoScaling::ScalableTarget",Properties:{MaxCapacity:P.max||10,MinCapacity:P.min||1,ResourceId:{"Fn::Sub":`service/\${${s}}/${e}-${t}-${d}`},ScalableDimension:"ecs:service:DesiredCount",ServiceNamespace:"ecs",RoleARN:{"Fn::Sub":"arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService"}},DependsOn:I}),P.targetCpuUtilization)this.builder.addResource(`${e}${t}${d}CPUScaling`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::ApplicationAutoScaling::ScalingPolicy",Properties:{PolicyName:`${e}-${t}-${d}-cpu-scaling`,PolicyType:"TargetTrackingScaling",ScalingTargetId:{Ref:v},TargetTrackingScalingPolicyConfiguration:{PredefinedMetricSpecification:{PredefinedMetricType:"ECSServiceAverageCPUUtilization"},TargetValue:P.targetCpuUtilization,ScaleInCooldown:300,ScaleOutCooldown:60}}});if(P.targetMemoryUtilization)this.builder.addResource(`${e}${t}${d}MemoryScaling`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::ApplicationAutoScaling::ScalingPolicy",Properties:{PolicyName:`${e}-${t}-${d}-memory-scaling`,PolicyType:"TargetTrackingScaling",ScalingTargetId:{Ref:v},TargetTrackingScalingPolicyConfiguration:{PredefinedMetricSpecification:{PredefinedMetricType:"ECSServiceAverageMemoryUtilization"},TargetValue:P.targetMemoryUtilization,ScaleInCooldown:300,ScaleOutCooldown:60}}})}if(l?.domain&&l?.hostedZoneId)this.builder.addResource(`${e}${t}ApiDnsRecord`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:l.hostedZoneId,Name:`api.${l.domain}`,Type:"A",AliasTarget:{DNSName:{"Fn::GetAtt":[f,"DNSName"]},HostedZoneId:{"Fn::GetAtt":[f,"CanonicalHostedZoneID"]}}}});this.builder.addOutput("ECSClusterArn",{Description:"ECS Cluster ARN",Value:{"Fn::GetAtt":[s,"Arn"]},Export:{Name:{"Fn::Sub":"${AWS::StackName}-ecs-cluster-arn"}}}),this.builder.addOutput("ECSServiceName",{Description:"ECS Service Name",Value:`${e}-${t}-${d}`,Export:{Name:{"Fn::Sub":"${AWS::StackName}-ecs-service-name"}}}),this.builder.addOutput("LoadBalancerDNS",{Description:"Application Load Balancer DNS Name",Value:{"Fn::GetAtt":[f,"DNSName"]},Export:{Name:{"Fn::Sub":"${AWS::StackName}-alb-dns"}}})}else{let C=`${e}${t}${d}Service`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(C,{Type:"AWS::ECS::Service",Properties:{ServiceName:`${e}-${t}-${d}`,Cluster:{Ref:s},TaskDefinition:{Ref:y},DesiredCount:b.desiredCount||1,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{AssignPublicIp:"ENABLED",SecurityGroups:[{Ref:h}],Subnets:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]}},Tags:[{Key:"Name",Value:`${e}-${t}-${d}`},{Key:"Environment",Value:t}]},DependsOn:[y]})}break}}generateServerless(e,t){if(this.mergedConfig.infrastructure?.functions)for(let[r,n]of Object.entries(this.mergedConfig.infrastructure.functions)){if(!this.shouldDeploy(n))continue;let{role:o,logicalId:l}=$e.createRole({slug:e,environment:t,roleName:`${e}-${t}-${r}-role`,servicePrincipal:"lambda.amazonaws.com",managedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]});this.builder.addResource(l,o);let{lambdaFunction:c,logicalId:s}=w.createLambdaFunction({slug:e,environment:t,functionName:`${e}-${t}-${r}`,handler:n.handler||"index.handler",runtime:n.runtime||"nodejs20.x",code:{zipFile:n.code||"export const handler = async () => ({ statusCode: 200 });"},role:l,timeout:n.timeout,memorySize:n.memorySize});this.builder.addResource(s,c)}if(this.mergedConfig.infrastructure?.api){let{restApi:r,logicalId:n}=Pe.createRestApi({slug:e,environment:t,apiName:`${e}-${t}-api`});this.builder.addResource(n,r)}}generateServer(e,t){if(!this.mergedConfig.infrastructure?.servers)return;let r=this.mergedConfig.infrastructure.servers,n=this.mergedConfig.infrastructure?.compute,o=this.mergedConfig.infrastructure?.ssl;if(Object.values(r).some((c)=>!c.privateNetwork||c.privateNetwork==="create"))this.generateNetworkInfrastructure(e,t);for(let[c,s]of Object.entries(r)){let u=s.instanceType||s.size||n?.size,d=(u?w.InstanceSize.specs[u]:void 0)?.instanceType||u||"t3.micro",b=s.type||"app",A=s.userData||s.startupScript;if(!A)A=w.UserData.generateAppServerScript({runtime:"bun",runtimeVersion:s.bunVersion||"latest",webServer:"none",domain:s.domain,enableSsl:!!o?.enabled,sslEmail:o?.letsEncrypt?.email,installRedis:b==="cache",installDatabaseClients:!!s.database});let T=s.privateNetwork&&s.privateNetwork!=="create"?s.privateNetwork:{Ref:"VPC"},g=s.subnet||{Ref:"PublicSubnet1"},a=!!this.mergedConfig.infrastructure?.email?.server?.enabled,y=[22,80,443,this.resolveApiOriginPort()];if(a)y.push(25,465,587,143,993);let i=w.createServerModeStack({slug:`${e}-${c}`,environment:t,vpcId:T,subnetId:g,instanceType:d,keyName:s.keyName||`${e}-${t}`,domain:s.domain,userData:A,volumeSize:s.diskSize||20,imageId:s.image,allowedPorts:y});for(let[p,f]of Object.entries(i.resources))this.builder.addResource(p,f);this.serverEipLogicalIds.set(c,i.outputs.eipLogicalId),this.serverEipLogicalIds.set(`${c}Instance`,i.outputs.instanceLogicalId),this.builder.addOutput(`${c}InstanceId`,{Value:{Ref:i.outputs.instanceLogicalId},Description:`Instance ID for ${c} server`}),this.builder.addOutput(`${c}PublicIp`,{Value:{Ref:i.outputs.eipLogicalId},Description:`Public IP for ${c} server`})}}generateComputeApp(e,t){let r=this.mergedConfig.infrastructure?.compute;if(!r)return;let n=this.mergedConfig.sites||{},o=Object.entries(n),c=this.mergedConfig.infrastructure?.dns?.domain,s=this.mergedConfig.infrastructure?.database,u=r.size,d=(u?w.InstanceSize.specs[u]:void 0)?.instanceType||u||"t3.micro";if(!this.builder.hasResource("VPC"))this.generateNetworkInfrastructure(e,t);let b=this.buildCaddyfile(o),A=w.UserData.generateBunAppScript({runtime:r.runtime||"bun",runtimeVersion:r.runtimeVersion||"latest",systemPackages:r.systemPackages,database:s,caddyfile:b}),T=Ee(r.appUpdates),g=T.length>0?`${A}
11
- ${T.join(`
10
+ `)}normalizeMountPath($){let M=$?.mountPath||$?.path;if(!M||M==="/")return;let J=`/${M}`.replace(/\/+/g,"/").replace(/\/$/,"");return J==="/"?void 0:J}storageBucketLogicalId($,M,J){return`${$}-${M}-s3-${J}`.split(/[^a-zA-Z0-9]+/).filter(Boolean).map((X)=>X.charAt(0).toUpperCase()+X.slice(1)).join("")}pathMountRewriteFunctionCode($,M="directory"){return`function handler(event) { var request = event.request; var prefix = ${JSON.stringify($)}; var rewriteStyle = ${JSON.stringify(M)}; var uri = request.uri; if (uri === prefix) { uri = '/'; } else if (uri.indexOf(prefix + '/') === 0) { uri = uri.substring(prefix.length); } if (uri === '' || uri === '/') { request.uri = '/index.html'; return request; } if (uri.endsWith('/')) { request.uri = uri + 'index.html'; return request; } var lastSegment = uri.substring(uri.lastIndexOf('/') + 1); if (lastSegment.indexOf('.') === -1) { request.uri = rewriteStyle === 'flat' ? uri + '.html' : uri + '/index.html'; return request; } request.uri = uri; return request; }`}generate(){let $=this.mergedConfig.project.slug,M=this.environment,J=!!(this.mergedConfig.infrastructure?.functions&&Object.keys(this.mergedConfig.infrastructure.functions).length>0||this.mergedConfig.infrastructure?.api),X=!!(this.mergedConfig.infrastructure?.servers&&Object.keys(this.mergedConfig.infrastructure.servers).length>0),Y=!!this.mergedConfig.infrastructure?.compute;if(!!((this.mergedConfig.mode||"server")==="serverless"&&this.mergedConfig.infrastructure?.containers&&Object.keys(this.mergedConfig.infrastructure.containers).length>0))this.generateNetworkInfrastructure($,M),this.generateContainerInfrastructure($,M);if(J)this.generateServerless($,M);if(X)this.generateServer($,M);if(Y)this.generateComputeApp($,M);if(this.mergedConfig.infrastructure?.jumpBox)this.generateJumpBox($,M);if(this.generateSharedInfrastructure($,M),this.config.tags)this.applyGlobalTags(this.config.tags);return this}applyGlobalTags($){}generateNetworkInfrastructure($,M){if(this.builder.hasResource("VPC"))return;let X=this.mergedConfig.infrastructure?.network?.cidr||"10.0.0.0/16",{vpc:Y,logicalId:U}=P0.createVpc({slug:$,environment:M,cidr:X,enableDnsHostnames:!0,enableDnsSupport:!0});this.builder.addResource("VPC",Y);let Q=`${$}${M}IGW`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(Q,{Type:"AWS::EC2::InternetGateway",Properties:{Tags:[{Key:"Name",Value:`${$}-${M}-igw`},{Key:"Environment",Value:M}]}});let _=`${$}${M}IGWAttach`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(_,{Type:"AWS::EC2::VPCGatewayAttachment",Properties:{VpcId:{Ref:"VPC"},InternetGatewayId:{Ref:Q}}});let K=`${$}${M}PublicRT`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(K,{Type:"AWS::EC2::RouteTable",Properties:{VpcId:{Ref:"VPC"},Tags:[{Key:"Name",Value:`${$}-${M}-public-rt`},{Key:"Environment",Value:M}]}}),this.builder.addResource(`${$}${M}PublicRoute`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::EC2::Route",Properties:{RouteTableId:{Ref:K},DestinationCidrBlock:"0.0.0.0/0",GatewayId:{Ref:Q}},DependsOn:_});let V=this.mergedConfig.environments[M]?.region||this.mergedConfig.project.region||"us-east-1",G=["a","b"];for(let q=0;q<2;q++){let A=`PublicSubnet${q+1}`;this.builder.addResource(A,{Type:"AWS::EC2::Subnet",Properties:{VpcId:{Ref:"VPC"},CidrBlock:`10.0.${q}.0/24`,AvailabilityZone:`${V}${G[q]}`,MapPublicIpOnLaunch:!0,Tags:[{Key:"Name",Value:`${$}-${M}-public-${G[q]}`},{Key:"Environment",Value:M}]}}),this.builder.addResource(`${A}RTAssoc`,{Type:"AWS::EC2::SubnetRouteTableAssociation",Properties:{SubnetId:{Ref:A},RouteTableId:{Ref:K}}})}}generateContainerInfrastructure($,M){let J=this.mergedConfig.infrastructure?.containers;if(!J)return;let X=this.mergedConfig.infrastructure?.loadBalancer,Y=this.mergedConfig.infrastructure?.ssl,U=this.mergedConfig.infrastructure?.dns,Q;if(Y?.enabled&&Y.domains?.length)if(Y.certificateArn);else{let G=Y.domains[0],q=Y.domains.slice(1).map((E)=>{if(E.includes(".")&&E.endsWith(G))return E.replace(`.${G}`,"");return E}),{certificate:A,logicalId:P}=J0.createCertificate({domain:G,subdomains:q,slug:$,environment:M,validationMethod:"DNS",hostedZoneId:U?.hostedZoneId});Q=P,this.builder.addResource(P,A)}let _="ECSCluster";this.builder.addResource(_,{Type:"AWS::ECS::Cluster",Properties:{ClusterName:`${$}-${M}`,ClusterSettings:[{Name:"containerInsights",Value:"enabled"}],Tags:[{Key:"Name",Value:`${$}-${M}`},{Key:"Environment",Value:M}]}});let K=`${$}${M}ALBSecurityGroup`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(K,{Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:`ALB security group for ${$}-${M}`,VpcId:{Ref:"VPC"},SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:80,ToPort:80,CidrIp:"0.0.0.0/0",Description:"HTTP"},{IpProtocol:"tcp",FromPort:443,ToPort:443,CidrIp:"0.0.0.0/0",Description:"HTTPS"}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound"}],Tags:[{Key:"Name",Value:`${$}-${M}-alb-sg`},{Key:"Environment",Value:M}]}});let V=`${$}${M}ECSSecurityGroup`.replace(/[^a-zA-Z0-9]/g,"");for(let[G,q]of Object.entries(J)){let A=q.port||3000;this.builder.addResource(V,{Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:`ECS tasks security group for ${$}-${M}`,VpcId:{Ref:"VPC"},SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:A,ToPort:A,SourceSecurityGroupId:{Ref:K},Description:"Allow traffic from ALB"}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound"}],Tags:[{Key:"Name",Value:`${$}-${M}-ecs-sg`},{Key:"Environment",Value:M}]}});let P=`${$}${M}TaskExecRole`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(P,{Type:"AWS::IAM::Role",Properties:{RoleName:`${$}-${M}-ecs-exec-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"],Policies:[{PolicyName:"ECRPullPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["ecr:GetAuthorizationToken","ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","logs:CreateLogStream","logs:PutLogEvents"],Resource:"*"}]}}]}});let E=`${$}${M}TaskRole`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(E,{Type:"AWS::IAM::Role",Properties:{RoleName:`${$}-${M}-ecs-task-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"TaskPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogStream","logs:PutLogEvents"],Resource:"*"},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:ListBucket"],Resource:"*"}]}}]}});let O=`${$}${M}${G}LogGroup`.replace(/[^a-zA-Z0-9]/g,""),F=`/ecs/${$}-${M}-${G}`;this.builder.addResource(O,{Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:F,RetentionInDays:30}});let R=`${$}${M}${G}TaskDef`.replace(/[^a-zA-Z0-9]/g,""),W=String(q.cpu||512),Z=String(q.memory||1024);this.builder.addResource(R,{Type:"AWS::ECS::TaskDefinition",Properties:{Family:`${$}-${M}-${G}`,NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:W,Memory:Z,ExecutionRoleArn:{"Fn::GetAtt":[P,"Arn"]},TaskRoleArn:{"Fn::GetAtt":[E,"Arn"]},ContainerDefinitions:[{Name:G,Image:{"Fn::Sub":`\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.amazonaws.com/${$}:latest`},Essential:!0,PortMappings:[{ContainerPort:A,Protocol:"tcp"}],LogConfiguration:{LogDriver:"awslogs",Options:{"awslogs-group":F,"awslogs-region":{Ref:"AWS::Region"},"awslogs-stream-prefix":G}},HealthCheck:{Command:["CMD-SHELL",`curl -f http://localhost:${A}${q.healthCheck||"/health"} || exit 1`],Interval:30,Timeout:5,Retries:3,StartPeriod:60}}],Tags:[{Key:"Name",Value:`${$}-${M}-${G}`},{Key:"Environment",Value:M}]},DependsOn:[P,E,O]});let H=`${$}${M}ALB`.replace(/[^a-zA-Z0-9]/g,"");if(X?.enabled!==!1){this.builder.addResource(H,{Type:"AWS::ElasticLoadBalancingV2::LoadBalancer",Properties:{Name:`${$}-${M}-alb`,Scheme:"internet-facing",Type:"application",Subnets:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}],SecurityGroups:[{Ref:K}],Tags:[{Key:"Name",Value:`${$}-${M}-alb`},{Key:"Environment",Value:M}]}});let z=`${$}${M}TargetGroup`.replace(/[^a-zA-Z0-9]/g,""),x=X?.healthCheck?.path||q.healthCheck||"/health";this.builder.addResource(z,{Type:"AWS::ElasticLoadBalancingV2::TargetGroup",Properties:{Name:`${$}-${M}-tg`,Port:A,Protocol:"HTTP",VpcId:{Ref:"VPC"},TargetType:"ip",HealthCheckPath:x,HealthCheckIntervalSeconds:X?.healthCheck?.interval||30,HealthyThresholdCount:X?.healthCheck?.healthyThreshold||2,UnhealthyThresholdCount:X?.healthCheck?.unhealthyThreshold||5,HealthCheckTimeoutSeconds:10,Tags:[{Key:"Name",Value:`${$}-${M}-tg`},{Key:"Environment",Value:M}]}});let N=`${$}${M}HTTPListener`.replace(/[^a-zA-Z0-9]/g,"");if(Y?.enabled&&Y?.redirectHttp)this.builder.addResource(N,{Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:{Ref:H},Port:80,Protocol:"HTTP",DefaultActions:[{Type:"redirect",RedirectConfig:{Protocol:"HTTPS",Port:"443",StatusCode:"HTTP_301"}}]}});else this.builder.addResource(N,{Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:{Ref:H},Port:80,Protocol:"HTTP",DefaultActions:[{Type:"forward",TargetGroupArn:{Ref:z}}]}});if(Y?.enabled){let D=Y.certificateArn||(Q?{Ref:Q}:void 0);if(D){let k=`${$}${M}HTTPSListener`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(k,{Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:{Ref:H},Port:443,Protocol:"HTTPS",Certificates:[{CertificateArn:D}],DefaultActions:[{Type:"forward",TargetGroupArn:{Ref:z}}],SslPolicy:"ELBSecurityPolicy-TLS13-1-2-2021-06"}})}}let B=`${$}${M}${G}Service`.replace(/[^a-zA-Z0-9]/g,""),T=q.desiredCount||1;this.builder.addResource(B,{Type:"AWS::ECS::Service",Properties:{ServiceName:`${$}-${M}-${G}`,Cluster:{Ref:_},TaskDefinition:{Ref:R},DesiredCount:T,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{AssignPublicIp:"ENABLED",SecurityGroups:[{Ref:V}],Subnets:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]}},LoadBalancers:[{ContainerName:G,ContainerPort:A,TargetGroupArn:{Ref:z}}],HealthCheckGracePeriodSeconds:120,Tags:[{Key:"Name",Value:`${$}-${M}-${G}`},{Key:"Environment",Value:M}]},DependsOn:[R,N,z]});let S=q.autoScaling;if(S){let D=`${$}${M}${G}ScalableTarget`.replace(/[^a-zA-Z0-9]/g,"");if(this.builder.addResource(D,{Type:"AWS::ApplicationAutoScaling::ScalableTarget",Properties:{MaxCapacity:S.max||10,MinCapacity:S.min||1,ResourceId:{"Fn::Sub":`service/\${${_}}/${$}-${M}-${G}`},ScalableDimension:"ecs:service:DesiredCount",ServiceNamespace:"ecs",RoleARN:{"Fn::Sub":"arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService"}},DependsOn:B}),S.targetCpuUtilization)this.builder.addResource(`${$}${M}${G}CPUScaling`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::ApplicationAutoScaling::ScalingPolicy",Properties:{PolicyName:`${$}-${M}-${G}-cpu-scaling`,PolicyType:"TargetTrackingScaling",ScalingTargetId:{Ref:D},TargetTrackingScalingPolicyConfiguration:{PredefinedMetricSpecification:{PredefinedMetricType:"ECSServiceAverageCPUUtilization"},TargetValue:S.targetCpuUtilization,ScaleInCooldown:300,ScaleOutCooldown:60}}});if(S.targetMemoryUtilization)this.builder.addResource(`${$}${M}${G}MemoryScaling`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::ApplicationAutoScaling::ScalingPolicy",Properties:{PolicyName:`${$}-${M}-${G}-memory-scaling`,PolicyType:"TargetTrackingScaling",ScalingTargetId:{Ref:D},TargetTrackingScalingPolicyConfiguration:{PredefinedMetricSpecification:{PredefinedMetricType:"ECSServiceAverageMemoryUtilization"},TargetValue:S.targetMemoryUtilization,ScaleInCooldown:300,ScaleOutCooldown:60}}})}if(U?.domain&&U?.hostedZoneId)this.builder.addResource(`${$}${M}ApiDnsRecord`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:U.hostedZoneId,Name:`api.${U.domain}`,Type:"A",AliasTarget:{DNSName:{"Fn::GetAtt":[H,"DNSName"]},HostedZoneId:{"Fn::GetAtt":[H,"CanonicalHostedZoneID"]}}}});this.builder.addOutput("ECSClusterArn",{Description:"ECS Cluster ARN",Value:{"Fn::GetAtt":[_,"Arn"]},Export:{Name:{"Fn::Sub":"${AWS::StackName}-ecs-cluster-arn"}}}),this.builder.addOutput("ECSServiceName",{Description:"ECS Service Name",Value:`${$}-${M}-${G}`,Export:{Name:{"Fn::Sub":"${AWS::StackName}-ecs-service-name"}}}),this.builder.addOutput("LoadBalancerDNS",{Description:"Application Load Balancer DNS Name",Value:{"Fn::GetAtt":[H,"DNSName"]},Export:{Name:{"Fn::Sub":"${AWS::StackName}-alb-dns"}}})}else{let z=`${$}${M}${G}Service`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(z,{Type:"AWS::ECS::Service",Properties:{ServiceName:`${$}-${M}-${G}`,Cluster:{Ref:_},TaskDefinition:{Ref:R},DesiredCount:q.desiredCount||1,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{AssignPublicIp:"ENABLED",SecurityGroups:[{Ref:V}],Subnets:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]}},Tags:[{Key:"Name",Value:`${$}-${M}-${G}`},{Key:"Environment",Value:M}]},DependsOn:[R]})}break}}generateServerless($,M){if(this.mergedConfig.infrastructure?.functions)for(let[J,X]of Object.entries(this.mergedConfig.infrastructure.functions)){if(!this.shouldDeploy(X))continue;let{role:Y,logicalId:U}=B0.createRole({slug:$,environment:M,roleName:`${$}-${M}-${J}-role`,servicePrincipal:"lambda.amazonaws.com",managedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]});this.builder.addResource(U,Y);let{lambdaFunction:Q,logicalId:_}=j.createLambdaFunction({slug:$,environment:M,functionName:`${$}-${M}-${J}`,handler:X.handler||"index.handler",runtime:X.runtime||"nodejs20.x",code:{zipFile:X.code||"export const handler = async () => ({ statusCode: 200 });"},role:U,timeout:X.timeout,memorySize:X.memorySize});this.builder.addResource(_,Q)}if(this.mergedConfig.infrastructure?.api){let{restApi:J,logicalId:X}=T0.createRestApi({slug:$,environment:M,apiName:`${$}-${M}-api`});this.builder.addResource(X,J)}}generateServer($,M){if(!this.mergedConfig.infrastructure?.servers)return;let J=this.mergedConfig.infrastructure.servers,X=this.mergedConfig.infrastructure?.compute,Y=this.mergedConfig.infrastructure?.ssl;if(Object.values(J).some((Q)=>!Q.privateNetwork||Q.privateNetwork==="create"))this.generateNetworkInfrastructure($,M);for(let[Q,_]of Object.entries(J)){let K=_.instanceType||_.size||X?.size,G=(K?j.InstanceSize.specs[K]:void 0)?.instanceType||K||"t3.micro",q=_.type||"app",A=_.userData||_.startupScript;if(!A)A=j.UserData.generateAppServerScript({runtime:"bun",runtimeVersion:_.bunVersion||"latest",webServer:"none",domain:_.domain,enableSsl:!!Y?.enabled,sslEmail:Y?.letsEncrypt?.email,installRedis:q==="cache",installDatabaseClients:!!_.database});let P=_.privateNetwork&&_.privateNetwork!=="create"?_.privateNetwork:{Ref:"VPC"},E=_.subnet||{Ref:"PublicSubnet1"},F=!!this.mergedConfig.infrastructure?.email?.server?.enabled,R=[22,80,443,this.resolveApiOriginPort()];if(F)R.push(25,465,587,143,993);let W=j.createServerModeStack({slug:`${$}-${Q}`,environment:M,vpcId:P,subnetId:E,instanceType:G,keyName:_.keyName||`${$}-${M}`,domain:_.domain,userData:A,volumeSize:_.diskSize||20,imageId:_.image,allowedPorts:R});for(let[Z,H]of Object.entries(W.resources))this.builder.addResource(Z,H);this.serverEipLogicalIds.set(Q,W.outputs.eipLogicalId),this.serverEipLogicalIds.set(`${Q}Instance`,W.outputs.instanceLogicalId),this.builder.addOutput(`${Q}InstanceId`,{Value:{Ref:W.outputs.instanceLogicalId},Description:`Instance ID for ${Q} server`}),this.builder.addOutput(`${Q}PublicIp`,{Value:{Ref:W.outputs.eipLogicalId},Description:`Public IP for ${Q} server`})}}generateComputeApp($,M){let J=this.mergedConfig.infrastructure?.compute;if(!J)return;let X=this.mergedConfig.sites||{},Y=Object.entries(X),Q=this.mergedConfig.infrastructure?.dns?.domain,_=this.mergedConfig.infrastructure?.database,K=J.size,G=(K?j.InstanceSize.specs[K]:void 0)?.instanceType||K||"t3.micro";if(!this.builder.hasResource("VPC"))this.generateNetworkInfrastructure($,M);let q=this.buildCaddyfile(Y),A=j.UserData.generateBunAppScript({runtime:J.runtime||"bun",runtimeVersion:J.runtimeVersion||"latest",systemPackages:J.systemPackages,database:_,caddyfile:q}),P=D0(J.appUpdates),E=P.length>0?`${A}
11
+ ${P.join(`
12
12
  `)}
13
- `:A,m=o.map(([,S])=>S.port).filter((S)=>typeof S==="number"&&![80,443].includes(S)),a=this.resolveApiOriginPort(),y=`${e}${t}DeployBucket`.replace(/[^a-zA-Z0-9]/g,""),i=`${e}-${t}-deploy`;this.builder.addResource(y,{Type:"AWS::S3::Bucket",Properties:{BucketName:i,PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},LifecycleConfiguration:{Rules:[{Id:"expire-old-releases",Status:"Enabled",ExpirationInDays:7,Prefix:"releases/"}]},Tags:[{Key:"Project",Value:e},{Key:"Environment",Value:t},{Key:"ManagedBy",Value:"ts-cloud"}]}});let p=w.createServerModeStack({slug:`${e}-app`,environment:t,vpcId:{Ref:"VPC"},subnetId:{Ref:"PublicSubnet1"},instanceType:d,keyName:r.allowSsh?`${e}-${t}`:void 0,domain:c,userData:g,volumeSize:r.disk?.size||20,imageId:r.image,allowedPorts:[...r.allowSsh?[22]:[],80,443,a,...m]}),f=p.resources[p.outputs.instanceLogicalId];if(f?.Properties){let S=f.Properties.Tags||[];f.Properties.Tags=[...S,{Key:"Project",Value:e},{Key:"Environment",Value:t},{Key:"Role",Value:"app"},{Key:"ManagedBy",Value:"ts-cloud"}]}let C=p.resources[p.outputs.roleLogicalId];if(C?.Properties)C.Properties.Policies=C.Properties.Policies||[],C.Properties.Policies.push({PolicyName:"DeployBucketRead",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["s3:GetObject","s3:ListBucket"],Resource:[`arn:aws:s3:::${i}`,`arn:aws:s3:::${i}/*`]}]}});for(let[S,R]of Object.entries(p.resources))this.builder.addResource(S,R);this.builder.addOutput("deployBucketName",{Value:{Ref:y},Description:"S3 bucket where release tarballs are uploaded"}),this.builder.addOutput("appInstanceId",{Value:{Ref:p.outputs.instanceLogicalId},Description:"EC2 instance ID for the app server"}),this.builder.addOutput("appPublicIp",{Value:{Ref:p.outputs.eipLogicalId},Description:"Public IP for the app server"}),this.serverEipLogicalIds.set("app",p.outputs.eipLogicalId),this.serverEipLogicalIds.set("appInstance",p.outputs.instanceLogicalId)}generateJumpBox(e,t){let r=this.mergedConfig.infrastructure?.jumpBox;if(!r)return;let n=r===!0?{}:r;if(n.enabled===!1)return;this.generateNetworkInfrastructure(e,t);let o=n.size||"micro",c=w.InstanceSize.specs[o]?.instanceType||o||"t3.micro",s;if(n.mountEfs)s={fileSystemId:typeof n.mountEfs==="string"?n.mountEfs:{Ref:"FileSystem"},mountPath:n.mountPath||"/mnt/efs"};let u;if(n.databaseTools)u=w.JumpBox.withDatabaseTools({slug:e,environment:t,vpcId:{Ref:"VPC"},subnetId:{Ref:"PublicSubnet1"},keyName:n.keyName||`${e}-${t}`,allowedCidrs:n.allowedCidrs});else if(s)u=w.JumpBox.withEfsMount({slug:e,environment:t,vpcId:{Ref:"VPC"},subnetId:{Ref:"PublicSubnet1"},keyName:n.keyName||`${e}-${t}`,fileSystemId:s.fileSystemId,mountPath:s.mountPath,allowedCidrs:n.allowedCidrs});else u=w.createJumpBox({slug:e,environment:t,vpcId:{Ref:"VPC"},subnetId:{Ref:"PublicSubnet1"},keyName:n.keyName||`${e}-${t}`,instanceType:c,allowedCidrs:n.allowedCidrs,mountEfs:s});for(let[h,d]of Object.entries(u.resources))this.builder.addResource(h,d);this.builder.addOutput("JumpBoxInstanceId",{Value:{Ref:u.instanceLogicalId},Description:"The ID of the JumpBox EC2 instance (use with SSM Session Manager or SSH)"})}generateSharedInfrastructure(e,t){let r=this.mergedConfig.infrastructure?.ssl,n=this.mergedConfig.infrastructure?.dns,o=n?.domain,l=n?.hostedZoneId,c=[],s,u;if(r?.certificateArn)u=r.certificateArn;else if(r?.enabled&&o&&l){let m=r.domains||[o],a=m[0],y=m.slice(1).map((f)=>{if(f.includes(".")&&f.endsWith(a))return f.replace(`.${a}`,"");return f}),{certificate:i,logicalId:p}=te.createCertificate({domain:a,subdomains:y,slug:e,environment:t,validationMethod:"DNS",hostedZoneId:l});s=p,this.builder.addResource(p,i)}if(this.mergedConfig.infrastructure?.storage){let m=Object.entries(this.mergedConfig.infrastructure.storage).some(([,i])=>i.website),a;if(m&&(s||u))a=`${e}${t}CloudFrontOAC`.replace(/[^a-zA-Z0-9]/g,""),this.builder.addResource(a,{Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${e}-${t}-s3-oac`,Description:`OAC for ${e} ${t} S3 website buckets`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}});let y=Object.entries(this.mergedConfig.infrastructure.storage).map(([i,p])=>({name:i,config:p,mountPath:this.normalizeMountPath(p),rewriteStyle:p.pathRewriteStyle||"directory",logicalId:this.storageBucketLogicalId(e,t,i)})).filter((i)=>i.name!=="public"&&i.config.website&&i.mountPath);for(let[i,p]of Object.entries(this.mergedConfig.infrastructure.storage)){let f=!!(p.website&&a),C=this.storageBucketName(e,t,i),{bucket:S,logicalId:R}=ee.createBucket({slug:e,name:i,environment:t,bucketName:C,versioning:p.versioning,encryption:p.encryption,public:f?!1:p.public});if(f&&S.Properties)S.Properties.PublicAccessBlockConfiguration={BlockPublicAcls:!0,IgnorePublicAcls:!0,BlockPublicPolicy:!1,RestrictPublicBuckets:!1};if(this.builder.addResource(R,S),p.website){let D=typeof p.website==="object"?p.website:{},P=ee.enableWebsiteHosting(S,D.indexDocument||"index.html",D.errorDocument);this.builder.addResource(R,P)}let I=this.normalizeMountPath(p);if(f&&a&&o&&!(I&&i!=="public")){let D=`${e}${t}${i}CDN`.replace(/[^a-zA-Z0-9]/g,""),P=[];if(p.aliases&&p.aliases.length>0)P.push(...p.aliases);else if(i==="public"){if(P.push(o),r?.domains?.includes(`www.${o}`))P.push(`www.${o}`)}else if(i==="docs")P.push(`docs.${o}`);else if(i==="blog")P.push(`blog.${o}`);let v=typeof p.website==="object"?p.website:{},O=p.spa===!0,F=v.errorDocument||(O?"index.html":"404.html"),V=[];if(O)V.push({ErrorCode:403,ResponseCode:200,ResponsePagePath:"/index.html",ErrorCachingMinTTL:300},{ErrorCode:404,ResponseCode:200,ResponsePagePath:"/index.html",ErrorCachingMinTTL:300});else V.push({ErrorCode:403,ResponseCode:404,ResponsePagePath:`/${F}`,ErrorCachingMinTTL:300},{ErrorCode:404,ResponseCode:404,ResponsePagePath:`/${F}`,ErrorCachingMinTTL:300});let z=u&&P.length>0?{AcmCertificateArn:u,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}:s&&P.length>0?{AcmCertificateArn:{Ref:s},SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}:{CloudFrontDefaultCertificate:!0},_=`S3-${e}-${t}-${i}`,k=this.mergedConfig.project.region||"us-east-1",x;if(!O)x=`${e}${t}${i}UrlRewrite`.replace(/[^a-zA-Z0-9]/g,""),this.builder.addResource(x,{Type:"AWS::CloudFront::Function",Properties:{Name:`${e}-${t}-${i}-url-rewrite`,AutoPublish:!0,FunctionConfig:{Comment:`URL rewrite for ${e} ${t} ${i} - appends .html to extensionless paths`,Runtime:"cloudfront-js-2.0"},FunctionCode:`function handler(event) { var request = event.request; var uri = request.uri; if (uri.endsWith('/')) { request.uri += 'index.html'; }
14
- else if (!uri.includes('.')) { request.uri += '.html'; } return request; }`}});let Y=[{Id:_,DomainName:{"Fn::Sub":`\${${R}}.s3.${k}.amazonaws.com`},OriginPath:"",S3OriginConfig:{OriginAccessIdentity:""},OriginAccessControlId:{Ref:a}}],G=[],Q=[];if(this.shouldRouteStorageBucketToCompute(i,p)){this.appendComputeAppOrigin(Y,G,Q,e,t,this.resolveComputeCachePathPatterns(p.computeRoutes));for(let E of y){let U=`S3-${e}-${t}-${E.name}`,X=`${e}${t}${E.name}PathMountRewrite`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(X,{Type:"AWS::CloudFront::Function",Properties:{Name:`${e}-${t}-${E.name}-path-mount-rewrite`,AutoPublish:!0,FunctionConfig:{Comment:`Path mount rewrite for ${e} ${t} ${E.name} at ${E.mountPath}`,Runtime:"cloudfront-js-2.0"},FunctionCode:this.pathMountRewriteFunctionCode(E.mountPath,E.rewriteStyle)}}),Y.push({Id:U,DomainName:{"Fn::Sub":`\${${E.logicalId}}.s3.${k}.amazonaws.com`},OriginPath:"",S3OriginConfig:{OriginAccessIdentity:""},OriginAccessControlId:{Ref:a}}),Q.push(E.logicalId,X);for(let Ve of[E.mountPath,`${E.mountPath}/*`])G.push({PathPattern:Ve,TargetOriginId:U,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,CachePolicyId:"4135ea2d-6df8-44a3-9df3-4b5a84be39ad",FunctionAssociations:[{EventType:"viewer-request",FunctionARN:{"Fn::GetAtt":[X,"FunctionARN"]}}]})}}let me={Type:"AWS::CloudFront::Distribution",DependsOn:[R,a,...x?[x]:[],...Q],Properties:{DistributionConfig:{Enabled:!0,Comment:`${e} ${t} ${i} site`,DefaultRootObject:"index.html",Origins:Y,DefaultCacheBehavior:{TargetOriginId:_,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,CachePolicyId:"658327ea-f89d-4fab-a63d-7e88639e58f6",...x?{FunctionAssociations:[{EventType:"viewer-request",FunctionARN:{"Fn::GetAtt":[x,"FunctionARN"]}}]}:{}},...G.length>0?{CacheBehaviors:G}:{},...P.length>0?{Aliases:P}:{},ViewerCertificate:z,PriceClass:"PriceClass_100",HttpVersion:"http2and3",IPV6Enabled:!0,CustomErrorResponses:V}}};if(s)me.DependsOn.push(s);this.builder.addResource(D,me);let Fe=`${R}CloudFrontPolicy`;if(this.builder.addResource(Fe,{Type:"AWS::S3::BucketPolicy",DependsOn:[R,D],Properties:{Bucket:{Ref:R},PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowCloudFrontServicePrincipal",Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:{"Fn::Sub":`arn:aws:s3:::\${${R}}/*`},Condition:{StringEquals:{"AWS:SourceArn":{"Fn::Sub":`arn:aws:cloudfront::\${AWS::AccountId}:distribution/\${${D}}`}}}}]}}}),this.shouldRouteStorageBucketToCompute(i,p))for(let E of y){let U=`${E.logicalId}CloudFrontPolicy`;this.builder.addResource(U,{Type:"AWS::S3::BucketPolicy",DependsOn:[E.logicalId,D],Properties:{Bucket:{Ref:E.logicalId},PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowCloudFrontServicePrincipal",Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:{"Fn::Sub":`arn:aws:s3:::\${${E.logicalId}}/*`},Condition:{StringEquals:{"AWS:SourceArn":{"Fn::Sub":`arn:aws:cloudfront::\${AWS::AccountId}:distribution/\${${D}}`}}}}]}}})}if(P.length>0)c.push({name:i,bucketLogicalId:R,distLogicalId:D,oacLogicalId:a,aliases:P});this.builder.addOutput(`${i}CloudFrontDomain`,{Value:{"Fn::GetAtt":[D,"DomainName"]},Description:`CloudFront domain for ${i}`}),this.builder.addOutput(`${i}CloudFrontDistributionId`,{Value:{Ref:D},Description:`CloudFront distribution ID for ${i}`})}if(this.builder.addOutput(`${i}BucketName`,{Value:{Ref:R},Description:`S3 bucket name for ${i}`}),i==="public")this.builder.addOutput("FrontendBucketName",{Value:{Ref:R},Description:"Frontend S3 bucket name"});if(i==="docs")this.builder.addOutput("DocsBucketName",{Value:{Ref:R},Description:"Documentation S3 bucket name"});if(i==="blog")this.builder.addOutput("BlogBucketName",{Value:{Ref:R},Description:"Blog S3 bucket name"})}}if(this.mergedConfig.infrastructure?.sftp){let m=this.mergedConfig.infrastructure.sftp,a=Te.create({...m,storage:this.resolveSftpStorage(m,e,t)??m.storage,slug:e,environment:t});for(let[y,i]of Object.entries(a.resources))this.builder.addResource(y,i);this.builder.addOutput("SftpServerId",{Value:{Ref:a.serverLogicalId},Description:"AWS Transfer Family SFTP server ID"}),this.builder.addOutput("SftpEndpoint",{Value:{"Fn::Sub":`\${${a.serverLogicalId}}.server.transfer.\${AWS::Region}.amazonaws.com`},Description:"AWS Transfer Family SFTP endpoint"}),this.builder.addOutput("SftpStorageDomain",{Value:a.domain,Description:"Storage backing the SFTP server (EFS or S3)"})}if(l&&c.length>0)for(let{name:m,distLogicalId:a,aliases:y}of c)for(let i of y){let p=i.replace(/\./g,"").replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(`${p}ARecord`,{Type:"AWS::Route53::RecordSet",DependsOn:[a],Properties:{HostedZoneId:l,Name:i,Type:"A",AliasTarget:{DNSName:{"Fn::GetAtt":[a,"DomainName"]},HostedZoneId:"Z2FDTNDATAQYW2",EvaluateTargetHealth:!1}}}),this.builder.addResource(`${p}AAAARecord`,{Type:"AWS::Route53::RecordSet",DependsOn:[a],Properties:{HostedZoneId:l,Name:i,Type:"AAAA",AliasTarget:{DNSName:{"Fn::GetAtt":[a,"DomainName"]},HostedZoneId:"Z2FDTNDATAQYW2",EvaluateTargetHealth:!1}}})}if(this.mergedConfig.infrastructure?.databases){for(let[m,a]of Object.entries(this.mergedConfig.infrastructure.databases))if(a.engine==="dynamodb"){let{table:y,logicalId:i}=q.createTable({slug:e,environment:t,tableName:`${e}-${t}-${m}`,partitionKey:a.partitionKey||{name:"id",type:"S"},sortKey:a.sortKey});this.builder.addResource(i,y)}else if(a.engine==="postgres"){let{dbInstance:y,logicalId:i}=q.createPostgres({slug:e,environment:t,dbInstanceIdentifier:`${e}-${t}-${m}`,masterUsername:a.username||"admin",masterUserPassword:a.password||"changeme123",allocatedStorage:a.storage||20,dbInstanceClass:a.instanceClass||"db.t3.micro"});this.builder.addResource(i,y)}else if(a.engine==="mysql"){let{dbInstance:y,logicalId:i}=q.createMysql({slug:e,environment:t,dbInstanceIdentifier:`${e}-${t}-${m}`,masterUsername:a.username||"admin",masterUserPassword:a.password||"changeme123",allocatedStorage:a.storage||20,dbInstanceClass:a.instanceClass||"db.t3.micro"});this.builder.addResource(i,y)}}if(this.mergedConfig.infrastructure?.cdn)for(let[m,a]of Object.entries(this.mergedConfig.infrastructure.cdn)){if(!a.origin)continue;let y=typeof a.customDomain==="string"?a.customDomain:a.customDomain?.domain||a.domain,i=typeof a.customDomain==="object"?a.customDomain?.certificateArn:a.certificateArn,p=i||u,f=`${e}${t}${m}CDN`.replace(/[^a-zA-Z0-9]/g,""),C=`S3-${e}-${t}-${m}-cdn`,S=[{Id:C,DomainName:a.origin,OriginPath:"",S3OriginConfig:{OriginAccessIdentity:""},OriginShield:a.originShield?{Enabled:!0,OriginShieldRegion:a.originShieldRegion||this.mergedConfig.environments[t]?.region||this.mergedConfig.project.region||"us-east-1"}:{Enabled:!1}}],R=[],I=[];if(a.routeCompute)this.appendComputeAppOrigin(S,R,I,e,t,this.resolveComputeCachePathPatterns(a.computeRoutes));let D=p&&y?{AcmCertificateArn:s&&!i?{Ref:s}:p,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}:{CloudFrontDefaultCertificate:!0},P=[...I];if(s&&!i&&y)P.push(s);let v={Type:"AWS::CloudFront::Distribution",...P.length>0?{DependsOn:P}:{},Properties:{DistributionConfig:{Enabled:!0,Comment:`${e} ${t} ${m} CDN`,DefaultRootObject:"index.html",Origins:S,DefaultCacheBehavior:{TargetOriginId:C,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:a.compress!==!1,CachePolicyId:"658327ea-f89d-4fab-a63d-7e88639e58f6"},...R.length>0?{CacheBehaviors:R}:{},...y&&p?{Aliases:[y]}:{},ViewerCertificate:D,PriceClass:"PriceClass_100",HttpVersion:a.http3?"http2and3":"http2"}}};if(this.builder.addResource(f,v),l&&y&&p){let O=y.replace(/\./g,"").replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(`${O}CdnARecord`,{Type:"AWS::Route53::RecordSet",DependsOn:[f,...s&&!i?[s]:[]],Properties:{HostedZoneId:l,Name:y,Type:"A",AliasTarget:{HostedZoneId:"Z2FDTNDATAQYW2",DNSName:{"Fn::GetAtt":[f,"DomainName"]}}}})}}if(this.mergedConfig.infrastructure?.queues)for(let[m,a]of Object.entries(this.mergedConfig.infrastructure.queues)){if(!this.shouldDeploy(a))continue;let{queue:y,logicalId:i}=re.createQueue({slug:e,environment:t,name:`${e}-${t}-${m}`,fifo:a.fifo,visibilityTimeout:a.visibilityTimeout,messageRetentionPeriod:a.messageRetentionPeriod,delaySeconds:a.delaySeconds,maxMessageSize:a.maxMessageSize,receiveMessageWaitTime:a.receiveMessageWaitTime,contentBasedDeduplication:a.contentBasedDeduplication,encrypted:a.encrypted,kmsKeyId:a.kmsKeyId});this.builder.addResource(i,y);let p;if(a.deadLetterQueue){let{deadLetterQueue:f,updatedSourceQueue:C,deadLetterLogicalId:S}=re.createDeadLetterQueue(i,{slug:e,environment:t,maxReceiveCount:a.maxReceiveCount});p=S,this.builder.addResource(S,f);let I=this.builder.getResources()[i];if(I?.Properties)I.Properties.RedrivePolicy=C.Properties?.RedrivePolicy}if(a.trigger){let f=a.trigger,C=`${e}${t}${f.functionName}`.replace(/[^a-zA-Z0-9]/g,""),S={Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:{"Fn::GetAtt":[i,"Arn"]},FunctionName:{Ref:C},BatchSize:f.batchSize||10,MaximumBatchingWindowInSeconds:f.batchWindow||0,Enabled:!0,...f.reportBatchItemFailures!==!1&&{FunctionResponseTypes:["ReportBatchItemFailures"]},...f.maxConcurrency&&{ScalingConfig:{MaximumConcurrency:f.maxConcurrency}},...f.filterPattern&&{FilterCriteria:{Filters:[{Pattern:JSON.stringify(f.filterPattern)}]}}},DependsOn:[i,C]};this.builder.addResource(`${i}Trigger`,S)}if(a.alarms?.enabled){let f=a.alarms,C=f.notificationTopicArn;if(!C&&f.notificationEmails?.length){let I=`${i}AlarmTopic`;this.builder.addResource(I,{Type:"AWS::SNS::Topic",Properties:{TopicName:`${e}-${t}-${m}-alarms`,DisplayName:`${m} Queue Alarms`}}),f.notificationEmails.forEach((D,P)=>{this.builder.addResource(`${I}Sub${P}`,{Type:"AWS::SNS::Subscription",Properties:{TopicArn:{Ref:I},Protocol:"email",Endpoint:D}})}),C={Ref:I}}let S=f.queueDepthThreshold||1000;this.builder.addResource(`${i}DepthAlarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${e}-${t}-${m}-queue-depth`,AlarmDescription:`Queue ${m} depth exceeds ${S} messages`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Average",Period:300,EvaluationPeriods:2,Threshold:S,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:{"Fn::GetAtt":[i,"QueueName"]}}],...C&&{AlarmActions:[C],OKActions:[C]}}});let R=f.messageAgeThreshold||3600;if(this.builder.addResource(`${i}AgeAlarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${e}-${t}-${m}-message-age`,AlarmDescription:`Queue ${m} oldest message exceeds ${R} seconds`,MetricName:"ApproximateAgeOfOldestMessage",Namespace:"AWS/SQS",Statistic:"Maximum",Period:300,EvaluationPeriods:2,Threshold:R,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:{"Fn::GetAtt":[i,"QueueName"]}}],...C&&{AlarmActions:[C],OKActions:[C]}}}),p&&f.dlqAlarm!==!1)this.builder.addResource(`${p}Alarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${e}-${t}-${m}-dlq-messages`,AlarmDescription:`Dead letter queue for ${m} has messages`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Sum",Period:300,EvaluationPeriods:1,Threshold:0,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:{"Fn::GetAtt":[p,"QueueName"]}}],...C&&{AlarmActions:[C]}}})}if(a.subscribe){let f=a.subscribe,C=f.topicArn;if(!C&&f.topicName)C={Ref:f.topicName};if(C){this.builder.addResource(`${i}SnsPolicy`,{Type:"AWS::SQS::QueuePolicy",Properties:{Queues:[{Ref:i}],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"sns.amazonaws.com"},Action:"sqs:SendMessage",Resource:{"Fn::GetAtt":[i,"Arn"]},Condition:{ArnEquals:{"aws:SourceArn":C}}}]}}});let S={TopicArn:C,Protocol:"sqs",Endpoint:{"Fn::GetAtt":[i,"Arn"]},RawMessageDelivery:f.rawMessageDelivery||!1};if(f.filterPolicy)S.FilterPolicy=f.filterPolicy,S.FilterPolicyScope=f.filterPolicyScope||"MessageAttributes";this.builder.addResource(`${i}SnsSub`,{Type:"AWS::SNS::Subscription",Properties:S,DependsOn:`${i}SnsPolicy`})}}}if(this.mergedConfig.infrastructure?.realtime?.enabled)if((this.mergedConfig.infrastructure.realtime.mode||"serverless")==="server")this.generateRealtimeServerResources(e,t);else this.generateRealtimeResources(e,t);let h=this.mergedConfig.infrastructure?.redirects;if(h){let m=h.target||this.mergedConfig.infrastructure?.dns?.domain||"",a=h.protocol||"https";if(h.domains?.length&&m)for(let y of h.domains){let{bucket:i,bucketPolicy:p,logicalId:f,policyLogicalId:C}=Z.createDomainRedirectBucket({slug:e,environment:t,sourceDomain:y,targetDomain:m,protocol:a});this.builder.addResource(f,i),this.builder.addResource(C,p)}if(h.paths&&Object.keys(h.paths).length>0){let y=Z.fromMapping(h.paths,{statusCode:h.statusCode||301}),{function:i,logicalId:p}=Z.createPathRedirectFunction({slug:e,environment:t,rules:y});this.builder.addResource(p,i)}}if(this.mergedConfig.infrastructure?.monitoring?.alarms)for(let[m,a]of Object.entries(this.mergedConfig.infrastructure.monitoring.alarms)){let{alarm:y,logicalId:i}=Ie.createAlarm({slug:e,environment:t,alarmName:`${e}-${t}-${m}`,metricName:a.metricName||"Errors",namespace:a.namespace||"AWS/Lambda",threshold:a.threshold||1,comparisonOperator:a.comparisonOperator||"GreaterThanThreshold"});this.builder.addResource(i,y)}let d=this.mergedConfig.infrastructure?.cache;if(d){let m=d.type||"redis";if(m==="redis"){this.generateNetworkInfrastructure(e,t);let a=d.redis||{},{replicationGroup:y,subnetGroup:i,logicalId:p,subnetGroupId:f}=ne.createRedis({slug:e,environment:t,nodeType:a.nodeType||d.nodeType||"cache.t3.micro",engineVersion:a.engineVersion||"7.1",port:a.port||6379,numCacheClusters:a.numCacheNodes||2,automaticFailover:a.automaticFailoverEnabled!==!1,atRestEncryption:!0,transitEncryption:!0,snapshotRetentionDays:a.snapshotRetentionLimit||7,snapshotWindow:a.snapshotWindow,subnetIds:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]});if(this.builder.addResource(p,y),i&&f)this.builder.addResource(f,i);this.builder.addOutput("CacheEndpoint",{Value:{"Fn::GetAtt":[p,"PrimaryEndPoint.Address"]},Description:"Redis primary endpoint address"}),this.builder.addOutput("CachePort",{Value:{"Fn::GetAtt":[p,"PrimaryEndPoint.Port"]},Description:"Redis primary endpoint port"})}else if(m==="memcached"){this.generateNetworkInfrastructure(e,t);let a=d.elasticache||{},{cluster:y,subnetGroup:i,logicalId:p,subnetGroupId:f}=ne.createMemcached({slug:e,environment:t,nodeType:a.nodeType||d.nodeType||"cache.t3.micro",engineVersion:a.engineVersion||"1.6.22",numCacheNodes:a.numCacheNodes||2,subnetIds:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]});if(this.builder.addResource(p,y),i&&f)this.builder.addResource(f,i);this.builder.addOutput("CacheEndpoint",{Value:{"Fn::GetAtt":[p,"ConfigurationEndpoint.Address"]},Description:"Memcached configuration endpoint address"})}}let b=this.mergedConfig.infrastructure?.email;if(b){let m=b.domain||this.mergedConfig.infrastructure?.dns?.domain;if(m){let{emailIdentity:a,logicalId:y}=L.verifyDomain({domain:m,slug:e,environment:t,enableDkim:b.enableDkim!==!1,dkimKeyLength:b.dkimKeyLength||"RSA_2048_BIT"});if(this.builder.addResource(y,a),b.configurationSet!==!1){let{configurationSet:f,logicalId:C}=L.createConfigurationSet({slug:e,environment:t});this.builder.addResource(C,f)}let i=b.hostedZoneId||this.mergedConfig.infrastructure?.dns?.hostedZoneId;if(i){if(b.enableDkim!==!1)for(let I=1;I<=3;I++){let D=`DkimRecord${I}${m.replace(/\./g,"")}`;this.builder.addResource(D,{Type:"AWS::Route53::RecordSet",DependsOn:[y],Properties:{HostedZoneId:i,Name:{"Fn::GetAtt":[y,`DkimDNSTokenName${I}`]},Type:"CNAME",TTL:1800,ResourceRecords:[{"Fn::GetAtt":[y,`DkimDNSTokenValue${I}`]}]}})}let{record:f,logicalId:C}=L.createSpfRecord(m,i);this.builder.addResource(C,f);let{record:S,logicalId:R}=L.createDmarcRecord(m,i,{policy:"none",reportingEmail:b.dmarcReportingEmail||`dmarc-reports@${m}`});this.builder.addResource(R,S)}this.builder.addOutput("EmailDomain",{Value:m,Description:"SES verified email domain"});let p=b.server;if(p?.enabled&&i){let f=this.mergedConfig.environments[t]?.region||this.mergedConfig.project.region||"us-east-1",C=`${e}-${t}-email`,{role:S,policy:R,roleLogicalId:I,policyLogicalId:D}=L.createEmailLambdaRole({slug:e,environment:t,s3BucketArn:`arn:aws:s3:::${C}`,sesIdentityArn:`arn:aws:ses:${f}:*:identity/${m}`});this.builder.addResource(I,S),this.builder.addResource(D,R);let{function:P,permission:v,logicalId:O,permissionLogicalId:F}=L.createInboundEmailLambda({slug:e,environment:t,roleArn:{"Fn::GetAtt":[I,"Arn"]},s3BucketName:C,organizedPrefix:"mailboxes/"});this.builder.addResource(O,P),this.builder.addResource(F,v);let V=L.createInboundEmailSetup({slug:e,environment:t,domain:m,s3BucketName:C,s3KeyPrefix:"inbox/",region:f,hostedZoneId:i,lambdaFunctionArn:{"Fn::GetAtt":[O,"Arn"]}});for(let[_,k]of Object.entries(V.resources)){if(k.Type==="AWS::SES::ReceiptRule")k.DependsOn=[F,O];this.builder.addResource(_,k)}this.builder.addOutput("InboundEmailLambda",{Value:{Ref:O},Description:"Inbound email processing Lambda function"}),this.builder.addOutput("EmailBucket",{Value:C,Description:"S3 bucket for email storage"});let z=this.serverEipLogicalIds.get("app");if(z&&i){let k=`${p?.subdomain||"mail"}.${m}`,x=k.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(`${x}ARecord`,{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:k,Type:"A",TTL:"300",ResourceRecords:[{Ref:z}]}})}this.builder.addOutput("MailHost",{Value:`mail.${m}`,Description:"Mail server hostname for SMTP/IMAP clients"})}}}let A=this.mergedConfig.infrastructure?.search;if(A){let m=A.vpc?{subnetIds:[{Ref:"PublicSubnet1"}],securityGroupIds:[]}:void 0;if(m)this.generateNetworkInfrastructure(e,t);let{domain:a,logicalId:y}=De.createDomain({slug:e,environment:t,engineVersion:A.engineVersion||"OpenSearch_2.11",instanceType:A.instanceType||"t3.small.search",instanceCount:A.instanceCount||1,volumeSize:A.volumeSize||10,volumeType:A.volumeType||"gp3",dedicatedMaster:A.dedicatedMaster||!1,dedicatedMasterType:A.dedicatedMasterType,dedicatedMasterCount:A.dedicatedMasterCount||3,multiAz:A.multiAz||!1,encryption:A.encryption||{atRest:!0,nodeToNode:!0},advancedSecurity:A.advancedSecurity,autoTune:A.autoTune!==!1,vpc:m});this.builder.addResource(y,a),this.builder.addOutput("SearchDomainEndpoint",{Value:{"Fn::GetAtt":[y,"DomainEndpoint"]},Description:"OpenSearch domain endpoint"}),this.builder.addOutput("SearchDomainArn",{Value:{"Fn::GetAtt":[y,"Arn"]},Description:"OpenSearch domain ARN"})}let T=this.mergedConfig.infrastructure?.fileSystem;if(T&&Object.keys(T).length>0){this.generateNetworkInfrastructure(e,t);for(let[m,a]of Object.entries(T)){let{fileSystem:y,logicalId:i}=K.createFileSystem({slug:`${e}-${m}`,environment:t,encrypted:a.encrypted!==!1,performanceMode:a.performanceMode||"generalPurpose",throughputMode:a.throughputMode||"bursting",enableBackup:!0});this.builder.addResource(i,y);let{securityGroup:p,logicalId:f}=K.createEfsSecurityGroup({slug:`${e}-${m}`,environment:t,vpcId:{Ref:"VPC"},sourceCidrBlocks:["10.0.0.0/16"]});this.builder.addResource(f,p);let{mountTargets:C,logicalIds:S}=K.createMultiAzMountTargets(i,{slug:`${e}-${m}`,environment:t,subnetIds:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}],securityGroupId:{Ref:f}});for(let R=0;R<C.length;R++)this.builder.addResource(S[R],C[R]);this.builder.addOutput(`${m}FileSystemId`,{Value:{Ref:i},Description:`EFS file system ID for ${m}`})}}let g=this.mergedConfig.infrastructure?.ai;if(g){let m=g.service||"ecs",a=g.models||["*"],y=g.allowStreaming!==!1,i;if(m==="ecs")i=M.enableBedrockForEcs({slug:e,environment:t,models:a,allowStreaming:y});else if(m==="ec2")i=M.enableBedrockForEc2({slug:e,environment:t,models:a,allowStreaming:y});else if(m==="lambda")i=M.enableBedrockForLambda({slug:e,environment:t,models:a,allowStreaming:y});else i=M.createBedrockRole(m,{slug:e,environment:t,models:a,allowStreaming:y});if(this.builder.addResource(i.logicalId,i.role),g.allowAsync){let{policy:p,logicalId:f}=M.createBedrockPolicy({slug:e,environment:t,models:a,allowStreaming:y,allowAsync:!0});this.builder.addResource(f,p)}this.builder.addOutput("BedrockRoleArn",{Value:{"Fn::GetAtt":[i.logicalId,"Arn"]},Description:"IAM role ARN with Bedrock permissions"})}}generateRealtimeResources(e,t){let r=this.mergedConfig.infrastructure?.realtime;if(!r)return;let n=r.name||`${e}-${t}-realtime`,o=r.scaling||{},l=r.storage||{type:"dynamodb"},c=o.handlerMemory||256,s=o.handlerTimeout||30,u=`${e}${t}RealtimeConnections`.replace(/[^a-zA-Z0-9]/g,""),h=`${e}${t}RealtimeChannels`.replace(/[^a-zA-Z0-9]/g,"");if(l.type==="dynamodb"){let S=l.dynamodb||{},R=S.billingMode||"PAY_PER_REQUEST";this.builder.addResource(u,{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e}-${t}-realtime-connections`,BillingMode:R,AttributeDefinitions:[{AttributeName:"connectionId",AttributeType:"S"},{AttributeName:"userId",AttributeType:"S"}],KeySchema:[{AttributeName:"connectionId",KeyType:"HASH"}],GlobalSecondaryIndexes:[{IndexName:"userId-index",KeySchema:[{AttributeName:"userId",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"},...R==="PROVISIONED"&&{ProvisionedThroughput:{ReadCapacityUnits:S.readCapacity||5,WriteCapacityUnits:S.writeCapacity||5}}}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0},...R==="PROVISIONED"&&{ProvisionedThroughput:{ReadCapacityUnits:S.readCapacity||5,WriteCapacityUnits:S.writeCapacity||5}},...S.pointInTimeRecovery&&{PointInTimeRecoverySpecification:{PointInTimeRecoveryEnabled:!0}},Tags:[{Key:"Name",Value:`${e}-${t}-realtime-connections`},{Key:"Environment",Value:t}]}}),this.builder.addResource(h,{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e}-${t}-realtime-channels`,BillingMode:R,AttributeDefinitions:[{AttributeName:"channel",AttributeType:"S"},{AttributeName:"connectionId",AttributeType:"S"}],KeySchema:[{AttributeName:"channel",KeyType:"HASH"},{AttributeName:"connectionId",KeyType:"RANGE"}],GlobalSecondaryIndexes:[{IndexName:"connectionId-index",KeySchema:[{AttributeName:"connectionId",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"},...R==="PROVISIONED"&&{ProvisionedThroughput:{ReadCapacityUnits:S.readCapacity||5,WriteCapacityUnits:S.writeCapacity||5}}}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0},...R==="PROVISIONED"&&{ProvisionedThroughput:{ReadCapacityUnits:S.readCapacity||5,WriteCapacityUnits:S.writeCapacity||5}},Tags:[{Key:"Name",Value:`${e}-${t}-realtime-channels`},{Key:"Environment",Value:t}]}})}let d=`${e}${t}RealtimeRole`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(d,{Type:"AWS::IAM::Role",Properties:{RoleName:`${e}-${t}-realtime-handler-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:"RealtimeHandlerPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:UpdateItem"],Resource:[{"Fn::GetAtt":[u,"Arn"]},{"Fn::Sub":`\${${u}.Arn}/index/*`},{"Fn::GetAtt":[h,"Arn"]},{"Fn::Sub":`\${${h}.Arn}/index/*`}]},{Effect:"Allow",Action:"execute-api:ManageConnections",Resource:{"Fn::Sub":"arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:*/*"}}]}}]}});let b=`${e}${t}RealtimeConnect`.replace(/[^a-zA-Z0-9]/g,""),A=`${e}${t}RealtimeDisconnect`.replace(/[^a-zA-Z0-9]/g,""),T=`${e}${t}RealtimeMessage`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(b,{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e}-${t}-realtime-connect`,Runtime:"nodejs20.x",Handler:"index.handler",Role:{"Fn::GetAtt":[d,"Arn"]},MemorySize:c,Timeout:s,Environment:{Variables:{CONNECTIONS_TABLE:{Ref:u},CHANNELS_TABLE:{Ref:h},ENVIRONMENT:t}},Code:{ZipFile:this.generateConnectHandlerCode()}},DependsOn:[d,u]}),this.builder.addResource(A,{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e}-${t}-realtime-disconnect`,Runtime:"nodejs20.x",Handler:"index.handler",Role:{"Fn::GetAtt":[d,"Arn"]},MemorySize:c,Timeout:s,Environment:{Variables:{CONNECTIONS_TABLE:{Ref:u},CHANNELS_TABLE:{Ref:h},ENVIRONMENT:t}},Code:{ZipFile:this.generateDisconnectHandlerCode()}},DependsOn:[d,u,h]}),this.builder.addResource(T,{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e}-${t}-realtime-message`,Runtime:"nodejs20.x",Handler:"index.handler",Role:{"Fn::GetAtt":[d,"Arn"]},MemorySize:c,Timeout:s,Environment:{Variables:{CONNECTIONS_TABLE:{Ref:u},CHANNELS_TABLE:{Ref:h},ENVIRONMENT:t}},Code:{ZipFile:this.generateMessageHandlerCode()}},DependsOn:[d,u,h]});let g=`${e}${t}RealtimeApi`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(g,{Type:"AWS::ApiGatewayV2::Api",Properties:{Name:n,ProtocolType:"WEBSOCKET",RouteSelectionExpression:"$request.body.action",Tags:{Name:n,Environment:t}}});let m=`${b}Permission`,a=`${A}Permission`,y=`${T}Permission`;this.builder.addResource(m,{Type:"AWS::Lambda::Permission",Properties:{FunctionName:{Ref:b},Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:{"Fn::Sub":`arn:aws:execute-api:\${AWS::Region}:\${AWS::AccountId}:\${${g}}/*/$connect`}}}),this.builder.addResource(a,{Type:"AWS::Lambda::Permission",Properties:{FunctionName:{Ref:A},Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:{"Fn::Sub":`arn:aws:execute-api:\${AWS::Region}:\${AWS::AccountId}:\${${g}}/*/$disconnect`}}}),this.builder.addResource(y,{Type:"AWS::Lambda::Permission",Properties:{FunctionName:{Ref:T},Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:{"Fn::Sub":`arn:aws:execute-api:\${AWS::Region}:\${AWS::AccountId}:\${${g}}/*/$default`}}});let i=`${g}ConnectInteg`,p=`${g}DisconnectInteg`,f=`${g}MessageInteg`;this.builder.addResource(i,{Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:{Ref:g},IntegrationType:"AWS_PROXY",IntegrationUri:{"Fn::Sub":`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${b}.Arn}/invocations`}}}),this.builder.addResource(p,{Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:{Ref:g},IntegrationType:"AWS_PROXY",IntegrationUri:{"Fn::Sub":`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${A}.Arn}/invocations`}}}),this.builder.addResource(f,{Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:{Ref:g},IntegrationType:"AWS_PROXY",IntegrationUri:{"Fn::Sub":`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${T}.Arn}/invocations`}}}),this.builder.addResource(`${g}ConnectRoute`,{Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:{Ref:g},RouteKey:"$connect",AuthorizationType:"NONE",Target:{"Fn::Sub":`integrations/\${${i}}`}}}),this.builder.addResource(`${g}DisconnectRoute`,{Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:{Ref:g},RouteKey:"$disconnect",Target:{"Fn::Sub":`integrations/\${${p}}`}}}),this.builder.addResource(`${g}DefaultRoute`,{Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:{Ref:g},RouteKey:"$default",Target:{"Fn::Sub":`integrations/\${${f}}`}}});let C=`${g}Stage`;if(this.builder.addResource(C,{Type:"AWS::ApiGatewayV2::Stage",Properties:{ApiId:{Ref:g},StageName:t,AutoDeploy:!0,DefaultRouteSettings:{ThrottlingBurstLimit:o.messagesPerSecond||1000,ThrottlingRateLimit:o.messagesPerSecond||1000}}}),r.monitoring?.enabled){let S=r.monitoring,R=S.notificationTopicArn;if(!R&&S.notificationEmails?.length){let I=`${g}AlarmTopic`;this.builder.addResource(I,{Type:"AWS::SNS::Topic",Properties:{TopicName:`${e}-${t}-realtime-alarms`,DisplayName:"Realtime WebSocket Alarms"}}),S.notificationEmails.forEach((D,P)=>{this.builder.addResource(`${I}Sub${P}`,{Type:"AWS::SNS::Subscription",Properties:{TopicArn:{Ref:I},Protocol:"email",Endpoint:D}})}),R={Ref:I}}if(S.connectionThreshold)this.builder.addResource(`${g}ConnectionAlarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${e}-${t}-realtime-connections`,AlarmDescription:`WebSocket connections exceed ${S.connectionThreshold}`,MetricName:"ConnectCount",Namespace:"AWS/ApiGateway",Statistic:"Sum",Period:300,EvaluationPeriods:2,Threshold:S.connectionThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"ApiId",Value:{Ref:g}}],...R&&{AlarmActions:[R]}}});if(S.errorThreshold)this.builder.addResource(`${g}ErrorAlarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${e}-${t}-realtime-errors`,AlarmDescription:`WebSocket errors exceed ${S.errorThreshold}/min`,MetricName:"ExecutionError",Namespace:"AWS/ApiGateway",Statistic:"Sum",Period:60,EvaluationPeriods:3,Threshold:S.errorThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"ApiId",Value:{Ref:g}}],...R&&{AlarmActions:[R]}}})}this.builder.addOutput(`${g}Endpoint`,{Description:"WebSocket API endpoint URL",Value:{"Fn::Sub":`wss://\${${g}}.execute-api.\${AWS::Region}.amazonaws.com/${t}`},Export:{Name:{"Fn::Sub":"${AWS::StackName}-realtime-endpoint"}}}),this.builder.addOutput(`${g}Id`,{Description:"WebSocket API ID",Value:{Ref:g},Export:{Name:{"Fn::Sub":"${AWS::StackName}-realtime-api-id"}}})}generateConnectHandlerCode(){return`
13
+ `:A,O=Y.map(([,x])=>x.port).filter((x)=>typeof x==="number"&&![80,443].includes(x)),F=this.resolveApiOriginPort(),R=`${$}${M}DeployBucket`.replace(/[^a-zA-Z0-9]/g,""),W=`${$}-${M}-deploy`;this.builder.addResource(R,{Type:"AWS::S3::Bucket",Properties:{BucketName:W,PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},LifecycleConfiguration:{Rules:[{Id:"expire-old-releases",Status:"Enabled",ExpirationInDays:7,Prefix:"releases/"}]},Tags:[{Key:"Project",Value:$},{Key:"Environment",Value:M},{Key:"ManagedBy",Value:"ts-cloud"}]}});let Z=j.createServerModeStack({slug:`${$}-app`,environment:M,vpcId:{Ref:"VPC"},subnetId:{Ref:"PublicSubnet1"},instanceType:G,keyName:J.allowSsh?`${$}-${M}`:void 0,domain:Q,userData:E,volumeSize:J.disk?.size||20,imageId:J.image,allowedPorts:[...J.allowSsh?[22]:[],80,443,F,...O]}),H=Z.resources[Z.outputs.instanceLogicalId];if(H?.Properties){let x=H.Properties.Tags||[];H.Properties.Tags=[...x,{Key:"Project",Value:$},{Key:"Environment",Value:M},{Key:"Role",Value:"app"},{Key:"ManagedBy",Value:"ts-cloud"}]}let z=Z.resources[Z.outputs.roleLogicalId];if(z?.Properties)z.Properties.Policies=z.Properties.Policies||[],z.Properties.Policies.push({PolicyName:"DeployBucketRead",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["s3:GetObject","s3:ListBucket"],Resource:[`arn:aws:s3:::${W}`,`arn:aws:s3:::${W}/*`]}]}});for(let[x,N]of Object.entries(Z.resources))this.builder.addResource(x,N);this.builder.addOutput("deployBucketName",{Value:{Ref:R},Description:"S3 bucket where release tarballs are uploaded"}),this.builder.addOutput("appInstanceId",{Value:{Ref:Z.outputs.instanceLogicalId},Description:"EC2 instance ID for the app server"}),this.builder.addOutput("appPublicIp",{Value:{Ref:Z.outputs.eipLogicalId},Description:"Public IP for the app server"}),this.serverEipLogicalIds.set("app",Z.outputs.eipLogicalId),this.serverEipLogicalIds.set("appInstance",Z.outputs.instanceLogicalId)}generateJumpBox($,M){let J=this.mergedConfig.infrastructure?.jumpBox;if(!J)return;let X=J===!0?{}:J;if(X.enabled===!1)return;this.generateNetworkInfrastructure($,M);let Y=X.size||"micro",Q=j.InstanceSize.specs[Y]?.instanceType||Y||"t3.micro",_;if(X.mountEfs)_={fileSystemId:typeof X.mountEfs==="string"?X.mountEfs:{Ref:"FileSystem"},mountPath:X.mountPath||"/mnt/efs"};let K;if(X.databaseTools)K=j.JumpBox.withDatabaseTools({slug:$,environment:M,vpcId:{Ref:"VPC"},subnetId:{Ref:"PublicSubnet1"},keyName:X.keyName||`${$}-${M}`,allowedCidrs:X.allowedCidrs});else if(_)K=j.JumpBox.withEfsMount({slug:$,environment:M,vpcId:{Ref:"VPC"},subnetId:{Ref:"PublicSubnet1"},keyName:X.keyName||`${$}-${M}`,fileSystemId:_.fileSystemId,mountPath:_.mountPath,allowedCidrs:X.allowedCidrs});else K=j.createJumpBox({slug:$,environment:M,vpcId:{Ref:"VPC"},subnetId:{Ref:"PublicSubnet1"},keyName:X.keyName||`${$}-${M}`,instanceType:Q,allowedCidrs:X.allowedCidrs,mountEfs:_});for(let[V,G]of Object.entries(K.resources))this.builder.addResource(V,G);this.builder.addOutput("JumpBoxInstanceId",{Value:{Ref:K.instanceLogicalId},Description:"The ID of the JumpBox EC2 instance (use with SSM Session Manager or SSH)"})}generateSharedInfrastructure($,M){let J=this.mergedConfig.infrastructure?.ssl,X=this.mergedConfig.infrastructure?.dns,Y=X?.domain,U=X?.hostedZoneId,Q=[],_,K;if(J?.certificateArn)K=J.certificateArn;else if(J?.enabled&&Y&&U){let O=J.domains||[Y],F=O[0],R=O.slice(1).map((H)=>{if(H.includes(".")&&H.endsWith(F))return H.replace(`.${F}`,"");return H}),{certificate:W,logicalId:Z}=J0.createCertificate({domain:F,subdomains:R,slug:$,environment:M,validationMethod:"DNS",hostedZoneId:U});_=Z,this.builder.addResource(Z,W)}if(this.mergedConfig.infrastructure?.storage){let O=Object.entries(this.mergedConfig.infrastructure.storage).some(([,W])=>W.website),F;if(O&&(_||K))F=`${$}${M}CloudFrontOAC`.replace(/[^a-zA-Z0-9]/g,""),this.builder.addResource(F,{Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${$}-${M}-s3-oac`,Description:`OAC for ${$} ${M} S3 website buckets`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}});let R=Object.entries(this.mergedConfig.infrastructure.storage).map(([W,Z])=>({name:W,config:Z,mountPath:this.normalizeMountPath(Z),rewriteStyle:Z.pathRewriteStyle||"directory",logicalId:this.storageBucketLogicalId($,M,W)})).filter((W)=>W.name!=="public"&&W.config.website&&W.mountPath);for(let[W,Z]of Object.entries(this.mergedConfig.infrastructure.storage)){let H=!!(Z.website&&F),z=this.storageBucketName($,M,W),{bucket:x,logicalId:N}=M0.createBucket({slug:$,name:W,environment:M,bucketName:z,versioning:Z.versioning,encryption:Z.encryption,public:H?!1:Z.public});if(H&&x.Properties)x.Properties.PublicAccessBlockConfiguration={BlockPublicAcls:!0,IgnorePublicAcls:!0,BlockPublicPolicy:!1,RestrictPublicBuckets:!1};if(this.builder.addResource(N,x),Z.website){let T=typeof Z.website==="object"?Z.website:{},S=M0.enableWebsiteHosting(x,T.indexDocument||"index.html",T.errorDocument);this.builder.addResource(N,S)}let B=this.normalizeMountPath(Z);if(H&&F&&Y&&!(B&&W!=="public")){let T=`${$}${M}${W}CDN`.replace(/[^a-zA-Z0-9]/g,""),S=[];if(Z.aliases&&Z.aliases.length>0)S.push(...Z.aliases);else if(W==="public"){if(S.push(Y),J?.domains?.includes(`www.${Y}`))S.push(`www.${Y}`)}else if(W==="docs")S.push(`docs.${Y}`);else if(W==="blog")S.push(`blog.${Y}`);let D=typeof Z.website==="object"?Z.website:{},k=Z.spa===!0,I=D.errorDocument||(k?"index.html":"404.html"),f=[];if(k)f.push({ErrorCode:403,ResponseCode:200,ResponsePagePath:"/index.html",ErrorCachingMinTTL:300},{ErrorCode:404,ResponseCode:200,ResponsePagePath:"/index.html",ErrorCachingMinTTL:300});else f.push({ErrorCode:403,ResponseCode:404,ResponsePagePath:`/${I}`,ErrorCachingMinTTL:300},{ErrorCode:404,ResponseCode:404,ResponsePagePath:`/${I}`,ErrorCachingMinTTL:300});let u=K&&S.length>0?{AcmCertificateArn:K,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}:_&&S.length>0?{AcmCertificateArn:{Ref:_},SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}:{CloudFrontDefaultCertificate:!0},p=`S3-${$}-${M}-${W}`,y=this.mergedConfig.project.region||"us-east-1",b;if(!k)b=`${$}${M}${W}UrlRewrite`.replace(/[^a-zA-Z0-9]/g,""),this.builder.addResource(b,{Type:"AWS::CloudFront::Function",Properties:{Name:`${$}-${M}-${W}-url-rewrite`,AutoPublish:!0,FunctionConfig:{Comment:`URL rewrite for ${$} ${M} ${W} - appends .html to extensionless paths`,Runtime:"cloudfront-js-2.0"},FunctionCode:`function handler(event) { var request = event.request; var uri = request.uri; if (uri.endsWith('/')) { request.uri += 'index.html'; }
14
+ else if (!uri.includes('.')) { request.uri += '.html'; } return request; }`}});let n=[{Id:p,DomainName:{"Fn::Sub":`\${${N}}.s3.${y}.amazonaws.com`},OriginPath:"",S3OriginConfig:{OriginAccessIdentity:""},OriginAccessControlId:{Ref:F}}],d=[],e=[];if(this.shouldRouteStorageBucketToCompute(W,Z)){this.appendComputeAppOrigin(n,d,e,$,M,this.resolveComputeCachePathPatterns(Z.computeRoutes));for(let w of R){let l=`S3-${$}-${M}-${w.name}`,$0=`${$}${M}${w.name}PathMountRewrite`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource($0,{Type:"AWS::CloudFront::Function",Properties:{Name:`${$}-${M}-${w.name}-path-mount-rewrite`,AutoPublish:!0,FunctionConfig:{Comment:`Path mount rewrite for ${$} ${M} ${w.name} at ${w.mountPath}`,Runtime:"cloudfront-js-2.0"},FunctionCode:this.pathMountRewriteFunctionCode(w.mountPath,w.rewriteStyle)}}),n.push({Id:l,DomainName:{"Fn::Sub":`\${${w.logicalId}}.s3.${y}.amazonaws.com`},OriginPath:"",S3OriginConfig:{OriginAccessIdentity:""},OriginAccessControlId:{Ref:F}}),e.push(w.logicalId,$0);for(let u0 of[w.mountPath,`${w.mountPath}/*`])d.push({PathPattern:u0,TargetOriginId:l,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,CachePolicyId:"4135ea2d-6df8-44a3-9df3-4b5a84be39ad",FunctionAssociations:[{EventType:"viewer-request",FunctionARN:{"Fn::GetAtt":[$0,"FunctionARN"]}}]})}}let Z0={Type:"AWS::CloudFront::Distribution",DependsOn:[N,F,...b?[b]:[],...e],Properties:{DistributionConfig:{Enabled:!0,Comment:`${$} ${M} ${W} site`,DefaultRootObject:"index.html",Origins:n,DefaultCacheBehavior:{TargetOriginId:p,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,CachePolicyId:"658327ea-f89d-4fab-a63d-7e88639e58f6",...b?{FunctionAssociations:[{EventType:"viewer-request",FunctionARN:{"Fn::GetAtt":[b,"FunctionARN"]}}]}:{}},...d.length>0?{CacheBehaviors:d}:{},...S.length>0?{Aliases:S}:{},ViewerCertificate:u,PriceClass:"PriceClass_100",HttpVersion:"http2and3",IPV6Enabled:!0,CustomErrorResponses:f}}};if(_)Z0.DependsOn.push(_);this.builder.addResource(T,Z0);let c0=`${N}CloudFrontPolicy`;if(this.builder.addResource(c0,{Type:"AWS::S3::BucketPolicy",DependsOn:[N,T],Properties:{Bucket:{Ref:N},PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowCloudFrontServicePrincipal",Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:{"Fn::Sub":`arn:aws:s3:::\${${N}}/*`},Condition:{StringEquals:{"AWS:SourceArn":{"Fn::Sub":`arn:aws:cloudfront::\${AWS::AccountId}:distribution/\${${T}}`}}}}]}}}),this.shouldRouteStorageBucketToCompute(W,Z))for(let w of R){let l=`${w.logicalId}CloudFrontPolicy`;this.builder.addResource(l,{Type:"AWS::S3::BucketPolicy",DependsOn:[w.logicalId,T],Properties:{Bucket:{Ref:w.logicalId},PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowCloudFrontServicePrincipal",Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:{"Fn::Sub":`arn:aws:s3:::\${${w.logicalId}}/*`},Condition:{StringEquals:{"AWS:SourceArn":{"Fn::Sub":`arn:aws:cloudfront::\${AWS::AccountId}:distribution/\${${T}}`}}}}]}}})}if(S.length>0)Q.push({name:W,bucketLogicalId:N,distLogicalId:T,oacLogicalId:F,aliases:S});this.builder.addOutput(`${W}CloudFrontDomain`,{Value:{"Fn::GetAtt":[T,"DomainName"]},Description:`CloudFront domain for ${W}`}),this.builder.addOutput(`${W}CloudFrontDistributionId`,{Value:{Ref:T},Description:`CloudFront distribution ID for ${W}`})}if(this.builder.addOutput(`${W}BucketName`,{Value:{Ref:N},Description:`S3 bucket name for ${W}`}),W==="public")this.builder.addOutput("FrontendBucketName",{Value:{Ref:N},Description:"Frontend S3 bucket name"});if(W==="docs")this.builder.addOutput("DocsBucketName",{Value:{Ref:N},Description:"Documentation S3 bucket name"});if(W==="blog")this.builder.addOutput("BlogBucketName",{Value:{Ref:N},Description:"Blog S3 bucket name"})}}if(this.mergedConfig.infrastructure?.sftp){let O=this.mergedConfig.infrastructure.sftp,F=S0.create({...O,storage:this.resolveSftpStorage(O,$,M)??O.storage,slug:$,environment:M});for(let[R,W]of Object.entries(F.resources))this.builder.addResource(R,W);this.builder.addOutput("SftpServerId",{Value:{Ref:F.serverLogicalId},Description:"AWS Transfer Family SFTP server ID"}),this.builder.addOutput("SftpEndpoint",{Value:{"Fn::Sub":`\${${F.serverLogicalId}}.server.transfer.\${AWS::Region}.amazonaws.com`},Description:"AWS Transfer Family SFTP endpoint"}),this.builder.addOutput("SftpStorageDomain",{Value:F.domain,Description:"Storage backing the SFTP server (EFS or S3)"})}if(U&&Q.length>0)for(let{name:O,distLogicalId:F,aliases:R}of Q)for(let W of R){let Z=W.replace(/\./g,"").replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(`${Z}ARecord`,{Type:"AWS::Route53::RecordSet",DependsOn:[F],Properties:{HostedZoneId:U,Name:W,Type:"A",AliasTarget:{DNSName:{"Fn::GetAtt":[F,"DomainName"]},HostedZoneId:"Z2FDTNDATAQYW2",EvaluateTargetHealth:!1}}}),this.builder.addResource(`${Z}AAAARecord`,{Type:"AWS::Route53::RecordSet",DependsOn:[F],Properties:{HostedZoneId:U,Name:W,Type:"AAAA",AliasTarget:{DNSName:{"Fn::GetAtt":[F,"DomainName"]},HostedZoneId:"Z2FDTNDATAQYW2",EvaluateTargetHealth:!1}}})}if(this.mergedConfig.infrastructure?.databases){for(let[O,F]of Object.entries(this.mergedConfig.infrastructure.databases))if(F.engine==="dynamodb"){let{table:R,logicalId:W}=t.createTable({slug:$,environment:M,tableName:`${$}-${M}-${O}`,partitionKey:F.partitionKey||{name:"id",type:"S"},sortKey:F.sortKey});this.builder.addResource(W,R)}else if(F.engine==="postgres"){let{dbInstance:R,logicalId:W}=t.createPostgres({slug:$,environment:M,dbInstanceIdentifier:`${$}-${M}-${O}`,masterUsername:F.username||"admin",masterUserPassword:F.password||"changeme123",allocatedStorage:F.storage||20,dbInstanceClass:F.instanceClass||"db.t3.micro"});this.builder.addResource(W,R)}else if(F.engine==="mysql"){let{dbInstance:R,logicalId:W}=t.createMysql({slug:$,environment:M,dbInstanceIdentifier:`${$}-${M}-${O}`,masterUsername:F.username||"admin",masterUserPassword:F.password||"changeme123",allocatedStorage:F.storage||20,dbInstanceClass:F.instanceClass||"db.t3.micro"});this.builder.addResource(W,R)}}if(this.mergedConfig.infrastructure?.cdn)for(let[O,F]of Object.entries(this.mergedConfig.infrastructure.cdn)){if(!F.origin)continue;let R=typeof F.customDomain==="string"?F.customDomain:F.customDomain?.domain||F.domain,W=typeof F.customDomain==="object"?F.customDomain?.certificateArn:F.certificateArn,Z=W||K,H=`${$}${M}${O}CDN`.replace(/[^a-zA-Z0-9]/g,""),z=`S3-${$}-${M}-${O}-cdn`,x=[{Id:z,DomainName:F.origin,OriginPath:"",S3OriginConfig:{OriginAccessIdentity:""},OriginShield:F.originShield?{Enabled:!0,OriginShieldRegion:F.originShieldRegion||this.mergedConfig.environments[M]?.region||this.mergedConfig.project.region||"us-east-1"}:{Enabled:!1}}],N=[],B=[];if(F.routeCompute)this.appendComputeAppOrigin(x,N,B,$,M,this.resolveComputeCachePathPatterns(F.computeRoutes));let T=Z&&R?{AcmCertificateArn:_&&!W?{Ref:_}:Z,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}:{CloudFrontDefaultCertificate:!0},S=[...B];if(_&&!W&&R)S.push(_);let D={Type:"AWS::CloudFront::Distribution",...S.length>0?{DependsOn:S}:{},Properties:{DistributionConfig:{Enabled:!0,Comment:`${$} ${M} ${O} CDN`,DefaultRootObject:"index.html",Origins:x,DefaultCacheBehavior:{TargetOriginId:z,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:F.compress!==!1,CachePolicyId:"658327ea-f89d-4fab-a63d-7e88639e58f6"},...N.length>0?{CacheBehaviors:N}:{},...R&&Z?{Aliases:[R]}:{},ViewerCertificate:T,PriceClass:"PriceClass_100",HttpVersion:F.http3?"http2and3":"http2"}}};if(this.builder.addResource(H,D),U&&R&&Z){let k=R.replace(/\./g,"").replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(`${k}CdnARecord`,{Type:"AWS::Route53::RecordSet",DependsOn:[H,..._&&!W?[_]:[]],Properties:{HostedZoneId:U,Name:R,Type:"A",AliasTarget:{HostedZoneId:"Z2FDTNDATAQYW2",DNSName:{"Fn::GetAtt":[H,"DomainName"]}}}})}}if(this.mergedConfig.infrastructure?.queues)for(let[O,F]of Object.entries(this.mergedConfig.infrastructure.queues)){if(!this.shouldDeploy(F))continue;let{queue:R,logicalId:W}=X0.createQueue({slug:$,environment:M,name:`${$}-${M}-${O}`,fifo:F.fifo,visibilityTimeout:F.visibilityTimeout,messageRetentionPeriod:F.messageRetentionPeriod,delaySeconds:F.delaySeconds,maxMessageSize:F.maxMessageSize,receiveMessageWaitTime:F.receiveMessageWaitTime,contentBasedDeduplication:F.contentBasedDeduplication,encrypted:F.encrypted,kmsKeyId:F.kmsKeyId});this.builder.addResource(W,R);let Z;if(F.deadLetterQueue){let{deadLetterQueue:H,updatedSourceQueue:z,deadLetterLogicalId:x}=X0.createDeadLetterQueue(W,{slug:$,environment:M,maxReceiveCount:F.maxReceiveCount});Z=x,this.builder.addResource(x,H);let B=this.builder.getResources()[W];if(B?.Properties)B.Properties.RedrivePolicy=z.Properties?.RedrivePolicy}if(F.trigger){let H=F.trigger,z=`${$}${M}${H.functionName}`.replace(/[^a-zA-Z0-9]/g,""),x={Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:{"Fn::GetAtt":[W,"Arn"]},FunctionName:{Ref:z},BatchSize:H.batchSize||10,MaximumBatchingWindowInSeconds:H.batchWindow||0,Enabled:!0,...H.reportBatchItemFailures!==!1&&{FunctionResponseTypes:["ReportBatchItemFailures"]},...H.maxConcurrency&&{ScalingConfig:{MaximumConcurrency:H.maxConcurrency}},...H.filterPattern&&{FilterCriteria:{Filters:[{Pattern:JSON.stringify(H.filterPattern)}]}}},DependsOn:[W,z]};this.builder.addResource(`${W}Trigger`,x)}if(F.alarms?.enabled){let H=F.alarms,z=H.notificationTopicArn;if(!z&&H.notificationEmails?.length){let B=`${W}AlarmTopic`;this.builder.addResource(B,{Type:"AWS::SNS::Topic",Properties:{TopicName:`${$}-${M}-${O}-alarms`,DisplayName:`${O} Queue Alarms`}}),H.notificationEmails.forEach((T,S)=>{this.builder.addResource(`${B}Sub${S}`,{Type:"AWS::SNS::Subscription",Properties:{TopicArn:{Ref:B},Protocol:"email",Endpoint:T}})}),z={Ref:B}}let x=H.queueDepthThreshold||1000;this.builder.addResource(`${W}DepthAlarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${$}-${M}-${O}-queue-depth`,AlarmDescription:`Queue ${O} depth exceeds ${x} messages`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Average",Period:300,EvaluationPeriods:2,Threshold:x,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:{"Fn::GetAtt":[W,"QueueName"]}}],...z&&{AlarmActions:[z],OKActions:[z]}}});let N=H.messageAgeThreshold||3600;if(this.builder.addResource(`${W}AgeAlarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${$}-${M}-${O}-message-age`,AlarmDescription:`Queue ${O} oldest message exceeds ${N} seconds`,MetricName:"ApproximateAgeOfOldestMessage",Namespace:"AWS/SQS",Statistic:"Maximum",Period:300,EvaluationPeriods:2,Threshold:N,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:{"Fn::GetAtt":[W,"QueueName"]}}],...z&&{AlarmActions:[z],OKActions:[z]}}}),Z&&H.dlqAlarm!==!1)this.builder.addResource(`${Z}Alarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${$}-${M}-${O}-dlq-messages`,AlarmDescription:`Dead letter queue for ${O} has messages`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Sum",Period:300,EvaluationPeriods:1,Threshold:0,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:{"Fn::GetAtt":[Z,"QueueName"]}}],...z&&{AlarmActions:[z]}}})}if(F.subscribe){let H=F.subscribe,z=H.topicArn;if(!z&&H.topicName)z={Ref:H.topicName};if(z){this.builder.addResource(`${W}SnsPolicy`,{Type:"AWS::SQS::QueuePolicy",Properties:{Queues:[{Ref:W}],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"sns.amazonaws.com"},Action:"sqs:SendMessage",Resource:{"Fn::GetAtt":[W,"Arn"]},Condition:{ArnEquals:{"aws:SourceArn":z}}}]}}});let x={TopicArn:z,Protocol:"sqs",Endpoint:{"Fn::GetAtt":[W,"Arn"]},RawMessageDelivery:H.rawMessageDelivery||!1};if(H.filterPolicy)x.FilterPolicy=H.filterPolicy,x.FilterPolicyScope=H.filterPolicyScope||"MessageAttributes";this.builder.addResource(`${W}SnsSub`,{Type:"AWS::SNS::Subscription",Properties:x,DependsOn:`${W}SnsPolicy`})}}}if(this.mergedConfig.infrastructure?.realtime?.enabled)if((this.mergedConfig.infrastructure.realtime.mode||"serverless")==="server")this.generateRealtimeServerResources($,M);else this.generateRealtimeResources($,M);let V=this.mergedConfig.infrastructure?.redirects;if(V){let O=V.target||this.mergedConfig.infrastructure?.dns?.domain||"",F=V.protocol||"https";if(V.domains?.length&&O)for(let R of V.domains){let{bucket:W,bucketPolicy:Z,logicalId:H,policyLogicalId:z}=g.createDomainRedirectBucket({slug:$,environment:M,sourceDomain:R,targetDomain:O,protocol:F});this.builder.addResource(H,W),this.builder.addResource(z,Z)}if(V.paths&&Object.keys(V.paths).length>0){let R=g.fromMapping(V.paths,{statusCode:V.statusCode||301}),{function:W,logicalId:Z}=g.createPathRedirectFunction({slug:$,environment:M,rules:R});this.builder.addResource(Z,W)}}if(this.mergedConfig.infrastructure?.monitoring?.alarms)for(let[O,F]of Object.entries(this.mergedConfig.infrastructure.monitoring.alarms)){let{alarm:R,logicalId:W}=w0.createAlarm({slug:$,environment:M,alarmName:`${$}-${M}-${O}`,metricName:F.metricName||"Errors",namespace:F.namespace||"AWS/Lambda",threshold:F.threshold||1,comparisonOperator:F.comparisonOperator||"GreaterThanThreshold"});this.builder.addResource(W,R)}let G=this.mergedConfig.infrastructure?.cache;if(G){let O=G.type||"redis";if(O==="redis"){this.generateNetworkInfrastructure($,M);let F=G.redis||{},{replicationGroup:R,subnetGroup:W,logicalId:Z,subnetGroupId:H}=Y0.createRedis({slug:$,environment:M,nodeType:F.nodeType||G.nodeType||"cache.t3.micro",engineVersion:F.engineVersion||"7.1",port:F.port||6379,numCacheClusters:F.numCacheNodes||2,automaticFailover:F.automaticFailoverEnabled!==!1,atRestEncryption:!0,transitEncryption:!0,snapshotRetentionDays:F.snapshotRetentionLimit||7,snapshotWindow:F.snapshotWindow,subnetIds:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]});if(this.builder.addResource(Z,R),W&&H)this.builder.addResource(H,W);this.builder.addOutput("CacheEndpoint",{Value:{"Fn::GetAtt":[Z,"PrimaryEndPoint.Address"]},Description:"Redis primary endpoint address"}),this.builder.addOutput("CachePort",{Value:{"Fn::GetAtt":[Z,"PrimaryEndPoint.Port"]},Description:"Redis primary endpoint port"})}else if(O==="memcached"){this.generateNetworkInfrastructure($,M);let F=G.elasticache||{},{cluster:R,subnetGroup:W,logicalId:Z,subnetGroupId:H}=Y0.createMemcached({slug:$,environment:M,nodeType:F.nodeType||G.nodeType||"cache.t3.micro",engineVersion:F.engineVersion||"1.6.22",numCacheNodes:F.numCacheNodes||2,subnetIds:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]});if(this.builder.addResource(Z,R),W&&H)this.builder.addResource(H,W);this.builder.addOutput("CacheEndpoint",{Value:{"Fn::GetAtt":[Z,"ConfigurationEndpoint.Address"]},Description:"Memcached configuration endpoint address"})}}let q=this.mergedConfig.infrastructure?.email;if(q){let O=q.domain||this.mergedConfig.infrastructure?.dns?.domain;if(O){let{emailIdentity:F,logicalId:R}=h.verifyDomain({domain:O,slug:$,environment:M,enableDkim:q.enableDkim!==!1,dkimKeyLength:q.dkimKeyLength||"RSA_2048_BIT"});if(this.builder.addResource(R,F),q.configurationSet!==!1){let{configurationSet:H,logicalId:z}=h.createConfigurationSet({slug:$,environment:M});this.builder.addResource(z,H)}let W=q.hostedZoneId||this.mergedConfig.infrastructure?.dns?.hostedZoneId;if(W){if(q.enableDkim!==!1)for(let B=1;B<=3;B++){let T=`DkimRecord${B}${O.replace(/\./g,"")}`;this.builder.addResource(T,{Type:"AWS::Route53::RecordSet",DependsOn:[R],Properties:{HostedZoneId:W,Name:{"Fn::GetAtt":[R,`DkimDNSTokenName${B}`]},Type:"CNAME",TTL:1800,ResourceRecords:[{"Fn::GetAtt":[R,`DkimDNSTokenValue${B}`]}]}})}let{record:H,logicalId:z}=h.createSpfRecord(O,W);this.builder.addResource(z,H);let{record:x,logicalId:N}=h.createDmarcRecord(O,W,{policy:"none",reportingEmail:q.dmarcReportingEmail||`dmarc-reports@${O}`});this.builder.addResource(N,x)}this.builder.addOutput("EmailDomain",{Value:O,Description:"SES verified email domain"});let Z=q.server;if(Z?.enabled&&W){let H=this.mergedConfig.environments[M]?.region||this.mergedConfig.project.region||"us-east-1",z=`${$}-${M}-email`,{role:x,policy:N,roleLogicalId:B,policyLogicalId:T}=h.createEmailLambdaRole({slug:$,environment:M,s3BucketArn:`arn:aws:s3:::${z}`,sesIdentityArn:`arn:aws:ses:${H}:*:identity/${O}`});this.builder.addResource(B,x),this.builder.addResource(T,N);let{function:S,permission:D,logicalId:k,permissionLogicalId:I}=h.createInboundEmailLambda({slug:$,environment:M,roleArn:{"Fn::GetAtt":[B,"Arn"]},s3BucketName:z,organizedPrefix:"mailboxes/"});this.builder.addResource(k,S),this.builder.addResource(I,D);let f=h.createInboundEmailSetup({slug:$,environment:M,domain:O,s3BucketName:z,s3KeyPrefix:"inbox/",region:H,hostedZoneId:W,lambdaFunctionArn:{"Fn::GetAtt":[k,"Arn"]}});for(let[p,y]of Object.entries(f.resources)){if(y.Type==="AWS::SES::ReceiptRule")y.DependsOn=[I,k];this.builder.addResource(p,y)}this.builder.addOutput("InboundEmailLambda",{Value:{Ref:k},Description:"Inbound email processing Lambda function"}),this.builder.addOutput("EmailBucket",{Value:z,Description:"S3 bucket for email storage"});let u=this.serverEipLogicalIds.get("app");if(u&&W){let y=`${Z?.subdomain||"mail"}.${O}`,b=y.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(`${b}ARecord`,{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:W,Name:y,Type:"A",TTL:"300",ResourceRecords:[{Ref:u}]}})}this.builder.addOutput("MailHost",{Value:`mail.${O}`,Description:"Mail server hostname for SMTP/IMAP clients"})}}}let A=this.mergedConfig.infrastructure?.search;if(A){let O=A.vpc?{subnetIds:[{Ref:"PublicSubnet1"}],securityGroupIds:[]}:void 0;if(O)this.generateNetworkInfrastructure($,M);let{domain:F,logicalId:R}=j0.createDomain({slug:$,environment:M,engineVersion:A.engineVersion||"OpenSearch_2.11",instanceType:A.instanceType||"t3.small.search",instanceCount:A.instanceCount||1,volumeSize:A.volumeSize||10,volumeType:A.volumeType||"gp3",dedicatedMaster:A.dedicatedMaster||!1,dedicatedMasterType:A.dedicatedMasterType,dedicatedMasterCount:A.dedicatedMasterCount||3,multiAz:A.multiAz||!1,encryption:A.encryption||{atRest:!0,nodeToNode:!0},advancedSecurity:A.advancedSecurity,autoTune:A.autoTune!==!1,vpc:O});this.builder.addResource(R,F),this.builder.addOutput("SearchDomainEndpoint",{Value:{"Fn::GetAtt":[R,"DomainEndpoint"]},Description:"OpenSearch domain endpoint"}),this.builder.addOutput("SearchDomainArn",{Value:{"Fn::GetAtt":[R,"Arn"]},Description:"OpenSearch domain ARN"})}let P=this.mergedConfig.infrastructure?.fileSystem;if(P&&Object.keys(P).length>0){this.generateNetworkInfrastructure($,M);for(let[O,F]of Object.entries(P)){let{fileSystem:R,logicalId:W}=r.createFileSystem({slug:`${$}-${O}`,environment:M,encrypted:F.encrypted!==!1,performanceMode:F.performanceMode||"generalPurpose",throughputMode:F.throughputMode||"bursting",enableBackup:!0});this.builder.addResource(W,R);let{securityGroup:Z,logicalId:H}=r.createEfsSecurityGroup({slug:`${$}-${O}`,environment:M,vpcId:{Ref:"VPC"},sourceCidrBlocks:["10.0.0.0/16"]});this.builder.addResource(H,Z);let{mountTargets:z,logicalIds:x}=r.createMultiAzMountTargets(W,{slug:`${$}-${O}`,environment:M,subnetIds:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}],securityGroupId:{Ref:H}});for(let N=0;N<z.length;N++)this.builder.addResource(x[N],z[N]);this.builder.addOutput(`${O}FileSystemId`,{Value:{Ref:W},Description:`EFS file system ID for ${O}`})}}let E=this.mergedConfig.infrastructure?.ai;if(E){let O=E.service||"ecs",F=E.models||["*"],R=E.allowStreaming!==!1,W;if(O==="ecs")W=C.enableBedrockForEcs({slug:$,environment:M,models:F,allowStreaming:R});else if(O==="ec2")W=C.enableBedrockForEc2({slug:$,environment:M,models:F,allowStreaming:R});else if(O==="lambda")W=C.enableBedrockForLambda({slug:$,environment:M,models:F,allowStreaming:R});else W=C.createBedrockRole(O,{slug:$,environment:M,models:F,allowStreaming:R});if(this.builder.addResource(W.logicalId,W.role),E.allowAsync){let{policy:Z,logicalId:H}=C.createBedrockPolicy({slug:$,environment:M,models:F,allowStreaming:R,allowAsync:!0});this.builder.addResource(H,Z)}this.builder.addOutput("BedrockRoleArn",{Value:{"Fn::GetAtt":[W.logicalId,"Arn"]},Description:"IAM role ARN with Bedrock permissions"})}}generateRealtimeResources($,M){let J=this.mergedConfig.infrastructure?.realtime;if(!J)return;let X=J.name||`${$}-${M}-realtime`,Y=J.scaling||{},U=J.storage||{type:"dynamodb"},Q=Y.handlerMemory||256,_=Y.handlerTimeout||30,K=`${$}${M}RealtimeConnections`.replace(/[^a-zA-Z0-9]/g,""),V=`${$}${M}RealtimeChannels`.replace(/[^a-zA-Z0-9]/g,"");if(U.type==="dynamodb"){let x=U.dynamodb||{},N=x.billingMode||"PAY_PER_REQUEST";this.builder.addResource(K,{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${$}-${M}-realtime-connections`,BillingMode:N,AttributeDefinitions:[{AttributeName:"connectionId",AttributeType:"S"},{AttributeName:"userId",AttributeType:"S"}],KeySchema:[{AttributeName:"connectionId",KeyType:"HASH"}],GlobalSecondaryIndexes:[{IndexName:"userId-index",KeySchema:[{AttributeName:"userId",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"},...N==="PROVISIONED"&&{ProvisionedThroughput:{ReadCapacityUnits:x.readCapacity||5,WriteCapacityUnits:x.writeCapacity||5}}}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0},...N==="PROVISIONED"&&{ProvisionedThroughput:{ReadCapacityUnits:x.readCapacity||5,WriteCapacityUnits:x.writeCapacity||5}},...x.pointInTimeRecovery&&{PointInTimeRecoverySpecification:{PointInTimeRecoveryEnabled:!0}},Tags:[{Key:"Name",Value:`${$}-${M}-realtime-connections`},{Key:"Environment",Value:M}]}}),this.builder.addResource(V,{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${$}-${M}-realtime-channels`,BillingMode:N,AttributeDefinitions:[{AttributeName:"channel",AttributeType:"S"},{AttributeName:"connectionId",AttributeType:"S"}],KeySchema:[{AttributeName:"channel",KeyType:"HASH"},{AttributeName:"connectionId",KeyType:"RANGE"}],GlobalSecondaryIndexes:[{IndexName:"connectionId-index",KeySchema:[{AttributeName:"connectionId",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"},...N==="PROVISIONED"&&{ProvisionedThroughput:{ReadCapacityUnits:x.readCapacity||5,WriteCapacityUnits:x.writeCapacity||5}}}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0},...N==="PROVISIONED"&&{ProvisionedThroughput:{ReadCapacityUnits:x.readCapacity||5,WriteCapacityUnits:x.writeCapacity||5}},Tags:[{Key:"Name",Value:`${$}-${M}-realtime-channels`},{Key:"Environment",Value:M}]}})}let G=`${$}${M}RealtimeRole`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(G,{Type:"AWS::IAM::Role",Properties:{RoleName:`${$}-${M}-realtime-handler-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:"RealtimeHandlerPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:UpdateItem"],Resource:[{"Fn::GetAtt":[K,"Arn"]},{"Fn::Sub":`\${${K}.Arn}/index/*`},{"Fn::GetAtt":[V,"Arn"]},{"Fn::Sub":`\${${V}.Arn}/index/*`}]},{Effect:"Allow",Action:"execute-api:ManageConnections",Resource:{"Fn::Sub":"arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:*/*"}}]}}]}});let q=`${$}${M}RealtimeConnect`.replace(/[^a-zA-Z0-9]/g,""),A=`${$}${M}RealtimeDisconnect`.replace(/[^a-zA-Z0-9]/g,""),P=`${$}${M}RealtimeMessage`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(q,{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${$}-${M}-realtime-connect`,Runtime:"nodejs20.x",Handler:"index.handler",Role:{"Fn::GetAtt":[G,"Arn"]},MemorySize:Q,Timeout:_,Environment:{Variables:{CONNECTIONS_TABLE:{Ref:K},CHANNELS_TABLE:{Ref:V},ENVIRONMENT:M}},Code:{ZipFile:this.generateConnectHandlerCode()}},DependsOn:[G,K]}),this.builder.addResource(A,{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${$}-${M}-realtime-disconnect`,Runtime:"nodejs20.x",Handler:"index.handler",Role:{"Fn::GetAtt":[G,"Arn"]},MemorySize:Q,Timeout:_,Environment:{Variables:{CONNECTIONS_TABLE:{Ref:K},CHANNELS_TABLE:{Ref:V},ENVIRONMENT:M}},Code:{ZipFile:this.generateDisconnectHandlerCode()}},DependsOn:[G,K,V]}),this.builder.addResource(P,{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${$}-${M}-realtime-message`,Runtime:"nodejs20.x",Handler:"index.handler",Role:{"Fn::GetAtt":[G,"Arn"]},MemorySize:Q,Timeout:_,Environment:{Variables:{CONNECTIONS_TABLE:{Ref:K},CHANNELS_TABLE:{Ref:V},ENVIRONMENT:M}},Code:{ZipFile:this.generateMessageHandlerCode()}},DependsOn:[G,K,V]});let E=`${$}${M}RealtimeApi`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(E,{Type:"AWS::ApiGatewayV2::Api",Properties:{Name:X,ProtocolType:"WEBSOCKET",RouteSelectionExpression:"$request.body.action",Tags:{Name:X,Environment:M}}});let O=`${q}Permission`,F=`${A}Permission`,R=`${P}Permission`;this.builder.addResource(O,{Type:"AWS::Lambda::Permission",Properties:{FunctionName:{Ref:q},Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:{"Fn::Sub":`arn:aws:execute-api:\${AWS::Region}:\${AWS::AccountId}:\${${E}}/*/$connect`}}}),this.builder.addResource(F,{Type:"AWS::Lambda::Permission",Properties:{FunctionName:{Ref:A},Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:{"Fn::Sub":`arn:aws:execute-api:\${AWS::Region}:\${AWS::AccountId}:\${${E}}/*/$disconnect`}}}),this.builder.addResource(R,{Type:"AWS::Lambda::Permission",Properties:{FunctionName:{Ref:P},Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:{"Fn::Sub":`arn:aws:execute-api:\${AWS::Region}:\${AWS::AccountId}:\${${E}}/*/$default`}}});let W=`${E}ConnectInteg`,Z=`${E}DisconnectInteg`,H=`${E}MessageInteg`;this.builder.addResource(W,{Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:{Ref:E},IntegrationType:"AWS_PROXY",IntegrationUri:{"Fn::Sub":`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${q}.Arn}/invocations`}}}),this.builder.addResource(Z,{Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:{Ref:E},IntegrationType:"AWS_PROXY",IntegrationUri:{"Fn::Sub":`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${A}.Arn}/invocations`}}}),this.builder.addResource(H,{Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:{Ref:E},IntegrationType:"AWS_PROXY",IntegrationUri:{"Fn::Sub":`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${P}.Arn}/invocations`}}}),this.builder.addResource(`${E}ConnectRoute`,{Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:{Ref:E},RouteKey:"$connect",AuthorizationType:"NONE",Target:{"Fn::Sub":`integrations/\${${W}}`}}}),this.builder.addResource(`${E}DisconnectRoute`,{Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:{Ref:E},RouteKey:"$disconnect",Target:{"Fn::Sub":`integrations/\${${Z}}`}}}),this.builder.addResource(`${E}DefaultRoute`,{Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:{Ref:E},RouteKey:"$default",Target:{"Fn::Sub":`integrations/\${${H}}`}}});let z=`${E}Stage`;if(this.builder.addResource(z,{Type:"AWS::ApiGatewayV2::Stage",Properties:{ApiId:{Ref:E},StageName:M,AutoDeploy:!0,DefaultRouteSettings:{ThrottlingBurstLimit:Y.messagesPerSecond||1000,ThrottlingRateLimit:Y.messagesPerSecond||1000}}}),J.monitoring?.enabled){let x=J.monitoring,N=x.notificationTopicArn;if(!N&&x.notificationEmails?.length){let B=`${E}AlarmTopic`;this.builder.addResource(B,{Type:"AWS::SNS::Topic",Properties:{TopicName:`${$}-${M}-realtime-alarms`,DisplayName:"Realtime WebSocket Alarms"}}),x.notificationEmails.forEach((T,S)=>{this.builder.addResource(`${B}Sub${S}`,{Type:"AWS::SNS::Subscription",Properties:{TopicArn:{Ref:B},Protocol:"email",Endpoint:T}})}),N={Ref:B}}if(x.connectionThreshold)this.builder.addResource(`${E}ConnectionAlarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${$}-${M}-realtime-connections`,AlarmDescription:`WebSocket connections exceed ${x.connectionThreshold}`,MetricName:"ConnectCount",Namespace:"AWS/ApiGateway",Statistic:"Sum",Period:300,EvaluationPeriods:2,Threshold:x.connectionThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"ApiId",Value:{Ref:E}}],...N&&{AlarmActions:[N]}}});if(x.errorThreshold)this.builder.addResource(`${E}ErrorAlarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${$}-${M}-realtime-errors`,AlarmDescription:`WebSocket errors exceed ${x.errorThreshold}/min`,MetricName:"ExecutionError",Namespace:"AWS/ApiGateway",Statistic:"Sum",Period:60,EvaluationPeriods:3,Threshold:x.errorThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"ApiId",Value:{Ref:E}}],...N&&{AlarmActions:[N]}}})}this.builder.addOutput(`${E}Endpoint`,{Description:"WebSocket API endpoint URL",Value:{"Fn::Sub":`wss://\${${E}}.execute-api.\${AWS::Region}.amazonaws.com/${M}`},Export:{Name:{"Fn::Sub":"${AWS::StackName}-realtime-endpoint"}}}),this.builder.addOutput(`${E}Id`,{Description:"WebSocket API ID",Value:{Ref:E},Export:{Name:{"Fn::Sub":"${AWS::StackName}-realtime-api-id"}}})}generateConnectHandlerCode(){return`
15
15
  const { DynamoDBClient } = require('@aws-sdk/client-dynamodb');
16
16
  const { DynamoDBDocumentClient, PutCommand } = require('@aws-sdk/lib-dynamodb');
17
17
 
@@ -170,56 +170,56 @@ catch (error) {
170
170
  return { statusCode: 500, body: JSON.stringify({ error: 'Internal error' }) };
171
171
  }
172
172
  };
173
- `.trim()}generateRealtimeServerResources(e,t){let r=this.mergedConfig.infrastructure?.realtime;if(!r)return;let n=r.server||{},o=n.port||6001,l=n.instances||1,c=`${e}${t}RealtimeSG`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(c,{Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:`Security group for ${e} realtime WebSocket server`,GroupName:`${e}-${t}-realtime-sg`,VpcId:{Ref:"VPC"},SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:o,ToPort:o,CidrIp:"0.0.0.0/0",Description:"WebSocket connections"},{IpProtocol:"tcp",FromPort:443,ToPort:443,CidrIp:"0.0.0.0/0",Description:"HTTPS/WSS connections"}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound"}],Tags:[{Key:"Name",Value:`${e}-${t}-realtime-sg`},{Key:"Environment",Value:t}]}});let s=`${e}${t}RealtimeTaskDef`.replace(/[^a-zA-Z0-9]/g,""),u=`${e}${t}RealtimeTaskRole`.replace(/[^a-zA-Z0-9]/g,""),h=`${e}${t}RealtimeExecRole`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(h,{Type:"AWS::IAM::Role",Properties:{RoleName:`${e}-${t}-realtime-exec-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"]}}),this.builder.addResource(u,{Type:"AWS::IAM::Role",Properties:{RoleName:`${e}-${t}-realtime-task-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"RealtimeTaskPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogStream","logs:PutLogEvents"],Resource:"*"},...n.redis?.enabled?[{Effect:"Allow",Action:["elasticache:DescribeCacheClusters","elasticache:DescribeReplicationGroups"],Resource:"*"}]:[]]}}]}});let d=[{Name:"BROADCAST_HOST",Value:n.host||"0.0.0.0"},{Name:"BROADCAST_PORT",Value:String(o)},{Name:"NODE_ENV",Value:t==="production"?"production":"development"}];if(n.redis?.enabled){if(n.redis.useElastiCache)d.push({Name:"REDIS_HOST",Value:{"Fn::GetAtt":["CacheCluster","RedisEndpoint.Address"]}}),d.push({Name:"REDIS_PORT",Value:{"Fn::GetAtt":["CacheCluster","RedisEndpoint.Port"]}});else d.push({Name:"REDIS_HOST",Value:n.redis.host||"localhost"}),d.push({Name:"REDIS_PORT",Value:String(n.redis.port||6379)});if(n.redis.keyPrefix)d.push({Name:"REDIS_KEY_PREFIX",Value:n.redis.keyPrefix})}this.builder.addResource(s,{Type:"AWS::ECS::TaskDefinition",Properties:{Family:`${e}-${t}-realtime`,NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:"512",Memory:"1024",ExecutionRoleArn:{"Fn::GetAtt":[h,"Arn"]},TaskRoleArn:{"Fn::GetAtt":[u,"Arn"]},ContainerDefinitions:[{Name:"realtime",Image:{"Fn::Sub":`\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.amazonaws.com/${e}-realtime:latest`},Essential:!0,PortMappings:[{ContainerPort:o,Protocol:"tcp"}],Environment:d,LogConfiguration:{LogDriver:"awslogs",Options:{"awslogs-group":`/ecs/${e}-${t}-realtime`,"awslogs-region":{Ref:"AWS::Region"},"awslogs-stream-prefix":"realtime"}},HealthCheck:{Command:["CMD-SHELL",`curl -f http://localhost:${o}${n.healthCheckPath||"/health"} || exit 1`],Interval:30,Timeout:5,Retries:3,StartPeriod:60}}],Tags:[{Key:"Name",Value:`${e}-${t}-realtime`},{Key:"Environment",Value:t}]},DependsOn:[h,u]});let b=`${e}${t}RealtimeLogs`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(b,{Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:`/ecs/${e}-${t}-realtime`,RetentionInDays:30}});let A=`${e}${t}RealtimeService`.replace(/[^a-zA-Z0-9]/g,"");if(this.builder.addResource(A,{Type:"AWS::ECS::Service",Properties:{ServiceName:`${e}-${t}-realtime`,Cluster:{Ref:"ECSCluster"},TaskDefinition:{Ref:s},DesiredCount:l,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{AssignPublicIp:"ENABLED",SecurityGroups:[{Ref:c}],Subnets:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]}},HealthCheckGracePeriodSeconds:60,Tags:[{Key:"Name",Value:`${e}-${t}-realtime`},{Key:"Environment",Value:t}]},DependsOn:[s,c,b]}),n.autoScaling){let T=n.autoScaling,g=`${e}${t}RealtimeScalableTarget`.replace(/[^a-zA-Z0-9]/g,"");if(this.builder.addResource(g,{Type:"AWS::ApplicationAutoScaling::ScalableTarget",Properties:{MaxCapacity:T.max||10,MinCapacity:T.min||1,ResourceId:{"Fn::Sub":`service/\${ECSCluster}/${e}-${t}-realtime`},RoleARN:{"Fn::Sub":"arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService"},ScalableDimension:"ecs:service:DesiredCount",ServiceNamespace:"ecs"},DependsOn:A}),T.targetCPU)this.builder.addResource(`${e}${t}RealtimeCPUPolicy`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::ApplicationAutoScaling::ScalingPolicy",Properties:{PolicyName:`${e}-${t}-realtime-cpu-scaling`,PolicyType:"TargetTrackingScaling",ScalingTargetId:{Ref:g},TargetTrackingScalingPolicyConfiguration:{PredefinedMetricSpecification:{PredefinedMetricType:"ECSServiceAverageCPUUtilization"},TargetValue:T.targetCPU,ScaleInCooldown:300,ScaleOutCooldown:60}}})}if(r.monitoring?.enabled){let T=r.monitoring,g=T.notificationTopicArn;if(!g&&T.notificationEmails?.length){let m=`${e}${t}RealtimeAlarmTopic`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(m,{Type:"AWS::SNS::Topic",Properties:{TopicName:`${e}-${t}-realtime-alarms`,DisplayName:"Realtime Server Alarms"}}),T.notificationEmails.forEach((a,y)=>{this.builder.addResource(`${m}Sub${y}`,{Type:"AWS::SNS::Subscription",Properties:{TopicArn:{Ref:m},Protocol:"email",Endpoint:a}})}),g={Ref:m}}this.builder.addResource(`${e}${t}RealtimeCPUAlarm`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${e}-${t}-realtime-high-cpu`,AlarmDescription:"Realtime server CPU utilization is high",MetricName:"CPUUtilization",Namespace:"AWS/ECS",Statistic:"Average",Period:300,EvaluationPeriods:2,Threshold:80,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"ClusterName",Value:{Ref:"ECSCluster"}},{Name:"ServiceName",Value:`${e}-${t}-realtime`}],...g&&{AlarmActions:[g]}},DependsOn:A}),this.builder.addResource(`${e}${t}RealtimeMemoryAlarm`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${e}-${t}-realtime-high-memory`,AlarmDescription:"Realtime server memory utilization is high",MetricName:"MemoryUtilization",Namespace:"AWS/ECS",Statistic:"Average",Period:300,EvaluationPeriods:2,Threshold:80,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"ClusterName",Value:{Ref:"ECSCluster"}},{Name:"ServiceName",Value:`${e}-${t}-realtime`}],...g&&{AlarmActions:[g]}},DependsOn:A})}this.builder.addOutput(`${e}${t}RealtimeEndpoint`.replace(/[^a-zA-Z0-9]/g,""),{Description:"Realtime WebSocket server endpoint",Value:{"Fn::Sub":`wss://${e}-${t}-realtime.\${AWS::Region}.elb.amazonaws.com:${o}`},Export:{Name:{"Fn::Sub":"${AWS::StackName}-realtime-endpoint"}}})}generateBroadcastConfig(){let e=this.mergedConfig.infrastructure?.realtime;if(!e||e.mode!=="server")return"";let t=e.server||{};return`import type { BroadcastConfig } from 'ts-broadcasting'
173
+ `.trim()}generateRealtimeServerResources($,M){let J=this.mergedConfig.infrastructure?.realtime;if(!J)return;let X=J.server||{},Y=X.port||6001,U=X.instances||1,Q=`${$}${M}RealtimeSG`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(Q,{Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:`Security group for ${$} realtime WebSocket server`,GroupName:`${$}-${M}-realtime-sg`,VpcId:{Ref:"VPC"},SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:Y,ToPort:Y,CidrIp:"0.0.0.0/0",Description:"WebSocket connections"},{IpProtocol:"tcp",FromPort:443,ToPort:443,CidrIp:"0.0.0.0/0",Description:"HTTPS/WSS connections"}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound"}],Tags:[{Key:"Name",Value:`${$}-${M}-realtime-sg`},{Key:"Environment",Value:M}]}});let _=`${$}${M}RealtimeTaskDef`.replace(/[^a-zA-Z0-9]/g,""),K=`${$}${M}RealtimeTaskRole`.replace(/[^a-zA-Z0-9]/g,""),V=`${$}${M}RealtimeExecRole`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(V,{Type:"AWS::IAM::Role",Properties:{RoleName:`${$}-${M}-realtime-exec-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"]}}),this.builder.addResource(K,{Type:"AWS::IAM::Role",Properties:{RoleName:`${$}-${M}-realtime-task-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"RealtimeTaskPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogStream","logs:PutLogEvents"],Resource:"*"},...X.redis?.enabled?[{Effect:"Allow",Action:["elasticache:DescribeCacheClusters","elasticache:DescribeReplicationGroups"],Resource:"*"}]:[]]}}]}});let G=[{Name:"BROADCAST_HOST",Value:X.host||"0.0.0.0"},{Name:"BROADCAST_PORT",Value:String(Y)},{Name:"NODE_ENV",Value:M==="production"?"production":"development"}];if(X.redis?.enabled){if(X.redis.useElastiCache)G.push({Name:"REDIS_HOST",Value:{"Fn::GetAtt":["CacheCluster","RedisEndpoint.Address"]}}),G.push({Name:"REDIS_PORT",Value:{"Fn::GetAtt":["CacheCluster","RedisEndpoint.Port"]}});else G.push({Name:"REDIS_HOST",Value:X.redis.host||"localhost"}),G.push({Name:"REDIS_PORT",Value:String(X.redis.port||6379)});if(X.redis.keyPrefix)G.push({Name:"REDIS_KEY_PREFIX",Value:X.redis.keyPrefix})}this.builder.addResource(_,{Type:"AWS::ECS::TaskDefinition",Properties:{Family:`${$}-${M}-realtime`,NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:"512",Memory:"1024",ExecutionRoleArn:{"Fn::GetAtt":[V,"Arn"]},TaskRoleArn:{"Fn::GetAtt":[K,"Arn"]},ContainerDefinitions:[{Name:"realtime",Image:{"Fn::Sub":`\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.amazonaws.com/${$}-realtime:latest`},Essential:!0,PortMappings:[{ContainerPort:Y,Protocol:"tcp"}],Environment:G,LogConfiguration:{LogDriver:"awslogs",Options:{"awslogs-group":`/ecs/${$}-${M}-realtime`,"awslogs-region":{Ref:"AWS::Region"},"awslogs-stream-prefix":"realtime"}},HealthCheck:{Command:["CMD-SHELL",`curl -f http://localhost:${Y}${X.healthCheckPath||"/health"} || exit 1`],Interval:30,Timeout:5,Retries:3,StartPeriod:60}}],Tags:[{Key:"Name",Value:`${$}-${M}-realtime`},{Key:"Environment",Value:M}]},DependsOn:[V,K]});let q=`${$}${M}RealtimeLogs`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(q,{Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:`/ecs/${$}-${M}-realtime`,RetentionInDays:30}});let A=`${$}${M}RealtimeService`.replace(/[^a-zA-Z0-9]/g,"");if(this.builder.addResource(A,{Type:"AWS::ECS::Service",Properties:{ServiceName:`${$}-${M}-realtime`,Cluster:{Ref:"ECSCluster"},TaskDefinition:{Ref:_},DesiredCount:U,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{AssignPublicIp:"ENABLED",SecurityGroups:[{Ref:Q}],Subnets:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]}},HealthCheckGracePeriodSeconds:60,Tags:[{Key:"Name",Value:`${$}-${M}-realtime`},{Key:"Environment",Value:M}]},DependsOn:[_,Q,q]}),X.autoScaling){let P=X.autoScaling,E=`${$}${M}RealtimeScalableTarget`.replace(/[^a-zA-Z0-9]/g,"");if(this.builder.addResource(E,{Type:"AWS::ApplicationAutoScaling::ScalableTarget",Properties:{MaxCapacity:P.max||10,MinCapacity:P.min||1,ResourceId:{"Fn::Sub":`service/\${ECSCluster}/${$}-${M}-realtime`},RoleARN:{"Fn::Sub":"arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService"},ScalableDimension:"ecs:service:DesiredCount",ServiceNamespace:"ecs"},DependsOn:A}),P.targetCPU)this.builder.addResource(`${$}${M}RealtimeCPUPolicy`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::ApplicationAutoScaling::ScalingPolicy",Properties:{PolicyName:`${$}-${M}-realtime-cpu-scaling`,PolicyType:"TargetTrackingScaling",ScalingTargetId:{Ref:E},TargetTrackingScalingPolicyConfiguration:{PredefinedMetricSpecification:{PredefinedMetricType:"ECSServiceAverageCPUUtilization"},TargetValue:P.targetCPU,ScaleInCooldown:300,ScaleOutCooldown:60}}})}if(J.monitoring?.enabled){let P=J.monitoring,E=P.notificationTopicArn;if(!E&&P.notificationEmails?.length){let O=`${$}${M}RealtimeAlarmTopic`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(O,{Type:"AWS::SNS::Topic",Properties:{TopicName:`${$}-${M}-realtime-alarms`,DisplayName:"Realtime Server Alarms"}}),P.notificationEmails.forEach((F,R)=>{this.builder.addResource(`${O}Sub${R}`,{Type:"AWS::SNS::Subscription",Properties:{TopicArn:{Ref:O},Protocol:"email",Endpoint:F}})}),E={Ref:O}}this.builder.addResource(`${$}${M}RealtimeCPUAlarm`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${$}-${M}-realtime-high-cpu`,AlarmDescription:"Realtime server CPU utilization is high",MetricName:"CPUUtilization",Namespace:"AWS/ECS",Statistic:"Average",Period:300,EvaluationPeriods:2,Threshold:80,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"ClusterName",Value:{Ref:"ECSCluster"}},{Name:"ServiceName",Value:`${$}-${M}-realtime`}],...E&&{AlarmActions:[E]}},DependsOn:A}),this.builder.addResource(`${$}${M}RealtimeMemoryAlarm`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${$}-${M}-realtime-high-memory`,AlarmDescription:"Realtime server memory utilization is high",MetricName:"MemoryUtilization",Namespace:"AWS/ECS",Statistic:"Average",Period:300,EvaluationPeriods:2,Threshold:80,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"ClusterName",Value:{Ref:"ECSCluster"}},{Name:"ServiceName",Value:`${$}-${M}-realtime`}],...E&&{AlarmActions:[E]}},DependsOn:A})}this.builder.addOutput(`${$}${M}RealtimeEndpoint`.replace(/[^a-zA-Z0-9]/g,""),{Description:"Realtime WebSocket server endpoint",Value:{"Fn::Sub":`wss://${$}-${M}-realtime.\${AWS::Region}.elb.amazonaws.com:${Y}`},Export:{Name:{"Fn::Sub":"${AWS::StackName}-realtime-endpoint"}}})}generateBroadcastConfig(){let $=this.mergedConfig.infrastructure?.realtime;if(!$||$.mode!=="server")return"";let M=$.server||{};return`import type { BroadcastConfig } from 'ts-broadcasting'
174
174
 
175
175
  export default {
176
176
  verbose: ${this.environment!=="production"},
177
- driver: '${t.driver||"bun"}',
177
+ driver: '${M.driver||"bun"}',
178
178
  default: 'bun',
179
179
 
180
180
  connections: {
181
181
  bun: {
182
182
  driver: 'bun',
183
- host: process.env.BROADCAST_HOST || '${t.host||"0.0.0.0"}',
184
- port: Number(process.env.BROADCAST_PORT) || ${t.port||6001},
185
- scheme: '${t.scheme||"wss"}',
183
+ host: process.env.BROADCAST_HOST || '${M.host||"0.0.0.0"}',
184
+ port: Number(process.env.BROADCAST_PORT) || ${M.port||6001},
185
+ scheme: '${M.scheme||"wss"}',
186
186
  options: {
187
- idleTimeout: ${t.idleTimeout||120},
188
- maxPayloadLength: ${t.maxPayloadLength||16777216},
189
- backpressureLimit: ${t.backpressureLimit||1048576},
190
- closeOnBackpressureLimit: ${t.closeOnBackpressureLimit||!1},
191
- sendPings: ${t.sendPings!==!1},
192
- perMessageDeflate: ${t.perMessageDeflate!==!1},
187
+ idleTimeout: ${M.idleTimeout||120},
188
+ maxPayloadLength: ${M.maxPayloadLength||16777216},
189
+ backpressureLimit: ${M.backpressureLimit||1048576},
190
+ closeOnBackpressureLimit: ${M.closeOnBackpressureLimit||!1},
191
+ sendPings: ${M.sendPings!==!1},
192
+ perMessageDeflate: ${M.perMessageDeflate!==!1},
193
193
  },
194
194
  },
195
195
  },
196
- ${t.redis?.enabled?`
196
+ ${M.redis?.enabled?`
197
197
  redis: {
198
- host: process.env.REDIS_HOST || '${t.redis.host||"localhost"}',
199
- port: Number(process.env.REDIS_PORT) || ${t.redis.port||6379},
200
- ${t.redis.password?`password: process.env.REDIS_PASSWORD || '${t.redis.password}',`:""}
201
- database: ${t.redis.database||0},
202
- keyPrefix: '${t.redis.keyPrefix||"broadcasting:"}',
198
+ host: process.env.REDIS_HOST || '${M.redis.host||"localhost"}',
199
+ port: Number(process.env.REDIS_PORT) || ${M.redis.port||6379},
200
+ ${M.redis.password?`password: process.env.REDIS_PASSWORD || '${M.redis.password}',`:""}
201
+ database: ${M.redis.database||0},
202
+ keyPrefix: '${M.redis.keyPrefix||"broadcasting:"}',
203
203
  },
204
204
  `:""}
205
- ${t.rateLimit?.enabled?`
205
+ ${M.rateLimit?.enabled?`
206
206
  rateLimit: {
207
- max: ${t.rateLimit.max||100},
208
- window: ${t.rateLimit.window||60000},
209
- perChannel: ${t.rateLimit.perChannel!==!1},
210
- perUser: ${t.rateLimit.perUser!==!1},
207
+ max: ${M.rateLimit.max||100},
208
+ window: ${M.rateLimit.window||60000},
209
+ perChannel: ${M.rateLimit.perChannel!==!1},
210
+ perUser: ${M.rateLimit.perUser!==!1},
211
211
  },
212
212
  `:""}
213
- ${t.loadManagement?.enabled?`
213
+ ${M.loadManagement?.enabled?`
214
214
  loadManagement: {
215
215
  enabled: true,
216
- maxConnections: ${t.loadManagement.maxConnections||1e4},
217
- maxSubscriptionsPerConnection: ${t.loadManagement.maxSubscriptionsPerConnection||100},
218
- shedLoadThreshold: ${t.loadManagement.shedLoadThreshold||0.8},
216
+ maxConnections: ${M.loadManagement.maxConnections||1e4},
217
+ maxSubscriptionsPerConnection: ${M.loadManagement.maxSubscriptionsPerConnection||100},
218
+ shedLoadThreshold: ${M.loadManagement.shedLoadThreshold||0.8},
219
219
  },
220
220
  `:""}
221
221
  } satisfies BroadcastConfig
222
- `}toYAML(){return this.builder.toYAML()}toJSON(){return this.builder.toJSON()}getBuilder(){return this.builder}}function ze(e){let t=[],r=[];if(!e.AWSTemplateFormatVersion)t.push({path:"AWSTemplateFormatVersion",message:"AWSTemplateFormatVersion is required",severity:"error"});else if(e.AWSTemplateFormatVersion!=="2010-09-09")r.push({path:"AWSTemplateFormatVersion",message:'AWSTemplateFormatVersion should be "2010-09-09"',severity:"warning"});if(!e.Resources||Object.keys(e.Resources).length===0)t.push({path:"Resources",message:"At least one resource is required",severity:"error"});else for(let[n,o]of Object.entries(e.Resources))Ge(n,o,t,r);if(e.Resources){let n=qe(e.Resources);if(n.length>0)t.push({path:"Resources",message:`Circular dependencies detected: ${n.join(" -> ")}`,severity:"error"})}if(e.Parameters)for(let[n,o]of Object.entries(e.Parameters))Ue(n,o,t,r);if(e.Outputs)for(let[n,o]of Object.entries(e.Outputs))Ke(n,o,t,r);return{valid:t.length===0,errors:t,warnings:r}}function Ge(e,t,r,n){if(!t.Type)r.push({path:`Resources.${e}.Type`,message:"Resource Type is required",severity:"error"});if(!/^[a-zA-Z0-9]+$/.test(e))n.push({path:`Resources.${e}`,message:"Logical ID should only contain alphanumeric characters",severity:"warning"});if(t.Type&&!t.Type.startsWith("AWS::")&&!t.Type.startsWith("Custom::"))r.push({path:`Resources.${e}.Type`,message:'Resource Type must start with "AWS::" or "Custom::"',severity:"error"});if(t.Properties){for(let[o,l]of Object.entries(t.Properties))if(l===void 0||l===null)n.push({path:`Resources.${e}.Properties.${o}`,message:"Property has undefined or null value",severity:"warning"})}if(t.DependsOn){if(typeof t.DependsOn==="string"){if(t.DependsOn===e)r.push({path:`Resources.${e}.DependsOn`,message:"Resource cannot depend on itself",severity:"error"})}else if(Array.isArray(t.DependsOn)){if(t.DependsOn.includes(e))r.push({path:`Resources.${e}.DependsOn`,message:"Resource cannot depend on itself",severity:"error"})}}}function Ue(e,t,r,n){if(!t.Type)r.push({path:`Parameters.${e}.Type`,message:"Parameter Type is required",severity:"error"});let o=["String","Number","List<Number>","CommaDelimitedList","AWS::SSM::Parameter::Value<String>"];if(t.Type&&!o.includes(t.Type)&&!t.Type.startsWith("AWS::"))n.push({path:`Parameters.${e}.Type`,message:`Uncommon parameter type: ${t.Type}`,severity:"warning"});if(t.NoEcho&&t.Default)n.push({path:`Parameters.${e}`,message:"NoEcho parameters should not have default values",severity:"warning"})}function Ke(e,t,r,n){if(!t.Value)r.push({path:`Outputs.${e}.Value`,message:"Output Value is required",severity:"error"})}function qe(e){let t={};for(let[c,s]of Object.entries(e)){if(t[c]=[],s.DependsOn){if(typeof s.DependsOn==="string")t[c].push(s.DependsOn);else if(Array.isArray(s.DependsOn))t[c].push(...s.DependsOn)}let u=ie(s);t[c].push(...u)}let r=new Set,n=new Set,o=[];function l(c,s){r.add(c),n.add(c),s.push(c);let u=t[c]||[];for(let h of u)if(!r.has(h)){if(l(h,s))return!0}else if(n.has(h)){let d=s.indexOf(h);return o.push(...s.slice(d),h),!0}return s.pop(),n.delete(c),!1}for(let c of Object.keys(t))if(!r.has(c)){if(l(c,[]))return o}return[]}function ie(e,t=[]){if(typeof e!=="object"||e===null)return t;if(Array.isArray(e)){for(let r of e)ie(r,t);return t}if(e.Ref&&typeof e.Ref==="string"&&!e.Ref.startsWith("AWS::"))t.push(e.Ref);if(e["Fn::GetAtt"]){let r=e["Fn::GetAtt"];if(Array.isArray(r)&&r.length>0)t.push(r[0])}for(let r of Object.values(e))ie(r,t);return t}function Ze(e){let t=[],r=[],n=new TextEncoder().encode(e).length,o=51200,l=460800;if(n>51200)if(n>460800)t.push({path:"template",message:`Template size (${n} bytes) exceeds maximum allowed size of 460800 bytes`,severity:"error"});else r.push({path:"template",message:`Template size (${n} bytes) exceeds direct upload limit (51200 bytes). You must upload to S3 first.`,severity:"warning"});return{valid:t.length===0,errors:t,warnings:r}}function je(e){let t=[],r=[],n=e.Resources?Object.keys(e.Resources).length:0,o=e.Parameters?Object.keys(e.Parameters).length:0,l=e.Outputs?Object.keys(e.Outputs).length:0;if(n>500)t.push({path:"Resources",message:`Template has ${n} resources, exceeding the limit of 500`,severity:"error"});else if(n>200)r.push({path:"Resources",message:`Template has ${n} resources. Consider using nested stacks for better organization.`,severity:"warning"});if(o>200)t.push({path:"Parameters",message:`Template has ${o} parameters, exceeding the limit of 200`,severity:"error"});if(l>200)t.push({path:"Outputs",message:`Template has ${l} outputs, exceeding the limit of 200`,severity:"error"});return{valid:t.length===0,errors:t,warnings:r}}function Xi(e){let{domains:t,email:r,staging:n=!1,challengeType:o="http-01",certPath:l="/etc/letsencrypt/live",autoRenew:c=!0}=e,s=t[0],u=t.map((d)=>`-d ${d}`).join(" "),h=n?"--staging":"";if(o==="http-01")return Ye({domains:t,email:r,staging:n,certPath:l,autoRenew:c,domainFlags:u,stagingFlag:h,primaryDomain:s});else{let d=e.dnsProvider?.provider||(e.hostedZoneId?"route53":void 0);return Qe({domains:t,email:r,staging:n,certPath:l,autoRenew:c,domainFlags:u,stagingFlag:h,primaryDomain:s,hostedZoneId:e.hostedZoneId,dnsProvider:e.dnsProvider,dnsProviderType:d})}}function Ye(e){let{email:t,certPath:r,autoRenew:n,domainFlags:o,stagingFlag:l,primaryDomain:c}=e;return`
222
+ `}toYAML(){return this.builder.toYAML()}toJSON(){return this.builder.toJSON()}getBuilder(){return this.builder}}function g0($){let M=[],J=[];if(!$.AWSTemplateFormatVersion)M.push({path:"AWSTemplateFormatVersion",message:"AWSTemplateFormatVersion is required",severity:"error"});else if($.AWSTemplateFormatVersion!=="2010-09-09")J.push({path:"AWSTemplateFormatVersion",message:'AWSTemplateFormatVersion should be "2010-09-09"',severity:"warning"});if(!$.Resources||Object.keys($.Resources).length===0)M.push({path:"Resources",message:"At least one resource is required",severity:"error"});else for(let[X,Y]of Object.entries($.Resources))i0(X,Y,M,J);if($.Resources){let X=s0($.Resources);if(X.length>0)M.push({path:"Resources",message:`Circular dependencies detected: ${X.join(" -> ")}`,severity:"error"})}if($.Parameters)for(let[X,Y]of Object.entries($.Parameters))a0(X,Y,M,J);if($.Outputs)for(let[X,Y]of Object.entries($.Outputs))o0(X,Y,M,J);return{valid:M.length===0,errors:M,warnings:J}}function i0($,M,J,X){if(!M.Type)J.push({path:`Resources.${$}.Type`,message:"Resource Type is required",severity:"error"});if(!/^[a-zA-Z0-9]+$/.test($))X.push({path:`Resources.${$}`,message:"Logical ID should only contain alphanumeric characters",severity:"warning"});if(M.Type&&!M.Type.startsWith("AWS::")&&!M.Type.startsWith("Custom::"))J.push({path:`Resources.${$}.Type`,message:'Resource Type must start with "AWS::" or "Custom::"',severity:"error"});if(M.Properties){for(let[Y,U]of Object.entries(M.Properties))if(U===void 0||U===null)X.push({path:`Resources.${$}.Properties.${Y}`,message:"Property has undefined or null value",severity:"warning"})}if(M.DependsOn){if(typeof M.DependsOn==="string"){if(M.DependsOn===$)J.push({path:`Resources.${$}.DependsOn`,message:"Resource cannot depend on itself",severity:"error"})}else if(Array.isArray(M.DependsOn)){if(M.DependsOn.includes($))J.push({path:`Resources.${$}.DependsOn`,message:"Resource cannot depend on itself",severity:"error"})}}}function a0($,M,J,X){if(!M.Type)J.push({path:`Parameters.${$}.Type`,message:"Parameter Type is required",severity:"error"});let Y=["String","Number","List<Number>","CommaDelimitedList","AWS::SSM::Parameter::Value<String>"];if(M.Type&&!Y.includes(M.Type)&&!M.Type.startsWith("AWS::"))X.push({path:`Parameters.${$}.Type`,message:`Uncommon parameter type: ${M.Type}`,severity:"warning"});if(M.NoEcho&&M.Default)X.push({path:`Parameters.${$}`,message:"NoEcho parameters should not have default values",severity:"warning"})}function o0($,M,J,X){if(!M.Value)J.push({path:`Outputs.${$}.Value`,message:"Output Value is required",severity:"error"})}function s0($){let M={};for(let[Q,_]of Object.entries($)){if(M[Q]=[],_.DependsOn){if(typeof _.DependsOn==="string")M[Q].push(_.DependsOn);else if(Array.isArray(_.DependsOn))M[Q].push(..._.DependsOn)}let K=W0(_);M[Q].push(...K)}let J=new Set,X=new Set,Y=[];function U(Q,_){J.add(Q),X.add(Q),_.push(Q);let K=M[Q]||[];for(let V of K)if(!J.has(V)){if(U(V,_))return!0}else if(X.has(V)){let G=_.indexOf(V);return Y.push(..._.slice(G),V),!0}return _.pop(),X.delete(Q),!1}for(let Q of Object.keys(M))if(!J.has(Q)){if(U(Q,[]))return Y}return[]}function W0($,M=[]){if(typeof $!=="object"||$===null)return M;if(Array.isArray($)){for(let J of $)W0(J,M);return M}if($.Ref&&typeof $.Ref==="string"&&!$.Ref.startsWith("AWS::"))M.push($.Ref);if($["Fn::GetAtt"]){let J=$["Fn::GetAtt"];if(Array.isArray(J)&&J.length>0)M.push(J[0])}for(let J of Object.values($))W0(J,M);return M}function n0($){let M=[],J=[],X=new TextEncoder().encode($).length,Y=51200,U=460800;if(X>51200)if(X>460800)M.push({path:"template",message:`Template size (${X} bytes) exceeds maximum allowed size of 460800 bytes`,severity:"error"});else J.push({path:"template",message:`Template size (${X} bytes) exceeds direct upload limit (51200 bytes). You must upload to S3 first.`,severity:"warning"});return{valid:M.length===0,errors:M,warnings:J}}function e0($){let M=[],J=[],X=$.Resources?Object.keys($.Resources).length:0,Y=$.Parameters?Object.keys($.Parameters).length:0,U=$.Outputs?Object.keys($.Outputs).length:0;if(X>500)M.push({path:"Resources",message:`Template has ${X} resources, exceeding the limit of 500`,severity:"error"});else if(X>200)J.push({path:"Resources",message:`Template has ${X} resources. Consider using nested stacks for better organization.`,severity:"warning"});if(Y>200)M.push({path:"Parameters",message:`Template has ${Y} parameters, exceeding the limit of 200`,severity:"error"});if(U>200)M.push({path:"Outputs",message:`Template has ${U} outputs, exceeding the limit of 200`,severity:"error"});return{valid:M.length===0,errors:M,warnings:J}}function _8($){let{domains:M,email:J,staging:X=!1,challengeType:Y="http-01",certPath:U="/etc/letsencrypt/live",autoRenew:Q=!0}=$,_=M[0],K=M.map((G)=>`-d ${G}`).join(" "),V=X?"--staging":"";if(Y==="http-01")return $$({domains:M,email:J,staging:X,certPath:U,autoRenew:Q,domainFlags:K,stagingFlag:V,primaryDomain:_});else{let G=$.dnsProvider?.provider||($.hostedZoneId?"route53":void 0);return M$({domains:M,email:J,staging:X,certPath:U,autoRenew:Q,domainFlags:K,stagingFlag:V,primaryDomain:_,hostedZoneId:$.hostedZoneId,dnsProvider:$.dnsProvider,dnsProviderType:G})}}function $$($){let{email:M,certPath:J,autoRenew:X,domainFlags:Y,stagingFlag:U,primaryDomain:Q}=$;return`
223
223
  # ==========================================
224
224
  # Let's Encrypt Certificate Setup (HTTP-01)
225
225
  # ==========================================
@@ -235,29 +235,29 @@ certbot certonly \\
235
235
  --standalone \\
236
236
  --non-interactive \\
237
237
  --agree-tos \\
238
- --email ${t} \\
239
- ${l} \\
240
- ${o}
238
+ --email ${M} \\
239
+ ${U} \\
240
+ ${Y}
241
241
 
242
242
  # Check if certificate was obtained
243
- if [ -f "${r}/${c}/fullchain.pem" ]; then
243
+ if [ -f "${J}/${Q}/fullchain.pem" ]; then
244
244
  echo "Certificate obtained successfully!"
245
245
 
246
246
  # Create symlinks for easier access
247
247
  mkdir -p /etc/ssl/stacks
248
- ln -sf ${r}/${c}/fullchain.pem /etc/ssl/stacks/fullchain.pem
249
- ln -sf ${r}/${c}/privkey.pem /etc/ssl/stacks/privkey.pem
250
- ln -sf ${r}/${c}/cert.pem /etc/ssl/stacks/cert.pem
251
- ln -sf ${r}/${c}/chain.pem /etc/ssl/stacks/chain.pem
248
+ ln -sf ${J}/${Q}/fullchain.pem /etc/ssl/stacks/fullchain.pem
249
+ ln -sf ${J}/${Q}/privkey.pem /etc/ssl/stacks/privkey.pem
250
+ ln -sf ${J}/${Q}/cert.pem /etc/ssl/stacks/cert.pem
251
+ ln -sf ${J}/${Q}/chain.pem /etc/ssl/stacks/chain.pem
252
252
  else
253
253
  echo "Failed to obtain certificate!"
254
254
  fi
255
255
 
256
- ${n?oe(c):"# Auto-renewal disabled"}
256
+ ${X?_0(Q):"# Auto-renewal disabled"}
257
257
 
258
258
  # Restart the application
259
259
  systemctl start stacks
260
- `}function Qe(e){let{email:t,certPath:r,autoRenew:n,domainFlags:o,stagingFlag:l,primaryDomain:c,hostedZoneId:s,dnsProvider:u,dnsProviderType:h}=e;if(h==="route53"||s){if(!s)throw Error("hostedZoneId is required for DNS-01 challenge with Route53");return`
260
+ `}function M$($){let{email:M,certPath:J,autoRenew:X,domainFlags:Y,stagingFlag:U,primaryDomain:Q,hostedZoneId:_,dnsProvider:K,dnsProviderType:V}=$;if(V==="route53"||_){if(!_)throw Error("hostedZoneId is required for DNS-01 challenge with Route53");return`
261
261
  # ==========================================
262
262
  # Let's Encrypt Certificate Setup (DNS-01 via Route53)
263
263
  # ==========================================
@@ -270,49 +270,49 @@ certbot certonly \\
270
270
  --dns-route53 \\
271
271
  --non-interactive \\
272
272
  --agree-tos \\
273
- --email ${t} \\
274
- ${l} \\
275
- ${o}
273
+ --email ${M} \\
274
+ ${U} \\
275
+ ${Y}
276
276
 
277
277
  # Check if certificate was obtained
278
- if [ -f "${r}/${c}/fullchain.pem" ]; then
278
+ if [ -f "${J}/${Q}/fullchain.pem" ]; then
279
279
  echo "Certificate obtained successfully!"
280
280
 
281
281
  # Create symlinks for easier access
282
282
  mkdir -p /etc/ssl/stacks
283
- ln -sf ${r}/${c}/fullchain.pem /etc/ssl/stacks/fullchain.pem
284
- ln -sf ${r}/${c}/privkey.pem /etc/ssl/stacks/privkey.pem
285
- ln -sf ${r}/${c}/cert.pem /etc/ssl/stacks/cert.pem
286
- ln -sf ${r}/${c}/chain.pem /etc/ssl/stacks/chain.pem
283
+ ln -sf ${J}/${Q}/fullchain.pem /etc/ssl/stacks/fullchain.pem
284
+ ln -sf ${J}/${Q}/privkey.pem /etc/ssl/stacks/privkey.pem
285
+ ln -sf ${J}/${Q}/cert.pem /etc/ssl/stacks/cert.pem
286
+ ln -sf ${J}/${Q}/chain.pem /etc/ssl/stacks/chain.pem
287
287
  else
288
288
  echo "Failed to obtain certificate!"
289
289
  fi
290
290
 
291
- ${n?oe(c):"# Auto-renewal disabled"}
292
- `}if(!u)throw Error("dnsProvider configuration is required for DNS-01 challenge with external DNS providers");let d=u.provider.toUpperCase(),b=Xe(u);return`
291
+ ${X?_0(Q):"# Auto-renewal disabled"}
292
+ `}if(!K)throw Error("dnsProvider configuration is required for DNS-01 challenge with external DNS providers");let G=K.provider.toUpperCase(),q=J$(K);return`
293
293
  # ==========================================
294
- # Let's Encrypt Certificate Setup (DNS-01 via ${d})
294
+ # Let's Encrypt Certificate Setup (DNS-01 via ${G})
295
295
  # ==========================================
296
296
 
297
297
  # Install certbot
298
298
  dnf install -y certbot jq curl
299
299
 
300
- ${b}
300
+ ${q}
301
301
 
302
302
  # Create DNS challenge hook scripts directory
303
303
  mkdir -p /etc/letsencrypt/hooks
304
304
 
305
- # Create authenticator hook for ${d}
305
+ # Create authenticator hook for ${G}
306
306
  cat > /etc/letsencrypt/hooks/auth-hook.sh << 'AUTHHOOK'
307
307
  #!/bin/bash
308
- # DNS-01 authenticator hook for ${d}
308
+ # DNS-01 authenticator hook for ${G}
309
309
  # This creates the TXT record for ACME challenge
310
310
 
311
311
  DOMAIN="$CERTBOT_DOMAIN"
312
312
  VALIDATION="$CERTBOT_VALIDATION"
313
313
  RECORD_NAME="_acme-challenge.$DOMAIN"
314
314
 
315
- ${et(u)}
315
+ ${X$(K)}
316
316
 
317
317
  # Wait for DNS propagation
318
318
  echo "Waiting 60 seconds for DNS propagation..."
@@ -321,17 +321,17 @@ AUTHHOOK
321
321
 
322
322
  chmod +x /etc/letsencrypt/hooks/auth-hook.sh
323
323
 
324
- # Create cleanup hook for ${d}
324
+ # Create cleanup hook for ${G}
325
325
  cat > /etc/letsencrypt/hooks/cleanup-hook.sh << 'CLEANUPHOOK'
326
326
  #!/bin/bash
327
- # DNS-01 cleanup hook for ${d}
327
+ # DNS-01 cleanup hook for ${G}
328
328
  # This removes the TXT record after validation
329
329
 
330
330
  DOMAIN="$CERTBOT_DOMAIN"
331
331
  VALIDATION="$CERTBOT_VALIDATION"
332
332
  RECORD_NAME="_acme-challenge.$DOMAIN"
333
333
 
334
- ${tt(u)}
334
+ ${Y$(K)}
335
335
  CLEANUPHOOK
336
336
 
337
337
  chmod +x /etc/letsencrypt/hooks/cleanup-hook.sh
@@ -344,37 +344,37 @@ certbot certonly \\
344
344
  --manual-cleanup-hook /etc/letsencrypt/hooks/cleanup-hook.sh \\
345
345
  --non-interactive \\
346
346
  --agree-tos \\
347
- --email ${t} \\
348
- ${l} \\
349
- ${o}
347
+ --email ${M} \\
348
+ ${U} \\
349
+ ${Y}
350
350
 
351
351
  # Check if certificate was obtained
352
- if [ -f "${r}/${c}/fullchain.pem" ]; then
352
+ if [ -f "${J}/${Q}/fullchain.pem" ]; then
353
353
  echo "Certificate obtained successfully!"
354
354
 
355
355
  # Create symlinks for easier access
356
356
  mkdir -p /etc/ssl/stacks
357
- ln -sf ${r}/${c}/fullchain.pem /etc/ssl/stacks/fullchain.pem
358
- ln -sf ${r}/${c}/privkey.pem /etc/ssl/stacks/privkey.pem
359
- ln -sf ${r}/${c}/cert.pem /etc/ssl/stacks/cert.pem
360
- ln -sf ${r}/${c}/chain.pem /etc/ssl/stacks/chain.pem
357
+ ln -sf ${J}/${Q}/fullchain.pem /etc/ssl/stacks/fullchain.pem
358
+ ln -sf ${J}/${Q}/privkey.pem /etc/ssl/stacks/privkey.pem
359
+ ln -sf ${J}/${Q}/cert.pem /etc/ssl/stacks/cert.pem
360
+ ln -sf ${J}/${Q}/chain.pem /etc/ssl/stacks/chain.pem
361
361
  else
362
362
  echo "Failed to obtain certificate!"
363
363
  fi
364
364
 
365
- ${n?oe(c):"# Auto-renewal disabled"}
366
- `}function Xe(e){switch(e.provider){case"porkbun":return`
365
+ ${X?_0(Q):"# Auto-renewal disabled"}
366
+ `}function J$($){switch($.provider){case"porkbun":return`
367
367
  # Porkbun API credentials
368
- export PORKBUN_API_KEY="${e.apiKey}"
369
- export PORKBUN_SECRET_KEY="${e.secretKey}"
368
+ export PORKBUN_API_KEY="${$.apiKey}"
369
+ export PORKBUN_SECRET_KEY="${$.secretKey}"
370
370
  `;case"godaddy":return`
371
371
  # GoDaddy API credentials
372
- export GODADDY_API_KEY="${e.apiKey}"
373
- export GODADDY_API_SECRET="${e.apiSecret}"
374
- export GODADDY_ENV="${e.environment||"production"}"
372
+ export GODADDY_API_KEY="${$.apiKey}"
373
+ export GODADDY_API_SECRET="${$.apiSecret}"
374
+ export GODADDY_ENV="${$.environment||"production"}"
375
375
  `;case"route53":return`
376
376
  # Route53 uses IAM role credentials
377
- `;default:return""}}function et(e){switch(e.provider){case"porkbun":return`
377
+ `;default:return""}}function X$($){switch($.provider){case"porkbun":return`
378
378
  # Extract root domain (last two parts)
379
379
  ROOT_DOMAIN=$(echo "$DOMAIN" | awk -F. '{print $(NF-1)"."$NF}')
380
380
  SUBDOMAIN="_acme-challenge"
@@ -418,7 +418,7 @@ curl -s -X PATCH "$API_URL/v1/domains/$ROOT_DOMAIN/records" \\
418
418
  "data": "'"$VALIDATION"'",
419
419
  "ttl": 600
420
420
  }]'
421
- `;default:return'echo "Unsupported DNS provider"'}}function tt(e){switch(e.provider){case"porkbun":return`
421
+ `;default:return'echo "Unsupported DNS provider"'}}function Y$($){switch($.provider){case"porkbun":return`
422
422
  # Extract root domain
423
423
  ROOT_DOMAIN=$(echo "$DOMAIN" | awk -F. '{print $(NF-1)"."$NF}')
424
424
 
@@ -461,7 +461,7 @@ fi
461
461
 
462
462
  curl -s -X DELETE "$API_URL/v1/domains/$ROOT_DOMAIN/records/TXT/$RECORD_NAME" \\
463
463
  -H "Authorization: sso-key $GODADDY_API_KEY:$GODADDY_API_SECRET"
464
- `;default:return'echo "Unsupported DNS provider"'}}function oe(e){return`
464
+ `;default:return'echo "Unsupported DNS provider"'}}function _0($){return`
465
465
  # ==========================================
466
466
  # Certificate Auto-Renewal Setup
467
467
  # ==========================================
@@ -506,13 +506,13 @@ systemctl enable certbot-renewal.timer
506
506
  systemctl start certbot-renewal.timer
507
507
 
508
508
  echo "Certificate auto-renewal configured"
509
- `}function eo(e){let{httpPort:t=80,httpsPort:r=443,certPath:n="/etc/ssl/stacks",redirectHttp:o=!0}=e;return`
509
+ `}function Q8($){let{httpPort:M=80,httpsPort:J=443,certPath:X="/etc/ssl/stacks",redirectHttp:Y=!0}=$;return`
510
510
  // HTTPS Server with Let's Encrypt certificates
511
511
  import { readFileSync, existsSync } from 'node:fs'
512
512
 
513
- const CERT_PATH = '${n}'
514
- const HTTP_PORT = ${t}
515
- const HTTPS_PORT = ${r}
513
+ const CERT_PATH = '${X}'
514
+ const HTTP_PORT = ${M}
515
+ const HTTPS_PORT = ${J}
516
516
 
517
517
  // Check if certificates exist
518
518
  const hasCerts = existsSync(\`\${CERT_PATH}/fullchain.pem\`) && existsSync(\`\${CERT_PATH}/privkey.pem\`)
@@ -532,7 +532,7 @@ if (hasCerts) {
532
532
  })
533
533
  console.log(\`HTTPS server running on port \${HTTPS_PORT}\`)
534
534
 
535
- ${o?`
535
+ ${Y?`
536
536
  // Start HTTP server for redirect
537
537
  const httpServer = Bun.serve({
538
538
  port: HTTP_PORT,
@@ -592,5 +592,5 @@ async function handleRequest(request: Request): Promise<Response> {
592
592
  // Implement your request handling here
593
593
  return new Response('Hello from Stacks!')
594
594
  }
595
- `}async function to(e){let{domain:t,challengeValue:r,hostedZoneId:n,dnsProvider:o,region:l="us-east-1"}=e;if(o){let s=await J(o).upsertRecord(t,{name:`_acme-challenge.${t}`,type:"TXT",content:r,ttl:60});if(!s.success)throw Error(`Failed to create DNS challenge record: ${s.message}`);return}if(n){await new j(l).changeResourceRecordSets({HostedZoneId:n,ChangeBatch:{Comment:"ACME DNS-01 challenge",Changes:[{Action:"UPSERT",ResourceRecordSet:{Name:`_acme-challenge.${t}`,Type:"TXT",TTL:60,ResourceRecords:[{Value:`"${r}"`}]}}]}});return}throw Error("Either dnsProvider or hostedZoneId must be provided")}async function ro(e){let{domain:t,challengeValue:r,hostedZoneId:n,dnsProvider:o,region:l="us-east-1"}=e;if(o){let s=await J(o).deleteRecord(t,{name:`_acme-challenge.${t}`,type:"TXT",content:r});if(!s.success)console.warn(`Failed to delete DNS challenge record: ${s.message}`);return}if(n){await new j(l).changeResourceRecordSets({HostedZoneId:n,ChangeBatch:{Comment:"Remove ACME DNS-01 challenge",Changes:[{Action:"DELETE",ResourceRecordSet:{Name:`_acme-challenge.${t}`,Type:"TXT",TTL:60,ResourceRecords:[{Value:`"${r}"`}]}}]}});return}throw Error("Either dnsProvider or hostedZoneId must be provided")}function no(e){try{let{execSync:t}=Je("node:child_process"),r=t(`openssl x509 -checkend 2592000 -noout -in ${e}/cert.pem`,{encoding:"utf-8",stdio:["pipe","pipe","pipe"]});return!1}catch{return!0}}import{createHash as we,createSign as rt,generateKeyPairSync as ve}from"node:crypto";var Oe={production:"https://acme-v02.api.letsencrypt.org/directory",staging:"https://acme-staging-v02.api.letsencrypt.org/directory"};class nt{directoryUrl;email;accountKey;accountUrl=null;directory=null;nonce=null;constructor(e){this.directoryUrl=e.staging?Oe.staging:Oe.production,this.email=e.email,this.accountKey=e.accountKey||this.generateAccountKey()}generateAccountKey(){let{privateKey:e}=ve("ec",{namedCurve:"P-256"});return e.export({type:"pkcs8",format:"pem"})}async getDirectory(){if(this.directory)return this.directory;let e=await fetch(this.directoryUrl);if(!e.ok)throw Error(`Failed to fetch ACME directory: ${e.status}`);return this.directory=await e.json(),this.directory}async getNonce(){if(this.nonce){let n=this.nonce;return this.nonce=null,n}let e=await this.getDirectory(),r=(await fetch(e.newNonce,{method:"HEAD"})).headers.get("replay-nonce");if(!r)throw Error("Failed to get nonce from ACME server");return r}getJwk(){let e=this.accountKey.split(`
596
- `).filter((l)=>!l.startsWith("-----")).join(""),t=Buffer.from(e,"base64"),r=t.length-65,n=t.subarray(r+1,r+33),o=t.subarray(r+33,r+65);return{kty:"EC",crv:"P-256",x:this.base64UrlEncode(n),y:this.base64UrlEncode(o)}}getJwkThumbprint(){let e=this.getJwk(),t=JSON.stringify({crv:e.crv,kty:e.kty,x:e.x,y:e.y}),r=we("sha256").update(t).digest();return this.base64UrlEncode(r)}base64UrlEncode(e){return(typeof e==="string"?Buffer.from(e):e).toString("base64").replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async signPayload(e,t){let r=await this.getNonce(),n=this.getJwk(),o={alg:"ES256",nonce:r,url:e};if(this.accountUrl)o.kid=this.accountUrl;else o.jwk=n;let l=this.base64UrlEncode(JSON.stringify(o)),c=t===""?"":this.base64UrlEncode(JSON.stringify(t)),s=`${l}.${c}`,u=rt("SHA256");u.update(s);let h=u.sign(this.accountKey),d=h.subarray(4,4+h[3]),b=4+h[3]+2,A=h.subarray(b,b+h[b-1]),T=Buffer.alloc(32),g=Buffer.alloc(32);d.copy(T,32-d.length),A.copy(g,32-A.length);let m=Buffer.concat([T,g]);return JSON.stringify({protected:l,payload:c,signature:this.base64UrlEncode(m)})}async acmeRequest(e,t){let r=await this.signPayload(e,t),n=await fetch(e,{method:"POST",headers:{"Content-Type":"application/jose+json"},body:r}),o=n.headers.get("replay-nonce");if(o)this.nonce=o;let l,c=n.headers.get("content-type");if(c?.includes("application/json")||c?.includes("application/problem+json"))l=await n.json();else l=await n.text();if(!n.ok)throw Error(`ACME request failed: ${JSON.stringify(l)}`);return{body:l,headers:n.headers}}async registerAccount(){let e=await this.getDirectory(),{body:t,headers:r}=await this.acmeRequest(e.newAccount,{termsOfServiceAgreed:!0,contact:[`mailto:${this.email}`]}),n=r.get("location");if(!n)throw Error("No account URL returned");return this.accountUrl=n,n}async createOrder(e){if(!this.accountUrl)await this.registerAccount();let t=await this.getDirectory(),{body:r,headers:n}=await this.acmeRequest(t.newOrder,{identifiers:e.map((l)=>({type:"dns",value:l}))}),o=n.get("location");if(!o)throw Error("No order URL returned");return{orderUrl:o,authorizations:r.authorizations,finalize:r.finalize}}async getAuthorization(e){let{body:t}=await this.acmeRequest(e,""),r=t.identifier.value,n=this.getJwkThumbprint(),o=t.challenges.filter((l)=>l.type==="http-01"||l.type==="dns-01").map((l)=>{let c=`${l.token}.${n}`;if(l.type==="http-01")return{type:"http-01",token:l.token,keyAuthorization:c,identifier:`/.well-known/acme-challenge/${l.token}`};else{let s=this.base64UrlEncode(we("sha256").update(c).digest());return{type:"dns-01",token:l.token,keyAuthorization:c,identifier:`_acme-challenge.${r}`,dnsValue:s}}});return{domain:r,challenges:o}}async respondToChallenge(e){await this.acmeRequest(e,{})}async waitForAuthorization(e,t=30){for(let r=0;r<t;r++){let{body:n}=await this.acmeRequest(e,"");if(n.status==="valid")return;if(n.status==="invalid")throw Error(`Authorization failed: ${JSON.stringify(n)}`);await new Promise((o)=>setTimeout(o,2000))}throw Error("Authorization timed out")}generateCsr(e){let{privateKey:t}=ve("rsa",{modulusLength:2048}),r=t.export({type:"pkcs8",format:"pem"});return{csr:this.createSimpleCsr(e,t),privateKey:r}}createSimpleCsr(e,t){throw Error("CSR generation requires additional implementation. Consider using the shell-based certbot approach instead.")}async finalizeOrder(e,t){let{csr:r,privateKey:n}=this.generateCsr(t),{body:o}=await this.acmeRequest(e,{csr:this.base64UrlEncode(Buffer.from(r,"base64"))}),l=o.certificate;if(!l)throw Error("Certificate not immediately available - polling not implemented");let s=await(await fetch(l)).text(),u=s.split(/(?=-----BEGIN CERTIFICATE-----)/g),h=u[0],d=u.slice(1).join("");return{certificate:h,privateKey:n,chain:d,fullchain:s,expiresAt:new Date(Date.now()+7776000000)}}getAccountKey(){return this.accountKey}}var Ne=["js","mjs","cjs","css","map","woff","woff2","ttf","otf","eot","png","jpg","jpeg","gif","webp","avif","svg","ico","mp4","webm","ogg","mp3","wav","pdf","wasm"],it=[{name:"x-stx-router",value:"true"}];function W(e){return`"${e.replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}"`}function ke(e){return`{${e.map(W).join(" ")}}`}function ot(e){let t=`http.request.headers[${W(e.name.toLowerCase())}]`;return e.value===void 0?`len(${t}) > 0`:`any(${t}[*] == ${W(e.value)})`}function ae(e){if(e.length===1)return`http.host eq ${W(e[0])}`;return`http.host in ${ke(e)}`}function se(e,t={}){if(t.enabled===!1||e.length===0)return[];let r=ae(e),n=[],l=(t.bypassPaths??[]).map((T)=>`starts_with(http.request.uri.path, ${W(T)})`),s=(t.negotiatedRequestHeaders??it).map(ot),u=[...l,...s],h=u.length>0?`(${u.join(" or ")})`:void 0;if(h)n.push({action:"set_cache_settings",description:"bypass cache",expression:`(${r} and ${h})`,enabled:!0,action_parameters:{cache:!1}});let d=h?`${r} and not ${h}`:r,b=t.assetExtensions??Ne,A=b.length>0?`lower(http.request.uri.path.extension) in ${ke([...b])}`:void 0;if(A)n.push({action:"set_cache_settings",description:"cache fingerprinted assets",expression:`(${d} and ${A})`,enabled:!0,action_parameters:{cache:!0,edge_ttl:{mode:"override_origin",default:t.assetEdgeTtl??2592000},browser_ttl:{mode:"override_origin",default:t.assetBrowserTtl??31536000}}});return n.push({action:"set_cache_settings",description:"cache documents",expression:A?`(${d} and not ${A})`:`(${d})`,enabled:!0,action_parameters:{cache:!0,edge_ttl:{mode:"override_origin",default:t.documentEdgeTtl??3600},browser_ttl:{mode:"override_origin",default:t.documentBrowserTtl??0}}}),n}function ce(e,t,r){if(e.length===0||!t||!r)return[];return[{action:"rewrite",description:"origin guard header",expression:`(${ae(e)})`,enabled:!0,action_parameters:{headers:{[t]:{operation:"set",value:r}}}}]}var N=(e)=>e===void 0?void 0:e?"on":"off";function le(e){let t={ssl:e.ssl,always_use_https:N(e.alwaysUseHttps),automatic_https_rewrites:N(e.automaticHttpsRewrites),min_tls_version:e.minTlsVersion,tls_1_3:N(e.tls13),brotli:N(e.brotli),http3:N(e.http3),"0rtt":N(e.zeroRtt),early_hints:N(e.earlyHints),browser_cache_ttl:e.browserCacheTtl,always_online:N(e.alwaysOnline),websockets:N(e.websockets),email_obfuscation:N(e.emailObfuscation)};if(e.hsts)t.security_header={strict_transport_security:{enabled:e.hsts.enabled,max_age:e.hsts.maxAge??31536000,include_subdomains:e.hsts.includeSubdomains??!1,preload:e.hsts.preload??!1,nosniff:e.hsts.noSniff??!0}};for(let r of Object.keys(t))if(t[r]===void 0)delete t[r];return{...t,...e.raw??{}}}var H={ssl:"strict",alwaysUseHttps:!0,automaticHttpsRewrites:!0,minTlsVersion:"1.2",tls13:!0,brotli:!0,http3:!0,earlyHints:!0,alwaysOnline:!0,emailObfuscation:!1,browserCacheTtl:0};import{connect as at}from"node:tls";async function de(e){let{address:t,serverName:r,port:n=443,timeoutMs:o=5000}=e;return new Promise((l)=>{let c=!1,s=(h)=>{if(c)return;c=!0;try{u.destroy()}catch{}l(h)},u=at({host:t,port:n,servername:r,rejectUnauthorized:!1,timeout:o});u.once("secureConnect",()=>{if(u.authorized){s({reachable:!0,trusted:!0});return}s({reachable:!0,trusted:!1,reason:u.authorizationError?String(u.authorizationError):"origin certificate is not trusted for this hostname"})}),u.once("timeout",()=>{s({reachable:!1,trusted:!1,reason:`no TLS handshake within ${o}ms`})}),u.once("error",(h)=>{s({reachable:!1,trusted:!1,reason:h.message})})})}function st(e,t){let r=t.replace(/\.$/,"").toLowerCase();return e.some((n)=>{let o=n.replace(/\.$/,"").toLowerCase();if(o===r)return!0;if(!o.startsWith("*."))return!1;let l=o.slice(2);if(!r.endsWith(`.${l}`))return!1;return!r.slice(0,r.length-l.length-1).includes(".")})}async function ct(e){let{provider:t,zone:r,hosts:n,ipv4:o,ipv6:l,proxied:c=!0,settings:s=H,cache:u,originGuard:h,purge:d=!0,ttl:b=300,skipOriginProbe:A=!1,skipEdgeCertificateCheck:T=!1}=e,g={records:[],settingsChanged:[],cacheRules:0,originGuard:!1,purged:!1,deferredProxy:[],warnings:[]};if(n.length===0)return g;let m=[],a=c&&!T?await t.listEdgeCertificateHosts(r):null;for(let i of n){let p=c;if(p&&a&&!st(a,i)){p=!1;let C=a.length===0?"the zone has no active edge certificate yet":`no active edge certificate covers it (${a.join(", ")})`;g.deferredProxy.push({host:i,reason:C}),g.warnings.push(`${i}: publishing DNS-only — ${C}. Proxying it would make Cloudflare terminate TLS with no certificate for the name, which fails the handshake outright rather than degrading. Universal SSL covers the apex and ONE level of subdomain, so a deeper name needs its own certificate; otherwise re-run the deploy once the certificate is active.`)}if(p&&!A){let C=await de({address:o,serverName:i});if(!C.trusted){p=!1;let S=C.reason||"origin is not serving a trusted certificate";g.deferredProxy.push({host:i,reason:S}),g.warnings.push(`${i}: publishing DNS-only for now — the origin does not yet serve a certificate this proxy can verify (${S}). The origin issues certificates over HTTP-01, which needs the name to reach it directly; re-run the deploy once it has one and the record will be proxied.`)}}if(p)m.push(i);let f=[{type:"A",content:o}];if(l&&ue(i))f.push({type:"AAAA",content:l});for(let{type:C,content:S}of f){let R=await t.upsertRecord(r,{name:i,type:C,content:S,ttl:b,proxied:p});if(R.success)g.records.push({host:i,type:C,content:S,proxied:p});else g.warnings.push(`${i} ${C} → ${S} failed: ${R.message||"unknown provider error"}`)}}if(m.length===0){if(c)g.warnings.push("No host is proxied yet, so zone settings, cache rules and purge were skipped — they only take effect through the proxy.");return g}try{let i=le(s),p=await t.applyZoneSettings(r,i);g.settingsChanged=p.changed;for(let f of p.failed)g.warnings.push(`zone setting '${f.id}' could not be applied: ${f.error}`)}catch(i){g.warnings.push(`zone settings could not be read: ${i instanceof Error?i.message:String(i)}`)}let y=se(m,u);if(y.length>0){let i=await t.putManagedPhaseRules(r,"http_request_cache_settings",y);if(i.success)g.cacheRules=y.length;else g.warnings.push(`cache rules could not be written: ${i.message}`)}if(h){let i=ce(m,h.header,h.value);if(i.length>0){let p=await t.putManagedPhaseRules(r,"http_request_late_transform",i);if(p.success)g.originGuard=!0;else g.warnings.push(`origin guard header could not be written: ${p.message}. `+"The gateway will reject requests that lack it — disable the guard or grant the token Transform Rules: Edit.")}}if(d){if(g.purged=await t.purgeCache(r,{hosts:m}),!g.purged)g.warnings.push("edge cache purge failed — new content may take until TTL expiry to appear.")}return g}var lt=(e)=>process.env[e];function xe(e,t){let r=e.replace(/\.$/,"").toLowerCase();if(t){let n=t.replace(/\.$/,"").toLowerCase();if(r===n||r.endsWith(`.${n}`))return n}return r.split(".").slice(-2).join(".")}function dt(e,t={}){let r=t.env??lt,n=e.infrastructure?.compute?.proxy?.cdn,o=[];if(!n||n.provider!=="cloudflare")return{plan:null,errors:o};if(n.originDomain)o.push(`compute.proxy.cdn.originDomain (${n.originDomain}) is ignored for Cloudflare: the proxy forwards to the address in the record it fronts, `+"so no separate origin hostname is needed — and publishing one gives clients a documented way around the edge.");let l=r("CLOUDFLARE_API_TOKEN");if(!l)return o.push("CLOUDFLARE_API_TOKEN is not set — the Cloudflare CDN cannot be reconciled."),{plan:null,errors:o};let c=e.sites??{},s=n.frontedHosts?.length?[...new Set(n.frontedHosts.map((A)=>A.toLowerCase()))]:pe(c,{autoWww:e.infrastructure?.compute?.proxy?.autoWww!==!1});if(s.length===0)return o.push("No hostnames to front — set compute.proxy.cdn.frontedHosts, or give a site a domain."),{plan:null,errors:o};let u=e.infrastructure?.dns?.domain,h=new Set(s.map((A)=>xe(A,u)));if(h.size>1)return o.push(`Fronted hosts span more than one zone (${[...h].join(", ")}). A Cloudflare zone is configured as a unit, so run one CDN config per zone.`),{plan:null,errors:o};let d=n.cloudflare??{},b=n.secret?{header:n.secretHeader??"X-Origin-Verify",value:n.secret}:void 0;return{plan:{zone:[...h][0],hosts:s,apiToken:l,zoneId:d.zoneId??r("CLOUDFLARE_ZONE_ID"),accountId:d.accountId??r("CLOUDFLARE_ACCOUNT_ID"),proxied:d.proxied!==!1,settings:d.settings??H,cache:d.cache,originGuard:b,purge:d.purgeOnDeploy!==!1,skipOriginProbe:d.skipOriginProbe===!0},errors:o}}export{Du as ABTestManager,hr as ACMClient,yr as ACMDnsValidator,Oe as ACME_DIRECTORIES,M as AI,xf as API_IDEMPOTENCY_TTL_MS,Nf as API_TOKEN_DEFAULT_TTL_MS,kf as API_TOKEN_MAX_TTL_MS,Vy as API_VERSION,Cf as AUTHORIZATION_CAPABILITIES,of as AUTH_ACTION_TOKEN_TTL_MS,af as AUTH_MFA_CHALLENGE_TTL_MS,sf as AUTH_OIDC_TRANSACTION_TTL_MS,nf as AUTH_SESSION_ABSOLUTE_TTL_MS,rf as AUTH_SESSION_IDLE_TTL_MS,Fc as AWSAPIError,bt as AWSClient,Le as AWSCloudFormationClient,Me as AWSCloudFrontClient,gu as AWSConfigManager,Os as AWS_PSEUDO_PARAMETERS,Id as AWS_REGIONS,nt as AcmeClient,Dt as AlertEvaluator,It as AlertStore,Gh as AnomalyConfigStore,Pe as ApiGateway,ky as ApiServiceError,Gr as ApplicationAutoScalingClient,vs as Arn,Ps as AssetHasher,Ts as Auth,cf as AuthenticationStore,Ly as AutomationApiService,Lf as AutomationIdentityStore,tS as AwsAuroraDataAdapter,aS as AwsAuroraTransport,QS as AwsDatabaseBackupSource,Sn as AwsDriver,rS as AwsElastiCacheDataAdapter,sS as AwsElastiCacheTransport,jy as AwsIamCapabilityScanner,sA as AwsInfrastructureBackupSource,eS as AwsRdsDataAdapter,oS as AwsRdsTransport,wS as AwsRegionalDriver,pA as AwsSecretsManagerConfigurationBackend,vy as AwsSpendTransport,mA as AwsSsmConfigurationBackend,JS as BackupCoordinator,uu as BackupManager,US as BackupStore,zp as BatchProcessingManager,kr as BedrockClient,Nr as BedrockRuntimeClient,xg as BitbucketSourceAdapter,Tu as BlueGreenManager,Dp as BounceComplaintHandler,np as BuildOptimizationManager,cS as BunDockerRuntime,iA as BunDockerVolumeRuntime,tA as BunFilesystemArchiveRuntime,ms as CDN,pt as CHAIN_HEADER,Qt as CLOUDFLARE_MANAGED_RULE_PREFIX,Ud as COMMON_CROSS_ACCOUNT_ROLES,hf as CONTROL_PLANE_SCHEMA_VERSION,ne as Cache,Pu as CanaryManager,Yu as CertificateManager,hg as CloudBlockVolumeDriver,In as CloudDriverFactory,Nc as CloudError,Ns as CloudFormationBuilder,Le as CloudFormationClient,Me as CloudFrontClient,yu as CloudTrailManager,Pr as CloudWatchLogsClient,Xt as CloudflareProvider,md as CommandHistory,Es as Communication,Ag as ComposeApplicationService,Sg as ComposeApplicationStore,xr as ComprehendClient,w as Compute,Oy as ComputeSpendTransport,kc as ConfigurationError,gA as ConfigurationService,cA as ConfigurationStore,Ir as ConnectClient,iS as ContainerDataAdapter,op as ContainerRegistryManager,aA as ControlPlaneBackupSource,HS as ControlPlaneCleanupDriver,vf as ControlPlaneStore,hh as CounterTracker,xc as CredentialError,Cd as CrossRegionReferenceManager,Qs as DASHBOARD_ENTRY,Xs as DASHBOARD_PORT_BASE,ec as DASHBOARD_PORT_SPAN,Ys as DASHBOARD_STATE_DIR,ai as DEFAULT_ATTACK_MODE_HOURS,Nt as DEFAULT_DDOS_THRESHOLDS,mh as DEFAULT_METER_MAPPINGS,ih as DEFAULT_PRICE_BOOK,gt as DEFAULT_RECURSION_LIMITS,Zc as DEFAULT_SERVICE_LIMITS,La as DEFAULT_STATE_DIR,Ne as DEFAULT_STATIC_ASSET_EXTENSIONS,cy as DEFAULT_TELEMETRY_POLICY,Ah as DEFAULT_THRESHOLDS,ig as DEPLOYMENT_QUEUE_KINDS,ut as DEPTH_HEADER,Uh as DETECTABLE_SIGNALS,OC as DIAGNOSTIC_PRESETS,Wp as DLQMonitoringManager,fs as DNS,Tp as DNSSECManager,QC as DataServiceLifecycle,JC as DataServiceStore,q as Database,Uu as DatabaseUserManager,Wc as DebugLogger,ls as DependencyGraph,$s as Deployment,Lc as DeploymentError,mu as DisasterRecoveryManager,fr as DnsProviderFactory,lS as DockerDataTransport,RC as DockerDiscoveryAdapter,fg as DockerNamedVolumeDriver,oA as DockerVolumeBackupSource,eg as DurableOperationQueue,tg as DurableQueueWorker,wr as DynamoDBClient,qt as EC2Client,Cr as ECRClient,Sr as ECSClient,Zr as EFSClient,Dr as ELBv2Client,jg as ENFORCEMENT_ACTIONS,wh as ENFORCEMENT_DESCRIPTIONS,Jg as ENFORCEMENT_SEVERITY,IC as EcsRuntimeAdapter,ri as EdgeRateLimiter,Hr as ElastiCacheClient,L as Email,Lp as EmailAdvanced,wp as EmailAnalyticsManager,Pt as EmailClient,Mp as EmailHandlers,kp as EmailTemplateManager,dS as EncryptedDataSecretStore,Vc as ErrorCodes,Wr as EventBridgeClient,GC as EventBridgeJobAdapter,fA as ExternalConfigurationBackend,_p as FIFOQueueManager,Jh as FOCUS_VERSION,Qc as FileCache,K as FileSystem,rA as FilesystemBackupSource,gS as FleetService,fS as FleetStore,ws as Fn,Lg as GiteaSourceAdapter,Ng as GithubSourceAdapter,kg as GitlabSourceAdapter,Sd as GlobalResourceManager,Yt as GoDaddyProvider,Su as GuardDutyManager,cl as HashCache,_m as HealthCheckManager,vt as HealthCheckRunner,An as HetznerClient,$n as HetznerDriver,Rt as IAMClient,Qr as IPV6_EXCLUDED_HOST_LABELS,tp as ImageScanningManager,He as InfrastructureGenerator,$f as InvalidOperationTransitionError,ys as JobLoader,UC as JobProviderReconciler,qC as JobService,WC as JobStore,Br as KendraClient,wm as LARAVEL_SERVERLESS_BUILD_STEPS,$r as LambdaClient,mp as LambdaConcurrencyManager,Sp as LambdaDLQManager,gp as LambdaDestinationsManager,lp as LambdaLayersManager,DC as LambdaRuntimeAdapter,yp as LambdaVPCManager,up as LambdaVersionsManager,uA as LocalEncryptedConfigurationBackend,nA as LogicalDatabaseBackupSource,Lu as LogsManager,Xp as MANAGED_NODE_VERSIONS,Hn as MANAGEMENT_DASHBOARD_SITE,oc as MANAGEMENT_DASHBOARD_SITE_PREFIX,oi as MAX_CONTROL_HOURS,Ef as MAX_CONTROL_PLANE_ERROR_BYTES,Df as MAX_CONTROL_PLANE_JSON_BYTES,Zg as METERS,qg as METER_KEYS,Yg as MICRO_CENTS,Ph as MIN_PROJECTION_CONFIDENCE,rn as MTA_STS_PORT,_S as MaintenanceService,FS as MaintenanceStore,bs as Messaging,ku as MetricsManager,_u as MigrationManager,Nl as MockCloudFormation,xl as MockDynamoDB,kl as MockS3,Ie as Monitoring,_d as MultiAccountManager,hd as MultiRegionManager,Yl as MultiStepProgress,Re as Network,Wm as NetworkSecurityManager,wt as NotificationRouter,vr as OpenSearchClient,Tf as OptimisticConcurrencyError,Bd as OrganizationManager,Om as PHP_DEFAULT_EXCLUDES,im as PHP_LAYER_EXTENSIONS,jt as PROXIABLE_RECORD_TYPES,Ds as ParameterStore,zu as PerformanceManager,$e as Permissions,_r as PersonalizeClient,hs as Phone,Fp as PhoneAdvanced,gs as PhoneHandlers,SS as PlacementService,CS as PlacementStore,Fr as PollyClient,Jt as PorkbunProvider,zy as PreDeployScanner,Ml as PreviewEnvironmentManager,ng as PreviewEnvironmentService,rg as PreviewEnvironmentStore,Wl as PreviewNotificationService,Jl as ProgressBar,wu as ProgressiveDeploymentManager,si as ProtectionControlStore,Ya as Pseudo,re as Queue,Yf as QueueCancellationError,Up as QueueManagementManager,ka as QueuePresets,Qf as QueueTimeoutError,Qn as RATE_LIMIT_KEY_SEPARATOR,Er as RDSClient,zd as RECOMMENDED_ACCOUNT_STRUCTURES,Gd as RECOMMENDED_SCPS,Eg as RELEASE_QUEUE_KINDS,dd as REPL,pd as REPLCommandBuilder,ud as REPLContext,gl as RateLimiter,xa as RealtimePresets,sy as RecordingSpendTransport,Ct as RecursionGuard,Z as Redirects,Ad as RegionPairManager,DS as RegionService,IS as RegionStore,ps as Registry,Lr as RekognitionClient,$g as ReleaseService,Tg as ReleaseStore,AS as RemoteBuildService,Wu as ReplicaManager,zm as ResourceManagementManager,Xf as RetryableOperationError,j as Route53Client,Zt as Route53DomainsClient,ir as Route53Provider,Pp as Route53ResolverManager,bp as Route53RoutingManager,NC as RuntimeOperationService,kC as RuntimeStreamRegistry,jS as S3BackupDestinationAdapter,Tt as S3Client,vc as S3Error,Hy as SECRET_PATTERNS,Hh as SENSITIVITY_THRESHOLDS,$t as SESClient,As as SMS,Rr as SNSClient,Ey as SPEND_CYCLE_SECONDS,ry as SPEND_GATE_SETTING,Py as SPEND_LEASE_SETTING,Tr as SQSClient,Ar as SSMClient,Ma as STATE_DIR_ENV_VAR,H as STATIC_SITE_ZONE_SETTINGS,Bt as STSClient,zr as SchedulerClient,De as Search,qy as SecretFindingScanner,Is as Secrets,ju as SecretsManager,br as SecretsManagerClient,qu as SecretsRotationManager,te as Security,bu as SecurityHubManager,Wy as SecurityPostureStore,Ky as SecurityScannerRunner,Xu as SecurityScanningManager,Op as SenderReputationManager,zC as ServerCronJobAdapter,nS as ServerDataAdapter,gg as ServerPathVolumeDriver,sp as ServiceMeshManager,Te as Sftp,qh as SignalSource,Vp as SmsAdvanced,Ur as SmsClient,Ss as SmsHandlers,vg as SourceConnectionStore,Og as SourceProviderError,iy as SpendCapError,ny as SpendGate,Iy as SpendLoopLease,$y as SpendNotificationRouter,Dy as SpendRunner,ey as SpendService,bh as SpendStore,Ql as Spinner,pS as SshFleetDriver,bd as StackDependencyManager,Cs as StacksIntegration,Lm as StaticSiteManager,ee as Storage,Fm as StorageAdvancedManager,qr as SupportClient,Fu as SyntheticsManager,uS as SystemFleetSshTransport,PC as SystemdDiscoveryAdapter,mt as TRACE_HEADER,Xl as TaskList,Ay as TelemetryStore,Se as TemplateBuilder,Xc as TemplateCache,Mr as TextractClient,Or as TranscribeClient,Vr as TranslateClient,zS as TransportDisasterRecoveryDriver,WS as TransportPlatformMaintenanceDriver,RS as TransportRemoteBuildDriver,Zy as TrivyImageScanner,Mf as TsCloudApiError,Ff as TsCloudClient,by as URGENT_SPEND_EVENTS,vh as USER_VISIBLE_ACTIONS,vS as UnavailableRegionalDriver,lr as UnifiedDnsValidator,Pf as UnsupportedSchemaVersionError,Mc as ValidationError,Kr as VoiceClient,pg as VolumeService,sg as VolumeStore,Rs as Workflow,Ou as XRayManager,Eu as abTestManager,Ig as activateImmutableRelease,gC as ageSeconds,Ch as aggregateDeltas,ds as analyzeStackDiff,Wh as anomalyOptionsForSignal,di as applyControlsToDdos,li as applyControlsToRateLimits,_t as applyMitigationFactor,sr as applyZoneMigration,Yp as artifactKey,Rg as assertReleaseStrategy,oy as assertSpendAllows,tC as attachProvenanceToRelease,Qy as attachSbomToRelease,Xy as attachVulnerabilitySummary,df as authEncryptionKeyFile,bf as authorizeOrganization,vC as authorizeRuntimePath,od as autocomplete,hu as awsConfigManager,ZS as backupCredentialStatus,pu as backupManager,dl as batch,Gp as batchProcessingManager,ff as beginOidcAuthorization,$u as blueGreenManager,Ep as bounceComplaintHandler,lh as budgetWindow,bi as buildAndPushServerlessImage,um as buildBunRuntimeLayerZip,ks as buildCloudFormationTemplate,jf as buildComposeLogsCommand,qf as buildComposeRuntimeCommand,Zf as buildComposeScaleCommand,Jf as buildComposeShellCommand,Ti as buildFunctionEnv,Wn as buildHostCleanupScript,ja as buildMailEnv,qn as buildManagementDashboardArtifact,_i as buildMediaCdnPlan,tn as buildMtaStsPolicy,nn as buildMtaStsServer,dm as buildNodeRuntimeLayerZip,ip as buildOptimizationManager,ce as buildOriginGuardRule,vm as buildPhpRuntimeLayerZip,_n as buildSiteDeployScript,En as buildSshArgs,se as buildStaticSiteCacheRules,Bn as buildStaticSiteDeployScript,hC as bytes,Iu as canaryManager,OS as canonicalJson,pC as capabilities,yS as capacity,bl as categorizeChanges,Qu as certificateManager,Uc as checkIAMPermissions,ym as checkInvocation,jc as checkServiceQuotas,hl as chunk,ro as cleanupDns01Challenge,wa as clearSigningKeyCache,Wg as cloneSourceBinding,$l as cloudConfigSchema,Dn as cloudDrivers,Cu as cloudTrailManager,km as collectPhpAppEntries,jr as collectServerDnsDomains,Cg as completeComposeVolumeDeletion,gf as completeOidcAuthorization,uc as composePresets,Kf as composeProjectName,nm as composeServerlessAppTemplate,Ny as compositeSpendTransport,XS as compressBackup,Zm as config,YC as connectionGuidance,ap as containerRegistryManager,If as controlPlaneDatabaseFile,yf as controlPlaneMigrations,Bs as createApiBackendPreset,By as createApiV1Handler,PS as createAsgBuildDriver,YS as createBackupQueueHandlers,$m as createCliHandler,Pn as createCloudDriver,Ce as createCloudFrontPolicy,Ic as createCredentialProvider,Js as createDashboardSite,Us as createDataPipelinePreset,XC as createDataServiceQueueHandlers,ag as createDeploymentQueueHandlers,J as createDnsProvider,$S as createEcsBuildDriver,ay as createEnforcementHandlers,Bc as createError,Vs as createExistingStaticFullStackPreset,mS as createFleetQueueHandlers,_s as createFullStackAppPreset,ur as createGoDaddyValidator,Pm as createHandlers,Rm as createHttpHandler,Hs as createJamstackPreset,ZC as createJobQueueHandlers,Zs as createLaravelPreset,Ks as createMLApiPreset,BS as createMaintenanceQueueHandlers,Mi as createMediaAccessToken,zs as createMicroservicesPreset,Ll as createMockAWS,Ls as createNodeJsServerPreset,Ms as createNodeJsServerlessPreset,Kt as createObjectStorageClient,dr as createPorkbunValidator,pc as createPreset,Ra as createPresignedUrl,Ta as createPresignedUrlAsync,Tm as createQueueHandler,Gs as createRealtimeAppPreset,ES as createRegionQueueHandlers,eC as createReleaseProvenance,wg as createReleaseQueueHandlers,bS as createRemoteBuildQueueHandlers,pr as createRoute53Validator,EC as createRuntimeAdapters,Oc as createS3Client,TS as createServerBuildDriver,js as createServerlessLaravelPreset,Fs as createServerlessNodePreset,Mg as createSourceAdapter,xs as createStaticSitePreset,qs as createTraditionalWebAppPreset,mg as createVolumeQueueHandlers,Ws as createWordPressPreset,qp as createZip,Rd as crossRegionReferenceManager,vi as dashboardActions,zn as dashboardCredentialsFile,jC as dataServiceCapabilities,Ku as databaseUserManager,Jm as decodeBase32,eA as decompressBackup,qS as decryptBackup,Um as defaultConfig,Il as defaultLocalConfig,ii as defaultRateLimitRules,Ci as deleteStaticSite,jn as deployAllComputeSites,$i as deployServerlessApp,Ai as deploySite,Zn as deploySiteRelease,gi as deployStaticSite,Si as deployStaticSiteFull,pi as deployStaticSiteWithExternalDns,mi as deployStaticSiteWithExternalDnsFull,Ga as deploymentCoexistenceError,tc as deriveManagementDashboardPort,ci as describePosture,HC as desiredJobProviderState,_h as detectAnomalies,Ha as detectDeploymentTargets,mr as detectDnsProvider,Bh as detectLatestAnomaly,zc as detectMisconfigurations,Sa as detectServiceRegion,Bf as diffCompose,Cl as diffTemplates,Bg as discoverGitRefs,mf as discoverOidcProvider,yC as discoverRuntimeInventory,Hp as dlqMonitoringManager,gr as dnsProviders,$p as dnssecManager,bC as dockerWorkloads,kS as documentDigest,fu as drManager,CC as ecsWorkloads,Rf as effectiveCapabilities,vp as emailAnalyticsManager,xp as emailTemplateManager,jm as encodeBase32,KS as encryptBackup,iC as ensureDefaultSecurityPolicies,Ln as ensureFirewall,Kn as ensureManagementDashboard,Mn as ensureServer,xn as ensureSshKey,pn as escapeSecLang,Dh as evaluateBudget,Ot as evaluateTelemetryAlertRules,_C as eventBridgeScheduleInput,Am as eventToRequest,Vh as ewma,_f as exportCompose,or as exportRoute53Zone,dc as extendPreset,Bp as fifoQueueManager,sl as findChangedFiles,fh as findMapping,Xg as findPriceEntry,jd as formatAccountStructure,Kl as formatBytes,Ry as formatCents,us as formatDiff,ql as formatDuration,sd as formatFlagSuggestions,fd as formatHistory,gd as formatHistoryStats,jl as formatKeyValue,Zl as formatList,Ul as formatProgressBar,Md as formatRegion,Fd as formatRegionList,Uy as formatScanResults,td as formatSuggestion,zl as formatTable,$h as formatTimeToExhaustion,Gl as formatTree,Rc as fromEC2Metadata,Tc as fromECSMetadata,Ac as fromEnvironment,bc as fromSharedCredentials,$c as fromWebIdentity,ft as functionFingerprint,pe as gatewayHostnames,cm as generateAppImageDockerfile,lu as generateApprovalConfig,Zp as generateBootstrap,_l as generateCleanupWorkflow,Bl as generateCostReportWorkflow,qd as generateCrossAccountRoleCF,Jy as generateCycloneDxSbom,au as generateDeploymentConfig,tu as generateDeploymentPipeline,Jd as generateDeploymentWorkflow,ui as generateExternalDnsStaticSiteTemplate,eo as generateHttpsServerCode,Yy as generateImageSbom,Xi as generateLetsEncryptUserData,be as generateLogicalId,ou as generateManualPipeline,eu as generateMatrixWorkflow,su as generateMultiEnvConfig,ru as generateMultiEnvPipeline,Yd as generateMultiEnvWorkflow,Qd as generatePRPreviewWorkflow,du as generateParallelConfig,Im as generatePhpFpmConfig,sm as generatePhpLayerDockerfile,nu as generatePreviewPipeline,Vl as generatePreviewWorkflow,Ae as generateResourceName,cu as generateScheduledConfig,iu as generateScheduledPipeline,Xd as generateScheduledWorkflow,fi as generateStaticSiteTemplate,Cn as generateUbuntuAppCloudInit,wc as getAccountId,Ed as getAllRegions,kd as getClosestRegion,cd as getCommandUsage,Hf as getComposeTemplate,Km as getConfig,nd as getContextualHelp,Pc as getCredentials,Rl as getDeploymentStrategy,Tl as getDiffStats,Sl as getDiffSummary,_c as getErrorDetails,Dl as getLocalConfig,vl as getLocalCredentials,wl as getLocalEndpoint,Ol as getLocalEnvVars,Jc as getQuotaUsageSummary,Kd as getRecommendedStructure,Dd as getRegion,Vd as getRegionStats,vd as getRegionsByCompliance,wd as getRegionsByLocation,Od as getRegionsByPricingTier,Kc as getRequiredPermissions,va as getSigningKeyCacheSize,Qa as getTimestamp,Xn as globMatches,fn as globToRegex,Td as globalResourceManager,Ih as governingLimitCents,Au as guardDutyManager,My as handleSpendRequest,un as hasAutoWwwVariant,ic as hasManagementDashboardSite,an as hasProxyUpstream,nl as hashBuffer,il as hashDirectory,tl as hashFile,ol as hashManifest,rl as hashString,Bm as healthCheckManager,ue as hostAcceptsIpv6,ae as hostCondition,Ym as hotp,uh as hourBucket,ph as hourBucketsBetween,rp as imageScanningManager,Ri as infraEnvFromOutputs,yt as inspectInvocation,fm as installRecursionFetch,yi as invalidateCache,pm as invocationContext,rd as isLikelyTypo,El as isLocalDevelopment,sc as isManagementDashboardSiteName,Oa as isNodeCryptoAvailable,xh as isOperationAllowed,Et as isQuietHours,mn as isSafePattern,Wa as isStatePath,kt as isValidCidr,Nd as isValidRegion,oh as isValidTimeZone,Na as isWebCryptoAvailable,FC as jobProviderCapability,Ht as keyMatchesFilters,fp as lambdaConcurrencyManager,Ap as lambdaDLQManager,hp as lambdaDestinationsManager,dp as lambdaLayersManager,Cp as lambdaVPCManager,pp as lambdaVersionsManager,SC as lambdaWorkloads,Em as laravelServerlessEnvDefaults,Wf as listComposeTemplates,Gg as listSourceReferences,qm as loadCloudConfig,uy as loadTelemetryPolicy,Mu as logsManager,jh as lookbackHoursForSignal,Ka as mailEnabled,Za as mailFirewallPorts,VS as maintenanceWindowOpen,$a as makeAWSRequest,Ia as makeAWSRequestAsync,Pa as makeAWSRequestOnce,ac as managementDashboardSiteName,NS as manifestDigest,ef as matchTotpCounter,Vi as mediaObjectHeaders,Lh as median,Mh as medianAbsoluteDeviation,Eh as mergeDecisions,mc as mergeInfrastructure,nh as mergePriceBooks,yh as meterTelemetry,xu as metricsManager,zt as migrateObjectStorage,Bu as migrationManager,Wd as multiAccountManager,yd as multiRegionManager,no as needsRenewal,Hm as networkSecurityManager,LC as nextScheduleRuns,Yr as normalizePublicIpv6,mC as normalizeRuntimeStatus,xC as normalizeScheduleExpression,Fg as normalizeSourceEvent,Rn as normalizeSshPublicKey,ly as normalizeTelemetryPolicy,_y as openApiDocument,Zh as optionsForSignal,Hd as organizationManager,xm as packagePhpApp,Qp as packageServerlessApp,ll as parallel,ul as parallelMap,pl as parallelWithRetry,ht as parseChain,Vf as parseCompose,Gf as parseComposeCatalog,AC as parseDockerInspect,lA as parseDotenv,Ea as parseJSONResponse,TC as parseSystemdRecords,Da as parseXMLResponse,hy as pathTemplate,Th as percentOfLimit,Gu as performanceManager,am as phpLayerBuildStage,om as phpLayerPackages,Dm as phpRuntimeLayerAssets,Uf as planComposeTemplateUpgrade,Oh as planEnforcement,Vt as planMitigation,ar as planZoneMigration,er as policyTag,Fl as previewManager,Hl as previewNotifications,MC as previewSchedule,dh as previousBudgetWindow,eh as priceUsage,th as priceUsageLines,de as probeOriginTls,yl as processInChunks,Vg as processSourceWebhook,cC as productionChangeReview,vu as progressiveDeploymentManager,Rh as projectSpend,St as propagationHeaders,Gt as providerEndpoint,xS as publicKeyFingerprint,tr as qualifyName,Kp as queueManagementManager,al as quickHash,ni as rateLimitHeaders,ti as rateLimitKey,Xr as reconcileAddressRecords,ct as reconcileCloudflareCdn,nr as reconcileDeclaredRecords,BC as reconcileJobObservation,Ug as reconcileSourceWebhook,sC as recordDashboardHostPosture,oC as recordPreDeploySecretScan,aC as recordSkippedSecretScan,At as recursionBlockedResponse,fC as redactRuntimeConfig,fy as redactTelemetryText,gy as redactTelemetryValue,Pi as redeployServerlessApp,$d as regionPairManager,bg as releaseStrategyCapabilities,Pg as releaseTrafficPlan,Jn as reloadRpxGateway,Wt as remapKey,Kg as removeSourceWebhook,Jr as removeStaleServerAddressRecords,zf as renderComposeTemplate,Ft as renderDdosInstallScript,Mt as renderNftablesRuleset,VC as renderServerCron,Lt as renderSysctlFile,gn as renderWafConfig,hn as renderWafInstallScript,Yn as renewRpxCertificates,Hu as replicaManager,xy as requestHash,Al as requiresReplacement,hm as resetRecursionRuntime,Sm as resolveApp,Ua as resolveAppDatabase,uf as resolveAuthEncryptionKey,Ja as resolveCloudProvider,dt as resolveCloudflareCdnPlan,Dc as resolveCredentials,Oi as resolveDashboardAction,Gn as resolveDashboardAuth,rc as resolveDashboardDomain,nc as resolveDashboardDomains,rr as resolveDeclaredRecords,os as resolveDeployBucketName,za as resolveDeploymentMode,Vn as resolveExecStart,bn as resolveHetznerApiToken,qa as resolveMailService,lc as resolveManagementDashboardSite,cc as resolveManagementDashboardSites,Ut as resolveObjectStorage,es as resolveProjectStackName,on as resolveProxyUpstreams,rm as resolveQueueNames,og as resolveQueuedDeploymentCommand,tm as resolveQueues,mm as resolveRecursionConfig,Ec as resolveRegion,wC as resolveRuntimeInventory,as as resolveServerlessAppStackName,ss as resolveServerlessArtifactBucketName,cs as resolveServerlessAssetBucketName,em as resolveServerlessRuntime,ns as resolveSiteBucketName,sn as resolveSiteDeployTarget,cn as resolveSiteKind,rs as resolveSiteResourceName,ts as resolveSiteStackName,Ba as resolveStatePath,is as resolveStorageBucketName,Un as resolveUiSource,xe as resolveZoneApex,Gm as resourceManagementManager,bm as responseToResult,Fh as robustZScore,Sf as roleCapabilities,Dg as rollbackImmutableRelease,Ii as rollbackServerlessApp,rh as roundCents,Ip as route53ResolverManager,Rp as route53RoutingManager,zh as routeMatches,ei as ruleMatches,jp as runBuildHooks,Nh as runEnforcement,Nm as runPhpBuildHooks,Ei as runRemoteCommand,dC as runtimeId,wi as sanitizeCloudConfig,wf as sanitizeControlPlaneValue,Xa as sanitizeName,pf as sanitizeOidcReturnPath,py as saveTelemetryPolicy,Gy as scanForSecrets,Af as scopeContains,Sh as scopeKey,On as scpUpload,id as searchCommands,Of as searchControlPlane,Ju as secretsManager,Zu as secretsRotationManager,lC as secureContainerRelease,Ru as securityHubManager,ep as securityScanningManager,nC as securityScope,lf as sendAuthenticationEmail,Np as senderReputationManager,ml as sequence,dA as serializeDotenv,Fn as serverPublicIpv4,cp as serviceMeshManager,Di as setMaintenance,Fa as setStateDir,to as setupDns01Challenge,Jp as sha256,gm as sharedRecursionGuard,lm as sharedRuntimeLoop,dn as shipsARelease,Li as signCloudFrontCookies,xi as signCloudFrontUrl,Aa as signRequest,ba as signRequestAsync,Kh as signalDefinition,Ty as spendNotificationText,Fy as spendOpenApiPaths,wn as sshExec,vn as sshExecOrThrow,Pd as stackDependencyManager,Ni as startLocalDashboardServer,wy as startSpendLoop,Va as stateDir,_a as statePath,Mm as staticSiteManager,Vm as storageAdvancedManager,Xh as streamFocusJsonl,kh as strongestActiveAction,ed as suggestCommand,ad as suggestFlags,qc as suggestIAMPolicy,Yc as suggestQuotaIncrease,Ld as suggestRegionPairs,xd as suggestRegions,zg as syncSourceRepositories,yg as synchronizeComposeVolumes,hA as synchronizeConfiguredConfiguration,KC as synchronizeConfiguredJobs,Vu as syntheticsManager,xt as sysctlHardening,$C as systemdWorkloads,Sy as telemetryBucketLabel,yy as telemetryCursor,my as telemetryEstimatedMonthlyCost,Cy as telemetryPercentile,dy as telemetryPolicyKey,el as templateCache,Hg as testSourceConnection,Qg as tieredMicroCents,le as toCloudflareZoneSettings,Qh as toFocusJsonl,Yh as toFocusRecords,Qm as totp,tf as totpUri,uC as unsupportedCapabilities,cg as unsupportedVolumeCapabilities,MS as updateCompatibility,hi as uploadStaticFiles,gh as usageDeltaKey,ch as utcInstantOfLocal,Zd as validateAccountStructure,Pl as validateAgainstSchema,ug as validateAttachment,GS as validateBackupDestination,ld as validateCommand,Hc as validateConfiguration,Gc as validateCredentials,ln as validateDeploymentConfig,dg as validateMountPath,je as validateResourceLimits,ze as validateTemplate,Ze as validateTemplateSize,en as verifyAddressRecord,rC as verifyArtifactSignature,Fi as verifyMediaAccessToken,Xm as verifyTotp,LS as verifyUpdateSignature,cr as verifyZoneParity,lg as volumeCapabilities,yn as wafEventTelemetry,kn as waitForCloudInit,Nn as waitForSsh,_g as webhookEndpoint,Cc as withCDN,yc as withCache,hc as withDatabase,Cm as withInvocation,fc as withMonitoring,Sc as withQueue,gc as withSecurity,fl as withTimeout,Tn as wrapCloudInitUserData,Nu as xrayManager,hS as zeroCapacity,ty as zeroFill,sh as zoneOffsetMs,ah as zonedParts};
595
+ `}async function F8($){let{domain:M,challengeValue:J,hostedZoneId:X,dnsProvider:Y,region:U="us-east-1"}=$;if(Y){let _=await o(Y).upsertRecord(M,{name:`_acme-challenge.${M}`,type:"TXT",content:J,ttl:60});if(!_.success)throw Error(`Failed to create DNS challenge record: ${_.message}`);return}if(X){await new a(U).changeResourceRecordSets({HostedZoneId:X,ChangeBatch:{Comment:"ACME DNS-01 challenge",Changes:[{Action:"UPSERT",ResourceRecordSet:{Name:`_acme-challenge.${M}`,Type:"TXT",TTL:60,ResourceRecords:[{Value:`"${J}"`}]}}]}});return}throw Error("Either dnsProvider or hostedZoneId must be provided")}async function K8($){let{domain:M,challengeValue:J,hostedZoneId:X,dnsProvider:Y,region:U="us-east-1"}=$;if(Y){let _=await o(Y).deleteRecord(M,{name:`_acme-challenge.${M}`,type:"TXT",content:J});if(!_.success)console.warn(`Failed to delete DNS challenge record: ${_.message}`);return}if(X){await new a(U).changeResourceRecordSets({HostedZoneId:X,ChangeBatch:{Comment:"Remove ACME DNS-01 challenge",Changes:[{Action:"DELETE",ResourceRecordSet:{Name:`_acme-challenge.${M}`,Type:"TXT",TTL:60,ResourceRecords:[{Value:`"${J}"`}]}}]}});return}throw Error("Either dnsProvider or hostedZoneId must be provided")}function U8($){try{let{execSync:M}=i("node:child_process"),J=M(`openssl x509 -checkend 2592000 -noout -in ${$}/cert.pem`,{encoding:"utf-8",stdio:["pipe","pipe","pipe"]});return!1}catch{return!0}}import{createHash as k0,createSign as W$,generateKeyPairSync as L0}from"node:crypto";var y0={production:"https://acme-v02.api.letsencrypt.org/directory",staging:"https://acme-staging-v02.api.letsencrypt.org/directory"};class _${directoryUrl;email;accountKey;accountUrl=null;directory=null;nonce=null;constructor($){this.directoryUrl=$.staging?y0.staging:y0.production,this.email=$.email,this.accountKey=$.accountKey||this.generateAccountKey()}generateAccountKey(){let{privateKey:$}=L0("ec",{namedCurve:"P-256"});return $.export({type:"pkcs8",format:"pem"})}async getDirectory(){if(this.directory)return this.directory;let $=await fetch(this.directoryUrl);if(!$.ok)throw Error(`Failed to fetch ACME directory: ${$.status}`);return this.directory=await $.json(),this.directory}async getNonce(){if(this.nonce){let X=this.nonce;return this.nonce=null,X}let $=await this.getDirectory(),J=(await fetch($.newNonce,{method:"HEAD"})).headers.get("replay-nonce");if(!J)throw Error("Failed to get nonce from ACME server");return J}getJwk(){let $=this.accountKey.split(`
596
+ `).filter((U)=>!U.startsWith("-----")).join(""),M=Buffer.from($,"base64"),J=M.length-65,X=M.subarray(J+1,J+33),Y=M.subarray(J+33,J+65);return{kty:"EC",crv:"P-256",x:this.base64UrlEncode(X),y:this.base64UrlEncode(Y)}}getJwkThumbprint(){let $=this.getJwk(),M=JSON.stringify({crv:$.crv,kty:$.kty,x:$.x,y:$.y}),J=k0("sha256").update(M).digest();return this.base64UrlEncode(J)}base64UrlEncode($){return(typeof $==="string"?Buffer.from($):$).toString("base64").replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async signPayload($,M){let J=await this.getNonce(),X=this.getJwk(),Y={alg:"ES256",nonce:J,url:$};if(this.accountUrl)Y.kid=this.accountUrl;else Y.jwk=X;let U=this.base64UrlEncode(JSON.stringify(Y)),Q=M===""?"":this.base64UrlEncode(JSON.stringify(M)),_=`${U}.${Q}`,K=W$("SHA256");K.update(_);let V=K.sign(this.accountKey),G=V.subarray(4,4+V[3]),q=4+V[3]+2,A=V.subarray(q,q+V[q-1]),P=Buffer.alloc(32),E=Buffer.alloc(32);G.copy(P,32-G.length),A.copy(E,32-A.length);let O=Buffer.concat([P,E]);return JSON.stringify({protected:U,payload:Q,signature:this.base64UrlEncode(O)})}async acmeRequest($,M){let J=await this.signPayload($,M),X=await fetch($,{method:"POST",headers:{"Content-Type":"application/jose+json"},body:J}),Y=X.headers.get("replay-nonce");if(Y)this.nonce=Y;let U,Q=X.headers.get("content-type");if(Q?.includes("application/json")||Q?.includes("application/problem+json"))U=await X.json();else U=await X.text();if(!X.ok)throw Error(`ACME request failed: ${JSON.stringify(U)}`);return{body:U,headers:X.headers}}async registerAccount(){let $=await this.getDirectory(),{body:M,headers:J}=await this.acmeRequest($.newAccount,{termsOfServiceAgreed:!0,contact:[`mailto:${this.email}`]}),X=J.get("location");if(!X)throw Error("No account URL returned");return this.accountUrl=X,X}async createOrder($){if(!this.accountUrl)await this.registerAccount();let M=await this.getDirectory(),{body:J,headers:X}=await this.acmeRequest(M.newOrder,{identifiers:$.map((U)=>({type:"dns",value:U}))}),Y=X.get("location");if(!Y)throw Error("No order URL returned");return{orderUrl:Y,authorizations:J.authorizations,finalize:J.finalize}}async getAuthorization($){let{body:M}=await this.acmeRequest($,""),J=M.identifier.value,X=this.getJwkThumbprint(),Y=M.challenges.filter((U)=>U.type==="http-01"||U.type==="dns-01").map((U)=>{let Q=`${U.token}.${X}`;if(U.type==="http-01")return{type:"http-01",token:U.token,keyAuthorization:Q,identifier:`/.well-known/acme-challenge/${U.token}`};else{let _=this.base64UrlEncode(k0("sha256").update(Q).digest());return{type:"dns-01",token:U.token,keyAuthorization:Q,identifier:`_acme-challenge.${J}`,dnsValue:_}}});return{domain:J,challenges:Y}}async respondToChallenge($){await this.acmeRequest($,{})}async waitForAuthorization($,M=30){for(let J=0;J<M;J++){let{body:X}=await this.acmeRequest($,"");if(X.status==="valid")return;if(X.status==="invalid")throw Error(`Authorization failed: ${JSON.stringify(X)}`);await new Promise((Y)=>setTimeout(Y,2000))}throw Error("Authorization timed out")}generateCsr($){let{privateKey:M}=L0("rsa",{modulusLength:2048}),J=M.export({type:"pkcs8",format:"pem"});return{csr:this.createSimpleCsr($,M),privateKey:J}}createSimpleCsr($,M){throw Error("CSR generation requires additional implementation. Consider using the shell-based certbot approach instead.")}async finalizeOrder($,M){let{csr:J,privateKey:X}=this.generateCsr(M),{body:Y}=await this.acmeRequest($,{csr:this.base64UrlEncode(Buffer.from(J,"base64"))}),U=Y.certificate;if(!U)throw Error("Certificate not immediately available - polling not implemented");let _=await(await fetch(U)).text(),K=_.split(/(?=-----BEGIN CERTIFICATE-----)/g),V=K[0],G=K.slice(1).join("");return{certificate:V,privateKey:X,chain:G,fullchain:_,expiresAt:new Date(Date.now()+7776000000)}}getAccountKey(){return this.accountKey}}var b0=["js","mjs","cjs","css","map","woff","woff2","ttf","otf","eot","png","jpg","jpeg","gif","webp","avif","svg","ico","mp4","webm","ogg","mp3","wav","pdf","wasm"],Q$=[{name:"x-stx-router",value:"true"}];function v($){return`"${$.replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}"`}function h0($){return`{${$.map(v).join(" ")}}`}function F$($){let M=`http.request.headers[${v($.name.toLowerCase())}]`;return $.value===void 0?`len(${M}) > 0`:`any(${M}[*] == ${v($.value)})`}function Q0($){if($.length===1)return`http.host eq ${v($[0])}`;return`http.host in ${h0($)}`}function F0($,M={}){if(M.enabled===!1||$.length===0)return[];let J=Q0($),X=[],U=(M.bypassPaths??[]).map((P)=>`starts_with(http.request.uri.path, ${v(P)})`),_=(M.negotiatedRequestHeaders??Q$).map(F$),K=[...U,..._],V=K.length>0?`(${K.join(" or ")})`:void 0;if(V)X.push({action:"set_cache_settings",description:"bypass cache",expression:`(${J} and ${V})`,enabled:!0,action_parameters:{cache:!1}});let G=V?`${J} and not ${V}`:J,q=M.assetExtensions??b0,A=q.length>0?`lower(http.request.uri.path.extension) in ${h0([...q])}`:void 0;if(A)X.push({action:"set_cache_settings",description:"cache fingerprinted assets",expression:`(${G} and ${A})`,enabled:!0,action_parameters:{cache:!0,edge_ttl:{mode:"override_origin",default:M.assetEdgeTtl??2592000},browser_ttl:{mode:"override_origin",default:M.assetBrowserTtl??31536000}}});return X.push({action:"set_cache_settings",description:"cache documents",expression:A?`(${G} and not ${A})`:`(${G})`,enabled:!0,action_parameters:{cache:!0,edge_ttl:{mode:"override_origin",default:M.documentEdgeTtl??3600},browser_ttl:{mode:"override_origin",default:M.documentBrowserTtl??0}}}),X}function K0($,M,J){if($.length===0||!M||!J)return[];return[{action:"rewrite",description:"origin guard header",expression:`(${Q0($)})`,enabled:!0,action_parameters:{headers:{[M]:{operation:"set",value:J}}}}]}var L=($)=>$===void 0?void 0:$?"on":"off";function U0($){let M={ssl:$.ssl,always_use_https:L($.alwaysUseHttps),automatic_https_rewrites:L($.automaticHttpsRewrites),min_tls_version:$.minTlsVersion,tls_1_3:L($.tls13),brotli:L($.brotli),http3:L($.http3),"0rtt":L($.zeroRtt),early_hints:L($.earlyHints),browser_cache_ttl:$.browserCacheTtl,always_online:L($.alwaysOnline),websockets:L($.websockets),email_obfuscation:L($.emailObfuscation)};if($.hsts)M.security_header={strict_transport_security:{enabled:$.hsts.enabled,max_age:$.hsts.maxAge??31536000,include_subdomains:$.hsts.includeSubdomains??!1,preload:$.hsts.preload??!1,nosniff:$.hsts.noSniff??!0}};for(let J of Object.keys(M))if(M[J]===void 0)delete M[J];return{...M,...$.raw??{}}}var c={ssl:"strict",alwaysUseHttps:!0,automaticHttpsRewrites:!0,minTlsVersion:"1.2",tls13:!0,brotli:!0,http3:!0,earlyHints:!0,alwaysOnline:!0,emailObfuscation:!1,browserCacheTtl:0};import{connect as K$}from"node:tls";async function G0($){let{address:M,serverName:J,port:X=443,timeoutMs:Y=5000}=$;return new Promise((U)=>{let Q=!1,_=(V)=>{if(Q)return;Q=!0;try{K.destroy()}catch{}U(V)},K=K$({host:M,port:X,servername:J,rejectUnauthorized:!1,timeout:Y});K.once("secureConnect",()=>{if(K.authorized){_({reachable:!0,trusted:!0});return}_({reachable:!0,trusted:!1,reason:K.authorizationError?String(K.authorizationError):"origin certificate is not trusted for this hostname"})}),K.once("timeout",()=>{_({reachable:!1,trusted:!1,reason:`no TLS handshake within ${Y}ms`})}),K.once("error",(V)=>{_({reachable:!1,trusted:!1,reason:V.message})})})}function U$($,M){let J=M.replace(/\.$/,"").toLowerCase();return $.some((X)=>{let Y=X.replace(/\.$/,"").toLowerCase();if(Y===J)return!0;if(!Y.startsWith("*."))return!1;let U=Y.slice(2);if(!J.endsWith(`.${U}`))return!1;return!J.slice(0,J.length-U.length-1).includes(".")})}async function G$($){let{provider:M,zone:J,hosts:X,ipv4:Y,ipv6:U,proxied:Q=!0,settings:_=c,cache:K,originGuard:V,purge:G=!0,ttl:q=300,skipOriginProbe:A=!1,skipEdgeCertificateCheck:P=!1}=$,E={records:[],settingsChanged:[],cacheRules:0,originGuard:!1,purged:!1,deferredProxy:[],warnings:[]};if(X.length===0)return E;let O=[],F=Q&&!P?await M.listEdgeCertificateHosts(J):null;for(let W of X){let Z=Q;if(Z&&F&&!U$(F,W)){Z=!1;let z=F.length===0?"the zone has no active edge certificate yet":`no active edge certificate covers it (${F.join(", ")})`;E.deferredProxy.push({host:W,reason:z}),E.warnings.push(`${W}: publishing DNS-only — ${z}. Proxying it would make Cloudflare terminate TLS with no certificate for the name, which fails the handshake outright rather than degrading. Universal SSL covers the apex and ONE level of subdomain, so a deeper name needs its own certificate; otherwise re-run the deploy once the certificate is active.`)}if(Z&&!A){let z=await G0({address:Y,serverName:W});if(!z.trusted){Z=!1;let x=z.reason||"origin is not serving a trusted certificate";E.deferredProxy.push({host:W,reason:x}),E.warnings.push(`${W}: publishing DNS-only for now — the origin does not yet serve a certificate this proxy can verify (${x}). The origin issues certificates over HTTP-01, which needs the name to reach it directly; re-run the deploy once it has one and the record will be proxied.`)}}if(Z)O.push(W);let H=[{type:"A",content:Y}];if(U&&V0(W))H.push({type:"AAAA",content:U});for(let{type:z,content:x}of H){let N=await M.upsertRecord(J,{name:W,type:z,content:x,ttl:q,proxied:Z});if(N.success)E.records.push({host:W,type:z,content:x,proxied:Z});else E.warnings.push(`${W} ${z} → ${x} failed: ${N.message||"unknown provider error"}`)}}if(O.length===0){if(Q)E.warnings.push("No host is proxied yet, so zone settings, cache rules and purge were skipped — they only take effect through the proxy.");return E}try{let W=U0(_),Z=await M.applyZoneSettings(J,W);E.settingsChanged=Z.changed;for(let H of Z.failed)E.warnings.push(`zone setting '${H.id}' could not be applied: ${H.error}`)}catch(W){E.warnings.push(`zone settings could not be read: ${W instanceof Error?W.message:String(W)}`)}let R=F0(O,K);if(R.length>0){let W=await M.putManagedPhaseRules(J,"http_request_cache_settings",R);if(W.success)E.cacheRules=R.length;else E.warnings.push(`cache rules could not be written: ${W.message}`)}if(V){let W=K0(O,V.header,V.value);if(W.length>0){let Z=await M.putManagedPhaseRules(J,"http_request_late_transform",W);if(Z.success)E.originGuard=!0;else E.warnings.push(`origin guard header could not be written: ${Z.message}. `+"The gateway will reject requests that lack it — disable the guard or grant the token Transform Rules: Edit.")}}if(G){if(E.purged=await M.purgeCache(J,{hosts:O}),!E.purged)E.warnings.push("edge cache purge failed — new content may take until TTL expiry to appear.")}return E}var V$=($)=>process.env[$];function C0($,M){let J=$.replace(/\.$/,"").toLowerCase();if(M){let X=M.replace(/\.$/,"").toLowerCase();if(J===X||J.endsWith(`.${X}`))return X}return J.split(".").slice(-2).join(".")}function O$($,M={}){let J=M.env??V$,X=$.infrastructure?.compute?.proxy?.cdn,Y=[];if(!X||X.provider!=="cloudflare")return{plan:null,errors:Y};if(X.originDomain)Y.push(`compute.proxy.cdn.originDomain (${X.originDomain}) is ignored for Cloudflare: the proxy forwards to the address in the record it fronts, `+"so no separate origin hostname is needed — and publishing one gives clients a documented way around the edge.");let U=J("CLOUDFLARE_API_TOKEN");if(!U)return Y.push("CLOUDFLARE_API_TOKEN is not set — the Cloudflare CDN cannot be reconciled."),{plan:null,errors:Y};let Q=$.sites??{},_=X.frontedHosts?.length?[...new Set(X.frontedHosts.map((A)=>A.toLowerCase()))]:O0(Q,{autoWww:$.infrastructure?.compute?.proxy?.autoWww!==!1});if(_.length===0)return Y.push("No hostnames to front — set compute.proxy.cdn.frontedHosts, or give a site a domain."),{plan:null,errors:Y};let K=$.infrastructure?.dns?.domain,V=new Set(_.map((A)=>C0(A,K)));if(V.size>1)return Y.push(`Fronted hosts span more than one zone (${[...V].join(", ")}). A Cloudflare zone is configured as a unit, so run one CDN config per zone.`),{plan:null,errors:Y};let G=X.cloudflare??{},q=X.secret?{header:X.secretHeader??"X-Origin-Verify",value:X.secret}:void 0;return{plan:{zone:[...V][0],hosts:_,apiToken:U,zoneId:G.zoneId??J("CLOUDFLARE_ZONE_ID"),accountId:G.accountId??J("CLOUDFLARE_ACCOUNT_ID"),proxied:G.proxied!==!1,settings:G.settings??c,cache:G.cache,originGuard:q,purge:G.purgeOnDeploy!==!1,skipOriginProbe:G.skipOriginProbe===!0},errors:Y}}var E$=26214400;var H$=new Set(["/_headers","/_redirects","/_routes.json","/_worker.js"]);class I0{name="cloudflare-pages";apiToken;accountId;constructor($){if(!$.apiToken)throw Error("Cloudflare Pages needs an API token");if(!$.accountId)throw Error("Cloudflare Pages needs an account id");this.apiToken=$.apiToken,this.accountId=$.accountId}async request($,M,J){return s($,`/accounts/${this.accountId}${M}`,`Bearer ${this.apiToken}`,J)}async getProject($){try{return await this.request("GET",`/pages/projects/${$}`)}catch(M){if(M instanceof Error&&/\b8000007\b|not found/i.test(M.message))return null;throw M}}async ensureProject($,M="main"){let J=await this.getProject($);if(J)return J;return this.request("POST","/pages/projects",{name:$,production_branch:M})}async uploadToken($){return(await this.request("GET",`/pages/projects/${$}/upload-token`)).jwt}async missingHashes($,M){let J=await s("POST","/pages/assets/check-missing",`Bearer ${$}`,{hashes:M});return new Set(J)}async upsertHashes($,M){await s("POST","/pages/assets/upsert-hashes",`Bearer ${$}`,{hashes:M})}async uploadBatch($,M){let J=M.map((X)=>({key:X.hash,value:X.base64,metadata:{contentType:A$(X.extension)},base64:!0}));await s("POST","/pages/assets/upload",`Bearer ${$}`,J)}async createDeployment($,M,J){let X={};for(let U of M)X[U.path]=U.hash;let Y=new FormData;if(Y.append("manifest",JSON.stringify(X)),J)Y.append("branch",J);return this.request("POST",`/pages/projects/${$}/deployments`,Y)}async deployDirectory($){let M=await p0($.directory);if(M.length===0)throw Error(`No files to deploy in ${$.directory}`);let J=await this.uploadToken($.project),X=await this.missingHashes(J,M.map((K)=>K.hash)),Y=M.filter((K)=>X.has(K.hash)),U=[];for(let K=0;K<Y.length;K+=100)U.push(Y.slice(K,K+100));let Q=0;for(let K=0;K<U.length;K+=4){let V=U.slice(K,K+4);await Promise.all(V.map((G)=>this.uploadBatch(J,G))),Q+=V.reduce((G,q)=>G+q.length,0),$.onProgress?.(Q,Y.length)}return await this.upsertHashes(J,M.map((K)=>K.hash)),{deployment:await this.createDeployment($.project,M,$.branch),total:M.length,uploaded:Y.length,uploadedBytes:Y.reduce((K,V)=>K+V.size,0)}}async listCustomDomains($){return(await this.request("GET",`/pages/projects/${$}/domains`)).map((J)=>J.name)}async attachCustomDomain($,M){if((await this.listCustomDomains($)).includes(M))return!1;return await this.request("POST",`/pages/projects/${$}/domains`,{name:M}),!0}}function R$($,M){return{type:"CNAME",name:$,value:M.endsWith(".pages.dev")?M:`${M}.pages.dev`,ttl:1,proxied:!0}}async function f0($,M){let{blake3:J}=await import("./chunk-4m6gwhwr.js").then((m)=>Z$(m.default,1));return(await J($+M)).slice(0,32)}async function p0($){let{readdir:M}=await import("node:fs/promises"),{join:J,relative:X,sep:Y}=await import("node:path"),U=[];async function Q(_){let K=await M(_,{withFileTypes:!0});for(let V of K){let G=J(_,V.name);if(V.isDirectory()){await Q(G);continue}if(!V.isFile())continue;let q=`/${X($,G).split(Y).join("/")}`;if(H$.has(q))continue;let A=await Bun.file(G).bytes();if(A.byteLength>26214400)throw Error(`${q} is ${A.byteLength} bytes, over the Cloudflare Pages limit of 26214400`);let P=Buffer.from(A).toString("base64"),E=V.name.lastIndexOf("."),O=E>0?V.name.slice(E+1):"";U.push({path:q,hash:await f0(P,O),base64:P,extension:O,size:A.byteLength})}}return await Q($),U.sort((_,K)=>_.path.localeCompare(K.path)),U}function A$($){return{html:"text/html; charset=utf-8",css:"text/css; charset=utf-8",js:"application/javascript; charset=utf-8",mjs:"application/javascript; charset=utf-8",json:"application/json; charset=utf-8",map:"application/json; charset=utf-8",xml:"application/xml; charset=utf-8",txt:"text/plain; charset=utf-8",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",pdf:"application/pdf",webmanifest:"application/manifest+json"}[$.toLowerCase()]||"application/octet-stream"}async function s($,M,J,X){let Y={Authorization:J},U;if(X instanceof FormData)U=X;else if(X!==void 0)Y["Content-Type"]="application/json",U=JSON.stringify(X);let Q=await fetch(`https://api.cloudflare.com/client/v4${M}`,{method:$,headers:Y,body:U}),_=await Q.text(),K;try{K=JSON.parse(_)}catch{throw Error(`Cloudflare Pages API returned ${Q.status} with a non-JSON body: ${_.slice(0,200)}`)}if(!K.success){let V=(K.errors??[]).map((G)=>`${G.code}: ${G.message}`).join(", ");throw Error(`Cloudflare Pages API error (${Q.status}): ${V||_.slice(0,200)}`)}return K.result}export{E5 as zonedParts,H5 as zoneOffsetMs,UF as zeroFill,BU as zeroCapacity,uY as xrayManager,k3 as wrapCloudInitUserData,SJ as withTimeout,B9 as withSecurity,D9 as withQueue,S9 as withMonitoring,jW as withInvocation,T9 as withDatabase,w9 as withCache,j9 as withCDN,iQ as webhookEndpoint,m3 as waitForSsh,v3 as waitForCloudInit,S3 as wafEventTelemetry,RQ as volumeCapabilities,H6 as verifyZoneParity,lU as verifyUpdateSignature,K_ as verifyTotp,lM as verifyMediaAccessToken,GK as verifyArtifactSignature,F3 as verifyAddressRecord,n0 as validateTemplateSize,g0 as validateTemplate,e0 as validateResourceLimits,AQ as validateMountPath,H3 as validateDeploymentConfig,$J as validateCredentials,n9 as validateConfiguration,zX as validateCommand,eU as validateBackupDestination,zQ as validateAttachment,CJ as validateAgainstSchema,YY as validateAccountStructure,R5 as utcInstantOfLocal,S5 as usageDeltaKey,PM as uploadStaticFiles,rU as updateCompatibility,HQ as unsupportedVolumeCapabilities,xK as unsupportedCapabilities,G_ as totpUri,F_ as totp,_F as toFocusRecords,QF as toFocusJsonl,U0 as toCloudflareZoneSettings,Q5 as tieredMicroCents,sQ as testSourceConnection,UJ as templateCache,zF as telemetryPolicyKey,wF as telemetryPercentile,NF as telemetryEstimatedMonthlyCost,TF as telemetryCursor,jF as telemetryBucketLabel,bK as systemdWorkloads,u$ as sysctlHardening,iY as syntheticsManager,$U as synchronizeConfiguredJobs,B7 as synchronizeConfiguredConfiguration,TQ as synchronizeComposeVolumes,nQ as syncSourceRepositories,lX as suggestRegions,rX as suggestRegionPairs,QJ as suggestQuotaIncrease,XJ as suggestIAMPolicy,HX as suggestFlags,UX as suggestCommand,u5 as strongestActiveAction,FF as streamFocusJsonl,iW as storageAdvancedManager,tW as staticSiteManager,a4 as statePath,i4 as stateDir,pF as startSpendLoop,mM as startLocalDashboardServer,CX as stackDependencyManager,f3 as sshExecOrThrow,I3 as sshExec,tF as spendOpenApiPaths,yF as spendNotificationText,MF as signalDefinition,L4 as signRequestAsync,k4 as signRequest,cM as signCloudFrontUrl,uM as signCloudFrontCookies,R3 as shipsARelease,zW as sharedRuntimeLoop,BW as sharedRecursionGuard,_W as sha256,F8 as setupDns01Challenge,g4 as setStateDir,hM as setMaintenance,A2 as serviceMeshManager,l3 as serverPublicIpv4,z7 as serializeDotenv,PJ as sequence,u2 as senderReputationManager,A_ as sendAuthenticationEmail,VK as securityScope,U2 as securityScanningManager,yY as securityHubManager,AK as secureContainerRelease,Y2 as secretsRotationManager,_2 as secretsManager,v_ as searchControlPlane,ZX as searchCommands,p3 as scpUpload,j5 as scopeKey,D_ as scopeContains,eF as scanForSecrets,qF as saveTelemetryPolicy,q_ as sanitizeOidcReturnPath,K1 as sanitizeName,p_ as sanitizeControlPlaneValue,IM as sanitizeCloudConfig,zK as runtimeId,CM as runRemoteCommand,uW as runPhpBuildHooks,c5 as runEnforcement,WW as runBuildHooks,QM as ruleMatches,n5 as routeMatches,y2 as route53RoutingManager,I2 as route53ResolverManager,G5 as roundCents,bM as rollbackServerlessApp,IQ as rollbackImmutableRelease,j_ as roleCapabilities,t5 as robustZScore,LW as responseToResult,$_ as resourceManagementManager,C0 as resolveZoneApex,n3 as resolveUiSource,Z1 as resolveStorageBucketName,o4 as resolveStatePath,G1 as resolveSiteStackName,V1 as resolveSiteResourceName,E3 as resolveSiteKind,Z3 as resolveSiteDeployTarget,O1 as resolveSiteBucketName,UW as resolveServerlessRuntime,A1 as resolveServerlessAssetBucketName,R1 as resolveServerlessArtifactBucketName,H1 as resolveServerlessAppStackName,pK as resolveRuntimeInventory,p9 as resolveRegion,PW as resolveRecursionConfig,GW as resolveQueues,ZQ as resolveQueuedDeploymentCommand,VW as resolveQueueNames,V3 as resolveProxyUpstreams,U1 as resolveProjectStackName,e$ as resolveObjectStorage,A9 as resolveManagementDashboardSites,z9 as resolveManagementDashboardSite,X1 as resolveMailService,j3 as resolveHetznerApiToken,r3 as resolveExecStart,e4 as resolveDeploymentMode,E1 as resolveDeployBucketName,U6 as resolveDeclaredRecords,O9 as resolveDashboardDomains,V9 as resolveDashboardDomain,s3 as resolveDashboardAuth,pM as resolveDashboardAction,f9 as resolveCredentials,O$ as resolveCloudflareCdnPlan,_1 as resolveCloudProvider,x_ as resolveAuthEncryptionKey,M1 as resolveAppDatabase,DW as resolveApp,TW as resetRecursionRuntime,kJ as requiresReplacement,dF as requestHash,nY as replicaManager,YM as renewRpxCertificates,P3 as renderWafInstallScript,N3 as renderWafConfig,d$ as renderSysctlFile,gK as renderServerCron,l$ as renderNftablesRuleset,r$ as renderDdosInstallScript,n_ as renderComposeTemplate,Y3 as removeStaleServerAddressRecords,M5 as removeSourceWebhook,a$ as remapKey,XM as reloadRpxGateway,hQ as releaseTrafficPlan,kQ as releaseStrategyCapabilities,hX as regionPairManager,yM as redeployServerlessApp,SF as redactTelemetryValue,PF as redactTelemetryText,PK as redactRuntimeConfig,j$ as recursionBlockedResponse,EK as recordSkippedSecretScan,ZK as recordPreDeploySecretScan,HK as recordDashboardHostPosture,$5 as reconcileSourceWebhook,aK as reconcileJobObservation,G6 as reconcileDeclaredRecords,G$ as reconcileCloudflareCdn,Q3 as reconcileAddressRecords,FM as rateLimitKey,UM as rateLimitHeaders,HJ as quickHash,JW as queueManagementManager,K6 as qualifyName,dU as publicKeyFingerprint,n$ as providerEndpoint,w$ as propagationHeaders,L5 as projectSpend,vY as progressiveDeploymentManager,RK as productionChangeReview,gQ as processSourceWebhook,wJ as processInChunks,G0 as probeOriginTls,U5 as priceUsageLines,K5 as priceUsage,z5 as previousBudgetWindow,rK as previewSchedule,nJ as previewNotifications,gJ as previewManager,F6 as policyTag,Z6 as planZoneMigration,t$ as planMitigation,v5 as planEnforcement,$Q as planComposeTemplateUpgrade,fW as phpRuntimeLayerAssets,EW as phpLayerPackages,HW as phpLayerBuildStage,$2 as performanceManager,y5 as percentOfLimit,BF as pathTemplate,f4 as parseXMLResponse,yK as parseSystemdRecords,p4 as parseJSONResponse,A7 as parseDotenv,DK as parseDockerInspect,e_ as parseComposeCatalog,g_ as parseCompose,S$ as parseChain,NJ as parallelWithRetry,qJ as parallelMap,zJ as parallel,R$ as pagesDnsRecord,f0 as pagesAssetHash,FW as packageServerlessApp,lW as packagePhpApp,nX as organizationManager,XF as optionsForSignal,iF as openApiDocument,AF as normalizeTelemetryPolicy,D3 as normalizeSshPublicKey,tQ as normalizeSourceEvent,dK as normalizeScheduleExpression,NK as normalizeRuntimeStatus,W3 as normalizePublicIpv6,lK as nextScheduleRuns,nW as networkSecurityManager,U8 as needsRenewal,wX as multiRegionManager,sX as multiAccountManager,oY as migrationManager,s$ as migrateObjectStorage,lY as metricsManager,T5 as meterTelemetry,V5 as mergePriceBooks,P9 as mergeInfrastructure,f5 as mergeDecisions,r5 as medianAbsoluteDeviation,l5 as median,rM as mediaObjectHeaders,U_ as matchTotpCounter,cU as manifestDigest,H9 as managementDashboardSiteName,C4 as makeAWSRequestOnce,I4 as makeAWSRequestAsync,h4 as makeAWSRequest,gU as maintenanceWindowOpen,Y1 as mailFirewallPorts,J1 as mailEnabled,YF as lookbackHoursForSignal,tY as logsManager,xF as loadTelemetryPolicy,X_ as loadCloudConfig,eQ as listSourceReferences,o_ as listComposeTemplates,pW as laravelServerlessEnvDefaults,jK as lambdaWorkloads,N2 as lambdaVersionsManager,j2 as lambdaVPCManager,x2 as lambdaLayersManager,T2 as lambdaDestinationsManager,k2 as lambdaDLQManager,S2 as lambdaConcurrencyManager,o$ as keyMatchesFilters,tK as jobProviderCapability,u4 as isWebCryptoAvailable,Z5 as isValidTimeZone,uX as isValidRegion,c$ as isValidCidr,s4 as isStatePath,x3 as isSafePattern,I$ as isQuietHours,d5 as isOperationAllowed,c4 as isNodeCryptoAvailable,R9 as isManagementDashboardSiteName,pJ as isLocalDevelopment,VX as isLikelyTypo,NW as invocationContext,SM as invalidateCache,SW as installRecursionFetch,B$ as inspectInvocation,DM as infraEnvFromOutputs,V2 as imageScanningManager,q5 as hourBucketsBetween,x5 as hourBucket,Q_ as hotp,Q0 as hostCondition,V0 as hostAcceptsIpv6,oW as healthCheckManager,VJ as hashString,EJ as hashManifest,GJ as hashFile,ZJ as hashDirectory,OJ as hashBuffer,O3 as hasProxyUpstream,Z9 as hasManagementDashboardSite,A3 as hasAutoWwwVariant,rF as handleSpendRequest,kY as guardDutyManager,C5 as governingLimitCents,bX as globalResourceManager,q3 as globToRegex,_M as globMatches,F1 as getTimestamp,v4 as getSigningKeyCacheSize,JJ as getRequiredPermissions,cX as getRegionsByPricingTier,mX as getRegionsByLocation,vX as getRegionsByCompliance,iX as getRegionStats,fX as getRegion,JY as getRecommendedStructure,_J as getQuotaUsageSummary,cJ as getLocalEnvVars,mJ as getLocalEndpoint,vJ as getLocalCredentials,fJ as getLocalConfig,a9 as getErrorDetails,DJ as getDiffSummary,bJ as getDiffStats,yJ as getDeploymentStrategy,C9 as getCredentials,OX as getContextualHelp,J_ as getConfig,s_ as getComposeTemplate,AX as getCommandUsage,dX as getClosestRegion,pX as getAllRegions,m9 as getAccountId,B3 as generateUbuntuAppCloudInit,qM as generateStaticSiteTemplate,KY as generateScheduledWorkflow,ZY as generateScheduledPipeline,AY as generateScheduledConfig,q0 as generateResourceName,iJ as generatePreviewWorkflow,OY as generatePreviewPipeline,RW as generatePhpLayerDockerfile,IW as generatePhpFpmConfig,xY as generateParallelConfig,FY as generatePRPreviewWorkflow,QY as generateMultiEnvWorkflow,VY as generateMultiEnvPipeline,RY as generateMultiEnvConfig,UY as generateMatrixWorkflow,EY as generateManualPipeline,N0 as generateLogicalId,_8 as generateLetsEncryptUserData,_K as generateImageSbom,Q8 as generateHttpsServerCode,AM as generateExternalDnsStaticSiteTemplate,_Y as generateDeploymentWorkflow,GY as generateDeploymentPipeline,HY as generateDeploymentConfig,WK as generateCycloneDxSbom,XY as generateCrossAccountRoleCF,oJ as generateCostReportWorkflow,aJ as generateCleanupWorkflow,YW as generateBootstrap,zY as generateApprovalConfig,AW as generateAppImageDockerfile,O0 as gatewayHostnames,N$ as functionFingerprint,h9 as fromWebIdentity,L9 as fromSharedCredentials,k9 as fromEnvironment,b9 as fromECSMetadata,y9 as fromEC2Metadata,$X as formatTree,b5 as formatTimeToExhaustion,eJ as formatTable,GX as formatSuggestion,$K as formatScanResults,gX as formatRegionList,tX as formatRegion,MX as formatProgressBar,YX as formatList,WX as formatKeyValue,BX as formatHistoryStats,SX as formatHistory,RX as formatFlagSuggestions,XX as formatDuration,q1 as formatDiff,LF as formatCents,JX as formatBytes,WY as formatAccountStructure,F5 as findPriceEntry,P5 as findMapping,RJ as findChangedFiles,o2 as fifoQueueManager,x9 as extendPreset,O6 as exportRoute53Zone,i_ as exportCompose,g5 as ewma,kW as eventToRequest,iK as eventBridgeScheduleInput,m$ as evaluateTelemetryAlertRules,I5 as evaluateBudget,z3 as escapeSecLang,c3 as ensureSshKey,d3 as ensureServer,e3 as ensureManagementDashboard,u3 as ensureFirewall,OK as ensureDefaultSecurityPolicies,M7 as encryptBackup,W_ as encodeBase32,l2 as emailTemplateManager,v2 as emailAnalyticsManager,L_ as effectiveCapabilities,wK as ecsWorkloads,SY as drManager,uU as documentDigest,kK as dockerWorkloads,h2 as dnssecManager,P6 as dnsProviders,n2 as dlqMonitoringManager,TK as discoverRuntimeInventory,N_ as discoverOidcProvider,aQ as discoverGitRefs,jJ as diffTemplates,a_ as diffCompose,D4 as detectServiceRegion,e9 as detectMisconfigurations,a5 as detectLatestAnomaly,q6 as detectDnsProvider,n4 as detectDeploymentTargets,i5 as detectAnomalies,oK as desiredJobProviderState,EM as describePosture,G9 as deriveManagementDashboardPort,$1 as deploymentCoexistenceError,xM as deployStaticSiteWithExternalDnsFull,zM as deployStaticSiteWithExternalDns,TM as deployStaticSiteFull,NM as deployStaticSite,MM as deploySiteRelease,wM as deploySite,LM as deployServerlessApp,JM as deployAllComputeSites,BM as deleteStaticSite,GM as defaultRateLimitRules,IJ as defaultLocalConfig,M_ as defaultConfig,J7 as decryptBackup,K7 as decompressBackup,__ as decodeBase32,J2 as databaseUserManager,YU as dataServiceCapabilities,o3 as dashboardCredentialsFile,fM as dashboardActions,yX as crossRegionReferenceManager,XW as createZip,s1 as createWordPressPreset,qQ as createVolumeQueueHandlers,X9 as createTraditionalWebAppPreset,l1 as createStaticSitePreset,rQ as createSourceAdapter,g1 as createServerlessNodePreset,W9 as createServerlessLaravelPreset,yU as createServerBuildDriver,c9 as createS3Client,fK as createRuntimeAdapters,x6 as createRoute53Validator,kU as createRemoteBuildQueueHandlers,pQ as createReleaseQueueHandlers,KK as createReleaseProvenance,fU as createRegionQueueHandlers,$9 as createRealtimeAppPreset,bW as createQueueHandler,b4 as createPresignedUrlAsync,y4 as createPresignedUrl,N9 as createPreset,A6 as createPorkbunValidator,$6 as createObjectStorageClient,t1 as createNodeJsServerlessPreset,r1 as createNodeJsServerPreset,rJ as createMockAWS,e1 as createMicroservicesPreset,dM as createMediaAccessToken,aU as createMaintenanceQueueHandlers,J9 as createMLApiPreset,Y9 as createLaravelPreset,JU as createJobQueueHandlers,n1 as createJamstackPreset,yW as createHttpHandler,CW as createHandlers,z6 as createGoDaddyValidator,a1 as createFullStackAppPreset,NU as createFleetQueueHandlers,i1 as createExistingStaticFullStackPreset,o9 as createError,EF as createEnforcementHandlers,bU as createEcsBuildDriver,o as createDnsProvider,EQ as createDeploymentQueueHandlers,FU as createDataServiceQueueHandlers,M9 as createDataPipelinePreset,_9 as createDashboardSite,I9 as createCredentialProvider,z0 as createCloudFrontPolicy,y3 as createCloudDriver,hW as createCliHandler,_7 as createBackupQueueHandlers,hU as createAsgBuildDriver,aF as createApiV1Handler,o1 as createApiBackendPreset,T_ as controlPlaneMigrations,C_ as controlPlaneDatabaseFile,H2 as containerRegistryManager,_U as connectionGuidance,Y_ as config,F7 as compressBackup,cF as compositeSpendTransport,OW as composeServerlessAppTemplate,MQ as composeProjectName,q9 as composePresets,S_ as completeOidcAuthorization,wQ as completeComposeVolumeDeletion,X3 as collectServerDnsDomains,dW as collectPhpAppEntries,p0 as collectAssets,jY as cloudTrailManager,h3 as cloudDrivers,hJ as cloudConfigSchema,oQ as cloneSourceBinding,m4 as clearSigningKeyCache,K8 as cleanupDns01Challenge,TJ as chunk,WJ as checkServiceQuotas,wW as checkInvocation,MJ as checkIAMPermissions,F2 as certificateManager,LJ as categorizeChanges,TU as capacity,qK as capabilities,vU as canonicalJson,IY as canaryManager,BK as bytes,g3 as buildStaticSiteDeployScript,F0 as buildStaticSiteCacheRules,C3 as buildSshArgs,t3 as buildSiteDeployScript,vW as buildPhpRuntimeLayerZip,K0 as buildOriginGuardRule,Z2 as buildOptimizationManager,xW as buildNodeRuntimeLayerZip,G3 as buildMtaStsServer,K3 as buildMtaStsPolicy,tM as buildMediaCdnPlan,$M as buildManagementDashboardArtifact,W1 as buildMailEnv,i3 as buildHostCleanupScript,kM as buildFunctionEnv,WQ as buildComposeShellCommand,XQ as buildComposeScaleCommand,JQ as buildComposeRuntimeCommand,YQ as buildComposeLogsCommand,d1 as buildCloudFormationTemplate,qW as buildBunRuntimeLayerZip,jM as buildAndPushServerlessImage,A5 as budgetWindow,p2 as bounceComplaintHandler,hY as blueGreenManager,P_ as beginOidcAuthorization,$W as batchProcessingManager,xJ as batch,NY as backupManager,X7 as backupCredentialStatus,TY as awsConfigManager,EX as autocomplete,mK as authorizeRuntimePath,k_ as authorizeOrganization,z_ as authEncryptionKeyFile,FK as attachVulnerabilitySummary,QK as attachSbomToRelease,UK as attachProvenanceToRelease,ZF as assertSpendAllows,LQ as assertReleaseStrategy,QW as artifactKey,E6 as applyZoneMigration,g$ as applyMitigationFactor,HM as applyControlsToRateLimits,RM as applyControlsToDdos,o5 as anomalyOptionsForSignal,x1 as analyzeStackDiff,w5 as aggregateDeltas,SK as ageSeconds,CQ as activateImmutableRelease,pY as abTestManager,cY as XRayManager,y1 as Workflow,BQ as VolumeStore,xQ as VolumeService,$3 as VoiceClient,t9 as ValidationError,h_ as UnsupportedSchemaVersionError,R6 as UnifiedDnsValidator,mU as UnavailableRegionalDriver,m5 as USER_VISIBLE_ACTIONS,kF as URGENT_SPEND_EVENTS,t_ as TsCloudClient,r_ as TsCloudApiError,XK as TrivyImageScanner,LU as TransportRemoteBuildDriver,oU as TransportPlatformMaintenanceDriver,nU as TransportDisasterRecoveryDriver,t6 as TranslateClient,m6 as TranscribeClient,l6 as TextractClient,KJ as TemplateCache,x0 as TemplateBuilder,DF as TelemetryStore,KX as TaskList,q$ as TRACE_HEADER,hK as SystemdDiscoveryAdapter,xU as SystemFleetSshTransport,gY as SyntheticsManager,M3 as SupportClient,gW as StorageAdvancedManager,M0 as Storage,rW as StaticSiteManager,j1 as StacksIntegration,LX as StackDependencyManager,qU as SshFleetDriver,FX as Spinner,k5 as SpendStore,KF as SpendService,IF as SpendRunner,bF as SpendNotificationRouter,CF as SpendLoopLease,VF as SpendGate,OF as SpendCapError,vQ as SourceProviderError,mQ as SourceConnectionStore,D1 as SmsHandlers,e6 as SmsClient,i2 as SmsAdvanced,JF as SignalSource,S0 as Sftp,R2 as ServiceMeshManager,PQ as ServerPathVolumeDriver,VU as ServerDataAdapter,sK as ServerCronJobAdapter,c2 as SenderReputationManager,K2 as SecurityScanningManager,MK as SecurityScannerRunner,oF as SecurityPostureStore,LY as SecurityHubManager,J0 as Security,X2 as SecretsRotationManager,D6 as SecretsManagerClient,W2 as SecretsManager,I1 as Secrets,JK as SecretFindingScanner,j0 as Search,s6 as SchedulerClient,i$ as STSClient,c as STATIC_SITE_ZONE_SETTINGS,t4 as STATE_DIR_ENV_VAR,j6 as SSMClient,L6 as SQSClient,hF as SPEND_LEASE_SETTING,GF as SPEND_GATE_SETTING,fF as SPEND_CYCLE_SECONDS,k6 as SNSClient,k1 as SMS,y$ as SESClient,s5 as SENSITIVITY_THRESHOLDS,sF as SECRET_PATTERNS,v9 as S3Error,L$ as S3Client,Y7 as S3BackupDestinationAdapter,uK as RuntimeStreamRegistry,cK as RuntimeOperationService,L2 as Route53RoutingManager,C2 as Route53ResolverManager,V6 as Route53Provider,J6 as Route53DomainsClient,a as Route53Client,FQ as RetryableOperationError,eW as ResourceManagementManager,sY as ReplicaManager,DU as RemoteBuildService,yQ as ReleaseStore,bQ as ReleaseService,d6 as RekognitionClient,N1 as Registry,CU as RegionStore,IU as RegionService,kX as RegionPairManager,g as Redirects,T$ as RecursionGuard,HF as RecordingSpendTransport,l4 as RealtimePresets,BJ as RateLimiter,qX as REPLContext,NX as REPLCommandBuilder,xX as REPL,fQ as RELEASE_QUEUE_KINDS,$Y as RECOMMENDED_SCPS,eX as RECOMMENDED_ACCOUNT_STRUCTURES,I6 as RDSClient,WM as RATE_LIMIT_KEY_SEPARATOR,QQ as QueueTimeoutError,d4 as QueuePresets,MW as QueueManagementManager,_Q as QueueCancellationError,X0 as Queue,Q1 as Pseudo,ZM as ProtectionControlStore,mY as ProgressiveDeploymentManager,_X as ProgressBar,sJ as PreviewNotificationService,GQ as PreviewEnvironmentStore,VQ as PreviewEnvironmentService,tJ as PreviewEnvironmentManager,nF as PreDeployScanner,Y6 as PorkbunProvider,r6 as PollyClient,wU as PlacementStore,jU as PlacementService,B1 as PhoneHandlers,g2 as PhoneAdvanced,T1 as Phone,g6 as PersonalizeClient,B0 as Permissions,eY as PerformanceManager,f1 as ParameterStore,X6 as PROXIABLE_RECORD_TYPES,ZW as PHP_LAYER_EXTENSIONS,cW as PHP_DEFAULT_EXCLUDES,E$ as PAGES_MAX_FILE_BYTES,oX as OrganizationManager,y_ as OptimisticConcurrencyError,p6 as OpenSearchClient,f$ as NotificationRouter,sW as NetworkSecurityManager,P0 as Network,QX as MultiStepProgress,TX as MultiRegionManager,aX as MultiAccountManager,w0 as Monitoring,dJ as MockS3,lJ as MockDynamoDB,uJ as MockCloudFormation,aY as MigrationManager,dY as MetricsManager,L1 as Messaging,tU as MaintenanceStore,iU as MaintenanceService,U3 as MTA_STS_PORT,h5 as MIN_PROJECTION_CONFIDENCE,_5 as MICRO_CENTS,J5 as METER_KEYS,X5 as METERS,I_ as MAX_CONTROL_PLANE_JSON_BYTES,f_ as MAX_CONTROL_PLANE_ERROR_BYTES,VM as MAX_CONTROL_HOURS,E9 as MANAGEMENT_DASHBOARD_SITE_PREFIX,a3 as MANAGEMENT_DASHBOARD_SITE,KW as MANAGED_NODE_VERSIONS,rY as LogsManager,V7 as LogicalDatabaseBackupSource,x7 as LocalEncryptedConfigurationBackend,q2 as LambdaVersionsManager,w2 as LambdaVPCManager,IK as LambdaRuntimeAdapter,z2 as LambdaLayersManager,B2 as LambdaDestinationsManager,D2 as LambdaDLQManager,P2 as LambdaConcurrencyManager,y6 as LambdaClient,mW as LARAVEL_SERVERLESS_BUILD_STEPS,i6 as KendraClient,XU as JobStore,MU as JobService,eK as JobProviderReconciler,w1 as JobLoader,b_ as InvalidOperationTransitionError,t0 as InfrastructureGenerator,G2 as ImageScanningManager,_3 as IPV6_EXCLUDED_HOST_LABELS,k$ as IAMClient,L3 as HetznerDriver,w3 as HetznerClient,p$ as HealthCheckRunner,aW as HealthCheckManager,AJ as HashCache,DY as GuardDutyManager,W6 as GoDaddyProvider,DX as GlobalResourceManager,uQ as GitlabSourceAdapter,cQ as GithubSourceAdapter,lQ as GiteaSourceAdapter,m1 as Fn,PU as FleetStore,SU as FleetService,G7 as FilesystemBackupSource,r as FileSystem,FJ as FileCache,WF as FOCUS_VERSION,a2 as FIFOQueueManager,P7 as ExternalConfigurationBackend,nK as EventBridgeJobAdapter,a6 as EventBridgeClient,i9 as ErrorCodes,zU as EncryptedDataSecretStore,d2 as EmailTemplateManager,t2 as EmailHandlers,b$ as EmailClient,m2 as EmailAnalyticsManager,r2 as EmailAdvanced,h as Email,o6 as ElastiCacheClient,KM as EdgeRateLimiter,CK as EcsRuntimeAdapter,W5 as ENFORCEMENT_SEVERITY,p5 as ENFORCEMENT_DESCRIPTIONS,Y5 as ENFORCEMENT_ACTIONS,C6 as ELBv2Client,J3 as EFSClient,w6 as ECSClient,T6 as ECRClient,M6 as EC2Client,f6 as DynamoDBClient,UQ as DurableQueueWorker,KQ as DurableOperationQueue,Z7 as DockerVolumeBackupSource,NQ as DockerNamedVolumeDriver,LK as DockerDiscoveryAdapter,AU as DockerDataTransport,N6 as DnsProviderFactory,PY as DisasterRecoveryManager,r9 as DeploymentError,h1 as Deployment,z1 as DependencyGraph,s9 as DebugLogger,M2 as DatabaseUserManager,t as Database,WU as DataServiceStore,QU as DataServiceLifecycle,b2 as DNSSECManager,S1 as DNS,s2 as DLQMonitoringManager,vK as DIAGNOSTIC_PRESETS,$F as DETECTABLE_SIGNALS,z$ as DEPTH_HEADER,OQ as DEPLOYMENT_QUEUE_KINDS,D5 as DEFAULT_THRESHOLDS,RF as DEFAULT_TELEMETRY_POLICY,b0 as DEFAULT_STATIC_ASSET_EXTENSIONS,r4 as DEFAULT_STATE_DIR,YJ as DEFAULT_SERVICE_LIMITS,P$ as DEFAULT_RECURSION_LIMITS,O5 as DEFAULT_PRICE_BOOK,N5 as DEFAULT_METER_MAPPINGS,v$ as DEFAULT_DDOS_THRESHOLDS,OM as DEFAULT_ATTACK_MODE_HOURS,Q9 as DASHBOARD_STATE_DIR,U9 as DASHBOARD_PORT_SPAN,K9 as DASHBOARD_PORT_BASE,F9 as DASHBOARD_ENTRY,jX as CrossRegionReferenceManager,l9 as CredentialError,B5 as CounterTracker,m_ as ControlPlaneStore,sU as ControlPlaneCleanupDriver,E7 as ControlPlaneBackupSource,E2 as ContainerRegistryManager,OU as ContainerDataAdapter,h6 as ConnectClient,R7 as ConfigurationStore,S7 as ConfigurationService,d9 as ConfigurationError,vF as ComputeSpendTransport,j as Compute,u6 as ComprehendClient,jQ as ComposeApplicationStore,DQ as ComposeApplicationService,p1 as Communication,PX as CommandHistory,Q6 as CloudflareProvider,I0 as CloudflarePagesProvider,b6 as CloudWatchLogsClient,wY as CloudTrailManager,v0 as CloudFrontClient,m0 as CloudFormationClient,u1 as CloudFormationBuilder,u9 as CloudError,b3 as CloudDriverFactory,SQ as CloudBlockVolumeDriver,Q2 as CertificateManager,CY as CanaryManager,Y0 as Cache,B_ as CONTROL_PLANE_SCHEMA_VERSION,MY as COMMON_CROSS_ACCOUNT_ROLES,_6 as CLOUDFLARE_MANAGED_RULE_PREFIX,x$ as CHAIN_HEADER,P1 as CDN,U7 as BunFilesystemArchiveRuntime,O7 as BunDockerVolumeRuntime,RU as BunDockerRuntime,O2 as BuildOptimizationManager,f2 as BounceComplaintHandler,bY as BlueGreenManager,dQ as BitbucketSourceAdapter,v6 as BedrockRuntimeClient,c6 as BedrockClient,e2 as BatchProcessingManager,$7 as BackupStore,qY as BackupManager,W7 as BackupCoordinator,N7 as AwsSsmConfigurationBackend,mF as AwsSpendTransport,q7 as AwsSecretsManagerConfigurationBackend,pU as AwsRegionalDriver,ZU as AwsRdsTransport,KU as AwsRdsDataAdapter,H7 as AwsInfrastructureBackupSource,YK as AwsIamCapabilityScanner,HU as AwsElastiCacheTransport,GU as AwsElastiCacheDataAdapter,T3 as AwsDriver,Q7 as AwsDatabaseBackupSource,EU as AwsAuroraTransport,UU as AwsAuroraDataAdapter,l_ as AutomationIdentityStore,lF as AutomationApiService,R_ as AuthenticationStore,b1 as Auth,C1 as AssetHasher,v1 as Arn,n6 as ApplicationAutoScalingClient,uF as ApiServiceError,T0 as ApiGateway,e5 as AnomalyConfigStore,h$ as AlertStore,C$ as AlertEvaluator,_$ as AcmeClient,IX as AWS_REGIONS,c1 as AWS_PSEUDO_PARAMETERS,BY as AWSConfigManager,v0 as AWSCloudFrontClient,m0 as AWSCloudFormationClient,D$ as AWSClient,g9 as AWSAPIError,V_ as AUTH_SESSION_IDLE_TTL_MS,O_ as AUTH_SESSION_ABSOLUTE_TTL_MS,H_ as AUTH_OIDC_TRANSACTION_TTL_MS,E_ as AUTH_MFA_CHALLENGE_TTL_MS,Z_ as AUTH_ACTION_TOKEN_TTL_MS,w_ as AUTHORIZATION_CAPABILITIES,gF as API_VERSION,u_ as API_TOKEN_MAX_TTL_MS,c_ as API_TOKEN_DEFAULT_TTL_MS,d_ as API_IDEMPOTENCY_TTL_MS,C as AI,y0 as ACME_DIRECTORIES,B6 as ACMDnsValidator,S6 as ACMClient,fY as ABTestManager};