@stacksjs/ts-cloud 0.11.6 → 0.12.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 (103) hide show
  1. package/dist/aws/index.js +1 -1
  2. package/dist/bin/{chunk-znnawt0k.js → chunk-71t1gmsq.js} +1 -1
  3. package/dist/bin/{chunk-4xhj37nj.js → chunk-8ewncfce.js} +1 -1
  4. package/dist/bin/{chunk-8khgprf6.js → chunk-9kf0np8j.js} +1 -1
  5. package/dist/bin/chunk-cxt74wsj.js +1 -0
  6. package/dist/bin/{chunk-j447p8t4.js → chunk-g6baf9c5.js} +84 -84
  7. package/dist/bin/{chunk-zsf6pccz.js → chunk-q5cmfpzt.js} +1 -1
  8. package/dist/bin/{chunk-r6b3pq31.js → chunk-rtecnmts.js} +1 -1
  9. package/dist/bin/{chunk-5nsqz5n3.js → chunk-rv18092e.js} +1 -1
  10. package/dist/bin/{chunk-yw6f160x.js → chunk-ta7sh0cc.js} +1 -1
  11. package/dist/bin/{chunk-cbsys5v8.js → chunk-tfbs8k8v.js} +1 -1
  12. package/dist/bin/{chunk-g0fm1xcs.js → chunk-xkfrqqcs.js} +1 -1
  13. package/dist/bin/cli.js +122 -116
  14. package/dist/bin/dashboard-server.js +1 -1
  15. package/dist/cdn/cloudflare-rules.d.ts +37 -0
  16. package/dist/chunk-13qjvbqh.js +2 -0
  17. package/dist/{chunk-nk7sav4r.js → chunk-152he7m3.js} +1 -1
  18. package/dist/{chunk-dr4pj8hp.js → chunk-3mgj3hrh.js} +1 -1
  19. package/dist/chunk-6kpbveb8.js +5 -0
  20. package/dist/{chunk-aw0cgv5w.js → chunk-86ss83s2.js} +1 -1
  21. package/dist/chunk-a84gmpyh.js +1 -0
  22. package/dist/{chunk-ywjkyg8p.js → chunk-b087qsyf.js} +99 -99
  23. package/dist/{chunk-zam6ecam.js → chunk-h42zck7h.js} +2 -2
  24. package/dist/{chunk-zz52xje8.js → chunk-jm5mg890.js} +1 -1
  25. package/dist/{chunk-kasdm9tx.js → chunk-m8fs0233.js} +1 -1
  26. package/dist/chunk-nms5q44e.js +1 -0
  27. package/dist/{chunk-aw0spg20.js → chunk-nzqxdkch.js} +2 -2
  28. package/dist/{chunk-rd38qdnf.js → chunk-qm32ytbr.js} +1 -1
  29. package/dist/{chunk-q0rc1ax9.js → chunk-t0xgmhd6.js} +1 -1
  30. package/dist/{chunk-q9q6cmt0.js → chunk-t3t9ymec.js} +1 -1
  31. package/dist/{chunk-5vt93kxx.js → chunk-y2v22hkv.js} +1 -1
  32. package/dist/deploy/index.js +1 -1
  33. package/dist/dns/index.js +1 -1
  34. package/dist/drivers/index.js +1 -1
  35. package/dist/index.d.ts +1 -0
  36. package/dist/index.js +45 -45
  37. package/dist/operations/drained-sites.d.ts +56 -0
  38. package/dist/operations/drained-sites.test.d.ts +1 -0
  39. package/dist/pages/cloudflare-pages.d.ts +227 -0
  40. package/dist/pages/cloudflare-pages.test.d.ts +1 -0
  41. package/dist/pages/index.d.ts +2 -0
  42. package/dist/protection/index.js +1 -1
  43. package/dist/push/index.js +1 -1
  44. package/dist/spend/index.js +1 -1
  45. package/dist/ui/404.html +1 -1
  46. package/dist/ui/accept-invitation.html +1 -1
  47. package/dist/ui/access-denied.html +1 -1
  48. package/dist/ui/account/automation.html +5 -5
  49. package/dist/ui/account/security.html +1 -1
  50. package/dist/ui/applications/compose.html +5 -5
  51. package/dist/ui/applications/new.html +2 -2
  52. package/dist/ui/data/backups.html +6 -6
  53. package/dist/ui/data/services.html +6 -6
  54. package/dist/ui/data/volumes.html +6 -6
  55. package/dist/ui/index.html +6 -6
  56. package/dist/ui/infrastructure/topology.html +5 -5
  57. package/dist/ui/integrations.html +2 -2
  58. package/dist/ui/operations/alerts.html +6 -6
  59. package/dist/ui/operations/configuration.html +6 -6
  60. package/dist/ui/operations/jobs.html +6 -6
  61. package/dist/ui/operations/maintenance.html +5 -5
  62. package/dist/ui/operations/observability.html +6 -6
  63. package/dist/ui/operations/previews.html +6 -6
  64. package/dist/ui/operations/queue.html +6 -6
  65. package/dist/ui/operations/regions.html +5 -5
  66. package/dist/ui/operations/releases.html +6 -6
  67. package/dist/ui/operations/spend.html +6 -6
  68. package/dist/ui/operations/workloads.html +6 -6
  69. package/dist/ui/security.html +2 -2
  70. package/dist/ui/server/actions.html +6 -6
  71. package/dist/ui/server/activity.html +2 -2
  72. package/dist/ui/server/capacity.html +6 -6
  73. package/dist/ui/server/database.html +6 -6
  74. package/dist/ui/server/deployments.html +6 -6
  75. package/dist/ui/server/diagnostics.html +1 -1
  76. package/dist/ui/server/firewall.html +6 -6
  77. package/dist/ui/server/fleet.html +6 -6
  78. package/dist/ui/server/logs.html +6 -6
  79. package/dist/ui/server/metrics.html +6 -6
  80. package/dist/ui/server/security.html +2 -2
  81. package/dist/ui/server/services.html +2 -2
  82. package/dist/ui/server/sites.html +6 -6
  83. package/dist/ui/server/ssh-keys.html +6 -6
  84. package/dist/ui/server/team.html +6 -6
  85. package/dist/ui/server/terminal.html +2 -2
  86. package/dist/ui/serverless/alarms.html +6 -6
  87. package/dist/ui/serverless/assets.html +2 -2
  88. package/dist/ui/serverless/cost.html +2 -2
  89. package/dist/ui/serverless/data.html +6 -6
  90. package/dist/ui/serverless/deployments.html +2 -2
  91. package/dist/ui/serverless/firewall.html +1 -1
  92. package/dist/ui/serverless/functions.html +5 -5
  93. package/dist/ui/serverless/logs.html +6 -6
  94. package/dist/ui/serverless/metrics.html +2 -2
  95. package/dist/ui/serverless/queues.html +6 -6
  96. package/dist/ui/serverless/secrets.html +6 -6
  97. package/dist/ui/serverless/traces.html +6 -6
  98. package/dist/ui/serverless.html +6 -6
  99. package/package.json +4 -3
  100. package/dist/bin/chunk-wkx799z2.js +0 -1
  101. package/dist/chunk-95e6aeqz.js +0 -1
  102. package/dist/chunk-p10xt3jb.js +0 -1
  103. package/dist/chunk-z2qqwy7e.js +0 -2
