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