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