@stacksjs/ts-cloud 0.16.89 → 0.16.91

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 (207) hide show
  1. package/dist/aws/client.d.ts +3 -5
  2. package/dist/aws/credentials.d.ts +9 -4
  3. package/dist/aws/index.js +1 -1
  4. package/dist/bin/chunk-0b6rv9dt.js +1 -0
  5. package/dist/bin/chunk-0qzt0swj.js +5 -0
  6. package/dist/bin/chunk-0rvzy2z7.js +1 -0
  7. package/dist/bin/{chunk-z9g7fa1w.js → chunk-0zepgwq9.js} +2 -2
  8. package/dist/bin/chunk-11hc309t.js +1 -0
  9. package/dist/bin/{chunk-qmwqntnx.js → chunk-1p7rtk98.js} +2 -2
  10. package/dist/bin/{chunk-qpasspad.js → chunk-32dr1fym.js} +5 -5
  11. package/dist/bin/{chunk-v3trt4q1.js → chunk-3h7gmatb.js} +3 -3
  12. package/dist/bin/{chunk-69mejej3.js → chunk-407wz1f4.js} +1 -1
  13. package/dist/bin/{chunk-xycxw00z.js → chunk-42nh9ac7.js} +8 -8
  14. package/dist/bin/chunk-49zcdbn0.js +1 -0
  15. package/dist/bin/chunk-4gv5j5s1.js +1 -0
  16. package/dist/bin/{chunk-gn7rdyz7.js → chunk-4kka906v.js} +2 -2
  17. package/dist/bin/{chunk-jqs2ywj2.js → chunk-55mv5w3m.js} +2 -2
  18. package/dist/bin/{chunk-4mep3m41.js → chunk-57yxbyh6.js} +5 -5
  19. package/dist/bin/chunk-5nfhjr0h.js +1 -0
  20. package/dist/bin/chunk-5njr2s5x.js +1 -0
  21. package/dist/bin/chunk-6qhgzf9a.js +1 -0
  22. package/dist/bin/{chunk-bycbwddj.js → chunk-6ty1wegm.js} +2 -2
  23. package/dist/bin/chunk-8ctmc30y.js +14 -0
  24. package/dist/bin/{chunk-deptcjq9.js → chunk-97j6xrfe.js} +97 -97
  25. package/dist/bin/chunk-9g4qsx30.js +1 -0
  26. package/dist/bin/chunk-afvk9mbs.js +1 -0
  27. package/dist/bin/{chunk-9bmaq8q7.js → chunk-cb0yqrpk.js} +111 -113
  28. package/dist/bin/{chunk-bxks81wn.js → chunk-chx779q9.js} +3 -3
  29. package/dist/bin/chunk-ckbv6y4c.js +1 -0
  30. package/dist/bin/{chunk-6b6yr784.js → chunk-drc9y2fj.js} +2 -2
  31. package/dist/bin/{chunk-b1cb27m8.js → chunk-eqqqbsjm.js} +7 -7
  32. package/dist/bin/{chunk-cgyk48s5.js → chunk-fcst782q.js} +1 -1
  33. package/dist/bin/{chunk-19mhwmfp.js → chunk-fmgv99xw.js} +1 -1
  34. package/dist/bin/{chunk-0e56zmps.js → chunk-g1s5s95g.js} +2 -2
  35. package/dist/bin/{chunk-h6xne9s6.js → chunk-g21yhm1b.js} +96 -96
  36. package/dist/bin/{chunk-ye2gymsr.js → chunk-gkgqss71.js} +3 -3
  37. package/dist/bin/chunk-gvacnz2y.js +1 -0
  38. package/dist/bin/{chunk-em9swj0k.js → chunk-h99kxww0.js} +1 -1
  39. package/dist/bin/chunk-j1dbkpha.js +1 -0
  40. package/dist/bin/{chunk-zfn3a9sx.js → chunk-j34ask5s.js} +2 -2
  41. package/dist/bin/{chunk-f7jzs1h1.js → chunk-j7j7gffr.js} +5 -5
  42. package/dist/bin/chunk-jjw5d8b9.js +1 -0
  43. package/dist/bin/{chunk-1wgyq50e.js → chunk-kbtx3q9m.js} +29 -30
  44. package/dist/bin/{chunk-t0r1rdj2.js → chunk-kdjrcvr6.js} +2 -2
  45. package/dist/bin/{chunk-76ekkat8.js → chunk-kefwtr8r.js} +3 -3
  46. package/dist/bin/{chunk-v1a0b9yq.js → chunk-kp84kged.js} +16 -16
  47. package/dist/bin/chunk-m5tpfe3s.js +1 -0
  48. package/dist/bin/{chunk-83tt2t15.js → chunk-mrkrn8dk.js} +5 -5
  49. package/dist/bin/chunk-n6yvpj86.js +1 -0
  50. package/dist/bin/{chunk-bkx2kapc.js → chunk-ncj8dpdp.js} +2 -2
  51. package/dist/bin/{chunk-w40r35vn.js → chunk-p6swcv5y.js} +1 -1
  52. package/dist/bin/{chunk-ndvma07s.js → chunk-pat56kbr.js} +5 -5
  53. package/dist/bin/chunk-q2hg6hmg.js +1 -0
  54. package/dist/bin/chunk-qd1jfsam.js +1 -0
  55. package/dist/bin/{chunk-yf2drw7r.js → chunk-r1q343bm.js} +1 -1
  56. package/dist/bin/chunk-r50x03ws.js +1 -0
  57. package/dist/bin/chunk-rhncmffy.js +1 -0
  58. package/dist/bin/chunk-seh19g93.js +1 -0
  59. package/dist/bin/{chunk-35325988.js → chunk-sjzzx539.js} +2 -2
  60. package/dist/bin/chunk-sxfdxk39.js +1 -0
  61. package/dist/bin/chunk-ty2pdbz3.js +1 -0
  62. package/dist/bin/chunk-tyeessz3.js +1 -0
  63. package/dist/bin/chunk-vbsk8b9d.js +1 -0
  64. package/dist/bin/chunk-we82q71y.js +1 -0
  65. package/dist/bin/{chunk-zn9wmqd1.js → chunk-xhqfha32.js} +2 -2
  66. package/dist/bin/{chunk-89v3ec9n.js → chunk-xk8nrvjz.js} +1 -1
  67. package/dist/bin/{chunk-88s5w4yt.js → chunk-zpk7fn1s.js} +6 -6
  68. package/dist/bin/cli.js +216 -216
  69. package/dist/bin/dashboard-server.js +1 -1
  70. package/dist/bin/stacks-queue-worker.js +1 -1
  71. package/dist/bin/stacks-scheduler.js +1 -1
  72. package/dist/chunk-0v77443p.js +1 -0
  73. package/dist/{chunk-z56sccfh.js → chunk-1087xz1v.js} +2 -2
  74. package/dist/{chunk-c8kf2268.js → chunk-1psh3mhm.js} +29 -30
  75. package/dist/chunk-4khjjgd3.js +1 -0
  76. package/dist/{chunk-4pztf7ws.js → chunk-4m5gpp6w.js} +5 -5
  77. package/dist/{chunk-3bvhthfb.js → chunk-72p2tdpe.js} +115 -117
  78. package/dist/chunk-7d9ek8rc.js +5 -0
  79. package/dist/chunk-872fdms3.js +1 -0
  80. package/dist/{chunk-cq079p4a.js → chunk-9f18pebj.js} +6 -6
  81. package/dist/{chunk-vq8bejep.js → chunk-a77mhcs7.js} +3 -3
  82. package/dist/chunk-bazah9w0.js +1 -0
  83. package/dist/{chunk-tmp2ym80.js → chunk-by7hejhg.js} +1 -1
  84. package/dist/{chunk-ax320pn8.js → chunk-byr76jcy.js} +19 -19
  85. package/dist/{chunk-m35z9vyn.js → chunk-c6kb5c5v.js} +4 -4
  86. package/dist/{chunk-gpgmp9dt.js → chunk-dmv3vryr.js} +10 -10
  87. package/dist/{chunk-5t92a838.js → chunk-fe6m7wb0.js} +45 -45
  88. package/dist/{chunk-py8dq1ey.js → chunk-fne338jr.js} +5 -5
  89. package/dist/{chunk-nftqsker.js → chunk-h6kptkce.js} +2 -2
  90. package/dist/{chunk-fdf181e6.js → chunk-hcbrgyfz.js} +2 -2
  91. package/dist/{chunk-9pwvnh3f.js → chunk-jz6dacx1.js} +2 -2
  92. package/dist/{chunk-fjs0wgyw.js → chunk-kcem6dzk.js} +2 -2
  93. package/dist/{chunk-7xy7bsyx.js → chunk-mvmxy0z7.js} +110 -110
  94. package/dist/{chunk-bvywngfv.js → chunk-n95wbpge.js} +136 -136
  95. package/dist/{chunk-4ccv5c4m.js → chunk-q7yf28cc.js} +1 -1
  96. package/dist/{chunk-jx1zz1pw.js → chunk-qra9k26f.js} +1 -1
  97. package/dist/chunk-qs7814ya.js +1 -0
  98. package/dist/chunk-sd5a61c6.js +1 -0
  99. package/dist/{bin/chunk-8rkfwgb4.js → chunk-sjfc9my3.js} +7 -7
  100. package/dist/{chunk-84z2a1xn.js → chunk-sxqe8e9c.js} +7 -7
  101. package/dist/{chunk-g0bh9atv.js → chunk-t1wq0ckc.js} +2 -2
  102. package/dist/{chunk-c71hhcsb.js → chunk-tpvmpmxj.js} +1 -1
  103. package/dist/{chunk-tr54e9c0.js → chunk-x7cnfn7y.js} +2 -2
  104. package/dist/{chunk-fpad8xw9.js → chunk-xs9m0v31.js} +4 -4
  105. package/dist/chunk-zft558kj.js +1 -0
  106. package/dist/{chunk-e75dvdqf.js → chunk-zwayp7fz.js} +2 -2
  107. package/dist/{chunk-gdw52mn4.js → chunk-zy3kr4s2.js} +3 -3
  108. package/dist/deploy/index.js +1 -1
  109. package/dist/dns/index.js +1 -1
  110. package/dist/drivers/index.js +1 -1
  111. package/dist/index.js +31 -31
  112. package/dist/mail/index.js +2 -2
  113. package/dist/operations/index.js +1 -1
  114. package/dist/protection/index.js +1 -1
  115. package/dist/spend/index.js +1 -1
  116. package/dist/ui/404.html +1 -1
  117. package/dist/ui/accept-invitation.html +1 -1
  118. package/dist/ui/access-denied.html +1 -1
  119. package/dist/ui/account/automation.html +6 -6
  120. package/dist/ui/account/security.html +2 -2
  121. package/dist/ui/applications/compose.html +6 -6
  122. package/dist/ui/applications/new.html +2 -2
  123. package/dist/ui/data/backups.html +5 -5
  124. package/dist/ui/data/services.html +6 -6
  125. package/dist/ui/data/volumes.html +6 -6
  126. package/dist/ui/index.html +6 -6
  127. package/dist/ui/infrastructure/topology.html +6 -6
  128. package/dist/ui/integrations.html +1 -1
  129. package/dist/ui/operations/alerts.html +6 -6
  130. package/dist/ui/operations/configuration.html +6 -6
  131. package/dist/ui/operations/jobs.html +6 -6
  132. package/dist/ui/operations/maintenance.html +5 -5
  133. package/dist/ui/operations/observability.html +5 -5
  134. package/dist/ui/operations/previews.html +5 -5
  135. package/dist/ui/operations/queue.html +5 -5
  136. package/dist/ui/operations/regions.html +5 -5
  137. package/dist/ui/operations/releases.html +5 -5
  138. package/dist/ui/operations/spend.html +6 -6
  139. package/dist/ui/operations/workloads.html +6 -6
  140. package/dist/ui/security.html +1 -1
  141. package/dist/ui/server/actions.html +6 -6
  142. package/dist/ui/server/activity.html +1 -1
  143. package/dist/ui/server/capacity.html +6 -6
  144. package/dist/ui/server/database.html +6 -6
  145. package/dist/ui/server/deployments.html +6 -6
  146. package/dist/ui/server/diagnostics.html +2 -2
  147. package/dist/ui/server/firewall.html +6 -6
  148. package/dist/ui/server/fleet.html +6 -6
  149. package/dist/ui/server/logs.html +6 -6
  150. package/dist/ui/server/metrics.html +6 -6
  151. package/dist/ui/server/security.html +2 -2
  152. package/dist/ui/server/services.html +1 -1
  153. package/dist/ui/server/sites.html +6 -6
  154. package/dist/ui/server/ssh-keys.html +6 -6
  155. package/dist/ui/server/team.html +5 -5
  156. package/dist/ui/server/terminal.html +2 -2
  157. package/dist/ui/serverless/alarms.html +6 -6
  158. package/dist/ui/serverless/assets.html +2 -2
  159. package/dist/ui/serverless/cost.html +2 -2
  160. package/dist/ui/serverless/data.html +6 -6
  161. package/dist/ui/serverless/deployments.html +2 -2
  162. package/dist/ui/serverless/firewall.html +2 -2
  163. package/dist/ui/serverless/functions.html +6 -6
  164. package/dist/ui/serverless/logs.html +6 -6
  165. package/dist/ui/serverless/metrics.html +2 -2
  166. package/dist/ui/serverless/queues.html +6 -6
  167. package/dist/ui/serverless/secrets.html +6 -6
  168. package/dist/ui/serverless/traces.html +6 -6
  169. package/dist/ui/serverless.html +5 -5
  170. package/package.json +3 -3
  171. package/dist/bin/chunk-1qez75tb.js +0 -1
  172. package/dist/bin/chunk-1rrmswhq.js +0 -1
  173. package/dist/bin/chunk-1vw6khps.js +0 -1
  174. package/dist/bin/chunk-2h1q758c.js +0 -2
  175. package/dist/bin/chunk-3rjer1mp.js +0 -1
  176. package/dist/bin/chunk-4k2x5x3k.js +0 -1
  177. package/dist/bin/chunk-5tzygzdy.js +0 -1
  178. package/dist/bin/chunk-6wvjr3ne.js +0 -1
  179. package/dist/bin/chunk-71fa7yed.js +0 -1
  180. package/dist/bin/chunk-7haewmr7.js +0 -1
  181. package/dist/bin/chunk-86w3vzx8.js +0 -1
  182. package/dist/bin/chunk-8tfqpp9m.js +0 -1
  183. package/dist/bin/chunk-9tt7ahdf.js +0 -1
  184. package/dist/bin/chunk-9zwvysdn.js +0 -1
  185. package/dist/bin/chunk-a66hyvc3.js +0 -1
  186. package/dist/bin/chunk-b9ersj22.js +0 -1
  187. package/dist/bin/chunk-btrxye8p.js +0 -6
  188. package/dist/bin/chunk-haezjam0.js +0 -1
  189. package/dist/bin/chunk-hp1cqk45.js +0 -1
  190. package/dist/bin/chunk-mwprtzxp.js +0 -1
  191. package/dist/bin/chunk-nemj07g1.js +0 -1
  192. package/dist/bin/chunk-nfxxr6g7.js +0 -1
  193. package/dist/bin/chunk-q3mtvtem.js +0 -1
  194. package/dist/bin/chunk-qpd51n1j.js +0 -1
  195. package/dist/bin/chunk-rtpc6djg.js +0 -1
  196. package/dist/bin/chunk-s9k81gq6.js +0 -1
  197. package/dist/bin/chunk-wrcdcg7m.js +0 -1
  198. package/dist/bin/chunk-ybekawxv.js +0 -1
  199. package/dist/chunk-03gf4e58.js +0 -1
  200. package/dist/chunk-86qwnp25.js +0 -1
  201. package/dist/chunk-8kn7rszy.js +0 -1
  202. package/dist/chunk-928z0h9b.js +0 -14
  203. package/dist/chunk-crpbs450.js +0 -1
  204. package/dist/chunk-m9szynnf.js +0 -6
  205. package/dist/chunk-ncet7ba7.js +0 -1
  206. package/dist/chunk-nh7rcks9.js +0 -1
  207. package/dist/chunk-ypsfkgme.js +0 -1
@@ -1,14 +1,14 @@
1
- import{k,na}from"./chunk-928z0h9b.js";import{An,st}from"./chunk-9pwvnh3f.js";var Nm={};An(Nm,{default:()=>Rr,handler:()=>At});var Bm={};An(Bm,{default:()=>Pr,handler:()=>Ct});var Ef={};An(Ef,{EmailAnalyticsModule:()=>Ye,EmailRules:()=>Ut,EmailScheduling:()=>Wt,EmailSearch:()=>Gt,EmailTemplates:()=>ke,EmailThreading:()=>_t,SharedMailboxes:()=>Vt});var vf={};An(vf,{default:()=>ki,handler:()=>xi});var Tf={};An(Tf,{CallAnalytics:()=>jt,CallRecording:()=>Ht,Callbacks:()=>mt,IVRBuilder:()=>Be});var wf={};An(wf,{AbTesting:()=>Pe,LinkTracking:()=>Jt,MmsSupport:()=>zt,SmsAnalytics:()=>qt,SmsCampaigns:()=>Kt,SmsChatbot:()=>Qt});var $I={backgroundJobs:{visibilityTimeout:120,messageRetentionPeriod:604800,deadLetterQueue:!0,maxReceiveCount:3,encrypted:!0},fifo:{fifo:!0,contentBasedDeduplication:!0,visibilityTimeout:30,encrypted:!0},highThroughput:{visibilityTimeout:30,receiveMessageWaitTime:20,encrypted:!0},delayed:{delaySeconds:60,visibilityTimeout:60,encrypted:!0},longRunning:{visibilityTimeout:900,messageRetentionPeriod:1209600,deadLetterQueue:!0,maxReceiveCount:2,encrypted:!0},monitored:{visibilityTimeout:60,messageRetentionPeriod:604800,deadLetterQueue:!0,maxReceiveCount:3,encrypted:!0,alarms:{enabled:!0,queueDepthThreshold:1000,messageAgeThreshold:3600,dlqAlarm:!0}},lambdaOptimized:{visibilityTimeout:360,receiveMessageWaitTime:20,deadLetterQueue:!0,maxReceiveCount:3,encrypted:!0},fanOut:{visibilityTimeout:30,receiveMessageWaitTime:20,encrypted:!0}},MI={serverless:{development:{enabled:!0,mode:"serverless",channels:{public:!0,private:!0,presence:!0},storage:{type:"dynamodb",dynamodb:{billingMode:"PAY_PER_REQUEST"}},scaling:{maxConnections:1000,handlerMemory:128}},production:{enabled:!0,mode:"serverless",channels:{public:!0,private:!0,presence:{enabled:!0,maxMembers:100,heartbeatInterval:30,inactivityTimeout:60}},storage:{type:"dynamodb",dynamodb:{billingMode:"PAY_PER_REQUEST",pointInTimeRecovery:!0,connectionTTL:86400}},scaling:{maxConnections:50000,messagesPerSecond:5000,handlerMemory:256,handlerTimeout:30},monitoring:{enabled:!0,connectionThreshold:40000,errorThreshold:100,latencyThreshold:500},keepAlive:!0,keepAliveInterval:30,idleTimeout:600},notifications:{enabled:!0,mode:"serverless",channels:{public:!1,private:!0,presence:!1},storage:{type:"dynamodb",dynamodb:{billingMode:"PAY_PER_REQUEST"}},scaling:{maxConnections:50000,messagesPerSecond:2000,handlerMemory:128},keepAlive:!0,keepAliveInterval:60,idleTimeout:1800}},server:{development:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:!0},server:{host:"0.0.0.0",port:6001,scheme:"ws",driver:"bun",idleTimeout:120,perMessageDeflate:!1,metrics:!1}},production:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:!0},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:120,maxPayloadLength:16777216,backpressureLimit:1048576,sendPings:!0,perMessageDeflate:!0,instances:2,redis:{enabled:!0,keyPrefix:"broadcasting:"},rateLimit:{enabled:!0,max:100,window:60000,perChannel:!0,perUser:!0},loadManagement:{enabled:!0,maxConnections:1e4,maxSubscriptionsPerConnection:100,shedLoadThreshold:0.8},metrics:!0,autoScaling:{min:2,max:10,targetCPU:70}},monitoring:{enabled:!0,connectionThreshold:8000,errorThreshold:100}},highPerformance:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:!0},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:60,maxPayloadLength:8388608,backpressureLimit:2097152,closeOnBackpressureLimit:!0,sendPings:!0,perMessageDeflate:!0,instances:4,redis:{enabled:!0,useElastiCache:!0,keyPrefix:"rt:"},rateLimit:{enabled:!0,max:200,window:60000,perChannel:!0},loadManagement:{enabled:!0,maxConnections:25000,maxSubscriptionsPerConnection:50,shedLoadThreshold:0.7},metrics:{enabled:!0,path:"/metrics"},autoScaling:{min:4,max:20,targetCPU:60,targetConnections:20000}},monitoring:{enabled:!0,connectionThreshold:80000,errorThreshold:50,latencyThreshold:50}},chat:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:{enabled:!0,maxMembers:200,heartbeatInterval:20,inactivityTimeout:60}},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:300,maxPayloadLength:1048576,sendPings:!0,perMessageDeflate:!0,instances:2,redis:{enabled:!0,keyPrefix:"chat:"},rateLimit:{enabled:!0,max:60,window:60000,perChannel:!0},loadManagement:{enabled:!0,maxConnections:15000,maxSubscriptionsPerConnection:20},metrics:!0},keepAlive:!0,keepAliveInterval:25,idleTimeout:900},gaming:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:{enabled:!0,maxMembers:100,heartbeatInterval:10,inactivityTimeout:30}},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:30,maxPayloadLength:65536,backpressureLimit:524288,closeOnBackpressureLimit:!0,sendPings:!0,perMessageDeflate:!1,instances:4,redis:{enabled:!0,useElastiCache:!0},rateLimit:{enabled:!0,max:120,window:60000},loadManagement:{enabled:!0,maxConnections:5000,maxSubscriptionsPerConnection:10,shedLoadThreshold:0.6},metrics:!0,autoScaling:{min:4,max:16,targetCPU:50}},keepAlive:!0,keepAliveInterval:10,idleTimeout:60},single:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:!0},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:120,sendPings:!0,perMessageDeflate:!0,instances:1,rateLimit:{enabled:!0,max:100,window:60000},loadManagement:{enabled:!0,maxConnections:1e4},metrics:!0}}}};import{isAbsolute as bt,join as Xe,relative as ar}from"node:path";var rl=".ts-cloud",Sm="TS_CLOUD_STATE_DIR",St=null;function nl(n){St=n?.trim()||null}function il(){return Boolean(process.env[Sm]?.trim()||St)}function dn(){return process.env[Sm]?.trim()||St||rl}function Q(...n){return Xe(dn(),...n)}function l(n,...i){let s=dn();return bt(s)?Xe(s,...i):Xe(n,s,...i)}function sl(n,i=process.cwd()){let s=(c,u)=>{let d=ar(c,u);return d===""||!d.startsWith("..")&&!bt(d)},o=bt(n)?n:Xe(i,n);return s(l(i),o)}function Im(n){let i=n.infrastructure?.compute!=null,s=Object.values(n.environments??{}).some((o)=>o?.app!=null);return{server:i,serverless:s}}function K(n){if(n.mode==="server"||n.mode==="serverless")return n.mode;let{serverless:i}=Im(n);return i?"serverless":"server"}function ol(n){let{server:i,serverless:s}=Im(n);if(i&&s)return"A project cannot be both a server and a serverless deployment. Found `infrastructure.compute` (server) AND `environments.<env>.app` (serverless Lambda). Keep one: remove `infrastructure.compute` for a serverless app, or remove `environments.<env>.app` for a server.";if(n.mode==="server"&&s&&!i)return"Config sets `mode: 'server'` but declares a serverless app (`environments.<env>.app`). Remove the app or change the mode.";if(n.mode==="serverless"&&i&&!s)return"Config sets `mode: 'serverless'` but declares a server (`infrastructure.compute`). Remove the compute block or change the mode.";return null}function p(n){return n.infrastructure?.appDatabase??n.infrastructure?.compute?.database}function or(n){return typeof n==="object"&&n!==null?n:{}}function ry(n){return n===!0||typeof n==="object"&&n!==null}function cr(n,i){let s=i?n.environments?.[i]:void 0;if(s?.domain)return s.domain;let o=Object.values(n.sites??{}),c=n.sites?.main?.domain??o.find((u)=>u.domain)?.domain;if(c)return c;return`${n.project?.slug??"app"}.local`}function dr(n){let i=n.indexOf(".");return i>0?n.slice(i+1):void 0}function b(n,i={}){let s=n.infrastructure?.compute?.managedServices?.mail,o=or(s),c=i.environmentType??(i.environment?n.environments?.[i.environment]?.type:void 0),u=o.mode??(c==="production"?"server":"catcher"),d=u==="server",g=cr(n,i.environment),y=o.hostname??(d?`mail.${g}`:"localhost"),h=o.ports??{},A=d?{smtp:h.smtp??25,submission:h.submission??587,submissions:h.submissions??465,imap:h.imap??143,imaps:h.imaps??993,webmail:h.webmail??8080,managesieve:h.managesieve}:{smtp:h.smtp??1025,submission:h.submission,submissions:h.submissions,imap:h.imap,imaps:h.imaps,webmail:h.webmail??8025,managesieve:h.managesieve},C=o.tls??{},v=C.enabled??d,T=!!(C.systemCredentials||C.certPath&&C.keyPath);if(C.systemCredentials&&Object.values(C.systemCredentials).some((ce)=>!/^\/[a-z0-9_./-]+$/i.test(ce)||ce.includes("/../")))throw Error("Mail system credentials require absolute certificate paths");let R=(o.accounts??[]).map((ce)=>({address:ce.address,password:ce.password,passwordPolicy:ce.passwordPolicy??"initial"})),P=typeof o.dkim==="object"&&o.dkim!==null?o.dkim:{},I=o.dkim===!1?!1:o.dkim===!0||d,M=typeof o.webmail==="object"&&o.webmail!==null?o.webmail:{},L=o.webmail===!1?!1:M.enabled??!0,N=y.includes(".")&&!y.endsWith(".local")&&!/^\d+\.\d+\.\d+\.\d+$/.test(y),O=M.domain===!1?void 0:M.domain??(d&&N?y:void 0),B=M.tls??(O?!1:v),F=[...new Set(M.aliases??[])].filter((ce)=>ce!==O),U=o.spam??{},j=o.delivery??(d?"direct":"none"),H=o.expose??d,z=dr(y),se=[...new Set([y,...z?[z]:[],...o.domains??[]])],ve=M.attachments?.maxFileBytes??20971520,oe=M.attachments?.maxTotalBytes??20971520,pe=M.attachments?.maxCount??20,ae=M.undoSendSeconds??10;for(let[ce,Ie,Le]of[["maxFileBytes",ve,104857600],["maxTotalBytes",oe,104857600],["maxCount",pe,100],["undoSendSeconds",ae,30]])if(!Number.isInteger(Ie)||Ie<0||Ie>Le)throw Error(`Mail webmail ${ce} must be an integer from 0 to ${Le}`);return{enabled:ry(s),mode:u,version:o.version,hostname:y,domains:se,ports:A,tls:{enabled:v,acme:v&&!T&&(C.acme??!0),certPath:C.systemCredentials?"/run/credentials/mail.service/server.crt":C.certPath,keyPath:C.systemCredentials?"/run/credentials/mail.service/server.key":C.keyPath,systemCredentials:C.systemCredentials,requireForAuth:C.requireForAuth??(v&&d),acmeEmail:C.acmeEmail??R[0]?.address},dkim:{enabled:I,selector:P.selector??"default",rotate:P.rotate??!1,rotateIntervalDays:P.rotateIntervalDays??90},webmail:{enabled:L,port:M.port??A.webmail,domain:O,aliases:F,tls:B,secureCookies:M.secureCookies??(!!O||B),attachmentMaxFileBytes:ve,attachmentMaxTotalBytes:oe,attachmentMaxCount:pe,undoSendSeconds:ae},delivery:j,sesRegion:o.sesRegion??"us-east-1",accounts:R,storagePath:o.storagePath??"/var/lib/mail",maxMessageSize:o.maxMessageSize??26214400,spam:{enabled:U.enabled??d,enforce:U.enforce??!1,junkScore:U.junkScore??5,rejectScore:U.rejectScore??12,dnsbl:U.dnsbl??d,dnsblReject:U.dnsblReject??!1,greylist:U.greylist??!1},webhookUrl:o.webhookUrl,expose:H,bindAddress:H?"0.0.0.0":"127.0.0.1"}}function Ze(n){if(!n.enabled||!n.expose)return[];let i=[n.ports.smtp,n.ports.submission,n.ports.submissions,n.ports.imap,n.ports.imaps,n.ports.managesieve].filter((s)=>typeof s==="number");if(n.webmail.enabled&&!n.webmail.domain)i.push(n.webmail.port);return[...new Set(i)].sort((s,o)=>s-o)}function Ji(n){if(!n.enabled)return{};let i=n.ports.submission??n.ports.smtp,s={MAIL_MAILER:"smtp",MAIL_HOST:"127.0.0.1",MAIL_PORT:String(i)};if(n.mode==="server"){s.MAIL_ENCRYPTION=n.tls.enabled?"tls":"null";let o=n.accounts[0];if(o)s.MAIL_USERNAME=o.address,s.MAIL_PASSWORD=o.password}else s.MAIL_ENCRYPTION="null",s.MAIL_USERNAME="null",s.MAIL_PASSWORD="null";return s}function ln(n){if(!n.enabled||!n.webmail.enabled||!n.webmail.domain)return{};let i=[n.webmail.domain,...n.webmail.aliases];if(!Number.isInteger(n.webmail.port)||n.webmail.port<1||n.webmail.port>65535)throw Error("Mail webmail port must be between 1 and 65535");return Object.fromEntries(i.map((s,o)=>{if(!/^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/i.test(s))throw Error(`Invalid mail webmail hostname: ${s}`);return[`__mail_webmail_${o}`,{domain:s,proxyTo:`localhost:${n.webmail.port}`}]}))}function w(n,i={}){let s=n.infrastructure?.compute?.proxy,o=b(n,i);if(!o.enabled||!o.webmail.enabled||!o.webmail.domain)return s;return{engine:"rpx",onDemandTls:!0,onDemandTlsEmail:o.tls.acmeEmail??`webmaster@${o.webmail.domain}`,...s}}function de(n){if(n.cloud?.provider)return n.cloud.provider;if(n.ssh?.hosts?.length)return"ssh";if(n.hetzner?.apiToken)return"hetzner";return"aws"}class al{template;constructor(n){this.template={AWSTemplateFormatVersion:"2010-09-09",Description:n,Resources:{}}}addResource(n,i){return this.template.Resources[n]=i,this}addResources(n){return Object.assign(this.template.Resources,n),this}addParameter(n,i){if(!this.template.Parameters)this.template.Parameters={};return this.template.Parameters[n]=i,this}addOutput(n,i){if(!this.template.Outputs)this.template.Outputs={};return this.template.Outputs[n]=i,this}addMetadata(n,i){if(!this.template.Metadata)this.template.Metadata={};return this.template.Metadata[n]=i,this}hasResource(n){return n in this.template.Resources}getResources(){return this.template.Resources}build(){return this.template}toJSON(n=!0){return JSON.stringify(this.template,null,n?2:0)}toYAML(){return this.convertToYAML(this.template)}convertToYAML(n,i=0){let s=" ".repeat(i),o="";for(let[c,u]of Object.entries(n)){if(u===null||u===void 0)continue;if(typeof u==="object"&&!Array.isArray(u))o+=`${s}${c}:
1
+ import{N,ga}from"./chunk-sjfc9my3.js";import{Sn,ls}from"./chunk-jz6dacx1.js";var Um={};Sn(Um,{default:()=>Fr,handler:()=>vt});var Qm={};Sn(Qm,{default:()=>Gr,handler:()=>Tt});var xf={};Sn(xf,{EmailAnalyticsModule:()=>Xe,EmailRules:()=>zt,EmailScheduling:()=>Kt,EmailSearch:()=>Ht,EmailTemplates:()=>Me,EmailThreading:()=>jt,SharedMailboxes:()=>qt});var Of={};Sn(Of,{default:()=>gs,handler:()=>ps});var _f={};Sn(_f,{CallAnalytics:()=>Jt,CallRecording:()=>Qt,Callbacks:()=>gt,IVRBuilder:()=>Ge});var Lf={};Sn(Lf,{AbTesting:()=>Ie,LinkTracking:()=>tn,MmsSupport:()=>Xt,SmsAnalytics:()=>Zt,SmsCampaigns:()=>Yt,SmsChatbot:()=>en});var WI={backgroundJobs:{visibilityTimeout:120,messageRetentionPeriod:604800,deadLetterQueue:!0,maxReceiveCount:3,encrypted:!0},fifo:{fifo:!0,contentBasedDeduplication:!0,visibilityTimeout:30,encrypted:!0},highThroughput:{visibilityTimeout:30,receiveMessageWaitTime:20,encrypted:!0},delayed:{delaySeconds:60,visibilityTimeout:60,encrypted:!0},longRunning:{visibilityTimeout:900,messageRetentionPeriod:1209600,deadLetterQueue:!0,maxReceiveCount:2,encrypted:!0},monitored:{visibilityTimeout:60,messageRetentionPeriod:604800,deadLetterQueue:!0,maxReceiveCount:3,encrypted:!0,alarms:{enabled:!0,queueDepthThreshold:1000,messageAgeThreshold:3600,dlqAlarm:!0}},lambdaOptimized:{visibilityTimeout:360,receiveMessageWaitTime:20,deadLetterQueue:!0,maxReceiveCount:3,encrypted:!0},fanOut:{visibilityTimeout:30,receiveMessageWaitTime:20,encrypted:!0}},JI={serverless:{development:{enabled:!0,mode:"serverless",channels:{public:!0,private:!0,presence:!0},storage:{type:"dynamodb",dynamodb:{billingMode:"PAY_PER_REQUEST"}},scaling:{maxConnections:1000,handlerMemory:128}},production:{enabled:!0,mode:"serverless",channels:{public:!0,private:!0,presence:{enabled:!0,maxMembers:100,heartbeatInterval:30,inactivityTimeout:60}},storage:{type:"dynamodb",dynamodb:{billingMode:"PAY_PER_REQUEST",pointInTimeRecovery:!0,connectionTTL:86400}},scaling:{maxConnections:50000,messagesPerSecond:5000,handlerMemory:256,handlerTimeout:30},monitoring:{enabled:!0,connectionThreshold:40000,errorThreshold:100,latencyThreshold:500},keepAlive:!0,keepAliveInterval:30,idleTimeout:600},notifications:{enabled:!0,mode:"serverless",channels:{public:!1,private:!0,presence:!1},storage:{type:"dynamodb",dynamodb:{billingMode:"PAY_PER_REQUEST"}},scaling:{maxConnections:50000,messagesPerSecond:2000,handlerMemory:128},keepAlive:!0,keepAliveInterval:60,idleTimeout:1800}},server:{development:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:!0},server:{host:"0.0.0.0",port:6001,scheme:"ws",driver:"bun",idleTimeout:120,perMessageDeflate:!1,metrics:!1}},production:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:!0},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:120,maxPayloadLength:16777216,backpressureLimit:1048576,sendPings:!0,perMessageDeflate:!0,instances:2,redis:{enabled:!0,keyPrefix:"broadcasting:"},rateLimit:{enabled:!0,max:100,window:60000,perChannel:!0,perUser:!0},loadManagement:{enabled:!0,maxConnections:1e4,maxSubscriptionsPerConnection:100,shedLoadThreshold:0.8},metrics:!0,autoScaling:{min:2,max:10,targetCPU:70}},monitoring:{enabled:!0,connectionThreshold:8000,errorThreshold:100}},highPerformance:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:!0},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:60,maxPayloadLength:8388608,backpressureLimit:2097152,closeOnBackpressureLimit:!0,sendPings:!0,perMessageDeflate:!0,instances:4,redis:{enabled:!0,useElastiCache:!0,keyPrefix:"rt:"},rateLimit:{enabled:!0,max:200,window:60000,perChannel:!0},loadManagement:{enabled:!0,maxConnections:25000,maxSubscriptionsPerConnection:50,shedLoadThreshold:0.7},metrics:{enabled:!0,path:"/metrics"},autoScaling:{min:4,max:20,targetCPU:60,targetConnections:20000}},monitoring:{enabled:!0,connectionThreshold:80000,errorThreshold:50,latencyThreshold:50}},chat:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:{enabled:!0,maxMembers:200,heartbeatInterval:20,inactivityTimeout:60}},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:300,maxPayloadLength:1048576,sendPings:!0,perMessageDeflate:!0,instances:2,redis:{enabled:!0,keyPrefix:"chat:"},rateLimit:{enabled:!0,max:60,window:60000,perChannel:!0},loadManagement:{enabled:!0,maxConnections:15000,maxSubscriptionsPerConnection:20},metrics:!0},keepAlive:!0,keepAliveInterval:25,idleTimeout:900},gaming:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:{enabled:!0,maxMembers:100,heartbeatInterval:10,inactivityTimeout:30}},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:30,maxPayloadLength:65536,backpressureLimit:524288,closeOnBackpressureLimit:!0,sendPings:!0,perMessageDeflate:!1,instances:4,redis:{enabled:!0,useElastiCache:!0},rateLimit:{enabled:!0,max:120,window:60000},loadManagement:{enabled:!0,maxConnections:5000,maxSubscriptionsPerConnection:10,shedLoadThreshold:0.6},metrics:!0,autoScaling:{min:4,max:16,targetCPU:50}},keepAlive:!0,keepAliveInterval:10,idleTimeout:60},single:{enabled:!0,mode:"server",channels:{public:!0,private:!0,presence:!0},server:{host:"0.0.0.0",port:6001,scheme:"wss",driver:"bun",idleTimeout:120,sendPings:!0,perMessageDeflate:!0,instances:1,rateLimit:{enabled:!0,max:100,window:60000},loadManagement:{enabled:!0,maxConnections:1e4},metrics:!0}}}};import{isAbsolute as At,join as et,relative as Ir}from"node:path";var ul=".ts-cloud",Dm="TS_CLOUD_STATE_DIR",Ct=null;function gl(n){Ct=n?.trim()||null}function pl(){return Boolean(process.env[Dm]?.trim()||Ct)}function ln(){return process.env[Dm]?.trim()||Ct||ul}function H(...n){return et(ln(),...n)}function l(n,...i){let s=ln();return At(s)?et(s,...i):et(n,s,...i)}function ml(n,i=process.cwd()){let s=(c,u)=>{let d=Ir(c,u);return d===""||!d.startsWith("..")&&!At(d)},o=At(n)?n:et(i,n);return s(l(i),o)}function Pm(n){let i=n.infrastructure?.compute!=null,s=Object.values(n.environments??{}).some((o)=>o?.app!=null);return{server:i,serverless:s}}function W(n){if(n.mode==="server"||n.mode==="serverless")return n.mode;let{serverless:i}=Pm(n);return i?"serverless":"server"}function fl(n){let{server:i,serverless:s}=Pm(n);if(i&&s)return"A project cannot be both a server and a serverless deployment. Found `infrastructure.compute` (server) AND `environments.<env>.app` (serverless Lambda). Keep one: remove `infrastructure.compute` for a serverless app, or remove `environments.<env>.app` for a server.";if(n.mode==="server"&&s&&!i)return"Config sets `mode: 'server'` but declares a serverless app (`environments.<env>.app`). Remove the app or change the mode.";if(n.mode==="serverless"&&i&&!s)return"Config sets `mode: 'serverless'` but declares a server (`infrastructure.compute`). Remove the compute block or change the mode.";return null}function p(n){return n.infrastructure?.appDatabase??n.infrastructure?.compute?.database}function Dr(n){return typeof n==="object"&&n!==null?n:{}}function gy(n){return n===!0||typeof n==="object"&&n!==null}function Nr(n,i){let s=i?n.environments?.[i]:void 0;if(s?.domain)return s.domain;let o=Object.values(n.sites??{}),c=n.sites?.main?.domain??o.find((u)=>u.domain)?.domain;if(c)return c;return`${n.project?.slug??"app"}.local`}function xr(n){let i=n.indexOf(".");return i>0?n.slice(i+1):void 0}function b(n,i={}){let s=n.infrastructure?.compute?.managedServices?.mail,o=Dr(s),c=i.environmentType??(i.environment?n.environments?.[i.environment]?.type:void 0),u=o.mode??(c==="production"?"server":"catcher"),d=u==="server",g=Nr(n,i.environment),y=o.hostname??(d?`mail.${g}`:"localhost"),h=o.ports??{},A=d?{smtp:h.smtp??25,submission:h.submission??587,submissions:h.submissions??465,imap:h.imap??143,imaps:h.imaps??993,webmail:h.webmail??8080,managesieve:h.managesieve}:{smtp:h.smtp??1025,submission:h.submission,submissions:h.submissions,imap:h.imap,imaps:h.imaps,webmail:h.webmail??8025,managesieve:h.managesieve},C=o.tls??{},v=C.enabled??d,T=!!(C.systemCredentials||C.certPath&&C.keyPath);if(C.systemCredentials&&Object.values(C.systemCredentials).some((de)=>!/^\/[a-z0-9_./-]+$/i.test(de)||de.includes("/../")))throw Error("Mail system credentials require absolute certificate paths");let R=(o.accounts??[]).map((de)=>({address:de.address,password:de.password,passwordPolicy:de.passwordPolicy??"initial"})),P=typeof o.dkim==="object"&&o.dkim!==null?o.dkim:{},I=o.dkim===!1?!1:o.dkim===!0||d,O=typeof o.webmail==="object"&&o.webmail!==null?o.webmail:{},B=o.webmail===!1?!1:O.enabled??!0,x=y.includes(".")&&!y.endsWith(".local")&&!/^\d+\.\d+\.\d+\.\d+$/.test(y),F=O.domain===!1?void 0:O.domain??(d&&x?y:void 0),G=O.tls??(F?!1:v),_=[...new Set(O.aliases??[])].filter((de)=>de!==F),U=o.spam??{},z=o.delivery??(d?"direct":"none"),K=o.expose??d,Q=xr(y),ae=[...new Set([y,...Q?[Q]:[],...o.domains??[]])],Pe=O.attachments?.maxFileBytes??20971520,ce=O.attachments?.maxTotalBytes??20971520,ye=O.attachments?.maxCount??20,oe=O.undoSendSeconds??10;for(let[de,Ne,Be]of[["maxFileBytes",Pe,104857600],["maxTotalBytes",ce,104857600],["maxCount",ye,100],["undoSendSeconds",oe,30]])if(!Number.isInteger(Ne)||Ne<0||Ne>Be)throw Error(`Mail webmail ${de} must be an integer from 0 to ${Be}`);return{enabled:gy(s),mode:u,version:o.version,hostname:y,domains:ae,ports:A,tls:{enabled:v,acme:v&&!T&&(C.acme??!0),certPath:C.systemCredentials?"/run/credentials/mail.service/server.crt":C.certPath,keyPath:C.systemCredentials?"/run/credentials/mail.service/server.key":C.keyPath,systemCredentials:C.systemCredentials,requireForAuth:C.requireForAuth??(v&&d),acmeEmail:C.acmeEmail??R[0]?.address},dkim:{enabled:I,selector:P.selector??"default",rotate:P.rotate??!1,rotateIntervalDays:P.rotateIntervalDays??90},webmail:{enabled:B,port:O.port??A.webmail,domain:F,aliases:_,tls:G,secureCookies:O.secureCookies??(!!F||G),attachmentMaxFileBytes:Pe,attachmentMaxTotalBytes:ce,attachmentMaxCount:ye,undoSendSeconds:oe},delivery:z,sesRegion:o.sesRegion??"us-east-1",accounts:R,storagePath:o.storagePath??"/var/lib/mail",maxMessageSize:o.maxMessageSize??26214400,spam:{enabled:U.enabled??d,enforce:U.enforce??!1,junkScore:U.junkScore??5,rejectScore:U.rejectScore??12,dnsbl:U.dnsbl??d,dnsblReject:U.dnsblReject??!1,greylist:U.greylist??!1},webhookUrl:o.webhookUrl,expose:K,bindAddress:K?"0.0.0.0":"127.0.0.1"}}function tt(n){if(!n.enabled||!n.expose)return[];let i=[n.ports.smtp,n.ports.submission,n.ports.submissions,n.ports.imap,n.ports.imaps,n.ports.managesieve].filter((s)=>typeof s==="number");if(n.webmail.enabled&&!n.webmail.domain)i.push(n.webmail.port);return[...new Set(i)].sort((s,o)=>s-o)}function Yi(n){if(!n.enabled)return{};let i=n.ports.submission??n.ports.smtp,s={MAIL_MAILER:"smtp",MAIL_HOST:"127.0.0.1",MAIL_PORT:String(i)};if(n.mode==="server"){s.MAIL_ENCRYPTION=n.tls.enabled?"tls":"null";let o=n.accounts[0];if(o)s.MAIL_USERNAME=o.address,s.MAIL_PASSWORD=o.password}else s.MAIL_ENCRYPTION="null",s.MAIL_USERNAME="null",s.MAIL_PASSWORD="null";return s}function un(n){if(!n.enabled||!n.webmail.enabled||!n.webmail.domain)return{};let i=[n.webmail.domain,...n.webmail.aliases];if(!Number.isInteger(n.webmail.port)||n.webmail.port<1||n.webmail.port>65535)throw Error("Mail webmail port must be between 1 and 65535");return Object.fromEntries(i.map((s,o)=>{if(!/^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/i.test(s))throw Error(`Invalid mail webmail hostname: ${s}`);return[`__mail_webmail_${o}`,{domain:s,proxyTo:`localhost:${n.webmail.port}`}]}))}function w(n,i={}){let s=n.infrastructure?.compute?.proxy,o=b(n,i);if(!o.enabled||!o.webmail.enabled||!o.webmail.domain)return s;return{engine:"rpx",onDemandTls:!0,onDemandTlsEmail:o.tls.acmeEmail??`webmaster@${o.webmail.domain}`,...s}}function le(n){if(n.cloud?.provider)return n.cloud.provider;if(n.ssh?.hosts?.length)return"ssh";if(n.hetzner?.apiToken)return"hetzner";return"aws"}class hl{template;constructor(n){this.template={AWSTemplateFormatVersion:"2010-09-09",Description:n,Resources:{}}}addResource(n,i){return this.template.Resources[n]=i,this}addResources(n){return Object.assign(this.template.Resources,n),this}addParameter(n,i){if(!this.template.Parameters)this.template.Parameters={};return this.template.Parameters[n]=i,this}addOutput(n,i){if(!this.template.Outputs)this.template.Outputs={};return this.template.Outputs[n]=i,this}addMetadata(n,i){if(!this.template.Metadata)this.template.Metadata={};return this.template.Metadata[n]=i,this}hasResource(n){return n in this.template.Resources}getResources(){return this.template.Resources}build(){return this.template}toJSON(n=!0){return JSON.stringify(this.template,null,n?2:0)}toYAML(){return this.convertToYAML(this.template)}convertToYAML(n,i=0){let s=" ".repeat(i),o="";for(let[c,u]of Object.entries(n)){if(u===null||u===void 0)continue;if(typeof u==="object"&&!Array.isArray(u))o+=`${s}${c}:
2
2
  ${this.convertToYAML(u,i+1)}`;else if(Array.isArray(u)){o+=`${s}${c}:
3
3
  `;for(let d of u)if(typeof d==="object")o+=`${s} -
4
4
  ${this.convertToYAML(d,i+2)}`;else o+=`${s} - ${d}
5
5
  `}else o+=`${s}${c}: ${u}
6
- `}return o}}var x={Ref:(n)=>({Ref:n}),GetAtt:(n,i)=>({"Fn::GetAtt":[n,i]}),Sub:(n,i)=>{if(i)return{"Fn::Sub":[n,i]};return{"Fn::Sub":n}},Join:(n,i)=>({"Fn::Join":[n,i]}),Select:(n,i)=>({"Fn::Select":[n,i]}),Split:(n,i)=>({"Fn::Split":[n,i]}),GetAZs:(n="")=>({"Fn::GetAZs":n}),ImportValue:(n)=>({"Fn::ImportValue":n}),If:(n,i,s)=>({"Fn::If":[n,i,s]}),Equals:(n,i)=>({"Fn::Equals":[n,i]}),And:(...n)=>({"Fn::And":n}),Or:(...n)=>({"Fn::Or":n}),Not:(n)=>({"Fn::Not":[n]}),Base64:(n)=>({"Fn::Base64":n})},ny={AccountId:{Ref:"AWS::AccountId"},Region:{Ref:"AWS::Region"},StackId:{Ref:"AWS::StackId"},StackName:{Ref:"AWS::StackName"},NotificationARNs:{Ref:"AWS::NotificationARNs"},Partition:{Ref:"AWS::Partition"},URLSuffix:{Ref:"AWS::URLSuffix"},NoValue:{Ref:"AWS::NoValue"}};function r(n){let{slug:i,environment:s,resourceType:o,timestamp:c,suffix:u}=n,d=[i,s,o];if(c)d.push(c);if(u)d.push(u);return d.join("-")}function t(n){return n.split("-").map((i)=>i.charAt(0).toUpperCase()+i.slice(1)).join("")}function FI(){return Date.now().toString()}function UI(n){return n.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/^-+|-+$/g,"").replace(/-+/g,"-")}function m(n,i){return n.project.stackName??`${n.project.slug}-${i}`}function QI(n,i,s,o){return s.stackName??`${n.project.slug}-${o}-${i}-site`}function HI(n,i){return`${n.project.slug}-${i}`}function GI(n,i,s,o){if(o)return o;if(s==="main")return`${n}-${i}-site`;return`${n}-${i}-${s}`}function VI(n,i,s,o){return o??`${n}-${i}-${s}`}function qI(n,i){return`${n}-${i}-deploy`}function lr(n,i){return`${n.project.slug}-${i}-app`}function cl(n,i){return`${n}-${i}-deployments`}function Xi(n,i){return`${n}-${i}-assets`}class iy{nodes=new Map;addResource(n,i){let s=this.extractDependencies(i);this.nodes.set(n,{logicalId:n,resource:i,dependencies:s})}extractDependencies(n){let i=new Set;if(n.DependsOn)if(Array.isArray(n.DependsOn))n.DependsOn.forEach((s)=>i.add(s));else i.add(n.DependsOn);return this.findReferences(n.Properties||{},i),i}findReferences(n,i){if(!n||typeof n!=="object")return;if("Ref"in n&&typeof n.Ref==="string"){if(!n.Ref.startsWith("AWS::"))i.add(n.Ref)}if("Fn::GetAtt"in n&&Array.isArray(n["Fn::GetAtt"]))i.add(n["Fn::GetAtt"][0]);for(let s of Object.values(n))if(typeof s==="object")this.findReferences(s,i)}topologicalSort(){let n=[],i=new Set,s=new Set,o=(c)=>{if(i.has(c))return;if(s.has(c))throw Error(`Circular dependency detected: ${c}`);s.add(c);let u=this.nodes.get(c);if(u)for(let d of u.dependencies)o(d);s.delete(c),i.add(c),n.push(c)};for(let c of this.nodes.keys())o(c);return n}validate(){for(let[n,i]of this.nodes.entries())for(let s of i.dependencies)if(!this.nodes.has(s))throw Error(`Resource "${n}" depends on "${s}" which does not exist`)}getDependents(n){let i=[];for(let[s,o]of this.nodes.entries())if(o.dependencies.has(n))i.push(s);return i}}function jI(n,i){let s=[],o=[],c=[],u=[],d=[],g=n.Resources||{},y=i.Resources||{},h=new Set([...Object.keys(g),...Object.keys(y)]);for(let C of h){let v=g[C],T=y[C];if(!v&&T)s.push({logicalId:C,action:"add",resourceType:T.Type});else if(v&&!T)o.push({logicalId:C,action:"remove",resourceType:v.Type});else if(v&&T)if(v.Type!==T.Type)u.push({logicalId:C,action:"replace",resourceType:T.Type,reason:`Type changed from ${v.Type} to ${T.Type}`});else{let R=tn(v.Properties||{},T.Properties||{});if(R.length>0)if(yr(v.Type,R))u.push({logicalId:C,action:"replace",resourceType:T.Type,changes:R,reason:"Property changes require replacement"});else c.push({logicalId:C,action:"update",resourceType:T.Type,changes:R});else d.push(C)}}let A=br([...o,...u,...c]);return{added:s,removed:o,updated:c,replaced:u,unchanged:d,summary:{totalChanges:s.length+o.length+c.length+u.length,requiresReplacement:u.length>0,dangerousChanges:A}}}function tn(n,i,s=""){let o=[],c=new Set([...Object.keys(n),...Object.keys(i)]);for(let u of c){let d=s?`${s}.${u}`:u,g=n[u],y=i[u];if(g===void 0&&y!==void 0)o.push({path:d,oldValue:void 0,newValue:y});else if(g!==void 0&&y===void 0)o.push({path:d,oldValue:g,newValue:void 0});else if(typeof g!==typeof y)o.push({path:d,oldValue:g,newValue:y});else if(typeof g==="object"&&g!==null)if(Array.isArray(g)&&Array.isArray(y)){if(JSON.stringify(g)!==JSON.stringify(y))o.push({path:d,oldValue:g,newValue:y})}else if(!Array.isArray(g)&&!Array.isArray(y)){let h=tn(g,y,d);o.push(...h)}else o.push({path:d,oldValue:g,newValue:y});else if(g!==y)o.push({path:d,oldValue:g,newValue:y})}return o}function yr(n,i){let o={"AWS::S3::Bucket":new Set(["BucketName"]),"AWS::DynamoDB::Table":new Set(["TableName","KeySchema"]),"AWS::RDS::DBInstance":new Set(["DBInstanceIdentifier","DBName","Engine"]),"AWS::Lambda::Function":new Set(["FunctionName"]),"AWS::EC2::Instance":new Set(["ImageId","InstanceType","KeyName"]),"AWS::ECS::TaskDefinition":new Set(["Family","ContainerDefinitions"]),"AWS::ElastiCache::CacheCluster":new Set(["CacheNodeType","Engine"]),"AWS::CloudFront::Distribution":new Set([]),"AWS::Route53::HostedZone":new Set(["Name"]),"AWS::IAM::Role":new Set(["RoleName","Path"]),"AWS::KMS::Key":new Set(["KeyPolicy"]),"AWS::Cognito::UserPool":new Set(["UserPoolName"]),"AWS::OpenSearchService::Domain":new Set(["DomainName"])}[n];if(!o)return!1;for(let c of i){let u=c.path.split(".")[0];if(o.has(u))return!0}return!1}function br(n){let i=[];for(let s of n){if(s.action==="remove"&&(s.resourceType==="AWS::RDS::DBInstance"||s.resourceType==="AWS::DynamoDB::Table"||s.resourceType==="AWS::ElastiCache::CacheCluster"))i.push(`Removing ${s.resourceType} ${s.logicalId} - data loss risk!`);if(s.action==="replace"&&(s.resourceType==="AWS::RDS::DBInstance"||s.resourceType==="AWS::DynamoDB::Table"))i.push(`Replacing ${s.resourceType} ${s.logicalId} - data loss risk!`);if((s.action==="remove"||s.action==="replace")&&s.resourceType==="AWS::S3::Bucket")i.push(`${s.action==="remove"?"Removing":"Replacing"} S3 bucket ${s.logicalId} - data loss risk!`);if(s.action==="replace"&&s.resourceType==="AWS::EC2::Instance")i.push(`Replacing EC2 instance ${s.logicalId} - downtime expected`);if(s.action==="update"&&s.resourceType==="AWS::EC2::SecurityGroup")i.push(`Updating security group ${s.logicalId} - may affect connectivity`);if((s.action==="update"||s.action==="replace")&&(s.resourceType==="AWS::IAM::Role"||s.resourceType==="AWS::IAM::Policy"))i.push(`Modifying IAM ${s.resourceType.split("::")[2]} ${s.logicalId} - may affect permissions`)}return i}function zI(n){let i=[];if(i.push(`=== Stack Update Analysis ===
6
+ `}return o}}var M={Ref:(n)=>({Ref:n}),GetAtt:(n,i)=>({"Fn::GetAtt":[n,i]}),Sub:(n,i)=>{if(i)return{"Fn::Sub":[n,i]};return{"Fn::Sub":n}},Join:(n,i)=>({"Fn::Join":[n,i]}),Select:(n,i)=>({"Fn::Select":[n,i]}),Split:(n,i)=>({"Fn::Split":[n,i]}),GetAZs:(n="")=>({"Fn::GetAZs":n}),ImportValue:(n)=>({"Fn::ImportValue":n}),If:(n,i,s)=>({"Fn::If":[n,i,s]}),Equals:(n,i)=>({"Fn::Equals":[n,i]}),And:(...n)=>({"Fn::And":n}),Or:(...n)=>({"Fn::Or":n}),Not:(n)=>({"Fn::Not":[n]}),Base64:(n)=>({"Fn::Base64":n})},py={AccountId:{Ref:"AWS::AccountId"},Region:{Ref:"AWS::Region"},StackId:{Ref:"AWS::StackId"},StackName:{Ref:"AWS::StackName"},NotificationARNs:{Ref:"AWS::NotificationARNs"},Partition:{Ref:"AWS::Partition"},URLSuffix:{Ref:"AWS::URLSuffix"},NoValue:{Ref:"AWS::NoValue"}};function r(n){let{slug:i,environment:s,resourceType:o,timestamp:c,suffix:u}=n,d=[i,s,o];if(c)d.push(c);if(u)d.push(u);return d.join("-")}function t(n){return n.split("-").map((i)=>i.charAt(0).toUpperCase()+i.slice(1)).join("")}function XI(){return Date.now().toString()}function YI(n){return n.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/^-+|-+$/g,"").replace(/-+/g,"-")}function m(n,i){return n.project.stackName??`${n.project.slug}-${i}`}function ZI(n,i,s,o){return s.stackName??`${n.project.slug}-${o}-${i}-site`}function eb(n,i){return`${n.project.slug}-${i}`}function tb(n,i,s,o){if(o)return o;if(s==="main")return`${n}-${i}-site`;return`${n}-${i}-${s}`}function rb(n,i,s,o){return o??`${n}-${i}-${s}`}function nb(n,i){return`${n}-${i}-deploy`}function ur(n,i){return`${n.project.slug}-${i}-app`}function Al(n,i){return`${n}-${i}-deployments`}function Zi(n,i){return`${n}-${i}-assets`}class my{nodes=new Map;addResource(n,i){let s=this.extractDependencies(i);this.nodes.set(n,{logicalId:n,resource:i,dependencies:s})}extractDependencies(n){let i=new Set;if(n.DependsOn)if(Array.isArray(n.DependsOn))n.DependsOn.forEach((s)=>i.add(s));else i.add(n.DependsOn);return this.findReferences(n.Properties||{},i),i}findReferences(n,i){if(!n||typeof n!=="object")return;if("Ref"in n&&typeof n.Ref==="string"){if(!n.Ref.startsWith("AWS::"))i.add(n.Ref)}if("Fn::GetAtt"in n&&Array.isArray(n["Fn::GetAtt"]))i.add(n["Fn::GetAtt"][0]);for(let s of Object.values(n))if(typeof s==="object")this.findReferences(s,i)}topologicalSort(){let n=[],i=new Set,s=new Set,o=(c)=>{if(i.has(c))return;if(s.has(c))throw Error(`Circular dependency detected: ${c}`);s.add(c);let u=this.nodes.get(c);if(u)for(let d of u.dependencies)o(d);s.delete(c),i.add(c),n.push(c)};for(let c of this.nodes.keys())o(c);return n}validate(){for(let[n,i]of this.nodes.entries())for(let s of i.dependencies)if(!this.nodes.has(s))throw Error(`Resource "${n}" depends on "${s}" which does not exist`)}getDependents(n){let i=[];for(let[s,o]of this.nodes.entries())if(o.dependencies.has(n))i.push(s);return i}}function ib(n,i){let s=[],o=[],c=[],u=[],d=[],g=n.Resources||{},y=i.Resources||{},h=new Set([...Object.keys(g),...Object.keys(y)]);for(let C of h){let v=g[C],T=y[C];if(!v&&T)s.push({logicalId:C,action:"add",resourceType:T.Type});else if(v&&!T)o.push({logicalId:C,action:"remove",resourceType:v.Type});else if(v&&T)if(v.Type!==T.Type)u.push({logicalId:C,action:"replace",resourceType:T.Type,reason:`Type changed from ${v.Type} to ${T.Type}`});else{let R=on(v.Properties||{},T.Properties||{});if(R.length>0)if(kr(v.Type,R))u.push({logicalId:C,action:"replace",resourceType:T.Type,changes:R,reason:"Property changes require replacement"});else c.push({logicalId:C,action:"update",resourceType:T.Type,changes:R});else d.push(C)}}let A=Mr([...o,...u,...c]);return{added:s,removed:o,updated:c,replaced:u,unchanged:d,summary:{totalChanges:s.length+o.length+c.length+u.length,requiresReplacement:u.length>0,dangerousChanges:A}}}function on(n,i,s=""){let o=[],c=new Set([...Object.keys(n),...Object.keys(i)]);for(let u of c){let d=s?`${s}.${u}`:u,g=n[u],y=i[u];if(g===void 0&&y!==void 0)o.push({path:d,oldValue:void 0,newValue:y});else if(g!==void 0&&y===void 0)o.push({path:d,oldValue:g,newValue:void 0});else if(typeof g!==typeof y)o.push({path:d,oldValue:g,newValue:y});else if(typeof g==="object"&&g!==null)if(Array.isArray(g)&&Array.isArray(y)){if(JSON.stringify(g)!==JSON.stringify(y))o.push({path:d,oldValue:g,newValue:y})}else if(!Array.isArray(g)&&!Array.isArray(y)){let h=on(g,y,d);o.push(...h)}else o.push({path:d,oldValue:g,newValue:y});else if(g!==y)o.push({path:d,oldValue:g,newValue:y})}return o}function kr(n,i){let o={"AWS::S3::Bucket":new Set(["BucketName"]),"AWS::DynamoDB::Table":new Set(["TableName","KeySchema"]),"AWS::RDS::DBInstance":new Set(["DBInstanceIdentifier","DBName","Engine"]),"AWS::Lambda::Function":new Set(["FunctionName"]),"AWS::EC2::Instance":new Set(["ImageId","InstanceType","KeyName"]),"AWS::ECS::TaskDefinition":new Set(["Family","ContainerDefinitions"]),"AWS::ElastiCache::CacheCluster":new Set(["CacheNodeType","Engine"]),"AWS::CloudFront::Distribution":new Set([]),"AWS::Route53::HostedZone":new Set(["Name"]),"AWS::IAM::Role":new Set(["RoleName","Path"]),"AWS::KMS::Key":new Set(["KeyPolicy"]),"AWS::Cognito::UserPool":new Set(["UserPoolName"]),"AWS::OpenSearchService::Domain":new Set(["DomainName"])}[n];if(!o)return!1;for(let c of i){let u=c.path.split(".")[0];if(o.has(u))return!0}return!1}function Mr(n){let i=[];for(let s of n){if(s.action==="remove"&&(s.resourceType==="AWS::RDS::DBInstance"||s.resourceType==="AWS::DynamoDB::Table"||s.resourceType==="AWS::ElastiCache::CacheCluster"))i.push(`Removing ${s.resourceType} ${s.logicalId} - data loss risk!`);if(s.action==="replace"&&(s.resourceType==="AWS::RDS::DBInstance"||s.resourceType==="AWS::DynamoDB::Table"))i.push(`Replacing ${s.resourceType} ${s.logicalId} - data loss risk!`);if((s.action==="remove"||s.action==="replace")&&s.resourceType==="AWS::S3::Bucket")i.push(`${s.action==="remove"?"Removing":"Replacing"} S3 bucket ${s.logicalId} - data loss risk!`);if(s.action==="replace"&&s.resourceType==="AWS::EC2::Instance")i.push(`Replacing EC2 instance ${s.logicalId} - downtime expected`);if(s.action==="update"&&s.resourceType==="AWS::EC2::SecurityGroup")i.push(`Updating security group ${s.logicalId} - may affect connectivity`);if((s.action==="update"||s.action==="replace")&&(s.resourceType==="AWS::IAM::Role"||s.resourceType==="AWS::IAM::Policy"))i.push(`Modifying IAM ${s.resourceType.split("::")[2]} ${s.logicalId} - may affect permissions`)}return i}function sb(n){let i=[];if(i.push(`=== Stack Update Analysis ===
7
7
  `),n.summary.totalChanges===0)return i.push(`No changes detected.
8
8
  `),i.join(`
9
9
  `);if(i.push(`Total changes: ${n.summary.totalChanges}`),i.push(`Requires replacement: ${n.summary.requiresReplacement?"Yes":"No"}
10
10
  `),n.summary.dangerousChanges.length>0){i.push("⚠️ DANGEROUS CHANGES DETECTED:");for(let s of n.summary.dangerousChanges)i.push(` • ${s}`);i.push("")}if(n.added.length>0){i.push(`✅ Resources to Add (${n.added.length}):`);for(let s of n.added)i.push(` + ${s.logicalId} (${s.resourceType})`);i.push("")}if(n.removed.length>0){i.push(`❌ Resources to Remove (${n.removed.length}):`);for(let s of n.removed)i.push(` - ${s.logicalId} (${s.resourceType})`);i.push("")}if(n.replaced.length>0){i.push(`\uD83D\uDD04 Resources to Replace (${n.replaced.length}):`);for(let s of n.replaced){if(i.push(` ~ ${s.logicalId} (${s.resourceType})`),s.reason)i.push(` Reason: ${s.reason}`);if(s.changes){for(let o of s.changes.slice(0,3))i.push(` • ${o.path}: ${JSON.stringify(o.oldValue)} → ${JSON.stringify(o.newValue)}`);if(s.changes.length>3)i.push(` ... and ${s.changes.length-3} more changes`)}}i.push("")}if(n.updated.length>0){i.push(`\uD83D\uDCDD Resources to Update (${n.updated.length}):`);for(let s of n.updated)if(i.push(` ~ ${s.logicalId} (${s.resourceType})`),s.changes){for(let o of s.changes.slice(0,3))i.push(` • ${o.path}: ${JSON.stringify(o.oldValue)} → ${JSON.stringify(o.newValue)}`);if(s.changes.length>3)i.push(` ... and ${s.changes.length-3} more changes`)}i.push("")}if(n.unchanged.length>0)i.push(`⚪ Unchanged Resources (${n.unchanged.length})`);return i.join(`
11
- `)}import{existsSync as He,readdirSync as Sr}from"node:fs";import{join as Re}from"node:path";class xe{static createBucket(n){let{name:i,bucketName:s,slug:o,environment:c,public:u=!1,versioning:d=!1,website:g=!1,encryption:y=!0,intelligentTiering:h=!1,cors:A,lifecycleRules:C}=n,v=s??r({slug:o,environment:c,resourceType:"s3",suffix:i}),T=t(v),R={Type:"AWS::S3::Bucket",Properties:{BucketName:v}};if(y)R.Properties.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(d)R.Properties.VersioningConfiguration={Status:"Enabled"};if(g)R.Properties.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"error.html"};if(!u)R.Properties.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(A&&A.length>0)R.Properties.CorsConfiguration={CorsRules:A.map((I)=>({AllowedOrigins:I.allowedOrigins,AllowedMethods:I.allowedMethods,AllowedHeaders:I.allowedHeaders,MaxAge:I.maxAge}))};if(C&&C.length>0)R.Properties.LifecycleConfiguration={Rules:C.map((I)=>({Id:I.id,Status:I.enabled?"Enabled":"Disabled",ExpirationInDays:I.expirationDays,Transitions:I.transitions?.map((M)=>({TransitionInDays:M.days,StorageClass:M.storageClass}))}))};if(h&&C){let I={id:"IntelligentTieringRule",enabled:!0,transitions:[{days:0,storageClass:"INTELLIGENT_TIERING"}]};if(!R.Properties.LifecycleConfiguration)R.Properties.LifecycleConfiguration={Rules:[]};R.Properties.LifecycleConfiguration.Rules.push({Id:I.id,Status:"Enabled",Transitions:I.transitions?.map((M)=>({TransitionInDays:M.days,StorageClass:M.storageClass}))})}let P;if(u)P={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:x.Ref(T),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[x.Join("",[x.GetAtt(T,"Arn"),"/*"])]}]}}};return{bucket:R,bucketPolicy:P,logicalId:T}}static enableVersioning(n){if(!n.Properties)n.Properties={};return n.Properties.VersioningConfiguration={Status:"Enabled"},n}static enableWebsiteHosting(n,i="index.html",s="error.html"){if(!n.Properties)n.Properties={};return n.Properties.WebsiteConfiguration={IndexDocument:i,ErrorDocument:s},n}static setLifecycleRules(n,i){if(!n.Properties)n.Properties={};return n.Properties.LifecycleConfiguration={Rules:i.map((s)=>({Id:s.id,Status:s.enabled?"Enabled":"Disabled",ExpirationInDays:s.expirationDays,Transitions:s.transitions?.map((o)=>({TransitionInDays:o.days,StorageClass:o.storageClass}))}))},n}static enableIntelligentTiering(n){if(!n.Properties)n.Properties={};if(!n.Properties.LifecycleConfiguration)n.Properties.LifecycleConfiguration={Rules:[]};return n.Properties.LifecycleConfiguration.Rules.push({Id:"IntelligentTieringRule",Status:"Enabled",Transitions:[{TransitionInDays:0,StorageClass:"INTELLIGENT_TIERING"}]}),n}static addLambdaNotification(n,i){if(!n.Properties)n.Properties={};if(!n.Properties.NotificationConfiguration)n.Properties.NotificationConfiguration={};if(!n.Properties.NotificationConfiguration.LambdaConfigurations)n.Properties.NotificationConfiguration.LambdaConfigurations=[];let s={Event:i.events[0],Function:i.functionArn};if(i.filter)s.Filter={S3Key:{Rules:[...i.filter.prefix?[{Name:"prefix",Value:i.filter.prefix}]:[],...i.filter.suffix?[{Name:"suffix",Value:i.filter.suffix}]:[]]}};for(let o of i.events){let c={...s,Event:o};n.Properties.NotificationConfiguration.LambdaConfigurations.push(c)}return n}static Notifications={onObjectCreated:(n)=>({functionArn:n,events:["s3:ObjectCreated:*"]}),onObjectRemoved:(n)=>({functionArn:n,events:["s3:ObjectRemoved:*"]}),onImageUpload:(n,i)=>({functionArn:n,events:["s3:ObjectCreated:*"],filter:{prefix:i,suffix:".jpg"}}),onFileType:(n,i,s)=>({functionArn:n,events:["s3:ObjectCreated:*"],filter:{prefix:s,suffix:i}}),onFolderUpload:(n,i)=>({functionArn:n,events:["s3:ObjectCreated:*"],filter:{prefix:i.endsWith("/")?i:`${i}/`}})};static createBackupPlan(n){let{name:i,slug:s,environment:o,bucketLogicalIds:c,retentionDays:u,schedule:d="cron(0 5 * * ? *)",vaultName:g,enableContinuousBackup:y=!1,moveToColdStorageAfterDays:h}=n,A=g||r({slug:s,environment:o,resourceType:"backup-vault",suffix:i}),C=t(A),v={Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:A}},T=r({slug:s,environment:o,resourceType:"backup-role",suffix:i}),R=t(T),P={Type:"AWS::IAM::Role",Properties:{RoleName:T,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"backup.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup","arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForRestores"]}},I=r({slug:s,environment:o,resourceType:"backup-plan",suffix:i}),M=t(I),L={DeleteAfterDays:u};if(h&&h<u)L.MoveToColdStorageAfterDays=h;let N={Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:I,BackupPlanRule:[{RuleName:`${i}-daily-backup`,TargetBackupVault:x.Ref(C),ScheduleExpression:d,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:L,EnableContinuousBackup:y}]}}},O=r({slug:s,environment:o,resourceType:"backup-selection",suffix:i}),B=t(O),F=c.map((j)=>x.GetAtt(j,"Arn")),U={Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:x.Ref(M),BackupSelection:{SelectionName:O,IamRoleArn:x.GetAtt(R,"Arn"),Resources:F}}};return{vault:v,plan:N,selection:U,role:P,vaultLogicalId:C,planLogicalId:M,selectionLogicalId:B,roleLogicalId:R}}static BackupSchedules={HOURLY:"cron(0 * * * ? *)",DAILY_5AM:"cron(0 5 * * ? *)",DAILY_MIDNIGHT:"cron(0 0 * * ? *)",WEEKLY_SUNDAY:"cron(0 5 ? * SUN *)",WEEKLY_SATURDAY:"cron(0 5 ? * SAT *)",MONTHLY_FIRST:"cron(0 5 1 * ? *)",EVERY_12_HOURS:"cron(0 */12 * * ? *)",EVERY_6_HOURS:"cron(0 */6 * * ? *)"};static BackupRetention={ONE_DAY:1,ONE_WEEK:7,TWO_WEEKS:14,ONE_MONTH:30,THREE_MONTHS:90,SIX_MONTHS:180,ONE_YEAR:365,TWO_YEARS:730,FIVE_YEARS:1825,SEVEN_YEARS:2555};static createWwwRedirectBucket(n){let{slug:i,environment:s,sourceDomain:o,targetDomain:c,protocol:u="https"}=n,d=r({slug:i,environment:s,resourceType:"s3",suffix:"www-redirect"}),g=t(d),y={Type:"AWS::S3::Bucket",Properties:{BucketName:o,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:c,Protocol:u}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1}}},h={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:x.Ref(g),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[x.Join("",[x.GetAtt(g,"Arn"),"/*"])]}]}}};return{bucket:y,bucketPolicy:h,logicalId:g}}static createDocsBucket(n){let{slug:i,environment:s,domain:o}=n,c=o||r({slug:i,environment:s,resourceType:"s3",suffix:"docs"}),u=t(c);return{bucket:{Type:"AWS::S3::Bucket",Properties:{BucketName:c,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},Tags:[{Key:"backup",Value:"weekly"}]}},logicalId:u}}static createEmailBucket(n){let{slug:i,environment:s}=n,o=r({slug:i,environment:s,resourceType:"s3",suffix:"email"}),c=t(o),u={Type:"AWS::S3::Bucket",Properties:{BucketName:o,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},LifecycleConfiguration:{Rules:[{Id:"EmailRetention",Status:"Enabled",ExpirationInDays:90,Transitions:[{TransitionInDays:30,StorageClass:"STANDARD_IA"}]}]}}},d={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:x.Ref(c),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowSESPuts",Effect:"Allow",Principal:{Service:"ses.amazonaws.com"},Action:"s3:PutObject",Resource:x.Join("",[x.GetAtt(c,"Arn"),"/*"]),Condition:{StringEquals:{"AWS:SourceAccount":x.Ref("AWS::AccountId")}}}]}}};return{bucket:u,bucketPolicy:d,logicalId:c}}static docsExist(n={}){let{projectRoot:i=process.cwd(),docsPaths:s=["docs","documentation","doc"]}=n;for(let o of s){let c=Re(i,o);if(He(c)){let u=["dist","build",".bunpress/dist","_site","out","public"];for(let d of u){let g=Re(c,d);if(He(g))try{if(Sr(g).length>0)return{exists:!0,path:c,hasDistFolder:!0,distPath:g}}catch{}}return{exists:!0,path:c,hasDistFolder:!1,distPath:null}}}return{exists:!1,path:null,hasDistFolder:!1,distPath:null}}static createDocsBucketIfExists(n){let i=xe.docsExist({projectRoot:n.projectRoot,docsPaths:n.docsPaths});if(!i.exists)return{bucket:null,logicalId:null,docsInfo:i};let s=xe.createDocsBucket({slug:n.slug,environment:n.environment,domain:n.domain});return{bucket:s.bucket,bucketPolicy:s.bucketPolicy,logicalId:s.logicalId,docsInfo:i}}static createPrivateBucket(n){let{slug:i,environment:s,enableVersioning:o=!0,retentionDays:c,encryptionKeyArn:u}=n,d=r({slug:i,environment:s,resourceType:"s3",suffix:"private"}),g=t(d);return{bucket:{Type:"AWS::S3::Bucket",Properties:{BucketName:d,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:u?{SSEAlgorithm:"aws:kms",KMSMasterKeyID:u}:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},VersioningConfiguration:o?{Status:"Enabled"}:void 0,LifecycleConfiguration:c?{Rules:[{Id:"RetentionPolicy",Status:"Enabled",ExpirationInDays:c}]}:void 0,Tags:[{Key:"backup",Value:"daily"}]}},logicalId:g}}static checkSourcePaths(n={}){let{projectRoot:i=process.cwd(),paths:s={}}=n,o=s.web||"views/web/dist",c=s.docs||"docs/dist",u=s.private||"private";return{web:{exists:He(Re(i,o)),path:Re(i,o)},docs:{exists:He(Re(i,c)),path:Re(i,c)},private:{exists:He(Re(i,u)),path:Re(i,u)}}}static createDeploymentBuckets(n){let{slug:i,environment:s,domain:o,projectRoot:c,paths:u}=n,d=xe.checkSourcePaths({projectRoot:c,paths:u}),g={},y={web:!1,docs:!1,private:!1},h=xe.createBucket({name:"web",slug:i,environment:s,public:!1,versioning:!1,encryption:!0});if(g[h.logicalId]=h.bucket,y.web=!0,d.docs.exists){let A=xe.createDocsBucket({slug:i,environment:s,domain:o?`docs.${o}`:void 0});if(g[A.logicalId]=A.bucket,A.bucketPolicy)g[`${A.logicalId}Policy`]=A.bucketPolicy;y.docs=!0}if(d.private.exists){let A=xe.createPrivateBucket({slug:i,environment:s,enableVersioning:!0});g[A.logicalId]=A.bucket,y.private=!0}return{resources:g,created:y,sourcePaths:d}}}class et{static createRepository(n){let{name:i,slug:s,environment:o,scanOnPush:c=!0,imageMutability:u="MUTABLE",encryption:d="AES256",kmsKey:g,lifecyclePolicy:y,tags:h}=n,A=r({slug:s,environment:o,resourceType:"ecr",suffix:i}),C=t(A),v={Type:"AWS::ECR::Repository",Properties:{RepositoryName:A,ImageTagMutability:u,ImageScanningConfiguration:{ScanOnPush:c},EncryptionConfiguration:{EncryptionType:d,...g&&d==="KMS"?{KmsKey:g}:{}}}};if(y)v.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(et.generateLifecyclePolicy(y))};if(h)v.Properties.Tags=Object.entries(h).map(([T,R])=>({Key:T,Value:R}));return{repository:v,logicalId:C}}static generateLifecyclePolicy(n){let i=[];if(n.untaggedImageExpireDays!==void 0)i.push({rulePriority:1,description:"Delete untagged images",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:n.untaggedImageExpireDays,countUnit:"days"},action:{type:"expire"}});if(n.maxImageCount!==void 0)i.push({rulePriority:i.length+1,description:"Keep only most recent images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:n.maxImageCount},action:{type:"expire"}});if(n.maxImageAgeDays!==void 0)i.push({rulePriority:i.length+1,description:"Delete images older than specified days",selection:{tagStatus:"any",countType:"sinceImagePushed",countNumber:n.maxImageAgeDays,countUnit:"days"},action:{type:"expire"}});return{rules:i}}static LifecyclePolicies={production:{maxImageCount:10,untaggedImageExpireDays:7},development:{maxImageCount:5,untaggedImageExpireDays:3},minimal:{maxImageCount:3,untaggedImageExpireDays:1},archive:{maxImageCount:50,untaggedImageExpireDays:30}};static enableImmutableTags(n){if(!n.Properties)n.Properties={};return n.Properties.ImageTagMutability="IMMUTABLE",n}static enableScanOnPush(n){if(!n.Properties)n.Properties={};return n.Properties.ImageScanningConfiguration={ScanOnPush:!0},n}static setLifecyclePolicy(n,i){if(!n.Properties)n.Properties={};return n.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(et.generateLifecyclePolicy(i))},n}static addCrossAccountAccess(n,i){if(!n.Properties)n.Properties={};return n.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"CrossAccountPull",Effect:"Allow",Principal:{AWS:i.map((s)=>`arn:aws:iam::${s}:root`)},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:BatchCheckLayerAvailability"]}]},n}static addLambdaAccess(n){if(!n.Properties)n.Properties={};return n.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"LambdaECRImageRetrievalPolicy",Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage"]}]},n}static generateBunDockerfile(n){let{baseImage:i="oven/bun:1-debian",serverPath:s,port:o=3000,additionalDirs:c=[],healthCheckEndpoint:u="/health",nodeCompatible:d=!1,envVars:g={},buildCommands:y=[],runCommand:h}=n,A=["app","config",...c],C=h||`bun run ${s}`,v=`# Multi-stage build for Bun application
11
+ `)}import{existsSync as Ke,readdirSync as Lr}from"node:fs";import{join as we}from"node:path";class _e{static createBucket(n){let{name:i,bucketName:s,slug:o,environment:c,public:u=!1,versioning:d=!1,website:g=!1,encryption:y=!0,intelligentTiering:h=!1,cors:A,lifecycleRules:C}=n,v=s??r({slug:o,environment:c,resourceType:"s3",suffix:i}),T=t(v),R={Type:"AWS::S3::Bucket",Properties:{BucketName:v}};if(y)R.Properties.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(d)R.Properties.VersioningConfiguration={Status:"Enabled"};if(g)R.Properties.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"error.html"};if(!u)R.Properties.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(A&&A.length>0)R.Properties.CorsConfiguration={CorsRules:A.map((I)=>({AllowedOrigins:I.allowedOrigins,AllowedMethods:I.allowedMethods,AllowedHeaders:I.allowedHeaders,MaxAge:I.maxAge}))};if(C&&C.length>0)R.Properties.LifecycleConfiguration={Rules:C.map((I)=>({Id:I.id,Status:I.enabled?"Enabled":"Disabled",ExpirationInDays:I.expirationDays,Transitions:I.transitions?.map((O)=>({TransitionInDays:O.days,StorageClass:O.storageClass}))}))};if(h&&C){let I={id:"IntelligentTieringRule",enabled:!0,transitions:[{days:0,storageClass:"INTELLIGENT_TIERING"}]};if(!R.Properties.LifecycleConfiguration)R.Properties.LifecycleConfiguration={Rules:[]};R.Properties.LifecycleConfiguration.Rules.push({Id:I.id,Status:"Enabled",Transitions:I.transitions?.map((O)=>({TransitionInDays:O.days,StorageClass:O.storageClass}))})}let P;if(u)P={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:M.Ref(T),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[M.Join("",[M.GetAtt(T,"Arn"),"/*"])]}]}}};return{bucket:R,bucketPolicy:P,logicalId:T}}static enableVersioning(n){if(!n.Properties)n.Properties={};return n.Properties.VersioningConfiguration={Status:"Enabled"},n}static enableWebsiteHosting(n,i="index.html",s="error.html"){if(!n.Properties)n.Properties={};return n.Properties.WebsiteConfiguration={IndexDocument:i,ErrorDocument:s},n}static setLifecycleRules(n,i){if(!n.Properties)n.Properties={};return n.Properties.LifecycleConfiguration={Rules:i.map((s)=>({Id:s.id,Status:s.enabled?"Enabled":"Disabled",ExpirationInDays:s.expirationDays,Transitions:s.transitions?.map((o)=>({TransitionInDays:o.days,StorageClass:o.storageClass}))}))},n}static enableIntelligentTiering(n){if(!n.Properties)n.Properties={};if(!n.Properties.LifecycleConfiguration)n.Properties.LifecycleConfiguration={Rules:[]};return n.Properties.LifecycleConfiguration.Rules.push({Id:"IntelligentTieringRule",Status:"Enabled",Transitions:[{TransitionInDays:0,StorageClass:"INTELLIGENT_TIERING"}]}),n}static addLambdaNotification(n,i){if(!n.Properties)n.Properties={};if(!n.Properties.NotificationConfiguration)n.Properties.NotificationConfiguration={};if(!n.Properties.NotificationConfiguration.LambdaConfigurations)n.Properties.NotificationConfiguration.LambdaConfigurations=[];let s={Event:i.events[0],Function:i.functionArn};if(i.filter)s.Filter={S3Key:{Rules:[...i.filter.prefix?[{Name:"prefix",Value:i.filter.prefix}]:[],...i.filter.suffix?[{Name:"suffix",Value:i.filter.suffix}]:[]]}};for(let o of i.events){let c={...s,Event:o};n.Properties.NotificationConfiguration.LambdaConfigurations.push(c)}return n}static Notifications={onObjectCreated:(n)=>({functionArn:n,events:["s3:ObjectCreated:*"]}),onObjectRemoved:(n)=>({functionArn:n,events:["s3:ObjectRemoved:*"]}),onImageUpload:(n,i)=>({functionArn:n,events:["s3:ObjectCreated:*"],filter:{prefix:i,suffix:".jpg"}}),onFileType:(n,i,s)=>({functionArn:n,events:["s3:ObjectCreated:*"],filter:{prefix:s,suffix:i}}),onFolderUpload:(n,i)=>({functionArn:n,events:["s3:ObjectCreated:*"],filter:{prefix:i.endsWith("/")?i:`${i}/`}})};static createBackupPlan(n){let{name:i,slug:s,environment:o,bucketLogicalIds:c,retentionDays:u,schedule:d="cron(0 5 * * ? *)",vaultName:g,enableContinuousBackup:y=!1,moveToColdStorageAfterDays:h}=n,A=g||r({slug:s,environment:o,resourceType:"backup-vault",suffix:i}),C=t(A),v={Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:A}},T=r({slug:s,environment:o,resourceType:"backup-role",suffix:i}),R=t(T),P={Type:"AWS::IAM::Role",Properties:{RoleName:T,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"backup.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup","arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForRestores"]}},I=r({slug:s,environment:o,resourceType:"backup-plan",suffix:i}),O=t(I),B={DeleteAfterDays:u};if(h&&h<u)B.MoveToColdStorageAfterDays=h;let x={Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:I,BackupPlanRule:[{RuleName:`${i}-daily-backup`,TargetBackupVault:M.Ref(C),ScheduleExpression:d,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:B,EnableContinuousBackup:y}]}}},F=r({slug:s,environment:o,resourceType:"backup-selection",suffix:i}),G=t(F),_=c.map((z)=>M.GetAtt(z,"Arn")),U={Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:M.Ref(O),BackupSelection:{SelectionName:F,IamRoleArn:M.GetAtt(R,"Arn"),Resources:_}}};return{vault:v,plan:x,selection:U,role:P,vaultLogicalId:C,planLogicalId:O,selectionLogicalId:G,roleLogicalId:R}}static BackupSchedules={HOURLY:"cron(0 * * * ? *)",DAILY_5AM:"cron(0 5 * * ? *)",DAILY_MIDNIGHT:"cron(0 0 * * ? *)",WEEKLY_SUNDAY:"cron(0 5 ? * SUN *)",WEEKLY_SATURDAY:"cron(0 5 ? * SAT *)",MONTHLY_FIRST:"cron(0 5 1 * ? *)",EVERY_12_HOURS:"cron(0 */12 * * ? *)",EVERY_6_HOURS:"cron(0 */6 * * ? *)"};static BackupRetention={ONE_DAY:1,ONE_WEEK:7,TWO_WEEKS:14,ONE_MONTH:30,THREE_MONTHS:90,SIX_MONTHS:180,ONE_YEAR:365,TWO_YEARS:730,FIVE_YEARS:1825,SEVEN_YEARS:2555};static createWwwRedirectBucket(n){let{slug:i,environment:s,sourceDomain:o,targetDomain:c,protocol:u="https"}=n,d=r({slug:i,environment:s,resourceType:"s3",suffix:"www-redirect"}),g=t(d),y={Type:"AWS::S3::Bucket",Properties:{BucketName:o,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:c,Protocol:u}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1}}},h={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:M.Ref(g),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[M.Join("",[M.GetAtt(g,"Arn"),"/*"])]}]}}};return{bucket:y,bucketPolicy:h,logicalId:g}}static createDocsBucket(n){let{slug:i,environment:s,domain:o}=n,c=o||r({slug:i,environment:s,resourceType:"s3",suffix:"docs"}),u=t(c);return{bucket:{Type:"AWS::S3::Bucket",Properties:{BucketName:c,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},Tags:[{Key:"backup",Value:"weekly"}]}},logicalId:u}}static createEmailBucket(n){let{slug:i,environment:s}=n,o=r({slug:i,environment:s,resourceType:"s3",suffix:"email"}),c=t(o),u={Type:"AWS::S3::Bucket",Properties:{BucketName:o,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},LifecycleConfiguration:{Rules:[{Id:"EmailRetention",Status:"Enabled",ExpirationInDays:90,Transitions:[{TransitionInDays:30,StorageClass:"STANDARD_IA"}]}]}}},d={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:M.Ref(c),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowSESPuts",Effect:"Allow",Principal:{Service:"ses.amazonaws.com"},Action:"s3:PutObject",Resource:M.Join("",[M.GetAtt(c,"Arn"),"/*"]),Condition:{StringEquals:{"AWS:SourceAccount":M.Ref("AWS::AccountId")}}}]}}};return{bucket:u,bucketPolicy:d,logicalId:c}}static docsExist(n={}){let{projectRoot:i=process.cwd(),docsPaths:s=["docs","documentation","doc"]}=n;for(let o of s){let c=we(i,o);if(Ke(c)){let u=["dist","build",".bunpress/dist","_site","out","public"];for(let d of u){let g=we(c,d);if(Ke(g))try{if(Lr(g).length>0)return{exists:!0,path:c,hasDistFolder:!0,distPath:g}}catch{}}return{exists:!0,path:c,hasDistFolder:!1,distPath:null}}}return{exists:!1,path:null,hasDistFolder:!1,distPath:null}}static createDocsBucketIfExists(n){let i=_e.docsExist({projectRoot:n.projectRoot,docsPaths:n.docsPaths});if(!i.exists)return{bucket:null,logicalId:null,docsInfo:i};let s=_e.createDocsBucket({slug:n.slug,environment:n.environment,domain:n.domain});return{bucket:s.bucket,bucketPolicy:s.bucketPolicy,logicalId:s.logicalId,docsInfo:i}}static createPrivateBucket(n){let{slug:i,environment:s,enableVersioning:o=!0,retentionDays:c,encryptionKeyArn:u}=n,d=r({slug:i,environment:s,resourceType:"s3",suffix:"private"}),g=t(d);return{bucket:{Type:"AWS::S3::Bucket",Properties:{BucketName:d,BucketEncryption:{ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:u?{SSEAlgorithm:"aws:kms",KMSMasterKeyID:u}:{SSEAlgorithm:"AES256"}}]},PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},VersioningConfiguration:o?{Status:"Enabled"}:void 0,LifecycleConfiguration:c?{Rules:[{Id:"RetentionPolicy",Status:"Enabled",ExpirationInDays:c}]}:void 0,Tags:[{Key:"backup",Value:"daily"}]}},logicalId:g}}static checkSourcePaths(n={}){let{projectRoot:i=process.cwd(),paths:s={}}=n,o=s.web||"views/web/dist",c=s.docs||"docs/dist",u=s.private||"private";return{web:{exists:Ke(we(i,o)),path:we(i,o)},docs:{exists:Ke(we(i,c)),path:we(i,c)},private:{exists:Ke(we(i,u)),path:we(i,u)}}}static createDeploymentBuckets(n){let{slug:i,environment:s,domain:o,projectRoot:c,paths:u}=n,d=_e.checkSourcePaths({projectRoot:c,paths:u}),g={},y={web:!1,docs:!1,private:!1},h=_e.createBucket({name:"web",slug:i,environment:s,public:!1,versioning:!1,encryption:!0});if(g[h.logicalId]=h.bucket,y.web=!0,d.docs.exists){let A=_e.createDocsBucket({slug:i,environment:s,domain:o?`docs.${o}`:void 0});if(g[A.logicalId]=A.bucket,A.bucketPolicy)g[`${A.logicalId}Policy`]=A.bucketPolicy;y.docs=!0}if(d.private.exists){let A=_e.createPrivateBucket({slug:i,environment:s,enableVersioning:!0});g[A.logicalId]=A.bucket,y.private=!0}return{resources:g,created:y,sourcePaths:d}}}class rt{static createRepository(n){let{name:i,slug:s,environment:o,scanOnPush:c=!0,imageMutability:u="MUTABLE",encryption:d="AES256",kmsKey:g,lifecyclePolicy:y,tags:h}=n,A=r({slug:s,environment:o,resourceType:"ecr",suffix:i}),C=t(A),v={Type:"AWS::ECR::Repository",Properties:{RepositoryName:A,ImageTagMutability:u,ImageScanningConfiguration:{ScanOnPush:c},EncryptionConfiguration:{EncryptionType:d,...g&&d==="KMS"?{KmsKey:g}:{}}}};if(y)v.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(rt.generateLifecyclePolicy(y))};if(h)v.Properties.Tags=Object.entries(h).map(([T,R])=>({Key:T,Value:R}));return{repository:v,logicalId:C}}static generateLifecyclePolicy(n){let i=[];if(n.untaggedImageExpireDays!==void 0)i.push({rulePriority:1,description:"Delete untagged images",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:n.untaggedImageExpireDays,countUnit:"days"},action:{type:"expire"}});if(n.maxImageCount!==void 0)i.push({rulePriority:i.length+1,description:"Keep only most recent images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:n.maxImageCount},action:{type:"expire"}});if(n.maxImageAgeDays!==void 0)i.push({rulePriority:i.length+1,description:"Delete images older than specified days",selection:{tagStatus:"any",countType:"sinceImagePushed",countNumber:n.maxImageAgeDays,countUnit:"days"},action:{type:"expire"}});return{rules:i}}static LifecyclePolicies={production:{maxImageCount:10,untaggedImageExpireDays:7},development:{maxImageCount:5,untaggedImageExpireDays:3},minimal:{maxImageCount:3,untaggedImageExpireDays:1},archive:{maxImageCount:50,untaggedImageExpireDays:30}};static enableImmutableTags(n){if(!n.Properties)n.Properties={};return n.Properties.ImageTagMutability="IMMUTABLE",n}static enableScanOnPush(n){if(!n.Properties)n.Properties={};return n.Properties.ImageScanningConfiguration={ScanOnPush:!0},n}static setLifecyclePolicy(n,i){if(!n.Properties)n.Properties={};return n.Properties.LifecyclePolicy={LifecyclePolicyText:JSON.stringify(rt.generateLifecyclePolicy(i))},n}static addCrossAccountAccess(n,i){if(!n.Properties)n.Properties={};return n.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"CrossAccountPull",Effect:"Allow",Principal:{AWS:i.map((s)=>`arn:aws:iam::${s}:root`)},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:BatchCheckLayerAvailability"]}]},n}static addLambdaAccess(n){if(!n.Properties)n.Properties={};return n.Properties.RepositoryPolicyText={Version:"2012-10-17",Statement:[{Sid:"LambdaECRImageRetrievalPolicy",Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage"]}]},n}static generateBunDockerfile(n){let{baseImage:i="oven/bun:1-debian",serverPath:s,port:o=3000,additionalDirs:c=[],healthCheckEndpoint:u="/health",nodeCompatible:d=!1,envVars:g={},buildCommands:y=[],runCommand:h}=n,A=["app","config",...c],C=h||`bun run ${s}`,v=`# Multi-stage build for Bun application
12
12
  # Generated by ts-cloud
13
13
 
14
14
  # Builder stage
@@ -62,7 +62,7 @@ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \\
62
62
 
63
63
  # Start application
64
64
  CMD ["bun", "run", "${s}"]
65
- `,v}static generateDockerBuildCommands(n){let{repositoryUri:i,tag:s="latest",dockerfilePath:o="Dockerfile",context:c=".",additionalTags:u=[],buildArgs:d={},platform:g="linux/amd64",noCache:y=!1}=n,h=`${i}:${s}`,A=[s,...u],C=`docker build -f ${o} -t ${h}`;if(g)C+=` --platform ${g}`;if(y)C+=" --no-cache";for(let[R,P]of Object.entries(d))C+=` --build-arg ${R}=${P}`;C+=` ${c}`;let v=A.slice(1).map((R)=>`docker tag ${h} ${i}:${R}`),T=A.map((R)=>`docker push ${i}:${R}`);return{build:C,tag:v,push:T,all:[C,...v,...T]}}static generateEcrLoginCommand(n,i){return`aws ecr get-login-password --region ${n} | docker login --username AWS --password-stdin ${i}.dkr.ecr.${n}.amazonaws.com`}static buildRepositoryUri(n){return`${n.accountId}.dkr.ecr.${n.region}.amazonaws.com/${n.repositoryName}`}static generateImageTags(n){let i=["latest"];if(n.version){i.push(n.version);let s=n.version.split(".");if(s.length>=2)i.push(`${s[0]}.${s[1]}`);if(s.length>=1)i.push(s[0])}if(n.gitSha)i.push(n.gitSha.substring(0,7)),i.push(n.gitSha);if(n.gitBranch){let s=n.gitBranch.replace(/[^a-zA-Z0-9.-]/g,"-").replace(/^-+|-+$/g,"");i.push(s)}if(n.environment)i.push(n.environment);if(n.timestamp){let s=new Date().toISOString().replace(/[:.]/g,"-").substring(0,19);i.push(s)}return[...new Set(i)]}static DeploymentWorkflow={generateDeployScript:(n)=>{let i=et.buildRepositoryUri({accountId:n.accountId,region:n.region,repositoryName:n.repositoryName}),s=n.tags||["latest"],o=s[0];return`#!/bin/bash
65
+ `,v}static generateDockerBuildCommands(n){let{repositoryUri:i,tag:s="latest",dockerfilePath:o="Dockerfile",context:c=".",additionalTags:u=[],buildArgs:d={},platform:g="linux/amd64",noCache:y=!1}=n,h=`${i}:${s}`,A=[s,...u],C=`docker build -f ${o} -t ${h}`;if(g)C+=` --platform ${g}`;if(y)C+=" --no-cache";for(let[R,P]of Object.entries(d))C+=` --build-arg ${R}=${P}`;C+=` ${c}`;let v=A.slice(1).map((R)=>`docker tag ${h} ${i}:${R}`),T=A.map((R)=>`docker push ${i}:${R}`);return{build:C,tag:v,push:T,all:[C,...v,...T]}}static generateEcrLoginCommand(n,i){return`aws ecr get-login-password --region ${n} | docker login --username AWS --password-stdin ${i}.dkr.ecr.${n}.amazonaws.com`}static buildRepositoryUri(n){return`${n.accountId}.dkr.ecr.${n.region}.amazonaws.com/${n.repositoryName}`}static generateImageTags(n){let i=["latest"];if(n.version){i.push(n.version);let s=n.version.split(".");if(s.length>=2)i.push(`${s[0]}.${s[1]}`);if(s.length>=1)i.push(s[0])}if(n.gitSha)i.push(n.gitSha.substring(0,7)),i.push(n.gitSha);if(n.gitBranch){let s=n.gitBranch.replace(/[^a-zA-Z0-9.-]/g,"-").replace(/^-+|-+$/g,"");i.push(s)}if(n.environment)i.push(n.environment);if(n.timestamp){let s=new Date().toISOString().replace(/[:.]/g,"-").substring(0,19);i.push(s)}return[...new Set(i)]}static DeploymentWorkflow={generateDeployScript:(n)=>{let i=rt.buildRepositoryUri({accountId:n.accountId,region:n.region,repositoryName:n.repositoryName}),s=n.tags||["latest"],o=s[0];return`#!/bin/bash
66
66
  set -e
67
67
 
68
68
  # Configuration
@@ -73,7 +73,7 @@ IMAGE_URI="${i}"
73
73
  DOCKERFILE="${n.dockerfilePath||"Dockerfile"}"
74
74
 
75
75
  echo "=== ECR Login ==="
76
- ${et.generateEcrLoginCommand(n.region,n.accountId)}
76
+ ${rt.generateEcrLoginCommand(n.region,n.accountId)}
77
77
 
78
78
  echo "=== Building Image ==="
79
79
  docker build -f $DOCKERFILE -t $IMAGE_URI:${o} --platform linux/amd64 .
@@ -91,7 +91,7 @@ echo "Image: $IMAGE_URI:${o}"
91
91
  docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
92
92
  docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest`},...n.ecsCluster&&n.ecsService?[{name:"Deploy to ECS",run:`aws ecs update-service --cluster ${n.ecsCluster} --service ${n.ecsService} --force-new-deployment`}]:[]]}}};return`# Generated by ts-cloud
93
93
  ${JSON.stringify(i,null,2).replace(/"/g,"").replace(/,\n/g,`
94
- `)}`}};static DockerfileTemplates={bunServer:(n,i=3000)=>et.generateBunDockerfile({serverPath:n,port:i}),bunWithBuild:(n,i,s=3000)=>et.generateBunDockerfile({serverPath:n,port:s,buildCommands:[i]}),bunFullStack:(n,i=3000)=>et.generateBunDockerfile({serverPath:n,port:i,additionalDirs:["public","views","dist"],buildCommands:["bun run build"]}),bunApi:(n,i=3000)=>et.generateBunDockerfile({serverPath:n,port:i,healthCheckEndpoint:"/api/health"})}}var dl=[400,403,404,416,429,500,502,503,504],bm=[500,502,503,504],Cm=["GET","HEAD","OPTIONS"],KI="-failover-group",Em=["default","media-quality-based"],vm={min:1,max:3},Tm={min:1,max:10};function Ho(n){if(n===void 0)return[...bm];if(n.length===0)throw Error(`CloudFront origin failover: statusCodes must list at least one code (allowed: ${dl.join(", ")}). Omit it to use the default ${bm.join(", ")}.`);let i=n.filter((s)=>!dl.includes(s));if(i.length>0)throw Error(`CloudFront origin failover: ${i.join(", ")} ${i.length===1?"is not a status code":"are not status codes"} CloudFront can fail over on. Allowed: ${dl.join(", ")}.`);return[...new Set(n)].sort((s,o)=>s-o)}function ll(n){let{primaryOriginId:i,secondaryOriginId:s}=n;if(!i||!s)throw Error("CloudFront origin failover: both a primary and a secondary origin id are required");if(i===s)throw Error(`CloudFront origin failover: the secondary origin must differ from the primary (both are "${i}")`);let o=Ho(n.statusCodes);return nn(n.selectionCriteria),{Id:n.groupId??`${i}-failover-group`,FailoverCriteria:{StatusCodes:{Quantity:o.length,Items:o}},Members:{Quantity:2,Items:[{OriginId:i},{OriginId:s}]},...n.selectionCriteria?{SelectionCriteria:n.selectionCriteria}:{}}}function nn(n,i="the origin group"){if(n===void 0)return;if(!Em.includes(n))throw Error(`CloudFront origin failover: ${i} has selection criteria ${JSON.stringify(n)}. Allowed: ${Em.join(", ")}.`)}function at(n,i,s){if(typeof n!=="number"||!Number.isInteger(n)||n<i.min||n>i.max)throw Error(`CloudFront origin: ${s} must be a whole number from ${i.min} to ${i.max}, got ${JSON.stringify(n)}.`)}function le(n,i="the origin"){let s={};if(n?.connectionAttempts!==void 0)at(n.connectionAttempts,vm,`${i} connectionAttempts`),s.ConnectionAttempts=n.connectionAttempts;if(n?.connectionTimeout!==void 0)at(n.connectionTimeout,Tm,`${i} connectionTimeout (seconds)`),s.ConnectionTimeout=n.connectionTimeout;return s}function un(n){return{Quantity:1,Items:[ll(n)]}}function kt(n,i="the cache behavior"){let o=(Array.isArray(n)?n:n?.Items??[]).filter((c)=>!Cm.includes(c.toUpperCase()));if(o.length>0)throw Error(`CloudFront origin failover: ${i} allows ${o.join(", ")}, but a cache behavior that targets an origin group may only allow ${Cm.join(", ")}. CloudFront never fails over a write, so point the write paths at a single origin in their own cache behavior.`)}function Go(n){return/\.s3[.-](?:[a-z0-9-]+\.)?amazonaws\.com(?:\.cn)?$/i.test(n)&&!/s3-website/i.test(n)}function je(n){if(!n)return[];if(Array.isArray(n))return n;return n.Items??[]}function Ae(n){return typeof n==="string"?n:void 0}var Cr=/\.mediapackagev2\.[a-z0-9-]+\.amazonaws\.com$/i;function Nt(n,i="the distribution"){let s=je(n.Origins),o=new Set(s.map((A)=>Ae(A.Id)).filter((A)=>!!A)),c=new Map(s.map((A)=>[Ae(A.Id)??"",A.DomainName])),u=s.some((A)=>Ae(A.Id)===void 0);for(let A of s){let C=Ae(A.Id)??"(unnamed origin)";if(A.ConnectionAttempts!==void 0)at(A.ConnectionAttempts,vm,`${i} origin "${C}" ConnectionAttempts`);if(A.ConnectionTimeout!==void 0)at(A.ConnectionTimeout,Tm,`${i} origin "${C}" ConnectionTimeout (seconds)`)}let d=n.OriginGroups,g=je(d);if(d&&!Array.isArray(d)&&d.Quantity!==void 0&&d.Quantity!==g.length)throw Error(`CloudFront origin failover: ${i} OriginGroups.Quantity is ${d.Quantity} but it lists ${g.length} group(s).`);let y=new Set;for(let A of g){let C=Ae(A.Id);if(A.Id===void 0||A.Id==="")throw Error(`CloudFront origin failover: ${i} has an origin group without an Id.`);let v=`${i} origin group "${C??"(intrinsic id)"}"`;if(C){if(y.has(C))throw Error(`CloudFront origin failover: ${i} declares origin group "${C}" twice.`);if(o.has(C))throw Error(`CloudFront origin failover: ${v} has the same id as an origin. Cache behaviors target groups and origins by id, so the two must differ.`);y.add(C)}let T=A.Members,R=je(T);if(R.length!==2||T?.Quantity!==void 0&&T.Quantity!==R.length)throw Error(`CloudFront origin failover: ${v} must have exactly 2 members (a primary and a secondary), it has ${R.length}${T?.Quantity!==void 0&&T.Quantity!==R.length?` with Quantity ${T.Quantity}`:""}.`);let P=R.map((L)=>Ae(L.OriginId));for(let L of P)if(L&&!o.has(L)&&!u)throw Error(`CloudFront origin failover: ${v} lists member "${L}", which is not an origin of this distribution. Origins: ${[...o].join(", ")||"(none)"}.`);if(P[0]&&P[0]===P[1])throw Error(`CloudFront origin failover: ${v} lists "${P[0]}" as both primary and secondary.`);let I=A.FailoverCriteria?.StatusCodes,M=je(I);if(Ho(M),I?.Quantity!==void 0&&I.Quantity!==M.length)throw Error(`CloudFront origin failover: ${v} FailoverCriteria.StatusCodes.Quantity is ${I.Quantity} but it lists ${M.length} code(s).`);if(nn(A.SelectionCriteria,v),A.SelectionCriteria==="media-quality-based")for(let L of P){let N=L?Ae(c.get(L)):void 0;if(N&&!Cr.test(N))throw Error(`CloudFront origin failover: ${v} uses media-quality-based selection, which only works between AWS Elemental MediaPackage v2 origins, but member "${L}" is ${N}. Use 'default'.`)}}let h=[];if(n.DefaultCacheBehavior)h.push({behavior:n.DefaultCacheBehavior,name:"the default cache behavior"});for(let A of je(n.CacheBehaviors))h.push({behavior:A,name:`the cache behavior for ${JSON.stringify(A.PathPattern)}`});for(let{behavior:A,name:C}of h){let v=Ae(A.TargetOriginId);if(!v)continue;if(y.has(v))kt(A.AllowedMethods??["GET","HEAD"],`${C} of ${i} (origin group "${v}")`);else if(!o.has(v)&&!u&&g.every((T)=>Ae(T.Id)!==void 0))throw Error(`CloudFront: ${C} of ${i} targets "${v}", which is neither an origin nor an origin group of this distribution.`)}}class Ee{static createDistribution(n){let{slug:i,environment:s,origin:o,customDomain:c,certificateArn:u,errorPages:d,cachePolicy:g,edgeFunctions:y,http3:h=!1,comment:A,failoverOrigin:C}=n,v=r({slug:i,environment:s,resourceType:"cdn"}),T=t(v),R={Id:"DefaultOrigin",DomainName:o.domainName,OriginPath:o.originPath||"",...le(o,"the CDN origin")},P;if(o.type==="s3"){let M=`${T}OAC`;P={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${v}-oac`,Description:`Origin Access Control for ${v}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},R.OriginAccessControlId=x.Ref(M)}else if(o.type==="alb"||o.type==="custom")R.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only"};let I={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:A||`CDN for ${v}`,DefaultRootObject:"index.html",Origins:[R],DefaultCacheBehavior:{TargetOriginId:"DefaultOrigin",ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0},PriceClass:"PriceClass_100",HttpVersion:h?"http2and3":"http2"}}};if(c&&u)I.Properties.DistributionConfig.Aliases=[c],I.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:u,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};if(d&&d.length>0)I.Properties.DistributionConfig.CustomErrorResponses=d.map((M)=>({ErrorCode:M.errorCode,ResponseCode:M.responseCode,ResponsePagePath:M.responsePagePath}));if(y&&y.length>0)I.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=y.map((M)=>({EventType:M.event,LambdaFunctionARN:M.functionArn}));if(C)Ee.addOriginFailover(I,C);return{distribution:I,originAccessControl:P,logicalId:T}}static addOriginFailover(n,i){let s=n.Properties.DistributionConfig,o=s.DefaultCacheBehavior,c=o.TargetOriginId,u=i.id??"FailoverOrigin";if(s.OriginGroups&&s.OriginGroups.Quantity>0)throw Error("CloudFront origin failover: this distribution already has an origin group");if(kt(o.AllowedMethods??["GET","HEAD"],"the default cache behavior"),s.Origins.some((A)=>A.Id===u))throw Error(`CloudFront origin failover: an origin with id "${u}" already exists`);let d=ll({primaryOriginId:c,secondaryOriginId:u,statusCodes:i.statusCodes,selectionCriteria:i.selectionCriteria}),g=i.type??(Go(i.domainName)?"s3":"custom"),y={Id:u,DomainName:i.domainName,OriginPath:i.originPath||"",...le(i,"the failover origin")},h=le(i.primary,"the primary origin");if(Object.keys(h).length>0){let A=s.Origins.find((C)=>C.Id===c);if(A)Object.assign(A,h)}if(g==="s3"){let A=s.Origins.find((C)=>C.Id===c);if(y.S3OriginConfig={OriginAccessIdentity:""},A?.OriginAccessControlId)y.OriginAccessControlId=A.OriginAccessControlId}else y.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only"};return s.Origins.push(y),s.OriginGroups={Quantity:1,Items:[d]},o.TargetOriginId=d.Id,Nt(s),n}static setCustomDomain(n,i,s){return n.Properties.DistributionConfig.Aliases=[i],n.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:s,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"},n}static setErrorPages(n,i){return n.Properties.DistributionConfig.CustomErrorResponses=i.map((s)=>({ErrorCode:s.errorCode,ResponseCode:s.responseCode,ResponsePagePath:s.responsePagePath})),n}static enableHttp3(n){return n.Properties.DistributionConfig.HttpVersion="http2and3",n}static addEdgeFunction(n,i,s){if(!n.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations)n.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=[];return n.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations.push({EventType:i,LambdaFunctionARN:s}),n}static setCachePolicy(n,i){return n.Properties.DistributionConfig.Comment=`${n.Properties.DistributionConfig.Comment||""} (TTL: ${i.default||86400}s)`,n}static createSpaDistribution(n){return Ee.createDistribution({...n,errorPages:[{errorCode:404,responseCode:200,responsePagePath:"/index.html"},{errorCode:403,responseCode:200,responsePagePath:"/index.html"}]})}static createDocsOriginRequestFunction(n){let{slug:i,environment:s}=n,o=r({slug:i,environment:s,resourceType:"edge-docs"}),c=t(o),u=t(`${o}-role`),d=t(`${o}-version`),g={Type:"AWS::IAM::Role",Properties:{RoleName:`${o}-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["lambda.amazonaws.com","edgelambda.amazonaws.com"]},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]}},y=`
94
+ `)}`}};static DockerfileTemplates={bunServer:(n,i=3000)=>rt.generateBunDockerfile({serverPath:n,port:i}),bunWithBuild:(n,i,s=3000)=>rt.generateBunDockerfile({serverPath:n,port:s,buildCommands:[i]}),bunFullStack:(n,i=3000)=>rt.generateBunDockerfile({serverPath:n,port:i,additionalDirs:["public","views","dist"],buildCommands:["bun run build"]}),bunApi:(n,i=3000)=>rt.generateBunDockerfile({serverPath:n,port:i,healthCheckEndpoint:"/api/health"})}}var yl=[400,403,404,416,429,500,502,503,504],km=[500,502,503,504],Nm=["GET","HEAD","OPTIONS"],ob="-failover-group",Bm=["default","media-quality-based"],xm={min:1,max:3},Om={min:1,max:10};function Ko(n){if(n===void 0)return[...km];if(n.length===0)throw Error(`CloudFront origin failover: statusCodes must list at least one code (allowed: ${yl.join(", ")}). Omit it to use the default ${km.join(", ")}.`);let i=n.filter((s)=>!yl.includes(s));if(i.length>0)throw Error(`CloudFront origin failover: ${i.join(", ")} ${i.length===1?"is not a status code":"are not status codes"} CloudFront can fail over on. Allowed: ${yl.join(", ")}.`);return[...new Set(n)].sort((s,o)=>s-o)}function Sl(n){let{primaryOriginId:i,secondaryOriginId:s}=n;if(!i||!s)throw Error("CloudFront origin failover: both a primary and a secondary origin id are required");if(i===s)throw Error(`CloudFront origin failover: the secondary origin must differ from the primary (both are "${i}")`);let o=Ko(n.statusCodes);return cn(n.selectionCriteria),{Id:n.groupId??`${i}-failover-group`,FailoverCriteria:{StatusCodes:{Quantity:o.length,Items:o}},Members:{Quantity:2,Items:[{OriginId:i},{OriginId:s}]},...n.selectionCriteria?{SelectionCriteria:n.selectionCriteria}:{}}}function cn(n,i="the origin group"){if(n===void 0)return;if(!Bm.includes(n))throw Error(`CloudFront origin failover: ${i} has selection criteria ${JSON.stringify(n)}. Allowed: ${Bm.join(", ")}.`)}function at(n,i,s){if(typeof n!=="number"||!Number.isInteger(n)||n<i.min||n>i.max)throw Error(`CloudFront origin: ${s} must be a whole number from ${i.min} to ${i.max}, got ${JSON.stringify(n)}.`)}function ue(n,i="the origin"){let s={};if(n?.connectionAttempts!==void 0)at(n.connectionAttempts,xm,`${i} connectionAttempts`),s.ConnectionAttempts=n.connectionAttempts;if(n?.connectionTimeout!==void 0)at(n.connectionTimeout,Om,`${i} connectionTimeout (seconds)`),s.ConnectionTimeout=n.connectionTimeout;return s}function gn(n){return{Quantity:1,Items:[Sl(n)]}}function Nt(n,i="the cache behavior"){let o=(Array.isArray(n)?n:n?.Items??[]).filter((c)=>!Nm.includes(c.toUpperCase()));if(o.length>0)throw Error(`CloudFront origin failover: ${i} allows ${o.join(", ")}, but a cache behavior that targets an origin group may only allow ${Nm.join(", ")}. CloudFront never fails over a write, so point the write paths at a single origin in their own cache behavior.`)}function Wo(n){return/\.s3[.-](?:[a-z0-9-]+\.)?amazonaws\.com(?:\.cn)?$/i.test(n)&&!/s3-website/i.test(n)}function qe(n){if(!n)return[];if(Array.isArray(n))return n;return n.Items??[]}function Ce(n){return typeof n==="string"?n:void 0}var Or=/\.mediapackagev2\.[a-z0-9-]+\.amazonaws\.com$/i;function Bt(n,i="the distribution"){let s=qe(n.Origins),o=new Set(s.map((A)=>Ce(A.Id)).filter((A)=>!!A)),c=new Map(s.map((A)=>[Ce(A.Id)??"",A.DomainName])),u=s.some((A)=>Ce(A.Id)===void 0);for(let A of s){let C=Ce(A.Id)??"(unnamed origin)";if(A.ConnectionAttempts!==void 0)at(A.ConnectionAttempts,xm,`${i} origin "${C}" ConnectionAttempts`);if(A.ConnectionTimeout!==void 0)at(A.ConnectionTimeout,Om,`${i} origin "${C}" ConnectionTimeout (seconds)`)}let d=n.OriginGroups,g=qe(d);if(d&&!Array.isArray(d)&&d.Quantity!==void 0&&d.Quantity!==g.length)throw Error(`CloudFront origin failover: ${i} OriginGroups.Quantity is ${d.Quantity} but it lists ${g.length} group(s).`);let y=new Set;for(let A of g){let C=Ce(A.Id);if(A.Id===void 0||A.Id==="")throw Error(`CloudFront origin failover: ${i} has an origin group without an Id.`);let v=`${i} origin group "${C??"(intrinsic id)"}"`;if(C){if(y.has(C))throw Error(`CloudFront origin failover: ${i} declares origin group "${C}" twice.`);if(o.has(C))throw Error(`CloudFront origin failover: ${v} has the same id as an origin. Cache behaviors target groups and origins by id, so the two must differ.`);y.add(C)}let T=A.Members,R=qe(T);if(R.length!==2||T?.Quantity!==void 0&&T.Quantity!==R.length)throw Error(`CloudFront origin failover: ${v} must have exactly 2 members (a primary and a secondary), it has ${R.length}${T?.Quantity!==void 0&&T.Quantity!==R.length?` with Quantity ${T.Quantity}`:""}.`);let P=R.map((B)=>Ce(B.OriginId));for(let B of P)if(B&&!o.has(B)&&!u)throw Error(`CloudFront origin failover: ${v} lists member "${B}", which is not an origin of this distribution. Origins: ${[...o].join(", ")||"(none)"}.`);if(P[0]&&P[0]===P[1])throw Error(`CloudFront origin failover: ${v} lists "${P[0]}" as both primary and secondary.`);let I=A.FailoverCriteria?.StatusCodes,O=qe(I);if(Ko(O),I?.Quantity!==void 0&&I.Quantity!==O.length)throw Error(`CloudFront origin failover: ${v} FailoverCriteria.StatusCodes.Quantity is ${I.Quantity} but it lists ${O.length} code(s).`);if(cn(A.SelectionCriteria,v),A.SelectionCriteria==="media-quality-based")for(let B of P){let x=B?Ce(c.get(B)):void 0;if(x&&!Or.test(x))throw Error(`CloudFront origin failover: ${v} uses media-quality-based selection, which only works between AWS Elemental MediaPackage v2 origins, but member "${B}" is ${x}. Use 'default'.`)}}let h=[];if(n.DefaultCacheBehavior)h.push({behavior:n.DefaultCacheBehavior,name:"the default cache behavior"});for(let A of qe(n.CacheBehaviors))h.push({behavior:A,name:`the cache behavior for ${JSON.stringify(A.PathPattern)}`});for(let{behavior:A,name:C}of h){let v=Ce(A.TargetOriginId);if(!v)continue;if(y.has(v))Nt(A.AllowedMethods??["GET","HEAD"],`${C} of ${i} (origin group "${v}")`);else if(!o.has(v)&&!u&&g.every((T)=>Ce(T.Id)!==void 0))throw Error(`CloudFront: ${C} of ${i} targets "${v}", which is neither an origin nor an origin group of this distribution.`)}}class ve{static createDistribution(n){let{slug:i,environment:s,origin:o,customDomain:c,certificateArn:u,errorPages:d,cachePolicy:g,edgeFunctions:y,http3:h=!1,comment:A,failoverOrigin:C}=n,v=r({slug:i,environment:s,resourceType:"cdn"}),T=t(v),R={Id:"DefaultOrigin",DomainName:o.domainName,OriginPath:o.originPath||"",...ue(o,"the CDN origin")},P;if(o.type==="s3"){let O=`${T}OAC`;P={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${v}-oac`,Description:`Origin Access Control for ${v}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},R.OriginAccessControlId=M.Ref(O)}else if(o.type==="alb"||o.type==="custom")R.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only"};let I={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:A||`CDN for ${v}`,DefaultRootObject:"index.html",Origins:[R],DefaultCacheBehavior:{TargetOriginId:"DefaultOrigin",ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0},PriceClass:"PriceClass_100",HttpVersion:h?"http2and3":"http2"}}};if(c&&u)I.Properties.DistributionConfig.Aliases=[c],I.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:u,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};if(d&&d.length>0)I.Properties.DistributionConfig.CustomErrorResponses=d.map((O)=>({ErrorCode:O.errorCode,ResponseCode:O.responseCode,ResponsePagePath:O.responsePagePath}));if(y&&y.length>0)I.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=y.map((O)=>({EventType:O.event,LambdaFunctionARN:O.functionArn}));if(C)ve.addOriginFailover(I,C);return{distribution:I,originAccessControl:P,logicalId:T}}static addOriginFailover(n,i){let s=n.Properties.DistributionConfig,o=s.DefaultCacheBehavior,c=o.TargetOriginId,u=i.id??"FailoverOrigin";if(s.OriginGroups&&s.OriginGroups.Quantity>0)throw Error("CloudFront origin failover: this distribution already has an origin group");if(Nt(o.AllowedMethods??["GET","HEAD"],"the default cache behavior"),s.Origins.some((A)=>A.Id===u))throw Error(`CloudFront origin failover: an origin with id "${u}" already exists`);let d=Sl({primaryOriginId:c,secondaryOriginId:u,statusCodes:i.statusCodes,selectionCriteria:i.selectionCriteria}),g=i.type??(Wo(i.domainName)?"s3":"custom"),y={Id:u,DomainName:i.domainName,OriginPath:i.originPath||"",...ue(i,"the failover origin")},h=ue(i.primary,"the primary origin");if(Object.keys(h).length>0){let A=s.Origins.find((C)=>C.Id===c);if(A)Object.assign(A,h)}if(g==="s3"){let A=s.Origins.find((C)=>C.Id===c);if(y.S3OriginConfig={OriginAccessIdentity:""},A?.OriginAccessControlId)y.OriginAccessControlId=A.OriginAccessControlId}else y.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only"};return s.Origins.push(y),s.OriginGroups={Quantity:1,Items:[d]},o.TargetOriginId=d.Id,Bt(s),n}static setCustomDomain(n,i,s){return n.Properties.DistributionConfig.Aliases=[i],n.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:s,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"},n}static setErrorPages(n,i){return n.Properties.DistributionConfig.CustomErrorResponses=i.map((s)=>({ErrorCode:s.errorCode,ResponseCode:s.responseCode,ResponsePagePath:s.responsePagePath})),n}static enableHttp3(n){return n.Properties.DistributionConfig.HttpVersion="http2and3",n}static addEdgeFunction(n,i,s){if(!n.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations)n.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations=[];return n.Properties.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations.push({EventType:i,LambdaFunctionARN:s}),n}static setCachePolicy(n,i){return n.Properties.DistributionConfig.Comment=`${n.Properties.DistributionConfig.Comment||""} (TTL: ${i.default||86400}s)`,n}static createSpaDistribution(n){return ve.createDistribution({...n,errorPages:[{errorCode:404,responseCode:200,responsePagePath:"/index.html"},{errorCode:403,responseCode:200,responsePagePath:"/index.html"}]})}static createDocsOriginRequestFunction(n){let{slug:i,environment:s}=n,o=r({slug:i,environment:s,resourceType:"edge-docs"}),c=t(o),u=t(`${o}-role`),d=t(`${o}-version`),g={Type:"AWS::IAM::Role",Properties:{RoleName:`${o}-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["lambda.amazonaws.com","edgelambda.amazonaws.com"]},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]}},y=`
95
95
  'use strict';
96
96
 
97
97
  exports.handler = async (event) => {
@@ -124,7 +124,7 @@ exports.handler = async (event) => {
124
124
 
125
125
  return request;
126
126
  };
127
- `.trim();return{lambdaFunction:{Type:"AWS::Lambda::Function",Properties:{FunctionName:o,Description:"Lambda@Edge origin request handler for docs routing",Runtime:"nodejs20.x",Handler:"index.handler",Role:x.GetAtt(u,"Arn"),Code:{ZipFile:y},MemorySize:128,Timeout:5}},role:g,functionLogicalId:c,roleLogicalId:u,versionLogicalId:d}}static createDocsDistribution(n){let{slug:i,environment:s,origin:o,customDomain:c,certificateArn:u,lambdaEdgeFunctionArn:d}=n,g=Ee.createDistribution({slug:i,environment:s,origin:o,customDomain:c,certificateArn:u,comment:`Docs CDN for ${i}`,errorPages:[{errorCode:404,responseCode:404,responsePagePath:"/404.html"},{errorCode:403,responseCode:403,responsePagePath:"/404.html"}]});if(d)Ee.addEdgeFunction(g.distribution,"origin-request",d);return g.distribution.Properties.DistributionConfig.DefaultCacheBehavior.DefaultTTL=86400,g.distribution.Properties.DistributionConfig.DefaultCacheBehavior.MaxTTL=604800,g.distribution.Properties.DistributionConfig.DefaultCacheBehavior.MinTTL=0,g}static createApiDistribution(n){let{slug:i,environment:s,albDomainName:o,customDomain:c,certificateArn:u,pathPattern:d="/api/*",forwardHeaders:g=["Host","Origin","Authorization","Content-Type","Accept"],forwardCookies:y="all",whitelistedCookies:h,customOriginHeaders:A={}}=n,C=r({slug:i,environment:s,resourceType:"cdn-api"}),v=t(C),T=Object.entries(A).map(([M,L])=>({HeaderName:M,HeaderValue:L})),R={Id:"ALBOrigin",DomainName:o,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(T.length>0)R.OriginCustomHeaders=T;let P={Forward:y};if(y==="whitelist"&&h)P.WhitelistedNames=h;let I={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:`API CDN for ${C}`,Origins:[R],DefaultCacheBehavior:{TargetOriginId:"ALBOrigin",ViewerProtocolPolicy:"https-only",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,DefaultTTL:0,MaxTTL:0,MinTTL:0,ForwardedValues:{QueryString:!0,Headers:g,Cookies:P}},PriceClass:"PriceClass_100",HttpVersion:"http2"}}};if(c&&u)I.Properties.DistributionConfig.Aliases=[c],I.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:u,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};return{distribution:I,logicalId:v}}static createMultiOriginDistribution(n){let{slug:i,environment:s,s3BucketDomainName:o,albDomainName:c,apiPathPattern:u="/api/*",customDomain:d,certificateArn:g,customOriginHeaders:y={}}=n,h=r({slug:i,environment:s,resourceType:"cdn"}),A=t(h),C=`${A}OAC`,v={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${h}-oac`,Description:`Origin Access Control for ${h}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},T=Object.entries(y).map(([M,L])=>({HeaderName:M,HeaderValue:L})),R={Id:"S3Origin",DomainName:o,OriginAccessControlId:x.Ref(C)},P={Id:"ALBOrigin",DomainName:c,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(T.length>0)P.OriginCustomHeaders=T;let I={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:`Multi-origin CDN for ${h}`,DefaultRootObject:"index.html",Origins:[R,P],DefaultCacheBehavior:{TargetOriginId:"S3Origin",ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0},CacheBehaviors:[{PathPattern:u,TargetOriginId:"ALBOrigin",ViewerProtocolPolicy:"https-only",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,DefaultTTL:0,MaxTTL:0,MinTTL:0,ForwardedValues:{QueryString:!0,Headers:["Host","Origin","Authorization","Content-Type","Accept"],Cookies:{Forward:"all"}}}],PriceClass:"PriceClass_100",HttpVersion:"http2",CustomErrorResponses:[{ErrorCode:404,ResponseCode:200,ResponsePagePath:"/index.html"},{ErrorCode:403,ResponseCode:200,ResponsePagePath:"/index.html"}]}}};if(d&&g)I.Properties.DistributionConfig.Aliases=[d],I.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:g,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};return{distribution:I,originAccessControl:v,logicalId:A,oacLogicalId:C}}static addAlbOrigin(n,i){let{originId:s,domainName:o,pathPattern:c,customHeaders:u={},forwardHeaders:d=["Host","Origin","Authorization","Content-Type","Accept"],cacheTtl:g={default:0,max:0,min:0}}=i,y=Object.entries(u).map(([A,C])=>({HeaderName:A,HeaderValue:C})),h={Id:s,DomainName:o,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(y.length>0)h.OriginCustomHeaders=y;if(!n.Properties.DistributionConfig.Origins)n.Properties.DistributionConfig.Origins=[];if(n.Properties.DistributionConfig.Origins.push(h),!n.Properties.DistributionConfig.CacheBehaviors)n.Properties.DistributionConfig.CacheBehaviors=[];return n.Properties.DistributionConfig.CacheBehaviors.push({PathPattern:c,TargetOriginId:s,ViewerProtocolPolicy:"https-only",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,DefaultTTL:g.default,MaxTTL:g.max,MinTTL:g.min,ForwardedValues:{QueryString:!0,Headers:d,Cookies:{Forward:"all"}}}),n}static addOriginHeader(n,i,s,o){let c=n.Properties.DistributionConfig.Origins?.find((u)=>u.Id===i);if(c){if(!c.OriginCustomHeaders)c.OriginCustomHeaders=[];c.OriginCustomHeaders.push({HeaderName:s,HeaderValue:o})}return n}static EdgeFunctionTemplates={docsOriginRequest:`
127
+ `.trim();return{lambdaFunction:{Type:"AWS::Lambda::Function",Properties:{FunctionName:o,Description:"Lambda@Edge origin request handler for docs routing",Runtime:"nodejs20.x",Handler:"index.handler",Role:M.GetAtt(u,"Arn"),Code:{ZipFile:y},MemorySize:128,Timeout:5}},role:g,functionLogicalId:c,roleLogicalId:u,versionLogicalId:d}}static createDocsDistribution(n){let{slug:i,environment:s,origin:o,customDomain:c,certificateArn:u,lambdaEdgeFunctionArn:d}=n,g=ve.createDistribution({slug:i,environment:s,origin:o,customDomain:c,certificateArn:u,comment:`Docs CDN for ${i}`,errorPages:[{errorCode:404,responseCode:404,responsePagePath:"/404.html"},{errorCode:403,responseCode:403,responsePagePath:"/404.html"}]});if(d)ve.addEdgeFunction(g.distribution,"origin-request",d);return g.distribution.Properties.DistributionConfig.DefaultCacheBehavior.DefaultTTL=86400,g.distribution.Properties.DistributionConfig.DefaultCacheBehavior.MaxTTL=604800,g.distribution.Properties.DistributionConfig.DefaultCacheBehavior.MinTTL=0,g}static createApiDistribution(n){let{slug:i,environment:s,albDomainName:o,customDomain:c,certificateArn:u,pathPattern:d="/api/*",forwardHeaders:g=["Host","Origin","Authorization","Content-Type","Accept"],forwardCookies:y="all",whitelistedCookies:h,customOriginHeaders:A={}}=n,C=r({slug:i,environment:s,resourceType:"cdn-api"}),v=t(C),T=Object.entries(A).map(([O,B])=>({HeaderName:O,HeaderValue:B})),R={Id:"ALBOrigin",DomainName:o,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(T.length>0)R.OriginCustomHeaders=T;let P={Forward:y};if(y==="whitelist"&&h)P.WhitelistedNames=h;let I={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:`API CDN for ${C}`,Origins:[R],DefaultCacheBehavior:{TargetOriginId:"ALBOrigin",ViewerProtocolPolicy:"https-only",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,DefaultTTL:0,MaxTTL:0,MinTTL:0,ForwardedValues:{QueryString:!0,Headers:g,Cookies:P}},PriceClass:"PriceClass_100",HttpVersion:"http2"}}};if(c&&u)I.Properties.DistributionConfig.Aliases=[c],I.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:u,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};return{distribution:I,logicalId:v}}static createMultiOriginDistribution(n){let{slug:i,environment:s,s3BucketDomainName:o,albDomainName:c,apiPathPattern:u="/api/*",customDomain:d,certificateArn:g,customOriginHeaders:y={}}=n,h=r({slug:i,environment:s,resourceType:"cdn"}),A=t(h),C=`${A}OAC`,v={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${h}-oac`,Description:`Origin Access Control for ${h}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},T=Object.entries(y).map(([O,B])=>({HeaderName:O,HeaderValue:B})),R={Id:"S3Origin",DomainName:o,OriginAccessControlId:M.Ref(C)},P={Id:"ALBOrigin",DomainName:c,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(T.length>0)P.OriginCustomHeaders=T;let I={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,Comment:`Multi-origin CDN for ${h}`,DefaultRootObject:"index.html",Origins:[R,P],DefaultCacheBehavior:{TargetOriginId:"S3Origin",ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0},CacheBehaviors:[{PathPattern:u,TargetOriginId:"ALBOrigin",ViewerProtocolPolicy:"https-only",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,DefaultTTL:0,MaxTTL:0,MinTTL:0,ForwardedValues:{QueryString:!0,Headers:["Host","Origin","Authorization","Content-Type","Accept"],Cookies:{Forward:"all"}}}],PriceClass:"PriceClass_100",HttpVersion:"http2",CustomErrorResponses:[{ErrorCode:404,ResponseCode:200,ResponsePagePath:"/index.html"},{ErrorCode:403,ResponseCode:200,ResponsePagePath:"/index.html"}]}}};if(d&&g)I.Properties.DistributionConfig.Aliases=[d],I.Properties.DistributionConfig.ViewerCertificate={AcmCertificateArn:g,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};return{distribution:I,originAccessControl:v,logicalId:A,oacLogicalId:C}}static addAlbOrigin(n,i){let{originId:s,domainName:o,pathPattern:c,customHeaders:u={},forwardHeaders:d=["Host","Origin","Authorization","Content-Type","Accept"],cacheTtl:g={default:0,max:0,min:0}}=i,y=Object.entries(u).map(([A,C])=>({HeaderName:A,HeaderValue:C})),h={Id:s,DomainName:o,CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"],OriginReadTimeout:60,OriginKeepaliveTimeout:60}};if(y.length>0)h.OriginCustomHeaders=y;if(!n.Properties.DistributionConfig.Origins)n.Properties.DistributionConfig.Origins=[];if(n.Properties.DistributionConfig.Origins.push(h),!n.Properties.DistributionConfig.CacheBehaviors)n.Properties.DistributionConfig.CacheBehaviors=[];return n.Properties.DistributionConfig.CacheBehaviors.push({PathPattern:c,TargetOriginId:s,ViewerProtocolPolicy:"https-only",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,DefaultTTL:g.default,MaxTTL:g.max,MinTTL:g.min,ForwardedValues:{QueryString:!0,Headers:d,Cookies:{Forward:"all"}}}),n}static addOriginHeader(n,i,s,o){let c=n.Properties.DistributionConfig.Origins?.find((u)=>u.Id===i);if(c){if(!c.OriginCustomHeaders)c.OriginCustomHeaders=[];c.OriginCustomHeaders.push({HeaderName:s,HeaderValue:o})}return n}static EdgeFunctionTemplates={docsOriginRequest:`
128
128
  'use strict';
129
129
  exports.handler = async (event) => {
130
130
  const request = event.Records[0].cf.request;
@@ -197,7 +197,7 @@ exports.handler = async (event) => {
197
197
 
198
198
  return request;
199
199
  };
200
- `.trim()};static Config={ttl:(n)=>{let{min:i=0,max:s=86400,default:o=86400}=n;return{MinTTL:i,MaxTTL:s,DefaultTTL:o}},cookies:(n,i)=>{let s={Forward:n==="allowList"?"whitelist":n};if(n==="allowList"&&i)s.WhitelistedNames=i;return s},allowedMethods:(n)=>{let i={ALL:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return i[n]||i.GET_HEAD},cachedMethods:(n)=>{let i={GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return i[n]||i.GET_HEAD},ttlPresets:{static:{min:0,max:31536000,default:31536000},dynamic:{min:0,max:0,default:0},api:{min:0,max:3600,default:60},html:{min:0,max:86400,default:86400},images:{min:0,max:604800,default:604800}},cacheBehavior:(n)=>{let{ttl:i={min:0,max:86400,default:86400},cookies:s="none",allowedCookies:o,allowedMethods:c="GET_HEAD",cachedMethods:u="GET_HEAD",compress:d=!0,forwardQueryString:g=!0,forwardHeaders:y=[]}=n;return{MinTTL:i.min,MaxTTL:i.max,DefaultTTL:i.default,Compress:d,AllowedMethods:Ee.Config.allowedMethods(c),CachedMethods:Ee.Config.cachedMethods(u),ForwardedValues:{QueryString:g,Headers:y,Cookies:Ee.Config.cookies(s,o)}}}};static applyConfig(n,i){let s=n.Properties.DistributionConfig.DefaultCacheBehavior;if(i.ttl)s.MinTTL=i.ttl.min,s.MaxTTL=i.ttl.max,s.DefaultTTL=i.ttl.default;if(i.compress!==void 0)s.Compress=i.compress;if(i.allowedMethods)s.AllowedMethods=Ee.Config.allowedMethods(i.allowedMethods);if(i.cachedMethods)s.CachedMethods=Ee.Config.cachedMethods(i.cachedMethods);if(i.cookies){if(!s.ForwardedValues)s.ForwardedValues={QueryString:!0};s.ForwardedValues.Cookies=Ee.Config.cookies(i.cookies,i.allowedCookies)}return n}}var sy=[403,404,500,502,503,504],ul="TsCloud::StorageFailover",Vo="AllowCloudFrontFailoverRead",vr=/^[a-z]{2}(?:-gov)?-[a-z]+-\d$/,Tr=/^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/;function wm(n){let{failover:i,primaryBucket:s,primaryRegion:o}=n,c=n.where??"storage failover";if(!i||typeof i!=="object")throw Error(`${c}.failover must be an object such as { region: 'us-west-2' }.`);if(!i.region||!vr.test(i.region))throw Error(`${c}.failover.region must be an AWS region such as 'us-west-2', got ${JSON.stringify(i.region)}.`);if(i.region===o)throw Error(`${c}.failover.region is ${i.region}, the same region as the primary bucket. Failover only helps when the replica is in another region.`);let u=i.bucket??`${s}-${i.region}`;if(!Tr.test(u)||u.includes("..")){let d=i.bucket===void 0&&u.length>63?` The default name (<primary bucket>-<region>) is ${u.length} characters; S3 allows 63. Set ${c}.failover.bucket.`:"";throw Error(`${c}.failover: "${u}" is not a valid S3 bucket name.${d}`)}if(u===s)throw Error(`${c}.failover.bucket must differ from the primary bucket "${s}".`);return{replicaBucket:u,replicaRegion:i.region,replicate:i.replicate!==!1,statusCodes:Ho(i.statusCodes??sy),primaryConnection:le(i,`${c}.failover`)}}function Rm(n,i){return`${n}.s3.${i}.amazonaws.com`}function Dm(n){let i=`arn:aws:s3:::${n.primaryBucket}`,s=`arn:aws:s3:::${n.replicaBucket}`;return{Type:"AWS::IAM::Role",Properties:{...n.roleName?{RoleName:n.roleName}:{},AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"s3.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"failover-replication",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["s3:GetReplicationConfiguration","s3:ListBucket"],Resource:i},{Effect:"Allow",Action:["s3:GetObjectVersionForReplication","s3:GetObjectVersionAcl","s3:GetObjectVersionTagging"],Resource:`${i}/*`},{Effect:"Allow",Action:["s3:ReplicateObject","s3:ReplicateDelete","s3:ReplicateTags"],Resource:`${s}/*`}]}}]}}}function Pm(n){return{Role:n.roleArn,Rules:[{Id:"cloudfront-failover-replica",Status:"Enabled",Priority:1,Filter:{Prefix:""},DeleteMarkerReplication:{Status:"Enabled"},Destination:{Bucket:`arn:aws:s3:::${n.replicaBucket}`}}]}}function gl(n){return{Sid:Vo,Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:`arn:aws:s3:::${n.replicaBucket}/*`,Condition:{StringEquals:{"AWS:SourceArn":n.distributionArn}}}}function WI(n){let s=(typeof n==="string"?JSON.parse(n):n)?.Metadata?.[ul];return Array.isArray(s)?s:[]}class W{static createHostedZone(n){let{domain:i,slug:s,environment:o,comment:c}=n,u=r({slug:s,environment:o,resourceType:"hostedzone"}),d=t(`${u}-${i.replace(/\./g,"")}`);return{zone:{Type:"AWS::Route53::HostedZone",Properties:{Name:i,HostedZoneConfig:{Comment:c||`Hosted zone for ${i}`}}},logicalId:d}}static createRecord(n){let{hostedZoneId:i,hostedZoneName:s,name:o,type:c,ttl:u,values:d,aliasTarget:g}=n,y=t(`record-${o.replace(/\./g,"")}-${c}`),h={Type:"AWS::Route53::RecordSet",Properties:{Name:o,Type:c}};if(i)h.Properties.HostedZoneId=i;else if(s)h.Properties.HostedZoneName=s;if(g)h.Properties.AliasTarget={DNSName:g.dnsName,HostedZoneId:g.hostedZoneId,EvaluateTargetHealth:g.evaluateTargetHealth??!1};else h.Properties.TTL=u||300,h.Properties.ResourceRecords=d||[];return{record:h,logicalId:y}}static createCloudFrontAlias(n,i,s){return W.createRecord({hostedZoneId:s,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:"Z2FDTNDATAQYW2",evaluateTargetHealth:!1}})}static createAlbAlias(n,i,s,o){return W.createRecord({hostedZoneId:o,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:s,evaluateTargetHealth:!0}})}static createCname(n,i,s,o=300){return W.createRecord({hostedZoneId:s,name:n,type:"CNAME",ttl:o,values:[i]})}static createWwwRedirect(n,i){return W.createRecord({hostedZoneId:i,name:`www.${n}`,type:"CNAME",ttl:300,values:[n]})}static createMxRecords(n,i,s,o=300){return W.createRecord({hostedZoneId:s,name:n,type:"MX",ttl:o,values:i.map((c)=>`${c.priority} ${c.server}`)})}static createTxtRecord(n,i,s,o=300){return W.createRecord({hostedZoneId:s,name:n,type:"TXT",ttl:o,values:[`"${i}"`]})}static createSpfRecord(n,i,s){return W.createTxtRecord(n,i,s)}static createDmarcRecord(n,i,s,o){let c=`v=DMARC1; p=${i}; rua=mailto:${s}`;return W.createTxtRecord(`_dmarc.${n}`,c,o)}static createS3WebsiteAlias(n,i,s,o){return W.createRecord({hostedZoneId:o,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:s,evaluateTargetHealth:!1}})}static S3WebsiteHostedZoneIds={"us-east-1":"Z3AQBSTGFYJSTF","us-east-2":"Z2O1EMRO9K5GLX","us-west-1":"Z2F56UZL2M1ACD","us-west-2":"Z3BJ6K6RIION7M","af-south-1":"Z83WF9RJE8B12","ap-east-1":"ZNB98KWMFR0R6","ap-south-1":"Z11RGJOFQNVJUP","ap-south-2":"Z02976202B4EZMXIPMXF7","ap-northeast-1":"Z2M4EHUR26P7ZW","ap-northeast-2":"Z3W03O7B5YMIYP","ap-northeast-3":"Z2YQB5RD63NC85","ap-southeast-1":"Z3O0J2DXBE1FTB","ap-southeast-2":"Z1WCIBER6CPFUU","ap-southeast-3":"Z01613992JD795ZI93075","ca-central-1":"Z1QDHH18159H29","eu-central-1":"Z21DNDUVLTQW6Q","eu-central-2":"Z030506016YDQGETNASS","eu-west-1":"Z1BKCTXD74EZPE","eu-west-2":"Z3GKZC51ZF0DB4","eu-west-3":"Z3R1K369G5AVDG","eu-north-1":"Z3BAZG2TWCNX0D","eu-south-1":"Z30OZKI7KPW7MI","eu-south-2":"Z0081959F7139GRJC19J","me-south-1":"Z1MPMWCPA7YB62","me-central-1":"Z06143092I8HRBER9VXCO","sa-east-1":"Z7KQH4QJS55SO"};static getS3WebsiteEndpoint(n,i){return`${n}.s3-website-${i}.amazonaws.com`}static createStoreRecord(n,i,s){return W.createCname(`store.${n}`,i,s)}static createApiRecord(n,i,s){return W.createCname(`api.${n}`,i,s)}static createDocsRecord(n,i,s){return W.createCname(`docs.${n}`,i,s)}static CloudFrontHostedZoneId="Z2FDTNDATAQYW2"}class E{static createCertificate(n){let{domain:i,subdomains:s=[],slug:o,environment:c,validationMethod:u="DNS",hostedZoneId:d}=n,g=r({slug:o,environment:c,resourceType:"acm"}),y=t(`${g}-${i.replace(/\./g,"")}`),h=[i];for(let C of s)if(C==="*")h.push(`*.${i}`);else h.push(`${C}.${i}`);let A={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:i,SubjectAlternativeNames:h,ValidationMethod:u}};if(u==="DNS"&&d)A.Properties.DomainValidationOptions=h.map((C)=>({DomainName:C,HostedZoneId:d}));return{certificate:A,logicalId:y}}static createKmsKey(n){let{description:i,slug:s,environment:o,enableRotation:c=!0,multiRegion:u=!1}=n,d=r({slug:s,environment:o,resourceType:"kms"}),g=t(d),y={Version:"2012-10-17",Statement:[{Sid:"Enable IAM User Permissions",Effect:"Allow",Principal:{AWS:x.Sub("arn:aws:iam::${AWS::AccountId}:root")},Action:"kms:*",Resource:"*"},{Sid:"Allow services to use the key",Effect:"Allow",Principal:{Service:["s3.amazonaws.com","cloudfront.amazonaws.com","logs.amazonaws.com","secretsmanager.amazonaws.com"]},Action:["kms:Decrypt","kms:GenerateDataKey"],Resource:"*"}]},h={Type:"AWS::KMS::Key",Properties:{Description:i,Enabled:!0,EnableKeyRotation:c,KeyPolicy:y,KeySpec:"SYMMETRIC_DEFAULT",KeyUsage:"ENCRYPT_DECRYPT",MultiRegion:u}},A=t(`${d}-alias`),C={Type:"AWS::KMS::Alias",Properties:{AliasName:`alias/${s}-${o}`,TargetKeyId:x.Ref(g)}};return{key:h,alias:C,logicalId:g,aliasId:A}}static createFirewall(n){let{slug:i,environment:s,scope:o="CLOUDFRONT",defaultAction:c="allow"}=n,u=r({slug:i,environment:s,resourceType:"waf"}),d=t(u);return{webAcl:{Type:"AWS::WAFv2::WebACL",Properties:{Name:u,Scope:o,DefaultAction:c==="allow"?{Allow:{}}:{Block:{}},Description:`WAF for ${i} ${s}`,Rules:[],VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${u}-metric`}}},logicalId:d}}static setRateLimit(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{RateBasedStatement:{Limit:i.requestsPerWindow,AggregateKeyType:i.aggregateKeyType||"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static blockCountries(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{GeoMatchStatement:{CountryCodes:i.countryCodes}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static blockIpAddresses(n,i,s,o){let c=r({slug:s,environment:o,resourceType:"ipset"}),u=t(`${c}-${i.name}`),d={Type:"AWS::WAFv2::IPSet",Properties:{Name:`${c}-${i.name}`,Scope:n.Properties.Scope,IPAddressVersion:i.ipVersion||"IPV4",Addresses:i.ipAddresses,Description:`Blocked IPs for ${i.name}`}};if(!n.Properties.Rules)n.Properties.Rules=[];return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{IPSetReferenceStatement:{Arn:x.GetAtt(u,"Arn")}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),{webAcl:n,ipSet:d,ipSetLogicalId:u}}static addManagedRules(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];let s={ManagedRuleGroupStatement:{VendorName:i.vendorName,Name:i.ruleName}};if(i.excludedRules&&i.excludedRules.length>0)s.ManagedRuleGroupStatement.ExcludedRules=i.excludedRules.map((o)=>({Name:o}));return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:s,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static ManagedRuleGroups={CoreRuleSet:{vendorName:"AWS",ruleName:"AWSManagedRulesCommonRuleSet"},KnownBadInputs:{vendorName:"AWS",ruleName:"AWSManagedRulesKnownBadInputsRuleSet"},SqlDatabase:{vendorName:"AWS",ruleName:"AWSManagedRulesSQLiRuleSet"},LinuxOS:{vendorName:"AWS",ruleName:"AWSManagedRulesLinuxRuleSet"},PosixOS:{vendorName:"AWS",ruleName:"AWSManagedRulesUnixRuleSet"},AmazonIpReputation:{vendorName:"AWS",ruleName:"AWSManagedRulesAmazonIpReputationList"},AnonymousIpList:{vendorName:"AWS",ruleName:"AWSManagedRulesAnonymousIpList"},BotControl:{vendorName:"AWS",ruleName:"AWSManagedRulesBotControlRuleSet"}};static setPathRateLimit(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];let s=i.paths.map((o)=>({SearchString:o,FieldToMatch:{UriPath:{}},TextTransformation:[{Priority:0,Type:"LOWERCASE"}],PositionalConstraint:"STARTS_WITH"}));return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{RateBasedStatement:{Limit:i.requestsPerWindow,AggregateKeyType:i.aggregateKeyType||"IP",ScopeDownStatement:{OrStatement:{Statements:s.map((o)=>({ByteMatchStatement:o}))}}}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static setHeaderRateLimit(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];let s={RateBasedStatement:{Limit:i.requestsPerWindow,AggregateKeyType:"CUSTOM_KEYS",CustomKeys:[{Header:{Name:i.headerName,TextTransformations:[{Priority:0,Type:"NONE"}]}}]}};if(i.headerValue)s.RateBasedStatement.ScopeDownStatement={ByteMatchStatement:{SearchString:i.headerValue,FieldToMatch:{SingleHeader:{Name:i.headerName}},TextTransformation:[{Priority:0,Type:"NONE"}],PositionalConstraint:"EXACTLY"}};return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:s,Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static protectLoginEndpoint(n,i){let{loginPaths:s,priority:o,requestsPerMinute:c=10}=i;return E.setPathRateLimit(n,{name:"LoginRateLimit",priority:o,requestsPerWindow:c*5,paths:s}),n}static protectApiEndpoints(n,i){let{apiPaths:s,priority:o,requestsPerMinute:c=100}=i;return E.setPathRateLimit(n,{name:"ApiRateLimit",priority:o,requestsPerWindow:c*5,paths:s}),n}static createProtectedFirewall(n){let{slug:i,environment:s,scope:o="CLOUDFRONT",enableBotControl:c=!1,enableRateLimiting:u=!0,rateLimitPerMinute:d=2000}=n,{webAcl:g,logicalId:y}=E.createFirewall({slug:i,environment:s,scope:o,defaultAction:"allow"}),h=0;if(g=E.addManagedRules(g,{name:"AWSIPReputationList",priority:h++,...E.ManagedRuleGroups.AmazonIpReputation}),g=E.addManagedRules(g,{name:"AWSAnonymousIPList",priority:h++,...E.ManagedRuleGroups.AnonymousIpList}),g=E.addManagedRules(g,{name:"AWSCoreRuleSet",priority:h++,...E.ManagedRuleGroups.CoreRuleSet}),g=E.addManagedRules(g,{name:"AWSKnownBadInputs",priority:h++,...E.ManagedRuleGroups.KnownBadInputs}),g=E.addManagedRules(g,{name:"AWSSQLi",priority:h++,...E.ManagedRuleGroups.SqlDatabase}),c)g=E.addManagedRules(g,{name:"AWSBotControl",priority:h++,...E.ManagedRuleGroups.BotControl});if(u)g=E.setRateLimit(g,{name:"GlobalRateLimit",priority:h++,requestsPerWindow:d*5});return{webAcl:g,logicalId:y}}static RateLimitPresets={STANDARD:2000,HIGH_TRAFFIC:1e4,STRICT:100,LOGIN:10,API:100}}function oy(n){let i=n.split(".")[0]??"";return i==="a1"||/^[a-z]+\d+g[a-z]*$/.test(i)}function ay(n="t3.micro"){return`/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-${oy(n)?"arm64":"x86_64"}`}function km(n="t3.micro"){return`{{resolve:ssm:${ay(n)}}}`}class a{static createServer(n){let{slug:i,environment:s,instanceType:o="t3.micro",imageId:c=km(o),keyName:u,securityGroupIds:d,subnetId:g,userData:y,volumeSize:h=20,volumeType:A="gp3",encrypted:C=!0}=n,v=r({slug:i,environment:s,resourceType:"ec2"}),T=t(v),R={Type:"AWS::EC2::Instance",Properties:{ImageId:c,InstanceType:o,Tags:[{Key:"Name",Value:v},{Key:"Environment",Value:s}]}};if(u)R.Properties.KeyName=u;if(d)R.Properties.SecurityGroupIds=d;if(g)R.Properties.SubnetId=g;if(y)R.Properties.UserData=x.Base64(y);return R.Properties.BlockDeviceMappings=[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:h,VolumeType:A,Encrypted:C,DeleteOnTermination:!0}}],{instance:R,logicalId:T}}static createSecurityGroup(n){let{slug:i,environment:s,vpcId:o,description:c,ingress:u=[],egress:d=[]}=n,g=r({slug:i,environment:s,resourceType:"sg"}),y=t(g),h={Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:c||`Security group for ${i} ${s}`,Tags:[{Key:"Name",Value:g},{Key:"Environment",Value:s}]}};if(o)h.Properties.VpcId=o;if(u.length>0)h.Properties.SecurityGroupIngress=u.map((A)=>({IpProtocol:A.protocol,FromPort:A.fromPort,ToPort:A.toPort,CidrIp:A.cidr,SourceSecurityGroupId:A.sourceSecurityGroupId}));if(d.length>0)h.Properties.SecurityGroupEgress=d.map((A)=>({IpProtocol:A.protocol,FromPort:A.fromPort,ToPort:A.toPort,CidrIp:A.cidr,DestinationSecurityGroupId:A.sourceSecurityGroupId}));return{securityGroup:h,logicalId:y}}static createWebServerSecurityGroup(n,i,s){return a.createSecurityGroup({slug:n,environment:i,vpcId:s,description:"Security group for web servers - HTTP, HTTPS, SSH",ingress:[{protocol:"tcp",fromPort:80,toPort:80,cidr:"0.0.0.0/0"},{protocol:"tcp",fromPort:443,toPort:443,cidr:"0.0.0.0/0"},{protocol:"tcp",fromPort:22,toPort:22,cidr:"0.0.0.0/0"}],egress:[{protocol:"-1",fromPort:0,toPort:0,cidr:"0.0.0.0/0"}]})}static createLoadBalancer(n){let{slug:i,environment:s,scheme:o="internet-facing",subnets:c,securityGroups:u,type:d="application"}=n,g=r({slug:i,environment:s,resourceType:"alb"}),y=t(g),h={Type:"AWS::ElasticLoadBalancingV2::LoadBalancer",Properties:{Name:g,Scheme:o,Type:d,Subnets:c,Tags:[{Key:"Name",Value:g},{Key:"Environment",Value:s}]}};if(u)h.Properties.SecurityGroups=u;return{loadBalancer:h,logicalId:y}}static createTargetGroup(n){let{slug:i,environment:s,port:o,protocol:c="HTTP",vpcId:u,targetType:d="ip",healthCheckPath:g="/",healthCheckInterval:y=30,healthCheckTimeout:h=5,healthyThreshold:A=2,unhealthyThreshold:C=3}=n,v=r({slug:i,environment:s,resourceType:"tg"}),T=t(v);return{targetGroup:{Type:"AWS::ElasticLoadBalancingV2::TargetGroup",Properties:{Name:v,Port:o,Protocol:c,VpcId:u,TargetType:d,HealthCheckEnabled:!0,HealthCheckProtocol:c,HealthCheckPath:g,HealthCheckIntervalSeconds:y,HealthCheckTimeoutSeconds:h,HealthyThresholdCount:A,UnhealthyThresholdCount:C,Tags:[{Key:"Name",Value:v},{Key:"Environment",Value:s}]}},logicalId:T}}static createListener(n,i){let{port:s,protocol:o="HTTP",certificateArn:c,defaultTargetGroupArn:u}=i,d=t(`listener-${n}-${s}`),g={Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:x.Ref(n),Port:s,Protocol:o,DefaultActions:[{Type:"forward",TargetGroupArn:u}]}};if(o==="HTTPS"&&c)g.Properties.Certificates=[{CertificateArn:c}],g.Properties.SslPolicy="ELBSecurityPolicy-TLS13-1-2-2021-06";return{listener:g,logicalId:d}}static createEcsCluster(n,i){let s=r({slug:n,environment:i,resourceType:"ecs-cluster"}),o=t(s);return{cluster:{Type:"AWS::ECS::Cluster",Properties:{ClusterName:s,Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:i}]}},logicalId:o}}static createFargateService(n){let{slug:i,environment:s,image:o,cpu:c="256",memory:u="512",desiredCount:d=1,containerPort:g=8080,environmentVariables:y={},secrets:h=[],healthCheck:A,logGroup:C,subnets:v,securityGroups:T,targetGroupArn:R}=n,{cluster:P,logicalId:I}=a.createEcsCluster(i,s),M=r({slug:i,environment:s,resourceType:"fargate"}),L=t(`${M}-execution-role`),N={Type:"AWS::IAM::Role",Properties:{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"]}},O=t(`${M}-task-role`),B={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]}}},F=t(`${M}-task`),U={Type:"AWS::ECS::TaskDefinition",Properties:{Family:M,TaskRoleArn:x.GetAtt(O,"Arn"),ExecutionRoleArn:x.GetAtt(L,"Arn"),NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:c,Memory:u,ContainerDefinitions:[{Name:i,Image:o,Essential:!0,PortMappings:[{ContainerPort:g,Protocol:"tcp"}],Environment:Object.entries(y).map(([z,se])=>({Name:z,Value:se})),Secrets:h.map((z)=>({Name:z.name,ValueFrom:z.valueFrom}))}],Tags:[{Key:"Name",Value:M},{Key:"Environment",Value:s}]}};if(A)U.Properties.ContainerDefinitions[0].HealthCheck={Command:A.command,Interval:A.interval||30,Timeout:A.timeout||5,Retries:A.retries||3,StartPeriod:60};if(C)U.Properties.ContainerDefinitions[0].LogConfiguration={LogDriver:"awslogs",Options:{"awslogs-group":C,"awslogs-region":x.Ref("AWS::Region"),"awslogs-stream-prefix":i}};let j=t(`${M}-service`),H={Type:"AWS::ECS::Service",Properties:{ServiceName:M,Cluster:x.Ref(I),TaskDefinition:x.Ref(F),DesiredCount:d,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{Subnets:v,SecurityGroups:T,AssignPublicIp:"ENABLED"}},Tags:[{Key:"Name",Value:M},{Key:"Environment",Value:s}]}};if(R)H.Properties.LoadBalancers=[{TargetGroupArn:R,ContainerName:i,ContainerPort:g}];return{cluster:P,taskDefinition:U,service:H,taskRole:B,executionRole:N,clusterLogicalId:I,taskDefinitionLogicalId:F,serviceLogicalId:j,taskRoleLogicalId:O,executionRoleLogicalId:L}}static createLambdaFunction(n){let{slug:i,environment:s,runtime:o,handler:c,code:u,timeout:d=30,memorySize:g=128,environmentVariables:y={},vpcConfig:h}=n,A=r({slug:i,environment:s,resourceType:"lambda"}),C=t(A),v=t(`${A}-role`),T={Type:"AWS::IAM::Role",Properties:{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"]}};if(h)T.Properties.ManagedPolicyArns.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");let R={Type:"AWS::Lambda::Function",Properties:{FunctionName:A,Runtime:o,Role:x.GetAtt(v,"Arn"),Handler:c,Code:{...u.s3Bucket&&{S3Bucket:u.s3Bucket},...u.s3Key&&{S3Key:u.s3Key},...u.zipFile&&{ZipFile:u.zipFile}},Timeout:d,MemorySize:g,Tags:[{Key:"Name",Value:A},{Key:"Environment",Value:s}]}};if(Object.keys(y).length>0)R.Properties.Environment={Variables:y};if(h)R.Properties.VpcConfig={SecurityGroupIds:h.securityGroupIds,SubnetIds:h.subnetIds};return{lambdaFunction:R,role:T,logicalId:C,roleLogicalId:v}}static generateNodeServerUserData(n={}){let{nodeVersion:i="20",appRepo:s,environment:o={}}=n,c=Object.entries(o).map(([u,d])=>`echo "export ${u}='${d}'" >> /etc/environment`).join(`
200
+ `.trim()};static Config={ttl:(n)=>{let{min:i=0,max:s=86400,default:o=86400}=n;return{MinTTL:i,MaxTTL:s,DefaultTTL:o}},cookies:(n,i)=>{let s={Forward:n==="allowList"?"whitelist":n};if(n==="allowList"&&i)s.WhitelistedNames=i;return s},allowedMethods:(n)=>{let i={ALL:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return i[n]||i.GET_HEAD},cachedMethods:(n)=>{let i={GET_HEAD:["GET","HEAD"],GET_HEAD_OPTIONS:["GET","HEAD","OPTIONS"]};return i[n]||i.GET_HEAD},ttlPresets:{static:{min:0,max:31536000,default:31536000},dynamic:{min:0,max:0,default:0},api:{min:0,max:3600,default:60},html:{min:0,max:86400,default:86400},images:{min:0,max:604800,default:604800}},cacheBehavior:(n)=>{let{ttl:i={min:0,max:86400,default:86400},cookies:s="none",allowedCookies:o,allowedMethods:c="GET_HEAD",cachedMethods:u="GET_HEAD",compress:d=!0,forwardQueryString:g=!0,forwardHeaders:y=[]}=n;return{MinTTL:i.min,MaxTTL:i.max,DefaultTTL:i.default,Compress:d,AllowedMethods:ve.Config.allowedMethods(c),CachedMethods:ve.Config.cachedMethods(u),ForwardedValues:{QueryString:g,Headers:y,Cookies:ve.Config.cookies(s,o)}}}};static applyConfig(n,i){let s=n.Properties.DistributionConfig.DefaultCacheBehavior;if(i.ttl)s.MinTTL=i.ttl.min,s.MaxTTL=i.ttl.max,s.DefaultTTL=i.ttl.default;if(i.compress!==void 0)s.Compress=i.compress;if(i.allowedMethods)s.AllowedMethods=ve.Config.allowedMethods(i.allowedMethods);if(i.cachedMethods)s.CachedMethods=ve.Config.cachedMethods(i.cachedMethods);if(i.cookies){if(!s.ForwardedValues)s.ForwardedValues={QueryString:!0};s.ForwardedValues.Cookies=ve.Config.cookies(i.cookies,i.allowedCookies)}return n}}var fy=[403,404,500,502,503,504],Il="TsCloud::StorageFailover",Jo="AllowCloudFrontFailoverRead",$r=/^[a-z]{2}(?:-gov)?-[a-z]+-\d$/,Br=/^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/;function _m(n){let{failover:i,primaryBucket:s,primaryRegion:o}=n,c=n.where??"storage failover";if(!i||typeof i!=="object")throw Error(`${c}.failover must be an object such as { region: 'us-west-2' }.`);if(!i.region||!$r.test(i.region))throw Error(`${c}.failover.region must be an AWS region such as 'us-west-2', got ${JSON.stringify(i.region)}.`);if(i.region===o)throw Error(`${c}.failover.region is ${i.region}, the same region as the primary bucket. Failover only helps when the replica is in another region.`);let u=i.bucket??`${s}-${i.region}`;if(!Br.test(u)||u.includes("..")){let d=i.bucket===void 0&&u.length>63?` The default name (<primary bucket>-<region>) is ${u.length} characters; S3 allows 63. Set ${c}.failover.bucket.`:"";throw Error(`${c}.failover: "${u}" is not a valid S3 bucket name.${d}`)}if(u===s)throw Error(`${c}.failover.bucket must differ from the primary bucket "${s}".`);return{replicaBucket:u,replicaRegion:i.region,replicate:i.replicate!==!1,statusCodes:Ko(i.statusCodes??fy),primaryConnection:ue(i,`${c}.failover`)}}function Lm(n,i){return`${n}.s3.${i}.amazonaws.com`}function $m(n){let i=`arn:aws:s3:::${n.primaryBucket}`,s=`arn:aws:s3:::${n.replicaBucket}`;return{Type:"AWS::IAM::Role",Properties:{...n.roleName?{RoleName:n.roleName}:{},AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"s3.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"failover-replication",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["s3:GetReplicationConfiguration","s3:ListBucket"],Resource:i},{Effect:"Allow",Action:["s3:GetObjectVersionForReplication","s3:GetObjectVersionAcl","s3:GetObjectVersionTagging"],Resource:`${i}/*`},{Effect:"Allow",Action:["s3:ReplicateObject","s3:ReplicateDelete","s3:ReplicateTags"],Resource:`${s}/*`}]}}]}}}function Mm(n){return{Role:n.roleArn,Rules:[{Id:"cloudfront-failover-replica",Status:"Enabled",Priority:1,Filter:{Prefix:""},DeleteMarkerReplication:{Status:"Enabled"},Destination:{Bucket:`arn:aws:s3:::${n.replicaBucket}`}}]}}function bl(n){return{Sid:Jo,Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:`arn:aws:s3:::${n.replicaBucket}/*`,Condition:{StringEquals:{"AWS:SourceArn":n.distributionArn}}}}function ab(n){let s=(typeof n==="string"?JSON.parse(n):n)?.Metadata?.[Il];return Array.isArray(s)?s:[]}class J{static createHostedZone(n){let{domain:i,slug:s,environment:o,comment:c}=n,u=r({slug:s,environment:o,resourceType:"hostedzone"}),d=t(`${u}-${i.replace(/\./g,"")}`);return{zone:{Type:"AWS::Route53::HostedZone",Properties:{Name:i,HostedZoneConfig:{Comment:c||`Hosted zone for ${i}`}}},logicalId:d}}static createRecord(n){let{hostedZoneId:i,hostedZoneName:s,name:o,type:c,ttl:u,values:d,aliasTarget:g}=n,y=t(`record-${o.replace(/\./g,"")}-${c}`),h={Type:"AWS::Route53::RecordSet",Properties:{Name:o,Type:c}};if(i)h.Properties.HostedZoneId=i;else if(s)h.Properties.HostedZoneName=s;if(g)h.Properties.AliasTarget={DNSName:g.dnsName,HostedZoneId:g.hostedZoneId,EvaluateTargetHealth:g.evaluateTargetHealth??!1};else h.Properties.TTL=u||300,h.Properties.ResourceRecords=d||[];return{record:h,logicalId:y}}static createCloudFrontAlias(n,i,s){return J.createRecord({hostedZoneId:s,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:"Z2FDTNDATAQYW2",evaluateTargetHealth:!1}})}static createAlbAlias(n,i,s,o){return J.createRecord({hostedZoneId:o,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:s,evaluateTargetHealth:!0}})}static createCname(n,i,s,o=300){return J.createRecord({hostedZoneId:s,name:n,type:"CNAME",ttl:o,values:[i]})}static createWwwRedirect(n,i){return J.createRecord({hostedZoneId:i,name:`www.${n}`,type:"CNAME",ttl:300,values:[n]})}static createMxRecords(n,i,s,o=300){return J.createRecord({hostedZoneId:s,name:n,type:"MX",ttl:o,values:i.map((c)=>`${c.priority} ${c.server}`)})}static createTxtRecord(n,i,s,o=300){return J.createRecord({hostedZoneId:s,name:n,type:"TXT",ttl:o,values:[`"${i}"`]})}static createSpfRecord(n,i,s){return J.createTxtRecord(n,i,s)}static createDmarcRecord(n,i,s,o){let c=`v=DMARC1; p=${i}; rua=mailto:${s}`;return J.createTxtRecord(`_dmarc.${n}`,c,o)}static createS3WebsiteAlias(n,i,s,o){return J.createRecord({hostedZoneId:o,name:n,type:"A",aliasTarget:{dnsName:i,hostedZoneId:s,evaluateTargetHealth:!1}})}static S3WebsiteHostedZoneIds={"us-east-1":"Z3AQBSTGFYJSTF","us-east-2":"Z2O1EMRO9K5GLX","us-west-1":"Z2F56UZL2M1ACD","us-west-2":"Z3BJ6K6RIION7M","af-south-1":"Z83WF9RJE8B12","ap-east-1":"ZNB98KWMFR0R6","ap-south-1":"Z11RGJOFQNVJUP","ap-south-2":"Z02976202B4EZMXIPMXF7","ap-northeast-1":"Z2M4EHUR26P7ZW","ap-northeast-2":"Z3W03O7B5YMIYP","ap-northeast-3":"Z2YQB5RD63NC85","ap-southeast-1":"Z3O0J2DXBE1FTB","ap-southeast-2":"Z1WCIBER6CPFUU","ap-southeast-3":"Z01613992JD795ZI93075","ca-central-1":"Z1QDHH18159H29","eu-central-1":"Z21DNDUVLTQW6Q","eu-central-2":"Z030506016YDQGETNASS","eu-west-1":"Z1BKCTXD74EZPE","eu-west-2":"Z3GKZC51ZF0DB4","eu-west-3":"Z3R1K369G5AVDG","eu-north-1":"Z3BAZG2TWCNX0D","eu-south-1":"Z30OZKI7KPW7MI","eu-south-2":"Z0081959F7139GRJC19J","me-south-1":"Z1MPMWCPA7YB62","me-central-1":"Z06143092I8HRBER9VXCO","sa-east-1":"Z7KQH4QJS55SO"};static getS3WebsiteEndpoint(n,i){return`${n}.s3-website-${i}.amazonaws.com`}static createStoreRecord(n,i,s){return J.createCname(`store.${n}`,i,s)}static createApiRecord(n,i,s){return J.createCname(`api.${n}`,i,s)}static createDocsRecord(n,i,s){return J.createCname(`docs.${n}`,i,s)}static CloudFrontHostedZoneId="Z2FDTNDATAQYW2"}class E{static createCertificate(n){let{domain:i,subdomains:s=[],slug:o,environment:c,validationMethod:u="DNS",hostedZoneId:d}=n,g=r({slug:o,environment:c,resourceType:"acm"}),y=t(`${g}-${i.replace(/\./g,"")}`),h=[i];for(let C of s)if(C==="*")h.push(`*.${i}`);else h.push(`${C}.${i}`);let A={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:i,SubjectAlternativeNames:h,ValidationMethod:u}};if(u==="DNS"&&d)A.Properties.DomainValidationOptions=h.map((C)=>({DomainName:C,HostedZoneId:d}));return{certificate:A,logicalId:y}}static createKmsKey(n){let{description:i,slug:s,environment:o,enableRotation:c=!0,multiRegion:u=!1}=n,d=r({slug:s,environment:o,resourceType:"kms"}),g=t(d),y={Version:"2012-10-17",Statement:[{Sid:"Enable IAM User Permissions",Effect:"Allow",Principal:{AWS:M.Sub("arn:aws:iam::${AWS::AccountId}:root")},Action:"kms:*",Resource:"*"},{Sid:"Allow services to use the key",Effect:"Allow",Principal:{Service:["s3.amazonaws.com","cloudfront.amazonaws.com","logs.amazonaws.com","secretsmanager.amazonaws.com"]},Action:["kms:Decrypt","kms:GenerateDataKey"],Resource:"*"}]},h={Type:"AWS::KMS::Key",Properties:{Description:i,Enabled:!0,EnableKeyRotation:c,KeyPolicy:y,KeySpec:"SYMMETRIC_DEFAULT",KeyUsage:"ENCRYPT_DECRYPT",MultiRegion:u}},A=t(`${d}-alias`),C={Type:"AWS::KMS::Alias",Properties:{AliasName:`alias/${s}-${o}`,TargetKeyId:M.Ref(g)}};return{key:h,alias:C,logicalId:g,aliasId:A}}static createFirewall(n){let{slug:i,environment:s,scope:o="CLOUDFRONT",defaultAction:c="allow"}=n,u=r({slug:i,environment:s,resourceType:"waf"}),d=t(u);return{webAcl:{Type:"AWS::WAFv2::WebACL",Properties:{Name:u,Scope:o,DefaultAction:c==="allow"?{Allow:{}}:{Block:{}},Description:`WAF for ${i} ${s}`,Rules:[],VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${u}-metric`}}},logicalId:d}}static setRateLimit(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{RateBasedStatement:{Limit:i.requestsPerWindow,AggregateKeyType:i.aggregateKeyType||"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static blockCountries(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{GeoMatchStatement:{CountryCodes:i.countryCodes}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static blockIpAddresses(n,i,s,o){let c=r({slug:s,environment:o,resourceType:"ipset"}),u=t(`${c}-${i.name}`),d={Type:"AWS::WAFv2::IPSet",Properties:{Name:`${c}-${i.name}`,Scope:n.Properties.Scope,IPAddressVersion:i.ipVersion||"IPV4",Addresses:i.ipAddresses,Description:`Blocked IPs for ${i.name}`}};if(!n.Properties.Rules)n.Properties.Rules=[];return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{IPSetReferenceStatement:{Arn:M.GetAtt(u,"Arn")}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),{webAcl:n,ipSet:d,ipSetLogicalId:u}}static addManagedRules(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];let s={ManagedRuleGroupStatement:{VendorName:i.vendorName,Name:i.ruleName}};if(i.excludedRules&&i.excludedRules.length>0)s.ManagedRuleGroupStatement.ExcludedRules=i.excludedRules.map((o)=>({Name:o}));return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:s,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static ManagedRuleGroups={CoreRuleSet:{vendorName:"AWS",ruleName:"AWSManagedRulesCommonRuleSet"},KnownBadInputs:{vendorName:"AWS",ruleName:"AWSManagedRulesKnownBadInputsRuleSet"},SqlDatabase:{vendorName:"AWS",ruleName:"AWSManagedRulesSQLiRuleSet"},LinuxOS:{vendorName:"AWS",ruleName:"AWSManagedRulesLinuxRuleSet"},PosixOS:{vendorName:"AWS",ruleName:"AWSManagedRulesUnixRuleSet"},AmazonIpReputation:{vendorName:"AWS",ruleName:"AWSManagedRulesAmazonIpReputationList"},AnonymousIpList:{vendorName:"AWS",ruleName:"AWSManagedRulesAnonymousIpList"},BotControl:{vendorName:"AWS",ruleName:"AWSManagedRulesBotControlRuleSet"}};static setPathRateLimit(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];let s=i.paths.map((o)=>({SearchString:o,FieldToMatch:{UriPath:{}},TextTransformation:[{Priority:0,Type:"LOWERCASE"}],PositionalConstraint:"STARTS_WITH"}));return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:{RateBasedStatement:{Limit:i.requestsPerWindow,AggregateKeyType:i.aggregateKeyType||"IP",ScopeDownStatement:{OrStatement:{Statements:s.map((o)=>({ByteMatchStatement:o}))}}}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static setHeaderRateLimit(n,i){if(!n.Properties.Rules)n.Properties.Rules=[];let s={RateBasedStatement:{Limit:i.requestsPerWindow,AggregateKeyType:"CUSTOM_KEYS",CustomKeys:[{Header:{Name:i.headerName,TextTransformations:[{Priority:0,Type:"NONE"}]}}]}};if(i.headerValue)s.RateBasedStatement.ScopeDownStatement={ByteMatchStatement:{SearchString:i.headerValue,FieldToMatch:{SingleHeader:{Name:i.headerName}},TextTransformation:[{Priority:0,Type:"NONE"}],PositionalConstraint:"EXACTLY"}};return n.Properties.Rules.push({Name:i.name,Priority:i.priority,Statement:s,Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${i.name}-metric`}}),n}static protectLoginEndpoint(n,i){let{loginPaths:s,priority:o,requestsPerMinute:c=10}=i;return E.setPathRateLimit(n,{name:"LoginRateLimit",priority:o,requestsPerWindow:c*5,paths:s}),n}static protectApiEndpoints(n,i){let{apiPaths:s,priority:o,requestsPerMinute:c=100}=i;return E.setPathRateLimit(n,{name:"ApiRateLimit",priority:o,requestsPerWindow:c*5,paths:s}),n}static createProtectedFirewall(n){let{slug:i,environment:s,scope:o="CLOUDFRONT",enableBotControl:c=!1,enableRateLimiting:u=!0,rateLimitPerMinute:d=2000}=n,{webAcl:g,logicalId:y}=E.createFirewall({slug:i,environment:s,scope:o,defaultAction:"allow"}),h=0;if(g=E.addManagedRules(g,{name:"AWSIPReputationList",priority:h++,...E.ManagedRuleGroups.AmazonIpReputation}),g=E.addManagedRules(g,{name:"AWSAnonymousIPList",priority:h++,...E.ManagedRuleGroups.AnonymousIpList}),g=E.addManagedRules(g,{name:"AWSCoreRuleSet",priority:h++,...E.ManagedRuleGroups.CoreRuleSet}),g=E.addManagedRules(g,{name:"AWSKnownBadInputs",priority:h++,...E.ManagedRuleGroups.KnownBadInputs}),g=E.addManagedRules(g,{name:"AWSSQLi",priority:h++,...E.ManagedRuleGroups.SqlDatabase}),c)g=E.addManagedRules(g,{name:"AWSBotControl",priority:h++,...E.ManagedRuleGroups.BotControl});if(u)g=E.setRateLimit(g,{name:"GlobalRateLimit",priority:h++,requestsPerWindow:d*5});return{webAcl:g,logicalId:y}}static RateLimitPresets={STANDARD:2000,HIGH_TRAFFIC:1e4,STRICT:100,LOGIN:10,API:100}}function hy(n){let i=n.split(".")[0]??"";return i==="a1"||/^[a-z]+\d+g[a-z]*$/.test(i)}function Ay(n="t3.micro"){return`/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-${hy(n)?"arm64":"x86_64"}`}function Fm(n="t3.micro"){return`{{resolve:ssm:${Ay(n)}}}`}class a{static createServer(n){let{slug:i,environment:s,instanceType:o="t3.micro",imageId:c=Fm(o),keyName:u,securityGroupIds:d,subnetId:g,userData:y,volumeSize:h=20,volumeType:A="gp3",encrypted:C=!0}=n,v=r({slug:i,environment:s,resourceType:"ec2"}),T=t(v),R={Type:"AWS::EC2::Instance",Properties:{ImageId:c,InstanceType:o,Tags:[{Key:"Name",Value:v},{Key:"Environment",Value:s}]}};if(u)R.Properties.KeyName=u;if(d)R.Properties.SecurityGroupIds=d;if(g)R.Properties.SubnetId=g;if(y)R.Properties.UserData=M.Base64(y);return R.Properties.BlockDeviceMappings=[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:h,VolumeType:A,Encrypted:C,DeleteOnTermination:!0}}],{instance:R,logicalId:T}}static createSecurityGroup(n){let{slug:i,environment:s,vpcId:o,description:c,ingress:u=[],egress:d=[]}=n,g=r({slug:i,environment:s,resourceType:"sg"}),y=t(g),h={Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:c||`Security group for ${i} ${s}`,Tags:[{Key:"Name",Value:g},{Key:"Environment",Value:s}]}};if(o)h.Properties.VpcId=o;if(u.length>0)h.Properties.SecurityGroupIngress=u.map((A)=>({IpProtocol:A.protocol,FromPort:A.fromPort,ToPort:A.toPort,CidrIp:A.cidr,SourceSecurityGroupId:A.sourceSecurityGroupId}));if(d.length>0)h.Properties.SecurityGroupEgress=d.map((A)=>({IpProtocol:A.protocol,FromPort:A.fromPort,ToPort:A.toPort,CidrIp:A.cidr,DestinationSecurityGroupId:A.sourceSecurityGroupId}));return{securityGroup:h,logicalId:y}}static createWebServerSecurityGroup(n,i,s){return a.createSecurityGroup({slug:n,environment:i,vpcId:s,description:"Security group for web servers - HTTP, HTTPS, SSH",ingress:[{protocol:"tcp",fromPort:80,toPort:80,cidr:"0.0.0.0/0"},{protocol:"tcp",fromPort:443,toPort:443,cidr:"0.0.0.0/0"},{protocol:"tcp",fromPort:22,toPort:22,cidr:"0.0.0.0/0"}],egress:[{protocol:"-1",fromPort:0,toPort:0,cidr:"0.0.0.0/0"}]})}static createLoadBalancer(n){let{slug:i,environment:s,scheme:o="internet-facing",subnets:c,securityGroups:u,type:d="application"}=n,g=r({slug:i,environment:s,resourceType:"alb"}),y=t(g),h={Type:"AWS::ElasticLoadBalancingV2::LoadBalancer",Properties:{Name:g,Scheme:o,Type:d,Subnets:c,Tags:[{Key:"Name",Value:g},{Key:"Environment",Value:s}]}};if(u)h.Properties.SecurityGroups=u;return{loadBalancer:h,logicalId:y}}static createTargetGroup(n){let{slug:i,environment:s,port:o,protocol:c="HTTP",vpcId:u,targetType:d="ip",healthCheckPath:g="/",healthCheckInterval:y=30,healthCheckTimeout:h=5,healthyThreshold:A=2,unhealthyThreshold:C=3}=n,v=r({slug:i,environment:s,resourceType:"tg"}),T=t(v);return{targetGroup:{Type:"AWS::ElasticLoadBalancingV2::TargetGroup",Properties:{Name:v,Port:o,Protocol:c,VpcId:u,TargetType:d,HealthCheckEnabled:!0,HealthCheckProtocol:c,HealthCheckPath:g,HealthCheckIntervalSeconds:y,HealthCheckTimeoutSeconds:h,HealthyThresholdCount:A,UnhealthyThresholdCount:C,Tags:[{Key:"Name",Value:v},{Key:"Environment",Value:s}]}},logicalId:T}}static createListener(n,i){let{port:s,protocol:o="HTTP",certificateArn:c,defaultTargetGroupArn:u}=i,d=t(`listener-${n}-${s}`),g={Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:M.Ref(n),Port:s,Protocol:o,DefaultActions:[{Type:"forward",TargetGroupArn:u}]}};if(o==="HTTPS"&&c)g.Properties.Certificates=[{CertificateArn:c}],g.Properties.SslPolicy="ELBSecurityPolicy-TLS13-1-2-2021-06";return{listener:g,logicalId:d}}static createEcsCluster(n,i){let s=r({slug:n,environment:i,resourceType:"ecs-cluster"}),o=t(s);return{cluster:{Type:"AWS::ECS::Cluster",Properties:{ClusterName:s,Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:i}]}},logicalId:o}}static createFargateService(n){let{slug:i,environment:s,image:o,cpu:c="256",memory:u="512",desiredCount:d=1,containerPort:g=8080,environmentVariables:y={},secrets:h=[],healthCheck:A,logGroup:C,subnets:v,securityGroups:T,targetGroupArn:R}=n,{cluster:P,logicalId:I}=a.createEcsCluster(i,s),O=r({slug:i,environment:s,resourceType:"fargate"}),B=t(`${O}-execution-role`),x={Type:"AWS::IAM::Role",Properties:{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"]}},F=t(`${O}-task-role`),G={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]}}},_=t(`${O}-task`),U={Type:"AWS::ECS::TaskDefinition",Properties:{Family:O,TaskRoleArn:M.GetAtt(F,"Arn"),ExecutionRoleArn:M.GetAtt(B,"Arn"),NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:c,Memory:u,ContainerDefinitions:[{Name:i,Image:o,Essential:!0,PortMappings:[{ContainerPort:g,Protocol:"tcp"}],Environment:Object.entries(y).map(([Q,ae])=>({Name:Q,Value:ae})),Secrets:h.map((Q)=>({Name:Q.name,ValueFrom:Q.valueFrom}))}],Tags:[{Key:"Name",Value:O},{Key:"Environment",Value:s}]}};if(A)U.Properties.ContainerDefinitions[0].HealthCheck={Command:A.command,Interval:A.interval||30,Timeout:A.timeout||5,Retries:A.retries||3,StartPeriod:60};if(C)U.Properties.ContainerDefinitions[0].LogConfiguration={LogDriver:"awslogs",Options:{"awslogs-group":C,"awslogs-region":M.Ref("AWS::Region"),"awslogs-stream-prefix":i}};let z=t(`${O}-service`),K={Type:"AWS::ECS::Service",Properties:{ServiceName:O,Cluster:M.Ref(I),TaskDefinition:M.Ref(_),DesiredCount:d,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{Subnets:v,SecurityGroups:T,AssignPublicIp:"ENABLED"}},Tags:[{Key:"Name",Value:O},{Key:"Environment",Value:s}]}};if(R)K.Properties.LoadBalancers=[{TargetGroupArn:R,ContainerName:i,ContainerPort:g}];return{cluster:P,taskDefinition:U,service:K,taskRole:G,executionRole:x,clusterLogicalId:I,taskDefinitionLogicalId:_,serviceLogicalId:z,taskRoleLogicalId:F,executionRoleLogicalId:B}}static createLambdaFunction(n){let{slug:i,environment:s,runtime:o,handler:c,code:u,timeout:d=30,memorySize:g=128,environmentVariables:y={},vpcConfig:h}=n,A=r({slug:i,environment:s,resourceType:"lambda"}),C=t(A),v=t(`${A}-role`),T={Type:"AWS::IAM::Role",Properties:{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"]}};if(h)T.Properties.ManagedPolicyArns.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");let R={Type:"AWS::Lambda::Function",Properties:{FunctionName:A,Runtime:o,Role:M.GetAtt(v,"Arn"),Handler:c,Code:{...u.s3Bucket&&{S3Bucket:u.s3Bucket},...u.s3Key&&{S3Key:u.s3Key},...u.zipFile&&{ZipFile:u.zipFile}},Timeout:d,MemorySize:g,Tags:[{Key:"Name",Value:A},{Key:"Environment",Value:s}]}};if(Object.keys(y).length>0)R.Properties.Environment={Variables:y};if(h)R.Properties.VpcConfig={SecurityGroupIds:h.securityGroupIds,SubnetIds:h.subnetIds};return{lambdaFunction:R,role:T,logicalId:C,roleLogicalId:v}}static generateNodeServerUserData(n={}){let{nodeVersion:i="20",appRepo:s,environment:o={}}=n,c=Object.entries(o).map(([u,d])=>`echo "export ${u}='${d}'" >> /etc/environment`).join(`
201
201
  `);return`#!/bin/bash
202
202
  # Update system
203
203
  yum update -y
@@ -298,20 +298,20 @@ systemctl enable caddy
298
298
  systemctl start caddy
299
299
 
300
300
  echo "Bun server setup complete!"
301
- `}static createLaunchConfiguration(n){let{slug:i,environment:s,imageId:o,instanceType:c,keyName:u,securityGroups:d,userData:g,volumeSize:y=20,volumeType:h="gp3",encrypted:A=!0,iamInstanceProfile:C}=n,v=r({slug:i,environment:s,resourceType:"launch-config"}),T=t(v),R={Type:"AWS::AutoScaling::LaunchConfiguration",Properties:{ImageId:o,InstanceType:c,BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:y,VolumeType:h,Encrypted:A,DeleteOnTermination:!0}}]}};if(u)R.Properties.KeyName=u;if(d)R.Properties.SecurityGroups=d;if(g)R.Properties.UserData=x.Base64(g);if(C)R.Properties.IamInstanceProfile=C;return{launchConfiguration:R,logicalId:T}}static createAutoScalingGroup(n){let{slug:i,environment:s,launchConfigurationName:o,minSize:c,maxSize:u,desiredCapacity:d,vpcZoneIdentifier:g,targetGroupArns:y,healthCheckType:h="EC2",healthCheckGracePeriod:A=300,cooldown:C=300,tags:v={}}=n,T=r({slug:i,environment:s,resourceType:"asg"}),R=t(T),P={Type:"AWS::AutoScaling::AutoScalingGroup",Properties:{AutoScalingGroupName:T,LaunchConfigurationName:o,MinSize:c,MaxSize:u,HealthCheckType:h,HealthCheckGracePeriod:A,Cooldown:C,Tags:[{Key:"Name",Value:T,PropagateAtLaunch:!0},{Key:"Environment",Value:s,PropagateAtLaunch:!0},...Object.entries(v).map(([I,M])=>({Key:I,Value:M,PropagateAtLaunch:!0}))]}};if(d!==void 0)P.Properties.DesiredCapacity=d;if(g)P.Properties.VPCZoneIdentifier=g;if(y)P.Properties.TargetGroupARNs=y;return P.UpdatePolicy={AutoScalingRollingUpdate:{MaxBatchSize:1,MinInstancesInService:Math.max(0,c-1),PauseTime:"PT5M",WaitOnResourceSignals:!1}},{autoScalingGroup:P,logicalId:R}}static createScalingPolicy(n){let{slug:i,environment:s,autoScalingGroupName:o,policyType:c="TargetTrackingScaling",targetValue:u=70,predefinedMetricType:d="ASGAverageCPUUtilization"}=n,g=r({slug:i,environment:s,resourceType:"scaling-policy"}),y=t(g),h={Type:"AWS::AutoScaling::ScalingPolicy",Properties:{AutoScalingGroupName:o,PolicyType:c}};if(c==="TargetTrackingScaling")h.Properties.TargetTrackingConfiguration={PredefinedMetricSpecification:{PredefinedMetricType:d},TargetValue:u};return{scalingPolicy:h,logicalId:y}}static AutoScaling={smallWebServer:(n,i,s,o,c)=>a.createAutoScalingGroup({slug:n,environment:i,launchConfigurationName:s,minSize:2,maxSize:4,desiredCapacity:2,vpcZoneIdentifier:o,targetGroupArns:c,healthCheckType:c?"ELB":"EC2",healthCheckGracePeriod:300}),mediumWebServer:(n,i,s,o,c)=>a.createAutoScalingGroup({slug:n,environment:i,launchConfigurationName:s,minSize:3,maxSize:10,desiredCapacity:3,vpcZoneIdentifier:o,targetGroupArns:c,healthCheckType:c?"ELB":"EC2",healthCheckGracePeriod:300}),largeWebServer:(n,i,s,o,c)=>a.createAutoScalingGroup({slug:n,environment:i,launchConfigurationName:s,minSize:5,maxSize:20,desiredCapacity:5,vpcZoneIdentifier:o,targetGroupArns:c,healthCheckType:c?"ELB":"EC2",healthCheckGracePeriod:300}),cpuScaling:(n,i,s,o=70)=>a.createScalingPolicy({slug:n,environment:i,autoScalingGroupName:s,policyType:"TargetTrackingScaling",predefinedMetricType:"ASGAverageCPUUtilization",targetValue:o}),requestCountScaling:(n,i,s,o=1000)=>a.createScalingPolicy({slug:n,environment:i,autoScalingGroupName:s,policyType:"TargetTrackingScaling",predefinedMetricType:"ALBRequestCountPerTarget",targetValue:o})};static Secrets={fromSecretsManager:(n)=>Object.entries(n).map(([i,s])=>({name:i,valueFrom:s})),fromJsonSecret:(n,i)=>`${n}:${i}::`,fromSecretVersion:(n,i)=>`${n}::${i}:`,fromSecretVersionStage:(n,i)=>`${n}:::${i}`,createAccessPolicy:(n)=>({PolicyName:"SecretsManagerAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],Resource:n}]}}),createKmsPolicy:(n)=>({PolicyName:"KMSDecryptAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["kms:Decrypt"],Resource:n}]}}),buildSecretArn:(n)=>`arn:aws:secretsmanager:${n.region}:${n.accountId}:secret:${n.secretName}`,buildSecretArnPattern:(n)=>{let i=n.region||"*",s=n.accountId||"*";return`arn:aws:secretsmanager:${i}:${s}:secret:${n.secretNamePrefix}*`},commonAppSecrets:(n)=>({DATABASE_URL:`${n}/database-url`,DATABASE_PASSWORD:`${n}/database-password`,REDIS_URL:`${n}/redis-url`,REDIS_PASSWORD:`${n}/redis-password`,API_KEY:`${n}/api-key`,JWT_SECRET:`${n}/jwt-secret`,ENCRYPTION_KEY:`${n}/encryption-key`,AWS_ACCESS_KEY_ID:`${n}/aws-access-key-id`,AWS_SECRET_ACCESS_KEY:`${n}/aws-secret-access-key`,MAIL_PASSWORD:`${n}/mail-password`,STRIPE_SECRET_KEY:`${n}/stripe-secret-key`,STRIPE_WEBHOOK_SECRET:`${n}/stripe-webhook-secret`})};static createFargateServiceWithSecrets(n){let{secretArns:i=[],kmsKeyArns:s=[],...o}=n,c=a.createFargateService(o);if(i.length>0){if(!c.executionRole.Properties.Policies)c.executionRole.Properties.Policies=[];if(c.executionRole.Properties.Policies.push(a.Secrets.createAccessPolicy(i)),s.length>0)c.executionRole.Properties.Policies.push(a.Secrets.createKmsPolicy(s))}return c}static generateSecretReferences(n){return n.secrets.map((i)=>{let s=`arn:aws:secretsmanager:${n.region}:${n.accountId}:secret:${n.secretPrefix}/${i}`;return{name:i.toUpperCase().replace(/-/g,"_"),valueFrom:s}})}static EnvSecrets={database:(n)=>[{name:"DB_HOST",valueFrom:`${n}:host::`},{name:"DB_PORT",valueFrom:`${n}:port::`},{name:"DB_USERNAME",valueFrom:`${n}:username::`},{name:"DB_PASSWORD",valueFrom:`${n}:password::`},{name:"DB_NAME",valueFrom:`${n}:dbname::`}],redis:(n)=>[{name:"REDIS_HOST",valueFrom:`${n}:host::`},{name:"REDIS_PORT",valueFrom:`${n}:port::`},{name:"REDIS_PASSWORD",valueFrom:`${n}:password::`}],apiCredentials:(n)=>[{name:"API_KEY",valueFrom:`${n}:apiKey::`},{name:"API_SECRET",valueFrom:`${n}:apiSecret::`}],mail:(n)=>[{name:"MAIL_HOST",valueFrom:`${n}:host::`},{name:"MAIL_PORT",valueFrom:`${n}:port::`},{name:"MAIL_USERNAME",valueFrom:`${n}:username::`},{name:"MAIL_PASSWORD",valueFrom:`${n}:password::`}],awsCredentials:(n)=>[{name:"AWS_ACCESS_KEY_ID",valueFrom:`${n}:accessKeyId::`},{name:"AWS_SECRET_ACCESS_KEY",valueFrom:`${n}:secretAccessKey::`}]};static createJumpBox(n){let{slug:i,environment:s,vpcId:o,subnetId:c,keyName:u,instanceType:d="t3.micro",imageId:g=km(d),mountEfs:y,databaseTools:h=!1}=n,A=n.allowedCidrs??(u?["0.0.0.0/0"]:[]),C=r({slug:i,environment:s,resourceType:"jumpbox"}),v=t(`${C}-sg`),T={Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:`${C}-sg`,GroupDescription:`Security group for ${C} JumpBox access`,VpcId:o,SecurityGroupIngress:A.map((F)=>({IpProtocol:"tcp",FromPort:22,ToPort:22,CidrIp:F,Description:`SSH access from ${F}`})),SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound traffic"}],Tags:[{Key:"Name",Value:`${C}-sg`},{Key:"Environment",Value:s}]}},R=t(`${C}-role`),P={Type:"AWS::IAM::Role",Properties:{RoleName:`${C}-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ec2.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"],Policies:y?[{PolicyName:"EFSAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess"],Resource:"*"}]}}]:void 0}},I=t(`${C}-profile`),M={Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:`${C}-profile`,Roles:[x.Ref(R)]}},L=`#!/bin/bash
301
+ `}static createLaunchConfiguration(n){let{slug:i,environment:s,imageId:o,instanceType:c,keyName:u,securityGroups:d,userData:g,volumeSize:y=20,volumeType:h="gp3",encrypted:A=!0,iamInstanceProfile:C}=n,v=r({slug:i,environment:s,resourceType:"launch-config"}),T=t(v),R={Type:"AWS::AutoScaling::LaunchConfiguration",Properties:{ImageId:o,InstanceType:c,BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:y,VolumeType:h,Encrypted:A,DeleteOnTermination:!0}}]}};if(u)R.Properties.KeyName=u;if(d)R.Properties.SecurityGroups=d;if(g)R.Properties.UserData=M.Base64(g);if(C)R.Properties.IamInstanceProfile=C;return{launchConfiguration:R,logicalId:T}}static createAutoScalingGroup(n){let{slug:i,environment:s,launchConfigurationName:o,minSize:c,maxSize:u,desiredCapacity:d,vpcZoneIdentifier:g,targetGroupArns:y,healthCheckType:h="EC2",healthCheckGracePeriod:A=300,cooldown:C=300,tags:v={}}=n,T=r({slug:i,environment:s,resourceType:"asg"}),R=t(T),P={Type:"AWS::AutoScaling::AutoScalingGroup",Properties:{AutoScalingGroupName:T,LaunchConfigurationName:o,MinSize:c,MaxSize:u,HealthCheckType:h,HealthCheckGracePeriod:A,Cooldown:C,Tags:[{Key:"Name",Value:T,PropagateAtLaunch:!0},{Key:"Environment",Value:s,PropagateAtLaunch:!0},...Object.entries(v).map(([I,O])=>({Key:I,Value:O,PropagateAtLaunch:!0}))]}};if(d!==void 0)P.Properties.DesiredCapacity=d;if(g)P.Properties.VPCZoneIdentifier=g;if(y)P.Properties.TargetGroupARNs=y;return P.UpdatePolicy={AutoScalingRollingUpdate:{MaxBatchSize:1,MinInstancesInService:Math.max(0,c-1),PauseTime:"PT5M",WaitOnResourceSignals:!1}},{autoScalingGroup:P,logicalId:R}}static createScalingPolicy(n){let{slug:i,environment:s,autoScalingGroupName:o,policyType:c="TargetTrackingScaling",targetValue:u=70,predefinedMetricType:d="ASGAverageCPUUtilization"}=n,g=r({slug:i,environment:s,resourceType:"scaling-policy"}),y=t(g),h={Type:"AWS::AutoScaling::ScalingPolicy",Properties:{AutoScalingGroupName:o,PolicyType:c}};if(c==="TargetTrackingScaling")h.Properties.TargetTrackingConfiguration={PredefinedMetricSpecification:{PredefinedMetricType:d},TargetValue:u};return{scalingPolicy:h,logicalId:y}}static AutoScaling={smallWebServer:(n,i,s,o,c)=>a.createAutoScalingGroup({slug:n,environment:i,launchConfigurationName:s,minSize:2,maxSize:4,desiredCapacity:2,vpcZoneIdentifier:o,targetGroupArns:c,healthCheckType:c?"ELB":"EC2",healthCheckGracePeriod:300}),mediumWebServer:(n,i,s,o,c)=>a.createAutoScalingGroup({slug:n,environment:i,launchConfigurationName:s,minSize:3,maxSize:10,desiredCapacity:3,vpcZoneIdentifier:o,targetGroupArns:c,healthCheckType:c?"ELB":"EC2",healthCheckGracePeriod:300}),largeWebServer:(n,i,s,o,c)=>a.createAutoScalingGroup({slug:n,environment:i,launchConfigurationName:s,minSize:5,maxSize:20,desiredCapacity:5,vpcZoneIdentifier:o,targetGroupArns:c,healthCheckType:c?"ELB":"EC2",healthCheckGracePeriod:300}),cpuScaling:(n,i,s,o=70)=>a.createScalingPolicy({slug:n,environment:i,autoScalingGroupName:s,policyType:"TargetTrackingScaling",predefinedMetricType:"ASGAverageCPUUtilization",targetValue:o}),requestCountScaling:(n,i,s,o=1000)=>a.createScalingPolicy({slug:n,environment:i,autoScalingGroupName:s,policyType:"TargetTrackingScaling",predefinedMetricType:"ALBRequestCountPerTarget",targetValue:o})};static Secrets={fromSecretsManager:(n)=>Object.entries(n).map(([i,s])=>({name:i,valueFrom:s})),fromJsonSecret:(n,i)=>`${n}:${i}::`,fromSecretVersion:(n,i)=>`${n}::${i}:`,fromSecretVersionStage:(n,i)=>`${n}:::${i}`,createAccessPolicy:(n)=>({PolicyName:"SecretsManagerAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],Resource:n}]}}),createKmsPolicy:(n)=>({PolicyName:"KMSDecryptAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["kms:Decrypt"],Resource:n}]}}),buildSecretArn:(n)=>`arn:aws:secretsmanager:${n.region}:${n.accountId}:secret:${n.secretName}`,buildSecretArnPattern:(n)=>{let i=n.region||"*",s=n.accountId||"*";return`arn:aws:secretsmanager:${i}:${s}:secret:${n.secretNamePrefix}*`},commonAppSecrets:(n)=>({DATABASE_URL:`${n}/database-url`,DATABASE_PASSWORD:`${n}/database-password`,REDIS_URL:`${n}/redis-url`,REDIS_PASSWORD:`${n}/redis-password`,API_KEY:`${n}/api-key`,JWT_SECRET:`${n}/jwt-secret`,ENCRYPTION_KEY:`${n}/encryption-key`,AWS_ACCESS_KEY_ID:`${n}/aws-access-key-id`,AWS_SECRET_ACCESS_KEY:`${n}/aws-secret-access-key`,MAIL_PASSWORD:`${n}/mail-password`,STRIPE_SECRET_KEY:`${n}/stripe-secret-key`,STRIPE_WEBHOOK_SECRET:`${n}/stripe-webhook-secret`})};static createFargateServiceWithSecrets(n){let{secretArns:i=[],kmsKeyArns:s=[],...o}=n,c=a.createFargateService(o);if(i.length>0){if(!c.executionRole.Properties.Policies)c.executionRole.Properties.Policies=[];if(c.executionRole.Properties.Policies.push(a.Secrets.createAccessPolicy(i)),s.length>0)c.executionRole.Properties.Policies.push(a.Secrets.createKmsPolicy(s))}return c}static generateSecretReferences(n){return n.secrets.map((i)=>{let s=`arn:aws:secretsmanager:${n.region}:${n.accountId}:secret:${n.secretPrefix}/${i}`;return{name:i.toUpperCase().replace(/-/g,"_"),valueFrom:s}})}static EnvSecrets={database:(n)=>[{name:"DB_HOST",valueFrom:`${n}:host::`},{name:"DB_PORT",valueFrom:`${n}:port::`},{name:"DB_USERNAME",valueFrom:`${n}:username::`},{name:"DB_PASSWORD",valueFrom:`${n}:password::`},{name:"DB_NAME",valueFrom:`${n}:dbname::`}],redis:(n)=>[{name:"REDIS_HOST",valueFrom:`${n}:host::`},{name:"REDIS_PORT",valueFrom:`${n}:port::`},{name:"REDIS_PASSWORD",valueFrom:`${n}:password::`}],apiCredentials:(n)=>[{name:"API_KEY",valueFrom:`${n}:apiKey::`},{name:"API_SECRET",valueFrom:`${n}:apiSecret::`}],mail:(n)=>[{name:"MAIL_HOST",valueFrom:`${n}:host::`},{name:"MAIL_PORT",valueFrom:`${n}:port::`},{name:"MAIL_USERNAME",valueFrom:`${n}:username::`},{name:"MAIL_PASSWORD",valueFrom:`${n}:password::`}],awsCredentials:(n)=>[{name:"AWS_ACCESS_KEY_ID",valueFrom:`${n}:accessKeyId::`},{name:"AWS_SECRET_ACCESS_KEY",valueFrom:`${n}:secretAccessKey::`}]};static createJumpBox(n){let{slug:i,environment:s,vpcId:o,subnetId:c,keyName:u,instanceType:d="t3.micro",imageId:g=Fm(d),mountEfs:y,databaseTools:h=!1}=n,A=n.allowedCidrs??(u?["0.0.0.0/0"]:[]),C=r({slug:i,environment:s,resourceType:"jumpbox"}),v=t(`${C}-sg`),T={Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:`${C}-sg`,GroupDescription:`Security group for ${C} JumpBox access`,VpcId:o,SecurityGroupIngress:A.map((_)=>({IpProtocol:"tcp",FromPort:22,ToPort:22,CidrIp:_,Description:`SSH access from ${_}`})),SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound traffic"}],Tags:[{Key:"Name",Value:`${C}-sg`},{Key:"Environment",Value:s}]}},R=t(`${C}-role`),P={Type:"AWS::IAM::Role",Properties:{RoleName:`${C}-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ec2.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"],Policies:y?[{PolicyName:"EFSAccess",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess"],Resource:"*"}]}}]:void 0}},I=t(`${C}-profile`),O={Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:`${C}-profile`,Roles:[M.Ref(R)]}},B=`#!/bin/bash
302
302
  dnf install -y amazon-efs-utils nfs-utils jq wget htop
303
- `;if(h)L+=`
303
+ `;if(h)B+=`
304
304
  # Database clients: psql, mysql (MariaDB), redis-cli
305
305
  dnf install -y postgresql16 mariadb105 redis6
306
- `;if(y){let F=y.mountPath||"/mnt/efs";L+=`
306
+ `;if(y){let _=y.mountPath||"/mnt/efs";B+=`
307
307
  # Mount EFS
308
- mkdir -p ${F}
308
+ mkdir -p ${_}
309
309
  for attempt in $(seq 1 30); do
310
- mount -t efs -o tls \${FileSystemId}:/ ${F} && break
310
+ mount -t efs -o tls \${FileSystemId}:/ ${_} && break
311
311
  sleep 10
312
312
  done
313
- echo "\${FileSystemId}:/ ${F} efs _netdev,tls,nofail 0 0" >> /etc/fstab
314
- `}let N=t(C),O={Type:"AWS::EC2::Instance",DependsOn:[I],Properties:{ImageId:g,InstanceType:d,SubnetId:c,SecurityGroupIds:[x.Ref(v)],IamInstanceProfile:x.Ref(I),UserData:y?{"Fn::Base64":x.Sub(L,{FileSystemId:y.fileSystemId})}:x.Base64(L),BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:20,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0}}],Tags:[{Key:"Name",Value:C},{Key:"Environment",Value:s},{Key:"Purpose",Value:"JumpBox/Bastion"}]}};if(u)O.Properties.KeyName=u;let B={[v]:T,[R]:P,[I]:M,[N]:O};return{instance:O,securityGroup:T,instanceProfile:M,instanceRole:P,instanceLogicalId:N,securityGroupLogicalId:v,instanceProfileLogicalId:I,instanceRoleLogicalId:R,resources:B}}static JumpBox={withEfsMount:(n)=>a.createJumpBox({slug:n.slug,environment:n.environment,vpcId:n.vpcId,subnetId:n.subnetId,keyName:n.keyName,instanceType:n.instanceType,allowedCidrs:n.allowedCidrs,mountEfs:{fileSystemId:n.fileSystemId,mountPath:n.mountPath||"/mnt/efs"}}),minimal:(n)=>a.createJumpBox({slug:n.slug,environment:n.environment,vpcId:n.vpcId,subnetId:n.subnetId,keyName:n.keyName,instanceType:"t3.nano",allowedCidrs:n.allowedCidrs}),withDatabaseTools:(n)=>a.createJumpBox({slug:n.slug,environment:n.environment,vpcId:n.vpcId,subnetId:n.subnetId,keyName:n.keyName,instanceType:n.instanceType,allowedCidrs:n.allowedCidrs,databaseTools:!0}),commonCidrs:{any:["0.0.0.0/0"],privateOnly:["10.0.0.0/8","172.16.0.0/12","192.168.0.0/16"]}};static InstanceSize={toInstanceType:(n,i="t3")=>`${i}.${n}`,specs:{nano:{vcpu:2,memory:0.5,instanceType:"t3.nano"},micro:{vcpu:2,memory:1,instanceType:"t3.micro"},small:{vcpu:2,memory:2,instanceType:"t3.small"},medium:{vcpu:2,memory:4,instanceType:"t3.medium"},large:{vcpu:2,memory:8,instanceType:"t3.large"},xlarge:{vcpu:4,memory:16,instanceType:"t3.xlarge"},"2xlarge":{vcpu:8,memory:32,instanceType:"t3.2xlarge"}},toFargateSpecs:(n)=>{let i={nano:{cpu:"256",memory:"512"},micro:{cpu:"256",memory:"1024"},small:{cpu:"512",memory:"1024"},medium:{cpu:"1024",memory:"2048"},large:{cpu:"2048",memory:"4096"},xlarge:{cpu:"4096",memory:"8192"},"2xlarge":{cpu:"4096",memory:"16384"}};return i[n]||i.medium},toLambdaMemory:(n)=>({nano:128,micro:256,small:512,medium:1024,large:2048,xlarge:4096,"2xlarge":8192})[n]||1024,presets:{webServer:"t3.small",apiServer:"t3.medium",worker:"t3.medium",database:"r6i.large",cache:"r6i.medium",compute:"c6i.large",general:"m6i.medium"}};static DiskConfig={create:(n)=>{let{size:i,type:s="ssd",encrypted:o=!0,iops:c,throughput:u,deleteOnTermination:d=!0}=n,y={standard:"gp2",ssd:"gp3",premium:"io2",gp2:"gp2",gp3:"gp3",io1:"io1",io2:"io2"}[s]||"gp3",h={VolumeSize:i,VolumeType:y,Encrypted:o,DeleteOnTermination:d};if((y==="io1"||y==="io2"||y==="gp3")&&c)h.Iops=c;if(y==="gp3"&&u)h.Throughput=u;return h},presets:{standard:{VolumeSize:20,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0},large:{VolumeSize:100,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0},highPerformance:{VolumeSize:50,VolumeType:"io2",Iops:3000,Encrypted:!0,DeleteOnTermination:!0},database:{VolumeSize:100,VolumeType:"io2",Iops:1e4,Encrypted:!0,DeleteOnTermination:!1}}};static SpotConfig={create:(n)=>{let{maxPrice:i,spotInstanceType:s="one-time",interruptionBehavior:o="terminate",blockDurationMinutes:c}=n,u={SpotInstanceType:s,InstanceInterruptionBehavior:o};if(i)u.MaxPrice=i;if(c)u.BlockDurationMinutes=c;return{SpotOptions:u}},presets:{standard:{spotInstanceType:"one-time",interruptionBehavior:"terminate"},persistent:{spotInstanceType:"persistent",interruptionBehavior:"stop"},costOptimized:{maxPrice:"0.05",spotInstanceType:"one-time",interruptionBehavior:"terminate"}}};static MixedInstances={create:(n)=>{let{instanceTypes:i,baseCapacity:s=0,onDemandPercentage:o=20,spotAllocationStrategy:c="capacity-optimized",spotMaxPrice:u}=n,d={OnDemandBaseCapacity:s,OnDemandPercentageAboveBaseCapacity:o,SpotAllocationStrategy:c};if(u)d.SpotMaxPrice=u;let g=i.map(({size:y,weight:h})=>{let A={InstanceType:a.InstanceSize.toInstanceType(y)};if(h)A.WeightedCapacity=String(h);return A});return{MixedInstancesPolicy:{InstancesDistribution:d,LaunchTemplate:{Overrides:g}}}},presets:{costOptimized:{baseCapacity:0,onDemandPercentage:20,spotAllocationStrategy:"lowest-price",instanceTypes:[{size:"small",weight:1},{size:"medium",weight:2}]},balanced:{baseCapacity:1,onDemandPercentage:50,spotAllocationStrategy:"capacity-optimized",instanceTypes:[{size:"medium",weight:1},{size:"large",weight:2}]},highAvailability:{baseCapacity:2,onDemandPercentage:80,spotAllocationStrategy:"capacity-optimized-prioritized",instanceTypes:[{size:"medium",weight:1}]}}};static AutoScalingConfig={create:(n)=>{let{min:i,max:s,desired:o=i,scaleUpThreshold:c=70,scaleDownThreshold:u=30,cooldownSeconds:d=300,targetMetric:g="cpu"}=n,y={cpu:"ASGAverageCPUUtilization",memory:"ASGAverageMemoryUtilization",requests:"ALBRequestCountPerTarget"};return{minSize:i,maxSize:s,desiredCapacity:o,scalingPolicies:[{policyType:"TargetTrackingScaling",targetValue:c,predefinedMetricType:y[g]||y.cpu,scaleInCooldown:d,scaleOutCooldown:d}]}},forEcs:(n)=>{let{min:i,max:s,cpuTarget:o=70,memoryTarget:c}=n,u=[{predefinedMetricType:"ECSServiceAverageCPUUtilization",targetValue:o}];if(c)u.push({predefinedMetricType:"ECSServiceAverageMemoryUtilization",targetValue:c});return{minCapacity:i,maxCapacity:s,targetTrackingPolicies:u}},presets:{small:{min:1,max:3,scaleUpThreshold:70,scaleDownThreshold:30},medium:{min:2,max:10,scaleUpThreshold:70,scaleDownThreshold:30},large:{min:3,max:50,scaleUpThreshold:60,scaleDownThreshold:40},highAvailability:{min:2,max:20,scaleUpThreshold:60,scaleDownThreshold:30}}};static LoadBalancerConfig={healthCheck:(n)=>{let{path:i="/",interval:s=30,timeout:o=5,healthyThreshold:c=2,unhealthyThreshold:u=5,protocol:d="HTTP"}=n,g={HealthCheckIntervalSeconds:s,HealthCheckTimeoutSeconds:o,HealthyThresholdCount:c,UnhealthyThresholdCount:u};if(d!=="TCP")g.HealthCheckPath=i,g.HealthCheckProtocol=d;return g},presets:{standard:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:5},fast:{path:"/health",interval:10,timeout:3,healthyThreshold:2,unhealthyThreshold:2},relaxed:{path:"/health",interval:60,timeout:30,healthyThreshold:2,unhealthyThreshold:10}}};static SslConfig={httpsListener:(n)=>{let{certificateArn:i,targetGroupArn:s,port:o=443,sslPolicy:c="ELBSecurityPolicy-TLS13-1-2-2021-06"}=n;return{Port:o,Protocol:"HTTPS",Certificates:[{CertificateArn:i}],SslPolicy:c,DefaultActions:[{Type:"forward",TargetGroupArn:s}]}},httpRedirectListener:(n=80)=>({Port:n,Protocol:"HTTP",DefaultActions:[{Type:"redirect",RedirectConfig:{Protocol:"HTTPS",Port:"443",StatusCode:"HTTP_301"}}]}),policies:{tls13:"ELBSecurityPolicy-TLS13-1-2-2021-06",tls12:"ELBSecurityPolicy-TLS-1-2-Ext-2018-06",tls11:"ELBSecurityPolicy-TLS-1-1-2017-01",fips:"ELBSecurityPolicy-TLS-1-2-Ext-FIPS-2022-05"}};static FunctionConfig={create:(n)=>{let{handler:i,runtime:s="nodejs20.x",timeout:o=30,memorySize:c=256,environmentVariables:u,reservedConcurrency:d}=n,g={Handler:i,Runtime:s,Timeout:o,MemorySize:c};if(u)g.Environment={Variables:u};if(d)g.ReservedConcurrentExecutions=d;return g},runtimes:{nodejs20:"nodejs20.x",nodejs18:"nodejs18.x",python312:"python3.12",python311:"python3.11",java21:"java21",java17:"java17",go:"provided.al2023",rust:"provided.al2023",bun:"provided.al2023"},presets:{api:{runtime:"nodejs20.x",timeout:30,memorySize:256},worker:{runtime:"nodejs20.x",timeout:300,memorySize:512},cron:{runtime:"nodejs20.x",timeout:900,memorySize:1024},dataProcessing:{runtime:"nodejs20.x",timeout:900,memorySize:3008}}};static UserData={generateAppServerScript:(n)=>{let{runtime:i="bun",runtimeVersion:s="latest",webServer:o="nginx",processManager:c="systemd",enableSsl:u=!0,sslEmail:d="admin@example.com",domain:g,appPort:y=3000,installDatabaseClients:h=!1,installRedis:A=!1,extraPackages:C=[]}=n,v=`#!/bin/bash
313
+ echo "\${FileSystemId}:/ ${_} efs _netdev,tls,nofail 0 0" >> /etc/fstab
314
+ `}let x=t(C),F={Type:"AWS::EC2::Instance",DependsOn:[I],Properties:{ImageId:g,InstanceType:d,SubnetId:c,SecurityGroupIds:[M.Ref(v)],IamInstanceProfile:M.Ref(I),UserData:y?{"Fn::Base64":M.Sub(B,{FileSystemId:y.fileSystemId})}:M.Base64(B),BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:20,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0}}],Tags:[{Key:"Name",Value:C},{Key:"Environment",Value:s},{Key:"Purpose",Value:"JumpBox/Bastion"}]}};if(u)F.Properties.KeyName=u;let G={[v]:T,[R]:P,[I]:O,[x]:F};return{instance:F,securityGroup:T,instanceProfile:O,instanceRole:P,instanceLogicalId:x,securityGroupLogicalId:v,instanceProfileLogicalId:I,instanceRoleLogicalId:R,resources:G}}static JumpBox={withEfsMount:(n)=>a.createJumpBox({slug:n.slug,environment:n.environment,vpcId:n.vpcId,subnetId:n.subnetId,keyName:n.keyName,instanceType:n.instanceType,allowedCidrs:n.allowedCidrs,mountEfs:{fileSystemId:n.fileSystemId,mountPath:n.mountPath||"/mnt/efs"}}),minimal:(n)=>a.createJumpBox({slug:n.slug,environment:n.environment,vpcId:n.vpcId,subnetId:n.subnetId,keyName:n.keyName,instanceType:"t3.nano",allowedCidrs:n.allowedCidrs}),withDatabaseTools:(n)=>a.createJumpBox({slug:n.slug,environment:n.environment,vpcId:n.vpcId,subnetId:n.subnetId,keyName:n.keyName,instanceType:n.instanceType,allowedCidrs:n.allowedCidrs,databaseTools:!0}),commonCidrs:{any:["0.0.0.0/0"],privateOnly:["10.0.0.0/8","172.16.0.0/12","192.168.0.0/16"]}};static InstanceSize={toInstanceType:(n,i="t3")=>`${i}.${n}`,specs:{nano:{vcpu:2,memory:0.5,instanceType:"t3.nano"},micro:{vcpu:2,memory:1,instanceType:"t3.micro"},small:{vcpu:2,memory:2,instanceType:"t3.small"},medium:{vcpu:2,memory:4,instanceType:"t3.medium"},large:{vcpu:2,memory:8,instanceType:"t3.large"},xlarge:{vcpu:4,memory:16,instanceType:"t3.xlarge"},"2xlarge":{vcpu:8,memory:32,instanceType:"t3.2xlarge"}},toFargateSpecs:(n)=>{let i={nano:{cpu:"256",memory:"512"},micro:{cpu:"256",memory:"1024"},small:{cpu:"512",memory:"1024"},medium:{cpu:"1024",memory:"2048"},large:{cpu:"2048",memory:"4096"},xlarge:{cpu:"4096",memory:"8192"},"2xlarge":{cpu:"4096",memory:"16384"}};return i[n]||i.medium},toLambdaMemory:(n)=>({nano:128,micro:256,small:512,medium:1024,large:2048,xlarge:4096,"2xlarge":8192})[n]||1024,presets:{webServer:"t3.small",apiServer:"t3.medium",worker:"t3.medium",database:"r6i.large",cache:"r6i.medium",compute:"c6i.large",general:"m6i.medium"}};static DiskConfig={create:(n)=>{let{size:i,type:s="ssd",encrypted:o=!0,iops:c,throughput:u,deleteOnTermination:d=!0}=n,y={standard:"gp2",ssd:"gp3",premium:"io2",gp2:"gp2",gp3:"gp3",io1:"io1",io2:"io2"}[s]||"gp3",h={VolumeSize:i,VolumeType:y,Encrypted:o,DeleteOnTermination:d};if((y==="io1"||y==="io2"||y==="gp3")&&c)h.Iops=c;if(y==="gp3"&&u)h.Throughput=u;return h},presets:{standard:{VolumeSize:20,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0},large:{VolumeSize:100,VolumeType:"gp3",Encrypted:!0,DeleteOnTermination:!0},highPerformance:{VolumeSize:50,VolumeType:"io2",Iops:3000,Encrypted:!0,DeleteOnTermination:!0},database:{VolumeSize:100,VolumeType:"io2",Iops:1e4,Encrypted:!0,DeleteOnTermination:!1}}};static SpotConfig={create:(n)=>{let{maxPrice:i,spotInstanceType:s="one-time",interruptionBehavior:o="terminate",blockDurationMinutes:c}=n,u={SpotInstanceType:s,InstanceInterruptionBehavior:o};if(i)u.MaxPrice=i;if(c)u.BlockDurationMinutes=c;return{SpotOptions:u}},presets:{standard:{spotInstanceType:"one-time",interruptionBehavior:"terminate"},persistent:{spotInstanceType:"persistent",interruptionBehavior:"stop"},costOptimized:{maxPrice:"0.05",spotInstanceType:"one-time",interruptionBehavior:"terminate"}}};static MixedInstances={create:(n)=>{let{instanceTypes:i,baseCapacity:s=0,onDemandPercentage:o=20,spotAllocationStrategy:c="capacity-optimized",spotMaxPrice:u}=n,d={OnDemandBaseCapacity:s,OnDemandPercentageAboveBaseCapacity:o,SpotAllocationStrategy:c};if(u)d.SpotMaxPrice=u;let g=i.map(({size:y,weight:h})=>{let A={InstanceType:a.InstanceSize.toInstanceType(y)};if(h)A.WeightedCapacity=String(h);return A});return{MixedInstancesPolicy:{InstancesDistribution:d,LaunchTemplate:{Overrides:g}}}},presets:{costOptimized:{baseCapacity:0,onDemandPercentage:20,spotAllocationStrategy:"lowest-price",instanceTypes:[{size:"small",weight:1},{size:"medium",weight:2}]},balanced:{baseCapacity:1,onDemandPercentage:50,spotAllocationStrategy:"capacity-optimized",instanceTypes:[{size:"medium",weight:1},{size:"large",weight:2}]},highAvailability:{baseCapacity:2,onDemandPercentage:80,spotAllocationStrategy:"capacity-optimized-prioritized",instanceTypes:[{size:"medium",weight:1}]}}};static AutoScalingConfig={create:(n)=>{let{min:i,max:s,desired:o=i,scaleUpThreshold:c=70,scaleDownThreshold:u=30,cooldownSeconds:d=300,targetMetric:g="cpu"}=n,y={cpu:"ASGAverageCPUUtilization",memory:"ASGAverageMemoryUtilization",requests:"ALBRequestCountPerTarget"};return{minSize:i,maxSize:s,desiredCapacity:o,scalingPolicies:[{policyType:"TargetTrackingScaling",targetValue:c,predefinedMetricType:y[g]||y.cpu,scaleInCooldown:d,scaleOutCooldown:d}]}},forEcs:(n)=>{let{min:i,max:s,cpuTarget:o=70,memoryTarget:c}=n,u=[{predefinedMetricType:"ECSServiceAverageCPUUtilization",targetValue:o}];if(c)u.push({predefinedMetricType:"ECSServiceAverageMemoryUtilization",targetValue:c});return{minCapacity:i,maxCapacity:s,targetTrackingPolicies:u}},presets:{small:{min:1,max:3,scaleUpThreshold:70,scaleDownThreshold:30},medium:{min:2,max:10,scaleUpThreshold:70,scaleDownThreshold:30},large:{min:3,max:50,scaleUpThreshold:60,scaleDownThreshold:40},highAvailability:{min:2,max:20,scaleUpThreshold:60,scaleDownThreshold:30}}};static LoadBalancerConfig={healthCheck:(n)=>{let{path:i="/",interval:s=30,timeout:o=5,healthyThreshold:c=2,unhealthyThreshold:u=5,protocol:d="HTTP"}=n,g={HealthCheckIntervalSeconds:s,HealthCheckTimeoutSeconds:o,HealthyThresholdCount:c,UnhealthyThresholdCount:u};if(d!=="TCP")g.HealthCheckPath=i,g.HealthCheckProtocol=d;return g},presets:{standard:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:5},fast:{path:"/health",interval:10,timeout:3,healthyThreshold:2,unhealthyThreshold:2},relaxed:{path:"/health",interval:60,timeout:30,healthyThreshold:2,unhealthyThreshold:10}}};static SslConfig={httpsListener:(n)=>{let{certificateArn:i,targetGroupArn:s,port:o=443,sslPolicy:c="ELBSecurityPolicy-TLS13-1-2-2021-06"}=n;return{Port:o,Protocol:"HTTPS",Certificates:[{CertificateArn:i}],SslPolicy:c,DefaultActions:[{Type:"forward",TargetGroupArn:s}]}},httpRedirectListener:(n=80)=>({Port:n,Protocol:"HTTP",DefaultActions:[{Type:"redirect",RedirectConfig:{Protocol:"HTTPS",Port:"443",StatusCode:"HTTP_301"}}]}),policies:{tls13:"ELBSecurityPolicy-TLS13-1-2-2021-06",tls12:"ELBSecurityPolicy-TLS-1-2-Ext-2018-06",tls11:"ELBSecurityPolicy-TLS-1-1-2017-01",fips:"ELBSecurityPolicy-TLS-1-2-Ext-FIPS-2022-05"}};static FunctionConfig={create:(n)=>{let{handler:i,runtime:s="nodejs20.x",timeout:o=30,memorySize:c=256,environmentVariables:u,reservedConcurrency:d}=n,g={Handler:i,Runtime:s,Timeout:o,MemorySize:c};if(u)g.Environment={Variables:u};if(d)g.ReservedConcurrentExecutions=d;return g},runtimes:{nodejs20:"nodejs20.x",nodejs18:"nodejs18.x",python312:"python3.12",python311:"python3.11",java21:"java21",java17:"java17",go:"provided.al2023",rust:"provided.al2023",bun:"provided.al2023"},presets:{api:{runtime:"nodejs20.x",timeout:30,memorySize:256},worker:{runtime:"nodejs20.x",timeout:300,memorySize:512},cron:{runtime:"nodejs20.x",timeout:900,memorySize:1024},dataProcessing:{runtime:"nodejs20.x",timeout:900,memorySize:3008}}};static UserData={generateAppServerScript:(n)=>{let{runtime:i="bun",runtimeVersion:s="latest",webServer:o="nginx",processManager:c="systemd",enableSsl:u=!0,sslEmail:d="admin@example.com",domain:g,appPort:y=3000,installDatabaseClients:h=!1,installRedis:A=!1,extraPackages:C=[]}=n,v=`#!/bin/bash
315
315
  set -e
316
316
 
317
317
  # Update system
@@ -569,7 +569,7 @@ ufw default allow outgoing
569
569
  ${n.map((i)=>`ufw allow ${i}`).join(`
570
570
  `)}
571
571
  ufw --force enable
572
- `},Presets:{bunWithNginx:(n,i=3000)=>a.UserData.generateAppServerScript({runtime:"bun",webServer:"nginx",processManager:"systemd",domain:n,appPort:i,enableSsl:!0}),bunWithCaddy:(n,i=3000)=>a.UserData.generateAppServerScript({runtime:"bun",webServer:"caddy",processManager:"systemd",domain:n,appPort:i,enableSsl:!1}),nodeWithPm2:(n,i=3000)=>a.UserData.generateAppServerScript({runtime:"node",webServer:"nginx",processManager:"pm2",domain:n,appPort:i,enableSsl:!0}),worker:(n="bun")=>a.UserData.generateAppServerScript({runtime:n,webServer:"none",processManager:"systemd",enableSsl:!1})}};static createElasticIp(n){let{slug:i,environment:s,domain:o,instanceLogicalId:c}=n,u=r({slug:i,environment:s,resourceType:"eip"}),d=t(u),g={Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:s},...o?[{Key:"Domain",Value:o}]:[]]}},y={[d]:g},h,A;if(c)A=t(`${u}-assoc`),h={Type:"AWS::EC2::EIPAssociation",Properties:{AllocationId:x.GetAtt(d,"AllocationId"),InstanceId:x.Ref(c)}},y[A]=h;return{eip:g,eipAssociation:h,eipLogicalId:d,associationLogicalId:A,resources:y}}static createServerModeStack(n){let{slug:i,environment:s,vpcId:o,subnetId:c,instanceType:u="t3.small",imageId:d="ami-0f3caa1cf4417e51b",keyName:g,domain:y,userData:h,allowedPorts:A=[22,80,443],volumeSize:C=20,volumeType:v="gp3"}=n,T={},R=r({slug:i,environment:s,resourceType:"server-sg"}),P=t(R),I={Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:R,GroupDescription:`Security group for ${i} server`,VpcId:o,SecurityGroupIngress:A.map((ae)=>({IpProtocol:"tcp",FromPort:ae,ToPort:ae,CidrIp:"0.0.0.0/0",Description:`Port ${ae}`})),SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound"}],Tags:[{Key:"Name",Value:R},{Key:"Environment",Value:s}]}};T[P]=I;let M=r({slug:i,environment:s,resourceType:"server-role"}),L=t(M),N={Type:"AWS::IAM::Role",Properties:{RoleName:M,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ec2.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore","arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"],Policies:[{PolicyName:"StacksServerPermissions",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail","ses:SendBulkEmail","ses:VerifyDomainIdentity","ses:VerifyDomainDkim","ses:GetIdentityDkimAttributes","ses:GetIdentityVerificationAttributes"],Resource:"*"},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:ListBucket"],Resource:"*"},{Effect:"Allow",Action:["route53:ChangeResourceRecordSets","route53:ListResourceRecordSets","route53:GetHostedZone"],Resource:"*"},{Effect:"Allow",Action:["ssm:GetParameter","ssm:GetParameters"],Resource:"*"}]}}]}};T[L]=N;let O=r({slug:i,environment:s,resourceType:"server-profile"}),B=t(O),F={Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:O,Roles:[x.Ref(L)]}};T[B]=F;let U=r({slug:i,environment:s,resourceType:"server"}),j=t(U),H={Type:"AWS::EC2::Instance",DependsOn:[B],Properties:{ImageId:d,InstanceType:u,KeyName:g,SubnetId:c,SecurityGroupIds:[x.Ref(P)],IamInstanceProfile:x.Ref(B),BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:C,VolumeType:v,Encrypted:!0,DeleteOnTermination:!0}}],Tags:[{Key:"Name",Value:U},{Key:"Environment",Value:s},...y?[{Key:"Domain",Value:y}]:[]]}};if(h)H.Properties.UserData=x.Base64(h);T[j]=H;let{eip:z,eipAssociation:se,eipLogicalId:ve,associationLogicalId:oe,resources:pe}=a.createElasticIp({slug:i,environment:s,domain:y,instanceLogicalId:j});return Object.assign(T,pe),{instance:H,securityGroup:I,eip:z,eipAssociation:se,instanceRole:N,instanceProfile:F,resources:T,outputs:{instanceLogicalId:j,securityGroupLogicalId:P,eipLogicalId:ve,associationLogicalId:oe,roleLogicalId:L,profileLogicalId:B}}}static ServerMode={webServer:(n)=>{let i=a.UserData.generateAppServerScript({runtime:n.runtime||"bun",webServer:n.webServer||"nginx",domain:n.domain,enableSsl:!0});return a.createServerModeStack({...n,userData:i,instanceType:"t3.small",allowedPorts:[22,80,443]})},workerServer:(n)=>{let i=a.UserData.generateAppServerScript({runtime:n.runtime||"bun",webServer:"none",installRedis:n.installRedis});return a.createServerModeStack({...n,userData:i,instanceType:"t3.medium",allowedPorts:[22]})},cacheServer:(n)=>a.createServerModeStack({...n,userData:`#!/bin/bash
572
+ `},Presets:{bunWithNginx:(n,i=3000)=>a.UserData.generateAppServerScript({runtime:"bun",webServer:"nginx",processManager:"systemd",domain:n,appPort:i,enableSsl:!0}),bunWithCaddy:(n,i=3000)=>a.UserData.generateAppServerScript({runtime:"bun",webServer:"caddy",processManager:"systemd",domain:n,appPort:i,enableSsl:!1}),nodeWithPm2:(n,i=3000)=>a.UserData.generateAppServerScript({runtime:"node",webServer:"nginx",processManager:"pm2",domain:n,appPort:i,enableSsl:!0}),worker:(n="bun")=>a.UserData.generateAppServerScript({runtime:n,webServer:"none",processManager:"systemd",enableSsl:!1})}};static createElasticIp(n){let{slug:i,environment:s,domain:o,instanceLogicalId:c}=n,u=r({slug:i,environment:s,resourceType:"eip"}),d=t(u),g={Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:s},...o?[{Key:"Domain",Value:o}]:[]]}},y={[d]:g},h,A;if(c)A=t(`${u}-assoc`),h={Type:"AWS::EC2::EIPAssociation",Properties:{AllocationId:M.GetAtt(d,"AllocationId"),InstanceId:M.Ref(c)}},y[A]=h;return{eip:g,eipAssociation:h,eipLogicalId:d,associationLogicalId:A,resources:y}}static createServerModeStack(n){let{slug:i,environment:s,vpcId:o,subnetId:c,instanceType:u="t3.small",imageId:d="ami-0f3caa1cf4417e51b",keyName:g,domain:y,userData:h,allowedPorts:A=[22,80,443],volumeSize:C=20,volumeType:v="gp3"}=n,T={},R=r({slug:i,environment:s,resourceType:"server-sg"}),P=t(R),I={Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:R,GroupDescription:`Security group for ${i} server`,VpcId:o,SecurityGroupIngress:A.map((oe)=>({IpProtocol:"tcp",FromPort:oe,ToPort:oe,CidrIp:"0.0.0.0/0",Description:`Port ${oe}`})),SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound"}],Tags:[{Key:"Name",Value:R},{Key:"Environment",Value:s}]}};T[P]=I;let O=r({slug:i,environment:s,resourceType:"server-role"}),B=t(O),x={Type:"AWS::IAM::Role",Properties:{RoleName:O,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ec2.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore","arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"],Policies:[{PolicyName:"StacksServerPermissions",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail","ses:SendBulkEmail","ses:VerifyDomainIdentity","ses:VerifyDomainDkim","ses:GetIdentityDkimAttributes","ses:GetIdentityVerificationAttributes"],Resource:"*"},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:ListBucket"],Resource:"*"},{Effect:"Allow",Action:["route53:ChangeResourceRecordSets","route53:ListResourceRecordSets","route53:GetHostedZone"],Resource:"*"},{Effect:"Allow",Action:["ssm:GetParameter","ssm:GetParameters"],Resource:"*"}]}}]}};T[B]=x;let F=r({slug:i,environment:s,resourceType:"server-profile"}),G=t(F),_={Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:F,Roles:[M.Ref(B)]}};T[G]=_;let U=r({slug:i,environment:s,resourceType:"server"}),z=t(U),K={Type:"AWS::EC2::Instance",DependsOn:[G],Properties:{ImageId:d,InstanceType:u,KeyName:g,SubnetId:c,SecurityGroupIds:[M.Ref(P)],IamInstanceProfile:M.Ref(G),BlockDeviceMappings:[{DeviceName:"/dev/xvda",Ebs:{VolumeSize:C,VolumeType:v,Encrypted:!0,DeleteOnTermination:!0}}],Tags:[{Key:"Name",Value:U},{Key:"Environment",Value:s},...y?[{Key:"Domain",Value:y}]:[]]}};if(h)K.Properties.UserData=M.Base64(h);T[z]=K;let{eip:Q,eipAssociation:ae,eipLogicalId:Pe,associationLogicalId:ce,resources:ye}=a.createElasticIp({slug:i,environment:s,domain:y,instanceLogicalId:z});return Object.assign(T,ye),{instance:K,securityGroup:I,eip:Q,eipAssociation:ae,instanceRole:x,instanceProfile:_,resources:T,outputs:{instanceLogicalId:z,securityGroupLogicalId:P,eipLogicalId:Pe,associationLogicalId:ce,roleLogicalId:B,profileLogicalId:G}}}static ServerMode={webServer:(n)=>{let i=a.UserData.generateAppServerScript({runtime:n.runtime||"bun",webServer:n.webServer||"nginx",domain:n.domain,enableSsl:!0});return a.createServerModeStack({...n,userData:i,instanceType:"t3.small",allowedPorts:[22,80,443]})},workerServer:(n)=>{let i=a.UserData.generateAppServerScript({runtime:n.runtime||"bun",webServer:"none",installRedis:n.installRedis});return a.createServerModeStack({...n,userData:i,instanceType:"t3.medium",allowedPorts:[22]})},cacheServer:(n)=>a.createServerModeStack({...n,userData:`#!/bin/bash
573
573
  set -e
574
574
  apt-get update && apt-get upgrade -y
575
575
  apt-get install -y redis-server
@@ -577,7 +577,7 @@ sed -i 's/bind 127.0.0.1/bind 0.0.0.0/' /etc/redis/redis.conf
577
577
  systemctl enable redis-server
578
578
  systemctl restart redis-server
579
579
  echo "Redis server setup complete!"
580
- `,instanceType:"t3.medium",allowedPorts:[22,6379]})}}class S{static createVpc(n){let{slug:i,environment:s,cidr:o="10.0.0.0/16",enableDnsHostnames:c=!0,enableDnsSupport:u=!0}=n,d=r({slug:i,environment:s,resourceType:"vpc"}),g=t(d);return{vpc:{Type:"AWS::EC2::VPC",Properties:{CidrBlock:o,EnableDnsHostnames:c,EnableDnsSupport:u,Tags:[{Key:"Name",Value:d},{Key:"Environment",Value:s}]}},logicalId:g}}static createSubnet(n){let{slug:i,environment:s,vpcId:o,type:c,cidr:u,availabilityZone:d,mapPublicIp:g=c==="public"}=n,y=r({slug:i,environment:s,resourceType:`subnet-${c}`}),h=t(`${y}-${d}`);return{subnet:{Type:"AWS::EC2::Subnet",Properties:{VpcId:o,CidrBlock:u,AvailabilityZone:d,MapPublicIpOnLaunch:g,Tags:[{Key:"Name",Value:`${y}-${d}`},{Key:"Environment",Value:s},{Key:"Type",Value:c}]}},logicalId:h}}static createInternetGateway(n,i){let s=r({slug:n,environment:i,resourceType:"igw"}),o=t(s);return{internetGateway:{Type:"AWS::EC2::InternetGateway",Properties:{Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:i}]}},logicalId:o}}static attachInternetGateway(n,i){let s=t(`${n}-igw-attachment`);return{attachment:{Type:"AWS::EC2::VPCGatewayAttachment",Properties:{VpcId:x.Ref(n),InternetGatewayId:x.Ref(i)}},logicalId:s}}static createEip(n,i){let s=r({slug:n,environment:i,resourceType:"eip"}),o=t(s);return{eip:{Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:i}]}},logicalId:o}}static createNatGateway(n,i){let{slug:s,environment:o,subnetId:c}=n,u=r({slug:s,environment:o,resourceType:"nat"}),d=t(u);return{natGateway:{Type:"AWS::EC2::NatGateway",Properties:{AllocationId:x.GetAtt(i,"AllocationId"),SubnetId:c,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:o},{Key:"Warning",Value:"NAT Gateway incurs hourly charges"}]}},logicalId:d}}static createRouteTable(n,i,s,o){let c=r({slug:n,environment:i,resourceType:`rt-${o}`}),u=t(c);return{routeTable:{Type:"AWS::EC2::RouteTable",Properties:{VpcId:x.Ref(s),Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:i},{Key:"Type",Value:o}]}},logicalId:u}}static createRoute(n,i,s){let o=t(`${n}-route-${s.type}`),c={Type:"AWS::EC2::Route",Properties:{RouteTableId:x.Ref(n),DestinationCidrBlock:i}};if(s.type==="igw")c.Properties.GatewayId=x.Ref(s.logicalId);else if(s.type==="nat")c.Properties.NatGatewayId=x.Ref(s.logicalId);else if(s.type==="instance")c.Properties.InstanceId=x.Ref(s.logicalId);return{route:c,logicalId:o}}static associateSubnetWithRouteTable(n,i){let s=t(`${n}-rt-assoc`);return{association:{Type:"AWS::EC2::SubnetRouteTableAssociation",Properties:{SubnetId:x.Ref(n),RouteTableId:x.Ref(i)}},logicalId:s}}static enableFlowLogs(n){let{slug:i,environment:s,resourceId:o,resourceType:c,trafficType:u="ALL",logGroupName:d}=n,g=r({slug:i,environment:s,resourceType:"flowlog"}),y=t(g);return{flowLog:{Type:"AWS::EC2::FlowLog",Properties:{ResourceType:c,ResourceIds:[o],TrafficType:u,LogDestinationType:"cloud-watch-logs",LogGroupName:d||`/aws/vpc/${i}-${s}`,Tags:[{Key:"Name",Value:g},{Key:"Environment",Value:s}]}},logicalId:y}}static calculateSubnetCidrs(n,i,s=3){let[o,c]=n.split("/"),u=Number.parseInt(c,10),d=Math.ceil(Math.log2(i*s)),g=u+d;if(g>28)throw Error("VPC CIDR is too small to accommodate requested subnets");let[y,h,A,C]=o.split(".").map(Number),v=(y<<24)+(h<<16)+(A<<8)+C,T=2**(32-g),R=[];for(let P=0;P<i*s;P++){let I=v+P*T,M=[I>>>24&255,I>>>16&255,I>>>8&255,I&255].join(".");R.push(`${M}/${g}`)}return R}static getAvailabilityZones(n,i){return["a","b","c","d","e","f"].slice(0,i).map((o)=>`${n}${o}`)}static createMultiAzNetwork(n){let{slug:i,environment:s,region:o,cidr:c="10.0.0.0/16",zones:u=3,enableNatGateway:d=!1,singleNatGateway:g=!1,enableFlowLogs:y=!1}=n,h={},A=[],C=[],v=[],{vpc:T,logicalId:R}=S.createVpc({slug:i,environment:s,cidr:c});h[R]=T;let{internetGateway:P,logicalId:I}=S.createInternetGateway(i,s);h[I]=P;let{attachment:M,logicalId:L}=S.attachInternetGateway(R,I);h[L]=M;let{routeTable:N,logicalId:O}=S.createRouteTable(i,s,R,"public");h[O]=N;let{route:B,logicalId:F}=S.createRoute(O,"0.0.0.0/0",{type:"igw",logicalId:I});B.DependsOn=L,h[F]=B;let U=S.calculateSubnetCidrs(c,u,2),j=S.getAvailabilityZones(o,u),H=[];for(let z=0;z<u;z++){let se=j[z],ve=U[z*2],oe=U[z*2+1],{subnet:pe,logicalId:ae}=S.createSubnet({slug:i,environment:s,vpcId:x.Ref(R),type:"public",cidr:ve,availabilityZone:se});h[ae]=pe,A.push(ae);let{association:ce,logicalId:Ie}=S.associateSubnetWithRouteTable(ae,O);h[Ie]=ce;let{subnet:Le,logicalId:he}=S.createSubnet({slug:i,environment:s,vpcId:x.Ref(R),type:"private",cidr:oe,availabilityZone:se});if(h[he]=Le,C.push(he),d&&(!g||z===0)){let{eip:ye,logicalId:be}=S.createEip(`${i}-${se}`,s);h[be]=ye;let{natGateway:De,logicalId:Se}=S.createNatGateway({slug:`${i}-${se}`,environment:s,subnetId:x.Ref(ae)},be);De.DependsOn=L,h[Se]=De,v.push(Se);let{routeTable:Te,logicalId:$e}=S.createRouteTable(`${i}-${se}`,s,R,"private");h[$e]=Te,H.push($e);let{route:We,logicalId:G}=S.createRoute($e,"0.0.0.0/0",{type:"nat",logicalId:Se});h[G]=We;let{association:ne,logicalId:ie}=S.associateSubnetWithRouteTable(he,$e);h[ie]=ne}else if(d&&g&&z>0){let{association:ye,logicalId:be}=S.associateSubnetWithRouteTable(he,H[0]);h[be]=ye}else{let{routeTable:ye,logicalId:be}=S.createRouteTable(`${i}-${se}-isolated`,s,R,"private");h[be]=ye;let{association:De,logicalId:Se}=S.associateSubnetWithRouteTable(he,be);h[Se]=De}}if(y){let{flowLog:z,logicalId:se}=S.enableFlowLogs({slug:i,environment:s,resourceId:x.Ref(R),resourceType:"VPC"});h[se]=z}return{resources:h,outputs:{vpcId:R,publicSubnetIds:A,privateSubnetIds:C,natGatewayIds:v.length>0?v:void 0}}}static NatGatewayCostWarning=`
580
+ `,instanceType:"t3.medium",allowedPorts:[22,6379]})}}class S{static createVpc(n){let{slug:i,environment:s,cidr:o="10.0.0.0/16",enableDnsHostnames:c=!0,enableDnsSupport:u=!0}=n,d=r({slug:i,environment:s,resourceType:"vpc"}),g=t(d);return{vpc:{Type:"AWS::EC2::VPC",Properties:{CidrBlock:o,EnableDnsHostnames:c,EnableDnsSupport:u,Tags:[{Key:"Name",Value:d},{Key:"Environment",Value:s}]}},logicalId:g}}static createSubnet(n){let{slug:i,environment:s,vpcId:o,type:c,cidr:u,availabilityZone:d,mapPublicIp:g=c==="public"}=n,y=r({slug:i,environment:s,resourceType:`subnet-${c}`}),h=t(`${y}-${d}`);return{subnet:{Type:"AWS::EC2::Subnet",Properties:{VpcId:o,CidrBlock:u,AvailabilityZone:d,MapPublicIpOnLaunch:g,Tags:[{Key:"Name",Value:`${y}-${d}`},{Key:"Environment",Value:s},{Key:"Type",Value:c}]}},logicalId:h}}static createInternetGateway(n,i){let s=r({slug:n,environment:i,resourceType:"igw"}),o=t(s);return{internetGateway:{Type:"AWS::EC2::InternetGateway",Properties:{Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:i}]}},logicalId:o}}static attachInternetGateway(n,i){let s=t(`${n}-igw-attachment`);return{attachment:{Type:"AWS::EC2::VPCGatewayAttachment",Properties:{VpcId:M.Ref(n),InternetGatewayId:M.Ref(i)}},logicalId:s}}static createEip(n,i){let s=r({slug:n,environment:i,resourceType:"eip"}),o=t(s);return{eip:{Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:s},{Key:"Environment",Value:i}]}},logicalId:o}}static createNatGateway(n,i){let{slug:s,environment:o,subnetId:c}=n,u=r({slug:s,environment:o,resourceType:"nat"}),d=t(u);return{natGateway:{Type:"AWS::EC2::NatGateway",Properties:{AllocationId:M.GetAtt(i,"AllocationId"),SubnetId:c,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:o},{Key:"Warning",Value:"NAT Gateway incurs hourly charges"}]}},logicalId:d}}static createRouteTable(n,i,s,o){let c=r({slug:n,environment:i,resourceType:`rt-${o}`}),u=t(c);return{routeTable:{Type:"AWS::EC2::RouteTable",Properties:{VpcId:M.Ref(s),Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:i},{Key:"Type",Value:o}]}},logicalId:u}}static createRoute(n,i,s){let o=t(`${n}-route-${s.type}`),c={Type:"AWS::EC2::Route",Properties:{RouteTableId:M.Ref(n),DestinationCidrBlock:i}};if(s.type==="igw")c.Properties.GatewayId=M.Ref(s.logicalId);else if(s.type==="nat")c.Properties.NatGatewayId=M.Ref(s.logicalId);else if(s.type==="instance")c.Properties.InstanceId=M.Ref(s.logicalId);return{route:c,logicalId:o}}static associateSubnetWithRouteTable(n,i){let s=t(`${n}-rt-assoc`);return{association:{Type:"AWS::EC2::SubnetRouteTableAssociation",Properties:{SubnetId:M.Ref(n),RouteTableId:M.Ref(i)}},logicalId:s}}static enableFlowLogs(n){let{slug:i,environment:s,resourceId:o,resourceType:c,trafficType:u="ALL",logGroupName:d}=n,g=r({slug:i,environment:s,resourceType:"flowlog"}),y=t(g);return{flowLog:{Type:"AWS::EC2::FlowLog",Properties:{ResourceType:c,ResourceIds:[o],TrafficType:u,LogDestinationType:"cloud-watch-logs",LogGroupName:d||`/aws/vpc/${i}-${s}`,Tags:[{Key:"Name",Value:g},{Key:"Environment",Value:s}]}},logicalId:y}}static calculateSubnetCidrs(n,i,s=3){let[o,c]=n.split("/"),u=Number.parseInt(c,10),d=Math.ceil(Math.log2(i*s)),g=u+d;if(g>28)throw Error("VPC CIDR is too small to accommodate requested subnets");let[y,h,A,C]=o.split(".").map(Number),v=(y<<24)+(h<<16)+(A<<8)+C,T=2**(32-g),R=[];for(let P=0;P<i*s;P++){let I=v+P*T,O=[I>>>24&255,I>>>16&255,I>>>8&255,I&255].join(".");R.push(`${O}/${g}`)}return R}static getAvailabilityZones(n,i){return["a","b","c","d","e","f"].slice(0,i).map((o)=>`${n}${o}`)}static createMultiAzNetwork(n){let{slug:i,environment:s,region:o,cidr:c="10.0.0.0/16",zones:u=3,enableNatGateway:d=!1,singleNatGateway:g=!1,enableFlowLogs:y=!1}=n,h={},A=[],C=[],v=[],{vpc:T,logicalId:R}=S.createVpc({slug:i,environment:s,cidr:c});h[R]=T;let{internetGateway:P,logicalId:I}=S.createInternetGateway(i,s);h[I]=P;let{attachment:O,logicalId:B}=S.attachInternetGateway(R,I);h[B]=O;let{routeTable:x,logicalId:F}=S.createRouteTable(i,s,R,"public");h[F]=x;let{route:G,logicalId:_}=S.createRoute(F,"0.0.0.0/0",{type:"igw",logicalId:I});G.DependsOn=B,h[_]=G;let U=S.calculateSubnetCidrs(c,u,2),z=S.getAvailabilityZones(o,u),K=[];for(let Q=0;Q<u;Q++){let ae=z[Q],Pe=U[Q*2],ce=U[Q*2+1],{subnet:ye,logicalId:oe}=S.createSubnet({slug:i,environment:s,vpcId:M.Ref(R),type:"public",cidr:Pe,availabilityZone:ae});h[oe]=ye,A.push(oe);let{association:de,logicalId:Ne}=S.associateSubnetWithRouteTable(oe,F);h[Ne]=de;let{subnet:Be,logicalId:be}=S.createSubnet({slug:i,environment:s,vpcId:M.Ref(R),type:"private",cidr:ce,availabilityZone:ae});if(h[be]=Be,C.push(be),d&&(!g||Q===0)){let{eip:fe,logicalId:Se}=S.createEip(`${i}-${ae}`,s);h[Se]=fe;let{natGateway:xe,logicalId:Ae}=S.createNatGateway({slug:`${i}-${ae}`,environment:s,subnetId:M.Ref(oe)},Se);xe.DependsOn=B,h[Ae]=xe,v.push(Ae);let{routeTable:Ee,logicalId:Fe}=S.createRouteTable(`${i}-${ae}`,s,R,"private");h[Fe]=Ee,K.push(Fe);let{route:Ue,logicalId:V}=S.createRoute(Fe,"0.0.0.0/0",{type:"nat",logicalId:Ae});h[V]=Ue;let{association:ne,logicalId:se}=S.associateSubnetWithRouteTable(be,Fe);h[se]=ne}else if(d&&g&&Q>0){let{association:fe,logicalId:Se}=S.associateSubnetWithRouteTable(be,K[0]);h[Se]=fe}else{let{routeTable:fe,logicalId:Se}=S.createRouteTable(`${i}-${ae}-isolated`,s,R,"private");h[Se]=fe;let{association:xe,logicalId:Ae}=S.associateSubnetWithRouteTable(be,Se);h[Ae]=xe}}if(y){let{flowLog:Q,logicalId:ae}=S.enableFlowLogs({slug:i,environment:s,resourceId:M.Ref(R),resourceType:"VPC"});h[ae]=Q}return{resources:h,outputs:{vpcId:R,publicSubnetIds:A,privateSubnetIds:C,natGatewayIds:v.length>0?v:void 0}}}static NatGatewayCostWarning=`
581
581
  ⚠️ NAT Gateway Cost Warning:
582
582
  - Each NAT Gateway costs approximately $32-45/month (hourly charges)
583
583
  - Data processing charges: $0.045/GB processed
@@ -585,7 +585,7 @@ echo "Redis server setup complete!"
585
585
  - Using a single NAT Gateway (singleNatGateway: true)
586
586
  - Using NAT Instances instead (cheaper but requires management)
587
587
  - Disabling NAT entirely for isolated private subnets
588
- `}class tt{static createFileSystem(n){let{slug:i,environment:s,encrypted:o=!0,kmsKeyId:c,performanceMode:u="generalPurpose",throughputMode:d="bursting",provisionedThroughput:g,enableBackup:y=!0}=n,h=r({slug:i,environment:s,resourceType:"efs"}),A=t(h),C={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:o,PerformanceMode:u,ThroughputMode:d,FileSystemTags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(c)C.Properties.KmsKeyId=c;if(d==="provisioned"&&g)C.Properties.ProvisionedThroughputInMibps=g;if(y)C.Properties.BackupPolicy={Status:"ENABLED"};return{fileSystem:C,logicalId:A}}static createMountTarget(n,i){let{slug:s,environment:o,subnetId:c,securityGroups:u,ipAddress:d}=i,g=r({slug:s,environment:o,resourceType:"efs-mt"}),y=t(`${g}-${c}`),h={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:x.Ref(n),SubnetId:c,SecurityGroups:u}};if(d)h.Properties.IpAddress=d;return{mountTarget:h,logicalId:y}}static createAccessPoint(n,i){let{slug:s,environment:o,path:c="/",uid:u="1000",gid:d="1000",permissions:g="755"}=i,y=r({slug:s,environment:o,resourceType:"efs-ap"}),h=t(`${y}-${c.replace(/\//g,"-")}`);return{accessPoint:{Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:x.Ref(n),PosixUser:{Uid:u,Gid:d},RootDirectory:{Path:c,CreationInfo:{OwnerUid:u,OwnerGid:d,Permissions:g}},AccessPointTags:[{Key:"Name",Value:`${y}-${c}`},{Key:"Environment",Value:o}]}},logicalId:h}}static setLifecyclePolicy(n,i){let{transitionToIA:s,transitionToPrimary:o=!1}=i;if(!n.Properties)n.Properties={};if(n.Properties.LifecyclePolicies=[],s){let c=`AFTER_${s}_DAYS`;n.Properties.LifecyclePolicies.push({TransitionToIA:c})}if(o)n.Properties.LifecyclePolicies.push({TransitionToPrimaryStorageClass:"AFTER_1_ACCESS"});return n}static enableBackup(n){if(!n.Properties)n.Properties={};return n.Properties.BackupPolicy={Status:"ENABLED"},n}static disableBackup(n){if(!n.Properties)n.Properties={};return n.Properties.BackupPolicy={Status:"DISABLED"},n}static setProvisionedThroughput(n,i){if(!n.Properties)n.Properties={};return n.Properties.ThroughputMode="provisioned",n.Properties.ProvisionedThroughputInMibps=i,n}static setElasticThroughput(n){if(!n.Properties)n.Properties={};return n.Properties.ThroughputMode="elastic",n}static enableMaxIO(n){if(!n.Properties)n.Properties={};return n.Properties.PerformanceMode="maxIO",n}static createEfsSecurityGroup(n){let{slug:i,environment:s,vpcId:o,sourceSecurityGroupIds:c=[],sourceCidrBlocks:u=[],description:d}=n,g=r({slug:i,environment:s,resourceType:"efs-sg"}),y=t(g),h=[];for(let C of c)h.push({IpProtocol:"tcp",FromPort:2049,ToPort:2049,SourceSecurityGroupId:C,Description:"NFS from security group"});for(let C of u)h.push({IpProtocol:"tcp",FromPort:2049,ToPort:2049,CidrIp:C,Description:"NFS from CIDR block"});return{securityGroup:{Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:g,GroupDescription:d||`Security group for EFS mount targets - ${i} ${s}`,VpcId:o,SecurityGroupIngress:h,Tags:[{Key:"Name",Value:g},{Key:"Environment",Value:s}]}},logicalId:y}}static createMultiAzMountTargets(n,i){let{slug:s,environment:o,subnetIds:c,securityGroupId:u}=i,d=[],g=[];for(let y=0;y<c.length;y++){let h=c[y],A=r({slug:s,environment:o,resourceType:"efs-mt"}),C=t(`${A}-az${y+1}`),v={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:x.Ref(n),SubnetId:h,SecurityGroups:[u]}};d.push(v),g.push(C)}return{mountTargets:d,logicalIds:g}}static createCompleteFileSystem(n){let{slug:i,environment:s,vpcId:o,subnetIds:c,sourceSecurityGroupIds:u=[],encrypted:d=!0,performanceMode:g="generalPurpose",throughputMode:y="elastic",enableBackup:h=!0,transitionToIA:A}=n,C={},{fileSystem:v,logicalId:T}=tt.createFileSystem({slug:i,environment:s,encrypted:d,performanceMode:g,throughputMode:y,enableBackup:h});if(A)tt.setLifecyclePolicy(v,{transitionToIA:A,transitionToPrimary:!0});C[T]=v;let{securityGroup:R,logicalId:P}=tt.createEfsSecurityGroup({slug:i,environment:s,vpcId:o,sourceSecurityGroupIds:u});C[P]=R;let{mountTargets:I,logicalIds:M}=tt.createMultiAzMountTargets(T,{slug:i,environment:s,subnetIds:c,securityGroupId:x.Ref(P)});for(let L=0;L<I.length;L++)C[M[L]]=I[L];return{resources:C,outputs:{fileSystemId:T,securityGroupId:P,mountTargetIds:M}}}}class f{static verifyDomain(n){let{domain:i,slug:s,environment:o,enableDkim:c=!0,dkimKeyLength:u="RSA_2048_BIT"}=n,d=r({slug:s,environment:o,resourceType:"ses-identity"}),g=t(`${d}-${i.replace(/\./g,"")}`),y={Type:"AWS::SES::EmailIdentity",Properties:{EmailIdentity:i,FeedbackAttributes:{EmailForwardingEnabled:!0}}};if(c)y.Properties.DkimSigningAttributes={NextSigningKeyLength:u};return{emailIdentity:y,logicalId:g}}static createDkimRecords(n,i,s){let o=[];for(let c=0;c<i.length;c++){let u=i[c],d=t(`dkim-${n.replace(/\./g,"")}-${c+1}`),g={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:s,Name:`${u}._domainkey.${n}`,Type:"CNAME",TTL:1800,ResourceRecords:[`${u}.dkim.amazonses.com`]}};o.push({record:g,logicalId:d})}return o}static createConfigurationSet(n){let{slug:i,environment:s,name:o,reputationMetrics:c=!0,sendingEnabled:u=!0,suppressBounces:d=!0,suppressComplaints:g=!0}=n,y=o||r({slug:i,environment:s,resourceType:"ses-config"}),h=t(y),A=[];if(d)A.push("BOUNCE");if(g)A.push("COMPLAINT");return{configurationSet:{Type:"AWS::SES::ConfigurationSet",Properties:{Name:y,ReputationOptions:{ReputationMetricsEnabled:c},SendingOptions:{SendingEnabled:u},SuppressionOptions:{SuppressedReasons:A}}},logicalId:h}}static createReceiptRuleSet(n){let{slug:i,environment:s,name:o}=n,c=o||r({slug:i,environment:s,resourceType:"ses-ruleset"}),u=t(c);return{ruleSet:{Type:"AWS::SES::ReceiptRuleSet",Properties:{RuleSetName:c}},logicalId:u}}static createReceiptRule(n,i){let{slug:s,environment:o,ruleSetName:c,recipients:u,enabled:d=!0,scanEnabled:g=!0,tlsPolicy:y="Require",s3Action:h,lambdaAction:A,snsAction:C}=i,v=r({slug:s,environment:o,resourceType:"ses-rule"}),T=t(v),R=[];if(h)R.push({S3Action:{BucketName:h.bucketName,ObjectKeyPrefix:h.prefix,KmsKeyArn:h.kmsKeyArn}});if(A)R.push({LambdaAction:{FunctionArn:A.functionArn,InvocationType:A.invocationType||"Event"}});if(C)R.push({SNSAction:{TopicArn:C.topicArn,Encoding:C.encoding||"UTF-8"}});return{receiptRule:{Type:"AWS::SES::ReceiptRule",Properties:{RuleSetName:c,Rule:{Name:v,Enabled:d,ScanEnabled:g,TlsPolicy:y,Recipients:u,Actions:R.length>0?R:void 0}}},logicalId:T}}static createMxRecord(n,i,s){let o=t(`mx-${n.replace(/\./g,"")}`);return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:n,Type:"MX",TTL:300,ResourceRecords:[`10 inbound-smtp.${s}.amazonaws.com`]}},logicalId:o}}static createVerificationRecord(n,i,s){let o=t(`verification-${n.replace(/\./g,"")}`);return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:s,Name:`_amazonses.${n}`,Type:"TXT",TTL:1800,ResourceRecords:[`"${i}"`]}},logicalId:o}}static getSmtpEndpoint(n){return`email-smtp.${n}.amazonaws.com`}static SmtpPorts={TLS:587,SSL:465,Unencrypted:25};static createSpfRecord(n,i,s){let{includeDomains:o=[],softFail:c=!1}=s||{},u=t(`spf-${n.replace(/\./g,"")}`),d="v=spf1 include:amazonses.com";for(let y of o)d+=` include:${y}`;return d+=c?" ~all":" -all",{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:n,Type:"TXT",TTL:300,ResourceRecords:[`"${d}"`]}},logicalId:u}}static createDmarcRecord(n,i,s){let{policy:o="none",subdomainPolicy:c,percentage:u=100,reportingEmail:d,forensicEmail:g}=s||{},y=t(`dmarc-${n.replace(/\./g,"")}`),h=`v=DMARC1; p=${o}; pct=${u}`;if(c)h+=`; sp=${c}`;if(d)h+=`; rua=mailto:${d}`;if(g)h+=`; ruf=mailto:${g}`;return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:`_dmarc.${n}`,Type:"TXT",TTL:300,ResourceRecords:[`"${h}"`]}},logicalId:y}}static createInboundEmailSetup(n){let{slug:i,environment:s,domain:o,s3BucketName:c,s3KeyPrefix:u="inbound/",region:d,hostedZoneId:g,lambdaFunctionArn:y,snsTopicArn:h}=n,A={},{ruleSet:C,logicalId:v}=f.createReceiptRuleSet({slug:i,environment:s});A[v]=C;let{receiptRule:T,logicalId:R}=f.createReceiptRule(v,{slug:i,environment:s,ruleSetName:C.Properties.RuleSetName||`${i}-${s}-receipt-rule-set`,recipients:[o],s3Action:{bucketName:c,prefix:u},lambdaAction:y?{functionArn:y,invocationType:"Event"}:void 0,snsAction:h?{topicArn:h}:void 0});A[R]=T;let{record:P,logicalId:I}=f.createMxRecord(o,g,d);return A[I]=P,{resources:A,outputs:{ruleSetLogicalId:v,ruleLogicalId:R,mxRecordLogicalId:I}}}static createCompleteDomainSetup(n){let{slug:i,environment:s,domain:o,hostedZoneId:c,region:u,enableInbound:d=!1,inboundS3Bucket:g,dmarcReportingEmail:y}=n,h={},{emailIdentity:A,logicalId:C}=f.verifyDomain({domain:o,slug:i,environment:s});h[C]=A;let{configurationSet:v,logicalId:T}=f.createConfigurationSet({slug:i,environment:s});h[T]=v;let{record:R,logicalId:P}=f.createSpfRecord(o,c);h[P]=R;let{record:I,logicalId:M}=f.createDmarcRecord(o,c,{policy:"none",reportingEmail:y||`dmarc-reports@${o}`});if(h[M]=I,d&&g){let L=f.createInboundEmailSetup({slug:i,environment:s,domain:o,s3BucketName:g,region:u,hostedZoneId:c});Object.assign(h,L.resources)}return{resources:h,outputs:{identityLogicalId:C,configSetLogicalId:T}}}static InboundSmtpEndpoints={"us-east-1":"inbound-smtp.us-east-1.amazonaws.com","us-west-2":"inbound-smtp.us-west-2.amazonaws.com","eu-west-1":"inbound-smtp.eu-west-1.amazonaws.com"};static supportsInboundEmail(n){return n in f.InboundSmtpEndpoints}static createEmailLambdaRole(n){let{slug:i,environment:s,s3BucketArn:o,sesIdentityArn:c}=n,u=r({slug:i,environment:s,resourceType:"email-lambda-role"}),d=t(u),g=t(`${u}-policy`),y={Type:"AWS::IAM::Role",Properties:{RoleName:u,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"],Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:s}]}},h=[{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[o,`${o}/*`]}];if(c)h.push({Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail"],Resource:c});let A={Type:"AWS::IAM::Policy",Properties:{PolicyName:`${u}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:h},Roles:[x.Ref(d)]}};return{role:y,policy:A,roleLogicalId:d,policyLogicalId:g}}static createOutboundEmailLambda(n){let{slug:i,environment:s,roleArn:o,domain:c,configurationSetName:u,timeout:d=30,memorySize:g=256}=n,y=r({slug:i,environment:s,resourceType:"outbound-email"}),h=t(y);return{function:{Type:"AWS::Lambda::Function",Properties:{FunctionName:y,Runtime:"nodejs20.x",Handler:"index.handler",Role:o,Timeout:d,MemorySize:g,Environment:{Variables:{DOMAIN:c,CONFIGURATION_SET:u||""}},Code:{ZipFile:f.LambdaCode.outboundEmail},Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:s},{Key:"Purpose",Value:"OutboundEmail"}]}},logicalId:h}}static createInboundEmailLambda(n){let{slug:i,environment:s,roleArn:o,s3BucketName:c,organizedPrefix:u="organized/",timeout:d=60,memorySize:g=512}=n,y=r({slug:i,environment:s,resourceType:"inbound-email"}),h=t(y),A=t(`${y}-permission`),C={Type:"AWS::Lambda::Function",Properties:{FunctionName:y,Runtime:"nodejs20.x",Handler:"index.handler",Role:o,Timeout:d,MemorySize:g,Environment:{Variables:{S3_BUCKET:c,ORGANIZED_PREFIX:u}},Code:{ZipFile:f.LambdaCode.inboundEmail},Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:s},{Key:"Purpose",Value:"InboundEmail"}]}},v={Type:"AWS::Lambda::Permission",Properties:{FunctionName:x.Ref(h),Action:"lambda:InvokeFunction",Principal:"ses.amazonaws.com",SourceAccount:x.Ref("AWS::AccountId")}};return{function:C,permission:v,logicalId:h,permissionLogicalId:A}}static createEmailConversionLambda(n){let{slug:i,environment:s,roleArn:o,s3BucketName:c,convertedPrefix:u="converted/",timeout:d=60,memorySize:g=512}=n,y=r({slug:i,environment:s,resourceType:"email-conversion"}),h=t(y);return{function:{Type:"AWS::Lambda::Function",Properties:{FunctionName:y,Runtime:"nodejs20.x",Handler:"index.handler",Role:o,Timeout:d,MemorySize:g,Environment:{Variables:{S3_BUCKET:c,CONVERTED_PREFIX:u}},Code:{ZipFile:f.LambdaCode.emailConversion},Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:s},{Key:"Purpose",Value:"EmailConversion"}]}},logicalId:h}}static createEmailBucketNotification(n){let{lambdaArn:i,prefix:s="inbound/",suffix:o,events:c}=n,u=c??["s3:ObjectCreated:*"],d={};if(s||o){if(d.S3Key={Rules:[]},s)d.S3Key.Rules.push({Name:"prefix",Value:s});if(o)d.S3Key.Rules.push({Name:"suffix",Value:o})}return{notificationConfiguration:{LambdaConfigurations:[{Event:u[0],Function:i,Filter:Object.keys(d).length>0?d:void 0}]}}}static createS3LambdaPermission(n){let{slug:i,environment:s,lambdaLogicalId:o,s3BucketArn:c}=n,u=r({slug:i,environment:s,resourceType:"s3-lambda-permission"}),d=t(u);return{permission:{Type:"AWS::Lambda::Permission",Properties:{FunctionName:x.Ref(o),Action:"lambda:InvokeFunction",Principal:"s3.amazonaws.com",SourceArn:c}},logicalId:d}}static createEmailProcessingStack(n){let{slug:i,environment:s,domain:o,s3BucketName:c,s3BucketArn:u,configurationSetName:d,enableInbound:g=!0,enableConversion:y=!0}=n,h={},{role:A,policy:C,roleLogicalId:v,policyLogicalId:T}=f.createEmailLambdaRole({slug:i,environment:s,s3BucketArn:u,sesIdentityArn:`arn:aws:ses:*:*:identity/${o}`});h[v]=A,h[T]=C;let{function:R,logicalId:P}=f.createOutboundEmailLambda({slug:i,environment:s,roleArn:x.GetAtt(v,"Arn"),domain:o,configurationSetName:d});h[P]=R;let I={roleLogicalId:v,outboundLambdaLogicalId:P};if(g){let{function:M,permission:L,logicalId:N,permissionLogicalId:O}=f.createInboundEmailLambda({slug:i,environment:s,roleArn:x.GetAtt(v,"Arn"),s3BucketName:c});h[N]=M,h[O]=L;let{permission:B,logicalId:F}=f.createS3LambdaPermission({slug:i,environment:s,lambdaLogicalId:N,s3BucketArn:u});h[F]=B,I.inboundLambdaLogicalId=N}if(y){let{function:M,logicalId:L}=f.createEmailConversionLambda({slug:i,environment:s,roleArn:x.GetAtt(v,"Arn"),s3BucketName:c});h[L]=M,I.conversionLambdaLogicalId=L}return{resources:h,outputs:I}}static LambdaCode={outboundEmail:`
588
+ `}class nt{static createFileSystem(n){let{slug:i,environment:s,encrypted:o=!0,kmsKeyId:c,performanceMode:u="generalPurpose",throughputMode:d="bursting",provisionedThroughput:g,enableBackup:y=!0}=n,h=r({slug:i,environment:s,resourceType:"efs"}),A=t(h),C={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:o,PerformanceMode:u,ThroughputMode:d,FileSystemTags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(c)C.Properties.KmsKeyId=c;if(d==="provisioned"&&g)C.Properties.ProvisionedThroughputInMibps=g;if(y)C.Properties.BackupPolicy={Status:"ENABLED"};return{fileSystem:C,logicalId:A}}static createMountTarget(n,i){let{slug:s,environment:o,subnetId:c,securityGroups:u,ipAddress:d}=i,g=r({slug:s,environment:o,resourceType:"efs-mt"}),y=t(`${g}-${c}`),h={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:M.Ref(n),SubnetId:c,SecurityGroups:u}};if(d)h.Properties.IpAddress=d;return{mountTarget:h,logicalId:y}}static createAccessPoint(n,i){let{slug:s,environment:o,path:c="/",uid:u="1000",gid:d="1000",permissions:g="755"}=i,y=r({slug:s,environment:o,resourceType:"efs-ap"}),h=t(`${y}-${c.replace(/\//g,"-")}`);return{accessPoint:{Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:M.Ref(n),PosixUser:{Uid:u,Gid:d},RootDirectory:{Path:c,CreationInfo:{OwnerUid:u,OwnerGid:d,Permissions:g}},AccessPointTags:[{Key:"Name",Value:`${y}-${c}`},{Key:"Environment",Value:o}]}},logicalId:h}}static setLifecyclePolicy(n,i){let{transitionToIA:s,transitionToPrimary:o=!1}=i;if(!n.Properties)n.Properties={};if(n.Properties.LifecyclePolicies=[],s){let c=`AFTER_${s}_DAYS`;n.Properties.LifecyclePolicies.push({TransitionToIA:c})}if(o)n.Properties.LifecyclePolicies.push({TransitionToPrimaryStorageClass:"AFTER_1_ACCESS"});return n}static enableBackup(n){if(!n.Properties)n.Properties={};return n.Properties.BackupPolicy={Status:"ENABLED"},n}static disableBackup(n){if(!n.Properties)n.Properties={};return n.Properties.BackupPolicy={Status:"DISABLED"},n}static setProvisionedThroughput(n,i){if(!n.Properties)n.Properties={};return n.Properties.ThroughputMode="provisioned",n.Properties.ProvisionedThroughputInMibps=i,n}static setElasticThroughput(n){if(!n.Properties)n.Properties={};return n.Properties.ThroughputMode="elastic",n}static enableMaxIO(n){if(!n.Properties)n.Properties={};return n.Properties.PerformanceMode="maxIO",n}static createEfsSecurityGroup(n){let{slug:i,environment:s,vpcId:o,sourceSecurityGroupIds:c=[],sourceCidrBlocks:u=[],description:d}=n,g=r({slug:i,environment:s,resourceType:"efs-sg"}),y=t(g),h=[];for(let C of c)h.push({IpProtocol:"tcp",FromPort:2049,ToPort:2049,SourceSecurityGroupId:C,Description:"NFS from security group"});for(let C of u)h.push({IpProtocol:"tcp",FromPort:2049,ToPort:2049,CidrIp:C,Description:"NFS from CIDR block"});return{securityGroup:{Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:g,GroupDescription:d||`Security group for EFS mount targets - ${i} ${s}`,VpcId:o,SecurityGroupIngress:h,Tags:[{Key:"Name",Value:g},{Key:"Environment",Value:s}]}},logicalId:y}}static createMultiAzMountTargets(n,i){let{slug:s,environment:o,subnetIds:c,securityGroupId:u}=i,d=[],g=[];for(let y=0;y<c.length;y++){let h=c[y],A=r({slug:s,environment:o,resourceType:"efs-mt"}),C=t(`${A}-az${y+1}`),v={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:M.Ref(n),SubnetId:h,SecurityGroups:[u]}};d.push(v),g.push(C)}return{mountTargets:d,logicalIds:g}}static createCompleteFileSystem(n){let{slug:i,environment:s,vpcId:o,subnetIds:c,sourceSecurityGroupIds:u=[],encrypted:d=!0,performanceMode:g="generalPurpose",throughputMode:y="elastic",enableBackup:h=!0,transitionToIA:A}=n,C={},{fileSystem:v,logicalId:T}=nt.createFileSystem({slug:i,environment:s,encrypted:d,performanceMode:g,throughputMode:y,enableBackup:h});if(A)nt.setLifecyclePolicy(v,{transitionToIA:A,transitionToPrimary:!0});C[T]=v;let{securityGroup:R,logicalId:P}=nt.createEfsSecurityGroup({slug:i,environment:s,vpcId:o,sourceSecurityGroupIds:u});C[P]=R;let{mountTargets:I,logicalIds:O}=nt.createMultiAzMountTargets(T,{slug:i,environment:s,subnetIds:c,securityGroupId:M.Ref(P)});for(let B=0;B<I.length;B++)C[O[B]]=I[B];return{resources:C,outputs:{fileSystemId:T,securityGroupId:P,mountTargetIds:O}}}}class f{static verifyDomain(n){let{domain:i,slug:s,environment:o,enableDkim:c=!0,dkimKeyLength:u="RSA_2048_BIT"}=n,d=r({slug:s,environment:o,resourceType:"ses-identity"}),g=t(`${d}-${i.replace(/\./g,"")}`),y={Type:"AWS::SES::EmailIdentity",Properties:{EmailIdentity:i,FeedbackAttributes:{EmailForwardingEnabled:!0}}};if(c)y.Properties.DkimSigningAttributes={NextSigningKeyLength:u};return{emailIdentity:y,logicalId:g}}static createDkimRecords(n,i,s){let o=[];for(let c=0;c<i.length;c++){let u=i[c],d=t(`dkim-${n.replace(/\./g,"")}-${c+1}`),g={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:s,Name:`${u}._domainkey.${n}`,Type:"CNAME",TTL:1800,ResourceRecords:[`${u}.dkim.amazonses.com`]}};o.push({record:g,logicalId:d})}return o}static createConfigurationSet(n){let{slug:i,environment:s,name:o,reputationMetrics:c=!0,sendingEnabled:u=!0,suppressBounces:d=!0,suppressComplaints:g=!0}=n,y=o||r({slug:i,environment:s,resourceType:"ses-config"}),h=t(y),A=[];if(d)A.push("BOUNCE");if(g)A.push("COMPLAINT");return{configurationSet:{Type:"AWS::SES::ConfigurationSet",Properties:{Name:y,ReputationOptions:{ReputationMetricsEnabled:c},SendingOptions:{SendingEnabled:u},SuppressionOptions:{SuppressedReasons:A}}},logicalId:h}}static createReceiptRuleSet(n){let{slug:i,environment:s,name:o}=n,c=o||r({slug:i,environment:s,resourceType:"ses-ruleset"}),u=t(c);return{ruleSet:{Type:"AWS::SES::ReceiptRuleSet",Properties:{RuleSetName:c}},logicalId:u}}static createReceiptRule(n,i){let{slug:s,environment:o,ruleSetName:c,recipients:u,enabled:d=!0,scanEnabled:g=!0,tlsPolicy:y="Require",s3Action:h,lambdaAction:A,snsAction:C}=i,v=r({slug:s,environment:o,resourceType:"ses-rule"}),T=t(v),R=[];if(h)R.push({S3Action:{BucketName:h.bucketName,ObjectKeyPrefix:h.prefix,KmsKeyArn:h.kmsKeyArn}});if(A)R.push({LambdaAction:{FunctionArn:A.functionArn,InvocationType:A.invocationType||"Event"}});if(C)R.push({SNSAction:{TopicArn:C.topicArn,Encoding:C.encoding||"UTF-8"}});return{receiptRule:{Type:"AWS::SES::ReceiptRule",Properties:{RuleSetName:c,Rule:{Name:v,Enabled:d,ScanEnabled:g,TlsPolicy:y,Recipients:u,Actions:R.length>0?R:void 0}}},logicalId:T}}static createMxRecord(n,i,s){let o=t(`mx-${n.replace(/\./g,"")}`);return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:n,Type:"MX",TTL:300,ResourceRecords:[`10 inbound-smtp.${s}.amazonaws.com`]}},logicalId:o}}static createVerificationRecord(n,i,s){let o=t(`verification-${n.replace(/\./g,"")}`);return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:s,Name:`_amazonses.${n}`,Type:"TXT",TTL:1800,ResourceRecords:[`"${i}"`]}},logicalId:o}}static getSmtpEndpoint(n){return`email-smtp.${n}.amazonaws.com`}static SmtpPorts={TLS:587,SSL:465,Unencrypted:25};static createSpfRecord(n,i,s){let{includeDomains:o=[],softFail:c=!1}=s||{},u=t(`spf-${n.replace(/\./g,"")}`),d="v=spf1 include:amazonses.com";for(let y of o)d+=` include:${y}`;return d+=c?" ~all":" -all",{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:n,Type:"TXT",TTL:300,ResourceRecords:[`"${d}"`]}},logicalId:u}}static createDmarcRecord(n,i,s){let{policy:o="none",subdomainPolicy:c,percentage:u=100,reportingEmail:d,forensicEmail:g}=s||{},y=t(`dmarc-${n.replace(/\./g,"")}`),h=`v=DMARC1; p=${o}; pct=${u}`;if(c)h+=`; sp=${c}`;if(d)h+=`; rua=mailto:${d}`;if(g)h+=`; ruf=mailto:${g}`;return{record:{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i,Name:`_dmarc.${n}`,Type:"TXT",TTL:300,ResourceRecords:[`"${h}"`]}},logicalId:y}}static createInboundEmailSetup(n){let{slug:i,environment:s,domain:o,s3BucketName:c,s3KeyPrefix:u="inbound/",region:d,hostedZoneId:g,lambdaFunctionArn:y,snsTopicArn:h}=n,A={},{ruleSet:C,logicalId:v}=f.createReceiptRuleSet({slug:i,environment:s});A[v]=C;let{receiptRule:T,logicalId:R}=f.createReceiptRule(v,{slug:i,environment:s,ruleSetName:C.Properties.RuleSetName||`${i}-${s}-receipt-rule-set`,recipients:[o],s3Action:{bucketName:c,prefix:u},lambdaAction:y?{functionArn:y,invocationType:"Event"}:void 0,snsAction:h?{topicArn:h}:void 0});A[R]=T;let{record:P,logicalId:I}=f.createMxRecord(o,g,d);return A[I]=P,{resources:A,outputs:{ruleSetLogicalId:v,ruleLogicalId:R,mxRecordLogicalId:I}}}static createCompleteDomainSetup(n){let{slug:i,environment:s,domain:o,hostedZoneId:c,region:u,enableInbound:d=!1,inboundS3Bucket:g,dmarcReportingEmail:y}=n,h={},{emailIdentity:A,logicalId:C}=f.verifyDomain({domain:o,slug:i,environment:s});h[C]=A;let{configurationSet:v,logicalId:T}=f.createConfigurationSet({slug:i,environment:s});h[T]=v;let{record:R,logicalId:P}=f.createSpfRecord(o,c);h[P]=R;let{record:I,logicalId:O}=f.createDmarcRecord(o,c,{policy:"none",reportingEmail:y||`dmarc-reports@${o}`});if(h[O]=I,d&&g){let B=f.createInboundEmailSetup({slug:i,environment:s,domain:o,s3BucketName:g,region:u,hostedZoneId:c});Object.assign(h,B.resources)}return{resources:h,outputs:{identityLogicalId:C,configSetLogicalId:T}}}static InboundSmtpEndpoints={"us-east-1":"inbound-smtp.us-east-1.amazonaws.com","us-west-2":"inbound-smtp.us-west-2.amazonaws.com","eu-west-1":"inbound-smtp.eu-west-1.amazonaws.com"};static supportsInboundEmail(n){return n in f.InboundSmtpEndpoints}static createEmailLambdaRole(n){let{slug:i,environment:s,s3BucketArn:o,sesIdentityArn:c}=n,u=r({slug:i,environment:s,resourceType:"email-lambda-role"}),d=t(u),g=t(`${u}-policy`),y={Type:"AWS::IAM::Role",Properties:{RoleName:u,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"],Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:s}]}},h=[{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[o,`${o}/*`]}];if(c)h.push({Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail"],Resource:c});let A={Type:"AWS::IAM::Policy",Properties:{PolicyName:`${u}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:h},Roles:[M.Ref(d)]}};return{role:y,policy:A,roleLogicalId:d,policyLogicalId:g}}static createOutboundEmailLambda(n){let{slug:i,environment:s,roleArn:o,domain:c,configurationSetName:u,timeout:d=30,memorySize:g=256}=n,y=r({slug:i,environment:s,resourceType:"outbound-email"}),h=t(y);return{function:{Type:"AWS::Lambda::Function",Properties:{FunctionName:y,Runtime:"nodejs20.x",Handler:"index.handler",Role:o,Timeout:d,MemorySize:g,Environment:{Variables:{DOMAIN:c,CONFIGURATION_SET:u||""}},Code:{ZipFile:f.LambdaCode.outboundEmail},Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:s},{Key:"Purpose",Value:"OutboundEmail"}]}},logicalId:h}}static createInboundEmailLambda(n){let{slug:i,environment:s,roleArn:o,s3BucketName:c,organizedPrefix:u="organized/",timeout:d=60,memorySize:g=512}=n,y=r({slug:i,environment:s,resourceType:"inbound-email"}),h=t(y),A=t(`${y}-permission`),C={Type:"AWS::Lambda::Function",Properties:{FunctionName:y,Runtime:"nodejs20.x",Handler:"index.handler",Role:o,Timeout:d,MemorySize:g,Environment:{Variables:{S3_BUCKET:c,ORGANIZED_PREFIX:u}},Code:{ZipFile:f.LambdaCode.inboundEmail},Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:s},{Key:"Purpose",Value:"InboundEmail"}]}},v={Type:"AWS::Lambda::Permission",Properties:{FunctionName:M.Ref(h),Action:"lambda:InvokeFunction",Principal:"ses.amazonaws.com",SourceAccount:M.Ref("AWS::AccountId")}};return{function:C,permission:v,logicalId:h,permissionLogicalId:A}}static createEmailConversionLambda(n){let{slug:i,environment:s,roleArn:o,s3BucketName:c,convertedPrefix:u="converted/",timeout:d=60,memorySize:g=512}=n,y=r({slug:i,environment:s,resourceType:"email-conversion"}),h=t(y);return{function:{Type:"AWS::Lambda::Function",Properties:{FunctionName:y,Runtime:"nodejs20.x",Handler:"index.handler",Role:o,Timeout:d,MemorySize:g,Environment:{Variables:{S3_BUCKET:c,CONVERTED_PREFIX:u}},Code:{ZipFile:f.LambdaCode.emailConversion},Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:s},{Key:"Purpose",Value:"EmailConversion"}]}},logicalId:h}}static createEmailBucketNotification(n){let{lambdaArn:i,prefix:s="inbound/",suffix:o,events:c}=n,u=c??["s3:ObjectCreated:*"],d={};if(s||o){if(d.S3Key={Rules:[]},s)d.S3Key.Rules.push({Name:"prefix",Value:s});if(o)d.S3Key.Rules.push({Name:"suffix",Value:o})}return{notificationConfiguration:{LambdaConfigurations:[{Event:u[0],Function:i,Filter:Object.keys(d).length>0?d:void 0}]}}}static createS3LambdaPermission(n){let{slug:i,environment:s,lambdaLogicalId:o,s3BucketArn:c}=n,u=r({slug:i,environment:s,resourceType:"s3-lambda-permission"}),d=t(u);return{permission:{Type:"AWS::Lambda::Permission",Properties:{FunctionName:M.Ref(o),Action:"lambda:InvokeFunction",Principal:"s3.amazonaws.com",SourceArn:c}},logicalId:d}}static createEmailProcessingStack(n){let{slug:i,environment:s,domain:o,s3BucketName:c,s3BucketArn:u,configurationSetName:d,enableInbound:g=!0,enableConversion:y=!0}=n,h={},{role:A,policy:C,roleLogicalId:v,policyLogicalId:T}=f.createEmailLambdaRole({slug:i,environment:s,s3BucketArn:u,sesIdentityArn:`arn:aws:ses:*:*:identity/${o}`});h[v]=A,h[T]=C;let{function:R,logicalId:P}=f.createOutboundEmailLambda({slug:i,environment:s,roleArn:M.GetAtt(v,"Arn"),domain:o,configurationSetName:d});h[P]=R;let I={roleLogicalId:v,outboundLambdaLogicalId:P};if(g){let{function:O,permission:B,logicalId:x,permissionLogicalId:F}=f.createInboundEmailLambda({slug:i,environment:s,roleArn:M.GetAtt(v,"Arn"),s3BucketName:c});h[x]=O,h[F]=B;let{permission:G,logicalId:_}=f.createS3LambdaPermission({slug:i,environment:s,lambdaLogicalId:x,s3BucketArn:u});h[_]=G,I.inboundLambdaLogicalId=x}if(y){let{function:O,logicalId:B}=f.createEmailConversionLambda({slug:i,environment:s,roleArn:M.GetAtt(v,"Arn"),s3BucketName:c});h[B]=O,I.conversionLambdaLogicalId=B}return{resources:h,outputs:I}}static LambdaCode={outboundEmail:`
589
589
  const { SESClient, SendRawEmailCommand } = require('@aws-sdk/client-ses');
590
590
  const ses = new SESClient({});
591
591
 
@@ -1131,7 +1131,7 @@ else if (encoding === 'quoted-printable') {
1131
1131
 
1132
1132
  return content;
1133
1133
  }
1134
- `}}var At=`
1134
+ `}}var vt=`
1135
1135
  const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');
1136
1136
  const { DynamoDBClient, PutItemCommand } = require('@aws-sdk/client-dynamodb');
1137
1137
 
@@ -1238,7 +1238,7 @@ catch (error) {
1238
1238
  };
1239
1239
  }
1240
1240
  };
1241
- `,Rr=`
1241
+ `,Fr=`
1242
1242
  const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');
1243
1243
  const { DynamoDBClient, PutItemCommand } = require('@aws-sdk/client-dynamodb');
1244
1244
 
@@ -1345,7 +1345,7 @@ catch (error) {
1345
1345
  };
1346
1346
  }
1347
1347
  };
1348
- `;var rn=`
1348
+ `;var dn=`
1349
1349
  const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');
1350
1350
  const { DynamoDBClient, UpdateItemCommand } = require('@aws-sdk/client-dynamodb');
1351
1351
 
@@ -1452,7 +1452,7 @@ catch (error) {
1452
1452
  };
1453
1453
  }
1454
1454
  };
1455
- `;var sn=`
1455
+ `;var bn=`
1456
1456
  const { S3Client, GetObjectCommand, PutObjectCommand } = require('@aws-sdk/client-s3');
1457
1457
  const { TranscribeClient, StartTranscriptionJobCommand, GetTranscriptionJobCommand } = require('@aws-sdk/client-transcribe');
1458
1458
  const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');
@@ -1623,7 +1623,7 @@ catch (error) {
1623
1623
 
1624
1624
  return { statusCode: 200, body: 'OK' };
1625
1625
  };
1626
- `;class rt{static LambdaCode={incomingCall:At,voicemail:sn,missedCall:rn};static createConnectInstance(n){let{slug:i,environment:s,instanceAlias:o,inboundCallsEnabled:c=!0,outboundCallsEnabled:u=!0}=n;return{[`${i}ConnectInstance`]:{Type:"AWS::Connect::Instance",Properties:{InstanceAlias:o,IdentityManagementType:"CONNECT_MANAGED",Attributes:{InboundCalls:c,OutboundCalls:u,ContactflowLogs:!0,ContactLens:!0,AutoResolveBestVoices:!0,UseCustomTTSVoices:!1,EarlyMedia:!0}}}}}static createHoursOfOperation(n){return{[`${n.slug}HoursOfOperation`]:{Type:"AWS::Connect::HoursOfOperation",Properties:{InstanceArn:n.instanceArn,Name:n.name,TimeZone:n.timezone,Config:n.schedule.map((i)=>({Day:i.day,StartTime:{Hours:i.startHour,Minutes:i.startMinute},EndTime:{Hours:i.endHour,Minutes:i.endMinute}}))}}}}static createQueue(n){return{[`${n.slug}Queue`]:{Type:"AWS::Connect::Queue",Properties:{InstanceArn:n.instanceArn,Name:n.name,HoursOfOperationArn:n.hoursOfOperationArn,MaxContacts:n.maxContacts||10}}}}static createContactFlow(n){return{[`${n.slug}ContactFlow`]:{Type:"AWS::Connect::ContactFlow",Properties:{InstanceArn:n.instanceArn,Name:n.name,Type:n.type,Content:n.content}}}}static createBasicIvrFlow(n){let i={Version:"2019-10-30",StartAction:"greeting",Actions:[{Identifier:"greeting",Type:"MessageParticipant",Parameters:{Text:n.greeting},Transitions:{NextAction:"transfer_to_queue",Errors:[{NextAction:"disconnect"}]}},{Identifier:"transfer_to_queue",Type:"TransferToQueue",Parameters:{QueueId:n.queueArn},Transitions:{NextAction:n.voicemailLambdaArn?"voicemail":"disconnect",Errors:[{NextAction:"disconnect"}]}},...n.voicemailLambdaArn?[{Identifier:"voicemail",Type:"InvokeLambdaFunction",Parameters:{LambdaFunctionARN:n.voicemailLambdaArn},Transitions:{NextAction:"disconnect",Errors:[{NextAction:"disconnect"}]}}]:[],{Identifier:"disconnect",Type:"DisconnectParticipant",Parameters:{},Transitions:{}}]};return JSON.stringify(i)}static createPhoneLambdaRole(n){return{[`${n.slug}PhoneLambdaRole`]:{Type:"AWS::IAM::Role",Properties:{RoleName:`${n.slug}-phone-lambda-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:"PhoneLambdaPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:GetItem"],Resource:"*"},{Effect:"Allow",Action:["sns:Publish"],Resource:"*"},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject"],Resource:"*"},{Effect:"Allow",Action:["transcribe:StartTranscriptionJob","transcribe:GetTranscriptionJob"],Resource:"*"},{Effect:"Allow",Action:["connect:*"],Resource:"*"}]}}]}}}}static createIncomingCallLambda(n){return{[`${n.slug}IncomingCallLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-incoming-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:rt.LambdaCode.incomingCall},Environment:{Variables:{NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",CALL_LOG_TABLE:n.callLogTable||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createVoicemailLambda(n){return{[`${n.slug}VoicemailLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-voicemail`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:300,MemorySize:512,Code:{ZipFile:rt.LambdaCode.voicemail},Environment:{Variables:{VOICEMAIL_BUCKET:n.voicemailBucket,NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",CALL_LOG_TABLE:n.callLogTable||"",TRANSCRIPTION_ENABLED:n.transcriptionEnabled?"true":"false"}}}}}}static createMissedCallLambda(n){return{[`${n.slug}MissedCallLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-missed-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:rt.LambdaCode.missedCall},Environment:{Variables:{NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",CALL_LOG_TABLE:n.callLogTable||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createCallLogTable(n){return{[`${n.slug}CallLogTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-call-log`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"contactId",AttributeType:"S"}],KeySchema:[{AttributeName:"contactId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createCompleteSetup(n){let i={},s={};Object.assign(i,rt.createPhoneLambdaRole({slug:n.slug})),Object.assign(i,rt.createCallLogTable({slug:n.slug})),i[`${n.slug}PhoneNotificationTopic`]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${n.slug}-phone-notifications`}},i[`${n.slug}VoicemailBucket`]={Type:"AWS::S3::Bucket",Properties:{BucketName:`${n.slug}-voicemails`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldVoicemails",Status:"Enabled",ExpirationInDays:90}]}}};let o={"Fn::GetAtt":[`${n.slug}PhoneLambdaRole`,"Arn"]},c={Ref:`${n.slug}PhoneNotificationTopic`},u={Ref:`${n.slug}CallLogTable`},d={Ref:`${n.slug}VoicemailBucket`};if(Object.assign(i,rt.createIncomingCallLambda({slug:n.slug,roleArn:o,notificationTopicArn:c,callLogTable:u,webhookUrl:n.webhookUrl})),n.voicemailEnabled!==!1)Object.assign(i,rt.createVoicemailLambda({slug:n.slug,roleArn:o,voicemailBucket:d,notificationTopicArn:c,callLogTable:u,transcriptionEnabled:n.transcriptionEnabled}));return Object.assign(i,rt.createMissedCallLambda({slug:n.slug,roleArn:o,notificationTopicArn:c,callLogTable:u,webhookUrl:n.webhookUrl})),s[`${n.slug}PhoneNotificationTopicArn`]={Description:"Phone notification topic ARN",Value:{Ref:`${n.slug}PhoneNotificationTopic`}},s[`${n.slug}CallLogTableName`]={Description:"Call log table name",Value:{Ref:`${n.slug}CallLogTable`}},s[`${n.slug}VoicemailBucketName`]={Description:"Voicemail bucket name",Value:{Ref:`${n.slug}VoicemailBucket`}},{resources:i,outputs:s}}}class J{static createQueue(n){let{slug:i,environment:s,name:o,delaySeconds:c=0,visibilityTimeout:u=30,messageRetentionPeriod:d=345600,maxMessageSize:g=262144,receiveMessageWaitTime:y=0,fifo:h=!1,contentBasedDeduplication:A=!1,encrypted:C=!0,kmsKeyId:v}=n,T=o||r({slug:i,environment:s,resourceType:"queue"}),R=h?`${T}.fifo`:T,P=t(T),I={Type:"AWS::SQS::Queue",Properties:{QueueName:R,DelaySeconds:c,MaximumMessageSize:g,MessageRetentionPeriod:d,ReceiveMessageWaitTimeSeconds:y,VisibilityTimeout:u,Tags:[{Key:"Name",Value:R},{Key:"Environment",Value:s}]}};if(h)I.Properties.FifoQueue=!0,I.Properties.ContentBasedDeduplication=A;if(C)if(v)I.Properties.KmsMasterKeyId=v;else I.Properties.SqsManagedSseEnabled=!0;return{queue:I,logicalId:P}}static createDeadLetterQueue(n,i){let{slug:s,environment:o,maxReceiveCount:c=3}=i,u=r({slug:s,environment:o,resourceType:"dlq"}),d=t(u),g={Type:"AWS::SQS::Queue",Properties:{QueueName:u,MessageRetentionPeriod:1209600,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:o},{Key:"Type",Value:"DeadLetterQueue"}]}},y={Type:"AWS::SQS::Queue",Properties:{RedrivePolicy:{deadLetterTargetArn:x.GetAtt(d,"Arn"),maxReceiveCount:c}}};return{deadLetterQueue:g,updatedSourceQueue:y,deadLetterLogicalId:d}}static createSchedule(n,i){let{slug:s,environment:o,name:c,description:u,enabled:d=!0}=i,g=c||r({slug:s,environment:o,resourceType:"schedule"}),y=t(g);return{rule:{Type:"AWS::Events::Rule",Properties:{Name:g,Description:u,ScheduleExpression:n,State:d?"ENABLED":"DISABLED",Targets:[]}},logicalId:y}}static scheduleEcsTask(n,i,s){let{slug:o,environment:c,name:u,description:d,enabled:g=!0,taskDefinitionArn:y,clusterArn:h,subnets:A,securityGroups:C=[],assignPublicIp:v=!1,taskCount:T=1,containerOverrides:R}=s,P=u||r({slug:o,environment:c,resourceType:"ecs-schedule"}),I=t(P),L={Id:"1",Arn:h,RoleArn:i,EcsParameters:{TaskDefinitionArn:y,TaskCount:T,LaunchType:"FARGATE",NetworkConfiguration:{awsvpcConfiguration:{Subnets:A,SecurityGroups:C,AssignPublicIp:v?"ENABLED":"DISABLED"}},PlatformVersion:"LATEST"}};if(R&&R.length>0)L.Input=JSON.stringify({containerOverrides:R});return{rule:{Type:"AWS::Events::Rule",Properties:{Name:P,Description:d||`Scheduled ECS task: ${y}`,ScheduleExpression:n,State:g?"ENABLED":"DISABLED",Targets:[L]}},logicalId:I}}static scheduleLambda(n,i){let{slug:s,environment:o,name:c,description:u,enabled:d=!0,functionArn:g,input:y}=i,h=c||r({slug:s,environment:o,resourceType:"lambda-schedule"}),A=t(h),C={Id:"1",Arn:g};if(y)C.Input=JSON.stringify(y);return{rule:{Type:"AWS::Events::Rule",Properties:{Name:h,Description:u||`Scheduled Lambda: ${g}`,ScheduleExpression:n,State:d?"ENABLED":"DISABLED",Targets:[C]}},logicalId:A}}static scheduleSqsMessage(n,i){let{slug:s,environment:o,name:c,description:u,enabled:d=!0,queueArn:g,messageGroupId:y}=i,h=c||r({slug:s,environment:o,resourceType:"sqs-schedule"}),A=t(h),C={Id:"1",Arn:g};if(y)C.SqsParameters={MessageGroupId:y};return{rule:{Type:"AWS::Events::Rule",Properties:{Name:h,Description:u||`Scheduled SQS message: ${g}`,ScheduleExpression:n,State:d?"ENABLED":"DISABLED",Targets:[C]}},logicalId:A}}static addTarget(n,i){if(!n.Properties.Targets)n.Properties.Targets=[];let s={Id:i.id,Arn:i.arn};if(i.roleArn)s.RoleArn=i.roleArn;if(i.input)s.Input=JSON.stringify(i.input);return n.Properties.Targets.push(s),n}static toCronExpression(n){if(n.startsWith("cron(")||n.startsWith("rate("))return n;return`cron(${n})`}static rateExpression(n,i){return`rate(${n} ${i})`}static CronExpressions={EveryMinute:"cron(* * * * ? *)",Every5Minutes:"cron(*/5 * * * ? *)",Every15Minutes:"cron(*/15 * * * ? *)",Every30Minutes:"cron(*/30 * * * ? *)",Hourly:"cron(0 * * * ? *)",Daily:"cron(0 0 * * ? *)",DailyAt9AM:"cron(0 9 * * ? *)",DailyAtMidnight:"cron(0 0 * * ? *)",Weekly:"cron(0 0 ? * SUN *)",Monthly:"cron(0 0 1 * ? *)"};static RateExpressions={Every1Minute:"rate(1 minute)",Every5Minutes:"rate(5 minutes)",Every10Minutes:"rate(10 minutes)",Every15Minutes:"rate(15 minutes)",Every30Minutes:"rate(30 minutes)",Every1Hour:"rate(1 hour)",Every6Hours:"rate(6 hours)",Every12Hours:"rate(12 hours)",Every1Day:"rate(1 day)"};static rateStringToExpression(n){let i=n.toLowerCase().trim(),s=i.match(/^every\s+(\d+)\s+(minute|minutes|hour|hours|day|days)$/i);if(s){let h=parseInt(s[1],10),A=s[2].toLowerCase(),C=A.endsWith("s")&&h===1?A.slice(0,-1):A,v=!A.endsWith("s")&&h>1?`${A}s`:A;return`rate(${h} ${h===1?C:v})`}let o=i.match(/^every\s+(minute|hour|day)$/i);if(o)return`rate(1 ${o[1]})`;let c={"every minute":"rate(1 minute)","every hour":"rate(1 hour)","every day":"rate(1 day)",hourly:"cron(0 * * * ? *)",daily:"cron(0 0 * * ? *)","daily at midnight":"cron(0 0 * * ? *)",weekly:"cron(0 0 ? * SUN *)",monthly:"cron(0 0 1 * ? *)",yearly:"cron(0 0 1 1 ? *)"};if(c[i])return c[i];let u=i.match(/^daily\s+at\s+(\d{1,2})\s*(am|pm)?$/i);if(u){let h=parseInt(u[1],10),A=u[2]?.toLowerCase();if(A==="pm"&&h!==12)h+=12;else if(A==="am"&&h===12)h=0;return`cron(0 ${h} * * ? *)`}let d=i.match(/^at\s+(\d{1,2}):(\d{2})$/i);if(d){let h=parseInt(d[1],10);return`cron(${parseInt(d[2],10)} ${h} * * ? *)`}let g={monday:"MON",tuesday:"TUE",wednesday:"WED",thursday:"THU",friday:"FRI",saturday:"SAT",sunday:"SUN"},y=i.match(/^every\s+(monday|tuesday|wednesday|thursday|friday|saturday|sunday)$/i);if(y)return`cron(0 0 ? * ${g[y[1].toLowerCase()]} *)`;return J.toCronExpression(n)}static JobConfig={create:(n)=>{let{name:i,handler:s,retries:o=3,backoff:c="exponential",backoffDelay:u=1000,maxDelay:d=30000,timeout:g=60000,jitter:y=!0}=n;return{name:i,handler:s,retries:o,backoff:c,backoffDelay:u,maxDelay:d,timeout:g,jitter:y}},calculateDelay:(n,i)=>{let{backoff:s,backoffDelay:o,maxDelay:c,jitter:u}=i,d;switch(s){case"linear":d=o*n;break;case"exponential":d=o*2**(n-1);break;case"fixed":default:d=o}if(d=Math.min(d,c||Number.MAX_SAFE_INTEGER),u){let g=d*0.25*Math.random();d+=g}return Math.floor(d)},presets:{fastRetry:{retries:5,backoff:"exponential",backoffDelay:100,maxDelay:5000,jitter:!0},standard:{retries:3,backoff:"exponential",backoffDelay:1000,maxDelay:30000,jitter:!0},longRunning:{retries:2,backoff:"exponential",backoffDelay:5000,maxDelay:60000,timeout:300000,jitter:!0},critical:{retries:10,backoff:"exponential",backoffDelay:500,maxDelay:60000,jitter:!0},noRetry:{retries:0,backoff:"fixed",backoffDelay:0,maxDelay:0,jitter:!1}}};static createJobContainerOverride(n){let{containerName:i,jobClass:s,jobData:o,environment:c={}}=n,u=[{name:"JOB_CLASS",value:s}];if(o)u.push({name:"JOB_DATA",value:JSON.stringify(o)});for(let[d,g]of Object.entries(c))u.push({name:d,value:g});return{name:i,command:["bun","run","app/Jobs/runner.ts"],environment:u}}static createScheduledJob(n){let{slug:i,environment:s,schedule:o,jobClass:c,jobData:u,taskDefinitionArn:d,clusterArn:g,subnets:y,securityGroups:h=[],roleArn:A,containerName:C="app"}=n,v=J.rateStringToExpression(o),T=J.createJobContainerOverride({containerName:C,jobClass:c,jobData:u});return J.scheduleEcsTask(v,A,{slug:i,environment:s,name:`${i}-${c.toLowerCase().replace(/[^a-z0-9]/g,"-")}`,description:`Scheduled job: ${c}`,taskDefinitionArn:d,clusterArn:g,subnets:y,securityGroups:h,containerOverrides:[T]})}static QueuePresets={highThroughput:(n,i)=>J.createQueue({slug:n,environment:i,visibilityTimeout:30,receiveMessageWaitTime:0,delaySeconds:0}),longRunning:(n,i)=>J.createQueue({slug:n,environment:i,visibilityTimeout:300,messageRetentionPeriod:1209600}),fifo:(n,i)=>J.createQueue({slug:n,environment:i,fifo:!0,contentBasedDeduplication:!0}),delayed:(n,i,s=60)=>J.createQueue({slug:n,environment:i,delaySeconds:s})}}class Bt{static async discoverJobs(n){let{projectRoot:i,jobsPath:s="app/Jobs"}=n,o=`${i}/${s}`,c=[];try{let u=await import("node:fs"),d=await import("node:path");if(!u.existsSync(o))return[];let g=u.readdirSync(o).filter((y)=>y.endsWith(".ts")&&!y.startsWith("_")&&y!=="runner.ts");for(let y of g){let h=d.join(o,y),A=y.replace(".ts",""),C=u.readFileSync(h,"utf-8"),v=Bt.parseJobMetadata(C,A,h);if(v)c.push(v)}}catch{return[]}return c}static parseJobMetadata(n,i,s){let o=n.match(/export\s + const\s + schedule\s*=\s*['"`]([^'"`]+)['"`]/)||n.match(/schedule:\s*['"`]([^'"`]+)['"`]/),c=n.match(/export\s+const\s+enabled\s*=\s*(true|false)/)||n.match(/enabled:\s*(true|false)/),u=n.match(/export\s+const\s+retries\s*=\s*(\d+)/)||n.match(/retries:\s*(\d+)/),d=n.match(/export\s+const\s+timeout\s*=\s*(\d+)/)||n.match(/timeout:\s*(\d+)/),g=n.match(/export\s+const\s+backoff\s*=\s*['"`](linear|exponential|fixed)['"`]/)||n.match(/backoff:\s*['"`](linear|exponential|fixed)['"`]/),y=n.match(/export\s + const\s + description\s*=\s*['"`]([^'"`]+)['"`]/)||n.match(/description:\s*['"`]([^'"`]+)['"`]/);if(!(n.includes("export async function handle")||n.includes("export function handle")||n.includes("export default")))return null;return{name:i,path:s,schedule:o?.[1],handler:`${i}.handle`,enabled:c?.[1]!=="false",retries:u?parseInt(u[1],10):void 0,backoff:g?.[1],timeout:d?parseInt(d[1],10):void 0,description:y?.[1]}}static async discoverActions(n){let{projectRoot:i,actionsPath:s="app/Actions"}=n,o=`${i}/${s}`,c=[];try{let u=await import("node:fs"),d=await import("node:path");if(!u.existsSync(o))return[];let g=u.readdirSync(o).filter((y)=>y.endsWith(".ts")&&!y.startsWith("_"));for(let y of g){let h=d.join(o,y),A=y.replace(".ts",""),C=u.readFileSync(h,"utf-8"),v=Bt.parseActionMetadata(C,A,h);if(v)c.push(v)}}catch{return[]}return c}static parseActionMetadata(n,i,s){if(!(n.includes("export async function handle")||n.includes("export function handle")||n.includes("export default")))return null;let c=n.match(/export\s + const\s + description\s*=\s*['"`]([^'"`]+)['"`]/)||n.match(/description:\s*['"`]([^'"`]+)['"`]/);return{name:i,path:s,handler:`${i}.handle`,description:c?.[1]}}static generateScheduledJobResources(n){let{slug:i,environment:s,jobs:o,taskDefinitionArn:c,clusterArn:u,subnets:d,securityGroups:g=[],roleArn:y,containerName:h="app"}=n,A={},C=0;for(let v of o){if(!v.schedule||!v.enabled)continue;let{rule:T,logicalId:R}=J.createScheduledJob({slug:i,environment:s,schedule:v.schedule,jobClass:v.name,taskDefinitionArn:c,clusterArn:u,subnets:d,securityGroups:g,roleArn:y,containerName:h});A[R]=T,C++}return{rules:A,count:C}}static generateJobRunnerScript(){return`#!/usr/bin/env bun
1626
+ `;class it{static LambdaCode={incomingCall:vt,voicemail:bn,missedCall:dn};static createConnectInstance(n){let{slug:i,environment:s,instanceAlias:o,inboundCallsEnabled:c=!0,outboundCallsEnabled:u=!0}=n;return{[`${i}ConnectInstance`]:{Type:"AWS::Connect::Instance",Properties:{InstanceAlias:o,IdentityManagementType:"CONNECT_MANAGED",Attributes:{InboundCalls:c,OutboundCalls:u,ContactflowLogs:!0,ContactLens:!0,AutoResolveBestVoices:!0,UseCustomTTSVoices:!1,EarlyMedia:!0}}}}}static createHoursOfOperation(n){return{[`${n.slug}HoursOfOperation`]:{Type:"AWS::Connect::HoursOfOperation",Properties:{InstanceArn:n.instanceArn,Name:n.name,TimeZone:n.timezone,Config:n.schedule.map((i)=>({Day:i.day,StartTime:{Hours:i.startHour,Minutes:i.startMinute},EndTime:{Hours:i.endHour,Minutes:i.endMinute}}))}}}}static createQueue(n){return{[`${n.slug}Queue`]:{Type:"AWS::Connect::Queue",Properties:{InstanceArn:n.instanceArn,Name:n.name,HoursOfOperationArn:n.hoursOfOperationArn,MaxContacts:n.maxContacts||10}}}}static createContactFlow(n){return{[`${n.slug}ContactFlow`]:{Type:"AWS::Connect::ContactFlow",Properties:{InstanceArn:n.instanceArn,Name:n.name,Type:n.type,Content:n.content}}}}static createBasicIvrFlow(n){let i={Version:"2019-10-30",StartAction:"greeting",Actions:[{Identifier:"greeting",Type:"MessageParticipant",Parameters:{Text:n.greeting},Transitions:{NextAction:"transfer_to_queue",Errors:[{NextAction:"disconnect"}]}},{Identifier:"transfer_to_queue",Type:"TransferToQueue",Parameters:{QueueId:n.queueArn},Transitions:{NextAction:n.voicemailLambdaArn?"voicemail":"disconnect",Errors:[{NextAction:"disconnect"}]}},...n.voicemailLambdaArn?[{Identifier:"voicemail",Type:"InvokeLambdaFunction",Parameters:{LambdaFunctionARN:n.voicemailLambdaArn},Transitions:{NextAction:"disconnect",Errors:[{NextAction:"disconnect"}]}}]:[],{Identifier:"disconnect",Type:"DisconnectParticipant",Parameters:{},Transitions:{}}]};return JSON.stringify(i)}static createPhoneLambdaRole(n){return{[`${n.slug}PhoneLambdaRole`]:{Type:"AWS::IAM::Role",Properties:{RoleName:`${n.slug}-phone-lambda-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:"PhoneLambdaPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:GetItem"],Resource:"*"},{Effect:"Allow",Action:["sns:Publish"],Resource:"*"},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject"],Resource:"*"},{Effect:"Allow",Action:["transcribe:StartTranscriptionJob","transcribe:GetTranscriptionJob"],Resource:"*"},{Effect:"Allow",Action:["connect:*"],Resource:"*"}]}}]}}}}static createIncomingCallLambda(n){return{[`${n.slug}IncomingCallLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-incoming-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:it.LambdaCode.incomingCall},Environment:{Variables:{NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",CALL_LOG_TABLE:n.callLogTable||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createVoicemailLambda(n){return{[`${n.slug}VoicemailLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-voicemail`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:300,MemorySize:512,Code:{ZipFile:it.LambdaCode.voicemail},Environment:{Variables:{VOICEMAIL_BUCKET:n.voicemailBucket,NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",CALL_LOG_TABLE:n.callLogTable||"",TRANSCRIPTION_ENABLED:n.transcriptionEnabled?"true":"false"}}}}}}static createMissedCallLambda(n){return{[`${n.slug}MissedCallLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-missed-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:it.LambdaCode.missedCall},Environment:{Variables:{NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",CALL_LOG_TABLE:n.callLogTable||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createCallLogTable(n){return{[`${n.slug}CallLogTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-call-log`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"contactId",AttributeType:"S"}],KeySchema:[{AttributeName:"contactId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createCompleteSetup(n){let i={},s={};Object.assign(i,it.createPhoneLambdaRole({slug:n.slug})),Object.assign(i,it.createCallLogTable({slug:n.slug})),i[`${n.slug}PhoneNotificationTopic`]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${n.slug}-phone-notifications`}},i[`${n.slug}VoicemailBucket`]={Type:"AWS::S3::Bucket",Properties:{BucketName:`${n.slug}-voicemails`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldVoicemails",Status:"Enabled",ExpirationInDays:90}]}}};let o={"Fn::GetAtt":[`${n.slug}PhoneLambdaRole`,"Arn"]},c={Ref:`${n.slug}PhoneNotificationTopic`},u={Ref:`${n.slug}CallLogTable`},d={Ref:`${n.slug}VoicemailBucket`};if(Object.assign(i,it.createIncomingCallLambda({slug:n.slug,roleArn:o,notificationTopicArn:c,callLogTable:u,webhookUrl:n.webhookUrl})),n.voicemailEnabled!==!1)Object.assign(i,it.createVoicemailLambda({slug:n.slug,roleArn:o,voicemailBucket:d,notificationTopicArn:c,callLogTable:u,transcriptionEnabled:n.transcriptionEnabled}));return Object.assign(i,it.createMissedCallLambda({slug:n.slug,roleArn:o,notificationTopicArn:c,callLogTable:u,webhookUrl:n.webhookUrl})),s[`${n.slug}PhoneNotificationTopicArn`]={Description:"Phone notification topic ARN",Value:{Ref:`${n.slug}PhoneNotificationTopic`}},s[`${n.slug}CallLogTableName`]={Description:"Call log table name",Value:{Ref:`${n.slug}CallLogTable`}},s[`${n.slug}VoicemailBucketName`]={Description:"Voicemail bucket name",Value:{Ref:`${n.slug}VoicemailBucket`}},{resources:i,outputs:s}}}class X{static createQueue(n){let{slug:i,environment:s,name:o,delaySeconds:c=0,visibilityTimeout:u=30,messageRetentionPeriod:d=345600,maxMessageSize:g=262144,receiveMessageWaitTime:y=0,fifo:h=!1,contentBasedDeduplication:A=!1,encrypted:C=!0,kmsKeyId:v}=n,T=o||r({slug:i,environment:s,resourceType:"queue"}),R=h?`${T}.fifo`:T,P=t(T),I={Type:"AWS::SQS::Queue",Properties:{QueueName:R,DelaySeconds:c,MaximumMessageSize:g,MessageRetentionPeriod:d,ReceiveMessageWaitTimeSeconds:y,VisibilityTimeout:u,Tags:[{Key:"Name",Value:R},{Key:"Environment",Value:s}]}};if(h)I.Properties.FifoQueue=!0,I.Properties.ContentBasedDeduplication=A;if(C)if(v)I.Properties.KmsMasterKeyId=v;else I.Properties.SqsManagedSseEnabled=!0;return{queue:I,logicalId:P}}static createDeadLetterQueue(n,i){let{slug:s,environment:o,maxReceiveCount:c=3}=i,u=r({slug:s,environment:o,resourceType:"dlq"}),d=t(u),g={Type:"AWS::SQS::Queue",Properties:{QueueName:u,MessageRetentionPeriod:1209600,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:o},{Key:"Type",Value:"DeadLetterQueue"}]}},y={Type:"AWS::SQS::Queue",Properties:{RedrivePolicy:{deadLetterTargetArn:M.GetAtt(d,"Arn"),maxReceiveCount:c}}};return{deadLetterQueue:g,updatedSourceQueue:y,deadLetterLogicalId:d}}static createSchedule(n,i){let{slug:s,environment:o,name:c,description:u,enabled:d=!0}=i,g=c||r({slug:s,environment:o,resourceType:"schedule"}),y=t(g);return{rule:{Type:"AWS::Events::Rule",Properties:{Name:g,Description:u,ScheduleExpression:n,State:d?"ENABLED":"DISABLED",Targets:[]}},logicalId:y}}static scheduleEcsTask(n,i,s){let{slug:o,environment:c,name:u,description:d,enabled:g=!0,taskDefinitionArn:y,clusterArn:h,subnets:A,securityGroups:C=[],assignPublicIp:v=!1,taskCount:T=1,containerOverrides:R}=s,P=u||r({slug:o,environment:c,resourceType:"ecs-schedule"}),I=t(P),B={Id:"1",Arn:h,RoleArn:i,EcsParameters:{TaskDefinitionArn:y,TaskCount:T,LaunchType:"FARGATE",NetworkConfiguration:{awsvpcConfiguration:{Subnets:A,SecurityGroups:C,AssignPublicIp:v?"ENABLED":"DISABLED"}},PlatformVersion:"LATEST"}};if(R&&R.length>0)B.Input=JSON.stringify({containerOverrides:R});return{rule:{Type:"AWS::Events::Rule",Properties:{Name:P,Description:d||`Scheduled ECS task: ${y}`,ScheduleExpression:n,State:g?"ENABLED":"DISABLED",Targets:[B]}},logicalId:I}}static scheduleLambda(n,i){let{slug:s,environment:o,name:c,description:u,enabled:d=!0,functionArn:g,input:y}=i,h=c||r({slug:s,environment:o,resourceType:"lambda-schedule"}),A=t(h),C={Id:"1",Arn:g};if(y)C.Input=JSON.stringify(y);return{rule:{Type:"AWS::Events::Rule",Properties:{Name:h,Description:u||`Scheduled Lambda: ${g}`,ScheduleExpression:n,State:d?"ENABLED":"DISABLED",Targets:[C]}},logicalId:A}}static scheduleSqsMessage(n,i){let{slug:s,environment:o,name:c,description:u,enabled:d=!0,queueArn:g,messageGroupId:y}=i,h=c||r({slug:s,environment:o,resourceType:"sqs-schedule"}),A=t(h),C={Id:"1",Arn:g};if(y)C.SqsParameters={MessageGroupId:y};return{rule:{Type:"AWS::Events::Rule",Properties:{Name:h,Description:u||`Scheduled SQS message: ${g}`,ScheduleExpression:n,State:d?"ENABLED":"DISABLED",Targets:[C]}},logicalId:A}}static addTarget(n,i){if(!n.Properties.Targets)n.Properties.Targets=[];let s={Id:i.id,Arn:i.arn};if(i.roleArn)s.RoleArn=i.roleArn;if(i.input)s.Input=JSON.stringify(i.input);return n.Properties.Targets.push(s),n}static toCronExpression(n){if(n.startsWith("cron(")||n.startsWith("rate("))return n;return`cron(${n})`}static rateExpression(n,i){return`rate(${n} ${i})`}static CronExpressions={EveryMinute:"cron(* * * * ? *)",Every5Minutes:"cron(*/5 * * * ? *)",Every15Minutes:"cron(*/15 * * * ? *)",Every30Minutes:"cron(*/30 * * * ? *)",Hourly:"cron(0 * * * ? *)",Daily:"cron(0 0 * * ? *)",DailyAt9AM:"cron(0 9 * * ? *)",DailyAtMidnight:"cron(0 0 * * ? *)",Weekly:"cron(0 0 ? * SUN *)",Monthly:"cron(0 0 1 * ? *)"};static RateExpressions={Every1Minute:"rate(1 minute)",Every5Minutes:"rate(5 minutes)",Every10Minutes:"rate(10 minutes)",Every15Minutes:"rate(15 minutes)",Every30Minutes:"rate(30 minutes)",Every1Hour:"rate(1 hour)",Every6Hours:"rate(6 hours)",Every12Hours:"rate(12 hours)",Every1Day:"rate(1 day)"};static rateStringToExpression(n){let i=n.toLowerCase().trim(),s=i.match(/^every\s+(\d+)\s+(minute|minutes|hour|hours|day|days)$/i);if(s){let h=parseInt(s[1],10),A=s[2].toLowerCase(),C=A.endsWith("s")&&h===1?A.slice(0,-1):A,v=!A.endsWith("s")&&h>1?`${A}s`:A;return`rate(${h} ${h===1?C:v})`}let o=i.match(/^every\s+(minute|hour|day)$/i);if(o)return`rate(1 ${o[1]})`;let c={"every minute":"rate(1 minute)","every hour":"rate(1 hour)","every day":"rate(1 day)",hourly:"cron(0 * * * ? *)",daily:"cron(0 0 * * ? *)","daily at midnight":"cron(0 0 * * ? *)",weekly:"cron(0 0 ? * SUN *)",monthly:"cron(0 0 1 * ? *)",yearly:"cron(0 0 1 1 ? *)"};if(c[i])return c[i];let u=i.match(/^daily\s+at\s+(\d{1,2})\s*(am|pm)?$/i);if(u){let h=parseInt(u[1],10),A=u[2]?.toLowerCase();if(A==="pm"&&h!==12)h+=12;else if(A==="am"&&h===12)h=0;return`cron(0 ${h} * * ? *)`}let d=i.match(/^at\s+(\d{1,2}):(\d{2})$/i);if(d){let h=parseInt(d[1],10);return`cron(${parseInt(d[2],10)} ${h} * * ? *)`}let g={monday:"MON",tuesday:"TUE",wednesday:"WED",thursday:"THU",friday:"FRI",saturday:"SAT",sunday:"SUN"},y=i.match(/^every\s+(monday|tuesday|wednesday|thursday|friday|saturday|sunday)$/i);if(y)return`cron(0 0 ? * ${g[y[1].toLowerCase()]} *)`;return X.toCronExpression(n)}static JobConfig={create:(n)=>{let{name:i,handler:s,retries:o=3,backoff:c="exponential",backoffDelay:u=1000,maxDelay:d=30000,timeout:g=60000,jitter:y=!0}=n;return{name:i,handler:s,retries:o,backoff:c,backoffDelay:u,maxDelay:d,timeout:g,jitter:y}},calculateDelay:(n,i)=>{let{backoff:s,backoffDelay:o,maxDelay:c,jitter:u}=i,d;switch(s){case"linear":d=o*n;break;case"exponential":d=o*2**(n-1);break;case"fixed":default:d=o}if(d=Math.min(d,c||Number.MAX_SAFE_INTEGER),u){let g=d*0.25*Math.random();d+=g}return Math.floor(d)},presets:{fastRetry:{retries:5,backoff:"exponential",backoffDelay:100,maxDelay:5000,jitter:!0},standard:{retries:3,backoff:"exponential",backoffDelay:1000,maxDelay:30000,jitter:!0},longRunning:{retries:2,backoff:"exponential",backoffDelay:5000,maxDelay:60000,timeout:300000,jitter:!0},critical:{retries:10,backoff:"exponential",backoffDelay:500,maxDelay:60000,jitter:!0},noRetry:{retries:0,backoff:"fixed",backoffDelay:0,maxDelay:0,jitter:!1}}};static createJobContainerOverride(n){let{containerName:i,jobClass:s,jobData:o,environment:c={}}=n,u=[{name:"JOB_CLASS",value:s}];if(o)u.push({name:"JOB_DATA",value:JSON.stringify(o)});for(let[d,g]of Object.entries(c))u.push({name:d,value:g});return{name:i,command:["bun","run","app/Jobs/runner.ts"],environment:u}}static createScheduledJob(n){let{slug:i,environment:s,schedule:o,jobClass:c,jobData:u,taskDefinitionArn:d,clusterArn:g,subnets:y,securityGroups:h=[],roleArn:A,containerName:C="app"}=n,v=X.rateStringToExpression(o),T=X.createJobContainerOverride({containerName:C,jobClass:c,jobData:u});return X.scheduleEcsTask(v,A,{slug:i,environment:s,name:`${i}-${c.toLowerCase().replace(/[^a-z0-9]/g,"-")}`,description:`Scheduled job: ${c}`,taskDefinitionArn:d,clusterArn:g,subnets:y,securityGroups:h,containerOverrides:[T]})}static QueuePresets={highThroughput:(n,i)=>X.createQueue({slug:n,environment:i,visibilityTimeout:30,receiveMessageWaitTime:0,delaySeconds:0}),longRunning:(n,i)=>X.createQueue({slug:n,environment:i,visibilityTimeout:300,messageRetentionPeriod:1209600}),fifo:(n,i)=>X.createQueue({slug:n,environment:i,fifo:!0,contentBasedDeduplication:!0}),delayed:(n,i,s=60)=>X.createQueue({slug:n,environment:i,delaySeconds:s})}}class xt{static async discoverJobs(n){let{projectRoot:i,jobsPath:s="app/Jobs"}=n,o=`${i}/${s}`,c=[];try{let u=await import("node:fs"),d=await import("node:path");if(!u.existsSync(o))return[];let g=u.readdirSync(o).filter((y)=>y.endsWith(".ts")&&!y.startsWith("_")&&y!=="runner.ts");for(let y of g){let h=d.join(o,y),A=y.replace(".ts",""),C=u.readFileSync(h,"utf-8"),v=xt.parseJobMetadata(C,A,h);if(v)c.push(v)}}catch{return[]}return c}static parseJobMetadata(n,i,s){let o=n.match(/export\s + const\s + schedule\s*=\s*['"`]([^'"`]+)['"`]/)||n.match(/schedule:\s*['"`]([^'"`]+)['"`]/),c=n.match(/export\s+const\s+enabled\s*=\s*(true|false)/)||n.match(/enabled:\s*(true|false)/),u=n.match(/export\s+const\s+retries\s*=\s*(\d+)/)||n.match(/retries:\s*(\d+)/),d=n.match(/export\s+const\s+timeout\s*=\s*(\d+)/)||n.match(/timeout:\s*(\d+)/),g=n.match(/export\s+const\s+backoff\s*=\s*['"`](linear|exponential|fixed)['"`]/)||n.match(/backoff:\s*['"`](linear|exponential|fixed)['"`]/),y=n.match(/export\s + const\s + description\s*=\s*['"`]([^'"`]+)['"`]/)||n.match(/description:\s*['"`]([^'"`]+)['"`]/);if(!(n.includes("export async function handle")||n.includes("export function handle")||n.includes("export default")))return null;return{name:i,path:s,schedule:o?.[1],handler:`${i}.handle`,enabled:c?.[1]!=="false",retries:u?parseInt(u[1],10):void 0,backoff:g?.[1],timeout:d?parseInt(d[1],10):void 0,description:y?.[1]}}static async discoverActions(n){let{projectRoot:i,actionsPath:s="app/Actions"}=n,o=`${i}/${s}`,c=[];try{let u=await import("node:fs"),d=await import("node:path");if(!u.existsSync(o))return[];let g=u.readdirSync(o).filter((y)=>y.endsWith(".ts")&&!y.startsWith("_"));for(let y of g){let h=d.join(o,y),A=y.replace(".ts",""),C=u.readFileSync(h,"utf-8"),v=xt.parseActionMetadata(C,A,h);if(v)c.push(v)}}catch{return[]}return c}static parseActionMetadata(n,i,s){if(!(n.includes("export async function handle")||n.includes("export function handle")||n.includes("export default")))return null;let c=n.match(/export\s + const\s + description\s*=\s*['"`]([^'"`]+)['"`]/)||n.match(/description:\s*['"`]([^'"`]+)['"`]/);return{name:i,path:s,handler:`${i}.handle`,description:c?.[1]}}static generateScheduledJobResources(n){let{slug:i,environment:s,jobs:o,taskDefinitionArn:c,clusterArn:u,subnets:d,securityGroups:g=[],roleArn:y,containerName:h="app"}=n,A={},C=0;for(let v of o){if(!v.schedule||!v.enabled)continue;let{rule:T,logicalId:R}=X.createScheduledJob({slug:i,environment:s,schedule:v.schedule,jobClass:v.name,taskDefinitionArn:c,clusterArn:u,subnets:d,securityGroups:g,roleArn:y,containerName:h});A[R]=T,C++}return{rules:A,count:C}}static generateJobRunnerScript(){return`#!/usr/bin/env bun
1627
1627
  /**
1628
1628
  * Job Runner Script
1629
1629
  * This script is invoked by ECS scheduled tasks to run jobs
@@ -1668,7 +1668,7 @@ catch (error) {
1668
1668
  }
1669
1669
 
1670
1670
  run()
1671
- `}static async generateJobManifest(n){let i=await Bt.discoverJobs(n),s=i.filter((o)=>o.schedule&&o.enabled);return{jobs:i,scheduledCount:s.length,totalCount:i.length}}}var JI={loadJobs:Bt.discoverJobs,loadActions:Bt.discoverActions,generateScheduledJobs:Bt.generateScheduledJobResources,generateRunner:Bt.generateJobRunnerScript,paths:{jobs:"app/Jobs",actions:"app/Actions",runner:"app/Jobs/runner.ts"}};var an=`
1671
+ `}static async generateJobManifest(n){let i=await xt.discoverJobs(n),s=i.filter((o)=>o.schedule&&o.enabled);return{jobs:i,scheduledCount:s.length,totalCount:i.length}}}var cb={loadJobs:xt.discoverJobs,loadActions:xt.discoverActions,generateScheduledJobs:xt.generateScheduledJobResources,generateRunner:xt.generateJobRunnerScript,paths:{jobs:"app/Jobs",actions:"app/Actions",runner:"app/Jobs/runner.ts"}};var Cn=`
1672
1672
  const { DynamoDBClient, UpdateItemCommand } = require('@aws-sdk/client-dynamodb');
1673
1673
  const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');
1674
1674
 
@@ -1791,7 +1791,7 @@ catch (error) {
1791
1791
 
1792
1792
  return { statusCode: 200, body: 'OK' };
1793
1793
  };
1794
- `;var on=`
1794
+ `;var vn=`
1795
1795
  const { DynamoDBClient, PutItemCommand, DeleteItemCommand } = require('@aws-sdk/client-dynamodb');
1796
1796
  const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');
1797
1797
 
@@ -1943,7 +1943,7 @@ catch (error) {
1943
1943
 
1944
1944
  return { statusCode: 200, body: 'OK' };
1945
1945
  };
1946
- `;var Ct=`
1946
+ `;var Tt=`
1947
1947
  const { PinpointClient, SendMessagesCommand } = require('@aws-sdk/client-pinpoint');
1948
1948
  const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');
1949
1949
  const { DynamoDBClient, PutItemCommand } = require('@aws-sdk/client-dynamodb');
@@ -2107,7 +2107,7 @@ function resolveTemplate(template, data) {
2107
2107
  }
2108
2108
  return result;
2109
2109
  }
2110
- `,Pr=`
2110
+ `,Gr=`
2111
2111
  const { PinpointClient, SendMessagesCommand } = require('@aws-sdk/client-pinpoint');
2112
2112
  const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');
2113
2113
  const { DynamoDBClient, PutItemCommand } = require('@aws-sdk/client-dynamodb');
@@ -2271,14 +2271,14 @@ function resolveTemplate(template, data) {
2271
2271
  }
2272
2272
  return result;
2273
2273
  }
2274
- `;class X{static LambdaCode={send:Ct,receive:on,deliveryStatus:an};static createPinpointApp(n){return{[`${n.slug}PinpointApp`]:{Type:"AWS::Pinpoint::App",Properties:{Name:n.name||`${n.slug}-sms`}}}}static createSmsChannel(n){let i={ApplicationId:n.applicationId,Enabled:n.enabled!==!1};if(n.senderId)i.SenderId=n.senderId;if(n.shortCode)i.ShortCode=n.shortCode;return{[`${n.slug}SmsChannel`]:{Type:"AWS::Pinpoint::SMSChannel",Properties:i}}}static createSmsLambdaRole(n){return{[`${n.slug}SmsLambdaRole`]:{Type:"AWS::IAM::Role",Properties:{RoleName:`${n.slug}-sms-lambda-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:"SmsLambdaPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["mobiletargeting:SendMessages","mobiletargeting:GetSmsChannel"],Resource:"*"},{Effect:"Allow",Action:["sns:Publish"],Resource:"*"},{Effect:"Allow",Action:["dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:GetItem","dynamodb:DeleteItem"],Resource:"*"}]}}]}}}}static createSendLambda(n){return{[`${n.slug}SmsSendLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-send`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:X.LambdaCode.send},Environment:{Variables:{PINPOINT_APP_ID:n.pinpointAppId,MESSAGE_LOG_TABLE:n.messageLogTable||"",SMS_SENDER_ID:n.senderId||"",SMS_ORIGINATION_NUMBER:n.originationNumber||""}}}}}}static createReceiveLambda(n){return{[`${n.slug}SmsReceiveLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-receive`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:X.LambdaCode.receive},Environment:{Variables:{OPT_OUT_TABLE:n.optOutTable||"",MESSAGE_LOG_TABLE:n.messageLogTable||"",NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createDeliveryStatusLambda(n){return{[`${n.slug}SmsDeliveryStatusLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-delivery-status`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:X.LambdaCode.deliveryStatus},Environment:{Variables:{MESSAGE_LOG_TABLE:n.messageLogTable||"",NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createMessageLogTable(n){return{[`${n.slug}SmsMessageLogTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-sms-messages`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createOptOutTable(n){return{[`${n.slug}SmsOptOutTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-sms-optouts`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}]}}}}static createNotificationTopic(n){return{[`${n.slug}SmsNotificationTopic`]:{Type:"AWS::SNS::Topic",Properties:{TopicName:`${n.slug}-sms-notifications`}}}}static createCompleteSetup(n){let i={},s={};Object.assign(i,X.createPinpointApp({slug:n.slug})),Object.assign(i,X.createSmsChannel({slug:n.slug,applicationId:{Ref:`${n.slug}PinpointApp`},senderId:n.senderId})),Object.assign(i,X.createSmsLambdaRole({slug:n.slug})),Object.assign(i,X.createMessageLogTable({slug:n.slug})),Object.assign(i,X.createOptOutTable({slug:n.slug})),Object.assign(i,X.createNotificationTopic({slug:n.slug}));let o={"Fn::GetAtt":[`${n.slug}SmsLambdaRole`,"Arn"]},c={Ref:`${n.slug}PinpointApp`},u={Ref:`${n.slug}SmsMessageLogTable`},d={Ref:`${n.slug}SmsOptOutTable`},g={Ref:`${n.slug}SmsNotificationTopic`};if(Object.assign(i,X.createSendLambda({slug:n.slug,roleArn:o,pinpointAppId:c,messageLogTable:u,senderId:n.senderId,originationNumber:n.originationNumber})),n.twoWayEnabled)Object.assign(i,X.createReceiveLambda({slug:n.slug,roleArn:o,optOutTable:d,messageLogTable:u,notificationTopicArn:g,webhookUrl:n.webhookUrl}));return Object.assign(i,X.createDeliveryStatusLambda({slug:n.slug,roleArn:o,messageLogTable:u,notificationTopicArn:g,webhookUrl:n.webhookUrl})),s[`${n.slug}PinpointAppId`]={Description:"Pinpoint application ID",Value:{Ref:`${n.slug}PinpointApp`}},s[`${n.slug}SmsSendLambdaArn`]={Description:"SMS send Lambda ARN",Value:{"Fn::GetAtt":[`${n.slug}SmsSendLambda`,"Arn"]}},s[`${n.slug}SmsNotificationTopicArn`]={Description:"SMS notification topic ARN",Value:{Ref:`${n.slug}SmsNotificationTopic`}},s[`${n.slug}SmsMessageLogTableName`]={Description:"SMS message log table name",Value:{Ref:`${n.slug}SmsMessageLogTable`}},{resources:i,outputs:s}}}function vt(n){return n.replace(/[^a-zA-Z0-9]/g," ").trim().split(/\s+/).map((o)=>o.charAt(0).toUpperCase()+o.slice(1)).join("")||"User"}function Er(n,i){let s=(n||i).replace(/^\/+|\/+$/g,"");if(!s||s.split("/").includes(".."))throw Error(`sftp: invalid homeDirectory for user ${i}`);return s}function wr(n){let i=n.storage;if(i?.type==="efs"){let o="fileSystemId"in i?i.fileSystemId:void 0;if(!o||typeof o==="string"&&!o.trim())throw Error("sftp: EFS storage requires fileSystemId, or a fileSystem name defined in infrastructure.fileSystem");return{type:"efs",fileSystemId:o,posixProfile:i.posixProfile}}let s=(i?.type==="s3"?i.bucket??n.bucket:n.bucket)?.trim();if(!s)throw Error("sftp: S3 storage requires bucket, or a storageBucket name defined in infrastructure.storage");return{type:"s3",bucket:s}}function Ir(n,i,s){let o=i.posixProfile??s;if(!o)throw Error(`sftp: user ${n} requires a posixProfile (uid/gid) on an EFS-backed server`);for(let c of[o.uid,o.gid,...o.secondaryGids??[]])if(!Number.isInteger(c)||c<0||c>4294967295)throw Error(`sftp: user ${n} has an invalid posixProfile id ${c}`);return{Uid:o.uid,Gid:o.gid,...o.secondaryGids?.length?{SecondaryGids:o.secondaryGids}:{}}}function Dr(n,i){return typeof n==="string"?`/${n}/${i}`:{"Fn::Sub":[`/\${FileSystemId}/${i}`,{FileSystemId:n}]}}function Nr(n){return typeof n==="string"?{"Fn::Sub":"arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}".replace("${FileSystemId}",n)}:{"Fn::Sub":["arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}",{FileSystemId:n}]}}class pl{static create(n){let i=wr(n),s=i.type==="efs"?"EFS":"S3",o=n.endpointType??"PUBLIC";if(o==="VPC"&&(!n.endpointDetails?.vpcId||!n.endpointDetails.subnetIds.length))throw Error("sftp: VPC endpoints require endpointDetails.vpcId and at least one subnet");let c=`${vt(n.slug)}${vt(n.environment)}Sftp`,u=`${c}Server`,d={},g;if(n.logging!==!1){let y=`${c}LoggingRole`;d[y]={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"transfer.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"TransferLogging",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:DescribeLogStreams","logs:PutLogEvents"],Resource:"arn:aws:logs:*:*:log-group:/aws/transfer/*"}]}}]}},g={"Fn::GetAtt":[y,"Arn"]}}d[u]={Type:"AWS::Transfer::Server",Properties:{Domain:s,EndpointType:o,IdentityProviderType:"SERVICE_MANAGED",Protocols:["SFTP"],...o==="VPC"?{EndpointDetails:{VpcId:n.endpointDetails.vpcId,SubnetIds:n.endpointDetails.subnetIds,...n.endpointDetails.securityGroupIds?.length?{SecurityGroupIds:n.endpointDetails.securityGroupIds}:{},...n.endpointDetails.addressAllocationIds?.length?{AddressAllocationIds:n.endpointDetails.addressAllocationIds}:{}}}:{},...n.securityPolicyName?{SecurityPolicyName:n.securityPolicyName}:{},...g?{LoggingRole:g}:{},Tags:[{Key:"Project",Value:n.slug},{Key:"Environment",Value:n.environment},{Key:"ManagedBy",Value:"ts-cloud"}]}};for(let[y,h]of Object.entries(n.users)){if(!/^[a-zA-Z0-9_.@-]{3,100}$/.test(y))throw Error(`sftp: invalid username ${y}`);if(!h.sshPublicKeys.length)throw Error(`sftp: user ${y} requires at least one SSH public key`);let A=vt(y),C=Er(h.homeDirectory,y),v=`${c}${A}User`,T=h.roleArn;if(!T){let R=`${c}${A}Role`,P;if(i.type==="efs")P=[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:DescribeMountTargets"],Resource:Nr(i.fileSystemId)}];else{let I=`arn:aws:s3:::${i.bucket}`;P=[{Effect:"Allow",Action:["s3:ListBucket","s3:GetBucketLocation"],Resource:I,Condition:{StringLike:{"s3:prefix":[C,`${C}/*`]}}},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:GetObjectVersion"],Resource:`${I}/${C}/*`}]}d[R]={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"transfer.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"SftpHomeDirectory",PolicyDocument:{Version:"2012-10-17",Statement:P}}]}},T={"Fn::GetAtt":[R,"Arn"]}}d[v]={Type:"AWS::Transfer::User",DependsOn:[u],Properties:{ServerId:{Ref:u},UserName:y,Role:T,HomeDirectoryType:"PATH",HomeDirectory:i.type==="efs"?Dr(i.fileSystemId,C):`/${i.bucket}/${C}`,...i.type==="efs"?{PosixProfile:Ir(y,h,i.posixProfile)}:{},SshPublicKeys:h.sshPublicKeys}}}return{resources:d,serverLogicalId:u,domain:s}}}class Oe{static createBedrockRole(n,i){let{slug:s,environment:o,name:c,models:u=["*"],allowStreaming:d=!0}=i,g=c||r({slug:s,environment:o,resourceType:"bedrock-role"}),y=t(g),h=["bedrock:InvokeModel"];if(d)h.push("bedrock:InvokeModelWithResponseStream");let A=u.map((v)=>v==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${v}`);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:g,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:n},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:`${g}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:h,Resource:A}]}}],Tags:[{Key:"Name",Value:g},{Key:"Environment",Value:o}]}},logicalId:y}}static createBedrockPolicy(n){let{slug:i,environment:s,name:o,models:c=["*"],allowInvoke:u=!0,allowStreaming:d=!0,allowAsync:g=!1}=n,y=o||r({slug:i,environment:s,resourceType:"bedrock-policy"}),h=t(y),A=[];if(u)A.push("bedrock:InvokeModel");if(d)A.push("bedrock:InvokeModelWithResponseStream");if(g)A.push("bedrock:InvokeModelAsync");let C=c.map((T)=>T==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${T}`);return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:y,PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"BedrockModelInvocation",Effect:"Allow",Action:A,Resource:C}]}}},logicalId:h}}static enableBedrockForLambda(n){return Oe.createBedrockRole("lambda.amazonaws.com",n)}static enableBedrockForEcs(n){return Oe.createBedrockRole("ecs-tasks.amazonaws.com",n)}static enableBedrockForEc2(n){return Oe.createBedrockRole("ec2.amazonaws.com",n)}static addBedrockPermissions(n,i=["*"],s=!0){let o=["bedrock:InvokeModel"];if(s)o.push("bedrock:InvokeModelWithResponseStream");let c=i.map((u)=>u==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${u}`);if(!n.Properties.Policies)n.Properties.Policies=[];return n.Properties.Policies.push({PolicyName:"bedrock-permissions",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:o,Resource:c}]}}),n}static Models={Claude3_5_Sonnet:"anthropic.claude-3-5-sonnet-20241022-v2:0",Claude3_5_Haiku:"anthropic.claude-3-5-haiku-20241022-v1:0",Claude3_Opus:"anthropic.claude-3-opus-20240229-v1:0",Claude3_Sonnet:"anthropic.claude-3-sonnet-20240229-v1:0",Claude3_Haiku:"anthropic.claude-3-haiku-20240307-v1:0",TitanTextG1Express:"amazon.titan-text-express-v1",TitanTextG1Lite:"amazon.titan-text-lite-v1",TitanEmbedG1Text:"amazon.titan-embed-text-v1",TitanImageG1:"amazon.titan-image-generator-v1",JurassicUltra:"ai21.j2-ultra-v1",JurassicMid:"ai21.j2-mid-v1",CommandText:"cohere.command-text-v14",CommandLight:"cohere.command-light-text-v14",EmbedEnglish:"cohere.embed-english-v3",EmbedMultilingual:"cohere.embed-multilingual-v3",Llama3_2_1B:"meta.llama3-2-1b-instruct-v1:0",Llama3_2_3B:"meta.llama3-2-3b-instruct-v1:0",Llama3_2_11B:"meta.llama3-2-11b-instruct-v1:0",Llama3_2_90B:"meta.llama3-2-90b-instruct-v1:0",Llama3_1_8B:"meta.llama3-1-8b-instruct-v1:0",Llama3_1_70B:"meta.llama3-1-70b-instruct-v1:0",Llama3_1_405B:"meta.llama3-1-405b-instruct-v1:0",Mistral7B:"mistral.mistral-7b-instruct-v0:2",Mixtral8x7B:"mistral.mixtral-8x7b-instruct-v0:1",MistralLarge:"mistral.mistral-large-2402-v1:0",StableDiffusionXL:"stability.stable-diffusion-xl-v1"};static ModelGroups={AllClaude:["anthropic.claude-3-5-sonnet-20241022-v2:0","anthropic.claude-3-5-haiku-20241022-v1:0","anthropic.claude-3-opus-20240229-v1:0","anthropic.claude-3-sonnet-20240229-v1:0","anthropic.claude-3-haiku-20240307-v1:0"],AllTitan:["amazon.titan-text-express-v1","amazon.titan-text-lite-v1","amazon.titan-embed-text-v1","amazon.titan-image-generator-v1"],AllLlama:["meta.llama3-2-1b-instruct-v1:0","meta.llama3-2-3b-instruct-v1:0","meta.llama3-2-11b-instruct-v1:0","meta.llama3-2-90b-instruct-v1:0","meta.llama3-1-8b-instruct-v1:0","meta.llama3-1-70b-instruct-v1:0","meta.llama3-1-405b-instruct-v1:0"],TextModels:["anthropic.claude-3-5-sonnet-20241022-v2:0","anthropic.claude-3-5-haiku-20241022-v1:0","amazon.titan-text-express-v1","meta.llama3-2-11b-instruct-v1:0","mistral.mistral-7b-instruct-v0:2"],EmbeddingModels:["amazon.titan-embed-text-v1","cohere.embed-english-v3","cohere.embed-multilingual-v3"],ImageModels:["amazon.titan-image-generator-v1","stability.stable-diffusion-xl-v1"]}}class ur{static createPostgres(n){return ur.createRDSInstance("postgres","16.2",n)}static createMysql(n){return ur.createRDSInstance("mysql","8.0.35",n)}static createRDSInstance(n,i,s){let{slug:o,environment:c,instanceClass:u="db.t3.micro",allocatedStorage:d=20,storageType:g="gp3",masterUsername:y="admin",masterPassword:h,databaseName:A,subnetIds:C,securityGroupIds:v,encrypted:T=!0,kmsKeyId:R,multiAz:P=!1,backupRetentionDays:I=7,publiclyAccessible:M=!1,enableCloudwatchLogs:L=!0,deletionProtection:N=!0}=s,O=r({slug:o,environment:c,resourceType:`${n}-db`}),B=t(O),F,U;if(C&&C.length>0){let H=r({slug:o,environment:c,resourceType:"db-subnet-group"});U=t(H),F={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupName:H,DBSubnetGroupDescription:`Subnet group for ${O}`,SubnetIds:C,Tags:[{Key:"Name",Value:H},{Key:"Environment",Value:c}]}}}let j={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:O,DBInstanceClass:u,Engine:n,EngineVersion:i,MasterUsername:y,MasterUserPassword:h,AllocatedStorage:d,StorageType:g,StorageEncrypted:T,MultiAZ:P,BackupRetentionPeriod:I,PubliclyAccessible:M,DeletionProtection:N,Tags:[{Key:"Name",Value:O},{Key:"Environment",Value:c}]}};if(A)j.Properties.DBName=A;if(R)j.Properties.KmsKeyId=R;if(U)j.Properties.DBSubnetGroupName=x.Ref(U);if(v&&v.length>0)j.Properties.VPCSecurityGroups=v;if(L)j.Properties.EnableCloudwatchLogsExports=n==="postgres"?["postgresql"]:["error","general","slowquery"];return{dbInstance:j,subnetGroup:F,logicalId:B,subnetGroupId:U}}static createReadReplica(n,i){let{slug:s,environment:o,instanceClass:c="db.t3.micro",securityGroupIds:u,publiclyAccessible:d=!1}=i,g=r({slug:s,environment:o,resourceType:"db-replica"}),y=t(g),h={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:g,DBInstanceClass:c,SourceDBInstanceIdentifier:x.Ref(n),PubliclyAccessible:d,Tags:[{Key:"Name",Value:g},{Key:"Environment",Value:o},{Key:"Type",Value:"ReadReplica"}]}};if(u&&u.length>0)h.Properties.VPCSecurityGroups=u;return{replica:h,logicalId:y}}static createParameterGroup(n,i,s){let{slug:o,environment:c,parameters:u={}}=s,d=r({slug:o,environment:c,resourceType:"db-params"}),g=t(d),y=n==="postgres"?`postgres${i.split(".")[0]}`:`mysql${i.split(".")[0]}.${i.split(".")[1]}`;return{parameterGroup:{Type:"AWS::RDS::DBParameterGroup",Properties:{DBParameterGroupName:d,Description:`Parameter group for ${d}`,Family:y,Parameters:u,Tags:[{Key:"Name",Value:d},{Key:"Environment",Value:c}]}},logicalId:g}}static enableBackup(n,i=7){return n.Properties.BackupRetentionPeriod=i,n}static createTable(n){let{slug:i,environment:s,tableName:o,partitionKey:c,sortKey:u,billingMode:d="PAY_PER_REQUEST",readCapacity:g=5,writeCapacity:y=5,streamEnabled:h=!1,streamViewType:A="NEW_AND_OLD_IMAGES",encrypted:C=!0,kmsKeyId:v,pointInTimeRecovery:T=!0,ttlAttribute:R}=n,P=o||r({slug:i,environment:s,resourceType:"table"}),I=t(P),M=[{AttributeName:c.name,AttributeType:c.type}];if(u)M.push({AttributeName:u.name,AttributeType:u.type});let L=[{AttributeName:c.name,KeyType:"HASH"}];if(u)L.push({AttributeName:u.name,KeyType:"RANGE"});let N={Type:"AWS::DynamoDB::Table",Properties:{TableName:P,BillingMode:d,AttributeDefinitions:M,KeySchema:L,Tags:[{Key:"Name",Value:P},{Key:"Environment",Value:s}]}};if(d==="PROVISIONED")N.Properties.ProvisionedThroughput={ReadCapacityUnits:g,WriteCapacityUnits:y};if(h)N.Properties.StreamSpecification={StreamViewType:A};if(C)N.Properties.SSESpecification={SSEEnabled:!0,SSEType:v?"KMS":"AES256",KMSMasterKeyId:v};if(T)N.Properties.PointInTimeRecoverySpecification={PointInTimeRecoveryEnabled:!0};if(R)N.Properties.TimeToLiveSpecification={AttributeName:R,Enabled:!0};return{table:N,logicalId:I}}static addGlobalSecondaryIndex(n,i){let{indexName:s,partitionKey:o,sortKey:c,projectionType:u="ALL",nonKeyAttributes:d,readCapacity:g=5,writeCapacity:y=5}=i;if(!n.Properties.AttributeDefinitions.some((C)=>C.AttributeName===o.name))n.Properties.AttributeDefinitions.push({AttributeName:o.name,AttributeType:o.type});if(c&&!n.Properties.AttributeDefinitions.some((C)=>C.AttributeName===c.name))n.Properties.AttributeDefinitions.push({AttributeName:c.name,AttributeType:c.type});let h=[{AttributeName:o.name,KeyType:"HASH"}];if(c)h.push({AttributeName:c.name,KeyType:"RANGE"});let A={IndexName:s,KeySchema:h,Projection:{ProjectionType:u,NonKeyAttributes:u==="INCLUDE"?d:void 0},ProvisionedThroughput:void 0};if(n.Properties.BillingMode==="PROVISIONED")A.ProvisionedThroughput={ReadCapacityUnits:g,WriteCapacityUnits:y};if(!n.Properties.GlobalSecondaryIndexes)n.Properties.GlobalSecondaryIndexes=[];return n.Properties.GlobalSecondaryIndexes.push(A),n}static enableStreams(n,i="NEW_AND_OLD_IMAGES"){return n.Properties.StreamSpecification={StreamViewType:i},n}static InstanceClasses={T3_Micro:"db.t3.micro",T3_Small:"db.t3.small",T3_Medium:"db.t3.medium",T3_Large:"db.t3.large",T4g_Micro:"db.t4g.micro",T4g_Small:"db.t4g.small",T4g_Medium:"db.t4g.medium",M5_Large:"db.m5.large",M5_XLarge:"db.m5.xlarge",M5_2XLarge:"db.m5.2xlarge",R5_Large:"db.r5.large",R5_XLarge:"db.r5.xlarge",R5_2XLarge:"db.r5.2xlarge"}}class qo{static createRedis(n){let{slug:i,environment:s,nodeType:o="cache.t3.micro",engineVersion:c="7.1",port:u=6379,subnetIds:d,securityGroupIds:g,numCacheClusters:y=2,automaticFailover:h=!0,multiAz:A=!0,clusterMode:C=!1,numNodeGroups:v=1,replicasPerNodeGroup:T=1,atRestEncryption:R=!0,transitEncryption:P=!0,authToken:I,kmsKeyId:M,snapshotRetentionDays:L=7,snapshotWindow:N,maintenanceWindow:O}=n,B=r({slug:i,environment:s,resourceType:"redis"}),F=t(B),U,j;if(d&&d.length>0){let z=r({slug:i,environment:s,resourceType:"cache-subnet-group"});j=t(z),U={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:z,Description:`Subnet group for ${B}`,SubnetIds:d,Tags:[{Key:"Name",Value:z},{Key:"Environment",Value:s}]}}}let H={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:B,ReplicationGroupDescription:`Redis cluster for ${i} ${s}`,Engine:"redis",EngineVersion:c,CacheNodeType:o,Port:u,AutomaticFailoverEnabled:h,MultiAZEnabled:A,AtRestEncryptionEnabled:R,TransitEncryptionEnabled:P,SnapshotRetentionLimit:L,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:B},{Key:"Environment",Value:s}]}};if(C)H.Properties.NumNodeGroups=v,H.Properties.ReplicasPerNodeGroup=T;else H.Properties.NumCacheClusters=y;if(I)H.Properties.AuthToken=I;if(M)H.Properties.KmsKeyId=M;if(j)H.Properties.CacheSubnetGroupName=x.Ref(j);if(g&&g.length>0)H.Properties.SecurityGroupIds=g;if(N)H.Properties.SnapshotWindow=N;if(O)H.Properties.PreferredMaintenanceWindow=O;return{replicationGroup:H,subnetGroup:U,logicalId:F,subnetGroupId:j}}static createMemcached(n){let{slug:i,environment:s,nodeType:o="cache.t3.micro",engineVersion:c="1.6.22",port:u=11211,numCacheNodes:d=2,subnetIds:g,securityGroupIds:y,azMode:h="cross-az",preferredAzs:A,maintenanceWindow:C}=n,v=r({slug:i,environment:s,resourceType:"memcached"}),T=t(v),R,P;if(g&&g.length>0){let M=r({slug:i,environment:s,resourceType:"cache-subnet-group"});P=t(M),R={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:M,Description:`Subnet group for ${v}`,SubnetIds:g,Tags:[{Key:"Name",Value:M},{Key:"Environment",Value:s}]}}}let I={Type:"AWS::ElastiCache::CacheCluster",Properties:{ClusterName:v,CacheNodeType:o,Engine:"memcached",EngineVersion:c,NumCacheNodes:d,Port:u,AZMode:h,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:v},{Key:"Environment",Value:s}]}};if(P)I.Properties.CacheSubnetGroupName=x.Ref(P);if(y&&y.length>0)I.Properties.VpcSecurityGroupIds=y;if(A&&A.length>0)I.Properties.PreferredAvailabilityZones=A;if(C)I.Properties.PreferredMaintenanceWindow=C;return{cluster:I,subnetGroup:R,logicalId:T,subnetGroupId:P}}static enableClusterMode(n,i=3,s=2){return delete n.Properties.NumCacheClusters,n.Properties.NumNodeGroups=i,n.Properties.ReplicasPerNodeGroup=s,n}static createRedisParameterGroup(n,i){let{slug:s,environment:o,parameters:c={}}=i,u=r({slug:s,environment:o,resourceType:"redis-params"}),d=t(u);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`redis${n.split(".")[0]}.x`,Description:`Parameter group for ${u}`,Properties:c,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:o}]}},logicalId:d}}static createMemcachedParameterGroup(n,i){let{slug:s,environment:o,parameters:c={}}=i,u=r({slug:s,environment:o,resourceType:"memcached-params"}),d=t(u);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`memcached${n.split(".")[0]}.${n.split(".")[1]}`,Description:`Parameter group for ${u}`,Properties:c,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:o}]}},logicalId:d}}static NodeTypes={T3_Micro:"cache.t3.micro",T3_Small:"cache.t3.small",T3_Medium:"cache.t3.medium",T4g_Micro:"cache.t4g.micro",T4g_Small:"cache.t4g.small",T4g_Medium:"cache.t4g.medium",M5_Large:"cache.m5.large",M5_XLarge:"cache.m5.xlarge",M5_2XLarge:"cache.m5.2xlarge",R5_Large:"cache.r5.large",R5_XLarge:"cache.r5.xlarge",R5_2XLarge:"cache.r5.2xlarge",R5_4XLarge:"cache.r5.4xlarge",R6g_Large:"cache.r6g.large",R6g_XLarge:"cache.r6g.xlarge",R6g_2XLarge:"cache.r6g.2xlarge"}}class ue{static createUser(n){let{slug:i,environment:s,userName:o,groups:c,managedPolicyArns:u}=n,d=o||r({slug:i,environment:s,resourceType:"user"}),g=t(d),y={Type:"AWS::IAM::User",Properties:{UserName:d,Tags:[{Key:"Name",Value:d},{Key:"Environment",Value:s}]}};if(c&&c.length>0)y.Properties.Groups=c;if(u&&u.length>0)y.Properties.ManagedPolicyArns=u;return{user:y,logicalId:g}}static createRole(n){let{slug:i,environment:s,roleName:o,servicePrincipal:c,awsPrincipal:u,managedPolicyArns:d}=n,g=o||r({slug:i,environment:s,resourceType:"role"}),y=t(g),h={};if(c)h.Service=c;if(u)h.AWS=u;let A={Type:"AWS::IAM::Role",Properties:{RoleName:g,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:h,Action:"sts:AssumeRole"}]},Tags:[{Key:"Name",Value:g},{Key:"Environment",Value:s}]}};if(d&&d.length>0)A.Properties.ManagedPolicyArns=d;return{role:A,logicalId:y}}static createGroup(n){let{slug:i,environment:s,groupName:o,managedPolicyArns:c}=n,u=o||r({slug:i,environment:s,resourceType:"group"}),d=t(u),g={Type:"AWS::IAM::Group",Properties:{GroupName:u}};if(c&&c.length>0)g.Properties.ManagedPolicyArns=c;return{group:g,logicalId:d}}static createPolicy(n){let{slug:i,environment:s,policyName:o,description:c,statements:u}=n,d=o||r({slug:i,environment:s,resourceType:"policy"}),g=t(d),y=u.map((A)=>({Sid:A.sid,Effect:A.effect||"Allow",Action:A.actions,Resource:A.resources,Condition:A.conditions}));return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:d,Description:c||`Managed policy for ${d}`,PolicyDocument:{Version:"2012-10-17",Statement:y}}},logicalId:g}}static attachPolicyToRole(n,i){if(!n.Properties.ManagedPolicyArns)n.Properties.ManagedPolicyArns=[];if(!n.Properties.ManagedPolicyArns.includes(i))n.Properties.ManagedPolicyArns.push(i);return n}static attachPolicyToUser(n,i){if(!n.Properties.ManagedPolicyArns)n.Properties.ManagedPolicyArns=[];if(!n.Properties.ManagedPolicyArns.includes(i))n.Properties.ManagedPolicyArns.push(i);return n}static attachPolicyToGroup(n,i){if(!n.Properties.ManagedPolicyArns)n.Properties.ManagedPolicyArns=[];if(!n.Properties.ManagedPolicyArns.includes(i))n.Properties.ManagedPolicyArns.push(i);return n}static addInlinePolicyToRole(n,i,s){if(!n.Properties.Policies)n.Properties.Policies=[];let o=s.map((c)=>({Effect:c.effect||"Allow",Action:c.actions,Resource:c.resources}));return n.Properties.Policies.push({PolicyName:i,PolicyDocument:{Version:"2012-10-17",Statement:o}}),n}static addInlinePolicyToUser(n,i,s){if(!n.Properties.Policies)n.Properties.Policies=[];let o=s.map((c)=>({Effect:c.effect||"Allow",Action:c.actions,Resource:c.resources}));return n.Properties.Policies.push({PolicyName:i,PolicyDocument:{Version:"2012-10-17",Statement:o}}),n}static createAccessKey(n,i){let{slug:s,environment:o,status:c="Active"}=i,u=r({slug:s,environment:o,resourceType:"access-key"}),d=t(u);return{accessKey:{Type:"AWS::IAM::AccessKey",Properties:{UserName:x.Ref(n),Status:c}},logicalId:d}}static createInstanceProfile(n,i){let{slug:s,environment:o,profileName:c}=i,u=c||r({slug:s,environment:o,resourceType:"instance-profile"}),d=t(u);return{instanceProfile:{Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:u,Roles:[x.Ref(n)]}},logicalId:d}}static ManagedPolicies={AdministratorAccess:"arn:aws:iam::aws:policy/AdministratorAccess",PowerUserAccess:"arn:aws:iam::aws:policy/PowerUserAccess",ReadOnlyAccess:"arn:aws:iam::aws:policy/ReadOnlyAccess",S3FullAccess:"arn:aws:iam::aws:policy/AmazonS3FullAccess",S3ReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess",DynamoDBFullAccess:"arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess",DynamoDBReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonDynamoDBReadOnlyAccess",RDSFullAccess:"arn:aws:iam::aws:policy/AmazonRDSFullAccess",RDSReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonRDSReadOnlyAccess",LambdaFullAccess:"arn:aws:iam::aws:policy/AWSLambda_FullAccess",LambdaReadOnlyAccess:"arn:aws:iam::aws:policy/AWSLambda_ReadOnlyAccess",LambdaBasicExecutionRole:"arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",LambdaVPCAccessExecutionRole:"arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole",EC2FullAccess:"arn:aws:iam::aws:policy/AmazonEC2FullAccess",EC2ReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess",EC2ContainerRegistryReadOnly:"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly",EC2ContainerRegistryPowerUser:"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPowerUser",ECSTaskExecutionRole:"arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy",ECSFullAccess:"arn:aws:iam::aws:policy/AmazonECS_FullAccess",CloudWatchFullAccess:"arn:aws:iam::aws:policy/CloudWatchFullAccess",CloudWatchLogsFullAccess:"arn:aws:iam::aws:policy/CloudWatchLogsFullAccess",SESFullAccess:"arn:aws:iam::aws:policy/AmazonSESFullAccess",SNSFullAccess:"arn:aws:iam::aws:policy/AmazonSNSFullAccess",SQSFullAccess:"arn:aws:iam::aws:policy/AmazonSQSFullAccess",SecretsManagerReadWrite:"arn:aws:iam::aws:policy/SecretsManagerReadWrite"};static ServicePrincipals={Lambda:"lambda.amazonaws.com",EC2:"ec2.amazonaws.com",ECS:"ecs.amazonaws.com",ECSTaskExecution:"ecs-tasks.amazonaws.com",APIGateway:"apigateway.amazonaws.com",Events:"events.amazonaws.com",States:"states.amazonaws.com",CodeBuild:"codebuild.amazonaws.com",CodeDeploy:"codedeploy.amazonaws.com",CloudFormation:"cloudformation.amazonaws.com"};static createCiCdUser(n){let{slug:i,environment:s,permissions:o,createAccessKey:c=!0}=n,u={},d=[];if(o.s3Buckets&&o.s3Buckets.length>0)d.push({sid:"S3Access",actions:["s3:GetBucketLocation","s3:ListBucket","s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucketMultipartUploads","s3:AbortMultipartUpload"],resources:[...o.s3Buckets,...o.s3Buckets.map((T)=>`${T}/*`)]});if(o.cloudFrontDistributions&&o.cloudFrontDistributions.length>0)d.push({sid:"CloudFrontAccess",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations","cloudfront:GetDistribution"],resources:o.cloudFrontDistributions});if(o.ecrRepositories&&o.ecrRepositories.length>0)d.push({sid:"ECRAccess",actions:["ecr:GetAuthorizationToken","ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:GetRepositoryPolicy","ecr:DescribeRepositories","ecr:ListImages","ecr:DescribeImages","ecr:BatchGetImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:PutImage"],resources:o.ecrRepositories}),d.push({sid:"ECRLogin",actions:["ecr:GetAuthorizationToken"],resources:"*"});if(o.ecsServices&&o.ecsServices.length>0)d.push({sid:"ECSAccess",actions:["ecs:DescribeServices","ecs:DescribeTaskDefinition","ecs:DescribeTasks","ecs:ListTasks","ecs:RegisterTaskDefinition","ecs:UpdateService","ecs:RunTask","ecs:StopTask"],resources:o.ecsServices}),d.push({sid:"ECSTaskDefinitions",actions:["ecs:RegisterTaskDefinition","ecs:DeregisterTaskDefinition"],resources:"*"}),d.push({sid:"ECSPassRole",actions:["iam:PassRole"],resources:"*",conditions:{StringLike:{"iam:PassedToService":"ecs-tasks.amazonaws.com"}}});if(o.cloudFormationStacks&&o.cloudFormationStacks.length>0)d.push({sid:"CloudFormationAccess",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:DescribeStackResources","cloudformation:GetTemplate","cloudformation:ListStackResources","cloudformation:ValidateTemplate"],resources:o.cloudFormationStacks});if(o.lambdaFunctions&&o.lambdaFunctions.length>0)d.push({sid:"LambdaAccess",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion","lambda:UpdateAlias","lambda:CreateAlias"],resources:o.lambdaFunctions});if(o.secretsManagerSecrets&&o.secretsManagerSecrets.length>0)d.push({sid:"SecretsManagerAccess",actions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],resources:o.secretsManagerSecrets});let{policy:g,logicalId:y}=ue.createPolicy({slug:i,environment:s,policyName:r({slug:i,environment:s,resourceType:"cicd-policy"}),description:`CI/CD deployment policy for ${i} (${s})`,statements:d});u[y]=g;let{user:h,logicalId:A}=ue.createUser({slug:i,environment:s,userName:r({slug:i,environment:s,resourceType:"cicd-user"}),managedPolicyArns:[x.Ref(y)]});u[A]=h;let C,v;if(c){let T=ue.createAccessKey(A,{slug:i,environment:s});C=T.accessKey,v=T.logicalId,u[v]=C}return{user:h,accessKey:C,policy:g,userLogicalId:A,accessKeyLogicalId:v,policyLogicalId:y,resources:u}}static createCrossAccountRole(n){let{slug:i,environment:s,trustedAccountIds:o,externalId:c,permissions:u,maxSessionDuration:d=3600}=n,g={},{policy:y,logicalId:h}=ue.createPolicy({slug:i,environment:s,policyName:r({slug:i,environment:s,resourceType:"cross-account-policy"}),description:`Cross-account access policy for ${i} (${s})`,statements:u});g[h]=y;let A=r({slug:i,environment:s,resourceType:"cross-account-role"}),C=t(A),v={};if(c)v.StringEquals={"sts:ExternalId":c};let T={Type:"AWS::IAM::Role",Properties:{RoleName:A,MaxSessionDuration:d,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:o.map((R)=>`arn:aws:iam::${R}:root`)},Action:"sts:AssumeRole",...Object.keys(v).length>0?{Condition:v}:{}}]},ManagedPolicyArns:[x.Ref(h)],Tags:[{Key:"Name",Value:A},{Key:"Environment",Value:s},{Key:"Purpose",Value:"Cross-Account Access"}]}};return g[C]=T,{role:T,policy:y,roleLogicalId:C,policyLogicalId:h,resources:g}}static createCliUser(n){let{slug:i,environment:s,permissions:o="readonly"}=n,c={},u=[],d=[];switch(o){case"readonly":d=[ue.ManagedPolicies.ReadOnlyAccess];break;case"deploy":u=[{sid:"S3Deploy",actions:["s3:*"],resources:"*"},{sid:"CloudFrontDeploy",actions:["cloudfront:*"],resources:"*"},{sid:"ECSDeploy",actions:["ecs:*"],resources:"*"},{sid:"ECRDeploy",actions:["ecr:*"],resources:"*"},{sid:"LambdaDeploy",actions:["lambda:*"],resources:"*"},{sid:"CloudFormationDeploy",actions:["cloudformation:*"],resources:"*"},{sid:"IAMPassRole",actions:["iam:PassRole"],resources:"*"}];break;case"admin":d=[ue.ManagedPolicies.AdministratorAccess];break}let g,y;if(u.length>0){let T=ue.createPolicy({slug:i,environment:s,policyName:r({slug:i,environment:s,resourceType:"cli-policy"}),description:`CLI access policy for ${i} (${s})`,statements:u});g=T.policy,y=T.logicalId,c[y]=g,d=[x.Ref(y)]}let{user:h,logicalId:A}=ue.createUser({slug:i,environment:s,userName:r({slug:i,environment:s,resourceType:"cli-user"}),managedPolicyArns:d});c[A]=h;let{accessKey:C,logicalId:v}=ue.createAccessKey(A,{slug:i,environment:s});return c[v]=C,{user:h,accessKey:C,policy:g,userLogicalId:A,accessKeyLogicalId:v,policyLogicalId:y,resources:c}}static CiCdPolicies={s3Deployment:(n)=>[{sid:"S3ListBuckets",actions:["s3:ListBucket","s3:GetBucketLocation"],resources:n},{sid:"S3Objects",actions:["s3:GetObject","s3:PutObject","s3:DeleteObject"],resources:n.map((i)=>`${i}/*`)}],cloudFrontInvalidation:(n)=>[{sid:"CloudFrontInvalidation",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations"],resources:n}],ecsDeployment:()=>[{sid:"ECSServices",actions:["ecs:DescribeServices","ecs:UpdateService","ecs:DescribeTaskDefinition","ecs:RegisterTaskDefinition"],resources:"*"},{sid:"ECSPassRole",actions:["iam:PassRole"],resources:"*",conditions:{StringLike:{"iam:PassedToService":"ecs-tasks.amazonaws.com"}}}],ecrPush:(n)=>[{sid:"ECRAuth",actions:["ecr:GetAuthorizationToken"],resources:"*"},{sid:"ECRPush",actions:["ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:PutImage"],resources:n}],lambdaDeployment:(n)=>[{sid:"LambdaDeploy",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion"],resources:n}],cloudFormationDeployment:(n)=>[{sid:"CloudFormationDeploy",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate"],resources:n}]}}class ml{static createRestApi(n){let{slug:i,environment:s,name:o,description:c,endpointType:u="REGIONAL",binaryMediaTypes:d,compressionSize:g}=n,y=o||r({slug:i,environment:s,resourceType:"rest-api"}),h=t(y),A={Type:"AWS::ApiGateway::RestApi",Properties:{Name:y,Description:c||`REST API for ${i} ${s}`,EndpointConfiguration:{Types:[u]},Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:s}]}};if(d&&d.length>0)A.Properties.BinaryMediaTypes=d;if(g!==void 0)A.Properties.MinimumCompressionSize=g;return{restApi:A,logicalId:h}}static createHttpApi(n){let{slug:i,environment:s,name:o,description:c,corsEnabled:u=!0,corsOrigins:d=["*"],corsMethods:g=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],corsHeaders:y=["*"],corsMaxAge:h=86400,corsAllowCredentials:A=!1}=n,C=o||r({slug:i,environment:s,resourceType:"http-api"}),v=t(C),T={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:C,Description:c||`HTTP API for ${i} ${s}`,ProtocolType:"HTTP",Tags:{Name:C,Environment:s}}};if(u)T.Properties.CorsConfiguration={AllowOrigins:d,AllowMethods:g,AllowHeaders:y,MaxAge:h,AllowCredentials:A};return{httpApi:T,logicalId:v}}static createWebSocketApi(n){let{slug:i,environment:s,name:o,description:c}=n,u=o||r({slug:i,environment:s,resourceType:"ws-api"}),d=t(u);return{webSocketApi:{Type:"AWS::ApiGatewayV2::Api",Properties:{Name:u,Description:c||`WebSocket API for ${i} ${s}`,ProtocolType:"WEBSOCKET",Tags:{Name:u,Environment:s}}},logicalId:d}}static createDeployment(n,i){let{slug:s,environment:o,description:c}=i,u=r({slug:s,environment:o,resourceType:"api-deployment"}),d=t(u);return{deployment:{Type:"AWS::ApiGateway::Deployment",Properties:{RestApiId:x.Ref(n),Description:c||`Deployment for ${u}`}},logicalId:d}}static createStage(n,i,s){let{slug:o,environment:c,stageName:u,description:d,cacheEnabled:g=!1,cacheSize:y="0.5",variables:h,throttling:A}=s,C=r({slug:o,environment:c,resourceType:"api-stage"}),v=t(C),T={Type:"AWS::ApiGateway::Stage",Properties:{StageName:u||c,RestApiId:x.Ref(n),DeploymentId:x.Ref(i),Description:d,CacheClusterEnabled:g,Tags:[{Key:"Name",Value:C},{Key:"Environment",Value:c}]}};if(g)T.Properties.CacheClusterSize=y;if(h)T.Properties.Variables=h;if(A)T.Properties.MethodSettings=[{HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:A.burstLimit,ThrottlingRateLimit:A.rateLimit}];return{stage:T,logicalId:v}}static createAuthorizer(n,i){let{slug:s,environment:o,name:c,type:u,functionArn:d,identitySource:g,userPoolArns:y,ttl:h=300}=i,A=c||r({slug:s,environment:o,resourceType:"api-authorizer"}),C=t(A),v={Type:"AWS::ApiGateway::Authorizer",Properties:{Name:A,Type:u,RestApiId:x.Ref(n),AuthorizerResultTtlInSeconds:h}};if(u==="TOKEN"||u==="REQUEST"){if(!d)throw Error("Lambda authorizer requires functionArn");v.Properties.AuthorizerUri=d,v.Properties.IdentitySource=g||"method.request.header.Authorization"}if(u==="COGNITO_USER_POOLS"){if(!y||y.length===0)throw Error("Cognito authorizer requires userPoolArns");v.Properties.ProviderARNs=y,v.Properties.IdentitySource=g||"method.request.header.Authorization"}return{authorizer:v,logicalId:C}}static setCors(n,i={}){let{origins:s=["*"],methods:o=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],headers:c=["*"],maxAge:u=86400,allowCredentials:d=!1}=i;return n.Properties.CorsConfiguration={AllowOrigins:s,AllowMethods:o,AllowHeaders:c,MaxAge:u,AllowCredentials:d},n}static addThrottling(n,i=5000,s=1e4){if(!n.Properties.MethodSettings)n.Properties.MethodSettings=[];return n.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:i,ThrottlingRateLimit:s}),n}static enableCaching(n,i="0.5",s=300){if(n.Properties.CacheClusterEnabled=!0,n.Properties.CacheClusterSize=i,!n.Properties.MethodSettings)n.Properties.MethodSettings=[];return n.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",CachingEnabled:!0,CacheTtlInSeconds:s}),n}static CacheSizes={Small:"0.5",Medium:"1.6",Large:"6.1",XLarge:"13.5",XXLarge:"28.4",XXXLarge:"58.2",Huge:"118",Massive:"237"};static ThrottlingPresets={Light:{burstLimit:100,rateLimit:50},Medium:{burstLimit:500,rateLimit:250},Heavy:{burstLimit:2000,rateLimit:1000},Default:{burstLimit:5000,rateLimit:1e4}}}class ge{static createTopic(n){let{slug:i,environment:s,topicName:o,displayName:c,encrypted:u=!1,kmsKeyId:d}=n,g=o||r({slug:i,environment:s,resourceType:"topic"}),y=t(g),h={Type:"AWS::SNS::Topic",Properties:{TopicName:g,DisplayName:c||g,Tags:[{Key:"Name",Value:g},{Key:"Environment",Value:s}]}};if(u&&d)h.Properties.KmsMasterKeyId=d;return{topic:h,logicalId:y}}static subscribe(n,i){let{slug:s,environment:o,protocol:c,endpoint:u,filterPolicy:d,rawMessageDelivery:g=!1}=i,y=r({slug:s,environment:o,resourceType:"subscription"}),h=u.replace(/[^a-zA-Z0-9]/g,""),A=h.length>12?h.slice(-12):h,C=t(`${y}-${c}-${A}`),v={Type:"AWS::SNS::Subscription",Properties:{TopicArn:x.Ref(n),Protocol:c,Endpoint:u,RawMessageDelivery:g}};if(d)v.Properties.FilterPolicy=d;return{subscription:v,logicalId:C}}static subscribeEmail(n,i,s){return ge.subscribe(n,{...s,protocol:"email",endpoint:i})}static subscribeLambda(n,i,s){return ge.subscribe(n,{...s,protocol:"lambda",endpoint:i,rawMessageDelivery:!0})}static subscribeSqs(n,i,s){return ge.subscribe(n,{...s,protocol:"sqs",endpoint:i})}static subscribeHttp(n,i,s){let o=i.startsWith("https://")?"https":"http";return ge.subscribe(n,{...s,protocol:o,endpoint:i})}static subscribeSms(n,i,s){return ge.subscribe(n,{...s,protocol:"sms",endpoint:i})}static setTopicPolicy(n,i){let{slug:s,environment:o,allowedPrincipals:c,allowedServices:u,actions:d="SNS:Publish"}=i,g=r({slug:s,environment:o,resourceType:"topic-policy"}),y=t(g),h={};if(c)h.AWS=c;if(u)h.Service=u;return{policy:{Type:"AWS::SNS::TopicPolicy",Properties:{Topics:[x.Ref(n)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:h,Action:d,Resource:x.Ref(n)}]}}},logicalId:y}}static allowCloudWatchAlarms(n,i){return ge.setTopicPolicy(n,{...i,allowedServices:"cloudwatch.amazonaws.com",actions:"SNS:Publish"})}static allowEventBridge(n,i){return ge.setTopicPolicy(n,{...i,allowedServices:"events.amazonaws.com",actions:"SNS:Publish"})}static allowS3(n,i){return ge.setTopicPolicy(n,{...i,allowedServices:"s3.amazonaws.com",actions:"SNS:Publish"})}static enableEncryption(n,i){if(!n.Properties)n.Properties={};return n.Properties.KmsMasterKeyId=i,n}static addInlineSubscription(n,i,s){if(!n.Properties)n.Properties={};if(!n.Properties.Subscription)n.Properties.Subscription=[];return n.Properties.Subscription.push({Protocol:i,Endpoint:s}),n}static FilterPolicies={eventType:(n)=>({eventType:n}),status:(n)=>({status:n}),numericRange:(n,i,s)=>({[n]:[{numeric:[">=",i,"<=",s]}]}),prefix:(n,i)=>({[n]:[{prefix:i}]}),and:(...n)=>Object.assign({},...n),exists:(n,i)=>({[n]:[{exists:i}]})};static UseCases={createAlertTopic:(n)=>ge.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-alerts`,displayName:n.displayName||"Alert Notifications"}),createEventFanout:(n)=>ge.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-events`,displayName:n.displayName||"Event Fanout"}),createNotificationTopic:(n)=>ge.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-notifications`,displayName:n.displayName||"User Notifications"})}}class cy{static createStateMachine(n){let{slug:i,environment:s,stateMachineName:o,type:c="STANDARD",definition:u,roleArn:d,loggingConfiguration:g,tracingConfiguration:y}=n,h=o||r({slug:i,environment:s,resourceType:"state-machine"}),A=t(h),C,v,T;if(d)T=d;else{let P=r({slug:i,environment:s,resourceType:"state-machine-role"});v=t(P),C={Type:"AWS::IAM::Role",Properties:{RoleName:P,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"states.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/CloudWatchLogsFullAccess"],Tags:[{Key:"Name",Value:P},{Key:"Environment",Value:s}]}},T=x.GetAtt(v,"Arn")}let R={Type:"AWS::StepFunctions::StateMachine",Properties:{StateMachineName:h,StateMachineType:c,DefinitionString:JSON.stringify(u),RoleArn:T,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(g)R.Properties.LoggingConfiguration={Level:g.level,IncludeExecutionData:g.includeExecutionData,Destinations:g.destinations?.map((P)=>({CloudWatchLogsLogGroup:{LogGroupArn:P}}))};if(y)R.Properties.TracingConfiguration={Enabled:y.enabled};return{stateMachine:R,logicalId:A,role:C,roleLogicalId:v}}static createLambdaTask(n,i){return{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Parameters:{FunctionName:n,Payload:i?.parameters||{"Input.$":"$"}},ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createDynamoDBTask(n,i,s,o){return{Type:"Task",Resource:{GetItem:"arn:aws:states:::dynamodb:getItem",PutItem:"arn:aws:states:::dynamodb:putItem",UpdateItem:"arn:aws:states:::dynamodb:updateItem",DeleteItem:"arn:aws:states:::dynamodb:deleteItem"}[n],Parameters:{TableName:i,...s},ResultPath:o?.resultPath,Retry:o?.retry,Catch:o?.catch,Next:o?.next,End:o?.end}}static createSNSPublishTask(n,i,s){return{Type:"Task",Resource:"arn:aws:states:::sns:publish",Parameters:{TopicArn:n,Message:i},ResultPath:s?.resultPath,Retry:s?.retry,Catch:s?.catch,Next:s?.next,End:s?.end}}static createSQSSendMessageTask(n,i,s){return{Type:"Task",Resource:"arn:aws:states:::sqs:sendMessage",Parameters:{QueueUrl:n,MessageBody:i},ResultPath:s?.resultPath,Retry:s?.retry,Catch:s?.catch,Next:s?.next,End:s?.end}}static createPassState(n){return{Type:"Pass",Result:n?.result,ResultPath:n?.resultPath,Parameters:n?.parameters,Next:n?.next,End:n?.end}}static createWaitState(n){return{Type:"Wait",Seconds:n.seconds,Timestamp:n.timestamp,SecondsPath:n.secondsPath,TimestampPath:n.timestampPath,Next:n.next,End:n.end}}static createChoiceState(n,i){return{Type:"Choice",Choices:n,Default:i}}static createParallelState(n,i){return{Type:"Parallel",Branches:n,ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createMapState(n,i){return{Type:"Map",ItemsPath:i?.itemsPath||"$.items",Iterator:n,MaxConcurrency:i?.maxConcurrency,ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createSucceedState(){return{Type:"Succeed"}}static createFailState(n,i){return{Type:"Fail",Error:n,Cause:i}}static RetryPolicies={standard:()=>({ErrorEquals:["States.ALL"],IntervalSeconds:2,MaxAttempts:3,BackoffRate:2}),aggressive:()=>({ErrorEquals:["States.TaskFailed","States.Timeout"],IntervalSeconds:1,MaxAttempts:5,BackoffRate:1.5}),custom:(n,i,s,o)=>({ErrorEquals:n,IntervalSeconds:i,MaxAttempts:s,BackoffRate:o})};static CatchPolicies={all:(n,i)=>({ErrorEquals:["States.ALL"],Next:n,ResultPath:i||"$.error"}),specific:(n,i,s)=>({ErrorEquals:n,Next:i,ResultPath:s||"$.error"})};static Patterns={sequential:(n,i,s)=>{let o={};return s.forEach((c,u)=>{let d=u===s.length-1;o[c.name]={...c.state,Next:d?void 0:s[u+1].name,End:d}}),{Comment:"Sequential workflow",StartAt:s[0].name,States:o}},fanout:(n,i,s)=>({Comment:"Fan-out workflow",StartAt:"Parallel",States:{Parallel:{Type:"Parallel",Branches:s.map((o)=>o.definition),End:!0}}}),map:(n,i,s,o)=>({Comment:"Map workflow",StartAt:"Map",States:{Map:{Type:"Map",ItemsPath:"$.items",Iterator:s,MaxConcurrency:o,End:!0}}}),withErrorHandling:(n,i,s,o)=>({Comment:"Workflow with error handling",StartAt:"Main",States:{Main:{...s,Catch:[{ErrorEquals:["States.ALL"],Next:"ErrorHandler"}],Next:"Success"},ErrorHandler:o,Success:{Type:"Succeed"}}})}}class jo{static createAlarm(n){let{slug:i,environment:s,alarmName:o,metricName:c,namespace:u,statistic:d="Average",period:g=300,evaluationPeriods:y=1,threshold:h,comparisonOperator:A,treatMissingData:C="notBreaching",actionsEnabled:v=!0,alarmActions:T,okActions:R,insufficientDataActions:P,dimensions:I,unit:M,datapointsToAlarm:L}=n,N=o||r({slug:i,environment:s,resourceType:"alarm"}),O=t(N),B={Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:N,MetricName:c,Namespace:u,Statistic:d,Period:g,EvaluationPeriods:y,Threshold:h,ComparisonOperator:A,TreatMissingData:C,ActionsEnabled:v}};if(T&&T.length>0)B.Properties.AlarmActions=T;if(R&&R.length>0)B.Properties.OKActions=R;if(P&&P.length>0)B.Properties.InsufficientDataActions=P;if(I)B.Properties.Dimensions=Object.entries(I).map(([F,U])=>({Name:F,Value:U}));if(M)B.Properties.Unit=M;if(L!==void 0)B.Properties.DatapointsToAlarm=L;return{alarm:B,logicalId:O}}static createCompositeAlarm(n){let{slug:i,environment:s,alarmName:o,alarmRule:c,actionsEnabled:u=!0,alarmActions:d,okActions:g,insufficientDataActions:y}=n,h=o||r({slug:i,environment:s,resourceType:"composite-alarm"}),A=t(h),C={Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:h,AlarmRule:c,ActionsEnabled:u}};if(d&&d.length>0)C.Properties.AlarmActions=d;if(g&&g.length>0)C.Properties.OKActions=g;if(y&&y.length>0)C.Properties.InsufficientDataActions=y;return{alarm:C,logicalId:A}}static createDashboard(n){let{slug:i,environment:s,dashboardName:o,widgets:c}=n,u=o||r({slug:i,environment:s,resourceType:"dashboard"}),d=t(u),g={widgets:c.map((h)=>({type:h.type,x:h.x,y:h.y,width:h.width,height:h.height,properties:h.properties}))};return{dashboard:{Type:"AWS::CloudWatch::Dashboard",Properties:{DashboardName:u,DashboardBody:JSON.stringify(g)}},logicalId:d}}static createLogGroup(n){let{slug:i,environment:s,logGroupName:o,retentionInDays:c,kmsKeyId:u}=n,d=o||r({slug:i,environment:s,resourceType:"log-group"}),g=t(d),y={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:d}};if(c!==void 0)y.Properties.RetentionInDays=c;if(u)y.Properties.KmsKeyId=u;return{logGroup:y,logicalId:g}}static createLogStream(n,i){let{slug:s,environment:o,logStreamName:c}=i,u=c||r({slug:s,environment:o,resourceType:"log-stream"}),d=t(u);return{logStream:{Type:"AWS::Logs::LogStream",Properties:{LogGroupName:x.Ref(n),LogStreamName:u}},logicalId:d}}static createMetricFilter(n,i){let{slug:s,environment:o,filterName:c,filterPattern:u,metricTransformations:d}=i,g=c||r({slug:s,environment:o,resourceType:"metric-filter"}),y=t(g);return{metricFilter:{Type:"AWS::Logs::MetricFilter",Properties:{LogGroupName:x.Ref(n),FilterPattern:u,MetricTransformations:d.map((A)=>({MetricName:A.metricName,MetricNamespace:A.metricNamespace,MetricValue:A.metricValue,DefaultValue:A.defaultValue,Unit:A.unit}))}},logicalId:y}}static AlarmTypes={highCpu:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-high-cpu`,metricName:"CPUUtilization",namespace:"AWS/EC2",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s},alarmActions:c?[c]:void 0}),highMemory:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-high-memory`,metricName:"MemoryUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s},alarmActions:c?[c]:void 0}),highDisk:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-high-disk`,metricName:"DiskSpaceUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s,Filesystem:"/dev/xvda1",MountPath:"/"},alarmActions:c?[c]:void 0}),lambdaErrors:(n,i,s,o=5,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-lambda-errors`,metricName:"Errors",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:s},alarmActions:c?[c]:void 0}),lambdaThrottles:(n,i,s,o=10,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-lambda-throttles`,metricName:"Throttles",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:s},alarmActions:c?[c]:void 0}),apiGateway5xxErrors:(n,i,s,o=10,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-api-5xx-errors`,metricName:"5XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:s},alarmActions:c?[c]:void 0}),apiGateway4xxErrors:(n,i,s,o=50,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-api-4xx-errors`,metricName:"4XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:s},alarmActions:c?[c]:void 0}),dynamoDBThrottles:(n,i,s,o=5,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-dynamodb-throttles`,metricName:"UserErrors",namespace:"AWS/DynamoDB",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{TableName:s},alarmActions:c?[c]:void 0}),rdsCpu:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-rds-cpu`,metricName:"CPUUtilization",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{DBInstanceIdentifier:s},alarmActions:c?[c]:void 0}),rdsFreeStorage:(n,i,s,o=5368709120,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-rds-storage`,metricName:"FreeStorageSpace",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"LessThanThreshold",dimensions:{DBInstanceIdentifier:s},alarmActions:c?[c]:void 0,unit:"Bytes"}),sqsQueueDepth:(n,i,s,o=100,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-sqs-depth`,metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{QueueName:s},alarmActions:c?[c]:void 0}),albUnhealthyTargets:(n,i,s,o,c=1,u)=>({slug:n,environment:i,alarmName:`${n}-${i}-alb-unhealthy`,metricName:"UnHealthyHostCount",namespace:"AWS/ApplicationELB",statistic:"Average",period:300,evaluationPeriods:2,threshold:c,comparisonOperator:"GreaterThanThreshold",dimensions:{LoadBalancer:s,TargetGroup:o},alarmActions:u?[u]:void 0}),sesBounceRate:(n,i,s=5,o)=>({slug:n,environment:i,alarmName:`${n}-${i}-ses-bounce-rate`,metricName:"Reputation.BounceRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:s/100,comparisonOperator:"GreaterThanThreshold",alarmActions:o?[o]:void 0}),sesComplaintRate:(n,i,s=0.1,o)=>({slug:n,environment:i,alarmName:`${n}-${i}-ses-complaint-rate`,metricName:"Reputation.ComplaintRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:s/100,comparisonOperator:"GreaterThanThreshold",alarmActions:o?[o]:void 0}),smsDeliveryFailure:(n,i,s,o=10,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-sms-delivery-failure`,metricName:"DirectSendMessagePermanentFailure",namespace:"AWS/Pinpoint",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{ApplicationId:s},alarmActions:c?[c]:void 0}),smsSpendLimit:(n,i,s=100,o)=>({slug:n,environment:i,alarmName:`${n}-${i}-sms-spend-limit`,metricName:"DirectSendMessageSpend",namespace:"AWS/Pinpoint",statistic:"Sum",period:86400,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",alarmActions:o?[o]:void 0}),connectMissedCalls:(n,i,s,o=5,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-connect-missed-calls`,metricName:"MissedCalls",namespace:"AWS/Connect",statistic:"Sum",period:3600,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s},alarmActions:c?[c]:void 0})};static DashboardWidgets={metric:(n,i,s,o,c,u)=>({type:"metric",x:n,y:i,width:s,height:o,properties:{metrics:c,title:u||"Metrics",region:"us-east-1",period:300}}),text:(n,i,s,o,c)=>({type:"text",x:n,y:i,width:s,height:o,properties:{markdown:c}}),log:(n,i,s,o,c,u)=>({type:"log",x:n,y:i,width:s,height:o,properties:{query:`SOURCE '${c.join("' | SOURCE '")}'
2274
+ `;class Y{static LambdaCode={send:Tt,receive:vn,deliveryStatus:Cn};static createPinpointApp(n){return{[`${n.slug}PinpointApp`]:{Type:"AWS::Pinpoint::App",Properties:{Name:n.name||`${n.slug}-sms`}}}}static createSmsChannel(n){let i={ApplicationId:n.applicationId,Enabled:n.enabled!==!1};if(n.senderId)i.SenderId=n.senderId;if(n.shortCode)i.ShortCode=n.shortCode;return{[`${n.slug}SmsChannel`]:{Type:"AWS::Pinpoint::SMSChannel",Properties:i}}}static createSmsLambdaRole(n){return{[`${n.slug}SmsLambdaRole`]:{Type:"AWS::IAM::Role",Properties:{RoleName:`${n.slug}-sms-lambda-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:"SmsLambdaPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["mobiletargeting:SendMessages","mobiletargeting:GetSmsChannel"],Resource:"*"},{Effect:"Allow",Action:["sns:Publish"],Resource:"*"},{Effect:"Allow",Action:["dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:GetItem","dynamodb:DeleteItem"],Resource:"*"}]}}]}}}}static createSendLambda(n){return{[`${n.slug}SmsSendLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-send`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Y.LambdaCode.send},Environment:{Variables:{PINPOINT_APP_ID:n.pinpointAppId,MESSAGE_LOG_TABLE:n.messageLogTable||"",SMS_SENDER_ID:n.senderId||"",SMS_ORIGINATION_NUMBER:n.originationNumber||""}}}}}}static createReceiveLambda(n){return{[`${n.slug}SmsReceiveLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-receive`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Y.LambdaCode.receive},Environment:{Variables:{OPT_OUT_TABLE:n.optOutTable||"",MESSAGE_LOG_TABLE:n.messageLogTable||"",NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createDeliveryStatusLambda(n){return{[`${n.slug}SmsDeliveryStatusLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-delivery-status`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Y.LambdaCode.deliveryStatus},Environment:{Variables:{MESSAGE_LOG_TABLE:n.messageLogTable||"",NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||"",WEBHOOK_URL:n.webhookUrl||""}}}}}}static createMessageLogTable(n){return{[`${n.slug}SmsMessageLogTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-sms-messages`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createOptOutTable(n){return{[`${n.slug}SmsOptOutTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-sms-optouts`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}]}}}}static createNotificationTopic(n){return{[`${n.slug}SmsNotificationTopic`]:{Type:"AWS::SNS::Topic",Properties:{TopicName:`${n.slug}-sms-notifications`}}}}static createCompleteSetup(n){let i={},s={};Object.assign(i,Y.createPinpointApp({slug:n.slug})),Object.assign(i,Y.createSmsChannel({slug:n.slug,applicationId:{Ref:`${n.slug}PinpointApp`},senderId:n.senderId})),Object.assign(i,Y.createSmsLambdaRole({slug:n.slug})),Object.assign(i,Y.createMessageLogTable({slug:n.slug})),Object.assign(i,Y.createOptOutTable({slug:n.slug})),Object.assign(i,Y.createNotificationTopic({slug:n.slug}));let o={"Fn::GetAtt":[`${n.slug}SmsLambdaRole`,"Arn"]},c={Ref:`${n.slug}PinpointApp`},u={Ref:`${n.slug}SmsMessageLogTable`},d={Ref:`${n.slug}SmsOptOutTable`},g={Ref:`${n.slug}SmsNotificationTopic`};if(Object.assign(i,Y.createSendLambda({slug:n.slug,roleArn:o,pinpointAppId:c,messageLogTable:u,senderId:n.senderId,originationNumber:n.originationNumber})),n.twoWayEnabled)Object.assign(i,Y.createReceiveLambda({slug:n.slug,roleArn:o,optOutTable:d,messageLogTable:u,notificationTopicArn:g,webhookUrl:n.webhookUrl}));return Object.assign(i,Y.createDeliveryStatusLambda({slug:n.slug,roleArn:o,messageLogTable:u,notificationTopicArn:g,webhookUrl:n.webhookUrl})),s[`${n.slug}PinpointAppId`]={Description:"Pinpoint application ID",Value:{Ref:`${n.slug}PinpointApp`}},s[`${n.slug}SmsSendLambdaArn`]={Description:"SMS send Lambda ARN",Value:{"Fn::GetAtt":[`${n.slug}SmsSendLambda`,"Arn"]}},s[`${n.slug}SmsNotificationTopicArn`]={Description:"SMS notification topic ARN",Value:{Ref:`${n.slug}SmsNotificationTopic`}},s[`${n.slug}SmsMessageLogTableName`]={Description:"SMS message log table name",Value:{Ref:`${n.slug}SmsMessageLogTable`}},{resources:i,outputs:s}}}function Rt(n){return n.replace(/[^a-zA-Z0-9]/g," ").trim().split(/\s+/).map((o)=>o.charAt(0).toUpperCase()+o.slice(1)).join("")||"User"}function _r(n,i){let s=(n||i).replace(/^\/+|\/+$/g,"");if(!s||s.split("/").includes(".."))throw Error(`sftp: invalid homeDirectory for user ${i}`);return s}function Wr(n){let i=n.storage;if(i?.type==="efs"){let o="fileSystemId"in i?i.fileSystemId:void 0;if(!o||typeof o==="string"&&!o.trim())throw Error("sftp: EFS storage requires fileSystemId, or a fileSystem name defined in infrastructure.fileSystem");return{type:"efs",fileSystemId:o,posixProfile:i.posixProfile}}let s=(i?.type==="s3"?i.bucket??n.bucket:n.bucket)?.trim();if(!s)throw Error("sftp: S3 storage requires bucket, or a storageBucket name defined in infrastructure.storage");return{type:"s3",bucket:s}}function Vr(n,i,s){let o=i.posixProfile??s;if(!o)throw Error(`sftp: user ${n} requires a posixProfile (uid/gid) on an EFS-backed server`);for(let c of[o.uid,o.gid,...o.secondaryGids??[]])if(!Number.isInteger(c)||c<0||c>4294967295)throw Error(`sftp: user ${n} has an invalid posixProfile id ${c}`);return{Uid:o.uid,Gid:o.gid,...o.secondaryGids?.length?{SecondaryGids:o.secondaryGids}:{}}}function Ur(n,i){return typeof n==="string"?`/${n}/${i}`:{"Fn::Sub":[`/\${FileSystemId}/${i}`,{FileSystemId:n}]}}function Hr(n){return typeof n==="string"?{"Fn::Sub":"arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}".replace("${FileSystemId}",n)}:{"Fn::Sub":["arn:aws:elasticfilesystem:${AWS::Region}:${AWS::AccountId}:file-system/${FileSystemId}",{FileSystemId:n}]}}class Cl{static create(n){let i=Wr(n),s=i.type==="efs"?"EFS":"S3",o=n.endpointType??"PUBLIC";if(o==="VPC"&&(!n.endpointDetails?.vpcId||!n.endpointDetails.subnetIds.length))throw Error("sftp: VPC endpoints require endpointDetails.vpcId and at least one subnet");let c=`${Rt(n.slug)}${Rt(n.environment)}Sftp`,u=`${c}Server`,d={},g;if(n.logging!==!1){let y=`${c}LoggingRole`;d[y]={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"transfer.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"TransferLogging",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:DescribeLogStreams","logs:PutLogEvents"],Resource:"arn:aws:logs:*:*:log-group:/aws/transfer/*"}]}}]}},g={"Fn::GetAtt":[y,"Arn"]}}d[u]={Type:"AWS::Transfer::Server",Properties:{Domain:s,EndpointType:o,IdentityProviderType:"SERVICE_MANAGED",Protocols:["SFTP"],...o==="VPC"?{EndpointDetails:{VpcId:n.endpointDetails.vpcId,SubnetIds:n.endpointDetails.subnetIds,...n.endpointDetails.securityGroupIds?.length?{SecurityGroupIds:n.endpointDetails.securityGroupIds}:{},...n.endpointDetails.addressAllocationIds?.length?{AddressAllocationIds:n.endpointDetails.addressAllocationIds}:{}}}:{},...n.securityPolicyName?{SecurityPolicyName:n.securityPolicyName}:{},...g?{LoggingRole:g}:{},Tags:[{Key:"Project",Value:n.slug},{Key:"Environment",Value:n.environment},{Key:"ManagedBy",Value:"ts-cloud"}]}};for(let[y,h]of Object.entries(n.users)){if(!/^[a-zA-Z0-9_.@-]{3,100}$/.test(y))throw Error(`sftp: invalid username ${y}`);if(!h.sshPublicKeys.length)throw Error(`sftp: user ${y} requires at least one SSH public key`);let A=Rt(y),C=_r(h.homeDirectory,y),v=`${c}${A}User`,T=h.roleArn;if(!T){let R=`${c}${A}Role`,P;if(i.type==="efs")P=[{Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:DescribeMountTargets"],Resource:Hr(i.fileSystemId)}];else{let I=`arn:aws:s3:::${i.bucket}`;P=[{Effect:"Allow",Action:["s3:ListBucket","s3:GetBucketLocation"],Resource:I,Condition:{StringLike:{"s3:prefix":[C,`${C}/*`]}}},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:GetObjectVersion"],Resource:`${I}/${C}/*`}]}d[R]={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"transfer.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"SftpHomeDirectory",PolicyDocument:{Version:"2012-10-17",Statement:P}}]}},T={"Fn::GetAtt":[R,"Arn"]}}d[v]={Type:"AWS::Transfer::User",DependsOn:[u],Properties:{ServerId:{Ref:u},UserName:y,Role:T,HomeDirectoryType:"PATH",HomeDirectory:i.type==="efs"?Ur(i.fileSystemId,C):`/${i.bucket}/${C}`,...i.type==="efs"?{PosixProfile:Vr(y,h,i.posixProfile)}:{},SshPublicKeys:h.sshPublicKeys}}}return{resources:d,serverLogicalId:u,domain:s}}}class Le{static createBedrockRole(n,i){let{slug:s,environment:o,name:c,models:u=["*"],allowStreaming:d=!0}=i,g=c||r({slug:s,environment:o,resourceType:"bedrock-role"}),y=t(g),h=["bedrock:InvokeModel"];if(d)h.push("bedrock:InvokeModelWithResponseStream");let A=u.map((v)=>v==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${v}`);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:g,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:n},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:`${g}-policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:h,Resource:A}]}}],Tags:[{Key:"Name",Value:g},{Key:"Environment",Value:o}]}},logicalId:y}}static createBedrockPolicy(n){let{slug:i,environment:s,name:o,models:c=["*"],allowInvoke:u=!0,allowStreaming:d=!0,allowAsync:g=!1}=n,y=o||r({slug:i,environment:s,resourceType:"bedrock-policy"}),h=t(y),A=[];if(u)A.push("bedrock:InvokeModel");if(d)A.push("bedrock:InvokeModelWithResponseStream");if(g)A.push("bedrock:InvokeModelAsync");let C=c.map((T)=>T==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${T}`);return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:y,PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"BedrockModelInvocation",Effect:"Allow",Action:A,Resource:C}]}}},logicalId:h}}static enableBedrockForLambda(n){return Le.createBedrockRole("lambda.amazonaws.com",n)}static enableBedrockForEcs(n){return Le.createBedrockRole("ecs-tasks.amazonaws.com",n)}static enableBedrockForEc2(n){return Le.createBedrockRole("ec2.amazonaws.com",n)}static addBedrockPermissions(n,i=["*"],s=!0){let o=["bedrock:InvokeModel"];if(s)o.push("bedrock:InvokeModelWithResponseStream");let c=i.map((u)=>u==="*"?"arn:aws:bedrock:*::foundation-model/*":`arn:aws:bedrock:*::foundation-model/${u}`);if(!n.Properties.Policies)n.Properties.Policies=[];return n.Properties.Policies.push({PolicyName:"bedrock-permissions",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:o,Resource:c}]}}),n}static Models={Claude3_5_Sonnet:"anthropic.claude-3-5-sonnet-20241022-v2:0",Claude3_5_Haiku:"anthropic.claude-3-5-haiku-20241022-v1:0",Claude3_Opus:"anthropic.claude-3-opus-20240229-v1:0",Claude3_Sonnet:"anthropic.claude-3-sonnet-20240229-v1:0",Claude3_Haiku:"anthropic.claude-3-haiku-20240307-v1:0",TitanTextG1Express:"amazon.titan-text-express-v1",TitanTextG1Lite:"amazon.titan-text-lite-v1",TitanEmbedG1Text:"amazon.titan-embed-text-v1",TitanImageG1:"amazon.titan-image-generator-v1",JurassicUltra:"ai21.j2-ultra-v1",JurassicMid:"ai21.j2-mid-v1",CommandText:"cohere.command-text-v14",CommandLight:"cohere.command-light-text-v14",EmbedEnglish:"cohere.embed-english-v3",EmbedMultilingual:"cohere.embed-multilingual-v3",Llama3_2_1B:"meta.llama3-2-1b-instruct-v1:0",Llama3_2_3B:"meta.llama3-2-3b-instruct-v1:0",Llama3_2_11B:"meta.llama3-2-11b-instruct-v1:0",Llama3_2_90B:"meta.llama3-2-90b-instruct-v1:0",Llama3_1_8B:"meta.llama3-1-8b-instruct-v1:0",Llama3_1_70B:"meta.llama3-1-70b-instruct-v1:0",Llama3_1_405B:"meta.llama3-1-405b-instruct-v1:0",Mistral7B:"mistral.mistral-7b-instruct-v0:2",Mixtral8x7B:"mistral.mixtral-8x7b-instruct-v0:1",MistralLarge:"mistral.mistral-large-2402-v1:0",StableDiffusionXL:"stability.stable-diffusion-xl-v1"};static ModelGroups={AllClaude:["anthropic.claude-3-5-sonnet-20241022-v2:0","anthropic.claude-3-5-haiku-20241022-v1:0","anthropic.claude-3-opus-20240229-v1:0","anthropic.claude-3-sonnet-20240229-v1:0","anthropic.claude-3-haiku-20240307-v1:0"],AllTitan:["amazon.titan-text-express-v1","amazon.titan-text-lite-v1","amazon.titan-embed-text-v1","amazon.titan-image-generator-v1"],AllLlama:["meta.llama3-2-1b-instruct-v1:0","meta.llama3-2-3b-instruct-v1:0","meta.llama3-2-11b-instruct-v1:0","meta.llama3-2-90b-instruct-v1:0","meta.llama3-1-8b-instruct-v1:0","meta.llama3-1-70b-instruct-v1:0","meta.llama3-1-405b-instruct-v1:0"],TextModels:["anthropic.claude-3-5-sonnet-20241022-v2:0","anthropic.claude-3-5-haiku-20241022-v1:0","amazon.titan-text-express-v1","meta.llama3-2-11b-instruct-v1:0","mistral.mistral-7b-instruct-v0:2"],EmbeddingModels:["amazon.titan-embed-text-v1","cohere.embed-english-v3","cohere.embed-multilingual-v3"],ImageModels:["amazon.titan-image-generator-v1","stability.stable-diffusion-xl-v1"]}}class gr{static createPostgres(n){return gr.createRDSInstance("postgres","16.2",n)}static createMysql(n){return gr.createRDSInstance("mysql","8.0.35",n)}static createRDSInstance(n,i,s){let{slug:o,environment:c,instanceClass:u="db.t3.micro",allocatedStorage:d=20,storageType:g="gp3",masterUsername:y="admin",masterPassword:h,databaseName:A,subnetIds:C,securityGroupIds:v,encrypted:T=!0,kmsKeyId:R,multiAz:P=!1,backupRetentionDays:I=7,publiclyAccessible:O=!1,enableCloudwatchLogs:B=!0,deletionProtection:x=!0}=s,F=r({slug:o,environment:c,resourceType:`${n}-db`}),G=t(F),_,U;if(C&&C.length>0){let K=r({slug:o,environment:c,resourceType:"db-subnet-group"});U=t(K),_={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupName:K,DBSubnetGroupDescription:`Subnet group for ${F}`,SubnetIds:C,Tags:[{Key:"Name",Value:K},{Key:"Environment",Value:c}]}}}let z={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:F,DBInstanceClass:u,Engine:n,EngineVersion:i,MasterUsername:y,MasterUserPassword:h,AllocatedStorage:d,StorageType:g,StorageEncrypted:T,MultiAZ:P,BackupRetentionPeriod:I,PubliclyAccessible:O,DeletionProtection:x,Tags:[{Key:"Name",Value:F},{Key:"Environment",Value:c}]}};if(A)z.Properties.DBName=A;if(R)z.Properties.KmsKeyId=R;if(U)z.Properties.DBSubnetGroupName=M.Ref(U);if(v&&v.length>0)z.Properties.VPCSecurityGroups=v;if(B)z.Properties.EnableCloudwatchLogsExports=n==="postgres"?["postgresql"]:["error","general","slowquery"];return{dbInstance:z,subnetGroup:_,logicalId:G,subnetGroupId:U}}static createReadReplica(n,i){let{slug:s,environment:o,instanceClass:c="db.t3.micro",securityGroupIds:u,publiclyAccessible:d=!1}=i,g=r({slug:s,environment:o,resourceType:"db-replica"}),y=t(g),h={Type:"AWS::RDS::DBInstance",Properties:{DBInstanceIdentifier:g,DBInstanceClass:c,SourceDBInstanceIdentifier:M.Ref(n),PubliclyAccessible:d,Tags:[{Key:"Name",Value:g},{Key:"Environment",Value:o},{Key:"Type",Value:"ReadReplica"}]}};if(u&&u.length>0)h.Properties.VPCSecurityGroups=u;return{replica:h,logicalId:y}}static createParameterGroup(n,i,s){let{slug:o,environment:c,parameters:u={}}=s,d=r({slug:o,environment:c,resourceType:"db-params"}),g=t(d),y=n==="postgres"?`postgres${i.split(".")[0]}`:`mysql${i.split(".")[0]}.${i.split(".")[1]}`;return{parameterGroup:{Type:"AWS::RDS::DBParameterGroup",Properties:{DBParameterGroupName:d,Description:`Parameter group for ${d}`,Family:y,Parameters:u,Tags:[{Key:"Name",Value:d},{Key:"Environment",Value:c}]}},logicalId:g}}static enableBackup(n,i=7){return n.Properties.BackupRetentionPeriod=i,n}static createTable(n){let{slug:i,environment:s,tableName:o,partitionKey:c,sortKey:u,billingMode:d="PAY_PER_REQUEST",readCapacity:g=5,writeCapacity:y=5,streamEnabled:h=!1,streamViewType:A="NEW_AND_OLD_IMAGES",encrypted:C=!0,kmsKeyId:v,pointInTimeRecovery:T=!0,ttlAttribute:R}=n,P=o||r({slug:i,environment:s,resourceType:"table"}),I=t(P),O=[{AttributeName:c.name,AttributeType:c.type}];if(u)O.push({AttributeName:u.name,AttributeType:u.type});let B=[{AttributeName:c.name,KeyType:"HASH"}];if(u)B.push({AttributeName:u.name,KeyType:"RANGE"});let x={Type:"AWS::DynamoDB::Table",Properties:{TableName:P,BillingMode:d,AttributeDefinitions:O,KeySchema:B,Tags:[{Key:"Name",Value:P},{Key:"Environment",Value:s}]}};if(d==="PROVISIONED")x.Properties.ProvisionedThroughput={ReadCapacityUnits:g,WriteCapacityUnits:y};if(h)x.Properties.StreamSpecification={StreamViewType:A};if(C)x.Properties.SSESpecification={SSEEnabled:!0,SSEType:v?"KMS":"AES256",KMSMasterKeyId:v};if(T)x.Properties.PointInTimeRecoverySpecification={PointInTimeRecoveryEnabled:!0};if(R)x.Properties.TimeToLiveSpecification={AttributeName:R,Enabled:!0};return{table:x,logicalId:I}}static addGlobalSecondaryIndex(n,i){let{indexName:s,partitionKey:o,sortKey:c,projectionType:u="ALL",nonKeyAttributes:d,readCapacity:g=5,writeCapacity:y=5}=i;if(!n.Properties.AttributeDefinitions.some((C)=>C.AttributeName===o.name))n.Properties.AttributeDefinitions.push({AttributeName:o.name,AttributeType:o.type});if(c&&!n.Properties.AttributeDefinitions.some((C)=>C.AttributeName===c.name))n.Properties.AttributeDefinitions.push({AttributeName:c.name,AttributeType:c.type});let h=[{AttributeName:o.name,KeyType:"HASH"}];if(c)h.push({AttributeName:c.name,KeyType:"RANGE"});let A={IndexName:s,KeySchema:h,Projection:{ProjectionType:u,NonKeyAttributes:u==="INCLUDE"?d:void 0},ProvisionedThroughput:void 0};if(n.Properties.BillingMode==="PROVISIONED")A.ProvisionedThroughput={ReadCapacityUnits:g,WriteCapacityUnits:y};if(!n.Properties.GlobalSecondaryIndexes)n.Properties.GlobalSecondaryIndexes=[];return n.Properties.GlobalSecondaryIndexes.push(A),n}static enableStreams(n,i="NEW_AND_OLD_IMAGES"){return n.Properties.StreamSpecification={StreamViewType:i},n}static InstanceClasses={T3_Micro:"db.t3.micro",T3_Small:"db.t3.small",T3_Medium:"db.t3.medium",T3_Large:"db.t3.large",T4g_Micro:"db.t4g.micro",T4g_Small:"db.t4g.small",T4g_Medium:"db.t4g.medium",M5_Large:"db.m5.large",M5_XLarge:"db.m5.xlarge",M5_2XLarge:"db.m5.2xlarge",R5_Large:"db.r5.large",R5_XLarge:"db.r5.xlarge",R5_2XLarge:"db.r5.2xlarge"}}class Xo{static createRedis(n){let{slug:i,environment:s,nodeType:o="cache.t3.micro",engineVersion:c="7.1",port:u=6379,subnetIds:d,securityGroupIds:g,numCacheClusters:y=2,automaticFailover:h=!0,multiAz:A=!0,clusterMode:C=!1,numNodeGroups:v=1,replicasPerNodeGroup:T=1,atRestEncryption:R=!0,transitEncryption:P=!0,authToken:I,kmsKeyId:O,snapshotRetentionDays:B=7,snapshotWindow:x,maintenanceWindow:F}=n,G=r({slug:i,environment:s,resourceType:"redis"}),_=t(G),U,z;if(d&&d.length>0){let Q=r({slug:i,environment:s,resourceType:"cache-subnet-group"});z=t(Q),U={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:Q,Description:`Subnet group for ${G}`,SubnetIds:d,Tags:[{Key:"Name",Value:Q},{Key:"Environment",Value:s}]}}}let K={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:G,ReplicationGroupDescription:`Redis cluster for ${i} ${s}`,Engine:"redis",EngineVersion:c,CacheNodeType:o,Port:u,AutomaticFailoverEnabled:h,MultiAZEnabled:A,AtRestEncryptionEnabled:R,TransitEncryptionEnabled:P,SnapshotRetentionLimit:B,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:G},{Key:"Environment",Value:s}]}};if(C)K.Properties.NumNodeGroups=v,K.Properties.ReplicasPerNodeGroup=T;else K.Properties.NumCacheClusters=y;if(I)K.Properties.AuthToken=I;if(O)K.Properties.KmsKeyId=O;if(z)K.Properties.CacheSubnetGroupName=M.Ref(z);if(g&&g.length>0)K.Properties.SecurityGroupIds=g;if(x)K.Properties.SnapshotWindow=x;if(F)K.Properties.PreferredMaintenanceWindow=F;return{replicationGroup:K,subnetGroup:U,logicalId:_,subnetGroupId:z}}static createMemcached(n){let{slug:i,environment:s,nodeType:o="cache.t3.micro",engineVersion:c="1.6.22",port:u=11211,numCacheNodes:d=2,subnetIds:g,securityGroupIds:y,azMode:h="cross-az",preferredAzs:A,maintenanceWindow:C}=n,v=r({slug:i,environment:s,resourceType:"memcached"}),T=t(v),R,P;if(g&&g.length>0){let O=r({slug:i,environment:s,resourceType:"cache-subnet-group"});P=t(O),R={Type:"AWS::ElastiCache::SubnetGroup",Properties:{CacheSubnetGroupName:O,Description:`Subnet group for ${v}`,SubnetIds:g,Tags:[{Key:"Name",Value:O},{Key:"Environment",Value:s}]}}}let I={Type:"AWS::ElastiCache::CacheCluster",Properties:{ClusterName:v,CacheNodeType:o,Engine:"memcached",EngineVersion:c,NumCacheNodes:d,Port:u,AZMode:h,AutoMinorVersionUpgrade:!0,Tags:[{Key:"Name",Value:v},{Key:"Environment",Value:s}]}};if(P)I.Properties.CacheSubnetGroupName=M.Ref(P);if(y&&y.length>0)I.Properties.VpcSecurityGroupIds=y;if(A&&A.length>0)I.Properties.PreferredAvailabilityZones=A;if(C)I.Properties.PreferredMaintenanceWindow=C;return{cluster:I,subnetGroup:R,logicalId:T,subnetGroupId:P}}static enableClusterMode(n,i=3,s=2){return delete n.Properties.NumCacheClusters,n.Properties.NumNodeGroups=i,n.Properties.ReplicasPerNodeGroup=s,n}static createRedisParameterGroup(n,i){let{slug:s,environment:o,parameters:c={}}=i,u=r({slug:s,environment:o,resourceType:"redis-params"}),d=t(u);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`redis${n.split(".")[0]}.x`,Description:`Parameter group for ${u}`,Properties:c,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:o}]}},logicalId:d}}static createMemcachedParameterGroup(n,i){let{slug:s,environment:o,parameters:c={}}=i,u=r({slug:s,environment:o,resourceType:"memcached-params"}),d=t(u);return{parameterGroup:{Type:"AWS::ElastiCache::ParameterGroup",Properties:{CacheParameterGroupFamily:`memcached${n.split(".")[0]}.${n.split(".")[1]}`,Description:`Parameter group for ${u}`,Properties:c,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:o}]}},logicalId:d}}static NodeTypes={T3_Micro:"cache.t3.micro",T3_Small:"cache.t3.small",T3_Medium:"cache.t3.medium",T4g_Micro:"cache.t4g.micro",T4g_Small:"cache.t4g.small",T4g_Medium:"cache.t4g.medium",M5_Large:"cache.m5.large",M5_XLarge:"cache.m5.xlarge",M5_2XLarge:"cache.m5.2xlarge",R5_Large:"cache.r5.large",R5_XLarge:"cache.r5.xlarge",R5_2XLarge:"cache.r5.2xlarge",R5_4XLarge:"cache.r5.4xlarge",R6g_Large:"cache.r6g.large",R6g_XLarge:"cache.r6g.xlarge",R6g_2XLarge:"cache.r6g.2xlarge"}}class ge{static createUser(n){let{slug:i,environment:s,userName:o,groups:c,managedPolicyArns:u}=n,d=o||r({slug:i,environment:s,resourceType:"user"}),g=t(d),y={Type:"AWS::IAM::User",Properties:{UserName:d,Tags:[{Key:"Name",Value:d},{Key:"Environment",Value:s}]}};if(c&&c.length>0)y.Properties.Groups=c;if(u&&u.length>0)y.Properties.ManagedPolicyArns=u;return{user:y,logicalId:g}}static createRole(n){let{slug:i,environment:s,roleName:o,servicePrincipal:c,awsPrincipal:u,managedPolicyArns:d}=n,g=o||r({slug:i,environment:s,resourceType:"role"}),y=t(g),h={};if(c)h.Service=c;if(u)h.AWS=u;let A={Type:"AWS::IAM::Role",Properties:{RoleName:g,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:h,Action:"sts:AssumeRole"}]},Tags:[{Key:"Name",Value:g},{Key:"Environment",Value:s}]}};if(d&&d.length>0)A.Properties.ManagedPolicyArns=d;return{role:A,logicalId:y}}static createGroup(n){let{slug:i,environment:s,groupName:o,managedPolicyArns:c}=n,u=o||r({slug:i,environment:s,resourceType:"group"}),d=t(u),g={Type:"AWS::IAM::Group",Properties:{GroupName:u}};if(c&&c.length>0)g.Properties.ManagedPolicyArns=c;return{group:g,logicalId:d}}static createPolicy(n){let{slug:i,environment:s,policyName:o,description:c,statements:u}=n,d=o||r({slug:i,environment:s,resourceType:"policy"}),g=t(d),y=u.map((A)=>({Sid:A.sid,Effect:A.effect||"Allow",Action:A.actions,Resource:A.resources,Condition:A.conditions}));return{policy:{Type:"AWS::IAM::ManagedPolicy",Properties:{ManagedPolicyName:d,Description:c||`Managed policy for ${d}`,PolicyDocument:{Version:"2012-10-17",Statement:y}}},logicalId:g}}static attachPolicyToRole(n,i){if(!n.Properties.ManagedPolicyArns)n.Properties.ManagedPolicyArns=[];if(!n.Properties.ManagedPolicyArns.includes(i))n.Properties.ManagedPolicyArns.push(i);return n}static attachPolicyToUser(n,i){if(!n.Properties.ManagedPolicyArns)n.Properties.ManagedPolicyArns=[];if(!n.Properties.ManagedPolicyArns.includes(i))n.Properties.ManagedPolicyArns.push(i);return n}static attachPolicyToGroup(n,i){if(!n.Properties.ManagedPolicyArns)n.Properties.ManagedPolicyArns=[];if(!n.Properties.ManagedPolicyArns.includes(i))n.Properties.ManagedPolicyArns.push(i);return n}static addInlinePolicyToRole(n,i,s){if(!n.Properties.Policies)n.Properties.Policies=[];let o=s.map((c)=>({Effect:c.effect||"Allow",Action:c.actions,Resource:c.resources}));return n.Properties.Policies.push({PolicyName:i,PolicyDocument:{Version:"2012-10-17",Statement:o}}),n}static addInlinePolicyToUser(n,i,s){if(!n.Properties.Policies)n.Properties.Policies=[];let o=s.map((c)=>({Effect:c.effect||"Allow",Action:c.actions,Resource:c.resources}));return n.Properties.Policies.push({PolicyName:i,PolicyDocument:{Version:"2012-10-17",Statement:o}}),n}static createAccessKey(n,i){let{slug:s,environment:o,status:c="Active"}=i,u=r({slug:s,environment:o,resourceType:"access-key"}),d=t(u);return{accessKey:{Type:"AWS::IAM::AccessKey",Properties:{UserName:M.Ref(n),Status:c}},logicalId:d}}static createInstanceProfile(n,i){let{slug:s,environment:o,profileName:c}=i,u=c||r({slug:s,environment:o,resourceType:"instance-profile"}),d=t(u);return{instanceProfile:{Type:"AWS::IAM::InstanceProfile",Properties:{InstanceProfileName:u,Roles:[M.Ref(n)]}},logicalId:d}}static ManagedPolicies={AdministratorAccess:"arn:aws:iam::aws:policy/AdministratorAccess",PowerUserAccess:"arn:aws:iam::aws:policy/PowerUserAccess",ReadOnlyAccess:"arn:aws:iam::aws:policy/ReadOnlyAccess",S3FullAccess:"arn:aws:iam::aws:policy/AmazonS3FullAccess",S3ReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess",DynamoDBFullAccess:"arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess",DynamoDBReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonDynamoDBReadOnlyAccess",RDSFullAccess:"arn:aws:iam::aws:policy/AmazonRDSFullAccess",RDSReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonRDSReadOnlyAccess",LambdaFullAccess:"arn:aws:iam::aws:policy/AWSLambda_FullAccess",LambdaReadOnlyAccess:"arn:aws:iam::aws:policy/AWSLambda_ReadOnlyAccess",LambdaBasicExecutionRole:"arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",LambdaVPCAccessExecutionRole:"arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole",EC2FullAccess:"arn:aws:iam::aws:policy/AmazonEC2FullAccess",EC2ReadOnlyAccess:"arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess",EC2ContainerRegistryReadOnly:"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly",EC2ContainerRegistryPowerUser:"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPowerUser",ECSTaskExecutionRole:"arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy",ECSFullAccess:"arn:aws:iam::aws:policy/AmazonECS_FullAccess",CloudWatchFullAccess:"arn:aws:iam::aws:policy/CloudWatchFullAccess",CloudWatchLogsFullAccess:"arn:aws:iam::aws:policy/CloudWatchLogsFullAccess",SESFullAccess:"arn:aws:iam::aws:policy/AmazonSESFullAccess",SNSFullAccess:"arn:aws:iam::aws:policy/AmazonSNSFullAccess",SQSFullAccess:"arn:aws:iam::aws:policy/AmazonSQSFullAccess",SecretsManagerReadWrite:"arn:aws:iam::aws:policy/SecretsManagerReadWrite"};static ServicePrincipals={Lambda:"lambda.amazonaws.com",EC2:"ec2.amazonaws.com",ECS:"ecs.amazonaws.com",ECSTaskExecution:"ecs-tasks.amazonaws.com",APIGateway:"apigateway.amazonaws.com",Events:"events.amazonaws.com",States:"states.amazonaws.com",CodeBuild:"codebuild.amazonaws.com",CodeDeploy:"codedeploy.amazonaws.com",CloudFormation:"cloudformation.amazonaws.com"};static createCiCdUser(n){let{slug:i,environment:s,permissions:o,createAccessKey:c=!0}=n,u={},d=[];if(o.s3Buckets&&o.s3Buckets.length>0)d.push({sid:"S3Access",actions:["s3:GetBucketLocation","s3:ListBucket","s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucketMultipartUploads","s3:AbortMultipartUpload"],resources:[...o.s3Buckets,...o.s3Buckets.map((T)=>`${T}/*`)]});if(o.cloudFrontDistributions&&o.cloudFrontDistributions.length>0)d.push({sid:"CloudFrontAccess",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations","cloudfront:GetDistribution"],resources:o.cloudFrontDistributions});if(o.ecrRepositories&&o.ecrRepositories.length>0)d.push({sid:"ECRAccess",actions:["ecr:GetAuthorizationToken","ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:GetRepositoryPolicy","ecr:DescribeRepositories","ecr:ListImages","ecr:DescribeImages","ecr:BatchGetImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:PutImage"],resources:o.ecrRepositories}),d.push({sid:"ECRLogin",actions:["ecr:GetAuthorizationToken"],resources:"*"});if(o.ecsServices&&o.ecsServices.length>0)d.push({sid:"ECSAccess",actions:["ecs:DescribeServices","ecs:DescribeTaskDefinition","ecs:DescribeTasks","ecs:ListTasks","ecs:RegisterTaskDefinition","ecs:UpdateService","ecs:RunTask","ecs:StopTask"],resources:o.ecsServices}),d.push({sid:"ECSTaskDefinitions",actions:["ecs:RegisterTaskDefinition","ecs:DeregisterTaskDefinition"],resources:"*"}),d.push({sid:"ECSPassRole",actions:["iam:PassRole"],resources:"*",conditions:{StringLike:{"iam:PassedToService":"ecs-tasks.amazonaws.com"}}});if(o.cloudFormationStacks&&o.cloudFormationStacks.length>0)d.push({sid:"CloudFormationAccess",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:DescribeStackResources","cloudformation:GetTemplate","cloudformation:ListStackResources","cloudformation:ValidateTemplate"],resources:o.cloudFormationStacks});if(o.lambdaFunctions&&o.lambdaFunctions.length>0)d.push({sid:"LambdaAccess",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion","lambda:UpdateAlias","lambda:CreateAlias"],resources:o.lambdaFunctions});if(o.secretsManagerSecrets&&o.secretsManagerSecrets.length>0)d.push({sid:"SecretsManagerAccess",actions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],resources:o.secretsManagerSecrets});let{policy:g,logicalId:y}=ge.createPolicy({slug:i,environment:s,policyName:r({slug:i,environment:s,resourceType:"cicd-policy"}),description:`CI/CD deployment policy for ${i} (${s})`,statements:d});u[y]=g;let{user:h,logicalId:A}=ge.createUser({slug:i,environment:s,userName:r({slug:i,environment:s,resourceType:"cicd-user"}),managedPolicyArns:[M.Ref(y)]});u[A]=h;let C,v;if(c){let T=ge.createAccessKey(A,{slug:i,environment:s});C=T.accessKey,v=T.logicalId,u[v]=C}return{user:h,accessKey:C,policy:g,userLogicalId:A,accessKeyLogicalId:v,policyLogicalId:y,resources:u}}static createCrossAccountRole(n){let{slug:i,environment:s,trustedAccountIds:o,externalId:c,permissions:u,maxSessionDuration:d=3600}=n,g={},{policy:y,logicalId:h}=ge.createPolicy({slug:i,environment:s,policyName:r({slug:i,environment:s,resourceType:"cross-account-policy"}),description:`Cross-account access policy for ${i} (${s})`,statements:u});g[h]=y;let A=r({slug:i,environment:s,resourceType:"cross-account-role"}),C=t(A),v={};if(c)v.StringEquals={"sts:ExternalId":c};let T={Type:"AWS::IAM::Role",Properties:{RoleName:A,MaxSessionDuration:d,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:o.map((R)=>`arn:aws:iam::${R}:root`)},Action:"sts:AssumeRole",...Object.keys(v).length>0?{Condition:v}:{}}]},ManagedPolicyArns:[M.Ref(h)],Tags:[{Key:"Name",Value:A},{Key:"Environment",Value:s},{Key:"Purpose",Value:"Cross-Account Access"}]}};return g[C]=T,{role:T,policy:y,roleLogicalId:C,policyLogicalId:h,resources:g}}static createCliUser(n){let{slug:i,environment:s,permissions:o="readonly"}=n,c={},u=[],d=[];switch(o){case"readonly":d=[ge.ManagedPolicies.ReadOnlyAccess];break;case"deploy":u=[{sid:"S3Deploy",actions:["s3:*"],resources:"*"},{sid:"CloudFrontDeploy",actions:["cloudfront:*"],resources:"*"},{sid:"ECSDeploy",actions:["ecs:*"],resources:"*"},{sid:"ECRDeploy",actions:["ecr:*"],resources:"*"},{sid:"LambdaDeploy",actions:["lambda:*"],resources:"*"},{sid:"CloudFormationDeploy",actions:["cloudformation:*"],resources:"*"},{sid:"IAMPassRole",actions:["iam:PassRole"],resources:"*"}];break;case"admin":d=[ge.ManagedPolicies.AdministratorAccess];break}let g,y;if(u.length>0){let T=ge.createPolicy({slug:i,environment:s,policyName:r({slug:i,environment:s,resourceType:"cli-policy"}),description:`CLI access policy for ${i} (${s})`,statements:u});g=T.policy,y=T.logicalId,c[y]=g,d=[M.Ref(y)]}let{user:h,logicalId:A}=ge.createUser({slug:i,environment:s,userName:r({slug:i,environment:s,resourceType:"cli-user"}),managedPolicyArns:d});c[A]=h;let{accessKey:C,logicalId:v}=ge.createAccessKey(A,{slug:i,environment:s});return c[v]=C,{user:h,accessKey:C,policy:g,userLogicalId:A,accessKeyLogicalId:v,policyLogicalId:y,resources:c}}static CiCdPolicies={s3Deployment:(n)=>[{sid:"S3ListBuckets",actions:["s3:ListBucket","s3:GetBucketLocation"],resources:n},{sid:"S3Objects",actions:["s3:GetObject","s3:PutObject","s3:DeleteObject"],resources:n.map((i)=>`${i}/*`)}],cloudFrontInvalidation:(n)=>[{sid:"CloudFrontInvalidation",actions:["cloudfront:CreateInvalidation","cloudfront:GetInvalidation","cloudfront:ListInvalidations"],resources:n}],ecsDeployment:()=>[{sid:"ECSServices",actions:["ecs:DescribeServices","ecs:UpdateService","ecs:DescribeTaskDefinition","ecs:RegisterTaskDefinition"],resources:"*"},{sid:"ECSPassRole",actions:["iam:PassRole"],resources:"*",conditions:{StringLike:{"iam:PassedToService":"ecs-tasks.amazonaws.com"}}}],ecrPush:(n)=>[{sid:"ECRAuth",actions:["ecr:GetAuthorizationToken"],resources:"*"},{sid:"ECRPush",actions:["ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:PutImage"],resources:n}],lambdaDeployment:(n)=>[{sid:"LambdaDeploy",actions:["lambda:GetFunction","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:PublishVersion"],resources:n}],cloudFormationDeployment:(n)=>[{sid:"CloudFormationDeploy",actions:["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate"],resources:n}]}}class El{static createRestApi(n){let{slug:i,environment:s,name:o,description:c,endpointType:u="REGIONAL",binaryMediaTypes:d,compressionSize:g}=n,y=o||r({slug:i,environment:s,resourceType:"rest-api"}),h=t(y),A={Type:"AWS::ApiGateway::RestApi",Properties:{Name:y,Description:c||`REST API for ${i} ${s}`,EndpointConfiguration:{Types:[u]},Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:s}]}};if(d&&d.length>0)A.Properties.BinaryMediaTypes=d;if(g!==void 0)A.Properties.MinimumCompressionSize=g;return{restApi:A,logicalId:h}}static createHttpApi(n){let{slug:i,environment:s,name:o,description:c,corsEnabled:u=!0,corsOrigins:d=["*"],corsMethods:g=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],corsHeaders:y=["*"],corsMaxAge:h=86400,corsAllowCredentials:A=!1}=n,C=o||r({slug:i,environment:s,resourceType:"http-api"}),v=t(C),T={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:C,Description:c||`HTTP API for ${i} ${s}`,ProtocolType:"HTTP",Tags:{Name:C,Environment:s}}};if(u)T.Properties.CorsConfiguration={AllowOrigins:d,AllowMethods:g,AllowHeaders:y,MaxAge:h,AllowCredentials:A};return{httpApi:T,logicalId:v}}static createWebSocketApi(n){let{slug:i,environment:s,name:o,description:c}=n,u=o||r({slug:i,environment:s,resourceType:"ws-api"}),d=t(u);return{webSocketApi:{Type:"AWS::ApiGatewayV2::Api",Properties:{Name:u,Description:c||`WebSocket API for ${i} ${s}`,ProtocolType:"WEBSOCKET",Tags:{Name:u,Environment:s}}},logicalId:d}}static createDeployment(n,i){let{slug:s,environment:o,description:c}=i,u=r({slug:s,environment:o,resourceType:"api-deployment"}),d=t(u);return{deployment:{Type:"AWS::ApiGateway::Deployment",Properties:{RestApiId:M.Ref(n),Description:c||`Deployment for ${u}`}},logicalId:d}}static createStage(n,i,s){let{slug:o,environment:c,stageName:u,description:d,cacheEnabled:g=!1,cacheSize:y="0.5",variables:h,throttling:A}=s,C=r({slug:o,environment:c,resourceType:"api-stage"}),v=t(C),T={Type:"AWS::ApiGateway::Stage",Properties:{StageName:u||c,RestApiId:M.Ref(n),DeploymentId:M.Ref(i),Description:d,CacheClusterEnabled:g,Tags:[{Key:"Name",Value:C},{Key:"Environment",Value:c}]}};if(g)T.Properties.CacheClusterSize=y;if(h)T.Properties.Variables=h;if(A)T.Properties.MethodSettings=[{HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:A.burstLimit,ThrottlingRateLimit:A.rateLimit}];return{stage:T,logicalId:v}}static createAuthorizer(n,i){let{slug:s,environment:o,name:c,type:u,functionArn:d,identitySource:g,userPoolArns:y,ttl:h=300}=i,A=c||r({slug:s,environment:o,resourceType:"api-authorizer"}),C=t(A),v={Type:"AWS::ApiGateway::Authorizer",Properties:{Name:A,Type:u,RestApiId:M.Ref(n),AuthorizerResultTtlInSeconds:h}};if(u==="TOKEN"||u==="REQUEST"){if(!d)throw Error("Lambda authorizer requires functionArn");v.Properties.AuthorizerUri=d,v.Properties.IdentitySource=g||"method.request.header.Authorization"}if(u==="COGNITO_USER_POOLS"){if(!y||y.length===0)throw Error("Cognito authorizer requires userPoolArns");v.Properties.ProviderARNs=y,v.Properties.IdentitySource=g||"method.request.header.Authorization"}return{authorizer:v,logicalId:C}}static setCors(n,i={}){let{origins:s=["*"],methods:o=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],headers:c=["*"],maxAge:u=86400,allowCredentials:d=!1}=i;return n.Properties.CorsConfiguration={AllowOrigins:s,AllowMethods:o,AllowHeaders:c,MaxAge:u,AllowCredentials:d},n}static addThrottling(n,i=5000,s=1e4){if(!n.Properties.MethodSettings)n.Properties.MethodSettings=[];return n.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",ThrottlingBurstLimit:i,ThrottlingRateLimit:s}),n}static enableCaching(n,i="0.5",s=300){if(n.Properties.CacheClusterEnabled=!0,n.Properties.CacheClusterSize=i,!n.Properties.MethodSettings)n.Properties.MethodSettings=[];return n.Properties.MethodSettings.push({HttpMethod:"*",ResourcePath:"/*",CachingEnabled:!0,CacheTtlInSeconds:s}),n}static CacheSizes={Small:"0.5",Medium:"1.6",Large:"6.1",XLarge:"13.5",XXLarge:"28.4",XXXLarge:"58.2",Huge:"118",Massive:"237"};static ThrottlingPresets={Light:{burstLimit:100,rateLimit:50},Medium:{burstLimit:500,rateLimit:250},Heavy:{burstLimit:2000,rateLimit:1000},Default:{burstLimit:5000,rateLimit:1e4}}}class pe{static createTopic(n){let{slug:i,environment:s,topicName:o,displayName:c,encrypted:u=!1,kmsKeyId:d}=n,g=o||r({slug:i,environment:s,resourceType:"topic"}),y=t(g),h={Type:"AWS::SNS::Topic",Properties:{TopicName:g,DisplayName:c||g,Tags:[{Key:"Name",Value:g},{Key:"Environment",Value:s}]}};if(u&&d)h.Properties.KmsMasterKeyId=d;return{topic:h,logicalId:y}}static subscribe(n,i){let{slug:s,environment:o,protocol:c,endpoint:u,filterPolicy:d,rawMessageDelivery:g=!1}=i,y=r({slug:s,environment:o,resourceType:"subscription"}),h=u.replace(/[^a-zA-Z0-9]/g,""),A=h.length>12?h.slice(-12):h,C=t(`${y}-${c}-${A}`),v={Type:"AWS::SNS::Subscription",Properties:{TopicArn:M.Ref(n),Protocol:c,Endpoint:u,RawMessageDelivery:g}};if(d)v.Properties.FilterPolicy=d;return{subscription:v,logicalId:C}}static subscribeEmail(n,i,s){return pe.subscribe(n,{...s,protocol:"email",endpoint:i})}static subscribeLambda(n,i,s){return pe.subscribe(n,{...s,protocol:"lambda",endpoint:i,rawMessageDelivery:!0})}static subscribeSqs(n,i,s){return pe.subscribe(n,{...s,protocol:"sqs",endpoint:i})}static subscribeHttp(n,i,s){let o=i.startsWith("https://")?"https":"http";return pe.subscribe(n,{...s,protocol:o,endpoint:i})}static subscribeSms(n,i,s){return pe.subscribe(n,{...s,protocol:"sms",endpoint:i})}static setTopicPolicy(n,i){let{slug:s,environment:o,allowedPrincipals:c,allowedServices:u,actions:d="SNS:Publish"}=i,g=r({slug:s,environment:o,resourceType:"topic-policy"}),y=t(g),h={};if(c)h.AWS=c;if(u)h.Service=u;return{policy:{Type:"AWS::SNS::TopicPolicy",Properties:{Topics:[M.Ref(n)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:h,Action:d,Resource:M.Ref(n)}]}}},logicalId:y}}static allowCloudWatchAlarms(n,i){return pe.setTopicPolicy(n,{...i,allowedServices:"cloudwatch.amazonaws.com",actions:"SNS:Publish"})}static allowEventBridge(n,i){return pe.setTopicPolicy(n,{...i,allowedServices:"events.amazonaws.com",actions:"SNS:Publish"})}static allowS3(n,i){return pe.setTopicPolicy(n,{...i,allowedServices:"s3.amazonaws.com",actions:"SNS:Publish"})}static enableEncryption(n,i){if(!n.Properties)n.Properties={};return n.Properties.KmsMasterKeyId=i,n}static addInlineSubscription(n,i,s){if(!n.Properties)n.Properties={};if(!n.Properties.Subscription)n.Properties.Subscription=[];return n.Properties.Subscription.push({Protocol:i,Endpoint:s}),n}static FilterPolicies={eventType:(n)=>({eventType:n}),status:(n)=>({status:n}),numericRange:(n,i,s)=>({[n]:[{numeric:[">=",i,"<=",s]}]}),prefix:(n,i)=>({[n]:[{prefix:i}]}),and:(...n)=>Object.assign({},...n),exists:(n,i)=>({[n]:[{exists:i}]})};static UseCases={createAlertTopic:(n)=>pe.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-alerts`,displayName:n.displayName||"Alert Notifications"}),createEventFanout:(n)=>pe.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-events`,displayName:n.displayName||"Event Fanout"}),createNotificationTopic:(n)=>pe.createTopic({...n,topicName:n.topicName||`${n.slug}-${n.environment}-notifications`,displayName:n.displayName||"User Notifications"})}}class yy{static createStateMachine(n){let{slug:i,environment:s,stateMachineName:o,type:c="STANDARD",definition:u,roleArn:d,loggingConfiguration:g,tracingConfiguration:y}=n,h=o||r({slug:i,environment:s,resourceType:"state-machine"}),A=t(h),C,v,T;if(d)T=d;else{let P=r({slug:i,environment:s,resourceType:"state-machine-role"});v=t(P),C={Type:"AWS::IAM::Role",Properties:{RoleName:P,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"states.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/CloudWatchLogsFullAccess"],Tags:[{Key:"Name",Value:P},{Key:"Environment",Value:s}]}},T=M.GetAtt(v,"Arn")}let R={Type:"AWS::StepFunctions::StateMachine",Properties:{StateMachineName:h,StateMachineType:c,DefinitionString:JSON.stringify(u),RoleArn:T,Tags:[{Key:"Name",Value:h},{Key:"Environment",Value:s}]}};if(g)R.Properties.LoggingConfiguration={Level:g.level,IncludeExecutionData:g.includeExecutionData,Destinations:g.destinations?.map((P)=>({CloudWatchLogsLogGroup:{LogGroupArn:P}}))};if(y)R.Properties.TracingConfiguration={Enabled:y.enabled};return{stateMachine:R,logicalId:A,role:C,roleLogicalId:v}}static createLambdaTask(n,i){return{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Parameters:{FunctionName:n,Payload:i?.parameters||{"Input.$":"$"}},ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createDynamoDBTask(n,i,s,o){return{Type:"Task",Resource:{GetItem:"arn:aws:states:::dynamodb:getItem",PutItem:"arn:aws:states:::dynamodb:putItem",UpdateItem:"arn:aws:states:::dynamodb:updateItem",DeleteItem:"arn:aws:states:::dynamodb:deleteItem"}[n],Parameters:{TableName:i,...s},ResultPath:o?.resultPath,Retry:o?.retry,Catch:o?.catch,Next:o?.next,End:o?.end}}static createSNSPublishTask(n,i,s){return{Type:"Task",Resource:"arn:aws:states:::sns:publish",Parameters:{TopicArn:n,Message:i},ResultPath:s?.resultPath,Retry:s?.retry,Catch:s?.catch,Next:s?.next,End:s?.end}}static createSQSSendMessageTask(n,i,s){return{Type:"Task",Resource:"arn:aws:states:::sqs:sendMessage",Parameters:{QueueUrl:n,MessageBody:i},ResultPath:s?.resultPath,Retry:s?.retry,Catch:s?.catch,Next:s?.next,End:s?.end}}static createPassState(n){return{Type:"Pass",Result:n?.result,ResultPath:n?.resultPath,Parameters:n?.parameters,Next:n?.next,End:n?.end}}static createWaitState(n){return{Type:"Wait",Seconds:n.seconds,Timestamp:n.timestamp,SecondsPath:n.secondsPath,TimestampPath:n.timestampPath,Next:n.next,End:n.end}}static createChoiceState(n,i){return{Type:"Choice",Choices:n,Default:i}}static createParallelState(n,i){return{Type:"Parallel",Branches:n,ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createMapState(n,i){return{Type:"Map",ItemsPath:i?.itemsPath||"$.items",Iterator:n,MaxConcurrency:i?.maxConcurrency,ResultPath:i?.resultPath,Retry:i?.retry,Catch:i?.catch,Next:i?.next,End:i?.end}}static createSucceedState(){return{Type:"Succeed"}}static createFailState(n,i){return{Type:"Fail",Error:n,Cause:i}}static RetryPolicies={standard:()=>({ErrorEquals:["States.ALL"],IntervalSeconds:2,MaxAttempts:3,BackoffRate:2}),aggressive:()=>({ErrorEquals:["States.TaskFailed","States.Timeout"],IntervalSeconds:1,MaxAttempts:5,BackoffRate:1.5}),custom:(n,i,s,o)=>({ErrorEquals:n,IntervalSeconds:i,MaxAttempts:s,BackoffRate:o})};static CatchPolicies={all:(n,i)=>({ErrorEquals:["States.ALL"],Next:n,ResultPath:i||"$.error"}),specific:(n,i,s)=>({ErrorEquals:n,Next:i,ResultPath:s||"$.error"})};static Patterns={sequential:(n,i,s)=>{let o={};return s.forEach((c,u)=>{let d=u===s.length-1;o[c.name]={...c.state,Next:d?void 0:s[u+1].name,End:d}}),{Comment:"Sequential workflow",StartAt:s[0].name,States:o}},fanout:(n,i,s)=>({Comment:"Fan-out workflow",StartAt:"Parallel",States:{Parallel:{Type:"Parallel",Branches:s.map((o)=>o.definition),End:!0}}}),map:(n,i,s,o)=>({Comment:"Map workflow",StartAt:"Map",States:{Map:{Type:"Map",ItemsPath:"$.items",Iterator:s,MaxConcurrency:o,End:!0}}}),withErrorHandling:(n,i,s,o)=>({Comment:"Workflow with error handling",StartAt:"Main",States:{Main:{...s,Catch:[{ErrorEquals:["States.ALL"],Next:"ErrorHandler"}],Next:"Success"},ErrorHandler:o,Success:{Type:"Succeed"}}})}}class Yo{static createAlarm(n){let{slug:i,environment:s,alarmName:o,metricName:c,namespace:u,statistic:d="Average",period:g=300,evaluationPeriods:y=1,threshold:h,comparisonOperator:A,treatMissingData:C="notBreaching",actionsEnabled:v=!0,alarmActions:T,okActions:R,insufficientDataActions:P,dimensions:I,unit:O,datapointsToAlarm:B}=n,x=o||r({slug:i,environment:s,resourceType:"alarm"}),F=t(x),G={Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:x,MetricName:c,Namespace:u,Statistic:d,Period:g,EvaluationPeriods:y,Threshold:h,ComparisonOperator:A,TreatMissingData:C,ActionsEnabled:v}};if(T&&T.length>0)G.Properties.AlarmActions=T;if(R&&R.length>0)G.Properties.OKActions=R;if(P&&P.length>0)G.Properties.InsufficientDataActions=P;if(I)G.Properties.Dimensions=Object.entries(I).map(([_,U])=>({Name:_,Value:U}));if(O)G.Properties.Unit=O;if(B!==void 0)G.Properties.DatapointsToAlarm=B;return{alarm:G,logicalId:F}}static createCompositeAlarm(n){let{slug:i,environment:s,alarmName:o,alarmRule:c,actionsEnabled:u=!0,alarmActions:d,okActions:g,insufficientDataActions:y}=n,h=o||r({slug:i,environment:s,resourceType:"composite-alarm"}),A=t(h),C={Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:h,AlarmRule:c,ActionsEnabled:u}};if(d&&d.length>0)C.Properties.AlarmActions=d;if(g&&g.length>0)C.Properties.OKActions=g;if(y&&y.length>0)C.Properties.InsufficientDataActions=y;return{alarm:C,logicalId:A}}static createDashboard(n){let{slug:i,environment:s,dashboardName:o,widgets:c}=n,u=o||r({slug:i,environment:s,resourceType:"dashboard"}),d=t(u),g={widgets:c.map((h)=>({type:h.type,x:h.x,y:h.y,width:h.width,height:h.height,properties:h.properties}))};return{dashboard:{Type:"AWS::CloudWatch::Dashboard",Properties:{DashboardName:u,DashboardBody:JSON.stringify(g)}},logicalId:d}}static createLogGroup(n){let{slug:i,environment:s,logGroupName:o,retentionInDays:c,kmsKeyId:u}=n,d=o||r({slug:i,environment:s,resourceType:"log-group"}),g=t(d),y={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:d}};if(c!==void 0)y.Properties.RetentionInDays=c;if(u)y.Properties.KmsKeyId=u;return{logGroup:y,logicalId:g}}static createLogStream(n,i){let{slug:s,environment:o,logStreamName:c}=i,u=c||r({slug:s,environment:o,resourceType:"log-stream"}),d=t(u);return{logStream:{Type:"AWS::Logs::LogStream",Properties:{LogGroupName:M.Ref(n),LogStreamName:u}},logicalId:d}}static createMetricFilter(n,i){let{slug:s,environment:o,filterName:c,filterPattern:u,metricTransformations:d}=i,g=c||r({slug:s,environment:o,resourceType:"metric-filter"}),y=t(g);return{metricFilter:{Type:"AWS::Logs::MetricFilter",Properties:{LogGroupName:M.Ref(n),FilterPattern:u,MetricTransformations:d.map((A)=>({MetricName:A.metricName,MetricNamespace:A.metricNamespace,MetricValue:A.metricValue,DefaultValue:A.defaultValue,Unit:A.unit}))}},logicalId:y}}static AlarmTypes={highCpu:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-high-cpu`,metricName:"CPUUtilization",namespace:"AWS/EC2",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s},alarmActions:c?[c]:void 0}),highMemory:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-high-memory`,metricName:"MemoryUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s},alarmActions:c?[c]:void 0}),highDisk:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-high-disk`,metricName:"DiskSpaceUtilization",namespace:"System/Linux",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s,Filesystem:"/dev/xvda1",MountPath:"/"},alarmActions:c?[c]:void 0}),lambdaErrors:(n,i,s,o=5,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-lambda-errors`,metricName:"Errors",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:s},alarmActions:c?[c]:void 0}),lambdaThrottles:(n,i,s,o=10,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-lambda-throttles`,metricName:"Throttles",namespace:"AWS/Lambda",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{FunctionName:s},alarmActions:c?[c]:void 0}),apiGateway5xxErrors:(n,i,s,o=10,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-api-5xx-errors`,metricName:"5XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:s},alarmActions:c?[c]:void 0}),apiGateway4xxErrors:(n,i,s,o=50,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-api-4xx-errors`,metricName:"4XXError",namespace:"AWS/ApiGateway",statistic:"Sum",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{ApiName:s},alarmActions:c?[c]:void 0}),dynamoDBThrottles:(n,i,s,o=5,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-dynamodb-throttles`,metricName:"UserErrors",namespace:"AWS/DynamoDB",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{TableName:s},alarmActions:c?[c]:void 0}),rdsCpu:(n,i,s,o=80,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-rds-cpu`,metricName:"CPUUtilization",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{DBInstanceIdentifier:s},alarmActions:c?[c]:void 0}),rdsFreeStorage:(n,i,s,o=5368709120,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-rds-storage`,metricName:"FreeStorageSpace",namespace:"AWS/RDS",statistic:"Average",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"LessThanThreshold",dimensions:{DBInstanceIdentifier:s},alarmActions:c?[c]:void 0,unit:"Bytes"}),sqsQueueDepth:(n,i,s,o=100,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-sqs-depth`,metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",statistic:"Average",period:300,evaluationPeriods:2,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{QueueName:s},alarmActions:c?[c]:void 0}),albUnhealthyTargets:(n,i,s,o,c=1,u)=>({slug:n,environment:i,alarmName:`${n}-${i}-alb-unhealthy`,metricName:"UnHealthyHostCount",namespace:"AWS/ApplicationELB",statistic:"Average",period:300,evaluationPeriods:2,threshold:c,comparisonOperator:"GreaterThanThreshold",dimensions:{LoadBalancer:s,TargetGroup:o},alarmActions:u?[u]:void 0}),sesBounceRate:(n,i,s=5,o)=>({slug:n,environment:i,alarmName:`${n}-${i}-ses-bounce-rate`,metricName:"Reputation.BounceRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:s/100,comparisonOperator:"GreaterThanThreshold",alarmActions:o?[o]:void 0}),sesComplaintRate:(n,i,s=0.1,o)=>({slug:n,environment:i,alarmName:`${n}-${i}-ses-complaint-rate`,metricName:"Reputation.ComplaintRate",namespace:"AWS/SES",statistic:"Average",period:3600,evaluationPeriods:1,threshold:s/100,comparisonOperator:"GreaterThanThreshold",alarmActions:o?[o]:void 0}),smsDeliveryFailure:(n,i,s,o=10,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-sms-delivery-failure`,metricName:"DirectSendMessagePermanentFailure",namespace:"AWS/Pinpoint",statistic:"Sum",period:300,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{ApplicationId:s},alarmActions:c?[c]:void 0}),smsSpendLimit:(n,i,s=100,o)=>({slug:n,environment:i,alarmName:`${n}-${i}-sms-spend-limit`,metricName:"DirectSendMessageSpend",namespace:"AWS/Pinpoint",statistic:"Sum",period:86400,evaluationPeriods:1,threshold:s,comparisonOperator:"GreaterThanThreshold",alarmActions:o?[o]:void 0}),connectMissedCalls:(n,i,s,o=5,c)=>({slug:n,environment:i,alarmName:`${n}-${i}-connect-missed-calls`,metricName:"MissedCalls",namespace:"AWS/Connect",statistic:"Sum",period:3600,evaluationPeriods:1,threshold:o,comparisonOperator:"GreaterThanThreshold",dimensions:{InstanceId:s},alarmActions:c?[c]:void 0})};static DashboardWidgets={metric:(n,i,s,o,c,u)=>({type:"metric",x:n,y:i,width:s,height:o,properties:{metrics:c,title:u||"Metrics",region:"us-east-1",period:300}}),text:(n,i,s,o,c)=>({type:"text",x:n,y:i,width:s,height:o,properties:{markdown:c}}),log:(n,i,s,o,c,u)=>({type:"log",x:n,y:i,width:s,height:o,properties:{query:`SOURCE '${c.join("' | SOURCE '")}'
2275
2275
  | fields @timestamp, @message
2276
2276
  | sort @timestamp desc
2277
2277
  | limit 20`,region:"us-east-1",title:u||"Logs"}})};static RetentionPeriods={ONE_DAY:1,THREE_DAYS:3,FIVE_DAYS:5,ONE_WEEK:7,TWO_WEEKS:14,ONE_MONTH:30,TWO_MONTHS:60,THREE_MONTHS:90,FOUR_MONTHS:120,FIVE_MONTHS:150,SIX_MONTHS:180,ONE_YEAR:365,THIRTEEN_MONTHS:400,EIGHTEEN_MONTHS:545,TWO_YEARS:731,FIVE_YEARS:1827,TEN_YEARS:3653,NEVER_EXPIRE:void 0};static FilterPatterns={errors:"[time, request_id, event_type = ERROR*, ...]",all:"",jsonField:(n,i)=>`{ $.${n} = "${i}" }`,httpStatus:(n)=>`[..., status_code = ${n}, ...]`,http4xx:"[..., status_code = 4*, ...]",http5xx:"[..., status_code = 5*, ...]"};static createApplicationDashboard(n){let{slug:i,environment:s,region:o="us-east-1",components:c={}}=n,u=[],d=0;if(u.push({type:"text",x:0,y:d,width:24,height:1,properties:{markdown:`# ${i.toUpperCase()} Dashboard (${s})`}}),d+=1,c.ec2InstanceIds&&c.ec2InstanceIds.length>0)u.push({type:"text",x:0,y:d,width:24,height:1,properties:{markdown:"## EC2 Instances"}}),d+=1,u.push({type:"metric",x:0,y:d,width:8,height:6,properties:{title:"CPU Utilization",region:o,metrics:c.ec2InstanceIds.map((g)=>["AWS/EC2","CPUUtilization","InstanceId",g]),period:300,stat:"Average"}}),u.push({type:"metric",x:8,y:d,width:8,height:6,properties:{title:"Network Traffic",region:o,metrics:[...c.ec2InstanceIds.flatMap((g)=>[["AWS/EC2","NetworkIn","InstanceId",g,{label:`${g} In`}],["AWS/EC2","NetworkOut","InstanceId",g,{label:`${g} Out`}]])],period:300,stat:"Sum"}}),u.push({type:"metric",x:16,y:d,width:8,height:6,properties:{title:"Status Checks",region:o,metrics:c.ec2InstanceIds.map((g)=>["AWS/EC2","StatusCheckFailed","InstanceId",g]),period:60,stat:"Maximum"}}),d+=6;if(c.lambdaFunctionNames&&c.lambdaFunctionNames.length>0)u.push({type:"text",x:0,y:d,width:24,height:1,properties:{markdown:"## Lambda Functions"}}),d+=1,u.push({type:"metric",x:0,y:d,width:8,height:6,properties:{title:"Invocations",region:o,metrics:c.lambdaFunctionNames.map((g)=>["AWS/Lambda","Invocations","FunctionName",g]),period:300,stat:"Sum"}}),u.push({type:"metric",x:8,y:d,width:8,height:6,properties:{title:"Duration",region:o,metrics:c.lambdaFunctionNames.map((g)=>["AWS/Lambda","Duration","FunctionName",g]),period:300,stat:"Average"}}),u.push({type:"metric",x:16,y:d,width:8,height:6,properties:{title:"Errors",region:o,metrics:c.lambdaFunctionNames.map((g)=>["AWS/Lambda","Errors","FunctionName",g]),period:300,stat:"Sum"}}),d+=6;if(c.ecsClusterName&&c.ecsServiceName)u.push({type:"text",x:0,y:d,width:24,height:1,properties:{markdown:"## ECS Service"}}),d+=1,u.push({type:"metric",x:0,y:d,width:8,height:6,properties:{title:"CPU Utilization",region:o,metrics:[["AWS/ECS","CPUUtilization","ClusterName",c.ecsClusterName,"ServiceName",c.ecsServiceName]],period:300,stat:"Average"}}),u.push({type:"metric",x:8,y:d,width:8,height:6,properties:{title:"Memory Utilization",region:o,metrics:[["AWS/ECS","MemoryUtilization","ClusterName",c.ecsClusterName,"ServiceName",c.ecsServiceName]],period:300,stat:"Average"}}),u.push({type:"metric",x:16,y:d,width:8,height:6,properties:{title:"Running Tasks",region:o,metrics:[["ECS/ContainerInsights","RunningTaskCount","ClusterName",c.ecsClusterName,"ServiceName",c.ecsServiceName]],period:60,stat:"Average"}}),d+=6;if(c.albName)u.push({type:"text",x:0,y:d,width:24,height:1,properties:{markdown:"## Application Load Balancer"}}),d+=1,u.push({type:"metric",x:0,y:d,width:8,height:6,properties:{title:"Request Count",region:o,metrics:[["AWS/ApplicationELB","RequestCount","LoadBalancer",c.albName]],period:60,stat:"Sum"}}),u.push({type:"metric",x:8,y:d,width:8,height:6,properties:{title:"Response Time",region:o,metrics:[["AWS/ApplicationELB","TargetResponseTime","LoadBalancer",c.albName]],period:60,stat:"Average"}}),u.push({type:"metric",x:16,y:d,width:8,height:6,properties:{title:"HTTP Errors",region:o,metrics:[["AWS/ApplicationELB","HTTPCode_Target_4XX_Count","LoadBalancer",c.albName,{label:"4XX"}],["AWS/ApplicationELB","HTTPCode_Target_5XX_Count","LoadBalancer",c.albName,{label:"5XX"}]],period:60,stat:"Sum"}}),d+=6;if(c.rdsInstanceId)u.push({type:"text",x:0,y:d,width:24,height:1,properties:{markdown:"## RDS Database"}}),d+=1,u.push({type:"metric",x:0,y:d,width:8,height:6,properties:{title:"CPU Utilization",region:o,metrics:[["AWS/RDS","CPUUtilization","DBInstanceIdentifier",c.rdsInstanceId]],period:300,stat:"Average"}}),u.push({type:"metric",x:8,y:d,width:8,height:6,properties:{title:"Database Connections",region:o,metrics:[["AWS/RDS","DatabaseConnections","DBInstanceIdentifier",c.rdsInstanceId]],period:60,stat:"Sum"}}),u.push({type:"metric",x:16,y:d,width:8,height:6,properties:{title:"Free Storage Space",region:o,metrics:[["AWS/RDS","FreeStorageSpace","DBInstanceIdentifier",c.rdsInstanceId]],period:300,stat:"Average"}}),d+=6;if(c.sqsQueueNames&&c.sqsQueueNames.length>0)u.push({type:"text",x:0,y:d,width:24,height:1,properties:{markdown:"## SQS Queues"}}),d+=1,u.push({type:"metric",x:0,y:d,width:12,height:6,properties:{title:"Messages Visible",region:o,metrics:c.sqsQueueNames.map((g)=>["AWS/SQS","ApproximateNumberOfMessagesVisible","QueueName",g]),period:60,stat:"Sum"}}),u.push({type:"metric",x:12,y:d,width:12,height:6,properties:{title:"Message Age",region:o,metrics:c.sqsQueueNames.map((g)=>["AWS/SQS","ApproximateAgeOfOldestMessage","QueueName",g]),period:60,stat:"Maximum"}}),d+=6;if(c.logGroupNames&&c.logGroupNames.length>0)u.push({type:"text",x:0,y:d,width:24,height:1,properties:{markdown:"## Application Logs"}}),d+=1,u.push({type:"log",x:0,y:d,width:24,height:6,properties:{query:`SOURCE '${c.logGroupNames.join("' | SOURCE '")}'
2278
2278
  | fields @timestamp, @message
2279
2279
  | filter @message like /ERROR|WARN|Exception/
2280
2280
  | sort @timestamp desc
2281
- | limit 50`,region:o,title:"Recent Errors and Warnings"}}),d+=6;return jo.createDashboard({slug:i,environment:s,widgets:u})}static DashboardTemplates={staticWebsite:(n)=>({slug:n.slug,environment:n.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${n.slug.toUpperCase()} Static Website Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"CloudFront Requests",region:"us-east-1",metrics:[["AWS/CloudFront","Requests","DistributionId",n.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"Error Rate",region:"us-east-1",metrics:[["AWS/CloudFront","4xxErrorRate","DistributionId",n.cloudFrontDistributionId,"Region","Global",{label:"4XX"}],["AWS/CloudFront","5xxErrorRate","DistributionId",n.cloudFrontDistributionId,"Region","Global",{label:"5XX"}]],period:300,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Bytes Downloaded",region:"us-east-1",metrics:[["AWS/CloudFront","BytesDownloaded","DistributionId",n.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:0,y:7,width:12,height:6,properties:{title:"S3 Bucket Size",region:n.region||"us-east-1",metrics:[["AWS/S3","BucketSizeBytes","BucketName",n.s3BucketName,"StorageType","StandardStorage"]],period:86400,stat:"Average"}},{type:"metric",x:12,y:7,width:12,height:6,properties:{title:"S3 Number of Objects",region:n.region||"us-east-1",metrics:[["AWS/S3","NumberOfObjects","BucketName",n.s3BucketName,"StorageType","AllStorageTypes"]],period:86400,stat:"Average"}}]}),serverlessApi:(n)=>({slug:n.slug,environment:n.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${n.slug.toUpperCase()} Serverless API Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"API Requests",region:n.region||"us-east-1",metrics:[["AWS/ApiGateway","Count","ApiName",n.apiGatewayName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"API Latency",region:n.region||"us-east-1",metrics:[["AWS/ApiGateway","Latency","ApiName",n.apiGatewayName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"API Errors",region:n.region||"us-east-1",metrics:[["AWS/ApiGateway","4XXError","ApiName",n.apiGatewayName,{label:"4XX"}],["AWS/ApiGateway","5XXError","ApiName",n.apiGatewayName,{label:"5XX"}]],period:60,stat:"Sum"}},...n.lambdaFunctionNames.map((i,s)=>({type:"metric",x:s%3*8,y:7+Math.floor(s/3)*6,width:8,height:6,properties:{title:`${i} Metrics`,region:n.region||"us-east-1",metrics:[["AWS/Lambda","Invocations","FunctionName",i],["AWS/Lambda","Duration","FunctionName",i],["AWS/Lambda","Errors","FunctionName",i]],period:300,stat:"Sum"}}))]}),containerService:(n)=>({slug:n.slug,environment:n.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${n.slug.toUpperCase()} Container Service Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"ECS CPU",region:n.region||"us-east-1",metrics:[["AWS/ECS","CPUUtilization","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"ECS Memory",region:n.region||"us-east-1",metrics:[["AWS/ECS","MemoryUtilization","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Running Tasks",region:n.region||"us-east-1",metrics:[["ECS/ContainerInsights","RunningTaskCount","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:0,y:7,width:8,height:6,properties:{title:"ALB Requests",region:n.region||"us-east-1",metrics:[["AWS/ApplicationELB","RequestCount","LoadBalancer",n.albName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:7,width:8,height:6,properties:{title:"Response Time",region:n.region||"us-east-1",metrics:[["AWS/ApplicationELB","TargetResponseTime","LoadBalancer",n.albName]],period:60,stat:"Average"}},{type:"metric",x:16,y:7,width:8,height:6,properties:{title:"Healthy Hosts",region:n.region||"us-east-1",metrics:[["AWS/ApplicationELB","HealthyHostCount","LoadBalancer",n.albName]],period:60,stat:"Average"}},...n.rdsInstanceId?[{type:"metric",x:0,y:13,width:12,height:6,properties:{title:"RDS CPU",region:n.region||"us-east-1",metrics:[["AWS/RDS","CPUUtilization","DBInstanceIdentifier",n.rdsInstanceId]],period:300,stat:"Average"}},{type:"metric",x:12,y:13,width:12,height:6,properties:{title:"RDS Connections",region:n.region||"us-east-1",metrics:[["AWS/RDS","DatabaseConnections","DBInstanceIdentifier",n.rdsInstanceId]],period:60,stat:"Sum"}}]:[]]})};static Config={createAlarmConfig:(n)=>{let{metricName:i,namespace:s,threshold:o,comparisonOperator:c="GreaterThanThreshold",evaluationPeriods:u=1,period:d=300,statistic:g="Average",treatMissingData:y="missing"}=n;return{MetricName:i,Namespace:s,Threshold:o,ComparisonOperator:c,EvaluationPeriods:u,Period:d,Statistic:g,TreatMissingData:y}},namespaces:{ec2:"AWS/EC2",ecs:"AWS/ECS",lambda:"AWS/Lambda",rds:"AWS/RDS",sqs:"AWS/SQS",sns:"AWS/SNS",s3:"AWS/S3",cloudfront:"AWS/CloudFront",alb:"AWS/ApplicationELB",nlb:"AWS/NetworkELB",apiGateway:"AWS/ApiGateway",dynamodb:"AWS/DynamoDB",elasticache:"AWS/ElastiCache"},comparisonOperators:{greaterThan:"GreaterThanThreshold",greaterOrEqual:"GreaterThanOrEqualToThreshold",lessThan:"LessThanThreshold",lessOrEqual:"LessThanOrEqualToThreshold"},metrics:{ec2:{cpu:{metricName:"CPUUtilization",namespace:"AWS/EC2"},networkIn:{metricName:"NetworkIn",namespace:"AWS/EC2"},networkOut:{metricName:"NetworkOut",namespace:"AWS/EC2"},statusCheck:{metricName:"StatusCheckFailed",namespace:"AWS/EC2"}},ecs:{cpu:{metricName:"CPUUtilization",namespace:"AWS/ECS"},memory:{metricName:"MemoryUtilization",namespace:"AWS/ECS"}},lambda:{invocations:{metricName:"Invocations",namespace:"AWS/Lambda"},errors:{metricName:"Errors",namespace:"AWS/Lambda"},duration:{metricName:"Duration",namespace:"AWS/Lambda"},throttles:{metricName:"Throttles",namespace:"AWS/Lambda"},concurrentExecutions:{metricName:"ConcurrentExecutions",namespace:"AWS/Lambda"}},rds:{cpu:{metricName:"CPUUtilization",namespace:"AWS/RDS"},connections:{metricName:"DatabaseConnections",namespace:"AWS/RDS"},freeStorage:{metricName:"FreeStorageSpace",namespace:"AWS/RDS"},readLatency:{metricName:"ReadLatency",namespace:"AWS/RDS"},writeLatency:{metricName:"WriteLatency",namespace:"AWS/RDS"}},alb:{requestCount:{metricName:"RequestCount",namespace:"AWS/ApplicationELB"},responseTime:{metricName:"TargetResponseTime",namespace:"AWS/ApplicationELB"},httpCode4xx:{metricName:"HTTPCode_Target_4XX_Count",namespace:"AWS/ApplicationELB"},httpCode5xx:{metricName:"HTTPCode_Target_5XX_Count",namespace:"AWS/ApplicationELB"},healthyHosts:{metricName:"HealthyHostCount",namespace:"AWS/ApplicationELB"}},sqs:{messagesVisible:{metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS"},messagesDelayed:{metricName:"ApproximateNumberOfMessagesDelayed",namespace:"AWS/SQS"},messageAge:{metricName:"ApproximateAgeOfOldestMessage",namespace:"AWS/SQS"}}},presets:{highCpu:(n=80)=>({metricName:"CPUUtilization",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highMemory:(n=80)=>({metricName:"MemoryUtilization",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highErrors:(n=10)=>({metricName:"Errors",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:1,period:60,statistic:"Sum"}),highLatency:(n=5000)=>({metricName:"Duration",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowHealthyHosts:(n=1)=>({metricName:"HealthyHostCount",namespace:"AWS/ApplicationELB",threshold:n,comparisonOperator:"LessThanThreshold",evaluationPeriods:2,period:60,statistic:"Minimum"}),queueDepth:(n=1000)=>({metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowStorage:(n=10737418240)=>({metricName:"FreeStorageSpace",namespace:"AWS/RDS",threshold:n,comparisonOperator:"LessThanThreshold",evaluationPeriods:1,period:300,statistic:"Average"})}}}class Y{static createUserPool(n){let{slug:i,environment:s,userPoolName:o,aliasAttributes:c,autoVerifiedAttributes:u,passwordPolicy:d,mfaConfiguration:g,emailConfiguration:y,smsConfiguration:h,lambdaTriggers:A,userPoolAddOns:C,accountRecoverySetting:v}=n,T=o||r({slug:i,environment:s,resourceType:"user-pool"}),R=t(T),P={Type:"AWS::Cognito::UserPool",Properties:{UserPoolName:T,Policies:d?{PasswordPolicy:{MinimumLength:d.minimumLength,RequireLowercase:d.requireLowercase,RequireUppercase:d.requireUppercase,RequireNumbers:d.requireNumbers,RequireSymbols:d.requireSymbols,TemporaryPasswordValidityDays:d.temporaryPasswordValidityDays}}:void 0,MfaConfiguration:g,Schema:[{Name:"email",AttributeDataType:"String",Required:!0,Mutable:!1}]}};if(c&&c.length>0)P.Properties.UsernameAttributes=c;if(u&&u.length>0)P.Properties.AutoVerifiedAttributes=u;if(y)P.Properties.EmailConfiguration={EmailSendingAccount:y.emailSendingAccount,From:y.from,ReplyToEmailAddress:y.replyToEmailAddress,SourceArn:y.sourceArn,ConfigurationSet:y.configurationSet};if(h)P.Properties.SmsConfiguration={ExternalId:h.externalId,SnsCallerArn:h.snsCallerArn};if(A)P.Properties.LambdaConfig={PreSignUp:A.preSignUp,PostConfirmation:A.postConfirmation,PreAuthentication:A.preAuthentication,PostAuthentication:A.postAuthentication,CustomMessage:A.customMessage,DefineAuthChallenge:A.defineAuthChallenge,CreateAuthChallenge:A.createAuthChallenge,VerifyAuthChallengeResponse:A.verifyAuthChallengeResponse,PreTokenGeneration:A.preTokenGeneration,UserMigration:A.userMigration};if(C)P.Properties.UserPoolAddOns={AdvancedSecurityMode:C.advancedSecurityMode};if(v)P.Properties.AccountRecoverySetting={RecoveryMechanisms:v.recoveryMechanisms};return{userPool:P,logicalId:R}}static createUserPoolClient(n,i){let{slug:s,environment:o,clientName:c,generateSecret:u=!1,refreshTokenValidity:d,accessTokenValidity:g,idTokenValidity:y,tokenValidityUnits:h,readAttributes:A,writeAttributes:C,explicitAuthFlows:v,preventUserExistenceErrors:T,enableTokenRevocation:R,callbackURLs:P,logoutURLs:I,allowedOAuthFlows:M,allowedOAuthScopes:L,allowedOAuthFlowsUserPoolClient:N,supportedIdentityProviders:O}=i,B=c||r({slug:s,environment:o,resourceType:"user-pool-client"}),F=t(B);return{client:{Type:"AWS::Cognito::UserPoolClient",Properties:{ClientName:B,UserPoolId:x.Ref(n),GenerateSecret:u,RefreshTokenValidity:d,AccessTokenValidity:g,IdTokenValidity:y,TokenValidityUnits:h,ReadAttributes:A,WriteAttributes:C,ExplicitAuthFlows:v,PreventUserExistenceErrors:T,EnableTokenRevocation:R,CallbackURLs:P,LogoutURLs:I,AllowedOAuthFlows:M,AllowedOAuthScopes:L,AllowedOAuthFlowsUserPoolClient:N,SupportedIdentityProviders:O}},logicalId:F}}static createUserPoolDomain(n,i){let{slug:s,environment:o,domain:c,customDomainConfig:u}=i,d=r({slug:s,environment:o,resourceType:"user-pool-domain"}),g=t(d);return{domain:{Type:"AWS::Cognito::UserPoolDomain",Properties:{Domain:c,UserPoolId:x.Ref(n),CustomDomainConfig:u}},logicalId:g}}static createIdentityPool(n){let{slug:i,environment:s,identityPoolName:o,allowUnauthenticatedIdentities:c=!1,cognitoIdentityProviders:u,supportedLoginProviders:d,samlProviderARNs:g,openIdConnectProviderARNs:y}=n,h=o||r({slug:i,environment:s,resourceType:"identity-pool"}),A=t(h);return{identityPool:{Type:"AWS::Cognito::IdentityPool",Properties:{IdentityPoolName:h,AllowUnauthenticatedIdentities:c,CognitoIdentityProviders:u,SupportedLoginProviders:d,SamlProviderARNs:g,OpenIdConnectProviderARNs:y}},logicalId:A}}static createIdentityPoolRoleAttachment(n,i){let{slug:s,environment:o,authenticatedRole:c,unauthenticatedRole:u,roleMappings:d}=i,g=r({slug:s,environment:o,resourceType:"identity-pool-role-attachment"}),y=t(g),h={authenticated:c};if(u)h.unauthenticated=u;return{attachment:{Type:"AWS::Cognito::IdentityPoolRoleAttachment",Properties:{IdentityPoolId:x.Ref(n),Roles:h,RoleMappings:d}},logicalId:y}}static createAuthenticatedRole(n){let{slug:i,environment:s,identityPoolLogicalId:o}=n,c=r({slug:i,environment:s,resourceType:"cognito-authenticated-role"}),u=t(c);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:c,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":x.Ref(o)},"ForAnyValue:StringLike":{"cognito-identity.amazonaws.com:amr":"authenticated"}}}]},Policies:[{PolicyName:"CognitoAuthenticatedPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["cognito-sync:*","cognito-identity:*"],Resource:"*"}]}}],Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:s}]}},logicalId:u}}static createUnauthenticatedRole(n){let{slug:i,environment:s,identityPoolLogicalId:o}=n,c=r({slug:i,environment:s,resourceType:"cognito-unauthenticated-role"}),u=t(c);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:c,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":x.Ref(o)},"ForAnyValue:StringLike":{"cognito-identity.amazonaws.com:amr":"unauthenticated"}}}]},Policies:[{PolicyName:"CognitoUnauthenticatedPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["cognito-sync:*"],Resource:"*"}]}}],Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:s}]}},logicalId:u}}static PasswordPolicies={relaxed:()=>({minimumLength:8,requireLowercase:!1,requireUppercase:!1,requireNumbers:!1,requireSymbols:!1,temporaryPasswordValidityDays:7}),standard:()=>({minimumLength:8,requireLowercase:!0,requireUppercase:!0,requireNumbers:!0,requireSymbols:!1,temporaryPasswordValidityDays:3}),strict:()=>({minimumLength:12,requireLowercase:!0,requireUppercase:!0,requireNumbers:!0,requireSymbols:!0,temporaryPasswordValidityDays:1})};static AuthFlows={standard:["ALLOW_USER_SRP_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],admin:["ALLOW_ADMIN_USER_PASSWORD_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],custom:["ALLOW_CUSTOM_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],all:["ALLOW_USER_SRP_AUTH","ALLOW_USER_PASSWORD_AUTH","ALLOW_ADMIN_USER_PASSWORD_AUTH","ALLOW_CUSTOM_AUTH","ALLOW_REFRESH_TOKEN_AUTH"]};static OAuthScopes={basic:["openid","email","profile"],all:["openid","email","profile","phone","aws.cognito.signin.user.admin"]};static UseCases={webApp:(n,i,s)=>{let{userPool:o,logicalId:c}=Y.createUserPool({slug:n,environment:i,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:Y.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:u,logicalId:d}=Y.createUserPoolClient(c,{slug:n,environment:i,explicitAuthFlows:[...Y.AuthFlows.standard],callbackURLs:[s],allowedOAuthFlows:["code"],allowedOAuthScopes:[...Y.OAuthScopes.basic],allowedOAuthFlowsUserPoolClient:!0});return{userPool:o,poolId:c,client:u,clientId:d}},mobileApp:(n,i)=>{let{userPool:s,logicalId:o}=Y.createUserPool({slug:n,environment:i,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:Y.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:c,logicalId:u}=Y.createUserPoolClient(o,{slug:n,environment:i,explicitAuthFlows:[...Y.AuthFlows.standard]}),{identityPool:d,logicalId:g}=Y.createIdentityPool({slug:n,environment:i,allowUnauthenticatedIdentities:!1,cognitoIdentityProviders:[{ClientId:x.Ref(u),ProviderName:x.GetAtt(o,"ProviderName")}]}),{role:y,logicalId:h}=Y.createAuthenticatedRole({slug:n,environment:i,identityPoolLogicalId:g}),{attachment:A,logicalId:C}=Y.createIdentityPoolRoleAttachment(g,{slug:n,environment:i,authenticatedRole:x.GetAtt(h,"Arn")});return{userPool:s,poolId:o,client:c,clientId:u,identityPool:d,identityPoolId:g,authRole:y,authRoleId:h,attachment:A,attachmentId:C}}}}import{createHash as xr}from"node:crypto";import{copyFileSync as kr,existsSync as Tt,readdirSync as Mr,readFileSync as ot,statSync as Lr,writeFileSync as ct}from"node:fs";import{basename as Or,dirname as cn,extname as yn,join as Ke}from"node:path";class Z{static createApplication(n){let{slug:i,environment:s,applicationName:o,computePlatform:c}=n,u=o||r({slug:i,environment:s,resourceType:"deploy-app"}),d=t(u);return{application:{Type:"AWS::CodeDeploy::Application",Properties:{ApplicationName:u,ComputePlatform:c,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:s}]}},logicalId:d}}static createDeploymentGroup(n,i){let{slug:s,environment:o,deploymentGroupName:c,serviceRoleArn:u,autoScalingGroups:d,ec2TagFilters:g,deploymentConfigName:y,autoRollbackConfiguration:h,alarmConfiguration:A,loadBalancerInfo:C,blueGreenDeploymentConfiguration:v}=i,T=c||r({slug:s,environment:o,resourceType:"deploy-group"}),R=t(T);return{deploymentGroup:{Type:"AWS::CodeDeploy::DeploymentGroup",Properties:{ApplicationName:x.Ref(n),DeploymentGroupName:T,ServiceRoleArn:u,AutoScalingGroups:d,Ec2TagFilters:g?.map((I)=>({Key:I.key,Value:I.value,Type:I.type})),DeploymentConfigName:y,AutoRollbackConfiguration:h?{Enabled:h.enabled,Events:h.events}:void 0,AlarmConfiguration:A?{Enabled:A.enabled,Alarms:A.alarms?.map((I)=>({Name:I.name})),IgnorePollAlarmFailure:A.ignorePollAlarmFailure}:void 0,LoadBalancerInfo:C?{TargetGroupInfoList:C.targetGroupInfoList?.map((I)=>({Name:I.name})),ElbInfoList:C.elbInfoList?.map((I)=>({Name:I.name}))}:void 0,BlueGreenDeploymentConfiguration:v?{TerminateBlueInstancesOnDeploymentSuccess:v.terminateBlueInstancesOnDeploymentSuccess?{Action:v.terminateBlueInstancesOnDeploymentSuccess.action,TerminationWaitTimeInMinutes:v.terminateBlueInstancesOnDeploymentSuccess.terminationWaitTimeInMinutes}:void 0,DeploymentReadyOption:v.deploymentReadyOption?{ActionOnTimeout:v.deploymentReadyOption.actionOnTimeout,WaitTimeInMinutes:v.deploymentReadyOption.waitTimeInMinutes}:void 0,GreenFleetProvisioningOption:v.greenFleetProvisioningOption?{Action:v.greenFleetProvisioningOption.action}:void 0}:void 0,Tags:[{Key:"Name",Value:T},{Key:"Environment",Value:o}]}},logicalId:R}}static createDeploymentConfig(n){let{slug:i,environment:s,deploymentConfigName:o,minimumHealthyHosts:c,trafficRoutingConfig:u}=n,d=o||r({slug:i,environment:s,resourceType:"deploy-config"}),g=t(d);return{deploymentConfig:{Type:"AWS::CodeDeploy::DeploymentConfig",Properties:{DeploymentConfigName:d,MinimumHealthyHosts:c?{Type:c.type,Value:c.value}:void 0,TrafficRoutingConfig:u?{Type:u.type,TimeBasedCanary:u.timeBasedCanary?{CanaryPercentage:u.timeBasedCanary.canaryPercentage,CanaryInterval:u.timeBasedCanary.canaryInterval}:void 0,TimeBasedLinear:u.timeBasedLinear?{LinearPercentage:u.timeBasedLinear.linearPercentage,LinearInterval:u.timeBasedLinear.linearInterval}:void 0}:void 0}},logicalId:g}}static DeploymentConfigs={allAtOnce:()=>({type:"FLEET_PERCENT",value:0}),halfAtATime:()=>({type:"FLEET_PERCENT",value:50}),oneAtATime:()=>({type:"HOST_COUNT",value:1}),custom:(n,i)=>({type:n,value:i})};static TrafficRouting={allAtOnce:()=>({type:"AllAtOnce"}),canary:(n,i)=>({type:"TimeBasedCanary",timeBasedCanary:{canaryPercentage:n,canaryInterval:i}}),linear:(n,i)=>({type:"TimeBasedLinear",timeBasedLinear:{linearPercentage:n,linearInterval:i}})};static RollbackConfigs={onFailure:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE"]}),onAlarmOrFailure:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE","DEPLOYMENT_STOP_ON_ALARM"]}),onAllEvents:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE","DEPLOYMENT_STOP_ON_ALARM","DEPLOYMENT_STOP_ON_REQUEST"]}),disabled:()=>({enabled:!1})};static BlueGreenConfigs={standard:()=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withDelay:(n)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:n},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withManualApproval:(n)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"STOP_DEPLOYMENT",waitTimeInMinutes:n},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),keepBlue:()=>({terminateBlueInstancesOnDeploymentSuccess:{action:"KEEP_ALIVE"},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}})};static UseCases={ec2Deployment:(n,i,s,o)=>{let{application:c,logicalId:u}=Z.createApplication({slug:n,environment:i,computePlatform:"Server"}),{deploymentGroup:d,logicalId:g}=Z.createDeploymentGroup(u,{slug:n,environment:i,serviceRoleArn:s,autoScalingGroups:o,deploymentConfigName:"CodeDeployDefault.OneAtATime",autoRollbackConfiguration:Z.RollbackConfigs.onFailure()});return{application:c,appId:u,deploymentGroup:d,groupId:g}},lambdaCanaryDeployment:(n,i,s,o=10,c=5)=>{let{application:u,logicalId:d}=Z.createApplication({slug:n,environment:i,computePlatform:"Lambda"}),{deploymentConfig:g,logicalId:y}=Z.createDeploymentConfig({slug:n,environment:i,trafficRoutingConfig:Z.TrafficRouting.canary(o,c)}),{deploymentGroup:h,logicalId:A}=Z.createDeploymentGroup(d,{slug:n,environment:i,serviceRoleArn:s,deploymentConfigName:x.Ref(y),autoRollbackConfiguration:Z.RollbackConfigs.onAlarmOrFailure()});return{application:u,appId:d,deploymentConfig:g,configId:y,deploymentGroup:h,groupId:A}},ecsBlueGreenDeployment:(n,i,s,o)=>{let{application:c,logicalId:u}=Z.createApplication({slug:n,environment:i,computePlatform:"ECS"}),{deploymentGroup:d,logicalId:g}=Z.createDeploymentGroup(u,{slug:n,environment:i,serviceRoleArn:s,loadBalancerInfo:{targetGroupInfoList:[{name:o}]},blueGreenDeploymentConfiguration:Z.BlueGreenConfigs.standard(),autoRollbackConfiguration:Z.RollbackConfigs.onFailure()});return{application:c,appId:u,deploymentGroup:d,groupId:g}}};static Strategies={rolling:(n=25)=>({type:"rolling",batchPercentage:n}),blueGreen:()=>({type:"blue-green"}),canary:(n=10,i=5)=>({type:"canary",canaryPercentage:n,canaryInterval:i}),allAtOnce:()=>({type:"all-at-once"})}}class _{static ContentTypes={".html":"text/html",".htm":"text/html",".css":"text/css",".js":"application/javascript",".mjs":"application/javascript",".json":"application/json",".xml":"application/xml",".svg":"image/svg+xml",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".avif":"image/avif",".ico":"image/x-icon",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".otf":"font/otf",".eot":"application/vnd.ms-fontobject",".pdf":"application/pdf",".txt":"text/plain",".md":"text/markdown",".map":"application/json"};static NoHashPatterns=[/^index\.html$/,/^favicon\.ico$/,/^robots\.txt$/,/^sitemap\.xml$/,/^manifest\.json$/,/^\.well-known\//,/^_redirects$/,/^_headers$/];static computeFileHash(n,i="md5"){let s=ot(n);return xr(i).update(s).digest("hex")}static computeShortHash(n){return _.computeFileHash(n).slice(0,8)}static getContentType(n){let i=yn(n).toLowerCase();return _.ContentTypes[i]||"application/octet-stream"}static shouldHashFile(n,i){return![..._.NoHashPatterns,...i||[]].some((o)=>o.test(n))}static generateHashedFilename(n,i){let s=yn(n),o=Or(n,s),c=cn(n);if(c===".")return`${o}.${i}${s}`;return Ke(c,`${o}.${i}${s}`)}static collectFiles(n,i){let s=[],o=i||n;if(!Tt(n))return s;let c=Mr(n,{withFileTypes:!0});for(let u of c){let d=Ke(n,u.name);if(u.isDirectory())s.push(..._.collectFiles(d,o));else if(u.isFile())s.push(d)}return s}static hashDirectory(n){let{sourceDir:i,outputDir:s,excludePatterns:o=[],hashAlgorithm:c="md5",copyUnhashed:u=!0}=n,d=_.collectFiles(i),g=[],y={};for(let A of d){let C=A.replace(i,"").replace(/^[/\\]/,""),v=_.shouldHashFile(C,o),T=Lr(A),R=v?_.computeFileHash(A,c).slice(0,8):"",P=v?_.generateHashedFilename(C,R):C,I={originalPath:C,hashedPath:P,hash:R,size:T.size,contentType:_.getContentType(A)};if(g.push(I),y[C]=P,s){let M=Ke(s,P),L=cn(M);if(!Tt(L)){let{mkdirSync:N}=st("node:fs");N(L,{recursive:!0})}if(v||u)kr(A,M)}}let h={version:"1.0",timestamp:new Date().toISOString(),assets:g,hashMap:y};if(s){let A=Ke(s,"asset-manifest.json");ct(A,JSON.stringify(h,null,2))}return h}static getInvalidationPaths(n,i){let s=[];if(!n)return["/*"];let o=n.hashMap,c=i.hashMap;for(let[u,d]of Object.entries(c)){let g=o[u];if(!g||g!==d){if(s.push(`/${u}`),g&&g!==d)s.push(`/${g}`)}}for(let[u,d]of Object.entries(o))if(!c[u])s.push(`/${u}`),s.push(`/${d}`);if(s.length>100)return["/*"];return[...new Set(s)]}static updateHtmlReferences(n){let{htmlDir:i,manifest:s,basePath:o=""}=n,c=_.collectFiles(i).filter((u)=>u.endsWith(".html")||u.endsWith(".htm"));for(let u of c){let d=ot(u,"utf-8");for(let[g,y]of Object.entries(s.hashMap)){if(g===y)continue;let h=[new RegExp(`(src|href)=["']${o}/?${_.escapeRegExp(g)}["']`,"g"),new RegExp(`url\\(["']?${o}/?${_.escapeRegExp(g)}["']?\\)`,"g")];for(let A of h)d=d.replace(A,(C)=>C.replace(g,y))}ct(u,d)}}static updateCssReferences(n){let{cssDir:i,manifest:s,basePath:o=""}=n,c=_.collectFiles(i).filter((u)=>u.endsWith(".css"));for(let u of c){let d=ot(u,"utf-8");for(let[g,y]of Object.entries(s.hashMap)){if(g===y)continue;let h=new RegExp(`url\\(["']?${o}/?${_.escapeRegExp(g)}["']?\\)`,"g");d=d.replace(h,`url(${o}/${y})`)}ct(u,d)}}static escapeRegExp(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}static generateS3DeploymentManifest(n){let{sourceDir:i,keyPrefix:s="",excludePatterns:o=[],cacheControl:c={hashed:"public, max-age=31536000, immutable",unhashed:"public, max-age=3600",html:"public, max-age=0, must-revalidate"}}=n;return _.hashDirectory({sourceDir:i,excludePatterns:o}).assets.map((d)=>{let g=d.hash!=="",y=d.contentType==="text/html",h=c.unhashed||"public, max-age=3600";if(y)h=c.html||"public, max-age=0, must-revalidate";else if(g)h=c.hashed||"public, max-age=31536000, immutable";return{localPath:Ke(i,d.originalPath),s3Key:s?`${s}/${d.hashedPath}`:d.hashedPath,contentType:d.contentType,cacheControl:h,hash:d.hash}})}static compareManifests(n,i){let s={added:[],removed:[],changed:[],unchanged:[]},o=new Set(Object.keys(n.hashMap)),c=new Set(Object.keys(i.hashMap));for(let u of c)if(!o.has(u))s.added.push(u);for(let u of o)if(!c.has(u))s.removed.push(u);for(let u of c)if(o.has(u))if(n.hashMap[u]!==i.hashMap[u])s.changed.push(u);else s.unchanged.push(u);return s}static loadManifest(n){if(!Tt(n))return null;try{let i=ot(n,"utf-8");return JSON.parse(i)}catch{return null}}static saveManifest(n,i){ct(i,JSON.stringify(n,null,2))}}class Yi{static createSecret(n){let{slug:i,environment:s,secretName:o,description:c,secretString:u,kmsKeyId:d,tags:g}=n,y=o||r({slug:i,environment:s,resourceType:"secret"}),h=t(y),A={Type:"AWS::SecretsManager::Secret",Properties:{Name:y,Description:c,SecretString:u,Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:s},...g?Object.entries(g).map(([C,v])=>({Key:C,Value:v})):[]]}};if(d)A.Properties.KmsKeyId=d;return{secret:A,logicalId:h}}static createGeneratedSecret(n){let{slug:i,environment:s,secretName:o,description:c,excludeCharacters:u,excludeLowercase:d,excludeNumbers:g,excludePunctuation:y,excludeUppercase:h,passwordLength:A,requireEachIncludedType:C,kmsKeyId:v,tags:T}=n,R=o||r({slug:i,environment:s,resourceType:"secret"}),P=t(R),I={Type:"AWS::SecretsManager::Secret",Properties:{Name:R,Description:c,GenerateSecretString:{ExcludeCharacters:u,ExcludeLowercase:d,ExcludeNumbers:g,ExcludePunctuation:y,ExcludeUppercase:h,PasswordLength:A||32,RequireEachIncludedType:C!==!1},Tags:[{Key:"Name",Value:R},{Key:"Environment",Value:s},...T?Object.entries(T).map(([M,L])=>({Key:M,Value:L})):[]]}};if(v)I.Properties.KmsKeyId=v;return{secret:I,logicalId:P}}static createDatabaseSecret(n){let{slug:i,environment:s,secretName:o,username:c,dbname:u,engine:d,host:g,port:y,kmsKeyId:h}=n,A=o||r({slug:i,environment:s,resourceType:"db-secret"}),C=t(A),v={username:c};if(u)v.dbname=u;if(d)v.engine=d;if(g)v.host=g;if(y)v.port=y;let T={Type:"AWS::SecretsManager::Secret",Properties:{Name:A,Description:`Database credentials for ${c}`,GenerateSecretString:{SecretStringTemplate:JSON.stringify(v),GenerateStringKey:"password",PasswordLength:32,ExcludeCharacters:'"@/\\',RequireEachIncludedType:!0},Tags:[{Key:"Name",Value:A},{Key:"Environment",Value:s},{Key:"Type",Value:"database"}]}};if(h)T.Properties.KmsKeyId=h;return{secret:T,logicalId:C}}static attachToDatabase(n){let{slug:i,environment:s,secretId:o,targetId:c,targetType:u}=n,d=r({slug:i,environment:s,resourceType:"secret-attachment"}),g=t(d);return{attachment:{Type:"AWS::SecretsManager::SecretTargetAttachment",Properties:{SecretId:o,TargetId:c,TargetType:u}},logicalId:g}}static enableRotation(n){let{slug:i,environment:s,secretId:o,rotationLambdaArn:c,automaticallyAfterDays:u,rotationType:d,kmsKeyArn:g,vpcSecurityGroupIds:y,vpcSubnetIds:h}=n,A=r({slug:i,environment:s,resourceType:"secret-rotation"}),C=t(A),v={Type:"AWS::SecretsManager::RotationSchedule",Properties:{SecretId:o,RotationRules:{AutomaticallyAfterDays:u||30}}};if(c)v.Properties.RotationLambdaARN=c;else if(d)v.Properties.HostedRotationLambda={RotationType:d,KmsKeyArn:g,VpcSecurityGroupIds:y,VpcSubnetIds:h};return{rotation:v,logicalId:C}}static SecretTypes={apiKey:(n,i,s)=>Yi.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-${s}-api-key`,description:`API key for ${s}`,passwordLength:32,excludePunctuation:!0,excludeLowercase:!1,excludeUppercase:!1,excludeNumbers:!1}),oauthClientSecret:(n,i,s)=>Yi.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-${s}-oauth-secret`,description:`OAuth client secret for ${s}`,passwordLength:64,excludeCharacters:"\"'`\\/@",requireEachIncludedType:!0}),jwtSecret:(n,i)=>Yi.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-jwt-secret`,description:"JWT signing secret",passwordLength:64,excludePunctuation:!0}),encryptionKey:(n,i)=>Yi.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-encryption-key`,description:"Data encryption key",passwordLength:64,excludeCharacters:"+/=",excludePunctuation:!0})};static RotationTypes={MySQLSingleUser:"MySQLSingleUser",MySQLMultiUser:"MySQLMultiUser",PostgreSQLSingleUser:"PostgreSQLSingleUser",PostgreSQLMultiUser:"PostgreSQLMultiUser",OracleSingleUser:"OracleSingleUser",OracleMultiUser:"OracleMultiUser",MariaDBSingleUser:"MariaDBSingleUser",MariaDBMultiUser:"MariaDBMultiUser",SQLServerSingleUser:"SQLServerSingleUser",SQLServerMultiUser:"SQLServerMultiUser",RedshiftSingleUser:"RedshiftSingleUser",RedshiftMultiUser:"RedshiftMultiUser",MongoDBSingleUser:"MongoDBSingleUser",MongoDBMultiUser:"MongoDBMultiUser"}}class D{static createParameter(n){let{slug:i,environment:s,parameterName:o,value:c,type:u="String",description:d,tier:g="Standard",tags:y}=n,h=o||r({slug:i,environment:s,resourceType:"parameter"}),A=t(h);return{parameter:{Type:"AWS::SSM::Parameter",Properties:{Name:`/${i}/${s}/${h}`,Type:u,Value:c,Description:d,Tier:g,Tags:{Name:h,Environment:s,...y}}},logicalId:A}}static createString(n,i,s,o,c){return D.createParameter({slug:n,environment:i,parameterName:s,value:o,type:"String",description:c})}static createSecureString(n,i,s,o,c){return D.createParameter({slug:n,environment:i,parameterName:s,value:o,type:"SecureString",description:c})}static createStringList(n,i,s,o,c){return D.createParameter({slug:n,environment:i,parameterName:s,value:o.join(","),type:"StringList",description:c})}static Parameters={databaseUrl:(n,i,s)=>D.createSecureString(n,i,"database-url",s,"Database connection URL"),apiEndpoint:(n,i,s)=>D.createString(n,i,"api-endpoint",s,"API endpoint URL"),appVersion:(n,i,s)=>D.createString(n,i,"app-version",s,"Application version"),featureFlags:(n,i,s)=>D.createStringList(n,i,"feature-flags",s,"Enabled feature flags"),apiKey:(n,i,s,o)=>D.createSecureString(n,i,`${s}-api-key`,o,`API key for ${s}`),oauthCredentials:(n,i,s,o)=>{let c=D.createString(n,i,"oauth-client-id",s,"OAuth client ID"),u=D.createSecureString(n,i,"oauth-client-secret",o,"OAuth client secret");return{clientId:c,clientSecret:u}},smtpCredentials:(n,i,s,o,c,u)=>{let d=D.createString(n,i,"smtp-username",s,"SMTP username"),g=D.createSecureString(n,i,"smtp-password",o,"SMTP password"),y=D.createString(n,i,"smtp-host",c,"SMTP host"),h=D.createString(n,i,"smtp-port",u.toString(),"SMTP port");return{username:d,password:g,host:y,port:h}},redisUrl:(n,i,s)=>D.createSecureString(n,i,"redis-url",s,"Redis connection URL"),s3Bucket:(n,i,s)=>D.createString(n,i,"s3-bucket",s,"S3 bucket name"),cloudFrontDistribution:(n,i,s)=>D.createString(n,i,"cloudfront-distribution-id",s,"CloudFront distribution ID")}}class gr{static createDomain(n){let{slug:i,environment:s,domainName:o,engineVersion:c="OpenSearch_2.11",instanceType:u="t3.small.search",instanceCount:d=1,volumeSize:g=10,volumeType:y="gp3",dedicatedMaster:h=!1,dedicatedMasterType:A,dedicatedMasterCount:C=3,multiAz:v=!1,availabilityZoneCount:T=2,vpc:R,encryption:P,enforceHttps:I=!0,tlsSecurityPolicy:M="Policy-Min-TLS-1-2-2019-07",advancedSecurity:L,autoSnapshotHour:N=0,autoTune:O=!0,tags:B={}}=n,F=o||r({slug:i,environment:s,resourceType:"search"}),U=t(F);return{domain:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:F,EngineVersion:c,ClusterConfig:{InstanceType:u,InstanceCount:d,DedicatedMasterEnabled:h,...h&&{DedicatedMasterType:A||u,DedicatedMasterCount:C},ZoneAwarenessEnabled:v,...v&&{ZoneAwarenessConfig:{AvailabilityZoneCount:T}}},EBSOptions:{EBSEnabled:!0,VolumeType:y,VolumeSize:g},DomainEndpointOptions:{EnforceHTTPS:I,TLSSecurityPolicy:M},SnapshotOptions:{AutomatedSnapshotStartHour:N},...R&&{VPCOptions:{SubnetIds:R.subnetIds,SecurityGroupIds:R.securityGroupIds}},...P&&{EncryptionAtRestOptions:{Enabled:P.atRest??!0,...P.kmsKeyId&&{KmsKeyId:P.kmsKeyId}},NodeToNodeEncryptionOptions:{Enabled:P.nodeToNode??!0}},...L&&{AdvancedSecurityOptions:{Enabled:L.enabled,InternalUserDatabaseEnabled:L.internalUserDatabase??!0,...L.masterUserName&&L.masterUserPassword&&{MasterUserOptions:{MasterUserName:L.masterUserName,MasterUserPassword:L.masterUserPassword}},...L.masterUserArn&&{MasterUserOptions:{MasterUserARN:L.masterUserArn}}}},...O&&{AutoTuneOptions:{DesiredState:"ENABLED"}},Tags:[{Key:"Name",Value:F},{Key:"Environment",Value:s},...Object.entries(B).map(([H,z])=>({Key:H,Value:z}))]}},logicalId:U}}static createAccessPolicy(n,i){let{ipAddresses:s,iamPrincipalArns:o,allowAll:c,vpcEndpoint:u}=i;if(c)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:n}]};let d=[];if(o&&o.length>0)d.push({Effect:"Allow",Principal:{AWS:o},Action:"es:*",Resource:n});if(s&&s.length>0)d.push({Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:n,Condition:{IpAddress:{"aws:SourceIp":s}}});if(u)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:n}]};return{Version:"2012-10-17",Statement:d}}static DomainPresets={development:(n,i)=>gr.createDomain({slug:n,environment:i,instanceType:"t3.small.search",instanceCount:1,volumeSize:10,multiAz:!1,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!1}),production:(n,i,s)=>gr.createDomain({slug:n,environment:i,instanceType:"m6g.large.search",instanceCount:3,volumeSize:100,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"m6g.large.search",dedicatedMasterCount:3,vpc:s,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!0},autoTune:!0}),costOptimized:(n,i)=>gr.createDomain({slug:n,environment:i,instanceType:"t3.medium.search",instanceCount:2,volumeSize:20,volumeType:"gp3",multiAz:!0,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!0}),highPerformance:(n,i,s)=>gr.createDomain({slug:n,environment:i,instanceType:"r6g.2xlarge.search",instanceCount:6,volumeSize:500,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"c6g.xlarge.search",dedicatedMasterCount:3,vpc:s,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!1},autoTune:!0})};static InstanceTypes={"t3.small.search":"t3.small.search","t3.medium.search":"t3.medium.search","m6g.large.search":"m6g.large.search","m6g.xlarge.search":"m6g.xlarge.search","m6g.2xlarge.search":"m6g.2xlarge.search","r6g.large.search":"r6g.large.search","r6g.xlarge.search":"r6g.xlarge.search","r6g.2xlarge.search":"r6g.2xlarge.search","r6g.4xlarge.search":"r6g.4xlarge.search","c6g.large.search":"c6g.large.search","c6g.xlarge.search":"c6g.xlarge.search","c6g.2xlarge.search":"c6g.2xlarge.search"};static EngineVersions={"OpenSearch_2.11":"OpenSearch_2.11","OpenSearch_2.9":"OpenSearch_2.9","OpenSearch_2.7":"OpenSearch_2.7","OpenSearch_1.3":"OpenSearch_1.3","Elasticsearch_7.10":"Elasticsearch_7.10"}}class xt{static createDomainRedirectBucket(n){let{slug:i,environment:s,sourceDomain:o,targetDomain:c,protocol:u="https"}=n,d=r({slug:i,environment:s,resourceType:"s3",suffix:"redirect"}),g=t(d),y=t(`${d}-policy`),h={Type:"AWS::S3::Bucket",Properties:{BucketName:o,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:c,Protocol:u}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1},Tags:[{Key:"Name",Value:d},{Key:"Environment",Value:s},{Key:"Purpose",Value:"Domain Redirect"}]}},A={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:x.Ref(g),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[x.Join("",[x.GetAtt(g,"Arn"),"/*"])]}]}}};return{bucket:h,bucketPolicy:A,logicalId:g,policyLogicalId:y}}static createPathRedirectFunction(n){let{slug:i,environment:s,rules:o}=n,c=r({slug:i,environment:s,resourceType:"cf-redirect"}),u=t(c),d=xt.generateRedirectFunctionCode(o);return{function:{Type:"AWS::CloudFront::Function",Properties:{Name:c,AutoPublish:!0,FunctionConfig:{Comment:`Path redirect function for ${i} (${s})`,Runtime:"cloudfront-js-2.0"},FunctionCode:d}},logicalId:u,functionCode:d}}static generateRedirectFunctionCode(n){return`function handler(event) {
2281
+ | limit 50`,region:o,title:"Recent Errors and Warnings"}}),d+=6;return Yo.createDashboard({slug:i,environment:s,widgets:u})}static DashboardTemplates={staticWebsite:(n)=>({slug:n.slug,environment:n.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${n.slug.toUpperCase()} Static Website Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"CloudFront Requests",region:"us-east-1",metrics:[["AWS/CloudFront","Requests","DistributionId",n.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"Error Rate",region:"us-east-1",metrics:[["AWS/CloudFront","4xxErrorRate","DistributionId",n.cloudFrontDistributionId,"Region","Global",{label:"4XX"}],["AWS/CloudFront","5xxErrorRate","DistributionId",n.cloudFrontDistributionId,"Region","Global",{label:"5XX"}]],period:300,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Bytes Downloaded",region:"us-east-1",metrics:[["AWS/CloudFront","BytesDownloaded","DistributionId",n.cloudFrontDistributionId,"Region","Global"]],period:300,stat:"Sum"}},{type:"metric",x:0,y:7,width:12,height:6,properties:{title:"S3 Bucket Size",region:n.region||"us-east-1",metrics:[["AWS/S3","BucketSizeBytes","BucketName",n.s3BucketName,"StorageType","StandardStorage"]],period:86400,stat:"Average"}},{type:"metric",x:12,y:7,width:12,height:6,properties:{title:"S3 Number of Objects",region:n.region||"us-east-1",metrics:[["AWS/S3","NumberOfObjects","BucketName",n.s3BucketName,"StorageType","AllStorageTypes"]],period:86400,stat:"Average"}}]}),serverlessApi:(n)=>({slug:n.slug,environment:n.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${n.slug.toUpperCase()} Serverless API Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"API Requests",region:n.region||"us-east-1",metrics:[["AWS/ApiGateway","Count","ApiName",n.apiGatewayName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"API Latency",region:n.region||"us-east-1",metrics:[["AWS/ApiGateway","Latency","ApiName",n.apiGatewayName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"API Errors",region:n.region||"us-east-1",metrics:[["AWS/ApiGateway","4XXError","ApiName",n.apiGatewayName,{label:"4XX"}],["AWS/ApiGateway","5XXError","ApiName",n.apiGatewayName,{label:"5XX"}]],period:60,stat:"Sum"}},...n.lambdaFunctionNames.map((i,s)=>({type:"metric",x:s%3*8,y:7+Math.floor(s/3)*6,width:8,height:6,properties:{title:`${i} Metrics`,region:n.region||"us-east-1",metrics:[["AWS/Lambda","Invocations","FunctionName",i],["AWS/Lambda","Duration","FunctionName",i],["AWS/Lambda","Errors","FunctionName",i]],period:300,stat:"Sum"}}))]}),containerService:(n)=>({slug:n.slug,environment:n.environment,widgets:[{type:"text",x:0,y:0,width:24,height:1,properties:{markdown:`# ${n.slug.toUpperCase()} Container Service Dashboard`}},{type:"metric",x:0,y:1,width:8,height:6,properties:{title:"ECS CPU",region:n.region||"us-east-1",metrics:[["AWS/ECS","CPUUtilization","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:8,y:1,width:8,height:6,properties:{title:"ECS Memory",region:n.region||"us-east-1",metrics:[["AWS/ECS","MemoryUtilization","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:16,y:1,width:8,height:6,properties:{title:"Running Tasks",region:n.region||"us-east-1",metrics:[["ECS/ContainerInsights","RunningTaskCount","ClusterName",n.ecsClusterName,"ServiceName",n.ecsServiceName]],period:60,stat:"Average"}},{type:"metric",x:0,y:7,width:8,height:6,properties:{title:"ALB Requests",region:n.region||"us-east-1",metrics:[["AWS/ApplicationELB","RequestCount","LoadBalancer",n.albName]],period:60,stat:"Sum"}},{type:"metric",x:8,y:7,width:8,height:6,properties:{title:"Response Time",region:n.region||"us-east-1",metrics:[["AWS/ApplicationELB","TargetResponseTime","LoadBalancer",n.albName]],period:60,stat:"Average"}},{type:"metric",x:16,y:7,width:8,height:6,properties:{title:"Healthy Hosts",region:n.region||"us-east-1",metrics:[["AWS/ApplicationELB","HealthyHostCount","LoadBalancer",n.albName]],period:60,stat:"Average"}},...n.rdsInstanceId?[{type:"metric",x:0,y:13,width:12,height:6,properties:{title:"RDS CPU",region:n.region||"us-east-1",metrics:[["AWS/RDS","CPUUtilization","DBInstanceIdentifier",n.rdsInstanceId]],period:300,stat:"Average"}},{type:"metric",x:12,y:13,width:12,height:6,properties:{title:"RDS Connections",region:n.region||"us-east-1",metrics:[["AWS/RDS","DatabaseConnections","DBInstanceIdentifier",n.rdsInstanceId]],period:60,stat:"Sum"}}]:[]]})};static Config={createAlarmConfig:(n)=>{let{metricName:i,namespace:s,threshold:o,comparisonOperator:c="GreaterThanThreshold",evaluationPeriods:u=1,period:d=300,statistic:g="Average",treatMissingData:y="missing"}=n;return{MetricName:i,Namespace:s,Threshold:o,ComparisonOperator:c,EvaluationPeriods:u,Period:d,Statistic:g,TreatMissingData:y}},namespaces:{ec2:"AWS/EC2",ecs:"AWS/ECS",lambda:"AWS/Lambda",rds:"AWS/RDS",sqs:"AWS/SQS",sns:"AWS/SNS",s3:"AWS/S3",cloudfront:"AWS/CloudFront",alb:"AWS/ApplicationELB",nlb:"AWS/NetworkELB",apiGateway:"AWS/ApiGateway",dynamodb:"AWS/DynamoDB",elasticache:"AWS/ElastiCache"},comparisonOperators:{greaterThan:"GreaterThanThreshold",greaterOrEqual:"GreaterThanOrEqualToThreshold",lessThan:"LessThanThreshold",lessOrEqual:"LessThanOrEqualToThreshold"},metrics:{ec2:{cpu:{metricName:"CPUUtilization",namespace:"AWS/EC2"},networkIn:{metricName:"NetworkIn",namespace:"AWS/EC2"},networkOut:{metricName:"NetworkOut",namespace:"AWS/EC2"},statusCheck:{metricName:"StatusCheckFailed",namespace:"AWS/EC2"}},ecs:{cpu:{metricName:"CPUUtilization",namespace:"AWS/ECS"},memory:{metricName:"MemoryUtilization",namespace:"AWS/ECS"}},lambda:{invocations:{metricName:"Invocations",namespace:"AWS/Lambda"},errors:{metricName:"Errors",namespace:"AWS/Lambda"},duration:{metricName:"Duration",namespace:"AWS/Lambda"},throttles:{metricName:"Throttles",namespace:"AWS/Lambda"},concurrentExecutions:{metricName:"ConcurrentExecutions",namespace:"AWS/Lambda"}},rds:{cpu:{metricName:"CPUUtilization",namespace:"AWS/RDS"},connections:{metricName:"DatabaseConnections",namespace:"AWS/RDS"},freeStorage:{metricName:"FreeStorageSpace",namespace:"AWS/RDS"},readLatency:{metricName:"ReadLatency",namespace:"AWS/RDS"},writeLatency:{metricName:"WriteLatency",namespace:"AWS/RDS"}},alb:{requestCount:{metricName:"RequestCount",namespace:"AWS/ApplicationELB"},responseTime:{metricName:"TargetResponseTime",namespace:"AWS/ApplicationELB"},httpCode4xx:{metricName:"HTTPCode_Target_4XX_Count",namespace:"AWS/ApplicationELB"},httpCode5xx:{metricName:"HTTPCode_Target_5XX_Count",namespace:"AWS/ApplicationELB"},healthyHosts:{metricName:"HealthyHostCount",namespace:"AWS/ApplicationELB"}},sqs:{messagesVisible:{metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS"},messagesDelayed:{metricName:"ApproximateNumberOfMessagesDelayed",namespace:"AWS/SQS"},messageAge:{metricName:"ApproximateAgeOfOldestMessage",namespace:"AWS/SQS"}}},presets:{highCpu:(n=80)=>({metricName:"CPUUtilization",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highMemory:(n=80)=>({metricName:"MemoryUtilization",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),highErrors:(n=10)=>({metricName:"Errors",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:1,period:60,statistic:"Sum"}),highLatency:(n=5000)=>({metricName:"Duration",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowHealthyHosts:(n=1)=>({metricName:"HealthyHostCount",namespace:"AWS/ApplicationELB",threshold:n,comparisonOperator:"LessThanThreshold",evaluationPeriods:2,period:60,statistic:"Minimum"}),queueDepth:(n=1000)=>({metricName:"ApproximateNumberOfMessagesVisible",namespace:"AWS/SQS",threshold:n,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,period:300,statistic:"Average"}),lowStorage:(n=10737418240)=>({metricName:"FreeStorageSpace",namespace:"AWS/RDS",threshold:n,comparisonOperator:"LessThanThreshold",evaluationPeriods:1,period:300,statistic:"Average"})}}}class Z{static createUserPool(n){let{slug:i,environment:s,userPoolName:o,aliasAttributes:c,autoVerifiedAttributes:u,passwordPolicy:d,mfaConfiguration:g,emailConfiguration:y,smsConfiguration:h,lambdaTriggers:A,userPoolAddOns:C,accountRecoverySetting:v}=n,T=o||r({slug:i,environment:s,resourceType:"user-pool"}),R=t(T),P={Type:"AWS::Cognito::UserPool",Properties:{UserPoolName:T,Policies:d?{PasswordPolicy:{MinimumLength:d.minimumLength,RequireLowercase:d.requireLowercase,RequireUppercase:d.requireUppercase,RequireNumbers:d.requireNumbers,RequireSymbols:d.requireSymbols,TemporaryPasswordValidityDays:d.temporaryPasswordValidityDays}}:void 0,MfaConfiguration:g,Schema:[{Name:"email",AttributeDataType:"String",Required:!0,Mutable:!1}]}};if(c&&c.length>0)P.Properties.UsernameAttributes=c;if(u&&u.length>0)P.Properties.AutoVerifiedAttributes=u;if(y)P.Properties.EmailConfiguration={EmailSendingAccount:y.emailSendingAccount,From:y.from,ReplyToEmailAddress:y.replyToEmailAddress,SourceArn:y.sourceArn,ConfigurationSet:y.configurationSet};if(h)P.Properties.SmsConfiguration={ExternalId:h.externalId,SnsCallerArn:h.snsCallerArn};if(A)P.Properties.LambdaConfig={PreSignUp:A.preSignUp,PostConfirmation:A.postConfirmation,PreAuthentication:A.preAuthentication,PostAuthentication:A.postAuthentication,CustomMessage:A.customMessage,DefineAuthChallenge:A.defineAuthChallenge,CreateAuthChallenge:A.createAuthChallenge,VerifyAuthChallengeResponse:A.verifyAuthChallengeResponse,PreTokenGeneration:A.preTokenGeneration,UserMigration:A.userMigration};if(C)P.Properties.UserPoolAddOns={AdvancedSecurityMode:C.advancedSecurityMode};if(v)P.Properties.AccountRecoverySetting={RecoveryMechanisms:v.recoveryMechanisms};return{userPool:P,logicalId:R}}static createUserPoolClient(n,i){let{slug:s,environment:o,clientName:c,generateSecret:u=!1,refreshTokenValidity:d,accessTokenValidity:g,idTokenValidity:y,tokenValidityUnits:h,readAttributes:A,writeAttributes:C,explicitAuthFlows:v,preventUserExistenceErrors:T,enableTokenRevocation:R,callbackURLs:P,logoutURLs:I,allowedOAuthFlows:O,allowedOAuthScopes:B,allowedOAuthFlowsUserPoolClient:x,supportedIdentityProviders:F}=i,G=c||r({slug:s,environment:o,resourceType:"user-pool-client"}),_=t(G);return{client:{Type:"AWS::Cognito::UserPoolClient",Properties:{ClientName:G,UserPoolId:M.Ref(n),GenerateSecret:u,RefreshTokenValidity:d,AccessTokenValidity:g,IdTokenValidity:y,TokenValidityUnits:h,ReadAttributes:A,WriteAttributes:C,ExplicitAuthFlows:v,PreventUserExistenceErrors:T,EnableTokenRevocation:R,CallbackURLs:P,LogoutURLs:I,AllowedOAuthFlows:O,AllowedOAuthScopes:B,AllowedOAuthFlowsUserPoolClient:x,SupportedIdentityProviders:F}},logicalId:_}}static createUserPoolDomain(n,i){let{slug:s,environment:o,domain:c,customDomainConfig:u}=i,d=r({slug:s,environment:o,resourceType:"user-pool-domain"}),g=t(d);return{domain:{Type:"AWS::Cognito::UserPoolDomain",Properties:{Domain:c,UserPoolId:M.Ref(n),CustomDomainConfig:u}},logicalId:g}}static createIdentityPool(n){let{slug:i,environment:s,identityPoolName:o,allowUnauthenticatedIdentities:c=!1,cognitoIdentityProviders:u,supportedLoginProviders:d,samlProviderARNs:g,openIdConnectProviderARNs:y}=n,h=o||r({slug:i,environment:s,resourceType:"identity-pool"}),A=t(h);return{identityPool:{Type:"AWS::Cognito::IdentityPool",Properties:{IdentityPoolName:h,AllowUnauthenticatedIdentities:c,CognitoIdentityProviders:u,SupportedLoginProviders:d,SamlProviderARNs:g,OpenIdConnectProviderARNs:y}},logicalId:A}}static createIdentityPoolRoleAttachment(n,i){let{slug:s,environment:o,authenticatedRole:c,unauthenticatedRole:u,roleMappings:d}=i,g=r({slug:s,environment:o,resourceType:"identity-pool-role-attachment"}),y=t(g),h={authenticated:c};if(u)h.unauthenticated=u;return{attachment:{Type:"AWS::Cognito::IdentityPoolRoleAttachment",Properties:{IdentityPoolId:M.Ref(n),Roles:h,RoleMappings:d}},logicalId:y}}static createAuthenticatedRole(n){let{slug:i,environment:s,identityPoolLogicalId:o}=n,c=r({slug:i,environment:s,resourceType:"cognito-authenticated-role"}),u=t(c);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:c,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":M.Ref(o)},"ForAnyValue:StringLike":{"cognito-identity.amazonaws.com:amr":"authenticated"}}}]},Policies:[{PolicyName:"CognitoAuthenticatedPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["cognito-sync:*","cognito-identity:*"],Resource:"*"}]}}],Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:s}]}},logicalId:u}}static createUnauthenticatedRole(n){let{slug:i,environment:s,identityPoolLogicalId:o}=n,c=r({slug:i,environment:s,resourceType:"cognito-unauthenticated-role"}),u=t(c);return{role:{Type:"AWS::IAM::Role",Properties:{RoleName:c,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Federated:"cognito-identity.amazonaws.com"},Action:"sts:AssumeRoleWithWebIdentity",Condition:{StringEquals:{"cognito-identity.amazonaws.com:aud":M.Ref(o)},"ForAnyValue:StringLike":{"cognito-identity.amazonaws.com:amr":"unauthenticated"}}}]},Policies:[{PolicyName:"CognitoUnauthenticatedPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["cognito-sync:*"],Resource:"*"}]}}],Tags:[{Key:"Name",Value:c},{Key:"Environment",Value:s}]}},logicalId:u}}static PasswordPolicies={relaxed:()=>({minimumLength:8,requireLowercase:!1,requireUppercase:!1,requireNumbers:!1,requireSymbols:!1,temporaryPasswordValidityDays:7}),standard:()=>({minimumLength:8,requireLowercase:!0,requireUppercase:!0,requireNumbers:!0,requireSymbols:!1,temporaryPasswordValidityDays:3}),strict:()=>({minimumLength:12,requireLowercase:!0,requireUppercase:!0,requireNumbers:!0,requireSymbols:!0,temporaryPasswordValidityDays:1})};static AuthFlows={standard:["ALLOW_USER_SRP_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],admin:["ALLOW_ADMIN_USER_PASSWORD_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],custom:["ALLOW_CUSTOM_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],all:["ALLOW_USER_SRP_AUTH","ALLOW_USER_PASSWORD_AUTH","ALLOW_ADMIN_USER_PASSWORD_AUTH","ALLOW_CUSTOM_AUTH","ALLOW_REFRESH_TOKEN_AUTH"]};static OAuthScopes={basic:["openid","email","profile"],all:["openid","email","profile","phone","aws.cognito.signin.user.admin"]};static UseCases={webApp:(n,i,s)=>{let{userPool:o,logicalId:c}=Z.createUserPool({slug:n,environment:i,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:Z.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:u,logicalId:d}=Z.createUserPoolClient(c,{slug:n,environment:i,explicitAuthFlows:[...Z.AuthFlows.standard],callbackURLs:[s],allowedOAuthFlows:["code"],allowedOAuthScopes:[...Z.OAuthScopes.basic],allowedOAuthFlowsUserPoolClient:!0});return{userPool:o,poolId:c,client:u,clientId:d}},mobileApp:(n,i)=>{let{userPool:s,logicalId:o}=Z.createUserPool({slug:n,environment:i,aliasAttributes:["email"],autoVerifiedAttributes:["email"],passwordPolicy:Z.PasswordPolicies.standard(),mfaConfiguration:"OPTIONAL"}),{client:c,logicalId:u}=Z.createUserPoolClient(o,{slug:n,environment:i,explicitAuthFlows:[...Z.AuthFlows.standard]}),{identityPool:d,logicalId:g}=Z.createIdentityPool({slug:n,environment:i,allowUnauthenticatedIdentities:!1,cognitoIdentityProviders:[{ClientId:M.Ref(u),ProviderName:M.GetAtt(o,"ProviderName")}]}),{role:y,logicalId:h}=Z.createAuthenticatedRole({slug:n,environment:i,identityPoolLogicalId:g}),{attachment:A,logicalId:C}=Z.createIdentityPoolRoleAttachment(g,{slug:n,environment:i,authenticatedRole:M.GetAtt(h,"Arn")});return{userPool:s,poolId:o,client:c,clientId:u,identityPool:d,identityPoolId:g,authRole:y,authRoleId:h,attachment:A,attachmentId:C}}}}import{createHash as jr}from"node:crypto";import{copyFileSync as Kr,existsSync as Pt,readdirSync as qr,readFileSync as ct,statSync as zr,writeFileSync as lt}from"node:fs";import{basename as Qr,dirname as Tn,extname as Rn,join as ze}from"node:path";class ee{static createApplication(n){let{slug:i,environment:s,applicationName:o,computePlatform:c}=n,u=o||r({slug:i,environment:s,resourceType:"deploy-app"}),d=t(u);return{application:{Type:"AWS::CodeDeploy::Application",Properties:{ApplicationName:u,ComputePlatform:c,Tags:[{Key:"Name",Value:u},{Key:"Environment",Value:s}]}},logicalId:d}}static createDeploymentGroup(n,i){let{slug:s,environment:o,deploymentGroupName:c,serviceRoleArn:u,autoScalingGroups:d,ec2TagFilters:g,deploymentConfigName:y,autoRollbackConfiguration:h,alarmConfiguration:A,loadBalancerInfo:C,blueGreenDeploymentConfiguration:v}=i,T=c||r({slug:s,environment:o,resourceType:"deploy-group"}),R=t(T);return{deploymentGroup:{Type:"AWS::CodeDeploy::DeploymentGroup",Properties:{ApplicationName:M.Ref(n),DeploymentGroupName:T,ServiceRoleArn:u,AutoScalingGroups:d,Ec2TagFilters:g?.map((I)=>({Key:I.key,Value:I.value,Type:I.type})),DeploymentConfigName:y,AutoRollbackConfiguration:h?{Enabled:h.enabled,Events:h.events}:void 0,AlarmConfiguration:A?{Enabled:A.enabled,Alarms:A.alarms?.map((I)=>({Name:I.name})),IgnorePollAlarmFailure:A.ignorePollAlarmFailure}:void 0,LoadBalancerInfo:C?{TargetGroupInfoList:C.targetGroupInfoList?.map((I)=>({Name:I.name})),ElbInfoList:C.elbInfoList?.map((I)=>({Name:I.name}))}:void 0,BlueGreenDeploymentConfiguration:v?{TerminateBlueInstancesOnDeploymentSuccess:v.terminateBlueInstancesOnDeploymentSuccess?{Action:v.terminateBlueInstancesOnDeploymentSuccess.action,TerminationWaitTimeInMinutes:v.terminateBlueInstancesOnDeploymentSuccess.terminationWaitTimeInMinutes}:void 0,DeploymentReadyOption:v.deploymentReadyOption?{ActionOnTimeout:v.deploymentReadyOption.actionOnTimeout,WaitTimeInMinutes:v.deploymentReadyOption.waitTimeInMinutes}:void 0,GreenFleetProvisioningOption:v.greenFleetProvisioningOption?{Action:v.greenFleetProvisioningOption.action}:void 0}:void 0,Tags:[{Key:"Name",Value:T},{Key:"Environment",Value:o}]}},logicalId:R}}static createDeploymentConfig(n){let{slug:i,environment:s,deploymentConfigName:o,minimumHealthyHosts:c,trafficRoutingConfig:u}=n,d=o||r({slug:i,environment:s,resourceType:"deploy-config"}),g=t(d);return{deploymentConfig:{Type:"AWS::CodeDeploy::DeploymentConfig",Properties:{DeploymentConfigName:d,MinimumHealthyHosts:c?{Type:c.type,Value:c.value}:void 0,TrafficRoutingConfig:u?{Type:u.type,TimeBasedCanary:u.timeBasedCanary?{CanaryPercentage:u.timeBasedCanary.canaryPercentage,CanaryInterval:u.timeBasedCanary.canaryInterval}:void 0,TimeBasedLinear:u.timeBasedLinear?{LinearPercentage:u.timeBasedLinear.linearPercentage,LinearInterval:u.timeBasedLinear.linearInterval}:void 0}:void 0}},logicalId:g}}static DeploymentConfigs={allAtOnce:()=>({type:"FLEET_PERCENT",value:0}),halfAtATime:()=>({type:"FLEET_PERCENT",value:50}),oneAtATime:()=>({type:"HOST_COUNT",value:1}),custom:(n,i)=>({type:n,value:i})};static TrafficRouting={allAtOnce:()=>({type:"AllAtOnce"}),canary:(n,i)=>({type:"TimeBasedCanary",timeBasedCanary:{canaryPercentage:n,canaryInterval:i}}),linear:(n,i)=>({type:"TimeBasedLinear",timeBasedLinear:{linearPercentage:n,linearInterval:i}})};static RollbackConfigs={onFailure:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE"]}),onAlarmOrFailure:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE","DEPLOYMENT_STOP_ON_ALARM"]}),onAllEvents:()=>({enabled:!0,events:["DEPLOYMENT_FAILURE","DEPLOYMENT_STOP_ON_ALARM","DEPLOYMENT_STOP_ON_REQUEST"]}),disabled:()=>({enabled:!1})};static BlueGreenConfigs={standard:()=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withDelay:(n)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:n},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),withManualApproval:(n)=>({terminateBlueInstancesOnDeploymentSuccess:{action:"TERMINATE",terminationWaitTimeInMinutes:5},deploymentReadyOption:{actionOnTimeout:"STOP_DEPLOYMENT",waitTimeInMinutes:n},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}}),keepBlue:()=>({terminateBlueInstancesOnDeploymentSuccess:{action:"KEEP_ALIVE"},deploymentReadyOption:{actionOnTimeout:"CONTINUE_DEPLOYMENT",waitTimeInMinutes:0},greenFleetProvisioningOption:{action:"COPY_AUTO_SCALING_GROUP"}})};static UseCases={ec2Deployment:(n,i,s,o)=>{let{application:c,logicalId:u}=ee.createApplication({slug:n,environment:i,computePlatform:"Server"}),{deploymentGroup:d,logicalId:g}=ee.createDeploymentGroup(u,{slug:n,environment:i,serviceRoleArn:s,autoScalingGroups:o,deploymentConfigName:"CodeDeployDefault.OneAtATime",autoRollbackConfiguration:ee.RollbackConfigs.onFailure()});return{application:c,appId:u,deploymentGroup:d,groupId:g}},lambdaCanaryDeployment:(n,i,s,o=10,c=5)=>{let{application:u,logicalId:d}=ee.createApplication({slug:n,environment:i,computePlatform:"Lambda"}),{deploymentConfig:g,logicalId:y}=ee.createDeploymentConfig({slug:n,environment:i,trafficRoutingConfig:ee.TrafficRouting.canary(o,c)}),{deploymentGroup:h,logicalId:A}=ee.createDeploymentGroup(d,{slug:n,environment:i,serviceRoleArn:s,deploymentConfigName:M.Ref(y),autoRollbackConfiguration:ee.RollbackConfigs.onAlarmOrFailure()});return{application:u,appId:d,deploymentConfig:g,configId:y,deploymentGroup:h,groupId:A}},ecsBlueGreenDeployment:(n,i,s,o)=>{let{application:c,logicalId:u}=ee.createApplication({slug:n,environment:i,computePlatform:"ECS"}),{deploymentGroup:d,logicalId:g}=ee.createDeploymentGroup(u,{slug:n,environment:i,serviceRoleArn:s,loadBalancerInfo:{targetGroupInfoList:[{name:o}]},blueGreenDeploymentConfiguration:ee.BlueGreenConfigs.standard(),autoRollbackConfiguration:ee.RollbackConfigs.onFailure()});return{application:c,appId:u,deploymentGroup:d,groupId:g}}};static Strategies={rolling:(n=25)=>({type:"rolling",batchPercentage:n}),blueGreen:()=>({type:"blue-green"}),canary:(n=10,i=5)=>({type:"canary",canaryPercentage:n,canaryInterval:i}),allAtOnce:()=>({type:"all-at-once"})}}class L{static ContentTypes={".html":"text/html",".htm":"text/html",".css":"text/css",".js":"application/javascript",".mjs":"application/javascript",".json":"application/json",".xml":"application/xml",".svg":"image/svg+xml",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".avif":"image/avif",".ico":"image/x-icon",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".otf":"font/otf",".eot":"application/vnd.ms-fontobject",".pdf":"application/pdf",".txt":"text/plain",".md":"text/markdown",".map":"application/json"};static NoHashPatterns=[/^index\.html$/,/^favicon\.ico$/,/^robots\.txt$/,/^sitemap\.xml$/,/^manifest\.json$/,/^\.well-known\//,/^_redirects$/,/^_headers$/];static computeFileHash(n,i="md5"){let s=ct(n);return jr(i).update(s).digest("hex")}static computeShortHash(n){return L.computeFileHash(n).slice(0,8)}static getContentType(n){let i=Rn(n).toLowerCase();return L.ContentTypes[i]||"application/octet-stream"}static shouldHashFile(n,i){return![...L.NoHashPatterns,...i||[]].some((o)=>o.test(n))}static generateHashedFilename(n,i){let s=Rn(n),o=Qr(n,s),c=Tn(n);if(c===".")return`${o}.${i}${s}`;return ze(c,`${o}.${i}${s}`)}static collectFiles(n,i){let s=[],o=i||n;if(!Pt(n))return s;let c=qr(n,{withFileTypes:!0});for(let u of c){let d=ze(n,u.name);if(u.isDirectory())s.push(...L.collectFiles(d,o));else if(u.isFile())s.push(d)}return s}static hashDirectory(n){let{sourceDir:i,outputDir:s,excludePatterns:o=[],hashAlgorithm:c="md5",copyUnhashed:u=!0}=n,d=L.collectFiles(i),g=[],y={};for(let A of d){let C=A.replace(i,"").replace(/^[/\\]/,""),v=L.shouldHashFile(C,o),T=zr(A),R=v?L.computeFileHash(A,c).slice(0,8):"",P=v?L.generateHashedFilename(C,R):C,I={originalPath:C,hashedPath:P,hash:R,size:T.size,contentType:L.getContentType(A)};if(g.push(I),y[C]=P,s){let O=ze(s,P),B=Tn(O);if(!Pt(B)){let{mkdirSync:x}=ls("node:fs");x(B,{recursive:!0})}if(v||u)Kr(A,O)}}let h={version:"1.0",timestamp:new Date().toISOString(),assets:g,hashMap:y};if(s){let A=ze(s,"asset-manifest.json");lt(A,JSON.stringify(h,null,2))}return h}static getInvalidationPaths(n,i){let s=[];if(!n)return["/*"];let o=n.hashMap,c=i.hashMap;for(let[u,d]of Object.entries(c)){let g=o[u];if(!g||g!==d){if(s.push(`/${u}`),g&&g!==d)s.push(`/${g}`)}}for(let[u,d]of Object.entries(o))if(!c[u])s.push(`/${u}`),s.push(`/${d}`);if(s.length>100)return["/*"];return[...new Set(s)]}static updateHtmlReferences(n){let{htmlDir:i,manifest:s,basePath:o=""}=n,c=L.collectFiles(i).filter((u)=>u.endsWith(".html")||u.endsWith(".htm"));for(let u of c){let d=ct(u,"utf-8");for(let[g,y]of Object.entries(s.hashMap)){if(g===y)continue;let h=[new RegExp(`(src|href)=["']${o}/?${L.escapeRegExp(g)}["']`,"g"),new RegExp(`url\\(["']?${o}/?${L.escapeRegExp(g)}["']?\\)`,"g")];for(let A of h)d=d.replace(A,(C)=>C.replace(g,y))}lt(u,d)}}static updateCssReferences(n){let{cssDir:i,manifest:s,basePath:o=""}=n,c=L.collectFiles(i).filter((u)=>u.endsWith(".css"));for(let u of c){let d=ct(u,"utf-8");for(let[g,y]of Object.entries(s.hashMap)){if(g===y)continue;let h=new RegExp(`url\\(["']?${o}/?${L.escapeRegExp(g)}["']?\\)`,"g");d=d.replace(h,`url(${o}/${y})`)}lt(u,d)}}static escapeRegExp(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}static generateS3DeploymentManifest(n){let{sourceDir:i,keyPrefix:s="",excludePatterns:o=[],cacheControl:c={hashed:"public, max-age=31536000, immutable",unhashed:"public, max-age=3600",html:"public, max-age=0, must-revalidate"}}=n;return L.hashDirectory({sourceDir:i,excludePatterns:o}).assets.map((d)=>{let g=d.hash!=="",y=d.contentType==="text/html",h=c.unhashed||"public, max-age=3600";if(y)h=c.html||"public, max-age=0, must-revalidate";else if(g)h=c.hashed||"public, max-age=31536000, immutable";return{localPath:ze(i,d.originalPath),s3Key:s?`${s}/${d.hashedPath}`:d.hashedPath,contentType:d.contentType,cacheControl:h,hash:d.hash}})}static compareManifests(n,i){let s={added:[],removed:[],changed:[],unchanged:[]},o=new Set(Object.keys(n.hashMap)),c=new Set(Object.keys(i.hashMap));for(let u of c)if(!o.has(u))s.added.push(u);for(let u of o)if(!c.has(u))s.removed.push(u);for(let u of c)if(o.has(u))if(n.hashMap[u]!==i.hashMap[u])s.changed.push(u);else s.unchanged.push(u);return s}static loadManifest(n){if(!Pt(n))return null;try{let i=ct(n,"utf-8");return JSON.parse(i)}catch{return null}}static saveManifest(n,i){lt(i,JSON.stringify(n,null,2))}}class es{static createSecret(n){let{slug:i,environment:s,secretName:o,description:c,secretString:u,kmsKeyId:d,tags:g}=n,y=o||r({slug:i,environment:s,resourceType:"secret"}),h=t(y),A={Type:"AWS::SecretsManager::Secret",Properties:{Name:y,Description:c,SecretString:u,Tags:[{Key:"Name",Value:y},{Key:"Environment",Value:s},...g?Object.entries(g).map(([C,v])=>({Key:C,Value:v})):[]]}};if(d)A.Properties.KmsKeyId=d;return{secret:A,logicalId:h}}static createGeneratedSecret(n){let{slug:i,environment:s,secretName:o,description:c,excludeCharacters:u,excludeLowercase:d,excludeNumbers:g,excludePunctuation:y,excludeUppercase:h,passwordLength:A,requireEachIncludedType:C,kmsKeyId:v,tags:T}=n,R=o||r({slug:i,environment:s,resourceType:"secret"}),P=t(R),I={Type:"AWS::SecretsManager::Secret",Properties:{Name:R,Description:c,GenerateSecretString:{ExcludeCharacters:u,ExcludeLowercase:d,ExcludeNumbers:g,ExcludePunctuation:y,ExcludeUppercase:h,PasswordLength:A||32,RequireEachIncludedType:C!==!1},Tags:[{Key:"Name",Value:R},{Key:"Environment",Value:s},...T?Object.entries(T).map(([O,B])=>({Key:O,Value:B})):[]]}};if(v)I.Properties.KmsKeyId=v;return{secret:I,logicalId:P}}static createDatabaseSecret(n){let{slug:i,environment:s,secretName:o,username:c,dbname:u,engine:d,host:g,port:y,kmsKeyId:h}=n,A=o||r({slug:i,environment:s,resourceType:"db-secret"}),C=t(A),v={username:c};if(u)v.dbname=u;if(d)v.engine=d;if(g)v.host=g;if(y)v.port=y;let T={Type:"AWS::SecretsManager::Secret",Properties:{Name:A,Description:`Database credentials for ${c}`,GenerateSecretString:{SecretStringTemplate:JSON.stringify(v),GenerateStringKey:"password",PasswordLength:32,ExcludeCharacters:'"@/\\',RequireEachIncludedType:!0},Tags:[{Key:"Name",Value:A},{Key:"Environment",Value:s},{Key:"Type",Value:"database"}]}};if(h)T.Properties.KmsKeyId=h;return{secret:T,logicalId:C}}static attachToDatabase(n){let{slug:i,environment:s,secretId:o,targetId:c,targetType:u}=n,d=r({slug:i,environment:s,resourceType:"secret-attachment"}),g=t(d);return{attachment:{Type:"AWS::SecretsManager::SecretTargetAttachment",Properties:{SecretId:o,TargetId:c,TargetType:u}},logicalId:g}}static enableRotation(n){let{slug:i,environment:s,secretId:o,rotationLambdaArn:c,automaticallyAfterDays:u,rotationType:d,kmsKeyArn:g,vpcSecurityGroupIds:y,vpcSubnetIds:h}=n,A=r({slug:i,environment:s,resourceType:"secret-rotation"}),C=t(A),v={Type:"AWS::SecretsManager::RotationSchedule",Properties:{SecretId:o,RotationRules:{AutomaticallyAfterDays:u||30}}};if(c)v.Properties.RotationLambdaARN=c;else if(d)v.Properties.HostedRotationLambda={RotationType:d,KmsKeyArn:g,VpcSecurityGroupIds:y,VpcSubnetIds:h};return{rotation:v,logicalId:C}}static SecretTypes={apiKey:(n,i,s)=>es.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-${s}-api-key`,description:`API key for ${s}`,passwordLength:32,excludePunctuation:!0,excludeLowercase:!1,excludeUppercase:!1,excludeNumbers:!1}),oauthClientSecret:(n,i,s)=>es.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-${s}-oauth-secret`,description:`OAuth client secret for ${s}`,passwordLength:64,excludeCharacters:"\"'`\\/@",requireEachIncludedType:!0}),jwtSecret:(n,i)=>es.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-jwt-secret`,description:"JWT signing secret",passwordLength:64,excludePunctuation:!0}),encryptionKey:(n,i)=>es.createGeneratedSecret({slug:n,environment:i,secretName:`${n}-${i}-encryption-key`,description:"Data encryption key",passwordLength:64,excludeCharacters:"+/=",excludePunctuation:!0})};static RotationTypes={MySQLSingleUser:"MySQLSingleUser",MySQLMultiUser:"MySQLMultiUser",PostgreSQLSingleUser:"PostgreSQLSingleUser",PostgreSQLMultiUser:"PostgreSQLMultiUser",OracleSingleUser:"OracleSingleUser",OracleMultiUser:"OracleMultiUser",MariaDBSingleUser:"MariaDBSingleUser",MariaDBMultiUser:"MariaDBMultiUser",SQLServerSingleUser:"SQLServerSingleUser",SQLServerMultiUser:"SQLServerMultiUser",RedshiftSingleUser:"RedshiftSingleUser",RedshiftMultiUser:"RedshiftMultiUser",MongoDBSingleUser:"MongoDBSingleUser",MongoDBMultiUser:"MongoDBMultiUser"}}class D{static createParameter(n){let{slug:i,environment:s,parameterName:o,value:c,type:u="String",description:d,tier:g="Standard",tags:y}=n,h=o||r({slug:i,environment:s,resourceType:"parameter"}),A=t(h);return{parameter:{Type:"AWS::SSM::Parameter",Properties:{Name:`/${i}/${s}/${h}`,Type:u,Value:c,Description:d,Tier:g,Tags:{Name:h,Environment:s,...y}}},logicalId:A}}static createString(n,i,s,o,c){return D.createParameter({slug:n,environment:i,parameterName:s,value:o,type:"String",description:c})}static createSecureString(n,i,s,o,c){return D.createParameter({slug:n,environment:i,parameterName:s,value:o,type:"SecureString",description:c})}static createStringList(n,i,s,o,c){return D.createParameter({slug:n,environment:i,parameterName:s,value:o.join(","),type:"StringList",description:c})}static Parameters={databaseUrl:(n,i,s)=>D.createSecureString(n,i,"database-url",s,"Database connection URL"),apiEndpoint:(n,i,s)=>D.createString(n,i,"api-endpoint",s,"API endpoint URL"),appVersion:(n,i,s)=>D.createString(n,i,"app-version",s,"Application version"),featureFlags:(n,i,s)=>D.createStringList(n,i,"feature-flags",s,"Enabled feature flags"),apiKey:(n,i,s,o)=>D.createSecureString(n,i,`${s}-api-key`,o,`API key for ${s}`),oauthCredentials:(n,i,s,o)=>{let c=D.createString(n,i,"oauth-client-id",s,"OAuth client ID"),u=D.createSecureString(n,i,"oauth-client-secret",o,"OAuth client secret");return{clientId:c,clientSecret:u}},smtpCredentials:(n,i,s,o,c,u)=>{let d=D.createString(n,i,"smtp-username",s,"SMTP username"),g=D.createSecureString(n,i,"smtp-password",o,"SMTP password"),y=D.createString(n,i,"smtp-host",c,"SMTP host"),h=D.createString(n,i,"smtp-port",u.toString(),"SMTP port");return{username:d,password:g,host:y,port:h}},redisUrl:(n,i,s)=>D.createSecureString(n,i,"redis-url",s,"Redis connection URL"),s3Bucket:(n,i,s)=>D.createString(n,i,"s3-bucket",s,"S3 bucket name"),cloudFrontDistribution:(n,i,s)=>D.createString(n,i,"cloudfront-distribution-id",s,"CloudFront distribution ID")}}class pr{static createDomain(n){let{slug:i,environment:s,domainName:o,engineVersion:c="OpenSearch_2.11",instanceType:u="t3.small.search",instanceCount:d=1,volumeSize:g=10,volumeType:y="gp3",dedicatedMaster:h=!1,dedicatedMasterType:A,dedicatedMasterCount:C=3,multiAz:v=!1,availabilityZoneCount:T=2,vpc:R,encryption:P,enforceHttps:I=!0,tlsSecurityPolicy:O="Policy-Min-TLS-1-2-2019-07",advancedSecurity:B,autoSnapshotHour:x=0,autoTune:F=!0,tags:G={}}=n,_=o||r({slug:i,environment:s,resourceType:"search"}),U=t(_);return{domain:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:_,EngineVersion:c,ClusterConfig:{InstanceType:u,InstanceCount:d,DedicatedMasterEnabled:h,...h&&{DedicatedMasterType:A||u,DedicatedMasterCount:C},ZoneAwarenessEnabled:v,...v&&{ZoneAwarenessConfig:{AvailabilityZoneCount:T}}},EBSOptions:{EBSEnabled:!0,VolumeType:y,VolumeSize:g},DomainEndpointOptions:{EnforceHTTPS:I,TLSSecurityPolicy:O},SnapshotOptions:{AutomatedSnapshotStartHour:x},...R&&{VPCOptions:{SubnetIds:R.subnetIds,SecurityGroupIds:R.securityGroupIds}},...P&&{EncryptionAtRestOptions:{Enabled:P.atRest??!0,...P.kmsKeyId&&{KmsKeyId:P.kmsKeyId}},NodeToNodeEncryptionOptions:{Enabled:P.nodeToNode??!0}},...B&&{AdvancedSecurityOptions:{Enabled:B.enabled,InternalUserDatabaseEnabled:B.internalUserDatabase??!0,...B.masterUserName&&B.masterUserPassword&&{MasterUserOptions:{MasterUserName:B.masterUserName,MasterUserPassword:B.masterUserPassword}},...B.masterUserArn&&{MasterUserOptions:{MasterUserARN:B.masterUserArn}}}},...F&&{AutoTuneOptions:{DesiredState:"ENABLED"}},Tags:[{Key:"Name",Value:_},{Key:"Environment",Value:s},...Object.entries(G).map(([K,Q])=>({Key:K,Value:Q}))]}},logicalId:U}}static createAccessPolicy(n,i){let{ipAddresses:s,iamPrincipalArns:o,allowAll:c,vpcEndpoint:u}=i;if(c)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:n}]};let d=[];if(o&&o.length>0)d.push({Effect:"Allow",Principal:{AWS:o},Action:"es:*",Resource:n});if(s&&s.length>0)d.push({Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:n,Condition:{IpAddress:{"aws:SourceIp":s}}});if(u)return{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:n}]};return{Version:"2012-10-17",Statement:d}}static DomainPresets={development:(n,i)=>pr.createDomain({slug:n,environment:i,instanceType:"t3.small.search",instanceCount:1,volumeSize:10,multiAz:!1,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!1}),production:(n,i,s)=>pr.createDomain({slug:n,environment:i,instanceType:"m6g.large.search",instanceCount:3,volumeSize:100,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"m6g.large.search",dedicatedMasterCount:3,vpc:s,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!0},autoTune:!0}),costOptimized:(n,i)=>pr.createDomain({slug:n,environment:i,instanceType:"t3.medium.search",instanceCount:2,volumeSize:20,volumeType:"gp3",multiAz:!0,dedicatedMaster:!1,encryption:{atRest:!0,nodeToNode:!0},autoTune:!0}),highPerformance:(n,i,s)=>pr.createDomain({slug:n,environment:i,instanceType:"r6g.2xlarge.search",instanceCount:6,volumeSize:500,volumeType:"gp3",multiAz:!0,availabilityZoneCount:3,dedicatedMaster:!0,dedicatedMasterType:"c6g.xlarge.search",dedicatedMasterCount:3,vpc:s,encryption:{atRest:!0,nodeToNode:!0},advancedSecurity:{enabled:!0,internalUserDatabase:!1},autoTune:!0})};static InstanceTypes={"t3.small.search":"t3.small.search","t3.medium.search":"t3.medium.search","m6g.large.search":"m6g.large.search","m6g.xlarge.search":"m6g.xlarge.search","m6g.2xlarge.search":"m6g.2xlarge.search","r6g.large.search":"r6g.large.search","r6g.xlarge.search":"r6g.xlarge.search","r6g.2xlarge.search":"r6g.2xlarge.search","r6g.4xlarge.search":"r6g.4xlarge.search","c6g.large.search":"c6g.large.search","c6g.xlarge.search":"c6g.xlarge.search","c6g.2xlarge.search":"c6g.2xlarge.search"};static EngineVersions={"OpenSearch_2.11":"OpenSearch_2.11","OpenSearch_2.9":"OpenSearch_2.9","OpenSearch_2.7":"OpenSearch_2.7","OpenSearch_1.3":"OpenSearch_1.3","Elasticsearch_7.10":"Elasticsearch_7.10"}}class Ot{static createDomainRedirectBucket(n){let{slug:i,environment:s,sourceDomain:o,targetDomain:c,protocol:u="https"}=n,d=r({slug:i,environment:s,resourceType:"s3",suffix:"redirect"}),g=t(d),y=t(`${d}-policy`),h={Type:"AWS::S3::Bucket",Properties:{BucketName:o,WebsiteConfiguration:{RedirectAllRequestsTo:{HostName:c,Protocol:u}},PublicAccessBlockConfiguration:{BlockPublicAcls:!1,BlockPublicPolicy:!1,IgnorePublicAcls:!1,RestrictPublicBuckets:!1},Tags:[{Key:"Name",Value:d},{Key:"Environment",Value:s},{Key:"Purpose",Value:"Domain Redirect"}]}},A={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:M.Ref(g),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadForRedirect",Effect:"Allow",Principal:"*",Action:["s3:GetObject"],Resource:[M.Join("",[M.GetAtt(g,"Arn"),"/*"])]}]}}};return{bucket:h,bucketPolicy:A,logicalId:g,policyLogicalId:y}}static createPathRedirectFunction(n){let{slug:i,environment:s,rules:o}=n,c=r({slug:i,environment:s,resourceType:"cf-redirect"}),u=t(c),d=Ot.generateRedirectFunctionCode(o);return{function:{Type:"AWS::CloudFront::Function",Properties:{Name:c,AutoPublish:!0,FunctionConfig:{Comment:`Path redirect function for ${i} (${s})`,Runtime:"cloudfront-js-2.0"},FunctionCode:d}},logicalId:u,functionCode:d}}static generateRedirectFunctionCode(n){return`function handler(event) {
2282
2282
  const request = event.request;
2283
2283
  const uri = request.uri;
2284
2284
  const querystring = request.querystring;
@@ -2332,7 +2332,7 @@ ${n.map((s)=>{let o=s.preserveQueryString!==!1,c=s.statusCode||301;return` '${s
2332
2332
  }
2333
2333
 
2334
2334
  return request;
2335
- }`}static CommonRedirects={wwwToApex:(n,i="https")=>({slug:n.replace(/\./g,"-"),environment:"production",sourceDomain:`www.${n}`,targetDomain:n,protocol:i,preservePath:!0}),apexToWww:(n,i="https")=>({slug:n.replace(/\./g,"-"),environment:"production",sourceDomain:n,targetDomain:`www.${n}`,protocol:i,preservePath:!0}),httpToHttps:(n="/")=>({source:n,target:n,statusCode:301}),addTrailingSlash:(n)=>n.map((i)=>({source:i.endsWith("/")?i.slice(0,-1):i,target:i.endsWith("/")?i:`${i}/`,statusCode:301})),removeTrailingSlash:(n)=>n.map((i)=>({source:i.endsWith("/")&&i!=="/"?i:`${i}/`,target:i.endsWith("/")&&i!=="/"?i.slice(0,-1):i,statusCode:301}))};static Patterns={flattenBlogUrls:(n)=>n.map(({oldPath:i,newPath:s})=>({source:i,target:s,statusCode:301,preserveQueryString:!0})),categoryRename:(n,i)=>[{source:`/${n}`,target:`/${i}`,statusCode:301},{source:`/${n}/`,target:`/${i}/`,statusCode:301}],productSlugChange:(n)=>n.map(({oldSlug:i,newSlug:s})=>({source:`/products/${i}`,target:`/products/${s}`,statusCode:301})),apiVersionRedirect:(n,i,s)=>s.map((o)=>({source:`/api/${n}/${o}`,target:`/api/${i}/${o}`,statusCode:307,preserveQueryString:!0})),gonePages:(n)=>n.map((i)=>({source:i,target:"/410",statusCode:301}))};static createRedirectSetup(n){let{slug:i,environment:s,domainRedirects:o=[],pathRedirects:c=[]}=n,u={},d=[];for(let y of o){let{bucket:h,bucketPolicy:A,logicalId:C,policyLogicalId:v}=xt.createDomainRedirectBucket({...y,slug:i,environment:s});u[C]=h,u[v]=A,d.push(C)}let g=null;if(c.length>0){let{function:y,logicalId:h}=xt.createPathRedirectFunction({slug:i,environment:s,rules:c});u[h]=y,g=h}return{resources:u,outputs:{domainRedirectBuckets:d,pathRedirectFunctionLogicalId:g}}}static fromMapping(n,i){return Object.entries(n).map(([s,o])=>({source:s,target:o,statusCode:i?.statusCode||301,preserveQueryString:i?.preserveQueryString??!0}))}static validateRules(n){let i=[],s=[],o=new Set;for(let c of n){if(o.has(c.source))i.push(`Duplicate source path: ${c.source}`);if(o.add(c.source),c.source===c.target)i.push(`Redirect loop detected: ${c.source} -> ${c.target}`);if(!c.target.startsWith("/")&&!c.target.startsWith("http"))s.push(`Target URL should start with / or http: ${c.target}`);if(!c.source||c.source.trim()==="")i.push("Source path cannot be empty");if(!c.target||c.target.trim()==="")i.push("Target path cannot be empty")}for(let c of n){let u=n.find((d)=>d.source===c.target);if(u)s.push(`Potential redirect chain: ${c.source} -> ${c.target} -> ${u.target}`)}return{valid:i.length===0,errors:i,warnings:s}}}class ee{static generate(n){let i={},{slug:s,environment:o,region:c="us-east-1"}=n,u=ee.createLambdaExecutionRole(s,o);if(Object.assign(i,u.resources),n.email?.enabled){let d=ee.generateEmailResources(n,u.roleArn);Object.assign(i,d)}if(n.phone?.enabled){let d=ee.generatePhoneResources(n,u.roleArn);Object.assign(i,d)}if(n.sms?.enabled){let d=ee.generateSmsResources(n,u.roleArn);Object.assign(i,d)}return i}static createLambdaExecutionRole(n,i){let s=`${n}-${i}-communication-role`,o=t(s);return{resources:{[o]:{Type:"AWS::IAM::Role",Properties:{RoleName:s,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:"CommunicationPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:"*"},{Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail","ses:GetIdentityVerificationAttributes"],Resource:"*"},{Effect:"Allow",Action:["sns:Publish","sns:Subscribe"],Resource:"*"},{Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:BatchWriteItem","dynamodb:BatchGetItem"],Resource:"*"},{Effect:"Allow",Action:["connect:*"],Resource:"*"},{Effect:"Allow",Action:["mobiletargeting:SendMessages","mobiletargeting:GetEndpoint","mobiletargeting:UpdateEndpoint"],Resource:"*"},{Effect:"Allow",Action:["transcribe:StartTranscriptionJob","transcribe:GetTranscriptionJob"],Resource:"*"},{Effect:"Allow",Action:["bedrock:InvokeModel"],Resource:"*"},{Effect:"Allow",Action:["es:ESHttpGet","es:ESHttpPost","es:ESHttpPut","es:ESHttpDelete"],Resource:"*"}]}}]}}},roleArn:x.GetAtt(o,"Arn"),roleName:s}}static generateEmailResources(n,i){let{slug:s,environment:o,email:c}=n;if(!c)return{};let u={},d=`${s}-${o}`,g=`${d}-email-storage`,y=t(g);u[y]={Type:"AWS::S3::Bucket",Properties:{BucketName:g,LifecycleConfiguration:{Rules:[{Id:"ArchiveOldEmails",Status:"Enabled",Transitions:c.server?.storage?.archiveAfterDays?[{StorageClass:"GLACIER",TransitionInDays:c.server.storage.archiveAfterDays}]:[],ExpirationInDays:c.server?.storage?.retentionDays||365}]},NotificationConfiguration:{LambdaConfigurations:[]}}};let h=t(`${d}-ses-identity`);if(u[h]={Type:"AWS::SES::EmailIdentity",Properties:{EmailIdentity:c.domain,DkimSigningAttributes:{NextSigningKeyLength:"RSA_2048_BIT"},FeedbackAttributes:{EmailForwardingEnabled:!0}}},c.notifications?.bounces||c.notifications?.complaints){let A=t(`${d}-bounce-topic`);u[A]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${d}-email-bounces`}};let C=t(`${d}-complaint-topic`);u[C]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${d}-email-complaints`}}}if(c.server?.enabled){let A=t(`${d}-inbound-email`);u[A]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${d}-inbound-email`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:60,MemorySize:256,Code:{ZipFile:ee.InboundEmailCode},Environment:{Variables:{EMAIL_BUCKET:g,DOMAIN:c.domain}}}};let C=t(`${d}-outbound-email`);u[C]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${d}-outbound-email`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:30,MemorySize:256,Code:{ZipFile:ee.OutboundEmailCode},Environment:{Variables:{EMAIL_BUCKET:g,DOMAIN:c.domain}}}}}if(c.advanced?.analytics){let A=t(`${d}-email-analytics`);u[A]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-email-analytics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.scheduling){let A=t(`${d}-email-scheduler`);u[A]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${d}-email-scheduler`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:300,MemorySize:256,Code:{ZipFile:ee.EmailSchedulerCode},Environment:{Variables:{EMAIL_BUCKET:g}}}};let C=t(`${d}-email-scheduler-rule`);u[C]={Type:"AWS::Events::Rule",Properties:{Name:`${d}-email-scheduler`,ScheduleExpression:"rate(1 minute)",State:"ENABLED",Targets:[{Id:"EmailSchedulerTarget",Arn:x.GetAtt(A,"Arn")}]}}}if(c.advanced?.threading){let A=t(`${d}-email-threading`);u[A]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${d}-email-threading`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:60,MemorySize:256,Code:{ZipFile:ee.EmailThreadingCode},Environment:{Variables:{EMAIL_BUCKET:g}}}}}if(c.advanced?.rules){let A=t(`${d}-email-rules`);u[A]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-email-rules`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"mailbox",AttributeType:"S"},{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"mailbox",KeyType:"HASH"},{AttributeName:"id",KeyType:"RANGE"}]}}}if(c.advanced?.sharedMailboxes){let A=t(`${d}-shared-mailboxes`);u[A]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-shared-mailboxes`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"},{AttributeName:"type",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],GlobalSecondaryIndexes:[{IndexName:"type-index",KeySchema:[{AttributeName:"type",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"}}]}}}if(c.advanced?.search){let A=t(`${d}-email-search`);u[A]={Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:`${d}-email-search`.toLowerCase().replace(/[^a-z0-9-]/g,"-").substring(0,28),EngineVersion:"OpenSearch_2.11",ClusterConfig:{InstanceType:"t3.small.search",InstanceCount:1},EBSOptions:{EBSEnabled:!0,VolumeType:"gp3",VolumeSize:10},NodeToNodeEncryptionOptions:{Enabled:!0},EncryptionAtRestOptions:{Enabled:!0},DomainEndpointOptions:{EnforceHTTPS:!0}}}}return u}static generatePhoneResources(n,i){let{slug:s,environment:o,phone:c}=n;if(!c)return{};let u={},d=`${s}-${o}`,g=t(`${d}-call-log`);if(u[g]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-call-log`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"contactId",AttributeType:"S"}],KeySchema:[{AttributeName:"contactId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}},c.voicemail?.enabled){let A=t(`${d}-voicemail`);u[A]={Type:"AWS::S3::Bucket",Properties:{BucketName:`${d}-voicemail`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldVoicemails",Status:"Enabled",ExpirationInDays:90}]}}}}let y=t(`${d}-phone-notifications`);u[y]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${d}-phone-notifications`}};let h=t(`${d}-incoming-call`);if(u[h]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${d}-incoming-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:30,MemorySize:256,Code:{ZipFile:ee.IncomingCallCode},Environment:{Variables:{CALL_LOG_TABLE:`${d}-call-log`,NOTIFICATION_TOPIC_ARN:x.Ref(y)}}}},c.voicemail?.enabled){let A=t(`${d}-voicemail-handler`);u[A]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${d}-voicemail-handler`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:c.voicemail.transcription?300:60,MemorySize:256,Code:{ZipFile:ee.VoicemailCode},Environment:{Variables:{VOICEMAIL_BUCKET:`${d}-voicemail`,TRANSCRIPTION_ENABLED:String(c.voicemail.transcription||!1),NOTIFICATION_TOPIC_ARN:x.Ref(y)}}}}}if(c.advanced?.recording){let A=t(`${d}-call-recordings`);u[A]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-call-recordings`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"recordingId",AttributeType:"S"}],KeySchema:[{AttributeName:"recordingId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.callbacks){let A=t(`${d}-callbacks`);u[A]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-callbacks`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.analytics){let A=t(`${d}-call-metrics`);u[A]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-call-metrics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"period",AttributeType:"S"}],KeySchema:[{AttributeName:"period",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}return u}static generateSmsResources(n,i){let{slug:s,environment:o,sms:c}=n;if(!c)return{};let u={},d=`${s}-${o}`,g=t(`${d}-pinpoint-app`);u[g]={Type:"AWS::Pinpoint::App",Properties:{Name:`${d}-sms`}};let y=t(`${d}-sms-channel`);u[y]={Type:"AWS::Pinpoint::SMSChannel",Properties:{ApplicationId:x.Ref(g),Enabled:!0,SenderId:c.senderId}};let h=t(`${d}-sms-log`);if(u[h]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-sms-log`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}},c.optOut?.enabled){let T=t(`${d}-sms-optout`);u[T]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-sms-optout`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}]}}}let A=t(`${d}-sms-notifications`);u[A]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${d}-sms-notifications`}};let C=t(`${d}-send-sms`);u[C]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${d}-send-sms`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:30,MemorySize:256,Code:{ZipFile:ee.SendSmsCode},Environment:{Variables:{PINPOINT_APP_ID:x.Ref(g),MESSAGE_LOG_TABLE:`${d}-sms-log`,OPT_OUT_TABLE:c.optOut?.enabled?`${d}-sms-optout`:"",MESSAGE_TYPE:c.messageType||"TRANSACTIONAL"}}}};let v=t(`${d}-receive-sms`);if(u[v]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${d}-receive-sms`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:30,MemorySize:256,Code:{ZipFile:ee.ReceiveSmsCode},Environment:{Variables:{MESSAGE_LOG_TABLE:`${d}-sms-log`,OPT_OUT_TABLE:c.optOut?.enabled?`${d}-sms-optout`:"",NOTIFICATION_TOPIC_ARN:x.Ref(A)}}}},c.advanced?.campaigns){let T=t(`${d}-sms-campaigns`);u[T]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-sms-campaigns`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}if(c.advanced?.analytics){let T=t(`${d}-sms-analytics`);u[T]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-sms-analytics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"period",AttributeType:"S"}],KeySchema:[{AttributeName:"period",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.linkTracking){let T=t(`${d}-short-links`);u[T]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-short-links`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.chatbot){let T=t(`${d}-chatbot-sessions`);u[T]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-chatbot-sessions`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}};let R=t(`${d}-chatbot-rules`);u[R]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-chatbot-rules`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}if(c.advanced?.abTesting){let T=t(`${d}-ab-tests`);u[T]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-ab-tests`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}if(c.advanced?.mms){let T=t(`${d}-mms-media`);u[T]={Type:"AWS::S3::Bucket",Properties:{BucketName:`${d}-mms-media`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldMedia",Status:"Enabled",ExpirationInDays:30}]}}}}return u}static InboundEmailCode=`
2335
+ }`}static CommonRedirects={wwwToApex:(n,i="https")=>({slug:n.replace(/\./g,"-"),environment:"production",sourceDomain:`www.${n}`,targetDomain:n,protocol:i,preservePath:!0}),apexToWww:(n,i="https")=>({slug:n.replace(/\./g,"-"),environment:"production",sourceDomain:n,targetDomain:`www.${n}`,protocol:i,preservePath:!0}),httpToHttps:(n="/")=>({source:n,target:n,statusCode:301}),addTrailingSlash:(n)=>n.map((i)=>({source:i.endsWith("/")?i.slice(0,-1):i,target:i.endsWith("/")?i:`${i}/`,statusCode:301})),removeTrailingSlash:(n)=>n.map((i)=>({source:i.endsWith("/")&&i!=="/"?i:`${i}/`,target:i.endsWith("/")&&i!=="/"?i.slice(0,-1):i,statusCode:301}))};static Patterns={flattenBlogUrls:(n)=>n.map(({oldPath:i,newPath:s})=>({source:i,target:s,statusCode:301,preserveQueryString:!0})),categoryRename:(n,i)=>[{source:`/${n}`,target:`/${i}`,statusCode:301},{source:`/${n}/`,target:`/${i}/`,statusCode:301}],productSlugChange:(n)=>n.map(({oldSlug:i,newSlug:s})=>({source:`/products/${i}`,target:`/products/${s}`,statusCode:301})),apiVersionRedirect:(n,i,s)=>s.map((o)=>({source:`/api/${n}/${o}`,target:`/api/${i}/${o}`,statusCode:307,preserveQueryString:!0})),gonePages:(n)=>n.map((i)=>({source:i,target:"/410",statusCode:301}))};static createRedirectSetup(n){let{slug:i,environment:s,domainRedirects:o=[],pathRedirects:c=[]}=n,u={},d=[];for(let y of o){let{bucket:h,bucketPolicy:A,logicalId:C,policyLogicalId:v}=Ot.createDomainRedirectBucket({...y,slug:i,environment:s});u[C]=h,u[v]=A,d.push(C)}let g=null;if(c.length>0){let{function:y,logicalId:h}=Ot.createPathRedirectFunction({slug:i,environment:s,rules:c});u[h]=y,g=h}return{resources:u,outputs:{domainRedirectBuckets:d,pathRedirectFunctionLogicalId:g}}}static fromMapping(n,i){return Object.entries(n).map(([s,o])=>({source:s,target:o,statusCode:i?.statusCode||301,preserveQueryString:i?.preserveQueryString??!0}))}static validateRules(n){let i=[],s=[],o=new Set;for(let c of n){if(o.has(c.source))i.push(`Duplicate source path: ${c.source}`);if(o.add(c.source),c.source===c.target)i.push(`Redirect loop detected: ${c.source} -> ${c.target}`);if(!c.target.startsWith("/")&&!c.target.startsWith("http"))s.push(`Target URL should start with / or http: ${c.target}`);if(!c.source||c.source.trim()==="")i.push("Source path cannot be empty");if(!c.target||c.target.trim()==="")i.push("Target path cannot be empty")}for(let c of n){let u=n.find((d)=>d.source===c.target);if(u)s.push(`Potential redirect chain: ${c.source} -> ${c.target} -> ${u.target}`)}return{valid:i.length===0,errors:i,warnings:s}}}class te{static generate(n){let i={},{slug:s,environment:o,region:c="us-east-1"}=n,u=te.createLambdaExecutionRole(s,o);if(Object.assign(i,u.resources),n.email?.enabled){let d=te.generateEmailResources(n,u.roleArn);Object.assign(i,d)}if(n.phone?.enabled){let d=te.generatePhoneResources(n,u.roleArn);Object.assign(i,d)}if(n.sms?.enabled){let d=te.generateSmsResources(n,u.roleArn);Object.assign(i,d)}return i}static createLambdaExecutionRole(n,i){let s=`${n}-${i}-communication-role`,o=t(s);return{resources:{[o]:{Type:"AWS::IAM::Role",Properties:{RoleName:s,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:"CommunicationPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:"*"},{Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail","ses:GetIdentityVerificationAttributes"],Resource:"*"},{Effect:"Allow",Action:["sns:Publish","sns:Subscribe"],Resource:"*"},{Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:BatchWriteItem","dynamodb:BatchGetItem"],Resource:"*"},{Effect:"Allow",Action:["connect:*"],Resource:"*"},{Effect:"Allow",Action:["mobiletargeting:SendMessages","mobiletargeting:GetEndpoint","mobiletargeting:UpdateEndpoint"],Resource:"*"},{Effect:"Allow",Action:["transcribe:StartTranscriptionJob","transcribe:GetTranscriptionJob"],Resource:"*"},{Effect:"Allow",Action:["bedrock:InvokeModel"],Resource:"*"},{Effect:"Allow",Action:["es:ESHttpGet","es:ESHttpPost","es:ESHttpPut","es:ESHttpDelete"],Resource:"*"}]}}]}}},roleArn:M.GetAtt(o,"Arn"),roleName:s}}static generateEmailResources(n,i){let{slug:s,environment:o,email:c}=n;if(!c)return{};let u={},d=`${s}-${o}`,g=`${d}-email-storage`,y=t(g);u[y]={Type:"AWS::S3::Bucket",Properties:{BucketName:g,LifecycleConfiguration:{Rules:[{Id:"ArchiveOldEmails",Status:"Enabled",Transitions:c.server?.storage?.archiveAfterDays?[{StorageClass:"GLACIER",TransitionInDays:c.server.storage.archiveAfterDays}]:[],ExpirationInDays:c.server?.storage?.retentionDays||365}]},NotificationConfiguration:{LambdaConfigurations:[]}}};let h=t(`${d}-ses-identity`);if(u[h]={Type:"AWS::SES::EmailIdentity",Properties:{EmailIdentity:c.domain,DkimSigningAttributes:{NextSigningKeyLength:"RSA_2048_BIT"},FeedbackAttributes:{EmailForwardingEnabled:!0}}},c.notifications?.bounces||c.notifications?.complaints){let A=t(`${d}-bounce-topic`);u[A]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${d}-email-bounces`}};let C=t(`${d}-complaint-topic`);u[C]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${d}-email-complaints`}}}if(c.server?.enabled){let A=t(`${d}-inbound-email`);u[A]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${d}-inbound-email`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:60,MemorySize:256,Code:{ZipFile:te.InboundEmailCode},Environment:{Variables:{EMAIL_BUCKET:g,DOMAIN:c.domain}}}};let C=t(`${d}-outbound-email`);u[C]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${d}-outbound-email`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:30,MemorySize:256,Code:{ZipFile:te.OutboundEmailCode},Environment:{Variables:{EMAIL_BUCKET:g,DOMAIN:c.domain}}}}}if(c.advanced?.analytics){let A=t(`${d}-email-analytics`);u[A]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-email-analytics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.scheduling){let A=t(`${d}-email-scheduler`);u[A]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${d}-email-scheduler`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:300,MemorySize:256,Code:{ZipFile:te.EmailSchedulerCode},Environment:{Variables:{EMAIL_BUCKET:g}}}};let C=t(`${d}-email-scheduler-rule`);u[C]={Type:"AWS::Events::Rule",Properties:{Name:`${d}-email-scheduler`,ScheduleExpression:"rate(1 minute)",State:"ENABLED",Targets:[{Id:"EmailSchedulerTarget",Arn:M.GetAtt(A,"Arn")}]}}}if(c.advanced?.threading){let A=t(`${d}-email-threading`);u[A]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${d}-email-threading`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:60,MemorySize:256,Code:{ZipFile:te.EmailThreadingCode},Environment:{Variables:{EMAIL_BUCKET:g}}}}}if(c.advanced?.rules){let A=t(`${d}-email-rules`);u[A]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-email-rules`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"mailbox",AttributeType:"S"},{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"mailbox",KeyType:"HASH"},{AttributeName:"id",KeyType:"RANGE"}]}}}if(c.advanced?.sharedMailboxes){let A=t(`${d}-shared-mailboxes`);u[A]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-shared-mailboxes`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"},{AttributeName:"type",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],GlobalSecondaryIndexes:[{IndexName:"type-index",KeySchema:[{AttributeName:"type",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"}}]}}}if(c.advanced?.search){let A=t(`${d}-email-search`);u[A]={Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:`${d}-email-search`.toLowerCase().replace(/[^a-z0-9-]/g,"-").substring(0,28),EngineVersion:"OpenSearch_2.11",ClusterConfig:{InstanceType:"t3.small.search",InstanceCount:1},EBSOptions:{EBSEnabled:!0,VolumeType:"gp3",VolumeSize:10},NodeToNodeEncryptionOptions:{Enabled:!0},EncryptionAtRestOptions:{Enabled:!0},DomainEndpointOptions:{EnforceHTTPS:!0}}}}return u}static generatePhoneResources(n,i){let{slug:s,environment:o,phone:c}=n;if(!c)return{};let u={},d=`${s}-${o}`,g=t(`${d}-call-log`);if(u[g]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-call-log`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"contactId",AttributeType:"S"}],KeySchema:[{AttributeName:"contactId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}},c.voicemail?.enabled){let A=t(`${d}-voicemail`);u[A]={Type:"AWS::S3::Bucket",Properties:{BucketName:`${d}-voicemail`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldVoicemails",Status:"Enabled",ExpirationInDays:90}]}}}}let y=t(`${d}-phone-notifications`);u[y]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${d}-phone-notifications`}};let h=t(`${d}-incoming-call`);if(u[h]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${d}-incoming-call`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:30,MemorySize:256,Code:{ZipFile:te.IncomingCallCode},Environment:{Variables:{CALL_LOG_TABLE:`${d}-call-log`,NOTIFICATION_TOPIC_ARN:M.Ref(y)}}}},c.voicemail?.enabled){let A=t(`${d}-voicemail-handler`);u[A]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${d}-voicemail-handler`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:c.voicemail.transcription?300:60,MemorySize:256,Code:{ZipFile:te.VoicemailCode},Environment:{Variables:{VOICEMAIL_BUCKET:`${d}-voicemail`,TRANSCRIPTION_ENABLED:String(c.voicemail.transcription||!1),NOTIFICATION_TOPIC_ARN:M.Ref(y)}}}}}if(c.advanced?.recording){let A=t(`${d}-call-recordings`);u[A]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-call-recordings`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"recordingId",AttributeType:"S"}],KeySchema:[{AttributeName:"recordingId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.callbacks){let A=t(`${d}-callbacks`);u[A]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-callbacks`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.analytics){let A=t(`${d}-call-metrics`);u[A]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-call-metrics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"period",AttributeType:"S"}],KeySchema:[{AttributeName:"period",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}return u}static generateSmsResources(n,i){let{slug:s,environment:o,sms:c}=n;if(!c)return{};let u={},d=`${s}-${o}`,g=t(`${d}-pinpoint-app`);u[g]={Type:"AWS::Pinpoint::App",Properties:{Name:`${d}-sms`}};let y=t(`${d}-sms-channel`);u[y]={Type:"AWS::Pinpoint::SMSChannel",Properties:{ApplicationId:M.Ref(g),Enabled:!0,SenderId:c.senderId}};let h=t(`${d}-sms-log`);if(u[h]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-sms-log`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}},c.optOut?.enabled){let T=t(`${d}-sms-optout`);u[T]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-sms-optout`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}]}}}let A=t(`${d}-sms-notifications`);u[A]={Type:"AWS::SNS::Topic",Properties:{TopicName:`${d}-sms-notifications`}};let C=t(`${d}-send-sms`);u[C]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${d}-send-sms`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:30,MemorySize:256,Code:{ZipFile:te.SendSmsCode},Environment:{Variables:{PINPOINT_APP_ID:M.Ref(g),MESSAGE_LOG_TABLE:`${d}-sms-log`,OPT_OUT_TABLE:c.optOut?.enabled?`${d}-sms-optout`:"",MESSAGE_TYPE:c.messageType||"TRANSACTIONAL"}}}};let v=t(`${d}-receive-sms`);if(u[v]={Type:"AWS::Lambda::Function",Properties:{FunctionName:`${d}-receive-sms`,Runtime:"nodejs20.x",Handler:"index.handler",Role:i,Timeout:30,MemorySize:256,Code:{ZipFile:te.ReceiveSmsCode},Environment:{Variables:{MESSAGE_LOG_TABLE:`${d}-sms-log`,OPT_OUT_TABLE:c.optOut?.enabled?`${d}-sms-optout`:"",NOTIFICATION_TOPIC_ARN:M.Ref(A)}}}},c.advanced?.campaigns){let T=t(`${d}-sms-campaigns`);u[T]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-sms-campaigns`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}if(c.advanced?.analytics){let T=t(`${d}-sms-analytics`);u[T]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-sms-analytics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"period",AttributeType:"S"}],KeySchema:[{AttributeName:"period",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.linkTracking){let T=t(`${d}-short-links`);u[T]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-short-links`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}if(c.advanced?.chatbot){let T=t(`${d}-chatbot-sessions`);u[T]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-chatbot-sessions`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}};let R=t(`${d}-chatbot-rules`);u[R]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-chatbot-rules`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}if(c.advanced?.abTesting){let T=t(`${d}-ab-tests`);u[T]={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${d}-ab-tests`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}if(c.advanced?.mms){let T=t(`${d}-mms-media`);u[T]={Type:"AWS::S3::Bucket",Properties:{BucketName:`${d}-mms-media`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldMedia",Status:"Enabled",ExpirationInDays:30}]}}}}return u}static InboundEmailCode=`
2336
2336
  const { S3Client, GetObjectCommand, PutObjectCommand } = require('@aws-sdk/client-s3');
2337
2337
  const s3 = new S3Client({});
2338
2338
  exports.handler = async (event) => {
@@ -2430,7 +2430,7 @@ exports.handler = async (event) => {
2430
2430
  console.log('Receive SMS:', JSON.stringify(event, null, 2));
2431
2431
  // Process inbound SMS, handle opt-out keywords
2432
2432
  return { statusCode: 200 };
2433
- };`}var e={ref:(n)=>({Ref:n}),getAtt:(n,i)=>({"Fn::GetAtt":[n,i]}),join:(n,i)=>({"Fn::Join":[n,i]}),sub:(n,i)=>i?{"Fn::Sub":[n,i]}:{"Fn::Sub":n},select:(n,i)=>({"Fn::Select":[n,i]}),split:(n,i)=>({"Fn::Split":[n,i]}),getAZs:(n="")=>({"Fn::GetAZs":n}),importValue:(n)=>({"Fn::ImportValue":n}),findInMap:(n,i,s)=>({"Fn::FindInMap":[n,i,s]}),base64:(n)=>({"Fn::Base64":n}),cidr:(n,i,s)=>({"Fn::Cidr":[n,i,s]}),equals:(n,i)=>({"Fn::Equals":[n,i]}),if:(n,i,s)=>({"Fn::If":[n,i,s]}),not:(n)=>({"Fn::Not":[n]}),and:(...n)=>({"Fn::And":n}),or:(...n)=>({"Fn::Or":n})},gn={s3Bucket:(n)=>e.sub(`arn:aws:s3:::${n}`),s3Object:(n,i="*")=>e.sub(`arn:aws:s3:::${n}/${i}`),lambda:(n,i,s)=>e.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${n}`,i&&s?{"AWS::Region":i,"AWS::AccountId":s}:void 0),dynamodb:(n)=>e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${n}`),sqs:(n)=>e.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${n}`),sns:(n)=>e.sub(`arn:aws:sns:\${AWS::Region}:\${AWS::AccountId}:${n}`),kinesis:(n)=>e.sub(`arn:aws:kinesis:\${AWS::Region}:\${AWS::AccountId}:stream/${n}`),iam:(n,i)=>e.sub(`arn:aws:iam::\${AWS::AccountId}:${n}/${i}`),secretsManager:(n)=>e.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${n}`),cloudwatch:(n)=>e.sub(`arn:aws:logs:\${AWS::Region}:\${AWS::AccountId}:log-group:${n}`)},XI={ACCOUNT_ID:{Ref:"AWS::AccountId"},NOTIFICATION_ARNS:{Ref:"AWS::NotificationARNs"},NO_VALUE:{Ref:"AWS::NoValue"},PARTITION:{Ref:"AWS::Partition"},REGION:{Ref:"AWS::Region"},STACK_ID:{Ref:"AWS::StackId"},STACK_NAME:{Ref:"AWS::StackName"},URL_SUFFIX:{Ref:"AWS::URLSuffix"}};function bn(n,i){if(i.type==="http")$r(n,i);else if(i.type==="rest")Br(n,i);else if(i.type==="websocket")Fr(n,i)}function $r(n,i){let s={Name:e.sub("${AWS::StackName}-http-api"),ProtocolType:"HTTP"};if(i.cors)s.CorsConfiguration={AllowOrigins:i.cors.allowOrigins,AllowMethods:i.cors.allowMethods,AllowHeaders:i.cors.allowHeaders||["*"],MaxAge:i.cors.maxAge||300};if(n.addResource("HttpApi","AWS::ApiGatewayV2::Api",s),n.addResource("HttpApiStage","AWS::ApiGatewayV2::Stage",{ApiId:e.ref("HttpApi"),StageName:"$default",AutoDeploy:!0,DefaultRouteSettings:i.throttling?{ThrottlingBurstLimit:i.throttling.burstLimit,ThrottlingRateLimit:i.throttling.rateLimit}:void 0,AccessLogSettings:{DestinationArn:e.getAtt("ApiLogGroup","Arn"),Format:"$context.requestId $context.error.message $context.error.messageString"}},{dependsOn:["HttpApi","ApiLogGroup"]}),n.addResource("ApiLogGroup","AWS::Logs::LogGroup",{LogGroupName:e.sub("/aws/apigateway/${AWS::StackName}-http-api"),RetentionInDays:14}),i.authorizer)Gr(n,"HttpApi",i.authorizer);if(i.customDomain)Rt(n,"HttpApi",i.customDomain,"HTTP");n.addOutputs({HttpApiId:{Description:"HTTP API ID",Value:e.ref("HttpApi"),Export:{Name:e.sub("${AWS::StackName}-http-api-id")}},HttpApiEndpoint:{Description:"HTTP API endpoint",Value:e.getAtt("HttpApi","ApiEndpoint"),Export:{Name:e.sub("${AWS::StackName}-http-api-endpoint")}}})}function Br(n,i){n.addResource("RestApi","AWS::ApiGateway::RestApi",{Name:e.sub("${AWS::StackName}-rest-api"),Description:e.sub("REST API for ${AWS::StackName}"),EndpointConfiguration:{Types:["REGIONAL"]}}),n.addResource("ApiGatewayAccount","AWS::ApiGateway::Account",{CloudWatchRoleArn:e.getAtt("ApiGatewayCloudWatchRole","Arn")},{dependsOn:"ApiGatewayCloudWatchRole"}),n.addResource("ApiGatewayCloudWatchRole","AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"apigateway.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs"]}),n.addResource("RestApiDeployment","AWS::ApiGateway::Deployment",{RestApiId:e.ref("RestApi"),Description:"Initial deployment"},{dependsOn:"RestApi"});let s={RestApiId:e.ref("RestApi"),DeploymentId:e.ref("RestApiDeployment"),StageName:"prod",Description:"Production stage",MethodSettings:[{ResourcePath:"/*",HttpMethod:"*",LoggingLevel:"INFO",DataTraceEnabled:!0,MetricsEnabled:!0}]};if(i.throttling)s.MethodSettings[0].ThrottlingBurstLimit=i.throttling.burstLimit,s.MethodSettings[0].ThrottlingRateLimit=i.throttling.rateLimit;if(n.addResource("RestApiStage","AWS::ApiGateway::Stage",s,{dependsOn:["RestApi","RestApiDeployment"]}),i.customDomain)Rt(n,"RestApi",i.customDomain,"REST");n.addOutputs({RestApiId:{Description:"REST API ID",Value:e.ref("RestApi"),Export:{Name:e.sub("${AWS::StackName}-rest-api-id")}},RestApiEndpoint:{Description:"REST API endpoint",Value:e.sub("https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/prod"),Export:{Name:e.sub("${AWS::StackName}-rest-api-endpoint")}}})}function Fr(n,i){if(n.addResource("WebSocketApi","AWS::ApiGatewayV2::Api",{Name:e.sub("${AWS::StackName}-websocket-api"),ProtocolType:"WEBSOCKET",RouteSelectionExpression:"$request.body.action"}),i.routes){if(i.routes.connect)lt(n,"$connect",i.routes.connect.functionName);if(i.routes.disconnect)lt(n,"$disconnect",i.routes.disconnect.functionName);if(i.routes.default)lt(n,"$default",i.routes.default.functionName);if(i.routes.custom)i.routes.custom.forEach((s)=>{lt(n,s.routeKey,s.functionName)})}if(n.addResource("WebSocketApiStage","AWS::ApiGatewayV2::Stage",{ApiId:e.ref("WebSocketApi"),StageName:"prod",AutoDeploy:!0,DefaultRouteSettings:i.throttling?{ThrottlingBurstLimit:i.throttling.burstLimit,ThrottlingRateLimit:i.throttling.rateLimit}:void 0},{dependsOn:"WebSocketApi"}),i.customDomain)Rt(n,"WebSocketApi",i.customDomain,"WEBSOCKET");n.addOutputs({WebSocketApiId:{Description:"WebSocket API ID",Value:e.ref("WebSocketApi"),Export:{Name:e.sub("${AWS::StackName}-websocket-api-id")}},WebSocketApiEndpoint:{Description:"WebSocket API endpoint",Value:e.getAtt("WebSocketApi","ApiEndpoint"),Export:{Name:e.sub("${AWS::StackName}-websocket-api-endpoint")}}})}function lt(n,i,s){let o=n.toLogicalId(`websocket-route-${i}`),c=n.toLogicalId(`websocket-integration-${i}`),u=n.toLogicalId(`${s}-function`);n.addResource(c,"AWS::ApiGatewayV2::Integration",{ApiId:e.ref("WebSocketApi"),IntegrationType:"AWS_PROXY",IntegrationUri:e.sub(`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${u}.Arn}/invocations`)},{dependsOn:["WebSocketApi",u]}),n.addResource(o,"AWS::ApiGatewayV2::Route",{ApiId:e.ref("WebSocketApi"),RouteKey:i,Target:e.join("/",["integrations",e.ref(c)])},{dependsOn:["WebSocketApi",c]}),n.addResource(`${o}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(u),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:e.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${WebSocketApi}/*")},{dependsOn:[u,"WebSocketApi"]})}function Rt(n,i,s,o){let c={DomainName:s.domain};if(o==="REST")c.CertificateArn=s.certificateArn,c.EndpointConfiguration={Types:["REGIONAL"]},n.addResource("ApiCustomDomain","AWS::ApiGateway::DomainName",c),n.addResource("ApiBasePathMapping","AWS::ApiGateway::BasePathMapping",{DomainName:e.ref("ApiCustomDomain"),RestApiId:e.ref(i),Stage:e.ref("RestApiStage")},{dependsOn:["ApiCustomDomain",i,"RestApiStage"]});else c.DomainNameConfigurations=[{CertificateArn:s.certificateArn,EndpointType:"REGIONAL"}],n.addResource("ApiCustomDomain","AWS::ApiGatewayV2::DomainName",c),n.addResource("ApiMapping","AWS::ApiGatewayV2::ApiMapping",{ApiId:e.ref(i),DomainName:e.ref("ApiCustomDomain"),Stage:o==="HTTP"?e.ref("HttpApiStage"):e.ref("WebSocketApiStage")},{dependsOn:["ApiCustomDomain",i]});if(s.dnsProvider!=="external")n.addResource("ApiDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:e.sub(`${_r(s.domain)}.`),Name:s.domain,Type:"A",AliasTarget:{HostedZoneId:e.getAtt("ApiCustomDomain","RegionalHostedZoneId"),DNSName:e.getAtt("ApiCustomDomain","RegionalDomainName"),EvaluateTargetHealth:!1}},{dependsOn:"ApiCustomDomain"});n.addOutputs({ApiCustomDomainName:{Description:"Configured API custom domain",Value:s.domain},ApiCustomDomainTarget:{Description:"DNS target for Route53 or an external DNS provider",Value:e.getAtt("ApiCustomDomain","RegionalDomainName")},ApiCustomDomainHostedZoneId:{Description:"Regional API Gateway hosted zone ID",Value:e.getAtt("ApiCustomDomain","RegionalHostedZoneId")}})}function Gr(n,i,s){if(!s)return;if(s.type==="jwt")n.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:e.ref(i),AuthorizerType:"JWT",IdentitySource:[s.identitySource||"$request.header.Authorization"],JwtConfiguration:{Issuer:s.issuer,Audience:s.audience},Name:"JWTAuthorizer"},{dependsOn:i});else if(s.type==="lambda")n.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:e.ref(i),AuthorizerType:"REQUEST",AuthorizerUri:s.authorizerUri,IdentitySource:[s.identitySource||"$request.header.Authorization"],Name:"LambdaAuthorizer"},{dependsOn:i})}function _r(n){let i=n.split(".");if(i.length>=2)return i.slice(-2).join(".");return n}function Sn(n,i){if(i.redis)Wr(n,i.redis);if(i.memcached)Vr(n,i.memcached);if(i.elasticache)Ur(n,i.elasticache)}function Wr(n,i){if(!i)return;if(n.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache Redis cluster",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-subnet-group")}]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]}),n.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Redis",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:i.port||6379,ToPort:i.port||6379,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]}),i.parameterGroup&&Object.keys(i.parameterGroup).length>0)n.addResource("CacheParameterGroup","AWS::ElastiCache::ParameterGroup",{Description:"Parameter group for Redis",CacheParameterGroupFamily:`redis${i.engineVersion.split(".")[0]}`,Properties:i.parameterGroup});if(i.numCacheNodes>1||i.automaticFailoverEnabled)n.addResource("RedisReplicationGroup","AWS::ElastiCache::ReplicationGroup",{ReplicationGroupDescription:"Redis replication group",ReplicationGroupId:e.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:i.engineVersion,CacheNodeType:i.nodeType,NumCacheClusters:i.numCacheNodes,AutomaticFailoverEnabled:i.automaticFailoverEnabled||!1,MultiAZEnabled:i.automaticFailoverEnabled||!1,Port:i.port||6379,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),SecurityGroupIds:[e.ref("CacheSecurityGroup")],CacheParameterGroupName:i.parameterGroup?e.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:i.snapshotRetentionLimit||5,SnapshotWindow:i.snapshotWindow||"03:00-05:00",PreferredMaintenanceWindow:"sun:05:00-sun:06:00",AtRestEncryptionEnabled:!0,TransitEncryptionEnabled:!0,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-redis")}]},{dependsOn:i.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),n.addOutputs({RedisEndpoint:{Description:"Redis primary endpoint",Value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Address"),Export:{Name:e.sub("${AWS::StackName}-redis-endpoint")}},RedisPort:{Description:"Redis port",Value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Port"),Export:{Name:e.sub("${AWS::StackName}-redis-port")}}});else n.addResource("RedisCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:i.engineVersion,CacheNodeType:i.nodeType,NumCacheNodes:1,Port:i.port||6379,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],CacheParameterGroupName:i.parameterGroup?e.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:i.snapshotRetentionLimit||5,SnapshotWindow:i.snapshotWindow||"03:00-05:00",PreferredMaintenanceWindow:"sun:05:00-sun:06:00",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-redis")}]},{dependsOn:i.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),n.addOutputs({RedisEndpoint:{Description:"Redis endpoint",Value:e.getAtt("RedisCacheCluster","RedisEndpoint.Address"),Export:{Name:e.sub("${AWS::StackName}-redis-endpoint")}},RedisPort:{Description:"Redis port",Value:e.getAtt("RedisCacheCluster","RedisEndpoint.Port"),Export:{Name:e.sub("${AWS::StackName}-redis-port")}}})}function Vr(n,i){if(!i)return;if(!n.hasResource("CacheSubnetGroup"))n.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!n.hasResource("CacheSecurityGroup"))n.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Memcached",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:i.port||11211,ToPort:i.port||11211,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});n.addResource("MemcachedCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub("${AWS::StackName}-memcached"),Engine:"memcached",EngineVersion:i.engineVersion,CacheNodeType:i.nodeType,NumCacheNodes:i.numCacheNodes,Port:i.port||11211,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],PreferredMaintenanceWindow:"sun:05:00-sun:06:00",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-memcached")}]},{dependsOn:["CacheSubnetGroup","CacheSecurityGroup"]}),n.addOutputs({MemcachedEndpoint:{Description:"Memcached configuration endpoint",Value:e.getAtt("MemcachedCacheCluster","ConfigurationEndpoint.Address"),Export:{Name:e.sub("${AWS::StackName}-memcached-endpoint")}},MemcachedPort:{Description:"Memcached port",Value:e.getAtt("MemcachedCacheCluster","ConfigurationEndpoint.Port"),Export:{Name:e.sub("${AWS::StackName}-memcached-port")}}})}function Ur(n,i){if(!i)return;let s=i.engine==="redis";if(!n.hasResource("CacheSubnetGroup"))n.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!n.hasResource("CacheSecurityGroup"))n.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:s?6379:11211,ToPort:s?6379:11211,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});n.addResource("CacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub(`\${AWS::StackName}-${i.engine}`),Engine:i.engine,EngineVersion:i.engineVersion,CacheNodeType:i.nodeType,NumCacheNodes:i.numCacheNodes,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i.engine}`)}]},{dependsOn:["CacheSubnetGroup","CacheSecurityGroup"]})}function Cn(n,i){if(!i.enabled)return;n.addResource("CloudFrontOriginAccessIdentity","AWS::CloudFront::CloudFrontOriginAccessIdentity",{CloudFrontOriginAccessIdentityConfig:{Comment:e.sub("${AWS::StackName} CloudFront OAI")}});let s=[],o=[];if(!i.origins||i.origins.length===0)s.push({Id:"S3Origin",DomainName:e.getAtt("StaticBucket","DomainName"),S3OriginConfig:{OriginAccessIdentity:e.sub("origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}")}});else i.origins.forEach((d,g)=>{let y={Id:d.id,DomainName:d.domainName};if(d.originPath)y.OriginPath=d.originPath;if(d.domainName.includes("s3"))y.S3OriginConfig={OriginAccessIdentity:e.sub("origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}")};else y.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"]};if(s.push(y),g>0||d.pathPattern)o.push({PathPattern:d.pathPattern||`/${d.id}/*`,TargetOriginId:d.id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:i.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:i.cachePolicy?.minTTL||0,DefaultTTL:i.cachePolicy?.defaultTTL||86400,MaxTTL:i.cachePolicy?.maxTTL||31536000})});let c={TargetOriginId:s[0].Id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:i.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:i.cachePolicy?.minTTL||0,DefaultTTL:i.cachePolicy?.defaultTTL||86400,MaxTTL:i.cachePolicy?.maxTTL||31536000};if(i.edgeFunctions&&i.edgeFunctions.length>0)c.LambdaFunctionAssociations=i.edgeFunctions.map((d)=>({EventType:d.eventType,LambdaFunctionARN:d.functionArn}));let u={Enabled:!0,HttpVersion:i.http3?"http3":"http2",IPV6Enabled:!0,Origins:s,DefaultCacheBehavior:c,PriceClass:i.priceClass||"PriceClass_100",ViewerCertificate:{}};if(o.length>0)u.CacheBehaviors=o;if(i.customDomain)u.Aliases=[i.customDomain.domain],u.ViewerCertificate={AcmCertificateArn:i.customDomain.certificateArn,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};else u.ViewerCertificate={CloudFrontDefaultCertificate:!0};if(i.errorPages)u.CustomErrorResponses=Object.entries(i.errorPages).map(([d,g])=>({ErrorCode:Number.parseInt(d),ResponseCode:200,ResponsePagePath:g,ErrorCachingMinTTL:300}));if(u.DefaultRootObject="index.html",u.Comment=e.sub("${AWS::StackName} CloudFront Distribution"),n.addResource("CloudFrontDistribution","AWS::CloudFront::Distribution",{DistributionConfig:u},{dependsOn:"CloudFrontOriginAccessIdentity"}),!i.origins||i.origins.length===0)n.addResource("StaticBucketPolicyForCloudFront","AWS::S3::BucketPolicy",{Bucket:e.ref("StaticBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowCloudFrontAccess",Effect:"Allow",Principal:{CanonicalUser:e.getAtt("CloudFrontOriginAccessIdentity","S3CanonicalUserId")},Action:"s3:GetObject",Resource:e.join("",[e.getAtt("StaticBucket","Arn"),"/*"])}]}},{dependsOn:["StaticBucket","CloudFrontOriginAccessIdentity"]});if(i.customDomain)n.addResource("CloudFrontDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:e.sub(`${Hr(i.customDomain.domain)}.`),Name:i.customDomain.domain,Type:"A",AliasTarget:{HostedZoneId:"Z2FDTNDATAQYW2",DNSName:e.getAtt("CloudFrontDistribution","DomainName"),EvaluateTargetHealth:!1}},{dependsOn:"CloudFrontDistribution"});if(n.addOutputs({CloudFrontDistributionId:{Description:"CloudFront distribution ID",Value:e.ref("CloudFrontDistribution"),Export:{Name:e.sub("${AWS::StackName}-cloudfront-id")}},CloudFrontDomainName:{Description:"CloudFront distribution domain name",Value:e.getAtt("CloudFrontDistribution","DomainName"),Export:{Name:e.sub("${AWS::StackName}-cloudfront-domain")}}}),i.customDomain)n.addOutputs({CloudFrontURL:{Description:"CloudFront custom domain URL",Value:e.sub(`https://${i.customDomain.domain}`)}})}function Hr(n){let i=n.split(".");if(i.length>=2)return i.slice(-2).join(".");return n}function Tn(n,i){if(i.server)jr(n,i.server);if(i.fargate)vn(n,"app",i.fargate);if(i.services)i.services.forEach((s)=>{if(s.type==="fargate")vn(n,s.name,{taskDefinition:s.taskDefinition,service:s.service})})}function jr(n,i){if(!i)return;n.addResource("AppSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for application instances",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:3000,ToPort:3000,SourceSecurityGroupId:e.ref("ALBSecurityGroup")},{IpProtocol:"tcp",FromPort:22,ToPort:22,CidrIp:"0.0.0.0/0"}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-app-sg")}]},{dependsOn:"VPC"}),n.addResource("EC2InstanceRole","AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ec2.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore","arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-ec2-role")}]}),n.addResource("EC2InstanceProfile","AWS::IAM::InstanceProfile",{Roles:[e.ref("EC2InstanceRole")]},{dependsOn:"EC2InstanceRole"});let s=i.userData||`#!/bin/bash
2433
+ };`}var e={ref:(n)=>({Ref:n}),getAtt:(n,i)=>({"Fn::GetAtt":[n,i]}),join:(n,i)=>({"Fn::Join":[n,i]}),sub:(n,i)=>i?{"Fn::Sub":[n,i]}:{"Fn::Sub":n},select:(n,i)=>({"Fn::Select":[n,i]}),split:(n,i)=>({"Fn::Split":[n,i]}),getAZs:(n="")=>({"Fn::GetAZs":n}),importValue:(n)=>({"Fn::ImportValue":n}),findInMap:(n,i,s)=>({"Fn::FindInMap":[n,i,s]}),base64:(n)=>({"Fn::Base64":n}),cidr:(n,i,s)=>({"Fn::Cidr":[n,i,s]}),equals:(n,i)=>({"Fn::Equals":[n,i]}),if:(n,i,s)=>({"Fn::If":[n,i,s]}),not:(n)=>({"Fn::Not":[n]}),and:(...n)=>({"Fn::And":n}),or:(...n)=>({"Fn::Or":n})},pn={s3Bucket:(n)=>e.sub(`arn:aws:s3:::${n}`),s3Object:(n,i="*")=>e.sub(`arn:aws:s3:::${n}/${i}`),lambda:(n,i,s)=>e.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${n}`,i&&s?{"AWS::Region":i,"AWS::AccountId":s}:void 0),dynamodb:(n)=>e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${n}`),sqs:(n)=>e.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${n}`),sns:(n)=>e.sub(`arn:aws:sns:\${AWS::Region}:\${AWS::AccountId}:${n}`),kinesis:(n)=>e.sub(`arn:aws:kinesis:\${AWS::Region}:\${AWS::AccountId}:stream/${n}`),iam:(n,i)=>e.sub(`arn:aws:iam::\${AWS::AccountId}:${n}/${i}`),secretsManager:(n)=>e.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${n}`),cloudwatch:(n)=>e.sub(`arn:aws:logs:\${AWS::Region}:\${AWS::AccountId}:log-group:${n}`)},db={ACCOUNT_ID:{Ref:"AWS::AccountId"},NOTIFICATION_ARNS:{Ref:"AWS::NotificationARNs"},NO_VALUE:{Ref:"AWS::NoValue"},PARTITION:{Ref:"AWS::Partition"},REGION:{Ref:"AWS::Region"},STACK_ID:{Ref:"AWS::StackId"},STACK_NAME:{Ref:"AWS::StackName"},URL_SUFFIX:{Ref:"AWS::URLSuffix"}};function Pn(n,i){if(i.type==="http")Jr(n,i);else if(i.type==="rest")Yr(n,i);else if(i.type==="websocket")Zr(n,i)}function Jr(n,i){let s={Name:e.sub("${AWS::StackName}-http-api"),ProtocolType:"HTTP"};if(i.cors)s.CorsConfiguration={AllowOrigins:i.cors.allowOrigins,AllowMethods:i.cors.allowMethods,AllowHeaders:i.cors.allowHeaders||["*"],MaxAge:i.cors.maxAge||300};if(n.addResource("HttpApi","AWS::ApiGatewayV2::Api",s),n.addResource("HttpApiStage","AWS::ApiGatewayV2::Stage",{ApiId:e.ref("HttpApi"),StageName:"$default",AutoDeploy:!0,DefaultRouteSettings:i.throttling?{ThrottlingBurstLimit:i.throttling.burstLimit,ThrottlingRateLimit:i.throttling.rateLimit}:void 0,AccessLogSettings:{DestinationArn:e.getAtt("ApiLogGroup","Arn"),Format:"$context.requestId $context.error.message $context.error.messageString"}},{dependsOn:["HttpApi","ApiLogGroup"]}),n.addResource("ApiLogGroup","AWS::Logs::LogGroup",{LogGroupName:e.sub("/aws/apigateway/${AWS::StackName}-http-api"),RetentionInDays:14}),i.authorizer)Xr(n,"HttpApi",i.authorizer);if(i.customDomain)Et(n,"HttpApi",i.customDomain,"HTTP");n.addOutputs({HttpApiId:{Description:"HTTP API ID",Value:e.ref("HttpApi"),Export:{Name:e.sub("${AWS::StackName}-http-api-id")}},HttpApiEndpoint:{Description:"HTTP API endpoint",Value:e.getAtt("HttpApi","ApiEndpoint"),Export:{Name:e.sub("${AWS::StackName}-http-api-endpoint")}}})}function Yr(n,i){n.addResource("RestApi","AWS::ApiGateway::RestApi",{Name:e.sub("${AWS::StackName}-rest-api"),Description:e.sub("REST API for ${AWS::StackName}"),EndpointConfiguration:{Types:["REGIONAL"]}}),n.addResource("ApiGatewayAccount","AWS::ApiGateway::Account",{CloudWatchRoleArn:e.getAtt("ApiGatewayCloudWatchRole","Arn")},{dependsOn:"ApiGatewayCloudWatchRole"}),n.addResource("ApiGatewayCloudWatchRole","AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"apigateway.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs"]}),n.addResource("RestApiDeployment","AWS::ApiGateway::Deployment",{RestApiId:e.ref("RestApi"),Description:"Initial deployment"},{dependsOn:"RestApi"});let s={RestApiId:e.ref("RestApi"),DeploymentId:e.ref("RestApiDeployment"),StageName:"prod",Description:"Production stage",MethodSettings:[{ResourcePath:"/*",HttpMethod:"*",LoggingLevel:"INFO",DataTraceEnabled:!0,MetricsEnabled:!0}]};if(i.throttling)s.MethodSettings[0].ThrottlingBurstLimit=i.throttling.burstLimit,s.MethodSettings[0].ThrottlingRateLimit=i.throttling.rateLimit;if(n.addResource("RestApiStage","AWS::ApiGateway::Stage",s,{dependsOn:["RestApi","RestApiDeployment"]}),i.customDomain)Et(n,"RestApi",i.customDomain,"REST");n.addOutputs({RestApiId:{Description:"REST API ID",Value:e.ref("RestApi"),Export:{Name:e.sub("${AWS::StackName}-rest-api-id")}},RestApiEndpoint:{Description:"REST API endpoint",Value:e.sub("https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/prod"),Export:{Name:e.sub("${AWS::StackName}-rest-api-endpoint")}}})}function Zr(n,i){if(n.addResource("WebSocketApi","AWS::ApiGatewayV2::Api",{Name:e.sub("${AWS::StackName}-websocket-api"),ProtocolType:"WEBSOCKET",RouteSelectionExpression:"$request.body.action"}),i.routes){if(i.routes.connect)ut(n,"$connect",i.routes.connect.functionName);if(i.routes.disconnect)ut(n,"$disconnect",i.routes.disconnect.functionName);if(i.routes.default)ut(n,"$default",i.routes.default.functionName);if(i.routes.custom)i.routes.custom.forEach((s)=>{ut(n,s.routeKey,s.functionName)})}if(n.addResource("WebSocketApiStage","AWS::ApiGatewayV2::Stage",{ApiId:e.ref("WebSocketApi"),StageName:"prod",AutoDeploy:!0,DefaultRouteSettings:i.throttling?{ThrottlingBurstLimit:i.throttling.burstLimit,ThrottlingRateLimit:i.throttling.rateLimit}:void 0},{dependsOn:"WebSocketApi"}),i.customDomain)Et(n,"WebSocketApi",i.customDomain,"WEBSOCKET");n.addOutputs({WebSocketApiId:{Description:"WebSocket API ID",Value:e.ref("WebSocketApi"),Export:{Name:e.sub("${AWS::StackName}-websocket-api-id")}},WebSocketApiEndpoint:{Description:"WebSocket API endpoint",Value:e.getAtt("WebSocketApi","ApiEndpoint"),Export:{Name:e.sub("${AWS::StackName}-websocket-api-endpoint")}}})}function ut(n,i,s){let o=n.toLogicalId(`websocket-route-${i}`),c=n.toLogicalId(`websocket-integration-${i}`),u=n.toLogicalId(`${s}-function`);n.addResource(c,"AWS::ApiGatewayV2::Integration",{ApiId:e.ref("WebSocketApi"),IntegrationType:"AWS_PROXY",IntegrationUri:e.sub(`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${u}.Arn}/invocations`)},{dependsOn:["WebSocketApi",u]}),n.addResource(o,"AWS::ApiGatewayV2::Route",{ApiId:e.ref("WebSocketApi"),RouteKey:i,Target:e.join("/",["integrations",e.ref(c)])},{dependsOn:["WebSocketApi",c]}),n.addResource(`${o}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(u),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:e.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${WebSocketApi}/*")},{dependsOn:[u,"WebSocketApi"]})}function Et(n,i,s,o){let c={DomainName:s.domain};if(o==="REST")c.CertificateArn=s.certificateArn,c.EndpointConfiguration={Types:["REGIONAL"]},n.addResource("ApiCustomDomain","AWS::ApiGateway::DomainName",c),n.addResource("ApiBasePathMapping","AWS::ApiGateway::BasePathMapping",{DomainName:e.ref("ApiCustomDomain"),RestApiId:e.ref(i),Stage:e.ref("RestApiStage")},{dependsOn:["ApiCustomDomain",i,"RestApiStage"]});else c.DomainNameConfigurations=[{CertificateArn:s.certificateArn,EndpointType:"REGIONAL"}],n.addResource("ApiCustomDomain","AWS::ApiGatewayV2::DomainName",c),n.addResource("ApiMapping","AWS::ApiGatewayV2::ApiMapping",{ApiId:e.ref(i),DomainName:e.ref("ApiCustomDomain"),Stage:o==="HTTP"?e.ref("HttpApiStage"):e.ref("WebSocketApiStage")},{dependsOn:["ApiCustomDomain",i]});if(s.dnsProvider!=="external")n.addResource("ApiDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:e.sub(`${ei(s.domain)}.`),Name:s.domain,Type:"A",AliasTarget:{HostedZoneId:e.getAtt("ApiCustomDomain","RegionalHostedZoneId"),DNSName:e.getAtt("ApiCustomDomain","RegionalDomainName"),EvaluateTargetHealth:!1}},{dependsOn:"ApiCustomDomain"});n.addOutputs({ApiCustomDomainName:{Description:"Configured API custom domain",Value:s.domain},ApiCustomDomainTarget:{Description:"DNS target for Route53 or an external DNS provider",Value:e.getAtt("ApiCustomDomain","RegionalDomainName")},ApiCustomDomainHostedZoneId:{Description:"Regional API Gateway hosted zone ID",Value:e.getAtt("ApiCustomDomain","RegionalHostedZoneId")}})}function Xr(n,i,s){if(!s)return;if(s.type==="jwt")n.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:e.ref(i),AuthorizerType:"JWT",IdentitySource:[s.identitySource||"$request.header.Authorization"],JwtConfiguration:{Issuer:s.issuer,Audience:s.audience},Name:"JWTAuthorizer"},{dependsOn:i});else if(s.type==="lambda")n.addResource("ApiAuthorizer","AWS::ApiGatewayV2::Authorizer",{ApiId:e.ref(i),AuthorizerType:"REQUEST",AuthorizerUri:s.authorizerUri,IdentitySource:[s.identitySource||"$request.header.Authorization"],Name:"LambdaAuthorizer"},{dependsOn:i})}function ei(n){let i=n.split(".");if(i.length>=2)return i.slice(-2).join(".");return n}function En(n,i){if(i.redis)ti(n,i.redis);if(i.memcached)ni(n,i.memcached);if(i.elasticache)ri(n,i.elasticache)}function ti(n,i){if(!i)return;if(n.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache Redis cluster",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-subnet-group")}]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]}),n.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Redis",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:i.port||6379,ToPort:i.port||6379,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]}),i.parameterGroup&&Object.keys(i.parameterGroup).length>0)n.addResource("CacheParameterGroup","AWS::ElastiCache::ParameterGroup",{Description:"Parameter group for Redis",CacheParameterGroupFamily:`redis${i.engineVersion.split(".")[0]}`,Properties:i.parameterGroup});if(i.numCacheNodes>1||i.automaticFailoverEnabled)n.addResource("RedisReplicationGroup","AWS::ElastiCache::ReplicationGroup",{ReplicationGroupDescription:"Redis replication group",ReplicationGroupId:e.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:i.engineVersion,CacheNodeType:i.nodeType,NumCacheClusters:i.numCacheNodes,AutomaticFailoverEnabled:i.automaticFailoverEnabled||!1,MultiAZEnabled:i.automaticFailoverEnabled||!1,Port:i.port||6379,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),SecurityGroupIds:[e.ref("CacheSecurityGroup")],CacheParameterGroupName:i.parameterGroup?e.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:i.snapshotRetentionLimit||5,SnapshotWindow:i.snapshotWindow||"03:00-05:00",PreferredMaintenanceWindow:"sun:05:00-sun:06:00",AtRestEncryptionEnabled:!0,TransitEncryptionEnabled:!0,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-redis")}]},{dependsOn:i.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),n.addOutputs({RedisEndpoint:{Description:"Redis primary endpoint",Value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Address"),Export:{Name:e.sub("${AWS::StackName}-redis-endpoint")}},RedisPort:{Description:"Redis port",Value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Port"),Export:{Name:e.sub("${AWS::StackName}-redis-port")}}});else n.addResource("RedisCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub("${AWS::StackName}-redis"),Engine:"redis",EngineVersion:i.engineVersion,CacheNodeType:i.nodeType,NumCacheNodes:1,Port:i.port||6379,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],CacheParameterGroupName:i.parameterGroup?e.ref("CacheParameterGroup"):void 0,SnapshotRetentionLimit:i.snapshotRetentionLimit||5,SnapshotWindow:i.snapshotWindow||"03:00-05:00",PreferredMaintenanceWindow:"sun:05:00-sun:06:00",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-redis")}]},{dependsOn:i.parameterGroup?["CacheSubnetGroup","CacheSecurityGroup","CacheParameterGroup"]:["CacheSubnetGroup","CacheSecurityGroup"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),n.addOutputs({RedisEndpoint:{Description:"Redis endpoint",Value:e.getAtt("RedisCacheCluster","RedisEndpoint.Address"),Export:{Name:e.sub("${AWS::StackName}-redis-endpoint")}},RedisPort:{Description:"Redis port",Value:e.getAtt("RedisCacheCluster","RedisEndpoint.Port"),Export:{Name:e.sub("${AWS::StackName}-redis-port")}}})}function ni(n,i){if(!i)return;if(!n.hasResource("CacheSubnetGroup"))n.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!n.hasResource("CacheSecurityGroup"))n.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache Memcached",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:i.port||11211,ToPort:i.port||11211,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});n.addResource("MemcachedCacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub("${AWS::StackName}-memcached"),Engine:"memcached",EngineVersion:i.engineVersion,CacheNodeType:i.nodeType,NumCacheNodes:i.numCacheNodes,Port:i.port||11211,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],PreferredMaintenanceWindow:"sun:05:00-sun:06:00",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-memcached")}]},{dependsOn:["CacheSubnetGroup","CacheSecurityGroup"]}),n.addOutputs({MemcachedEndpoint:{Description:"Memcached configuration endpoint",Value:e.getAtt("MemcachedCacheCluster","ConfigurationEndpoint.Address"),Export:{Name:e.sub("${AWS::StackName}-memcached-endpoint")}},MemcachedPort:{Description:"Memcached port",Value:e.getAtt("MemcachedCacheCluster","ConfigurationEndpoint.Port"),Export:{Name:e.sub("${AWS::StackName}-memcached-port")}}})}function ri(n,i){if(!i)return;let s=i.engine==="redis";if(!n.hasResource("CacheSubnetGroup"))n.addResource("CacheSubnetGroup","AWS::ElastiCache::SubnetGroup",{Description:"Subnet group for ElastiCache",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]});if(!n.hasResource("CacheSecurityGroup"))n.addResource("CacheSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for ElastiCache",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:s?6379:11211,ToPort:s?6379:11211,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cache-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});n.addResource("CacheCluster","AWS::ElastiCache::CacheCluster",{ClusterName:e.sub(`\${AWS::StackName}-${i.engine}`),Engine:i.engine,EngineVersion:i.engineVersion,CacheNodeType:i.nodeType,NumCacheNodes:i.numCacheNodes,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),VpcSecurityGroupIds:[e.ref("CacheSecurityGroup")],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i.engine}`)}]},{dependsOn:["CacheSubnetGroup","CacheSecurityGroup"]})}function wn(n,i){if(!i.enabled)return;n.addResource("CloudFrontOriginAccessIdentity","AWS::CloudFront::CloudFrontOriginAccessIdentity",{CloudFrontOriginAccessIdentityConfig:{Comment:e.sub("${AWS::StackName} CloudFront OAI")}});let s=[],o=[];if(!i.origins||i.origins.length===0)s.push({Id:"S3Origin",DomainName:e.getAtt("StaticBucket","DomainName"),S3OriginConfig:{OriginAccessIdentity:e.sub("origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}")}});else i.origins.forEach((d,g)=>{let y={Id:d.id,DomainName:d.domainName};if(d.originPath)y.OriginPath=d.originPath;if(d.domainName.includes("s3"))y.S3OriginConfig={OriginAccessIdentity:e.sub("origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}")};else y.CustomOriginConfig={HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:"https-only",OriginSSLProtocols:["TLSv1.2"]};if(s.push(y),g>0||d.pathPattern)o.push({PathPattern:d.pathPattern||`/${d.id}/*`,TargetOriginId:d.id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:i.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:i.cachePolicy?.minTTL||0,DefaultTTL:i.cachePolicy?.defaultTTL||86400,MaxTTL:i.cachePolicy?.maxTTL||31536000})});let c={TargetOriginId:s[0].Id,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD"],Compress:i.compress!==!1,ForwardedValues:{QueryString:!0,Cookies:{Forward:"none"}},MinTTL:i.cachePolicy?.minTTL||0,DefaultTTL:i.cachePolicy?.defaultTTL||86400,MaxTTL:i.cachePolicy?.maxTTL||31536000};if(i.edgeFunctions&&i.edgeFunctions.length>0)c.LambdaFunctionAssociations=i.edgeFunctions.map((d)=>({EventType:d.eventType,LambdaFunctionARN:d.functionArn}));let u={Enabled:!0,HttpVersion:i.http3?"http3":"http2",IPV6Enabled:!0,Origins:s,DefaultCacheBehavior:c,PriceClass:i.priceClass||"PriceClass_100",ViewerCertificate:{}};if(o.length>0)u.CacheBehaviors=o;if(i.customDomain)u.Aliases=[i.customDomain.domain],u.ViewerCertificate={AcmCertificateArn:i.customDomain.certificateArn,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"};else u.ViewerCertificate={CloudFrontDefaultCertificate:!0};if(i.errorPages)u.CustomErrorResponses=Object.entries(i.errorPages).map(([d,g])=>({ErrorCode:Number.parseInt(d),ResponseCode:200,ResponsePagePath:g,ErrorCachingMinTTL:300}));if(u.DefaultRootObject="index.html",u.Comment=e.sub("${AWS::StackName} CloudFront Distribution"),n.addResource("CloudFrontDistribution","AWS::CloudFront::Distribution",{DistributionConfig:u},{dependsOn:"CloudFrontOriginAccessIdentity"}),!i.origins||i.origins.length===0)n.addResource("StaticBucketPolicyForCloudFront","AWS::S3::BucketPolicy",{Bucket:e.ref("StaticBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowCloudFrontAccess",Effect:"Allow",Principal:{CanonicalUser:e.getAtt("CloudFrontOriginAccessIdentity","S3CanonicalUserId")},Action:"s3:GetObject",Resource:e.join("",[e.getAtt("StaticBucket","Arn"),"/*"])}]}},{dependsOn:["StaticBucket","CloudFrontOriginAccessIdentity"]});if(i.customDomain)n.addResource("CloudFrontDNSRecord","AWS::Route53::RecordSet",{HostedZoneName:e.sub(`${ii(i.customDomain.domain)}.`),Name:i.customDomain.domain,Type:"A",AliasTarget:{HostedZoneId:"Z2FDTNDATAQYW2",DNSName:e.getAtt("CloudFrontDistribution","DomainName"),EvaluateTargetHealth:!1}},{dependsOn:"CloudFrontDistribution"});if(n.addOutputs({CloudFrontDistributionId:{Description:"CloudFront distribution ID",Value:e.ref("CloudFrontDistribution"),Export:{Name:e.sub("${AWS::StackName}-cloudfront-id")}},CloudFrontDomainName:{Description:"CloudFront distribution domain name",Value:e.getAtt("CloudFrontDistribution","DomainName"),Export:{Name:e.sub("${AWS::StackName}-cloudfront-domain")}}}),i.customDomain)n.addOutputs({CloudFrontURL:{Description:"CloudFront custom domain URL",Value:e.sub(`https://${i.customDomain.domain}`)}})}function ii(n){let i=n.split(".");if(i.length>=2)return i.slice(-2).join(".");return n}function Dn(n,i){if(i.server)si(n,i.server);if(i.fargate)In(n,"app",i.fargate);if(i.services)i.services.forEach((s)=>{if(s.type==="fargate")In(n,s.name,{taskDefinition:s.taskDefinition,service:s.service})})}function si(n,i){if(!i)return;n.addResource("AppSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for application instances",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:3000,ToPort:3000,SourceSecurityGroupId:e.ref("ALBSecurityGroup")},{IpProtocol:"tcp",FromPort:22,ToPort:22,CidrIp:"0.0.0.0/0"}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-app-sg")}]},{dependsOn:"VPC"}),n.addResource("EC2InstanceRole","AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ec2.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore","arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-ec2-role")}]}),n.addResource("EC2InstanceProfile","AWS::IAM::InstanceProfile",{Roles:[e.ref("EC2InstanceRole")]},{dependsOn:"EC2InstanceRole"});let s=i.userData||`#!/bin/bash
2434
2434
  set -e
2435
2435
  # Update system
2436
2436
  yum update -y || apt-get update -y
@@ -2445,36 +2445,34 @@ rpm -U ./amazon-cloudwatch-agent.rpm || true
2445
2445
 
2446
2446
  # Signal completion
2447
2447
  /opt/aws/bin/cfn-signal -e $? --stack \${AWS::StackName} --resource AutoScalingGroup --region \${AWS::Region}
2448
- `;if(n.addResource("LaunchTemplate","AWS::EC2::LaunchTemplate",{LaunchTemplateName:e.sub("${AWS::StackName}-template"),LaunchTemplateData:{ImageId:i.ami||e.findInMap("RegionMap",e.ref("AWS::Region"),"AMI"),InstanceType:i.instanceType,IamInstanceProfile:{Arn:e.getAtt("EC2InstanceProfile","Arn")},SecurityGroupIds:[e.ref("AppSecurityGroup")],UserData:e.base64(e.sub(s)),TagSpecifications:[{ResourceType:"instance",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-instance")}]}],MetadataOptions:{HttpTokens:"required",HttpPutResponseHopLimit:1}}},{dependsOn:["AppSecurityGroup","EC2InstanceProfile"]}),i.loadBalancer){Kr(n,i.loadBalancer);let o={LaunchTemplate:{LaunchTemplateId:e.ref("LaunchTemplate"),Version:e.getAtt("LaunchTemplate","LatestVersionNumber")},MinSize:i.autoScaling?.min.toString()||"1",MaxSize:i.autoScaling?.max.toString()||"3",DesiredCapacity:i.autoScaling?.min.toString()||"2",VPCZoneIdentifier:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],TargetGroupARNs:[e.ref("TargetGroup")],HealthCheckType:"ELB",HealthCheckGracePeriod:300,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-asg"),PropagateAtLaunch:!0}]};if(n.addResource("AutoScalingGroup","AWS::AutoScaling::AutoScalingGroup",o,{dependsOn:["LaunchTemplate","TargetGroup"]}),i.autoScaling)n.addResource("ScaleUpPolicy","AWS::AutoScaling::ScalingPolicy",{AdjustmentType:"ChangeInCapacity",AutoScalingGroupName:e.ref("AutoScalingGroup"),Cooldown:i.autoScaling.scaleUpCooldown?.toString()||"300",ScalingAdjustment:"1"},{dependsOn:"AutoScalingGroup"}),n.addResource("ScaleDownPolicy","AWS::AutoScaling::ScalingPolicy",{AdjustmentType:"ChangeInCapacity",AutoScalingGroupName:e.ref("AutoScalingGroup"),Cooldown:i.autoScaling.scaleDownCooldown?.toString()||"300",ScalingAdjustment:"-1"},{dependsOn:"AutoScalingGroup"}),n.addResource("HighCPUAlarm","AWS::CloudWatch::Alarm",{AlarmDescription:"Scale up when CPU exceeds target",MetricName:"CPUUtilization",Namespace:"AWS/EC2",Statistic:"Average",Period:"300",EvaluationPeriods:"2",Threshold:(i.autoScaling.targetCPU||70).toString(),AlarmActions:[e.ref("ScaleUpPolicy")],Dimensions:[{Name:"AutoScalingGroupName",Value:e.ref("AutoScalingGroup")}],ComparisonOperator:"GreaterThanThreshold"},{dependsOn:["AutoScalingGroup","ScaleUpPolicy"]}),n.addResource("LowCPUAlarm","AWS::CloudWatch::Alarm",{AlarmDescription:"Scale down when CPU is below threshold",MetricName:"CPUUtilization",Namespace:"AWS/EC2",Statistic:"Average",Period:"300",EvaluationPeriods:"2",Threshold:((i.autoScaling.targetCPU||70)-20).toString(),AlarmActions:[e.ref("ScaleDownPolicy")],Dimensions:[{Name:"AutoScalingGroupName",Value:e.ref("AutoScalingGroup")}],ComparisonOperator:"LessThanThreshold"},{dependsOn:["AutoScalingGroup","ScaleDownPolicy"]})}}function Kr(n,i){if(!i)return;n.addResource("ALBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for Application Load Balancer",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:80,ToPort:80,CidrIp:"0.0.0.0/0"},{IpProtocol:"tcp",FromPort:443,ToPort:443,CidrIp:"0.0.0.0/0"}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-alb-sg")}]},{dependsOn:"VPC"}),n.addResource("LoadBalancer","AWS::ElasticLoadBalancingV2::LoadBalancer",{Name:e.sub("${AWS::StackName}-alb"),Type:i.type||"application",Scheme:"internet-facing",IpAddressType:"ipv4",Subnets:[e.ref("PublicSubnet1"),e.ref("PublicSubnet2")],SecurityGroups:[e.ref("ALBSecurityGroup")],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-alb")}]},{dependsOn:["PublicSubnet1","PublicSubnet2","ALBSecurityGroup"]}),n.addResource("TargetGroup","AWS::ElasticLoadBalancingV2::TargetGroup",{Name:e.sub("${AWS::StackName}-tg"),Port:3000,Protocol:"HTTP",VpcId:e.ref("VPC"),HealthCheckEnabled:!0,HealthCheckPath:i.healthCheck?.path||"/health",HealthCheckProtocol:"HTTP",HealthCheckIntervalSeconds:i.healthCheck?.interval||30,HealthCheckTimeoutSeconds:i.healthCheck?.timeout||5,HealthyThresholdCount:i.healthCheck?.healthyThreshold||2,UnhealthyThresholdCount:i.healthCheck?.unhealthyThreshold||3,TargetType:"instance",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-tg")}]},{dependsOn:"VPC"}),n.addResource("LoadBalancerListener","AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:e.ref("LoadBalancer"),Port:80,Protocol:"HTTP",DefaultActions:[{Type:"forward",TargetGroupArn:e.ref("TargetGroup")}]},{dependsOn:["LoadBalancer","TargetGroup"]}),n.addOutputs({LoadBalancerDNS:{Description:"Load Balancer DNS Name",Value:e.getAtt("LoadBalancer","DNSName"),Export:{Name:e.sub("${AWS::StackName}-alb-dns")}}})}function vn(n,i,s){let o=n.toLogicalId(i),c=s.taskDefinition.containerDefinitions?.[0],u=c?.name||c?.Name||i,d=c?.portMappings?.[0]?.containerPort||c?.PortMappings?.[0]?.ContainerPort||3000,g=(s.taskDefinition.containerDefinitions||[]).flatMap((v)=>(v.secrets||v.Secrets||[]).map((T)=>T.valueFrom||T.ValueFrom)).filter(Boolean);if(!n.hasResource("ECSCluster"))n.addResource("ECSCluster","AWS::ECS::Cluster",{ClusterName:e.sub("${AWS::StackName}-cluster"),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cluster")}]});if(n.addResource(`${o}TaskExecutionRole`,"AWS::IAM::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"],...g.length?{Policies:[{PolicyName:"read-task-secrets",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameters"],Resource:g},{Effect:"Allow",Action:"kms:Decrypt",Resource:"*"}]}}]}:{}}),n.addResource(`${o}TaskRole`,"AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"application-services",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes","sqs:SendMessage"],Resource:e.sub("arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:${AWS::StackName}-*")},{Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail"],Resource:"*"}]}}]}),!n.hasResource("ALBSecurityGroup"))n.addResource("ALBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Public ingress for the application load balancer",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:80,ToPort:80,CidrIp:"0.0.0.0/0"},...s.loadBalancer?.customDomain?.certificateArn?[{IpProtocol:"tcp",FromPort:443,ToPort:443,CidrIp:"0.0.0.0/0"}]:[]],SecurityGroupEgress:[{IpProtocol:"tcp",FromPort:d,ToPort:d,CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-alb-sg")}]},{dependsOn:"VPC"});if(!n.hasResource("AppSecurityGroup"))n.addResource("AppSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Only the application load balancer may reach Fargate tasks",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:d,ToPort:d,SourceSecurityGroupId:e.ref("ALBSecurityGroup")}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-app-sg")}]},{dependsOn:["VPC","ALBSecurityGroup"]});let y=(s.taskDefinition.containerDefinitions||[{name:i,image:e.sub(`\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.amazonaws.com/${i}:latest`),portMappings:[{containerPort:3000}]}]).map((v)=>({Name:v.Name||v.name,Image:v.Image||v.image,Essential:v.Essential??v.essential??!0,PortMappings:(v.PortMappings||v.portMappings||[]).map((T)=>({ContainerPort:T.ContainerPort??T.containerPort,Protocol:T.Protocol||T.protocol||"tcp"})),Environment:Array.isArray(v.Environment||v.environment)?(v.Environment||v.environment).map((T)=>({Name:T.Name||T.name,Value:T.Value??T.value})):Object.entries(v.Environment||v.environment||{}).map(([T,R])=>({Name:T,Value:R})),Secrets:(v.Secrets||v.secrets||[]).map((T)=>({Name:T.Name||T.name,ValueFrom:T.ValueFrom||T.valueFrom})),HealthCheck:v.HealthCheck||v.healthCheck,Command:v.Command||v.command,EntryPoint:v.EntryPoint||v.entryPoint,LogConfiguration:v.LogConfiguration||v.logConfiguration||{LogDriver:"awslogs",Options:{"awslogs-group":e.ref(`${o}LogGroup`),"awslogs-region":e.ref("AWS::Region"),"awslogs-stream-prefix":i}}}));n.addResource(`${o}TaskDefinition`,"AWS::ECS::TaskDefinition",{Family:e.sub(`\${AWS::StackName}-${i}`),NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:s.taskDefinition.cpu,Memory:s.taskDefinition.memory,ExecutionRoleArn:e.getAtt(`${o}TaskExecutionRole`,"Arn"),TaskRoleArn:e.getAtt(`${o}TaskRole`,"Arn"),ContainerDefinitions:y},{dependsOn:[`${o}TaskExecutionRole`,`${o}TaskRole`,`${o}LogGroup`]}),n.addResource(`${o}LogGroup`,"AWS::Logs::LogGroup",{LogGroupName:e.sub(`/ecs/\${AWS::StackName}/${i}`),RetentionInDays:14});let h=s.service.healthCheck||{};n.addResource(`${o}TargetGroup`,"AWS::ElasticLoadBalancingV2::TargetGroup",{VpcId:e.ref("VPC"),Port:d,Protocol:"HTTP",TargetType:"ip",HealthCheckEnabled:!0,HealthCheckPath:h.path||"/health",HealthCheckProtocol:"HTTP",HealthCheckIntervalSeconds:h.interval||30,HealthCheckTimeoutSeconds:h.timeout||5,HealthyThresholdCount:h.healthyThreshold||2,UnhealthyThresholdCount:h.unhealthyThreshold||3,Matcher:{HttpCode:"200-399"},TargetGroupAttributes:[{Key:"deregistration_delay.timeout_seconds",Value:"30"}]},{dependsOn:"VPC"}),n.addResource(`${o}LoadBalancer`,"AWS::ElasticLoadBalancingV2::LoadBalancer",{Type:"application",Scheme:"internet-facing",IpAddressType:"ipv4",Subnets:[e.ref("PublicSubnet1"),e.ref("PublicSubnet2")],SecurityGroups:[e.ref("ALBSecurityGroup")],LoadBalancerAttributes:[{Key:"routing.http.drop_invalid_header_fields.enabled",Value:"true"},{Key:"deletion_protection.enabled",Value:String(s.loadBalancer?.deletionProtection===!0)}],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}-alb`)}]},{dependsOn:["PublicSubnet1","PublicSubnet2","ALBSecurityGroup"]});let A=s.loadBalancer?.customDomain?.certificateArn,C=s.loadBalancer?.originVerifyHeader;if(n.addResource(`${o}HttpListener`,"AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:e.ref(`${o}LoadBalancer`),Port:80,Protocol:"HTTP",DefaultActions:A?[{Type:"redirect",RedirectConfig:{Protocol:"HTTPS",Port:"443",StatusCode:"HTTP_301"}}]:C?[{Type:"fixed-response",FixedResponseConfig:{StatusCode:"403",ContentType:"text/plain",MessageBody:"Forbidden"}}]:[{Type:"forward",TargetGroupArn:e.ref(`${o}TargetGroup`)}]},{dependsOn:[`${o}LoadBalancer`,`${o}TargetGroup`]}),A)n.addResource(`${o}HttpsListener`,"AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:e.ref(`${o}LoadBalancer`),Port:443,Protocol:"HTTPS",Certificates:[{CertificateArn:A}],SslPolicy:"ELBSecurityPolicy-TLS13-1-2-2021-06",DefaultActions:C?[{Type:"fixed-response",FixedResponseConfig:{StatusCode:"403",ContentType:"text/plain",MessageBody:"Forbidden"}}]:[{Type:"forward",TargetGroupArn:e.ref(`${o}TargetGroup`)}]},{dependsOn:[`${o}LoadBalancer`,`${o}TargetGroup`]});if(C){let v=A?`${o}HttpsListener`:`${o}HttpListener`;n.addResource(`${o}OriginVerifyRule`,"AWS::ElasticLoadBalancingV2::ListenerRule",{ListenerArn:e.ref(v),Priority:1,Conditions:[{Field:"http-header",HttpHeaderConfig:{HttpHeaderName:C.name,Values:[C.value]}}],Actions:[{Type:"forward",TargetGroupArn:e.ref(`${o}TargetGroup`)}]},{dependsOn:[v,`${o}TargetGroup`]})}if(n.addResource(`${o}Service`,"AWS::ECS::Service",{ServiceName:e.sub(`\${AWS::StackName}-${i}`),Cluster:e.ref("ECSCluster"),TaskDefinition:e.ref(`${o}TaskDefinition`),DesiredCount:s.service.desiredCount,LaunchType:"FARGATE",PlatformVersion:"LATEST",HealthCheckGracePeriodSeconds:60,DeploymentConfiguration:{MinimumHealthyPercent:100,MaximumPercent:200,DeploymentCircuitBreaker:{Enable:!0,Rollback:!0}},LoadBalancers:[{ContainerName:u,ContainerPort:d,TargetGroupArn:e.ref(`${o}TargetGroup`)}],NetworkConfiguration:{AwsvpcConfiguration:{AssignPublicIp:"DISABLED",Subnets:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],SecurityGroups:[e.ref("AppSecurityGroup")]}}},{dependsOn:["ECSCluster",`${o}TaskDefinition`,C?`${o}OriginVerifyRule`:A?`${o}HttpsListener`:`${o}HttpListener`]}),s.service.autoScaling){let v=s.service.autoScaling;n.addResource(`${o}ScalableTarget`,"AWS::ApplicationAutoScaling::ScalableTarget",{MinCapacity:v.min,MaxCapacity:v.max,ResourceId:e.join("/",["service",e.ref("ECSCluster"),e.getAtt(`${o}Service`,"Name")]),RoleARN:e.sub("arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService"),ScalableDimension:"ecs:service:DesiredCount",ServiceNamespace:"ecs"},{dependsOn:`${o}Service`}),n.addResource(`${o}ScalingPolicy`,"AWS::ApplicationAutoScaling::ScalingPolicy",{PolicyType:"TargetTrackingScaling",ScalingTargetId:e.ref(`${o}ScalableTarget`),TargetTrackingScalingPolicyConfiguration:{TargetValue:v.targetCPU||70,PredefinedMetricSpecification:{PredefinedMetricType:"ECSServiceAverageCPUUtilization"},ScaleInCooldown:60,ScaleOutCooldown:30}},{dependsOn:`${o}ScalableTarget`})}n.addOutputs({[`${o}ClusterName`]:{Description:"ECS cluster name",Value:e.ref("ECSCluster")},[`${o}ServiceName`]:{Description:"ECS service name",Value:e.getAtt(`${o}Service`,"Name")},[`${o}LoadBalancerDnsName`]:{Description:"ALB origin hostname",Value:e.getAtt(`${o}LoadBalancer`,"DNSName")},[`${o}LoadBalancerHostedZoneId`]:{Description:"ALB canonical hosted zone ID",Value:e.getAtt(`${o}LoadBalancer`,"CanonicalHostedZoneID")},[`${o}TargetGroupArn`]:{Description:"ECS target group ARN",Value:e.ref(`${o}TargetGroup`)}})}function Pn(n,i){if(i.postgres)Rn(n,"postgres",i.postgres);if(i.mysql)Rn(n,"mysql",i.mysql);if(i.dynamodb?.tables)i.dynamodb.tables.forEach((s)=>{qr(n,s)})}function Rn(n,i,s){if(!s)return;let o=i==="postgres"?"postgres":"mysql",c=n.toLogicalId(`${o}-db`);n.addResource("DBSubnetGroup","AWS::RDS::DBSubnetGroup",{DBSubnetGroupDescription:"Subnet group for RDS instance",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-db-subnet-group")}]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]}),n.addResource("DBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for RDS instance",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:i==="postgres"?5432:3306,ToPort:i==="postgres"?5432:3306,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-db-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});let u=i==="postgres"?`postgres${s.version.split(".")[0]}`:`mysql${s.version.split(".")[0]}.${s.version.split(".")[1]||"0"}`;if(s.parameters&&Object.keys(s.parameters).length>0)n.addResource("DBParameterGroup","AWS::RDS::DBParameterGroup",{Description:`Parameter group for ${o}`,Family:u,Parameters:s.parameters,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-db-params")}]});n.addResource("DBSecret","AWS::SecretsManager::Secret",{Description:"Database credentials",GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"admin"}),GenerateStringKey:"password",PasswordLength:32,ExcludeCharacters:'"@/\\'},Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-db-secret")}]},{deletionPolicy:"Retain",updateReplacePolicy:"Retain"});let d={Engine:o,EngineVersion:s.version,DBInstanceClass:s.instanceClass,AllocatedStorage:s.allocatedStorage.toString(),MaxAllocatedStorage:s.maxAllocatedStorage?.toString(),StorageType:"gp3",StorageEncrypted:!0,MultiAZ:s.multiAZ!==!1,DBSubnetGroupName:e.ref("DBSubnetGroup"),VPCSecurityGroups:[e.ref("DBSecurityGroup")],MasterUsername:e.sub("{{resolve:secretsmanager:${DBSecret}:SecretString:username}}"),MasterUserPassword:e.sub("{{resolve:secretsmanager:${DBSecret}:SecretString:password}}"),BackupRetentionPeriod:s.backupRetentionDays||7,PreferredBackupWindow:s.preferredBackupWindow||"03:00-04:00",PreferredMaintenanceWindow:s.preferredMaintenanceWindow||"sun:04:00-sun:05:00",EnablePerformanceInsights:s.enablePerformanceInsights!==!1,PerformanceInsightsRetentionPeriod:s.performanceInsightsRetention||7,DeletionProtection:s.deletionProtection!==!1,CopyTagsToSnapshot:!0,EnableCloudwatchLogsExports:i==="postgres"?["postgresql"]:["error","general","slowquery"],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${o}-db`)}]};if(s.parameters&&Object.keys(s.parameters).length>0)d.DBParameterGroupName=e.ref("DBParameterGroup");n.addResource(c,"AWS::RDS::DBInstance",d,{dependsOn:["DBSubnetGroup","DBSecurityGroup","DBSecret"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),n.addResource("DBSecretAttachment","AWS::SecretsManager::SecretTargetAttachment",{SecretId:e.ref("DBSecret"),TargetId:e.ref(c),TargetType:"AWS::RDS::DBInstance"},{dependsOn:[c,"DBSecret"]}),n.addOutputs({DBEndpoint:{Description:"Database endpoint",Value:e.getAtt(c,"Endpoint.Address"),Export:{Name:e.sub("${AWS::StackName}-db-endpoint")}},DBPort:{Description:"Database port",Value:e.getAtt(c,"Endpoint.Port"),Export:{Name:e.sub("${AWS::StackName}-db-port")}},DBSecretArn:{Description:"ARN of the database credentials secret",Value:e.ref("DBSecret"),Export:{Name:e.sub("${AWS::StackName}-db-secret-arn")}}})}function qr(n,i){let s=n.toLogicalId(`${i.name}-table`),o={TableName:e.sub(`\${AWS::StackName}-${i.name}`),BillingMode:i.billingMode||"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:i.partitionKey,AttributeType:"S"}],KeySchema:[{AttributeName:i.partitionKey,KeyType:"HASH"}],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i.name}`)}]};if(i.sortKey)o.AttributeDefinitions.push({AttributeName:i.sortKey,AttributeType:"S"}),o.KeySchema.push({AttributeName:i.sortKey,KeyType:"RANGE"});if(i.billingMode==="PROVISIONED")o.ProvisionedThroughput={ReadCapacityUnits:i.readCapacity||5,WriteCapacityUnits:i.writeCapacity||5};if(i.streamEnabled)o.StreamSpecification={StreamViewType:"NEW_AND_OLD_IMAGES"};if(i.pointInTimeRecovery)o.PointInTimeRecoverySpecification={PointInTimeRecoveryEnabled:!0};if(i.ttl?.enabled)o.TimeToLiveSpecification={Enabled:!0,AttributeName:i.ttl.attributeName};if(i.globalSecondaryIndexes&&i.globalSecondaryIndexes.length>0)o.GlobalSecondaryIndexes=i.globalSecondaryIndexes.map((c)=>{let u=new Set(o.AttributeDefinitions.map((g)=>g.AttributeName));if(!u.has(c.partitionKey))o.AttributeDefinitions.push({AttributeName:c.partitionKey,AttributeType:"S"});if(c.sortKey&&!u.has(c.sortKey))o.AttributeDefinitions.push({AttributeName:c.sortKey,AttributeType:"S"});let d={IndexName:c.name,KeySchema:[{AttributeName:c.partitionKey,KeyType:"HASH"}],Projection:{ProjectionType:c.projectionType||"ALL"}};if(c.sortKey)d.KeySchema.push({AttributeName:c.sortKey,KeyType:"RANGE"});if(c.projectionType==="INCLUDE"&&c.nonKeyAttributes)d.Projection.NonKeyAttributes=c.nonKeyAttributes;if(i.billingMode==="PROVISIONED")d.ProvisionedThroughput={ReadCapacityUnits:i.readCapacity||5,WriteCapacityUnits:i.writeCapacity||5};return d});if(n.addResource(s,"AWS::DynamoDB::Table",o,{deletionPolicy:"Retain"}),n.addOutputs({[`${s}Name`]:{Description:`${i.name} table name`,Value:e.ref(s),Export:{Name:e.sub(`\${AWS::StackName}-${i.name}-table`)}},[`${s}Arn`]:{Description:`${i.name} table ARN`,Value:e.getAtt(s,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${i.name}-table-arn`)}}}),i.streamEnabled)n.addOutputs({[`${s}StreamArn`]:{Description:`${i.name} stream ARN`,Value:e.getAtt(s,"StreamArn"),Export:{Name:e.sub(`\${AWS::StackName}-${i.name}-stream-arn`)}}})}function En(n,i){for(let[s,o]of Object.entries(i))o.forEach((c)=>{zr(n,c,s)})}function zr(n,i,s){let o=n.toLogicalId(`${s}-${i.name}-function`),c=`${o}Role`;n.addResource(c,"AWS::IAM::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","arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"],Policies:[{PolicyName:"LambdaExecutionPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[...Jr(i.events||[])]}}],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i.name}-role`)}]});let u={FunctionName:e.sub(`\${AWS::StackName}-${i.name}`),Runtime:i.runtime,Handler:i.handler,Role:e.getAtt(c,"Arn"),MemorySize:i.memory,Timeout:i.timeout,Code:{ZipFile:`exports.handler = async (event) => {
2448
+ `;if(n.addResource("LaunchTemplate","AWS::EC2::LaunchTemplate",{LaunchTemplateName:e.sub("${AWS::StackName}-template"),LaunchTemplateData:{ImageId:i.ami||e.findInMap("RegionMap",e.ref("AWS::Region"),"AMI"),InstanceType:i.instanceType,IamInstanceProfile:{Arn:e.getAtt("EC2InstanceProfile","Arn")},SecurityGroupIds:[e.ref("AppSecurityGroup")],UserData:e.base64(e.sub(s)),TagSpecifications:[{ResourceType:"instance",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-instance")}]}],MetadataOptions:{HttpTokens:"required",HttpPutResponseHopLimit:1}}},{dependsOn:["AppSecurityGroup","EC2InstanceProfile"]}),i.loadBalancer){ai(n,i.loadBalancer);let o={LaunchTemplate:{LaunchTemplateId:e.ref("LaunchTemplate"),Version:e.getAtt("LaunchTemplate","LatestVersionNumber")},MinSize:i.autoScaling?.min.toString()||"1",MaxSize:i.autoScaling?.max.toString()||"3",DesiredCapacity:i.autoScaling?.min.toString()||"2",VPCZoneIdentifier:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],TargetGroupARNs:[e.ref("TargetGroup")],HealthCheckType:"ELB",HealthCheckGracePeriod:300,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-asg"),PropagateAtLaunch:!0}]};if(n.addResource("AutoScalingGroup","AWS::AutoScaling::AutoScalingGroup",o,{dependsOn:["LaunchTemplate","TargetGroup"]}),i.autoScaling)n.addResource("ScaleUpPolicy","AWS::AutoScaling::ScalingPolicy",{AdjustmentType:"ChangeInCapacity",AutoScalingGroupName:e.ref("AutoScalingGroup"),Cooldown:i.autoScaling.scaleUpCooldown?.toString()||"300",ScalingAdjustment:"1"},{dependsOn:"AutoScalingGroup"}),n.addResource("ScaleDownPolicy","AWS::AutoScaling::ScalingPolicy",{AdjustmentType:"ChangeInCapacity",AutoScalingGroupName:e.ref("AutoScalingGroup"),Cooldown:i.autoScaling.scaleDownCooldown?.toString()||"300",ScalingAdjustment:"-1"},{dependsOn:"AutoScalingGroup"}),n.addResource("HighCPUAlarm","AWS::CloudWatch::Alarm",{AlarmDescription:"Scale up when CPU exceeds target",MetricName:"CPUUtilization",Namespace:"AWS/EC2",Statistic:"Average",Period:"300",EvaluationPeriods:"2",Threshold:(i.autoScaling.targetCPU||70).toString(),AlarmActions:[e.ref("ScaleUpPolicy")],Dimensions:[{Name:"AutoScalingGroupName",Value:e.ref("AutoScalingGroup")}],ComparisonOperator:"GreaterThanThreshold"},{dependsOn:["AutoScalingGroup","ScaleUpPolicy"]}),n.addResource("LowCPUAlarm","AWS::CloudWatch::Alarm",{AlarmDescription:"Scale down when CPU is below threshold",MetricName:"CPUUtilization",Namespace:"AWS/EC2",Statistic:"Average",Period:"300",EvaluationPeriods:"2",Threshold:((i.autoScaling.targetCPU||70)-20).toString(),AlarmActions:[e.ref("ScaleDownPolicy")],Dimensions:[{Name:"AutoScalingGroupName",Value:e.ref("AutoScalingGroup")}],ComparisonOperator:"LessThanThreshold"},{dependsOn:["AutoScalingGroup","ScaleDownPolicy"]})}}function ai(n,i){if(!i)return;n.addResource("ALBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for Application Load Balancer",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:80,ToPort:80,CidrIp:"0.0.0.0/0"},{IpProtocol:"tcp",FromPort:443,ToPort:443,CidrIp:"0.0.0.0/0"}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-alb-sg")}]},{dependsOn:"VPC"}),n.addResource("LoadBalancer","AWS::ElasticLoadBalancingV2::LoadBalancer",{Name:e.sub("${AWS::StackName}-alb"),Type:i.type||"application",Scheme:"internet-facing",IpAddressType:"ipv4",Subnets:[e.ref("PublicSubnet1"),e.ref("PublicSubnet2")],SecurityGroups:[e.ref("ALBSecurityGroup")],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-alb")}]},{dependsOn:["PublicSubnet1","PublicSubnet2","ALBSecurityGroup"]}),n.addResource("TargetGroup","AWS::ElasticLoadBalancingV2::TargetGroup",{Name:e.sub("${AWS::StackName}-tg"),Port:3000,Protocol:"HTTP",VpcId:e.ref("VPC"),HealthCheckEnabled:!0,HealthCheckPath:i.healthCheck?.path||"/health",HealthCheckProtocol:"HTTP",HealthCheckIntervalSeconds:i.healthCheck?.interval||30,HealthCheckTimeoutSeconds:i.healthCheck?.timeout||5,HealthyThresholdCount:i.healthCheck?.healthyThreshold||2,UnhealthyThresholdCount:i.healthCheck?.unhealthyThreshold||3,TargetType:"instance",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-tg")}]},{dependsOn:"VPC"}),n.addResource("LoadBalancerListener","AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:e.ref("LoadBalancer"),Port:80,Protocol:"HTTP",DefaultActions:[{Type:"forward",TargetGroupArn:e.ref("TargetGroup")}]},{dependsOn:["LoadBalancer","TargetGroup"]}),n.addOutputs({LoadBalancerDNS:{Description:"Load Balancer DNS Name",Value:e.getAtt("LoadBalancer","DNSName"),Export:{Name:e.sub("${AWS::StackName}-alb-dns")}}})}function In(n,i,s){let o=n.toLogicalId(i),c=s.taskDefinition.containerDefinitions?.[0],u=c?.name||c?.Name||i,d=c?.portMappings?.[0]?.containerPort||c?.PortMappings?.[0]?.ContainerPort||3000,g=(s.taskDefinition.containerDefinitions||[]).flatMap((v)=>(v.secrets||v.Secrets||[]).map((T)=>T.valueFrom||T.ValueFrom)).filter(Boolean);if(!n.hasResource("ECSCluster"))n.addResource("ECSCluster","AWS::ECS::Cluster",{ClusterName:e.sub("${AWS::StackName}-cluster"),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-cluster")}]});if(n.addResource(`${o}TaskExecutionRole`,"AWS::IAM::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"],...g.length?{Policies:[{PolicyName:"read-task-secrets",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameters"],Resource:g},{Effect:"Allow",Action:"kms:Decrypt",Resource:"*"}]}}]}:{}}),n.addResource(`${o}TaskRole`,"AWS::IAM::Role",{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"application-services",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes","sqs:SendMessage"],Resource:e.sub("arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:${AWS::StackName}-*")},{Effect:"Allow",Action:["ses:SendEmail","ses:SendRawEmail"],Resource:"*"}]}}]}),!n.hasResource("ALBSecurityGroup"))n.addResource("ALBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Public ingress for the application load balancer",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:80,ToPort:80,CidrIp:"0.0.0.0/0"},...s.loadBalancer?.customDomain?.certificateArn?[{IpProtocol:"tcp",FromPort:443,ToPort:443,CidrIp:"0.0.0.0/0"}]:[]],SecurityGroupEgress:[{IpProtocol:"tcp",FromPort:d,ToPort:d,CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-alb-sg")}]},{dependsOn:"VPC"});if(!n.hasResource("AppSecurityGroup"))n.addResource("AppSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Only the application load balancer may reach Fargate tasks",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:d,ToPort:d,SourceSecurityGroupId:e.ref("ALBSecurityGroup")}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-app-sg")}]},{dependsOn:["VPC","ALBSecurityGroup"]});let y=(s.taskDefinition.containerDefinitions||[{name:i,image:e.sub(`\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.amazonaws.com/${i}:latest`),portMappings:[{containerPort:3000}]}]).map((v)=>({Name:v.Name||v.name,Image:v.Image||v.image,Essential:v.Essential??v.essential??!0,PortMappings:(v.PortMappings||v.portMappings||[]).map((T)=>({ContainerPort:T.ContainerPort??T.containerPort,Protocol:T.Protocol||T.protocol||"tcp"})),Environment:Array.isArray(v.Environment||v.environment)?(v.Environment||v.environment).map((T)=>({Name:T.Name||T.name,Value:T.Value??T.value})):Object.entries(v.Environment||v.environment||{}).map(([T,R])=>({Name:T,Value:R})),Secrets:(v.Secrets||v.secrets||[]).map((T)=>({Name:T.Name||T.name,ValueFrom:T.ValueFrom||T.valueFrom})),HealthCheck:v.HealthCheck||v.healthCheck,Command:v.Command||v.command,EntryPoint:v.EntryPoint||v.entryPoint,LogConfiguration:v.LogConfiguration||v.logConfiguration||{LogDriver:"awslogs",Options:{"awslogs-group":e.ref(`${o}LogGroup`),"awslogs-region":e.ref("AWS::Region"),"awslogs-stream-prefix":i}}}));n.addResource(`${o}TaskDefinition`,"AWS::ECS::TaskDefinition",{Family:e.sub(`\${AWS::StackName}-${i}`),NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:s.taskDefinition.cpu,Memory:s.taskDefinition.memory,ExecutionRoleArn:e.getAtt(`${o}TaskExecutionRole`,"Arn"),TaskRoleArn:e.getAtt(`${o}TaskRole`,"Arn"),ContainerDefinitions:y},{dependsOn:[`${o}TaskExecutionRole`,`${o}TaskRole`,`${o}LogGroup`]}),n.addResource(`${o}LogGroup`,"AWS::Logs::LogGroup",{LogGroupName:e.sub(`/ecs/\${AWS::StackName}/${i}`),RetentionInDays:14});let h=s.service.healthCheck||{};n.addResource(`${o}TargetGroup`,"AWS::ElasticLoadBalancingV2::TargetGroup",{VpcId:e.ref("VPC"),Port:d,Protocol:"HTTP",TargetType:"ip",HealthCheckEnabled:!0,HealthCheckPath:h.path||"/health",HealthCheckProtocol:"HTTP",HealthCheckIntervalSeconds:h.interval||30,HealthCheckTimeoutSeconds:h.timeout||5,HealthyThresholdCount:h.healthyThreshold||2,UnhealthyThresholdCount:h.unhealthyThreshold||3,Matcher:{HttpCode:"200-399"},TargetGroupAttributes:[{Key:"deregistration_delay.timeout_seconds",Value:"30"}]},{dependsOn:"VPC"}),n.addResource(`${o}LoadBalancer`,"AWS::ElasticLoadBalancingV2::LoadBalancer",{Type:"application",Scheme:"internet-facing",IpAddressType:"ipv4",Subnets:[e.ref("PublicSubnet1"),e.ref("PublicSubnet2")],SecurityGroups:[e.ref("ALBSecurityGroup")],LoadBalancerAttributes:[{Key:"routing.http.drop_invalid_header_fields.enabled",Value:"true"},{Key:"deletion_protection.enabled",Value:String(s.loadBalancer?.deletionProtection===!0)}],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}-alb`)}]},{dependsOn:["PublicSubnet1","PublicSubnet2","ALBSecurityGroup"]});let A=s.loadBalancer?.customDomain?.certificateArn,C=s.loadBalancer?.originVerifyHeader;if(n.addResource(`${o}HttpListener`,"AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:e.ref(`${o}LoadBalancer`),Port:80,Protocol:"HTTP",DefaultActions:A?[{Type:"redirect",RedirectConfig:{Protocol:"HTTPS",Port:"443",StatusCode:"HTTP_301"}}]:C?[{Type:"fixed-response",FixedResponseConfig:{StatusCode:"403",ContentType:"text/plain",MessageBody:"Forbidden"}}]:[{Type:"forward",TargetGroupArn:e.ref(`${o}TargetGroup`)}]},{dependsOn:[`${o}LoadBalancer`,`${o}TargetGroup`]}),A)n.addResource(`${o}HttpsListener`,"AWS::ElasticLoadBalancingV2::Listener",{LoadBalancerArn:e.ref(`${o}LoadBalancer`),Port:443,Protocol:"HTTPS",Certificates:[{CertificateArn:A}],SslPolicy:"ELBSecurityPolicy-TLS13-1-2-2021-06",DefaultActions:C?[{Type:"fixed-response",FixedResponseConfig:{StatusCode:"403",ContentType:"text/plain",MessageBody:"Forbidden"}}]:[{Type:"forward",TargetGroupArn:e.ref(`${o}TargetGroup`)}]},{dependsOn:[`${o}LoadBalancer`,`${o}TargetGroup`]});if(C){let v=A?`${o}HttpsListener`:`${o}HttpListener`;n.addResource(`${o}OriginVerifyRule`,"AWS::ElasticLoadBalancingV2::ListenerRule",{ListenerArn:e.ref(v),Priority:1,Conditions:[{Field:"http-header",HttpHeaderConfig:{HttpHeaderName:C.name,Values:[C.value]}}],Actions:[{Type:"forward",TargetGroupArn:e.ref(`${o}TargetGroup`)}]},{dependsOn:[v,`${o}TargetGroup`]})}if(n.addResource(`${o}Service`,"AWS::ECS::Service",{ServiceName:e.sub(`\${AWS::StackName}-${i}`),Cluster:e.ref("ECSCluster"),TaskDefinition:e.ref(`${o}TaskDefinition`),DesiredCount:s.service.desiredCount,LaunchType:"FARGATE",PlatformVersion:"LATEST",HealthCheckGracePeriodSeconds:60,DeploymentConfiguration:{MinimumHealthyPercent:100,MaximumPercent:200,DeploymentCircuitBreaker:{Enable:!0,Rollback:!0}},LoadBalancers:[{ContainerName:u,ContainerPort:d,TargetGroupArn:e.ref(`${o}TargetGroup`)}],NetworkConfiguration:{AwsvpcConfiguration:{AssignPublicIp:"DISABLED",Subnets:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],SecurityGroups:[e.ref("AppSecurityGroup")]}}},{dependsOn:["ECSCluster",`${o}TaskDefinition`,C?`${o}OriginVerifyRule`:A?`${o}HttpsListener`:`${o}HttpListener`]}),s.service.autoScaling){let v=s.service.autoScaling;n.addResource(`${o}ScalableTarget`,"AWS::ApplicationAutoScaling::ScalableTarget",{MinCapacity:v.min,MaxCapacity:v.max,ResourceId:e.join("/",["service",e.ref("ECSCluster"),e.getAtt(`${o}Service`,"Name")]),RoleARN:e.sub("arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService"),ScalableDimension:"ecs:service:DesiredCount",ServiceNamespace:"ecs"},{dependsOn:`${o}Service`}),n.addResource(`${o}ScalingPolicy`,"AWS::ApplicationAutoScaling::ScalingPolicy",{PolicyType:"TargetTrackingScaling",ScalingTargetId:e.ref(`${o}ScalableTarget`),TargetTrackingScalingPolicyConfiguration:{TargetValue:v.targetCPU||70,PredefinedMetricSpecification:{PredefinedMetricType:"ECSServiceAverageCPUUtilization"},ScaleInCooldown:60,ScaleOutCooldown:30}},{dependsOn:`${o}ScalableTarget`})}n.addOutputs({[`${o}ClusterName`]:{Description:"ECS cluster name",Value:e.ref("ECSCluster")},[`${o}ServiceName`]:{Description:"ECS service name",Value:e.getAtt(`${o}Service`,"Name")},[`${o}LoadBalancerDnsName`]:{Description:"ALB origin hostname",Value:e.getAtt(`${o}LoadBalancer`,"DNSName")},[`${o}LoadBalancerHostedZoneId`]:{Description:"ALB canonical hosted zone ID",Value:e.getAtt(`${o}LoadBalancer`,"CanonicalHostedZoneID")},[`${o}TargetGroupArn`]:{Description:"ECS target group ARN",Value:e.ref(`${o}TargetGroup`)}})}function xn(n,i){if(i.postgres)Nn(n,"postgres",i.postgres);if(i.mysql)Nn(n,"mysql",i.mysql);if(i.dynamodb?.tables)i.dynamodb.tables.forEach((s)=>{oi(n,s)})}function Nn(n,i,s){if(!s)return;let o=i==="postgres"?"postgres":"mysql",c=n.toLogicalId(`${o}-db`);n.addResource("DBSubnetGroup","AWS::RDS::DBSubnetGroup",{DBSubnetGroupDescription:"Subnet group for RDS instance",SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-db-subnet-group")}]},{dependsOn:["PrivateSubnet1","PrivateSubnet2"]}),n.addResource("DBSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for RDS instance",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:i==="postgres"?5432:3306,ToPort:i==="postgres"?5432:3306,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-db-sg")}]},{dependsOn:["VPC","AppSecurityGroup"]});let u=i==="postgres"?`postgres${s.version.split(".")[0]}`:`mysql${s.version.split(".")[0]}.${s.version.split(".")[1]||"0"}`;if(s.parameters&&Object.keys(s.parameters).length>0)n.addResource("DBParameterGroup","AWS::RDS::DBParameterGroup",{Description:`Parameter group for ${o}`,Family:u,Parameters:s.parameters,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-db-params")}]});n.addResource("DBSecret","AWS::SecretsManager::Secret",{Description:"Database credentials",GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"admin"}),GenerateStringKey:"password",PasswordLength:32,ExcludeCharacters:'"@/\\'},Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-db-secret")}]},{deletionPolicy:"Retain",updateReplacePolicy:"Retain"});let d={Engine:o,EngineVersion:s.version,DBInstanceClass:s.instanceClass,AllocatedStorage:s.allocatedStorage.toString(),MaxAllocatedStorage:s.maxAllocatedStorage?.toString(),StorageType:"gp3",StorageEncrypted:!0,MultiAZ:s.multiAZ!==!1,DBSubnetGroupName:e.ref("DBSubnetGroup"),VPCSecurityGroups:[e.ref("DBSecurityGroup")],MasterUsername:e.sub("{{resolve:secretsmanager:${DBSecret}:SecretString:username}}"),MasterUserPassword:e.sub("{{resolve:secretsmanager:${DBSecret}:SecretString:password}}"),BackupRetentionPeriod:s.backupRetentionDays||7,PreferredBackupWindow:s.preferredBackupWindow||"03:00-04:00",PreferredMaintenanceWindow:s.preferredMaintenanceWindow||"sun:04:00-sun:05:00",EnablePerformanceInsights:s.enablePerformanceInsights!==!1,PerformanceInsightsRetentionPeriod:s.performanceInsightsRetention||7,DeletionProtection:s.deletionProtection!==!1,CopyTagsToSnapshot:!0,EnableCloudwatchLogsExports:i==="postgres"?["postgresql"]:["error","general","slowquery"],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${o}-db`)}]};if(s.parameters&&Object.keys(s.parameters).length>0)d.DBParameterGroupName=e.ref("DBParameterGroup");n.addResource(c,"AWS::RDS::DBInstance",d,{dependsOn:["DBSubnetGroup","DBSecurityGroup","DBSecret"],deletionPolicy:"Snapshot",updateReplacePolicy:"Snapshot"}),n.addResource("DBSecretAttachment","AWS::SecretsManager::SecretTargetAttachment",{SecretId:e.ref("DBSecret"),TargetId:e.ref(c),TargetType:"AWS::RDS::DBInstance"},{dependsOn:[c,"DBSecret"]}),n.addOutputs({DBEndpoint:{Description:"Database endpoint",Value:e.getAtt(c,"Endpoint.Address"),Export:{Name:e.sub("${AWS::StackName}-db-endpoint")}},DBPort:{Description:"Database port",Value:e.getAtt(c,"Endpoint.Port"),Export:{Name:e.sub("${AWS::StackName}-db-port")}},DBSecretArn:{Description:"ARN of the database credentials secret",Value:e.ref("DBSecret"),Export:{Name:e.sub("${AWS::StackName}-db-secret-arn")}}})}function oi(n,i){let s=n.toLogicalId(`${i.name}-table`),o={TableName:e.sub(`\${AWS::StackName}-${i.name}`),BillingMode:i.billingMode||"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:i.partitionKey,AttributeType:"S"}],KeySchema:[{AttributeName:i.partitionKey,KeyType:"HASH"}],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i.name}`)}]};if(i.sortKey)o.AttributeDefinitions.push({AttributeName:i.sortKey,AttributeType:"S"}),o.KeySchema.push({AttributeName:i.sortKey,KeyType:"RANGE"});if(i.billingMode==="PROVISIONED")o.ProvisionedThroughput={ReadCapacityUnits:i.readCapacity||5,WriteCapacityUnits:i.writeCapacity||5};if(i.streamEnabled)o.StreamSpecification={StreamViewType:"NEW_AND_OLD_IMAGES"};if(i.pointInTimeRecovery)o.PointInTimeRecoverySpecification={PointInTimeRecoveryEnabled:!0};if(i.ttl?.enabled)o.TimeToLiveSpecification={Enabled:!0,AttributeName:i.ttl.attributeName};if(i.globalSecondaryIndexes&&i.globalSecondaryIndexes.length>0)o.GlobalSecondaryIndexes=i.globalSecondaryIndexes.map((c)=>{let u=new Set(o.AttributeDefinitions.map((g)=>g.AttributeName));if(!u.has(c.partitionKey))o.AttributeDefinitions.push({AttributeName:c.partitionKey,AttributeType:"S"});if(c.sortKey&&!u.has(c.sortKey))o.AttributeDefinitions.push({AttributeName:c.sortKey,AttributeType:"S"});let d={IndexName:c.name,KeySchema:[{AttributeName:c.partitionKey,KeyType:"HASH"}],Projection:{ProjectionType:c.projectionType||"ALL"}};if(c.sortKey)d.KeySchema.push({AttributeName:c.sortKey,KeyType:"RANGE"});if(c.projectionType==="INCLUDE"&&c.nonKeyAttributes)d.Projection.NonKeyAttributes=c.nonKeyAttributes;if(i.billingMode==="PROVISIONED")d.ProvisionedThroughput={ReadCapacityUnits:i.readCapacity||5,WriteCapacityUnits:i.writeCapacity||5};return d});if(n.addResource(s,"AWS::DynamoDB::Table",o,{deletionPolicy:"Retain"}),n.addOutputs({[`${s}Name`]:{Description:`${i.name} table name`,Value:e.ref(s),Export:{Name:e.sub(`\${AWS::StackName}-${i.name}-table`)}},[`${s}Arn`]:{Description:`${i.name} table ARN`,Value:e.getAtt(s,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${i.name}-table-arn`)}}}),i.streamEnabled)n.addOutputs({[`${s}StreamArn`]:{Description:`${i.name} stream ARN`,Value:e.getAtt(s,"StreamArn"),Export:{Name:e.sub(`\${AWS::StackName}-${i.name}-stream-arn`)}}})}function kn(n,i){for(let[s,o]of Object.entries(i))o.forEach((c)=>{ci(n,c,s)})}function ci(n,i,s){let o=n.toLogicalId(`${s}-${i.name}-function`),c=`${o}Role`;n.addResource(c,"AWS::IAM::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","arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"],Policies:[{PolicyName:"LambdaExecutionPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[...ui(i.events||[])]}}],Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i.name}-role`)}]});let u={FunctionName:e.sub(`\${AWS::StackName}-${i.name}`),Runtime:i.runtime,Handler:i.handler,Role:e.getAtt(c,"Arn"),MemorySize:i.memory,Timeout:i.timeout,Code:{ZipFile:`exports.handler = async (event) => {
2449
2449
  console.log('Event:', JSON.stringify(event, null, 2));
2450
2450
  return { statusCode: 200, body: 'Function not yet implemented' };
2451
- };`},Environment:i.environment?{Variables:i.environment}:void 0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i.name}`)}]};if(s!=="edge")u.VpcConfig={SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],SecurityGroupIds:[e.ref("AppSecurityGroup")]};if(n.addResource(o,"AWS::Lambda::Function",u,{dependsOn:c}),n.addResource(`${o}LogGroup`,"AWS::Logs::LogGroup",{LogGroupName:e.sub(`/aws/lambda/\${AWS::StackName}-${i.name}`),RetentionInDays:14}),i.events)i.events.forEach((d,g)=>{Qr(n,o,d,g)});n.addOutputs({[`${o}Arn`]:{Description:`${i.name} function ARN`,Value:e.getAtt(o,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${i.name}-function-arn`)}}})}function Qr(n,i,s,o){let c=`${i}EventSource${o}`;switch(s.type){case"http":break;case"s3":if(s.bucket){let u=n.toLogicalId(`${s.bucket}-bucket`);n.addResource(`${c}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(i),Action:"lambda:InvokeFunction",Principal:"s3.amazonaws.com",SourceArn:gn.s3Bucket(e.ref(u))},{dependsOn:[i,u]})}break;case"sqs":if(s.queueName){let u=n.toLogicalId(`${s.queueName}-queue`);n.addResource(c,"AWS::Lambda::EventSourceMapping",{EventSourceArn:e.getAtt(u,"Arn"),FunctionName:e.ref(i),BatchSize:s.batchSize||10},{dependsOn:[i,u]})}break;case"kinesis":if(s.streamName){let u=n.toLogicalId(`${s.streamName}-stream`);n.addResource(c,"AWS::Lambda::EventSourceMapping",{EventSourceArn:e.getAtt(u,"Arn"),FunctionName:e.ref(i),BatchSize:s.batchSize||100,StartingPosition:s.startingPosition||"LATEST",ParallelizationFactor:s.parallelizationFactor||1},{dependsOn:[i,u]})}break;case"dynamodb-stream":if(s.tableName){let u=n.toLogicalId(`${s.tableName}-table`);n.addResource(c,"AWS::Lambda::EventSourceMapping",{EventSourceArn:e.getAtt(u,"StreamArn"),FunctionName:e.ref(i),BatchSize:s.batchSize||100,StartingPosition:s.startingPosition||"LATEST"},{dependsOn:[i,u]})}break;case"schedule":if(s.expression)n.addResource(`${c}Rule`,"AWS::Events::Rule",{ScheduleExpression:s.expression,State:"ENABLED",Targets:[{Arn:e.getAtt(i,"Arn"),Id:`${i}Target`}]},{dependsOn:i}),n.addResource(`${c}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(i),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.getAtt(`${c}Rule`,"Arn")},{dependsOn:[i,`${c}Rule`]});break}}function Jr(n){let i=[];if(!n)return i;if(n.forEach((s)=>{switch(s.type){case"s3":i.push({Effect:"Allow",Action:["s3:GetObject","s3:GetObjectVersion"],Resource:s.bucket?`arn:aws:s3:::${s.bucket}/*`:"arn:aws:s3:::*/*"});break;case"sqs":i.push({Effect:"Allow",Action:["sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes"],Resource:s.queueName?gn.sqs(s.queueName):"arn:aws:sqs:*:*:*"});break;case"kinesis":i.push({Effect:"Allow",Action:["kinesis:GetRecords","kinesis:GetShardIterator","kinesis:DescribeStream","kinesis:ListStreams"],Resource:s.streamName?gn.kinesis(s.streamName):"arn:aws:kinesis:*:*:stream/*"});break;case"dynamodb-stream":i.push({Effect:"Allow",Action:["dynamodb:GetRecords","dynamodb:GetShardIterator","dynamodb:DescribeStream","dynamodb:ListStreams"],Resource:s.tableName?e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${s.tableName}/stream/*`):"arn:aws:dynamodb:*:*:table/*/stream/*"});break}}),i.length===0)i.push({Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:"arn:aws:logs:*:*:*"});return i}function wn(n,i){if(i.topics)i.topics.forEach((s)=>{Yr(n,s)})}function Yr(n,i){let s=n.toLogicalId(`${i.name}-topic`);if(n.addResource(s,"AWS::SNS::Topic",{TopicName:e.sub(`\${AWS::StackName}-${i.name}`),DisplayName:i.displayName||i.name,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i.name}`)}]}),n.addResource(`${s}Policy`,"AWS::SNS::TopicPolicy",{Topics:[e.ref(s)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["events.amazonaws.com","cloudwatch.amazonaws.com","s3.amazonaws.com"]},Action:"sns:Publish",Resource:e.ref(s)},{Effect:"Allow",Principal:{AWS:e.sub("arn:aws:iam::${AWS::AccountId}:root")},Action:["sns:Subscribe","sns:Publish","sns:Receive"],Resource:e.ref(s)}]}},{dependsOn:s}),i.subscriptions)i.subscriptions.forEach((o,c)=>{let u=`${s}Subscription${c+1}`,d={Protocol:o.protocol,TopicArn:e.ref(s),Endpoint:o.endpoint};if(o.filterPolicy)d.FilterPolicy=o.filterPolicy;if(o.protocol==="sqs"){let g=n.toLogicalId(`${o.endpoint}-queue`);d.Endpoint=e.getAtt(g,"Arn")}if(o.protocol==="lambda"){let g=n.toLogicalId(o.endpoint);d.Endpoint=e.getAtt(g,"Arn"),n.addResource(`${u}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(g),Action:"lambda:InvokeFunction",Principal:"sns.amazonaws.com",SourceArn:e.ref(s)},{dependsOn:[g,s]})}n.addResource(u,"AWS::SNS::Subscription",d,{dependsOn:s})});n.addOutputs({[`${s}Arn`]:{Description:`${i.name} topic ARN`,Value:e.ref(s),Export:{Name:e.sub(`\${AWS::StackName}-${i.name}-topic-arn`)}}})}function In(n,i){if(i.alarms&&i.alarms.length>0)n.addResource("AlarmTopic","AWS::SNS::Topic",{TopicName:e.sub("${AWS::StackName}-alarms"),DisplayName:"CloudWatch Alarms",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-alarms")}]}),i.alarms.forEach((s,o)=>{Zr(n,s,o)});if(i.dashboard)Xr(n,i.dashboard);if(i.logs?.groups)i.logs.groups.forEach((s)=>{ei(n,s,i.logs?.retention)})}function Zr(n,i,s){let o=n.toLogicalId(`alarm-${i.name||i.metric}-${s}`),c={AlarmName:i.name||e.sub(`\${AWS::StackName}-${i.metric}`),AlarmDescription:`Alarm for ${i.metric}`,MetricName:i.metric,Namespace:i.namespace||Pt(i.metric,i.service),Statistic:i.statistic||"Average",Period:i.period||300,EvaluationPeriods:i.evaluationPeriods||1,Threshold:i.threshold,ComparisonOperator:i.comparisonOperator||"GreaterThanThreshold",TreatMissingData:i.treatMissingData||"notBreaching",AlarmActions:[e.ref("AlarmTopic")],OKActions:[e.ref("AlarmTopic")]};if(i.dimensions)c.Dimensions=Object.entries(i.dimensions).map(([u,d])=>({Name:u,Value:d}));else if(i.service)c.Dimensions=ti(i.service);n.addResource(o,"AWS::CloudWatch::Alarm",c,{dependsOn:"AlarmTopic"})}function Xr(n,i){if(!i)return;let s=[],o=0,c=0;i.widgets?.forEach((u)=>{let d=u.width||12,g=u.height||6;if(u.type==="metric"&&u.metrics){let y=u.metrics.map((h)=>{if(typeof h==="string")return[Pt(h),h];else return[Pt(h.metric,h.service),h.metric]});s.push({type:"metric",x:o,y:c,width:d,height:g,properties:{metrics:y,period:300,stat:"Average",region:e.ref("AWS::Region"),title:u.metrics.length>1?"Multiple Metrics":typeof u.metrics[0]==="string"?u.metrics[0]:u.metrics[0].metric}})}else if(u.type==="log"&&u.logGroup)s.push({type:"log",x:o,y:c,width:d,height:g,properties:{query:`SOURCE '${u.logGroup}'
2451
+ };`},Environment:i.environment?{Variables:i.environment}:void 0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i.name}`)}]};if(s!=="edge")u.VpcConfig={SubnetIds:[e.ref("PrivateSubnet1"),e.ref("PrivateSubnet2")],SecurityGroupIds:[e.ref("AppSecurityGroup")]};if(n.addResource(o,"AWS::Lambda::Function",u,{dependsOn:c}),n.addResource(`${o}LogGroup`,"AWS::Logs::LogGroup",{LogGroupName:e.sub(`/aws/lambda/\${AWS::StackName}-${i.name}`),RetentionInDays:14}),i.events)i.events.forEach((d,g)=>{li(n,o,d,g)});n.addOutputs({[`${o}Arn`]:{Description:`${i.name} function ARN`,Value:e.getAtt(o,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${i.name}-function-arn`)}}})}function li(n,i,s,o){let c=`${i}EventSource${o}`;switch(s.type){case"http":break;case"s3":if(s.bucket){let u=n.toLogicalId(`${s.bucket}-bucket`);n.addResource(`${c}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(i),Action:"lambda:InvokeFunction",Principal:"s3.amazonaws.com",SourceArn:pn.s3Bucket(e.ref(u))},{dependsOn:[i,u]})}break;case"sqs":if(s.queueName){let u=n.toLogicalId(`${s.queueName}-queue`);n.addResource(c,"AWS::Lambda::EventSourceMapping",{EventSourceArn:e.getAtt(u,"Arn"),FunctionName:e.ref(i),BatchSize:s.batchSize||10},{dependsOn:[i,u]})}break;case"kinesis":if(s.streamName){let u=n.toLogicalId(`${s.streamName}-stream`);n.addResource(c,"AWS::Lambda::EventSourceMapping",{EventSourceArn:e.getAtt(u,"Arn"),FunctionName:e.ref(i),BatchSize:s.batchSize||100,StartingPosition:s.startingPosition||"LATEST",ParallelizationFactor:s.parallelizationFactor||1},{dependsOn:[i,u]})}break;case"dynamodb-stream":if(s.tableName){let u=n.toLogicalId(`${s.tableName}-table`);n.addResource(c,"AWS::Lambda::EventSourceMapping",{EventSourceArn:e.getAtt(u,"StreamArn"),FunctionName:e.ref(i),BatchSize:s.batchSize||100,StartingPosition:s.startingPosition||"LATEST"},{dependsOn:[i,u]})}break;case"schedule":if(s.expression)n.addResource(`${c}Rule`,"AWS::Events::Rule",{ScheduleExpression:s.expression,State:"ENABLED",Targets:[{Arn:e.getAtt(i,"Arn"),Id:`${i}Target`}]},{dependsOn:i}),n.addResource(`${c}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(i),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.getAtt(`${c}Rule`,"Arn")},{dependsOn:[i,`${c}Rule`]});break}}function ui(n){let i=[];if(!n)return i;if(n.forEach((s)=>{switch(s.type){case"s3":i.push({Effect:"Allow",Action:["s3:GetObject","s3:GetObjectVersion"],Resource:s.bucket?`arn:aws:s3:::${s.bucket}/*`:"arn:aws:s3:::*/*"});break;case"sqs":i.push({Effect:"Allow",Action:["sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes"],Resource:s.queueName?pn.sqs(s.queueName):"arn:aws:sqs:*:*:*"});break;case"kinesis":i.push({Effect:"Allow",Action:["kinesis:GetRecords","kinesis:GetShardIterator","kinesis:DescribeStream","kinesis:ListStreams"],Resource:s.streamName?pn.kinesis(s.streamName):"arn:aws:kinesis:*:*:stream/*"});break;case"dynamodb-stream":i.push({Effect:"Allow",Action:["dynamodb:GetRecords","dynamodb:GetShardIterator","dynamodb:DescribeStream","dynamodb:ListStreams"],Resource:s.tableName?e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${s.tableName}/stream/*`):"arn:aws:dynamodb:*:*:table/*/stream/*"});break}}),i.length===0)i.push({Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:"arn:aws:logs:*:*:*"});return i}function Mn(n,i){if(i.topics)i.topics.forEach((s)=>{di(n,s)})}function di(n,i){let s=n.toLogicalId(`${i.name}-topic`);if(n.addResource(s,"AWS::SNS::Topic",{TopicName:e.sub(`\${AWS::StackName}-${i.name}`),DisplayName:i.displayName||i.name,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i.name}`)}]}),n.addResource(`${s}Policy`,"AWS::SNS::TopicPolicy",{Topics:[e.ref(s)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["events.amazonaws.com","cloudwatch.amazonaws.com","s3.amazonaws.com"]},Action:"sns:Publish",Resource:e.ref(s)},{Effect:"Allow",Principal:{AWS:e.sub("arn:aws:iam::${AWS::AccountId}:root")},Action:["sns:Subscribe","sns:Publish","sns:Receive"],Resource:e.ref(s)}]}},{dependsOn:s}),i.subscriptions)i.subscriptions.forEach((o,c)=>{let u=`${s}Subscription${c+1}`,d={Protocol:o.protocol,TopicArn:e.ref(s),Endpoint:o.endpoint};if(o.filterPolicy)d.FilterPolicy=o.filterPolicy;if(o.protocol==="sqs"){let g=n.toLogicalId(`${o.endpoint}-queue`);d.Endpoint=e.getAtt(g,"Arn")}if(o.protocol==="lambda"){let g=n.toLogicalId(o.endpoint);d.Endpoint=e.getAtt(g,"Arn"),n.addResource(`${u}Permission`,"AWS::Lambda::Permission",{FunctionName:e.ref(g),Action:"lambda:InvokeFunction",Principal:"sns.amazonaws.com",SourceArn:e.ref(s)},{dependsOn:[g,s]})}n.addResource(u,"AWS::SNS::Subscription",d,{dependsOn:s})});n.addOutputs({[`${s}Arn`]:{Description:`${i.name} topic ARN`,Value:e.ref(s),Export:{Name:e.sub(`\${AWS::StackName}-${i.name}-topic-arn`)}}})}function Ln(n,i){if(i.alarms&&i.alarms.length>0)n.addResource("AlarmTopic","AWS::SNS::Topic",{TopicName:e.sub("${AWS::StackName}-alarms"),DisplayName:"CloudWatch Alarms",Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-alarms")}]}),i.alarms.forEach((s,o)=>{mi(n,s,o)});if(i.dashboard)pi(n,i.dashboard);if(i.logs?.groups)i.logs.groups.forEach((s)=>{gi(n,s,i.logs?.retention)})}function mi(n,i,s){let o=n.toLogicalId(`alarm-${i.name||i.metric}-${s}`),c={AlarmName:i.name||e.sub(`\${AWS::StackName}-${i.metric}`),AlarmDescription:`Alarm for ${i.metric}`,MetricName:i.metric,Namespace:i.namespace||wt(i.metric,i.service),Statistic:i.statistic||"Average",Period:i.period||300,EvaluationPeriods:i.evaluationPeriods||1,Threshold:i.threshold,ComparisonOperator:i.comparisonOperator||"GreaterThanThreshold",TreatMissingData:i.treatMissingData||"notBreaching",AlarmActions:[e.ref("AlarmTopic")],OKActions:[e.ref("AlarmTopic")]};if(i.dimensions)c.Dimensions=Object.entries(i.dimensions).map(([u,d])=>({Name:u,Value:d}));else if(i.service)c.Dimensions=yi(i.service);n.addResource(o,"AWS::CloudWatch::Alarm",c,{dependsOn:"AlarmTopic"})}function pi(n,i){if(!i)return;let s=[],o=0,c=0;i.widgets?.forEach((u)=>{let d=u.width||12,g=u.height||6;if(u.type==="metric"&&u.metrics){let y=u.metrics.map((h)=>{if(typeof h==="string")return[wt(h),h];else return[wt(h.metric,h.service),h.metric]});s.push({type:"metric",x:o,y:c,width:d,height:g,properties:{metrics:y,period:300,stat:"Average",region:e.ref("AWS::Region"),title:u.metrics.length>1?"Multiple Metrics":typeof u.metrics[0]==="string"?u.metrics[0]:u.metrics[0].metric}})}else if(u.type==="log"&&u.logGroup)s.push({type:"log",x:o,y:c,width:d,height:g,properties:{query:`SOURCE '${u.logGroup}'
2452
2452
  | fields @timestamp, @message
2453
2453
  | sort @timestamp desc
2454
- | limit 20`,region:e.ref("AWS::Region"),title:`Logs: ${u.logGroup}`}});else if(u.type==="text"&&u.text)s.push({type:"text",x:o,y:c,width:d,height:g,properties:{markdown:u.text}});if(o+=d,o>=24)o=0,c+=g}),n.addResource("CloudWatchDashboard","AWS::CloudWatch::Dashboard",{DashboardName:e.sub(`\${AWS::StackName}-${i.name}`),DashboardBody:JSON.stringify({widgets:s})}),n.addOutputs({DashboardURL:{Description:"CloudWatch Dashboard URL",Value:e.sub("https://console.aws.amazon.com/cloudwatch/home?region=${AWS::Region}#dashboards:name=${CloudWatchDashboard}")}})}function ei(n,i,s){let o=n.toLogicalId(`${i}-log-group`);n.addResource(o,"AWS::Logs::LogGroup",{LogGroupName:e.sub(`/aws/\${AWS::StackName}/${i}`),RetentionInDays:s||14,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}`)}]})}function Pt(n,i){if(i)return{ec2:"AWS/EC2",ecs:"AWS/ECS",lambda:"AWS/Lambda",rds:"AWS/RDS",dynamodb:"AWS/DynamoDB",s3:"AWS/S3",cloudfront:"AWS/CloudFront",alb:"AWS/ApplicationELB",nlb:"AWS/NetworkELB",apigateway:"AWS/ApiGateway",sqs:"AWS/SQS",sns:"AWS/SNS",kinesis:"AWS/Kinesis",elasticache:"AWS/ElastiCache"}[i.toLowerCase()]||"AWS/CloudWatch";let s=n.toLowerCase();if(s.includes("cpu")||s.includes("memory")||s.includes("network"))return"AWS/EC2";if(s.includes("lambda")||s.includes("invocation")||s.includes("duration"))return"AWS/Lambda";if(s.includes("request")||s.includes("latency")||s.includes("target"))return"AWS/ApplicationELB";if(s.includes("database")||s.includes("connection"))return"AWS/RDS";if(s.includes("read")||s.includes("write")||s.includes("consumed"))return"AWS/DynamoDB";return"AWS/CloudWatch"}function ti(n){return{ec2:[{Name:"InstanceId",Value:e.ref("EC2Instance")}],ecs:[{Name:"ClusterName",Value:e.ref("ECSCluster")},{Name:"ServiceName",Value:e.getAtt("ECSService","Name")}],lambda:[{Name:"FunctionName",Value:e.ref("LambdaFunction")}],rds:[{Name:"DBInstanceIdentifier",Value:e.ref("Database")}],dynamodb:[{Name:"TableName",Value:e.ref("DynamoDBTable")}],alb:[{Name:"LoadBalancer",Value:e.getAtt("LoadBalancer","LoadBalancerFullName")}],apigateway:[{Name:"ApiName",Value:e.ref("HttpApi")}]}[n.toLowerCase()]||[]}function Dn(n,i){if(!i.vpc)return;let{cidr:s="10.0.0.0/16",availabilityZones:o=2,natGateways:c=1,enableDnsHostnames:u=!0,enableDnsSupport:d=!0}=i.vpc;n.addResource("VPC","AWS::EC2::VPC",{CidrBlock:s,EnableDnsHostnames:u,EnableDnsSupport:d,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-vpc")}]}),n.addResource("InternetGateway","AWS::EC2::InternetGateway",{Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-igw")}]}),n.addResource("VPCGatewayAttachment","AWS::EC2::VPCGatewayAttachment",{VpcId:e.ref("VPC"),InternetGatewayId:e.ref("InternetGateway")},{dependsOn:["VPC","InternetGateway"]});let g=[];for(let C=0;C<o;C++){let v=`PublicSubnet${C+1}`;g.push(v),n.addResource(v,"AWS::EC2::Subnet",{VpcId:e.ref("VPC"),CidrBlock:e.select(C,e.cidr(e.getAtt("VPC","CidrBlock"),o*2,8)),AvailabilityZone:e.select(C,e.getAZs()),MapPublicIpOnLaunch:!0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-public-${C+1}`)},{Key:"Type",Value:"public"}]},{dependsOn:"VPC"})}let y=[];for(let C=0;C<o;C++){let v=`PrivateSubnet${C+1}`;y.push(v),n.addResource(v,"AWS::EC2::Subnet",{VpcId:e.ref("VPC"),CidrBlock:e.select(C+o,e.cidr(e.getAtt("VPC","CidrBlock"),o*2,8)),AvailabilityZone:e.select(C,e.getAZs()),MapPublicIpOnLaunch:!1,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-private-${C+1}`)},{Key:"Type",Value:"private"}]},{dependsOn:"VPC"})}let h=[];for(let C=0;C<c;C++){let v=`NatEIP${C+1}`;h.push(v),n.addResource(v,"AWS::EC2::EIP",{Domain:"vpc",Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-nat-eip-${C+1}`)}]},{dependsOn:"VPCGatewayAttachment"})}let A=[];for(let C=0;C<c;C++){let v=`NatGateway${C+1}`;A.push(v);let T=C%o;n.addResource(v,"AWS::EC2::NatGateway",{AllocationId:e.getAtt(h[C],"AllocationId"),SubnetId:e.ref(g[T]),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-nat-${C+1}`)}]},{dependsOn:[h[C],g[T]]})}n.addResource("PublicRouteTable","AWS::EC2::RouteTable",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-public-rt")}]},{dependsOn:"VPC"}),n.addResource("PublicRoute","AWS::EC2::Route",{RouteTableId:e.ref("PublicRouteTable"),DestinationCidrBlock:"0.0.0.0/0",GatewayId:e.ref("InternetGateway")},{dependsOn:["PublicRouteTable","VPCGatewayAttachment"]}),g.forEach((C,v)=>{n.addResource(`PublicSubnetRouteTableAssociation${v+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:e.ref(C),RouteTableId:e.ref("PublicRouteTable")},{dependsOn:[C,"PublicRouteTable"]})}),y.forEach((C,v)=>{let T=`PrivateRouteTable${v+1}`,R=v%c;n.addResource(T,"AWS::EC2::RouteTable",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-private-rt-${v+1}`)}]},{dependsOn:"VPC"}),n.addResource(`PrivateRoute${v+1}`,"AWS::EC2::Route",{RouteTableId:e.ref(T),DestinationCidrBlock:"0.0.0.0/0",NatGatewayId:e.ref(A[R])},{dependsOn:[T,A[R]]}),n.addResource(`PrivateSubnetRouteTableAssociation${v+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:e.ref(C),RouteTableId:e.ref(T)},{dependsOn:[C,T]})}),n.addResource("S3VPCEndpoint","AWS::EC2::VPCEndpoint",{VpcId:e.ref("VPC"),ServiceName:e.sub("com.amazonaws.${AWS::Region}.s3"),VpcEndpointType:"Gateway",RouteTableIds:[e.ref("PublicRouteTable"),...Array.from({length:o},(C,v)=>e.ref(`PrivateRouteTable${v+1}`))]},{dependsOn:"VPC"}),n.addResource("NetworkAcl","AWS::EC2::NetworkAcl",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-nacl")}]},{dependsOn:"VPC"}),n.addResource("NetworkAclEntryInbound","AWS::EC2::NetworkAclEntry",{NetworkAclId:e.ref("NetworkAcl"),RuleNumber:100,Protocol:-1,RuleAction:"allow",CidrBlock:"0.0.0.0/0"},{dependsOn:"NetworkAcl"}),n.addResource("NetworkAclEntryOutbound","AWS::EC2::NetworkAclEntry",{NetworkAclId:e.ref("NetworkAcl"),RuleNumber:100,Protocol:-1,Egress:!0,RuleAction:"allow",CidrBlock:"0.0.0.0/0"},{dependsOn:"NetworkAcl"}),n.addOutputs({VPCId:{Description:"VPC ID",Value:e.ref("VPC"),Export:{Name:e.sub("${AWS::StackName}-VPC")}},PublicSubnets:{Description:"Public subnet IDs",Value:e.join(",",g.map((C)=>e.ref(C))),Export:{Name:e.sub("${AWS::StackName}-PublicSubnets")}},PrivateSubnets:{Description:"Private subnet IDs",Value:e.join(",",y.map((C)=>e.ref(C))),Export:{Name:e.sub("${AWS::StackName}-PrivateSubnets")}}})}function Nn(n,i){for(let[s,o]of Object.entries(i))ni(n,s,o)}function ni(n,i,s){let o=n.toLogicalId(`${i}-queue`),c=s.fifo||!1,u;if(s.deadLetterQueue){let g=`${o}DLQ`;n.addResource(g,"AWS::SQS::Queue",{QueueName:c?e.sub(`\${AWS::StackName}-${i}-dlq.fifo`):e.sub(`\${AWS::StackName}-${i}-dlq`),FifoQueue:c,MessageRetentionPeriod:1209600,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}-dlq`)}]},{deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),u=e.getAtt(g,"Arn")}let d={QueueName:c?e.sub(`\${AWS::StackName}-${i}.fifo`):e.sub(`\${AWS::StackName}-${i}`),FifoQueue:c,VisibilityTimeout:s.visibilityTimeout||30,MessageRetentionPeriod:s.messageRetentionPeriod||345600,ReceiveMessageWaitTimeSeconds:s.receiveMessageWaitTime||0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}`)}]};if(c&&s.contentBasedDeduplication)d.ContentBasedDeduplication=!0;if(s.deadLetterQueue&&u)d.RedrivePolicy={deadLetterTargetArn:u,maxReceiveCount:s.maxReceiveCount||3};if(n.addResource(o,"AWS::SQS::Queue",d,{dependsOn:s.deadLetterQueue?`${o}DLQ`:void 0,deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),n.addResource(`${o}Policy`,"AWS::SQS::QueuePolicy",{Queues:[e.ref(o)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["lambda.amazonaws.com","events.amazonaws.com","sns.amazonaws.com"]},Action:"sqs:SendMessage",Resource:e.getAtt(o,"Arn"),Condition:{ArnEquals:{"aws:SourceArn":e.sub("arn:aws:*:${AWS::Region}:${AWS::AccountId}:*")}}}]}},{dependsOn:o}),n.addOutputs({[`${o}Url`]:{Description:`${i} queue URL`,Value:e.ref(o),Export:{Name:e.sub(`\${AWS::StackName}-${i}-queue-url`)}},[`${o}Arn`]:{Description:`${i} queue ARN`,Value:e.getAtt(o,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${i}-queue-arn`)}}}),s.deadLetterQueue)n.addOutputs({[`${o}DLQUrl`]:{Description:`${i} dead letter queue URL`,Value:e.ref(`${o}DLQ`),Export:{Name:e.sub(`\${AWS::StackName}-${i}-dlq-url`)}}})}function xn(n,i){if(i.certificate)ri(n,i.certificate);if(i.waf?.enabled)ii(n,i.waf);if(i.securityGroups)for(let[s,o]of Object.entries(i.securityGroups))si(n,s,o)}function ri(n,i){if(!i)return;let s=[i.domain];if(i.subdomains)s.push(...i.subdomains);n.addResource("Certificate","AWS::CertificateManager::Certificate",{DomainName:i.domain,SubjectAlternativeNames:i.subdomains,ValidationMethod:i.validationMethod||"DNS",DomainValidationOptions:s.map((o)=>({DomainName:o,HostedZoneId:e.ref("HostedZone")})),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-certificate")}]}),n.addOutputs({CertificateArn:{Description:"ACM Certificate ARN",Value:e.ref("Certificate"),Export:{Name:e.sub("${AWS::StackName}-certificate-arn")}}})}function ii(n,i){if(!i)return;let s=[],o=i.rules||["rateLimit","sqlInjection","xss"];if(o.includes("rateLimit"))s.push({Name:"RateLimitRule",Priority:1,Statement:{RateBasedStatement:{Limit:i.rateLimit||2000,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"RateLimitRule"}});let c=s.length+1;if(o.includes("sqlInjection"))s.push({Name:"AWSManagedRulesSQLi",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesSQLiRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesSQLi"}});if(o.includes("xss"))s.push({Name:"AWSManagedRulesXSS",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesXSS"}});if(o.includes("knownBadInputs"))s.push({Name:"AWSManagedRulesKnownBadInputs",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesKnownBadInputs"}});if(o.includes("coreRuleSet"))s.push({Name:"AWSManagedRulesCoreRuleSet",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesCommonRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesCoreRuleSet"}});if(o.includes("linuxRuleSet"))s.push({Name:"AWSManagedRulesLinuxRuleSet",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesLinuxRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesLinuxRuleSet"}});if(o.includes("apiProtection"))s.push({Name:"AWSManagedRulesAPIProtection",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesAmazonIpReputationList"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesAPIProtection"}});if(o.includes("geoBlock"))s.push({Name:"GeoBlockRule",Priority:c++,Statement:{GeoMatchStatement:{CountryCodes:["CN","RU"]}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"GeoBlockRule"}});if(o.includes("connectionLimit"))s.push({Name:"ConnectionLimitRule",Priority:c++,Statement:{RateBasedStatement:{Limit:100,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"ConnectionLimitRule"}});if(n.addResource("WebACL","AWS::WAFv2::WebACL",{Name:e.sub("${AWS::StackName}-waf"),Scope:i.scope||"REGIONAL",DefaultAction:{Allow:{}},Rules:s,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:e.sub("${AWS::StackName}-waf")},Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-waf")}]}),n.hasResource("LoadBalancer"))n.addResource("WebACLAssociation","AWS::WAFv2::WebACLAssociation",{ResourceArn:e.ref("LoadBalancer"),WebACLArn:e.getAtt("WebACL","Arn")},{dependsOn:["WebACL","LoadBalancer"]});n.addOutputs({WebACLId:{Description:"WAF Web ACL ID",Value:e.ref("WebACL"),Export:{Name:e.sub("${AWS::StackName}-waf-id")}},WebACLArn:{Description:"WAF Web ACL ARN",Value:e.getAtt("WebACL","Arn"),Export:{Name:e.sub("${AWS::StackName}-waf-arn")}}})}function si(n,i,s){if(!s)return;let o=n.toLogicalId(`${i}-security-group`),c=s.ingress?.map((d)=>({IpProtocol:d.protocol,FromPort:d.port,ToPort:d.port,CidrIp:d.cidr,SourceSecurityGroupId:d.source?e.ref(d.source):void 0}))||[],u=s.egress?.map((d)=>({IpProtocol:d.protocol,FromPort:d.port,ToPort:d.port,CidrIp:d.cidr||"0.0.0.0/0"}))||[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}];n.addResource(o,"AWS::EC2::SecurityGroup",{GroupDescription:`Security group for ${i}`,VpcId:e.ref("VPC"),SecurityGroupIngress:c,SecurityGroupEgress:u,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}-sg`)}]},{dependsOn:"VPC"}),n.addOutputs({[`${o}Id`]:{Description:`${i} security group ID`,Value:e.ref(o),Export:{Name:e.sub(`\${AWS::StackName}-${i}-sg-id`)}}})}function kn(n,i){for(let[s,o]of Object.entries(i)){if(o.type==="efs"){oi(n,s,o);continue}ai(n,s,o)}}function ai(n,i,s){let o=n.toLogicalId(`${i}-bucket`),c={BucketName:e.sub(`\${AWS::StackName}-${i}`),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}`)}]};if(s.versioning)c.VersioningConfiguration={Status:"Enabled"};if(s.encryption)c.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(!s.public)c.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(s.website)c.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"index.html"};if(s.cors&&s.cors.length>0)c.CorsConfiguration={CorsRules:s.cors.map((u)=>({AllowedOrigins:u.allowedOrigins,AllowedMethods:u.allowedMethods,AllowedHeaders:u.allowedHeaders||["*"],MaxAge:u.maxAge||3600}))};if(s.lifecycleRules&&s.lifecycleRules.length>0)c.LifecycleConfiguration={Rules:s.lifecycleRules.map((u)=>({Id:u.id,Status:u.enabled?"Enabled":"Disabled",ExpirationInDays:u.expirationDays,Transitions:u.transitions?.map((d)=>({TransitionInDays:d.days,StorageClass:d.storageClass}))}))};if(s.intelligentTiering)c.IntelligentTieringConfigurations=[{Id:"EntireBucket",Status:"Enabled",Tierings:[{AccessTier:"ARCHIVE_ACCESS",Days:90},{AccessTier:"DEEP_ARCHIVE_ACCESS",Days:180}]}];if(n.addResource(o,"AWS::S3::Bucket",c,{deletionPolicy:s.versioning?"Retain":"Delete"}),s.public)n.addResource(`${o}Policy`,"AWS::S3::BucketPolicy",{Bucket:e.ref(o),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:"s3:GetObject",Resource:e.join("",[gn.s3Bucket(e.ref(o)),"/*"])}]}},{dependsOn:o});if(n.addOutputs({[`${o}Name`]:{Description:`${i} bucket name`,Value:e.ref(o),Export:{Name:e.sub(`\${AWS::StackName}-${i}-bucket`)}},[`${o}Arn`]:{Description:`${i} bucket ARN`,Value:e.getAtt(o,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${i}-bucket-arn`)}}}),s.website)n.addOutputs({[`${o}WebsiteURL`]:{Description:`${i} website URL`,Value:e.getAtt(o,"WebsiteURL")}})}function oi(n,i,s){let o=n.toLogicalId(`${i}-efs`),c={Encrypted:s.encryption!==!1,PerformanceMode:s.performanceMode||"generalPurpose",ThroughputMode:s.throughputMode||"bursting",FileSystemTags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}`)}]};if(s.lifecyclePolicy){if(c.LifecyclePolicies=[],s.lifecyclePolicy.transitionToIA)c.LifecyclePolicies.push({TransitionToIA:`AFTER_${s.lifecyclePolicy.transitionToIA}_DAYS`});if(s.lifecyclePolicy.transitionToPrimaryStorageClass)c.LifecyclePolicies.push({TransitionToPrimaryStorageClass:"AFTER_1_ACCESS"})}n.addResource(o,"AWS::EFS::FileSystem",c,{deletionPolicy:"Retain"});let u=2;for(let d=0;d<u;d++)n.addResource(`${o}MountTarget${d+1}`,"AWS::EFS::MountTarget",{FileSystemId:e.ref(o),SubnetId:e.ref(`PrivateSubnet${d+1}`),SecurityGroups:[e.ref("EFSSecurityGroup")]},{dependsOn:[o,`PrivateSubnet${d+1}`]});n.addResource("EFSSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for EFS mount targets",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:2049,ToPort:2049,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-efs-sg")}]},{dependsOn:"VPC"}),n.addOutputs({[`${o}Id`]:{Description:`${i} EFS file system ID`,Value:e.ref(o),Export:{Name:e.sub(`\${AWS::StackName}-${i}-efs`)}}})}class xm{template;config;resourceDependencies;constructor(n){this.config=n,this.resourceDependencies=new Map,this.template={AWSTemplateFormatVersion:"2010-09-09",Description:`Infrastructure for ${n.project.name} (${n.project.slug})`,Resources:{}}}build(){return this.addParameters(),this.addMappings(),this.addConditions(),this.addResources(),this.initializeOutputs(),this.resolveDependencies(),this.template}addParameters(){this.template.Parameters={Environment:{Type:"String",Default:"production",AllowedValues:["development","staging","production"],Description:"Environment name"}}}addMappings(){this.template.Mappings={RegionMap:{"us-east-1":{AMI:"ami-0f3caa1cf4417e51b"},"us-west-2":{AMI:"ami-0d1cd67c26f5fca19"},"eu-west-1":{AMI:"ami-0bbc25e23a7640b9b"}}}}addConditions(){this.template.Conditions={IsProduction:e.equals(e.ref("Environment"),"production"),HasDomain:e.not([e.equals(this.config.environments?.production?.domain||"","")])}}addResources(){let{infrastructure:n}=this.config;if(!n)return;if(n.network)this.addNetworkResources(n.network);if(n.storage)this.addStorageResources(n.storage);if(n.compute)this.addComputeResources(n.compute);if(n.databases)this.addDatabaseResources(n.databases);if(n.cache)this.addCacheResources(n.cache);if(n.cdn)this.addCDNResources(n.cdn);if(n.apiGateway)this.addApiGatewayResources(n.apiGateway);if(n.functions)this.addFunctionResources(n.functions);if(n.queues)this.addQueueResources(n.queues);if(n.messaging)this.addMessagingResources(n.messaging);if(n.monitoring)this.addMonitoringResources(n.monitoring);if(n.security)this.addSecurityResources(n.security)}initializeOutputs(){let n=this.template.Outputs||{};if(this.template.Outputs={StackName:{Description:"Stack name",Value:e.ref("AWS::StackName"),Export:{Name:e.sub("${AWS::StackName}-Name")}},Region:{Description:"AWS Region",Value:e.ref("AWS::Region"),Export:{Name:e.sub("${AWS::StackName}-Region")}},...n},this.config.environments?.production?.domain)this.template.Outputs.Domain={Description:"Production domain",Value:this.config.environments.production.domain,Condition:"HasDomain"}}addResource(n,i,s,o){let c={Type:i,Properties:s};if(o?.dependsOn)c.DependsOn=o.dependsOn,this.trackDependency(n,o.dependsOn);if(o?.condition)c.Condition=o.condition;if(o?.deletionPolicy)c.DeletionPolicy=o.deletionPolicy;if(o?.updateReplacePolicy)c.UpdateReplacePolicy=o.updateReplacePolicy;this.template.Resources[n]=c}addOutputs(n){this.template.Outputs={...this.template.Outputs,...n}}getOutputs(){return this.template.Outputs||{}}hasResource(n){return n in this.template.Resources}getResource(n){return this.template.Resources[n]}trackDependency(n,i){if(!this.resourceDependencies.has(n))this.resourceDependencies.set(n,new Set);(Array.isArray(i)?i:[i]).forEach((o)=>this.resourceDependencies.get(n).add(o))}resolveDependencies(){let n=new Set,i=new Set,s=(o)=>{if(i.has(o))throw Error(`Circular dependency detected involving resource: ${o}`);if(n.has(o))return!0;n.add(o),i.add(o);let c=this.resourceDependencies.get(o);if(c)for(let u of c)s(u);return i.delete(o),!0};for(let o of this.resourceDependencies.keys())s(o)}toLogicalId(n){return n.split(/[-_\s]/).map((i)=>i.charAt(0).toUpperCase()+i.slice(1).toLowerCase()).join("")}addNetworkResources(n){Dn(this,n)}addStorageResources(n){kn(this,n)}addComputeResources(n){Tn(this,n)}addDatabaseResources(n){Pn(this,n)}addFunctionResources(n){En(this,n)}addCacheResources(n){Sn(this,n)}addQueueResources(n){Nn(this,n)}addMessagingResources(n){wn(this,n)}addCDNResources(n){Cn(this,n)}addApiGatewayResources(n){bn(this,n)}addMonitoringResources(n){In(this,n)}addSecurityResources(n){xn(this,n)}}function fl(n){return new xm(n).build()}function YI(n){let{name:i,slug:s,domain:o,subdomain:c}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:c&&o?`${c}.${o}`:o}},infrastructure:{storage:{assets:{public:!0,versioning:!1,website:!0,encryption:!1,cors:[{allowedOrigins:["*"],allowedMethods:["GET","HEAD"],allowedHeaders:["*"],maxAge:3600}]}},cdn:{enabled:!0,customDomain:o?{domain:c&&o?`${c}.${o}`:o,certificateArn:"TO_BE_GENERATED"}:void 0,cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0,errorPages:{404:"/index.html",403:"/index.html"}}}}}function ZI(n){let{name:i,slug:s,domain:o,instanceType:c="t3.small",minInstances:u=2,maxInstances:d=10}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",keyPair:`${s}-key`,autoScaling:{min:u,max:d,desired:u,targetCPU:70},loadBalancer:{type:"application",healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3}},userData:{packages:["nodejs","npm","nginx"],commands:["curl -fsSL https://bun.sh/install | bash","npm install -g pm2"]}}},databases:{postgres:{engine:"postgres",version:"15",instanceClass:"db.t3.micro",allocatedStorage:20,multiAZ:!0,backupRetentionDays:7,deletionProtection:!0}},cache:{redis:{nodeType:"cache.t3.micro",numCacheNodes:1,engine:"redis",engineVersion:"7.0"}},security:{certificate:o?{domain:o,subdomains:[`*.${o}`],validationMethod:"DNS"}:void 0}}}}function eb(n){let{name:i,slug:s,domain:o,taskCpu:c="256",taskMemory:u="512",desiredCount:d=2}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:0}},compute:{fargate:{taskDefinition:{cpu:c,memory:u,containerDefinitions:[{name:"app",image:`${s}-app:latest`,portMappings:[{containerPort:3000}],environment:[],secrets:[]}]},service:{desiredCount:d,healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3},autoScaling:{min:d,max:d*5,targetCPU:70,targetMemory:80}},loadBalancer:{type:"application"}}},databases:{dynamodb:{tables:{[`${s}-main`]:{partitionKey:{name:"id",type:"S"},sortKey:{name:"createdAt",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0}}}},functions:{"process-queue":{runtime:"nodejs20.x",handler:"dist/workers/queue.handler",memory:512,timeout:60,events:[{type:"sqs",queueName:`${s}-queue`}]}},security:{certificate:o?{domain:o,subdomains:[`*.${o}`],validationMethod:"DNS"}:void 0}}}}function tb(n){let{name:i,slug:s,entry:o,domain:c,runtime:u="nodejs20.x",memory:d=1024,build:g,deploy:y,assets:h,queues:A=!0,scheduler:C="on",region:v="us-east-1"}=n;return{project:{name:i,slug:s,region:v},mode:"serverless",environments:{production:{type:"production",domain:c,app:{kind:"node",runtime:u,entry:o,memory:d,build:g,deploy:y,assets:h,queues:A,scheduler:C,domain:c}}}}}function hl(n){let i=n.database!==!1,s=n.cache!==!1,o=n.queue!==!1;return{project:{name:n.name,slug:n.slug,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:n.domain}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{fargate:{taskDefinition:{cpu:"256",memory:"512",containerDefinitions:[{name:"api",image:n.imageUri,portMappings:[{containerPort:3000}],environment:[{name:"NODE_ENV",value:"production"},{name:"PORT",value:"3000"},{name:"AWS_REGION",value:e.ref("AWS::Region")},...i?[{name:"DB_HOST",value:e.getAtt("PostgresDb","Endpoint.Address")},{name:"DB_PORT",value:e.getAtt("PostgresDb","Endpoint.Port")}]:[],...s?[{name:"REDIS_HOST",value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Address")},{name:"REDIS_PORT",value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Port")},{name:"REDIS_TLS",value:"true"}]:[],...o?[{name:"QUEUE_URL",value:e.ref("JobsQueue")}]:[],{name:"MAIL_TRANSPORT",value:"ses"}],secrets:i?[{name:"DB_USERNAME",valueFrom:e.sub("${DBSecret}:username::")},{name:"DB_PASSWORD",valueFrom:e.sub("${DBSecret}:password::")}]:[]}]},service:{desiredCount:n.desiredCount||1,healthCheck:{path:"/api/health",interval:30,timeout:5},autoScaling:{min:n.desiredCount||1,max:6,targetCPU:70}},loadBalancer:{type:"application",...n.certificateArn?{customDomain:{domain:n.domain,certificateArn:n.certificateArn}}:{},...n.originVerifySecret?{originVerifyHeader:{name:"X-Origin-Verify",value:n.originVerifySecret}}:{}}}},...i?{databases:{postgres:{engine:"postgres",version:"16",instanceClass:"db.t4g.micro",allocatedStorage:20,maxAllocatedStorage:100,multiAZ:!1,backupRetentionDays:7,deletionProtection:!0}}}:{},...s?{cache:{redis:{nodeType:"cache.t4g.micro",numCacheNodes:2,engine:"redis",engineVersion:"7.1",automaticFailoverEnabled:!0,snapshotRetentionLimit:5}}}:{},...o?{queues:{jobs:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0,maxReceiveCount:3,receiveMessageWaitTime:20}}}:{}}}}function rb(n){let{name:i,slug:s,domain:o,apiSubdomain:c="api"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},storage:{frontend:{public:!0,versioning:!0,website:!0,encryption:!1}},cdn:{enabled:!0,customDomain:{domain:o,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0,errorPages:{404:"/index.html"}},compute:{fargate:{taskDefinition:{cpu:"512",memory:"1024",containerDefinitions:[{name:"api",image:`${s}-api:latest`,portMappings:[{containerPort:3000}]}]},service:{desiredCount:2,healthCheck:{path:"/api/health",interval:30},autoScaling:{min:2,max:10,targetCPU:70}},loadBalancer:{type:"application",customDomain:{domain:`${c}.${o}`,certificateArn:"TO_BE_GENERATED"}}}},databases:{postgres:{engine:"postgres",version:"15",instanceClass:"db.t3.small",allocatedStorage:50,multiAZ:!0,backupRetentionDays:14,deletionProtection:!0}},cache:{redis:{nodeType:"cache.t3.small",numCacheNodes:2,engine:"redis",engineVersion:"7.0"}},queues:{jobs:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0}},security:{certificate:{domain:o,subdomains:[`*.${o}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss"]}}}}}function nb(n){let{name:i,slug:s,domain:o}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{apiGateway:{type:"HTTP",cors:{allowOrigins:["*"],allowMethods:["GET","POST","PUT","DELETE","PATCH"],allowHeaders:["Content-Type","Authorization"],maxAge:3600},customDomain:o?{domain:o,certificateArn:"TO_BE_GENERATED"}:void 0,throttling:{rateLimit:1e4,burstLimit:5000},authorizer:{type:"JWT",identitySource:"$request.header.Authorization"}},functions:{users:{runtime:"nodejs20.x",handler:"dist/api/users.handler",memory:512,timeout:30,events:[{type:"http",path:"/users",method:"GET"},{type:"http",path:"/users",method:"POST"}]},products:{runtime:"nodejs20.x",handler:"dist/api/products.handler",memory:512,timeout:30,events:[{type:"http",path:"/products",method:"GET"}]}},databases:{dynamodb:{tables:{[`${s}-users`]:{partitionKey:{name:"userId",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0,globalSecondaryIndexes:[{name:"EmailIndex",partitionKey:{name:"email",type:"S"},projection:"ALL"}]},[`${s}-products`]:{partitionKey:{name:"productId",type:"S"},sortKey:{name:"category",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!1}}}},cache:{elasticache:{nodeType:"cache.t3.micro",numCacheNodes:1,engine:"redis",engineVersion:"7.0"}},security:{certificate:o?{domain:o,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","sqlInjection"]}},monitoring:{alarms:[{metric:"Errors",threshold:10,period:300,evaluationPeriods:1},{metric:"Duration",threshold:3000,period:300,evaluationPeriods:2}]}}}}function ib(n){let{name:i,slug:s,domain:o,instanceType:c="t3.small"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",keyPair:`${s}-key`,autoScaling:{min:2,max:6,desired:2,targetCPU:75},loadBalancer:{type:"application",healthCheck:{path:"/wp-admin/install.php",interval:30}},userData:{packages:["nginx","php8.1-fpm","php8.1-mysql","php8.1-curl","php8.1-gd","php8.1-mbstring","php8.1-xml","php8.1-zip"],commands:["cd /var/www","wget https://wordpress.org/latest.tar.gz","tar -xzf latest.tar.gz","chown -R www-data:www-data wordpress","rm /etc/nginx/sites-enabled/default","systemctl restart nginx","systemctl restart php8.1-fpm"]}}},fileSystem:{uploads:{performanceMode:"generalPurpose",throughputMode:"bursting",encrypted:!0,lifecyclePolicy:{transitionToIA:30},mountPath:"/var/www/wordpress/wp-content/uploads"}},databases:{mysql:{engine:"mysql",version:"8.0",instanceClass:"db.t3.small",allocatedStorage:50,multiAZ:!0,backupRetentionDays:7,deletionProtection:!0,databaseName:"wordpress"}},cache:{redis:{nodeType:"cache.t3.micro",numCacheNodes:1,engine:"redis",engineVersion:"7.0"}},cdn:{enabled:!0,customDomain:{domain:o,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,origins:[{type:"alb",pathPattern:"/wp-content/*"}]},security:{certificate:{domain:o,subdomains:[`www.${o}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss","wordpressRules"]}}}}}function sb(n){let{name:i,slug:s,domain:o,apiDomain:c}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{storage:{static:{public:!0,versioning:!0,website:!0,encryption:!1,cors:[{allowedOrigins:["*"],allowedMethods:["GET","HEAD"]}],lifecycleRules:[{id:"DeleteOldVersions",enabled:!0,expirationDays:90}]}},cdn:{enabled:!0,customDomain:{domain:o,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:0,maxTTL:31536000},compress:!0,http3:!0,errorPages:{404:"/404.html",500:"/500.html"},edgeFunctions:[{eventType:"origin-request",functionArn:"TO_BE_CREATED",name:"ssr-handler"}]},functions:{ssr:{runtime:"nodejs20.x",handler:"dist/edge/ssr.handler",memory:512,timeout:5},...c?{api:{runtime:"nodejs20.x",handler:"dist/api/index.handler",memory:1024,timeout:30,events:[{type:"http",path:"/{proxy+}",method:"ANY"}]}}:{}},apiGateway:c?{type:"HTTP",customDomain:{domain:c,certificateArn:"TO_BE_GENERATED"},cors:{allowOrigins:[o],allowMethods:["GET","POST","PUT","DELETE"],allowHeaders:["Content-Type","Authorization"]}}:void 0,databases:{dynamodb:{tables:{content:{partitionKey:{name:"id",type:"S"},sortKey:{name:"type",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!1}}}},security:{certificate:{domain:o,subdomains:c?[c]:[],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","geoBlock"]}}}}}function ob(n){let{name:i,slug:s,domain:o,services:c}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:3,natGateways:2}},compute:{services:c.map((u)=>({name:u.name,type:"fargate",taskDefinition:{cpu:u.cpu||"256",memory:u.memory||"512",containerDefinitions:[{name:u.name,image:`${s}-${u.name}:latest`,portMappings:[{containerPort:u.port}],healthCheck:{command:["CMD-SHELL",`curl -f http://localhost:${u.port}/health || exit 1`],interval:30,timeout:5,retries:3}}]},service:{desiredCount:u.desiredCount||2,serviceDiscovery:{enabled:!0,namespace:`${s}.local`},autoScaling:{min:2,max:10,targetCPU:70}}}))},apiGateway:{type:"HTTP",customDomain:{domain:o,certificateArn:"TO_BE_GENERATED"},cors:{allowOrigins:["*"],allowMethods:["GET","POST","PUT","DELETE","PATCH"]},routes:c.map((u)=>({path:`/${u.name}/{proxy+}`,integration:{type:"vpc-link",service:u.name}}))},databases:{dynamodb:{tables:Object.fromEntries(c.map((u)=>[`${s}-${u.name}`,{partitionKey:{name:"id",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0}]))}},queues:{events:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0}},messaging:{topics:{events:{name:`${s}-events`,subscriptions:c.map((u)=>({protocol:"sqs",endpoint:`${s}-${u.name}-queue`,filterPolicy:{service:[u.name]}}))}}},monitoring:{dashboard:{name:`${s}-microservices`,widgets:c.map((u)=>({type:"metric",metrics:[{service:u.name,metric:"CPUUtilization"},{service:u.name,metric:"MemoryUtilization"},{service:u.name,metric:"RequestCount"}]}))},alarms:c.flatMap((u)=>[{name:`${u.name}-high-cpu`,metric:"CPUUtilization",threshold:80,service:u.name},{name:`${u.name}-errors`,metric:"Errors",threshold:10,service:u.name}])},security:{certificate:{domain:o,validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection"]}}}}}function ab(n){let{name:i,slug:s,domain:o}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{apiGateway:{type:"websocket",customDomain:o?{domain:o,certificateArn:"TO_BE_GENERATED"}:void 0,routes:[{path:"$connect",method:"WEBSOCKET",integration:"websocket-connect"},{path:"$disconnect",method:"WEBSOCKET",integration:"websocket-disconnect"},{path:"$default",method:"WEBSOCKET",integration:"websocket-default"},{path:"sendMessage",method:"WEBSOCKET",integration:"websocket-send-message"},{path:"joinRoom",method:"WEBSOCKET",integration:"websocket-join-room"}]},functions:{connect:{runtime:"nodejs20.x",handler:"dist/websocket/connect.handler",memory:512,timeout:30},disconnect:{runtime:"nodejs20.x",handler:"dist/websocket/disconnect.handler",memory:512,timeout:30},default:{runtime:"nodejs20.x",handler:"dist/websocket/default.handler",memory:512,timeout:30},"send-message":{runtime:"nodejs20.x",handler:"dist/websocket/sendMessage.handler",memory:512,timeout:30},"join-room":{runtime:"nodejs20.x",handler:"dist/websocket/joinRoom.handler",memory:512,timeout:30},broadcast:{runtime:"nodejs20.x",handler:"dist/streams/broadcast.handler",memory:1024,timeout:60,events:[{type:"dynamodb-stream",tableName:`${s}-messages`,startingPosition:"LATEST",batchSize:100}]}},databases:{dynamodb:{tables:{[`${s}-connections`]:{partitionKey:{name:"connectionId",type:"S"},billingMode:"PAY_PER_REQUEST",globalSecondaryIndexes:[{name:"RoomIndex",partitionKey:{name:"roomId",type:"S"},sortKey:{name:"connectionId",type:"S"},projection:"ALL"}]},[`${s}-messages`]:{partitionKey:{name:"roomId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0,globalSecondaryIndexes:[{name:"UserIndex",partitionKey:{name:"userId",type:"S"},sortKey:{name:"timestamp",type:"S"},projection:"ALL"}]},[`${s}-rooms`]:{partitionKey:{name:"roomId",type:"S"},billingMode:"PAY_PER_REQUEST"}}}},cache:{elasticache:{nodeType:"cache.t3.small",numCacheNodes:2,engine:"redis",engineVersion:"7.0"}},monitoring:{alarms:[{metric:"WebSocketConnections",threshold:1e4,evaluationPeriods:1},{metric:"IntegrationLatency",threshold:1000,evaluationPeriods:2}],dashboard:{name:`${s}-realtime`,widgets:[{type:"metric",metrics:["WebSocketConnections","MessagesSent","IntegrationLatency"]}]}},security:{certificate:o?{domain:o,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","connectionLimit"]}}}}}function cb(n){let{name:i,slug:s,retentionDays:o=7}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",infrastructure:{streaming:{dataStream:{name:`${s}-stream`,shardCount:2,retentionPeriod:o*24,encryption:!0}},storage:{raw:{public:!1,versioning:!0,encryption:!0,intelligentTiering:!0,lifecycleRules:[{id:"ArchiveOldData",enabled:!0,transitions:[{days:30,storageClass:"GLACIER"},{days:90,storageClass:"DEEP_ARCHIVE"}]}]},processed:{public:!1,versioning:!0,encryption:!0,intelligentTiering:!0}},functions:{"stream-processor":{runtime:"nodejs20.x",handler:"dist/processors/stream.handler",memory:2048,timeout:300,events:[{type:"kinesis",streamName:`${s}-stream`,batchSize:1000,startingPosition:"LATEST",parallelizationFactor:10}]},transformer:{runtime:"nodejs20.x",handler:"dist/processors/transform.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${s}-raw`,prefix:"incoming/"}]},aggregator:{runtime:"nodejs20.x",handler:"dist/processors/aggregate.handler",memory:2048,timeout:600,events:[{type:"schedule",expression:"cron(0 * * * ? *)"}]}},analytics:{athena:{database:`${s}_analytics`,workgroup:`${s}-workgroup`,outputBucket:`${s}-query-results`,tables:[{name:"raw_events",location:`s3://${s}-raw/events/`,format:"parquet",partitionKeys:["year","month","day"]},{name:"processed_events",location:`s3://${s}-processed/events/`,format:"parquet",partitionKeys:["year","month","day"]}]},glue:{crawlers:[{name:`${s}-crawler`,databaseName:`${s}_analytics`,s3Targets:[`s3://${s}-raw/`,`s3://${s}-processed/`],schedule:"cron(0 2 * * ? *)"}],jobs:[{name:`${s}-etl-job`,scriptLocation:`s3://${s}-scripts/etl.py`,role:`${s}-glue-role`,maxCapacity:10,timeout:120}]}},databases:{dynamodb:{tables:{[`${s}-metadata`]:{partitionKey:{name:"pipelineId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST"}}}},queues:{failedJobs:{fifo:!1,visibilityTimeout:900,messageRetentionPeriod:1209600,deadLetterQueue:!0,maxReceiveCount:3}},workflow:{pipelines:[{name:`${s}-daily-pipeline`,type:"stepFunctions",definition:{StartAt:"ExtractData",States:{ExtractData:{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Next:"TransformData"},TransformData:{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Next:"LoadData"},LoadData:{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",End:!0}}},schedule:"cron(0 0 * * ? *)"}]},monitoring:{dashboard:{name:`${s}-pipeline`,widgets:[{type:"metric",metrics:["KinesisIncomingRecords","LambdaInvocations","S3ObjectsCreated","GlueJobsSucceeded"]}]},alarms:[{metric:"LambdaErrors",threshold:10,evaluationPeriods:1},{metric:"KinesisIteratorAge",threshold:60000,evaluationPeriods:2}]}}}}function db(n){let{name:i,slug:s,domain:o,modelS3Path:c=`s3://${s}-models/`,instanceType:u="ml.t3.medium"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{storage:{models:{public:!1,versioning:!0,encryption:!0,intelligentTiering:!0},datasets:{public:!1,versioning:!0,encryption:!0,lifecycleRules:[{id:"ArchiveOldDatasets",enabled:!0,transitions:[{days:90,storageClass:"GLACIER"}]}]},predictions:{public:!1,versioning:!1,encryption:!0,lifecycleRules:[{id:"DeleteOldPredictions",enabled:!0,expirationDays:30}]}},machineLearning:{sagemaker:{endpoints:[{name:`${s}-inference`,modelS3Path:c,instanceType:u,initialInstanceCount:1,autoScaling:{minInstances:1,maxInstances:5,targetInvocationsPerInstance:1000}}],trainingJobs:[{name:`${s}-training`,algorithmSpecification:{trainingImage:"TO_BE_SPECIFIED",trainingInputMode:"File"},instanceType:"ml.p3.2xlarge",instanceCount:1,volumeSizeInGB:50,maxRuntimeInSeconds:86400}]}},apiGateway:{type:"HTTP",customDomain:o?{domain:o,certificateArn:"TO_BE_GENERATED"}:void 0,cors:{allowOrigins:["*"],allowMethods:["POST"],allowHeaders:["Content-Type","Authorization"]},throttling:{rateLimit:1000,burstLimit:500}},functions:{predict:{runtime:"python3.11",handler:"handlers/predict.handler",memory:2048,timeout:60,events:[{type:"http",path:"/predict",method:"POST"}],environment:{SAGEMAKER_ENDPOINT:`${s}-inference`,MODEL_BUCKET:`${s}-models`}},"batch-predict":{runtime:"python3.11",handler:"handlers/batchPredict.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${s}-datasets`,suffix:".csv"}]},"trigger-training":{runtime:"python3.11",handler:"handlers/training.handler",memory:1024,timeout:300,events:[{type:"schedule",expression:"cron(0 2 * * ? *)"}]}},databases:{dynamodb:{tables:{[`${s}-predictions`]:{partitionKey:{name:"requestId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0},[`${s}-models`]:{partitionKey:{name:"modelId",type:"S"},sortKey:{name:"version",type:"S"},billingMode:"PAY_PER_REQUEST"}}}},queues:{predictions:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:86400,deadLetterQueue:!0}},monitoring:{dashboard:{name:`${s}-ml`,widgets:[{type:"metric",metrics:["SageMakerInvocations","SageMakerModelLatency","APIGatewayRequests","LambdaErrors"]}]},alarms:[{metric:"SageMakerModelLatency",threshold:1000,evaluationPeriods:2},{metric:"SageMakerInvocationErrors",threshold:10,evaluationPeriods:1}]},security:{certificate:o?{domain:o,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","apiProtection"]}}}}}function lb(n){let{name:i,slug:s,domain:o,instanceType:c="t3.medium",minInstances:u=2,maxInstances:d=10,databaseEngine:g="mysql",sessionStore:y="redis"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:2}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",autoScaling:{min:u,max:d,targetCPU:70,scaleUpCooldown:300,scaleDownCooldown:300},loadBalancer:{type:"application",healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3},stickySession:{enabled:!0,duration:86400}},userData:`#!/bin/bash
2454
+ | limit 20`,region:e.ref("AWS::Region"),title:`Logs: ${u.logGroup}`}});else if(u.type==="text"&&u.text)s.push({type:"text",x:o,y:c,width:d,height:g,properties:{markdown:u.text}});if(o+=d,o>=24)o=0,c+=g}),n.addResource("CloudWatchDashboard","AWS::CloudWatch::Dashboard",{DashboardName:e.sub(`\${AWS::StackName}-${i.name}`),DashboardBody:JSON.stringify({widgets:s})}),n.addOutputs({DashboardURL:{Description:"CloudWatch Dashboard URL",Value:e.sub("https://console.aws.amazon.com/cloudwatch/home?region=${AWS::Region}#dashboards:name=${CloudWatchDashboard}")}})}function gi(n,i,s){let o=n.toLogicalId(`${i}-log-group`);n.addResource(o,"AWS::Logs::LogGroup",{LogGroupName:e.sub(`/aws/\${AWS::StackName}/${i}`),RetentionInDays:s||14,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}`)}]})}function wt(n,i){if(i)return{ec2:"AWS/EC2",ecs:"AWS/ECS",lambda:"AWS/Lambda",rds:"AWS/RDS",dynamodb:"AWS/DynamoDB",s3:"AWS/S3",cloudfront:"AWS/CloudFront",alb:"AWS/ApplicationELB",nlb:"AWS/NetworkELB",apigateway:"AWS/ApiGateway",sqs:"AWS/SQS",sns:"AWS/SNS",kinesis:"AWS/Kinesis",elasticache:"AWS/ElastiCache"}[i.toLowerCase()]||"AWS/CloudWatch";let s=n.toLowerCase();if(s.includes("cpu")||s.includes("memory")||s.includes("network"))return"AWS/EC2";if(s.includes("lambda")||s.includes("invocation")||s.includes("duration"))return"AWS/Lambda";if(s.includes("request")||s.includes("latency")||s.includes("target"))return"AWS/ApplicationELB";if(s.includes("database")||s.includes("connection"))return"AWS/RDS";if(s.includes("read")||s.includes("write")||s.includes("consumed"))return"AWS/DynamoDB";return"AWS/CloudWatch"}function yi(n){return{ec2:[{Name:"InstanceId",Value:e.ref("EC2Instance")}],ecs:[{Name:"ClusterName",Value:e.ref("ECSCluster")},{Name:"ServiceName",Value:e.getAtt("ECSService","Name")}],lambda:[{Name:"FunctionName",Value:e.ref("LambdaFunction")}],rds:[{Name:"DBInstanceIdentifier",Value:e.ref("Database")}],dynamodb:[{Name:"TableName",Value:e.ref("DynamoDBTable")}],alb:[{Name:"LoadBalancer",Value:e.getAtt("LoadBalancer","LoadBalancerFullName")}],apigateway:[{Name:"ApiName",Value:e.ref("HttpApi")}]}[n.toLowerCase()]||[]}function On(n,i){if(!i.vpc)return;let{cidr:s="10.0.0.0/16",availabilityZones:o=2,natGateways:c=1,enableDnsHostnames:u=!0,enableDnsSupport:d=!0}=i.vpc;n.addResource("VPC","AWS::EC2::VPC",{CidrBlock:s,EnableDnsHostnames:u,EnableDnsSupport:d,Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-vpc")}]}),n.addResource("InternetGateway","AWS::EC2::InternetGateway",{Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-igw")}]}),n.addResource("VPCGatewayAttachment","AWS::EC2::VPCGatewayAttachment",{VpcId:e.ref("VPC"),InternetGatewayId:e.ref("InternetGateway")},{dependsOn:["VPC","InternetGateway"]});let g=[];for(let C=0;C<o;C++){let v=`PublicSubnet${C+1}`;g.push(v),n.addResource(v,"AWS::EC2::Subnet",{VpcId:e.ref("VPC"),CidrBlock:e.select(C,e.cidr(e.getAtt("VPC","CidrBlock"),o*2,8)),AvailabilityZone:e.select(C,e.getAZs()),MapPublicIpOnLaunch:!0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-public-${C+1}`)},{Key:"Type",Value:"public"}]},{dependsOn:"VPC"})}let y=[];for(let C=0;C<o;C++){let v=`PrivateSubnet${C+1}`;y.push(v),n.addResource(v,"AWS::EC2::Subnet",{VpcId:e.ref("VPC"),CidrBlock:e.select(C+o,e.cidr(e.getAtt("VPC","CidrBlock"),o*2,8)),AvailabilityZone:e.select(C,e.getAZs()),MapPublicIpOnLaunch:!1,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-private-${C+1}`)},{Key:"Type",Value:"private"}]},{dependsOn:"VPC"})}let h=[];for(let C=0;C<c;C++){let v=`NatEIP${C+1}`;h.push(v),n.addResource(v,"AWS::EC2::EIP",{Domain:"vpc",Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-nat-eip-${C+1}`)}]},{dependsOn:"VPCGatewayAttachment"})}let A=[];for(let C=0;C<c;C++){let v=`NatGateway${C+1}`;A.push(v);let T=C%o;n.addResource(v,"AWS::EC2::NatGateway",{AllocationId:e.getAtt(h[C],"AllocationId"),SubnetId:e.ref(g[T]),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-nat-${C+1}`)}]},{dependsOn:[h[C],g[T]]})}n.addResource("PublicRouteTable","AWS::EC2::RouteTable",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-public-rt")}]},{dependsOn:"VPC"}),n.addResource("PublicRoute","AWS::EC2::Route",{RouteTableId:e.ref("PublicRouteTable"),DestinationCidrBlock:"0.0.0.0/0",GatewayId:e.ref("InternetGateway")},{dependsOn:["PublicRouteTable","VPCGatewayAttachment"]}),g.forEach((C,v)=>{n.addResource(`PublicSubnetRouteTableAssociation${v+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:e.ref(C),RouteTableId:e.ref("PublicRouteTable")},{dependsOn:[C,"PublicRouteTable"]})}),y.forEach((C,v)=>{let T=`PrivateRouteTable${v+1}`,R=v%c;n.addResource(T,"AWS::EC2::RouteTable",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-private-rt-${v+1}`)}]},{dependsOn:"VPC"}),n.addResource(`PrivateRoute${v+1}`,"AWS::EC2::Route",{RouteTableId:e.ref(T),DestinationCidrBlock:"0.0.0.0/0",NatGatewayId:e.ref(A[R])},{dependsOn:[T,A[R]]}),n.addResource(`PrivateSubnetRouteTableAssociation${v+1}`,"AWS::EC2::SubnetRouteTableAssociation",{SubnetId:e.ref(C),RouteTableId:e.ref(T)},{dependsOn:[C,T]})}),n.addResource("S3VPCEndpoint","AWS::EC2::VPCEndpoint",{VpcId:e.ref("VPC"),ServiceName:e.sub("com.amazonaws.${AWS::Region}.s3"),VpcEndpointType:"Gateway",RouteTableIds:[e.ref("PublicRouteTable"),...Array.from({length:o},(C,v)=>e.ref(`PrivateRouteTable${v+1}`))]},{dependsOn:"VPC"}),n.addResource("NetworkAcl","AWS::EC2::NetworkAcl",{VpcId:e.ref("VPC"),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-nacl")}]},{dependsOn:"VPC"}),n.addResource("NetworkAclEntryInbound","AWS::EC2::NetworkAclEntry",{NetworkAclId:e.ref("NetworkAcl"),RuleNumber:100,Protocol:-1,RuleAction:"allow",CidrBlock:"0.0.0.0/0"},{dependsOn:"NetworkAcl"}),n.addResource("NetworkAclEntryOutbound","AWS::EC2::NetworkAclEntry",{NetworkAclId:e.ref("NetworkAcl"),RuleNumber:100,Protocol:-1,Egress:!0,RuleAction:"allow",CidrBlock:"0.0.0.0/0"},{dependsOn:"NetworkAcl"}),n.addOutputs({VPCId:{Description:"VPC ID",Value:e.ref("VPC"),Export:{Name:e.sub("${AWS::StackName}-VPC")}},PublicSubnets:{Description:"Public subnet IDs",Value:e.join(",",g.map((C)=>e.ref(C))),Export:{Name:e.sub("${AWS::StackName}-PublicSubnets")}},PrivateSubnets:{Description:"Private subnet IDs",Value:e.join(",",y.map((C)=>e.ref(C))),Export:{Name:e.sub("${AWS::StackName}-PrivateSubnets")}}})}function $n(n,i){for(let[s,o]of Object.entries(i))fi(n,s,o)}function fi(n,i,s){let o=n.toLogicalId(`${i}-queue`),c=s.fifo||!1,u;if(s.deadLetterQueue){let g=`${o}DLQ`;n.addResource(g,"AWS::SQS::Queue",{QueueName:c?e.sub(`\${AWS::StackName}-${i}-dlq.fifo`):e.sub(`\${AWS::StackName}-${i}-dlq`),FifoQueue:c,MessageRetentionPeriod:1209600,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}-dlq`)}]},{deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),u=e.getAtt(g,"Arn")}let d={QueueName:c?e.sub(`\${AWS::StackName}-${i}.fifo`):e.sub(`\${AWS::StackName}-${i}`),FifoQueue:c,VisibilityTimeout:s.visibilityTimeout||30,MessageRetentionPeriod:s.messageRetentionPeriod||345600,ReceiveMessageWaitTimeSeconds:s.receiveMessageWaitTime||0,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}`)}]};if(c&&s.contentBasedDeduplication)d.ContentBasedDeduplication=!0;if(s.deadLetterQueue&&u)d.RedrivePolicy={deadLetterTargetArn:u,maxReceiveCount:s.maxReceiveCount||3};if(n.addResource(o,"AWS::SQS::Queue",d,{dependsOn:s.deadLetterQueue?`${o}DLQ`:void 0,deletionPolicy:"Retain",updateReplacePolicy:"Retain"}),n.addResource(`${o}Policy`,"AWS::SQS::QueuePolicy",{Queues:[e.ref(o)],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:["lambda.amazonaws.com","events.amazonaws.com","sns.amazonaws.com"]},Action:"sqs:SendMessage",Resource:e.getAtt(o,"Arn"),Condition:{ArnEquals:{"aws:SourceArn":e.sub("arn:aws:*:${AWS::Region}:${AWS::AccountId}:*")}}}]}},{dependsOn:o}),n.addOutputs({[`${o}Url`]:{Description:`${i} queue URL`,Value:e.ref(o),Export:{Name:e.sub(`\${AWS::StackName}-${i}-queue-url`)}},[`${o}Arn`]:{Description:`${i} queue ARN`,Value:e.getAtt(o,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${i}-queue-arn`)}}}),s.deadLetterQueue)n.addOutputs({[`${o}DLQUrl`]:{Description:`${i} dead letter queue URL`,Value:e.ref(`${o}DLQ`),Export:{Name:e.sub(`\${AWS::StackName}-${i}-dlq-url`)}}})}function Bn(n,i){if(i.certificate)hi(n,i.certificate);if(i.waf?.enabled)bi(n,i.waf);if(i.securityGroups)for(let[s,o]of Object.entries(i.securityGroups))Si(n,s,o)}function hi(n,i){if(!i)return;let s=[i.domain];if(i.subdomains)s.push(...i.subdomains);n.addResource("Certificate","AWS::CertificateManager::Certificate",{DomainName:i.domain,SubjectAlternativeNames:i.subdomains,ValidationMethod:i.validationMethod||"DNS",DomainValidationOptions:s.map((o)=>({DomainName:o,HostedZoneId:e.ref("HostedZone")})),Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-certificate")}]}),n.addOutputs({CertificateArn:{Description:"ACM Certificate ARN",Value:e.ref("Certificate"),Export:{Name:e.sub("${AWS::StackName}-certificate-arn")}}})}function bi(n,i){if(!i)return;let s=[],o=i.rules||["rateLimit","sqlInjection","xss"];if(o.includes("rateLimit"))s.push({Name:"RateLimitRule",Priority:1,Statement:{RateBasedStatement:{Limit:i.rateLimit||2000,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"RateLimitRule"}});let c=s.length+1;if(o.includes("sqlInjection"))s.push({Name:"AWSManagedRulesSQLi",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesSQLiRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesSQLi"}});if(o.includes("xss"))s.push({Name:"AWSManagedRulesXSS",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesXSS"}});if(o.includes("knownBadInputs"))s.push({Name:"AWSManagedRulesKnownBadInputs",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesKnownBadInputsRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesKnownBadInputs"}});if(o.includes("coreRuleSet"))s.push({Name:"AWSManagedRulesCoreRuleSet",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesCommonRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesCoreRuleSet"}});if(o.includes("linuxRuleSet"))s.push({Name:"AWSManagedRulesLinuxRuleSet",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesLinuxRuleSet"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesLinuxRuleSet"}});if(o.includes("apiProtection"))s.push({Name:"AWSManagedRulesAPIProtection",Priority:c++,Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:"AWSManagedRulesAmazonIpReputationList"}},OverrideAction:{None:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"AWSManagedRulesAPIProtection"}});if(o.includes("geoBlock"))s.push({Name:"GeoBlockRule",Priority:c++,Statement:{GeoMatchStatement:{CountryCodes:["CN","RU"]}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"GeoBlockRule"}});if(o.includes("connectionLimit"))s.push({Name:"ConnectionLimitRule",Priority:c++,Statement:{RateBasedStatement:{Limit:100,AggregateKeyType:"IP"}},Action:{Block:{}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:"ConnectionLimitRule"}});if(n.addResource("WebACL","AWS::WAFv2::WebACL",{Name:e.sub("${AWS::StackName}-waf"),Scope:i.scope||"REGIONAL",DefaultAction:{Allow:{}},Rules:s,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:e.sub("${AWS::StackName}-waf")},Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-waf")}]}),n.hasResource("LoadBalancer"))n.addResource("WebACLAssociation","AWS::WAFv2::WebACLAssociation",{ResourceArn:e.ref("LoadBalancer"),WebACLArn:e.getAtt("WebACL","Arn")},{dependsOn:["WebACL","LoadBalancer"]});n.addOutputs({WebACLId:{Description:"WAF Web ACL ID",Value:e.ref("WebACL"),Export:{Name:e.sub("${AWS::StackName}-waf-id")}},WebACLArn:{Description:"WAF Web ACL ARN",Value:e.getAtt("WebACL","Arn"),Export:{Name:e.sub("${AWS::StackName}-waf-arn")}}})}function Si(n,i,s){if(!s)return;let o=n.toLogicalId(`${i}-security-group`),c=s.ingress?.map((d)=>({IpProtocol:d.protocol,FromPort:d.port,ToPort:d.port,CidrIp:d.cidr,SourceSecurityGroupId:d.source?e.ref(d.source):void 0}))||[],u=s.egress?.map((d)=>({IpProtocol:d.protocol,FromPort:d.port,ToPort:d.port,CidrIp:d.cidr||"0.0.0.0/0"}))||[{IpProtocol:"-1",CidrIp:"0.0.0.0/0"}];n.addResource(o,"AWS::EC2::SecurityGroup",{GroupDescription:`Security group for ${i}`,VpcId:e.ref("VPC"),SecurityGroupIngress:c,SecurityGroupEgress:u,Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}-sg`)}]},{dependsOn:"VPC"}),n.addOutputs({[`${o}Id`]:{Description:`${i} security group ID`,Value:e.ref(o),Export:{Name:e.sub(`\${AWS::StackName}-${i}-sg-id`)}}})}function Fn(n,i){for(let[s,o]of Object.entries(i)){if(o.type==="efs"){Ci(n,s,o);continue}Ai(n,s,o)}}function Ai(n,i,s){let o=n.toLogicalId(`${i}-bucket`),c={BucketName:e.sub(`\${AWS::StackName}-${i}`),Tags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}`)}]};if(s.versioning)c.VersioningConfiguration={Status:"Enabled"};if(s.encryption)c.BucketEncryption={ServerSideEncryptionConfiguration:[{ServerSideEncryptionByDefault:{SSEAlgorithm:"AES256"}}]};if(!s.public)c.PublicAccessBlockConfiguration={BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0};if(s.website)c.WebsiteConfiguration={IndexDocument:"index.html",ErrorDocument:"index.html"};if(s.cors&&s.cors.length>0)c.CorsConfiguration={CorsRules:s.cors.map((u)=>({AllowedOrigins:u.allowedOrigins,AllowedMethods:u.allowedMethods,AllowedHeaders:u.allowedHeaders||["*"],MaxAge:u.maxAge||3600}))};if(s.lifecycleRules&&s.lifecycleRules.length>0)c.LifecycleConfiguration={Rules:s.lifecycleRules.map((u)=>({Id:u.id,Status:u.enabled?"Enabled":"Disabled",ExpirationInDays:u.expirationDays,Transitions:u.transitions?.map((d)=>({TransitionInDays:d.days,StorageClass:d.storageClass}))}))};if(s.intelligentTiering)c.IntelligentTieringConfigurations=[{Id:"EntireBucket",Status:"Enabled",Tierings:[{AccessTier:"ARCHIVE_ACCESS",Days:90},{AccessTier:"DEEP_ARCHIVE_ACCESS",Days:180}]}];if(n.addResource(o,"AWS::S3::Bucket",c,{deletionPolicy:s.versioning?"Retain":"Delete"}),s.public)n.addResource(`${o}Policy`,"AWS::S3::BucketPolicy",{Bucket:e.ref(o),PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"PublicReadGetObject",Effect:"Allow",Principal:"*",Action:"s3:GetObject",Resource:e.join("",[pn.s3Bucket(e.ref(o)),"/*"])}]}},{dependsOn:o});if(n.addOutputs({[`${o}Name`]:{Description:`${i} bucket name`,Value:e.ref(o),Export:{Name:e.sub(`\${AWS::StackName}-${i}-bucket`)}},[`${o}Arn`]:{Description:`${i} bucket ARN`,Value:e.getAtt(o,"Arn"),Export:{Name:e.sub(`\${AWS::StackName}-${i}-bucket-arn`)}}}),s.website)n.addOutputs({[`${o}WebsiteURL`]:{Description:`${i} website URL`,Value:e.getAtt(o,"WebsiteURL")}})}function Ci(n,i,s){let o=n.toLogicalId(`${i}-efs`),c={Encrypted:s.encryption!==!1,PerformanceMode:s.performanceMode||"generalPurpose",ThroughputMode:s.throughputMode||"bursting",FileSystemTags:[{Key:"Name",Value:e.sub(`\${AWS::StackName}-${i}`)}]};if(s.lifecyclePolicy){if(c.LifecyclePolicies=[],s.lifecyclePolicy.transitionToIA)c.LifecyclePolicies.push({TransitionToIA:`AFTER_${s.lifecyclePolicy.transitionToIA}_DAYS`});if(s.lifecyclePolicy.transitionToPrimaryStorageClass)c.LifecyclePolicies.push({TransitionToPrimaryStorageClass:"AFTER_1_ACCESS"})}n.addResource(o,"AWS::EFS::FileSystem",c,{deletionPolicy:"Retain"});let u=2;for(let d=0;d<u;d++)n.addResource(`${o}MountTarget${d+1}`,"AWS::EFS::MountTarget",{FileSystemId:e.ref(o),SubnetId:e.ref(`PrivateSubnet${d+1}`),SecurityGroups:[e.ref("EFSSecurityGroup")]},{dependsOn:[o,`PrivateSubnet${d+1}`]});n.addResource("EFSSecurityGroup","AWS::EC2::SecurityGroup",{GroupDescription:"Security group for EFS mount targets",VpcId:e.ref("VPC"),SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:2049,ToPort:2049,SourceSecurityGroupId:e.ref("AppSecurityGroup")}],Tags:[{Key:"Name",Value:e.sub("${AWS::StackName}-efs-sg")}]},{dependsOn:"VPC"}),n.addOutputs({[`${o}Id`]:{Description:`${i} EFS file system ID`,Value:e.ref(o),Export:{Name:e.sub(`\${AWS::StackName}-${i}-efs`)}}})}class Hm{template;config;resourceDependencies;constructor(n){this.config=n,this.resourceDependencies=new Map,this.template={AWSTemplateFormatVersion:"2010-09-09",Description:`Infrastructure for ${n.project.name} (${n.project.slug})`,Resources:{}}}build(){return this.addParameters(),this.addMappings(),this.addConditions(),this.addResources(),this.initializeOutputs(),this.resolveDependencies(),this.template}addParameters(){this.template.Parameters={Environment:{Type:"String",Default:"production",AllowedValues:["development","staging","production"],Description:"Environment name"}}}addMappings(){this.template.Mappings={RegionMap:{"us-east-1":{AMI:"ami-0f3caa1cf4417e51b"},"us-west-2":{AMI:"ami-0d1cd67c26f5fca19"},"eu-west-1":{AMI:"ami-0bbc25e23a7640b9b"}}}}addConditions(){this.template.Conditions={IsProduction:e.equals(e.ref("Environment"),"production"),HasDomain:e.not([e.equals(this.config.environments?.production?.domain||"","")])}}addResources(){let{infrastructure:n}=this.config;if(!n)return;if(n.network)this.addNetworkResources(n.network);if(n.storage)this.addStorageResources(n.storage);if(n.compute)this.addComputeResources(n.compute);if(n.databases)this.addDatabaseResources(n.databases);if(n.cache)this.addCacheResources(n.cache);if(n.cdn)this.addCDNResources(n.cdn);if(n.apiGateway)this.addApiGatewayResources(n.apiGateway);if(n.functions)this.addFunctionResources(n.functions);if(n.queues)this.addQueueResources(n.queues);if(n.messaging)this.addMessagingResources(n.messaging);if(n.monitoring)this.addMonitoringResources(n.monitoring);if(n.security)this.addSecurityResources(n.security)}initializeOutputs(){let n=this.template.Outputs||{};if(this.template.Outputs={StackName:{Description:"Stack name",Value:e.ref("AWS::StackName"),Export:{Name:e.sub("${AWS::StackName}-Name")}},Region:{Description:"AWS Region",Value:e.ref("AWS::Region"),Export:{Name:e.sub("${AWS::StackName}-Region")}},...n},this.config.environments?.production?.domain)this.template.Outputs.Domain={Description:"Production domain",Value:this.config.environments.production.domain,Condition:"HasDomain"}}addResource(n,i,s,o){let c={Type:i,Properties:s};if(o?.dependsOn)c.DependsOn=o.dependsOn,this.trackDependency(n,o.dependsOn);if(o?.condition)c.Condition=o.condition;if(o?.deletionPolicy)c.DeletionPolicy=o.deletionPolicy;if(o?.updateReplacePolicy)c.UpdateReplacePolicy=o.updateReplacePolicy;this.template.Resources[n]=c}addOutputs(n){this.template.Outputs={...this.template.Outputs,...n}}getOutputs(){return this.template.Outputs||{}}hasResource(n){return n in this.template.Resources}getResource(n){return this.template.Resources[n]}trackDependency(n,i){if(!this.resourceDependencies.has(n))this.resourceDependencies.set(n,new Set);(Array.isArray(i)?i:[i]).forEach((o)=>this.resourceDependencies.get(n).add(o))}resolveDependencies(){let n=new Set,i=new Set,s=(o)=>{if(i.has(o))throw Error(`Circular dependency detected involving resource: ${o}`);if(n.has(o))return!0;n.add(o),i.add(o);let c=this.resourceDependencies.get(o);if(c)for(let u of c)s(u);return i.delete(o),!0};for(let o of this.resourceDependencies.keys())s(o)}toLogicalId(n){return n.split(/[-_\s]/).map((i)=>i.charAt(0).toUpperCase()+i.slice(1).toLowerCase()).join("")}addNetworkResources(n){On(this,n)}addStorageResources(n){Fn(this,n)}addComputeResources(n){Dn(this,n)}addDatabaseResources(n){xn(this,n)}addFunctionResources(n){kn(this,n)}addCacheResources(n){En(this,n)}addQueueResources(n){$n(this,n)}addMessagingResources(n){Mn(this,n)}addCDNResources(n){wn(this,n)}addApiGatewayResources(n){Pn(this,n)}addMonitoringResources(n){Ln(this,n)}addSecurityResources(n){Bn(this,n)}}function vl(n){return new Hm(n).build()}function lb(n){let{name:i,slug:s,domain:o,subdomain:c}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:c&&o?`${c}.${o}`:o}},infrastructure:{storage:{assets:{public:!0,versioning:!1,website:!0,encryption:!1,cors:[{allowedOrigins:["*"],allowedMethods:["GET","HEAD"],allowedHeaders:["*"],maxAge:3600}]}},cdn:{enabled:!0,customDomain:o?{domain:c&&o?`${c}.${o}`:o,certificateArn:"TO_BE_GENERATED"}:void 0,cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0,errorPages:{404:"/index.html",403:"/index.html"}}}}}function ub(n){let{name:i,slug:s,domain:o,instanceType:c="t3.small",minInstances:u=2,maxInstances:d=10}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",keyPair:`${s}-key`,autoScaling:{min:u,max:d,desired:u,targetCPU:70},loadBalancer:{type:"application",healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3}},userData:{packages:["nodejs","npm","nginx"],commands:["curl -fsSL https://bun.sh/install | bash","npm install -g pm2"]}}},databases:{postgres:{engine:"postgres",version:"15",instanceClass:"db.t3.micro",allocatedStorage:20,multiAZ:!0,backupRetentionDays:7,deletionProtection:!0}},cache:{redis:{nodeType:"cache.t3.micro",numCacheNodes:1,engine:"redis",engineVersion:"7.0"}},security:{certificate:o?{domain:o,subdomains:[`*.${o}`],validationMethod:"DNS"}:void 0}}}}function gb(n){let{name:i,slug:s,domain:o,taskCpu:c="256",taskMemory:u="512",desiredCount:d=2}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:0}},compute:{fargate:{taskDefinition:{cpu:c,memory:u,containerDefinitions:[{name:"app",image:`${s}-app:latest`,portMappings:[{containerPort:3000}],environment:[],secrets:[]}]},service:{desiredCount:d,healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3},autoScaling:{min:d,max:d*5,targetCPU:70,targetMemory:80}},loadBalancer:{type:"application"}}},databases:{dynamodb:{tables:{[`${s}-main`]:{partitionKey:{name:"id",type:"S"},sortKey:{name:"createdAt",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0}}}},functions:{"process-queue":{runtime:"nodejs20.x",handler:"dist/workers/queue.handler",memory:512,timeout:60,events:[{type:"sqs",queueName:`${s}-queue`}]}},security:{certificate:o?{domain:o,subdomains:[`*.${o}`],validationMethod:"DNS"}:void 0}}}}function pb(n){let{name:i,slug:s,entry:o,domain:c,runtime:u="nodejs20.x",memory:d=1024,build:g,deploy:y,assets:h,queues:A=!0,scheduler:C="on",region:v="us-east-1"}=n;return{project:{name:i,slug:s,region:v},mode:"serverless",environments:{production:{type:"production",domain:c,app:{kind:"node",runtime:u,entry:o,memory:d,build:g,deploy:y,assets:h,queues:A,scheduler:C,domain:c}}}}}function Tl(n){let i=n.database!==!1,s=n.cache!==!1,o=n.queue!==!1;return{project:{name:n.name,slug:n.slug,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:n.domain}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{fargate:{taskDefinition:{cpu:"256",memory:"512",containerDefinitions:[{name:"api",image:n.imageUri,portMappings:[{containerPort:3000}],environment:[{name:"NODE_ENV",value:"production"},{name:"PORT",value:"3000"},{name:"AWS_REGION",value:e.ref("AWS::Region")},...i?[{name:"DB_HOST",value:e.getAtt("PostgresDb","Endpoint.Address")},{name:"DB_PORT",value:e.getAtt("PostgresDb","Endpoint.Port")}]:[],...s?[{name:"REDIS_HOST",value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Address")},{name:"REDIS_PORT",value:e.getAtt("RedisReplicationGroup","PrimaryEndPoint.Port")},{name:"REDIS_TLS",value:"true"}]:[],...o?[{name:"QUEUE_URL",value:e.ref("JobsQueue")}]:[],{name:"MAIL_TRANSPORT",value:"ses"}],secrets:i?[{name:"DB_USERNAME",valueFrom:e.sub("${DBSecret}:username::")},{name:"DB_PASSWORD",valueFrom:e.sub("${DBSecret}:password::")}]:[]}]},service:{desiredCount:n.desiredCount||1,healthCheck:{path:"/api/health",interval:30,timeout:5},autoScaling:{min:n.desiredCount||1,max:6,targetCPU:70}},loadBalancer:{type:"application",...n.certificateArn?{customDomain:{domain:n.domain,certificateArn:n.certificateArn}}:{},...n.originVerifySecret?{originVerifyHeader:{name:"X-Origin-Verify",value:n.originVerifySecret}}:{}}}},...i?{databases:{postgres:{engine:"postgres",version:"16",instanceClass:"db.t4g.micro",allocatedStorage:20,maxAllocatedStorage:100,multiAZ:!1,backupRetentionDays:7,deletionProtection:!0}}}:{},...s?{cache:{redis:{nodeType:"cache.t4g.micro",numCacheNodes:2,engine:"redis",engineVersion:"7.1",automaticFailoverEnabled:!0,snapshotRetentionLimit:5}}}:{},...o?{queues:{jobs:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0,maxReceiveCount:3,receiveMessageWaitTime:20}}}:{}}}}function mb(n){let{name:i,slug:s,domain:o,apiSubdomain:c="api"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},storage:{frontend:{public:!0,versioning:!0,website:!0,encryption:!1}},cdn:{enabled:!0,customDomain:{domain:o,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0,errorPages:{404:"/index.html"}},compute:{fargate:{taskDefinition:{cpu:"512",memory:"1024",containerDefinitions:[{name:"api",image:`${s}-api:latest`,portMappings:[{containerPort:3000}]}]},service:{desiredCount:2,healthCheck:{path:"/api/health",interval:30},autoScaling:{min:2,max:10,targetCPU:70}},loadBalancer:{type:"application",customDomain:{domain:`${c}.${o}`,certificateArn:"TO_BE_GENERATED"}}}},databases:{postgres:{engine:"postgres",version:"15",instanceClass:"db.t3.small",allocatedStorage:50,multiAZ:!0,backupRetentionDays:14,deletionProtection:!0}},cache:{redis:{nodeType:"cache.t3.small",numCacheNodes:2,engine:"redis",engineVersion:"7.0"}},queues:{jobs:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0}},security:{certificate:{domain:o,subdomains:[`*.${o}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss"]}}}}}function fb(n){let{name:i,slug:s,domain:o}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{apiGateway:{type:"HTTP",cors:{allowOrigins:["*"],allowMethods:["GET","POST","PUT","DELETE","PATCH"],allowHeaders:["Content-Type","Authorization"],maxAge:3600},customDomain:o?{domain:o,certificateArn:"TO_BE_GENERATED"}:void 0,throttling:{rateLimit:1e4,burstLimit:5000},authorizer:{type:"JWT",identitySource:"$request.header.Authorization"}},functions:{users:{runtime:"nodejs20.x",handler:"dist/api/users.handler",memory:512,timeout:30,events:[{type:"http",path:"/users",method:"GET"},{type:"http",path:"/users",method:"POST"}]},products:{runtime:"nodejs20.x",handler:"dist/api/products.handler",memory:512,timeout:30,events:[{type:"http",path:"/products",method:"GET"}]}},databases:{dynamodb:{tables:{[`${s}-users`]:{partitionKey:{name:"userId",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0,globalSecondaryIndexes:[{name:"EmailIndex",partitionKey:{name:"email",type:"S"},projection:"ALL"}]},[`${s}-products`]:{partitionKey:{name:"productId",type:"S"},sortKey:{name:"category",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!1}}}},cache:{elasticache:{nodeType:"cache.t3.micro",numCacheNodes:1,engine:"redis",engineVersion:"7.0"}},security:{certificate:o?{domain:o,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","sqlInjection"]}},monitoring:{alarms:[{metric:"Errors",threshold:10,period:300,evaluationPeriods:1},{metric:"Duration",threshold:3000,period:300,evaluationPeriods:2}]}}}}function hb(n){let{name:i,slug:s,domain:o,instanceType:c="t3.small"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:1}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",keyPair:`${s}-key`,autoScaling:{min:2,max:6,desired:2,targetCPU:75},loadBalancer:{type:"application",healthCheck:{path:"/wp-admin/install.php",interval:30}},userData:{packages:["nginx","php8.1-fpm","php8.1-mysql","php8.1-curl","php8.1-gd","php8.1-mbstring","php8.1-xml","php8.1-zip"],commands:["cd /var/www","wget https://wordpress.org/latest.tar.gz","tar -xzf latest.tar.gz","chown -R www-data:www-data wordpress","rm /etc/nginx/sites-enabled/default","systemctl restart nginx","systemctl restart php8.1-fpm"]}}},fileSystem:{uploads:{performanceMode:"generalPurpose",throughputMode:"bursting",encrypted:!0,lifecyclePolicy:{transitionToIA:30},mountPath:"/var/www/wordpress/wp-content/uploads"}},databases:{mysql:{engine:"mysql",version:"8.0",instanceClass:"db.t3.small",allocatedStorage:50,multiAZ:!0,backupRetentionDays:7,deletionProtection:!0,databaseName:"wordpress"}},cache:{redis:{nodeType:"cache.t3.micro",numCacheNodes:1,engine:"redis",engineVersion:"7.0"}},cdn:{enabled:!0,customDomain:{domain:o,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,origins:[{type:"alb",pathPattern:"/wp-content/*"}]},security:{certificate:{domain:o,subdomains:[`www.${o}`],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss","wordpressRules"]}}}}}function Ab(n){let{name:i,slug:s,domain:o,apiDomain:c}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{storage:{static:{public:!0,versioning:!0,website:!0,encryption:!1,cors:[{allowedOrigins:["*"],allowedMethods:["GET","HEAD"]}],lifecycleRules:[{id:"DeleteOldVersions",enabled:!0,expirationDays:90}]}},cdn:{enabled:!0,customDomain:{domain:o,certificateArn:"TO_BE_GENERATED"},cachePolicy:{minTTL:0,defaultTTL:0,maxTTL:31536000},compress:!0,http3:!0,errorPages:{404:"/404.html",500:"/500.html"},edgeFunctions:[{eventType:"origin-request",functionArn:"TO_BE_CREATED",name:"ssr-handler"}]},functions:{ssr:{runtime:"nodejs20.x",handler:"dist/edge/ssr.handler",memory:512,timeout:5},...c?{api:{runtime:"nodejs20.x",handler:"dist/api/index.handler",memory:1024,timeout:30,events:[{type:"http",path:"/{proxy+}",method:"ANY"}]}}:{}},apiGateway:c?{type:"HTTP",customDomain:{domain:c,certificateArn:"TO_BE_GENERATED"},cors:{allowOrigins:[o],allowMethods:["GET","POST","PUT","DELETE"],allowHeaders:["Content-Type","Authorization"]}}:void 0,databases:{dynamodb:{tables:{content:{partitionKey:{name:"id",type:"S"},sortKey:{name:"type",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!1}}}},security:{certificate:{domain:o,subdomains:c?[c]:[],validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","geoBlock"]}}}}}function yb(n){let{name:i,slug:s,domain:o,services:c}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:3,natGateways:2}},compute:{services:c.map((u)=>({name:u.name,type:"fargate",taskDefinition:{cpu:u.cpu||"256",memory:u.memory||"512",containerDefinitions:[{name:u.name,image:`${s}-${u.name}:latest`,portMappings:[{containerPort:u.port}],healthCheck:{command:["CMD-SHELL",`curl -f http://localhost:${u.port}/health || exit 1`],interval:30,timeout:5,retries:3}}]},service:{desiredCount:u.desiredCount||2,serviceDiscovery:{enabled:!0,namespace:`${s}.local`},autoScaling:{min:2,max:10,targetCPU:70}}}))},apiGateway:{type:"HTTP",customDomain:{domain:o,certificateArn:"TO_BE_GENERATED"},cors:{allowOrigins:["*"],allowMethods:["GET","POST","PUT","DELETE","PATCH"]},routes:c.map((u)=>({path:`/${u.name}/{proxy+}`,integration:{type:"vpc-link",service:u.name}}))},databases:{dynamodb:{tables:Object.fromEntries(c.map((u)=>[`${s}-${u.name}`,{partitionKey:{name:"id",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0}]))}},queues:{events:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:345600,deadLetterQueue:!0}},messaging:{topics:{events:{name:`${s}-events`,subscriptions:c.map((u)=>({protocol:"sqs",endpoint:`${s}-${u.name}-queue`,filterPolicy:{service:[u.name]}}))}}},monitoring:{dashboard:{name:`${s}-microservices`,widgets:c.map((u)=>({type:"metric",metrics:[{service:u.name,metric:"CPUUtilization"},{service:u.name,metric:"MemoryUtilization"},{service:u.name,metric:"RequestCount"}]}))},alarms:c.flatMap((u)=>[{name:`${u.name}-high-cpu`,metric:"CPUUtilization",threshold:80,service:u.name},{name:`${u.name}-errors`,metric:"Errors",threshold:10,service:u.name}])},security:{certificate:{domain:o,validationMethod:"DNS"},waf:{enabled:!0,rules:["rateLimit","sqlInjection"]}}}}}function Sb(n){let{name:i,slug:s,domain:o}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{apiGateway:{type:"websocket",customDomain:o?{domain:o,certificateArn:"TO_BE_GENERATED"}:void 0,routes:[{path:"$connect",method:"WEBSOCKET",integration:"websocket-connect"},{path:"$disconnect",method:"WEBSOCKET",integration:"websocket-disconnect"},{path:"$default",method:"WEBSOCKET",integration:"websocket-default"},{path:"sendMessage",method:"WEBSOCKET",integration:"websocket-send-message"},{path:"joinRoom",method:"WEBSOCKET",integration:"websocket-join-room"}]},functions:{connect:{runtime:"nodejs20.x",handler:"dist/websocket/connect.handler",memory:512,timeout:30},disconnect:{runtime:"nodejs20.x",handler:"dist/websocket/disconnect.handler",memory:512,timeout:30},default:{runtime:"nodejs20.x",handler:"dist/websocket/default.handler",memory:512,timeout:30},"send-message":{runtime:"nodejs20.x",handler:"dist/websocket/sendMessage.handler",memory:512,timeout:30},"join-room":{runtime:"nodejs20.x",handler:"dist/websocket/joinRoom.handler",memory:512,timeout:30},broadcast:{runtime:"nodejs20.x",handler:"dist/streams/broadcast.handler",memory:1024,timeout:60,events:[{type:"dynamodb-stream",tableName:`${s}-messages`,startingPosition:"LATEST",batchSize:100}]}},databases:{dynamodb:{tables:{[`${s}-connections`]:{partitionKey:{name:"connectionId",type:"S"},billingMode:"PAY_PER_REQUEST",globalSecondaryIndexes:[{name:"RoomIndex",partitionKey:{name:"roomId",type:"S"},sortKey:{name:"connectionId",type:"S"},projection:"ALL"}]},[`${s}-messages`]:{partitionKey:{name:"roomId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0,pointInTimeRecovery:!0,globalSecondaryIndexes:[{name:"UserIndex",partitionKey:{name:"userId",type:"S"},sortKey:{name:"timestamp",type:"S"},projection:"ALL"}]},[`${s}-rooms`]:{partitionKey:{name:"roomId",type:"S"},billingMode:"PAY_PER_REQUEST"}}}},cache:{elasticache:{nodeType:"cache.t3.small",numCacheNodes:2,engine:"redis",engineVersion:"7.0"}},monitoring:{alarms:[{metric:"WebSocketConnections",threshold:1e4,evaluationPeriods:1},{metric:"IntegrationLatency",threshold:1000,evaluationPeriods:2}],dashboard:{name:`${s}-realtime`,widgets:[{type:"metric",metrics:["WebSocketConnections","MessagesSent","IntegrationLatency"]}]}},security:{certificate:o?{domain:o,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","connectionLimit"]}}}}}function Ib(n){let{name:i,slug:s,retentionDays:o=7}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",infrastructure:{streaming:{dataStream:{name:`${s}-stream`,shardCount:2,retentionPeriod:o*24,encryption:!0}},storage:{raw:{public:!1,versioning:!0,encryption:!0,intelligentTiering:!0,lifecycleRules:[{id:"ArchiveOldData",enabled:!0,transitions:[{days:30,storageClass:"GLACIER"},{days:90,storageClass:"DEEP_ARCHIVE"}]}]},processed:{public:!1,versioning:!0,encryption:!0,intelligentTiering:!0}},functions:{"stream-processor":{runtime:"nodejs20.x",handler:"dist/processors/stream.handler",memory:2048,timeout:300,events:[{type:"kinesis",streamName:`${s}-stream`,batchSize:1000,startingPosition:"LATEST",parallelizationFactor:10}]},transformer:{runtime:"nodejs20.x",handler:"dist/processors/transform.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${s}-raw`,prefix:"incoming/"}]},aggregator:{runtime:"nodejs20.x",handler:"dist/processors/aggregate.handler",memory:2048,timeout:600,events:[{type:"schedule",expression:"cron(0 * * * ? *)"}]}},analytics:{athena:{database:`${s}_analytics`,workgroup:`${s}-workgroup`,outputBucket:`${s}-query-results`,tables:[{name:"raw_events",location:`s3://${s}-raw/events/`,format:"parquet",partitionKeys:["year","month","day"]},{name:"processed_events",location:`s3://${s}-processed/events/`,format:"parquet",partitionKeys:["year","month","day"]}]},glue:{crawlers:[{name:`${s}-crawler`,databaseName:`${s}_analytics`,s3Targets:[`s3://${s}-raw/`,`s3://${s}-processed/`],schedule:"cron(0 2 * * ? *)"}],jobs:[{name:`${s}-etl-job`,scriptLocation:`s3://${s}-scripts/etl.py`,role:`${s}-glue-role`,maxCapacity:10,timeout:120}]}},databases:{dynamodb:{tables:{[`${s}-metadata`]:{partitionKey:{name:"pipelineId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST"}}}},queues:{failedJobs:{fifo:!1,visibilityTimeout:900,messageRetentionPeriod:1209600,deadLetterQueue:!0,maxReceiveCount:3}},workflow:{pipelines:[{name:`${s}-daily-pipeline`,type:"stepFunctions",definition:{StartAt:"ExtractData",States:{ExtractData:{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Next:"TransformData"},TransformData:{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",Next:"LoadData"},LoadData:{Type:"Task",Resource:"arn:aws:states:::lambda:invoke",End:!0}}},schedule:"cron(0 0 * * ? *)"}]},monitoring:{dashboard:{name:`${s}-pipeline`,widgets:[{type:"metric",metrics:["KinesisIncomingRecords","LambdaInvocations","S3ObjectsCreated","GlueJobsSucceeded"]}]},alarms:[{metric:"LambdaErrors",threshold:10,evaluationPeriods:1},{metric:"KinesisIteratorAge",threshold:60000,evaluationPeriods:2}]}}}}function bb(n){let{name:i,slug:s,domain:o,modelS3Path:c=`s3://${s}-models/`,instanceType:u="ml.t3.medium"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"serverless",environments:{production:{type:"production",domain:o}},infrastructure:{storage:{models:{public:!1,versioning:!0,encryption:!0,intelligentTiering:!0},datasets:{public:!1,versioning:!0,encryption:!0,lifecycleRules:[{id:"ArchiveOldDatasets",enabled:!0,transitions:[{days:90,storageClass:"GLACIER"}]}]},predictions:{public:!1,versioning:!1,encryption:!0,lifecycleRules:[{id:"DeleteOldPredictions",enabled:!0,expirationDays:30}]}},machineLearning:{sagemaker:{endpoints:[{name:`${s}-inference`,modelS3Path:c,instanceType:u,initialInstanceCount:1,autoScaling:{minInstances:1,maxInstances:5,targetInvocationsPerInstance:1000}}],trainingJobs:[{name:`${s}-training`,algorithmSpecification:{trainingImage:"TO_BE_SPECIFIED",trainingInputMode:"File"},instanceType:"ml.p3.2xlarge",instanceCount:1,volumeSizeInGB:50,maxRuntimeInSeconds:86400}]}},apiGateway:{type:"HTTP",customDomain:o?{domain:o,certificateArn:"TO_BE_GENERATED"}:void 0,cors:{allowOrigins:["*"],allowMethods:["POST"],allowHeaders:["Content-Type","Authorization"]},throttling:{rateLimit:1000,burstLimit:500}},functions:{predict:{runtime:"python3.11",handler:"handlers/predict.handler",memory:2048,timeout:60,events:[{type:"http",path:"/predict",method:"POST"}],environment:{SAGEMAKER_ENDPOINT:`${s}-inference`,MODEL_BUCKET:`${s}-models`}},"batch-predict":{runtime:"python3.11",handler:"handlers/batchPredict.handler",memory:3008,timeout:900,events:[{type:"s3",bucket:`${s}-datasets`,suffix:".csv"}]},"trigger-training":{runtime:"python3.11",handler:"handlers/training.handler",memory:1024,timeout:300,events:[{type:"schedule",expression:"cron(0 2 * * ? *)"}]}},databases:{dynamodb:{tables:{[`${s}-predictions`]:{partitionKey:{name:"requestId",type:"S"},sortKey:{name:"timestamp",type:"S"},billingMode:"PAY_PER_REQUEST",streamEnabled:!0},[`${s}-models`]:{partitionKey:{name:"modelId",type:"S"},sortKey:{name:"version",type:"S"},billingMode:"PAY_PER_REQUEST"}}}},queues:{predictions:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:86400,deadLetterQueue:!0}},monitoring:{dashboard:{name:`${s}-ml`,widgets:[{type:"metric",metrics:["SageMakerInvocations","SageMakerModelLatency","APIGatewayRequests","LambdaErrors"]}]},alarms:[{metric:"SageMakerModelLatency",threshold:1000,evaluationPeriods:2},{metric:"SageMakerInvocationErrors",threshold:10,evaluationPeriods:1}]},security:{certificate:o?{domain:o,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","apiProtection"]}}}}}function Cb(n){let{name:i,slug:s,domain:o,instanceType:c="t3.medium",minInstances:u=2,maxInstances:d=10,databaseEngine:g="mysql",sessionStore:y="redis"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",environments:{production:{type:"production",domain:o}},infrastructure:{network:{vpc:{cidr:"10.0.0.0/16",availabilityZones:2,natGateways:2}},compute:{server:{instanceType:c,ami:"ubuntu-22.04",autoScaling:{min:u,max:d,targetCPU:70,scaleUpCooldown:300,scaleDownCooldown:300},loadBalancer:{type:"application",healthCheck:{path:"/health",interval:30,timeout:5,healthyThreshold:2,unhealthyThreshold:3},stickySession:{enabled:!0,duration:86400}},userData:`#!/bin/bash
2455
2455
  # Install Node.js or PHP/Python based on app needs
2456
2456
  # Configure application server (PM2, Nginx, Apache)
2457
2457
  # Mount EFS for shared file storage
2458
- `}},storage:{uploads:{type:"efs",performanceMode:"generalPurpose",throughputMode:"bursting",encrypted:!0,lifecyclePolicy:{transitionToIA:30}},backups:{public:!1,versioning:!0,encryption:!0,lifecycleRules:[{id:"ArchiveOldBackups",enabled:!0,transitions:[{days:90,storageClass:"GLACIER"}]}]},static:{public:!0,versioning:!1,encryption:!1,cors:[{allowedOrigins:[o||"*"],allowedMethods:["GET","HEAD"]}]}},cdn:{enabled:!0,origins:[{originId:"static-assets",domainName:`${s}-static.s3.amazonaws.com`,pathPattern:"/static/*"}],customDomain:o?{domain:o,certificateArn:"TO_BE_GENERATED"}:void 0,cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0},databases:g==="mysql"?{mysql:{engine:"mysql",version:"8.0",instanceClass:"db.t3.medium",allocatedStorage:100,maxAllocatedStorage:500,multiAZ:!0,backupRetentionDays:14,preferredBackupWindow:"03:00-04:00",preferredMaintenanceWindow:"sun:04:00-sun:05:00",enablePerformanceInsights:!0,performanceInsightsRetention:7,deletionProtection:!0,parameters:{max_connections:"500",innodb_buffer_pool_size:"{DBInstanceClassMemory*3/4}",slow_query_log:"1",long_query_time:"2"}}}:{postgres:{engine:"postgres",version:"15",instanceClass:"db.t3.medium",allocatedStorage:100,maxAllocatedStorage:500,multiAZ:!0,backupRetentionDays:14,preferredBackupWindow:"03:00-04:00",preferredMaintenanceWindow:"sun:04:00-sun:05:00",enablePerformanceInsights:!0,performanceInsightsRetention:7,deletionProtection:!0,parameters:{max_connections:"500",shared_buffers:"{DBInstanceClassMemory/4}",log_min_duration_statement:"2000"}}},cache:y==="redis"?{redis:{nodeType:"cache.t3.medium",numCacheNodes:2,engine:"redis",engineVersion:"7.0",port:6379,parameterGroup:{maxmemoryPolicy:"allkeys-lru",timeout:"300"},snapshotRetentionLimit:5,snapshotWindow:"03:00-05:00",automaticFailoverEnabled:!0}}:void 0,queues:{jobs:{fifo:!1,visibilityTimeout:900,messageRetentionPeriod:345600,receiveMessageWaitTime:20,deadLetterQueue:!0,maxReceiveCount:3},emails:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:86400,deadLetterQueue:!0}},functions:{"job-worker":{runtime:"nodejs20.x",handler:"dist/workers/jobs.handler",memory:2048,timeout:900,events:[{type:"sqs",queueName:`${s}-jobs`,batchSize:10}]},"email-sender":{runtime:"nodejs20.x",handler:"dist/workers/email.handler",memory:512,timeout:60,events:[{type:"sqs",queueName:`${s}-emails`,batchSize:10}]},cleanup:{runtime:"nodejs20.x",handler:"dist/tasks/cleanup.handler",memory:512,timeout:300,events:[{type:"schedule",expression:"cron(0 2 * * ? *)"}]}},monitoring:{dashboard:{name:`${s}-web-app`,widgets:[{type:"metric",metrics:["EC2CPUUtilization","ALBRequestCount","ALBTargetResponseTime","RDSCPUUtilization","RDSDatabaseConnections","RDSReadLatency","RDSWriteLatency"]}]},alarms:[{metric:"EC2CPUUtilization",threshold:80,evaluationPeriods:2},{metric:"RDSCPUUtilization",threshold:80,evaluationPeriods:2},{metric:"RDSDatabaseConnections",threshold:400,evaluationPeriods:1},{metric:"ALBTargetResponseTime",threshold:2000,evaluationPeriods:2},{metric:"ALBUnhealthyHostCount",threshold:1,evaluationPeriods:1}],logs:{retention:14,groups:[`${s}-app`,`${s}-nginx`,`${s}-workers`]}},security:{certificate:o?{domain:o,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss","knownBadInputs"]},securityGroups:{alb:{ingress:[{port:80,protocol:"tcp",cidr:"0.0.0.0/0"},{port:443,protocol:"tcp",cidr:"0.0.0.0/0"}]},app:{ingress:[{port:3000,protocol:"tcp",source:"alb-sg"}]},database:{ingress:[{port:g==="mysql"?3306:5432,protocol:"tcp",source:"app-sg"}]},...y==="redis"&&{cache:{ingress:[{port:6379,protocol:"tcp",source:"app-sg"}]}}}}}}}function ub(n){let{name:i,slug:s,domain:o,repository:c,phpVersion:u="8.3",size:d="small",database:g=s.replace(/-/g,"_"),databasePassword:y,sslEmail:h,deployStrategy:A="push",provider:C="hetzner"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",cloud:{provider:C},environments:{production:{type:"production",domain:o}},infrastructure:{compute:{mode:"server",size:d,runtime:"php",webServer:"nginx",php:{versions:[u],default:u},managedServices:{mysql:!0,redis:!0},firewall:{enabled:!0},autoUpdates:!0,monitoring:!0,backups:{enabled:!0,schedule:"0 2 * * *",retentionCount:7}},appDatabase:{engine:"mysql",name:g,username:g,password:y}},sites:{main:{root:".",type:"laravel",domain:o,phpVersion:u,repository:{...c,strategy:A},scheduler:!0,queues:[{connection:"redis",queue:"default",processes:1}],ssl:{provider:"letsencrypt",email:h}}}}}function gb(n){let{name:i,slug:s,domain:o,layers:c,phpVersion:u="8.3",architecture:d="x86_64",memory:g=1024,build:y,deploy:h=["migrate --force"],cache:A="dynamodb",scheduler:C="on",region:v="us-east-1"}=n;return{project:{name:i,slug:s,region:v},mode:"serverless",environments:{production:{type:"production",domain:o,app:{kind:"php",runtime:"provided.al2023",phpVersion:u,architecture:d,layers:c,memory:g,build:y,deploy:h,assets:"public",queues:!0,scheduler:C,cache:{driver:A},domain:o}}}}}function pb(n){return{root:n.root??"packages/ui/dist",deploy:"server",type:"static",domain:n.domain,build:n.build??"cd packages/ui && bun install && bun run build",ssl:{provider:"letsencrypt"},auth:{username:n.username??"admin",password:n.password}}}var dy=rl,ly="./node_modules/@stacksjs/ts-cloud/dist/bin/dashboard-server.js";function ci(n){let i=n.split(".").filter(Boolean);return i.length<=2?n:i.slice(-2).join(".")}function li(n){let i=2166136261;for(let s=0;s<n.length;s++)i^=n.charCodeAt(s),i=Math.imul(i,16777619);return i>>>0}var uy=20000,gy=12000;function py(n){return uy+li(n)%gy}function Mn(n,i){let s=ci(n);if(s===n)return`dashboard.${s}`;for(let o of i)if(o===s)return`dashboard.${s}`;return`dashboard.${n}`}function Ln(n,i){let s=[],o=n.infrastructure?.dns?.domain;if(o&&!n.cloud?.attachTo)s.push(o);if(i&&n.environments?.[i]?.domain)s.push(n.environments[i].domain);for(let c of Object.values(n.sites??{})){let u=c;if(!u||u.redirect)continue;let d=u.domain;if(typeof d==="string")s.push(d);else if(Array.isArray(d))s.push(...d.filter((g)=>typeof g==="string"))}return s.filter((c)=>c&&!c.startsWith("dashboard."))}function my(n,i,s){if(s)return s;let o=Ln(n,i),c=o[0];if(!c)return null;return Mn(c,o)}function fy(n,i,s){if(s)return[s];let o=Ln(n,i),c=[];for(let u of o){let d=Mn(u,o);if(!c.includes(d))c.push(d)}return c}function pr(n){return Object.entries(n.sites??{}).some(([i,s])=>{if(!s)return!1;let o=s.root??"";return mr(i)||o==="ui/dist"||o.endsWith("/ui/dist")||o.endsWith("/dist/ui")})}var Om="dashboard-";function _m(n){return Om+n.replace(/^dashboard\./,"").replace(/\./g,"-")}function mr(n){return n==="dashboard"||n.startsWith(Om)}function Zi(n,i,s){if(pr(n))return[];if(n.cloud?.attachTo)return[];let o=s.password?{auth:{username:s.username||"admin",password:s.password,realm:s.realm}}:{},c=s.build===!1||s.build===void 0?{}:{build:s.build};if(s.live!==!1){let d=my(n,i,s.domain);if(!d)return[];let g=s.port??py(d),y=n.infrastructure?.appDatabase??n.infrastructure?.compute?.database,h={root:s.uiRoot,deploy:"server",domain:d,preStart:["bun install --production --no-save"],start:`bun ${ly} --box --host 127.0.0.1 --port ${g}`,port:g,cpuWeight:10,ioWeight:10,tasksMax:128,env:{APP_ENV:"production",NODE_ENV:"production",TS_CLOUD_DASHBOARD_TELEMETRY:"1",...y?.password?{TS_CLOUD_DASHBOARD_DB_PASSWORD:y.password}:{}},zeroDowntime:!1,sharedPaths:[dy],healthCheck:{path:"/login"},ssl:{provider:"letsencrypt"}};return[{name:_m(d),site:h}]}return fy(n,i,s.domain).map((d)=>({name:_m(d),site:{root:s.uiRoot,deploy:"server",type:"static",domain:d,ssl:{provider:"letsencrypt"},...c,...o}}))}function mb(n,i,s){return Zi(n,i,s)[0]??null}function Et(n,i){let s={...n};for(let o in i){let c=i[o],u=s[o];if(c===void 0)continue;if(Array.isArray(c)&&Array.isArray(u))s[o]=[...u,...c];else if(typeof c==="object"&&c!==null&&!Array.isArray(c)&&typeof u==="object"&&u!==null&&!Array.isArray(u))s[o]=Et(u,c);else s[o]=c}return s}function Lm(n,i){return Et(n,i)}function fb(...n){return n.reduce((i,s)=>Et(i,s),{})}function hb(n,i){return(s)=>{let o=n(s);if(typeof i==="function")return Lm(o,i(o,s));return Lm(o,i)}}function pn(n){return{infrastructure:n}}function Ab(n){return pn({monitoring:n})}function yb(n){return pn({security:n})}function Sb(n){return pn({databases:n})}function Ib(n){return pn({cache:n})}function bb(n){return pn({cdn:n})}function Cb(n){return pn({queues:n})}import{existsSync as On,readFileSync as wt}from"node:fs";import{homedir as $n}from"node:os";import{join as Bn}from"node:path";function hy(){let n=process.env.AWS_ACCESS_KEY_ID,i=process.env.AWS_SECRET_ACCESS_KEY;if(!n||!i)return null;return{accessKeyId:n,secretAccessKey:i,sessionToken:process.env.AWS_SESSION_TOKEN}}function Ay(n){let i=n?.profile||process.env.AWS_PROFILE||"default",s=n?.credentialsFile||Bn($n(),".aws","credentials");if(!On(s))return null;try{let o=wt(s,"utf-8");return ui(o,i)}catch{return null}}function ui(n,i){let s=n.split(`
2459
- `),o=null,c,u,d;for(let g of s){let y=g.trim();if(!y||y.startsWith("#")||y.startsWith(";"))continue;let h=y.match(/^\[([^\]]+)\]$/);if(h){if(o===i&&c&&u)return{accessKeyId:c,secretAccessKey:u,sessionToken:d};o=h[1],c=void 0,u=void 0,d=void 0;continue}if(o===i){let[A,...C]=y.split("="),v=C.join("=").trim();switch(A.trim().toLowerCase()){case"aws_access_key_id":c=v;break;case"aws_secret_access_key":u=v;break;case"aws_session_token":d=v;break}}}if(o===i&&c&&u)return{accessKeyId:c,secretAccessKey:u,sessionToken:d};return null}async function yy(n){let i=n?.timeout??1000,s="http://169.254.169.254";try{let o=await ze("http://169.254.169.254/latest/api/token",{method:"PUT",headers:{"X-aws-ec2-metadata-token-ttl-seconds":"21600"}},i);if(!o.ok)return null;let c=await o.text(),u=await ze("http://169.254.169.254/latest/meta-data/iam/security-credentials/",{headers:{"X-aws-ec2-metadata-token":c}},i);if(!u.ok)return null;let d=(await u.text()).trim(),g=await ze(`http://169.254.169.254/latest/meta-data/iam/security-credentials/${d}`,{headers:{"X-aws-ec2-metadata-token":c}},i);if(!g.ok)return null;let y=await g.json();return{accessKeyId:y.AccessKeyId,secretAccessKey:y.SecretAccessKey,sessionToken:y.Token,expiration:new Date(y.Expiration)}}catch{return null}}async function Sy(n){let i=n?.timeout??1000,s=process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI,o=process.env.AWS_CONTAINER_CREDENTIALS_FULL_URI,c=null;if(s)c=`http://169.254.170.2${s}`;else if(o)c=o;if(!c)return null;try{let u={},d=process.env.AWS_CONTAINER_AUTHORIZATION_TOKEN;if(d)u.Authorization=d;let g=await ze(c,{headers:u},i);if(!g.ok)return null;let y=await g.json();return{accessKeyId:y.AccessKeyId,secretAccessKey:y.SecretAccessKey,sessionToken:y.Token,expiration:new Date(y.Expiration)}}catch{return null}}async function Iy(n){let i=n?.timeout??5000,s=process.env.AWS_WEB_IDENTITY_TOKEN_FILE,o=process.env.AWS_ROLE_ARN,c=process.env.AWS_ROLE_SESSION_NAME||"ts-cloud-session";if(!s||!o)return null;try{let u=wt(s,"utf-8").trim(),d=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION||"us-east-1",g=d.startsWith("us-gov")?`https://sts.${d}.amazonaws.com`:d==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${d}.amazonaws.com`,y=new URLSearchParams({Action:"AssumeRoleWithWebIdentity",Version:"2011-06-15",RoleArn:o,RoleSessionName:c,WebIdentityToken:u}),h=await ze(`${g}/?${y.toString()}`,{method:"POST"},i);if(!h.ok)return null;let A=await h.text(),C=qe(A,"AccessKeyId"),v=qe(A,"SecretAccessKey"),T=qe(A,"SessionToken"),R=qe(A,"Expiration");if(!C||!v)return null;return{accessKeyId:C,secretAccessKey:v,sessionToken:T??void 0,expiration:R?new Date(R):void 0}}catch{return null}}async function es(n){let i=hy();if(i)return i;let s=Ay(n);if(s)return s;let o=await Iy(n);if(o)return o;let c=await Sy(n);if(c)return c;let u=await yy(n);if(u)return u;throw Error("Could not find AWS credentials. Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables, or configure ~/.aws/credentials, or run on an EC2 instance with an IAM role.")}function Eb(n){let i=null,s=null;return async()=>{if(i){if(!i.expiration)return i;let o=300000;if(i.expiration.getTime()-Date.now()>o)return i}if(s)return s;return s=es(n).then((o)=>(i=o,s=null,o)).catch((o)=>{throw s=null,o}),s}}async function ze(n,i,s){let o=new AbortController,c=setTimeout(()=>o.abort(),s);try{let u=await fetch(n,{...i,signal:o.signal});return clearTimeout(c),u}catch(u){throw clearTimeout(c),u}}function qe(n,i){let s=new RegExp(`<${i}>([^<]+)</${i}>`),o=n.match(s);return o?o[1]:null}async function zo(n){return es({profile:n})}function by(n){let i=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION;if(i)return i;let s=Bn($n(),".aws","config");if(On(s))try{let o=wt(s,"utf-8"),c=n||process.env.AWS_PROFILE||"default",u=c==="default"?"[default]":`[profile ${c}]`,d=o.split(`
2460
- `),g=!1;for(let y of d){let h=y.trim();if(h.startsWith("[")){g=h===u;continue}if(g&&h.startsWith("region")){let[,A]=h.split("=");if(A)return A.trim()}}}catch{}return"us-east-1"}async function $m(n){let i=n||await es(),s=by(),{signRequest:o}=await import("./chunk-ypsfkgme.js"),c=s.startsWith("us-gov")?`https://sts.${s}.amazonaws.com`:s==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${s}.amazonaws.com`,u="Action=GetCallerIdentity&Version=2011-06-15",d=o({method:"POST",url:c,body:"Action=GetCallerIdentity&Version=2011-06-15",headers:{"Content-Type":"application/x-www-form-urlencoded"},...i,service:"sts",region:s}),g=await fetch(d.url,{method:d.method,headers:d.headers,body:d.body});if(!g.ok)throw Error(`Failed to get account ID: ${await g.text()}`);let y=await g.text(),h=qe(y,"Account");if(!h)throw Error("Failed to parse account ID from response");return h}var mi=5242880,It=5242880;var pi=5242880;class Dt{region;endpoint;forcePathStyle;credentials;credentialOptions;retryOptions;constructor(n={}){this.region=n.region||process.env.AWS_REGION||"us-east-1",this.endpoint=n.endpoint||`https://s3.${this.region}.amazonaws.com`,this.forcePathStyle=n.forcePathStyle||!1,this.credentials=n.credentials,this.credentialOptions=n.credentialOptions,this.retryOptions=n.retryOptions||{}}async getCredentials(){if(this.credentials)return this.credentials;return es(this.credentialOptions)}buildUrl(n,i){let s=i?encodeURIComponent(i).replace(/%2F/g,"/"):"";if(this.forcePathStyle)return i?`${this.endpoint}/${n}/${s}`:`${this.endpoint}/${n}`;let o=new URL(this.endpoint);return o.hostname=`${n}.${o.hostname}`,i?`${o.origin}/${s}`:o.origin}async get(n,i,s={}){let o=await this.getCredentials(),c=this.buildUrl(n,i),u={};if(s.range)u.Range=s.range;if(s.ifModifiedSince)u["If-Modified-Since"]=s.ifModifiedSince.toUTCString();if(s.ifMatch)u["If-Match"]=s.ifMatch;if(s.ifNoneMatch)u["If-None-Match"]=s.ifNoneMatch;let d=new URL(c);if(s.responseContentType)d.searchParams.set("response-content-type",s.responseContentType);if(s.responseContentDisposition)d.searchParams.set("response-content-disposition",s.responseContentDisposition);let g=k({method:"GET",url:d.toString(),headers:u,...o,service:"s3",region:this.region}),y=await fetch(g.url,{method:g.method,headers:g.headers});if(!y.ok&&y.status!==304){let h=await y.text();throw new V(`Failed to get object: ${h}`,y.status,n,i)}return y}async getText(n,i,s={}){return(await this.get(n,i,s)).text()}async getJSON(n,i,s={}){return(await this.get(n,i,s)).json()}async getBuffer(n,i,s={}){return(await this.get(n,i,s)).arrayBuffer()}async put(n,i,s,o={}){let c,u;if(typeof s==="string")c=new TextEncoder().encode(s).length,u=s;else if(s instanceof ArrayBuffer)c=s.byteLength,u=s;else if(s instanceof Uint8Array)c=s.byteLength,u=s;else if(s instanceof Blob)c=s.size,u=s;else return this.uploadMultipart(n,i,s,{...o,partSize:It});if(c>pi){let d=fi(u).stream();return this.uploadMultipart(n,i,d,{...o,partSize:It})}return this.putSimple(n,i,u,c,o)}async putSimple(n,i,s,o,c){let u=await this.getCredentials(),d=this.buildUrl(n,i),g={"Content-Length":String(o),"Content-Type":c.contentType||Fn(i)};if(c.contentEncoding)g["Content-Encoding"]=c.contentEncoding;if(c.cacheControl)g["Cache-Control"]=c.cacheControl;if(c.contentDisposition)g["Content-Disposition"]=c.contentDisposition;if(c.storageClass)g["x-amz-storage-class"]=c.storageClass;if(c.serverSideEncryption)g["x-amz-server-side-encryption"]=c.serverSideEncryption;if(c.acl)g["x-amz-acl"]=c.acl;if(c.tagging)g["x-amz-tagging"]=c.tagging;if(c.metadata)for(let[v,T]of Object.entries(c.metadata))g[`x-amz-meta-${v.toLowerCase()}`]=T;let y;if(typeof s==="string")y=s;else if(s instanceof Blob)y=await s.text();else y=new TextDecoder().decode(s instanceof ArrayBuffer?new Uint8Array(s):s);let h=k({method:"PUT",url:d,headers:g,body:y,...u,service:"s3",region:this.region}),A=await fetch(h.url,{method:h.method,headers:h.headers,body:s});if(!A.ok){let v=await A.text();throw new V(`Failed to put object: ${v}`,A.status,n,i)}return{etag:(A.headers.get("ETag")||"").replace(/"/g,"")}}async delete(n,i){let s=await this.getCredentials(),o=this.buildUrl(n,i),c=k({method:"DELETE",url:o,...s,service:"s3",region:this.region}),u=await fetch(c.url,{method:c.method,headers:c.headers});if(!u.ok&&u.status!==204){let d=await u.text();throw new V(`Failed to delete object: ${d}`,u.status,n,i)}}async deleteMany(n,i){let s=await this.getCredentials(),o=`${this.buildUrl(n)}?delete`,u=`<?xml version="1.0" encoding="UTF-8"?><Delete><Quiet>false</Quiet>${i.map((R)=>`<Object><Key>${yi(R)}</Key></Object>`).join("")}</Delete>`,d=k({method:"POST",url:o,headers:{"Content-Type":"application/xml"},body:u,...s,service:"s3",region:this.region}),g=await fetch(d.url,{method:d.method,headers:d.headers,body:u});if(!g.ok){let R=await g.text();throw new V(`Failed to delete objects: ${R}`,g.status,n)}let y=await g.text(),h=[],A=[],C=/<Deleted><Key>([^<]+)<\/Key>/g,v;while((v=C.exec(y))!==null)h.push(v[1]);let T=/<Error><Key>([^<]+)<\/Key><Code>([^<]+)<\/Code><Message>([^<]+)<\/Message>/g;while((v=T.exec(y))!==null)A.push({key:v[1],error:`${v[2]}: ${v[3]}`});return{deleted:h,errors:A}}async list(n,i={}){let s=await this.getCredentials(),o=new URL(this.buildUrl(n));if(o.searchParams.set("list-type","2"),i.prefix)o.searchParams.set("prefix",i.prefix);if(i.delimiter)o.searchParams.set("delimiter",i.delimiter);if(i.maxKeys)o.searchParams.set("max-keys",String(i.maxKeys));if(i.continuationToken)o.searchParams.set("continuation-token",i.continuationToken);if(i.startAfter)o.searchParams.set("start-after",i.startAfter);let c=k({method:"GET",url:o.toString(),...s,service:"s3",region:this.region}),u=await fetch(c.url,{method:c.method,headers:c.headers});if(!u.ok){let g=await u.text();throw new V(`Failed to list objects: ${g}`,u.status,n)}let d=await u.text();return gi(d)}async*listAll(n,i={}){let s;do{let o=await this.list(n,{...i,continuationToken:s});for(let c of o.contents)yield c;s=o.nextContinuationToken}while(s)}async head(n,i){let s=await this.getCredentials(),o=this.buildUrl(n,i),c=k({method:"HEAD",url:o,...s,service:"s3",region:this.region}),u=await fetch(c.url,{method:c.method,headers:c.headers});if(u.status===404)return null;if(!u.ok){let g=await u.text();throw new V(`Failed to head object: ${g}`,u.status,n,i)}let d={};return u.headers.forEach((g,y)=>{if(y.toLowerCase().startsWith("x-amz-meta-"))d[y.slice(11)]=g}),{contentLength:Number(u.headers.get("Content-Length")||0),contentType:u.headers.get("Content-Type")||"application/octet-stream",etag:(u.headers.get("ETag")||"").replace(/"/g,""),lastModified:new Date(u.headers.get("Last-Modified")||0),metadata:d,storageClass:u.headers.get("x-amz-storage-class")||void 0,serverSideEncryption:u.headers.get("x-amz-server-side-encryption")||void 0}}async exists(n,i){return await this.head(n,i)!==null}async copy(n,i,s,o,c={}){let u=await this.getCredentials(),d=this.buildUrl(s,o),g={"x-amz-copy-source":`/${n}/${encodeURIComponent(i)}`};if(c.metadataDirective)g["x-amz-metadata-directive"]=c.metadataDirective;if(c.contentType)g["Content-Type"]=c.contentType;if(c.storageClass)g["x-amz-storage-class"]=c.storageClass;if(c.acl)g["x-amz-acl"]=c.acl;if(c.metadata)for(let[T,R]of Object.entries(c.metadata))g[`x-amz-meta-${T.toLowerCase()}`]=R;let y=k({method:"PUT",url:d,headers:g,...u,service:"s3",region:this.region}),h=await fetch(y.url,{method:y.method,headers:y.headers});if(!h.ok){let T=await h.text();throw new V(`Failed to copy object: ${T}`,h.status,s,o)}let C=(await h.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:C?C[1]:""}}async getPresignedUrl(n,i,s={}){let o=await this.getCredentials(),c=this.buildUrl(n,i);return na({url:c,method:s.method||"GET",expiresIn:s.expiresIn||3600,...o,service:"s3",region:this.region})}async uploadMultipart(n,i,s,o={}){let c=await this.getCredentials(),u=Math.max(o.partSize||It,mi),d,g;if(s instanceof ReadableStream)d=s;else if(s instanceof Blob)d=s.stream(),g=s.size;else{let A=new Blob([s]);d=A.stream(),g=A.size}let{uploadId:y,baseUrl:h}=await this.initiateMultipartUpload(n,i,o);try{let A=await this.uploadParts(n,i,h,y,d,u,c,g,o.concurrency||4,o.onProgress);return await this.completeMultipartUpload(n,i,h,y,A)}catch(A){throw await this.abortMultipartUpload(n,i,y,h).catch(()=>{}),A}}async initiateMultipartUpload(n,i,s){let o=await this.getCredentials(),c=this.buildUrl(n,i),u=`${c}?uploads`,d={"Content-Type":s.contentType||Fn(i)};if(s.storageClass)d["x-amz-storage-class"]=s.storageClass;if(s.serverSideEncryption)d["x-amz-server-side-encryption"]=s.serverSideEncryption;if(s.acl)d["x-amz-acl"]=s.acl;if(s.metadata)for(let[v,T]of Object.entries(s.metadata))d[`x-amz-meta-${v.toLowerCase()}`]=T;let g=k({method:"POST",url:u,headers:d,...o,service:"s3",region:this.region}),y=await fetch(g.url,{method:g.method,headers:g.headers});if(!y.ok){let v=await y.text();throw new V(`Failed to initiate multipart upload: ${v}`,y.status,n,i)}let A=(await y.text()).match(/<UploadId>([^<]+)<\/UploadId>/);if(!A)throw new V("Failed to parse upload ID from response",0,n,i);let C=c;if(y.url)try{let v=new URL(y.url);v.search="",C=v.toString()}catch{}return{uploadId:A[1],baseUrl:C}}async uploadParts(n,i,s,o,c,u,d,g,y,h){let A=[],C=c.getReader(),v=1,T=new Uint8Array(0),R=0,P=g?Math.ceil(g/u):void 0,I=new Map,M=async(N,O)=>{let B=`${s}?partNumber=${O}&uploadId=${encodeURIComponent(o)}`,F={"Content-Length":String(N.byteLength),"x-amz-content-sha256":"UNSIGNED-PAYLOAD"},U=k({method:"PUT",url:B,headers:F,...d,service:"s3",region:this.region}),j=await fetch(U.url,{method:U.method,headers:U.headers,body:N,redirect:"error"});if(!j.ok){let z=await j.text();throw new V(`Failed to upload part ${O}: ${z}`,j.status,n,i)}let H=(j.headers.get("ETag")||"").replace(/"/g,"");if(!H)throw new V(`Missing ETag for part ${O}`,j.status,n,i);return{partNumber:O,etag:H}},L=async()=>{let N=await Promise.race(I.values());I.delete(N.partNumber),A.push(N)};while(!0){let{done:N,value:O}=await C.read();if(O){let B=new Uint8Array(T.length+O.length);B.set(T),B.set(O,T.length),T=B}while(T.length>=u||N&&T.length>0){let B=T.slice(0,u);T=T.slice(u);let F=v++;if(I.size>=y)await L();if(I.set(F,M(B,F)),R+=B.byteLength,h)h({loaded:R,total:g||R,part:F,totalParts:P||F})}if(N)break}while(I.size>0)await L();return A.sort((N,O)=>N.partNumber-O.partNumber),A}async completeMultipartUpload(n,i,s,o,c){let u=await this.getCredentials(),d=`${s}?uploadId=${encodeURIComponent(o)}`,y=`<?xml version="1.0" encoding="UTF-8"?><CompleteMultipartUpload>${c.map((R)=>`<Part><PartNumber>${R.partNumber}</PartNumber><ETag>"${R.etag}"</ETag></Part>`).join("")}</CompleteMultipartUpload>`,h=k({method:"POST",url:d,headers:{"Content-Type":"application/xml"},body:y,...u,service:"s3",region:this.region}),A=await fetch(h.url,{method:h.method,headers:h.headers,body:y});if(!A.ok){let R=await A.text();throw new V(`Failed to complete multipart upload: ${R}`,A.status,n,i)}let v=(await A.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:v?v[1]:""}}async abortMultipartUpload(n,i,s,o){let c=await this.getCredentials(),u=`${o??this.buildUrl(n,i)}?uploadId=${encodeURIComponent(s)}`,d=k({method:"DELETE",url:u,...c,service:"s3",region:this.region});await fetch(d.url,{method:d.method,headers:d.headers})}async emptyAndDeleteBucket(n){let s=[];for await(let d of this.listAll(n,{}))if(s.push(d.key),s.length>=1000)await this.deleteMany(n,s),s=[];if(s.length>0)await this.deleteMany(n,s);let o=await this.getCredentials(),c=this.buildUrl(n),u=k({method:"DELETE",url:c,...o,service:"s3",region:this.region});await fetch(u.url,{method:u.method,headers:u.headers})}}class V extends Error{statusCode;bucket;key;constructor(n,i,s,o){super(n);this.statusCode=i;this.bucket=s;this.key=o;this.name="S3Error"}}function gi(n){let i=[],s=[],o=/<Contents>([\s\S]*?)<\/Contents>/g,c;while((c=o.exec(n))!==null){let d=c[1];i.push({key:me(d,"Key")||"",lastModified:new Date(me(d,"LastModified")||0),etag:(me(d,"ETag")||"").replace(/"/g,""),size:Number(me(d,"Size")||0),storageClass:me(d,"StorageClass")||"STANDARD"})}let u=/<CommonPrefixes><Prefix>([^<]+)<\/Prefix><\/CommonPrefixes>/g;while((c=u.exec(n))!==null)s.push(c[1]);return{contents:i,commonPrefixes:s,isTruncated:me(n,"IsTruncated")==="true",continuationToken:me(n,"ContinuationToken")||void 0,nextContinuationToken:me(n,"NextContinuationToken")||void 0,keyCount:Number(me(n,"KeyCount")||0),maxKeys:Number(me(n,"MaxKeys")||1000),prefix:me(n,"Prefix")||void 0,delimiter:me(n,"Delimiter")||void 0}}function me(n,i){let s=new RegExp(`<${i}>([^<]*)</${i}>`),o=n.match(s);return o?o[1]:null}function yi(n){return n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function Fn(n){let i=n.split(".").pop()?.toLowerCase();return{html:"text/html",htm:"text/html",css:"text/css",js:"application/javascript",mjs:"application/javascript",json:"application/json",xml:"application/xml",txt:"text/plain",md:"text/markdown",csv:"text/csv",jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",gif:"image/gif",webp:"image/webp",svg:"image/svg+xml",ico:"image/x-icon",avif:"image/avif",mp4:"video/mp4",webm:"video/webm",mov:"video/quicktime",avi:"video/x-msvideo",mp3:"audio/mpeg",wav:"audio/wav",ogg:"audio/ogg",pdf:"application/pdf",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xls:"application/vnd.ms-excel",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",ppt:"application/vnd.ms-powerpoint",pptx:"application/vnd.openxmlformats-officedocument.presentationml.presentation",zip:"application/zip",gz:"application/gzip",tar:"application/x-tar",rar:"application/vnd.rar","7z":"application/x-7z-compressed",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf",otf:"font/otf",eot:"application/vnd.ms-fontobject",wasm:"application/wasm"}[i||""]||"application/octet-stream"}function fi(n){if(n instanceof Blob)return n;if(typeof n==="string")return new Blob([n],{type:"text/plain"});return new Blob([n])}function Cy(n){return new Dt(n)}class nt extends Error{code;solution;details;constructor(n,i,s,o){super(n);this.code=i;this.solution=s;this.details=o;this.name="CloudError",Error.captureStackTrace?.(this,nt)}toString(){let n=`${this.name} [${this.code}]: ${this.message}`;if(this.solution)n+=`
2458
+ `}},storage:{uploads:{type:"efs",performanceMode:"generalPurpose",throughputMode:"bursting",encrypted:!0,lifecyclePolicy:{transitionToIA:30}},backups:{public:!1,versioning:!0,encryption:!0,lifecycleRules:[{id:"ArchiveOldBackups",enabled:!0,transitions:[{days:90,storageClass:"GLACIER"}]}]},static:{public:!0,versioning:!1,encryption:!1,cors:[{allowedOrigins:[o||"*"],allowedMethods:["GET","HEAD"]}]}},cdn:{enabled:!0,origins:[{originId:"static-assets",domainName:`${s}-static.s3.amazonaws.com`,pathPattern:"/static/*"}],customDomain:o?{domain:o,certificateArn:"TO_BE_GENERATED"}:void 0,cachePolicy:{minTTL:0,defaultTTL:86400,maxTTL:31536000},compress:!0,http3:!0},databases:g==="mysql"?{mysql:{engine:"mysql",version:"8.0",instanceClass:"db.t3.medium",allocatedStorage:100,maxAllocatedStorage:500,multiAZ:!0,backupRetentionDays:14,preferredBackupWindow:"03:00-04:00",preferredMaintenanceWindow:"sun:04:00-sun:05:00",enablePerformanceInsights:!0,performanceInsightsRetention:7,deletionProtection:!0,parameters:{max_connections:"500",innodb_buffer_pool_size:"{DBInstanceClassMemory*3/4}",slow_query_log:"1",long_query_time:"2"}}}:{postgres:{engine:"postgres",version:"15",instanceClass:"db.t3.medium",allocatedStorage:100,maxAllocatedStorage:500,multiAZ:!0,backupRetentionDays:14,preferredBackupWindow:"03:00-04:00",preferredMaintenanceWindow:"sun:04:00-sun:05:00",enablePerformanceInsights:!0,performanceInsightsRetention:7,deletionProtection:!0,parameters:{max_connections:"500",shared_buffers:"{DBInstanceClassMemory/4}",log_min_duration_statement:"2000"}}},cache:y==="redis"?{redis:{nodeType:"cache.t3.medium",numCacheNodes:2,engine:"redis",engineVersion:"7.0",port:6379,parameterGroup:{maxmemoryPolicy:"allkeys-lru",timeout:"300"},snapshotRetentionLimit:5,snapshotWindow:"03:00-05:00",automaticFailoverEnabled:!0}}:void 0,queues:{jobs:{fifo:!1,visibilityTimeout:900,messageRetentionPeriod:345600,receiveMessageWaitTime:20,deadLetterQueue:!0,maxReceiveCount:3},emails:{fifo:!1,visibilityTimeout:300,messageRetentionPeriod:86400,deadLetterQueue:!0}},functions:{"job-worker":{runtime:"nodejs20.x",handler:"dist/workers/jobs.handler",memory:2048,timeout:900,events:[{type:"sqs",queueName:`${s}-jobs`,batchSize:10}]},"email-sender":{runtime:"nodejs20.x",handler:"dist/workers/email.handler",memory:512,timeout:60,events:[{type:"sqs",queueName:`${s}-emails`,batchSize:10}]},cleanup:{runtime:"nodejs20.x",handler:"dist/tasks/cleanup.handler",memory:512,timeout:300,events:[{type:"schedule",expression:"cron(0 2 * * ? *)"}]}},monitoring:{dashboard:{name:`${s}-web-app`,widgets:[{type:"metric",metrics:["EC2CPUUtilization","ALBRequestCount","ALBTargetResponseTime","RDSCPUUtilization","RDSDatabaseConnections","RDSReadLatency","RDSWriteLatency"]}]},alarms:[{metric:"EC2CPUUtilization",threshold:80,evaluationPeriods:2},{metric:"RDSCPUUtilization",threshold:80,evaluationPeriods:2},{metric:"RDSDatabaseConnections",threshold:400,evaluationPeriods:1},{metric:"ALBTargetResponseTime",threshold:2000,evaluationPeriods:2},{metric:"ALBUnhealthyHostCount",threshold:1,evaluationPeriods:1}],logs:{retention:14,groups:[`${s}-app`,`${s}-nginx`,`${s}-workers`]}},security:{certificate:o?{domain:o,validationMethod:"DNS"}:void 0,waf:{enabled:!0,rules:["rateLimit","sqlInjection","xss","knownBadInputs"]},securityGroups:{alb:{ingress:[{port:80,protocol:"tcp",cidr:"0.0.0.0/0"},{port:443,protocol:"tcp",cidr:"0.0.0.0/0"}]},app:{ingress:[{port:3000,protocol:"tcp",source:"alb-sg"}]},database:{ingress:[{port:g==="mysql"?3306:5432,protocol:"tcp",source:"app-sg"}]},...y==="redis"&&{cache:{ingress:[{port:6379,protocol:"tcp",source:"app-sg"}]}}}}}}}function Eb(n){let{name:i,slug:s,domain:o,repository:c,phpVersion:u="8.3",size:d="small",database:g=s.replace(/-/g,"_"),databasePassword:y,sslEmail:h,deployStrategy:A="push",provider:C="hetzner"}=n;return{project:{name:i,slug:s,region:"us-east-1"},mode:"server",cloud:{provider:C},environments:{production:{type:"production",domain:o}},infrastructure:{compute:{mode:"server",size:d,runtime:"php",webServer:"nginx",php:{versions:[u],default:u},managedServices:{mysql:!0,redis:!0},firewall:{enabled:!0},autoUpdates:!0,monitoring:!0,backups:{enabled:!0,schedule:"0 2 * * *",retentionCount:7}},appDatabase:{engine:"mysql",name:g,username:g,password:y}},sites:{main:{root:".",type:"laravel",domain:o,phpVersion:u,repository:{...c,strategy:A},scheduler:!0,queues:[{connection:"redis",queue:"default",processes:1}],ssl:{provider:"letsencrypt",email:h}}}}}function vb(n){let{name:i,slug:s,domain:o,layers:c,phpVersion:u="8.3",architecture:d="x86_64",memory:g=1024,build:y,deploy:h=["migrate --force"],cache:A="dynamodb",scheduler:C="on",region:v="us-east-1"}=n;return{project:{name:i,slug:s,region:v},mode:"serverless",environments:{production:{type:"production",domain:o,app:{kind:"php",runtime:"provided.al2023",phpVersion:u,architecture:d,layers:c,memory:g,build:y,deploy:h,assets:"public",queues:!0,scheduler:C,cache:{driver:A},domain:o}}}}}function Tb(n){return{root:n.root??"packages/ui/dist",deploy:"server",type:"static",domain:n.domain,build:n.build??"cd packages/ui && bun install && bun run build",ssl:{provider:"letsencrypt"},auth:{username:n.username??"admin",password:n.password}}}var Sy=ul,Iy="./node_modules/@stacksjs/ts-cloud/dist/bin/dashboard-server.js";function vi(n){let i=n.split(".").filter(Boolean);return i.length<=2?n:i.slice(-2).join(".")}function Ti(n){let i=2166136261;for(let s=0;s<n.length;s++)i^=n.charCodeAt(s),i=Math.imul(i,16777619);return i>>>0}var by=20000,Cy=12000;function Ey(n){return by+Ti(n)%Cy}function Gn(n,i){let s=vi(n);if(s===n)return`dashboard.${s}`;for(let o of i)if(o===s)return`dashboard.${s}`;return`dashboard.${n}`}function _n(n,i){let s=[],o=n.infrastructure?.dns?.domain;if(o&&!n.cloud?.attachTo)s.push(o);if(i&&n.environments?.[i]?.domain)s.push(n.environments[i].domain);for(let c of Object.values(n.sites??{})){let u=c;if(!u||u.redirect)continue;let d=u.domain;if(typeof d==="string")s.push(d);else if(Array.isArray(d))s.push(...d.filter((g)=>typeof g==="string"))}return s.filter((c)=>c&&!c.startsWith("dashboard."))}function vy(n,i,s){if(s)return s;let o=_n(n,i),c=o[0];if(!c)return null;return Gn(c,o)}function Ty(n,i,s){if(s)return[s];let o=_n(n,i),c=[];for(let u of o){let d=Gn(u,o);if(!c.includes(d))c.push(d)}return c}function mr(n){return Object.entries(n.sites??{}).some(([i,s])=>{if(!s)return!1;let o=s.root??"";return fr(i)||o==="ui/dist"||o.endsWith("/ui/dist")||o.endsWith("/dist/ui")})}var Gm="dashboard-";function Vm(n){return Gm+n.replace(/^dashboard\./,"").replace(/\./g,"-")}function fr(n){return n==="dashboard"||n.startsWith(Gm)}function ts(n,i,s){if(mr(n))return[];if(n.cloud?.attachTo)return[];let o=s.password?{auth:{username:s.username||"admin",password:s.password,realm:s.realm}}:{},c=s.build===!1||s.build===void 0?{}:{build:s.build};if(s.live!==!1){let d=vy(n,i,s.domain);if(!d)return[];let g=s.port??Ey(d),y=n.infrastructure?.appDatabase??n.infrastructure?.compute?.database,h={root:s.uiRoot,deploy:"server",domain:d,preStart:["bun install --production --no-save"],start:`bun ${Iy} --box --host 127.0.0.1 --port ${g}`,port:g,cpuWeight:10,ioWeight:10,tasksMax:128,env:{APP_ENV:"production",NODE_ENV:"production",TS_CLOUD_DASHBOARD_TELEMETRY:"1",...y?.password?{TS_CLOUD_DASHBOARD_DB_PASSWORD:y.password}:{}},zeroDowntime:!1,sharedPaths:[Sy],healthCheck:{path:"/login"},ssl:{provider:"letsencrypt"}};return[{name:Vm(d),site:h}]}return Ty(n,i,s.domain).map((d)=>({name:Vm(d),site:{root:s.uiRoot,deploy:"server",type:"static",domain:d,ssl:{provider:"letsencrypt"},...c,...o}}))}function wb(n,i,s){return ts(n,i,s)[0]??null}function It(n,i){let s={...n};for(let o in i){let c=i[o],u=s[o];if(c===void 0)continue;if(Array.isArray(c)&&Array.isArray(u))s[o]=[...u,...c];else if(typeof c==="object"&&c!==null&&!Array.isArray(c)&&typeof u==="object"&&u!==null&&!Array.isArray(u))s[o]=It(u,c);else s[o]=c}return s}function qm(n,i){return It(n,i)}function Rb(...n){return n.reduce((i,s)=>It(i,s),{})}function Db(n,i){return(s)=>{let o=n(s);if(typeof i==="function")return qm(o,i(o,s));return qm(o,i)}}function mn(n){return{infrastructure:n}}function Pb(n){return mn({monitoring:n})}function kb(n){return mn({security:n})}function Nb(n){return mn({databases:n})}function Bb(n){return mn({cache:n})}function xb(n){return mn({cdn:n})}function Ob(n){return mn({queues:n})}import{readFileSync as Mi}from"node:fs";import{spawn as Ri,spawnSync as Pi}from"node:child_process";import{existsSync as Ei,readFileSync as wi}from"node:fs";import{homedir as Dt}from"node:os";import{join as kt}from"node:path";var jm=30000,Ii=300000,Un=1048576;class k extends Error{code="CredentialProcessError";profile;command;constructor(n,i,s){super(`AWS profile "${n}": credential_process \`${i}\` ${s}`);this.name="CredentialProcessError",this.profile=n,this.command=i}}function Hn(n){return n==="~"||n.startsWith("~/")?kt(Dt(),n.slice(1)):n}function Te(n){return n||process.env.AWS_PROFILE||process.env.AWS_DEFAULT_PROFILE||"default"}function rs(n){return Hn(n||process.env.AWS_SHARED_CREDENTIALS_FILE||kt(Dt(),".aws","credentials"))}function Zo(n){return Hn(n||process.env.AWS_CONFIG_FILE||kt(Dt(),".aws","config"))}function Di(n){let i=new Map,s=null;for(let o of n.replace(/^/,"").split(/\r?\n/)){let c=o.trim();if(!c||c.startsWith("#")||c.startsWith(";"))continue;let u=c.match(/^\[([^\]]+)\]/);if(u){let g=u[1].trim();s=i.get(g)??{},i.set(g,s);continue}let d=c.indexOf("=");if(s&&d>0)s[c.slice(0,d).trim().toLowerCase()]=c.slice(d+1).trim()}return i}function Wn(n){if(!Ei(n))return new Map;try{return Di(wi(n,"utf-8"))}catch{return new Map}}function Ni(n,i){if(i==="default")return n.get("default")??n.get("profile default");for(let[s,o]of n){let c=s.match(/^profile\s+(.+)$/);if(c&&c[1].trim()===i)return o}return}function fn(n){let i=Te(n?.profile),s=Ni(Wn(Zo(n?.configFile)),i),o=Wn(rs(n?.credentialsFile)).get(i);if(!s&&!o)return;return{...s,...o}}function Mt(n){let i=n?.aws_access_key_id,s=n?.aws_secret_access_key;if(!i||!s)return null;return{accessKeyId:i,secretAccessKey:s,sessionToken:n?.aws_session_token||void 0}}function ns(n){return Mt(fn(n))}function ea(n){return fn(n)?.credential_process||null}function wy(n,i=process.platform){let s=[],o="",c=!1,u=null;for(let d=0;d<n.length;d++){let g=n[d];if(u==="'"){if(g==="'")u=null;else o+=g;continue}if(u==='"'){if(g==='"')u=null;else if(g==="\\"&&(n[d+1]==='"'||n[d+1]==="\\"||i!=="win32"&&(n[d+1]==="$"||n[d+1]==="`")))o+=n[++d];else o+=g;continue}if(g==="'"||g==='"')u=g,c=!0;else if(g==="\\"&&i!=="win32"&&d+1<n.length)o+=n[++d],c=!0;else if(/\s/.test(g)){if(c)s.push(o),o="",c=!1}else o+=g,c=!0}if(u)throw Error("unterminated quote");if(c)s.push(o);return s}function jn(n){let i=n.replace(/\s+/g," ").trim();return i.length>200?`${i.slice(0,200)}...`:i}function Kn(n,i,s){let o;try{o=JSON.parse(n)}catch{throw new k(i,s,"printed output that is not valid JSON")}if(!o||typeof o!=="object"||Array.isArray(o))throw new k(i,s,"printed JSON that is not an object");let c=o;if(c.Version!==1)throw new k(i,s,'printed JSON without "Version": 1');let{AccessKeyId:u,SecretAccessKey:d,SessionToken:g,Expiration:y}=c;if(typeof u!=="string"||!u||typeof d!=="string"||!d)throw new k(i,s,"printed JSON without AccessKeyId and SecretAccessKey");if(g!==void 0&&g!==null&&typeof g!=="string")throw new k(i,s,"printed a SessionToken that is not a string");let h;if(y!==void 0&&y!==null){if(h=typeof y==="string"?new Date(y):void 0,!h||Number.isNaN(h.getTime()))throw new k(i,s,"printed an Expiration that is not a date")}return{accessKeyId:u,secretAccessKey:d,sessionToken:typeof g==="string"&&g?g:void 0,expiration:h}}function qn(n){return n>=1000&&n%1000===0?`${n/1000}s`:`${n}ms`}function zn(n,i){let s;try{s=wy(i)}catch(o){throw new k(n,i,`could not be parsed (${o.message})`)}if(s.length===0)throw new k(n,i,"is empty");return s}function Vn(n,i){try{if(n&&process.platform!=="win32")process.kill(-n,"SIGKILL");else i()}catch{try{i()}catch{}}}function xi(n,i,s){let o=zn(n,i);return new Promise((c,u)=>{let d=!1,g=[],y=0,h="",A=Ri(o[0],o.slice(1),{stdio:["ignore","pipe","pipe"],detached:process.platform!=="win32",windowsHide:!0}),C=(T)=>{if(d)return;d=!0,clearTimeout(v),A.stdout?.destroy(),A.stderr?.destroy(),T()},v=setTimeout(()=>{Vn(A.pid,()=>A.kill("SIGKILL")),C(()=>u(new k(n,i,`timed out after ${qn(s)} and was killed`)))},s);A.on("error",(T)=>{C(()=>u(new k(n,i,`could not be started (${T.code??"spawn error"})`)))}),A.stdout?.on("data",(T)=>{if(y+=T.length,y>Un){Vn(A.pid,()=>A.kill("SIGKILL")),C(()=>u(new k(n,i,"printed more than 1 MiB")));return}g.push(T)}),A.stderr?.on("data",(T)=>{if(h.length<2000)h+=T.toString("utf-8")}),A.on("close",(T,R)=>{C(()=>{if(T!==0){let P=jn(h),I=T===null?`was stopped by ${R}`:`exited with code ${T}`;u(new k(n,i,P?`${I}: ${P}`:I));return}c(Buffer.concat(g).toString("utf-8"))})})})}function ki(n,i,s){let o=zn(n,i),c=Pi(o[0],o.slice(1),{stdio:["ignore","pipe","pipe"],timeout:s,killSignal:"SIGKILL",maxBuffer:Un,windowsHide:!0}),u=c.error?.code;if(u==="ETIMEDOUT")throw new k(n,i,`timed out after ${qn(s)} and was killed`);if(u==="ENOBUFS")throw new k(n,i,"printed more than 1 MiB");if(c.error)throw new k(n,i,`could not be started (${u??"spawn error"})`);if(c.status!==0){let d=jn(c.stderr?.toString("utf-8")??""),g=c.status===null?`was stopped by ${c.signal}`:`exited with code ${c.status}`;throw new k(n,i,d?`${g}: ${d}`:g)}return c.stdout.toString("utf-8")}var Lt=new Map,dt=new Map;function Qn(n,i){return`${n}\x00${i}`}function Jn(n){let i=Lt.get(n);return i&&Date.now()<i.refreshAt?i.credentials:null}function Yn(n,i){Lt.set(n,{credentials:i,refreshAt:i.expiration?i.expiration.getTime()-Ii:Number.POSITIVE_INFINITY})}function _b(){Lt.clear(),dt.clear()}async function is(n){let i=Te(n?.profile),s=fn({...n,profile:i}),o=Mt(s);if(o)return o;let c=s?.credential_process;if(!c)return null;let u=Qn(i,c),d=Jn(u);if(d)return d;let g=dt.get(u);if(g)return g;let y=xi(i,c,n?.timeoutMs??jm).then((h)=>{let A=Kn(h,i,c);return Yn(u,A),A}).finally(()=>{dt.delete(u)});return dt.set(u,y),y}function ta(n){let i=Te(n?.profile),s=fn({...n,profile:i}),o=Mt(s);if(o)return o;let c=s?.credential_process;if(!c)return null;let u=Qn(i,c),d=Jn(u);if(d)return d;let g=Kn(ki(i,c,n?.timeoutMs??jm),i,c);return Yn(u,g),g}function Ry(){let n=process.env.AWS_ACCESS_KEY_ID,i=process.env.AWS_SECRET_ACCESS_KEY;if(!n||!i)return null;return{accessKeyId:n,secretAccessKey:i,sessionToken:process.env.AWS_SESSION_TOKEN}}function Dy(n){let i=ns({profile:n?.profile,credentialsFile:n?.credentialsFile,configFile:n?.configFile});return i?{accessKeyId:i.accessKeyId,secretAccessKey:i.secretAccessKey,sessionToken:i.sessionToken}:null}async function Py(n){return is({profile:n?.profile,credentialsFile:n?.credentialsFile,configFile:n?.configFile})}async function ky(n){let i=n?.timeout??1000,s="http://169.254.169.254";try{let o=await Je("http://169.254.169.254/latest/api/token",{method:"PUT",headers:{"X-aws-ec2-metadata-token-ttl-seconds":"21600"}},i);if(!o.ok)return null;let c=await o.text(),u=await Je("http://169.254.169.254/latest/meta-data/iam/security-credentials/",{headers:{"X-aws-ec2-metadata-token":c}},i);if(!u.ok)return null;let d=(await u.text()).trim(),g=await Je(`http://169.254.169.254/latest/meta-data/iam/security-credentials/${d}`,{headers:{"X-aws-ec2-metadata-token":c}},i);if(!g.ok)return null;let y=await g.json();return{accessKeyId:y.AccessKeyId,secretAccessKey:y.SecretAccessKey,sessionToken:y.Token,expiration:new Date(y.Expiration)}}catch{return null}}async function Ny(n){let i=n?.timeout??1000,s=process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI,o=process.env.AWS_CONTAINER_CREDENTIALS_FULL_URI,c=null;if(s)c=`http://169.254.170.2${s}`;else if(o)c=o;if(!c)return null;try{let u={},d=process.env.AWS_CONTAINER_AUTHORIZATION_TOKEN;if(d)u.Authorization=d;let g=await Je(c,{headers:u},i);if(!g.ok)return null;let y=await g.json();return{accessKeyId:y.AccessKeyId,secretAccessKey:y.SecretAccessKey,sessionToken:y.Token,expiration:new Date(y.Expiration)}}catch{return null}}async function By(n){let i=n?.timeout??5000,s=process.env.AWS_WEB_IDENTITY_TOKEN_FILE,o=process.env.AWS_ROLE_ARN,c=process.env.AWS_ROLE_SESSION_NAME||"ts-cloud-session";if(!s||!o)return null;try{let u=Mi(s,"utf-8").trim(),d=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION||"us-east-1",g=d.startsWith("us-gov")?`https://sts.${d}.amazonaws.com`:d==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${d}.amazonaws.com`,y=new URLSearchParams({Action:"AssumeRoleWithWebIdentity",Version:"2011-06-15",RoleArn:o,RoleSessionName:c,WebIdentityToken:u}),h=await Je(`${g}/?${y.toString()}`,{method:"POST"},i);if(!h.ok)return null;let A=await h.text(),C=Qe(A,"AccessKeyId"),v=Qe(A,"SecretAccessKey"),T=Qe(A,"SessionToken"),R=Qe(A,"Expiration");if(!C||!v)return null;return{accessKeyId:C,secretAccessKey:v,sessionToken:T??void 0,expiration:R?new Date(R):void 0}}catch{return null}}async function ss(n){let i=Ry();if(i)return i;let s=Dy(n);if(s)return s;let o=await Py(n);if(o)return o;let c=await By(n);if(c)return c;let u=await Ny(n);if(u)return u;let d=await ky(n);if(d)return d;throw Error("Could not find AWS credentials. Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables, or configure ~/.aws/credentials, or run on an EC2 instance with an IAM role.")}function Lb(n){let i=null,s=null;return async()=>{if(i){if(!i.expiration)return i;let o=300000;if(i.expiration.getTime()-Date.now()>o)return i}if(s)return s;return s=ss(n).then((o)=>(i=o,s=null,o)).catch((o)=>{throw s=null,o}),s}}async function Je(n,i,s){let o=new AbortController,c=setTimeout(()=>o.abort(),s);try{let u=await fetch(n,{...i,signal:o.signal});return clearTimeout(c),u}catch(u){throw clearTimeout(c),u}}function Qe(n,i){let s=new RegExp(`<${i}>([^<]+)</${i}>`),o=n.match(s);return o?o[1]:null}async function ra(n){return ss({profile:n})}function xy(n){let i=process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION;if(i)return i;let s=fn({profile:n})?.region;if(s)return s;return"us-east-1"}async function zm(n){let i=n||await ss(),s=xy(),{signRequest:o}=await import("./chunk-0v77443p.js"),c=s.startsWith("us-gov")?`https://sts.${s}.amazonaws.com`:s==="us-east-1"?"https://sts.amazonaws.com":`https://sts.${s}.amazonaws.com`,u="Action=GetCallerIdentity&Version=2011-06-15",d=o({method:"POST",url:c,body:"Action=GetCallerIdentity&Version=2011-06-15",headers:{"Content-Type":"application/x-www-form-urlencoded"},...i,service:"sts",region:s}),g=await fetch(d.url,{method:d.method,headers:d.headers,body:d.body});if(!g.ok)throw Error(`Failed to get account ID: ${await g.text()}`);let y=await g.text(),h=Qe(y,"Account");if(!h)throw Error("Failed to parse account ID from response");return h}var Oi=5242880,$t=5242880;var $i=5242880;class Ft{region;endpoint;forcePathStyle;credentials;credentialOptions;retryOptions;constructor(n={}){this.region=n.region||process.env.AWS_REGION||"us-east-1",this.endpoint=n.endpoint||`https://s3.${this.region}.amazonaws.com`,this.forcePathStyle=n.forcePathStyle||!1,this.credentials=n.credentials,this.credentialOptions=n.credentialOptions,this.retryOptions=n.retryOptions||{}}async getCredentials(){if(this.credentials)return this.credentials;return ss(this.credentialOptions)}buildUrl(n,i){let s=i?encodeURIComponent(i).replace(/%2F/g,"/"):"";if(this.forcePathStyle)return i?`${this.endpoint}/${n}/${s}`:`${this.endpoint}/${n}`;let o=new URL(this.endpoint);return o.hostname=`${n}.${o.hostname}`,i?`${o.origin}/${s}`:o.origin}async get(n,i,s={}){let o=await this.getCredentials(),c=this.buildUrl(n,i),u={};if(s.range)u.Range=s.range;if(s.ifModifiedSince)u["If-Modified-Since"]=s.ifModifiedSince.toUTCString();if(s.ifMatch)u["If-Match"]=s.ifMatch;if(s.ifNoneMatch)u["If-None-Match"]=s.ifNoneMatch;let d=new URL(c);if(s.responseContentType)d.searchParams.set("response-content-type",s.responseContentType);if(s.responseContentDisposition)d.searchParams.set("response-content-disposition",s.responseContentDisposition);let g=N({method:"GET",url:d.toString(),headers:u,...o,service:"s3",region:this.region}),y=await fetch(g.url,{method:g.method,headers:g.headers});if(!y.ok&&y.status!==304){let h=await y.text();throw new q(`Failed to get object: ${h}`,y.status,n,i)}return y}async getText(n,i,s={}){return(await this.get(n,i,s)).text()}async getJSON(n,i,s={}){return(await this.get(n,i,s)).json()}async getBuffer(n,i,s={}){return(await this.get(n,i,s)).arrayBuffer()}async put(n,i,s,o={}){let c,u;if(typeof s==="string")c=new TextEncoder().encode(s).length,u=s;else if(s instanceof ArrayBuffer)c=s.byteLength,u=s;else if(s instanceof Uint8Array)c=s.byteLength,u=s;else if(s instanceof Blob)c=s.size,u=s;else return this.uploadMultipart(n,i,s,{...o,partSize:$t});if(c>$i){let d=Gi(u).stream();return this.uploadMultipart(n,i,d,{...o,partSize:$t})}return this.putSimple(n,i,u,c,o)}async putSimple(n,i,s,o,c){let u=await this.getCredentials(),d=this.buildUrl(n,i),g={"Content-Length":String(o),"Content-Type":c.contentType||Zn(i)};if(c.contentEncoding)g["Content-Encoding"]=c.contentEncoding;if(c.cacheControl)g["Cache-Control"]=c.cacheControl;if(c.contentDisposition)g["Content-Disposition"]=c.contentDisposition;if(c.storageClass)g["x-amz-storage-class"]=c.storageClass;if(c.serverSideEncryption)g["x-amz-server-side-encryption"]=c.serverSideEncryption;if(c.acl)g["x-amz-acl"]=c.acl;if(c.tagging)g["x-amz-tagging"]=c.tagging;if(c.metadata)for(let[v,T]of Object.entries(c.metadata))g[`x-amz-meta-${v.toLowerCase()}`]=T;let y;if(typeof s==="string")y=s;else if(s instanceof Blob)y=await s.text();else y=new TextDecoder().decode(s instanceof ArrayBuffer?new Uint8Array(s):s);let h=N({method:"PUT",url:d,headers:g,body:y,...u,service:"s3",region:this.region}),A=await fetch(h.url,{method:h.method,headers:h.headers,body:s});if(!A.ok){let v=await A.text();throw new q(`Failed to put object: ${v}`,A.status,n,i)}return{etag:(A.headers.get("ETag")||"").replace(/"/g,"")}}async delete(n,i){let s=await this.getCredentials(),o=this.buildUrl(n,i),c=N({method:"DELETE",url:o,...s,service:"s3",region:this.region}),u=await fetch(c.url,{method:c.method,headers:c.headers});if(!u.ok&&u.status!==204){let d=await u.text();throw new q(`Failed to delete object: ${d}`,u.status,n,i)}}async deleteMany(n,i){let s=await this.getCredentials(),o=`${this.buildUrl(n)}?delete`,u=`<?xml version="1.0" encoding="UTF-8"?><Delete><Quiet>false</Quiet>${i.map((R)=>`<Object><Key>${Fi(R)}</Key></Object>`).join("")}</Delete>`,d=N({method:"POST",url:o,headers:{"Content-Type":"application/xml"},body:u,...s,service:"s3",region:this.region}),g=await fetch(d.url,{method:d.method,headers:d.headers,body:u});if(!g.ok){let R=await g.text();throw new q(`Failed to delete objects: ${R}`,g.status,n)}let y=await g.text(),h=[],A=[],C=/<Deleted><Key>([^<]+)<\/Key>/g,v;while((v=C.exec(y))!==null)h.push(v[1]);let T=/<Error><Key>([^<]+)<\/Key><Code>([^<]+)<\/Code><Message>([^<]+)<\/Message>/g;while((v=T.exec(y))!==null)A.push({key:v[1],error:`${v[2]}: ${v[3]}`});return{deleted:h,errors:A}}async list(n,i={}){let s=await this.getCredentials(),o=new URL(this.buildUrl(n));if(o.searchParams.set("list-type","2"),i.prefix)o.searchParams.set("prefix",i.prefix);if(i.delimiter)o.searchParams.set("delimiter",i.delimiter);if(i.maxKeys)o.searchParams.set("max-keys",String(i.maxKeys));if(i.continuationToken)o.searchParams.set("continuation-token",i.continuationToken);if(i.startAfter)o.searchParams.set("start-after",i.startAfter);let c=N({method:"GET",url:o.toString(),...s,service:"s3",region:this.region}),u=await fetch(c.url,{method:c.method,headers:c.headers});if(!u.ok){let g=await u.text();throw new q(`Failed to list objects: ${g}`,u.status,n)}let d=await u.text();return Bi(d)}async*listAll(n,i={}){let s;do{let o=await this.list(n,{...i,continuationToken:s});for(let c of o.contents)yield c;s=o.nextContinuationToken}while(s)}async head(n,i){let s=await this.getCredentials(),o=this.buildUrl(n,i),c=N({method:"HEAD",url:o,...s,service:"s3",region:this.region}),u=await fetch(c.url,{method:c.method,headers:c.headers});if(u.status===404)return null;if(!u.ok){let g=await u.text();throw new q(`Failed to head object: ${g}`,u.status,n,i)}let d={};return u.headers.forEach((g,y)=>{if(y.toLowerCase().startsWith("x-amz-meta-"))d[y.slice(11)]=g}),{contentLength:Number(u.headers.get("Content-Length")||0),contentType:u.headers.get("Content-Type")||"application/octet-stream",etag:(u.headers.get("ETag")||"").replace(/"/g,""),lastModified:new Date(u.headers.get("Last-Modified")||0),metadata:d,storageClass:u.headers.get("x-amz-storage-class")||void 0,serverSideEncryption:u.headers.get("x-amz-server-side-encryption")||void 0}}async exists(n,i){return await this.head(n,i)!==null}async copy(n,i,s,o,c={}){let u=await this.getCredentials(),d=this.buildUrl(s,o),g={"x-amz-copy-source":`/${n}/${encodeURIComponent(i)}`};if(c.metadataDirective)g["x-amz-metadata-directive"]=c.metadataDirective;if(c.contentType)g["Content-Type"]=c.contentType;if(c.storageClass)g["x-amz-storage-class"]=c.storageClass;if(c.acl)g["x-amz-acl"]=c.acl;if(c.metadata)for(let[T,R]of Object.entries(c.metadata))g[`x-amz-meta-${T.toLowerCase()}`]=R;let y=N({method:"PUT",url:d,headers:g,...u,service:"s3",region:this.region}),h=await fetch(y.url,{method:y.method,headers:y.headers});if(!h.ok){let T=await h.text();throw new q(`Failed to copy object: ${T}`,h.status,s,o)}let C=(await h.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:C?C[1]:""}}async getPresignedUrl(n,i,s={}){let o=await this.getCredentials(),c=this.buildUrl(n,i);return ga({url:c,method:s.method||"GET",expiresIn:s.expiresIn||3600,...o,service:"s3",region:this.region})}async uploadMultipart(n,i,s,o={}){let c=await this.getCredentials(),u=Math.max(o.partSize||$t,Oi),d,g;if(s instanceof ReadableStream)d=s;else if(s instanceof Blob)d=s.stream(),g=s.size;else{let A=new Blob([s]);d=A.stream(),g=A.size}let{uploadId:y,baseUrl:h}=await this.initiateMultipartUpload(n,i,o);try{let A=await this.uploadParts(n,i,h,y,d,u,c,g,o.concurrency||4,o.onProgress);return await this.completeMultipartUpload(n,i,h,y,A)}catch(A){throw await this.abortMultipartUpload(n,i,y,h).catch(()=>{}),A}}async initiateMultipartUpload(n,i,s){let o=await this.getCredentials(),c=this.buildUrl(n,i),u=`${c}?uploads`,d={"Content-Type":s.contentType||Zn(i)};if(s.storageClass)d["x-amz-storage-class"]=s.storageClass;if(s.serverSideEncryption)d["x-amz-server-side-encryption"]=s.serverSideEncryption;if(s.acl)d["x-amz-acl"]=s.acl;if(s.metadata)for(let[v,T]of Object.entries(s.metadata))d[`x-amz-meta-${v.toLowerCase()}`]=T;let g=N({method:"POST",url:u,headers:d,...o,service:"s3",region:this.region}),y=await fetch(g.url,{method:g.method,headers:g.headers});if(!y.ok){let v=await y.text();throw new q(`Failed to initiate multipart upload: ${v}`,y.status,n,i)}let A=(await y.text()).match(/<UploadId>([^<]+)<\/UploadId>/);if(!A)throw new q("Failed to parse upload ID from response",0,n,i);let C=c;if(y.url)try{let v=new URL(y.url);v.search="",C=v.toString()}catch{}return{uploadId:A[1],baseUrl:C}}async uploadParts(n,i,s,o,c,u,d,g,y,h){let A=[],C=c.getReader(),v=1,T=new Uint8Array(0),R=0,P=g?Math.ceil(g/u):void 0,I=new Map,O=async(x,F)=>{let G=`${s}?partNumber=${F}&uploadId=${encodeURIComponent(o)}`,_={"Content-Length":String(x.byteLength),"x-amz-content-sha256":"UNSIGNED-PAYLOAD"},U=N({method:"PUT",url:G,headers:_,...d,service:"s3",region:this.region}),z=await fetch(U.url,{method:U.method,headers:U.headers,body:x,redirect:"error"});if(!z.ok){let Q=await z.text();throw new q(`Failed to upload part ${F}: ${Q}`,z.status,n,i)}let K=(z.headers.get("ETag")||"").replace(/"/g,"");if(!K)throw new q(`Missing ETag for part ${F}`,z.status,n,i);return{partNumber:F,etag:K}},B=async()=>{let x=await Promise.race(I.values());I.delete(x.partNumber),A.push(x)};while(!0){let{done:x,value:F}=await C.read();if(F){let G=new Uint8Array(T.length+F.length);G.set(T),G.set(F,T.length),T=G}while(T.length>=u||x&&T.length>0){let G=T.slice(0,u);T=T.slice(u);let _=v++;if(I.size>=y)await B();if(I.set(_,O(G,_)),R+=G.byteLength,h)h({loaded:R,total:g||R,part:_,totalParts:P||_})}if(x)break}while(I.size>0)await B();return A.sort((x,F)=>x.partNumber-F.partNumber),A}async completeMultipartUpload(n,i,s,o,c){let u=await this.getCredentials(),d=`${s}?uploadId=${encodeURIComponent(o)}`,y=`<?xml version="1.0" encoding="UTF-8"?><CompleteMultipartUpload>${c.map((R)=>`<Part><PartNumber>${R.partNumber}</PartNumber><ETag>"${R.etag}"</ETag></Part>`).join("")}</CompleteMultipartUpload>`,h=N({method:"POST",url:d,headers:{"Content-Type":"application/xml"},body:y,...u,service:"s3",region:this.region}),A=await fetch(h.url,{method:h.method,headers:h.headers,body:y});if(!A.ok){let R=await A.text();throw new q(`Failed to complete multipart upload: ${R}`,A.status,n,i)}let v=(await A.text()).match(/<ETag>"?([^"<]+)"?<\/ETag>/);return{etag:v?v[1]:""}}async abortMultipartUpload(n,i,s,o){let c=await this.getCredentials(),u=`${o??this.buildUrl(n,i)}?uploadId=${encodeURIComponent(s)}`,d=N({method:"DELETE",url:u,...c,service:"s3",region:this.region});await fetch(d.url,{method:d.method,headers:d.headers})}async emptyAndDeleteBucket(n){let s=[];for await(let d of this.listAll(n,{}))if(s.push(d.key),s.length>=1000)await this.deleteMany(n,s),s=[];if(s.length>0)await this.deleteMany(n,s);let o=await this.getCredentials(),c=this.buildUrl(n),u=N({method:"DELETE",url:c,...o,service:"s3",region:this.region});await fetch(u.url,{method:u.method,headers:u.headers})}}class q extends Error{statusCode;bucket;key;constructor(n,i,s,o){super(n);this.statusCode=i;this.bucket=s;this.key=o;this.name="S3Error"}}function Bi(n){let i=[],s=[],o=/<Contents>([\s\S]*?)<\/Contents>/g,c;while((c=o.exec(n))!==null){let d=c[1];i.push({key:me(d,"Key")||"",lastModified:new Date(me(d,"LastModified")||0),etag:(me(d,"ETag")||"").replace(/"/g,""),size:Number(me(d,"Size")||0),storageClass:me(d,"StorageClass")||"STANDARD"})}let u=/<CommonPrefixes><Prefix>([^<]+)<\/Prefix><\/CommonPrefixes>/g;while((c=u.exec(n))!==null)s.push(c[1]);return{contents:i,commonPrefixes:s,isTruncated:me(n,"IsTruncated")==="true",continuationToken:me(n,"ContinuationToken")||void 0,nextContinuationToken:me(n,"NextContinuationToken")||void 0,keyCount:Number(me(n,"KeyCount")||0),maxKeys:Number(me(n,"MaxKeys")||1000),prefix:me(n,"Prefix")||void 0,delimiter:me(n,"Delimiter")||void 0}}function me(n,i){let s=new RegExp(`<${i}>([^<]*)</${i}>`),o=n.match(s);return o?o[1]:null}function Fi(n){return n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function Zn(n){let i=n.split(".").pop()?.toLowerCase();return{html:"text/html",htm:"text/html",css:"text/css",js:"application/javascript",mjs:"application/javascript",json:"application/json",xml:"application/xml",txt:"text/plain",md:"text/markdown",csv:"text/csv",jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",gif:"image/gif",webp:"image/webp",svg:"image/svg+xml",ico:"image/x-icon",avif:"image/avif",mp4:"video/mp4",webm:"video/webm",mov:"video/quicktime",avi:"video/x-msvideo",mp3:"audio/mpeg",wav:"audio/wav",ogg:"audio/ogg",pdf:"application/pdf",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xls:"application/vnd.ms-excel",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",ppt:"application/vnd.ms-powerpoint",pptx:"application/vnd.openxmlformats-officedocument.presentationml.presentation",zip:"application/zip",gz:"application/gzip",tar:"application/x-tar",rar:"application/vnd.rar","7z":"application/x-7z-compressed",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf",otf:"font/otf",eot:"application/vnd.ms-fontobject",wasm:"application/wasm"}[i||""]||"application/octet-stream"}function Gi(n){if(n instanceof Blob)return n;if(typeof n==="string")return new Blob([n],{type:"text/plain"});return new Blob([n])}function Oy(n){return new Ft(n)}class st extends Error{code;solution;details;constructor(n,i,s,o){super(n);this.code=i;this.solution=s;this.details=o;this.name="CloudError",Error.captureStackTrace?.(this,st)}toString(){let n=`${this.name} [${this.code}]: ${this.message}`;if(this.solution)n+=`
2461
2459
 
2462
2460
  \uD83D\uDCA1 Solution: ${this.solution}`;if(this.details&&Object.keys(this.details).length>0){n+=`
2463
2461
 
2464
2462
  Details:`;for(let[i,s]of Object.entries(this.details))n+=`
2465
- ${i}: ${JSON.stringify(s)}`}return n}}class Ko extends nt{constructor(n,i,s){super(n,"CONFIG_ERROR",i,s);this.name="ConfigurationError"}}class Ot extends nt{constructor(n,i,s){super(n,"CREDENTIAL_ERROR",i,s);this.name="CredentialError"}}class Ey extends nt{constructor(n,i,s){super(n,"DEPLOYMENT_ERROR",i,s);this.name="DeploymentError"}}class Mm extends nt{constructor(n,i,s){super(n,"VALIDATION_ERROR",i,s);this.name="ValidationError"}}class vy extends nt{statusCode;constructor(n,i,s,o){super(n,"AWS_API_ERROR",s,o);this.statusCode=i;this.name="AWSAPIError"}}var Ty={NO_CREDENTIALS:{message:"AWS credentials not found",solution:`Configure AWS credentials using one of these methods:
2463
+ ${i}: ${JSON.stringify(s)}`}return n}}class na extends st{constructor(n,i,s){super(n,"CONFIG_ERROR",i,s);this.name="ConfigurationError"}}class _t extends st{constructor(n,i,s){super(n,"CREDENTIAL_ERROR",i,s);this.name="CredentialError"}}class _y extends st{constructor(n,i,s){super(n,"DEPLOYMENT_ERROR",i,s);this.name="DeploymentError"}}class Km extends st{constructor(n,i,s){super(n,"VALIDATION_ERROR",i,s);this.name="ValidationError"}}class Ly extends st{statusCode;constructor(n,i,s,o){super(n,"AWS_API_ERROR",s,o);this.statusCode=i;this.name="AWSAPIError"}}var $y={NO_CREDENTIALS:{message:"AWS credentials not found",solution:`Configure AWS credentials using one of these methods:
2466
2464
  1. Set environment variables: AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
2467
2465
  2. Create ~/.aws/credentials file with your credentials
2468
2466
  3. Use an IAM role (for EC2 instances)
2469
- 4. Run 'aws configure' if you have AWS CLI installed`},INVALID_CREDENTIALS:{message:"AWS credentials are invalid",solution:"Verify your AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are correct. Run: aws sts get-caller-identity"},EXPIRED_CREDENTIALS:{message:"AWS credentials have expired",solution:"Refresh your AWS credentials. If using temporary credentials, generate new ones."},MISSING_CONFIG:{message:"Configuration file not found",solution:"Create a cloud.config.ts file in your project root. Use: cloud init"},INVALID_CONFIG:{message:"Configuration is invalid",solution:"Check your cloud.config.ts file for syntax errors. Use: cloud config:validate"},MISSING_REQUIRED_FIELD:{message:"Required configuration field is missing",solution:"Add the missing field to your cloud.config.ts file"},INVALID_REGION:{message:"AWS region is invalid",solution:"Use a valid AWS region like us-east-1, us-west-2, eu-west-1, etc."},STACK_ALREADY_EXISTS:{message:"CloudFormation stack already exists",solution:"Use: cloud deploy --update to update the existing stack, or cloud destroy to delete it first"},STACK_IN_PROGRESS:{message:"Stack operation already in progress",solution:"Wait for the current operation to complete, or cancel it in the AWS Console"},INSUFFICIENT_PERMISSIONS:{message:"Insufficient IAM permissions",solution:"Ensure your IAM user/role has the necessary permissions for CloudFormation and the resources you're deploying"},RESOURCE_LIMIT_EXCEEDED:{message:"AWS service limit exceeded",solution:"Request a service limit increase in the AWS Console, or clean up unused resources"},ROLLBACK_COMPLETE:{message:"Stack creation failed and rolled back",solution:"Check the CloudFormation events to see which resource failed. Fix the issue and try again."},CIRCULAR_DEPENDENCY:{message:"Circular dependency detected in resources",solution:"Review your resource dependencies and remove the circular reference"},INVALID_RESOURCE_NAME:{message:"Resource name contains invalid characters",solution:"Use only alphanumeric characters and hyphens in resource names"},DUPLICATE_RESOURCE:{message:"Duplicate resource name detected",solution:"Ensure all resource names are unique in your configuration"},VPC_CIDR_CONFLICT:{message:"VPC CIDR block conflicts with existing VPC",solution:"Use a different CIDR block that doesn't overlap with existing VPCs"},SUBNET_CIDR_INVALID:{message:"Subnet CIDR block is invalid or outside VPC range",solution:"Ensure subnet CIDR is within the VPC CIDR range and properly sized"},DB_INSTANCE_LIMIT:{message:"RDS instance limit reached",solution:"Delete unused RDS instances or request a limit increase"},INVALID_DB_NAME:{message:"Database name contains invalid characters",solution:"Use only alphanumeric characters and underscores, starting with a letter"},BUCKET_ALREADY_EXISTS:{message:"S3 bucket name already exists globally",solution:"S3 bucket names must be globally unique. Try a different name with your organization prefix"},INVALID_BUCKET_NAME:{message:"S3 bucket name is invalid",solution:"Use lowercase letters, numbers, and hyphens. Must start/end with letter/number. 3-63 characters."},TEMPLATE_TOO_LARGE:{message:"CloudFormation template exceeds size limit",solution:"Split your infrastructure into multiple stacks or use nested stacks"},INVALID_TEMPLATE:{message:"CloudFormation template is invalid",solution:"Validate your template with: cloud config:validate"},PARAMETER_NOT_FOUND:{message:"CloudFormation parameter not found",solution:"Check that all referenced parameters are defined in your template"}};function wy(n){return Ty[n]}function Fm(n,i){let s=wy(n);return new nt(s.message,n,s.solution,i)}class q{static verboseMode=!1;static debugMode=!1;static setVerbose(n){this.verboseMode=n}static setDebug(n){this.debugMode=n}static verbose(n,...i){if(this.verboseMode)console.log(`[VERBOSE] ${n}`,...i)}static debug(n,...i){if(this.debugMode)console.log(`[DEBUG] ${n}`,...i)}static info(n,...i){console.log(`ℹ ${n}`,...i)}static warn(n,...i){console.warn(`⚠ ${n}`,...i)}static error(n,i){if(console.error(`✖ ${n}`),i){if(i instanceof nt)console.error(i.toString());else console.error(i.message);if(this.debugMode&&i.stack)console.error(`
2470
- Stack trace:`),console.error(i.stack)}}static success(n){console.log(`✔ ${n}`)}}function vb(n){if(!n)throw Fm("MISSING_CONFIG");if(!n.project)throw new Ko("Missing required field: project","Add a project configuration with name, slug, and region",{field:"project"});if(!n.project.name)throw new Ko("Missing required field: project.name","Add a project name to your configuration",{field:"project.name"});if(!n.project.slug)throw new Ko("Missing required field: project.slug","Add a project slug (lowercase, alphanumeric with hyphens)",{field:"project.slug"});if(!/^[a-z0-9-]+$/.test(n.project.slug))throw new Mm("Invalid project slug format","Use only lowercase letters, numbers, and hyphens",{slug:n.project.slug});if(n.project.region){if(!["us-east-1","us-east-2","us-west-1","us-west-2","eu-west-1","eu-west-2","eu-west-3","eu-central-1","ap-southeast-1","ap-southeast-2","ap-northeast-1","ap-northeast-2","sa-east-1","ca-central-1"].includes(n.project.region))throw Fm("INVALID_REGION",{region:n.project.region})}q.success("Configuration validation passed")}function Tb(n){let i=[];if(n.environments?.production&&n.infrastructure?.database){let s=n.infrastructure.database;if((s.postgres||s.mysql)&&!s.postgres?.multiAZ&&!s.mysql?.multiAZ)i.push("Production database should use Multi-AZ for high availability")}if(n.infrastructure?.storage){for(let[s,o]of Object.entries(n.infrastructure.storage))if(o.encryption===!1)i.push(`Storage "${s}" is not encrypted - consider enabling encryption for security`)}if(n.infrastructure?.storage){for(let[s,o]of Object.entries(n.infrastructure.storage))if(o.public===!0)i.push(`Storage "${s}" is publicly accessible - ensure this is intentional`)}if(n.infrastructure?.database){let s=n.infrastructure.database;if(s.postgres||s.mysql){let o=s.postgres?.backupRetentionDays||s.mysql?.backupRetentionDays;if(!o||o<7)i.push("Database backup retention is less than 7 days - consider increasing for production")}}if(!n.infrastructure?.monitoring)i.push("No monitoring configured - consider adding CloudWatch alarms");return i}async function wb(n="default"){try{q.verbose("Resolving AWS credentials...");let i=await zo(n);if(!i.accessKeyId||!i.secretAccessKey)throw new Ot("AWS credentials are incomplete","Ensure both AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are set");q.verbose("Credentials resolved successfully"),q.debug("Access Key ID:",i.accessKeyId.substring(0,8)+"..."),q.verbose("Testing credentials with GetCallerIdentity...");let s;try{s=await $m(i),q.verbose("Credentials are valid"),q.debug("Account ID:",s)}catch(o){if(o instanceof Error)if(o.message.includes("InvalidClientTokenId"))throw new Ot("Invalid AWS access key ID","Check that your AWS_ACCESS_KEY_ID is correct");else if(o.message.includes("SignatureDoesNotMatch"))throw new Ot("Invalid AWS secret access key","Check that your AWS_SECRET_ACCESS_KEY is correct");else if(o.message.includes("ExpiredToken"))throw new Ot("AWS credentials have expired","Refresh your temporary credentials or use long-term credentials");else throw new Ot(`Failed to validate credentials: ${o.message}`,"Verify your AWS credentials are correct and have the necessary permissions");throw o}return{valid:!0,accountId:s,region:i.region}}catch(i){if(i instanceof Ot)throw i;return{valid:!1,error:i instanceof Error?i.message:"Unknown error"}}}async function Rb(n,i){return{allowed:i,denied:[]}}function Ry(n){let i=new Set(["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate","cloudformation:ListStacks"]);if(n.infrastructure){if(n.infrastructure.storage)i.add("s3:CreateBucket"),i.add("s3:DeleteBucket"),i.add("s3:PutBucketPolicy"),i.add("s3:PutBucketVersioning"),i.add("s3:PutBucketEncryption"),i.add("s3:PutObject"),i.add("s3:GetObject");if(n.infrastructure.compute){if(n.infrastructure.compute.server)i.add("ec2:RunInstances"),i.add("ec2:TerminateInstances"),i.add("ec2:DescribeInstances"),i.add("autoscaling:CreateAutoScalingGroup"),i.add("autoscaling:UpdateAutoScalingGroup"),i.add("autoscaling:DeleteAutoScalingGroup"),i.add("elasticloadbalancing:CreateLoadBalancer"),i.add("elasticloadbalancing:DeleteLoadBalancer");if(n.infrastructure.compute.fargate)i.add("ecs:CreateCluster"),i.add("ecs:DeleteCluster"),i.add("ecs:CreateService"),i.add("ecs:UpdateService"),i.add("ecs:DeleteService"),i.add("ecs:RegisterTaskDefinition")}if(n.infrastructure.database){if(n.infrastructure.database.postgres||n.infrastructure.database.mysql)i.add("rds:CreateDBInstance"),i.add("rds:DeleteDBInstance"),i.add("rds:ModifyDBInstance"),i.add("rds:DescribeDBInstances");if(n.infrastructure.database.dynamodb)i.add("dynamodb:CreateTable"),i.add("dynamodb:DeleteTable"),i.add("dynamodb:UpdateTable"),i.add("dynamodb:DescribeTable")}if(n.infrastructure.functions)i.add("lambda:CreateFunction"),i.add("lambda:DeleteFunction"),i.add("lambda:UpdateFunctionCode"),i.add("lambda:UpdateFunctionConfiguration"),i.add("lambda:AddPermission");if(n.infrastructure.cdn)i.add("cloudfront:CreateDistribution"),i.add("cloudfront:UpdateDistribution"),i.add("cloudfront:DeleteDistribution"),i.add("cloudfront:GetDistribution");if(n.infrastructure.network)i.add("ec2:CreateVpc"),i.add("ec2:DeleteVpc"),i.add("ec2:CreateSubnet"),i.add("ec2:DeleteSubnet"),i.add("ec2:CreateInternetGateway"),i.add("ec2:DeleteInternetGateway"),i.add("ec2:CreateNatGateway"),i.add("ec2:DeleteNatGateway"),i.add("ec2:CreateRouteTable"),i.add("ec2:DeleteRouteTable"),i.add("ec2:CreateSecurityGroup"),i.add("ec2:DeleteSecurityGroup")}return i.add("iam:CreateRole"),i.add("iam:DeleteRole"),i.add("iam:AttachRolePolicy"),i.add("iam:DetachRolePolicy"),i.add("iam:PutRolePolicy"),i.add("iam:GetRole"),i.add("iam:PassRole"),Array.from(i).sort()}function Db(n){let i=Ry(n);return JSON.stringify({Version:"2012-10-17",Statement:[{Effect:"Allow",Action:i,Resource:"*"}]},null,2)}var te={ec2:{"Running On-Demand Instances":20,"Elastic IPs":5,VPCs:5,"Internet Gateways":5,"NAT Gateways":5,"Security Groups":500},rds:{"DB Instances":40,"DB Snapshots":100,"DB Parameter Groups":50},lambda:{"Concurrent Executions":1000,"Function Storage":80530636800},s3:{Buckets:100},cloudformation:{Stacks:200,StackSets:100},elasticache:{Nodes:100,Clusters:100},dynamodb:{Tables:256},ecs:{Clusters:1e4,"Services per Cluster":2000}};async function Pb(n){let i=[];if(q.verbose("Checking AWS service quotas..."),n.infrastructure?.compute?.server){let o=n.infrastructure.compute.server.autoScaling?.max||1;i.push({service:"EC2",quotaName:"Running On-Demand Instances",currentValue:o,limit:te.ec2["Running On-Demand Instances"],percentage:o/te.ec2["Running On-Demand Instances"]*100,warning:o>te.ec2["Running On-Demand Instances"]*0.8})}if(n.infrastructure?.network?.vpc)i.push({service:"EC2",quotaName:"VPCs",currentValue:1,limit:te.ec2.VPCs,percentage:1/te.ec2.VPCs*100,warning:!1});if(n.infrastructure?.database?.postgres||n.infrastructure?.database?.mysql)i.push({service:"RDS",quotaName:"DB Instances",currentValue:1,limit:te.rds["DB Instances"],percentage:1/te.rds["DB Instances"]*100,warning:!1});if(n.infrastructure?.storage){let o=Object.keys(n.infrastructure.storage).length;i.push({service:"S3",quotaName:"Buckets",currentValue:o,limit:te.s3.Buckets,percentage:o/te.s3.Buckets*100,warning:o>te.s3.Buckets*0.8})}if(n.infrastructure?.functions){let o=0;for(let c of Object.values(n.infrastructure.functions))if(Array.isArray(c))o+=c.length;i.push({service:"Lambda",quotaName:"Functions (estimated)",currentValue:o,limit:1000,percentage:o/1000*100,warning:o>800})}if(n.infrastructure?.database?.dynamodb){let o=n.infrastructure.database.dynamodb.tables?.length||0;i.push({service:"DynamoDB",quotaName:"Tables",currentValue:o,limit:te.dynamodb.Tables,percentage:o/te.dynamodb.Tables*100,warning:o>te.dynamodb.Tables*0.8})}let s=i.filter((o)=>o.warning);if(s.length>0){q.warn("Service quota warnings detected:");for(let o of s)q.warn(` ${o.service} - ${o.quotaName}: ${o.currentValue}/${o.limit} (${o.percentage.toFixed(1)}%)`)}else q.verbose("All service quotas are within limits");return i}function kb(n){if(n.length===0)return"No quotas to check";let i=`Service Quota Usage:
2467
+ 4. Run 'aws configure' if you have AWS CLI installed`},INVALID_CREDENTIALS:{message:"AWS credentials are invalid",solution:"Verify your AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are correct. Run: aws sts get-caller-identity"},EXPIRED_CREDENTIALS:{message:"AWS credentials have expired",solution:"Refresh your AWS credentials. If using temporary credentials, generate new ones."},MISSING_CONFIG:{message:"Configuration file not found",solution:"Create a cloud.config.ts file in your project root. Use: cloud init"},INVALID_CONFIG:{message:"Configuration is invalid",solution:"Check your cloud.config.ts file for syntax errors. Use: cloud config:validate"},MISSING_REQUIRED_FIELD:{message:"Required configuration field is missing",solution:"Add the missing field to your cloud.config.ts file"},INVALID_REGION:{message:"AWS region is invalid",solution:"Use a valid AWS region like us-east-1, us-west-2, eu-west-1, etc."},STACK_ALREADY_EXISTS:{message:"CloudFormation stack already exists",solution:"Use: cloud deploy --update to update the existing stack, or cloud destroy to delete it first"},STACK_IN_PROGRESS:{message:"Stack operation already in progress",solution:"Wait for the current operation to complete, or cancel it in the AWS Console"},INSUFFICIENT_PERMISSIONS:{message:"Insufficient IAM permissions",solution:"Ensure your IAM user/role has the necessary permissions for CloudFormation and the resources you're deploying"},RESOURCE_LIMIT_EXCEEDED:{message:"AWS service limit exceeded",solution:"Request a service limit increase in the AWS Console, or clean up unused resources"},ROLLBACK_COMPLETE:{message:"Stack creation failed and rolled back",solution:"Check the CloudFormation events to see which resource failed. Fix the issue and try again."},CIRCULAR_DEPENDENCY:{message:"Circular dependency detected in resources",solution:"Review your resource dependencies and remove the circular reference"},INVALID_RESOURCE_NAME:{message:"Resource name contains invalid characters",solution:"Use only alphanumeric characters and hyphens in resource names"},DUPLICATE_RESOURCE:{message:"Duplicate resource name detected",solution:"Ensure all resource names are unique in your configuration"},VPC_CIDR_CONFLICT:{message:"VPC CIDR block conflicts with existing VPC",solution:"Use a different CIDR block that doesn't overlap with existing VPCs"},SUBNET_CIDR_INVALID:{message:"Subnet CIDR block is invalid or outside VPC range",solution:"Ensure subnet CIDR is within the VPC CIDR range and properly sized"},DB_INSTANCE_LIMIT:{message:"RDS instance limit reached",solution:"Delete unused RDS instances or request a limit increase"},INVALID_DB_NAME:{message:"Database name contains invalid characters",solution:"Use only alphanumeric characters and underscores, starting with a letter"},BUCKET_ALREADY_EXISTS:{message:"S3 bucket name already exists globally",solution:"S3 bucket names must be globally unique. Try a different name with your organization prefix"},INVALID_BUCKET_NAME:{message:"S3 bucket name is invalid",solution:"Use lowercase letters, numbers, and hyphens. Must start/end with letter/number. 3-63 characters."},TEMPLATE_TOO_LARGE:{message:"CloudFormation template exceeds size limit",solution:"Split your infrastructure into multiple stacks or use nested stacks"},INVALID_TEMPLATE:{message:"CloudFormation template is invalid",solution:"Validate your template with: cloud config:validate"},PARAMETER_NOT_FOUND:{message:"CloudFormation parameter not found",solution:"Check that all referenced parameters are defined in your template"}};function My(n){return $y[n]}function Wm(n,i){let s=My(n);return new st(s.message,n,s.solution,i)}class j{static verboseMode=!1;static debugMode=!1;static setVerbose(n){this.verboseMode=n}static setDebug(n){this.debugMode=n}static verbose(n,...i){if(this.verboseMode)console.log(`[VERBOSE] ${n}`,...i)}static debug(n,...i){if(this.debugMode)console.log(`[DEBUG] ${n}`,...i)}static info(n,...i){console.log(`ℹ ${n}`,...i)}static warn(n,...i){console.warn(`⚠ ${n}`,...i)}static error(n,i){if(console.error(`✖ ${n}`),i){if(i instanceof st)console.error(i.toString());else console.error(i.message);if(this.debugMode&&i.stack)console.error(`
2468
+ Stack trace:`),console.error(i.stack)}}static success(n){console.log(`✔ ${n}`)}}function $b(n){if(!n)throw Wm("MISSING_CONFIG");if(!n.project)throw new na("Missing required field: project","Add a project configuration with name, slug, and region",{field:"project"});if(!n.project.name)throw new na("Missing required field: project.name","Add a project name to your configuration",{field:"project.name"});if(!n.project.slug)throw new na("Missing required field: project.slug","Add a project slug (lowercase, alphanumeric with hyphens)",{field:"project.slug"});if(!/^[a-z0-9-]+$/.test(n.project.slug))throw new Km("Invalid project slug format","Use only lowercase letters, numbers, and hyphens",{slug:n.project.slug});if(n.project.region){if(!["us-east-1","us-east-2","us-west-1","us-west-2","eu-west-1","eu-west-2","eu-west-3","eu-central-1","ap-southeast-1","ap-southeast-2","ap-northeast-1","ap-northeast-2","sa-east-1","ca-central-1"].includes(n.project.region))throw Wm("INVALID_REGION",{region:n.project.region})}j.success("Configuration validation passed")}function Mb(n){let i=[];if(n.environments?.production&&n.infrastructure?.database){let s=n.infrastructure.database;if((s.postgres||s.mysql)&&!s.postgres?.multiAZ&&!s.mysql?.multiAZ)i.push("Production database should use Multi-AZ for high availability")}if(n.infrastructure?.storage){for(let[s,o]of Object.entries(n.infrastructure.storage))if(o.encryption===!1)i.push(`Storage "${s}" is not encrypted - consider enabling encryption for security`)}if(n.infrastructure?.storage){for(let[s,o]of Object.entries(n.infrastructure.storage))if(o.public===!0)i.push(`Storage "${s}" is publicly accessible - ensure this is intentional`)}if(n.infrastructure?.database){let s=n.infrastructure.database;if(s.postgres||s.mysql){let o=s.postgres?.backupRetentionDays||s.mysql?.backupRetentionDays;if(!o||o<7)i.push("Database backup retention is less than 7 days - consider increasing for production")}}if(!n.infrastructure?.monitoring)i.push("No monitoring configured - consider adding CloudWatch alarms");return i}async function Fb(n="default"){try{j.verbose("Resolving AWS credentials...");let i=await ra(n);if(!i.accessKeyId||!i.secretAccessKey)throw new _t("AWS credentials are incomplete","Ensure both AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are set");j.verbose("Credentials resolved successfully"),j.debug("Access Key ID:",i.accessKeyId.substring(0,8)+"..."),j.verbose("Testing credentials with GetCallerIdentity...");let s;try{s=await zm(i),j.verbose("Credentials are valid"),j.debug("Account ID:",s)}catch(o){if(o instanceof Error)if(o.message.includes("InvalidClientTokenId"))throw new _t("Invalid AWS access key ID","Check that your AWS_ACCESS_KEY_ID is correct");else if(o.message.includes("SignatureDoesNotMatch"))throw new _t("Invalid AWS secret access key","Check that your AWS_SECRET_ACCESS_KEY is correct");else if(o.message.includes("ExpiredToken"))throw new _t("AWS credentials have expired","Refresh your temporary credentials or use long-term credentials");else throw new _t(`Failed to validate credentials: ${o.message}`,"Verify your AWS credentials are correct and have the necessary permissions");throw o}return{valid:!0,accountId:s,region:i.region}}catch(i){if(i instanceof _t)throw i;return{valid:!1,error:i instanceof Error?i.message:"Unknown error"}}}async function Ub(n,i){return{allowed:i,denied:[]}}function Fy(n){let i=new Set(["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:DescribeStacks","cloudformation:DescribeStackEvents","cloudformation:GetTemplate","cloudformation:ListStacks"]);if(n.infrastructure){if(n.infrastructure.storage)i.add("s3:CreateBucket"),i.add("s3:DeleteBucket"),i.add("s3:PutBucketPolicy"),i.add("s3:PutBucketVersioning"),i.add("s3:PutBucketEncryption"),i.add("s3:PutObject"),i.add("s3:GetObject");if(n.infrastructure.compute){if(n.infrastructure.compute.server)i.add("ec2:RunInstances"),i.add("ec2:TerminateInstances"),i.add("ec2:DescribeInstances"),i.add("autoscaling:CreateAutoScalingGroup"),i.add("autoscaling:UpdateAutoScalingGroup"),i.add("autoscaling:DeleteAutoScalingGroup"),i.add("elasticloadbalancing:CreateLoadBalancer"),i.add("elasticloadbalancing:DeleteLoadBalancer");if(n.infrastructure.compute.fargate)i.add("ecs:CreateCluster"),i.add("ecs:DeleteCluster"),i.add("ecs:CreateService"),i.add("ecs:UpdateService"),i.add("ecs:DeleteService"),i.add("ecs:RegisterTaskDefinition")}if(n.infrastructure.database){if(n.infrastructure.database.postgres||n.infrastructure.database.mysql)i.add("rds:CreateDBInstance"),i.add("rds:DeleteDBInstance"),i.add("rds:ModifyDBInstance"),i.add("rds:DescribeDBInstances");if(n.infrastructure.database.dynamodb)i.add("dynamodb:CreateTable"),i.add("dynamodb:DeleteTable"),i.add("dynamodb:UpdateTable"),i.add("dynamodb:DescribeTable")}if(n.infrastructure.functions)i.add("lambda:CreateFunction"),i.add("lambda:DeleteFunction"),i.add("lambda:UpdateFunctionCode"),i.add("lambda:UpdateFunctionConfiguration"),i.add("lambda:AddPermission");if(n.infrastructure.cdn)i.add("cloudfront:CreateDistribution"),i.add("cloudfront:UpdateDistribution"),i.add("cloudfront:DeleteDistribution"),i.add("cloudfront:GetDistribution");if(n.infrastructure.network)i.add("ec2:CreateVpc"),i.add("ec2:DeleteVpc"),i.add("ec2:CreateSubnet"),i.add("ec2:DeleteSubnet"),i.add("ec2:CreateInternetGateway"),i.add("ec2:DeleteInternetGateway"),i.add("ec2:CreateNatGateway"),i.add("ec2:DeleteNatGateway"),i.add("ec2:CreateRouteTable"),i.add("ec2:DeleteRouteTable"),i.add("ec2:CreateSecurityGroup"),i.add("ec2:DeleteSecurityGroup")}return i.add("iam:CreateRole"),i.add("iam:DeleteRole"),i.add("iam:AttachRolePolicy"),i.add("iam:DetachRolePolicy"),i.add("iam:PutRolePolicy"),i.add("iam:GetRole"),i.add("iam:PassRole"),Array.from(i).sort()}function Qb(n){let i=Fy(n);return JSON.stringify({Version:"2012-10-17",Statement:[{Effect:"Allow",Action:i,Resource:"*"}]},null,2)}var re={ec2:{"Running On-Demand Instances":20,"Elastic IPs":5,VPCs:5,"Internet Gateways":5,"NAT Gateways":5,"Security Groups":500},rds:{"DB Instances":40,"DB Snapshots":100,"DB Parameter Groups":50},lambda:{"Concurrent Executions":1000,"Function Storage":80530636800},s3:{Buckets:100},cloudformation:{Stacks:200,StackSets:100},elasticache:{Nodes:100,Clusters:100},dynamodb:{Tables:256},ecs:{Clusters:1e4,"Services per Cluster":2000}};async function Hb(n){let i=[];if(j.verbose("Checking AWS service quotas..."),n.infrastructure?.compute?.server){let o=n.infrastructure.compute.server.autoScaling?.max||1;i.push({service:"EC2",quotaName:"Running On-Demand Instances",currentValue:o,limit:re.ec2["Running On-Demand Instances"],percentage:o/re.ec2["Running On-Demand Instances"]*100,warning:o>re.ec2["Running On-Demand Instances"]*0.8})}if(n.infrastructure?.network?.vpc)i.push({service:"EC2",quotaName:"VPCs",currentValue:1,limit:re.ec2.VPCs,percentage:1/re.ec2.VPCs*100,warning:!1});if(n.infrastructure?.database?.postgres||n.infrastructure?.database?.mysql)i.push({service:"RDS",quotaName:"DB Instances",currentValue:1,limit:re.rds["DB Instances"],percentage:1/re.rds["DB Instances"]*100,warning:!1});if(n.infrastructure?.storage){let o=Object.keys(n.infrastructure.storage).length;i.push({service:"S3",quotaName:"Buckets",currentValue:o,limit:re.s3.Buckets,percentage:o/re.s3.Buckets*100,warning:o>re.s3.Buckets*0.8})}if(n.infrastructure?.functions){let o=0;for(let c of Object.values(n.infrastructure.functions))if(Array.isArray(c))o+=c.length;i.push({service:"Lambda",quotaName:"Functions (estimated)",currentValue:o,limit:1000,percentage:o/1000*100,warning:o>800})}if(n.infrastructure?.database?.dynamodb){let o=n.infrastructure.database.dynamodb.tables?.length||0;i.push({service:"DynamoDB",quotaName:"Tables",currentValue:o,limit:re.dynamodb.Tables,percentage:o/re.dynamodb.Tables*100,warning:o>re.dynamodb.Tables*0.8})}let s=i.filter((o)=>o.warning);if(s.length>0){j.warn("Service quota warnings detected:");for(let o of s)j.warn(` ${o.service} - ${o.quotaName}: ${o.currentValue}/${o.limit} (${o.percentage.toFixed(1)}%)`)}else j.verbose("All service quotas are within limits");return i}function Gb(n){if(n.length===0)return"No quotas to check";let i=`Service Quota Usage:
2471
2469
 
2472
2470
  `,s=n.reduce((o,c)=>{if(!o[c.service])o[c.service]=[];return o[c.service].push(c),o},{});for(let[o,c]of Object.entries(s)){i+=`${o}:
2473
2471
  `;for(let u of c){let d=u.warning?"⚠":"✓";i+=` ${d} ${u.quotaName}: ${u.currentValue}/${u.limit} (${u.percentage.toFixed(1)}%)
2474
2472
  `}i+=`
2475
- `}return i}function Nb(n){let i=[];for(let s of n)if(s.percentage>=100)i.push(`Request quota increase for ${s.service} - ${s.quotaName} (currently ${s.limit})`);else if(s.warning)i.push(`Consider requesting quota increase for ${s.service} - ${s.quotaName} (${s.percentage.toFixed(1)}% used)`);return i}import{createHash as Wn}from"node:crypto";import{existsSync as ut,mkdirSync as hi,readdirSync as Gn,readFileSync as _n,unlinkSync as Qe,writeFileSync as bi}from"node:fs";import{join as Mt}from"node:path";class Al{cacheDir;ttl;constructor(n,i={}){this.cacheDir=n,this.ttl=i.ttl||86400000}ensureCacheDir(){if(!ut(this.cacheDir))hi(this.cacheDir,{recursive:!0})}getCachePath(n){let i=Wn("sha256").update(n).digest("hex");return Mt(this.cacheDir,`${i}.json`)}get(n){let i=this.getCachePath(n);if(!ut(i))return;try{let s=_n(i,"utf-8"),o=JSON.parse(s);if(Date.now()-o.timestamp>this.ttl){Qe(i);return}return o.value}catch{Qe(i);return}}set(n,i,s){this.ensureCacheDir();let o=this.getCachePath(n),c={value:i,timestamp:Date.now(),hash:s};bi(o,JSON.stringify(c),"utf-8")}has(n){return this.get(n)!==void 0}clear(){if(!ut(this.cacheDir))return;let n=Gn(this.cacheDir);for(let i of n)Qe(Mt(this.cacheDir,i))}prune(){if(!ut(this.cacheDir))return;let n=Gn(this.cacheDir),i=Date.now();for(let s of n){let o=Mt(this.cacheDir,s);try{let c=_n(o,"utf-8"),u=JSON.parse(c);if(i-u.timestamp>this.ttl)Qe(o)}catch{Qe(o)}}}}class yl{cache;constructor(n=Q("cache","templates")){this.cache=new Al(n,{ttl:86400000})}getTemplate(n){return this.cache.get(`template:${n}`)}setTemplate(n,i){let s=this.hashTemplate(i);this.cache.set(`template:${n}`,i,s)}hasChanged(n,i){let s=this.cache.get(`template:${n}`);if(!s)return!0;let o=this.hashTemplate(s),c=this.hashTemplate(i);return o!==c}hashTemplate(n){return Wn("sha256").update(n).digest("hex")}clear(){this.cache.clear()}prune(){this.cache.prune()}}var Lt=null;function Dy(){if(!Lt)Lt=new yl;return Lt}import{createHash as $t}from"node:crypto";import{createReadStream as Si,readdirSync as Ai,statSync as dt}from"node:fs";import{join as Ci,relative as vi}from"node:path";async function Um(n,i={}){let s=i.algorithm||"sha256",o=i.chunkSize||65536;return new Promise((c,u)=>{let d=$t(s),g=Si(n,{highWaterMark:o});g.on("data",(y)=>d.update(y)),g.on("end",()=>c(d.digest("hex"))),g.on("error",u)})}function Qm(n,i="sha256"){return $t(i).update(n).digest("hex")}function Bb(n,i="sha256"){return $t(i).update(n).digest("hex")}async function xb(n,i={}){let s=i.ignorePatterns||["node_modules",".git","dist","build",dn()],o=[];async function c(u){let d=Ai(u,{withFileTypes:!0});for(let g of d){let y=Ci(u,g.name),h=vi(n,y);if(s.some((A)=>h.includes(A)))continue;if(g.isDirectory())await c(y);else if(g.isFile()){let A=dt(y),C=await Um(y,i);o.push({path:h,hash:C,size:A.size,mtime:A.mtimeMs})}}}return await c(n),o}function Ob(n){let s=[...n].sort((o,c)=>o.path.localeCompare(c.path)).map((o)=>`${o.path}:${o.hash}`).join(`
2476
- `);return Qm(s)}function _b(n){let i=dt(n);return Qm(`${n}:${i.size}:${i.mtimeMs}`)}function Lb(n,i){let s=new Map(n.map((g)=>[g.path,g])),o=new Map(i.map((g)=>[g.path,g])),c=[],u=[],d=[];for(let[g,y]of o){let h=s.get(g);if(!h)c.push(y);else if(h.hash!==y.hash)u.push(y)}for(let[g,y]of s)if(!o.has(g))d.push(y);return{added:c,modified:u,deleted:d}}class Py{cache;constructor(){this.cache=new Map}get(n){let i=dt(n),s=this.cache.get(n);if(s&&s.mtime===i.mtimeMs&&s.size===i.size)return s.hash;return}set(n,i){let s=dt(n);this.cache.set(n,{hash:i,mtime:s.mtimeMs,size:s.size})}async getOrCompute(n,i={}){let s=this.get(n);if(s)return s;let o=await Um(n,i);return this.set(n,o),o}clear(){this.cache.clear()}}async function Sl(n,i={}){let s=i.concurrency||5,o=i.stopOnError??!0,c=[],u=[],d=Date.now(),g=[...n],y=[];async function h(v,T){try{let R=await v();c[T]=R}catch(R){let P=R instanceof Error?R:Error(String(R));if(u.push(P),o)throw g.length=0,P}}let A=0;while(g.length>0||y.length>0){while(y.length<s&&g.length>0){let v=g.shift(),T=A++,R=h(v,T);y.push(R)}if(y.length>0){await Promise.race(y);for(let v=y.length-1;v>=0;v--)if(await Promise.race([y[v].then(()=>!0),Promise.resolve(!1)]))y.splice(v,1)}if(o&&u.length>0)break}let C=Date.now()-d;return{results:c.filter((v)=>v!==void 0),errors:u,duration:C}}async function $b(n,i,s={}){let o=n.map((c)=>()=>i(c));return Sl(o,s)}async function Mb(n,i,s=5){let o=n.map((u,d)=>()=>i(u,d)),c=await Sl(o,{concurrency:s,stopOnError:!1});if(c.errors.length>0)throw AggregateError(c.errors,"Parallel map failed");return c.results}async function Fb(n,i={}){let s=i.retries||3,o=i.retryDelay||1000,c=n.map((u)=>async()=>{let d;for(let g=0;g<=s;g++)try{return await u()}catch(y){if(d=y instanceof Error?y:Error(String(y)),g<s)await Vn(o*(g+1))}throw d});return Sl(c,i)}async function Ub(n){let i=[];for(let s of n){let o=await s();i.push(o)}return i}function Vn(n){return new Promise((i)=>setTimeout(i,n))}async function Qb(n,i,s="Operation timed out"){return Promise.race([n(),new Promise((o,c)=>setTimeout(()=>c(Error(s)),i))])}class ky{maxConcurrent;minInterval;queue=[];running=0;lastExecution=0;constructor(n=5,i=100){this.maxConcurrent=n;this.minInterval=i}async execute(n){await this.waitForSlot(),this.running++,this.lastExecution=Date.now();try{return await n()}finally{this.running--,this.processQueue()}}waitForSlot(){if(this.running<this.maxConcurrent){let n=Date.now()-this.lastExecution;if(n>=this.minInterval)return Promise.resolve();return Vn(this.minInterval-n)}return new Promise((n)=>this.queue.push(n))}processQueue(){if(this.queue.length>0&&this.running<this.maxConcurrent)this.queue.shift()()}stats(){return{running:this.running,queued:this.queue.length}}}function Ny(n,i){let s=[];for(let o=0;o<n.length;o+=i)s.push(n.slice(o,o+i));return s}async function Hb(n,i,s){let o=Ny(n,i),c=[];for(let u of o){let d=await s(u);c.push(...d)}return c}function Gb(n,i){let s=[],o=[],c=[],u=[],d=n.Resources||{},g=i.Resources||{},y=new Set(Object.keys(d)),h=new Set(Object.keys(g));for(let v of h)if(!y.has(v))s.push(v);for(let v of y)if(!h.has(v))c.push(v);for(let v of h)if(y.has(v)){let T=d[v],R=g[v];if(JSON.stringify(T)!==JSON.stringify(R))o.push(v);else u.push(v)}let A=JSON.stringify(n.Parameters||{})!==JSON.stringify(i.Parameters||{}),C=JSON.stringify(n.Outputs||{})!==JSON.stringify(i.Outputs||{});return{added:s,modified:o,deleted:c,unchanged:u,parametersChanged:A,outputsChanged:C,hasChanges:s.length>0||o.length>0||c.length>0||A||C}}function Vb(n){let i=[];if(!n.hasChanges)return"No changes detected";if(n.added.length>0){i.push(`Added resources (${n.added.length}):`);for(let s of n.added)i.push(` + ${s}`)}if(n.modified.length>0){i.push(`Modified resources (${n.modified.length}):`);for(let s of n.modified)i.push(` ~ ${s}`)}if(n.deleted.length>0){i.push(`Deleted resources (${n.deleted.length}):`);for(let s of n.deleted)i.push(` - ${s}`)}if(n.parametersChanged)i.push("Parameters changed");if(n.outputsChanged)i.push("Outputs changed");return i.join(`
2477
- `)}function qb(n,i,s){if(n.deleted.length>0)return!0;for(let o of n.modified){let c=i.Resources[o],u=s.Resources[o];if(c.Type!==u.Type)return!0;let d=Ti(u.Type);for(let g of d){let y=c.Properties?.[g],h=u.Properties?.[g];if(JSON.stringify(y)!==JSON.stringify(h))return!0}}return!1}function Ti(n){return{"AWS::S3::Bucket":["BucketName"],"AWS::EC2::Instance":["ImageId","InstanceType","KeyName"],"AWS::RDS::DBInstance":["DBInstanceIdentifier","Engine"],"AWS::DynamoDB::Table":["TableName","KeySchema"],"AWS::Lambda::Function":["FunctionName"],"AWS::ECS::Service":["ServiceName"],"AWS::ElasticLoadBalancingV2::LoadBalancer":["Name","Type"]}[n]||[]}function jb(n){let i=[],s=[],o=[];i.push(...n.added);for(let c of n.modified)s.push(c);return o.push(...n.deleted),{safe:i,caution:s,dangerous:o}}function zb(n){if(!n.hasChanges)return{strategy:"skip",reason:"No changes detected"};if(n.deleted.length>0)return{strategy:"replace",reason:"Resources will be deleted"};if(n.added.length>0&&n.modified.length===0)return{strategy:"update",reason:"Only new resources added"};return{strategy:"update",reason:"Resources will be updated"}}function Kb(n){let i=n.added.length+n.modified.length+n.deleted.length+n.unchanged.length,s=n.added.length+n.modified.length+n.deleted.length,o=i>0?s/i*100:0;return{total:i,added:n.added.length,modified:n.modified.length,deleted:n.deleted.length,unchanged:n.unchanged.length,changePercentage:o}}var By={$schema:"http://json-schema.org/draft-07/schema#",title:"ts-cloud Configuration",description:"Configuration schema for ts-cloud infrastructure-as-code",type:"object",required:["project"],properties:{project:{type:"object",description:"Project configuration",required:["name","slug"],properties:{name:{type:"string",description:"Human-readable project name",minLength:1},slug:{type:"string",description:"URL-safe project identifier (lowercase, alphanumeric, hyphens only)",pattern:"^[a-z0-9-]+$",minLength:1,maxLength:63},region:{type:"string",description:"Default AWS region",enum:["us-east-1","us-east-2","us-west-1","us-west-2","eu-west-1","eu-west-2","eu-west-3","eu-central-1","ap-southeast-1","ap-southeast-2","ap-northeast-1","ap-northeast-2","sa-east-1","ca-central-1"]}}},mode:{type:"string",description:"Deployment mode (server and serverless are mutually exclusive; auto-detected when omitted)",enum:["server","serverless"]},environments:{type:"object",description:"Environment-specific configurations",properties:{production:{$ref:"#/definitions/environment"},staging:{$ref:"#/definitions/environment"},development:{$ref:"#/definitions/environment"}}},infrastructure:{type:"object",description:"Infrastructure configuration",properties:{network:{$ref:"#/definitions/network"},storage:{type:"object",description:"S3 storage configuration",additionalProperties:{$ref:"#/definitions/storage"}},compute:{$ref:"#/definitions/compute"},database:{$ref:"#/definitions/database"},cache:{$ref:"#/definitions/cache"},cdn:{$ref:"#/definitions/cdn"},sftp:{$ref:"#/definitions/sftp"},functions:{type:"object",description:"Lambda functions configuration",additionalProperties:{type:"array",items:{$ref:"#/definitions/function"}}},monitoring:{$ref:"#/definitions/monitoring"},security:{$ref:"#/definitions/security"},queue:{type:"object",description:"SQS queue configuration",additionalProperties:{$ref:"#/definitions/queue"}}}}},definitions:{environment:{type:"object",properties:{domain:{type:"string",description:"Custom domain for this environment"},region:{type:"string",description:"AWS region override for this environment"},app:{type:"object",description:"Serverless application manifest (Laravel-Vapor-equivalent). Defining this opts the environment into the serverless app deploy pipeline (http/queue/cli Lambda functions, assets, build/deploy hooks).",properties:{runtime:{type:"string",description:"Lambda runtime override (usually derived from kind + runtimeVersion)"},runtimeVersion:{type:"string",description:"Node major (18/20/22 managed, 24+ custom layer) or Bun release for node/bun apps"},kind:{type:"string",enum:["node","bun","php"],description:"Application kind (drives packaging + runtime)"},entry:{type:"string",description:"Entry file exporting the request handler"},memory:{type:"number",description:"HTTP function memory in MB"},timeout:{type:"number",description:"HTTP request timeout in seconds"},gatewayVersion:{type:"number",enum:[1,2],description:"API Gateway version (2 = HTTP API, 1 = REST)"},warm:{type:"number",description:"Keep-warm / provisioned concurrency count"},lambdaInsights:{type:"object",description:"CloudWatch Lambda Insights extension configuration for zip deployments",required:["layerArn"],properties:{layerArn:{type:"string",description:"Region- and architecture-specific Lambda Insights extension layer ARN"}}},queues:{description:"Queue names (true = single default queue, false = disabled)"},scheduler:{type:"string",enum:["off","on","sub-minute"],description:"Task scheduler mode"},build:{type:"array",items:{type:"string"},description:"Commands run locally before packaging"},deploy:{type:"array",items:{type:"string"},description:"Commands run remotely after activation (e.g. migrations)"},octane:{type:"boolean",description:"Persistent application mode (Laravel Octane)"},packaging:{type:"string",enum:["zip","image"],description:"Deployment package format (zip or container image)"},phpVersion:{type:"string",description:"PHP version for the runtime layer (kind: php)"},architecture:{type:"string",enum:["x86_64","arm64"],description:"CPU architecture"}}}}},network:{type:"object",properties:{vpc:{type:"object",properties:{cidr:{type:"string",description:"VPC CIDR block",pattern:"^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]{1,2}$",default:"10.0.0.0/16"},availabilityZones:{type:"number",description:"Number of availability zones",minimum:1,maximum:3,default:2},natGateways:{type:"number",description:"Number of NAT gateways (0 for no NAT, saves cost)",minimum:0,maximum:3,default:1}}}}},storage:{type:"object",properties:{public:{type:"boolean",description:"Allow public access",default:!1},versioning:{type:"boolean",description:"Enable versioning",default:!1},encryption:{type:"boolean",description:"Enable server-side encryption",default:!0},website:{type:"boolean",description:"Enable static website hosting",default:!1},cors:{type:"object",description:"CORS configuration",properties:{allowedOrigins:{type:"array",items:{type:"string"}},allowedMethods:{type:"array",items:{type:"string",enum:["GET","PUT","POST","DELETE","HEAD"]}}}}}},compute:{type:"object",properties:{server:{type:"object",description:"EC2 server configuration",properties:{instanceType:{type:"string",description:"EC2 instance type",enum:["t3.micro","t3.small","t3.medium","t3.large","t3.xlarge","t3.2xlarge"]},autoScaling:{type:"object",properties:{min:{type:"number",minimum:1},max:{type:"number",minimum:1},desired:{type:"number",minimum:1}}}}},fargate:{type:"object",description:"ECS Fargate configuration",properties:{cpu:{type:"number",description:"CPU units (256, 512, 1024, 2048, 4096)",enum:[256,512,1024,2048,4096]},memory:{type:"number",description:"Memory in MB"},desiredCount:{type:"number",description:"Desired number of tasks",minimum:1}}}}},database:{type:"object",properties:{postgres:{type:"object",properties:{instanceClass:{type:"string",description:"RDS instance class",pattern:"^db\\.[a-z0-9]+\\.[a-z0-9]+$"},engine:{type:"string",const:"postgres"},version:{type:"string",description:"PostgreSQL version"},multiAZ:{type:"boolean",description:"Enable Multi-AZ deployment",default:!1},backupRetentionDays:{type:"number",description:"Backup retention period in days",minimum:0,maximum:35,default:7}}},mysql:{type:"object",properties:{instanceClass:{type:"string",pattern:"^db\\.[a-z0-9]+\\.[a-z0-9]+$"},engine:{type:"string",const:"mysql"},version:{type:"string"},multiAZ:{type:"boolean",default:!1},backupRetentionDays:{type:"number",minimum:0,maximum:35,default:7}}},dynamodb:{type:"object",properties:{tables:{type:"array",items:{type:"object",required:["name","partitionKey"],properties:{name:{type:"string"},partitionKey:{type:"string"},sortKey:{type:"string"},billingMode:{type:"string",enum:["PAY_PER_REQUEST","PROVISIONED"],default:"PAY_PER_REQUEST"}}}}}}}},cache:{type:"object",properties:{redis:{type:"object",properties:{nodeType:{type:"string",description:"ElastiCache node type",pattern:"^cache\\.[a-z0-9]+\\.[a-z0-9]+$"},numCacheNodes:{type:"number",minimum:1,default:1},engineVersion:{type:"string",description:"Redis engine version"}}},memcached:{type:"object",properties:{nodeType:{type:"string",pattern:"^cache\\.[a-z0-9]+\\.[a-z0-9]+$"},numCacheNodes:{type:"number",minimum:1,default:1}}}}},cdn:{type:"object",properties:{enabled:{type:"boolean",default:!0},originShield:{type:"boolean",description:"Enable CloudFront Origin Shield",default:!1},originShieldRegion:{type:"string",description:"AWS region used by CloudFront Origin Shield"},compress:{type:"boolean",description:"Enable automatic compression",default:!0},http3:{type:"boolean",description:"Enable HTTP/3 support",default:!0},customDomain:{type:"object",properties:{domain:{type:"string"},certificateArn:{type:"string"}}},cachePolicy:{type:"object",properties:{minTTL:{type:"number",minimum:0},defaultTTL:{type:"number",minimum:0},maxTTL:{type:"number",minimum:0}}}}},sftp:{type:"object",required:["bucket","users"],properties:{bucket:{type:"string",description:"S3 bucket backing the SFTP server"},endpointType:{type:"string",enum:["PUBLIC","VPC"],default:"PUBLIC"},endpointDetails:{type:"object",required:["vpcId","subnetIds"],properties:{vpcId:{type:"string"},subnetIds:{type:"array",items:{type:"string"},minItems:1},securityGroupIds:{type:"array",items:{type:"string"}},addressAllocationIds:{type:"array",items:{type:"string"}}}},securityPolicyName:{type:"string"},logging:{type:"boolean",default:!0},users:{type:"object",additionalProperties:{type:"object",required:["sshPublicKeys"],properties:{sshPublicKeys:{type:"array",items:{type:"string"},minItems:1},homeDirectory:{type:"string"},roleArn:{type:"string"}}}}}},function:{type:"object",required:["name","runtime"],properties:{name:{type:"string"},runtime:{type:"string",enum:["nodejs18.x","nodejs20.x","python3.10","python3.11","python3.12"]},handler:{type:"string",default:"index.handler"},timeout:{type:"number",minimum:1,maximum:900,default:30},memory:{type:"number",minimum:128,maximum:10240,default:1024}}},monitoring:{type:"object",properties:{alarms:{type:"array",items:{type:"object",required:["metric","threshold"],properties:{metric:{type:"string"},threshold:{type:"number"},evaluationPeriods:{type:"number",minimum:1,default:2}}}},dashboard:{type:"object",properties:{name:{type:"string"},widgets:{type:"array"}}}}},security:{type:"object",properties:{waf:{type:"boolean",description:"Enable AWS WAF",default:!1},certificates:{type:"array",items:{type:"object",required:["domain"],properties:{domain:{type:"string"},subdomains:{type:"array",items:{type:"string"}}}}}}},queue:{type:"object",properties:{fifo:{type:"boolean",default:!1},deadLetterQueue:{type:"boolean",default:!0},visibilityTimeout:{type:"number",minimum:0,maximum:43200,default:30},messageRetentionPeriod:{type:"number",minimum:60,maximum:1209600,default:345600}}}}};function Wb(n){let i=[];if(!n.project)i.push("Missing required field: project");else{if(!n.project.name)i.push("Missing required field: project.name");if(!n.project.slug)i.push("Missing required field: project.slug")}if(n.project?.slug&&!/^[a-z0-9-]+$/.test(n.project.slug))i.push("Invalid project.slug: must contain only lowercase letters, numbers, and hyphens");let s=["us-east-1","us-east-2","us-west-1","us-west-2","eu-west-1","eu-west-2","eu-west-3","eu-central-1","ap-southeast-1","ap-southeast-2","ap-northeast-1","ap-northeast-2","sa-east-1","ca-central-1"];if(n.project?.region&&!s.includes(n.project.region))i.push(`Invalid region: ${n.project.region}. Must be one of: ${s.join(", ")}`);if(n.mode&&!["server","serverless"].includes(n.mode))i.push("Invalid mode: must be one of server or serverless");return{valid:i.length===0,errors:i}}var Hm={enabled:process.env.TS_CLOUD_LOCAL==="true"||!0,localstackEndpoint:process.env.LOCALSTACK_ENDPOINT||"http://localhost:4566",postgresUrl:process.env.POSTGRES_URL||"postgresql://tscloud:tscloud@localhost:5432/tscloud",redisUrl:process.env.REDIS_URL||"redis://localhost:6379",dynamodbEndpoint:process.env.DYNAMODB_ENDPOINT||"http://localhost:8000",s3Endpoint:process.env.S3_ENDPOINT||"http://localhost:9000",emailEndpoint:process.env.EMAIL_ENDPOINT||"smtp://localhost:1025",awsRegion:process.env.AWS_REGION||"us-east-1",awsAccessKeyId:process.env.AWS_ACCESS_KEY_ID||"test",awsSecretAccessKey:process.env.AWS_SECRET_ACCESS_KEY||"test"};function Il(){return Hm}function Jb(){return Hm.enabled}function Xb(n){let i=Il();if(!i.enabled)return"";switch(n.toLowerCase()){case"dynamodb":return i.dynamodbEndpoint;case"s3":return i.s3Endpoint;case"localstack":case"cloudformation":case"lambda":case"apigateway":case"sns":case"sqs":case"cloudwatch":case"iam":case"sts":return i.localstackEndpoint;default:return i.localstackEndpoint}}function Yb(){let n=Il();return{accessKeyId:n.awsAccessKeyId,secretAccessKey:n.awsSecretAccessKey,region:n.awsRegion}}function Zb(){let n=Il();if(!n.enabled)return{};return{AWS_ACCESS_KEY_ID:n.awsAccessKeyId,AWS_SECRET_ACCESS_KEY:n.awsSecretAccessKey,AWS_REGION:n.awsRegion,AWS_ENDPOINT_URL:n.localstackEndpoint,LOCALSTACK_ENDPOINT:n.localstackEndpoint,TS_CLOUD_LOCAL:"true"}}class Gm{stacks=new Map;stackEvents=new Map;async createStack(n){let i=`arn:aws:cloudformation:${n.region||"us-east-1"}:123456789012:stack/${n.StackName}/${Date.now()}`;return this.stacks.set(n.StackName,{StackId:i,StackName:n.StackName,StackStatus:"CREATE_IN_PROGRESS",CreationTime:new Date().toISOString(),TemplateBody:n.TemplateBody,Parameters:n.Parameters||[]}),this.addEvent(n.StackName,{EventId:Date.now().toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_IN_PROGRESS"}),setTimeout(()=>{let s=this.stacks.get(n.StackName);if(s)s.StackStatus="CREATE_COMPLETE",this.addEvent(n.StackName,{EventId:(Date.now()+1).toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_COMPLETE"})},100),{StackId:i}}async updateStack(n){let i=this.stacks.get(n.StackName);if(!i)throw Error(`Stack ${n.StackName} does not exist`);return i.StackStatus="UPDATE_IN_PROGRESS",i.TemplateBody=n.TemplateBody||i.TemplateBody,this.addEvent(n.StackName,{EventId:Date.now().toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_IN_PROGRESS"}),setTimeout(()=>{i.StackStatus="UPDATE_COMPLETE",this.addEvent(n.StackName,{EventId:(Date.now()+1).toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_COMPLETE"})},100),{StackId:i.StackId}}async deleteStack(n){let i=this.stacks.get(n.StackName);if(!i)throw Error(`Stack ${n.StackName} does not exist`);i.StackStatus="DELETE_IN_PROGRESS",this.addEvent(n.StackName,{EventId:Date.now().toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_IN_PROGRESS"}),setTimeout(()=>{this.stacks.delete(n.StackName),this.addEvent(n.StackName,{EventId:(Date.now()+1).toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_COMPLETE"})},100)}async describeStacks(n){if(n.StackName){let i=this.stacks.get(n.StackName);if(!i)throw Error(`Stack ${n.StackName} does not exist`);return{Stacks:[i]}}return{Stacks:Array.from(this.stacks.values())}}async describeStackEvents(n){return{StackEvents:this.stackEvents.get(n.StackName)||[]}}addEvent(n,i){if(!this.stackEvents.has(n))this.stackEvents.set(n,[]);this.stackEvents.get(n).unshift(i)}reset(){this.stacks.clear(),this.stackEvents.clear()}}class Vm{buckets=new Map;async createBucket(n){return this.buckets.set(n.Bucket,new Map),{Location:`/${n.Bucket}`}}async deleteBucket(n){this.buckets.delete(n.Bucket)}async putObject(n){let i=this.buckets.get(n.Bucket);if(!i)i=new Map,this.buckets.set(n.Bucket,i);return i.set(n.Key,Buffer.from(n.Body||"")),{ETag:`"${Date.now()}"`}}async getObject(n){let i=this.buckets.get(n.Bucket);if(!i)throw Error(`Bucket ${n.Bucket} does not exist`);let s=i.get(n.Key);if(!s)throw Error(`Object ${n.Key} does not exist`);return{Body:s,ContentLength:s.length}}async deleteObject(n){let i=this.buckets.get(n.Bucket);if(i)i.delete(n.Key)}async listObjects(n){let i=this.buckets.get(n.Bucket);if(!i)throw Error(`Bucket ${n.Bucket} does not exist`);return{Contents:Array.from(i.keys()).map((o)=>({Key:o,Size:i.get(o).length,LastModified:new Date().toISOString()}))}}reset(){this.buckets.clear()}}class qm{tables=new Map;data=new Map;async createTable(n){return this.tables.set(n.TableName,{TableName:n.TableName,KeySchema:n.KeySchema,AttributeDefinitions:n.AttributeDefinitions,TableStatus:"ACTIVE",CreationDateTime:new Date().toISOString()}),this.data.set(n.TableName,new Map),{TableDescription:this.tables.get(n.TableName)}}async deleteTable(n){this.tables.delete(n.TableName),this.data.delete(n.TableName)}async putItem(n){let i=this.data.get(n.TableName);if(!i)i=new Map,this.data.set(n.TableName,i);let s=JSON.stringify(n.Item);i.set(s,n.Item)}async getItem(n){let i=this.data.get(n.TableName);if(!i)return{};let s=JSON.stringify(n.Key),o=i.get(s);return o?{Item:o}:{}}async deleteItem(n){let i=this.data.get(n.TableName);if(i){let s=JSON.stringify(n.Key);i.delete(s)}}async scan(n){let i=this.data.get(n.TableName);if(!i)return{Items:[]};return{Items:Array.from(i.values())}}reset(){this.tables.clear(),this.data.clear()}}function eC(n){return{cloudformation:new Gm,s3:new Vm,dynamodb:new qm}}class bl{environments=new Map;async createPreviewEnvironment(n){let{branch:i,pr:s,commitSha:o,ttl:c=24,baseConfig:u,region:d="us-east-1"}=n,g=this.generatePreviewId(i,s,o),y=this.generatePreviewName(i,s),h=`preview-${y}`,A=new Date,C=new Date(A.getTime()+c*60*60*1000),v={id:g,name:y,branch:i,pr:s,commitSha:o,createdAt:A,expiresAt:C,status:"creating",stackName:h,region:d,resources:[]};this.environments.set(g,v);try{let T=this.createPreviewConfig(u,y);return v.status="active",v.url=`https://${y}.preview.example.com`,v}catch(T){throw v.status="failed",T}}async destroyPreviewEnvironment(n){let i=this.environments.get(n);if(!i)throw Error(`Preview environment ${n} not found`);i.status="destroying";try{i.status="destroyed",this.environments.delete(n)}catch(s){throw Error(`Failed to destroy preview environment: ${s}`)}}getPreviewEnvironment(n){return this.environments.get(n)}getPreviewEnvironmentByBranch(n){return Array.from(this.environments.values()).find((i)=>i.branch===n)}getPreviewEnvironmentByPR(n){return Array.from(this.environments.values()).find((i)=>i.pr===n)}listPreviewEnvironments(){return Array.from(this.environments.values())}listActivePreviewEnvironments(){return this.listPreviewEnvironments().filter((n)=>n.status==="active")}async cleanupExpiredEnvironments(n={}){let{maxAge:i,keepCount:s,dryRun:o=!1}=n,c=[],u=[],d=new Date,g=this.listPreviewEnvironments().sort((y,h)=>h.createdAt.getTime()-y.createdAt.getTime());for(let y=0;y<g.length;y++){let h=g[y];if(h.status!=="active")continue;let A=!1;if(h.expiresAt<d)A=!0;if(i){if((d.getTime()-h.createdAt.getTime())/3600000>i)A=!0}if(s&&y>=s)A=!0;if(A)if(o)c.push(h.id);else try{await this.destroyPreviewEnvironment(h.id),c.push(h.id)}catch(C){u.push(h.id)}}return{destroyed:c,failed:u}}async updatePreviewEnvironment(n,i){let s=this.environments.get(n);if(!s)throw Error(`Preview environment ${n} not found`);s.commitSha=i,s.status="creating";try{return s.status="active",s}catch(o){throw s.status="failed",o}}async getPreviewEnvironmentsCost(){let n={},i=0;for(let s of this.environments.values())n[s.id]=0,i+=0;return{total:i,byEnvironment:n}}generatePreviewId(n,i,s){let o=n.replace(/[^a-z0-9-]/gi,"-").toLowerCase(),c=s?.substring(0,7)||Date.now().toString();return i?`pr-${i}-${c}`:`${o}-${c}`}generatePreviewName(n,i){let s=n.replace(/[^a-z0-9-]/gi,"-").toLowerCase();return i?`pr-${i}`:s}createPreviewConfig(n,i){return{...n,project:{...n.project,name:`${n.project.name} Preview (${i})`,slug:`${n.project.slug}-preview-${i}`}}}}var xy=new bl;function Oy(n={}){let{workflowName:i="Preview Environment",trigger:s="pull_request",branches:o=["main","develop"],awsRegion:c="us-east-1",awsRole:u,configFile:d="cloud.config.ts",ttl:g=24}=n;return`name: ${i}
2473
+ `}return i}function Vb(n){let i=[];for(let s of n)if(s.percentage>=100)i.push(`Request quota increase for ${s.service} - ${s.quotaName} (currently ${s.limit})`);else if(s.warning)i.push(`Consider requesting quota increase for ${s.service} - ${s.quotaName} (${s.percentage.toFixed(1)}% used)`);return i}import{createHash as tr}from"node:crypto";import{existsSync as mt,mkdirSync as _i,readdirSync as Xn,readFileSync as er,unlinkSync as Ye,writeFileSync as Wi}from"node:fs";import{join as Gt}from"node:path";class wl{cacheDir;ttl;constructor(n,i={}){this.cacheDir=n,this.ttl=i.ttl||86400000}ensureCacheDir(){if(!mt(this.cacheDir))_i(this.cacheDir,{recursive:!0})}getCachePath(n){let i=tr("sha256").update(n).digest("hex");return Gt(this.cacheDir,`${i}.json`)}get(n){let i=this.getCachePath(n);if(!mt(i))return;try{let s=er(i,"utf-8"),o=JSON.parse(s);if(Date.now()-o.timestamp>this.ttl){Ye(i);return}return o.value}catch{Ye(i);return}}set(n,i,s){this.ensureCacheDir();let o=this.getCachePath(n),c={value:i,timestamp:Date.now(),hash:s};Wi(o,JSON.stringify(c),"utf-8")}has(n){return this.get(n)!==void 0}clear(){if(!mt(this.cacheDir))return;let n=Xn(this.cacheDir);for(let i of n)Ye(Gt(this.cacheDir,i))}prune(){if(!mt(this.cacheDir))return;let n=Xn(this.cacheDir),i=Date.now();for(let s of n){let o=Gt(this.cacheDir,s);try{let c=er(o,"utf-8"),u=JSON.parse(c);if(i-u.timestamp>this.ttl)Ye(o)}catch{Ye(o)}}}}class Rl{cache;constructor(n=H("cache","templates")){this.cache=new wl(n,{ttl:86400000})}getTemplate(n){return this.cache.get(`template:${n}`)}setTemplate(n,i){let s=this.hashTemplate(i);this.cache.set(`template:${n}`,i,s)}hasChanged(n,i){let s=this.cache.get(`template:${n}`);if(!s)return!0;let o=this.hashTemplate(s),c=this.hashTemplate(i);return o!==c}hashTemplate(n){return tr("sha256").update(n).digest("hex")}clear(){this.cache.clear()}prune(){this.cache.prune()}}var Wt=null;function Uy(){if(!Wt)Wt=new Rl;return Wt}import{createHash as Vt}from"node:crypto";import{createReadStream as Vi,readdirSync as Ui,statSync as pt}from"node:fs";import{join as Hi,relative as ji}from"node:path";async function Jm(n,i={}){let s=i.algorithm||"sha256",o=i.chunkSize||65536;return new Promise((c,u)=>{let d=Vt(s),g=Vi(n,{highWaterMark:o});g.on("data",(y)=>d.update(y)),g.on("end",()=>c(d.digest("hex"))),g.on("error",u)})}function Xm(n,i="sha256"){return Vt(i).update(n).digest("hex")}function qb(n,i="sha256"){return Vt(i).update(n).digest("hex")}async function jb(n,i={}){let s=i.ignorePatterns||["node_modules",".git","dist","build",ln()],o=[];async function c(u){let d=Ui(u,{withFileTypes:!0});for(let g of d){let y=Hi(u,g.name),h=ji(n,y);if(s.some((A)=>h.includes(A)))continue;if(g.isDirectory())await c(y);else if(g.isFile()){let A=pt(y),C=await Jm(y,i);o.push({path:h,hash:C,size:A.size,mtime:A.mtimeMs})}}}return await c(n),o}function zb(n){let s=[...n].sort((o,c)=>o.path.localeCompare(c.path)).map((o)=>`${o.path}:${o.hash}`).join(`
2474
+ `);return Xm(s)}function Kb(n){let i=pt(n);return Xm(`${n}:${i.size}:${i.mtimeMs}`)}function Wb(n,i){let s=new Map(n.map((g)=>[g.path,g])),o=new Map(i.map((g)=>[g.path,g])),c=[],u=[],d=[];for(let[g,y]of o){let h=s.get(g);if(!h)c.push(y);else if(h.hash!==y.hash)u.push(y)}for(let[g,y]of s)if(!o.has(g))d.push(y);return{added:c,modified:u,deleted:d}}class Qy{cache;constructor(){this.cache=new Map}get(n){let i=pt(n),s=this.cache.get(n);if(s&&s.mtime===i.mtimeMs&&s.size===i.size)return s.hash;return}set(n,i){let s=pt(n);this.cache.set(n,{hash:i,mtime:s.mtimeMs,size:s.size})}async getOrCompute(n,i={}){let s=this.get(n);if(s)return s;let o=await Jm(n,i);return this.set(n,o),o}clear(){this.cache.clear()}}async function Dl(n,i={}){let s=i.concurrency||5,o=i.stopOnError??!0,c=[],u=[],d=Date.now(),g=[...n],y=[];async function h(v,T){try{let R=await v();c[T]=R}catch(R){let P=R instanceof Error?R:Error(String(R));if(u.push(P),o)throw g.length=0,P}}let A=0;while(g.length>0||y.length>0){while(y.length<s&&g.length>0){let v=g.shift(),T=A++,R=h(v,T);y.push(R)}if(y.length>0){await Promise.race(y);for(let v=y.length-1;v>=0;v--)if(await Promise.race([y[v].then(()=>!0),Promise.resolve(!1)]))y.splice(v,1)}if(o&&u.length>0)break}let C=Date.now()-d;return{results:c.filter((v)=>v!==void 0),errors:u,duration:C}}async function Jb(n,i,s={}){let o=n.map((c)=>()=>i(c));return Dl(o,s)}async function Xb(n,i,s=5){let o=n.map((u,d)=>()=>i(u,d)),c=await Dl(o,{concurrency:s,stopOnError:!1});if(c.errors.length>0)throw AggregateError(c.errors,"Parallel map failed");return c.results}async function Yb(n,i={}){let s=i.retries||3,o=i.retryDelay||1000,c=n.map((u)=>async()=>{let d;for(let g=0;g<=s;g++)try{return await u()}catch(y){if(d=y instanceof Error?y:Error(String(y)),g<s)await nr(o*(g+1))}throw d});return Dl(c,i)}async function Zb(n){let i=[];for(let s of n){let o=await s();i.push(o)}return i}function nr(n){return new Promise((i)=>setTimeout(i,n))}async function eC(n,i,s="Operation timed out"){return Promise.race([n(),new Promise((o,c)=>setTimeout(()=>c(Error(s)),i))])}class Hy{maxConcurrent;minInterval;queue=[];running=0;lastExecution=0;constructor(n=5,i=100){this.maxConcurrent=n;this.minInterval=i}async execute(n){await this.waitForSlot(),this.running++,this.lastExecution=Date.now();try{return await n()}finally{this.running--,this.processQueue()}}waitForSlot(){if(this.running<this.maxConcurrent){let n=Date.now()-this.lastExecution;if(n>=this.minInterval)return Promise.resolve();return nr(this.minInterval-n)}return new Promise((n)=>this.queue.push(n))}processQueue(){if(this.queue.length>0&&this.running<this.maxConcurrent)this.queue.shift()()}stats(){return{running:this.running,queued:this.queue.length}}}function Gy(n,i){let s=[];for(let o=0;o<n.length;o+=i)s.push(n.slice(o,o+i));return s}async function tC(n,i,s){let o=Gy(n,i),c=[];for(let u of o){let d=await s(u);c.push(...d)}return c}function rC(n,i){let s=[],o=[],c=[],u=[],d=n.Resources||{},g=i.Resources||{},y=new Set(Object.keys(d)),h=new Set(Object.keys(g));for(let v of h)if(!y.has(v))s.push(v);for(let v of y)if(!h.has(v))c.push(v);for(let v of h)if(y.has(v)){let T=d[v],R=g[v];if(JSON.stringify(T)!==JSON.stringify(R))o.push(v);else u.push(v)}let A=JSON.stringify(n.Parameters||{})!==JSON.stringify(i.Parameters||{}),C=JSON.stringify(n.Outputs||{})!==JSON.stringify(i.Outputs||{});return{added:s,modified:o,deleted:c,unchanged:u,parametersChanged:A,outputsChanged:C,hasChanges:s.length>0||o.length>0||c.length>0||A||C}}function nC(n){let i=[];if(!n.hasChanges)return"No changes detected";if(n.added.length>0){i.push(`Added resources (${n.added.length}):`);for(let s of n.added)i.push(` + ${s}`)}if(n.modified.length>0){i.push(`Modified resources (${n.modified.length}):`);for(let s of n.modified)i.push(` ~ ${s}`)}if(n.deleted.length>0){i.push(`Deleted resources (${n.deleted.length}):`);for(let s of n.deleted)i.push(` - ${s}`)}if(n.parametersChanged)i.push("Parameters changed");if(n.outputsChanged)i.push("Outputs changed");return i.join(`
2475
+ `)}function iC(n,i,s){if(n.deleted.length>0)return!0;for(let o of n.modified){let c=i.Resources[o],u=s.Resources[o];if(c.Type!==u.Type)return!0;let d=Ki(u.Type);for(let g of d){let y=c.Properties?.[g],h=u.Properties?.[g];if(JSON.stringify(y)!==JSON.stringify(h))return!0}}return!1}function Ki(n){return{"AWS::S3::Bucket":["BucketName"],"AWS::EC2::Instance":["ImageId","InstanceType","KeyName"],"AWS::RDS::DBInstance":["DBInstanceIdentifier","Engine"],"AWS::DynamoDB::Table":["TableName","KeySchema"],"AWS::Lambda::Function":["FunctionName"],"AWS::ECS::Service":["ServiceName"],"AWS::ElasticLoadBalancingV2::LoadBalancer":["Name","Type"]}[n]||[]}function sC(n){let i=[],s=[],o=[];i.push(...n.added);for(let c of n.modified)s.push(c);return o.push(...n.deleted),{safe:i,caution:s,dangerous:o}}function oC(n){if(!n.hasChanges)return{strategy:"skip",reason:"No changes detected"};if(n.deleted.length>0)return{strategy:"replace",reason:"Resources will be deleted"};if(n.added.length>0&&n.modified.length===0)return{strategy:"update",reason:"Only new resources added"};return{strategy:"update",reason:"Resources will be updated"}}function aC(n){let i=n.added.length+n.modified.length+n.deleted.length+n.unchanged.length,s=n.added.length+n.modified.length+n.deleted.length,o=i>0?s/i*100:0;return{total:i,added:n.added.length,modified:n.modified.length,deleted:n.deleted.length,unchanged:n.unchanged.length,changePercentage:o}}var Vy={$schema:"http://json-schema.org/draft-07/schema#",title:"ts-cloud Configuration",description:"Configuration schema for ts-cloud infrastructure-as-code",type:"object",required:["project"],properties:{project:{type:"object",description:"Project configuration",required:["name","slug"],properties:{name:{type:"string",description:"Human-readable project name",minLength:1},slug:{type:"string",description:"URL-safe project identifier (lowercase, alphanumeric, hyphens only)",pattern:"^[a-z0-9-]+$",minLength:1,maxLength:63},region:{type:"string",description:"Default AWS region",enum:["us-east-1","us-east-2","us-west-1","us-west-2","eu-west-1","eu-west-2","eu-west-3","eu-central-1","ap-southeast-1","ap-southeast-2","ap-northeast-1","ap-northeast-2","sa-east-1","ca-central-1"]}}},mode:{type:"string",description:"Deployment mode (server and serverless are mutually exclusive; auto-detected when omitted)",enum:["server","serverless"]},environments:{type:"object",description:"Environment-specific configurations",properties:{production:{$ref:"#/definitions/environment"},staging:{$ref:"#/definitions/environment"},development:{$ref:"#/definitions/environment"}}},infrastructure:{type:"object",description:"Infrastructure configuration",properties:{network:{$ref:"#/definitions/network"},storage:{type:"object",description:"S3 storage configuration",additionalProperties:{$ref:"#/definitions/storage"}},compute:{$ref:"#/definitions/compute"},database:{$ref:"#/definitions/database"},cache:{$ref:"#/definitions/cache"},cdn:{$ref:"#/definitions/cdn"},sftp:{$ref:"#/definitions/sftp"},functions:{type:"object",description:"Lambda functions configuration",additionalProperties:{type:"array",items:{$ref:"#/definitions/function"}}},monitoring:{$ref:"#/definitions/monitoring"},security:{$ref:"#/definitions/security"},queue:{type:"object",description:"SQS queue configuration",additionalProperties:{$ref:"#/definitions/queue"}}}}},definitions:{environment:{type:"object",properties:{domain:{type:"string",description:"Custom domain for this environment"},region:{type:"string",description:"AWS region override for this environment"},app:{type:"object",description:"Serverless application manifest (Laravel-Vapor-equivalent). Defining this opts the environment into the serverless app deploy pipeline (http/queue/cli Lambda functions, assets, build/deploy hooks).",properties:{runtime:{type:"string",description:"Lambda runtime override (usually derived from kind + runtimeVersion)"},runtimeVersion:{type:"string",description:"Node major (18/20/22 managed, 24+ custom layer) or Bun release for node/bun apps"},kind:{type:"string",enum:["node","bun","php"],description:"Application kind (drives packaging + runtime)"},entry:{type:"string",description:"Entry file exporting the request handler"},memory:{type:"number",description:"HTTP function memory in MB"},timeout:{type:"number",description:"HTTP request timeout in seconds"},gatewayVersion:{type:"number",enum:[1,2],description:"API Gateway version (2 = HTTP API, 1 = REST)"},warm:{type:"number",description:"Keep-warm / provisioned concurrency count"},lambdaInsights:{type:"object",description:"CloudWatch Lambda Insights extension configuration for zip deployments",required:["layerArn"],properties:{layerArn:{type:"string",description:"Region- and architecture-specific Lambda Insights extension layer ARN"}}},queues:{description:"Queue names (true = single default queue, false = disabled)"},scheduler:{type:"string",enum:["off","on","sub-minute"],description:"Task scheduler mode"},build:{type:"array",items:{type:"string"},description:"Commands run locally before packaging"},deploy:{type:"array",items:{type:"string"},description:"Commands run remotely after activation (e.g. migrations)"},octane:{type:"boolean",description:"Persistent application mode (Laravel Octane)"},packaging:{type:"string",enum:["zip","image"],description:"Deployment package format (zip or container image)"},phpVersion:{type:"string",description:"PHP version for the runtime layer (kind: php)"},architecture:{type:"string",enum:["x86_64","arm64"],description:"CPU architecture"}}}}},network:{type:"object",properties:{vpc:{type:"object",properties:{cidr:{type:"string",description:"VPC CIDR block",pattern:"^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]{1,2}$",default:"10.0.0.0/16"},availabilityZones:{type:"number",description:"Number of availability zones",minimum:1,maximum:3,default:2},natGateways:{type:"number",description:"Number of NAT gateways (0 for no NAT, saves cost)",minimum:0,maximum:3,default:1}}}}},storage:{type:"object",properties:{public:{type:"boolean",description:"Allow public access",default:!1},versioning:{type:"boolean",description:"Enable versioning",default:!1},encryption:{type:"boolean",description:"Enable server-side encryption",default:!0},website:{type:"boolean",description:"Enable static website hosting",default:!1},cors:{type:"object",description:"CORS configuration",properties:{allowedOrigins:{type:"array",items:{type:"string"}},allowedMethods:{type:"array",items:{type:"string",enum:["GET","PUT","POST","DELETE","HEAD"]}}}}}},compute:{type:"object",properties:{server:{type:"object",description:"EC2 server configuration",properties:{instanceType:{type:"string",description:"EC2 instance type",enum:["t3.micro","t3.small","t3.medium","t3.large","t3.xlarge","t3.2xlarge"]},autoScaling:{type:"object",properties:{min:{type:"number",minimum:1},max:{type:"number",minimum:1},desired:{type:"number",minimum:1}}}}},fargate:{type:"object",description:"ECS Fargate configuration",properties:{cpu:{type:"number",description:"CPU units (256, 512, 1024, 2048, 4096)",enum:[256,512,1024,2048,4096]},memory:{type:"number",description:"Memory in MB"},desiredCount:{type:"number",description:"Desired number of tasks",minimum:1}}}}},database:{type:"object",properties:{postgres:{type:"object",properties:{instanceClass:{type:"string",description:"RDS instance class",pattern:"^db\\.[a-z0-9]+\\.[a-z0-9]+$"},engine:{type:"string",const:"postgres"},version:{type:"string",description:"PostgreSQL version"},multiAZ:{type:"boolean",description:"Enable Multi-AZ deployment",default:!1},backupRetentionDays:{type:"number",description:"Backup retention period in days",minimum:0,maximum:35,default:7}}},mysql:{type:"object",properties:{instanceClass:{type:"string",pattern:"^db\\.[a-z0-9]+\\.[a-z0-9]+$"},engine:{type:"string",const:"mysql"},version:{type:"string"},multiAZ:{type:"boolean",default:!1},backupRetentionDays:{type:"number",minimum:0,maximum:35,default:7}}},dynamodb:{type:"object",properties:{tables:{type:"array",items:{type:"object",required:["name","partitionKey"],properties:{name:{type:"string"},partitionKey:{type:"string"},sortKey:{type:"string"},billingMode:{type:"string",enum:["PAY_PER_REQUEST","PROVISIONED"],default:"PAY_PER_REQUEST"}}}}}}}},cache:{type:"object",properties:{redis:{type:"object",properties:{nodeType:{type:"string",description:"ElastiCache node type",pattern:"^cache\\.[a-z0-9]+\\.[a-z0-9]+$"},numCacheNodes:{type:"number",minimum:1,default:1},engineVersion:{type:"string",description:"Redis engine version"}}},memcached:{type:"object",properties:{nodeType:{type:"string",pattern:"^cache\\.[a-z0-9]+\\.[a-z0-9]+$"},numCacheNodes:{type:"number",minimum:1,default:1}}}}},cdn:{type:"object",properties:{enabled:{type:"boolean",default:!0},originShield:{type:"boolean",description:"Enable CloudFront Origin Shield",default:!1},originShieldRegion:{type:"string",description:"AWS region used by CloudFront Origin Shield"},compress:{type:"boolean",description:"Enable automatic compression",default:!0},http3:{type:"boolean",description:"Enable HTTP/3 support",default:!0},customDomain:{type:"object",properties:{domain:{type:"string"},certificateArn:{type:"string"}}},cachePolicy:{type:"object",properties:{minTTL:{type:"number",minimum:0},defaultTTL:{type:"number",minimum:0},maxTTL:{type:"number",minimum:0}}}}},sftp:{type:"object",required:["bucket","users"],properties:{bucket:{type:"string",description:"S3 bucket backing the SFTP server"},endpointType:{type:"string",enum:["PUBLIC","VPC"],default:"PUBLIC"},endpointDetails:{type:"object",required:["vpcId","subnetIds"],properties:{vpcId:{type:"string"},subnetIds:{type:"array",items:{type:"string"},minItems:1},securityGroupIds:{type:"array",items:{type:"string"}},addressAllocationIds:{type:"array",items:{type:"string"}}}},securityPolicyName:{type:"string"},logging:{type:"boolean",default:!0},users:{type:"object",additionalProperties:{type:"object",required:["sshPublicKeys"],properties:{sshPublicKeys:{type:"array",items:{type:"string"},minItems:1},homeDirectory:{type:"string"},roleArn:{type:"string"}}}}}},function:{type:"object",required:["name","runtime"],properties:{name:{type:"string"},runtime:{type:"string",enum:["nodejs18.x","nodejs20.x","python3.10","python3.11","python3.12"]},handler:{type:"string",default:"index.handler"},timeout:{type:"number",minimum:1,maximum:900,default:30},memory:{type:"number",minimum:128,maximum:10240,default:1024}}},monitoring:{type:"object",properties:{alarms:{type:"array",items:{type:"object",required:["metric","threshold"],properties:{metric:{type:"string"},threshold:{type:"number"},evaluationPeriods:{type:"number",minimum:1,default:2}}}},dashboard:{type:"object",properties:{name:{type:"string"},widgets:{type:"array"}}}}},security:{type:"object",properties:{waf:{type:"boolean",description:"Enable AWS WAF",default:!1},certificates:{type:"array",items:{type:"object",required:["domain"],properties:{domain:{type:"string"},subdomains:{type:"array",items:{type:"string"}}}}}}},queue:{type:"object",properties:{fifo:{type:"boolean",default:!1},deadLetterQueue:{type:"boolean",default:!0},visibilityTimeout:{type:"number",minimum:0,maximum:43200,default:30},messageRetentionPeriod:{type:"number",minimum:60,maximum:1209600,default:345600}}}}};function cC(n){let i=[];if(!n.project)i.push("Missing required field: project");else{if(!n.project.name)i.push("Missing required field: project.name");if(!n.project.slug)i.push("Missing required field: project.slug")}if(n.project?.slug&&!/^[a-z0-9-]+$/.test(n.project.slug))i.push("Invalid project.slug: must contain only lowercase letters, numbers, and hyphens");let s=["us-east-1","us-east-2","us-west-1","us-west-2","eu-west-1","eu-west-2","eu-west-3","eu-central-1","ap-southeast-1","ap-southeast-2","ap-northeast-1","ap-northeast-2","sa-east-1","ca-central-1"];if(n.project?.region&&!s.includes(n.project.region))i.push(`Invalid region: ${n.project.region}. Must be one of: ${s.join(", ")}`);if(n.mode&&!["server","serverless"].includes(n.mode))i.push("Invalid mode: must be one of server or serverless");return{valid:i.length===0,errors:i}}var Ym={enabled:process.env.TS_CLOUD_LOCAL==="true"||!0,localstackEndpoint:process.env.LOCALSTACK_ENDPOINT||"http://localhost:4566",postgresUrl:process.env.POSTGRES_URL||"postgresql://tscloud:tscloud@localhost:5432/tscloud",redisUrl:process.env.REDIS_URL||"redis://localhost:6379",dynamodbEndpoint:process.env.DYNAMODB_ENDPOINT||"http://localhost:8000",s3Endpoint:process.env.S3_ENDPOINT||"http://localhost:9000",emailEndpoint:process.env.EMAIL_ENDPOINT||"smtp://localhost:1025",awsRegion:process.env.AWS_REGION||"us-east-1",awsAccessKeyId:process.env.AWS_ACCESS_KEY_ID||"test",awsSecretAccessKey:process.env.AWS_SECRET_ACCESS_KEY||"test"};function Pl(){return Ym}function dC(){return Ym.enabled}function lC(n){let i=Pl();if(!i.enabled)return"";switch(n.toLowerCase()){case"dynamodb":return i.dynamodbEndpoint;case"s3":return i.s3Endpoint;case"localstack":case"cloudformation":case"lambda":case"apigateway":case"sns":case"sqs":case"cloudwatch":case"iam":case"sts":return i.localstackEndpoint;default:return i.localstackEndpoint}}function uC(){let n=Pl();return{accessKeyId:n.awsAccessKeyId,secretAccessKey:n.awsSecretAccessKey,region:n.awsRegion}}function gC(){let n=Pl();if(!n.enabled)return{};return{AWS_ACCESS_KEY_ID:n.awsAccessKeyId,AWS_SECRET_ACCESS_KEY:n.awsSecretAccessKey,AWS_REGION:n.awsRegion,AWS_ENDPOINT_URL:n.localstackEndpoint,LOCALSTACK_ENDPOINT:n.localstackEndpoint,TS_CLOUD_LOCAL:"true"}}class Zm{stacks=new Map;stackEvents=new Map;async createStack(n){let i=`arn:aws:cloudformation:${n.region||"us-east-1"}:123456789012:stack/${n.StackName}/${Date.now()}`;return this.stacks.set(n.StackName,{StackId:i,StackName:n.StackName,StackStatus:"CREATE_IN_PROGRESS",CreationTime:new Date().toISOString(),TemplateBody:n.TemplateBody,Parameters:n.Parameters||[]}),this.addEvent(n.StackName,{EventId:Date.now().toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_IN_PROGRESS"}),setTimeout(()=>{let s=this.stacks.get(n.StackName);if(s)s.StackStatus="CREATE_COMPLETE",this.addEvent(n.StackName,{EventId:(Date.now()+1).toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"CREATE_COMPLETE"})},100),{StackId:i}}async updateStack(n){let i=this.stacks.get(n.StackName);if(!i)throw Error(`Stack ${n.StackName} does not exist`);return i.StackStatus="UPDATE_IN_PROGRESS",i.TemplateBody=n.TemplateBody||i.TemplateBody,this.addEvent(n.StackName,{EventId:Date.now().toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_IN_PROGRESS"}),setTimeout(()=>{i.StackStatus="UPDATE_COMPLETE",this.addEvent(n.StackName,{EventId:(Date.now()+1).toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"UPDATE_COMPLETE"})},100),{StackId:i.StackId}}async deleteStack(n){let i=this.stacks.get(n.StackName);if(!i)throw Error(`Stack ${n.StackName} does not exist`);i.StackStatus="DELETE_IN_PROGRESS",this.addEvent(n.StackName,{EventId:Date.now().toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_IN_PROGRESS"}),setTimeout(()=>{this.stacks.delete(n.StackName),this.addEvent(n.StackName,{EventId:(Date.now()+1).toString(),StackName:n.StackName,LogicalResourceId:n.StackName,ResourceType:"AWS::CloudFormation::Stack",Timestamp:new Date().toISOString(),ResourceStatus:"DELETE_COMPLETE"})},100)}async describeStacks(n){if(n.StackName){let i=this.stacks.get(n.StackName);if(!i)throw Error(`Stack ${n.StackName} does not exist`);return{Stacks:[i]}}return{Stacks:Array.from(this.stacks.values())}}async describeStackEvents(n){return{StackEvents:this.stackEvents.get(n.StackName)||[]}}addEvent(n,i){if(!this.stackEvents.has(n))this.stackEvents.set(n,[]);this.stackEvents.get(n).unshift(i)}reset(){this.stacks.clear(),this.stackEvents.clear()}}class ef{buckets=new Map;async createBucket(n){return this.buckets.set(n.Bucket,new Map),{Location:`/${n.Bucket}`}}async deleteBucket(n){this.buckets.delete(n.Bucket)}async putObject(n){let i=this.buckets.get(n.Bucket);if(!i)i=new Map,this.buckets.set(n.Bucket,i);return i.set(n.Key,Buffer.from(n.Body||"")),{ETag:`"${Date.now()}"`}}async getObject(n){let i=this.buckets.get(n.Bucket);if(!i)throw Error(`Bucket ${n.Bucket} does not exist`);let s=i.get(n.Key);if(!s)throw Error(`Object ${n.Key} does not exist`);return{Body:s,ContentLength:s.length}}async deleteObject(n){let i=this.buckets.get(n.Bucket);if(i)i.delete(n.Key)}async listObjects(n){let i=this.buckets.get(n.Bucket);if(!i)throw Error(`Bucket ${n.Bucket} does not exist`);return{Contents:Array.from(i.keys()).map((o)=>({Key:o,Size:i.get(o).length,LastModified:new Date().toISOString()}))}}reset(){this.buckets.clear()}}class tf{tables=new Map;data=new Map;async createTable(n){return this.tables.set(n.TableName,{TableName:n.TableName,KeySchema:n.KeySchema,AttributeDefinitions:n.AttributeDefinitions,TableStatus:"ACTIVE",CreationDateTime:new Date().toISOString()}),this.data.set(n.TableName,new Map),{TableDescription:this.tables.get(n.TableName)}}async deleteTable(n){this.tables.delete(n.TableName),this.data.delete(n.TableName)}async putItem(n){let i=this.data.get(n.TableName);if(!i)i=new Map,this.data.set(n.TableName,i);let s=JSON.stringify(n.Item);i.set(s,n.Item)}async getItem(n){let i=this.data.get(n.TableName);if(!i)return{};let s=JSON.stringify(n.Key),o=i.get(s);return o?{Item:o}:{}}async deleteItem(n){let i=this.data.get(n.TableName);if(i){let s=JSON.stringify(n.Key);i.delete(s)}}async scan(n){let i=this.data.get(n.TableName);if(!i)return{Items:[]};return{Items:Array.from(i.values())}}reset(){this.tables.clear(),this.data.clear()}}function pC(n){return{cloudformation:new Zm,s3:new ef,dynamodb:new tf}}class kl{environments=new Map;async createPreviewEnvironment(n){let{branch:i,pr:s,commitSha:o,ttl:c=24,baseConfig:u,region:d="us-east-1"}=n,g=this.generatePreviewId(i,s,o),y=this.generatePreviewName(i,s),h=`preview-${y}`,A=new Date,C=new Date(A.getTime()+c*60*60*1000),v={id:g,name:y,branch:i,pr:s,commitSha:o,createdAt:A,expiresAt:C,status:"creating",stackName:h,region:d,resources:[]};this.environments.set(g,v);try{let T=this.createPreviewConfig(u,y);return v.status="active",v.url=`https://${y}.preview.example.com`,v}catch(T){throw v.status="failed",T}}async destroyPreviewEnvironment(n){let i=this.environments.get(n);if(!i)throw Error(`Preview environment ${n} not found`);i.status="destroying";try{i.status="destroyed",this.environments.delete(n)}catch(s){throw Error(`Failed to destroy preview environment: ${s}`)}}getPreviewEnvironment(n){return this.environments.get(n)}getPreviewEnvironmentByBranch(n){return Array.from(this.environments.values()).find((i)=>i.branch===n)}getPreviewEnvironmentByPR(n){return Array.from(this.environments.values()).find((i)=>i.pr===n)}listPreviewEnvironments(){return Array.from(this.environments.values())}listActivePreviewEnvironments(){return this.listPreviewEnvironments().filter((n)=>n.status==="active")}async cleanupExpiredEnvironments(n={}){let{maxAge:i,keepCount:s,dryRun:o=!1}=n,c=[],u=[],d=new Date,g=this.listPreviewEnvironments().sort((y,h)=>h.createdAt.getTime()-y.createdAt.getTime());for(let y=0;y<g.length;y++){let h=g[y];if(h.status!=="active")continue;let A=!1;if(h.expiresAt<d)A=!0;if(i){if((d.getTime()-h.createdAt.getTime())/3600000>i)A=!0}if(s&&y>=s)A=!0;if(A)if(o)c.push(h.id);else try{await this.destroyPreviewEnvironment(h.id),c.push(h.id)}catch(C){u.push(h.id)}}return{destroyed:c,failed:u}}async updatePreviewEnvironment(n,i){let s=this.environments.get(n);if(!s)throw Error(`Preview environment ${n} not found`);s.commitSha=i,s.status="creating";try{return s.status="active",s}catch(o){throw s.status="failed",o}}async getPreviewEnvironmentsCost(){let n={},i=0;for(let s of this.environments.values())n[s.id]=0,i+=0;return{total:i,byEnvironment:n}}generatePreviewId(n,i,s){let o=n.replace(/[^a-z0-9-]/gi,"-").toLowerCase(),c=s?.substring(0,7)||Date.now().toString();return i?`pr-${i}-${c}`:`${o}-${c}`}generatePreviewName(n,i){let s=n.replace(/[^a-z0-9-]/gi,"-").toLowerCase();return i?`pr-${i}`:s}createPreviewConfig(n,i){return{...n,project:{...n.project,name:`${n.project.name} Preview (${i})`,slug:`${n.project.slug}-preview-${i}`}}}}var qy=new kl;function jy(n={}){let{workflowName:i="Preview Environment",trigger:s="pull_request",branches:o=["main","develop"],awsRegion:c="us-east-1",awsRole:u,configFile:d="cloud.config.ts",ttl:g=24}=n;return`name: ${i}
2478
2476
 
2479
2477
  on:
2480
2478
  ${s}:
@@ -2608,7 +2606,7 @@ jobs:
2608
2606
  run: |
2609
2607
  # Clean up environments older than TTL
2610
2608
  bun run cloud env:cleanup --max-age=\${{ env.TTL_HOURS }}
2611
- `}function _y(n={}){let{schedule:i="0 0 * * *",maxAge:s=48,keepCount:o=10}=n;return`name: Cleanup Stale Preview Environments
2609
+ `}function zy(n={}){let{schedule:i="0 0 * * *",maxAge:s=48,keepCount:o=10}=n;return`name: Cleanup Stale Preview Environments
2612
2610
 
2613
2611
  on:
2614
2612
  schedule:
@@ -2653,7 +2651,7 @@ jobs:
2653
2651
  - name: Report cleanup results
2654
2652
  run: |
2655
2653
  bun run cloud env:list --status=destroyed
2656
- `}function Ly(n={}){let{schedule:i="0 8 * * 1",webhookUrl:s}=n;return`name: Preview Environment Cost Report
2654
+ `}function Ky(n={}){let{schedule:i="0 8 * * 1",webhookUrl:s}=n;return`name: Preview Environment Cost Report
2657
2655
 
2658
2656
  on:
2659
2657
  schedule:
@@ -2702,15 +2700,15 @@ jobs:
2702
2700
  curl -X POST -H 'Content-type: application/json' \\
2703
2701
  --data '{"text":"Preview Environment Cost Report\\n\${{ steps.cost.outputs.cost_json }}"}' \\
2704
2702
  $SLACK_WEBHOOK_URL`:'run: |\n echo "${{ steps.cost.outputs.cost_json }}"'}
2705
- `}class Cl{channels=[];addChannel(n){this.channels.push(n)}removeChannel(n){this.channels=this.channels.filter((i)=>i.type!==n)}async notify(n){let i=this.channels.map((s)=>this.sendToChannel(s,n));await Promise.allSettled(i)}async sendToChannel(n,i){switch(n.type){case"slack":await this.sendToSlack(n.config,i);break;case"discord":await this.sendToDiscord(n.config,i);break;case"email":await this.sendToEmail(n.config,i);break;case"webhook":await this.sendToWebhook(n.config,i);break}}async sendToSlack(n,i){let s=this.formatSlackMessage(i,n),o=await fetch(n.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!o.ok)throw Error(`Failed to send Slack notification: ${o.statusText}`)}formatSlackMessage(n,i){let{environment:s,type:o}=n,c={created:":rocket:",updated:":arrows_counterclockwise:",destroyed:":wastebasket:",failed:":x:",expired:":hourglass_flowing_sand:"}[o],u={created:"#36a64f",updated:"#2196F3",destroyed:"#808080",failed:"#f44336",expired:"#ff9800"}[o],d={created:"Preview Environment Created",updated:"Preview Environment Updated",destroyed:"Preview Environment Destroyed",failed:"Preview Environment Failed",expired:"Preview Environment Expired"}[o];return{username:i.username||"ts-cloud",icon_emoji:i.iconEmoji||":cloud:",channel:i.channel,attachments:[{color:u,title:`${c} ${d}`,fields:[{title:"Environment",value:s.name,short:!0},{title:"Branch",value:s.branch,short:!0},...s.pr?[{title:"PR",value:`#${s.pr}`,short:!0}]:[],{title:"Commit",value:s.commitSha.substring(0,7),short:!0},...s.url?[{title:"URL",value:s.url,short:!1}]:[],...o==="created"?[{title:"Expires",value:s.expiresAt.toLocaleString(),short:!0}]:[]],footer:"ts-cloud Preview Environments",ts:Math.floor(n.timestamp.getTime()/1000)}]}}async sendToDiscord(n,i){let s=this.formatDiscordMessage(i,n),o=await fetch(n.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!o.ok)throw Error(`Failed to send Discord notification: ${o.statusText}`)}formatDiscordMessage(n,i){let{environment:s,type:o}=n,c={created:":rocket:",updated:":arrows_counterclockwise:",destroyed:":wastebasket:",failed:":x:",expired:":hourglass:"}[o],u={created:3581519,updated:2201331,destroyed:8421504,failed:16007990,expired:16750592}[o],d={created:"Preview Environment Created",updated:"Preview Environment Updated",destroyed:"Preview Environment Destroyed",failed:"Preview Environment Failed",expired:"Preview Environment Expired"}[o];return{username:i.username||"ts-cloud",avatar_url:i.avatarUrl,embeds:[{title:`${c} ${d}`,color:u,fields:[{name:"Environment",value:s.name,inline:!0},{name:"Branch",value:s.branch,inline:!0},...s.pr?[{name:"PR",value:`#${s.pr}`,inline:!0}]:[],{name:"Commit",value:`\`${s.commitSha.substring(0,7)}\``,inline:!0},...s.url?[{name:"URL",value:s.url,inline:!1}]:[]],timestamp:n.timestamp.toISOString(),footer:{text:"ts-cloud Preview Environments"}}]}}async sendToEmail(n,i){console.log(`Email notification would be sent to ${n.to.join(", ")}`)}async sendToWebhook(n,i){let s=await fetch(n.url,{method:n.method||"POST",headers:{"Content-Type":"application/json",...n.headers},body:JSON.stringify({event:i.type,environment:i.environment,timestamp:i.timestamp.toISOString(),metadata:i.metadata})});if(!s.ok)throw Error(`Failed to send webhook notification: ${s.statusText}`)}}var $y=new Cl;function tC(n){let{columns:i,data:s,border:o=!0,header:c=!0,compact:u=!1,maxWidth:d}=n;if(s.length===0)return"No data to display";let g=i.map((h)=>{let A=h.label.length,C=Math.max(...s.map((T)=>(h.formatter?h.formatter(T[h.key]):String(T[h.key]||"")).length)),v=h.width||Math.max(A,C);if(d&&v>d)v=d;return v}),y=[];if(o)y.push(Ft(g,"top",u));if(c){if(y.push(Un(i.map((h)=>h.label),g,i.map((h)=>h.align||"left"),o)),o)y.push(Ft(g,"middle",u))}for(let h of s){let A=i.map((C)=>{let v=C.formatter?C.formatter(h[C.key]):String(h[C.key]||"");return Ei(v,g[i.indexOf(C)])});y.push(Un(A,g,i.map((C)=>C.align||"left"),o))}if(o)y.push(Ft(g,"bottom",u));return y.join(`
2706
- `)}function Un(n,i,s,o){let c=n.map((u,d)=>{let g=i[d],y=s[d];return Pi(u,g,y)});if(o)return`│ ${c.join(" │ ")} │`;return c.join(" ")}function Ft(n,i,s){let o=i==="top"?"┌":i==="middle"?"├":"└",c=i==="top"?"┐":i==="middle"?"┤":"┘",u=i==="top"?"┬":i==="middle"?"┼":"┴",d="─";if(s)return o+n.map((g)=>"─".repeat(g+2)).join(u)+c;return o+n.map((g)=>"─".repeat(g+2)).join(u)+c}function Pi(n,i,s){let o=Hn(n).length;if(o>=i)return n;let c=i-o;switch(s){case"right":return" ".repeat(c)+n;case"center":{let u=Math.floor(c/2),d=c-u;return" ".repeat(u)+n+" ".repeat(d)}default:return n+" ".repeat(c)}}function Ei(n,i){if(Hn(n).length<=i)return n;return n.substring(0,i-1)+"…"}function Hn(n){return n.replace(/\x1B\[[0-9;]*m/g,"")}function rC(n,i={}){let{indent:s=" ",showMetadata:o=!1}=i,c=[];function u(d,g,y){let A=g+(y?"└─ ":"├─ ")+d.label;if(c.push(A),o&&d.metadata){let C=g+(y?" ":"│ ");for(let[v,T]of Object.entries(d.metadata))c.push(`${C}${v}: ${T}`)}if(d.children&&d.children.length>0){let C=g+(y?" ":"│ ");d.children.forEach((v,T)=>{u(v,C,T===d.children.length-1)})}}return n.forEach((d,g)=>{u(d,"",g===n.length-1)}),c.join(`
2707
- `)}function nC(n){let{total:i,current:s,width:o=40,format:c=":bar :percent :current/:total",complete:u="█",incomplete:d="░"}=n,g=Math.min(100,Math.max(0,s/i*100)),y=Math.floor(o*s/i),h=o-y,A=u.repeat(y)+d.repeat(h);return c.replace(":bar",A).replace(":percent",`${g.toFixed(0)}%`).replace(":current",String(s)).replace(":total",String(i))}function iC(n,i=2){if(n===0)return"0 Bytes";let s=1024,o=i<0?0:i,c=["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"],u=Math.floor(Math.log(n)/Math.log(s));return`${Number.parseFloat((n/Math.pow(s,u)).toFixed(o))} ${c[u]}`}function sC(n){if(n<1000)return`${n}ms`;let i=Math.floor(n/1000);if(i<60)return`${i}s`;let s=Math.floor(i/60),o=i%60;if(s<60)return o>0?`${s}m ${o}s`:`${s}m`;let c=Math.floor(s/60),u=s%60;if(c<24)return u>0?`${c}h ${u}m`:`${c}h`;let d=Math.floor(c/24),g=c%24;return g>0?`${d}d ${g}h`:`${d}d`}function oC(n,i="•"){return n.map((s)=>`${i} ${s}`).join(`
2708
- `)}function aC(n,i={}){let{indent:s="",separator:o=": "}=i,c=Math.max(...Object.keys(n).map((u)=>u.length));return Object.entries(n).map(([u,d])=>{let g=u.padEnd(c);return`${s}${g}${o}${d}`}).join(`
2709
- `)}class My{total;current=0;width;format;message;showETA;showPercentage;showCounter;startTime=Date.now();lastUpdate=0;constructor(n){this.total=n.total,this.current=n.current||0,this.width=n.width||40,this.format=n.format||":message :bar :percent :eta",this.message=n.message||"Progress",this.showETA=n.showETA!==!1,this.showPercentage=n.showPercentage!==!1,this.showCounter=n.showCounter!==!1}tick(n=1){this.current=Math.min(this.total,this.current+n),this.lastUpdate=Date.now()}update(n){this.current=Math.min(this.total,Math.max(0,n)),this.lastUpdate=Date.now()}setMessage(n){this.message=n}getPercentage(){return Math.min(100,this.current/this.total*100)}getETA(){if(this.current===0)return 0;let n=Date.now()-this.startTime,i=this.current/n,s=this.total-this.current;return Math.round(s/i)}getETAFormatted(){if(this.current===0)return"calculating...";if(this.current===this.total)return"complete";let n=this.getETA();if(n<1000)return"< 1s";if(n<60000)return`${Math.round(n/1000)}s`;let i=Math.floor(n/60000);if(i<60)return`${i}m`;let s=Math.floor(i/60),o=i%60;if(s<24)return o>0?`${s}h ${o}m`:`${s}h`;let c=Math.floor(s/24),u=s%24;return u>0?`${c}d ${u}h`:`${c}d`}render(){let n=this.getPercentage(),i=Math.floor(this.width*this.current/this.total),s=this.width-i,o="█".repeat(i)+"░".repeat(s),c=`${n.toFixed(1)}%`,u=`${this.current}/${this.total}`,d=this.showETA?`ETA: ${this.getETAFormatted()}`:"",g=this.format.replace(":message",this.message).replace(":bar",o).replace(":percent",this.showPercentage?c:"").replace(":counter",this.showCounter?u:"").replace(":eta",d).replace(":current",String(this.current)).replace(":total",String(this.total));return g=g.replace(/\s+/g," ").trim(),g}isComplete(){return this.current>=this.total}}class Fy{steps;currentStepIndex=0;constructor(n){this.steps=n.map((i)=>({name:i,status:"pending"}))}startStep(n,i){if(n>=0&&n<this.steps.length)this.steps[n].status="active",this.steps[n].message=i,this.currentStepIndex=n}completeStep(n){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="completed",this.steps[this.currentStepIndex].message=n,this.currentStepIndex++}failStep(n){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="failed",this.steps[this.currentStepIndex].error=n}skipStep(n){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="skipped",this.steps[this.currentStepIndex].message=n,this.currentStepIndex++}getStep(n){return this.steps[n]}getSteps(){return this.steps}render(){let n=[];for(let i of this.steps){let o=`${this.getStatusIcon(i.status)} ${i.name}`;if(i.message)o+=` - ${i.message}`;if(i.error)o+=`
2703
+ `}class Nl{channels=[];addChannel(n){this.channels.push(n)}removeChannel(n){this.channels=this.channels.filter((i)=>i.type!==n)}async notify(n){let i=this.channels.map((s)=>this.sendToChannel(s,n));await Promise.allSettled(i)}async sendToChannel(n,i){switch(n.type){case"slack":await this.sendToSlack(n.config,i);break;case"discord":await this.sendToDiscord(n.config,i);break;case"email":await this.sendToEmail(n.config,i);break;case"webhook":await this.sendToWebhook(n.config,i);break}}async sendToSlack(n,i){let s=this.formatSlackMessage(i,n),o=await fetch(n.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!o.ok)throw Error(`Failed to send Slack notification: ${o.statusText}`)}formatSlackMessage(n,i){let{environment:s,type:o}=n,c={created:":rocket:",updated:":arrows_counterclockwise:",destroyed:":wastebasket:",failed:":x:",expired:":hourglass_flowing_sand:"}[o],u={created:"#36a64f",updated:"#2196F3",destroyed:"#808080",failed:"#f44336",expired:"#ff9800"}[o],d={created:"Preview Environment Created",updated:"Preview Environment Updated",destroyed:"Preview Environment Destroyed",failed:"Preview Environment Failed",expired:"Preview Environment Expired"}[o];return{username:i.username||"ts-cloud",icon_emoji:i.iconEmoji||":cloud:",channel:i.channel,attachments:[{color:u,title:`${c} ${d}`,fields:[{title:"Environment",value:s.name,short:!0},{title:"Branch",value:s.branch,short:!0},...s.pr?[{title:"PR",value:`#${s.pr}`,short:!0}]:[],{title:"Commit",value:s.commitSha.substring(0,7),short:!0},...s.url?[{title:"URL",value:s.url,short:!1}]:[],...o==="created"?[{title:"Expires",value:s.expiresAt.toLocaleString(),short:!0}]:[]],footer:"ts-cloud Preview Environments",ts:Math.floor(n.timestamp.getTime()/1000)}]}}async sendToDiscord(n,i){let s=this.formatDiscordMessage(i,n),o=await fetch(n.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!o.ok)throw Error(`Failed to send Discord notification: ${o.statusText}`)}formatDiscordMessage(n,i){let{environment:s,type:o}=n,c={created:":rocket:",updated:":arrows_counterclockwise:",destroyed:":wastebasket:",failed:":x:",expired:":hourglass:"}[o],u={created:3581519,updated:2201331,destroyed:8421504,failed:16007990,expired:16750592}[o],d={created:"Preview Environment Created",updated:"Preview Environment Updated",destroyed:"Preview Environment Destroyed",failed:"Preview Environment Failed",expired:"Preview Environment Expired"}[o];return{username:i.username||"ts-cloud",avatar_url:i.avatarUrl,embeds:[{title:`${c} ${d}`,color:u,fields:[{name:"Environment",value:s.name,inline:!0},{name:"Branch",value:s.branch,inline:!0},...s.pr?[{name:"PR",value:`#${s.pr}`,inline:!0}]:[],{name:"Commit",value:`\`${s.commitSha.substring(0,7)}\``,inline:!0},...s.url?[{name:"URL",value:s.url,inline:!1}]:[]],timestamp:n.timestamp.toISOString(),footer:{text:"ts-cloud Preview Environments"}}]}}async sendToEmail(n,i){console.log(`Email notification would be sent to ${n.to.join(", ")}`)}async sendToWebhook(n,i){let s=await fetch(n.url,{method:n.method||"POST",headers:{"Content-Type":"application/json",...n.headers},body:JSON.stringify({event:i.type,environment:i.environment,timestamp:i.timestamp.toISOString(),metadata:i.metadata})});if(!s.ok)throw Error(`Failed to send webhook notification: ${s.statusText}`)}}var Wy=new Nl;function mC(n){let{columns:i,data:s,border:o=!0,header:c=!0,compact:u=!1,maxWidth:d}=n;if(s.length===0)return"No data to display";let g=i.map((h)=>{let A=h.label.length,C=Math.max(...s.map((T)=>(h.formatter?h.formatter(T[h.key]):String(T[h.key]||"")).length)),v=h.width||Math.max(A,C);if(d&&v>d)v=d;return v}),y=[];if(o)y.push(Ut(g,"top",u));if(c){if(y.push(rr(i.map((h)=>h.label),g,i.map((h)=>h.align||"left"),o)),o)y.push(Ut(g,"middle",u))}for(let h of s){let A=i.map((C)=>{let v=C.formatter?C.formatter(h[C.key]):String(h[C.key]||"");return Qi(v,g[i.indexOf(C)])});y.push(rr(A,g,i.map((C)=>C.align||"left"),o))}if(o)y.push(Ut(g,"bottom",u));return y.join(`
2704
+ `)}function rr(n,i,s,o){let c=n.map((u,d)=>{let g=i[d],y=s[d];return zi(u,g,y)});if(o)return`│ ${c.join(" │ ")} │`;return c.join(" ")}function Ut(n,i,s){let o=i==="top"?"┌":i==="middle"?"├":"└",c=i==="top"?"┐":i==="middle"?"┤":"┘",u=i==="top"?"┬":i==="middle"?"┼":"┴",d="─";if(s)return o+n.map((g)=>"─".repeat(g+2)).join(u)+c;return o+n.map((g)=>"─".repeat(g+2)).join(u)+c}function zi(n,i,s){let o=ir(n).length;if(o>=i)return n;let c=i-o;switch(s){case"right":return" ".repeat(c)+n;case"center":{let u=Math.floor(c/2),d=c-u;return" ".repeat(u)+n+" ".repeat(d)}default:return n+" ".repeat(c)}}function Qi(n,i){if(ir(n).length<=i)return n;return n.substring(0,i-1)+"…"}function ir(n){return n.replace(/\x1B\[[0-9;]*m/g,"")}function fC(n,i={}){let{indent:s=" ",showMetadata:o=!1}=i,c=[];function u(d,g,y){let A=g+(y?"└─ ":"├─ ")+d.label;if(c.push(A),o&&d.metadata){let C=g+(y?" ":"│ ");for(let[v,T]of Object.entries(d.metadata))c.push(`${C}${v}: ${T}`)}if(d.children&&d.children.length>0){let C=g+(y?" ":"│ ");d.children.forEach((v,T)=>{u(v,C,T===d.children.length-1)})}}return n.forEach((d,g)=>{u(d,"",g===n.length-1)}),c.join(`
2705
+ `)}function hC(n){let{total:i,current:s,width:o=40,format:c=":bar :percent :current/:total",complete:u="█",incomplete:d="░"}=n,g=Math.min(100,Math.max(0,s/i*100)),y=Math.floor(o*s/i),h=o-y,A=u.repeat(y)+d.repeat(h);return c.replace(":bar",A).replace(":percent",`${g.toFixed(0)}%`).replace(":current",String(s)).replace(":total",String(i))}function AC(n,i=2){if(n===0)return"0 Bytes";let s=1024,o=i<0?0:i,c=["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"],u=Math.floor(Math.log(n)/Math.log(s));return`${Number.parseFloat((n/Math.pow(s,u)).toFixed(o))} ${c[u]}`}function yC(n){if(n<1000)return`${n}ms`;let i=Math.floor(n/1000);if(i<60)return`${i}s`;let s=Math.floor(i/60),o=i%60;if(s<60)return o>0?`${s}m ${o}s`:`${s}m`;let c=Math.floor(s/60),u=s%60;if(c<24)return u>0?`${c}h ${u}m`:`${c}h`;let d=Math.floor(c/24),g=c%24;return g>0?`${d}d ${g}h`:`${d}d`}function SC(n,i="•"){return n.map((s)=>`${i} ${s}`).join(`
2706
+ `)}function IC(n,i={}){let{indent:s="",separator:o=": "}=i,c=Math.max(...Object.keys(n).map((u)=>u.length));return Object.entries(n).map(([u,d])=>{let g=u.padEnd(c);return`${s}${g}${o}${d}`}).join(`
2707
+ `)}class Jy{total;current=0;width;format;message;showETA;showPercentage;showCounter;startTime=Date.now();lastUpdate=0;constructor(n){this.total=n.total,this.current=n.current||0,this.width=n.width||40,this.format=n.format||":message :bar :percent :eta",this.message=n.message||"Progress",this.showETA=n.showETA!==!1,this.showPercentage=n.showPercentage!==!1,this.showCounter=n.showCounter!==!1}tick(n=1){this.current=Math.min(this.total,this.current+n),this.lastUpdate=Date.now()}update(n){this.current=Math.min(this.total,Math.max(0,n)),this.lastUpdate=Date.now()}setMessage(n){this.message=n}getPercentage(){return Math.min(100,this.current/this.total*100)}getETA(){if(this.current===0)return 0;let n=Date.now()-this.startTime,i=this.current/n,s=this.total-this.current;return Math.round(s/i)}getETAFormatted(){if(this.current===0)return"calculating...";if(this.current===this.total)return"complete";let n=this.getETA();if(n<1000)return"< 1s";if(n<60000)return`${Math.round(n/1000)}s`;let i=Math.floor(n/60000);if(i<60)return`${i}m`;let s=Math.floor(i/60),o=i%60;if(s<24)return o>0?`${s}h ${o}m`:`${s}h`;let c=Math.floor(s/24),u=s%24;return u>0?`${c}d ${u}h`:`${c}d`}render(){let n=this.getPercentage(),i=Math.floor(this.width*this.current/this.total),s=this.width-i,o="█".repeat(i)+"░".repeat(s),c=`${n.toFixed(1)}%`,u=`${this.current}/${this.total}`,d=this.showETA?`ETA: ${this.getETAFormatted()}`:"",g=this.format.replace(":message",this.message).replace(":bar",o).replace(":percent",this.showPercentage?c:"").replace(":counter",this.showCounter?u:"").replace(":eta",d).replace(":current",String(this.current)).replace(":total",String(this.total));return g=g.replace(/\s+/g," ").trim(),g}isComplete(){return this.current>=this.total}}class Xy{steps;currentStepIndex=0;constructor(n){this.steps=n.map((i)=>({name:i,status:"pending"}))}startStep(n,i){if(n>=0&&n<this.steps.length)this.steps[n].status="active",this.steps[n].message=i,this.currentStepIndex=n}completeStep(n){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="completed",this.steps[this.currentStepIndex].message=n,this.currentStepIndex++}failStep(n){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="failed",this.steps[this.currentStepIndex].error=n}skipStep(n){if(this.currentStepIndex>=0&&this.currentStepIndex<this.steps.length)this.steps[this.currentStepIndex].status="skipped",this.steps[this.currentStepIndex].message=n,this.currentStepIndex++}getStep(n){return this.steps[n]}getSteps(){return this.steps}render(){let n=[];for(let i of this.steps){let o=`${this.getStatusIcon(i.status)} ${i.name}`;if(i.message)o+=` - ${i.message}`;if(i.error)o+=`
2710
2708
  Error: ${i.error}`;n.push(o)}return n.join(`
2711
- `)}getStatusIcon(n){switch(n){case"pending":return"○";case"active":return"◐";case"completed":return"✓";case"failed":return"✗";case"skipped":return"⊘";default:return"○"}}isComplete(){return this.steps.every((n)=>n.status==="completed"||n.status==="skipped")}hasFailed(){return this.steps.some((n)=>n.status==="failed")}}class Uy{frames=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];currentFrame=0;message;interval=null;constructor(n="Loading..."){this.message=n}start(){if(this.interval)return;this.interval=setInterval(()=>{this.currentFrame=(this.currentFrame+1)%this.frames.length},80)}stop(){if(this.interval)clearInterval(this.interval),this.interval=null}setMessage(n){this.message=n}render(){return`${this.frames[this.currentFrame]} ${this.message}`}succeed(n){return this.stop(),`✓ ${n||this.message}`}fail(n){return this.stop(),`✗ ${n||this.message}`}warn(n){return this.stop(),`⚠ ${n||this.message}`}info(n){return this.stop(),`ℹ ${n||this.message}`}}class Qy{tasks=[];add(n){return this.tasks.push({title:n,status:"pending"}),this.tasks.length-1}start(n){if(n>=0&&n<this.tasks.length)this.tasks[n].status="running"}complete(n,i){if(n>=0&&n<this.tasks.length)this.tasks[n].status="completed",this.tasks[n].output=i}fail(n,i){if(n>=0&&n<this.tasks.length)this.tasks[n].status="failed",this.tasks[n].output=i}render(){let n=[];for(let i of this.tasks){let o=`${this.getStatusIcon(i.status)} ${i.title}`;if(i.output)o+=`
2709
+ `)}getStatusIcon(n){switch(n){case"pending":return"○";case"active":return"◐";case"completed":return"✓";case"failed":return"✗";case"skipped":return"⊘";default:return"○"}}isComplete(){return this.steps.every((n)=>n.status==="completed"||n.status==="skipped")}hasFailed(){return this.steps.some((n)=>n.status==="failed")}}class Yy{frames=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];currentFrame=0;message;interval=null;constructor(n="Loading..."){this.message=n}start(){if(this.interval)return;this.interval=setInterval(()=>{this.currentFrame=(this.currentFrame+1)%this.frames.length},80)}stop(){if(this.interval)clearInterval(this.interval),this.interval=null}setMessage(n){this.message=n}render(){return`${this.frames[this.currentFrame]} ${this.message}`}succeed(n){return this.stop(),`✓ ${n||this.message}`}fail(n){return this.stop(),`✗ ${n||this.message}`}warn(n){return this.stop(),`⚠ ${n||this.message}`}info(n){return this.stop(),`ℹ ${n||this.message}`}}class Zy{tasks=[];add(n){return this.tasks.push({title:n,status:"pending"}),this.tasks.length-1}start(n){if(n>=0&&n<this.tasks.length)this.tasks[n].status="running"}complete(n,i){if(n>=0&&n<this.tasks.length)this.tasks[n].status="completed",this.tasks[n].output=i}fail(n,i){if(n>=0&&n<this.tasks.length)this.tasks[n].status="failed",this.tasks[n].output=i}render(){let n=[];for(let i of this.tasks){let o=`${this.getStatusIcon(i.status)} ${i.title}`;if(i.output)o+=`
2712
2710
  ${i.output}`;n.push(o)}return n.join(`
2713
- `)}getStatusIcon(n){switch(n){case"pending":return"○";case"running":return"◐";case"completed":return"✓";case"failed":return"✗";default:return"○"}}}function wi(n,i){let s=[];for(let o=0;o<=i.length;o++)s[o]=[o];for(let o=0;o<=n.length;o++)s[0][o]=o;for(let o=1;o<=i.length;o++)for(let c=1;c<=n.length;c++)if(i.charAt(o-1)===n.charAt(c-1))s[o][c]=s[o-1][c-1];else s[o][c]=Math.min(s[o-1][c-1]+1,s[o][c-1]+1,s[o-1][c]+1);return s[i.length][n.length]}function Ii(n,i){let s=wi(n.toLowerCase(),i.toLowerCase()),o=Math.max(n.length,i.length);if(o===0)return 1;return 1-s/o}function jm(n,i,s=0.5){return i.map((c)=>({command:c,score:Ii(n,c)})).filter((c)=>c.score>=s).sort((c,u)=>u.score-c.score).map((c)=>c.command).slice(0,5)}function cC(n,i){if(i.length===0)return`Unknown command: '${n}'
2711
+ `)}getStatusIcon(n){switch(n){case"pending":return"○";case"running":return"◐";case"completed":return"✓";case"failed":return"✗";default:return"○"}}}function Ji(n,i){let s=[];for(let o=0;o<=i.length;o++)s[o]=[o];for(let o=0;o<=n.length;o++)s[0][o]=o;for(let o=1;o<=i.length;o++)for(let c=1;c<=n.length;c++)if(i.charAt(o-1)===n.charAt(c-1))s[o][c]=s[o-1][c-1];else s[o][c]=Math.min(s[o-1][c-1]+1,s[o][c-1]+1,s[o-1][c]+1);return s[i.length][n.length]}function Xi(n,i){let s=Ji(n.toLowerCase(),i.toLowerCase()),o=Math.max(n.length,i.length);if(o===0)return 1;return 1-s/o}function rf(n,i,s=0.5){return i.map((c)=>({command:c,score:Xi(n,c)})).filter((c)=>c.score>=s).sort((c,u)=>u.score-c.score).map((c)=>c.command).slice(0,5)}function bC(n,i){if(i.length===0)return`Unknown command: '${n}'
2714
2712
 
2715
2713
  Run 'ts-cloud --help' to see available commands.`;if(i.length===1)return`Unknown command: '${n}'
2716
2714
 
@@ -2718,17 +2716,17 @@ Did you mean: ${i[0]}?`;return`Unknown command: '${n}'
2718
2716
 
2719
2717
  Did you mean one of these?
2720
2718
  ${i.map((s)=>` • ${s}`).join(`
2721
- `)}`}function dC(n,i){return jm(n,i,0.7).length>0}function lC(n,i){let s=i.find((u)=>u.commands.some((d)=>d.name===n||d.aliases?.includes(n)));if(!s)return"No contextual help available.";let o=[];o.push(`${s.name}`),o.push("─".repeat(s.name.length)),o.push(s.description),o.push(""),o.push("Related commands:");for(let u of s.commands)if(o.push(` ${u.name.padEnd(20)} ${u.description}`),u.aliases&&u.aliases.length>0)o.push(` Aliases: ${u.aliases.join(", ")}`);let c=s.commands.find((u)=>u.name===n||u.aliases?.includes(n));if(c?.examples&&c.examples.length>0){o.push(""),o.push("Examples:");for(let u of c.examples)o.push(` ${u}`)}return o.join(`
2722
- `)}function uC(n,i){let s=[],o=n.toLowerCase();for(let c of i)for(let u of c.commands){let d=u.name.toLowerCase().includes(o),g=u.description.toLowerCase().includes(o),y=u.aliases?.some((h)=>h.toLowerCase().includes(o));if(d||g||y)s.push({command:u,category:c.name})}return s}function gC(n,i,s=10){let o=n.toLowerCase(),c=i.filter((d)=>d.toLowerCase().startsWith(o)),u=i.filter((d)=>d.toLowerCase().includes(o)&&!d.toLowerCase().startsWith(o));return[...c,...u].slice(0,s)}function pC(n,i){let s=n.toLowerCase();return i.filter((o)=>{let c=o.name.toLowerCase().includes(s),u=o.alias?.toLowerCase().includes(s);return c||u})}function mC(n){if(n.length===0)return"No matching flags found.";let i=[];for(let s of n){let o=` --${s.name}`;if(s.alias)o+=`, -${s.alias}`;if(o=o.padEnd(30),o+=s.description,s.required)o+=" (required)";i.push(o)}return i.join(`
2723
- `)}function fC(n){let i=[];if(i.push(`Usage: ts-cloud ${n.name}`),i.push(""),i.push(n.description),n.aliases&&n.aliases.length>0)i.push(""),i.push(`Aliases: ${n.aliases.join(", ")}`);if(n.examples&&n.examples.length>0){i.push(""),i.push("Examples:");for(let s of n.examples)i.push(` ${s}`)}return i.join(`
2724
- `)}function hC(n,i,s=[]){let o={valid:!0,errors:[],warnings:[],suggestions:[]},[c,...u]=n.split(" ");if(!i.includes(c)){o.valid=!1,o.errors.push(`Unknown command: ${c}`);let d=jm(c,i);if(d.length>0)o.suggestions.push(...d)}for(let d of s)if(!u.some((g)=>g===`--${d}`||g.startsWith(`--${d}=`)))o.valid=!1,o.errors.push(`Missing required flag: --${d}`);return o}class Hy{options;running=!1;history={commands:[],maxSize:1000};historyIndex=-1;constructor(n){this.options={prompt:n.prompt||"> ",welcome:n.welcome||'Welcome to ts-cloud interactive mode. Type "help" for available commands.',...n}}async start(){if(this.running=!0,this.options.welcome)console.log(this.options.welcome),console.log("");if(this.options.historyFile)await this.loadHistory();while(this.running)try{let n=await this.readInput();if(!n.trim())continue;this.addToHistory(n),await this.executeCommand(n)}catch(n){if(n instanceof Error)console.error(`Error: ${n.message}`)}if(this.options.historyFile)await this.saveHistory()}stop(){this.running=!1}async readInput(){return new Promise((n)=>{process.stdout.write(this.options.prompt||"> "),n("")})}async executeCommand(n){let[i,...s]=this.parseCommand(n);if(i==="exit"||i==="quit"){this.stop();return}if(i==="help"){this.showHelp();return}if(i==="history"){this.showHistory();return}if(i==="clear"){console.clear();return}let o=this.findCommand(i);if(!o){console.error(`Unknown command: ${i}`),console.log('Type "help" to see available commands.');return}try{await o.handler(s)}catch(c){if(c instanceof Error)console.error(`Command failed: ${c.message}`)}}parseCommand(n){return n.trim().split(/\s+/)}findCommand(n){for(let[i,s]of this.options.commands)if(s.name===n||s.aliases?.includes(n))return s;return}showHelp(){console.log("Available commands:"),console.log("");let n=Array.from(this.options.commands.values());console.log(" help Show this help message"),console.log(" history Show command history"),console.log(" clear Clear screen"),console.log(" exit, quit Exit interactive mode"),console.log("");for(let i of n){let s=` ${i.name.padEnd(20)} ${i.description}`;if(i.aliases&&i.aliases.length>0)s+=` (aliases: ${i.aliases.join(", ")})`;console.log(s)}}showHistory(){if(this.history.commands.length===0){console.log("No command history");return}console.log("Command history:"),this.history.commands.forEach((n,i)=>{console.log(` ${(i+1).toString().padStart(4)} ${n}`)})}addToHistory(n){if(this.history.commands[this.history.commands.length-1]===n)return;if(this.history.commands.push(n),this.history.commands.length>this.history.maxSize)this.history.commands=this.history.commands.slice(-this.history.maxSize);this.historyIndex=this.history.commands.length}historyBack(){if(this.historyIndex>0)return this.historyIndex--,this.history.commands[this.historyIndex];return}historyForward(){if(this.historyIndex<this.history.commands.length-1)return this.historyIndex++,this.history.commands[this.historyIndex];return this.historyIndex=this.history.commands.length,""}autocomplete(n){let i=[],s=["help","history","clear","exit","quit"];for(let o of s)if(o.startsWith(n))i.push(o);for(let[o,c]of this.options.commands){if(c.name.startsWith(n))i.push(c.name);if(c.aliases){for(let u of c.aliases)if(u.startsWith(n))i.push(u)}}return i}async loadHistory(){if(!this.options.historyFile)return;try{let n=await import("node:fs/promises"),i=await n.readFile(this.options.historyFile,"utf-8");this.history.commands=i.split(`
2719
+ `)}`}function CC(n,i){return rf(n,i,0.7).length>0}function EC(n,i){let s=i.find((u)=>u.commands.some((d)=>d.name===n||d.aliases?.includes(n)));if(!s)return"No contextual help available.";let o=[];o.push(`${s.name}`),o.push("─".repeat(s.name.length)),o.push(s.description),o.push(""),o.push("Related commands:");for(let u of s.commands)if(o.push(` ${u.name.padEnd(20)} ${u.description}`),u.aliases&&u.aliases.length>0)o.push(` Aliases: ${u.aliases.join(", ")}`);let c=s.commands.find((u)=>u.name===n||u.aliases?.includes(n));if(c?.examples&&c.examples.length>0){o.push(""),o.push("Examples:");for(let u of c.examples)o.push(` ${u}`)}return o.join(`
2720
+ `)}function vC(n,i){let s=[],o=n.toLowerCase();for(let c of i)for(let u of c.commands){let d=u.name.toLowerCase().includes(o),g=u.description.toLowerCase().includes(o),y=u.aliases?.some((h)=>h.toLowerCase().includes(o));if(d||g||y)s.push({command:u,category:c.name})}return s}function TC(n,i,s=10){let o=n.toLowerCase(),c=i.filter((d)=>d.toLowerCase().startsWith(o)),u=i.filter((d)=>d.toLowerCase().includes(o)&&!d.toLowerCase().startsWith(o));return[...c,...u].slice(0,s)}function wC(n,i){let s=n.toLowerCase();return i.filter((o)=>{let c=o.name.toLowerCase().includes(s),u=o.alias?.toLowerCase().includes(s);return c||u})}function RC(n){if(n.length===0)return"No matching flags found.";let i=[];for(let s of n){let o=` --${s.name}`;if(s.alias)o+=`, -${s.alias}`;if(o=o.padEnd(30),o+=s.description,s.required)o+=" (required)";i.push(o)}return i.join(`
2721
+ `)}function DC(n){let i=[];if(i.push(`Usage: ts-cloud ${n.name}`),i.push(""),i.push(n.description),n.aliases&&n.aliases.length>0)i.push(""),i.push(`Aliases: ${n.aliases.join(", ")}`);if(n.examples&&n.examples.length>0){i.push(""),i.push("Examples:");for(let s of n.examples)i.push(` ${s}`)}return i.join(`
2722
+ `)}function PC(n,i,s=[]){let o={valid:!0,errors:[],warnings:[],suggestions:[]},[c,...u]=n.split(" ");if(!i.includes(c)){o.valid=!1,o.errors.push(`Unknown command: ${c}`);let d=rf(c,i);if(d.length>0)o.suggestions.push(...d)}for(let d of s)if(!u.some((g)=>g===`--${d}`||g.startsWith(`--${d}=`)))o.valid=!1,o.errors.push(`Missing required flag: --${d}`);return o}class eS{options;running=!1;history={commands:[],maxSize:1000};historyIndex=-1;constructor(n){this.options={prompt:n.prompt||"> ",welcome:n.welcome||'Welcome to ts-cloud interactive mode. Type "help" for available commands.',...n}}async start(){if(this.running=!0,this.options.welcome)console.log(this.options.welcome),console.log("");if(this.options.historyFile)await this.loadHistory();while(this.running)try{let n=await this.readInput();if(!n.trim())continue;this.addToHistory(n),await this.executeCommand(n)}catch(n){if(n instanceof Error)console.error(`Error: ${n.message}`)}if(this.options.historyFile)await this.saveHistory()}stop(){this.running=!1}async readInput(){return new Promise((n)=>{process.stdout.write(this.options.prompt||"> "),n("")})}async executeCommand(n){let[i,...s]=this.parseCommand(n);if(i==="exit"||i==="quit"){this.stop();return}if(i==="help"){this.showHelp();return}if(i==="history"){this.showHistory();return}if(i==="clear"){console.clear();return}let o=this.findCommand(i);if(!o){console.error(`Unknown command: ${i}`),console.log('Type "help" to see available commands.');return}try{await o.handler(s)}catch(c){if(c instanceof Error)console.error(`Command failed: ${c.message}`)}}parseCommand(n){return n.trim().split(/\s+/)}findCommand(n){for(let[i,s]of this.options.commands)if(s.name===n||s.aliases?.includes(n))return s;return}showHelp(){console.log("Available commands:"),console.log("");let n=Array.from(this.options.commands.values());console.log(" help Show this help message"),console.log(" history Show command history"),console.log(" clear Clear screen"),console.log(" exit, quit Exit interactive mode"),console.log("");for(let i of n){let s=` ${i.name.padEnd(20)} ${i.description}`;if(i.aliases&&i.aliases.length>0)s+=` (aliases: ${i.aliases.join(", ")})`;console.log(s)}}showHistory(){if(this.history.commands.length===0){console.log("No command history");return}console.log("Command history:"),this.history.commands.forEach((n,i)=>{console.log(` ${(i+1).toString().padStart(4)} ${n}`)})}addToHistory(n){if(this.history.commands[this.history.commands.length-1]===n)return;if(this.history.commands.push(n),this.history.commands.length>this.history.maxSize)this.history.commands=this.history.commands.slice(-this.history.maxSize);this.historyIndex=this.history.commands.length}historyBack(){if(this.historyIndex>0)return this.historyIndex--,this.history.commands[this.historyIndex];return}historyForward(){if(this.historyIndex<this.history.commands.length-1)return this.historyIndex++,this.history.commands[this.historyIndex];return this.historyIndex=this.history.commands.length,""}autocomplete(n){let i=[],s=["help","history","clear","exit","quit"];for(let o of s)if(o.startsWith(n))i.push(o);for(let[o,c]of this.options.commands){if(c.name.startsWith(n))i.push(c.name);if(c.aliases){for(let u of c.aliases)if(u.startsWith(n))i.push(u)}}return i}async loadHistory(){if(!this.options.historyFile)return;try{let n=await import("node:fs/promises"),i=await n.readFile(this.options.historyFile,"utf-8");this.history.commands=i.split(`
2725
2723
  `).filter((s)=>s.trim()),this.historyIndex=this.history.commands.length}catch{}}async saveHistory(){if(!this.options.historyFile)return;try{let n=await import("node:fs/promises");await n.writeFile(this.options.historyFile,this.history.commands.join(`
2726
- `))}catch(n){console.error(`Failed to save history: ${n}`)}}searchHistory(n){return this.history.commands.filter((i)=>i.includes(n))}clearHistory(){this.history.commands=[],this.historyIndex=0}}class Gy{variables=new Map;workingDirectory=process.cwd();set(n,i){this.variables.set(n,i)}get(n){return this.variables.get(n)}has(n){return this.variables.has(n)}delete(n){this.variables.delete(n)}getAll(){return Object.fromEntries(this.variables)}clear(){this.variables.clear()}setWorkingDirectory(n){this.workingDirectory=n}getWorkingDirectory(){return this.workingDirectory}}class Vy{command={};name(n){return this.command.name=n,this}description(n){return this.command.description=n,this}aliases(...n){return this.command.aliases=n,this}handler(n){return this.command.handler=n,this}autocomplete(n){return this.command.autocomplete=n,this}build(){if(!this.command.name||!this.command.description||!this.command.handler)throw Error("Command must have name, description, and handler");return this.command}}class qy{entries=[];maxSize;persistFile;trackOutput;constructor(n={}){this.maxSize=n.maxSize||1000,this.persistFile=n.persistFile,this.trackOutput=n.trackOutput||!1}add(n){if(this.entries.push({...n,timestamp:new Date}),this.entries.length>this.maxSize)this.entries=this.entries.slice(-this.maxSize)}getAll(){return[...this.entries]}getRecent(n=10){return this.entries.slice(-n)}search(n){let i=n.toLowerCase();return this.entries.filter((s)=>s.command.toLowerCase().includes(i))}searchByDate(n,i){return this.entries.filter((s)=>s.timestamp>=n&&s.timestamp<=i)}getSuccessful(){return this.entries.filter((n)=>n.success)}getFailed(){return this.entries.filter((n)=>!n.success)}getMostUsed(n=10){let i=new Map;for(let s of this.entries){let o=s.command.split(" ")[0];i.set(o,(i.get(o)||0)+1)}return Array.from(i.entries()).map(([s,o])=>({command:s,count:o})).sort((s,o)=>o.count-s.count).slice(0,n)}getStats(){let n=this.entries.length,i=this.entries.filter((g)=>g.success).length,s=this.entries.filter((g)=>!g.success).length,o=this.entries.filter((g)=>g.duration!==void 0),c=o.length>0?o.reduce((g,y)=>g+(y.duration||0),0)/o.length:0,u=this.getMostUsed(1),d=u.length>0?u[0].command:"N/A";return{total:n,successful:i,failed:s,averageDuration:c,mostUsed:d}}clear(){this.entries=[]}getByIndex(n){if(n<0||n>=this.entries.length)return;return this.entries[n]}removeByIndex(n){if(n>=0&&n<this.entries.length)this.entries.splice(n,1)}async save(){if(!this.persistFile)return;try{let n=await import("node:fs/promises"),i=JSON.stringify(this.entries,null,2);await n.writeFile(this.persistFile,i,"utf-8")}catch(n){throw Error(`Failed to save history: ${n}`)}}async load(){if(!this.persistFile)return;try{let n=await import("node:fs/promises"),i=await n.readFile(this.persistFile,"utf-8"),s=JSON.parse(i);this.entries=s.map((o)=>({...o,timestamp:new Date(o.timestamp)}))}catch{this.entries=[]}}exportJSON(){return JSON.stringify(this.entries,null,2)}exportCSV(){return["Timestamp,Command,Success,Duration",...this.entries.map((s)=>[s.timestamp.toISOString(),`"${s.command.replace(/"/g,'""')}"`,s.success,s.duration||""].join(","))].join(`
2727
- `)}importJSON(n){let s=JSON.parse(n).map((o)=>({...o,timestamp:new Date(o.timestamp)}));if(this.entries.push(...s),this.entries.length>this.maxSize)this.entries=this.entries.slice(-this.maxSize)}groupByDate(){let n=new Map;for(let i of this.entries){let s=i.timestamp.toISOString().split("T")[0];if(!n.has(s))n.set(s,[]);n.get(s).push(i)}return n}groupByCommand(){let n=new Map;for(let i of this.entries){let s=i.command.split(" ")[0];if(!n.has(s))n.set(s,[]);n.get(s).push(i)}return n}replay(n){return this.getByIndex(n)?.command}getSuggestions(n,i=5){let s=n.toLowerCase(),o=this.entries.filter((c)=>c.command.toLowerCase().startsWith(s)).map((c)=>c.command);return[...new Set(o)].slice(0,i)}analyzePatterns(){let n=new Map,i=new Map;for(let o of this.entries){let c=o.timestamp.getHours(),u=o.timestamp.getDay();n.set(c,(n.get(c)||0)+1),i.set(u,(i.get(u)||0)+1)}let s=this.entries.length>0?this.getSuccessful().length/this.entries.length:0;return{timeOfDay:n,dayOfWeek:i,successRate:s}}}function AC(n,i={}){let{maxWidth:s=100}=i;if(n.length===0)return"No command history";let o=[];for(let c=0;c<n.length;c++){let u=n[c],d=(c+1).toString().padStart(4),g=u.timestamp.toLocaleString(),y=u.success?"✓":"✗",h=u.command;if(h.length>s-30)h=h.substring(0,s-33)+"...";let A=`${d} ${g} ${y} ${h}`;if(u.duration)A+=` (${u.duration}ms)`;o.push(A)}return o.join(`
2728
- `)}function yC(n){let i=[];return i.push("Command History Statistics"),i.push("─".repeat(30)),i.push(`Total commands: ${n.total}`),i.push(`Successful: ${n.successful}`),i.push(`Failed: ${n.failed}`),i.push(`Success rate: ${(n.successful/n.total*100).toFixed(1)}%`),i.push(`Average duration: ${n.averageDuration.toFixed(0)}ms`),i.push(`Most used: ${n.mostUsed}`),i.join(`
2729
- `)}class zm{deployments=new Map;async deploy(n,i){let s=this.generateDeploymentId(),o={id:s,regions:i.regions.map((c)=>({region:c.code,stackName:this.getStackName(n,c.code),status:"pending"})),status:"deploying",startTime:new Date};this.deployments.set(s,o);try{let c=i.regions.find((d)=>d.isPrimary)||i.regions[0];await this.deployToRegion(n,c,o);let u=i.regions.filter((d)=>d.code!==c.code);if(await Promise.all(u.map((d)=>this.deployToRegion(n,d,o))),i.globalResources)await this.deployGlobalResources(o,i);if(i.replication)await this.setupReplication(o,i);if(i.failover?.enabled)await this.setupFailover(o,i);return o.status="deployed",o.endTime=new Date,o}catch(c){throw o.status="failed",o.endTime=new Date,c}}async deployToRegion(n,i,s){let o=s.regions.find((c)=>c.region===i.code);if(!o)throw Error(`Region deployment not found: ${i.code}`);o.status="deploying",o.startTime=new Date;try{let c=this.createRegionConfig(n,i);await this.deployStack(o.stackName,c,i.code),o.status="deployed",o.endTime=new Date,o.outputs={stackId:`arn:aws:cloudformation:${i.code}:123456789012:stack/${o.stackName}/guid`,endpoint:`https://${o.stackName}.${i.code}.example.com`}}catch(c){throw o.status="failed",o.endTime=new Date,o.error=c instanceof Error?c.message:String(c),c}}async deployGlobalResources(n,i){let s={};if(i.globalResources?.route53)s.route53=await this.deployRoute53(n,i);if(i.globalResources?.cloudfront)s.cloudfront=await this.deployCloudFront(n,i);if(i.globalResources?.waf)s.waf=await this.deployWAF(n);n.globalResources=s}async deployRoute53(n,i){let s=[],o=[];for(let c of n.regions){if(c.status!=="deployed")continue;let u={id:`health-${c.region}`,endpoint:c.outputs?.endpoint,path:i.failover?.healthCheckPath||"/health",region:c.region};s.push(u);let d={name:"example.com",type:"A",region:c.region,setIdentifier:c.region,healthCheckId:u.id,resourceRecords:[c.outputs?.endpoint]};o.push(d)}return{healthChecks:s,recordSets:o,hostedZoneId:"Z1234567890ABC"}}async deployCloudFront(n,i){return{distributionId:"E1234567890ABC",domainName:"d1234567890abc.cloudfront.net",origins:n.regions.filter((o)=>o.status==="deployed").map((o,c)=>{let u=i.regions[c];return{id:`origin-${o.region}`,domainName:o.outputs?.endpoint,weight:u?.weight||100}}),status:"Deployed"}}async deployWAF(n){return{webAclId:"arn:aws:wafv2:us-east-1:123456789012:global/webacl/test/a1234567-b890-c123-d456-e789012345f6",webAclArn:"arn:aws:wafv2:us-east-1:123456789012:global/webacl/test/a1234567-b890-c123-d456-e789012345f6"}}async setupReplication(n,i){if(i.replication?.s3)await this.setupS3Replication(n);if(i.replication?.dynamodb)await this.setupDynamoDBReplication(n);if(i.replication?.secrets)await this.setupSecretsReplication(n)}async setupS3Replication(n){let i=n.regions.filter((s)=>s.status==="deployed");for(let s=0;s<i.length-1;s++){let o=i[s],c=i[s+1];console.log(`Setting up S3 replication: ${o.region} -> ${c.region}`)}}async setupDynamoDBReplication(n){let i=n.regions.filter((s)=>s.status==="deployed").map((s)=>s.region);console.log(`Setting up DynamoDB global table in regions: ${i.join(", ")}`)}async setupSecretsReplication(n){let i=n.regions.filter((s)=>s.status==="deployed").map((s)=>s.region);console.log(`Setting up Secrets Manager replication in regions: ${i.join(", ")}`)}async setupFailover(n,i){let s=n.regions.find((c,u)=>i.regions[u]?.isPrimary)||n.regions[0],o=n.regions.filter((c)=>c.region!==s.region);console.log(`Setting up failover: primary=${s.region}, secondary=${o.map((c)=>c.region).join(", ")}`)}async destroy(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);i.status="rolling-back";try{if(i.globalResources)await this.destroyGlobalResources(i.globalResources);await Promise.all(i.regions.map((s)=>this.destroyRegionStack(s))),this.deployments.delete(n)}catch(s){throw i.status="failed",s}}async destroyGlobalResources(n){if(n.waf)console.log("Destroying WAF resources");if(n.cloudfront)console.log("Destroying CloudFront distribution");if(n.route53)console.log("Destroying Route53 resources")}async destroyRegionStack(n){if(n.status!=="deployed")return;n.status="rolling-back";try{console.log(`Destroying stack ${n.stackName} in ${n.region}`),n.status="pending"}catch(i){throw n.status="failed",n.error=i instanceof Error?i.message:String(i),i}}getDeployment(n){return this.deployments.get(n)}listDeployments(){return Array.from(this.deployments.values())}getStackName(n,i){return`${n.project.slug}-${i}`}createRegionConfig(n,i){return{...n,infrastructure:{...n.infrastructure}}}async deployStack(n,i,s){console.log(`Deploying stack ${n} to ${s}`)}generateDeploymentId(){return`deploy-${Date.now()}-${Math.random().toString(36).substring(7)}`}}var SC=new zm;class Km{references=[];exports=new Map;addExport(n){let i=`${n.region}:${n.exportName}`;if(!this.exports.has(n.region))this.exports.set(n.region,[]);this.exports.get(n.region).push(n)}getExport(n,i){let s=this.exports.get(n);if(!s)return;return s.find((c)=>c.exportName===i)?.value}createReference(n,i,s,o){let c=`/cross-region/${n}/${s}/${o}`;return this.references.push({sourceRegion:n,targetRegion:i,resourceType:s,resourceId:o,value:c}),c}async resolveReference(n,i){let s=this.references.find((o)=>o.targetRegion===n&&o.value===i);if(!s)throw Error(`Reference not found: ${i}`);return`arn:aws:resource:${s.sourceRegion}:123456789012:${s.resourceType}/${s.resourceId}`}getReferencesForRegion(n){return this.references.filter((i)=>i.sourceRegion===n||i.targetRegion===n)}clear(){this.references=[],this.exports.clear()}}class Wm{resources=new Map;register(n){this.resources.set(n.id,n)}get(n){return this.resources.get(n)}getByType(n){return Array.from(this.resources.values()).filter((i)=>i.type===n)}getCloudFrontDistributions(){return this.getByType("cloudfront")}getRoute53HostedZones(){return this.getByType("route53")}getWAFWebACLs(){return this.getByType("waf")}remove(n){this.resources.delete(n)}clear(){this.resources.clear()}}class Jm{pairs=[];addPair(n){this.pairs.push(n)}getPairedRegion(n){let i=this.pairs.find((s)=>s.primary===n||s.secondary===n);if(!i)return;return i.primary===n?i.secondary:i.primary}getAllPairs(){return[...this.pairs]}getReplicatedPairs(){return this.pairs.filter((n)=>n.replicationConfig)}getFailoverPairs(){return this.pairs.filter((n)=>n.failoverConfig?.automatic)}arePaired(n,i){return this.pairs.some((s)=>s.primary===n&&s.secondary===i||s.primary===i&&s.secondary===n)}clear(){this.pairs=[]}}class Xm{dependencies=[];addDependency(n){this.dependencies.push(n)}getDependencies(n,i){return this.dependencies.filter((s)=>s.dependentStack===n&&s.dependentRegion===i)}getDependents(n,i){return this.dependencies.filter((s)=>s.dependsOnStack===n&&s.dependsOnRegion===i)}hasDependencies(n,i){return this.getDependencies(n,i).length>0}getDeploymentOrder(n){let i=new Set,s=[],o=(c)=>{let u=`${c.name}:${c.region}`;if(i.has(u))return;i.add(u);let d=this.getDependencies(c.name,c.region);for(let g of d)o({name:g.dependsOnStack,region:g.dependsOnRegion});s.push(c)};for(let c of n)o(c);return s}detectCircularDependencies(){let n=new Set,i=new Set,s=(o,c)=>{let u=`${o}:${c}`;if(i.has(u))return!0;if(n.has(u))return!1;n.add(u),i.add(u);let d=this.getDependencies(o,c);for(let g of d)if(s(g.dependsOnStack,g.dependsOnRegion))return!0;return i.delete(u),!1};for(let o of this.dependencies)if(s(o.dependentStack,o.dependentRegion))return!0;return!1}clear(){this.dependencies=[]}}var IC=new Km,bC=new Wm,CC=new Jm,EC=new Xm;var _e=[{code:"us-east-1",name:"US East (N. Virginia)",location:"Virginia, USA",launchYear:2006,availabilityZones:6,localZones:16,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"standard",multiplier:1},compliance:["PCI-DSS","HIPAA","SOC","ISO","FedRAMP"]},{code:"us-east-2",name:"US East (Ohio)",location:"Ohio, USA",launchYear:2016,availabilityZones:3,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"standard",multiplier:1},compliance:["PCI-DSS","HIPAA","SOC","ISO"]},{code:"us-west-1",name:"US West (N. California)",location:"California, USA",launchYear:2009,availabilityZones:3,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"premium",multiplier:1.1},compliance:["PCI-DSS","HIPAA","SOC","ISO"]},{code:"us-west-2",name:"US West (Oregon)",location:"Oregon, USA",launchYear:2011,availabilityZones:4,localZones:2,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"standard",multiplier:1},compliance:["PCI-DSS","HIPAA","SOC","ISO"]},{code:"eu-west-1",name:"Europe (Ireland)",location:"Dublin, Ireland",launchYear:2007,availabilityZones:3,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"standard",multiplier:1.05},compliance:["PCI-DSS","GDPR","SOC","ISO"]},{code:"eu-central-1",name:"Europe (Frankfurt)",location:"Frankfurt, Germany",launchYear:2014,availabilityZones:3,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"premium",multiplier:1.1},compliance:["PCI-DSS","GDPR","SOC","ISO"]},{code:"ap-southeast-1",name:"Asia Pacific (Singapore)",location:"Singapore",launchYear:2010,availabilityZones:3,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"premium",multiplier:1.12},compliance:["PCI-DSS","SOC","ISO","MTCS"]},{code:"ap-northeast-1",name:"Asia Pacific (Tokyo)",location:"Tokyo, Japan",launchYear:2011,availabilityZones:4,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"premium",multiplier:1.15},compliance:["PCI-DSS","SOC","ISO"]}];function ts(n){return _e.find((i)=>i.code===n)}function vC(){return _e}function TC(n){let i=n.toLowerCase();return _e.filter((s)=>s.location.toLowerCase().includes(i))}function wC(n){return _e.filter((i)=>i.compliance.includes(n))}function RC(n){return _e.filter((i)=>i.pricing.tier===n)}function DC(n){return _e.some((i)=>i.code===n)}function PC(n){if(n.continent==="North America")return ts("us-east-1");if(n.continent==="Europe")return ts("eu-west-1");if(n.continent==="Asia")return ts("ap-southeast-1");return ts("us-east-1")}function kC(n){let i=[..._e];if(n.compliance)i=i.filter((s)=>n.compliance.every((o)=>s.compliance.includes(o)));if(n.requiredServices)i=i.filter((s)=>n.requiredServices.every((o)=>s.services[o]));if(n.pricingSensitive)i.sort((s,o)=>s.pricing.multiplier-o.pricing.multiplier);return i.slice(0,5)}function NC(n){let i=ts(n);if(!i)throw Error(`Invalid region: ${n}`);let s=[];for(let o of _e){if(o.code===n)continue;let c=Di(i,o),u=Ni(i,o);s.push({primary:i,secondary:o,distance:c,sameContinent:u})}return s.sort((o,c)=>{if(o.sameContinent!==c.sameContinent)return o.sameContinent?1:-1;return o.distance-c.distance}),s.slice(0,3)}function Di(n,i){let s={"North America":0,"South America":1,Europe:2,Asia:3,Africa:4,Oceania:5},o=Je(n.location),c=Je(i.location);return Math.abs((s[o]||0)-(s[c]||0))}function Ni(n,i){return Je(n.location)===Je(i.location)}function Je(n){if(n.includes("USA")||n.includes("Canada"))return"North America";if(n.includes("Europe")||n.includes("Ireland")||n.includes("Germany"))return"Europe";if(n.includes("Asia")||n.includes("Singapore")||n.includes("Japan"))return"Asia";if(n.includes("Brazil"))return"South America";if(n.includes("Australia"))return"Oceania";return"Unknown"}function jy(n){return`${n.name} (${n.code})`}function BC(n){return n.map((i)=>jy(i)).join(`
2730
- `)}function xC(){let n={total:_e.length,byContinent:{},byPricingTier:{}};for(let i of _e){let s=Je(i.location);n.byContinent[s]=(n.byContinent[s]||0)+1,n.byPricingTier[i.pricing.tier]=(n.byPricingTier[i.pricing.tier]||0)+1}return n}class Ym{accounts=new Map;crossAccountRoles=[];accountMappings=[];registerAccount(n){this.accounts.set(n.id,n)}getAccount(n){return this.accounts.get(n)}getAccountByAlias(n){return Array.from(this.accounts.values()).find((i)=>i.alias===n)}listAccounts(){return Array.from(this.accounts.values())}getAccountsByRole(n){return Array.from(this.accounts.values()).filter((i)=>i.role===n)}createCrossAccountRole(n,i,s,o,c){let u={roleArn:`arn:aws:iam::${i}:role/${s}`,roleName:s,sourceAccountId:n,targetAccountId:i,permissions:o,externalId:c?.externalId,sessionDuration:c?.sessionDuration||3600};return this.crossAccountRoles.push(u),u}getAssumeRolePolicyDocument(n,i){let s={Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${n}:root`},Action:"sts:AssumeRole"}]};if(i)s.Statement[0].Condition={StringEquals:{"sts:ExternalId":i}};return s}generateCrossAccountPolicy(n){return{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:n,Resource:"*"}]}}mapEnvironmentToAccount(n,i,s){this.accountMappings.push({environment:n,accountId:i,region:s})}getAccountForEnvironment(n){return this.accountMappings.find((i)=>i.environment===n)}async assumeRole(n,i,s){return console.log(`Assuming role: ${n} with session: ${i}`),{accessKeyId:"AKIAIOSFODNN7EXAMPLE",secretAccessKey:"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",sessionToken:"token",expiration:new Date(Date.now()+3600000)}}async getCredentialsForAccount(n){let i=this.accounts.get(n);if(!i)throw Error(`Account not found: ${n}`);if(i.assumeRoleArn){let s=await this.assumeRole(i.assumeRoleArn,`ts-cloud-${Date.now()}`);return{accessKeyId:s.accessKeyId,secretAccessKey:s.secretAccessKey,sessionToken:s.sessionToken}}throw Error("No credentials available for account")}listCrossAccountRoles(){return[...this.crossAccountRoles]}getCrossAccountRolesForAccount(n){return this.crossAccountRoles.filter((i)=>i.sourceAccountId===n||i.targetAccountId===n)}async validateAccountAccess(n){try{let i=await this.getCredentialsForAccount(n);return console.log(`Validating access to account: ${n}`),!0}catch{return!1}}async getConsolidatedBilling(){let n={};for(let s of this.accounts.values())n[s.id]=Math.random()*1000;return{totalCost:Object.values(n).reduce((s,o)=>s+o,0),byAccount:n}}clear(){this.accounts.clear(),this.crossAccountRoles=[],this.accountMappings=[]}}class Zm{organizationId;organizationalUnits=new Map;getOrganizationId(){return this.organizationId}setOrganizationId(n){this.organizationId=n}createOrganizationalUnit(n,i){let s={id:`ou-${Date.now()}`,name:n,parentId:i,accounts:[]};return this.organizationalUnits.set(s.id,s),s}getOrganizationalUnit(n){return this.organizationalUnits.get(n)}listOrganizationalUnits(){return Array.from(this.organizationalUnits.values())}addAccountToOU(n,i){let s=this.organizationalUnits.get(n);if(!s)throw Error(`Organizational unit not found: ${n}`);if(!s.accounts.includes(i))s.accounts.push(i)}removeAccountFromOU(n,i){let s=this.organizationalUnits.get(n);if(!s)throw Error(`Organizational unit not found: ${n}`);s.accounts=s.accounts.filter((o)=>o!==i)}getAccountsInOU(n){let i=this.organizationalUnits.get(n);if(!i)return[];return[...i.accounts]}applyServiceControlPolicy(n,i){return{id:`scp-${Date.now()}`,name:"Custom SCP",targetId:n,policyDocument:i}}clear(){this.organizationId=void 0,this.organizationalUnits.clear()}}var OC=new Ym,_C=new Zm;var zy={basic:{name:"Basic (3 Accounts)",description:"Simple structure for small teams",accounts:[{alias:"management",email:"aws+management@example.com",role:"management",ou:"root",description:"Management account for AWS Organizations"},{alias:"production",email:"aws+production@example.com",role:"production",ou:"workloads",description:"Production workloads"},{alias:"development",email:"aws+development@example.com",role:"development",ou:"workloads",description:"Development and testing"}],organizationalUnits:[{name:"root"},{name:"workloads",parent:"root"}]},standard:{name:"Standard (5 Accounts)",description:"Recommended for most organizations",accounts:[{alias:"management",email:"aws+management@example.com",role:"management",ou:"root",description:"Management account"},{alias:"security",email:"aws+security@example.com",role:"security",ou:"security",description:"Security tooling and audit logs"},{alias:"shared-services",email:"aws+shared@example.com",role:"shared-services",ou:"infrastructure",description:"Shared services (CI/CD, monitoring)"},{alias:"production",email:"aws+production@example.com",role:"production",ou:"workloads",description:"Production environment"},{alias:"staging",email:"aws+staging@example.com",role:"staging",ou:"workloads",description:"Staging environment"},{alias:"development",email:"aws+development@example.com",role:"development",ou:"workloads",description:"Development environment"}],organizationalUnits:[{name:"root"},{name:"security",parent:"root"},{name:"infrastructure",parent:"root"},{name:"workloads",parent:"root"}]},enterprise:{name:"Enterprise (7+ Accounts)",description:"For large organizations with strict compliance requirements",accounts:[{alias:"management",email:"aws+management@example.com",role:"management",ou:"root",description:"Management account"},{alias:"audit",email:"aws+audit@example.com",role:"security",ou:"security",description:"Audit and compliance"},{alias:"log-archive",email:"aws+logs@example.com",role:"security",ou:"security",description:"Centralized log storage"},{alias:"shared-services",email:"aws+shared@example.com",role:"shared-services",ou:"infrastructure",description:"Shared infrastructure"},{alias:"network",email:"aws+network@example.com",role:"shared-services",ou:"infrastructure",description:"Network infrastructure (Transit Gateway)"},{alias:"production",email:"aws+production@example.com",role:"production",ou:"production-ou",description:"Production workloads"},{alias:"staging",email:"aws+staging@example.com",role:"staging",ou:"non-production-ou",description:"Staging environment"},{alias:"development",email:"aws+development@example.com",role:"development",ou:"non-production-ou",description:"Development environment"}],organizationalUnits:[{name:"root"},{name:"security",parent:"root",policies:["deny-root-access"]},{name:"infrastructure",parent:"root"},{name:"production-ou",parent:"root",policies:["require-mfa"]},{name:"non-production-ou",parent:"root"}]}},LC={denyRootAccess:{name:"Deny Root User Access",description:"Prevent root user from performing any actions",policyDocument:{Version:"2012-10-17",Statement:[{Sid:"DenyRootUser",Effect:"Deny",Action:"*",Resource:"*",Condition:{StringLike:{"aws:PrincipalArn":"arn:aws:iam::*:root"}}}]}},requireMFA:{name:"Require MFA for All Actions",description:"Require MFA for console and API access",policyDocument:{Version:"2012-10-17",Statement:[{Sid:"RequireMFA",Effect:"Deny",Action:"*",Resource:"*",Condition:{BoolIfExists:{"aws:MultiFactorAuthPresent":"false"}}}]}},denyRegions:{name:"Deny Access to Non-Approved Regions",description:"Restrict operations to specific regions",policyDocument:{Version:"2012-10-17",Statement:[{Sid:"DenyNonApprovedRegions",Effect:"Deny",NotAction:["iam:*","organizations:*","route53:*","cloudfront:*","support:*","s3:*"],Resource:"*",Condition:{StringNotEquals:{"aws:RequestedRegion":["us-east-1","us-west-2"]}}}]}},preventLeaving:{name:"Prevent Leaving Organization",description:"Prevent accounts from leaving the organization",policyDocument:{Version:"2012-10-17",Statement:[{Sid:"PreventLeaving",Effect:"Deny",Action:"organizations:LeaveOrganization",Resource:"*"}]}},denyS3Unencrypted:{name:"Deny Unencrypted S3 Uploads",description:"Require encryption for all S3 uploads",policyDocument:{Version:"2012-10-17",Statement:[{Sid:"DenyUnencryptedS3Uploads",Effect:"Deny",Action:"s3:PutObject",Resource:"*",Condition:{StringNotEquals:{"s3:x-amz-server-side-encryption":["AES256","aws:kms"]}}}]}}},$C={deploymentRole:{name:"CrossAccountDeploymentRole",description:"Role for deploying infrastructure from CI/CD",permissions:["cloudformation:*","s3:*","ec2:*","ecs:*","lambda:*","iam:GetRole","iam:PassRole","logs:*","events:*"]},readOnlyRole:{name:"CrossAccountReadOnlyRole",description:"Read-only access for monitoring and auditing",permissions:["cloudformation:Describe*","cloudformation:List*","ec2:Describe*","ecs:Describe*","lambda:Get*","lambda:List*","s3:Get*","s3:List*","logs:Get*","logs:Describe*"]},securityAuditRole:{name:"CrossAccountSecurityAuditRole",description:"Security audit and compliance checks",permissions:["iam:Get*","iam:List*","iam:Generate*","access-analyzer:*","guardduty:Get*","guardduty:List*","securityhub:Get*","securityhub:List*","config:Describe*","config:Get*","config:List*"]},breakGlassRole:{name:"CrossAccountBreakGlassRole",description:"Emergency access role (use with caution)",permissions:["*"]}};function MC(n){return zy[n]}function FC(n,i){return{Type:"AWS::IAM::Role",Properties:{RoleName:n.roleName,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${n.sourceAccountId}:root`},Action:"sts:AssumeRole",...n.externalId&&{Condition:{StringEquals:{"sts:ExternalId":n.externalId}}}}]},Policies:[{PolicyName:`${n.roleName}Policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:n.permissions,Resource:"*"}]}}],...i&&{ManagedPolicyArns:i},MaxSessionDuration:n.sessionDuration||3600,Tags:[{Key:"ManagedBy",Value:"TS-Cloud"},{Key:"SourceAccount",Value:n.sourceAccountId}]}}}function UC(n){let i=[],s=[],o=n.accounts.filter((y)=>y.role==="management");if(o.length===0)i.push("No management account defined");if(o.length>1)i.push("Multiple management accounts defined");let c=n.accounts.map((y)=>y.email),u=c.filter((y,h)=>c.indexOf(y)!==h);if(u.length>0)i.push(`Duplicate email addresses: ${u.join(", ")}`);let d=n.accounts.map((y)=>y.alias),g=d.filter((y,h)=>d.indexOf(y)!==h);if(g.length>0)i.push(`Duplicate aliases: ${g.join(", ")}`);if(!n.accounts.some((y)=>y.role==="security"))s.push("No dedicated security account - consider adding one for audit logs");if(n.accounts.length<3)s.push("Less than 3 accounts - consider separating environments");if(!n.accounts.some((y)=>y.role==="production"))s.push("No production account defined");return{valid:i.length===0,errors:i,warnings:s}}function QC(n){let i=[];if(i.push(`${n.name}`),i.push("─".repeat(n.name.length)),i.push(n.description),i.push(""),n.organizationalUnits){i.push("Organizational Units:");for(let s of n.organizationalUnits){let o=s.parent?" └─ ":" ";i.push(`${o}${s.name}`)}i.push("")}i.push("Accounts:");for(let s of n.accounts)i.push(` ${s.alias.padEnd(20)} ${s.role.padEnd(15)} ${s.email}`),i.push(` ${"".padEnd(20)} ${s.description}`),i.push("");return i.join(`
2731
- `)}function HC(n={}){let{workflowName:i="Deploy",trigger:s="push",branches:o=["main"],environments:c=["production"],awsRegion:u="us-east-1",awsRole:d,bunVersion:g="latest",deployCommand:y="bun run cloud deploy",testCommand:h="bun test",buildCommand:A="bun run build"}=n,C=!!d;return`name: ${i}
2724
+ `))}catch(n){console.error(`Failed to save history: ${n}`)}}searchHistory(n){return this.history.commands.filter((i)=>i.includes(n))}clearHistory(){this.history.commands=[],this.historyIndex=0}}class tS{variables=new Map;workingDirectory=process.cwd();set(n,i){this.variables.set(n,i)}get(n){return this.variables.get(n)}has(n){return this.variables.has(n)}delete(n){this.variables.delete(n)}getAll(){return Object.fromEntries(this.variables)}clear(){this.variables.clear()}setWorkingDirectory(n){this.workingDirectory=n}getWorkingDirectory(){return this.workingDirectory}}class rS{command={};name(n){return this.command.name=n,this}description(n){return this.command.description=n,this}aliases(...n){return this.command.aliases=n,this}handler(n){return this.command.handler=n,this}autocomplete(n){return this.command.autocomplete=n,this}build(){if(!this.command.name||!this.command.description||!this.command.handler)throw Error("Command must have name, description, and handler");return this.command}}class nS{entries=[];maxSize;persistFile;trackOutput;constructor(n={}){this.maxSize=n.maxSize||1000,this.persistFile=n.persistFile,this.trackOutput=n.trackOutput||!1}add(n){if(this.entries.push({...n,timestamp:new Date}),this.entries.length>this.maxSize)this.entries=this.entries.slice(-this.maxSize)}getAll(){return[...this.entries]}getRecent(n=10){return this.entries.slice(-n)}search(n){let i=n.toLowerCase();return this.entries.filter((s)=>s.command.toLowerCase().includes(i))}searchByDate(n,i){return this.entries.filter((s)=>s.timestamp>=n&&s.timestamp<=i)}getSuccessful(){return this.entries.filter((n)=>n.success)}getFailed(){return this.entries.filter((n)=>!n.success)}getMostUsed(n=10){let i=new Map;for(let s of this.entries){let o=s.command.split(" ")[0];i.set(o,(i.get(o)||0)+1)}return Array.from(i.entries()).map(([s,o])=>({command:s,count:o})).sort((s,o)=>o.count-s.count).slice(0,n)}getStats(){let n=this.entries.length,i=this.entries.filter((g)=>g.success).length,s=this.entries.filter((g)=>!g.success).length,o=this.entries.filter((g)=>g.duration!==void 0),c=o.length>0?o.reduce((g,y)=>g+(y.duration||0),0)/o.length:0,u=this.getMostUsed(1),d=u.length>0?u[0].command:"N/A";return{total:n,successful:i,failed:s,averageDuration:c,mostUsed:d}}clear(){this.entries=[]}getByIndex(n){if(n<0||n>=this.entries.length)return;return this.entries[n]}removeByIndex(n){if(n>=0&&n<this.entries.length)this.entries.splice(n,1)}async save(){if(!this.persistFile)return;try{let n=await import("node:fs/promises"),i=JSON.stringify(this.entries,null,2);await n.writeFile(this.persistFile,i,"utf-8")}catch(n){throw Error(`Failed to save history: ${n}`)}}async load(){if(!this.persistFile)return;try{let n=await import("node:fs/promises"),i=await n.readFile(this.persistFile,"utf-8"),s=JSON.parse(i);this.entries=s.map((o)=>({...o,timestamp:new Date(o.timestamp)}))}catch{this.entries=[]}}exportJSON(){return JSON.stringify(this.entries,null,2)}exportCSV(){return["Timestamp,Command,Success,Duration",...this.entries.map((s)=>[s.timestamp.toISOString(),`"${s.command.replace(/"/g,'""')}"`,s.success,s.duration||""].join(","))].join(`
2725
+ `)}importJSON(n){let s=JSON.parse(n).map((o)=>({...o,timestamp:new Date(o.timestamp)}));if(this.entries.push(...s),this.entries.length>this.maxSize)this.entries=this.entries.slice(-this.maxSize)}groupByDate(){let n=new Map;for(let i of this.entries){let s=i.timestamp.toISOString().split("T")[0];if(!n.has(s))n.set(s,[]);n.get(s).push(i)}return n}groupByCommand(){let n=new Map;for(let i of this.entries){let s=i.command.split(" ")[0];if(!n.has(s))n.set(s,[]);n.get(s).push(i)}return n}replay(n){return this.getByIndex(n)?.command}getSuggestions(n,i=5){let s=n.toLowerCase(),o=this.entries.filter((c)=>c.command.toLowerCase().startsWith(s)).map((c)=>c.command);return[...new Set(o)].slice(0,i)}analyzePatterns(){let n=new Map,i=new Map;for(let o of this.entries){let c=o.timestamp.getHours(),u=o.timestamp.getDay();n.set(c,(n.get(c)||0)+1),i.set(u,(i.get(u)||0)+1)}let s=this.entries.length>0?this.getSuccessful().length/this.entries.length:0;return{timeOfDay:n,dayOfWeek:i,successRate:s}}}function kC(n,i={}){let{maxWidth:s=100}=i;if(n.length===0)return"No command history";let o=[];for(let c=0;c<n.length;c++){let u=n[c],d=(c+1).toString().padStart(4),g=u.timestamp.toLocaleString(),y=u.success?"✓":"✗",h=u.command;if(h.length>s-30)h=h.substring(0,s-33)+"...";let A=`${d} ${g} ${y} ${h}`;if(u.duration)A+=` (${u.duration}ms)`;o.push(A)}return o.join(`
2726
+ `)}function NC(n){let i=[];return i.push("Command History Statistics"),i.push("─".repeat(30)),i.push(`Total commands: ${n.total}`),i.push(`Successful: ${n.successful}`),i.push(`Failed: ${n.failed}`),i.push(`Success rate: ${(n.successful/n.total*100).toFixed(1)}%`),i.push(`Average duration: ${n.averageDuration.toFixed(0)}ms`),i.push(`Most used: ${n.mostUsed}`),i.join(`
2727
+ `)}class nf{deployments=new Map;async deploy(n,i){let s=this.generateDeploymentId(),o={id:s,regions:i.regions.map((c)=>({region:c.code,stackName:this.getStackName(n,c.code),status:"pending"})),status:"deploying",startTime:new Date};this.deployments.set(s,o);try{let c=i.regions.find((d)=>d.isPrimary)||i.regions[0];await this.deployToRegion(n,c,o);let u=i.regions.filter((d)=>d.code!==c.code);if(await Promise.all(u.map((d)=>this.deployToRegion(n,d,o))),i.globalResources)await this.deployGlobalResources(o,i);if(i.replication)await this.setupReplication(o,i);if(i.failover?.enabled)await this.setupFailover(o,i);return o.status="deployed",o.endTime=new Date,o}catch(c){throw o.status="failed",o.endTime=new Date,c}}async deployToRegion(n,i,s){let o=s.regions.find((c)=>c.region===i.code);if(!o)throw Error(`Region deployment not found: ${i.code}`);o.status="deploying",o.startTime=new Date;try{let c=this.createRegionConfig(n,i);await this.deployStack(o.stackName,c,i.code),o.status="deployed",o.endTime=new Date,o.outputs={stackId:`arn:aws:cloudformation:${i.code}:123456789012:stack/${o.stackName}/guid`,endpoint:`https://${o.stackName}.${i.code}.example.com`}}catch(c){throw o.status="failed",o.endTime=new Date,o.error=c instanceof Error?c.message:String(c),c}}async deployGlobalResources(n,i){let s={};if(i.globalResources?.route53)s.route53=await this.deployRoute53(n,i);if(i.globalResources?.cloudfront)s.cloudfront=await this.deployCloudFront(n,i);if(i.globalResources?.waf)s.waf=await this.deployWAF(n);n.globalResources=s}async deployRoute53(n,i){let s=[],o=[];for(let c of n.regions){if(c.status!=="deployed")continue;let u={id:`health-${c.region}`,endpoint:c.outputs?.endpoint,path:i.failover?.healthCheckPath||"/health",region:c.region};s.push(u);let d={name:"example.com",type:"A",region:c.region,setIdentifier:c.region,healthCheckId:u.id,resourceRecords:[c.outputs?.endpoint]};o.push(d)}return{healthChecks:s,recordSets:o,hostedZoneId:"Z1234567890ABC"}}async deployCloudFront(n,i){return{distributionId:"E1234567890ABC",domainName:"d1234567890abc.cloudfront.net",origins:n.regions.filter((o)=>o.status==="deployed").map((o,c)=>{let u=i.regions[c];return{id:`origin-${o.region}`,domainName:o.outputs?.endpoint,weight:u?.weight||100}}),status:"Deployed"}}async deployWAF(n){return{webAclId:"arn:aws:wafv2:us-east-1:123456789012:global/webacl/test/a1234567-b890-c123-d456-e789012345f6",webAclArn:"arn:aws:wafv2:us-east-1:123456789012:global/webacl/test/a1234567-b890-c123-d456-e789012345f6"}}async setupReplication(n,i){if(i.replication?.s3)await this.setupS3Replication(n);if(i.replication?.dynamodb)await this.setupDynamoDBReplication(n);if(i.replication?.secrets)await this.setupSecretsReplication(n)}async setupS3Replication(n){let i=n.regions.filter((s)=>s.status==="deployed");for(let s=0;s<i.length-1;s++){let o=i[s],c=i[s+1];console.log(`Setting up S3 replication: ${o.region} -> ${c.region}`)}}async setupDynamoDBReplication(n){let i=n.regions.filter((s)=>s.status==="deployed").map((s)=>s.region);console.log(`Setting up DynamoDB global table in regions: ${i.join(", ")}`)}async setupSecretsReplication(n){let i=n.regions.filter((s)=>s.status==="deployed").map((s)=>s.region);console.log(`Setting up Secrets Manager replication in regions: ${i.join(", ")}`)}async setupFailover(n,i){let s=n.regions.find((c,u)=>i.regions[u]?.isPrimary)||n.regions[0],o=n.regions.filter((c)=>c.region!==s.region);console.log(`Setting up failover: primary=${s.region}, secondary=${o.map((c)=>c.region).join(", ")}`)}async destroy(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);i.status="rolling-back";try{if(i.globalResources)await this.destroyGlobalResources(i.globalResources);await Promise.all(i.regions.map((s)=>this.destroyRegionStack(s))),this.deployments.delete(n)}catch(s){throw i.status="failed",s}}async destroyGlobalResources(n){if(n.waf)console.log("Destroying WAF resources");if(n.cloudfront)console.log("Destroying CloudFront distribution");if(n.route53)console.log("Destroying Route53 resources")}async destroyRegionStack(n){if(n.status!=="deployed")return;n.status="rolling-back";try{console.log(`Destroying stack ${n.stackName} in ${n.region}`),n.status="pending"}catch(i){throw n.status="failed",n.error=i instanceof Error?i.message:String(i),i}}getDeployment(n){return this.deployments.get(n)}listDeployments(){return Array.from(this.deployments.values())}getStackName(n,i){return`${n.project.slug}-${i}`}createRegionConfig(n,i){return{...n,infrastructure:{...n.infrastructure}}}async deployStack(n,i,s){console.log(`Deploying stack ${n} to ${s}`)}generateDeploymentId(){return`deploy-${Date.now()}-${Math.random().toString(36).substring(7)}`}}var BC=new nf;class sf{references=[];exports=new Map;addExport(n){let i=`${n.region}:${n.exportName}`;if(!this.exports.has(n.region))this.exports.set(n.region,[]);this.exports.get(n.region).push(n)}getExport(n,i){let s=this.exports.get(n);if(!s)return;return s.find((c)=>c.exportName===i)?.value}createReference(n,i,s,o){let c=`/cross-region/${n}/${s}/${o}`;return this.references.push({sourceRegion:n,targetRegion:i,resourceType:s,resourceId:o,value:c}),c}async resolveReference(n,i){let s=this.references.find((o)=>o.targetRegion===n&&o.value===i);if(!s)throw Error(`Reference not found: ${i}`);return`arn:aws:resource:${s.sourceRegion}:123456789012:${s.resourceType}/${s.resourceId}`}getReferencesForRegion(n){return this.references.filter((i)=>i.sourceRegion===n||i.targetRegion===n)}clear(){this.references=[],this.exports.clear()}}class of{resources=new Map;register(n){this.resources.set(n.id,n)}get(n){return this.resources.get(n)}getByType(n){return Array.from(this.resources.values()).filter((i)=>i.type===n)}getCloudFrontDistributions(){return this.getByType("cloudfront")}getRoute53HostedZones(){return this.getByType("route53")}getWAFWebACLs(){return this.getByType("waf")}remove(n){this.resources.delete(n)}clear(){this.resources.clear()}}class af{pairs=[];addPair(n){this.pairs.push(n)}getPairedRegion(n){let i=this.pairs.find((s)=>s.primary===n||s.secondary===n);if(!i)return;return i.primary===n?i.secondary:i.primary}getAllPairs(){return[...this.pairs]}getReplicatedPairs(){return this.pairs.filter((n)=>n.replicationConfig)}getFailoverPairs(){return this.pairs.filter((n)=>n.failoverConfig?.automatic)}arePaired(n,i){return this.pairs.some((s)=>s.primary===n&&s.secondary===i||s.primary===i&&s.secondary===n)}clear(){this.pairs=[]}}class cf{dependencies=[];addDependency(n){this.dependencies.push(n)}getDependencies(n,i){return this.dependencies.filter((s)=>s.dependentStack===n&&s.dependentRegion===i)}getDependents(n,i){return this.dependencies.filter((s)=>s.dependsOnStack===n&&s.dependsOnRegion===i)}hasDependencies(n,i){return this.getDependencies(n,i).length>0}getDeploymentOrder(n){let i=new Set,s=[],o=(c)=>{let u=`${c.name}:${c.region}`;if(i.has(u))return;i.add(u);let d=this.getDependencies(c.name,c.region);for(let g of d)o({name:g.dependsOnStack,region:g.dependsOnRegion});s.push(c)};for(let c of n)o(c);return s}detectCircularDependencies(){let n=new Set,i=new Set,s=(o,c)=>{let u=`${o}:${c}`;if(i.has(u))return!0;if(n.has(u))return!1;n.add(u),i.add(u);let d=this.getDependencies(o,c);for(let g of d)if(s(g.dependsOnStack,g.dependsOnRegion))return!0;return i.delete(u),!1};for(let o of this.dependencies)if(s(o.dependentStack,o.dependentRegion))return!0;return!1}clear(){this.dependencies=[]}}var xC=new sf,OC=new of,_C=new af,LC=new cf;var $e=[{code:"us-east-1",name:"US East (N. Virginia)",location:"Virginia, USA",launchYear:2006,availabilityZones:6,localZones:16,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"standard",multiplier:1},compliance:["PCI-DSS","HIPAA","SOC","ISO","FedRAMP"]},{code:"us-east-2",name:"US East (Ohio)",location:"Ohio, USA",launchYear:2016,availabilityZones:3,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"standard",multiplier:1},compliance:["PCI-DSS","HIPAA","SOC","ISO"]},{code:"us-west-1",name:"US West (N. California)",location:"California, USA",launchYear:2009,availabilityZones:3,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"premium",multiplier:1.1},compliance:["PCI-DSS","HIPAA","SOC","ISO"]},{code:"us-west-2",name:"US West (Oregon)",location:"Oregon, USA",launchYear:2011,availabilityZones:4,localZones:2,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"standard",multiplier:1},compliance:["PCI-DSS","HIPAA","SOC","ISO"]},{code:"eu-west-1",name:"Europe (Ireland)",location:"Dublin, Ireland",launchYear:2007,availabilityZones:3,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"standard",multiplier:1.05},compliance:["PCI-DSS","GDPR","SOC","ISO"]},{code:"eu-central-1",name:"Europe (Frankfurt)",location:"Frankfurt, Germany",launchYear:2014,availabilityZones:3,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"premium",multiplier:1.1},compliance:["PCI-DSS","GDPR","SOC","ISO"]},{code:"ap-southeast-1",name:"Asia Pacific (Singapore)",location:"Singapore",launchYear:2010,availabilityZones:3,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"premium",multiplier:1.12},compliance:["PCI-DSS","SOC","ISO","MTCS"]},{code:"ap-northeast-1",name:"Asia Pacific (Tokyo)",location:"Tokyo, Japan",launchYear:2011,availabilityZones:4,services:{compute:!0,storage:!0,database:!0,networking:!0,ml:!0,analytics:!0},pricing:{tier:"premium",multiplier:1.15},compliance:["PCI-DSS","SOC","ISO"]}];function os(n){return $e.find((i)=>i.code===n)}function $C(){return $e}function MC(n){let i=n.toLowerCase();return $e.filter((s)=>s.location.toLowerCase().includes(i))}function FC(n){return $e.filter((i)=>i.compliance.includes(n))}function UC(n){return $e.filter((i)=>i.pricing.tier===n)}function QC(n){return $e.some((i)=>i.code===n)}function HC(n){if(n.continent==="North America")return os("us-east-1");if(n.continent==="Europe")return os("eu-west-1");if(n.continent==="Asia")return os("ap-southeast-1");return os("us-east-1")}function GC(n){let i=[...$e];if(n.compliance)i=i.filter((s)=>n.compliance.every((o)=>s.compliance.includes(o)));if(n.requiredServices)i=i.filter((s)=>n.requiredServices.every((o)=>s.services[o]));if(n.pricingSensitive)i.sort((s,o)=>s.pricing.multiplier-o.pricing.multiplier);return i.slice(0,5)}function VC(n){let i=os(n);if(!i)throw Error(`Invalid region: ${n}`);let s=[];for(let o of $e){if(o.code===n)continue;let c=us(i,o),u=ms(i,o);s.push({primary:i,secondary:o,distance:c,sameContinent:u})}return s.sort((o,c)=>{if(o.sameContinent!==c.sameContinent)return o.sameContinent?1:-1;return o.distance-c.distance}),s.slice(0,3)}function us(n,i){let s={"North America":0,"South America":1,Europe:2,Asia:3,Africa:4,Oceania:5},o=Ze(n.location),c=Ze(i.location);return Math.abs((s[o]||0)-(s[c]||0))}function ms(n,i){return Ze(n.location)===Ze(i.location)}function Ze(n){if(n.includes("USA")||n.includes("Canada"))return"North America";if(n.includes("Europe")||n.includes("Ireland")||n.includes("Germany"))return"Europe";if(n.includes("Asia")||n.includes("Singapore")||n.includes("Japan"))return"Asia";if(n.includes("Brazil"))return"South America";if(n.includes("Australia"))return"Oceania";return"Unknown"}function iS(n){return`${n.name} (${n.code})`}function qC(n){return n.map((i)=>iS(i)).join(`
2728
+ `)}function jC(){let n={total:$e.length,byContinent:{},byPricingTier:{}};for(let i of $e){let s=Ze(i.location);n.byContinent[s]=(n.byContinent[s]||0)+1,n.byPricingTier[i.pricing.tier]=(n.byPricingTier[i.pricing.tier]||0)+1}return n}class df{accounts=new Map;crossAccountRoles=[];accountMappings=[];registerAccount(n){this.accounts.set(n.id,n)}getAccount(n){return this.accounts.get(n)}getAccountByAlias(n){return Array.from(this.accounts.values()).find((i)=>i.alias===n)}listAccounts(){return Array.from(this.accounts.values())}getAccountsByRole(n){return Array.from(this.accounts.values()).filter((i)=>i.role===n)}createCrossAccountRole(n,i,s,o,c){let u={roleArn:`arn:aws:iam::${i}:role/${s}`,roleName:s,sourceAccountId:n,targetAccountId:i,permissions:o,externalId:c?.externalId,sessionDuration:c?.sessionDuration||3600};return this.crossAccountRoles.push(u),u}getAssumeRolePolicyDocument(n,i){let s={Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${n}:root`},Action:"sts:AssumeRole"}]};if(i)s.Statement[0].Condition={StringEquals:{"sts:ExternalId":i}};return s}generateCrossAccountPolicy(n){return{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:n,Resource:"*"}]}}mapEnvironmentToAccount(n,i,s){this.accountMappings.push({environment:n,accountId:i,region:s})}getAccountForEnvironment(n){return this.accountMappings.find((i)=>i.environment===n)}async assumeRole(n,i,s){return console.log(`Assuming role: ${n} with session: ${i}`),{accessKeyId:"AKIAIOSFODNN7EXAMPLE",secretAccessKey:"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",sessionToken:"token",expiration:new Date(Date.now()+3600000)}}async getCredentialsForAccount(n){let i=this.accounts.get(n);if(!i)throw Error(`Account not found: ${n}`);if(i.assumeRoleArn){let s=await this.assumeRole(i.assumeRoleArn,`ts-cloud-${Date.now()}`);return{accessKeyId:s.accessKeyId,secretAccessKey:s.secretAccessKey,sessionToken:s.sessionToken}}throw Error("No credentials available for account")}listCrossAccountRoles(){return[...this.crossAccountRoles]}getCrossAccountRolesForAccount(n){return this.crossAccountRoles.filter((i)=>i.sourceAccountId===n||i.targetAccountId===n)}async validateAccountAccess(n){try{let i=await this.getCredentialsForAccount(n);return console.log(`Validating access to account: ${n}`),!0}catch{return!1}}async getConsolidatedBilling(){let n={};for(let s of this.accounts.values())n[s.id]=Math.random()*1000;return{totalCost:Object.values(n).reduce((s,o)=>s+o,0),byAccount:n}}clear(){this.accounts.clear(),this.crossAccountRoles=[],this.accountMappings=[]}}class lf{organizationId;organizationalUnits=new Map;getOrganizationId(){return this.organizationId}setOrganizationId(n){this.organizationId=n}createOrganizationalUnit(n,i){let s={id:`ou-${Date.now()}`,name:n,parentId:i,accounts:[]};return this.organizationalUnits.set(s.id,s),s}getOrganizationalUnit(n){return this.organizationalUnits.get(n)}listOrganizationalUnits(){return Array.from(this.organizationalUnits.values())}addAccountToOU(n,i){let s=this.organizationalUnits.get(n);if(!s)throw Error(`Organizational unit not found: ${n}`);if(!s.accounts.includes(i))s.accounts.push(i)}removeAccountFromOU(n,i){let s=this.organizationalUnits.get(n);if(!s)throw Error(`Organizational unit not found: ${n}`);s.accounts=s.accounts.filter((o)=>o!==i)}getAccountsInOU(n){let i=this.organizationalUnits.get(n);if(!i)return[];return[...i.accounts]}applyServiceControlPolicy(n,i){return{id:`scp-${Date.now()}`,name:"Custom SCP",targetId:n,policyDocument:i}}clear(){this.organizationId=void 0,this.organizationalUnits.clear()}}var zC=new df,KC=new lf;var sS={basic:{name:"Basic (3 Accounts)",description:"Simple structure for small teams",accounts:[{alias:"management",email:"aws+management@example.com",role:"management",ou:"root",description:"Management account for AWS Organizations"},{alias:"production",email:"aws+production@example.com",role:"production",ou:"workloads",description:"Production workloads"},{alias:"development",email:"aws+development@example.com",role:"development",ou:"workloads",description:"Development and testing"}],organizationalUnits:[{name:"root"},{name:"workloads",parent:"root"}]},standard:{name:"Standard (5 Accounts)",description:"Recommended for most organizations",accounts:[{alias:"management",email:"aws+management@example.com",role:"management",ou:"root",description:"Management account"},{alias:"security",email:"aws+security@example.com",role:"security",ou:"security",description:"Security tooling and audit logs"},{alias:"shared-services",email:"aws+shared@example.com",role:"shared-services",ou:"infrastructure",description:"Shared services (CI/CD, monitoring)"},{alias:"production",email:"aws+production@example.com",role:"production",ou:"workloads",description:"Production environment"},{alias:"staging",email:"aws+staging@example.com",role:"staging",ou:"workloads",description:"Staging environment"},{alias:"development",email:"aws+development@example.com",role:"development",ou:"workloads",description:"Development environment"}],organizationalUnits:[{name:"root"},{name:"security",parent:"root"},{name:"infrastructure",parent:"root"},{name:"workloads",parent:"root"}]},enterprise:{name:"Enterprise (7+ Accounts)",description:"For large organizations with strict compliance requirements",accounts:[{alias:"management",email:"aws+management@example.com",role:"management",ou:"root",description:"Management account"},{alias:"audit",email:"aws+audit@example.com",role:"security",ou:"security",description:"Audit and compliance"},{alias:"log-archive",email:"aws+logs@example.com",role:"security",ou:"security",description:"Centralized log storage"},{alias:"shared-services",email:"aws+shared@example.com",role:"shared-services",ou:"infrastructure",description:"Shared infrastructure"},{alias:"network",email:"aws+network@example.com",role:"shared-services",ou:"infrastructure",description:"Network infrastructure (Transit Gateway)"},{alias:"production",email:"aws+production@example.com",role:"production",ou:"production-ou",description:"Production workloads"},{alias:"staging",email:"aws+staging@example.com",role:"staging",ou:"non-production-ou",description:"Staging environment"},{alias:"development",email:"aws+development@example.com",role:"development",ou:"non-production-ou",description:"Development environment"}],organizationalUnits:[{name:"root"},{name:"security",parent:"root",policies:["deny-root-access"]},{name:"infrastructure",parent:"root"},{name:"production-ou",parent:"root",policies:["require-mfa"]},{name:"non-production-ou",parent:"root"}]}},WC={denyRootAccess:{name:"Deny Root User Access",description:"Prevent root user from performing any actions",policyDocument:{Version:"2012-10-17",Statement:[{Sid:"DenyRootUser",Effect:"Deny",Action:"*",Resource:"*",Condition:{StringLike:{"aws:PrincipalArn":"arn:aws:iam::*:root"}}}]}},requireMFA:{name:"Require MFA for All Actions",description:"Require MFA for console and API access",policyDocument:{Version:"2012-10-17",Statement:[{Sid:"RequireMFA",Effect:"Deny",Action:"*",Resource:"*",Condition:{BoolIfExists:{"aws:MultiFactorAuthPresent":"false"}}}]}},denyRegions:{name:"Deny Access to Non-Approved Regions",description:"Restrict operations to specific regions",policyDocument:{Version:"2012-10-17",Statement:[{Sid:"DenyNonApprovedRegions",Effect:"Deny",NotAction:["iam:*","organizations:*","route53:*","cloudfront:*","support:*","s3:*"],Resource:"*",Condition:{StringNotEquals:{"aws:RequestedRegion":["us-east-1","us-west-2"]}}}]}},preventLeaving:{name:"Prevent Leaving Organization",description:"Prevent accounts from leaving the organization",policyDocument:{Version:"2012-10-17",Statement:[{Sid:"PreventLeaving",Effect:"Deny",Action:"organizations:LeaveOrganization",Resource:"*"}]}},denyS3Unencrypted:{name:"Deny Unencrypted S3 Uploads",description:"Require encryption for all S3 uploads",policyDocument:{Version:"2012-10-17",Statement:[{Sid:"DenyUnencryptedS3Uploads",Effect:"Deny",Action:"s3:PutObject",Resource:"*",Condition:{StringNotEquals:{"s3:x-amz-server-side-encryption":["AES256","aws:kms"]}}}]}}},JC={deploymentRole:{name:"CrossAccountDeploymentRole",description:"Role for deploying infrastructure from CI/CD",permissions:["cloudformation:*","s3:*","ec2:*","ecs:*","lambda:*","iam:GetRole","iam:PassRole","logs:*","events:*"]},readOnlyRole:{name:"CrossAccountReadOnlyRole",description:"Read-only access for monitoring and auditing",permissions:["cloudformation:Describe*","cloudformation:List*","ec2:Describe*","ecs:Describe*","lambda:Get*","lambda:List*","s3:Get*","s3:List*","logs:Get*","logs:Describe*"]},securityAuditRole:{name:"CrossAccountSecurityAuditRole",description:"Security audit and compliance checks",permissions:["iam:Get*","iam:List*","iam:Generate*","access-analyzer:*","guardduty:Get*","guardduty:List*","securityhub:Get*","securityhub:List*","config:Describe*","config:Get*","config:List*"]},breakGlassRole:{name:"CrossAccountBreakGlassRole",description:"Emergency access role (use with caution)",permissions:["*"]}};function XC(n){return sS[n]}function YC(n,i){return{Type:"AWS::IAM::Role",Properties:{RoleName:n.roleName,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:`arn:aws:iam::${n.sourceAccountId}:root`},Action:"sts:AssumeRole",...n.externalId&&{Condition:{StringEquals:{"sts:ExternalId":n.externalId}}}}]},Policies:[{PolicyName:`${n.roleName}Policy`,PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:n.permissions,Resource:"*"}]}}],...i&&{ManagedPolicyArns:i},MaxSessionDuration:n.sessionDuration||3600,Tags:[{Key:"ManagedBy",Value:"TS-Cloud"},{Key:"SourceAccount",Value:n.sourceAccountId}]}}}function ZC(n){let i=[],s=[],o=n.accounts.filter((y)=>y.role==="management");if(o.length===0)i.push("No management account defined");if(o.length>1)i.push("Multiple management accounts defined");let c=n.accounts.map((y)=>y.email),u=c.filter((y,h)=>c.indexOf(y)!==h);if(u.length>0)i.push(`Duplicate email addresses: ${u.join(", ")}`);let d=n.accounts.map((y)=>y.alias),g=d.filter((y,h)=>d.indexOf(y)!==h);if(g.length>0)i.push(`Duplicate aliases: ${g.join(", ")}`);if(!n.accounts.some((y)=>y.role==="security"))s.push("No dedicated security account - consider adding one for audit logs");if(n.accounts.length<3)s.push("Less than 3 accounts - consider separating environments");if(!n.accounts.some((y)=>y.role==="production"))s.push("No production account defined");return{valid:i.length===0,errors:i,warnings:s}}function eE(n){let i=[];if(i.push(`${n.name}`),i.push("─".repeat(n.name.length)),i.push(n.description),i.push(""),n.organizationalUnits){i.push("Organizational Units:");for(let s of n.organizationalUnits){let o=s.parent?" └─ ":" ";i.push(`${o}${s.name}`)}i.push("")}i.push("Accounts:");for(let s of n.accounts)i.push(` ${s.alias.padEnd(20)} ${s.role.padEnd(15)} ${s.email}`),i.push(` ${"".padEnd(20)} ${s.description}`),i.push("");return i.join(`
2729
+ `)}function tE(n={}){let{workflowName:i="Deploy",trigger:s="push",branches:o=["main"],environments:c=["production"],awsRegion:u="us-east-1",awsRole:d,bunVersion:g="latest",deployCommand:y="bun run cloud deploy",testCommand:h="bun test",buildCommand:A="bun run build"}=n,C=!!d;return`name: ${i}
2732
2730
 
2733
2731
  on:
2734
2732
  ${s}:
@@ -2797,7 +2795,7 @@ jobs:
2797
2795
 
2798
2796
  - name: Post-deployment tests
2799
2797
  run: bun run cloud test:smoke
2800
- `}function GC(n){let{environments:i,awsRegion:s="us-east-1",awsRole:o}=n,c=!!o;return`name: Multi-Environment Deploy
2798
+ `}function rE(n){let{environments:i,awsRegion:s="us-east-1",awsRole:o}=n,c=!!o;return`name: Multi-Environment Deploy
2801
2799
 
2802
2800
  on:
2803
2801
  push:
@@ -2853,7 +2851,7 @@ ${i.map((u,d)=>` ${d>0?"elif":"if"} [[ "\${{ github.ref }}" == "refs/he
2853
2851
 
2854
2852
  - name: Deploy
2855
2853
  run: bun run cloud deploy --env=\${{ needs.determine-environment.outputs.environment }}
2856
- `}function VC(n={}){let{awsRegion:i="us-east-1",awsRole:s,ttl:o=24}=n,c=!!s;return`name: PR Preview Environment
2854
+ `}function nE(n={}){let{awsRegion:i="us-east-1",awsRole:s,ttl:o=24}=n,c=!!s;return`name: PR Preview Environment
2857
2855
 
2858
2856
  on:
2859
2857
  pull_request:
@@ -2958,7 +2956,7 @@ jobs:
2958
2956
  bun run cloud env:preview --destroy \\
2959
2957
  --branch=\${{ github.head_ref }} \\
2960
2958
  --pr=\${{ github.event.pull_request.number }}
2961
- `}function qC(n){let{schedule:i,environment:s,awsRegion:o="us-east-1",awsRole:c}=n;return`name: Scheduled Deployment
2959
+ `}function iE(n){let{schedule:i,environment:s,awsRegion:o="us-east-1",awsRole:c}=n;return`name: Scheduled Deployment
2962
2960
 
2963
2961
  on:
2964
2962
  schedule:
@@ -3000,7 +2998,7 @@ jobs:
3000
2998
 
3001
2999
  - name: Deploy
3002
3000
  run: bun run cloud deploy --env=\${{ env.ENVIRONMENT }}
3003
- `}function jC(n){let{matrix:i,awsRole:s}=n,o=!!s;return`name: Matrix Deployment
3001
+ `}function sE(n){let{matrix:i,awsRole:s}=n,o=!!s;return`name: Matrix Deployment
3004
3002
 
3005
3003
  on:
3006
3004
  workflow_dispatch:
@@ -3047,7 +3045,7 @@ ${i.map((c)=>` - environment: ${c.environment}
3047
3045
 
3048
3046
  - name: Deploy to \${{ matrix.environment }} (\${{ matrix.region }})
3049
3047
  run: bun run cloud deploy --env=\${{ matrix.environment }} --region=\${{ matrix.region }}
3050
- `}function zC(n={}){let{stages:i=["test","build","deploy"],environments:s=["production"],awsRegion:o="us-east-1",dockerImage:c="oven/bun:latest",deployCommand:u="bun run cloud deploy",testCommand:d="bun test",buildCommand:g="bun run build"}=n;return`stages:
3048
+ `}function oE(n={}){let{stages:i=["test","build","deploy"],environments:s=["production"],awsRegion:o="us-east-1",dockerImage:c="oven/bun:latest",deployCommand:u="bun run cloud deploy",testCommand:d="bun test",buildCommand:g="bun run build"}=n;return`stages:
3051
3049
  ${i.map((y)=>` - ${y}`).join(`
3052
3050
  `)}
3053
3051
 
@@ -3095,7 +3093,7 @@ deploy:
3095
3093
  only:
3096
3094
  - main
3097
3095
  when: manual
3098
- `}function KC(n){let{environments:i,awsRegion:s="us-east-1"}=n,o=i.map((c)=>`
3096
+ `}function aE(n){let{environments:i,awsRegion:s="us-east-1"}=n,o=i.map((c)=>`
3099
3097
  deploy:${c.name}:
3100
3098
  stage: deploy
3101
3099
  script:
@@ -3136,7 +3134,7 @@ build:
3136
3134
  paths:
3137
3135
  - dist/
3138
3136
  ${o}
3139
- `}function WC(n={}){let{awsRegion:i="us-east-1",ttl:s=24}=n;return`stages:
3137
+ `}function cE(n={}){let{awsRegion:i="us-east-1",ttl:s=24}=n;return`stages:
3140
3138
  - build
3141
3139
  - deploy
3142
3140
  - cleanup
@@ -3181,7 +3179,7 @@ cleanup:preview:
3181
3179
  when: manual
3182
3180
  only:
3183
3181
  - merge_requests
3184
- `}function JC(n){let{environment:i,awsRegion:s="us-east-1"}=n;return`stages:
3182
+ `}function dE(n){let{environment:i,awsRegion:s="us-east-1"}=n;return`stages:
3185
3183
  - deploy
3186
3184
 
3187
3185
  variables:
@@ -3200,7 +3198,7 @@ deploy:scheduled:
3200
3198
  name: \${ENVIRONMENT}
3201
3199
  only:
3202
3200
  - schedules
3203
- `}function XC(n){let{environments:i,awsRegion:s="us-east-1"}=n,o=i.map((c)=>`
3201
+ `}function lE(n){let{environments:i,awsRegion:s="us-east-1"}=n,o=i.map((c)=>`
3204
3202
  deploy:${c}:
3205
3203
  stage: deploy
3206
3204
  script:
@@ -3221,7 +3219,7 @@ variables:
3221
3219
  default:
3222
3220
  image: oven/bun:latest
3223
3221
  ${o}
3224
- `}function YC(n={}){let{awsRegion:i="us-east-1",dockerImage:s="oven/bun:latest",deployCommand:o="bun run cloud deploy",testCommand:c="bun test",buildCommand:u="bun run build",workflows:d=!0}=n;return`version: 2.1
3222
+ `}function uE(n={}){let{awsRegion:i="us-east-1",dockerImage:s="oven/bun:latest",deployCommand:o="bun run cloud deploy",testCommand:c="bun test",buildCommand:u="bun run build",workflows:d=!0}=n;return`version: 2.1
3225
3223
 
3226
3224
  orbs:
3227
3225
  aws-cli: circleci/aws-cli@4.0
@@ -3304,7 +3302,7 @@ ${d?`workflows:
3304
3302
  branches:
3305
3303
  only: main
3306
3304
  `:""}
3307
- `}function ZC(n){let{environments:i,awsRegion:s="us-east-1"}=n,o=i.map((u)=>`
3305
+ `}function gE(n){let{environments:i,awsRegion:s="us-east-1"}=n,o=i.map((u)=>`
3308
3306
  deploy-${u.name}:
3309
3307
  executor: bun-executor
3310
3308
  steps:
@@ -3380,7 +3378,7 @@ workflows:
3380
3378
  requires:
3381
3379
  - test
3382
3380
  ${c}
3383
- `}function eE(n){let{schedule:i,environment:s,awsRegion:o="us-east-1"}=n;return`version: 2.1
3381
+ `}function pE(n){let{schedule:i,environment:s,awsRegion:o="us-east-1"}=n;return`version: 2.1
3384
3382
 
3385
3383
  orbs:
3386
3384
  aws-cli: circleci/aws-cli@4.0
@@ -3417,7 +3415,7 @@ workflows:
3417
3415
  only: main
3418
3416
  jobs:
3419
3417
  - deploy
3420
- `}function tE(n){let{environments:i,awsRegion:s="us-east-1"}=n,o=i.map((u)=>`
3418
+ `}function mE(n){let{environments:i,awsRegion:s="us-east-1"}=n,o=i.map((u)=>`
3421
3419
  deploy-${u}:
3422
3420
  executor: bun-executor
3423
3421
  steps:
@@ -3493,7 +3491,7 @@ workflows:
3493
3491
  requires:
3494
3492
  - test
3495
3493
  ${c}
3496
- `}function rE(n){let{regions:i,environment:s}=n,o=i.map((u)=>`
3494
+ `}function fE(n){let{regions:i,environment:s}=n,o=i.map((u)=>`
3497
3495
  deploy-${u.replace(/-/g,"_")}:
3498
3496
  executor: bun-executor
3499
3497
  environment:
@@ -3562,7 +3560,7 @@ workflows:
3562
3560
  requires:
3563
3561
  - test
3564
3562
  ${c}
3565
- `}class El{backupPlans=new Map;backupVaults=new Map;restoreJobs=new Map;continuousBackups=new Map;planCounter=0;restoreCounter=0;continuousBackupCounter=0;createVault(n){this.backupVaults.set(n.name,n)}getVault(n){return this.backupVaults.get(n)}createBackupPlan(n){let i=`backup-plan-${Date.now()}-${this.planCounter++}`,s={id:i,...n};return this.backupPlans.set(i,s),s}getBackupPlan(n){return this.backupPlans.get(n)}listBackupPlans(){return Array.from(this.backupPlans.values())}createRDSBackupPlan(n){let{dbInstanceArn:i,schedule:s="0 2 * * *",retentionDays:o=7,vaultName:c="default-vault"}=n;return this.createBackupPlan({name:"RDS Daily Backup",schedule:s,retentionDays:o,vaultName:c,resources:[{resourceArn:i,resourceType:"rds",region:"us-east-1"}],lifecycle:{moveTocoldStorageAfterDays:30,deleteAfterDays:o}})}createDynamoDBBackupPlan(n){let{tableArn:i,schedule:s="0 3 * * *",retentionDays:o=35,crossRegionCopy:c}=n;return this.createBackupPlan({name:"DynamoDB Daily Backup",schedule:s,retentionDays:o,vaultName:"dynamodb-vault",resources:[{resourceArn:i,resourceType:"dynamodb",region:"us-east-1"}],lifecycle:{deleteAfterDays:o},tags:c?{CrossRegionCopy:c.join(",")}:void 0})}createEFSBackupPlan(n){let{fileSystemArn:i,schedule:s="0 1 * * *",retentionDays:o=30}=n;return this.createBackupPlan({name:"EFS Daily Backup",schedule:s,retentionDays:o,vaultName:"efs-vault",resources:[{resourceArn:i,resourceType:"efs",region:"us-east-1"}],lifecycle:{deleteAfterDays:o}})}enableContinuousBackup(n,i=35){let s=`continuous-backup-${Date.now()}-${this.continuousBackupCounter++}`,o={id:s,resourceId:n,enabled:!0,retentionDays:i};return this.continuousBackups.set(s,o),o}getContinuousBackup(n){return this.continuousBackups.get(n)}enablePointInTimeRecovery(n,i){return{enabled:!0,earliestRestorableTime:new Date(Date.now()-604800000),latestRestorableTime:new Date}}async restoreFromBackup(n){let{backupId:i,resourceType:s,targetRegion:o}=n,c={id:`restore-${Date.now()}-${this.restoreCounter++}`,backupId:i,resourceType:s,status:"pending",startTime:new Date,targetRegion:o};return this.restoreJobs.set(c.id,c),setTimeout(()=>{c.status="running"},100),setTimeout(()=>{c.status="completed",c.endTime=new Date},1000),c}async restoreToPointInTime(n){let{sourceResourceArn:i,targetResourceName:s,restoreTime:o,resourceType:c}=n,u={id:`pitr-${Date.now()}-${this.restoreCounter++}`,backupId:`pitr-${o.getTime()}`,resourceType:c,status:"pending",startTime:new Date};return this.restoreJobs.set(u.id,u),console.log(`Restoring ${c} from ${i} to ${s} at ${o.toISOString()}`),setTimeout(()=>{u.status="completed",u.endTime=new Date},2000),u}getRestoreJob(n){return this.restoreJobs.get(n)}listRestoreJobs(){return Array.from(this.restoreJobs.values())}setupCrossRegionReplication(n){let{sourceVault:i,sourceRegion:s,targetRegions:o}=n;console.log("Setting up cross-region replication:"),console.log(` Source: ${i} in ${s}`),console.log(` Targets: ${o.join(", ")}`)}generateBackupVaultCF(n){return{Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:n.name,...n.encryptionKeyArn&&{EncryptionKeyArn:n.encryptionKeyArn},...n.accessPolicy&&{AccessPolicy:n.accessPolicy}}}}generateBackupPlanCF(n){return{Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:n.name,BackupPlanRule:[{RuleName:"DailyBackup",TargetBackupVault:n.vaultName,ScheduleExpression:`cron(${n.schedule})`,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:n.lifecycle?{...n.lifecycle.moveTocoldStorageAfterDays&&{MoveToColdStorageAfterDays:n.lifecycle.moveTocoldStorageAfterDays},...n.lifecycle.deleteAfterDays&&{DeleteAfterDays:n.lifecycle.deleteAfterDays}}:void 0}]},...n.tags&&{BackupPlanTags:n.tags}}}}generateBackupSelectionCF(n){return{Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:{Ref:`BackupPlan${n.id}`},BackupSelection:{SelectionName:`${n.name}Selection`,IamRoleArn:"arn:aws:iam::123456789012:role/service-role/AWSBackupDefaultServiceRole",Resources:n.resources.map((i)=>i.resourceArn)}}}}clear(){this.backupPlans.clear(),this.backupVaults.clear(),this.restoreJobs.clear(),this.continuousBackups.clear(),this.planCounter=0,this.restoreCounter=0,this.continuousBackupCounter=0}}var Ky=new El;class vl{drPlans=new Map;failoverTests=new Map;planCounter=0;testCounter=0;createDRPlan(n){let i=`dr-plan-${Date.now()}-${this.planCounter++}`,s={id:i,...n};return this.drPlans.set(i,s),s}createRDSDRPlan(n){let{primaryDbArn:i,secondaryDbArn:s,primaryRegion:o,secondaryRegion:c,rto:u=60,rpo:d=5}=n;return this.createDRPlan({name:"RDS Multi-Region DR",primaryRegion:o,secondaryRegion:c,rto:u,rpo:d,resources:[{resourceId:"primary-db",resourceType:"rds",primaryArn:i,secondaryArn:s,replicationEnabled:!0}],runbook:this.generateRDSRunbook(o,c),testSchedule:"0 0 1 * *"})}createDynamoDBDRPlan(n){let{tableArn:i,regions:s,rto:o=15,rpo:c=1}=n;return this.createDRPlan({name:"DynamoDB Global Tables DR",primaryRegion:s[0],secondaryRegion:s[1],rto:o,rpo:c,resources:[{resourceId:"dynamodb-table",resourceType:"dynamodb",primaryArn:i,replicationEnabled:!0}],runbook:this.generateDynamoDBRunbook(s)})}generateRDSRunbook(n,i){return{estimatedDuration:60,requiredApprovals:["cto","engineering-lead"],steps:[{order:1,name:"Verify Primary Database Failure",description:"Confirm that the primary database is truly unavailable and not experiencing temporary issues",action:"aws rds describe-db-instances --region "+n,automatable:!0,estimatedDuration:2,rollbackable:!1},{order:2,name:"Check Replication Lag",description:"Verify that the read replica is up to date",action:"Check ReplicaLag metric in CloudWatch",automatable:!0,estimatedDuration:1,rollbackable:!1},{order:3,name:"Promote Read Replica",description:"Promote the read replica in the secondary region to be the new primary",action:"aws rds promote-read-replica --db-instance-identifier replica --region "+i,automatable:!0,estimatedDuration:10,rollbackable:!1},{order:4,name:"Update DNS Records",description:"Update Route53 records to point to the new primary database",action:"Update Route53 failover record set",automatable:!0,estimatedDuration:5,rollbackable:!0},{order:5,name:"Update Application Configuration",description:"Update application connection strings if needed",action:"Deploy configuration update to ECS/Lambda",automatable:!0,estimatedDuration:10,rollbackable:!0},{order:6,name:"Verify Application Connectivity",description:"Test that applications can connect to the new primary",action:"Run smoke tests",automatable:!0,estimatedDuration:5,rollbackable:!1},{order:7,name:"Monitor for Issues",description:"Monitor CloudWatch metrics and application logs",action:"Monitor for 30 minutes",automatable:!1,estimatedDuration:30,rollbackable:!1}]}}generateDynamoDBRunbook(n){return{estimatedDuration:15,steps:[{order:1,name:"Verify Primary Region Failure",description:"Confirm that the primary region is experiencing an outage",action:"Check AWS Health Dashboard",automatable:!0,estimatedDuration:2,rollbackable:!1},{order:2,name:"Update Route53 Failover",description:"Update Route53 to direct traffic to secondary region",action:"Update Route53 health check and failover records",automatable:!0,estimatedDuration:5,rollbackable:!0},{order:3,name:"Update Application Endpoints",description:"Update Lambda/ECS to use secondary region DynamoDB endpoint",action:"Deploy configuration update",automatable:!0,estimatedDuration:5,rollbackable:!0},{order:4,name:"Verify Data Consistency",description:"Verify that data is consistent in secondary region",action:"Run data validation queries",automatable:!0,estimatedDuration:3,rollbackable:!1}]}}async executeFailover(n,i=!1){let s=this.drPlans.get(n);if(!s)throw Error(`DR plan not found: ${n}`);let o=Date.now(),c=0;console.log(`${i?"[DRY RUN] ":""}Executing failover for plan: ${s.name}`),console.log(`Primary: ${s.primaryRegion} -> Secondary: ${s.secondaryRegion}`),console.log(`RTO: ${s.rto} minutes, RPO: ${s.rpo} minutes`),console.log("");for(let d of s.runbook.steps){if(console.log(`Step ${d.order}: ${d.name}`),console.log(` ${d.description}`),console.log(` Action: ${d.action}`),console.log(` Estimated: ${d.estimatedDuration} minutes`),i)console.log(" [SKIPPED - DRY RUN]");else if(d.automatable)console.log(" [AUTOMATED]");else console.log(" [MANUAL - WAITING]");c++,console.log("")}return{success:!0,duration:(Date.now()-o)/1000/60,completedSteps:c}}scheduleFailoverTest(n,i){let s={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:n,status:"scheduled",startTime:i};return this.failoverTests.set(s.id,s),s}async runFailoverTest(n){let i=this.drPlans.get(n);if(!i)throw Error(`DR plan not found: ${n}`);let s={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:n,status:"running",startTime:new Date,results:[]};this.failoverTests.set(s.id,s),console.log(`Running failover test for plan: ${i.name}`),console.log("This is a non-destructive test using test resources"),console.log("");for(let o of i.runbook.steps){let c=Date.now();console.log(`Testing step ${o.order}: ${o.name}`);let u={step:o.name,status:"success",duration:(Date.now()-c)/1000,message:`Successfully validated step ${o.order}`};s.results.push(u)}return s.status="completed",s.endTime=new Date,s}getDRPlan(n){return this.drPlans.get(n)}listDRPlans(){return Array.from(this.drPlans.values())}getFailoverTest(n){return this.failoverTests.get(n)}listFailoverTests(){return Array.from(this.failoverTests.values())}validateDRPlan(n){let i=[],s=[];if(n.rto<n.rpo)s.push("RTO cannot be less than RPO");if(n.rto>240)i.push("RTO exceeds 4 hours - consider improving recovery time");if(n.rpo>60)i.push("RPO exceeds 1 hour - consider more frequent backups");if(n.resources.length===0)s.push("No resources defined in DR plan");for(let u of n.resources){if(!u.replicationEnabled)i.push(`Resource ${u.resourceId} does not have replication enabled`);if(!u.secondaryArn&&u.resourceType!=="dynamodb")i.push(`Resource ${u.resourceId} does not have secondary resource defined`)}if(n.runbook.steps.length===0)s.push("No recovery steps defined in runbook");let o=n.runbook.steps.reduce((u,d)=>u+d.estimatedDuration,0);if(o>n.rto)i.push(`Estimated recovery duration (${o}m) exceeds RTO (${n.rto}m)`);let c=n.runbook.steps.filter((u)=>!u.automatable);if(c.length>0)i.push(`${c.length} manual steps in runbook - consider automation`);return{valid:s.length===0,warnings:i,errors:s}}clear(){this.drPlans.clear(),this.failoverTests.clear(),this.planCounter=0,this.testCounter=0}}var Wy=new vl;class Tl{configRules=new Map;configRecorders=new Map;deliveryChannels=new Map;ruleCounter=0;createConfigRecorder(n){return this.configRecorders.set(n.name,n),n}createDeliveryChannel(n){return this.deliveryChannels.set(n.name,n),n}createConfigRule(n){let i=`config-rule-${Date.now()}-${this.ruleCounter++}`,s={id:i,...n};return this.configRules.set(i,s),s}createS3EncryptionRule(){return this.createConfigRule({name:"s3-bucket-server-side-encryption-enabled",description:"Checks that S3 buckets have server-side encryption enabled",source:"AWS_MANAGED",identifier:"S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED",scope:{complianceResourceTypes:["AWS::S3::Bucket"]}})}createS3PublicAccessBlockRule(){return this.createConfigRule({name:"s3-bucket-public-read-prohibited",description:"Checks that S3 buckets do not allow public read access",source:"AWS_MANAGED",identifier:"S3_BUCKET_PUBLIC_READ_PROHIBITED",scope:{complianceResourceTypes:["AWS::S3::Bucket"]}})}createS3VersioningRule(){return this.createConfigRule({name:"s3-bucket-versioning-enabled",description:"Checks whether versioning is enabled for S3 buckets",source:"AWS_MANAGED",identifier:"S3_BUCKET_VERSIONING_ENABLED",scope:{complianceResourceTypes:["AWS::S3::Bucket"]}})}createRdsEncryptionRule(){return this.createConfigRule({name:"rds-storage-encrypted",description:"Checks whether storage encryption is enabled for RDS DB instances",source:"AWS_MANAGED",identifier:"RDS_STORAGE_ENCRYPTED",scope:{complianceResourceTypes:["AWS::RDS::DBInstance"]}})}createRdsSnapshotEncryptionRule(){return this.createConfigRule({name:"rds-snapshots-public-prohibited",description:"Checks if RDS snapshots are public",source:"AWS_MANAGED",identifier:"RDS_SNAPSHOTS_PUBLIC_PROHIBITED",scope:{complianceResourceTypes:["AWS::RDS::DBSnapshot","AWS::RDS::DBClusterSnapshot"]}})}createRdsBackupRule(n=7){return this.createConfigRule({name:"db-backup-enabled",description:"Checks whether RDS DB instances have backups enabled",source:"AWS_MANAGED",identifier:"DB_BACKUP_ENABLED",inputParameters:{backupRetentionPeriod:n},scope:{complianceResourceTypes:["AWS::RDS::DBInstance"]}})}createEc2InstanceProfileRule(){return this.createConfigRule({name:"ec2-instance-managed-by-systems-manager",description:"Checks if EC2 instances are managed by Systems Manager",source:"AWS_MANAGED",identifier:"EC2_INSTANCE_MANAGED_BY_SSM",scope:{complianceResourceTypes:["AWS::EC2::Instance"]}})}createEbsEncryptionRule(){return this.createConfigRule({name:"encrypted-volumes",description:"Checks whether EBS volumes are encrypted",source:"AWS_MANAGED",identifier:"ENCRYPTED_VOLUMES",scope:{complianceResourceTypes:["AWS::EC2::Volume"]}})}createIamPasswordPolicyRule(){return this.createConfigRule({name:"iam-password-policy",description:"Checks whether the IAM password policy meets specified requirements",source:"AWS_MANAGED",identifier:"IAM_PASSWORD_POLICY",inputParameters:{RequireUppercaseCharacters:!0,RequireLowercaseCharacters:!0,RequireSymbols:!0,RequireNumbers:!0,MinimumPasswordLength:14,PasswordReusePrevention:24,MaxPasswordAge:90}})}createIamMfaRule(){return this.createConfigRule({name:"iam-user-mfa-enabled",description:"Checks whether IAM users have MFA enabled",source:"AWS_MANAGED",identifier:"IAM_USER_MFA_ENABLED"})}createRootAccountMfaRule(){return this.createConfigRule({name:"root-account-mfa-enabled",description:"Checks whether the root account has MFA enabled",source:"AWS_MANAGED",identifier:"ROOT_ACCOUNT_MFA_ENABLED"})}createVpcFlowLogsRule(){return this.createConfigRule({name:"vpc-flow-logs-enabled",description:"Checks whether VPC Flow Logs is enabled",source:"AWS_MANAGED",identifier:"VPC_FLOW_LOGS_ENABLED",scope:{complianceResourceTypes:["AWS::EC2::VPC"]}})}createCloudTrailEnabledRule(){return this.createConfigRule({name:"cloudtrail-enabled",description:"Checks whether CloudTrail is enabled",source:"AWS_MANAGED",identifier:"CLOUD_TRAIL_ENABLED",maxExecutionFrequency:"TwentyFour_Hours"})}createCloudWatchAlarmRule(){return this.createConfigRule({name:"cloudwatch-alarm-action-check",description:"Checks whether CloudWatch alarms have actions configured",source:"AWS_MANAGED",identifier:"CLOUDWATCH_ALARM_ACTION_CHECK",inputParameters:{alarmActionRequired:!0,insufficientDataActionRequired:!1,okActionRequired:!1},scope:{complianceResourceTypes:["AWS::CloudWatch::Alarm"]}})}createCustomLambdaRule(n){return this.createConfigRule({name:n.name,description:n.description,source:"CUSTOM_LAMBDA",lambdaFunctionArn:n.lambdaFunctionArn,scope:n.resourceTypes?{complianceResourceTypes:n.resourceTypes}:void 0,maxExecutionFrequency:n.maxExecutionFrequency,inputParameters:n.inputParameters})}createCompliancePreset(n){let i=[];switch(n){case"hipaa":i.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createRdsBackupRule(7),this.createVpcFlowLogsRule());break;case"pci-dss":i.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createIamMfaRule(),this.createRootAccountMfaRule(),this.createVpcFlowLogsRule());break;case"sox":i.push(this.createS3VersioningRule(),this.createCloudTrailEnabledRule(),this.createRdsBackupRule(30),this.createIamPasswordPolicyRule());break;case"gdpr":i.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createRdsSnapshotEncryptionRule());break;case"basic":i.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamMfaRule(),this.createRootAccountMfaRule());break}return i}getConfigRule(n){return this.configRules.get(n)}listConfigRules(){return Array.from(this.configRules.values())}getConfigRecorder(n){return this.configRecorders.get(n)}listConfigRecorders(){return Array.from(this.configRecorders.values())}getDeliveryChannel(n){return this.deliveryChannels.get(n)}listDeliveryChannels(){return Array.from(this.deliveryChannels.values())}generateConfigRuleCF(n){let i={Type:"AWS::Config::ConfigRule",Properties:{ConfigRuleName:n.name,Description:n.description,Source:{Owner:n.source==="AWS_MANAGED"?"AWS":"CUSTOM_LAMBDA"}}};if(n.source==="AWS_MANAGED"&&n.identifier)i.Properties.Source.SourceIdentifier=n.identifier;if(n.source==="CUSTOM_LAMBDA"&&n.lambdaFunctionArn)i.Properties.Source.SourceIdentifier=n.lambdaFunctionArn,i.Properties.Source.SourceDetails=[{EventSource:"aws.config",MessageType:"ConfigurationItemChangeNotification"}];if(n.inputParameters)i.Properties.InputParameters=JSON.stringify(n.inputParameters);if(n.scope){if(i.Properties.Scope={},n.scope.complianceResourceTypes)i.Properties.Scope.ComplianceResourceTypes=n.scope.complianceResourceTypes;if(n.scope.tagKey)i.Properties.Scope.TagKey=n.scope.tagKey;if(n.scope.tagValue)i.Properties.Scope.TagValue=n.scope.tagValue}if(n.maxExecutionFrequency)i.Properties.MaximumExecutionFrequency=n.maxExecutionFrequency;return i}generateConfigRecorderCF(n){return{Type:"AWS::Config::ConfigurationRecorder",Properties:{Name:n.name,RoleArn:n.roleArn,RecordingGroup:n.recordingGroup||{AllSupported:!0,IncludeGlobalResourceTypes:!0}}}}generateDeliveryChannelCF(n){return{Type:"AWS::Config::DeliveryChannel",Properties:{Name:n.name,S3BucketName:n.s3BucketName,...n.s3KeyPrefix&&{S3KeyPrefix:n.s3KeyPrefix},...n.snsTopicArn&&{SnsTopicARN:n.snsTopicArn},...n.configSnapshotDeliveryProperties&&{ConfigSnapshotDeliveryProperties:n.configSnapshotDeliveryProperties}}}}clear(){this.configRules.clear(),this.configRecorders.clear(),this.deliveryChannels.clear(),this.ruleCounter=0}}var Jy=new Tl;class wl{trails=new Map;trailCounter=0;createTrail(n){let i=`trail-${Date.now()}-${this.trailCounter++}`,s={id:i,...n};return this.trails.set(i,s),s}createOrganizationTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,s3KeyPrefix:"organization-trail",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:n.kmsKeyId,cloudWatchLogsLogGroupArn:n.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:n.cloudWatchLogsRoleArn})}createSecurityAuditTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,s3KeyPrefix:"security-audit",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:n.kmsKeyId,cloudWatchLogsLogGroupArn:n.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:n.cloudWatchLogsRoleArn,eventSelectors:[{readWriteType:"All",includeManagementEvents:!0,excludeManagementEventSources:[]}],insightSelectors:[{insightType:"ApiCallRateInsight"},{insightType:"ApiErrorRateInsight"}]})}createDataEventsTrail(n){let i=[];if(n.s3DataBuckets&&n.s3DataBuckets.length>0)i.push({type:"AWS::S3::Object",values:n.s3DataBuckets.map((s)=>`arn:aws:s3:::${s}/*`)});if(n.lambdaFunctions&&n.lambdaFunctions.length>0)i.push({type:"AWS::Lambda::Function",values:n.lambdaFunctions});return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,s3KeyPrefix:"data-events",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"All",includeManagementEvents:!1,dataResources:i}]})}createAdvancedTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,advancedEventSelectors:n.selectors})}createReadOnlyTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"ReadOnly",includeManagementEvents:!0}]})}createWriteOnlyTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"WriteOnly",includeManagementEvents:!0}]})}getTrail(n){return this.trails.get(n)}listTrails(){return Array.from(this.trails.values())}generateTrailCF(n){let i={Type:"AWS::CloudTrail::Trail",Properties:{TrailName:n.name,S3BucketName:n.s3BucketName,IsLogging:!0,IncludeGlobalServiceEvents:n.includeGlobalServiceEvents??!0,IsMultiRegionTrail:n.isMultiRegionTrail??!0,EnableLogFileValidation:n.enableLogFileValidation??!0}};if(n.s3KeyPrefix)i.Properties.S3KeyPrefix=n.s3KeyPrefix;if(n.cloudWatchLogsLogGroupArn)i.Properties.CloudWatchLogsLogGroupArn=n.cloudWatchLogsLogGroupArn;if(n.cloudWatchLogsRoleArn)i.Properties.CloudWatchLogsRoleArn=n.cloudWatchLogsRoleArn;if(n.snsTopicName)i.Properties.SnsTopicName=n.snsTopicName;if(n.kmsKeyId)i.Properties.KMSKeyId=n.kmsKeyId;if(n.eventSelectors)i.Properties.EventSelectors=n.eventSelectors.map((s)=>({ReadWriteType:s.readWriteType,IncludeManagementEvents:s.includeManagementEvents??!0,...s.dataResources&&{DataResources:s.dataResources.map((o)=>({Type:o.type,Values:o.values}))},...s.excludeManagementEventSources&&{ExcludeManagementEventSources:s.excludeManagementEventSources}}));if(n.insightSelectors)i.Properties.InsightSelectors=n.insightSelectors.map((s)=>({InsightType:s.insightType}));if(n.advancedEventSelectors)i.Properties.AdvancedEventSelectors=n.advancedEventSelectors.map((s)=>({Name:s.name,FieldSelectors:s.fieldSelectors.map((o)=>({Field:o.field,...o.equals&&{Equals:o.equals},...o.startsWith&&{StartsWith:o.startsWith},...o.endsWith&&{EndsWith:o.endsWith},...o.notEquals&&{NotEquals:o.notEquals},...o.notStartsWith&&{NotStartsWith:o.notStartsWith},...o.notEndsWith&&{NotEndsWith:o.notEndsWith}}))}));return i}generateBucketPolicy(n,i){return{Version:"2012-10-17",Statement:[{Sid:"AWSCloudTrailAclCheck",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:GetBucketAcl",Resource:`arn:aws:s3:::${n}`},{Sid:"AWSCloudTrailWrite",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:PutObject",Resource:i.map((s)=>`arn:aws:s3:::${n}/AWSLogs/${s}/*`),Condition:{StringEquals:{"s3:x-amz-acl":"bucket-owner-full-control"}}}]}}clear(){this.trails.clear(),this.trailCounter=0}}var Xy=new wl;class Rl{detectors=new Map;threatIntelSets=new Map;ipSets=new Map;filters=new Map;detectorCounter=0;threatIntelCounter=0;ipSetCounter=0;filterCounter=0;createDetector(n){let i=`detector-${Date.now()}-${this.detectorCounter++}`,s={id:i,...n};return this.detectors.set(i,s),s}createComprehensiveDetector(){return this.createDetector({enable:!0,findingPublishingFrequency:"FIFTEEN_MINUTES",dataSources:{s3Logs:{enable:!0},kubernetes:{auditLogs:{enable:!0}},malwareProtection:{scanEc2InstanceWithFindings:{ebsVolumes:{enable:!0}}}},features:[{name:"S3_DATA_EVENTS",status:"ENABLED"},{name:"EKS_AUDIT_LOGS",status:"ENABLED"},{name:"EBS_MALWARE_PROTECTION",status:"ENABLED"},{name:"RDS_LOGIN_EVENTS",status:"ENABLED"},{name:"LAMBDA_NETWORK_LOGS",status:"ENABLED"}]})}createBasicDetector(){return this.createDetector({enable:!0,findingPublishingFrequency:"SIX_HOURS"})}createThreatIntelSet(n){let i=`threat-intel-${Date.now()}-${this.threatIntelCounter++}`,s={id:i,...n};return this.threatIntelSets.set(i,s),s}createIPSet(n){let i=`ip-set-${Date.now()}-${this.ipSetCounter++}`,s={id:i,...n};return this.ipSets.set(i,s),s}createFindingFilter(n){let i=`filter-${Date.now()}-${this.filterCounter++}`,s={id:i,...n};return this.filters.set(i,s),s}createLowSeverityArchiveFilter(n){return this.createFindingFilter({detectorId:n,name:"archive-low-severity",description:"Automatically archive low severity findings",action:"ARCHIVE",rank:1,findingCriteria:{criterion:{severity:{lt:4}}}})}createFindingTypeFilter(n,i,s){return this.createFindingFilter({detectorId:n,name:`filter-finding-types-${s.toLowerCase()}`,description:`${s==="ARCHIVE"?"Archive":"Keep"} specific finding types`,action:s,rank:2,findingCriteria:{criterion:{type:{eq:i}}}})}createTrustedIPFilter(n,i){return this.createFindingFilter({detectorId:n,name:"trusted-ip-addresses",description:"Archive findings from trusted IP addresses",action:"ARCHIVE",rank:3,findingCriteria:{criterion:{"resource.instanceDetails.networkInterfaces.privateIpAddress":{eq:i}}}})}getDetector(n){return this.detectors.get(n)}listDetectors(){return Array.from(this.detectors.values())}getThreatIntelSet(n){return this.threatIntelSets.get(n)}listThreatIntelSets(){return Array.from(this.threatIntelSets.values())}getIPSet(n){return this.ipSets.get(n)}listIPSets(){return Array.from(this.ipSets.values())}getFindingFilter(n){return this.filters.get(n)}listFindingFilters(){return Array.from(this.filters.values())}generateDetectorCF(n){let i={Type:"AWS::GuardDuty::Detector",Properties:{Enable:n.enable}};if(n.findingPublishingFrequency)i.Properties.FindingPublishingFrequency=n.findingPublishingFrequency;if(n.dataSources){if(i.Properties.DataSources={},n.dataSources.s3Logs)i.Properties.DataSources.S3Logs={Enable:n.dataSources.s3Logs.enable};if(n.dataSources.kubernetes)i.Properties.DataSources.Kubernetes={AuditLogs:{Enable:n.dataSources.kubernetes.auditLogs.enable}};if(n.dataSources.malwareProtection)i.Properties.DataSources.MalwareProtection={ScanEc2InstanceWithFindings:{EbsVolumes:{Enable:n.dataSources.malwareProtection.scanEc2InstanceWithFindings.ebsVolumes.enable}}}}if(n.features)i.Properties.Features=n.features.map((s)=>({Name:s.name,Status:s.status,...s.additionalConfiguration&&{AdditionalConfiguration:s.additionalConfiguration}}));return i}generateThreatIntelSetCF(n){return{Type:"AWS::GuardDuty::ThreatIntelSet",Properties:{DetectorId:n.detectorId,Name:n.name,Format:n.format,Location:n.location,Activate:n.activate}}}generateIPSetCF(n){return{Type:"AWS::GuardDuty::IPSet",Properties:{DetectorId:n.detectorId,Name:n.name,Format:n.format,Location:n.location,Activate:n.activate}}}generateFilterCF(n){return{Type:"AWS::GuardDuty::Filter",Properties:{DetectorId:n.detectorId,Name:n.name,Description:n.description,Action:n.action,Rank:n.rank,FindingCriteria:{Criterion:n.findingCriteria.criterion}}}}clear(){this.detectors.clear(),this.threatIntelSets.clear(),this.ipSets.clear(),this.filters.clear(),this.detectorCounter=0,this.threatIntelCounter=0,this.ipSetCounter=0,this.filterCounter=0}}var Yy=new Rl;class fr{hubs=new Map;hubCounter=0;ruleCounter=0;static Standards={AWS_FOUNDATIONAL_SECURITY:{arn:"arn:aws:securityhub:::ruleset/aws-foundational-security-best-practices/v/1.0.0",name:"AWS Foundational Security Best Practices",description:"AWS recommended security best practices"},CIS_AWS_FOUNDATIONS_1_2:{arn:"arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0",name:"CIS AWS Foundations Benchmark v1.2.0",description:"CIS AWS Foundations Benchmark v1.2.0"},CIS_AWS_FOUNDATIONS_1_4:{arn:"arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.4.0",name:"CIS AWS Foundations Benchmark v1.4.0",description:"CIS AWS Foundations Benchmark v1.4.0"},PCI_DSS:{arn:"arn:aws:securityhub:us-east-1::standards/pci-dss/v/3.2.1",name:"PCI DSS v3.2.1",description:"Payment Card Industry Data Security Standard"},NIST_800_53:{arn:"arn:aws:securityhub:us-east-1::standards/nist-800-53/v/5.0.0",name:"NIST SP 800-53 Rev. 5",description:"NIST Special Publication 800-53 Revision 5"}};createHub(n){let i=`hub-${Date.now()}-${this.hubCounter++}`,s={id:i,...n};return this.hubs.set(i,s),s}createComprehensiveHub(){return this.createHub({enable:!0,controlFindingGenerator:"SECURITY_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...fr.Standards.AWS_FOUNDATIONAL_SECURITY,enabled:!0},{id:"cis-1-4",...fr.Standards.CIS_AWS_FOUNDATIONS_1_4,enabled:!0},{id:"pci-dss",...fr.Standards.PCI_DSS,enabled:!0}]})}createBasicHub(){return this.createHub({enable:!0,controlFindingGenerator:"STANDARD_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...fr.Standards.AWS_FOUNDATIONAL_SECURITY,enabled:!0}]})}createLowSeveritySuppressionRule(){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:"Suppress Low Severity Informational Findings",description:"Automatically suppress informational findings",actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"SUPPRESSED"},note:{text:"Automatically suppressed low severity finding",updatedBy:"SecurityHub Automation"}}}],criteria:{severityLabel:[{value:"INFORMATIONAL",comparison:"EQUALS"}],recordState:[{value:"ACTIVE",comparison:"EQUALS"}]},ruleStatus:"ENABLED",ruleOrder:1}}createResourceTypeNotificationRule(n){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:"Notify on Critical Resource Findings",description:"Set findings for critical resources to NOTIFIED status",actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"NOTIFIED"},note:{text:"Critical resource finding requires attention",updatedBy:"SecurityHub Automation"}}}],criteria:{resourceType:n.map((i)=>({value:i,comparison:"EQUALS"})),severityLabel:[{value:"HIGH",comparison:"EQUALS"},{value:"CRITICAL",comparison:"EQUALS"}],workflowStatus:[{value:"NEW",comparison:"EQUALS"}]},ruleStatus:"ENABLED",ruleOrder:2}}createComplianceFailureRule(){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:"Flag Compliance Failures",description:"Increase severity for compliance failures",actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{severity:{label:"HIGH"},workflow:{status:"NOTIFIED"},note:{text:"Compliance failure detected - requires immediate attention",updatedBy:"SecurityHub Automation"}}}],criteria:{complianceStatus:[{value:"FAILED",comparison:"EQUALS"}],recordState:[{value:"ACTIVE",comparison:"EQUALS"}]},ruleStatus:"ENABLED",ruleOrder:3}}createFalsePositiveSuppressionRule(n,i){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:`Suppress False Positives - ${n}`,description:`Automatically suppress known false positives from ${n}`,actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"SUPPRESSED"},note:{text:"Known false positive - automatically suppressed",updatedBy:"SecurityHub Automation"}}}],criteria:{productName:[{value:n,comparison:"EQUALS"}],title:i.map((s)=>({value:s,comparison:"PREFIX"}))},ruleStatus:"ENABLED",ruleOrder:10}}getHub(n){return this.hubs.get(n)}listHubs(){return Array.from(this.hubs.values())}generateHubCF(n){let i={Type:"AWS::SecurityHub::Hub",Properties:{}};if(n.controlFindingGenerator)i.Properties.ControlFindingGenerator=n.controlFindingGenerator;if(n.enableDefaultStandards!==void 0)i.Properties.EnableDefaultStandards=n.enableDefaultStandards;return i}generateStandardCF(n){let i={Type:"AWS::SecurityHub::Standard",Properties:{StandardsArn:n.arn}};if(n.disabledControls&&n.disabledControls.length>0)i.Properties.DisabledStandardsControls=n.disabledControls.map((s)=>({StandardsControlArn:s,Reason:"Disabled by configuration"}));return i}generateAutomationRuleCF(n){return{Type:"AWS::SecurityHub::AutomationRule",Properties:{RuleName:n.ruleName,Description:n.description,Actions:n.actions.map((i)=>({Type:i.type,FindingFieldsUpdate:i.findingFieldsUpdate})),Criteria:n.criteria,RuleStatus:n.ruleStatus,RuleOrder:n.ruleOrder}}}clear(){this.hubs.clear(),this.hubCounter=0,this.ruleCounter=0}}var Zy=new fr;class Dl{deployments=new Map;deploymentHistory=new Map;deploymentCounter=0;resultCounter=0;createDeployment(n){let i=`bg-deployment-${Date.now()}-${this.deploymentCounter++}`,s={id:i,...n};return this.deployments.set(i,s),s}createALBDeployment(n){return this.createDeployment({name:n.name,blueEnvironment:{name:"blue",targetGroupArn:n.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:n.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:n.listenerArn,switchoverTimeSeconds:0},autoPromote:n.autoPromote,healthCheckConfig:n.healthCheckConfig})}createRoute53Deployment(n){return this.createDeployment({name:n.name,blueEnvironment:{name:"blue",targetGroupArn:n.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:n.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"route53",hostedZoneId:n.hostedZoneId,switchoverTimeSeconds:n.switchoverTimeSeconds||60}})}createECSDeployment(n){return this.createDeployment({name:n.name,blueEnvironment:{name:"blue",targetGroupArn:n.blueTargetGroupArn,taskDefinitionArn:n.blueTaskDefinitionArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:n.greenTargetGroupArn,taskDefinitionArn:n.greenTaskDefinitionArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:n.listenerArn},autoRollback:n.autoRollback??!0})}async executeDeployment(n,i=!1){let s=this.deployments.get(n);if(!s)throw Error(`Deployment not found: ${n}`);let o={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!1,errors:[]};console.log(`${i?"[DRY RUN] ":""}Starting blue/green deployment: ${s.name}`),console.log(` Active environment: ${s.activeEnvironment}`),console.log(` Routing type: ${s.routingConfig.type}`);let c=s.activeEnvironment==="blue"?"green":"blue";if(console.log(` Switching to: ${c}`),console.log(`\\n1. Deploying to ${c} environment`),!i)await new Promise((u)=>setTimeout(u,100));if(console.log(`\\n2. Running health checks on ${c} environment`),s.healthCheckConfig){let u=await this.runHealthChecks(s,c,i);if(o.healthChecksPassed=u,!u){if(o.errors?.push("Health checks failed"),o.endTime=new Date,s.autoRollback)console.log(" Auto-rollback enabled - keeping current environment active"),o.rolledBackAt=new Date;return this.recordDeployment(n,o),o}}else o.healthChecksPassed=!0;if(console.log(`\\n3. Switching traffic to ${c} environment`),!i)s.activeEnvironment=c,o.switchedAt=new Date;if(console.log(`\\n4. Monitoring ${c} environment`),!i)await new Promise((u)=>setTimeout(u,100));return o.success=!0,o.endTime=new Date,console.log("\\n✓ Deployment completed successfully"),this.recordDeployment(n,o),o}async rollback(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);let s={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!0,errors:[]};console.log(`Rolling back deployment: ${i.name}`);let o=i.activeEnvironment==="blue"?"green":"blue";return i.activeEnvironment=o,s.success=!0,s.rolledBackAt=new Date,s.endTime=new Date,console.log(` Switched back to: ${o}`),this.recordDeployment(n,s),s}async runHealthChecks(n,i,s){let o=n.healthCheckConfig;if(console.log(` Health check path: ${o.path||"/"}`),console.log(` Healthy threshold: ${o.healthyThreshold}`),console.log(` Interval: ${o.interval}s`),s)return console.log(" [SKIPPED - DRY RUN]"),!0;let c=0,u=o.healthyThreshold+2;for(let d=0;d<u;d++)if(await new Promise((y)=>setTimeout(y,50)),Math.random()>0.1){if(c++,console.log(` Check ${d+1}: ✓ Healthy (${c}/${o.healthyThreshold})`),c>=o.healthyThreshold)return!0}else c=0,console.log(` Check ${d+1}: ✗ Unhealthy`);return!1}recordDeployment(n,i){if(!this.deploymentHistory.has(n))this.deploymentHistory.set(n,[]);this.deploymentHistory.get(n).push(i)}getDeployment(n){return this.deployments.get(n)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(n){return this.deploymentHistory.get(n)||[]}generateALBListenerCF(n){let i=n.activeEnvironment==="blue"?n.blueEnvironment:n.greenEnvironment;return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:n.routingConfig.listenerArn,Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",TargetGroupArn:i.targetGroupArn}]}}}generateRoute53RecordSetCF(n,i){return[{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.routingConfig.hostedZoneId,Name:i,Type:"A",SetIdentifier:"blue",Weight:n.activeEnvironment==="blue"?100:0,AliasTarget:{HostedZoneId:n.routingConfig.hostedZoneId,DNSName:n.blueEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}},{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.routingConfig.hostedZoneId,Name:i,Type:"A",SetIdentifier:"green",Weight:n.activeEnvironment==="green"?100:0,AliasTarget:{HostedZoneId:n.routingConfig.hostedZoneId,DNSName:n.greenEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}}]}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var eS=new Dl;class rs{deployments=new Map;deploymentHistory=new Map;deploymentCounter=0;resultCounter=0;static Strategies={CONSERVATIVE:[{name:"Initial Canary",trafficPercentage:10,durationMinutes:10},{name:"Quarter Traffic",trafficPercentage:25,durationMinutes:10},{name:"Half Traffic",trafficPercentage:50,durationMinutes:15},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}],BALANCED:[{name:"Initial Canary",trafficPercentage:20,durationMinutes:5},{name:"Half Traffic",trafficPercentage:50,durationMinutes:10},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}],AGGRESSIVE:[{name:"Half Traffic",trafficPercentage:50,durationMinutes:5},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}],LINEAR_10:[{name:"Canary 10%",trafficPercentage:10,durationMinutes:5},{name:"Canary 20%",trafficPercentage:20,durationMinutes:5},{name:"Canary 30%",trafficPercentage:30,durationMinutes:5},{name:"Canary 40%",trafficPercentage:40,durationMinutes:5},{name:"Canary 50%",trafficPercentage:50,durationMinutes:5},{name:"Canary 60%",trafficPercentage:60,durationMinutes:5},{name:"Canary 70%",trafficPercentage:70,durationMinutes:5},{name:"Canary 80%",trafficPercentage:80,durationMinutes:5},{name:"Canary 90%",trafficPercentage:90,durationMinutes:5},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}]};createDeployment(n){let i=`canary-${Date.now()}-${this.deploymentCounter++}`,s={id:i,...n};return this.deployments.set(i,s),s}createLambdaCanaryDeployment(n){let i=n.strategy||"BALANCED",s=rs.Strategies[i].map((o)=>({...o,alarmThresholds:{errorRate:n.errorRateThreshold||1,latencyP99:n.latencyThreshold||1000}}));return this.createDeployment({name:n.name,baselineVersion:{version:"baseline",functionVersionArn:n.baselineVersionArn,weight:100},canaryVersion:{version:"canary",functionVersionArn:n.canaryVersionArn,weight:0},stages:s,currentStage:0,status:"pending",autoPromote:n.autoPromote??!0,autoRollback:!0})}createECSCanaryDeployment(n){let i=n.strategy||"CONSERVATIVE",s=rs.Strategies[i];return this.createDeployment({name:n.name,baselineVersion:{version:"baseline",taskDefinitionArn:n.baselineTaskDefinitionArn,targetGroupArn:n.baselineTargetGroupArn,weight:100},canaryVersion:{version:"canary",taskDefinitionArn:n.canaryTaskDefinitionArn,targetGroupArn:n.canaryTargetGroupArn,weight:0},stages:s,currentStage:0,status:"pending",autoRollback:!0})}async executeDeployment(n,i=!1){let s=this.deployments.get(n);if(!s)throw Error(`Deployment not found: ${n}`);let o={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,completedStages:0,rolledBack:!1};console.log(`${i?"[DRY RUN] ":""}Starting canary deployment: ${s.name}`),console.log(` Strategy: ${s.stages.length} stages`),console.log(` Auto-promote: ${s.autoPromote}`),console.log(` Auto-rollback: ${s.autoRollback}`),console.log(""),s.status="in_progress";for(let c=0;c<s.stages.length;c++){let u=s.stages[c];if(s.currentStage=c,console.log(`Stage ${c+1}/${s.stages.length}: ${u.name}`),console.log(` Traffic: ${u.trafficPercentage}% canary, ${100-u.trafficPercentage}% baseline`),console.log(` Duration: ${u.durationMinutes} minutes`),!i)s.baselineVersion.weight=100-u.trafficPercentage,s.canaryVersion.weight=u.trafficPercentage;if(!await this.monitorStage(s,u,i)){if(console.log(" ✗ Stage failed - metrics exceeded thresholds"),s.autoRollback)console.log("\\n Rolling back deployment..."),await this.rollback(n,i),o.rolledBack=!0,o.reason="Metrics exceeded thresholds";return o.endTime=new Date,s.status="rolled_back",this.recordDeployment(n,o),o}console.log(" ✓ Stage completed successfully"),o.completedStages++,console.log("")}return s.status="completed",o.success=!0,o.endTime=new Date,console.log("✓ Canary deployment completed successfully"),this.recordDeployment(n,o),o}async monitorStage(n,i,s){if(console.log(" Monitoring metrics..."),s)return console.log(" [SKIPPED - DRY RUN]"),!0;await new Promise((c)=>setTimeout(c,100));let o={baselineErrorRate:Math.random()*0.5,canaryErrorRate:Math.random()*0.8,baselineLatencyP99:200+Math.random()*100,canaryLatencyP99:180+Math.random()*150,baselineRequestCount:Math.floor(Math.random()*1000)+500,canaryRequestCount:Math.floor((Math.random()*1000+500)*i.trafficPercentage/100)};if(n.metrics=o,console.log(` Baseline: ${o.baselineErrorRate.toFixed(2)}% errors, ${o.baselineLatencyP99.toFixed(0)}ms P99`),console.log(` Canary: ${o.canaryErrorRate.toFixed(2)}% errors, ${o.canaryLatencyP99.toFixed(0)}ms P99`),i.alarmThresholds){let{errorRate:c,latencyP99:u}=i.alarmThresholds;if(c&&o.canaryErrorRate>c)return console.log(` ⚠ Error rate exceeded threshold: ${o.canaryErrorRate.toFixed(2)}% > ${c}%`),!1;if(u&&o.canaryLatencyP99>u)return console.log(` ⚠ Latency P99 exceeded threshold: ${o.canaryLatencyP99.toFixed(0)}ms > ${u}ms`),!1}return!0}async rollback(n,i=!1){let s=this.deployments.get(n);if(!s)throw Error(`Deployment not found: ${n}`);if(console.log(`${i?"[DRY RUN] ":""}Rolling back canary deployment: ${s.name}`),!i)s.baselineVersion.weight=100,s.canaryVersion.weight=0,s.status="rolled_back";console.log(" Traffic restored to baseline: 100%")}promoteCanary(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);console.log(`Promoting canary to baseline: ${i.name}`);let s=i.baselineVersion;i.baselineVersion=i.canaryVersion,i.canaryVersion=s,i.baselineVersion.weight=100,i.canaryVersion.weight=0,i.status="completed",console.log(" Canary promoted successfully")}recordDeployment(n,i){if(!this.deploymentHistory.has(n))this.deploymentHistory.set(n,[]);this.deploymentHistory.get(n).push(i)}getDeployment(n){return this.deployments.get(n)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(n){return this.deploymentHistory.get(n)||[]}generateLambdaAliasCF(n,i){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:{Ref:"LambdaFunction"},Name:i,FunctionVersion:n.canaryVersion.version,RoutingConfig:{AdditionalVersionWeights:[{FunctionVersion:n.baselineVersion.version,FunctionWeight:n.baselineVersion.weight/100}]}}}}generateALBListenerRuleCF(n){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:[{TargetGroupArn:n.baselineVersion.targetGroupArn,Weight:n.baselineVersion.weight},{TargetGroupArn:n.canaryVersion.targetGroupArn,Weight:n.canaryVersion.weight}],TargetGroupStickinessConfig:{Enabled:!1}}}]}}}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var tS=new rs;class Pl{tests=new Map;testCounter=0;createTest(n){let i=`abtest-${Date.now()}-${this.testCounter++}`,s={id:i,...n};return this.tests.set(i,s),s}createSimpleABTest(n){let i=n.variantTrafficPercentage||50;return this.createTest({name:n.name,description:n.description,variants:[{id:"control",name:"Control",description:"Original version",trafficPercentage:100-i,targetGroupArn:n.controlTargetGroupArn,weight:100-i},{id:"variant-a",name:"Variant A",description:"Test version",trafficPercentage:i,targetGroupArn:n.variantTargetGroupArn,weight:i}],routingStrategy:{type:n.stickySession?"cookie":"random",cookieName:n.stickySession?"ab_variant":void 0,stickySession:n.stickySession??!1,sessionDuration:1440},startTime:new Date,status:"draft"})}createMultivariateTest(n){let i=n.variants.reduce((s,o)=>s+o.trafficPercentage,0);if(i!==100)throw Error(`Traffic percentages must sum to 100, got ${i}`);return this.createTest({name:n.name,description:n.description,variants:n.variants.map((s,o)=>({id:`variant-${o}`,name:s.name,description:s.description,trafficPercentage:s.trafficPercentage,targetGroupArn:s.targetGroupArn,weight:s.trafficPercentage})),routingStrategy:n.routingStrategy||{type:"random",stickySession:!1},startTime:new Date,status:"draft"})}createHeaderBasedTest(n){return this.createTest({name:n.name,description:`Route based on ${n.headerName} header`,variants:[{id:"control",name:"Control",trafficPercentage:50,targetGroupArn:n.controlTargetGroupArn,weight:50},{id:"variant-a",name:"Variant A",trafficPercentage:50,targetGroupArn:n.variantTargetGroupArn,weight:50}],routingStrategy:{type:"header",headerName:n.headerName,stickySession:!1},startTime:new Date,status:"draft"})}createGeoBasedTest(n){return this.createTest({name:n.name,description:"Route based on geographic location",variants:[{id:"control",name:"Control (Rest of World)",trafficPercentage:50,targetGroupArn:n.controlTargetGroupArn,weight:50},{id:"variant-a",name:`Variant A (${n.regions.join(", ")})`,trafficPercentage:50,targetGroupArn:n.variantTargetGroupArn,weight:50}],routingStrategy:{type:"geo",stickySession:!0,sessionDuration:1440},startTime:new Date,status:"draft"})}startTest(n){let i=this.tests.get(n);if(!i)throw Error(`Test not found: ${n}`);if(i.status!=="draft"&&i.status!=="paused")throw Error(`Cannot start test in ${i.status} status`);i.status="active",i.startTime=new Date,console.log(`Started A/B test: ${i.name}`),console.log(` Variants: ${i.variants.length}`),i.variants.forEach((s)=>{console.log(` - ${s.name}: ${s.trafficPercentage}%`)})}pauseTest(n){let i=this.tests.get(n);if(!i)throw Error(`Test not found: ${n}`);i.status="paused",console.log(`Paused A/B test: ${i.name}`)}updateTrafficSplit(n,i,s){let o=this.tests.get(n);if(!o)throw Error(`Test not found: ${n}`);let c=o.variants.find((d)=>d.id===i);if(!c)throw Error(`Variant not found: ${i}`);let u=c.trafficPercentage;c.trafficPercentage=s,c.weight=s,console.log(`Updated ${c.name} traffic: ${u}% → ${s}%`)}analyzeResults(n){let i=this.tests.get(n);if(!i)throw Error(`Test not found: ${n}`);if(!i.metrics)i.metrics=this.collectMetrics(i);let s=i.variants[0],o=0;for(let h of i.variants){let A=i.metrics.variants[h.id];if(A&&A.conversionRate>o)o=A.conversionRate,s=h}let c=i.metrics.variants.control||i.metrics.variants[i.variants[0].id],u=i.metrics.variants[s.id],d=(u.conversionRate-c.conversionRate)/c.conversionRate*100,g=100,y=u.requests>g&&c.requests>g&&Math.abs(d)>10;return{testId:n,winningVariant:s.name,confidence:y?95:75,improvement:d,statisticalSignificance:y,metrics:i.metrics,recommendation:this.generateRecommendation(d,y,s.name)}}declareWinner(n,i){let s=this.tests.get(n);if(!s)throw Error(`Test not found: ${n}`);let o=s.variants.find((c)=>c.id===i);if(!o)throw Error(`Variant not found: ${i}`);s.variants.forEach((c)=>{if(c.id===i)c.trafficPercentage=100,c.weight=100;else c.trafficPercentage=0,c.weight=0}),s.status="completed",s.endTime=new Date,s.winner=i,console.log(`Declared winner: ${o.name}`),console.log(` All traffic now routed to ${o.name}`)}collectMetrics(n){let i={},s=0;for(let o of n.variants){let c=Math.floor(Math.random()*1000)+500,u=Math.floor(c*(Math.random()*0.1+0.05)),d=u/c*100;i[o.id]={requests:c,conversions:u,conversionRate:d,averageLatency:150+Math.random()*100,errorRate:Math.random()*0.5,revenue:u*(Math.random()*50+100)},s+=c}return{variants:i,totalRequests:s,startTime:n.startTime,lastUpdated:new Date}}generateRecommendation(n,i,s){if(!i)return"Continue test - sample size too small or no significant difference detected";if(n>20)return`Strong winner detected - ${s} shows ${n.toFixed(1)}% improvement. Recommend deploying to all traffic.`;if(n>10)return`Moderate improvement - ${s} shows ${n.toFixed(1)}% improvement. Consider deploying.`;if(n>0)return`Minor improvement - ${s} shows ${n.toFixed(1)}% improvement. May not be worth the complexity.`;return"No improvement detected - consider reverting to control variant"}getTest(n){return this.tests.get(n)}listTests(){return Array.from(this.tests.values())}generateALBListenerRuleCF(n){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:n.variants.map((i)=>({TargetGroupArn:i.targetGroupArn,Weight:i.weight})),TargetGroupStickinessConfig:{Enabled:n.routingStrategy.stickySession||!1,DurationSeconds:n.routingStrategy.sessionDuration?n.routingStrategy.sessionDuration*60:void 0}}}]}}}generateLambdaEdgeFunction(n){return`'use strict';
3563
+ `}class Bl{backupPlans=new Map;backupVaults=new Map;restoreJobs=new Map;continuousBackups=new Map;planCounter=0;restoreCounter=0;continuousBackupCounter=0;createVault(n){this.backupVaults.set(n.name,n)}getVault(n){return this.backupVaults.get(n)}createBackupPlan(n){let i=`backup-plan-${Date.now()}-${this.planCounter++}`,s={id:i,...n};return this.backupPlans.set(i,s),s}getBackupPlan(n){return this.backupPlans.get(n)}listBackupPlans(){return Array.from(this.backupPlans.values())}createRDSBackupPlan(n){let{dbInstanceArn:i,schedule:s="0 2 * * *",retentionDays:o=7,vaultName:c="default-vault"}=n;return this.createBackupPlan({name:"RDS Daily Backup",schedule:s,retentionDays:o,vaultName:c,resources:[{resourceArn:i,resourceType:"rds",region:"us-east-1"}],lifecycle:{moveTocoldStorageAfterDays:30,deleteAfterDays:o}})}createDynamoDBBackupPlan(n){let{tableArn:i,schedule:s="0 3 * * *",retentionDays:o=35,crossRegionCopy:c}=n;return this.createBackupPlan({name:"DynamoDB Daily Backup",schedule:s,retentionDays:o,vaultName:"dynamodb-vault",resources:[{resourceArn:i,resourceType:"dynamodb",region:"us-east-1"}],lifecycle:{deleteAfterDays:o},tags:c?{CrossRegionCopy:c.join(",")}:void 0})}createEFSBackupPlan(n){let{fileSystemArn:i,schedule:s="0 1 * * *",retentionDays:o=30}=n;return this.createBackupPlan({name:"EFS Daily Backup",schedule:s,retentionDays:o,vaultName:"efs-vault",resources:[{resourceArn:i,resourceType:"efs",region:"us-east-1"}],lifecycle:{deleteAfterDays:o}})}enableContinuousBackup(n,i=35){let s=`continuous-backup-${Date.now()}-${this.continuousBackupCounter++}`,o={id:s,resourceId:n,enabled:!0,retentionDays:i};return this.continuousBackups.set(s,o),o}getContinuousBackup(n){return this.continuousBackups.get(n)}enablePointInTimeRecovery(n,i){return{enabled:!0,earliestRestorableTime:new Date(Date.now()-604800000),latestRestorableTime:new Date}}async restoreFromBackup(n){let{backupId:i,resourceType:s,targetRegion:o}=n,c={id:`restore-${Date.now()}-${this.restoreCounter++}`,backupId:i,resourceType:s,status:"pending",startTime:new Date,targetRegion:o};return this.restoreJobs.set(c.id,c),setTimeout(()=>{c.status="running"},100),setTimeout(()=>{c.status="completed",c.endTime=new Date},1000),c}async restoreToPointInTime(n){let{sourceResourceArn:i,targetResourceName:s,restoreTime:o,resourceType:c}=n,u={id:`pitr-${Date.now()}-${this.restoreCounter++}`,backupId:`pitr-${o.getTime()}`,resourceType:c,status:"pending",startTime:new Date};return this.restoreJobs.set(u.id,u),console.log(`Restoring ${c} from ${i} to ${s} at ${o.toISOString()}`),setTimeout(()=>{u.status="completed",u.endTime=new Date},2000),u}getRestoreJob(n){return this.restoreJobs.get(n)}listRestoreJobs(){return Array.from(this.restoreJobs.values())}setupCrossRegionReplication(n){let{sourceVault:i,sourceRegion:s,targetRegions:o}=n;console.log("Setting up cross-region replication:"),console.log(` Source: ${i} in ${s}`),console.log(` Targets: ${o.join(", ")}`)}generateBackupVaultCF(n){return{Type:"AWS::Backup::BackupVault",Properties:{BackupVaultName:n.name,...n.encryptionKeyArn&&{EncryptionKeyArn:n.encryptionKeyArn},...n.accessPolicy&&{AccessPolicy:n.accessPolicy}}}}generateBackupPlanCF(n){return{Type:"AWS::Backup::BackupPlan",Properties:{BackupPlan:{BackupPlanName:n.name,BackupPlanRule:[{RuleName:"DailyBackup",TargetBackupVault:n.vaultName,ScheduleExpression:`cron(${n.schedule})`,StartWindowMinutes:60,CompletionWindowMinutes:120,Lifecycle:n.lifecycle?{...n.lifecycle.moveTocoldStorageAfterDays&&{MoveToColdStorageAfterDays:n.lifecycle.moveTocoldStorageAfterDays},...n.lifecycle.deleteAfterDays&&{DeleteAfterDays:n.lifecycle.deleteAfterDays}}:void 0}]},...n.tags&&{BackupPlanTags:n.tags}}}}generateBackupSelectionCF(n){return{Type:"AWS::Backup::BackupSelection",Properties:{BackupPlanId:{Ref:`BackupPlan${n.id}`},BackupSelection:{SelectionName:`${n.name}Selection`,IamRoleArn:"arn:aws:iam::123456789012:role/service-role/AWSBackupDefaultServiceRole",Resources:n.resources.map((i)=>i.resourceArn)}}}}clear(){this.backupPlans.clear(),this.backupVaults.clear(),this.restoreJobs.clear(),this.continuousBackups.clear(),this.planCounter=0,this.restoreCounter=0,this.continuousBackupCounter=0}}var oS=new Bl;class xl{drPlans=new Map;failoverTests=new Map;planCounter=0;testCounter=0;createDRPlan(n){let i=`dr-plan-${Date.now()}-${this.planCounter++}`,s={id:i,...n};return this.drPlans.set(i,s),s}createRDSDRPlan(n){let{primaryDbArn:i,secondaryDbArn:s,primaryRegion:o,secondaryRegion:c,rto:u=60,rpo:d=5}=n;return this.createDRPlan({name:"RDS Multi-Region DR",primaryRegion:o,secondaryRegion:c,rto:u,rpo:d,resources:[{resourceId:"primary-db",resourceType:"rds",primaryArn:i,secondaryArn:s,replicationEnabled:!0}],runbook:this.generateRDSRunbook(o,c),testSchedule:"0 0 1 * *"})}createDynamoDBDRPlan(n){let{tableArn:i,regions:s,rto:o=15,rpo:c=1}=n;return this.createDRPlan({name:"DynamoDB Global Tables DR",primaryRegion:s[0],secondaryRegion:s[1],rto:o,rpo:c,resources:[{resourceId:"dynamodb-table",resourceType:"dynamodb",primaryArn:i,replicationEnabled:!0}],runbook:this.generateDynamoDBRunbook(s)})}generateRDSRunbook(n,i){return{estimatedDuration:60,requiredApprovals:["cto","engineering-lead"],steps:[{order:1,name:"Verify Primary Database Failure",description:"Confirm that the primary database is truly unavailable and not experiencing temporary issues",action:"aws rds describe-db-instances --region "+n,automatable:!0,estimatedDuration:2,rollbackable:!1},{order:2,name:"Check Replication Lag",description:"Verify that the read replica is up to date",action:"Check ReplicaLag metric in CloudWatch",automatable:!0,estimatedDuration:1,rollbackable:!1},{order:3,name:"Promote Read Replica",description:"Promote the read replica in the secondary region to be the new primary",action:"aws rds promote-read-replica --db-instance-identifier replica --region "+i,automatable:!0,estimatedDuration:10,rollbackable:!1},{order:4,name:"Update DNS Records",description:"Update Route53 records to point to the new primary database",action:"Update Route53 failover record set",automatable:!0,estimatedDuration:5,rollbackable:!0},{order:5,name:"Update Application Configuration",description:"Update application connection strings if needed",action:"Deploy configuration update to ECS/Lambda",automatable:!0,estimatedDuration:10,rollbackable:!0},{order:6,name:"Verify Application Connectivity",description:"Test that applications can connect to the new primary",action:"Run smoke tests",automatable:!0,estimatedDuration:5,rollbackable:!1},{order:7,name:"Monitor for Issues",description:"Monitor CloudWatch metrics and application logs",action:"Monitor for 30 minutes",automatable:!1,estimatedDuration:30,rollbackable:!1}]}}generateDynamoDBRunbook(n){return{estimatedDuration:15,steps:[{order:1,name:"Verify Primary Region Failure",description:"Confirm that the primary region is experiencing an outage",action:"Check AWS Health Dashboard",automatable:!0,estimatedDuration:2,rollbackable:!1},{order:2,name:"Update Route53 Failover",description:"Update Route53 to direct traffic to secondary region",action:"Update Route53 health check and failover records",automatable:!0,estimatedDuration:5,rollbackable:!0},{order:3,name:"Update Application Endpoints",description:"Update Lambda/ECS to use secondary region DynamoDB endpoint",action:"Deploy configuration update",automatable:!0,estimatedDuration:5,rollbackable:!0},{order:4,name:"Verify Data Consistency",description:"Verify that data is consistent in secondary region",action:"Run data validation queries",automatable:!0,estimatedDuration:3,rollbackable:!1}]}}async executeFailover(n,i=!1){let s=this.drPlans.get(n);if(!s)throw Error(`DR plan not found: ${n}`);let o=Date.now(),c=0;console.log(`${i?"[DRY RUN] ":""}Executing failover for plan: ${s.name}`),console.log(`Primary: ${s.primaryRegion} -> Secondary: ${s.secondaryRegion}`),console.log(`RTO: ${s.rto} minutes, RPO: ${s.rpo} minutes`),console.log("");for(let d of s.runbook.steps){if(console.log(`Step ${d.order}: ${d.name}`),console.log(` ${d.description}`),console.log(` Action: ${d.action}`),console.log(` Estimated: ${d.estimatedDuration} minutes`),i)console.log(" [SKIPPED - DRY RUN]");else if(d.automatable)console.log(" [AUTOMATED]");else console.log(" [MANUAL - WAITING]");c++,console.log("")}return{success:!0,duration:(Date.now()-o)/1000/60,completedSteps:c}}scheduleFailoverTest(n,i){let s={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:n,status:"scheduled",startTime:i};return this.failoverTests.set(s.id,s),s}async runFailoverTest(n){let i=this.drPlans.get(n);if(!i)throw Error(`DR plan not found: ${n}`);let s={id:`failover-test-${Date.now()}-${this.testCounter++}`,planId:n,status:"running",startTime:new Date,results:[]};this.failoverTests.set(s.id,s),console.log(`Running failover test for plan: ${i.name}`),console.log("This is a non-destructive test using test resources"),console.log("");for(let o of i.runbook.steps){let c=Date.now();console.log(`Testing step ${o.order}: ${o.name}`);let u={step:o.name,status:"success",duration:(Date.now()-c)/1000,message:`Successfully validated step ${o.order}`};s.results.push(u)}return s.status="completed",s.endTime=new Date,s}getDRPlan(n){return this.drPlans.get(n)}listDRPlans(){return Array.from(this.drPlans.values())}getFailoverTest(n){return this.failoverTests.get(n)}listFailoverTests(){return Array.from(this.failoverTests.values())}validateDRPlan(n){let i=[],s=[];if(n.rto<n.rpo)s.push("RTO cannot be less than RPO");if(n.rto>240)i.push("RTO exceeds 4 hours - consider improving recovery time");if(n.rpo>60)i.push("RPO exceeds 1 hour - consider more frequent backups");if(n.resources.length===0)s.push("No resources defined in DR plan");for(let u of n.resources){if(!u.replicationEnabled)i.push(`Resource ${u.resourceId} does not have replication enabled`);if(!u.secondaryArn&&u.resourceType!=="dynamodb")i.push(`Resource ${u.resourceId} does not have secondary resource defined`)}if(n.runbook.steps.length===0)s.push("No recovery steps defined in runbook");let o=n.runbook.steps.reduce((u,d)=>u+d.estimatedDuration,0);if(o>n.rto)i.push(`Estimated recovery duration (${o}m) exceeds RTO (${n.rto}m)`);let c=n.runbook.steps.filter((u)=>!u.automatable);if(c.length>0)i.push(`${c.length} manual steps in runbook - consider automation`);return{valid:s.length===0,warnings:i,errors:s}}clear(){this.drPlans.clear(),this.failoverTests.clear(),this.planCounter=0,this.testCounter=0}}var aS=new xl;class Ol{configRules=new Map;configRecorders=new Map;deliveryChannels=new Map;ruleCounter=0;createConfigRecorder(n){return this.configRecorders.set(n.name,n),n}createDeliveryChannel(n){return this.deliveryChannels.set(n.name,n),n}createConfigRule(n){let i=`config-rule-${Date.now()}-${this.ruleCounter++}`,s={id:i,...n};return this.configRules.set(i,s),s}createS3EncryptionRule(){return this.createConfigRule({name:"s3-bucket-server-side-encryption-enabled",description:"Checks that S3 buckets have server-side encryption enabled",source:"AWS_MANAGED",identifier:"S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED",scope:{complianceResourceTypes:["AWS::S3::Bucket"]}})}createS3PublicAccessBlockRule(){return this.createConfigRule({name:"s3-bucket-public-read-prohibited",description:"Checks that S3 buckets do not allow public read access",source:"AWS_MANAGED",identifier:"S3_BUCKET_PUBLIC_READ_PROHIBITED",scope:{complianceResourceTypes:["AWS::S3::Bucket"]}})}createS3VersioningRule(){return this.createConfigRule({name:"s3-bucket-versioning-enabled",description:"Checks whether versioning is enabled for S3 buckets",source:"AWS_MANAGED",identifier:"S3_BUCKET_VERSIONING_ENABLED",scope:{complianceResourceTypes:["AWS::S3::Bucket"]}})}createRdsEncryptionRule(){return this.createConfigRule({name:"rds-storage-encrypted",description:"Checks whether storage encryption is enabled for RDS DB instances",source:"AWS_MANAGED",identifier:"RDS_STORAGE_ENCRYPTED",scope:{complianceResourceTypes:["AWS::RDS::DBInstance"]}})}createRdsSnapshotEncryptionRule(){return this.createConfigRule({name:"rds-snapshots-public-prohibited",description:"Checks if RDS snapshots are public",source:"AWS_MANAGED",identifier:"RDS_SNAPSHOTS_PUBLIC_PROHIBITED",scope:{complianceResourceTypes:["AWS::RDS::DBSnapshot","AWS::RDS::DBClusterSnapshot"]}})}createRdsBackupRule(n=7){return this.createConfigRule({name:"db-backup-enabled",description:"Checks whether RDS DB instances have backups enabled",source:"AWS_MANAGED",identifier:"DB_BACKUP_ENABLED",inputParameters:{backupRetentionPeriod:n},scope:{complianceResourceTypes:["AWS::RDS::DBInstance"]}})}createEc2InstanceProfileRule(){return this.createConfigRule({name:"ec2-instance-managed-by-systems-manager",description:"Checks if EC2 instances are managed by Systems Manager",source:"AWS_MANAGED",identifier:"EC2_INSTANCE_MANAGED_BY_SSM",scope:{complianceResourceTypes:["AWS::EC2::Instance"]}})}createEbsEncryptionRule(){return this.createConfigRule({name:"encrypted-volumes",description:"Checks whether EBS volumes are encrypted",source:"AWS_MANAGED",identifier:"ENCRYPTED_VOLUMES",scope:{complianceResourceTypes:["AWS::EC2::Volume"]}})}createIamPasswordPolicyRule(){return this.createConfigRule({name:"iam-password-policy",description:"Checks whether the IAM password policy meets specified requirements",source:"AWS_MANAGED",identifier:"IAM_PASSWORD_POLICY",inputParameters:{RequireUppercaseCharacters:!0,RequireLowercaseCharacters:!0,RequireSymbols:!0,RequireNumbers:!0,MinimumPasswordLength:14,PasswordReusePrevention:24,MaxPasswordAge:90}})}createIamMfaRule(){return this.createConfigRule({name:"iam-user-mfa-enabled",description:"Checks whether IAM users have MFA enabled",source:"AWS_MANAGED",identifier:"IAM_USER_MFA_ENABLED"})}createRootAccountMfaRule(){return this.createConfigRule({name:"root-account-mfa-enabled",description:"Checks whether the root account has MFA enabled",source:"AWS_MANAGED",identifier:"ROOT_ACCOUNT_MFA_ENABLED"})}createVpcFlowLogsRule(){return this.createConfigRule({name:"vpc-flow-logs-enabled",description:"Checks whether VPC Flow Logs is enabled",source:"AWS_MANAGED",identifier:"VPC_FLOW_LOGS_ENABLED",scope:{complianceResourceTypes:["AWS::EC2::VPC"]}})}createCloudTrailEnabledRule(){return this.createConfigRule({name:"cloudtrail-enabled",description:"Checks whether CloudTrail is enabled",source:"AWS_MANAGED",identifier:"CLOUD_TRAIL_ENABLED",maxExecutionFrequency:"TwentyFour_Hours"})}createCloudWatchAlarmRule(){return this.createConfigRule({name:"cloudwatch-alarm-action-check",description:"Checks whether CloudWatch alarms have actions configured",source:"AWS_MANAGED",identifier:"CLOUDWATCH_ALARM_ACTION_CHECK",inputParameters:{alarmActionRequired:!0,insufficientDataActionRequired:!1,okActionRequired:!1},scope:{complianceResourceTypes:["AWS::CloudWatch::Alarm"]}})}createCustomLambdaRule(n){return this.createConfigRule({name:n.name,description:n.description,source:"CUSTOM_LAMBDA",lambdaFunctionArn:n.lambdaFunctionArn,scope:n.resourceTypes?{complianceResourceTypes:n.resourceTypes}:void 0,maxExecutionFrequency:n.maxExecutionFrequency,inputParameters:n.inputParameters})}createCompliancePreset(n){let i=[];switch(n){case"hipaa":i.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createRdsBackupRule(7),this.createVpcFlowLogsRule());break;case"pci-dss":i.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamPasswordPolicyRule(),this.createIamMfaRule(),this.createRootAccountMfaRule(),this.createVpcFlowLogsRule());break;case"sox":i.push(this.createS3VersioningRule(),this.createCloudTrailEnabledRule(),this.createRdsBackupRule(30),this.createIamPasswordPolicyRule());break;case"gdpr":i.push(this.createS3EncryptionRule(),this.createRdsEncryptionRule(),this.createEbsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createRdsSnapshotEncryptionRule());break;case"basic":i.push(this.createS3EncryptionRule(),this.createS3PublicAccessBlockRule(),this.createRdsEncryptionRule(),this.createCloudTrailEnabledRule(),this.createIamMfaRule(),this.createRootAccountMfaRule());break}return i}getConfigRule(n){return this.configRules.get(n)}listConfigRules(){return Array.from(this.configRules.values())}getConfigRecorder(n){return this.configRecorders.get(n)}listConfigRecorders(){return Array.from(this.configRecorders.values())}getDeliveryChannel(n){return this.deliveryChannels.get(n)}listDeliveryChannels(){return Array.from(this.deliveryChannels.values())}generateConfigRuleCF(n){let i={Type:"AWS::Config::ConfigRule",Properties:{ConfigRuleName:n.name,Description:n.description,Source:{Owner:n.source==="AWS_MANAGED"?"AWS":"CUSTOM_LAMBDA"}}};if(n.source==="AWS_MANAGED"&&n.identifier)i.Properties.Source.SourceIdentifier=n.identifier;if(n.source==="CUSTOM_LAMBDA"&&n.lambdaFunctionArn)i.Properties.Source.SourceIdentifier=n.lambdaFunctionArn,i.Properties.Source.SourceDetails=[{EventSource:"aws.config",MessageType:"ConfigurationItemChangeNotification"}];if(n.inputParameters)i.Properties.InputParameters=JSON.stringify(n.inputParameters);if(n.scope){if(i.Properties.Scope={},n.scope.complianceResourceTypes)i.Properties.Scope.ComplianceResourceTypes=n.scope.complianceResourceTypes;if(n.scope.tagKey)i.Properties.Scope.TagKey=n.scope.tagKey;if(n.scope.tagValue)i.Properties.Scope.TagValue=n.scope.tagValue}if(n.maxExecutionFrequency)i.Properties.MaximumExecutionFrequency=n.maxExecutionFrequency;return i}generateConfigRecorderCF(n){return{Type:"AWS::Config::ConfigurationRecorder",Properties:{Name:n.name,RoleArn:n.roleArn,RecordingGroup:n.recordingGroup||{AllSupported:!0,IncludeGlobalResourceTypes:!0}}}}generateDeliveryChannelCF(n){return{Type:"AWS::Config::DeliveryChannel",Properties:{Name:n.name,S3BucketName:n.s3BucketName,...n.s3KeyPrefix&&{S3KeyPrefix:n.s3KeyPrefix},...n.snsTopicArn&&{SnsTopicARN:n.snsTopicArn},...n.configSnapshotDeliveryProperties&&{ConfigSnapshotDeliveryProperties:n.configSnapshotDeliveryProperties}}}}clear(){this.configRules.clear(),this.configRecorders.clear(),this.deliveryChannels.clear(),this.ruleCounter=0}}var cS=new Ol;class _l{trails=new Map;trailCounter=0;createTrail(n){let i=`trail-${Date.now()}-${this.trailCounter++}`,s={id:i,...n};return this.trails.set(i,s),s}createOrganizationTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,s3KeyPrefix:"organization-trail",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:n.kmsKeyId,cloudWatchLogsLogGroupArn:n.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:n.cloudWatchLogsRoleArn})}createSecurityAuditTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,s3KeyPrefix:"security-audit",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,kmsKeyId:n.kmsKeyId,cloudWatchLogsLogGroupArn:n.cloudWatchLogsLogGroupArn,cloudWatchLogsRoleArn:n.cloudWatchLogsRoleArn,eventSelectors:[{readWriteType:"All",includeManagementEvents:!0,excludeManagementEventSources:[]}],insightSelectors:[{insightType:"ApiCallRateInsight"},{insightType:"ApiErrorRateInsight"}]})}createDataEventsTrail(n){let i=[];if(n.s3DataBuckets&&n.s3DataBuckets.length>0)i.push({type:"AWS::S3::Object",values:n.s3DataBuckets.map((s)=>`arn:aws:s3:::${s}/*`)});if(n.lambdaFunctions&&n.lambdaFunctions.length>0)i.push({type:"AWS::Lambda::Function",values:n.lambdaFunctions});return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,s3KeyPrefix:"data-events",includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"All",includeManagementEvents:!1,dataResources:i}]})}createAdvancedTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,advancedEventSelectors:n.selectors})}createReadOnlyTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"ReadOnly",includeManagementEvents:!0}]})}createWriteOnlyTrail(n){return this.createTrail({name:n.name,s3BucketName:n.s3BucketName,includeGlobalServiceEvents:!0,isMultiRegionTrail:!0,enableLogFileValidation:!0,eventSelectors:[{readWriteType:"WriteOnly",includeManagementEvents:!0}]})}getTrail(n){return this.trails.get(n)}listTrails(){return Array.from(this.trails.values())}generateTrailCF(n){let i={Type:"AWS::CloudTrail::Trail",Properties:{TrailName:n.name,S3BucketName:n.s3BucketName,IsLogging:!0,IncludeGlobalServiceEvents:n.includeGlobalServiceEvents??!0,IsMultiRegionTrail:n.isMultiRegionTrail??!0,EnableLogFileValidation:n.enableLogFileValidation??!0}};if(n.s3KeyPrefix)i.Properties.S3KeyPrefix=n.s3KeyPrefix;if(n.cloudWatchLogsLogGroupArn)i.Properties.CloudWatchLogsLogGroupArn=n.cloudWatchLogsLogGroupArn;if(n.cloudWatchLogsRoleArn)i.Properties.CloudWatchLogsRoleArn=n.cloudWatchLogsRoleArn;if(n.snsTopicName)i.Properties.SnsTopicName=n.snsTopicName;if(n.kmsKeyId)i.Properties.KMSKeyId=n.kmsKeyId;if(n.eventSelectors)i.Properties.EventSelectors=n.eventSelectors.map((s)=>({ReadWriteType:s.readWriteType,IncludeManagementEvents:s.includeManagementEvents??!0,...s.dataResources&&{DataResources:s.dataResources.map((o)=>({Type:o.type,Values:o.values}))},...s.excludeManagementEventSources&&{ExcludeManagementEventSources:s.excludeManagementEventSources}}));if(n.insightSelectors)i.Properties.InsightSelectors=n.insightSelectors.map((s)=>({InsightType:s.insightType}));if(n.advancedEventSelectors)i.Properties.AdvancedEventSelectors=n.advancedEventSelectors.map((s)=>({Name:s.name,FieldSelectors:s.fieldSelectors.map((o)=>({Field:o.field,...o.equals&&{Equals:o.equals},...o.startsWith&&{StartsWith:o.startsWith},...o.endsWith&&{EndsWith:o.endsWith},...o.notEquals&&{NotEquals:o.notEquals},...o.notStartsWith&&{NotStartsWith:o.notStartsWith},...o.notEndsWith&&{NotEndsWith:o.notEndsWith}}))}));return i}generateBucketPolicy(n,i){return{Version:"2012-10-17",Statement:[{Sid:"AWSCloudTrailAclCheck",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:GetBucketAcl",Resource:`arn:aws:s3:::${n}`},{Sid:"AWSCloudTrailWrite",Effect:"Allow",Principal:{Service:"cloudtrail.amazonaws.com"},Action:"s3:PutObject",Resource:i.map((s)=>`arn:aws:s3:::${n}/AWSLogs/${s}/*`),Condition:{StringEquals:{"s3:x-amz-acl":"bucket-owner-full-control"}}}]}}clear(){this.trails.clear(),this.trailCounter=0}}var dS=new _l;class Ll{detectors=new Map;threatIntelSets=new Map;ipSets=new Map;filters=new Map;detectorCounter=0;threatIntelCounter=0;ipSetCounter=0;filterCounter=0;createDetector(n){let i=`detector-${Date.now()}-${this.detectorCounter++}`,s={id:i,...n};return this.detectors.set(i,s),s}createComprehensiveDetector(){return this.createDetector({enable:!0,findingPublishingFrequency:"FIFTEEN_MINUTES",dataSources:{s3Logs:{enable:!0},kubernetes:{auditLogs:{enable:!0}},malwareProtection:{scanEc2InstanceWithFindings:{ebsVolumes:{enable:!0}}}},features:[{name:"S3_DATA_EVENTS",status:"ENABLED"},{name:"EKS_AUDIT_LOGS",status:"ENABLED"},{name:"EBS_MALWARE_PROTECTION",status:"ENABLED"},{name:"RDS_LOGIN_EVENTS",status:"ENABLED"},{name:"LAMBDA_NETWORK_LOGS",status:"ENABLED"}]})}createBasicDetector(){return this.createDetector({enable:!0,findingPublishingFrequency:"SIX_HOURS"})}createThreatIntelSet(n){let i=`threat-intel-${Date.now()}-${this.threatIntelCounter++}`,s={id:i,...n};return this.threatIntelSets.set(i,s),s}createIPSet(n){let i=`ip-set-${Date.now()}-${this.ipSetCounter++}`,s={id:i,...n};return this.ipSets.set(i,s),s}createFindingFilter(n){let i=`filter-${Date.now()}-${this.filterCounter++}`,s={id:i,...n};return this.filters.set(i,s),s}createLowSeverityArchiveFilter(n){return this.createFindingFilter({detectorId:n,name:"archive-low-severity",description:"Automatically archive low severity findings",action:"ARCHIVE",rank:1,findingCriteria:{criterion:{severity:{lt:4}}}})}createFindingTypeFilter(n,i,s){return this.createFindingFilter({detectorId:n,name:`filter-finding-types-${s.toLowerCase()}`,description:`${s==="ARCHIVE"?"Archive":"Keep"} specific finding types`,action:s,rank:2,findingCriteria:{criterion:{type:{eq:i}}}})}createTrustedIPFilter(n,i){return this.createFindingFilter({detectorId:n,name:"trusted-ip-addresses",description:"Archive findings from trusted IP addresses",action:"ARCHIVE",rank:3,findingCriteria:{criterion:{"resource.instanceDetails.networkInterfaces.privateIpAddress":{eq:i}}}})}getDetector(n){return this.detectors.get(n)}listDetectors(){return Array.from(this.detectors.values())}getThreatIntelSet(n){return this.threatIntelSets.get(n)}listThreatIntelSets(){return Array.from(this.threatIntelSets.values())}getIPSet(n){return this.ipSets.get(n)}listIPSets(){return Array.from(this.ipSets.values())}getFindingFilter(n){return this.filters.get(n)}listFindingFilters(){return Array.from(this.filters.values())}generateDetectorCF(n){let i={Type:"AWS::GuardDuty::Detector",Properties:{Enable:n.enable}};if(n.findingPublishingFrequency)i.Properties.FindingPublishingFrequency=n.findingPublishingFrequency;if(n.dataSources){if(i.Properties.DataSources={},n.dataSources.s3Logs)i.Properties.DataSources.S3Logs={Enable:n.dataSources.s3Logs.enable};if(n.dataSources.kubernetes)i.Properties.DataSources.Kubernetes={AuditLogs:{Enable:n.dataSources.kubernetes.auditLogs.enable}};if(n.dataSources.malwareProtection)i.Properties.DataSources.MalwareProtection={ScanEc2InstanceWithFindings:{EbsVolumes:{Enable:n.dataSources.malwareProtection.scanEc2InstanceWithFindings.ebsVolumes.enable}}}}if(n.features)i.Properties.Features=n.features.map((s)=>({Name:s.name,Status:s.status,...s.additionalConfiguration&&{AdditionalConfiguration:s.additionalConfiguration}}));return i}generateThreatIntelSetCF(n){return{Type:"AWS::GuardDuty::ThreatIntelSet",Properties:{DetectorId:n.detectorId,Name:n.name,Format:n.format,Location:n.location,Activate:n.activate}}}generateIPSetCF(n){return{Type:"AWS::GuardDuty::IPSet",Properties:{DetectorId:n.detectorId,Name:n.name,Format:n.format,Location:n.location,Activate:n.activate}}}generateFilterCF(n){return{Type:"AWS::GuardDuty::Filter",Properties:{DetectorId:n.detectorId,Name:n.name,Description:n.description,Action:n.action,Rank:n.rank,FindingCriteria:{Criterion:n.findingCriteria.criterion}}}}clear(){this.detectors.clear(),this.threatIntelSets.clear(),this.ipSets.clear(),this.filters.clear(),this.detectorCounter=0,this.threatIntelCounter=0,this.ipSetCounter=0,this.filterCounter=0}}var lS=new Ll;class hr{hubs=new Map;hubCounter=0;ruleCounter=0;static Standards={AWS_FOUNDATIONAL_SECURITY:{arn:"arn:aws:securityhub:::ruleset/aws-foundational-security-best-practices/v/1.0.0",name:"AWS Foundational Security Best Practices",description:"AWS recommended security best practices"},CIS_AWS_FOUNDATIONS_1_2:{arn:"arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0",name:"CIS AWS Foundations Benchmark v1.2.0",description:"CIS AWS Foundations Benchmark v1.2.0"},CIS_AWS_FOUNDATIONS_1_4:{arn:"arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.4.0",name:"CIS AWS Foundations Benchmark v1.4.0",description:"CIS AWS Foundations Benchmark v1.4.0"},PCI_DSS:{arn:"arn:aws:securityhub:us-east-1::standards/pci-dss/v/3.2.1",name:"PCI DSS v3.2.1",description:"Payment Card Industry Data Security Standard"},NIST_800_53:{arn:"arn:aws:securityhub:us-east-1::standards/nist-800-53/v/5.0.0",name:"NIST SP 800-53 Rev. 5",description:"NIST Special Publication 800-53 Revision 5"}};createHub(n){let i=`hub-${Date.now()}-${this.hubCounter++}`,s={id:i,...n};return this.hubs.set(i,s),s}createComprehensiveHub(){return this.createHub({enable:!0,controlFindingGenerator:"SECURITY_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...hr.Standards.AWS_FOUNDATIONAL_SECURITY,enabled:!0},{id:"cis-1-4",...hr.Standards.CIS_AWS_FOUNDATIONS_1_4,enabled:!0},{id:"pci-dss",...hr.Standards.PCI_DSS,enabled:!0}]})}createBasicHub(){return this.createHub({enable:!0,controlFindingGenerator:"STANDARD_CONTROL",enableDefaultStandards:!0,standards:[{id:"aws-foundational",...hr.Standards.AWS_FOUNDATIONAL_SECURITY,enabled:!0}]})}createLowSeveritySuppressionRule(){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:"Suppress Low Severity Informational Findings",description:"Automatically suppress informational findings",actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"SUPPRESSED"},note:{text:"Automatically suppressed low severity finding",updatedBy:"SecurityHub Automation"}}}],criteria:{severityLabel:[{value:"INFORMATIONAL",comparison:"EQUALS"}],recordState:[{value:"ACTIVE",comparison:"EQUALS"}]},ruleStatus:"ENABLED",ruleOrder:1}}createResourceTypeNotificationRule(n){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:"Notify on Critical Resource Findings",description:"Set findings for critical resources to NOTIFIED status",actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"NOTIFIED"},note:{text:"Critical resource finding requires attention",updatedBy:"SecurityHub Automation"}}}],criteria:{resourceType:n.map((i)=>({value:i,comparison:"EQUALS"})),severityLabel:[{value:"HIGH",comparison:"EQUALS"},{value:"CRITICAL",comparison:"EQUALS"}],workflowStatus:[{value:"NEW",comparison:"EQUALS"}]},ruleStatus:"ENABLED",ruleOrder:2}}createComplianceFailureRule(){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:"Flag Compliance Failures",description:"Increase severity for compliance failures",actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{severity:{label:"HIGH"},workflow:{status:"NOTIFIED"},note:{text:"Compliance failure detected - requires immediate attention",updatedBy:"SecurityHub Automation"}}}],criteria:{complianceStatus:[{value:"FAILED",comparison:"EQUALS"}],recordState:[{value:"ACTIVE",comparison:"EQUALS"}]},ruleStatus:"ENABLED",ruleOrder:3}}createFalsePositiveSuppressionRule(n,i){return{id:`rule-${Date.now()}-${this.ruleCounter++}`,ruleName:`Suppress False Positives - ${n}`,description:`Automatically suppress known false positives from ${n}`,actions:[{type:"FINDING_FIELDS_UPDATE",findingFieldsUpdate:{workflow:{status:"SUPPRESSED"},note:{text:"Known false positive - automatically suppressed",updatedBy:"SecurityHub Automation"}}}],criteria:{productName:[{value:n,comparison:"EQUALS"}],title:i.map((s)=>({value:s,comparison:"PREFIX"}))},ruleStatus:"ENABLED",ruleOrder:10}}getHub(n){return this.hubs.get(n)}listHubs(){return Array.from(this.hubs.values())}generateHubCF(n){let i={Type:"AWS::SecurityHub::Hub",Properties:{}};if(n.controlFindingGenerator)i.Properties.ControlFindingGenerator=n.controlFindingGenerator;if(n.enableDefaultStandards!==void 0)i.Properties.EnableDefaultStandards=n.enableDefaultStandards;return i}generateStandardCF(n){let i={Type:"AWS::SecurityHub::Standard",Properties:{StandardsArn:n.arn}};if(n.disabledControls&&n.disabledControls.length>0)i.Properties.DisabledStandardsControls=n.disabledControls.map((s)=>({StandardsControlArn:s,Reason:"Disabled by configuration"}));return i}generateAutomationRuleCF(n){return{Type:"AWS::SecurityHub::AutomationRule",Properties:{RuleName:n.ruleName,Description:n.description,Actions:n.actions.map((i)=>({Type:i.type,FindingFieldsUpdate:i.findingFieldsUpdate})),Criteria:n.criteria,RuleStatus:n.ruleStatus,RuleOrder:n.ruleOrder}}}clear(){this.hubs.clear(),this.hubCounter=0,this.ruleCounter=0}}var uS=new hr;class $l{deployments=new Map;deploymentHistory=new Map;deploymentCounter=0;resultCounter=0;createDeployment(n){let i=`bg-deployment-${Date.now()}-${this.deploymentCounter++}`,s={id:i,...n};return this.deployments.set(i,s),s}createALBDeployment(n){return this.createDeployment({name:n.name,blueEnvironment:{name:"blue",targetGroupArn:n.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:n.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:n.listenerArn,switchoverTimeSeconds:0},autoPromote:n.autoPromote,healthCheckConfig:n.healthCheckConfig})}createRoute53Deployment(n){return this.createDeployment({name:n.name,blueEnvironment:{name:"blue",targetGroupArn:n.blueTargetGroupArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:n.greenTargetGroupArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"route53",hostedZoneId:n.hostedZoneId,switchoverTimeSeconds:n.switchoverTimeSeconds||60}})}createECSDeployment(n){return this.createDeployment({name:n.name,blueEnvironment:{name:"blue",targetGroupArn:n.blueTargetGroupArn,taskDefinitionArn:n.blueTaskDefinitionArn,weight:100},greenEnvironment:{name:"green",targetGroupArn:n.greenTargetGroupArn,taskDefinitionArn:n.greenTaskDefinitionArn,weight:0},activeEnvironment:"blue",routingConfig:{type:"alb",listenerArn:n.listenerArn},autoRollback:n.autoRollback??!0})}async executeDeployment(n,i=!1){let s=this.deployments.get(n);if(!s)throw Error(`Deployment not found: ${n}`);let o={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!1,errors:[]};console.log(`${i?"[DRY RUN] ":""}Starting blue/green deployment: ${s.name}`),console.log(` Active environment: ${s.activeEnvironment}`),console.log(` Routing type: ${s.routingConfig.type}`);let c=s.activeEnvironment==="blue"?"green":"blue";if(console.log(` Switching to: ${c}`),console.log(`\\n1. Deploying to ${c} environment`),!i)await new Promise((u)=>setTimeout(u,100));if(console.log(`\\n2. Running health checks on ${c} environment`),s.healthCheckConfig){let u=await this.runHealthChecks(s,c,i);if(o.healthChecksPassed=u,!u){if(o.errors?.push("Health checks failed"),o.endTime=new Date,s.autoRollback)console.log(" Auto-rollback enabled - keeping current environment active"),o.rolledBackAt=new Date;return this.recordDeployment(n,o),o}}else o.healthChecksPassed=!0;if(console.log(`\\n3. Switching traffic to ${c} environment`),!i)s.activeEnvironment=c,o.switchedAt=new Date;if(console.log(`\\n4. Monitoring ${c} environment`),!i)await new Promise((u)=>setTimeout(u,100));return o.success=!0,o.endTime=new Date,console.log("\\n✓ Deployment completed successfully"),this.recordDeployment(n,o),o}async rollback(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);let s={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,healthChecksPassed:!0,errors:[]};console.log(`Rolling back deployment: ${i.name}`);let o=i.activeEnvironment==="blue"?"green":"blue";return i.activeEnvironment=o,s.success=!0,s.rolledBackAt=new Date,s.endTime=new Date,console.log(` Switched back to: ${o}`),this.recordDeployment(n,s),s}async runHealthChecks(n,i,s){let o=n.healthCheckConfig;if(console.log(` Health check path: ${o.path||"/"}`),console.log(` Healthy threshold: ${o.healthyThreshold}`),console.log(` Interval: ${o.interval}s`),s)return console.log(" [SKIPPED - DRY RUN]"),!0;let c=0,u=o.healthyThreshold+2;for(let d=0;d<u;d++)if(await new Promise((y)=>setTimeout(y,50)),Math.random()>0.1){if(c++,console.log(` Check ${d+1}: ✓ Healthy (${c}/${o.healthyThreshold})`),c>=o.healthyThreshold)return!0}else c=0,console.log(` Check ${d+1}: ✗ Unhealthy`);return!1}recordDeployment(n,i){if(!this.deploymentHistory.has(n))this.deploymentHistory.set(n,[]);this.deploymentHistory.get(n).push(i)}getDeployment(n){return this.deployments.get(n)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(n){return this.deploymentHistory.get(n)||[]}generateALBListenerCF(n){let i=n.activeEnvironment==="blue"?n.blueEnvironment:n.greenEnvironment;return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:n.routingConfig.listenerArn,Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",TargetGroupArn:i.targetGroupArn}]}}}generateRoute53RecordSetCF(n,i){return[{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.routingConfig.hostedZoneId,Name:i,Type:"A",SetIdentifier:"blue",Weight:n.activeEnvironment==="blue"?100:0,AliasTarget:{HostedZoneId:n.routingConfig.hostedZoneId,DNSName:n.blueEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}},{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.routingConfig.hostedZoneId,Name:i,Type:"A",SetIdentifier:"green",Weight:n.activeEnvironment==="green"?100:0,AliasTarget:{HostedZoneId:n.routingConfig.hostedZoneId,DNSName:n.greenEnvironment.targetGroupArn,EvaluateTargetHealth:!0}}}]}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var gS=new $l;class as{deployments=new Map;deploymentHistory=new Map;deploymentCounter=0;resultCounter=0;static Strategies={CONSERVATIVE:[{name:"Initial Canary",trafficPercentage:10,durationMinutes:10},{name:"Quarter Traffic",trafficPercentage:25,durationMinutes:10},{name:"Half Traffic",trafficPercentage:50,durationMinutes:15},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}],BALANCED:[{name:"Initial Canary",trafficPercentage:20,durationMinutes:5},{name:"Half Traffic",trafficPercentage:50,durationMinutes:10},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}],AGGRESSIVE:[{name:"Half Traffic",trafficPercentage:50,durationMinutes:5},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}],LINEAR_10:[{name:"Canary 10%",trafficPercentage:10,durationMinutes:5},{name:"Canary 20%",trafficPercentage:20,durationMinutes:5},{name:"Canary 30%",trafficPercentage:30,durationMinutes:5},{name:"Canary 40%",trafficPercentage:40,durationMinutes:5},{name:"Canary 50%",trafficPercentage:50,durationMinutes:5},{name:"Canary 60%",trafficPercentage:60,durationMinutes:5},{name:"Canary 70%",trafficPercentage:70,durationMinutes:5},{name:"Canary 80%",trafficPercentage:80,durationMinutes:5},{name:"Canary 90%",trafficPercentage:90,durationMinutes:5},{name:"Full Traffic",trafficPercentage:100,durationMinutes:5}]};createDeployment(n){let i=`canary-${Date.now()}-${this.deploymentCounter++}`,s={id:i,...n};return this.deployments.set(i,s),s}createLambdaCanaryDeployment(n){let i=n.strategy||"BALANCED",s=as.Strategies[i].map((o)=>({...o,alarmThresholds:{errorRate:n.errorRateThreshold||1,latencyP99:n.latencyThreshold||1000}}));return this.createDeployment({name:n.name,baselineVersion:{version:"baseline",functionVersionArn:n.baselineVersionArn,weight:100},canaryVersion:{version:"canary",functionVersionArn:n.canaryVersionArn,weight:0},stages:s,currentStage:0,status:"pending",autoPromote:n.autoPromote??!0,autoRollback:!0})}createECSCanaryDeployment(n){let i=n.strategy||"CONSERVATIVE",s=as.Strategies[i];return this.createDeployment({name:n.name,baselineVersion:{version:"baseline",taskDefinitionArn:n.baselineTaskDefinitionArn,targetGroupArn:n.baselineTargetGroupArn,weight:100},canaryVersion:{version:"canary",taskDefinitionArn:n.canaryTaskDefinitionArn,targetGroupArn:n.canaryTargetGroupArn,weight:0},stages:s,currentStage:0,status:"pending",autoRollback:!0})}async executeDeployment(n,i=!1){let s=this.deployments.get(n);if(!s)throw Error(`Deployment not found: ${n}`);let o={success:!1,deploymentId:`result-${Date.now()}-${this.resultCounter++}`,startTime:new Date,completedStages:0,rolledBack:!1};console.log(`${i?"[DRY RUN] ":""}Starting canary deployment: ${s.name}`),console.log(` Strategy: ${s.stages.length} stages`),console.log(` Auto-promote: ${s.autoPromote}`),console.log(` Auto-rollback: ${s.autoRollback}`),console.log(""),s.status="in_progress";for(let c=0;c<s.stages.length;c++){let u=s.stages[c];if(s.currentStage=c,console.log(`Stage ${c+1}/${s.stages.length}: ${u.name}`),console.log(` Traffic: ${u.trafficPercentage}% canary, ${100-u.trafficPercentage}% baseline`),console.log(` Duration: ${u.durationMinutes} minutes`),!i)s.baselineVersion.weight=100-u.trafficPercentage,s.canaryVersion.weight=u.trafficPercentage;if(!await this.monitorStage(s,u,i)){if(console.log(" ✗ Stage failed - metrics exceeded thresholds"),s.autoRollback)console.log("\\n Rolling back deployment..."),await this.rollback(n,i),o.rolledBack=!0,o.reason="Metrics exceeded thresholds";return o.endTime=new Date,s.status="rolled_back",this.recordDeployment(n,o),o}console.log(" ✓ Stage completed successfully"),o.completedStages++,console.log("")}return s.status="completed",o.success=!0,o.endTime=new Date,console.log("✓ Canary deployment completed successfully"),this.recordDeployment(n,o),o}async monitorStage(n,i,s){if(console.log(" Monitoring metrics..."),s)return console.log(" [SKIPPED - DRY RUN]"),!0;await new Promise((c)=>setTimeout(c,100));let o={baselineErrorRate:Math.random()*0.5,canaryErrorRate:Math.random()*0.8,baselineLatencyP99:200+Math.random()*100,canaryLatencyP99:180+Math.random()*150,baselineRequestCount:Math.floor(Math.random()*1000)+500,canaryRequestCount:Math.floor((Math.random()*1000+500)*i.trafficPercentage/100)};if(n.metrics=o,console.log(` Baseline: ${o.baselineErrorRate.toFixed(2)}% errors, ${o.baselineLatencyP99.toFixed(0)}ms P99`),console.log(` Canary: ${o.canaryErrorRate.toFixed(2)}% errors, ${o.canaryLatencyP99.toFixed(0)}ms P99`),i.alarmThresholds){let{errorRate:c,latencyP99:u}=i.alarmThresholds;if(c&&o.canaryErrorRate>c)return console.log(` ⚠ Error rate exceeded threshold: ${o.canaryErrorRate.toFixed(2)}% > ${c}%`),!1;if(u&&o.canaryLatencyP99>u)return console.log(` ⚠ Latency P99 exceeded threshold: ${o.canaryLatencyP99.toFixed(0)}ms > ${u}ms`),!1}return!0}async rollback(n,i=!1){let s=this.deployments.get(n);if(!s)throw Error(`Deployment not found: ${n}`);if(console.log(`${i?"[DRY RUN] ":""}Rolling back canary deployment: ${s.name}`),!i)s.baselineVersion.weight=100,s.canaryVersion.weight=0,s.status="rolled_back";console.log(" Traffic restored to baseline: 100%")}promoteCanary(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);console.log(`Promoting canary to baseline: ${i.name}`);let s=i.baselineVersion;i.baselineVersion=i.canaryVersion,i.canaryVersion=s,i.baselineVersion.weight=100,i.canaryVersion.weight=0,i.status="completed",console.log(" Canary promoted successfully")}recordDeployment(n,i){if(!this.deploymentHistory.has(n))this.deploymentHistory.set(n,[]);this.deploymentHistory.get(n).push(i)}getDeployment(n){return this.deployments.get(n)}listDeployments(){return Array.from(this.deployments.values())}getDeploymentHistory(n){return this.deploymentHistory.get(n)||[]}generateLambdaAliasCF(n,i){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:{Ref:"LambdaFunction"},Name:i,FunctionVersion:n.canaryVersion.version,RoutingConfig:{AdditionalVersionWeights:[{FunctionVersion:n.baselineVersion.version,FunctionWeight:n.baselineVersion.weight/100}]}}}}generateALBListenerRuleCF(n){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:[{TargetGroupArn:n.baselineVersion.targetGroupArn,Weight:n.baselineVersion.weight},{TargetGroupArn:n.canaryVersion.targetGroupArn,Weight:n.canaryVersion.weight}],TargetGroupStickinessConfig:{Enabled:!1}}}]}}}clear(){this.deployments.clear(),this.deploymentHistory.clear(),this.deploymentCounter=0,this.resultCounter=0}}var pS=new as;class Ml{tests=new Map;testCounter=0;createTest(n){let i=`abtest-${Date.now()}-${this.testCounter++}`,s={id:i,...n};return this.tests.set(i,s),s}createSimpleABTest(n){let i=n.variantTrafficPercentage||50;return this.createTest({name:n.name,description:n.description,variants:[{id:"control",name:"Control",description:"Original version",trafficPercentage:100-i,targetGroupArn:n.controlTargetGroupArn,weight:100-i},{id:"variant-a",name:"Variant A",description:"Test version",trafficPercentage:i,targetGroupArn:n.variantTargetGroupArn,weight:i}],routingStrategy:{type:n.stickySession?"cookie":"random",cookieName:n.stickySession?"ab_variant":void 0,stickySession:n.stickySession??!1,sessionDuration:1440},startTime:new Date,status:"draft"})}createMultivariateTest(n){let i=n.variants.reduce((s,o)=>s+o.trafficPercentage,0);if(i!==100)throw Error(`Traffic percentages must sum to 100, got ${i}`);return this.createTest({name:n.name,description:n.description,variants:n.variants.map((s,o)=>({id:`variant-${o}`,name:s.name,description:s.description,trafficPercentage:s.trafficPercentage,targetGroupArn:s.targetGroupArn,weight:s.trafficPercentage})),routingStrategy:n.routingStrategy||{type:"random",stickySession:!1},startTime:new Date,status:"draft"})}createHeaderBasedTest(n){return this.createTest({name:n.name,description:`Route based on ${n.headerName} header`,variants:[{id:"control",name:"Control",trafficPercentage:50,targetGroupArn:n.controlTargetGroupArn,weight:50},{id:"variant-a",name:"Variant A",trafficPercentage:50,targetGroupArn:n.variantTargetGroupArn,weight:50}],routingStrategy:{type:"header",headerName:n.headerName,stickySession:!1},startTime:new Date,status:"draft"})}createGeoBasedTest(n){return this.createTest({name:n.name,description:"Route based on geographic location",variants:[{id:"control",name:"Control (Rest of World)",trafficPercentage:50,targetGroupArn:n.controlTargetGroupArn,weight:50},{id:"variant-a",name:`Variant A (${n.regions.join(", ")})`,trafficPercentage:50,targetGroupArn:n.variantTargetGroupArn,weight:50}],routingStrategy:{type:"geo",stickySession:!0,sessionDuration:1440},startTime:new Date,status:"draft"})}startTest(n){let i=this.tests.get(n);if(!i)throw Error(`Test not found: ${n}`);if(i.status!=="draft"&&i.status!=="paused")throw Error(`Cannot start test in ${i.status} status`);i.status="active",i.startTime=new Date,console.log(`Started A/B test: ${i.name}`),console.log(` Variants: ${i.variants.length}`),i.variants.forEach((s)=>{console.log(` - ${s.name}: ${s.trafficPercentage}%`)})}pauseTest(n){let i=this.tests.get(n);if(!i)throw Error(`Test not found: ${n}`);i.status="paused",console.log(`Paused A/B test: ${i.name}`)}updateTrafficSplit(n,i,s){let o=this.tests.get(n);if(!o)throw Error(`Test not found: ${n}`);let c=o.variants.find((d)=>d.id===i);if(!c)throw Error(`Variant not found: ${i}`);let u=c.trafficPercentage;c.trafficPercentage=s,c.weight=s,console.log(`Updated ${c.name} traffic: ${u}% → ${s}%`)}analyzeResults(n){let i=this.tests.get(n);if(!i)throw Error(`Test not found: ${n}`);if(!i.metrics)i.metrics=this.collectMetrics(i);let s=i.variants[0],o=0;for(let h of i.variants){let A=i.metrics.variants[h.id];if(A&&A.conversionRate>o)o=A.conversionRate,s=h}let c=i.metrics.variants.control||i.metrics.variants[i.variants[0].id],u=i.metrics.variants[s.id],d=(u.conversionRate-c.conversionRate)/c.conversionRate*100,g=100,y=u.requests>g&&c.requests>g&&Math.abs(d)>10;return{testId:n,winningVariant:s.name,confidence:y?95:75,improvement:d,statisticalSignificance:y,metrics:i.metrics,recommendation:this.generateRecommendation(d,y,s.name)}}declareWinner(n,i){let s=this.tests.get(n);if(!s)throw Error(`Test not found: ${n}`);let o=s.variants.find((c)=>c.id===i);if(!o)throw Error(`Variant not found: ${i}`);s.variants.forEach((c)=>{if(c.id===i)c.trafficPercentage=100,c.weight=100;else c.trafficPercentage=0,c.weight=0}),s.status="completed",s.endTime=new Date,s.winner=i,console.log(`Declared winner: ${o.name}`),console.log(` All traffic now routed to ${o.name}`)}collectMetrics(n){let i={},s=0;for(let o of n.variants){let c=Math.floor(Math.random()*1000)+500,u=Math.floor(c*(Math.random()*0.1+0.05)),d=u/c*100;i[o.id]={requests:c,conversions:u,conversionRate:d,averageLatency:150+Math.random()*100,errorRate:Math.random()*0.5,revenue:u*(Math.random()*50+100)},s+=c}return{variants:i,totalRequests:s,startTime:n.startTime,lastUpdated:new Date}}generateRecommendation(n,i,s){if(!i)return"Continue test - sample size too small or no significant difference detected";if(n>20)return`Strong winner detected - ${s} shows ${n.toFixed(1)}% improvement. Recommend deploying to all traffic.`;if(n>10)return`Moderate improvement - ${s} shows ${n.toFixed(1)}% improvement. Consider deploying.`;if(n>0)return`Minor improvement - ${s} shows ${n.toFixed(1)}% improvement. May not be worth the complexity.`;return"No improvement detected - consider reverting to control variant"}getTest(n){return this.tests.get(n)}listTests(){return Array.from(this.tests.values())}generateALBListenerRuleCF(n){return{Type:"AWS::ElasticLoadBalancingV2::ListenerRule",Properties:{ListenerArn:{Ref:"LoadBalancerListener"},Priority:1,Conditions:[{Field:"path-pattern",Values:["/*"]}],Actions:[{Type:"forward",ForwardConfig:{TargetGroups:n.variants.map((i)=>({TargetGroupArn:i.targetGroupArn,Weight:i.weight})),TargetGroupStickinessConfig:{Enabled:n.routingStrategy.stickySession||!1,DurationSeconds:n.routingStrategy.sessionDuration?n.routingStrategy.sessionDuration*60:void 0}}}]}}}generateLambdaEdgeFunction(n){return`'use strict';
3566
3564
 
3567
3565
  exports.handler = (event, _context, _callback) => {
3568
3566
  const request = event.Records[0].cf.request;
@@ -3609,7 +3607,7 @@ exports.handler = (event, _context, _callback) => {
3609
3607
  }`).join(" else ")}
3610
3608
 
3611
3609
  callback(null, request);
3612
- };`}clear(){this.tests.clear(),this.testCounter=0}}var rS=new Pl;class kl{rollouts=new Map;flags=new Map;gates=new Map;counter=0;createProgressiveRollout(n,i){let s=`rollout-${Date.now()}-${this.counter++}`,o={id:s,name:n,stages:i,currentStage:0};return this.rollouts.set(s,o),o}createFeatureFlag(n,i=0){let s=`flag-${Date.now()}-${this.counter++}`,o={id:s,name:n,enabled:!1,rolloutPercentage:i,targetingRules:[]};return this.flags.set(s,o),o}createDeploymentGate(n,i,s,o){let c=`gate-${Date.now()}-${this.counter++}`,u={id:c,name:n,type:i,approvers:s,conditions:o};return this.gates.set(c,u),u}clear(){this.rollouts.clear(),this.flags.clear(),this.gates.clear()}}var nS=new kl;class ef{configs=new Map;samplingRules=new Map;configCounter=0;ruleCounter=0;createConfig(n){let i=`xray-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}createLambdaConfig(n){return this.createConfig({name:`${n.functionName}-xray`,serviceName:n.functionName,samplingRate:n.samplingRate||0.1,enableActiveTracing:!0})}createECSConfig(n){return this.createConfig({name:`${n.serviceName}-xray`,serviceName:`${n.clusterName}/${n.serviceName}`,samplingRate:n.samplingRate||0.05,enableActiveTracing:!0})}createAPIGatewayConfig(n){return this.createConfig({name:`${n.apiName}-${n.stage}-xray`,serviceName:`${n.apiName}/${n.stage}`,samplingRate:n.samplingRate||0.05,enableActiveTracing:!0})}createSamplingRule(n){let i=`sampling-rule-${Date.now()}-${this.ruleCounter++}`,s={id:i,...n};return this.samplingRules.set(i,s),s}createHighPrioritySamplingRule(n){return this.createSamplingRule({ruleName:n.ruleName,priority:100,fixedRate:1,reservoirSize:100,serviceName:n.serviceName,serviceType:"*",host:"*",httpMethod:"*",urlPath:n.urlPath,version:1})}createErrorSamplingRule(n){return this.createSamplingRule({ruleName:`${n}-errors`,priority:200,fixedRate:1,reservoirSize:50,serviceName:n,serviceType:"*",host:"*",httpMethod:"*",urlPath:"/error/*",version:1})}createDefaultSamplingRule(n,i=0.05){return this.createSamplingRule({ruleName:`${n}-default`,priority:1000,fixedRate:i,reservoirSize:10,serviceName:n,serviceType:"*",host:"*",httpMethod:"*",urlPath:"*",version:1})}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getSamplingRule(n){return this.samplingRules.get(n)}listSamplingRules(){return Array.from(this.samplingRules.values())}generateLambdaXRayCF(n){return{TracingConfig:{Mode:n.enableActiveTracing?"Active":"PassThrough"}}}generateAPIGatewayXRayCF(n){return{TracingEnabled:n.enableActiveTracing}}generateECSXRaySidecarCF(){return{Name:"xray-daemon",Image:"public.ecr.aws/xray/aws-xray-daemon:latest",Cpu:32,MemoryReservation:256,PortMappings:[{ContainerPort:2000,Protocol:"udp"}]}}generateSamplingRuleCF(n){return{Type:"AWS::XRay::SamplingRule",Properties:{SamplingRule:{RuleName:n.ruleName,Priority:n.priority,FixedRate:n.fixedRate,ReservoirSize:n.reservoirSize,ServiceName:n.serviceName,ServiceType:n.serviceType,Host:n.host,HTTPMethod:n.httpMethod,URLPath:n.urlPath,Version:n.version,ResourceARN:"*"}}}}createTrace(n,i){return{id:`trace-${Date.now()}-${this.configCounter++}`,traceId:n,spans:i}}clear(){this.configs.clear(),this.samplingRules.clear(),this.configCounter=0,this.ruleCounter=0}}var nE=new ef;class tf{namespaces=new Map;metrics=new Map;namespaceCounter=0;metricCounter=0;alarmCounter=0;createNamespace(n){let i=`namespace-${Date.now()}-${this.namespaceCounter++}`,s={id:i,...n};return this.namespaces.set(i,s),s}createMetric(n){let i=`metric-${Date.now()}-${this.metricCounter++}`,s={id:i,...n};return this.metrics.set(i,s),s}createBusinessMetric(n){return this.createMetric({name:n.name,namespace:n.namespace,unit:n.unit,dimensions:[{name:"Environment",value:"production"},{name:"Type",value:"Business"}]})}createApplicationMetric(n){return this.createMetric({name:n.name,namespace:n.namespace,unit:n.unit,dimensions:[{name:"Service",value:n.serviceName},{name:"Type",value:"Application"}]})}createPerformanceMetric(n){return this.createMetric({name:n.name,namespace:n.namespace,unit:"Milliseconds",dimensions:[{name:"Operation",value:n.operation},{name:"Type",value:"Performance"}]})}createErrorMetric(n){return this.createMetric({name:n.name,namespace:n.namespace,unit:"Count",dimensions:[{name:"ErrorType",value:n.errorType},{name:"Type",value:"Error"}]})}createAlarm(n,i){let s=this.metrics.get(n);if(!s)throw Error(`Metric not found: ${n}`);let c={id:`alarm-${Date.now()}-${this.alarmCounter++}`,...i};if(!s.alarms)s.alarms=[];return s.alarms.push(c),c}createErrorRateAlarm(n){return this.createAlarm(n.metricId,{name:n.name,description:`Alert when error rate exceeds ${n.threshold} errors/min`,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:2,threshold:n.threshold,period:60,statistic:"Sum",treatMissingData:"notBreaching",actionsEnabled:!0,alarmActions:n.snsTopicArn?[n.snsTopicArn]:void 0})}createLatencyAlarm(n){return this.createAlarm(n.metricId,{name:n.name,description:`Alert when latency exceeds ${n.thresholdMs}ms`,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,threshold:n.thresholdMs,period:300,statistic:"Average",treatMissingData:"notBreaching",actionsEnabled:!0,alarmActions:n.snsTopicArn?[n.snsTopicArn]:void 0})}createThroughputAlarm(n){return this.createAlarm(n.metricId,{name:n.name,description:`Alert when throughput drops below ${n.minimumThreshold}`,comparisonOperator:"LessThanThreshold",evaluationPeriods:2,threshold:n.minimumThreshold,period:300,statistic:"Sum",treatMissingData:"breaching",actionsEnabled:!0,alarmActions:n.snsTopicArn?[n.snsTopicArn]:void 0})}createCompositeAlarm(n){return{name:n.name,description:n.description,alarmRule:n.alarmRule,actionsEnabled:n.actionsEnabled??!0,alarmActions:n.alarmActions}}getNamespace(n){return this.namespaces.get(n)}listNamespaces(){return Array.from(this.namespaces.values())}getMetric(n){return this.metrics.get(n)}listMetrics(){return Array.from(this.metrics.values())}generateAlarmCF(n,i){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:i.name,AlarmDescription:i.description,ComparisonOperator:i.comparisonOperator,EvaluationPeriods:i.evaluationPeriods,MetricName:n.name,Namespace:n.namespace,Period:i.period,Statistic:i.statistic,Threshold:i.threshold,TreatMissingData:i.treatMissingData||"notBreaching",ActionsEnabled:i.actionsEnabled??!0,...i.alarmActions&&{AlarmActions:i.alarmActions},...i.okActions&&{OKActions:i.okActions},...i.insufficientDataActions&&{InsufficientDataActions:i.insufficientDataActions},...n.dimensions&&{Dimensions:n.dimensions.map((s)=>({Name:s.name,Value:s.value}))}}}}generateCompositeAlarmCF(n){return{Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:n.name,AlarmDescription:n.description,AlarmRule:n.alarmRule,ActionsEnabled:n.actionsEnabled,...n.alarmActions&&{AlarmActions:n.alarmActions}}}}generateDashboardWidget(n){return{type:"metric",properties:{metrics:[[n.namespace,n.name,...n.dimensions?.flatMap((i)=>[i.name,i.value])||[]]],period:300,stat:"Average",region:"us-east-1",title:n.name}}}publishCustomMetric(n,i,s,o={},c="Count"){return{id:`metric-${Date.now()}-${this.metricCounter++}`,namespace:n,name:i,dimensions:o,value:s,unit:c,timestamp:new Date}}clear(){this.namespaces.clear(),this.metrics.clear(),this.namespaceCounter=0,this.metricCounter=0,this.alarmCounter=0}}var iE=new tf;class Nl{logGroups=new Map;queries=new Map;insightsQueries=new Map;logGroupCounter=0;filterCounter=0;queryCounter=0;createLogGroup(n){let i=`log-group-${Date.now()}-${this.logGroupCounter++}`,s={id:i,...n};return this.logGroups.set(i,s),s}createLambdaLogGroup(n,i=7){return this.createLogGroup({name:`/aws/lambda/${n}`,retentionDays:i})}createECSLogGroup(n){return this.createLogGroup({name:`/ecs/${n.clusterName}/${n.serviceName}`,retentionDays:n.retentionDays||14})}createAPIGatewayLogGroup(n,i,s=30){return this.createLogGroup({name:`/aws/apigateway/${n}/${i}`,retentionDays:s})}createApplicationLogGroup(n){return this.createLogGroup({name:`/application/${n.appName}/${n.environment}`,retentionDays:n.retentionDays||30,kmsKeyId:n.kmsKeyId})}createMetricFilter(n,i){let s=this.logGroups.get(n);if(!s)throw Error(`Log group not found: ${n}`);let c={id:`filter-${Date.now()}-${this.filterCounter++}`,...i};if(!s.metricFilters)s.metricFilters=[];return s.metricFilters.push(c),c}createErrorCountFilter(n,i){return this.createMetricFilter(n,{name:"ErrorCount",filterPattern:"[timestamp, request_id, level = ERROR*, ...]",metricTransformations:[{metricName:"ErrorCount",metricNamespace:i,metricValue:"1",defaultValue:0,unit:"Count"}]})}createLatencyFilter(n,i){return this.createMetricFilter(n,{name:"Latency",filterPattern:"[timestamp, request_id, level, duration, ...]",metricTransformations:[{metricName:"ResponseTime",metricNamespace:i,metricValue:"$duration",unit:"Milliseconds"}]})}createCustomPatternFilter(n){return this.createMetricFilter(n.logGroupId,{name:n.name,filterPattern:n.pattern,metricTransformations:[{metricName:n.metricName,metricNamespace:n.namespace,metricValue:"1",defaultValue:0,unit:"Count"}]})}createSubscriptionFilter(n,i){let s=this.logGroups.get(n);if(!s)throw Error(`Log group not found: ${n}`);let c={id:`subscription-${Date.now()}-${this.filterCounter++}`,...i};if(!s.subscriptionFilters)s.subscriptionFilters=[];return s.subscriptionFilters.push(c),c}createKinesisSubscription(n){let i=this.logGroups.get(n.logGroupId);if(!i)throw Error(`Log group not found: ${n.logGroupId}`);return this.createSubscriptionFilter(n.logGroupId,{name:"KinesisSubscription",logGroupName:i.name,filterPattern:n.filterPattern||"",destinationArn:n.kinesisStreamArn,roleArn:n.roleArn,distribution:"Random"})}createLambdaSubscription(n){let i=this.logGroups.get(n.logGroupId);if(!i)throw Error(`Log group not found: ${n.logGroupId}`);return this.createSubscriptionFilter(n.logGroupId,{name:"LambdaSubscription",logGroupName:i.name,filterPattern:n.filterPattern||"",destinationArn:n.lambdaFunctionArn,distribution:"ByLogStream"})}createInsightsQuery(n){let i=`query-${Date.now()}-${this.queryCounter++}`,s={id:i,...n};return this.insightsQueries.set(i,s),s}createErrorAnalysisQuery(n){return this.createInsightsQuery({name:"Error Analysis",description:"Analyze error patterns and frequencies",query:`fields @timestamp, @message
3610
+ };`}clear(){this.tests.clear(),this.testCounter=0}}var mS=new Ml;class Fl{rollouts=new Map;flags=new Map;gates=new Map;counter=0;createProgressiveRollout(n,i){let s=`rollout-${Date.now()}-${this.counter++}`,o={id:s,name:n,stages:i,currentStage:0};return this.rollouts.set(s,o),o}createFeatureFlag(n,i=0){let s=`flag-${Date.now()}-${this.counter++}`,o={id:s,name:n,enabled:!1,rolloutPercentage:i,targetingRules:[]};return this.flags.set(s,o),o}createDeploymentGate(n,i,s,o){let c=`gate-${Date.now()}-${this.counter++}`,u={id:c,name:n,type:i,approvers:s,conditions:o};return this.gates.set(c,u),u}clear(){this.rollouts.clear(),this.flags.clear(),this.gates.clear()}}var fS=new Fl;class uf{configs=new Map;samplingRules=new Map;configCounter=0;ruleCounter=0;createConfig(n){let i=`xray-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}createLambdaConfig(n){return this.createConfig({name:`${n.functionName}-xray`,serviceName:n.functionName,samplingRate:n.samplingRate||0.1,enableActiveTracing:!0})}createECSConfig(n){return this.createConfig({name:`${n.serviceName}-xray`,serviceName:`${n.clusterName}/${n.serviceName}`,samplingRate:n.samplingRate||0.05,enableActiveTracing:!0})}createAPIGatewayConfig(n){return this.createConfig({name:`${n.apiName}-${n.stage}-xray`,serviceName:`${n.apiName}/${n.stage}`,samplingRate:n.samplingRate||0.05,enableActiveTracing:!0})}createSamplingRule(n){let i=`sampling-rule-${Date.now()}-${this.ruleCounter++}`,s={id:i,...n};return this.samplingRules.set(i,s),s}createHighPrioritySamplingRule(n){return this.createSamplingRule({ruleName:n.ruleName,priority:100,fixedRate:1,reservoirSize:100,serviceName:n.serviceName,serviceType:"*",host:"*",httpMethod:"*",urlPath:n.urlPath,version:1})}createErrorSamplingRule(n){return this.createSamplingRule({ruleName:`${n}-errors`,priority:200,fixedRate:1,reservoirSize:50,serviceName:n,serviceType:"*",host:"*",httpMethod:"*",urlPath:"/error/*",version:1})}createDefaultSamplingRule(n,i=0.05){return this.createSamplingRule({ruleName:`${n}-default`,priority:1000,fixedRate:i,reservoirSize:10,serviceName:n,serviceType:"*",host:"*",httpMethod:"*",urlPath:"*",version:1})}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getSamplingRule(n){return this.samplingRules.get(n)}listSamplingRules(){return Array.from(this.samplingRules.values())}generateLambdaXRayCF(n){return{TracingConfig:{Mode:n.enableActiveTracing?"Active":"PassThrough"}}}generateAPIGatewayXRayCF(n){return{TracingEnabled:n.enableActiveTracing}}generateECSXRaySidecarCF(){return{Name:"xray-daemon",Image:"public.ecr.aws/xray/aws-xray-daemon:latest",Cpu:32,MemoryReservation:256,PortMappings:[{ContainerPort:2000,Protocol:"udp"}]}}generateSamplingRuleCF(n){return{Type:"AWS::XRay::SamplingRule",Properties:{SamplingRule:{RuleName:n.ruleName,Priority:n.priority,FixedRate:n.fixedRate,ReservoirSize:n.reservoirSize,ServiceName:n.serviceName,ServiceType:n.serviceType,Host:n.host,HTTPMethod:n.httpMethod,URLPath:n.urlPath,Version:n.version,ResourceARN:"*"}}}}createTrace(n,i){return{id:`trace-${Date.now()}-${this.configCounter++}`,traceId:n,spans:i}}clear(){this.configs.clear(),this.samplingRules.clear(),this.configCounter=0,this.ruleCounter=0}}var hE=new uf;class gf{namespaces=new Map;metrics=new Map;namespaceCounter=0;metricCounter=0;alarmCounter=0;createNamespace(n){let i=`namespace-${Date.now()}-${this.namespaceCounter++}`,s={id:i,...n};return this.namespaces.set(i,s),s}createMetric(n){let i=`metric-${Date.now()}-${this.metricCounter++}`,s={id:i,...n};return this.metrics.set(i,s),s}createBusinessMetric(n){return this.createMetric({name:n.name,namespace:n.namespace,unit:n.unit,dimensions:[{name:"Environment",value:"production"},{name:"Type",value:"Business"}]})}createApplicationMetric(n){return this.createMetric({name:n.name,namespace:n.namespace,unit:n.unit,dimensions:[{name:"Service",value:n.serviceName},{name:"Type",value:"Application"}]})}createPerformanceMetric(n){return this.createMetric({name:n.name,namespace:n.namespace,unit:"Milliseconds",dimensions:[{name:"Operation",value:n.operation},{name:"Type",value:"Performance"}]})}createErrorMetric(n){return this.createMetric({name:n.name,namespace:n.namespace,unit:"Count",dimensions:[{name:"ErrorType",value:n.errorType},{name:"Type",value:"Error"}]})}createAlarm(n,i){let s=this.metrics.get(n);if(!s)throw Error(`Metric not found: ${n}`);let c={id:`alarm-${Date.now()}-${this.alarmCounter++}`,...i};if(!s.alarms)s.alarms=[];return s.alarms.push(c),c}createErrorRateAlarm(n){return this.createAlarm(n.metricId,{name:n.name,description:`Alert when error rate exceeds ${n.threshold} errors/min`,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:2,threshold:n.threshold,period:60,statistic:"Sum",treatMissingData:"notBreaching",actionsEnabled:!0,alarmActions:n.snsTopicArn?[n.snsTopicArn]:void 0})}createLatencyAlarm(n){return this.createAlarm(n.metricId,{name:n.name,description:`Alert when latency exceeds ${n.thresholdMs}ms`,comparisonOperator:"GreaterThanThreshold",evaluationPeriods:3,threshold:n.thresholdMs,period:300,statistic:"Average",treatMissingData:"notBreaching",actionsEnabled:!0,alarmActions:n.snsTopicArn?[n.snsTopicArn]:void 0})}createThroughputAlarm(n){return this.createAlarm(n.metricId,{name:n.name,description:`Alert when throughput drops below ${n.minimumThreshold}`,comparisonOperator:"LessThanThreshold",evaluationPeriods:2,threshold:n.minimumThreshold,period:300,statistic:"Sum",treatMissingData:"breaching",actionsEnabled:!0,alarmActions:n.snsTopicArn?[n.snsTopicArn]:void 0})}createCompositeAlarm(n){return{name:n.name,description:n.description,alarmRule:n.alarmRule,actionsEnabled:n.actionsEnabled??!0,alarmActions:n.alarmActions}}getNamespace(n){return this.namespaces.get(n)}listNamespaces(){return Array.from(this.namespaces.values())}getMetric(n){return this.metrics.get(n)}listMetrics(){return Array.from(this.metrics.values())}generateAlarmCF(n,i){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:i.name,AlarmDescription:i.description,ComparisonOperator:i.comparisonOperator,EvaluationPeriods:i.evaluationPeriods,MetricName:n.name,Namespace:n.namespace,Period:i.period,Statistic:i.statistic,Threshold:i.threshold,TreatMissingData:i.treatMissingData||"notBreaching",ActionsEnabled:i.actionsEnabled??!0,...i.alarmActions&&{AlarmActions:i.alarmActions},...i.okActions&&{OKActions:i.okActions},...i.insufficientDataActions&&{InsufficientDataActions:i.insufficientDataActions},...n.dimensions&&{Dimensions:n.dimensions.map((s)=>({Name:s.name,Value:s.value}))}}}}generateCompositeAlarmCF(n){return{Type:"AWS::CloudWatch::CompositeAlarm",Properties:{AlarmName:n.name,AlarmDescription:n.description,AlarmRule:n.alarmRule,ActionsEnabled:n.actionsEnabled,...n.alarmActions&&{AlarmActions:n.alarmActions}}}}generateDashboardWidget(n){return{type:"metric",properties:{metrics:[[n.namespace,n.name,...n.dimensions?.flatMap((i)=>[i.name,i.value])||[]]],period:300,stat:"Average",region:"us-east-1",title:n.name}}}publishCustomMetric(n,i,s,o={},c="Count"){return{id:`metric-${Date.now()}-${this.metricCounter++}`,namespace:n,name:i,dimensions:o,value:s,unit:c,timestamp:new Date}}clear(){this.namespaces.clear(),this.metrics.clear(),this.namespaceCounter=0,this.metricCounter=0,this.alarmCounter=0}}var AE=new gf;class Ul{logGroups=new Map;queries=new Map;insightsQueries=new Map;logGroupCounter=0;filterCounter=0;queryCounter=0;createLogGroup(n){let i=`log-group-${Date.now()}-${this.logGroupCounter++}`,s={id:i,...n};return this.logGroups.set(i,s),s}createLambdaLogGroup(n,i=7){return this.createLogGroup({name:`/aws/lambda/${n}`,retentionDays:i})}createECSLogGroup(n){return this.createLogGroup({name:`/ecs/${n.clusterName}/${n.serviceName}`,retentionDays:n.retentionDays||14})}createAPIGatewayLogGroup(n,i,s=30){return this.createLogGroup({name:`/aws/apigateway/${n}/${i}`,retentionDays:s})}createApplicationLogGroup(n){return this.createLogGroup({name:`/application/${n.appName}/${n.environment}`,retentionDays:n.retentionDays||30,kmsKeyId:n.kmsKeyId})}createMetricFilter(n,i){let s=this.logGroups.get(n);if(!s)throw Error(`Log group not found: ${n}`);let c={id:`filter-${Date.now()}-${this.filterCounter++}`,...i};if(!s.metricFilters)s.metricFilters=[];return s.metricFilters.push(c),c}createErrorCountFilter(n,i){return this.createMetricFilter(n,{name:"ErrorCount",filterPattern:"[timestamp, request_id, level = ERROR*, ...]",metricTransformations:[{metricName:"ErrorCount",metricNamespace:i,metricValue:"1",defaultValue:0,unit:"Count"}]})}createLatencyFilter(n,i){return this.createMetricFilter(n,{name:"Latency",filterPattern:"[timestamp, request_id, level, duration, ...]",metricTransformations:[{metricName:"ResponseTime",metricNamespace:i,metricValue:"$duration",unit:"Milliseconds"}]})}createCustomPatternFilter(n){return this.createMetricFilter(n.logGroupId,{name:n.name,filterPattern:n.pattern,metricTransformations:[{metricName:n.metricName,metricNamespace:n.namespace,metricValue:"1",defaultValue:0,unit:"Count"}]})}createSubscriptionFilter(n,i){let s=this.logGroups.get(n);if(!s)throw Error(`Log group not found: ${n}`);let c={id:`subscription-${Date.now()}-${this.filterCounter++}`,...i};if(!s.subscriptionFilters)s.subscriptionFilters=[];return s.subscriptionFilters.push(c),c}createKinesisSubscription(n){let i=this.logGroups.get(n.logGroupId);if(!i)throw Error(`Log group not found: ${n.logGroupId}`);return this.createSubscriptionFilter(n.logGroupId,{name:"KinesisSubscription",logGroupName:i.name,filterPattern:n.filterPattern||"",destinationArn:n.kinesisStreamArn,roleArn:n.roleArn,distribution:"Random"})}createLambdaSubscription(n){let i=this.logGroups.get(n.logGroupId);if(!i)throw Error(`Log group not found: ${n.logGroupId}`);return this.createSubscriptionFilter(n.logGroupId,{name:"LambdaSubscription",logGroupName:i.name,filterPattern:n.filterPattern||"",destinationArn:n.lambdaFunctionArn,distribution:"ByLogStream"})}createInsightsQuery(n){let i=`query-${Date.now()}-${this.queryCounter++}`,s={id:i,...n};return this.insightsQueries.set(i,s),s}createErrorAnalysisQuery(n){return this.createInsightsQuery({name:"Error Analysis",description:"Analyze error patterns and frequencies",query:`fields @timestamp, @message
3613
3611
  | filter @message like /ERROR/
3614
3612
  | stats count() by bin(5m)
3615
3613
  | sort @timestamp desc`,logGroupNames:n})}createLatencyAnalysisQuery(n){return this.createInsightsQuery({name:"Latency Analysis",description:"Analyze request latency patterns",query:`fields @timestamp, @duration
@@ -3619,7 +3617,7 @@ exports.handler = (event, _context, _callback) => {
3619
3617
  | filter @message like /ERROR/
3620
3618
  | stats count() as error_count by @message
3621
3619
  | sort error_count desc
3622
- | limit 20`,logGroupNames:n})}getLogGroup(n){return this.logGroups.get(n)}listLogGroups(){return Array.from(this.logGroups.values())}getInsightsQuery(n){return this.insightsQueries.get(n)}listInsightsQueries(){return Array.from(this.insightsQueries.values())}generateLogGroupCF(n){return{Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:n.name,...n.retentionDays&&{RetentionInDays:n.retentionDays},...n.kmsKeyId&&{KmsKeyId:n.kmsKeyId}}}}generateMetricFilterCF(n,i){return{Type:"AWS::Logs::MetricFilter",Properties:{FilterName:i.name,FilterPattern:i.filterPattern,LogGroupName:n.name,MetricTransformations:i.metricTransformations.map((s)=>({MetricName:s.metricName,MetricNamespace:s.metricNamespace,MetricValue:s.metricValue,...s.defaultValue!==void 0&&{DefaultValue:s.defaultValue},...s.unit&&{Unit:s.unit},...s.dimensions&&{Dimensions:s.dimensions}}))}}}generateSubscriptionFilterCF(n){return{Type:"AWS::Logs::SubscriptionFilter",Properties:{FilterName:n.name,FilterPattern:n.filterPattern,LogGroupName:n.logGroupName,DestinationArn:n.destinationArn,...n.roleArn&&{RoleArn:n.roleArn},...n.distribution&&{Distribution:n.distribution}}}}generateQueryDefinitionCF(n){return{Type:"AWS::Logs::QueryDefinition",Properties:{Name:n.name,QueryString:n.query,LogGroupNames:n.logGroupNames}}}createLogAggregation(n,i,s=7){let o=`aggregation-${Date.now()}-${this.logGroupCounter++}`,c=this.createLogGroup({name:n,retentionDays:s});return i.forEach((u)=>{this.createMetricFilter(c.id,{name:u.metric,filterPattern:u.pattern,metricTransformations:[{metricName:u.metric,metricNamespace:"CustomMetrics",metricValue:"1",defaultValue:0,unit:"Count"}]})}),{id:o,logGroup:n,filters:i,retention:s}}clear(){this.logGroups.clear(),this.queries.clear(),this.insightsQueries.clear(),this.logGroupCounter=0,this.filterCounter=0,this.queryCounter=0}}var iS=new Nl;class hr{canaries=new Map;heartbeats=new Map;apiMonitors=new Map;canaryCounter=0;heartbeatCounter=0;apiMonitorCounter=0;alarmCounter=0;static RuntimeVersions={NODEJS_PUPPETEER_3_9:"syn-nodejs-puppeteer-3.9",NODEJS_PUPPETEER_4_0:"syn-nodejs-puppeteer-4.0",PYTHON_SELENIUM_1_3:"syn-python-selenium-1.3"};createCanary(n){let i=`canary-${Date.now()}-${this.canaryCounter++}`,s={id:i,...n};return this.canaries.set(i,s),s}createHeartbeatCanary(n){let i=`
3620
+ | limit 20`,logGroupNames:n})}getLogGroup(n){return this.logGroups.get(n)}listLogGroups(){return Array.from(this.logGroups.values())}getInsightsQuery(n){return this.insightsQueries.get(n)}listInsightsQueries(){return Array.from(this.insightsQueries.values())}generateLogGroupCF(n){return{Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:n.name,...n.retentionDays&&{RetentionInDays:n.retentionDays},...n.kmsKeyId&&{KmsKeyId:n.kmsKeyId}}}}generateMetricFilterCF(n,i){return{Type:"AWS::Logs::MetricFilter",Properties:{FilterName:i.name,FilterPattern:i.filterPattern,LogGroupName:n.name,MetricTransformations:i.metricTransformations.map((s)=>({MetricName:s.metricName,MetricNamespace:s.metricNamespace,MetricValue:s.metricValue,...s.defaultValue!==void 0&&{DefaultValue:s.defaultValue},...s.unit&&{Unit:s.unit},...s.dimensions&&{Dimensions:s.dimensions}}))}}}generateSubscriptionFilterCF(n){return{Type:"AWS::Logs::SubscriptionFilter",Properties:{FilterName:n.name,FilterPattern:n.filterPattern,LogGroupName:n.logGroupName,DestinationArn:n.destinationArn,...n.roleArn&&{RoleArn:n.roleArn},...n.distribution&&{Distribution:n.distribution}}}}generateQueryDefinitionCF(n){return{Type:"AWS::Logs::QueryDefinition",Properties:{Name:n.name,QueryString:n.query,LogGroupNames:n.logGroupNames}}}createLogAggregation(n,i,s=7){let o=`aggregation-${Date.now()}-${this.logGroupCounter++}`,c=this.createLogGroup({name:n,retentionDays:s});return i.forEach((u)=>{this.createMetricFilter(c.id,{name:u.metric,filterPattern:u.pattern,metricTransformations:[{metricName:u.metric,metricNamespace:"CustomMetrics",metricValue:"1",defaultValue:0,unit:"Count"}]})}),{id:o,logGroup:n,filters:i,retention:s}}clear(){this.logGroups.clear(),this.queries.clear(),this.insightsQueries.clear(),this.logGroupCounter=0,this.filterCounter=0,this.queryCounter=0}}var hS=new Ul;class Ar{canaries=new Map;heartbeats=new Map;apiMonitors=new Map;canaryCounter=0;heartbeatCounter=0;apiMonitorCounter=0;alarmCounter=0;static RuntimeVersions={NODEJS_PUPPETEER_3_9:"syn-nodejs-puppeteer-3.9",NODEJS_PUPPETEER_4_0:"syn-nodejs-puppeteer-4.0",PYTHON_SELENIUM_1_3:"syn-python-selenium-1.3"};createCanary(n){let i=`canary-${Date.now()}-${this.canaryCounter++}`,s={id:i,...n};return this.canaries.set(i,s),s}createHeartbeatCanary(n){let i=`
3623
3621
  const synthetics = require('Synthetics');
3624
3622
  const log = require('SyntheticsLogger');
3625
3623
 
@@ -3639,7 +3637,7 @@ const heartbeat = async function () {
3639
3637
  exports.handler = async () => {
3640
3638
  return await heartbeat();
3641
3639
  };
3642
- `;return this.createCanary({name:n.name,description:`Heartbeat monitor for ${n.url}`,runtimeVersion:hr.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:i},schedule:{expression:`rate(${n.interval} minutes)`},runConfig:{timeoutInSeconds:60,memoryInMB:960,activeTracing:!0},artifactS3Location:`s3://${n.s3Bucket}/canary-artifacts/${n.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}createAPICanary(n){let s=`
3640
+ `;return this.createCanary({name:n.name,description:`Heartbeat monitor for ${n.url}`,runtimeVersion:Ar.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:i},schedule:{expression:`rate(${n.interval} minutes)`},runConfig:{timeoutInSeconds:60,memoryInMB:960,activeTracing:!0},artifactS3Location:`s3://${n.s3Bucket}/canary-artifacts/${n.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}createAPICanary(n){let s=`
3643
3641
  const synthetics = require('Synthetics');
3644
3642
  const log = require('SyntheticsLogger');
3645
3643
 
@@ -3668,7 +3666,7 @@ const apiCheck = async function () {
3668
3666
  exports.handler = async () => {
3669
3667
  return await apiCheck();
3670
3668
  };
3671
- `;return this.createCanary({name:n.name,description:`API monitor for ${n.baseUrl}`,runtimeVersion:hr.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:s},schedule:{expression:`rate(${n.interval} minutes)`},runConfig:{timeoutInSeconds:120,memoryInMB:960,activeTracing:!0},artifactS3Location:`s3://${n.s3Bucket}/canary-artifacts/${n.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}createVisualRegressionCanary(n){let i=`
3669
+ `;return this.createCanary({name:n.name,description:`API monitor for ${n.baseUrl}`,runtimeVersion:Ar.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:s},schedule:{expression:`rate(${n.interval} minutes)`},runConfig:{timeoutInSeconds:120,memoryInMB:960,activeTracing:!0},artifactS3Location:`s3://${n.s3Bucket}/canary-artifacts/${n.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}createVisualRegressionCanary(n){let i=`
3672
3670
  const synthetics = require('Synthetics');
3673
3671
  const log = require('SyntheticsLogger');
3674
3672
 
@@ -3688,7 +3686,7 @@ const visualCheck = async function () {
3688
3686
  exports.handler = async () => {
3689
3687
  return await visualCheck();
3690
3688
  };
3691
- `;return this.createCanary({name:n.name,description:`Visual regression monitor for ${n.url}`,runtimeVersion:hr.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:i},schedule:{expression:`rate(${n.interval} minutes)`},runConfig:{timeoutInSeconds:120,memoryInMB:1024,activeTracing:!0},artifactS3Location:`s3://${n.s3Bucket}/canary-artifacts/${n.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}createWorkflowCanary(n){let s=`
3689
+ `;return this.createCanary({name:n.name,description:`Visual regression monitor for ${n.url}`,runtimeVersion:Ar.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:i},schedule:{expression:`rate(${n.interval} minutes)`},runConfig:{timeoutInSeconds:120,memoryInMB:1024,activeTracing:!0},artifactS3Location:`s3://${n.s3Bucket}/canary-artifacts/${n.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}createWorkflowCanary(n){let s=`
3692
3690
  const synthetics = require('Synthetics');
3693
3691
  const log = require('SyntheticsLogger');
3694
3692
 
@@ -3710,35 +3708,35 @@ const workflowCheck = async function () {
3710
3708
  exports.handler = async () => {
3711
3709
  return await workflowCheck();
3712
3710
  };
3713
- `;return this.createCanary({name:n.name,description:n.description,runtimeVersion:hr.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:s},schedule:{expression:`rate(${n.interval} minutes)`},runConfig:{timeoutInSeconds:180,memoryInMB:1024,activeTracing:!0},artifactS3Location:`s3://${n.s3Bucket}/canary-artifacts/${n.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}generateActionScript(n){switch(n.type){case"click":return`await page.click('${n.selector}');`;case"type":return`await page.type('${n.selector}', '${n.value}');`;case"wait":return`await page.waitForTimeout(${n.duration});`;case"waitForSelector":return`await page.waitForSelector('${n.selector}');`;default:return""}}createAlarm(n,i){let s=this.canaries.get(n);if(!s)throw Error(`Canary not found: ${n}`);let c={id:`alarm-${Date.now()}-${this.alarmCounter++}`,...i};if(!s.alarms)s.alarms=[];return s.alarms.push(c),c}getCanary(n){return this.canaries.get(n)}listCanaries(){return Array.from(this.canaries.values())}generateCanaryCF(n){let i={Type:"AWS::Synthetics::Canary",Properties:{Name:n.name,RuntimeVersion:n.runtimeVersion,ExecutionRoleArn:{"Fn::GetAtt":["CanaryExecutionRole","Arn"]},Schedule:{Expression:n.schedule.expression,...n.schedule.durationInSeconds&&{DurationInSeconds:n.schedule.durationInSeconds}},ArtifactS3Location:n.artifactS3Location,StartCanaryAfterCreation:!0}};if(n.code.type==="script")i.Properties.Code={Handler:n.handler,Script:n.code.script};else i.Properties.Code={Handler:n.handler,S3Bucket:n.code.s3Bucket,S3Key:n.code.s3Key,...n.code.s3Version&&{S3ObjectVersion:n.code.s3Version}};if(n.runConfig)i.Properties.RunConfig={TimeoutInSeconds:n.runConfig.timeoutInSeconds,MemoryInMB:n.runConfig.memoryInMB,...n.runConfig.environmentVariables&&{EnvironmentVariables:n.runConfig.environmentVariables},...n.runConfig.activeTracing!==void 0&&{ActiveTracing:n.runConfig.activeTracing}};if(n.vpcConfig)i.Properties.VPCConfig={SubnetIds:n.vpcConfig.subnetIds,SecurityGroupIds:n.vpcConfig.securityGroupIds};if(n.successRetentionPeriod)i.Properties.SuccessRetentionPeriod=n.successRetentionPeriod;if(n.failureRetentionPeriod)i.Properties.FailureRetentionPeriod=n.failureRetentionPeriod;return i}generateCanaryRoleCF(){return{Type:"AWS::IAM::Role",Properties:{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","arn:aws:iam::aws:policy/CloudWatchSyntheticsFullAccess"],Policies:[{PolicyName:"CanaryS3Policy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["s3:PutObject","s3:GetBucketLocation"],Resource:["arn:aws:s3:::*/*"]}]}}]}}}clear(){this.canaries.clear(),this.heartbeats.clear(),this.apiMonitors.clear(),this.canaryCounter=0,this.heartbeatCounter=0,this.apiMonitorCounter=0,this.alarmCounter=0}}var sS=new hr;class rf{plans=new Map;migrations=new Map;planCounter=0;migrationCounter=0;createPlan(n){let i=`migration-plan-${Date.now()}-${this.planCounter++}`,s={id:i,...n};return this.plans.set(i,s),s}createMigration(n){let i=`migration-${Date.now()}-${this.migrationCounter++}`,s=this.generateChecksum(n.up+n.down),o={id:i,checksum:s,...n};return this.migrations.set(i,o),o}createSchemaMigration(n){let{up:i,down:s}=this.generateSchemaSQL(n.changes,n.tableName,n.engine);return this.createMigration({version:n.version,name:n.name,description:`Schema changes for ${n.tableName}`,up:i,down:s})}createDataMigration(n){return this.createMigration({version:n.version,name:n.name,description:n.description,up:n.upSQL,down:n.downSQL})}addMigrationToPlan(n,i){let s=this.plans.get(n);if(!s)throw Error(`Migration plan not found: ${n}`);s.migrations.push(i)}async executePlan(n,i=!1){let s=this.plans.get(n);if(!s)throw Error(`Migration plan not found: ${n}`);let o=Date.now(),c=[],u=[];if(console.log(`${i?"[DRY RUN] ":""}Executing migration plan: ${s.name}`),console.log(`Database: ${s.database.type} - ${s.database.identifier}`),console.log(`Migrations to apply: ${s.migrations.length}
3711
+ `;return this.createCanary({name:n.name,description:n.description,runtimeVersion:Ar.RuntimeVersions.NODEJS_PUPPETEER_4_0,handler:"index.handler",code:{type:"script",script:s},schedule:{expression:`rate(${n.interval} minutes)`},runConfig:{timeoutInSeconds:180,memoryInMB:1024,activeTracing:!0},artifactS3Location:`s3://${n.s3Bucket}/canary-artifacts/${n.name}/`,successRetentionPeriod:31,failureRetentionPeriod:31})}generateActionScript(n){switch(n.type){case"click":return`await page.click('${n.selector}');`;case"type":return`await page.type('${n.selector}', '${n.value}');`;case"wait":return`await page.waitForTimeout(${n.duration});`;case"waitForSelector":return`await page.waitForSelector('${n.selector}');`;default:return""}}createAlarm(n,i){let s=this.canaries.get(n);if(!s)throw Error(`Canary not found: ${n}`);let c={id:`alarm-${Date.now()}-${this.alarmCounter++}`,...i};if(!s.alarms)s.alarms=[];return s.alarms.push(c),c}getCanary(n){return this.canaries.get(n)}listCanaries(){return Array.from(this.canaries.values())}generateCanaryCF(n){let i={Type:"AWS::Synthetics::Canary",Properties:{Name:n.name,RuntimeVersion:n.runtimeVersion,ExecutionRoleArn:{"Fn::GetAtt":["CanaryExecutionRole","Arn"]},Schedule:{Expression:n.schedule.expression,...n.schedule.durationInSeconds&&{DurationInSeconds:n.schedule.durationInSeconds}},ArtifactS3Location:n.artifactS3Location,StartCanaryAfterCreation:!0}};if(n.code.type==="script")i.Properties.Code={Handler:n.handler,Script:n.code.script};else i.Properties.Code={Handler:n.handler,S3Bucket:n.code.s3Bucket,S3Key:n.code.s3Key,...n.code.s3Version&&{S3ObjectVersion:n.code.s3Version}};if(n.runConfig)i.Properties.RunConfig={TimeoutInSeconds:n.runConfig.timeoutInSeconds,MemoryInMB:n.runConfig.memoryInMB,...n.runConfig.environmentVariables&&{EnvironmentVariables:n.runConfig.environmentVariables},...n.runConfig.activeTracing!==void 0&&{ActiveTracing:n.runConfig.activeTracing}};if(n.vpcConfig)i.Properties.VPCConfig={SubnetIds:n.vpcConfig.subnetIds,SecurityGroupIds:n.vpcConfig.securityGroupIds};if(n.successRetentionPeriod)i.Properties.SuccessRetentionPeriod=n.successRetentionPeriod;if(n.failureRetentionPeriod)i.Properties.FailureRetentionPeriod=n.failureRetentionPeriod;return i}generateCanaryRoleCF(){return{Type:"AWS::IAM::Role",Properties:{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","arn:aws:iam::aws:policy/CloudWatchSyntheticsFullAccess"],Policies:[{PolicyName:"CanaryS3Policy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["s3:PutObject","s3:GetBucketLocation"],Resource:["arn:aws:s3:::*/*"]}]}}]}}}clear(){this.canaries.clear(),this.heartbeats.clear(),this.apiMonitors.clear(),this.canaryCounter=0,this.heartbeatCounter=0,this.apiMonitorCounter=0,this.alarmCounter=0}}var AS=new Ar;class pf{plans=new Map;migrations=new Map;planCounter=0;migrationCounter=0;createPlan(n){let i=`migration-plan-${Date.now()}-${this.planCounter++}`,s={id:i,...n};return this.plans.set(i,s),s}createMigration(n){let i=`migration-${Date.now()}-${this.migrationCounter++}`,s=this.generateChecksum(n.up+n.down),o={id:i,checksum:s,...n};return this.migrations.set(i,o),o}createSchemaMigration(n){let{up:i,down:s}=this.generateSchemaSQL(n.changes,n.tableName,n.engine);return this.createMigration({version:n.version,name:n.name,description:`Schema changes for ${n.tableName}`,up:i,down:s})}createDataMigration(n){return this.createMigration({version:n.version,name:n.name,description:n.description,up:n.upSQL,down:n.downSQL})}addMigrationToPlan(n,i){let s=this.plans.get(n);if(!s)throw Error(`Migration plan not found: ${n}`);s.migrations.push(i)}async executePlan(n,i=!1){let s=this.plans.get(n);if(!s)throw Error(`Migration plan not found: ${n}`);let o=Date.now(),c=[],u=[];if(console.log(`${i?"[DRY RUN] ":""}Executing migration plan: ${s.name}`),console.log(`Database: ${s.database.type} - ${s.database.identifier}`),console.log(`Migrations to apply: ${s.migrations.length}
3714
3712
  `),s.backupBeforeMigration&&!i)console.log("Creating database backup before migration...");for(let g of s.migrations)try{if(console.log(`Applying migration: ${g.version} - ${g.name}`),!i){if(this.generateChecksum(g.up+g.down)!==g.checksum)throw Error("Migration checksum mismatch - migration has been modified");let h=Date.now();g.appliedAt=new Date,g.executionTimeMs=Date.now()-h,console.log(`✓ Applied in ${g.executionTimeMs}ms
3715
3713
  `)}else console.log(`[SKIPPED - DRY RUN]
3716
3714
  `);c.push(g.version)}catch(y){if(console.error(`✗ Failed: ${y instanceof Error?y.message:String(y)}
3717
3715
  `),u.push(g.version),!i)return console.log("Rolling back previously applied migrations..."),await this.rollbackMigrations(c.reverse(),s),{success:!1,version:g.version,appliedMigrations:[],failedMigrations:u,executionTimeMs:Date.now()-o,error:y instanceof Error?y.message:String(y),rollbackPerformed:!0}}let d=Date.now()-o;return console.log(`${i?"[DRY RUN] ":""}Migration plan completed successfully`),console.log(`Total time: ${d}ms`),{success:!0,version:s.migrations[s.migrations.length-1]?.version||"unknown",appliedMigrations:c,failedMigrations:u,executionTimeMs:d}}async rollbackMigrations(n,i){for(let s of n){let o=i.migrations.find((c)=>c.version===s);if(o)console.log(`Rolling back: ${o.version} - ${o.name}`),o.rolledBackAt=new Date,console.log(`✓ Rolled back
3718
3716
  `)}}getMigrationStatus(n){let i=this.plans.get(n);if(!i)throw Error(`Migration plan not found: ${n}`);let s=i.migrations.filter((c)=>c.appliedAt&&!c.rolledBackAt),o=i.migrations.filter((c)=>!c.appliedAt);return{currentVersion:s[s.length-1]?.version||"0.0.0",pendingMigrations:o,appliedMigrations:s,lastMigration:s[s.length-1]}}generateSchemaSQL(n,i,s="postgres"){let o=[],c=[];for(let u of n)switch(u.type){case"add_column":o.push(`ALTER TABLE ${i} ADD COLUMN ${u.columnName} ${u.columnType}${u.nullable===!1?" NOT NULL":""}${u.defaultValue?` DEFAULT ${u.defaultValue}`:""}; `),c.push(`ALTER TABLE ${i} DROP COLUMN ${u.columnName};`);break;case"drop_column":o.push(`ALTER TABLE ${i} DROP COLUMN ${u.columnName};`),c.push(`-- Cannot restore dropped column ${u.columnName}`);break;case"modify_column":if(s==="postgres")o.push(`ALTER TABLE ${i} ALTER COLUMN ${u.columnName} TYPE ${u.newType};`);else o.push(`ALTER TABLE ${i} MODIFY COLUMN ${u.columnName} ${u.newType};`);c.push(`-- Reverting ${u.columnName} type change requires manual intervention`);break;case"add_index":o.push(`CREATE INDEX ${u.indexName} ON ${i} (${(u.columns??[]).join(", ")});`),c.push(`DROP INDEX ${u.indexName};`);break;case"drop_index":o.push(`DROP INDEX ${u.indexName};`),c.push(`-- Cannot restore index ${u.indexName} without schema details`);break}return{up:o.join(`
3719
3717
  `),down:c.reverse().join(`
3720
- `)}}generateChecksum(n){let i=0;for(let s=0;s<n.length;s++){let o=n.charCodeAt(s);i=(i<<5)-i+o,i=i&i}return i.toString(16)}validatePlan(n){let i=this.plans.get(n);if(!i)return{valid:!1,errors:["Migration plan not found"]};let s=[],o=new Set;for(let c of i.migrations){if(o.has(c.version))s.push(`Duplicate migration version: ${c.version}`);o.add(c.version)}for(let c of i.migrations)if(!c.down||c.down.trim()==="")s.push(`Migration ${c.version} is missing rollback SQL`);for(let c of i.migrations)if(this.generateChecksum(c.up+c.down)!==c.checksum)s.push(`Migration ${c.version} has invalid checksum`);return{valid:s.length===0,errors:s}}getPlan(n){return this.plans.get(n)}listPlans(){return Array.from(this.plans.values())}getMigration(n){return this.migrations.get(n)}listMigrations(){return Array.from(this.migrations.values())}clear(){this.plans.clear(),this.migrations.clear(),this.planCounter=0,this.migrationCounter=0}}var sE=new rf;class Bl{replicas=new Map;replicationGroups=new Map;proxies=new Map;proxyTargets=new Map;replicaCounter=0;groupCounter=0;proxyCounter=0;targetCounter=0;createReplica(n){let i=`replica-${Date.now()}-${this.replicaCounter++}`,s={id:i,status:"creating",...n};return this.replicas.set(i,s),s}createRDSReplica(n){return this.createReplica({name:n.name,sourceDatabase:n.sourceDatabase,region:n.region||"us-east-1",instanceClass:n.instanceClass||"db.t3.medium",multiAZ:n.multiAZ||!1,autoMinorVersionUpgrade:!0,backupRetentionPeriod:7})}createCrossRegionReplica(n){return this.createReplica({name:n.name,sourceDatabase:n.sourceDatabase,region:n.targetRegion,instanceClass:n.instanceClass||"db.t3.medium",multiAZ:!0,autoMinorVersionUpgrade:!0,backupRetentionPeriod:7})}createReplicationGroup(n){let i=`replication-group-${Date.now()}-${this.groupCounter++}`,s={id:i,...n};return this.replicationGroups.set(i,s),s}createAutoScalingReplicationGroup(n){return this.createReplicationGroup({name:n.name,primaryDatabase:n.primaryDatabase,replicas:[],loadBalancing:n.loadBalancing||{type:"round-robin"},failoverEnabled:!0,autoScaling:{enabled:!0,minReplicas:n.minReplicas,maxReplicas:n.maxReplicas,targetCPU:n.targetCPU||70,scaleUpCooldown:300,scaleDownCooldown:600}})}addReplicaToGroup(n,i){let s=this.replicationGroups.get(n);if(!s)throw Error(`Replication group not found: ${n}`);s.replicas.push(i)}createProxy(n){let i=`rds-proxy-${Date.now()}-${this.proxyCounter++}`,s={id:i,...n};return this.proxies.set(i,s),s}createConnectionPoolProxy(n){return this.createProxy({name:n.name,engineFamily:n.engineFamily,targetDatabase:n.targetDatabase,maxConnectionsPercent:n.maxConnections||100,maxIdleConnectionsPercent:50,connectionBorrowTimeout:120,sessionPinningFilters:["EXCLUDE_VARIABLE_SETS"],requireTLS:!0,idleClientTimeout:1800,vpcSubnetIds:n.vpcSubnetIds,securityGroupIds:n.securityGroupIds,secretArn:n.secretArn})}createServerlessProxy(n){return this.createProxy({name:n.name,engineFamily:n.engineFamily,targetDatabase:n.targetDatabase,maxConnectionsPercent:100,maxIdleConnectionsPercent:10,connectionBorrowTimeout:60,sessionPinningFilters:["EXCLUDE_VARIABLE_SETS"],requireTLS:!0,idleClientTimeout:300,vpcSubnetIds:n.vpcSubnetIds,securityGroupIds:n.securityGroupIds,secretArn:n.secretArn})}addProxyTarget(n){let i=`proxy-target-${Date.now()}-${this.targetCounter++}`,s={id:i,...n};return this.proxyTargets.set(i,s),s}promoteReplica(n){let i=this.replicas.get(n);if(!i)return{success:!1,message:"Replica not found"};if(console.log(`Promoting replica to primary: ${i.name}`),console.log(`Region: ${i.region}`),console.log(`
3718
+ `)}}generateChecksum(n){let i=0;for(let s=0;s<n.length;s++){let o=n.charCodeAt(s);i=(i<<5)-i+o,i=i&i}return i.toString(16)}validatePlan(n){let i=this.plans.get(n);if(!i)return{valid:!1,errors:["Migration plan not found"]};let s=[],o=new Set;for(let c of i.migrations){if(o.has(c.version))s.push(`Duplicate migration version: ${c.version}`);o.add(c.version)}for(let c of i.migrations)if(!c.down||c.down.trim()==="")s.push(`Migration ${c.version} is missing rollback SQL`);for(let c of i.migrations)if(this.generateChecksum(c.up+c.down)!==c.checksum)s.push(`Migration ${c.version} has invalid checksum`);return{valid:s.length===0,errors:s}}getPlan(n){return this.plans.get(n)}listPlans(){return Array.from(this.plans.values())}getMigration(n){return this.migrations.get(n)}listMigrations(){return Array.from(this.migrations.values())}clear(){this.plans.clear(),this.migrations.clear(),this.planCounter=0,this.migrationCounter=0}}var yE=new pf;class Ql{replicas=new Map;replicationGroups=new Map;proxies=new Map;proxyTargets=new Map;replicaCounter=0;groupCounter=0;proxyCounter=0;targetCounter=0;createReplica(n){let i=`replica-${Date.now()}-${this.replicaCounter++}`,s={id:i,status:"creating",...n};return this.replicas.set(i,s),s}createRDSReplica(n){return this.createReplica({name:n.name,sourceDatabase:n.sourceDatabase,region:n.region||"us-east-1",instanceClass:n.instanceClass||"db.t3.medium",multiAZ:n.multiAZ||!1,autoMinorVersionUpgrade:!0,backupRetentionPeriod:7})}createCrossRegionReplica(n){return this.createReplica({name:n.name,sourceDatabase:n.sourceDatabase,region:n.targetRegion,instanceClass:n.instanceClass||"db.t3.medium",multiAZ:!0,autoMinorVersionUpgrade:!0,backupRetentionPeriod:7})}createReplicationGroup(n){let i=`replication-group-${Date.now()}-${this.groupCounter++}`,s={id:i,...n};return this.replicationGroups.set(i,s),s}createAutoScalingReplicationGroup(n){return this.createReplicationGroup({name:n.name,primaryDatabase:n.primaryDatabase,replicas:[],loadBalancing:n.loadBalancing||{type:"round-robin"},failoverEnabled:!0,autoScaling:{enabled:!0,minReplicas:n.minReplicas,maxReplicas:n.maxReplicas,targetCPU:n.targetCPU||70,scaleUpCooldown:300,scaleDownCooldown:600}})}addReplicaToGroup(n,i){let s=this.replicationGroups.get(n);if(!s)throw Error(`Replication group not found: ${n}`);s.replicas.push(i)}createProxy(n){let i=`rds-proxy-${Date.now()}-${this.proxyCounter++}`,s={id:i,...n};return this.proxies.set(i,s),s}createConnectionPoolProxy(n){return this.createProxy({name:n.name,engineFamily:n.engineFamily,targetDatabase:n.targetDatabase,maxConnectionsPercent:n.maxConnections||100,maxIdleConnectionsPercent:50,connectionBorrowTimeout:120,sessionPinningFilters:["EXCLUDE_VARIABLE_SETS"],requireTLS:!0,idleClientTimeout:1800,vpcSubnetIds:n.vpcSubnetIds,securityGroupIds:n.securityGroupIds,secretArn:n.secretArn})}createServerlessProxy(n){return this.createProxy({name:n.name,engineFamily:n.engineFamily,targetDatabase:n.targetDatabase,maxConnectionsPercent:100,maxIdleConnectionsPercent:10,connectionBorrowTimeout:60,sessionPinningFilters:["EXCLUDE_VARIABLE_SETS"],requireTLS:!0,idleClientTimeout:300,vpcSubnetIds:n.vpcSubnetIds,securityGroupIds:n.securityGroupIds,secretArn:n.secretArn})}addProxyTarget(n){let i=`proxy-target-${Date.now()}-${this.targetCounter++}`,s={id:i,...n};return this.proxyTargets.set(i,s),s}promoteReplica(n){let i=this.replicas.get(n);if(!i)return{success:!1,message:"Replica not found"};if(console.log(`Promoting replica to primary: ${i.name}`),console.log(`Region: ${i.region}`),console.log(`
3721
3719
  1. Checking replication lag...`),i.replicationLag&&i.replicationLag>5000)return{success:!1,message:`Replication lag too high: ${i.replicationLag}ms`};return console.log(` Replication lag: ${i.replicationLag||0}ms (acceptable)`),console.log(`
3722
3720
  2. Promoting replica to standalone instance...`),console.log(`
3723
3721
  3. Updating DNS records...`),console.log(`
3724
3722
  4. Updating application configuration...`),console.log(`
3725
- ✓ Promotion completed successfully`),i.status="available",{success:!0,message:"Replica promoted successfully"}}getReplicationLag(n){if(!this.replicas.get(n))throw Error(`Replica not found: ${n}`);return Math.floor(Math.random()*1000)}getReplica(n){return this.replicas.get(n)}listReplicas(){return Array.from(this.replicas.values())}getReplicationGroup(n){return this.replicationGroups.get(n)}listReplicationGroups(){return Array.from(this.replicationGroups.values())}getProxy(n){return this.proxies.get(n)}listProxies(){return Array.from(this.proxies.values())}generateReplicaCF(n){return{Type:"AWS::RDS::DBInstance",Properties:{SourceDBInstanceIdentifier:n.sourceDatabase,DBInstanceIdentifier:n.name,DBInstanceClass:n.instanceClass,MultiAZ:n.multiAZ||!1,AutoMinorVersionUpgrade:n.autoMinorVersionUpgrade??!0,...n.backupRetentionPeriod&&{BackupRetentionPeriod:n.backupRetentionPeriod},...n.preferredBackupWindow&&{PreferredBackupWindow:n.preferredBackupWindow},...n.preferredMaintenanceWindow&&{PreferredMaintenanceWindow:n.preferredMaintenanceWindow}}}}generateProxyCF(n){return{Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:n.name,EngineFamily:n.engineFamily,Auth:[{AuthScheme:"SECRETS",SecretArn:n.secretArn,IAMAuth:"DISABLED"}],RoleArn:{"Fn::GetAtt":["RDSProxyRole","Arn"]},VpcSubnetIds:n.vpcSubnetIds,VpcSecurityGroupIds:n.securityGroupIds,RequireTLS:n.requireTLS??!0,IdleClientTimeout:n.idleClientTimeout||1800,...n.maxConnectionsPercent&&{MaxConnectionsPercent:n.maxConnectionsPercent},...n.maxIdleConnectionsPercent&&{MaxIdleConnectionsPercent:n.maxIdleConnectionsPercent},...n.connectionBorrowTimeout&&{ConnectionBorrowTimeout:n.connectionBorrowTimeout}}}}generateProxyTargetCF(n,i){return{Type:"AWS::RDS::DBProxyTargetGroup",Properties:{DBProxyName:i.name,TargetGroupName:"default",DBInstanceIdentifiers:[n.targetArn],ConnectionPoolConfig:{MaxConnectionsPercent:100,MaxIdleConnectionsPercent:50,ConnectionBorrowTimeout:120}}}}generateProxyRoleCF(){return{Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"rds.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"RDSProxySecretsPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],Resource:"arn:aws:secretsmanager:*:*:secret:*"},{Effect:"Allow",Action:["kms:Decrypt"],Resource:"arn:aws:kms:*:*:key/*",Condition:{StringEquals:{"kms:ViaService":"secretsmanager.*.amazonaws.com"}}}]}}]}}}clear(){this.replicas.clear(),this.replicationGroups.clear(),this.proxies.clear(),this.proxyTargets.clear(),this.replicaCounter=0,this.groupCounter=0,this.proxyCounter=0,this.targetCounter=0}}var oS=new Bl;class nf{insights=new Map;slowQueryLogs=new Map;queryMetrics=new Map;reports=new Map;indexRecommendations=new Map;insightsCounter=0;logCounter=0;metricCounter=0;reportCounter=0;recommendationCounter=0;enablePerformanceInsights(n){let i=`pi-${Date.now()}-${this.insightsCounter++}`,s={id:i,name:n.name,databaseIdentifier:n.databaseIdentifier,enabled:!0,retentionPeriod:n.retentionPeriod||7,kmsKeyId:n.kmsKeyId};return this.insights.set(i,s),s}enableSlowQueryLog(n){let i=`slow-query-${Date.now()}-${this.logCounter++}`,s={id:i,name:n.name,databaseIdentifier:n.databaseIdentifier,enabled:!0,logDestination:n.logDestination,cloudwatchLogGroup:n.cloudwatchLogGroup,s3Bucket:n.s3Bucket,s3Prefix:n.s3Bucket?"slow-queries/":void 0,minExecutionTime:n.minExecutionTime||1000};return this.slowQueryLogs.set(i,s),s}recordQueryMetric(n){let i=`metric-${Date.now()}-${this.metricCounter++}`,s={id:i,timestamp:new Date,...n};return this.queryMetrics.set(i,s),s}generatePerformanceReport(n){let i=`report-${Date.now()}-${this.reportCounter++}`,s={avgCPU:Math.random()*60+20,maxCPU:Math.random()*30+70,avgConnections:Math.floor(Math.random()*50+10),maxConnections:Math.floor(Math.random()*50+100),avgReadIOPS:Math.floor(Math.random()*1000+500),avgWriteIOPS:Math.floor(Math.random()*500+200),avgReadThroughput:Math.random()*50+10,avgWriteThroughput:Math.random()*20+5,avgReadLatency:Math.random()*5+1,avgWriteLatency:Math.random()*8+2,cacheHitRatio:Math.random()*10+90,deadlocks:Math.floor(Math.random()*5),longRunningTransactions:Math.floor(Math.random()*10)},o=Array.from(this.queryMetrics.values()),c=o.sort((y,h)=>h.executionCount-y.executionCount).slice(0,10),u=o.filter((y)=>y.avgExecutionTime>1000).sort((y,h)=>h.avgExecutionTime-y.avgExecutionTime).slice(0,10),d=this.generateRecommendations(s,u),g={id:i,name:n.name,databaseIdentifier:n.databaseIdentifier,reportType:n.reportType,metrics:s,topQueries:c,slowQueries:u,recommendations:d,generatedAt:new Date};return this.reports.set(i,g),g}generateRecommendations(n,i){let s=[];if(n.avgCPU>70)s.push({type:"scaling",severity:"high",title:"High CPU Usage",description:`Average CPU usage is ${n.avgCPU.toFixed(1)}%, which is above the recommended threshold of 70%.`,impact:"Performance degradation, increased latency, potential timeouts",effort:"medium"});if(n.cacheHitRatio<95)s.push({type:"configuration",severity:"medium",title:"Low Cache Hit Ratio",description:`Cache hit ratio is ${n.cacheHitRatio.toFixed(1)}%. Consider increasing buffer pool size.`,impact:"Increased disk I/O, slower query performance",effort:"low"});if(n.deadlocks>0)s.push({type:"query",severity:"medium",title:"Deadlocks Detected",description:`${n.deadlocks} deadlock(s) detected. Review transaction isolation levels and query patterns.`,impact:"Transaction failures, application errors",effort:"high"});if(i.length>0)s.push({type:"index",severity:"high",title:"Slow Queries Detected",description:`${i.length} slow queries detected. Consider adding indexes or optimizing queries.`,impact:"High latency, poor user experience",effort:"medium"});if(n.avgReadLatency>10||n.avgWriteLatency>10)s.push({type:"scaling",severity:"high",title:"High I/O Latency",description:"Read or write latency is high. Consider upgrading to Provisioned IOPS or moving to a larger instance.",impact:"Slow query execution, application timeouts",effort:"medium"});return s}analyzeQuery(n){let i=`analysis-${Date.now()}-${Math.random().toString(36).slice(2,9)}`,s=[{id:1,operation:"Seq Scan",table:"users",rows:1e4,cost:850.5,children:[]}],o=[];if(n.toLowerCase().includes("select *"))o.push({type:"full_table_scan",severity:"warning",description:"Query selects all columns. Consider selecting only required columns."});if(!n.toLowerCase().includes("where")&&n.toLowerCase().includes("select"))o.push({type:"full_table_scan",severity:"critical",description:"Query has no WHERE clause and may scan entire table."});return{id:i,queryId:i,sql:n,executionPlan:s,bottlenecks:o,recommendations:["Add appropriate indexes on WHERE clause columns","Consider using EXPLAIN ANALYZE to get actual execution statistics","Review and optimize JOIN conditions"],estimatedCost:s[0].cost}}recommendIndex(n){let i=`index-rec-${Date.now()}-${this.recommendationCounter++}`,s=`idx_${n.tableName}_${n.columns.join("_")}`,o={id:i,tableName:n.tableName,columns:n.columns,reason:n.reason,estimatedImprovement:n.estimatedImprovement||50,estimatedSize:n.columns.length*10,createSQL:`CREATE INDEX ${s} ON ${n.tableName} (${n.columns.join(", ")});`};return this.indexRecommendations.set(i,o),o}getInsights(n){return this.insights.get(n)}listInsights(){return Array.from(this.insights.values())}getSlowQueryLog(n){return this.slowQueryLogs.get(n)}listSlowQueryLogs(){return Array.from(this.slowQueryLogs.values())}getReport(n){return this.reports.get(n)}listReports(){return Array.from(this.reports.values())}listIndexRecommendations(){return Array.from(this.indexRecommendations.values())}generatePerformanceInsightsCF(n){return{EnablePerformanceInsights:n.enabled,PerformanceInsightsRetentionPeriod:n.retentionPeriod,...n.kmsKeyId&&{PerformanceInsightsKMSKeyId:n.kmsKeyId}}}generateSlowQueryAlarmCF(n){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:n.alarmName,AlarmDescription:"Alert when slow queries exceed threshold",MetricName:"SlowQueryCount",Namespace:"AWS/RDS",Statistic:"Sum",Period:300,EvaluationPeriods:1,Threshold:n.threshold,ComparisonOperator:"GreaterThanThreshold",...n.snsTopicArn&&{AlarmActions:[n.snsTopicArn]}}}}clear(){this.insights.clear(),this.slowQueryLogs.clear(),this.queryMetrics.clear(),this.reports.clear(),this.indexRecommendations.clear(),this.insightsCounter=0,this.logCounter=0,this.metricCounter=0,this.reportCounter=0,this.recommendationCounter=0}}var oE=new nf;class sf{users=new Map;roles=new Map;audits=new Map;userCounter=0;roleCounter=0;auditCounter=0;createUser(n){let i=`db-user-${Date.now()}-${this.userCounter++}`,s={id:i,createdAt:new Date,...n};return this.users.set(i,s),s}createReadOnlyUser(n){let i=n.tables?n.tables.map((s)=>({database:n.database,table:s,privileges:["SELECT"]})):[{database:n.database,privileges:["SELECT"]}];return this.createUser({username:n.username,database:n.database,privileges:i,passwordSecretArn:n.passwordSecretArn,rotationEnabled:!0,rotationDays:90})}createReadWriteUser(n){let i=n.tables?n.tables.map((s)=>({database:n.database,table:s,privileges:["SELECT","INSERT","UPDATE","DELETE"]})):[{database:n.database,privileges:["SELECT","INSERT","UPDATE","DELETE"]}];return this.createUser({username:n.username,database:n.database,privileges:i,passwordSecretArn:n.passwordSecretArn,rotationEnabled:!0,rotationDays:60})}createAdminUser(n){return this.createUser({username:n.username,database:n.database,privileges:[{database:n.database,privileges:["ALL"]}],passwordSecretArn:n.passwordSecretArn,rotationEnabled:!0,rotationDays:30})}createApplicationUser(n){let i=n.tables.map((s)=>({database:n.database,table:s.name,privileges:s.privileges}));return this.createUser({username:n.username,database:n.database,privileges:i,passwordSecretArn:n.passwordSecretArn,rotationEnabled:!0,rotationDays:90})}createRole(n){let i=`role-${Date.now()}-${this.roleCounter++}`,s={id:i,users:[],...n};return this.roles.set(i,s),s}assignUserToRole(n,i){let s=this.users.get(n),o=this.roles.get(i);if(!s)throw Error(`User not found: ${n}`);if(!o)throw Error(`Role not found: ${i}`);o.users.push(n);for(let c of o.privileges){let u=s.privileges.find((d)=>d.database===c.database&&d.table===c.table);if(u)u.privileges=Array.from(new Set([...u.privileges,...c.privileges]));else s.privileges.push({...c})}}grantPrivileges(n,i){let s=this.users.get(n);if(!s)return{success:!1,message:"User not found"};for(let o of i){let c=s.privileges.find((u)=>u.database===o.database&&u.table===o.table);if(c)c.privileges=Array.from(new Set([...c.privileges,...o.privileges]));else s.privileges.push(o)}return this.auditAccess({username:s.username,action:"GRANT",database:i[0]?.database,table:i[0]?.table,success:!0}),{success:!0,message:"Privileges granted successfully"}}revokePrivileges(n,i){let s=this.users.get(n);if(!s)return{success:!1,message:"User not found"};for(let o of i){let c=s.privileges.findIndex((u)=>u.database===o.database&&u.table===o.table);if(c!==-1){let u=s.privileges[c];if(u.privileges=u.privileges.filter((d)=>!o.privileges.includes(d)),u.privileges.length===0)s.privileges.splice(c,1)}}return this.auditAccess({username:s.username,action:"REVOKE",database:i[0]?.database,table:i[0]?.table,success:!0}),{success:!0,message:"Privileges revoked successfully"}}rotatePassword(n){let i=this.users.get(n);if(!i)return{success:!1};let s=`arn:aws:secretsmanager:us-east-1:123456789012:secret:db-${i.username}-${Date.now()}`;return i.passwordSecretArn=s,i.lastRotated=new Date,console.log(`Password rotated for user: ${i.username}`),{success:!0,newSecretArn:s}}needsPasswordRotation(n){let i=this.users.get(n);if(!i||!i.rotationEnabled||!i.lastRotated||!i.rotationDays)return!1;return(Date.now()-i.lastRotated.getTime())/86400000>=i.rotationDays}auditAccess(n){let i=`audit-${Date.now()}-${this.auditCounter++}`,s={id:i,timestamp:new Date,...n};return this.audits.set(i,s),s}getUserAccessHistory(n,i=100){return Array.from(this.audits.values()).filter((s)=>s.username===n).sort((s,o)=>o.timestamp.getTime()-s.timestamp.getTime()).slice(0,i)}getFailedLoginAttempts(n,i=24){let s=Date.now()-i*60*60*1000;return Array.from(this.audits.values()).filter((o)=>o.username===n&&o.action==="LOGIN"&&!o.success&&o.timestamp.getTime()>s)}generateCreateUserSQL(n,i="postgres"){let s=[];if(i==="postgres"){s.push(`CREATE USER ${n.username} WITH PASSWORD '${n.passwordSecretArn}';`);for(let o of n.privileges)if(o.privileges.includes("ALL"))s.push(`GRANT ALL PRIVILEGES ON DATABASE ${o.database} TO ${n.username};`);else{let c=o.privileges.join(", ");if(o.table)s.push(`GRANT ${c} ON ${o.database}.${o.table} TO ${n.username};`);else s.push(`GRANT ${c} ON DATABASE ${o.database} TO ${n.username};`)}}else{s.push(`CREATE USER '${n.username}'@'%' IDENTIFIED BY '${n.passwordSecretArn}';`);for(let o of n.privileges){let c=o.privileges.includes("ALL")?"ALL PRIVILEGES":o.privileges.join(", "),u=o.table?`${o.database}.${o.table}`:`${o.database}.*`;s.push(`GRANT ${c} ON ${u} TO '${n.username}'@'%';`)}s.push("FLUSH PRIVILEGES;")}return s.join(`
3726
- `)}getUser(n){return this.users.get(n)}listUsers(){return Array.from(this.users.values())}getRole(n){return this.roles.get(n)}listRoles(){return Array.from(this.roles.values())}clear(){this.users.clear(),this.roles.clear(),this.audits.clear(),this.userCounter=0,this.roleCounter=0,this.auditCounter=0}}var aE=new sf;class of{rotations=new Map;schedules=new Map;rotationCounter=0;scheduleCounter=0;createRotation(n){let i=`rotation-${Date.now()}-${this.rotationCounter++}`,s={id:i,...n};return this.rotations.set(i,s),s}enableRDSRotation(n){let i=this.createRotation({secretId:n.secretId,secretType:"rds_credentials",rotationEnabled:!0,rotationDays:n.rotationDays||30,rotationLambdaArn:this.generateRDSRotationLambdaArn(n.engine)});return i.nextRotation=new Date(Date.now()+i.rotationDays*24*60*60*1000),i}enableAPIKeyRotation(n){return this.createRotation({secretId:n.secretId,secretType:"api_key",rotationEnabled:!0,rotationDays:n.rotationDays||90,rotationLambdaArn:n.rotationLambdaArn})}enableOAuthRotation(n){return this.createRotation({secretId:n.secretId,secretType:"oauth_token",rotationEnabled:!0,rotationDays:n.rotationDays||60,rotationLambdaArn:n.rotationLambdaArn})}enableSSHKeyRotation(n){return this.createRotation({secretId:n.secretId,secretType:"ssh_key",rotationEnabled:!0,rotationDays:n.rotationDays||180,rotationLambdaArn:n.rotationLambdaArn})}createSchedule(n){let i=`schedule-${Date.now()}-${this.scheduleCounter++}`,s={id:i,...n};return this.schedules.set(i,s),s}async executeRotation(n){let i=this.rotations.get(n);if(!i)throw Error(`Rotation not found: ${n}`);console.log(`
3723
+ ✓ Promotion completed successfully`),i.status="available",{success:!0,message:"Replica promoted successfully"}}getReplicationLag(n){if(!this.replicas.get(n))throw Error(`Replica not found: ${n}`);return Math.floor(Math.random()*1000)}getReplica(n){return this.replicas.get(n)}listReplicas(){return Array.from(this.replicas.values())}getReplicationGroup(n){return this.replicationGroups.get(n)}listReplicationGroups(){return Array.from(this.replicationGroups.values())}getProxy(n){return this.proxies.get(n)}listProxies(){return Array.from(this.proxies.values())}generateReplicaCF(n){return{Type:"AWS::RDS::DBInstance",Properties:{SourceDBInstanceIdentifier:n.sourceDatabase,DBInstanceIdentifier:n.name,DBInstanceClass:n.instanceClass,MultiAZ:n.multiAZ||!1,AutoMinorVersionUpgrade:n.autoMinorVersionUpgrade??!0,...n.backupRetentionPeriod&&{BackupRetentionPeriod:n.backupRetentionPeriod},...n.preferredBackupWindow&&{PreferredBackupWindow:n.preferredBackupWindow},...n.preferredMaintenanceWindow&&{PreferredMaintenanceWindow:n.preferredMaintenanceWindow}}}}generateProxyCF(n){return{Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:n.name,EngineFamily:n.engineFamily,Auth:[{AuthScheme:"SECRETS",SecretArn:n.secretArn,IAMAuth:"DISABLED"}],RoleArn:{"Fn::GetAtt":["RDSProxyRole","Arn"]},VpcSubnetIds:n.vpcSubnetIds,VpcSecurityGroupIds:n.securityGroupIds,RequireTLS:n.requireTLS??!0,IdleClientTimeout:n.idleClientTimeout||1800,...n.maxConnectionsPercent&&{MaxConnectionsPercent:n.maxConnectionsPercent},...n.maxIdleConnectionsPercent&&{MaxIdleConnectionsPercent:n.maxIdleConnectionsPercent},...n.connectionBorrowTimeout&&{ConnectionBorrowTimeout:n.connectionBorrowTimeout}}}}generateProxyTargetCF(n,i){return{Type:"AWS::RDS::DBProxyTargetGroup",Properties:{DBProxyName:i.name,TargetGroupName:"default",DBInstanceIdentifiers:[n.targetArn],ConnectionPoolConfig:{MaxConnectionsPercent:100,MaxIdleConnectionsPercent:50,ConnectionBorrowTimeout:120}}}}generateProxyRoleCF(){return{Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"rds.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"RDSProxySecretsPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],Resource:"arn:aws:secretsmanager:*:*:secret:*"},{Effect:"Allow",Action:["kms:Decrypt"],Resource:"arn:aws:kms:*:*:key/*",Condition:{StringEquals:{"kms:ViaService":"secretsmanager.*.amazonaws.com"}}}]}}]}}}clear(){this.replicas.clear(),this.replicationGroups.clear(),this.proxies.clear(),this.proxyTargets.clear(),this.replicaCounter=0,this.groupCounter=0,this.proxyCounter=0,this.targetCounter=0}}var yS=new Ql;class mf{insights=new Map;slowQueryLogs=new Map;queryMetrics=new Map;reports=new Map;indexRecommendations=new Map;insightsCounter=0;logCounter=0;metricCounter=0;reportCounter=0;recommendationCounter=0;enablePerformanceInsights(n){let i=`pi-${Date.now()}-${this.insightsCounter++}`,s={id:i,name:n.name,databaseIdentifier:n.databaseIdentifier,enabled:!0,retentionPeriod:n.retentionPeriod||7,kmsKeyId:n.kmsKeyId};return this.insights.set(i,s),s}enableSlowQueryLog(n){let i=`slow-query-${Date.now()}-${this.logCounter++}`,s={id:i,name:n.name,databaseIdentifier:n.databaseIdentifier,enabled:!0,logDestination:n.logDestination,cloudwatchLogGroup:n.cloudwatchLogGroup,s3Bucket:n.s3Bucket,s3Prefix:n.s3Bucket?"slow-queries/":void 0,minExecutionTime:n.minExecutionTime||1000};return this.slowQueryLogs.set(i,s),s}recordQueryMetric(n){let i=`metric-${Date.now()}-${this.metricCounter++}`,s={id:i,timestamp:new Date,...n};return this.queryMetrics.set(i,s),s}generatePerformanceReport(n){let i=`report-${Date.now()}-${this.reportCounter++}`,s={avgCPU:Math.random()*60+20,maxCPU:Math.random()*30+70,avgConnections:Math.floor(Math.random()*50+10),maxConnections:Math.floor(Math.random()*50+100),avgReadIOPS:Math.floor(Math.random()*1000+500),avgWriteIOPS:Math.floor(Math.random()*500+200),avgReadThroughput:Math.random()*50+10,avgWriteThroughput:Math.random()*20+5,avgReadLatency:Math.random()*5+1,avgWriteLatency:Math.random()*8+2,cacheHitRatio:Math.random()*10+90,deadlocks:Math.floor(Math.random()*5),longRunningTransactions:Math.floor(Math.random()*10)},o=Array.from(this.queryMetrics.values()),c=o.sort((y,h)=>h.executionCount-y.executionCount).slice(0,10),u=o.filter((y)=>y.avgExecutionTime>1000).sort((y,h)=>h.avgExecutionTime-y.avgExecutionTime).slice(0,10),d=this.generateRecommendations(s,u),g={id:i,name:n.name,databaseIdentifier:n.databaseIdentifier,reportType:n.reportType,metrics:s,topQueries:c,slowQueries:u,recommendations:d,generatedAt:new Date};return this.reports.set(i,g),g}generateRecommendations(n,i){let s=[];if(n.avgCPU>70)s.push({type:"scaling",severity:"high",title:"High CPU Usage",description:`Average CPU usage is ${n.avgCPU.toFixed(1)}%, which is above the recommended threshold of 70%.`,impact:"Performance degradation, increased latency, potential timeouts",effort:"medium"});if(n.cacheHitRatio<95)s.push({type:"configuration",severity:"medium",title:"Low Cache Hit Ratio",description:`Cache hit ratio is ${n.cacheHitRatio.toFixed(1)}%. Consider increasing buffer pool size.`,impact:"Increased disk I/O, slower query performance",effort:"low"});if(n.deadlocks>0)s.push({type:"query",severity:"medium",title:"Deadlocks Detected",description:`${n.deadlocks} deadlock(s) detected. Review transaction isolation levels and query patterns.`,impact:"Transaction failures, application errors",effort:"high"});if(i.length>0)s.push({type:"index",severity:"high",title:"Slow Queries Detected",description:`${i.length} slow queries detected. Consider adding indexes or optimizing queries.`,impact:"High latency, poor user experience",effort:"medium"});if(n.avgReadLatency>10||n.avgWriteLatency>10)s.push({type:"scaling",severity:"high",title:"High I/O Latency",description:"Read or write latency is high. Consider upgrading to Provisioned IOPS or moving to a larger instance.",impact:"Slow query execution, application timeouts",effort:"medium"});return s}analyzeQuery(n){let i=`analysis-${Date.now()}-${Math.random().toString(36).slice(2,9)}`,s=[{id:1,operation:"Seq Scan",table:"users",rows:1e4,cost:850.5,children:[]}],o=[];if(n.toLowerCase().includes("select *"))o.push({type:"full_table_scan",severity:"warning",description:"Query selects all columns. Consider selecting only required columns."});if(!n.toLowerCase().includes("where")&&n.toLowerCase().includes("select"))o.push({type:"full_table_scan",severity:"critical",description:"Query has no WHERE clause and may scan entire table."});return{id:i,queryId:i,sql:n,executionPlan:s,bottlenecks:o,recommendations:["Add appropriate indexes on WHERE clause columns","Consider using EXPLAIN ANALYZE to get actual execution statistics","Review and optimize JOIN conditions"],estimatedCost:s[0].cost}}recommendIndex(n){let i=`index-rec-${Date.now()}-${this.recommendationCounter++}`,s=`idx_${n.tableName}_${n.columns.join("_")}`,o={id:i,tableName:n.tableName,columns:n.columns,reason:n.reason,estimatedImprovement:n.estimatedImprovement||50,estimatedSize:n.columns.length*10,createSQL:`CREATE INDEX ${s} ON ${n.tableName} (${n.columns.join(", ")});`};return this.indexRecommendations.set(i,o),o}getInsights(n){return this.insights.get(n)}listInsights(){return Array.from(this.insights.values())}getSlowQueryLog(n){return this.slowQueryLogs.get(n)}listSlowQueryLogs(){return Array.from(this.slowQueryLogs.values())}getReport(n){return this.reports.get(n)}listReports(){return Array.from(this.reports.values())}listIndexRecommendations(){return Array.from(this.indexRecommendations.values())}generatePerformanceInsightsCF(n){return{EnablePerformanceInsights:n.enabled,PerformanceInsightsRetentionPeriod:n.retentionPeriod,...n.kmsKeyId&&{PerformanceInsightsKMSKeyId:n.kmsKeyId}}}generateSlowQueryAlarmCF(n){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:n.alarmName,AlarmDescription:"Alert when slow queries exceed threshold",MetricName:"SlowQueryCount",Namespace:"AWS/RDS",Statistic:"Sum",Period:300,EvaluationPeriods:1,Threshold:n.threshold,ComparisonOperator:"GreaterThanThreshold",...n.snsTopicArn&&{AlarmActions:[n.snsTopicArn]}}}}clear(){this.insights.clear(),this.slowQueryLogs.clear(),this.queryMetrics.clear(),this.reports.clear(),this.indexRecommendations.clear(),this.insightsCounter=0,this.logCounter=0,this.metricCounter=0,this.reportCounter=0,this.recommendationCounter=0}}var SE=new mf;class ff{users=new Map;roles=new Map;audits=new Map;userCounter=0;roleCounter=0;auditCounter=0;createUser(n){let i=`db-user-${Date.now()}-${this.userCounter++}`,s={id:i,createdAt:new Date,...n};return this.users.set(i,s),s}createReadOnlyUser(n){let i=n.tables?n.tables.map((s)=>({database:n.database,table:s,privileges:["SELECT"]})):[{database:n.database,privileges:["SELECT"]}];return this.createUser({username:n.username,database:n.database,privileges:i,passwordSecretArn:n.passwordSecretArn,rotationEnabled:!0,rotationDays:90})}createReadWriteUser(n){let i=n.tables?n.tables.map((s)=>({database:n.database,table:s,privileges:["SELECT","INSERT","UPDATE","DELETE"]})):[{database:n.database,privileges:["SELECT","INSERT","UPDATE","DELETE"]}];return this.createUser({username:n.username,database:n.database,privileges:i,passwordSecretArn:n.passwordSecretArn,rotationEnabled:!0,rotationDays:60})}createAdminUser(n){return this.createUser({username:n.username,database:n.database,privileges:[{database:n.database,privileges:["ALL"]}],passwordSecretArn:n.passwordSecretArn,rotationEnabled:!0,rotationDays:30})}createApplicationUser(n){let i=n.tables.map((s)=>({database:n.database,table:s.name,privileges:s.privileges}));return this.createUser({username:n.username,database:n.database,privileges:i,passwordSecretArn:n.passwordSecretArn,rotationEnabled:!0,rotationDays:90})}createRole(n){let i=`role-${Date.now()}-${this.roleCounter++}`,s={id:i,users:[],...n};return this.roles.set(i,s),s}assignUserToRole(n,i){let s=this.users.get(n),o=this.roles.get(i);if(!s)throw Error(`User not found: ${n}`);if(!o)throw Error(`Role not found: ${i}`);o.users.push(n);for(let c of o.privileges){let u=s.privileges.find((d)=>d.database===c.database&&d.table===c.table);if(u)u.privileges=Array.from(new Set([...u.privileges,...c.privileges]));else s.privileges.push({...c})}}grantPrivileges(n,i){let s=this.users.get(n);if(!s)return{success:!1,message:"User not found"};for(let o of i){let c=s.privileges.find((u)=>u.database===o.database&&u.table===o.table);if(c)c.privileges=Array.from(new Set([...c.privileges,...o.privileges]));else s.privileges.push(o)}return this.auditAccess({username:s.username,action:"GRANT",database:i[0]?.database,table:i[0]?.table,success:!0}),{success:!0,message:"Privileges granted successfully"}}revokePrivileges(n,i){let s=this.users.get(n);if(!s)return{success:!1,message:"User not found"};for(let o of i){let c=s.privileges.findIndex((u)=>u.database===o.database&&u.table===o.table);if(c!==-1){let u=s.privileges[c];if(u.privileges=u.privileges.filter((d)=>!o.privileges.includes(d)),u.privileges.length===0)s.privileges.splice(c,1)}}return this.auditAccess({username:s.username,action:"REVOKE",database:i[0]?.database,table:i[0]?.table,success:!0}),{success:!0,message:"Privileges revoked successfully"}}rotatePassword(n){let i=this.users.get(n);if(!i)return{success:!1};let s=`arn:aws:secretsmanager:us-east-1:123456789012:secret:db-${i.username}-${Date.now()}`;return i.passwordSecretArn=s,i.lastRotated=new Date,console.log(`Password rotated for user: ${i.username}`),{success:!0,newSecretArn:s}}needsPasswordRotation(n){let i=this.users.get(n);if(!i||!i.rotationEnabled||!i.lastRotated||!i.rotationDays)return!1;return(Date.now()-i.lastRotated.getTime())/86400000>=i.rotationDays}auditAccess(n){let i=`audit-${Date.now()}-${this.auditCounter++}`,s={id:i,timestamp:new Date,...n};return this.audits.set(i,s),s}getUserAccessHistory(n,i=100){return Array.from(this.audits.values()).filter((s)=>s.username===n).sort((s,o)=>o.timestamp.getTime()-s.timestamp.getTime()).slice(0,i)}getFailedLoginAttempts(n,i=24){let s=Date.now()-i*60*60*1000;return Array.from(this.audits.values()).filter((o)=>o.username===n&&o.action==="LOGIN"&&!o.success&&o.timestamp.getTime()>s)}generateCreateUserSQL(n,i="postgres"){let s=[];if(i==="postgres"){s.push(`CREATE USER ${n.username} WITH PASSWORD '${n.passwordSecretArn}';`);for(let o of n.privileges)if(o.privileges.includes("ALL"))s.push(`GRANT ALL PRIVILEGES ON DATABASE ${o.database} TO ${n.username};`);else{let c=o.privileges.join(", ");if(o.table)s.push(`GRANT ${c} ON ${o.database}.${o.table} TO ${n.username};`);else s.push(`GRANT ${c} ON DATABASE ${o.database} TO ${n.username};`)}}else{s.push(`CREATE USER '${n.username}'@'%' IDENTIFIED BY '${n.passwordSecretArn}';`);for(let o of n.privileges){let c=o.privileges.includes("ALL")?"ALL PRIVILEGES":o.privileges.join(", "),u=o.table?`${o.database}.${o.table}`:`${o.database}.*`;s.push(`GRANT ${c} ON ${u} TO '${n.username}'@'%';`)}s.push("FLUSH PRIVILEGES;")}return s.join(`
3724
+ `)}getUser(n){return this.users.get(n)}listUsers(){return Array.from(this.users.values())}getRole(n){return this.roles.get(n)}listRoles(){return Array.from(this.roles.values())}clear(){this.users.clear(),this.roles.clear(),this.audits.clear(),this.userCounter=0,this.roleCounter=0,this.auditCounter=0}}var IE=new ff;class hf{rotations=new Map;schedules=new Map;rotationCounter=0;scheduleCounter=0;createRotation(n){let i=`rotation-${Date.now()}-${this.rotationCounter++}`,s={id:i,...n};return this.rotations.set(i,s),s}enableRDSRotation(n){let i=this.createRotation({secretId:n.secretId,secretType:"rds_credentials",rotationEnabled:!0,rotationDays:n.rotationDays||30,rotationLambdaArn:this.generateRDSRotationLambdaArn(n.engine)});return i.nextRotation=new Date(Date.now()+i.rotationDays*24*60*60*1000),i}enableAPIKeyRotation(n){return this.createRotation({secretId:n.secretId,secretType:"api_key",rotationEnabled:!0,rotationDays:n.rotationDays||90,rotationLambdaArn:n.rotationLambdaArn})}enableOAuthRotation(n){return this.createRotation({secretId:n.secretId,secretType:"oauth_token",rotationEnabled:!0,rotationDays:n.rotationDays||60,rotationLambdaArn:n.rotationLambdaArn})}enableSSHKeyRotation(n){return this.createRotation({secretId:n.secretId,secretType:"ssh_key",rotationEnabled:!0,rotationDays:n.rotationDays||180,rotationLambdaArn:n.rotationLambdaArn})}createSchedule(n){let i=`schedule-${Date.now()}-${this.scheduleCounter++}`,s={id:i,...n};return this.schedules.set(i,s),s}async executeRotation(n){let i=this.rotations.get(n);if(!i)throw Error(`Rotation not found: ${n}`);console.log(`
3727
3725
  Executing rotation for secret: ${i.secretId}`),console.log(`Secret type: ${i.secretType}`),console.log(`Rotation interval: ${i.rotationDays} days`);try{console.log(`
3728
3726
  Rotation steps:`),console.log("1. Creating new secret version...");let s=`v${Date.now()}`;console.log("2. Testing new credentials..."),console.log("3. Updating application references..."),console.log("4. Marking previous version as deprecated...");let o=i.versionStages?.[0]||"v1";return console.log("5. Finalizing rotation..."),i.lastRotated=new Date,i.nextRotation=new Date(Date.now()+i.rotationDays*24*60*60*1000),console.log(`
3729
3727
  ✓ Rotation completed successfully`),console.log(` New version: ${s}`),console.log(` Next rotation: ${i.nextRotation.toISOString()}`),{success:!0,secretId:i.secretId,oldVersion:o,newVersion:s,rotatedAt:new Date}}catch(s){return console.error(`
3730
- ✗ Rotation failed:`,s),{success:!1,secretId:i.secretId,oldVersion:"unknown",newVersion:"unknown",rotatedAt:new Date,error:s instanceof Error?s.message:String(s)}}}needsRotation(n){let i=this.rotations.get(n);if(!i||!i.rotationEnabled)return!1;if(!i.lastRotated)return!0;return(Date.now()-i.lastRotated.getTime())/86400000>=i.rotationDays}getSecretsNeedingRotation(){return Array.from(this.rotations.values()).filter((n)=>this.needsRotation(n.id))}generateRDSRotationLambdaArn(n){let i={postgres:"SecretsManagerRDSPostgreSQLRotationSingleUser",mysql:"SecretsManagerRDSMySQLRotationSingleUser",sqlserver:"SecretsManagerRDSSQLServerRotationSingleUser",oracle:"SecretsManagerRDSOracleRotationSingleUser"};return`arn:aws:lambda:us-east-1:123456789012:function:${i[n]||i.postgres}`}getRotation(n){return this.rotations.get(n)}listRotations(){return Array.from(this.rotations.values())}getSchedule(n){return this.schedules.get(n)}listSchedules(){return Array.from(this.schedules.values())}generateRotationCF(n){return{RotationEnabled:n.rotationEnabled,RotationRules:{AutomaticallyAfterDays:n.rotationDays},...n.rotationLambdaArn&&{RotationLambdaARN:n.rotationLambdaArn}}}generateRotationLambdaCF(n){return{Type:"AWS::Lambda::Function",Properties:{FunctionName:n.functionName,Runtime:"python3.11",Handler:"lambda_function.lambda_handler",Role:{"Fn::GetAtt":["RotationLambdaRole","Arn"]},Timeout:30,Environment:{Variables:{SECRETS_MANAGER_ENDPOINT:"https://secretsmanager.us-east-1.amazonaws.com"}},...n.vpcConfig&&{VpcConfig:{SubnetIds:n.vpcConfig.subnetIds,SecurityGroupIds:n.vpcConfig.securityGroupIds}}}}}generateRotationLambdaRoleCF(){return{Type:"AWS::IAM::Role",Properties:{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","arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"],Policies:[{PolicyName:"SecretsRotationPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:DescribeSecret","secretsmanager:GetSecretValue","secretsmanager:PutSecretValue","secretsmanager:UpdateSecretVersionStage"],Resource:"*"},{Effect:"Allow",Action:["secretsmanager:GetRandomPassword"],Resource:"*"}]}}]}}}generateRotationScheduleCF(n){return{Type:"AWS::Events::Rule",Properties:{Name:n.name,Description:`Rotation schedule for ${n.secrets.length} secrets`,ScheduleExpression:n.schedule,State:n.enabled?"ENABLED":"DISABLED",Targets:[{Arn:{"Fn::GetAtt":["RotationStateMachine","Arn"]},RoleArn:{"Fn::GetAtt":["EventBridgeRotationRole","Arn"]},Input:JSON.stringify({secrets:n.secrets})}]}}}clear(){this.rotations.clear(),this.schedules.clear(),this.rotationCounter=0,this.scheduleCounter=0}}var cE=new of;class xl{versions=new Map;audits=new Map;externalManagers=new Map;replications=new Map;policies=new Map;versionCounter=0;auditCounter=0;managerCounter=0;replicationCounter=0;policyCounter=0;createVersion(n){let i=`version-${Date.now()}-${this.versionCounter++}`,s={id:i,...n};return this.versions.set(i,s),this.auditAction({secretId:n.secretId,action:"CREATE",actor:"system",versionId:n.versionId,success:!0}),s}getVersionByStage(n,i){return Array.from(this.versions.values()).find((s)=>s.secretId===n&&s.versionStages.includes(i))}listVersions(n){return Array.from(this.versions.values()).filter((i)=>i.secretId===n).sort((i,s)=>s.createdAt.getTime()-i.createdAt.getTime())}deprecateVersion(n){let i=Array.from(this.versions.values()).find((s)=>s.versionId===n);if(i)i.deprecatedAt=new Date,i.versionStages=i.versionStages.filter((s)=>s!=="AWSCURRENT"),this.auditAction({secretId:i.secretId,action:"UPDATE",actor:"system",versionId:n,success:!0})}restoreVersion(n){let i=Array.from(this.versions.values()).find((s)=>s.versionId===n);if(i)Array.from(this.versions.values()).filter((s)=>s.secretId===i.secretId&&s.versionId!==n).forEach((s)=>{s.versionStages=s.versionStages.filter((o)=>o!=="AWSCURRENT")}),i.versionStages.push("AWSCURRENT"),i.deprecatedAt=void 0,this.auditAction({secretId:i.secretId,action:"RESTORE",actor:"system",versionId:n,success:!0})}auditAction(n){let i=`audit-${Date.now()}-${this.auditCounter++}`,s={id:i,timestamp:new Date,...n};return this.audits.set(i,s),s}getAuditTrail(n,i=100){return Array.from(this.audits.values()).filter((s)=>s.secretId===n).sort((s,o)=>o.timestamp.getTime()-s.timestamp.getTime()).slice(0,i)}getFailedAccesses(n,i=24){let s=Date.now()-i*60*60*1000;return Array.from(this.audits.values()).filter((o)=>o.secretId===n&&!o.success&&o.timestamp.getTime()>s)}registerExternalManager(n){let i=`ext-manager-${Date.now()}-${this.managerCounter++}`,s={id:i,...n};return this.externalManagers.set(i,s),s}registerVault(n){return this.registerExternalManager({type:"vault",name:n.name,endpoint:n.endpoint,authentication:{type:n.token?"token":"iam",credentials:n.token?{token:n.token}:void 0,roleArn:n.roleArn},syncEnabled:n.syncEnabled||!1,syncInterval:60})}registerOnePassword(n){return this.registerExternalManager({type:"onepassword",name:n.name,endpoint:n.endpoint||"https://my.1password.com",authentication:{type:"apikey",credentials:{apiKey:n.apiKey}},syncEnabled:n.syncEnabled||!1,syncInterval:30})}enableReplication(n){let i=`replication-${Date.now()}-${this.replicationCounter++}`,s={id:i,secretId:n.secretId,sourceRegion:n.sourceRegion,replicaRegions:n.replicaRegions,kmsKeyIds:n.kmsKeyIds,status:"replicating"};return this.replications.set(i,s),this.auditAction({secretId:n.secretId,action:"REPLICATE",actor:"system",success:!0}),setTimeout(()=>{s.status="completed"},100),s}createPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,secretId:n.secretId,policy:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:n.allowedPrincipals},Action:n.allowedActions,Resource:"*"}]}};return this.policies.set(i,s),s}createCrossAccountPolicy(n){let i=n.roleNames.map((s)=>`arn:aws:iam::${n.accountId}:role/${s}`);return this.createPolicy({secretId:n.secretId,allowedPrincipals:i,allowedActions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"]})}getVersion(n){return this.versions.get(n)}getExternalManager(n){return this.externalManagers.get(n)}listExternalManagers(){return Array.from(this.externalManagers.values())}getReplication(n){return this.replications.get(n)}listReplications(){return Array.from(this.replications.values())}generateSecretCF(n){return{Type:"AWS::SecretsManager::Secret",Properties:{Name:n.name,Description:n.description,...n.kmsKeyId&&{KmsKeyId:n.kmsKeyId},...n.replicaRegions&&{ReplicaRegions:n.replicaRegions.map((i)=>({Region:i}))}}}}generateSecretPolicyCF(n){return{Type:"AWS::SecretsManager::ResourcePolicy",Properties:{SecretId:n.secretId,ResourcePolicy:n.policy}}}clear(){this.versions.clear(),this.audits.clear(),this.externalManagers.clear(),this.replications.clear(),this.policies.clear(),this.versionCounter=0,this.auditCounter=0,this.managerCounter=0,this.replicationCounter=0,this.policyCounter=0}}var aS=new xl;class af{certificates=new Map;renewals=new Map;validations=new Map;monitors=new Map;alerts=new Map;certificateCounter=0;renewalCounter=0;validationCounter=0;monitorCounter=0;alertCounter=0;requestCertificate(n){let i=`cert-${Date.now()}-${this.certificateCounter++}`,s=`arn:aws:acm:us-east-1:123456789012:certificate/${i}`,o={id:i,arn:s,domainName:n.domainName,subjectAlternativeNames:n.subjectAlternativeNames,validationMethod:n.validationMethod||"DNS",status:"PENDING_VALIDATION"};return this.certificates.set(i,o),this.createValidation(o),o}requestWildcardCertificate(n){let i=[];if(n.includeApex)i.push(n.domainName.replace("*.",""));return this.requestCertificate({domainName:n.domainName,subjectAlternativeNames:i.length>0?i:void 0,validationMethod:"DNS"})}requestMultiDomainCertificate(n){return this.requestCertificate({domainName:n.primaryDomain,subjectAlternativeNames:n.additionalDomains,validationMethod:n.validationMethod||"DNS"})}createValidation(n){let i={domainName:n.domainName,validationMethod:n.validationMethod,validationStatus:"PENDING"};if(n.validationMethod==="DNS")i.resourceRecords=[{name:`_${Math.random().toString(36).slice(2)}.${n.domainName}`,type:"CNAME",value:`_${Math.random().toString(36).slice(2)}.acm-validations.aws.`}];else i.validationEmails=[`admin@${n.domainName}`,`administrator@${n.domainName}`,`hostmaster@${n.domainName}`];return this.validations.set(n.id,i),i}validateCertificate(n){let i=this.certificates.get(n),s=this.validations.get(n);if(!i||!s)return{success:!1,message:"Certificate or validation not found"};return s.validationStatus="SUCCESS",i.status="ISSUED",i.issuedAt=new Date,i.expiresAt=new Date(Date.now()+31536000000),i.renewalEligibility=!0,i.issuer="Amazon",{success:!0,message:"Certificate validated and issued successfully"}}enableAutoRenewal(n){let i=`renewal-${Date.now()}-${this.renewalCounter++}`,s={id:i,certificateArn:n.certificateArn,autoRenew:!0,renewBeforeDays:n.renewBeforeDays||30};return this.renewals.set(i,s),s}async renewCertificate(n){let i=this.renewals.get(n);if(!i)return{success:!1,message:"Renewal configuration not found"};let s=Array.from(this.certificates.values()).find((o)=>o.arn===i.certificateArn);if(!s)return{success:!1,message:"Certificate not found"};console.log(`
3728
+ ✗ Rotation failed:`,s),{success:!1,secretId:i.secretId,oldVersion:"unknown",newVersion:"unknown",rotatedAt:new Date,error:s instanceof Error?s.message:String(s)}}}needsRotation(n){let i=this.rotations.get(n);if(!i||!i.rotationEnabled)return!1;if(!i.lastRotated)return!0;return(Date.now()-i.lastRotated.getTime())/86400000>=i.rotationDays}getSecretsNeedingRotation(){return Array.from(this.rotations.values()).filter((n)=>this.needsRotation(n.id))}generateRDSRotationLambdaArn(n){let i={postgres:"SecretsManagerRDSPostgreSQLRotationSingleUser",mysql:"SecretsManagerRDSMySQLRotationSingleUser",sqlserver:"SecretsManagerRDSSQLServerRotationSingleUser",oracle:"SecretsManagerRDSOracleRotationSingleUser"};return`arn:aws:lambda:us-east-1:123456789012:function:${i[n]||i.postgres}`}getRotation(n){return this.rotations.get(n)}listRotations(){return Array.from(this.rotations.values())}getSchedule(n){return this.schedules.get(n)}listSchedules(){return Array.from(this.schedules.values())}generateRotationCF(n){return{RotationEnabled:n.rotationEnabled,RotationRules:{AutomaticallyAfterDays:n.rotationDays},...n.rotationLambdaArn&&{RotationLambdaARN:n.rotationLambdaArn}}}generateRotationLambdaCF(n){return{Type:"AWS::Lambda::Function",Properties:{FunctionName:n.functionName,Runtime:"python3.11",Handler:"lambda_function.lambda_handler",Role:{"Fn::GetAtt":["RotationLambdaRole","Arn"]},Timeout:30,Environment:{Variables:{SECRETS_MANAGER_ENDPOINT:"https://secretsmanager.us-east-1.amazonaws.com"}},...n.vpcConfig&&{VpcConfig:{SubnetIds:n.vpcConfig.subnetIds,SecurityGroupIds:n.vpcConfig.securityGroupIds}}}}}generateRotationLambdaRoleCF(){return{Type:"AWS::IAM::Role",Properties:{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","arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"],Policies:[{PolicyName:"SecretsRotationPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:DescribeSecret","secretsmanager:GetSecretValue","secretsmanager:PutSecretValue","secretsmanager:UpdateSecretVersionStage"],Resource:"*"},{Effect:"Allow",Action:["secretsmanager:GetRandomPassword"],Resource:"*"}]}}]}}}generateRotationScheduleCF(n){return{Type:"AWS::Events::Rule",Properties:{Name:n.name,Description:`Rotation schedule for ${n.secrets.length} secrets`,ScheduleExpression:n.schedule,State:n.enabled?"ENABLED":"DISABLED",Targets:[{Arn:{"Fn::GetAtt":["RotationStateMachine","Arn"]},RoleArn:{"Fn::GetAtt":["EventBridgeRotationRole","Arn"]},Input:JSON.stringify({secrets:n.secrets})}]}}}clear(){this.rotations.clear(),this.schedules.clear(),this.rotationCounter=0,this.scheduleCounter=0}}var bE=new hf;class Hl{versions=new Map;audits=new Map;externalManagers=new Map;replications=new Map;policies=new Map;versionCounter=0;auditCounter=0;managerCounter=0;replicationCounter=0;policyCounter=0;createVersion(n){let i=`version-${Date.now()}-${this.versionCounter++}`,s={id:i,...n};return this.versions.set(i,s),this.auditAction({secretId:n.secretId,action:"CREATE",actor:"system",versionId:n.versionId,success:!0}),s}getVersionByStage(n,i){return Array.from(this.versions.values()).find((s)=>s.secretId===n&&s.versionStages.includes(i))}listVersions(n){return Array.from(this.versions.values()).filter((i)=>i.secretId===n).sort((i,s)=>s.createdAt.getTime()-i.createdAt.getTime())}deprecateVersion(n){let i=Array.from(this.versions.values()).find((s)=>s.versionId===n);if(i)i.deprecatedAt=new Date,i.versionStages=i.versionStages.filter((s)=>s!=="AWSCURRENT"),this.auditAction({secretId:i.secretId,action:"UPDATE",actor:"system",versionId:n,success:!0})}restoreVersion(n){let i=Array.from(this.versions.values()).find((s)=>s.versionId===n);if(i)Array.from(this.versions.values()).filter((s)=>s.secretId===i.secretId&&s.versionId!==n).forEach((s)=>{s.versionStages=s.versionStages.filter((o)=>o!=="AWSCURRENT")}),i.versionStages.push("AWSCURRENT"),i.deprecatedAt=void 0,this.auditAction({secretId:i.secretId,action:"RESTORE",actor:"system",versionId:n,success:!0})}auditAction(n){let i=`audit-${Date.now()}-${this.auditCounter++}`,s={id:i,timestamp:new Date,...n};return this.audits.set(i,s),s}getAuditTrail(n,i=100){return Array.from(this.audits.values()).filter((s)=>s.secretId===n).sort((s,o)=>o.timestamp.getTime()-s.timestamp.getTime()).slice(0,i)}getFailedAccesses(n,i=24){let s=Date.now()-i*60*60*1000;return Array.from(this.audits.values()).filter((o)=>o.secretId===n&&!o.success&&o.timestamp.getTime()>s)}registerExternalManager(n){let i=`ext-manager-${Date.now()}-${this.managerCounter++}`,s={id:i,...n};return this.externalManagers.set(i,s),s}registerVault(n){return this.registerExternalManager({type:"vault",name:n.name,endpoint:n.endpoint,authentication:{type:n.token?"token":"iam",credentials:n.token?{token:n.token}:void 0,roleArn:n.roleArn},syncEnabled:n.syncEnabled||!1,syncInterval:60})}registerOnePassword(n){return this.registerExternalManager({type:"onepassword",name:n.name,endpoint:n.endpoint||"https://my.1password.com",authentication:{type:"apikey",credentials:{apiKey:n.apiKey}},syncEnabled:n.syncEnabled||!1,syncInterval:30})}enableReplication(n){let i=`replication-${Date.now()}-${this.replicationCounter++}`,s={id:i,secretId:n.secretId,sourceRegion:n.sourceRegion,replicaRegions:n.replicaRegions,kmsKeyIds:n.kmsKeyIds,status:"replicating"};return this.replications.set(i,s),this.auditAction({secretId:n.secretId,action:"REPLICATE",actor:"system",success:!0}),setTimeout(()=>{s.status="completed"},100),s}createPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,secretId:n.secretId,policy:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:n.allowedPrincipals},Action:n.allowedActions,Resource:"*"}]}};return this.policies.set(i,s),s}createCrossAccountPolicy(n){let i=n.roleNames.map((s)=>`arn:aws:iam::${n.accountId}:role/${s}`);return this.createPolicy({secretId:n.secretId,allowedPrincipals:i,allowedActions:["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"]})}getVersion(n){return this.versions.get(n)}getExternalManager(n){return this.externalManagers.get(n)}listExternalManagers(){return Array.from(this.externalManagers.values())}getReplication(n){return this.replications.get(n)}listReplications(){return Array.from(this.replications.values())}generateSecretCF(n){return{Type:"AWS::SecretsManager::Secret",Properties:{Name:n.name,Description:n.description,...n.kmsKeyId&&{KmsKeyId:n.kmsKeyId},...n.replicaRegions&&{ReplicaRegions:n.replicaRegions.map((i)=>({Region:i}))}}}}generateSecretPolicyCF(n){return{Type:"AWS::SecretsManager::ResourcePolicy",Properties:{SecretId:n.secretId,ResourcePolicy:n.policy}}}clear(){this.versions.clear(),this.audits.clear(),this.externalManagers.clear(),this.replications.clear(),this.policies.clear(),this.versionCounter=0,this.auditCounter=0,this.managerCounter=0,this.replicationCounter=0,this.policyCounter=0}}var SS=new Hl;class Af{certificates=new Map;renewals=new Map;validations=new Map;monitors=new Map;alerts=new Map;certificateCounter=0;renewalCounter=0;validationCounter=0;monitorCounter=0;alertCounter=0;requestCertificate(n){let i=`cert-${Date.now()}-${this.certificateCounter++}`,s=`arn:aws:acm:us-east-1:123456789012:certificate/${i}`,o={id:i,arn:s,domainName:n.domainName,subjectAlternativeNames:n.subjectAlternativeNames,validationMethod:n.validationMethod||"DNS",status:"PENDING_VALIDATION"};return this.certificates.set(i,o),this.createValidation(o),o}requestWildcardCertificate(n){let i=[];if(n.includeApex)i.push(n.domainName.replace("*.",""));return this.requestCertificate({domainName:n.domainName,subjectAlternativeNames:i.length>0?i:void 0,validationMethod:"DNS"})}requestMultiDomainCertificate(n){return this.requestCertificate({domainName:n.primaryDomain,subjectAlternativeNames:n.additionalDomains,validationMethod:n.validationMethod||"DNS"})}createValidation(n){let i={domainName:n.domainName,validationMethod:n.validationMethod,validationStatus:"PENDING"};if(n.validationMethod==="DNS")i.resourceRecords=[{name:`_${Math.random().toString(36).slice(2)}.${n.domainName}`,type:"CNAME",value:`_${Math.random().toString(36).slice(2)}.acm-validations.aws.`}];else i.validationEmails=[`admin@${n.domainName}`,`administrator@${n.domainName}`,`hostmaster@${n.domainName}`];return this.validations.set(n.id,i),i}validateCertificate(n){let i=this.certificates.get(n),s=this.validations.get(n);if(!i||!s)return{success:!1,message:"Certificate or validation not found"};return s.validationStatus="SUCCESS",i.status="ISSUED",i.issuedAt=new Date,i.expiresAt=new Date(Date.now()+31536000000),i.renewalEligibility=!0,i.issuer="Amazon",{success:!0,message:"Certificate validated and issued successfully"}}enableAutoRenewal(n){let i=`renewal-${Date.now()}-${this.renewalCounter++}`,s={id:i,certificateArn:n.certificateArn,autoRenew:!0,renewBeforeDays:n.renewBeforeDays||30};return this.renewals.set(i,s),s}async renewCertificate(n){let i=this.renewals.get(n);if(!i)return{success:!1,message:"Renewal configuration not found"};let s=Array.from(this.certificates.values()).find((o)=>o.arn===i.certificateArn);if(!s)return{success:!1,message:"Certificate not found"};console.log(`
3731
3729
  Renewing certificate: ${s.domainName}`),console.log(`Certificate ARN: ${s.arn}`);try{return console.log(`
3732
3730
  1. Requesting new certificate...`),console.log("2. Validating domain ownership..."),console.log("3. Issuing renewed certificate..."),console.log("4. Updating resource associations..."),s.issuedAt=new Date,s.expiresAt=new Date(Date.now()+31536000000),i.lastRenewal=new Date,i.renewalStatus="success",i.nextRenewal=new Date(s.expiresAt.getTime()-i.renewBeforeDays*24*60*60*1000),console.log(`
3733
- ✓ Certificate renewed successfully`),console.log(` New expiration: ${s.expiresAt.toISOString()}`),console.log(` Next renewal: ${i.nextRenewal.toISOString()}`),{success:!0,message:"Certificate renewed successfully"}}catch(o){return i.renewalStatus="failed",this.createAlert({certificateArn:s.arn,alertType:"renewal_failed",severity:"critical",message:`Certificate renewal failed: ${o}`}),{success:!1,message:o instanceof Error?o.message:String(o)}}}createMonitor(n){let i=`monitor-${Date.now()}-${this.monitorCounter++}`,s={id:i,...n};return this.monitors.set(i,s),s}checkExpiration(){let n=[],i=Date.now();for(let s of this.certificates.values()){if(!s.expiresAt)continue;let o=(s.expiresAt.getTime()-i)/86400000;if(o<0)n.push(this.createAlert({certificateArn:s.arn,alertType:"expired",severity:"critical",message:`Certificate has expired for ${s.domainName}`}));else if(o<30)n.push(this.createAlert({certificateArn:s.arn,alertType:"expiring_soon",severity:o<7?"critical":"warning",message:`Certificate expiring in ${Math.floor(o)} days for ${s.domainName}`}))}return n}createAlert(n){let i=`alert-${Date.now()}-${this.alertCounter++}`,s={id:i,timestamp:new Date,acknowledged:!1,...n};return this.alerts.set(i,s),s}acknowledgeAlert(n){let i=this.alerts.get(n);if(i)i.acknowledged=!0}getCertificate(n){return this.certificates.get(n)}listCertificates(){return Array.from(this.certificates.values())}getExpiringCertificates(n=30){let i=Date.now()+n*24*60*60*1000;return Array.from(this.certificates.values()).filter((s)=>s.expiresAt&&s.expiresAt.getTime()<i)}getValidation(n){return this.validations.get(n)}getRenewal(n){return this.renewals.get(n)}listRenewals(){return Array.from(this.renewals.values())}listAlerts(n=!1){return Array.from(this.alerts.values()).filter((i)=>i.acknowledged===n)}generateCertificateCF(n){return{Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:n.domainName,...n.subjectAlternativeNames&&{SubjectAlternativeNames:n.subjectAlternativeNames},ValidationMethod:n.validationMethod}}}generateExpirationAlarmCF(n){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:n.alarmName,AlarmDescription:`Certificate expiring in ${n.daysBeforeExpiration} days`,MetricName:"DaysToExpiry",Namespace:"AWS/CertificateManager",Statistic:"Minimum",Period:86400,EvaluationPeriods:1,Threshold:n.daysBeforeExpiration,ComparisonOperator:"LessThanThreshold",Dimensions:[{Name:"CertificateArn",Value:n.certificateArn}],...n.snsTopicArn&&{AlarmActions:[n.snsTopicArn]}}}}clear(){this.certificates.clear(),this.renewals.clear(),this.validations.clear(),this.monitors.clear(),this.alerts.clear(),this.certificateCounter=0,this.renewalCounter=0,this.validationCounter=0,this.monitorCounter=0,this.alertCounter=0}}var dE=new af;class cf{scans=new Map;findings=new Map;reports=new Map;complianceChecks=new Map;postures=new Map;scanCounter=0;findingCounter=0;reportCounter=0;checkCounter=0;postureCounter=0;createScan(n){let i=`scan-${Date.now()}-${this.scanCounter++}`,s={id:i,status:"queued",findings:[],...n};return this.scans.set(i,s),s}createContainerScan(n){return this.createScan({name:n.name,scanType:"container_image",target:{type:"ecr_image",identifier:n.imageUri,region:n.region||"us-east-1"}})}createLambdaScan(n){return this.createScan({name:n.name,scanType:"vulnerability",target:{type:"lambda",identifier:n.functionName,region:n.region||"us-east-1"}})}createSecretsDetectionScan(n){return this.createScan({name:n.name,scanType:"secrets_detection",target:{type:"repository",identifier:n.repositoryUrl}})}async executeScan(n){let i=this.scans.get(n);if(!i)throw Error(`Scan not found: ${n}`);console.log(`
3731
+ ✓ Certificate renewed successfully`),console.log(` New expiration: ${s.expiresAt.toISOString()}`),console.log(` Next renewal: ${i.nextRenewal.toISOString()}`),{success:!0,message:"Certificate renewed successfully"}}catch(o){return i.renewalStatus="failed",this.createAlert({certificateArn:s.arn,alertType:"renewal_failed",severity:"critical",message:`Certificate renewal failed: ${o}`}),{success:!1,message:o instanceof Error?o.message:String(o)}}}createMonitor(n){let i=`monitor-${Date.now()}-${this.monitorCounter++}`,s={id:i,...n};return this.monitors.set(i,s),s}checkExpiration(){let n=[],i=Date.now();for(let s of this.certificates.values()){if(!s.expiresAt)continue;let o=(s.expiresAt.getTime()-i)/86400000;if(o<0)n.push(this.createAlert({certificateArn:s.arn,alertType:"expired",severity:"critical",message:`Certificate has expired for ${s.domainName}`}));else if(o<30)n.push(this.createAlert({certificateArn:s.arn,alertType:"expiring_soon",severity:o<7?"critical":"warning",message:`Certificate expiring in ${Math.floor(o)} days for ${s.domainName}`}))}return n}createAlert(n){let i=`alert-${Date.now()}-${this.alertCounter++}`,s={id:i,timestamp:new Date,acknowledged:!1,...n};return this.alerts.set(i,s),s}acknowledgeAlert(n){let i=this.alerts.get(n);if(i)i.acknowledged=!0}getCertificate(n){return this.certificates.get(n)}listCertificates(){return Array.from(this.certificates.values())}getExpiringCertificates(n=30){let i=Date.now()+n*24*60*60*1000;return Array.from(this.certificates.values()).filter((s)=>s.expiresAt&&s.expiresAt.getTime()<i)}getValidation(n){return this.validations.get(n)}getRenewal(n){return this.renewals.get(n)}listRenewals(){return Array.from(this.renewals.values())}listAlerts(n=!1){return Array.from(this.alerts.values()).filter((i)=>i.acknowledged===n)}generateCertificateCF(n){return{Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:n.domainName,...n.subjectAlternativeNames&&{SubjectAlternativeNames:n.subjectAlternativeNames},ValidationMethod:n.validationMethod}}}generateExpirationAlarmCF(n){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:n.alarmName,AlarmDescription:`Certificate expiring in ${n.daysBeforeExpiration} days`,MetricName:"DaysToExpiry",Namespace:"AWS/CertificateManager",Statistic:"Minimum",Period:86400,EvaluationPeriods:1,Threshold:n.daysBeforeExpiration,ComparisonOperator:"LessThanThreshold",Dimensions:[{Name:"CertificateArn",Value:n.certificateArn}],...n.snsTopicArn&&{AlarmActions:[n.snsTopicArn]}}}}clear(){this.certificates.clear(),this.renewals.clear(),this.validations.clear(),this.monitors.clear(),this.alerts.clear(),this.certificateCounter=0,this.renewalCounter=0,this.validationCounter=0,this.monitorCounter=0,this.alertCounter=0}}var CE=new Af;class yf{scans=new Map;findings=new Map;reports=new Map;complianceChecks=new Map;postures=new Map;scanCounter=0;findingCounter=0;reportCounter=0;checkCounter=0;postureCounter=0;createScan(n){let i=`scan-${Date.now()}-${this.scanCounter++}`,s={id:i,status:"queued",findings:[],...n};return this.scans.set(i,s),s}createContainerScan(n){return this.createScan({name:n.name,scanType:"container_image",target:{type:"ecr_image",identifier:n.imageUri,region:n.region||"us-east-1"}})}createLambdaScan(n){return this.createScan({name:n.name,scanType:"vulnerability",target:{type:"lambda",identifier:n.functionName,region:n.region||"us-east-1"}})}createSecretsDetectionScan(n){return this.createScan({name:n.name,scanType:"secrets_detection",target:{type:"repository",identifier:n.repositoryUrl}})}async executeScan(n){let i=this.scans.get(n);if(!i)throw Error(`Scan not found: ${n}`);console.log(`
3734
3732
  Executing security scan: ${i.name}`),console.log(`Scan type: ${i.scanType}`),console.log(`Target: ${i.target.type} - ${i.target.identifier}`),i.status="running",i.startedAt=new Date;try{console.log(`
3735
3733
  Scanning...`);let s=this.simulateFindings(i);return i.findings=s,i.status="completed",i.completedAt=new Date,i.summary={totalFindings:s.length,criticalCount:s.filter((o)=>o.severity==="CRITICAL").length,highCount:s.filter((o)=>o.severity==="HIGH").length,mediumCount:s.filter((o)=>o.severity==="MEDIUM").length,lowCount:s.filter((o)=>o.severity==="LOW").length,infoCount:s.filter((o)=>o.severity==="INFO").length,executionTime:i.completedAt.getTime()-i.startedAt.getTime()},console.log(`
3736
- ✓ Scan completed`),console.log(` Findings: ${i.summary.totalFindings}`),console.log(` Critical: ${i.summary.criticalCount}`),console.log(` High: ${i.summary.highCount}`),console.log(` Medium: ${i.summary.mediumCount}`),console.log(` Low: ${i.summary.lowCount}`),i}catch(s){throw i.status="failed",i.completedAt=new Date,s}}simulateFindings(n){let i=[],s=new Date;if(n.scanType==="container_image")i.push(this.createFinding({severity:"HIGH",title:"Vulnerable OpenSSL version detected",description:"OpenSSL 1.1.1k contains known vulnerabilities",cve:"CVE-2021-3711",cvss:7.5,affectedResource:n.target.identifier,remediation:"Update OpenSSL to version 1.1.1l or later",status:"OPEN",firstDetected:s,lastSeen:s})),i.push(this.createFinding({severity:"MEDIUM",title:"Outdated npm package: lodash",description:"lodash 4.17.19 has known security issues",cve:"CVE-2020-8203",cvss:5.3,affectedResource:n.target.identifier,remediation:"Update lodash to version 4.17.21 or later",status:"OPEN",firstDetected:s,lastSeen:s}));else if(n.scanType==="secrets_detection")i.push(this.createFinding({severity:"CRITICAL",title:"AWS Access Key exposed in code",description:"Hardcoded AWS access key found in source code",affectedResource:`${n.target.identifier}/src/config.ts:12`,remediation:"Remove hardcoded credentials and use AWS Secrets Manager",status:"OPEN",firstDetected:s,lastSeen:s}));return i}createFinding(n){let i=`finding-${Date.now()}-${this.findingCounter++}`,s={id:i,...n};return this.findings.set(i,s),s}suppressFinding(n,i){let s=this.findings.get(n);if(s){if(s.status="SUPPRESSED",console.log(`Finding suppressed: ${s.title}`),i)console.log(`Reason: ${i}`)}}resolveFinding(n){let i=this.findings.get(n);if(i)i.status="RESOLVED",console.log(`Finding resolved: ${i.title}`)}generateReport(n){let i=`report-${Date.now()}-${this.reportCounter++}`,s={id:i,scanId:n.scanId,reportType:n.reportType,format:n.format,generatedAt:new Date,s3Location:`s3://security-reports/${i}.${n.format}`};return this.reports.set(i,s),s}runComplianceCheck(n){let i=[];if(n.framework.includes("CIS"))i.push(this.createComplianceCheck({framework:n.framework,checkId:"1.1",title:"Avoid the use of root account",description:"Root account should not be used for everyday tasks",status:"PASS",severity:"CRITICAL",resourceType:n.resourceType,resourceId:n.resourceId})),i.push(this.createComplianceCheck({framework:n.framework,checkId:"2.1",title:"Ensure CloudTrail is enabled",description:"CloudTrail should be enabled in all regions",status:"FAIL",severity:"HIGH",resourceType:n.resourceType,resourceId:n.resourceId,remediation:"Enable CloudTrail in all regions"}));return i}createComplianceCheck(n){let i=`check-${Date.now()}-${this.checkCounter++}`,s={id:i,...n};return this.complianceChecks.set(i,s),s}assessSecurityPosture(n){let i=`posture-${Date.now()}-${this.postureCounter++}`,s=Array.from(this.complianceChecks.values()),o=s.filter((y)=>y.status==="PASS").length,c=s.length,u=c>0?Math.round(o/c*100):0,d;if(u>=90)d="A";else if(u>=80)d="B";else if(u>=70)d="C";else if(u>=60)d="D";else d="F";let g={id:i,accountId:n.accountId,region:n.region,score:u,grade:d,assessedAt:new Date,strengths:["IAM password policy enforced","Multi-factor authentication enabled","CloudTrail logging enabled"],weaknesses:["Some S3 buckets are publicly accessible","Security groups allow unrestricted ingress","Outdated dependencies in Lambda functions"],recommendations:["Review and update S3 bucket policies","Implement least-privilege security group rules","Update Lambda runtime versions and dependencies","Enable GuardDuty for threat detection"]};return this.postures.set(i,g),g}getScan(n){return this.scans.get(n)}listScans(){return Array.from(this.scans.values())}getOpenFindings(n){return Array.from(this.findings.values()).filter((i)=>i.status==="OPEN"&&(!n||i.severity===n))}getComplianceChecksByStatus(n){return Array.from(this.complianceChecks.values()).filter((i)=>i.status===n)}listPostures(){return Array.from(this.postures.values())}generateECRScanCF(n){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:n,ImageScanningConfiguration:{ScanOnPush:!0},ImageTagMutability:"IMMUTABLE"}}}clear(){this.scans.clear(),this.findings.clear(),this.reports.clear(),this.complianceChecks.clear(),this.postures.clear(),this.scanCounter=0,this.findingCounter=0,this.reportCounter=0,this.checkCounter=0,this.postureCounter=0}}var lE=new cf;class df{configs=new Map;results=new Map;policies=new Map;configCounter=0;resultCounter=0;policyCounter=0;configureScan(n){let i=`scan-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}configureTrivyScan(n){return this.configureScan({repository:n.repository,imageTag:n.imageTag,scanner:"trivy",scanOnPush:n.scanOnPush??!0,ignoreUnfixed:n.ignoreUnfixed??!1,failOnSeverity:"HIGH"})}configureSnykScan(n){return this.configureScan({repository:n.repository,imageTag:n.imageTag,scanner:"snyk",scanOnPush:n.scanOnPush??!0,failOnSeverity:"HIGH"})}configureECRScan(n){return this.configureScan({repository:n.repository,imageTag:"latest",scanner:"ecr",scanOnPush:n.scanOnPush??!0,failOnSeverity:"CRITICAL"})}async scanImage(n){let i=this.configs.get(n);if(!i)throw Error(`Scan config not found: ${n}`);let s=`${i.repository}:${i.imageTag}`;console.log(`
3734
+ ✓ Scan completed`),console.log(` Findings: ${i.summary.totalFindings}`),console.log(` Critical: ${i.summary.criticalCount}`),console.log(` High: ${i.summary.highCount}`),console.log(` Medium: ${i.summary.mediumCount}`),console.log(` Low: ${i.summary.lowCount}`),i}catch(s){throw i.status="failed",i.completedAt=new Date,s}}simulateFindings(n){let i=[],s=new Date;if(n.scanType==="container_image")i.push(this.createFinding({severity:"HIGH",title:"Vulnerable OpenSSL version detected",description:"OpenSSL 1.1.1k contains known vulnerabilities",cve:"CVE-2021-3711",cvss:7.5,affectedResource:n.target.identifier,remediation:"Update OpenSSL to version 1.1.1l or later",status:"OPEN",firstDetected:s,lastSeen:s})),i.push(this.createFinding({severity:"MEDIUM",title:"Outdated npm package: lodash",description:"lodash 4.17.19 has known security issues",cve:"CVE-2020-8203",cvss:5.3,affectedResource:n.target.identifier,remediation:"Update lodash to version 4.17.21 or later",status:"OPEN",firstDetected:s,lastSeen:s}));else if(n.scanType==="secrets_detection")i.push(this.createFinding({severity:"CRITICAL",title:"AWS Access Key exposed in code",description:"Hardcoded AWS access key found in source code",affectedResource:`${n.target.identifier}/src/config.ts:12`,remediation:"Remove hardcoded credentials and use AWS Secrets Manager",status:"OPEN",firstDetected:s,lastSeen:s}));return i}createFinding(n){let i=`finding-${Date.now()}-${this.findingCounter++}`,s={id:i,...n};return this.findings.set(i,s),s}suppressFinding(n,i){let s=this.findings.get(n);if(s){if(s.status="SUPPRESSED",console.log(`Finding suppressed: ${s.title}`),i)console.log(`Reason: ${i}`)}}resolveFinding(n){let i=this.findings.get(n);if(i)i.status="RESOLVED",console.log(`Finding resolved: ${i.title}`)}generateReport(n){let i=`report-${Date.now()}-${this.reportCounter++}`,s={id:i,scanId:n.scanId,reportType:n.reportType,format:n.format,generatedAt:new Date,s3Location:`s3://security-reports/${i}.${n.format}`};return this.reports.set(i,s),s}runComplianceCheck(n){let i=[];if(n.framework.includes("CIS"))i.push(this.createComplianceCheck({framework:n.framework,checkId:"1.1",title:"Avoid the use of root account",description:"Root account should not be used for everyday tasks",status:"PASS",severity:"CRITICAL",resourceType:n.resourceType,resourceId:n.resourceId})),i.push(this.createComplianceCheck({framework:n.framework,checkId:"2.1",title:"Ensure CloudTrail is enabled",description:"CloudTrail should be enabled in all regions",status:"FAIL",severity:"HIGH",resourceType:n.resourceType,resourceId:n.resourceId,remediation:"Enable CloudTrail in all regions"}));return i}createComplianceCheck(n){let i=`check-${Date.now()}-${this.checkCounter++}`,s={id:i,...n};return this.complianceChecks.set(i,s),s}assessSecurityPosture(n){let i=`posture-${Date.now()}-${this.postureCounter++}`,s=Array.from(this.complianceChecks.values()),o=s.filter((y)=>y.status==="PASS").length,c=s.length,u=c>0?Math.round(o/c*100):0,d;if(u>=90)d="A";else if(u>=80)d="B";else if(u>=70)d="C";else if(u>=60)d="D";else d="F";let g={id:i,accountId:n.accountId,region:n.region,score:u,grade:d,assessedAt:new Date,strengths:["IAM password policy enforced","Multi-factor authentication enabled","CloudTrail logging enabled"],weaknesses:["Some S3 buckets are publicly accessible","Security groups allow unrestricted ingress","Outdated dependencies in Lambda functions"],recommendations:["Review and update S3 bucket policies","Implement least-privilege security group rules","Update Lambda runtime versions and dependencies","Enable GuardDuty for threat detection"]};return this.postures.set(i,g),g}getScan(n){return this.scans.get(n)}listScans(){return Array.from(this.scans.values())}getOpenFindings(n){return Array.from(this.findings.values()).filter((i)=>i.status==="OPEN"&&(!n||i.severity===n))}getComplianceChecksByStatus(n){return Array.from(this.complianceChecks.values()).filter((i)=>i.status===n)}listPostures(){return Array.from(this.postures.values())}generateECRScanCF(n){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:n,ImageScanningConfiguration:{ScanOnPush:!0},ImageTagMutability:"IMMUTABLE"}}}clear(){this.scans.clear(),this.findings.clear(),this.reports.clear(),this.complianceChecks.clear(),this.postures.clear(),this.scanCounter=0,this.findingCounter=0,this.reportCounter=0,this.checkCounter=0,this.postureCounter=0}}var EE=new yf;class Sf{configs=new Map;results=new Map;policies=new Map;configCounter=0;resultCounter=0;policyCounter=0;configureScan(n){let i=`scan-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}configureTrivyScan(n){return this.configureScan({repository:n.repository,imageTag:n.imageTag,scanner:"trivy",scanOnPush:n.scanOnPush??!0,ignoreUnfixed:n.ignoreUnfixed??!1,failOnSeverity:"HIGH"})}configureSnykScan(n){return this.configureScan({repository:n.repository,imageTag:n.imageTag,scanner:"snyk",scanOnPush:n.scanOnPush??!0,failOnSeverity:"HIGH"})}configureECRScan(n){return this.configureScan({repository:n.repository,imageTag:"latest",scanner:"ecr",scanOnPush:n.scanOnPush??!0,failOnSeverity:"CRITICAL"})}async scanImage(n){let i=this.configs.get(n);if(!i)throw Error(`Scan config not found: ${n}`);let s=`${i.repository}:${i.imageTag}`;console.log(`
3737
3735
  Scanning image: ${s}`),console.log(`Scanner: ${i.scanner}`);let o=`scan-result-${Date.now()}-${this.resultCounter++}`,c=this.simulateVulnerabilities(i),u={total:c.length,critical:c.filter((y)=>y.severity==="CRITICAL").length,high:c.filter((y)=>y.severity==="HIGH").length,medium:c.filter((y)=>y.severity==="MEDIUM").length,low:c.filter((y)=>y.severity==="LOW").length,unknown:c.filter((y)=>y.severity==="UNKNOWN").length},d=this.evaluateScanResult(i,u),g={id:o,imageUri:s,scannerType:i.scanner,scanDate:new Date,vulnerabilities:c,summary:u,passed:d};return this.results.set(o,g),console.log(`
3738
- Scan Results:`),console.log(` Total vulnerabilities: ${u.total}`),console.log(` Critical: ${u.critical}`),console.log(` High: ${u.high}`),console.log(` Medium: ${u.medium}`),console.log(` Low: ${u.low}`),console.log(` Status: ${d?"✓ PASSED":"✗ FAILED"}`),g}simulateVulnerabilities(n){let i=[];if(n.scanner==="trivy"||n.scanner==="ecr")i.push({id:"vuln-1",cve:"CVE-2024-1234",severity:"HIGH",packageName:"openssl",installedVersion:"1.1.1k",fixedVersion:"1.1.1l",title:"OpenSSL buffer overflow",description:"Buffer overflow vulnerability in OpenSSL",references:["https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-1234"],cvss:7.5}),i.push({id:"vuln-2",cve:"CVE-2024-5678",severity:"MEDIUM",packageName:"curl",installedVersion:"7.68.0",fixedVersion:"7.79.0",title:"curl remote code execution",description:"Remote code execution in curl",references:["https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-5678"],cvss:5.3});return i}evaluateScanResult(n,i){if(!n.failOnSeverity)return!0;switch(n.failOnSeverity){case"CRITICAL":return i.critical===0;case"HIGH":return i.critical===0&&i.high===0;case"MEDIUM":return i.critical===0&&i.high===0&&i.medium===0;case"LOW":return i.total===0;default:return!0}}createPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,...n};return this.policies.set(i,s),s}createStrictPolicy(n){return this.createPolicy({name:n,allowedSeverities:[],maxCritical:0,maxHigh:0,blockOnFailure:!0,exemptions:[]})}createPermissivePolicy(n){return this.createPolicy({name:n,allowedSeverities:["CRITICAL","HIGH","MEDIUM","LOW"],maxCritical:5,maxHigh:10,blockOnFailure:!1,exemptions:[]})}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getResult(n){return this.results.get(n)}listResults(){return Array.from(this.results.values())}generateECRScanCF(n){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:n.repository,ImageScanningConfiguration:{ScanOnPush:n.scanOnPush},ImageTagMutability:"IMMUTABLE",EncryptionConfiguration:{EncryptionType:"AES256"}}}}clear(){this.configs.clear(),this.results.clear(),this.policies.clear(),this.configCounter=0,this.resultCounter=0,this.policyCounter=0}}var uE=new df;class lf{configs=new Map;multiStageConfigs=new Map;optimizations=new Map;analyses=new Map;configCounter=0;multiStageCounter=0;optimizationCounter=0;analysisCounter=0;createBuildConfig(n){let i=`build-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}createOptimizedBuildConfig(n){let i={type:n.enableCache?"registry":"inline",cacheFrom:n.registry?[`${n.registry}/cache`]:void 0,cacheTo:n.registry?`${n.registry}/cache`:void 0,maxCacheAge:7};return this.createBuildConfig({name:n.name,dockerfile:n.dockerfile,context:".",cacheStrategy:i,buildArgs:{BUILDKIT_INLINE_CACHE:"1"}})}createMultiStageConfig(n){let i=`multi-stage-${Date.now()}-${this.multiStageCounter++}`,s={id:i,...n};return this.multiStageConfigs.set(i,s),s}createNodeMultiStageBuild(n){let i=n.nodeVersion||"18-alpine";return this.createMultiStageConfig({name:n.name,targetStage:n.targetStage||"production",stages:[{name:"dependencies",baseImage:`node:${i}`,workdir:"/app",commands:["COPY package*.json ./","RUN npm ci --only=production"]},{name:"build",baseImage:`node:${i}`,workdir:"/app",commands:["COPY package*.json ./","RUN npm ci","COPY . .","RUN npm run build"]},{name:"production",baseImage:`node:${i}`,workdir:"/app",copyFrom:["dependencies:/app/node_modules","build:/app/dist"],commands:["COPY package*.json ./","ENV NODE_ENV=production",'CMD ["node", "dist/index.js"]']}]})}generateDockerfile(n){let i=this.multiStageConfigs.get(n);if(!i)throw Error(`Multi-stage config not found: ${n}`);let s=[];for(let o of i.stages){if(s.push(`# Stage: ${o.name}`),s.push(`FROM ${o.baseImage} AS ${o.name}`),o.workdir)s.push(`WORKDIR ${o.workdir}`);if(o.env)for(let[c,u]of Object.entries(o.env))s.push(`ENV ${c}=${u}`);for(let c of o.commands)s.push(c);s.push("")}return s.join(`
3736
+ Scan Results:`),console.log(` Total vulnerabilities: ${u.total}`),console.log(` Critical: ${u.critical}`),console.log(` High: ${u.high}`),console.log(` Medium: ${u.medium}`),console.log(` Low: ${u.low}`),console.log(` Status: ${d?"✓ PASSED":"✗ FAILED"}`),g}simulateVulnerabilities(n){let i=[];if(n.scanner==="trivy"||n.scanner==="ecr")i.push({id:"vuln-1",cve:"CVE-2024-1234",severity:"HIGH",packageName:"openssl",installedVersion:"1.1.1k",fixedVersion:"1.1.1l",title:"OpenSSL buffer overflow",description:"Buffer overflow vulnerability in OpenSSL",references:["https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-1234"],cvss:7.5}),i.push({id:"vuln-2",cve:"CVE-2024-5678",severity:"MEDIUM",packageName:"curl",installedVersion:"7.68.0",fixedVersion:"7.79.0",title:"curl remote code execution",description:"Remote code execution in curl",references:["https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-5678"],cvss:5.3});return i}evaluateScanResult(n,i){if(!n.failOnSeverity)return!0;switch(n.failOnSeverity){case"CRITICAL":return i.critical===0;case"HIGH":return i.critical===0&&i.high===0;case"MEDIUM":return i.critical===0&&i.high===0&&i.medium===0;case"LOW":return i.total===0;default:return!0}}createPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,...n};return this.policies.set(i,s),s}createStrictPolicy(n){return this.createPolicy({name:n,allowedSeverities:[],maxCritical:0,maxHigh:0,blockOnFailure:!0,exemptions:[]})}createPermissivePolicy(n){return this.createPolicy({name:n,allowedSeverities:["CRITICAL","HIGH","MEDIUM","LOW"],maxCritical:5,maxHigh:10,blockOnFailure:!1,exemptions:[]})}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getResult(n){return this.results.get(n)}listResults(){return Array.from(this.results.values())}generateECRScanCF(n){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:n.repository,ImageScanningConfiguration:{ScanOnPush:n.scanOnPush},ImageTagMutability:"IMMUTABLE",EncryptionConfiguration:{EncryptionType:"AES256"}}}}clear(){this.configs.clear(),this.results.clear(),this.policies.clear(),this.configCounter=0,this.resultCounter=0,this.policyCounter=0}}var vE=new Sf;class If{configs=new Map;multiStageConfigs=new Map;optimizations=new Map;analyses=new Map;configCounter=0;multiStageCounter=0;optimizationCounter=0;analysisCounter=0;createBuildConfig(n){let i=`build-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}createOptimizedBuildConfig(n){let i={type:n.enableCache?"registry":"inline",cacheFrom:n.registry?[`${n.registry}/cache`]:void 0,cacheTo:n.registry?`${n.registry}/cache`:void 0,maxCacheAge:7};return this.createBuildConfig({name:n.name,dockerfile:n.dockerfile,context:".",cacheStrategy:i,buildArgs:{BUILDKIT_INLINE_CACHE:"1"}})}createMultiStageConfig(n){let i=`multi-stage-${Date.now()}-${this.multiStageCounter++}`,s={id:i,...n};return this.multiStageConfigs.set(i,s),s}createNodeMultiStageBuild(n){let i=n.nodeVersion||"18-alpine";return this.createMultiStageConfig({name:n.name,targetStage:n.targetStage||"production",stages:[{name:"dependencies",baseImage:`node:${i}`,workdir:"/app",commands:["COPY package*.json ./","RUN npm ci --only=production"]},{name:"build",baseImage:`node:${i}`,workdir:"/app",commands:["COPY package*.json ./","RUN npm ci","COPY . .","RUN npm run build"]},{name:"production",baseImage:`node:${i}`,workdir:"/app",copyFrom:["dependencies:/app/node_modules","build:/app/dist"],commands:["COPY package*.json ./","ENV NODE_ENV=production",'CMD ["node", "dist/index.js"]']}]})}generateDockerfile(n){let i=this.multiStageConfigs.get(n);if(!i)throw Error(`Multi-stage config not found: ${n}`);let s=[];for(let o of i.stages){if(s.push(`# Stage: ${o.name}`),s.push(`FROM ${o.baseImage} AS ${o.name}`),o.workdir)s.push(`WORKDIR ${o.workdir}`);if(o.env)for(let[c,u]of Object.entries(o.env))s.push(`ENV ${c}=${u}`);for(let c of o.commands)s.push(c);s.push("")}return s.join(`
3739
3737
  `)}analyzeImage(n,i){let s=`analysis-${Date.now()}-${this.analysisCounter++}`,o=i.map((g)=>({...g,cacheable:this.isLayerCacheable(g.command)})),c=o.reduce((g,y)=>g+y.size,0),u=o.filter((g)=>!g.cacheable&&g.size>100).length,d={id:s,imageId:n,layers:o,totalSize:c,unnecessaryLayers:u};return this.analyses.set(s,d),d}isLayerCacheable(n){let i=["FROM","RUN","COPY","ADD","WORKDIR","ENV"],s=["CMD","ENTRYPOINT","LABEL"];for(let o of i)if(n.startsWith(o))return!0;for(let o of s)if(n.startsWith(o))return!1;return!1}generateOptimizations(n){let i=this.analyses.get(n);if(!i)throw Error(`Analysis not found: ${n}`);let s=`optimization-${Date.now()}-${this.optimizationCounter++}`,o=[],c=i.layers.filter((h)=>h.command.startsWith("RUN"));if(c.length>5)o.push({type:"layer_reduction",priority:"high",title:"Combine RUN commands",description:`${c.length} RUN commands found. Combine them to reduce layers.`,example:"RUN apt-get update && apt-get install -y package1 package2",impact:"Reduce image size by 20-30% and improve build time"});let u=i.layers[0];if(u.command.includes("ubuntu")||u.command.includes("debian"))o.push({type:"base_image",priority:"medium",title:"Use Alpine base image",description:"Switch to Alpine Linux for smaller image size",example:"FROM node:18-alpine",impact:"Reduce image size by 50-70%"});let d=i.layers.filter((h)=>h.command.startsWith("COPY"));if(d.length>0&&d[0].index>3)o.push({type:"cache_optimization",priority:"high",title:"Copy dependencies first",description:"Copy package files before source code to leverage layer caching",example:`COPY package*.json ./
3740
3738
  RUN npm install
3741
- COPY . .`,impact:"Improve build time by 60-80% on subsequent builds"});let g={sizeBefore:i.totalSize,sizeAfter:i.totalSize*0.6,timeBefore:300,timeAfter:120},y={id:s,name:`Optimization for ${i.imageId}`,recommendations:o,estimatedSavings:g};return this.optimizations.set(s,y),y}getBuildConfig(n){return this.configs.get(n)}listBuildConfigs(){return Array.from(this.configs.values())}getMultiStageConfig(n){return this.multiStageConfigs.get(n)}listMultiStageConfigs(){return Array.from(this.multiStageConfigs.values())}getOptimization(n){return this.optimizations.get(n)}listOptimizations(){return Array.from(this.optimizations.values())}clear(){this.configs.clear(),this.multiStageConfigs.clear(),this.optimizations.clear(),this.analyses.clear(),this.configCounter=0,this.multiStageCounter=0,this.optimizationCounter=0,this.analysisCounter=0}}var gE=new lf;class Ol{registries=new Map;credentials=new Map;registryCounter=0;credentialsCounter=0;createRegistry(n){let i=`registry-${Date.now()}-${this.registryCounter++}`,s={id:i,...n};return this.registries.set(i,s),s}createECRRepository(n){return this.createRegistry({name:n.name,registryType:"ecr",repositoryUri:`123456789012.dkr.ecr.${n.region||"us-east-1"}.amazonaws.com/${n.name}`,region:n.region||"us-east-1",encryption:{encryptionType:n.encryption||"AES256",kmsKeyId:n.kmsKeyId},scanning:{scanOnPush:n.scanOnPush??!0}})}createManagedRepository(n){let i=this.createECRRepository({name:n.name,region:n.region,scanOnPush:!0,encryption:"KMS"});return i.lifecycle={id:`lifecycle-${Date.now()}`,rules:[{rulePriority:1,description:"Keep only last N images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:n.maxImageCount||10},action:{type:"expire"}},{rulePriority:2,description:"Remove images older than N days",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:n.maxImageAgeDays||30,countUnit:"days"},action:{type:"expire"}}]},i}enableReplication(n,i){let s=this.registries.get(n);if(!s)throw Error(`Registry not found: ${n}`);return s.replication={enabled:!0,destinations:i},s}createCredentials(n){let i=`creds-${Date.now()}-${this.credentialsCounter++}`,s={id:i,...n};return this.credentials.set(i,s),s}getRegistry(n){return this.registries.get(n)}listRegistries(){return Array.from(this.registries.values())}generateECRRepositoryCF(n){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:n.name,ImageScanningConfiguration:{ScanOnPush:n.scanning?.scanOnPush??!1},EncryptionConfiguration:{EncryptionType:n.encryption?.encryptionType||"AES256",...n.encryption?.kmsKeyId&&{KmsKey:n.encryption.kmsKeyId}},ImageTagMutability:"MUTABLE",...n.lifecycle&&{LifecyclePolicy:{LifecyclePolicyText:JSON.stringify({rules:n.lifecycle.rules})}}}}}generateReplicationConfigCF(n){return{Type:"AWS::ECR::ReplicationConfiguration",Properties:{ReplicationConfiguration:{Rules:n.destinations.map((i)=>({Destinations:[{Region:i.region,...i.registryId&&{RegistryId:i.registryId}}]}))}}}}clear(){this.registries.clear(),this.credentials.clear(),this.registryCounter=0,this.credentialsCounter=0}}var cS=new Ol;class _l{meshes=new Map;virtualNodes=new Map;virtualRouters=new Map;virtualGateways=new Map;meshCounter=0;nodeCounter=0;routerCounter=0;gatewayCounter=0;createMesh(n){let i=`mesh-${Date.now()}-${this.meshCounter++}`,s={id:i,...n};return this.meshes.set(i,s),s}createAppMesh(n){return this.createMesh({name:n.name,meshType:"app_mesh",services:n.services,virtualNodes:[],virtualRouters:[],virtualGateways:[]})}createVirtualNode(n){let i=`vnode-${Date.now()}-${this.nodeCounter++}`,s={id:i,...n};return this.virtualNodes.set(i,s),s}createHTTPVirtualNode(n){return this.createVirtualNode({name:n.name,serviceName:n.serviceName,listeners:[{port:n.port,protocol:"http",healthCheck:{protocol:"http",path:"/health",interval:30,timeout:10,healthyThreshold:2,unhealthyThreshold:3},timeout:{perRequest:15000,idle:300000}}],serviceDiscovery:{type:"aws_cloud_map",namespace:n.namespace,serviceName:n.serviceName}})}createVirtualRouter(n){let i=`vrouter-${Date.now()}-${this.routerCounter++}`,s={id:i,...n};return this.virtualRouters.set(i,s),s}createCanaryRoute(n){return this.createVirtualRouter({name:n.name,listeners:[{port:n.port,protocol:n.protocol}],routes:[{name:"canary-route",match:{prefix:"/"},action:{weightedTargets:[{virtualNode:n.stableTarget,weight:100-n.canaryWeight},{virtualNode:n.canaryTarget,weight:n.canaryWeight}]},retryPolicy:{maxRetries:3,perRetryTimeout:5000,httpRetryEvents:["server-error","gateway-error"],tcpRetryEvents:["connection-error"]}}]})}createVirtualGateway(n){let i=`vgateway-${Date.now()}-${this.gatewayCounter++}`,s={id:i,...n};return this.virtualGateways.set(i,s),s}createIngressGateway(n){let i={port:n.port,protocol:"http",healthCheck:{protocol:"http",path:"/health",interval:30,timeout:10,healthyThreshold:2,unhealthyThreshold:3}};if(n.enableTLS&&n.certificateArn)i.tls={mode:"STRICT",certificate:{acm:n.certificateArn}};return this.createVirtualGateway({name:n.name,listeners:[i],logging:{accessLog:{file:{path:"/dev/stdout"}}}})}getMesh(n){return this.meshes.get(n)}listMeshes(){return Array.from(this.meshes.values())}getVirtualNode(n){return this.virtualNodes.get(n)}listVirtualNodes(){return Array.from(this.virtualNodes.values())}generateMeshCF(n){return{Type:"AWS::AppMesh::Mesh",Properties:{MeshName:n.name,Spec:{EgressFilter:{Type:"ALLOW_ALL"}}}}}generateVirtualNodeCF(n,i){return{Type:"AWS::AppMesh::VirtualNode",Properties:{MeshName:i,VirtualNodeName:n.name,Spec:{Listeners:n.listeners.map((s)=>({PortMapping:{Port:s.port,Protocol:s.protocol},...s.healthCheck&&{HealthCheck:{Protocol:s.healthCheck.protocol,...s.healthCheck.path&&{Path:s.healthCheck.path},IntervalMillis:s.healthCheck.interval*1000,TimeoutMillis:s.healthCheck.timeout*1000,HealthyThreshold:s.healthCheck.healthyThreshold,UnhealthyThreshold:s.healthCheck.unhealthyThreshold}}})),ServiceDiscovery:{AWSCloudMap:{NamespaceName:n.serviceDiscovery.namespace,ServiceName:n.serviceDiscovery.serviceName}}}}}}generateVirtualRouterCF(n,i){return{Type:"AWS::AppMesh::VirtualRouter",Properties:{MeshName:i,VirtualRouterName:n.name,Spec:{Listeners:n.listeners.map((s)=>({PortMapping:{Port:s.port,Protocol:s.protocol}}))}}}}clear(){this.meshes.clear(),this.virtualNodes.clear(),this.virtualRouters.clear(),this.virtualGateways.clear(),this.meshCounter=0,this.nodeCounter=0,this.routerCounter=0,this.gatewayCounter=0}}var dS=new _l;class uf{layers=new Map;versions=new Map;permissions=new Map;layerCounter=0;versionCounter=0;permissionCounter=0;createLayer(n){let i=`layer-${Date.now()}-${this.layerCounter++}`,s=1,o={id:i,layerArn:`arn:aws:lambda:us-east-1:123456789012:layer:${n.layerName}:1`,version:1,...n};return this.layers.set(i,o),o}createNodeDependenciesLayer(n){return this.createLayer({layerName:n.layerName,description:"Node.js dependencies layer",compatibleRuntimes:[`nodejs${n.nodeVersion}`],content:{type:"s3",s3Bucket:n.s3Bucket,s3Key:n.s3Key},size:5242880})}createUtilitiesLayer(n){return this.createLayer({layerName:n.layerName,description:"Shared utilities and helpers",compatibleRuntimes:n.runtimes,content:{type:"s3",s3Bucket:n.s3Bucket,s3Key:n.s3Key},size:1048576})}publishVersion(n){let i=this.layers.get(n);if(!i)throw Error(`Layer not found: ${n}`);let s=`version-${Date.now()}-${this.versionCounter++}`,o=i.version+1,c={id:s,layerName:i.layerName,version:o,createdAt:new Date,compatibleRuntimes:i.compatibleRuntimes,size:i.size,codeHash:this.generateHash()};return this.versions.set(s,c),i.version=o,i.layerArn=`arn:aws:lambda:us-east-1:123456789012:layer:${i.layerName}:${o}`,c}addPermission(n){let i=`permission-${Date.now()}-${this.permissionCounter++}`,s={id:i,layerName:n.layerName,version:n.version,principal:n.principal,action:"lambda:GetLayerVersion",organizationId:n.organizationId};return this.permissions.set(i,s),s}generateHash(){return Math.random().toString(36).substring(2,15)}getLayer(n){return this.layers.get(n)}listLayers(){return Array.from(this.layers.values())}getLayerVersions(n){return Array.from(this.versions.values()).filter((i)=>i.layerName===n)}generateLayerCF(n){return{Type:"AWS::Lambda::LayerVersion",Properties:{LayerName:n.layerName,Description:n.description,Content:n.content.type==="s3"?{S3Bucket:n.content.s3Bucket,S3Key:n.content.s3Key,...n.content.s3ObjectVersion&&{S3ObjectVersion:n.content.s3ObjectVersion}}:{ZipFile:n.content.zipFile},CompatibleRuntimes:n.compatibleRuntimes,...n.licenseInfo&&{LicenseInfo:n.licenseInfo}}}}generateLayerPermissionCF(n){return{Type:"AWS::Lambda::LayerVersionPermission",Properties:{LayerVersionArn:`arn:aws:lambda:us-east-1:123456789012:layer:${n.layerName}:${n.version}`,Action:n.action,Principal:n.principal,...n.organizationId&&{OrganizationId:n.organizationId}}}}clear(){this.layers.clear(),this.versions.clear(),this.permissions.clear(),this.layerCounter=0,this.versionCounter=0,this.permissionCounter=0}}var pE=new uf;class gf{versions=new Map;aliases=new Map;deployments=new Map;versionCounter=0;aliasCounter=0;deploymentCounter=0;publishVersion(n){let i=`version-${Date.now()}-${this.versionCounter++}`,s=this.getNextVersionNumber(n.functionName),o={id:i,functionName:n.functionName,version:s.toString(),functionArn:`arn:aws:lambda:us-east-1:123456789012:function:${n.functionName}:${s}`,codeHash:this.generateHash(),description:n.description,runtime:n.runtime,memorySize:n.memorySize,timeout:n.timeout,publishedAt:new Date};return this.versions.set(i,o),o}getNextVersionNumber(n){let i=Array.from(this.versions.values()).filter((s)=>s.functionName===n).map((s)=>parseInt(s.version));return i.length>0?Math.max(...i)+1:1}createAlias(n){let i=`alias-${Date.now()}-${this.aliasCounter++}`,s={id:i,aliasArn:`arn:aws:lambda:us-east-1:123456789012:function:${n.functionName}:${n.aliasName}`,revisionId:this.generateHash(),...n};return this.aliases.set(i,s),s}createProductionAlias(n){return this.createAlias({functionName:n.functionName,aliasName:"production",functionVersion:n.version,description:"Production alias"})}createStagingAlias(n){return this.createAlias({functionName:n.functionName,aliasName:"staging",functionVersion:n.version,description:"Staging alias"})}updateAlias(n,i){let s=this.aliases.get(n);if(!s)throw Error(`Alias not found: ${n}`);return s.functionVersion=i,s.revisionId=this.generateHash(),s}configureWeightedRouting(n,i){let s=this.aliases.get(n);if(!s)throw Error(`Alias not found: ${n}`);return s.routingConfig={additionalVersionWeights:i},s}createCanaryDeployment(n){let i=`deployment-${Date.now()}-${this.deploymentCounter++}`,s=Array.from(this.aliases.values()).find((c)=>c.functionName===n.functionName&&c.aliasName===n.aliasName);if(!s)s=this.createAlias({functionName:n.functionName,aliasName:n.aliasName,functionVersion:n.fromVersion});this.configureWeightedRouting(s.id,{[n.toVersion]:n.canaryWeight});let o={id:i,functionName:n.functionName,fromVersion:n.fromVersion,toVersion:n.toVersion,aliasName:n.aliasName,strategy:"canary",status:"in_progress",startedAt:new Date};return this.deployments.set(i,o),o}completeDeployment(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);let s=Array.from(this.aliases.values()).find((o)=>o.functionName===i.functionName&&o.aliasName===i.aliasName);if(s)s.functionVersion=i.toVersion,s.routingConfig=void 0;return i.status="completed",i.completedAt=new Date,i}rollbackDeployment(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);let s=Array.from(this.aliases.values()).find((o)=>o.functionName===i.functionName&&o.aliasName===i.aliasName);if(s)s.functionVersion=i.fromVersion,s.routingConfig=void 0;return i.status="failed",i.completedAt=new Date,i}generateHash(){return Math.random().toString(36).substring(2,15)}getVersion(n){return this.versions.get(n)}listVersions(n){let i=Array.from(this.versions.values());return n?i.filter((s)=>s.functionName===n):i}getAlias(n){return this.aliases.get(n)}listAliases(n){let i=Array.from(this.aliases.values());return n?i.filter((s)=>s.functionName===n):i}generateVersionCF(n){return{Type:"AWS::Lambda::Version",Properties:{FunctionName:n.functionName,Description:n.description}}}generateAliasCF(n){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:n.functionName,Name:n.aliasName,FunctionVersion:n.functionVersion,Description:n.description,...n.routingConfig&&{RoutingConfig:{AdditionalVersionWeights:Object.entries(n.routingConfig.additionalVersionWeights||{}).map(([i,s])=>({FunctionVersion:i,FunctionWeight:s}))}}}}}clear(){this.versions.clear(),this.aliases.clear(),this.deployments.clear(),this.versionCounter=0,this.aliasCounter=0,this.deploymentCounter=0}}var mE=new gf;class pf{configs=new Map;provisionedConfigs=new Map;schedules=new Map;autoScalingConfigs=new Map;configCounter=0;provisionedCounter=0;scheduleCounter=0;autoScalingCounter=0;setReservedConcurrency(n){let i=`concurrency-${Date.now()}-${this.configCounter++}`,s={id:i,functionName:n.functionName,reservedConcurrency:n.reservedConcurrency};return this.configs.set(i,s),s}setProvisionedConcurrency(n){let i=`provisioned-${Date.now()}-${this.provisionedCounter++}`,s={id:i,functionName:n.functionName,qualifier:n.qualifier,provisionedConcurrentExecutions:n.provisionedConcurrentExecutions,status:"pending",lastModified:new Date};return this.provisionedConfigs.set(i,s),setTimeout(()=>{s.status="ready",s.allocatedConcurrency=n.provisionedConcurrentExecutions,s.availableConcurrency=n.provisionedConcurrentExecutions},100),s}configureWarmPool(n){return this.setProvisionedConcurrency({functionName:n.functionName,qualifier:n.alias,provisionedConcurrentExecutions:n.minInstances})}createSchedule(n){let i=`schedule-${Date.now()}-${this.scheduleCounter++}`,s={id:i,...n};return this.schedules.set(i,s),s}createBusinessHoursSchedule(n){return this.createSchedule({name:`${n.functionName}-business-hours`,functionName:n.functionName,qualifier:n.qualifier,schedule:[{name:"business-hours",cronExpression:"0 8 * * MON-FRI",targetConcurrency:n.businessHoursConcurrency},{name:"off-hours",cronExpression:"0 18 * * MON-FRI",targetConcurrency:n.offHoursConcurrency},{name:"weekend",cronExpression:"0 0 * * SAT",targetConcurrency:n.offHoursConcurrency}]})}configureAutoScaling(n){let i=`autoscaling-${Date.now()}-${this.autoScalingCounter++}`,s={id:i,...n};return this.autoScalingConfigs.set(i,s),s}configurePredictiveScaling(n){return this.configureAutoScaling({functionName:n.functionName,qualifier:n.qualifier,minCapacity:n.baselineCapacity,maxCapacity:n.peakCapacity,targetUtilization:0.7,scaleInCooldown:300,scaleOutCooldown:60})}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getProvisionedConfig(n){return this.provisionedConfigs.get(n)}listProvisionedConfigs(){return Array.from(this.provisionedConfigs.values())}generateReservedConcurrencyCF(n){return{Type:"AWS::Lambda::Function",Properties:{FunctionName:n.functionName,ReservedConcurrentExecutions:n.reservedConcurrency}}}generateProvisionedConcurrencyCF(n){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:n.functionName,Name:n.qualifier,ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:n.provisionedConcurrentExecutions}}}}generateAutoScalingTargetCF(n){return{Type:"AWS::ApplicationAutoScaling::ScalableTarget",Properties:{ServiceNamespace:"lambda",ResourceId:`function:${n.functionName}:${n.qualifier}`,ScalableDimension:"lambda:function:ProvisionedConcurrentExecutions",MinCapacity:n.minCapacity,MaxCapacity:n.maxCapacity}}}generateAutoScalingPolicyCF(n){return{Type:"AWS::ApplicationAutoScaling::ScalingPolicy",Properties:{PolicyName:`${n.functionName}-autoscaling`,PolicyType:"TargetTrackingScaling",ScalingTargetId:{Ref:`${n.functionName}AutoScalingTarget`},TargetTrackingScalingPolicyConfiguration:{TargetValue:n.targetUtilization*100,PredefinedMetricSpecification:{PredefinedMetricType:"LambdaProvisionedConcurrencyUtilization"},ScaleInCooldown:n.scaleInCooldown||300,ScaleOutCooldown:n.scaleOutCooldown||60}}}}clear(){this.configs.clear(),this.provisionedConfigs.clear(),this.schedules.clear(),this.autoScalingConfigs.clear(),this.configCounter=0,this.provisionedCounter=0,this.scheduleCounter=0,this.autoScalingCounter=0}}var fE=new pf;class mf{destinations=new Map;records=new Map;eventBridgeDestinations=new Map;destinationCounter=0;recordCounter=0;eventBridgeCounter=0;configureDestinations(n){let i=`destination-${Date.now()}-${this.destinationCounter++}`,s={id:i,...n};return this.destinations.set(i,s),s}configureSQSDestination(n){let i={type:"sqs",arn:n.queueArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureSNSDestination(n){let i={type:"sns",arn:n.topicArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureEventBridgeDestination(n){let i={type:"eventbridge",arn:n.eventBusArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureLambdaDestination(n){let i={type:"lambda",arn:n.destinationFunctionArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureDLQWithNotification(n){return this.configureDestinations({functionName:n.functionName,failureDestination:{type:"sqs",arn:n.dlqArn},maxEventAge:3600,maxRetries:0})}createEventBridgeIntegration(n){let i=`eventbridge-${Date.now()}-${this.eventBridgeCounter++}`,s={id:i,functionName:n.functionName,eventBusArn:n.eventBusArn,detailType:n.detailType||"Lambda Function Invocation Result",source:n.source||`lambda.${n.functionName}`};return this.eventBridgeDestinations.set(i,s),s}sendToDestination(n){let i=Array.from(this.destinations.values()).find((u)=>u.functionName===n.functionName);if(!i)return null;let s=n.status==="success"?i.successDestination:i.failureDestination;if(!s)return null;let o=`record-${Date.now()}-${this.recordCounter++}`,c={id:o,timestamp:new Date,functionName:n.functionName,requestId:n.requestId,status:n.status,destinationType:s.type,destinationArn:s.arn,payload:n.payload,error:n.error};return this.records.set(o,c),c}getDestination(n){return this.destinations.get(n)}listDestinations(n){let i=Array.from(this.destinations.values());return n?i.filter((s)=>s.functionName===n):i}getDestinationRecords(n){let i=Array.from(this.records.values());return n?i.filter((s)=>s.functionName===n):i}generateEventInvokeConfigCF(n){return{Type:"AWS::Lambda::EventInvokeConfig",Properties:{FunctionName:n.functionName,Qualifier:n.qualifier||"$LATEST",MaximumEventAgeInSeconds:n.maxEventAge||21600,MaximumRetryAttempts:n.maxRetries??2,...n.successDestination&&{DestinationConfig:{OnSuccess:{Destination:n.successDestination.arn}}},...n.failureDestination&&{DestinationConfig:{OnFailure:{Destination:n.failureDestination.arn}}}}}}generateEventBridgeRuleCF(n){return{Type:"AWS::Events::Rule",Properties:{EventBusName:n.eventBusArn.split("/").pop(),EventPattern:{source:[n.source],"detail-type":[n.detailType]},State:"ENABLED",Targets:[{Arn:`arn:aws:lambda:us-east-1:123456789012:function:${n.functionName}`,Id:n.id}]}}}clear(){this.destinations.clear(),this.records.clear(),this.eventBridgeDestinations.clear(),this.destinationCounter=0,this.recordCounter=0,this.eventBridgeCounter=0}}var hE=new mf;class ff{vpcConfigs=new Map;endpoints=new Map;networkInterfaces=new Map;connectivity=new Map;configCounter=0;endpointCounter=0;eniCounter=0;connectivityCounter=0;configureVPC(n){let i=`vpc-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};this.vpcConfigs.set(i,s);for(let o of n.subnetIds)this.createNetworkInterface({functionName:n.functionName,subnetId:o});return s}configurePrivateVPC(n){return this.configureVPC({functionName:n.functionName,vpcId:n.vpcId,subnetIds:n.privateSubnetIds,securityGroupIds:[n.securityGroupId],ipv6Allowed:!1})}configureMultiAZVPC(n){if(n.subnetIds.length<2)throw Error("Multi-AZ configuration requires at least 2 subnets");return this.configureVPC({functionName:n.functionName,vpcId:n.vpcId,subnetIds:n.subnetIds,securityGroupIds:n.securityGroupIds})}createVPCEndpoint(n){let i=`endpoint-${Date.now()}-${this.endpointCounter++}`,s={id:i,...n};return this.endpoints.set(i,s),s}createS3Endpoint(n){return this.createVPCEndpoint({vpcId:n.vpcId,serviceName:"com.amazonaws.us-east-1.s3",endpointType:"Gateway",privateDnsEnabled:!1})}createDynamoDBEndpoint(n){return this.createVPCEndpoint({vpcId:n.vpcId,serviceName:"com.amazonaws.us-east-1.dynamodb",endpointType:"Gateway",privateDnsEnabled:!1})}createSecretsManagerEndpoint(n){return this.createVPCEndpoint({vpcId:n.vpcId,serviceName:"com.amazonaws.us-east-1.secretsmanager",endpointType:"Interface",subnetIds:n.subnetIds,securityGroupIds:n.securityGroupIds,privateDnsEnabled:!0})}createNetworkInterface(n){let i=`eni-${Date.now()}-${this.eniCounter++}`,s={id:i,functionName:n.functionName,networkInterfaceId:`eni-${Math.random().toString(36).substring(2,15)}`,subnetId:n.subnetId,privateIpAddress:`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`,status:"creating",attachedAt:new Date};return this.networkInterfaces.set(i,s),setTimeout(()=>{s.status="available"},100),s}analyzeConnectivity(n){let i=`connectivity-${Date.now()}-${this.connectivityCounter++}`,s=Array.from(this.vpcConfigs.values()).find((y)=>y.functionName===n.functionName),o=Array.from(this.endpoints.values()).filter((y)=>y.vpcId===s?.vpcId).map((y)=>y.serviceName),c=[],u=n.hasNATGateway??!1,d=n.hasInternetGateway??!1;if(!u&&!d)c.push("Add NAT Gateway for internet access");if(!o.includes("com.amazonaws.us-east-1.s3"))c.push("Add S3 VPC endpoint to reduce NAT costs");if(!o.includes("com.amazonaws.us-east-1.dynamodb"))c.push("Add DynamoDB VPC endpoint for private access");let g={id:i,functionName:n.functionName,hasInternetAccess:u||d,hasNATGateway:u,hasVPCEndpoints:o.length>0,endpoints:o,recommendations:c};return this.connectivity.set(i,g),g}getVPCConfig(n){return this.vpcConfigs.get(n)}listVPCConfigs(n){let i=Array.from(this.vpcConfigs.values());return n?i.filter((s)=>s.functionName===n):i}getNetworkInterfaces(n){return Array.from(this.networkInterfaces.values()).filter((i)=>i.functionName===n)}listVPCEndpoints(n){let i=Array.from(this.endpoints.values());return n?i.filter((s)=>s.vpcId===n):i}generateVPCConfigCF(n){return{VpcConfig:{SubnetIds:n.subnetIds,SecurityGroupIds:n.securityGroupIds,...n.ipv6Allowed&&{Ipv6AllowedForDualStack:!0}}}}generateVPCEndpointCF(n){return{Type:"AWS::EC2::VPCEndpoint",Properties:{VpcId:n.vpcId,ServiceName:n.serviceName,VpcEndpointType:n.endpointType,...n.subnetIds&&{SubnetIds:n.subnetIds},...n.securityGroupIds&&{SecurityGroupIds:n.securityGroupIds},...n.privateDnsEnabled!==void 0&&{PrivateDnsEnabled:n.privateDnsEnabled}}}}generateSecurityGroupCF(n){return{Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:n.groupName,GroupDescription:`Security group for Lambda ${n.groupName}`,VpcId:n.vpcId,...n.ingressRules&&{SecurityGroupIngress:n.ingressRules.map((i)=>({IpProtocol:i.protocol,FromPort:i.fromPort,ToPort:i.toPort,...i.cidrIp&&{CidrIp:i.cidrIp},...i.sourceSecurityGroupId&&{SourceSecurityGroupId:i.sourceSecurityGroupId}}))},...n.egressRules&&{SecurityGroupEgress:n.egressRules.map((i)=>({IpProtocol:i.protocol,FromPort:i.fromPort,ToPort:i.toPort,CidrIp:i.cidrIp||"0.0.0.0/0"}))}}}}clear(){this.vpcConfigs.clear(),this.endpoints.clear(),this.networkInterfaces.clear(),this.connectivity.clear(),this.configCounter=0,this.endpointCounter=0,this.eniCounter=0,this.connectivityCounter=0}}var AE=new ff;class hf{dlqConfigs=new Map;messages=new Map;alarms=new Map;reprocessing=new Map;configCounter=0;messageCounter=0;alarmCounter=0;reprocessCounter=0;configureDLQ(n){let i=`dlq-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.dlqConfigs.set(i,s),s}configureSQSDLQ(n){return this.configureDLQ({functionName:n.functionName,targetArn:n.queueArn,targetType:"sqs",maxReceiveCount:n.maxReceiveCount||3,retentionPeriod:n.retentionPeriod||1209600})}configureSNSDLQ(n){return this.configureDLQ({functionName:n.functionName,targetArn:n.topicArn,targetType:"sns"})}configureDLQWithAlarm(n){let i=this.configureSQSDLQ({functionName:n.functionName,queueArn:n.queueArn});return this.createDLQAlarm({dlqConfigId:i.id,alarmName:`${n.functionName}-dlq-alarm`,threshold:n.alarmThreshold,evaluationPeriods:1,notificationTopicArn:n.notificationTopicArn,enabled:!0}),i}sendToDLQ(n){let i=`message-${Date.now()}-${this.messageCounter++}`,s={id:i,timestamp:new Date,...n};return this.messages.set(i,s),s}createDLQAlarm(n){let i=`alarm-${Date.now()}-${this.alarmCounter++}`,s={id:i,...n};return this.alarms.set(i,s),s}createAgeAlarm(n){let i=this.dlqConfigs.get(n.dlqConfigId);if(!i)throw Error(`DLQ config not found: ${n.dlqConfigId}`);return this.createDLQAlarm({dlqConfigId:n.dlqConfigId,alarmName:`${i.functionName}-dlq-age-alarm`,threshold:n.maxAgeSeconds,evaluationPeriods:1,notificationTopicArn:n.notificationTopicArn,enabled:!0})}async reprocessMessage(n){let i=this.messages.get(n);if(!i)throw Error(`Message not found: ${n}`);let s=Array.from(this.dlqConfigs.values()).find((u)=>u.functionName===i.functionName);if(!s)throw Error(`DLQ config not found for function: ${i.functionName}`);let o=`reprocess-${Date.now()}-${this.reprocessCounter++}`,c={id:o,dlqConfigId:s.id,messageId:n,status:"pending",startedAt:new Date};return this.reprocessing.set(o,c),setTimeout(()=>{c.status="processing",setTimeout(()=>{let u=Math.random()>0.3;if(c.status=u?"success":"failed",c.completedAt=new Date,!u)c.error="Reprocessing failed - same error occurred";else this.messages.delete(n)},100)},50),c}async batchReprocess(n){let i=this.dlqConfigs.get(n.dlqConfigId);if(!i)throw Error(`DLQ config not found: ${n.dlqConfigId}`);let o=Array.from(this.messages.values()).filter((c)=>c.functionName===i.functionName).slice(0,n.maxMessages||10).map((c)=>this.reprocessMessage(c.id));return Promise.all(o)}getDLQStats(n){let i=this.dlqConfigs.get(n);if(!i)throw Error(`DLQ config not found: ${n}`);let s=Array.from(this.messages.values()).filter((d)=>d.functionName===i.functionName),o={},c=0;for(let d of s)o[d.errorType]=(o[d.errorType]||0)+1,c+=d.attemptCount;let u=s.map((d)=>d.timestamp);return{totalMessages:s.length,oldestMessage:u.length>0?new Date(Math.min(...u.map((d)=>d.getTime()))):void 0,newestMessage:u.length>0?new Date(Math.max(...u.map((d)=>d.getTime()))):void 0,averageAttempts:s.length>0?c/s.length:0,errorTypes:o}}getDLQConfig(n){return this.dlqConfigs.get(n)}listDLQConfigs(){return Array.from(this.dlqConfigs.values())}getDLQMessages(n){let i=this.dlqConfigs.get(n);if(!i)return[];return Array.from(this.messages.values()).filter((s)=>s.functionName===i.functionName)}generateDLQCF(n){return{DeadLetterConfig:{TargetArn:n.targetArn}}}generateSQSDLQCF(n){return{Type:"AWS::SQS::Queue",Properties:{QueueName:`${n.functionName}-dlq`,MessageRetentionPeriod:n.retentionPeriod||1209600,...n.maxReceiveCount&&{RedrivePolicy:{deadLetterTargetArn:n.targetArn,maxReceiveCount:n.maxReceiveCount}}}}}generateDLQAlarmCF(n){let i=this.dlqConfigs.get(n.dlqConfigId);if(!i)throw Error(`DLQ config not found: ${n.dlqConfigId}`);return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:n.alarmName,AlarmDescription:`DLQ alarm for ${i.functionName}`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Sum",Period:300,EvaluationPeriods:n.evaluationPeriods,Threshold:n.threshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:i.targetArn.split(":").pop()}],...n.notificationTopicArn&&{AlarmActions:[n.notificationTopicArn]}}}}clear(){this.dlqConfigs.clear(),this.messages.clear(),this.alarms.clear(),this.reprocessing.clear(),this.configCounter=0,this.messageCounter=0,this.alarmCounter=0,this.reprocessCounter=0}}var yE=new hf;class Ll{policies=new Map;healthChecks=new Map;trafficPolicies=new Map;policyCounter=0;healthCheckCounter=0;trafficPolicyCounter=0;createWeightedPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"weighted",...n};return this.policies.set(i,s),s}createLatencyPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"latency",...n};return this.policies.set(i,s),s}createFailoverPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"failover",...n};return this.policies.set(i,s),s}createGeolocationPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"geolocation",...n};return this.policies.set(i,s),s}createGeoproximityPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"geoproximity",...n};return this.policies.set(i,s),s}createHTTPHealthCheck(n){let i=`health-check-${Date.now()}-${this.healthCheckCounter++}`,s={id:i,type:n.port===443?"https":"http",requestInterval:n.requestInterval||30,failureThreshold:n.failureThreshold||3,healthCheckStatus:"Unknown",port:n.port||(n.port===443?443:80),...n};return this.healthChecks.set(i,s),setTimeout(()=>{s.healthCheckStatus=Math.random()>0.2?"Healthy":"Unhealthy"},100),s}createTCPHealthCheck(n){let i=`health-check-${Date.now()}-${this.healthCheckCounter++}`,s={id:i,type:"tcp",fullyQualifiedDomainName:n.ipAddress,requestInterval:n.requestInterval||30,failureThreshold:n.failureThreshold||3,healthCheckStatus:"Unknown",...n};return this.healthChecks.set(i,s),setTimeout(()=>{s.healthCheckStatus=Math.random()>0.1?"Healthy":"Unhealthy"},100),s}createCalculatedHealthCheck(n){let i=`health-check-${Date.now()}-${this.healthCheckCounter++}`,s={id:i,type:"calculated",requestInterval:30,failureThreshold:0,healthCheckStatus:"Unknown",...n};return this.healthChecks.set(i,s),setTimeout(()=>{let c=n.childHealthChecks.filter((u)=>this.healthChecks.get(u)?.healthCheckStatus==="Healthy").length;s.healthCheckStatus=c>=n.healthThreshold?"Healthy":"Unhealthy"},150),s}createTrafficPolicy(n){let i=`traffic-policy-${Date.now()}-${this.trafficPolicyCounter++}`,s={id:i,version:1,...n};return this.trafficPolicies.set(i,s),s}createFailoverTrafficPolicy(n){return this.createTrafficPolicy({name:n.name,document:{recordType:n.recordType||"A",startRule:"failover",endpoints:{primary:{type:"value",value:n.primaryEndpoint},secondary:{type:"value",value:n.secondaryEndpoint}},rules:{failover:{ruleType:"failover",primary:"primary",secondary:"secondary"}}}})}createGeoproximityTrafficPolicy(n){let i={},s=[];return n.locations.forEach((o,c)=>{let u=`endpoint${c}`;i[u]={type:"value",value:o.endpoint},s.push({endpointReference:u,region:o.region,latitude:o.latitude,longitude:o.longitude,bias:o.bias})}),this.createTrafficPolicy({name:n.name,document:{recordType:"A",startRule:"geoproximity",endpoints:i,rules:{geoproximity:{ruleType:"geoproximity",locations:s}}}})}getPolicy(n){return this.policies.get(n)}listPolicies(){return Array.from(this.policies.values())}getHealthCheck(n){return this.healthChecks.get(n)}listHealthChecks(){return Array.from(this.healthChecks.values())}getHealthCheckStatus(n){return this.healthChecks.get(n)?.healthCheckStatus||"Unknown"}generateHealthCheckCF(n){let i={Type:"AWS::Route53::HealthCheck",Properties:{HealthCheckConfig:{Type:n.type.toUpperCase(),RequestInterval:n.requestInterval,FailureThreshold:n.failureThreshold,...n.measureLatency&&{MeasureLatency:!0}},HealthCheckTags:[{Key:"Name",Value:n.name}]}};if(n.type==="calculated"){let s=n;i.Properties.HealthCheckConfig.ChildHealthChecks=s.childHealthChecks,i.Properties.HealthCheckConfig.HealthThreshold=s.healthThreshold}else{if(n.ipAddress)i.Properties.HealthCheckConfig.IPAddress=n.ipAddress;if(n.fullyQualifiedDomainName)i.Properties.HealthCheckConfig.FullyQualifiedDomainName=n.fullyQualifiedDomainName;if(n.port)i.Properties.HealthCheckConfig.Port=n.port;if(n.resourcePath)i.Properties.HealthCheckConfig.ResourcePath=n.resourcePath;if(n.enableSNI)i.Properties.HealthCheckConfig.EnableSNI=!0}return i}generateWeightedRecordSetCF(n){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:n.name,Type:n.type,TTL:n.ttl,ResourceRecords:n.resourceRecords,Weight:n.weight,SetIdentifier:n.setIdentifier,...n.healthCheckId&&{HealthCheckId:n.healthCheckId}}}}generateFailoverRecordSetCF(n){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:n.name,Type:n.type,TTL:n.ttl,ResourceRecords:n.resourceRecords,Failover:n.failover,SetIdentifier:n.setIdentifier,...n.healthCheckId&&{HealthCheckId:n.healthCheckId}}}}clear(){this.policies.clear(),this.healthChecks.clear(),this.trafficPolicies.clear(),this.policyCounter=0,this.healthCheckCounter=0,this.trafficPolicyCounter=0}}var lS=new Ll;class Af{configs=new Map;ksks=new Map;validations=new Map;configCounter=0;kskCounter=0;validationCounter=0;enableDNSSEC(n){let i=`dnssec-${Date.now()}-${this.configCounter++}`,s={id:i,hostedZoneId:n.hostedZoneId,status:"SIGNING",signingStatus:"Initializing DNSSEC signing"};if(this.configs.set(i,s),n.kmsKeyArn)this.createKSK({name:`ksk-${n.hostedZoneId}`,hostedZoneId:n.hostedZoneId,kmsKeyArn:n.kmsKeyArn});return setTimeout(()=>{s.status="SIGNED",s.signingStatus="DNSSEC signing complete"},100),s}disableDNSSEC(n){let i=this.configs.get(n);if(!i)throw Error(`DNSSEC config not found: ${n}`);return i.status="DELETING",i.signingStatus="Removing DNSSEC signing",setTimeout(()=>{i.status="NOT_SIGNING",i.signingStatus="DNSSEC signing removed"},100),i}createKSK(n){let i=`ksk-${Date.now()}-${this.kskCounter++}`,s={id:i,status:"ACTIVE",flag:257,keyManagementServiceArn:n.kmsKeyArn,digestAlgorithm:2,keyTag:Math.floor(Math.random()*65535),publicKey:this.generatePublicKey(),...n};s.dnskeyRecord=`${s.flag} 3 8 ${s.publicKey}`;let o=this.generateDigest(s.dnskeyRecord);return s.digestValue=o,s.dsRecord=`${s.keyTag} 8 ${s.digestAlgorithm} ${o}`,this.ksks.set(i,s),s}deactivateKSK(n){let i=this.ksks.get(n);if(!i)throw Error(`KSK not found: ${n}`);return i.status="INACTIVE",i}validateDNSSEC(n){let i=`validation-${Date.now()}-${this.validationCounter++}`,s=n.checkDNSKEY!==!1?Math.random()>0.1:!1,o=n.checkRRSIG!==!1?Math.random()>0.1:!1,c=s&&o,u=[];if(!s)u.push("DNSKEY record not found");if(!o)u.push("RRSIG record not found");let d;if(!s&&!o)d="INSECURE";else if(s&&o&&c)d="VALID";else if(s||o)d="BOGUS",u.push("Invalid signature or incomplete DNSSEC chain");else d="INVALID";let g={id:i,domain:n.domain,validationStatus:d,dnskeyPresent:s,rrsigPresent:o,validSignature:c,errors:u};return this.validations.set(i,g),g}getDNSSECConfig(n){return this.configs.get(n)}listDNSSECConfigs(){return Array.from(this.configs.values())}getKSK(n){return this.ksks.get(n)}listKSKs(n){let i=Array.from(this.ksks.values());return n?i.filter((s)=>s.hostedZoneId===n):i}getDSRecord(n){let i=this.ksks.get(n);if(!i||!i.dsRecord)throw Error("DS record not available");return i.dsRecord}generatePublicKey(){let i="";for(let s=0;s<256;s++)i+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(Math.floor(Math.random()*64));return i}generateDigest(n){let s="";for(let o=0;o<64;o++)s+="0123456789ABCDEF".charAt(Math.floor(Math.random()*16));return s}generateDNSSECCF(n){return{Type:"AWS::Route53::DNSSEC",Properties:{HostedZoneId:n.hostedZoneId}}}generateKSKCF(n){return{Type:"AWS::Route53::KeySigningKey",Properties:{Name:n.name,HostedZoneId:n.hostedZoneId,KeyManagementServiceArn:n.keyManagementServiceArn,Status:n.status}}}clear(){this.configs.clear(),this.ksks.clear(),this.validations.clear(),this.configCounter=0,this.kskCounter=0,this.validationCounter=0}}var SE=new Af;class yf{endpoints=new Map;rules=new Map;firewalls=new Map;ruleGroups=new Map;domainLists=new Map;endpointCounter=0;ruleCounter=0;firewallCounter=0;ruleGroupCounter=0;domainListCounter=0;createResolverEndpoint(n){let i=`endpoint-${Date.now()}-${this.endpointCounter++}`,s={id:i,status:"CREATING",...n};return this.endpoints.set(i,s),setTimeout(()=>{s.status="OPERATIONAL",s.ipAddresses.forEach((o)=>{if(!o.ip)o.ip=`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`})},100),s}createInboundEndpoint(n){return this.createResolverEndpoint({name:n.name,direction:"INBOUND",ipAddresses:n.subnetIds.map((i)=>({subnetId:i})),securityGroupIds:n.securityGroupIds})}createOutboundEndpoint(n){return this.createResolverEndpoint({name:n.name,direction:"OUTBOUND",ipAddresses:n.subnetIds.map((i)=>({subnetId:i})),securityGroupIds:n.securityGroupIds})}createResolverRule(n){let i=`rule-${Date.now()}-${this.ruleCounter++}`,s={id:i,status:"CREATING",...n};return this.rules.set(i,s),setTimeout(()=>{s.status="COMPLETE"},100),s}createForwardRule(n){return this.createResolverRule({name:n.name,ruleType:"FORWARD",domainName:n.domainName,targetIps:n.targetIps,resolverEndpointId:n.resolverEndpointId})}createSystemRule(n){return this.createResolverRule({name:n.name,ruleType:"SYSTEM",domainName:n.domainName})}createFirewallDomainList(n){let i=`domain-list-${Date.now()}-${this.domainListCounter++}`,s={id:i,status:"CREATING",...n};return this.domainLists.set(i,s),setTimeout(()=>{s.status="COMPLETE"},100),s}createFirewallRuleGroup(n){let i=`rule-group-${Date.now()}-${this.ruleGroupCounter++}`,s={id:i,name:n.name,rules:n.rules.map((o,c)=>({id:`rule-${i}-${c}`,...o})),shareStatus:"NOT_SHARED"};return this.ruleGroups.set(i,s),s}createBlockRule(n){return this.createFirewallRuleGroup({name:n.name,rules:[{name:n.name,priority:n.priority,action:"BLOCK",blockResponse:n.blockResponse||"NODATA",blockOverrideDomain:n.blockOverrideDomain,firewallDomainListId:n.domainListId}]})}createAllowRule(n){return this.createFirewallRuleGroup({name:n.name,rules:[{name:n.name,priority:n.priority,action:"ALLOW",firewallDomainListId:n.domainListId}]})}createDNSFirewall(n){let i=`firewall-${Date.now()}-${this.firewallCounter++}`,s={id:i,name:n.name,firewallRuleGroupAssociations:n.ruleGroupAssociations.map((o,c)=>({id:`assoc-${i}-${c}`,vpcId:n.vpcId,firewallRuleGroupId:o.firewallRuleGroupId,priority:o.priority,mutationProtection:o.mutationProtection||"DISABLED",status:"COMPLETE"}))};return this.firewalls.set(i,s),s}createMalwareProtectionFirewall(n){let i=this.createFirewallDomainList({name:`${n.name}-malware-domains`,domains:n.maliciousDomains}),s=this.createBlockRule({name:`${n.name}-block-malware`,priority:100,domainListId:i.id,blockResponse:"NXDOMAIN"});return this.createDNSFirewall({name:n.name,vpcId:n.vpcId,ruleGroupAssociations:[{firewallRuleGroupId:s.id,priority:100,mutationProtection:"ENABLED"}]})}getEndpoint(n){return this.endpoints.get(n)}listEndpoints(n){let i=Array.from(this.endpoints.values());return n?i.filter((s)=>s.direction===n):i}getRule(n){return this.rules.get(n)}listRules(){return Array.from(this.rules.values())}getFirewall(n){return this.firewalls.get(n)}listFirewalls(){return Array.from(this.firewalls.values())}generateResolverEndpointCF(n){return{Type:"AWS::Route53Resolver::ResolverEndpoint",Properties:{Name:n.name,Direction:n.direction,IpAddresses:n.ipAddresses.map((i)=>({SubnetId:i.subnetId,...i.ip&&{Ip:i.ip}})),SecurityGroupIds:n.securityGroupIds}}}generateResolverRuleCF(n){return{Type:"AWS::Route53Resolver::ResolverRule",Properties:{Name:n.name,RuleType:n.ruleType,DomainName:n.domainName,...n.targetIps&&{TargetIps:n.targetIps.map((i)=>({Ip:i.ip,Port:i.port||53}))},...n.resolverEndpointId&&{ResolverEndpointId:n.resolverEndpointId}}}}generateFirewallRuleGroupCF(n){return{Type:"AWS::Route53Resolver::FirewallRuleGroup",Properties:{Name:n.name,FirewallRules:n.rules.map((i)=>({Name:i.name,Priority:i.priority,Action:i.action,FirewallDomainListId:i.firewallDomainListId,...i.blockResponse&&{BlockResponse:i.blockResponse},...i.blockOverrideDomain&&{BlockOverrideDomain:i.blockOverrideDomain},...i.blockOverrideTTL&&{BlockOverrideTtl:i.blockOverrideTTL}}))}}}clear(){this.endpoints.clear(),this.rules.clear(),this.firewalls.clear(),this.ruleGroups.clear(),this.domainLists.clear(),this.endpointCounter=0,this.ruleCounter=0,this.firewallCounter=0,this.ruleGroupCounter=0,this.domainListCounter=0}}var IE=new yf;class Sf{bounces=new Map;complaints=new Map;handlers=new Map;suppressionList=new Map;metrics=new Map;bounceCounter=0;complaintCounter=0;handlerCounter=0;suppressionCounter=0;metricsCounter=0;recordBounce(n){let i=`bounce-${Date.now()}-${this.bounceCounter++}`,s={id:i,...n};if(this.bounces.set(i,s),n.bounceType==="Permanent")this.addToSuppressionList({emailAddress:n.recipient,reason:"BOUNCE"});return s}recordComplaint(n){let i=`complaint-${Date.now()}-${this.complaintCounter++}`,s={id:i,...n};this.complaints.set(i,s);for(let o of n.recipients)this.addToSuppressionList({emailAddress:o,reason:"COMPLAINT"});return s}createBounceHandler(n){let i=`handler-${Date.now()}-${this.handlerCounter++}`,s={id:i,...n};return this.handlers.set(i,s),s}createAutomaticBounceHandler(n){return this.createBounceHandler({name:n.name,bounceThreshold:5,complaintThreshold:0.1,suppressionDuration:2592000,autoSuppress:!0,notificationTopicArn:n.notificationTopicArn})}addToSuppressionList(n){let i=`suppression-${Date.now()}-${this.suppressionCounter++}`,s=n.expirationDays?new Date(Date.now()+n.expirationDays*24*60*60*1000):void 0,o={id:i,emailAddress:n.emailAddress,reason:n.reason,suppressedAt:new Date,expiresAt:s,bounceCount:n.reason==="BOUNCE"?1:0,complaintCount:n.reason==="COMPLAINT"?1:0};return this.suppressionList.set(n.emailAddress,o),o}removeFromSuppressionList(n){return this.suppressionList.delete(n)}isSuppressed(n){let i=this.suppressionList.get(n);if(!i)return!1;if(i.expiresAt&&i.expiresAt<new Date)return this.suppressionList.delete(n),!1;return!0}getBounceStatistics(n,i){let s=Array.from(this.bounces.values()).filter((A)=>A.timestamp>=n&&A.timestamp<=i),o=s.length,c=s.filter((A)=>A.bounceType==="Permanent").length,u=s.filter((A)=>A.bounceType==="Transient").length,d=o*10,g=o/d*100,y=new Map;for(let A of s)y.set(A.recipient,(y.get(A.recipient)||0)+1);let h=Array.from(y.entries()).map(([A,C])=>({email:A,count:C})).sort((A,C)=>C.count-A.count).slice(0,10);return{totalBounces:o,permanentBounces:c,transientBounces:u,bounceRate:g,topRecipients:h}}getComplaintStatistics(n,i){let s=Array.from(this.complaints.values()).filter((y)=>y.timestamp>=n&&y.timestamp<=i),o=s.length,c=new Set;for(let y of s)for(let h of y.recipients)c.add(h);let u=c.size,d=o*1000,g=o/d*100;return{totalComplaints:o,uniqueComplainters:u,complaintRate:g}}calculateReputationMetrics(){let n=`metrics-${Date.now()}-${this.metricsCounter++}`,i=new Date,s=new Date(i.getTime()-86400000),o=this.getBounceStatistics(s,i),c=this.getComplaintStatistics(s,i),u;if(o.bounceRate>10||c.complaintRate>0.5)u="Shutdown";else if(o.bounceRate>5||c.complaintRate>0.1)u="Probation";else if(o.bounceRate>2||c.complaintRate>0.05)u="Warning";else u="Good";let d={id:n,timestamp:i,bounceRate:o.bounceRate,complaintRate:c.complaintRate,sendingQuota:50000,maxSendRate:14,sentLast24Hours:o.totalBounces*10,reputationStatus:u};return this.metrics.set(n,d),d}getBounces(n){let i=Array.from(this.bounces.values());return n?i.filter((s)=>s.messageId===n):i}getComplaints(n){let i=Array.from(this.complaints.values());return n?i.filter((s)=>s.messageId===n):i}listSuppressionList(n){let i=Array.from(this.suppressionList.values());return n?i.filter((s)=>s.reason===n):i}generateSNSSubscriptionCF(n){return{Type:"AWS::SNS::Subscription",Properties:{TopicArn:n.topicArn,Endpoint:n.endpoint,Protocol:n.protocol}}}generateEventDestinationCF(n){return{Type:"AWS::SES::ConfigurationSetEventDestination",Properties:{ConfigurationSetName:n.configurationSetName,EventDestination:{Name:n.eventDestinationName,Enabled:!0,MatchingEventTypes:n.eventTypes,...n.snsTopicArn&&{SnsDestination:{TopicARN:n.snsTopicArn}},...n.cloudWatchDestination&&{CloudWatchDestination:n.cloudWatchDestination}}}}}clear(){this.bounces.clear(),this.complaints.clear(),this.handlers.clear(),this.suppressionList.clear(),this.metrics.clear(),this.bounceCounter=0,this.complaintCounter=0,this.handlerCounter=0,this.suppressionCounter=0,this.metricsCounter=0}}var bE=new Sf;class If{events=new Map;campaigns=new Map;reports=new Map;abTests=new Map;eventCounter=0;campaignCounter=0;reportCounter=0;abTestCounter=0;trackEvent(n){let i=`event-${Date.now()}-${this.eventCounter++}`,s={id:i,...n};if(this.events.set(i,s),n.tags?.campaignId)this.updateCampaignStats(n.tags.campaignId,n.eventType);return s}trackOpen(n){return this.trackEvent({...n,eventType:"open",timestamp:new Date})}trackClick(n){return this.trackEvent({...n,eventType:"click",timestamp:new Date})}createCampaign(n){let i=`campaign-${Date.now()}-${this.campaignCounter++}`,s={id:i,sentCount:0,deliveredCount:0,openCount:0,clickCount:0,bounceCount:0,complaintCount:0,createdAt:new Date,...n};return this.campaigns.set(i,s),s}updateCampaignStats(n,i){let s=this.campaigns.get(n);if(!s)return;switch(i){case"send":s.sentCount++;break;case"delivery":s.deliveredCount++;break;case"open":s.openCount++;break;case"click":s.clickCount++;break;case"bounce":s.bounceCount++;break;case"complaint":s.complaintCount++;break}}generateReport(n){let i=`report-${Date.now()}-${this.reportCounter++}`,s=Array.from(this.events.values()).filter((N)=>{let O=N.timestamp>=n.startDate&&N.timestamp<=n.endDate,B=!n.campaignId||N.tags?.campaignId===n.campaignId;return O&&B}),o=s.filter((N)=>N.eventType==="send").length,c=s.filter((N)=>N.eventType==="delivery").length,u=s.filter((N)=>N.eventType==="open").length,d=s.filter((N)=>N.eventType==="click").length,g=s.filter((N)=>N.eventType==="bounce").length,y=s.filter((N)=>N.eventType==="complaint").length,h=o>0?c/o*100:0,A=c>0?u/c*100:0,C=c>0?d/c*100:0,v=u>0?d/u*100:0,T=o>0?g/o*100:0,R=c>0?y/c*100:0,P=new Map;for(let N of s)if(N.eventType==="click"){let O=N;P.set(O.link,(P.get(O.link)||0)+1)}let I=Array.from(P.entries()).map(([N,O])=>({link:N,clicks:O})).sort((N,O)=>O.clicks-N.clicks).slice(0,10),M={desktop:0,mobile:0,tablet:0,unknown:0};for(let N of s)if(N.eventType==="open"||N.eventType==="click"){let O=N.userAgent.toLowerCase();if(O.includes("mobile"))M.mobile++;else if(O.includes("tablet"))M.tablet++;else if(O.includes("mozilla"))M.desktop++;else M.unknown++}let L={id:i,campaignId:n.campaignId,startDate:n.startDate,endDate:n.endDate,totalSent:o,totalDelivered:c,totalOpened:u,totalClicked:d,totalBounced:g,totalComplaints:y,deliveryRate:h,openRate:A,clickRate:C,clickToOpenRate:v,bounceRate:T,complaintRate:R,topLinks:I,deviceBreakdown:M,locationBreakdown:{}};return this.reports.set(i,L),L}createABTest(n){let i=`abtest-${Date.now()}-${this.abTestCounter++}`,s={id:i,name:n.name,variants:n.variants.map((o,c)=>({id:`variant-${i}-${c}`,sentCount:0,openCount:0,clickCount:0,conversionCount:0,...o})),status:"draft"};return this.abTests.set(i,s),s}startABTest(n){let i=this.abTests.get(n);if(!i)throw Error(`A/B test not found: ${n}`);return i.status="running",i.startedAt=new Date,i}completeABTest(n){let i=this.abTests.get(n);if(!i)throw Error(`A/B test not found: ${n}`);let s=i.variants[0],o=0;for(let c of i.variants){let u=c.sentCount>0?c.openCount/c.sentCount:0;if(u>o)o=u,s=c}return i.status="completed",i.completedAt=new Date,i.winner=s.id,i}getCampaign(n){return this.campaigns.get(n)}listCampaigns(){return Array.from(this.campaigns.values())}getEvents(n){let i=Array.from(this.events.values());if(n?.messageId)i=i.filter((s)=>s.messageId===n.messageId);if(n?.eventType)i=i.filter((s)=>s.eventType===n.eventType);if(n?.startDate)i=i.filter((s)=>s.timestamp>=n.startDate);if(n?.endDate)i=i.filter((s)=>s.timestamp<=n.endDate);return i}generateTrackingConfigurationCF(n){return{Type:"AWS::SES::ConfigurationSet",Properties:{Name:n.configurationSetName,...n.openTracking&&{TrackingOptions:{CustomRedirectDomain:"tracking.example.com"}}}}}clear(){this.events.clear(),this.campaigns.clear(),this.reports.clear(),this.abTests.clear(),this.eventCounter=0,this.campaignCounter=0,this.reportCounter=0,this.abTestCounter=0}}var CE=new If;class bf{dashboards=new Map;warmupPlans=new Map;domainReputations=new Map;dashboardCounter=0;warmupCounter=0;domainCounter=0;getReputationDashboard(){let n=`dashboard-${Date.now()}-${this.dashboardCounter++}`,i=Math.random()*5,s=Math.random()*0.5,o=Math.floor(Math.random()*10),c=Math.max(0,100-i*10-s*100-o*2),u=[];if(i>2)u.push("Reduce bounce rate by cleaning email list");if(s>0.1)u.push("Review email content and unsubscribe process");if(o>5)u.push("Improve email relevance and targeting");let d={id:n,timestamp:new Date,overallScore:c,bounceRate:i,complaintRate:s,spamReports:o,blacklistStatus:this.checkBlacklists(),dkimStatus:"VERIFIED",spfStatus:"PASS",dmarcStatus:"PASS",sendingLimits:{maxSendRate:14,max24HourSend:50000,sentLast24Hours:12000,remainingQuota:38000,quotaResetTime:new Date(Date.now()+86400000)},recommendations:u};return this.dashboards.set(n,d),d}checkBlacklists(){return["Spamhaus ZEN","Spamcop","SORBS","Barracuda","URIBL"].map((i)=>({listName:i,listed:Math.random()>0.95,delistUrl:`https://www.${i.toLowerCase().replace(/\s/g,"")}.org/delist`}))}createWarmupPlan(n){let i=`warmup-${Date.now()}-${this.warmupCounter++}`,s=[],o=(n.targetDailyLimit-n.initialDailyLimit)/n.durationDays;for(let u=0;u<n.durationDays;u++)s.push(Math.floor(n.initialDailyLimit+o*u));let c={id:i,name:n.name,startDate:new Date,currentDay:1,totalDays:n.durationDays,dailyLimits:s,currentLimit:s[0],status:"active"};return this.warmupPlans.set(i,c),c}createAggressiveWarmupPlan(n){return this.createWarmupPlan({name:n.name,initialDailyLimit:500,targetDailyLimit:50000,durationDays:14})}createConservativeWarmupPlan(n){return this.createWarmupPlan({name:n.name,initialDailyLimit:200,targetDailyLimit:50000,durationDays:30})}advanceWarmupPlan(n){let i=this.warmupPlans.get(n);if(!i)throw Error(`Warmup plan not found: ${n}`);if(i.currentDay<i.totalDays)i.currentDay++,i.currentLimit=i.dailyLimits[i.currentDay-1];if(i.currentDay>=i.totalDays)i.status="completed";return i}trackDomainReputation(n){let i=`domain-${Date.now()}-${this.domainCounter++}`,s=n.delivered/n.totalSent*100,o=n.delivered>0?n.opened/n.delivered*100:0,c=n.delivered>0?n.clicked/n.delivered*100:0,u=n.bounced/n.totalSent*100,d=n.delivered>0?n.complained/n.delivered*100:0,g=o*0.4+c*0.6,y=Math.max(0,100-u*10-d*100+g*0.2),h={id:i,domain:n.domain,reputationScore:y,totalSent:n.totalSent,deliveryRate:s,openRate:o,clickRate:c,bounceRate:u,complaintRate:d,engagementScore:g};return this.domainReputations.set(n.domain,h),h}getDomainReputation(n){return this.domainReputations.get(n)}listDomainReputations(){return Array.from(this.domainReputations.values())}getWarmupPlan(n){return this.warmupPlans.get(n)}listWarmupPlans(){return Array.from(this.warmupPlans.values())}clear(){this.dashboards.clear(),this.warmupPlans.clear(),this.domainReputations.clear(),this.dashboardCounter=0,this.warmupCounter=0,this.domainCounter=0}}var EE=new bf;class Cf{templates=new Map;versions=new Map;tests=new Map;templateCounter=0;testCounter=0;createTemplate(n){let i=`template-${Date.now()}-${this.templateCounter++}`,s=this.extractVariables(n.subject+n.htmlPart+n.textPart),o={id:i,variables:s,createdAt:new Date,updatedAt:new Date,version:1,...n};return this.templates.set(i,o),this.addVersion({templateId:i,version:1,subject:n.subject,htmlPart:n.htmlPart,textPart:n.textPart,createdBy:"system"}),o}createWelcomeTemplate(n){return this.createTemplate({name:n.name,subject:"Welcome to {{companyName}}!",htmlPart:`
3739
+ COPY . .`,impact:"Improve build time by 60-80% on subsequent builds"});let g={sizeBefore:i.totalSize,sizeAfter:i.totalSize*0.6,timeBefore:300,timeAfter:120},y={id:s,name:`Optimization for ${i.imageId}`,recommendations:o,estimatedSavings:g};return this.optimizations.set(s,y),y}getBuildConfig(n){return this.configs.get(n)}listBuildConfigs(){return Array.from(this.configs.values())}getMultiStageConfig(n){return this.multiStageConfigs.get(n)}listMultiStageConfigs(){return Array.from(this.multiStageConfigs.values())}getOptimization(n){return this.optimizations.get(n)}listOptimizations(){return Array.from(this.optimizations.values())}clear(){this.configs.clear(),this.multiStageConfigs.clear(),this.optimizations.clear(),this.analyses.clear(),this.configCounter=0,this.multiStageCounter=0,this.optimizationCounter=0,this.analysisCounter=0}}var TE=new If;class Gl{registries=new Map;credentials=new Map;registryCounter=0;credentialsCounter=0;createRegistry(n){let i=`registry-${Date.now()}-${this.registryCounter++}`,s={id:i,...n};return this.registries.set(i,s),s}createECRRepository(n){return this.createRegistry({name:n.name,registryType:"ecr",repositoryUri:`123456789012.dkr.ecr.${n.region||"us-east-1"}.amazonaws.com/${n.name}`,region:n.region||"us-east-1",encryption:{encryptionType:n.encryption||"AES256",kmsKeyId:n.kmsKeyId},scanning:{scanOnPush:n.scanOnPush??!0}})}createManagedRepository(n){let i=this.createECRRepository({name:n.name,region:n.region,scanOnPush:!0,encryption:"KMS"});return i.lifecycle={id:`lifecycle-${Date.now()}`,rules:[{rulePriority:1,description:"Keep only last N images",selection:{tagStatus:"any",countType:"imageCountMoreThan",countNumber:n.maxImageCount||10},action:{type:"expire"}},{rulePriority:2,description:"Remove images older than N days",selection:{tagStatus:"untagged",countType:"sinceImagePushed",countNumber:n.maxImageAgeDays||30,countUnit:"days"},action:{type:"expire"}}]},i}enableReplication(n,i){let s=this.registries.get(n);if(!s)throw Error(`Registry not found: ${n}`);return s.replication={enabled:!0,destinations:i},s}createCredentials(n){let i=`creds-${Date.now()}-${this.credentialsCounter++}`,s={id:i,...n};return this.credentials.set(i,s),s}getRegistry(n){return this.registries.get(n)}listRegistries(){return Array.from(this.registries.values())}generateECRRepositoryCF(n){return{Type:"AWS::ECR::Repository",Properties:{RepositoryName:n.name,ImageScanningConfiguration:{ScanOnPush:n.scanning?.scanOnPush??!1},EncryptionConfiguration:{EncryptionType:n.encryption?.encryptionType||"AES256",...n.encryption?.kmsKeyId&&{KmsKey:n.encryption.kmsKeyId}},ImageTagMutability:"MUTABLE",...n.lifecycle&&{LifecyclePolicy:{LifecyclePolicyText:JSON.stringify({rules:n.lifecycle.rules})}}}}}generateReplicationConfigCF(n){return{Type:"AWS::ECR::ReplicationConfiguration",Properties:{ReplicationConfiguration:{Rules:n.destinations.map((i)=>({Destinations:[{Region:i.region,...i.registryId&&{RegistryId:i.registryId}}]}))}}}}clear(){this.registries.clear(),this.credentials.clear(),this.registryCounter=0,this.credentialsCounter=0}}var IS=new Gl;class Vl{meshes=new Map;virtualNodes=new Map;virtualRouters=new Map;virtualGateways=new Map;meshCounter=0;nodeCounter=0;routerCounter=0;gatewayCounter=0;createMesh(n){let i=`mesh-${Date.now()}-${this.meshCounter++}`,s={id:i,...n};return this.meshes.set(i,s),s}createAppMesh(n){return this.createMesh({name:n.name,meshType:"app_mesh",services:n.services,virtualNodes:[],virtualRouters:[],virtualGateways:[]})}createVirtualNode(n){let i=`vnode-${Date.now()}-${this.nodeCounter++}`,s={id:i,...n};return this.virtualNodes.set(i,s),s}createHTTPVirtualNode(n){return this.createVirtualNode({name:n.name,serviceName:n.serviceName,listeners:[{port:n.port,protocol:"http",healthCheck:{protocol:"http",path:"/health",interval:30,timeout:10,healthyThreshold:2,unhealthyThreshold:3},timeout:{perRequest:15000,idle:300000}}],serviceDiscovery:{type:"aws_cloud_map",namespace:n.namespace,serviceName:n.serviceName}})}createVirtualRouter(n){let i=`vrouter-${Date.now()}-${this.routerCounter++}`,s={id:i,...n};return this.virtualRouters.set(i,s),s}createCanaryRoute(n){return this.createVirtualRouter({name:n.name,listeners:[{port:n.port,protocol:n.protocol}],routes:[{name:"canary-route",match:{prefix:"/"},action:{weightedTargets:[{virtualNode:n.stableTarget,weight:100-n.canaryWeight},{virtualNode:n.canaryTarget,weight:n.canaryWeight}]},retryPolicy:{maxRetries:3,perRetryTimeout:5000,httpRetryEvents:["server-error","gateway-error"],tcpRetryEvents:["connection-error"]}}]})}createVirtualGateway(n){let i=`vgateway-${Date.now()}-${this.gatewayCounter++}`,s={id:i,...n};return this.virtualGateways.set(i,s),s}createIngressGateway(n){let i={port:n.port,protocol:"http",healthCheck:{protocol:"http",path:"/health",interval:30,timeout:10,healthyThreshold:2,unhealthyThreshold:3}};if(n.enableTLS&&n.certificateArn)i.tls={mode:"STRICT",certificate:{acm:n.certificateArn}};return this.createVirtualGateway({name:n.name,listeners:[i],logging:{accessLog:{file:{path:"/dev/stdout"}}}})}getMesh(n){return this.meshes.get(n)}listMeshes(){return Array.from(this.meshes.values())}getVirtualNode(n){return this.virtualNodes.get(n)}listVirtualNodes(){return Array.from(this.virtualNodes.values())}generateMeshCF(n){return{Type:"AWS::AppMesh::Mesh",Properties:{MeshName:n.name,Spec:{EgressFilter:{Type:"ALLOW_ALL"}}}}}generateVirtualNodeCF(n,i){return{Type:"AWS::AppMesh::VirtualNode",Properties:{MeshName:i,VirtualNodeName:n.name,Spec:{Listeners:n.listeners.map((s)=>({PortMapping:{Port:s.port,Protocol:s.protocol},...s.healthCheck&&{HealthCheck:{Protocol:s.healthCheck.protocol,...s.healthCheck.path&&{Path:s.healthCheck.path},IntervalMillis:s.healthCheck.interval*1000,TimeoutMillis:s.healthCheck.timeout*1000,HealthyThreshold:s.healthCheck.healthyThreshold,UnhealthyThreshold:s.healthCheck.unhealthyThreshold}}})),ServiceDiscovery:{AWSCloudMap:{NamespaceName:n.serviceDiscovery.namespace,ServiceName:n.serviceDiscovery.serviceName}}}}}}generateVirtualRouterCF(n,i){return{Type:"AWS::AppMesh::VirtualRouter",Properties:{MeshName:i,VirtualRouterName:n.name,Spec:{Listeners:n.listeners.map((s)=>({PortMapping:{Port:s.port,Protocol:s.protocol}}))}}}}clear(){this.meshes.clear(),this.virtualNodes.clear(),this.virtualRouters.clear(),this.virtualGateways.clear(),this.meshCounter=0,this.nodeCounter=0,this.routerCounter=0,this.gatewayCounter=0}}var bS=new Vl;class bf{layers=new Map;versions=new Map;permissions=new Map;layerCounter=0;versionCounter=0;permissionCounter=0;createLayer(n){let i=`layer-${Date.now()}-${this.layerCounter++}`,s=1,o={id:i,layerArn:`arn:aws:lambda:us-east-1:123456789012:layer:${n.layerName}:1`,version:1,...n};return this.layers.set(i,o),o}createNodeDependenciesLayer(n){return this.createLayer({layerName:n.layerName,description:"Node.js dependencies layer",compatibleRuntimes:[`nodejs${n.nodeVersion}`],content:{type:"s3",s3Bucket:n.s3Bucket,s3Key:n.s3Key},size:5242880})}createUtilitiesLayer(n){return this.createLayer({layerName:n.layerName,description:"Shared utilities and helpers",compatibleRuntimes:n.runtimes,content:{type:"s3",s3Bucket:n.s3Bucket,s3Key:n.s3Key},size:1048576})}publishVersion(n){let i=this.layers.get(n);if(!i)throw Error(`Layer not found: ${n}`);let s=`version-${Date.now()}-${this.versionCounter++}`,o=i.version+1,c={id:s,layerName:i.layerName,version:o,createdAt:new Date,compatibleRuntimes:i.compatibleRuntimes,size:i.size,codeHash:this.generateHash()};return this.versions.set(s,c),i.version=o,i.layerArn=`arn:aws:lambda:us-east-1:123456789012:layer:${i.layerName}:${o}`,c}addPermission(n){let i=`permission-${Date.now()}-${this.permissionCounter++}`,s={id:i,layerName:n.layerName,version:n.version,principal:n.principal,action:"lambda:GetLayerVersion",organizationId:n.organizationId};return this.permissions.set(i,s),s}generateHash(){return Math.random().toString(36).substring(2,15)}getLayer(n){return this.layers.get(n)}listLayers(){return Array.from(this.layers.values())}getLayerVersions(n){return Array.from(this.versions.values()).filter((i)=>i.layerName===n)}generateLayerCF(n){return{Type:"AWS::Lambda::LayerVersion",Properties:{LayerName:n.layerName,Description:n.description,Content:n.content.type==="s3"?{S3Bucket:n.content.s3Bucket,S3Key:n.content.s3Key,...n.content.s3ObjectVersion&&{S3ObjectVersion:n.content.s3ObjectVersion}}:{ZipFile:n.content.zipFile},CompatibleRuntimes:n.compatibleRuntimes,...n.licenseInfo&&{LicenseInfo:n.licenseInfo}}}}generateLayerPermissionCF(n){return{Type:"AWS::Lambda::LayerVersionPermission",Properties:{LayerVersionArn:`arn:aws:lambda:us-east-1:123456789012:layer:${n.layerName}:${n.version}`,Action:n.action,Principal:n.principal,...n.organizationId&&{OrganizationId:n.organizationId}}}}clear(){this.layers.clear(),this.versions.clear(),this.permissions.clear(),this.layerCounter=0,this.versionCounter=0,this.permissionCounter=0}}var wE=new bf;class Cf{versions=new Map;aliases=new Map;deployments=new Map;versionCounter=0;aliasCounter=0;deploymentCounter=0;publishVersion(n){let i=`version-${Date.now()}-${this.versionCounter++}`,s=this.getNextVersionNumber(n.functionName),o={id:i,functionName:n.functionName,version:s.toString(),functionArn:`arn:aws:lambda:us-east-1:123456789012:function:${n.functionName}:${s}`,codeHash:this.generateHash(),description:n.description,runtime:n.runtime,memorySize:n.memorySize,timeout:n.timeout,publishedAt:new Date};return this.versions.set(i,o),o}getNextVersionNumber(n){let i=Array.from(this.versions.values()).filter((s)=>s.functionName===n).map((s)=>parseInt(s.version));return i.length>0?Math.max(...i)+1:1}createAlias(n){let i=`alias-${Date.now()}-${this.aliasCounter++}`,s={id:i,aliasArn:`arn:aws:lambda:us-east-1:123456789012:function:${n.functionName}:${n.aliasName}`,revisionId:this.generateHash(),...n};return this.aliases.set(i,s),s}createProductionAlias(n){return this.createAlias({functionName:n.functionName,aliasName:"production",functionVersion:n.version,description:"Production alias"})}createStagingAlias(n){return this.createAlias({functionName:n.functionName,aliasName:"staging",functionVersion:n.version,description:"Staging alias"})}updateAlias(n,i){let s=this.aliases.get(n);if(!s)throw Error(`Alias not found: ${n}`);return s.functionVersion=i,s.revisionId=this.generateHash(),s}configureWeightedRouting(n,i){let s=this.aliases.get(n);if(!s)throw Error(`Alias not found: ${n}`);return s.routingConfig={additionalVersionWeights:i},s}createCanaryDeployment(n){let i=`deployment-${Date.now()}-${this.deploymentCounter++}`,s=Array.from(this.aliases.values()).find((c)=>c.functionName===n.functionName&&c.aliasName===n.aliasName);if(!s)s=this.createAlias({functionName:n.functionName,aliasName:n.aliasName,functionVersion:n.fromVersion});this.configureWeightedRouting(s.id,{[n.toVersion]:n.canaryWeight});let o={id:i,functionName:n.functionName,fromVersion:n.fromVersion,toVersion:n.toVersion,aliasName:n.aliasName,strategy:"canary",status:"in_progress",startedAt:new Date};return this.deployments.set(i,o),o}completeDeployment(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);let s=Array.from(this.aliases.values()).find((o)=>o.functionName===i.functionName&&o.aliasName===i.aliasName);if(s)s.functionVersion=i.toVersion,s.routingConfig=void 0;return i.status="completed",i.completedAt=new Date,i}rollbackDeployment(n){let i=this.deployments.get(n);if(!i)throw Error(`Deployment not found: ${n}`);let s=Array.from(this.aliases.values()).find((o)=>o.functionName===i.functionName&&o.aliasName===i.aliasName);if(s)s.functionVersion=i.fromVersion,s.routingConfig=void 0;return i.status="failed",i.completedAt=new Date,i}generateHash(){return Math.random().toString(36).substring(2,15)}getVersion(n){return this.versions.get(n)}listVersions(n){let i=Array.from(this.versions.values());return n?i.filter((s)=>s.functionName===n):i}getAlias(n){return this.aliases.get(n)}listAliases(n){let i=Array.from(this.aliases.values());return n?i.filter((s)=>s.functionName===n):i}generateVersionCF(n){return{Type:"AWS::Lambda::Version",Properties:{FunctionName:n.functionName,Description:n.description}}}generateAliasCF(n){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:n.functionName,Name:n.aliasName,FunctionVersion:n.functionVersion,Description:n.description,...n.routingConfig&&{RoutingConfig:{AdditionalVersionWeights:Object.entries(n.routingConfig.additionalVersionWeights||{}).map(([i,s])=>({FunctionVersion:i,FunctionWeight:s}))}}}}}clear(){this.versions.clear(),this.aliases.clear(),this.deployments.clear(),this.versionCounter=0,this.aliasCounter=0,this.deploymentCounter=0}}var RE=new Cf;class Ef{configs=new Map;provisionedConfigs=new Map;schedules=new Map;autoScalingConfigs=new Map;configCounter=0;provisionedCounter=0;scheduleCounter=0;autoScalingCounter=0;setReservedConcurrency(n){let i=`concurrency-${Date.now()}-${this.configCounter++}`,s={id:i,functionName:n.functionName,reservedConcurrency:n.reservedConcurrency};return this.configs.set(i,s),s}setProvisionedConcurrency(n){let i=`provisioned-${Date.now()}-${this.provisionedCounter++}`,s={id:i,functionName:n.functionName,qualifier:n.qualifier,provisionedConcurrentExecutions:n.provisionedConcurrentExecutions,status:"pending",lastModified:new Date};return this.provisionedConfigs.set(i,s),setTimeout(()=>{s.status="ready",s.allocatedConcurrency=n.provisionedConcurrentExecutions,s.availableConcurrency=n.provisionedConcurrentExecutions},100),s}configureWarmPool(n){return this.setProvisionedConcurrency({functionName:n.functionName,qualifier:n.alias,provisionedConcurrentExecutions:n.minInstances})}createSchedule(n){let i=`schedule-${Date.now()}-${this.scheduleCounter++}`,s={id:i,...n};return this.schedules.set(i,s),s}createBusinessHoursSchedule(n){return this.createSchedule({name:`${n.functionName}-business-hours`,functionName:n.functionName,qualifier:n.qualifier,schedule:[{name:"business-hours",cronExpression:"0 8 * * MON-FRI",targetConcurrency:n.businessHoursConcurrency},{name:"off-hours",cronExpression:"0 18 * * MON-FRI",targetConcurrency:n.offHoursConcurrency},{name:"weekend",cronExpression:"0 0 * * SAT",targetConcurrency:n.offHoursConcurrency}]})}configureAutoScaling(n){let i=`autoscaling-${Date.now()}-${this.autoScalingCounter++}`,s={id:i,...n};return this.autoScalingConfigs.set(i,s),s}configurePredictiveScaling(n){return this.configureAutoScaling({functionName:n.functionName,qualifier:n.qualifier,minCapacity:n.baselineCapacity,maxCapacity:n.peakCapacity,targetUtilization:0.7,scaleInCooldown:300,scaleOutCooldown:60})}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getProvisionedConfig(n){return this.provisionedConfigs.get(n)}listProvisionedConfigs(){return Array.from(this.provisionedConfigs.values())}generateReservedConcurrencyCF(n){return{Type:"AWS::Lambda::Function",Properties:{FunctionName:n.functionName,ReservedConcurrentExecutions:n.reservedConcurrency}}}generateProvisionedConcurrencyCF(n){return{Type:"AWS::Lambda::Alias",Properties:{FunctionName:n.functionName,Name:n.qualifier,ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:n.provisionedConcurrentExecutions}}}}generateAutoScalingTargetCF(n){return{Type:"AWS::ApplicationAutoScaling::ScalableTarget",Properties:{ServiceNamespace:"lambda",ResourceId:`function:${n.functionName}:${n.qualifier}`,ScalableDimension:"lambda:function:ProvisionedConcurrentExecutions",MinCapacity:n.minCapacity,MaxCapacity:n.maxCapacity}}}generateAutoScalingPolicyCF(n){return{Type:"AWS::ApplicationAutoScaling::ScalingPolicy",Properties:{PolicyName:`${n.functionName}-autoscaling`,PolicyType:"TargetTrackingScaling",ScalingTargetId:{Ref:`${n.functionName}AutoScalingTarget`},TargetTrackingScalingPolicyConfiguration:{TargetValue:n.targetUtilization*100,PredefinedMetricSpecification:{PredefinedMetricType:"LambdaProvisionedConcurrencyUtilization"},ScaleInCooldown:n.scaleInCooldown||300,ScaleOutCooldown:n.scaleOutCooldown||60}}}}clear(){this.configs.clear(),this.provisionedConfigs.clear(),this.schedules.clear(),this.autoScalingConfigs.clear(),this.configCounter=0,this.provisionedCounter=0,this.scheduleCounter=0,this.autoScalingCounter=0}}var DE=new Ef;class vf{destinations=new Map;records=new Map;eventBridgeDestinations=new Map;destinationCounter=0;recordCounter=0;eventBridgeCounter=0;configureDestinations(n){let i=`destination-${Date.now()}-${this.destinationCounter++}`,s={id:i,...n};return this.destinations.set(i,s),s}configureSQSDestination(n){let i={type:"sqs",arn:n.queueArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureSNSDestination(n){let i={type:"sns",arn:n.topicArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureEventBridgeDestination(n){let i={type:"eventbridge",arn:n.eventBusArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureLambdaDestination(n){let i={type:"lambda",arn:n.destinationFunctionArn};return this.configureDestinations({functionName:n.functionName,successDestination:n.onSuccess?i:void 0,failureDestination:n.onFailure?i:void 0,maxEventAge:21600,maxRetries:2})}configureDLQWithNotification(n){return this.configureDestinations({functionName:n.functionName,failureDestination:{type:"sqs",arn:n.dlqArn},maxEventAge:3600,maxRetries:0})}createEventBridgeIntegration(n){let i=`eventbridge-${Date.now()}-${this.eventBridgeCounter++}`,s={id:i,functionName:n.functionName,eventBusArn:n.eventBusArn,detailType:n.detailType||"Lambda Function Invocation Result",source:n.source||`lambda.${n.functionName}`};return this.eventBridgeDestinations.set(i,s),s}sendToDestination(n){let i=Array.from(this.destinations.values()).find((u)=>u.functionName===n.functionName);if(!i)return null;let s=n.status==="success"?i.successDestination:i.failureDestination;if(!s)return null;let o=`record-${Date.now()}-${this.recordCounter++}`,c={id:o,timestamp:new Date,functionName:n.functionName,requestId:n.requestId,status:n.status,destinationType:s.type,destinationArn:s.arn,payload:n.payload,error:n.error};return this.records.set(o,c),c}getDestination(n){return this.destinations.get(n)}listDestinations(n){let i=Array.from(this.destinations.values());return n?i.filter((s)=>s.functionName===n):i}getDestinationRecords(n){let i=Array.from(this.records.values());return n?i.filter((s)=>s.functionName===n):i}generateEventInvokeConfigCF(n){return{Type:"AWS::Lambda::EventInvokeConfig",Properties:{FunctionName:n.functionName,Qualifier:n.qualifier||"$LATEST",MaximumEventAgeInSeconds:n.maxEventAge||21600,MaximumRetryAttempts:n.maxRetries??2,...n.successDestination&&{DestinationConfig:{OnSuccess:{Destination:n.successDestination.arn}}},...n.failureDestination&&{DestinationConfig:{OnFailure:{Destination:n.failureDestination.arn}}}}}}generateEventBridgeRuleCF(n){return{Type:"AWS::Events::Rule",Properties:{EventBusName:n.eventBusArn.split("/").pop(),EventPattern:{source:[n.source],"detail-type":[n.detailType]},State:"ENABLED",Targets:[{Arn:`arn:aws:lambda:us-east-1:123456789012:function:${n.functionName}`,Id:n.id}]}}}clear(){this.destinations.clear(),this.records.clear(),this.eventBridgeDestinations.clear(),this.destinationCounter=0,this.recordCounter=0,this.eventBridgeCounter=0}}var PE=new vf;class Tf{vpcConfigs=new Map;endpoints=new Map;networkInterfaces=new Map;connectivity=new Map;configCounter=0;endpointCounter=0;eniCounter=0;connectivityCounter=0;configureVPC(n){let i=`vpc-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};this.vpcConfigs.set(i,s);for(let o of n.subnetIds)this.createNetworkInterface({functionName:n.functionName,subnetId:o});return s}configurePrivateVPC(n){return this.configureVPC({functionName:n.functionName,vpcId:n.vpcId,subnetIds:n.privateSubnetIds,securityGroupIds:[n.securityGroupId],ipv6Allowed:!1})}configureMultiAZVPC(n){if(n.subnetIds.length<2)throw Error("Multi-AZ configuration requires at least 2 subnets");return this.configureVPC({functionName:n.functionName,vpcId:n.vpcId,subnetIds:n.subnetIds,securityGroupIds:n.securityGroupIds})}createVPCEndpoint(n){let i=`endpoint-${Date.now()}-${this.endpointCounter++}`,s={id:i,...n};return this.endpoints.set(i,s),s}createS3Endpoint(n){return this.createVPCEndpoint({vpcId:n.vpcId,serviceName:"com.amazonaws.us-east-1.s3",endpointType:"Gateway",privateDnsEnabled:!1})}createDynamoDBEndpoint(n){return this.createVPCEndpoint({vpcId:n.vpcId,serviceName:"com.amazonaws.us-east-1.dynamodb",endpointType:"Gateway",privateDnsEnabled:!1})}createSecretsManagerEndpoint(n){return this.createVPCEndpoint({vpcId:n.vpcId,serviceName:"com.amazonaws.us-east-1.secretsmanager",endpointType:"Interface",subnetIds:n.subnetIds,securityGroupIds:n.securityGroupIds,privateDnsEnabled:!0})}createNetworkInterface(n){let i=`eni-${Date.now()}-${this.eniCounter++}`,s={id:i,functionName:n.functionName,networkInterfaceId:`eni-${Math.random().toString(36).substring(2,15)}`,subnetId:n.subnetId,privateIpAddress:`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`,status:"creating",attachedAt:new Date};return this.networkInterfaces.set(i,s),setTimeout(()=>{s.status="available"},100),s}analyzeConnectivity(n){let i=`connectivity-${Date.now()}-${this.connectivityCounter++}`,s=Array.from(this.vpcConfigs.values()).find((y)=>y.functionName===n.functionName),o=Array.from(this.endpoints.values()).filter((y)=>y.vpcId===s?.vpcId).map((y)=>y.serviceName),c=[],u=n.hasNATGateway??!1,d=n.hasInternetGateway??!1;if(!u&&!d)c.push("Add NAT Gateway for internet access");if(!o.includes("com.amazonaws.us-east-1.s3"))c.push("Add S3 VPC endpoint to reduce NAT costs");if(!o.includes("com.amazonaws.us-east-1.dynamodb"))c.push("Add DynamoDB VPC endpoint for private access");let g={id:i,functionName:n.functionName,hasInternetAccess:u||d,hasNATGateway:u,hasVPCEndpoints:o.length>0,endpoints:o,recommendations:c};return this.connectivity.set(i,g),g}getVPCConfig(n){return this.vpcConfigs.get(n)}listVPCConfigs(n){let i=Array.from(this.vpcConfigs.values());return n?i.filter((s)=>s.functionName===n):i}getNetworkInterfaces(n){return Array.from(this.networkInterfaces.values()).filter((i)=>i.functionName===n)}listVPCEndpoints(n){let i=Array.from(this.endpoints.values());return n?i.filter((s)=>s.vpcId===n):i}generateVPCConfigCF(n){return{VpcConfig:{SubnetIds:n.subnetIds,SecurityGroupIds:n.securityGroupIds,...n.ipv6Allowed&&{Ipv6AllowedForDualStack:!0}}}}generateVPCEndpointCF(n){return{Type:"AWS::EC2::VPCEndpoint",Properties:{VpcId:n.vpcId,ServiceName:n.serviceName,VpcEndpointType:n.endpointType,...n.subnetIds&&{SubnetIds:n.subnetIds},...n.securityGroupIds&&{SecurityGroupIds:n.securityGroupIds},...n.privateDnsEnabled!==void 0&&{PrivateDnsEnabled:n.privateDnsEnabled}}}}generateSecurityGroupCF(n){return{Type:"AWS::EC2::SecurityGroup",Properties:{GroupName:n.groupName,GroupDescription:`Security group for Lambda ${n.groupName}`,VpcId:n.vpcId,...n.ingressRules&&{SecurityGroupIngress:n.ingressRules.map((i)=>({IpProtocol:i.protocol,FromPort:i.fromPort,ToPort:i.toPort,...i.cidrIp&&{CidrIp:i.cidrIp},...i.sourceSecurityGroupId&&{SourceSecurityGroupId:i.sourceSecurityGroupId}}))},...n.egressRules&&{SecurityGroupEgress:n.egressRules.map((i)=>({IpProtocol:i.protocol,FromPort:i.fromPort,ToPort:i.toPort,CidrIp:i.cidrIp||"0.0.0.0/0"}))}}}}clear(){this.vpcConfigs.clear(),this.endpoints.clear(),this.networkInterfaces.clear(),this.connectivity.clear(),this.configCounter=0,this.endpointCounter=0,this.eniCounter=0,this.connectivityCounter=0}}var kE=new Tf;class wf{dlqConfigs=new Map;messages=new Map;alarms=new Map;reprocessing=new Map;configCounter=0;messageCounter=0;alarmCounter=0;reprocessCounter=0;configureDLQ(n){let i=`dlq-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.dlqConfigs.set(i,s),s}configureSQSDLQ(n){return this.configureDLQ({functionName:n.functionName,targetArn:n.queueArn,targetType:"sqs",maxReceiveCount:n.maxReceiveCount||3,retentionPeriod:n.retentionPeriod||1209600})}configureSNSDLQ(n){return this.configureDLQ({functionName:n.functionName,targetArn:n.topicArn,targetType:"sns"})}configureDLQWithAlarm(n){let i=this.configureSQSDLQ({functionName:n.functionName,queueArn:n.queueArn});return this.createDLQAlarm({dlqConfigId:i.id,alarmName:`${n.functionName}-dlq-alarm`,threshold:n.alarmThreshold,evaluationPeriods:1,notificationTopicArn:n.notificationTopicArn,enabled:!0}),i}sendToDLQ(n){let i=`message-${Date.now()}-${this.messageCounter++}`,s={id:i,timestamp:new Date,...n};return this.messages.set(i,s),s}createDLQAlarm(n){let i=`alarm-${Date.now()}-${this.alarmCounter++}`,s={id:i,...n};return this.alarms.set(i,s),s}createAgeAlarm(n){let i=this.dlqConfigs.get(n.dlqConfigId);if(!i)throw Error(`DLQ config not found: ${n.dlqConfigId}`);return this.createDLQAlarm({dlqConfigId:n.dlqConfigId,alarmName:`${i.functionName}-dlq-age-alarm`,threshold:n.maxAgeSeconds,evaluationPeriods:1,notificationTopicArn:n.notificationTopicArn,enabled:!0})}async reprocessMessage(n){let i=this.messages.get(n);if(!i)throw Error(`Message not found: ${n}`);let s=Array.from(this.dlqConfigs.values()).find((u)=>u.functionName===i.functionName);if(!s)throw Error(`DLQ config not found for function: ${i.functionName}`);let o=`reprocess-${Date.now()}-${this.reprocessCounter++}`,c={id:o,dlqConfigId:s.id,messageId:n,status:"pending",startedAt:new Date};return this.reprocessing.set(o,c),setTimeout(()=>{c.status="processing",setTimeout(()=>{let u=Math.random()>0.3;if(c.status=u?"success":"failed",c.completedAt=new Date,!u)c.error="Reprocessing failed - same error occurred";else this.messages.delete(n)},100)},50),c}async batchReprocess(n){let i=this.dlqConfigs.get(n.dlqConfigId);if(!i)throw Error(`DLQ config not found: ${n.dlqConfigId}`);let o=Array.from(this.messages.values()).filter((c)=>c.functionName===i.functionName).slice(0,n.maxMessages||10).map((c)=>this.reprocessMessage(c.id));return Promise.all(o)}getDLQStats(n){let i=this.dlqConfigs.get(n);if(!i)throw Error(`DLQ config not found: ${n}`);let s=Array.from(this.messages.values()).filter((d)=>d.functionName===i.functionName),o={},c=0;for(let d of s)o[d.errorType]=(o[d.errorType]||0)+1,c+=d.attemptCount;let u=s.map((d)=>d.timestamp);return{totalMessages:s.length,oldestMessage:u.length>0?new Date(Math.min(...u.map((d)=>d.getTime()))):void 0,newestMessage:u.length>0?new Date(Math.max(...u.map((d)=>d.getTime()))):void 0,averageAttempts:s.length>0?c/s.length:0,errorTypes:o}}getDLQConfig(n){return this.dlqConfigs.get(n)}listDLQConfigs(){return Array.from(this.dlqConfigs.values())}getDLQMessages(n){let i=this.dlqConfigs.get(n);if(!i)return[];return Array.from(this.messages.values()).filter((s)=>s.functionName===i.functionName)}generateDLQCF(n){return{DeadLetterConfig:{TargetArn:n.targetArn}}}generateSQSDLQCF(n){return{Type:"AWS::SQS::Queue",Properties:{QueueName:`${n.functionName}-dlq`,MessageRetentionPeriod:n.retentionPeriod||1209600,...n.maxReceiveCount&&{RedrivePolicy:{deadLetterTargetArn:n.targetArn,maxReceiveCount:n.maxReceiveCount}}}}}generateDLQAlarmCF(n){let i=this.dlqConfigs.get(n.dlqConfigId);if(!i)throw Error(`DLQ config not found: ${n.dlqConfigId}`);return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:n.alarmName,AlarmDescription:`DLQ alarm for ${i.functionName}`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Sum",Period:300,EvaluationPeriods:n.evaluationPeriods,Threshold:n.threshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:i.targetArn.split(":").pop()}],...n.notificationTopicArn&&{AlarmActions:[n.notificationTopicArn]}}}}clear(){this.dlqConfigs.clear(),this.messages.clear(),this.alarms.clear(),this.reprocessing.clear(),this.configCounter=0,this.messageCounter=0,this.alarmCounter=0,this.reprocessCounter=0}}var NE=new wf;class ql{policies=new Map;healthChecks=new Map;trafficPolicies=new Map;policyCounter=0;healthCheckCounter=0;trafficPolicyCounter=0;createWeightedPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"weighted",...n};return this.policies.set(i,s),s}createLatencyPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"latency",...n};return this.policies.set(i,s),s}createFailoverPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"failover",...n};return this.policies.set(i,s),s}createGeolocationPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"geolocation",...n};return this.policies.set(i,s),s}createGeoproximityPolicy(n){let i=`policy-${Date.now()}-${this.policyCounter++}`,s={id:i,type:"geoproximity",...n};return this.policies.set(i,s),s}createHTTPHealthCheck(n){let i=`health-check-${Date.now()}-${this.healthCheckCounter++}`,s={id:i,type:n.port===443?"https":"http",requestInterval:n.requestInterval||30,failureThreshold:n.failureThreshold||3,healthCheckStatus:"Unknown",port:n.port||(n.port===443?443:80),...n};return this.healthChecks.set(i,s),setTimeout(()=>{s.healthCheckStatus=Math.random()>0.2?"Healthy":"Unhealthy"},100),s}createTCPHealthCheck(n){let i=`health-check-${Date.now()}-${this.healthCheckCounter++}`,s={id:i,type:"tcp",fullyQualifiedDomainName:n.ipAddress,requestInterval:n.requestInterval||30,failureThreshold:n.failureThreshold||3,healthCheckStatus:"Unknown",...n};return this.healthChecks.set(i,s),setTimeout(()=>{s.healthCheckStatus=Math.random()>0.1?"Healthy":"Unhealthy"},100),s}createCalculatedHealthCheck(n){let i=`health-check-${Date.now()}-${this.healthCheckCounter++}`,s={id:i,type:"calculated",requestInterval:30,failureThreshold:0,healthCheckStatus:"Unknown",...n};return this.healthChecks.set(i,s),setTimeout(()=>{let c=n.childHealthChecks.filter((u)=>this.healthChecks.get(u)?.healthCheckStatus==="Healthy").length;s.healthCheckStatus=c>=n.healthThreshold?"Healthy":"Unhealthy"},150),s}createTrafficPolicy(n){let i=`traffic-policy-${Date.now()}-${this.trafficPolicyCounter++}`,s={id:i,version:1,...n};return this.trafficPolicies.set(i,s),s}createFailoverTrafficPolicy(n){return this.createTrafficPolicy({name:n.name,document:{recordType:n.recordType||"A",startRule:"failover",endpoints:{primary:{type:"value",value:n.primaryEndpoint},secondary:{type:"value",value:n.secondaryEndpoint}},rules:{failover:{ruleType:"failover",primary:"primary",secondary:"secondary"}}}})}createGeoproximityTrafficPolicy(n){let i={},s=[];return n.locations.forEach((o,c)=>{let u=`endpoint${c}`;i[u]={type:"value",value:o.endpoint},s.push({endpointReference:u,region:o.region,latitude:o.latitude,longitude:o.longitude,bias:o.bias})}),this.createTrafficPolicy({name:n.name,document:{recordType:"A",startRule:"geoproximity",endpoints:i,rules:{geoproximity:{ruleType:"geoproximity",locations:s}}}})}getPolicy(n){return this.policies.get(n)}listPolicies(){return Array.from(this.policies.values())}getHealthCheck(n){return this.healthChecks.get(n)}listHealthChecks(){return Array.from(this.healthChecks.values())}getHealthCheckStatus(n){return this.healthChecks.get(n)?.healthCheckStatus||"Unknown"}generateHealthCheckCF(n){let i={Type:"AWS::Route53::HealthCheck",Properties:{HealthCheckConfig:{Type:n.type.toUpperCase(),RequestInterval:n.requestInterval,FailureThreshold:n.failureThreshold,...n.measureLatency&&{MeasureLatency:!0}},HealthCheckTags:[{Key:"Name",Value:n.name}]}};if(n.type==="calculated"){let s=n;i.Properties.HealthCheckConfig.ChildHealthChecks=s.childHealthChecks,i.Properties.HealthCheckConfig.HealthThreshold=s.healthThreshold}else{if(n.ipAddress)i.Properties.HealthCheckConfig.IPAddress=n.ipAddress;if(n.fullyQualifiedDomainName)i.Properties.HealthCheckConfig.FullyQualifiedDomainName=n.fullyQualifiedDomainName;if(n.port)i.Properties.HealthCheckConfig.Port=n.port;if(n.resourcePath)i.Properties.HealthCheckConfig.ResourcePath=n.resourcePath;if(n.enableSNI)i.Properties.HealthCheckConfig.EnableSNI=!0}return i}generateWeightedRecordSetCF(n){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:n.name,Type:n.type,TTL:n.ttl,ResourceRecords:n.resourceRecords,Weight:n.weight,SetIdentifier:n.setIdentifier,...n.healthCheckId&&{HealthCheckId:n.healthCheckId}}}}generateFailoverRecordSetCF(n){return{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:n.hostedZoneId,Name:n.name,Type:n.type,TTL:n.ttl,ResourceRecords:n.resourceRecords,Failover:n.failover,SetIdentifier:n.setIdentifier,...n.healthCheckId&&{HealthCheckId:n.healthCheckId}}}}clear(){this.policies.clear(),this.healthChecks.clear(),this.trafficPolicies.clear(),this.policyCounter=0,this.healthCheckCounter=0,this.trafficPolicyCounter=0}}var CS=new ql;class Rf{configs=new Map;ksks=new Map;validations=new Map;configCounter=0;kskCounter=0;validationCounter=0;enableDNSSEC(n){let i=`dnssec-${Date.now()}-${this.configCounter++}`,s={id:i,hostedZoneId:n.hostedZoneId,status:"SIGNING",signingStatus:"Initializing DNSSEC signing"};if(this.configs.set(i,s),n.kmsKeyArn)this.createKSK({name:`ksk-${n.hostedZoneId}`,hostedZoneId:n.hostedZoneId,kmsKeyArn:n.kmsKeyArn});return setTimeout(()=>{s.status="SIGNED",s.signingStatus="DNSSEC signing complete"},100),s}disableDNSSEC(n){let i=this.configs.get(n);if(!i)throw Error(`DNSSEC config not found: ${n}`);return i.status="DELETING",i.signingStatus="Removing DNSSEC signing",setTimeout(()=>{i.status="NOT_SIGNING",i.signingStatus="DNSSEC signing removed"},100),i}createKSK(n){let i=`ksk-${Date.now()}-${this.kskCounter++}`,s={id:i,status:"ACTIVE",flag:257,keyManagementServiceArn:n.kmsKeyArn,digestAlgorithm:2,keyTag:Math.floor(Math.random()*65535),publicKey:this.generatePublicKey(),...n};s.dnskeyRecord=`${s.flag} 3 8 ${s.publicKey}`;let o=this.generateDigest(s.dnskeyRecord);return s.digestValue=o,s.dsRecord=`${s.keyTag} 8 ${s.digestAlgorithm} ${o}`,this.ksks.set(i,s),s}deactivateKSK(n){let i=this.ksks.get(n);if(!i)throw Error(`KSK not found: ${n}`);return i.status="INACTIVE",i}validateDNSSEC(n){let i=`validation-${Date.now()}-${this.validationCounter++}`,s=n.checkDNSKEY!==!1?Math.random()>0.1:!1,o=n.checkRRSIG!==!1?Math.random()>0.1:!1,c=s&&o,u=[];if(!s)u.push("DNSKEY record not found");if(!o)u.push("RRSIG record not found");let d;if(!s&&!o)d="INSECURE";else if(s&&o&&c)d="VALID";else if(s||o)d="BOGUS",u.push("Invalid signature or incomplete DNSSEC chain");else d="INVALID";let g={id:i,domain:n.domain,validationStatus:d,dnskeyPresent:s,rrsigPresent:o,validSignature:c,errors:u};return this.validations.set(i,g),g}getDNSSECConfig(n){return this.configs.get(n)}listDNSSECConfigs(){return Array.from(this.configs.values())}getKSK(n){return this.ksks.get(n)}listKSKs(n){let i=Array.from(this.ksks.values());return n?i.filter((s)=>s.hostedZoneId===n):i}getDSRecord(n){let i=this.ksks.get(n);if(!i||!i.dsRecord)throw Error("DS record not available");return i.dsRecord}generatePublicKey(){let i="";for(let s=0;s<256;s++)i+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(Math.floor(Math.random()*64));return i}generateDigest(n){let s="";for(let o=0;o<64;o++)s+="0123456789ABCDEF".charAt(Math.floor(Math.random()*16));return s}generateDNSSECCF(n){return{Type:"AWS::Route53::DNSSEC",Properties:{HostedZoneId:n.hostedZoneId}}}generateKSKCF(n){return{Type:"AWS::Route53::KeySigningKey",Properties:{Name:n.name,HostedZoneId:n.hostedZoneId,KeyManagementServiceArn:n.keyManagementServiceArn,Status:n.status}}}clear(){this.configs.clear(),this.ksks.clear(),this.validations.clear(),this.configCounter=0,this.kskCounter=0,this.validationCounter=0}}var BE=new Rf;class Df{endpoints=new Map;rules=new Map;firewalls=new Map;ruleGroups=new Map;domainLists=new Map;endpointCounter=0;ruleCounter=0;firewallCounter=0;ruleGroupCounter=0;domainListCounter=0;createResolverEndpoint(n){let i=`endpoint-${Date.now()}-${this.endpointCounter++}`,s={id:i,status:"CREATING",...n};return this.endpoints.set(i,s),setTimeout(()=>{s.status="OPERATIONAL",s.ipAddresses.forEach((o)=>{if(!o.ip)o.ip=`10.0.${Math.floor(Math.random()*255)}.${Math.floor(Math.random()*255)}`})},100),s}createInboundEndpoint(n){return this.createResolverEndpoint({name:n.name,direction:"INBOUND",ipAddresses:n.subnetIds.map((i)=>({subnetId:i})),securityGroupIds:n.securityGroupIds})}createOutboundEndpoint(n){return this.createResolverEndpoint({name:n.name,direction:"OUTBOUND",ipAddresses:n.subnetIds.map((i)=>({subnetId:i})),securityGroupIds:n.securityGroupIds})}createResolverRule(n){let i=`rule-${Date.now()}-${this.ruleCounter++}`,s={id:i,status:"CREATING",...n};return this.rules.set(i,s),setTimeout(()=>{s.status="COMPLETE"},100),s}createForwardRule(n){return this.createResolverRule({name:n.name,ruleType:"FORWARD",domainName:n.domainName,targetIps:n.targetIps,resolverEndpointId:n.resolverEndpointId})}createSystemRule(n){return this.createResolverRule({name:n.name,ruleType:"SYSTEM",domainName:n.domainName})}createFirewallDomainList(n){let i=`domain-list-${Date.now()}-${this.domainListCounter++}`,s={id:i,status:"CREATING",...n};return this.domainLists.set(i,s),setTimeout(()=>{s.status="COMPLETE"},100),s}createFirewallRuleGroup(n){let i=`rule-group-${Date.now()}-${this.ruleGroupCounter++}`,s={id:i,name:n.name,rules:n.rules.map((o,c)=>({id:`rule-${i}-${c}`,...o})),shareStatus:"NOT_SHARED"};return this.ruleGroups.set(i,s),s}createBlockRule(n){return this.createFirewallRuleGroup({name:n.name,rules:[{name:n.name,priority:n.priority,action:"BLOCK",blockResponse:n.blockResponse||"NODATA",blockOverrideDomain:n.blockOverrideDomain,firewallDomainListId:n.domainListId}]})}createAllowRule(n){return this.createFirewallRuleGroup({name:n.name,rules:[{name:n.name,priority:n.priority,action:"ALLOW",firewallDomainListId:n.domainListId}]})}createDNSFirewall(n){let i=`firewall-${Date.now()}-${this.firewallCounter++}`,s={id:i,name:n.name,firewallRuleGroupAssociations:n.ruleGroupAssociations.map((o,c)=>({id:`assoc-${i}-${c}`,vpcId:n.vpcId,firewallRuleGroupId:o.firewallRuleGroupId,priority:o.priority,mutationProtection:o.mutationProtection||"DISABLED",status:"COMPLETE"}))};return this.firewalls.set(i,s),s}createMalwareProtectionFirewall(n){let i=this.createFirewallDomainList({name:`${n.name}-malware-domains`,domains:n.maliciousDomains}),s=this.createBlockRule({name:`${n.name}-block-malware`,priority:100,domainListId:i.id,blockResponse:"NXDOMAIN"});return this.createDNSFirewall({name:n.name,vpcId:n.vpcId,ruleGroupAssociations:[{firewallRuleGroupId:s.id,priority:100,mutationProtection:"ENABLED"}]})}getEndpoint(n){return this.endpoints.get(n)}listEndpoints(n){let i=Array.from(this.endpoints.values());return n?i.filter((s)=>s.direction===n):i}getRule(n){return this.rules.get(n)}listRules(){return Array.from(this.rules.values())}getFirewall(n){return this.firewalls.get(n)}listFirewalls(){return Array.from(this.firewalls.values())}generateResolverEndpointCF(n){return{Type:"AWS::Route53Resolver::ResolverEndpoint",Properties:{Name:n.name,Direction:n.direction,IpAddresses:n.ipAddresses.map((i)=>({SubnetId:i.subnetId,...i.ip&&{Ip:i.ip}})),SecurityGroupIds:n.securityGroupIds}}}generateResolverRuleCF(n){return{Type:"AWS::Route53Resolver::ResolverRule",Properties:{Name:n.name,RuleType:n.ruleType,DomainName:n.domainName,...n.targetIps&&{TargetIps:n.targetIps.map((i)=>({Ip:i.ip,Port:i.port||53}))},...n.resolverEndpointId&&{ResolverEndpointId:n.resolverEndpointId}}}}generateFirewallRuleGroupCF(n){return{Type:"AWS::Route53Resolver::FirewallRuleGroup",Properties:{Name:n.name,FirewallRules:n.rules.map((i)=>({Name:i.name,Priority:i.priority,Action:i.action,FirewallDomainListId:i.firewallDomainListId,...i.blockResponse&&{BlockResponse:i.blockResponse},...i.blockOverrideDomain&&{BlockOverrideDomain:i.blockOverrideDomain},...i.blockOverrideTTL&&{BlockOverrideTtl:i.blockOverrideTTL}}))}}}clear(){this.endpoints.clear(),this.rules.clear(),this.firewalls.clear(),this.ruleGroups.clear(),this.domainLists.clear(),this.endpointCounter=0,this.ruleCounter=0,this.firewallCounter=0,this.ruleGroupCounter=0,this.domainListCounter=0}}var xE=new Df;class Pf{bounces=new Map;complaints=new Map;handlers=new Map;suppressionList=new Map;metrics=new Map;bounceCounter=0;complaintCounter=0;handlerCounter=0;suppressionCounter=0;metricsCounter=0;recordBounce(n){let i=`bounce-${Date.now()}-${this.bounceCounter++}`,s={id:i,...n};if(this.bounces.set(i,s),n.bounceType==="Permanent")this.addToSuppressionList({emailAddress:n.recipient,reason:"BOUNCE"});return s}recordComplaint(n){let i=`complaint-${Date.now()}-${this.complaintCounter++}`,s={id:i,...n};this.complaints.set(i,s);for(let o of n.recipients)this.addToSuppressionList({emailAddress:o,reason:"COMPLAINT"});return s}createBounceHandler(n){let i=`handler-${Date.now()}-${this.handlerCounter++}`,s={id:i,...n};return this.handlers.set(i,s),s}createAutomaticBounceHandler(n){return this.createBounceHandler({name:n.name,bounceThreshold:5,complaintThreshold:0.1,suppressionDuration:2592000,autoSuppress:!0,notificationTopicArn:n.notificationTopicArn})}addToSuppressionList(n){let i=`suppression-${Date.now()}-${this.suppressionCounter++}`,s=n.expirationDays?new Date(Date.now()+n.expirationDays*24*60*60*1000):void 0,o={id:i,emailAddress:n.emailAddress,reason:n.reason,suppressedAt:new Date,expiresAt:s,bounceCount:n.reason==="BOUNCE"?1:0,complaintCount:n.reason==="COMPLAINT"?1:0};return this.suppressionList.set(n.emailAddress,o),o}removeFromSuppressionList(n){return this.suppressionList.delete(n)}isSuppressed(n){let i=this.suppressionList.get(n);if(!i)return!1;if(i.expiresAt&&i.expiresAt<new Date)return this.suppressionList.delete(n),!1;return!0}getBounceStatistics(n,i){let s=Array.from(this.bounces.values()).filter((A)=>A.timestamp>=n&&A.timestamp<=i),o=s.length,c=s.filter((A)=>A.bounceType==="Permanent").length,u=s.filter((A)=>A.bounceType==="Transient").length,d=o*10,g=o/d*100,y=new Map;for(let A of s)y.set(A.recipient,(y.get(A.recipient)||0)+1);let h=Array.from(y.entries()).map(([A,C])=>({email:A,count:C})).sort((A,C)=>C.count-A.count).slice(0,10);return{totalBounces:o,permanentBounces:c,transientBounces:u,bounceRate:g,topRecipients:h}}getComplaintStatistics(n,i){let s=Array.from(this.complaints.values()).filter((y)=>y.timestamp>=n&&y.timestamp<=i),o=s.length,c=new Set;for(let y of s)for(let h of y.recipients)c.add(h);let u=c.size,d=o*1000,g=o/d*100;return{totalComplaints:o,uniqueComplainters:u,complaintRate:g}}calculateReputationMetrics(){let n=`metrics-${Date.now()}-${this.metricsCounter++}`,i=new Date,s=new Date(i.getTime()-86400000),o=this.getBounceStatistics(s,i),c=this.getComplaintStatistics(s,i),u;if(o.bounceRate>10||c.complaintRate>0.5)u="Shutdown";else if(o.bounceRate>5||c.complaintRate>0.1)u="Probation";else if(o.bounceRate>2||c.complaintRate>0.05)u="Warning";else u="Good";let d={id:n,timestamp:i,bounceRate:o.bounceRate,complaintRate:c.complaintRate,sendingQuota:50000,maxSendRate:14,sentLast24Hours:o.totalBounces*10,reputationStatus:u};return this.metrics.set(n,d),d}getBounces(n){let i=Array.from(this.bounces.values());return n?i.filter((s)=>s.messageId===n):i}getComplaints(n){let i=Array.from(this.complaints.values());return n?i.filter((s)=>s.messageId===n):i}listSuppressionList(n){let i=Array.from(this.suppressionList.values());return n?i.filter((s)=>s.reason===n):i}generateSNSSubscriptionCF(n){return{Type:"AWS::SNS::Subscription",Properties:{TopicArn:n.topicArn,Endpoint:n.endpoint,Protocol:n.protocol}}}generateEventDestinationCF(n){return{Type:"AWS::SES::ConfigurationSetEventDestination",Properties:{ConfigurationSetName:n.configurationSetName,EventDestination:{Name:n.eventDestinationName,Enabled:!0,MatchingEventTypes:n.eventTypes,...n.snsTopicArn&&{SnsDestination:{TopicARN:n.snsTopicArn}},...n.cloudWatchDestination&&{CloudWatchDestination:n.cloudWatchDestination}}}}}clear(){this.bounces.clear(),this.complaints.clear(),this.handlers.clear(),this.suppressionList.clear(),this.metrics.clear(),this.bounceCounter=0,this.complaintCounter=0,this.handlerCounter=0,this.suppressionCounter=0,this.metricsCounter=0}}var OE=new Pf;class kf{events=new Map;campaigns=new Map;reports=new Map;abTests=new Map;eventCounter=0;campaignCounter=0;reportCounter=0;abTestCounter=0;trackEvent(n){let i=`event-${Date.now()}-${this.eventCounter++}`,s={id:i,...n};if(this.events.set(i,s),n.tags?.campaignId)this.updateCampaignStats(n.tags.campaignId,n.eventType);return s}trackOpen(n){return this.trackEvent({...n,eventType:"open",timestamp:new Date})}trackClick(n){return this.trackEvent({...n,eventType:"click",timestamp:new Date})}createCampaign(n){let i=`campaign-${Date.now()}-${this.campaignCounter++}`,s={id:i,sentCount:0,deliveredCount:0,openCount:0,clickCount:0,bounceCount:0,complaintCount:0,createdAt:new Date,...n};return this.campaigns.set(i,s),s}updateCampaignStats(n,i){let s=this.campaigns.get(n);if(!s)return;switch(i){case"send":s.sentCount++;break;case"delivery":s.deliveredCount++;break;case"open":s.openCount++;break;case"click":s.clickCount++;break;case"bounce":s.bounceCount++;break;case"complaint":s.complaintCount++;break}}generateReport(n){let i=`report-${Date.now()}-${this.reportCounter++}`,s=Array.from(this.events.values()).filter((x)=>{let F=x.timestamp>=n.startDate&&x.timestamp<=n.endDate,G=!n.campaignId||x.tags?.campaignId===n.campaignId;return F&&G}),o=s.filter((x)=>x.eventType==="send").length,c=s.filter((x)=>x.eventType==="delivery").length,u=s.filter((x)=>x.eventType==="open").length,d=s.filter((x)=>x.eventType==="click").length,g=s.filter((x)=>x.eventType==="bounce").length,y=s.filter((x)=>x.eventType==="complaint").length,h=o>0?c/o*100:0,A=c>0?u/c*100:0,C=c>0?d/c*100:0,v=u>0?d/u*100:0,T=o>0?g/o*100:0,R=c>0?y/c*100:0,P=new Map;for(let x of s)if(x.eventType==="click"){let F=x;P.set(F.link,(P.get(F.link)||0)+1)}let I=Array.from(P.entries()).map(([x,F])=>({link:x,clicks:F})).sort((x,F)=>F.clicks-x.clicks).slice(0,10),O={desktop:0,mobile:0,tablet:0,unknown:0};for(let x of s)if(x.eventType==="open"||x.eventType==="click"){let F=x.userAgent.toLowerCase();if(F.includes("mobile"))O.mobile++;else if(F.includes("tablet"))O.tablet++;else if(F.includes("mozilla"))O.desktop++;else O.unknown++}let B={id:i,campaignId:n.campaignId,startDate:n.startDate,endDate:n.endDate,totalSent:o,totalDelivered:c,totalOpened:u,totalClicked:d,totalBounced:g,totalComplaints:y,deliveryRate:h,openRate:A,clickRate:C,clickToOpenRate:v,bounceRate:T,complaintRate:R,topLinks:I,deviceBreakdown:O,locationBreakdown:{}};return this.reports.set(i,B),B}createABTest(n){let i=`abtest-${Date.now()}-${this.abTestCounter++}`,s={id:i,name:n.name,variants:n.variants.map((o,c)=>({id:`variant-${i}-${c}`,sentCount:0,openCount:0,clickCount:0,conversionCount:0,...o})),status:"draft"};return this.abTests.set(i,s),s}startABTest(n){let i=this.abTests.get(n);if(!i)throw Error(`A/B test not found: ${n}`);return i.status="running",i.startedAt=new Date,i}completeABTest(n){let i=this.abTests.get(n);if(!i)throw Error(`A/B test not found: ${n}`);let s=i.variants[0],o=0;for(let c of i.variants){let u=c.sentCount>0?c.openCount/c.sentCount:0;if(u>o)o=u,s=c}return i.status="completed",i.completedAt=new Date,i.winner=s.id,i}getCampaign(n){return this.campaigns.get(n)}listCampaigns(){return Array.from(this.campaigns.values())}getEvents(n){let i=Array.from(this.events.values());if(n?.messageId)i=i.filter((s)=>s.messageId===n.messageId);if(n?.eventType)i=i.filter((s)=>s.eventType===n.eventType);if(n?.startDate)i=i.filter((s)=>s.timestamp>=n.startDate);if(n?.endDate)i=i.filter((s)=>s.timestamp<=n.endDate);return i}generateTrackingConfigurationCF(n){return{Type:"AWS::SES::ConfigurationSet",Properties:{Name:n.configurationSetName,...n.openTracking&&{TrackingOptions:{CustomRedirectDomain:"tracking.example.com"}}}}}clear(){this.events.clear(),this.campaigns.clear(),this.reports.clear(),this.abTests.clear(),this.eventCounter=0,this.campaignCounter=0,this.reportCounter=0,this.abTestCounter=0}}var _E=new kf;class Nf{dashboards=new Map;warmupPlans=new Map;domainReputations=new Map;dashboardCounter=0;warmupCounter=0;domainCounter=0;getReputationDashboard(){let n=`dashboard-${Date.now()}-${this.dashboardCounter++}`,i=Math.random()*5,s=Math.random()*0.5,o=Math.floor(Math.random()*10),c=Math.max(0,100-i*10-s*100-o*2),u=[];if(i>2)u.push("Reduce bounce rate by cleaning email list");if(s>0.1)u.push("Review email content and unsubscribe process");if(o>5)u.push("Improve email relevance and targeting");let d={id:n,timestamp:new Date,overallScore:c,bounceRate:i,complaintRate:s,spamReports:o,blacklistStatus:this.checkBlacklists(),dkimStatus:"VERIFIED",spfStatus:"PASS",dmarcStatus:"PASS",sendingLimits:{maxSendRate:14,max24HourSend:50000,sentLast24Hours:12000,remainingQuota:38000,quotaResetTime:new Date(Date.now()+86400000)},recommendations:u};return this.dashboards.set(n,d),d}checkBlacklists(){return["Spamhaus ZEN","Spamcop","SORBS","Barracuda","URIBL"].map((i)=>({listName:i,listed:Math.random()>0.95,delistUrl:`https://www.${i.toLowerCase().replace(/\s/g,"")}.org/delist`}))}createWarmupPlan(n){let i=`warmup-${Date.now()}-${this.warmupCounter++}`,s=[],o=(n.targetDailyLimit-n.initialDailyLimit)/n.durationDays;for(let u=0;u<n.durationDays;u++)s.push(Math.floor(n.initialDailyLimit+o*u));let c={id:i,name:n.name,startDate:new Date,currentDay:1,totalDays:n.durationDays,dailyLimits:s,currentLimit:s[0],status:"active"};return this.warmupPlans.set(i,c),c}createAggressiveWarmupPlan(n){return this.createWarmupPlan({name:n.name,initialDailyLimit:500,targetDailyLimit:50000,durationDays:14})}createConservativeWarmupPlan(n){return this.createWarmupPlan({name:n.name,initialDailyLimit:200,targetDailyLimit:50000,durationDays:30})}advanceWarmupPlan(n){let i=this.warmupPlans.get(n);if(!i)throw Error(`Warmup plan not found: ${n}`);if(i.currentDay<i.totalDays)i.currentDay++,i.currentLimit=i.dailyLimits[i.currentDay-1];if(i.currentDay>=i.totalDays)i.status="completed";return i}trackDomainReputation(n){let i=`domain-${Date.now()}-${this.domainCounter++}`,s=n.delivered/n.totalSent*100,o=n.delivered>0?n.opened/n.delivered*100:0,c=n.delivered>0?n.clicked/n.delivered*100:0,u=n.bounced/n.totalSent*100,d=n.delivered>0?n.complained/n.delivered*100:0,g=o*0.4+c*0.6,y=Math.max(0,100-u*10-d*100+g*0.2),h={id:i,domain:n.domain,reputationScore:y,totalSent:n.totalSent,deliveryRate:s,openRate:o,clickRate:c,bounceRate:u,complaintRate:d,engagementScore:g};return this.domainReputations.set(n.domain,h),h}getDomainReputation(n){return this.domainReputations.get(n)}listDomainReputations(){return Array.from(this.domainReputations.values())}getWarmupPlan(n){return this.warmupPlans.get(n)}listWarmupPlans(){return Array.from(this.warmupPlans.values())}clear(){this.dashboards.clear(),this.warmupPlans.clear(),this.domainReputations.clear(),this.dashboardCounter=0,this.warmupCounter=0,this.domainCounter=0}}var LE=new Nf;class Bf{templates=new Map;versions=new Map;tests=new Map;templateCounter=0;testCounter=0;createTemplate(n){let i=`template-${Date.now()}-${this.templateCounter++}`,s=this.extractVariables(n.subject+n.htmlPart+n.textPart),o={id:i,variables:s,createdAt:new Date,updatedAt:new Date,version:1,...n};return this.templates.set(i,o),this.addVersion({templateId:i,version:1,subject:n.subject,htmlPart:n.htmlPart,textPart:n.textPart,createdBy:"system"}),o}createWelcomeTemplate(n){return this.createTemplate({name:n.name,subject:"Welcome to {{companyName}}!",htmlPart:`
3742
3740
  <html>
3743
3741
  <body>
3744
3742
  <h1>Welcome, {{userName}}!</h1>
@@ -3758,7 +3756,7 @@ COPY . .`,impact:"Improve build time by 60-80% on subsequent builds"});let g={si
3758
3756
  <p>If you didn't request this, please ignore this email.</p>
3759
3757
  </body>
3760
3758
  </html>
3761
- `,textPart:"Hi {{userName}}, reset your password at: {{resetUrl}}. This link expires in {{expirationHours}} hours."})}updateTemplate(n,i,s){let o=this.templates.get(n);if(!o)throw Error(`Template not found: ${n}`);if(i.subject)o.subject=i.subject;if(i.htmlPart)o.htmlPart=i.htmlPart;if(i.textPart)o.textPart=i.textPart;return o.version++,o.updatedAt=new Date,o.variables=this.extractVariables(o.subject+o.htmlPart+o.textPart),this.addVersion({templateId:n,version:o.version,subject:o.subject,htmlPart:o.htmlPart,textPart:o.textPart,createdBy:"system",changelog:s}),o}addVersion(n){let s={id:`version-${n.templateId}-${n.version}`,createdAt:new Date,...n},o=this.versions.get(n.templateId)||[];return o.push(s),this.versions.set(n.templateId,o),s}extractVariables(n){let i=/\{\{([^}]+)\}\}/g,s=new Set,o;while((o=i.exec(n))!==null)s.add(o[1].trim());return Array.from(s)}renderTemplate(n,i){let s=this.templates.get(n);if(!s)throw Error(`Template not found: ${n}`);let o=(c)=>c.replace(/\{\{([^}]+)\}\}/g,(u,d)=>{let g=d.trim();return i[g]!==void 0?String(i[g]):u});return{subject:o(s.subject),html:o(s.htmlPart),text:o(s.textPart)}}testTemplate(n,i){let s=`test-${Date.now()}-${this.testCounter++}`,o=this.renderTemplate(n,i),c={id:s,templateId:n,testData:i,renderedSubject:o.subject,renderedHtml:o.html,renderedText:o.text,timestamp:new Date};return this.tests.set(s,c),c}getTemplate(n){return this.templates.get(n)}listTemplates(){return Array.from(this.templates.values())}getTemplateVersions(n){return this.versions.get(n)||[]}revertToVersion(n,i){let s=this.templates.get(n);if(!s)throw Error(`Template not found: ${n}`);let c=(this.versions.get(n)||[]).find((u)=>u.version===i);if(!c)throw Error(`Version ${i} not found for template ${n}`);return s.subject=c.subject,s.htmlPart=c.htmlPart,s.textPart=c.textPart,s.version++,s.updatedAt=new Date,this.addVersion({templateId:n,version:s.version,subject:s.subject,htmlPart:s.htmlPart,textPart:s.textPart,createdBy:"system",changelog:`Reverted to version ${i}`}),s}generateTemplateCF(n){return{Type:"AWS::SES::Template",Properties:{Template:{TemplateName:n.name,SubjectPart:n.subject,HtmlPart:n.htmlPart,TextPart:n.textPart}}}}clear(){this.templates.clear(),this.versions.clear(),this.tests.clear(),this.templateCounter=0,this.testCounter=0}}var vE=new Cf;class Gt{static createSearchDomain(n){let{slug:i,environment:s,domainName:o,instanceType:c="t3.small.search",instanceCount:u=1,ebsVolumeSize:d=10,masterUserName:g="admin",masterUserPassword:y}=n,h=o||`${i}-${s}-email-search`;return{[`${i}EmailSearchDomain`]:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:h,EngineVersion:"OpenSearch_2.11",ClusterConfig:{InstanceType:c,InstanceCount:u,DedicatedMasterEnabled:!1,ZoneAwarenessEnabled:!1},EBSOptions:{EBSEnabled:!0,VolumeType:"gp3",VolumeSize:d},NodeToNodeEncryptionOptions:{Enabled:!0},EncryptionAtRestOptions:{Enabled:!0},DomainEndpointOptions:{EnforceHTTPS:!0},AdvancedSecurityOptions:{Enabled:!0,InternalUserDatabaseEnabled:!0,MasterUserOptions:{MasterUserName:g,MasterUserPassword:y||`${i}-search-${Date.now()}`}},AccessPolicies:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:`arn:aws:es:*:*:domain/${h}/*`}]}}}}}static createIndexerLambda(n){return{[`${n.slug}EmailIndexerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-email-indexer`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:60,MemorySize:512,Code:{ZipFile:Gt.IndexerLambdaCode},Environment:{Variables:{OPENSEARCH_ENDPOINT:n.searchDomainEndpoint,EMAIL_BUCKET:n.emailBucket}}}}}}static IndexerLambdaCode=`
3759
+ `,textPart:"Hi {{userName}}, reset your password at: {{resetUrl}}. This link expires in {{expirationHours}} hours."})}updateTemplate(n,i,s){let o=this.templates.get(n);if(!o)throw Error(`Template not found: ${n}`);if(i.subject)o.subject=i.subject;if(i.htmlPart)o.htmlPart=i.htmlPart;if(i.textPart)o.textPart=i.textPart;return o.version++,o.updatedAt=new Date,o.variables=this.extractVariables(o.subject+o.htmlPart+o.textPart),this.addVersion({templateId:n,version:o.version,subject:o.subject,htmlPart:o.htmlPart,textPart:o.textPart,createdBy:"system",changelog:s}),o}addVersion(n){let s={id:`version-${n.templateId}-${n.version}`,createdAt:new Date,...n},o=this.versions.get(n.templateId)||[];return o.push(s),this.versions.set(n.templateId,o),s}extractVariables(n){let i=/\{\{([^}]+)\}\}/g,s=new Set,o;while((o=i.exec(n))!==null)s.add(o[1].trim());return Array.from(s)}renderTemplate(n,i){let s=this.templates.get(n);if(!s)throw Error(`Template not found: ${n}`);let o=(c)=>c.replace(/\{\{([^}]+)\}\}/g,(u,d)=>{let g=d.trim();return i[g]!==void 0?String(i[g]):u});return{subject:o(s.subject),html:o(s.htmlPart),text:o(s.textPart)}}testTemplate(n,i){let s=`test-${Date.now()}-${this.testCounter++}`,o=this.renderTemplate(n,i),c={id:s,templateId:n,testData:i,renderedSubject:o.subject,renderedHtml:o.html,renderedText:o.text,timestamp:new Date};return this.tests.set(s,c),c}getTemplate(n){return this.templates.get(n)}listTemplates(){return Array.from(this.templates.values())}getTemplateVersions(n){return this.versions.get(n)||[]}revertToVersion(n,i){let s=this.templates.get(n);if(!s)throw Error(`Template not found: ${n}`);let c=(this.versions.get(n)||[]).find((u)=>u.version===i);if(!c)throw Error(`Version ${i} not found for template ${n}`);return s.subject=c.subject,s.htmlPart=c.htmlPart,s.textPart=c.textPart,s.version++,s.updatedAt=new Date,this.addVersion({templateId:n,version:s.version,subject:s.subject,htmlPart:s.htmlPart,textPart:s.textPart,createdBy:"system",changelog:`Reverted to version ${i}`}),s}generateTemplateCF(n){return{Type:"AWS::SES::Template",Properties:{Template:{TemplateName:n.name,SubjectPart:n.subject,HtmlPart:n.htmlPart,TextPart:n.textPart}}}}clear(){this.templates.clear(),this.versions.clear(),this.tests.clear(),this.templateCounter=0,this.testCounter=0}}var $E=new Bf;class Ht{static createSearchDomain(n){let{slug:i,environment:s,domainName:o,instanceType:c="t3.small.search",instanceCount:u=1,ebsVolumeSize:d=10,masterUserName:g="admin",masterUserPassword:y}=n,h=o||`${i}-${s}-email-search`;return{[`${i}EmailSearchDomain`]:{Type:"AWS::OpenSearchService::Domain",Properties:{DomainName:h,EngineVersion:"OpenSearch_2.11",ClusterConfig:{InstanceType:c,InstanceCount:u,DedicatedMasterEnabled:!1,ZoneAwarenessEnabled:!1},EBSOptions:{EBSEnabled:!0,VolumeType:"gp3",VolumeSize:d},NodeToNodeEncryptionOptions:{Enabled:!0},EncryptionAtRestOptions:{Enabled:!0},DomainEndpointOptions:{EnforceHTTPS:!0},AdvancedSecurityOptions:{Enabled:!0,InternalUserDatabaseEnabled:!0,MasterUserOptions:{MasterUserName:g,MasterUserPassword:y||`${i}-search-${Date.now()}`}},AccessPolicies:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{AWS:"*"},Action:"es:*",Resource:`arn:aws:es:*:*:domain/${h}/*`}]}}}}}static createIndexerLambda(n){return{[`${n.slug}EmailIndexerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-email-indexer`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:60,MemorySize:512,Code:{ZipFile:Ht.IndexerLambdaCode},Environment:{Variables:{OPENSEARCH_ENDPOINT:n.searchDomainEndpoint,EMAIL_BUCKET:n.emailBucket}}}}}}static IndexerLambdaCode=`
3762
3760
  const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
3763
3761
  const https = require('https');
3764
3762
 
@@ -3858,7 +3856,7 @@ async function indexDocument(doc) {
3858
3856
  req.end();
3859
3857
  });
3860
3858
  }
3861
- `;static getIndexMapping(){return{mappings:{properties:{messageId:{type:"keyword"},from:{type:"keyword"},fromName:{type:"text"},to:{type:"keyword"},toName:{type:"text"},cc:{type:"keyword"},subject:{type:"text",analyzer:"standard",fields:{keyword:{type:"keyword"}}},body:{type:"text",analyzer:"standard"},bodyPreview:{type:"text"},date:{type:"date"},receivedAt:{type:"date"},hasAttachments:{type:"boolean"},attachmentNames:{type:"keyword"},labels:{type:"keyword"},folder:{type:"keyword"},threadId:{type:"keyword"},isRead:{type:"boolean"},isStarred:{type:"boolean"},mailbox:{type:"keyword"}}},settings:{number_of_shards:1,number_of_replicas:0}}}static buildSearchQuery(n){let i=[],s=[];if(n.query)i.push({multi_match:{query:n.query,fields:["subject^3","body","fromName","toName"],type:"best_fields",fuzziness:"AUTO"}});if(n.from)s.push({term:{from:n.from}});if(n.to)s.push({term:{to:n.to}});if(n.subject)i.push({match_phrase:{subject:n.subject}});if(n.hasAttachments!==void 0)s.push({term:{hasAttachments:n.hasAttachments}});if(n.folder)s.push({term:{folder:n.folder}});if(n.labels&&n.labels.length>0)s.push({terms:{labels:n.labels}});if(n.isRead!==void 0)s.push({term:{isRead:n.isRead}});if(n.dateFrom||n.dateTo){let u={date:{}};if(n.dateFrom)u.date.gte=n.dateFrom;if(n.dateTo)u.date.lte=n.dateTo;s.push({range:u})}let o={bool:{}};if(i.length>0)o.bool.must=i;if(s.length>0)o.bool.filter=s;if(i.length===0&&s.length===0)o.bool.must=[{match_all:{}}];let c=[];if(n.sort==="relevance"&&n.query)c.push({_score:n.sortOrder||"desc"});return c.push({date:n.sortOrder||"desc"}),{query:o,sort:c,from:n.offset||0,size:n.limit||20,highlight:{fields:{subject:{},body:{fragment_size:150,number_of_fragments:3}}}}}}class _t{static ThreadingLambdaCode=`
3859
+ `;static getIndexMapping(){return{mappings:{properties:{messageId:{type:"keyword"},from:{type:"keyword"},fromName:{type:"text"},to:{type:"keyword"},toName:{type:"text"},cc:{type:"keyword"},subject:{type:"text",analyzer:"standard",fields:{keyword:{type:"keyword"}}},body:{type:"text",analyzer:"standard"},bodyPreview:{type:"text"},date:{type:"date"},receivedAt:{type:"date"},hasAttachments:{type:"boolean"},attachmentNames:{type:"keyword"},labels:{type:"keyword"},folder:{type:"keyword"},threadId:{type:"keyword"},isRead:{type:"boolean"},isStarred:{type:"boolean"},mailbox:{type:"keyword"}}},settings:{number_of_shards:1,number_of_replicas:0}}}static buildSearchQuery(n){let i=[],s=[];if(n.query)i.push({multi_match:{query:n.query,fields:["subject^3","body","fromName","toName"],type:"best_fields",fuzziness:"AUTO"}});if(n.from)s.push({term:{from:n.from}});if(n.to)s.push({term:{to:n.to}});if(n.subject)i.push({match_phrase:{subject:n.subject}});if(n.hasAttachments!==void 0)s.push({term:{hasAttachments:n.hasAttachments}});if(n.folder)s.push({term:{folder:n.folder}});if(n.labels&&n.labels.length>0)s.push({terms:{labels:n.labels}});if(n.isRead!==void 0)s.push({term:{isRead:n.isRead}});if(n.dateFrom||n.dateTo){let u={date:{}};if(n.dateFrom)u.date.gte=n.dateFrom;if(n.dateTo)u.date.lte=n.dateTo;s.push({range:u})}let o={bool:{}};if(i.length>0)o.bool.must=i;if(s.length>0)o.bool.filter=s;if(i.length===0&&s.length===0)o.bool.must=[{match_all:{}}];let c=[];if(n.sort==="relevance"&&n.query)c.push({_score:n.sortOrder||"desc"});return c.push({date:n.sortOrder||"desc"}),{query:o,sort:c,from:n.offset||0,size:n.limit||20,highlight:{fields:{subject:{},body:{fragment_size:150,number_of_fragments:3}}}}}}class jt{static ThreadingLambdaCode=`
3862
3860
  const { S3Client, GetObjectCommand, PutObjectCommand } = require('@aws-sdk/client-s3');
3863
3861
  const crypto = require('crypto');
3864
3862
 
@@ -3998,7 +3996,7 @@ catch {
3998
3996
  ContentType: 'application/json',
3999
3997
  }));
4000
3998
  }
4001
- `;static createThreadingLambda(n){return{[`${n.slug}EmailThreadingLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-email-threading`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:_t.ThreadingLambdaCode},Environment:{Variables:{EMAIL_BUCKET:n.emailBucket}}}}}}static async getThreads(n){let{s3Client:i,bucket:s,mailbox:o,limit:c=50,offset:u=0}=n,[d,g]=o.includes("@")?o.split("@"):[o,"default"],y=`mailboxes/${g}/${d}/threads.json`;try{let h=await i.send({Bucket:s,Key:y}),A=JSON.parse(h.Body),C=Object.values(A);return C.sort((v,T)=>new Date(T.lastMessageDate).getTime()-new Date(v.lastMessageDate).getTime()),C.slice(u,u+c)}catch{return[]}}static async getThread(n){let{s3Client:i,bucket:s,mailbox:o,threadId:c}=n,[u,d]=o.includes("@")?o.split("@"):[o,"default"],g=`mailboxes/${d}/${u}/threads.json`;try{let y=await i.send({Bucket:s,Key:g});return JSON.parse(y.Body)[c]||null}catch{return null}}}class Wt{static SchedulerLambdaCode=`
3999
+ `;static createThreadingLambda(n){return{[`${n.slug}EmailThreadingLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-email-threading`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:jt.ThreadingLambdaCode},Environment:{Variables:{EMAIL_BUCKET:n.emailBucket}}}}}}static async getThreads(n){let{s3Client:i,bucket:s,mailbox:o,limit:c=50,offset:u=0}=n,[d,g]=o.includes("@")?o.split("@"):[o,"default"],y=`mailboxes/${g}/${d}/threads.json`;try{let h=await i.send({Bucket:s,Key:y}),A=JSON.parse(h.Body),C=Object.values(A);return C.sort((v,T)=>new Date(T.lastMessageDate).getTime()-new Date(v.lastMessageDate).getTime()),C.slice(u,u+c)}catch{return[]}}static async getThread(n){let{s3Client:i,bucket:s,mailbox:o,threadId:c}=n,[u,d]=o.includes("@")?o.split("@"):[o,"default"],g=`mailboxes/${d}/${u}/threads.json`;try{let y=await i.send({Bucket:s,Key:g});return JSON.parse(y.Body)[c]||null}catch{return null}}}class Kt{static SchedulerLambdaCode=`
4002
4000
  const { S3Client, GetObjectCommand, PutObjectCommand, DeleteObjectCommand, ListObjectsV2Command } = require('@aws-sdk/client-s3');
4003
4001
  const { SESClient, SendRawEmailCommand } = require('@aws-sdk/client-ses');
4004
4002
 
@@ -4127,7 +4125,7 @@ else {
4127
4125
 
4128
4126
  return raw;
4129
4127
  }
4130
- `;static createSchedulerLambda(n){return{[`${n.slug}EmailSchedulerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-email-scheduler`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:300,MemorySize:256,Code:{ZipFile:Wt.SchedulerLambdaCode},Environment:{Variables:{EMAIL_BUCKET:n.emailBucket}}}}}}static createSchedulerRule(n){return{[`${n.slug}EmailSchedulerRule`]:{Type:"AWS::Events::Rule",Properties:{Name:`${n.slug}-email-scheduler`,Description:"Trigger email scheduler every minute",ScheduleExpression:n.scheduleExpression||"rate(1 minute)",State:"ENABLED",Targets:[{Id:"EmailSchedulerTarget",Arn:n.lambdaArn}]}},[`${n.slug}EmailSchedulerPermission`]:{Type:"AWS::Lambda::Permission",Properties:{FunctionName:n.lambdaArn,Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:{"Fn::GetAtt":[`${n.slug}EmailSchedulerRule`,"Arn"]}}}}}static async scheduleEmail(n){let{s3Client:i,bucket:s,email:o,scheduledFor:c,timezone:u}=n,d=`sched-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,g={id:d,email:o,scheduledFor:typeof c==="string"?c:c.toISOString(),timezone:u,status:"pending",createdAt:new Date().toISOString()};return await i.send({Bucket:s,Key:`scheduled/${d}.json`,Body:JSON.stringify(g,null,2),ContentType:"application/json"}),g}static async cancelScheduledEmail(n){let{s3Client:i,bucket:s,id:o}=n;try{let c=await i.send({Bucket:s,Key:`scheduled/${o}.json`}),u=JSON.parse(c.Body);if(u.status!=="pending")return!1;return u.status="cancelled",await i.send({Bucket:s,Key:`scheduled/${o}.json`,Body:JSON.stringify(u,null,2),ContentType:"application/json"}),!0}catch{return!1}}static async listScheduledEmails(n){let{s3Client:i,bucket:s,status:o}=n,c=await i.send({Bucket:s,Prefix:"scheduled/"}),u=[];for(let d of c.Contents||[]){if(!d.Key.endsWith(".json"))continue;try{let g=await i.send({Bucket:s,Key:d.Key}),y=JSON.parse(g.Body);if(!o||y.status===o)u.push(y)}catch{}}return u.sort((d,g)=>new Date(d.scheduledFor).getTime()-new Date(g.scheduledFor).getTime()),u}}class Ye{static TrackingPixelLambdaCode=`
4128
+ `;static createSchedulerLambda(n){return{[`${n.slug}EmailSchedulerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-email-scheduler`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:300,MemorySize:256,Code:{ZipFile:Kt.SchedulerLambdaCode},Environment:{Variables:{EMAIL_BUCKET:n.emailBucket}}}}}}static createSchedulerRule(n){return{[`${n.slug}EmailSchedulerRule`]:{Type:"AWS::Events::Rule",Properties:{Name:`${n.slug}-email-scheduler`,Description:"Trigger email scheduler every minute",ScheduleExpression:n.scheduleExpression||"rate(1 minute)",State:"ENABLED",Targets:[{Id:"EmailSchedulerTarget",Arn:n.lambdaArn}]}},[`${n.slug}EmailSchedulerPermission`]:{Type:"AWS::Lambda::Permission",Properties:{FunctionName:n.lambdaArn,Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:{"Fn::GetAtt":[`${n.slug}EmailSchedulerRule`,"Arn"]}}}}}static async scheduleEmail(n){let{s3Client:i,bucket:s,email:o,scheduledFor:c,timezone:u}=n,d=`sched-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,g={id:d,email:o,scheduledFor:typeof c==="string"?c:c.toISOString(),timezone:u,status:"pending",createdAt:new Date().toISOString()};return await i.send({Bucket:s,Key:`scheduled/${d}.json`,Body:JSON.stringify(g,null,2),ContentType:"application/json"}),g}static async cancelScheduledEmail(n){let{s3Client:i,bucket:s,id:o}=n;try{let c=await i.send({Bucket:s,Key:`scheduled/${o}.json`}),u=JSON.parse(c.Body);if(u.status!=="pending")return!1;return u.status="cancelled",await i.send({Bucket:s,Key:`scheduled/${o}.json`,Body:JSON.stringify(u,null,2),ContentType:"application/json"}),!0}catch{return!1}}static async listScheduledEmails(n){let{s3Client:i,bucket:s,status:o}=n,c=await i.send({Bucket:s,Prefix:"scheduled/"}),u=[];for(let d of c.Contents||[]){if(!d.Key.endsWith(".json"))continue;try{let g=await i.send({Bucket:s,Key:d.Key}),y=JSON.parse(g.Body);if(!o||y.status===o)u.push(y)}catch{}}return u.sort((d,g)=>new Date(d.scheduledFor).getTime()-new Date(g.scheduledFor).getTime()),u}}class Xe{static TrackingPixelLambdaCode=`
4131
4129
  const { DynamoDBClient, UpdateItemCommand } = require('@aws-sdk/client-dynamodb');
4132
4130
 
4133
4131
  const dynamodb = new DynamoDBClient({});
@@ -4330,7 +4328,7 @@ catch (error) {
4330
4328
 
4331
4329
  return { statusCode: 200 };
4332
4330
  };
4333
- `;static createAnalyticsTable(n){return{[`${n.slug}EmailAnalyticsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-email-analytics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createTrackingPixelLambda(n){return{[`${n.slug}TrackingPixelLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-tracking-pixel`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:10,MemorySize:128,Code:{ZipFile:Ye.TrackingPixelLambdaCode},Environment:{Variables:{ANALYTICS_TABLE:n.analyticsTable}}}}}}static createClickTrackingLambda(n){return{[`${n.slug}ClickTrackingLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-click-tracking`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:10,MemorySize:128,Code:{ZipFile:Ye.ClickTrackingLambdaCode},Environment:{Variables:{ANALYTICS_TABLE:n.analyticsTable}}}}}}static createSesEventProcessorLambda(n){return{[`${n.slug}SesEventProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-ses-event-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Ye.SesEventProcessorCode},Environment:{Variables:{ANALYTICS_TABLE:n.analyticsTable}}}}}}static injectTracking(n){let{html:i,messageId:s,trackingDomain:o}=n,c=`<img src="https://${o}/track/open/${s}" width="1" height="1" style="display:none" alt="" />`,u=i.replace("</body>",`${c}</body>`);return u=u.replace(/href="(https?:\/\/[^"]+)"/g,(d,g)=>{let y=encodeURIComponent(g);return`href="https://${o}/track/click/${s}?url=${y}"`}),u}static calculateMetrics(n){let i=n.filter((y)=>y.sent).length,s=n.filter((y)=>y.delivered).length,o=n.filter((y)=>y.opened).length,c=n.filter((y)=>y.clicked).length,u=n.filter((y)=>y.bounced).length,d=n.filter((y)=>y.complained).length,g=n.filter((y)=>y.unsubscribed).length;return{period:new Date().toISOString(),sent:i,delivered:s,opened:o,clicked:c,bounced:u,complained:d,unsubscribed:g,deliveryRate:i>0?s/i*100:0,openRate:s>0?o/s*100:0,clickRate:o>0?c/o*100:0,bounceRate:i>0?u/i*100:0,complaintRate:s>0?d/s*100:0}}}class ke{static TemplateRendererCode=`
4331
+ `;static createAnalyticsTable(n){return{[`${n.slug}EmailAnalyticsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-email-analytics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createTrackingPixelLambda(n){return{[`${n.slug}TrackingPixelLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-tracking-pixel`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:10,MemorySize:128,Code:{ZipFile:Xe.TrackingPixelLambdaCode},Environment:{Variables:{ANALYTICS_TABLE:n.analyticsTable}}}}}}static createClickTrackingLambda(n){return{[`${n.slug}ClickTrackingLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-click-tracking`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:10,MemorySize:128,Code:{ZipFile:Xe.ClickTrackingLambdaCode},Environment:{Variables:{ANALYTICS_TABLE:n.analyticsTable}}}}}}static createSesEventProcessorLambda(n){return{[`${n.slug}SesEventProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-ses-event-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Xe.SesEventProcessorCode},Environment:{Variables:{ANALYTICS_TABLE:n.analyticsTable}}}}}}static injectTracking(n){let{html:i,messageId:s,trackingDomain:o}=n,c=`<img src="https://${o}/track/open/${s}" width="1" height="1" style="display:none" alt="" />`,u=i.replace("</body>",`${c}</body>`);return u=u.replace(/href="(https?:\/\/[^"]+)"/g,(d,g)=>{let y=encodeURIComponent(g);return`href="https://${o}/track/click/${s}?url=${y}"`}),u}static calculateMetrics(n){let i=n.filter((y)=>y.sent).length,s=n.filter((y)=>y.delivered).length,o=n.filter((y)=>y.opened).length,c=n.filter((y)=>y.clicked).length,u=n.filter((y)=>y.bounced).length,d=n.filter((y)=>y.complained).length,g=n.filter((y)=>y.unsubscribed).length;return{period:new Date().toISOString(),sent:i,delivered:s,opened:o,clicked:c,bounced:u,complained:d,unsubscribed:g,deliveryRate:i>0?s/i*100:0,openRate:s>0?o/s*100:0,clickRate:o>0?c/o*100:0,bounceRate:i>0?u/i*100:0,complaintRate:s>0?d/s*100:0}}}class Me{static TemplateRendererCode=`
4334
4332
  const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
4335
4333
 
4336
4334
  const s3 = new S3Client({});
@@ -4585,7 +4583,7 @@ The {{appName}} Team`,variables:["appName","userName","resetUrl","expiresIn"],ca
4585
4583
 
4586
4584
  <p>Best regards,<br>The {{appName}} Team</p>
4587
4585
  </body>
4588
- </html>`,variables:["invoiceNumber","customerName","period","items","total","paymentUrl","appName"],category:"billing"}};static createTemplateBucket(n){return{[`${n.slug}EmailTemplateBucket`]:{Type:"AWS::S3::Bucket",Properties:{BucketName:`${n.slug}-email-templates`,VersioningConfiguration:{Status:"Enabled"}}}}}static createTemplateRendererLambda(n){return{[`${n.slug}TemplateRendererLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-template-renderer`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:ke.TemplateRendererCode},Environment:{Variables:{TEMPLATE_BUCKET:n.templateBucket}}}}}}static render(n,i){if(!n||!i)return n;let s=n;return s=s.replace(/\{\{\s*([\w.]+)\s*\}\}/g,(o,c)=>{let u=ke.getNestedValue(i,c);return u!==void 0?String(u):o}),s=s.replace(/\{\{#if\s+([\w.]+)\}\}([\s\S]*?)\{\{\/if\}\}/g,(o,c,u)=>ke.getNestedValue(i,c)?u:""),s=s.replace(/\{\{#unless\s+([\w.]+)\}\}([\s\S]*?)\{\{\/unless\}\}/g,(o,c,u)=>!ke.getNestedValue(i,c)?u:""),s=s.replace(/\{\{#each\s+([\w.]+)\}\}([\s\S]*?)\{\{\/each\}\}/g,(o,c,u)=>{let d=ke.getNestedValue(i,c);if(!Array.isArray(d))return"";return d.map((g,y)=>{let h=u;if(h=h.replace(/\{\{this\}\}/g,String(g)),h=h.replace(/\{\{@index\}\}/g,String(y)),typeof g==="object")Object.entries(g).forEach(([A,C])=>{h=h.replace(new RegExp(`\\{\\{\\s*${A}\\s*\\}\\}`,"g"),String(C))});return h}).join("")}),s}static getNestedValue(n,i){return i.split(".").reduce((s,o)=>s?.[o],n)}static extractVariables(n){let i=new Set,s=n.matchAll(/\{\{\s*([\w.]+)\s*\}\}/g);for(let c of s)if(!c[1].startsWith("#")&&!c[1].startsWith("/")&&!c[1].startsWith("@"))i.add(c[1].split(".")[0]);let o=n.matchAll(/\{\{#(?:if|unless|each)\s+([\w.]+)\}\}/g);for(let c of o)i.add(c[1].split(".")[0]);return Array.from(i)}}class Vt{static SharedMailboxLambdaCode=`
4586
+ </html>`,variables:["invoiceNumber","customerName","period","items","total","paymentUrl","appName"],category:"billing"}};static createTemplateBucket(n){return{[`${n.slug}EmailTemplateBucket`]:{Type:"AWS::S3::Bucket",Properties:{BucketName:`${n.slug}-email-templates`,VersioningConfiguration:{Status:"Enabled"}}}}}static createTemplateRendererLambda(n){return{[`${n.slug}TemplateRendererLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-template-renderer`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Me.TemplateRendererCode},Environment:{Variables:{TEMPLATE_BUCKET:n.templateBucket}}}}}}static render(n,i){if(!n||!i)return n;let s=n;return s=s.replace(/\{\{\s*([\w.]+)\s*\}\}/g,(o,c)=>{let u=Me.getNestedValue(i,c);return u!==void 0?String(u):o}),s=s.replace(/\{\{#if\s+([\w.]+)\}\}([\s\S]*?)\{\{\/if\}\}/g,(o,c,u)=>Me.getNestedValue(i,c)?u:""),s=s.replace(/\{\{#unless\s+([\w.]+)\}\}([\s\S]*?)\{\{\/unless\}\}/g,(o,c,u)=>!Me.getNestedValue(i,c)?u:""),s=s.replace(/\{\{#each\s+([\w.]+)\}\}([\s\S]*?)\{\{\/each\}\}/g,(o,c,u)=>{let d=Me.getNestedValue(i,c);if(!Array.isArray(d))return"";return d.map((g,y)=>{let h=u;if(h=h.replace(/\{\{this\}\}/g,String(g)),h=h.replace(/\{\{@index\}\}/g,String(y)),typeof g==="object")Object.entries(g).forEach(([A,C])=>{h=h.replace(new RegExp(`\\{\\{\\s*${A}\\s*\\}\\}`,"g"),String(C))});return h}).join("")}),s}static getNestedValue(n,i){return i.split(".").reduce((s,o)=>s?.[o],n)}static extractVariables(n){let i=new Set,s=n.matchAll(/\{\{\s*([\w.]+)\s*\}\}/g);for(let c of s)if(!c[1].startsWith("#")&&!c[1].startsWith("/")&&!c[1].startsWith("@"))i.add(c[1].split(".")[0]);let o=n.matchAll(/\{\{#(?:if|unless|each)\s+([\w.]+)\}\}/g);for(let c of o)i.add(c[1].split(".")[0]);return Array.from(i)}}class qt{static SharedMailboxLambdaCode=`
4589
4587
  const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
4590
4588
  const { DynamoDBClient, GetItemCommand, PutItemCommand, QueryCommand, UpdateItemCommand } = require('@aws-sdk/client-dynamodb');
4591
4589
 
@@ -4816,7 +4814,7 @@ function unmarshallMailbox(item) {
4816
4814
  updatedAt: item.updatedAt.S,
4817
4815
  };
4818
4816
  }
4819
- `;static createMailboxTable(n){return{[`${n.slug}SharedMailboxTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-shared-mailboxes`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"},{AttributeName:"type",AttributeType:"S"},{AttributeName:"mailboxId",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],GlobalSecondaryIndexes:[{IndexName:"type-index",KeySchema:[{AttributeName:"type",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"}},{IndexName:"mailbox-index",KeySchema:[{AttributeName:"mailboxId",KeyType:"HASH"},{AttributeName:"id",KeyType:"RANGE"}],Projection:{ProjectionType:"ALL"}}]}}}}static createSharedMailboxLambda(n){return{[`${n.slug}SharedMailboxLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-shared-mailbox`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Vt.SharedMailboxLambdaCode},Environment:{Variables:{EMAIL_BUCKET:n.emailBucket,MAILBOX_TABLE:n.mailboxTable}}}}}}static PermissionSets={owner:{read:!0,send:!0,delete:!0,manage:!0,assignTo:!0},admin:{read:!0,send:!0,delete:!0,manage:!0,assignTo:!0},member:{read:!0,send:!0,delete:!1,manage:!1,assignTo:!0},viewer:{read:!0,send:!1,delete:!1,manage:!1,assignTo:!1}}}class Ut{static RuleProcessorCode=`
4817
+ `;static createMailboxTable(n){return{[`${n.slug}SharedMailboxTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-shared-mailboxes`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"},{AttributeName:"type",AttributeType:"S"},{AttributeName:"mailboxId",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],GlobalSecondaryIndexes:[{IndexName:"type-index",KeySchema:[{AttributeName:"type",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"}},{IndexName:"mailbox-index",KeySchema:[{AttributeName:"mailboxId",KeyType:"HASH"},{AttributeName:"id",KeyType:"RANGE"}],Projection:{ProjectionType:"ALL"}}]}}}}static createSharedMailboxLambda(n){return{[`${n.slug}SharedMailboxLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-shared-mailbox`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:qt.SharedMailboxLambdaCode},Environment:{Variables:{EMAIL_BUCKET:n.emailBucket,MAILBOX_TABLE:n.mailboxTable}}}}}}static PermissionSets={owner:{read:!0,send:!0,delete:!0,manage:!0,assignTo:!0},admin:{read:!0,send:!0,delete:!0,manage:!0,assignTo:!0},member:{read:!0,send:!0,delete:!1,manage:!1,assignTo:!0},viewer:{read:!0,send:!1,delete:!1,manage:!1,assignTo:!1}}}class zt{static RuleProcessorCode=`
4820
4818
  const { S3Client, GetObjectCommand, PutObjectCommand, CopyObjectCommand, DeleteObjectCommand } = require('@aws-sdk/client-s3');
4821
4819
  const { DynamoDBClient, QueryCommand } = require('@aws-sdk/client-dynamodb');
4822
4820
  const { LambdaClient, InvokeCommand } = require('@aws-sdk/client-lambda');
@@ -5129,7 +5127,7 @@ async function invokeLambda(functionName, metadata) {
5129
5127
  Payload: JSON.stringify(metadata),
5130
5128
  }));
5131
5129
  }
5132
- `;static createRulesTable(n){return{[`${n.slug}EmailRulesTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-email-rules`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"mailbox",AttributeType:"S"},{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"mailbox",KeyType:"HASH"},{AttributeName:"id",KeyType:"RANGE"}]}}}}static createRuleProcessorLambda(n){return{[`${n.slug}EmailRuleProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-email-rule-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:Ut.RuleProcessorCode},Environment:{Variables:{EMAIL_BUCKET:n.emailBucket,RULES_TABLE:n.rulesTable}}}}}}static RuleTemplates={spamFilter:{name:"Spam Filter",conditions:[{field:"subject",operator:"regex",value:"(viagra|lottery|winner|prince|inheritance)",caseSensitive:!1}],conditionOperator:"or",actions:[{type:"move",params:{folder:"spam"}},{type:"mark-read",params:{}}]},autoLabel:{name:"Auto Label Invoices",conditions:[{field:"subject",operator:"contains",value:"invoice",caseSensitive:!1}],conditionOperator:"and",actions:[{type:"label",params:{label:"invoices"}}]},forwardUrgent:{name:"Forward Urgent",conditions:[{field:"subject",operator:"contains",value:"urgent",caseSensitive:!1}],conditionOperator:"and",actions:[{type:"forward",params:{to:"admin@example.com"}},{type:"label",params:{label:"urgent"}}]}}}var xi=`
5130
+ `;static createRulesTable(n){return{[`${n.slug}EmailRulesTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-email-rules`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"mailbox",AttributeType:"S"},{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"mailbox",KeyType:"HASH"},{AttributeName:"id",KeyType:"RANGE"}]}}}}static createRuleProcessorLambda(n){return{[`${n.slug}EmailRuleProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-email-rule-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:zt.RuleProcessorCode},Environment:{Variables:{EMAIL_BUCKET:n.emailBucket,RULES_TABLE:n.rulesTable}}}}}}static RuleTemplates={spamFilter:{name:"Spam Filter",conditions:[{field:"subject",operator:"regex",value:"(viagra|lottery|winner|prince|inheritance)",caseSensitive:!1}],conditionOperator:"or",actions:[{type:"move",params:{folder:"spam"}},{type:"mark-read",params:{}}]},autoLabel:{name:"Auto Label Invoices",conditions:[{field:"subject",operator:"contains",value:"invoice",caseSensitive:!1}],conditionOperator:"and",actions:[{type:"label",params:{label:"invoices"}}]},forwardUrgent:{name:"Forward Urgent",conditions:[{field:"subject",operator:"contains",value:"urgent",caseSensitive:!1}],conditionOperator:"and",actions:[{type:"forward",params:{to:"admin@example.com"}},{type:"label",params:{label:"urgent"}}]}}}var ps=`
5133
5131
  const { S3Client, GetObjectCommand, PutObjectCommand, CopyObjectCommand } = require('@aws-sdk/client-s3');
5134
5132
  const s3 = new S3Client({});
5135
5133
 
@@ -5287,7 +5285,7 @@ catch (error) {
5287
5285
 
5288
5286
  return { statusCode: 200, body: 'OK' };
5289
5287
  };
5290
- `,ki=`
5288
+ `,gs=`
5291
5289
  const { S3Client, GetObjectCommand, PutObjectCommand, CopyObjectCommand } = require('@aws-sdk/client-s3');
5292
5290
  const s3 = new S3Client({});
5293
5291
 
@@ -5445,7 +5443,7 @@ catch (error) {
5445
5443
 
5446
5444
  return { statusCode: 200, body: 'OK' };
5447
5445
  };
5448
- `;class Ht{static RecordingProcessorCode=`
5446
+ `;class Qt{static RecordingProcessorCode=`
5449
5447
  const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
5450
5448
  const { TranscribeClient, StartTranscriptionJobCommand } = require('@aws-sdk/client-transcribe');
5451
5449
  const { DynamoDBClient, PutItemCommand, UpdateItemCommand } = require('@aws-sdk/client-dynamodb');
@@ -5637,7 +5635,7 @@ else if (jobStatus === 'FAILED') {
5637
5635
 
5638
5636
  return { statusCode: 200 };
5639
5637
  };
5640
- `;static createRecordingsTable(n){return{[`${n.slug}CallRecordingsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-call-recordings`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"recordingId",AttributeType:"S"},{AttributeName:"transcriptionJobName",AttributeType:"S"}],KeySchema:[{AttributeName:"recordingId",KeyType:"HASH"}],GlobalSecondaryIndexes:[{IndexName:"job-index",KeySchema:[{AttributeName:"transcriptionJobName",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"}}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createRecordingProcessorLambda(n){return{[`${n.slug}RecordingProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-recording-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:Ht.RecordingProcessorCode},Environment:{Variables:{RECORDING_BUCKET:n.recordingBucket,RECORDINGS_TABLE:n.recordingsTable}}}}}}}class Be{nodes=[];connections=[];startNodeId="";static create(n){return new Be}start(){let n={id:this.generateId(),type:"start",position:{x:0,y:0},config:{}};return this.nodes.push(n),this.startNodeId=n.id,this}playPrompt(n,i){let s={id:this.generateId(),type:"play-prompt",position:{x:0,y:0},config:{text:n,textType:i?.ssml?"ssml":"text",voice:i?.voice||"Joanna"}};return this.nodes.push(s),this.connectToLast(s.id),this}getInput(n,i){let s={id:this.generateId(),type:"get-input",position:{x:0,y:0},config:{prompt:n,maxDigits:i?.maxDigits||1,timeout:i?.timeout||5,errorPrompt:i?.errorPrompt||"Sorry, I didn't get that."}};return this.nodes.push(s),this.connectToLast(s.id),this}menu(n,i){let s={id:this.generateId(),type:"menu",position:{x:0,y:0},config:{prompt:n,options:i}};return this.nodes.push(s),this.connectToLast(s.id),this}transferToQueue(n,i){let s={id:this.generateId(),type:"transfer-queue",position:{x:0,y:0},config:{queueArn:n,priority:i?.priority||5}};return this.nodes.push(s),this.connectToLast(s.id),this}transferToPhone(n){let i={id:this.generateId(),type:"transfer-phone",position:{x:0,y:0},config:{phoneNumber:n}};return this.nodes.push(i),this.connectToLast(i.id),this}invokeLambda(n,i){let s={id:this.generateId(),type:"invoke-lambda",position:{x:0,y:0},config:{functionArn:n,timeout:i?.timeout||8}};return this.nodes.push(s),this.connectToLast(s.id),this}setAttribute(n,i){let s={id:this.generateId(),type:"set-attribute",position:{x:0,y:0},config:{key:n,value:i}};return this.nodes.push(s),this.connectToLast(s.id),this}checkHours(n){let i={id:this.generateId(),type:"check-hours",position:{x:0,y:0},config:{hoursOfOperationArn:n}};return this.nodes.push(i),this.connectToLast(i.id),this}recordVoicemail(n){let i={id:this.generateId(),type:"record-voicemail",position:{x:0,y:0},config:{maxDuration:n?.maxDuration||120,greeting:n?.greeting||"Please leave a message after the beep.",beep:n?.beep!==!1}};return this.nodes.push(i),this.connectToLast(i.id),this}wait(n){let i={id:this.generateId(),type:"wait",position:{x:0,y:0},config:{seconds:n}};return this.nodes.push(i),this.connectToLast(i.id),this}disconnect(){let n={id:this.generateId(),type:"disconnect",position:{x:0,y:0},config:{}};return this.nodes.push(n),this.connectToLast(n.id),this}build(){return{id:this.generateId(),name:"IVR Flow",nodes:this.nodes,connections:this.connections,startNodeId:this.startNodeId,version:1,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()}}toContactFlow(){let n=[],i=new Map(this.nodes.map((o)=>[o.id,o]));for(let o of this.nodes){let c=this.nodeToAction(o,i);if(c)n.push(c)}let s={Version:"2019-10-30",StartAction:this.startNodeId,Actions:n};return JSON.stringify(s,null,2)}nodeToAction(n,i){let s=this.getNextNodeId(n.id),o={NextAction:s||"disconnect",Errors:[{NextAction:"disconnect"}]};switch(n.type){case"start":return null;case"play-prompt":return{Identifier:n.id,Type:"MessageParticipant",Parameters:{Text:n.config.text,TextType:n.config.textType},Transitions:o};case"get-input":return{Identifier:n.id,Type:"GetParticipantInput",Parameters:{Text:n.config.prompt,InputTimeLimitSeconds:n.config.timeout,MaxDigits:n.config.maxDigits},Transitions:{...o,Conditions:[]}};case"transfer-queue":return{Identifier:n.id,Type:"TransferToQueue",Parameters:{QueueId:n.config.queueArn},Transitions:o};case"transfer-phone":return{Identifier:n.id,Type:"TransferToPhoneNumber",Parameters:{PhoneNumber:n.config.phoneNumber},Transitions:o};case"invoke-lambda":return{Identifier:n.id,Type:"InvokeLambdaFunction",Parameters:{LambdaFunctionARN:n.config.functionArn,InvocationTimeLimitSeconds:n.config.timeout},Transitions:o};case"set-attribute":return{Identifier:n.id,Type:"UpdateContactAttributes",Parameters:{Attributes:{[n.config.key]:n.config.value}},Transitions:o};case"check-hours":return{Identifier:n.id,Type:"CheckHoursOfOperation",Parameters:{HoursOfOperationId:n.config.hoursOfOperationArn},Transitions:{NextAction:s,Conditions:[{NextAction:s,Condition:{Operator:"Equals",Operands:["True"]}}],Errors:[{NextAction:"disconnect"}]}};case"wait":return{Identifier:n.id,Type:"Wait",Parameters:{Seconds:n.config.seconds},Transitions:o};case"disconnect":return{Identifier:n.id,Type:"DisconnectParticipant",Parameters:{},Transitions:{}};default:return null}}connectToLast(n){if(this.nodes.length>1){let i=this.nodes[this.nodes.length-2];this.connections.push({id:this.generateId(),sourceNodeId:i.id,targetNodeId:n,sourcePort:"default"})}}getNextNodeId(n){return this.connections.find((s)=>s.sourceNodeId===n)?.targetNodeId||null}generateId(){return`node-${Date.now()}-${Math.random().toString(36).substr(2,9)}`}static Templates={basicSupport:()=>Be.create("Basic Support").start().playPrompt("Welcome to customer support.").menu("Press 1 for sales, 2 for support, or 3 to leave a message.",{"1":"sales","2":"support","3":"voicemail"}),afterHours:(n)=>Be.create("After Hours").start().playPrompt(n).recordVoicemail({greeting:"Please leave your name, number, and a brief message.",maxDuration:120}).playPrompt("Thank you for your message. Goodbye.").disconnect(),callbackRequest:(n)=>Be.create("Callback Request").start().playPrompt("All agents are currently busy.").getInput("Press 1 to request a callback, or 2 to wait.",{maxDigits:1}).invokeLambda(n).playPrompt("We will call you back shortly. Goodbye.").disconnect()}}class jt{static MetricsAggregatorCode=`
5638
+ `;static createRecordingsTable(n){return{[`${n.slug}CallRecordingsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-call-recordings`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"recordingId",AttributeType:"S"},{AttributeName:"transcriptionJobName",AttributeType:"S"}],KeySchema:[{AttributeName:"recordingId",KeyType:"HASH"}],GlobalSecondaryIndexes:[{IndexName:"job-index",KeySchema:[{AttributeName:"transcriptionJobName",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"}}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createRecordingProcessorLambda(n){return{[`${n.slug}RecordingProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-recording-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:Qt.RecordingProcessorCode},Environment:{Variables:{RECORDING_BUCKET:n.recordingBucket,RECORDINGS_TABLE:n.recordingsTable}}}}}}}class Ge{nodes=[];connections=[];startNodeId="";static create(n){return new Ge}start(){let n={id:this.generateId(),type:"start",position:{x:0,y:0},config:{}};return this.nodes.push(n),this.startNodeId=n.id,this}playPrompt(n,i){let s={id:this.generateId(),type:"play-prompt",position:{x:0,y:0},config:{text:n,textType:i?.ssml?"ssml":"text",voice:i?.voice||"Joanna"}};return this.nodes.push(s),this.connectToLast(s.id),this}getInput(n,i){let s={id:this.generateId(),type:"get-input",position:{x:0,y:0},config:{prompt:n,maxDigits:i?.maxDigits||1,timeout:i?.timeout||5,errorPrompt:i?.errorPrompt||"Sorry, I didn't get that."}};return this.nodes.push(s),this.connectToLast(s.id),this}menu(n,i){let s={id:this.generateId(),type:"menu",position:{x:0,y:0},config:{prompt:n,options:i}};return this.nodes.push(s),this.connectToLast(s.id),this}transferToQueue(n,i){let s={id:this.generateId(),type:"transfer-queue",position:{x:0,y:0},config:{queueArn:n,priority:i?.priority||5}};return this.nodes.push(s),this.connectToLast(s.id),this}transferToPhone(n){let i={id:this.generateId(),type:"transfer-phone",position:{x:0,y:0},config:{phoneNumber:n}};return this.nodes.push(i),this.connectToLast(i.id),this}invokeLambda(n,i){let s={id:this.generateId(),type:"invoke-lambda",position:{x:0,y:0},config:{functionArn:n,timeout:i?.timeout||8}};return this.nodes.push(s),this.connectToLast(s.id),this}setAttribute(n,i){let s={id:this.generateId(),type:"set-attribute",position:{x:0,y:0},config:{key:n,value:i}};return this.nodes.push(s),this.connectToLast(s.id),this}checkHours(n){let i={id:this.generateId(),type:"check-hours",position:{x:0,y:0},config:{hoursOfOperationArn:n}};return this.nodes.push(i),this.connectToLast(i.id),this}recordVoicemail(n){let i={id:this.generateId(),type:"record-voicemail",position:{x:0,y:0},config:{maxDuration:n?.maxDuration||120,greeting:n?.greeting||"Please leave a message after the beep.",beep:n?.beep!==!1}};return this.nodes.push(i),this.connectToLast(i.id),this}wait(n){let i={id:this.generateId(),type:"wait",position:{x:0,y:0},config:{seconds:n}};return this.nodes.push(i),this.connectToLast(i.id),this}disconnect(){let n={id:this.generateId(),type:"disconnect",position:{x:0,y:0},config:{}};return this.nodes.push(n),this.connectToLast(n.id),this}build(){return{id:this.generateId(),name:"IVR Flow",nodes:this.nodes,connections:this.connections,startNodeId:this.startNodeId,version:1,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()}}toContactFlow(){let n=[],i=new Map(this.nodes.map((o)=>[o.id,o]));for(let o of this.nodes){let c=this.nodeToAction(o,i);if(c)n.push(c)}let s={Version:"2019-10-30",StartAction:this.startNodeId,Actions:n};return JSON.stringify(s,null,2)}nodeToAction(n,i){let s=this.getNextNodeId(n.id),o={NextAction:s||"disconnect",Errors:[{NextAction:"disconnect"}]};switch(n.type){case"start":return null;case"play-prompt":return{Identifier:n.id,Type:"MessageParticipant",Parameters:{Text:n.config.text,TextType:n.config.textType},Transitions:o};case"get-input":return{Identifier:n.id,Type:"GetParticipantInput",Parameters:{Text:n.config.prompt,InputTimeLimitSeconds:n.config.timeout,MaxDigits:n.config.maxDigits},Transitions:{...o,Conditions:[]}};case"transfer-queue":return{Identifier:n.id,Type:"TransferToQueue",Parameters:{QueueId:n.config.queueArn},Transitions:o};case"transfer-phone":return{Identifier:n.id,Type:"TransferToPhoneNumber",Parameters:{PhoneNumber:n.config.phoneNumber},Transitions:o};case"invoke-lambda":return{Identifier:n.id,Type:"InvokeLambdaFunction",Parameters:{LambdaFunctionARN:n.config.functionArn,InvocationTimeLimitSeconds:n.config.timeout},Transitions:o};case"set-attribute":return{Identifier:n.id,Type:"UpdateContactAttributes",Parameters:{Attributes:{[n.config.key]:n.config.value}},Transitions:o};case"check-hours":return{Identifier:n.id,Type:"CheckHoursOfOperation",Parameters:{HoursOfOperationId:n.config.hoursOfOperationArn},Transitions:{NextAction:s,Conditions:[{NextAction:s,Condition:{Operator:"Equals",Operands:["True"]}}],Errors:[{NextAction:"disconnect"}]}};case"wait":return{Identifier:n.id,Type:"Wait",Parameters:{Seconds:n.config.seconds},Transitions:o};case"disconnect":return{Identifier:n.id,Type:"DisconnectParticipant",Parameters:{},Transitions:{}};default:return null}}connectToLast(n){if(this.nodes.length>1){let i=this.nodes[this.nodes.length-2];this.connections.push({id:this.generateId(),sourceNodeId:i.id,targetNodeId:n,sourcePort:"default"})}}getNextNodeId(n){return this.connections.find((s)=>s.sourceNodeId===n)?.targetNodeId||null}generateId(){return`node-${Date.now()}-${Math.random().toString(36).substr(2,9)}`}static Templates={basicSupport:()=>Ge.create("Basic Support").start().playPrompt("Welcome to customer support.").menu("Press 1 for sales, 2 for support, or 3 to leave a message.",{"1":"sales","2":"support","3":"voicemail"}),afterHours:(n)=>Ge.create("After Hours").start().playPrompt(n).recordVoicemail({greeting:"Please leave your name, number, and a brief message.",maxDuration:120}).playPrompt("Thank you for your message. Goodbye.").disconnect(),callbackRequest:(n)=>Ge.create("Callback Request").start().playPrompt("All agents are currently busy.").getInput("Press 1 to request a callback, or 2 to wait.",{maxDigits:1}).invokeLambda(n).playPrompt("We will call you back shortly. Goodbye.").disconnect()}}class Jt{static MetricsAggregatorCode=`
5641
5639
  const { DynamoDBClient, PutItemCommand, ScanCommand } = require('@aws-sdk/client-dynamodb');
5642
5640
 
5643
5641
  const dynamodb = new DynamoDBClient({});
@@ -5836,7 +5834,7 @@ catch (error) {
5836
5834
  };
5837
5835
  }
5838
5836
  };
5839
- `;static createMetricsTable(n){return{[`${n.slug}CallMetricsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-call-metrics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"period",AttributeType:"S"}],KeySchema:[{AttributeName:"period",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createMetricsAggregatorLambda(n){return{[`${n.slug}CallMetricsAggregatorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-call-metrics-aggregator`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:jt.MetricsAggregatorCode},Environment:{Variables:{CALL_LOG_TABLE:n.callLogTable,METRICS_TABLE:n.metricsTable}}}}}}static createMetricsSchedule(n){return{[`${n.slug}CallMetricsSchedule`]:{Type:"AWS::Events::Rule",Properties:{Name:`${n.slug}-call-metrics-schedule`,Description:"Aggregate call metrics hourly",ScheduleExpression:"rate(1 hour)",State:"ENABLED",Targets:[{Id:"MetricsAggregatorTarget",Arn:n.lambdaArn}]}}}}}class mt{static CallbackRequestCode=`
5837
+ `;static createMetricsTable(n){return{[`${n.slug}CallMetricsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-call-metrics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"period",AttributeType:"S"}],KeySchema:[{AttributeName:"period",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createMetricsAggregatorLambda(n){return{[`${n.slug}CallMetricsAggregatorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-call-metrics-aggregator`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:Jt.MetricsAggregatorCode},Environment:{Variables:{CALL_LOG_TABLE:n.callLogTable,METRICS_TABLE:n.metricsTable}}}}}}static createMetricsSchedule(n){return{[`${n.slug}CallMetricsSchedule`]:{Type:"AWS::Events::Rule",Properties:{Name:`${n.slug}-call-metrics-schedule`,Description:"Aggregate call metrics hourly",ScheduleExpression:"rate(1 hour)",State:"ENABLED",Targets:[{Id:"MetricsAggregatorTarget",Arn:n.lambdaArn}]}}}}}class gt{static CallbackRequestCode=`
5840
5838
  const { DynamoDBClient, PutItemCommand, UpdateItemCommand } = require('@aws-sdk/client-dynamodb');
5841
5839
  const { ConnectClient, StartOutboundVoiceContactCommand } = require('@aws-sdk/client-connect');
5842
5840
  const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');
@@ -6126,7 +6124,7 @@ catch (error) {
6126
6124
  return { statusCode: 500, error: error.message };
6127
6125
  }
6128
6126
  };
6129
- `;static createCallbacksTable(n){return{[`${n.slug}CallbacksTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-callbacks`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createCallbackRequestLambda(n){return{[`${n.slug}CallbackRequestLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-callback-request`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:mt.CallbackRequestCode},Environment:{Variables:{CALLBACKS_TABLE:n.callbacksTable,NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||""}}}}}}static createCallbackProcessorLambda(n){return{[`${n.slug}CallbackProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-callback-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:300,MemorySize:256,Code:{ZipFile:mt.CallbackProcessorCode},Environment:{Variables:{CALLBACKS_TABLE:n.callbacksTable,CONNECT_INSTANCE_ID:n.connectInstanceId,CONTACT_FLOW_ID:n.contactFlowId,SOURCE_PHONE_NUMBER:n.sourcePhoneNumber,QUEUE_ID:n.queueId||""}}}}}}}class Kt{static CampaignManagerCode=`
6127
+ `;static createCallbacksTable(n){return{[`${n.slug}CallbacksTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-callbacks`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createCallbackRequestLambda(n){return{[`${n.slug}CallbackRequestLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-callback-request`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:gt.CallbackRequestCode},Environment:{Variables:{CALLBACKS_TABLE:n.callbacksTable,NOTIFICATION_TOPIC_ARN:n.notificationTopicArn||""}}}}}}static createCallbackProcessorLambda(n){return{[`${n.slug}CallbackProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-callback-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:300,MemorySize:256,Code:{ZipFile:gt.CallbackProcessorCode},Environment:{Variables:{CALLBACKS_TABLE:n.callbacksTable,CONNECT_INSTANCE_ID:n.connectInstanceId,CONTACT_FLOW_ID:n.contactFlowId,SOURCE_PHONE_NUMBER:n.sourcePhoneNumber,QUEUE_ID:n.queueId||""}}}}}}}class Yt{static CampaignManagerCode=`
6130
6128
  const { DynamoDBClient, PutItemCommand, GetItemCommand, UpdateItemCommand, ScanCommand } = require('@aws-sdk/client-dynamodb');
6131
6129
 
6132
6130
  const dynamodb = new DynamoDBClient({});
@@ -6510,7 +6508,7 @@ function unmarshallCampaign(item) {
6510
6508
  stats: JSON.parse(item.stats?.S || '{}'),
6511
6509
  };
6512
6510
  }
6513
- `;static createCampaignsTable(n){return{[`${n.slug}SmsCampaignsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-sms-campaigns`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}}static createCampaignManagerLambda(n){return{[`${n.slug}SmsCampaignManagerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-campaign-manager`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Kt.CampaignManagerCode},Environment:{Variables:{CAMPAIGNS_TABLE:n.campaignsTable}}}}}}}class qt{static AnalyticsAggregatorCode=`
6511
+ `;static createCampaignsTable(n){return{[`${n.slug}SmsCampaignsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-sms-campaigns`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}}static createCampaignManagerLambda(n){return{[`${n.slug}SmsCampaignManagerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-campaign-manager`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Yt.CampaignManagerCode},Environment:{Variables:{CAMPAIGNS_TABLE:n.campaignsTable}}}}}}}class Zt{static AnalyticsAggregatorCode=`
6514
6512
  const { DynamoDBClient, ScanCommand, PutItemCommand } = require('@aws-sdk/client-dynamodb');
6515
6513
 
6516
6514
  const dynamodb = new DynamoDBClient({});
@@ -6705,7 +6703,7 @@ catch (error) {
6705
6703
 
6706
6704
  return { statusCode: 200 };
6707
6705
  };
6708
- `;static createAnalyticsTable(n){return{[`${n.slug}SmsAnalyticsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-sms-analytics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"period",AttributeType:"S"}],KeySchema:[{AttributeName:"period",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createDeliveryReportsTable(n){return{[`${n.slug}SmsDeliveryReportsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-sms-delivery-reports`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createAnalyticsAggregatorLambda(n){return{[`${n.slug}SmsAnalyticsAggregatorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-analytics-aggregator`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:qt.AnalyticsAggregatorCode},Environment:{Variables:{MESSAGE_LOG_TABLE:n.messageLogTable,ANALYTICS_TABLE:n.analyticsTable}}}}}}}class zt{static MmsSenderCode=`
6706
+ `;static createAnalyticsTable(n){return{[`${n.slug}SmsAnalyticsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-sms-analytics`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"period",AttributeType:"S"}],KeySchema:[{AttributeName:"period",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createDeliveryReportsTable(n){return{[`${n.slug}SmsDeliveryReportsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-sms-delivery-reports`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"messageId",AttributeType:"S"}],KeySchema:[{AttributeName:"messageId",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createAnalyticsAggregatorLambda(n){return{[`${n.slug}SmsAnalyticsAggregatorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-sms-analytics-aggregator`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:60,MemorySize:256,Code:{ZipFile:Zt.AnalyticsAggregatorCode},Environment:{Variables:{MESSAGE_LOG_TABLE:n.messageLogTable,ANALYTICS_TABLE:n.analyticsTable}}}}}}}class Xt{static MmsSenderCode=`
6709
6707
  const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');
6710
6708
  const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');
6711
6709
  const { DynamoDBClient, PutItemCommand } = require('@aws-sdk/client-dynamodb');
@@ -6897,8 +6895,8 @@ async function sendFallbackSms(to, message) {
6897
6895
  fallback: true,
6898
6896
  };
6899
6897
  }
6900
- `;static createMediaBucket(n){return{[`${n.slug}MmsMediaBucket`]:{Type:"AWS::S3::Bucket",Properties:{BucketName:`${n.slug}-mms-media`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldMedia",Status:"Enabled",ExpirationInDays:30}]},CorsConfiguration:{CorsRules:[{AllowedOrigins:["*"],AllowedMethods:["GET"],AllowedHeaders:["*"],MaxAge:3600}]}}}}}static createMmsSenderLambda(n){return{[`${n.slug}MmsSenderLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-mms-sender`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:60,MemorySize:512,Code:{ZipFile:zt.MmsSenderCode},Environment:{Variables:{MEDIA_BUCKET:n.mediaBucket,MESSAGE_LOG_TABLE:n.messageLogTable,ORIGINATION_NUMBER:n.originationNumber||""}}}}}}static SupportedMediaTypes={image:["image/jpeg","image/png","image/gif"],video:["video/mp4","video/3gpp"],audio:["audio/mpeg","audio/wav"]};static MediaSizeLimits={image:1048576,video:5242880,audio:1048576}}class Qt{static ChatbotProcessorCode=["const { DynamoDBClient, GetItemCommand, PutItemCommand, UpdateItemCommand, ScanCommand } = require('@aws-sdk/client-dynamodb');","const { BedrockRuntimeClient, InvokeModelCommand } = require('@aws-sdk/client-bedrock-runtime');","const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');","","const dynamodb = new DynamoDBClient({});","const bedrock = new BedrockRuntimeClient({});","const sns = new SNSClient({});","","const SESSIONS_TABLE = process.env.SESSIONS_TABLE;","const RULES_TABLE = process.env.RULES_TABLE;","const CHATBOT_CONFIG = JSON.parse(process.env.CHATBOT_CONFIG || '{}');","","exports.handler = async (event) => {"," console.log('Chatbot event:', JSON.stringify(event, null, 2));"," for (const record of event.Records) {"," try {"," const message = JSON.parse(record.Sns?.Message || record.body || '{}');"," const { originationNumber, messageBody } = message;"," if (!originationNumber || !messageBody) continue;"," const response = await processMessage(originationNumber, messageBody.trim());"," await sendResponse(originationNumber, response);"," } catch (error) {"," console.error('Error:', error);"," }"," }"," return { statusCode: 200 };","};","","async function processMessage(phoneNumber, message) {"," const rules = await getRules();"," const lowerMessage = message.toLowerCase();"," for (const rule of rules) {"," for (const pattern of rule.patterns) {"," if (new RegExp(pattern, 'i').test(lowerMessage)) {"," return rule.response;"," }"," }"," }"," return CHATBOT_CONFIG.fallbackMessage || 'Sorry, I did not understand. Please try again.';","}","","async function getRules() {"," const result = await dynamodb.send(new ScanCommand({ TableName: RULES_TABLE }));"," return (result.Items || []).map(item => ({"," patterns: JSON.parse(item.patterns?.S || '[]'),"," response: item.response?.S || '',"," })).sort((a, b) => (a.priority || 0) - (b.priority || 0));","}","","async function sendResponse(phoneNumber, message) {"," await sns.send(new PublishCommand({"," PhoneNumber: phoneNumber,"," Message: message.substring(0, 1600),"," MessageAttributes: {"," 'AWS.SNS.SMS.SMSType': { DataType: 'String', StringValue: 'Transactional' },"," },"," }));","}"].join(`
6901
- `);static createSessionsTable(n){return{[`${n.slug}ChatbotSessionsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-chatbot-sessions`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createRulesTable(n){return{[`${n.slug}ChatbotRulesTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-chatbot-rules`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}}static createChatbotProcessorLambda(n){return{[`${n.slug}ChatbotProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-chatbot-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Qt.ChatbotProcessorCode},Environment:{Variables:{SESSIONS_TABLE:n.sessionsTable,RULES_TABLE:n.rulesTable,CHATBOT_CONFIG:JSON.stringify(n.chatbotConfig),ORIGINATION_NUMBER:n.originationNumber||""}}}}}}static DefaultRules=[{id:"greeting",priority:1,patterns:["^(hi|hello|hey|howdy)$","^good (morning|afternoon|evening)"],response:"Hello! How can I help you today?"},{id:"help",priority:2,patterns:["^help$","what can you do","how does this work"],response:"I can help with: 1) Account info 2) Support 3) Hours. Reply with a number."},{id:"hours",priority:3,patterns:["hours","open","when are you"],response:"We are open Mon-Fri 9am-5pm EST. Closed weekends."},{id:"thanks",priority:4,patterns:["^(thanks|thank you|thx)"],response:"You're welcome! Is there anything else I can help with?"},{id:"bye",priority:5,patterns:["^(bye|goodbye|quit|exit|stop)$"],response:"Goodbye! Text us anytime if you need help.",action:"end"}]}class Jt{static LinkShortenerCode=`
6898
+ `;static createMediaBucket(n){return{[`${n.slug}MmsMediaBucket`]:{Type:"AWS::S3::Bucket",Properties:{BucketName:`${n.slug}-mms-media`,LifecycleConfiguration:{Rules:[{Id:"DeleteOldMedia",Status:"Enabled",ExpirationInDays:30}]},CorsConfiguration:{CorsRules:[{AllowedOrigins:["*"],AllowedMethods:["GET"],AllowedHeaders:["*"],MaxAge:3600}]}}}}}static createMmsSenderLambda(n){return{[`${n.slug}MmsSenderLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-mms-sender`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:60,MemorySize:512,Code:{ZipFile:Xt.MmsSenderCode},Environment:{Variables:{MEDIA_BUCKET:n.mediaBucket,MESSAGE_LOG_TABLE:n.messageLogTable,ORIGINATION_NUMBER:n.originationNumber||""}}}}}}static SupportedMediaTypes={image:["image/jpeg","image/png","image/gif"],video:["video/mp4","video/3gpp"],audio:["audio/mpeg","audio/wav"]};static MediaSizeLimits={image:1048576,video:5242880,audio:1048576}}class en{static ChatbotProcessorCode=["const { DynamoDBClient, GetItemCommand, PutItemCommand, UpdateItemCommand, ScanCommand } = require('@aws-sdk/client-dynamodb');","const { BedrockRuntimeClient, InvokeModelCommand } = require('@aws-sdk/client-bedrock-runtime');","const { SNSClient, PublishCommand } = require('@aws-sdk/client-sns');","","const dynamodb = new DynamoDBClient({});","const bedrock = new BedrockRuntimeClient({});","const sns = new SNSClient({});","","const SESSIONS_TABLE = process.env.SESSIONS_TABLE;","const RULES_TABLE = process.env.RULES_TABLE;","const CHATBOT_CONFIG = JSON.parse(process.env.CHATBOT_CONFIG || '{}');","","exports.handler = async (event) => {"," console.log('Chatbot event:', JSON.stringify(event, null, 2));"," for (const record of event.Records) {"," try {"," const message = JSON.parse(record.Sns?.Message || record.body || '{}');"," const { originationNumber, messageBody } = message;"," if (!originationNumber || !messageBody) continue;"," const response = await processMessage(originationNumber, messageBody.trim());"," await sendResponse(originationNumber, response);"," } catch (error) {"," console.error('Error:', error);"," }"," }"," return { statusCode: 200 };","};","","async function processMessage(phoneNumber, message) {"," const rules = await getRules();"," const lowerMessage = message.toLowerCase();"," for (const rule of rules) {"," for (const pattern of rule.patterns) {"," if (new RegExp(pattern, 'i').test(lowerMessage)) {"," return rule.response;"," }"," }"," }"," return CHATBOT_CONFIG.fallbackMessage || 'Sorry, I did not understand. Please try again.';","}","","async function getRules() {"," const result = await dynamodb.send(new ScanCommand({ TableName: RULES_TABLE }));"," return (result.Items || []).map(item => ({"," patterns: JSON.parse(item.patterns?.S || '[]'),"," response: item.response?.S || '',"," })).sort((a, b) => (a.priority || 0) - (b.priority || 0));","}","","async function sendResponse(phoneNumber, message) {"," await sns.send(new PublishCommand({"," PhoneNumber: phoneNumber,"," Message: message.substring(0, 1600),"," MessageAttributes: {"," 'AWS.SNS.SMS.SMSType': { DataType: 'String', StringValue: 'Transactional' },"," },"," }));","}"].join(`
6899
+ `);static createSessionsTable(n){return{[`${n.slug}ChatbotSessionsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-chatbot-sessions`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"phoneNumber",AttributeType:"S"}],KeySchema:[{AttributeName:"phoneNumber",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createRulesTable(n){return{[`${n.slug}ChatbotRulesTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-chatbot-rules`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}}static createChatbotProcessorLambda(n){return{[`${n.slug}ChatbotProcessorLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-chatbot-processor`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:en.ChatbotProcessorCode},Environment:{Variables:{SESSIONS_TABLE:n.sessionsTable,RULES_TABLE:n.rulesTable,CHATBOT_CONFIG:JSON.stringify(n.chatbotConfig),ORIGINATION_NUMBER:n.originationNumber||""}}}}}}static DefaultRules=[{id:"greeting",priority:1,patterns:["^(hi|hello|hey|howdy)$","^good (morning|afternoon|evening)"],response:"Hello! How can I help you today?"},{id:"help",priority:2,patterns:["^help$","what can you do","how does this work"],response:"I can help with: 1) Account info 2) Support 3) Hours. Reply with a number."},{id:"hours",priority:3,patterns:["hours","open","when are you"],response:"We are open Mon-Fri 9am-5pm EST. Closed weekends."},{id:"thanks",priority:4,patterns:["^(thanks|thank you|thx)"],response:"You're welcome! Is there anything else I can help with?"},{id:"bye",priority:5,patterns:["^(bye|goodbye|quit|exit|stop)$"],response:"Goodbye! Text us anytime if you need help.",action:"end"}]}class tn{static LinkShortenerCode=`
6902
6900
  const { DynamoDBClient, PutItemCommand, GetItemCommand, UpdateItemCommand } = require('@aws-sdk/client-dynamodb');
6903
6901
  const crypto = require('crypto');
6904
6902
 
@@ -7032,7 +7030,7 @@ function generateShortId() {
7032
7030
  }
7033
7031
  return id;
7034
7032
  }
7035
- `;static createLinksTable(n){return{[`${n.slug}ShortLinksTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-short-links`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createLinkShortenerLambda(n){return{[`${n.slug}LinkShortenerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-link-shortener`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:10,MemorySize:128,Code:{ZipFile:Jt.LinkShortenerCode},Environment:{Variables:{LINKS_TABLE:n.linksTable,SHORT_DOMAIN:n.shortDomain||""}}}}}}static shortenUrlsInMessage(n,i,s){let o=/(https?:\/\/[^\s]+)/g,c=[],u=0;return{message:n.replace(o,(g)=>{let y=`${s}-${u++}`,h=`https://${i}/l/${y}`;return c.push({original:g,short:h,id:y}),h}),links:c}}}class Pe{static AbTestManagerCode=`
7033
+ `;static createLinksTable(n){return{[`${n.slug}ShortLinksTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-short-links`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0}}}}}static createLinkShortenerLambda(n){return{[`${n.slug}LinkShortenerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-link-shortener`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:10,MemorySize:128,Code:{ZipFile:tn.LinkShortenerCode},Environment:{Variables:{LINKS_TABLE:n.linksTable,SHORT_DOMAIN:n.shortDomain||""}}}}}}static shortenUrlsInMessage(n,i,s){let o=/(https?:\/\/[^\s]+)/g,c=[],u=0;return{message:n.replace(o,(g)=>{let y=`${s}-${u++}`,h=`https://${i}/l/${y}`;return c.push({original:g,short:h,id:y}),h}),links:c}}}class Ie{static AbTestManagerCode=`
7036
7034
  const { DynamoDBClient, PutItemCommand, GetItemCommand, UpdateItemCommand, ScanCommand } = require('@aws-sdk/client-dynamodb');
7037
7035
 
7038
7036
  const dynamodb = new DynamoDBClient({});
@@ -7226,7 +7224,7 @@ function unmarshallTest(item) {
7226
7224
 
7227
7225
  return test;
7228
7226
  }
7229
- `;static createAbTestsTable(n){return{[`${n.slug}AbTestsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-ab-tests`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}}static createAbTestManagerLambda(n){return{[`${n.slug}AbTestManagerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-ab-test-manager`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Pe.AbTestManagerCode},Environment:{Variables:{AB_TESTS_TABLE:n.abTestsTable}}}}}}static selectVariant(n,i){let o=Pe.hashString(i+n.id)%100,c=0;for(let u=0;u<n.variants.length;u++)if(c+=n.trafficSplit[u],o<c)return n.variants[u];return n.variants[n.variants.length-1]}static determineWinner(n){if(n.variants.length===0)return null;let i=n.winningCriteria,s=n.variants[0],o=Pe.getMetricValue(s,i);for(let c of n.variants.slice(1)){let u=Pe.getMetricValue(c,i);if(u>o)o=u,s=c}return s}static calculateSignificance(n,i,s){let o=n.stats.sent,c=i.stats.sent;if(o<30||c<30)return 0;let u=Pe.getMetricValue(n,s)/100,d=Pe.getMetricValue(i,s)/100,g=(u*o+d*c)/(o+c),y=Math.sqrt(g*(1-g)*(1/o+1/c));if(y===0)return 0;let h=Math.abs(u-d)/y;if(h>=2.576)return 99;if(h>=1.96)return 95;if(h>=1.645)return 90;if(h>=1.28)return 80;return Math.round(h*30)}static getMetricValue(n,i){switch(i){case"delivery_rate":return n.stats.deliveryRate;case"click_rate":return n.stats.clickRate;case"reply_rate":return n.stats.replyRate;case"conversion_rate":return n.stats.conversionRate;default:return n.stats.deliveryRate}}static hashString(n){let i=0;for(let s=0;s<n.length;s++){let o=n.charCodeAt(s);i=(i<<5)-i+o,i=i&i}return Math.abs(i)}}class Rf{queues=new Map;messageGroups=new Map;deduplicationConfigs=new Map;messages=new Map;queueCounter=0;groupCounter=0;deduplicationCounter=0;messageCounter=0;sequenceCounter=0;createFIFOQueue(n){let i=`fifo-queue-${Date.now()}-${this.queueCounter++}`,s=n.name.endsWith(".fifo")?n.name:`${n.name}.fifo`,{name:o,...c}=n,u={id:i,name:s,queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${s}`,...c};return this.queues.set(i,u),this.createDeduplicationConfig({queueId:i,contentBasedDeduplication:n.contentBasedDeduplication,deduplicationInterval:300}),u}createHighThroughputFIFO(n){return this.createFIFOQueue({name:n.name,contentBasedDeduplication:n.contentBasedDeduplication??!0,deduplicationScope:"messageGroup",fifoThroughputLimit:"perMessageGroupId",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createStandardFIFO(n){return this.createFIFOQueue({name:n.name,contentBasedDeduplication:n.contentBasedDeduplication??!1,deduplicationScope:"queue",fifoThroughputLimit:"perQueue",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createDeduplicationConfig(n){let s={id:`dedup-${Date.now()}-${this.deduplicationCounter++}`,deduplicationHashes:new Map,...n};return this.deduplicationConfigs.set(n.queueId,s),s}sendMessage(n){let i=this.queues.get(n.queueId);if(!i)throw Error(`Queue not found: ${n.queueId}`);let s=this.deduplicationConfigs.get(n.queueId);if(s){let d=n.messageDeduplicationId||(i.contentBasedDeduplication?this.generateHash(n.messageBody):void 0);if(d&&this.isDuplicate(s,d))return null;if(d)s.deduplicationHashes.set(d,new Date)}let o=`msg-${Date.now()}-${this.messageCounter++}`,c=this.generateSequenceNumber(),u={id:o,messageId:o,messageGroupId:n.messageGroupId,messageDeduplicationId:n.messageDeduplicationId,body:n.messageBody,attributes:n.messageAttributes||{},sentTimestamp:new Date,sequenceNumber:c};return this.messages.set(o,u),this.updateMessageGroup(n.queueId,n.messageGroupId),u}isDuplicate(n,i){let s=n.deduplicationHashes.get(i);if(!s)return!1;if((Date.now()-s.getTime())/1000>n.deduplicationInterval)return n.deduplicationHashes.delete(i),!1;return!0}generateHash(n){let i=0;for(let s=0;s<n.length;s++){let o=n.charCodeAt(s);i=(i<<5)-i+o,i=i&i}return Math.abs(i).toString(36)}generateSequenceNumber(){return`${Date.now()}${this.sequenceCounter++}`.padStart(20,"0")}updateMessageGroup(n,i){let s=`${n}-${i}`,o=this.messageGroups.get(s);if(!o)o={id:`group-${Date.now()}-${this.groupCounter++}`,messageGroupId:i,queueId:n,messagesInFlight:0},this.messageGroups.set(s,o);o.messagesInFlight++,o.lastMessageTimestamp=new Date}getMessageGroups(n){return Array.from(this.messageGroups.values()).filter((i)=>i.queueId===n)}getQueue(n){return this.queues.get(n)}listQueues(){return Array.from(this.queues.values())}getMessages(n,i){let s=Array.from(this.messages.values());if(i)s=s.filter((o)=>o.messageGroupId===i);return s.sort((o,c)=>o.sequenceNumber.localeCompare(c.sequenceNumber))}generateFIFOQueueCF(n){return{Type:"AWS::SQS::Queue",Properties:{QueueName:n.name,FifoQueue:!0,ContentBasedDeduplication:n.contentBasedDeduplication,DeduplicationScope:n.deduplicationScope,FifoThroughputLimit:n.fifoThroughputLimit,MessageRetentionPeriod:n.messageRetentionPeriod,VisibilityTimeout:n.visibilityTimeout,ReceiveMessageWaitTimeSeconds:n.receiveMessageWaitTime,...n.deadLetterTargetArn&&{RedrivePolicy:{deadLetterTargetArn:n.deadLetterTargetArn,maxReceiveCount:n.maxReceiveCount||3}}}}}clear(){this.queues.clear(),this.messageGroups.clear(),this.deduplicationConfigs.clear(),this.messages.clear(),this.queueCounter=0,this.groupCounter=0,this.deduplicationCounter=0,this.messageCounter=0,this.sequenceCounter=0}}var TE=new Rf;class Df{monitors=new Map;metrics=new Map;alerts=new Map;reprocessJobs=new Map;monitorCounter=0;metricsCounter=0;alertCounter=0;jobCounter=0;createDLQMonitor(n){let i=`dlq-monitor-${Date.now()}-${this.monitorCounter++}`,s={id:i,...n};return this.monitors.set(i,s),s}createAutomatedMonitor(n){return this.createDLQMonitor({name:n.name,queueUrl:n.queueUrl,sourceQueues:n.sourceQueues,maxReceiveCount:3,alarmThreshold:10,autoReprocess:!0,reprocessStrategy:"scheduled",notificationTopicArn:n.notificationTopicArn})}collectMetrics(n){let s={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:n,timestamp:new Date,approximateNumberOfMessages:Math.floor(Math.random()*100),approximateAgeOfOldestMessage:Math.floor(Math.random()*86400),messagesReceived:Math.floor(Math.random()*50),messagesDeleted:Math.floor(Math.random()*30),messagesReprocessed:Math.floor(Math.random()*20)},o=this.metrics.get(n)||[];return o.push(s),this.metrics.set(n,o),this.checkForAlerts(n,s),s}checkForAlerts(n,i){let s=Array.from(this.monitors.values()).find((c)=>c.queueUrl===n);if(!s)return;if(i.approximateNumberOfMessages>=s.alarmThreshold)this.createAlert({monitorId:s.id,alertType:"threshold_exceeded",severity:"high",message:`DLQ ${s.name} has ${i.approximateNumberOfMessages} messages (threshold: ${s.alarmThreshold})`});let o=3600;if(i.approximateAgeOfOldestMessage>o)this.createAlert({monitorId:s.id,alertType:"old_message",severity:"medium",message:`DLQ ${s.name} has messages older than ${o} seconds`})}createAlert(n){let i=`alert-${Date.now()}-${this.alertCounter++}`,s={id:i,timestamp:new Date,acknowledged:!1,...n};return this.alerts.set(i,s),s}acknowledgeAlert(n){let i=this.alerts.get(n);if(!i)throw Error(`Alert not found: ${n}`);return i.acknowledged=!0,i}createReprocessJob(n){let i=`reprocess-${Date.now()}-${this.jobCounter++}`,s={id:i,queueUrl:n.queueUrl,messageId:n.messageId,attempts:0,status:"pending"};return this.reprocessJobs.set(i,s),s}async executeReprocessJob(n){let i=this.reprocessJobs.get(n);if(!i)throw Error(`Reprocess job not found: ${n}`);i.status="processing",i.startedAt=new Date,i.attempts++,await new Promise((o)=>setTimeout(o,100));let s=Math.random()>0.3;if(i.status=s?"success":"failed",i.completedAt=new Date,!s)i.error="Reprocessing failed - original error still present";return i}async batchReprocess(n){let i=[];for(let s=0;s<n.maxMessages;s++){let o=this.createReprocessJob({queueUrl:n.queueUrl,messageId:`msg-${s}`});await this.executeReprocessJob(o.id),i.push(o)}return i}getDLQStatistics(n,i=24){let s=new Date(Date.now()-i*60*60*1000),o=(this.metrics.get(n)||[]).filter((A)=>A.timestamp>=s);if(o.length===0)return{totalMessages:0,avgAge:0,messagesReceived:0,messagesDeleted:0,messagesReprocessed:0,successRate:0};let c=o[o.length-1],u=o.reduce((A,C)=>A+C.messagesReceived,0),d=o.reduce((A,C)=>A+C.messagesDeleted,0),g=o.reduce((A,C)=>A+C.messagesReprocessed,0),y=o.reduce((A,C)=>A+C.approximateAgeOfOldestMessage,0)/o.length,h=g>0?d/g*100:0;return{totalMessages:c.approximateNumberOfMessages,avgAge:y,messagesReceived:u,messagesDeleted:d,messagesReprocessed:g,successRate:h}}getMonitor(n){return this.monitors.get(n)}listMonitors(){return Array.from(this.monitors.values())}getAlerts(n,i){let s=Array.from(this.alerts.values());if(n)s=s.filter((o)=>o.monitorId===n);if(i!==void 0)s=s.filter((o)=>o.acknowledged===i);return s.sort((o,c)=>c.timestamp.getTime()-o.timestamp.getTime())}getReprocessJobs(n){let i=Array.from(this.reprocessJobs.values());if(n)i=i.filter((s)=>s.queueUrl===n);return i}generateDLQAlarmCF(n){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${n.name}-messages-alarm`,AlarmDescription:`Alert when DLQ ${n.name} exceeds threshold`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Average",Period:300,EvaluationPeriods:1,Threshold:n.alarmThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:n.queueUrl.split("/").pop()}],...n.notificationTopicArn&&{AlarmActions:[n.notificationTopicArn]}}}}clear(){this.monitors.clear(),this.metrics.clear(),this.alerts.clear(),this.reprocessJobs.clear(),this.monitorCounter=0,this.metricsCounter=0,this.alertCounter=0,this.jobCounter=0}}var wE=new Df;class Pf{configs=new Map;jobs=new Map;metrics=new Map;configCounter=0;jobCounter=0;metricsCounter=0;createBatchConfig(n){let i=`batch-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}createHighThroughputConfig(n){return this.createBatchConfig({queueUrl:n.queueUrl,batchSize:10,maxWaitTime:100,parallelProcessors:10,retryAttempts:3,visibilityTimeout:30})}createLowLatencyConfig(n){return this.createBatchConfig({queueUrl:n.queueUrl,batchSize:1,maxWaitTime:0,parallelProcessors:5,retryAttempts:2,visibilityTimeout:10})}createBatchJob(n){let i=`batch-job-${Date.now()}-${this.jobCounter++}`;if(!this.configs.get(n.configId))throw Error(`Batch config not found: ${n.configId}`);let o=[];for(let u=0;u<n.messageCount;u++)o.push({id:`msg-${i}-${u}`,messageId:`${i}-${u}`,body:`Message ${u}`,receiptHandle:`receipt-${i}-${u}`,attributes:{},status:"pending"});let c={id:i,configId:n.configId,messages:o,status:"pending",processedCount:0,failedCount:0};return this.jobs.set(i,c),c}async processBatchJob(n){let i=this.jobs.get(n);if(!i)throw Error(`Batch job not found: ${n}`);let s=this.configs.get(i.configId);if(!s)throw Error(`Batch config not found: ${i.configId}`);i.status="processing",i.startedAt=new Date;let o=this.chunkArray(i.messages,s.batchSize);for(let c of o)await this.processBatch(c,s);return i.processedCount=i.messages.filter((c)=>c.status==="success").length,i.failedCount=i.messages.filter((c)=>c.status==="failed").length,i.status=i.failedCount===0?"completed":"failed",i.completedAt=new Date,this.collectProcessorMetrics(s.id,i),i}async processBatch(n,i){let s=n.map((o)=>this.processMessage(o,i));await Promise.all(s)}async processMessage(n,i){n.status="processing";let s=Date.now();await new Promise((u)=>setTimeout(u,Math.random()*100));let o=Date.now()-s;if(n.processingTime=o,Math.random()>0.1)n.status="success";else n.status="failed",n.error="Processing error"}chunkArray(n,i){let s=[];for(let o=0;o<n.length;o+=i)s.push(n.slice(o,o+i));return s}collectProcessorMetrics(n,i){let s=`metrics-${Date.now()}-${this.metricsCounter++}`,c=i.messages.filter((C)=>C.status==="success").map((C)=>C.processingTime||0).filter((C)=>C>0),u=c.length>0?c.reduce((C,v)=>C+v,0)/c.length:0,d=i.completedAt&&i.startedAt?(i.completedAt.getTime()-i.startedAt.getTime())/1000:1,g=i.processedCount/d,y=i.messages.length>0?i.failedCount/i.messages.length*100:0,h={id:s,configId:n,timestamp:new Date,messagesProcessed:i.processedCount,averageProcessingTime:u,throughput:g,errorRate:y},A=this.metrics.get(n)||[];A.push(h),this.metrics.set(n,A)}getBatchStatistics(n){let i=this.metrics.get(n)||[];if(i.length===0)return{totalJobsProcessed:0,totalMessagesProcessed:0,averageThroughput:0,averageErrorRate:0,averageProcessingTime:0};let s=i.reduce((d,g)=>d+g.messagesProcessed,0),o=i.reduce((d,g)=>d+g.throughput,0)/i.length,c=i.reduce((d,g)=>d+g.errorRate,0)/i.length,u=i.reduce((d,g)=>d+g.averageProcessingTime,0)/i.length;return{totalJobsProcessed:i.length,totalMessagesProcessed:s,averageThroughput:o,averageErrorRate:c,averageProcessingTime:u}}optimizeBatchConfig(n){let i=this.configs.get(n);if(!i)throw Error(`Batch config not found: ${n}`);let s=this.getBatchStatistics(n);if(s.averageErrorRate<5&&i.batchSize<10)i.batchSize=Math.min(10,i.batchSize+1);if(s.averageErrorRate>20&&i.batchSize>1)i.batchSize=Math.max(1,i.batchSize-1);if(s.averageThroughput<5&&i.parallelProcessors<20)i.parallelProcessors++;return i}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getJob(n){return this.jobs.get(n)}listJobs(n){let i=Array.from(this.jobs.values());if(n)i=i.filter((s)=>s.configId===n);return i}generateBatchProcessorCF(n){return{Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:`arn:aws:sqs:us-east-1:123456789012:${n.queueUrl.split("/").pop()}`,FunctionName:"batch-processor-function",BatchSize:n.batchSize,MaximumBatchingWindowInSeconds:n.maxWaitTime/1000,FunctionResponseTypes:["ReportBatchItemFailures"]}}}clear(){this.configs.clear(),this.jobs.clear(),this.metrics.clear(),this.configCounter=0,this.jobCounter=0,this.metricsCounter=0}}var RE=new Pf;class kf{queues=new Map;retentionPolicies=new Map;delayQueues=new Map;purgeOperations=new Map;metrics=new Map;queueCounter=0;retentionCounter=0;delayCounter=0;purgeCounter=0;metricsCounter=0;createQueue(n){let i=`queue-${Date.now()}-${this.queueCounter++}`,s={id:i,purgeInProgress:!1,...n};return this.queues.set(i,s),s}createStandardQueue(n){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${n.queueName}`,queueName:n.queueName,messageRetentionPeriod:(n.messageRetentionDays||4)*24*60*60,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:0})}createLongPollingQueue(n){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${n.queueName}`,queueName:n.queueName,messageRetentionPeriod:345600,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:n.waitTimeSeconds||20})}createRetentionPolicy(n){let i=`retention-${Date.now()}-${this.retentionCounter++}`,s={id:i,...n};this.retentionPolicies.set(i,s);let o=this.queues.get(n.queueId);if(o)o.messageRetentionPeriod=n.retentionPeriod;return s}createShortRetentionPolicy(n){return this.createRetentionPolicy({queueId:n.queueId,retentionPeriod:n.retentionHours*60*60,autoCleanup:!0,archiveExpiredMessages:!1})}createArchivalRetentionPolicy(n){return this.createRetentionPolicy({queueId:n.queueId,retentionPeriod:n.retentionDays*24*60*60,autoCleanup:!0,cleanupSchedule:"cron(0 0 * * ? *)",archiveExpiredMessages:!0,archiveS3Bucket:n.s3Bucket})}createDelayQueue(n){let i=`delay-${Date.now()}-${this.delayCounter++}`,s={id:i,...n};this.delayQueues.set(i,s);let o=Array.from(this.queues.values()).find((c)=>c.queueUrl===n.queueUrl);if(o)o.delaySeconds=n.defaultDelay;return s}createScheduledDelayQueue(n){return this.createDelayQueue({queueUrl:n.queueUrl,defaultDelay:n.delayMinutes*60,perMessageDelay:!1,maxDelay:900})}async purgeQueue(n){let i=this.queues.get(n);if(!i)throw Error(`Queue not found: ${n}`);if(i.purgeInProgress)throw Error("Purge already in progress for this queue");let s=`purge-${Date.now()}-${this.purgeCounter++}`,o={id:s,queueUrl:i.queueUrl,status:"in_progress",startedAt:new Date};return this.purgeOperations.set(s,o),i.purgeInProgress=!0,setTimeout(()=>{o.status="completed",o.completedAt=new Date,o.messagesPurged=Math.floor(Math.random()*1000),i.purgeInProgress=!1},100),o}collectQueueMetrics(n){let s={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:n,timestamp:new Date,approximateNumberOfMessages:Math.floor(Math.random()*1000),approximateNumberOfMessagesNotVisible:Math.floor(Math.random()*100),approximateNumberOfMessagesDelayed:Math.floor(Math.random()*50),oldestMessageAge:Math.floor(Math.random()*86400)},o=this.metrics.get(n)||[];return o.push(s),this.metrics.set(n,o),s}getQueueHealth(n){let i=this.metrics.get(n)||[];if(i.length===0)return{status:"healthy",issues:[],recommendations:[]};let s=i[i.length-1],o=[],c=[],u="healthy";if(s.approximateNumberOfMessages>1e4)u="critical",o.push("Large message backlog detected"),c.push("Increase consumer capacity");else if(s.approximateNumberOfMessages>1000)u="warning",o.push("Growing message backlog"),c.push("Monitor consumer performance");if(s.oldestMessageAge&&s.oldestMessageAge>3600){if(u!=="critical")u="warning";o.push("Old messages in queue"),c.push("Review message processing")}if(s.approximateNumberOfMessagesDelayed>100){if(u!=="critical")u="warning";o.push("High number of delayed messages")}return{status:u,issues:o,recommendations:c}}getQueue(n){return this.queues.get(n)}listQueues(){return Array.from(this.queues.values())}getRetentionPolicy(n){return this.retentionPolicies.get(n)}listRetentionPolicies(){return Array.from(this.retentionPolicies.values())}getPurgeOperations(n){let i=Array.from(this.purgeOperations.values());if(n)i=i.filter((s)=>s.queueUrl===n);return i}generateQueueCF(n){return{Type:"AWS::SQS::Queue",Properties:{QueueName:n.queueName,MessageRetentionPeriod:n.messageRetentionPeriod,DelaySeconds:n.delaySeconds,MaximumMessageSize:n.maximumMessageSize,ReceiveMessageWaitTimeSeconds:n.receiveMessageWaitTime}}}generateCleanupRuleCF(n){return{Type:"AWS::Events::Rule",Properties:{Name:`${n.id}-cleanup`,Description:"Automated queue cleanup",ScheduleExpression:n.cleanupSchedule||"cron(0 0 * * ? *)",State:"ENABLED",Targets:[{Arn:"arn:aws:lambda:us-east-1:123456789012:function:queue-cleanup",Id:n.id,Input:JSON.stringify({queueId:n.queueId,archiveBucket:n.archiveS3Bucket})}]}}}clear(){this.queues.clear(),this.retentionPolicies.clear(),this.delayQueues.clear(),this.purgeOperations.clear(),this.metrics.clear(),this.queueCounter=0,this.retentionCounter=0,this.delayCounter=0,this.purgeCounter=0,this.metricsCounter=0}}var DE=new kf;import{deflateRawSync as Mi}from"node:zlib";var Li=(()=>{let n=[];for(let i=0;i<256;i++){let s=i;for(let o=0;o<8;o++)s=s&1?3988292384^s>>>1:s>>>1;n[i]=s>>>0}return n})();function Oi(n){let i=4294967295;for(let s=0;s<n.length;s++)i=Li[(i^n[s])&255]^i>>>8;return(i^4294967295)>>>0}function $i(n){if(typeof n==="string")return Buffer.from(n,"utf-8");if(Buffer.isBuffer(n))return n;return Buffer.from(n)}function Bi(n){let i=Math.max(1980,n.getFullYear()),s=(n.getHours()<<11|n.getMinutes()<<5|n.getSeconds()>>1)&65535,o=(i-1980<<9|n.getMonth()+1<<5|n.getDate())&65535;return{time:s,date:o}}function it(n){let i=[],s=[],o=0;for(let d of n){let g=$i(d.data),y=Mi(g),h=Oi(g),A=Buffer.from(d.name.replace(/\\/g,"/"),"utf-8"),{time:C,date:v}=Bi(d.date??new Date(0)),T=d.mode??420,R=Buffer.alloc(30+A.length);R.writeUInt32LE(67324752,0),R.writeUInt16LE(20,4),R.writeUInt16LE(0,6),R.writeUInt16LE(8,8),R.writeUInt16LE(C,10),R.writeUInt16LE(v,12),R.writeUInt32LE(h,14),R.writeUInt32LE(y.length,18),R.writeUInt32LE(g.length,22),R.writeUInt16LE(A.length,26),R.writeUInt16LE(0,28),A.copy(R,30);let P=Buffer.alloc(46+A.length);P.writeUInt32LE(33639248,0),P.writeUInt16LE(798,4),P.writeUInt16LE(20,6),P.writeUInt16LE(0,8),P.writeUInt16LE(8,10),P.writeUInt16LE(C,12),P.writeUInt16LE(v,14),P.writeUInt32LE(h,16),P.writeUInt32LE(y.length,20),P.writeUInt32LE(g.length,24),P.writeUInt16LE(A.length,28),P.writeUInt16LE(0,30),P.writeUInt16LE(0,32),P.writeUInt16LE(0,34),P.writeUInt16LE(0,36),P.writeUInt32LE((T&65535)<<16,38),P.writeUInt32LE(o,42),A.copy(P,46),i.push(R,y),s.push(P),o+=R.length+y.length}let c=Buffer.concat(s),u=Buffer.alloc(22);return u.writeUInt32LE(101010256,0),u.writeUInt16LE(0,4),u.writeUInt16LE(0,6),u.writeUInt16LE(n.length,8),u.writeUInt16LE(n.length,10),u.writeUInt32LE(c.length,12),u.writeUInt32LE(o,16),u.writeUInt16LE(0,20),Buffer.concat([...i,c,u])}function Nf(n){let i=n.adapterImport??"./adapter",s=n.entryImport.replace(/\\/g,"/");return`// Generated by ts-cloud — serverless app bootstrap. Do not edit.
7227
+ `;static createAbTestsTable(n){return{[`${n.slug}AbTestsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${n.slug}-ab-tests`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}}static createAbTestManagerLambda(n){return{[`${n.slug}AbTestManagerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${n.slug}-ab-test-manager`,Runtime:"nodejs20.x",Handler:"index.handler",Role:n.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:Ie.AbTestManagerCode},Environment:{Variables:{AB_TESTS_TABLE:n.abTestsTable}}}}}}static selectVariant(n,i){let o=Ie.hashString(i+n.id)%100,c=0;for(let u=0;u<n.variants.length;u++)if(c+=n.trafficSplit[u],o<c)return n.variants[u];return n.variants[n.variants.length-1]}static determineWinner(n){if(n.variants.length===0)return null;let i=n.winningCriteria,s=n.variants[0],o=Ie.getMetricValue(s,i);for(let c of n.variants.slice(1)){let u=Ie.getMetricValue(c,i);if(u>o)o=u,s=c}return s}static calculateSignificance(n,i,s){let o=n.stats.sent,c=i.stats.sent;if(o<30||c<30)return 0;let u=Ie.getMetricValue(n,s)/100,d=Ie.getMetricValue(i,s)/100,g=(u*o+d*c)/(o+c),y=Math.sqrt(g*(1-g)*(1/o+1/c));if(y===0)return 0;let h=Math.abs(u-d)/y;if(h>=2.576)return 99;if(h>=1.96)return 95;if(h>=1.645)return 90;if(h>=1.28)return 80;return Math.round(h*30)}static getMetricValue(n,i){switch(i){case"delivery_rate":return n.stats.deliveryRate;case"click_rate":return n.stats.clickRate;case"reply_rate":return n.stats.replyRate;case"conversion_rate":return n.stats.conversionRate;default:return n.stats.deliveryRate}}static hashString(n){let i=0;for(let s=0;s<n.length;s++){let o=n.charCodeAt(s);i=(i<<5)-i+o,i=i&i}return Math.abs(i)}}class $f{queues=new Map;messageGroups=new Map;deduplicationConfigs=new Map;messages=new Map;queueCounter=0;groupCounter=0;deduplicationCounter=0;messageCounter=0;sequenceCounter=0;createFIFOQueue(n){let i=`fifo-queue-${Date.now()}-${this.queueCounter++}`,s=n.name.endsWith(".fifo")?n.name:`${n.name}.fifo`,{name:o,...c}=n,u={id:i,name:s,queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${s}`,...c};return this.queues.set(i,u),this.createDeduplicationConfig({queueId:i,contentBasedDeduplication:n.contentBasedDeduplication,deduplicationInterval:300}),u}createHighThroughputFIFO(n){return this.createFIFOQueue({name:n.name,contentBasedDeduplication:n.contentBasedDeduplication??!0,deduplicationScope:"messageGroup",fifoThroughputLimit:"perMessageGroupId",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createStandardFIFO(n){return this.createFIFOQueue({name:n.name,contentBasedDeduplication:n.contentBasedDeduplication??!1,deduplicationScope:"queue",fifoThroughputLimit:"perQueue",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createDeduplicationConfig(n){let s={id:`dedup-${Date.now()}-${this.deduplicationCounter++}`,deduplicationHashes:new Map,...n};return this.deduplicationConfigs.set(n.queueId,s),s}sendMessage(n){let i=this.queues.get(n.queueId);if(!i)throw Error(`Queue not found: ${n.queueId}`);let s=this.deduplicationConfigs.get(n.queueId);if(s){let d=n.messageDeduplicationId||(i.contentBasedDeduplication?this.generateHash(n.messageBody):void 0);if(d&&this.isDuplicate(s,d))return null;if(d)s.deduplicationHashes.set(d,new Date)}let o=`msg-${Date.now()}-${this.messageCounter++}`,c=this.generateSequenceNumber(),u={id:o,messageId:o,messageGroupId:n.messageGroupId,messageDeduplicationId:n.messageDeduplicationId,body:n.messageBody,attributes:n.messageAttributes||{},sentTimestamp:new Date,sequenceNumber:c};return this.messages.set(o,u),this.updateMessageGroup(n.queueId,n.messageGroupId),u}isDuplicate(n,i){let s=n.deduplicationHashes.get(i);if(!s)return!1;if((Date.now()-s.getTime())/1000>n.deduplicationInterval)return n.deduplicationHashes.delete(i),!1;return!0}generateHash(n){let i=0;for(let s=0;s<n.length;s++){let o=n.charCodeAt(s);i=(i<<5)-i+o,i=i&i}return Math.abs(i).toString(36)}generateSequenceNumber(){return`${Date.now()}${this.sequenceCounter++}`.padStart(20,"0")}updateMessageGroup(n,i){let s=`${n}-${i}`,o=this.messageGroups.get(s);if(!o)o={id:`group-${Date.now()}-${this.groupCounter++}`,messageGroupId:i,queueId:n,messagesInFlight:0},this.messageGroups.set(s,o);o.messagesInFlight++,o.lastMessageTimestamp=new Date}getMessageGroups(n){return Array.from(this.messageGroups.values()).filter((i)=>i.queueId===n)}getQueue(n){return this.queues.get(n)}listQueues(){return Array.from(this.queues.values())}getMessages(n,i){let s=Array.from(this.messages.values());if(i)s=s.filter((o)=>o.messageGroupId===i);return s.sort((o,c)=>o.sequenceNumber.localeCompare(c.sequenceNumber))}generateFIFOQueueCF(n){return{Type:"AWS::SQS::Queue",Properties:{QueueName:n.name,FifoQueue:!0,ContentBasedDeduplication:n.contentBasedDeduplication,DeduplicationScope:n.deduplicationScope,FifoThroughputLimit:n.fifoThroughputLimit,MessageRetentionPeriod:n.messageRetentionPeriod,VisibilityTimeout:n.visibilityTimeout,ReceiveMessageWaitTimeSeconds:n.receiveMessageWaitTime,...n.deadLetterTargetArn&&{RedrivePolicy:{deadLetterTargetArn:n.deadLetterTargetArn,maxReceiveCount:n.maxReceiveCount||3}}}}}clear(){this.queues.clear(),this.messageGroups.clear(),this.deduplicationConfigs.clear(),this.messages.clear(),this.queueCounter=0,this.groupCounter=0,this.deduplicationCounter=0,this.messageCounter=0,this.sequenceCounter=0}}var ME=new $f;class Mf{monitors=new Map;metrics=new Map;alerts=new Map;reprocessJobs=new Map;monitorCounter=0;metricsCounter=0;alertCounter=0;jobCounter=0;createDLQMonitor(n){let i=`dlq-monitor-${Date.now()}-${this.monitorCounter++}`,s={id:i,...n};return this.monitors.set(i,s),s}createAutomatedMonitor(n){return this.createDLQMonitor({name:n.name,queueUrl:n.queueUrl,sourceQueues:n.sourceQueues,maxReceiveCount:3,alarmThreshold:10,autoReprocess:!0,reprocessStrategy:"scheduled",notificationTopicArn:n.notificationTopicArn})}collectMetrics(n){let s={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:n,timestamp:new Date,approximateNumberOfMessages:Math.floor(Math.random()*100),approximateAgeOfOldestMessage:Math.floor(Math.random()*86400),messagesReceived:Math.floor(Math.random()*50),messagesDeleted:Math.floor(Math.random()*30),messagesReprocessed:Math.floor(Math.random()*20)},o=this.metrics.get(n)||[];return o.push(s),this.metrics.set(n,o),this.checkForAlerts(n,s),s}checkForAlerts(n,i){let s=Array.from(this.monitors.values()).find((c)=>c.queueUrl===n);if(!s)return;if(i.approximateNumberOfMessages>=s.alarmThreshold)this.createAlert({monitorId:s.id,alertType:"threshold_exceeded",severity:"high",message:`DLQ ${s.name} has ${i.approximateNumberOfMessages} messages (threshold: ${s.alarmThreshold})`});let o=3600;if(i.approximateAgeOfOldestMessage>o)this.createAlert({monitorId:s.id,alertType:"old_message",severity:"medium",message:`DLQ ${s.name} has messages older than ${o} seconds`})}createAlert(n){let i=`alert-${Date.now()}-${this.alertCounter++}`,s={id:i,timestamp:new Date,acknowledged:!1,...n};return this.alerts.set(i,s),s}acknowledgeAlert(n){let i=this.alerts.get(n);if(!i)throw Error(`Alert not found: ${n}`);return i.acknowledged=!0,i}createReprocessJob(n){let i=`reprocess-${Date.now()}-${this.jobCounter++}`,s={id:i,queueUrl:n.queueUrl,messageId:n.messageId,attempts:0,status:"pending"};return this.reprocessJobs.set(i,s),s}async executeReprocessJob(n){let i=this.reprocessJobs.get(n);if(!i)throw Error(`Reprocess job not found: ${n}`);i.status="processing",i.startedAt=new Date,i.attempts++,await new Promise((o)=>setTimeout(o,100));let s=Math.random()>0.3;if(i.status=s?"success":"failed",i.completedAt=new Date,!s)i.error="Reprocessing failed - original error still present";return i}async batchReprocess(n){let i=[];for(let s=0;s<n.maxMessages;s++){let o=this.createReprocessJob({queueUrl:n.queueUrl,messageId:`msg-${s}`});await this.executeReprocessJob(o.id),i.push(o)}return i}getDLQStatistics(n,i=24){let s=new Date(Date.now()-i*60*60*1000),o=(this.metrics.get(n)||[]).filter((A)=>A.timestamp>=s);if(o.length===0)return{totalMessages:0,avgAge:0,messagesReceived:0,messagesDeleted:0,messagesReprocessed:0,successRate:0};let c=o[o.length-1],u=o.reduce((A,C)=>A+C.messagesReceived,0),d=o.reduce((A,C)=>A+C.messagesDeleted,0),g=o.reduce((A,C)=>A+C.messagesReprocessed,0),y=o.reduce((A,C)=>A+C.approximateAgeOfOldestMessage,0)/o.length,h=g>0?d/g*100:0;return{totalMessages:c.approximateNumberOfMessages,avgAge:y,messagesReceived:u,messagesDeleted:d,messagesReprocessed:g,successRate:h}}getMonitor(n){return this.monitors.get(n)}listMonitors(){return Array.from(this.monitors.values())}getAlerts(n,i){let s=Array.from(this.alerts.values());if(n)s=s.filter((o)=>o.monitorId===n);if(i!==void 0)s=s.filter((o)=>o.acknowledged===i);return s.sort((o,c)=>c.timestamp.getTime()-o.timestamp.getTime())}getReprocessJobs(n){let i=Array.from(this.reprocessJobs.values());if(n)i=i.filter((s)=>s.queueUrl===n);return i}generateDLQAlarmCF(n){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${n.name}-messages-alarm`,AlarmDescription:`Alert when DLQ ${n.name} exceeds threshold`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Average",Period:300,EvaluationPeriods:1,Threshold:n.alarmThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:n.queueUrl.split("/").pop()}],...n.notificationTopicArn&&{AlarmActions:[n.notificationTopicArn]}}}}clear(){this.monitors.clear(),this.metrics.clear(),this.alerts.clear(),this.reprocessJobs.clear(),this.monitorCounter=0,this.metricsCounter=0,this.alertCounter=0,this.jobCounter=0}}var FE=new Mf;class Ff{configs=new Map;jobs=new Map;metrics=new Map;configCounter=0;jobCounter=0;metricsCounter=0;createBatchConfig(n){let i=`batch-config-${Date.now()}-${this.configCounter++}`,s={id:i,...n};return this.configs.set(i,s),s}createHighThroughputConfig(n){return this.createBatchConfig({queueUrl:n.queueUrl,batchSize:10,maxWaitTime:100,parallelProcessors:10,retryAttempts:3,visibilityTimeout:30})}createLowLatencyConfig(n){return this.createBatchConfig({queueUrl:n.queueUrl,batchSize:1,maxWaitTime:0,parallelProcessors:5,retryAttempts:2,visibilityTimeout:10})}createBatchJob(n){let i=`batch-job-${Date.now()}-${this.jobCounter++}`;if(!this.configs.get(n.configId))throw Error(`Batch config not found: ${n.configId}`);let o=[];for(let u=0;u<n.messageCount;u++)o.push({id:`msg-${i}-${u}`,messageId:`${i}-${u}`,body:`Message ${u}`,receiptHandle:`receipt-${i}-${u}`,attributes:{},status:"pending"});let c={id:i,configId:n.configId,messages:o,status:"pending",processedCount:0,failedCount:0};return this.jobs.set(i,c),c}async processBatchJob(n){let i=this.jobs.get(n);if(!i)throw Error(`Batch job not found: ${n}`);let s=this.configs.get(i.configId);if(!s)throw Error(`Batch config not found: ${i.configId}`);i.status="processing",i.startedAt=new Date;let o=this.chunkArray(i.messages,s.batchSize);for(let c of o)await this.processBatch(c,s);return i.processedCount=i.messages.filter((c)=>c.status==="success").length,i.failedCount=i.messages.filter((c)=>c.status==="failed").length,i.status=i.failedCount===0?"completed":"failed",i.completedAt=new Date,this.collectProcessorMetrics(s.id,i),i}async processBatch(n,i){let s=n.map((o)=>this.processMessage(o,i));await Promise.all(s)}async processMessage(n,i){n.status="processing";let s=Date.now();await new Promise((u)=>setTimeout(u,Math.random()*100));let o=Date.now()-s;if(n.processingTime=o,Math.random()>0.1)n.status="success";else n.status="failed",n.error="Processing error"}chunkArray(n,i){let s=[];for(let o=0;o<n.length;o+=i)s.push(n.slice(o,o+i));return s}collectProcessorMetrics(n,i){let s=`metrics-${Date.now()}-${this.metricsCounter++}`,c=i.messages.filter((C)=>C.status==="success").map((C)=>C.processingTime||0).filter((C)=>C>0),u=c.length>0?c.reduce((C,v)=>C+v,0)/c.length:0,d=i.completedAt&&i.startedAt?(i.completedAt.getTime()-i.startedAt.getTime())/1000:1,g=i.processedCount/d,y=i.messages.length>0?i.failedCount/i.messages.length*100:0,h={id:s,configId:n,timestamp:new Date,messagesProcessed:i.processedCount,averageProcessingTime:u,throughput:g,errorRate:y},A=this.metrics.get(n)||[];A.push(h),this.metrics.set(n,A)}getBatchStatistics(n){let i=this.metrics.get(n)||[];if(i.length===0)return{totalJobsProcessed:0,totalMessagesProcessed:0,averageThroughput:0,averageErrorRate:0,averageProcessingTime:0};let s=i.reduce((d,g)=>d+g.messagesProcessed,0),o=i.reduce((d,g)=>d+g.throughput,0)/i.length,c=i.reduce((d,g)=>d+g.errorRate,0)/i.length,u=i.reduce((d,g)=>d+g.averageProcessingTime,0)/i.length;return{totalJobsProcessed:i.length,totalMessagesProcessed:s,averageThroughput:o,averageErrorRate:c,averageProcessingTime:u}}optimizeBatchConfig(n){let i=this.configs.get(n);if(!i)throw Error(`Batch config not found: ${n}`);let s=this.getBatchStatistics(n);if(s.averageErrorRate<5&&i.batchSize<10)i.batchSize=Math.min(10,i.batchSize+1);if(s.averageErrorRate>20&&i.batchSize>1)i.batchSize=Math.max(1,i.batchSize-1);if(s.averageThroughput<5&&i.parallelProcessors<20)i.parallelProcessors++;return i}getConfig(n){return this.configs.get(n)}listConfigs(){return Array.from(this.configs.values())}getJob(n){return this.jobs.get(n)}listJobs(n){let i=Array.from(this.jobs.values());if(n)i=i.filter((s)=>s.configId===n);return i}generateBatchProcessorCF(n){return{Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:`arn:aws:sqs:us-east-1:123456789012:${n.queueUrl.split("/").pop()}`,FunctionName:"batch-processor-function",BatchSize:n.batchSize,MaximumBatchingWindowInSeconds:n.maxWaitTime/1000,FunctionResponseTypes:["ReportBatchItemFailures"]}}}clear(){this.configs.clear(),this.jobs.clear(),this.metrics.clear(),this.configCounter=0,this.jobCounter=0,this.metricsCounter=0}}var UE=new Ff;class Uf{queues=new Map;retentionPolicies=new Map;delayQueues=new Map;purgeOperations=new Map;metrics=new Map;queueCounter=0;retentionCounter=0;delayCounter=0;purgeCounter=0;metricsCounter=0;createQueue(n){let i=`queue-${Date.now()}-${this.queueCounter++}`,s={id:i,purgeInProgress:!1,...n};return this.queues.set(i,s),s}createStandardQueue(n){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${n.queueName}`,queueName:n.queueName,messageRetentionPeriod:(n.messageRetentionDays||4)*24*60*60,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:0})}createLongPollingQueue(n){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${n.queueName}`,queueName:n.queueName,messageRetentionPeriod:345600,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:n.waitTimeSeconds||20})}createRetentionPolicy(n){let i=`retention-${Date.now()}-${this.retentionCounter++}`,s={id:i,...n};this.retentionPolicies.set(i,s);let o=this.queues.get(n.queueId);if(o)o.messageRetentionPeriod=n.retentionPeriod;return s}createShortRetentionPolicy(n){return this.createRetentionPolicy({queueId:n.queueId,retentionPeriod:n.retentionHours*60*60,autoCleanup:!0,archiveExpiredMessages:!1})}createArchivalRetentionPolicy(n){return this.createRetentionPolicy({queueId:n.queueId,retentionPeriod:n.retentionDays*24*60*60,autoCleanup:!0,cleanupSchedule:"cron(0 0 * * ? *)",archiveExpiredMessages:!0,archiveS3Bucket:n.s3Bucket})}createDelayQueue(n){let i=`delay-${Date.now()}-${this.delayCounter++}`,s={id:i,...n};this.delayQueues.set(i,s);let o=Array.from(this.queues.values()).find((c)=>c.queueUrl===n.queueUrl);if(o)o.delaySeconds=n.defaultDelay;return s}createScheduledDelayQueue(n){return this.createDelayQueue({queueUrl:n.queueUrl,defaultDelay:n.delayMinutes*60,perMessageDelay:!1,maxDelay:900})}async purgeQueue(n){let i=this.queues.get(n);if(!i)throw Error(`Queue not found: ${n}`);if(i.purgeInProgress)throw Error("Purge already in progress for this queue");let s=`purge-${Date.now()}-${this.purgeCounter++}`,o={id:s,queueUrl:i.queueUrl,status:"in_progress",startedAt:new Date};return this.purgeOperations.set(s,o),i.purgeInProgress=!0,setTimeout(()=>{o.status="completed",o.completedAt=new Date,o.messagesPurged=Math.floor(Math.random()*1000),i.purgeInProgress=!1},100),o}collectQueueMetrics(n){let s={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:n,timestamp:new Date,approximateNumberOfMessages:Math.floor(Math.random()*1000),approximateNumberOfMessagesNotVisible:Math.floor(Math.random()*100),approximateNumberOfMessagesDelayed:Math.floor(Math.random()*50),oldestMessageAge:Math.floor(Math.random()*86400)},o=this.metrics.get(n)||[];return o.push(s),this.metrics.set(n,o),s}getQueueHealth(n){let i=this.metrics.get(n)||[];if(i.length===0)return{status:"healthy",issues:[],recommendations:[]};let s=i[i.length-1],o=[],c=[],u="healthy";if(s.approximateNumberOfMessages>1e4)u="critical",o.push("Large message backlog detected"),c.push("Increase consumer capacity");else if(s.approximateNumberOfMessages>1000)u="warning",o.push("Growing message backlog"),c.push("Monitor consumer performance");if(s.oldestMessageAge&&s.oldestMessageAge>3600){if(u!=="critical")u="warning";o.push("Old messages in queue"),c.push("Review message processing")}if(s.approximateNumberOfMessagesDelayed>100){if(u!=="critical")u="warning";o.push("High number of delayed messages")}return{status:u,issues:o,recommendations:c}}getQueue(n){return this.queues.get(n)}listQueues(){return Array.from(this.queues.values())}getRetentionPolicy(n){return this.retentionPolicies.get(n)}listRetentionPolicies(){return Array.from(this.retentionPolicies.values())}getPurgeOperations(n){let i=Array.from(this.purgeOperations.values());if(n)i=i.filter((s)=>s.queueUrl===n);return i}generateQueueCF(n){return{Type:"AWS::SQS::Queue",Properties:{QueueName:n.queueName,MessageRetentionPeriod:n.messageRetentionPeriod,DelaySeconds:n.delaySeconds,MaximumMessageSize:n.maximumMessageSize,ReceiveMessageWaitTimeSeconds:n.receiveMessageWaitTime}}}generateCleanupRuleCF(n){return{Type:"AWS::Events::Rule",Properties:{Name:`${n.id}-cleanup`,Description:"Automated queue cleanup",ScheduleExpression:n.cleanupSchedule||"cron(0 0 * * ? *)",State:"ENABLED",Targets:[{Arn:"arn:aws:lambda:us-east-1:123456789012:function:queue-cleanup",Id:n.id,Input:JSON.stringify({queueId:n.queueId,archiveBucket:n.archiveS3Bucket})}]}}}clear(){this.queues.clear(),this.retentionPolicies.clear(),this.delayQueues.clear(),this.purgeOperations.clear(),this.metrics.clear(),this.queueCounter=0,this.retentionCounter=0,this.delayCounter=0,this.purgeCounter=0,this.metricsCounter=0}}var QE=new Uf;import{deflateRawSync as ys}from"node:zlib";var fs=(()=>{let n=[];for(let i=0;i<256;i++){let s=i;for(let o=0;o<8;o++)s=s&1?3988292384^s>>>1:s>>>1;n[i]=s>>>0}return n})();function hs(n){let i=4294967295;for(let s=0;s<n.length;s++)i=fs[(i^n[s])&255]^i>>>8;return(i^4294967295)>>>0}function bs(n){if(typeof n==="string")return Buffer.from(n,"utf-8");if(Buffer.isBuffer(n))return n;return Buffer.from(n)}function Ss(n){let i=Math.max(1980,n.getFullYear()),s=(n.getHours()<<11|n.getMinutes()<<5|n.getSeconds()>>1)&65535,o=(i-1980<<9|n.getMonth()+1<<5|n.getDate())&65535;return{time:s,date:o}}function ot(n){let i=[],s=[],o=0;for(let d of n){let g=bs(d.data),y=ys(g),h=hs(g),A=Buffer.from(d.name.replace(/\\/g,"/"),"utf-8"),{time:C,date:v}=Ss(d.date??new Date(0)),T=d.mode??420,R=Buffer.alloc(30+A.length);R.writeUInt32LE(67324752,0),R.writeUInt16LE(20,4),R.writeUInt16LE(0,6),R.writeUInt16LE(8,8),R.writeUInt16LE(C,10),R.writeUInt16LE(v,12),R.writeUInt32LE(h,14),R.writeUInt32LE(y.length,18),R.writeUInt32LE(g.length,22),R.writeUInt16LE(A.length,26),R.writeUInt16LE(0,28),A.copy(R,30);let P=Buffer.alloc(46+A.length);P.writeUInt32LE(33639248,0),P.writeUInt16LE(798,4),P.writeUInt16LE(20,6),P.writeUInt16LE(0,8),P.writeUInt16LE(8,10),P.writeUInt16LE(C,12),P.writeUInt16LE(v,14),P.writeUInt32LE(h,16),P.writeUInt32LE(y.length,20),P.writeUInt32LE(g.length,24),P.writeUInt16LE(A.length,28),P.writeUInt16LE(0,30),P.writeUInt16LE(0,32),P.writeUInt16LE(0,34),P.writeUInt16LE(0,36),P.writeUInt32LE((T&65535)<<16,38),P.writeUInt32LE(o,42),A.copy(P,46),i.push(R,y),s.push(P),o+=R.length+y.length}let c=Buffer.concat(s),u=Buffer.alloc(22);return u.writeUInt32LE(101010256,0),u.writeUInt16LE(0,4),u.writeUInt16LE(0,6),u.writeUInt16LE(n.length,8),u.writeUInt16LE(n.length,10),u.writeUInt32LE(c.length,12),u.writeUInt32LE(o,16),u.writeUInt16LE(0,20),Buffer.concat([...i,c,u])}function Qf(n){let i=n.adapterImport??"./adapter",s=n.entryImport.replace(/\\/g,"/");return`// Generated by ts-cloud — serverless app bootstrap. Do not edit.
7230
7228
  import * as __userModule from ${JSON.stringify(s)}
7231
7229
  import { resolveApp, createHandlers } from ${JSON.stringify(i)}
7232
7230
 
@@ -7236,9 +7234,9 @@ const __handlers = createHandlers(__app)
7236
7234
  export const http = __handlers.http
7237
7235
  export const queue = __handlers.queue
7238
7236
  export const cli = __handlers.cli
7239
- `}import{execSync as Fi}from"node:child_process";import{createHash as Gi}from"node:crypto";import{cpSync as _i,mkdtempSync as Wi,rmSync as Vi,writeFileSync as Ui}from"node:fs";import{tmpdir as Hi}from"node:os";import{dirname as ji,isAbsolute as Ki,join as Fe,resolve as qi}from"node:path";import{fileURLToPath as zi}from"node:url";var Qi=["adapter.ts","recursion.ts","auto-recursion.ts"];function ss(){return Fe(ji(zi(import.meta.url)),"runtime")}function uS(n,i,s){for(let o of n??[])s?.(`build: ${o}`),Fi(o,{stdio:"inherit",cwd:i})}function Wo(n){return Gi("sha256").update(n).digest("hex")}function $l(n,i,s){return`deployments/${n}/${i}/${s}.zip`}async function mn(n){let i=qi(n.projectRoot??process.cwd()),{app:s}=n;if(!n.skipBuild)uS(s.build,i,n.onStep);let o=s.entry;if(!o)throw Error("serverless app: `entry` is required to package a Node/Bun application");let c=Ki(o)?o:Fe(i,o),u=Wi(Fe(Hi(),"tscloud-pkg-"));try{for(let v of Qi)_i(Fe(ss(),v),Fe(u,v));let d=Fe(u,"bootstrap.ts");Ui(d,Nf({entryImport:c,adapterImport:"./adapter"})),n.onStep?.("bundling application");let g=await Bun.build({entrypoints:[d],target:s.kind==="bun"?"bun":"node",format:"esm",minify:!1,sourcemap:"none"});if(!g.success){let v=g.logs.map((T)=>String(T)).join(`
7237
+ `}import{execSync as As}from"node:child_process";import{createHash as Cs}from"node:crypto";import{cpSync as vs,mkdtempSync as Ts,rmSync as Rs,writeFileSync as Ps}from"node:fs";import{tmpdir as Es}from"node:os";import{dirname as ws,isAbsolute as Is,join as We,resolve as Ds}from"node:path";import{fileURLToPath as Ns}from"node:url";var xs=["adapter.ts","recursion.ts","auto-recursion.ts"];function ks(){return We(ws(Ns(import.meta.url)),"runtime")}function ES(n,i,s){for(let o of n??[])s?.(`build: ${o}`),As(o,{stdio:"inherit",cwd:i})}function ia(n){return Cs("sha256").update(n).digest("hex")}function jl(n,i,s){return`deployments/${n}/${i}/${s}.zip`}async function hn(n){let i=Ds(n.projectRoot??process.cwd()),{app:s}=n;if(!n.skipBuild)ES(s.build,i,n.onStep);let o=s.entry;if(!o)throw Error("serverless app: `entry` is required to package a Node/Bun application");let c=Is(o)?o:We(i,o),u=Ts(We(Es(),"tscloud-pkg-"));try{for(let v of xs)vs(We(ks(),v),We(u,v));let d=We(u,"bootstrap.ts");Ps(d,Qf({entryImport:c,adapterImport:"./adapter"})),n.onStep?.("bundling application");let g=await Bun.build({entrypoints:[d],target:s.kind==="bun"?"bun":"node",format:"esm",minify:!1,sourcemap:"none"});if(!g.success){let v=g.logs.map((T)=>String(T)).join(`
7240
7238
  `);throw Error(`serverless app bundle failed:
7241
- ${v}`)}let y=g.outputs[0],h=Buffer.from(await y.arrayBuffer()),A="index",C=it([{name:`${A}.mjs`,data:h}]);return{zip:C,bundle:h,sha256:Wo(C),handlerFile:A,handlers:{http:s.handlers?.http??`${A}.http`,queue:s.handlers?.queue??`${A}.queue`,cli:s.handlers?.cli??`${A}.cli`},bundleBytes:h.length}}finally{Vi(u,{recursive:!0,force:!0})}}var gS=["18","20","22"];function as(n){if(!n)return"22";let i=String(n).match(/(\d+)/);return i?i[1]:"22"}function ns(n){let i=n.kind??"node";if(i==="php")return{lambdaRuntime:"provided.al2023",kind:"php",version:n.phpVersion??"8.3",usesLayer:!0,layerKind:"php",layerEnvVar:"TSCLOUD_PHP_LAYER_ARN"};if(i==="bun")return{lambdaRuntime:"provided.al2023",kind:"bun",version:n.runtimeVersion??"latest",usesLayer:!0,layerKind:"bun",layerEnvVar:"TSCLOUD_BUN_LAYER_ARN"};let s=as(n.runtimeVersion);if(n.runtime!=="provided.al2023"&&gS.includes(s))return{lambdaRuntime:n.runtime&&n.runtime.startsWith("nodejs")?n.runtime:`nodejs${s}.x`,kind:"node",version:s,usesLayer:!1};return{lambdaRuntime:"provided.al2023",kind:"node",version:s,usesLayer:!0,layerKind:"node",layerEnvVar:"TSCLOUD_NODE_LAYER_ARN"}}function Ar(n,i,s){if(n.queues===!1)return[];if(n.queues===void 0||n.queues===!0)return[{name:`${i}-${s}-default`}];return n.queues.map((o)=>{if(typeof o==="string")return{name:`${i}-${s}-${o}`};let[c,u]=Object.entries(o)[0];return{name:`${i}-${s}-${c}`,concurrency:u}})}function Ml(n,i,s){return Ar(n,i,s).map((o)=>o.name)}function Fl(n){let{app:i,environment:s,handlers:o}=n,c=n.config.project.slug,u=ns(i).lambdaRuntime,d=i.architecture??"x86_64",g=n.config.project.region,y={http:`${c}-${s}-http`,queue:`${c}-${s}-queue`,cli:`${c}-${s}-cli`};if(i.gatewayVersion===1)throw Error("serverless app: `gatewayVersion: 1` (REST API) is not supported — ts-cloud uses API Gateway HTTP API (v2). Remove `gatewayVersion` or set it to 2.");let h=Ar(i,c,s),A=h.map((G)=>G.name),C=A.length>0,v=i.logRetention??14,T=i.packaging==="image";if(T&&i.lambdaInsights)throw Error("serverless app: `lambdaInsights` layer attachment is only supported for zip packaging. Container images must install the Lambda Insights extension in the image.");let R=(i.scheduler??"on")!=="off",P=(i.cache?.driver??"dynamodb")==="dynamodb",I=Boolean(i.assets),M=Xi(c,s),L=i.tmpStorage??512,N={},O={},B=[{PolicyName:"tscloud-serverless-app",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:e.sub("arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*")},{Effect:"Allow",Action:["lambda:InvokeFunction"],Resource:e.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${c}-${s}-*`)},{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameter","ssm:GetParameters","ssm:GetParametersByPath"],Resource:[e.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${c}/${s}/*`),e.sub(`arn:aws:ssm:\${AWS::Region}:\${AWS::AccountId}:parameter/${c}/${s}/*`)]},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[e.sub(`arn:aws:s3:::${M}`),e.sub(`arn:aws:s3:::${M}/*`),...i.storage?.bucket?[e.sub(`arn:aws:s3:::${i.storage.bucket}`),e.sub(`arn:aws:s3:::${i.storage.bucket}/*`)]:[]]}]}}];if(C)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["sqs:SendMessage","sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes","sqs:GetQueueUrl"],Resource:e.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${c}-${s}-*`)});if(P)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:BatchGetItem","dynamodb:BatchWriteItem"],Resource:e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${c}-${s}-cache*`)});let F=["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"];if(i.vpc?.subnets?.length)F.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");if(i.lambdaInsights)F.push("arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy");N.AppRole={Type:"AWS::IAM::Role",Properties:{RoleName:`${c}-${s}-app-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:F,Policies:B}};let U=(G)=>({TSCLOUD_LAMBDA_MODE:G,TSCLOUD_ENV:s,...i.octane?{TSCLOUD_OCTANE:"1"}:{},...i.scheduler==="sub-minute"?{TSCLOUD_SCHEDULER:"sub-minute"}:{},...P?{TSCLOUD_CACHE_TABLE:`${c}-${s}-cache`}:{},...C?{TSCLOUD_QUEUE:A[0]}:{},...i.env??{}}),j=Boolean(i.efs),H=typeof i.efs==="object"?i.efs:{},z=H.mountPath??"/mnt/local",se=j&&!H.accessPointArn,ve=H.accessPointArn??(se?e.getAtt("EfsAccessPoint","Arn"):void 0),oe=i.vpc?.subnets??[],pe=oe.length>0,ae=i.cache?.driver==="elasticache"||i.database?.connection==="aurora-serverless"||Boolean(i.rdsProxy)||j;if(ae&&!pe)throw Error("serverless app: elasticache / aurora-serverless / rdsProxy / efs require app.vpc.subnets (private subnets) to be set.");let ce=pe?{VpcConfig:{SubnetIds:oe,SecurityGroupIds:[...i.vpc?.securityGroups??[],...ae?[e.getAtt("DataSecurityGroup","GroupId")]:[]]}}:{},Ie=se?oe.map((G,ne)=>`EfsMountTarget${ne}`):[],Le=j?{FileSystemConfigs:[{Arn:ve,LocalMountPath:z}]}:{};if(j)B[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess","elasticfilesystem:DescribeMountTargets"],Resource:"*"});function he(G,ne,ie,re,fe,ht,Ve,Ne=L){N[`${G}LogGroup`]={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:`/aws/lambda/${ne}`,RetentionInDays:v}};let Ue=[...n.runtimeLayers??[],...i.lambdaInsights?[i.lambdaInsights.layerArn]:[]],en=T?{PackageType:"Image",Code:{ImageUri:e.ref("ImageUri")},...i.kind==="php"?{}:{ImageConfig:{Command:[ie]}}}:{Runtime:u,Handler:ie,Code:{S3Bucket:e.ref("ArtifactBucket"),S3Key:e.ref("ArtifactKey")},...Ue.length?{Layers:[...new Set(Ue)]}:{}};N[G]={Type:"AWS::Lambda::Function",DependsOn:[`${G}LogGroup`,...Ie],Properties:{FunctionName:ne,Architectures:[d],MemorySize:fe,Timeout:ht,Role:e.getAtt("AppRole","Arn"),Environment:{Variables:U(re)},EphemeralStorage:{Size:Ne},...en,...Ve!==void 0?{ReservedConcurrentExecutions:Ve}:{},...ce,...Le}}}if(he("HttpFunction",y.http,o.http,"http",i.memory??1024,i.timeout??28,i.concurrency,L),he("CliFunction",y.cli,o.cli,"cli",i.cliMemory??1024,i.cliTimeout??900,void 0,i.cliTmpStorage??L),C)he("QueueFunction",y.queue,o.queue,"queue",i.queueMemory??1024,i.queueTimeout??120,void 0,i.queueTmpStorage??L);let ye=(i.provisionedConcurrency??0)>0?i.provisionedConcurrency:0,be=["HttpFunction","CliFunction",...C?["QueueFunction"]:[]];if(ye)for(let G of be)N[`${G}Version`]={Type:"AWS::Lambda::Version",DeletionPolicy:"Retain",Properties:{FunctionName:e.ref(G)}},N[`${G}Alias`]={Type:"AWS::Lambda::Alias",Properties:{FunctionName:e.ref(G),Name:"live",FunctionVersion:e.getAtt(`${G}Version`,"Version"),ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:ye}}};let De=(G)=>ye?e.ref(`${G}Alias`):e.getAtt(G,"Arn"),Se=(G)=>ye?e.ref(`${G}Alias`):e.ref(G);N.HttpApi={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:`${c}-${s}`,ProtocolType:"HTTP"}},N.HttpIntegration={Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:e.ref("HttpApi"),IntegrationType:"AWS_PROXY",IntegrationUri:De("HttpFunction"),PayloadFormatVersion:"2.0"}},N.HttpRoute={Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:e.ref("HttpApi"),RouteKey:"$default",Target:e.join("/",["integrations",e.ref("HttpIntegration")])}},N.HttpStage={Type:"AWS::ApiGatewayV2::Stage",Properties:{ApiId:e.ref("HttpApi"),StageName:"$default",AutoDeploy:!0}},N.HttpPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:Se("HttpFunction"),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:e.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${HttpApi}/*/*")}},O.HttpApiEndpoint={Description:"HTTP API endpoint",Value:e.getAtt("HttpApi","ApiEndpoint")},O.HttpApiId={Description:"HTTP API id",Value:e.ref("HttpApi")};let Te=(Array.isArray(i.domain)?i.domain:i.domain?[i.domain]:[]).filter(Boolean);if(Te.length){if(!i.certificateArn&&!i.hostedZoneId)throw Error("serverless app: a custom `domain` needs either `certificateArn` (pre-issued, regional) or `hostedZoneId` (to auto-issue + validate an ACM cert).");let G=i.certificateArn;if(!G)N.HttpCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:Te[0],...Te.length>1?{SubjectAlternativeNames:Te.slice(1)}:{},ValidationMethod:"DNS",DomainValidationOptions:Te.map((ne)=>({DomainName:ne,HostedZoneId:i.hostedZoneId}))}},G=e.ref("HttpCertificate");Te.forEach((ne,ie)=>{let re=`HttpDomain${ie}`;if(N[re]={Type:"AWS::ApiGatewayV2::DomainName",Properties:{DomainName:ne,DomainNameConfigurations:[{CertificateArn:G,EndpointType:"REGIONAL"}]}},N[`HttpApiMapping${ie}`]={Type:"AWS::ApiGatewayV2::ApiMapping",DependsOn:["HttpStage"],Properties:{ApiId:e.ref("HttpApi"),DomainName:e.ref(re),Stage:"$default"}},i.hostedZoneId)N[`HttpDomainRecord${ie}`]={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i.hostedZoneId,Name:ne,Type:"A",AliasTarget:{DNSName:e.getAtt(re,"RegionalDomainName"),HostedZoneId:e.getAtt(re,"RegionalHostedZoneId")}}};O[`CustomDomain${ie}`]={Description:`Custom domain ${ne}`,Value:ne},O[`CustomDomainTarget${ie}`]={Description:`Point ${ne} (CNAME/alias) at this APIGW regional domain`,Value:e.getAtt(re,"RegionalDomainName")}})}if(C)N.AppQueueDlq={Type:"AWS::SQS::Queue",Properties:{QueueName:`${c}-${s}-dlq`,MessageRetentionPeriod:1209600}},h.forEach((G,ne)=>{let ie=`AppQueue${ne}`,re=i.queueTimeout??120;N[ie]={Type:"AWS::SQS::Queue",Properties:{QueueName:G.name,VisibilityTimeout:Math.min(43200,re*6),RedrivePolicy:{deadLetterTargetArn:e.getAtt("AppQueueDlq","Arn"),maxReceiveCount:i.queueTries??3}}};let fe=G.concurrency??i.queueConcurrency;N[`${ie}Mapping`]={Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:e.getAtt(ie,"Arn"),FunctionName:Se("QueueFunction"),BatchSize:1,FunctionResponseTypes:["ReportBatchItemFailures"],...fe?{ScalingConfig:{MaximumConcurrency:Math.max(2,fe)}}:{}}},O[`QueueUrl${ne}`]={Description:`Queue URL: ${G.name}`,Value:e.ref(ie)}});if(R)N.SchedulerRule={Type:"AWS::Events::Rule",Properties:{Name:`${c}-${s}-scheduler`,ScheduleExpression:"rate(1 minute)",State:"ENABLED",Targets:[{Id:"cli",Arn:De("CliFunction"),Input:JSON.stringify({command:"schedule:run"})}]}},N.SchedulerPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:Se("CliFunction"),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.getAtt("SchedulerRule","Arn")}};if(i.warm&&i.warm>0){let ne={http:"HttpFunction",queue:"QueueFunction",cli:"CliFunction"},ie=(i.warmFunctions??["http"]).filter((re)=>re!=="queue"||C);for(let re of ie){let fe=re.charAt(0).toUpperCase()+re.slice(1),ht=Math.ceil(i.warm/5),Ve=0;for(let Ne=0;Ne<ht;Ne++){let Ue=Math.min(5,i.warm-Ve);N[`Warmer${fe}Rule${Ne}`]={Type:"AWS::Events::Rule",Properties:{Name:`${c}-${s}-warmer-${re}-${Ne}`,ScheduleExpression:"rate(5 minutes)",State:"ENABLED",Targets:Array.from({length:Ue},(en,sr)=>({Id:`warm-${re}-${Ne}-${sr}`,Arn:e.getAtt(ne[re],"Arn"),Input:JSON.stringify({warmer:!0})}))}},Ve+=Ue}N[`Warmer${fe}Permission`]={Type:"AWS::Lambda::Permission",Properties:{FunctionName:e.ref(ne[re]),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.sub(`arn:aws:events:\${AWS::Region}:\${AWS::AccountId}:rule/${c}-${s}-warmer-${re}-*`)}}}}if(P)N.CacheTable={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${c}-${s}-cache`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"key",AttributeType:"S"}],KeySchema:[{AttributeName:"key",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"expires_at",Enabled:!0}}},O.CacheTableName={Description:"DynamoDB cache table",Value:e.ref("CacheTable")};if(I){if(N.AssetsBucket={Type:"AWS::S3::Bucket",Properties:{BucketName:M,PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}}},N.AssetsOAC={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${c}-${s}-assets-oac`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},N.AssetsDistribution={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,DefaultCacheBehavior:{TargetOriginId:"assets",ViewerProtocolPolicy:"redirect-to-https",Compress:!0,CachePolicyId:"658327ea-f89d-4fab-a63d-7e88639e58f6"},Origins:[{Id:"assets",DomainName:e.getAtt("AssetsBucket","RegionalDomainName"),OriginAccessControlId:e.ref("AssetsOAC"),S3OriginConfig:{OriginAccessIdentity:""}}],...i.assetDomain?{Aliases:[i.assetDomain],ViewerCertificate:{AcmCertificateArn:i.assetCertificateArn??e.ref("AssetsCertificate"),SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}}:{}}}},i.assetDomain){if(!i.assetCertificateArn){if(!i.hostedZoneId)throw Error("serverless app: `assetDomain` requires either `assetCertificateArn` (a us-east-1 ACM cert) or `hostedZoneId` (to auto-issue + validate one). CloudFront only accepts certs from us-east-1.");if(g!=="us-east-1")throw Error(`serverless app: auto-issuing an asset-domain cert needs a us-east-1 app (CloudFront certs must be us-east-1); this app is in ${g}. Supply a pre-issued us-east-1 \`assetCertificateArn\` instead.`);N.AssetsCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:i.assetDomain,ValidationMethod:"DNS",DomainValidationOptions:[{DomainName:i.assetDomain,HostedZoneId:i.hostedZoneId}]}}}if(i.hostedZoneId)N.AssetsDomainRecord={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i.hostedZoneId,Name:i.assetDomain,Type:"A",AliasTarget:{DNSName:e.getAtt("AssetsDistribution","DomainName"),HostedZoneId:"Z2FDTNDATAQYW2"}}};O.AssetDomain={Description:"Custom asset CDN host",Value:i.assetDomain}}N.AssetsBucketPolicy={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:e.ref("AssetsBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:e.sub(`arn:aws:s3:::${M}/*`),Condition:{StringEquals:{"AWS:SourceArn":e.sub("arn:aws:cloudfront::${AWS::AccountId}:distribution/${AssetsDistribution}")}}}]}}},O.AssetsBucketName={Description:"Assets bucket",Value:e.ref("AssetsBucket")},O.AssetsCdnDomain={Description:"Assets CloudFront domain",Value:e.getAtt("AssetsDistribution","DomainName")}}if(i.firewall?.enabled){let G=[],ne=0;if(i.firewall.rateLimit)G.push({Name:"rate-limit",Priority:ne++,Action:{Block:{}},Statement:{RateBasedStatement:{Limit:i.firewall.rateLimit,AggregateKeyType:"IP"}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${s}-rate`}});let ie={sqlInjection:"AWSManagedRulesSQLiRuleSet",xss:"AWSManagedRulesCommonRuleSet",common:"AWSManagedRulesCommonRuleSet",botControl:"AWSManagedRulesBotControlRuleSet",ipReputation:"AWSManagedRulesAmazonIpReputationList"};for(let re of i.firewall.rules??[]){let fe=ie[re];if(!fe)continue;G.push({Name:`managed-${re}`,Priority:ne++,OverrideAction:{None:{}},Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:fe}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${s}-${re}`}})}N.WebAcl={Type:"AWS::WAFv2::WebACL",Properties:{Name:`${c}-${s}-waf`,Scope:"REGIONAL",DefaultAction:{Allow:{}},Rules:G,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${s}-waf`}}},O.WafAclArn={Description:"WAF web ACL ARN. Attach to a CloudFront distribution fronting the API to enforce (HTTP API v2 stages do not support direct WAF association).",Value:e.getAtt("WebAcl","Arn")}}if(pe&&ae){if(!i.vpc?.id)throw Error("serverless app: data services (elasticache / aurora-serverless / rdsProxy / efs) need app.vpc.id (the VPC id) so the managed security group is created in the right VPC.");N.DataSecurityGroup={Type:"AWS::EC2::SecurityGroup",Properties:{VpcId:i.vpc.id,GroupDescription:`${c}-${s} serverless data access`,SecurityGroupIngress:[{IpProtocol:"-1",CidrIp:"10.0.0.0/8"}]}}}if(se)N.EfsFileSystem={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:!0,FileSystemTags:[{Key:"Name",Value:`${c}-${s}-efs`}]}},oe.forEach((G,ne)=>{N[`EfsMountTarget${ne}`]={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:e.ref("EfsFileSystem"),SubnetId:G,SecurityGroups:[e.getAtt("DataSecurityGroup","GroupId")]}}}),N.EfsAccessPoint={Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:e.ref("EfsFileSystem"),PosixUser:{Uid:1001,Gid:1001},RootDirectory:{Path:"/lambda",CreationInfo:{OwnerUid:1001,OwnerGid:1001,Permissions:"0755"}}}},O.EfsFileSystemId={Description:"EFS file system id",Value:e.ref("EfsFileSystem")};if(i.cache?.driver==="elasticache")N.CacheSubnetGroup={Type:"AWS::ElastiCache::SubnetGroup",Properties:{Description:`${c}-${s} cache subnets`,SubnetIds:oe}},N.CacheCluster={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:`${c}-${s}-cache`,ReplicationGroupDescription:`${c}-${s} redis`,Engine:"redis",CacheNodeType:"cache.t4g.micro",NumCacheClusters:1,AutomaticFailoverEnabled:!1,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),SecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")],TransitEncryptionEnabled:!1}},O.CacheEndpoint={Description:"Redis primary endpoint",Value:e.getAtt("CacheCluster","PrimaryEndPoint.Address")};if(i.database?.connection==="aurora-serverless")N.DbSubnetGroup={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupDescription:`${c}-${s} db subnets`,SubnetIds:oe}},N.DbSecret={Type:"AWS::SecretsManager::Secret",Properties:{Name:`${c}/${s}/db`,GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"app"}),GenerateStringKey:"password",PasswordLength:32,ExcludePunctuation:!0}}},N.DbCluster={Type:"AWS::RDS::DBCluster",Properties:{Engine:"aurora-mysql",EngineMode:"provisioned",DBClusterIdentifier:`${c}-${s}-db`,DatabaseName:"app",MasterUsername:e.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:username}}"),MasterUserPassword:e.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:password}}"),ServerlessV2ScalingConfiguration:{MinCapacity:i.database?.minCapacity??0.5,MaxCapacity:i.database?.maxCapacity??4},DBSubnetGroupName:e.ref("DbSubnetGroup"),VpcSecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")]}},N.DbInstance={Type:"AWS::RDS::DBInstance",Properties:{Engine:"aurora-mysql",DBInstanceClass:"db.serverless",DBClusterIdentifier:e.ref("DbCluster")}},O.DbEndpoint={Description:"Aurora cluster endpoint",Value:e.getAtt("DbCluster","Endpoint.Address")};if(i.rdsProxy&&i.database?.connection==="aurora-serverless")N.DbProxyRole={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"rds.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"read-db-secret",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue"],Resource:e.ref("DbSecret")}]}}]}},N.DbProxy={Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:typeof i.rdsProxy==="object"&&i.rdsProxy.name?i.rdsProxy.name:`${c}-${s}-proxy`,EngineFamily:"MYSQL",RoleArn:e.getAtt("DbProxyRole","Arn"),Auth:[{AuthScheme:"SECRETS",SecretArn:e.ref("DbSecret"),IAMAuth:"DISABLED"}],VpcSubnetIds:oe,VpcSecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")],RequireTLS:!1}},N.DbProxyTargetGroup={Type:"AWS::RDS::DBProxyTargetGroup",DependsOn:["DbInstance"],Properties:{DBProxyName:e.ref("DbProxy"),TargetGroupName:"default",DBClusterIdentifiers:[e.ref("DbCluster")]}},O.DbProxyEndpoint={Description:"RDS Proxy endpoint",Value:e.getAtt("DbProxy","Endpoint")};if(O.HttpFunctionName={Description:"HTTP function name",Value:e.ref("HttpFunction")},O.CliFunctionName={Description:"CLI function name",Value:e.ref("CliFunction")},C)O.QueueFunctionName={Description:"Queue function name",Value:e.ref("QueueFunction")};let $e={AWSTemplateFormatVersion:"2010-09-09",Description:`Serverless application for ${n.config.project.name} (${c}-${s})`,Parameters:T?{ImageUri:{Type:"String",Description:"ECR image URI of the deployment artifact"}}:{ArtifactBucket:{Type:"String",Description:"S3 bucket holding the deployment artifact"},ArtifactKey:{Type:"String",Description:"S3 key of the deployment artifact (zip)"}},Resources:N,Outputs:O},We={};for(let G of Object.values(N))We[G.Type]=(We[G.Type]??0)+1;return{template:$e,functionNames:y,queueNames:A,resourceSummary:We}}var pS=["cli","fpm","curl","mbstring","xml","pdo","mysqlnd","gd","bcmath","intl","opcache","sodium","process","pecl-redis6","pecl-apcu","pgsql"];function mS(n){let i=`php${n.replace(".","")}`;return pS.map((s)=>`${i}-php-${s}`)}function Ul(n,i){let s=`php${n.replace(".","")}`,o=mS(n).join(" \\\n "),c=`/opt/remi/${s}/root`,u=`/etc/opt/remi/${s}`;return`${i?`FROM almalinux:9 AS ${i}`:"FROM almalinux:9"}
7239
+ ${v}`)}let y=g.outputs[0],h=Buffer.from(await y.arrayBuffer()),A="index",C=ot([{name:`${A}.mjs`,data:h}]);return{zip:C,bundle:h,sha256:ia(C),handlerFile:A,handlers:{http:s.handlers?.http??`${A}.http`,queue:s.handlers?.queue??`${A}.queue`,cli:s.handlers?.cli??`${A}.cli`},bundleBytes:h.length}}finally{Rs(u,{recursive:!0,force:!0})}}var vS=["18","20","22"];function Ms(n){if(!n)return"22";let i=String(n).match(/(\d+)/);return i?i[1]:"22"}function cs(n){let i=n.kind??"node";if(i==="php")return{lambdaRuntime:"provided.al2023",kind:"php",version:n.phpVersion??"8.3",usesLayer:!0,layerKind:"php",layerEnvVar:"TSCLOUD_PHP_LAYER_ARN"};if(i==="bun")return{lambdaRuntime:"provided.al2023",kind:"bun",version:n.runtimeVersion??"latest",usesLayer:!0,layerKind:"bun",layerEnvVar:"TSCLOUD_BUN_LAYER_ARN"};let s=Ms(n.runtimeVersion);if(n.runtime!=="provided.al2023"&&vS.includes(s))return{lambdaRuntime:n.runtime&&n.runtime.startsWith("nodejs")?n.runtime:`nodejs${s}.x`,kind:"node",version:s,usesLayer:!1};return{lambdaRuntime:"provided.al2023",kind:"node",version:s,usesLayer:!0,layerKind:"node",layerEnvVar:"TSCLOUD_NODE_LAYER_ARN"}}function yr(n,i,s){if(n.queues===!1)return[];if(n.queues===void 0||n.queues===!0)return[{name:`${i}-${s}-default`}];return n.queues.map((o)=>{if(typeof o==="string")return{name:`${i}-${s}-${o}`};let[c,u]=Object.entries(o)[0];return{name:`${i}-${s}-${c}`,concurrency:u}})}function zl(n,i,s){return yr(n,i,s).map((o)=>o.name)}function Kl(n){let{app:i,environment:s,handlers:o}=n,c=n.config.project.slug,u=cs(i).lambdaRuntime,d=i.architecture??"x86_64",g=n.config.project.region,y={http:`${c}-${s}-http`,queue:`${c}-${s}-queue`,cli:`${c}-${s}-cli`};if(i.gatewayVersion===1)throw Error("serverless app: `gatewayVersion: 1` (REST API) is not supported — ts-cloud uses API Gateway HTTP API (v2). Remove `gatewayVersion` or set it to 2.");let h=yr(i,c,s),A=h.map((V)=>V.name),C=A.length>0,v=i.logRetention??14,T=i.packaging==="image";if(T&&i.lambdaInsights)throw Error("serverless app: `lambdaInsights` layer attachment is only supported for zip packaging. Container images must install the Lambda Insights extension in the image.");let R=(i.scheduler??"on")!=="off",P=(i.cache?.driver??"dynamodb")==="dynamodb",I=Boolean(i.assets),O=Zi(c,s),B=i.tmpStorage??512,x={},F={},G=[{PolicyName:"tscloud-serverless-app",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:e.sub("arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*")},{Effect:"Allow",Action:["lambda:InvokeFunction"],Resource:e.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${c}-${s}-*`)},{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameter","ssm:GetParameters","ssm:GetParametersByPath"],Resource:[e.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${c}/${s}/*`),e.sub(`arn:aws:ssm:\${AWS::Region}:\${AWS::AccountId}:parameter/${c}/${s}/*`)]},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[e.sub(`arn:aws:s3:::${O}`),e.sub(`arn:aws:s3:::${O}/*`),...i.storage?.bucket?[e.sub(`arn:aws:s3:::${i.storage.bucket}`),e.sub(`arn:aws:s3:::${i.storage.bucket}/*`)]:[]]}]}}];if(C)G[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["sqs:SendMessage","sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes","sqs:GetQueueUrl"],Resource:e.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${c}-${s}-*`)});if(P)G[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:BatchGetItem","dynamodb:BatchWriteItem"],Resource:e.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${c}-${s}-cache*`)});let _=["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"];if(i.vpc?.subnets?.length)_.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");if(i.lambdaInsights)_.push("arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy");x.AppRole={Type:"AWS::IAM::Role",Properties:{RoleName:`${c}-${s}-app-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:_,Policies:G}};let U=(V)=>({TSCLOUD_LAMBDA_MODE:V,TSCLOUD_ENV:s,...i.octane?{TSCLOUD_OCTANE:"1"}:{},...i.scheduler==="sub-minute"?{TSCLOUD_SCHEDULER:"sub-minute"}:{},...P?{TSCLOUD_CACHE_TABLE:`${c}-${s}-cache`}:{},...C?{TSCLOUD_QUEUE:A[0]}:{},...i.env??{}}),z=Boolean(i.efs),K=typeof i.efs==="object"?i.efs:{},Q=K.mountPath??"/mnt/local",ae=z&&!K.accessPointArn,Pe=K.accessPointArn??(ae?e.getAtt("EfsAccessPoint","Arn"):void 0),ce=i.vpc?.subnets??[],ye=ce.length>0,oe=i.cache?.driver==="elasticache"||i.database?.connection==="aurora-serverless"||Boolean(i.rdsProxy)||z;if(oe&&!ye)throw Error("serverless app: elasticache / aurora-serverless / rdsProxy / efs require app.vpc.subnets (private subnets) to be set.");let de=ye?{VpcConfig:{SubnetIds:ce,SecurityGroupIds:[...i.vpc?.securityGroups??[],...oe?[e.getAtt("DataSecurityGroup","GroupId")]:[]]}}:{},Ne=ae?ce.map((V,ne)=>`EfsMountTarget${ne}`):[],Be=z?{FileSystemConfigs:[{Arn:Pe,LocalMountPath:Q}]}:{};if(z)G[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess","elasticfilesystem:DescribeMountTargets"],Resource:"*"});function be(V,ne,se,ie,he,St,He,ke=B){x[`${V}LogGroup`]={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:`/aws/lambda/${ne}`,RetentionInDays:v}};let je=[...n.runtimeLayers??[],...i.lambdaInsights?[i.lambdaInsights.layerArn]:[]],an=T?{PackageType:"Image",Code:{ImageUri:e.ref("ImageUri")},...i.kind==="php"?{}:{ImageConfig:{Command:[se]}}}:{Runtime:u,Handler:se,Code:{S3Bucket:e.ref("ArtifactBucket"),S3Key:e.ref("ArtifactKey")},...je.length?{Layers:[...new Set(je)]}:{}};x[V]={Type:"AWS::Lambda::Function",DependsOn:[`${V}LogGroup`,...Ne],Properties:{FunctionName:ne,Architectures:[d],MemorySize:he,Timeout:St,Role:e.getAtt("AppRole","Arn"),Environment:{Variables:U(ie)},EphemeralStorage:{Size:ke},...an,...He!==void 0?{ReservedConcurrentExecutions:He}:{},...de,...Be}}}if(be("HttpFunction",y.http,o.http,"http",i.memory??1024,i.timeout??28,i.concurrency,B),be("CliFunction",y.cli,o.cli,"cli",i.cliMemory??1024,i.cliTimeout??900,void 0,i.cliTmpStorage??B),C)be("QueueFunction",y.queue,o.queue,"queue",i.queueMemory??1024,i.queueTimeout??120,void 0,i.queueTmpStorage??B);let fe=(i.provisionedConcurrency??0)>0?i.provisionedConcurrency:0,Se=["HttpFunction","CliFunction",...C?["QueueFunction"]:[]];if(fe)for(let V of Se)x[`${V}Version`]={Type:"AWS::Lambda::Version",DeletionPolicy:"Retain",Properties:{FunctionName:e.ref(V)}},x[`${V}Alias`]={Type:"AWS::Lambda::Alias",Properties:{FunctionName:e.ref(V),Name:"live",FunctionVersion:e.getAtt(`${V}Version`,"Version"),ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:fe}}};let xe=(V)=>fe?e.ref(`${V}Alias`):e.getAtt(V,"Arn"),Ae=(V)=>fe?e.ref(`${V}Alias`):e.ref(V);x.HttpApi={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:`${c}-${s}`,ProtocolType:"HTTP"}},x.HttpIntegration={Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:e.ref("HttpApi"),IntegrationType:"AWS_PROXY",IntegrationUri:xe("HttpFunction"),PayloadFormatVersion:"2.0"}},x.HttpRoute={Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:e.ref("HttpApi"),RouteKey:"$default",Target:e.join("/",["integrations",e.ref("HttpIntegration")])}},x.HttpStage={Type:"AWS::ApiGatewayV2::Stage",Properties:{ApiId:e.ref("HttpApi"),StageName:"$default",AutoDeploy:!0}},x.HttpPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:Ae("HttpFunction"),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:e.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${HttpApi}/*/*")}},F.HttpApiEndpoint={Description:"HTTP API endpoint",Value:e.getAtt("HttpApi","ApiEndpoint")},F.HttpApiId={Description:"HTTP API id",Value:e.ref("HttpApi")};let Ee=(Array.isArray(i.domain)?i.domain:i.domain?[i.domain]:[]).filter(Boolean);if(Ee.length){if(!i.certificateArn&&!i.hostedZoneId)throw Error("serverless app: a custom `domain` needs either `certificateArn` (pre-issued, regional) or `hostedZoneId` (to auto-issue + validate an ACM cert).");let V=i.certificateArn;if(!V)x.HttpCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:Ee[0],...Ee.length>1?{SubjectAlternativeNames:Ee.slice(1)}:{},ValidationMethod:"DNS",DomainValidationOptions:Ee.map((ne)=>({DomainName:ne,HostedZoneId:i.hostedZoneId}))}},V=e.ref("HttpCertificate");Ee.forEach((ne,se)=>{let ie=`HttpDomain${se}`;if(x[ie]={Type:"AWS::ApiGatewayV2::DomainName",Properties:{DomainName:ne,DomainNameConfigurations:[{CertificateArn:V,EndpointType:"REGIONAL"}]}},x[`HttpApiMapping${se}`]={Type:"AWS::ApiGatewayV2::ApiMapping",DependsOn:["HttpStage"],Properties:{ApiId:e.ref("HttpApi"),DomainName:e.ref(ie),Stage:"$default"}},i.hostedZoneId)x[`HttpDomainRecord${se}`]={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i.hostedZoneId,Name:ne,Type:"A",AliasTarget:{DNSName:e.getAtt(ie,"RegionalDomainName"),HostedZoneId:e.getAtt(ie,"RegionalHostedZoneId")}}};F[`CustomDomain${se}`]={Description:`Custom domain ${ne}`,Value:ne},F[`CustomDomainTarget${se}`]={Description:`Point ${ne} (CNAME/alias) at this APIGW regional domain`,Value:e.getAtt(ie,"RegionalDomainName")}})}if(C)x.AppQueueDlq={Type:"AWS::SQS::Queue",Properties:{QueueName:`${c}-${s}-dlq`,MessageRetentionPeriod:1209600}},h.forEach((V,ne)=>{let se=`AppQueue${ne}`,ie=i.queueTimeout??120;x[se]={Type:"AWS::SQS::Queue",Properties:{QueueName:V.name,VisibilityTimeout:Math.min(43200,ie*6),RedrivePolicy:{deadLetterTargetArn:e.getAtt("AppQueueDlq","Arn"),maxReceiveCount:i.queueTries??3}}};let he=V.concurrency??i.queueConcurrency;x[`${se}Mapping`]={Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:e.getAtt(se,"Arn"),FunctionName:Ae("QueueFunction"),BatchSize:1,FunctionResponseTypes:["ReportBatchItemFailures"],...he?{ScalingConfig:{MaximumConcurrency:Math.max(2,he)}}:{}}},F[`QueueUrl${ne}`]={Description:`Queue URL: ${V.name}`,Value:e.ref(se)}});if(R)x.SchedulerRule={Type:"AWS::Events::Rule",Properties:{Name:`${c}-${s}-scheduler`,ScheduleExpression:"rate(1 minute)",State:"ENABLED",Targets:[{Id:"cli",Arn:xe("CliFunction"),Input:JSON.stringify({command:"schedule:run"})}]}},x.SchedulerPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:Ae("CliFunction"),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.getAtt("SchedulerRule","Arn")}};if(i.warm&&i.warm>0){let ne={http:"HttpFunction",queue:"QueueFunction",cli:"CliFunction"},se=(i.warmFunctions??["http"]).filter((ie)=>ie!=="queue"||C);for(let ie of se){let he=ie.charAt(0).toUpperCase()+ie.slice(1),St=Math.ceil(i.warm/5),He=0;for(let ke=0;ke<St;ke++){let je=Math.min(5,i.warm-He);x[`Warmer${he}Rule${ke}`]={Type:"AWS::Events::Rule",Properties:{Name:`${c}-${s}-warmer-${ie}-${ke}`,ScheduleExpression:"rate(5 minutes)",State:"ENABLED",Targets:Array.from({length:je},(an,wr)=>({Id:`warm-${ie}-${ke}-${wr}`,Arn:e.getAtt(ne[ie],"Arn"),Input:JSON.stringify({warmer:!0})}))}},He+=je}x[`Warmer${he}Permission`]={Type:"AWS::Lambda::Permission",Properties:{FunctionName:e.ref(ne[ie]),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:e.sub(`arn:aws:events:\${AWS::Region}:\${AWS::AccountId}:rule/${c}-${s}-warmer-${ie}-*`)}}}}if(P)x.CacheTable={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${c}-${s}-cache`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"key",AttributeType:"S"}],KeySchema:[{AttributeName:"key",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"expires_at",Enabled:!0}}},F.CacheTableName={Description:"DynamoDB cache table",Value:e.ref("CacheTable")};if(I){if(x.AssetsBucket={Type:"AWS::S3::Bucket",Properties:{BucketName:O,PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}}},x.AssetsOAC={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${c}-${s}-assets-oac`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},x.AssetsDistribution={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,DefaultCacheBehavior:{TargetOriginId:"assets",ViewerProtocolPolicy:"redirect-to-https",Compress:!0,CachePolicyId:"658327ea-f89d-4fab-a63d-7e88639e58f6"},Origins:[{Id:"assets",DomainName:e.getAtt("AssetsBucket","RegionalDomainName"),OriginAccessControlId:e.ref("AssetsOAC"),S3OriginConfig:{OriginAccessIdentity:""}}],...i.assetDomain?{Aliases:[i.assetDomain],ViewerCertificate:{AcmCertificateArn:i.assetCertificateArn??e.ref("AssetsCertificate"),SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}}:{}}}},i.assetDomain){if(!i.assetCertificateArn){if(!i.hostedZoneId)throw Error("serverless app: `assetDomain` requires either `assetCertificateArn` (a us-east-1 ACM cert) or `hostedZoneId` (to auto-issue + validate one). CloudFront only accepts certs from us-east-1.");if(g!=="us-east-1")throw Error(`serverless app: auto-issuing an asset-domain cert needs a us-east-1 app (CloudFront certs must be us-east-1); this app is in ${g}. Supply a pre-issued us-east-1 \`assetCertificateArn\` instead.`);x.AssetsCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:i.assetDomain,ValidationMethod:"DNS",DomainValidationOptions:[{DomainName:i.assetDomain,HostedZoneId:i.hostedZoneId}]}}}if(i.hostedZoneId)x.AssetsDomainRecord={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:i.hostedZoneId,Name:i.assetDomain,Type:"A",AliasTarget:{DNSName:e.getAtt("AssetsDistribution","DomainName"),HostedZoneId:"Z2FDTNDATAQYW2"}}};F.AssetDomain={Description:"Custom asset CDN host",Value:i.assetDomain}}x.AssetsBucketPolicy={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:e.ref("AssetsBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:e.sub(`arn:aws:s3:::${O}/*`),Condition:{StringEquals:{"AWS:SourceArn":e.sub("arn:aws:cloudfront::${AWS::AccountId}:distribution/${AssetsDistribution}")}}}]}}},F.AssetsBucketName={Description:"Assets bucket",Value:e.ref("AssetsBucket")},F.AssetsCdnDomain={Description:"Assets CloudFront domain",Value:e.getAtt("AssetsDistribution","DomainName")}}if(i.firewall?.enabled){let V=[],ne=0;if(i.firewall.rateLimit)V.push({Name:"rate-limit",Priority:ne++,Action:{Block:{}},Statement:{RateBasedStatement:{Limit:i.firewall.rateLimit,AggregateKeyType:"IP"}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${s}-rate`}});let se={sqlInjection:"AWSManagedRulesSQLiRuleSet",xss:"AWSManagedRulesCommonRuleSet",common:"AWSManagedRulesCommonRuleSet",botControl:"AWSManagedRulesBotControlRuleSet",ipReputation:"AWSManagedRulesAmazonIpReputationList"};for(let ie of i.firewall.rules??[]){let he=se[ie];if(!he)continue;V.push({Name:`managed-${ie}`,Priority:ne++,OverrideAction:{None:{}},Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:he}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${s}-${ie}`}})}x.WebAcl={Type:"AWS::WAFv2::WebACL",Properties:{Name:`${c}-${s}-waf`,Scope:"REGIONAL",DefaultAction:{Allow:{}},Rules:V,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${c}-${s}-waf`}}},F.WafAclArn={Description:"WAF web ACL ARN. Attach to a CloudFront distribution fronting the API to enforce (HTTP API v2 stages do not support direct WAF association).",Value:e.getAtt("WebAcl","Arn")}}if(ye&&oe){if(!i.vpc?.id)throw Error("serverless app: data services (elasticache / aurora-serverless / rdsProxy / efs) need app.vpc.id (the VPC id) so the managed security group is created in the right VPC.");x.DataSecurityGroup={Type:"AWS::EC2::SecurityGroup",Properties:{VpcId:i.vpc.id,GroupDescription:`${c}-${s} serverless data access`,SecurityGroupIngress:[{IpProtocol:"-1",CidrIp:"10.0.0.0/8"}]}}}if(ae)x.EfsFileSystem={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:!0,FileSystemTags:[{Key:"Name",Value:`${c}-${s}-efs`}]}},ce.forEach((V,ne)=>{x[`EfsMountTarget${ne}`]={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:e.ref("EfsFileSystem"),SubnetId:V,SecurityGroups:[e.getAtt("DataSecurityGroup","GroupId")]}}}),x.EfsAccessPoint={Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:e.ref("EfsFileSystem"),PosixUser:{Uid:1001,Gid:1001},RootDirectory:{Path:"/lambda",CreationInfo:{OwnerUid:1001,OwnerGid:1001,Permissions:"0755"}}}},F.EfsFileSystemId={Description:"EFS file system id",Value:e.ref("EfsFileSystem")};if(i.cache?.driver==="elasticache")x.CacheSubnetGroup={Type:"AWS::ElastiCache::SubnetGroup",Properties:{Description:`${c}-${s} cache subnets`,SubnetIds:ce}},x.CacheCluster={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:`${c}-${s}-cache`,ReplicationGroupDescription:`${c}-${s} redis`,Engine:"redis",CacheNodeType:"cache.t4g.micro",NumCacheClusters:1,AutomaticFailoverEnabled:!1,CacheSubnetGroupName:e.ref("CacheSubnetGroup"),SecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")],TransitEncryptionEnabled:!1}},F.CacheEndpoint={Description:"Redis primary endpoint",Value:e.getAtt("CacheCluster","PrimaryEndPoint.Address")};if(i.database?.connection==="aurora-serverless")x.DbSubnetGroup={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupDescription:`${c}-${s} db subnets`,SubnetIds:ce}},x.DbSecret={Type:"AWS::SecretsManager::Secret",Properties:{Name:`${c}/${s}/db`,GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"app"}),GenerateStringKey:"password",PasswordLength:32,ExcludePunctuation:!0}}},x.DbCluster={Type:"AWS::RDS::DBCluster",Properties:{Engine:"aurora-mysql",EngineMode:"provisioned",DBClusterIdentifier:`${c}-${s}-db`,DatabaseName:"app",MasterUsername:e.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:username}}"),MasterUserPassword:e.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:password}}"),ServerlessV2ScalingConfiguration:{MinCapacity:i.database?.minCapacity??0.5,MaxCapacity:i.database?.maxCapacity??4},DBSubnetGroupName:e.ref("DbSubnetGroup"),VpcSecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")]}},x.DbInstance={Type:"AWS::RDS::DBInstance",Properties:{Engine:"aurora-mysql",DBInstanceClass:"db.serverless",DBClusterIdentifier:e.ref("DbCluster")}},F.DbEndpoint={Description:"Aurora cluster endpoint",Value:e.getAtt("DbCluster","Endpoint.Address")};if(i.rdsProxy&&i.database?.connection==="aurora-serverless")x.DbProxyRole={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"rds.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"read-db-secret",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue"],Resource:e.ref("DbSecret")}]}}]}},x.DbProxy={Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:typeof i.rdsProxy==="object"&&i.rdsProxy.name?i.rdsProxy.name:`${c}-${s}-proxy`,EngineFamily:"MYSQL",RoleArn:e.getAtt("DbProxyRole","Arn"),Auth:[{AuthScheme:"SECRETS",SecretArn:e.ref("DbSecret"),IAMAuth:"DISABLED"}],VpcSubnetIds:ce,VpcSecurityGroupIds:[e.getAtt("DataSecurityGroup","GroupId")],RequireTLS:!1}},x.DbProxyTargetGroup={Type:"AWS::RDS::DBProxyTargetGroup",DependsOn:["DbInstance"],Properties:{DBProxyName:e.ref("DbProxy"),TargetGroupName:"default",DBClusterIdentifiers:[e.ref("DbCluster")]}},F.DbProxyEndpoint={Description:"RDS Proxy endpoint",Value:e.getAtt("DbProxy","Endpoint")};if(F.HttpFunctionName={Description:"HTTP function name",Value:e.ref("HttpFunction")},F.CliFunctionName={Description:"CLI function name",Value:e.ref("CliFunction")},C)F.QueueFunctionName={Description:"Queue function name",Value:e.ref("QueueFunction")};let Fe={AWSTemplateFormatVersion:"2010-09-09",Description:`Serverless application for ${n.config.project.name} (${c}-${s})`,Parameters:T?{ImageUri:{Type:"String",Description:"ECR image URI of the deployment artifact"}}:{ArtifactBucket:{Type:"String",Description:"S3 bucket holding the deployment artifact"},ArtifactKey:{Type:"String",Description:"S3 key of the deployment artifact (zip)"}},Resources:x,Outputs:F},Ue={};for(let V of Object.values(x))Ue[V.Type]=(Ue[V.Type]??0)+1;return{template:Fe,functionNames:y,queueNames:A,resourceSummary:Ue}}var TS=["cli","fpm","curl","mbstring","xml","pdo","mysqlnd","gd","bcmath","intl","opcache","sodium","process","pecl-redis6","pecl-apcu","pgsql"];function wS(n){let i=`php${n.replace(".","")}`;return TS.map((s)=>`${i}-php-${s}`)}function Wl(n,i){let s=`php${n.replace(".","")}`,o=wS(n).join(" \\\n "),c=`/opt/remi/${s}/root`,u=`/etc/opt/remi/${s}`;return`${i?`FROM almalinux:9 AS ${i}`:"FROM almalinux:9"}
7242
7240
 
7243
7241
  # Build PHP on AlmaLinux 9 (where Remi's version-isolated SCL packages install
7244
7242
  # cleanly — Remi's release RPM rejects Amazon Linux 2023). AlmaLinux 9 shares
@@ -7278,9 +7276,9 @@ RUN printf 'extension_dir=/opt/php/lib/php/modules\\n' > /opt/php/etc/php.ini &&
7278
7276
  # Runtime assets (bootstrap, runtime loops, fpm config) are added by the build
7279
7277
  # orchestrator after the image is produced. Export /opt as the layer payload.
7280
7278
  CMD ["true"]
7281
- `}function Bf(n={}){let i=n.phpVersion??"8.3";return`# ts-cloud PHP ${i} runtime layer (generated) — AWS Lambda provided.al2023.
7282
- ${Ul(i)}`}function Ql(n){if(n.kind==="php"){let s=n.phpVersion??"8.3";return`# ts-cloud serverless PHP app image (generated, multi-stage).
7283
- ${Ul(s,"phpbuild")}
7279
+ `}function Hf(n={}){let i=n.phpVersion??"8.3";return`# ts-cloud PHP ${i} runtime layer (generated) — AWS Lambda provided.al2023.
7280
+ ${Wl(i)}`}function Jl(n){if(n.kind==="php"){let s=n.phpVersion??"8.3";return`# ts-cloud serverless PHP app image (generated, multi-stage).
7281
+ ${Wl(s,"phpbuild")}
7284
7282
 
7285
7283
  FROM public.ecr.aws/lambda/provided:al2023
7286
7284
  # Bake the relocated PHP runtime from the build stage.
@@ -7299,7 +7297,7 @@ COPY app/ \${LAMBDA_TASK_ROOT}/
7299
7297
 
7300
7298
  # Per-function CMD (e.g. index.http) is supplied via ImageConfig.Command.
7301
7299
  CMD [ "index.http" ]
7302
- `}import{execFileSync as pt}from"node:child_process";import{mkdtempSync as jn,readFileSync as gt,rmSync as Kn}from"node:fs";import{tmpdir as qn}from"node:os";import{dirname as os,join as we}from"node:path";import{fileURLToPath as cs}from"node:url";function zn(){return os(cs(import.meta.url))}function xf(){return gt(we(zn(),"runtime.mjs"),"utf-8")}function Qn(n){return gt(we(zn(),`${n}-bootstrap`),"utf-8")}function PE(n){let i=n.architecture??"x86_64",s=i==="arm64"?"arm64":"x64",o=n.version.replace(/^v/,""),c=n.onStep??(()=>{}),u=jn(we(qn(),"tscloud-node-layer-"));try{let d=o.includes(".")?o:ls(o),g=`node-v${d}-linux-${s}`,y=`https://nodejs.org/dist/v${d}/${g}.tar.xz`;c(`downloading Node ${d} (${i})`);let h=we(u,"node.tar.xz");Jn(y,h),c("extracting node binary"),pt("tar",["-xf",h,"-C",u,`${g}/bin/node`],{stdio:"inherit"});let A=gt(we(u,g,"bin","node"));c("packaging layer");let C=[{name:"bootstrap",data:Qn("node"),mode:493},{name:"runtime.mjs",data:xf(),mode:420},{name:"bin/node",data:A,mode:493}];return{zip:it(C),architecture:i,version:d,fileCount:C.length}}finally{Kn(u,{recursive:!0,force:!0})}}function kE(n){let i=n.architecture??"x86_64",s=i==="arm64"?"bun-linux-aarch64":"bun-linux-x64",o=n.version==="latest"?"":n.version.replace(/^v/,""),c=n.onStep??(()=>{}),u=jn(we(qn(),"tscloud-bun-layer-"));try{let d=o?`https://github.com/oven-sh/bun/releases/download/bun-v${o}/${s}.zip`:`https://github.com/oven-sh/bun/releases/latest/download/${s}.zip`;c(`downloading Bun ${o||"latest"} (${i})`);let g=we(u,"bun.zip");Jn(d,g),c("extracting bun binary"),pt("unzip",["-o","-q",g,"-d",u],{stdio:"inherit"});let y=gt(we(u,s,"bun"));c("packaging layer");let h=[{name:"bootstrap",data:Qn("bun"),mode:493},{name:"runtime.mjs",data:xf(),mode:420},{name:"bin/bun",data:y,mode:493}];return{zip:it(h),architecture:i,version:o||"latest",fileCount:h.length}}finally{Kn(u,{recursive:!0,force:!0})}}function Jn(n,i){pt("curl",["-fsSL","-o",i,n],{stdio:["ignore","ignore","inherit"]})}function ls(n){let i=pt("curl",["-fsSL","https://nodejs.org/dist/index.json"],{encoding:"utf-8"}),o=JSON.parse(i).find((c)=>c.version.startsWith(`v${n}.`));if(!o)throw Error(`No Node release found for major version ${n}`);return o.version.replace(/^v/,"")}import{AsyncLocalStorage as ds}from"node:async_hooks";import{createHash as us}from"node:crypto";var Jo="x-ts-cloud-invoke-depth",Xo="x-ts-cloud-invoke-chain",Yo="x-ts-cloud-trace-id";function Hl(n){return us("sha256").update(n).digest("hex").slice(0,8)}var fn={maxDepth:10,maxRepeats:3,maxInvocationsPerTrace:100,traceWindowMs:60000,breakerThreshold:5,breakerCooldownMs:60000};function Yt(n,i){if(typeof n.get==="function")return n.get(i)??void 0;let s=n;return s[i]??s[i.toLowerCase()]??s[i.toUpperCase()]}function Gl(n,i=64){if(!n)return[];return n.split(".").map((s)=>s.trim()).filter((s)=>/^[0-9a-f]{8}$/.test(s)).slice(-i)}function Vl(n,i=fn){let s=Hl(n.functionId),o=Gl(Yt(n.headers,Xo)),c=n.traceId??Yt(n.headers,Yo)??crypto.randomUUID(),u=[...o,s],d=o.filter((C)=>C===s).length,g=o[o.length-1]===s,y=Number.parseInt(Yt(n.headers,Jo)??"",10),h=Math.max(u.length,Number.isFinite(y)?y+1:0),A="ok";if(h>i.maxDepth)A="depth_exceeded";else if(d>=i.maxRepeats)A="cycle_detected";else if(g&&i.maxRepeats<=1)A="self_invocation";return{reason:A,depth:h,chain:u,traceId:c,selfInvocation:g,repeats:d,propagate:{[Jo]:String(h),[Xo]:u.join("."),[Yo]:c}}}var Yn={ok:"",depth_exceeded:"Invocation chain is deeper than the configured limit; the call was refused to stop a runaway loop.",cycle_detected:"This function already appears in the invocation chain; the call was refused as a recursion loop.",self_invocation:"This function invoked itself directly; the call was refused.",trace_budget_exceeded:"This request has already made more invocations than its budget allows.",breaker_open:"Recursion protection is open for this function after repeated loop detections."};class is{limits;clock;traces=new Map;breakers=new Map;constructor(n=fn,i=()=>Date.now()){this.limits=n;this.clock=i}check(n){let i=this.clock();this.expireTraces(i);let s=Vl(n,this.limits),o=this.breakers.get(n.functionId);if(o?.openUntil!=null&&o.openUntil>i)return this.deny(n.functionId,s,"breaker_open",i,!1);if(s.reason!=="ok")return this.deny(n.functionId,s,s.reason,i,!0);let c=this.traces.get(s.traceId)??{count:0,firstAt:i};if(c.count>=this.limits.maxInvocationsPerTrace)return this.traces.set(s.traceId,c),this.deny(n.functionId,s,"trace_budget_exceeded",i,!0);if(this.traces.set(s.traceId,{count:c.count+1,firstAt:c.firstAt}),o)this.breakers.set(n.functionId,{consecutiveBlocks:0});return{...s,allowed:!0,reason:"ok",propagate:s.propagate}}deny(n,i,s,o,c){if(c){let u=this.breakers.get(n)??{consecutiveBlocks:0},d=u.consecutiveBlocks+1;this.breakers.set(n,{consecutiveBlocks:d,openUntil:d>=this.limits.breakerThreshold?o+this.limits.breakerCooldownMs:u.openUntil})}return{...i,allowed:!1,reason:s,message:Yn[s]}}breakerOpen(n){let i=this.breakers.get(n);return i?.openUntil!=null&&i.openUntil>this.clock()}reset(n){if(n){this.breakers.delete(n);return}this.breakers.clear(),this.traces.clear()}expireTraces(n){if(this.traces.size===0)return;for(let[i,s]of this.traces)if(n-s.firstAt>this.limits.traceWindowMs)this.traces.delete(i)}get trackedTraces(){return this.traces.size}}function Zo(n){return{...n.propagate}}function ea(n){return{status:508,headers:{"content-type":"application/json","x-ts-cloud-recursion-blocked":n.reason},body:{error:"recursion_blocked",reason:n.reason,message:n.message??Yn[n.reason],depth:n.depth,traceId:n.traceId}}}var Of=new ds;function Zn(n){let i=globalThis.process?.env?.[n];if(i==null||i==="")return;return i!=="0"&&i.toLowerCase()!=="false"}function ms(){let n=globalThis.process?.env??{};return n.TS_CLOUD_FUNCTION_ID||n.AWS_LAMBDA_FUNCTION_NAME||n.FUNCTION_NAME||"function"}function fS(n){let i=n===!1?{enabled:!1}:n??{},s=Zn("TS_CLOUD_RECURSION_PROTECTION"),o=Zn("TS_CLOUD_RECURSION_DETECTION_ONLY");return{enabled:s??i.enabled??!0,detectionOnly:o??i.detectionOnly??!1,limits:{...fn,...i.limits},functionId:i.functionId??ms()}}var Me,Ce;function hS(){let n=globalThis.fetch;if(!n||Me===n)return()=>{};Ce=n;let i=async(s,o)=>{let c=Of.getStore();if(!c)return Ce(s,o);let u=new Headers(o?.headers??(s instanceof Request?s.headers:void 0));for(let[d,g]of Object.entries(Zo(c)))u.set(d,g);if(s instanceof Request)return Ce(new Request(s,{headers:u}),o);return Ce(s,{...o,headers:u})};return Object.assign(i,n),globalThis.fetch=i,Me=i,()=>{if(globalThis.fetch===Me&&Ce)globalThis.fetch=Ce;Me=void 0}}var yt,Zt;function AS(n){if(!yt||JSON.stringify(Zt)!==JSON.stringify(n))yt=new is(n),Zt=n;return yt}function NE(){if(yt=void 0,Zt=void 0,Me&&Ce&&globalThis.fetch===Me)globalThis.fetch=Ce;Me=void 0,Ce=void 0}function _f(n,i){let s=fS(i);if(!s.enabled)return;let o=AS(s.limits),c={functionId:s.functionId,headers:n},u=o.check(c);return{verdict:u,blocked:!u.allowed&&!s.detectionOnly,observed:!u.allowed&&s.detectionOnly}}function Lf(n,i){return hS(),Of.run(n,i)}function BE(n){let i=n,s=i?.default??i;if(typeof s==="function")return{fetch:s};return{fetch:s?.fetch??i?.fetch,queue:s?.queue??i?.queue,cli:s?.cli??i?.cli}}var ps=/^(?:text\/|application\/(?:json|xml|javascript|graphql|x-www-form-urlencoded|.*\+json|.*\+xml)|image\/svg)/i;function gs(n){if(!n)return!0;return ps.test(n)}function ys(n){if(n?.maintenance)return n.maintenance;let i=globalThis.process?.env??{};return{enabled:i.MAINTENANCE_MODE==="1"||i.MAINTENANCE_MODE==="true",bypassSecret:i.MAINTENANCE_BYPASS_SECRET}}function yS(n){let i=n.requestContext?.domainName??"localhost",s=n.rawQueryString?`?${n.rawQueryString}`:"",o=`https://${i}${n.rawPath||"/"}${s}`,c=new Headers;for(let[g,y]of Object.entries(n.headers??{}))if(y!==void 0)c.set(g,y);if(n.cookies?.length)c.set("cookie",n.cookies.join("; "));let u=n.requestContext.http.method,d;if(n.body!==void 0&&u!=="GET"&&u!=="HEAD")d=n.isBase64Encoded?new Uint8Array(Buffer.from(n.body,"base64")):new TextEncoder().encode(n.body);return new Request(o,{method:u,headers:c,body:d})}async function $f(n){let i={},s=[],o=typeof n.headers.getSetCookie==="function"?n.headers.getSetCookie():[];for(let d of o)s.push(d);n.headers.forEach((d,g)=>{if(g.toLowerCase()==="set-cookie")return;i[g]=d});let c=Buffer.from(await n.arrayBuffer()),u=gs(n.headers.get("content-type"));return{statusCode:n.status,headers:i,...s.length?{cookies:s}:{},body:u?c.toString("utf-8"):c.toString("base64"),isBase64Encoded:!u}}function SS(n,i){return async(s)=>{if(s.warmer)return{statusCode:200,headers:{"content-type":"text/plain"},body:"warm",isBase64Encoded:!1};if(!n)return{statusCode:501,headers:{"content-type":"text/plain"},body:"No HTTP handler configured",isBase64Encoded:!1};let o=ys(i);if(o.enabled){let d=s.headers?.["x-maintenance-bypass"]??s.cookies?.find((g)=>g.startsWith("tscloud_bypass="))?.split("=")[1];if(!o.bypassSecret||d!==o.bypassSecret)return{statusCode:503,headers:{"content-type":"text/plain","retry-after":"120"},body:"Service temporarily unavailable (maintenance mode)",isBase64Encoded:!1}}let c=_f(s.headers??{},i?.recursionProtection);if(c?.blocked){let d=ea(c.verdict);return{statusCode:d.status,headers:{...d.headers,"retry-after":"60"},body:JSON.stringify(d.body),isBase64Encoded:!1}}let u=yS(s);if(!c){let d=await n(u);return $f(d)}if(c.observed)console.warn(`[ts-cloud] recursion detected (${c.verdict.reason}) at depth ${c.verdict.depth}; detection-only mode let it run`);return Lf(c.verdict,async()=>$f(await n(u)))}}function fs(n){try{return JSON.parse(n)}catch{return n}}function IS(n){return async(i)=>{let s=[];if(i.warmer)return{batchItemFailures:s};if(!n)return{batchItemFailures:s};for(let o of i.Records??[])try{await n(fs(o.body),o)}catch{s.push({itemIdentifier:o.messageId})}return{batchItemFailures:s}}}function bS(n){return async(i)=>{if(i.warmer)return{statusCode:0,output:"warm"};if(!n)return{statusCode:501,output:"No CLI handler configured"};return n(i)}}function xE(n,i){return{http:SS(n.fetch,i),queue:IS(n.queue),cli:bS(n.cli)}}function Mf(n={}){let i=n.socketPath??"/tmp/.tscloud-fpm.sock",s=n.maxChildren??1;return`; ts-cloud php-fpm configuration (generated) — AWS Lambda custom runtime.
7300
+ `}import{execFileSync as yt}from"node:child_process";import{mkdtempSync as sr,readFileSync as ft,rmSync as ar}from"node:fs";import{tmpdir as or}from"node:os";import{dirname as Ls,join as De}from"node:path";import{fileURLToPath as Os}from"node:url";function cr(){return Ls(Os(import.meta.url))}function Gf(){return ft(De(cr(),"runtime.mjs"),"utf-8")}function lr(n){return ft(De(cr(),`${n}-bootstrap`),"utf-8")}function HE(n){let i=n.architecture??"x86_64",s=i==="arm64"?"arm64":"x64",o=n.version.replace(/^v/,""),c=n.onStep??(()=>{}),u=sr(De(or(),"tscloud-node-layer-"));try{let d=o.includes(".")?o:$s(o),g=`node-v${d}-linux-${s}`,y=`https://nodejs.org/dist/v${d}/${g}.tar.xz`;c(`downloading Node ${d} (${i})`);let h=De(u,"node.tar.xz");dr(y,h),c("extracting node binary"),yt("tar",["-xf",h,"-C",u,`${g}/bin/node`],{stdio:"inherit"});let A=ft(De(u,g,"bin","node"));c("packaging layer");let C=[{name:"bootstrap",data:lr("node"),mode:493},{name:"runtime.mjs",data:Gf(),mode:420},{name:"bin/node",data:A,mode:493}];return{zip:ot(C),architecture:i,version:d,fileCount:C.length}}finally{ar(u,{recursive:!0,force:!0})}}function GE(n){let i=n.architecture??"x86_64",s=i==="arm64"?"bun-linux-aarch64":"bun-linux-x64",o=n.version==="latest"?"":n.version.replace(/^v/,""),c=n.onStep??(()=>{}),u=sr(De(or(),"tscloud-bun-layer-"));try{let d=o?`https://github.com/oven-sh/bun/releases/download/bun-v${o}/${s}.zip`:`https://github.com/oven-sh/bun/releases/latest/download/${s}.zip`;c(`downloading Bun ${o||"latest"} (${i})`);let g=De(u,"bun.zip");dr(d,g),c("extracting bun binary"),yt("unzip",["-o","-q",g,"-d",u],{stdio:"inherit"});let y=ft(De(u,s,"bun"));c("packaging layer");let h=[{name:"bootstrap",data:lr("bun"),mode:493},{name:"runtime.mjs",data:Gf(),mode:420},{name:"bin/bun",data:y,mode:493}];return{zip:ot(h),architecture:i,version:o||"latest",fileCount:h.length}}finally{ar(u,{recursive:!0,force:!0})}}function dr(n,i){yt("curl",["-fsSL","-o",i,n],{stdio:["ignore","ignore","inherit"]})}function $s(n){let i=yt("curl",["-fsSL","https://nodejs.org/dist/index.json"],{encoding:"utf-8"}),o=JSON.parse(i).find((c)=>c.version.startsWith(`v${n}.`));if(!o)throw Error(`No Node release found for major version ${n}`);return o.version.replace(/^v/,"")}import{AsyncLocalStorage as Fs}from"node:async_hooks";import{createHash as Bs}from"node:crypto";var sa="x-ts-cloud-invoke-depth",oa="x-ts-cloud-invoke-chain",aa="x-ts-cloud-trace-id";function Xl(n){return Bs("sha256").update(n).digest("hex").slice(0,8)}var An={maxDepth:10,maxRepeats:3,maxInvocationsPerTrace:100,traceWindowMs:60000,breakerThreshold:5,breakerCooldownMs:60000};function nn(n,i){if(typeof n.get==="function")return n.get(i)??void 0;let s=n;return s[i]??s[i.toLowerCase()]??s[i.toUpperCase()]}function Yl(n,i=64){if(!n)return[];return n.split(".").map((s)=>s.trim()).filter((s)=>/^[0-9a-f]{8}$/.test(s)).slice(-i)}function Zl(n,i=An){let s=Xl(n.functionId),o=Yl(nn(n.headers,oa)),c=n.traceId??nn(n.headers,aa)??crypto.randomUUID(),u=[...o,s],d=o.filter((C)=>C===s).length,g=o[o.length-1]===s,y=Number.parseInt(nn(n.headers,sa)??"",10),h=Math.max(u.length,Number.isFinite(y)?y+1:0),A="ok";if(h>i.maxDepth)A="depth_exceeded";else if(d>=i.maxRepeats)A="cycle_detected";else if(g&&i.maxRepeats<=1)A="self_invocation";return{reason:A,depth:h,chain:u,traceId:c,selfInvocation:g,repeats:d,propagate:{[sa]:String(h),[oa]:u.join("."),[aa]:c}}}var br={ok:"",depth_exceeded:"Invocation chain is deeper than the configured limit; the call was refused to stop a runaway loop.",cycle_detected:"This function already appears in the invocation chain; the call was refused as a recursion loop.",self_invocation:"This function invoked itself directly; the call was refused.",trace_budget_exceeded:"This request has already made more invocations than its budget allows.",breaker_open:"Recursion protection is open for this function after repeated loop detections."};class ds{limits;clock;traces=new Map;breakers=new Map;constructor(n=An,i=()=>Date.now()){this.limits=n;this.clock=i}check(n){let i=this.clock();this.expireTraces(i);let s=Zl(n,this.limits),o=this.breakers.get(n.functionId);if(o?.openUntil!=null&&o.openUntil>i)return this.deny(n.functionId,s,"breaker_open",i,!1);if(s.reason!=="ok")return this.deny(n.functionId,s,s.reason,i,!0);let c=this.traces.get(s.traceId)??{count:0,firstAt:i};if(c.count>=this.limits.maxInvocationsPerTrace)return this.traces.set(s.traceId,c),this.deny(n.functionId,s,"trace_budget_exceeded",i,!0);if(this.traces.set(s.traceId,{count:c.count+1,firstAt:c.firstAt}),o)this.breakers.set(n.functionId,{consecutiveBlocks:0});return{...s,allowed:!0,reason:"ok",propagate:s.propagate}}deny(n,i,s,o,c){if(c){let u=this.breakers.get(n)??{consecutiveBlocks:0},d=u.consecutiveBlocks+1;this.breakers.set(n,{consecutiveBlocks:d,openUntil:d>=this.limits.breakerThreshold?o+this.limits.breakerCooldownMs:u.openUntil})}return{...i,allowed:!1,reason:s,message:br[s]}}breakerOpen(n){let i=this.breakers.get(n);return i?.openUntil!=null&&i.openUntil>this.clock()}reset(n){if(n){this.breakers.delete(n);return}this.breakers.clear(),this.traces.clear()}expireTraces(n){if(this.traces.size===0)return;for(let[i,s]of this.traces)if(n-s.firstAt>this.limits.traceWindowMs)this.traces.delete(i)}get trackedTraces(){return this.traces.size}}function ca(n){return{...n.propagate}}function da(n){return{status:508,headers:{"content-type":"application/json","x-ts-cloud-recursion-blocked":n.reason},body:{error:"recursion_blocked",reason:n.reason,message:n.message??br[n.reason],depth:n.depth,traceId:n.traceId}}}var Vf=new Fs;function Sr(n){let i=globalThis.process?.env?.[n];if(i==null||i==="")return;return i!=="0"&&i.toLowerCase()!=="false"}function Gs(){let n=globalThis.process?.env??{};return n.TS_CLOUD_FUNCTION_ID||n.AWS_LAMBDA_FUNCTION_NAME||n.FUNCTION_NAME||"function"}function RS(n){let i=n===!1?{enabled:!1}:n??{},s=Sr("TS_CLOUD_RECURSION_PROTECTION"),o=Sr("TS_CLOUD_RECURSION_DETECTION_ONLY");return{enabled:s??i.enabled??!0,detectionOnly:o??i.detectionOnly??!1,limits:{...An,...i.limits},functionId:i.functionId??Gs()}}var Oe,Re;function DS(){let n=globalThis.fetch;if(!n||Oe===n)return()=>{};Re=n;let i=async(s,o)=>{let c=Vf.getStore();if(!c)return Re(s,o);let u=new Headers(o?.headers??(s instanceof Request?s.headers:void 0));for(let[d,g]of Object.entries(ca(c)))u.set(d,g);if(s instanceof Request)return Re(new Request(s,{headers:u}),o);return Re(s,{...o,headers:u})};return Object.assign(i,n),globalThis.fetch=i,Oe=i,()=>{if(globalThis.fetch===Oe&&Re)globalThis.fetch=Re;Oe=void 0}}var ht,rn;function PS(n){if(!ht||JSON.stringify(rn)!==JSON.stringify(n))ht=new ds(n),rn=n;return ht}function VE(){if(ht=void 0,rn=void 0,Oe&&Re&&globalThis.fetch===Oe)globalThis.fetch=Re;Oe=void 0,Re=void 0}function qf(n,i){let s=RS(i);if(!s.enabled)return;let o=PS(s.limits),c={functionId:s.functionId,headers:n},u=o.check(c);return{verdict:u,blocked:!u.allowed&&!s.detectionOnly,observed:!u.allowed&&s.detectionOnly}}function jf(n,i){return DS(),Vf.run(n,i)}function qE(n){let i=n,s=i?.default??i;if(typeof s==="function")return{fetch:s};return{fetch:s?.fetch??i?.fetch,queue:s?.queue??i?.queue,cli:s?.cli??i?.cli}}var _s=/^(?:text\/|application\/(?:json|xml|javascript|graphql|x-www-form-urlencoded|.*\+json|.*\+xml)|image\/svg)/i;function Ws(n){if(!n)return!0;return _s.test(n)}function Vs(n){if(n?.maintenance)return n.maintenance;let i=globalThis.process?.env??{};return{enabled:i.MAINTENANCE_MODE==="1"||i.MAINTENANCE_MODE==="true",bypassSecret:i.MAINTENANCE_BYPASS_SECRET}}function kS(n){let i=n.requestContext?.domainName??"localhost",s=n.rawQueryString?`?${n.rawQueryString}`:"",o=`https://${i}${n.rawPath||"/"}${s}`,c=new Headers;for(let[g,y]of Object.entries(n.headers??{}))if(y!==void 0)c.set(g,y);if(n.cookies?.length)c.set("cookie",n.cookies.join("; "));let u=n.requestContext.http.method,d;if(n.body!==void 0&&u!=="GET"&&u!=="HEAD")d=n.isBase64Encoded?new Uint8Array(Buffer.from(n.body,"base64")):new TextEncoder().encode(n.body);return new Request(o,{method:u,headers:c,body:d})}async function zf(n){let i={},s=[],o=typeof n.headers.getSetCookie==="function"?n.headers.getSetCookie():[];for(let d of o)s.push(d);n.headers.forEach((d,g)=>{if(g.toLowerCase()==="set-cookie")return;i[g]=d});let c=Buffer.from(await n.arrayBuffer()),u=Ws(n.headers.get("content-type"));return{statusCode:n.status,headers:i,...s.length?{cookies:s}:{},body:u?c.toString("utf-8"):c.toString("base64"),isBase64Encoded:!u}}function NS(n,i){return async(s)=>{if(s.warmer)return{statusCode:200,headers:{"content-type":"text/plain"},body:"warm",isBase64Encoded:!1};if(!n)return{statusCode:501,headers:{"content-type":"text/plain"},body:"No HTTP handler configured",isBase64Encoded:!1};let o=Vs(i);if(o.enabled){let d=s.headers?.["x-maintenance-bypass"]??s.cookies?.find((g)=>g.startsWith("tscloud_bypass="))?.split("=")[1];if(!o.bypassSecret||d!==o.bypassSecret)return{statusCode:503,headers:{"content-type":"text/plain","retry-after":"120"},body:"Service temporarily unavailable (maintenance mode)",isBase64Encoded:!1}}let c=qf(s.headers??{},i?.recursionProtection);if(c?.blocked){let d=da(c.verdict);return{statusCode:d.status,headers:{...d.headers,"retry-after":"60"},body:JSON.stringify(d.body),isBase64Encoded:!1}}let u=kS(s);if(!c){let d=await n(u);return zf(d)}if(c.observed)console.warn(`[ts-cloud] recursion detected (${c.verdict.reason}) at depth ${c.verdict.depth}; detection-only mode let it run`);return jf(c.verdict,async()=>zf(await n(u)))}}function Us(n){try{return JSON.parse(n)}catch{return n}}function BS(n){return async(i)=>{let s=[];if(i.warmer)return{batchItemFailures:s};if(!n)return{batchItemFailures:s};for(let o of i.Records??[])try{await n(Us(o.body),o)}catch{s.push({itemIdentifier:o.messageId})}return{batchItemFailures:s}}}function xS(n){return async(i)=>{if(i.warmer)return{statusCode:0,output:"warm"};if(!n)return{statusCode:501,output:"No CLI handler configured"};return n(i)}}function jE(n,i){return{http:NS(n.fetch,i),queue:BS(n.queue),cli:xS(n.cli)}}function Kf(n={}){let i=n.socketPath??"/tmp/.tscloud-fpm.sock",s=n.maxChildren??1;return`; ts-cloud php-fpm configuration (generated) — AWS Lambda custom runtime.
7303
7301
  [global]
7304
7302
  daemonize = no
7305
7303
  error_log = ${n.errorLog??"/tmp/storage/logs/php-fpm.log"}
@@ -7316,4 +7314,4 @@ decorate_workers_output = no
7316
7314
  php_admin_value[error_log] = /dev/stderr
7317
7315
  php_admin_flag[log_errors] = on
7318
7316
  clear_env = no
7319
- `}import{readFileSync as hs}from"node:fs";import{dirname as bs,join as Xn}from"node:path";import{fileURLToPath as Ss}from"node:url";function As(){return Xn(bs(Ss(import.meta.url)),"runtime-assets")}function hn(){let n=As(),i=(s)=>hs(Xn(n,s),"utf-8");return[{path:"bootstrap",contents:i("bootstrap"),mode:493},{path:"tscloud/runtime.php",contents:i("runtime.php"),mode:420},{path:"tscloud/octane-runtime.php",contents:i("octane-runtime.php"),mode:420},{path:"tscloud/cli-runtime.php",contents:i("cli-runtime.php"),mode:420},{path:"tscloud/fastcgi-client.php",contents:i("fastcgi-client.php"),mode:420},{path:"tscloud/php-fpm.conf",contents:Mf(),mode:420}]}function ql(n={}){let i=n.cacheDriver??"dynamodb";return{APP_ENV:"production",LOG_CHANNEL:"stderr",CACHE_STORE:i,CACHE_DRIVER:i,SESSION_DRIVER:i,QUEUE_CONNECTION:"sqs",FILESYSTEM_DISK:"s3",VIEW_COMPILED_PATH:"/tmp/storage/framework/views",APP_SERVICES_CACHE:"/tmp/bootstrap/cache/services.php",APP_PACKAGES_CACHE:"/tmp/bootstrap/cache/packages.php",APP_CONFIG_CACHE:"/tmp/bootstrap/cache/config.php",APP_ROUTES_CACHE:"/tmp/bootstrap/cache/routes.php",APP_EVENTS_CACHE:"/tmp/bootstrap/cache/events.php"}}var Ff=["composer install --no-dev --optimize-autoloader --no-interaction","php artisan config:cache","php artisan route:cache","php artisan event:cache","php artisan view:cache"];import{execFileSync as ft}from"node:child_process";import{existsSync as Cs,mkdirSync as vs,mkdtempSync as Ts,readdirSync as Rs,readFileSync as Ps,rmSync as Es,statSync as er,writeFileSync as ws}from"node:fs";import{tmpdir as Is}from"node:os";import{join as Ge,relative as Ds}from"node:path";function*tr(n){for(let i of Rs(n)){let s=Ge(n,i);if(er(s).isDirectory())yield*tr(s);else yield s}}function OE(n={}){let i=n.architecture??"x86_64",s=n.platform??(i==="arm64"?"linux/arm64":"linux/amd64"),o=n.onStep??(()=>{}),c=Ts(Ge(Is(),"tscloud-php-layer-")),u="tscloud-php-layer:build";try{ws(Ge(c,"Dockerfile"),Bf(n)),o("Building PHP runtime image (docker)"),ft("docker",["build","--platform",s,"-t","tscloud-php-layer:build",c],{stdio:"inherit"}),o("Extracting /opt/php from image");let d=ft("docker",["create","--platform",s,"tscloud-php-layer:build"],{encoding:"utf-8"}).trim(),g=Ge(c,"opt");vs(g,{recursive:!0});try{ft("docker",["cp",`${d}:/opt/php`,Ge(g,"php")],{stdio:"inherit"})}finally{ft("docker",["rm",d],{stdio:"ignore"})}if(!Cs(Ge(g,"php","bin","php")))throw Error("layer build produced no /opt/php/bin/php");let y=[];for(let v of tr(g)){let T=Ds(g,v).replace(/\\/g,"/"),R=er(v).mode&73?493:420;y.push({name:T,data:Ps(v),mode:R})}o("Injecting runtime assets");let h=new Set(hn().map((v)=>v.path)),A=y.filter((v)=>!h.has(v.name));for(let v of hn())A.push({name:v.path,data:v.contents,mode:v.mode});return o("Packaging layer ZIP"),{zip:it(A),architecture:i,fileCount:A.length}}finally{Es(c,{recursive:!0,force:!0})}}import{execSync as Ns}from"node:child_process";import{createHash as xs}from"node:crypto";import{readdirSync as ks,readFileSync as Ms,statSync as nr}from"node:fs";import{join as Ls,relative as rr,resolve as Xt}from"node:path";var CS=[".git",".github","node_modules","tests","storage/logs","storage/framework/cache","storage/framework/sessions","storage/framework/views",".env",".env.local",".vapor",".ts-cloud","dist-lambda"];function Os(n,i){return i.some((s)=>n===s||n.startsWith(`${s}/`))}function*ir(n,i,s){for(let o of ks(n)){let c=Ls(n,o),u=rr(i,c).replace(/\\/g,"/");if(Os(u,s))continue;if(nr(c).isDirectory())yield*ir(c,i,s);else yield c}}function ta(n){if(n.skipBuild)return;let i=Xt(n.projectRoot??process.cwd()),s=n.app.build??Ff;for(let o of s)n.onStep?.(`build: ${o}`),Ns(o,{stdio:"inherit",cwd:i})}function ra(n,i=[]){let s=Xt(n),o=[...CS,dn(),...i],c=[];for(let u of ir(s,s,o)){let d=rr(s,u).replace(/\\/g,"/"),g=(nr(u).mode&73)!==0;c.push({name:d,data:Ms(u),mode:g?493:420})}return c}function jl(n){let i=Xt(n.projectRoot??process.cwd());ta(n),n.onStep?.("packaging application tree");let s=ra(i,n.exclude);if(!s.length)throw Error(`No files to package under ${i}`);let o=it(s),c=n.app.handlers?.http??"public/index.php";return{zip:o,sha256:xs("sha256").update(o).digest("hex"),handlers:{http:c,queue:n.app.handlers?.queue??c,cli:n.app.handlers?.cli??c},fileCount:s.length}}class Uf{optimizations=new Map;imageConfigs=new Map;ssgConfigs=new Map;prerenderConfigs=new Map;counter=0;createAssetOptimization(n){let i=`asset-opt-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.optimizations.set(i,s),s}createImageOptimization(n){let i=`image-opt-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.imageConfigs.set(i,s),s}createSSGConfig(n){let i=`ssg-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.ssgConfigs.set(i,s),s}createPrerenderConfig(n){let i=`prerender-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.prerenderConfigs.set(i,s),s}listOptimizations(){return Array.from(this.optimizations.values())}listImageConfigs(){return Array.from(this.imageConfigs.values())}clear(){this.optimizations.clear(),this.imageConfigs.clear(),this.ssgConfigs.clear(),this.prerenderConfigs.clear()}}var _E=new Uf;class zl{policies=new Map;versioningConfigs=new Map;replicationRules=new Map;tieringConfigs=new Map;objectLocks=new Map;transferAcceleration=new Map;accessPoints=new Map;glacierConfigs=new Map;inventories=new Map;batchOps=new Map;eventNotifications=new Map;counter=0;createLifecyclePolicy(n,i){let s=`lifecycle-${Date.now()}-${this.counter++}`,o={id:s,transitions:n,expiration:i};return this.policies.set(s,o),o}enableVersioning(n=!1){let i=`versioning-${Date.now()}-${this.counter++}`,s={id:i,enabled:!0,mfaDelete:n};return this.versioningConfigs.set(i,s),s}createReplicationRule(n,i,s){let o=`replication-${Date.now()}-${this.counter++}`,c={id:o,sourceRegion:n,destRegion:i,destBucket:s};return this.replicationRules.set(o,c),c}createIntelligentTiering(n,i){let s=`tiering-${Date.now()}-${this.counter++}`,o={id:s,archiveDays:n,deepArchiveDays:i};return this.tieringConfigs.set(s,o),o}enableObjectLock(n){let i=`object-lock-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,mode:n.mode||"COMPLIANCE",retentionDays:n.retentionDays,retentionYears:n.retentionYears,legalHoldEnabled:n.legalHoldEnabled||!1};return this.objectLocks.set(i,s),s}enableTransferAcceleration(n){let i=`transfer-accel-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n,enabled:!0,endpoint:`${n}.s3-accelerate.amazonaws.com`};return this.transferAcceleration.set(i,s),s}createAccessPoint(n){let i=`access-point-${Date.now()}-${this.counter++}`,s={id:i,name:n.name,bucketName:n.bucketName,vpcId:n.vpcId,publicAccessBlock:n.publicAccessBlock!==!1,policy:n.policy};return this.accessPoints.set(i,s),s}createGlacierArchive(n){let i=`glacier-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,archiveType:n.archiveType,transitionDays:n.transitionDays,restoreConfig:n.restoreTier?{tier:n.restoreTier,days:n.restoreDays||7}:void 0};return this.glacierConfigs.set(i,s),s}createInventory(n){let i=`inventory-${Date.now()}-${this.counter++}`,s={id:i,sourceBucket:n.sourceBucket,destinationBucket:n.destinationBucket,schedule:n.schedule||"Daily",format:n.format||"CSV",includedFields:n.includedFields||["Size","LastModifiedDate","StorageClass","ETag"],prefix:n.prefix};return this.inventories.set(i,s),s}createBatchOperation(n){let i=`batch-op-${Date.now()}-${this.counter++}`,s={id:i,operation:n.operation,manifestBucket:n.manifestBucket,manifestKey:n.manifestKey,priority:n.priority||10,status:"pending"};return this.batchOps.set(i,s),s}executeBatchOperation(n){let i=this.batchOps.get(n);if(!i)throw Error(`Batch operation not found: ${n}`);return i.status="in_progress",i.totalObjects=1000,i.processedObjects=0,i}getBatchOperationStatus(n){return this.batchOps.get(n)}createLambdaNotification(n){let i=`event-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,events:n.events,destination:{type:"Lambda",arn:n.lambdaArn},filter:n.prefix||n.suffix?{prefix:n.prefix,suffix:n.suffix}:void 0};return this.eventNotifications.set(i,s),s}createSQSNotification(n){let i=`event-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,events:n.events,destination:{type:"SQS",arn:n.queueArn},filter:n.prefix||n.suffix?{prefix:n.prefix,suffix:n.suffix}:void 0};return this.eventNotifications.set(i,s),s}createSNSNotification(n){let i=`event-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,events:n.events,destination:{type:"SNS",arn:n.topicArn},filter:n.prefix||n.suffix?{prefix:n.prefix,suffix:n.suffix}:void 0};return this.eventNotifications.set(i,s),s}generateObjectLockCF(n){let i={ObjectLockEnabled:"Enabled",ObjectLockConfiguration:{ObjectLockEnabled:"Enabled",Rule:{DefaultRetention:{Mode:n.mode}}}};if(n.retentionDays)i.ObjectLockConfiguration.Rule.DefaultRetention.Days=n.retentionDays;if(n.retentionYears)i.ObjectLockConfiguration.Rule.DefaultRetention.Years=n.retentionYears;return i}generateTransferAccelerationCF(n){return{AccelerateConfiguration:{AccelerationStatus:n.enabled?"Enabled":"Suspended"}}}generateAccessPointCF(n){return{Type:"AWS::S3::AccessPoint",Properties:{Name:n.name,Bucket:n.bucketName,...n.vpcId&&{VpcConfiguration:{VpcId:n.vpcId}},PublicAccessBlockConfiguration:n.publicAccessBlock?{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}:void 0,...n.policy&&{Policy:n.policy}}}}generateInventoryCF(n){return{Type:"AWS::S3::Bucket",Properties:{InventoryConfigurations:[{Id:n.id,Destination:{BucketArn:`arn:aws:s3:::${n.destinationBucket}`,Format:n.format},Enabled:!0,IncludedObjectVersions:"Current",OptionalFields:n.includedFields,ScheduleFrequency:n.schedule,...n.prefix&&{Prefix:n.prefix}}]}}}generateEventNotificationCF(n){let i=n.destination.type==="Lambda"?"LambdaConfigurations":n.destination.type==="SQS"?"QueueConfigurations":"TopicConfigurations",s=n.destination.type==="Lambda"?"Function":n.destination.type==="SQS"?"Queue":"Topic",o={Event:n.events[0],[s]:n.destination.arn};if(n.filter)o.Filter={S3Key:{Rules:[...n.filter.prefix?[{Name:"prefix",Value:n.filter.prefix}]:[],...n.filter.suffix?[{Name:"suffix",Value:n.filter.suffix}]:[]]}};return{NotificationConfiguration:{[i]:[o]}}}clear(){this.policies.clear(),this.versioningConfigs.clear(),this.replicationRules.clear(),this.tieringConfigs.clear(),this.objectLocks.clear(),this.transferAcceleration.clear(),this.accessPoints.clear(),this.glacierConfigs.clear(),this.inventories.clear(),this.batchOps.clear(),this.eventNotifications.clear()}}var ES=new zl;class Qf{checks=new Map;synthetics=new Map;uptimeTrackers=new Map;counter=0;createHealthCheck(n,i=30,s=10){let o=`health-${Date.now()}-${this.counter++}`,c={id:o,url:n,interval:i,timeout:s,status:"healthy"};return this.checks.set(o,c),c}createSyntheticMonitor(n,i,s,o){let c=`synthetic-${Date.now()}-${this.counter++}`,u={id:c,name:n,script:i,frequency:s,locations:o};return this.synthetics.set(c,u),u}trackUptime(n,i,s){let o=`uptime-${Date.now()}-${this.counter++}`,c=i/(i+s)*100,u={id:o,resource:n,uptime:i,downtime:s,availability:c};return this.uptimeTrackers.set(o,u),u}clear(){this.checks.clear(),this.synthetics.clear(),this.uptimeTrackers.clear()}}var LE=new Qf;class Hf{wafRules=new Map;shieldProtections=new Map;securityGroups=new Map;nacls=new Map;counter=0;createWAFRule(n,i,s,o){let c=`waf-${Date.now()}-${this.counter++}`,u={id:c,name:n,priority:i,action:s,conditions:o};return this.wafRules.set(c,u),u}enableShield(n,i="standard"){let s=`shield-${Date.now()}-${this.counter++}`,o={id:s,resourceArn:n,protectionType:i};return this.shieldProtections.set(s,o),o}createSecurityGroup(n,i,s){let o=`sg-${Date.now()}-${this.counter++}`,c={id:o,name:n,vpcId:i,rules:s};return this.securityGroups.set(o,c),c}createNACL(n,i){let s=`nacl-${Date.now()}-${this.counter++}`,o={id:s,vpcId:n,rules:i};return this.nacls.set(s,o),o}clear(){this.wafRules.clear(),this.shieldProtections.clear(),this.securityGroups.clear(),this.nacls.clear()}}var $E=new Hf;class Gf{strategies=new Map;allocations=new Map;groups=new Map;counter=0;createTaggingStrategy(n,i){let s=`tagging-${Date.now()}-${this.counter++}`,o={id:s,tags:n,resources:i};return this.strategies.set(s,o),o}createCostAllocation(n,i){let s=`cost-${Date.now()}-${this.counter++}`,o={id:s,tagKey:n,allocations:i};return this.allocations.set(s,o),o}createResourceGroup(n,i,s){let o=`group-${Date.now()}-${this.counter++}`,c={id:o,name:n,query:{resourceTypeFilters:i,tagFilters:s}};return this.groups.set(o,c),c}clear(){this.strategies.clear(),this.allocations.clear(),this.groups.clear()}}var ME=new Gf;export{$I,MI,rl,Sm,nl,il,dn,Q,l,sl,Im,K,ol,p,ry,b,Ze,Ji,ln,w,de,al,ny,r,t,FI,UI,m,QI,HI,GI,VI,qI,lr,cl,Xi,iy,jI,zI,xe,et,dl,bm,Cm,KI,Em,vm,Tm,Ho,ll,le,un,kt,Go,Nt,Ee,sy,ul,Vo,wm,Rm,Dm,Pm,gl,WI,W,E,oy,ay,km,a,S,tt,f,Nm,rt,J,Bt,JI,Bm,X,pl,Oe,ur,qo,ue,ml,ge,cy,jo,Y,Z,_,Yi,D,gr,xt,ee,e,gn,XI,xm,fl,YI,ZI,eb,tb,hl,rb,nb,ib,sb,ob,ab,cb,db,lb,ub,gb,pb,dy,ly,uy,gy,py,my,fy,pr,Om,_m,mr,Zi,mb,Lm,fb,hb,pn,Ab,yb,Sb,Ib,bb,Cb,hy,Ay,yy,Sy,Iy,es,Eb,zo,by,$m,V,Cy,nt,Ko,Ot,Ey,Mm,vy,Ty,wy,Fm,q,vb,Tb,wb,Rb,Ry,Db,te,Pb,kb,Nb,Al,yl,Dy,Um,Qm,Bb,xb,Ob,_b,Lb,Py,Sl,$b,Mb,Fb,Ub,Qb,ky,Ny,Hb,Gb,Vb,qb,jb,zb,Kb,By,Wb,Hm,Il,Jb,Xb,Yb,Zb,Gm,Vm,qm,eC,bl,xy,Oy,_y,Ly,Cl,$y,tC,rC,nC,iC,sC,oC,aC,My,Fy,Uy,Qy,jm,cC,dC,lC,uC,gC,pC,mC,fC,hC,Hy,Gy,Vy,qy,AC,yC,zm,SC,Km,Wm,Jm,Xm,IC,bC,CC,EC,_e,ts,vC,TC,wC,RC,DC,PC,kC,NC,jy,BC,xC,Ym,Zm,OC,_C,zy,LC,$C,MC,FC,UC,QC,HC,GC,VC,qC,jC,zC,KC,WC,JC,XC,YC,ZC,eE,tE,rE,El,Ky,vl,Wy,Tl,Jy,wl,Xy,Rl,Yy,fr,Zy,Dl,eS,rs,tS,Pl,rS,kl,nS,ef,nE,tf,iE,Nl,iS,hr,sS,rf,sE,Bl,oS,nf,oE,sf,aE,of,cE,xl,aS,af,dE,cf,lE,df,uE,lf,gE,Ol,cS,_l,dS,uf,pE,gf,mE,pf,fE,mf,hE,ff,AE,hf,yE,Ll,lS,Af,SE,yf,IE,Sf,bE,If,CE,bf,EE,Cf,vE,Ef,vf,Tf,wf,Rf,TE,Df,wE,Pf,RE,kf,DE,it,Nf,uS,Wo,$l,mn,gS,ns,Ar,Ml,Fl,pS,mS,Ul,Bf,Ql,xf,PE,kE,Jo,Xo,Yo,Hl,fn,Gl,Vl,is,Zo,ea,Of,fS,hS,AS,NE,_f,Lf,BE,yS,$f,SS,IS,bS,xE,Mf,hn,ql,Ff,OE,CS,ta,ra,jl,Uf,_E,zl,ES,Qf,LE,Hf,$E,Gf,ME};
7317
+ `}import{readFileSync as Hs}from"node:fs";import{dirname as js,join as Cr}from"node:path";import{fileURLToPath as Ks}from"node:url";function qs(){return Cr(js(Ks(import.meta.url)),"runtime-assets")}function yn(){let n=qs(),i=(s)=>Hs(Cr(n,s),"utf-8");return[{path:"bootstrap",contents:i("bootstrap"),mode:493},{path:"tscloud/runtime.php",contents:i("runtime.php"),mode:420},{path:"tscloud/octane-runtime.php",contents:i("octane-runtime.php"),mode:420},{path:"tscloud/cli-runtime.php",contents:i("cli-runtime.php"),mode:420},{path:"tscloud/fastcgi-client.php",contents:i("fastcgi-client.php"),mode:420},{path:"tscloud/php-fpm.conf",contents:Kf(),mode:420}]}function eu(n={}){let i=n.cacheDriver??"dynamodb";return{APP_ENV:"production",LOG_CHANNEL:"stderr",CACHE_STORE:i,CACHE_DRIVER:i,SESSION_DRIVER:i,QUEUE_CONNECTION:"sqs",FILESYSTEM_DISK:"s3",VIEW_COMPILED_PATH:"/tmp/storage/framework/views",APP_SERVICES_CACHE:"/tmp/bootstrap/cache/services.php",APP_PACKAGES_CACHE:"/tmp/bootstrap/cache/packages.php",APP_CONFIG_CACHE:"/tmp/bootstrap/cache/config.php",APP_ROUTES_CACHE:"/tmp/bootstrap/cache/routes.php",APP_EVENTS_CACHE:"/tmp/bootstrap/cache/events.php"}}var Wf=["composer install --no-dev --optimize-autoloader --no-interaction","php artisan config:cache","php artisan route:cache","php artisan event:cache","php artisan view:cache"];import{execFileSync as bt}from"node:child_process";import{existsSync as zs,mkdirSync as Qs,mkdtempSync as Js,readdirSync as Ys,readFileSync as Zs,rmSync as Xs,statSync as vr,writeFileSync as ma}from"node:fs";import{tmpdir as pa}from"node:os";import{join as Ve,relative as ya}from"node:path";function*Tr(n){for(let i of Ys(n)){let s=Ve(n,i);if(vr(s).isDirectory())yield*Tr(s);else yield s}}function zE(n={}){let i=n.architecture??"x86_64",s=n.platform??(i==="arm64"?"linux/arm64":"linux/amd64"),o=n.onStep??(()=>{}),c=Js(Ve(pa(),"tscloud-php-layer-")),u="tscloud-php-layer:build";try{ma(Ve(c,"Dockerfile"),Hf(n)),o("Building PHP runtime image (docker)"),bt("docker",["build","--platform",s,"-t","tscloud-php-layer:build",c],{stdio:"inherit"}),o("Extracting /opt/php from image");let d=bt("docker",["create","--platform",s,"tscloud-php-layer:build"],{encoding:"utf-8"}).trim(),g=Ve(c,"opt");Qs(g,{recursive:!0});try{bt("docker",["cp",`${d}:/opt/php`,Ve(g,"php")],{stdio:"inherit"})}finally{bt("docker",["rm",d],{stdio:"ignore"})}if(!zs(Ve(g,"php","bin","php")))throw Error("layer build produced no /opt/php/bin/php");let y=[];for(let v of Tr(g)){let T=ya(g,v).replace(/\\/g,"/"),R=vr(v).mode&73?493:420;y.push({name:T,data:Zs(v),mode:R})}o("Injecting runtime assets");let h=new Set(yn().map((v)=>v.path)),A=y.filter((v)=>!h.has(v.name));for(let v of yn())A.push({name:v.path,data:v.contents,mode:v.mode});return o("Packaging layer ZIP"),{zip:ot(A),architecture:i,fileCount:A.length}}finally{Xs(c,{recursive:!0,force:!0})}}import{execSync as fa}from"node:child_process";import{createHash as ha}from"node:crypto";import{readdirSync as ba,readFileSync as Sa,statSync as Rr}from"node:fs";import{join as Aa,relative as Pr,resolve as sn}from"node:path";var OS=[".git",".github","node_modules","tests","storage/logs","storage/framework/cache","storage/framework/sessions","storage/framework/views",".env",".env.local",".vapor",".ts-cloud","dist-lambda"];function Ca(n,i){return i.some((s)=>n===s||n.startsWith(`${s}/`))}function*Er(n,i,s){for(let o of ba(n)){let c=Aa(n,o),u=Pr(i,c).replace(/\\/g,"/");if(Ca(u,s))continue;if(Rr(c).isDirectory())yield*Er(c,i,s);else yield c}}function la(n){if(n.skipBuild)return;let i=sn(n.projectRoot??process.cwd()),s=n.app.build??Wf;for(let o of s)n.onStep?.(`build: ${o}`),fa(o,{stdio:"inherit",cwd:i})}function ua(n,i=[]){let s=sn(n),o=[...OS,ln(),...i],c=[];for(let u of Er(s,s,o)){let d=Pr(s,u).replace(/\\/g,"/"),g=(Rr(u).mode&73)!==0;c.push({name:d,data:Sa(u),mode:g?493:420})}return c}function tu(n){let i=sn(n.projectRoot??process.cwd());la(n),n.onStep?.("packaging application tree");let s=ua(i,n.exclude);if(!s.length)throw Error(`No files to package under ${i}`);let o=ot(s),c=n.app.handlers?.http??"public/index.php";return{zip:o,sha256:ha("sha256").update(o).digest("hex"),handlers:{http:c,queue:n.app.handlers?.queue??c,cli:n.app.handlers?.cli??c},fileCount:s.length}}class Jf{optimizations=new Map;imageConfigs=new Map;ssgConfigs=new Map;prerenderConfigs=new Map;counter=0;createAssetOptimization(n){let i=`asset-opt-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.optimizations.set(i,s),s}createImageOptimization(n){let i=`image-opt-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.imageConfigs.set(i,s),s}createSSGConfig(n){let i=`ssg-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.ssgConfigs.set(i,s),s}createPrerenderConfig(n){let i=`prerender-${Date.now()}-${this.counter++}`,s={id:i,...n};return this.prerenderConfigs.set(i,s),s}listOptimizations(){return Array.from(this.optimizations.values())}listImageConfigs(){return Array.from(this.imageConfigs.values())}clear(){this.optimizations.clear(),this.imageConfigs.clear(),this.ssgConfigs.clear(),this.prerenderConfigs.clear()}}var KE=new Jf;class ru{policies=new Map;versioningConfigs=new Map;replicationRules=new Map;tieringConfigs=new Map;objectLocks=new Map;transferAcceleration=new Map;accessPoints=new Map;glacierConfigs=new Map;inventories=new Map;batchOps=new Map;eventNotifications=new Map;counter=0;createLifecyclePolicy(n,i){let s=`lifecycle-${Date.now()}-${this.counter++}`,o={id:s,transitions:n,expiration:i};return this.policies.set(s,o),o}enableVersioning(n=!1){let i=`versioning-${Date.now()}-${this.counter++}`,s={id:i,enabled:!0,mfaDelete:n};return this.versioningConfigs.set(i,s),s}createReplicationRule(n,i,s){let o=`replication-${Date.now()}-${this.counter++}`,c={id:o,sourceRegion:n,destRegion:i,destBucket:s};return this.replicationRules.set(o,c),c}createIntelligentTiering(n,i){let s=`tiering-${Date.now()}-${this.counter++}`,o={id:s,archiveDays:n,deepArchiveDays:i};return this.tieringConfigs.set(s,o),o}enableObjectLock(n){let i=`object-lock-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,mode:n.mode||"COMPLIANCE",retentionDays:n.retentionDays,retentionYears:n.retentionYears,legalHoldEnabled:n.legalHoldEnabled||!1};return this.objectLocks.set(i,s),s}enableTransferAcceleration(n){let i=`transfer-accel-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n,enabled:!0,endpoint:`${n}.s3-accelerate.amazonaws.com`};return this.transferAcceleration.set(i,s),s}createAccessPoint(n){let i=`access-point-${Date.now()}-${this.counter++}`,s={id:i,name:n.name,bucketName:n.bucketName,vpcId:n.vpcId,publicAccessBlock:n.publicAccessBlock!==!1,policy:n.policy};return this.accessPoints.set(i,s),s}createGlacierArchive(n){let i=`glacier-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,archiveType:n.archiveType,transitionDays:n.transitionDays,restoreConfig:n.restoreTier?{tier:n.restoreTier,days:n.restoreDays||7}:void 0};return this.glacierConfigs.set(i,s),s}createInventory(n){let i=`inventory-${Date.now()}-${this.counter++}`,s={id:i,sourceBucket:n.sourceBucket,destinationBucket:n.destinationBucket,schedule:n.schedule||"Daily",format:n.format||"CSV",includedFields:n.includedFields||["Size","LastModifiedDate","StorageClass","ETag"],prefix:n.prefix};return this.inventories.set(i,s),s}createBatchOperation(n){let i=`batch-op-${Date.now()}-${this.counter++}`,s={id:i,operation:n.operation,manifestBucket:n.manifestBucket,manifestKey:n.manifestKey,priority:n.priority||10,status:"pending"};return this.batchOps.set(i,s),s}executeBatchOperation(n){let i=this.batchOps.get(n);if(!i)throw Error(`Batch operation not found: ${n}`);return i.status="in_progress",i.totalObjects=1000,i.processedObjects=0,i}getBatchOperationStatus(n){return this.batchOps.get(n)}createLambdaNotification(n){let i=`event-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,events:n.events,destination:{type:"Lambda",arn:n.lambdaArn},filter:n.prefix||n.suffix?{prefix:n.prefix,suffix:n.suffix}:void 0};return this.eventNotifications.set(i,s),s}createSQSNotification(n){let i=`event-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,events:n.events,destination:{type:"SQS",arn:n.queueArn},filter:n.prefix||n.suffix?{prefix:n.prefix,suffix:n.suffix}:void 0};return this.eventNotifications.set(i,s),s}createSNSNotification(n){let i=`event-${Date.now()}-${this.counter++}`,s={id:i,bucketName:n.bucketName,events:n.events,destination:{type:"SNS",arn:n.topicArn},filter:n.prefix||n.suffix?{prefix:n.prefix,suffix:n.suffix}:void 0};return this.eventNotifications.set(i,s),s}generateObjectLockCF(n){let i={ObjectLockEnabled:"Enabled",ObjectLockConfiguration:{ObjectLockEnabled:"Enabled",Rule:{DefaultRetention:{Mode:n.mode}}}};if(n.retentionDays)i.ObjectLockConfiguration.Rule.DefaultRetention.Days=n.retentionDays;if(n.retentionYears)i.ObjectLockConfiguration.Rule.DefaultRetention.Years=n.retentionYears;return i}generateTransferAccelerationCF(n){return{AccelerateConfiguration:{AccelerationStatus:n.enabled?"Enabled":"Suspended"}}}generateAccessPointCF(n){return{Type:"AWS::S3::AccessPoint",Properties:{Name:n.name,Bucket:n.bucketName,...n.vpcId&&{VpcConfiguration:{VpcId:n.vpcId}},PublicAccessBlockConfiguration:n.publicAccessBlock?{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}:void 0,...n.policy&&{Policy:n.policy}}}}generateInventoryCF(n){return{Type:"AWS::S3::Bucket",Properties:{InventoryConfigurations:[{Id:n.id,Destination:{BucketArn:`arn:aws:s3:::${n.destinationBucket}`,Format:n.format},Enabled:!0,IncludedObjectVersions:"Current",OptionalFields:n.includedFields,ScheduleFrequency:n.schedule,...n.prefix&&{Prefix:n.prefix}}]}}}generateEventNotificationCF(n){let i=n.destination.type==="Lambda"?"LambdaConfigurations":n.destination.type==="SQS"?"QueueConfigurations":"TopicConfigurations",s=n.destination.type==="Lambda"?"Function":n.destination.type==="SQS"?"Queue":"Topic",o={Event:n.events[0],[s]:n.destination.arn};if(n.filter)o.Filter={S3Key:{Rules:[...n.filter.prefix?[{Name:"prefix",Value:n.filter.prefix}]:[],...n.filter.suffix?[{Name:"suffix",Value:n.filter.suffix}]:[]]}};return{NotificationConfiguration:{[i]:[o]}}}clear(){this.policies.clear(),this.versioningConfigs.clear(),this.replicationRules.clear(),this.tieringConfigs.clear(),this.objectLocks.clear(),this.transferAcceleration.clear(),this.accessPoints.clear(),this.glacierConfigs.clear(),this.inventories.clear(),this.batchOps.clear(),this.eventNotifications.clear()}}var _S=new ru;class Xf{checks=new Map;synthetics=new Map;uptimeTrackers=new Map;counter=0;createHealthCheck(n,i=30,s=10){let o=`health-${Date.now()}-${this.counter++}`,c={id:o,url:n,interval:i,timeout:s,status:"healthy"};return this.checks.set(o,c),c}createSyntheticMonitor(n,i,s,o){let c=`synthetic-${Date.now()}-${this.counter++}`,u={id:c,name:n,script:i,frequency:s,locations:o};return this.synthetics.set(c,u),u}trackUptime(n,i,s){let o=`uptime-${Date.now()}-${this.counter++}`,c=i/(i+s)*100,u={id:o,resource:n,uptime:i,downtime:s,availability:c};return this.uptimeTrackers.set(o,u),u}clear(){this.checks.clear(),this.synthetics.clear(),this.uptimeTrackers.clear()}}var WE=new Xf;class Yf{wafRules=new Map;shieldProtections=new Map;securityGroups=new Map;nacls=new Map;counter=0;createWAFRule(n,i,s,o){let c=`waf-${Date.now()}-${this.counter++}`,u={id:c,name:n,priority:i,action:s,conditions:o};return this.wafRules.set(c,u),u}enableShield(n,i="standard"){let s=`shield-${Date.now()}-${this.counter++}`,o={id:s,resourceArn:n,protectionType:i};return this.shieldProtections.set(s,o),o}createSecurityGroup(n,i,s){let o=`sg-${Date.now()}-${this.counter++}`,c={id:o,name:n,vpcId:i,rules:s};return this.securityGroups.set(o,c),c}createNACL(n,i){let s=`nacl-${Date.now()}-${this.counter++}`,o={id:s,vpcId:n,rules:i};return this.nacls.set(s,o),o}clear(){this.wafRules.clear(),this.shieldProtections.clear(),this.securityGroups.clear(),this.nacls.clear()}}var JE=new Yf;class Zf{strategies=new Map;allocations=new Map;groups=new Map;counter=0;createTaggingStrategy(n,i){let s=`tagging-${Date.now()}-${this.counter++}`,o={id:s,tags:n,resources:i};return this.strategies.set(s,o),o}createCostAllocation(n,i){let s=`cost-${Date.now()}-${this.counter++}`,o={id:s,tagKey:n,allocations:i};return this.allocations.set(s,o),o}createResourceGroup(n,i,s){let o=`group-${Date.now()}-${this.counter++}`,c={id:o,name:n,query:{resourceTypeFilters:i,tagFilters:s}};return this.groups.set(o,c),c}clear(){this.strategies.clear(),this.allocations.clear(),this.groups.clear()}}var XE=new Zf;export{WI,JI,ul,Dm,gl,pl,ln,H,l,ml,Pm,W,fl,p,gy,b,tt,Yi,un,w,le,hl,py,r,t,XI,YI,m,ZI,eb,tb,rb,nb,ur,Al,Zi,my,ib,sb,_e,rt,yl,km,Nm,ob,Bm,xm,Om,Ko,Sl,ue,gn,Nt,Wo,Bt,ve,fy,Il,Jo,_m,Lm,$m,Mm,bl,ab,J,E,hy,Ay,Fm,a,S,nt,f,Um,it,X,xt,cb,Qm,Y,Cl,Le,gr,Xo,ge,El,pe,yy,Yo,Z,ee,L,es,D,pr,Ot,te,e,pn,db,Hm,vl,lb,ub,gb,pb,Tl,mb,fb,hb,Ab,yb,Sb,Ib,bb,Cb,Eb,vb,Tb,Sy,Iy,by,Cy,Ey,vy,Ty,mr,Gm,Vm,fr,ts,wb,qm,Rb,Db,mn,Pb,kb,Nb,Bb,xb,Ob,jm,k,Te,rs,Zo,fn,ns,ea,wy,_b,is,ta,Ry,Dy,Py,ky,Ny,By,ss,Lb,ra,xy,zm,q,Oy,st,na,_t,_y,Km,Ly,$y,My,Wm,j,$b,Mb,Fb,Ub,Fy,Qb,re,Hb,Gb,Vb,wl,Rl,Uy,Jm,Xm,qb,jb,zb,Kb,Wb,Qy,Dl,Jb,Xb,Yb,Zb,eC,Hy,Gy,tC,rC,nC,iC,sC,oC,aC,Vy,cC,Ym,Pl,dC,lC,uC,gC,Zm,ef,tf,pC,kl,qy,jy,zy,Ky,Nl,Wy,mC,fC,hC,AC,yC,SC,IC,Jy,Xy,Yy,Zy,rf,bC,CC,EC,vC,TC,wC,RC,DC,PC,eS,tS,rS,nS,kC,NC,nf,BC,sf,of,af,cf,xC,OC,_C,LC,$e,os,$C,MC,FC,UC,QC,HC,GC,VC,iS,qC,jC,df,lf,zC,KC,sS,WC,JC,XC,YC,ZC,eE,tE,rE,nE,iE,sE,oE,aE,cE,dE,lE,uE,gE,pE,mE,fE,Bl,oS,xl,aS,Ol,cS,_l,dS,Ll,lS,hr,uS,$l,gS,as,pS,Ml,mS,Fl,fS,uf,hE,gf,AE,Ul,hS,Ar,AS,pf,yE,Ql,yS,mf,SE,ff,IE,hf,bE,Hl,SS,Af,CE,yf,EE,Sf,vE,If,TE,Gl,IS,Vl,bS,bf,wE,Cf,RE,Ef,DE,vf,PE,Tf,kE,wf,NE,ql,CS,Rf,BE,Df,xE,Pf,OE,kf,_E,Nf,LE,Bf,$E,xf,Of,_f,Lf,$f,ME,Mf,FE,Ff,UE,Uf,QE,ot,Qf,ES,ia,jl,hn,vS,cs,yr,zl,Kl,TS,wS,Wl,Hf,Jl,Gf,HE,GE,sa,oa,aa,Xl,An,Yl,Zl,ds,ca,da,Vf,RS,DS,PS,VE,qf,jf,qE,kS,zf,NS,BS,xS,jE,Kf,yn,eu,Wf,zE,OS,la,ua,tu,Jf,KE,ru,_S,Xf,WE,Yf,JE,Zf,XE};