package/dist/index.js CHANGED
@@ -1,17 +1,17 @@
1
- import{$ as zg,$a as kC,$b as kS,$c as eA,A as Nf,Aa as aC,Ab as aS,B as kf,Ba as sC,Bb as sS,Bc as Ai,C as xf,Ca as cC,Cb as cS,Cc as bi,D as Lf,Da as lC,Db as lS,Dc as Ri,E as Sg,Ea as dC,Eb as dS,Ec as Ti,F as Ag,Fa as uC,Fb as uS,Fc as $i,G as bg,Ga as pC,Gb as pS,Gc as Pi,H as Rg,Ha as mC,Hb as mS,Hc as Ii,I as Tg,Ia as fC,Ib as fS,J as $g,Ja as gC,Jb as gS,K as Pg,Ka as hC,Kb as hS,L as Ig,La as yC,Lb as yS,M as Dg,Ma as CC,Mb as CS,N as Eg,Na as SC,Nb as SS,O as wg,Oa as AC,Ob as AS,P as vg,Pa as bC,Pb as bS,Pc as zS,Q as Og,Qa as RC,Qb as RS,Qc as HS,R as Ng,Ra as TC,Rb as TS,Rc as GS,S as kg,Sa as $C,Sb as $S,Sc as KS,T as xg,Ta as PC,Tb as PS,Tc as US,U as Lg,Ua as IC,Ub as IS,Uc as ZS,V as Mg,Va as DC,Vb as DS,Vc as jS,W as Fg,Wa as EC,Wb as ES,Wc as qS,X as Vg,Xa as wC,Xb as wS,Xc as JS,Y as _g,Ya as vC,Yb as vS,Yc as YS,Z as Bg,Za as OC,Zb as OS,Zc as QS,_ as Wg,_a as NC,_b as NS,_c as XS,a as Hm,aa as Hg,ab as xC,ac as xS,ad as tA,b as Gm,ba as Gg,bb as LC,bc as LS,bd as rA,c as Km,ca as My,cb as MC,cc as MS,cd as nA,d as Um,da as Fy,db as FC,dc as FS,dd as iA,e as Zm,ea as Vy,eb as VC,ec as VS,ed as oA,f as jm,fa as _y,fb as _C,fc as _S,fd as aA,g as qm,ga as By,gb as BC,gc as BS,gd as sA,h as Jm,ha as Wy,hb as WC,hc as WS,hd as cA,i as Ym,ia as zy,ib as zC,id as lA,j as Qm,ja as Hy,jb as HC,jd as dA,k as Xm,ka as Gy,kb as GC,kd as uA,l as ef,la as Ky,lb as KC,ld as pA,m as tf,ma as Uy,mb as UC,md as mA,n as rf,na as Zy,nb as ZC,nd as fA,o as nf,oa as jy,ob as jC,od as Di,p as of,pa as qy,pb as qC,pc as Ci,pd as Ei,q as af,qa as Jy,qb as JC,qd as wi,r as sf,ra as Yy,rb as YC,rd as vi,s as cf,sa as Qy,sb as QC,t as lf,ta as Xy,tb as XC,u as df,ua as eC,ub as eS,v as uf,va as tC,vb as tS,w as pf,wa as rC,wb as rS,x as mf,xa as nC,xb as nS,y as vf,ya as iC,yb as iS,z as Of,za as oC,zb as oS}from"./chunk-ywjkyg8p.js";import{Ad as yi,sd as li,td as di,ud as ui,vd as pi,wd as mi,xd as fi,yd as gi,zd as hi}from"./chunk-zam6ecam.js";import{Id as Si}from"./chunk-dr4pj8hp.js";import{$d as Dr,Be as Mr,Fe as Fr,Jd as Vt,Ld as _t,Le as Vr,Md as Bt,Nd as Wt,Od as zt,Oe as _r,Pd as Ht,Pe as Br,Qd as Gt,Qe as Wr,Re as zr,Sd as Ut,Td as yr,Ud as Sr,Vd as Ar,Wd as br,We as Hr,Xd as Rr,Yd as Tr,Zd as $r,_d as Pr,ae as Er,be as wr,ce as vr,de as Or,ef as Gr,if as Kr,ke as Nr,nf as Ur,pe as kr,te as xr,xe as Lr}from"./chunk-q0rc1ax9.js";import{of as At,pf as Rt,qf as Tt}from"./chunk-kasdm9tx.js";import{sf as Me}from"./chunk-by2bwzk6.js";import{tf as hr}from"./chunk-73ztr55z.js";import{uf as Ir}from"./chunk-xcj8zfmg.js";import{Af as Qt,Bf as Xt,Cf as er,Df as tr,Ef as rr,Ff as nr,Gf as ir,Hf as or,If as ar,Jf as sr,Kf as cr,Lf as lr,Mf as dr,Nf as q,Of as ur,Pf as pr,Qf as mr,Rf as fr,Sf as gr,vf as Zt,wf as jt,xf as qt,yf as Jt,zf as Yt}from"./chunk-tz9myq9a.js";import{Tf as j}from"./chunk-y4xkj2f1.js";import{$f as Xr,$g as vn,Ah as Fn,Bh as Vn,Fh as _n,Gh as Bn,Hg as hn,Hh as Wn,Ig as yn,Ih as zn,Jh as Hn,Kg as Cn,Kh as Gn,Lg as Sn,Lh as Kn,Mg as An,Ng as bn,Nh as Un,Og as Rn,Oh as Zn,Ph as jn,Qh as qn,Rg as Tn,Sg as $n,Tg as Pn,Uf as Zr,Vf as jr,Wf as qr,Xf as Jr,Xg as In,Yf as ue,Yg as Dn,Zf as Yr,Zg as En,_f as Qr,_g as wn,ag as en,ah as On,bg as tn,ig as Ee,lg as rn,mg as nn,ng as on,og as an,oh as Nn,ph as kn,qg as sn,qh as xn,rg as cn,rh as Ln,vg as ln,wg as pe,zh as Mn}from"./chunk-aw0spg20.js";import{Vh as Kt,Wh as Cr}from"./chunk-aj025v2s.js";import{Xh as Le}from"./chunk-wavjkdb8.js";import{Zh as bt}from"./chunk-nk7sav4r.js";import{$h as St}from"./chunk-mz0dk78z.js";import{$i as yg,$j as Hh,Ai as Gf,Aj as hh,Ak as uy,Bi as Kf,Bj as yh,Bk as py,Ci as Uf,Cj as Ch,Ck as my,Di as Zf,Dj as Sh,Dk as fy,Ei as jf,Ej as Ah,Ek as gy,Fi as qf,Fj as bh,Fk as hy,Gi as Jf,Gj as Rh,Gk as yy,Hi as Yf,Hj as Th,Hk as Cy,Ii as Qf,Ij as $h,Ik as wt,Ji as Xf,Jj as Ph,Jk as Sy,Ki as eg,Kj as Ih,Kk as Ay,Li as tg,Lj as Dh,Lk as by,Mi as rg,Mj as Eh,Mk as Ry,Ni as ng,Nj as wh,Nk as Ty,Oi as ig,Oj as vh,Ok as $y,Pi as og,Pj as Oh,Pk as Py,Qi as ag,Qj as Nh,Qk as Iy,Ri as sg,Rj as kh,Rk as Dy,Si as cg,Sj as xh,Sk as Ey,Ti as lg,Tj as Lh,Tk as wy,Ui as dg,Uj as Mh,Uk as vy,Vi as ug,Vj as Fh,Vk as Oy,Wi as pg,Wj as Vh,Wk as Ny,Xi as mg,Xj as _h,Xk as ky,Yi as fg,Yj as Bh,Yk as xy,Zi as gg,Zj as Wh,Zk as Ly,_i as hg,_j as zh,aj as Cg,ak as Gh,bj as Kg,bk as Kh,ci as ff,cj as Ug,ck as Uh,di as gf,dj as Zg,dk as Zh,ei as hf,ej as jg,ek as jh,fi as yf,fj as qg,fk as qh,gi as Cf,gj as Jg,gk as Jh,hi as Sf,hj as Yg,hk as Yh,ii as Af,ij as Qg,ik as Qh,ji as bf,jj as Xg,jk as Xh,ki as Rf,kj as eh,kk as ey,li as Tf,lj as th,lk as ty,mi as $f,mj as rh,mk as ry,ni as Pf,nj as nh,nk as ny,oi as If,oj as ih,ok as iy,pi as Df,pj as oh,pk as oy,qi as Ef,qj as ah,qk as $t,ri as wf,rj as sh,rk as Pt,si as Mf,sj as ch,sk as It,ti as Ff,tj as lh,tk as Dt,ui as Vf,uj as dh,uk as Et,vi as _f,vj as uh,vk as ay,wi as Bf,wj as ph,wk as sy,xi as Wf,xj as mh,xk as cy,yi as zf,yj as fh,yk as ly,zi as Hf,zj as gh,zk as dy}from"./chunk-aw0cgv5w.js";import{$k as Yn,_k as Jn,al as Qn,bl as Xn,cl as ei,dl as ti,el as ri,gl as ni,hl as ii,il as oi,jl as ai,kl as si,ll as ci}from"./chunk-1qdne0bf.js";import{nl as dn,ol as un,pl as pn,ql as mn,rl as fn,sl as gn}from"./chunk-hn40z11p.js";import{Al as Ft,tl as vt,ul as Ot,vl as Nt,wl as kt,xl as xt,yl as Lt,zl as Mt}from"./chunk-x3hay61c.js";import{$l as Ha,$m as De,$n as $c,$o as $l,$p as $d,$q as $u,$r as $p,$s as fm,Am as ps,An as Ys,Ao as Yc,Ap as Yl,Aq as Yd,Ar as Yu,As as Yp,At as Wm,Bl as ya,Bm as ee,Bn as Qs,Bo as Qc,Bp as Ql,Bq as Qd,Br as Qu,Bs as Qp,Bt as zm,Cl as Ca,Cm as w,Cn as Xs,Co as Xc,Cp as Xl,Cq as Xd,Cr as Xu,Cs as Xp,Dl as Sa,Dm as Re,Dn as ec,Do as el,Dp as ed,Dq as eu,Dr as ep,Ds as em,El as Aa,Em as K,En as tc,Eo as tl,Ep as td,Eq as tu,Er as tp,Es as tm,Fl as ba,Fm as L,Fn as rc,Fo as rl,Fp as rd,Fq as ru,Fr as rp,Fs as rm,Gl as Ra,Gm as ms,Gn as nc,Go as nl,Gp as nd,Gq as nu,Gr as np,Gs as nm,Hl as Ta,Hm as fs,Hn as ic,Ho as il,Hp as id,Hq as iu,Hr as ip,Hs as im,Il as $a,Im as te,In as oc,Io as ol,Ip as od,Iq as ou,Ir as op,Is as om,Jl as Pa,Jm as gs,Jn as ac,Jo as al,Jp as ad,Jq as au,Jr as ap,Js as am,Kl as Ia,Km as hs,Kn as sc,Ko as sl,Kp as sd,Kq as su,Kr as sp,Ks as sm,Ll as Da,Lm as ys,Ln as cc,Lo as cl,Lp as cd,Lq as cu,Lr as cp,Ls as cm,Ml as Ea,Mm as Cs,Mn as lc,Mo as ll,Mp as ld,Mq as lu,Mr as lp,Ms as lm,Nl as wa,Nm as Te,Nn as dc,No as dl,Np as dd,Nq as du,Nr as dp,Ns as lt,Ol as va,Om as M,On as uc,Oo as ul,Op as ud,Oq as uu,Or as up,Os as dt,Pl as Oa,Pm as U,Pn as pc,Po as pl,Pp as pd,Pq as pu,Pr as pp,Ps as ut,Ql as Na,Qm as re,Qn as mc,Qo as ml,Qp as md,Qq as mu,Qr as mp,Qs as pt,Rl as ka,Rm as $e,Rn as fc,Ro as fl,Rp as fd,Rq as fu,Rr as fp,Rs as mt,Sl as xa,Sm as Pe,Sn as gc,So as gl,Sp as gd,Sq as gu,Sr as gp,Ss as ft,Tl as La,Tm as Ss,Tn as hc,To as hl,Tp as hd,Tq as hu,Tr as hp,Ts as gt,Ul as Ma,Um as As,Un as yc,Uo as yl,Up as yd,Uq as yu,Ur as yp,Us as ht,Vl as Fa,Vm as Ie,Vn as Cc,Vo as Cl,Vp as Cd,Vq as Cu,Vr as Cp,Vs as yt,Wl as Va,Wm as bs,Wn as Sc,Wo as Sl,Wp as Sd,Wq as Su,Wr as Sp,Ws as Ct,Xl as _a,Xm as Rs,Xn as Ac,Xo as Al,Xp as Ad,Xq as Au,Xr as Ap,Xs as dm,Yl as Ba,Ym as Ts,Yn as bc,Yo as bl,Yp as bd,Yq as bu,Yr as bp,Ys as um,Zl as Wa,Zm as $s,Zn as Rc,Zo as Rl,Zp as Rd,Zq as Ru,Zr as Rp,Zs as pm,_l as za,_m as Ps,_n as Tc,_o as Tl,_p as Td,_q as Tu,_r as Tp,_s as mm,am as Ga,an as Z,ao as Pc,ap as Pl,aq as Pd,ar as Pu,as as Pp,at as gm,bm as Ka,bn as Is,bo as Ic,bp as Il,bq as Id,br as Iu,bs as Ip,bt as hm,cm as Ua,cn as Ds,co as Dc,cp as Dl,cq as Dd,cr as Du,cs as Dp,ct as ym,dm as Za,dn as Es,do as Ec,dp as El,dq as Ed,dr as Eu,ds as Ep,dt as Cm,em as ja,en as ws,eo as wc,ep as wl,eq as wd,er as wu,es as wp,et as Sm,fm as Se,fn as vs,fo as vc,fp as vl,fq as vd,fr as vu,fs as vp,ft as Am,gm as qa,gn as Os,go as Oc,gp as Ol,gq as Od,gr as Ou,gs as Op,gt as bm,hm as Ae,hn as Ns,ho as Nc,hp as Nl,hq as Nd,hr as Nu,hs as Np,ht as Rm,im as be,in as ks,io as kc,ip as kl,iq as kd,ir as ku,is as kp,it as Tm,jm as Ja,jn as xs,jo as xc,jp as xl,jq as xd,jr as xu,js as xp,jt as $m,km as Ya,kn as Ls,ko as Lc,kp as Ll,kq as Ld,kr as Lu,ks as Lp,kt as Pm,lm as Qa,ln as Ms,lo as Mc,lp as Ml,lq as Md,lr as Mu,ls as Mp,lt as Im,mm as Xa,mn as Fs,mo as Fc,mp as Fl,mq as Fd,mr as Fu,ms as Fp,mt as Dm,nm as es,nn as Vs,no as Vc,np as Vl,nq as Vd,nr as Vu,ns as Vp,nt as Em,om as ts,on as _s,oo as _c,op as _l,oq as _d,or as _u,os as _p,ot as wm,pm as rs,pn as Bs,po as Bc,pp as Bl,pq as Bd,pr as Bu,ps as Bp,pt as vm,qm as ns,qn as Ws,qo as Wc,qp as Wl,qq as Wd,qr as Wu,qs as Wp,qt as Om,rm as is,rn as zs,ro as zc,rp as zl,rq as zd,rr as zu,rs as zp,rt as Nm,sm as os,sn as Hs,so as Hc,sp as Hl,sq as Hd,sr as Hu,ss as Hp,st as km,tm as as,tn as Gs,to as Gc,tp as Gl,tq as Gd,tr as Gu,ts as Gp,tt as xm,um as ss,un as Ks,uo as Kc,up as Kl,uq as Kd,ur as Ku,us as Kp,ut as Lm,vm as cs,vn as Us,vo as Uc,vp as Ul,vq as Ud,vr as Uu,vs as Up,vt as Mm,wm as ls,wn as Zs,wo as Zc,wp as Zl,wq as Zd,wr as Zu,ws as Zp,wt as Fm,xm as X,xn as js,xo as jc,xp as jl,xq as jd,xr as ju,xs as jp,xt as Vm,ym as ds,yn as qs,yo as qc,yp as ql,yq as qd,yr as qu,ys as qp,yt as _m,zm as us,zn as Js,zo as Jc,zp as Jl,zq as Jd,zr as Ju,zs as Jp,zt as Bm}from"./chunk-zz52xje8.js";import{Ct as Je}from"./chunk-z2qqwy7e.js";import{createHmac as fe,createSign as _e,timingSafeEqual as Be}from"node:crypto";function B(e){let t=e instanceof Date?e.getTime():e;if(!Number.isFinite(t))throw TypeError("Media access timestamp must be finite");return Math.floor(t/1000)}function ge(e){return Buffer.from(e).toString("base64").replaceAll("+","-").replaceAll("=","_").replaceAll("/","~")}function We(e){return Buffer.from(e).toString("base64url")}function he(e,t=!1){if(!e||/[\r\n]/.test(e))throw TypeError("Media resource is invalid");let r=t?e.replaceAll("*","wildcard"):e,n=new URL(r);if(!["http:","https:"].includes(n.protocol))throw TypeError("Media resource must use HTTP or HTTPS");if(!t&&e.includes("*"))throw TypeError("Canned policies cannot contain wildcards")}function ye(e,t){let r=_e("RSA-SHA1");return r.update(e),r.end(),ge(r.sign(t))}function Ce(e){he(e.resource,!0);let r={DateLessThan:{"AWS:EpochTime":B(e.expiresAt)}};if(e.activeAt!==void 0)r.DateGreaterThan={"AWS:EpochTime":B(e.activeAt)};if(e.ipAddress)r.IpAddress={"AWS:SourceIp":e.ipAddress};return JSON.stringify({Statement:[{Resource:e.resource,Condition:r}]})}function Ni(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 ki(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 xi(e){if(!e.resource||/[\r\n]/.test(e.resource))throw TypeError("Media resource is invalid");let t=We(Buffer.from(JSON.stringify({resource:e.resource,expiresAt:B(e.expiresAt),...e.keyId?{keyId:e.keyId}:{},...e.audience?{audience:e.audience}:{}}))),r=fe("sha256",e.secret).update(t).digest("base64url");return`${t}.${r}`}function Li(e,t){let[r,n,o]=e.split(".");if(!r||!n||o)return null;let l=fe("sha256",t.secret).update(r).digest(),c;try{c=Buffer.from(n,"base64url")}catch{return null}if(l.length!==c.length||!Be(l,c))return null;try{let s=JSON.parse(Buffer.from(r,"base64url").toString("utf8")),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 Mi(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 Fi(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 ze{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`,h=this.mergedConfig.infrastructure?.servers?.app?.region||this.mergedConfig.project?.region||"us-east-1",u=h==="us-east-1"?".compute-1.amazonaws.com":`.${h}.compute.amazonaws.com`,b={"Fn::Join":["",["ec2-",{"Fn::Join":["-",{"Fn::Split":[".",{Ref:c}]}]},u]]},A=this.resolveApiOriginPort();if(e.push({Id:d,DomainName:b,CustomOriginConfig:{HTTPPort:A,HTTPSPort:443,OriginProtocolPolicy:"http-only",OriginSSLProtocols:["TLSv1.2"]}}),r.push(c),s)r.push(s);for(let T of l)t.push(this.createComputeCacheBehavior(T,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,h)=>{let u=!d.path||d.path==="/",b=!h.path||h.path==="/";if(u&&!b)return 1;if(!u&&b)return-1;return(h.path?.length??0)-(d.path?.length??0)}).map((d)=>{let h=!d.path||d.path==="/",u=`reverse_proxy localhost:${d.port}`;return h?` handle {
1
+ import{$ as nh,$a as qC,$b as qS,$c as gA,A as Kf,Aa as bC,Ab as bS,B as qf,Ba as RC,Bb as RS,Bc as Oi,C as Zf,Ca as TC,Cb as TS,Cc as Ni,D as Jf,Da as PC,Db as PS,Dc as ki,E as xg,Ea as $C,Eb as $S,Ec as xi,F as Lg,Fa as DC,Fb as DS,Fc as Li,G as Fg,Ga as IC,Gb as IS,Gc as Fi,H as Mg,Ha as wC,Hb as wS,Hc as Mi,I as _g,Ia as EC,Ib as ES,J as Bg,Ja as vC,Jb as vS,K as Vg,Ka as OC,Kb as OS,L as Wg,La as NC,Lb as NS,M as Hg,Ma as kC,Mb as kS,N as zg,Na as xC,Nb as xS,O as Gg,Oa as LC,Ob as LS,P as Ug,Pa as FC,Pb as FS,Pc as nA,Q as jg,Qa as MC,Qb as MS,Qc as iA,R as Kg,Ra as _C,Rb as _S,Rc as oA,S as qg,Sa as BC,Sb as BS,Sc as aA,T as Zg,Ta as VC,Tb as VS,Tc as sA,U as Jg,Ua as WC,Ub as WS,Uc as cA,V as Yg,Va as HC,Vb as HS,Vc as lA,W as Xg,Wa as zC,Wb as zS,Wc as dA,X as Qg,Xa as GC,Xb as GS,Xc as uA,Y as eh,Ya as UC,Yb as US,Yc as pA,Z as th,Za as jC,Zb as jS,Zc as mA,_ as rh,_a as KC,_b as KS,_c as fA,a as of,aa as ih,ab as ZC,ac as ZS,ad as hA,b as af,ba as oh,bb as JC,bc as JS,bd as yA,c as sf,ca as Yy,cb as YC,cc as YS,cd as CA,d as cf,da as Xy,db as XC,dc as XS,dd as SA,e as lf,ea as Qy,eb as QC,ec as QS,ed as AA,f as df,fa as eC,fb as eS,fc as eA,fd as bA,g as uf,ga as tC,gb as tS,gc as tA,gd as RA,h as pf,ha as rC,hb as rS,hc as rA,hd as TA,i as mf,ia as nC,ib as nS,id as PA,j as ff,ja as iC,jb as iS,jd as $A,k as gf,ka as oC,kb as oS,kd as DA,l as hf,la as aC,lb as aS,ld as IA,m as yf,ma as sC,mb as sS,md as wA,n as Cf,na as cC,nb as cS,nd as EA,o as Sf,oa as lC,ob as lS,od as _i,p as Af,pa as dC,pb as dS,pc as Ei,pd as Bi,q as bf,qa as uC,qb as uS,qd as Vi,r as Rf,ra as pC,rb as pS,rd as Wi,s as Tf,sa as mC,sb as mS,t as Pf,ta as fC,tb as fS,u as $f,ua as gC,ub as gS,v as Df,va as hC,vb as hS,w as If,wa as yC,wb as yS,x as wf,xa as CC,xb as CS,y as Uf,ya as SC,yb as SS,z as jf,za as AC,zb as AS}from"./chunk-b087qsyf.js";import{Ad as wi,sd as Ai,td as bi,ud as Ri,vd as Ti,wd as Pi,xd as $i,yd as Di,zd as Ii}from"./chunk-h42zck7h.js";import{Id as vi}from"./chunk-3mgj3hrh.js";import{$d as _r,Be as Kr,Fe as qr,Jd as Zt,Ld as Jt,Le as Zr,Md as Yt,Nd as Xt,Od as Qt,Oe as Jr,Pd as er,Pe as Yr,Qd as tr,Qe as Xr,Re as Qr,Sd as nr,Td as wr,Ud as vr,Vd as Or,Wd as Nr,We as en,Xd as kr,Yd as xr,Zd as Lr,_d as Fr,ae as Br,be as Vr,ce as Wr,de as Hr,ef as tn,if as rn,ke as zr,nf as nn,pe as Gr,te as Ur,xe as jr}from"./chunk-t0xgmhd6.js";import{of as Ot,pf as kt,qf as xt}from"./chunk-m8fs0233.js";import{sf as We}from"./chunk-by2bwzk6.js";import{tf as Ir}from"./chunk-73ztr55z.js";import{uf as Mr}from"./chunk-xcj8zfmg.js";import{Af as lr,Bf as dr,Cf as ur,Df as pr,Ef as mr,Ff as fr,Gf as gr,Hf as hr,If as yr,Jf as Cr,Kf as Sr,Lf as Ar,Mf as br,Nf as Y,Of as Rr,Pf as Tr,Qf as Pr,Rf as $r,Sf as Dr,vf as ir,wf as or,xf as ar,yf as sr,zf as cr}from"./chunk-tz9myq9a.js";import{Tf as J}from"./chunk-y4xkj2f1.js";import{$f as un,$g as Wn,Ah as qn,Bh as Zn,Fh as Jn,Gh as Yn,Hg as In,Hh as Xn,Ig as wn,Ih as Qn,Jh as ei,Kg as En,Kh as ti,Lg as vn,Lh as ri,Mg as On,Ng as Nn,Nh as ni,Og as kn,Oh as ii,Ph as oi,Qh as ai,Rg as xn,Sg as Ln,Tg as Fn,Uf as on,Vf as an,Wf as sn,Xf as cn,Xg as Mn,Yf as pe,Yg as _n,Zf as ln,Zg as Bn,_f as dn,_g as Vn,ag as pn,ah as Hn,bg as mn,ig as ve,lg as fn,mg as gn,ng as hn,og as yn,oh as zn,ph as Gn,qg as Cn,qh as Un,rg as Sn,rh as jn,vg as An,wg as me,zh as Kn}from"./chunk-nzqxdkch.js";import{Vh as rr,Wh as Er}from"./chunk-aj025v2s.js";import{Xh as Ve}from"./chunk-wavjkdb8.js";import{Zh as Nt}from"./chunk-152he7m3.js";import{$h as vt}from"./chunk-mz0dk78z.js";import{$i as Ng,$j as iy,Ai as og,Aj as Oh,Ak as Dy,Bi as ag,Bj as Nh,Bk as Iy,Ci as sg,Cj as kh,Ck as wy,Di as cg,Dj as xh,Dk as Ey,Ei as lg,Ej as Lh,Ek as vy,Fi as dg,Fj as Fh,Fk as Oy,Gi as ug,Gj as Mh,Gk as Ny,Hi as pg,Hj as _h,Hk as ky,Ii as mg,Ij as Bh,Ik as Vt,Ji as fg,Jj as Vh,Jk as xy,Ki as gg,Kj as Wh,Kk as Ly,Li as hg,Lj as Hh,Lk as Fy,Mi as yg,Mj as zh,Mk as My,Ni as Cg,Nj as Gh,Nk as _y,Oi as Sg,Oj as Uh,Ok as By,Pi as Ag,Pj as jh,Pk as Vy,Qi as bg,Qj as Kh,Qk as Wy,Ri as Rg,Rj as qh,Rk as Hy,Si as Tg,Sj as Zh,Sk as zy,Ti as Pg,Tj as Jh,Tk as Gy,Ui as $g,Uj as Yh,Uk as Uy,Vi as Dg,Vj as Xh,Vk as jy,Wi as Ig,Wj as Qh,Wk as Ky,Xi as wg,Xj as ey,Xk as qy,Yi as Eg,Yj as ty,Yk as Zy,Zi as vg,Zj as ry,Zk as Jy,_i as Og,_j as ny,aj as kg,ak as oy,bj as ah,bk as ay,ci as Ef,cj as sh,ck as sy,di as vf,dj as ch,dk as cy,ei as Of,ej as lh,ek as ly,fi as Nf,fj as dh,fk as dy,gi as kf,gj as uh,gk as uy,hi as xf,hj as ph,hk as py,ii as Lf,ij as mh,ik as my,ji as Ff,jj as fh,jk as fy,ki as Mf,kj as gh,kk as gy,li as _f,lj as hh,lk as hy,mi as Bf,mj as yh,mk as yy,ni as Vf,nj as Ch,nk as Cy,oi as Wf,oj as Sh,ok as Sy,pi as Hf,pj as Ah,pk as Ay,qi as zf,qj as bh,qk as Lt,ri as Gf,rj as Rh,rk as Ft,si as Yf,sj as Th,sk as Mt,ti as Xf,tj as Ph,tk as _t,ui as Qf,uj as $h,uk as Bt,vi as eg,vj as Dh,vk as by,wi as tg,wj as Ih,wk as Ry,xi as rg,xj as wh,xk as Ty,yi as ng,yj as Eh,yk as Py,zi as ig,zj as vh,zk as $y}from"./chunk-86ss83s2.js";import{$k as ci,_k as si,al as li,bl as di,cl as ui,dl as pi,el as mi,gl as fi,hl as gi,il as hi,jl as yi,kl as Ci,ll as Si}from"./chunk-1qdne0bf.js";import{nl as bn,ol as Rn,pl as Tn,ql as Pn,rl as $n,sl as Dn}from"./chunk-hn40z11p.js";import{Al as qt,tl as Wt,ul as Ht,vl as zt,wl as Gt,xl as Ut,yl as jt,zl as Kt}from"./chunk-x3hay61c.js";import{$l as is,$m as Ee,$n as Bc,$o as Bl,$p as Bd,$q as Bu,$r as Bp,$s as Em,Am as Is,An as pc,Ao as pl,Ap as pd,Aq as pu,Ar as pp,As as pm,At as rf,Bl as Na,Bm as re,Bn as mc,Bo as ml,Bp as md,Bq as mu,Br as mp,Bs as mm,Bt as nf,Cl as ka,Cm as E,Cn as fc,Co as fl,Cp as fd,Cq as fu,Cr as fp,Cs as fm,Dl as xa,Dm as Pe,Dn as gc,Do as gl,Dp as gd,Dq as gu,Dr as gp,Ds as gm,El as La,Em as j,En as hc,Eo as hl,Ep as hd,Eq as hu,Er as hp,Es as hm,Fl as Fa,Fm as L,Fn as yc,Fo as yl,Fp as yd,Fq as yu,Fr as yp,Fs as ym,Gl as Ma,Gm as ws,Gn as Cc,Go as Cl,Gp as Cd,Gq as Cu,Gr as Cp,Gs as Cm,Hl as _a,Hm as Es,Hn as Sc,Ho as Sl,Hp as Sd,Hq as Su,Hr as Sp,Hs as Sm,Il as Ba,Im as ne,In as Ac,Io as Al,Ip as Ad,Iq as Au,Ir as Ap,Is as Am,Jl as Va,Jm as vs,Jn as bc,Jo as bl,Jp as bd,Jq as bu,Jr as bp,Js as bm,Kl as Wa,Km as Os,Kn as Rc,Ko as Rl,Kp as Rd,Kq as Ru,Kr as Rp,Ks as Rm,Ll as Ha,Lm as Ns,Ln as Tc,Lo as Tl,Lp as Td,Lq as Tu,Lr as Tp,Ls as Tm,Ml as za,Mm as ks,Mn as Pc,Mo as Pl,Mp as Pd,Mq as Pu,Mr as Pp,Ms as Pm,Nl as Ga,Nm as $e,Nn as $c,No as $l,Np as $d,Nq as $u,Nr as $p,Ns as At,Ol as Ua,Om as F,On as Dc,Oo as Dl,Op as Dd,Oq as Du,Or as Dp,Os as bt,Pl as ja,Pm as K,Pn as Ic,Po as Il,Pp as Id,Pq as Iu,Pr as Ip,Ps as Rt,Ql as Ka,Qm as ie,Qn as wc,Qo as wl,Qp as wd,Qq as wu,Qr as wp,Qs as Tt,Rl as qa,Rm as De,Rn as Ec,Ro as El,Rp as Ed,Rq as Eu,Rr as Ep,Rs as Pt,Sl as Za,Sm as Ie,Sn as vc,So as vl,Sp as vd,Sq as vu,Sr as vp,Ss as $t,Tl as Ja,Tm as xs,Tn as Oc,To as Ol,Tp as Od,Tq as Ou,Tr as Op,Ts as Dt,Ul as Ya,Um as Ls,Un as Nc,Uo as Nl,Up as Nd,Uq as Nu,Ur as Np,Us as It,Vl as Xa,Vm as we,Vn as kc,Vo as kl,Vp as kd,Vq as ku,Vr as kp,Vs as wt,Wl as Qa,Wm as Fs,Wn as xc,Wo as xl,Wp as xd,Wq as xu,Wr as xp,Ws as Et,Xl as es,Xm as Ms,Xn as Lc,Xo as Ll,Xp as Ld,Xq as Lu,Xr as Lp,Xs as $m,Yl as ts,Ym as _s,Yn as Fc,Yo as Fl,Yp as Fd,Yq as Fu,Yr as Fp,Ys as Dm,Zl as rs,Zm as Bs,Zn as Mc,Zo as Ml,Zp as Md,Zq as Mu,Zr as Mp,Zs as Im,_l as ns,_m as Vs,_n as _c,_o as _l,_p as _d,_q as _u,_r as _p,_s as wm,am as os,an as q,ao as Vc,ap as Vl,aq as Vd,ar as Vu,as as Vp,at as vm,bm as as,bn as Ws,bo as Wc,bp as Wl,bq as Wd,br as Wu,bs as Wp,bt as Om,cm as ss,cn as Hs,co as Hc,cp as Hl,cq as Hd,cr as Hu,cs as Hp,ct as Nm,dm as cs,dn as zs,do as zc,dp as zl,dq as zd,dr as zu,ds as zp,dt as km,em as ls,en as Gs,eo as Gc,ep as Gl,eq as Gd,er as Gu,es as Gp,et as xm,fm as be,fn as Us,fo as Uc,fp as Ul,fq as Ud,fr as Uu,fs as Up,ft as Lm,gm as ds,gn as js,go as jc,gp as jl,gq as jd,gr as ju,gs as jp,gt as Fm,hm as Re,hn as Ks,ho as Kc,hp as Kl,hq as Kd,hr as Ku,hs as Kp,ht as Mm,im as Te,in as qs,io as qc,ip as ql,iq as qd,ir as qu,is as qp,it as _m,jm as us,jn as Zs,jo as Zc,jp as Zl,jq as Zd,jr as Zu,js as Zp,jt as Bm,km as ps,kn as Js,ko as Jc,kp as Jl,kq as Jd,kr as Ju,ks as Jp,kt as Vm,lm as ms,ln as Ys,lo as Yc,lp as Yl,lq as Yd,lr as Yu,ls as Yp,lt as Wm,mm as fs,mn as Xs,mo as Xc,mp as Xl,mq as Xd,mr as Xu,ms as Xp,mt as Hm,nm as gs,nn as Qs,no as Qc,np as Ql,nq as Qd,nr as Qu,ns as Qp,nt as zm,om as hs,on as ec,oo as el,op as ed,oq as eu,or as ep,os as em,ot as Gm,pm as ys,pn as tc,po as tl,pp as td,pq as tu,pr as tp,ps as tm,pt as Um,qm as Cs,qn as rc,qo as rl,qp as rd,qq as ru,qr as rp,qs as rm,qt as jm,rm as Ss,rn as nc,ro as nl,rp as nd,rq as nu,rr as np,rs as nm,rt as Km,sm as As,sn as ic,so as il,sp as id,sq as iu,sr as ip,ss as im,st as qm,tm as bs,tn as oc,to as ol,tp as od,tq as ou,tr as op,ts as om,tt as Zm,um as Rs,un as ac,uo as al,up as ad,uq as au,ur as ap,us as am,ut as Jm,vm as Ts,vn as sc,vo as sl,vp as sd,vq as su,vr as sp,vs as sm,vt as Ym,wm as Ps,wn as cc,wo as cl,wp as cd,wq as cu,wr as cp,ws as cm,wt as Xm,xm as te,xn as lc,xo as ll,xp as ld,xq as lu,xr as lp,xs as lm,xt as Qm,ym as $s,yn as dc,yo as dl,yp as dd,yq as du,yr as dp,ys as dm,yt as ef,zm as Ds,zn as uc,zo as ul,zp as ud,zq as uu,zr as up,zs as um,zt as tf}from"./chunk-jm5mg890.js";import{Ct as gt,Et as Z}from"./chunk-13qjvbqh.js";import{createHmac as he,createSign as Ge,timingSafeEqual as Ue}from"node:crypto";function V(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 ye(e){return Buffer.from(e).toString("base64").replaceAll("+","-").replaceAll("=","_").replaceAll("/","~")}function je(e){return Buffer.from(e).toString("base64url")}function Ce(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 Se(e,t){let r=Ge("RSA-SHA1");return r.update(e),r.end(),ye(r.sign(t))}function Ae(e){Ce(e.resource,!0);let r={DateLessThan:{"AWS:EpochTime":V(e.expiresAt)}};if(e.activeAt!==void 0)r.DateGreaterThan={"AWS:EpochTime":V(e.activeAt)};if(e.ipAddress)r.IpAddress={"AWS:SourceIp":e.ipAddress};return JSON.stringify({Statement:[{Resource:e.resource,Condition:r}]})}function zi(e,t,r){Ce(e);let n=V(t),i=e.includes("?")?"&":"?",d=Ae({resource:e,expiresAt:t}),s=Se(d,r.privateKey);return`${e}${i}Expires=${n}&Signature=${encodeURIComponent(s)}&Key-Pair-Id=${encodeURIComponent(r.keyPairId)}`}function Gi(e,t){let r=Ae(e);return{"CloudFront-Key-Pair-Id":t.keyPairId,"CloudFront-Policy":ye(Buffer.from(r)),"CloudFront-Signature":Se(r,t.privateKey)}}function Ui(e){if(!e.resource||/[\r\n]/.test(e.resource))throw TypeError("Media resource is invalid");let t=je(Buffer.from(JSON.stringify({resource:e.resource,expiresAt:V(e.expiresAt),...e.keyId?{keyId:e.keyId}:{},...e.audience?{audience:e.audience}:{}}))),r=he("sha256",e.secret).update(t).digest("base64url");return`${t}.${r}`}function ji(e,t){let[r,n,i]=e.split(".");if(!r||!n||i)return null;let d=he("sha256",t.secret).update(r).digest(),s;try{s=Buffer.from(n,"base64url")}catch{return null}if(d.length!==s.length||!Ue(d,s))return null;try{let a=JSON.parse(Buffer.from(r,"base64url").toString("utf8")),l=V(t.now??Date.now());if(!a.resource||!Number.isSafeInteger(a.expiresAt)||a.expiresAt<=l)return null;if(t.resource&&a.resource!==t.resource)return null;if(t.audience&&a.audience!==t.audience)return null;return a}catch{return null}}function Ki(e,t=!1){let r=new URL(e,"https://media.invalid").pathname.toLowerCase(),n=/\.(?:m3u8|mpd|vtt|json)$/.test(r),i=/\.(?:key|license)$/.test(r)||r.includes("/keys/")||r.includes("/licenses/");return{"Accept-Ranges":"bytes","Cache-Control":t&&(n||i)?"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 qi(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",i=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:i,compress:!0,signed:r},{pathPattern:"*.mpd",cacheControl:i,compress:!0,signed:r},{pathPattern:"*.vtt",cacheControl:i,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 Ke{builder;config;environment;mergedConfig;serverEipLogicalIds=new Map;constructor(e){this.config=e.config,this.environment=e.environment,this.builder=new be(`${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 Te(Re({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,i,d){let s=this.serverEipLogicalIds.get("app"),a=this.serverEipLogicalIds.get("appInstance");if(!s)return;let l=`EC2-${n}-${i}-api`,p=this.mergedConfig.infrastructure?.servers?.app?.region||this.mergedConfig.project?.region||"us-east-1",u=p==="us-east-1"?".compute-1.amazonaws.com":`.${p}.compute.amazonaws.com`,b={"Fn::Join":["",["ec2-",{"Fn::Join":["-",{"Fn::Split":[".",{Ref:s}]}]},u]]},C=this.resolveApiOriginPort();if(e.push({Id:l,DomainName:b,CustomOriginConfig:{HTTPPort:C,HTTPSPort:443,OriginProtocolPolicy:"http-only",OriginSSLProtocols:["TLSv1.2"]}}),r.push(s),a)r.push(a);for(let T of d)t.push(this.createComputeCacheBehavior(T,l))}buildCaddyfile(e){let t=e.filter(([,i])=>typeof i.domain==="string"&&i.domain&&typeof i.port==="number");if(t.length===0)return;let r=new Map;for(let[,i]of t){let d=r.get(i.domain)??[];d.push({port:i.port,path:i.path}),r.set(i.domain,d)}let n=[];for(let[i,d]of r){let a=[...d].sort((l,p)=>{let u=!l.path||l.path==="/",b=!p.path||p.path==="/";if(u&&!b)return 1;if(!u&&b)return-1;return(p.path?.length??0)-(l.path?.length??0)}).map((l)=>{let p=!l.path||l.path==="/",u=`reverse_proxy localhost:${l.port}`;return p?` handle {
2
2
  ${u}
3
- }`:` handle ${d.path} {
3
+ }`:` handle ${l.path} {
4
4
  ${u}
5
- }`});n.push(`${o} {
6
- ${s.join(`
5
+ }`});n.push(`${i} {
6
+ ${a.join(`
7
7
  `)}
8
8
  }`)}return n.join(`
9
9
 
10
- `)}normalizeMountPath(e){let t=e?.mountPath||e?.path;if(!t||t==="/")return;let r=`/${t}`.replace(/\/+/g,"/").replace(/\/$/,"");return r==="/"?void 0:r}storageBucketLogicalId(e,t,r){return`${e}-${t}-s3-${r}`.split(/[^a-zA-Z0-9]+/).filter(Boolean).map((n)=>n.charAt(0).toUpperCase()+n.slice(1)).join("")}pathMountRewriteFunctionCode(e,t="directory"){return`function handler(event) { var request = event.request; var prefix = ${JSON.stringify(e)}; var rewriteStyle = ${JSON.stringify(t)}; var uri = request.uri; if (uri === prefix) { uri = '/'; } else if (uri.indexOf(prefix + '/') === 0) { uri = uri.substring(prefix.length); } if (uri === '' || uri === '/') { request.uri = '/index.html'; return request; } if (uri.endsWith('/')) { request.uri = uri + 'index.html'; return request; } var lastSegment = uri.substring(uri.lastIndexOf('/') + 1); if (lastSegment.indexOf('.') === -1) { request.uri = rewriteStyle === 'flat' ? uri + '.html' : uri + '/index.html'; return request; } request.uri = uri; return request; }`}generate(){let e=this.mergedConfig.project.slug,t=this.environment,r=!!(this.mergedConfig.infrastructure?.functions&&Object.keys(this.mergedConfig.infrastructure.functions).length>0||this.mergedConfig.infrastructure?.api),n=!!(this.mergedConfig.infrastructure?.servers&&Object.keys(this.mergedConfig.infrastructure.servers).length>0),o=!!this.mergedConfig.infrastructure?.compute;if(!!((this.mergedConfig.mode||"server")==="serverless"&&this.mergedConfig.infrastructure?.containers&&Object.keys(this.mergedConfig.infrastructure.containers).length>0))this.generateNetworkInfrastructure(e,t),this.generateContainerInfrastructure(e,t);if(r)this.generateServerless(e,t);if(n)this.generateServer(e,t);if(o)this.generateComputeApp(e,t);if(this.mergedConfig.infrastructure?.jumpBox)this.generateJumpBox(e,t);if(this.generateSharedInfrastructure(e,t),this.config.tags)this.applyGlobalTags(this.config.tags);return this}applyGlobalTags(e){}generateNetworkInfrastructure(e,t){if(this.builder.hasResource("VPC"))return;let n=this.mergedConfig.infrastructure?.network?.cidr||"10.0.0.0/16",{vpc:o,logicalId:l}=Re.createVpc({slug:e,environment:t,cidr:n,enableDnsHostnames:!0,enableDnsSupport:!0});this.builder.addResource("VPC",o);let c=`${e}${t}IGW`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(c,{Type:"AWS::EC2::InternetGateway",Properties:{Tags:[{Key:"Name",Value:`${e}-${t}-igw`},{Key:"Environment",Value:t}]}});let s=`${e}${t}IGWAttach`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(s,{Type:"AWS::EC2::VPCGatewayAttachment",Properties:{VpcId:{Ref:"VPC"},InternetGatewayId:{Ref:c}}});let 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 h=this.mergedConfig.environments[t]?.region||this.mergedConfig.project.region||"us-east-1",u=["a","b"];for(let b=0;b<2;b++){let A=`PublicSubnet${b+1}`;this.builder.addResource(A,{Type:"AWS::EC2::Subnet",Properties:{VpcId:{Ref:"VPC"},CidrBlock:`10.0.${b}.0/24`,AvailabilityZone:`${h}${u[b]}`,MapPublicIpOnLaunch:!0,Tags:[{Key:"Name",Value:`${e}-${t}-public-${u[b]}`},{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],b=o.domains.slice(1).map((g)=>{if(g.includes(".")&&g.endsWith(u))return g.replace(`.${u}`,"");return g}),{certificate:A,logicalId:T}=ee.createCertificate({domain:u,subdomains:b,slug:e,environment:t,validationMethod:"DNS",hostedZoneId:l?.hostedZoneId});c=T,this.builder.addResource(T,A)}let s="ECSCluster";this.builder.addResource(s,{Type:"AWS::ECS::Cluster",Properties:{ClusterName:`${e}-${t}`,ClusterSettings:[{Name:"containerInsights",Value:"enabled"}],Tags:[{Key:"Name",Value:`${e}-${t}`},{Key:"Environment",Value:t}]}});let 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 h=`${e}${t}ECSSecurityGroup`.replace(/[^a-zA-Z0-9]/g,"");for(let[u,b]of Object.entries(r)){let A=b.port||3000;this.builder.addResource(h,{Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:`ECS tasks security group for ${e}-${t}`,VpcId:{Ref:"VPC"},SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:A,ToPort:A,SourceSecurityGroupId:{Ref: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 T=`${e}${t}TaskExecRole`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(T,{Type:"AWS::IAM::Role",Properties:{RoleName:`${e}-${t}-ecs-exec-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"],Policies:[{PolicyName:"ECRPullPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["ecr:GetAuthorizationToken","ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","logs:CreateLogStream","logs:PutLogEvents"],Resource:"*"}]}}]}});let g=`${e}${t}TaskRole`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(g,{Type:"AWS::IAM::Role",Properties:{RoleName:`${e}-${t}-ecs-task-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"TaskPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogStream","logs:PutLogEvents"],Resource:"*"},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:ListBucket"],Resource:"*"}]}}]}});let m=`${e}${t}${u}LogGroup`.replace(/[^a-zA-Z0-9]/g,""),a=`/ecs/${e}-${t}-${u}`;this.builder.addResource(m,{Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:a,RetentionInDays:30}});let y=`${e}${t}${u}TaskDef`.replace(/[^a-zA-Z0-9]/g,""),i=String(b.cpu||512),p=String(b.memory||1024);this.builder.addResource(y,{Type:"AWS::ECS::TaskDefinition",Properties:{Family:`${e}-${t}-${u}`,NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:i,Memory:p,ExecutionRoleArn:{"Fn::GetAtt":[T,"Arn"]},TaskRoleArn:{"Fn::GetAtt":[g,"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":a,"awslogs-region":{Ref:"AWS::Region"},"awslogs-stream-prefix":u}},HealthCheck:{Command:["CMD-SHELL",`curl -f http://localhost:${A}${b.healthCheck||"/health"} || exit 1`],Interval:30,Timeout:5,Retries:3,StartPeriod:60}}],Tags:[{Key:"Name",Value:`${e}-${t}-${u}`},{Key:"Environment",Value:t}]},DependsOn:[T,g,m]});let f=`${e}${t}ALB`.replace(/[^a-zA-Z0-9]/g,"");if(n?.enabled!==!1){this.builder.addResource(f,{Type:"AWS::ElasticLoadBalancingV2::LoadBalancer",Properties:{Name:`${e}-${t}-alb`,Scheme:"internet-facing",Type:"application",Subnets:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}],SecurityGroups:[{Ref:d}],Tags:[{Key:"Name",Value:`${e}-${t}-alb`},{Key:"Environment",Value:t}]}});let C=`${e}${t}TargetGroup`.replace(/[^a-zA-Z0-9]/g,""),S=n?.healthCheck?.path||b.healthCheck||"/health";this.builder.addResource(C,{Type:"AWS::ElasticLoadBalancingV2::TargetGroup",Properties:{Name:`${e}-${t}-tg`,Port:A,Protocol:"HTTP",VpcId:{Ref:"VPC"},TargetType:"ip",HealthCheckPath:S,HealthCheckIntervalSeconds:n?.healthCheck?.interval||30,HealthyThresholdCount:n?.healthCheck?.healthyThreshold||2,UnhealthyThresholdCount:n?.healthCheck?.unhealthyThreshold||5,HealthCheckTimeoutSeconds:10,Tags:[{Key:"Name",Value:`${e}-${t}-tg`},{Key:"Environment",Value:t}]}});let R=`${e}${t}HTTPListener`.replace(/[^a-zA-Z0-9]/g,"");if(o?.enabled&&o?.redirectHttp)this.builder.addResource(R,{Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:{Ref:f},Port:80,Protocol:"HTTP",DefaultActions:[{Type:"redirect",RedirectConfig:{Protocol:"HTTPS",Port:"443",StatusCode:"HTTP_301"}}]}});else this.builder.addResource(R,{Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:{Ref:f},Port:80,Protocol:"HTTP",DefaultActions:[{Type:"forward",TargetGroupArn:{Ref:C}}]}});if(o?.enabled){let v=o.certificateArn||(c?{Ref:c}:void 0);if(v){let O=`${e}${t}HTTPSListener`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(O,{Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:{Ref:f},Port:443,Protocol:"HTTPS",Certificates:[{CertificateArn:v}],DefaultActions:[{Type:"forward",TargetGroupArn:{Ref:C}}],SslPolicy:"ELBSecurityPolicy-TLS13-1-2-2021-06"}})}}let I=`${e}${t}${u}Service`.replace(/[^a-zA-Z0-9]/g,""),D=b.desiredCount||1;this.builder.addResource(I,{Type:"AWS::ECS::Service",Properties:{ServiceName:`${e}-${t}-${u}`,Cluster:{Ref:s},TaskDefinition:{Ref:y},DesiredCount:D,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{AssignPublicIp:"ENABLED",SecurityGroups:[{Ref:h}],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:[y,R,C]});let P=b.autoScaling;if(P){let v=`${e}${t}${u}ScalableTarget`.replace(/[^a-zA-Z0-9]/g,"");if(this.builder.addResource(v,{Type:"AWS::ApplicationAutoScaling::ScalableTarget",Properties:{MaxCapacity:P.max||10,MinCapacity:P.min||1,ResourceId:{"Fn::Sub":`service/\${${s}}/${e}-${t}-${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:v},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:v},TargetTrackingScalingPolicyConfiguration:{PredefinedMetricSpecification:{PredefinedMetricType:"ECSServiceAverageMemoryUtilization"},TargetValue:P.targetMemoryUtilization,ScaleInCooldown:300,ScaleOutCooldown:60}}})}if(l?.domain&&l?.hostedZoneId)this.builder.addResource(`${e}${t}ApiDnsRecord`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:l.hostedZoneId,Name:`api.${l.domain}`,Type:"A",AliasTarget:{DNSName:{"Fn::GetAtt":[f,"DNSName"]},HostedZoneId:{"Fn::GetAtt":[f,"CanonicalHostedZoneID"]}}}});this.builder.addOutput("ECSClusterArn",{Description:"ECS Cluster ARN",Value:{"Fn::GetAtt":[s,"Arn"]},Export:{Name:{"Fn::Sub":"${AWS::StackName}-ecs-cluster-arn"}}}),this.builder.addOutput("ECSServiceName",{Description:"ECS Service Name",Value:`${e}-${t}-${u}`,Export:{Name:{"Fn::Sub":"${AWS::StackName}-ecs-service-name"}}}),this.builder.addOutput("LoadBalancerDNS",{Description:"Application Load Balancer DNS Name",Value:{"Fn::GetAtt":[f,"DNSName"]},Export:{Name:{"Fn::Sub":"${AWS::StackName}-alb-dns"}}})}else{let C=`${e}${t}${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:y},DesiredCount:b.desiredCount||1,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{AssignPublicIp:"ENABLED",SecurityGroups:[{Ref:h}],Subnets:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]}},Tags:[{Key:"Name",Value:`${e}-${t}-${u}`},{Key:"Environment",Value:t}]},DependsOn:[y]})}break}}generateServerless(e,t){if(this.mergedConfig.infrastructure?.functions)for(let[r,n]of Object.entries(this.mergedConfig.infrastructure.functions)){if(!this.shouldDeploy(n))continue;let{role:o,logicalId:l}=$e.createRole({slug:e,environment:t,roleName:`${e}-${t}-${r}-role`,servicePrincipal:"lambda.amazonaws.com",managedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]});this.builder.addResource(l,o);let{lambdaFunction:c,logicalId:s}=w.createLambdaFunction({slug:e,environment:t,functionName:`${e}-${t}-${r}`,handler:n.handler||"index.handler",runtime:n.runtime||"nodejs20.x",code:{zipFile:n.code||"export const handler = async () => ({ statusCode: 200 });"},role:l,timeout:n.timeout,memorySize:n.memorySize});this.builder.addResource(s,c)}if(this.mergedConfig.infrastructure?.api){let{restApi:r,logicalId:n}=Pe.createRestApi({slug:e,environment:t,apiName:`${e}-${t}-api`});this.builder.addResource(n,r)}}generateServer(e,t){if(!this.mergedConfig.infrastructure?.servers)return;let r=this.mergedConfig.infrastructure.servers,n=this.mergedConfig.infrastructure?.compute,o=this.mergedConfig.infrastructure?.ssl;if(Object.values(r).some((c)=>!c.privateNetwork||c.privateNetwork==="create"))this.generateNetworkInfrastructure(e,t);for(let[c,s]of Object.entries(r)){let d=s.instanceType||s.size||n?.size,u=(d?w.InstanceSize.specs[d]:void 0)?.instanceType||d||"t3.micro",b=s.type||"app",A=s.userData||s.startupScript;if(!A)A=w.UserData.generateAppServerScript({runtime:"bun",runtimeVersion:s.bunVersion||"latest",webServer:"none",domain:s.domain,enableSsl:!!o?.enabled,sslEmail:o?.letsEncrypt?.email,installRedis:b==="cache",installDatabaseClients:!!s.database});let T=s.privateNetwork&&s.privateNetwork!=="create"?s.privateNetwork:{Ref:"VPC"},g=s.subnet||{Ref:"PublicSubnet1"},a=!!this.mergedConfig.infrastructure?.email?.server?.enabled,y=[22,80,443,this.resolveApiOriginPort()];if(a)y.push(25,465,587,143,993);let i=w.createServerModeStack({slug:`${e}-${c}`,environment:t,vpcId:T,subnetId:g,instanceType:u,keyName:s.keyName||`${e}-${t}`,domain:s.domain,userData:A,volumeSize:s.diskSize||20,imageId:s.image,allowedPorts:y});for(let[p,f]of Object.entries(i.resources))this.builder.addResource(p,f);this.serverEipLogicalIds.set(c,i.outputs.eipLogicalId),this.serverEipLogicalIds.set(`${c}Instance`,i.outputs.instanceLogicalId),this.builder.addOutput(`${c}InstanceId`,{Value:{Ref:i.outputs.instanceLogicalId},Description:`Instance ID for ${c} server`}),this.builder.addOutput(`${c}PublicIp`,{Value:{Ref:i.outputs.eipLogicalId},Description:`Public IP for ${c} server`})}}generateComputeApp(e,t){let r=this.mergedConfig.infrastructure?.compute;if(!r)return;let n=this.mergedConfig.sites||{},o=Object.entries(n),c=this.mergedConfig.infrastructure?.dns?.domain,s=this.mergedConfig.infrastructure?.database,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 b=this.buildCaddyfile(o),A=w.UserData.generateBunAppScript({runtime:r.runtime||"bun",runtimeVersion:r.runtimeVersion||"latest",systemPackages:r.systemPackages,database:s,caddyfile:b}),T=Ee(r.appUpdates),g=T.length>0?`${A}
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),i=!!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(i)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:i,logicalId:d}=Pe.createVpc({slug:e,environment:t,cidr:n,enableDnsHostnames:!0,enableDnsSupport:!0});this.builder.addResource("VPC",i);let s=`${e}${t}IGW`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(s,{Type:"AWS::EC2::InternetGateway",Properties:{Tags:[{Key:"Name",Value:`${e}-${t}-igw`},{Key:"Environment",Value:t}]}});let a=`${e}${t}IGWAttach`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(a,{Type:"AWS::EC2::VPCGatewayAttachment",Properties:{VpcId:{Ref:"VPC"},InternetGatewayId:{Ref:s}}});let l=`${e}${t}PublicRT`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(l,{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:l},DestinationCidrBlock:"0.0.0.0/0",GatewayId:{Ref:s}},DependsOn:a});let p=this.mergedConfig.environments[t]?.region||this.mergedConfig.project.region||"us-east-1",u=["a","b"];for(let b=0;b<2;b++){let C=`PublicSubnet${b+1}`;this.builder.addResource(C,{Type:"AWS::EC2::Subnet",Properties:{VpcId:{Ref:"VPC"},CidrBlock:`10.0.${b}.0/24`,AvailabilityZone:`${p}${u[b]}`,MapPublicIpOnLaunch:!0,Tags:[{Key:"Name",Value:`${e}-${t}-public-${u[b]}`},{Key:"Environment",Value:t}]}}),this.builder.addResource(`${C}RTAssoc`,{Type:"AWS::EC2::SubnetRouteTableAssociation",Properties:{SubnetId:{Ref:C},RouteTableId:{Ref:l}}})}}generateContainerInfrastructure(e,t){let r=this.mergedConfig.infrastructure?.containers;if(!r)return;let n=this.mergedConfig.infrastructure?.loadBalancer,i=this.mergedConfig.infrastructure?.ssl,d=this.mergedConfig.infrastructure?.dns,s;if(i?.enabled&&i.domains?.length)if(i.certificateArn);else{let u=i.domains[0],b=i.domains.slice(1).map((g)=>{if(g.includes(".")&&g.endsWith(u))return g.replace(`.${u}`,"");return g}),{certificate:C,logicalId:T}=re.createCertificate({domain:u,subdomains:b,slug:e,environment:t,validationMethod:"DNS",hostedZoneId:d?.hostedZoneId});s=T,this.builder.addResource(T,C)}let a="ECSCluster";this.builder.addResource(a,{Type:"AWS::ECS::Cluster",Properties:{ClusterName:`${e}-${t}`,ClusterSettings:[{Name:"containerInsights",Value:"enabled"}],Tags:[{Key:"Name",Value:`${e}-${t}`},{Key:"Environment",Value:t}]}});let l=`${e}${t}ALBSecurityGroup`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(l,{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 p=`${e}${t}ECSSecurityGroup`.replace(/[^a-zA-Z0-9]/g,"");for(let[u,b]of Object.entries(r)){let C=b.port||3000;this.builder.addResource(p,{Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:`ECS tasks security group for ${e}-${t}`,VpcId:{Ref:"VPC"},SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:C,ToPort:C,SourceSecurityGroupId:{Ref:l},Description:"Allow traffic from ALB"}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound"}],Tags:[{Key:"Name",Value:`${e}-${t}-ecs-sg`},{Key:"Environment",Value:t}]}});let T=`${e}${t}TaskExecRole`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(T,{Type:"AWS::IAM::Role",Properties:{RoleName:`${e}-${t}-ecs-exec-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"],Policies:[{PolicyName:"ECRPullPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["ecr:GetAuthorizationToken","ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","logs:CreateLogStream","logs:PutLogEvents"],Resource:"*"}]}}]}});let g=`${e}${t}TaskRole`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(g,{Type:"AWS::IAM::Role",Properties:{RoleName:`${e}-${t}-ecs-task-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"TaskPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogStream","logs:PutLogEvents"],Resource:"*"},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:ListBucket"],Resource:"*"}]}}]}});let m=`${e}${t}${u}LogGroup`.replace(/[^a-zA-Z0-9]/g,""),c=`/ecs/${e}-${t}-${u}`;this.builder.addResource(m,{Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:c,RetentionInDays:30}});let y=`${e}${t}${u}TaskDef`.replace(/[^a-zA-Z0-9]/g,""),o=String(b.cpu||512),f=String(b.memory||1024);this.builder.addResource(y,{Type:"AWS::ECS::TaskDefinition",Properties:{Family:`${e}-${t}-${u}`,NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:o,Memory:f,ExecutionRoleArn:{"Fn::GetAtt":[T,"Arn"]},TaskRoleArn:{"Fn::GetAtt":[g,"Arn"]},ContainerDefinitions:[{Name:u,Image:{"Fn::Sub":`\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.amazonaws.com/${e}:latest`},Essential:!0,PortMappings:[{ContainerPort:C,Protocol:"tcp"}],LogConfiguration:{LogDriver:"awslogs",Options:{"awslogs-group":c,"awslogs-region":{Ref:"AWS::Region"},"awslogs-stream-prefix":u}},HealthCheck:{Command:["CMD-SHELL",`curl -f http://localhost:${C}${b.healthCheck||"/health"} || exit 1`],Interval:30,Timeout:5,Retries:3,StartPeriod:60}}],Tags:[{Key:"Name",Value:`${e}-${t}-${u}`},{Key:"Environment",Value:t}]},DependsOn:[T,g,m]});let h=`${e}${t}ALB`.replace(/[^a-zA-Z0-9]/g,"");if(n?.enabled!==!1){this.builder.addResource(h,{Type:"AWS::ElasticLoadBalancingV2::LoadBalancer",Properties:{Name:`${e}-${t}-alb`,Scheme:"internet-facing",Type:"application",Subnets:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}],SecurityGroups:[{Ref:l}],Tags:[{Key:"Name",Value:`${e}-${t}-alb`},{Key:"Environment",Value:t}]}});let S=`${e}${t}TargetGroup`.replace(/[^a-zA-Z0-9]/g,""),A=n?.healthCheck?.path||b.healthCheck||"/health";this.builder.addResource(S,{Type:"AWS::ElasticLoadBalancingV2::TargetGroup",Properties:{Name:`${e}-${t}-tg`,Port:C,Protocol:"HTTP",VpcId:{Ref:"VPC"},TargetType:"ip",HealthCheckPath:A,HealthCheckIntervalSeconds:n?.healthCheck?.interval||30,HealthyThresholdCount:n?.healthCheck?.healthyThreshold||2,UnhealthyThresholdCount:n?.healthCheck?.unhealthyThreshold||5,HealthCheckTimeoutSeconds:10,Tags:[{Key:"Name",Value:`${e}-${t}-tg`},{Key:"Environment",Value:t}]}});let R=`${e}${t}HTTPListener`.replace(/[^a-zA-Z0-9]/g,"");if(i?.enabled&&i?.redirectHttp)this.builder.addResource(R,{Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:{Ref:h},Port:80,Protocol:"HTTP",DefaultActions:[{Type:"redirect",RedirectConfig:{Protocol:"HTTPS",Port:"443",StatusCode:"HTTP_301"}}]}});else this.builder.addResource(R,{Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:{Ref:h},Port:80,Protocol:"HTTP",DefaultActions:[{Type:"forward",TargetGroupArn:{Ref:S}}]}});if(i?.enabled){let v=i.certificateArn||(s?{Ref:s}:void 0);if(v){let O=`${e}${t}HTTPSListener`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(O,{Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:{Ref:h},Port:443,Protocol:"HTTPS",Certificates:[{CertificateArn:v}],DefaultActions:[{Type:"forward",TargetGroupArn:{Ref:S}}],SslPolicy:"ELBSecurityPolicy-TLS13-1-2-2021-06"}})}}let D=`${e}${t}${u}Service`.replace(/[^a-zA-Z0-9]/g,""),I=b.desiredCount||1;this.builder.addResource(D,{Type:"AWS::ECS::Service",Properties:{ServiceName:`${e}-${t}-${u}`,Cluster:{Ref:a},TaskDefinition:{Ref:y},DesiredCount:I,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{AssignPublicIp:"ENABLED",SecurityGroups:[{Ref:p}],Subnets:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]}},LoadBalancers:[{ContainerName:u,ContainerPort:C,TargetGroupArn:{Ref:S}}],HealthCheckGracePeriodSeconds:120,Tags:[{Key:"Name",Value:`${e}-${t}-${u}`},{Key:"Environment",Value:t}]},DependsOn:[y,R,S]});let P=b.autoScaling;if(P){let v=`${e}${t}${u}ScalableTarget`.replace(/[^a-zA-Z0-9]/g,"");if(this.builder.addResource(v,{Type:"AWS::ApplicationAutoScaling::ScalableTarget",Properties:{MaxCapacity:P.max||10,MinCapacity:P.min||1,ResourceId:{"Fn::Sub":`service/\${${a}}/${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:D}),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:v},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:v},TargetTrackingScalingPolicyConfiguration:{PredefinedMetricSpecification:{PredefinedMetricType:"ECSServiceAverageMemoryUtilization"},TargetValue:P.targetMemoryUtilization,ScaleInCooldown:300,ScaleOutCooldown:60}}})}if(d?.domain&&d?.hostedZoneId)this.builder.addResource(`${e}${t}ApiDnsRecord`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:d.hostedZoneId,Name:`api.${d.domain}`,Type:"A",AliasTarget:{DNSName:{"Fn::GetAtt":[h,"DNSName"]},HostedZoneId:{"Fn::GetAtt":[h,"CanonicalHostedZoneID"]}}}});this.builder.addOutput("ECSClusterArn",{Description:"ECS Cluster ARN",Value:{"Fn::GetAtt":[a,"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":[h,"DNSName"]},Export:{Name:{"Fn::Sub":"${AWS::StackName}-alb-dns"}}})}else{let S=`${e}${t}${u}Service`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(S,{Type:"AWS::ECS::Service",Properties:{ServiceName:`${e}-${t}-${u}`,Cluster:{Ref:a},TaskDefinition:{Ref:y},DesiredCount:b.desiredCount||1,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{AssignPublicIp:"ENABLED",SecurityGroups:[{Ref:p}],Subnets:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]}},Tags:[{Key:"Name",Value:`${e}-${t}-${u}`},{Key:"Environment",Value:t}]},DependsOn:[y]})}break}}generateServerless(e,t){if(this.mergedConfig.infrastructure?.functions)for(let[r,n]of Object.entries(this.mergedConfig.infrastructure.functions)){if(!this.shouldDeploy(n))continue;let{role:i,logicalId:d}=De.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(d,i);let{lambdaFunction:s,logicalId:a}=E.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:d,timeout:n.timeout,memorySize:n.memorySize});this.builder.addResource(a,s)}if(this.mergedConfig.infrastructure?.api){let{restApi:r,logicalId:n}=Ie.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,i=this.mergedConfig.infrastructure?.ssl;if(Object.values(r).some((s)=>!s.privateNetwork||s.privateNetwork==="create"))this.generateNetworkInfrastructure(e,t);for(let[s,a]of Object.entries(r)){let l=a.instanceType||a.size||n?.size,u=(l?E.InstanceSize.specs[l]:void 0)?.instanceType||l||"t3.micro",b=a.type||"app",C=a.userData||a.startupScript;if(!C)C=E.UserData.generateAppServerScript({runtime:"bun",runtimeVersion:a.bunVersion||"latest",webServer:"none",domain:a.domain,enableSsl:!!i?.enabled,sslEmail:i?.letsEncrypt?.email,installRedis:b==="cache",installDatabaseClients:!!a.database});let T=a.privateNetwork&&a.privateNetwork!=="create"?a.privateNetwork:{Ref:"VPC"},g=a.subnet||{Ref:"PublicSubnet1"},c=!!this.mergedConfig.infrastructure?.email?.server?.enabled,y=[22,80,443,this.resolveApiOriginPort()];if(c)y.push(25,465,587,143,993);let o=E.createServerModeStack({slug:`${e}-${s}`,environment:t,vpcId:T,subnetId:g,instanceType:u,keyName:a.keyName||`${e}-${t}`,domain:a.domain,userData:C,volumeSize:a.diskSize||20,imageId:a.image,allowedPorts:y});for(let[f,h]of Object.entries(o.resources))this.builder.addResource(f,h);this.serverEipLogicalIds.set(s,o.outputs.eipLogicalId),this.serverEipLogicalIds.set(`${s}Instance`,o.outputs.instanceLogicalId),this.builder.addOutput(`${s}InstanceId`,{Value:{Ref:o.outputs.instanceLogicalId},Description:`Instance ID for ${s} server`}),this.builder.addOutput(`${s}PublicIp`,{Value:{Ref:o.outputs.eipLogicalId},Description:`Public IP for ${s} server`})}}generateComputeApp(e,t){let r=this.mergedConfig.infrastructure?.compute;if(!r)return;let n=this.mergedConfig.sites||{},i=Object.entries(n),s=this.mergedConfig.infrastructure?.dns?.domain,a=this.mergedConfig.infrastructure?.database,l=r.size,u=(l?E.InstanceSize.specs[l]:void 0)?.instanceType||l||"t3.micro";if(!this.builder.hasResource("VPC"))this.generateNetworkInfrastructure(e,t);let b=this.buildCaddyfile(i),C=E.UserData.generateBunAppScript({runtime:r.runtime||"bun",runtimeVersion:r.runtimeVersion||"latest",systemPackages:r.systemPackages,database:a,caddyfile:b}),T=ve(r.appUpdates),g=T.length>0?`${C}
11
11
  ${T.join(`
12
12
  `)}
13
- `:A,m=o.map(([,S])=>S.port).filter((S)=>typeof S==="number"&&![80,443].includes(S)),a=this.resolveApiOriginPort(),y=`${e}${t}DeployBucket`.replace(/[^a-zA-Z0-9]/g,""),i=`${e}-${t}-deploy`;this.builder.addResource(y,{Type:"AWS::S3::Bucket",Properties:{BucketName:i,PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},LifecycleConfiguration:{Rules:[{Id:"expire-old-releases",Status:"Enabled",ExpirationInDays:7,Prefix:"releases/"}]},Tags:[{Key:"Project",Value:e},{Key:"Environment",Value:t},{Key:"ManagedBy",Value:"ts-cloud"}]}});let p=w.createServerModeStack({slug:`${e}-app`,environment:t,vpcId:{Ref:"VPC"},subnetId:{Ref:"PublicSubnet1"},instanceType:u,keyName:r.allowSsh?`${e}-${t}`:void 0,domain:c,userData:g,volumeSize:r.disk?.size||20,imageId:r.image,allowedPorts:[...r.allowSsh?[22]:[],80,443,a,...m]}),f=p.resources[p.outputs.instanceLogicalId];if(f?.Properties){let S=f.Properties.Tags||[];f.Properties.Tags=[...S,{Key:"Project",Value:e},{Key:"Environment",Value:t},{Key:"Role",Value:"app"},{Key:"ManagedBy",Value:"ts-cloud"}]}let C=p.resources[p.outputs.roleLogicalId];if(C?.Properties)C.Properties.Policies=C.Properties.Policies||[],C.Properties.Policies.push({PolicyName:"DeployBucketRead",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["s3:GetObject","s3:ListBucket"],Resource:[`arn:aws:s3:::${i}`,`arn:aws:s3:::${i}/*`]}]}});for(let[S,R]of Object.entries(p.resources))this.builder.addResource(S,R);this.builder.addOutput("deployBucketName",{Value:{Ref:y},Description:"S3 bucket where release tarballs are uploaded"}),this.builder.addOutput("appInstanceId",{Value:{Ref:p.outputs.instanceLogicalId},Description:"EC2 instance ID for the app server"}),this.builder.addOutput("appPublicIp",{Value:{Ref:p.outputs.eipLogicalId},Description:"Public IP for the app server"}),this.serverEipLogicalIds.set("app",p.outputs.eipLogicalId),this.serverEipLogicalIds.set("appInstance",p.outputs.instanceLogicalId)}generateJumpBox(e,t){let r=this.mergedConfig.infrastructure?.jumpBox;if(!r)return;let n=r===!0?{}:r;if(n.enabled===!1)return;this.generateNetworkInfrastructure(e,t);let o=n.size||"micro",c=w.InstanceSize.specs[o]?.instanceType||o||"t3.micro",s;if(n.mountEfs)s={fileSystemId:typeof n.mountEfs==="string"?n.mountEfs:{Ref:"FileSystem"},mountPath:n.mountPath||"/mnt/efs"};let 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[h,u]of Object.entries(d.resources))this.builder.addResource(h,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 m=r.domains||[o],a=m[0],y=m.slice(1).map((f)=>{if(f.includes(".")&&f.endsWith(a))return f.replace(`.${a}`,"");return f}),{certificate:i,logicalId:p}=ee.createCertificate({domain:a,subdomains:y,slug:e,environment:t,validationMethod:"DNS",hostedZoneId:l});s=p,this.builder.addResource(p,i)}if(this.mergedConfig.infrastructure?.storage){let m=Object.entries(this.mergedConfig.infrastructure.storage).some(([,i])=>i.website),a;if(m&&(s||d))a=`${e}${t}CloudFrontOAC`.replace(/[^a-zA-Z0-9]/g,""),this.builder.addResource(a,{Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${e}-${t}-s3-oac`,Description:`OAC for ${e} ${t} S3 website buckets`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}});let y=Object.entries(this.mergedConfig.infrastructure.storage).map(([i,p])=>({name:i,config:p,mountPath:this.normalizeMountPath(p),rewriteStyle:p.pathRewriteStyle||"directory",logicalId:this.storageBucketLogicalId(e,t,i)})).filter((i)=>i.name!=="public"&&i.config.website&&i.mountPath);for(let[i,p]of Object.entries(this.mergedConfig.infrastructure.storage)){let f=!!(p.website&&a),C=this.storageBucketName(e,t,i),{bucket:S,logicalId:R}=X.createBucket({slug:e,name:i,environment:t,bucketName:C,versioning:p.versioning,encryption:p.encryption,public:f?!1:p.public});if(f&&S.Properties)S.Properties.PublicAccessBlockConfiguration={BlockPublicAcls:!0,IgnorePublicAcls:!0,BlockPublicPolicy:!1,RestrictPublicBuckets:!1};if(this.builder.addResource(R,S),p.website){let D=typeof p.website==="object"?p.website:{},P=X.enableWebsiteHosting(S,D.indexDocument||"index.html",D.errorDocument);this.builder.addResource(R,P)}let I=this.normalizeMountPath(p);if(f&&a&&o&&!(I&&i!=="public")){let D=`${e}${t}${i}CDN`.replace(/[^a-zA-Z0-9]/g,""),P=[];if(p.aliases&&p.aliases.length>0)P.push(...p.aliases);else if(i==="public"){if(P.push(o),r?.domains?.includes(`www.${o}`))P.push(`www.${o}`)}else if(i==="docs")P.push(`docs.${o}`);else if(i==="blog")P.push(`blog.${o}`);let v=typeof p.website==="object"?p.website:{},O=p.spa===!0,F=v.errorDocument||(O?"index.html":"404.html"),V=[];if(O)V.push({ErrorCode:403,ResponseCode:200,ResponsePagePath:"/index.html",ErrorCachingMinTTL:300},{ErrorCode:404,ResponseCode:200,ResponsePagePath:"/index.html",ErrorCachingMinTTL:300});else V.push({ErrorCode:403,ResponseCode:404,ResponsePagePath:`/${F}`,ErrorCachingMinTTL:300},{ErrorCode:404,ResponseCode:404,ResponsePagePath:`/${F}`,ErrorCachingMinTTL:300});let z=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}-${i}`,k=this.mergedConfig.project.region||"us-east-1",x;if(!O)x=`${e}${t}${i}UrlRewrite`.replace(/[^a-zA-Z0-9]/g,""),this.builder.addResource(x,{Type:"AWS::CloudFront::Function",Properties:{Name:`${e}-${t}-${i}-url-rewrite`,AutoPublish:!0,FunctionConfig:{Comment:`URL rewrite for ${e} ${t} ${i} - appends .html to extensionless paths`,Runtime:"cloudfront-js-2.0"},FunctionCode:`function handler(event) { var request = event.request; var uri = request.uri; if (uri.endsWith('/')) { request.uri += 'index.html'; }
14
- else if (!uri.includes('.')) { request.uri += '.html'; } return request; }`}});let J=[{Id:_,DomainName:{"Fn::Sub":`\${${R}}.s3.${k}.amazonaws.com`},OriginPath:"",S3OriginConfig:{OriginAccessIdentity:""},OriginAccessControlId:{Ref:a}}],H=[],Y=[];if(this.shouldRouteStorageBucketToCompute(i,p)){this.appendComputeAppOrigin(J,H,Y,e,t,this.resolveComputeCachePathPatterns(p.computeRoutes));for(let E of y){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.${k}.amazonaws.com`},OriginPath:"",S3OriginConfig:{OriginAccessIdentity:""},OriginAccessControlId:{Ref:a}}),Y.push(E.logicalId,Q);for(let Ve of[E.mountPath,`${E.mountPath}/*`])H.push({PathPattern:Ve,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:[R,a,...x?[x]:[],...Y],Properties:{DistributionConfig:{Enabled:!0,Comment:`${e} ${t} ${i} 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 Fe=`${R}CloudFrontPolicy`;if(this.builder.addResource(Fe,{Type:"AWS::S3::BucketPolicy",DependsOn:[R,D],Properties:{Bucket:{Ref:R},PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowCloudFrontServicePrincipal",Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:{"Fn::Sub":`arn:aws:s3:::\${${R}}/*`},Condition:{StringEquals:{"AWS:SourceArn":{"Fn::Sub":`arn:aws:cloudfront::\${AWS::AccountId}:distribution/\${${D}}`}}}}]}}}),this.shouldRouteStorageBucketToCompute(i,p))for(let E of y){let 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:i,bucketLogicalId:R,distLogicalId:D,oacLogicalId:a,aliases:P});this.builder.addOutput(`${i}CloudFrontDomain`,{Value:{"Fn::GetAtt":[D,"DomainName"]},Description:`CloudFront domain for ${i}`}),this.builder.addOutput(`${i}CloudFrontDistributionId`,{Value:{Ref:D},Description:`CloudFront distribution ID for ${i}`})}if(this.builder.addOutput(`${i}BucketName`,{Value:{Ref:R},Description:`S3 bucket name for ${i}`}),i==="public")this.builder.addOutput("FrontendBucketName",{Value:{Ref:R},Description:"Frontend S3 bucket name"});if(i==="docs")this.builder.addOutput("DocsBucketName",{Value:{Ref:R},Description:"Documentation S3 bucket name"});if(i==="blog")this.builder.addOutput("BlogBucketName",{Value:{Ref:R},Description:"Blog S3 bucket name"})}}if(this.mergedConfig.infrastructure?.sftp){let m=this.mergedConfig.infrastructure.sftp,a=Te.create({...m,storage:this.resolveSftpStorage(m,e,t)??m.storage,slug:e,environment:t});for(let[y,i]of Object.entries(a.resources))this.builder.addResource(y,i);this.builder.addOutput("SftpServerId",{Value:{Ref:a.serverLogicalId},Description:"AWS Transfer Family SFTP server ID"}),this.builder.addOutput("SftpEndpoint",{Value:{"Fn::Sub":`\${${a.serverLogicalId}}.server.transfer.\${AWS::Region}.amazonaws.com`},Description:"AWS Transfer Family SFTP endpoint"}),this.builder.addOutput("SftpStorageDomain",{Value:a.domain,Description:"Storage backing the SFTP server (EFS or S3)"})}if(l&&c.length>0)for(let{name:m,distLogicalId:a,aliases:y}of c)for(let i of y){let p=i.replace(/\./g,"").replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(`${p}ARecord`,{Type:"AWS::Route53::RecordSet",DependsOn:[a],Properties:{HostedZoneId:l,Name:i,Type:"A",AliasTarget:{DNSName:{"Fn::GetAtt":[a,"DomainName"]},HostedZoneId:"Z2FDTNDATAQYW2",EvaluateTargetHealth:!1}}}),this.builder.addResource(`${p}AAAARecord`,{Type:"AWS::Route53::RecordSet",DependsOn:[a],Properties:{HostedZoneId:l,Name:i,Type:"AAAA",AliasTarget:{DNSName:{"Fn::GetAtt":[a,"DomainName"]},HostedZoneId:"Z2FDTNDATAQYW2",EvaluateTargetHealth:!1}}})}if(this.mergedConfig.infrastructure?.databases){for(let[m,a]of Object.entries(this.mergedConfig.infrastructure.databases))if(a.engine==="dynamodb"){let{table:y,logicalId:i}=U.createTable({slug:e,environment:t,tableName:`${e}-${t}-${m}`,partitionKey:a.partitionKey||{name:"id",type:"S"},sortKey:a.sortKey});this.builder.addResource(i,y)}else if(a.engine==="postgres"){let{dbInstance:y,logicalId:i}=U.createPostgres({slug:e,environment:t,dbInstanceIdentifier:`${e}-${t}-${m}`,masterUsername:a.username||"admin",masterUserPassword:a.password||"changeme123",allocatedStorage:a.storage||20,dbInstanceClass:a.instanceClass||"db.t3.micro"});this.builder.addResource(i,y)}else if(a.engine==="mysql"){let{dbInstance:y,logicalId:i}=U.createMysql({slug:e,environment:t,dbInstanceIdentifier:`${e}-${t}-${m}`,masterUsername:a.username||"admin",masterUserPassword:a.password||"changeme123",allocatedStorage:a.storage||20,dbInstanceClass:a.instanceClass||"db.t3.micro"});this.builder.addResource(i,y)}}if(this.mergedConfig.infrastructure?.cdn)for(let[m,a]of Object.entries(this.mergedConfig.infrastructure.cdn)){if(!a.origin)continue;let y=typeof a.customDomain==="string"?a.customDomain:a.customDomain?.domain||a.domain,i=typeof a.customDomain==="object"?a.customDomain?.certificateArn:a.certificateArn,p=i||d,f=`${e}${t}${m}CDN`.replace(/[^a-zA-Z0-9]/g,""),C=`S3-${e}-${t}-${m}-cdn`,S=[{Id:C,DomainName:a.origin,OriginPath:"",S3OriginConfig:{OriginAccessIdentity:""},OriginShield:a.originShield?{Enabled:!0,OriginShieldRegion:a.originShieldRegion||this.mergedConfig.environments[t]?.region||this.mergedConfig.project.region||"us-east-1"}:{Enabled:!1}}],R=[],I=[];if(a.routeCompute)this.appendComputeAppOrigin(S,R,I,e,t,this.resolveComputeCachePathPatterns(a.computeRoutes));let D=p&&y?{AcmCertificateArn:s&&!i?{Ref:s}:p,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}:{CloudFrontDefaultCertificate:!0},P=[...I];if(s&&!i&&y)P.push(s);let v={Type:"AWS::CloudFront::Distribution",...P.length>0?{DependsOn:P}:{},Properties:{DistributionConfig:{Enabled:!0,Comment:`${e} ${t} ${m} CDN`,DefaultRootObject:"index.html",Origins:S,DefaultCacheBehavior:{TargetOriginId:C,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:a.compress!==!1,CachePolicyId:"658327ea-f89d-4fab-a63d-7e88639e58f6"},...R.length>0?{CacheBehaviors:R}:{},...y&&p?{Aliases:[y]}:{},ViewerCertificate:D,PriceClass:"PriceClass_100",HttpVersion:a.http3?"http2and3":"http2"}}};if(this.builder.addResource(f,v),l&&y&&p){let O=y.replace(/\./g,"").replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(`${O}CdnARecord`,{Type:"AWS::Route53::RecordSet",DependsOn:[f,...s&&!i?[s]:[]],Properties:{HostedZoneId:l,Name:y,Type:"A",AliasTarget:{HostedZoneId:"Z2FDTNDATAQYW2",DNSName:{"Fn::GetAtt":[f,"DomainName"]}}}})}}if(this.mergedConfig.infrastructure?.queues)for(let[m,a]of Object.entries(this.mergedConfig.infrastructure.queues)){if(!this.shouldDeploy(a))continue;let{queue:y,logicalId:i}=te.createQueue({slug:e,environment:t,name:`${e}-${t}-${m}`,fifo:a.fifo,visibilityTimeout:a.visibilityTimeout,messageRetentionPeriod:a.messageRetentionPeriod,delaySeconds:a.delaySeconds,maxMessageSize:a.maxMessageSize,receiveMessageWaitTime:a.receiveMessageWaitTime,contentBasedDeduplication:a.contentBasedDeduplication,encrypted:a.encrypted,kmsKeyId:a.kmsKeyId});this.builder.addResource(i,y);let p;if(a.deadLetterQueue){let{deadLetterQueue:f,updatedSourceQueue:C,deadLetterLogicalId:S}=te.createDeadLetterQueue(i,{slug:e,environment:t,maxReceiveCount:a.maxReceiveCount});p=S,this.builder.addResource(S,f);let I=this.builder.getResources()[i];if(I?.Properties)I.Properties.RedrivePolicy=C.Properties?.RedrivePolicy}if(a.trigger){let f=a.trigger,C=`${e}${t}${f.functionName}`.replace(/[^a-zA-Z0-9]/g,""),S={Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:{"Fn::GetAtt":[i,"Arn"]},FunctionName:{Ref:C},BatchSize:f.batchSize||10,MaximumBatchingWindowInSeconds:f.batchWindow||0,Enabled:!0,...f.reportBatchItemFailures!==!1&&{FunctionResponseTypes:["ReportBatchItemFailures"]},...f.maxConcurrency&&{ScalingConfig:{MaximumConcurrency:f.maxConcurrency}},...f.filterPattern&&{FilterCriteria:{Filters:[{Pattern:JSON.stringify(f.filterPattern)}]}}},DependsOn:[i,C]};this.builder.addResource(`${i}Trigger`,S)}if(a.alarms?.enabled){let f=a.alarms,C=f.notificationTopicArn;if(!C&&f.notificationEmails?.length){let I=`${i}AlarmTopic`;this.builder.addResource(I,{Type:"AWS::SNS::Topic",Properties:{TopicName:`${e}-${t}-${m}-alarms`,DisplayName:`${m} Queue Alarms`}}),f.notificationEmails.forEach((D,P)=>{this.builder.addResource(`${I}Sub${P}`,{Type:"AWS::SNS::Subscription",Properties:{TopicArn:{Ref:I},Protocol:"email",Endpoint:D}})}),C={Ref:I}}let S=f.queueDepthThreshold||1000;this.builder.addResource(`${i}DepthAlarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${e}-${t}-${m}-queue-depth`,AlarmDescription:`Queue ${m} depth exceeds ${S} messages`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Average",Period:300,EvaluationPeriods:2,Threshold:S,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:{"Fn::GetAtt":[i,"QueueName"]}}],...C&&{AlarmActions:[C],OKActions:[C]}}});let R=f.messageAgeThreshold||3600;if(this.builder.addResource(`${i}AgeAlarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${e}-${t}-${m}-message-age`,AlarmDescription:`Queue ${m} oldest message exceeds ${R} seconds`,MetricName:"ApproximateAgeOfOldestMessage",Namespace:"AWS/SQS",Statistic:"Maximum",Period:300,EvaluationPeriods:2,Threshold:R,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:{"Fn::GetAtt":[i,"QueueName"]}}],...C&&{AlarmActions:[C],OKActions:[C]}}}),p&&f.dlqAlarm!==!1)this.builder.addResource(`${p}Alarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${e}-${t}-${m}-dlq-messages`,AlarmDescription:`Dead letter queue for ${m} has messages`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Sum",Period:300,EvaluationPeriods:1,Threshold:0,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:{"Fn::GetAtt":[p,"QueueName"]}}],...C&&{AlarmActions:[C]}}})}if(a.subscribe){let f=a.subscribe,C=f.topicArn;if(!C&&f.topicName)C={Ref:f.topicName};if(C){this.builder.addResource(`${i}SnsPolicy`,{Type:"AWS::SQS::QueuePolicy",Properties:{Queues:[{Ref:i}],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"sns.amazonaws.com"},Action:"sqs:SendMessage",Resource:{"Fn::GetAtt":[i,"Arn"]},Condition:{ArnEquals:{"aws:SourceArn":C}}}]}}});let S={TopicArn:C,Protocol:"sqs",Endpoint:{"Fn::GetAtt":[i,"Arn"]},RawMessageDelivery:f.rawMessageDelivery||!1};if(f.filterPolicy)S.FilterPolicy=f.filterPolicy,S.FilterPolicyScope=f.filterPolicyScope||"MessageAttributes";this.builder.addResource(`${i}SnsSub`,{Type:"AWS::SNS::Subscription",Properties:S,DependsOn:`${i}SnsPolicy`})}}}if(this.mergedConfig.infrastructure?.realtime?.enabled)if((this.mergedConfig.infrastructure.realtime.mode||"serverless")==="server")this.generateRealtimeServerResources(e,t);else this.generateRealtimeResources(e,t);let h=this.mergedConfig.infrastructure?.redirects;if(h){let m=h.target||this.mergedConfig.infrastructure?.dns?.domain||"",a=h.protocol||"https";if(h.domains?.length&&m)for(let y of h.domains){let{bucket:i,bucketPolicy:p,logicalId:f,policyLogicalId:C}=Z.createDomainRedirectBucket({slug:e,environment:t,sourceDomain:y,targetDomain:m,protocol:a});this.builder.addResource(f,i),this.builder.addResource(C,p)}if(h.paths&&Object.keys(h.paths).length>0){let y=Z.fromMapping(h.paths,{statusCode:h.statusCode||301}),{function:i,logicalId:p}=Z.createPathRedirectFunction({slug:e,environment:t,rules:y});this.builder.addResource(p,i)}}if(this.mergedConfig.infrastructure?.monitoring?.alarms)for(let[m,a]of Object.entries(this.mergedConfig.infrastructure.monitoring.alarms)){let{alarm:y,logicalId:i}=Ie.createAlarm({slug:e,environment:t,alarmName:`${e}-${t}-${m}`,metricName:a.metricName||"Errors",namespace:a.namespace||"AWS/Lambda",threshold:a.threshold||1,comparisonOperator:a.comparisonOperator||"GreaterThanThreshold"});this.builder.addResource(i,y)}let u=this.mergedConfig.infrastructure?.cache;if(u){let m=u.type||"redis";if(m==="redis"){this.generateNetworkInfrastructure(e,t);let a=u.redis||{},{replicationGroup:y,subnetGroup:i,logicalId:p,subnetGroupId:f}=re.createRedis({slug:e,environment:t,nodeType:a.nodeType||u.nodeType||"cache.t3.micro",engineVersion:a.engineVersion||"7.1",port:a.port||6379,numCacheClusters:a.numCacheNodes||2,automaticFailover:a.automaticFailoverEnabled!==!1,atRestEncryption:!0,transitEncryption:!0,snapshotRetentionDays:a.snapshotRetentionLimit||7,snapshotWindow:a.snapshotWindow,subnetIds:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]});if(this.builder.addResource(p,y),i&&f)this.builder.addResource(f,i);this.builder.addOutput("CacheEndpoint",{Value:{"Fn::GetAtt":[p,"PrimaryEndPoint.Address"]},Description:"Redis primary endpoint address"}),this.builder.addOutput("CachePort",{Value:{"Fn::GetAtt":[p,"PrimaryEndPoint.Port"]},Description:"Redis primary endpoint port"})}else if(m==="memcached"){this.generateNetworkInfrastructure(e,t);let a=u.elasticache||{},{cluster:y,subnetGroup:i,logicalId:p,subnetGroupId:f}=re.createMemcached({slug:e,environment:t,nodeType:a.nodeType||u.nodeType||"cache.t3.micro",engineVersion:a.engineVersion||"1.6.22",numCacheNodes:a.numCacheNodes||2,subnetIds:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]});if(this.builder.addResource(p,y),i&&f)this.builder.addResource(f,i);this.builder.addOutput("CacheEndpoint",{Value:{"Fn::GetAtt":[p,"ConfigurationEndpoint.Address"]},Description:"Memcached configuration endpoint address"})}}let b=this.mergedConfig.infrastructure?.email;if(b){let m=b.domain||this.mergedConfig.infrastructure?.dns?.domain;if(m){let{emailIdentity:a,logicalId:y}=L.verifyDomain({domain:m,slug:e,environment:t,enableDkim:b.enableDkim!==!1,dkimKeyLength:b.dkimKeyLength||"RSA_2048_BIT"});if(this.builder.addResource(y,a),b.configurationSet!==!1){let{configurationSet:f,logicalId:C}=L.createConfigurationSet({slug:e,environment:t});this.builder.addResource(C,f)}let i=b.hostedZoneId||this.mergedConfig.infrastructure?.dns?.hostedZoneId;if(i){if(b.enableDkim!==!1)for(let I=1;I<=3;I++){let D=`DkimRecord${I}${m.replace(/\./g,"")}`;this.builder.addResource(D,{Type:"AWS::Route53::RecordSet",DependsOn:[y],Properties:{HostedZoneId:i,Name:{"Fn::GetAtt":[y,`DkimDNSTokenName${I}`]},Type:"CNAME",TTL:1800,ResourceRecords:[{"Fn::GetAtt":[y,`DkimDNSTokenValue${I}`]}]}})}let{record:f,logicalId:C}=L.createSpfRecord(m,i);this.builder.addResource(C,f);let{record:S,logicalId:R}=L.createDmarcRecord(m,i,{policy:"none",reportingEmail:b.dmarcReportingEmail||`dmarc-reports@${m}`});this.builder.addResource(R,S)}this.builder.addOutput("EmailDomain",{Value:m,Description:"SES verified email domain"});let p=b.server;if(p?.enabled&&i){let f=this.mergedConfig.environments[t]?.region||this.mergedConfig.project.region||"us-east-1",C=`${e}-${t}-email`,{role:S,policy:R,roleLogicalId:I,policyLogicalId:D}=L.createEmailLambdaRole({slug:e,environment:t,s3BucketArn:`arn:aws:s3:::${C}`,sesIdentityArn:`arn:aws:ses:${f}:*:identity/${m}`});this.builder.addResource(I,S),this.builder.addResource(D,R);let{function:P,permission:v,logicalId:O,permissionLogicalId:F}=L.createInboundEmailLambda({slug:e,environment:t,roleArn:{"Fn::GetAtt":[I,"Arn"]},s3BucketName:C,organizedPrefix:"mailboxes/"});this.builder.addResource(O,P),this.builder.addResource(F,v);let V=L.createInboundEmailSetup({slug:e,environment:t,domain:m,s3BucketName:C,s3KeyPrefix:"inbox/",region:f,hostedZoneId:i,lambdaFunctionArn:{"Fn::GetAtt":[O,"Arn"]}});for(let[_,k]of Object.entries(V.resources)){if(k.Type==="AWS::SES::ReceiptRule")k.DependsOn=[F,O];this.builder.addResource(_,k)}this.builder.addOutput("InboundEmailLambda",{Value:{Ref:O},Description:"Inbound email processing Lambda function"}),this.builder.addOutput("EmailBucket",{Value:C,Description:"S3 bucket for email storage"});let z=this.serverEipLogicalIds.get("app");if(z&&i){let k=`${p?.subdomain||"mail"}.${m}`,x=k.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(`${x}ARecord`,{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:k,Type:"A",TTL:"300",ResourceRecords:[{Ref:z}]}})}this.builder.addOutput("MailHost",{Value:`mail.${m}`,Description:"Mail server hostname for SMTP/IMAP clients"})}}}let A=this.mergedConfig.infrastructure?.search;if(A){let m=A.vpc?{subnetIds:[{Ref:"PublicSubnet1"}],securityGroupIds:[]}:void 0;if(m)this.generateNetworkInfrastructure(e,t);let{domain:a,logicalId:y}=De.createDomain({slug:e,environment:t,engineVersion:A.engineVersion||"OpenSearch_2.11",instanceType:A.instanceType||"t3.small.search",instanceCount:A.instanceCount||1,volumeSize:A.volumeSize||10,volumeType:A.volumeType||"gp3",dedicatedMaster:A.dedicatedMaster||!1,dedicatedMasterType:A.dedicatedMasterType,dedicatedMasterCount:A.dedicatedMasterCount||3,multiAz:A.multiAz||!1,encryption:A.encryption||{atRest:!0,nodeToNode:!0},advancedSecurity:A.advancedSecurity,autoTune:A.autoTune!==!1,vpc:m});this.builder.addResource(y,a),this.builder.addOutput("SearchDomainEndpoint",{Value:{"Fn::GetAtt":[y,"DomainEndpoint"]},Description:"OpenSearch domain endpoint"}),this.builder.addOutput("SearchDomainArn",{Value:{"Fn::GetAtt":[y,"Arn"]},Description:"OpenSearch domain ARN"})}let T=this.mergedConfig.infrastructure?.fileSystem;if(T&&Object.keys(T).length>0){this.generateNetworkInfrastructure(e,t);for(let[m,a]of Object.entries(T)){let{fileSystem:y,logicalId:i}=K.createFileSystem({slug:`${e}-${m}`,environment:t,encrypted:a.encrypted!==!1,performanceMode:a.performanceMode||"generalPurpose",throughputMode:a.throughputMode||"bursting",enableBackup:!0});this.builder.addResource(i,y);let{securityGroup:p,logicalId:f}=K.createEfsSecurityGroup({slug:`${e}-${m}`,environment:t,vpcId:{Ref:"VPC"},sourceCidrBlocks:["10.0.0.0/16"]});this.builder.addResource(f,p);let{mountTargets:C,logicalIds:S}=K.createMultiAzMountTargets(i,{slug:`${e}-${m}`,environment:t,subnetIds:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}],securityGroupId:{Ref:f}});for(let R=0;R<C.length;R++)this.builder.addResource(S[R],C[R]);this.builder.addOutput(`${m}FileSystemId`,{Value:{Ref:i},Description:`EFS file system ID for ${m}`})}}let g=this.mergedConfig.infrastructure?.ai;if(g){let m=g.service||"ecs",a=g.models||["*"],y=g.allowStreaming!==!1,i;if(m==="ecs")i=M.enableBedrockForEcs({slug:e,environment:t,models:a,allowStreaming:y});else if(m==="ec2")i=M.enableBedrockForEc2({slug:e,environment:t,models:a,allowStreaming:y});else if(m==="lambda")i=M.enableBedrockForLambda({slug:e,environment:t,models:a,allowStreaming:y});else i=M.createBedrockRole(m,{slug:e,environment:t,models:a,allowStreaming:y});if(this.builder.addResource(i.logicalId,i.role),g.allowAsync){let{policy:p,logicalId:f}=M.createBedrockPolicy({slug:e,environment:t,models:a,allowStreaming:y,allowAsync:!0});this.builder.addResource(f,p)}this.builder.addOutput("BedrockRoleArn",{Value:{"Fn::GetAtt":[i.logicalId,"Arn"]},Description:"IAM role ARN with Bedrock permissions"})}}generateRealtimeResources(e,t){let r=this.mergedConfig.infrastructure?.realtime;if(!r)return;let n=r.name||`${e}-${t}-realtime`,o=r.scaling||{},l=r.storage||{type:"dynamodb"},c=o.handlerMemory||256,s=o.handlerTimeout||30,d=`${e}${t}RealtimeConnections`.replace(/[^a-zA-Z0-9]/g,""),h=`${e}${t}RealtimeChannels`.replace(/[^a-zA-Z0-9]/g,"");if(l.type==="dynamodb"){let S=l.dynamodb||{},R=S.billingMode||"PAY_PER_REQUEST";this.builder.addResource(d,{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e}-${t}-realtime-connections`,BillingMode:R,AttributeDefinitions:[{AttributeName:"connectionId",AttributeType:"S"},{AttributeName:"userId",AttributeType:"S"}],KeySchema:[{AttributeName:"connectionId",KeyType:"HASH"}],GlobalSecondaryIndexes:[{IndexName:"userId-index",KeySchema:[{AttributeName:"userId",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"},...R==="PROVISIONED"&&{ProvisionedThroughput:{ReadCapacityUnits:S.readCapacity||5,WriteCapacityUnits:S.writeCapacity||5}}}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0},...R==="PROVISIONED"&&{ProvisionedThroughput:{ReadCapacityUnits:S.readCapacity||5,WriteCapacityUnits:S.writeCapacity||5}},...S.pointInTimeRecovery&&{PointInTimeRecoverySpecification:{PointInTimeRecoveryEnabled:!0}},Tags:[{Key:"Name",Value:`${e}-${t}-realtime-connections`},{Key:"Environment",Value:t}]}}),this.builder.addResource(h,{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e}-${t}-realtime-channels`,BillingMode:R,AttributeDefinitions:[{AttributeName:"channel",AttributeType:"S"},{AttributeName:"connectionId",AttributeType:"S"}],KeySchema:[{AttributeName:"channel",KeyType:"HASH"},{AttributeName:"connectionId",KeyType:"RANGE"}],GlobalSecondaryIndexes:[{IndexName:"connectionId-index",KeySchema:[{AttributeName:"connectionId",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"},...R==="PROVISIONED"&&{ProvisionedThroughput:{ReadCapacityUnits:S.readCapacity||5,WriteCapacityUnits:S.writeCapacity||5}}}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0},...R==="PROVISIONED"&&{ProvisionedThroughput:{ReadCapacityUnits:S.readCapacity||5,WriteCapacityUnits:S.writeCapacity||5}},Tags:[{Key:"Name",Value:`${e}-${t}-realtime-channels`},{Key:"Environment",Value:t}]}})}let 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":[h,"Arn"]},{"Fn::Sub":`\${${h}.Arn}/index/*`}]},{Effect:"Allow",Action:"execute-api:ManageConnections",Resource:{"Fn::Sub":"arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:*/*"}}]}}]}});let b=`${e}${t}RealtimeConnect`.replace(/[^a-zA-Z0-9]/g,""),A=`${e}${t}RealtimeDisconnect`.replace(/[^a-zA-Z0-9]/g,""),T=`${e}${t}RealtimeMessage`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(b,{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e}-${t}-realtime-connect`,Runtime:"nodejs20.x",Handler:"index.handler",Role:{"Fn::GetAtt":[u,"Arn"]},MemorySize:c,Timeout:s,Environment:{Variables:{CONNECTIONS_TABLE:{Ref:d},CHANNELS_TABLE:{Ref:h},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:h},ENVIRONMENT:t}},Code:{ZipFile:this.generateDisconnectHandlerCode()}},DependsOn:[u,d,h]}),this.builder.addResource(T,{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:h},ENVIRONMENT:t}},Code:{ZipFile:this.generateMessageHandlerCode()}},DependsOn:[u,d,h]});let g=`${e}${t}RealtimeApi`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(g,{Type:"AWS::ApiGatewayV2::Api",Properties:{Name:n,ProtocolType:"WEBSOCKET",RouteSelectionExpression:"$request.body.action",Tags:{Name:n,Environment:t}}});let m=`${b}Permission`,a=`${A}Permission`,y=`${T}Permission`;this.builder.addResource(m,{Type:"AWS::Lambda::Permission",Properties:{FunctionName:{Ref:b},Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:{"Fn::Sub":`arn:aws:execute-api:\${AWS::Region}:\${AWS::AccountId}:\${${g}}/*/$connect`}}}),this.builder.addResource(a,{Type:"AWS::Lambda::Permission",Properties:{FunctionName:{Ref:A},Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:{"Fn::Sub":`arn:aws:execute-api:\${AWS::Region}:\${AWS::AccountId}:\${${g}}/*/$disconnect`}}}),this.builder.addResource(y,{Type:"AWS::Lambda::Permission",Properties:{FunctionName:{Ref:T},Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:{"Fn::Sub":`arn:aws:execute-api:\${AWS::Region}:\${AWS::AccountId}:\${${g}}/*/$default`}}});let i=`${g}ConnectInteg`,p=`${g}DisconnectInteg`,f=`${g}MessageInteg`;this.builder.addResource(i,{Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:{Ref:g},IntegrationType:"AWS_PROXY",IntegrationUri:{"Fn::Sub":`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${b}.Arn}/invocations`}}}),this.builder.addResource(p,{Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:{Ref:g},IntegrationType:"AWS_PROXY",IntegrationUri:{"Fn::Sub":`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${A}.Arn}/invocations`}}}),this.builder.addResource(f,{Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:{Ref:g},IntegrationType:"AWS_PROXY",IntegrationUri:{"Fn::Sub":`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${T}.Arn}/invocations`}}}),this.builder.addResource(`${g}ConnectRoute`,{Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:{Ref:g},RouteKey:"$connect",AuthorizationType:"NONE",Target:{"Fn::Sub":`integrations/\${${i}}`}}}),this.builder.addResource(`${g}DisconnectRoute`,{Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:{Ref:g},RouteKey:"$disconnect",Target:{"Fn::Sub":`integrations/\${${p}}`}}}),this.builder.addResource(`${g}DefaultRoute`,{Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:{Ref:g},RouteKey:"$default",Target:{"Fn::Sub":`integrations/\${${f}}`}}});let C=`${g}Stage`;if(this.builder.addResource(C,{Type:"AWS::ApiGatewayV2::Stage",Properties:{ApiId:{Ref:g},StageName:t,AutoDeploy:!0,DefaultRouteSettings:{ThrottlingBurstLimit:o.messagesPerSecond||1000,ThrottlingRateLimit:o.messagesPerSecond||1000}}}),r.monitoring?.enabled){let S=r.monitoring,R=S.notificationTopicArn;if(!R&&S.notificationEmails?.length){let I=`${g}AlarmTopic`;this.builder.addResource(I,{Type:"AWS::SNS::Topic",Properties:{TopicName:`${e}-${t}-realtime-alarms`,DisplayName:"Realtime WebSocket Alarms"}}),S.notificationEmails.forEach((D,P)=>{this.builder.addResource(`${I}Sub${P}`,{Type:"AWS::SNS::Subscription",Properties:{TopicArn:{Ref:I},Protocol:"email",Endpoint:D}})}),R={Ref:I}}if(S.connectionThreshold)this.builder.addResource(`${g}ConnectionAlarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${e}-${t}-realtime-connections`,AlarmDescription:`WebSocket connections exceed ${S.connectionThreshold}`,MetricName:"ConnectCount",Namespace:"AWS/ApiGateway",Statistic:"Sum",Period:300,EvaluationPeriods:2,Threshold:S.connectionThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"ApiId",Value:{Ref:g}}],...R&&{AlarmActions:[R]}}});if(S.errorThreshold)this.builder.addResource(`${g}ErrorAlarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${e}-${t}-realtime-errors`,AlarmDescription:`WebSocket errors exceed ${S.errorThreshold}/min`,MetricName:"ExecutionError",Namespace:"AWS/ApiGateway",Statistic:"Sum",Period:60,EvaluationPeriods:3,Threshold:S.errorThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"ApiId",Value:{Ref:g}}],...R&&{AlarmActions:[R]}}})}this.builder.addOutput(`${g}Endpoint`,{Description:"WebSocket API endpoint URL",Value:{"Fn::Sub":`wss://\${${g}}.execute-api.\${AWS::Region}.amazonaws.com/${t}`},Export:{Name:{"Fn::Sub":"${AWS::StackName}-realtime-endpoint"}}}),this.builder.addOutput(`${g}Id`,{Description:"WebSocket API ID",Value:{Ref:g},Export:{Name:{"Fn::Sub":"${AWS::StackName}-realtime-api-id"}}})}generateConnectHandlerCode(){return`
13
+ `:C,m=i.map(([,A])=>A.port).filter((A)=>typeof A==="number"&&![80,443].includes(A)),c=this.resolveApiOriginPort(),y=`${e}${t}DeployBucket`.replace(/[^a-zA-Z0-9]/g,""),o=`${e}-${t}-deploy`;this.builder.addResource(y,{Type:"AWS::S3::Bucket",Properties:{BucketName:o,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 f=E.createServerModeStack({slug:`${e}-app`,environment:t,vpcId:{Ref:"VPC"},subnetId:{Ref:"PublicSubnet1"},instanceType:u,keyName:r.allowSsh?`${e}-${t}`:void 0,domain:s,userData:g,volumeSize:r.disk?.size||20,imageId:r.image,allowedPorts:[...r.allowSsh?[22]:[],80,443,c,...m]}),h=f.resources[f.outputs.instanceLogicalId];if(h?.Properties){let A=h.Properties.Tags||[];h.Properties.Tags=[...A,{Key:"Project",Value:e},{Key:"Environment",Value:t},{Key:"Role",Value:"app"},{Key:"ManagedBy",Value:"ts-cloud"}]}let S=f.resources[f.outputs.roleLogicalId];if(S?.Properties)S.Properties.Policies=S.Properties.Policies||[],S.Properties.Policies.push({PolicyName:"DeployBucketRead",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["s3:GetObject","s3:ListBucket"],Resource:[`arn:aws:s3:::${o}`,`arn:aws:s3:::${o}/*`]}]}});for(let[A,R]of Object.entries(f.resources))this.builder.addResource(A,R);this.builder.addOutput("deployBucketName",{Value:{Ref:y},Description:"S3 bucket where release tarballs are uploaded"}),this.builder.addOutput("appInstanceId",{Value:{Ref:f.outputs.instanceLogicalId},Description:"EC2 instance ID for the app server"}),this.builder.addOutput("appPublicIp",{Value:{Ref:f.outputs.eipLogicalId},Description:"Public IP for the app server"}),this.serverEipLogicalIds.set("app",f.outputs.eipLogicalId),this.serverEipLogicalIds.set("appInstance",f.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 i=n.size||"micro",s=E.InstanceSize.specs[i]?.instanceType||i||"t3.micro",a;if(n.mountEfs)a={fileSystemId:typeof n.mountEfs==="string"?n.mountEfs:{Ref:"FileSystem"},mountPath:n.mountPath||"/mnt/efs"};let l;if(n.databaseTools)l=E.JumpBox.withDatabaseTools({slug:e,environment:t,vpcId:{Ref:"VPC"},subnetId:{Ref:"PublicSubnet1"},keyName:n.keyName||`${e}-${t}`,allowedCidrs:n.allowedCidrs});else if(a)l=E.JumpBox.withEfsMount({slug:e,environment:t,vpcId:{Ref:"VPC"},subnetId:{Ref:"PublicSubnet1"},keyName:n.keyName||`${e}-${t}`,fileSystemId:a.fileSystemId,mountPath:a.mountPath,allowedCidrs:n.allowedCidrs});else l=E.createJumpBox({slug:e,environment:t,vpcId:{Ref:"VPC"},subnetId:{Ref:"PublicSubnet1"},keyName:n.keyName||`${e}-${t}`,instanceType:s,allowedCidrs:n.allowedCidrs,mountEfs:a});for(let[p,u]of Object.entries(l.resources))this.builder.addResource(p,u);this.builder.addOutput("JumpBoxInstanceId",{Value:{Ref:l.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,i=n?.domain,d=n?.hostedZoneId,s=[],a,l;if(r?.certificateArn)l=r.certificateArn;else if(r?.enabled&&i&&d){let m=r.domains||[i],c=m[0],y=m.slice(1).map((h)=>{if(h.includes(".")&&h.endsWith(c))return h.replace(`.${c}`,"");return h}),{certificate:o,logicalId:f}=re.createCertificate({domain:c,subdomains:y,slug:e,environment:t,validationMethod:"DNS",hostedZoneId:d});a=f,this.builder.addResource(f,o)}if(this.mergedConfig.infrastructure?.storage){let m=Object.entries(this.mergedConfig.infrastructure.storage).some(([,o])=>o.website),c;if(m&&(a||l))c=`${e}${t}CloudFrontOAC`.replace(/[^a-zA-Z0-9]/g,""),this.builder.addResource(c,{Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${e}-${t}-s3-oac`,Description:`OAC for ${e} ${t} S3 website buckets`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}});let y=Object.entries(this.mergedConfig.infrastructure.storage).map(([o,f])=>({name:o,config:f,mountPath:this.normalizeMountPath(f),rewriteStyle:f.pathRewriteStyle||"directory",logicalId:this.storageBucketLogicalId(e,t,o)})).filter((o)=>o.name!=="public"&&o.config.website&&o.mountPath);for(let[o,f]of Object.entries(this.mergedConfig.infrastructure.storage)){let h=!!(f.website&&c),S=this.storageBucketName(e,t,o),{bucket:A,logicalId:R}=te.createBucket({slug:e,name:o,environment:t,bucketName:S,versioning:f.versioning,encryption:f.encryption,public:h?!1:f.public});if(h&&A.Properties)A.Properties.PublicAccessBlockConfiguration={BlockPublicAcls:!0,IgnorePublicAcls:!0,BlockPublicPolicy:!1,RestrictPublicBuckets:!1};if(this.builder.addResource(R,A),f.website){let I=typeof f.website==="object"?f.website:{},P=te.enableWebsiteHosting(A,I.indexDocument||"index.html",I.errorDocument);this.builder.addResource(R,P)}let D=this.normalizeMountPath(f);if(h&&c&&i&&!(D&&o!=="public")){let I=`${e}${t}${o}CDN`.replace(/[^a-zA-Z0-9]/g,""),P=[];if(f.aliases&&f.aliases.length>0)P.push(...f.aliases);else if(o==="public"){if(P.push(i),r?.domains?.includes(`www.${i}`))P.push(`www.${i}`)}else if(o==="docs")P.push(`docs.${i}`);else if(o==="blog")P.push(`blog.${i}`);let v=typeof f.website==="object"?f.website:{},O=f.spa===!0,M=v.errorDocument||(O?"index.html":"404.html"),_=[];if(O)_.push({ErrorCode:403,ResponseCode:200,ResponsePagePath:"/index.html",ErrorCachingMinTTL:300},{ErrorCode:404,ResponseCode:200,ResponsePagePath:"/index.html",ErrorCachingMinTTL:300});else _.push({ErrorCode:403,ResponseCode:404,ResponsePagePath:`/${M}`,ErrorCachingMinTTL:300},{ErrorCode:404,ResponseCode:404,ResponsePagePath:`/${M}`,ErrorCachingMinTTL:300});let z=l&&P.length>0?{AcmCertificateArn:l,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}:a&&P.length>0?{AcmCertificateArn:{Ref:a},SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}:{CloudFrontDefaultCertificate:!0},B=`S3-${e}-${t}-${o}`,k=this.mergedConfig.project.region||"us-east-1",x;if(!O)x=`${e}${t}${o}UrlRewrite`.replace(/[^a-zA-Z0-9]/g,""),this.builder.addResource(x,{Type:"AWS::CloudFront::Function",Properties:{Name:`${e}-${t}-${o}-url-rewrite`,AutoPublish:!0,FunctionConfig:{Comment:`URL rewrite for ${e} ${t} ${o} - appends .html to extensionless paths`,Runtime:"cloudfront-js-2.0"},FunctionCode:`function handler(event) { var request = event.request; var uri = request.uri; if (uri.endsWith('/')) { request.uri += 'index.html'; }
14
+ else if (!uri.includes('.')) { request.uri += '.html'; } return request; }`}});let X=[{Id:B,DomainName:{"Fn::Sub":`\${${R}}.s3.${k}.amazonaws.com`},OriginPath:"",S3OriginConfig:{OriginAccessIdentity:""},OriginAccessControlId:{Ref:c}}],G=[],Q=[];if(this.shouldRouteStorageBucketToCompute(o,f)){this.appendComputeAppOrigin(X,G,Q,e,t,this.resolveComputeCachePathPatterns(f.computeRoutes));for(let w of y){let U=`S3-${e}-${t}-${w.name}`,ee=`${e}${t}${w.name}PathMountRewrite`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(ee,{Type:"AWS::CloudFront::Function",Properties:{Name:`${e}-${t}-${w.name}-path-mount-rewrite`,AutoPublish:!0,FunctionConfig:{Comment:`Path mount rewrite for ${e} ${t} ${w.name} at ${w.mountPath}`,Runtime:"cloudfront-js-2.0"},FunctionCode:this.pathMountRewriteFunctionCode(w.mountPath,w.rewriteStyle)}}),X.push({Id:U,DomainName:{"Fn::Sub":`\${${w.logicalId}}.s3.${k}.amazonaws.com`},OriginPath:"",S3OriginConfig:{OriginAccessIdentity:""},OriginAccessControlId:{Ref:c}}),Q.push(w.logicalId,ee);for(let ze of[w.mountPath,`${w.mountPath}/*`])G.push({PathPattern:ze,TargetOriginId:U,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,CachePolicyId:"4135ea2d-6df8-44a3-9df3-4b5a84be39ad",FunctionAssociations:[{EventType:"viewer-request",FunctionARN:{"Fn::GetAtt":[ee,"FunctionARN"]}}]})}}let ge={Type:"AWS::CloudFront::Distribution",DependsOn:[R,c,...x?[x]:[],...Q],Properties:{DistributionConfig:{Enabled:!0,Comment:`${e} ${t} ${o} site`,DefaultRootObject:"index.html",Origins:X,DefaultCacheBehavior:{TargetOriginId:B,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,CachePolicyId:"658327ea-f89d-4fab-a63d-7e88639e58f6",...x?{FunctionAssociations:[{EventType:"viewer-request",FunctionARN:{"Fn::GetAtt":[x,"FunctionARN"]}}]}:{}},...G.length>0?{CacheBehaviors:G}:{},...P.length>0?{Aliases:P}:{},ViewerCertificate:z,PriceClass:"PriceClass_100",HttpVersion:"http2and3",IPV6Enabled:!0,CustomErrorResponses:_}}};if(a)ge.DependsOn.push(a);this.builder.addResource(I,ge);let He=`${R}CloudFrontPolicy`;if(this.builder.addResource(He,{Type:"AWS::S3::BucketPolicy",DependsOn:[R,I],Properties:{Bucket:{Ref:R},PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowCloudFrontServicePrincipal",Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:{"Fn::Sub":`arn:aws:s3:::\${${R}}/*`},Condition:{StringEquals:{"AWS:SourceArn":{"Fn::Sub":`arn:aws:cloudfront::\${AWS::AccountId}:distribution/\${${I}}`}}}}]}}}),this.shouldRouteStorageBucketToCompute(o,f))for(let w of y){let U=`${w.logicalId}CloudFrontPolicy`;this.builder.addResource(U,{Type:"AWS::S3::BucketPolicy",DependsOn:[w.logicalId,I],Properties:{Bucket:{Ref:w.logicalId},PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowCloudFrontServicePrincipal",Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:{"Fn::Sub":`arn:aws:s3:::\${${w.logicalId}}/*`},Condition:{StringEquals:{"AWS:SourceArn":{"Fn::Sub":`arn:aws:cloudfront::\${AWS::AccountId}:distribution/\${${I}}`}}}}]}}})}if(P.length>0)s.push({name:o,bucketLogicalId:R,distLogicalId:I,oacLogicalId:c,aliases:P});this.builder.addOutput(`${o}CloudFrontDomain`,{Value:{"Fn::GetAtt":[I,"DomainName"]},Description:`CloudFront domain for ${o}`}),this.builder.addOutput(`${o}CloudFrontDistributionId`,{Value:{Ref:I},Description:`CloudFront distribution ID for ${o}`})}if(this.builder.addOutput(`${o}BucketName`,{Value:{Ref:R},Description:`S3 bucket name for ${o}`}),o==="public")this.builder.addOutput("FrontendBucketName",{Value:{Ref:R},Description:"Frontend S3 bucket name"});if(o==="docs")this.builder.addOutput("DocsBucketName",{Value:{Ref:R},Description:"Documentation S3 bucket name"});if(o==="blog")this.builder.addOutput("BlogBucketName",{Value:{Ref:R},Description:"Blog S3 bucket name"})}}if(this.mergedConfig.infrastructure?.sftp){let m=this.mergedConfig.infrastructure.sftp,c=$e.create({...m,storage:this.resolveSftpStorage(m,e,t)??m.storage,slug:e,environment:t});for(let[y,o]of Object.entries(c.resources))this.builder.addResource(y,o);this.builder.addOutput("SftpServerId",{Value:{Ref:c.serverLogicalId},Description:"AWS Transfer Family SFTP server ID"}),this.builder.addOutput("SftpEndpoint",{Value:{"Fn::Sub":`\${${c.serverLogicalId}}.server.transfer.\${AWS::Region}.amazonaws.com`},Description:"AWS Transfer Family SFTP endpoint"}),this.builder.addOutput("SftpStorageDomain",{Value:c.domain,Description:"Storage backing the SFTP server (EFS or S3)"})}if(d&&s.length>0)for(let{name:m,distLogicalId:c,aliases:y}of s)for(let o of y){let f=o.replace(/\./g,"").replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(`${f}ARecord`,{Type:"AWS::Route53::RecordSet",DependsOn:[c],Properties:{HostedZoneId:d,Name:o,Type:"A",AliasTarget:{DNSName:{"Fn::GetAtt":[c,"DomainName"]},HostedZoneId:"Z2FDTNDATAQYW2",EvaluateTargetHealth:!1}}}),this.builder.addResource(`${f}AAAARecord`,{Type:"AWS::Route53::RecordSet",DependsOn:[c],Properties:{HostedZoneId:d,Name:o,Type:"AAAA",AliasTarget:{DNSName:{"Fn::GetAtt":[c,"DomainName"]},HostedZoneId:"Z2FDTNDATAQYW2",EvaluateTargetHealth:!1}}})}if(this.mergedConfig.infrastructure?.databases){for(let[m,c]of Object.entries(this.mergedConfig.infrastructure.databases))if(c.engine==="dynamodb"){let{table:y,logicalId:o}=K.createTable({slug:e,environment:t,tableName:`${e}-${t}-${m}`,partitionKey:c.partitionKey||{name:"id",type:"S"},sortKey:c.sortKey});this.builder.addResource(o,y)}else if(c.engine==="postgres"){let{dbInstance:y,logicalId:o}=K.createPostgres({slug:e,environment:t,dbInstanceIdentifier:`${e}-${t}-${m}`,masterUsername:c.username||"admin",masterUserPassword:c.password||"changeme123",allocatedStorage:c.storage||20,dbInstanceClass:c.instanceClass||"db.t3.micro"});this.builder.addResource(o,y)}else if(c.engine==="mysql"){let{dbInstance:y,logicalId:o}=K.createMysql({slug:e,environment:t,dbInstanceIdentifier:`${e}-${t}-${m}`,masterUsername:c.username||"admin",masterUserPassword:c.password||"changeme123",allocatedStorage:c.storage||20,dbInstanceClass:c.instanceClass||"db.t3.micro"});this.builder.addResource(o,y)}}if(this.mergedConfig.infrastructure?.cdn)for(let[m,c]of Object.entries(this.mergedConfig.infrastructure.cdn)){if(!c.origin)continue;let y=typeof c.customDomain==="string"?c.customDomain:c.customDomain?.domain||c.domain,o=typeof c.customDomain==="object"?c.customDomain?.certificateArn:c.certificateArn,f=o||l,h=`${e}${t}${m}CDN`.replace(/[^a-zA-Z0-9]/g,""),S=`S3-${e}-${t}-${m}-cdn`,A=[{Id:S,DomainName:c.origin,OriginPath:"",S3OriginConfig:{OriginAccessIdentity:""},OriginShield:c.originShield?{Enabled:!0,OriginShieldRegion:c.originShieldRegion||this.mergedConfig.environments[t]?.region||this.mergedConfig.project.region||"us-east-1"}:{Enabled:!1}}],R=[],D=[];if(c.routeCompute)this.appendComputeAppOrigin(A,R,D,e,t,this.resolveComputeCachePathPatterns(c.computeRoutes));let I=f&&y?{AcmCertificateArn:a&&!o?{Ref:a}:f,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}:{CloudFrontDefaultCertificate:!0},P=[...D];if(a&&!o&&y)P.push(a);let v={Type:"AWS::CloudFront::Distribution",...P.length>0?{DependsOn:P}:{},Properties:{DistributionConfig:{Enabled:!0,Comment:`${e} ${t} ${m} CDN`,DefaultRootObject:"index.html",Origins:A,DefaultCacheBehavior:{TargetOriginId:S,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:c.compress!==!1,CachePolicyId:"658327ea-f89d-4fab-a63d-7e88639e58f6"},...R.length>0?{CacheBehaviors:R}:{},...y&&f?{Aliases:[y]}:{},ViewerCertificate:I,PriceClass:"PriceClass_100",HttpVersion:c.http3?"http2and3":"http2"}}};if(this.builder.addResource(h,v),d&&y&&f){let O=y.replace(/\./g,"").replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(`${O}CdnARecord`,{Type:"AWS::Route53::RecordSet",DependsOn:[h,...a&&!o?[a]:[]],Properties:{HostedZoneId:d,Name:y,Type:"A",AliasTarget:{HostedZoneId:"Z2FDTNDATAQYW2",DNSName:{"Fn::GetAtt":[h,"DomainName"]}}}})}}if(this.mergedConfig.infrastructure?.queues)for(let[m,c]of Object.entries(this.mergedConfig.infrastructure.queues)){if(!this.shouldDeploy(c))continue;let{queue:y,logicalId:o}=ne.createQueue({slug:e,environment:t,name:`${e}-${t}-${m}`,fifo:c.fifo,visibilityTimeout:c.visibilityTimeout,messageRetentionPeriod:c.messageRetentionPeriod,delaySeconds:c.delaySeconds,maxMessageSize:c.maxMessageSize,receiveMessageWaitTime:c.receiveMessageWaitTime,contentBasedDeduplication:c.contentBasedDeduplication,encrypted:c.encrypted,kmsKeyId:c.kmsKeyId});this.builder.addResource(o,y);let f;if(c.deadLetterQueue){let{deadLetterQueue:h,updatedSourceQueue:S,deadLetterLogicalId:A}=ne.createDeadLetterQueue(o,{slug:e,environment:t,maxReceiveCount:c.maxReceiveCount});f=A,this.builder.addResource(A,h);let D=this.builder.getResources()[o];if(D?.Properties)D.Properties.RedrivePolicy=S.Properties?.RedrivePolicy}if(c.trigger){let h=c.trigger,S=`${e}${t}${h.functionName}`.replace(/[^a-zA-Z0-9]/g,""),A={Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:{"Fn::GetAtt":[o,"Arn"]},FunctionName:{Ref:S},BatchSize:h.batchSize||10,MaximumBatchingWindowInSeconds:h.batchWindow||0,Enabled:!0,...h.reportBatchItemFailures!==!1&&{FunctionResponseTypes:["ReportBatchItemFailures"]},...h.maxConcurrency&&{ScalingConfig:{MaximumConcurrency:h.maxConcurrency}},...h.filterPattern&&{FilterCriteria:{Filters:[{Pattern:JSON.stringify(h.filterPattern)}]}}},DependsOn:[o,S]};this.builder.addResource(`${o}Trigger`,A)}if(c.alarms?.enabled){let h=c.alarms,S=h.notificationTopicArn;if(!S&&h.notificationEmails?.length){let D=`${o}AlarmTopic`;this.builder.addResource(D,{Type:"AWS::SNS::Topic",Properties:{TopicName:`${e}-${t}-${m}-alarms`,DisplayName:`${m} Queue Alarms`}}),h.notificationEmails.forEach((I,P)=>{this.builder.addResource(`${D}Sub${P}`,{Type:"AWS::SNS::Subscription",Properties:{TopicArn:{Ref:D},Protocol:"email",Endpoint:I}})}),S={Ref:D}}let A=h.queueDepthThreshold||1000;this.builder.addResource(`${o}DepthAlarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${e}-${t}-${m}-queue-depth`,AlarmDescription:`Queue ${m} depth exceeds ${A} messages`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Average",Period:300,EvaluationPeriods:2,Threshold:A,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:{"Fn::GetAtt":[o,"QueueName"]}}],...S&&{AlarmActions:[S],OKActions:[S]}}});let R=h.messageAgeThreshold||3600;if(this.builder.addResource(`${o}AgeAlarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${e}-${t}-${m}-message-age`,AlarmDescription:`Queue ${m} oldest message exceeds ${R} seconds`,MetricName:"ApproximateAgeOfOldestMessage",Namespace:"AWS/SQS",Statistic:"Maximum",Period:300,EvaluationPeriods:2,Threshold:R,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:{"Fn::GetAtt":[o,"QueueName"]}}],...S&&{AlarmActions:[S],OKActions:[S]}}}),f&&h.dlqAlarm!==!1)this.builder.addResource(`${f}Alarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${e}-${t}-${m}-dlq-messages`,AlarmDescription:`Dead letter queue for ${m} has messages`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Sum",Period:300,EvaluationPeriods:1,Threshold:0,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:{"Fn::GetAtt":[f,"QueueName"]}}],...S&&{AlarmActions:[S]}}})}if(c.subscribe){let h=c.subscribe,S=h.topicArn;if(!S&&h.topicName)S={Ref:h.topicName};if(S){this.builder.addResource(`${o}SnsPolicy`,{Type:"AWS::SQS::QueuePolicy",Properties:{Queues:[{Ref:o}],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"sns.amazonaws.com"},Action:"sqs:SendMessage",Resource:{"Fn::GetAtt":[o,"Arn"]},Condition:{ArnEquals:{"aws:SourceArn":S}}}]}}});let A={TopicArn:S,Protocol:"sqs",Endpoint:{"Fn::GetAtt":[o,"Arn"]},RawMessageDelivery:h.rawMessageDelivery||!1};if(h.filterPolicy)A.FilterPolicy=h.filterPolicy,A.FilterPolicyScope=h.filterPolicyScope||"MessageAttributes";this.builder.addResource(`${o}SnsSub`,{Type:"AWS::SNS::Subscription",Properties:A,DependsOn:`${o}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 p=this.mergedConfig.infrastructure?.redirects;if(p){let m=p.target||this.mergedConfig.infrastructure?.dns?.domain||"",c=p.protocol||"https";if(p.domains?.length&&m)for(let y of p.domains){let{bucket:o,bucketPolicy:f,logicalId:h,policyLogicalId:S}=q.createDomainRedirectBucket({slug:e,environment:t,sourceDomain:y,targetDomain:m,protocol:c});this.builder.addResource(h,o),this.builder.addResource(S,f)}if(p.paths&&Object.keys(p.paths).length>0){let y=q.fromMapping(p.paths,{statusCode:p.statusCode||301}),{function:o,logicalId:f}=q.createPathRedirectFunction({slug:e,environment:t,rules:y});this.builder.addResource(f,o)}}if(this.mergedConfig.infrastructure?.monitoring?.alarms)for(let[m,c]of Object.entries(this.mergedConfig.infrastructure.monitoring.alarms)){let{alarm:y,logicalId:o}=we.createAlarm({slug:e,environment:t,alarmName:`${e}-${t}-${m}`,metricName:c.metricName||"Errors",namespace:c.namespace||"AWS/Lambda",threshold:c.threshold||1,comparisonOperator:c.comparisonOperator||"GreaterThanThreshold"});this.builder.addResource(o,y)}let u=this.mergedConfig.infrastructure?.cache;if(u){let m=u.type||"redis";if(m==="redis"){this.generateNetworkInfrastructure(e,t);let c=u.redis||{},{replicationGroup:y,subnetGroup:o,logicalId:f,subnetGroupId:h}=ie.createRedis({slug:e,environment:t,nodeType:c.nodeType||u.nodeType||"cache.t3.micro",engineVersion:c.engineVersion||"7.1",port:c.port||6379,numCacheClusters:c.numCacheNodes||2,automaticFailover:c.automaticFailoverEnabled!==!1,atRestEncryption:!0,transitEncryption:!0,snapshotRetentionDays:c.snapshotRetentionLimit||7,snapshotWindow:c.snapshotWindow,subnetIds:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]});if(this.builder.addResource(f,y),o&&h)this.builder.addResource(h,o);this.builder.addOutput("CacheEndpoint",{Value:{"Fn::GetAtt":[f,"PrimaryEndPoint.Address"]},Description:"Redis primary endpoint address"}),this.builder.addOutput("CachePort",{Value:{"Fn::GetAtt":[f,"PrimaryEndPoint.Port"]},Description:"Redis primary endpoint port"})}else if(m==="memcached"){this.generateNetworkInfrastructure(e,t);let c=u.elasticache||{},{cluster:y,subnetGroup:o,logicalId:f,subnetGroupId:h}=ie.createMemcached({slug:e,environment:t,nodeType:c.nodeType||u.nodeType||"cache.t3.micro",engineVersion:c.engineVersion||"1.6.22",numCacheNodes:c.numCacheNodes||2,subnetIds:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]});if(this.builder.addResource(f,y),o&&h)this.builder.addResource(h,o);this.builder.addOutput("CacheEndpoint",{Value:{"Fn::GetAtt":[f,"ConfigurationEndpoint.Address"]},Description:"Memcached configuration endpoint address"})}}let b=this.mergedConfig.infrastructure?.email;if(b){let m=b.domain||this.mergedConfig.infrastructure?.dns?.domain;if(m){let{emailIdentity:c,logicalId:y}=L.verifyDomain({domain:m,slug:e,environment:t,enableDkim:b.enableDkim!==!1,dkimKeyLength:b.dkimKeyLength||"RSA_2048_BIT"});if(this.builder.addResource(y,c),b.configurationSet!==!1){let{configurationSet:h,logicalId:S}=L.createConfigurationSet({slug:e,environment:t});this.builder.addResource(S,h)}let o=b.hostedZoneId||this.mergedConfig.infrastructure?.dns?.hostedZoneId;if(o){if(b.enableDkim!==!1)for(let D=1;D<=3;D++){let I=`DkimRecord${D}${m.replace(/\./g,"")}`;this.builder.addResource(I,{Type:"AWS::Route53::RecordSet",DependsOn:[y],Properties:{HostedZoneId:o,Name:{"Fn::GetAtt":[y,`DkimDNSTokenName${D}`]},Type:"CNAME",TTL:1800,ResourceRecords:[{"Fn::GetAtt":[y,`DkimDNSTokenValue${D}`]}]}})}let{record:h,logicalId:S}=L.createSpfRecord(m,o);this.builder.addResource(S,h);let{record:A,logicalId:R}=L.createDmarcRecord(m,o,{policy:"none",reportingEmail:b.dmarcReportingEmail||`dmarc-reports@${m}`});this.builder.addResource(R,A)}this.builder.addOutput("EmailDomain",{Value:m,Description:"SES verified email domain"});let f=b.server;if(f?.enabled&&o){let h=this.mergedConfig.environments[t]?.region||this.mergedConfig.project.region||"us-east-1",S=`${e}-${t}-email`,{role:A,policy:R,roleLogicalId:D,policyLogicalId:I}=L.createEmailLambdaRole({slug:e,environment:t,s3BucketArn:`arn:aws:s3:::${S}`,sesIdentityArn:`arn:aws:ses:${h}:*:identity/${m}`});this.builder.addResource(D,A),this.builder.addResource(I,R);let{function:P,permission:v,logicalId:O,permissionLogicalId:M}=L.createInboundEmailLambda({slug:e,environment:t,roleArn:{"Fn::GetAtt":[D,"Arn"]},s3BucketName:S,organizedPrefix:"mailboxes/"});this.builder.addResource(O,P),this.builder.addResource(M,v);let _=L.createInboundEmailSetup({slug:e,environment:t,domain:m,s3BucketName:S,s3KeyPrefix:"inbox/",region:h,hostedZoneId:o,lambdaFunctionArn:{"Fn::GetAtt":[O,"Arn"]}});for(let[B,k]of Object.entries(_.resources)){if(k.Type==="AWS::SES::ReceiptRule")k.DependsOn=[M,O];this.builder.addResource(B,k)}this.builder.addOutput("InboundEmailLambda",{Value:{Ref:O},Description:"Inbound email processing Lambda function"}),this.builder.addOutput("EmailBucket",{Value:S,Description:"S3 bucket for email storage"});let z=this.serverEipLogicalIds.get("app");if(z&&o){let k=`${f?.subdomain||"mail"}.${m}`,x=k.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(`${x}ARecord`,{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:o,Name:k,Type:"A",TTL:"300",ResourceRecords:[{Ref:z}]}})}this.builder.addOutput("MailHost",{Value:`mail.${m}`,Description:"Mail server hostname for SMTP/IMAP clients"})}}}let C=this.mergedConfig.infrastructure?.search;if(C){let m=C.vpc?{subnetIds:[{Ref:"PublicSubnet1"}],securityGroupIds:[]}:void 0;if(m)this.generateNetworkInfrastructure(e,t);let{domain:c,logicalId:y}=Ee.createDomain({slug:e,environment:t,engineVersion:C.engineVersion||"OpenSearch_2.11",instanceType:C.instanceType||"t3.small.search",instanceCount:C.instanceCount||1,volumeSize:C.volumeSize||10,volumeType:C.volumeType||"gp3",dedicatedMaster:C.dedicatedMaster||!1,dedicatedMasterType:C.dedicatedMasterType,dedicatedMasterCount:C.dedicatedMasterCount||3,multiAz:C.multiAz||!1,encryption:C.encryption||{atRest:!0,nodeToNode:!0},advancedSecurity:C.advancedSecurity,autoTune:C.autoTune!==!1,vpc:m});this.builder.addResource(y,c),this.builder.addOutput("SearchDomainEndpoint",{Value:{"Fn::GetAtt":[y,"DomainEndpoint"]},Description:"OpenSearch domain endpoint"}),this.builder.addOutput("SearchDomainArn",{Value:{"Fn::GetAtt":[y,"Arn"]},Description:"OpenSearch domain ARN"})}let T=this.mergedConfig.infrastructure?.fileSystem;if(T&&Object.keys(T).length>0){this.generateNetworkInfrastructure(e,t);for(let[m,c]of Object.entries(T)){let{fileSystem:y,logicalId:o}=j.createFileSystem({slug:`${e}-${m}`,environment:t,encrypted:c.encrypted!==!1,performanceMode:c.performanceMode||"generalPurpose",throughputMode:c.throughputMode||"bursting",enableBackup:!0});this.builder.addResource(o,y);let{securityGroup:f,logicalId:h}=j.createEfsSecurityGroup({slug:`${e}-${m}`,environment:t,vpcId:{Ref:"VPC"},sourceCidrBlocks:["10.0.0.0/16"]});this.builder.addResource(h,f);let{mountTargets:S,logicalIds:A}=j.createMultiAzMountTargets(o,{slug:`${e}-${m}`,environment:t,subnetIds:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}],securityGroupId:{Ref:h}});for(let R=0;R<S.length;R++)this.builder.addResource(A[R],S[R]);this.builder.addOutput(`${m}FileSystemId`,{Value:{Ref:o},Description:`EFS file system ID for ${m}`})}}let g=this.mergedConfig.infrastructure?.ai;if(g){let m=g.service||"ecs",c=g.models||["*"],y=g.allowStreaming!==!1,o;if(m==="ecs")o=F.enableBedrockForEcs({slug:e,environment:t,models:c,allowStreaming:y});else if(m==="ec2")o=F.enableBedrockForEc2({slug:e,environment:t,models:c,allowStreaming:y});else if(m==="lambda")o=F.enableBedrockForLambda({slug:e,environment:t,models:c,allowStreaming:y});else o=F.createBedrockRole(m,{slug:e,environment:t,models:c,allowStreaming:y});if(this.builder.addResource(o.logicalId,o.role),g.allowAsync){let{policy:f,logicalId:h}=F.createBedrockPolicy({slug:e,environment:t,models:c,allowStreaming:y,allowAsync:!0});this.builder.addResource(h,f)}this.builder.addOutput("BedrockRoleArn",{Value:{"Fn::GetAtt":[o.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`,i=r.scaling||{},d=r.storage||{type:"dynamodb"},s=i.handlerMemory||256,a=i.handlerTimeout||30,l=`${e}${t}RealtimeConnections`.replace(/[^a-zA-Z0-9]/g,""),p=`${e}${t}RealtimeChannels`.replace(/[^a-zA-Z0-9]/g,"");if(d.type==="dynamodb"){let A=d.dynamodb||{},R=A.billingMode||"PAY_PER_REQUEST";this.builder.addResource(l,{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e}-${t}-realtime-connections`,BillingMode:R,AttributeDefinitions:[{AttributeName:"connectionId",AttributeType:"S"},{AttributeName:"userId",AttributeType:"S"}],KeySchema:[{AttributeName:"connectionId",KeyType:"HASH"}],GlobalSecondaryIndexes:[{IndexName:"userId-index",KeySchema:[{AttributeName:"userId",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"},...R==="PROVISIONED"&&{ProvisionedThroughput:{ReadCapacityUnits:A.readCapacity||5,WriteCapacityUnits:A.writeCapacity||5}}}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0},...R==="PROVISIONED"&&{ProvisionedThroughput:{ReadCapacityUnits:A.readCapacity||5,WriteCapacityUnits:A.writeCapacity||5}},...A.pointInTimeRecovery&&{PointInTimeRecoverySpecification:{PointInTimeRecoveryEnabled:!0}},Tags:[{Key:"Name",Value:`${e}-${t}-realtime-connections`},{Key:"Environment",Value:t}]}}),this.builder.addResource(p,{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${e}-${t}-realtime-channels`,BillingMode:R,AttributeDefinitions:[{AttributeName:"channel",AttributeType:"S"},{AttributeName:"connectionId",AttributeType:"S"}],KeySchema:[{AttributeName:"channel",KeyType:"HASH"},{AttributeName:"connectionId",KeyType:"RANGE"}],GlobalSecondaryIndexes:[{IndexName:"connectionId-index",KeySchema:[{AttributeName:"connectionId",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"},...R==="PROVISIONED"&&{ProvisionedThroughput:{ReadCapacityUnits:A.readCapacity||5,WriteCapacityUnits:A.writeCapacity||5}}}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0},...R==="PROVISIONED"&&{ProvisionedThroughput:{ReadCapacityUnits:A.readCapacity||5,WriteCapacityUnits:A.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":[l,"Arn"]},{"Fn::Sub":`\${${l}.Arn}/index/*`},{"Fn::GetAtt":[p,"Arn"]},{"Fn::Sub":`\${${p}.Arn}/index/*`}]},{Effect:"Allow",Action:"execute-api:ManageConnections",Resource:{"Fn::Sub":"arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:*/*"}}]}}]}});let b=`${e}${t}RealtimeConnect`.replace(/[^a-zA-Z0-9]/g,""),C=`${e}${t}RealtimeDisconnect`.replace(/[^a-zA-Z0-9]/g,""),T=`${e}${t}RealtimeMessage`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(b,{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e}-${t}-realtime-connect`,Runtime:"nodejs20.x",Handler:"index.handler",Role:{"Fn::GetAtt":[u,"Arn"]},MemorySize:s,Timeout:a,Environment:{Variables:{CONNECTIONS_TABLE:{Ref:l},CHANNELS_TABLE:{Ref:p},ENVIRONMENT:t}},Code:{ZipFile:this.generateConnectHandlerCode()}},DependsOn:[u,l]}),this.builder.addResource(C,{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e}-${t}-realtime-disconnect`,Runtime:"nodejs20.x",Handler:"index.handler",Role:{"Fn::GetAtt":[u,"Arn"]},MemorySize:s,Timeout:a,Environment:{Variables:{CONNECTIONS_TABLE:{Ref:l},CHANNELS_TABLE:{Ref:p},ENVIRONMENT:t}},Code:{ZipFile:this.generateDisconnectHandlerCode()}},DependsOn:[u,l,p]}),this.builder.addResource(T,{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${e}-${t}-realtime-message`,Runtime:"nodejs20.x",Handler:"index.handler",Role:{"Fn::GetAtt":[u,"Arn"]},MemorySize:s,Timeout:a,Environment:{Variables:{CONNECTIONS_TABLE:{Ref:l},CHANNELS_TABLE:{Ref:p},ENVIRONMENT:t}},Code:{ZipFile:this.generateMessageHandlerCode()}},DependsOn:[u,l,p]});let g=`${e}${t}RealtimeApi`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(g,{Type:"AWS::ApiGatewayV2::Api",Properties:{Name:n,ProtocolType:"WEBSOCKET",RouteSelectionExpression:"$request.body.action",Tags:{Name:n,Environment:t}}});let m=`${b}Permission`,c=`${C}Permission`,y=`${T}Permission`;this.builder.addResource(m,{Type:"AWS::Lambda::Permission",Properties:{FunctionName:{Ref:b},Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:{"Fn::Sub":`arn:aws:execute-api:\${AWS::Region}:\${AWS::AccountId}:\${${g}}/*/$connect`}}}),this.builder.addResource(c,{Type:"AWS::Lambda::Permission",Properties:{FunctionName:{Ref:C},Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:{"Fn::Sub":`arn:aws:execute-api:\${AWS::Region}:\${AWS::AccountId}:\${${g}}/*/$disconnect`}}}),this.builder.addResource(y,{Type:"AWS::Lambda::Permission",Properties:{FunctionName:{Ref:T},Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:{"Fn::Sub":`arn:aws:execute-api:\${AWS::Region}:\${AWS::AccountId}:\${${g}}/*/$default`}}});let o=`${g}ConnectInteg`,f=`${g}DisconnectInteg`,h=`${g}MessageInteg`;this.builder.addResource(o,{Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:{Ref:g},IntegrationType:"AWS_PROXY",IntegrationUri:{"Fn::Sub":`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${b}.Arn}/invocations`}}}),this.builder.addResource(f,{Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:{Ref:g},IntegrationType:"AWS_PROXY",IntegrationUri:{"Fn::Sub":`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${C}.Arn}/invocations`}}}),this.builder.addResource(h,{Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:{Ref:g},IntegrationType:"AWS_PROXY",IntegrationUri:{"Fn::Sub":`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${T}.Arn}/invocations`}}}),this.builder.addResource(`${g}ConnectRoute`,{Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:{Ref:g},RouteKey:"$connect",AuthorizationType:"NONE",Target:{"Fn::Sub":`integrations/\${${o}}`}}}),this.builder.addResource(`${g}DisconnectRoute`,{Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:{Ref:g},RouteKey:"$disconnect",Target:{"Fn::Sub":`integrations/\${${f}}`}}}),this.builder.addResource(`${g}DefaultRoute`,{Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:{Ref:g},RouteKey:"$default",Target:{"Fn::Sub":`integrations/\${${h}}`}}});let S=`${g}Stage`;if(this.builder.addResource(S,{Type:"AWS::ApiGatewayV2::Stage",Properties:{ApiId:{Ref:g},StageName:t,AutoDeploy:!0,DefaultRouteSettings:{ThrottlingBurstLimit:i.messagesPerSecond||1000,ThrottlingRateLimit:i.messagesPerSecond||1000}}}),r.monitoring?.enabled){let A=r.monitoring,R=A.notificationTopicArn;if(!R&&A.notificationEmails?.length){let D=`${g}AlarmTopic`;this.builder.addResource(D,{Type:"AWS::SNS::Topic",Properties:{TopicName:`${e}-${t}-realtime-alarms`,DisplayName:"Realtime WebSocket Alarms"}}),A.notificationEmails.forEach((I,P)=>{this.builder.addResource(`${D}Sub${P}`,{Type:"AWS::SNS::Subscription",Properties:{TopicArn:{Ref:D},Protocol:"email",Endpoint:I}})}),R={Ref:D}}if(A.connectionThreshold)this.builder.addResource(`${g}ConnectionAlarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${e}-${t}-realtime-connections`,AlarmDescription:`WebSocket connections exceed ${A.connectionThreshold}`,MetricName:"ConnectCount",Namespace:"AWS/ApiGateway",Statistic:"Sum",Period:300,EvaluationPeriods:2,Threshold:A.connectionThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"ApiId",Value:{Ref:g}}],...R&&{AlarmActions:[R]}}});if(A.errorThreshold)this.builder.addResource(`${g}ErrorAlarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${e}-${t}-realtime-errors`,AlarmDescription:`WebSocket errors exceed ${A.errorThreshold}/min`,MetricName:"ExecutionError",Namespace:"AWS/ApiGateway",Statistic:"Sum",Period:60,EvaluationPeriods:3,Threshold:A.errorThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"ApiId",Value:{Ref:g}}],...R&&{AlarmActions:[R]}}})}this.builder.addOutput(`${g}Endpoint`,{Description:"WebSocket API endpoint URL",Value:{"Fn::Sub":`wss://\${${g}}.execute-api.\${AWS::Region}.amazonaws.com/${t}`},Export:{Name:{"Fn::Sub":"${AWS::StackName}-realtime-endpoint"}}}),this.builder.addOutput(`${g}Id`,{Description:"WebSocket API ID",Value:{Ref:g},Export:{Name:{"Fn::Sub":"${AWS::StackName}-realtime-api-id"}}})}generateConnectHandlerCode(){return`
15
15
  const { DynamoDBClient } = require('@aws-sdk/client-dynamodb');
16
16
  const { DynamoDBDocumentClient, PutCommand } = require('@aws-sdk/lib-dynamodb');
17
17
 
@@ -170,7 +170,7 @@ catch (error) {
170
170
  return { statusCode: 500, body: JSON.stringify({ error: 'Internal error' }) };
171
171
  }
172
172
  };
173
- `.trim()}generateRealtimeServerResources(e,t){let r=this.mergedConfig.infrastructure?.realtime;if(!r)return;let n=r.server||{},o=n.port||6001,l=n.instances||1,c=`${e}${t}RealtimeSG`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(c,{Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:`Security group for ${e} realtime WebSocket server`,GroupName:`${e}-${t}-realtime-sg`,VpcId:{Ref:"VPC"},SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:o,ToPort:o,CidrIp:"0.0.0.0/0",Description:"WebSocket connections"},{IpProtocol:"tcp",FromPort:443,ToPort:443,CidrIp:"0.0.0.0/0",Description:"HTTPS/WSS connections"}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound"}],Tags:[{Key:"Name",Value:`${e}-${t}-realtime-sg`},{Key:"Environment",Value:t}]}});let s=`${e}${t}RealtimeTaskDef`.replace(/[^a-zA-Z0-9]/g,""),d=`${e}${t}RealtimeTaskRole`.replace(/[^a-zA-Z0-9]/g,""),h=`${e}${t}RealtimeExecRole`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(h,{Type:"AWS::IAM::Role",Properties:{RoleName:`${e}-${t}-realtime-exec-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"]}}),this.builder.addResource(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":[h,"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:[h,d]});let b=`${e}${t}RealtimeLogs`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(b,{Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:`/ecs/${e}-${t}-realtime`,RetentionInDays:30}});let A=`${e}${t}RealtimeService`.replace(/[^a-zA-Z0-9]/g,"");if(this.builder.addResource(A,{Type:"AWS::ECS::Service",Properties:{ServiceName:`${e}-${t}-realtime`,Cluster:{Ref:"ECSCluster"},TaskDefinition:{Ref:s},DesiredCount:l,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{AssignPublicIp:"ENABLED",SecurityGroups:[{Ref:c}],Subnets:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]}},HealthCheckGracePeriodSeconds:60,Tags:[{Key:"Name",Value:`${e}-${t}-realtime`},{Key:"Environment",Value:t}]},DependsOn:[s,c,b]}),n.autoScaling){let T=n.autoScaling,g=`${e}${t}RealtimeScalableTarget`.replace(/[^a-zA-Z0-9]/g,"");if(this.builder.addResource(g,{Type:"AWS::ApplicationAutoScaling::ScalableTarget",Properties:{MaxCapacity:T.max||10,MinCapacity:T.min||1,ResourceId:{"Fn::Sub":`service/\${ECSCluster}/${e}-${t}-realtime`},RoleARN:{"Fn::Sub":"arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService"},ScalableDimension:"ecs:service:DesiredCount",ServiceNamespace:"ecs"},DependsOn:A}),T.targetCPU)this.builder.addResource(`${e}${t}RealtimeCPUPolicy`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::ApplicationAutoScaling::ScalingPolicy",Properties:{PolicyName:`${e}-${t}-realtime-cpu-scaling`,PolicyType:"TargetTrackingScaling",ScalingTargetId:{Ref:g},TargetTrackingScalingPolicyConfiguration:{PredefinedMetricSpecification:{PredefinedMetricType:"ECSServiceAverageCPUUtilization"},TargetValue:T.targetCPU,ScaleInCooldown:300,ScaleOutCooldown:60}}})}if(r.monitoring?.enabled){let T=r.monitoring,g=T.notificationTopicArn;if(!g&&T.notificationEmails?.length){let m=`${e}${t}RealtimeAlarmTopic`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(m,{Type:"AWS::SNS::Topic",Properties:{TopicName:`${e}-${t}-realtime-alarms`,DisplayName:"Realtime Server Alarms"}}),T.notificationEmails.forEach((a,y)=>{this.builder.addResource(`${m}Sub${y}`,{Type:"AWS::SNS::Subscription",Properties:{TopicArn:{Ref:m},Protocol:"email",Endpoint:a}})}),g={Ref:m}}this.builder.addResource(`${e}${t}RealtimeCPUAlarm`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${e}-${t}-realtime-high-cpu`,AlarmDescription:"Realtime server CPU utilization is high",MetricName:"CPUUtilization",Namespace:"AWS/ECS",Statistic:"Average",Period:300,EvaluationPeriods:2,Threshold:80,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"ClusterName",Value:{Ref:"ECSCluster"}},{Name:"ServiceName",Value:`${e}-${t}-realtime`}],...g&&{AlarmActions:[g]}},DependsOn:A}),this.builder.addResource(`${e}${t}RealtimeMemoryAlarm`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${e}-${t}-realtime-high-memory`,AlarmDescription:"Realtime server memory utilization is high",MetricName:"MemoryUtilization",Namespace:"AWS/ECS",Statistic:"Average",Period:300,EvaluationPeriods:2,Threshold:80,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"ClusterName",Value:{Ref:"ECSCluster"}},{Name:"ServiceName",Value:`${e}-${t}-realtime`}],...g&&{AlarmActions:[g]}},DependsOn:A})}this.builder.addOutput(`${e}${t}RealtimeEndpoint`.replace(/[^a-zA-Z0-9]/g,""),{Description:"Realtime WebSocket server endpoint",Value:{"Fn::Sub":`wss://${e}-${t}-realtime.\${AWS::Region}.elb.amazonaws.com:${o}`},Export:{Name:{"Fn::Sub":"${AWS::StackName}-realtime-endpoint"}}})}generateBroadcastConfig(){let e=this.mergedConfig.infrastructure?.realtime;if(!e||e.mode!=="server")return"";let t=e.server||{};return`import type { BroadcastConfig } from 'ts-broadcasting'
173
+ `.trim()}generateRealtimeServerResources(e,t){let r=this.mergedConfig.infrastructure?.realtime;if(!r)return;let n=r.server||{},i=n.port||6001,d=n.instances||1,s=`${e}${t}RealtimeSG`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(s,{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:i,ToPort:i,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 a=`${e}${t}RealtimeTaskDef`.replace(/[^a-zA-Z0-9]/g,""),l=`${e}${t}RealtimeTaskRole`.replace(/[^a-zA-Z0-9]/g,""),p=`${e}${t}RealtimeExecRole`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(p,{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(l,{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(i)},{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(a,{Type:"AWS::ECS::TaskDefinition",Properties:{Family:`${e}-${t}-realtime`,NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:"512",Memory:"1024",ExecutionRoleArn:{"Fn::GetAtt":[p,"Arn"]},TaskRoleArn:{"Fn::GetAtt":[l,"Arn"]},ContainerDefinitions:[{Name:"realtime",Image:{"Fn::Sub":`\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.amazonaws.com/${e}-realtime:latest`},Essential:!0,PortMappings:[{ContainerPort:i,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:${i}${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:[p,l]});let b=`${e}${t}RealtimeLogs`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(b,{Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:`/ecs/${e}-${t}-realtime`,RetentionInDays:30}});let C=`${e}${t}RealtimeService`.replace(/[^a-zA-Z0-9]/g,"");if(this.builder.addResource(C,{Type:"AWS::ECS::Service",Properties:{ServiceName:`${e}-${t}-realtime`,Cluster:{Ref:"ECSCluster"},TaskDefinition:{Ref:a},DesiredCount:d,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{AssignPublicIp:"ENABLED",SecurityGroups:[{Ref:s}],Subnets:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]}},HealthCheckGracePeriodSeconds:60,Tags:[{Key:"Name",Value:`${e}-${t}-realtime`},{Key:"Environment",Value:t}]},DependsOn:[a,s,b]}),n.autoScaling){let T=n.autoScaling,g=`${e}${t}RealtimeScalableTarget`.replace(/[^a-zA-Z0-9]/g,"");if(this.builder.addResource(g,{Type:"AWS::ApplicationAutoScaling::ScalableTarget",Properties:{MaxCapacity:T.max||10,MinCapacity:T.min||1,ResourceId:{"Fn::Sub":`service/\${ECSCluster}/${e}-${t}-realtime`},RoleARN:{"Fn::Sub":"arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService"},ScalableDimension:"ecs:service:DesiredCount",ServiceNamespace:"ecs"},DependsOn:C}),T.targetCPU)this.builder.addResource(`${e}${t}RealtimeCPUPolicy`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::ApplicationAutoScaling::ScalingPolicy",Properties:{PolicyName:`${e}-${t}-realtime-cpu-scaling`,PolicyType:"TargetTrackingScaling",ScalingTargetId:{Ref:g},TargetTrackingScalingPolicyConfiguration:{PredefinedMetricSpecification:{PredefinedMetricType:"ECSServiceAverageCPUUtilization"},TargetValue:T.targetCPU,ScaleInCooldown:300,ScaleOutCooldown:60}}})}if(r.monitoring?.enabled){let T=r.monitoring,g=T.notificationTopicArn;if(!g&&T.notificationEmails?.length){let m=`${e}${t}RealtimeAlarmTopic`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(m,{Type:"AWS::SNS::Topic",Properties:{TopicName:`${e}-${t}-realtime-alarms`,DisplayName:"Realtime Server Alarms"}}),T.notificationEmails.forEach((c,y)=>{this.builder.addResource(`${m}Sub${y}`,{Type:"AWS::SNS::Subscription",Properties:{TopicArn:{Ref:m},Protocol:"email",Endpoint:c}})}),g={Ref:m}}this.builder.addResource(`${e}${t}RealtimeCPUAlarm`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${e}-${t}-realtime-high-cpu`,AlarmDescription:"Realtime server CPU utilization is high",MetricName:"CPUUtilization",Namespace:"AWS/ECS",Statistic:"Average",Period:300,EvaluationPeriods:2,Threshold:80,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"ClusterName",Value:{Ref:"ECSCluster"}},{Name:"ServiceName",Value:`${e}-${t}-realtime`}],...g&&{AlarmActions:[g]}},DependsOn:C}),this.builder.addResource(`${e}${t}RealtimeMemoryAlarm`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${e}-${t}-realtime-high-memory`,AlarmDescription:"Realtime server memory utilization is high",MetricName:"MemoryUtilization",Namespace:"AWS/ECS",Statistic:"Average",Period:300,EvaluationPeriods:2,Threshold:80,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"ClusterName",Value:{Ref:"ECSCluster"}},{Name:"ServiceName",Value:`${e}-${t}-realtime`}],...g&&{AlarmActions:[g]}},DependsOn:C})}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:${i}`},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'
174
174
 
175
175
  export default {
176
176
  verbose: ${this.environment!=="production"},
@@ -219,7 +219,7 @@ ${t.loadManagement?.enabled?`
219
219
  },
220
220
  `:""}
221
221
  } satisfies BroadcastConfig
222
- `}toYAML(){return this.builder.toYAML()}toJSON(){return this.builder.toJSON()}getBuilder(){return this.builder}}function He(e){let t=[],r=[];if(!e.AWSTemplateFormatVersion)t.push({path:"AWSTemplateFormatVersion",message:"AWSTemplateFormatVersion is required",severity:"error"});else if(e.AWSTemplateFormatVersion!=="2010-09-09")r.push({path:"AWSTemplateFormatVersion",message:'AWSTemplateFormatVersion should be "2010-09-09"',severity:"warning"});if(!e.Resources||Object.keys(e.Resources).length===0)t.push({path:"Resources",message:"At least one resource is required",severity:"error"});else for(let[n,o]of Object.entries(e.Resources))Ge(n,o,t,r);if(e.Resources){let n=Ze(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))Ke(n,o,t,r);if(e.Outputs)for(let[n,o]of Object.entries(e.Outputs))Ue(n,o,t,r);return{valid:t.length===0,errors:t,warnings:r}}function Ge(e,t,r,n){if(!t.Type)r.push({path:`Resources.${e}.Type`,message:"Resource Type is required",severity:"error"});if(!/^[a-zA-Z0-9]+$/.test(e))n.push({path:`Resources.${e}`,message:"Logical ID should only contain alphanumeric characters",severity:"warning"});if(t.Type&&!t.Type.startsWith("AWS::")&&!t.Type.startsWith("Custom::"))r.push({path:`Resources.${e}.Type`,message:'Resource Type must start with "AWS::" or "Custom::"',severity:"error"});if(t.Properties){for(let[o,l]of Object.entries(t.Properties))if(l===void 0||l===null)n.push({path:`Resources.${e}.Properties.${o}`,message:"Property has undefined or null value",severity:"warning"})}if(t.DependsOn){if(typeof t.DependsOn==="string"){if(t.DependsOn===e)r.push({path:`Resources.${e}.DependsOn`,message:"Resource cannot depend on itself",severity:"error"})}else if(Array.isArray(t.DependsOn)){if(t.DependsOn.includes(e))r.push({path:`Resources.${e}.DependsOn`,message:"Resource cannot depend on itself",severity:"error"})}}}function Ke(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 Ue(e,t,r,n){if(!t.Value)r.push({path:`Outputs.${e}.Value`,message:"Output Value is required",severity:"error"})}function Ze(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 h of d)if(!r.has(h)){if(l(h,s))return!0}else if(n.has(h)){let u=s.indexOf(h);return o.push(...s.slice(u),h),!0}return s.pop(),n.delete(c),!1}for(let c of Object.keys(t))if(!r.has(c)){if(l(c,[]))return o}return[]}function 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 je(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 Yi(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(" "),h=n?"--staging":"";if(o==="http-01")return Ye({domains:t,email:r,staging:n,certPath:l,autoRenew:c,domainFlags:d,stagingFlag:h,primaryDomain:s});else{let u=e.dnsProvider?.provider||(e.hostedZoneId?"route53":void 0);return Qe({domains:t,email:r,staging:n,certPath:l,autoRenew:c,domainFlags:d,stagingFlag:h,primaryDomain:s,hostedZoneId:e.hostedZoneId,dnsProvider:e.dnsProvider,dnsProviderType:u})}}function Ye(e){let{email:t,certPath:r,autoRenew:n,domainFlags:o,stagingFlag:l,primaryDomain:c}=e;return`
222
+ `}toYAML(){return this.builder.toYAML()}toJSON(){return this.builder.toJSON()}getBuilder(){return this.builder}}function qe(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,i]of Object.entries(e.Resources))Ze(n,i,t,r);if(e.Resources){let n=Xe(e.Resources);if(n.length>0)t.push({path:"Resources",message:`Circular dependencies detected: ${n.join(" -> ")}`,severity:"error"})}if(e.Parameters)for(let[n,i]of Object.entries(e.Parameters))Je(n,i,t,r);if(e.Outputs)for(let[n,i]of Object.entries(e.Outputs))Ye(n,i,t,r);return{valid:t.length===0,errors:t,warnings:r}}function Ze(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[i,d]of Object.entries(t.Properties))if(d===void 0||d===null)n.push({path:`Resources.${e}.Properties.${i}`,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 Je(e,t,r,n){if(!t.Type)r.push({path:`Parameters.${e}.Type`,message:"Parameter Type is required",severity:"error"});let i=["String","Number","List<Number>","CommaDelimitedList","AWS::SSM::Parameter::Value<String>"];if(t.Type&&!i.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 Ye(e,t,r,n){if(!t.Value)r.push({path:`Outputs.${e}.Value`,message:"Output Value is required",severity:"error"})}function Xe(e){let t={};for(let[s,a]of Object.entries(e)){if(t[s]=[],a.DependsOn){if(typeof a.DependsOn==="string")t[s].push(a.DependsOn);else if(Array.isArray(a.DependsOn))t[s].push(...a.DependsOn)}let l=oe(a);t[s].push(...l)}let r=new Set,n=new Set,i=[];function d(s,a){r.add(s),n.add(s),a.push(s);let l=t[s]||[];for(let p of l)if(!r.has(p)){if(d(p,a))return!0}else if(n.has(p)){let u=a.indexOf(p);return i.push(...a.slice(u),p),!0}return a.pop(),n.delete(s),!1}for(let s of Object.keys(t))if(!r.has(s)){if(d(s,[]))return i}return[]}function oe(e,t=[]){if(typeof e!=="object"||e===null)return t;if(Array.isArray(e)){for(let r of e)oe(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))oe(r,t);return t}function Qe(e){let t=[],r=[],n=new TextEncoder().encode(e).length,i=51200,d=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 et(e){let t=[],r=[],n=e.Resources?Object.keys(e.Resources).length:0,i=e.Parameters?Object.keys(e.Parameters).length:0,d=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(i>200)t.push({path:"Parameters",message:`Template has ${i} parameters, exceeding the limit of 200`,severity:"error"});if(d>200)t.push({path:"Outputs",message:`Template has ${d} outputs, exceeding the limit of 200`,severity:"error"});return{valid:t.length===0,errors:t,warnings:r}}function co(e){let{domains:t,email:r,staging:n=!1,challengeType:i="http-01",certPath:d="/etc/letsencrypt/live",autoRenew:s=!0}=e,a=t[0],l=t.map((u)=>`-d ${u}`).join(" "),p=n?"--staging":"";if(i==="http-01")return tt({domains:t,email:r,staging:n,certPath:d,autoRenew:s,domainFlags:l,stagingFlag:p,primaryDomain:a});else{let u=e.dnsProvider?.provider||(e.hostedZoneId?"route53":void 0);return rt({domains:t,email:r,staging:n,certPath:d,autoRenew:s,domainFlags:l,stagingFlag:p,primaryDomain:a,hostedZoneId:e.hostedZoneId,dnsProvider:e.dnsProvider,dnsProviderType:u})}}function tt(e){let{email:t,certPath:r,autoRenew:n,domainFlags:i,stagingFlag:d,primaryDomain:s}=e;return`
223
223
  # ==========================================
224
224
  # Let's Encrypt Certificate Setup (HTTP-01)
225
225
  # ==========================================
@@ -236,28 +236,28 @@ certbot certonly \\
236
236
  --non-interactive \\
237
237
  --agree-tos \\
238
238
  --email ${t} \\
239
- ${l} \\
240
- ${o}
239
+ ${d} \\
240
+ ${i}
241
241
 
242
242
  # Check if certificate was obtained
243
- if [ -f "${r}/${c}/fullchain.pem" ]; then
243
+ if [ -f "${r}/${s}/fullchain.pem" ]; then
244
244
  echo "Certificate obtained successfully!"
245
245
 
246
246
  # Create symlinks for easier access
247
247
  mkdir -p /etc/ssl/stacks
248
- ln -sf ${r}/${c}/fullchain.pem /etc/ssl/stacks/fullchain.pem
249
- ln -sf ${r}/${c}/privkey.pem /etc/ssl/stacks/privkey.pem
250
- ln -sf ${r}/${c}/cert.pem /etc/ssl/stacks/cert.pem
251
- ln -sf ${r}/${c}/chain.pem /etc/ssl/stacks/chain.pem
248
+ ln -sf ${r}/${s}/fullchain.pem /etc/ssl/stacks/fullchain.pem
249
+ ln -sf ${r}/${s}/privkey.pem /etc/ssl/stacks/privkey.pem
250
+ ln -sf ${r}/${s}/cert.pem /etc/ssl/stacks/cert.pem
251
+ ln -sf ${r}/${s}/chain.pem /etc/ssl/stacks/chain.pem
252
252
  else
253
253
  echo "Failed to obtain certificate!"
254
254
  fi
255
255
 
256
- ${n?ie(c):"# Auto-renewal disabled"}
256
+ ${n?ae(s):"# Auto-renewal disabled"}
257
257
 
258
258
  # Restart the application
259
259
  systemctl start stacks
260
- `}function Qe(e){let{email:t,certPath:r,autoRenew:n,domainFlags:o,stagingFlag:l,primaryDomain:c,hostedZoneId:s,dnsProvider:d,dnsProviderType:h}=e;if(h==="route53"||s){if(!s)throw Error("hostedZoneId is required for DNS-01 challenge with Route53");return`
260
+ `}function rt(e){let{email:t,certPath:r,autoRenew:n,domainFlags:i,stagingFlag:d,primaryDomain:s,hostedZoneId:a,dnsProvider:l,dnsProviderType:p}=e;if(p==="route53"||a){if(!a)throw Error("hostedZoneId is required for DNS-01 challenge with Route53");return`
261
261
  # ==========================================
262
262
  # Let's Encrypt Certificate Setup (DNS-01 via Route53)
263
263
  # ==========================================
@@ -271,25 +271,25 @@ certbot certonly \\
271
271
  --non-interactive \\
272
272
  --agree-tos \\
273
273
  --email ${t} \\
274
- ${l} \\
275
- ${o}
274
+ ${d} \\
275
+ ${i}
276
276
 
277
277
  # Check if certificate was obtained
278
- if [ -f "${r}/${c}/fullchain.pem" ]; then
278
+ if [ -f "${r}/${s}/fullchain.pem" ]; then
279
279
  echo "Certificate obtained successfully!"
280
280
 
281
281
  # Create symlinks for easier access
282
282
  mkdir -p /etc/ssl/stacks
283
- ln -sf ${r}/${c}/fullchain.pem /etc/ssl/stacks/fullchain.pem
284
- ln -sf ${r}/${c}/privkey.pem /etc/ssl/stacks/privkey.pem
285
- ln -sf ${r}/${c}/cert.pem /etc/ssl/stacks/cert.pem
286
- ln -sf ${r}/${c}/chain.pem /etc/ssl/stacks/chain.pem
283
+ ln -sf ${r}/${s}/fullchain.pem /etc/ssl/stacks/fullchain.pem
284
+ ln -sf ${r}/${s}/privkey.pem /etc/ssl/stacks/privkey.pem
285
+ ln -sf ${r}/${s}/cert.pem /etc/ssl/stacks/cert.pem
286
+ ln -sf ${r}/${s}/chain.pem /etc/ssl/stacks/chain.pem
287
287
  else
288
288
  echo "Failed to obtain certificate!"
289
289
  fi
290
290
 
291
- ${n?ie(c):"# Auto-renewal disabled"}
292
- `}if(!d)throw Error("dnsProvider configuration is required for DNS-01 challenge with external DNS providers");let u=d.provider.toUpperCase(),b=Xe(d);return`
291
+ ${n?ae(s):"# Auto-renewal disabled"}
292
+ `}if(!l)throw Error("dnsProvider configuration is required for DNS-01 challenge with external DNS providers");let u=l.provider.toUpperCase(),b=nt(l);return`
293
293
  # ==========================================
294
294
  # Let's Encrypt Certificate Setup (DNS-01 via ${u})
295
295
  # ==========================================
@@ -312,7 +312,7 @@ DOMAIN="$CERTBOT_DOMAIN"
312
312
  VALIDATION="$CERTBOT_VALIDATION"
313
313
  RECORD_NAME="_acme-challenge.$DOMAIN"
314
314
 
315
- ${et(d)}
315
+ ${it(l)}
316
316
 
317
317
  # Wait for DNS propagation
318
318
  echo "Waiting 60 seconds for DNS propagation..."
@@ -331,7 +331,7 @@ DOMAIN="$CERTBOT_DOMAIN"
331
331
  VALIDATION="$CERTBOT_VALIDATION"
332
332
  RECORD_NAME="_acme-challenge.$DOMAIN"
333
333
 
334
- ${tt(d)}
334
+ ${ot(l)}
335
335
  CLEANUPHOOK
336
336
 
337
337
  chmod +x /etc/letsencrypt/hooks/cleanup-hook.sh
@@ -345,25 +345,25 @@ certbot certonly \\
345
345
  --non-interactive \\
346
346
  --agree-tos \\
347
347
  --email ${t} \\
348
- ${l} \\
349
- ${o}
348
+ ${d} \\
349
+ ${i}
350
350
 
351
351
  # Check if certificate was obtained
352
- if [ -f "${r}/${c}/fullchain.pem" ]; then
352
+ if [ -f "${r}/${s}/fullchain.pem" ]; then
353
353
  echo "Certificate obtained successfully!"
354
354
 
355
355
  # Create symlinks for easier access
356
356
  mkdir -p /etc/ssl/stacks
357
- ln -sf ${r}/${c}/fullchain.pem /etc/ssl/stacks/fullchain.pem
358
- ln -sf ${r}/${c}/privkey.pem /etc/ssl/stacks/privkey.pem
359
- ln -sf ${r}/${c}/cert.pem /etc/ssl/stacks/cert.pem
360
- ln -sf ${r}/${c}/chain.pem /etc/ssl/stacks/chain.pem
357
+ ln -sf ${r}/${s}/fullchain.pem /etc/ssl/stacks/fullchain.pem
358
+ ln -sf ${r}/${s}/privkey.pem /etc/ssl/stacks/privkey.pem
359
+ ln -sf ${r}/${s}/cert.pem /etc/ssl/stacks/cert.pem
360
+ ln -sf ${r}/${s}/chain.pem /etc/ssl/stacks/chain.pem
361
361
  else
362
362
  echo "Failed to obtain certificate!"
363
363
  fi
364
364
 
365
- ${n?ie(c):"# Auto-renewal disabled"}
366
- `}function Xe(e){switch(e.provider){case"porkbun":return`
365
+ ${n?ae(s):"# Auto-renewal disabled"}
366
+ `}function nt(e){switch(e.provider){case"porkbun":return`
367
367
  # Porkbun API credentials
368
368
  export PORKBUN_API_KEY="${e.apiKey}"
369
369
  export PORKBUN_SECRET_KEY="${e.secretKey}"
@@ -374,7 +374,7 @@ export GODADDY_API_SECRET="${e.apiSecret}"
374
374
  export GODADDY_ENV="${e.environment||"production"}"
375
375
  `;case"route53":return`
376
376
  # Route53 uses IAM role credentials
377
- `;default:return""}}function et(e){switch(e.provider){case"porkbun":return`
377
+ `;default:return""}}function it(e){switch(e.provider){case"porkbun":return`
378
378
  # Extract root domain (last two parts)
379
379
  ROOT_DOMAIN=$(echo "$DOMAIN" | awk -F. '{print $(NF-1)"."$NF}')
380
380
  SUBDOMAIN="_acme-challenge"
@@ -418,7 +418,7 @@ curl -s -X PATCH "$API_URL/v1/domains/$ROOT_DOMAIN/records" \\
418
418
  "data": "'"$VALIDATION"'",
419
419
  "ttl": 600
420
420
  }]'
421
- `;default:return'echo "Unsupported DNS provider"'}}function tt(e){switch(e.provider){case"porkbun":return`
421
+ `;default:return'echo "Unsupported DNS provider"'}}function ot(e){switch(e.provider){case"porkbun":return`
422
422
  # Extract root domain
423
423
  ROOT_DOMAIN=$(echo "$DOMAIN" | awk -F. '{print $(NF-1)"."$NF}')
424
424
 
@@ -461,7 +461,7 @@ fi
461
461
 
462
462
  curl -s -X DELETE "$API_URL/v1/domains/$ROOT_DOMAIN/records/TXT/$RECORD_NAME" \\
463
463
  -H "Authorization: sso-key $GODADDY_API_KEY:$GODADDY_API_SECRET"
464
- `;default:return'echo "Unsupported DNS provider"'}}function ie(e){return`
464
+ `;default:return'echo "Unsupported DNS provider"'}}function ae(e){return`
465
465
  # ==========================================
466
466
  # Certificate Auto-Renewal Setup
467
467
  # ==========================================
@@ -506,7 +506,7 @@ systemctl enable certbot-renewal.timer
506
506
  systemctl start certbot-renewal.timer
507
507
 
508
508
  echo "Certificate auto-renewal configured"
509
- `}function Qi(e){let{httpPort:t=80,httpsPort:r=443,certPath:n="/etc/ssl/stacks",redirectHttp:o=!0}=e;return`
509
+ `}function lo(e){let{httpPort:t=80,httpsPort:r=443,certPath:n="/etc/ssl/stacks",redirectHttp:i=!0}=e;return`
510
510
  // HTTPS Server with Let's Encrypt certificates
511
511
  import { readFileSync, existsSync } from 'node:fs'
512
512
 
@@ -532,7 +532,7 @@ if (hasCerts) {
532
532
  })
533
533
  console.log(\`HTTPS server running on port \${HTTPS_PORT}\`)
534
534
 
535
- ${o?`
535
+ ${i?`
536
536
  // Start HTTP server for redirect
537
537
  const httpServer = Bun.serve({
538
538
  port: HTTP_PORT,
@@ -592,5 +592,5 @@ async function handleRequest(request: Request): Promise<Response> {
592
592
  // Implement your request handling here
593
593
  return new Response('Hello from Stacks!')
594
594
  }
595
- `}async function Xi(e){let{domain:t,challengeValue:r,hostedZoneId:n,dnsProvider:o,region:l="us-east-1"}=e;if(o){let s=await q(o).upsertRecord(t,{name:`_acme-challenge.${t}`,type:"TXT",content:r,ttl:60});if(!s.success)throw Error(`Failed to create DNS challenge record: ${s.message}`);return}if(n){await new j(l).changeResourceRecordSets({HostedZoneId:n,ChangeBatch:{Comment:"ACME DNS-01 challenge",Changes:[{Action:"UPSERT",ResourceRecordSet:{Name:`_acme-challenge.${t}`,Type:"TXT",TTL:60,ResourceRecords:[{Value:`"${r}"`}]}}]}});return}throw Error("Either dnsProvider or hostedZoneId must be provided")}async function eo(e){let{domain:t,challengeValue:r,hostedZoneId:n,dnsProvider:o,region:l="us-east-1"}=e;if(o){let s=await q(o).deleteRecord(t,{name:`_acme-challenge.${t}`,type:"TXT",content:r});if(!s.success)console.warn(`Failed to delete DNS challenge record: ${s.message}`);return}if(n){await new j(l).changeResourceRecordSets({HostedZoneId:n,ChangeBatch:{Comment:"Remove ACME DNS-01 challenge",Changes:[{Action:"DELETE",ResourceRecordSet:{Name:`_acme-challenge.${t}`,Type:"TXT",TTL:60,ResourceRecords:[{Value:`"${r}"`}]}}]}});return}throw Error("Either dnsProvider or hostedZoneId must be provided")}function to(e){try{let{execSync:t}=Je("node:child_process"),r=t(`openssl x509 -checkend 2592000 -noout -in ${e}/cert.pem`,{encoding:"utf-8",stdio:["pipe","pipe","pipe"]});return!1}catch{return!0}}import{createHash as we,createSign as rt,generateKeyPairSync as ve}from"node:crypto";var Oe={production:"https://acme-v02.api.letsencrypt.org/directory",staging:"https://acme-staging-v02.api.letsencrypt.org/directory"};class nt{directoryUrl;email;accountKey;accountUrl=null;directory=null;nonce=null;constructor(e){this.directoryUrl=e.staging?Oe.staging:Oe.production,this.email=e.email,this.accountKey=e.accountKey||this.generateAccountKey()}generateAccountKey(){let{privateKey:e}=ve("ec",{namedCurve:"P-256"});return e.export({type:"pkcs8",format:"pem"})}async getDirectory(){if(this.directory)return this.directory;let e=await fetch(this.directoryUrl);if(!e.ok)throw Error(`Failed to fetch ACME directory: ${e.status}`);return this.directory=await e.json(),this.directory}async getNonce(){if(this.nonce){let n=this.nonce;return this.nonce=null,n}let e=await this.getDirectory(),r=(await fetch(e.newNonce,{method:"HEAD"})).headers.get("replay-nonce");if(!r)throw Error("Failed to get nonce from ACME server");return r}getJwk(){let e=this.accountKey.split(`
596
- `).filter((l)=>!l.startsWith("-----")).join(""),t=Buffer.from(e,"base64"),r=t.length-65,n=t.subarray(r+1,r+33),o=t.subarray(r+33,r+65);return{kty:"EC",crv:"P-256",x:this.base64UrlEncode(n),y:this.base64UrlEncode(o)}}getJwkThumbprint(){let e=this.getJwk(),t=JSON.stringify({crv:e.crv,kty:e.kty,x:e.x,y:e.y}),r=we("sha256").update(t).digest();return this.base64UrlEncode(r)}base64UrlEncode(e){return(typeof e==="string"?Buffer.from(e):e).toString("base64").replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async signPayload(e,t){let r=await this.getNonce(),n=this.getJwk(),o={alg:"ES256",nonce:r,url:e};if(this.accountUrl)o.kid=this.accountUrl;else o.jwk=n;let l=this.base64UrlEncode(JSON.stringify(o)),c=t===""?"":this.base64UrlEncode(JSON.stringify(t)),s=`${l}.${c}`,d=rt("SHA256");d.update(s);let h=d.sign(this.accountKey),u=h.subarray(4,4+h[3]),b=4+h[3]+2,A=h.subarray(b,b+h[b-1]),T=Buffer.alloc(32),g=Buffer.alloc(32);u.copy(T,32-u.length),A.copy(g,32-A.length);let m=Buffer.concat([T,g]);return JSON.stringify({protected:l,payload:c,signature:this.base64UrlEncode(m)})}async acmeRequest(e,t){let r=await this.signPayload(e,t),n=await fetch(e,{method:"POST",headers:{"Content-Type":"application/jose+json"},body:r}),o=n.headers.get("replay-nonce");if(o)this.nonce=o;let l,c=n.headers.get("content-type");if(c?.includes("application/json")||c?.includes("application/problem+json"))l=await n.json();else l=await n.text();if(!n.ok)throw Error(`ACME request failed: ${JSON.stringify(l)}`);return{body:l,headers:n.headers}}async registerAccount(){let e=await this.getDirectory(),{body:t,headers:r}=await this.acmeRequest(e.newAccount,{termsOfServiceAgreed:!0,contact:[`mailto:${this.email}`]}),n=r.get("location");if(!n)throw Error("No account URL returned");return this.accountUrl=n,n}async createOrder(e){if(!this.accountUrl)await this.registerAccount();let t=await this.getDirectory(),{body:r,headers:n}=await this.acmeRequest(t.newOrder,{identifiers:e.map((l)=>({type:"dns",value:l}))}),o=n.get("location");if(!o)throw Error("No order URL returned");return{orderUrl:o,authorizations:r.authorizations,finalize:r.finalize}}async getAuthorization(e){let{body:t}=await this.acmeRequest(e,""),r=t.identifier.value,n=this.getJwkThumbprint(),o=t.challenges.filter((l)=>l.type==="http-01"||l.type==="dns-01").map((l)=>{let c=`${l.token}.${n}`;if(l.type==="http-01")return{type:"http-01",token:l.token,keyAuthorization:c,identifier:`/.well-known/acme-challenge/${l.token}`};else{let s=this.base64UrlEncode(we("sha256").update(c).digest());return{type:"dns-01",token:l.token,keyAuthorization:c,identifier:`_acme-challenge.${r}`,dnsValue:s}}});return{domain:r,challenges:o}}async respondToChallenge(e){await this.acmeRequest(e,{})}async waitForAuthorization(e,t=30){for(let r=0;r<t;r++){let{body:n}=await this.acmeRequest(e,"");if(n.status==="valid")return;if(n.status==="invalid")throw Error(`Authorization failed: ${JSON.stringify(n)}`);await new Promise((o)=>setTimeout(o,2000))}throw Error("Authorization timed out")}generateCsr(e){let{privateKey:t}=ve("rsa",{modulusLength:2048}),r=t.export({type:"pkcs8",format:"pem"});return{csr:this.createSimpleCsr(e,t),privateKey:r}}createSimpleCsr(e,t){throw Error("CSR generation requires additional implementation. Consider using the shell-based certbot approach instead.")}async finalizeOrder(e,t){let{csr:r,privateKey:n}=this.generateCsr(t),{body:o}=await this.acmeRequest(e,{csr:this.base64UrlEncode(Buffer.from(r,"base64"))}),l=o.certificate;if(!l)throw Error("Certificate not immediately available - polling not implemented");let s=await(await fetch(l)).text(),d=s.split(/(?=-----BEGIN CERTIFICATE-----)/g),h=d[0],u=d.slice(1).join("");return{certificate:h,privateKey:n,chain:u,fullchain:s,expiresAt:new Date(Date.now()+7776000000)}}getAccountKey(){return this.accountKey}}var Ne=["js","mjs","cjs","css","map","woff","woff2","ttf","otf","eot","png","jpg","jpeg","gif","webp","avif","svg","ico","mp4","webm","ogg","mp3","wav","pdf","wasm"];function oe(e){return`"${e.replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}"`}function ke(e){return`{${e.map(oe).join(" ")}}`}function ae(e){if(e.length===1)return`http.host eq ${oe(e[0])}`;return`http.host in ${ke(e)}`}function se(e,t={}){if(t.enabled===!1||e.length===0)return[];let r=ae(e),n=[],o=t.bypassPaths??[],l=o.length>0?`(${o.map((h)=>`starts_with(http.request.uri.path, ${oe(h)})`).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??Ne,d=s.length>0?`lower(http.request.uri.path.extension) in ${ke([...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 N=(e)=>e===void 0?void 0:e?"on":"off";function le(e){let t={ssl:e.ssl,always_use_https:N(e.alwaysUseHttps),automatic_https_rewrites:N(e.automaticHttpsRewrites),min_tls_version:e.minTlsVersion,tls_1_3:N(e.tls13),brotli:N(e.brotli),http3:N(e.http3),"0rtt":N(e.zeroRtt),early_hints:N(e.earlyHints),browser_cache_ttl:e.browserCacheTtl,always_online:N(e.alwaysOnline),websockets:N(e.websockets),email_obfuscation:N(e.emailObfuscation)};if(e.hsts)t.security_header={strict_transport_security:{enabled:e.hsts.enabled,max_age:e.hsts.maxAge??31536000,include_subdomains:e.hsts.includeSubdomains??!1,preload:e.hsts.preload??!1,nosniff:e.hsts.noSniff??!0}};for(let r of Object.keys(t))if(t[r]===void 0)delete t[r];return{...t,...e.raw??{}}}var W={ssl:"strict",alwaysUseHttps:!0,automaticHttpsRewrites:!0,minTlsVersion:"1.2",tls13:!0,brotli:!0,http3:!0,earlyHints:!0,alwaysOnline:!0,emailObfuscation:!1,browserCacheTtl:0};import{connect as it}from"node:tls";async function de(e){let{address:t,serverName:r,port:n=443,timeoutMs:o=5000}=e;return new Promise((l)=>{let c=!1,s=(h)=>{if(c)return;c=!0;try{d.destroy()}catch{}l(h)},d=it({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",(h)=>{s({reachable:!1,trusted:!1,reason:h.message})})})}function ot(e,t){let r=t.replace(/\.$/,"").toLowerCase();return e.some((n)=>{let o=n.replace(/\.$/,"").toLowerCase();if(o===r)return!0;if(!o.startsWith("*."))return!1;let l=o.slice(2);if(!r.endsWith(`.${l}`))return!1;return!r.slice(0,r.length-l.length-1).includes(".")})}async function at(e){let{provider:t,zone:r,hosts:n,ipv4:o,ipv6:l,proxied:c=!0,settings:s=W,cache:d,originGuard:h,purge:u=!0,ttl:b=300,skipOriginProbe:A=!1,skipEdgeCertificateCheck:T=!1}=e,g={records:[],settingsChanged:[],cacheRules:0,originGuard:!1,purged:!1,deferredProxy:[],warnings:[]};if(n.length===0)return g;let m=[],a=c&&!T?await t.listEdgeCertificateHosts(r):null;for(let i of n){let p=c;if(p&&a&&!ot(a,i)){p=!1;let C=a.length===0?"the zone has no active edge certificate yet":`no active edge certificate covers it (${a.join(", ")})`;g.deferredProxy.push({host:i,reason:C}),g.warnings.push(`${i}: publishing DNS-only — ${C}. Proxying it would make Cloudflare terminate TLS with no certificate for the name, which fails the handshake outright rather than degrading. Universal SSL covers the apex and ONE level of subdomain, so a deeper name needs its own certificate; otherwise re-run the deploy once the certificate is active.`)}if(p&&!A){let C=await de({address:o,serverName:i});if(!C.trusted){p=!1;let S=C.reason||"origin is not serving a trusted certificate";g.deferredProxy.push({host:i,reason:S}),g.warnings.push(`${i}: publishing DNS-only for now — the origin does not yet serve a certificate this proxy can verify (${S}). The origin issues certificates over HTTP-01, which needs the name to reach it directly; re-run the deploy once it has one and the record will be proxied.`)}}if(p)m.push(i);let f=[{type:"A",content:o}];if(l&&ue(i))f.push({type:"AAAA",content:l});for(let{type:C,content:S}of f){let R=await t.upsertRecord(r,{name:i,type:C,content:S,ttl:b,proxied:p});if(R.success)g.records.push({host:i,type:C,content:S,proxied:p});else g.warnings.push(`${i} ${C} → ${S} failed: ${R.message||"unknown provider error"}`)}}if(m.length===0){if(c)g.warnings.push("No host is proxied yet, so zone settings, cache rules and purge were skipped — they only take effect through the proxy.");return g}try{let i=le(s),p=await t.applyZoneSettings(r,i);g.settingsChanged=p.changed;for(let f of p.failed)g.warnings.push(`zone setting '${f.id}' could not be applied: ${f.error}`)}catch(i){g.warnings.push(`zone settings could not be read: ${i instanceof Error?i.message:String(i)}`)}let y=se(m,d);if(y.length>0){let i=await t.putManagedPhaseRules(r,"http_request_cache_settings",y);if(i.success)g.cacheRules=y.length;else g.warnings.push(`cache rules could not be written: ${i.message}`)}if(h){let i=ce(m,h.header,h.value);if(i.length>0){let p=await t.putManagedPhaseRules(r,"http_request_late_transform",i);if(p.success)g.originGuard=!0;else g.warnings.push(`origin guard header could not be written: ${p.message}. `+"The gateway will reject requests that lack it — disable the guard or grant the token Transform Rules: Edit.")}}if(u){if(g.purged=await t.purgeCache(r,{hosts:m}),!g.purged)g.warnings.push("edge cache purge failed — new content may take until TTL expiry to appear.")}return g}var st=(e)=>process.env[e];function xe(e,t){let r=e.replace(/\.$/,"").toLowerCase();if(t){let n=t.replace(/\.$/,"").toLowerCase();if(r===n||r.endsWith(`.${n}`))return n}return r.split(".").slice(-2).join(".")}function ct(e,t={}){let r=t.env??st,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,h=new Set(s.map((A)=>xe(A,d)));if(h.size>1)return o.push(`Fronted hosts span more than one zone (${[...h].join(", ")}). A Cloudflare zone is configured as a unit, so run one CDN config per zone.`),{plan:null,errors:o};let u=n.cloudflare??{},b=n.secret?{header:n.secretHeader??"X-Origin-Verify",value:n.secret}:void 0;return{plan:{zone:[...h][0],hosts:s,apiToken:l,zoneId: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:b,purge:u.purgeOnDeploy!==!1,skipOriginProbe:u.skipOriginProbe===!0},errors:o}}export{Pu as ABTestManager,fr as ACMClient,gr as ACMDnsValidator,Oe as ACME_DIRECTORIES,M as AI,Nf as API_IDEMPOTENCY_TTL_MS,vf as API_TOKEN_DEFAULT_TTL_MS,Of as API_TOKEN_MAX_TTL_MS,My as API_VERSION,hf as AUTHORIZATION_CAPABILITIES,rf as AUTH_ACTION_TOKEN_TTL_MS,nf as AUTH_MFA_CHALLENGE_TTL_MS,of as AUTH_OIDC_TRANSACTION_TTL_MS,tf as AUTH_SESSION_ABSOLUTE_TTL_MS,ef as AUTH_SESSION_IDLE_TTL_MS,Lc as AWSAPIError,St as AWSClient,Le as AWSCloudFormationClient,Me as AWSCloudFrontClient,mu as AWSConfigManager,ws as AWS_PSEUDO_PARAMETERS,$d as AWS_REGIONS,nt as AcmeClient,Pt as AlertEvaluator,$t as AlertStore,zh as AnomalyConfigStore,Pe as ApiGateway,Oy as ApiServiceError,zr as ApplicationAutoScalingClient,Es as Arn,Ts as AssetHasher,bs as Auth,af as AuthenticationStore,ky as AutomationApiService,kf as AutomationIdentityStore,XC as AwsAuroraDataAdapter,iS as AwsAuroraTransport,JS as AwsDatabaseBackupSource,yn as AwsDriver,eS as AwsElastiCacheDataAdapter,oS as AwsElastiCacheTransport,Zy as AwsIamCapabilityScanner,oA as AwsInfrastructureBackupSource,QC as AwsRdsDataAdapter,nS as AwsRdsTransport,DS as AwsRegionalDriver,dA as AwsSecretsManagerConfigurationBackend,Ey as AwsSpendTransport,uA as AwsSsmConfigurationBackend,jS as BackupCoordinator,lu as BackupManager,HS as BackupStore,Wp as BatchProcessingManager,Or as BedrockClient,vr as BedrockRuntimeClient,Ng as BitbucketSourceAdapter,bu as BlueGreenManager,Pp as BounceComplaintHandler,tp as BuildOptimizationManager,aS as BunDockerRuntime,rA as BunDockerVolumeRuntime,XS as BunFilesystemArchiveRuntime,us as CDN,dt as CHAIN_HEADER,Jt as CLOUDFLARE_MANAGED_RULE_PREFIX,Hd as COMMON_CROSS_ACCOUNT_ROLES,ff as CONTROL_PLANE_SCHEMA_VERSION,re as Cache,Tu as CanaryManager,qu as CertificateManager,fg as CloudBlockVolumeDriver,$n as CloudDriverFactory,vc as CloudError,vs as CloudFormationBuilder,Le as CloudFormationClient,Me as CloudFrontClient,gu as CloudTrailManager,Tr as CloudWatchLogsClient,Yt as CloudflareProvider,ud as CommandHistory,Is as Communication,Cg as ComposeApplicationService,yg as ComposeApplicationStore,Nr as ComprehendClient,w as Compute,wy as ComputeSpendTransport,Oc as ConfigurationError,mA as ConfigurationService,aA as ConfigurationStore,$r as ConnectClient,rS as ContainerDataAdapter,np as ContainerRegistryManager,iA as ControlPlaneBackupSource,BS as ControlPlaneCleanupDriver,Ef as ControlPlaneStore,fh as CounterTracker,Nc as CredentialError,hd as CrossRegionReferenceManager,Js as DASHBOARD_ENTRY,Ys as DASHBOARD_PORT_BASE,Qs as DASHBOARD_PORT_SPAN,qs as DASHBOARD_STATE_DIR,ii as DEFAULT_ATTACK_MODE_HOURS,vt as DEFAULT_DDOS_THRESHOLDS,uh as DEFAULT_METER_MAPPINGS,rh as DEFAULT_PRICE_BOOK,mt as DEFAULT_RECURSION_LIMITS,Uc as DEFAULT_SERVICE_LIMITS,ka as DEFAULT_STATE_DIR,Ne as DEFAULT_STATIC_ASSET_EXTENSIONS,ay as DEFAULT_TELEMETRY_POLICY,Ch as DEFAULT_THRESHOLDS,rg as DEPLOYMENT_QUEUE_KINDS,lt as DEPTH_HEADER,Hh as DETECTABLE_SIGNALS,wC as DIAGNOSTIC_PRESETS,_p as DLQMonitoringManager,ps as DNS,bp as DNSSECManager,JC as DataServiceLifecycle,jC as DataServiceStore,U as Database,Hu as DatabaseUserManager,_c as DebugLogger,ss as DependencyGraph,Rs as Deployment,kc as DeploymentError,uu as DisasterRecoveryManager,pr as DnsProviderFactory,sS as DockerDataTransport,AC as DockerDiscoveryAdapter,pg as DockerNamedVolumeDriver,nA as DockerVolumeBackupSource,Qf as DurableOperationQueue,Xf as DurableQueueWorker,Dr as DynamoDBClient,Kt as EC2Client,hr as ECRClient,yr as ECSClient,Ur as EFSClient,Pr as ELBv2Client,Zg as ENFORCEMENT_ACTIONS,Dh as ENFORCEMENT_DESCRIPTIONS,jg as ENFORCEMENT_SEVERITY,$C as EcsRuntimeAdapter,ei as EdgeRateLimiter,Br as ElastiCacheClient,L as Email,kp as EmailAdvanced,Dp as EmailAnalyticsManager,Tt as EmailClient,xp as EmailHandlers,Op as EmailTemplateManager,cS as EncryptedDataSecretStore,Mc as ErrorCodes,_r as EventBridgeClient,zC as EventBridgeJobAdapter,pA as ExternalConfigurationBackend,Fp as FIFOQueueManager,jh as FOCUS_VERSION,Jc as FileCache,K as FileSystem,eA as FilesystemBackupSource,mS as FleetService,pS as FleetStore,Ds as Fn,kg as GiteaSourceAdapter,vg as GithubSourceAdapter,Og as GitlabSourceAdapter,yd as GlobalResourceManager,qt as GoDaddyProvider,yu as GuardDutyManager,al as HashCache,Fm as HealthCheckManager,Et as HealthCheckRunner,Cn as HetznerClient,Rn as HetznerDriver,At as IAMClient,Jr as IPV6_EXCLUDED_HOST_LABELS,Xu as ImageScanningManager,ze as InfrastructureGenerator,Rf as InvalidOperationTransitionError,gs as JobLoader,HC as JobProviderReconciler,KC as JobService,_C as JobStore,Vr as KendraClient,Dm as LARAVEL_SERVERLESS_BUILD_STEPS,Rr as LambdaClient,up as LambdaConcurrencyManager,yp as LambdaDLQManager,mp as LambdaDestinationsManager,sp as LambdaLayersManager,PC as LambdaRuntimeAdapter,gp as LambdaVPCManager,lp as LambdaVersionsManager,lA as LocalEncryptedConfigurationBackend,tA as LogicalDatabaseBackupSource,ku as LogsManager,Yp as MANAGED_NODE_VERSIONS,Bn as MANAGEMENT_DASHBOARD_SITE,nc as MANAGEMENT_DASHBOARD_SITE_PREFIX,ni as MAX_CONTROL_HOURS,If as MAX_CONTROL_PLANE_ERROR_BYTES,Pf as MAX_CONTROL_PLANE_JSON_BYTES,Ug as METERS,Kg as METER_KEYS,qg as MICRO_CENTS,Th as MIN_PROJECTION_CONFIDENCE,en as MTA_STS_PORT,FS as MaintenanceService,LS as MaintenanceStore,Ss as Messaging,Ou as MetricsManager,Fu as MigrationManager,vl as MockCloudFormation,Nl as MockDynamoDB,Ol as MockS3,Ie as Monitoring,Fd as MultiAccountManager,fd as MultiRegionManager,ql as MultiStepProgress,Re as Network,_m as NetworkSecurityManager,Dt as NotificationRouter,Er as OpenSearchClient,bf as OptimisticConcurrencyError,Vd as OrganizationManager,wm as PHP_DEFAULT_EXCLUDES,rm as PHP_LAYER_EXTENSIONS,Zt as PROXIABLE_RECORD_TYPES,Ps as ParameterStore,Wu as PerformanceManager,$e as Permissions,Fr as PersonalizeClient,fs as Phone,Lp as PhoneAdvanced,ms as PhoneHandlers,yS as PlacementService,hS as PlacementStore,Lr as PollyClient,jt as PorkbunProvider,Wy as PreDeployScanner,xl as PreviewEnvironmentManager,tg as PreviewEnvironmentService,eg as PreviewEnvironmentStore,_l as PreviewNotificationService,jl as ProgressBar,Du as ProgressiveDeploymentManager,oi as ProtectionControlStore,qa as Pseudo,te as Queue,qf as QueueCancellationError,Hp as QueueManagementManager,Oa as QueuePresets,Jf as QueueTimeoutError,Jn as RATE_LIMIT_KEY_SEPARATOR,Ir as RDSClient,Wd as RECOMMENDED_ACCOUNT_STRUCTURES,zd as RECOMMENDED_SCPS,Ig as RELEASE_QUEUE_KINDS,cd as REPL,dd as REPLCommandBuilder,ld as REPLContext,ml as RateLimiter,Na as RealtimePresets,oy as RecordingSpendTransport,ht as RecursionGuard,Z as Redirects,Cd as RegionPairManager,PS as RegionService,$S as RegionStore,ds as Registry,kr as RekognitionClient,Rg as ReleaseService,bg as ReleaseStore,CS as RemoteBuildService,_u as ReplicaManager,Wm as ResourceManagementManager,Yf as RetryableOperationError,j as Route53Client,Ut as Route53DomainsClient,rr as Route53Provider,Tp as Route53ResolverManager,Sp as Route53RoutingManager,vC as RuntimeOperationService,OC as RuntimeStreamRegistry,ZS as S3BackupDestinationAdapter,bt as S3Client,Ec as S3Error,By as SECRET_PATTERNS,Bh as SENSITIVITY_THRESHOLDS,Rt as SESClient,Cs as SMS,Ar as SNSClient,Iy as SPEND_CYCLE_SECONDS,ey as SPEND_GATE_SETTING,Ty as SPEND_LEASE_SETTING,br as SQSClient,Cr as SSMClient,xa as STATE_DIR_ENV_VAR,W as STATIC_SITE_ZONE_SETTINGS,Vt as STSClient,Wr as SchedulerClient,De as Search,Ky as SecretFindingScanner,$s as Secrets,Zu as SecretsManager,Sr as SecretsManagerClient,Ku as SecretsRotationManager,ee as Security,Su as SecurityHubManager,_y as SecurityPostureStore,Gy as SecurityScannerRunner,Yu as SecurityScanningManager,wp as SenderReputationManager,WC as ServerCronJobAdapter,tS as ServerDataAdapter,mg as ServerPathVolumeDriver,op as ServiceMeshManager,Te as Sftp,Kh as SignalSource,Mp as SmsAdvanced,Hr as SmsClient,ys as SmsHandlers,Eg as SourceConnectionStore,wg as SourceProviderError,ry as SpendCapError,ty as SpendGate,$y as SpendLoopLease,Ry as SpendNotificationRouter,Py as SpendRunner,Qh as SpendService,Sh as SpendStore,Jl as Spinner,dS as SshFleetDriver,Sd as StackDependencyManager,hs as StacksIntegration,km as StaticSiteManager,X as Storage,Lm as StorageAdvancedManager,Kr as SupportClient,Lu as SyntheticsManager,lS as SystemFleetSshTransport,TC as SystemdDiscoveryAdapter,ut as TRACE_HEADER,Yl as TaskList,Cy as TelemetryStore,Se as TemplateBuilder,Yc as TemplateCache,xr as TextractClient,wr as TranscribeClient,Mr as TranslateClient,WS as TransportDisasterRecoveryDriver,_S as TransportPlatformMaintenanceDriver,AS as TransportRemoteBuildDriver,Uy as TrivyImageScanner,xf as TsCloudApiError,Lf as TsCloudClient,Sy as URGENT_SPEND_EVENTS,Eh as USER_VISIBLE_ACTIONS,ES as UnavailableRegionalDriver,sr as UnifiedDnsValidator,Tf as UnsupportedSchemaVersionError,xc as ValidationError,Gr as VoiceClient,dg as VolumeService,og as VolumeStore,As as Workflow,wu as XRayManager,Iu as abTestManager,$g as activateImmutableRelease,mC as ageSeconds,hh as aggregateDeltas,cs as analyzeStackDiff,_h as anomalyOptionsForSignal,ci as applyControlsToDdos,si as applyControlsToRateLimits,Ft as applyMitigationFactor,or as applyZoneMigration,qp as artifactKey,Ag as assertReleaseStrategy,ny as assertSpendAllows,Xy as attachProvenanceToRelease,Jy as attachSbomToRelease,Yy as attachVulnerabilitySummary,cf as authEncryptionKeyFile,Sf as authorizeOrganization,EC as authorizeRuntimePath,nd as autocomplete,fu as awsConfigManager,US as backupCredentialStatus,du as backupManager,cl as batch,zp as batchProcessingManager,pf as beginOidcAuthorization,Ru as blueGreenManager,Ip as bounceComplaintHandler,sh as budgetWindow,Si as buildAndPushServerlessImage,lm as buildBunRuntimeLayerZip,Os as buildCloudFormationTemplate,Zf as buildComposeLogsCommand,Kf as buildComposeRuntimeCommand,Uf as buildComposeScaleCommand,jf as buildComposeShellCommand,bi as buildFunctionEnv,_n as buildHostCleanupScript,Za as buildMailEnv,Kn as buildManagementDashboardArtifact,Fi as buildMediaCdnPlan,Xr as buildMtaStsPolicy,tn as buildMtaStsServer,cm as buildNodeRuntimeLayerZip,rp as buildOptimizationManager,ce as buildOriginGuardRule,Em as buildPhpRuntimeLayerZip,Fn as buildSiteDeployScript,In as buildSshArgs,se as buildStaticSiteCacheRules,Vn as buildStaticSiteDeployScript,fC as bytes,$u as canaryManager,wS as canonicalJson,dC as capabilities,gS as capacity,Sl as categorizeChanges,Ju as certificateManager,Hc as checkIAMPermissions,gm as checkInvocation,Zc as checkServiceQuotas,fl as chunk,eo as cleanupDns01Challenge,Da as clearSigningKeyCache,_g as cloneSourceBinding,Rl as cloudConfigSchema,Pn as cloudDrivers,hu as cloudTrailManager,Om as collectPhpAppEntries,Zr as collectServerDnsDomains,hg as completeComposeVolumeDeletion,mf as completeOidcAuthorization,lc as composePresets,Gf as composeProjectName,tm as composeServerlessAppTemplate,vy as compositeSpendTransport,YS as compressBackup,Um as config,qC as connectionGuidance,ip as containerRegistryManager,$f as controlPlaneDatabaseFile,gf as controlPlaneMigrations,Vs as createApiBackendPreset,Vy as createApiV1Handler,TS as createAsgBuildDriver,qS as createBackupQueueHandlers,Rm as createCliHandler,Tn as createCloudDriver,Ce as createCloudFrontPolicy,$c as createCredentialProvider,js as createDashboardSite,Hs as createDataPipelinePreset,YC as createDataServiceQueueHandlers,ig as createDeploymentQueueHandlers,q as createDnsProvider,RS as createEcsBuildDriver,iy as createEnforcementHandlers,Vc as createError,Ms as createExistingStaticFullStackPreset,uS as createFleetQueueHandlers,Fs as createFullStackAppPreset,lr as createGoDaddyValidator,Tm as createHandlers,Am as createHttpHandler,Bs as createJamstackPreset,UC as createJobQueueHandlers,Us as createLaravelPreset,Gs as createMLApiPreset,VS as createMaintenanceQueueHandlers,xi as createMediaAccessToken,Ws as createMicroservicesPreset,kl as createMockAWS,ks as createNodeJsServerPreset,xs as createNodeJsServerlessPreset,Gt as createObjectStorageClient,cr as createPorkbunValidator,dc as createPreset,Aa as createPresignedUrl,ba as createPresignedUrlAsync,bm as createQueueHandler,zs as createRealtimeAppPreset,IS as createRegionQueueHandlers,Qy as createReleaseProvenance,Dg as createReleaseQueueHandlers,SS as createRemoteBuildQueueHandlers,dr as createRoute53Validator,IC as createRuntimeAdapters,wc as createS3Client,bS as createServerBuildDriver,Zs as createServerlessLaravelPreset,Ls as createServerlessNodePreset,xg as createSourceAdapter,Ns as createStaticSitePreset,Ks as createTraditionalWebAppPreset,ug as createVolumeQueueHandlers,_s as createWordPressPreset,Kp as createZip,Ad as crossRegionReferenceManager,Ei as dashboardActions,Wn as dashboardCredentialsFile,ZC as dataServiceCapabilities,Gu as databaseUserManager,jm as decodeBase32,QS as decompressBackup,KS as decryptBackup,Hm as defaultConfig,$l as defaultLocalConfig,ri as defaultRateLimitRules,hi as deleteStaticSite,Zn as deployAllComputeSites,Ri as deployServerlessApp,Ci as deploySite,Un as deploySiteRelease,mi as deployStaticSite,yi as deployStaticSiteFull,di as deployStaticSiteWithExternalDns,ui as deployStaticSiteWithExternalDnsFull,za as deploymentCoexistenceError,Xs as deriveManagementDashboardPort,ai as describePosture,BC as desiredJobProviderState,Fh as detectAnomalies,Ba as detectDeploymentTargets,ur as detectDnsProvider,Vh as detectLatestAnomaly,Wc as detectMisconfigurations,ya as detectServiceRegion,Vf as diffCompose,hl as diffTemplates,Vg as discoverGitRefs,uf as discoverOidcProvider,gC as discoverRuntimeInventory,Bp as dlqMonitoringManager,mr as dnsProviders,Rp as dnssecManager,SC as dockerWorkloads,OS as documentDigest,pu as drManager,hC as ecsWorkloads,Af as effectiveCapabilities,Ep as emailAnalyticsManager,Np as emailTemplateManager,Zm as encodeBase32,GS as encryptBackup,rC as ensureDefaultSecurityPolicies,kn as ensureFirewall,Gn as ensureManagementDashboard,xn as ensureServer,Nn as ensureSshKey,dn as escapeSecLang,Ph as evaluateBudget,wt as evaluateTelemetryAlertRules,FC as eventBridgeScheduleInput,Cm as eventToRequest,Mh as ewma,Ff as exportCompose,nr as exportRoute53Zone,cc as extendPreset,Vp as fifoQueueManager,ol as findChangedFiles,ph as findMapping,Yg as findPriceEntry,Zd as formatAccountStructure,Gl as formatBytes,Ay as formatCents,ls as formatDiff,Kl as formatDuration,od as formatFlagSuggestions,pd as formatHistory,md as formatHistoryStats,Zl as formatKeyValue,Ul as formatList,Hl as formatProgressBar,xd as formatRegion,Ld as formatRegionList,Hy as formatScanResults,Xl as formatSuggestion,Wl as formatTable,Rh as formatTimeToExhaustion,zl as formatTree,Ac as fromEC2Metadata,bc as fromECSMetadata,Cc as fromEnvironment,Sc as fromSharedCredentials,Rc as fromWebIdentity,pt as functionFingerprint,pe as gatewayHostnames,am as generateAppImageDockerfile,su as generateApprovalConfig,Up as generateBootstrap,Fl as generateCleanupWorkflow,Vl as generateCostReportWorkflow,Kd as generateCrossAccountRoleCF,jy as generateCycloneDxSbom,iu as generateDeploymentConfig,Xd as generateDeploymentPipeline,jd as generateDeploymentWorkflow,li as generateExternalDnsStaticSiteTemplate,Qi as generateHttpsServerCode,qy as generateImageSbom,Yi as generateLetsEncryptUserData,be as generateLogicalId,nu as generateManualPipeline,Qd as generateMatrixWorkflow,ou as generateMultiEnvConfig,eu as generateMultiEnvPipeline,qd as generateMultiEnvWorkflow,Jd as generatePRPreviewWorkflow,cu as generateParallelConfig,$m as generatePhpFpmConfig,om as generatePhpLayerDockerfile,tu as generatePreviewPipeline,Ml as generatePreviewWorkflow,Ae as generateResourceName,au as generateScheduledConfig,ru as generateScheduledPipeline,Yd as generateScheduledWorkflow,pi as generateStaticSiteTemplate,hn as generateUbuntuAppCloudInit,Dc as getAccountId,Id as getAllRegions,Od as getClosestRegion,ad as getCommandUsage,Bf as getComposeTemplate,Gm as getConfig,td as getContextualHelp,Tc as getCredentials,Al as getDeploymentStrategy,bl as getDiffStats,yl as getDiffSummary,Fc as getErrorDetails,Pl as getLocalConfig,El as getLocalCredentials,Dl as getLocalEndpoint,wl as getLocalEnvVars,jc as getQuotaUsageSummary,Gd as getRecommendedStructure,Pd as getRegion,Md as getRegionStats,Ed as getRegionsByCompliance,Dd as getRegionsByLocation,wd as getRegionsByPricingTier,Gc as getRequiredPermissions,Ea as getSigningKeyCacheSize,Ja as getTimestamp,Yn as globMatches,pn as globToRegex,bd as globalResourceManager,$h as governingLimitCents,Cu as guardDutyManager,xy as handleSpendRequest,ln as hasAutoWwwVariant,rc as hasManagementDashboardSite,nn as hasProxyUpstream,tl as hashBuffer,rl as hashDirectory,Xc as hashFile,nl as hashManifest,el as hashString,Vm as healthCheckManager,ue as hostAcceptsIpv6,ae as hostCondition,qm as hotp,lh as hourBucket,dh as hourBucketsBetween,ep as imageScanningManager,Ai as infraEnvFromOutputs,gt as inspectInvocation,pm as installRecursionFetch,gi as invalidateCache,dm as invocationContext,ed as isLikelyTypo,Il as isLocalDevelopment,oc as isManagementDashboardSiteName,wa as isNodeCryptoAvailable,Nh as isOperationAllowed,It as isQuietHours,un as isSafePattern,_a as isStatePath,Ot as isValidCidr,vd as isValidRegion,nh as isValidTimeZone,va as isWebCryptoAvailable,LC as jobProviderCapability,Bt as keyMatchesFilters,pp as lambdaConcurrencyManager,Cp as lambdaDLQManager,fp as lambdaDestinationsManager,cp as lambdaLayersManager,hp as lambdaVPCManager,dp as lambdaVersionsManager,yC as lambdaWorkloads,Im as laravelServerlessEnvDefaults,_f as listComposeTemplates,zg as listSourceReferences,Km as loadCloudConfig,ly as loadTelemetryPolicy,xu as logsManager,Zh as lookbackHoursForSignal,Ga as mailEnabled,Ua as mailFirewallPorts,MS as maintenanceWindowOpen,Ra as makeAWSRequest,$a as makeAWSRequestAsync,Ta as makeAWSRequestOnce,ic as managementDashboardSiteName,vS as manifestDigest,Qm as matchTotpCounter,Mi as mediaObjectHeaders,kh as median,xh as medianAbsoluteDeviation,Ih as mergeDecisions,uc as mergeInfrastructure,th as mergePriceBooks,gh as meterTelemetry,Nu as metricsManager,Wt as migrateObjectStorage,Vu as migrationManager,_d as multiAccountManager,gd as multiRegionManager,to as needsRenewal,Bm as networkSecurityManager,kC as nextScheduleRuns,qr as normalizePublicIpv6,uC as normalizeRuntimeStatus,NC as normalizeScheduleExpression,Lg as normalizeSourceEvent,An as normalizeSshPublicKey,sy as normalizeTelemetryPolicy,Fy as openApiDocument,Uh as optionsForSignal,Bd as organizationManager,Nm as packagePhpApp,Jp as packageServerlessApp,sl as parallel,ll as parallelMap,dl as parallelWithRetry,ft as parseChain,Mf as parseCompose,zf as parseComposeCatalog,CC as parseDockerInspect,sA as parseDotenv,Ia as parseJSONResponse,bC as parseSystemdRecords,Pa as parseXMLResponse,fy as pathTemplate,bh as percentOfLimit,zu as performanceManager,im as phpLayerBuildStage,nm as phpLayerPackages,Pm as phpRuntimeLayerAssets,Hf as planComposeTemplateUpgrade,wh as planEnforcement,Mt as planMitigation,ir as planZoneMigration,Qt as policyTag,Ll as previewManager,Bl as previewNotifications,xC as previewSchedule,ch as previousBudgetWindow,Qg as priceUsage,Xg as priceUsageLines,de as probeOriginTls,gl as processInChunks,Mg as processSourceWebhook,aC as productionChangeReview,Eu as progressiveDeploymentManager,Ah as projectSpend,yt as propagationHeaders,zt as providerEndpoint,NS as publicKeyFingerprint,Xt as qualifyName,Gp as queueManagementManager,il as quickHash,ti as rateLimitHeaders,Xn as rateLimitKey,Yr as reconcileAddressRecords,at as reconcileCloudflareCdn,tr as reconcileDeclaredRecords,VC as reconcileJobObservation,Hg as reconcileSourceWebhook,oC as recordDashboardHostPosture,nC as recordPreDeploySecretScan,iC as recordSkippedSecretScan,Ct as recursionBlockedResponse,pC as redactRuntimeConfig,py as redactTelemetryText,my as redactTelemetryValue,Ti as redeployServerlessApp,Rd as regionPairManager,Sg as releaseStrategyCapabilities,Tg as releaseTrafficPlan,jn as reloadRpxGateway,_t as remapKey,Gg as removeSourceWebhook,jr as removeStaleServerAddressRecords,Wf as renderComposeTemplate,Lt as renderDdosInstallScript,xt as renderNftablesRuleset,MC as renderServerCron,kt as renderSysctlFile,mn as renderWafConfig,fn as renderWafInstallScript,qn as renewRpxCertificates,Bu as replicaManager,Ny as requestHash,Cl as requiresReplacement,fm as resetRecursionRuntime,ym as resolveApp,Ha as resolveAppDatabase,lf as resolveAuthEncryptionKey,ja as resolveCloudProvider,ct as resolveCloudflareCdnPlan,Pc as resolveCredentials,wi as resolveDashboardAction,zn as resolveDashboardAuth,ec as resolveDashboardDomain,tc as resolveDashboardDomains,er as resolveDeclaredRecords,ns as resolveDeployBucketName,Wa as resolveDeploymentMode,Mn as resolveExecStart,Sn as resolveHetznerApiToken,Ka as resolveMailService,sc as resolveManagementDashboardSite,ac as resolveManagementDashboardSites,Ht as resolveObjectStorage,Qa as resolveProjectStackName,rn as resolveProxyUpstreams,em as resolveQueueNames,ng as resolveQueuedDeploymentCommand,Xp as resolveQueues,um as resolveRecursionConfig,Ic as resolveRegion,DC as resolveRuntimeInventory,is as resolveServerlessAppStackName,os as resolveServerlessArtifactBucketName,as as resolveServerlessAssetBucketName,Qp as resolveServerlessRuntime,ts as resolveSiteBucketName,on as resolveSiteDeployTarget,an as resolveSiteKind,es as resolveSiteResourceName,Xa as resolveSiteStackName,Va as resolveStatePath,rs as resolveStorageBucketName,Hn as resolveUiSource,xe as resolveZoneApex,zm as resourceManagementManager,Sm as responseToResult,Lh as robustZScore,yf as roleCapabilities,Pg as rollbackImmutableRelease,$i as rollbackServerlessApp,eh as roundCents,$p as route53ResolverManager,Ap as route53RoutingManager,Wh as routeMatches,Qn as ruleMatches,Zp as runBuildHooks,vh as runEnforcement,vm as runPhpBuildHooks,Ii as runRemoteCommand,cC as runtimeId,Di as sanitizeCloudConfig,Df as sanitizeControlPlaneValue,Ya as sanitizeName,df as sanitizeOidcReturnPath,dy as saveTelemetryPolicy,zy as scanForSecrets,Cf as scopeContains,yh as scopeKey,wn as scpUpload,rd as searchCommands,wf as searchControlPlane,ju as secretsManager,Uu as secretsRotationManager,sC as secureContainerRelease,Au as securityHubManager,Qu as securityScanningManager,tC as securityScope,sf as sendAuthenticationEmail,vp as senderReputationManager,ul as sequence,cA as serializeDotenv,Ln as serverPublicIpv4,ap as serviceMeshManager,Pi as setMaintenance,La as setStateDir,Xi as setupDns01Challenge,jp as sha256,mm as sharedRecursionGuard,sm as sharedRuntimeLoop,cn as shipsARelease,ki as signCloudFrontCookies,Ni as signCloudFrontUrl,Ca as signRequest,Sa as signRequestAsync,Gh as signalDefinition,by as spendNotificationText,Ly as spendOpenApiPaths,Dn as sshExec,En as sshExecOrThrow,Td as stackDependencyManager,vi as startLocalDashboardServer,Dy as startSpendLoop,Ma as stateDir,Fa as statePath,xm as staticSiteManager,Mm as storageAdvancedManager,Yh as streamFocusJsonl,Oh as strongestActiveAction,Ql as suggestCommand,id as suggestFlags,Kc as suggestIAMPolicy,qc as suggestQuotaIncrease,kd as suggestRegionPairs,Nd as suggestRegions,Wg as syncSourceRepositories,gg as synchronizeComposeVolumes,fA as synchronizeConfiguredConfiguration,GC as synchronizeConfiguredJobs,Mu as syntheticsManager,Nt as sysctlHardening,RC as systemdWorkloads,yy as telemetryBucketLabel,gy as telemetryCursor,uy as telemetryEstimatedMonthlyCost,hy as telemetryPercentile,cy as telemetryPolicyKey,Qc as templateCache,Bg as testSourceConnection,Jg as tieredMicroCents,le as toCloudflareZoneSettings,Jh as toFocusJsonl,qh as toFocusRecords,Jm as totp,Xm as totpUri,lC as unsupportedCapabilities,ag as unsupportedVolumeCapabilities,xS as updateCompatibility,fi as uploadStaticFiles,mh as usageDeltaKey,ah as utcInstantOfLocal,Ud as validateAccountStructure,Tl as validateAgainstSchema,lg as validateAttachment,zS as validateBackupDestination,sd as validateCommand,Bc as validateConfiguration,zc as validateCredentials,sn as validateDeploymentConfig,cg as validateMountPath,qe as validateResourceLimits,He as validateTemplate,je as validateTemplateSize,Qr as verifyAddressRecord,eC as verifyArtifactSignature,Li as verifyMediaAccessToken,Ym as verifyTotp,kS as verifyUpdateSignature,ar as verifyZoneParity,sg as volumeCapabilities,gn as wafEventTelemetry,On as waitForCloudInit,vn as waitForSsh,Fg as webhookEndpoint,hc as withCDN,gc as withCache,fc as withDatabase,hm as withInvocation,pc as withMonitoring,yc as withQueue,mc as withSecurity,pl as withTimeout,bn as wrapCloudInitUserData,vu as xrayManager,fS as zeroCapacity,Xh as zeroFill,oh as zoneOffsetMs,ih as zonedParts};
595
+ `}async function uo(e){let{domain:t,challengeValue:r,hostedZoneId:n,dnsProvider:i,region:d="us-east-1"}=e;if(i){let a=await Y(i).upsertRecord(t,{name:`_acme-challenge.${t}`,type:"TXT",content:r,ttl:60});if(!a.success)throw Error(`Failed to create DNS challenge record: ${a.message}`);return}if(n){await new J(d).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 po(e){let{domain:t,challengeValue:r,hostedZoneId:n,dnsProvider:i,region:d="us-east-1"}=e;if(i){let a=await Y(i).deleteRecord(t,{name:`_acme-challenge.${t}`,type:"TXT",content:r});if(!a.success)console.warn(`Failed to delete DNS challenge record: ${a.message}`);return}if(n){await new J(d).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 mo(e){try{let{execSync:t}=Z("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 Oe,createSign as at,generateKeyPairSync as Ne}from"node:crypto";var ke={production:"https://acme-v02.api.letsencrypt.org/directory",staging:"https://acme-staging-v02.api.letsencrypt.org/directory"};class st{directoryUrl;email;accountKey;accountUrl=null;directory=null;nonce=null;constructor(e){this.directoryUrl=e.staging?ke.staging:ke.production,this.email=e.email,this.accountKey=e.accountKey||this.generateAccountKey()}generateAccountKey(){let{privateKey:e}=Ne("ec",{namedCurve:"P-256"});return e.export({type:"pkcs8",format:"pem"})}async getDirectory(){if(this.directory)return this.directory;let e=await fetch(this.directoryUrl);if(!e.ok)throw Error(`Failed to fetch ACME directory: ${e.status}`);return this.directory=await e.json(),this.directory}async getNonce(){if(this.nonce){let n=this.nonce;return this.nonce=null,n}let e=await this.getDirectory(),r=(await fetch(e.newNonce,{method:"HEAD"})).headers.get("replay-nonce");if(!r)throw Error("Failed to get nonce from ACME server");return r}getJwk(){let e=this.accountKey.split(`
596
+ `).filter((d)=>!d.startsWith("-----")).join(""),t=Buffer.from(e,"base64"),r=t.length-65,n=t.subarray(r+1,r+33),i=t.subarray(r+33,r+65);return{kty:"EC",crv:"P-256",x:this.base64UrlEncode(n),y:this.base64UrlEncode(i)}}getJwkThumbprint(){let e=this.getJwk(),t=JSON.stringify({crv:e.crv,kty:e.kty,x:e.x,y:e.y}),r=Oe("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(),i={alg:"ES256",nonce:r,url:e};if(this.accountUrl)i.kid=this.accountUrl;else i.jwk=n;let d=this.base64UrlEncode(JSON.stringify(i)),s=t===""?"":this.base64UrlEncode(JSON.stringify(t)),a=`${d}.${s}`,l=at("SHA256");l.update(a);let p=l.sign(this.accountKey),u=p.subarray(4,4+p[3]),b=4+p[3]+2,C=p.subarray(b,b+p[b-1]),T=Buffer.alloc(32),g=Buffer.alloc(32);u.copy(T,32-u.length),C.copy(g,32-C.length);let m=Buffer.concat([T,g]);return JSON.stringify({protected:d,payload:s,signature:this.base64UrlEncode(m)})}async acmeRequest(e,t){let r=await this.signPayload(e,t),n=await fetch(e,{method:"POST",headers:{"Content-Type":"application/jose+json"},body:r}),i=n.headers.get("replay-nonce");if(i)this.nonce=i;let d,s=n.headers.get("content-type");if(s?.includes("application/json")||s?.includes("application/problem+json"))d=await n.json();else d=await n.text();if(!n.ok)throw Error(`ACME request failed: ${JSON.stringify(d)}`);return{body:d,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((d)=>({type:"dns",value:d}))}),i=n.get("location");if(!i)throw Error("No order URL returned");return{orderUrl:i,authorizations:r.authorizations,finalize:r.finalize}}async getAuthorization(e){let{body:t}=await this.acmeRequest(e,""),r=t.identifier.value,n=this.getJwkThumbprint(),i=t.challenges.filter((d)=>d.type==="http-01"||d.type==="dns-01").map((d)=>{let s=`${d.token}.${n}`;if(d.type==="http-01")return{type:"http-01",token:d.token,keyAuthorization:s,identifier:`/.well-known/acme-challenge/${d.token}`};else{let a=this.base64UrlEncode(Oe("sha256").update(s).digest());return{type:"dns-01",token:d.token,keyAuthorization:s,identifier:`_acme-challenge.${r}`,dnsValue:a}}});return{domain:r,challenges:i}}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((i)=>setTimeout(i,2000))}throw Error("Authorization timed out")}generateCsr(e){let{privateKey:t}=Ne("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:i}=await this.acmeRequest(e,{csr:this.base64UrlEncode(Buffer.from(r,"base64"))}),d=i.certificate;if(!d)throw Error("Certificate not immediately available - polling not implemented");let a=await(await fetch(d)).text(),l=a.split(/(?=-----BEGIN CERTIFICATE-----)/g),p=l[0],u=l.slice(1).join("");return{certificate:p,privateKey:n,chain:u,fullchain:a,expiresAt:new Date(Date.now()+7776000000)}}getAccountKey(){return this.accountKey}}var xe=["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"],ct=[{name:"x-stx-router",value:"true"}];function W(e){return`"${e.replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}"`}function Le(e){return`{${e.map(W).join(" ")}}`}function lt(e){let t=`http.request.headers[${W(e.name.toLowerCase())}]`;return e.value===void 0?`len(${t}) > 0`:`any(${t}[*] == ${W(e.value)})`}function se(e){if(e.length===1)return`http.host eq ${W(e[0])}`;return`http.host in ${Le(e)}`}function ce(e,t={}){if(t.enabled===!1||e.length===0)return[];let r=se(e),n=[],d=(t.bypassPaths??[]).map((T)=>`starts_with(http.request.uri.path, ${W(T)})`),a=(t.negotiatedRequestHeaders??ct).map(lt),l=[...d,...a],p=l.length>0?`(${l.join(" or ")})`:void 0;if(p)n.push({action:"set_cache_settings",description:"bypass cache",expression:`(${r} and ${p})`,enabled:!0,action_parameters:{cache:!1}});let u=p?`${r} and not ${p}`:r,b=t.assetExtensions??xe,C=b.length>0?`lower(http.request.uri.path.extension) in ${Le([...b])}`:void 0;if(C)n.push({action:"set_cache_settings",description:"cache fingerprinted assets",expression:`(${u} and ${C})`,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:C?`(${u} and not ${C})`:`(${u})`,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 le(e,t,r){if(e.length===0||!t||!r)return[];return[{action:"rewrite",description:"origin guard header",expression:`(${se(e)})`,enabled:!0,action_parameters:{headers:{[t]:{operation:"set",value:r}}}}]}var N=(e)=>e===void 0?void 0:e?"on":"off";function de(e){let t={ssl:e.ssl,always_use_https:N(e.alwaysUseHttps),automatic_https_rewrites:N(e.automaticHttpsRewrites),min_tls_version:e.minTlsVersion,tls_1_3:N(e.tls13),brotli:N(e.brotli),http3:N(e.http3),"0rtt":N(e.zeroRtt),early_hints:N(e.earlyHints),browser_cache_ttl:e.browserCacheTtl,always_online:N(e.alwaysOnline),websockets:N(e.websockets),email_obfuscation:N(e.emailObfuscation)};if(e.hsts)t.security_header={strict_transport_security:{enabled:e.hsts.enabled,max_age:e.hsts.maxAge??31536000,include_subdomains:e.hsts.includeSubdomains??!1,preload:e.hsts.preload??!1,nosniff:e.hsts.noSniff??!0}};for(let r of Object.keys(t))if(t[r]===void 0)delete t[r];return{...t,...e.raw??{}}}var H={ssl:"strict",alwaysUseHttps:!0,automaticHttpsRewrites:!0,minTlsVersion:"1.2",tls13:!0,brotli:!0,http3:!0,earlyHints:!0,alwaysOnline:!0,emailObfuscation:!1,browserCacheTtl:0};import{connect as dt}from"node:tls";async function ue(e){let{address:t,serverName:r,port:n=443,timeoutMs:i=5000}=e;return new Promise((d)=>{let s=!1,a=(p)=>{if(s)return;s=!0;try{l.destroy()}catch{}d(p)},l=dt({host:t,port:n,servername:r,rejectUnauthorized:!1,timeout:i});l.once("secureConnect",()=>{if(l.authorized){a({reachable:!0,trusted:!0});return}a({reachable:!0,trusted:!1,reason:l.authorizationError?String(l.authorizationError):"origin certificate is not trusted for this hostname"})}),l.once("timeout",()=>{a({reachable:!1,trusted:!1,reason:`no TLS handshake within ${i}ms`})}),l.once("error",(p)=>{a({reachable:!1,trusted:!1,reason:p.message})})})}function ut(e,t){let r=t.replace(/\.$/,"").toLowerCase();return e.some((n)=>{let i=n.replace(/\.$/,"").toLowerCase();if(i===r)return!0;if(!i.startsWith("*."))return!1;let d=i.slice(2);if(!r.endsWith(`.${d}`))return!1;return!r.slice(0,r.length-d.length-1).includes(".")})}async function pt(e){let{provider:t,zone:r,hosts:n,ipv4:i,ipv6:d,proxied:s=!0,settings:a=H,cache:l,originGuard:p,purge:u=!0,ttl:b=300,skipOriginProbe:C=!1,skipEdgeCertificateCheck:T=!1}=e,g={records:[],settingsChanged:[],cacheRules:0,originGuard:!1,purged:!1,deferredProxy:[],warnings:[]};if(n.length===0)return g;let m=[],c=s&&!T?await t.listEdgeCertificateHosts(r):null;for(let o of n){let f=s;if(f&&c&&!ut(c,o)){f=!1;let S=c.length===0?"the zone has no active edge certificate yet":`no active edge certificate covers it (${c.join(", ")})`;g.deferredProxy.push({host:o,reason:S}),g.warnings.push(`${o}: publishing DNS-only — ${S}. Proxying it would make Cloudflare terminate TLS with no certificate for the name, which fails the handshake outright rather than degrading. Universal SSL covers the apex and ONE level of subdomain, so a deeper name needs its own certificate; otherwise re-run the deploy once the certificate is active.`)}if(f&&!C){let S=await ue({address:i,serverName:o});if(!S.trusted){f=!1;let A=S.reason||"origin is not serving a trusted certificate";g.deferredProxy.push({host:o,reason:A}),g.warnings.push(`${o}: publishing DNS-only for now — the origin does not yet serve a certificate this proxy can verify (${A}). 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(f)m.push(o);let h=[{type:"A",content:i}];if(d&&pe(o))h.push({type:"AAAA",content:d});for(let{type:S,content:A}of h){let R=await t.upsertRecord(r,{name:o,type:S,content:A,ttl:b,proxied:f});if(R.success)g.records.push({host:o,type:S,content:A,proxied:f});else g.warnings.push(`${o} ${S} → ${A} failed: ${R.message||"unknown provider error"}`)}}if(m.length===0){if(s)g.warnings.push("No host is proxied yet, so zone settings, cache rules and purge were skipped — they only take effect through the proxy.");return g}try{let o=de(a),f=await t.applyZoneSettings(r,o);g.settingsChanged=f.changed;for(let h of f.failed)g.warnings.push(`zone setting '${h.id}' could not be applied: ${h.error}`)}catch(o){g.warnings.push(`zone settings could not be read: ${o instanceof Error?o.message:String(o)}`)}let y=ce(m,l);if(y.length>0){let o=await t.putManagedPhaseRules(r,"http_request_cache_settings",y);if(o.success)g.cacheRules=y.length;else g.warnings.push(`cache rules could not be written: ${o.message}`)}if(p){let o=le(m,p.header,p.value);if(o.length>0){let f=await t.putManagedPhaseRules(r,"http_request_late_transform",o);if(f.success)g.originGuard=!0;else g.warnings.push(`origin guard header could not be written: ${f.message}. `+"The gateway will reject requests that lack it — disable the guard or grant the token Transform Rules: Edit.")}}if(u){if(g.purged=await t.purgeCache(r,{hosts:m}),!g.purged)g.warnings.push("edge cache purge failed — new content may take until TTL expiry to appear.")}return g}var mt=(e)=>process.env[e];function Fe(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 ft(e,t={}){let r=t.env??mt,n=e.infrastructure?.compute?.proxy?.cdn,i=[];if(!n||n.provider!=="cloudflare")return{plan:null,errors:i};if(n.originDomain)i.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 d=r("CLOUDFLARE_API_TOKEN");if(!d)return i.push("CLOUDFLARE_API_TOKEN is not set — the Cloudflare CDN cannot be reconciled."),{plan:null,errors:i};let s=e.sites??{},a=n.frontedHosts?.length?[...new Set(n.frontedHosts.map((C)=>C.toLowerCase()))]:me(s,{autoWww:e.infrastructure?.compute?.proxy?.autoWww!==!1});if(a.length===0)return i.push("No hostnames to front — set compute.proxy.cdn.frontedHosts, or give a site a domain."),{plan:null,errors:i};let l=e.infrastructure?.dns?.domain,p=new Set(a.map((C)=>Fe(C,l)));if(p.size>1)return i.push(`Fronted hosts span more than one zone (${[...p].join(", ")}). A Cloudflare zone is configured as a unit, so run one CDN config per zone.`),{plan:null,errors:i};let u=n.cloudflare??{},b=n.secret?{header:n.secretHeader??"X-Origin-Verify",value:n.secret}:void 0;return{plan:{zone:[...p][0],hosts:a,apiToken:d,zoneId:u.zoneId??r("CLOUDFLARE_ZONE_ID"),accountId:u.accountId??r("CLOUDFLARE_ACCOUNT_ID"),proxied:u.proxied!==!1,settings:u.settings??H,cache:u.cache,originGuard:b,purge:u.purgeOnDeploy!==!1,skipOriginProbe:u.skipOriginProbe===!0},errors:i}}var ht=26214400;var yt=new Set(["/_headers","/_redirects","/_routes.json","/_worker.js"]);class Me{name="cloudflare-pages";apiToken;accountId;constructor(e){if(!e.apiToken)throw Error("Cloudflare Pages needs an API token");if(!e.accountId)throw Error("Cloudflare Pages needs an account id");this.apiToken=e.apiToken,this.accountId=e.accountId}async request(e,t,r){return fe(e,`/accounts/${this.accountId}${t}`,`Bearer ${this.apiToken}`,r)}async getProject(e){try{return await this.request("GET",`/pages/projects/${e}`)}catch(t){if(t instanceof Error&&/\b8000007\b|not found/i.test(t.message))return null;throw t}}async ensureProject(e,t="main"){let r=await this.getProject(e);if(r)return r;return this.request("POST","/pages/projects",{name:e,production_branch:t})}async uploadToken(e){return(await this.request("GET",`/pages/projects/${e}/upload-token`)).jwt}async missingHashes(e,t){let r=await fe("POST","/pages/assets/check-missing",`Bearer ${e}`,{hashes:t});return new Set(r)}async uploadBatch(e,t){let r=t.map((n)=>({key:n.hash,value:n.base64,metadata:{contentType:St(n.extension)},base64:!0}));await fe("POST","/pages/assets/upload",`Bearer ${e}`,r)}async createDeployment(e,t,r){let n={};for(let d of t)n[d.path]=d.hash;let i=new FormData;if(i.append("manifest",JSON.stringify(n)),r)i.append("branch",r);return this.request("POST",`/pages/projects/${e}/deployments`,i)}async deployDirectory(e){let t=await Be(e.directory);if(t.length===0)throw Error(`No files to deploy in ${e.directory}`);let r=await this.uploadToken(e.project),n=await this.missingHashes(r,t.map((l)=>l.hash)),i=t.filter((l)=>n.has(l.hash)),d=[];for(let l=0;l<i.length;l+=100)d.push(i.slice(l,l+100));let s=0;for(let l=0;l<d.length;l+=4){let p=d.slice(l,l+4);await Promise.all(p.map((u)=>this.uploadBatch(r,u))),s+=p.reduce((u,b)=>u+b.length,0),e.onProgress?.(s,i.length)}return{deployment:await this.createDeployment(e.project,t,e.branch),total:t.length,uploaded:i.length,uploadedBytes:i.reduce((l,p)=>l+p.size,0)}}async listCustomDomains(e){return(await this.request("GET",`/pages/projects/${e}/domains`)).map((r)=>r.name)}async attachCustomDomain(e,t){if((await this.listCustomDomains(e)).includes(t))return!1;return await this.request("POST",`/pages/projects/${e}/domains`,{name:t}),!0}}function Ct(e,t){return{type:"CNAME",name:e,value:t.endsWith(".pages.dev")?t:`${t}.pages.dev`,ttl:1,proxied:!0}}async function _e(e,t){let{blake3:r}=await import("./chunk-6kpbveb8.js").then((m)=>gt(m.default,1));return(await r(e+t)).slice(0,32)}async function Be(e){let{readdir:t}=await import("node:fs/promises"),{join:r,relative:n,sep:i}=await import("node:path"),d=[];async function s(a){let l=await t(a,{withFileTypes:!0});for(let p of l){let u=r(a,p.name);if(p.isDirectory()){await s(u);continue}if(!p.isFile())continue;let b=`/${n(e,u).split(i).join("/")}`;if(yt.has(b))continue;let C=await Bun.file(u).bytes();if(C.byteLength>26214400)throw Error(`${b} is ${C.byteLength} bytes, over the Cloudflare Pages limit of 26214400`);let T=Buffer.from(C).toString("base64"),g=p.name.lastIndexOf("."),m=g>0?p.name.slice(g+1):"";d.push({path:b,hash:await _e(T,m),base64:T,extension:m,size:C.byteLength})}}return await s(e),d.sort((a,l)=>a.path.localeCompare(l.path)),d}function St(e){return{html:"text/html; charset=utf-8",css:"text/css; charset=utf-8",js:"application/javascript; charset=utf-8",mjs:"application/javascript; charset=utf-8",json:"application/json; charset=utf-8",map:"application/json; charset=utf-8",xml:"application/xml; charset=utf-8",txt:"text/plain; charset=utf-8",svg:"image/svg+xml",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",webp:"image/webp",avif:"image/avif",ico:"image/x-icon",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf",otf:"font/otf",pdf:"application/pdf",webmanifest:"application/manifest+json"}[e.toLowerCase()]||"application/octet-stream"}async function fe(e,t,r,n){let i={Authorization:r},d;if(n instanceof FormData)d=n;else if(n!==void 0)i["Content-Type"]="application/json",d=JSON.stringify(n);let s=await fetch(`https://api.cloudflare.com/client/v4${t}`,{method:e,headers:i,body:d}),a=await s.text(),l;try{l=JSON.parse(a)}catch{throw Error(`Cloudflare Pages API returned ${s.status} with a non-JSON body: ${a.slice(0,200)}`)}if(!l.success){let p=(l.errors??[]).map((u)=>`${u.code}: ${u.message}`).join(", ");throw Error(`Cloudflare Pages API error (${s.status}): ${p||a.slice(0,200)}`)}return l.result}export{Vu as ABTestManager,$r as ACMClient,Dr as ACMDnsValidator,ke as ACME_DIRECTORIES,F as AI,Kf as API_IDEMPOTENCY_TTL_MS,Uf as API_TOKEN_DEFAULT_TTL_MS,jf as API_TOKEN_MAX_TTL_MS,Yy as API_VERSION,Of as AUTHORIZATION_CAPABILITIES,Cf as AUTH_ACTION_TOKEN_TTL_MS,Sf as AUTH_MFA_CHALLENGE_TTL_MS,Af as AUTH_OIDC_TRANSACTION_TTL_MS,yf as AUTH_SESSION_ABSOLUTE_TTL_MS,hf as AUTH_SESSION_IDLE_TTL_MS,Jc as AWSAPIError,vt as AWSClient,Ve as AWSCloudFormationClient,We as AWSCloudFrontClient,wu as AWSConfigManager,Gs as AWS_PSEUDO_PARAMETERS,Bd as AWS_REGIONS,st as AcmeClient,Ft as AlertEvaluator,Lt as AlertStore,ny as AnomalyConfigStore,Ie as ApiGateway,jy as ApiServiceError,Qr as ApplicationAutoScalingClient,zs as Arn,_s as AssetHasher,Fs as Auth,bf as AuthenticationStore,qy as AutomationApiService,qf as AutomationIdentityStore,fS as AwsAuroraDataAdapter,SS as AwsAuroraTransport,uA as AwsDatabaseBackupSource,wn as AwsDriver,gS as AwsElastiCacheDataAdapter,AS as AwsElastiCacheTransport,cC as AwsIamCapabilityScanner,AA as AwsInfrastructureBackupSource,mS as AwsRdsDataAdapter,CS as AwsRdsTransport,HS as AwsRegionalDriver,$A as AwsSecretsManagerConfigurationBackend,zy as AwsSpendTransport,DA as AwsSsmConfigurationBackend,lA as BackupCoordinator,Pu as BackupManager,iA as BackupStore,rm as BatchProcessingManager,Hr as BedrockClient,Wr as BedrockRuntimeClient,Kg as BitbucketSourceAdapter,Fu as BlueGreenManager,Vp as BounceComplaintHandler,hp as BuildOptimizationManager,bS as BunDockerRuntime,yA as BunDockerVolumeRuntime,fA as BunFilesystemArchiveRuntime,Ds as CDN,bt as CHAIN_HEADER,sr as CLOUDFLARE_MANAGED_RULE_PREFIX,iu as COMMON_CROSS_ACCOUNT_ROLES,Ef as CONTROL_PLANE_SCHEMA_VERSION,ie as Cache,_u as CanaryManager,dp as CertificateManager,Eg as CloudBlockVolumeDriver,Ln as CloudDriverFactory,Uc as CloudError,Us as CloudFormationBuilder,Ve as CloudFormationClient,We as CloudFrontClient,vu as CloudTrailManager,xr as CloudWatchLogsClient,Me as CloudflarePagesProvider,cr as CloudflareProvider,Dd as CommandHistory,Ws as Communication,kg as ComposeApplicationService,Ng as ComposeApplicationStore,zr as ComprehendClient,E as Compute,Gy as ComputeSpendTransport,jc as ConfigurationError,wA as ConfigurationService,bA as ConfigurationStore,Lr as ConnectClient,yS as ContainerDataAdapter,Cp as ContainerRegistryManager,SA as ControlPlaneBackupSource,tA as ControlPlaneCleanupDriver,zf as ControlPlaneStore,Eh as CounterTracker,Kc as CredentialError,Od as CrossRegionReferenceManager,uc as DASHBOARD_ENTRY,pc as DASHBOARD_PORT_BASE,mc as DASHBOARD_PORT_SPAN,dc as DASHBOARD_STATE_DIR,gi as DEFAULT_ATTACK_MODE_HOURS,Wt as DEFAULT_DDOS_THRESHOLDS,Dh as DEFAULT_METER_MAPPINGS,yh as DEFAULT_PRICE_BOOK,Pt as DEFAULT_RECURSION_LIMITS,sl as DEFAULT_SERVICE_LIMITS,qa as DEFAULT_STATE_DIR,xe as DEFAULT_STATIC_ASSET_EXTENSIONS,by as DEFAULT_TELEMETRY_POLICY,kh as DEFAULT_THRESHOLDS,yg as DEPLOYMENT_QUEUE_KINDS,At as DEPTH_HEADER,iy as DETECTABLE_SIGNALS,GC as DIAGNOSTIC_PRESETS,em as DLQMonitoringManager,Is as DNS,Fp as DNSSECManager,uS as DataServiceLifecycle,lS as DataServiceStore,K as Database,ip as DatabaseUserManager,el as DebugLogger,Rs as DependencyGraph,Ms as Deployment,qc as DeploymentError,Du as DisasterRecoveryManager,Tr as DnsProviderFactory,RS as DockerDataTransport,LC as DockerDiscoveryAdapter,Ig as DockerNamedVolumeDriver,CA as DockerVolumeBackupSource,mg as DurableOperationQueue,fg as DurableQueueWorker,_r as DynamoDBClient,rr as EC2Client,Ir as ECRClient,wr as ECSClient,nn as EFSClient,Fr as ELBv2Client,ch as ENFORCEMENT_ACTIONS,Hh as ENFORCEMENT_DESCRIPTIONS,lh as ENFORCEMENT_SEVERITY,BC as EcsRuntimeAdapter,ui as EdgeRateLimiter,Yr as ElastiCacheClient,L as Email,qp as EmailAdvanced,Hp as EmailAnalyticsManager,xt as EmailClient,Zp as EmailHandlers,jp as EmailTemplateManager,TS as EncryptedDataSecretStore,Yc as ErrorCodes,Jr as EventBridgeClient,nS as EventBridgeJobAdapter,IA as ExternalConfigurationBackend,Xp as FIFOQueueManager,ly as FOCUS_VERSION,ul as FileCache,j as FileSystem,gA as FilesystemBackupSource,wS as FleetService,IS as FleetStore,Hs as Fn,qg as GiteaSourceAdapter,Ug as GithubSourceAdapter,jg as GitlabSourceAdapter,Nd as GlobalResourceManager,ar as GoDaddyProvider,Nu as GuardDutyManager,bl as HashCache,Xm as HealthCheckManager,Bt as HealthCheckRunner,En as HetznerClient,kn as HetznerDriver,Ot as IAMClient,cn as IPV6_EXCLUDED_HOST_LABELS,fp as ImageScanningManager,Ke as InfrastructureGenerator,Mf as InvalidOperationTransitionError,vs as JobLoader,iS as JobProviderReconciler,aS as JobService,eS as JobStore,Zr as KendraClient,Hm as LARAVEL_SERVERLESS_BUILD_STEPS,kr as LambdaClient,Dp as LambdaConcurrencyManager,Np as LambdaDLQManager,wp as LambdaDestinationsManager,Rp as LambdaLayersManager,VC as LambdaRuntimeAdapter,vp as LambdaVPCManager,Pp as LambdaVersionsManager,PA as LocalEncryptedConfigurationBackend,hA as LogicalDatabaseBackupSource,qu as LogsManager,pm as MANAGED_NODE_VERSIONS,Yn as MANAGEMENT_DASHBOARD_SITE,Cc as MANAGEMENT_DASHBOARD_SITE_PREFIX,fi as MAX_CONTROL_HOURS,Wf as MAX_CONTROL_PLANE_ERROR_BYTES,Vf as MAX_CONTROL_PLANE_JSON_BYTES,sh as METERS,ah as METER_KEYS,dh as MICRO_CENTS,_h as MIN_PROJECTION_CONFIDENCE,pn as MTA_STS_PORT,XS as MaintenanceService,JS as MaintenanceStore,xs as Messaging,ju as MetricsManager,Xu as MigrationManager,Ul as MockCloudFormation,Kl as MockDynamoDB,jl as MockS3,we as Monitoring,Xd as MultiAccountManager,Ed as MultiRegionManager,dd as MultiStepProgress,Pe as Network,ef as NetworkSecurityManager,_t as NotificationRouter,Br as OpenSearchClient,Ff as OptimisticConcurrencyError,Qd as OrganizationManager,ht as PAGES_MAX_FILE_BYTES,Gm as PHP_DEFAULT_EXCLUDES,ym as PHP_LAYER_EXTENSIONS,ir as PROXIABLE_RECORD_TYPES,Vs as ParameterStore,rp as PerformanceManager,De as Permissions,qr as PersonalizeClient,Es as Phone,Jp as PhoneAdvanced,ws as PhoneHandlers,NS as PlacementService,OS as PlacementStore,jr as PollyClient,or as PorkbunProvider,rC as PreDeployScanner,Zl as PreviewEnvironmentManager,hg as PreviewEnvironmentService,gg as PreviewEnvironmentStore,ed as PreviewNotificationService,ld as ProgressBar,Hu as ProgressiveDeploymentManager,hi as ProtectionControlStore,ds as Pseudo,ne as Queue,dg as QueueCancellationError,im as QueueManagementManager,ja as QueuePresets,ug as QueueTimeoutError,si as RATE_LIMIT_KEY_SEPARATOR,Mr as RDSClient,ru as RECOMMENDED_ACCOUNT_STRUCTURES,nu as RECOMMENDED_SCPS,Wg as RELEASE_QUEUE_KINDS,Td as REPL,$d as REPLCommandBuilder,Pd as REPLContext,wl as RateLimiter,Ka as RealtimePresets,Ay as RecordingSpendTransport,It as RecursionGuard,q as Redirects,kd as RegionPairManager,VS as RegionService,BS as RegionStore,$s as Registry,Gr as RekognitionClient,Mg as ReleaseService,Fg as ReleaseStore,kS as RemoteBuildService,ep as ReplicaManager,rf as ResourceManagementManager,pg as RetryableOperationError,J as Route53Client,nr as Route53DomainsClient,mr as Route53Provider,_p as Route53ResolverManager,xp as Route53RoutingManager,UC as RuntimeOperationService,jC as RuntimeStreamRegistry,cA as S3BackupDestinationAdapter,Nt as S3Client,zc as S3Error,tC as SECRET_PATTERNS,ty as SENSITIVITY_THRESHOLDS,kt as SESClient,ks as SMS,Or as SNSClient,Wy as SPEND_CYCLE_SECONDS,gy as SPEND_GATE_SETTING,_y as SPEND_LEASE_SETTING,Nr as SQSClient,Er as SSMClient,Za as STATE_DIR_ENV_VAR,H as STATIC_SITE_ZONE_SETTINGS,Zt as STSClient,Xr as SchedulerClient,Ee as Search,aC as SecretFindingScanner,Bs as Secrets,cp as SecretsManager,vr as SecretsManagerClient,ap as SecretsRotationManager,re as Security,xu as SecurityHubManager,eC as SecurityPostureStore,oC as SecurityScannerRunner,pp as SecurityScanningManager,Gp as SenderReputationManager,rS as ServerCronJobAdapter,hS as ServerDataAdapter,wg as ServerPathVolumeDriver,Ap as ServiceMeshManager,$e as Sftp,ay as SignalSource,Yp as SmsAdvanced,en as SmsClient,Ns as SmsHandlers,zg as SourceConnectionStore,Gg as SourceProviderError,yy as SpendCapError,hy as SpendGate,By as SpendLoopLease,My as SpendNotificationRouter,Vy as SpendRunner,my as SpendService,xh as SpendStore,ud as Spinner,$S as SshFleetDriver,xd as StackDependencyManager,Os as StacksIntegration,qm as StaticSiteManager,te as Storage,Jm as StorageAdvancedManager,rn as SupportClient,Ju as SyntheticsManager,PS as SystemFleetSshTransport,_C as SystemdDiscoveryAdapter,Rt as TRACE_HEADER,pd as TaskList,ky as TelemetryStore,be as TemplateBuilder,pl as TemplateCache,Ur as TextractClient,Vr as TranscribeClient,Kr as TranslateClient,rA as TransportDisasterRecoveryDriver,eA as TransportPlatformMaintenanceDriver,LS as TransportRemoteBuildDriver,sC as TrivyImageScanner,Zf as TsCloudApiError,Jf as TsCloudClient,xy as URGENT_SPEND_EVENTS,zh as USER_VISIBLE_ACTIONS,zS as UnavailableRegionalDriver,Cr as UnifiedDnsValidator,_f as UnsupportedSchemaVersionError,Zc as ValidationError,tn as VoiceClient,$g as VolumeService,Ag as VolumeStore,Ls as Workflow,Gu as XRayManager,Wu as abTestManager,Bg as activateImmutableRelease,wC as ageSeconds,Oh as aggregateDeltas,Ts as analyzeStackDiff,ey as anomalyOptionsForSignal,Si as applyControlsToDdos,Ci as applyControlsToRateLimits,qt as applyMitigationFactor,hr as applyZoneMigration,dm as artifactKey,Lg as assertReleaseStrategy,Cy as assertSpendAllows,fC as attachProvenanceToRelease,uC as attachSbomToRelease,pC as attachVulnerabilitySummary,Tf as authEncryptionKeyFile,xf as authorizeOrganization,zC as authorizeRuntimePath,Cd as autocomplete,Eu as awsConfigManager,sA as backupCredentialStatus,$u as backupManager,Tl as batch,nm as batchProcessingManager,If as beginOidcAuthorization,Mu as blueGreenManager,Wp as bounceComplaintHandler,Rh as budgetWindow,vi as buildAndPushServerlessImage,Pm as buildBunRuntimeLayerZip,js as buildCloudFormationTemplate,cg as buildComposeLogsCommand,ag as buildComposeRuntimeCommand,sg as buildComposeScaleCommand,lg as buildComposeShellCommand,Ni as buildFunctionEnv,Jn as buildHostCleanupScript,cs as buildMailEnv,ri as buildManagementDashboardArtifact,qi as buildMediaCdnPlan,un as buildMtaStsPolicy,mn as buildMtaStsServer,Tm as buildNodeRuntimeLayerZip,yp as buildOptimizationManager,le as buildOriginGuardRule,zm as buildPhpRuntimeLayerZip,qn as buildSiteDeployScript,Mn as buildSshArgs,ce as buildStaticSiteCacheRules,Zn as buildStaticSiteDeployScript,EC as bytes,Bu as canaryManager,GS as canonicalJson,$C as capabilities,vS as capacity,xl as categorizeChanges,up as certificateManager,il as checkIAMPermissions,vm as checkInvocation,cl as checkServiceQuotas,El as chunk,po as cleanupDns01Challenge,Ha as clearSigningKeyCache,eh as cloneSourceBinding,Ml as cloudConfigSchema,Fn as cloudDrivers,Ou as cloudTrailManager,Be as collectAssets,jm as collectPhpAppEntries,on as collectServerDnsDomains,Og as completeComposeVolumeDeletion,wf as completeOidcAuthorization,Pc as composePresets,og as composeProjectName,hm as composeServerlessAppTemplate,Uy as compositeSpendTransport,pA as compressBackup,cf as config,dS as connectionGuidance,Sp as containerRegistryManager,Bf as controlPlaneDatabaseFile,vf as controlPlaneMigrations,Qs as createApiBackendPreset,Qy as createApiV1Handler,_S as createAsgBuildDriver,dA as createBackupQueueHandlers,Mm as createCliHandler,xn as createCloudDriver,Ae as createCloudFrontPolicy,Bc as createCredentialProvider,lc as createDashboardSite,ic as createDataPipelinePreset,pS as createDataServiceQueueHandlers,Sg as createDeploymentQueueHandlers,Y as createDnsProvider,MS as createEcsBuildDriver,Sy as createEnforcementHandlers,Qc as createError,Ys as createExistingStaticFullStackPreset,DS as createFleetQueueHandlers,Xs as createFullStackAppPreset,Ar as createGoDaddyValidator,_m as createHandlers,Lm as createHttpHandler,tc as createJamstackPreset,sS as createJobQueueHandlers,sc as createLaravelPreset,oc as createMLApiPreset,QS as createMaintenanceQueueHandlers,Ui as createMediaAccessToken,rc as createMicroservicesPreset,ql as createMockAWS,qs as createNodeJsServerPreset,Zs as createNodeJsServerlessPreset,tr as createObjectStorageClient,Sr as createPorkbunValidator,$c as createPreset,La as createPresignedUrl,Fa as createPresignedUrlAsync,Fm as createQueueHandler,nc as createRealtimeAppPreset,WS as createRegionQueueHandlers,mC as createReleaseProvenance,Hg as createReleaseQueueHandlers,xS as createRemoteBuildQueueHandlers,br as createRoute53Validator,WC as createRuntimeAdapters,Gc as createS3Client,FS as createServerBuildDriver,cc as createServerlessLaravelPreset,Js as createServerlessNodePreset,Zg as createSourceAdapter,Ks as createStaticSitePreset,ac as createTraditionalWebAppPreset,Dg as createVolumeQueueHandlers,ec as createWordPressPreset,am as createZip,Ld as crossRegionReferenceManager,Bi as dashboardActions,Xn as dashboardCredentialsFile,cS as dataServiceCapabilities,op as databaseUserManager,df as decodeBase32,mA as decompressBackup,aA as decryptBackup,of as defaultConfig,Bl as defaultLocalConfig,mi as defaultRateLimitRules,Ii as deleteStaticSite,ii as deployAllComputeSites,ki as deployServerlessApp,Ei as deploySite,ni as deploySiteRelease,Pi as deployStaticSite,wi as deployStaticSiteFull,bi as deployStaticSiteWithExternalDns,Ri as deployStaticSiteWithExternalDnsFull,ns as deploymentCoexistenceError,fc as deriveManagementDashboardPort,yi as describePosture,tS as desiredJobProviderState,Xh as detectAnomalies,ts as detectDeploymentTargets,Rr as detectDnsProvider,Qh as detectLatestAnomaly,rl as detectMisconfigurations,Na as detectServiceRegion,Qf as diffCompose,Ol as diffTemplates,Qg as discoverGitRefs,Df as discoverOidcProvider,vC as discoverRuntimeInventory,tm as dlqMonitoringManager,Pr as dnsProviders,Mp as dnssecManager,xC as dockerWorkloads,jS as documentDigest,Iu as drManager,OC as ecsWorkloads,Lf as effectiveCapabilities,zp as emailAnalyticsManager,Kp as emailTemplateManager,lf as encodeBase32,oA as encryptBackup,yC as ensureDefaultSecurityPolicies,Gn as ensureFirewall,ti as ensureManagementDashboard,Un as ensureServer,zn as ensureSshKey,bn as escapeSecLang,Vh as evaluateBudget,Vt as evaluateTelemetryAlertRules,XC as eventBridgeScheduleInput,km as eventToRequest,Yh as ewma,Xf as exportCompose,fr as exportRoute53Zone,Tc as extendPreset,Qp as fifoQueueManager,Al as findChangedFiles,Ih as findMapping,ph as findPriceEntry,cu as formatAccountStructure,od as formatBytes,Ly as formatCents,Ps as formatDiff,ad as formatDuration,Ad as formatFlagSuggestions,Id as formatHistory,wd as formatHistoryStats,cd as formatKeyValue,sd as formatList,id as formatProgressBar,Zd as formatRegion,Jd as formatRegionList,iC as formatScanResults,fd as formatSuggestion,rd as formatTable,Mh as formatTimeToExhaustion,nd as formatTree,Lc as fromEC2Metadata,Fc as fromECSMetadata,kc as fromEnvironment,xc as fromSharedCredentials,Mc as fromWebIdentity,Tt as functionFingerprint,me as gatewayHostnames,bm as generateAppImageDockerfile,Ru as generateApprovalConfig,sm as generateBootstrap,Xl as generateCleanupWorkflow,Ql as generateCostReportWorkflow,au as generateCrossAccountRoleCF,lC as generateCycloneDxSbom,Su as generateDeploymentConfig,fu as generateDeploymentPipeline,lu as generateDeploymentWorkflow,Ai as generateExternalDnsStaticSiteTemplate,lo as generateHttpsServerCode,dC as generateImageSbom,co as generateLetsEncryptUserData,Te as generateLogicalId,Cu as generateManualPipeline,mu as generateMatrixWorkflow,Au as generateMultiEnvConfig,gu as generateMultiEnvPipeline,du as generateMultiEnvWorkflow,uu as generatePRPreviewWorkflow,Tu as generateParallelConfig,Bm as generatePhpFpmConfig,Am as generatePhpLayerDockerfile,hu as generatePreviewPipeline,Yl as generatePreviewWorkflow,Re as generateResourceName,bu as generateScheduledConfig,yu as generateScheduledPipeline,pu as generateScheduledWorkflow,Ti as generateStaticSiteTemplate,In as generateUbuntuAppCloudInit,Hc as getAccountId,Wd as getAllRegions,jd as getClosestRegion,bd as getCommandUsage,tg as getComposeTemplate,af as getConfig,hd as getContextualHelp,_c as getCredentials,Ll as getDeploymentStrategy,Fl as getDiffStats,Nl as getDiffSummary,Xc as getErrorDetails,Vl as getLocalConfig,zl as getLocalCredentials,Hl as getLocalEndpoint,Gl as getLocalEnvVars,ll as getQuotaUsageSummary,ou as getRecommendedStructure,Vd as getRegion,Yd as getRegionStats,zd as getRegionsByCompliance,Hd as getRegionsByLocation,Gd as getRegionsByPricingTier,ol as getRequiredPermissions,za as getSigningKeyCacheSize,us as getTimestamp,ci as globMatches,Tn as globToRegex,Fd as globalResourceManager,Bh as governingLimitCents,ku as guardDutyManager,Zy as handleSpendRequest,An as hasAutoWwwVariant,yc as hasManagementDashboardSite,gn as hasProxyUpstream,hl as hashBuffer,yl as hashDirectory,fl as hashFile,Cl as hashManifest,gl as hashString,Qm as healthCheckManager,pe as hostAcceptsIpv6,se as hostCondition,uf as hotp,Ph as hourBucket,$h as hourBucketsBetween,gp as imageScanningManager,Oi as infraEnvFromOutputs,Dt as inspectInvocation,Im as installRecursionFetch,Di as invalidateCache,$m as invocationContext,gd as isLikelyTypo,Wl as isLocalDevelopment,Ac as isManagementDashboardSiteName,Ga as isNodeCryptoAvailable,Kh as isOperationAllowed,Mt as isQuietHours,Rn as isSafePattern,es as isStatePath,Ht as isValidCidr,Ud as isValidRegion,Ch as isValidTimeZone,Ua as isWebCryptoAvailable,JC as jobProviderCapability,Yt as keyMatchesFilters,Ip as lambdaConcurrencyManager,kp as lambdaDLQManager,Ep as lambdaDestinationsManager,Tp as lambdaLayersManager,Op as lambdaVPCManager,$p as lambdaVersionsManager,NC as lambdaWorkloads,Wm as laravelServerlessEnvDefaults,eg as listComposeTemplates,nh as listSourceReferences,sf as loadCloudConfig,Py as loadTelemetryPolicy,Zu as logsManager,cy as lookbackHoursForSignal,os as mailEnabled,ss as mailFirewallPorts,YS as maintenanceWindowOpen,Ma as makeAWSRequest,Ba as makeAWSRequestAsync,_a as makeAWSRequestOnce,Sc as managementDashboardSiteName,US as manifestDigest,ff as matchTotpCounter,Ki as mediaObjectHeaders,qh as median,Zh as medianAbsoluteDeviation,Wh as mergeDecisions,Dc as mergeInfrastructure,hh as mergePriceBooks,vh as meterTelemetry,Ku as metricsManager,Xt as migrateObjectStorage,Qu as migrationManager,eu as multiAccountManager,vd as multiRegionManager,mo as needsRenewal,tf as networkSecurityManager,qC as nextScheduleRuns,sn as normalizePublicIpv6,DC as normalizeRuntimeStatus,KC as normalizeScheduleExpression,Jg as normalizeSourceEvent,On as normalizeSshPublicKey,Ry as normalizeTelemetryPolicy,Xy as openApiDocument,sy as optionsForSignal,tu as organizationManager,Km as packagePhpApp,um as packageServerlessApp,_e as pagesAssetHash,Ct as pagesDnsRecord,Rl as parallel,Pl as parallelMap,$l as parallelWithRetry,$t as parseChain,Yf as parseCompose,ng as parseComposeCatalog,kC as parseDockerInspect,RA as parseDotenv,Wa as parseJSONResponse,FC as parseSystemdRecords,Va as parseXMLResponse,Ey as pathTemplate,Fh as percentOfLimit,np as performanceManager,Sm as phpLayerBuildStage,Cm as phpLayerPackages,Vm as phpRuntimeLayerAssets,ig as planComposeTemplateUpgrade,Gh as planEnforcement,Kt as planMitigation,gr as planZoneMigration,lr as policyTag,Jl as previewManager,td as previewNotifications,ZC as previewSchedule,Th as previousBudgetWindow,mh as priceUsage,fh as priceUsageLines,ue as probeOriginTls,vl as processInChunks,Yg as processSourceWebhook,bC as productionChangeReview,zu as progressiveDeploymentManager,Lh as projectSpend,wt as propagationHeaders,Qt as providerEndpoint,KS as publicKeyFingerprint,dr as qualifyName,om as queueManagementManager,Sl as quickHash,pi as rateLimitHeaders,di as rateLimitKey,ln as reconcileAddressRecords,pt as reconcileCloudflareCdn,pr as reconcileDeclaredRecords,QC as reconcileJobObservation,ih as reconcileSourceWebhook,AC as recordDashboardHostPosture,CC as recordPreDeploySecretScan,SC as recordSkippedSecretScan,Et as recursionBlockedResponse,IC as redactRuntimeConfig,Iy as redactTelemetryText,wy as redactTelemetryValue,xi as redeployServerlessApp,Md as regionPairManager,xg as releaseStrategyCapabilities,_g as releaseTrafficPlan,oi as reloadRpxGateway,Jt as remapKey,oh as removeSourceWebhook,an as removeStaleServerAddressRecords,rg as renderComposeTemplate,jt as renderDdosInstallScript,Ut as renderNftablesRuleset,YC as renderServerCron,Gt as renderSysctlFile,Pn as renderWafConfig,$n as renderWafInstallScript,ai as renewRpxCertificates,tp as replicaManager,Ky as requestHash,kl as requiresReplacement,Em as resetRecursionRuntime,Nm as resolveApp,is as resolveAppDatabase,Pf as resolveAuthEncryptionKey,ls as resolveCloudProvider,ft as resolveCloudflareCdnPlan,Vc as resolveCredentials,Vi as resolveDashboardAction,Qn as resolveDashboardAuth,gc as resolveDashboardDomain,hc as resolveDashboardDomains,ur as resolveDeclaredRecords,Cs as resolveDeployBucketName,rs as resolveDeploymentMode,Kn as resolveExecStart,vn as resolveHetznerApiToken,as as resolveMailService,Rc as resolveManagementDashboardSite,bc as resolveManagementDashboardSites,er as resolveObjectStorage,ms as resolveProjectStackName,fn as resolveProxyUpstreams,gm as resolveQueueNames,Cg as resolveQueuedDeploymentCommand,fm as resolveQueues,Dm as resolveRecursionConfig,Wc as resolveRegion,HC as resolveRuntimeInventory,Ss as resolveServerlessAppStackName,As as resolveServerlessArtifactBucketName,bs as resolveServerlessAssetBucketName,mm as resolveServerlessRuntime,hs as resolveSiteBucketName,hn as resolveSiteDeployTarget,yn as resolveSiteKind,gs as resolveSiteResourceName,fs as resolveSiteStackName,Qa as resolveStatePath,ys as resolveStorageBucketName,ei as resolveUiSource,Fe as resolveZoneApex,nf as resourceManagementManager,xm as responseToResult,Jh as robustZScore,Nf as roleCapabilities,Vg as rollbackImmutableRelease,Li as rollbackServerlessApp,gh as roundCents,Bp as route53ResolverManager,Lp as route53RoutingManager,ry as routeMatches,li as ruleMatches,cm as runBuildHooks,Uh as runEnforcement,Um as runPhpBuildHooks,Mi as runRemoteCommand,TC as runtimeId,_i as sanitizeCloudConfig,Hf as sanitizeControlPlaneValue,ps as sanitizeName,$f as sanitizeOidcReturnPath,$y as saveTelemetryPolicy,nC as scanForSecrets,kf as scopeContains,Nh as scopeKey,Vn as scpUpload,yd as searchCommands,Gf as searchControlPlane,lp as secretsManager,sp as secretsRotationManager,RC as secureContainerRelease,Lu as securityHubManager,mp as securityScanningManager,hC as securityScope,Rf as sendAuthenticationEmail,Up as senderReputationManager,Dl as sequence,TA as serializeDotenv,jn as serverPublicIpv4,bp as serviceMeshManager,Fi as setMaintenance,Ja as setStateDir,uo as setupDns01Challenge,lm as sha256,wm as sharedRecursionGuard,Rm as sharedRuntimeLoop,Sn as shipsARelease,Gi as signCloudFrontCookies,zi as signCloudFrontUrl,ka as signRequest,xa as signRequestAsync,oy as signalDefinition,Fy as spendNotificationText,Jy as spendOpenApiPaths,_n as sshExec,Bn as sshExecOrThrow,_d as stackDependencyManager,Wi as startLocalDashboardServer,Hy as startSpendLoop,Ya as stateDir,Xa as statePath,Zm as staticSiteManager,Ym as storageAdvancedManager,py as streamFocusJsonl,jh as strongestActiveAction,md as suggestCommand,Sd as suggestFlags,al as suggestIAMPolicy,dl as suggestQuotaIncrease,qd as suggestRegionPairs,Kd as suggestRegions,rh as syncSourceRepositories,vg as synchronizeComposeVolumes,EA as synchronizeConfiguredConfiguration,oS as synchronizeConfiguredJobs,Yu as syntheticsManager,zt as sysctlHardening,MC as systemdWorkloads,Ny as telemetryBucketLabel,vy as telemetryCursor,Dy as telemetryEstimatedMonthlyCost,Oy as telemetryPercentile,Ty as telemetryPolicyKey,ml as templateCache,th as testSourceConnection,uh as tieredMicroCents,de as toCloudflareZoneSettings,uy as toFocusJsonl,dy as toFocusRecords,pf as totp,gf as totpUri,PC as unsupportedCapabilities,bg as unsupportedVolumeCapabilities,ZS as updateCompatibility,$i as uploadStaticFiles,wh as usageDeltaKey,bh as utcInstantOfLocal,su as validateAccountStructure,_l as validateAgainstSchema,Pg as validateAttachment,nA as validateBackupDestination,Rd as validateCommand,tl as validateConfiguration,nl as validateCredentials,Cn as validateDeploymentConfig,Tg as validateMountPath,et as validateResourceLimits,qe as validateTemplate,Qe as validateTemplateSize,dn as verifyAddressRecord,gC as verifyArtifactSignature,ji as verifyMediaAccessToken,mf as verifyTotp,qS as verifyUpdateSignature,yr as verifyZoneParity,Rg as volumeCapabilities,Dn as wafEventTelemetry,Hn as waitForCloudInit,Wn as waitForSsh,Xg as webhookEndpoint,Oc as withCDN,vc as withCache,Ec as withDatabase,Om as withInvocation,Ic as withMonitoring,Nc as withQueue,wc as withSecurity,Il as withTimeout,Nn as wrapCloudInitUserData,Uu as xrayManager,ES as zeroCapacity,fy as zeroFill,Ah as zoneOffsetMs,Sh as zonedParts};