@stacksjs/ts-cloud 0.11.6 → 0.11.7

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