@stacksjs/ts-cloud 0.9.4 → 0.10.0

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